tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: shutdown hooks at panic (was Re: CVS commit: src/sys/kern)
Here are the shutdown hooks I have been running as an experiment.
They have helped me find many bugs in detach routines. Buggy detach
routines remain.
The patch also includes a patch for i386 that allows interrupts while
the shutdown hooks run.
Dave
--
David Young OJC Technologies
dyoung%ojctech.com@localhost Urbana, IL * (217) 278-3933 ext 24
Index: kern/kern_pmf.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_pmf.c,v
retrieving revision 1.10
diff -p -u -u -p -r1.10 kern_pmf.c
--- kern/kern_pmf.c 27 Dec 2007 16:03:10 -0000 1.10
+++ kern/kern_pmf.c 30 Jan 2008 00:40:39 -0000
@@ -88,6 +88,15 @@ typedef struct pmf_event_workitem {
device_t pew_device;
} pmf_event_workitem_t;
+struct shutdown_state {
+ bool initialized;
+ int depth;
+ device_t prevdev;
+};
+
+static device_t shutdown_first(struct shutdown_state *);
+static device_t shutdown_next(struct shutdown_state *);
+
static void
pmf_event_worker(struct work *wk, void *dummy)
{
@@ -267,40 +276,73 @@ pmf_system_suspend(void)
return true;
}
-void
-pmf_system_shutdown(void)
+static device_t
+shutdown_first(struct shutdown_state *s)
{
- int depth, maxdepth;
device_t curdev;
- aprint_debug("Shutting down devices:");
-
- maxdepth = 0;
- TAILQ_FOREACH(curdev, &alldevs, dv_list) {
- if (curdev->dv_depth > maxdepth)
- maxdepth = curdev->dv_depth;
- }
+ if (!s->initialized) {
+ s->depth = -1;
+ s->prevdev = NULL;
- for (depth = maxdepth; depth >= 0; --depth) {
TAILQ_FOREACH_REVERSE(curdev, &alldevs, devicelist, dv_list) {
- if (curdev->dv_depth != depth)
- continue;
if (!device_is_active(curdev))
continue;
+ if (curdev->dv_depth <= s->depth)
+ continue;
+ s->depth = curdev->dv_depth;
+ s->prevdev = curdev;
+ }
+ s->initialized = true;
+ }
+ return shutdown_next(s);
+}
- aprint_debug(" %s", device_xname(curdev));
+static device_t
+shutdown_next(struct shutdown_state *s)
+{
+ device_t curdev, retdev;
- if (!device_pmf_is_registered(curdev))
- continue;
- if (!device_pmf_class_suspend(curdev)) {
- aprint_debug("(failed)");
- continue;
- }
- if (!device_pmf_driver_suspend(curdev)) {
- aprint_debug("(failed)");
- continue;
- }
+ curdev = retdev = s->prevdev;
+
+ while (curdev != NULL) {
+ curdev = TAILQ_PREV(curdev, devicelist, dv_list);
+ if (curdev == NULL) {
+ if (--s->depth < 0)
+ break;
+ if ((curdev = TAILQ_LAST(&alldevs, devicelist)) == NULL)
+ break;
}
+ if (curdev->dv_depth == s->depth && device_is_active(curdev))
+ break;
+ }
+ s->prevdev = curdev;
+ return retdev;
+}
+
+void
+pmf_system_shutdown(void)
+{
+ static struct shutdown_state s;
+ device_t curdev;
+
+ if (!pmf_check_system_drivers())
+ delay(1000000);
+
+ aprint_debug("Shutting down devices:");
+
+ for (curdev = shutdown_first(&s); curdev != NULL;
+ curdev = shutdown_next(&s)) {
+ aprint_debug(" attempting %s shutdown",
+ device_xname(curdev));
+ if (config_detach(curdev, 0) == 0)
+ aprint_debug("(detached)");
+ else if (!device_pmf_is_registered(curdev))
+ aprint_debug("(skipped)");
+ else if (!device_pmf_class_suspend(curdev))
+ aprint_debug("(failed)");
+ else if (!device_pmf_driver_suspend(curdev))
+ aprint_debug("(failed)");
}
aprint_debug(".\n");
Index: arch/i386/i386/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.625
diff -p -u -u -p -r1.625 machdep.c
--- arch/i386/i386/machdep.c 23 Jan 2008 19:46:44 -0000 1.625
+++ arch/i386/i386/machdep.c 30 Jan 2008 00:40:39 -0000
@@ -926,6 +926,7 @@ int waittime = -1;
void
cpu_reboot(int howto, char *bootstr)
{
+ int s;
if (cold) {
howto |= RB_HALT;
@@ -945,15 +946,20 @@ cpu_reboot(int howto, char *bootstr)
}
/* Disable interrupts. */
- splhigh();
+ s = splhigh();
/* Do a dump if requested. */
if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
dumpsys();
+ splx(s);
+
haltsys:
doshutdownhooks();
+ if (!cold)
+ splhigh();
+
#ifdef MULTIPROCESSOR
x86_broadcast_ipi(X86_IPI_HALT);
#endif
Home |
Main Index |
Thread Index |
Old Index