Skip to content

Commit babaa4b

Browse files
authored
Merge pull request swiftlang#63019 from apple/rokhinip/88093007-priority-escalation-to-future
Provide support for live priority escalation in the task runtime
2 parents 5bfc7e6 + e052cce commit babaa4b

File tree

16 files changed

+842
-467
lines changed

16 files changed

+842
-467
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ enum class MetadataKind : uint32_t {
9292
#define ABSTRACTMETADATAKIND(name, start, end) \
9393
name##_Start = start, name##_End = end,
9494
#include "MetadataKind.def"
95-
95+
9696
/// The largest possible non-isa-pointer metadata kind value.
9797
///
9898
/// This is included in the enumeration to prevent against attempts to
@@ -473,7 +473,7 @@ class ProtocolDescriptorFlags {
473473
};
474474

475475
int_type Data;
476-
476+
477477
constexpr ProtocolDescriptorFlags(int_type Data) : Data(Data) {}
478478
public:
479479
constexpr ProtocolDescriptorFlags() : Data(0) {}
@@ -498,32 +498,32 @@ class ProtocolDescriptorFlags {
498498
constexpr ProtocolDescriptorFlags withResilient(bool s) const {
499499
return ProtocolDescriptorFlags((Data & ~IsResilient) | (s ? IsResilient : 0));
500500
}
501-
501+
502502
/// Was the protocol defined in Swift 1 or 2?
503503
bool isSwift() const { return Data & IsSwift; }
504504

505505
/// Is the protocol class-constrained?
506506
ProtocolClassConstraint getClassConstraint() const {
507507
return ProtocolClassConstraint(bool(Data & ClassConstraint));
508508
}
509-
509+
510510
/// What dispatch strategy does this protocol use?
511511
ProtocolDispatchStrategy getDispatchStrategy() const {
512512
return ProtocolDispatchStrategy((Data & DispatchStrategyMask)
513513
>> DispatchStrategyShift);
514514
}
515-
515+
516516
/// Does the protocol require a witness table for method dispatch?
517517
bool needsWitnessTable() const {
518518
return swift::protocolRequiresWitnessTable(getDispatchStrategy());
519519
}
520-
520+
521521
/// Return the identifier if this is a special runtime-known protocol.
522522
SpecialProtocol getSpecialProtocol() const {
523523
return SpecialProtocol(uint8_t((Data & SpecialProtocolMask)
524524
>> SpecialProtocolShift));
525525
}
526-
526+
527527
/// Can new requirements with default witnesses be added resiliently?
528528
bool isResilient() const { return Data & IsResilient; }
529529

@@ -784,11 +784,11 @@ class ExistentialTypeFlags {
784784
return ExistentialTypeFlags((Data & ~SpecialProtocolMask)
785785
| (int_type(sp) << SpecialProtocolShift));
786786
}
787-
787+
788788
unsigned getNumWitnessTables() const {
789789
return Data & NumWitnessTablesMask;
790790
}
791-
791+
792792
ProtocolClassConstraint getClassConstraint() const {
793793
return ProtocolClassConstraint(bool(Data & ClassConstraintMask));
794794
}
@@ -803,7 +803,7 @@ class ExistentialTypeFlags {
803803
return SpecialProtocol(uint8_t((Data & SpecialProtocolMask)
804804
>> SpecialProtocolShift));
805805
}
806-
806+
807807
int_type getIntValue() const {
808808
return Data;
809809
}
@@ -998,7 +998,7 @@ class TargetFunctionTypeFlags {
998998
// NOTE: The next bit will need to introduce a separate flags word.
999999
};
10001000
int_type Data;
1001-
1001+
10021002
constexpr TargetFunctionTypeFlags(int_type Data) : Data(Data) {}
10031003
public:
10041004
constexpr TargetFunctionTypeFlags() : Data(0) {}
@@ -1007,7 +1007,7 @@ class TargetFunctionTypeFlags {
10071007
withNumParameters(unsigned numParams) const {
10081008
return TargetFunctionTypeFlags((Data & ~NumParametersMask) | numParams);
10091009
}
1010-
1010+
10111011
constexpr TargetFunctionTypeFlags<int_type>
10121012
withConvention(FunctionMetadataConvention c) const {
10131013
return TargetFunctionTypeFlags((Data & ~ConventionMask)
@@ -1088,11 +1088,11 @@ class TargetFunctionTypeFlags {
10881088
int_type getIntValue() const {
10891089
return Data;
10901090
}
1091-
1091+
10921092
static TargetFunctionTypeFlags<int_type> fromIntValue(int_type Data) {
10931093
return TargetFunctionTypeFlags(Data);
10941094
}
1095-
1095+
10961096
bool operator==(TargetFunctionTypeFlags<int_type> other) const {
10971097
return Data == other.Data;
10981098
}
@@ -1458,32 +1458,32 @@ constexpr unsigned WitnessTableFirstRequirementOffset = 1;
14581458
enum class ContextDescriptorKind : uint8_t {
14591459
/// This context descriptor represents a module.
14601460
Module = 0,
1461-
1461+
14621462
/// This context descriptor represents an extension.
14631463
Extension = 1,
1464-
1464+
14651465
/// This context descriptor represents an anonymous possibly-generic context
14661466
/// such as a function body.
14671467
Anonymous = 2,
14681468

14691469
/// This context descriptor represents a protocol context.
14701470
Protocol = 3,
1471-
1471+
14721472
/// This context descriptor represents an opaque type alias.
14731473
OpaqueType = 4,
14741474

14751475
/// First kind that represents a type of any sort.
14761476
Type_First = 16,
1477-
1477+
14781478
/// This context descriptor represents a class.
14791479
Class = Type_First,
1480-
1480+
14811481
/// This context descriptor represents a struct.
14821482
Struct = Type_First + 1,
1483-
1483+
14841484
/// This context descriptor represents an enum.
14851485
Enum = Type_First + 2,
1486-
1486+
14871487
/// Last kind that represents a type of any sort.
14881488
Type_Last = 31,
14891489
};
@@ -1514,34 +1514,34 @@ struct ContextDescriptorFlags {
15141514
constexpr ContextDescriptorKind getKind() const {
15151515
return ContextDescriptorKind(Value & 0x1Fu);
15161516
}
1517-
1517+
15181518
/// Whether the context being described is generic.
15191519
constexpr bool isGeneric() const {
15201520
return (Value & 0x80u) != 0;
15211521
}
1522-
1522+
15231523
/// Whether this is a unique record describing the referenced context.
15241524
constexpr bool isUnique() const {
15251525
return (Value & 0x40u) != 0;
15261526
}
1527-
1527+
15281528
/// The format version of the descriptor. Higher version numbers may have
15291529
/// additional fields that aren't present in older versions.
15301530
constexpr uint8_t getVersion() const {
15311531
return (Value >> 8u) & 0xFFu;
15321532
}
1533-
1533+
15341534
/// The most significant two bytes of the flags word, which can have
15351535
/// kind-specific meaning.
15361536
constexpr uint16_t getKindSpecificFlags() const {
15371537
return (Value >> 16u) & 0xFFFFu;
15381538
}
1539-
1539+
15401540
constexpr ContextDescriptorFlags withKind(ContextDescriptorKind kind) const {
15411541
return assert((uint8_t(kind) & 0x1F) == uint8_t(kind)),
15421542
ContextDescriptorFlags((Value & 0xFFFFFFE0u) | uint8_t(kind));
15431543
}
1544-
1544+
15451545
constexpr ContextDescriptorFlags withGeneric(bool isGeneric) const {
15461546
return ContextDescriptorFlags((Value & 0xFFFFFF7Fu)
15471547
| (isGeneric ? 0x80u : 0));
@@ -1560,7 +1560,7 @@ struct ContextDescriptorFlags {
15601560
withKindSpecificFlags(uint16_t flags) const {
15611561
return ContextDescriptorFlags((Value & 0xFFFFu) | (flags << 16u));
15621562
}
1563-
1563+
15641564
constexpr uint32_t getIntValue() const {
15651565
return Value;
15661566
}
@@ -1591,7 +1591,7 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
15911591
/// Meaningful for all type-descriptor kinds.
15921592
HasImportInfo = 2,
15931593

1594-
/// Set if the type descriptor has a pointer to a list of canonical
1594+
/// Set if the type descriptor has a pointer to a list of canonical
15951595
/// prespecializations.
15961596
HasCanonicalMetadataPrespecializations = 3,
15971597

@@ -1780,13 +1780,13 @@ class AnonymousContextDescriptorFlags : public FlagSet<uint16_t> {
17801780
enum class GenericParamKind : uint8_t {
17811781
/// A type parameter.
17821782
Type = 0,
1783-
1783+
17841784
Max = 0x3F,
17851785
};
17861786

17871787
class GenericParamDescriptor {
17881788
uint8_t Value;
1789-
1789+
17901790
explicit constexpr GenericParamDescriptor(uint8_t Value)
17911791
: Value(Value) {}
17921792
public:
@@ -1798,7 +1798,7 @@ class GenericParamDescriptor {
17981798
.withKeyArgument(hasKeyArgument)
17991799
.withExtraArgument(hasExtraArgument))
18001800
{}
1801-
1801+
18021802
constexpr bool hasKeyArgument() const {
18031803
return (Value & 0x80u) != 0;
18041804
}
@@ -1810,24 +1810,24 @@ class GenericParamDescriptor {
18101810
constexpr GenericParamKind getKind() const {
18111811
return GenericParamKind(Value & 0x3Fu);
18121812
}
1813-
1813+
18141814
constexpr GenericParamDescriptor
18151815
withKeyArgument(bool hasKeyArgument) const {
18161816
return GenericParamDescriptor((Value & 0x7Fu)
18171817
| (hasKeyArgument ? 0x80u : 0));
18181818
}
1819-
1819+
18201820
constexpr GenericParamDescriptor
18211821
withExtraArgument(bool hasExtraArgument) const {
18221822
return GenericParamDescriptor((Value & 0xBFu)
18231823
| (hasExtraArgument ? 0x40u : 0));
18241824
}
1825-
1825+
18261826
constexpr GenericParamDescriptor withKind(GenericParamKind kind) const {
18271827
return assert((uint8_t(kind) & 0x3Fu) == uint8_t(kind)),
18281828
GenericParamDescriptor((Value & 0xC0u) | uint8_t(kind));
18291829
}
1830-
1830+
18311831
constexpr uint8_t getIntValue() const {
18321832
return Value;
18331833
}
@@ -1881,7 +1881,7 @@ enum class GenericRequirementKind : uint8_t {
18811881

18821882
class GenericRequirementFlags {
18831883
uint32_t Value;
1884-
1884+
18851885
explicit constexpr GenericRequirementFlags(uint32_t Value)
18861886
: Value(Value) {}
18871887
public:
@@ -1893,7 +1893,7 @@ class GenericRequirementFlags {
18931893
.withKeyArgument(hasKeyArgument)
18941894
.withExtraArgument(hasExtraArgument))
18951895
{}
1896-
1896+
18971897
constexpr bool hasKeyArgument() const {
18981898
return (Value & 0x80u) != 0;
18991899
}
@@ -1905,25 +1905,25 @@ class GenericRequirementFlags {
19051905
constexpr GenericRequirementKind getKind() const {
19061906
return GenericRequirementKind(Value & 0x1Fu);
19071907
}
1908-
1908+
19091909
constexpr GenericRequirementFlags
19101910
withKeyArgument(bool hasKeyArgument) const {
19111911
return GenericRequirementFlags((Value & 0x7Fu)
19121912
| (hasKeyArgument ? 0x80u : 0));
19131913
}
1914-
1914+
19151915
constexpr GenericRequirementFlags
19161916
withExtraArgument(bool hasExtraArgument) const {
19171917
return GenericRequirementFlags((Value & 0xBFu)
19181918
| (hasExtraArgument ? 0x40u : 0));
19191919
}
1920-
1920+
19211921
constexpr GenericRequirementFlags
19221922
withKind(GenericRequirementKind kind) const {
19231923
return assert((uint8_t(kind) & 0x1Fu) == uint8_t(kind)),
19241924
GenericRequirementFlags((Value & 0xE0u) | uint8_t(kind));
19251925
}
1926-
1926+
19271927
constexpr uint32_t getIntValue() const {
19281928
return Value;
19291929
}
@@ -2343,8 +2343,9 @@ class JobFlags : public FlagSet<uint32_t> {
23432343

23442344
/// Kinds of task status record.
23452345
enum class TaskStatusRecordKind : uint8_t {
2346-
/// A DeadlineStatusRecord, which represents an active deadline.
2347-
Deadline = 0,
2346+
/// A TaskDependencyStatusRecord which tracks what the current task is
2347+
/// dependent on.
2348+
TaskDependency = 0,
23482349

23492350
/// A ChildTaskStatusRecord, which represents the potential for
23502351
/// active child tasks.

include/swift/ABI/Task.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ class Job;
3737
struct OpaqueValue;
3838
struct SwiftError;
3939
class TaskStatusRecord;
40+
class TaskDependencyStatusRecord;
4041
class TaskOptionRecord;
4142
class TaskGroup;
43+
class ContinuationAsyncContext;
4244

4345
extern FullMetadata<DispatchClassMetadata> jobHeapMetadata;
4446

@@ -316,16 +318,25 @@ class AsyncTask : public Job {
316318
/// ActiveTask.
317319
void flagAsRunning();
318320

319-
/// Flag that this task is now suspended.
320-
void flagAsSuspended();
321+
/// Flag that this task is now suspended with information about what it is
322+
/// waiting on.
323+
void flagAsSuspendedOnTask(AsyncTask *task);
324+
void flagAsSuspendedOnContinuation(ContinuationAsyncContext *context);
325+
void flagAsSuspendedOnTaskGroup(TaskGroup *taskGroup);
321326

327+
private:
328+
// Helper function
329+
void flagAsSuspended(TaskDependencyStatusRecord *dependencyStatusRecord);
330+
void destroyTaskDependency(TaskDependencyStatusRecord *dependencyRecord);
331+
332+
public:
322333
/// Flag that the task is to be enqueued on the provided executor and actually
323334
/// enqueue it
324335
void flagAsAndEnqueueOnExecutor(ExecutorRef newExecutor);
325336

326337
/// Flag that this task is now completed. This normally does not do anything
327338
/// but can be used to locally insert logging.
328-
void flagAsCompleted();
339+
void flagAsDestroyed();
329340

330341
/// Check whether this task has been cancelled.
331342
/// Checking this is, of course, inherently race-prone on its own.

0 commit comments

Comments
 (0)