Skip to content

Commit 4ab5d26

Browse files
authored
Merge pull request #77609 from ktoso/wip-task-names
[Concurrency] Task names
1 parent 6805e15 commit 4ab5d26

Some content is hidden

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

44 files changed

+1521
-1068
lines changed

Runtimes/Core/Concurrency/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
add_subdirectory(InternalShims)
22

3+
gyb_expand(TaskGroup+addTask.swift.gyb TaskGroup+addTask.swift)
4+
35
add_library(swift_Concurrency
46
Actor.cpp
57
AsyncLet.cpp
@@ -77,10 +79,11 @@ add_library(swift_Concurrency
7779
Task+TaskExecutor.swift
7880
TaskCancellation.swift
7981
TaskGroup.swift
80-
TaskGroup+TaskExecutor.swift
8182
TaskLocal.swift
8283
TaskSleep.swift
83-
TaskSleepDuration.swift)
84+
TaskSleepDuration.swift
85+
"${CMAKE_CURRENT_BINARY_DIR}/TaskGroup+addTask.swift")
86+
8487
include(${SwiftCore_CONCURRENCY_GLOBAL_EXECUTOR}.cmake)
8588
target_compile_definitions(swift_Concurrency PRIVATE
8689
$<$<COMPILE_LANGUAGE:C,CXX>:-DSWIFT_TARGET_LIBRARY_NAME=swift_Concurrency>

include/swift/ABI/MetadataValues.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2730,6 +2730,7 @@ class JobFlags : public FlagSet<uint32_t> {
27302730
// 27 is currently unused
27312731
Task_IsAsyncLetTask = 28,
27322732
Task_HasInitialTaskExecutorPreference = 29,
2733+
Task_HasInitialTaskName = 30,
27332734
};
27342735
// clang-format on
27352736

@@ -2766,6 +2767,9 @@ class JobFlags : public FlagSet<uint32_t> {
27662767
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_HasInitialTaskExecutorPreference,
27672768
task_hasInitialTaskExecutorPreference,
27682769
task_setHasInitialTaskExecutorPreference)
2770+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_HasInitialTaskName,
2771+
task_hasInitialTaskName,
2772+
task_setHasInitialTaskName)
27692773
};
27702774

27712775
/// Kinds of task status record.
@@ -2795,6 +2799,9 @@ enum class TaskStatusRecordKind : uint8_t {
27952799
/// enqueued on.
27962800
TaskExecutorPreference = 5,
27972801

2802+
/// A human-readable task name.
2803+
TaskName = 6,
2804+
27982805
// Kinds >= 192 are private to the implementation.
27992806
First_Reserved = 192,
28002807
Private_RecordLock = 192
@@ -2818,6 +2825,8 @@ enum class TaskOptionRecordKind : uint8_t {
28182825
/// Set the initial task executor preference of the task.
28192826
InitialTaskExecutorUnowned = 5,
28202827
InitialTaskExecutorOwned = 6,
2828+
// Set a human-readable task name.
2829+
InitialTaskName = 7,
28212830
/// Request a child task for swift_task_run_inline.
28222831
RunInline = UINT8_MAX,
28232832
};

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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,7 @@ static ValueDecl *getCreateTask(ASTContext &ctx, Identifier id) {
15731573
_existential(_taskExecutor),
15741574
/*else*/ _executor))),
15751575
_nil)),
1576+
_label("taskName", _defaulted(_optional(_rawPointer), _nil)),
15761577
_label("operation",
15771578
_sending(_function(_async(_throws(_thick)), _typeparam(0),
15781579
_parameters())))),
@@ -1597,6 +1598,7 @@ static ValueDecl *getCreateDiscardingTask(ASTContext &ctx, Identifier id) {
15971598
_existential(_taskExecutor),
15981599
/*else*/ _executor))),
15991600
_nil)),
1601+
_label("taskName", _defaulted(_optional(_rawPointer), _nil)),
16001602
_label("operation", _sending(_function(_async(_throws(_thick)), _void,
16011603
_parameters())))),
16021604
_tuple(_nativeObject, _rawPointer));

