Module Name:    src
Committed By:   pgoyette
Date:           Thu Apr 23 23:22:03 UTC 2015

Modified Files:
        src/sys/dev/sysmon: sysmon.c sysmon_envsys.c sysmon_power.c
            sysmon_taskq.c sysmon_wdog.c sysmonvar.h
Removed Files:
        src/sys/dev/sysmon: sysmonconf.h

Log Message:
Modularize sysmon and its components


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/sysmon/sysmon.c
cvs rdiff -u -r1.130 -r1.131 src/sys/dev/sysmon/sysmon_envsys.c
cvs rdiff -u -r1.53 -r1.54 src/sys/dev/sysmon/sysmon_power.c
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/sysmon/sysmon_taskq.c
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/sysmon/sysmon_wdog.c
cvs rdiff -u -r1.3 -r0 src/sys/dev/sysmon/sysmonconf.h
cvs rdiff -u -r1.48 -r1.49 src/sys/dev/sysmon/sysmonvar.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/dev/sysmon/sysmon.c
diff -u src/sys/dev/sysmon/sysmon.c:1.19 src/sys/dev/sysmon/sysmon.c:1.20
--- src/sys/dev/sysmon/sysmon.c:1.19	Fri Jul 25 08:10:39 2014
+++ src/sys/dev/sysmon/sysmon.c	Thu Apr 23 23:22:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysmon.c,v 1.19 2014/07/25 08:10:39 dholland Exp $	*/
+/*	$NetBSD: sysmon.c,v 1.20 2015/04/23 23:22:03 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2000 Zembu Labs, Inc.
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon.c,v 1.19 2014/07/25 08:10:39 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon.c,v 1.20 2015/04/23 23:22:03 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -49,9 +49,11 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon.c,v 1
 #include <sys/kernel.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/device.h>
 
 #include <dev/sysmon/sysmonvar.h>
-#include <dev/sysmon/sysmonconf.h>
 
 dev_type_open(sysmonopen);
 dev_type_close(sysmonclose);
@@ -75,6 +77,97 @@ const struct cdevsw sysmon_cdevsw = {
 	.d_flag = D_OTHER | D_MPSAFE
 };
 
+static int	sysmon_match(device_t, cfdata_t, void *);
+static void	sysmon_attach(device_t, device_t, void *);
+static int	sysmon_detach(device_t, int);
+
+static int	sysmon_modcmd(modcmd_t, void *); 
+
+CFDRIVER_DECL(sysmon, DV_DULL, NULL);
+
+/*
+ * Info about our minor "devices"
+ */
+static struct sysmon_opvec	*sysmon_opvec_table[] = { NULL, NULL, NULL };
+static int			sysmon_refcnt[] = { 0, 0, 0 };
+static const char		*sysmon_mod[] = { "sysmon_envsys",
+						  "sysmon_wdog",
+						  "sysmon_power" };
+
+struct sysmon_softc { 
+	device_t sc_dev;
+	kmutex_t sc_minor_mtx;
+}; 
+
+static device_t sysmon_dev = NULL;
+
+CFATTACH_DECL_NEW(sysmon, sizeof(struct sysmon_softc),
+        sysmon_match, sysmon_attach, sysmon_detach, NULL);
+extern struct cfdriver sysmon_cd;
+
+static int
+sysmon_match(device_t parent, cfdata_t data, void *aux)   
+{
+
+	return 1;
+}
+
+static void
+sysmon_attach(device_t parent, device_t self, void *aux)
+{
+
+        struct sysmon_softc *sc = device_private(self);
+                    
+        sc->sc_dev = self;
+
+	mutex_init(&sc->sc_minor_mtx, MUTEX_DEFAULT, IPL_NONE);
+}
+
+static int
+sysmon_detach(device_t self, int flags)
+{
+        struct sysmon_softc *sc = device_private(self);
+
+	mutex_destroy(&sc->sc_minor_mtx);
+	return 0;
+}
+
+/*
+ * sysmon_attach_minor
+ *
+ *	Attach a minor device for wdog, power, or envsys.  Manage a
+ *	reference count so we can prevent the device from being
+ *	detached if there are still users with the minor device opened.
+ *
+ *	If the opvec argument is NULL, this is a request to detach the
+ *	minor device - make sure the refcnt is zero!
+ */
+int
+sysmon_attach_minor(int minor, struct sysmon_opvec *opvec)
+{
+	struct sysmon_softc *sc = device_private(sysmon_dev);
+	int ret;
+
+	mutex_enter(&sc->sc_minor_mtx);
+	if (opvec) {
+		if (sysmon_opvec_table[minor] == NULL) {
+			sysmon_refcnt[minor] = 0;
+			sysmon_opvec_table[minor] = opvec;
+			ret = 0;
+		} else
+			ret = EEXIST;
+	} else {
+		if (sysmon_refcnt[minor] == 0) {
+			sysmon_opvec_table[minor] = NULL;
+			ret = 0;
+		} else
+			ret = EBUSY;
+	}
+
+	mutex_exit(&sc->sc_minor_mtx);
+	return ret;
+}
+
 /*
  * sysmonopen:
  *
@@ -83,28 +176,33 @@ const struct cdevsw sysmon_cdevsw = {
 int
 sysmonopen(dev_t dev, int flag, int mode, struct lwp *l)
 {
+	struct sysmon_softc *sc = device_private(sysmon_dev);
 	int error;
 
+	mutex_enter(&sc->sc_minor_mtx);
+
 	switch (minor(dev)) {
-#if NSYSMON_ENVSYS > 0
 	case SYSMON_MINOR_ENVSYS:
-		error = sysmonopen_envsys(dev, flag, mode, l);
-		break;
-#endif
-#if NSYSMON_WDOG > 0
 	case SYSMON_MINOR_WDOG:
-		error = sysmonopen_wdog(dev, flag, mode, l);
-		break;
-#endif
-#if NSYSMON_POWER > 0
 	case SYSMON_MINOR_POWER:
-		error = sysmonopen_power(dev, flag, mode, l);
+		if (sysmon_opvec_table[minor(dev)] == NULL) {
+			mutex_exit(&sc->sc_minor_mtx);
+			error = module_autoload(sysmon_mod[minor(dev)],
+						MODULE_CLASS_MISC);
+			mutex_enter(&sc->sc_minor_mtx);
+			if (sysmon_opvec_table[minor(dev)] == NULL)
+				error = ENODEV;
+		}
+		error = (sysmon_opvec_table[minor(dev)]->so_open)(dev, flag,
+		    mode, l);
+		if (error == 0)
+			sysmon_refcnt[minor(dev)]++;
 		break;
-#endif
 	default:
 		error = ENODEV;
 	}
 
+	mutex_exit(&sc->sc_minor_mtx);
 	return (error);
 }
 
@@ -119,21 +217,20 @@ sysmonclose(dev_t dev, int flag, int mod
 	int error;
 
 	switch (minor(dev)) {
-#if NSYSMON_ENVSYS > 0
 	case SYSMON_MINOR_ENVSYS:
-		error = sysmonclose_envsys(dev, flag, mode, l);
-		break;
-#endif
-#if NSYSMON_WDOG > 0
 	case SYSMON_MINOR_WDOG:
-		error = sysmonclose_wdog(dev, flag, mode, l);
-		break;
-#endif
-#if NSYSMON_POWER > 0
 	case SYSMON_MINOR_POWER:
-		error = sysmonclose_power(dev, flag, mode, l);
+		if (sysmon_opvec_table[minor(dev)] == NULL)
+			error = ENODEV;
+		else {
+			error = (sysmon_opvec_table[minor(dev)]->so_close)(dev,
+			    flag, mode, l);
+			if (error == 0) {
+				sysmon_refcnt[minor(dev)]--;
+				KASSERT(sysmon_refcnt[minor(dev)] >= 0);
+			}
+		}
 		break;
-#endif
 	default:
 		error = ENODEV;
 	}
@@ -152,21 +249,15 @@ sysmonioctl(dev_t dev, u_long cmd, void 
 	int error;
 
 	switch (minor(dev)) {
-#if NSYSMON_ENVSYS > 0
 	case SYSMON_MINOR_ENVSYS:
-		error = sysmonioctl_envsys(dev, cmd, data, flag, l);
-		break;
-#endif
-#if NSYSMON_WDOG > 0
 	case SYSMON_MINOR_WDOG:
-		error = sysmonioctl_wdog(dev, cmd, data, flag, l);
-		break;
-#endif
-#if NSYSMON_POWER > 0
 	case SYSMON_MINOR_POWER:
-		error = sysmonioctl_power(dev, cmd, data, flag, l);
+		if (sysmon_opvec_table[minor(dev)] == NULL)
+			error = ENODEV;
+		else
+			error = (sysmon_opvec_table[minor(dev)]->so_ioctl)(dev,
+			    cmd, data, flag, l);
 		break;
-#endif
 	default:
 		error = ENODEV;
 	}
@@ -185,11 +276,13 @@ sysmonread(dev_t dev, struct uio *uio, i
 	int error;
 
 	switch (minor(dev)) {
-#if NSYSMON_POWER > 0
 	case SYSMON_MINOR_POWER:
-		error = sysmonread_power(dev, uio, flags);
+		if (sysmon_opvec_table[minor(dev)] == NULL)
+			error = ENODEV;
+		else
+			error = (sysmon_opvec_table[minor(dev)]->so_read)(dev,
+			    uio, flags);
 		break;
-#endif
 	default:
 		error = ENODEV;
 	}
@@ -208,11 +301,13 @@ sysmonpoll(dev_t dev, int events, struct
 	int rv;
 
 	switch (minor(dev)) {
-#if NSYSMON_POWER > 0
 	case SYSMON_MINOR_POWER:
-		rv = sysmonpoll_power(dev, events, l);
+		if (sysmon_opvec_table[minor(dev)] == NULL)
+			rv = events;
+		else
+			rv = (sysmon_opvec_table[minor(dev)]->so_poll)(dev,
+			    events, l);
 		break;
-#endif
 	default:
 		rv = events;
 	}
@@ -231,14 +326,119 @@ sysmonkqfilter(dev_t dev, struct knote *
 	int error;
 
 	switch (minor(dev)) {
-#if NSYSMON_POWER > 0
 	case SYSMON_MINOR_POWER:
-		error = sysmonkqfilter_power(dev, kn);
+		if (sysmon_opvec_table[minor(dev)] == NULL)
+			error = ENODEV;
+		else
+			error = (sysmon_opvec_table[minor(dev)]->so_filter)(dev,
+			    kn);
 		break;
-#endif
 	default:
 		error = 1;
 	}
 
 	return (error);
 }
+
+MODULE(MODULE_CLASS_DRIVER, sysmon, "");
+
+int
+sysmon_init(void)
+{
+	devmajor_t bmajor, cmajor;
+	static struct cfdata cf;
+	int error = 0;
+
+	if (sysmon_dev != NULL) {
+		return EEXIST;
+	}
+
+	error = config_cfdriver_attach(&sysmon_cd);
+	if (error) {
+		aprint_error("%s: unable to attach cfdriver\n",
+		    sysmon_cd.cd_name);
+		return error;
+	}
+	error = config_cfattach_attach(sysmon_cd.cd_name, &sysmon_ca);
+	if (error) {
+		config_cfdriver_detach(&sysmon_cd);
+		aprint_error("%s: unable to attach cfattach\n",
+		    sysmon_cd.cd_name);
+		return error;
+	}
+
+	bmajor = cmajor = -1;
+	error = devsw_attach("sysmon", NULL, &bmajor,
+			&sysmon_cdevsw, &cmajor);
+	if (error) {
+		config_cfattach_detach(sysmon_cd.cd_name, &sysmon_ca);
+		config_cfdriver_detach(&sysmon_cd);
+		aprint_error("%s: unable to attach devsw\n",
+		    sysmon_cd.cd_name);
+		return error;
+	}
+
+	cf.cf_name = sysmon_cd.cd_name;
+	cf.cf_atname = sysmon_cd.cd_name; 
+	cf.cf_unit = 0;
+	cf.cf_fstate = FSTATE_STAR;
+	cf.cf_pspec = NULL;
+	cf.cf_loc = NULL;
+	cf.cf_flags = 0;
+ 
+	sysmon_dev = config_attach_pseudo(&cf);
+	if (sysmon_dev == NULL) {
+		aprint_error("%s: failed to attach pseudo device\n",
+		    sysmon_cd.cd_name);
+		error = ENODEV;
+	}
+
+	return error;
+}
+
+int
+sysmon_fini(void)
+{
+	int error = 0;
+
+	if (sysmon_opvec_table[SYSMON_MINOR_ENVSYS] != NULL)
+		error = EBUSY;
+	else if (sysmon_opvec_table[SYSMON_MINOR_WDOG] != NULL)
+		error = EBUSY;
+	else if (sysmon_opvec_table[SYSMON_MINOR_POWER] != NULL)
+		error = EBUSY;
+
+	else {
+		config_detach(sysmon_dev, 0);
+		devsw_detach(NULL, &sysmon_cdevsw);
+		config_cfattach_detach(sysmon_cd.cd_name, &sysmon_ca);
+		config_cfdriver_detach(&sysmon_cd);
+	}
+	if (error == 0)
+		sysmon_dev = NULL;
+
+	return error;
+}
+
+static
+int   
+sysmon_modcmd(modcmd_t cmd, void *arg)
+{
+	int ret;
+ 
+	switch (cmd) { 
+	case MODULE_CMD_INIT:
+		ret = sysmon_init();
+		break;
+ 
+	case MODULE_CMD_FINI: 
+		ret = sysmon_fini(); 
+		break;
+ 
+	case MODULE_CMD_STAT:
+	default: 
+		ret = ENOTTY;
+	}
+ 
+	return ret;
+}

Index: src/sys/dev/sysmon/sysmon_envsys.c
diff -u src/sys/dev/sysmon/sysmon_envsys.c:1.130 src/sys/dev/sysmon/sysmon_envsys.c:1.131
--- src/sys/dev/sysmon/sysmon_envsys.c:1.130	Mon Apr 13 16:33:25 2015
+++ src/sys/dev/sysmon/sysmon_envsys.c	Thu Apr 23 23:22:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysmon_envsys.c,v 1.130 2015/04/13 16:33:25 riastradh Exp $	*/
+/*	$NetBSD: sysmon_envsys.c,v 1.131 2015/04/23 23:22:03 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008 Juan Romero Pardines.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.130 2015/04/13 16:33:25 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.131 2015/04/23 23:22:03 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -77,6 +77,7 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_envsy
 #include <sys/mutex.h>
 #include <sys/kmem.h>
 #include <sys/rndsource.h>
+#include <sys/module.h>
 
 #include <dev/sysmon/sysmonvar.h>
 #include <dev/sysmon/sysmon_envsysvar.h>
@@ -101,17 +102,46 @@ static void sme_initial_refresh(void *);
 static uint32_t sme_get_max_value(struct sysmon_envsys *,
      bool (*)(const envsys_data_t*), bool);
 
+MODULE(MODULE_CLASS_MISC, sysmon_envsys, "sysmon,sysmon_taskq");
+
+static struct sysmon_opvec sysmon_envsys_opvec = {    
+        sysmonopen_envsys, sysmonclose_envsys, sysmonioctl_envsys,
+        NULL, NULL, NULL
+};
+
 /*
  * sysmon_envsys_init:
  *
  * 	+ Initialize global mutex, dictionary and the linked list.
  */
