Index: trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c
===================================================================
--- trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c	(revision 30576)
+++ trunk/src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c	(revision 30578)
@@ -49,5 +49,5 @@
 *******************************************************************************/
 /**
- * FreeBSD multiple release event semaphore.
+ * Solaris multiple release event semaphore.
  */
 typedef struct RTSEMEVENTMULTIINTERNAL
@@ -56,11 +56,13 @@
     uint32_t volatile   u32Magic;
     /** The number of waiting threads. */
-    uint32_t volatile   cWaiters;
+    uint32_t            cWaiters;
     /** Set if the event object is signaled. */
-    uint8_t volatile    fSignaled;
+    uint8_t             fSignaled;
     /** The number of threads in the process of waking up, doubles up as a ref counter. */
-    uint32_t volatile   cWaking;
-    /** Object version that is incremented every time the object is signaled. */
-    uint32_t volatile   u32Version;
+    uint32_t            cWaking;
+    /** Object generation.
+     * This is incremented every time the object is signalled and used to
+     * check for spurious wake-ups. */
+    uint32_t            uSignalGen;
     /** The Solaris mutex protecting this structure and pairing up the with the cv. */
     kmutex_t            Mtx;
@@ -88,9 +90,9 @@
     if (pThis)
     {
-        pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
-        pThis->cWaiters = 0;
-        pThis->cWaking = 0;
-        pThis->fSignaled = 0;
-        pThis->u32Version = 0;
+        pThis->u32Magic   = RTSEMEVENTMULTI_MAGIC;
+        pThis->cWaiters   = 0;
+        pThis->cWaking    = 0;
+        pThis->fSignaled  = 0;
+        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);
@@ -113,10 +115,14 @@
 
     mutex_enter(&pThis->Mtx);
-    ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
+
+    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+    pThis->u32Magic = RTSEMEVENTMULTI_MAGIC_DEAD;
     if (pThis->cWaiters > 0)
     {
         /* abort waiting thread, last man cleans up. */
-        ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
+        pThis->cWaking += pThis->cWaiters;
+        pThis->cWaiters = 0;
         cv_broadcast(&pThis->Cnd);
+
         mutex_exit(&pThis->Mtx);
     }
@@ -127,4 +133,5 @@
     {
         mutex_exit(&pThis->Mtx);
+
         cv_destroy(&pThis->Cnd);
         mutex_destroy(&pThis->Mtx);
@@ -166,10 +173,10 @@
     }
 
-    ASMAtomicXchgU8(&pThis->fSignaled, true);
+    pThis->fSignaled = true;
+    pThis->uSignalGen++;
     if (pThis->cWaiters > 0)
     {
-        ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
-        ASMAtomicXchgU32(&pThis->cWaiters, 0);
-        ASMAtomicIncU32(&pThis->u32Version);
+        pThis->cWaking += pThis->cWaiters;
+        pThis->cWaiters = 0;
         cv_broadcast(&pThis->Cnd);
     }
@@ -212,5 +219,5 @@
     }
 
-    ASMAtomicXchgU8(&pThis->fSignaled, false);
+    pThis->fSignaled = false;
     mutex_exit(&pThis->Mtx);
 
@@ -220,10 +227,14 @@
 
 
+/**
+ * Translate milliseconds into ticks and go to sleep using the right method.
+ *
+ * @retval  >0 on normal or spurious wake-up.
+ * @retval  -1 on timeout.
+ * @retval  0 on signal.
+ */
 static int rtSemEventMultiWaitWorker(PRTSEMEVENTMULTIINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible)
 {
-    /*
-     * Translate milliseconds into ticks and go to sleep.
-     */
-    int rc = 0;
+    int rc;
     if (cMillies != RT_INDEFINITE_WAIT)
     {
@@ -269,26 +280,21 @@
     else
     {
-        ASMAtomicIncU32(&pThis->cWaiters);
+        pThis->cWaiters++;
+
+        /* This loop is only for continuing after a spurious wake-up. */
         for (;;)
         {
-            uint32_t u32VersionBeforeWait = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->u32Version);
+            uint32_t const uSignalGenBeforeWait = pThis->uSignalGen;
             rc = rtSemEventMultiWaitWorker(pThis, cMillies, fInterruptible);
-            uint32_t u32Version = ASMAtomicUoReadU32((uint32_t volatile *)&pThis->u32Version);
             if (rc > 0)
             {
                 if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
                 {
+                    if (pThis->uSignalGen == uSignalGenBeforeWait)
+                        continue; /* Spurious wake-up, go back to waiting. */
+
                     /* Retured due to call to cv_signal() or cv_broadcast() */
-                    if (u32Version != u32VersionBeforeWait)
-                    {
-                        rc = VINF_SUCCESS;
-                        ASMAtomicDecU32(&pThis->cWaking);
-                        break;
-                    }
-                    else
-                    {
-                        /* Spurious wakeup, go back to waiting */
-                        continue;
-                    }
+                    pThis->cWaking--;
+                    rc = VINF_SUCCESS;
                 }
                 else
@@ -296,5 +302,5 @@
                     /* We're being destroyed */
                     rc = VERR_SEM_DESTROYED;
-                    if (!ASMAtomicDecU32(&pThis->cWaking))
+                    if (!--pThis->cWaiters)
                     {
                         mutex_exit(&pThis->Mtx);
@@ -304,5 +310,4 @@
                         return rc;
                     }
-                    break;
                 }
             }
@@ -311,7 +316,6 @@
                 /* Returned due to timeout being reached */
                 if (pThis->cWaiters > 0)
-                    ASMAtomicDecU32(&pThis->cWaiters);
+                    pThis->cWaiters--;
                 rc = VERR_TIMEOUT;
-                break;
             }
             else
@@ -319,8 +323,8 @@
                 /* Returned due to pending signal */
                 if (pThis->cWaiters > 0)
-                    ASMAtomicDecU32(&pThis->cWaiters);
+                    pThis->cWaiters--;
                 rc = VERR_INTERRUPTED;
-                break;
             }
+            break;
         }
     }
