-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Add GetSyncBlockData cDAC API #124933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add GetSyncBlockData cDAC API #124933
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
89ad7c5
add syncblock cdac api
rcj1 95f5f1b
merge
rcj1 74cc391
add syncblock api
rcj1 54f76eb
Merge branch 'main' into GetSyncBlockData
rcj1 01728fc
code review
rcj1 d948b77
Update comment to clarify SyncBlock debuggee dump
rcj1 b963095
code review and test fixes
rcj1 a0d0c9b
Merge branch 'main' into GetSyncBlockData
rcj1 c79fb77
fix merge and code review
rcj1 4a3e20d
fix merge
rcj1 70e83e9
fix build break
rcj1 15f803f
fix bug
rcj1 0c1e611
Update SyncBlockDumpTests.cs
rcj1 34e0946
Add DumpTypes property to SyncBlock project
rcj1 7ce52ef
Update docs/design/datacontracts/Object.md
rcj1 55ed1f0
Update src/native/managed/cdac/tests/DumpTests/README.md
rcj1 bb28035
Update README.md
rcj1 8980986
Add DumpType property to SyncBlockDumpTests
rcj1 79a3142
Update Object_1.cs
rcj1 3f776d1
Fix pointer assignment logic in Object.md
rcj1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| # Contract SyncBlock | ||
|
|
||
| This contract is for reading sync block table entries and lock state. | ||
|
|
||
| ## APIs of contract | ||
|
|
||
| ``` csharp | ||
| TargetPointer GetSyncBlock(uint index); | ||
| TargetPointer GetSyncBlockObject(uint index); | ||
| bool IsSyncBlockFree(uint index); | ||
| uint GetSyncBlockCount(); | ||
| bool TryGetLockInfo(TargetPointer syncBlock, out uint owningThreadId, out uint recursion); | ||
| uint GetAdditionalThreadCount(TargetPointer syncBlock); | ||
| ``` | ||
|
|
||
| ## Version 1 | ||
|
|
||
| Data descriptors used: | ||
| | Data Descriptor Name | Field | Meaning | | ||
| | --- | --- | --- | | ||
| | `SyncTableEntry` | `SyncBlock` | Pointer to the sync block for a sync table entry | | ||
| | `SyncTableEntry` | `Object` | Pointer to the object associated with a sync table entry | | ||
| | `SyncBlockCache` | `FreeSyncTableIndex` | One past the highest sync table entry index allocated | | ||
| | `SyncBlock` | `Lock` | Optional pointer to a `System.Threading.Lock` object payload | | ||
| | `SyncBlock` | `ThinLock` | Thin-lock state bits | | ||
| | `SyncBlock` | `LinkNext` | Head pointer for additional waiting threads list | | ||
| | `SLink` | `Next` | Next link for the additional waiting threads list | | ||
|
|
||
| Global variables used: | ||
| | Global Name | Type | Purpose | | ||
| | --- | --- | --- | | ||
| | `SyncTableEntries` | TargetPointer | Pointer to the sync table entries array | | ||
| | `SyncBlockCache` | TargetPointer | Pointer to the runtime sync block cache | | ||
| | `SyncBlockMaskLockThreadId` | uint32 | Mask for extracting thread id from `SyncBlock.ThinLock` | | ||
| | `SyncBlockMaskLockRecursionLevel` | uint32 | Mask for extracting recursion level from `SyncBlock.ThinLock` | | ||
| | `SyncBlockRecursionLevelShift` | uint32 | Shift value for `SyncBlock.ThinLock` recursion level | | ||
|
|
||
| ### Contract Constants: | ||
| | Name | Type | Purpose | Value | | ||
| | --- | --- | --- | --- | | ||
| | `LockStateName` | string | Field name in `System.Threading.Lock` storing monitor-held state bits. | `_state` | | ||
| | `LockOwningThreadIdName` | string | Field name in `System.Threading.Lock` storing owning thread id. | `_owningThreadId` | | ||
| | `LockRecursionCountName` | string | Field name in `System.Threading.Lock` storing monitor recursion count. | `_recursionCount` | | ||
| | `LockName` | string | Type name used to resolve `System.Threading.Lock`. | `Lock` | | ||
| | `LockNamespace` | string | Namespace used to resolve `System.Threading.Lock`. | `System.Threading` | | ||
|
|
||
| Contracts used: | ||
| | Contract Name | | ||
| | --- | | ||
| | `Loader` | | ||
| | `RuntimeTypeSystem` | | ||
| | `EcmaMetadata` | | ||
|
|
||
| ``` csharp | ||
| TargetPointer GetSyncBlock(uint index) | ||
| { | ||
| TargetPointer syncTableEntries = target.ReadGlobalPointer("SyncTableEntries"); | ||
| ulong offsetInSyncTable = index * /* SyncTableEntry size */; | ||
| return target.ReadPointer(syncTableEntries + offsetInSyncTable + /* SyncTableEntry::SyncBlock offset */); | ||
| } | ||
|
|
||
| TargetPointer GetSyncBlockObject(uint index) | ||
| { | ||
| TargetPointer syncTableEntries = target.ReadGlobalPointer("SyncTableEntries"); | ||
| ulong offsetInSyncTable = index * /* SyncTableEntry size */; | ||
| return target.ReadPointer(syncTableEntries + offsetInSyncTable + /* SyncTableEntry::Object offset */); | ||
| } | ||
|
|
||
| bool IsSyncBlockFree(uint index) | ||
| { | ||
| TargetPointer syncTableEntries = target.ReadGlobalPointer("SyncTableEntries"); | ||
| ulong offsetInSyncTable = index * /* SyncTableEntry size */; | ||
| TargetPointer obj = target.ReadPointer(syncTableEntries + offsetInSyncTable + /* SyncTableEntry::Object offset */); | ||
| return (obj.Value & 1) != 0; | ||
| } | ||
|
|
||
| uint GetSyncBlockCount() | ||
| { | ||
| TargetPointer syncBlockCache = target.ReadPointer(target.ReadGlobalPointer("SyncBlockCache")); | ||
| uint freeSyncTableIndex = target.Read<uint>(syncBlockCache + /* SyncBlockCache::FreeSyncTableIndex offset */); | ||
| return freeSyncTableIndex - 1; | ||
| } | ||
|
|
||
| bool TryGetLockInfo(TargetPointer syncBlock, out uint owningThreadId, out uint recursion) | ||
| { | ||
| owningThreadId = 0; | ||
| recursion = 0; | ||
|
|
||
| TargetPointer lockObject = target.ReadPointer(syncBlock + /* SyncBlock::Lock offset */); | ||
|
|
||
| if (lockObject != TargetPointer.Null) | ||
| { | ||
| // Resolve System.Threading.Lock in System.Private.CoreLib by name using RuntimeTypeSystem contract, LockName and LockNamespace. | ||
| uint state = ReadUintField(/* Lock type */, "LockStateName", /* RuntimeTypeSystem contract */, /* MetadataReader for SPC */, lockObject); | ||
| bool monitorHeld = (state & 1) != 0; | ||
| if (monitorHeld) | ||
| { | ||
| owningThreadId = ReadUintField(/* Lock type */, "LockOwningThreadIdName", /* contracts */, lockObject); | ||
| recursion = ReadUintField(/* Lock type */, "LockRecursionCountName", /* contracts */, lockObject); | ||
| } | ||
|
|
||
| return monitorHeld; | ||
| } | ||
|
|
||
| uint thinLock = target.Read<uint>(syncBlock + /* SyncBlock::ThinLock offset */); | ||
| if (thinLock != 0) | ||
| { | ||
| owningThreadId = thinLock & target.ReadGlobal<uint>("SyncBlockMaskLockThreadId"); | ||
| bool monitorHeld = owningThreadId != 0; | ||
| if (monitorHeld) | ||
| { | ||
| recursion = (thinLock & target.ReadGlobal<uint>("SyncBlockMaskLockRecursionLevel")) | ||
| >> (int)target.ReadGlobal<uint>("SyncBlockRecursionLevelShift"); | ||
| } | ||
|
|
||
| return monitorHeld; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| private uint ReadUintField(TypeHandle enclosingType, string fieldName, IRuntimeTypeSystem rts, MetadataReader mdReader, TargetPointer dataAddr) | ||
| { | ||
| TargetPointer field = rts.GetFieldDescByName(enclosingType, fieldName); | ||
| uint token = rts.GetFieldDescMemberDef(field); | ||
| FieldDefinitionHandle fieldHandle = (FieldDefinitionHandle)MetadataTokens.Handle((int)token); | ||
| FieldDefinition fieldDef = mdReader.GetFieldDefinition(fieldHandle); | ||
| uint offset = rts.GetFieldDescOffset(field, fieldDef); | ||
| return _target.Read<uint>(dataAddr + offset); | ||
| } | ||
|
|
||
| uint GetAdditionalThreadCount(TargetPointer syncBlock) | ||
| { | ||
| uint threadCount = 0; | ||
| TargetPointer next = target.ReadPointer(syncBlock + /* SyncBlock::LinkNext offset */); | ||
| while (next != TargetPointer.Null && threadCount < 1000) | ||
| { | ||
| threadCount++; | ||
| next = target.ReadPointer(next + /* SLink::Next offset */); | ||
| } | ||
|
|
||
| return threadCount; | ||
| } | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
...anaged/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISyncBlock.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // 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.Contracts; | ||
| public interface ISyncBlock : IContract | ||
| { | ||
| static string IContract.Name { get; } = nameof(SyncBlock); | ||
| TargetPointer GetSyncBlock(uint index) => throw new NotImplementedException(); | ||
| TargetPointer GetSyncBlockObject(uint index) => throw new NotImplementedException(); | ||
| bool IsSyncBlockFree(uint index) => throw new NotImplementedException(); | ||
| uint GetSyncBlockCount() => throw new NotImplementedException(); | ||
| bool TryGetLockInfo(TargetPointer syncBlock, out uint owningThreadId, out uint recursion) => throw new NotImplementedException(); | ||
| uint GetAdditionalThreadCount(TargetPointer syncBlock) => throw new NotImplementedException(); | ||
| } | ||
|
|
||
| public readonly struct SyncBlock : ISyncBlock | ||
| { | ||
| // Everything throws NotImplementedException | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.