PERFORCE change 83036 for review
John Baldwin
jhb at FreeBSD.org
Fri Sep 2 19:39:36 GMT 2005
http://perforce.freebsd.org/chv.cgi?CH=83036
Change 83036 by jhb at jhb_slimer on 2005/09/02 19:39:25
Add a simple API to indicate that a thread is not allowed to sleep
and use it in place of the g_xdown and g_xup mutexes. Also, use
it in the ithreads around the handlers. Also, add a test for it to
the crash module.
Affected files ...
.. //depot/projects/smpng/sys/geom/geom_io.c#37 edit
.. //depot/projects/smpng/sys/kern/kern_intr.c#69 edit
.. //depot/projects/smpng/sys/kern/subr_sleepqueue.c#17 edit
.. //depot/projects/smpng/sys/modules/crash/crash.c#17 edit
.. //depot/projects/smpng/sys/notes#53 edit
.. //depot/projects/smpng/sys/sys/proc.h#148 edit
Differences ...
==== //depot/projects/smpng/sys/geom/geom_io.c#37 (text+ko) ====
@@ -42,6 +42,7 @@
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/ktr.h>
+#include <sys/proc.h>
#include <sys/errno.h>
#include <geom/geom.h>
@@ -364,12 +365,6 @@
struct bio *bp;
off_t excess;
int error;
-#ifdef WITNESS
- struct mtx mymutex;
-
- bzero(&mymutex, sizeof mymutex);
- mtx_init(&mymutex, "g_xdown", NULL, MTX_DEF);
-#endif
for(;;) {
g_bioq_lock(&g_bio_run_down);
@@ -425,16 +420,12 @@
default:
break;
}
-#ifdef WITNESS
- mtx_lock(&mymutex);
-#endif
+ THREAD_NO_SLEEPING();
CTR4(KTR_GEOM, "g_down starting bp %p provider %s off %ld "
"len %ld", bp, bp->bio_to->name, bp->bio_offset,
bp->bio_length);
bp->bio_to->geom->start(bp);
-#ifdef WITNESS
- mtx_unlock(&mymutex);
-#endif
+ THREAD_SLEEPING_OK();
}
}
@@ -462,40 +453,26 @@
g_io_schedule_up(struct thread *tp __unused)
{
struct bio *bp;
-#ifdef WITNESS
- struct mtx mymutex;
-
- bzero(&mymutex, sizeof mymutex);
- mtx_init(&mymutex, "g_xup", NULL, MTX_DEF);
-#endif
for(;;) {
g_bioq_lock(&g_bio_run_up);
bp = g_bioq_first(&g_bio_run_task);
if (bp != NULL) {
g_bioq_unlock(&g_bio_run_up);
-#ifdef WITNESS
- mtx_lock(&mymutex);
-#endif
+ THREAD_NO_SLEEPING();
CTR1(KTR_GEOM, "g_up processing task bp %p", bp);
bp->bio_task(bp->bio_task_arg);
-#ifdef WITNESS
- mtx_unlock(&mymutex);
-#endif
+ THREAD_SLEEPING_OK();
continue;
}
bp = g_bioq_first(&g_bio_run_up);
if (bp != NULL) {
g_bioq_unlock(&g_bio_run_up);
-#ifdef WITNESS
- mtx_lock(&mymutex);
-#endif
+ THREAD_NO_SLEEPING();
CTR4(KTR_GEOM, "g_up biodone bp %p provider %s off "
"%ld len %ld", bp, bp->bio_to->name,
bp->bio_offset, bp->bio_length);
biodone(bp);
-#ifdef WITNESS
- mtx_unlock(&mymutex);
-#endif
+ THREAD_SLEEPING_OK();
continue;
}
CTR0(KTR_GEOM, "g_up going to sleep");
==== //depot/projects/smpng/sys/kern/kern_intr.c#69 (text+ko) ====
@@ -521,6 +521,7 @@
* another pass.
*/
atomic_store_rel_int(&ithd->it_need, 0);
+ THREAD_NO_SLEEPING();
restart:
TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) {
if (ithd->it_flags & IT_SOFT && !ih->ih_need)
@@ -546,6 +547,7 @@
if ((ih->ih_flags & IH_MPSAFE) == 0)
mtx_unlock(&Giant);
}
+ THREAD_SLEEPING_OK();
/*
* Interrupt storm handling:
==== //depot/projects/smpng/sys/kern/subr_sleepqueue.c#17 (text+ko) ====
@@ -269,6 +269,10 @@
MPASS(td->td_sleepqueue != NULL);
MPASS(wchan != NULL);
+ /* If this thread is not allowed to sleep, die a horrible death. */
+ KASSERT(!(td->td_pflags & TDP_NOSLEEPING),
+ ("trying to sleep while sleeping is prohibited"));
+
/* Look up the sleep queue associated with the wait channel 'wchan'. */
sq = sleepq_lookup(wchan);
==== //depot/projects/smpng/sys/modules/crash/crash.c#17 (text+ko) ====
@@ -383,7 +383,18 @@
}
CRASH_EVENT("lock test1 mutex and then Giant", test_mtx_then_Giant);
#endif
-
+
+static void
+test_no_sleeping(void)
+{
+
+ printf("Should panic\n");
+ THREAD_NO_SLEEPING();
+ tsleep(&test1_mtx, curthread->td_priority, "sleep", 1);
+ THREAD_SLEEPING_OK();
+}
+CRASH_EVENT("sleep while sleeping is prohibited", test_no_sleeping);
+
/* Help event should be last so that it is always event 1. */
static void
==== //depot/projects/smpng/sys/notes#53 (text+ko) ====
@@ -85,7 +85,7 @@
- fork counts?
- Add a cache-line padded mtx_aligned union and use it for the mutex pools.
- Robert wants intrcnt's for IPIs
-- Add checks to msleep() and cv_wait*() to ensure they aren't called by an
++ Add checks to msleep() and cv_wait*() to ensure they aren't called by an
interrupt thread. Would need to provide an exception for the istorm
stuff.
- Add witness checks to thread exit to make sure dying threads don't leak
==== //depot/projects/smpng/sys/sys/proc.h#148 (text+ko) ====
@@ -368,7 +368,7 @@
#define TDP_ALTSTACK 0x00000020 /* Have alternate signal stack. */
#define TDP_DEADLKTREAT 0x00000040 /* Lock aquisition - deadlock treatment. */
#define TDP_SA 0x00000080 /* A scheduler activation based thread. */
-#define TDP_UNUSED8 0x00000100 /* --available -- */
+#define TDP_NOSLEEPING 0x00000100 /* Thread is not allowed to sleep on a sq. */
#define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */
#define TDP_UNUSED10 0x00000400 /* --available -- */
#define TDP_CAN_UNBIND 0x00000800 /* Only temporarily bound. */
@@ -793,6 +793,19 @@
/* Check whether a thread is safe to be swapped out. */
#define thread_safetoswapout(td) (TD_IS_SLEEPING(td) || TD_IS_SUSPENDED(td))
+/* Control whether or not it is safe for curthread to sleep. */
+#define THREAD_NO_SLEEPING() do { \
+ KASSERT(!(curthread->td_pflags & TDP_NOSLEEPING), \
+ ("nested no sleeping")); \
+ curthread->td_pflags |= TDP_NOSLEEPING; \
+} while (0)
+
+#define THREAD_SLEEPING_OK() do { \
+ KASSERT((curthread->td_pflags & TDP_NOSLEEPING), \
+ ("nested sleeping ok")); \
+ curthread->td_pflags &= ~TDP_NOSLEEPING; \
+} while (0)
+
/* Lock and unlock process arguments. */
#define PARGS_LOCK(p) mtx_lock(&pargs_ref_lock)
#define PARGS_UNLOCK(p) mtx_unlock(&pargs_ref_lock)
More information about the p4-projects
mailing list