Index: /trunk/include/iprt/semaphore.h
===================================================================
--- /trunk/include/iprt/semaphore.h	(revision 33010)
+++ /trunk/include/iprt/semaphore.h	(revision 33011)
@@ -350,4 +350,6 @@
  * @param   hEventMultiSem      The multiple release event semaphore.
  * @param   cMillies            Number of milliseconds to wait.
+ * @todo    Rename to RTSemEventMultiWaitIntr since it is mainly for
+ *          ring-0 consumption.
  */
 RTDECL(int)  RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies);
Index: /trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile	(revision 33010)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile	(revision 33011)
@@ -119,4 +119,6 @@
         generic/RTLogWriteStdErr-stub-generic.o \
         generic/RTLogWriteStdOut-stub-generic.o \
+	generic/RTSemEventMultiWait-2-ex-generic.o \
+	generic/RTSemEventMultiWaitNoResume-2-ex-generic.o \
 	VBox/log-vbox.o \
 	VBox/logbackdoor.o
Index: /trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest	(revision 33010)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest	(revision 33011)
@@ -123,4 +123,6 @@
     ${PATH_ROOT}/src/VBox/Runtime/generic/RTLogWriteStdErr-stub-generic.cpp=>generic/RTLogWriteStdErr-stub-generic.c \
     ${PATH_ROOT}/src/VBox/Runtime/generic/RTLogWriteStdOut-stub-generic.cpp=>generic/RTLogWriteStdOut-stub-generic.c \
+    ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventMultiWait-2-ex-generic.cpp=>generic/RTSemEventMultiWait-2-ex-generic.c \
+    ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp=>generic/RTSemEventMultiWaitNoResume-2-ex-generic.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.cpp=>r0drv/alloc-r0drv.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.h=>r0drv/alloc-r0drv.h \
@@ -147,4 +149,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/thread-r0drv-linux.c=>r0drv/linux/thread-r0drv-linux.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c=>r0drv/linux/time-r0drv-linux.c \
+    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h=>r0drv/linux/waitqueue-r0drv-linux.h \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c=>r0drv/linux/RTLogWriteDebugger-r0drv-linux.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/semspinmutex-r0drv-generic.c=>r0drv/generic/semspinmutex-r0drv-generic.c \
Index: /trunk/src/VBox/HostDrivers/Support/linux/Makefile
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 33010)
+++ /trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 33011)
@@ -131,4 +131,6 @@
 	generic/RTLogWriteUser-generic.o \
 	generic/RTMpGetArraySize-generic.o \
+	generic/RTSemEventMultiWait-2-ex-generic.o \
+	generic/RTSemEventMultiWaitNoResume-2-ex-generic.o \
 	generic/RTTimerCreate-generic.o \
 	generic/uuid-generic.o \
Index: /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 33010)
+++ /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 33011)
@@ -129,4 +129,6 @@
     ${PATH_ROOT}/src/VBox/Runtime/generic/RTLogWriteUser-generic.cpp=>generic/RTLogWriteUser-generic.c \
     ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpGetArraySize-generic.cpp=>generic/RTMpGetArraySize-generic.c \
+    ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventMultiWait-2-ex-generic.cpp=>generic/RTSemEventMultiWait-2-ex-generic.c \
+    ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp=>generic/RTSemEventMultiWaitNoResume-2-ex-generic.c \
     ${PATH_ROOT}/src/VBox/Runtime/generic/RTTimerCreate-generic.cpp=>generic/RTTimerCreate-generic.c \
     ${PATH_ROOT}/src/VBox/Runtime/generic/uuid-generic.cpp=>generic/uuid-generic.c \
@@ -158,4 +160,5 @@
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c=>r0drv/linux/time-r0drv-linux.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c=>r0drv/linux/timer-r0drv-linux.c \
+    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h=>r0drv/linux/waitqueue-r0drv-linux.h \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/semspinmutex-r0drv-generic.c=>r0drv/generic/semspinmutex-r0drv-generic.c \
     ${PATH_ROOT}/src/VBox/Runtime/r0drv/memobj-r0drv.cpp=>r0drv/memobj-r0drv.c \
Index: /trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp	(revision 33010)
+++ /trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp	(revision 33011)
@@ -111,13 +111,27 @@
     RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent),          VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0),  VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 1),  VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 2),  VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 8),  VERR_TIMEOUT);
     RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,20),  VERR_TIMEOUT);
     RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent),           VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0),  VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent),           VINF_SUCCESS);
