Skip to content

Commit 3727db2

Browse files
committed
Create a separate set of task creation flags for swift_task_create.
The flags that are useful for task creation are a bit different from the flags that go on a job. Create a separate flag set for task creation and use that in the API for `swift_task_create`. For now, have the callers do the remapping.
1 parent 51d9db6 commit 3727db2

File tree

5 files changed

+107
-75
lines changed

5 files changed

+107
-75
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,6 +2022,42 @@ enum class JobPriority : size_t {
20222022
Unspecified = 0x00,
20232023
};
20242024

2025+
/// Flags for task creation.
2026+
class TaskCreateFlags : public FlagSet<size_t> {
2027+
public:
2028+
enum {
2029+
Priority = 0,
2030+
Priority_width = 8,
2031+
2032+
Task_IsChildTask = 8,
2033+
Task_IsAsyncLetTask = 9,
2034+
Task_CopyThreadLocals = 10,
2035+
Task_InheritContext = 11,
2036+
Task_EnqueueJob = 12,
2037+
};
2038+
2039+
explicit constexpr TaskCreateFlags(size_t bits) : FlagSet(bits) {}
2040+
constexpr TaskCreateFlags() {}
2041+
2042+
FLAGSET_DEFINE_FIELD_ACCESSORS(Priority, Priority_width, JobPriority,
2043+
getPriority, setPriority)
2044+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsChildTask,
2045+
isChildTask,
2046+
setIsChildTask)
2047+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsAsyncLetTask,
2048+
isAsyncLetTask,
2049+
setIsAsyncLetTask)
2050+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_CopyThreadLocals,
2051+
copyThreadLocals,
2052+
setCopyThreadLocals)
2053+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_InheritContext,
2054+
inheritContext,
2055+
setInheritContext)
2056+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_EnqueueJob,
2057+
enqueueJob,
2058+
setEnqueueJob)
2059+
};
2060+
20252061
/// Flags for schedulable jobs.
20262062
class JobFlags : public FlagSet<uint32_t> {
20272063
public:
@@ -2039,7 +2075,7 @@ class JobFlags : public FlagSet<uint32_t> {
20392075
Task_IsChildTask = 24,
20402076
Task_IsFuture = 25,
20412077
Task_IsGroupChildTask = 26,
2042-
Task_IsContinuingAsyncTask = 27,
2078+
// 27 is currently unused
20432079
Task_IsAsyncLetTask = 28,
20442080
};
20452081

@@ -2070,9 +2106,6 @@ class JobFlags : public FlagSet<uint32_t> {
20702106
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsGroupChildTask,
20712107
task_isGroupChildTask,
20722108
task_setIsGroupChildTask)
2073-
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsContinuingAsyncTask,
2074-
task_isContinuingAsyncTask,
2075-
task_setIsContinuingAsyncTask)
20762109
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsAsyncLetTask,
20772110
task_isAsyncLetTask,
20782111
task_setIsAsyncLetTask)

