Module Name: src
Committed By: pgoyette
Date: Sat Jul 16 22:06:42 UTC 2016
Modified Files:
src/sys/kern [pgoyette-localcount]: subr_autoconf.c
src/sys/sys [pgoyette-localcount]: device.h
Log Message:
Add new xxx_acquire variants for device_lookup_private() and
device_find_by_driver_unit_acquire rather than blindly making the old
variants call localcount_acquire().
Also fix a couple of locking sequences.
Thanks to Taylor for the review!
To generate a diff of this commit:
cvs rdiff -u -r1.246.2.1 -r1.246.2.2 src/sys/kern/subr_autoconf.c
cvs rdiff -u -r1.149.2.1 -r1.149.2.2 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.2.1 src/sys/kern/subr_autoconf.c:1.246.2.2
--- src/sys/kern/subr_autoconf.c:1.246.2.1 Sat Jul 16 02:13:07 2016
+++ src/sys/kern/subr_autoconf.c Sat Jul 16 22:06:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.246.2.1 2016/07/16 02:13:07 pgoyette Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.246.2.2 2016/07/16 22:06:42 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.2.1 2016/07/16 02:13:07 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.246.2.2 2016/07/16 22:06:42 pgoyette Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -1257,9 +1257,6 @@ 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);
@@ -1267,6 +1264,10 @@ config_devunlink(device_t dev, struct de
/* Remove from cfdriver's array. */
cd->cd_devs[dev->dv_unit] = NULL;
+ /* Now wait for references to drain - no new refs are possible */
+ localcount_drain(dev->dv_localcnt, &config_drain_cv,
+ &alldevs_mtx);
+
/*
* If the device now has no units in use, unlink its softc array.
*/
@@ -2265,9 +2266,15 @@ device_lookup_acquire(cfdriver_t cd, int
{
device_t dv;
- dv = device_lookup(cd, unit);
- if (dv != NULL)
+ mutex_enter(&alldevs_mtx);
+ if (unit < 0 || unit >= cd->cd_ndevs)
+ dv = NULL;
+ else if ((dv = cd->cd_devs[unit]) != NULL && dv->dv_del_gen != 0)
+ dv = NULL;
+ else
localcount_acquire(dv->dv_localcnt);
+ mutex_exit(&alldevs_mtx);
+
return dv;
}
@@ -2294,6 +2301,19 @@ void *
device_lookup_private(cfdriver_t cd, int unit)
{
+ return device_private(device_lookup(cd, unit));
+}
+
+/*
+ * device_lookup_private_acquire:
+ *
+ * Look up the softc and acquire a reference to the device
+ * so it won't disappear.
+ */
+void *
+device_lookup_private_acquire(cfdriver_t cd, int unit)
+{
+
return device_private(device_lookup_acquire(cd, unit));
}
@@ -2330,6 +2350,23 @@ device_find_by_driver_unit(const char *n
if ((cd = config_cfdriver_lookup(name)) == NULL)
return NULL;
+ return device_lookup(cd, unit);
+}
+
+/*
+ * device_find_by_driver_unit_acquire:
+ *
+ * Returns the device of the given driver name and unit or
+ * NULL if it doesn't exist. If driver is found, it's
+ * reference count is incremented so it won't go away.
+ */
+device_t
+device_find_by_driver_unit_acquire(const char *name, int unit)
+{
+ struct cfdriver *cd;
+
+ if ((cd = config_cfdriver_lookup(name)) == NULL)
+ return NULL;
return device_lookup_acquire(cd, unit);
}
Index: src/sys/sys/device.h
diff -u src/sys/sys/device.h:1.149.2.1 src/sys/sys/device.h:1.149.2.2
--- src/sys/sys/device.h:1.149.2.1 Sat Jul 16 02:13:08 2016
+++ src/sys/sys/device.h Sat Jul 16 22:06:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: device.h,v 1.149.2.1 2016/07/16 02:13:08 pgoyette Exp $ */
+/* $NetBSD: device.h,v 1.149.2.2 2016/07/16 22:06:42 pgoyette Exp $ */
/*
* Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -493,6 +493,7 @@ 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_lookup_private_acquire(cfdriver_t, int);
void device_register(device_t, void *);
void device_register_post_config(device_t, void *);
@@ -526,6 +527,7 @@ bool device_is_a(device_t, const char *
device_t device_find_by_xname(const char *);
device_t device_find_by_driver_unit(const char *, int);
+device_t device_find_by_driver_unit_acquire(const char *, int);
bool device_pmf_is_registered(device_t);