Date: Mon, 29 Dec 2008 00:55:33 +0000 (UTC) From: Kip Macy <kmacy@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r186549 - in projects/releng_6_xen/sys: kern sys Message-ID: <200812290055.mBT0tXJu032690@svn.freebsd.org>
index | next in thread | raw e-mail
Author: kmacy Date: Mon Dec 29 00:55:33 2008 New Revision: 186549 URL: http://svn.freebsd.org/changeset/base/186549 Log: Log: integrate generic sleepq_add and _sleep Modified: projects/releng_6_xen/sys/kern/kern_condvar.c projects/releng_6_xen/sys/kern/kern_lock.c projects/releng_6_xen/sys/kern/kern_mutex.c projects/releng_6_xen/sys/kern/kern_rwlock.c projects/releng_6_xen/sys/kern/kern_sx.c projects/releng_6_xen/sys/kern/kern_synch.c projects/releng_6_xen/sys/kern/kern_timeout.c projects/releng_6_xen/sys/sys/lock.h projects/releng_6_xen/sys/sys/sleepqueue.h projects/releng_6_xen/sys/sys/sx.h projects/releng_6_xen/sys/sys/systm.h Modified: projects/releng_6_xen/sys/kern/kern_condvar.c ============================================================================== --- projects/releng_6_xen/sys/kern/kern_condvar.c Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/kern/kern_condvar.c Mon Dec 29 00:55:33 2008 (r186549) @@ -124,8 +124,7 @@ cv_wait(struct cv *cvp, struct mtx *mp) DROP_GIANT(); mtx_unlock(mp); - sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR, - 0); + sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR, 0); sleepq_wait(cvp); #ifdef KTRACE @@ -232,8 +231,7 @@ cv_timedwait(struct cv *cvp, struct mtx DROP_GIANT(); mtx_unlock(mp); - sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR, - 0); + sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR, 0); sleepq_set_timeout(cvp, timo); rval = sleepq_timedwait(cvp); Modified: projects/releng_6_xen/sys/kern/kern_lock.c ============================================================================== --- projects/releng_6_xen/sys/kern/kern_lock.c Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/kern/kern_lock.c Mon Dec 29 00:55:33 2008 (r186549) @@ -62,6 +62,43 @@ __FBSDID("$FreeBSD$"); #include <ddb/ddb.h> #endif + +#ifdef DDB +#include <ddb/ddb.h> +static void db_show_lockmgr(struct lock_object *lock); +#endif +static void lock_lockmgr(struct lock_object *lock, int how); +static int unlock_lockmgr(struct lock_object *lock); + +struct lock_class lock_class_lockmgr = { + .lc_name = "lockmgr", + .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE, +#ifdef DDB + .lc_ddb_show = db_show_lockmgr, +#endif + .lc_lock = lock_lockmgr, + .lc_unlock = unlock_lockmgr, +}; + +/* + * Locking primitives implementation. + * Locks provide shared/exclusive sychronization. + */ + +void +lock_lockmgr(struct lock_object *lock, int how) +{ + + panic("lockmgr locks do not support sleep interlocking"); +} + +int +unlock_lockmgr(struct lock_object *lock) +{ + + panic("lockmgr locks do not support sleep interlocking"); +} + /* * Locking primitives implementation. * Locks provide shared/exclusive sychronization. @@ -639,14 +676,13 @@ ok: return (1); } -DB_SHOW_COMMAND(lockmgr, db_show_lockmgr) +void +db_show_lockmgr(struct lock_object *lock) { struct thread *td; struct lock *lkp; - if (!have_addr) - return; - lkp = (struct lock *)addr; + lkp = (struct lock *)lock; db_printf("lock type: %s\n", lkp->lk_wmesg); db_printf("state: "); Modified: projects/releng_6_xen/sys/kern/kern_mutex.c ============================================================================== --- projects/releng_6_xen/sys/kern/kern_mutex.c Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/kern/kern_mutex.c Mon Dec 29 00:55:33 2008 (r186549) @@ -92,25 +92,66 @@ __FBSDID("$FreeBSD$"); #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, }; +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"); +} + /* * System-wide mutexes */ Modified: projects/releng_6_xen/sys/kern/kern_rwlock.c ============================================================================== --- projects/releng_6_xen/sys/kern/kern_rwlock.c Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/kern/kern_rwlock.c Mon Dec 29 00:55:33 2008 (r186549) @@ -60,13 +60,19 @@ CTASSERT((RW_RECURSE & LO_CLASSFLAGS) == 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 = { .lc_name = "rw", .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE | LC_UPGRADABLE, #ifdef DDB .lc_ddb_show = db_show_rwlock, #endif + .lc_lock = lock_rw, + .lc_unlock = unlock_rw }; + /* * Return a pointer to the owning thread if the lock is write-locked or @@ -99,6 +105,34 @@ struct lock_class lock_class_rw = { #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_flags(struct rwlock *rw, const char *name, int opts) { int flags; Modified: projects/releng_6_xen/sys/kern/kern_sx.c ============================================================================== --- projects/releng_6_xen/sys/kern/kern_sx.c Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/kern/kern_sx.c Mon Dec 29 00:55:33 2008 (r186549) @@ -108,12 +108,17 @@ CTASSERT(((SX_ADAPTIVESPIN | SX_RECURSE) 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 = { .lc_name = "sx", .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE, #ifdef DDB .lc_ddb_show = db_show_sx, #endif + .lc_lock = lock_sx, + .lc_unlock = unlock_sx, }; #ifndef INVARIANTS @@ -121,6 +126,34 @@ struct lock_class lock_class_sx = { #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, SA_LOCKED | SA_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; @@ -845,6 +878,7 @@ _sx_sunlock_hard(struct sx *sx, const ch } } +#if 0 /* * Atomically drop an sx lock while going to sleep. This is just a hack * for 6.x. In 7.0 and later this is done more cleanly. @@ -961,6 +995,7 @@ sx_sleep(void *ident, struct sx *sx, int } return (rval); } +#endif #ifdef INVARIANT_SUPPORT #ifndef INVARIANTS Modified: projects/releng_6_xen/sys/kern/kern_synch.c ============================================================================== --- projects/releng_6_xen/sys/kern/kern_synch.c Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/kern/kern_synch.c Mon Dec 29 00:55:33 2008 (r186549) @@ -75,6 +75,7 @@ SYSINIT(synch_setup, SI_SUB_KICK_SCHEDUL int hogticks; int lbolt; +static int pause_wchan; static struct callout loadav_callout; static struct callout lbolt_callout; @@ -106,6 +107,143 @@ sleepinit(void) init_sleepqueues(); } + +/* + * General sleep call. Suspends the current thread until a wakeup is + * performed on the specified identifier. The thread will then be made + * runnable with the specified priority. Sleeps at most timo/hz seconds + * (0 means no timeout). If pri includes PCATCH flag, signals are checked + * before and after sleeping, else signals are not checked. Returns 0 if + * awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a + * signal needs to be delivered, ERESTART is returned if the current system + * call should be restarted if possible, and EINTR is returned if the system + * call should be interrupted by the signal (return EINTR). + * + * The lock argument is unlocked before the caller is suspended, and + * re-locked before _sleep() returns. If priority includes the PDROP + * flag the lock is not re-locked before returning. + */ +int +_sleep(void *ident, struct lock_object *lock, int priority, + const char *wmesg, int timo) +{ + struct thread *td; + struct proc *p; + struct lock_class *class; + int catch, flags, lock_state, pri, rval; + WITNESS_SAVE_DECL(lock_witness); + + td = curthread; + p = td->td_proc; +#ifdef KTRACE + if (KTRPOINT(td, KTR_CSW)) + ktrcsw(1, 0); +#endif + 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) { + /* + * During autoconfiguration, just return; + * don't run any other threads or panic below, + * in case this is the idle thread and already asleep. + * XXX: this used to do "s = splhigh(); splx(safepri); + * splx(s);" to give interrupts a chance, but there is + * no way to give interrupts a chance now. + */ + if (lock != NULL && priority & PDROP) + class->lc_unlock(lock); + return (0); + } + catch = priority & PCATCH; + rval = 0; + + /* + * If we are already on a sleep queue, then remove us from that + * sleep queue first. We have to do this to handle recursive + * sleeps. + */ + if (TD_ON_SLEEPQ(td)) + sleepq_remove(td, td->td_wchan); + + if (ident == &pause_wchan) + flags = SLEEPQ_PAUSE; + else + flags = SLEEPQ_SLEEP; + if (catch) + flags |= SLEEPQ_INTERRUPTIBLE; + + sleepq_lock(ident); + CTR5(KTR_PROC, "sleep: thread %ld (pid %ld, %s) on %s (%p)", + td->td_tid, p->p_pid, p->p_comm, wmesg, ident); + + DROP_GIANT(); + if (lock != NULL && !(class->lc_flags & LC_SLEEPABLE)) { + 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 + * before calling thread_suspend_check, as we could stop there, + * and a wakeup or a SIGCONT (or both) could occur while we were + * stopped without resuming us. Thus, we must be ready for sleep + * when cursig() is called. If the wakeup happens while we're + * stopped, then td will no longer be on a sleep queue upon + * return from cursig(). + */ + sleepq_add(ident, ident == &lbolt ? NULL : lock, wmesg, flags, 0); + if (timo) + sleepq_set_timeout(ident, timo); + if (lock != NULL && class->lc_flags & LC_SLEEPABLE) { + sleepq_release(ident); + WITNESS_SAVE(lock, lock_witness); + lock_state = class->lc_unlock(lock); + sleepq_lock(ident); + } + + /* + * Adjust this thread's priority, if necessary. + */ + pri = priority & PRIMASK; + if (pri != 0 && pri != td->td_priority) { + mtx_lock_spin(&sched_lock); + sched_prio(td, pri); + mtx_unlock_spin(&sched_lock); + } + + if (timo && catch) + rval = sleepq_timedwait_sig(ident); + else if (timo) + rval = sleepq_timedwait(ident); + else if (catch) + rval = sleepq_wait_sig(ident); + else { + sleepq_wait(ident); + rval = 0; + } +#ifdef KTRACE + if (KTRPOINT(td, KTR_CSW)) + ktrcsw(0, 0); +#endif + PICKUP_GIANT(); + if (lock != NULL && !(priority & PDROP)) { + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); + } + return (rval); +} + /* * General sleep call. Suspends the current process until a wakeup is * performed on the specified identifier. The process will then be made @@ -170,7 +308,7 @@ msleep(ident, mtx, priority, wmesg, timo if (TD_ON_SLEEPQ(td)) sleepq_remove(td, td->td_wchan); - flags = SLEEPQ_MSLEEP; + flags = SLEEPQ_SLEEP; if (catch) flags |= SLEEPQ_INTERRUPTIBLE; @@ -271,7 +409,7 @@ msleep_spin(ident, mtx, wmesg, timo) /* * 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); @@ -320,7 +458,7 @@ wakeup(ident) { sleepq_lock(ident); - sleepq_broadcast(ident, SLEEPQ_MSLEEP, -1, 0); + sleepq_broadcast(ident, SLEEPQ_SLEEP, -1, 0); } /* @@ -334,7 +472,7 @@ wakeup_one(ident) { sleepq_lock(ident); - sleepq_signal(ident, SLEEPQ_MSLEEP, -1, 0); + sleepq_signal(ident, SLEEPQ_SLEEP, -1, 0); } /* Modified: projects/releng_6_xen/sys/kern/kern_timeout.c ============================================================================== --- projects/releng_6_xen/sys/kern/kern_timeout.c Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/kern/kern_timeout.c Mon Dec 29 00:55:33 2008 (r186549) @@ -557,7 +557,7 @@ again: mtx_unlock_spin(&callout_lock); sleepq_add(&callout_wait, &callout_lock.mtx_object, "codrain", - SLEEPQ_MSLEEP, 0); + SLEEPQ_SLEEP, 0); sleepq_wait(&callout_wait); sq_locked = 0; Modified: projects/releng_6_xen/sys/sys/lock.h ============================================================================== --- projects/releng_6_xen/sys/sys/lock.h Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/sys/lock.h Mon Dec 29 00:55:33 2008 (r186549) @@ -51,6 +51,8 @@ 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. */ Modified: projects/releng_6_xen/sys/sys/sleepqueue.h ============================================================================== --- projects/releng_6_xen/sys/sys/sleepqueue.h Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/sys/sleepqueue.h Mon Dec 29 00:55:33 2008 (r186549) @@ -83,11 +83,13 @@ struct thread; #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 msleep/wakeup. */ #define SLEEPQ_CONDVAR 0x01 /* Used for a cv. */ +#define SLEEPQ_PAUSE 0x02 /* Used by pause. */ #define SLEEPQ_SX 0x03 /* Used by an sx lock. */ #define SLEEPQ_INTERRUPTIBLE 0x100 /* Sleep is interruptible. */ + void init_sleepqueues(void); void sleepq_abort(struct thread *td, int intrval); void sleepq_add(void *, struct lock_object *, const char *, int, int); Modified: projects/releng_6_xen/sys/sys/sx.h ============================================================================== --- projects/releng_6_xen/sys/sys/sx.h Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/sys/sx.h Mon Dec 29 00:55:33 2008 (r186549) @@ -257,6 +257,9 @@ __sx_sunlock(struct sx *sx, const char * sx_sunlock(sx); \ } while (0) +#define sx_sleep(chan, sx, pri, wmesg, timo) \ + _sleep((chan), &(sx)->lock_object, (pri), (wmesg), (timo)) + /* * Options passed to sx_init_flags(). */ Modified: projects/releng_6_xen/sys/sys/systm.h ============================================================================== --- projects/releng_6_xen/sys/sys/systm.h Sun Dec 28 23:50:05 2008 (r186548) +++ projects/releng_6_xen/sys/sys/systm.h Mon Dec 29 00:55:33 2008 (r186549) @@ -113,6 +113,7 @@ extern char **kenvp; * General function declarations. */ +struct lock_object; struct clockframe; struct malloc_type; struct mtx; @@ -295,6 +296,8 @@ static __inline void splx(intrmask_t ip * Common `proc' functions are declared here so that proc.h can be included * less often. */ +int _sleep(void *chan, struct lock_object *lock, int pri, const char *wmesg, + int timo) __nonnull(1); 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);help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812290055.mBT0tXJu032690>
