Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 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
8ff75cd
Various PR feedback
jkoritzinsky Aug 6, 2025
c17aec2
Make CurrentThreadIsFinalizerThread an FCall on CoreCLR and share code
jkoritzinsky Aug 8, 2025
875eb1a
Remove qcall entrypoint
jkoritzinsky Aug 8, 2025
5e28e5a
Add missing using
jkoritzinsky Aug 8, 2025
a18d6c8
Apply suggestions from code review
jkoritzinsky Aug 11, 2025
12936de
Adjust code to pass new tests being added in another PR
jkoritzinsky Aug 14, 2025
747eaad
Fix name for NAOT import
jkoritzinsky Aug 14, 2025
d5960a7
Use Environment.SystemPageSize
jkoritzinsky Aug 14, 2025
fb49a22
Merge branch 'main' of https://github.com/dotnet/runtime into shared-…
jkoritzinsky Aug 15, 2025
a9d94ff
Fix test for slashes in name
jkoritzinsky Aug 15, 2025
029d73b
Use existing PlatformDetection options for named mutex feature detection
jkoritzinsky Aug 15, 2025
5331532
PR feedback
jkoritzinsky Aug 18, 2025
ca516d7
Apply suggestions from code review
jkoritzinsky Aug 18, 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
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 @@ -302,15 +302,9 @@
<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
8 changes: 8 additions & 0 deletions src/coreclr/vm/comsynchronizable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -899,3 +899,11 @@ extern "C" void QCALLTYPE ThreadNative_ResetAbort()
pThread->UnmarkThreadForAbort(EEPolicy::TA_Safe);
}
}

FCIMPL0(FC_BOOL_RET, ThreadNative::CurrentThreadIsFinalizerThread)
{
FCALL_CONTRACT;

FC_RETURN_BOOL(IsFinalizerThread());
}
FCIMPLEND
1 change: 1 addition & 0 deletions src/coreclr/vm/comsynchronizable.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class ThreadNative
static FCDECL0(INT32, GetOptimalMaxSpinWaitsPerSpinIteration);
static FCDECL1(void, Finalize, ThreadBaseObject* pThis);
static FCDECL0(FC_BOOL_RET, CatchAtSafePoint);
static FCDECL0(FC_BOOL_RET, CurrentThreadIsFinalizerThread);
};

extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, BOOL isThreadPool, PCWSTR pThreadName);
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ FCFuncEnd()
FCFuncStart(gThreadFuncs)
FCFuncElement("InternalFinalize", ThreadNative::Finalize)
FCFuncElement("CatchAtSafePoint", ThreadNative::CatchAtSafePoint)
FCFuncElement("CurrentThreadIsFinalizerThread", ThreadNative::CurrentThreadIsFinalizerThread)
FCFuncElement("get_OptimalMaxSpinWaitsPerSpinIteration", ThreadNative::GetOptimalMaxSpinWaitsPerSpinIteration)
FCFuncEnd()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static unsafe partial class Sys
{
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_LowLevelCrossProcessMutex_Init", SetLastError = true)]
internal static partial int LowLevelCrossProcessMutex_Init(void* mutex);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_LowLevelCrossProcessMutex_Acquire", SetLastError = true)]
internal static partial int LowLevelCrossProcessMutex_Acquire(void* mutex, int timeoutMilliseconds);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_LowLevelCrossProcessMutex_Release", SetLastError = true)]
internal static partial int LowLevelCrossProcessMutex_Release(void* mutex);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_LowLevelCrossProcessMutex_Destroy", SetLastError = true)]
internal static partial int LowLevelCrossProcessMutex_Destroy(void* mutex);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_LowLevelCrossProcessMutex_Size")]
[SuppressGCTransition]
internal static partial int LowLevelCrossProcessMutex_Size();

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_LowLevelCrossProcessMutex_GetOwnerProcessAndThreadId", SetLastError = true)]
[SuppressGCTransition]
internal static partial void LowLevelCrossProcessMutex_GetOwnerProcessAndThreadId(void* mutex, out uint processId, out uint threadId);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_LowLevelCrossProcessMutex_SetOwnerProcessAndThreadId", SetLastError = true)]
[SuppressGCTransition]
internal static partial void LowLevelCrossProcessMutex_SetOwnerProcessAndThreadId(void* mutex, uint processId, uint threadId);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_LowLevelCrossProcessMutex_IsAbandoned", SetLastError = true)]
[SuppressGCTransition]
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool LowLevelCrossProcessMutex_IsAbandoned(void* mutex);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_LowLevelCrossProcessMutex_SetAbandoned", SetLastError = true)]
[SuppressGCTransition]
internal static partial void LowLevelCrossProcessMutex_SetAbandoned(void* mutex, [MarshalAs(UnmanagedType.U1)] bool abandoned);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public static partial class PlatformDetection
public static bool IsNotMonoAOT => Environment.GetEnvironmentVariable("MONO_AOT_MODE") != "aot";
public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported;
public static bool IsNotNativeAot => !IsNativeAot;
public static bool IsCoreCLR => IsNotMonoRuntime && IsNotNativeAot;
public static bool IsFreeBSD => RuntimeInformation.IsOSPlatform(OSPlatform.Create("FREEBSD"));
public static bool IsNetBSD => RuntimeInformation.IsOSPlatform(OSPlatform.Create("NETBSD"));
public static bool IsAndroid => RuntimeInformation.IsOSPlatform(OSPlatform.Create("ANDROID"));
Expand Down
29 changes: 29 additions & 0 deletions src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -4387,5 +4387,34 @@
</data>
<data name="PlatformNotSupported_DynamicEntrypoint" xml:space="preserve">
<value>Dynamic entrypoint allocation is not supported in the current environment.</value>
</data> <data name="Arg_InvalidOperationException_CannotReleaseUnownedMutex" xml:space="preserve">
<value>Cannot release a lock that is not owned by the current thread.</value>
</data>
<data name="Arg_FailedToInitializePThreadMutex" xml:space="preserve">
<value>Failed to initialize pthread mutex</value>
</data>
<data name="IO_SharedMemory_InvalidHeader" xml:space="preserve">
<value>Cross-process shared memory file '{0}' has a header that is not supported by this version of the .NET runtime.</value>
</data>
<data name="IO_SharedMemory_FileNotOwnedByUid" xml:space="preserve">
<value>The file '{0}' is not owned by the current user with UID {1}.</value>
</data>
<data name="IO_SharedMemory_FilePermissionsIncorrect" xml:space="preserve">
<value>The file '{0}' does not have the expected permissions for user scope: {1}.</value>
</data>
<data name="IO_SharedMemory_PathExistsButNotDirectory" xml:space="preserve">
<value>The path '{0}' exists but is not a directory.</value>
</data>
<data name="IO_SharedMemory_DirectoryPermissionsIncorrect" xml:space="preserve">
<value>The directory '{0}' does not have the expected owner or permissions for system scope: {1}, {2}.</value>
</data>
<data name="IO_SharedMemory_DirectoryNotOwnedByUid" xml:space="preserve">
<value>The directory '{0}' is not owned by the current user with UID {1}.</value>
</data>
<data name="IO_SharedMemory_DirectoryPermissionsIncorrectUserScope" xml:space="preserve">
<value>The directory '{0}' does not have the expected permissions for user scope: {1}.</value>
</data>
<data name="IO_SharedMemory_DirectoryOwnerPermissionsIncorrect" xml:space="preserve">
<value>The directory '{0}' does not have the expected owner permissions: {1}.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<Is64Bit Condition="'$(Platform)' == 'arm64' or '$(Platform)' == 'x64' or '$(Platform)' == 's390x' or '$(Platform)' == 'loongarch64' or '$(Platform)' == 'ppc64le' or '$(Platform)' == 'riscv64'">true</Is64Bit>
<UseMinimalGlobalizationData Condition="'$(TargetsBrowser)' == 'true' or '$(TargetsWasi)' == 'true'">true</UseMinimalGlobalizationData>
<EnableLibraryImportGenerator>true</EnableLibraryImportGenerator>
<FeatureCrossProcessMutex Condition="'$(IsMobileLike)' != 'true'">true</FeatureCrossProcessMutex>
</PropertyGroup>
<PropertyGroup>
<DefineConstants Condition="'$(IsBigEndian)' == 'true'">$(DefineConstants);BIGENDIAN</DefineConstants>
Expand All @@ -49,6 +50,9 @@
<DefineConstants Condition="'$(TargetsSolaris)' == 'true'">$(DefineConstants);TARGET_SOLARIS</DefineConstants>
<DefineConstants Condition="'$(TargetsHaiku)' == 'true'">$(DefineConstants);TARGET_HAIKU</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<DefineConstants Condition="'$(FeatureCrossProcessMutex)' == 'true'">$(DefineConstants);FEATURE_CROSS_PROCESS_MUTEX</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ApiCompatSuppressionFile Include="$(MSBuildThisFileDirectory)CompatibilitySuppressions.xml" />
</ItemGroup>
Expand Down Expand Up @@ -2463,6 +2467,12 @@
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.MksTemps.cs">
<Link>Common\Interop\Unix\System.Native\Interop.MksTemps.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.MMap.cs">
<Link>Common\Interop\Unix\System.Native\Interop.MMap.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.MUnmap.cs">
<Link>Common\Interop\Unix\System.Native\Interop.MUnmap.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.MountPoints.cs">
<Link>Common\Interop\Unix\System.Native\Interop.MountPoints.cs</Link>
</Compile>
Expand Down Expand Up @@ -2622,6 +2632,9 @@
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetPid.cs">
<Link>Common\Interop\Unix\System.Native\Interop.GetPid.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetSid.cs">
<Link>Common\Interop\Unix\System.Native\Interop.GetSid.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\FreeBSD\Interop.Process.GetProcInfo.cs" Condition="'$(TargetsFreeBSD)' == 'true'" Link="Common\Interop\FreeBSD\Interop.Process.GetProcInfo.cs" />
<Compile Include="$(CommonPath)Interop\BSD\System.Native\Interop.Sysctl.cs" Condition="'$(TargetsFreeBSD)' == 'true'" Link="Common\Interop\BSD\System.Native\Interop.Sysctl.cs" />
<Compile Include="$(CommonPath)Interop\Linux\procfs\Interop.ProcFsStat.TryReadStatusFile.cs" Condition="'$(TargetsLinux)' == 'true'" Link="Common\Interop\Linux\Interop.ProcFsStat.TryReadStatusFile.cs" />
Expand Down Expand Up @@ -2844,6 +2857,13 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitSubsystem.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitSubsystem.WaitableObject.Unix.cs" />
</ItemGroup>
<ItemGroup Condition="'$(FeatureCoreCLR)' != 'true' and '$(TargetsUnix)' == 'true' and '$(FeatureCrossProcessMutex)' == 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\IO\SharedMemoryManager.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\NamedMutex.Unix.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.LowLevelCrossProcessMutex.cs">
<Link>Common\Interop\Unix\System.Native\Interop.LowLevelCrossProcessMutex.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(FeatureCoreCLR)' != 'true' and '$(TargetsWindows)' == 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitHandle.Windows.cs" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ private static void EnsureUserDirectories()

// In initialization conditions, however, the "HOME" environment variable may
// not yet be set. For such cases, consult with the password entry.
return GetHomeDirectoryFromPasswd();
}

internal static string GetHomeDirectoryFromPasswd()
{
unsafe
{
// First try with a buffer that should suffice for 99% of cases.
Expand All @@ -65,8 +70,8 @@ private static void EnsureUserDirectories()
// what to do.
const int BufLen = Interop.Sys.Passwd.InitialBufferSize;
byte* stackBuf = stackalloc byte[BufLen];
if (TryGetHomeDirectoryFromPasswd(stackBuf, BufLen, out userHomeDirectory))
return userHomeDirectory;
if (TryGetHomeDirectoryFromPasswd(stackBuf, BufLen, out string? userHomeDirectory))
return userHomeDirectory!;

// Fallback to heap allocations if necessary, growing the buffer until
// we succeed. TryGetHomeDirectory will throw if there's an unexpected error.
Expand All @@ -78,7 +83,7 @@ private static void EnsureUserDirectories()
fixed (byte* buf = &heapBuf[0])
{
if (TryGetHomeDirectoryFromPasswd(buf, heapBuf.Length, out userHomeDirectory))
return userHomeDirectory;
return userHomeDirectory!;
}
}
}
Expand Down
Loading
Loading