Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/coreclr/vm/syncblk.inl
Original file line number Diff line number Diff line change
Expand Up @@ -632,10 +632,10 @@ FORCEINLINE AwareLock::EnterHelperResult ObjHeader::EnterObjMonitorHelper(Thread
return AwareLock::EnterHelperResult_Contention;
}

// The header is transitioning - treat this as if the lock was taken
// The header is transitioning - use the slow path
if (oldValue & BIT_SBLK_SPIN_LOCK)
{
return AwareLock::EnterHelperResult_Contention;
return AwareLock::EnterHelperResult_UseSlowPath;
}

// Here we know we have the "thin lock" layout, but the lock is not free.
Expand Down
30 changes: 30 additions & 0 deletions src/libraries/System.Threading/tests/MonitorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -456,5 +456,35 @@ public static void Enter_HasToWait_LockContentionCountTest()
Enter_HasToWait();
Assert.True(Monitor.LockContentionCount - initialLockContentionCount >= 2);
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
public static void ObjectHeaderSyncBlockTransitionTryEnterRaceTest()
{
var threadStarted = new AutoResetEvent(false);
var startTest = new AutoResetEvent(false);
var obj = new object();
var t = ThreadTestHelpers.CreateGuardedThread(out _, () =>
{
threadStarted.Set();
startTest.CheckedWait();
Monitor.TryEnter(obj, 100); // likely to perform a full wait, which may involve some sort of transition
});
t.IsBackground = true;
t.Start();
threadStarted.CheckedWait();

lock (obj)
{
startTest.Set();
do
{
for (int i = 0; i < 1000; i++)
{
Assert.True(Monitor.TryEnter(obj)); // this could race with the transition happening on the other thread
Monitor.Exit(obj);
}
} while (!t.Join(0));
}
}
}
}