summaryrefslogtreecommitdiffstats
path: root/include/asm-mips64/semaphore.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-10-20 21:09:19 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-10-20 21:09:19 +0000
commitff28d8ce709b1137516ff67a7c398ccf3c93ab5e (patch)
treed89d28b8500a3cbfed9db44c8ced84973326be01 /include/asm-mips64/semaphore.h
parent929e0befd2cc9e36339bd8da47ad552192e61545 (diff)
Rewrite of semaphores for MIPS64.
Diffstat (limited to 'include/asm-mips64/semaphore.h')
-rw-r--r--include/asm-mips64/semaphore.h78
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;