Skip to content

Commit 6247a7c

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 (cherry picked from commit 0aec816) Conflicts: stdlib/public/Concurrency/TaskPrivate.h
1 parent 65b3c07 commit 6247a7c

File tree

5 files changed

+1412
-12
lines changed

5 files changed

+1412
-12
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 & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +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"
2220
#include "swift/ABI/Metadata.h"
21+
#include "swift/ABI/Task.h"
2322
#include "swift/Runtime/Atomic.h"
24-
#include "swift/Runtime/HeapObject.h"
23+
#include "swift/Runtime/Concurrency.h"
2524
#include "swift/Runtime/Error.h"
25+
#include "swift/Runtime/Exclusivity.h"
26+
#include "swift/Runtime/HeapObject.h"
27+
2628
#include "../runtime/StackAllocator.h"
2729

2830
namespace swift {
@@ -255,14 +257,19 @@ struct AsyncTask::PrivateStorage {
255257
/// Currently one word.
256258
TaskLocal::Storage Local;
257259

260+
/// State inside the AsyncTask whose state is only managed by the exclusivity
261+
/// runtime in stdlibCore. We zero initialize to provide a safe initial value,
262+
/// but actually initialize its bit state to a const global provided by
263+
/// libswiftCore so that libswiftCore can control the layout of our initial
264+
/// state.
265+
uintptr_t ExclusivityAccessSet[2] = {0, 0};
266+
258267
PrivateStorage(JobFlags flags)
259-
: Status(ActiveTaskStatus(flags)),
260-
Local(TaskLocal::Storage()) {}
268+
: Status(ActiveTaskStatus(flags)), Local(TaskLocal::Storage()) {}
261269

262270
PrivateStorage(JobFlags flags, void *slab, size_t slabCapacity)
263-
: Status(ActiveTaskStatus(flags)),
264-
Allocator(slab, slabCapacity),
265-
Local(TaskLocal::Storage()) {}
271+
: Status(ActiveTaskStatus(flags)), Allocator(slab, slabCapacity),
272+
Local(TaskLocal::Storage()) {}
266273

267274
void complete(AsyncTask *task) {
268275
// Destroy and deallocate any remaining task local items.
@@ -320,7 +327,10 @@ inline void AsyncTask::flagAsRunning() {
320327
while (true) {
321328
assert(!oldStatus.isRunning());
322329
if (oldStatus.isLocked()) {
323-
return flagAsRunning_slow();
330+
flagAsRunning_slow();
331+
swift_task_enterThreadLocalContext(
332+
(char *)&_private().ExclusivityAccessSet[0]);
333+
return;
324334
}
325335

326336
auto newStatus = oldStatus.withRunning(true);
@@ -331,8 +341,11 @@ inline void AsyncTask::flagAsRunning() {
331341

332342
if (_private().Status.compare_exchange_weak(oldStatus, newStatus,
333343
std::memory_order_relaxed,
334-
std::memory_order_relaxed))
344+
std::memory_order_relaxed)) {
345+
swift_task_enterThreadLocalContext(
346+
(char *)&_private().ExclusivityAccessSet[0]);
335347
return;
348+
}
336349
}
337350
}
338351

@@ -341,7 +354,10 @@ inline void AsyncTask::flagAsSuspended() {
341354
while (true) {
342355
assert(oldStatus.isRunning());
343356
if (oldStatus.isLocked()) {
344-
return flagAsSuspended_slow();
357+
flagAsSuspended_slow();
358+
swift_task_exitThreadLocalContext(
359+
(char *)&_private().ExclusivityAccessSet[0]);
360+
return;
345361
}
346362

347363
auto newStatus = oldStatus.withRunning(false);
@@ -352,8 +368,11 @@ inline void AsyncTask::flagAsSuspended() {
352368

353369
if (_private().Status.compare_exchange_weak(oldStatus, newStatus,
354370
std::memory_order_relaxed,
355-
std::memory_order_relaxed))
371+
std::memory_order_relaxed)) {
372+
swift_task_exitThreadLocalContext(
373+
(char *)&_private().ExclusivityAccessSet[0]);
356374
return;
375+
}
357376
}
358377
}
359378

0 commit comments

Comments
 (0)