[pulseaudio-discuss] [PATCH 4/4] Wrap clock_gettime and friends

Daniel Mack daniel at caiaq.de
Wed Sep 16 00:15:23 PDT 2009


From: Kim Lester <kim at dfusion.com.au>

OS X does not define clockid_t or clock_gettime() and friends.
Add a wrapper to fix this.

Signed-off-by: Kim Lester <kim at dfusion.com.au>
Signed-off-by: Daniel Mack <daniel at caiaq.de>
---
 src/Makefile.am              |    1 +
 src/pulsecore/core-clock.c   |  176 ++++++++++++++++++++++++++++++++++++++++++
 src/pulsecore/core-clock.h   |   75 ++++++++++++++++++
 src/pulsecore/core-rtclock.c |   13 ++--
 src/tests/rtstutter.c        |    9 +-
 5 files changed, 264 insertions(+), 10 deletions(-)
 create mode 100644 src/pulsecore/core-clock.c
 create mode 100644 src/pulsecore/core-clock.h

diff --git a/src/Makefile.am b/src/Makefile.am
index b12ed8f..f73772e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -580,6 +580,7 @@ libpulsecommon_ at PA_MAJORMINORMICRO@_la_SOURCES = \
 		pulsecore/conf-parser.c pulsecore/conf-parser.h \
 		pulsecore/core-error.c pulsecore/core-error.h \
 		pulsecore/core-rtclock.c pulsecore/core-rtclock.h \
+		pulsecore/core-clock.c pulsecore/core-clock.h \
 		pulsecore/core-util.c pulsecore/core-util.h \
 		pulsecore/creds.h \
 		pulsecore/dynarray.c pulsecore/dynarray.h \
