@@ -206,8 +206,11 @@ template <class Fn>
206
206
static bool withStatusRecordLock (AsyncTask *task,
207
207
LockContext lockContext,
208
208
Fn &&fn) {
209
+ auto loadOrdering = getLoadOrdering (lockContext);
209
210
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);
211
214
return withStatusRecordLock (task, lockContext, status, [&] {
212
215
fn (status);
213
216
});
@@ -242,6 +245,7 @@ bool swift::addStatusRecord(
242
245
// We have to use a release on success to make the initialization of
243
246
// the new record visible to an asynchronous thread trying to modify the
244
247
// status records
248
+ _swift_tsan_release (task);
245
249
if (task->_private ()._status ().compare_exchange_weak (oldStatus, newStatus,
246
250
/* success*/ std::memory_order_release,
247
251
/* failure*/ std::memory_order_relaxed)) {
@@ -460,9 +464,19 @@ static void swift_task_cancelImpl(AsyncTask *task) {
460
464
// Set cancelled bit even if oldStatus.isStatusRecordLocked()
461
465
newStatus = oldStatus.withCancelled ();
462
466
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.
463
476
if (task->_private ()._status ().compare_exchange_weak (oldStatus, newStatus,
464
- /* success*/ std::memory_order_relaxed ,
477
+ /* success*/ std::memory_order_acquire ,
465
478
/* failure*/ std::memory_order_relaxed)) {
479
+ _swift_tsan_acquire (task);
466
480
break ;
467
481
}
468
482
}
0 commit comments