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>