Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reapply "Task names" (#79562) #79600

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Runtimes/Core/Concurrency/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
add_subdirectory(InternalShims)

gyb_expand(TaskGroup+addTask.swift.gyb TaskGroup+addTask.swift)

add_library(swift_Concurrency
Actor.cpp
AsyncLet.cpp
Expand Down Expand Up @@ -77,10 +79,11 @@ add_library(swift_Concurrency
Task+TaskExecutor.swift
TaskCancellation.swift
TaskGroup.swift
TaskGroup+TaskExecutor.swift
TaskLocal.swift
TaskSleep.swift
TaskSleepDuration.swift)
TaskSleepDuration.swift
"${CMAKE_CURRENT_BINARY_DIR}/TaskGroup+addTask.swift")

include(${SwiftCore_CONCURRENCY_GLOBAL_EXECUTOR}.cmake)
target_compile_definitions(swift_Concurrency PRIVATE
$<$<COMPILE_LANGUAGE:C,CXX>:-DSWIFT_TARGET_LIBRARY_NAME=swift_Concurrency>
Expand Down
9 changes: 9 additions & 0 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -2730,6 +2730,7 @@ class JobFlags : public FlagSet<uint32_t> {
// 27 is currently unused
Task_IsAsyncLetTask = 28,
Task_HasInitialTaskExecutorPreference = 29,
Task_HasInitialTaskName = 30,
};
// clang-format on

Expand Down Expand Up @@ -2766,6 +2767,9 @@ class JobFlags : public FlagSet<uint32_t> {
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_HasInitialTaskExecutorPreference,
task_hasInitialTaskExecutorPreference,
task_setHasInitialTaskExecutorPreference)
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_HasInitialTaskName,
task_hasInitialTaskName,
task_setHasInitialTaskName)
};

/// Kinds of task status record.
Expand Down Expand Up @@ -2795,6 +2799,9 @@ enum class TaskStatusRecordKind : uint8_t {
/// enqueued on.
TaskExecutorPreference = 5,

/// A human-readable task name.
TaskName = 6,

// Kinds >= 192 are private to the implementation.
First_Reserved = 192,
Private_RecordLock = 192
Expand All @@ -2818,6 +2825,8 @@ enum class TaskOptionRecordKind : uint8_t {
/// Set the initial task executor preference of the task.
InitialTaskExecutorUnowned = 5,
InitialTaskExecutorOwned = 6,
// Set a human-readable task name.
InitialTaskName = 7,
/// Request a child task for swift_task_run_inline.
RunInline = UINT8_MAX,
};
Expand Down
22 changes: 22 additions & 0 deletions include/swift/ABI/Task.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,28 @@ class AsyncTask : public Job {
/// Checking this is, of course, inherently race-prone on its own.
bool isCancelled() const;

// ==== INITIAL TASK RECORDS =================================================
// A task may have a number of "initial" records set, they MUST be set in the
// following order to make the task-local allocation/deallocation's stack
// discipline easy to work out at the tasks destruction:
//
// - Initial TaskName
// - Initial ExecutorPreference

// ==== Task Naming ----------------------------------------------------------

/// At task creation a task may be assigned a name.
void pushInitialTaskName(const char* taskName);
void dropInitialTaskNameRecord();

/// Get the initial task name that was given to this task during creation,
/// or nullptr if the task has no name
const char* getTaskName();

bool hasInitialTaskNameRecord() const {
return Flags.task_hasInitialTaskName();
}

// ==== Task Executor Preference ---------------------------------------------

/// Get the preferred task executor reference if there is one set for this
Expand Down
20 changes: 20 additions & 0 deletions include/swift/ABI/TaskOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,26 @@ class InitialTaskExecutorOwnedPreferenceTaskOptionRecord
}
};

class InitialTaskNameTaskOptionRecord
: public TaskOptionRecord {

const char* TaskName;

public:
InitialTaskNameTaskOptionRecord(
const char* taskName)
: TaskOptionRecord(TaskOptionRecordKind::InitialTaskName),
TaskName(taskName) {}

const char* getTaskName() const {
return TaskName;
}

static bool classof(const TaskOptionRecord *record) {
return record->getKind() == TaskOptionRecordKind::InitialTaskName;
}
};

