Index: /trunk/src/VBox/Runtime/r3/posix/timer-posix.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/posix/timer-posix.cpp	(revision 10919)
+++ /trunk/src/VBox/Runtime/r3/posix/timer-posix.cpp	(revision 10920)
@@ -37,4 +37,5 @@
 #endif /* !RT_OS_SOLARIS */
 
+#define LOG_GROUP          RTLOGGROUP_TIMER
 
 /*******************************************************************************
@@ -65,4 +66,22 @@
 #endif
 
+#ifdef IPRT_WITH_POSIX_TIMERS
+#define RT_TIMER_SIGNAL SIGALRM
+
+/** 
+ * Global counter of RTTimer instances. The signal thread is 
+ * started when it changes from 0 to 1. The signal thread 
+ * terminates when it becomes 0 again. 
+ */ 
+uint32_t   g_cTimerInstances;
+/** The signal handling thread. */
+RTTHREAD   g_Thread;
+/** 
+ * Event semaphore on which the calling thread is blocked until 
+ * the signal thread has been initialized. 
+ */
+RTSEMEVENT g_Event;
+
+#endif /* IPRT_WITH_POSIX_TIMERS */
 
 /*******************************************************************************
@@ -93,5 +112,5 @@
     /** Event semaphore on which the thread is blocked. */
     RTSEMEVENT              Event;
-#endif
+#endif /* !IPRT_WITH_POSIX_TIMERS */
     /** User argument. */
     void                   *pvUser;
@@ -111,11 +130,9 @@
      * to errno on failure in starting the timer. */
     int volatile            iError;
-#else /* !IPRT_WITH_POSIX_TIMERS */
+#else /* IPRT_WITH_POSIX_TIMERS */
     timer_t                 timer;
-#endif /* !IPRT_WITH_POSIX_TIMERS */
+#endif /* IPRT_WITH_POSIX_TIMERS */
 
 } RTTIMER;
-
-#ifndef IPRT_WITH_POSIX_TIMERS
 
 /**
@@ -135,7 +152,9 @@
 static DECLCALLBACK(int) rttimerThread(RTTHREAD Thread, void *pvArg)
 {
+#ifndef IPRT_WITH_POSIX_TIMERS
     PRTTIMER pTimer = (PRTTIMER)(void *)pvArg;
     RTTIMER Timer = *pTimer;
     Assert(pTimer->u32Magic == RTTIMER_MAGIC);
+#endif /* !IPRT_WITH_POSIX_TIMERS */
 
     /*
@@ -170,5 +189,9 @@
     if (sigprocmask(SIG_SETMASK, &SigSet, NULL))
     {
+#ifndef IPRT_WITH_POSIX_TIMERS
         int rc = pTimer->iError = RTErrConvertFromErrno(errno);
+#else /* IPRT_WITH_POSIX_TIMERS */
+        int rc = RTErrConvertFromErrno(errno);
+#endif /* IPRT_WITH_POSIX_TIMERS */
         AssertMsgFailed(("sigprocmask -> errno=%d\n", errno));
         return rc;
@@ -179,4 +202,6 @@
      */
     RTThreadUserSignal(Thread);
+
+#ifndef IPRT_WITH_POSIX_TIMERS
     while (     !pTimer->fDestroyed
            &&   pTimer->u32Magic == RTTIMER_MAGIC)
@@ -305,17 +330,54 @@
     return VINF_SUCCESS;
 }
-#else /* !IPRT_WITH_POSIX_TIMERS */
-void rttimerCallback(union sigval SigVal)
+#else /* IPRT_WITH_POSIX_TIMERS */
+    sigemptyset(&SigSet);
+    sigaddset(&SigSet, RT_TIMER_SIGNAL);
+    while (g_cTimerInstances)
+    {
+        siginfo_t SigInfo = {0};
+        if (RT_LIKELY(sigwaitinfo(&SigSet, &SigInfo) >= 0))
+        {
+            LogFlow(("rttimerThread: signo=%d pTimer=%p\n", SigInfo.si_signo, SigInfo._sifields._timer.si_sigval.sival_ptr));
+            if (RT_LIKELY(SigInfo.si_signo == RT_TIMER_SIGNAL))
+            {
+                PRTTIMER pTimer = (PRTTIMER)SigInfo._sifields._timer.si_sigval.sival_ptr;
+                if (RT_UNLIKELY(    pTimer == NULL
+                                ||  pTimer->fSuspended
+                                ||  pTimer->fDestroyed
+                                ||  pTimer->u32Magic != RTTIMER_MAGIC))
+                    continue;
+                pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick);
+                /* auto suspend one-shot timers. */
+                if (RT_UNLIKELY(!pTimer->u64NanoInterval))
+                {
+                    ASMAtomicXchgU8(&pTimer->fSuspended, true); /* @todo Can't we do a simple assigment here? */
+                    //break;
+                }
+            }
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Create the SIGALRM handling thread and wait for it to get 
+ * ready. 
+ */
+static int rttimerCreateSignalThread()
 {
-    PRTTIMER pTimer = (PRTTIMER)SigVal.sival_ptr;
-    /* Is the timer being destoyed/suspended at this very moment? */
-    if (RT_LIKELY(pTimer->u32Magic == RTTIMER_MAGIC
-                  && !pTimer->fSuspended
-                  && !pTimer->fDestroyed))
-    {
-        pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->iTick);
-    }
+    int rc = RTThreadCreate(&g_Thread, rttimerThread, NULL, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "Timer");
+    AssertRC(rc);
+    if (RT_SUCCESS(rc))
+    {
+        /* Let's wait for the thread to get ready to handle signals. */
+        rc = RTThreadUserWait(g_Thread, 5000); /* @todo 5 sec is enough? or is it too much? */
+    }
+    LogFlow(("rttimerCreateSignalThread: rc=%Vrc\n", rc));
+
+    return rc;
+
 }
-#endif /* !IPRT_WITH_POSIX_TIMERS */
+#endif /* IPRT_WITH_POSIX_TIMERS */
 
 
@@ -328,5 +390,5 @@
         return VERR_NOT_SUPPORTED;
 
-#ifndef IPRT_WITH_POSIX_TIMERS /** @todo the signal blocking applies to the new code too, see comment in the struct. */
+#ifndef IPRT_WITH_POSIX_TIMERS
     /*
      * Check if timer is busy.
@@ -345,4 +407,5 @@
         return VERR_TIMER_BUSY;
     }
+#endif /* !IPRT_WITH_POSIX_TIMERS */
 
     /*
@@ -354,4 +417,5 @@
     sigprocmask(SIG_BLOCK, &SigSet, NULL);
 
+#ifndef IPRT_WITH_POSIX_TIMERS
     /** @todo Move this RTC hack else where... */
     static bool fDoneRTC;
@@ -452,9 +516,11 @@
     else
         rc = VERR_NO_MEMORY;
-#else /* !IPRT_WITH_POSIX_TIMERS */
+#else /* IPRT_WITH_POSIX_TIMERS */
     /*
      * Create a new timer.
      */
-    int rc;
+    LogFlow(("RTTimerCreateEx: u64NanoInterval=%llu fFlags=%lu\n", u64NanoInterval, fFlags));
+
+    int rc = VINF_SUCCESS;
     PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer));
     if (pTimer)
@@ -471,16 +537,29 @@
         pTimer->iTick           = 0;
 
-        /* Ask to call rttimerCallback in a separate thread context upon timer expiration. */
-        memset(&evt, 0, sizeof(evt));
-        evt.sigev_notify = SIGEV_THREAD;
-        evt.sigev_value.sival_ptr = pTimer;
-        evt.sigev_notify_function = rttimerCallback;
-
-        rc = RTErrConvertFromErrno(timer_create(CLOCK_REALTIME, &evt, &pTimer->timer));
+        /* Create the signal handling thread if it is the first instance. */
+        if (ASMAtomicIncU32(&g_cTimerInstances) == 1)
+            rc = rttimerCreateSignalThread();
+
         if (RT_SUCCESS(rc))
         {
-            *ppTimer = pTimer;
-            return VINF_SUCCESS;
-        }
+            /* Ask to deliver RT_TIMER_SIGNAL upon timer expiration. */
+            evt.sigev_notify = SIGEV_SIGNAL;
+            evt.sigev_signo  = RT_TIMER_SIGNAL;
+            evt.sigev_value.sival_ptr = pTimer; /* sigev_value gets copied to siginfo. */
+
+            rc = RTErrConvertFromErrno(timer_create(CLOCK_REALTIME, &evt, &pTimer->timer));
+            LogFlow(("RTTimerCreateEx: rc=%Vrc pTimer=%p\n", rc, pTimer));
+            if (RT_SUCCESS(rc))
+            {
+                *ppTimer = pTimer;
+                return VINF_SUCCESS;
+            }
+        }
+        /** 
+         * Roll back the timer instance counter. This will cause 
+         * termination of the signal handling thread if it is the only 
+         * timer. 
+         */ 
+        ASMAtomicDecU32(&g_cTimerInstances);
         RTMemFree(pTimer);
     }
