Index: /trunk/src/VBox/Runtime/testcase/tstRTR0Timer.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTR0Timer.cpp	(revision 48410)
+++ /trunk/src/VBox/Runtime/testcase/tstRTR0Timer.cpp	(revision 48411)
@@ -32,4 +32,5 @@
 
 #include <iprt/asm.h>
+#include <iprt/asm-amd64-x86.h>
 #include <iprt/cpuset.h>
 #include <iprt/err.h>
@@ -106,4 +107,51 @@
 } TSTRTR0TIMEROMNI1;
 typedef TSTRTR0TIMEROMNI1 *PTSTRTR0TIMEROMNI1;
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/**
+ * Latency data.
+ */
+static struct TSTRTR0TIMEROMNILATENCY
+{
+    /** The number of samples.  */
+    volatile uint32_t   cSamples;
+    uint32_t            auPadding[3];
+    struct
+    {
+        uint64_t        uTsc;
+        uint64_t        uNanoTs;
+    } aSamples[4096];
+} g_aOmniLatency[16];
+
+
+/**
+ * Callback for the omni timer latency test, adds a sample to g_aOmniLatency.
+ *
+ * @param   pTimer      The timer.
+ * @param   iTick       The current tick.
+ * @param   pvUser      The user argument.
+ */
+static DECLCALLBACK(void) tstRTR0TimerCallbackLatencyOmni(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
+{
+    RTCPUID             idCpu    = RTMpCpuId();
+    uint32_t            iCpu     = RTMpCpuIdToSetIndex(idCpu);
+    NOREF(pTimer); NOREF(pvUser); NOREF(iTick);
+
+    RTR0TESTR0_CHECK_MSG(iCpu < RT_ELEMENTS(g_aOmniLatency), ("iCpu=%d idCpu=%u\n", iCpu, idCpu));
+    if (iCpu < RT_ELEMENTS(g_aOmniLatency))
+    {
+        uint32_t iSample = g_aOmniLatency[iCpu].cSamples;
+        if (iSample < RT_ELEMENTS(g_aOmniLatency[iCpu].aSamples))
+        {
+            g_aOmniLatency[iCpu].aSamples[iSample].uTsc    = ASMReadTSC();
+            g_aOmniLatency[iCpu].aSamples[iSample].uNanoTs = RTTimeSystemNanoTS();
+            g_aOmniLatency[iCpu].cSamples = iSample + 1;
+        }
+    }
+}
+
 
 
@@ -807,4 +855,70 @@
             break;
         }
+
+        case TSTRTR0TIMER_LATENCY_OMNI:
+        case TSTRTR0TIMER_LATENCY_OMNI_HIRES:
+        {
+            /*
+             * Create a periodic timer running at max host frequency, but no more than 1000 Hz.
+             */
+            PRTTIMER        pTimer;
+            uint32_t        fFlags = (TSTRTR0TIMER_IS_HIRES(uOperation) ? RTTIMER_FLAGS_HIGH_RES : 0)
+                                   | RTTIMER_FLAGS_CPU_ALL;
+            uint32_t        cNsInterval = cNsSysHz;
+            while (cNsInterval < UINT32_C(1000000))
+                cNsInterval *= 2;
+            int rc = RTTimerCreateEx(&pTimer, cNsInterval, fFlags, tstRTR0TimerCallbackLatencyOmni, NULL);
+            if (rc == VERR_NOT_SUPPORTED)
+            {
+                RTR0TESTR0_SKIP_BREAK();
+            }
+            RTR0TESTR0_CHECK_RC_BREAK(rc, VINF_SUCCESS);
+
+            /*
+             * Reset the state and run the test for 4 seconds.
+             */
+            RT_ZERO(g_aOmniLatency);
+
+            RTCPUSET OnlineSet;
+            uint64_t uStartNsTS = RTTimeSystemNanoTS();
+            RTR0TESTR0_CHECK_RC_BREAK(RTTimerStart(pTimer, 0), VINF_SUCCESS);
+            RTMpGetOnlineSet(&OnlineSet);
+
+            for (uint32_t i = 0; i < 5000 && RTTimeSystemNanoTS() - uStartNsTS <= UINT64_C(4000000000); i++)
+                RTThreadSleep(2);
+
+            RTR0TESTR0_CHECK_RC_BREAK(RTTimerStop(pTimer), VINF_SUCCESS);
+            uint64_t    cNsElapsedX = RTTimeNanoTS() - uStartNsTS;
+
+            /*
+             * Process the result.
+             */
+            int32_t     cNsDiv = cNsInterval / 4; /* 25% */
+            uint32_t    cTotal = 0;
+            uint32_t    cLow   = 0;
+            uint32_t    cHigh  = 0;
+            for (uint32_t iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++)
+            {
+                uint32_t cSamples = g_aOmniLatency[iCpu].cSamples;
+                if (cSamples > 1)
+                {
+                    cTotal += cSamples - 1;
+                    for (uint32_t iSample = 1; iSample < cSamples; iSample++)
+                    {
+                        int64_t cNsDelta = g_aOmniLatency[iCpu].aSamples[iSample - 1].uNanoTs
+                                         - g_aOmniLatency[iCpu].aSamples[iSample].uNanoTs;
+                        if (cNsDelta < 0 && cNsDelta < -cNsDiv)
+                            cLow++;
+                        else if (cNsDelta > 0 && cNsDelta > cNsDiv)
+                            cHigh++;
+                    }
+                }
+            }
+
+            RTR0TestR0Info("25%: %u; -25%: %u; total: %u", cHigh, cLow, cTotal);
+            RTR0TESTR0_CHECK_RC(RTTimerDestroy(pTimer), VINF_SUCCESS);
+            break;
+        }
+
     }
 
