2222
2323#include " swift/ABI/MetadataValues.h"
2424#include " swift/ABI/Task.h"
25+ #include " swift/ABI/Executor.h"
2526#include " swift/Runtime/HeapObject.h"
2627
2728namespace swift {
@@ -278,22 +279,23 @@ class EscalationNotificationStatusRecord : public TaskStatusRecord {
278279// This record is allocated for a task to record what it is dependent on before
279280// the task can make progress again.
280281class TaskDependencyStatusRecord : public TaskStatusRecord {
281- // A word sized storage which references what this task is suspended waiting
282- // for. Note that this is different from the waitQueue in the future fragment
283- // of a task since that denotes all the tasks which this specific task, will
284- // unblock.
282+ // A word sized storage which references what this task is waiting for. Note
283+ // that this is different from the waitQueue in the future fragment of a task
284+ // since that denotes all the tasks which this specific task, will unblock.
285285 //
286286 // This field is only really pointing to something valid when the
287- // ActiveTaskStatus specifies that the task is suspended. It can be accessed
288- // asynchronous to the task during escalation which will therefore require the
289- // task status record lock for synchronization.
287+ // ActiveTaskStatus specifies that the task is suspended or enqueued . It can
288+ // be accessed asynchronous to the task during escalation which will therefore
289+ // require the task status record lock for synchronization.
290290 //
291291 // When a task has TaskDependencyStatusRecord in the status record list, it
292292 // must be the innermost status record, barring the status record lock which
293293 // could be taken while this record is present.
294294 //
295295 // The type of thing we are waiting on, is specified in the enum below
296- union {
296+ union Dependent {
297+ constexpr Dependent () {}
298+
297299 // This task is suspended waiting on another task. This could be an async
298300 // let child task or it could be another unstructured task.
299301 AsyncTask *Task;
@@ -310,35 +312,58 @@ class TaskDependencyStatusRecord : public TaskStatusRecord {
310312 // the duration of the wait. We do not need to take an additional +1 on this
311313 // task group in this dependency record.
312314 TaskGroup *TaskGroup;
313- } WaitingOn;
315+
316+ // The task is enqueued waiting on an executor. It could be any kind of
317+ // executor - the generic executor, the default actor's executor, or an
318+ // actor with a custom executor.
319+ //
320+ // This information is helpful to know *where* a task is enqueued into
321+ // (potentially intrusively), so that the appropriate escalation effect
322+ // (which may be different for each type of executor) can happen if a task
323+ // is escalated while enqueued.
324+ ExecutorRef Executor;
325+ } DependentOn;
314326
315327 // Enum specifying the type of dependency this task has
316328 enum DependencyKind {
317329 WaitingOnTask = 1 ,
318330 WaitingOnContinuation,
319331 WaitingOnTaskGroup,
332+
333+ EnqueuedOnExecutor,
320334 } DependencyKind;
321335
336+ // The task that has this task status record - ie a backpointer from the
337+ // record to the task with the record. This is not its own +1, we rely on the
338+ // fact that since this status record is linked into a task, the task is
339+ // already alive and maintained by someone and we can safely borrow the
340+ // reference.
341+ AsyncTask *WaitingTask;
342+
322343public:
323- TaskDependencyStatusRecord (AsyncTask *task) :
344+ TaskDependencyStatusRecord (AsyncTask *waitingTask, AsyncTask * task) :
324345 TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
325- DependencyKind (WaitingOnTask) {
326- WaitingOn .Task = task;
346+ DependencyKind (WaitingOnTask), WaitingTask(waitingTask) {
347+ DependentOn .Task = task;
327348 }
328349
329- TaskDependencyStatusRecord (ContinuationAsyncContext *context) :
350+ TaskDependencyStatusRecord (AsyncTask *waitingTask, ContinuationAsyncContext *context) :
330351 TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
331- DependencyKind (WaitingOnContinuation) {
332- WaitingOn .Continuation = context;
352+ DependencyKind (WaitingOnContinuation), WaitingTask(waitingTask) {
353+ DependentOn .Continuation = context;
333354 }
334355
335- TaskDependencyStatusRecord (TaskGroup *taskGroup) :
356+ TaskDependencyStatusRecord (AsyncTask *waitingTask, TaskGroup *taskGroup) :
336357 TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
337- DependencyKind (WaitingOnTaskGroup) {
338- WaitingOn .TaskGroup = taskGroup;
358+ DependencyKind (WaitingOnTaskGroup), WaitingTask(waitingTask) {
359+ DependentOn .TaskGroup = taskGroup;
339360 }
340361
341- void destroy () { }
362+ TaskDependencyStatusRecord (AsyncTask *waitingTask, ExecutorRef executor) :
363+ TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
364+ DependencyKind (EnqueuedOnExecutor), WaitingTask(waitingTask) {
365+ DependentOn.Executor = executor;
366+ }
342367
343368 static bool classof (const TaskStatusRecord *record) {
344369 return record->getKind () == TaskStatusRecordKind::TaskDependency;
0 commit comments