-
- 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;
+ /* It can still block in proc_exit() after the teardown. */
+ if (p->p_stats != NULL)
+ OSIncrementAtomicLong(&p->p_stats->p_ru.ru_nvcsw);
+
+ if (pri & PCATCH)
+ catch = THREAD_ABORTSAFE;
+ else
+ catch = THREAD_UNINT;
+
+ /* set wait message & channel */
+ ut->uu_wchan = chan;
+ ut->uu_wmesg = wmsg ? wmsg : "unknown";
+
+ if (mtx != NULL && chan != NULL && (thread_continue_t)continuation == THREAD_CONTINUE_NULL) {
+ int flags;
+
+ if (dropmutex)
+ flags = LCK_SLEEP_UNLOCK;
+ else
+ flags = LCK_SLEEP_DEFAULT;
+
+ if (spinmutex)
+ flags |= LCK_SLEEP_SPIN;
+
+ if (abstime)
+ wait_result = lck_mtx_sleep_deadline(mtx, flags, chan, catch, abstime);
+ else
+ wait_result = lck_mtx_sleep(mtx, flags, chan, catch);
+ }
+ else {
+ if (chan != NULL)
+ assert_wait_deadline(chan, catch, abstime);
+ if (mtx)
+ lck_mtx_unlock(mtx);
+
+ if (catch == THREAD_ABORTSAFE) {
+ if (SHOULDissignal(p,ut)) {
+ if ((sig = CURSIG(p)) != 0) {
+ if (clear_wait(self, THREAD_INTERRUPTED) == KERN_FAILURE)
+ goto block;
+ if (p->p_sigacts->ps_sigintr & sigmask(sig))
+ error = EINTR;
+ else
+ error = ERESTART;
+ if (mtx && !dropmutex) {
+ if (spinmutex)
+ lck_mtx_lock_spin(mtx);
+ else
+ lck_mtx_lock(mtx);
+ }