@@ -206,8 +206,11 @@ template <class Fn>
206206static bool withStatusRecordLock (AsyncTask *task,
207207 LockContext lockContext,
208208 Fn &&fn) {
209+ auto loadOrdering = getLoadOrdering (lockContext);
209210 ActiveTaskStatus status =
210- task->_private ()._status ().load (getLoadOrdering (lockContext));
211+ task->_private ()._status ().load (loadOrdering);
212+ if (loadOrdering == std::memory_order_acquire)
213+ _swift_tsan_acquire (task);
211214 return withStatusRecordLock (task, lockContext, status, [&] {
212215 fn (status);
213216 });
@@ -242,6 +245,7 @@ bool swift::addStatusRecord(
242245 // We have to use a release on success to make the initialization of
243246 // the new record visible to an asynchronous thread trying to modify the
244247 // status records
248+ _swift_tsan_release (task);
245249 if (task->_private ()._status ().compare_exchange_weak (oldStatus, newStatus,
246250 /* success*/ std::memory_order_release,
247251 /* failure*/ std::memory_order_relaxed)) {
@@ -460,9 +464,19 @@ static void swift_task_cancelImpl(AsyncTask *task) {
460464 // Set cancelled bit even if oldStatus.isStatusRecordLocked()
461465 newStatus = oldStatus.withCancelled ();
462466
467+ // Perform an acquire operation on success, which pairs with the release
468+ // operation in addStatusRecord. This ensures that the contents of the
469+ // status records are visible to this thread, as well as the contents of any
470+ // cancellation handlers and the data they access. We place this acquire
471+ // barrier here, because the subsequent call to `withStatusRecordLock` might
472+ // not have its own acquire barrier. We're calling the four-argument version
473+ // which relies on the caller to have performed the first load, and if the
474+ // compare_exchange operation in withStatusRecordLock succeeds the first
475+ // time, then it won't perform an acquire.
463476 if (task->_private ()._status ().compare_exchange_weak (oldStatus, newStatus,
464- /* success*/ std::memory_order_relaxed ,
477+ /* success*/ std::memory_order_acquire ,
465478 /* failure*/ std::memory_order_relaxed)) {
479+ _swift_tsan_acquire (task);
466480 break ;
467481 }
468482 }
0 commit comments