svn commit: r186549 - in projects/releng_6_xen/sys: kern sys

Kip Macy kmacy at FreeBSD.org
Sun Dec 28 16:55:34 PST 2008


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);


More information about the svn-src-projects mailing list