/// Task option to specify the initial serial executor for the task.
class InitialSerialExecutorTaskOptionRecord : public TaskOptionRecord {
const SerialExecutorRef Executor;
Expand Down
16 changes: 16 additions & 0 deletions include/swift/ABI/TaskStatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,22 @@ class TaskExecutorPreferenceStatusRecord : public TaskStatusRecord {
}
};

class TaskNameStatusRecord : public TaskStatusRecord {
private:
const char *Name;

public:
TaskNameStatusRecord(const char *name)
: TaskStatusRecord(TaskStatusRecordKind::TaskName),
Name(name) {}

const char *getName() { return Name; }

static bool classof(const TaskStatusRecord *record) {
return record->getKind() == TaskStatusRecordKind::TaskName;
}
};

// This record is allocated for a task to record what it is dependent on before
// the task can make progress again.
class TaskDependencyStatusRecord : public TaskStatusRecord {
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/ASTSynthesis.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ enum SingletonTypeSynthesizer {
_taskExecutor, // the '_Concurrency.TaskExecutor' protocol
_actor, // the '_Concurrency.Actor' protocol
_distributedActor, // the 'Distributed.DistributedActor' protocol
_unsafeRawBufferPointer // UnsafeRawBufferPointer
};
inline Type synthesizeType(SynthesisContext &SC,
SingletonTypeSynthesizer kind) {
Expand Down Expand Up @@ -89,6 +90,8 @@ inline Type synthesizeType(SynthesisContext &SC,
case _distributedActor:
return SC.Context.getProtocol(KnownProtocolKind::DistributedActor)
->getDeclaredInterfaceType();
case _unsafeRawBufferPointer:
return SC.Context.getUnsafeRawBufferPointerType();
case _copyable:
return SC.Context.getProtocol(KnownProtocolKind::Copyable)
->getDeclaredInterfaceType();
Expand Down
3 changes: 2 additions & 1 deletion include/swift/AST/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,8 @@ BUILTIN_MISC_OPERATION(UnprotectedAddressOfBorrowOpaque, "unprotectedAddressOfBo
/// createTask<T>(flags: Int,
/// initialSerialExecutor: (Builtin.Executor)? = nil,
/// taskGroup: Builtin.RawPointer? = nil,
/// initialTaskExecutor: (Builtin.Executor)? = nil,
/// initialTaskExecutorDeprecated: (Builtin.Executor)? = nil,
/// initialTaskExecutorOwned: (any TaskExecutor)? = nil,
/// operation: sending @escaping () async throws -> T)
/// -> Builtin.NativeObject, Builtin.RawPointer)
///
Expand Down
1 change: 1 addition & 0 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ BASELINE_LANGUAGE_FEATURE(BuiltinBuildExecutor, 0, "Executor-building builtins")
BASELINE_LANGUAGE_FEATURE(BuiltinBuildComplexEqualityExecutor, 0, "Executor-building for 'complexEquality executor' builtins")
BASELINE_LANGUAGE_FEATURE(BuiltinBuildMainExecutor, 0, "MainActor executor building builtin")
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskOwnedTaskExecutor, 0, "Task create with owned TaskExecutor")
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskName, 0, "Task create with a name")
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroup, 0, "Task create in task group builtin with extra flags")
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroupWithExecutor, 0, "Task create in task group builtin with extra flags")
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncDiscardingTaskInGroup, 0, "Task create in discarding task group builtin, accounting for the Void return type")
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Runtime/Concurrency.h
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,9 @@ void swift_task_reportUnexpectedExecutor(
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
JobPriority swift_task_getCurrentThreadPriority(void);

SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
const char *swift_task_getCurrentTaskName(void);

SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
void swift_task_startOnMainActor(AsyncTask* job);

Expand Down
2 changes: 2 additions & 0 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1573,6 +1573,7 @@ static ValueDecl *getCreateTask(ASTContext &ctx, Identifier id) {
_existential(_taskExecutor),
/*else*/ _executor))),
_nil)),
_label("taskName", _defaulted(_optional(_rawPointer), _nil)),
_label("operation",
_sending(_function(_async(_throws(_thick)), _typeparam(0),
_parameters())))),
Expand All @@ -1597,6 +1598,7 @@ static ValueDecl *getCreateDiscardingTask(ASTContext &ctx, Identifier id) {
_existential(_taskExecutor),
/*else*/ _executor))),
_nil)),
_label("taskName", _defaulted(_optional(_rawPointer), _nil)),
_label("operation", _sending(_function(_async(_throws(_thick)), _void,
_parameters())))),
_tuple(_nativeObject, _rawPointer));
Expand Down
34 changes: 34 additions & 0 deletions lib/IRGen/GenConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,29 @@ struct InitialTaskExecutorOwnedRecordTraits {
}
};

