aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2003-04-28 08:27:58 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2003-04-28 08:27:58 -0700
commit5d4d8070c3d10a9a18894c671b247c6790e3355a (patch)
tree2b16d944518eeda825e8dc621946a64537f76f21 /lib
parenta0e259f3f8e6884f70699f3dd2d4d3ec6ef9be76 (diff)
downloadhistory-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.c24
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);
+ }
}