-
- if (chan)
- wait_result = assert_wait(chan,
- (catch) ? THREAD_ABORTSAFE : THREAD_UNINT);
-
- if (abstime)
- thread_set_timer_deadline(abstime);
-
- /*
- * We start our timeout
- * before calling CURSIG, as we could stop there, and a wakeup
- * or a SIGCONT (or both) could occur while we were stopped.
- * A SIGCONT would cause us to be marked as SSLEEP
- * without resuming us, thus we must be ready for sleep
- * when CURSIG is called. If the wakeup happens while we're
- * stopped, p->p_wchan will be 0 upon return from CURSIG.
- */
- if (catch) {
- if (SHOULDissignal(p,ut)) {
- if (sig = CURSIG(p)) {
- clear_wait(thread, THREAD_INTERRUPTED);
- /* if SIGTTOU or SIGTTIN then block till SIGCONT */
- if (sigttblock && ((sig == SIGTTOU) || (sig == SIGTTIN))) {
- p->p_flag |= P_TTYSLEEP;
- /* reset signal bits */
- clear_procsiglist(p, sig);
- assert_wait(&p->p_siglist, THREAD_ABORTSAFE);
- /* assert wait can block and SIGCONT should be checked */
- if (p->p_flag & P_TTYSLEEP)
- thread_block(THREAD_CONTINUE_NULL);
- /* return with success */
- error = 0;
+ p->p_stats->p_ru.ru_nvcsw++;
+
+ if (mtx != NULL && chan != NULL && (thread_continue_t)continuation == THREAD_CONTINUE_NULL) {
+
+ if (abstime)
+ wait_result = lck_mtx_sleep_deadline(mtx, (dropmutex) ? LCK_SLEEP_UNLOCK : 0,
+ chan, (catch) ? THREAD_ABORTSAFE : THREAD_UNINT, abstime);
+ else
+ wait_result = lck_mtx_sleep(mtx, (dropmutex) ? LCK_SLEEP_UNLOCK : 0,
+ chan, (catch) ? THREAD_ABORTSAFE : THREAD_UNINT);
+ }
+ else {
+ if (chan != NULL)
+ assert_wait_deadline(chan, (catch) ? THREAD_ABORTSAFE : THREAD_UNINT, abstime);
+ if (mtx)
+ lck_mtx_unlock(mtx);
+ if (catch) {
+ if (SHOULDissignal(p,ut)) {
+ if (sig = CURSIG(p)) {
+ if (clear_wait(self, THREAD_INTERRUPTED) == KERN_FAILURE)
+ goto block;
+ /* if SIGTTOU or SIGTTIN then block till SIGCONT */
+ if ((pri & PTTYBLOCK) && ((sig == SIGTTOU) || (sig == SIGTTIN))) {
+ p->p_flag |= P_TTYSLEEP;
+ /* reset signal bits */
+ clear_procsiglist(p, sig);
+ assert_wait(&p->p_siglist, THREAD_ABORTSAFE);
+ /* assert wait can block and SIGCONT should be checked */
+ if (p->p_flag & P_TTYSLEEP) {
+ thread_block(THREAD_CONTINUE_NULL);
+
+ if (mtx && !dropmutex)
+ lck_mtx_lock(mtx);
+ }
+
+ /* return with success */
+ error = 0;
+ goto out;
+ }
+ if (p->p_sigacts->ps_sigintr & sigmask(sig))
+ error = EINTR;
+ else
+ error = ERESTART;
+ if (mtx && !dropmutex)
+ lck_mtx_lock(mtx);