+ else if (kern_result == KERN_SUCCESS && truncated_timeout)
+ return(EINTR); /* simulate an exceptional condition because Mach doesn't support a longer timeout */
+ else if (kern_result == KERN_ABORTED)
+ return(EINTR);
+ else if (kern_result == KERN_OPERATION_TIMED_OUT)
+ return(ETIMEDOUT);
+ else
+ return(EINVAL);
+}
+#endif /* OLD_SEMWAIT_SIGNAL*/
+
+/*
+ * Returns: 0 Success
+ * EINTR
+ * ETIMEDOUT
+ * EINVAL
+ * EFAULT if timespec is NULL
+ */
+int
+__semwait_signal(proc_t p, struct __semwait_signal_args *uap,
+ int32_t *retval)
+{
+ __pthread_testcancel(0);
+ return(__semwait_signal_nocancel(p, (struct __semwait_signal_nocancel_args *)uap, retval));
+}
+
+int
+__semwait_signal_nocancel(__unused proc_t p, struct __semwait_signal_nocancel_args *uap,
+ __unused int32_t *retval)
+{
+
+ kern_return_t kern_result;
+ mach_timespec_t then;
+ struct timespec now;
+ struct user_timespec ts;
+ boolean_t truncated_timeout = FALSE;
+
+ if(uap->timeout) {
+
+ ts.tv_sec = uap->tv_sec;
+ ts.tv_nsec = uap->tv_nsec;
+
+ if ((ts.tv_sec & 0xFFFFFFFF00000000ULL) != 0) {
+ ts.tv_sec = 0xFFFFFFFF;
+ ts.tv_nsec = 0;
+ truncated_timeout = TRUE;
+ }
+
+ if (uap->relative) {
+ then.tv_sec = ts.tv_sec;
+ then.tv_nsec = ts.tv_nsec;
+ } else {
+ nanotime(&now);
+
+ /* if time has elapsed, set time to null timepsec to bailout rightaway */
+ if (now.tv_sec == ts.tv_sec ?
+ now.tv_nsec > ts.tv_nsec :
+ now.tv_sec > ts.tv_sec) {
+ then.tv_sec = 0;
+ then.tv_nsec = 0;
+ } else {
+ then.tv_sec = ts.tv_sec - now.tv_sec;
+ then.tv_nsec = ts.tv_nsec - now.tv_nsec;
+ if (then.tv_nsec < 0) {
+ then.tv_nsec += NSEC_PER_SEC;
+ then.tv_sec--;
+ }
+ }
+ }
+
+ if (uap->mutex_sem == 0)
+ kern_result = semaphore_timedwait_trap_internal((mach_port_name_t)uap->cond_sem, then.tv_sec, then.tv_nsec, __posix_sem_syscall_return);
+ else
+ kern_result = semaphore_timedwait_signal_trap_internal(uap->cond_sem, uap->mutex_sem, then.tv_sec, then.tv_nsec, __posix_sem_syscall_return);
+
+ } else {
+
+ if (uap->mutex_sem == 0)
+ kern_result = semaphore_wait_trap_internal(uap->cond_sem, __posix_sem_syscall_return);
+ else
+
+ kern_result = semaphore_wait_signal_trap_internal(uap->cond_sem, uap->mutex_sem, __posix_sem_syscall_return);
+ }
+
+ if (kern_result == KERN_SUCCESS && !truncated_timeout)
+ return(0);
+ else if (kern_result == KERN_SUCCESS && truncated_timeout)
+ return(EINTR); /* simulate an exceptional condition because Mach doesn't support a longer timeout */