lib/IRGen/GenConcurrency.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,29 @@ 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+
return ctx.TheRawPointerType;
762+
}
763+
764+
// Create 'InitialTaskNameTaskOptionRecord'
765+
void initialize(IRGenFunction &IGF, Address recordAddr,
766+
Explosion &taskName) const {
767+
auto record =
768+
IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
769+
IGF.Builder.CreateStore(taskName.claimNext(), record);
770+
}
771+
};
772+
750773
} // end anonymous namespace
751774

752775
static llvm::Value *
@@ -783,12 +806,20 @@ maybeAddInitialTaskExecutorOwnedOptionRecord(IRGenFunction &IGF,
783806
taskExecutorExistential);
784807
}
785808

809+
static llvm::Value *
810+
maybeAddTaskNameOptionRecord(IRGenFunction &IGF, llvm::Value *prevOptions,
811+
OptionalExplosion &taskName) {
812+
return maybeAddOptionRecord(IGF, prevOptions, InitialTaskNameRecordTraits(),
813+
taskName);
814+
}
815+
786816
std::pair<llvm::Value *, llvm::Value *>
787817
irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
788818
OptionalExplosion &serialExecutor,
789819
OptionalExplosion &taskGroup,
790820
OptionalExplosion &taskExecutorUnowned,
791821
OptionalExplosion &taskExecutorExistential,
822+
OptionalExplosion &taskName,
792823
Explosion &taskFunction,
793824
SubstitutionMap subs) {
794825
llvm::Value *taskOptions =
@@ -825,6 +856,9 @@ irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
825856
IGF, taskOptions, taskExecutorExistential);
826857
}
827858

859+
// Add an option record for the initial task name, if present.
860+
taskOptions = maybeAddTaskNameOptionRecord(IGF, taskOptions, taskName);
861+
828862
// In embedded Swift, create and pass result type info.
829863
taskOptions = maybeAddEmbeddedSwiftResultTypeInfo(IGF, taskOptions, resultType);
830864

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;

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3734,19 +3734,21 @@ static void emitBuiltinStackDealloc(IRGenSILFunction &IGF,
37343734

37353735
static void emitBuiltinCreateAsyncTask(IRGenSILFunction &IGF,
37363736
swift::BuiltinInst *i) {
3737-
assert(i->getOperandValues().size() == 6 &&
3738-
"createAsyncTask needs 6 operands");
3737+
assert(i->getOperandValues().size() == 7 &&
3738+
"createAsyncTask needs 7 operands");
37393739
auto flags = IGF.getLoweredSingletonExplosion(i->getOperand(0));
37403740
auto serialExecutor = IGF.getLoweredOptionalExplosion(i->getOperand(1));
37413741
auto taskGroup = IGF.getLoweredOptionalExplosion(i->getOperand(2));
37423742
auto taskExecutorUnowned = IGF.getLoweredOptionalExplosion(i->getOperand(3));
37433743
auto taskExecutorOwned = IGF.getLoweredOptionalExplosion(i->getOperand(4));
3744-
Explosion taskFunction = IGF.getLoweredExplosion(i->getOperand(5));
3744+
// %11 = enum $Optional<UnsafeRawBufferPointer>, #Optional.some!enumelt, %10 : $UnsafeRawBufferPointer // user: %20
3745+
auto taskName = IGF.getLoweredOptionalExplosion(i->getOperand(5));
3746+
Explosion taskFunction = IGF.getLoweredExplosion(i->getOperand(6));
37453747

37463748
auto taskAndContext =
37473749
emitTaskCreate(IGF, flags, serialExecutor, taskGroup,
37483750
taskExecutorUnowned, taskExecutorOwned,
3749-
taskFunction, i->getSubstitutions());
3751+
taskName, taskFunction, i->getSubstitutions());
37503752
Explosion out;
37513753
out.add(taskAndContext.first);
37523754
out.add(taskAndContext.second);

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,8 +2427,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
24272427
if (builtinKind == BuiltinValueKind::CreateAsyncTask) {
24282428
requireType(BI->getType(), _object(_tuple(_nativeObject, _rawPointer)),
24292429
"result of createAsyncTask");
2430-
require(arguments.size() == 6,
2431-
"createAsyncTask expects six arguments");
2430+
require(arguments.size() == 7,
2431+
"createAsyncTask expects seven arguments");
24322432
requireType(arguments[0]->getType(), _object(_swiftInt),
24332433
"first argument of createAsyncTask");
24342434
requireType(arguments[1]->getType(), _object(_optional(_executor)),
@@ -2448,7 +2448,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
24482448
_object(_optional(_executor)),
24492449
"fifth argument of createAsyncTask");
24502450
}
2451-
auto fnType = requireObjectType(SILFunctionType, arguments[5],
2451+
requireType(arguments[5]->getType(), _object(_optional(_rawPointer)),
2452+
"sixth argument of createAsyncTask");
2453+
auto fnType = requireObjectType(SILFunctionType, arguments[6],
24522454
"result of createAsyncTask");
24532455
bool haveSending =
24542456
F.getASTContext().LangOpts.hasFeature(Feature::SendingArgsAndResults);

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,14 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
16361636
}
16371637
}();
16381638

