Skip to content

Commit 55c5ae6

Browse files
committed
[Concurrency] Initial task names for Task(), more APIs soon
1 parent c2e36de commit 55c5ae6

File tree

26 files changed

+639
-45
lines changed

26 files changed

+639
-45
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2719,6 +2719,7 @@ class JobFlags : public FlagSet<uint32_t> {
27192719
// 27 is currently unused
27202720
Task_IsAsyncLetTask = 28,
27212721
Task_HasInitialTaskExecutorPreference = 29,
2722+
Task_HasInitialTaskName = 30,
27222723
};
27232724
// clang-format on
27242725

@@ -2755,6 +2756,9 @@ class JobFlags : public FlagSet<uint32_t> {
27552756
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_HasInitialTaskExecutorPreference,
27562757
task_hasInitialTaskExecutorPreference,
27572758
task_setHasInitialTaskExecutorPreference)
2759+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_HasInitialTaskName,
2760+
task_hasInitialTaskName,
2761+
task_setHasInitialTaskName)
27582762
};
27592763

27602764
/// Kinds of task status record.
@@ -2784,6 +2788,9 @@ enum class TaskStatusRecordKind : uint8_t {
27842788
/// enqueued on.
27852789
TaskExecutorPreference = 5,
27862790

2791+
/// A human-readable task name.
2792+
TaskName = 6,
2793+
27872794
// Kinds >= 192 are private to the implementation.
27882795
First_Reserved = 192,
27892796
Private_RecordLock = 192
@@ -2807,6 +2814,8 @@ enum class TaskOptionRecordKind : uint8_t {
28072814
/// Set the initial task executor preference of the task.
28082815
InitialTaskExecutorUnowned = 5,
28092816
InitialTaskExecutorOwned = 6,
2817+
// Set a human-readable task name.
2818+
InitialTaskName = 7,
28102819
/// Request a child task for swift_task_run_inline.
28112820
RunInline = UINT8_MAX,
28122821
};

include/swift/ABI/Task.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,28 @@ class AsyncTask : public Job {
421421
/// Checking this is, of course, inherently race-prone on its own.
422422
bool isCancelled() const;
423423

424+
// ==== INITIAL TASK RECORDS =================================================
425+
// A task may have a number of "initial" records set, they MUST be set in the
426+
// following order to make the task-local allocation/deallocation's stack
427+
// discipline easy to work out at the tasks destruction:
428+
//
429+
// - Initial TaskName
430+
// - Initial ExecutorPreference
431+
432+
// ==== Task Naming ----------------------------------------------------------
433+
434+
/// At task creation a task may be assigned a name.
435+
void pushInitialTaskName(const char* taskName);
436+
void dropInitialTaskNameRecord();
437+
438+
/// Get the initial task name that was given to this task during creation,
439+
/// or nullptr if the task has no name
440+
const char* getTaskName();
441+
442+
bool hasInitialTaskNameRecord() const {
443+
return Flags.task_hasInitialTaskName();
444+
}
445+
424446
// ==== Task Executor Preference ---------------------------------------------
425447

426448
/// Get the preferred task executor reference if there is one set for this

include/swift/ABI/TaskOptions.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,26 @@ class InitialTaskExecutorOwnedPreferenceTaskOptionRecord
131131
}
132132
};
133133

134+
class InitialTaskNameTaskOptionRecord
135+
: public TaskOptionRecord {
136+
137+
const char* TaskName;
138+
139+
public:
140+
InitialTaskNameTaskOptionRecord(
141+
const char* taskName)
142+
: TaskOptionRecord(TaskOptionRecordKind::InitialTaskName),
143+
TaskName(taskName) {}
144+
145+
const char* getTaskName() const {
146+
return TaskName;
147+
}
148+
149+
static bool classof(const TaskOptionRecord *record) {
150+
return record->getKind() == TaskOptionRecordKind::InitialTaskName;
151+
}
152+
};
153+
134154
/// Task option to specify the initial serial executor for the task.
135155
class InitialSerialExecutorTaskOptionRecord : public TaskOptionRecord {
136156
const SerialExecutorRef Executor;

include/swift/ABI/TaskStatus.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,22 @@ class TaskExecutorPreferenceStatusRecord : public TaskStatusRecord {
325325
}
326326
};
327327

