Index: trunk/include/VBox/sup.h
===================================================================
--- trunk/include/VBox/sup.h	(revision 33166)
+++ trunk/include/VBox/sup.h	(revision 33167)
@@ -385,4 +385,33 @@
 SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
 
+/**
+ * Waits on a single release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param   pSession            The session handle of the caller.
+ * @param   hEvent              The semaphore handle.
+ * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
+ */
+SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout);
+
+/**
+ * Waits on a single release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param   pSession            The session handle of the caller.
+ * @param   hEvent              The semaphore handle.
+ * @param   cNsTimeout          The number of nanoseconds to wait.
+ */
+SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout);
+
+/**
+ * Gets the best timeout resolution that SUPSemEventWaitNsAbsIntr and
+ * SUPSemEventWaitNsAbsIntr can do.
+ *
+ * @returns The resolution in nanoseconds.
+ * @param   pSession            The session handle of the caller.
+ */
+SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession);
+
 
 /** Multiple release event semaphore handle. Ring-0 / ring-3. */
@@ -455,4 +484,33 @@
  */
 SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
+
+/**
+ * Waits on a multiple release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param   pSession            The session handle of the caller.
+ * @param   hEventMulti         The semaphore handle.
+ * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
+ */
+SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout);
+
+/**
+ * Waits on a multiple release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param   pSession            The session handle of the caller.
+ * @param   hEventMulti         The semaphore handle.
+ * @param   cNsTimeout          The number of nanoseconds to wait.
+ */
+SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout);
+
+/**
+ * Gets the best timeout resolution that SUPSemEventMultiWaitNsAbsIntr and
+ * SUPSemEventMultiWaitNsRelIntr can do.
+ *
+ * @returns The resolution in nanoseconds.
+ * @param   pSession            The session handle of the caller.
+ */
+SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession);
 
 
Index: trunk/src/VBox/HostDrivers/Support/SUPDrv.c
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 33166)
+++ trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 33167)
@@ -176,4 +176,7 @@
     { "SUPSemEventWait",                        (void *)SUPSemEventWait },
     { "SUPSemEventWaitNoResume",                (void *)SUPSemEventWaitNoResume },
+    { "SUPSemEventWaitNsAbsIntr",               (void *)SUPSemEventWaitNsAbsIntr },
+    { "SUPSemEventWaitNsRelIntr",               (void *)SUPSemEventWaitNsRelIntr },
+    { "SUPSemEventGetResolution",               (void *)SUPSemEventGetResolution },
     { "SUPSemEventMultiCreate",                 (void *)SUPSemEventMultiCreate },
     { "SUPSemEventMultiClose",                  (void *)SUPSemEventMultiClose },
@@ -182,4 +185,7 @@
     { "SUPSemEventMultiWait",                   (void *)SUPSemEventMultiWait },
     { "SUPSemEventMultiWaitNoResume",           (void *)SUPSemEventMultiWaitNoResume },
+    { "SUPSemEventMultiWaitNsAbsIntr",          (void *)SUPSemEventMultiWaitNsAbsIntr },
+    { "SUPSemEventMultiWaitNsRelIntr",          (void *)SUPSemEventMultiWaitNsRelIntr },
+    { "SUPSemEventMultiGetResolution",          (void *)SUPSemEventMultiGetResolution },
     { "SUPR0GetPagingMode",                     (void *)SUPR0GetPagingMode },
     { "SUPR0EnableVTx",                         (void *)SUPR0EnableVTx },
@@ -234,4 +240,7 @@
     { "RTSemEventWait",                         (void *)RTSemEventWait },
     { "RTSemEventWaitNoResume",                 (void *)RTSemEventWaitNoResume },
+    { "RTSemEventWaitEx",                       (void *)RTSemEventWaitEx },
+    { "RTSemEventWaitExDebug",                  (void *)RTSemEventWaitExDebug },
+    { "RTSemEventGetResolution",                (void *)RTSemEventGetResolution },
     { "RTSemEventDestroy",                      (void *)RTSemEventDestroy },
     { "RTSemEventMultiCreate",                  (void *)RTSemEventMultiCreate },
@@ -240,4 +249,7 @@
     { "RTSemEventMultiWait",                    (void *)RTSemEventMultiWait },
     { "RTSemEventMultiWaitNoResume",            (void *)RTSemEventMultiWaitNoResume },
+    { "RTSemEventMultiWaitEx",                  (void *)RTSemEventMultiWaitEx },
+    { "RTSemEventMultiWaitExDebug",             (void *)RTSemEventMultiWaitExDebug },
+    { "RTSemEventMultiGetResolution",           (void *)RTSemEventMultiGetResolution },
     { "RTSemEventMultiDestroy",                 (void *)RTSemEventMultiDestroy },
     { "RTSpinlockCreate",                       (void *)RTSpinlockCreate },
@@ -1628,4 +1640,141 @@
         }
 
