2006-12-11 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mono / io-layer / wait.c
index d66f8994269b39154865c10e022a8da0ae68ca47..228d17dd134694e3095656e7cc9f7e10148b3763 100644 (file)
@@ -4,7 +4,7 @@
  * Author:
  *     Dick Porter (dick@ximian.com)
  *
- * (C) 2002 Ximian, Inc.
+ * (C) 2002-2006 Novell, Inc.
  */
 
 #include <config.h>
 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,20 @@ 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 (_wapi_handle_test_capabilities (handle,
                                            WAPI_HANDLE_CAP_WAIT) == FALSE) {
@@ -106,6 +117,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 +172,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 +184,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 +197,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);
                }
        
                if (alertable)
@@ -280,7 +299,28 @@ 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 (_wapi_handle_test_capabilities (signal_handle,
                                            WAPI_HANDLE_CAP_SIGNAL)==FALSE) {
@@ -292,6 +332,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 +386,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 +398,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);
                }
 
                if (alertable) {
@@ -412,15 +456,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 +481,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 +540,17 @@ 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 ());
+       
+       if (current_thread == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(WAIT_FAILED);
+       }
        
        if (numobjects > MAXIMUM_WAIT_OBJECTS) {
 #ifdef DEBUG
@@ -522,7 +567,22 @@ 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;
+                       }
+               }
+               
+               exists = g_hash_table_lookup (dups, handles[i]);
                if (exists != NULL) {
 #ifdef DEBUG
                        g_message ("%s: Handle %p duplicated", __func__,
@@ -542,11 +602,8 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
                        bogustype = TRUE;
                }
 
-               if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handles[i]))) {
-                       shared_wait = TRUE;
-               }
-
                g_hash_table_insert (dups, handles[i], handles[i]);
+               _wapi_handle_ops_prewait (handles[i]);
        }
        g_hash_table_destroy (dups);
 
@@ -571,6 +628,9 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
                return(WAIT_OBJECT_0+lowest);
        }
        
+       if (timeout == 0) {
+               return WAIT_TIMEOUT;
+       }
        /* Have to wait for some or all handles to become signalled
         */
 
@@ -584,10 +644,12 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
        }
        
        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);
                        }
@@ -609,18 +671,10 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
                thr_ret = _wapi_handle_lock_signal_mutex ();
                g_assert (thr_ret == 0);
                
-               if (shared_wait == TRUE) {
-                       if (timeout == INFINITE) {
-                               ret = _wapi_handle_wait_signal_poll_share ();
-                       } else {
-                               ret = _wapi_handle_timedwait_signal_poll_share (&abstime);
-                       }
+               if (timeout == INFINITE) {
+                       ret = _wapi_handle_wait_signal ();
                } else {
-                       if (timeout == INFINITE) {
-                               ret = _wapi_handle_wait_signal ();
-                       } else {
-                               ret = _wapi_handle_timedwait_signal (&abstime);
-                       }
+                       ret = _wapi_handle_timedwait_signal (&abstime);
                }
 
 #ifdef DEBUG