struct InitialTaskNameRecordTraits {
static StringRef getLabel() {
return "task_name";
}
static llvm::StructType *getRecordType(IRGenModule &IGM) {
return IGM.SwiftInitialTaskNameTaskOptionRecordTy;
}
static TaskOptionRecordFlags getRecordFlags() {
return TaskOptionRecordFlags(TaskOptionRecordKind::InitialTaskName);
}
static CanType getValueType(ASTContext &ctx) {
return ctx.TheRawPointerType;
}

// Create 'InitialTaskNameTaskOptionRecord'
void initialize(IRGenFunction &IGF, Address recordAddr,
Explosion &taskName) const {
auto record =
IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
IGF.Builder.CreateStore(taskName.claimNext(), record);
}
};

} // end anonymous namespace

static llvm::Value *
Expand Down Expand Up @@ -783,12 +806,20 @@ maybeAddInitialTaskExecutorOwnedOptionRecord(IRGenFunction &IGF,
taskExecutorExistential);
}

static llvm::Value *
maybeAddTaskNameOptionRecord(IRGenFunction &IGF, llvm::Value *prevOptions,
OptionalExplosion &taskName) {
return maybeAddOptionRecord(IGF, prevOptions, InitialTaskNameRecordTraits(),
taskName);
}

std::pair<llvm::Value *, llvm::Value *>
irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
OptionalExplosion &serialExecutor,
OptionalExplosion &taskGroup,
OptionalExplosion &taskExecutorUnowned,
OptionalExplosion &taskExecutorExistential,
OptionalExplosion &taskName,
Explosion &taskFunction,
SubstitutionMap subs) {
llvm::Value *taskOptions =
Expand Down Expand Up @@ -825,6 +856,9 @@ irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
IGF, taskOptions, taskExecutorExistential);
}

// Add an option record for the initial task name, if present.
taskOptions = maybeAddTaskNameOptionRecord(IGF, taskOptions, taskName);

// In embedded Swift, create and pass result type info.
taskOptions = maybeAddEmbeddedSwiftResultTypeInfo(IGF, taskOptions, resultType);

Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/GenConcurrency.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
OptionalExplosion &taskGroup,
OptionalExplosion &taskExecutorUnowned,
OptionalExplosion &taskExecutorExistential,
OptionalExplosion &taskName,
Explosion &taskFunction,
SubstitutionMap subs);

