27
27
28
28
#include " swift/ABI/Enum.h"
29
29
#include " swift/ABI/ObjectFile.h"
30
+ #include " swift/Concurrency/Actor.h"
30
31
#include " swift/Remote/MemoryReader.h"
31
32
#include " swift/Remote/MetadataReader.h"
32
33
#include " swift/Reflection/Records.h"
58
59
// with escalation | present | full
59
60
// with escalation | not present | DEGRADED
60
61
//
61
- // Currently, degraded info means that IsRunning is not available (indicated
62
- // with `HasIsRunning = false`) and async backtraces are not provided.
62
+ // Currently, degraded info has these effects:
63
+ // 1. Task.IsRunning is not available, indicated with Task.HasIsRunning = false.
64
+ // 2. Task async backtraces are not provided.
65
+ // 3. Task and actor thread ports are not available, indicated with
66
+ // HasThreadPort = false.
63
67
64
68
#if __has_include(<dispatch/swift_concurrency_private.h>)
65
69
#include < dispatch/swift_concurrency_private.h>
@@ -185,6 +189,9 @@ class ReflectionContext
185
189
bool IsRunning;
186
190
bool IsEnqueued;
187
191
192
+ bool HasThreadPort;
193
+ uint32_t ThreadPort;
194
+
188
195
uint64_t Id;
189
196
StoredPointer RunJob;
190
197
StoredPointer AllocatorSlabPtr;
@@ -193,8 +200,15 @@ class ReflectionContext
193
200
};
194
201
195
202
struct ActorInfo {
196
- StoredSize Flags;
197
203
StoredPointer FirstJob;
204
+
205
+ uint8_t State;
206
+ bool IsDistributedRemote;
207
+ bool IsPriorityEscalated;
208
+ uint8_t MaxPriority;
209
+
210
+ bool HasThreadPort;
211
+ uint32_t ThreadPort;
198
212
};
199
213
200
214
explicit ReflectionContext (std::shared_ptr<MemoryReader> reader)
@@ -1532,6 +1546,44 @@ class ReflectionContext
1532
1546
Task->PrivateStorage .Status .Flags [0 ] & ActiveTaskStatusFlags::IsRunning;
1533
1547
}
1534
1548
1549
+ std::pair<bool , uint32_t > getThreadPort (
1550
+ const AsyncTask<Runtime, ActiveTaskStatusWithEscalation<Runtime>> *Task) {
1551
+ #if HAS_DISPATCH_LOCK_IS_LOCKED
1552
+ return {true ,
1553
+ dispatch_lock_owner (Task->PrivateStorage .Status .ExecutionLock [0 ])};
1554
+ #else
1555
+ // The target runtime was built with priority escalation but we don't have
1556
+ // the swift_concurrency_private.h header needed to decode the lock.
1557
+ return {false , 0 };
1558
+ #endif
1559
+ }
1560
+
1561
+ std::pair<bool , uint32_t > getThreadPort (
1562
+ const AsyncTask<Runtime, ActiveTaskStatusWithoutEscalation<Runtime>>
1563
+ *Task) {
1564
+ // Tasks without escalation have no thread port to query.
1565
+ return {false , 0 };
1566
+ }
1567
+
1568
+ std::pair<bool , uint32_t > getThreadPort (
1569
+ const DefaultActorImpl<Runtime, ActiveActorStatusWithEscalation<Runtime>>
1570
+ *Actor) {
1571
+ #if HAS_DISPATCH_LOCK_IS_LOCKED
1572
+ return {true , dispatch_lock_owner (Actor->Status .DrainLock [0 ])};
1573
+ #else
1574
+ // The target runtime was built with priority escalation but we don't have
1575
+ // the swift_concurrency_private.h header needed to decode the lock.
1576
+ return {false , 0 };
1577
+ #endif
1578
+ }
1579
+
1580
+ std::pair<bool , uint32_t >
1581
+ getThreadPort (const DefaultActorImpl<
1582
+ Runtime, ActiveActorStatusWithoutEscalation<Runtime>> *Actor) {
1583
+ // Actors without escalation have no thread port to query.
1584
+ return {false , 0 };
1585
+ }
1586
+
1535
1587
template <typename AsyncTaskType>
1536
1588
std::pair<llvm::Optional<std::string>, AsyncTaskInfo>
1537
1589
asyncTaskInfo (StoredPointer AsyncTaskPtr) {
@@ -1557,6 +1609,8 @@ class ReflectionContext
1557
1609
Info.IsEnqueued = TaskStatusFlags & ActiveTaskStatusFlags::IsEnqueued;
1558
1610
1559
1611
setIsRunning (Info, AsyncTaskObj.get ());
1612
+ std::tie (Info.HasThreadPort , Info.ThreadPort ) =
1613
+ getThreadPort (AsyncTaskObj.get ());
1560
1614
1561
1615
Info.Id =
1562
1616
AsyncTaskObj->Id | ((uint64_t )AsyncTaskObj->PrivateStorage .Id << 32 );
@@ -1626,15 +1680,26 @@ class ReflectionContext
1626
1680
return {std::string (" failure reading actor" ), {}};
1627
1681
1628
1682
ActorInfo Info{};
1629
- Info.Flags = ActorObj->Status .Flags [0 ];
1630
1683
1631
- // Status is the low 3 bits of Flags. Status of 0 is Idle. Don't read
1632
- // FirstJob when idle.
1633
- auto Status = Info.Flags & 0x7 ;
1634
- if (Status != 0 ) {
1684
+ uint32_t Flags = ActorObj->Status .Flags [0 ];
1685
+ Info.State = Flags & concurrency::ActorFlagConstants::ActorStateMask;
1686
+ Info.IsDistributedRemote =
1687
+ Flags & concurrency::ActorFlagConstants::DistributedRemote;
1688
+ Info.IsPriorityEscalated =
1689
+ Flags & concurrency::ActorFlagConstants::IsPriorityEscalated;
1690
+ Info.MaxPriority =
1691
+ (Flags & concurrency::ActorFlagConstants::PriorityMask) >>
1692
+ concurrency::ActorFlagConstants::PriorityShift;
1693
+
1694
+ // Don't read FirstJob when idle.
1695
+ if (Info.State != concurrency::ActorFlagConstants::Idle) {
1635
1696
// This is a JobRef which stores flags in the low bits.
1636
1697
Info.FirstJob = ActorObj->Status .FirstJob & ~StoredPointer (0x3 );
1637
1698
}
1699
+
1700
+ std::tie (Info.HasThreadPort , Info.ThreadPort ) =
1701
+ getThreadPort (ActorObj.get ());
1702
+
1638
1703
return {llvm::None, Info};
1639
1704
}
1640
1705
0 commit comments