+        case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_SEM_OP2):
+        {
+            /* validate */
+            PSUPSEMOP2 pReq = (PSUPSEMOP2)pReqHdr;
+            REQ_CHECK_SIZES_EX(SUP_IOCTL_SEM_OP2, SUP_IOCTL_SEM_OP2_SIZE_IN, SUP_IOCTL_SEM_OP2_SIZE_OUT);
+            REQ_CHECK_EXPR(SUP_IOCTL_SEM_OP2, pReq->u.In.uReserved == 0);
+
+            /* execute */
+            switch (pReq->u.In.uType)
+            {
+                case SUP_SEM_TYPE_EVENT:
+                {
+                    SUPSEMEVENT hEvent = (SUPSEMEVENT)(uintptr_t)pReq->u.In.hSem;
+                    switch (pReq->u.In.uOp)
+                    {
+                        case SUPSEMOP2_WAIT_MS_REL:
+                            pReq->Hdr.rc = SUPSemEventWaitNoResume(pSession, hEvent, pReq->u.In.uArg.cRelMsTimeout);
+                            break;
+                        case SUPSEMOP2_WAIT_NS_ABS:
+                            pReq->Hdr.rc = SUPSemEventWaitNsAbsIntr(pSession, hEvent, pReq->u.In.uArg.uAbsNsTimeout);
+                            break;
+                        case SUPSEMOP2_WAIT_NS_REL:
+                            pReq->Hdr.rc = SUPSemEventWaitNsRelIntr(pSession, hEvent, pReq->u.In.uArg.cRelNsTimeout);
+                            break;
+                        case SUPSEMOP2_SIGNAL:
+                            pReq->Hdr.rc = SUPSemEventSignal(pSession, hEvent);
+                            break;
+                        case SUPSEMOP2_CLOSE:
+                            pReq->Hdr.rc = SUPSemEventClose(pSession, hEvent);
+                            break;
+                        case SUPSEMOP2_RESET:
+                        default:
+                            pReq->Hdr.rc = VERR_INVALID_FUNCTION;
+                            break;
+                    }
+                    break;
+                }
+
+                case SUP_SEM_TYPE_EVENT_MULTI:
+                {
+                    SUPSEMEVENTMULTI hEventMulti = (SUPSEMEVENTMULTI)(uintptr_t)pReq->u.In.hSem;
+                    switch (pReq->u.In.uOp)
+                    {
+                        case SUPSEMOP2_WAIT_MS_REL:
+                            pReq->Hdr.rc = SUPSemEventMultiWaitNoResume(pSession, hEventMulti, pReq->u.In.uArg.cRelMsTimeout);
+                            break;
+                        case SUPSEMOP2_WAIT_NS_ABS:
+                            pReq->Hdr.rc = SUPSemEventMultiWaitNsAbsIntr(pSession, hEventMulti, pReq->u.In.uArg.uAbsNsTimeout);
+                            break;
+                        case SUPSEMOP2_WAIT_NS_REL:
+                            pReq->Hdr.rc = SUPSemEventMultiWaitNsRelIntr(pSession, hEventMulti, pReq->u.In.uArg.cRelNsTimeout);
+                            break;
+                        case SUPSEMOP2_SIGNAL:
+                            pReq->Hdr.rc = SUPSemEventMultiSignal(pSession, hEventMulti);
+                            break;
+                        case SUPSEMOP2_CLOSE:
+                            pReq->Hdr.rc = SUPSemEventMultiClose(pSession, hEventMulti);
+                            break;
+                        case SUPSEMOP2_RESET:
+                            pReq->Hdr.rc = SUPSemEventMultiReset(pSession, hEventMulti);
+                            break;
+                        default:
+                            pReq->Hdr.rc = VERR_INVALID_FUNCTION;
+                            break;
+                    }
+                    break;
+                }
+
+                default:
+                    pReq->Hdr.rc = VERR_INVALID_PARAMETER;
+                    break;
+            }
+            return 0;
+        }
+
+        case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_SEM_OP3):
+        {
+            /* validate */
+            PSUPSEMOP3 pReq = (PSUPSEMOP3)pReqHdr;
+            REQ_CHECK_SIZES_EX(SUP_IOCTL_SEM_OP3, SUP_IOCTL_SEM_OP3_SIZE_IN, SUP_IOCTL_SEM_OP3_SIZE_OUT);
+            REQ_CHECK_EXPR(SUP_IOCTL_SEM_OP3, pReq->u.In.u32Reserved == 0 && pReq->u.In.u64Reserved == 0);
+
+            /* execute */
+            switch (pReq->u.In.uType)
+            {
+                case SUP_SEM_TYPE_EVENT:
+                {
+                    SUPSEMEVENT hEvent = (SUPSEMEVENT)(uintptr_t)pReq->u.In.hSem;
+                    switch (pReq->u.In.uOp)
+                    {
+                        case SUPSEMOP3_CREATE:
+                            REQ_CHECK_EXPR(SUP_IOCTL_SEM_OP3, hEvent == NIL_SUPSEMEVENT);
+                            pReq->Hdr.rc = SUPSemEventCreate(pSession, &hEvent);
+                            pReq->u.Out.hSem = (uint32_t)(uintptr_t)hEvent;
+                            break;
+                        case SUPSEMOP3_GET_RESOLUTION:
+                            REQ_CHECK_EXPR(SUP_IOCTL_SEM_OP3, hEvent == NIL_SUPSEMEVENT);
+                            pReq->Hdr.rc = VINF_SUCCESS;
+                            pReq->Hdr.cbOut = sizeof(*pReq);
+                            pReq->u.Out.cNsResolution = SUPSemEventGetResolution(pSession);
+                            break;
+                        default:
+                            pReq->Hdr.rc = VERR_INVALID_FUNCTION;
+                            break;
+                    }
+                    break;
+                }
+
+                case SUP_SEM_TYPE_EVENT_MULTI:
+                {
+                    SUPSEMEVENTMULTI hEventMulti = (SUPSEMEVENTMULTI)(uintptr_t)pReq->u.In.hSem;
+                    switch (pReq->u.In.uOp)
+                    {
+                        case SUPSEMOP3_CREATE:
+                            REQ_CHECK_EXPR(SUP_IOCTL_SEM_OP3, hEventMulti == NIL_SUPSEMEVENTMULTI);
+                            pReq->Hdr.rc = SUPSemEventMultiCreate(pSession, &hEventMulti);
+                            pReq->u.Out.hSem = (uint32_t)(uintptr_t)hEventMulti;
+                            break;
+                        case SUPSEMOP3_GET_RESOLUTION:
+                            REQ_CHECK_EXPR(SUP_IOCTL_SEM_OP3, hEventMulti == NIL_SUPSEMEVENTMULTI);
+                            pReq->Hdr.rc = VINF_SUCCESS;
+                            pReq->u.Out.cNsResolution = SUPSemEventMultiGetResolution(pSession);
+                            break;
+                        default:
+                            pReq->Hdr.rc = VERR_INVALID_FUNCTION;
+                            break;
+                    }
+                    break;
+                }
+
+                default:
+                    pReq->Hdr.rc = VERR_INVALID_PARAMETER;
+                    break;
+            }
+            return 0;
+        }
+
         case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_VT_CAPS):
         {
Index: trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 33166)
+++ trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 33167)
@@ -191,7 +191,7 @@
  *
  * @todo Pending work on next major version change:
- *          - Nothing.
- */
-#define SUPDRV_IOC_VERSION                              0x00150003
+ *          - Remove SUPSEMOP and SUPSEMCREATE.
+ */
+#define SUPDRV_IOC_VERSION                              0x00150004
 
 /** SUP_IOCTL_COOKIE. */
@@ -1019,4 +1019,5 @@
 /** @name SUP_IOCTL_SEM_CREATE
  * Create a semaphore
+ * @todo remove this interface with the next major version change.
  * @{
  */
@@ -1049,4 +1050,5 @@
 /** @name SUP_IOCTL_SEM_OP
  * Semaphore operations.
+ * @todo remove this interface with the next major version change.
  * @{
  */
