[PATCH] Subject: PATCH: fix numa caused compile warnings
[pandora-kernel.git] / arch / sparc64 / lib / debuglocks.c
1 /* $Id: debuglocks.c,v 1.9 2001/11/17 00:10:48 davem Exp $
2  * debuglocks.c: Debugging versions of SMP locking primitives.
3  *
4  * Copyright (C) 1998 David S. Miller (davem@redhat.com)
5  */
6
7 #include <linux/config.h>
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/spinlock.h>
11 #include <asm/system.h>
12
13 #ifdef CONFIG_SMP
14
15 static inline void show (char *str, spinlock_t *lock, unsigned long caller)
16 {
17         int cpu = smp_processor_id();
18
19         printk("%s(%p) CPU#%d stuck at %08x, owner PC(%08x):CPU(%x)\n",
20                str, lock, cpu, (unsigned int) caller,
21                lock->owner_pc, lock->owner_cpu);
22 }
23
24 static inline void show_read (char *str, rwlock_t *lock, unsigned long caller)
25 {
26         int cpu = smp_processor_id();
27
28         printk("%s(%p) CPU#%d stuck at %08x, writer PC(%08x):CPU(%x)\n",
29                str, lock, cpu, (unsigned int) caller,
30                lock->writer_pc, lock->writer_cpu);
31 }
32
33 static inline void show_write (char *str, rwlock_t *lock, unsigned long caller)
34 {
35         int cpu = smp_processor_id();
36         int i;
37
38         printk("%s(%p) CPU#%d stuck at %08x\n",
39                str, lock, cpu, (unsigned int) caller);
40         printk("Writer: PC(%08x):CPU(%x)\n",
41                lock->writer_pc, lock->writer_cpu);
42         printk("Readers:");
43         for (i = 0; i < NR_CPUS; i++)
44                 if (lock->reader_pc[i])
45                         printk(" %d[%08x]", i, lock->reader_pc[i]);
46         printk("\n");
47 }
48
49 #undef INIT_STUCK
50 #define INIT_STUCK 100000000
51
52 void _do_spin_lock(spinlock_t *lock, char *str, unsigned long caller)
53 {
54         unsigned long val;
55         int stuck = INIT_STUCK;
56         int cpu = get_cpu();
57         int shown = 0;
58
59 again:
60         __asm__ __volatile__("ldstub [%1], %0"
61                              : "=r" (val)
62                              : "r" (&(lock->lock))
63                              : "memory");
64         membar_storeload_storestore();
65         if (val) {
66                 while (lock->lock) {
67                         if (!--stuck) {
68                                 if (shown++ <= 2)
69                                         show(str, lock, caller);
70                                 stuck = INIT_STUCK;
71                         }
72                         rmb();
73                 }
74                 goto again;
75         }
76         lock->owner_pc = ((unsigned int)caller);
77         lock->owner_cpu = cpu;
78         current->thread.smp_lock_count++;
79         current->thread.smp_lock_pc = ((unsigned int)caller);
80
81         put_cpu();
82 }
83
84 int _do_spin_trylock(spinlock_t *lock, unsigned long caller)
85 {
86         unsigned long val;
87         int cpu = get_cpu();
88
89         __asm__ __volatile__("ldstub [%1], %0"
90                              : "=r" (val)
91                              : "r" (&(lock->lock))
92                              : "memory");
93         membar_storeload_storestore();
94         if (!val) {
95                 lock->owner_pc = ((unsigned int)caller);
96                 lock->owner_cpu = cpu;
97                 current->thread.smp_lock_count++;
98                 current->thread.smp_lock_pc = ((unsigned int)caller);
99         }
100
101         put_cpu();
102
103         return val == 0;
104 }
105
106 void _do_spin_unlock(spinlock_t *lock)
107 {
108         lock->owner_pc = 0;
109         lock->owner_cpu = NO_PROC_ID;
110         membar_storestore_loadstore();
111         lock->lock = 0;
112         current->thread.smp_lock_count--;
113 }
114
115 /* Keep INIT_STUCK the same... */
116
117 void _do_read_lock(rwlock_t *rw, char *str, unsigned long caller)
118 {
119         unsigned long val;
120         int stuck = INIT_STUCK;
121         int cpu = get_cpu();
122         int shown = 0;
123
124 wlock_again:
125         /* Wait for any writer to go away.  */
126         while (((long)(rw->lock)) < 0) {
127                 if (!--stuck) {
128                         if (shown++ <= 2)
129                                 show_read(str, rw, caller);
130                         stuck = INIT_STUCK;
131                 }
132                 rmb();
133         }
134         /* Try once to increment the counter.  */
135         __asm__ __volatile__(
136 "       ldx             [%0], %%g1\n"
137 "       brlz,a,pn       %%g1, 2f\n"
138 "        mov            1, %0\n"
139 "       add             %%g1, 1, %%g7\n"
140 "       casx            [%0], %%g1, %%g7\n"
141 "       sub             %%g1, %%g7, %0\n"
142 "2:"    : "=r" (val)
143         : "0" (&(rw->lock))
144         : "g1", "g7", "memory");
145         membar_storeload_storestore();
146         if (val)
147                 goto wlock_again;
148         rw->reader_pc[cpu] = ((unsigned int)caller);
149         current->thread.smp_lock_count++;
150         current->thread.smp_lock_pc = ((unsigned int)caller);
151
152         put_cpu();
153 }
154
155 void _do_read_unlock(rwlock_t *rw, char *str, unsigned long caller)
156 {
157         unsigned long val;
158         int stuck = INIT_STUCK;
159         int cpu = get_cpu();
160         int shown = 0;
161
162         /* Drop our identity _first_. */
163         rw->reader_pc[cpu] = 0;
164         current->thread.smp_lock_count--;
165 runlock_again:
166         /* Spin trying to decrement the counter using casx.  */
167         __asm__ __volatile__(
168 "       membar  #StoreLoad | #LoadLoad\n"
169 "       ldx     [%0], %%g1\n"
170 "       sub     %%g1, 1, %%g7\n"
171 "       casx    [%0], %%g1, %%g7\n"
172 "       membar  #StoreLoad | #StoreStore\n"
173 "       sub     %%g1, %%g7, %0\n"
174         : "=r" (val)
175         : "0" (&(rw->lock))
176         : "g1", "g7", "memory");
177         if (val) {
178                 if (!--stuck) {
179                         if (shown++ <= 2)
180                                 show_read(str, rw, caller);
181                         stuck = INIT_STUCK;
182                 }
183                 goto runlock_again;
184         }
185
186         put_cpu();
187 }
188
189 void _do_write_lock(rwlock_t *rw, char *str, unsigned long caller)
190 {
191         unsigned long val;
192         int stuck = INIT_STUCK;
193         int cpu = get_cpu();
194         int shown = 0;
195
196 wlock_again:
197         /* Spin while there is another writer. */
198         while (((long)rw->lock) < 0) {
199                 if (!--stuck) {
200                         if (shown++ <= 2)
201                                 show_write(str, rw, caller);
202                         stuck = INIT_STUCK;
203                 }
204                 rmb();
205         }
206
207         /* Try to acuire the write bit.  */
208         __asm__ __volatile__(
209 "       mov     1, %%g3\n"
210 "       sllx    %%g3, 63, %%g3\n"
211 "       ldx     [%0], %%g1\n"
212 "       brlz,pn %%g1, 1f\n"
213 "        or     %%g1, %%g3, %%g7\n"
214 "       casx    [%0], %%g1, %%g7\n"
215 "       membar  #StoreLoad | #StoreStore\n"
216 "       ba,pt   %%xcc, 2f\n"
217 "        sub    %%g1, %%g7, %0\n"
218 "1:     mov     1, %0\n"
219 "2:"    : "=r" (val)
220         : "0" (&(rw->lock))
221         : "g3", "g1", "g7", "memory");
222         if (val) {
223                 /* We couldn't get the write bit. */
224                 if (!--stuck) {
225                         if (shown++ <= 2)
226                                 show_write(str, rw, caller);
227                         stuck = INIT_STUCK;
228                 }
229                 goto wlock_again;
230         }
231         if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
232                 /* Readers still around, drop the write
233                  * lock, spin, and try again.
234                  */
235                 if (!--stuck) {
236                         if (shown++ <= 2)
237                                 show_write(str, rw, caller);
238                         stuck = INIT_STUCK;
239                 }
240                 __asm__ __volatile__(
241 "               mov     1, %%g3\n"
242 "               sllx    %%g3, 63, %%g3\n"
243 "1:             ldx     [%0], %%g1\n"
244 "               andn    %%g1, %%g3, %%g7\n"
245 "               casx    [%0], %%g1, %%g7\n"
246 "               cmp     %%g1, %%g7\n"
247 "               membar  #StoreLoad | #StoreStore\n"
248 "               bne,pn  %%xcc, 1b\n"
249 "                nop"
250                 : /* no outputs */
251                 : "r" (&(rw->lock))
252                 : "g3", "g1", "g7", "cc", "memory");
253                 while(rw->lock != 0) {
254                         if (!--stuck) {
255                                 if (shown++ <= 2)
256                                         show_write(str, rw, caller);
257                                 stuck = INIT_STUCK;
258                         }
259                         rmb();
260                 }
261                 goto wlock_again;
262         }
263
264         /* We have it, say who we are. */
265         rw->writer_pc = ((unsigned int)caller);
266         rw->writer_cpu = cpu;
267         current->thread.smp_lock_count++;
268         current->thread.smp_lock_pc = ((unsigned int)caller);
269
270         put_cpu();
271 }
272
273 void _do_write_unlock(rwlock_t *rw, unsigned long caller)
274 {
275         unsigned long val;
276         int stuck = INIT_STUCK;
277         int shown = 0;
278
279         /* Drop our identity _first_ */
280         rw->writer_pc = 0;
281         rw->writer_cpu = NO_PROC_ID;
282         current->thread.smp_lock_count--;
283 wlock_again:
284         __asm__ __volatile__(
285 "       membar  #StoreLoad | #LoadLoad\n"
286 "       mov     1, %%g3\n"
287 "       sllx    %%g3, 63, %%g3\n"
288 "       ldx     [%0], %%g1\n"
289 "       andn    %%g1, %%g3, %%g7\n"
290 "       casx    [%0], %%g1, %%g7\n"
291 "       membar  #StoreLoad | #StoreStore\n"
292 "       sub     %%g1, %%g7, %0\n"
293         : "=r" (val)
294         : "0" (&(rw->lock))
295         : "g3", "g1", "g7", "memory");
296         if (val) {
297                 if (!--stuck) {
298                         if (shown++ <= 2)
299                                 show_write("write_unlock", rw, caller);
300                         stuck = INIT_STUCK;
301                 }
302                 goto wlock_again;
303         }
304 }
305
306 int _do_write_trylock(rwlock_t *rw, char *str, unsigned long caller)
307 {
308         unsigned long val;
309         int cpu = get_cpu();
310
311         /* Try to acuire the write bit.  */
312         __asm__ __volatile__(
313 "       mov     1, %%g3\n"
314 "       sllx    %%g3, 63, %%g3\n"
315 "       ldx     [%0], %%g1\n"
316 "       brlz,pn %%g1, 1f\n"
317 "        or     %%g1, %%g3, %%g7\n"
318 "       casx    [%0], %%g1, %%g7\n"
319 "       membar  #StoreLoad | #StoreStore\n"
320 "       ba,pt   %%xcc, 2f\n"
321 "        sub    %%g1, %%g7, %0\n"
322 "1:     mov     1, %0\n"
323 "2:"    : "=r" (val)
324         : "0" (&(rw->lock))
325         : "g3", "g1", "g7", "memory");
326
327         if (val) {
328                 put_cpu();
329                 return 0;
330         }
331
332         if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
333                 /* Readers still around, drop the write
334                  * lock, return failure.
335                  */
336                 __asm__ __volatile__(
337 "               mov     1, %%g3\n"
338 "               sllx    %%g3, 63, %%g3\n"
339 "1:             ldx     [%0], %%g1\n"
340 "               andn    %%g1, %%g3, %%g7\n"
341 "               casx    [%0], %%g1, %%g7\n"
342 "               cmp     %%g1, %%g7\n"
343 "               membar  #StoreLoad | #StoreStore\n"
344 "               bne,pn  %%xcc, 1b\n"
345 "                nop"
346                 : /* no outputs */
347                 : "r" (&(rw->lock))
348                 : "g3", "g1", "g7", "cc", "memory");
349
350                 put_cpu();
351
352                 return 0;
353         }
354
355         /* We have it, say who we are. */
356         rw->writer_pc = ((unsigned int)caller);
357         rw->writer_cpu = cpu;
358         current->thread.smp_lock_count++;
359         current->thread.smp_lock_pc = ((unsigned int)caller);
360
361         put_cpu();
362
363         return 1;
364 }
365
366 #endif /* CONFIG_SMP */