Skip to content

[cDAC] Implement EnumerateMonitorEventWaitList for cDAC#129054

Open
barosiak wants to merge 2 commits into
dotnet:mainfrom
barosiak:barosiak/EnumerateMonitorEventWaitList
Open

[cDAC] Implement EnumerateMonitorEventWaitList for cDAC#129054
barosiak wants to merge 2 commits into
dotnet:mainfrom
barosiak:barosiak/EnumerateMonitorEventWaitList

Conversation

@barosiak

@barosiak barosiak commented Jun 5, 2026

Copy link
Copy Markdown
Member

Summary

Implement DacDbiImpl.EnumerateMonitorEventWaitList in the cDAC to enumerate threads waiting on a monitor lock for a given object.

Changes

  • DacDbiImpl.cs - Implement EnumerateMonitorEventWaitList with #if DEBUG legacy validation
  • DacDbiImplTests.cs - Add 4 test methods (16 cases across architectures) covering no sync block, null callback, ConditionalWeakTable miss/empty list, and single/multiple/non-waiting thread scenarios

@barosiak barosiak self-assigned this Jun 5, 2026
Copilot AI review requested due to automatic review settings June 5, 2026 21:48
@dotnet-policy-service

Copy link
Copy Markdown
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 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Implements DacDbiImpl.EnumerateMonitorEventWaitList in the cDAC managed DacDbiImpl to enumerate threads waiting on a monitor’s condition wait list for a given object, and adds unit tests exercising key scenarios across architectures.

Changes:

  • Added a cDAC implementation of EnumerateMonitorEventWaitList that reads the Monitor.s_conditionTable, resolves the object’s Condition via ConditionalWeakTable, maps per-thread waiter objects to threads, then walks the waiters linked list to invoke the callback.
  • Added #if DEBUG validation comparing cDAC results against legacy DAC results.
  • Added unit tests covering: no sync block, null callback, missing condition / empty waiters list, and single/multiple/non-waiting thread cases.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs Adds the cDAC implementation of EnumerateMonitorEventWaitList plus DEBUG-only legacy cross-validation.
src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs Adds helper infrastructure and new tests for EnumerateMonitorEventWaitList behavior across architectures.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 5, 2026 22:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comment on lines +3206 to +3219
// Build a map of Waiter objects to their owning Threads.
var waiterToThreadMap = new Dictionary<ulong, TargetPointer>();
Contracts.IThread threadContract = _target.Contracts.Thread;
Contracts.ThreadStoreData threadStore = threadContract.GetThreadStoreData();
TargetPointer currentThread = threadStore.FirstThread;
while (currentThread != TargetPointer.Null)
{
Contracts.ThreadData threadData = threadContract.GetThreadData(currentThread);

if (_target.Contracts.ManagedTypeSource.TryGetThreadStaticFieldAddress(
"System.Threading.Condition", "t_waiterForCurrentThread", currentThread, out TargetPointer waiterSlot))
{
TargetPointer waiterObj = _target.ReadPointer(waiterSlot);
if (waiterObj != TargetPointer.Null)
Comment on lines +1002 to +1009
var slotFragment = allocator.Allocate((ulong)ptrSize, $"WaiterSlot_{thread.Value:x}");
helpers.WritePointer(slotFragment.Data, waiterFragments[waiterIdx].Address);

TargetPointer outAddr = new(slotFragment.Address);
mockMts.Setup(m => m.TryGetThreadStaticFieldAddress(
"System.Threading.Condition", "t_waiterForCurrentThread", thread, out outAddr))
.Returns(true);
waiterIdx++;
Comment on lines +3251 to +3252
if (_legacy is not null && fpCallback != 0)
List<ulong> dacThreads = new();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

missing opening brace?

// no sync block means no wait list
if (syncBlock != TargetPointer.Null
&& _target.Contracts.ManagedTypeSource.TryGetStaticFieldAddress(
"System.Threading.Monitor", "s_conditionTable", out TargetPointer conditionTableSlot))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wondering if we should put this in a contract to allow it to be versioned.

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