public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* (no subject)
@ 2005-01-18  0:07 Greg KH
  0 siblings, 0 replies; only message in thread
From: Greg KH @ 2005-01-18  0:07 UTC (permalink / raw)
  To: linux-kernel

Subject [RFC] sysdev: change locking to use a class based spinlock
Reply-To: 

Here's another patch in my steps of removing the use of the subsystem
rwsem lock.  I've converted the sysdev subsystem here to use a spinlock
(instead of a semaphore, like my previous class patch did, I'll go
change that later too.)

The patch is against 2.6.11-rc1.  Any comments would be appreciated.

thanks,

greg k-h

-------
sysdev: change locking to use a class based spinlock

Use the new lock, and not the global subsystem lock.  This is a step in
removing the rwsem from subsystems, and should allow sysdevs to now be
able to add and remove themselves from within their function callbacks.

Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>


--- 1.28/drivers/base/sys.c	2004-10-20 09:47:44 -07:00
+++ edited/drivers/base/sys.c	2005-01-17 15:37:06 -08:00
@@ -79,13 +79,14 @@ EXPORT_SYMBOL_GPL(sysdev_remove_file);
 /*
  * declare system_subsys
  */
-decl_subsys(system, &ktype_sysdev, NULL);
+static decl_subsys(system, &ktype_sysdev, NULL);
 
 int sysdev_class_register(struct sysdev_class * cls)
 {
 	pr_debug("Registering sysdev class '%s'\n",
 		 kobject_name(&cls->kset.kobj));
 	INIT_LIST_HEAD(&cls->drivers);
+	spin_lock_init(&cls->lock);
 	cls->kset.subsys = &system_subsys;
 	kset_set_kset_s(cls, system_subsys);
 	return kset_register(&cls->kset);
@@ -103,6 +104,7 @@ EXPORT_SYMBOL_GPL(sysdev_class_unregiste
 
 
 static LIST_HEAD(global_drivers);
+static DEFINE_SPINLOCK(global_drivers_lock);
 
 /**
  *	sysdev_driver_register - Register auxillary driver
@@ -119,19 +121,22 @@ static LIST_HEAD(global_drivers);
 int sysdev_driver_register(struct sysdev_class * cls,
 			   struct sysdev_driver * drv)
 {
-	down_write(&system_subsys.rwsem);
 	if (cls && kset_get(&cls->kset)) {
+		spin_lock(&cls->lock);
 		list_add_tail(&drv->entry, &cls->drivers);
+		spin_unlock(&cls->lock);
 
 		/* If devices of this class already exist, tell the driver */
 		if (drv->add) {
-			struct sys_device *dev;
-			list_for_each_entry(dev, &cls->kset.list, kobj.entry)
+			struct sys_device *dev, *temp;
+			list_for_each_entry_safe(dev, temp, &cls->kset.list, kobj.entry)
 				drv->add(dev);
 		}
-	} else
+	} else {
+		spin_lock(&global_drivers_lock);
 		list_add_tail(&drv->entry, &global_drivers);
-	up_write(&system_subsys.rwsem);
+		spin_unlock(&global_drivers_lock);
+	}
 	return 0;
 }
 
