From: Kim Lester <kim@xxxxxxxxxxxxxx> 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