[io-layer] Remove unused WaitForMultipleObjects
[mono.git] / mono / io-layer / wait.c
index a8b41b576a9cf56a2a18af0f08ef3e4e41366853..5ccec7bf9add8f4c4a2a89796389365b82e56091 100644 (file)
 
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/mono-time.h>
 #include <mono/utils/w32handle.h>
 
-static gboolean own_if_signalled(gpointer handle)
-{
-       gboolean ret = FALSE;
-
-       if (mono_w32handle_issignalled (handle)) {
-               mono_w32handle_ops_own (handle);
-               ret = TRUE;
-       }
-
-       return(ret);
-}
-
-static gboolean own_if_owned(gpointer handle)
-{
-       gboolean ret = FALSE;
-
-       if (mono_w32handle_ops_isowned (handle)) {
-               mono_w32handle_ops_own (handle);
-               ret = TRUE;
-       }
-
-       return(ret);
-}
-
 /**
  * WaitForSingleObjectEx:
  * @handle: an object to wait for
@@ -62,149 +35,21 @@ static gboolean own_if_owned(gpointer handle)
  * @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)
-{
-       guint32 ret, waited;
-       int thr_ret;
-       gboolean apc_pending = FALSE;
-       gpointer current_thread = wapi_get_current_thread_handle ();
-       gint64 wait_start, timeout_in_ticks;
-       
-       if (current_thread == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(WAIT_FAILED);
-       }
-
-       if (handle == _WAPI_THREAD_CURRENT) {
-               handle = wapi_get_current_thread_handle ();
-               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 (mono_w32handle_test_capabilities (handle,
-                                           MONO_W32HANDLE_CAP_WAIT) == FALSE) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p can't be waited for", __func__,
-                          handle);
-
-               return(WAIT_FAILED);
-       }
-
-       mono_w32handle_ops_prewait (handle);
-       
-       if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p has special wait", __func__, handle);
-
-               ret = mono_w32handle_ops_specialwait (handle, timeout, alertable);
-       
-               if (alertable && _wapi_thread_cur_apc_pending ())
-                       ret = WAIT_IO_COMPLETION;
-
-               return ret;
-       }
-       
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handle %p", __func__, handle);
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       if (mono_w32handle_test_capabilities (handle,
-                                           MONO_W32HANDLE_CAP_OWN) == TRUE) {
-               if (own_if_owned (handle) == TRUE) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already owned", __func__,
-                                  handle);
-                       ret = WAIT_OBJECT_0;
-                       goto done;
-               }
-       }
-
-       if (own_if_signalled (handle) == TRUE) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already signalled", __func__,
-                          handle);
-
-               ret=WAIT_OBJECT_0;
-               goto done;
-       }
-
-       if (timeout == 0) {
-               ret = WAIT_TIMEOUT;
-               goto done;
-       }
-       
-       if (timeout != INFINITE) {
-               wait_start = mono_100ns_ticks ();
-               timeout_in_ticks = (gint64)timeout * 10 * 1000; //can't overflow as timeout is 32bits
-       }
-
-       do {
-               /* Check before waiting on the condition, just in case
-                */
-               mono_w32handle_ops_prewait (handle);
-
-               if (own_if_signalled (handle)) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__,
-                                  handle);
-
-                       ret = WAIT_OBJECT_0;
-                       goto done;
-               }
-
-               if (timeout == INFINITE) {
-                       waited = mono_w32handle_timedwait_signal_handle (handle, INFINITE, FALSE, alertable ? &apc_pending : NULL);
-               } else {
-                       gint64 elapsed = mono_100ns_ticks () - wait_start;
-                       if (elapsed >= timeout_in_ticks) {
-                               ret = WAIT_TIMEOUT;
-                               goto done;
-                       }
-
-                       waited = mono_w32handle_timedwait_signal_handle (handle, (timeout_in_ticks - elapsed) / 10 / 1000, FALSE, alertable ? &apc_pending : NULL);
-               }
-
-               if(waited==0 && !apc_pending) {
-                       /* Condition was signalled, so hopefully
-                        * handle is signalled now.  (It might not be
-                        * if someone else got in before us.)
-                        */
-                       if (own_if_signalled (handle)) {
-                               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__,
-                                          handle);
-
-                               ret=WAIT_OBJECT_0;
-                               goto done;
-                       }
-               
-                       /* Better luck next time */
-               }
-       } while(waited == 0 && !apc_pending);
-
-       /* Timeout or other error */
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: wait on handle %p error: %s", __func__, handle,
-                  strerror (waited));
-
-       ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT;
-
-done:
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, handle);
-       
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       return(ret);
-}
-
-guint32 WaitForSingleObject(gpointer handle, guint32 timeout)
+guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, gboolean alertable)
 {
-       return WaitForSingleObjectEx (handle, timeout, FALSE);
+       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_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);
 }
 
 
