From: Ludovic Henry Date: Mon, 28 Nov 2016 19:55:09 +0000 (-0500) Subject: [io-layer] Extract WaitForSingleObjectEx, WaitForMultipleObjectsEx and SignalObjectAn... X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=7e79a9cdb005f67998614940b3ce8e54717ca6dc;p=mono.git [io-layer] Extract WaitForSingleObjectEx, WaitForMultipleObjectsEx and SignalObjectAndWait --- diff --git a/mono/io-layer/Makefile.am b/mono/io-layer/Makefile.am index 934ed07b729..2262281abaa 100644 --- a/mono/io-layer/Makefile.am +++ b/mono/io-layer/Makefile.am @@ -56,7 +56,6 @@ OTHER_SRC = \ uglify.h \ versioninfo.c \ versioninfo.h \ - wait.c \ wait.h \ wapi_glob.h \ wapi_glob.c \ diff --git a/mono/io-layer/wait.c b/mono/io-layer/wait.c deleted file mode 100644 index b7ff4684263..00000000000 --- a/mono/io-layer/wait.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * wait.c: wait for handles to become signalled - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002-2006 Novell, Inc. - */ - -#include -#include -#include -#include - -#include -#include -#include - -/** - * WaitForSingleObjectEx: - * @handle: an object to wait for - * @timeout: the maximum time in milliseconds to wait for - * @alertable: if TRUE, the wait can be interrupted by an APC call - * - * This function returns when either @handle is signalled, or @timeout - * ms elapses. If @timeout is zero, the object's state is tested and - * the function returns immediately. If @timeout is %INFINITE, the - * function waits forever. - * - * Return value: %WAIT_ABANDONED - @handle is a mutex that was not - * released by the owning thread when it exited. Ownership of the - * mutex object is granted to the calling thread and the mutex is set - * to nonsignalled. %WAIT_OBJECT_0 - The state of @handle is - * signalled. %WAIT_TIMEOUT - The @timeout interval elapsed and - * @handle's state is still not signalled. %WAIT_FAILED - an error - * occurred. %WAIT_IO_COMPLETION - the wait was ended by an APC. - */ -guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, gboolean alertable) -{ - MonoW32HandleWaitRet ret; - - ret = mono_w32handle_wait_one (handle, timeout, alertable); - if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0) - return WAIT_OBJECT_0; - else if (ret == MONO_W32HANDLE_WAIT_RET_ABANDONED_0) - return WAIT_ABANDONED_0; - else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED) - return WAIT_IO_COMPLETION; - else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT) - return WAIT_TIMEOUT; - else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED) - return WAIT_FAILED; - else - g_error ("%s: unknown ret value %d", __func__, ret); -} - - -/** - * SignalObjectAndWait: - * @signal_handle: An object to signal - * @wait: An object to wait for - * @timeout: The maximum time in milliseconds to wait for - * @alertable: Specifies whether the function returnes when the system - * queues an I/O completion routine or an APC for the calling thread. - * - * Atomically signals @signal and waits for @wait to become signalled, - * or @timeout ms elapses. If @timeout is zero, the object's state is - * tested and the function returns immediately. If @timeout is - * %INFINITE, the function waits forever. - * - * @signal can be a semaphore, mutex or event object. - * - * If @alertable is %TRUE and the system queues an I/O completion - * routine or an APC for the calling thread, the function returns and - * the thread calls the completion routine or APC function. If - * %FALSE, the function does not return, and the thread does not call - * the completion routine or APC function. A completion routine is - * queued when the ReadFileEx() or WriteFileEx() function in which it - * was specified has completed. The calling thread is the thread that - * initiated the read or write operation. An APC is queued when - * QueueUserAPC() is called. Currently completion routines and APC - * functions are not supported. - * - * Return value: %WAIT_ABANDONED - @wait is a mutex that was not - * released by the owning thread when it exited. Ownershop of the - * mutex object is granted to the calling thread and the mutex is set - * to nonsignalled. %WAIT_IO_COMPLETION - the wait was ended by one - * or more user-mode asynchronous procedure calls queued to the - * thread. %WAIT_OBJECT_0 - The state of @wait is signalled. - * %WAIT_TIMEOUT - The @timeout interval elapsed and @wait's state is - * still not signalled. %WAIT_FAILED - an error occurred. - */ -guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait, - guint32 timeout, gboolean alertable) -{ - MonoW32HandleWaitRet ret; - - ret = mono_w32handle_signal_and_wait (signal_handle, wait, timeout, alertable); - if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0) - return WAIT_OBJECT_0; - else if (ret == MONO_W32HANDLE_WAIT_RET_ABANDONED_0) - return WAIT_ABANDONED_0; - else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED) - return WAIT_IO_COMPLETION; - else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT) - return WAIT_TIMEOUT; - else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED) - return WAIT_FAILED; - else - g_error ("%s: unknown ret value %d", __func__, ret); -} - -/** - * WaitForMultipleObjectsEx: - * @numobjects: The number of objects in @handles. The maximum allowed - * is %MAXIMUM_WAIT_OBJECTS. - * @handles: An array of object handles. Duplicates are not allowed. - * @waitall: If %TRUE, this function waits until all of the handles - * are signalled. If %FALSE, this function returns when any object is - * signalled. - * @timeout: The maximum time in milliseconds to wait for. - * @alertable: if TRUE, the wait can be interrupted by an APC call - * - * This function returns when either one or more of @handles is - * signalled, or @timeout ms elapses. If @timeout is zero, the state - * of each item of @handles is tested and the function returns - * immediately. If @timeout is %INFINITE, the function waits forever. - * - * Return value: %WAIT_OBJECT_0 to %WAIT_OBJECT_0 + @numobjects - 1 - - * if @waitall is %TRUE, indicates that all objects are signalled. If - * @waitall is %FALSE, the return value minus %WAIT_OBJECT_0 indicates - * the first index into @handles of the objects that are signalled. - * %WAIT_ABANDONED_0 to %WAIT_ABANDONED_0 + @numobjects - 1 - if - * @waitall is %TRUE, indicates that all objects are signalled, and at - * least one object is an abandoned mutex object (See - * WaitForSingleObject() for a description of abandoned mutexes.) If - * @waitall is %FALSE, the return value minus %WAIT_ABANDONED_0 - * indicates the first index into @handles of an abandoned mutex. - * %WAIT_TIMEOUT - The @timeout interval elapsed and no objects in - * @handles are signalled. %WAIT_FAILED - an error occurred. - * %WAIT_IO_COMPLETION - the wait was ended by an APC. - */ -guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, - gboolean waitall, guint32 timeout, - gboolean alertable) -{ - MonoW32HandleWaitRet ret; - - ret = mono_w32handle_wait_multiple (handles, numobjects, waitall, timeout, alertable); - if (ret >= MONO_W32HANDLE_WAIT_RET_SUCCESS_0 && ret <= MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + numobjects - 1) - return WAIT_OBJECT_0 + (ret - MONO_W32HANDLE_WAIT_RET_SUCCESS_0); - else if (ret >= MONO_W32HANDLE_WAIT_RET_ABANDONED_0 && ret <= MONO_W32HANDLE_WAIT_RET_ABANDONED_0 + numobjects - 1) - return WAIT_ABANDONED_0 + (ret - MONO_W32HANDLE_WAIT_RET_ABANDONED_0); - else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED) - return WAIT_IO_COMPLETION; - else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT) - return WAIT_TIMEOUT; - else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED) - return WAIT_FAILED; - else - g_error ("%s: unknown ret value %d", __func__, ret); -} - diff --git a/mono/io-layer/wait.h b/mono/io-layer/wait.h index cbbf5d68203..b470c2d6f23 100644 --- a/mono/io-layer/wait.h +++ b/mono/io-layer/wait.h @@ -26,12 +26,5 @@ G_BEGIN_DECLS #define WAIT_TIMEOUT STATUS_TIMEOUT #define WAIT_IO_COMPLETION STATUS_USER_APC -extern guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, - gboolean alertable); -extern guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait, - guint32 timeout, gboolean alertable); -extern guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, - gboolean waitall, guint32 timeout, gboolean alertable); - G_END_DECLS #endif /* _WAPI_WAIT_H_ */ diff --git a/mono/io-layer/wapi-remap.h b/mono/io-layer/wapi-remap.h index b19465c7c68..c106ee767c1 100644 --- a/mono/io-layer/wapi-remap.h +++ b/mono/io-layer/wapi-remap.h @@ -63,8 +63,5 @@ #define GetFileVersionInfo wapi_GetFileVersionInfo #define VerQueryValue wapi_VerQueryValue #define VerLanguageName wapi_VerLanguageName -#define WaitForSingleObjectEx wapi_WaitForSingleObjectEx -#define SignalObjectAndWait wapi_SignalObjectAndWait -#define WaitForMultipleObjectsEx wapi_WaitForMultipleObjectsEx #endif /* __WAPI_REMAP_H__ */ diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index aed903cc6a9..51c5eebb056 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/mono/metadata/monitor.c b/mono/metadata/monitor.c index 1d9ff1b8acc..f11c9589b82 100644 --- a/mono/metadata/monitor.c +++ b/mono/metadata/monitor.c @@ -1294,7 +1294,7 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms) MonoThreadsSync *mon; HANDLE event; guint32 nest; - guint32 ret; + MonoW32HandleWaitRet ret; gboolean success = FALSE; gint32 regain; MonoInternalThread *thread = mono_thread_internal_current (); @@ -1350,7 +1350,11 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms) * signalled before we wait, we still succeed. */ MONO_ENTER_GC_SAFE; - ret = WaitForSingleObjectEx (event, ms, TRUE); +#ifdef HOST_WIN32 + ret = mono_w32handle_convert_wait_ret (WaitForSingleObjectEx (event, ms, TRUE), 1); +#else + ret = mono_w32handle_wait_one (event, ms, TRUE); +#endif /* HOST_WIN32 */ MONO_EXIT_GC_SAFE; /* Reset the thread state fairly early, so we don't have to worry @@ -1370,12 +1374,16 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms) LOCK_DEBUG (g_message ("%s: (%d) Regained %p lock %p", __func__, mono_thread_info_get_small_id (), obj, mon)); - if (ret == WAIT_TIMEOUT) { + if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT) { /* Poll the event again, just in case it was signalled * while we were trying to regain the monitor lock */ MONO_ENTER_GC_SAFE; - ret = WaitForSingleObjectEx (event, 0, FALSE); +#ifdef HOST_WIN32 + ret = mono_w32handle_convert_wait_ret (WaitForSingleObjectEx (event, 0, FALSE), 1); +#else + ret = mono_w32handle_wait_one (event, 0, FALSE); +#endif /* HOST_WIN32 */ MONO_EXIT_GC_SAFE; } @@ -1389,7 +1397,7 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms) * thread. */ - if (ret == WAIT_OBJECT_0) { + if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0) { LOCK_DEBUG (g_message ("%s: (%d) Success", __func__, mono_thread_info_get_small_id ())); success = TRUE; } else { diff --git a/mono/metadata/threadpool-ms.c b/mono/metadata/threadpool-ms.c index f042e176294..43444211fe4 100644 --- a/mono/metadata/threadpool-ms.c +++ b/mono/metadata/threadpool-ms.c @@ -1443,7 +1443,11 @@ mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, Mono } mono_monitor_exit ((MonoObject*) ares); MONO_ENTER_GC_SAFE; +#ifdef HOST_WIN32 WaitForSingleObjectEx (wait_event, INFINITE, TRUE); +#else + mono_w32handle_wait_one (wait_event, INFINITE, TRUE); +#endif MONO_EXIT_GC_SAFE; } diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index b0aad20a5c9..a779e4a07a4 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -1664,17 +1664,29 @@ ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms) #define MANAGED_WAIT_FAILED 0x7fffffff static gint32 -map_native_wait_result_to_managed (gint32 val) -{ - /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */ - return val == WAIT_FAILED ? MANAGED_WAIT_FAILED : val; +map_native_wait_result_to_managed (MonoW32HandleWaitRet val, gsize numobjects) +{ + if (val >= MONO_W32HANDLE_WAIT_RET_SUCCESS_0 && val < MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + numobjects) { + return WAIT_OBJECT_0 + (val - MONO_W32HANDLE_WAIT_RET_SUCCESS_0); + } else if (val >= MONO_W32HANDLE_WAIT_RET_ABANDONED_0 && val < MONO_W32HANDLE_WAIT_RET_ABANDONED_0 + numobjects) { + return WAIT_ABANDONED_0 + (val - MONO_W32HANDLE_WAIT_RET_ABANDONED_0); + } else if (val == MONO_W32HANDLE_WAIT_RET_ALERTED) { + return WAIT_IO_COMPLETION; + } else if (val == MONO_W32HANDLE_WAIT_RET_TIMEOUT) { + return WAIT_TIMEOUT; + } else if (val == MONO_W32HANDLE_WAIT_RET_FAILED) { + /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */ + return MANAGED_WAIT_FAILED; + } else { + g_error ("%s: unknown val value %d", __func__, val); + } } -static gint32 +static MonoW32HandleWaitRet mono_wait_uninterrupted (MonoInternalThread *thread, guint32 numhandles, gpointer *handles, gboolean waitall, gint32 ms, MonoError *error) { MonoException *exc; - guint32 ret; + MonoW32HandleWaitRet ret; gint64 start; gint32 diff_ms; gint32 wait = ms; @@ -1684,13 +1696,18 @@ mono_wait_uninterrupted (MonoInternalThread *thread, guint32 numhandles, gpointe start = (ms == -1) ? 0 : mono_100ns_ticks (); do { MONO_ENTER_GC_SAFE; +#ifdef HOST_WIN32 if (numhandles != 1) - ret = WaitForMultipleObjectsEx (numhandles, handles, waitall, wait, TRUE); + ret = mono_w32handle_convert_wait_ret (WaitForMultipleObjectsEx (numhandles, handles, waitall, wait, TRUE), numhandles); else - ret = WaitForSingleObjectEx (handles [0], ms, TRUE); + ret = mono_w32handle_convert_wait_ret (WaitForSingleObjectEx (handles [0], ms, TRUE), 1); +#else + /* mono_w32handle_wait_multiple optimizes the case for numhandles == 1 */ + ret = mono_w32handle_wait_multiple (handles, numhandles, waitall, wait, TRUE); +#endif /* HOST_WIN32 */ MONO_EXIT_GC_SAFE; - if (ret != WAIT_IO_COMPLETION) + if (ret != MONO_W32HANDLE_WAIT_RET_ALERTED) break; exc = mono_thread_execute_interruption (); @@ -1705,7 +1722,7 @@ mono_wait_uninterrupted (MonoInternalThread *thread, guint32 numhandles, gpointe /* Re-calculate ms according to the time passed */ diff_ms = (gint32)((mono_100ns_ticks () - start) / 10000); if (diff_ms >= ms) { - ret = WAIT_TIMEOUT; + ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT; break; } wait = ms - diff_ms; @@ -1719,14 +1736,14 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_ha MonoError error; HANDLE *handles; guint32 numhandles; - guint32 ret; + 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 (WAIT_FAILED); + 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); @@ -1751,8 +1768,7 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_ha mono_error_set_pending_exception (&error); - /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */ - return map_native_wait_result_to_managed (ret); + return map_native_wait_result_to_managed (ret, numhandles); } gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms) @@ -1760,18 +1776,18 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_ha MonoError error; HANDLE handles [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS]; uintptr_t numhandles; - guint32 ret; + 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 (WAIT_FAILED); + return map_native_wait_result_to_managed (MONO_W32HANDLE_WAIT_RET_FAILED, 0); numhandles = mono_array_length(mono_handles); if (numhandles > MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) - return map_native_wait_result_to_managed (WAIT_FAILED); + return map_native_wait_result_to_managed (MONO_W32HANDLE_WAIT_RET_FAILED, 0); for(i = 0; i < numhandles; i++) { waitHandle = mono_array_get(mono_handles, MonoObject*, i); @@ -1792,14 +1808,13 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_ha mono_error_set_pending_exception (&error); - /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */ - return map_native_wait_result_to_managed (ret); + return map_native_wait_result_to_managed (ret, numhandles); } gint32 ves_icall_System_Threading_WaitHandle_WaitOne_internal(HANDLE handle, gint32 ms) { MonoError error; - guint32 ret; + 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)); @@ -1809,7 +1824,7 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitOne_internal(HANDLE handle, gin } if (mono_thread_current_check_pending_interrupt ()) - return map_native_wait_result_to_managed (WAIT_FAILED); + return map_native_wait_result_to_managed (MONO_W32HANDLE_WAIT_RET_FAILED, 0); mono_thread_set_state (thread, ThreadState_WaitSleepJoin); @@ -1818,30 +1833,34 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitOne_internal(HANDLE handle, gin mono_thread_clr_state (thread, ThreadState_WaitSleepJoin); mono_error_set_pending_exception (&error); - return map_native_wait_result_to_managed (ret); + return map_native_wait_result_to_managed (ret, 1); } gint32 ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, HANDLE toWait, gint32 ms) { - guint32 ret; + MonoW32HandleWaitRet ret; MonoInternalThread *thread = mono_thread_internal_current (); if (ms == -1) ms = INFINITE; if (mono_thread_current_check_pending_interrupt ()) - return map_native_wait_result_to_managed (WAIT_FAILED); + return map_native_wait_result_to_managed (MONO_W32HANDLE_WAIT_RET_FAILED, 0); mono_thread_set_state (thread, ThreadState_WaitSleepJoin); MONO_ENTER_GC_SAFE; - ret = SignalObjectAndWait (toSignal, toWait, ms, TRUE); +#ifdef HOST_WIN32 + ret = mono_w32handle_convert_wait_ret (SignalObjectAndWait (toSignal, toWait, ms, TRUE), 1); +#else + ret = mono_w32handle_signal_and_wait (toSignal, toWait, ms, TRUE); +#endif MONO_EXIT_GC_SAFE; mono_thread_clr_state (thread, ThreadState_WaitSleepJoin); - return map_native_wait_result_to_managed (ret); + return map_native_wait_result_to_managed (ret, 1); } gint32 ves_icall_System_Threading_Interlocked_Increment_Int (gint32 *location) diff --git a/mono/metadata/w32handle.h b/mono/metadata/w32handle.h index ce7d76ec688..1416bf2479b 100644 --- a/mono/metadata/w32handle.h +++ b/mono/metadata/w32handle.h @@ -5,6 +5,10 @@ #include #include +#ifdef HOST_WIN32 +#include +#endif + #ifndef INVALID_HANDLE_VALUE #define INVALID_HANDLE_VALUE (gpointer)-1 #endif @@ -41,10 +45,10 @@ typedef struct { void (*close)(gpointer handle, gpointer data); - /* SignalObjectAndWait */ + /* mono_w32handle_signal_and_wait */ void (*signal)(gpointer signal); - /* Called by WaitForSingleObject and WaitForMultipleObjects, + /* Called by mono_w32handle_wait_one and mono_w32handle_wait_multiple, * with the handle locked (shared handles aren't locked.) * Returns TRUE if ownership was established, false otherwise. * If TRUE, *statuscode contains a status code such as @@ -52,20 +56,20 @@ typedef struct */ gboolean (*own_handle)(gpointer handle, guint32 *statuscode); - /* Called by WaitForSingleObject and WaitForMultipleObjects, if the + /* Called by mono_w32handle_wait_one and mono_w32handle_wait_multiple, if the * handle in question is "ownable" (ie mutexes), to see if the current * thread already owns this handle */ gboolean (*is_owned)(gpointer handle); - /* Called by WaitForSingleObject and WaitForMultipleObjects, + /* Called by mono_w32handle_wait_one and mono_w32handle_wait_multiple, * if the handle in question needs a special wait function * instead of using the normal handle signal mechanism. - * Returns the WaitForSingleObject return code. + * Returns the mono_w32handle_wait_one return code. */ MonoW32HandleWaitRet (*special_wait)(gpointer handle, guint32 timeout, gboolean *alerted); - /* Called by WaitForSingleObject and WaitForMultipleObjects, + /* Called by mono_w32handle_wait_one and mono_w32handle_wait_multiple, * if the handle in question needs some preprocessing before the * signal wait. */ @@ -159,4 +163,24 @@ mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waital MonoW32HandleWaitRet mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable); +#ifdef HOST_WIN32 +static inline MonoW32HandleWaitRet +mono_w32handle_convert_wait_ret (guint32 res, guint32 numobjects) +{ + if (res >= WAIT_OBJECT_0 && res <= WAIT_OBJECT_0 + numobjects - 1) + return MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + (res - WAIT_OBJECT_0); + else if (res >= WAIT_ABANDONED_0 && res <= WAIT_ABANDONED_0 + numobjects - 1) + return MONO_W32HANDLE_WAIT_RET_ABANDONED_0 + (res - WAIT_ABANDONED_0); + else if (res == WAIT_IO_COMPLETION) + return MONO_W32HANDLE_WAIT_RET_ALERTED; + else if (res == WAIT_TIMEOUT) + return MONO_W32HANDLE_WAIT_RET_TIMEOUT; + else if (res == WAIT_FAILED) + return MONO_W32HANDLE_WAIT_RET_FAILED; + else + g_error ("%s: unknown res value %d", __func__, res); +} +#endif + + #endif /* _MONO_METADATA_W32HANDLE_H_ */