1 /* $Id: debuglocks.c,v 1.3 1999/09/10 10:40:50 davem Exp $
2 * debuglocks.c: Debugging versions of SMP locking primitives.
4 * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
7 #include <linux/kernel.h>
8 #include <linux/sched.h>
9 #include <linux/spinlock.h>
10 #include <asm/system.h>
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]);
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();
61 __asm__
__volatile__("ldstub [%1], %0"
65 membar("#StoreLoad | #StoreStore");
69 show(str
, lock
, caller
);
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();
86 __asm__
__volatile__("ldstub [%1], %0"
90 membar("#StoreLoad | #StoreStore");
92 lock
->owner_pc
= ((unsigned int)caller
);
93 lock
->owner_cpu
= cpu
;
98 void _do_spin_unlock(spinlock_t
*lock
)
101 lock
->owner_cpu
= NO_PROC_ID
;
102 membar("#StoreStore | #LoadStore");
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();
116 /* Wait for any writer to go away. */
117 while (((long)(rw
->lock
)) < 0) {
119 show_read(str
, rw
, caller
);
124 /* Try once to increment the counter. */
125 __asm__
__volatile__("
130 casx [%0], %%g5, %%g7
134 : "g5", "g7", "memory");
135 membar("#StoreLoad | #StoreStore");
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();
149 /* Drop our identity _first_. */
150 rw
->reader_pc
[cpu
] = 0;
152 /* Spin trying to decrement the counter using casx. */
153 __asm__
__volatile__("
156 casx [%0], %%g5, %%g7
157 membar #StoreLoad | #StoreStore
161 : "g5", "g7", "memory");
164 show_read(str
, rw
, caller
);
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();
179 /* Spin while there is another writer. */
180 while (((long)rw
->lock
) < 0) {
182 show_write(str
, rw
, caller
);
188 /* Try to acuire the write bit. */
189 __asm__
__volatile__("
195 casx [%0], %%g5, %%g7
196 membar #StoreLoad | #StoreStore
202 : "g3", "g5", "g7", "memory");
204 /* We couldn't get the write bit. */
206 show_write(str
, rw
, caller
);
211 if ((rw
->lock
& ((1UL<<63)-1UL)) != 0UL) {
212 /* Readers still around, drop the write
213 * lock, spin, and try again.
216 show_write(str
, rw
, caller
);
219 __asm__
__volatile__("
223 andn %%g5, %%g3, %%g7
224 casx [%0], %%g5, %%g7
227 membar #StoreLoad | #StoreStore"
230 : "g3", "g5", "g7", "cc", "memory");
231 while(rw
->lock
!= 0) {
233 show_write(str
, rw
, caller
);
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
;
253 /* Drop our identity _first_ */
255 rw
->writer_cpu
= NO_PROC_ID
;
257 __asm__
__volatile__("
261 andn %%g5, %%g3, %%g7
262 casx [%0], %%g5, %%g7
263 membar #StoreLoad | #StoreStore
267 : "g3", "g5", "g7", "memory");
270 show_write("write_unlock", rw
, caller
);
277 #endif /* SPIN_LOCK_DEBUG */