Skip to content

Commit 6c879d6

Browse files
committed
Change the async ABI to not pass the active task and executor.
Most of the async runtime functions have been changed to not expect the task and executor to be passed in. When knowing the task and executor is necessary, there are runtime functions available to recover them. The biggest change I had to make to a runtime function signature was to swift_task_switch, which has been altered to expect to be passed the context and resumption function instead of requiring the caller to park the task. This has the pleasant consequence of allowing the implementation to very quickly turn around when it recognizes that the current executor is satisfactory. It does mean that on arm64e we have to sign the continuation function pointer as an argument and then potentially resign it when assigning into the task's resume slot. rdar://70546948
1 parent 5499235 commit 6c879d6

File tree

88 files changed

+624
-684
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+624
-684
lines changed

include/swift/ABI/Executor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@ class ExecutorRef {
114114

115115
using JobInvokeFunction =
116116
SWIFT_CC(swiftasync)
117-
void (Job *, ExecutorRef);
117+
void (Job *);
118118

119119
using TaskContinuationFunction =
120120
SWIFT_CC(swiftasync)
121-
void (AsyncTask *, ExecutorRef, SWIFT_ASYNC_CONTEXT AsyncContext *);
121+
void (SWIFT_ASYNC_CONTEXT AsyncContext *);
122122

123123
template <class AsyncSignature>
124124
class AsyncFunctionPointer;

include/swift/ABI/Task.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ class alignas(2 * alignof(void*)) Job : public HeapObject {
8787
/// Given that we've fully established the job context in the current
8888
/// thread, actually start running this job. To establish the context
8989
/// correctly, call swift_job_run or runJobInExecutorContext.
90-
void runInFullyEstablishedContext(ExecutorRef currentExecutor);
90+
void runInFullyEstablishedContext();
9191

9292
/// Given that we've fully established the job context in the
9393
/// current thread, and that the job is a simple (non-task) job,
9494
/// actually start running this job.
95-
void runSimpleInFullyEstablishedContext(ExecutorRef currentExecutor) {
96-
RunJob(this, currentExecutor);
95+
void runSimpleInFullyEstablishedContext() {
96+
RunJob(this);
9797
}
9898
};
9999

@@ -193,8 +193,8 @@ class AsyncTask : public Job {
193193
/// in the current thread, start running this task. To establish
194194
/// the job context correctly, call swift_job_run or
195195
/// runInExecutorContext.
196-
void runInFullyEstablishedContext(ExecutorRef currentExecutor) {
197-
ResumeTask(this, currentExecutor, ResumeContext);
196+
void runInFullyEstablishedContext() {
197+
ResumeTask(ResumeContext);
198198
}
199199

200200
/// Check whether this task has been cancelled.
@@ -433,7 +433,7 @@ class AsyncTask : public Job {
433433
///
434434
/// Upon completion, any waiting tasks will be scheduled on the given
435435
/// executor.
436-
void completeFuture(AsyncContext *context, ExecutorRef executor);
436+
void completeFuture(AsyncContext *context);
437437

438438
// ==== ----------------------------------------------------------------------
439439

@@ -456,11 +456,11 @@ static_assert(sizeof(AsyncTask) == 14 * sizeof(void*),
456456
static_assert(alignof(AsyncTask) == 2 * alignof(void*),
457457
"AsyncTask alignment is wrong");
458458

459-
inline void Job::runInFullyEstablishedContext(ExecutorRef currentExecutor) {
459+
inline void Job::runInFullyEstablishedContext() {
460460
if (auto task = dyn_cast<AsyncTask>(this))
461-
task->runInFullyEstablishedContext(currentExecutor);
461+
task->runInFullyEstablishedContext();
462462
else
463-
runSimpleInFullyEstablishedContext(currentExecutor);
463+
runSimpleInFullyEstablishedContext();
464464
}
465465

466466
/// An asynchronous context within a task. Generally contexts are
@@ -484,6 +484,7 @@ class alignas(MaximumAlignment) AsyncContext {
484484
ResumeParent;
485485

486486
/// The executor that the parent needs to be resumed on.
487+
/// FIXME: remove this
487488
ExecutorRef ResumeParentExecutor;
488489

489490
/// Flags describing this context.
@@ -496,10 +497,9 @@ class alignas(MaximumAlignment) AsyncContext {
496497

497498
AsyncContext(AsyncContextFlags flags,
498499
TaskContinuationFunction *resumeParent,
499-
ExecutorRef resumeParentExecutor,
500500
AsyncContext *parent)
501501
: Parent(parent), ResumeParent(resumeParent),
502-
ResumeParentExecutor(resumeParentExecutor),
502+
ResumeParentExecutor(ExecutorRef::generic()),
503503
Flags(flags) {}
504504

505505
AsyncContext(const AsyncContext &) = delete;
@@ -509,10 +509,10 @@ class alignas(MaximumAlignment) AsyncContext {
509509
///
510510
/// Generally this should be tail-called.
511511
SWIFT_CC(swiftasync)
512-
void resumeParent(AsyncTask *task, ExecutorRef executor) {
512+
void resumeParent() {
513513
// TODO: destroy context before returning?
514514
// FIXME: force tail call
515-
return ResumeParent(task, executor, Parent);
515+
return ResumeParent(Parent);
516516
}
517517
};
518518

@@ -529,11 +529,10 @@ class YieldingAsyncContext : public AsyncContext {
529529

530530
YieldingAsyncContext(AsyncContextFlags flags,
531531
TaskContinuationFunction *resumeParent,
532-
ExecutorRef resumeParentExecutor,
533532
TaskContinuationFunction *yieldToParent,
534533
ExecutorRef yieldToParentExecutor,
535534
AsyncContext *parent)
536-
: AsyncContext(flags, resumeParent, resumeParentExecutor, parent),
535+
: AsyncContext(flags, resumeParent, parent),
537536
YieldToParent(yieldToParent),
538537
YieldToParentExecutor(yieldToParentExecutor) {}
539538

include/swift/ABI/TaskGroup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class alignas(Alignment_TaskGroup) TaskGroup {
3838
void *PrivateData[NumWords_TaskGroup];
3939

4040
/// Upon a future task's completion, offer it to the task group it belongs to.
41-
void offer(AsyncTask *completed, AsyncContext *context, ExecutorRef executor);
41+
void offer(AsyncTask *completed, AsyncContext *context);
4242
};
4343

4444
} // end namespace swift

include/swift/Runtime/Concurrency.h

Lines changed: 36 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#include "swift/ABI/TaskGroup.h"
2121
#include "swift/ABI/TaskStatus.h"
2222

23+
#pragma clang diagnostic push
24+
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
25+
2326
namespace swift {
2427
class DefaultActor;
2528

@@ -34,7 +37,6 @@ struct AsyncTaskAndContext {
3437
/// function.
3538
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
3639
AsyncTaskAndContext swift_task_create_f(JobFlags flags,
37-
AsyncTask *parent,
3840
ThinNullaryAsyncSignature::FunctionType *function,
3941
size_t initialContextSize);
4042

@@ -47,24 +49,23 @@ using FutureAsyncSignature =
4749
/// closure.
4850
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
4951
AsyncTaskAndContext swift_task_create_future(
50-
JobFlags flags, AsyncTask *parent, const Metadata *futureResultType,
52+
JobFlags flags, const Metadata *futureResultType,
5153
void *closureEntryPoint,
5254
HeapObject * /* +1 */ closureContext);
5355

5456
/// Create a task object with a future which will run the given
5557
/// function.
5658
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
5759
AsyncTaskAndContext swift_task_create_future_f(
58-
JobFlags flags, AsyncTask *parent, const Metadata *futureResultType,
60+
JobFlags flags, const Metadata *futureResultType,
5961
FutureAsyncSignature::FunctionType *function,
6062
size_t initialContextSize);
6163

6264
/// Create a task object with a future which will run the given
6365
/// closure, and offer its result to the task group
6466
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
6567
AsyncTaskAndContext swift_task_create_group_future(
66-
JobFlags flags,
67-
AsyncTask *parent, TaskGroup *group,
68+
JobFlags flags, TaskGroup *group,
6869
const Metadata *futureResultType,
6970
void *closureEntryPoint,
7071
HeapObject * /* +1 */ closureContext);
@@ -73,8 +74,7 @@ AsyncTaskAndContext swift_task_create_group_future(
7374
/// function, and offer its result to the task group
7475
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
7576
AsyncTaskAndContext swift_task_create_group_future_f(
76-
JobFlags flags,
77-
AsyncTask *parent, TaskGroup *group,
77+
JobFlags flags, TaskGroup *group,
7878
const Metadata *futureResultType,
7979
FutureAsyncSignature::FunctionType *function,
8080
size_t initialContextSize);
@@ -85,15 +85,15 @@ AsyncTaskAndContext swift_task_create_group_future_f(
8585
///
8686
/// All allocations will be rounded to a multiple of MAX_ALIGNMENT.
8787
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
88-
void *swift_task_alloc(AsyncTask *task, size_t size);
88+
void *swift_task_alloc(size_t size);
8989

9090
/// Deallocate memory in a task.
9191
///
9292
/// The pointer provided must be the last pointer allocated on
9393
/// this task that has not yet been deallocated; that is, memory
9494
/// must be allocated and deallocated in a strict stack discipline.
9595
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
96-
void swift_task_dealloc(AsyncTask *task, void *ptr);
96+
void swift_task_dealloc(void *ptr);
9797

9898
/// Cancel a task and all of its child tasks.
9999
///
@@ -103,9 +103,9 @@ void swift_task_dealloc(AsyncTask *task, void *ptr);
103103
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
104104
void swift_task_cancel(AsyncTask *task);
105105

106-
/// Cancel all child tasks of `parent` that belong to the `group`.
106+
/// Cancel all the child tasks that belong to the `group`.
107107
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
108-
void swift_task_cancel_group_child_tasks(AsyncTask *task, TaskGroup *group);
108+
void swift_task_cancel_group_child_tasks(TaskGroup *group);
109109

110110
/// Escalate the priority of a task and all of its child tasks.
111111
///
@@ -170,26 +170,22 @@ swift_taskGroup_wait_next_throwing;
170170
/// Its Swift signature is
171171
///
172172
/// \code
173-
/// func swift_taskGroup_create(
174-
/// _ task: Builtin.NativeObject
175-
/// ) -> Builtin.RawPointer
173+
/// func swift_taskGroup_create() -> Builtin.RawPointer
176174
/// \endcode
177175
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
178-
TaskGroup* swift_taskGroup_create(AsyncTask *task); // TODO: probably remove this call, and just use the initialize always
176+
TaskGroup* swift_taskGroup_create(); // TODO: probably remove this call, and just use the initialize always
179177

180178
/// Initialize a `TaskGroup` in the passed `group` memory location.
181179
/// The caller is responsible for retaining and managing the group's lifecycle.
182180
///
183181
/// Its Swift signature is
184182
///
185183
/// \code
186-
/// func swift_taskGroup_initialize(
187-
/// _ task: Builtin.NativeObject,
188-
/// group: Builtin.RawPointer,
184+
/// func swift_taskGroup_initialize(group: Builtin.RawPointer
189185
/// )
190186
/// \endcode
191187
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
192-
void swift_taskGroup_initialize(AsyncTask *task, TaskGroup *group);
188+
void swift_taskGroup_initialize(TaskGroup *group);
193189

194190
/// Attach a child task to the parent task's task group record.
195191
///
@@ -215,13 +211,10 @@ void swift_taskGroup_attachChild(TaskGroup *group, AsyncTask *child);
215211
/// This function MUST be called from the AsyncTask running the task group.
216212
///
217213
/// \code
218-
/// func swift_taskGroup_destroy(
219-
/// _ task: Builtin.NativeObject,
220-
/// _ group: UnsafeRawPointer
221-
/// )
214+
/// func swift_taskGroup_destroy(_ group: UnsafeRawPointer)
222215
/// \endcode
223216
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
224-
void swift_taskGroup_destroy(AsyncTask *task, TaskGroup *group);
217+
void swift_taskGroup_destroy(TaskGroup *group);
225218

226219
/// Before starting a task group child task, inform the group that there is one
227220
/// more 'pending' child to account for.
@@ -247,13 +240,10 @@ bool swift_taskGroup_addPending(TaskGroup *group);
247240
/// Its Swift signature is
248241
///
249242
/// \code
250-
/// func swift_taskGroup_cancelAll(
251-
/// task: Builtin.NativeObject,
252-
/// group: UnsafeRawPointer
253-
/// )
243+
/// func swift_taskGroup_cancelAll(group: UnsafeRawPointer)
254244
/// \endcode
255245
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
256-
void swift_taskGroup_cancelAll(AsyncTask *task, TaskGroup *group);
246+
void swift_taskGroup_cancelAll(TaskGroup *group);
257247

258248
/// Check ONLY if the group was explicitly cancelled, e.g. by `cancelAll`.
259249
///
@@ -263,13 +253,10 @@ void swift_taskGroup_cancelAll(AsyncTask *task, TaskGroup *group);
263253
/// This can be called from any thread. Its Swift signature is
264254
///
265255
/// \code
266-
/// func swift_taskGroup_isCancelled(
267-
/// task: Builtin.NativeObject,
268-
/// group: UnsafeRawPointer
269-
/// )
256+
/// func swift_taskGroup_isCancelled(group: UnsafeRawPointer)
270257
/// \endcode
271258
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
272-
bool swift_taskGroup_isCancelled(AsyncTask *task, TaskGroup *group);
259+
bool swift_taskGroup_isCancelled(TaskGroup *group);
273260

274261
/// Check the readyQueue of a task group, return true if it has no pending tasks.
275262
///
@@ -291,8 +278,7 @@ bool swift_taskGroup_isEmpty(TaskGroup *group);
291278
/// If the task is already cancelled, returns `false` but still adds
292279
/// the status record.
293280
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
294-
bool swift_task_addStatusRecord(AsyncTask *task,
295-
TaskStatusRecord *record);
281+
bool swift_task_addStatusRecord(TaskStatusRecord *record);
296282

297283
/// Add a status record to a task if the task has not already
298284
/// been cancelled. The record should not be modified while it is
@@ -303,8 +289,7 @@ bool swift_task_addStatusRecord(AsyncTask *task,
303289
/// If the task is already cancelled, returns `false` and does not
304290
/// add the status record.
305291
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
306-
bool swift_task_tryAddStatusRecord(AsyncTask *task,
307-
TaskStatusRecord *record);
292+
bool swift_task_tryAddStatusRecord(TaskStatusRecord *record);
308293

309294
/// Remove a status record from a task. After this call returns,
310295
/// the record's memory can be freely modified or deallocated.
@@ -317,7 +302,7 @@ bool swift_task_tryAddStatusRecord(AsyncTask *task,
317302
///s
318303
/// Returns false if the task has been cancelled.
319304
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
320-
bool swift_task_removeStatusRecord(AsyncTask *task, TaskStatusRecord *record);
305+
bool swift_task_removeStatusRecord(TaskStatusRecord *record);
321306

322307
/// Attach a child task to its parent task and return the newly created
323308
/// `ChildTaskStatusRecord`.
@@ -326,11 +311,11 @@ bool swift_task_removeStatusRecord(AsyncTask *task, TaskStatusRecord *record);
326311
/// `swift_task_detachChild` when the child has completed.
327312
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
328313
ChildTaskStatusRecord*
329-
swift_task_attachChild(AsyncTask *parent, AsyncTask *child);
314+
swift_task_attachChild(AsyncTask *child);
330315

331316
/// Remove a child task from the parent tracking it.
332317
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
333-
void swift_task_detachChild(AsyncTask *parent, ChildTaskStatusRecord *record);
318+
void swift_task_detachChild(ChildTaskStatusRecord *record);
334319

335320
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
336321
size_t swift_task_getJobFlags(AsyncTask* task);
@@ -342,12 +327,12 @@ bool swift_task_isCancelled(AsyncTask* task);
342327
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
343328
CancellationNotificationStatusRecord*
344329
swift_task_addCancellationHandler(
345-
AsyncTask *task, CancellationNotificationStatusRecord::FunctionType handler);
330+
CancellationNotificationStatusRecord::FunctionType handler);
346331

347332
/// Remove the passed cancellation record from the task.
348333
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
349334
void swift_task_removeCancellationHandler(
350-
AsyncTask *task, CancellationNotificationStatusRecord *record);
335+
CancellationNotificationStatusRecord *record);
351336

352337
/// Get a task local value from the passed in task. Its Swift signature is
353338
///
@@ -446,8 +431,8 @@ void swift_task_runAndBlockThread(const void *function,
446431
/// generally be tail-called, as it may continue executing the task
447432
/// synchronously if possible.
448433
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
449-
void swift_task_switch(AsyncTask *task,
450-
ExecutorRef currentExecutor,
434+
void swift_task_switch(SWIFT_ASYNC_CONTEXT AsyncContext *resumeToContext,
435+
TaskContinuationFunction *resumeFunction,
451436
ExecutorRef newExecutor);
452437

453438
/// Enqueue the given job to run asynchronously on the given executor.
@@ -552,6 +537,12 @@ void swift_job_run(Job *job, ExecutorRef executor);
552537
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
553538
AsyncTask *swift_task_getCurrent(void);
554539

540+
/// Return the current thread's active executor reference.
541+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
542+
ExecutorRef swift_task_getCurrentExecutor(void);
543+
555544
}
556545

546+
#pragma clang diagnostic pop
547+
557548
#endif

0 commit comments

Comments
 (0)