+ int res, saved_error;
+ kern_return_t kern_res;
+ int wait_res;
+ pthread_mutex_t *busy;
+ mach_timespec_t then;
+ struct timespec cthen = {0,0};
+ int sig = cond->sig;
+ int msig = mutex->sig;
+extern void _pthread_testcancel(pthread_t thread, int isconforming);
+
+ /* to provide backwards compat for apps using united condtn vars */
+ if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init) && (sig != _PTHREAD_KERN_COND_SIG))
+ return(EINVAL);
+
+ if (isconforming) {
+ if((msig != _PTHREAD_MUTEX_SIG) && (msig != _PTHREAD_MUTEX_SIG_init) && (msig != _PTHREAD_KERN_MUTEX_SIG))
+ return(EINVAL);
+ if (isconforming > 0)
+ _pthread_testcancel(pthread_self(), 1);
+ }
+ LOCK(cond->lock);
+ if (cond->sig != _PTHREAD_COND_SIG)
+ {
+ if (cond->sig != _PTHREAD_COND_SIG_init)
+ {
+ if ((cond->sig == _PTHREAD_KERN_COND_SIG) && (mutex->sig == _PTHREAD_KERN_MUTEX_SIG)) {
+ int condid = cond->_pthread_cond_kernid;
+ int mutexid = mutex->_pthread_mutex_kernid;
+ UNLOCK(cond->lock);
+
+ if (abstime) {
+ struct timespec now;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &now);
+
+ /* Compute relative time to sleep */
+ then.tv_nsec = abstime->tv_nsec - now.tv_nsec;
+ then.tv_sec = abstime->tv_sec - now.tv_sec;
+ if (then.tv_nsec < 0)
+ {
+ then.tv_nsec += NSEC_PER_SEC;
+ then.tv_sec--;
+ }
+ if (((int)then.tv_sec < 0) ||
+ ((then.tv_sec == 0) && (then.tv_nsec == 0)))
+ {
+ UNLOCK(cond->lock);
+ return ETIMEDOUT;
+ }
+ if ((res = pthread_mutex_unlock(mutex)) != 0)
+ return (res);
+
+ if ((__pthread_cond_timedwait(condid, mutexid, &then)) == -1)
+ saved_error = errno;
+ else
+ saved_error = 0;
+ } else {
+ if ((res = pthread_mutex_unlock(mutex)) != 0)
+ return (res);
+ if(( __pthread_cond_wait(condid, mutexid)) == -1)
+ saved_error = errno;
+ else
+ saved_error = 0;
+ }
+ if ((res = pthread_mutex_lock(mutex)) != 0)
+ return (res);
+ return(saved_error);
+ } else {
+ UNLOCK(cond->lock);
+ return (EINVAL); /* Not a condition variable */
+ }
+ }
+ _pthread_cond_init(cond, NULL, 0);
+ }
+
+ if (abstime) {
+ if (!isconforming)
+ {
+ if (isRelative == 0) {
+ struct timespec now;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &now);
+
+ /* Compute relative time to sleep */
+ then.tv_nsec = abstime->tv_nsec - now.tv_nsec;
+ then.tv_sec = abstime->tv_sec - now.tv_sec;
+ if (then.tv_nsec < 0)
+ {
+ then.tv_nsec += NSEC_PER_SEC;
+ then.tv_sec--;
+ }
+ if (((int)then.tv_sec < 0) ||
+ ((then.tv_sec == 0) && (then.tv_nsec == 0)))
+ {
+ UNLOCK(cond->lock);
+ return ETIMEDOUT;
+ }
+ } else {
+ then.tv_sec = abstime->tv_sec;
+ then.tv_nsec = abstime->tv_nsec;
+ }
+ if (then.tv_nsec >= NSEC_PER_SEC) {
+ UNLOCK(cond->lock);
+ return EINVAL;
+ }
+ } else {
+ if (isRelative == 0) {
+ /* preflight the checks for failures */
+ struct timespec now;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &now);