-    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,20),  VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 1),  VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent),           VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 2),  VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent),           VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 8),  VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent),           VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 20), VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent),           VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,1000),VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent),           VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventSignal(pSession, hEvent),           VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0),  VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 0),  VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 1),  VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 2),  VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent, 8),  VERR_TIMEOUT);
     RTTESTI_CHECK_RC(SUPSemEventWaitNoResume(pSession, hEvent,20),  VERR_TIMEOUT);
     RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent),            VINF_OBJECT_DESTROYED);
@@ -129,4 +143,7 @@
     RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEventMulti),            VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0),    VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1),    VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2),    VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8),    VERR_TIMEOUT);
     RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,20),    VERR_TIMEOUT);
     RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti),             VINF_SUCCESS);
@@ -134,4 +151,9 @@
     RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0),    VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0),    VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1),    VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2),    VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8),    VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,20),    VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,1000),  VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti),             VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti),             VINF_SUCCESS);
@@ -139,7 +161,15 @@
     RTTESTI_CHECK_RC(SUPSemEventMultiReset(pSession, hEventMulti),              VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0),    VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1),    VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2),    VERR_TIMEOUT);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8),    VERR_TIMEOUT);
     RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,20),    VERR_TIMEOUT);
     RTTESTI_CHECK_RC(SUPSemEventMultiSignal(pSession, hEventMulti),             VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 0),    VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 1),    VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 2),    VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 8),    VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti, 20),   VINF_SUCCESS);
+    RTTESTI_CHECK_RC(SUPSemEventMultiWaitNoResume(pSession, hEventMulti,1000),  VINF_SUCCESS);
     RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti),              VINF_OBJECT_DESTROYED);
     RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEventMulti),              VERR_INVALID_HANDLE);
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 33010)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 33011)
@@ -1430,4 +1430,6 @@
 	generic/RTAssertShouldPanic-generic.cpp \
 	generic/RTLogWriteStdOut-stub-generic.cpp \
+ 	generic/RTSemEventMultiWait-2-ex-generic.cpp \
+ 	generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp \
 	generic/mppresent-generic.cpp \
 	r0drv/linux/alloc-r0drv-linux.c \
Index: /trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c	(revision 33010)
+++ /trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c	(revision 33011)
@@ -175,5 +175,5 @@
  * @param   enmType     The object type.
  * @param   cb          The number of bytes to allocate.
- * @param   uAlignment  The alignment of the phyiscal memory.
+ * @param   uAlignment  The alignment of the physical memory.
  *                      Only valid if fContiguous == true, ignored otherwise.
  * @param   fFlagsLnx   The page allocation flags (GPFs).
Index: /trunk/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c	(revision 33010)
+++ /trunk/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c	(revision 33011)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -32,11 +32,31 @@
 #include "internal/iprt.h"
 #include <iprt/semaphore.h>
-#include <iprt/alloc.h>
+
 #include <iprt/assert.h>
 #include <iprt/asm.h>
 #include <iprt/err.h>
-
+#include <iprt/mem.h>
+#include <iprt/lockvalidator.h>
+
+#include "waitqueue-r0drv-linux.h"
 #include "internal/magics.h"
 
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** @name fStateAndGen values
+ * @{ */
+/** The state bit number. */
+#define RTSEMEVENTMULTILNX_STATE_BIT        0
+/** The state mask. */
+#define RTSEMEVENTMULTILNX_STATE_MASK       RT_BIT_32(RTSEMEVENTMULTILNX_STATE_BIT)
+/** The generation mask. */
+#define RTSEMEVENTMULTILNX_GEN_MASK         ~RTSEMEVENTMULTILNX_STATE_MASK
+/** The generation shift. */
+#define RTSEMEVENTMULTILNX_GEN_SHIFT        1
+/** The initial variable value. */
+#define RTSEMEVENTMULTILNX_STATE_GEN_INIT   UINT32_C(0xfffffffc)
+/** @}  */
 
 /*******************************************************************************
@@ -50,9 +70,14 @@
     /** Magic value (RTSEMEVENTMULTI_MAGIC). */
     uint32_t volatile   u32Magic;
-    /** The object status - !0 when signaled and 0 when reset. */
-    uint32_t volatile   fState;
+    /** The object state bit and generation counter.
+     * The generation counter is incremented every time the object is   */
+    uint32_t volatile   fStateAndGen;
+    /** Reference counter. */
+    uint32_t volatile   cRefs;
     /** The wait queue. */
     wait_queue_head_t   Head;
 } RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
+
+
 
 
@@ -73,6 +98,7 @@
     if (pThis)
     {
-        pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
-        pThis->fState   = 0;
+        pThis->u32Magic     = RTSEMEVENTMULTI_MAGIC;
+        pThis->fStateAndGen = RTSEMEVENTMULTILNX_STATE_GEN_INIT;
+        pThis->cRefs        = 1;
         init_waitqueue_head(&pThis->Head);
 
@@ -83,4 +109,31 @@
 }
 RT_EXPORT_SYMBOL(RTSemEventMultiCreate);