328+
class TaskNameStatusRecord : public TaskStatusRecord {
329+
private:
330+
const char *Name;
331+
332+
public:
333+
TaskNameStatusRecord(const char *name)
334+
: TaskStatusRecord(TaskStatusRecordKind::TaskName),
335+
Name(name) {}
336+
337+
const char *getName() { return Name; }
338+
339+
static bool classof(const TaskStatusRecord *record) {
340+
return record->getKind() == TaskStatusRecordKind::TaskName;
341+
}
342+
};
343+
328344
// This record is allocated for a task to record what it is dependent on before
329345
// the task can make progress again.
330346
class TaskDependencyStatusRecord : public TaskStatusRecord {

include/swift/AST/ASTSynthesis.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ enum SingletonTypeSynthesizer {
5757
_taskExecutor, // the '_Concurrency.TaskExecutor' protocol
5858
_actor, // the '_Concurrency.Actor' protocol
5959
_distributedActor, // the 'Distributed.DistributedActor' protocol
60+
_unsafeRawBufferPointer // UnsafeRawBufferPointer
6061
};
6162
inline Type synthesizeType(SynthesisContext &SC,
6263
SingletonTypeSynthesizer kind) {
@@ -89,6 +90,8 @@ inline Type synthesizeType(SynthesisContext &SC,
8990
case _distributedActor:
9091
return SC.Context.getProtocol(KnownProtocolKind::DistributedActor)
9192
->getDeclaredInterfaceType();
93+
case _unsafeRawBufferPointer:
94+
return SC.Context.getUnsafeRawBufferPointerType();
9295
case _copyable:
9396
return SC.Context.getProtocol(KnownProtocolKind::Copyable)
9497
->getDeclaredInterfaceType();

include/swift/AST/Builtins.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,8 @@ BUILTIN_MISC_OPERATION(UnprotectedAddressOfBorrowOpaque, "unprotectedAddressOfBo
954954
/// createTask<T>(flags: Int,
955955
/// initialSerialExecutor: (Builtin.Executor)? = nil,
956956
/// taskGroup: Builtin.RawPointer? = nil,
957-
/// initialTaskExecutor: (Builtin.Executor)? = nil,
957+
/// initialTaskExecutorDeprecated: (Builtin.Executor)? = nil,
958+
/// initialTaskExecutorOwned: (any TaskExecutor)? = nil,
958959
/// operation: sending @escaping () async throws -> T)
959960
/// -> Builtin.NativeObject, Builtin.RawPointer)
960961
///

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ BASELINE_LANGUAGE_FEATURE(BuiltinBuildExecutor, 0, "Executor-building builtins")
151151
BASELINE_LANGUAGE_FEATURE(BuiltinBuildComplexEqualityExecutor, 0, "Executor-building for 'complexEquality executor' builtins")
152152
BASELINE_LANGUAGE_FEATURE(BuiltinBuildMainExecutor, 0, "MainActor executor building builtin")
153153
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskOwnedTaskExecutor, 0, "Task create with owned TaskExecutor")
154+
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskName, 0, "Task create with a name")
154155
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroup, 0, "Task create in task group builtin with extra flags")
155156
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroupWithExecutor, 0, "Task create in task group builtin with extra flags")
156157
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncDiscardingTaskInGroup, 0, "Task create in discarding task group builtin, accounting for the Void return type")

