Swift 5.5.3 repairs task group synchronization
Swift 5.5.3 updates the Linux and Windows toolchains. A task group fix shows why an atomic operation can be correct in isolation and still be wrong for its caller.
An atomic compare-and-exchange can report failure even when no competing thread changed the value. The weak form permits that outcome. Code that treats every failure as evidence of interference can therefore take an invalid path, despite using atomic operations throughout. One of the fixes listed for Swift 5.5.3 addresses precisely that mistake in the task group runtime.
Mishal Shah's release announcement, dated February 10 UTC, makes Swift 5.5.3 available for Linux and Windows. This is a maintenance release within the existing language series. Its most useful technical context comes from the development thread, where the release manager listed the intended changes and the repositories that had no changes between the two release tags.
I find Swift's language design coherent, which makes runtime details like this worth understanding. The source-level concurrency model depends on machinery that application code does not usually see. A small correction there can matter more to correctness than a visible syntax addition.
Failure without interference
The task group patch changes several calls from compare_exchange_weak to compare_exchange_strong. Its explanation identifies a null-pointer dereference in TaskGroupImpl::poll under a narrow condition. The weak operation could return false spuriously, and the code around it did not safely accommodate that possibility.
Compare-and-exchange receives an expected value and a replacement. Success means the expected value matched and the operation installed the replacement. The distinction between weak and strong matters on the failure path. A weak operation can fail spuriously. The patch explains that the strong version retries that kind of failure on the affected target.
The commit specifically connects the observed failure to the arm64 runtime slice. On that target, Clang uses the ldxr and stxr instructions for the synchronization described in the patch. The weak form does not retry a spurious failure. Consequently, a failure result did not necessarily mean what the task group's surrounding control flow assumed it meant.
This is a useful boundary between an operation's contract and an algorithm's contract. An atomic operation can obey its documented rules while the larger algorithm remains incorrect. Choosing the weak form requires the caller to tolerate every failure the operation permits. Merely expecting the value to change infrequently does not establish that tolerance.
The change preserves the ordering choices
The patch touches the task group's status transitions and wait queue operations. For example, it replaces the comparison in the helper that completes a pending, ready and waiting status. Other replacements occur when offering a completed task and when polling or adding a waiting task to the queue.
The diff retains the existing memory-order arguments. Some affected calls use relaxed ordering, while queue operations include release and acquire ordering. The correction therefore changes how the comparison handles spurious failure without replacing the algorithm's ordering decisions. Strong compare-and-exchange and stronger memory ordering are different choices, as this diff makes concrete.
The patch is small enough to make that distinction inspectable. It changes five operation names in one runtime source file. Its description supplies the failure mechanism, while the surrounding diff shows which transitions depend on the result. An application developer does not need to reproduce the runtime's internal algorithm to understand why the previous failure branch was unsafe.
I value this kind of maintenance explanation because it connects the symptom to a specific contract violation. A statement that concurrency is more reliable would give little basis for understanding the update. Here the weak operation's permitted result explains the null dereference and the purpose of the replacement.
A toolchain release contains several projects
The development thread also lists Windows-related LLVM changes, including balancing the frame prologue and epilogue on Win64. Its compiler list includes work on async function pointer symbols and linkage. Swift Package Manager has a separate entry adding an automatic library product for SwiftPMDataModel.
These entries describe different parts of the distributed toolchain. They should not be read as a list of new language capabilities. A platform code-generation correction and a package manager product declaration solve different problems, even though both arrive under the same Swift release number.
The release manager's January inventory explicitly lists no changes between the release tags for several repositories, including corelibs Foundation, libdispatch and XCTest. That matters when interpreting this update. The presence of a new toolchain version does not imply that every bundled library acquired new APIs. In particular, a maintenance announcement alone is insufficient evidence for claiming a missing platform API has appeared.
The development window opened in January, and Shah later reported it closed. The February announcement confirms availability after that selection process. For this release, the runtime patch provides the clearest account of a concrete correctness problem, while the repository inventory keeps the scope of the other changes explicit. The distinction between the compare-and-exchange result and memory ordering remains useful when reading any of the affected task group transitions.