Commit | Line | Data |
---|---|---|
f5e706ad SR |
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 | ||
f5e706ad SR |
9 | #ifndef __ASSEMBLY__ |
10 | ||
11 | /* To get debugging spinlocks which detect and catch | |
12 | * deadlock situations, set CONFIG_DEBUG_SPINLOCK | |
13 | * and rebuild your kernel. | |
14 | */ | |
15 | ||
64f2dde3 DM |
16 | /* Because we play games to save cycles in the non-contention case, we |
17 | * need to be extra careful about branch targets into the "spinning" | |
18 | * code. They live in their own section, but the newer V9 branches | |
19 | * have a shorter range than the traditional 32-bit sparc branch | |
20 | * variants. The rule is that the branches that go into and out of | |
21 | * the spinner sections must be pre-V9 branches. | |
f5e706ad SR |
22 | */ |
23 | ||
24 | #define __raw_spin_is_locked(lp) ((lp)->lock != 0) | |
25 | ||
26 | #define __raw_spin_unlock_wait(lp) \ | |
27 | do { rmb(); \ | |
28 | } while((lp)->lock) | |
29 | ||
30 | static inline void __raw_spin_lock(raw_spinlock_t *lock) | |
31 | { | |
32 | unsigned long tmp; | |
33 | ||
34 | __asm__ __volatile__( | |
35 | "1: ldstub [%1], %0\n" | |
f5e706ad SR |
36 | " brnz,pn %0, 2f\n" |
37 | " nop\n" | |
38 | " .subsection 2\n" | |
39 | "2: ldub [%1], %0\n" | |
f5e706ad SR |
40 | " brnz,pt %0, 2b\n" |
41 | " nop\n" | |
42 | " ba,a,pt %%xcc, 1b\n" | |
43 | " .previous" | |
44 | : "=&r" (tmp) | |
45 | : "r" (lock) | |
46 | : "memory"); | |
47 | } | |
48 | ||
49 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) | |
50 | { | |
51 | unsigned long result; | |
52 | ||
53 | __asm__ __volatile__( | |
54 | " ldstub [%1], %0\n" | |
f5e706ad SR |
55 | : "=r" (result) |
56 | : "r" (lock) | |
57 | : "memory"); | |
58 | ||
59 | return (result == 0UL); | |
60 | } | |
61 | ||
62 | static inline void __raw_spin_unlock(raw_spinlock_t *lock) | |
63 | { | |
64 | __asm__ __volatile__( | |
f5e706ad SR |
65 | " stb %%g0, [%0]" |
66 | : /* No outputs */ | |
67 | : "r" (lock) | |
68 | : "memory"); | |
69 | } | |
70 | ||
71 | static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) | |
72 | { | |
73 | unsigned long tmp1, tmp2; | |
74 | ||
75 | __asm__ __volatile__( | |
76 | "1: ldstub [%2], %0\n" | |
f5e706ad SR |
77 | " brnz,pn %0, 2f\n" |
78 | " nop\n" | |
79 | " .subsection 2\n" | |
80 | "2: rdpr %%pil, %1\n" | |
81 | " wrpr %3, %%pil\n" | |
82 | "3: ldub [%2], %0\n" | |
f5e706ad SR |
83 | " brnz,pt %0, 3b\n" |
84 | " nop\n" | |
85 | " ba,pt %%xcc, 1b\n" | |
86 | " wrpr %1, %%pil\n" | |
87 | " .previous" | |
88 | : "=&r" (tmp1), "=&r" (tmp2) | |
89 | : "r"(lock), "r"(flags) | |
90 | : "memory"); | |
91 | } | |
92 | ||
93 | /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */ | |
94 | ||
9f34ceb6 | 95 | static void inline arch_read_lock(raw_rwlock_t *lock) |
f5e706ad SR |
96 | { |
97 | unsigned long tmp1, tmp2; | |
98 | ||
99 | __asm__ __volatile__ ( | |
100 | "1: ldsw [%2], %0\n" | |
101 | " brlz,pn %0, 2f\n" | |
102 | "4: add %0, 1, %1\n" | |
103 | " cas [%2], %0, %1\n" | |
104 | " cmp %0, %1\n" | |
f5e706ad SR |
105 | " bne,pn %%icc, 1b\n" |
106 | " nop\n" | |
107 | " .subsection 2\n" | |
108 | "2: ldsw [%2], %0\n" | |
f5e706ad SR |
109 | " brlz,pt %0, 2b\n" |
110 | " nop\n" | |
111 | " ba,a,pt %%xcc, 4b\n" | |
112 | " .previous" | |
113 | : "=&r" (tmp1), "=&r" (tmp2) | |
114 | : "r" (lock) | |
115 | : "memory"); | |
116 | } | |
117 | ||
9f34ceb6 | 118 | static int inline arch_read_trylock(raw_rwlock_t *lock) |
f5e706ad SR |
119 | { |
120 | int tmp1, tmp2; | |
121 | ||
122 | __asm__ __volatile__ ( | |
123 | "1: ldsw [%2], %0\n" | |
124 | " brlz,a,pn %0, 2f\n" | |
125 | " mov 0, %0\n" | |
126 | " add %0, 1, %1\n" | |
127 | " cas [%2], %0, %1\n" | |
128 | " cmp %0, %1\n" | |
f5e706ad SR |
129 | " bne,pn %%icc, 1b\n" |
130 | " mov 1, %0\n" | |
131 | "2:" | |
132 | : "=&r" (tmp1), "=&r" (tmp2) | |
133 | : "r" (lock) | |
134 | : "memory"); | |
135 | ||
136 | return tmp1; | |
137 | } | |
138 | ||
9f34ceb6 | 139 | static void inline arch_read_unlock(raw_rwlock_t *lock) |
f5e706ad SR |
140 | { |
141 | unsigned long tmp1, tmp2; | |
142 | ||
143 | __asm__ __volatile__( | |
f5e706ad SR |
144 | "1: lduw [%2], %0\n" |
145 | " sub %0, 1, %1\n" | |
146 | " cas [%2], %0, %1\n" | |
147 | " cmp %0, %1\n" | |
148 | " bne,pn %%xcc, 1b\n" | |
149 | " nop" | |
150 | : "=&r" (tmp1), "=&r" (tmp2) | |
151 | : "r" (lock) | |
152 | : "memory"); | |
153 | } | |
154 | ||
9f34ceb6 | 155 | static void inline arch_write_lock(raw_rwlock_t *lock) |
f5e706ad SR |
156 | { |
157 | unsigned long mask, tmp1, tmp2; | |
158 | ||
159 | mask = 0x80000000UL; | |
160 | ||
161 | __asm__ __volatile__( | |
162 | "1: lduw [%2], %0\n" | |
163 | " brnz,pn %0, 2f\n" | |
164 | "4: or %0, %3, %1\n" | |
165 | " cas [%2], %0, %1\n" | |
166 | " cmp %0, %1\n" | |
f5e706ad SR |
167 | " bne,pn %%icc, 1b\n" |
168 | " nop\n" | |
169 | " .subsection 2\n" | |
170 | "2: lduw [%2], %0\n" | |
f5e706ad SR |
171 | " brnz,pt %0, 2b\n" |
172 | " nop\n" | |
173 | " ba,a,pt %%xcc, 4b\n" | |
174 | " .previous" | |
175 | : "=&r" (tmp1), "=&r" (tmp2) | |
176 | : "r" (lock), "r" (mask) | |
177 | : "memory"); | |
178 | } | |
179 | ||
9f34ceb6 | 180 | static void inline arch_write_unlock(raw_rwlock_t *lock) |
f5e706ad SR |
181 | { |
182 | __asm__ __volatile__( | |
f5e706ad SR |
183 | " stw %%g0, [%0]" |
184 | : /* no outputs */ | |
185 | : "r" (lock) | |
186 | : "memory"); | |
187 | } | |
188 | ||
9f34ceb6 | 189 | static int inline arch_write_trylock(raw_rwlock_t *lock) |
f5e706ad SR |
190 | { |
191 | unsigned long mask, tmp1, tmp2, result; | |
192 | ||
193 | mask = 0x80000000UL; | |
194 | ||
195 | __asm__ __volatile__( | |
196 | " mov 0, %2\n" | |
197 | "1: lduw [%3], %0\n" | |
198 | " brnz,pn %0, 2f\n" | |
199 | " or %0, %4, %1\n" | |
200 | " cas [%3], %0, %1\n" | |
201 | " cmp %0, %1\n" | |
f5e706ad SR |
202 | " bne,pn %%icc, 1b\n" |
203 | " nop\n" | |
204 | " mov 1, %2\n" | |
205 | "2:" | |
206 | : "=&r" (tmp1), "=&r" (tmp2), "=&r" (result) | |
207 | : "r" (lock), "r" (mask) | |
208 | : "memory"); | |
209 | ||
210 | return result; | |
211 | } | |
212 | ||
9f34ceb6 HC |
213 | #define __raw_read_lock(p) arch_read_lock(p) |
214 | #define __raw_read_lock_flags(p, f) arch_read_lock(p) | |
215 | #define __raw_read_trylock(p) arch_read_trylock(p) | |
216 | #define __raw_read_unlock(p) arch_read_unlock(p) | |
217 | #define __raw_write_lock(p) arch_write_lock(p) | |
218 | #define __raw_write_lock_flags(p, f) arch_write_lock(p) | |
219 | #define __raw_write_unlock(p) arch_write_unlock(p) | |
220 | #define __raw_write_trylock(p) arch_write_trylock(p) | |
f5e706ad SR |
221 | |
222 | #define __raw_read_can_lock(rw) (!((rw)->lock & 0x80000000UL)) | |
223 | #define __raw_write_can_lock(rw) (!(rw)->lock) | |
224 | ||
225 | #define _raw_spin_relax(lock) cpu_relax() | |
226 | #define _raw_read_relax(lock) cpu_relax() | |
227 | #define _raw_write_relax(lock) cpu_relax() | |
228 | ||
229 | #endif /* !(__ASSEMBLY__) */ | |
230 | ||
231 | #endif /* !(__SPARC64_SPINLOCK_H) */ |