#include <config.h>
#endif
+#ifdef OS_IS_DARWIN
+#define _POSIX_C_SOURCE 1
+#endif
+
#include <stddef.h>
#include <time.h>
#include <sys/time.h>
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
#endif
#include <pulse/timeval.h>
#include "core-rtclock.h"
+#ifdef OS_IS_WIN32
+static int64_t counter_freq = 0;
+#endif
+
pa_usec_t pa_rtclock_age(const struct timeval *tv) {
struct timeval now;
pa_assert(tv);
struct timeval *pa_rtclock_get(struct timeval *tv) {
-#if defined(HAVE_CLOCK_GETTIME)
+#if defined(OS_IS_DARWIN)
+ uint64_t val, abs_time = mach_absolute_time();
+ Nanoseconds nanos;
+
+ nanos = AbsoluteToNanoseconds(*(AbsoluteTime *) &abs_time);
+ val = *(uint64_t *) &nanos;
+
+ tv->tv_sec = val / PA_NSEC_PER_SEC;
+ tv->tv_usec = (val % PA_NSEC_PER_SEC) / PA_NSEC_PER_USEC;
+
+ return tv;
+
+#elif defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
#ifdef CLOCK_MONOTONIC
/* No locking or atomic ops for no_monotonic here */
- static pa_bool_t no_monotonic = FALSE;
+ static bool no_monotonic = false;
if (!no_monotonic)
if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
- no_monotonic = TRUE;
+ no_monotonic = true;
if (no_monotonic)
#endif /* CLOCK_MONOTONIC */
tv->tv_usec = ts.tv_nsec / PA_NSEC_PER_USEC;
return tv;
+#elif defined(OS_IS_WIN32)
+ if (counter_freq > 0) {
+ LARGE_INTEGER count;
-#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
+ pa_assert_se(QueryPerformanceCounter(&count));
- Note: argument is timespec NOT timeval (timespec uses nsec, timeval uses usec)
- */
+ tv->tv_sec = count.QuadPart / counter_freq;
+ tv->tv_usec = (count.QuadPart % counter_freq) * PA_USEC_PER_SEC / counter_freq;
- /* 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;
+ }
+#endif /* HAVE_CLOCK_GETTIME */
- return tv;
+ return pa_gettimeofday(tv);
+}
-#else /* OS_IS_DARWIN */
+bool pa_rtclock_hrtimer(void) {
- return pa_gettimeofday(tv);
+#if defined (OS_IS_DARWIN)
+ mach_timebase_info_data_t tbi;
+ uint64_t time_nsec;
-#endif
-}
+ mach_timebase_info(&tbi);
-pa_bool_t pa_rtclock_hrtimer(void) {
+ /* 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);
-#if defined(HAVE_CLOCK_GETTIME)
+#elif 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 /* 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);
-#elif defined (OS_IS_DARWIN)
- mach_timebase_info_data_t tbi;
- uint64_t time_nsec;
+#elif defined(OS_IS_WIN32)
- 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);
+ if (counter_freq > 0)
+ return counter_freq >= (int64_t) (PA_USEC_PER_SEC/PA_HRTIMER_THRESHOLD_USEC);
-#else /* OS_IS_DARWIN */
- return FALSE;
+#endif /* HAVE_CLOCK_GETTIME */
-#endif
+ return false;
}
#define TIMER_SLACK_NS (int) ((500 * PA_NSEC_PER_USEC))
}
}
+#elif defined(OS_IS_WIN32)
+ LARGE_INTEGER freq;
+
+ pa_assert_se(QueryPerformanceFrequency(&freq));
+ counter_freq = freq.QuadPart;
+
#endif
}
struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
-
-#ifdef HAVE_CLOCK_GETTIME
struct timeval wc_now, rt_now;
+ pa_assert(tv);
+
pa_gettimeofday(&wc_now);
pa_rtclock_get(&rt_now);
- pa_assert(tv);
-
/* pa_timeval_sub() saturates on underflow! */
if (pa_timeval_cmp(&wc_now, tv) < 0)
pa_timeval_sub(&rt_now, pa_timeval_diff(&wc_now, tv));
*tv = rt_now;
-#endif
return tv;
}
+#ifdef HAVE_CLOCK_GETTIME
pa_usec_t pa_timespec_load(const struct timespec *ts) {
if (PA_UNLIKELY(!ts))
return ts;
}
+#endif
static struct timeval* wallclock_from_rtclock(struct timeval *tv) {
-
-#ifdef HAVE_CLOCK_GETTIME
struct timeval wc_now, rt_now;
+ pa_assert(tv);
+
pa_gettimeofday(&wc_now);
pa_rtclock_get(&rt_now);
- pa_assert(tv);
-
/* pa_timeval_sub() saturates on underflow! */
if (pa_timeval_cmp(&rt_now, tv) < 0)
pa_timeval_sub(&wc_now, pa_timeval_diff(&rt_now, tv));
*tv = wc_now;
-#endif
return tv;
}
-struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, pa_bool_t rtclock) {
+struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, bool rtclock) {
pa_assert(tv);
if (v == PA_USEC_INVALID)