@@ -144,17 +149,21 @@ int sysdev_driver_register(struct sysdev
 void sysdev_driver_unregister(struct sysdev_class * cls,
 			      struct sysdev_driver * drv)
 {
-	down_write(&system_subsys.rwsem);
+	/* we don't know which list the drv is on, so lock both of them */
+	spin_lock(&cls->lock);
+	spin_lock(&global_drivers_lock);
 	list_del_init(&drv->entry);
+	spin_unlock(&global_drivers_lock);
+	spin_unlock(&cls->lock);
+
 	if (cls) {
 		if (drv->remove) {
-			struct sys_device *dev;
-			list_for_each_entry(dev, &cls->kset.list, kobj.entry)
+			struct sys_device *dev, *temp;
+			list_for_each_entry_safe(dev, temp, &cls->kset.list, kobj.entry)
 				drv->remove(dev);
 		}
 		kset_put(&cls->kset);
 	}
-	up_write(&system_subsys.rwsem);
 }
 
 EXPORT_SYMBOL_GPL(sysdev_driver_register);
@@ -191,44 +200,40 @@ int sysdev_register(struct sys_device * 
 	error = kobject_register(&sysdev->kobj);
 
 	if (!error) {
-		struct sysdev_driver * drv;
+		struct sysdev_driver *drv, *temp;
 
-		down_write(&system_subsys.rwsem);
 		/* Generic notification is implicit, because it's that
 		 * code that should have called us.
 		 */
 
 		/* Notify global drivers */
-		list_for_each_entry(drv, &global_drivers, entry) {
+		list_for_each_entry_safe(drv, temp, &global_drivers, entry) {
 			if (drv->add)
 				drv->add(sysdev);
 		}
 
 		/* Notify class auxillary drivers */
-		list_for_each_entry(drv, &cls->drivers, entry) {
+		list_for_each_entry_safe(drv, temp, &cls->drivers, entry) {
 			if (drv->add)
 				drv->add(sysdev);
 		}
-		up_write(&system_subsys.rwsem);
 	}
 	return error;
 }
 
 void sysdev_unregister(struct sys_device * sysdev)
 {
-	struct sysdev_driver * drv;
+	struct sysdev_driver *drv, *temp;
 
-	down_write(&system_subsys.rwsem);
-	list_for_each_entry(drv, &global_drivers, entry) {
+	list_for_each_entry_safe(drv, temp, &global_drivers, entry) {
 		if (drv->remove)
 			drv->remove(sysdev);
 	}
 
-	list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
+	list_for_each_entry_safe(drv, temp, &sysdev->cls->drivers, entry) {
 		if (drv->remove)
 			drv->remove(sysdev);
 	}
-	up_write(&system_subsys.rwsem);
 
 	kobject_unregister(&sysdev->kobj);
 }
@@ -251,30 +256,29 @@ void sysdev_unregister(struct sys_device
 
 void sysdev_shutdown(void)
 {
-	struct sysdev_class * cls;
+	struct sysdev_class *cls;
 
 	pr_debug("Shutting Down System Devices\n");
 
-	down_write(&system_subsys.rwsem);
 	list_for_each_entry_reverse(cls, &system_subsys.kset.list,
 				    kset.kobj.entry) {
-		struct sys_device * sysdev;
+		struct sys_device *sysdev, *temp_dev;
 
 		pr_debug("Shutting down type '%s':\n",
 			 kobject_name(&cls->kset.kobj));
 
-		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
-			struct sysdev_driver * drv;
+		list_for_each_entry_safe(sysdev, temp_dev, &cls->kset.list, kobj.entry) {
+			struct sysdev_driver *drv, *temp_drv;
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
 			/* Call global drivers first. */
-			list_for_each_entry(drv, &global_drivers, entry) {
+			list_for_each_entry_safe(drv, temp_drv, &global_drivers, entry) {
 				if (drv->shutdown)
 					drv->shutdown(sysdev);
 			}
 
 			/* Call auxillary drivers next. */
-			list_for_each_entry(drv, &cls->drivers, entry) {
+			list_for_each_entry_safe(drv, temp_drv, &cls->drivers, entry) {
 				if (drv->shutdown)
 					drv->shutdown(sysdev);
 			}
@@ -284,7 +288,6 @@ void sysdev_shutdown(void)
 				cls->shutdown(sysdev);
 		}
 	}
-	up_write(&system_subsys.rwsem);
 }
 
 
@@ -309,23 +312,23 @@ int sysdev_suspend(u32 state)
 
 	list_for_each_entry_reverse(cls, &system_subsys.kset.list,
 				    kset.kobj.entry) {
-		struct sys_device * sysdev;
+		struct sys_device *sysdev, *temp_dev;
 
 		pr_debug("Suspending type '%s':\n",
 			 kobject_name(&cls->kset.kobj));
 
-		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
-			struct sysdev_driver * drv;
+		list_for_each_entry_safe(sysdev, temp_dev, &cls->kset.list, kobj.entry) {
+			struct sysdev_driver *drv, *temp_drv;
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
 			/* Call global drivers first. */
-			list_for_each_entry(drv, &global_drivers, entry) {
+			list_for_each_entry_safe(drv, temp_drv, &global_drivers, entry) {
 				if (drv->suspend)
 					drv->suspend(sysdev, state);
 			}
 
 			/* Call auxillary drivers next. */
-			list_for_each_entry(drv, &cls->drivers, entry) {
+			list_for_each_entry_safe(drv, temp_drv, &cls->drivers, entry) {
 				if (drv->suspend)
 					drv->suspend(sysdev, state);
 			}
@@ -355,13 +358,13 @@ int sysdev_resume(void)
 	pr_debug("Resuming System Devices\n");
 
 	list_for_each_entry(cls, &system_subsys.kset.list, kset.kobj.entry) {
-		struct sys_device * sysdev;
+		struct sys_device *sysdev, *temp_dev;
 
 		pr_debug("Resuming type '%s':\n",
 			 kobject_name(&cls->kset.kobj));
 
-		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
-			struct sysdev_driver * drv;
+		list_for_each_entry_safe(sysdev, temp_dev, &cls->kset.list, kobj.entry) {
+			struct sysdev_driver *drv, *temp_drv;
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
 			/* First, call the class-specific one */
@@ -369,13 +372,13 @@ int sysdev_resume(void)
 				cls->resume(sysdev);
 
 			/* Call auxillary drivers next. */
-			list_for_each_entry(drv, &cls->drivers, entry) {
+			list_for_each_entry_safe(drv, temp_drv, &cls->drivers, entry) {
 				if (drv->resume)
 					drv->resume(sysdev);
 			}
 
 			/* Call global drivers. */
-			list_for_each_entry(drv, &global_drivers, entry) {
+			list_for_each_entry_safe(drv, temp_drv, &global_drivers, entry) {
 				if (drv->resume)
 					drv->resume(sysdev);
 			}
===== include/linux/sysdev.h 1.6 vs edited =====
--- 1.6/include/linux/sysdev.h	2004-03-04 08:57:52 -08:00
+++ edited/include/linux/sysdev.h	2005-01-17 14:46:50 -08:00
@@ -22,12 +22,14 @@
 #define _SYSDEV_H_
 
 #include <linux/kobject.h>
+#include <linux/spinlock.h>
 
 
 struct sys_device;
 
 struct sysdev_class {
 	struct list_head	drivers;
+	spinlock_t	lock;	/* locks the list for this class */
 
 	/* Default operations for these types of devices */
 	int	(*shutdown)(struct sys_device *);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-01-18  0:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-18  0:07 Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox