X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/224c70764cab4e0e39a26aaf3ad3016552f62f55..aa54d2fad3d9038b43475aa93c76795c5141a993:/gen/nanosleep.c?ds=sidebyside diff --git a/gen/nanosleep.c b/gen/nanosleep.c index ae732f8..934707e 100644 --- a/gen/nanosleep.c +++ b/gen/nanosleep.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2003, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (c) 1999, 2003, 2006, 2007, 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,21 +26,49 @@ #include #include #include - +#include +#include +#include #if __DARWIN_UNIX03 -#include "pthread_internals.h" #include +#include +#include +#include -extern int __unix_conforming; -extern mach_port_t clock_port; +#if !defined(BUILDING_VARIANT) +semaphore_t clock_sem = MACH_PORT_NULL; +mach_port_t clock_port = MACH_PORT_NULL; + +void _init_clock_port(void); + +void _init_clock_port(void) { + kern_return_t kr; + mach_port_t host = mach_host_self(); + + /* Get the clock service port for nanosleep */ + kr = host_get_clock_service(host, SYSTEM_CLOCK, &clock_port); + if (kr != KERN_SUCCESS) { + abort(); + } + + kr = semaphore_create(mach_task_self(), &clock_sem, SYNC_POLICY_FIFO, 0); + if (kr != KERN_SUCCESS) { + abort(); + } + mach_port_deallocate(mach_task_self(), host); +} +#else extern semaphore_t clock_sem; +extern mach_port_t clock_port; +#endif /* !BUILDING_VARIANT */ + +extern int __unix_conforming; #ifdef VARIANT_CANCELABLE -extern void _pthread_testcancel(pthread_t thread, int isconforming); -extern int __semwait_signal(int cond_sem, int mutex_sem, int timeout, int relative, time_t tv_sec, __int32_t tv_nsec); +extern int __semwait_signal(int cond_sem, int mutex_sem, int timeout, int relative, __int64_t tv_sec, __int32_t tv_nsec); #define SEMWAIT_SIGNAL __semwait_signal #else /* !VARIANT_CANCELABLE */ -extern int __semwait_signal_nocancel(int cond_sem, int mutex_sem, int timeout, int relative, time_t tv_sec, __int32_t tv_nsec); +extern int __semwait_signal_nocancel(int cond_sem, int mutex_sem, int timeout, int relative, __int64_t tv_sec, __int32_t tv_nsec); #define SEMWAIT_SIGNAL __semwait_signal_nocancel #endif /* VARIANT_CANCELABLE */ @@ -48,14 +76,14 @@ int nanosleep(const struct timespec *requested_time, struct timespec *remaining_time) { kern_return_t kret; int ret; - mach_timespec_t remain; mach_timespec_t current; + mach_timespec_t completion; if (__unix_conforming == 0) __unix_conforming = 1; #ifdef VARIANT_CANCELABLE - _pthread_testcancel(pthread_self(), 1); + pthread_testcancel(); #endif /* VARIANT_CANCELABLE */ if ((requested_time == NULL) || (requested_time->tv_sec < 0) || (requested_time->tv_nsec >= NSEC_PER_SEC)) { @@ -65,28 +93,35 @@ nanosleep(const struct timespec *requested_time, struct timespec *remaining_time if (remaining_time != NULL) { - kret = clock_get_time(clock_port, ¤t); + /* once we add requested_time, this will be the completion time */ + kret = clock_get_time(clock_port, &completion); if (kret != KERN_SUCCESS) { fprintf(stderr, "clock_get_time() failed: %s\n", mach_error_string(kret)); + errno = EINVAL; return -1; } } - ret = SEMWAIT_SIGNAL(clock_sem, MACH_PORT_NULL, 1, 1, requested_time->tv_sec, requested_time->tv_nsec); + ret = SEMWAIT_SIGNAL(clock_sem, MACH_PORT_NULL, 1, 1, (int64_t)requested_time->tv_sec, (int32_t)requested_time->tv_nsec); if (ret < 0) { if (errno == ETIMEDOUT) { return 0; } else if (errno == EINTR) { if (remaining_time != NULL) { - ret = clock_get_time(clock_port, &remain); + ret = clock_get_time(clock_port, ¤t); if (ret != KERN_SUCCESS) { fprintf(stderr, "clock_get_time() failed: %s\n", mach_error_string(ret)); return -1; } /* This depends on the layout of a mach_timespec_t and timespec_t being equivalent */ - ADD_MACH_TIMESPEC(¤t, requested_time); - SUB_MACH_TIMESPEC(¤t, &remain); - remaining_time->tv_sec = current.tv_sec; - remaining_time->tv_nsec = current.tv_nsec; + ADD_MACH_TIMESPEC(&completion, requested_time); + /* We have to compare first, since mach_timespect_t contains unsigned integers */ + if(CMP_MACH_TIMESPEC(&completion, ¤t) > 0) { + SUB_MACH_TIMESPEC(&completion, ¤t); + remaining_time->tv_sec = completion.tv_sec; + remaining_time->tv_nsec = completion.tv_nsec; + } else { + bzero(remaining_time, sizeof(*remaining_time)); + } } } else { errno = EINVAL; @@ -196,7 +231,7 @@ muldiv128(uint64_t x, uint64_t y, uint64_t divisor, uint64_t *res) * answer from the lesser side. So if our estimate is too large * we need to decrease it until it is smaller. */ - while(backmul.high > temp.high || backmul.high == temp.high && backmul.low > temp.low) { + while(backmul.high > temp.high || (backmul.high == temp.high && backmul.low > temp.low)) { sub128_128(&backmul, &divisor128); uapprox--; }