Skip to content

Commit 7ad89fe

Browse files
committed
Replace Task.h with right (5.6) version
I seem to have copied over the wrong version of Task.h. There is an ABI mismatch in the size of AsyncContext due to the removal of Flags. This resulted in programs crashing when running against the backdeploy library and should have crashed when running on the swift 5.6 runtime. The successResultPointer pointer was set in AsyncTask::waitFuture, but with the wrong layout. When the pointer was read in the concurrency backdeploy library, it was at a different offset, and thus contained a nullptr. I pulled the AsyncContextKind and AsyncContextFlags from the old MetadataValues.h into Task.h as they were removed in commit aca744b, but are necessary with the flags included.
1 parent 188c7bd commit 7ad89fe

File tree

1 file changed

+93
-47
lines changed
  • stdlib/toolchain/Compatibility56/include/Concurrency

1 file changed

+93
-47
lines changed

stdlib/toolchain/Compatibility56/include/Concurrency/Task.h

Lines changed: 93 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
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"
@@ -26,7 +27,7 @@
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

3132
namespace swift {
3233
class 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
@@ -316,14 +310,15 @@ class AsyncTask : public Job {
316310
void flagAsRunning();
317311
void flagAsRunning_slow();
318312

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.
320319
void flagAsSuspended();
321320
void flagAsSuspended_slow();
322321

323-
/// Flag that the task is to be enqueued on the provided executor and actually
324-
/// enqueue it
325-
void flagAsAndEnqueueOnExecutor(ExecutorRef newExecutor);
326-
327322
/// Flag that this task is now completed. This normally does not do anything
328323
/// but can be used to locally insert logging.
329324
void flagAsCompleted();
@@ -566,7 +561,7 @@ class AsyncTask : public Job {
566561
/// \c Executing, then \c waitingTask has been added to the
567562
/// wait queue and will be scheduled when the future completes. Otherwise,
568563
/// 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
570565
/// the current's task state is executing.
571566
FutureFragment::Status waitFuture(AsyncTask *waitingTask,
572567
AsyncContext *waitingTaskContext,
@@ -614,6 +609,65 @@ inline void Job::runInFullyEstablishedContext() {
614609

615610
// ==== ------------------------------------------------------------------------
616611

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+
617671
/// An asynchronous context within a task. Generally contexts are
618672
/// allocated using the task-local stack alloc/dealloc operations, but
619673
/// there's no guarantee of that, and the ABI is designed to permit
@@ -634,9 +688,19 @@ class alignas(MaximumAlignment) AsyncContext {
634688
TaskContinuationFunction * __ptrauth_swift_async_context_resume
635689
ResumeParent;
636690

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,
638701
AsyncContext *parent)
639-
: Parent(parent), ResumeParent(resumeParent) {}
702+
: Parent(parent), ResumeParent(resumeParent),
703+
Flags(flags) {}
640704

641705
AsyncContext(const AsyncContext &) = delete;
642706
AsyncContext &operator=(const AsyncContext &) = delete;
@@ -660,66 +724,48 @@ class YieldingAsyncContext : public AsyncContext {
660724
TaskContinuationFunction * __ptrauth_swift_async_context_yield
661725
YieldToParent;
662726

663-
YieldingAsyncContext(TaskContinuationFunction *resumeParent,
727+
YieldingAsyncContext(AsyncContextFlags flags,
728+
TaskContinuationFunction *resumeParent,
664729
TaskContinuationFunction *yieldToParent,
665730
AsyncContext *parent)
666-
: AsyncContext(resumeParent, parent),
731+
: AsyncContext(flags, resumeParent, parent),
667732
YieldToParent(yieldToParent) {}
733+
734+
static bool classof(const AsyncContext *context) {
735+
return context->Flags.getKind() == AsyncContextKind::Yielding;
736+
}
668737
};
669738

670739
/// An async context that can be resumed as a continuation.
671740
class ContinuationAsyncContext : public AsyncContext {
672741
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-
697742
/// An atomic object used to ensure that a continuation is not
698743
/// 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.
700745
std::atomic<ContinuationStatus> AwaitSynchronization;
701746

702747
/// The error result value of the continuation.
703748
/// This should be null-initialized when setting up the continuation.
704749
/// Throwing resumers must overwrite this with a non-null value.
705-
/// Public ABI.
706750
SwiftError *ErrorResult;
707751

708752
/// A pointer to the normal result value of the continuation.
709753
/// Normal resumers must initialize this before resuming.
710-
/// Public ABI.
711754
OpaqueValue *NormalResult;
712755

713756
/// The executor that should be resumed to.
714-
/// Public ABI.
715757
ExecutorRef ResumeToExecutor;
716758

717759
void setErrorResult(SwiftError *error) {
718760
ErrorResult = error;
719761
}
720762

721763
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;
723769
}
724770
};
725771

0 commit comments

Comments
 (0)