Index: kern/kern_condvar.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_condvar.c,v retrieving revision 1.57 diff -u -r1.57 kern_condvar.c --- kern/kern_condvar.c 16 Dec 2006 06:54:08 -0000 1.57 +++ kern/kern_condvar.c 23 Feb 2007 23:05:43 -0000 @@ -49,12 +49,11 @@ /* * Common sanity checks for cv_wait* functions. */ -#define CV_ASSERT(cvp, mp, td) do { \ +#define CV_ASSERT(cvp, lock, td) do { \ KASSERT((td) != NULL, ("%s: curthread NULL", __func__)); \ KASSERT(TD_IS_RUNNING(td), ("%s: not TDS_RUNNING", __func__)); \ KASSERT((cvp) != NULL, ("%s: cvp NULL", __func__)); \ - KASSERT((mp) != NULL, ("%s: mp NULL", __func__)); \ - mtx_assert((mp), MA_OWNED | MA_NOTRECURSED); \ + KASSERT((lock) != NULL, ("%s: lock NULL", __func__)); \ } while (0) /* @@ -93,11 +92,23 @@ * held when cv_signal or cv_broadcast are called. */ void -cv_wait(struct cv *cvp, struct mtx *mp) +_cv_wait(struct cv *cvp, struct lock_object *lock) { - WITNESS_SAVE_DECL(mp); + struct lock_class *class; + struct thread *td; + int lock_state; + WITNESS_SAVE_DECL(lock_witness); - WITNESS_SAVE(&mp->mtx_object, mp); + td = curthread; +#ifdef KTRACE + if (KTRPOINT(td, KTR_CSW)) + ktrcsw(1, 0); +#endif + CV_ASSERT(cvp, lock, td); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, + "Waiting on \"%s\"", cvp->cv_description); + WITNESS_SAVE(lock, lock_witness); + class = LOCK_CLASS(lock); if (cold || panicstr) { /* @@ -109,9 +120,23 @@ return; } - cv_wait_unlock(cvp, mp); - mtx_lock(mp); - WITNESS_RESTORE(&mp->mtx_object, mp); + sleepq_lock(cvp); + + cvp->cv_waiters++; + DROP_GIANT(); + lock_state = class->lc_unlock(lock); + + sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR, + 0); + sleepq_wait(cvp); + +#ifdef KTRACE + if (KTRPOINT(td, KTR_CSW)) + ktrcsw(0, 0); +#endif + PICKUP_GIANT(); + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); } /* @@ -119,8 +144,9 @@ * not aquiring the mutex after condition variable was signaled. */ void -cv_wait_unlock(struct cv *cvp, struct mtx *mp) +_cv_wait_unlock(struct cv *cvp, struct lock_object *lock) { + struct lock_class *class; struct thread *td; td = curthread; @@ -128,9 +154,10 @@ if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0); #endif - CV_ASSERT(cvp, mp, td); - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object, + CV_ASSERT(cvp, lock, td); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, "Waiting on \"%s\"", cvp->cv_description); + class = LOCK_CLASS(lock); if (cold || panicstr) { /* @@ -139,7 +166,7 @@ * thread or panic below, in case this is the idle * process and already asleep. */ - mtx_unlock(mp); + class->lc_unlock(lock); return; } @@ -147,12 +174,16 @@ cvp->cv_waiters++; DROP_GIANT(); - mtx_unlock(mp); + class->lc_unlock(lock); - sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR, + sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR, 0); sleepq_wait(cvp); +#ifdef KTRACE + if (KTRPOINT(td, KTR_CSW)) + ktrcsw(0, 0); +#endif PICKUP_GIANT(); } @@ -163,12 +194,13 @@ * restarted if possible. */ int -cv_wait_sig(struct cv *cvp, struct mtx *mp) +_cv_wait_sig(struct cv *cvp, struct lock_object *lock) { + struct lock_class *class; struct thread *td; struct proc *p; - int rval; - WITNESS_SAVE_DECL(mp); + int lock_state, rval; + WITNESS_SAVE_DECL(lock_witness); td = curthread; p = td->td_proc; @@ -176,10 +208,11 @@ if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0); #endif - CV_ASSERT(cvp, mp, td); - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object, + CV_ASSERT(cvp, lock, td); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, "Waiting on \"%s\"", cvp->cv_description); - WITNESS_SAVE(&mp->mtx_object, mp); + WITNESS_SAVE(lock, lock_witness); + class = LOCK_CLASS(lock); if (cold || panicstr) { /* @@ -195,9 +228,9 @@ cvp->cv_waiters++; DROP_GIANT(); - mtx_unlock(mp); + lock_state = class->lc_unlock(lock); - sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR | + sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR | SLEEPQ_INTERRUPTIBLE, 0); rval = sleepq_wait_sig(cvp); @@ -206,8 +239,8 @@ ktrcsw(0, 0); #endif PICKUP_GIANT(); - mtx_lock(mp); - WITNESS_RESTORE(&mp->mtx_object, mp); + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); return (rval); } @@ -218,11 +251,12 @@ * expires. */ int -cv_timedwait(struct cv *cvp, struct mtx *mp, int timo) +_cv_timedwait(struct cv *cvp, struct lock_object *lock, int timo) { + struct lock_class *class; struct thread *td; - int rval; - WITNESS_SAVE_DECL(mp); + int lock_state, rval; + WITNESS_SAVE_DECL(lock_witness); td = curthread; rval = 0; @@ -230,10 +264,11 @@ if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0); #endif - CV_ASSERT(cvp, mp, td); - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object, + CV_ASSERT(cvp, lock, td); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, "Waiting on \"%s\"", cvp->cv_description); - WITNESS_SAVE(&mp->mtx_object, mp); + WITNESS_SAVE(lock, lock_witness); + class = LOCK_CLASS(lock); if (cold || panicstr) { /* @@ -249,9 +284,9 @@ cvp->cv_waiters++; DROP_GIANT(); - mtx_unlock(mp); + lock_state = class->lc_unlock(lock); - sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR, + sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR, 0); sleepq_set_timeout(cvp, timo); rval = sleepq_timedwait(cvp); @@ -261,8 +296,8 @@ ktrcsw(0, 0); #endif PICKUP_GIANT(); - mtx_lock(mp); - WITNESS_RESTORE(&mp->mtx_object, mp); + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); return (rval); } @@ -274,12 +309,13 @@ * a signal was caught. */ int -cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo) +_cv_timedwait_sig(struct cv *cvp, struct lock_object *lock, int timo) { + struct lock_class *class; struct thread *td; struct proc *p; - int rval; - WITNESS_SAVE_DECL(mp); + int lock_state, rval; + WITNESS_SAVE_DECL(lock_witness); td = curthread; p = td->td_proc; @@ -288,10 +324,11 @@ if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0); #endif - CV_ASSERT(cvp, mp, td); - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object, + CV_ASSERT(cvp, lock, td); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, "Waiting on \"%s\"", cvp->cv_description); - WITNESS_SAVE(&mp->mtx_object, mp); + WITNESS_SAVE(lock, lock_witness); + class = LOCK_CLASS(lock); if (cold || panicstr) { /* @@ -307,9 +344,9 @@ cvp->cv_waiters++; DROP_GIANT(); - mtx_unlock(mp); + lock_state = class->lc_unlock(lock); - sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR | + sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR | SLEEPQ_INTERRUPTIBLE, 0); sleepq_set_timeout(cvp, timo); rval = sleepq_timedwait_sig(cvp); @@ -319,8 +356,8 @@ ktrcsw(0, 0); #endif PICKUP_GIANT(); - mtx_lock(mp); - WITNESS_RESTORE(&mp->mtx_object, mp); + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); return (rval); } Index: kern/kern_mutex.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_mutex.c,v retrieving revision 1.179 diff -u -r1.179 kern_mutex.c --- kern/kern_mutex.c 16 Dec 2006 02:37:57 -0000 1.179 +++ kern/kern_mutex.c 23 Feb 2007 23:05:43 -0000 @@ -91,23 +91,31 @@ #ifdef DDB static void db_show_mtx(struct lock_object *lock); #endif +static void lock_mtx(struct lock_object *lock, int how); +static void lock_spin(struct lock_object *lock, int how); +static int unlock_mtx(struct lock_object *lock); +static int unlock_spin(struct lock_object *lock); /* * Lock classes for sleep and spin mutexes. */ struct lock_class lock_class_mtx_sleep = { - "sleep mutex", - LC_SLEEPLOCK | LC_RECURSABLE, + .lc_name = "sleep mutex", + .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE, #ifdef DDB - db_show_mtx + .lc_ddb_show = db_show_mtx, #endif + .lc_lock = lock_mtx, + .lc_unlock = unlock_mtx, }; struct lock_class lock_class_mtx_spin = { - "spin mutex", - LC_SPINLOCK | LC_RECURSABLE, + .lc_name = "spin mutex", + .lc_flags = LC_SPINLOCK | LC_RECURSABLE, #ifdef DDB - db_show_mtx + .lc_ddb_show = db_show_mtx, #endif + .lc_lock = lock_spin, + .lc_unlock = unlock_spin, }; /* @@ -130,6 +138,39 @@ static inline void lock_profile_init(void) {;} #endif + +void +lock_mtx(struct lock_object *lock, int how) +{ + + mtx_lock((struct mtx *)lock); +} + +void +lock_spin(struct lock_object *lock, int how) +{ + + panic("spin locks can only use msleep_spin"); +} + +int +unlock_mtx(struct lock_object *lock) +{ + struct mtx *m; + + m = (struct mtx *)lock; + mtx_assert(m, MA_OWNED | MA_NOTRECURSED); + mtx_unlock(m); + return (0); +} + +int +unlock_spin(struct lock_object *lock) +{ + + panic("spin locks can only use msleep_spin"); +} + /* * Function versions of the inlined __mtx_* macros. These are used by * modules and can also be called from assembly language if needed. Index: kern/kern_rwlock.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_rwlock.c,v retrieving revision 1.12 diff -u -r1.12 kern_rwlock.c --- kern/kern_rwlock.c 13 Nov 2006 05:41:46 -0000 1.12 +++ kern/kern_rwlock.c 23 Feb 2007 23:05:43 -0000 @@ -52,13 +52,17 @@ static void db_show_rwlock(struct lock_object *lock); #endif +static void lock_rw(struct lock_object *lock, int how); +static int unlock_rw(struct lock_object *lock); struct lock_class lock_class_rw = { - "rw", - LC_SLEEPLOCK | LC_RECURSABLE | LC_UPGRADABLE, + .lc_name = "rw", + .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE | LC_UPGRADABLE, #ifdef DDB - db_show_rwlock + .lc_ddb_show = db_show_rwlock, #endif + .lc_lock = lock_rw, + .lc_unlock = unlock_rw, }; /* @@ -81,6 +85,34 @@ #endif void +lock_rw(struct lock_object *lock, int how) +{ + struct rwlock *rw; + + rw = (struct rwlock *)lock; + if (how) + rw_wlock(rw); + else + rw_rlock(rw); +} + +int +unlock_rw(struct lock_object *lock) +{ + struct rwlock *rw; + + rw = (struct rwlock *)lock; + rw_assert(rw, RA_LOCKED | LA_NOTRECURSED); + if (rw->rw_lock & RW_LOCK_READ) { + rw_runlock(rw); + return (0); + } else { + rw_wunlock(rw); + return (1); + } +} + +void rw_init(struct rwlock *rw, const char *name) { @@ -756,6 +788,7 @@ return; switch (what) { case RA_LOCKED: + case RA_LOCKED | LA_NOTRECURSED: case RA_RLOCKED: #ifdef WITNESS witness_assert(&rw->rw_object, what, file, line); Index: kern/kern_sx.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_sx.c,v retrieving revision 1.32 diff -u -r1.32 kern_sx.c --- kern/kern_sx.c 13 Nov 2006 05:41:46 -0000 1.32 +++ kern/kern_sx.c 23 Feb 2007 23:05:43 -0000 @@ -54,13 +54,17 @@ static void db_show_sx(struct lock_object *lock); #endif +static void lock_sx(struct lock_object *lock, int how); +static int unlock_sx(struct lock_object *lock); struct lock_class lock_class_sx = { - "sx", - LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE, + .lc_name = "sx", + .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE, #ifdef DDB - db_show_sx + .lc_ddb_show = db_show_sx, #endif + .lc_lock = lock_sx, + .lc_unlock = unlock_sx, }; #ifndef INVARIANTS @@ -68,6 +72,34 @@ #endif void +lock_sx(struct lock_object *lock, int how) +{ + struct sx *sx; + + sx = (struct sx *)lock; + if (how) + sx_xlock(sx); + else + sx_slock(sx); +} + +int +unlock_sx(struct lock_object *lock) +{ + struct sx *sx; + + sx = (struct sx *)lock; + sx_assert(sx, SX_LOCKED | LA_NOTRECURSED); + if (sx_xlocked(sx)) { + sx_xunlock(sx); + return (1); + } else { + sx_sunlock(sx); + return (0); + } +} + +void sx_sysinit(void *arg) { struct sx_args *sargs = arg; @@ -352,6 +384,7 @@ return; switch (what) { case SX_LOCKED: + case SX_LOCKED | LA_NOTRECURSED: case SX_SLOCKED: #ifdef WITNESS witness_assert(&sx->sx_object, what, file, line); Index: kern/kern_synch.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_synch.c,v retrieving revision 1.288 diff -u -r1.288 kern_synch.c --- kern/kern_synch.c 23 Feb 2007 16:22:09 -0000 1.288 +++ kern/kern_synch.c 23 Feb 2007 23:05:43 -0000 @@ -112,21 +112,22 @@ * call should be restarted if possible, and EINTR is returned if the system * call should be interrupted by the signal (return EINTR). * - * The mutex argument is unlocked before the caller is suspended, and - * re-locked before msleep returns. If priority includes the PDROP - * flag the mutex is not re-locked before returning. + * The lock argument is unlocked before the caller is suspended, and + * re-locked before lsleep returns. If priority includes the PDROP + * flag the lock is not re-locked before returning. */ int -msleep(ident, mtx, priority, wmesg, timo) +lsleep(ident, lock, priority, wmesg, timo) void *ident; - struct mtx *mtx; + struct lock_object *lock; int priority, timo; const char *wmesg; { struct thread *td; struct proc *p; - int catch, rval, flags, pri; - WITNESS_SAVE_DECL(mtx); + struct lock_class *class; + int catch, flags, lock_state, pri, rval; + WITNESS_SAVE_DECL(lock_witness); td = curthread; p = td->td_proc; @@ -134,12 +135,16 @@ if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0); #endif - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, mtx == NULL ? NULL : - &mtx->mtx_object, "Sleeping on \"%s\"", wmesg); - KASSERT(timo != 0 || mtx_owned(&Giant) || mtx != NULL || - ident == &lbolt, ("sleeping without a mutex")); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, + "Sleeping on \"%s\"", wmesg); + KASSERT(timo != 0 || mtx_owned(&Giant) || lock != NULL || + ident == &lbolt, ("sleeping without a lock")); KASSERT(p != NULL, ("msleep1")); KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep")); + if (lock != NULL) + class = LOCK_CLASS(lock); + else + class = NULL; if (cold) { /* @@ -150,8 +155,8 @@ * splx(s);" to give interrupts a chance, but there is * no way to give interrupts a chance now. */ - if (mtx != NULL && priority & PDROP) - mtx_unlock(mtx); + if (lock != NULL && priority & PDROP) + class->lc_unlock(lock); return (0); } catch = priority & PCATCH; @@ -168,20 +173,21 @@ if (ident == &pause_wchan) flags = SLEEPQ_PAUSE; else - flags = SLEEPQ_MSLEEP; + flags = SLEEPQ_SLEEP; if (catch) flags |= SLEEPQ_INTERRUPTIBLE; sleepq_lock(ident); - CTR5(KTR_PROC, "msleep: thread %p (pid %ld, %s) on %s (%p)", - (void *)td, (long)p->p_pid, p->p_comm, wmesg, ident); + CTR5(KTR_PROC, "lsleep: thread %ld (pid %ld, %s) on %s (%p)", + td->td_tid, p->p_pid, p->p_comm, wmesg, ident); DROP_GIANT(); - if (mtx != NULL) { - mtx_assert(mtx, MA_OWNED | MA_NOTRECURSED); - WITNESS_SAVE(&mtx->mtx_object, mtx); - mtx_unlock(mtx); - } + if (lock != NULL) { + WITNESS_SAVE(lock, lock_witness); + lock_state = class->lc_unlock(lock); + } else + /* GCC needs to follow the Yellow Brick Road */ + lock_state = -1; /* * We put ourselves on the sleep queue and start our timeout @@ -192,8 +198,7 @@ * stopped, then td will no longer be on a sleep queue upon * return from cursig(). */ - sleepq_add(ident, ident == &lbolt ? NULL : &mtx->mtx_object, wmesg, - flags, 0); + sleepq_add(ident, ident == &lbolt ? NULL : lock, wmesg, flags, 0); if (timo) sleepq_set_timeout(ident, timo); @@ -222,9 +227,9 @@ ktrcsw(0, 0); #endif PICKUP_GIANT(); - if (mtx != NULL && !(priority & PDROP)) { - mtx_lock(mtx); - WITNESS_RESTORE(&mtx->mtx_object, mtx); + if (lock != NULL && !(priority & PDROP)) { + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); } return (rval); } @@ -260,8 +265,8 @@ } sleepq_lock(ident); - CTR5(KTR_PROC, "msleep_spin: thread %p (pid %ld, %s) on %s (%p)", - (void *)td, (long)p->p_pid, p->p_comm, wmesg, ident); + CTR5(KTR_PROC, "msleep_spin: thread %ld (pid %ld, %s) on %s (%p)", + td->td_tid, p->p_pid, p->p_comm, wmesg, ident); DROP_GIANT(); mtx_assert(mtx, MA_OWNED | MA_NOTRECURSED); @@ -271,7 +276,7 @@ /* * We put ourselves on the sleep queue and start our timeout. */ - sleepq_add(ident, &mtx->mtx_object, wmesg, SLEEPQ_MSLEEP, 0); + sleepq_add(ident, &mtx->mtx_object, wmesg, SLEEPQ_SLEEP, 0); if (timo) sleepq_set_timeout(ident, timo); @@ -336,7 +341,7 @@ { sleepq_lock(ident); - sleepq_broadcast(ident, SLEEPQ_MSLEEP, -1, 0); + sleepq_broadcast(ident, SLEEPQ_SLEEP, -1, 0); } /* @@ -350,7 +355,7 @@ { sleepq_lock(ident); - sleepq_signal(ident, SLEEPQ_MSLEEP, -1, 0); + sleepq_signal(ident, SLEEPQ_SLEEP, -1, 0); } /* @@ -425,8 +430,8 @@ cnt.v_swtch++; PCPU_SET(switchtime, new_switchtime); PCPU_SET(switchticks, ticks); - CTR4(KTR_PROC, "mi_switch: old thread %p (kse %p, pid %ld, %s)", - (void *)td, td->td_sched, (long)p->p_pid, p->p_comm); + CTR4(KTR_PROC, "mi_switch: old thread %ld (kse %p, pid %ld, %s)", + td->td_tid, td->td_sched, p->p_pid, p->p_comm); #if (KTR_COMPILE & KTR_SCHED) != 0 if (td == PCPU_GET(idlethread)) CTR3(KTR_SCHED, "mi_switch: %p(%s) prio %d idle", @@ -454,8 +459,8 @@ CTR3(KTR_SCHED, "mi_switch: running %p(%s) prio %d", td, td->td_proc->p_comm, td->td_priority); - CTR4(KTR_PROC, "mi_switch: new thread %p (kse %p, pid %ld, %s)", - (void *)td, td->td_sched, (long)p->p_pid, p->p_comm); + CTR4(KTR_PROC, "mi_switch: new thread %ld (kse %p, pid %ld, %s)", + td->td_tid, td->td_sched, p->p_pid, p->p_comm); /* * If the last thread was exiting, finish cleaning it up. Index: sys/condvar.h =================================================================== RCS file: /usr/cvs/src/sys/sys/condvar.h,v retrieving revision 1.13 diff -u -r1.13 condvar.h --- sys/condvar.h 12 Dec 2005 00:02:22 -0000 1.13 +++ sys/condvar.h 23 Feb 2007 23:05:43 -0000 @@ -32,7 +32,7 @@ #ifndef LOCORE #include -struct mtx; +struct lock_object; struct thread; TAILQ_HEAD(cv_waitq, thread); @@ -52,15 +52,49 @@ void cv_init(struct cv *cvp, const char *desc); void cv_destroy(struct cv *cvp); -void cv_wait(struct cv *cvp, struct mtx *mp); -void cv_wait_unlock(struct cv *cvp, struct mtx *mp); -int cv_wait_sig(struct cv *cvp, struct mtx *mp); -int cv_timedwait(struct cv *cvp, struct mtx *mp, int timo); -int cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo); +void _cv_wait(struct cv *cvp, struct lock_object *lock); +void _cv_wait_unlock(struct cv *cvp, struct lock_object *lock); +int _cv_wait_sig(struct cv *cvp, struct lock_object *lock); +int _cv_timedwait(struct cv *cvp, struct lock_object *lock, int timo); +int _cv_timedwait_sig(struct cv *cvp, struct lock_object *lock, int timo); void cv_signal(struct cv *cvp); void cv_broadcastpri(struct cv *cvp, int pri); +/* By default condition variables use mutexes for the interlock. */ +#define cv_wait(cvp, mtx) \ + _cv_wait((cvp), &(mtx)->mtx_object) +#define cv_wait_unlock(cvp, mtx) \ + _cv_wait_unlock((cvp), &(mtx)->mtx_object) +#define cv_wait_sig(cvp, mtx) \ + _cv_wait_sig((cvp), &(mtx)->mtx_object) +#define cv_timedwait(cvp, mtx, timo) \ + _cv_timedwait((cvp), &(mtx)->mtx_object, (timo)) +#define cv_timedwait_sig(cvp, mtx, timo) \ + _cv_timedwait_sig((cvp), &(mtx)->mtx_object, (timo)) + +/* The _rw variants support rw locks, and the _sx variants support sx locks. */ +#define cv_wait_rw(cvp, rw) \ + _cv_wait((cvp), &(rw)->rw_object) +#define cv_wait_unlock_rw(cvp, rw) \ + _cv_wait_unlock((cvp), &(rw)->rw_object) +#define cv_wait_sig_rw(cvp, rw) \ + _cv_wait_sig((cvp), &(rw)->rw_object) +#define cv_timedwait_rw(cvp, rw, timo) \ + _cv_timedwait((cvp), &(rw)->rw_object, (timo)) +#define cv_timedwait_sig_rw(cvp, rw, timo) \ + _cv_timedwait_sig((cvp), &(rw)->rw_object, (timo)) +#define cv_wait_sx(cvp, sx) \ + _cv_wait((cvp), &(sx)->sx_object) +#define cv_wait_unlock_sx(cvp, sx) \ + _cv_wait_unlock((cvp), &(sx)->sx_object) +#define cv_wait_sig_sx(cvp, sx) \ + _cv_wait_sig((cvp), &(sx)->sx_object) +#define cv_timedwait_sx(cvp, sx, timo) \ + _cv_timedwait((cvp), &(sx)->sx_object, (timo)) +#define cv_timedwait_sig_sx(cvp, sx, timo) \ + _cv_timedwait_sig((cvp), &(sx)->sx_object, (timo)) + #define cv_broadcast(cvp) cv_broadcastpri(cvp, -1) #define cv_wmesg(cvp) ((cvp)->cv_description) Index: sys/lock.h =================================================================== RCS file: /usr/cvs/src/sys/sys/lock.h,v retrieving revision 1.63 diff -u -r1.63 lock.h --- sys/lock.h 3 Feb 2007 07:49:20 -0000 1.63 +++ sys/lock.h 23 Feb 2007 23:05:43 -0000 @@ -45,12 +45,21 @@ * an error to perform any type of context switch while holding a spin lock. * Also, for an individual lock to be recursable, its class must allow * recursion and the lock itself must explicitly allow recursion. + * + * The 'lc_ddb_show' function pointer is used to dump class-specific + * data for the 'show lock' DDB command. The 'lc_lock' and + * 'lc_unlock' function pointers are used in lsleep(9) and cv_wait(9) + * to lock and unlock locks while blocking on a sleep queue. The + * return value of 'lc_unlock' will be passed to 'lc_lock' on resume + * to allow communication of state between the two routines. */ struct lock_class { const char *lc_name; u_int lc_flags; void (*lc_ddb_show)(struct lock_object *lock); + void (*lc_lock)(struct lock_object *lock, int how); + int (*lc_unlock)(struct lock_object *lock); }; #define LC_SLEEPLOCK 0x00000001 /* Sleep lock. */ Index: sys/sleepqueue.h =================================================================== RCS file: /usr/cvs/src/sys/sys/sleepqueue.h,v retrieving revision 1.10 diff -u -r1.10 sleepqueue.h --- sys/sleepqueue.h 23 Feb 2007 16:22:09 -0000 1.10 +++ sys/sleepqueue.h 23 Feb 2007 23:05:43 -0000 @@ -82,7 +82,7 @@ #ifdef _KERNEL #define SLEEPQ_TYPE 0x0ff /* Mask of sleep queue types. */ -#define SLEEPQ_MSLEEP 0x00 /* Used by msleep/wakeup. */ +#define SLEEPQ_SLEEP 0x00 /* Used by sleep/wakeup. */ #define SLEEPQ_CONDVAR 0x01 /* Used for a cv. */ #define SLEEPQ_PAUSE 0x02 /* Used by pause. */ #define SLEEPQ_INTERRUPTIBLE 0x100 /* Sleep is interruptible. */ Index: sys/systm.h =================================================================== RCS file: /usr/cvs/src/sys/sys/systm.h,v retrieving revision 1.250 diff -u -r1.250 systm.h --- sys/systm.h 23 Feb 2007 16:22:09 -0000 1.250 +++ sys/systm.h 23 Feb 2007 23:05:43 -0000 @@ -116,6 +116,7 @@ * General function declarations. */ +struct lock_object; struct malloc_type; struct mtx; struct proc; @@ -307,11 +308,21 @@ * Common `proc' functions are declared here so that proc.h can be included * less often. */ -int msleep(void *chan, struct mtx *mtx, int pri, const char *wmesg, - int timo); -int msleep_spin(void *chan, struct mtx *mtx, const char *wmesg, int timo); +int lsleep(void *chan, struct lock_object *lock, int pri, const char *wmesg, + int timo) __nonnull(1); +#define msleep(chan, mtx, pri, wmesg, timo) \ + lsleep((chan), &(mtx)->mtx_object, (pri), (wmesg), (timo)) +#define mtx_sleep(chan, mtx, pri, wmesg, timo) \ + lsleep((chan), &(mtx)->mtx_object, (pri), (wmesg), (timo)) +#define rw_sleep(chan, rw, pri, wmesg, timo) \ + lsleep((chan), &(rw)->rw_object, (pri), (wmesg), (timo)) +#define sx_sleep(chan, sx, pri, wmesg, timo) \ + lsleep((chan), &(sx)->sx_object, (pri), (wmesg), (timo)) +#define tsleep(chan, pri, wmesg, timo) \ + lsleep((chan), NULL, (pri), (wmesg), (timo)) +int msleep_spin(void *chan, struct mtx *mtx, const char *wmesg, int timo) + __nonnull(1); int pause(const char *wmesg, int timo); -#define tsleep(chan, pri, wmesg, timo) msleep(chan, NULL, pri, wmesg, timo) void wakeup(void *chan) __nonnull(1); void wakeup_one(void *chan) __nonnull(1);