Skip to content

Commit 10f6c4c

Browse files
Convert WaitHandle FCalls to QCalls (dotnet#107488)
1 parent b523ec5 commit 10f6c4c

File tree

7 files changed

+66
-91
lines changed

7 files changed

+66
-91
lines changed

src/coreclr/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Unix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public bool WaitCore(int timeoutMs)
3131
return waitResult == WaitHandle.WaitSuccess;
3232
}
3333

34-
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_CorWaitOnePrioritizedNative")]
34+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_WaitOnePrioritized")]
3535
private static partial int WaitNative(SafeWaitHandle handle, int timeoutMs);
3636

3737
private void ReleaseCore(int count)

src/coreclr/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,18 @@ namespace System.Threading
88
{
99
public abstract partial class WaitHandle
1010
{
11-
[MethodImpl(MethodImplOptions.InternalCall)]
12-
private static extern int WaitOneCore(IntPtr waitHandle, int millisecondsTimeout, bool useTrivialWaits);
11+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_WaitOneCore")]
12+
private static partial int WaitOneCore(IntPtr waitHandle, int millisecondsTimeout, [MarshalAs(UnmanagedType.Bool)] bool useTrivialWaits);
1313

1414
private static unsafe int WaitMultipleIgnoringSyncContextCore(ReadOnlySpan<IntPtr> waitHandles, bool waitAll, int millisecondsTimeout)
15-
{
16-
fixed (IntPtr* pWaitHandles = &MemoryMarshal.GetReference(waitHandles))
17-
{
18-
return WaitMultipleIgnoringSyncContext(pWaitHandles, waitHandles.Length, waitAll, millisecondsTimeout);
19-
}
20-
}
15+
=> WaitMultipleIgnoringSyncContext(waitHandles, waitHandles.Length, waitAll, millisecondsTimeout);
2116

22-
[MethodImpl(MethodImplOptions.InternalCall)]
23-
private static extern unsafe int WaitMultipleIgnoringSyncContext(IntPtr* waitHandles, int numHandles, bool waitAll, int millisecondsTimeout);
17+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_WaitMultipleIgnoringSyncContext")]
18+
private static partial int WaitMultipleIgnoringSyncContext(ReadOnlySpan<IntPtr> waitHandles, int numHandles, [MarshalAs(UnmanagedType.Bool)] bool waitAll, int millisecondsTimeout);
2419

2520
private static int SignalAndWaitCore(IntPtr waitHandleToSignal, IntPtr waitHandleToWaitOn, int millisecondsTimeout)
2621
{
27-
int ret = SignalAndWaitNative(waitHandleToSignal, waitHandleToWaitOn, millisecondsTimeout);
22+
int ret = SignalAndWait(waitHandleToSignal, waitHandleToWaitOn, millisecondsTimeout);
2823

2924
if (ret == Interop.Errors.ERROR_TOO_MANY_POSTS)
3025
{
@@ -34,7 +29,7 @@ private static int SignalAndWaitCore(IntPtr waitHandleToSignal, IntPtr waitHandl
3429
return ret;
3530
}
3631

37-
[MethodImpl(MethodImplOptions.InternalCall)]
38-
private static extern int SignalAndWaitNative(IntPtr waitHandleToSignal, IntPtr waitHandleToWaitOn, int millisecondsTimeout);
32+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "WaitHandle_SignalAndWait")]
33+
private static partial int SignalAndWait(IntPtr waitHandleToSignal, IntPtr waitHandleToWaitOn, int millisecondsTimeout);
3934
}
4035
}

src/coreclr/vm/comwaithandle.cpp

Lines changed: 43 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -11,106 +11,93 @@
1111
**
1212
===========================================================*/
1313
#include "common.h"
14-
#include "object.h"
15-
#include "field.h"
16-
#include "excep.h"
1714
#include "comwaithandle.h"
1815

