Navigation Menu

Skip to content

Commit

Permalink
darwin: work around clock jumping back in time
Browse files Browse the repository at this point in the history
It was reported that mach_absolute_time() can jump backward in time when
the machine is suspended. Use mach_continuous_time() when available to
work around that (macOS 10.12 and up.)

Fixes: libuv#2891
PR-URL: libuv#2894
Reviewed-By: Phil Willoughby <philwill@fb.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
  • Loading branch information
bnoordhuis committed Jul 1, 2020
1 parent 41f5732 commit 4685be2
Showing 1 changed file with 16 additions and 7 deletions.
23 changes: 16 additions & 7 deletions src/unix/darwin.c
Expand Up @@ -25,13 +25,18 @@
#include <stdint.h>
#include <errno.h>

#include <dlfcn.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <mach-o/dyld.h> /* _NSGetExecutablePath */
#include <sys/resource.h>
#include <sys/sysctl.h>
#include <unistd.h> /* sysconf */

static uv_once_t once = UV_ONCE_INIT;
static uint64_t (*time_func)(void);
static mach_timebase_info_data_t timebase;


int uv__platform_loop_init(uv_loop_t* loop) {
loop->cf_state = NULL;
Expand All @@ -48,15 +53,19 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}


uint64_t uv__hrtime(uv_clocktype_t type) {
static mach_timebase_info_data_t info;

if ((ACCESS_ONCE(uint32_t, info.numer) == 0 ||
ACCESS_ONCE(uint32_t, info.denom) == 0) &&
mach_timebase_info(&info) != KERN_SUCCESS)
static void uv__hrtime_init_once(void) {
if (KERN_SUCCESS != mach_timebase_info(&timebase))
abort();

return mach_absolute_time() * info.numer / info.denom;
time_func = (uint64_t (*)(void)) dlsym(RTLD_DEFAULT, "mach_continuous_time");
if (time_func == NULL)
time_func = mach_absolute_time;
}


uint64_t uv__hrtime(uv_clocktype_t type) {
uv_once(&once, uv__hrtime_init_once);
return time_func() * timebase.numer / timebase.denom;
}


Expand Down

0 comments on commit 4685be2

Please sign in to comment.