22
22
23
23
#include " swift/ABI/MetadataValues.h"
24
24
#include " swift/ABI/Task.h"
25
+ #include " swift/ABI/Executor.h"
25
26
#include " swift/Runtime/HeapObject.h"
26
27
27
28
namespace swift {
@@ -278,22 +279,23 @@ class EscalationNotificationStatusRecord : public TaskStatusRecord {
278
279
// This record is allocated for a task to record what it is dependent on before
279
280
// the task can make progress again.
280
281
class 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.
285
285
//
286
286
// 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.
290
290
//
291
291
// When a task has TaskDependencyStatusRecord in the status record list, it
292
292
// must be the innermost status record, barring the status record lock which
293
293
// could be taken while this record is present.
294
294
//
295
295
// The type of thing we are waiting on, is specified in the enum below
296
- union {
296
+ union Dependent {
297
+ constexpr Dependent () {}
298
+
297
299
// This task is suspended waiting on another task. This could be an async
298
300
// let child task or it could be another unstructured task.
299
301
AsyncTask *Task;
@@ -310,35 +312,58 @@ class TaskDependencyStatusRecord : public TaskStatusRecord {
310
312
// the duration of the wait. We do not need to take an additional +1 on this
311
313
// task group in this dependency record.
312
314
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;
314
326
315
327
// Enum specifying the type of dependency this task has
316
328
enum DependencyKind {
317
329
WaitingOnTask = 1 ,
318
330
WaitingOnContinuation,
319
331
WaitingOnTaskGroup,
332
+
333
+ EnqueuedOnExecutor,
320
334
} DependencyKind;
321
335
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
+
322
343
public:
323
- TaskDependencyStatusRecord (AsyncTask *task) :
344
+ TaskDependencyStatusRecord (AsyncTask *waitingTask, AsyncTask * task) :
324
345
TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
325
- DependencyKind (WaitingOnTask) {
326
- WaitingOn .Task = task;
346
+ DependencyKind (WaitingOnTask), WaitingTask(waitingTask) {
347
+ DependentOn .Task = task;
327
348
}
328
349
329
- TaskDependencyStatusRecord (ContinuationAsyncContext *context) :
350
+ TaskDependencyStatusRecord (AsyncTask *waitingTask, ContinuationAsyncContext *context) :
330
351
TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
331
- DependencyKind (WaitingOnContinuation) {
332
- WaitingOn .Continuation = context;
352
+ DependencyKind (WaitingOnContinuation), WaitingTask(waitingTask) {
353
+ DependentOn .Continuation = context;
333
354
}
334
355
335
- TaskDependencyStatusRecord (TaskGroup *taskGroup) :
356
+ TaskDependencyStatusRecord (AsyncTask *waitingTask, TaskGroup *taskGroup) :
336
357
TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
337
- DependencyKind (WaitingOnTaskGroup) {
338
- WaitingOn .TaskGroup = taskGroup;
358
+ DependencyKind (WaitingOnTaskGroup), WaitingTask(waitingTask) {
359
+ DependentOn .TaskGroup = taskGroup;
339
360
}
340
361
341
- void destroy () { }
362
+ TaskDependencyStatusRecord (AsyncTask *waitingTask, ExecutorRef executor) :
363
+ TaskStatusRecord (TaskStatusRecordKind::TaskDependency),
364
+ DependencyKind (EnqueuedOnExecutor), WaitingTask(waitingTask) {
365
+ DependentOn.Executor = executor;
366
+ }
342
367
343
368
static bool classof (const TaskStatusRecord *record) {
344
369
return record->getKind () == TaskStatusRecordKind::TaskDependency;
0 commit comments