PERFORCE change 121867 for review
Scott Long
scottl at FreeBSD.org
Sun Jun 17 18:56:13 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=121867
Change 121867 by scottl at scottl-x64 on 2007/06/17 18:55:17
initial, incomplete whack at newbus locking.
Affected files ...
.. //depot/projects/scottl-camlock/src/sys/kern/subr_bus.c#12 edit
Differences ...
==== //depot/projects/scottl-camlock/src/sys/kern/subr_bus.c#12 (text+ko) ====
@@ -74,6 +74,7 @@
typedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t;
typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t;
typedef TAILQ_HEAD(device_list, device) device_list_t;
+struct mtx newbus_lock;
struct devclass {
TAILQ_ENTRY(devclass) link;
@@ -736,6 +737,7 @@
*/
static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
+MTX_SYSINIT(newbus_lock, &newbus_lock, "Newbus internal lock", MTX_DEF);
/**
@@ -759,6 +761,8 @@
{
devclass_t dc;
+ mtx_assert(&newbus_lock, MA_OWNED);
+
PDEBUG(("looking for %s", classname));
if (!classname)
return (NULL);
@@ -810,7 +814,12 @@
devclass_t
devclass_create(const char *classname)
{
- return (devclass_find_internal(classname, NULL, TRUE));
+ devclass_t dc;
+
+ mtx_lock(&newbus_lock);
+ dc = devclass_find_internal(classname, NULL, TRUE);
+ mtx_unlock(&newbus_lock);
+ return (dc);
}
/**
@@ -824,7 +833,12 @@
devclass_t
devclass_find(const char *classname)
{
- return (devclass_find_internal(classname, NULL, FALSE));
+ devclass_t dc;
+
+ mtx_lock(&newbus_lock);
+ dc = devclass_find_internal(classname, NULL, FALSE);
+ mtx_lock(&newbus_lock);
+ return (dc);
}
/**
@@ -861,6 +875,7 @@
/*
* Make sure the devclass which the driver is implementing exists.
*/
+ mtx_lock(&newbus_lock);
devclass_find_internal(driver->name, NULL, TRUE);
dl->driver = driver;
@@ -871,10 +886,16 @@
* Call BUS_DRIVER_ADDED for any existing busses in this class.
*/
for (i = 0; i < dc->maxunit; i++)
- if (dc->devices[i])
+ if (dc->devices[i]) {
+ /* XXX UNSAFE */
+ mtx_unlock(&newbus_lock);
BUS_DRIVER_ADDED(dc->devices[i], driver);
+ mtx_lock(&newbus_lock);
+ }
+ }
bus_data_generation_update();
+ mtx_unlock(&newbus_lock);
return (0);
}
@@ -909,6 +930,7 @@
/*
* Find the link structure in the bus' list of drivers.
*/
+ mtx_lock(&newbus_lock);
TAILQ_FOREACH(dl, &busclass->drivers, link) {
if (dl->driver == driver)
break;
@@ -917,8 +939,10 @@
if (!dl) {
PDEBUG(("%s not found in %s list", driver->name,
busclass->name));
+ mtx_unlock(&newbus_lock);
return (ENOENT);
}
+ TAILQ_REMOVE(&busclass->drivers, dl, link);
/*
* Disassociate from any devices. We iterate through all the
@@ -935,14 +959,16 @@
dev = dc->devices[i];
if (dev->driver == driver && dev->parent &&
dev->parent->devclass == busclass) {
+ /* XXX UNSAFE */
+ mtx_unlock(&newbus_lock);
if ((error = device_detach(dev)) != 0)
return (error);
device_set_driver(dev, NULL);
+ mtx_lock(&newbus_lock);
}
}
}
- TAILQ_REMOVE(&busclass->drivers, dl, link);
free(dl, M_BUS);
/* XXX: kobj_mtx */
@@ -951,6 +977,7 @@
kobj_class_free((kobj_class_t) driver);
bus_data_generation_update();
+ mtx_unlock(&newbus_lock);
return (0);
}
@@ -984,6 +1011,7 @@
/*
* Find the link structure in the bus' list of drivers.
*/
+ mtx_lock(&newbus_lock);
TAILQ_FOREACH(dl, &busclass->drivers, link) {
if (dl->driver == driver)
break;
@@ -992,6 +1020,7 @@
if (!dl) {
PDEBUG(("%s not found in %s list", driver->name,
busclass->name));
+ mtx_unlock(&newbus_lock);
return (ENOENT);
}
@@ -1010,12 +1039,16 @@
dev = dc->devices[i];
if (dev->driver == driver && dev->parent &&
dev->parent->devclass == busclass) {
+ /* XXX UNSAFE */
+ mtx_unlock(&newbus_lock);
if ((error = device_quiesce(dev)) != 0)
return (error);
+ mtx_lock(&newbus_lock);
}
}
}
+ mtx_unlock(&newbus_lock);
return (0);
}
@@ -1051,12 +1084,15 @@
kobj_class_t
devclass_find_driver(devclass_t dc, const char *classname)
{
+ kobj_class_t kc = NULL;
driverlink_t dl;
+ mtx_lock(&newbus_lock);
dl = devclass_find_driver_internal(dc, classname);
if (dl)
- return (dl->driver);
- return (NULL);
+ kc = dl->driver;
+ mtx_unlock(&newbus_lock);
+ return (kc);
}
/**
@@ -1697,8 +1733,7 @@
int result, pri = 0;
int hasclass = (child->devclass != 0);
- GIANT_REQUIRED;
-
+ mtx_lock(&newbus_lock);
dc = dev->devclass;
if (!dc)
panic("device_probe_child: parent device has no devclass");
@@ -1707,8 +1742,10 @@
* If the state is already probed, then return. However, don't
* return if we can rebid this object.
*/
- if (child->state == DS_ALIVE && (child->flags & DF_REBID) == 0)
+ if (child->state == DS_ALIVE && (child->flags & DF_REBID) == 0) {
+ mtx_unlock(&newbus_lock);
return (0);
+ }
for (; dc; dc = dc->parent) {
for (dl = first_matching_driver(dc, child);
@@ -1723,7 +1760,10 @@
resource_int_value(dl->driver->name, child->unit,
"flags", &child->devflags);
+ /* XXX UNSAFE */
+ mtx_unlock(&newbus_lock);
result = DEVICE_PROBE(child);
+ mtx_lock(&newbus_lock);
/* Reset flags and devclass before the next probe. */
child->devflags = 0;
@@ -1815,9 +1855,11 @@
child->state = DS_ALIVE;
bus_data_generation_update();
+ mtx_unlock(&newbus_lock);
return (0);
}
+ mtx_unlock(&newbus_lock);
return (ENXIO);
}
@@ -1854,13 +1896,16 @@
device_t *list;
count = 0;
+ mtx_lock(&newbus_lock);
TAILQ_FOREACH(child, &dev->children, link) {
count++;
}
list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT|M_ZERO);
- if (!list)
+ if (!list) {
+ mtx_unlock(&newbus_lock);
return (ENOMEM);
+ }
count = 0;
TAILQ_FOREACH(child, &dev->children, link) {
@@ -1870,6 +1915,7 @@
*devlistp = list;
*devcountp = count;
+ mtx_unlock(&newbus_lock);
return (0);
}
@@ -2230,24 +2276,30 @@
devclass_t dc;
int error;
+ mtx_lock(&newbus_lock);
if (!classname) {
if (dev->devclass)
devclass_delete_device(dev->devclass, dev);
+ mtx_unlock(&newbus_lock);
return (0);
}
if (dev->devclass) {
printf("device_set_devclass: device class already set\n");
+ mtx_unlock(&newbus_lock);
return (EINVAL);
}
dc = devclass_find_internal(classname, NULL, TRUE);
- if (!dc)
+ if (!dc) {
+ mtx_unlock(&newbus_lock);
return (ENOMEM);
+ }
error = devclass_add_device(dc, dev);
bus_data_generation_update();
+ mtx_unlock(&newbus_lock);
return (error);
}
@@ -3729,7 +3781,9 @@
kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
root_bus->driver = &root_driver;
root_bus->state = DS_ATTACHED;
+ mtx_lock(&newbus_lock);
root_devclass = devclass_find_internal("root", NULL, FALSE);
+ mtx_unlock(&newbus_lock);
devinit();
return (0);
@@ -3785,7 +3839,9 @@
kobj_class_t driver;
dmd = (struct driver_module_data *)arg;
+ mtx_lock(&newbus_lock);
bus_devclass = devclass_find_internal(dmd->dmd_busname, NULL, TRUE);
+ mtx_unlock(&newbus_lock);
error = 0;
switch (what) {
@@ -3807,6 +3863,7 @@
* search for drivers in both devclasses for children
* of a device using this driver.
*/
+ mtx_lock(&newbus_lock);
if (driver->baseclasses) {
const char *parentname;
parentname = driver->baseclasses[0]->name;
@@ -3817,6 +3874,7 @@
*dmd->dmd_devclass =
devclass_find_internal(driver->name, NULL, TRUE);
}
+ mtx_unlock(&newbus_lock);
break;
case MOD_UNLOAD:
More information about the p4-projects
mailing list