patch-2.4.20 linux-2.4.20/include/asm-parisc/semaphore.h

Next file: linux-2.4.20/include/asm-parisc/sembuf.h
Previous file: linux-2.4.20/include/asm-parisc/semaphore-helper.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/include/asm-parisc/semaphore.h linux-2.4.20/include/asm-parisc/semaphore.h
@@ -1,26 +1,30 @@
 #ifndef _ASM_PARISC_SEMAPHORE_H
 #define _ASM_PARISC_SEMAPHORE_H
 
-#include <linux/linkage.h>
-
 /*
  * SMP- and interrupt-safe semaphores.
  *
  * (C) Copyright 1996 Linus Torvalds
  *
- * SuperH verison by Niibe Yutaka
+ * PA-RISC version by Matthew Wilcox
  *
  */
 
 #include <linux/spinlock.h>
+#include <linux/wait.h>
 #include <linux/rwsem.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
 
+/*
+ * The `count' is initialised to the number of people who are allowed to
+ * take the lock.  (Normally we want a mutex, so this is `1').  if
+ * `count' is positive, the lock can be taken.  if it's 0, no-one is
+ * waiting on it.  if it's -1, at least one task is waiting.
+ */
 struct semaphore {
-	atomic_t count;
-	int waking;
+	spinlock_t	sentry;
+	int		count;
 	wait_queue_head_t wait;
 #if WAITQUEUE_DEBUG
 	long __magic;
@@ -35,7 +39,7 @@
 #endif
 
 #define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+{ SPIN_LOCK_UNLOCKED, count, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
 	__SEM_DEBUG_INIT(name) }
 
 #define __MUTEX_INITIALIZER(name) \
@@ -49,18 +53,7 @@
 
 extern inline void sema_init (struct semaphore *sem, int val)
 {
-/*
- *	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
- *
- * i'd rather use the more flexible initialization above, but sadly
- * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
- */
-	atomic_set(&sem->count, val);
-	sem->waking = 0;
-	init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
+	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -73,17 +66,18 @@
 	sema_init(sem, 0);
 }
 
-asmlinkage void __down_failed(void /* special register calling convention */);
-asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
-asmlinkage int  __down_failed_trylock(void  /* params in registers */);
-asmlinkage void __up_wakeup(void /* special register calling convention */);
+static inline int sem_getcount(struct semaphore *sem)
+{
+	return sem->count;
+}
 
 asmlinkage void __down(struct semaphore * sem);
 asmlinkage int  __down_interruptible(struct semaphore * sem);
-asmlinkage int  __down_trylock(struct semaphore * sem);
 asmlinkage void __up(struct semaphore * sem);
 
-extern spinlock_t semaphore_wake_lock;
+/* Semaphores can be `tried' from irq context.  So we have to disable
+ * interrupts while we're messing with the semaphore.  Sorry.
+ */
 
 extern __inline__ void down(struct semaphore * sem)
 {
@@ -91,8 +85,13 @@
 	CHECK_MAGIC(sem->__magic);
 #endif
 
-	if (atomic_dec_return(&sem->count) < 0)
+	spin_lock_irq(&sem->sentry);
+	if (sem->count > 0) {
+		sem->count--;
+	} else {
 		__down(sem);
+	}
+	spin_unlock_irq(&sem->sentry);
 }
 
 extern __inline__ int down_interruptible(struct semaphore * sem)
@@ -102,21 +101,33 @@
 	CHECK_MAGIC(sem->__magic);
 #endif
 
-	if (atomic_dec_return(&sem->count) < 0)
+	spin_lock_irq(&sem->sentry);
+	if (sem->count > 0) {
+		sem->count--;
+	} else {
 		ret = __down_interruptible(sem);
+	}
+	spin_unlock_irq(&sem->sentry);
 	return ret;
 }
 
+/*
+ * down_trylock returns 0 on success, 1 if we failed to get the lock.
+ * May not sleep, but must preserve irq state
+ */
 extern __inline__ int down_trylock(struct semaphore * sem)
 {
-	int ret = 0;
+	int flags, count;
 #if WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 
-	if (atomic_dec_return(&sem->count) < 0)
-		ret = __down_trylock(sem);
-	return ret;
+	spin_lock_irqsave(&sem->sentry, flags);
+	count = sem->count - 1;
+	if (count >= 0)
+		sem->count = count;
+	spin_unlock_irqrestore(&sem->sentry, flags);
+	return (count < 0);
 }
 
 /*
@@ -125,11 +136,17 @@
  */
 extern __inline__ void up(struct semaphore * sem)
 {
+	int flags;
 #if WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
-	if (atomic_inc_return(&sem->count) <= 0)
+	spin_lock_irqsave(&sem->sentry, flags);
+	if (sem->count < 0) {
 		__up(sem);
+	} else {
+		sem->count++;
+	}
+	spin_unlock_irqrestore(&sem->sentry, flags);
 }
 
 #endif /* _ASM_PARISC_SEMAPHORE_H */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)