Import 2.3.18pre1
[davej-history.git] / arch / sparc64 / lib / debuglocks.c
blob6bdcbb3cc59ffb6b4d0e129386d02cfd2f8fce5d
1 /* $Id: debuglocks.c,v 1.2 1998/10/13 09:07:27 davem Exp $
2 * debuglocks.c: Debugging versions of SMP locking primitives.
4 * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
5 */
7 #include <linux/kernel.h>
8 #include <linux/sched.h>
9 #include <linux/spinlock.h>
10 #include <asm/system.h>
12 #ifdef __SMP__
14 /* To enable this code, just define SPIN_LOCK_DEBUG in asm/spinlock.h */
15 #ifdef SPIN_LOCK_DEBUG
17 #define GET_CALLER(PC) __asm__ __volatile__("mov %%i7, %0" : "=r" (PC))
19 static inline void show (char *str, spinlock_t *lock, unsigned long caller)
21 int cpu = smp_processor_id();
23 printk("%s(%p) CPU#%d stuck at %08x, owner PC(%08x):CPU(%x)\n",
24 str, lock, cpu, (unsigned int) caller,
25 lock->owner_pc, lock->owner_cpu);
28 static inline void show_read (char *str, rwlock_t *lock, unsigned long caller)
30 int cpu = smp_processor_id();
32 printk("%s(%p) CPU#%d stuck at %08x, writer PC(%08x):CPU(%x)\n",
33 str, lock, cpu, (unsigned int) caller,
34 lock->writer_pc, lock->writer_cpu);
37 static inline void show_write (char *str, rwlock_t *lock, unsigned long caller)
39 int cpu = smp_processor_id();
41 printk("%s(%p) CPU#%d stuck at %08x\n",
42 str, lock, cpu, (unsigned int) caller);
43 printk("Writer: PC(%08x):CPU(%x)\n",
44 lock->writer_pc, lock->writer_cpu);
45 printk("Readers: 0[%08x] 1[%08x] 2[%08x] 4[%08x]\n",
46 lock->reader_pc[0], lock->reader_pc[1],
47 lock->reader_pc[2], lock->reader_pc[3]);
50 #undef INIT_STUCK
51 #define INIT_STUCK 100000000
53 void _do_spin_lock(spinlock_t *lock, char *str)
55 unsigned long caller, val;
56 int stuck = INIT_STUCK;
57 int cpu = smp_processor_id();
59 GET_CALLER(caller);
60 again:
61 __asm__ __volatile__("ldstub [%1], %0"
62 : "=r" (val)
63 : "r" (&(lock->lock))
64 : "memory");
65 membar("#StoreLoad | #StoreStore");
66 if (val) {
67 while (lock->lock) {
68 if (!--stuck) {
69 show(str, lock, caller);
70 stuck = INIT_STUCK;
72 membar("#LoadLoad");
74 goto again;
76 lock->owner_pc = ((unsigned int)caller);
77 lock->owner_cpu = cpu;
80 int _spin_trylock(spinlock_t *lock)
82 unsigned long val, caller;
83 int cpu = smp_processor_id();
85 GET_CALLER(caller);
86 __asm__ __volatile__("ldstub [%1], %0"
87 : "=r" (val)
88 : "r" (&(lock->lock))
89 : "memory");
90 membar("#StoreLoad | #StoreStore");
91 if (!val) {
92 lock->owner_pc = ((unsigned int)caller);
93 lock->owner_cpu = cpu;
95 return val == 0;
98 void _do_spin_unlock(spinlock_t *lock)
100 lock->owner_pc = 0;
101 lock->owner_cpu = NO_PROC_ID;
102 membar("#StoreStore | #LoadStore");
103 lock->lock = 0;
106 /* Keep INIT_STUCK the same... */
108 void _do_read_lock (rwlock_t *rw, char *str)
110 unsigned long caller, val;
111 int stuck = INIT_STUCK;
112 int cpu = smp_processor_id();
114 GET_CALLER(caller);
115 wlock_again:
116 /* Wait for any writer to go away. */
117 while (((long)(rw->lock)) < 0) {
118 if (!--stuck) {
119 show_read(str, rw, caller);
120 stuck = INIT_STUCK;
122 membar("#LoadLoad");
124 /* Try once to increment the counter. */
125 __asm__ __volatile__("
126 ldx [%0], %%g5
127 brlz,a,pn %%g5, 2f
128 mov 1, %0
129 add %%g5, 1, %%g7
130 casx [%0], %%g5, %%g7
131 sub %%g5, %%g7, %0
132 2:" : "=r" (val)
133 : "0" (&(rw->lock))
134 : "g5", "g7", "memory");
135 membar("#StoreLoad | #StoreStore");
136 if (val)
137 goto wlock_again;
138 rw->reader_pc[cpu] = ((unsigned int)caller);
141 void _do_read_unlock (rwlock_t *rw, char *str)
143 unsigned long caller, val;
144 int stuck = INIT_STUCK;
145 int cpu = smp_processor_id();
147 GET_CALLER(caller);
149 /* Drop our identity _first_. */
150 rw->reader_pc[cpu] = 0;
151 runlock_again:
152 /* Spin trying to decrement the counter using casx. */
153 __asm__ __volatile__("
154 ldx [%0], %%g5
155 sub %%g5, 1, %%g7
156 casx [%0], %%g5, %%g7
157 membar #StoreLoad | #StoreStore
158 sub %%g5, %%g7, %0
159 " : "=r" (val)
160 : "0" (&(rw->lock))
161 : "g5", "g7", "memory");
162 if (val) {
163 if (!--stuck) {
164 show_read(str, rw, caller);
165 stuck = INIT_STUCK;
167 goto runlock_again;
171 void _do_write_lock (rwlock_t *rw, char *str)
173 unsigned long caller, val;
174 int stuck = INIT_STUCK;
175 int cpu = smp_processor_id();
177 GET_CALLER(caller);
178 wlock_again:
179 /* Spin while there is another writer. */
180 while (((long)rw->lock) < 0) {
181 if (!--stuck) {
182 show_write(str, rw, caller);
183 stuck = INIT_STUCK;
185 membar("#LoadLoad");
188 /* Try to acuire the write bit. */
189 __asm__ __volatile__("
190 mov 1, %%g3
191 sllx %%g3, 63, %%g3
192 ldx [%0], %%g5
193 brlz,pn %%g5, 1f
194 or %%g5, %%g3, %%g7
195 casx [%0], %%g5, %%g7
196 membar #StoreLoad | #StoreStore
197 ba,pt %%xcc, 2f
198 sub %%g5, %%g7, %0
199 1: mov 1, %0
200 2:" : "=r" (val)
201 : "0" (&(rw->lock))
202 : "g3", "g5", "g7", "memory");
203 if (val) {
204 /* We couldn't get the write bit. */
205 if (!--stuck) {
206 show_write(str, rw, caller);
207 stuck = INIT_STUCK;
209 goto wlock_again;
211 if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
212 /* Readers still around, drop the write
213 * lock, spin, and try again.
215 if (!--stuck) {
216 show_write(str, rw, caller);
217 stuck = INIT_STUCK;
219 __asm__ __volatile__("
220 mov 1, %%g3
221 sllx %%g3, 63, %%g3
222 1: ldx [%0], %%g5
223 andn %%g5, %%g3, %%g7
224 casx [%0], %%g5, %%g7
225 cmp %%g5, %%g7
226 bne,pn %%xcc, 1b
227 membar #StoreLoad | #StoreStore"
228 : /* no outputs */
229 : "r" (&(rw->lock))
230 : "g3", "g5", "g7", "cc", "memory");
231 while(rw->lock != 0) {
232 if (!--stuck) {
233 show_write(str, rw, caller);
234 stuck = INIT_STUCK;
236 membar("#LoadLoad");
238 goto wlock_again;
241 /* We have it, say who we are. */
242 rw->writer_pc = ((unsigned int)caller);
243 rw->writer_cpu = cpu;
246 void _do_write_unlock(rwlock_t *rw)
248 unsigned long caller, val;
249 int stuck = INIT_STUCK;
251 GET_CALLER(caller);
253 /* Drop our identity _first_ */
254 rw->writer_pc = 0;
255 rw->writer_cpu = NO_PROC_ID;
256 wlock_again:
257 __asm__ __volatile__("
258 mov 1, %%g3
259 sllx %%g3, 63, %%g3
260 ldx [%0], %%g5
261 andn %%g5, %%g3, %%g7
262 casx [%0], %%g5, %%g7
263 membar #StoreLoad | #StoreStore
264 sub %%g5, %%g7, %0
265 " : "=r" (val)
266 : "0" (&(rw->lock))
267 : "g3", "g5", "g7", "memory");
268 if (val) {
269 if (!--stuck) {
270 show_write("write_unlock", rw, caller);
271 stuck = INIT_STUCK;
273 goto wlock_again;
277 #endif /* SPIN_LOCK_DEBUG */
278 #endif /* __SMP__ */