svn commit: r185618 - in projects/release_6_3_xen/sys: kern sys
Kip Macy
kmacy at FreeBSD.org
Thu Dec 4 12:03:16 PST 2008
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);
More information about the svn-src-projects
mailing list