[PATCH] rwsem: Make rwsems use interrupt disabling spinlocks

Linux Kernel Mailing List <[email protected]> Tue, 05 Apr 2005 14:05:24 +0000
Newsgroups gmane.linux.kernel.commits.2-4
Message-ID <[email protected]>
ChangeSet 1.1492.1.2, 2005/04/05 11:05:24-03:00, [email protected]

	[PATCH] rwsem: Make rwsems use interrupt disabling spinlocks
	
	# This is a BitKeeper generated diff -Nru style patch.
	#
	# ChangeSet
	#   2005/03/09 10:25:02-08:00 [email protected]
	#   [PATCH] rwsem: Make rwsems use interrupt disabling spinlocks
	#
	#   The attached patch makes read/write semaphores use interrupt disabling
	#   spinlocks in the slow path, thus rendering the up functions and trylock
	#   functions available for use in interrupt context.  This matches the
	#   regular semaphore behaviour.
	#
	#   I've assumed that the normal down functions must be called with interrupts
	#   enabled (since they might schedule), and used the irq-disabling spinlock
	#   variants that don't save the flags.
	#
	#   Signed-Off-By: David Howells <[email protected]>
	#   Tested-by: Badari Pulavarty <[email protected]>
	#   Signed-off-by: Linus Torvalds <[email protected]>
	#
	# lib/rwsem.c
	#   2005/03/09 02:45:16-08:00 [email protected] +10 -6
	#   rwsem: Make rwsems use interrupt disabling spinlocks
	#
	# lib/rwsem-spinlock.c
	#   2005/03/09 02:43:47-08:00 [email protected] +26 -16
	#   rwsem: Make rwsems use interrupt disabling spinlocks
	#



 rwsem-spinlock.c |   32 ++++++++++++++++++--------------
 rwsem.c          |    9 +++++----
 2 files changed, 23 insertions(+), 18 deletions(-)


diff -Nru a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
--- a/lib/rwsem-spinlock.c	2005-04-05 13:02:58 -07:00
+++ b/lib/rwsem-spinlock.c	2005-04-05 13:02:58 -07:00
@@ -127,12 +127,12 @@
 
 	rwsemtrace(sem,"Entering __down_read");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irq(&sem->wait_lock);
 
 	if (sem->activity>=0 && list_empty(&sem->wait_list)) {
 		/* granted */
 		sem->activity++;
-		spin_unlock(&sem->wait_lock);
+		spin_unlock_irq(&sem->wait_lock);
 		goto out;
 	}
 
@@ -147,7 +147,7 @@
 	list_add_tail(&waiter.list,&sem->wait_list);
 
 	/* we don't need to touch the semaphore struct anymore */
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irq(&sem->wait_lock);
 
 	/* wait to be given the lock */
 	for (;;) {
@@ -169,9 +169,10 @@
 int fastcall __down_read_trylock(struct rw_semaphore *sem)
 {
 	int ret = 0;
+	unsigned long flags;
 	rwsemtrace(sem,"Entering __down_read_trylock");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	if (sem->activity>=0 && list_empty(&sem->wait_list)) {
 		/* granted */
@@ -179,7 +180,7 @@
 		ret = 1;
 	}
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem,"Leaving __down_read_trylock");
 	return ret;
@@ -196,12 +197,12 @@
 
 	rwsemtrace(sem,"Entering __down_write");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irq(&sem->wait_lock);
 
 	if (sem->activity==0 && list_empty(&sem->wait_list)) {
 		/* granted */
 		sem->activity = -1;
-		spin_unlock(&sem->wait_lock);
+		spin_unlock_irq(&sem->wait_lock);
 		goto out;
 	}
 
@@ -216,7 +217,7 @@
 	list_add_tail(&waiter.list,&sem->wait_list);
 
 	/* we don't need to touch the semaphore struct anymore */
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irq(&sem->wait_lock);
 
 	/* wait to be given the lock */
 	for (;;) {
@@ -238,9 +239,10 @@
 int fastcall __down_write_trylock(struct rw_semaphore *sem)
 {
 	int ret = 0;
+	unsigned long flags;
 	rwsemtrace(sem,"Entering __down_write_trylock");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	if (sem->activity==0 && list_empty(&sem->wait_list)) {
 		/* granted */
@@ -248,7 +250,7 @@
 		ret = 1;
 	}
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem,"Leaving __down_write_trylock");
 	return ret;
@@ -259,14 +261,15 @@
  */
 void fastcall __up_read(struct rw_semaphore *sem)
 {
+	unsigned long flags;
 	rwsemtrace(sem,"Entering __up_read");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	if (--sem->activity==0 && !list_empty(&sem->wait_list))
 		sem = __rwsem_wake_one_writer(sem);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_restore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem,"Leaving __up_read");
 }
@@ -276,15 +279,16 @@
  */
 void fastcall __up_write(struct rw_semaphore *sem)
 {
+	unsigned long flags;
 	rwsemtrace(sem,"Entering __up_write");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	sem->activity = 0;
 	if (!list_empty(&sem->wait_list))
 		sem = __rwsem_do_wake(sem);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem,"Leaving __up_write");
 }
diff -Nru a/lib/rwsem.c b/lib/rwsem.c
--- a/lib/rwsem.c	2005-04-05 13:02:58 -07:00
+++ b/lib/rwsem.c	2005-04-05 13:02:58 -07:00
@@ -127,7 +127,7 @@
 	set_task_state(tsk,TASK_UNINTERRUPTIBLE);
 
 	/* set up my own style of waitqueue */
-	spin_lock(&sem->wait_lock);
+	spin_lock_irq(&sem->wait_lock);
 	waiter->task = tsk;
 	get_task_struct(tsk);
 
@@ -142,7 +142,7 @@
 	if (!(count & RWSEM_ACTIVE_MASK))
 		sem = __rwsem_do_wake(sem);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irq(&sem->wait_lock);
 
 	/* wait to be given the lock */
 	for (;;) {
@@ -195,15 +195,16 @@
  */
 struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem)
 {
+	unsigned long flags;
 	rwsemtrace(sem,"Entering rwsem_wake");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	/* do nothing if list empty */
 	if (!list_empty(&sem->wait_list))
 		sem = __rwsem_do_wake(sem);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem,"Leaving rwsem_wake");