@@ -1075,5 +1077,5 @@
 } SUPSEMOP, *PSUPSEMOP;
 
-/** Wait for a number of millisecons. */
+/** Wait for a number of milliseconds. */
 #define SUPSEMOP_WAIT       0
 /** Signal the semaphore. */
@@ -1086,4 +1088,112 @@
 /** @} */
 
+/** @name SUP_IOCTL_SEM_OP2
+ * Semaphore operations.
+ * @remarks This replaces the old SUP_IOCTL_SEM_OP interface.
+ * @{
+ */
+#define SUP_IOCTL_SEM_OP2                               SUP_CTL_CODE_SIZE(27, SUP_IOCTL_SEM_OP2_SIZE)
+#define SUP_IOCTL_SEM_OP2_SIZE                          sizeof(SUPSEMOP2)
+#define SUP_IOCTL_SEM_OP2_SIZE_IN                       sizeof(SUPSEMOP2)
+#define SUP_IOCTL_SEM_OP2_SIZE_OUT                      sizeof(SUPREQHDR)
+typedef struct SUPSEMOP2
+{
+    /** The header. */
+    SUPREQHDR               Hdr;
+    union
+    {
+        struct
+        {
+            /** The semaphore type. */
+            uint32_t        uType;
+            /** The semaphore handle. */
+            uint32_t        hSem;
+            /** The operation. */
+            uint32_t        uOp;
+            /** Reserved, must be zero. */
+            uint32_t        uReserved;
+            /** The number of milliseconds to wait if it's a wait operation. */
+            union
+            {
+                /** Absolute timeout (RTTime[System]NanoTS).
+                 * Used by SUPSEMOP2_WAIT_NS_ABS. */
+                uint64_t    uAbsNsTimeout;
+                /** Relative nanosecond timeout.
+                 * Used by SUPSEMOP2_WAIT_NS_REL. */
+                uint64_t    cRelNsTimeout;
+                /** Relative millisecond timeout.
+                 * Used by SUPSEMOP2_WAIT_MS_REL. */
+                uint32_t    cRelMsTimeout;
+                /** Generic 64-bit accessor.
+                 * ASSUMES little endian!  */
+                uint64_t    u64;
+            } uArg;
+        } In;
+    } u;
+} SUPSEMOP2, *PSUPSEMOP2;
+
+/** Wait for a number of milliseconds. */
+#define SUPSEMOP2_WAIT_MS_REL       0
+/** Wait until the specified deadline is reached. */
+#define SUPSEMOP2_WAIT_NS_ABS       1
+/** Wait for a number of nanoseconds. */
+#define SUPSEMOP2_WAIT_NS_REL       2
+/** Signal the semaphore. */
+#define SUPSEMOP2_SIGNAL            3
+/** Reset the sempahore (only applicable to SUP_SEM_TYPE_EVENT_MULTI). */
+#define SUPSEMOP2_RESET             4
+/** Close the semaphore handle. */
+#define SUPSEMOP2_CLOSE             5
+/** @} */
+
+/** @name SUP_IOCTL_SEM_OP3
+ * Semaphore operations.
+ * @{
+ */
+#define SUP_IOCTL_SEM_OP3                               SUP_CTL_CODE_SIZE(28, SUP_IOCTL_SEM_OP3_SIZE)
+#define SUP_IOCTL_SEM_OP3_SIZE                          sizeof(SUPSEMOP3)
+#define SUP_IOCTL_SEM_OP3_SIZE_IN                       sizeof(SUPSEMOP3)
+#define SUP_IOCTL_SEM_OP3_SIZE_OUT                      sizeof(SUPSEMOP3)
+typedef struct SUPSEMOP3
+{
+    /** The header. */
+    SUPREQHDR               Hdr;
+    union
+    {
+        struct
+        {
+            /** The semaphore type. */
+            uint32_t        uType;
+            /** The semaphore handle. */
+            uint32_t        hSem;
+            /** The operation. */
+            uint32_t        uOp;
+            /** Reserved, must be zero. */
+            uint32_t        u32Reserved;
+            /** Reserved for future use. */
+            uint64_t        u64Reserved;
+        } In;
+        union
+        {
+            /** The handle of the created semaphore.
+             * Used by SUPSEMOP3_CREATE. */
+            uint32_t        hSem;
+            /** The semaphore resolution in nano seconds.
+             * Used by SUPSEMOP3_GET_RESOLUTION. */
+            uint32_t        cNsResolution;
+            /** The 32-bit view. */
+            uint32_t        u32;
+            /** Reserved some space for later expansion. */
+            uint64_t        u64Reserved;
+        } Out;
+    } u;
+} SUPSEMOP3, *PSUPSEMOP3;
+
+/** Get the wait resolution.  */
+#define SUPSEMOP3_CREATE            0
+/** Get the wait resolution.  */
+#define SUPSEMOP3_GET_RESOLUTION    1
+/** @} */
+
 /** @name SUP_IOCTL_VT_CAPS
  * Get the VT-x/AMD-V capabilities.
Index: trunk/src/VBox/HostDrivers/Support/SUPDrvSem.c
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPDrvSem.c	(revision 33166)
+++ trunk/src/VBox/HostDrivers/Support/SUPDrvSem.c	(revision 33167)
@@ -156,5 +156,5 @@
 
 
-SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
+static int supR0SemEventWaitEx(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t fFlags, uint64_t uTimeout)
 {
     int         rc;
@@ -176,5 +176,5 @@
      * Do the job.
      */
-    rc = RTSemEventWait((RTSEMEVENT)pObj->pvUser1, cMillies);
+    rc = RTSemEventWaitEx((RTSEMEVENT)pObj->pvUser1, fFlags, uTimeout);
 
     SUPR0ObjRelease(pObj, pSession);