1639+
ManagedValue taskName = [&] {
1640+
if (options & CreateTaskOptions::OptionalEverything) {
1641+
return nextArg().getAsSingleValue(SGF);
1642+
} else {
1643+
return emitOptionalNone(ctx.TheRawPointerType);
1644+
}
1645+
}();
1646+
16391647
auto functionValue = [&] {
16401648
// No reabstraction required.
16411649
if (options & CreateTaskOptions::Discarding) {
@@ -1693,6 +1701,7 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
16931701
taskGroup.getUnmanagedValue(),
16941702
taskExecutorDeprecated.getUnmanagedValue(),
16951703
taskExecutorConsuming.forward(SGF),
1704+
taskName.forward(SGF),
16961705
functionValue.forward(SGF)
16971706
};
16981707

stdlib/public/Concurrency/Actor.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,18 @@ JobPriority swift::swift_task_getCurrentThreadPriority() {
314314
#endif
315315
}
316316

317+
const char *swift_task_getTaskName(AsyncTask *task) {
318+
if (!task) {
319+
return nullptr;
320+
}
321+
return task->getTaskName();
322+
}
323+
324+
const char *swift::swift_task_getCurrentTaskName() {
325+
auto task = swift_task_getCurrent();
326+
return swift_task_getTaskName(task);
327+
}
328+
317329
// Implemented in Swift to avoid some annoying hard-coding about
318330
// SerialExecutor's protocol witness table. We could inline this
319331
// with effort, though.

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ set(SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES
144144
Task+TaskExecutor.swift
145145
TaskCancellation.swift
146146
TaskGroup.swift
147-
TaskGroup+TaskExecutor.swift
147+
TaskGroup+Embedded.swift
148148
DiscardingTaskGroup.swift
149149
TaskLocal.swift
150150
TaskSleep.swift
@@ -181,6 +181,9 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
181181
${SWIFT_RUNTIME_CONCURRENCY_EXECUTOR_SOURCES}
182182
${SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES}
183183

184+
GYB_SOURCES
185+
TaskGroup+addTask.swift.gyb
186+
184187
SWIFT_MODULE_DEPENDS_ANDROID Android
185188
SWIFT_MODULE_DEPENDS_LINUX Glibc
186189
SWIFT_MODULE_DEPENDS_LINUX_STATIC Musl

0 commit comments

Comments
 (0)