1717#ifndef SWIFT_ABI_TASK_BACKDEPLOY56_H
1818#define SWIFT_ABI_TASK_BACKDEPLOY56_H
1919
20+ #include " Concurrency/TaskLocal.h"
2021#include " Executor.h"
2122#include " swift/ABI/HeapObject.h"
2223#include " swift/ABI/Metadata.h"
2627#include " VoucherShims.h"
2728#include " swift/Basic/STLExtras.h"
2829#include < bitset>
29- #include < queue>
30+ #include < queue> // TODO: remove and replace with our own mpsc
3031
3132namespace swift {
3233class AsyncTask ;
@@ -275,13 +276,6 @@ class AsyncTask : public Job {
275276 void setTaskId ();
276277 uint64_t getTaskId ();
277278
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-
285279 // / Given that we've already fully established the job context
286280 // / in the current thread, start running this task. To establish
287281 // / the job context correctly, call swift_job_run or
@@ -313,34 +307,44 @@ class AsyncTask : public Job {
313307 // /
314308 // / Generally this should be done immediately after updating
315309 // / ActiveTask.
310+ __attribute__ ((visibility(" hidden" )))
316311 void flagAsRunning();
312+ __attribute__ ((visibility(" hidden" )))
317313 void flagAsRunning_slow();
318314
319- // / Flag that this task is now suspended.
315+ // / Flag that this task is now suspended. This can update the
316+ // / priority stored in the job flags if the priority hsa been
317+ // / escalated. Generally this should be done immediately after
318+ // / clearing ActiveTask and immediately before enqueuing the task
319+ // / somewhere. TODO: record where the task is enqueued if
320+ // / possible.
321+ __attribute__ ((visibility(" hidden" )))
320322 void flagAsSuspended();
323+ __attribute__ ((visibility(" hidden" )))
321324 void flagAsSuspended_slow();
322325
323- // / Flag that the task is to be enqueued on the provided executor and actually
324- // / enqueue it
325- void flagAsAndEnqueueOnExecutor (ExecutorRef newExecutor);
326-
327326 // / Flag that this task is now completed. This normally does not do anything
328327 // / but can be used to locally insert logging.
328+ __attribute__ ((visibility(" hidden" )))
329329 void flagAsCompleted();
330330
331331 // / Check whether this task has been cancelled.
332332 // / Checking this is, of course, inherently race-prone on its own.
333+ __attribute__ ((visibility(" hidden" )))
333334 bool isCancelled() const ;
334335
335336 // ==== Task Local Values ----------------------------------------------------
336337
338+ __attribute__ ((visibility(" hidden" )))
337339 void localValuePush(const HeapObject *key,
338340 /* +1 */ OpaqueValue *value,
339341 const Metadata *valueType);
340342
343+ __attribute__ ((visibility(" hidden" )))
341344 OpaqueValue *localValueGet(const HeapObject *key);
342345
343346 // / Returns true if storage has still more bindings.
347+ __attribute__ ((visibility(" hidden" )))
344348 bool localValuePop();
345349
346350 // ==== Child Fragment -------------------------------------------------------
@@ -566,8 +570,9 @@ class AsyncTask : public Job {
566570 // / \c Executing, then \c waitingTask has been added to the
567571 // / wait queue and will be scheduled when the future completes. Otherwise,
568572 // / the future has completed and can be queried.
569- // / The waiting task's async context will be initialized with the parameters if
573+ // / The waiting task's async context will be intialized with the parameters if
570574 // / the current's task state is executing.
575+ __attribute__ ((visibility(" hidden" )))
571576 FutureFragment::Status waitFuture(AsyncTask *waitingTask,
572577 AsyncContext *waitingTaskContext,
573578 TaskContinuationFunction *resumeFn,
@@ -614,6 +619,65 @@ inline void Job::runInFullyEstablishedContext() {
614619
615620// ==== ------------------------------------------------------------------------
616621
622+ // / The Swift5.6 AsyncContextKind for the AsyncContext.
623+ // / Note that these were removed in Swift5.7
624+ // / (aca744b21165a20655502b563a6fa54c2c83efdf).
625+ // / Kinds of async context.
626+ enum class AsyncContextKind {
627+ // / An ordinary asynchronous function.
628+ Ordinary = 0 ,
629+
630+ // / A context which can yield to its caller.
631+ Yielding = 1 ,
632+
633+ // / A continuation context.
634+ Continuation = 2 ,
635+
636+ // Other kinds are reserved for interesting special
637+ // intermediate contexts.
638+
639+ // Kinds >= 192 are private to the implementation.
640+ First_Reserved = 192
641+ };
642+
643+
644+ // / The Swift5.6 AsyncContextFlags for the AsyncContext.
645+ // / Note that these were removed in Swift5.7
646+ // / (aca744b21165a20655502b563a6fa54c2c83efdf).
647+ // / Flags for async contexts.
648+ class AsyncContextFlags : public FlagSet <uint32_t > {
649+ public:
650+ enum {
651+ Kind = 0 ,
652+ Kind_width = 8 ,
653+
654+ CanThrow = 8 ,
655+
656+ // Kind-specific flags should grow down from 31.
657+
658+ Continuation_IsExecutorSwitchForced = 31 ,
659+ };
660+
661+ explicit AsyncContextFlags (uint32_t bits) : FlagSet(bits) {}
662+ constexpr AsyncContextFlags () {}
663+ AsyncContextFlags (AsyncContextKind kind) {
664+ setKind (kind);
665+ }
666+
667+ // / The kind of context this represents.
668+ FLAGSET_DEFINE_FIELD_ACCESSORS (Kind, Kind_width, AsyncContextKind,
669+ getKind, setKind)
670+
671+ // / Whether this context is permitted to throw.
672+ FLAGSET_DEFINE_FLAG_ACCESSORS (CanThrow, canThrow, setCanThrow)
673+
674+ // / See AsyncContinuationFlags::isExecutorSwitchForced.
675+ FLAGSET_DEFINE_FLAG_ACCESSORS (Continuation_IsExecutorSwitchForced,
676+ continuation_isExecutorSwitchForced,
677+ continuation_setIsExecutorSwitchForced)
678+ };
679+
680+
617681// / An asynchronous context within a task. Generally contexts are
618682// / allocated using the task-local stack alloc/dealloc operations, but
619683// / there's no guarantee of that, and the ABI is designed to permit
@@ -634,9 +698,19 @@ class alignas(MaximumAlignment) AsyncContext {
634698 TaskContinuationFunction * __ptrauth_swift_async_context_resume
635699 ResumeParent;
636700
637- AsyncContext (TaskContinuationFunction *resumeParent,
701+ // / Flags describing this context.
702+ // /
703+ // / Note that this field is only 32 bits; any alignment padding
704+ // / following this on 64-bit platforms can be freely used by the
705+ // / function. If the function is a yielding function, that padding
706+ // / is of course interrupted by the YieldToParent field.
707+ AsyncContextFlags Flags;
708+
709+ AsyncContext (AsyncContextFlags flags,
710+ TaskContinuationFunction *resumeParent,
638711 AsyncContext *parent)
639- : Parent (parent), ResumeParent (resumeParent) {}
712+ : Parent (parent), ResumeParent (resumeParent),
713+ Flags (flags) {}
640714
641715 AsyncContext (const AsyncContext &) = delete ;
642716 AsyncContext &operator =(const AsyncContext &) = delete ;
@@ -660,66 +734,48 @@ class YieldingAsyncContext : public AsyncContext {
660734 TaskContinuationFunction * __ptrauth_swift_async_context_yield
661735 YieldToParent;
662736
663- YieldingAsyncContext (TaskContinuationFunction *resumeParent,
737+ YieldingAsyncContext (AsyncContextFlags flags,
738+ TaskContinuationFunction *resumeParent,
664739 TaskContinuationFunction *yieldToParent,
665740 AsyncContext *parent)
666- : AsyncContext(resumeParent, parent),
741+ : AsyncContext(flags, resumeParent, parent),
667742 YieldToParent (yieldToParent) {}
743+
744+ static bool classof (const AsyncContext *context) {
745+ return context->Flags .getKind () == AsyncContextKind::Yielding;
746+ }
668747};
669748
670749// / An async context that can be resumed as a continuation.
671750class ContinuationAsyncContext : public AsyncContext {
672751public:
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-
697752 // / An atomic object used to ensure that a continuation is not
698753 // / scheduled immediately during a resume if it hasn't yet been
699- // / awaited by the function which set it up. Not public ABI.
754+ // / awaited by the function which set it up.
700755 std::atomic<ContinuationStatus> AwaitSynchronization;
701756
702757 // / The error result value of the continuation.
703758 // / This should be null-initialized when setting up the continuation.
704759 // / Throwing resumers must overwrite this with a non-null value.
705- // / Public ABI.
706760 SwiftError *ErrorResult;
707761
708762 // / A pointer to the normal result value of the continuation.
709763 // / Normal resumers must initialize this before resuming.
710- // / Public ABI.
711764 OpaqueValue *NormalResult;
712765
713766 // / The executor that should be resumed to.
714- // / Public ABI.
715767 ExecutorRef ResumeToExecutor;
716768
717769 void setErrorResult (SwiftError *error) {
718770 ErrorResult = error;
719771 }
720772
721773 bool isExecutorSwitchForced () const {
722- return Flags.isExecutorSwitchForced ();
774+ return Flags.continuation_isExecutorSwitchForced ();
775+ }
776+
777+ static bool classof (const AsyncContext *context) {
778+ return context->Flags .getKind () == AsyncContextKind::Continuation;
723779 }
724780};
725781
0 commit comments