diff --git a/src/pulsecore/core-clock.c b/src/pulsecore/core-clock.c
new file mode 100644
index 0000000..d4a47ce
--- /dev/null
+++ b/src/pulsecore/core-clock.c
@@ -0,0 +1,176 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2009 Kim Lester, Datafusion Systems P/L
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef OS_IS_DARWIN
+#include <CoreServices/CoreServices.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#endif
+
+#include <time.h>
+#include <errno.h>
+
+#include "core-clock.h"
+
+
+int pa_clock_getres(clockid_t clk_id, struct timespec *res) {
+#ifndef OS_IS_DARWIN
+/* #ifdef HAVE_CLOCK_GETRES - use this eventually !? */
+
+    return clock_getres(clk_id, res);
+
+#elif defined(OS_IS_DARWIN)
+
+    mach_timebase_info_data_t tbi;
+    uint64_t time_nsec;
+
+    if (!res) {
+        /* KRL: can one always set errno - cross platform ? */
+        errno =  EFAULT;
+        return -1;
+    }
+
+    switch (clk_id) {
+        case PA_CLOCK_REALTIME:
+		/* System-wide realtime clock (may be changed). */
+        case PA_CLOCK_MONOTONIC:
+		/* Clock that cannot be set and represents
+                   monotonic time since some unspecified starting point. */
+        case PA_CLOCK_MONOTONIC_RAW:
+		/* What's the difference? */
+            break;
+
+#if 0
+        case PA_CLOCK_PROCESS_CPUTIME_ID:
+		/* High-resolution per-process timer from the CPU. */
+        case PA_CLOCK_THREAD_CPUTIME_ID:
+		/* Thread-specific CPU-time clock. */
+#endif
+
+        default:
+            /* KRL: can one always set errno - cross platform ? */
+            errno = EINVAL;
+            return -1;
+    }
+
+    mach_timebase_info(&tbi);
+
+    /* nsec = nticks * (N/D) - we want 1 tick == resolution !? */
+    time_nsec = tbi.numer / tbi.denom;
+
+    /* I presume this is expected to be set !? */
+    res->tv_sec = time_nsec / 1E9;
+    res->tv_nsec = time_nsec;
+
+    return 0;
+#endif
+}
+
+
+int pa_clock_gettime(clockid_t clk_id, struct timespec *tp) {
+/* can't use HAVE_CLOCK_GETTIME as we override this to be true for Darwin */
+#ifndef OS_IS_DARWIN
+
+    return clock_gettime(clk_id, tp);
+
+#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)
+    */
+
+    if (!tp) {
+        /* KRL: can one always set errno - cross platform ? */
+        errno =  EFAULT;
+        return -1; // an error occurred
+    }
+
+    switch (clk_id) {
+        case PA_CLOCK_REALTIME:
+		/* System-wide realtime clock (may be changed). */
+        case PA_CLOCK_MONOTONIC:
+		/* Clock that cannot be set and represents
+                   monotonic time since some unspecified starting point. */
+        case PA_CLOCK_MONOTONIC_RAW:
+		/* What's the difference? */
+            break;
+
+#if 0
+        case PA_CLOCK_PROCESS_CPUTIME_ID:
+		/* High-resolution per-process timer from the CPU. */
+        case PA_CLOCK_THREAD_CPUTIME_ID:
+		/* Thread-specific CPU-time clock. */
+#endif
+
+        default:
+            // KRL: can one always set errno - cross platform ?
+            errno = EINVAL; // unsupported clk_id
+            return -1; // an error occurred (unsupported clk_id)
+    }
+
+    /* 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
+
+    tp->tv_sec = time_nsec / 1E9;
+    tp->tv_nsec = time_nsec;
+
+    /* FIXME: For CLOCK_REALTIME - modify by epoch else intermixing results of
+       gettimeofday() and this may cause confusion ....
+       However we probably want MONOTONIC anyway... */
+
+    return 0;
+
+#else
+
+    /* No clock_gettime() or replacement :-( */
+
+#endif
+}
+
+
+int pa_clock_settime(clockid_t clk_id, const struct timespec *tp) {
+#ifndef OS_IS_DARWIN
+/* #ifdef HAVE_CLOCK_SETTIME - use this eventually !? */
+
+    return clock_settime(clk_id, tp);
+
+#else
+
+    /* NOT IMPLEMENTED */
+    errno = EINVAL;
+    return -1;
+
+#endif
+}
diff --git a/src/pulsecore/core-clock.h b/src/pulsecore/core-clock.h
new file mode 100644
index 0000000..12d410b
--- /dev/null
+++ b/src/pulsecore/core-clock.h
@@ -0,0 +1,75 @@
+#ifndef foopulseclockhfoo
+#define foopulseclockhfoo
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2009 Kim Lester, Datafusion Systems P/L
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <time.h>
+
+
+#ifdef OS_IS_DARWIN
+
+/* OS X does not define clockid_t or clock_gettime() and friends */
+typedef int clockid_t;
+
+#define PA_CLOCK_REALTIME                  0
+#define PA_CLOCK_MONOTONIC                 1
+
+#if 0
+/* Not yet implemented, commented out for calling code that tests #defines: */
+#define PA_CLOCK_PROCESS_CPUTIME_ID        2
+#define PA_CLOCK_THREAD_CPUTIME_ID         3
+#endif
+
+/* treated as MONOTONIC for now...: */
+#define PA_CLOCK_MONOTONIC_RAW             4
+
+#else
+
+/* probably shouldn't expose the underlying implementation, however
+   it is expedient for now as calling code tests for #define existence */
+#ifdef CLOCK_REALTIME
+#define PA_CLOCK_REALTIME                  CLOCK_REALTIME
+#endif
+
+#ifdef CLOCK_MONOTONIC
+#define PA_CLOCK_MONOTONIC                 CLOCK_MONOTONIC
+#endif
+
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+#define PA_CLOCK_PROCESS_CPUTIME_ID        CLOCK_PROCESS_CPUTIME_ID
+#endif
+
+#ifdef CLOCK_THREAD_CPUTIME_ID
+#define PA_CLOCK_THREAD_CPUTIME_ID         CLOCK_THREAD_CPUTIME_ID
+#endif
+
+#if CLOCK_MONOTONIC_RAW
+#define PA_CLOCK_MONOTONIC_RAW             CLOCK_MONOTONIC_RAW
+#endif
+
+#endif
+
+int pa_clock_getres(clockid_t clk_id, struct timespec *res);
+int pa_clock_gettime(clockid_t clk_id, struct timespec *tp);
+int pa_clock_settime(clockid_t clk_id, const struct timespec *tp);
+
+#endif
diff --git a/src/pulsecore/core-rtclock.c b/src/pulsecore/core-rtclock.c
index 3b3e3a6..8d564f3 100644
--- a/src/pulsecore/core-rtclock.c
+++ b/src/pulsecore/core-rtclock.c
@@ -38,6 +38,7 @@
 #include <pulsecore/core-error.h>
 
 #include "core-rtclock.h"
