mirror of https://github.com/dotnet/runtime
Merge ecfdcada2d
into 123627ba0f
This commit is contained in:
commit
a9344a7712
|
@ -46,6 +46,7 @@ record struct ThreadData (
|
|||
ThreadStoreData GetThreadStoreData();
|
||||
ThreadStoreCounts GetThreadCounts();
|
||||
ThreadData GetThreadData(TargetPointer threadPointer);
|
||||
TargetPointer IdToThread(uint id);
|
||||
```
|
||||
|
||||
## Version 1
|
||||
|
@ -58,6 +59,7 @@ This contract depends on the following descriptors:
|
|||
| `RuntimeThreadLocals` |
|
||||
| `Thread` |
|
||||
| `ThreadStore` |
|
||||
| `IdDispenser` |
|
||||
|
||||
| Global name |
|
||||
| --- |
|
||||
|
@ -66,7 +68,7 @@ This contract depends on the following descriptors:
|
|||
| `FeatureEHFunclets` |
|
||||
| `FinalizerThread` |
|
||||
| `GCThread` |
|
||||
|
||||
| `ThinLockThreadIdDispenser` |
|
||||
``` csharp
|
||||
ThreadStoreData GetThreadStoreData()
|
||||
{
|
||||
|
@ -93,11 +95,11 @@ DacThreadStoreCounts GetThreadCounts()
|
|||
|
||||
ThreadData GetThreadData(TargetPointer address)
|
||||
{
|
||||
var runtimeThread = new Thread(Target, threadPointer);
|
||||
var runtimeThread = new Thread(target, threadPointer);
|
||||
|
||||
// Exception tracker is a pointer when EH funclets are enabled
|
||||
TargetPointer exceptionTrackerAddr = _target.ReadGlobal<byte>("FeatureEHFunclets") != 0
|
||||
? _target.ReadPointer(address + /* Thread::ExceptionTracker offset */)
|
||||
TargetPointer exceptionTrackerAddr = target.ReadGlobal<byte>("FeatureEHFunclets") != 0
|
||||
? target.ReadPointer(address + /* Thread::ExceptionTracker offset */)
|
||||
: address + /* Thread::ExceptionTracker offset */;
|
||||
TargetPointer firstNestedException = exceptionTrackerAddr != TargetPointer.Null
|
||||
? target.ReadPointer(exceptionTrackerAddr + /* ExceptionInfo::PreviousNestedInfo offset*/)
|
||||
|
@ -127,4 +129,15 @@ ThreadData GetThreadData(TargetPointer address)
|
|||
NextThread: target.ReadPointer(address + /* Thread::LinkNext offset */) - threadLinkOffset;
|
||||
);
|
||||
}
|
||||
|
||||
TargetPointer IThread.IdToThread(uint id)
|
||||
{
|
||||
TargetPointer idDispenserPointer = target.ReadGlobalPointer(Constants.Globals.ThinlockThreadIdDispenser);
|
||||
TargetPointer idDispenser = target.ReadPointer(idDispenserPointer)
|
||||
uint HighestId = target.ReadPointer(idDispenser + /* IdDispenser::HighestId offset */);
|
||||
TargetPointer threadPtr = TargetPointer.Null;
|
||||
if (id < HighestId)
|
||||
threadPtr = target.ReadPointer(idDispenser + /* IdDispenser::IdToThread offset */);
|
||||
return threadPtr;
|
||||
}
|
||||
```
|
||||
|
|
|
@ -140,6 +140,12 @@ CDAC_TYPE_INDETERMINATE(RuntimeThreadLocals)
|
|||
CDAC_TYPE_FIELD(RuntimeThreadLocals, /*EEAllocContext*/, AllocContext, offsetof(RuntimeThreadLocals, alloc_context))
|
||||
CDAC_TYPE_END(RuntimeThreadLocals)
|
||||
|
||||
CDAC_TYPE_BEGIN(IdDispenser)
|
||||
CDAC_TYPE_INDETERMINATE(IdDispenser)
|
||||
CDAC_TYPE_FIELD(IdDispenser, /*pointer*/, IdToThread, cdac_data<IdDispenser>::IdToThread)
|
||||
CDAC_TYPE_FIELD(IdDispenser, /*uint32*/, HighestId, cdac_data<IdDispenser>::HighestId)
|
||||
CDAC_TYPE_END(IdDispenser)
|
||||
|
||||
CDAC_TYPE_BEGIN(EEAllocContext)
|
||||
CDAC_TYPE_INDETERMINATE(EEAllocContext)
|
||||
CDAC_TYPE_FIELD(EEAllocContext, /*GCAllocContext*/, GCAllocationContext, offsetof(ee_alloc_context, m_GCAllocContext))
|
||||
|
@ -992,6 +998,7 @@ CDAC_GLOBAL_POINTER(MiniMetaDataBuffAddress, &::g_MiniMetaDataBuffAddress)
|
|||
CDAC_GLOBAL_POINTER(MiniMetaDataBuffMaxSize, &::g_MiniMetaDataBuffMaxSize)
|
||||
CDAC_GLOBAL_POINTER(DacNotificationFlags, &::g_dacNotificationFlags)
|
||||
CDAC_GLOBAL_POINTER(OffsetOfCurrentThreadInfo, &::g_offsetOfCurrentThreadInfo)
|
||||
CDAC_GLOBAL_POINTER(ThinlockThreadIdDispenser, &::g_pThinLockThreadIdDispenser)
|
||||
#ifdef TARGET_WINDOWS
|
||||
CDAC_GLOBAL_POINTER(TlsIndexBase, &::_tls_index)
|
||||
#endif // TARGET_WINDOWS
|
||||
|
|
|
@ -4390,7 +4390,17 @@ public:
|
|||
_ASSERTE(result == NULL || (dac_cast<size_t>(result) & 0x3) == 0 || ((Thread*)result)->GetThreadId() == id);
|
||||
return result;
|
||||
}
|
||||
|
||||
friend struct ::cdac_data<IdDispenser>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cdac_data<IdDispenser>
|
||||
{
|
||||
static constexpr size_t IdToThread = offsetof(IdDispenser, m_idToThread);
|
||||
static constexpr size_t HighestId = offsetof(IdDispenser, m_highestId);
|
||||
};
|
||||
|
||||
typedef DPTR(IdDispenser) PTR_IdDispenser;
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ public interface IThread : IContract
|
|||
ThreadStoreData GetThreadStoreData() => throw new NotImplementedException();
|
||||
ThreadStoreCounts GetThreadCounts() => throw new NotImplementedException();
|
||||
ThreadData GetThreadData(TargetPointer thread) => throw new NotImplementedException();
|
||||
TargetPointer IdToThread(uint id) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public readonly struct Thread : IThread
|
||||
|
|
|
@ -28,6 +28,7 @@ public enum DataType
|
|||
Exception,
|
||||
ExceptionInfo,
|
||||
RuntimeThreadLocals,
|
||||
IdDispenser,
|
||||
Module,
|
||||
ModuleLookupMap,
|
||||
AppDomain,
|
||||
|
|
|
@ -30,6 +30,7 @@ public static class Constants
|
|||
public const string DacNotificationFlags = nameof(DacNotificationFlags);
|
||||
public const string OffsetOfCurrentThreadInfo = nameof(OffsetOfCurrentThreadInfo);
|
||||
public const string TlsIndexBase = nameof(TlsIndexBase);
|
||||
public const string ThinlockThreadIdDispenser = nameof(ThinlockThreadIdDispenser);
|
||||
|
||||
public const string StressLogEnabled = nameof(StressLogEnabled);
|
||||
public const string StressLogHasModuleTable = nameof(StressLogHasModuleTable);
|
||||
|
|
|
@ -68,6 +68,17 @@ internal readonly struct Thread_1 : IThread
|
|||
GetThreadFromLink(thread.LinkNext));
|
||||
}
|
||||
|
||||
TargetPointer IThread.IdToThread(uint id)
|
||||
{
|
||||
TargetPointer idDispenserPtr = _target.ReadGlobalPointer(Constants.Globals.ThinlockThreadIdDispenser);
|
||||
TargetPointer idDispenser = _target.ReadPointer(idDispenserPtr);
|
||||
Data.IdDispenser idDispenserObj = _target.ProcessedData.GetOrAdd<Data.IdDispenser>(idDispenser);
|
||||
TargetPointer threadPtr = TargetPointer.Null;
|
||||
if (id < idDispenserObj.HighestId)
|
||||
threadPtr = _target.ReadPointer(idDispenserObj.IdToThread + (ulong)(id * _target.PointerSize));
|
||||
return threadPtr;
|
||||
}
|
||||
|
||||
private TargetPointer GetThreadFromLink(TargetPointer threadLink)
|
||||
{
|
||||
if (threadLink == TargetPointer.Null)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Diagnostics.DataContractReader.Data;
|
||||
|
||||
internal sealed class IdDispenser : IData<IdDispenser>
|
||||
{
|
||||
static IdDispenser IData<IdDispenser>.Create(Target target, TargetPointer address) => new IdDispenser(target, address);
|
||||
public IdDispenser(Target target, TargetPointer address)
|
||||
{
|
||||
Target.TypeInfo type = target.GetTypeInfo(DataType.IdDispenser);
|
||||
IdToThread = target.ReadPointer(address + (ulong)type.Fields[nameof(IdToThread)].Offset);
|
||||
HighestId = target.Read<uint>(address + (ulong)type.Fields[nameof(HighestId)].Offset);
|
||||
}
|
||||
|
||||
public TargetPointer IdToThread { get; init; }
|
||||
public uint HighestId { get; init; }
|
||||
}
|
|
@ -1920,7 +1920,33 @@ internal sealed unsafe partial class SOSDacImpl
|
|||
return hr;
|
||||
}
|
||||
int ISOSDacInterface.GetThreadFromThinlockID(uint thinLockId, ClrDataAddress* pThread)
|
||||
=> _legacyImpl is not null ? _legacyImpl.GetThreadFromThinlockID(thinLockId, pThread) : HResults.E_NOTIMPL;
|
||||
{
|
||||
int hr = HResults.S_OK;
|
||||
if (pThread == null)
|
||||
hr = HResults.E_INVALIDARG;
|
||||
try
|
||||
{
|
||||
TargetPointer threadPtr = _target.Contracts.Thread.IdToThread(thinLockId);
|
||||
*pThread = threadPtr.ToClrDataAddress(_target);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
hr = ex.HResult;
|
||||
}
|
||||
#if DEBUG
|
||||
if (_legacyImpl is not null)
|
||||
{
|
||||
ClrDataAddress pThreadLocal;
|
||||
int hrLocal = _legacyImpl.GetThreadFromThinlockID(thinLockId, &pThreadLocal);
|
||||
Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}");
|
||||
if (hr == HResults.S_OK)
|
||||
{
|
||||
Debug.Assert(*pThread == pThreadLocal);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return hr;
|
||||
}
|
||||
int ISOSDacInterface.GetThreadLocalModuleData(ClrDataAddress thread, uint index, void* data)
|
||||
{
|
||||
// CoreCLR does not use thread local modules anymore
|
||||
|
|
Loading…
Reference in New Issue