DELAY() is a spin loop, we can't use it any more because shutdown
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 18 Jul 2005 02:47:36 +0000 (02:47 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 18 Jul 2005 02:47:36 +0000 (02:47 +0000)
depends on other threads working.  Not only does the syncer and buffer
flusher need to work (else they might get stuck holding a lock on a buffer),
but the scheduler helper threads and device helper threads must also continue
to operate to be able to successfully flush the buffer cache.   In addition,
busy looping while holding the BGL can seriously deadlock SMP machines, so
even if it was (sometimes) possible to get away with using DELAY on UP boxes,
it's simply impossible on an SMP box.

So change the DELAY's to tsleep's in the shutdown code.  The current thread
is also given a very high priority (higher then an interrupt thread,
in fact), to try to ensure it gets through the shutdown procedure even if
the system is fried.  For the moment we do not move the thread to cpu #0.

This puts us in a somewhat awkwar situation when handling panics, but I don't
see that we have much of a choice.

Reported-by: Peter Avalos, David Rhodus, and numerous other people over time.
sys/kern/kern_shutdown.c

index 283b678..6ade3d7 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_shutdown.c     8.3 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/kern_shutdown.c,v 1.72.2.12 2002/02/21 19:15:10 dillon Exp $
- * $DragonFly: src/sys/kern/kern_shutdown.c,v 1.20 2005/06/16 17:55:06 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_shutdown.c,v 1.21 2005/07/18 02:47:36 dillon Exp $
  */
 
 #include "opt_ddb.h"
@@ -226,6 +226,13 @@ print_uptime()
 static void
 boot(int howto)
 {
+       /*
+        * Get rid of any user scheduler baggage and then give
+        * us a high priority.
+        */
+       if (curthread->td_release)
+               curthread->td_release(curthread);
+       lwkt_setpri_self(TDPRI_MAX);
 
        /* collect extra flags that shutdown_nice might have set */
        howto |= shutdown_howto;
@@ -283,7 +290,7 @@ boot(int howto)
                        if (iter > 5 && bioops.io_sync)
                                (*bioops.io_sync)(NULL);
                        sync(NULL); /* YYY was sync(&proc0, NULL). why proc0 ? */
-                       DELAY(50000 * iter);
+                       tsleep(boot, 0, "shutdn", hz * iter / 20 + 1);
                }
                printf("\n");
                /*
@@ -317,7 +324,7 @@ boot(int howto)
 #ifdef DDB
                        Debugger("busy buffer problem");
 #endif /* DDB */
-                       DELAY(5000000); /* 5 seconds */
+                       tsleep(boot, 0, "shutdn", hz * 5 + 1);
                } else {
                        printf("done\n");
                        /*
@@ -326,7 +333,7 @@ boot(int howto)
                        if (panicstr == 0)
                                vfs_unmountall();
                }
-               DELAY(100000);          /* wait for console output to finish */
+               tsleep(boot, 0, "shutdn", hz / 10 + 1);
        }
 
        print_uptime();