@@ -183,28 +183,40 @@
 
 
+SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
+{
+    uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_UNINTERRUPTIBLE;
+    if (cMillies == RT_INDEFINITE_WAIT)
+        fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
+    return supR0SemEventWaitEx(pSession, hEvent, fFlags, cMillies);
+}
+
+
 SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
 {
-    int         rc;
-    uint32_t    h32;
-    PSUPDRVOBJ  pObj;
-
-    /*
-     * Input validation.
-     */
-    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
-    h32 = (uint32_t)(uintptr_t)hEvent;
-    if (h32 != (uintptr_t)hEvent)
-        return VERR_INVALID_HANDLE;
-    pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT);
-    if (!pObj)
-        return VERR_INVALID_HANDLE;
-
-    /*
-     * Do the job.
-     */
-    rc = RTSemEventWaitNoResume((RTSEMEVENT)pObj->pvUser1, cMillies);
-
-    SUPR0ObjRelease(pObj, pSession);
-    return rc;
+    uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
+    if (cMillies == RT_INDEFINITE_WAIT)
+        fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
+    return supR0SemEventWaitEx(pSession, hEvent, fFlags, cMillies);
+}
+
+
+SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
+{
+    uint32_t fFlags = RTSEMWAIT_FLAGS_ABSOLUTE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
+    return supR0SemEventWaitEx(pSession, hEvent, fFlags, uNsTimeout);
+}
+
+
+SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
+{
+    uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
+    return supR0SemEventWaitEx(pSession, hEvent, fFlags, cNsTimeout);
+}
+
+
+SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession)
+{
+    Assert(SUP_IS_SESSION_VALID(pSession));
+    return RTSemEventGetResolution();
 }
 
@@ -343,5 +355,5 @@
 
 
-SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
+static int supR0SemEventMultiWaitEx(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t fFlags, uint64_t uTimeout)
 {
     int         rc;
@@ -363,5 +375,5 @@
      * Do the job.
      */
-    rc = RTSemEventMultiWait((RTSEMEVENTMULTI)pObj->pvUser1, cMillies);
+    rc = RTSemEventMultiWaitEx((RTSEMEVENTMULTI)pObj->pvUser1, fFlags, uTimeout);
 
     SUPR0ObjRelease(pObj, pSession);
@@ -369,29 +381,41 @@
 }
 
+SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
+{
+    uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_UNINTERRUPTIBLE;
+    if (cMillies == RT_INDEFINITE_WAIT)
+        fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
+    return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cMillies);
+}
+
+
 
 SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
 {
-    int         rc;
-    uint32_t    h32;
-    PSUPDRVOBJ  pObj;
-
-    /*
-     * Input validation.
-     */
-    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
-    h32 = (uint32_t)(uintptr_t)hEventMulti;
-    if (h32 != (uintptr_t)hEventMulti)
-        return VERR_INVALID_HANDLE;
-    pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
-    if (!pObj)
-        return VERR_INVALID_HANDLE;
-
-    /*
-     * Do the job.
-     */
-    rc = RTSemEventMultiWaitNoResume((RTSEMEVENTMULTI)pObj->pvUser1, cMillies);
-
-    SUPR0ObjRelease(pObj, pSession);
-    return rc;
-}
-
+    uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
+    if (cMillies == RT_INDEFINITE_WAIT)
+        fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
+    return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cMillies);
+}
+
+
+SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout)
+{
+    uint32_t fFlags = RTSEMWAIT_FLAGS_ABSOLUTE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
+    return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, uNsTimeout);
+}
+
+
+SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout)
+{
+    uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
+    return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cNsTimeout);
+}
+
+
+SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession)
+{
+    Assert(SUP_IS_SESSION_VALID(pSession));
+    return RTSemEventMultiGetResolution();
+}
+
Index: trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 33166)
+++ trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 33167)
@@ -269,5 +269,5 @@
         CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
         const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00150000
-                                   ?  0x00150003
+                                   ?  0x00150004
                                    : SUPDRV_IOC_VERSION & 0xffff0000;
         CookieReq.u.In.u32MinVersion = uMinVersion;
Index: trunk/src/VBox/HostDrivers/Support/SUPLibSem.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPLibSem.cpp	(revision 33166)
+++ trunk/src/VBox/HostDrivers/Support/SUPLibSem.cpp	(revision 33167)
@@ -41,5 +41,5 @@
 
 /**
- * Worker that makes a SUP_IOCTL_SEM_OP request.
+ * Worker that makes a SUP_IOCTL_SEM_OP2 request.
  *
  * @returns VBox status code.
@@ -48,13 +48,13 @@
  * @param   hSem                The semaphore handle.
  * @param   uOp                 The operation.
- * @param   cMillies            The timeout if applicable, otherwise 0.
- */
-DECLINLINE(int) supSemOp(PSUPDRVSESSION pSession, uint32_t uType, uintptr_t hSem, uint32_t uOp, uint32_t cMillies)
-{
-    SUPSEMOP Req;
+ * @param   u64Arg              The argument if applicable, otherwise 0.
+ */
+DECLINLINE(int) supSemOp2(PSUPDRVSESSION pSession, uint32_t uType, uintptr_t hSem, uint32_t uOp, uint64_t u64Arg)
+{
+    SUPSEMOP2 Req;
     Req.Hdr.u32Cookie           = g_u32Cookie;
     Req.Hdr.u32SessionCookie    = g_u32SessionCookie;
-    Req.Hdr.cbIn                = SUP_IOCTL_SEM_OP_SIZE_IN;
-    Req.Hdr.cbOut               = SUP_IOCTL_SEM_OP_SIZE_OUT;
+    Req.Hdr.cbIn                = SUP_IOCTL_SEM_OP2_SIZE_IN;
+    Req.Hdr.cbOut               = SUP_IOCTL_SEM_OP2_SIZE_OUT;
     Req.Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
     Req.Hdr.rc                  = VERR_INTERNAL_ERROR;
@@ -63,6 +63,7 @@
     AssertReturn(Req.u.In.hSem == hSem, VERR_INVALID_HANDLE);
     Req.u.In.uOp                = uOp;
-    Req.u.In.cMillies           = cMillies;
-    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SEM_OP, &Req, sizeof(Req));
+    Req.u.In.uReserved          = 0;
+    Req.u.In.uArg.u64           = u64Arg;
+    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SEM_OP2, &Req, sizeof(Req));
     if (RT_SUCCESS(rc))
         rc = Req.Hdr.rc;
