Wrap clock_gettime and friends
authorDaniel Mack <daniel@caiaq.de>
Mon, 19 Oct 2009 10:45:30 +0000 (12:45 +0200)
committerLennart Poettering <lennart@poettering.net>
Sat, 31 Oct 2009 00:33:13 +0000 (01:33 +0100)
On Wed, Sep 16, 2009 at 11:48:58PM +0200, Lennart Poettering wrote:
> On Wed, 16.09.09 15:15, Daniel Mack (daniel@caiaq.de) wrote:
>
> > From: Kim Lester <kim@dfusion.com.au>
> >
> > OS X does not define clockid_t or clock_gettime() and friends.
> > Add a wrapper to fix this.
>
> Hmpf. I am not particularly happy with this. This adds a lot of
> unnecessary compat code. We don't actually need implementations of
> clock_getres(). All we need is some kind of check whether system
> timers are accurate or whether they are rounded up to scheduling
> slices. On Linux we do that check with clock_getres(), but all the
> information it returns is actually not intertesting at all. We just
> check if this is below some trheshold, that's all.
>
> clock_settime() we don't use at all! We shouldn't carry compat code
> for that.
>
> And clock_gettime we don't really need either. We need some kind of
> accurate system timers (preferably monotonic), and on Linux we use
> clock_gettime() for that. But we already have a fallback there for
> gettimeofday().
>
> Or in other words, the current APIs pa_rtclock_get(),
> pa_rtclock_hrtimer() is supposed to be the abstract API that has
> different backends on different systems. I'd very much prefer if any
> MacOS specific code would simply be plugged in there instead of
> creating various new abstraction interfaces!

Ok - what about the version below? I don't particularily like the

Daniel

>From 9f0a051953ec354ccdb8aa44a9845c408b26ae0b Mon Sep 17 00:00:00 2001
From: Kim Lester <kim@dfusion.com.au>
Date: Wed, 16 Sep 2009 14:40:01 +0800
Subject: [PATCH] Implement pa_rtclock_get() and pa_rtclock_hrtimer() for Darwin

OS X does not define clockid_t or clock_gettime() and friends.
Add wrappers to fix this. Based on a patch from Kim Lester
<kim@dfusion.com.au>.

src/pulsecore/core-rtclock.c

index 1420470..4fe0a47 100644 (file)
 #include <sys/prctl.h>
 #endif
 
+#ifdef OS_IS_DARWIN
+#include <CoreServices/CoreServices.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#endif
+
 #include <pulse/timeval.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/core-error.h>
@@ -47,7 +53,8 @@ pa_usec_t pa_rtclock_age(const struct timeval *tv) {
 }
 
 struct timeval *pa_rtclock_get(struct timeval *tv) {
-#ifdef HAVE_CLOCK_GETTIME
+
+#if defined(HAVE_CLOCK_GETTIME)
     struct timespec ts;
 
 #ifdef CLOCK_MONOTONIC
@@ -59,7 +66,7 @@ struct timeval *pa_rtclock_get(struct timeval *tv) {
             no_monotonic = TRUE;
 
     if (no_monotonic)
-#endif
+#endif /* CLOCK_MONOTONIC */
         pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
 
     pa_assert(tv);
@@ -69,7 +76,30 @@ struct timeval *pa_rtclock_get(struct timeval *tv) {
 
     return tv;
 
-#else /* HAVE_CLOCK_GETTIME */
+#elif defined(OS_IS_DARWIN)
+    static mach_timebase_info_data_t   tbi;
+    uint64_t nticks;
+    uint64_t time_nsec;
+
+    /* Refer Apple ADC QA1398
+       Also: http://devworld.apple.com/documentation/Darwin/Conceptual/KernelProgramming/services/services.html
+
+       Note: argument is timespec NOT timeval (timespec uses nsec, timeval uses usec)
+    */
+
+    /* try and be a mite efficient - maybe I should keep the N/D as a float !? */
+    if (tbi.denom == 0)
+        mach_timebase_info(&tbi);
+
+    nticks = mach_absolute_time();
+    time_nsec = nticks * tbi.numer / tbi.denom; // see above
+
+    tv->tv_sec = time_nsec / PA_NSEC_PER_SEC;
+    tv->tv_usec = time_nsec / PA_NSEC_PER_USEC;
+
+    return tv;
+
+#else /* OS_IS_DARWIN */
 
     return pa_gettimeofday(tv);
 
@@ -77,19 +107,30 @@ struct timeval *pa_rtclock_get(struct timeval *tv) {
 }
 
 pa_bool_t pa_rtclock_hrtimer(void) {
-#ifdef HAVE_CLOCK_GETTIME
+
+#if defined(HAVE_CLOCK_GETTIME)
     struct timespec ts;
 
 #ifdef CLOCK_MONOTONIC
+
     if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0)
         return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
-#endif
+#endif /* CLOCK_MONOTONIC */
 
     pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0);
     return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
 
-#else /* HAVE_CLOCK_GETTIME */
+#elif defined (OS_IS_DARWIN)
+    mach_timebase_info_data_t tbi;
+    uint64_t time_nsec;
+
+    mach_timebase_info(&tbi);
 
+    /* nsec = nticks * (N/D) - we want 1 tick == resolution !? */
+    time_nsec = tbi.numer / tbi.denom;
+    return time_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
+
+#else /* OS_IS_DARWIN */
     return FALSE;
 
 #endif
@@ -98,6 +139,7 @@ pa_bool_t pa_rtclock_hrtimer(void) {
 #define TIMER_SLACK_NS (int) ((500 * PA_NSEC_PER_USEC))
 
 void pa_rtclock_hrtimer_enable(void) {
+
 #ifdef PR_SET_TIMERSLACK
     int slack_ns;