Repository navigation
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 🧰 Additional context used📚 Code guidelines (2)No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (1)
Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review. WalkthroughOn non-X86_64 FreeBSD, the WebAssembly instruction-cache barrier attempts private expedited sync-core membarrier. If registration or execution fails, it uses the existing locked per-thread barrier iteration. X86_64 retains its immediate return. ChangesInstruction-cache barrier
Priority: ⬆️ High 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Warning Git: CodeRabbit could not clone the repository, so clone-backed analysis was skipped and this review may be incomplete. Verify repository clone access, such as SSH credentials, before requesting another full review. If clone access is intentionally unavailable, use Comment |
barrierInstructionCacheOnAllThreads() published modified Wasm code by suspend()ing and resume()ing each tracked thread through Thread::barrierInstructionCache(). That takes the global ThreadSuspendLocker and parks the target, which deadlocks against the GC's stop-the-world path on FreeBSD (a two-GC plus JIT-worklist inversion; see oven-sh/bun#44572). FreeBSD implements membarrier(2) as a clean-room port of the Linux interface. MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE asks the kernel to run a context-synchronizing event (an ISB on ARM64) on every running thread in the process, so the modified code is published without a signal, without ThreadSuspendLocker and without any per-thread handshake. This is the mechanism the FIXME here already asked for. Registration is process-wide and done once; kernels without the syscall (or non-FreeBSD) keep the existing path as a fallback. Refs: oven-sh/bun#44572.
19e72b4 to
1986b99
Compare
[Wasm] Use membarrier(2) to publish modified code on FreeBSD
Problem
A
bun build --compileexecutable deadlocks on FreeBSD/aarch64 (oven-sh/bun#44572).The freeze is in the Wasm instruction-cache publication path:
Wasm::barrierInstructionCacheOnAllThreads()made every tracked thread re-fetchmodified instructions through
Thread::barrierInstructionCache(), which published bysuspend()+resume()-ing the target. That takes the globalThreadSuspendLockerand parks the target.
MachineThreads::tryCopyOtherThreadStacks) and aWorker VM's
JITWorklist::suspendAllThreads()both want the same global lock, whilethe JIT-worklist / Wasm-compiler threads sit parked on their worklists.
The result is a two-GC plus JIT-worklist stop-the-world inversion, with the Wasm
publisher holding the suspend lock. Symbolized
lldbcaptures are in oven-sh/bun#44572.Every signal-based variant we tried was either still deadlock-prone (holding
ThreadSuspendLocker) or lost its acknowledgment (sharingsigThreadSuspendResumewith suspend/resume, or dropping the Wasm thread-list lock and racing
Thread::didExit()).Fix
Implement the
FIXMEthat was already here: on FreeBSD, ask the kernel to run acontext-synchronizing event (an ISB on ARM64) on every running thread via
MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE. FreeBSD implementsmembarrier(2)as aclean-room port of the Linux interface, and this is the mechanism SpiderMonkey uses for
the same purpose.
This publishes the modified code with:
ThreadSuspendLocker, so it cannot participate in the GC/JITWorklist inversion;Registration is process-wide and done once (
std::call_once). Kernels without thesyscall (or non-FreeBSD) keep the existing per-thread path as a fallback.
Testing
2e2aa2290f) on FreeBSD 15.1-RELEASE aarch64, with thecompiled OpenCode TUI and
libopentuiviabun:ffi. With the equivalent change, therepro goes from 5/5 freezes to repeated passes: three consecutive turns all
complete (deterministic, zero-latency mock model), three real-model conversations pass,
and the process survives an 8×
SIGUSR1heap-snapshot-GC storm.dtraceconfirms the syscall (membarrier) is what now publishes the code duringWasm compilation.
main, compile-checked with theFreeBSD/aarch64 cross build. (Runtime validation on
maindirectly is not possibleyet because bun 1.4.2's
src/jsc/bindingsdoes not compile againstmain's headers.)Not in this PR
There is a separate, architecture-independent FreeBSD deadlock at process exit
(after a successful conversation), in the
WTFthread-suspension handshake(
Thread::suspend↔tryCopyOtherThreadStacks↔VMTraps::SignalSender). It reproduceson amd64 as well as aarch64 and is unrelated to this change; it is being tracked
separately and will be filed on its own.
Refs: oven-sh/bun#44572.