@@ -72,24 +73,45 @@
 
 
+/**
+ * Worker that makes a SUP_IOCTL_SEM_OP3 request.
+ *
+ * @returns VBox status code.
+ * @param   pSession            The session handle.
+ * @param   uType               The semaphore type.
+ * @param   hSem                The semaphore handle.
+ * @param   uOp                 The operation.
+ * @param   pReq                The request structure.  The caller should pick
+ *                              the output data from it himself.
+ */
+DECLINLINE(int) supSemOp3(PSUPDRVSESSION pSession, uint32_t uType, uintptr_t hSem, uint32_t uOp, PSUPSEMOP3 pReq)
+{
+    pReq->Hdr.u32Cookie           = g_u32Cookie;
+    pReq->Hdr.u32SessionCookie    = g_u32SessionCookie;
+    pReq->Hdr.cbIn                = SUP_IOCTL_SEM_OP3_SIZE_IN;
+    pReq->Hdr.cbOut               = SUP_IOCTL_SEM_OP3_SIZE_OUT;
+    pReq->Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
+    pReq->Hdr.rc                  = VERR_INTERNAL_ERROR;
+    pReq->u.In.uType              = uType;
+    pReq->u.In.hSem               = (uint32_t)hSem;
+    AssertReturn(pReq->u.In.hSem == hSem, VERR_INVALID_HANDLE);
+    pReq->u.In.uOp                = uOp;
+    pReq->u.In.u32Reserved        = 0;
+    pReq->u.In.u64Reserved        = 0;
+    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SEM_OP3, pReq, sizeof(*pReq));
+    if (RT_SUCCESS(rc))
+        rc = pReq->Hdr.rc;
+
+    return rc;
+}
+
+
 SUPDECL(int) SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent)
 {
     AssertPtrReturn(phEvent, VERR_INVALID_POINTER);
 
-    SUPSEMCREATE Req;
-    Req.Hdr.u32Cookie           = g_u32Cookie;
-    Req.Hdr.u32SessionCookie    = g_u32SessionCookie;
-    Req.Hdr.cbIn                = SUP_IOCTL_SEM_CREATE_SIZE_IN;
-    Req.Hdr.cbOut               = SUP_IOCTL_SEM_CREATE_SIZE_OUT;
-    Req.Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
-    Req.Hdr.rc                  = VERR_INTERNAL_ERROR;
-    Req.u.In.uType              = SUP_SEM_TYPE_EVENT;
-    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SEM_CREATE, &Req, sizeof(Req));
-    if (RT_SUCCESS(rc))
-    {
-        rc = Req.Hdr.rc;
-        if (RT_SUCCESS(rc))
-            *phEvent = (SUPSEMEVENT)(uintptr_t)Req.u.Out.hSem;
-    }
-
+    SUPSEMOP3 Req;
+    int rc = supSemOp3(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)NIL_SUPSEMEVENT, SUPSEMOP3_CREATE, &Req);
+    if (RT_SUCCESS(rc))
+        *phEvent = (SUPSEMEVENT)(uintptr_t)Req.u.Out.hSem;
     return rc;
 }
@@ -100,5 +122,5 @@
     if (hEvent == NIL_SUPSEMEVENT)
         return VINF_SUCCESS;
-    return supSemOp(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)hEvent, SUPSEMOP_CLOSE, 0);
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)hEvent, SUPSEMOP2_CLOSE, 0);
 }
 
@@ -106,5 +128,5 @@
 SUPDECL(int) SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
 {
-    return supSemOp(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)hEvent, SUPSEMOP_SIGNAL, 0);
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)hEvent, SUPSEMOP2_SIGNAL, 0);
 }
 
@@ -112,6 +134,32 @@
 SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
 {
-    return supSemOp(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)hEvent, SUPSEMOP_WAIT, cMillies);
-}
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)hEvent, SUPSEMOP2_WAIT_MS_REL, cMillies);
+}
+
+
+SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
+{
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)hEvent, SUPSEMOP2_WAIT_NS_ABS, uNsTimeout);
+}
+
+
+SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
+{
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)hEvent, SUPSEMOP2_WAIT_NS_REL, cNsTimeout);
+}
+
+
+SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession)
+{
+    SUPSEMOP3 Req;
+    int rc = supSemOp3(pSession, SUP_SEM_TYPE_EVENT, (uintptr_t)NIL_SUPSEMEVENT, SUPSEMOP3_GET_RESOLUTION, &Req);
+    if (RT_SUCCESS(rc))
+        return Req.u.Out.cNsResolution;
+    return 1000 / 100;
+}
+
+
+
+
 
 SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti)
@@ -119,20 +167,8 @@
     AssertPtrReturn(phEventMulti, VERR_INVALID_POINTER);
 
-    SUPSEMCREATE Req;
-    Req.Hdr.u32Cookie           = g_u32Cookie;
-    Req.Hdr.u32SessionCookie    = g_u32SessionCookie;
-    Req.Hdr.cbIn                = SUP_IOCTL_SEM_CREATE_SIZE_IN;
-    Req.Hdr.cbOut               = SUP_IOCTL_SEM_CREATE_SIZE_OUT;
-    Req.Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
-    Req.Hdr.rc                  = VERR_INTERNAL_ERROR;
-    Req.u.In.uType              = SUP_SEM_TYPE_EVENT_MULTI;
-    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SEM_CREATE, &Req, sizeof(Req));
-    if (RT_SUCCESS(rc))
-    {
-        rc = Req.Hdr.rc;
-        if (RT_SUCCESS(rc))
-            *phEventMulti = (SUPSEMEVENTMULTI)(uintptr_t)Req.u.Out.hSem;
-    }
-
+    SUPSEMOP3 Req;
+    int rc = supSemOp3(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)NIL_SUPSEMEVENTMULTI, SUPSEMOP3_CREATE, &Req);
+    if (RT_SUCCESS(rc))
+        *phEventMulti = (SUPSEMEVENTMULTI)(uintptr_t)Req.u.Out.hSem;
     return rc;
 }
@@ -143,5 +179,5 @@
     if (hEventMulti == NIL_SUPSEMEVENTMULTI)
         return VINF_SUCCESS;
-    return supSemOp(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP_CLOSE, 0);
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP2_CLOSE, 0);
 }
 
@@ -149,5 +185,5 @@
 SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
 {
-    return supSemOp(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP_SIGNAL, 0);
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP2_SIGNAL, 0);
 }
 
@@ -155,5 +191,5 @@
 SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
 {
-    return supSemOp(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP_RESET, 0);
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP2_RESET, 0);
 }
 
@@ -161,5 +197,27 @@
 SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
 {
-    return supSemOp(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP_WAIT, cMillies);
-}
-
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP2_WAIT_MS_REL, cMillies);
+}
+
+
+SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout)
+{
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP2_WAIT_NS_ABS, uNsTimeout);
+}
+
+
+SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout)
+{
+    return supSemOp2(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)hEventMulti, SUPSEMOP2_WAIT_NS_REL, cNsTimeout);
+}
+
+
+SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession)
+{
+    SUPSEMOP3 Req;
+    int rc = supSemOp3(pSession, SUP_SEM_TYPE_EVENT_MULTI, (uintptr_t)NIL_SUPSEMEVENTMULTI, SUPSEMOP3_GET_RESOLUTION, &Req);
+    if (RT_SUCCESS(rc))
+        return Req.u.Out.cNsResolution;
+    return 1000 / 100;
+}
+
Index: trunk/src/VBox/HostDrivers/Support/SUPR0.def
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPR0.def	(revision 33166)
+++ trunk/src/VBox/HostDrivers/Support/SUPR0.def	(revision 33167)
@@ -56,4 +56,7 @@
     SUPSemEventWait
     SUPSemEventWaitNoResume
