diff options
| author | Patrick Mochel <mochel@osdl.org> | 2002-10-29 19:47:41 -0800 |
|---|---|---|
| committer | Patrick Mochel <mochel@osdl.org> | 2002-10-29 19:47:41 -0800 |
| commit | a6c066de9d449b0bbe2efbf6431b19c270e02060 (patch) | |
| tree | 1039c0c2a45cfd11703ff3d4347e2becd2331627 /lib | |
| parent | 0862416ecefa629a52f3ee0907206e9633ca45c3 (diff) | |
Introduce struct subsystem.
A struct subsystem is basically a collection of objects of a certain type,
and some callbacks to operate on objects of that type.
subsystems contain embedded kobjects themselves, and have a similar set of
library routines that kobjects do, which are mostly just wrappers for the
correlating kobject routines.
kobjects are inserted in depth-first order into their subsystem's list of
objects. Orphan kobjects are also given foster parents that point to their
subsystem. This provides a bit more rigidity in the hierarchy, and disallows
any orphan kobjects.
When an object is unregistered, it is removed from its subsystem's list. When
the objects' refcount hits 0, the subsystem's ->release() callback is called.
Documentation describing the objects and the interfaces has also been added.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/kobject.c | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/lib/kobject.c b/lib/kobject.c index 48e950c9e4ce..89fb79c873fb 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -31,10 +31,21 @@ void kobject_init(struct kobject * kobj) int kobject_register(struct kobject * kobj) { + struct subsystem * s = subsys_get(kobj->subsys); + struct kobject * parent = kobject_get(kobj->parent); + pr_debug("kobject %s: registering\n",kobj->name); - if (kobj->parent) - kobject_get(kobj->parent); - return 0; + if (s) { + down_write(&s->rwsem); + if (parent) + list_add_tail(&kobj->entry,&parent->entry); + else { + list_add_tail(&kobj->entry,&s->list); + kobj->parent = &s->kobj; + } + up_write(&s->rwsem); + } + return sysfs_create_dir(kobj); } /** @@ -53,6 +64,12 @@ int kobject_register(struct kobject * kobj) void kobject_unregister(struct kobject * kobj) { pr_debug("kobject %s: unregistering\n",kobj->name); + sysfs_remove_dir(kobj); + if (kobj->subsys) { + down_write(&kobj->subsys->rwsem); + list_del_init(&kobj->entry); + up_write(&kobj->subsys->rwsem); + } kobject_put(kobj); } @@ -64,7 +81,7 @@ void kobject_unregister(struct kobject * kobj) struct kobject * kobject_get(struct kobject * kobj) { struct kobject * ret = kobj; - if (atomic_read(&kobj->refcount) > 0) + if (kobj && atomic_read(&kobj->refcount) > 0) atomic_inc(&kobj->refcount); else ret = NULL; @@ -78,21 +95,68 @@ struct kobject * kobject_get(struct kobject * kobj) * Decrement the refcount, and check if 0. If it is, then * we're gonna need to clean it up, and decrement the refcount * of its parent. + * + * @kobj->parent could point to its subsystem, which we also + * want to decrement the reference count for. We always dec + * the refcount for the parent, but only do so for the subsystem + * if it points to a different place than the parent. */ void kobject_put(struct kobject * kobj) { struct kobject * parent = kobj->parent; + struct subsystem * s = kobj->subsys; if (!atomic_dec_and_test(&kobj->refcount)) return; + pr_debug("kobject %s: cleaning up\n",kobj->name); - if (parent) + if (s) { + if (s->release) + s->release(kobj); + if (&s->kobj != parent) + subsys_put(s); + } + + if (parent) kobject_put(parent); } + +void subsystem_init(struct subsystem * s) +{ + kobject_init(&s->kobj); + init_rwsem(&s->rwsem); + INIT_LIST_HEAD(&s->list); +} + +/** + * subsystem_register - register a subsystem. + * @s: the subsystem we're registering. + */ + +int subsystem_register(struct subsystem * s) +{ + subsystem_init(s); + if (s->parent) + s->kobj.parent = &s->parent->kobj; + pr_debug("subsystem %s: registering\n",s->kobj.name); + return kobject_register(&s->kobj); +} + +void subsystem_unregister(struct subsystem * s) +{ + pr_debug("subsystem %s: unregistering\n",s->kobj.name); + kobject_unregister(&s->kobj); +} + + EXPORT_SYMBOL(kobject_init); EXPORT_SYMBOL(kobject_register); EXPORT_SYMBOL(kobject_unregister); EXPORT_SYMBOL(kobject_get); EXPORT_SYMBOL(kobject_put); + +EXPORT_SYMBOL(subsystem_init); +EXPORT_SYMBOL(subsystem_register); +EXPORT_SYMBOL(subsystem_unregister); |
