Skip to content

Commit 6791d05

Browse files
authored
Port some CoreRT Threading classes to Mono (#47333)
1 parent 2b55b10 commit 6791d05

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+970
-10365
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Runtime.InteropServices;
5+
6+
internal partial class Interop
7+
{
8+
internal partial class Kernel32
9+
{
10+
[DllImport(Libraries.Kernel32)]
11+
[SuppressGCTransition]
12+
internal static extern int GetLastError();
13+
}
14+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.Win32.SafeHandles;
5+
using System;
6+
using System.Runtime.InteropServices;
7+
8+
internal static partial class Interop
9+
{
10+
internal static partial class Kernel32
11+
{
12+
internal const int WAIT_FAILED = unchecked((int)0xFFFFFFFF);
13+
14+
[DllImport(Libraries.Kernel32)]
15+
internal static extern uint WaitForMultipleObjectsEx(uint nCount, IntPtr lpHandles, BOOL bWaitAll, uint dwMilliseconds, BOOL bAlertable);
16+
17+
[DllImport(Libraries.Kernel32)]
18+
internal static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
19+
20+
[DllImport(Libraries.Kernel32)]
21+
internal static extern uint SignalObjectAndWait(IntPtr hObjectToSignal, IntPtr hObjectToWaitOn, uint dwMilliseconds, BOOL bAlertable);
22+
23+
[DllImport(Libraries.Kernel32)]
24+
internal static extern void Sleep(uint milliseconds);
25+
26+
internal const uint CREATE_SUSPENDED = 0x00000004;
27+
internal const uint STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000;
28+
29+
[DllImport(Libraries.Kernel32)]
30+
internal static extern unsafe SafeWaitHandle CreateThread(
31+
IntPtr lpThreadAttributes,
32+
IntPtr dwStackSize,
33+
delegate* unmanaged<IntPtr, uint> lpStartAddress,
34+
IntPtr lpParameter,
35+
uint dwCreationFlags,
36+
out uint lpThreadId);
37+
38+
[DllImport(Libraries.Kernel32)]
39+
internal static extern uint ResumeThread(SafeWaitHandle hThread);
40+
41+
[DllImport(Libraries.Kernel32)]
42+
internal static extern IntPtr GetCurrentThread();
43+
44+
internal const int DUPLICATE_SAME_ACCESS = 2;
45+
46+
[DllImport(Libraries.Kernel32, SetLastError = true)]
47+
internal static extern bool DuplicateHandle(
48+
IntPtr hSourceProcessHandle,
49+
IntPtr hSourceHandle,
50+
IntPtr hTargetProcessHandle,
51+
out SafeWaitHandle lpTargetHandle,
52+
uint dwDesiredAccess,
53+
bool bInheritHandle,
54+
uint dwOptions);
55+
56+
internal enum ThreadPriority : int
57+
{
58+
Idle = -15,
59+
Lowest = -2,
60+
BelowNormal = -1,
61+
Normal = 0,
62+
AboveNormal = 1,
63+
Highest = 2,
64+
TimeCritical = 15,
65+
66+
ErrorReturn = 0x7FFFFFFF
67+
}
68+
69+
[DllImport(Libraries.Kernel32)]
70+
internal static extern ThreadPriority GetThreadPriority(SafeWaitHandle hThread);
71+
72+
[DllImport(Libraries.Kernel32)]
73+
internal static extern bool SetThreadPriority(SafeWaitHandle hThread, int nPriority);
74+
}
75+
}

src/libraries/System.IO.IsolatedStorage/tests/AssemblyInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
// create unique identities for every test to allow every test to have
99
// it's own store.
1010
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)]
11+
[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/48720", TestPlatforms.AnyUnix, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
1112
[assembly: SkipOnMono("System.IO.IsolatedStorage is not supported on Browser", TestPlatforms.Browser)]

src/libraries/System.Private.CoreLib/src/Resources/Strings.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2998,6 +2998,9 @@
29982998
<data name="Overflow_Int64" xml:space="preserve">
29992999
<value>Value was either too large or too small for an Int64.</value>
30003000
</data>
3001+
<data name="Overflow_MutexReacquireCount" xml:space="preserve">
3002+
<value>The current thread attempted to reacquire a mutex that has reached its maximum acquire count.</value>
3003+
</data>
30013004
<data name="Overflow_NegateTwosCompNum" xml:space="preserve">
30023005
<value>Negating the minimum value of a twos complement number is invalid.</value>
30033006
</data>
@@ -3577,6 +3580,9 @@
35773580
<data name="InvalidOperation_InvalidComUnRegFunctionSig" xml:space="preserve">
35783581
<value>COM unregister function must have a System.Type parameter and a void return type.</value>
35793582
</data>
3583+
<data name="InvalidOperation_InvalidHandle" xml:space="preserve">
3584+
<value>The handle is invalid.</value>
3585+
</data>
35803586
<data name="InvalidOperation_MultipleComRegFunctions" xml:space="preserve">
35813587
<value>Type '{0}' has more than one COM registration function.</value>
35823588
</data>

src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,4 +1980,24 @@
19801980
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\LowLevelLifoSemaphore.Windows.cs" Condition="'$(TargetsWindows)' == 'true'" />
19811981
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\RegisteredWaitHandle.Portable.cs" />
19821982
</ItemGroup>
1983+
<ItemGroup Condition="'$(FeatureCoreCLR)' != 'true' and ('$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true')">
1984+
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeWaitHandle.Unix.cs" />
1985+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\EventWaitHandle.Unix.cs" />
1986+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Mutex.Unix.cs" />
1987+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Semaphore.Unix.cs" />
1988+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitHandle.Unix.cs" />
1989+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitSubsystem.HandleManager.Unix.cs" />
1990+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitSubsystem.ThreadWaitInfo.Unix.cs" />
1991+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitSubsystem.Unix.cs" />
1992+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitSubsystem.WaitableObject.Unix.cs" />
1993+
</ItemGroup>
1994+
<ItemGroup Condition="'$(FeatureCoreCLR)' != 'true' and '$(TargetsWindows)' == 'true'">
1995+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitHandle.Windows.cs" />
1996+
<Compile Include="$(CommonPath)\Interop\Windows\Kernel32\Interop.GetLastError.cs">
1997+
<Link>Interop\Windows\Kernel32\Interop.GetLastError.cs</Link>
1998+
</Compile>
1999+
<Compile Include="$(CommonPath)\Interop\Windows\Kernel32\Interop.Threading.cs">
2000+
<Link>Interop\Windows\Kernel32\Interop.Threading.cs</Link>
2001+
</Compile>
2002+
</ItemGroup>
19832003
</Project>

src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeHandle.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,13 @@ public void DangerousAddRef(ref bool success)
161161
success = true;
162162
}
163163