+    SUPSemEventWaitNsAbsIntr
+    SUPSemEventWaitNsRelIntr
+    SUPSemEventGetResolution
     SUPSemEventMultiCreate
     SUPSemEventMultiClose
@@ -62,4 +65,7 @@
     SUPSemEventMultiWait
     SUPSemEventMultiWaitNoResume
+    SUPSemEventMultiWaitNsAbsIntr
+    SUPSemEventMultiWaitNsRelIntr
+    SUPSemEventMultiGetResolution
     SUPR0GetPagingMode
     SUPR0EnableVTx
@@ -101,4 +107,7 @@
     RTSemEventWait
     RTSemEventWaitNoResume
+    RTSemEventWaitEx
+    RTSemEventWaitExDebug
+    RTSemEventGetResolution
     RTSemEventDestroy
     RTSemEventMultiCreate
@@ -107,4 +116,7 @@
     RTSemEventMultiWait
     RTSemEventMultiWaitNoResume
+    RTSemEventMultiWaitEx
+    RTSemEventMultiWaitExDebug
+    RTSemEventMultiGetResolution
     RTSemEventMultiDestroy
     RTSemFastMutexCreate
Index: trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp	(revision 33166)
+++ trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp	(revision 33167)
@@ -70,4 +70,10 @@
 int main(int argc, char **argv)
 {
+    bool fSys = true;
+    bool fGip = false;
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
+    fGip = true;
+#endif
+
     /*
      * Init.
@@ -283,78 +289,278 @@
 #endif /* !OS2 && !WINDOWS */
 
-    if (RTTestErrorCount(hTest) == 0)
     {
-        RTTestSub(hTest, "SRE Timeout Accuracy");
-        RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
-
         static unsigned const s_acMsIntervals[] = { 0, 1, 2, 3, 4, 8, 10, 16, 32 };
-        for (unsigned i = 0; i < RT_ELEMENTS(s_acMsIntervals); i++)
-        {
-            uint64_t cMs        = s_acMsIntervals[i];
-            uint64_t cNsMinSys  = UINT64_MAX;
-            uint64_t cNsMin     = UINT64_MAX;
-            uint64_t cNsTotalSys= 0;
-            uint64_t cNsTotal   = 0;
-            for (unsigned j = 0; j < 10; j++)
+        if (RTTestErrorCount(hTest) == 0)
+        {
+            RTTestSub(hTest, "SRE Timeout Accuracy (ms)");
+            RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
+
+            for (unsigned i = 0; i < RT_ELEMENTS(s_acMsIntervals); i++)
             {
-                uint64_t u64StartSys = RTTimeSystemNanoTS();
-                uint64_t u64Start    = RTTimeNanoTS();
-                int rcX = SUPSemEventWaitNoResume(pSession, hEvent, cMs);
-                if (rc == VERR_TIMEOUT)
-                    RTTestFailed(hTest, "%Rrc j=%u cMs=%u", rcX, j, cMs);
-                uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
-                uint64_t cNsElapsed    = RTTimeNanoTS()       - u64Start;
-                if (cNsElapsedSys < cNsMinSys)
-                    cNsMinSys = cNsElapsedSys;
-                if (cNsElapsed < cNsMin)
-                    cNsMin = cNsElapsed;
-                cNsTotalSys += cNsElapsedSys;
-                cNsTotal    += cNsElapsed;
+                uint64_t cMs        = s_acMsIntervals[i];
+                uint64_t cNsMinSys  = UINT64_MAX;
+                uint64_t cNsMin     = UINT64_MAX;
+                uint64_t cNsTotalSys= 0;
+                uint64_t cNsTotal   = 0;
+                for (unsigned j = 0; j < 10; j++)
+                {
+                    uint64_t u64StartSys = RTTimeSystemNanoTS();
+                    uint64_t u64Start    = RTTimeNanoTS();
+                    int rcX = SUPSemEventWaitNoResume(pSession, hEvent, cMs);
+                    if (rc == VERR_TIMEOUT)
+                        RTTestFailed(hTest, "%Rrc j=%u cMs=%u", rcX, j, cMs);
+                    uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
+                    uint64_t cNsElapsed    = RTTimeNanoTS()       - u64Start;
+                    if (cNsElapsedSys < cNsMinSys)
+                        cNsMinSys = cNsElapsedSys;
+                    if (cNsElapsed < cNsMin)
+                        cNsMin = cNsElapsed;
+                    cNsTotalSys += cNsElapsedSys;
+                    cNsTotal    += cNsElapsed;
+                }
+                if (fSys)
+                {
+                    RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS,        "%u ms min (clock=sys)", cMs);
+                    RTTestValueF(hTest, cNsTotalSys / 10, RTTESTUNIT_NS, "%u ms avg (clock=sys)", cMs);
+                }
+                if (fGip)
+                {
+                    RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS,           "%u ms min (clock=gip)", cMs);
+                    RTTestValueF(hTest, cNsTotal / 10, RTTESTUNIT_NS,    "%u ms avg (clock=gip)", cMs);
+                }
             }
-            RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%u ms min (clock=sys)", cMs);
-            RTTestValueF(hTest, cNsTotalSys / 10, RTTESTUNIT_NS, "%u ms avg - (clock=sys)", cMs);
-            RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%u ms min (clock=gip)", cMs);
-            RTTestValueF(hTest, cNsTotal / 10, RTTESTUNIT_NS, "%u ms avg - (clock=gip)", cMs);
+
+            RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
         }
 
-        RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
+        if (RTTestErrorCount(hTest) == 0)
+        {
+            RTTestSub(hTest, "MRE Timeout Accuracy (ms)");
+            RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS);
+
+            for (unsigned i = 0; i < RT_ELEMENTS(s_acMsIntervals); i++)
+            {
+                uint64_t cMs        = s_acMsIntervals[i];
+                uint64_t cNsMinSys  = UINT64_MAX;
+                uint64_t cNsMin     = UINT64_MAX;
+                uint64_t cNsTotalSys= 0;
+                uint64_t cNsTotal   = 0;
+                for (unsigned j = 0; j < 10; j++)
+                {
+                    uint64_t u64StartSys = RTTimeSystemNanoTS();
+                    uint64_t u64Start    = RTTimeNanoTS();
+                    int rcX = SUPSemEventMultiWaitNoResume(pSession, hEvent, cMs);
+                    if (rc == VERR_TIMEOUT)
+                        RTTestFailed(hTest, "%Rrc j=%u cMs=%u", rcX, j, cMs);
+                    uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
+                    uint64_t cNsElapsed    = RTTimeNanoTS()       - u64Start;
+                    if (cNsElapsedSys < cNsMinSys)
+                        cNsMinSys = cNsElapsedSys;
+                    if (cNsElapsed < cNsMin)
+                        cNsMin = cNsElapsed;
+                    cNsTotalSys += cNsElapsedSys;
+                    cNsTotal    += cNsElapsed;
+                }
+                if (fSys)
+                {
+                    RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS,        "%u ms min (clock=sys)", cMs);
+                    RTTestValueF(hTest, cNsTotalSys / 10, RTTESTUNIT_NS, "%u ms avg (clock=sys)", cMs);
+                }
+                if (fGip)
+                {
+                    RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS,           "%u ms min (clock=gip)", cMs);
+                    RTTestValueF(hTest, cNsTotal / 10, RTTESTUNIT_NS,    "%u ms avg (clock=gip)", cMs);
+                }
+            }
+
+            RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
+        }
     }
 
