summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorFilip Navara <filip.navara@gmail.com>2019-02-25 18:28:46 +0100
committerJan Kotas <jkotas@microsoft.com>2019-02-25 09:28:46 -0800
commitcf85f56e473b6cdc4a68e9758f57dc571e14c9cb (patch)
treee1f319aadb12338392f6e5586091ead93fd71843 /src/vm
parent5ffa6ecefe6b1dcd2418ce7a5524f367e7f865f0 (diff)
downloadcoreclr-cf85f56e473b6cdc4a68e9758f57dc571e14c9cb.tar.gz
coreclr-cf85f56e473b6cdc4a68e9758f57dc571e14c9cb.tar.bz2
coreclr-cf85f56e473b6cdc4a68e9758f57dc571e14c9cb.zip
Move WaitHandle to shared CoreLib (#22634)
* Move part of WaitHandle to shared CoreLib * Bring back OpenExistingResult to fix build * Move reminder of WaitHandle to shared, implement SynchronizationContext logic in managed code, handle SafeHandle referencing in managed code * Update with changes neeeded for CoreRT * Span -> ReadOnlySpan * Remove dead code * Fix SafeHandle error handling * Avoid double check on input values in WaitHandle.WaitOne overloads * Make OpenExistingResult private protected instead of internal * Make WaitHandle._waitHandle private * Code style fixes * Remove unnecessary GC.KeepAlive * Move ERROR_TOO_MANY_POSTS exception handling to CoreCLR specific code * Add cache for wait arrays to match previous CoreRT behavior and reduce GC pressure, change unmanaged code to allocate small array on stack * Address PR feedback * Reduce allocations/copying by moving stack allocation to managed code * Address PR feedback * Minor code reshuffle * Move thread local access close to each other * Address code style feedback * Add const to Wait* constants
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/comwaithandle.cpp162
-rw-r--r--src/vm/comwaithandle.h7
-rw-r--r--src/vm/ecalllist.h7
3 files changed, 36 insertions, 140 deletions
diff --git a/src/vm/comwaithandle.cpp b/src/vm/comwaithandle.cpp
index abb1daf16b..d6c7da37aa 100644
--- a/src/vm/comwaithandle.cpp
+++ b/src/vm/comwaithandle.cpp
@@ -78,37 +78,6 @@ private:
}
};
-void AcquireSafeHandleFromWaitHandle(WAITHANDLEREF wh)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(wh != NULL);
- } CONTRACTL_END;
-
- SAFEHANDLEREF sh = wh->GetSafeHandle();
- if (sh == NULL)
- COMPlusThrow(kObjectDisposedException);
- sh->AddRef();
-}
-
-void ReleaseSafeHandleFromWaitHandle(WAITHANDLEREF wh)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(wh != NULL);
- } CONTRACTL_END;
-
- SAFEHANDLEREF sh = wh->GetSafeHandle();
- _ASSERTE(sh);
- sh->Release();
-}
-
-typedef ObjArrayHolder<WAITHANDLEREF, AcquireSafeHandleFromWaitHandle, ReleaseSafeHandleFromWaitHandle> WaitHandleArrayHolder;
-
INT64 AdditionalWait(INT64 sPauseTime, INT64 sTime, INT64 expDuration)
{
LIMITED_METHOD_CONTRACT;
@@ -157,91 +126,58 @@ INT64 AdditionalWait(INT64 sPauseTime, INT64 sTime, INT64 expDuration)
return additional;
}
-FCIMPL3(INT32, WaitHandleNative::CorWaitOneNative, SafeHandle* safeWaitHandleUNSAFE, INT32 timeout, CLR_BOOL exitContext)
+FCIMPL2(INT32, WaitHandleNative::CorWaitOneNative, HANDLE handle, INT32 timeout)
{
FCALL_CONTRACT;
INT32 retVal = 0;
- SAFEHANDLEREF sh(safeWaitHandleUNSAFE);
- HELPER_METHOD_FRAME_BEGIN_RET_1(sh);
+ HELPER_METHOD_FRAME_BEGIN_RET_0();
- _ASSERTE(sh != NULL);
+ _ASSERTE(handle != 0);
+ _ASSERTE(handle != INVALID_HANDLE_VALUE);
Thread* pThread = GET_THREAD();
DWORD res = (DWORD) -1;
- SafeHandleHolder shh(&sh);
- // Note that SafeHandle is a GC object, and RequestCallback and
- // DoAppropriateWait work on an array of handles. Don't pass the address
- // of the handle field - that's a GC hole. Instead, pass this temp
- // array.
- HANDLE handles[1];
- handles[0] = sh->GetHandle();
+ // Support for pause/resume (FXFREEZE)
+ while(true)
{
- // Support for pause/resume (FXFREEZE)
- while(true)
- {
- INT64 sPauseTime = g_PauseTime;
- INT64 sTime = CLRGetTickCount64();
- res = pThread->DoAppropriateWait(1,handles,TRUE,timeout, WaitMode_Alertable /*alertable*/);
- if(res != WAIT_TIMEOUT)
- break;
- timeout = (INT32)AdditionalWait(sPauseTime, sTime, timeout);
- if(timeout == 0)
- break;
- }
+ INT64 sPauseTime = g_PauseTime;
+ INT64 sTime = CLRGetTickCount64();
+ res = pThread->DoAppropriateWait(1, &handle, TRUE, timeout, (WaitMode)(WaitMode_Alertable | WaitMode_IgnoreSyncCtx));
+ if(res != WAIT_TIMEOUT)
+ break;
+ timeout = (INT32)AdditionalWait(sPauseTime, sTime, timeout);
+ if(timeout == 0)
+ break;
}
retVal = res;
-
HELPER_METHOD_FRAME_END();
return retVal;
}
FCIMPLEND
-FCIMPL4(INT32, WaitHandleNative::CorWaitMultipleNative, Object* waitObjectsUNSAFE, INT32 timeout, CLR_BOOL exitContext, CLR_BOOL waitForAll)
+FCIMPL4(INT32, WaitHandleNative::CorWaitMultipleNative, HANDLE *handleArray, INT32 numHandles, CLR_BOOL waitForAll, INT32 timeout)
{
FCALL_CONTRACT;
- INT32 retVal = 0;
- OBJECTREF waitObjects = (OBJECTREF) waitObjectsUNSAFE;
- HELPER_METHOD_FRAME_BEGIN_RET_1(waitObjects);
-
- _ASSERTE(waitObjects);
-
- Thread* pThread = GET_THREAD();
+ INT32 ret = 0;
+ HELPER_METHOD_FRAME_BEGIN_RET_0();
- PTRARRAYREF pWaitObjects = (PTRARRAYREF)waitObjects; // array of objects on which to wait
- int numWaiters = pWaitObjects->GetNumComponents();
+ Thread * pThread = GET_THREAD();
#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
// There are some issues with wait-all from an STA thread
// - https://github.com/dotnet/coreclr/issues/17787#issuecomment-385117537
- if (waitForAll && numWaiters > 1 && pThread->GetApartment() == Thread::AS_InSTA)
+ if (waitForAll && numHandles > 1 && pThread->GetApartment() == Thread::AS_InSTA)
{
COMPlusThrow(kNotSupportedException, W("NotSupported_WaitAllSTAThread"));
}
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
- WaitHandleArrayHolder arrayHolder;
- arrayHolder.Initialize(numWaiters, (PTRARRAYREF*) &waitObjects);
-
- pWaitObjects = (PTRARRAYREF)waitObjects; // array of objects on which to wait
- HANDLE* internalHandles = (HANDLE*) _alloca(numWaiters*sizeof(HANDLE));
- for (int i=0;i<numWaiters;i++)
- {
- WAITHANDLEREF waitObject = (WAITHANDLEREF) pWaitObjects->m_Array[i];
- _ASSERTE(waitObject != NULL);
-
- //If the size of the array is 1 and handle is INVALID_HANDLE_VALUE then WaitForMultipleObjectsEx will
- // return ERROR_INVALID_HANDLE but DoAppropriateWait will convert to WAIT_OBJECT_0. i.e Success,
- // this behavior seems wrong but someone explicitly coded that condition so it must have been for a reason.
- internalHandles[i] = waitObject->GetWaitHandle();
-
- }
-
DWORD res = (DWORD) -1;
{
// Support for pause/resume (FXFREEZE)
@@ -249,7 +185,7 @@ FCIMPL4(INT32, WaitHandleNative::CorWaitMultipleNative, Object* waitObjectsUNSAF
{
INT64 sPauseTime = g_PauseTime;
INT64 sTime = CLRGetTickCount64();
- res = pThread->DoAppropriateWait(numWaiters, internalHandles, waitForAll, timeout, WaitMode_Alertable /*alertable*/);
+ res = pThread->DoAppropriateWait(numHandles, handleArray, waitForAll, timeout, (WaitMode)(WaitMode_Alertable | WaitMode_IgnoreSyncCtx));
if(res != WAIT_TIMEOUT)
break;
timeout = (INT32)AdditionalWait(sPauseTime, sTime, timeout);
@@ -258,30 +194,23 @@ FCIMPL4(INT32, WaitHandleNative::CorWaitMultipleNative, Object* waitObjectsUNSAF
}
}
-
- retVal = res;
-
+ ret = res;
+
HELPER_METHOD_FRAME_END();
- return retVal;
+ return ret;
}
FCIMPLEND
-FCIMPL4(INT32, WaitHandleNative::CorSignalAndWaitOneNative, SafeHandle* safeWaitHandleSignalUNSAFE,SafeHandle* safeWaitHandleWaitUNSAFE, INT32 timeout, CLR_BOOL exitContext)
+FCIMPL3(INT32, WaitHandleNative::CorSignalAndWaitOneNative, HANDLE waitHandleSignalUNSAFE, HANDLE waitHandleWaitUNSAFE, INT32 timeout)
{
FCALL_CONTRACT;
INT32 retVal = 0;
- SAFEHANDLEREF shSignal(safeWaitHandleSignalUNSAFE);
- SAFEHANDLEREF shWait(safeWaitHandleWaitUNSAFE);
- HELPER_METHOD_FRAME_BEGIN_RET_2(shSignal,shWait);
-
- if(shSignal == NULL || shWait == NULL)
- COMPlusThrow(kObjectDisposedException);
-
- _ASSERTE(safeWaitHandleSignalUNSAFE != NULL);
- _ASSERTE( safeWaitHandleWaitUNSAFE != NULL);
+ HELPER_METHOD_FRAME_BEGIN_RET_0();
+ _ASSERTE(waitHandleSignalUNSAFE != 0);
+ _ASSERTE(waitHandleWaitUNSAFE != 0);
Thread* pThread = GET_THREAD();
@@ -293,47 +222,16 @@ FCIMPL4(INT32, WaitHandleNative::CorSignalAndWaitOneNative, SafeHandle* safeWait
DWORD res = (DWORD) -1;
- SafeHandleHolder shhSignal(&shSignal);
- SafeHandleHolder shhWait(&shWait);
- // Don't pass the address of the handle field
- // - that's a GC hole. Instead, pass this temp array.
HANDLE handles[2];
- handles[0] = shSignal->GetHandle();
- handles[1] = shWait->GetHandle();
+ handles[0] = waitHandleSignalUNSAFE;
+ handles[1] = waitHandleWaitUNSAFE;
{
- res = pThread->DoSignalAndWait(handles,timeout,TRUE /*alertable*/);
+ res = pThread->DoSignalAndWait(handles, timeout, TRUE /*alertable*/);
}
-
retVal = res;
HELPER_METHOD_FRAME_END();
return retVal;
}
FCIMPLEND
-
-FCIMPL3(DWORD, WaitHandleNative::WaitHelper, PTRArray *handleArrayUNSAFE, CLR_BOOL waitAll, DWORD millis)
-{
- FCALL_CONTRACT;
-
- DWORD ret = 0;
-
- PTRARRAYREF handleArrayObj = (PTRARRAYREF) handleArrayUNSAFE;
- HELPER_METHOD_FRAME_BEGIN_RET_1(handleArrayObj);
-
- CQuickArray<HANDLE> qbHandles;
- int cHandles = handleArrayObj->GetNumComponents();
-
- // Since DoAppropriateWait could cause a GC, we need to copy the handles to an unmanaged block
- // of memory to ensure they aren't relocated during the call to DoAppropriateWait.
- qbHandles.AllocThrows(cHandles);
- memcpy(qbHandles.Ptr(), handleArrayObj->GetDataPtr(), cHandles * sizeof(HANDLE));
-
- Thread * pThread = GetThread();
- ret = pThread->DoAppropriateWait(cHandles, qbHandles.Ptr(), waitAll, millis,
- (WaitMode)(WaitMode_Alertable | WaitMode_IgnoreSyncCtx));
-
- HELPER_METHOD_FRAME_END();
- return ret;
-}
-FCIMPLEND
diff --git a/src/vm/comwaithandle.h b/src/vm/comwaithandle.h
index 816af13e9b..218446881a 100644
--- a/src/vm/comwaithandle.h
+++ b/src/vm/comwaithandle.h
@@ -19,9 +19,8 @@
class WaitHandleNative
{
public:
- static FCDECL3(INT32, CorWaitOneNative, SafeHandle* safeWaitHandleUNSAFE, INT32 timeout, CLR_BOOL exitContext);
- static FCDECL4(INT32, CorWaitMultipleNative, Object* waitObjectsUNSAFE, INT32 timeout, CLR_BOOL exitContext, CLR_BOOL waitForAll);
- static FCDECL4(INT32, CorSignalAndWaitOneNative, SafeHandle* safeWaitHandleSignalUNSAFE, SafeHandle* safeWaitHandleWaitUNSAFE, INT32 timeout, CLR_BOOL exitContext);
- static FCDECL3(DWORD, WaitHelper, PTRArray *handleArrayUNSAFE, CLR_BOOL waitAll, DWORD millis);
+ static FCDECL2(INT32, CorWaitOneNative, HANDLE handle, INT32 timeout);
+ static FCDECL4(INT32, CorWaitMultipleNative, HANDLE *handleArray, INT32 numHandles, CLR_BOOL waitForAll, INT32 timeout);
+ static FCDECL3(INT32, CorSignalAndWaitOneNative, HANDLE waitHandleSignalUNSAFE, HANDLE waitHandleWaitUNSAFE, INT32 timeout);
};
#endif
diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h
index cc07d0e570..30492d1512 100644
--- a/src/vm/ecalllist.h
+++ b/src/vm/ecalllist.h
@@ -689,10 +689,9 @@ FCFuncStart(gRegisteredWaitHandleFuncs)
FCFuncEnd()
FCFuncStart(gWaitHandleFuncs)
- FCFuncElement("WaitOneNative", WaitHandleNative::CorWaitOneNative)
- FCFuncElement("WaitMultiple", WaitHandleNative::CorWaitMultipleNative)
- FCFuncElement("SignalAndWaitOne", WaitHandleNative::CorSignalAndWaitOneNative)
- FCFuncElement("WaitMultipleIgnoringSyncContext", WaitHandleNative::WaitHelper)
+ FCFuncElement("WaitOneCore", WaitHandleNative::CorWaitOneNative)
+ FCFuncElement("WaitMultipleIgnoringSyncContext", WaitHandleNative::CorWaitMultipleNative)
+ FCFuncElement("SignalAndWaitNative", WaitHandleNative::CorSignalAndWaitOneNative)
FCFuncEnd()
#ifdef FEATURE_COMINTEROP