uglify.h \
versioninfo.c \
versioninfo.h \
- wait.c \
wait.h \
wapi_glob.h \
wapi_glob.c \
+++ /dev/null
-/*
- * wait.c: wait for handles to become signalled
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/metadata/w32handle.h>
-
-/**
- * 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);
-}
-
#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_ */
#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__ */
#include <mono/metadata/runtime.h>
#include <mono/metadata/handle.h>
#include <mono/metadata/sgen-toggleref.h>
+#include <mono/metadata/w32handle.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/mono-memory-model.h>
MonoThreadsSync *mon;
HANDLE event;
guint32 nest;
- guint32 ret;
+ MonoW32HandleWaitRet ret;
gboolean success = FALSE;
gint32 regain;
MonoInternalThread *thread = mono_thread_internal_current ();
* 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
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;
}
* 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 {
}
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;
}
#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;
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 ();
/* 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;
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);
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)
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);
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));
}
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_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)
#include <config.h>
#include <glib.h>
+#ifdef HOST_WIN32
+#include <windows.h>
+#endif
+
#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE (gpointer)-1
#endif
{
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
*/
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.
*/
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_ */