-    if (RTTestErrorCount(hTest) == 0)
     {
-        RTTestSub(hTest, "MRE Timeout Accuracy");
-        RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS);
-
-        static unsigned const s_acMsIntervals[] = { 0, 1, 2, 3, 4, 8, 10, 16, 32 };
-        for (unsigned i = 0; i < RT_ELEMENTS(s_acMsIntervals); i++)
-        {
-            uint64_t cMs        = s_acMsIntervals[i];
-            uint64_t cNsMinSys  = UINT64_MAX;
-            uint64_t cNsMin     = UINT64_MAX;
-            uint64_t cNsTotalSys= 0;
-            uint64_t cNsTotal   = 0;
-            for (unsigned j = 0; j < 10; j++)
+        static uint32_t const s_acNsIntervals[] =
+        {
+            0, 1000, 5000, 15000, 30000, 50000, 100000, 250000, 500000, 750000, 900000, 1500000, 2200000
+        };
+
+        if (RTTestErrorCount(hTest) == 0)
+        {
+            RTTestSub(hTest, "SUPSemEventWaitNsRelIntr Accuracy");
+            RTTestValueF(hTest, SUPSemEventGetResolution(pSession), RTTESTUNIT_NS, "SRE resolution");
+            RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
+
+            for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++)
             {
-                uint64_t u64StartSys = RTTimeSystemNanoTS();
-                uint64_t u64Start    = RTTimeNanoTS();
-                int rcX = SUPSemEventMultiWaitNoResume(pSession, hEvent, cMs);
-                if (rc == VERR_TIMEOUT)
-                    RTTestFailed(hTest, "%Rrc j=%u cMs=%u", rcX, j, cMs);
-                uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
-                uint64_t cNsElapsed    = RTTimeNanoTS()       - u64Start;
-                if (cNsElapsedSys < cNsMinSys)
-                    cNsMinSys = cNsElapsedSys;
-                if (cNsElapsed < cNsMin)
-                    cNsMin = cNsElapsed;
-                cNsTotalSys += cNsElapsedSys;
-                cNsTotal    += cNsElapsed;
+                uint64_t cNs        = s_acNsIntervals[i];
+                uint64_t cNsMinSys  = UINT64_MAX;
+                uint64_t cNsMin     = UINT64_MAX;
+                uint64_t cNsTotalSys= 0;
+                uint64_t cNsTotal   = 0;
+                for (unsigned j = 0; j < 10; j++)
+                {
+                    uint64_t u64StartSys = RTTimeSystemNanoTS();
+                    uint64_t u64Start    = RTTimeNanoTS();
+                    int rcX = SUPSemEventWaitNsRelIntr(pSession, hEvent, cNs);
+                    if (rc == VERR_TIMEOUT)
+                        RTTestFailed(hTest, "%Rrc j=%u cNs=%u", rcX, j, cNs);
+                    uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
+                    uint64_t cNsElapsed    = RTTimeNanoTS()       - u64Start;
+                    if (cNsElapsedSys < cNsMinSys)
+                        cNsMinSys = cNsElapsedSys;
+                    if (cNsElapsed < cNsMin)
+                        cNsMin = cNsElapsed;
+                    cNsTotalSys += cNsElapsedSys;
+                    cNsTotal    += cNsElapsed;
+                }
+                if (fSys)
+                {
+                    RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS,        "%'u ns min (clock=sys)", cNs);
+                    RTTestValueF(hTest, cNsTotalSys / 10, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs);
+                }
+                if (fGip)
+                {
+                    RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS,           "%'u ns min (clock=gip)", cNs);
+                    RTTestValueF(hTest, cNsTotal / 10, RTTESTUNIT_NS,    "%'u ns avg (clock=gip)", cNs);
+                }
             }
-            RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS, "%u ms min (clock=sys)", cMs);
-            RTTestValueF(hTest, cNsTotalSys / 10, RTTESTUNIT_NS, "%u ms avg - (clock=sys)", cMs);
-            RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS, "%u ms min (clock=gip)", cMs);
-            RTTestValueF(hTest, cNsTotal / 10, RTTESTUNIT_NS, "%u ms avg - (clock=gip)", cMs);
+
+            RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
         }
 
