X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fio-layer%2Fwait.c;h=db008cc1f87a0b910254bd82997650ddc1196bb7;hb=490468131f374120e12924ac31556ab262c280b6;hp=d66f8994269b39154865c10e022a8da0ae68ca47;hpb=6d48036db04107a1c2966d8de93cf36524e6e482;p=mono.git diff --git a/mono/io-layer/wait.c b/mono/io-layer/wait.c index d66f8994269..db008cc1f87 100644 --- a/mono/io-layer/wait.c +++ b/mono/io-layer/wait.c @@ -4,7 +4,7 @@ * Author: * Dick Porter (dick@ximian.com) * - * (C) 2002 Ximian, Inc. + * (C) 2002-2006 Novell, Inc. */ #include @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include @@ -25,10 +25,9 @@ static gboolean own_if_signalled(gpointer handle) { gboolean ret = FALSE; - guint32 now = (guint32)(time (NULL) & 0xFFFFFFFF); if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - if (_wapi_handle_shared_trylock_handle (handle, now) == EBUSY) { + if (_wapi_handle_trylock_shared_handles () == EBUSY) { return (FALSE); } } @@ -39,7 +38,7 @@ static gboolean own_if_signalled(gpointer handle) } if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - _wapi_handle_shared_unlock_handle (handle, now); + _wapi_handle_unlock_shared_handles (); } return(ret); @@ -48,10 +47,9 @@ static gboolean own_if_signalled(gpointer handle) static gboolean own_if_owned(gpointer handle) { gboolean ret = FALSE; - guint32 now = (guint32)(time (NULL) & 0xFFFFFFFF); if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - if (_wapi_handle_shared_trylock_handle (handle, now) == EBUSY) { + if (_wapi_handle_trylock_shared_handles () == EBUSY) { return (FALSE); } } @@ -62,7 +60,7 @@ static gboolean own_if_owned(gpointer handle) } if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - _wapi_handle_shared_unlock_handle (handle, now); + _wapi_handle_unlock_shared_handles (); } return(ret); @@ -94,7 +92,25 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, struct timespec abstime; int thr_ret; gboolean apc_pending = FALSE; - gpointer current_thread = GetCurrentThread (); + gpointer current_thread = _wapi_thread_handle_from_id (pthread_self ()); + + if (current_thread == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(WAIT_FAILED); + } + + if (handle == _WAPI_THREAD_CURRENT) { + handle = _wapi_thread_handle_from_id (pthread_self ()); + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(WAIT_FAILED); + } + } + + if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + SetLastError (ERROR_INVALID_HANDLE); + return(WAIT_FAILED); + } if (_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_WAIT) == FALSE) { @@ -106,6 +122,8 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, return(WAIT_FAILED); } + _wapi_handle_ops_prewait (handle); + if (_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE) { #ifdef DEBUG g_message ("%s: handle %p has special wait", __func__, handle); @@ -159,6 +177,10 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, goto done; } + if (timeout == 0) { + ret = WAIT_TIMEOUT; + goto done; + } /* Have to wait for it */ if (timeout != INFINITE) { _wapi_calc_timeout (&abstime, timeout); @@ -167,6 +189,8 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, do { /* Check before waiting on the condition, just in case */ + _wapi_handle_ops_prewait (handle); + if (own_if_signalled (handle)) { #ifdef DEBUG g_message ("%s: handle %p signalled", __func__, @@ -178,9 +202,9 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, } if (timeout == INFINITE) { - waited = _wapi_handle_wait_signal_handle (handle); + waited = _wapi_handle_wait_signal_handle (handle, alertable); } else { - waited = _wapi_handle_timedwait_signal_handle (handle, &abstime); + waited = _wapi_handle_timedwait_signal_handle (handle, &abstime, alertable, FALSE); } if (alertable) @@ -280,7 +304,38 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait, struct timespec abstime; int thr_ret; gboolean apc_pending = FALSE; - gpointer current_thread = GetCurrentThread (); + gpointer current_thread = _wapi_thread_handle_from_id (pthread_self ()); + + if (current_thread == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(WAIT_FAILED); + } + + if (signal_handle == _WAPI_THREAD_CURRENT) { + signal_handle = _wapi_thread_handle_from_id (pthread_self ()); + if (signal_handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(WAIT_FAILED); + } + } + + if (wait == _WAPI_THREAD_CURRENT) { + wait = _wapi_thread_handle_from_id (pthread_self ()); + if (wait == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(WAIT_FAILED); + } + } + + if ((GPOINTER_TO_UINT (signal_handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + SetLastError (ERROR_INVALID_HANDLE); + return(WAIT_FAILED); + } + + if ((GPOINTER_TO_UINT (wait) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { + SetLastError (ERROR_INVALID_HANDLE); + return(WAIT_FAILED); + } if (_wapi_handle_test_capabilities (signal_handle, WAPI_HANDLE_CAP_SIGNAL)==FALSE) { @@ -292,6 +347,8 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait, return(WAIT_FAILED); } + _wapi_handle_ops_prewait (wait); + if (_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE) { g_warning ("%s: handle %p has special wait, implement me!!", __func__, wait); @@ -344,6 +401,8 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait, do { /* Check before waiting on the condition, just in case */ + _wapi_handle_ops_prewait (wait); + if (own_if_signalled (wait)) { #ifdef DEBUG g_message ("%s: handle %p signalled", __func__, wait); @@ -354,9 +413,9 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait, } if (timeout == INFINITE) { - waited = _wapi_handle_wait_signal_handle (wait); + waited = _wapi_handle_wait_signal_handle (wait, alertable); } else { - waited = _wapi_handle_timedwait_signal_handle (wait, &abstime); + waited = _wapi_handle_timedwait_signal_handle (wait, &abstime, alertable, FALSE); } if (alertable) { @@ -412,15 +471,13 @@ struct handle_cleanup_data { guint32 numobjects; gpointer *handles; - guint32 now; }; static void handle_cleanup (void *data) { struct handle_cleanup_data *handles = (struct handle_cleanup_data *)data; - _wapi_handle_unlock_handles (handles->numobjects, handles->handles, - handles->now); + _wapi_handle_unlock_handles (handles->numobjects, handles->handles); } static gboolean test_and_own (guint32 numobjects, gpointer *handles, @@ -439,8 +496,7 @@ static gboolean test_and_own (guint32 numobjects, gpointer *handles, pthread_cleanup_push (handle_cleanup, (void *)&cleanup_data); done = _wapi_handle_count_signalled_handles (numobjects, handles, - waitall, count, lowest, - &cleanup_data.now); + waitall, count, lowest); if (done == TRUE) { if (waitall == TRUE) { for (i = 0; i < numobjects; i++) { @@ -499,13 +555,19 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, { GHashTable *dups; gboolean duplicate = FALSE, bogustype = FALSE, done; - gboolean shared_wait = FALSE; guint32 count, lowest; struct timespec abstime; guint i; guint32 ret; int thr_ret; - gpointer current_thread = GetCurrentThread (); + gpointer current_thread = _wapi_thread_handle_from_id (pthread_self ()); + guint32 retval; + gboolean poll; + + if (current_thread == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(WAIT_FAILED); + } if (numobjects > MAXIMUM_WAIT_OBJECTS) { #ifdef DEBUG @@ -522,7 +584,32 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, /* Check for duplicates */ dups = g_hash_table_new (g_direct_hash, g_direct_equal); for (i = 0; i < numobjects; i++) { - gpointer exists = g_hash_table_lookup (dups, handles[i]); + gpointer exists; + + if (handles[i] == _WAPI_THREAD_CURRENT) { + handles[i] = _wapi_thread_handle_from_id (pthread_self ()); + + if (handles[i] == NULL) { +#ifdef DEBUG + g_message ("%s: Handle %d bogus", __func__, i); +#endif + + bogustype = TRUE; + break; + } + } + + if ((GPOINTER_TO_UINT (handles[i]) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { +#ifdef DEBUG + g_message ("%s: Handle %d pseudo process", __func__, + i); +#endif + + bogustype = TRUE; + break; + } + + exists = g_hash_table_lookup (dups, handles[i]); if (exists != NULL) { #ifdef DEBUG g_message ("%s: Handle %p duplicated", __func__, @@ -540,13 +627,11 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, #endif bogustype = TRUE; - } - - if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handles[i]))) { - shared_wait = TRUE; + break; } g_hash_table_insert (dups, handles[i], handles[i]); + _wapi_handle_ops_prewait (handles[i]); } g_hash_table_destroy (dups); @@ -566,11 +651,20 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, return(WAIT_FAILED); } + poll = FALSE; + for (i = 0; i < numobjects; ++i) + if (_wapi_handle_type (handles [i]) == WAPI_HANDLE_PROCESS) + /* Can't wait for a process handle + another handle without polling */ + poll = TRUE; + done = test_and_own (numobjects, handles, waitall, &count, &lowest); if (done == TRUE) { return(WAIT_OBJECT_0+lowest); } + if (timeout == 0) { + return WAIT_TIMEOUT; + } /* Have to wait for some or all handles to become signalled */ @@ -583,23 +677,25 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, return WAIT_IO_COMPLETION; } + for (i = 0; i < numobjects; i++) { + /* Add a reference, as we need to ensure the handle wont + * disappear from under us while we're waiting in the loop + * (not lock, as we don't want exclusive access here) + */ + _wapi_handle_ref (handles[i]); + } + while(1) { - /* Prod all special-wait handles that aren't already - * signalled + /* Prod all handles with prewait methods and + * special-wait handles that aren't already signalled */ for (i = 0; i < numobjects; i++) { + _wapi_handle_ops_prewait (handles[i]); + if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE && _wapi_handle_issignalled (handles[i]) == FALSE) { _wapi_handle_ops_special_wait (handles[i], 0); } } - - /* Check before waiting on the condition, just in case - */ - done = test_and_own (numobjects, handles, waitall, - &count, &lowest); - if (done == TRUE) { - return(WAIT_OBJECT_0 + lowest); - } #ifdef DEBUG g_message ("%s: locking signal mutex", __func__); @@ -608,19 +704,30 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_signal_mutex, NULL); thr_ret = _wapi_handle_lock_signal_mutex (); g_assert (thr_ret == 0); + + /* Check the signalled state of handles inside the critical section */ + if (waitall) { + done = TRUE; + for (i = 0; i < numobjects; i++) + if (!_wapi_handle_issignalled (handles [i])) + done = FALSE; + } else { + done = FALSE; + for (i = 0; i < numobjects; i++) + if (_wapi_handle_issignalled (handles [i])) + done = TRUE; + } - if (shared_wait == TRUE) { + if (!done) { + /* Enter the wait */ if (timeout == INFINITE) { - ret = _wapi_handle_wait_signal_poll_share (); + ret = _wapi_handle_wait_signal (poll); } else { - ret = _wapi_handle_timedwait_signal_poll_share (&abstime); + ret = _wapi_handle_timedwait_signal (&abstime, poll); } } else { - if (timeout == INFINITE) { - ret = _wapi_handle_wait_signal (); - } else { - ret = _wapi_handle_timedwait_signal (&abstime); - } + /* No need to wait */ + ret = 0; } #ifdef DEBUG @@ -633,7 +740,8 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, if (alertable && _wapi_thread_apc_pending (current_thread)) { _wapi_thread_dispatch_apc_queue (current_thread); - return WAIT_IO_COMPLETION; + retval = WAIT_IO_COMPLETION; + break; } /* Check if everything is signalled, as we can't @@ -643,7 +751,8 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, done = test_and_own (numobjects, handles, waitall, &count, &lowest); if (done == TRUE) { - return(WAIT_OBJECT_0+lowest); + retval = WAIT_OBJECT_0+lowest; + break; } else if (ret != 0) { /* Didn't get all handles, and there was a * timeout or other error @@ -654,12 +763,20 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, #endif if(ret==ETIMEDOUT) { - return(WAIT_TIMEOUT); + retval = WAIT_TIMEOUT; } else { - return(WAIT_FAILED); + retval = WAIT_FAILED; } + break; } } + + for (i = 0; i < numobjects; i++) { + /* Unref everything we reffed above */ + _wapi_handle_unref (handles[i]); + } + + return retval; } guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles, @@ -667,3 +784,25 @@ guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles, { return WaitForMultipleObjectsEx(numobjects, handles, waitall, timeout, FALSE); } + +/** + * WaitForInputIdle: + * @handle: a handle to the process to wait for + * @timeout: the maximum time in milliseconds to wait for + * + * This function returns when either @handle process is waiting + * for input, or @timeout ms elapses. If @timeout is zero, the + * process state is tested and the function returns immediately. + * If @timeout is %INFINITE, the function waits forever. + * + * Return value: 0 - @handle process is waiting for input. + * %WAIT_TIMEOUT - The @timeout interval elapsed and + * @handle process is not waiting for input. %WAIT_FAILED - an error + * occurred. + */ +guint32 WaitForInputIdle(gpointer handle, guint32 timeout) +{ + /*TODO: Not implemented*/ + return WAIT_TIMEOUT; +} +