]> git.saurik.com Git - apple/libc.git/blobdiff - gen/nanosleep.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / gen / nanosleep.c
index ae732f82f67697a9739357a8584e5d472e7f16c9..934707eefb81ddd96a735d693264d510bd3919e2 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <mach/mach_error.h>
 #include <mach/mach_time.h>
 #include <stdio.h>
 #include <mach/mach_error.h>
 #include <mach/mach_time.h>
 #include <stdio.h>
-
+#include <stdlib.h>
+#include <string.h>
+#include <TargetConditionals.h>
 
 #if __DARWIN_UNIX03
 
 #if __DARWIN_UNIX03
-#include "pthread_internals.h"
 #include <mach/clock.h>
 #include <mach/clock.h>
+#include <pthread.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
 
 
-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 semaphore_t clock_sem;
+extern mach_port_t clock_port;
+#endif /* !BUILDING_VARIANT */
+
+extern int __unix_conforming;
 #ifdef VARIANT_CANCELABLE
 #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 */
 #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 */
 
 #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;
 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 current;
+    mach_timespec_t completion;
    
        if (__unix_conforming == 0)
                __unix_conforming = 1;
 
 #ifdef VARIANT_CANCELABLE
    
        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)) {
 #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) {
 
 
     if (remaining_time != NULL) {
-        kret = clock_get_time(clock_port, &current);
+       /* 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));
         if (kret != KERN_SUCCESS) {
             fprintf(stderr, "clock_get_time() failed: %s\n", mach_error_string(kret));
+            errno = EINVAL;
             return -1;
         }
     }
             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) {
     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, &current);
                 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 */
                 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(&current, requested_time);
-                SUB_MACH_TIMESPEC(&current, &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, &current) > 0) {
+                   SUB_MACH_TIMESPEC(&completion, &current);
+                   remaining_time->tv_sec = completion.tv_sec;
+                   remaining_time->tv_nsec = completion.tv_nsec;
+               } else {
+                   bzero(remaining_time, sizeof(*remaining_time));
+               }
             }
         } else {
             errno = EINVAL;
             }
         } 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.
         */
         * 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--;
        }
            sub128_128(&backmul, &divisor128);
            uapprox--;
        }