-        RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
+        if (RTTestErrorCount(hTest) == 0)
+        {
+            RTTestSub(hTest, "SUPSemEventMultiWaitNsRelIntr Accuracy");
+            RTTestValueF(hTest, SUPSemEventMultiGetResolution(pSession), RTTESTUNIT_NS, "MRE resolution");
+            RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS);
+
+            for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++)
+            {
+                uint64_t cNs        = s_acNsIntervals[i];
+                uint64_t cNsMinSys  = UINT64_MAX;
+                uint64_t cNsMin     = UINT64_MAX;
+                uint64_t cNsTotalSys= 0;
+                uint64_t cNsTotal   = 0;
+                for (unsigned j = 0; j < 10; j++)
+                {
+                    uint64_t u64StartSys = RTTimeSystemNanoTS();
+                    uint64_t u64Start    = RTTimeNanoTS();
+                    int rcX = SUPSemEventMultiWaitNsRelIntr(pSession, hEvent, cNs);
+                    if (rc == VERR_TIMEOUT)
+                        RTTestFailed(hTest, "%Rrc j=%u cNs=%u", rcX, j, cNs);
+                    uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
+                    uint64_t cNsElapsed    = RTTimeNanoTS()       - u64Start;
+                    if (cNsElapsedSys < cNsMinSys)
+                        cNsMinSys = cNsElapsedSys;
+                    if (cNsElapsed < cNsMin)
+                        cNsMin = cNsElapsed;
+                    cNsTotalSys += cNsElapsedSys;
+                    cNsTotal    += cNsElapsed;
+                }
+                if (fSys)
+                {
+                    RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS,        "%'u ns min (clock=sys)", cNs);
+                    RTTestValueF(hTest, cNsTotalSys / 10, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs);
+                }
+                if (fGip)
+                {
+                    RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS,           "%'u ns min (clock=gip)", cNs);
+                    RTTestValueF(hTest, cNsTotal / 10, RTTESTUNIT_NS,    "%'u ns avg (clock=gip)", cNs);
+                }
+            }
+
+            RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
+        }
+
+        if (RTTestErrorCount(hTest) == 0)
+        {
+            RTTestSub(hTest, "SUPSemEventWaitNsAbsIntr Accuracy");
+            RTTestValueF(hTest, SUPSemEventGetResolution(pSession), RTTESTUNIT_NS, "MRE resolution");
+            RTTESTI_CHECK_RC(SUPSemEventCreate(pSession, &hEvent), VINF_SUCCESS);
+
+            for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++)
+            {
+                uint64_t cNs        = s_acNsIntervals[i];
+                uint64_t cNsMinSys  = UINT64_MAX;
+                uint64_t cNsMin     = UINT64_MAX;
+                uint64_t cNsTotalSys= 0;
+                uint64_t cNsTotal   = 0;
+                for (unsigned j = 0; j < 10; j++)
+                {
+                    uint64_t u64StartSys   = RTTimeSystemNanoTS();
+                    uint64_t u64Start      = RTTimeNanoTS();
+                    uint64_t uAbsDeadline  = (fGip ? u64Start : u64StartSys) + cNs;
+                    int rcX = SUPSemEventWaitNsAbsIntr(pSession, hEvent, uAbsDeadline);
+                    if (rc == VERR_TIMEOUT)
+                        RTTestFailed(hTest, "%Rrc j=%u cNs=%u", rcX, j, cNs);
+                    uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
+                    uint64_t cNsElapsed    = RTTimeNanoTS()       - u64Start;
+                    if (cNsElapsedSys < cNsMinSys)
+                        cNsMinSys = cNsElapsedSys;
+                    if (cNsElapsed < cNsMin)
+                        cNsMin = cNsElapsed;
+                    cNsTotalSys += cNsElapsedSys;
+                    cNsTotal    += cNsElapsed;
+                }
+                if (fSys)
+                {
+                    RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS,        "%'u ns min (clock=sys)", cNs);
+                    RTTestValueF(hTest, cNsTotalSys / 10, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs);
+                }
+                if (fGip)
+                {
+                    RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS,           "%'u ns min (clock=gip)", cNs);
+                    RTTestValueF(hTest, cNsTotal / 10, RTTESTUNIT_NS,    "%'u ns avg (clock=gip)", cNs);
+                }
+            }
+
+            RTTESTI_CHECK_RC(SUPSemEventClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
+        }
+
+
+        if (RTTestErrorCount(hTest) == 0)
+        {
+            RTTestSub(hTest, "SUPSemEventMultiWaitNsAbsIntr Accuracy");
+            RTTestValueF(hTest, SUPSemEventMultiGetResolution(pSession), RTTESTUNIT_NS, "MRE resolution");
+            RTTESTI_CHECK_RC(SUPSemEventMultiCreate(pSession, &hEvent), VINF_SUCCESS);
+
+            for (unsigned i = 0; i < RT_ELEMENTS(s_acNsIntervals); i++)
+            {
+                uint64_t cNs        = s_acNsIntervals[i];
+                uint64_t cNsMinSys  = UINT64_MAX;
+                uint64_t cNsMin     = UINT64_MAX;
+                uint64_t cNsTotalSys= 0;
+                uint64_t cNsTotal   = 0;
+                for (unsigned j = 0; j < 10; j++)
+                {
+                    uint64_t u64StartSys   = RTTimeSystemNanoTS();
+                    uint64_t u64Start      = RTTimeNanoTS();
+                    uint64_t uAbsDeadline  = (fGip ? u64Start : u64StartSys) + cNs;
+                    int rcX = SUPSemEventMultiWaitNsAbsIntr(pSession, hEvent, uAbsDeadline);
+                    if (rc == VERR_TIMEOUT)
+                        RTTestFailed(hTest, "%Rrc j=%u cNs=%u", rcX, j, cNs);
+                    uint64_t cNsElapsedSys = RTTimeSystemNanoTS() - u64StartSys;
+                    uint64_t cNsElapsed    = RTTimeNanoTS()       - u64Start;
+                    if (cNsElapsedSys < cNsMinSys)
+                        cNsMinSys = cNsElapsedSys;
+                    if (cNsElapsed < cNsMin)
+                        cNsMin = cNsElapsed;
+                    cNsTotalSys += cNsElapsedSys;
+                    cNsTotal    += cNsElapsed;
+                }
+                if (fSys)
+                {
+                    RTTestValueF(hTest, cNsMinSys, RTTESTUNIT_NS,        "%'u ns min (clock=sys)", cNs);
+                    RTTestValueF(hTest, cNsTotalSys / 10, RTTESTUNIT_NS, "%'u ns avg (clock=sys)", cNs);
+                }
+                if (fGip)
+                {
+                    RTTestValueF(hTest, cNsMin, RTTESTUNIT_NS,           "%'u ns min (clock=gip)", cNs);
+                    RTTestValueF(hTest, cNsTotal / 10, RTTESTUNIT_NS,    "%'u ns avg (clock=gip)", cNs);
+                }
+            }
+
+            RTTESTI_CHECK_RC(SUPSemEventMultiClose(pSession, hEvent), VINF_OBJECT_DESTROYED);
+        }
+
     }
 
