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
- Lines: 164
- Date:
Thu Nov 28 15:53:15 2002
- Orig file:
linux-2.4.19/include/asm-parisc/semaphore.h
- Orig date:
Mon Feb 25 11:38:12 2002
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)