int gettime(struct timespec *tp) { static struct timespec res = {.tv_sec = 0, .tv_nsec = 0}; /* Find out clock resolution. Will only be retrieved on first call */ if (!res.tv_sec && !res.tv_nsec) { clock_getres(CLOCK_REALTIME, &res); /* Clock resolution is lower than expected (1ns) */ assert(res.tv_nsec == 1); } /* Get wall-clock time */ return clock_gettime(CLOCK_REALTIME, tp); } /* OS X hasn't defined POSIX clocks, but clock_get_time() */ #elif defined HAVE_CLOCK_GET_TIME int gettime(struct timespec *tp) { static struct timespec res = {.tv_sec = 0, .tv_nsec = 0}; clock_serv_t cclock; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); /* Find out clock resolution. Will only be retrieved on first call */ if (!res.tv_sec && !res.tv_nsec) { natural_t attribute[4]; mach_msg_type_number_t count = sizeof(attribute)/sizeof(natural_t); clock_get_attributes(cclock, CLOCK_GET_TIME_RES, (clock_attr_t) &attribute, &count); /* Clock resolution is lower than expected (1ns) */ assert(attribute[0] > 1); } mach_timespec_t mts; kern_return_t rc = clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); tp->tv_sec = mts.tv_sec; tp->tv_nsec = mts.tv_nsec; return (rc == KERN_SUCCESS ? 0 : -1); }
static Sint64 mach_clock_getres(ErtsMachClock *clk) { kern_return_t kret; natural_t attr[1]; mach_msg_type_number_t cnt; cnt = sizeof(attr); kret = clock_get_attributes(clk->srv, CLOCK_GET_TIME_RES, (clock_attr_t) attr, &cnt); if (kret != KERN_SUCCESS || cnt != 1) { erl_exit(ERTS_ABORT_EXIT, "clock_get_attributes(%s, _) failed\n", clk->name); } return (Sint64) attr[0]; }