Skip to content

Implement cDAC API GetSyncBlockCleanupData#125009

Open
Copilot wants to merge 8 commits intomainfrom
copilot/implement-get-sync-block-cleanup-data
Open

Implement cDAC API GetSyncBlockCleanupData#125009
Copilot wants to merge 8 commits intomainfrom
copilot/implement-get-sync-block-cleanup-data

Conversation

Copy link
Contributor

Copilot AI commented Feb 28, 2026

Implements GetSyncBlockCleanupData in the cDAC. Also corrects addr=0 behavior: the legacy C++ implementation incorrectly returned E_INVALIDARG; per the API contract, addr=0 should start traversal from SyncBlockCache.m_pCleanupBlockList.

Objects on the cleanup list may not be valid managed objects, so COM data must be read directly from the sync block — not via the object header. This required splitting GetBuiltInComData across two contracts.

Changes

  • ISyncBlock / SyncBlock_1 — Add GetBuiltInComData(TargetPointer syncBlock, ...) to read RCW/CCW/CCF directly from a sync block pointer (safe during cleanup). Add GetSyncBlockFromCleanupList() and GetNextSyncBlock(TargetPointer) for cleanup-list traversal.
  • Object_1GetBuiltInComData keeps the object-header → sync-table → sync-block lookup (inlined, no SyncBlockValue nested class — bit constants are now runtime globals), then delegates to ISyncBlock.GetBuiltInComData. Private GetSyncBlock helper inlined and removed.
  • datadescriptor.inc — Expose SyncBlockCache.m_pCleanupBlockList and the three sync block bit constants (SyncBlockIsHashOrSyncBlockIndex, SyncBlockIsHashCode, SyncBlockIndexMask) as runtime globals backed by existing C++ macros. Remove SyncIndex (no longer needed).
  • SyncBlockFactorysyncBlockLinkOffset computation moved from SyncBlock_1 constructor into the factory's CreateContract and passed as a parameter.
  • SyncBlockCacheCleanupBlockList uses direct field access instead of optional TryGetValue.
  • SOSDacImplGetSyncBlockCleanupData: addr==0 walks from GetSyncBlockFromCleanupList(), addr!=0 reads the block directly; both call syncBlockContract.GetBuiltInComData(syncBlockPtr, ...) without touching the object. Null check for data moved inside the try block. DEBUG assertion no longer skips addr==0 case. GetSyncBlockData likewise uses the SyncBlock contract directly.
  • request.cpp — Removed syncBlock == 0 from the E_INVALIDARG guard to allow the "start from cleanup list head" case.
  • SyncBlock.md / Object.md — Updated to document new APIs, globals, data descriptors, and the delegation pattern.
  • TestsSyncBlockTests covering cleanup-list traversal, GetBuiltInComData with/without interop info, chained linkage. ObjectTests.ComData wired up with SyncBlock contract. Mock descriptors updated with new globals.

🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

Copilot AI and others added 2 commits February 28, 2026 15:17
Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
…ockCleanupInfo_RCWLockBitMasked tests

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement cDAC API GetSyncBlockCleanupData Implement cDAC API GetSyncBlockCleanupData Feb 28, 2026
Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
… COM data

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
…ct delegates to it; update docs

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
@rcj1
Copy link
Contributor

rcj1 commented Feb 28, 2026

@copilot please apply the following patch.
patch.patch

…to factory, simplify null checks

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 28, 2026

@copilot please apply the following patch.
patch.patch

Applied in b2c0797. Key changes from the patch:

  • Removed the hardcoded SyncBlockValue nested class from Object_1; the bit constants (SyncBlockIsHashOrSyncBlockIndex, SyncBlockIsHashCode, SyncBlockIndexMask) are now runtime globals read via ReadGlobal<uint>, backed by datadescriptor.inc macros (BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX, BIT_SBLK_IS_HASHCODE, MASK_SYNCBLOCKINDEX)
  • Moved syncBlockLinkOffset computation from SyncBlock_1's constructor into SyncBlockFactory
  • Simplified SyncBlockCache.CleanupBlockList to direct field access (removed optional TryGetValue pattern)
  • Moved the data == null check inside the try block in GetSyncBlockCleanupData; removed the addr != 0 guard on the DEBUG assertion
  • Fixed request.cpp to allow syncBlock == 0

