diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-10-20 21:09:19 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-10-20 21:09:19 +0000 |
commit | ff28d8ce709b1137516ff67a7c398ccf3c93ab5e (patch) | |
tree | d89d28b8500a3cbfed9db44c8ced84973326be01 /include/asm-mips64/semaphore.h | |
parent | 929e0befd2cc9e36339bd8da47ad552192e61545 (diff) |
Rewrite of semaphores for MIPS64.
Diffstat (limited to 'include/asm-mips64/semaphore.h')
-rw-r--r-- | include/asm-mips64/semaphore.h | 78 |
1 files changed, 61 insertions, 17 deletions
diff --git a/include/asm-mips64/semaphore.h b/include/asm-mips64/semaphore.h index 868396781..b28d9999f 100644 --- a/include/asm-mips64/semaphore.h +++ b/include/asm-mips64/semaphore.h @@ -1,4 +1,4 @@ -/* $Id$ +/* $Id: semaphore.h,v 1.1 1999/08/18 23:37:52 ralf Exp $ * * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -12,7 +12,7 @@ #include <asm/system.h> #include <asm/atomic.h> -#include <asm/spinlock.h> +#include <linux/spinlock.h> #include <linux/wait.h> struct semaphore { @@ -94,7 +94,22 @@ extern inline int down_interruptible(struct semaphore * sem) * down_trylock returns 0 on success, 1 if we failed to get the lock. * * We must manipulate count and waking simultaneously and atomically. - * Do this by using ll/sc on the pair of 32-bit words. + * Here, we this by using ll/sc on the pair of 32-bit words. + * + * Pseudocode: + * + * Decrement(sem->count) + * If(sem->count >=0) { + * Return(SUCCESS) // resource is free + * } else { + * If(sem->waking <= 0) { // if no wakeup pending + * Increment(sem->count) // undo decrement + * Return(FAILURE) + * } else { + * Decrement(sem->waking) // otherwise "steal" wakeup + * Return(SUCCESS) + * } + * } */ extern inline int down_trylock(struct semaphore * sem) { @@ -106,32 +121,61 @@ extern inline int down_trylock(struct semaphore * sem) #ifdef __MIPSEB__ __asm__ __volatile__(" .set mips3 + 0: lld %1, %4 dli %3, 0x0000000100000000 - sltu %0, %1, $0 - - bltz %1, 1f - move %3, $0 + dsubu %1, %3 + li %0, 0 + bgez %1, 2f + sll %2, %1, 0 + blez %2, 1f + daddiu %1, %1, -1 + b 2f 1: + daddu %1, %1, %3 + li %0, 1 + 2: + scd %1, %4 + beqz %1, 0b - sltu %2, %1, $0 - and %0, %0, %2 - bnez %0, 2f + .set mips0" + : "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub) + : "m"(*sem) + : "memory"); - subu %0, %3 - scd %1, %4 +#elif defined(__MIPSEL__) - beqz %1, 0b + __asm__ __volatile__(" + .set mips3 + + 0: lld %1, %4 + li %0, 0 + sll %2, %1, 0 + addiu %2, %2, -1 + bgez %2, 2f + bltz %1, 1f + dsll32 %2, %2, 0 + dsrl32 %2, %2, 0 + dli %3, 0x0000000100000000 + dsubu %1, %3 + b 2f + 1: + li %0, 1 + b 3f 2: + dsrl32 %1, %1, 0 + dsll32 %1, %1, 0 + or %1, %1, %2 + 3: + scd %1, %4 + beqz %1, 0b .set mips0" : "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub) : "m"(*sem) : "memory"); -#endif - -#ifdef __MIPSEL__ -#error "FIXME: down_trylock doesn't support little endian machines yet." +#else +#error "MIPS but neither __MIPSEL__ nor __MIPSEB__" #endif return ret; |