@@ -1044,16 +1044,44 @@ swift_task_create_commonImpl(size_t rawTaskCreateFlags,
1044
1044
" with parent %p at base pri %zu" ,
1045
1045
task, task->getTaskId (), parent, basePriority);
1046
1046
1047
+ // Configure the initial context.
1048
+
1049
+ // Initialize the parent context pointer to null.
1050
+ initialContext->Parent = nullptr ;
1051
+
1047
1052
#pragma clang diagnostic push
1048
1053
#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
+ }
1056
1081
#pragma clang diagnostic pop
1082
+
1083
+ // Initialize the task-local allocator and our other private runtime
1084
+ // state for the task.
1057
1085
if ((asyncLet || (runInlineOption && runInlineOption->getAllocation ())) &&
1058
1086
initialSlabSize > 0 ) {
1059
1087
assert (parent || (runInlineOption && runInlineOption->getAllocation ()));
@@ -1095,14 +1123,6 @@ swift_task_create_commonImpl(size_t rawTaskCreateFlags,
1095
1123
task->_private ().Local .initializeLinkParent (task, parent);
1096
1124
}
1097
1125
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
-
1106
1126
// FIXME: add discarding flag
1107
1127
// FIXME: add task executor
1108
1128
concurrency::trace::task_create (
0 commit comments