- Linus: more PageDirty / swapcache handling
[davej-history.git] / include / asm-mips64 / semaphore-helper.h
blob91799d486322f3f75e0e825f547f67b1d0216267
1 /*
2 * SMP- and interrupt-safe semaphores helper functions.
4 * (C) Copyright 1996 Linus Torvalds
5 * (C) Copyright 1999 Andrea Arcangeli
6 * (C) Copyright 1999 Ralf Baechle
7 * (C) Copyright 1999 Silicon Graphics, Inc.
8 */
9 #ifndef _ASM_SEMAPHORE_HELPER_H
10 #define _ASM_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" (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 * Pseudocode:
53 * If(sem->waking > 0) {
54 * Decrement(sem->waking)
55 * Return(SUCCESS)
56 * } else If(segnal_pending(tsk)) {
57 * Increment(sem->count)
58 * Return(-EINTR)
59 * } else {
60 * Return(SLEEP)
61 * }
64 static inline int
65 waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
67 long ret, tmp;
69 #ifdef __MIPSEB__
71 __asm__ __volatile__("
72 .set push
73 .set noat
74 0: lld %1, %2
75 li %0, 0
76 sll $1, %1, 0
77 blez $1, 1f
78 daddiu %1, %1, -1
79 li %0, 1
80 b 2f
82 beqz %3, 2f
83 li %0, %4
84 dli $1, 0x0000000100000000
85 daddu %1, %1, $1
87 scd %1, %2
88 beqz %1, 0b
89 .set pop"
90 : "=&r" (ret), "=&r" (tmp), "=m" (*sem)
91 : "r" (signal_pending(tsk)), "i" (-EINTR));
93 #elif defined(__MIPSEL__)
95 __asm__ __volatile__("
96 .set push
97 .set noat
99 lld %1, %2
100 li %0, 0
101 blez %1, 1f
102 dli $1, 0x0000000100000000
103 dsubu %1, %1, $1
104 li %0, 1
105 b 2f
107 beqz %3, 2f
108 li %0, %4
110 * It would be nice to assume that sem->count
111 * is != -1, but we will guard against that case
113 daddiu $1, %1, 1
114 dsll32 $1, $1, 0
115 dsrl32 $1, $1, 0
116 dsrl32 %1, %1, 0
117 dsll32 %1, %1, 0
118 or %1, %1, $1
120 scd %1, %2
121 beqz %1, 0b
122 .set pop"
123 : "=&r" (ret), "=&r" (tmp), "=m" (*sem)
124 : "r" (signal_pending(tsk)), "i" (-EINTR));
126 #else
127 #error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
128 #endif
130 return ret;
134 * waking_non_zero_trylock is unused. we do everything in
135 * down_trylock and let non-ll/sc hosts bounce around.
138 static inline int
139 waking_non_zero_trylock(struct semaphore *sem)
141 #if WAITQUEUE_DEBUG
142 CHECK_MAGIC(sem->__magic);
143 #endif
145 return 0;
148 #endif /* _ASM_SEMAPHORE_HELPER_H */