[parisc-linux-cvs] Semaphore rewrite

Matthew Wilcox willy@ldl.fc.hp.com
Fri, 16 Mar 2001 21:33:17 -0700


Here's the rewrite of the implementation I described earlier.  It now
survives pipetest.c.  go forth and celebrate.  Thanks to paul for writing
the pipetest program.

Index: arch/parisc/kernel/semaphore.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/semaphore.c,v
retrieving revision 1.6
diff -u -p -r1.6 semaphore.c
--- semaphore.c	2001/02/16 17:10:55	1.6
+++ semaphore.c	2001/03/17 04:20:19
@@ -34,6 +34,7 @@
  */
 void __up(struct semaphore *sem)
 {
+	sem->count--;
 	wake_up(&sem->wait);
 }
 
@@ -47,17 +48,20 @@ void __up(struct semaphore *sem)
 	/* protected by the sentry still -- use unlocked version */	\
 	wait.flags = WQ_FLAG_EXCLUSIVE;					\
 	__add_wait_queue_tail(&sem->wait, &wait);			\
-lost_race:								\
+ lost_race:								\
 	spin_unlock_irq(&sem->sentry);					\
 
 #define DOWN_TAIL							\
 	spin_lock_irq(&sem->sentry);					\
-	if (sem->count < 0)						\
-		goto lost_race;						\
+	if (sem->count == -1)						\
+		goto lost_race;	/* Someone stole our wakeup */		\
 	__remove_wait_queue(&sem->wait, &wait);				\
 	current->state = TASK_RUNNING;					\
-	if (!waitqueue_active(&sem->wait))				\
-		sem->count = 1;
+	if (!waitqueue_active(&sem->wait)) {				\
+		sem->count = 0;						\
+	} else {							\
+		sem->count += 1;					\
+	}
 
 void __down(struct semaphore * sem)
 {
@@ -66,7 +70,7 @@ void __down(struct semaphore * sem)
 	for(;;) {
 		set_task_state(current, TASK_UNINTERRUPTIBLE);
 		/* we can _read_ this without the sentry */
-		if (sem->count >= 0)
+		if (sem->count != -1)
 			break;
  		schedule();
  	}
@@ -83,7 +87,7 @@ int __down_interruptible(struct semaphor
 	for(;;) {
 		set_task_state(current, TASK_INTERRUPTIBLE);
 		/* we can _read_ this without the sentry */
-		if (sem->count >= 0)
+		if (sem->count != -1)
 			break;
 
 		if (signal_pending(current)) {
Index: include/asm-parisc/semaphore.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/asm-parisc/semaphore.h,v
retrieving revision 1.6
diff -u -p -r1.6 semaphore.h
--- semaphore.h	2001/02/16 02:53:30	1.6
+++ semaphore.h	2001/03/17 04:23:16
@@ -68,7 +68,7 @@ asmlinkage void __down(struct semaphore 
 asmlinkage int  __down_interruptible(struct semaphore * sem);
 asmlinkage void __up(struct semaphore * sem);
 
-/* Sempahores can be `tried' from irq context.  So we have to disable
+/* Semaphores can be `tried' from irq context.  So we have to disable
  * interrupts while we're messing with the semaphore.  Sorry.
  */
 
@@ -131,8 +131,11 @@ extern __inline__ void up(struct semapho
 	CHECK_MAGIC(sem->__magic);
 #endif
 	spin_lock_irqsave(&sem->sentry, flags);
-	if (++sem->count <= 0)
+	if (sem->count < 0) {
 		__up(sem);
+	} else {
+		sem->count++;
+	}
 	spin_unlock_irqrestore(&sem->sentry, flags);
 }