+
+
+/**
+ * Retain a reference to the semaphore.
+ *
+ * @param   pThis       The semaphore.
+ */
+DECLINLINE(void) rtR0SemEventMultiLnxRetain(PRTSEMEVENTMULTIINTERNAL pThis)
+{
+    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
+    Assert(cRefs && cRefs < 100000);
+}
+
+
+/**
+ * Release a reference, destroy the thing if necessary.
+ *
+ * @param   pThis       The semaphore.
+ */
+DECLINLINE(void) rtR0SemEventMultiLnxRelease(PRTSEMEVENTMULTIINTERNAL pThis)
+{
+    if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
+    {
+        Assert(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC);
+        RTMemFree(pThis);
+    }
+}
 
 
@@ -95,4 +148,5 @@
     AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
     AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
+    Assert(pThis->cRefs > 0);
 
     /*
@@ -100,8 +154,7 @@
      */
     ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC);
-    ASMAtomicXchgU32(&pThis->fState, 0);
+    ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTILNX_GEN_MASK);
     Assert(!waitqueue_active(&pThis->Head));
     wake_up_all(&pThis->Head);
-    RTMemFree(pThis);
     return VINF_SUCCESS;
 }
@@ -111,4 +164,7 @@
 RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
 {
+    uint32_t fNew;
+    uint32_t fOld;
+
     /*
      * Validate input.
@@ -119,10 +175,22 @@
     AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
     AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
-
-    /*
-     * Signal the event object.
-     */
-    ASMAtomicXchgU32(&pThis->fState, 1);
+    rtR0SemEventMultiLnxRetain(pThis);
+
+    /*
+     * Signal the event object.  The cause of the parnoia here is racing to try
+     * deal with racing RTSemEventMultiSignal calls (should probably be
+     * forbidden, but it's relatively easy to handle).
+     */
+    do
+    {
+        fNew = fOld = ASMAtomicUoReadU32(&pThis->fStateAndGen);
+        fNew += 1 << RTSEMEVENTMULTILNX_GEN_SHIFT;
+        fNew |= RTSEMEVENTMULTILNX_STATE_MASK;
+    }
+    while (!ASMAtomicCmpXchgU32(&pThis->fStateAndGen, fNew, fOld));
+
     wake_up_all(&pThis->Head);
+
+    rtR0SemEventMultiLnxRelease(pThis);
     return VINF_SUCCESS;
 }
@@ -140,9 +208,12 @@
     AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
     AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
+    rtR0SemEventMultiLnxRetain(pThis);
 
     /*
      * Reset it.
      */
-    ASMAtomicXchgU32(&pThis->fState, 0);
+    ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTILNX_STATE_MASK);
+
+    rtR0SemEventMultiLnxRelease(pThis);
     return VINF_SUCCESS;
 }
@@ -151,89 +222,95 @@
 
 /**
- * Worker for RTSemEventMulti and RTSemEventMultiNoResume.
+ * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
  *
  * @returns VBox status code.
  * @param   pThis           The event semaphore.
- * @param   cMillies            The number of milliseconds to wait.
- * @param   fInterruptible      Whether it's an interruptible wait or not.
- */
-static int rtSemEventMultiWait(PRTSEMEVENTMULTIINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible)
-{
-    /*
-     * Ok wait for it.
-     */
-    DEFINE_WAIT(Wait);
-    int     rc       = VINF_SUCCESS;
-    long    lTimeout = cMillies == RT_INDEFINITE_WAIT ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(cMillies);
-    IPRT_DEBUG_SEMS_STATE(pThis, 'E');
-    for (;;)
+ */
+static int rtR0SemEventMultiLnxWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
+                                    PCRTLOCKVALSRCPOS pSrcPos)
+{
+    uint32_t    fOrgStateAndGen;
+    int         rc;
+
+    /*
+     * Validate the input.
+     */
+    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
+    rtR0SemEventMultiLnxRetain(pThis);
+
+    /*
+     * Is the event already signalled or do we have to wait?
+     */
+    fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen);
+    if (fOrgStateAndGen & RTSEMEVENTMULTILNX_STATE_MASK)
+        rc = VINF_SUCCESS;
+    else
     {
-        /* make everything thru schedule() atomic scheduling wise. */
-        prepare_to_wait(&pThis->Head, &Wait, fInterruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-
-        /* check the condition. */
-        if (pThis->fState)
-            break;
-
-        /* check for pending signals. */
-        if (fInterruptible && signal_pending(current))
+        /*
+         * We have to wait.
+         */
+        RTR0SEMLNXWAIT Wait;
+        rc = rtR0SemLnxWaitInit(&Wait, fFlags, uTimeout, &pThis->Head);
+        if (RT_SUCCESS(rc))
         {
-            rc = VERR_INTERRUPTED;
-            break;
-        }
-
-        /* wait */
-        lTimeout = schedule_timeout(lTimeout);
-
-        after_wait(&Wait);
-
-        /* Check if someone destroyed the semaphore while we were waiting. */
-        if (pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)
-        {
-            rc = VERR_SEM_DESTROYED;
-            break;
-        }
-
-        /* check for timeout. */
-        if (!lTimeout)
-        {
-            rc = VERR_TIMEOUT;
-            break;
+            IPRT_DEBUG_SEMS_STATE(pThis, 'E');
+            for (;;)
+            {
+                /* The destruction test. */
+                if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
+                    rc = VERR_SEM_DESTROYED;
+                else
+                {
+                    rtR0SemLnxWaitPrepare(&Wait);
+
+                    /* Check the exit conditions. */
+                    if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
+                        rc = VERR_SEM_DESTROYED;
+                    else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)
+                        rc = VINF_SUCCESS;
+                    else if (rtR0SemLnxWaitHasTimedOut(&Wait))
+                        rc = VERR_TIMEOUT;
+                    else if (rtR0SemLnxWaitWasInterrupted(&Wait))
+                        rc = VERR_INTERRUPTED;
+                    else
+                    {
+                        /* Do the wait and then recheck the conditions. */
+                        rtR0SemLnxWaitDoIt(&Wait);
+                        continue;
+                    }
+                }
+                break;
+            }
+
+            rtR0SemLnxWaitDelete(&Wait);
+            IPRT_DEBUG_SEMS_STATE_RC(pThis, 'E', rc);
         }
     }
 