164+
// Used by internal callers to avoid declaring a bool to pass by ref
165+
internal void DangerousAddRef()
166+
{
167+
bool success = false;
168+
DangerousAddRef(ref success);
169+
}
170+
164171
public void DangerousRelease() => InternalRelease(disposeOrFinalizeOperation: false);
165172

166173
private void InternalRelease(bool disposeOrFinalizeOperation)

src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace System.Threading
1010
{
1111
public partial class EventWaitHandle
1212
{
13-
private void CreateEventCore(bool initialState, EventResetMode mode, string name, out bool createdNew)
13+
private void CreateEventCore(bool initialState, EventResetMode mode, string? name, out bool createdNew)
1414
{
1515
if (name != null)
1616
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
@@ -19,7 +19,7 @@ private void CreateEventCore(bool initialState, EventResetMode mode, string name
1919
createdNew = true;
2020
}
2121

22-
private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle result)
22+
private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle? result)
2323
{
2424
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
2525
}

src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Unix.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,19 @@ private void WaitCore()
4444
Interop.Sys.LowLevelMonitor_Wait(_nativeMonitor);
4545
}
4646

47+
private bool WaitCore(int timeoutMilliseconds)
48+
{
49+
Debug.Assert(timeoutMilliseconds >= -1);
50+
51+
if (timeoutMilliseconds < 0)
52+
{
53+
WaitCore();
54+
return true;
55+
}
56+
57+
return Interop.Sys.LowLevelMonitor_TimedWait(_nativeMonitor, timeoutMilliseconds);
58+
}
59+
4760
private void Signal_ReleaseCore()
4861
{
4962
Interop.Sys.LowLevelMonitor_Signal_Release(_nativeMonitor);

src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,16 @@ public void Wait()
9090
SetOwnerThreadToCurrent();
9191
}
9292

93+
public bool Wait(int timeoutMilliseconds)
94+
{
95+
Debug.Assert(timeoutMilliseconds >= -1);
96+
97+
ResetOwnerThread();
98+
bool waitResult = WaitCore(timeoutMilliseconds);
99+
SetOwnerThreadToCurrent();
100+
return waitResult;
101+
}
102+
93103
public void Signal_Release()
94104
{
95105
ResetOwnerThread();

src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ namespace System.Threading
1010
{
1111
public sealed partial class Mutex
1212
{
13-
private void CreateMutexCore(bool initiallyOwned, string name, out bool createdNew)
13+
private void CreateMutexCore(bool initiallyOwned, string? name, out bool createdNew)
1414
{
15+
// See https://github.com/dotnet/runtime/issues/48720
1516
if (name != null)
1617
{
1718
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
@@ -21,7 +22,7 @@ private void CreateMutexCore(bool initiallyOwned, string name, out bool createdN
2122
createdNew = true;
2223
}
2324

24-
private static OpenExistingResult OpenExistingWorker(string name, out Mutex result)
25+
private static OpenExistingResult OpenExistingWorker(string name, out Mutex? result)
2526
{
2627
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
2728
}

src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace System.Threading
1010
{
1111
public sealed partial class Semaphore
1212
{
13-
private void CreateSemaphoreCore(int initialCount, int maximumCount, string name, out bool createdNew)
13+
private void CreateSemaphoreCore(int initialCount, int maximumCount, string? name, out bool createdNew)
1414
{
1515
if (name != null)
1616
{
@@ -21,7 +21,7 @@ private void CreateSemaphoreCore(int initialCount, int maximumCount, string name
2121
createdNew = true;
2222
}
2323

24-
private static OpenExistingResult OpenExistingWorker(string name, out Semaphore result)
24+
private static OpenExistingResult OpenExistingWorker(string name, out Semaphore? result)
2525
{
2626
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
2727
}

0 commit comments

Comments
 (0)