@@ -246,171 +91,19 @@ guint32 WaitForSingleObject(gpointer handle, guint32 timeout)
 guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
                            guint32 timeout, gboolean alertable)
 {
-       guint32 ret = 0, waited;
-       int thr_ret;
-       gboolean apc_pending = FALSE;
-       gpointer current_thread = wapi_get_current_thread_handle ();
-       gint64 wait_start, timeout_in_ticks;
-       
-       if (current_thread == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(WAIT_FAILED);
-       }
-
-       if (signal_handle == _WAPI_THREAD_CURRENT) {
-               signal_handle = wapi_get_current_thread_handle ();
-               if (signal_handle == NULL) {
-                       SetLastError (ERROR_INVALID_HANDLE);
-                       return(WAIT_FAILED);
-               }
-       }
-
-       if (wait == _WAPI_THREAD_CURRENT) {
-               wait = wapi_get_current_thread_handle ();
-               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 (mono_w32handle_test_capabilities (signal_handle,
-                                           MONO_W32HANDLE_CAP_SIGNAL)==FALSE) {
-               return(WAIT_FAILED);
-       }
-       
-       if (mono_w32handle_test_capabilities (wait,
-                                           MONO_W32HANDLE_CAP_WAIT)==FALSE) {
-               return(WAIT_FAILED);
-       }
-
-       mono_w32handle_ops_prewait (wait);
-       
-       if (mono_w32handle_test_capabilities (wait, MONO_W32HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
-               g_warning ("%s: handle %p has special wait, implement me!!",
-                          __func__, wait);
-
-               return (WAIT_FAILED);
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handle %p", __func__, wait);
-
-       thr_ret = mono_w32handle_lock_handle (wait);
-       g_assert (thr_ret == 0);
-
-       mono_w32handle_ops_signal (signal_handle);
-
-       if (mono_w32handle_test_capabilities (wait, MONO_W32HANDLE_CAP_OWN)==TRUE) {
-               if (own_if_owned (wait)) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already owned", __func__,
-                                  wait);
-                       ret = WAIT_OBJECT_0;
-                       goto done;
-               }
-       }
-
-       if (own_if_signalled (wait)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already signalled", __func__, wait);
-
-               ret = WAIT_OBJECT_0;
-               goto done;
-       }
-
-       if (timeout != INFINITE) {
-               wait_start = mono_100ns_ticks ();
-               timeout_in_ticks = (gint64)timeout * 10 * 1000; //can't overflow as timeout is 32bits
-       }
-       do {
-               /* Check before waiting on the condition, just in case
-                */
-               mono_w32handle_ops_prewait (wait);
-       
-               if (own_if_signalled (wait)) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__, wait);
-
-                       ret = WAIT_OBJECT_0;
-                       goto done;
-               }
-
-               if (timeout == INFINITE) {
-                       waited = mono_w32handle_timedwait_signal_handle (wait, INFINITE, FALSE, alertable ? &apc_pending : NULL);
-               } else {
-                       gint64 elapsed = mono_100ns_ticks () - wait_start;
-                       if (elapsed >= timeout_in_ticks) {
-                               ret = WAIT_TIMEOUT;
-                               goto done;
-                       }
-
-                       waited = mono_w32handle_timedwait_signal_handle (wait, (timeout_in_ticks - elapsed) / 10 / 1000, FALSE, alertable ? &apc_pending : NULL);
-               }
-
-               if (waited==0 && !apc_pending) {
-                       /* Condition was signalled, so hopefully
-                        * handle is signalled now.  (It might not be
-                        * if someone else got in before us.)
-                        */
-                       if (own_if_signalled (wait)) {
-                               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__,
-                                          wait);
-
-                               ret = WAIT_OBJECT_0;
-                               goto done;
-                       }
-               
-                       /* Better luck next time */
-               }
-       } while(waited == 0 && !apc_pending);
-
-       /* Timeout or other error */
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: wait on handle %p error: %s", __func__, wait, strerror (ret));
-
-       ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT;
-
-done:
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, wait);
-
-       thr_ret = mono_w32handle_unlock_handle (wait);
-       g_assert (thr_ret == 0);
-
-       return(ret);
-}
-
-static gboolean test_and_own (guint32 numobjects, gpointer *handles,
-                             gboolean waitall, guint32 *count,
-                             guint32 *lowest)
-{
-       gboolean done;
-       int i;
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handles", __func__);
-       
-       done = mono_w32handle_count_signalled_handles (numobjects, handles,
-                                                    waitall, count, lowest);
-       if (done == TRUE) {
-               if (waitall == TRUE) {
-                       for (i = 0; i < numobjects; i++) {
-                               own_if_signalled (handles[i]);
-                       }
-               } else {
-                       own_if_signalled (handles[*lowest]);
-               }
-       }
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handles", __func__);
-
-       mono_w32handle_unlock_handles (numobjects, handles);
-
-       return(done);
+       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_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);
 }
 
 /**
@@ -447,211 +140,19 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
                                 gboolean waitall, guint32 timeout,
                                 gboolean alertable)
 {
-       gboolean duplicate = FALSE, bogustype = FALSE, done;
-       guint32 count, lowest;
-       guint i;
-       guint32 ret;
-       int thr_ret;
-       gpointer current_thread = wapi_get_current_thread_handle ();
-       guint32 retval;
-       gboolean poll;
-       gpointer sorted_handles [MAXIMUM_WAIT_OBJECTS];
-       gboolean apc_pending = FALSE;
-       gint64 wait_start, timeout_in_ticks;
-       
-       if (current_thread == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(WAIT_FAILED);
-       }
-       
-       if (numobjects > MAXIMUM_WAIT_OBJECTS) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Too many handles: %d", __func__, numobjects);
-
-               return(WAIT_FAILED);
-       }
-       
-       if (numobjects == 1) {
-               return WaitForSingleObjectEx (handles [0], timeout, alertable);
-       }
-
-       /* Check for duplicates */
-       for (i = 0; i < numobjects; i++) {
-               if (handles[i] == _WAPI_THREAD_CURRENT) {
-                       handles[i] = wapi_get_current_thread_handle ();
-                       
-                       if (handles[i] == NULL) {
-                               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %d bogus", __func__, i);
-
-                               bogustype = TRUE;
-                               break;
-                       }
-               }
-
-               if ((GPOINTER_TO_UINT (handles[i]) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %d pseudo process", __func__,
-                                  i);
-
-                       bogustype = TRUE;
-                       break;
-               }
-
-               if (mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_WAIT) == FALSE) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %p can't be waited for",
-                                  __func__, handles[i]);
-
-                       bogustype = TRUE;
-                       break;
-               }
-
-               sorted_handles [i] = handles [i];
-               mono_w32handle_ops_prewait (handles[i]);
-       }
-
-       qsort (sorted_handles, numobjects, sizeof (gpointer), g_direct_equal);
-       for (i = 1; i < numobjects; i++) {
-               if (sorted_handles [i - 1] == sorted_handles [i]) {
-                       duplicate = TRUE;
-                       break;
-               }
-       }
-
-       if (duplicate == TRUE) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning due to duplicates", __func__);
-
-               return(WAIT_FAILED);
-       }
-
-       if (bogustype == TRUE) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning due to bogus type", __func__);
-
-               return(WAIT_FAILED);
-       }
-
-       poll = FALSE;
-       for (i = 0; i < numobjects; ++i)
-               if (mono_w32handle_get_type (handles [i]) == MONO_W32HANDLE_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) {
+       MonoW32HandleWaitRet ret;
+
+       ret = mono_w32handle_wait_multiple (handles, numobjects, waitall, timeout, alertable);
+       if (ret >= MONO_W32HANDLE_WAIT_RET_SUCCESS_0)
+               return WAIT_OBJECT_0 + (ret - MONO_W32HANDLE_WAIT_RET_SUCCESS_0);
+       else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED)
+               return WAIT_IO_COMPLETION;
+       else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT)
                return WAIT_TIMEOUT;
