Skip to contentSkip to conversation

can: replace spinlocks with mutexes

RFC In review Oliver Hartkopp 2 participants 4 messages Apr 20, 2011 – Apr 21, 2011

Subsystems (3)
lore
Share & tools
lore

Oliver Hartkopp

author maintainer
#0 lore raw

RFC 1/1 can: replace spinlocks with mutexes

This patch removes spinlocks for the CAN netdevice specific receive lists. The RCU-based receive lists can be modified from process context or from the netdevice notifier call. As both might sleep we can safely replace the spinlocks with mutexes.

---

net/can/af_can.c +8 -8
index a8dcaa4..e52ed358 100644
@@ -47,7 +47,7 @@
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/list.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/rcupdate.h>
 #include <linux/uaccess.h>
 #include <linux/net.h>
@@ -79,7 +79,7 @@ MODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)");
 
 /* receive filters subscribed for 'all' CAN devices */
 struct dev_rcv_lists can_rx_alldev_list;
-static DEFINE_SPINLOCK(can_rcvlists_lock);
+static DEFINE_MUTEX(can_rcvlists_lock);
 
 static struct kmem_cache *rcv_cache __read_mostly;
 
@@ -435,7 +435,7 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
 	if (!r)
 		return -ENOMEM;
 
-	spin_lock(&can_rcvlists_lock);
+	mutex_lock(&can_rcvlists_lock);
 
 	d = find_dev_rcv_lists(dev);
 	if (d) {
@@ -459,7 +459,7 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
 		err = -ENODEV;
 	}
 
-	spin_unlock(&can_rcvlists_lock);
+	mutex_unlock(&can_rcvlists_lock);
 
 	return err;
 }
@@ -497,7 +497,7 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
 	if (dev && dev->type != ARPHRD_CAN)
 		return;
 
-	spin_lock(&can_rcvlists_lock);
+	mutex_lock(&can_rcvlists_lock);
 
 	d = find_dev_rcv_lists(dev);
 	if (!d) {
@@ -548,7 +548,7 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
 	}
 
  out:
-	spin_unlock(&can_rcvlists_lock);
+	mutex_unlock(&can_rcvlists_lock);
 
 	/* schedule the receiver item for deletion */
 	if (r)
@@ -775,7 +775,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
 		break;
 
 	case NETDEV_UNREGISTER:
-		spin_lock(&can_rcvlists_lock);
+		mutex_lock(&can_rcvlists_lock);
 
 		d = dev->ml_priv;
 		if (d) {
@@ -789,7 +789,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
 			printk(KERN_ERR "can: notifier: receive list not "
 			       "found for dev %s\n", dev->name);
 
-		spin_unlock(&can_rcvlists_lock);
+		mutex_unlock(&can_rcvlists_lock);
 
 		break;
 	}
#1 lore raw
Quoted 8 lines · Oliver Hartkopp

This patch removes spinlocks for the CAN netdevice specific receive lists. The RCU-based receive lists can be modified from process context or from the netdevice notifier call. As both might sleep we can safely replace the spinlocks with mutexes.

---

But... why ?

A spinlock is faster/smaller than a mutex.

Maybe you wanted to _remove_ spinlock, since/if writer hold RTNL and doesnt need to exclude another writer(s) ?

Note : I did not check the RTNL assertion, you might add appropriate ASSERT_RTNL() calls just to be 100% safe.

author maintainer
#2 lore raw
Quoted 6 lines · Eric Dumazet
Quoted 5 lines · Oliver Hartkopp

This patch removes spinlocks for the CAN netdevice specific receive lists. The RCU-based receive lists can be modified from process context or from the netdevice notifier call. As both might sleep we can safely replace the spinlocks with mutexes.

Quoted 7 lines
Quoted 3 lines

---

But... why ?

A spinlock is faster/smaller than a mutex.

Hm, i expected the mutex to have some advantages especially in multicore systems ...

But if it doesn't has any vital advantage, we can leave it as-is.

Quoted 2 lines

Maybe you wanted to _remove_ spinlock, since/if writer hold RTNL and doesnt need to exclude another writer(s) ?

That's an interesting idea. The filters are modified at socket creation/removal time and can also be modified in between using sockopts by _ordinary_ users. Could that be a problem?

Quoted 2 lines

Note : I did not check the RTNL assertion, you might add appropriate ASSERT_RTNL() calls just to be 100% safe.

I'll investigate some similar places in the networking code and then replace the spinlocks with rtnl_locks for some testing.

Thanks for the feedback,
Oliver

author maintainer
#3 lore raw
In reply to Eric Dumazet
Quoted 12 lines · Eric Dumazet
Quoted 8 lines · Oliver Hartkopp

This patch removes spinlocks for the CAN netdevice specific receive lists. The RCU-based receive lists can be modified from process context or from the netdevice notifier call. As both might sleep we can safely replace the spinlocks with mutexes.

---

But... why ?

Quoted 8 lines

A spinlock is faster/smaller than a mutex.

Maybe you wanted to _remove_ spinlock, since/if writer hold RTNL and doesnt need to exclude another writer(s) ?

Note : I did not check the RTNL assertion, you might add appropriate ASSERT_RTNL() calls just to be 100% safe.

I played a bit with rtnl locks but ran into problems with a lock sock when enabling all locking debug techniques. Therefore i pull back my RFC for now and leave the locking using spinlocks as-is.

Thanks,
Oliver