Index: /trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile	(revision 33032)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile	(revision 33033)
@@ -119,4 +119,6 @@
         generic/RTLogWriteStdErr-stub-generic.o \
         generic/RTLogWriteStdOut-stub-generic.o \
+	generic/RTSemEventWait-2-ex-generic.o \
+	generic/RTSemEventWaitNoResume-2-ex-generic.o \
 	generic/RTSemEventMultiWait-2-ex-generic.o \
 	generic/RTSemEventMultiWaitNoResume-2-ex-generic.o \
Index: /trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest	(revision 33032)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest	(revision 33033)
@@ -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/RTSemEventWait-2-ex-generic.cpp=>generic/RTSemEventWait-2-ex-generic.c \
+    ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventWaitNoResume-2-ex-generic.cpp=>generic/RTSemEventWaitNoResume-2-ex-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 \
Index: /trunk/src/VBox/HostDrivers/Support/linux/Makefile
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 33032)
+++ /trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 33033)
@@ -131,4 +131,6 @@
 	generic/RTLogWriteUser-generic.o \
 	generic/RTMpGetArraySize-generic.o \
+	generic/RTSemEventWait-2-ex-generic.o \
+	generic/RTSemEventWaitNoResume-2-ex-generic.o \
 	generic/RTSemEventMultiWait-2-ex-generic.o \
 	generic/RTSemEventMultiWaitNoResume-2-ex-generic.o \
Index: /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 33032)
+++ /trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv	(revision 33033)
@@ -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/RTSemEventWait-2-ex-generic.cpp=>generic/RTSemEventWait-2-ex-generic.c \
+    ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventWaitNoResume-2-ex-generic.cpp=>generic/RTSemEventWaitNoResume-2-ex-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 \
Index: /trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp	(revision 33032)
+++ /trunk/src/VBox/HostDrivers/Support/testcase/tstSupSem.cpp	(revision 33033)
@@ -282,4 +282,42 @@
 
 #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++)
+            {
+                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;
+            }
+            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);
+    }
 
     if (RTTestErrorCount(hTest) == 0)
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 33032)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 33033)
@@ -1430,4 +1430,6 @@
 	generic/RTAssertShouldPanic-generic.cpp \
 	generic/RTLogWriteStdOut-stub-generic.cpp \
+ 	generic/RTSemEventWait-2-ex-generic.cpp \
+ 	generic/RTSemEventWaitNoResume-2-ex-generic.cpp \
  	generic/RTSemEventMultiWait-2-ex-generic.cpp \
  	generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp \
Index: /trunk/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c	(revision 33032)
+++ /trunk/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c	(revision 33033)
@@ -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,9 +32,12 @@
 #include "internal/iprt.h"
 #include <iprt/semaphore.h>
-#include <iprt/alloc.h>
+
+#include <iprt/asm.h>
 #include <iprt/assert.h>
-#include <iprt/asm.h>
 #include <iprt/err.h>
-
+#include <iprt/lockvalidator.h>
+#include <iprt/mem.h>
+
+#include "waitqueue-r0drv-linux.h"
 #include "internal/magics.h"
 
@@ -52,4 +55,6 @@
     /** The object status - !0 when signaled and 0 when reset. */
     uint32_t volatile   fState;
+    /** Reference counter. */
+    uint32_t volatile   cRefs;
     /** The wait queue. */
     wait_queue_head_t   Head;
@@ -75,4 +80,5 @@
     pThis->u32Magic = RTSEMEVENT_MAGIC;
     pThis->fState   = 0;
+    pThis->cRefs    = 1;
     init_waitqueue_head(&pThis->Head);
 
@@ -81,4 +87,28 @@
 }
 RT_EXPORT_SYMBOL(RTSemEventCreate);
