2002-03-28 Dick Porter <dick@ximian.com>
[mono.git] / mono / io-layer / semaphores.c
index 9a213e1c48d4863a4dc63c2e5a1ca143619ac492..1b7f3d1db4e8cc0e44a172918b0f61fb9f58c79e 100644 (file)
@@ -69,11 +69,19 @@ static gboolean sema_wait(WapiHandle *handle, WapiHandle *signal, guint32 ms)
        int ret;
        
        mono_mutex_lock(&sem_mutex);
+
+#ifdef DEBUG
+       g_message(G_GNUC_PRETTY_FUNCTION ": Sem %p val %d ms %d", handle,
+                 sem_handle->val, ms);
+#endif
        
        /* Signal this handle after we have obtained the semaphore
         * global lock
         */
        if(signal!=NULL) {
+#ifdef DEBUG
+               g_message(G_GNUC_PRETTY_FUNCTION ": signalling %p", signal);
+#endif
                signal->ops->signal(signal);
        }
        
@@ -98,16 +106,63 @@ static gboolean sema_wait(WapiHandle *handle, WapiHandle *signal, guint32 ms)
        }
        
        if(ms==INFINITE) {
+#ifdef DEBUG
+               g_message(G_GNUC_PRETTY_FUNCTION ": wait for %p INFINITE",
+                         sem_handle);
+#endif
+       try_again_infinite:
                ret=mono_cond_wait(&sem_cond, &sem_mutex);
-               waited=TRUE;
+               if(ret==0) {
+                       /* See if we were signalled (it might have been
+                        * another semaphore)
+                        */
+                       if(sem_handle->val>0) {
+#ifdef DEBUG
+                               g_message(G_GNUC_PRETTY_FUNCTION
+                                         ": sem %p has been signalled",
+                                         sem_handle);
+#endif
+                               waited=TRUE;
+                       } else {
+#ifdef DEBUG
+                               g_message(G_GNUC_PRETTY_FUNCTION
+                                         ": sem %p not signalled",
+                                         sem_handle);
+#endif
+                               goto try_again_infinite;
+                       }
+               }
        } else {
                struct timespec timeout;
 
+#ifdef DEBUG
+               g_message(G_GNUC_PRETTY_FUNCTION ": wait for %p for %d ms",
+                         sem_handle, ms);
+#endif
+
                _wapi_calc_timeout(&timeout, ms);
                
+       try_again_timed:
                ret=mono_cond_timedwait(&sem_cond, &sem_mutex, &timeout);
                if(ret==0) {
-                       waited=TRUE;
+                       /* See if we were signalled (it might have been
+                        * another semaphore)
+                        */
+                       if(sem_handle->val>0) {
+#ifdef DEBUG
+                               g_message(G_GNUC_PRETTY_FUNCTION
+                                         ": sem %p has been signalled",
+                                         sem_handle);
+#endif
+                               waited=TRUE;
+                       } else {
+#ifdef DEBUG
+                               g_message(G_GNUC_PRETTY_FUNCTION
+                                         ": sem %p not signalled",
+                                         sem_handle);
+#endif
+                               goto try_again_timed;
+                       }
                } else {
                        /* ret might be ETIMEDOUT for timeout, or
                         * other for error */
@@ -118,7 +173,18 @@ static gboolean sema_wait(WapiHandle *handle, WapiHandle *signal, guint32 ms)
 end:
        if(waited==TRUE) {
                sem_handle->val--;
+#ifdef DEBUG
+               g_message(G_GNUC_PRETTY_FUNCTION
+                         ": Waited TRUE, sem %p val now %d", sem_handle,
+                         sem_handle->val);
+#endif
        }
+#ifdef DEBUG
+       else {
+               g_message(G_GNUC_PRETTY_FUNCTION ": Waited FALSE, sem %p",
+                         sem_handle);
+       }
+#endif
        
        mono_mutex_unlock(&sem_mutex);
        return(waited);
@@ -332,6 +398,11 @@ gboolean ReleaseSemaphore(WapiHandle *handle, gint32 count, gint32 *prevcount)
        
        
        mono_mutex_lock(&sem_mutex);
+
+#ifdef DEBUG
+       g_message(G_GNUC_PRETTY_FUNCTION ": sem %p val %d count %d",
+                 sem_handle, sem_handle->val, count);
+#endif
        
        /* Do this before checking for count overflow, because overflowing max
         * is a listed technique for finding the current value
@@ -353,6 +424,11 @@ gboolean ReleaseSemaphore(WapiHandle *handle, gint32 count, gint32 *prevcount)
        sem_handle->val+=count;
        pthread_cond_broadcast(&sem_cond);
        ret=TRUE;
+
+#ifdef DEBUG
+       g_message(G_GNUC_PRETTY_FUNCTION ": sem %p val now %d", sem_handle,
+                 sem_handle->val);
+#endif
        
 end:
        mono_mutex_unlock(&sem_mutex);