[ARM] 3443/1: [S3C2410] Improve IRQ entry code
[linux-2.6/verdex.git] / include / asm-sparc64 / spinlock.h
blob508c416e9d6a8b1423ab3bb88eef8ee27d67ec9a
1 /* spinlock.h: 64-bit Sparc spinlock support.
3 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
4 */
6 #ifndef __SPARC64_SPINLOCK_H
7 #define __SPARC64_SPINLOCK_H
9 #include <linux/config.h>
10 #include <linux/threads.h> /* For NR_CPUS */
12 #ifndef __ASSEMBLY__
14 /* To get debugging spinlocks which detect and catch
15 * deadlock situations, set CONFIG_DEBUG_SPINLOCK
16 * and rebuild your kernel.
19 /* All of these locking primitives are expected to work properly
20 * even in an RMO memory model, which currently is what the kernel
21 * runs in.
23 * There is another issue. Because we play games to save cycles
24 * in the non-contention case, we need to be extra careful about
25 * branch targets into the "spinning" code. They live in their
26 * own section, but the newer V9 branches have a shorter range
27 * than the traditional 32-bit sparc branch variants. The rule
28 * is that the branches that go into and out of the spinner sections
29 * must be pre-V9 branches.
32 #define __raw_spin_is_locked(lp) ((lp)->lock != 0)
34 #define __raw_spin_unlock_wait(lp) \
35 do { rmb(); \
36 } while((lp)->lock)
38 static inline void __raw_spin_lock(raw_spinlock_t *lock)
40 unsigned long tmp;
42 __asm__ __volatile__(
43 "1: ldstub [%1], %0\n"
44 " membar #StoreLoad | #StoreStore\n"
45 " brnz,pn %0, 2f\n"
46 " nop\n"
47 " .subsection 2\n"
48 "2: ldub [%1], %0\n"
49 " membar #LoadLoad\n"
50 " brnz,pt %0, 2b\n"
51 " nop\n"
52 " ba,a,pt %%xcc, 1b\n"
53 " .previous"
54 : "=&r" (tmp)
55 : "r" (lock)
56 : "memory");
59 static inline int __raw_spin_trylock(raw_spinlock_t *lock)
61 unsigned long result;
63 __asm__ __volatile__(
64 " ldstub [%1], %0\n"
65 " membar #StoreLoad | #StoreStore"
66 : "=r" (result)
67 : "r" (lock)
68 : "memory");
70 return (result == 0UL);
73 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
75 __asm__ __volatile__(
76 " membar #StoreStore | #LoadStore\n"
77 " stb %%g0, [%0]"
78 : /* No outputs */
79 : "r" (lock)
80 : "memory");
83 static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
85 unsigned long tmp1, tmp2;
87 __asm__ __volatile__(
88 "1: ldstub [%2], %0\n"
89 " membar #StoreLoad | #StoreStore\n"
90 " brnz,pn %0, 2f\n"
91 " nop\n"
92 " .subsection 2\n"
93 "2: rdpr %%pil, %1\n"
94 " wrpr %3, %%pil\n"
95 "3: ldub [%2], %0\n"
96 " membar #LoadLoad\n"
97 " brnz,pt %0, 3b\n"
98 " nop\n"
99 " ba,pt %%xcc, 1b\n"
100 " wrpr %1, %%pil\n"
101 " .previous"
102 : "=&r" (tmp1), "=&r" (tmp2)
103 : "r"(lock), "r"(flags)
104 : "memory");
107 /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
109 static void inline __read_lock(raw_rwlock_t *lock)
111 unsigned long tmp1, tmp2;
113 __asm__ __volatile__ (
114 "1: ldsw [%2], %0\n"
115 " brlz,pn %0, 2f\n"
116 "4: add %0, 1, %1\n"
117 " cas [%2], %0, %1\n"
118 " cmp %0, %1\n"
119 " membar #StoreLoad | #StoreStore\n"
120 " bne,pn %%icc, 1b\n"
121 " nop\n"
122 " .subsection 2\n"
123 "2: ldsw [%2], %0\n"
124 " membar #LoadLoad\n"
125 " brlz,pt %0, 2b\n"
126 " nop\n"
127 " ba,a,pt %%xcc, 4b\n"
128 " .previous"
129 : "=&r" (tmp1), "=&r" (tmp2)
130 : "r" (lock)
131 : "memory");
134 static int inline __read_trylock(raw_rwlock_t *lock)
136 int tmp1, tmp2;
138 __asm__ __volatile__ (
139 "1: ldsw [%2], %0\n"
140 " brlz,a,pn %0, 2f\n"
141 " mov 0, %0\n"
142 " add %0, 1, %1\n"
143 " cas [%2], %0, %1\n"
144 " cmp %0, %1\n"
145 " membar #StoreLoad | #StoreStore\n"
146 " bne,pn %%icc, 1b\n"
147 " mov 1, %0\n"
148 "2:"
149 : "=&r" (tmp1), "=&r" (tmp2)
150 : "r" (lock)
151 : "memory");
153 return tmp1;
156 static void inline __read_unlock(raw_rwlock_t *lock)
158 unsigned long tmp1, tmp2;
160 __asm__ __volatile__(
161 " membar #StoreLoad | #LoadLoad\n"
162 "1: lduw [%2], %0\n"
163 " sub %0, 1, %1\n"
164 " cas [%2], %0, %1\n"
165 " cmp %0, %1\n"
166 " bne,pn %%xcc, 1b\n"
167 " nop"
168 : "=&r" (tmp1), "=&r" (tmp2)
169 : "r" (lock)
170 : "memory");
173 static void inline __write_lock(raw_rwlock_t *lock)
175 unsigned long mask, tmp1, tmp2;
177 mask = 0x80000000UL;
179 __asm__ __volatile__(
180 "1: lduw [%2], %0\n"
181 " brnz,pn %0, 2f\n"
182 "4: or %0, %3, %1\n"
183 " cas [%2], %0, %1\n"
184 " cmp %0, %1\n"
185 " membar #StoreLoad | #StoreStore\n"
186 " bne,pn %%icc, 1b\n"
187 " nop\n"
188 " .subsection 2\n"
189 "2: lduw [%2], %0\n"
190 " membar #LoadLoad\n"
191 " brnz,pt %0, 2b\n"
192 " nop\n"
193 " ba,a,pt %%xcc, 4b\n"
194 " .previous"
195 : "=&r" (tmp1), "=&r" (tmp2)
196 : "r" (lock), "r" (mask)
197 : "memory");
200 static void inline __write_unlock(raw_rwlock_t *lock)
202 __asm__ __volatile__(
203 " membar #LoadStore | #StoreStore\n"
204 " stw %%g0, [%0]"
205 : /* no outputs */
206 : "r" (lock)
207 : "memory");
210 static int inline __write_trylock(raw_rwlock_t *lock)
212 unsigned long mask, tmp1, tmp2, result;
214 mask = 0x80000000UL;
216 __asm__ __volatile__(
217 " mov 0, %2\n"
218 "1: lduw [%3], %0\n"
219 " brnz,pn %0, 2f\n"
220 " or %0, %4, %1\n"
221 " cas [%3], %0, %1\n"
222 " cmp %0, %1\n"
223 " membar #StoreLoad | #StoreStore\n"
224 " bne,pn %%icc, 1b\n"
225 " nop\n"
226 " mov 1, %2\n"
227 "2:"
228 : "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
229 : "r" (lock), "r" (mask)
230 : "memory");
232 return result;
235 #define __raw_read_lock(p) __read_lock(p)
236 #define __raw_read_trylock(p) __read_trylock(p)
237 #define __raw_read_unlock(p) __read_unlock(p)
238 #define __raw_write_lock(p) __write_lock(p)
239 #define __raw_write_unlock(p) __write_unlock(p)
240 #define __raw_write_trylock(p) __write_trylock(p)
242 #define __raw_read_can_lock(rw) (!((rw)->lock & 0x80000000UL))
243 #define __raw_write_can_lock(rw) (!(rw)->lock)
245 #endif /* !(__ASSEMBLY__) */
247 #endif /* !(__SPARC64_SPINLOCK_H) */