+
+
+/**
+ * Retains a reference to the event semaphore.
+ *
+ * @param   pThis       The event semaphore.
+ */
+DECLINLINE(void) rtR0SemEventLnxRetain(PRTSEMEVENTINTERNAL pThis)
+{
+    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
+    Assert(cRefs < 100000); NOREF(cRefs);
+}
+
+
+/**
+ * Releases a reference to the event semaphore.
+ *
+ * @param   pThis       The event semaphore.
+ */
+DECLINLINE(void) rtR0SemEventLnxRelease(PRTSEMEVENTINTERNAL pThis)
+{
+    if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
+        RTMemFree(pThis);
+}
 
 
@@ -92,4 +122,5 @@
         return VINF_SUCCESS;
     AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+    Assert(pThis->cRefs > 0);
 
     /*
@@ -100,5 +131,5 @@
     Assert(!waitqueue_active(&pThis->Head));
     wake_up_all(&pThis->Head);
-    RTMemFree(pThis);
+    rtR0SemEventLnxRelease(pThis);
     return VINF_SUCCESS;
 }
@@ -114,4 +145,5 @@
     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+    rtR0SemEventLnxRetain(pThis);
 
     /*
@@ -121,4 +153,5 @@
     wake_up(&pThis->Head);
 
+    rtR0SemEventLnxRelease(pThis);
     return VINF_SUCCESS;
 }
@@ -127,85 +160,97 @@
 
 /**
- * Worker for RTSemEvent and RTSemEventNoResume.
+ * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
  *
  * @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 rtSemEventWait(PRTSEMEVENTINTERNAL 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 (;;)
+ * @param   fFlags          See RTSemEventWaitEx.
+ * @param   uTimeout        See RTSemEventWaitEx.
+ * @param   pSrcPos         The source code position of the wait.
+ */
+static int rtR0SemEventLnxWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
+                               PCRTLOCKVALSRCPOS pSrcPos)
+{
+    int rc;
+
+    /*
+     * Validate the input.
+     */
+    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
+    rtR0SemEventLnxRetain(pThis);
+
+    /*
+     * Try grab the event without setting up the wait.
+     */
+    if (   1 /** @todo check if there are someone waiting already - waitqueue_active, but then what do we do below? */
+        && ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
+        rc = VINF_SUCCESS;
+    else
     {
-        /* make everything thru schedule_timeout() atomic scheduling wise. */
-        prepare_to_wait(&pThis->Head, &Wait, fInterruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-
-        /* check the condition. */
-        if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
-            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 != RTSEMEVENT_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 != RTSEMEVENT_MAGIC))
+                    rc = VERR_SEM_DESTROYED;
+                else
+                {
+                    rtR0SemLnxWaitPrepare(&Wait);
+
+                    /* Check the exit conditions. */
+                    if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
+                        rc = VERR_SEM_DESTROYED;
+                    else if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
+                        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);
+    rtR0SemEventLnxRelease(pThis);
     return rc;
 }
 
 
-RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
-{
-    PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
-    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
-    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
-
-    if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
-        return VINF_SUCCESS;
-    return rtSemEventWait(pThis, cMillies, false /* fInterruptible */);
-}
-RT_EXPORT_SYMBOL(RTSemEventWait);
-
-
-RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
-{
-    PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
-    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
-    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
-
-    if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
-        return VINF_SUCCESS;
-    return rtSemEventWait(pThis, cMillies, true /* fInterruptible */);
-}
-RT_EXPORT_SYMBOL(RTSemEventWaitNoResume);
-
+#undef RTSemEventWaitEx
+RTDECL(int)  RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
+{
+#ifndef RTSEMEVENT_STRICT
+    return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, NULL);
+#else
+    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
+    return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
+#endif
+}
+RT_EXPORT_SYMBOL(RTSemEventWaitEx);
+
+
+RTDECL(int)  RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
+                                   RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
+    return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
+}
+RT_EXPORT_SYMBOL(RTSemEventWaitExDebug);
+
Index: /trunk/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c	(revision 33032)
+++ /trunk/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c	(revision 33033)
@@ -226,4 +226,7 @@
  * @returns VBox status code.
  * @param   pThis           The event semaphore.
+ * @param   fFlags          See RTSemEventMultiWaitEx.
+ * @param   uTimeout        See RTSemEventMultiWaitEx.
+ * @param   pSrcPos         The source code position of the wait.
  */
 static int rtR0SemEventMultiLnxWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
