Index: trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c
===================================================================
--- trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c	(revision 30578)
+++ trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c	(revision 30579)
@@ -55,10 +55,8 @@
     /** Magic value (RTSEMEVENTMULTI_MAGIC). */
     uint32_t volatile   u32Magic;
-    /** The number of waiting threads. */
-    uint32_t            cWaiters;
+    /** The number of references. */
+    int32_t volatile    cRefs;
     /** Set if the event object is signaled. */
-    uint8_t             fSignaled;
-    /** The number of threads in the process of waking up, doubles up as a ref counter. */
-    uint32_t            cWaking;
+    bool                fSignaled;
     /** Object generation.
      * This is incremented every time the object is signalled and used to
@@ -90,9 +88,8 @@
     if (pThis)
     {
-        pThis->u32Magic   = RTSEMEVENTMULTI_MAGIC;
-        pThis->cWaiters   = 0;
-        pThis->cWaking    = 0;
-        pThis->fSignaled  = 0;
-        pThis->uSignalGen = 0;
+        pThis->u32Magic     = RTSEMEVENTMULTI_MAGIC;
+        pThis->cRefs        = 1;
+        pThis->fSignaled    = false;
+        pThis->uSignalGen   = 0;
         mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
         cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
@@ -102,4 +99,16 @@
     }
     return VERR_NO_MEMORY;
+}
+
+
+/**
+ * Destructor that is called when cRefs == 0.
+ * @param   pThis               The instance to destroy.
+ */
+static void rtSemEventMultiDtor(PRTSEMEVENTMULTIINTERNAL pThis)
+{
+    cv_destroy(&pThis->Cnd);
+    mutex_destroy(&pThis->Mtx);
+    RTMemFree(pThis);
 }
 
@@ -112,36 +121,25 @@
     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
+    AssertMsgReturn(pThis->cRefs > 0, ("pThis=%p cRefs=%d\n", pThis, pThis->cRefs), VERR_INVALID_HANDLE);
     RT_ASSERT_INTS_ON();
 
     mutex_enter(&pThis->Mtx);
 
+    /* Invalidate the handle and wake up all threads that might be waiting on the semaphore. */
     Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
     pThis->u32Magic = RTSEMEVENTMULTI_MAGIC_DEAD;
-    if (pThis->cWaiters > 0)
-    {
-        /* abort waiting thread, last man cleans up. */
-        pThis->cWaking += pThis->cWaiters;
-        pThis->cWaiters = 0;
-        cv_broadcast(&pThis->Cnd);
-
-        mutex_exit(&pThis->Mtx);
-    }
-    else if (pThis->cWaking)
-        /* the last waking thread is gonna do the cleanup */
+    cv_broadcast(&pThis->Cnd);
+
+    /* Drop the reference from RTSemEventMultiCreateEx. */
+    if (ASMAtomicDecS32(&pThis->cRefs))
         mutex_exit(&pThis->Mtx);
     else
-    {
-        mutex_exit(&pThis->Mtx);
-
-        cv_destroy(&pThis->Cnd);
-        mutex_destroy(&pThis->Mtx);
-        RTMemFree(pThis);
-    }
-
+        rtSemEventMultiDtor(pThis);
     return VINF_SUCCESS;
-}
-
-
-RTDECL(int)  RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
+
+}
+
+
+RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
 {
     PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
@@ -172,13 +170,12 @@
         mutex_enter(&pThis->Mtx);
     }
-
+    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+
+    /*
+     * Do the job.
+     */
     pThis->fSignaled = true;
     pThis->uSignalGen++;
-    if (pThis->cWaiters > 0)
-    {
-        pThis->cWaking += pThis->cWaiters;
-        pThis->cWaiters = 0;
-        cv_broadcast(&pThis->Cnd);
-    }
+    cv_broadcast(&pThis->Cnd);
 
     mutex_exit(&pThis->Mtx);
@@ -189,5 +186,5 @@
 
 
-RTDECL(int)  RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
+RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
 {
     PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
@@ -218,6 +215,11 @@
         mutex_enter(&pThis->Mtx);
     }
-
+    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+
+    /*
+     * Do the job.
+     */
     pThis->fSignaled = false;
+
     mutex_exit(&pThis->Mtx);
 
@@ -273,4 +275,6 @@
 
     mutex_enter(&pThis->Mtx);
+    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+    ASMAtomicIncS32(&pThis->cRefs);
 
     if (pThis->fSignaled)
@@ -280,5 +284,4 @@
     else
     {
-        pThis->cWaiters++;
 
         /* This loop is only for continuing after a spurious wake-up. */
@@ -294,41 +297,25 @@
                         continue; /* Spurious wake-up, go back to waiting. */
 
-                    /* Retured due to call to cv_signal() or cv_broadcast() */
-                    pThis->cWaking--;
+                    /* Retured due to call to cv_signal() or cv_broadcast(). */
                     rc = VINF_SUCCESS;
                 }
                 else
-                {
-                    /* We're being destroyed */
+                    /* We're being destroyed. */
                     rc = VERR_SEM_DESTROYED;
-                    if (!--pThis->cWaiters)
-                    {
-                        mutex_exit(&pThis->Mtx);
-                        cv_destroy(&pThis->Cnd);
-                        mutex_destroy(&pThis->Mtx);
-                        RTMemFree(pThis);
-                        return rc;
-                    }
-                }
             }
             else if (rc == -1)
-            {
-                /* Returned due to timeout being reached */
-                if (pThis->cWaiters > 0)
-                    pThis->cWaiters--;
+                /* Returned due to timeout being reached. */
                 rc = VERR_TIMEOUT;
-            }
             else
-            {
-                /* Returned due to pending signal */
-                if (pThis->cWaiters > 0)
-                    pThis->cWaiters--;
                 rc = VERR_INTERRUPTED;
-            }
+                /* Returned due to pending signal. */
             break;
         }
     }
 
-    mutex_exit(&pThis->Mtx);
+    if (RT_LIKELY(ASMAtomicDecS32(&pThis->cRefs)))
+        mutex_exit(&pThis->Mtx);
+    else
+        rtSemEventMultiDtor(pThis);
     return rc;
 }