include/swift/Runtime/Concurrency.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ AsyncTaskAndContext swift_task_create_group_future_f(
8787
/// Create a task object.
8888
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
8989
AsyncTaskAndContext swift_task_create(
90-
size_t flags,
90+
size_t taskCreateFlags,
9191
TaskOptionRecord *options,
9292
const Metadata *futureResultType,
9393
FutureAsyncSignature::FunctionType *function, void *closureContext,

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,20 +1547,6 @@ FUNCTION(TaskCancel,
15471547
ARGS(SwiftTaskPtrTy),
15481548
ATTRS(NoUnwind, ArgMemOnly))
15491549

1550-
// AsyncTaskAndContext swift_task_create_f(
1551-
// size_t flags,
1552-
// TaskOptionRecord *options,
1553-
// TaskContinuationFunction* function, size_t contextSize);
1554-
FUNCTION(TaskCreateFunc,
1555-
swift_task_create_f, SwiftCC,
1556-
ConcurrencyAvailability,
1557-
RETURNS(AsyncTaskAndContextTy),
1558-
ARGS(SizeTy,
1559-
SwiftTaskOptionRecordPtrTy,
1560-
TaskContinuationFunctionPtrTy,
1561-
SizeTy),
1562-
ATTRS(NoUnwind, ArgMemOnly))
1563-
15641550
// AsyncTaskAndContext swift_task_create_future(
15651551
// size_t flags,
15661552
// TaskOptionRecord *options,
@@ -1577,22 +1563,6 @@ FUNCTION(TaskCreateFuture,
15771563
RefCountedPtrTy),
15781564
ATTRS(NoUnwind, ArgMemOnly))
15791565

1580-
// AsyncTaskAndContext swift_task_create_future_f(
1581-
// size_t flags,
1582-
// TaskOptionRecord *options,
1583-
// const Metadata *futureResultType,
1584-
// TaskContinuationFunction *function, size_t contextSize);
1585-
FUNCTION(TaskCreateFutureFunc,
1586-
swift_task_create_future_f, SwiftCC,
1587-
ConcurrencyAvailability,
1588-
RETURNS(AsyncTaskAndContextTy),
1589-
ARGS(SizeTy,
1590-
SwiftTaskOptionRecordPtrTy,
1591-
TypeMetadataPtrTy,
1592-
TaskContinuationFunctionPtrTy,
1593-
SizeTy),
1594-
ATTRS(NoUnwind, ArgMemOnly))
1595-
15961566
// AsyncTaskAndContext swift_task_create_group_future(
15971567
// size_t flags,
15981568
// TaskGroup *group,
@@ -1611,21 +1581,21 @@ FUNCTION(TaskCreateGroupFuture,
16111581
RefCountedPtrTy),
16121582
ATTRS(NoUnwind, ArgMemOnly))
16131583