-       }
-
-       if (timeout != INFINITE) {
-               wait_start = mono_100ns_ticks ();
-               timeout_in_ticks = (gint64)timeout * 10 * 1000; //can't overflow as timeout is 32bits
-       }
-
-       /* Have to wait for some or all handles to become signalled
-        */
-
-       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)
-                */
-               mono_w32handle_ref (handles[i]);
-       }
-
-       while(1) {
-               /* Prod all handles with prewait methods and
-                * special-wait handles that aren't already signalled
-                */
-               for (i = 0; i < numobjects; i++) {
-                       mono_w32handle_ops_prewait (handles[i]);
-               
-                       if (mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_SPECIAL_WAIT) == TRUE && mono_w32handle_issignalled (handles[i]) == FALSE) {
-                               mono_w32handle_ops_specialwait (handles[i], 0, alertable);
-                       }
-               }
-               
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking signal mutex", __func__);
-
-               thr_ret = mono_w32handle_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 (!mono_w32handle_issignalled (handles [i]))
-                                       done = FALSE;
-               } else {
-                       done = FALSE;
-                       for (i = 0; i < numobjects; i++)
-                               if (mono_w32handle_issignalled (handles [i]))
-                                       done = TRUE;
-               }
-               
-               if (!done) {
-                       /* Enter the wait */
-                       if (timeout == INFINITE) {
-                               ret = mono_w32handle_timedwait_signal (INFINITE, poll, &apc_pending);
-                       } else {
-                               gint64 elapsed = mono_100ns_ticks () - wait_start;
-                               if (elapsed >= timeout_in_ticks) {
-                                       ret = WAIT_TIMEOUT;
-                               } else {
-                                       ret = mono_w32handle_timedwait_signal ((timeout_in_ticks - elapsed) / 10 / 1000, poll, &apc_pending);
-                               }
-                       }
-               } else {
-                       /* No need to wait */
-                       ret = 0;
-               }
-
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking signal mutex", __func__);
-
-               thr_ret = mono_w32handle_unlock_signal_mutex ();
-               g_assert (thr_ret == 0);
-               
-               if (alertable && apc_pending) {
-                       retval = WAIT_IO_COMPLETION;
-                       break;
-               }
-       
-               /* Check if everything is signalled, as we can't
-                * guarantee to notice a shared signal even if the
-                * wait timed out
-                */
-               done = test_and_own (numobjects, handles, waitall,
-                                    &count, &lowest);
-               if (done == TRUE) {
-                       retval = WAIT_OBJECT_0+lowest;
-                       break;
-               } else if (ret != 0) {
-                       /* Didn't get all handles, and there was a
-                        * timeout or other error
-                        */
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: wait returned error: %s", __func__,
-                                  strerror (ret));
-
-                       if(ret==ETIMEDOUT) {
-                               retval = WAIT_TIMEOUT;
-                       } else {
-                               retval = WAIT_FAILED;
-                       }
-                       break;
-               }
-       }
-
-       for (i = 0; i < numobjects; i++) {
-               /* Unref everything we reffed above */
-               mono_w32handle_unref (handles[i]);
-       }
-
-       return retval;
-}
-
-guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles,
-                              gboolean waitall, guint32 timeout)
-{
-       return WaitForMultipleObjectsEx(numobjects, handles, waitall, timeout, FALSE);
+       else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED)
+               return WAIT_FAILED;
+       else
+               g_error ("%s: unknown ret value %d", __func__, ret);
 }
 
 /**