19-
FCIMPL3(INT32, WaitHandleNative::CorWaitOneNative, HANDLE handle, INT32 timeout, FC_BOOL_ARG useTrivialWaits)
16+
extern "C" INT32 QCALLTYPE WaitHandle_WaitOneCore(HANDLE handle, INT32 timeout, BOOL useTrivialWaits)
2017
{
21-
FCALL_CONTRACT;
18+
QCALL_CONTRACT;
2219

2320
INT32 retVal = 0;
24-
HELPER_METHOD_FRAME_BEGIN_RET_0();
21+
22+
BEGIN_QCALL;
2523

2624
_ASSERTE(handle != 0);
2725
_ASSERTE(handle != INVALID_HANDLE_VALUE);
2826

2927
Thread* pThread = GET_THREAD();
30-
31-
WaitMode waitMode = (WaitMode)((!FC_ACCESS_BOOL(useTrivialWaits) ? WaitMode_Alertable : WaitMode_None) | WaitMode_IgnoreSyncCtx);
28+
WaitMode waitMode = (WaitMode)((!useTrivialWaits ? WaitMode_Alertable : WaitMode_None) | WaitMode_IgnoreSyncCtx);
3229
retVal = pThread->DoAppropriateWait(1, &handle, TRUE, timeout, waitMode);
3330

34-
HELPER_METHOD_FRAME_END();
31+
END_QCALL;
3532
return retVal;
3633
}
37-
FCIMPLEND
3834

39-
#ifdef TARGET_UNIX
40-
extern "C" INT32 QCALLTYPE WaitHandle_CorWaitOnePrioritizedNative(HANDLE handle, INT32 timeoutMs)
35+
extern "C" INT32 QCALLTYPE WaitHandle_WaitMultipleIgnoringSyncContext(HANDLE *handleArray, INT32 numHandles, BOOL waitForAll, INT32 timeout)
4136
{
4237
QCALL_CONTRACT;
4338

44-
DWORD result = WAIT_FAILED;
45-
46-
BEGIN_QCALL;
47-
48-
_ASSERTE(handle != NULL);
49-
_ASSERTE(handle != INVALID_HANDLE_VALUE);
50-
51-
result = PAL_WaitForSingleObjectPrioritized(handle, timeoutMs);
52-
53-
END_QCALL;
54-
return (INT32)result;
55-
}
56-
#endif
57-
58-
FCIMPL4(INT32, WaitHandleNative::CorWaitMultipleNative, HANDLE *handleArray, INT32 numHandles, FC_BOOL_ARG waitForAll, INT32 timeout)
59-
{
60-
FCALL_CONTRACT;
61-
6239
INT32 ret = 0;
63-
HELPER_METHOD_FRAME_BEGIN_RET_0();
40+
BEGIN_QCALL;
6441

6542
Thread * pThread = GET_THREAD();
6643

6744
#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
6845
// There are some issues with wait-all from an STA thread
6946
// - https://github.com/dotnet/runtime/issues/10243#issuecomment-385117537
70-
if (FC_ACCESS_BOOL(waitForAll) && numHandles > 1 && pThread->GetApartment() == Thread::AS_InSTA)
47+
if (waitForAll && numHandles > 1 && pThread->GetApartment() == Thread::AS_InSTA)
7148
{
7249
COMPlusThrow(kNotSupportedException, W("NotSupported_WaitAllSTAThread"));
7350
}
7451
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
7552

76-
ret = pThread->DoAppropriateWait(numHandles, handleArray, FC_ACCESS_BOOL(waitForAll), timeout, (WaitMode)(WaitMode_Alertable | WaitMode_IgnoreSyncCtx));
53+
ret = pThread->DoAppropriateWait(numHandles, handleArray, waitForAll, timeout, (WaitMode)(WaitMode_Alertable | WaitMode_IgnoreSyncCtx));
7754

78-
HELPER_METHOD_FRAME_END();
55+
END_QCALL;
7956
return ret;
8057
}
81-
FCIMPLEND
8258

