summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_bus.c
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2000-04-08 14:17:18 +0000
committerdfr <dfr@FreeBSD.org>2000-04-08 14:17:18 +0000
commitc9bf4be3c29d14ce9b4af20459517870eed8bce9 (patch)
treeb0ea9aab688814aec913835039451900941b1619 /sys/kern/subr_bus.c
parent2d18287eb4e48e437d5e7a756df6f20a59c7e176 (diff)
downloadFreeBSD-src-c9bf4be3c29d14ce9b4af20459517870eed8bce9.zip
FreeBSD-src-c9bf4be3c29d14ce9b4af20459517870eed8bce9.tar.gz
* Factor out the object system from new-bus so that it can be used by
non-device code. * Re-implement the method dispatch to improve efficiency. The new system takes about 40ns for a method dispatch on a 300Mhz PII which is only 10ns slower than a direct function call on the same hardware. This changes the new-bus ABI slightly so make sure you re-compile any driver modules which you use.
Diffstat (limited to 'sys/kern/subr_bus.c')
-rw-r--r--sys/kern/subr_bus.c220
1 files changed, 26 insertions, 194 deletions
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 7492a4b..dbcf4ee 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -36,6 +36,7 @@
#ifdef DEVICE_SYSCTLS
#include <sys/sysctl.h>
#endif
+#include <sys/kobj.h>
#include <sys/bus_private.h>
#include <sys/systm.h>
#include <machine/bus.h>
@@ -56,7 +57,6 @@ MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
#define indentprintf(p) do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf(" "); printf p ; } while(0)
static void print_method_list(device_method_t *m, int indent);
-static void print_device_ops(device_ops_t ops, int indent);
static void print_device_short(device_t dev, int indent);
static void print_device(device_t dev, int indent);
void print_device_tree_short(device_t dev, int indent);
@@ -77,7 +77,6 @@ void print_devclass_list(void);
#define DEVCLANAME(d) /* nop */
#define print_method_list(m,i) /* nop */
-#define print_device_ops(o,i) /* nop */
#define print_device_short(d,i) /* nop */
#define print_device(d,i) /* nop */
#define print_device_tree_short(d,i) /* nop */
@@ -96,146 +95,11 @@ static void device_register_oids(device_t dev);
static void device_unregister_oids(device_t dev);
#endif
-/*
- * Method table handling
- */
-static int error_method(void);
-static int next_method_offset = 1;
-
-LIST_HEAD(methodlist, method) methods;
-struct method {
- LIST_ENTRY(method) link; /* linked list of methods */
- int offset; /* offset in method table */
- int refs; /* count of device_op_desc users */
- devop_t deflt; /* default implementation */
- char* name; /* unique name of method */
+kobj_method_t null_methods[] = {
+ { 0, 0 }
};
-static void
-register_method(struct device_op_desc *desc)
-{
- struct method* m;
-
- if (desc->method) {
- desc->method->refs++;
- return;
- }
-
- /*
- * Make sure that desc->deflt is always valid to simplify dispatch.
- */
- if (!desc->deflt)
- desc->deflt = error_method;
-
- for (m = LIST_FIRST(&methods); m; m = LIST_NEXT(m, link)) {
- if (!strcmp(m->name, desc->name)) {
- desc->offset = m->offset;
- desc->method = m;
- m->refs++;
- PDEBUG(("method %p has the same name, %s, with offset %d",
- (void *)m, desc->name, desc->offset));
- return;
- }
- }
-
- m = (struct method *) malloc(sizeof(struct method)
- + strlen(desc->name) + 1,
- M_BUS, M_NOWAIT);
- if (!m)
- panic("register_method: out of memory");
- bzero(m, sizeof(struct method) + strlen(desc->name) + 1);
- m->offset = next_method_offset++;
- m->refs = 1;
- m->deflt = desc->deflt;
- m->name = (char*) (m + 1);
- strcpy(m->name, desc->name);
- LIST_INSERT_HEAD(&methods, m, link);
-
- desc->offset = m->offset;
- desc->method = m;
-}
-
-static void
-unregister_method(struct device_op_desc *desc)
-{
- struct method *m = desc->method;
- m->refs--;
- if (m->refs == 0) {
- PDEBUG(("method %s, reached refcount 0", desc->name));
- LIST_REMOVE(m, link);
- free(m, M_BUS);
- desc->method = 0;
- }
-}
-
-static int error_method(void)
-{
- return ENXIO;
-}
-
-static struct device_ops null_ops = {
- 1,
- { error_method }
-};
-
-static void
-compile_methods(driver_t *driver)
-{
- device_ops_t ops;
- struct device_method *m;
- struct method *cm;
- int i;
-
- /*
- * First register any methods which need it.
- */
- for (i = 0, m = driver->methods; m->desc; i++, m++)
- register_method(m->desc);
-
- /*
- * Then allocate the compiled op table.
- */
- ops = malloc(sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t),
- M_BUS, M_NOWAIT);
- if (!ops)
- panic("compile_methods: out of memory");
- bzero(ops, sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t));
-
- ops->maxoffset = next_method_offset;
- /* Fill in default methods and then overwrite with driver methods */
- for (i = 0; i < next_method_offset; i++)
- ops->methods[i] = error_method;
- for (cm = LIST_FIRST(&methods); cm; cm = LIST_NEXT(cm, link)) {
- if (cm->deflt)
- ops->methods[cm->offset] = cm->deflt;
- }
- for (i = 0, m = driver->methods; m->desc; i++, m++)
- ops->methods[m->desc->offset] = m->func;
- PDEBUG(("%s has %d method%s, wasting %d bytes",
- DRIVERNAME(driver), i, (i==1?"":"s"),
- (next_method_offset-i)*sizeof(devop_t)));
-
- driver->ops = ops;
-}
-
-static void
-free_methods(driver_t *driver)
-{
- int i;
- struct device_method *m;
-
- /*
- * Unregister any methods which are no longer used.
- */
- for (i = 0, m = driver->methods; m->desc; i++, m++)
- unregister_method(m->desc);
-
- /*
- * Free memory and clean up.
- */
- free(driver->ops, M_BUS);
- driver->ops = 0;
-}
+DEFINE_CLASS(null, null_methods, 0);
/*
* Devclass implementation
@@ -302,8 +166,7 @@ devclass_add_driver(devclass_t dc, driver_t *driver)
/*
* Compile the driver's methods.
*/
- if (!driver->ops)
- compile_methods(driver);
+ kobj_class_compile((kobj_class_t) driver);
/*
* Make sure the devclass which the driver is implementing exists.
@@ -379,7 +242,7 @@ devclass_delete_driver(devclass_t busclass, driver_t *driver)
driver->refs--;
if (driver->refs == 0)
- free_methods(driver);
+ kobj_class_free((kobj_class_t) driver);
return 0;
}
@@ -609,7 +472,7 @@ make_device(device_t parent, const char *name, int unit)
dev->parent = parent;
TAILQ_INIT(&dev->children);
- dev->ops = &null_ops;
+ kobj_init((kobj_t) dev, &null_class);
dev->driver = NULL;
dev->devclass = NULL;
dev->unit = unit;
@@ -630,6 +493,8 @@ make_device(device_t parent, const char *name, int unit)
dev->state = DS_NOTPRESENT;
+ kobj_init((kobj_t) dev, &null_class);
+
return dev;
}
@@ -1112,18 +977,19 @@ device_set_driver(device_t dev, driver_t *driver)
free(dev->softc, M_BUS);
dev->softc = NULL;
}
- dev->ops = &null_ops;
+ kobj_delete((kobj_t) dev, 0);
dev->driver = driver;
if (driver) {
- dev->ops = driver->ops;
- dev->softc = malloc(driver->softc, M_BUS, M_NOWAIT);
+ kobj_init((kobj_t) dev, (kobj_class_t) driver);
+ dev->softc = malloc(driver->size, M_BUS, M_NOWAIT);
if (!dev->softc) {
- dev->ops = &null_ops;
+ kobj_init((kobj_t) dev, &null_class);
dev->driver = NULL;
return ENOMEM;
}
- bzero(dev->softc, driver->softc);
- }
+ bzero(dev->softc, driver->size);
+ } else
+ kobj_init((kobj_t) dev, &null_class);
return 0;
}
@@ -2180,17 +2046,17 @@ root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg,
panic("root_setup_intr");
}
-static device_method_t root_methods[] = {
+static kobj_method_t root_methods[] = {
/* Device interface */
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
+ KOBJMETHOD(device_shutdown, bus_generic_shutdown),
+ KOBJMETHOD(device_suspend, bus_generic_suspend),
+ KOBJMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, root_print_child),
- DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
- DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
- DEVMETHOD(bus_setup_intr, root_setup_intr),
+ KOBJMETHOD(bus_print_child, root_print_child),
+ KOBJMETHOD(bus_read_ivar, bus_generic_read_ivar),
+ KOBJMETHOD(bus_write_ivar, bus_generic_write_ivar),
+ KOBJMETHOD(bus_setup_intr, root_setup_intr),
{ 0, 0 }
};
@@ -2209,10 +2075,10 @@ root_bus_module_handler(module_t mod, int what, void* arg)
{
switch (what) {
case MOD_LOAD:
- compile_methods(&root_driver);
+ kobj_class_compile((kobj_class_t) &root_driver);
root_bus = make_device(NULL, "root", 0);
root_bus->desc = "System root bus";
- root_bus->ops = root_driver.ops;
+ kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
root_bus->driver = &root_driver;
root_bus->state = DS_ATTACHED;
root_devclass = devclass_find_internal("root", FALSE);
@@ -2318,36 +2184,6 @@ print_method_list(device_method_t *m, int indent)
}
static void
-print_device_ops(device_ops_t ops, int indent)
-{
- int i;
- int count = 0;
-
- if (!ops)
- return;
-
- /* we present a list of the methods that are pointing to the
- * error_method, but ignore the 0'th elements; it is always
- * error_method.
- */
- for (i = 1; i < ops->maxoffset; i++) {
- if (ops->methods[i] == error_method) {
- if (count == 0)
- indentprintf(("error_method:"));
- printf(" %d", i);
- count++;
- }
- }
- if (count)
- printf("\n");
-
- indentprintf(("(%d method%s, %d valid, %d error_method%s)\n",
- ops->maxoffset-1, (ops->maxoffset-1 == 1? "":"s"),
- ops->maxoffset-1-count,
- count, (count == 1? "":"'s")));
-}
-
-static void
print_device_short(device_t dev, int indent)
{
if (!dev)
@@ -2376,8 +2212,6 @@ print_device(device_t dev, int indent)
indentprintf(("Parent:\n"));
print_device_short(dev->parent, indent+1);
- indentprintf(("Methods:\n"));
- print_device_ops(dev->ops, indent+1);
indentprintf(("Driver:\n"));
print_driver_short(dev->driver, indent+1);
indentprintf(("Devclass:\n"));
@@ -2435,8 +2269,6 @@ print_driver(driver_t *driver, int indent)
print_driver_short(driver, indent);
indentprintf(("Methods:\n"));
print_method_list(driver->methods, indent+1);
- indentprintf(("Operations:\n"));
- print_device_ops(driver->ops, indent+1);
}
OpenPOWER on IntegriCloud