Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Henry <ludovic@xamarin.com>2017-06-17 04:01:51 +0300
committerGitHub <noreply@github.com>2017-06-17 04:01:51 +0300
commit6fc58f529b10f664c71bb301ed9d3524ed4e4f87 (patch)
treee34a8c4492372cc34a5140f94ff99f490ddfc22d
parent77a8ed1b39af8caa6da04163605ec40283942062 (diff)
[w32handle] Unify WaitHandle.Wait{One,Any,All} icalls (#5051)
-rw-r--r--mcs/class/Mono.Debugger.Soft/Test/dtest.cs2
-rw-r--r--mcs/class/corlib/System.Threading/WaitHandle.cs31
-rw-r--r--mono/metadata/icall-def.h6
-rw-r--r--mono/metadata/threads-types.h6
-rw-r--r--mono/metadata/threads.c156
5 files changed, 55 insertions, 146 deletions
diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
index 8d22ac808b2..7a16e5dcb83 100644
--- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
+++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
@@ -4145,7 +4145,7 @@ public class DebuggerTests
frames = thread.GetFrames ();
Assert.AreEqual (8, frames.Length, "#7");
- Assert.AreEqual ("WaitOne_internal", frames [0].Method.Name, "#8.0");
+ Assert.AreEqual ("Wait_internal", frames [0].Method.Name, "#8.0");
Assert.AreEqual ("WaitOneNative", frames [1].Method.Name, "#8.1");
Assert.AreEqual ("InternalWaitOne", frames [2].Method.Name, "#8.2");
Assert.AreEqual ("WaitOne", frames [3].Method.Name, "#8.3");
diff --git a/mcs/class/corlib/System.Threading/WaitHandle.cs b/mcs/class/corlib/System.Threading/WaitHandle.cs
index dd91330355e..0e16f046e80 100644
--- a/mcs/class/corlib/System.Threading/WaitHandle.cs
+++ b/mcs/class/corlib/System.Threading/WaitHandle.cs
@@ -49,6 +49,9 @@ namespace System.Threading
static int WaitMultiple(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext, bool WaitAll)
{
+ if (waitHandles.Length > MaxWaitHandles)
+ return WAIT_FAILED;
+
int release_last = -1;
try {
@@ -58,8 +61,7 @@ namespace System.Threading
#endif
for (int i = 0; i < waitHandles.Length; ++i) {
- try {
- } finally {
+ try {} finally {
/* we have to put it in a finally block, to avoid having a ThreadAbortException
* between the return from DangerousAddRef and the assignement to release_last */
bool release = false;
@@ -68,10 +70,14 @@ namespace System.Threading
}
}
- if (WaitAll)
- return WaitAll_internal (waitHandles, millisecondsTimeout);
- else
- return WaitAny_internal (waitHandles, millisecondsTimeout);
+ unsafe {
+ IntPtr* handles = stackalloc IntPtr[waitHandles.Length];
+
+ for (int i = 0; i < waitHandles.Length; ++i)
+ handles[i] = waitHandles[i].SafeWaitHandle.DangerousGetHandle ();
+
+ return Wait_internal(handles, waitHandles.Length, WaitAll, millisecondsTimeout);
+ }
} finally {
for (int i = release_last; i >= 0; --i) {
waitHandles [i].SafeWaitHandle.DangerousRelease ();
@@ -84,12 +90,6 @@ namespace System.Threading
}
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern int WaitAll_internal(WaitHandle[] handles, int ms);
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern int WaitAny_internal(WaitHandle[] handles, int ms);
-
static int WaitOneNative (SafeHandle waitableSafeHandle, uint millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
{
bool release = false;
@@ -101,7 +101,10 @@ namespace System.Threading
waitableSafeHandle.DangerousAddRef (ref release);
- return WaitOne_internal (waitableSafeHandle.DangerousGetHandle (), (int) millisecondsTimeout);
+ unsafe {
+ IntPtr handle = waitableSafeHandle.DangerousGetHandle();
+ return Wait_internal(&handle, 1, false, (int)millisecondsTimeout);
+ }
} finally {
if (release)
waitableSafeHandle.DangerousRelease ();
@@ -114,7 +117,7 @@ namespace System.Threading
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- static extern int WaitOne_internal(IntPtr handle, int ms);
+ unsafe static extern int Wait_internal(IntPtr* handles, int numHandles, bool waitAll, int ms);
static int SignalAndWaitOne (SafeWaitHandle waitHandleToSignal,SafeWaitHandle waitHandleToWaitOn, int millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
{
diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h
index a77e1a7c00e..64c806a05f6 100644
--- a/mono/metadata/icall-def.h
+++ b/mono/metadata/icall-def.h
@@ -1032,10 +1032,8 @@ ICALL(VOLATILE_25, "Write(uintptr&,uintptr)", ves_icall_System_Threading_Volatil
ICALL(VOLATILE_26, "Write(ulong&,ulong)", ves_icall_System_Threading_Volatile_Write8)
ICALL_TYPE(WAITH, "System.Threading.WaitHandle", WAITH_1)
-ICALL(WAITH_1, "SignalAndWait_Internal", ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal)
-ICALL(WAITH_2, "WaitAll_internal", ves_icall_System_Threading_WaitHandle_WaitAll_internal)
-ICALL(WAITH_3, "WaitAny_internal", ves_icall_System_Threading_WaitHandle_WaitAny_internal)
-ICALL(WAITH_4, "WaitOne_internal", ves_icall_System_Threading_WaitHandle_WaitOne_internal)
+HANDLES(ICALL(WAITH_1, "SignalAndWait_Internal", ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal))
+HANDLES(ICALL(WAITH_2, "Wait_internal", ves_icall_System_Threading_WaitHandle_Wait_internal))
ICALL_TYPE(TYPE, "System.Type", TYPE_1)
HANDLES(ICALL(TYPE_1, "internal_from_handle", ves_icall_System_Type_internal_from_handle))
diff --git a/mono/metadata/threads-types.h b/mono/metadata/threads-types.h
index 59d4856629b..257266e21b6 100644
--- a/mono/metadata/threads-types.h
+++ b/mono/metadata/threads-types.h
@@ -89,10 +89,8 @@ MonoObject* ves_icall_System_Threading_Thread_GetCachedCurrentUICulture (MonoInt
void ves_icall_System_Threading_Thread_SetCachedCurrentUICulture (MonoThread *this_obj, MonoObject *culture);
MonoThread *ves_icall_System_Threading_Thread_GetCurrentThread (void);
-gint32 ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_handles, gint32 ms);
-gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms);
-gint32 ves_icall_System_Threading_WaitHandle_WaitOne_internal(gpointer handle, gint32 ms);
-gint32 ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (gpointer toSignal, gpointer toWait, gint32 ms);
+gint32 ves_icall_System_Threading_WaitHandle_Wait_internal(gpointer *handles, gint32 numhandles, MonoBoolean waitall, gint32 ms, MonoError *error);
+gint32 ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (gpointer toSignal, gpointer toWait, gint32 ms, MonoError *error);
MonoArray* ves_icall_System_Threading_Thread_ByteArrayToRootDomain (MonoArray *arr);
MonoArray* ves_icall_System_Threading_Thread_ByteArrayToCurrentDomain (MonoArray *arr);
diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c
index 60848191ddc..da85ec6e9a0 100644
--- a/mono/metadata/threads.c
+++ b/mono/metadata/threads.c
@@ -1858,28 +1858,40 @@ map_native_wait_result_to_managed (MonoW32HandleWaitRet val, gsize numobjects)
}
}
-static MonoW32HandleWaitRet
-mono_wait_uninterrupted (MonoInternalThread *thread, guint32 numhandles, gpointer *handles, gboolean waitall, gint32 ms, MonoError *error)
+gint32
+ves_icall_System_Threading_WaitHandle_Wait_internal (gpointer *handles, gint32 numhandles, MonoBoolean waitall, gint32 timeout, MonoError *error)
{
- MonoException *exc;
MonoW32HandleWaitRet ret;
+ MonoInternalThread *thread;
+ MonoException *exc;
gint64 start;
- gint32 diff_ms;
- gint32 wait = ms;
+ guint32 timeoutLeft;
- error_init (error);
+ /* Do this WaitSleepJoin check before creating objects */
+ if (mono_thread_current_check_pending_interrupt ())
+ return map_native_wait_result_to_managed (MONO_W32HANDLE_WAIT_RET_FAILED, 0);
- start = (ms == -1) ? 0 : mono_100ns_ticks ();
- do {
+ thread = mono_thread_internal_current ();
+
+ mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
+
+ if (timeout == -1)
+ timeout = MONO_INFINITE_WAIT;
+ if (timeout != MONO_INFINITE_WAIT)
+ start = mono_msec_ticks ();
+
+ timeoutLeft = timeout;
+
+ for (;;) {
MONO_ENTER_GC_SAFE;
#ifdef HOST_WIN32
if (numhandles != 1)
- ret = mono_w32handle_convert_wait_ret (WaitForMultipleObjectsEx (numhandles, handles, waitall, wait, TRUE), numhandles);
+ ret = mono_w32handle_convert_wait_ret (WaitForMultipleObjectsEx (numhandles, handles, waitall, timeoutLeft, TRUE), numhandles);
else
- ret = mono_w32handle_convert_wait_ret (WaitForSingleObjectEx (handles [0], ms, TRUE), 1);
+ ret = mono_w32handle_convert_wait_ret (WaitForSingleObjectEx (handles [0], timeoutLeft, TRUE), 1);
#else
/* mono_w32handle_wait_multiple optimizes the case for numhandles == 1 */
- ret = mono_w32handle_wait_multiple (handles, numhandles, waitall, wait, TRUE);
+ ret = mono_w32handle_wait_multiple (handles, numhandles, waitall, timeoutLeft, TRUE);
#endif /* HOST_WIN32 */
MONO_EXIT_GC_SAFE;
@@ -1892,128 +1904,26 @@ mono_wait_uninterrupted (MonoInternalThread *thread, guint32 numhandles, gpointe
break;
}
- if (ms == -1)
- continue;
-
- /* Re-calculate ms according to the time passed */
- diff_ms = (gint32)((mono_100ns_ticks () - start) / 10000);
- if (diff_ms >= ms) {
- ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
- break;
- }
- wait = ms - diff_ms;
- } while (TRUE);
-
- return ret;
-}
-
-gint32 ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_handles, gint32 ms)
-{
- MonoError error;
- HANDLE *handles;
- guint32 numhandles;
- MonoW32HandleWaitRet ret;
- guint32 i;
- MonoObject *waitHandle;
- MonoInternalThread *thread = mono_thread_internal_current ();
-
- /* Do this WaitSleepJoin check before creating objects */
- if (mono_thread_current_check_pending_interrupt ())
- return map_native_wait_result_to_managed (MONO_W32HANDLE_WAIT_RET_FAILED, 0);
-
- /* We fail in managed if the array has more than 64 elements */
- numhandles = (guint32)mono_array_length(mono_handles);
- handles = g_new0(HANDLE, numhandles);
-
- for(i = 0; i < numhandles; i++) {
- waitHandle = mono_array_get(mono_handles, MonoObject*, i);
- handles [i] = mono_wait_handle_get_handle ((MonoWaitHandle *) waitHandle);
- }
-
- if(ms== -1) {
- ms=MONO_INFINITE_WAIT;
- }
-
- mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
-
- ret = mono_wait_uninterrupted (thread, numhandles, handles, TRUE, ms, &error);
-
- mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
-
- g_free(handles);
-
- mono_error_set_pending_exception (&error);
-
- return map_native_wait_result_to_managed (ret, numhandles);
-}
-
-gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms)
-{
- MonoError error;
- HANDLE handles [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
- uintptr_t numhandles;
- MonoW32HandleWaitRet ret;
- guint32 i;
- MonoObject *waitHandle;
- MonoInternalThread *thread = mono_thread_internal_current ();
-
- /* Do this WaitSleepJoin check before creating objects */
- if (mono_thread_current_check_pending_interrupt ())
- return map_native_wait_result_to_managed (MONO_W32HANDLE_WAIT_RET_FAILED, 0);
+ if (timeout != MONO_INFINITE_WAIT) {
+ gint64 elapsed;
- numhandles = mono_array_length(mono_handles);
- if (numhandles > MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS)
- return map_native_wait_result_to_managed (MONO_W32HANDLE_WAIT_RET_FAILED, 0);
+ elapsed = mono_msec_ticks () - start;
+ if (elapsed >= timeout) {
+ ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ break;
+ }
- for(i = 0; i < numhandles; i++) {
- waitHandle = mono_array_get(mono_handles, MonoObject*, i);
- handles [i] = mono_wait_handle_get_handle ((MonoWaitHandle *) waitHandle);
- }
-
- if(ms== -1) {
- ms=MONO_INFINITE_WAIT;
+ timeoutLeft = timeout - elapsed;
+ }
}
- mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
-
- ret = mono_wait_uninterrupted (thread, numhandles, handles, FALSE, ms, &error);
-
mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
- THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") returning %d", __func__, mono_native_thread_id_get (), ret));
-
- mono_error_set_pending_exception (&error);
-
return map_native_wait_result_to_managed (ret, numhandles);
}
-gint32 ves_icall_System_Threading_WaitHandle_WaitOne_internal(HANDLE handle, gint32 ms)
-{
- MonoError error;
- MonoW32HandleWaitRet ret;
- MonoInternalThread *thread = mono_thread_internal_current ();
-
- THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for %p, %d ms", __func__, mono_native_thread_id_get (), handle, ms));
-
- if(ms== -1) {
- ms=MONO_INFINITE_WAIT;
- }
-
- if (mono_thread_current_check_pending_interrupt ())
- return map_native_wait_result_to_managed (MONO_W32HANDLE_WAIT_RET_FAILED, 0);
-
- mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
-
- ret = mono_wait_uninterrupted (thread, 1, &handle, FALSE, ms, &error);
-
- mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
-
- mono_error_set_pending_exception (&error);
- return map_native_wait_result_to_managed (ret, 1);
-}
-
gint32
-ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, HANDLE toWait, gint32 ms)
+ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (gpointer toSignal, gpointer toWait, gint32 ms, MonoError *error)
{
MonoW32HandleWaitRet ret;
MonoInternalThread *thread = mono_thread_internal_current ();