1614-
// AsyncTaskAndContext swift_task_create_group_future_f(
1615-
// size_t flags,
1616-
// TaskGroup *group,
1617-
// TaskOptionRecord *options
1584+
// AsyncTaskAndContext swift_task_create(
1585+
// size_t taskCreateFlags,
1586+
// TaskOptionRecord *options,
16181587
// const Metadata *futureResultType,
1619-
// TaskContinuationFunction *function, size_t contextSize);
1620-
FUNCTION(TaskCreateGroupFutureFunc,
1621-
swift_task_create_group_future_f, SwiftCC,
1588+
// void *closureEntry, HeapObject *closureContext,
1589+
// size_t initialContextSize);
1590+
FUNCTION(TaskCreate,
1591+
swift_task_create, SwiftCC,
16221592
ConcurrencyAvailability,
16231593
RETURNS(AsyncTaskAndContextTy),
16241594
ARGS(SizeTy,
1625-
SwiftTaskGroupPtrTy,
16261595
SwiftTaskOptionRecordPtrTy,
16271596
TypeMetadataPtrTy,
1628-
TaskContinuationFunctionPtrTy,
1597+
Int8PtrTy,
1598+
RefCountedPtrTy,
16291599
SizeTy),
16301600
ATTRS(NoUnwind, ArgMemOnly))
16311601

stdlib/public/CompatibilityOverride/CompatibilityOverrideConcurrency.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,14 @@ OVERRIDE_ACTOR(task_switch, void,
9898

9999
OVERRIDE_TASK(task_create, AsyncTaskAndContext,
100100
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
101-
(size_t flags,
101+
(size_t taskCreateFlags,
102102
TaskOptionRecord *options,
103103
const Metadata *futureResultType,
104104
FutureAsyncSignature::FunctionType *function,
105105
void *closureContext,
106106
size_t initialContextSize),
107-
(flags, options, futureResultType, function, closureContext,
108-
initialContextSize))
107+
(taskCreateFlags, options, futureResultType, function,
108+
closureContext, initialContextSize))
109109

110110
OVERRIDE_TASK(task_future_wait, void, SWIFT_EXPORT_FROM(swift_Concurrency),
111111
SWIFT_CC(swiftasync), swift::,

stdlib/public/Concurrency/Task.cpp

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -405,17 +405,28 @@ task_future_wait_resume_adapter(SWIFT_ASYNC_CONTEXT AsyncContext *_context) {
405405
/// task's stack allocator.
406406
SWIFT_CC(swift)
407407
static AsyncTaskAndContext swift_task_createImpl(
408-
size_t rawFlags,
408+
size_t rawTaskCreateFlags,
409409
TaskOptionRecord *options,
410410
const Metadata *futureResultType,
411411
FutureAsyncSignature::FunctionType *function, void *closureContext,
412412
size_t initialContextSize) {
413-
JobFlags flags(rawFlags);
414-
bool isAsyncLetTask = flags.task_isAsyncLetTask();
415-
assert((futureResultType != nullptr) == flags.task_isFuture());
416-
assert(!isAsyncLetTask || isAsyncLetTask == flags.task_isChildTask());
417-
assert(!flags.task_isFuture() ||
418-
initialContextSize >= sizeof(FutureAsyncContext));
413+
TaskCreateFlags taskCreateFlags(rawTaskCreateFlags);
414+
415+
// Propagate task-creation flags to job flags as appropriate.
416+
JobFlags jobFlags(JobKind::Task, taskCreateFlags.getPriority());
417+
418+
bool isAsyncLetTask = taskCreateFlags.isAsyncLetTask();
419+
if (isAsyncLetTask) {
420+
jobFlags.task_setIsAsyncLetTask(true);
421+
jobFlags.task_setIsChildTask(true);
422+
} else {
423+
jobFlags.task_setIsChildTask(taskCreateFlags.isChildTask());
424+
}
425+
426+
if (futureResultType) {
427+
jobFlags.task_setIsFuture(true);
428+
assert(initialContextSize >= sizeof(FutureAsyncContext));
429+
}
419430

420431
// Collect the options we know about.
421432
ExecutorRef executor = ExecutorRef::generic();
@@ -428,32 +439,28 @@ static AsyncTaskAndContext swift_task_createImpl(
428439

429440
case TaskOptionRecordKind::TaskGroup:
430441
group = cast<TaskGroupTaskOptionRecord>(option)->getGroup();
431-
break;
432-
433-
default:
434-
// Ignore unknown options.
442+
assert(group && "Missing group");
443+
jobFlags.task_setIsGroupChildTask(true);
435444
break;
436445
}
437446
}
438447

439-
assert((group != nullptr) == flags.task_isGroupChildTask());
440-
441448
AsyncTask *parent = nullptr;
442-
if (flags.task_isChildTask()) {
449+
if (jobFlags.task_isChildTask()) {
443450
parent = swift_task_getCurrent();
444451
assert(parent != nullptr && "creating a child task with no active task");
445452

446453
// Inherit the priority of the parent task if unspecified.
447-
if (flags.getPriority() == JobPriority::Unspecified)
448-
flags.setPriority(parent->getPriority());
454+
if (jobFlags.getPriority() == JobPriority::Unspecified)
455+
jobFlags.setPriority(parent->getPriority());
449456
}
450457

451458
// Figure out the size of the header.
452459
size_t headerSize = sizeof(AsyncTask);
453460
if (parent) {
454461
headerSize += sizeof(AsyncTask::ChildFragment);
455462
}
456-
if (flags.task_isGroupChildTask()) {
463+
if (group) {
457464
headerSize += sizeof(AsyncTask::GroupChildFragment);
458465
}
459466
if (futureResultType) {
@@ -527,10 +534,10 @@ static AsyncTaskAndContext swift_task_createImpl(
527534
// Initialize the refcount bits to "immortal", so that
528535
// ARC operations don't have any effect on the task.
529536
task = new(allocation) AsyncTask(&taskHeapMetadata,
530-
InlineRefCounts::Immortal, flags,
537+
InlineRefCounts::Immortal, jobFlags,
531538
function, initialContext);
532539
} else {
533-
task = new(allocation) AsyncTask(&taskHeapMetadata, flags,
540+
task = new(allocation) AsyncTask(&taskHeapMetadata, jobFlags,
534541
function, initialContext);
535542
}
536543

@@ -541,7 +548,7 @@ static AsyncTaskAndContext swift_task_createImpl(
541548
}
542549

543550
// Initialize the group child fragment if applicable.
544-
if (flags.task_isGroupChildTask()) {
551+
if (group) {
545552
auto groupChildFragment = task->groupChildFragment();
546553
new (groupChildFragment) AsyncTask::GroupChildFragment(group);
547554
}
@@ -604,6 +611,16 @@ static AsyncTaskAndContext swift_task_createImpl(
604611
initialContext->Flags = AsyncContextKind::Ordinary;
605612
initialContext->Flags.setShouldNotDeallocateInCallee(true);
606613

614+
// If we're supposed to copy task locals, do so now.
615+
if (taskCreateFlags.copyThreadLocals()) {
616+
swift_task_localsCopyTo(task);
617+
}
618+
619+
// If we're supposed to enqueue the task, do so now.
620+
if (taskCreateFlags.enqueueJob()) {
621+
swift_task_enqueue(task, executor);
622+
}
623+
607624
return {task, initialContext};
608625
}
609626

@@ -632,6 +649,18 @@ AsyncTaskAndContext swift::swift_task_create_future_f(
632649
function, initialContextSize);
633650
}
634651

652+
/// Temporary hack to convert from job flags to task-creation flags,
653+
/// until we can eliminate the entry points that operate in terms of job
654+
/// flags.
655+
static size_t convertJobFlagsToTaskCreateFlags(size_t rawJobFlags) {
656+
JobFlags jobFlags(rawJobFlags);
657+
TaskCreateFlags taskCreateFlags;
658+
taskCreateFlags.setPriority(jobFlags.getPriority());
659+
taskCreateFlags.setIsChildTask(jobFlags.task_isChildTask());
660+
taskCreateFlags.setIsAsyncLetTask(jobFlags.task_isAsyncLetTask());
661+
return taskCreateFlags.getOpaqueValue();
662+
}
663+
635664
AsyncTaskAndContext swift::swift_task_create_group_future_f(
636665
size_t flags,
637666
TaskGroup *group,
@@ -646,8 +675,8 @@ AsyncTaskAndContext swift::swift_task_create_group_future_f(
646675
}
647676

648677
return swift_task_create(
649-
flags, options, futureResultType, function, /*closureContext=*/nullptr,
650-
initialContextSize);
678+
convertJobFlagsToTaskCreateFlags(flags), options, futureResultType,
679+
function, /*closureContext=*/nullptr, initialContextSize);
651680
}
652681

653682
/// Extract the entry point address and initial context size from an async closure value.
@@ -681,8 +710,8 @@ AsyncTaskAndContext swift::swift_task_create_future(
681710
>(closureEntry, closureContext);
682711

683712
return swift_task_create(
684-
flags, options, futureResultType, taskEntry, closureContext,
685-
initialContextSize);
713+
convertJobFlagsToTaskCreateFlags(flags), options, futureResultType,
714+
taskEntry, closureContext, initialContextSize);
686715
}
687716

688717
AsyncTaskAndContext swift::swift_task_create_async_let_future(
@@ -701,8 +730,8 @@ AsyncTaskAndContext swift::swift_task_create_async_let_future(
701730
JobFlags flags(rawFlags);
702731
flags.task_setIsAsyncLetTask(true);
703732
return swift_task_create(
704-
flags.getOpaqueValue(), options, futureResultType,
705-
taskEntry, closureContext, initialContextSize);
733+
convertJobFlagsToTaskCreateFlags(flags.getOpaqueValue()), options,
734+
futureResultType, taskEntry, closureContext, initialContextSize);
706735
}
707736

708737
AsyncTaskAndContext
@@ -729,8 +758,8 @@ swift::swift_task_create_group_future(
729758
}
730759

731760
return swift_task_create(
732-
flags, options, futureResultType, taskEntry, closureContext,
733-
initialContextSize);
761+
convertJobFlagsToTaskCreateFlags(flags), options, futureResultType,
762+
taskEntry, closureContext, initialContextSize);
734763
}
735764

736765
SWIFT_CC(swiftasync)

0 commit comments

Comments
 (0)