include/swift/Runtime/Concurrency.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,9 @@ void swift_task_reportUnexpectedExecutor(
10221022
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
10231023
JobPriority swift_task_getCurrentThreadPriority(void);
10241024

1025+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
1026+
const char *swift_task_getCurrentTaskName(void);
1027+
10251028
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
10261029
void swift_task_startOnMainActor(AsyncTask* job);
10271030

lib/AST/Builtins.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,19 @@ _generics(ParamS... params) {
219219
return {{params...}};
220220
}
221221

222+
///// A conditional synthesizer which generates a generic parameter list.
223+
///// If the 'condition' is false, no generic parameters are created.
224+
//template <class... ParamS>
225+
//struct ConditionalGenericParamListSynthesizer {
226+
// bool condition;
227+
// VariadicSynthesizerStorage<ParamS...> Params;
228+
//};
229+
//template <class... ParamS>
230+
//constexpr ConditionalGenericParamListSynthesizer<ParamS...>
231+
//_ifGenerics(bool condition, ParamS... params) {
232+
// return {condition, {params...}};
233+
//}
234+
222235
struct CountGenericParameters {
223236
unsigned &Count;
224237

@@ -292,6 +305,21 @@ static GenericParamList *synthesizeGenericParamList(SynthesisContext &SC,
292305
return paramList;
293306
}
294307

308+
//template <class... ParamsS>
309+
//static GenericParamList *synthesizeGenericParamList(
310+
// SynthesisContext &SC,
311+
// const ConditionalGenericParamListSynthesizer<ParamsS...> &params) {
312+
// if (params.condition) {
313+
// unsigned count = 0;
314+
// params.Params.visit(CountGenericParameters{count});
315+
// auto paramList = getGenericParams(SC.Context, count);
316+
// SC.GenericParams = paramList;
317+
// return paramList;
318+
// } else {
319+
// return GenericParamList::create(SC.Context, SourceLoc(), {}, SourceLoc());
320+
// }
321+
//}
322+
295323
namespace {
296324
struct CollectGenericParams {
297325
SynthesisContext &SC;
@@ -341,6 +369,24 @@ synthesizeGenericSignature(SynthesisContext &SC,
341369
/*allowInverses=*/false);
342370
}
343371

372+
//template <class... ParamsS>
373+
//static GenericSignature
374+
//synthesizeGenericSignature(SynthesisContext &SC,
375+
// const ConditionalGenericParamListSynthesizer<ParamsS...> &list) {
376+
// CollectGenericParams collector(SC);
377+
// if (list.condition) {
378+
// list.Params.visit(collector);
379+
//
380+
// return buildGenericSignature(SC.Context,
381+
// GenericSignature(),
382+
// std::move(collector.GenericParamTypes),
383+
// std::move(collector.AddedRequirements),
384+
// /*allowInverses=*/false);
385+
// } else {
386+
// return GenericSignature();
387+
// }
388+
//}
389+
344390
/// Build a builtin function declaration.
345391
///
346392
/// This is a "legacy" interface; you should probably use one of
@@ -1573,6 +1619,7 @@ static ValueDecl *getCreateTask(ASTContext &ctx, Identifier id) {
15731619
_existential(_taskExecutor),
15741620
/*else*/ _executor))),
15751621
_nil)),
1622+
_label("taskName", _defaulted(_optional(_rawPointer), _nil)),
15761623
_label("operation",
15771624
_sending(_function(_async(_throws(_thick)), _typeparam(0),
15781625
_parameters())))),
@@ -1597,6 +1644,7 @@ static ValueDecl *getCreateDiscardingTask(ASTContext &ctx, Identifier id) {
15971644
_existential(_taskExecutor),
15981645
/*else*/ _executor))),
15991646
_nil)),
1647+
_label("taskName", _defaulted(_optional(_rawPointer), _nil)),
16001648
_label("operation", _sending(_function(_async(_throws(_thick)), _void,
16011649
_parameters())))),
16021650
_tuple(_nativeObject, _rawPointer));

lib/IRGen/GenConcurrency.cpp

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -686,9 +686,9 @@ struct TaskGroupRecordTraits {
686686

687687
void initialize(IRGenFunction &IGF, Address recordAddr,
688688
Explosion &taskGroup) const {
689-
IGF.Builder.CreateStore(
690-
taskGroup.claimNext(),
691-
IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize()));
689+
auto record =
690+
IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
691+
IGF.Builder.CreateStore(taskGroup.claimNext(), record);
692692
}
693693
};
694694

@@ -747,6 +747,63 @@ struct InitialTaskExecutorOwnedRecordTraits {
747747
}
748748
};
749749

750+
struct InitialTaskNameRecordTraits {
751+
static StringRef getLabel() {
752+
return "task_name";
753+
}
754+
static llvm::StructType *getRecordType(IRGenModule &IGM) {
755+
return IGM.SwiftInitialTaskNameTaskOptionRecordTy;
756+
}
757+
static TaskOptionRecordFlags getRecordFlags() {
758+
return TaskOptionRecordFlags(TaskOptionRecordKind::InitialTaskName);
759+
}
760+
static CanType getValueType(ASTContext &ctx) {
761+
// FIXME: maybe raw pointer type?
762+
// return OptionalType::get(ctx.getUnsafeRawBufferPointerType())
763+
// ->getCanonicalType();
764+
765+
// return OptionalType::get(ctx.TheRawPointerType)
766+
// ->getCanonicalType();
767+
768+
return ctx.TheRawPointerType;
769+
}
770+
771+
// Create 'InitialTaskNameTaskOptionRecord'
772+
void initialize(IRGenFunction &IGF, Address recordAddr,
773+
Explosion &taskName) const {
774+
auto record =
775+
IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
776+
IGF.Builder.CreateStore(taskName.claimNext(), record);
777+
//
778+
// fprintf(stderr, "[%s:%d](%s) initialize InitialTaskNameTaskOptionRecord\n", __FILE_NAME__, __LINE__, __FUNCTION__);
779+
// taskName.dump();
780+
//
781+
// fprintf(stderr, "[%s:%d](%s) taskName.size() = %d\n", __FILE_NAME__, __LINE__, __FUNCTION__,
782+
// taskName.size());
783+
//
784+
// // FIXME: why is this wrong?
785+
// // [GenConcurrency.cpp:725](initialize) initialize InitialTaskNameTaskOptionRecord
786+
// // %16 = extractvalue { i64, i64 } %15, 0
787+
// // %17 = extractvalue { i64, i64 } %15, 1
788+
// // [GenConcurrency.cpp:728](initialize) taskName.size() = 2
789+
// // Assertion failed: (isa<llvm::StructType>(address.getElementType()) || isa<llvm::ArrayType>(address.getElementType())), function CreateStructGEP, file IRBuilder.h, line 193. Process 27213 stopped
790+
//
791+
//// auto record =
792+
//// IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
793+
//// IGF.Builder.CreateStore(taskName.claimNext(),
794+
//// IGF.Builder.CreateStructGEP(record, 0, Size()));
795+
//// IGF.Builder.CreateStore(taskName.claimNext(),
796+
//// IGF.Builder.CreateStructGEP(record, 1, Size()));
797+
//
798+
// auto record = IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
799+
// fprintf(stderr, "[%s:%d](%s) record = \n", __FILE_NAME__, __LINE__, __FUNCTION__);
800+
// record->dump();
801+
// IGF.Builder.CreateStore(
802+
// taskName.claimNext(),
803+
// record);
804+
}
805+
};
806+
750807
} // end anonymous namespace
751808

