#include <kern/task.h>
#include <mach/time_value.h>
-#include <kern/lock.h>
+#include <kern/locks.h>
#include <sys/systm.h> /* for unix_syscall_return() */
#include <libkern/OSAtomic.h>
-extern boolean_t thread_should_abort(thread_t); /* XXX */
extern void compute_averunnable(void *); /* XXX */
struct uthread * ut;
int sig, catch;
int error = 0;
- int dropmutex;
+ int dropmutex, spinmutex;
ut = get_bsdthread_info(self);
catch = ut->uu_pri & PCATCH;
dropmutex = ut->uu_pri & PDROP;
+ spinmutex = ut->uu_pri & PSPIN;
switch (wresult) {
case THREAD_TIMED_OUT:
if (error == EINTR || error == ERESTART)
act_set_astbsd(self);
- if (ut->uu_mtx && !dropmutex)
- lck_mtx_lock(ut->uu_mtx);
-
+ if (ut->uu_mtx && !dropmutex) {
+ if (spinmutex)
+ lck_mtx_lock_spin(ut->uu_mtx);
+ else
+ lck_mtx_lock(ut->uu_mtx);
+ }
ut->uu_wchan = NULL;
ut->uu_wmesg = NULL;
struct proc *p;
thread_t self = current_thread();
struct uthread * ut;
- int sig, catch = pri & PCATCH;
+ int sig, catch;
int dropmutex = pri & PDROP;
+ int spinmutex = pri & PSPIN;
int wait_result;
int error = 0;
p->p_priority = pri & PRIMASK;
/* It can still block in proc_exit() after the teardown. */
if (p->p_stats != NULL)
- OSIncrementAtomic(&p->p_stats->p_ru.ru_nvcsw);
+ 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, (dropmutex) ? LCK_SLEEP_UNLOCK : 0,
- chan, (catch) ? THREAD_ABORTSAFE : THREAD_UNINT, abstime);
+ wait_result = lck_mtx_sleep_deadline(mtx, flags, chan, catch, abstime);
else
- wait_result = lck_mtx_sleep(mtx, (dropmutex) ? LCK_SLEEP_UNLOCK : 0,
- chan, (catch) ? THREAD_ABORTSAFE : THREAD_UNINT);
+ wait_result = lck_mtx_sleep(mtx, flags, chan, catch);
}
else {
if (chan != NULL)
- assert_wait_deadline(chan, (catch) ? THREAD_ABORTSAFE : THREAD_UNINT, abstime);
+ assert_wait_deadline(chan, catch, abstime);
if (mtx)
lck_mtx_unlock(mtx);
- if (catch) {
+
+ if (catch == THREAD_ABORTSAFE) {
if (SHOULDissignal(p,ut)) {
if ((sig = CURSIG(p)) != 0) {
if (clear_wait(self, THREAD_INTERRUPTED) == KERN_FAILURE)
error = EINTR;
else
error = ERESTART;
- if (mtx && !dropmutex)
- lck_mtx_lock(mtx);
+ if (mtx && !dropmutex) {
+ if (spinmutex)
+ lck_mtx_lock_spin(mtx);
+ else
+ lck_mtx_lock(mtx);
+ }
goto out;
}
}
goto block;
error = EINTR;
- if (mtx && !dropmutex)
- lck_mtx_lock(mtx);
+ if (mtx && !dropmutex) {
+ if (spinmutex)
+ lck_mtx_lock_spin(mtx);
+ else
+ lck_mtx_lock(mtx);
+ }
goto out;
}
}
wait_result = thread_block(THREAD_CONTINUE_NULL);
- if (mtx && !dropmutex)
- lck_mtx_lock(mtx);
+ if (mtx && !dropmutex) {
+ if (spinmutex)
+ lck_mtx_lock_spin(mtx);
+ else
+ lck_mtx_lock(mtx);
+ }
}
switch (wait_result) {
* first, regardless of whether awakened due
* to receiving event.
*/
- if (!catch)
+ if (catch != THREAD_ABORTSAFE)
break;
/* else fall through */
case THREAD_INTERRUPTED:
- if (catch) {
+ if (catch == THREAD_ABORTSAFE) {
if (thread_should_abort(self)) {
error = EINTR;
} else if (SHOULDissignal(p, ut)) {
if (thread_should_abort(self)) {
error = EINTR;
}
- }
+ } else if( (ut->uu_flag & ( UT_CANCELDISABLE | UT_CANCEL | UT_CANCELED)) == UT_CANCEL) {
+ /* due to thread cancel */
+ error = EINTR;
+ }
} else
error = EINTR;
break;
void
wakeup(void *chan)
{
- thread_wakeup_prim((caddr_t)chan, FALSE, THREAD_AWAKENED);
+ thread_wakeup((caddr_t)chan);
}
/*
void
wakeup_one(caddr_t chan)
{
- thread_wakeup_prim((caddr_t)chan, TRUE, THREAD_AWAKENED);
+ thread_wakeup_one((caddr_t)chan);
}
/*