diff options
author | Greg Kroah-Hartman <greg@kroah.com> | 2003-04-28 08:27:58 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <greg@kroah.com> | 2003-04-28 08:27:58 -0700 |
commit | 5d4d8070c3d10a9a18894c671b247c6790e3355a (patch) | |
tree | 2b16d944518eeda825e8dc621946a64537f76f21 /lib | |
parent | a0e259f3f8e6884f70699f3dd2d4d3ec6ef9be76 (diff) | |
download | history-5d4d8070c3d10a9a18894c671b247c6790e3355a.tar.gz |
kobject: kobj_lock needs to be grabed using spinlock_irq
This is because some subsystems (cough, usb...) can grab a kobject from irq context.
This lock can be completely removed once the sysfs_init() code is cleaned up.
Patch originally by Andrew Morton.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/kobject.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/lib/kobject.c b/lib/kobject.c index 6ea750e95c5655..64bee08f6d1e4a 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -1,5 +1,8 @@ /* * kobject.c - library routines for handling generic kernel objects + * + * Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org> + * */ #undef DEBUG @@ -9,6 +12,8 @@ #include <linux/module.h> #include <linux/stat.h> +/* This lock can be removed entirely when the sysfs_init() code is cleaned up + * to not try to reference itself before it is initialized. */ static spinlock_t kobj_lock = SPIN_LOCK_UNLOCKED; /** @@ -336,12 +341,14 @@ void kobject_unregister(struct kobject * kobj) struct kobject * kobject_get(struct kobject * kobj) { struct kobject * ret = kobj; - spin_lock(&kobj_lock); + unsigned long flags; + + spin_lock_irqsave(&kobj_lock, flags); if (kobj && atomic_read(&kobj->refcount) > 0) atomic_inc(&kobj->refcount); else ret = NULL; - spin_unlock(&kobj_lock); + spin_unlock_irqrestore(&kobj_lock, flags); return ret; } @@ -371,10 +378,15 @@ void kobject_cleanup(struct kobject * kobj) void kobject_put(struct kobject * kobj) { - if (!atomic_dec_and_lock(&kobj->refcount, &kobj_lock)) - return; - spin_unlock(&kobj_lock); - kobject_cleanup(kobj); + unsigned long flags; + + local_irq_save(flags); + if (atomic_dec_and_lock(&kobj->refcount, &kobj_lock)) { + spin_unlock_irqrestore(&kobj_lock, flags); + kobject_cleanup(kobj); + } else { + local_irq_restore(flags); + } } |