Import 2.3.9pre5
[davej-history.git] / include / asm-mips / semaphore-helper.h
blob59337b89820289799a8b631094d8f824f24335e1
1 /* $Id: semaphore-helper.h,v 1.3 1999/06/11 14:30:15 ralf Exp $
3 * SMP- and interrupt-safe semaphores helper functions.
5 * (C) Copyright 1996 Linus Torvalds
6 * (C) Copyright 1999 Andrea Arcangeli
7 * (C) Copyright 1999 Ralf Baechle
8 */
9 #ifndef __ASM_MIPS_SEMAPHORE_HELPER_H
10 #define __ASM_MIPS_SEMAPHORE_HELPER_H
13 * These two _must_ execute atomically wrt each other.
15 static inline void wake_one_more(struct semaphore * sem)
17 atomic_inc(&sem->waking);
20 static inline int
21 waking_non_zero(struct semaphore *sem)
23 int ret, tmp;
25 __asm__ __volatile__(
26 "1:\tll\t%1,%2\n\t"
27 "blez\t%1,2f\n\t"
28 "subu\t%0,%1,1\n\t"
29 "sc\t%0,%2\n\t"
30 "beqz\t%0,1b\n\t"
31 "2:"
32 ".text"
33 : "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
34 : "0"(0));
36 return ret;
40 * waking_non_zero_interruptible:
41 * 1 got the lock
42 * 0 go to sleep
43 * -EINTR interrupted
45 * We must undo the sem->count down_interruptible decrement
46 * simultaneously and atomicly with the sem->waking adjustment,
47 * otherwise we can race with wake_one_more.
49 * This is accomplished by doing a 64-bit ll/sc on the 2 32-bit words.
51 * This is crazy. Normally it stricly forbidden to use 64-bit operation
52 * in the 32-bit MIPS kernel. In this case it's however ok because if an
53 * interrupt has destroyed the upper half of registers sc will fail.
55 static inline int
56 waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
58 long ret, tmp;
60 #ifdef __MIPSEB__
61 __asm__ __volatile__("
62 .set mips3
63 .set push
64 .set noat
65 0: lld %1,%2
66 li %0,0
68 bltz %1, 1f
69 dli $1, 0xffffffff00000000
70 daddu %1, $1
71 li %0, 1
72 b 2f
75 beqz %3, 1f
76 addiu $1, %1, 1
77 dsll32 $1, $1, 0
78 dsrl32 $1, $1, 0
79 dsrl32 %1, %1, 0
80 dsll32 %1, %1, 0
81 or %1, $1
82 li %0, %4
83 b 2f
85 scd %1, %2
87 beqz %1,0b
88 .set pop
89 .set mips0"
90 : "=&r"(ret), "=&r"(tmp), "=m"(*sem)
91 : "r"(signal_pending(tsk)), "i"(-EINTR));
92 #endif
94 #ifdef __MIPSEL__
95 #error "FIXME: waking_non_zero_interruptible doesn't support little endian machines yet."
96 #endif
98 return ret;
102 * waking_non_zero_trylock:
103 * 1 failed to lock
104 * 0 got the lock
106 * XXX SMP ALERT
108 #ifdef __SMP__
109 #error FIXME, waking_non_zero_trylock is broken for SMP.
110 #endif
111 static inline int waking_non_zero_trylock(struct semaphore *sem)
113 int ret = 1;
115 if (atomic_read(&sem->waking) <= 0)
116 atomic_inc(&sem->count);
117 else {
118 atomic_dec(&sem->waking);
119 ret = 0;
122 return ret;
125 #endif /* __ASM_MIPS_SEMAPHORE_HELPER_H */