@@ -488,5 +567,5 @@
         rc = VERR_NO_MEMORY;
 
-#endif /* !IPRT_WITH_POSIX_TIMERS */
+#endif /* IPRT_WITH_POSIX_TIMERS */
     return rc;
 }
@@ -527,5 +606,5 @@
     RTSemEventDestroy(pTimer->Event);
     pTimer->Event = NIL_RTSEMEVENT;
-#else /* !IPRT_WITH_POSIX_TIMERS */
+#else /* IPRT_WITH_POSIX_TIMERS */
     if (ASMAtomicXchgU8(&pTimer->fDestroyed, true))
     {
@@ -534,5 +613,15 @@
     }
     rc = RTErrConvertFromErrno(timer_delete(pTimer->timer));
-#endif /* !IPRT_WITH_POSIX_TIMERS */
+    /** 
+     * Decrement the timer instance counter. This will cause 
+     * termination of the signal handling thread if it is the last 
+     * remaining timer. 
+     */ 
+    if (ASMAtomicDecU32(&g_cTimerInstances) == 0)
+    {
+        /* Wake up the timer thread so it can exit. */
+        kill(getpid(), RT_TIMER_SIGNAL);
+    }
+#endif /* IPRT_WITH_POSIX_TIMERS */
     if (RT_SUCCESS(rc))
         RTMemFree(pTimer);
@@ -575,5 +664,7 @@
     if (RT_FAILURE(rc))
         ASMAtomicXchgU8(&pTimer->fSuspended, false);
-#else /* !IPRT_WITH_POSIX_TIMERS */
+#else /* IPRT_WITH_POSIX_TIMERS */
+    LogFlow(("RTTimerStart: pTimer=%p u64First=%llu u64NanoInterval=%llu\n", pTimer, u64First, pTimer->u64NanoInterval));
+
     struct itimerspec ts;
 
@@ -582,9 +673,9 @@
 
     ts.it_value.tv_sec     = u64First / 1000000000; /* nanosec => sec */
-    ts.it_value.tv_nsec    = u64First ? u64First % 1000000000 : 1; /* 0 means disable, replace it with 1. */
+    ts.it_value.tv_nsec    = u64First ? u64First % 1000000000 : 10; /* 0 means disable, replace it with 10. */
     ts.it_interval.tv_sec  = pTimer->u64NanoInterval / 1000000000;
     ts.it_interval.tv_nsec = pTimer->u64NanoInterval % 1000000000;
     int rc = RTErrConvertFromErrno(timer_settime(pTimer->timer, 0, &ts, NULL));
-#endif /* !IPRT_WITH_POSIX_TIMERS */
+#endif /* IPRT_WITH_POSIX_TIMERS */
 
     return rc;
@@ -622,5 +713,7 @@
         RTThreadUserReset(pTimer->Thread);
     }
-#else /* !IPRT_WITH_POSIX_TIMERS */
+#else /* IPRT_WITH_POSIX_TIMERS */
+    LogFlow(("RTTimerStop: pTimer=%p\n", pTimer));
+
     struct itimerspec ts;
 
@@ -631,5 +724,5 @@
     ts.it_value.tv_nsec    = 0;
     int rc = RTErrConvertFromErrno(timer_settime(pTimer->timer, 0, &ts, NULL));
-#endif /* !IPRT_WITH_POSIX_TIMERS */
+#endif /* IPRT_WITH_POSIX_TIMERS */
 
     return rc;
