2 * SMP- and interrupt-safe semaphores helper functions.
4 * (C) Copyright 1996 Linus Torvalds
5 * (C) Copyright 1999 Andrea Arcangeli
6 * (C) Copyright 1999, 2001 Ralf Baechle
7 * (C) Copyright 1999, 2001 Silicon Graphics, Inc.
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 waking_non_zero(struct semaphore *sem)
25 "1:\tll\t%1, %2\t\t\t# waking_non_zero\n\t"
31 : "=r" (ret), "=r" (tmp), "+m" (sem->waking)
38 * waking_non_zero_interruptible:
43 * We must undo the sem->count down_interruptible decrement
44 * simultaneously and atomically with the sem->waking adjustment,
45 * otherwise we can race with wake_one_more.
47 * This is accomplished by doing a 64-bit lld/scd on the 2 32-bit words.
51 * If(sem->waking > 0) {
52 * Decrement(sem->waking)
54 * } else If(signal_pending(tsk)) {
55 * Increment(sem->count)
63 waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
70 ".set\tpush\t\t\t# waking_non_zero_interruptible\n\t"
76 "daddiu\t%1, %1, -1\n\t"
79 "1:\tbeqz\t%3, 2f\n\t"
81 "dli\t$1, 0x0000000100000000\n\t"
82 "daddu\t%1, %1, $1\n\t"
86 : "=&r" (ret), "=&r" (tmp), "=m" (*sem)
87 : "r" (signal_pending(tsk)), "i" (-EINTR));
89 #elif defined(__MIPSEL__)
92 ".set\tpush\t\t\t# waking_non_zero_interruptible\n\t"
97 "dli\t$1, 0x0000000100000000\n\t"
98 "dsubu\t%1, %1, $1\n\t"
101 "1:\tbeqz\t%3, 2f\n\t"
104 * It would be nice to assume that sem->count
105 * is != -1, but we will guard against that case
107 "daddiu\t$1, %1, 1\n\t"
108 "dsll32\t$1, $1, 0\n\t"
109 "dsrl32\t$1, $1, 0\n\t"
110 "dsrl32\t%1, %1, 0\n\t"
111 "dsll32\t%1, %1, 0\n\t"
113 "2:\tscd\t%1, %2\n\t"
116 : "=&r" (ret), "=&r" (tmp), "=m" (*sem)
117 : "r" (signal_pending(tsk)), "i" (-EINTR));
125 * waking_non_zero_trylock is unused. we do everything in
126 * down_trylock and let non-ll/sc hosts bounce around.
129 static inline int waking_non_zero_trylock(struct semaphore *sem)
132 CHECK_MAGIC(sem->__magic);
138 #endif /* _ASM_SEMAPHORE_HELPER_H */