Skip to content

Commit 0aec816

Browse files
committed
[exclusivity] Add support for Task local exclusivity access sets.
The implemented semantics are that: 1. Tasks have separate exclusivity access sets. 2. Any synchronous context that creates tasks will have its exclusive access set merged into the Tasks while the Task is running. rdar://80492364
1 parent fc4d6c8 commit 0aec816

File tree

5 files changed

+1410
-13
lines changed

5 files changed

+1410
-13
lines changed

include/swift/Runtime/Exclusivity.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,30 @@ void swift_dumpTrackedAccesses();
9191

9292
#endif
9393

94+
/// Called when a task inits, resumes and returns control to caller synchronous
95+
/// code to update any exclusivity specific state associated with the task.
96+
///
97+
/// State is assumed to point to a buffer of memory with
98+
/// swift_task_threadLocalContextSize bytes that was initialized with
99+
/// swift_task_initThreadLocalContext.
100+
///
101+
/// We describe the algorithm in detail on SwiftTaskThreadLocalContext in
102+
/// Exclusivity.cpp.
103+
SWIFT_RUNTIME_EXPORT
104+
void swift_task_enterThreadLocalContext(char *state);
105+
106+
/// Called when a task suspends and returns control to caller synchronous code
107+
/// to update any exclusivity specific state associated with the task.
108+
///
109+
/// State is assumed to point to a buffer of memory with
110+
/// swift_task_threadLocalContextSize bytes that was initialized with
111+
/// swift_task_initThreadLocalContext.
112+
///
113+
/// We describe the algorithm in detail on SwiftTaskThreadLocalContext in
114+
/// Exclusivity.cpp.
115+
SWIFT_RUNTIME_EXPORT
116+
void swift_task_exitThreadLocalContext(char *state);
117+
94118
} // end namespace swift
95119

96120
#endif

stdlib/public/Concurrency/TaskPrivate.h

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@
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,8 +394,11 @@ 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

0 commit comments

Comments
 (0)