@@ -1044,16 +1044,44 @@ swift_task_create_commonImpl(size_t rawTaskCreateFlags,
10441044 " with parent %p at base pri %zu" ,
10451045 task, task->getTaskId (), parent, basePriority);
10461046
1047+ // Configure the initial context.
1048+
1049+ // Initialize the parent context pointer to null.
1050+ initialContext->Parent = nullptr ;
1051+
10471052#pragma clang diagnostic push
10481053#pragma clang diagnostic ignored "-Wcast-function-type-mismatch"
1049- // Initialize the task-local allocator.
1050- initialContext->ResumeParent =
1051- runInlineOption ? &completeInlineTask
1052- : reinterpret_cast <TaskContinuationFunction *>(
1053- asyncLet ? &completeTask
1054- : closureContext ? &completeTaskWithClosure
1055- : &completeTaskAndRelease);
1054+ // Initialize the resumption funclet pointer (async return address) to
1055+ // the final funclet for completing the task.
1056+
1057+ // Inline tasks are unmanaged, non-throwing, and use a non-escaping
1058+ // task function. The final funclet doesn't expect to get passed an error,
1059+ // and it doesn't clean up either the function or the task directly.
1060+ if (runInlineOption) {
1061+ initialContext->ResumeParent = &completeInlineTask;
1062+
1063+ // `async let` tasks are unmanaged and use a non-escaping task function.
1064+ // The final funclet shouldn't release the task or the task function.
1065+ } else if (asyncLet) {
1066+ initialContext->ResumeParent =
1067+ reinterpret_cast <TaskContinuationFunction*>(&completeTask);
1068+
1069+ // If we have a non-null closure context and the task function is not
1070+ // consumed by calling it, use a final funclet that releases both the
1071+ // task and the closure context.
1072+ } else if (closureContext && !taskCreateFlags.isTaskFunctionConsumed ()) {
1073+ initialContext->ResumeParent =
1074+ reinterpret_cast <TaskContinuationFunction*>(&completeTaskWithClosure);
1075+
1076+ // Otherwise, just release the task.
1077+ } else {
1078+ initialContext->ResumeParent =
1079+ reinterpret_cast <TaskContinuationFunction*>(&completeTaskAndRelease);
1080+ }
10561081#pragma clang diagnostic pop
1082+
1083+ // Initialize the task-local allocator and our other private runtime
1084+ // state for the task.
10571085 if ((asyncLet || (runInlineOption && runInlineOption->getAllocation ())) &&
10581086 initialSlabSize > 0 ) {
10591087 assert (parent || (runInlineOption && runInlineOption->getAllocation ()));
@@ -1095,14 +1123,6 @@ swift_task_create_commonImpl(size_t rawTaskCreateFlags,
10951123 task->_private ().Local .initializeLinkParent (task, parent);
10961124 }
10971125
1098- // Configure the initial context.
1099- //
1100- // FIXME: if we store a null pointer here using the standard ABI for
1101- // signed null pointers, then we'll have to authenticate context pointers
1102- // as if they might be null, even though the only time they ever might
1103- // be is the final hop. Store a signed null instead.
1104- initialContext->Parent = nullptr ;
1105-
11061126 // FIXME: add discarding flag
11071127 // FIXME: add task executor
11081128 concurrency::trace::task_create (
0 commit comments