Skip to content

Commit 2910718

Browse files
author
Julian Lettner
committed
Teach TSan about TaskGroups
`TaskGroup::offer(completedTask)`: * Called from `AsyncTask::completeFuture()` which already takes care of `release(completedTask)`. No additional edge is required if no task is waiting and completed task is stored so it can be retrieved by `group.poll()`. * If group has waiting task, it will be dequeued and scheduled, add `acquire(waitingTask)`. `TaskGroupImpl::poll(waitingTask)`: * If no pending tasks, do nothing. * If returning finished task, `acquire(finishedTask)`. * If enqueuing waiting task, `release(waitingTask)`. Note: `release()` should go before, and `acquire()` after the annotated synchronization operation. Radar-Id: rdar://75910632
1 parent f85633a commit 2910718

File tree

1 file changed

+5
-0
lines changed

1 file changed

+5
-0
lines changed

stdlib/public/Concurrency/TaskGroup.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,8 @@ void TaskGroupImpl::offer(AsyncTask *completedTask, AsyncContext *context) {
621621

622622
fillGroupNextResult(waitingContext, result);
623623

624+
_swift_tsan_acquire(static_cast<Job *>(waitingTask));
625+
624626
// TODO: allow the caller to suggest an executor
625627
swift_task_enqueueGlobal(waitingTask);
626628
return;
@@ -750,6 +752,7 @@ PollResult TaskGroupImpl::poll(AsyncTask *waitingTask) {
750752
result.status = PollStatus::Success;
751753
result.storage = futureFragment->getStoragePtr();
752754
assert(result.retainedTask && "polled a task, it must be not null");
755+
_swift_tsan_acquire(static_cast<Job *>(result.retainedTask));
753756
mutex.unlock(); // TODO: remove fragment lock, and use status for synchronization
754757
return result;
755758

@@ -759,6 +762,7 @@ PollResult TaskGroupImpl::poll(AsyncTask *waitingTask) {
759762
result.storage =
760763
reinterpret_cast<OpaqueValue *>(futureFragment->getError());
761764
assert(result.retainedTask && "polled a task, it must be not null");
765+
_swift_tsan_acquire(static_cast<Job *>(result.retainedTask));
762766
mutex.unlock(); // TODO: remove fragment lock, and use status for synchronization
763767
return result;
764768

@@ -775,6 +779,7 @@ PollResult TaskGroupImpl::poll(AsyncTask *waitingTask) {
775779

776780
// ==== 3) Add to wait queue -------------------------------------------------
777781
assert(assumed.readyTasks() == 0);
782+
_swift_tsan_release(static_cast<Job *>(waitingTask));
778783
while (true) {
779784
// Put the waiting task at the beginning of the wait queue.
780785
if (waitQueue.compare_exchange_weak(

0 commit comments

Comments
 (0)