Skip to content

Move CoreCLR over to the managed wait subsystem #117788

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

Draft
wants to merge 47 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
02db598
Start working on porting shared mutexes to managed in a line-by-line …
jkoritzinsky Jul 9, 2025
b855928
Fill out a lot of the rest of the logic.
jkoritzinsky Jul 9, 2025
9ec79b8
Finish filling in the holes in the shared memory impl.
jkoritzinsky Jul 10, 2025
74d6db7
Fix process-level lock handling
jkoritzinsky Jul 10, 2025
ab7b688
Split into two files and fill out other entrypoints
jkoritzinsky Jul 10, 2025
5c59aad
Move the named mutex impl to a runtime that has the wait subsystem.
jkoritzinsky Jul 10, 2025
40ec2d7
Finish integrating with the wait subsystem entry points and bring bac…
jkoritzinsky Jul 10, 2025
4904eb7
Enable tests
jkoritzinsky Jul 10, 2025
194ea40
Fix various problems found by tests and adjust locking to actually wo…
jkoritzinsky Jul 12, 2025
6495e44
Adjust PThread setting default based on testing with our cross-build …
jkoritzinsky Jul 14, 2025
189a71e
Handle EOWNERDEAD
jkoritzinsky Jul 14, 2025
7cfb931
Add stubs to wasi
jkoritzinsky Jul 14, 2025
69fe72f
Don't use cross-process mutexes on mobile platforms. Only use the in-…
jkoritzinsky Jul 14, 2025
ee0f7ce
Move the whole "shared data" struct for the pthread mutex impl across…
jkoritzinsky Jul 14, 2025
9787f15
Do a little cleanup
jkoritzinsky Jul 14, 2025
bce3af6
Remove unused member
jkoritzinsky Jul 14, 2025
36bd5c0
Cleanup projitems
jkoritzinsky Jul 14, 2025
182c57a
Cleanup libraries pal a little
jkoritzinsky Jul 14, 2025
61aabd4
Rename and split out the "unsupported" impl
jkoritzinsky Jul 15, 2025
ba0ecc2
Rename as requested
jkoritzinsky Jul 17, 2025
a2d9121
Remove unused AcquirePthreadMutexWithTimeout impl
jkoritzinsky Jul 17, 2025
0cfacc1
Fix failure on the "unsupported" path
jkoritzinsky Jul 17, 2025
5cbaa62
Add arg references.
jkoritzinsky Jul 18, 2025
05cecb6
Use the correct API for locking with a specific clock.
jkoritzinsky Jul 19, 2025
e4d595d
Mark noreturn for debug builds to satisfy compiler
jkoritzinsky Jul 21, 2025
d1dca10
Allow abandonment from the finalizer thread. Sometimes we can only cl…
jkoritzinsky Jul 24, 2025
1c7c39d
Add timeout for one test that was missing it. Fix named mutex tests o…
jkoritzinsky Jul 25, 2025
e23ccc5
Fix CoreCLR and NAOT builds
jkoritzinsky Jul 25, 2025
510efcf
Refactor how named mutex ownership is tracked for abandonment to make…
jkoritzinsky Jul 25, 2025
895af9e
Update comsynchronizable.cpp
jkoritzinsky Jul 25, 2025
4e80270
Use a Mutex for process-level locking in the no-pthreads implementati…
jkoritzinsky Jul 29, 2025
79c7812
PR feedback
jkoritzinsky Jul 29, 2025
625b8d6
Do a little bit of cleanup on formatting
jkoritzinsky Jul 29, 2025
bccae1d
Various build fixes
jkoritzinsky Jul 29, 2025
0d764fd
Don't release when abandoning as we don't know our thread and we can'…
jkoritzinsky Jul 30, 2025
c5f32cb
Remove unintended whitespace change
jkoritzinsky Jul 30, 2025
47bd54c
Fix indent
jkoritzinsky Jul 30, 2025
dda0121
Use the wait subsystem on CoreCLR on Unix platforms.
jkoritzinsky Jul 14, 2025
72ad939
Remove wait subsystem qcall entrypoints
jkoritzinsky Jul 15, 2025
7cc7b2b
Remove named mutex support from the CoreCLR PAL
jkoritzinsky Jul 15, 2025
34c2c42
Fix qcalls and managed/native sizes
jkoritzinsky Jul 21, 2025
f0be4c2
Unify LowLevelLifoSemaphore implementations for Unix to use the wait …
jkoritzinsky Jul 21, 2025
14c8a8c
Hook up the "thread exiting" callback
jkoritzinsky Jul 22, 2025
d1d8344
Delete Mutex support from the PAL
jkoritzinsky Jul 29, 2025
d87f635
Remove concept of ownership and abandonment and other vistigial compo…
jkoritzinsky Jul 29, 2025
32c9e60
Change spinlock scoping
jkoritzinsky Jul 29, 2025
63a1aa6
Remove prioritized waits from the PAL and remove WAIT_ABANDONED usage
jkoritzinsky Jul 29, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,6 @@
<Compile Include="$(BclSourcesRoot)\System\Threading\Monitor.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Thread.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\WaitHandle.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Type.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\TypedReference.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\TypeLoadException.CoreCLR.cs" />
Expand Down Expand Up @@ -290,8 +289,6 @@
<ItemGroup Condition="'$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true'" >
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\InMemoryAssemblyLoader.PlatformNotSupported.cs" />
<Compile Include="$(BclSourcesRoot)\Interop\Unix\Interop.Libraries.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\LowLevelLifoSemaphore.Unix.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Mutex.CoreCLR.Unix.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\InMemoryAssemblyLoader.cs" />
Expand All @@ -301,6 +298,7 @@
<Compile Include="$(CommonPath)Interop\Windows\OleAut32\Interop.VariantChangeTypeEx.cs">
<Link>Common\Interop\Windows\OleAut32\Interop.VariantChangeTypeEx.cs</Link>
</Compile>
<Compile Include="$(BclSourcesRoot)\System\Threading\WaitHandle.CoreCLR.Windows.cs" />
</ItemGroup>
<ItemGroup Condition="'$(FeatureObjCMarshal)' == 'true'">
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ObjectiveCMarshal.CoreCLR.cs" />
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public sealed partial class Thread
private string? _name;
private StartHelper? _startHelper;