-void
+int
 sysmon_envsys_init(void)
 {
+	int error;
+
 	LIST_INIT(&sysmon_envsys_list);
 	mutex_init(&sme_global_mtx, MUTEX_DEFAULT, IPL_NONE);
 	sme_propd = prop_dictionary_create();
+
+	error = sysmon_attach_minor(SYSMON_MINOR_ENVSYS, &sysmon_envsys_opvec);
+
+	return error;
+}
+
+int
+sysmon_envsys_fini(void)
+{
+	int error;
+
+	if ( ! LIST_EMPTY(&sysmon_envsys_list))
+		error = EBUSY;
+	else
+		error = sysmon_attach_minor(SYSMON_MINOR_ENVSYS, NULL);
+
+	if (error == 0)
+		mutex_destroy(&sme_global_mtx);
+
+	return error;
 }
 
 /*
@@ -771,7 +801,6 @@ out:
 	 */
 	if (error == 0) {
 		nevent = 0;
-		sysmon_task_queue_init();
 
 		if (sme->sme_flags & SME_INIT_REFRESH) {
 			sysmon_task_queue_sched(0, sme_initial_refresh, sme);
@@ -848,6 +877,7 @@ out2:
 		SLIST_REMOVE_HEAD(&sme_evdrv_list, evdrv_head);
 		kmem_free(evdv, sizeof(*evdv));
 	}
+printf("%s: finished, error %d\n", __func__, error);
 	if (!error)
 		return 0;
 
@@ -2034,3 +2064,26 @@ sysmon_envsys_refresh_sensor(struct sysm
 		rnd_add_uint32(&edata->rnd_src, edata->value_cur);
 	edata->value_prev = edata->value_cur;
 }
+
+static
+int
+sysmon_envsys_modcmd(modcmd_t cmd, void *arg)
+{
+        int ret;
+ 
+        switch (cmd) { 
+        case MODULE_CMD_INIT:
+                ret = sysmon_envsys_init();
+                break;
+ 
+        case MODULE_CMD_FINI:
+                ret = sysmon_envsys_fini();
+                break; 
+   
+        case MODULE_CMD_STAT:
+        default:
+                ret = ENOTTY;
+        }
+  
+        return ret; 
+} 

Index: src/sys/dev/sysmon/sysmon_power.c
diff -u src/sys/dev/sysmon/sysmon_power.c:1.53 src/sys/dev/sysmon/sysmon_power.c:1.54
--- src/sys/dev/sysmon/sysmon_power.c:1.53	Mon Apr 13 16:33:25 2015
+++ src/sys/dev/sysmon/sysmon_power.c	Thu Apr 23 23:22:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysmon_power.c,v 1.53 2015/04/13 16:33:25 riastradh Exp $	*/
+/*	$NetBSD: sysmon_power.c,v 1.54 2015/04/23 23:22:03 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2007 Juan Romero Pardines.
@@ -69,9 +69,12 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.53 2015/04/13 16:33:25 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.54 2015/04/23 23:22:03 pgoyette Exp $");
 
+#ifndef _LKM
 #include "opt_compat_netbsd.h"
+#endif
+
 #include <sys/param.h>
 #include <sys/reboot.h>
 #include <sys/systm.h>
@@ -84,10 +87,13 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_power
 #include <sys/proc.h>
 #include <sys/device.h>
 #include <sys/rndsource.h>
+#include <sys/module.h>
 
 #include <dev/sysmon/sysmonvar.h>
 #include <prop/proplib.h>
 
+MODULE(MODULE_CLASS_MISC, sysmon_power, "sysmon");
+
 /*
  * Singly linked list for dictionaries to be stored/sent.
  */
@@ -186,17 +192,24 @@ static int sysmon_power_daemon_task(stru
 				    void *, int);
 static void sysmon_power_destroy_dictionary(struct power_event_dictionary *);
 
+static struct sysmon_opvec sysmon_power_opvec = {
+	sysmonopen_power, sysmonclose_power, sysmonioctl_power,
+	sysmonread_power, sysmonpoll_power, sysmonkqfilter_power
+};
+
 #define	SYSMON_NEXT_EVENT(x)		(((x) + 1) % SYSMON_MAX_POWER_EVENTS)
 
 /*
  * sysmon_power_init:
  *
  * 	Initializes the mutexes and condition variables in the
- * 	boot process via init_main.c.
+ * 	boot process via module initialization process.
  */
-void
+int
 sysmon_power_init(void)
 {
+	int error;
+
 	mutex_init(&sysmon_power_event_queue_mtx, MUTEX_DEFAULT, IPL_NONE);
 	cv_init(&sysmon_power_event_queue_cv, "smpower");
 	selinit(&sysmon_power_event_queue_selinfo);
@@ -204,6 +217,29 @@ sysmon_power_init(void)
 	rnd_attach_source(&sysmon_rndsource, "system-power",
 			  RND_TYPE_POWER, RND_FLAG_DEFAULT);
 
+	error = sysmon_attach_minor(SYSMON_MINOR_POWER, &sysmon_power_opvec);
+
+	return error;
+}
+
+int
+sysmon_power_fini(void)
+{
+	int error;
+
+	if (sysmon_power_daemon != NULL)
+		error = EBUSY;
+	else
+		error = sysmon_attach_minor(SYSMON_MINOR_POWER, NULL);
+
+	if (error == 0) {
+		rnd_detach_source(&sysmon_rndsource);
+		seldestroy(&sysmon_power_event_queue_selinfo);
+		cv_destroy(&sysmon_power_event_queue_cv);
+		mutex_destroy(&sysmon_power_event_queue_mtx);
+	}
+
+	return error;
 }
 
 /*
@@ -1059,3 +1095,27 @@ sysmon_pswitch_event(struct sysmon_pswit
 
 	}
 }
+
+static
+int   
+sysmon_power_modcmd(modcmd_t cmd, void *arg)
+{
+	int ret;
+ 
+	switch (cmd) { 
+	case MODULE_CMD_INIT:
+		ret = sysmon_power_init();
+		break;
+ 
+	case MODULE_CMD_FINI: 
+		ret = sysmon_power_fini();
+		break;
+ 
+	case MODULE_CMD_STAT:
+	default: 
+		ret = ENOTTY;
+	}
+
+	return ret;
+}
+

Index: src/sys/dev/sysmon/sysmon_taskq.c
diff -u src/sys/dev/sysmon/sysmon_taskq.c:1.14 src/sys/dev/sysmon/sysmon_taskq.c:1.15
--- src/sys/dev/sysmon/sysmon_taskq.c:1.14	Fri Sep  5 22:06:52 2008
+++ src/sys/dev/sysmon/sysmon_taskq.c	Thu Apr 23 23:22:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysmon_taskq.c,v 1.14 2008/09/05 22:06:52 gmcgarry Exp $	*/
+/*	$NetBSD: sysmon_taskq.c,v 1.15 2015/04/23 23:22:03 pgoyette Exp $	*/
 
 /*
  * Copyright (c) 2001, 2003 Wasabi Systems, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon_taskq.c,v 1.14 2008/09/05 22:06:52 gmcgarry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_taskq.c,v 1.15 2015/04/23 23:22:03 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -49,6 +49,7 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_taskq
 #include <sys/proc.h>
 #include <sys/kthread.h>
 #include <sys/systm.h>
+#include <sys/module.h>
 
 #include <dev/sysmon/sysmon_taskq.h>
 
@@ -71,15 +72,36 @@ static int sysmon_task_queue_cleanup_sem
 static struct lwp *sysmon_task_queue_lwp;
 static void sysmon_task_queue_thread(void *);
 
+MODULE(MODULE_CLASS_MISC, sysmon_taskq, NULL);
+
+/*
+ * XXX	Normally, all initialization would be handled as part of
+ *	the module(9) framework.  However, there are a number of
+ *	users of the sysmon_taskq facility that are not modular,
+ *	and these can directly call sysmon_task_queue_init()
+ *	directly.  To accomodate these non-standard users, we
+ *	make sure that sysmon_task_queue_init() handles multiple
+ *	invocations.  And we also ensure that, if any non-module
+ *	user exists, we don't allow the module to be unloaded.
+ *	(We can't use module_hold() for this, since the module(9)
+ *	framework itself isn't necessarily initialized yet.)
+ */
+
+/*
+ * sysmon_task_queue_preinit:
+ *
+ *	Early one-time initialization of task-queue
+ */
 void
 sysmon_task_queue_preinit(void)
 {
+
 	mutex_init(&sysmon_task_queue_mtx, MUTEX_DEFAULT, IPL_VM);
 	mutex_init(&sysmon_task_queue_init_mtx, MUTEX_DEFAULT, IPL_NONE);
 	cv_init(&sysmon_task_queue_cv, "smtaskq");
+	sysmon_task_queue_initialized = 0;
 }
 
-
 /*
  * sysmon_task_queue_init:
  *
@@ -91,12 +113,11 @@ sysmon_task_queue_init(void)
 	int error;
 
 	mutex_enter(&sysmon_task_queue_init_mtx);
-	if (sysmon_task_queue_initialized) {
+	if (sysmon_task_queue_initialized++) {
 		mutex_exit(&sysmon_task_queue_init_mtx);
 		return;
 	}
 
-	sysmon_task_queue_initialized = 1;
 	mutex_exit(&sysmon_task_queue_init_mtx);
 
 	error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
@@ -117,6 +138,9 @@ void
 sysmon_task_queue_fini(void)
 {
 
+	if (sysmon_task_queue_initialized > 1)
+		return EBUSY;
+
 	mutex_enter(&sysmon_task_queue_mtx);
 
 	sysmon_task_queue_cleanup_sem = 1;
@@ -209,3 +233,31 @@ sysmon_task_queue_sched(u_int pri, void 
 
 	return 0;
 }
+
+static
+int   
+sysmon_taskq_modcmd(modcmd_t cmd, void *arg)
+{
+	int ret;
+ 
+	switch (cmd) { 
+	case MODULE_CMD_INIT:
+#ifdef _MODULE
+		sysmon_task_queue_preinit();
+#endif
+		sysmon_task_queue_init();
+		ret = 0;
+		break;
+ 
+	case MODULE_CMD_FINI: 
+		sysmon_task_queue_fini();
+		ret = 0;
+		break;
+ 
+	case MODULE_CMD_STAT:
+	default: 
+		ret = ENOTTY;
+	}
+ 
+	return ret;
+}

Index: src/sys/dev/sysmon/sysmon_wdog.c
diff -u src/sys/dev/sysmon/sysmon_wdog.c:1.25 src/sys/dev/sysmon/sysmon_wdog.c:1.26
--- src/sys/dev/sysmon/sysmon_wdog.c:1.25	Tue Jan  4 01:51:06 2011
+++ src/sys/dev/sysmon/sysmon_wdog.c	Thu Apr 23 23:22:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysmon_wdog.c,v 1.25 2011/01/04 01:51:06 matt Exp $	*/
+/*	$NetBSD: sysmon_wdog.c,v 1.26 2015/04/23 23:22:03 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2000 Zembu Labs, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.c,v 1.25 2011/01/04 01:51:06 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.c,v 1.26 2015/04/23 23:22:03 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -53,6 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.
 #include <sys/kernel.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
+#include <sys/module.h>
 
 #include <dev/sysmon/sysmonvar.h>
 
@@ -74,9 +75,18 @@ void	sysmon_wdog_critpoll(void *);
 void	sysmon_wdog_shutdown(void *);
 void	sysmon_wdog_ref(struct sysmon_wdog *);
 
-void
+static struct sysmon_opvec sysmon_wdog_opvec = {    
+        sysmonopen_wdog, sysmonclose_wdog, sysmonioctl_wdog,
+        NULL, NULL, NULL
+};
+
+MODULE(MODULE_CLASS_MISC, sysmon_wdog, "sysmon");
+
+int
 sysmon_wdog_init(void)
 {
+	int error;
+
 	mutex_init(&sysmon_wdog_list_mtx, MUTEX_DEFAULT, IPL_NONE);
 	mutex_init(&sysmon_wdog_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
 	cv_init(&sysmon_wdog_cv, "wdogref");
@@ -87,6 +97,32 @@ sysmon_wdog_init(void)
 	if (sysmon_wdog_cphook == NULL)
 		printf("WARNING: unable to register watchdog critpoll hook\n");
 	callout_init(&sysmon_wdog_callout, 0);
+
+	error = sysmon_attach_minor(SYSMON_MINOR_WDOG, &sysmon_wdog_opvec);
+
+	return error;
+}
+
+int
+sysmon_wdog_fini(void)
+{
+	int error;
+
+	if ( ! LIST_EMPTY(&sysmon_wdog_list))
+		return EBUSY;
+
+	error = sysmon_attach_minor(SYSMON_MINOR_WDOG, NULL);
+
+	if (error == 0) {
+		callout_destroy(&sysmon_wdog_callout);
+		critpollhook_disestablish(sysmon_wdog_cphook);
+		shutdownhook_disestablish(sysmon_wdog_sdhook);
+		cv_destroy(&sysmon_wdog_cv);
+		mutex_destroy(&sysmon_wdog_mtx);
+		mutex_destroy(&sysmon_wdog_list_mtx);
+	}
+
+	return error;
 }
 
 /*
@@ -500,3 +536,25 @@ sysmon_wdog_shutdown(void *arg)
 			    smw->smw_name);
 	}
 }
+static
+int   
+sysmon_wdog_modcmd(modcmd_t cmd, void *arg)
+{
+        int ret;
+  
+        switch (cmd) {
+        case MODULE_CMD_INIT:
+                ret = sysmon_wdog_init();
+                break;
+ 
+        case MODULE_CMD_FINI:
+                ret = sysmon_wdog_fini();
+                break; 
+   
+        case MODULE_CMD_STAT:
+        default:
+                ret = ENOTTY;
+        }
+  
+        return ret; 
+}

Index: src/sys/dev/sysmon/sysmonvar.h
diff -u src/sys/dev/sysmon/sysmonvar.h:1.48 src/sys/dev/sysmon/sysmonvar.h:1.49
--- src/sys/dev/sysmon/sysmonvar.h:1.48	Sat Apr 18 14:44:44 2015
+++ src/sys/dev/sysmon/sysmonvar.h	Thu Apr 23 23:22:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysmonvar.h,v 1.48 2015/04/18 14:44:44 mlelstv Exp $	*/
+/*	$NetBSD: sysmonvar.h,v 1.49 2015/04/23 23:22:03 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2000 Zembu Labs, Inc.
@@ -242,7 +242,8 @@ void	sysmon_envsys_foreach_sensor(sysmon
 
 int	sysmon_envsys_update_limits(struct sysmon_envsys *, envsys_data_t *);
 
-void	sysmon_envsys_init(void);
+int	sysmon_envsys_init(void);
+int	sysmon_envsys_fini(void);
 
 /*****************************************************************************
  * Watchdog timer support
@@ -270,7 +271,8 @@ int     sysmon_wdog_setmode(struct sysmo
 int     sysmon_wdog_register(struct sysmon_wdog *);
 int     sysmon_wdog_unregister(struct sysmon_wdog *);
 
-void	sysmon_wdog_init(void);
+int	sysmon_wdog_init(void);
+int	sysmon_wdog_fini(void);
 
 /*****************************************************************************
  * Power management support
@@ -298,6 +300,23 @@ void	sysmon_pswitch_unregister(struct sy
 void	sysmon_pswitch_event(struct sysmon_pswitch *, int);
 void	sysmon_penvsys_event(struct penvsys_state *, int);
 
-void	sysmon_power_init(void);
+int	sysmon_power_init(void);
+int	sysmon_power_fini(void);
+
+/*
+ * Interface to sysmon common code used for autoloading
+ */
+struct sysmon_opvec {
+	int (*so_open)(dev_t, int, int, struct lwp*);
+	int (*so_close)(dev_t, int, int, struct lwp*);
+	int (*so_ioctl)(dev_t, u_long, void *, int, struct lwp*);
+	int (*so_read)(dev_t, struct uio*, int);
+	int (*so_poll)(dev_t, int, struct lwp*);
+	int (*so_filter)(dev_t, struct knote*);
+};
+
+int	sysmon_init(void);
+int	sysmon_fini(void);
+int	sysmon_attach_minor(int, struct sysmon_opvec*);
 
 #endif /* _DEV_SYSMON_SYSMONVAR_H_ */

Reply via email to