Date: Thu, 4 Dec 2008 20:03:15 +0000 (UTC) From: Kip Macy <kmacy@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r185618 - in projects/release_6_3_xen/sys: kern sys Message-ID: <200812042003.mB4K3FD7032837@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kmacy Date: Thu Dec 4 20:03:15 2008 New Revision: 185618 URL: http://svn.freebsd.org/changeset/base/185618 Log: integrate generic sleepq_add and _sleep in order to implement sx_sleep Modified: projects/release_6_3_xen/sys/kern/init_main.c projects/release_6_3_xen/sys/kern/kern_condvar.c projects/release_6_3_xen/sys/kern/kern_lock.c projects/release_6_3_xen/sys/kern/kern_mutex.c projects/release_6_3_xen/sys/kern/kern_rwlock.c projects/release_6_3_xen/sys/kern/kern_sx.c projects/release_6_3_xen/sys/kern/kern_synch.c projects/release_6_3_xen/sys/kern/subr_sleepqueue.c projects/release_6_3_xen/sys/sys/lock.h projects/release_6_3_xen/sys/sys/sleepqueue.h projects/release_6_3_xen/sys/sys/systm.h Modified: projects/release_6_3_xen/sys/kern/init_main.c ============================================================================== Modified: projects/release_6_3_xen/sys/kern/kern_condvar.c ============================================================================== --- projects/release_6_3_xen/sys/kern/kern_condvar.c Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/kern/kern_condvar.c Thu Dec 4 20:03:15 2008 (r185618) @@ -124,7 +124,7 @@ cv_wait(struct cv *cvp, struct mtx *mp) DROP_GIANT(); mtx_unlock(mp); - sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR, 0); + sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR, 0); sleepq_wait(cvp); #ifdef KTRACE @@ -177,7 +177,7 @@ cv_wait_sig(struct cv *cvp, struct mtx * DROP_GIANT(); mtx_unlock(mp); - sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR | + sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR | SLEEPQ_INTERRUPTIBLE, 0); rval = sleepq_wait_sig(cvp); @@ -231,7 +231,7 @@ cv_timedwait(struct cv *cvp, struct mtx DROP_GIANT(); mtx_unlock(mp); - sleepq_add(cvp, mp, 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); @@ -288,7 +288,7 @@ cv_timedwait_sig(struct cv *cvp, struct DROP_GIANT(); mtx_unlock(mp); - sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR | + sleepq_add(cvp, &mp->mtx_object, cvp->cv_description, SLEEPQ_CONDVAR | SLEEPQ_INTERRUPTIBLE, 0); sleepq_set_timeout(cvp, timo); rval = sleepq_timedwait_sig(cvp); Modified: projects/release_6_3_xen/sys/kern/kern_lock.c ============================================================================== --- projects/release_6_3_xen/sys/kern/kern_lock.c Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/kern/kern_lock.c Thu Dec 4 20:03:15 2008 (r185618) @@ -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/release_6_3_xen/sys/kern/kern_mutex.c ============================================================================== --- projects/release_6_3_xen/sys/kern/kern_mutex.c Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/kern/kern_mutex.c Thu Dec 4 20:03:15 2008 (r185618) @@ -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/release_6_3_xen/sys/kern/kern_rwlock.c ============================================================================== --- projects/release_6_3_xen/sys/kern/kern_rwlock.c Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/kern/kern_rwlock.c Thu Dec 4 20:03:15 2008 (r185618) @@ -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/release_6_3_xen/sys/kern/kern_sx.c ============================================================================== --- projects/release_6_3_xen/sys/kern/kern_sx.c Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/kern/kern_sx.c Thu Dec 4 20:03:15 2008 (r185618) @@ -107,12 +107,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 @@ -120,6 +125,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; Modified: projects/release_6_3_xen/sys/kern/kern_synch.c ============================================================================== --- projects/release_6_3_xen/sys/kern/kern_synch.c Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/kern/kern_synch.c Thu Dec 4 20:03:15 2008 (r185618) @@ -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; @@ -194,7 +332,7 @@ msleep(ident, mtx, priority, wmesg, timo * stopped, then td will no longer be on a sleep queue upon * return from cursig(). */ - sleepq_add(ident, mtx, wmesg, flags, 0); + sleepq_add(ident, &mtx->mtx_object, wmesg, flags, 0); if (timo) sleepq_set_timeout(ident, timo); @@ -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, 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/release_6_3_xen/sys/kern/subr_sleepqueue.c ============================================================================== --- projects/release_6_3_xen/sys/kern/subr_sleepqueue.c Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/kern/subr_sleepqueue.c Thu Dec 4 20:03:15 2008 (r185618) @@ -121,7 +121,7 @@ struct sleepqueue { void *sq_wchan; /* (c) Wait channel. */ #ifdef INVARIANTS int sq_type; /* (c) Queue type. */ - struct mtx *sq_lock; /* (c) Associated lock. */ + struct lock_object *sq_lock; /* (c) Associated lock. */ #endif }; @@ -270,7 +270,7 @@ sleepq_release(void *wchan) * woken up. */ void -sleepq_add(void *wchan, struct mtx *lock, const char *wmesg, int flags, +sleepq_add(void *wchan, struct lock_object *lock, const char *wmesg, int flags, int queue) { struct sleepqueue_chain *sc; @@ -947,7 +947,7 @@ found: #ifdef INVARIANTS db_printf("Queue type: %d\n", sq->sq_type); if (sq->sq_lock) { - lock = &sq->sq_lock->mtx_object; + lock = sq->sq_lock; db_printf("Associated Interlock: %p - (%s) %s\n", lock, LOCK_CLASS(lock)->lc_name, lock->lo_name); } Modified: projects/release_6_3_xen/sys/sys/lock.h ============================================================================== --- projects/release_6_3_xen/sys/sys/lock.h Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/sys/lock.h Thu Dec 4 20:03:15 2008 (r185618) @@ -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/release_6_3_xen/sys/sys/sleepqueue.h ============================================================================== --- projects/release_6_3_xen/sys/sys/sleepqueue.h Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/sys/sleepqueue.h Thu Dec 4 20:03:15 2008 (r185618) @@ -83,14 +83,16 @@ 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 mtx *, const char *, int, int); +void sleepq_add(void *, struct lock_object *, const char *, int, int); struct sleepqueue *sleepq_alloc(void); void sleepq_broadcast(void *, int, int, int); void sleepq_free(struct sleepqueue *); Modified: projects/release_6_3_xen/sys/sys/systm.h ============================================================================== --- projects/release_6_3_xen/sys/sys/systm.h Thu Dec 4 18:48:08 2008 (r185617) +++ projects/release_6_3_xen/sys/sys/systm.h Thu Dec 4 20:03:15 2008 (r185618) @@ -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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812042003.mB4K3FD7032837>