#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI
internal WaitSubsystem.ThreadWaitInfo? _waitInfo;
#endif

/*=========================================================================
** The base implementation of Thread is all native. The following fields
** should never be used in the C# code. They are here to define the proper
Expand Down Expand Up @@ -298,6 +302,30 @@ public ThreadState ThreadState
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_GetThreadState")]
private static partial int GetThreadState(ThreadHandle t);

#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI
internal void SetWaitSleepJoinState()
{
// This method is called when the thread is about to enter a wait, sleep, or join state.
// It sets the state in the native layer to indicate that the thread is waiting.
SetWaitSleepJoinState(GetNativeHandle());
GC.KeepAlive(this);
}

internal void ClearWaitSleepJoinState()
{
// This method is called when the thread is no longer in a wait, sleep, or join state.
// It clears the state in the native layer to indicate that the thread is no longer waiting.
ClearWaitSleepJoinState(GetNativeHandle());
GC.KeepAlive(this);
}

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_SetWaitSleepJoinState")]
private static partial void SetWaitSleepJoinState(ThreadHandle t);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_ClearWaitSleepJoinState")]
private static partial void ClearWaitSleepJoinState(ThreadHandle t);
#endif

/// <summary>
/// An unstarted thread can be marked to indicate that it will host a
/// single-threaded or multi-threaded apartment.
Expand Down Expand Up @@ -513,6 +541,35 @@ private static void PollGC()
static void PollGCWorker() => PollGCInternal();
}

#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI
internal WaitSubsystem.ThreadWaitInfo WaitInfo
{
get
{
return Volatile.Read(ref _waitInfo) ?? AllocateWaitInfo();

WaitSubsystem.ThreadWaitInfo AllocateWaitInfo()
{
Interlocked.CompareExchange(ref _waitInfo, new WaitSubsystem.ThreadWaitInfo(this), null!);
return _waitInfo;
}
}
}
#endif

private void OnThreadExiting()
{
#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI
// Inform the wait subsystem that the thread is exiting. For instance, this would abandon any mutexes locked by
// the thread.
_waitInfo?.OnThreadExiting();
#endif
}

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_CurrentThreadIsFinalizerThread")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool CurrentThreadIsFinalizerThread();

[StructLayout(LayoutKind.Sequential)]
private struct NativeThreadClass
{
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/dlls/mscordac/mscordac_unixexports.src
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ nativeStringResourceTable_mscorrc
#CreateFileMappingW
#CreateFileA
#CreateFileW
#CreateMutexW
#CreateMutexExW
#CreateEventW
#CreateEventExW
#CreateProcessW
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/nativeaot/Runtime/FinalizerHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,9 @@ FCIMPL0(OBJECTREF, RhpGetNextFinalizableObject)
}
}
FCIMPLEND

FCIMPL0(FC_BOOL_RET, RhpCurrentThreadIsFinalizerThread)
{
FC_RETURN_BOOL(ThreadStore::GetCurrentThread() == g_pFinalizerThread);
}
FCIMPLEND
Original file line number Diff line number Diff line change
Expand Up @@ -294,23 +294,16 @@
<Compile Include="System\Environment.NativeAot.Unix.cs" />
<Compile Include="System\Runtime\InteropServices\NativeLibrary.NativeAot.Unix.cs" />
<Compile Include="System\Runtime\InteropServices\PInvokeMarshal.Unix.cs" />
<Compile Include="System\Threading\LowLevelLifoSemaphore.Unix.cs" />
<Compile Include="System\Threading\Thread.NativeAot.Unix.cs" />
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Abort.cs">
<Link>Interop\Unix\System.Native\Interop.Abort.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Exit.cs">
<Link>Interop\Unix\System.Native\Interop.Exit.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.MMap.cs">
<Link>Interop\Unix\System.Native\Interop.MMap.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.MProtect.cs">
<Link>Interop\Unix\System.Native\Interop.MProtect.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.MUnmap.cs">
<Link>Interop\Unix\System.Native\Interop.MUnmap.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="$(CompilerCommonPath)\System\Collections\Generic\ArrayBuilder.cs">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ internal static void RhWaitForPendingFinalizers(bool allowReentrantWait)
RhWaitForPendingFinalizers(allowReentrantWait ? 1 : 0);
}

[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpCurrentThreadIsFinalizerThread")]
internal static extern bool RhpCurrentThreadIsFinalizerThread();

// Get maximum GC generation number.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhGetMaxGcGeneration")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,5 +517,10 @@ internal static void WaitForForegroundThreads()
}
s_allDone.WaitOne();
}

internal static bool CurrentThreadIsFinalizerThread()
{
return RuntimeImports.RhpCurrentThreadIsFinalizerThread();
}
}
}
Loading
Loading