752809
static llvm::Value *
@@ -783,12 +840,20 @@ maybeAddInitialTaskExecutorOwnedOptionRecord(IRGenFunction &IGF,
783840
taskExecutorExistential);
784841
}
785842

843+
static llvm::Value *
844+
maybeAddTaskNameOptionRecord(IRGenFunction &IGF, llvm::Value *prevOptions,
845+
OptionalExplosion &taskName) {
846+
return maybeAddOptionRecord(IGF, prevOptions, InitialTaskNameRecordTraits(),
847+
taskName);
848+
}
849+
786850
std::pair<llvm::Value *, llvm::Value *>
787851
irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
788852
OptionalExplosion &serialExecutor,
789853
OptionalExplosion &taskGroup,
790854
OptionalExplosion &taskExecutorUnowned,
791855
OptionalExplosion &taskExecutorExistential,
856+
OptionalExplosion &taskName,
792857
Explosion &taskFunction,
793858
SubstitutionMap subs) {
794859
llvm::Value *taskOptions =
@@ -825,6 +890,16 @@ irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
825890
IGF, taskOptions, taskExecutorExistential);
826891
}
827892

893+
// Add an option record for the initial task name, if present.
894+
//
895+
// (lldb) e taskName.value.Values[0]
896+
// (llvm::Value *) $11 = 0x000060000220d1a0
897+
// (lldb) e taskName.value.Values[0]->dump()
898+
// %16 = extractvalue { i64, i64 } %15, 0
899+
// (lldb) e taskName.value.Values[1]->dump()
900+
// %17 = extractvalue { i64, i64 } %15, 1
901+
taskOptions = maybeAddTaskNameOptionRecord(IGF, taskOptions, taskName);
902+
828903
// In embedded Swift, create and pass result type info.
829904
taskOptions = maybeAddEmbeddedSwiftResultTypeInfo(IGF, taskOptions, resultType);
830905

lib/IRGen/GenConcurrency.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
106106
OptionalExplosion &taskGroup,
107107
OptionalExplosion &taskExecutorUnowned,
108108
OptionalExplosion &taskExecutorExistential,
109+
OptionalExplosion &taskName,
109110
Explosion &taskFunction,
110111
SubstitutionMap subs);
111112

lib/IRGen/IRGenModule.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,11 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
724724
SwiftTaskOptionRecordTy, // Base option record
725725
SwiftExecutorTy, // Executor
726726
});
727+
SwiftInitialTaskNameTaskOptionRecordTy =
728+
createStructType(*this, "swift.task_name_task_option", {
729+
SwiftTaskOptionRecordTy, // Base option record
730+
Int8PtrTy, // Task name string (char*)
731+
});
727732
SwiftJobTy = createStructType(*this, "swift.job", {
728733
RefCountedStructTy, // object header
729734
Int8PtrTy, Int8PtrTy, // SchedulerPrivate

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ class IRGenModule {
829829
llvm::StructType *SwiftTaskGroupTaskOptionRecordTy;
830830
llvm::StructType *SwiftInitialTaskExecutorUnownedPreferenceTaskOptionRecordTy;
831831
llvm::StructType *SwiftInitialTaskExecutorOwnedPreferenceTaskOptionRecordTy;
832+
llvm::StructType *SwiftInitialTaskNameTaskOptionRecordTy;
832833
llvm::StructType *SwiftResultTypeInfoTaskOptionRecordTy;
833834
llvm::PointerType *SwiftJobPtrTy;
834835
llvm::IntegerType *ExecutorFirstTy;

0 commit comments

Comments
 (0)