-    finish_wait(&pThis->Head, &Wait);
-    IPRT_DEBUG_SEMS_STATE_RC(pThis, 'E', rc);
+    rtR0SemEventMultiLnxRelease(pThis);
     return rc;
 }
 
 
-RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
-{
-    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
-    if (!pThis)
-        return VERR_INVALID_PARAMETER;
-    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
-    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
-
-    if (pThis->fState)
-        return VINF_SUCCESS;
-    return rtSemEventMultiWait(pThis, cMillies, false /* fInterruptible */);
-}
-RT_EXPORT_SYMBOL(RTSemEventMultiWait);
-
-
-RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
-{
-    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
-    if (!pThis)
-        return VERR_INVALID_PARAMETER;
-    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
-    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
-
-    if (pThis->fState)
-        return VINF_SUCCESS;
-    return rtSemEventMultiWait(pThis, cMillies, true /* fInterruptible */);
-}
-RT_EXPORT_SYMBOL(RTSemEventMultiWaitNoResume);
-
+#undef RTSemEventMultiWaitEx
+RTDECL(int)  RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
+{
+#ifndef RTSEMEVENT_STRICT
+    return rtR0SemEventMultiLnxWait(hEventMultiSem, fFlags, uTimeout, NULL);
+#else
+    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
+    return rtR0SemEventMultiLnxWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
+#endif
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiWaitEx);
+
+
+RTDECL(int)  RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
+                                        RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
+    return rtR0SemEventMultiLnxWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
+}
+RT_EXPORT_SYMBOL(RTSemEventMultiWaitExDebug);
+
Index: /trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h	(revision 33010)
+++ /trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h	(revision 33011)
@@ -347,4 +347,15 @@
 #endif
 
-#endif
-
+/*
+ * Some global indicator macros.
+ */
+/** @def IPRT_LINUX_HAS_HRTIMER
+ * Whether the kernel support high resolution timers (Linux kernel versions
+ * 2.6.28 and later (hrtimer_add_expires_ns() & schedule_hrtimeout). */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+# define IPRT_LINUX_HAS_HRTIMER
+#endif
+
+
+#endif
+
Index: /trunk/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c	(revision 33010)
+++ /trunk/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c	(revision 33011)
@@ -44,15 +44,8 @@
 #include "internal/magics.h"
 
-/** @def RTTIMER_LINUX_HAVE_HRTIMER
- * Whether the kernel support high resolution timers (Linux kernel versions
- * 2.6.28 and later (hrtimer_add_expires_ns()). */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
-# define RTTIMER_LINUX_HAVE_HRTIMER
-#endif
-
 /** @def RTTIMER_LINUX_WITH_HRTIMER
  * Whether to use high resolution timers.  */
 #if !defined(RTTIMER_LINUX_WITH_HRTIMER) \
-    && defined(RTTIMER_LINUX_HAVE_HRTIMER)
+    && defined(IPRT_LINUX_HAS_HRTIMER)
 # define RTTIMER_LINUX_WITH_HRTIMER
 #endif