83-
FCIMPL3(INT32, WaitHandleNative::CorSignalAndWaitOneNative, HANDLE waitHandleSignalUNSAFE, HANDLE waitHandleWaitUNSAFE, INT32 timeout)
59+
extern "C" INT32 QCALLTYPE WaitHandle_SignalAndWait(HANDLE waitHandleSignal, HANDLE waitHandleWait, INT32 timeout)
8460
{
85-
FCALL_CONTRACT;
61+
QCALL_CONTRACT;
8662

87-
INT32 retVal = 0;
63+
INT32 retVal = (DWORD)-1;
8864

89-
HELPER_METHOD_FRAME_BEGIN_RET_0();
65+
BEGIN_QCALL;
9066

91-
_ASSERTE(waitHandleSignalUNSAFE != 0);
92-
_ASSERTE(waitHandleWaitUNSAFE != 0);
67+
_ASSERTE(waitHandleSignal != 0);
68+
_ASSERTE(waitHandleWait != 0);
9369

9470
Thread* pThread = GET_THREAD();
9571

96-
#ifdef FEATURE_COMINTEROP
97-
if (pThread->GetApartment() == Thread::AS_InSTA) {
98-
COMPlusThrow(kNotSupportedException, W("NotSupported_SignalAndWaitSTAThread")); //<TODO> Change this message
99-
}
100-
#endif
101-
102-
DWORD res = (DWORD) -1;
103-
104-
HANDLE handles[2];
105-
handles[0] = waitHandleSignalUNSAFE;
106-
handles[1] = waitHandleWaitUNSAFE;
72+
#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
73+
if (pThread->GetApartment() == Thread::AS_InSTA)
10774
{
108-
res = pThread->DoSignalAndWait(handles, timeout, TRUE /*alertable*/);
75+
COMPlusThrow(kNotSupportedException, W("NotSupported_SignalAndWaitSTAThread"));
10976
}
77+
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
11078

111-
retVal = res;
79+
HANDLE handles[] = { waitHandleSignal, waitHandleWait };
80+
retVal = pThread->DoSignalAndWait(handles, timeout, TRUE /*alertable*/);
11281

113-
HELPER_METHOD_FRAME_END();
82+
END_QCALL;
11483
return retVal;
11584
}
116-
FCIMPLEND
85+
86+
#ifdef TARGET_UNIX
87+
extern "C" INT32 QCALLTYPE WaitHandle_WaitOnePrioritized(HANDLE handle, INT32 timeoutMs)
88+
{
89+
QCALL_CONTRACT;
90+
91+
DWORD result = WAIT_FAILED;
92+
93+
BEGIN_QCALL;
94+
95+
_ASSERTE(handle != NULL);
96+
_ASSERTE(handle != INVALID_HANDLE_VALUE);
97+
98+
result = PAL_WaitForSingleObjectPrioritized(handle, timeoutMs);
99+
100+
END_QCALL;
101+
return (INT32)result;
102+
}
103+
#endif // TARGET_UNIX

src/coreclr/vm/comwaithandle.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,12 @@
1414
#ifndef _COM_WAITABLE_HANDLE_H
1515
#define _COM_WAITABLE_HANDLE_H
1616

17+
extern "C" INT32 QCALLTYPE WaitHandle_WaitOneCore(HANDLE handle, INT32 timeout, BOOL useTrivialWaits);
18+
extern "C" INT32 QCALLTYPE WaitHandle_WaitMultipleIgnoringSyncContext(HANDLE *handleArray, INT32 numHandles, BOOL waitForAll, INT32 timeout);
19+
extern "C" INT32 QCALLTYPE WaitHandle_SignalAndWait(HANDLE waitHandleSignal, HANDLE waitHandleWait, INT32 timeout);
1720

18-
class WaitHandleNative
19-
{
20-
public:
21-
static FCDECL3(INT32, CorWaitOneNative, HANDLE handle, INT32 timeout, FC_BOOL_ARG useTrivialWaits);
22-
static FCDECL4(INT32, CorWaitMultipleNative, HANDLE *handleArray, INT32 numHandles, FC_BOOL_ARG waitForAll, INT32 timeout);
23-
static FCDECL3(INT32, CorSignalAndWaitOneNative, HANDLE waitHandleSignalUNSAFE, HANDLE waitHandleWaitUNSAFE, INT32 timeout);
24-
};
2521
#ifdef TARGET_UNIX
26-
extern "C" INT32 QCALLTYPE WaitHandle_CorWaitOnePrioritizedNative(HANDLE handle, INT32 timeoutMs);
27-
#endif
28-
#endif
22+
extern "C" INT32 QCALLTYPE WaitHandle_WaitOnePrioritized(HANDLE handle, INT32 timeoutMs);
23+
#endif // TARGET_UNIX
24+
25+
#endif // _COM_WAITABLE_HANDLE_H