+#include "core-clock.h"
 
 pa_usec_t pa_rtclock_age(const struct timeval *tv) {
     struct timeval now;
@@ -50,17 +51,17 @@ struct timeval *pa_rtclock_get(struct timeval *tv) {
 #ifdef HAVE_CLOCK_GETTIME
     struct timespec ts;
 
-#ifdef CLOCK_MONOTONIC
+#ifdef PA_CLOCK_MONOTONIC
     /* No locking or atomic ops for no_monotonic here */
     static pa_bool_t no_monotonic = FALSE;
 
     if (!no_monotonic)
-        if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
+        if (pa_clock_gettime(PA_CLOCK_MONOTONIC, &ts) < 0)
             no_monotonic = TRUE;
 
     if (no_monotonic)
 #endif
-        pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
+        pa_assert_se(pa_clock_gettime(PA_CLOCK_REALTIME, &ts) == 0);
 
     pa_assert(tv);
 
@@ -80,12 +81,12 @@ pa_bool_t pa_rtclock_hrtimer(void) {
 #ifdef HAVE_CLOCK_GETTIME
     struct timespec ts;
 
-#ifdef CLOCK_MONOTONIC
-    if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0)
+#ifdef PA_CLOCK_MONOTONIC
+    if (pa_clock_getres(PA_CLOCK_MONOTONIC, &ts) >= 0)
         return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
 #endif
 
-    pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0);
+    pa_assert_se(pa_clock_getres(PA_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 */
diff --git a/src/tests/rtstutter.c b/src/tests/rtstutter.c
index c93fee9..ba5f109 100644
--- a/src/tests/rtstutter.c
+++ b/src/tests/rtstutter.c
@@ -37,6 +37,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/core-clock.h>
 
 static int msec_lower, msec_upper;
 
@@ -67,8 +68,8 @@ static void* work(void *p) {
         pa_log_notice("CPU%i: Sleeping for 1s", PA_PTR_TO_UINT(p));
         sleep(1);
 
-#ifdef CLOCK_REALTIME
-        pa_assert_se(clock_gettime(CLOCK_REALTIME, &end) == 0);
+#ifdef PA_CLOCK_REALTIME
+        pa_assert_se(pa_clock_gettime(PA_CLOCK_REALTIME, &end) == 0);
 #endif
 
         nsec =
@@ -86,8 +87,8 @@ static void* work(void *p) {
         }
 
         do {
-#ifdef CLOCK_REALTIME
-            pa_assert_se(clock_gettime(CLOCK_REALTIME, &now) == 0);
+#ifdef PA_CLOCK_REALTIME
+            pa_assert_se(pa_clock_gettime(PA_CLOCK_REALTIME, &now) == 0);
 #endif
         } while (now.tv_sec < end.tv_sec ||
                  (now.tv_sec == end.tv_sec && now.tv_nsec < end.tv_nsec));
-- 
1.6.3.3




More information about the pulseaudio-discuss mailing list