#include <errno.h>
#include <sys/time.h>
#include <mach/mach_error.h>
#include <mach/mach_time.h>
#include <stdio.h>
int
nanosleep(const struct timespec *requested_time, struct timespec *remaining_time) {
kern_return_t ret;
mach_timespec_t remain;
mach_timespec_t current;
uint64_t end;
static double ratio = 0.0, rratio;
if ((requested_time == NULL) || (requested_time->tv_sec < 0) || (requested_time->tv_nsec > NSEC_PER_SEC)) {
errno = EINVAL;
return -1;
}
if (ratio == 0.0) {
struct mach_timebase_info info;
ret = mach_timebase_info(&info);
if (ret != KERN_SUCCESS) {
fprintf(stderr, "mach_timebase_info() failed: %s\n", mach_error_string(ret));
errno = EAGAIN;
return -1;
}
ratio = (double)info.numer / ((double)info.denom * NSEC_PER_SEC);
rratio = (double)info.denom / (double)info.numer;
}
end = mach_absolute_time() + (uint64_t)(((double)requested_time->tv_sec * NSEC_PER_SEC + (double)requested_time->tv_nsec) * rratio);
ret = mach_wait_until(end);
if (ret != KERN_SUCCESS) {
if (ret == KERN_ABORTED) {
errno = EINTR;
if (remaining_time != NULL) {
uint64_t now = mach_absolute_time();
double delta;
if (now > end)
now = end;
delta = (end - now) * ratio;
remaining_time->tv_sec = delta;
remaining_time->tv_nsec = NSEC_PER_SEC * (delta - remaining_time->tv_sec);
}
} else {
errno = EINVAL;
}
return -1;
}
return 0;
}