src/coreclr/vm/ecalllist.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -313,12 +313,6 @@ FCFuncStart(gThreadPoolFuncs)
313313
FCFuncElement("GetNextConfigUInt32Value", ThreadPoolNative::GetNextConfigUInt32Value)
314314
FCFuncEnd()
315315

316-
FCFuncStart(gWaitHandleFuncs)
317-
FCFuncElement("WaitOneCore", WaitHandleNative::CorWaitOneNative)
318-
FCFuncElement("WaitMultipleIgnoringSyncContext", WaitHandleNative::CorWaitMultipleNative)
319-
FCFuncElement("SignalAndWaitNative", WaitHandleNative::CorSignalAndWaitOneNative)
320-
FCFuncEnd()
321-
322316
FCFuncStart(gCastHelpers)
323317
FCFuncElement("IsInstanceOfAny_NoCacheLookup", ::IsInstanceOfAny_NoCacheLookup)
324318
FCFuncElement("ChkCastAny_NoCacheLookup", ::ChkCastAny_NoCacheLookup)
@@ -493,7 +487,6 @@ FCClassElement("Thread", "System.Threading", gThreadFuncs)
493487
FCClassElement("ThreadPool", "System.Threading", gThreadPoolFuncs)
494488
FCClassElement("Type", "System", gSystem_Type)
495489
FCClassElement("TypedReference", "System", gTypedReferenceFuncs)
496-
FCClassElement("WaitHandle", "System.Threading", gWaitHandleFuncs)
497490

498491
#undef FCFuncElement
499492
#undef FCFuncElementSig

src/coreclr/vm/qcallentrypoints.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,12 @@ static const Entry s_QCall[] =
252252
#ifdef FEATURE_COMINTEROP
253253
DllImportEntry(ThreadNative_DisableComObjectEagerCleanup)
254254
#endif // FEATURE_COMINTEROP
255+
DllImportEntry(WaitHandle_WaitOneCore)
256+
DllImportEntry(WaitHandle_WaitMultipleIgnoringSyncContext)
257+
DllImportEntry(WaitHandle_SignalAndWait)
255258
#ifdef TARGET_UNIX
256-
DllImportEntry(WaitHandle_CorWaitOnePrioritizedNative)
257-
#endif
259+
DllImportEntry(WaitHandle_WaitOnePrioritized)
260+
#endif // TARGET_UNIX
258261
DllImportEntry(ClrConfig_GetConfigBoolValue)
259262
DllImportEntry(Buffer_Clear)
260263
DllImportEntry(Buffer_MemMove)

src/coreclr/vm/threads.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3116,14 +3116,14 @@ DWORD MsgWaitHelper(int numWaiters, HANDLE* phEvent, BOOL bWaitAll, DWORD millis
31163116
// want true WAIT_ALL, we need to fire up a different thread in the MTA and wait
31173117
// on its result. This isn't implemented yet.
31183118
//
3119-
// A change was added to WaitHandleNative::CorWaitMultipleNative to disable WaitAll
3119+
// A change was added to WaitHandle_WaitMultipleIgnoringSyncContext to disable WaitAll
31203120
// in an STA with more than one handle.
31213121
if (bWaitAll)
31223122
{
31233123
if (numWaiters == 1)
31243124
bWaitAll = FALSE;
31253125

3126-
// The check that's supposed to prevent this condition from occurring, in WaitHandleNative::CorWaitMultipleNative,
3126+
// The check that's supposed to prevent this condition from occurring, in WaitHandle_WaitMultipleIgnoringSyncContext,
31273127
// is unfortunately behind FEATURE_COMINTEROP instead of FEATURE_COMINTEROP_APARTMENT_SUPPORT.
31283128
// So on CoreCLR (where FEATURE_COMINTEROP is not currently defined) we can actually reach this point.
31293129
// We can't fix this, because it's a breaking change, so we just won't assert here.

0 commit comments

Comments
 (0)