Skip to content

Commit 786d008

Browse files
committed
Implement GetThreadStoreData in cDAC
1 parent 1ee61b8 commit 786d008

File tree

10 files changed

+138
-110
lines changed

10 files changed

+138
-110
lines changed

docs/design/datacontracts/Thread.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22

33
This contract is for reading and iterating the threads of the process.
44

5-
## Data structures defined by contract
5+
## APIs of contract
6+
67
``` csharp
7-
record struct DacThreadStoreData (
8+
record struct ThreadStoreData (
89
int ThreadCount,
910
TargetPointer FirstThread,
1011
TargetPointer FinalizerThread,
1112
TargetPointer GcThread);
1213

13-
record struct DacThreadStoreCounts (
14+
record struct ThreadStoreCounts (
1415
int UnstartedThreadCount,
1516
int BackgroundThreadCount,
1617
int PendingThreadCount,
@@ -75,7 +76,7 @@ enum ThreadState
7576
TS_Detached = 0x80000000, // Thread was detached by DllMain
7677
}
7778

78-
record struct DacThreadData (
79+
record struct ThreadData (
7980
uint ThreadId;
8081
TargetNUint OsThreadId;
8182
ThreadState State;
@@ -90,11 +91,10 @@ record struct DacThreadData (
9091
);
9192
```
9293

