Conversation
Not to be merged. A litmus test for the reordering alone, and the reproducer from #10 under three rebuilds of the toolchain's libdispatch: as released, with a store barrier after the LISTLESS store, and with a load barrier in the same place as a placebo.
…f it A rebuilt library's RUNPATH names the build job's tree, so swift-backtrace, inheriting LD_LIBRARY_PATH, found no libBlocksRuntime.so and every crash of a rebuilt variant went uncounted as LISTLESS. The toolchain's directory now follows the variant's. The toolchain's library and the plain rebuild get more copies.
ResultsThe reading holds. Two runs, all on 36094940006, at fb51953. The rebuilt variants' crashes were counted as other failures: swift-backtrace inherited 36099069116, at 2d93300, with the toolchain's directory after the variant's in
Litmus, x and y in different cache lines: 1205 of 1.60 × 10⁹ and 4668 of 1.37 × 10⁹ with the acquire-only swap; none in one line, and none in either layout with release on the swap or Reported upstream as swiftlang/swift-corelibs-libdispatch#963. Closing; #11 has the summary. |
Not to be merged. This exists to run
.github/workflows/store-order.ymlon the runner the crash in #11 happens on.The reading under test
When a worker takes Swift's global concurrent queue off a root queue,
_dispatch_queue_class_invokewritesDISPATCH_OBJECT_LISTLESSinto the queue'sdo_nextwith a plain store. If the queue cannot run because its width is used up,_dispatch_queue_drain_try_lockthen clearsENQUEUEDwith an acquire-only compare-and-swap (casa). Nothing orders the store before the swap. Another thread can seeENQUEUEDclear, enqueue the queue again — writing NULL intodo_nextand linking it — and then have the late LISTLESS land on top. The next worker takes LISTLESS for the next item, and the one after it dies at_dispatch_worker_thread + 556:ldr x0, [x25, #0x10]!,next = head->do_next, withheadLISTLESS.The wakeup that enqueues a queue does not check its width, so with hundreds of tasks on a queue four wide, the failing path is routine. x86_64 cannot reorder the store past a locked instruction, which fits 0 of 2546 there.
How
StoreOrder/litmus.cis the pattern alone, with the same outline-atomic helpers libdispatch uses, and two controls that must stay at zero (acqrel, anddmb ishstbefore the swap).swift-6.4.0-RELEASE, rebuilt with the toolchain's clang three ways from one patch — as released, withdmb ishstright after the LISTLESS store, and withdmb ishldin the same place as a placebo that costs about as much and orders nothing that matters here — each put in front of the toolchain's own throughLD_LIBRARY_PATH, beside the toolchain's library itself. The loader is asked which library it took before any run is counted.What would say otherwise
ishstcrashes: the reading is wrong, or not the only way there.ishlddrops to zero as well: the barrier's timing, not the order it enforces.rebuiltdiffers fromstock: the rebuild does not stand in for the toolchain's library.Already seen locally
Apple M4 Pro, Linux VM (
swift:6.4-noble), 60 s each:So the hardware makes the reordering there too, when the two words are in different lines. The reproducer has never crashed on that machine; why is not known.