Index: /trunk/src/VBox/Runtime/testcase/tstRTR0Timer.h
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTR0Timer.h	(revision 48410)
+++ /trunk/src/VBox/Runtime/testcase/tstRTR0Timer.h	(revision 48411)
@@ -55,4 +55,6 @@
     TSTRTR0TIMER_PERIODIC_OMNI,
     TSTRTR0TIMER_PERIODIC_OMNI_HIRES,
+    TSTRTR0TIMER_LATENCY_OMNI,
+    TSTRTR0TIMER_LATENCY_OMNI_HIRES,
     TSTRTR0TIMER_END
 } TSTRTR0TIMER;
@@ -69,4 +71,5 @@
      || (uOperation) == TSTRTR0TIMER_PERIODIC_SPECIFIC_HIRES \
      || (uOperation) == TSTRTR0TIMER_PERIODIC_OMNI_HIRES \
+     || (uOperation) == TSTRTR0TIMER_LATENCY_OMNI_HIRES \
     )
 
Index: /trunk/src/VBox/Runtime/testcase/tstRTR0TimerDriver.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTR0TimerDriver.cpp	(revision 48410)
+++ /trunk/src/VBox/Runtime/testcase/tstRTR0TimerDriver.cpp	(revision 48411)
@@ -57,49 +57,57 @@
         return rcExit;
 
+    if (argc == 2 && !strcmp(argv[1], "latency"))
+    {
+        RTR3TestR0SimpleTest(TSTRTR0TIMER_LATENCY_OMNI, "Latency omni timer");
+        RTR3TestR0SimpleTest(TSTRTR0TIMER_LATENCY_OMNI_HIRES, "Latency omni hires timer");
+    }
+    else
+    {
 # if 1
-    /*
-     * Standard timers.
-     */
-    RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_BASIC,       "Basic one shot");
-    RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_BASIC,       "Basic periodic");
-    if (RTTestErrorCount(g_hTest) == 0)
-    {
+        /*
+         * Standard timers.
+         */
+        RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_BASIC,       "Basic one shot");
+        RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_BASIC,       "Basic periodic");
+        if (RTTestErrorCount(g_hTest) == 0)
+        {
 #  if 1
 #   ifndef RT_OS_SOLARIS        /* Solaris cannot call back into cyclic subsystem from a cyclic callback. */
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_RESTART, "Restart one shot from callback");
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_DESTROY, "Destroy one shot from callback");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_RESTART, "Restart one shot from callback");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_DESTROY, "Destroy one shot from callback");
 #   endif
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_CSSD_LOOPS, "Create-start-stop-destroy loops");
-        for (uint32_t i = 0; i <= 7; i++)
-            RTR3TestR0SimpleTestWithArg(TSTRTR0TIMER_PERIODIC_CHANGE_INTERVAL, i, "Change interval from callback, variation %u", i);
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_CSSD_LOOPS, "Create-start-stop-destroy loops");
+            for (uint32_t i = 0; i <= 7; i++)
+                RTR3TestR0SimpleTestWithArg(TSTRTR0TIMER_PERIODIC_CHANGE_INTERVAL, i, "Change interval from callback, variation %u", i);
 #  endif
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_SPECIFIC, "One shot cpu specific");
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_SPECIFIC, "Periodic cpu specific");
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_OMNI, "Periodic omni timer");
-    }
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_SPECIFIC, "One shot cpu specific");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_SPECIFIC, "Periodic cpu specific");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_OMNI, "Periodic omni timer");
+        }
 # endif
 
 # if 1
-    /*
-     * High resolution timers.
-     */
-    RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_BASIC_HIRES, "Basic hires one shot");
-    RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_BASIC_HIRES, "Basic hires periodic");
-    if (RTTestErrorCount(g_hTest) == 0)
-    {
+        /*
+         * High resolution timers.
+         */
+        RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_BASIC_HIRES, "Basic hires one shot");
+        RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_BASIC_HIRES, "Basic hires periodic");
+        if (RTTestErrorCount(g_hTest) == 0)
+        {
 #  if 1
 #   ifndef RT_OS_SOLARIS        /* Solaris cannot call back into cyclic subsystem from a cyclic callback. */
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_RESTART_HIRES, "Restart hires one shot from callback");
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_DESTROY_HIRES, "Destroy hires one shot from callback");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_RESTART_HIRES, "Restart hires one shot from callback");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_DESTROY_HIRES, "Destroy hires one shot from callback");
 #   endif
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_CSSD_LOOPS_HIRES, "Create-start-stop-destroy loops, hires");
-        for (uint32_t i = 0; i <= 7; i++)
-            RTR3TestR0SimpleTestWithArg(TSTRTR0TIMER_PERIODIC_CHANGE_INTERVAL, i, "Change interval from callback, hires, variation %u", i);
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_CSSD_LOOPS_HIRES, "Create-start-stop-destroy loops, hires");
+            for (uint32_t i = 0; i <= 7; i++)
+                RTR3TestR0SimpleTestWithArg(TSTRTR0TIMER_PERIODIC_CHANGE_INTERVAL, i, "Change interval from callback, hires, variation %u", i);
 #  endif
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_SPECIFIC_HIRES, "One shot hires cpu specific");
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_SPECIFIC_HIRES, "Periodic hires cpu specific");
-        RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_OMNI, "Periodic omni hires timer");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_ONE_SHOT_SPECIFIC_HIRES, "One shot hires cpu specific");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_SPECIFIC_HIRES, "Periodic hires cpu specific");
+            RTR3TestR0SimpleTest(TSTRTR0TIMER_PERIODIC_OMNI, "Periodic omni hires timer");
+        }
+# endif
     }
-# endif
 
     /*