@rcj1 rcj1 requested a review from barosiak February 28, 2026 20:55
@rcj1 rcj1 marked this pull request as ready for review February 28, 2026 20:55
Copilot AI review requested due to automatic review settings February 28, 2026 20:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements the GetSyncBlockCleanupData API in the cDAC (Contracts Data for Diagnostics). It also fixes a pre-existing behavior discrepancy: the legacy C++ implementation incorrectly returned E_INVALIDARG for addr=0, while the API contract specifies that addr=0 should start cleanup list traversal from SyncBlockCache.m_pCleanupBlockList. Additionally, it refactors GetBuiltInComData to work directly from a sync block pointer, enabling safe access during cleanup when the associated managed object may not be valid.

Changes:

  • Adds GetSyncBlockFromCleanupList(), GetNextSyncBlock(), and GetBuiltInComData(TargetPointer syncBlock, ...) to the ISyncBlock interface and SyncBlock_1 implementation
  • Refactors Object_1.GetBuiltInComData to delegate to the SyncBlock contract, and moves the sync block bit constants (SyncBlockIsHashOrSyncBlockIndex, SyncBlockIsHashCode, SyncBlockIndexMask) to runtime globals exposed via the data descriptor
  • Adds GetSyncBlockCleanupData implementation in SOSDacImpl using the new SyncBlock contract APIs, and updates GetSyncBlockData to use syncBlock.GetBuiltInComData directly

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
ISyncBlock.cs Adds three new cleanup-list and COM-data interface methods
SyncBlock_1.cs Implements new methods; receives syncBlockLinkOffset for list pointer arithmetic
SyncBlockFactory.cs Computes and passes syncBlockLinkOffset to SyncBlock_1
Object_1.cs Removes SyncBlockValue nested class; reads bit constants from runtime globals; delegates GetBuiltInComData to ISyncBlock
SOSDacImpl.cs Implements GetSyncBlockCleanupData; updates GetSyncBlockData to use SyncBlock contract
ISOSDacInterface.cs Adds DacpSyncBlockCleanupData struct; updates GetSyncBlockCleanupData signature
Constants.cs Adds three new SyncBlock* global name constants
SyncBlockCache.cs Adds CleanupBlockList field
datadescriptor.inc Exposes SyncBlockCache.CleanupBlockList and three bit constants as globals
syncblk.h Adds CleanupBlockList to cdac_data<SyncBlockCache>
request.cpp Removes syncBlock == 0 from E_INVALIDARG guard
SyncBlockTests.cs New unit tests for cleanup list traversal and COM data
MockDescriptors.SyncBlock.cs New test descriptor for SyncBlock cleanup list
MockDescriptors.Object.cs Adds three new globals to Object mock
MockDescriptors.cs Adds CleanupBlockList to SyncBlockCacheFields
SyncBlock.md Documents new APIs, data descriptors
Object.md Documents new globals and delegation pattern

}
#endif
return hr;
}
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a missing blank line between the closing brace of GetSyncBlockCleanupData (line 3473) and the start of GetSyncBlockData (line 3474). All other method implementations in this file have a blank line separating them for readability. This is a minor style inconsistency introduced by this PR.

Suggested change
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +16 to +18
private const ulong TestSyncBlockCacheGlobalAddress = 0x0000_0100;
private const ulong TestSyncTableEntriesGlobalAddress = 0x0000_0200;
private const ulong TestSyncTableEntriesAddress = 0x0000_0300;
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constants TestSyncBlockCacheGlobalAddress (0x0000_0100), TestSyncTableEntriesGlobalAddress (0x0000_0200), and TestSyncTableEntriesAddress (0x0000_0300) are defined but never used. The actual global pointer fragments are allocated from _allocator using the bump allocator, not from these fixed addresses. These unused constants should be removed.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants