Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Dec 2005 16:17:43 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 88838 for review
Message-ID:  <200512281617.jBSGHhS2048563@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=88838

Change 88838 by jhb@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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200512281617.jBSGHhS2048563>