Module Name:    src
Committed By:   dyoung
Date:           Fri Jun 26 19:30:46 UTC 2009

Modified Files:
        src/sys/kern: kern_pmf.c subr_autoconf.c
        src/sys/sys: device.h

Log Message:
Switch to kmem(9).

(void *)pew is one way to get a struct work *, but let's
write&pew->pew_work, instead.  It is more defensive and persuasive.

Make miscellaneous changes in support of tearing down arbitrary
stacks of filesystems and devices during shutdown:

1 Move struct shutdown_state, shutdown_first(), and shutdown_next(),
  from kern_pmf.c to subr_autoconf.c.  Rename detach_all() to
  config_detach_all(), and move it from kern_pmf.c to subr_autoconf.c.
  Export all of those routines.

2 In pmf_system_shutdown(), do not suspend user process scheduling, and
  do not detach all devices: I am going to do that in cpu_reboot(),
  instead.  (Soon I will do it in an MI cpu_reboot() routine.)  Do still
  call PMF shutdown hooks.

3 In config_detach(), add a DIAGNOSTIC assertion: if we're exiting
  config_detach() at the bottom, alldevs_nwrite had better not be 0,
  because config_detach() is a writer of the device list.

4 In deviter_release(), check to see if we're iterating the device list
  for reading, *first*, and if so, decrease the number of readers.  Used
  to be that if we happened to be reading during shutdown, we ran the
  shutdown branch.  Thus the number of writers reached 0, the number
  of readers remained > 0, and no writer could iterate again.  Under
  certain circumstances that would cause a hang during shutdown.


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/kern/kern_pmf.c
cvs rdiff -u -r1.177 -r1.178 src/sys/kern/subr_autoconf.c
cvs rdiff -u -r1.119 -r1.120 src/sys/sys/device.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_pmf.c
diff -u src/sys/kern/kern_pmf.c:1.26 src/sys/kern/kern_pmf.c:1.27
--- src/sys/kern/kern_pmf.c:1.26	Fri Apr 17 20:45:09 2009
+++ src/sys/kern/kern_pmf.c	Fri Jun 26 19:30:45 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_pmf.c,v 1.26 2009/04/17 20:45:09 dyoung Exp $ */
+/* $NetBSD: kern_pmf.c,v 1.27 2009/06/26 19:30:45 dyoung Exp $ */
 
 /*-
  * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca>
@@ -27,11 +27,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_pmf.c,v 1.26 2009/04/17 20:45:09 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_pmf.c,v 1.27 2009/06/26 19:30:45 dyoung Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
-#include <sys/malloc.h>
+#include <sys/kmem.h>
 #include <sys/buf.h>
 #include <sys/callout.h>
 #include <sys/kernel.h>
@@ -94,13 +94,7 @@
 	device_t		pew_device;
 } pmf_event_workitem_t;
 
-struct shutdown_state {
-	bool initialized;
-	deviter_t di;
-};
 
-static device_t shutdown_first(struct shutdown_state *);
-static device_t shutdown_next(struct shutdown_state *);
 
 static bool pmf_device_resume_locked(device_t PMF_FN_PROTO);
 static bool pmf_device_suspend_locked(device_t PMF_FN_PROTO);
@@ -122,7 +116,7 @@
 			(*event->pmf_handler)(event->pmf_device);
 	}
 
-	free(pew, M_TEMP);
+	kmem_free(pew, sizeof(*pew));
 }
 
 static bool
@@ -270,52 +264,6 @@
 	return true;
 }
 
-static device_t
-shutdown_first(struct shutdown_state *s)
-{
-	if (!s->initialized) {
-		deviter_init(&s->di, DEVITER_F_SHUTDOWN|DEVITER_F_LEAVES_FIRST);
-		s->initialized = true;
-	}
-	return shutdown_next(s);
-}
-
-static device_t
-shutdown_next(struct shutdown_state *s)
-{
-	device_t dv;
-
-	while ((dv = deviter_next(&s->di)) != NULL && !device_is_active(dv))
-		;
-
-	if (dv == NULL)
-		s->initialized = false;
-
-	return dv;
-}
-
-static bool
-detach_all(int how)
-{
-	static struct shutdown_state s;
-	device_t curdev;
-	bool progress = false;
-
-	if ((how & RB_NOSYNC) != 0)
-		return false;
-
-	for (curdev = shutdown_first(&s); curdev != NULL;
-	     curdev = shutdown_next(&s)) {
-		aprint_debug(" detaching %s, ", device_xname(curdev));
-		if (config_detach(curdev, DETACH_SHUTDOWN) == 0) {
-			progress = true;
-			aprint_debug("success.");
-		} else
-			aprint_debug("failed.");
-	}
-	return progress;
-}
-
 static bool
 shutdown_all(int how)
 {
@@ -348,11 +296,6 @@
 pmf_system_shutdown(int how)
 {
 	aprint_debug("Shutting down devices:");
-	suspendsched();
-
-	while (detach_all(how))
-		;
-
 	shutdown_all(how);
 }
 
@@ -612,7 +555,7 @@
 {
 	pmf_event_workitem_t *pew;
 
-	pew = malloc(sizeof(pmf_event_workitem_t), M_TEMP, M_NOWAIT);
+	pew = kmem_alloc(sizeof(pmf_event_workitem_t), KM_NOSLEEP);
 	if (pew == NULL) {
 		PMF_EVENT_PRINTF(("%s: PMF event %d dropped (no memory)\n",
 		    dv ? device_xname(dv) : "<anonymous>", ev));
@@ -622,7 +565,7 @@
 	pew->pew_event = ev;
 	pew->pew_device = dv;
 
-	workqueue_enqueue(pmf_event_workqueue, (void *)pew, NULL);
+	workqueue_enqueue(pmf_event_workqueue, &pew->pew_work, NULL);
 	PMF_EVENT_PRINTF(("%s: PMF event %d injected\n",
 	    dv ? device_xname(dv) : "<anonymous>", ev));
 
@@ -635,7 +578,7 @@
 {
 	pmf_event_handler_t *event; 
 	
-	event = malloc(sizeof(*event), M_DEVBUF, M_WAITOK);
+	event = kmem_alloc(sizeof(*event), KM_SLEEP);
 	event->pmf_event = ev;
 	event->pmf_handler = handler;
 	event->pmf_device = dv;
@@ -661,7 +604,7 @@
 		if (event->pmf_handler != handler)
 			continue;
 		TAILQ_REMOVE(&pmf_all_events, event, pmf_link);
-		free(event, M_DEVBUF);
+		kmem_free(event, sizeof(*event));
 		return;
 	}
 }
@@ -719,7 +662,7 @@
 		callout_stop(&global_idle_counter);
 	splx(s);
 
-	free(sc, M_DEVBUF);
+	kmem_free(sc, sizeof(*sc));
 }
 
 bool
@@ -728,7 +671,7 @@
 	struct display_class_softc *sc;
 	int s;
 
-	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK);
+	sc = kmem_alloc(sizeof(*sc), KM_SLEEP);
 
 	s = splsoftclock();
 	if (TAILQ_EMPTY(&all_displays))

Index: src/sys/kern/subr_autoconf.c
diff -u src/sys/kern/subr_autoconf.c:1.177 src/sys/kern/subr_autoconf.c:1.178
--- src/sys/kern/subr_autoconf.c:1.177	Fri May 29 23:27:08 2009
+++ src/sys/kern/subr_autoconf.c	Fri Jun 26 19:30:45 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.177 2009/05/29 23:27:08 dyoung Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.178 2009/06/26 19:30:45 dyoung Exp $ */
 
 /*
  * Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -77,7 +77,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.177 2009/05/29 23:27:08 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.178 2009/06/26 19:30:45 dyoung Exp $");
 
 #include "opt_ddb.h"
 #include "drvctl.h"
@@ -1598,6 +1598,7 @@
 
 out:
 	mutex_enter(&alldevs_mtx);
+	KASSERT(alldevs_nwrite != 0);
 	if (--alldevs_nwrite == 0)
 		alldevs_writer = NULL;
 	cv_signal(&alldevs_cv);
@@ -1623,6 +1624,52 @@
 	return error;
 }
 
+device_t
+shutdown_first(struct shutdown_state *s)
+{
+	if (!s->initialized) {
+		deviter_init(&s->di, DEVITER_F_SHUTDOWN|DEVITER_F_LEAVES_FIRST);
+		s->initialized = true;
+	}
+	return shutdown_next(s);
+}
+
+device_t
+shutdown_next(struct shutdown_state *s)
+{
+	device_t dv;
+
+	while ((dv = deviter_next(&s->di)) != NULL && !device_is_active(dv))
+		;
+
+	if (dv == NULL)
+		s->initialized = false;
+
+	return dv;
+}
+
+bool
+config_detach_all(int how)
+{
+	static struct shutdown_state s;
+	device_t curdev;
+	bool progress = false;
+
+	if ((how & RB_NOSYNC) != 0)
+		return false;
+
+	for (curdev = shutdown_first(&s); curdev != NULL;
+	     curdev = shutdown_next(&s)) {
+		aprint_debug(" detaching %s, ", device_xname(curdev));
+		if (config_detach(curdev, DETACH_SHUTDOWN) == 0) {
+			progress = true;
+			aprint_debug("success.");
+		} else
+			aprint_debug("failed.");
+	}
+	return progress;
+}
+
 int
 config_activate(device_t dev)
 {
@@ -2689,16 +2736,15 @@
 	bool rw = (di->di_flags & DEVITER_F_RW) != 0;
 
 	mutex_enter(&alldevs_mtx);
-	if (alldevs_nwrite > 0 && alldevs_writer == NULL)
-		--alldevs_nwrite;
-	else {
-
-		if (rw) {
-			if (--alldevs_nwrite == 0)
-				alldevs_writer = NULL;
-		} else
-			--alldevs_nread;
-
+	if (!rw) {
+		--alldevs_nread;
+		cv_signal(&alldevs_cv);
+	} else if (alldevs_nwrite > 0 && alldevs_writer == NULL) {
+		--alldevs_nwrite;	/* shutting down: do not signal */
+	} else {
+		KASSERT(alldevs_nwrite != 0);
+		if (--alldevs_nwrite == 0)
+			alldevs_writer = NULL;
 		cv_signal(&alldevs_cv);
 	}
 	mutex_exit(&alldevs_mtx);

