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