93-
## Apis of contract
9494
``` csharp
95-
DacThreadStoreData GetThreadStoreData();
96-
DacThreadStoreCounts GetThreadCounts();
97-
DacThreadData GetThreadData(TargetPointer threadPointer);
95+
ThreadStoreData GetThreadStoreData();
96+
ThreadStoreCounts GetThreadCounts();
97+
ThreadData GetThreadData(TargetPointer threadPointer);
9898
TargetPointer GetNestedExceptionInfo(TargetPointer nestedExceptionPointer, out TargetPointer nextNestedException);
9999
TargetPointer GetManagedThreadObject(TargetPointer threadPointer);
100100
```
@@ -106,34 +106,34 @@ TargetPointer GetManagedThreadObject(TargetPointer threadPointer);
106106
``` csharp
107107
SListReader ThreadListReader = Contracts.SList.GetReader("Thread");
108108

109-
DacThreadStoreData GetThreadStoreData()
109+
ThreadStoreData GetThreadStoreData()
110110
{
111-
TargetPointer threadStore = Target.ReadGlobalTargetPointer("s_pThreadStore");
111+
TargetPointer threadStore = Target.ReadGlobalPointer("s_pThreadStore");
112112
var runtimeThreadStore = new ThreadStore(Target, threadStore);
113113

114114
TargetPointer firstThread = ThreadListReader.GetHead(runtimeThreadStore.SList.Pointer);
115115

116-
return new DacThreadStoreData(
116+
return new ThreadStoreData(
117117
ThreadCount : runtimeThreadStore.m_ThreadCount,
118118
FirstThread: firstThread,
119-
FinalizerThread: Target.ReadGlobalTargetPointer("g_pFinalizerThread"),
120-
GcThread: Target.ReadGlobalTargetPointer("g_pSuspensionThread"));
119+
FinalizerThread: Target.ReadGlobalPointer("g_pFinalizerThread"),
120+
GCThread: Target.ReadGlobalPointer("g_pSuspensionThread"));
121121
}
122122

123123
DacThreadStoreCounts GetThreadCounts()
124124
{
125-
TargetPointer threadStore = Target.ReadGlobalTargetPointer("s_pThreadStore");
125+
TargetPointer threadStore = Target.ReadGlobalPointer("s_pThreadStore");
126126
var runtimeThreadStore = new ThreadStore(Target, threadStore);
127127

128-
return new DacThreadStoreCounts(
128+
return new ThreadStoreCounts(
129129
ThreadCount : runtimeThreadStore.m_ThreadCount,
130130
UnstartedThreadCount : runtimeThreadStore.m_UnstartedThreadCount,
131131
BackgroundThreadCount : runtimeThreadStore.m_BackgroundThreadCount,
132132
PendingThreadCount : runtimeThreadStore.m_PendingThreadCount,
133133
DeadThreadCount: runtimeThreadStore.m_DeadThreadCount,
134134
}
135135

136-
DacThreadData GetThreadData(TargetPointer threadPointer)
136+
ThreadData GetThreadData(TargetPointer threadPointer)
137137
{
138138
var runtimeThread = new Thread(Target, threadPointer);
139139

@@ -150,7 +150,7 @@ DacThreadData GetThreadData(TargetPointer threadPointer)
150150
firstNestedException = runtimeThread.m_ExceptionState.m_currentExInfo.m_pPrevNestedInfo;
151151
}
152152

153-
return new DacThread(
153+
return new ThreadData(
154154
ThreadId : runtimeThread.m_ThreadId,
155155
OsThreadId : (OsThreadId)runtimeThread.m_OSThreadId,
156156
State : (ThreadState)runtimeThread.m_State,

docs/design/datacontracts/contract_csharp_api_design.cs

Lines changed: 19 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct TargetPointer
4040
struct TargetNInt
4141
{
4242
public long Value;
43-
// Add a full set of operators to support arithmetic as well as casting to/from TargetPointer
43+
// Add a full set of operators to support arithmetic as well as casting to/from TargetPointer
4444
}
4545

4646
struct TargetNUInt
@@ -72,109 +72,53 @@ struct FieldLayout
7272
public FieldType Type;
7373
}
7474

75-
interface IAlgorithmContract
76-
{
77-
void Init();
78-
}
79-
8075
interface IContract
8176
{
8277
string Name { get; }
8378
uint Version { get; }
8479
}
85-
class Target
80+
81+
class Target
8682
{
8783
// Users of the data contract may adjust this number to force re-reading of all data
8884
public int CurrentEpoch = 0;
8985

90-
sbyte ReadInt8(TargetPointer pointer);
91-
byte ReadUInt8(TargetPointer pointer);
92-
short ReadInt16(TargetPointer pointer);
93-
ushort ReadUInt16(TargetPointer pointer);
94-
int ReadInt32(TargetPointer pointer);
95-
uint ReadUInt32(TargetPointer pointer);
96-
long ReadInt64(TargetPointer pointer);
97-
ulong ReadUInt64(TargetPointer pointer);
98-
TargetPointer ReadTargetPointer(TargetPointer pointer);
99-
TargetNInt ReadNInt(TargetPointer pointer);
100-
TargetNUInt ReadNUint(TargetPointer pointer);
86+
public T Read<T>(ulong address) where T : unmanaged, IBinaryInteger<T>, IMinMaxValue<T>;
87+
TargetPointer ReadPointer(ulong address);
88+
10189
byte[] ReadByteArray(TargetPointer pointer, ulong size);
10290
void FillByteArray(TargetPointer pointer, byte[] array, ulong size);
10391

104-
bool TryReadInt8(TargetPointer pointer, out sbyte value);
105-
bool TryReadUInt8(TargetPointer pointer, out byte value);
106-
bool TryReadInt16(TargetPointer pointer, out short value);
107-
bool TryReadUInt16(TargetPointer pointer, out ushort value);
108-
bool TryReadInt32(TargetPointer pointer, out int value);
109-
bool TryReadUInt32(TargetPointer pointer, out uint value);
110-
bool TryReadInt64(TargetPointer pointer, out long value);
111-
bool TryReadUInt64(TargetPointer pointer, out ulong value);
112-
bool TryReadTargetPointer(TargetPointer pointer, out TargetPointer value);
113-
bool TryReadNInt(TargetPointer pointer, out TargetNInt value);
114-
bool TryReadNUInt(TargetPointer pointer, out TargetNUInt value);
115-
bool TryReadByteArray(TargetPointer pointer, ulong size, out byte[] value);
116-
bool TryFillByteArray(TargetPointer pointer, byte[] array, ulong size);
117-
11892
// If pointer is 0, then the return value will be 0
11993
TargetPointer GetTargetPointerForField(TargetPointer pointer, FieldLayout fieldLayout);
12094

121-
sbyte ReadGlobalInt8(string globalName);
122-
byte ReadGlobalUInt8(string globalName);
123-
short ReadGlobalInt16(string globalName);
124-
ushort ReadGlobalUInt16(string globalName);
125-
int ReadGlobalInt32(string globalName);
126-
uint ReadGlobalUInt32(string globalName);
127-
long ReadGlobalInt64(string globalName);
128-
ulong ReadGlobalUInt64(string globalName);
129-
TargetPointer ReadGlobalTargetPointer(string globalName);
130-
131-
bool TryReadGlobalInt8(string globalName, out sbyte value);
132-
bool TryReadGlobalUInt8(string globalName, out byte value);
133-
bool TryReadGlobalInt16(string globalName, out short value);
134-
bool TryReadGlobalUInt16(string globalName, out ushort value);
135-
bool TryReadGlobalInt32(string globalName, out int value);
136-
bool TryReadGlobalUInt32(string globalName, out uint value);
137-
bool TryReadGlobalInt64(string globalName, out long value);
138-
bool TryReadGlobalUInt64(string globalName, out ulong value);
139-
bool TryReadGlobalTargetPointer(string globalName, out TargetPointer value);
140-
141-
Contracts Contract { get; }
142-
143-
partial class Contracts
144-
{
145-
FieldLayout GetFieldLayout(string typeName, string fieldName);
146-
bool TryGetFieldLayout(string typeName, string fieldName, out FieldLayout layout);
147-
int GetTypeSize(string typeName);
148-
bool TryGetTypeSize(string typeName, out int size);
95+
T ReadGlobal<T>(string globalName) where T : unmanaged, IBinaryInteger<T>, IMinMaxValue<T>;
96+
TargetPointer ReadGlobalPointer(string globalName);
14997

150-
object GetContract(string contractName);
151-
bool TryGetContract(string contractName, out object contract);
98+
Contracts.Registry Contracts { get; }
99+
}
152100

101+
// Types defined by contracts live here
102+
namespace Contracts
103+
{
104+
class Registry
105+
{
153106
// Every contract that is defined has a field here. As an example this document defines a MethodTableContract
154107
// If the contract is not supported by the runtime in use, then the implementation of the contract will be the base type which
155108
// is defined to throw if it is ever used.
156109

157110
// List of contracts will be inserted here by source generator
158111
MethodTableContract MethodTableContract;
159112
}
160-
}
161-
162-
// Types defined by contracts live here
163-
namespace ContractDefinitions
164-
{
165-
class CompositeContract
166-
{
167-
List<Tuple<string, uint>> Subcontracts;
168-
}
169113

170114
class DataStructureContract
171115
{
172116
string MethodTableName {get;}
173117
List<Tuple<string, FieldLayout>> FieldData;
174118
}
175119

176-
// Insert Algorithmic Contract definitions here
177-
class MethodTableContract
120+
// Insert contract definitions here
121+
interface MethodTableContract : IContract
178122
{
179123
public virtual int DynamicTypeID(TargetPointer methodTablePointer) { throw new NotImplementedException(); }
180124
public virtual int BaseSize(TargetPointer methodTablePointer) { throw new NotImplementedException(); }
@@ -207,7 +151,7 @@ public class FeatureFlags_2
207151
}
208152

209153
[DataContractAlgorithm(1)]
210-
class MethodTableContract_1 : ContractDefinitions.MethodTableContract, IAlgorithmContract
154+
readonly struct MethodTableContract_1 : Contracts.MethodTableContract
211155
{
212156
DataContracts.Target Target;
213157
readonly uint ContractVersion;
@@ -219,7 +163,7 @@ class MethodTableContract_1 : ContractDefinitions.MethodTableContract, IAlgorith
219163

220164
// This is used for version 2 and 3 of the contract, where the dynamic type id is no longer present, and baseSize has a new limitation in that it can only be a value up to 0x1FFFFFFF in v3
221165
[DataContractAlgorithm(2, 3)]
222-
class MethodTableContract_2 : ContractDefinitions.MethodTableContract, IAlgorithmContract
166+
readonly struct MethodTableContract_2 : Contracts.MethodTableContract
223167
{
224168
DataContracts.Target Target;
225169
readonly uint ContractVersion;

src/coreclr/debug/runtimeinfo/datadescriptor.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,12 @@ CDAC_TYPE_END(Thread)
111111

112112
CDAC_TYPE_BEGIN(ThreadStore)
113113
CDAC_TYPE_INDETERMINATE(ThreadStore)
114-
CDAC_TYPE_FIELD(ThreadStore, /*omit type*/, ThreadCount, cdac_offsets<ThreadStore>::ThreadCount)
115-
CDAC_TYPE_FIELD(ThreadStore, /*omit type*/, ThreadList, cdac_offsets<ThreadStore>::ThreadList)
114+
CDAC_TYPE_FIELD(ThreadStore, /*SLink*/, FirstThreadLink, cdac_offsets<ThreadStore>::FirstThreadLink)
115+
CDAC_TYPE_FIELD(ThreadStore, /*int32*/, ThreadCount, cdac_offsets<ThreadStore>::ThreadCount)
116+
CDAC_TYPE_FIELD(ThreadStore, /*int32*/, UnstartedCount, cdac_offsets<ThreadStore>::UnstartedCount)
117+
CDAC_TYPE_FIELD(ThreadStore, /*int32*/, BackgroundCount, cdac_offsets<ThreadStore>::BackgroundCount)
118+
CDAC_TYPE_FIELD(ThreadStore, /*int32*/, PendingCount, cdac_offsets<ThreadStore>::PendingCount)
119+
CDAC_TYPE_FIELD(ThreadStore, /*int32*/, DeadCount, cdac_offsets<ThreadStore>::DeadCount)
116120
CDAC_TYPE_END(ThreadStore)
117121

118122
CDAC_TYPE_BEGIN(GCHandle)
@@ -123,6 +127,8 @@ CDAC_TYPES_END()
123127

124128
CDAC_GLOBALS_BEGIN()
125129
CDAC_GLOBAL_POINTER(ThreadStore, &ThreadStore::s_pThreadStore)
130+
CDAC_GLOBAL_POINTER(FinalizerThread, &::g_pFinalizerThread)
131+
CDAC_GLOBAL_POINTER(GCThread, &::g_pSuspensionThread)
126132
#if FEATURE_EH_FUNCLETS
127133
CDAC_GLOBAL(FeatureEHFunclets, uint8, 1)
128134
#else

src/coreclr/inc/slist.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#ifndef _H_SLIST_
2727
#define _H_SLIST_
2828

29+
#include "cdacoffsets.h"
30+
2931
//------------------------------------------------------------------
3032
// struct SLink, to use a singly linked list
3133
// have a data member m_Link of type SLink in your class
@@ -118,6 +120,8 @@ class SList
118120
PTR_SLink m_pHead;
119121
PTR_SLink m_pTail;
120122

123+
template<typename T> friend struct ::cdac_offsets;
124+
121125
// get the list node within the object
122126
static SLink* GetLink (T* pLink)
123127
{

src/coreclr/vm/threads.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4307,8 +4307,12 @@ class ThreadStore
43074307
template<>
43084308
struct cdac_offsets<ThreadStore>
43094309
{
4310-
static constexpr size_t ThreadList = offsetof(ThreadStore, m_ThreadList);
4310+
static constexpr size_t FirstThreadLink = offsetof(ThreadStore, m_ThreadList) + offsetof(ThreadList, m_link);
43114311
static constexpr size_t ThreadCount = offsetof(ThreadStore, m_ThreadCount);
4312+
static constexpr size_t UnstartedCount = offsetof(ThreadStore, m_UnstartedThreadCount);
4313+
static constexpr size_t BackgroundCount = offsetof(ThreadStore, m_BackgroundThreadCount);
4314+
static constexpr size_t PendingCount = offsetof(ThreadStore, m_PendingThreadCount);
4315+
static constexpr size_t DeadCount = offsetof(ThreadStore, m_DeadThreadCount);
43124316
};
43134317

43144318
struct TSSuspendHelper {

src/native/managed/cdacreader/src/Constants.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ internal static class Globals
99
{
1010
// See src/coreclr/debug/runtimeinfo/datadescriptor.h
1111
internal const string ThreadStore = nameof(ThreadStore);
12+
internal const string FinalizerThread = nameof(FinalizerThread);
13+
internal const string GCThread = nameof(GCThread);
14+
1215
internal const string SOSBreakingChangeVersion = nameof(SOSBreakingChangeVersion);
1316
}
1417
}

0 commit comments

Comments
 (0)