Module Name:    src
Committed By:   pgoyette
Date:           Sat Jul 16 02:13:08 UTC 2016

Modified Files:
        src/sys/kern [pgoyette-localcount]: subr_autoconf.c
        src/sys/sys [pgoyette-localcount]: device.h

Log Message:
Initial set of changes for subr_autoconf usage of localcount mechanism.

Nothing actually uses this yet - all callers of device_lookup() need
conversion to device_lookup_acquire()/device_release().  This also
means that callers of device_lookup_private() need to be modified to
call device_release() when finished accessing the softc.

XXX Perhaps device_lookup_private() should be removed, and all callers
XXX modified to use device_lookup_acquire()/.../device_release()?


To generate a diff of this commit:
cvs rdiff -u -r1.246 -r1.246.2.1 src/sys/kern/subr_autoconf.c
cvs rdiff -u -r1.149 -r1.149.2.1 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/subr_autoconf.c
diff -u src/sys/kern/subr_autoconf.c:1.246 src/sys/kern/subr_autoconf.c:1.246.2.1
--- src/sys/kern/subr_autoconf.c:1.246	Fri Jul 15 01:17:47 2016
+++ src/sys/kern/subr_autoconf.c	Sat Jul 16 02:13:07 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.246 2016/07/15 01:17:47 pgoyette Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.246.2.1 2016/07/16 02:13:07 pgoyette 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.246 2016/07/15 01:17:47 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.246.2.1 2016/07/16 02:13:07 pgoyette Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -107,6 +107,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_autocon
 #include <sys/devmon.h>
 #include <sys/cpu.h>
 #include <sys/sysctl.h>
+#include <sys/localcount.h>
 
 #include <sys/disk.h>
 
@@ -227,6 +228,7 @@ static volatile int alldevs_nwrite = 0;
 static int config_pending;		/* semaphore for mountroot */
 static kmutex_t config_misc_lock;
 static kcondvar_t config_misc_cv;
+static kcondvar_t config_drain_cv;
 
 static bool detachall = false;
 
@@ -345,6 +347,7 @@ config_init(void)
 
 	mutex_init(&config_misc_lock, MUTEX_DEFAULT, IPL_NONE);
 	cv_init(&config_misc_cv, "cfgmisc");
+	cv_init(&config_drain_cv, "cfgdrain");
 
 	callout_init(&config_twiddle_ch, CALLOUT_MPSAFE);
 
@@ -567,7 +570,6 @@ config_cfdriver_attach(struct cfdriver *
 		if (STREQ(lcd->cd_name, cd->cd_name))
 			return EEXIST;
 	}
-
 	LIST_INIT(&cd->cd_attach);
 	LIST_INSERT_HEAD(&allcfdrivers, cd, cd_list);
 
@@ -592,7 +594,6 @@ config_cfdriver_detach(struct cfdriver *
 		}
 	}
 	config_alldevs_exit(&af);
-
 	if (rc != 0)
 		return rc;
 
