PERFORCE change 88838 for review
John Baldwin
jhb at FreeBSD.org
Wed Dec 28 08:17:45 PST 2005
http://perforce.freebsd.org/chv.cgi?CH=88838
Change 88838 by jhb at jhb_slimer on 2005/12/28 16:17:15
Implement msleep_spin() which is a stripped down version of msleep()
(no PCATCH or PDROP and no priority at all) that works with spin
mutexes. Add a test event to crash.ko as well.
Affected files ...
.. //depot/projects/smpng/sys/kern/kern_synch.c#93 edit
.. //depot/projects/smpng/sys/modules/crash/crash.c#26 edit
.. //depot/projects/smpng/sys/sys/systm.h#68 edit
Differences ...
==== //depot/projects/smpng/sys/kern/kern_synch.c#93 (text+ko) ====
@@ -241,6 +241,88 @@
return (rval);
}
+int
+msleep_spin(ident, mtx, wmesg, timo)
+ void *ident;
+ struct mtx *mtx;
+ const char *wmesg;
+ int timo;
+{
+ struct thread *td;
+ struct proc *p;
+ int rval;
+ WITNESS_SAVE_DECL(mtx);
+
+ td = curthread;
+ p = td->td_proc;
+ KASSERT(mtx != NULL, ("sleeping without a mutex"));
+ KASSERT(p != NULL, ("msleep1"));
+ KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep"));
+
+ 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.
+ */
+ return (0);
+ }
+
+ 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);
+
+ DROP_GIANT();
+ mtx_assert(mtx, MA_OWNED | MA_NOTRECURSED);
+ WITNESS_SAVE(&mtx->mtx_object, mtx);
+ mtx_unlock_spin(mtx);
+
+ /*
+ * We put ourselves on the sleep queue and start our timeout.
+ */
+ sleepq_add(ident, mtx, wmesg, SLEEPQ_MSLEEP);
+ if (timo)
+ sleepq_set_timeout(ident, timo);
+
+ /*
+ * Can't call ktrace with any spin locks held so it can lock the
+ * ktrace_mtx lock, and WITNESS_WARN considers it an error to hold
+ * any spin lock. Thus, we have to drop the sleepq spin lock while
+ * we handle those requests. This is safe since we have placed our
+ * thread on the sleep queue already.
+ */
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_CSW)) {
+ sleepq_release(ident);
+ ktrcsw(1, 0);
+ sleepq_lock(ident);
+ }
+#endif
+#ifdef WITNESS
+ sleepq_release(ident);
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "Sleeping on \"%s\"",
+ wmesg);
+ sleepq_lock(ident);
+#endif
+ if (timo)
+ rval = sleepq_timedwait(ident);
+ else {
+ sleepq_wait(ident);
+ rval = 0;
+ }
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_CSW))
+ ktrcsw(0, 0);
+#endif
+ PICKUP_GIANT();
+ mtx_lock_spin(mtx);
+ WITNESS_RESTORE(&mtx->mtx_object, mtx);
+ return (rval);
+}
+
/*
* Make all threads sleeping on the specified identifier runnable.
*/
==== //depot/projects/smpng/sys/modules/crash/crash.c#26 (text+ko) ====
@@ -84,6 +84,31 @@
/* Events. */
static void
+msleep_spin_callout(void *dummy)
+{
+
+ wakeup(&test1_mtx);
+}
+
+static void
+msleep_spin_test(void)
+{
+ int error;
+
+ bzero(&test1_mtx, sizeof(test1_mtx));
+ mtx_init(&test1_mtx, "test1", NULL, MTX_SPIN);
+ error = msleep_spin(&test1_mtx, &test1_mtx, "spincr", 5);
+ printf("msleep_spin returned %d\n", error);
+ kdb_enter("timed out");
+ timeout(msleep_spin_callout, NULL, 5);
+ error = msleep_spin(&test1_mtx, &test1_mtx, "spincr2", 0);
+ printf("msleep_spin returned %d\n", error);
+ kdb_enter("awoke from spin");
+ mtx_destroy(&test1_mtx);
+}
+CRASH_EVENT("msleep_spin", msleep_spin_test);
+
+static void
ddblock_test(void)
{
==== //depot/projects/smpng/sys/sys/systm.h#68 (text+ko) ====
@@ -295,6 +295,7 @@
*/
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);
#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);
More information about the p4-projects
mailing list