1717#ifndef SWIFT_CONCURRENCY_TASKPRIVATE_H
1818#define SWIFT_CONCURRENCY_TASKPRIVATE_H
1919
20- #include " swift/Runtime/Concurrency.h"
21- #include " swift/ABI/Task.h"
20+ #include " Error.h"
2221#include " swift/ABI/Metadata.h"
22+ #include " swift/ABI/Task.h"
2323#include " swift/Runtime/Atomic.h"
24- #include " swift/Runtime/HeapObject .h"
24+ #include " swift/Runtime/Concurrency .h"
2525#include " swift/Runtime/Error.h"
26- #include " Error.h"
26+ #include " swift/Runtime/Exclusivity.h"
27+ #include " swift/Runtime/HeapObject.h"
2728
2829#define SWIFT_FATAL_ERROR swift_Concurrency_fatalError
2930#include " ../runtime/StackAllocator.h"
@@ -282,14 +283,19 @@ struct AsyncTask::PrivateStorage {
282283 // / Currently one word.
283284 TaskLocal::Storage Local;
284285
286+ // / State inside the AsyncTask whose state is only managed by the exclusivity
287+ // / runtime in stdlibCore. We zero initialize to provide a safe initial value,
288+ // / but actually initialize its bit state to a const global provided by
289+ // / libswiftCore so that libswiftCore can control the layout of our initial
290+ // / state.
291+ uintptr_t ExclusivityAccessSet[2 ] = {0 , 0 };
292+
285293 PrivateStorage (JobFlags flags)
286- : Status(ActiveTaskStatus(flags)),
287- Local (TaskLocal::Storage()) {}
294+ : Status(ActiveTaskStatus(flags)), Local(TaskLocal::Storage()) {}
288295
289296 PrivateStorage (JobFlags flags, void *slab, size_t slabCapacity)
290- : Status(ActiveTaskStatus(flags)),
291- Allocator(slab, slabCapacity),
292- Local(TaskLocal::Storage()) {}
297+ : Status(ActiveTaskStatus(flags)), Allocator(slab, slabCapacity),
298+ Local (TaskLocal::Storage()) {}
293299
294300 void complete (AsyncTask *task) {
295301 // Destroy and deallocate any remaining task local items.
@@ -347,7 +353,10 @@ inline void AsyncTask::flagAsRunning() {
347353 while (true ) {
348354 assert (!oldStatus.isRunning ());
349355 if (oldStatus.isLocked ()) {
350- return flagAsRunning_slow ();
356+ flagAsRunning_slow ();
357+ swift_task_enterThreadLocalContext (
358+ (char *)&_private ().ExclusivityAccessSet [0 ]);
359+ return ;
351360 }
352361
353362 auto newStatus = oldStatus.withRunning (true );
@@ -358,8 +367,11 @@ inline void AsyncTask::flagAsRunning() {
358367
359368 if (_private ().Status .compare_exchange_weak (oldStatus, newStatus,
360369 std::memory_order_relaxed,
361- std::memory_order_relaxed))
370+ std::memory_order_relaxed)) {
371+ swift_task_enterThreadLocalContext (
372+ (char *)&_private ().ExclusivityAccessSet [0 ]);
362373 return ;
374+ }
363375 }
364376}
365377
@@ -368,7 +380,10 @@ inline void AsyncTask::flagAsSuspended() {
368380 while (true ) {
369381 assert (oldStatus.isRunning ());
370382 if (oldStatus.isLocked ()) {
371- return flagAsSuspended_slow ();
383+ flagAsSuspended_slow ();
384+ swift_task_exitThreadLocalContext (
385+ (char *)&_private ().ExclusivityAccessSet [0 ]);
386+ return ;
372387 }
373388
374389 auto newStatus = oldStatus.withRunning (false );
@@ -379,11 +394,24 @@ inline void AsyncTask::flagAsSuspended() {
379394
380395 if (_private ().Status .compare_exchange_weak (oldStatus, newStatus,
381396 std::memory_order_relaxed,
382- std::memory_order_relaxed))
397+ std::memory_order_relaxed)) {
398+ swift_task_exitThreadLocalContext (
399+ (char *)&_private ().ExclusivityAccessSet [0 ]);
383400 return ;
401+ }
384402 }
385403}
386404
405+ // READ ME: This is not a dead function! Do not remove it! This is a function
406+ // that can be used when debugging locally to instrument when a task actually is
407+ // dealloced.
408+ inline void AsyncTask::flagAsCompleted () {
409+ #if SWIFT_TASK_PRINTF_DEBUG
410+ fprintf (stderr, " [%lu] task completed %p\n " ,
411+ _swift_get_thread_id (), this );
412+ #endif
413+ }
414+
387415inline void AsyncTask::localValuePush (const HeapObject *key,
388416 /* +1 */ OpaqueValue *value,
389417 const Metadata *valueType) {
0 commit comments