From ad9aa180d30ebf2ae91e3cc656c814693bb921ca Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Wed, 21 Jan 2015 21:21:28 +0800 Subject: [PATCH] utils: use clock_get_time() for clock_gettime() on Apple. It turns out that mach_absolute_time() is not monotonic at all. While at it, convert the CLOCK_REALTIME implementation to using clock_get_time() as well. Signed-off-by: Yousong Zhou --- utils.c | 59 ++++++++++++++++++++++++++++++++++------------------------- utils.h | 11 ++++++++--- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/utils.c b/utils.c index 078a8a1..8fd19f4 100644 --- a/utils.c +++ b/utils.c @@ -54,41 +54,50 @@ void *__calloc_a(size_t len, ...) } #ifdef __APPLE__ -#include +#include /* host_get_clock_service() */ +#include /* mach_port_deallocate() */ +#include /* mach_host_self(), mach_task_self() */ +#include /* clock_get_time() */ -static void clock_gettime_realtime(struct timespec *tv) +static clock_serv_t clock_realtime; +static clock_serv_t clock_monotonic; + +static void __constructor clock_name_init(void) { - struct timeval _tv; + mach_port_t host_self = mach_host_self(); - gettimeofday(&_tv, NULL); - tv->tv_sec = _tv.tv_sec; - tv->tv_nsec = _tv.tv_usec * 1000; + host_get_clock_service(host_self, CLOCK_REALTIME, &clock_realtime); + host_get_clock_service(host_self, CLOCK_MONOTONIC, &clock_monotonic); } -static void clock_gettime_monotonic(struct timespec *tv) +static void __destructor clock_name_dealloc(void) { - mach_timebase_info_data_t info; - float sec; - uint64_t val; - - mach_timebase_info(&info); - - val = mach_absolute_time(); - tv->tv_nsec = (val * info.numer / info.denom) % 1000000000; + mach_port_t self = mach_task_self(); - sec = val; - sec *= info.numer; - sec /= info.denom; - sec /= 1000000000; - tv->tv_sec = sec; + mach_port_deallocate(self, clock_realtime); + mach_port_deallocate(self, clock_monotonic); } -void clock_gettime(int type, struct timespec *tv) +int clock_gettime(int type, struct timespec *tv) { - if (type == CLOCK_REALTIME) - return clock_gettime_realtime(tv); - else - return clock_gettime_monotonic(tv); + int retval = -1; + mach_timespec_t mts; + + switch (type) { + case CLOCK_REALTIME: + retval = clock_get_time(clock_realtime, &mts); + break; + case CLOCK_MONOTONIC: + retval = clock_get_time(clock_monotonic, &mts); + break; + default: + goto out; + } + + tv->tv_sec = mts.tv_sec; + tv->tv_nsec = mts.tv_nsec; +out: + return retval; } #endif diff --git a/utils.h b/utils.h index 9688a6a..7ef82c6 100644 --- a/utils.h +++ b/utils.h @@ -58,10 +58,11 @@ extern int __BUILD_BUG_ON_CONDITION_FAILED; #ifdef __APPLE__ -#define CLOCK_REALTIME 0 -#define CLOCK_MONOTONIC 1 +#include +#define CLOCK_REALTIME CALENDAR_CLOCK +#define CLOCK_MONOTONIC SYSTEM_CLOCK -void clock_gettime(int type, struct timespec *tv); +int clock_gettime(int type, struct timespec *tv); #endif @@ -159,6 +160,10 @@ static inline uint16_t __u_bswap16(uint16_t val) #define __constructor __attribute__((constructor)) #endif +#ifndef __destructor +#define __destructor __attribute__((destructor)) +#endif + #ifndef __hidden #define __hidden __attribute__((visibility("hidden"))) #endif -- 2.11.0