Expand Down
5 changes: 5 additions & 0 deletions lib/IRGen/IRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,11 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
SwiftTaskOptionRecordTy, // Base option record
SwiftExecutorTy, // Executor
});
SwiftInitialTaskNameTaskOptionRecordTy =
createStructType(*this, "swift.task_name_task_option", {
SwiftTaskOptionRecordTy, // Base option record
Int8PtrTy, // Task name string (char*)
});
SwiftJobTy = createStructType(*this, "swift.job", {
RefCountedStructTy, // object header
Int8PtrTy, Int8PtrTy, // SchedulerPrivate
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/IRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,7 @@ class IRGenModule {
llvm::StructType *SwiftTaskGroupTaskOptionRecordTy;
llvm::StructType *SwiftInitialTaskExecutorUnownedPreferenceTaskOptionRecordTy;
llvm::StructType *SwiftInitialTaskExecutorOwnedPreferenceTaskOptionRecordTy;
llvm::StructType *SwiftInitialTaskNameTaskOptionRecordTy;
llvm::StructType *SwiftResultTypeInfoTaskOptionRecordTy;
llvm::PointerType *SwiftJobPtrTy;
llvm::IntegerType *ExecutorFirstTy;
Expand Down
10 changes: 6 additions & 4 deletions lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3734,19 +3734,21 @@ static void emitBuiltinStackDealloc(IRGenSILFunction &IGF,

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

auto taskAndContext =
emitTaskCreate(IGF, flags, serialExecutor, taskGroup,
taskExecutorUnowned, taskExecutorOwned,
taskFunction, i->getSubstitutions());
taskName, taskFunction, i->getSubstitutions());
Explosion out;
out.add(taskAndContext.first);
out.add(taskAndContext.second);
Expand Down
8 changes: 5 additions & 3 deletions lib/SIL/Verifier/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2427,8 +2427,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
if (builtinKind == BuiltinValueKind::CreateAsyncTask) {
requireType(BI->getType(), _object(_tuple(_nativeObject, _rawPointer)),
"result of createAsyncTask");
require(arguments.size() == 6,
"createAsyncTask expects six arguments");
require(arguments.size() == 7,
"createAsyncTask expects seven arguments");
requireType(arguments[0]->getType(), _object(_swiftInt),
"first argument of createAsyncTask");
requireType(arguments[1]->getType(), _object(_optional(_executor)),
Expand All @@ -2448,7 +2448,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
_object(_optional(_executor)),
"fifth argument of createAsyncTask");
}
auto fnType = requireObjectType(SILFunctionType, arguments[5],
requireType(arguments[5]->getType(), _object(_optional(_rawPointer)),
"sixth argument of createAsyncTask");
auto fnType = requireObjectType(SILFunctionType, arguments[6],
"result of createAsyncTask");
bool haveSending =
F.getASTContext().LangOpts.hasFeature(Feature::SendingArgsAndResults);
Expand Down
9 changes: 9 additions & 0 deletions lib/SILGen/SILGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1636,6 +1636,14 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
}
}();

ManagedValue taskName = [&] {
if (options & CreateTaskOptions::OptionalEverything) {
return nextArg().getAsSingleValue(SGF);
} else {
return emitOptionalNone(ctx.TheRawPointerType);
}
}();

auto functionValue = [&] {
// No reabstraction required.
if (options & CreateTaskOptions::Discarding) {
Expand Down Expand Up @@ -1693,6 +1701,7 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
taskGroup.getUnmanagedValue(),
taskExecutorDeprecated.getUnmanagedValue(),
taskExecutorConsuming.forward(SGF),
taskName.forward(SGF),
functionValue.forward(SGF)
};

Expand Down
12 changes: 12 additions & 0 deletions stdlib/public/Concurrency/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,18 @@ JobPriority swift::swift_task_getCurrentThreadPriority() {
#endif
}

const char *swift_task_getTaskName(AsyncTask *task) {
if (!task) {
return nullptr;
}
return task->getTaskName();
}

const char *swift::swift_task_getCurrentTaskName() {
auto task = swift_task_getCurrent();
return swift_task_getTaskName(task);
}

// Implemented in Swift to avoid some annoying hard-coding about
// SerialExecutor's protocol witness table. We could inline this
// with effort, though.
Expand Down
5 changes: 4 additions & 1 deletion stdlib/public/Concurrency/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ set(SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES
Task+TaskExecutor.swift
TaskCancellation.swift
TaskGroup.swift
TaskGroup+TaskExecutor.swift
TaskGroup+Embedded.swift
DiscardingTaskGroup.swift
TaskLocal.swift
TaskSleep.swift
Expand Down Expand Up @@ -181,6 +181,9 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
${SWIFT_RUNTIME_CONCURRENCY_EXECUTOR_SOURCES}
${SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES}

GYB_SOURCES
TaskGroup+addTask.swift.gyb

SWIFT_MODULE_DEPENDS_ANDROID Android
SWIFT_MODULE_DEPENDS_LINUX Glibc
SWIFT_MODULE_DEPENDS_LINUX_STATIC Musl
Expand Down
Loading