| File: Contracts\SyncBlock_1.cs | Web Access |
| Project: src\runtime\src\native\managed\cdac\Microsoft.Diagnostics.DataContractReader.Contracts\Microsoft.Diagnostics.DataContractReader.Contracts.csproj (Microsoft.Diagnostics.DataContractReader.Contracts) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace Microsoft.Diagnostics.DataContractReader.Contracts; internal readonly struct SyncBlock_1 : ISyncBlock { private readonly Target _target; private readonly TargetPointer _syncTableEntries; internal SyncBlock_1(Target target) { _target = target; _syncTableEntries = target.ReadPointer(target.ReadGlobalPointer(Constants.Globals.SyncTableEntries)); } public TargetPointer GetSyncBlock(uint index) { Data.SyncTableEntry ste = _target.ProcessedData.GetOrAdd<Data.SyncTableEntry>(_syncTableEntries + index * _target.GetTypeInfo(DataType.SyncTableEntry).Size!.Value); return ste.SyncBlock?.Address ?? TargetPointer.Null; } public TargetPointer GetSyncBlockObject(uint index) { Data.SyncTableEntry ste = _target.ProcessedData.GetOrAdd<Data.SyncTableEntry>(_syncTableEntries + index * _target.GetTypeInfo(DataType.SyncTableEntry).Size!.Value); return ste.Object?.Address ?? TargetPointer.Null; } public bool IsSyncBlockFree(uint index) { Data.SyncTableEntry ste = _target.ProcessedData.GetOrAdd<Data.SyncTableEntry>(_syncTableEntries + index * _target.GetTypeInfo(DataType.SyncTableEntry).Size!.Value); return (ste.Object?.Address & 1) != 0; } public uint GetSyncBlockCount() { TargetPointer syncBlockCache = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.SyncBlockCache)); Data.SyncBlockCache cache = _target.ProcessedData.GetOrAdd<Data.SyncBlockCache>(syncBlockCache); return cache.FreeSyncTableIndex - 1; } public bool TryGetLockInfo(TargetPointer syncBlock, out uint owningThreadId, out uint recursion) { owningThreadId = 0; recursion = 0; Data.SyncBlock sb = _target.ProcessedData.GetOrAdd<Data.SyncBlock>(syncBlock); if (sb.Lock != null) { Data.Lock lockData = _target.ProcessedData.GetOrAdd<Data.Lock>(sb.Lock.Object); bool monitorHeld = (lockData.State & 1) != 0; if (monitorHeld) { owningThreadId = (uint)lockData.OwningThreadId; recursion = lockData.RecursionCount; } return monitorHeld; } else if (sb.ThinLock != 0) { owningThreadId = sb.ThinLock & _target.ReadGlobal<uint>(Constants.Globals.SyncBlockMaskLockThreadId); bool monitorHeld = owningThreadId != 0; if (monitorHeld) { recursion = (sb.ThinLock & _target.ReadGlobal<uint>(Constants.Globals.SyncBlockMaskLockRecursionLevel)) >> (int)_target.ReadGlobal<uint>(Constants.Globals.SyncBlockRecursionLevelShift); } return monitorHeld; } else { return false; } } public uint GetAdditionalThreadCount(TargetPointer syncBlock) { // TODO: read conditional weak table to get additional thread count return 0; } public TargetPointer GetSyncBlockFromCleanupList() { TargetPointer syncBlockCache = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.SyncBlockCache)); Data.SyncBlockCache cache = _target.ProcessedData.GetOrAdd<Data.SyncBlockCache>(syncBlockCache); TargetPointer cleanupBlockList = cache.CleanupBlockList; if (cleanupBlockList == TargetPointer.Null) return TargetPointer.Null; return cleanupBlockList; } public TargetPointer GetNextSyncBlock(TargetPointer syncBlock) { Data.SyncBlock sb = _target.ProcessedData.GetOrAdd<Data.SyncBlock>(syncBlock); if (sb.LinkNext == TargetPointer.Null) return TargetPointer.Null; return sb.LinkNext; } public bool GetBuiltInComData(TargetPointer syncBlock, out TargetPointer rcw, out TargetPointer ccw, out TargetPointer ccf) { rcw = TargetPointer.Null; ccw = TargetPointer.Null; ccf = TargetPointer.Null; Data.SyncBlock sb = _target.ProcessedData.GetOrAdd<Data.SyncBlock>(syncBlock); Data.InteropSyncBlockInfo? interopInfo = sb.InteropInfo; if (interopInfo == null) return false; rcw = (interopInfo.RCW ?? TargetPointer.Null) & ~1ul; ccw = interopInfo.CCW == 1 ? TargetPointer.Null : (interopInfo.CCW ?? TargetPointer.Null); ccf = interopInfo.CCF == 1 ? TargetPointer.Null : (interopInfo.CCF ?? TargetPointer.Null); return rcw != TargetPointer.Null || ccw != TargetPointer.Null || ccf != TargetPointer.Null; } }