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 {
@@ -61,25 +62,10 @@ class TaskStatusRecord {
6162
6263 TaskStatusRecord *getParent () const { return Parent; }
6364
64- // / Change the parent of this unregistered status record to the
65- // / given record.
66- // /
67- // / This should be used when the record has been previously initialized
68- // / without knowing what the true parent is. If we decide to cache
69- // / important information (e.g. the earliest timeout) in the innermost
70- // / status record, this is the method that should fill that in
71- // / from the parent.
65+ // / Change the parent of this status record to the given record.
7266 void resetParent (TaskStatusRecord *newParent) {
7367 Parent = newParent;
74- // TODO: cache
7568 }
76-
77- // / Splice a record out of the status-record chain.
78- // /
79- // / Unlike resetParent, this assumes that it's just removing one or
80- // / more records from the chain and that there's no need to do any
81- // / extra cache manipulation.
82- void spliceParent (TaskStatusRecord *newParent) { Parent = newParent; }
8369};
8470
8571// / A status record which states that a task has one or
@@ -293,22 +279,23 @@ class EscalationNotificationStatusRecord : public TaskStatusRecord {
293279// This record is allocated for a task to record what it is dependent on before
294280// the task can make progress again.
295281class TaskDependencyStatusRecord : public TaskStatusRecord {
296- // A word sized storage which references what this task is suspended waiting
297- // for. Note that this is different from the waitQueue in the future fragment
298- // of a task since that denotes all the tasks which this specific task, will
299- // 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.
300285 //
301286 // This field is only really pointing to something valid when the
302- // ActiveTaskStatus specifies that the task is suspended. It can be accessed
303- // asynchronous to the task during escalation which will therefore require the
304- // 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.
305290 //
306291 // When a task has TaskDependencyStatusRecord in the status record list, it
307292 // must be the innermost status record, barring the status record lock which
308293 // could be taken while this record is present.
309294 //
310295 // The type of thing we are waiting on, is specified in the enum below
311- union {
296+ union Dependent {
297+ constexpr Dependent () {}
298+
312299 // This task is suspended waiting on another task. This could be an async
313300 // let child task or it could be another unstructured task.
314301 AsyncTask *Task;
@@ -325,40 +312,68 @@ class TaskDependencyStatusRecord : public TaskStatusRecord {
325312 // the duration of the wait. We do not need to take an additional +1 on this
326313 // task group in this dependency record.
327314 TaskGroup *TaskGroup;
328- } 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;
329326
330327 // Enum specifying the type of dependency this task has
331328 enum DependencyKind {
332329 WaitingOnTask = 1 ,
333330 WaitingOnContinuation,
334331 WaitingOnTaskGroup,
332+
333+ EnqueuedOnExecutor,
335334 } DependencyKind;
336335
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+
337343public:
338- TaskDependencyStatusRecord (AsyncTask *task) :
344+ TaskDependencyStatusRecord (AsyncTask *waitingTask, AsyncTask * task) :
339345 TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
340- DependencyKind (WaitingOnTask) {
341- WaitingOn .Task = task;
346+ DependencyKind (WaitingOnTask), WaitingTask(waitingTask) {
347+ DependentOn .Task = task;
342348 }
343349
344- TaskDependencyStatusRecord (ContinuationAsyncContext *context) :
350+ TaskDependencyStatusRecord (AsyncTask *waitingTask, ContinuationAsyncContext *context) :
345351 TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
346- DependencyKind (WaitingOnContinuation) {
347- WaitingOn .Continuation = context;
352+ DependencyKind (WaitingOnContinuation), WaitingTask(waitingTask) {
353+ DependentOn .Continuation = context;
348354 }
349355
350- TaskDependencyStatusRecord (TaskGroup *taskGroup) :
356+ TaskDependencyStatusRecord (AsyncTask *waitingTask, TaskGroup *taskGroup) :
351357 TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
352- DependencyKind (WaitingOnTaskGroup) {
353- WaitingOn .TaskGroup = taskGroup;
358+ DependencyKind (WaitingOnTaskGroup), WaitingTask(waitingTask) {
359+ DependentOn .TaskGroup = taskGroup;
354360 }
355361
356- void destroy () { }
362+ TaskDependencyStatusRecord (AsyncTask *waitingTask, ExecutorRef executor) :
363+ TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
364+ DependencyKind (EnqueuedOnExecutor), WaitingTask(waitingTask) {
365+ DependentOn.Executor = executor;
366+ }
357367
358368 static bool classof (const TaskStatusRecord *record) {
359369 return record->getKind () == TaskStatusRecordKind::TaskDependency;
360370 }
361371
372+ void updateDependencyToEnqueuedOn (ExecutorRef executor) {
373+ DependencyKind = EnqueuedOnExecutor;
374+ DependentOn.Executor = executor;
375+ }
376+
362377 void performEscalationAction (JobPriority newPriority);
363378};
364379
0 commit comments