17
17
#ifndef SWIFT_ABI_TASK_BACKDEPLOY56_H
18
18
#define SWIFT_ABI_TASK_BACKDEPLOY56_H
19
19
20
+ #include " Concurrency/TaskLocal.h"
20
21
#include " Executor.h"
21
22
#include " swift/ABI/HeapObject.h"
22
23
#include " swift/ABI/Metadata.h"
26
27
#include " VoucherShims.h"
27
28
#include " swift/Basic/STLExtras.h"
28
29
#include < bitset>
29
- #include < queue>
30
+ #include < queue> // TODO: remove and replace with our own mpsc
30
31
31
32
namespace swift {
32
33
class AsyncTask ;
@@ -275,13 +276,6 @@ class AsyncTask : public Job {
275
276
void setTaskId ();
276
277
uint64_t getTaskId ();
277
278
278
- // / Get the task's resume function, for logging purposes only. This will
279
- // / attempt to see through the various adapters that are sometimes used, and
280
- // / failing that will return ResumeTask. The returned function pointer may
281
- // / have a different signature than ResumeTask, and it's only for identifying
282
- // / code associated with the task.
283
- const void *getResumeFunctionForLogging ();
284
-
285
279
// / Given that we've already fully established the job context
286
280
// / in the current thread, start running this task. To establish
287
281
// / the job context correctly, call swift_job_run or
@@ -316,14 +310,15 @@ class AsyncTask : public Job {
316
310
void flagAsRunning ();
317
311
void flagAsRunning_slow ();
318
312
319
- // / Flag that this task is now suspended.
313
+ // / Flag that this task is now suspended. This can update the
314
+ // / priority stored in the job flags if the priority hsa been
315
+ // / escalated. Generally this should be done immediately after
316
+ // / clearing ActiveTask and immediately before enqueuing the task
317
+ // / somewhere. TODO: record where the task is enqueued if
318
+ // / possible.
320
319
void flagAsSuspended ();
321
320
void flagAsSuspended_slow ();
322
321
323
- // / Flag that the task is to be enqueued on the provided executor and actually
324
- // / enqueue it
325
- void flagAsAndEnqueueOnExecutor (ExecutorRef newExecutor);
326
-
327
322
// / Flag that this task is now completed. This normally does not do anything
328
323
// / but can be used to locally insert logging.
329
324
void flagAsCompleted ();
@@ -566,7 +561,7 @@ class AsyncTask : public Job {
566
561
// / \c Executing, then \c waitingTask has been added to the
567
562
// / wait queue and will be scheduled when the future completes. Otherwise,
568
563
// / the future has completed and can be queried.
569
- // / The waiting task's async context will be initialized with the parameters if
564
+ // / The waiting task's async context will be intialized with the parameters if
570
565
// / the current's task state is executing.
571
566
FutureFragment::Status waitFuture (AsyncTask *waitingTask,
572
567
AsyncContext *waitingTaskContext,
@@ -614,6 +609,65 @@ inline void Job::runInFullyEstablishedContext() {
614
609
615
610
// ==== ------------------------------------------------------------------------
616
611
612
+ // / The Swift5.6 AsyncContextKind for the AsyncContext.
613
+ // / Note that these were removed in Swift5.7
614
+ // / (aca744b21165a20655502b563a6fa54c2c83efdf).
615
+ // / Kinds of async context.
616
+ enum class AsyncContextKind {
617
+ // / An ordinary asynchronous function.
618
+ Ordinary = 0 ,
619
+
620
+ // / A context which can yield to its caller.
621
+ Yielding = 1 ,
622
+
623
+ // / A continuation context.
624
+ Continuation = 2 ,
625
+
626
+ // Other kinds are reserved for interesting special
627
+ // intermediate contexts.
628
+
629
+ // Kinds >= 192 are private to the implementation.
630
+ First_Reserved = 192
631
+ };
632
+
633
+
634
+ // / The Swift5.6 AsyncContextFlags for the AsyncContext.
635
+ // / Note that these were removed in Swift5.7
636
+ // / (aca744b21165a20655502b563a6fa54c2c83efdf).
637
+ // / Flags for async contexts.
638
+ class AsyncContextFlags : public FlagSet <uint32_t > {
639
+ public:
640
+ enum {
641
+ Kind = 0 ,
642
+ Kind_width = 8 ,
643
+
644
+ CanThrow = 8 ,
645
+
646
+ // Kind-specific flags should grow down from 31.
647
+
648
+ Continuation_IsExecutorSwitchForced = 31 ,
649
+ };
650
+
651
+ explicit AsyncContextFlags (uint32_t bits) : FlagSet(bits) {}
652
+ constexpr AsyncContextFlags () {}
653
+ AsyncContextFlags (AsyncContextKind kind) {
654
+ setKind (kind);
655
+ }
656
+
657
+ // / The kind of context this represents.
658
+ FLAGSET_DEFINE_FIELD_ACCESSORS (Kind, Kind_width, AsyncContextKind,
659
+ getKind, setKind)
660
+
661
+ // / Whether this context is permitted to throw.
662
+ FLAGSET_DEFINE_FLAG_ACCESSORS (CanThrow, canThrow, setCanThrow)
663
+
664
+ // / See AsyncContinuationFlags::isExecutorSwitchForced.
665
+ FLAGSET_DEFINE_FLAG_ACCESSORS (Continuation_IsExecutorSwitchForced,
666
+ continuation_isExecutorSwitchForced,
667
+ continuation_setIsExecutorSwitchForced)
668
+ };
669
+
670
+
617
671
// / An asynchronous context within a task. Generally contexts are
618
672
// / allocated using the task-local stack alloc/dealloc operations, but
619
673
// / there's no guarantee of that, and the ABI is designed to permit
@@ -634,9 +688,19 @@ class alignas(MaximumAlignment) AsyncContext {
634
688
TaskContinuationFunction * __ptrauth_swift_async_context_resume
635
689
ResumeParent;
636
690
637
- AsyncContext (TaskContinuationFunction *resumeParent,
691
+ // / Flags describing this context.
692
+ // /
693
+ // / Note that this field is only 32 bits; any alignment padding
694
+ // / following this on 64-bit platforms can be freely used by the
695
+ // / function. If the function is a yielding function, that padding
696
+ // / is of course interrupted by the YieldToParent field.
697
+ AsyncContextFlags Flags;
698
+
699
+ AsyncContext (AsyncContextFlags flags,
700
+ TaskContinuationFunction *resumeParent,
638
701
AsyncContext *parent)
639
- : Parent (parent), ResumeParent (resumeParent) {}
702
+ : Parent (parent), ResumeParent (resumeParent),
703
+ Flags (flags) {}
640
704
641
705
AsyncContext (const AsyncContext &) = delete ;
642
706
AsyncContext &operator =(const AsyncContext &) = delete ;
@@ -660,66 +724,48 @@ class YieldingAsyncContext : public AsyncContext {
660
724
TaskContinuationFunction * __ptrauth_swift_async_context_yield
661
725
YieldToParent;
662
726
663
- YieldingAsyncContext (TaskContinuationFunction *resumeParent,
727
+ YieldingAsyncContext (AsyncContextFlags flags,
728
+ TaskContinuationFunction *resumeParent,
664
729
TaskContinuationFunction *yieldToParent,
665
730
AsyncContext *parent)
666
- : AsyncContext(resumeParent, parent),
731
+ : AsyncContext(flags, resumeParent, parent),
667
732
YieldToParent (yieldToParent) {}
733
+
734
+ static bool classof (const AsyncContext *context) {
735
+ return context->Flags .getKind () == AsyncContextKind::Yielding;
736
+ }
668
737
};
669
738
670
739
// / An async context that can be resumed as a continuation.
671
740
class ContinuationAsyncContext : public AsyncContext {
672
741
public:
673
- class FlagsType : public FlagSet <size_t > {
674
- public:
675
- enum {
676
- CanThrow = 0 ,
677
- IsExecutorSwitchForced = 1 ,
678
- };
679
-
680
- explicit FlagsType (size_t bits) : FlagSet(bits) {}
681
- constexpr FlagsType () {}
682
-
683
- // / Whether this is a throwing continuation.
684
- FLAGSET_DEFINE_FLAG_ACCESSORS (CanThrow,
685
- canThrow,
686
- setCanThrow)
687
-
688
- // / See AsyncContinuationFlags::isExecutorSwitchForced().
689
- FLAGSET_DEFINE_FLAG_ACCESSORS (IsExecutorSwitchForced,
690
- isExecutorSwitchForced,
691
- setIsExecutorSwitchForced)
692
- };
693
-
694
- // / Flags for the continuation. Not public ABI.
695
- FlagsType Flags;
696
-
697
742
// / An atomic object used to ensure that a continuation is not
698
743
// / scheduled immediately during a resume if it hasn't yet been
699
- // / awaited by the function which set it up. Not public ABI.
744
+ // / awaited by the function which set it up.
700
745
std::atomic<ContinuationStatus> AwaitSynchronization;
701
746
702
747
// / The error result value of the continuation.
703
748
// / This should be null-initialized when setting up the continuation.
704
749
// / Throwing resumers must overwrite this with a non-null value.
705
- // / Public ABI.
706
750
SwiftError *ErrorResult;
707
751
708
752
// / A pointer to the normal result value of the continuation.
709
753
// / Normal resumers must initialize this before resuming.
710
- // / Public ABI.
711
754
OpaqueValue *NormalResult;
712
755
713
756
// / The executor that should be resumed to.
714
- // / Public ABI.
715
757
ExecutorRef ResumeToExecutor;
716
758
717
759
void setErrorResult (SwiftError *error) {
718
760
ErrorResult = error;
719
761
}
720
762
721
763
bool isExecutorSwitchForced () const {
722
- return Flags.isExecutorSwitchForced ();
764
+ return Flags.continuation_isExecutorSwitchForced ();
765
+ }
766
+
767
+ static bool classof (const AsyncContext *context) {
768
+ return context->Flags .getKind () == AsyncContextKind::Continuation;
723
769
}
724
770
};
725
771
0 commit comments