@@ -1236,6 +1237,8 @@ config_devfree(device_t dev)
 {
 	int priv = (dev->dv_flags & DVF_PRIV_ALLOC);
 
+	if (dev->dv_localcnt != NULL)
+		localcount_fini(dev->dv_localcnt);
 	if (dev->dv_cfattach->ca_devsize > 0)
 		kmem_free(dev->dv_private, dev->dv_cfattach->ca_devsize);
 	if (priv)
@@ -1254,6 +1257,9 @@ config_devunlink(device_t dev, struct de
 
 	KASSERT(mutex_owned(&alldevs_mtx));
 
+	localcount_drain(dev->dv_localcnt, &config_drain_cv,
+	    &alldevs_mtx);
+
  	/* Unlink from device list.  Link to garbage list. */
 	TAILQ_REMOVE(&alldevs, dev, dv_list);
 	TAILQ_INSERT_TAIL(garbage, dev, dv_list);
@@ -1392,8 +1398,8 @@ config_devalloc(const device_t parent, c
 		printf("%s has not been converted to device_t\n", cd->cd_name);
 #endif
 	}
-	if (dev == NULL)
-		panic("config_devalloc: memory allocation for device_t failed");
+	KASSERTMSG(dev, "%s: memory allocation for %s device_t failed",
+	    __func__, cd->cd_name);
 
 	dev->dv_class = cd->cd_class;
 	dev->dv_cfdata = cf;
@@ -1403,6 +1409,10 @@ config_devalloc(const device_t parent, c
 	dev->dv_activity_handlers = NULL;
 	dev->dv_private = dev_private;
 	dev->dv_flags = ca->ca_flags;	/* inherit flags from class */
+	dev->dv_localcnt = kmem_alloc(sizeof(*dev->dv_localcnt), KM_SLEEP);
+	KASSERTMSG(dev->dv_localcnt, "%s: unable to allocate localcnt for %s",
+	    __func__, cd->cd_name);
+	localcount_init(dev->dv_localcnt);
 
 	myunit = config_unit_alloc(dev, cd, cf);
 	if (myunit == -1) {
@@ -2245,6 +2255,37 @@ device_lookup(cfdriver_t cd, int unit)
 }
 
 /*
+ * device_lookup_accquire:
+ *
+ *	Look up a device instance for a given driver and
+ *	hold a reference to the device.
+ */
+device_t
+device_lookup_acquire(cfdriver_t cd, int unit)
+{
+	device_t dv;
+
+	dv = device_lookup(cd, unit);
+	if (dv != NULL)
+		localcount_acquire(dv->dv_localcnt);
+	return dv;
+}
+
+/*
+ * device_release:
+ *
+ *	Release the reference that was created by an earlier call to
+ *	device_lookup_acquire().
+ */
+void
+device_release(device_t dv)
+{
+
+	localcount_release(dv->dv_localcnt, &config_drain_cv,
+	    &alldevs_mtx);
+}
+
+/*
  * device_lookup_private:
  *
  *	Look up a softc instance for a given driver.
@@ -2253,7 +2294,7 @@ void *
 device_lookup_private(cfdriver_t cd, int unit)
 {
 
-	return device_private(device_lookup(cd, unit));
+	return device_private(device_lookup_acquire(cd, unit));
 }
 
 /*
@@ -2289,7 +2330,7 @@ device_find_by_driver_unit(const char *n
 
 	if ((cd = config_cfdriver_lookup(name)) == NULL)
 		return NULL;
-	return device_lookup(cd, unit);
+	return device_lookup_acquire(cd, unit);
 }
 
 /*

Index: src/sys/sys/device.h
diff -u src/sys/sys/device.h:1.149 src/sys/sys/device.h:1.149.2.1
--- src/sys/sys/device.h:1.149	Sun Jun 19 09:35:06 2016
+++ src/sys/sys/device.h	Sat Jul 16 02:13:08 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: device.h,v 1.149 2016/06/19 09:35:06 bouyer Exp $ */
+/* $NetBSD: device.h,v 1.149.2.1 2016/07/16 02:13:08 pgoyette Exp $ */
 
 /*
  * Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -188,6 +188,7 @@ struct device {
 	    *dv_driver_suspensors[DEVICE_SUSPENSORS_MAX],
 	    *dv_class_suspensors[DEVICE_SUSPENSORS_MAX];
 	struct device_garbage dv_garbage;
+	struct localcount *dv_localcnt;	/* reference counter */
 };
 
 /* dv_flags */
@@ -489,6 +490,8 @@ void	config_twiddle_fn(void *);
 void	null_childdetached(device_t, device_t);
 
 device_t	device_lookup(cfdriver_t, int);
+device_t	device_lookup_acquire(cfdriver_t, int);
+void		device_release(device_t);
 void		*device_lookup_private(cfdriver_t, int);
 void		device_register(device_t, void *);
 void		device_register_post_config(device_t, void *);

Reply via email to