Index: src/sys/sys/device.h
diff -u src/sys/sys/device.h:1.119 src/sys/sys/device.h:1.120
--- src/sys/sys/device.h:1.119	Thu May  7 22:17:41 2009
+++ src/sys/sys/device.h	Fri Jun 26 19:30:45 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: device.h,v 1.119 2009/05/07 22:17:41 cegger Exp $ */
+/* $NetBSD: device.h,v 1.120 2009/06/26 19:30:45 dyoung Exp $ */
 
 /*
  * Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -201,6 +201,11 @@
 };
 
 typedef struct deviter deviter_t;
+
+struct shutdown_state {
+	bool initialized;
+	deviter_t di;
+};
 #endif
 
 /*
@@ -446,6 +451,7 @@
 
 int	config_detach(device_t, int);
 int	config_detach_children(device_t, int flags);
+bool	config_detach_all(int);
 int	config_activate(device_t);
 int	config_deactivate(device_t);
 void	config_defer(device_t, void (*)(device_t));
@@ -540,6 +546,8 @@
 		    void (*)(device_t));
 void		device_pmf_class_deregister(device_t);
 
+device_t	shutdown_first(struct shutdown_state *);
+device_t	shutdown_next(struct shutdown_state *);
 #endif /* _KERNEL */
 
 #endif /* !_SYS_DEVICE_H_ */

Reply via email to