OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [sparc64/] [lib/] [debuglocks.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: debuglocks.c,v 1.1.1.1 2004-04-15 01:33:42 phoenix 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
#if defined(CONFIG_SMP) && defined(CONFIG_DEBUG_SPINLOCK)
14
 
15
#define GET_CALLER(PC) __asm__ __volatile__("mov %%i7, %0" : "=r" (PC))
16
 
17
static inline void show (char *str, spinlock_t *lock, unsigned long caller)
18
{
19
        int cpu = smp_processor_id();
20
 
21
        printk("%s(%p) CPU#%d stuck at %08x, owner PC(%08x):CPU(%x)\n",
22
               str, lock, cpu, (unsigned int) caller,
23
               lock->owner_pc, lock->owner_cpu);
24
}
25
 
26
static inline void show_read (char *str, rwlock_t *lock, unsigned long caller)
27
{
28
        int cpu = smp_processor_id();
29
 
30
        printk("%s(%p) CPU#%d stuck at %08x, writer PC(%08x):CPU(%x)\n",
31
               str, lock, cpu, (unsigned int) caller,
32
               lock->writer_pc, lock->writer_cpu);
33
}
34
 
35
static inline void show_write (char *str, rwlock_t *lock, unsigned long caller)
36
{
37
        int cpu = smp_processor_id();
38
 
39
        printk("%s(%p) CPU#%d stuck at %08x\n",
40
               str, lock, cpu, (unsigned int) caller);
41
        printk("Writer: PC(%08x):CPU(%x)\n",
42
               lock->writer_pc, lock->writer_cpu);
43
        printk("Readers: 0[%08x] 1[%08x] 2[%08x] 4[%08x]\n",
44
               lock->reader_pc[0], lock->reader_pc[1],
45
               lock->reader_pc[2], lock->reader_pc[3]);
46
}
47
 
48
#undef INIT_STUCK
49
#define INIT_STUCK 100000000
50
 
51
void _do_spin_lock(spinlock_t *lock, char *str)
52
{
53
        unsigned long caller, val;
54
        int stuck = INIT_STUCK;
55
        int cpu = smp_processor_id();
56
        int shown = 0;
57
 
58
        GET_CALLER(caller);
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
                        membar("#LoadLoad");
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
 
82
int _spin_trylock(spinlock_t *lock)
83
{
84
        unsigned long val, caller;
85
        int cpu = smp_processor_id();
86
 
87
        GET_CALLER(caller);
88
        __asm__ __volatile__("ldstub [%1], %0"
89
                             : "=r" (val)
90
                             : "r" (&(lock->lock))
91
                             : "memory");
92
        membar("#StoreLoad | #StoreStore");
93
        if (!val) {
94
                lock->owner_pc = ((unsigned int)caller);
95
                lock->owner_cpu = cpu;
96
                current->thread.smp_lock_count++;
97
                current->thread.smp_lock_pc = ((unsigned int)caller);
98
        }
99
        return val == 0;
100
}
101
 
102
void _do_spin_unlock(spinlock_t *lock)
103
{
104
        lock->owner_pc = 0;
105
        lock->owner_cpu = NO_PROC_ID;
106
        membar("#StoreStore | #LoadStore");
107
        lock->lock = 0;
108
        current->thread.smp_lock_count--;
109
}
110
 
111
/* Keep INIT_STUCK the same... */
112
 
113
void _do_read_lock (rwlock_t *rw, char *str)
114
{
115
        unsigned long caller, val;
116
        int stuck = INIT_STUCK;
117
        int cpu = smp_processor_id();
118
        int shown = 0;
119
 
120
        GET_CALLER(caller);
121
wlock_again:
122
        /* Wait for any writer to go away.  */
123
        while (((long)(rw->lock)) < 0) {
124
                if (!--stuck) {
125
                        if (shown++ <= 2)
126
                                show_read(str, rw, caller);
127
                        stuck = INIT_STUCK;
128
                }
129
                membar("#LoadLoad");
130
        }
131
        /* Try once to increment the counter.  */
132
        __asm__ __volatile__(
133
"       ldx             [%0], %%g5\n"
134
"       brlz,a,pn       %%g5, 2f\n"
135
"        mov            1, %0\n"
136
"       add             %%g5, 1, %%g7\n"
137
"       casx            [%0], %%g5, %%g7\n"
138
"       sub             %%g5, %%g7, %0\n"
139
"2:"    : "=r" (val)
140
        : "0" (&(rw->lock))
141
        : "g5", "g7", "memory");
142
        membar("#StoreLoad | #StoreStore");
143
        if (val)
144
                goto wlock_again;
145
        rw->reader_pc[cpu] = ((unsigned int)caller);
146
        current->thread.smp_lock_count++;
147
        current->thread.smp_lock_pc = ((unsigned int)caller);
148
}
149
 
150
void _do_read_unlock (rwlock_t *rw, char *str)
151
{
152
        unsigned long caller, val;
153
        int stuck = INIT_STUCK;
154
        int cpu = smp_processor_id();
155
        int shown = 0;
156
 
157
        GET_CALLER(caller);
158
 
159
        /* Drop our identity _first_. */
160
        rw->reader_pc[cpu] = 0;
161
        current->thread.smp_lock_count--;
162
runlock_again:
163
        /* Spin trying to decrement the counter using casx.  */
164
        __asm__ __volatile__(
165
"       ldx     [%0], %%g5\n"
166
"       sub     %%g5, 1, %%g7\n"
167
"       casx    [%0], %%g5, %%g7\n"
168
"       membar  #StoreLoad | #StoreStore\n"
169
"       sub     %%g5, %%g7, %0\n"
170
        : "=r" (val)
171
        : "0" (&(rw->lock))
172
        : "g5", "g7", "memory");
173
        if (val) {
174
                if (!--stuck) {
175
                        if (shown++ <= 2)
176
                                show_read(str, rw, caller);
177
                        stuck = INIT_STUCK;
178
                }
179
                goto runlock_again;
180
        }
181
}
182
 
183
void _do_write_lock (rwlock_t *rw, char *str)
184
{
185
        unsigned long caller, val;
186
        int stuck = INIT_STUCK;
187
        int cpu = smp_processor_id();
188
        int shown = 0;
189
 
190
        GET_CALLER(caller);
191
wlock_again:
192
        /* Spin while there is another writer. */
193
        while (((long)rw->lock) < 0) {
194
                if (!--stuck) {
195
                        if (shown++ <= 2)
196
                                show_write(str, rw, caller);
197
                        stuck = INIT_STUCK;
198
                }
199
                membar("#LoadLoad");
200
        }
201
 
202
        /* Try to acuire the write bit.  */
203
        __asm__ __volatile__(
204
"       mov     1, %%g3\n"
205
"       sllx    %%g3, 63, %%g3\n"
206
"       ldx     [%0], %%g5\n"
207
"       brlz,pn %%g5, 1f\n"
208
"        or     %%g5, %%g3, %%g7\n"
209
"       casx    [%0], %%g5, %%g7\n"
210
"       membar  #StoreLoad | #StoreStore\n"
211
"       ba,pt   %%xcc, 2f\n"
212
"        sub    %%g5, %%g7, %0\n"
213
"1:     mov     1, %0\n"
214
"2:"    : "=r" (val)
215
        : "0" (&(rw->lock))
216
        : "g3", "g5", "g7", "memory");
217
        if (val) {
218
                /* We couldn't get the write bit. */
219
                if (!--stuck) {
220
                        if (shown++ <= 2)
221
                                show_write(str, rw, caller);
222
                        stuck = INIT_STUCK;
223
                }
224
                goto wlock_again;
225
        }
226
        if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
227
                /* Readers still around, drop the write
228
                 * lock, spin, and try again.
229
                 */
230
                if (!--stuck) {
231
                        if (shown++ <= 2)
232
                                show_write(str, rw, caller);
233
                        stuck = INIT_STUCK;
234
                }
235
                __asm__ __volatile__(
236
"               mov     1, %%g3\n"
237
"               sllx    %%g3, 63, %%g3\n"
238
"1:             ldx     [%0], %%g5\n"
239
"               andn    %%g5, %%g3, %%g7\n"
240
"               casx    [%0], %%g5, %%g7\n"
241
"               cmp     %%g5, %%g7\n"
242
"               bne,pn  %%xcc, 1b\n"
243
"                membar #StoreLoad | #StoreStore"
244
                : /* no outputs */
245
                : "r" (&(rw->lock))
246
                : "g3", "g5", "g7", "cc", "memory");
247
                while(rw->lock != 0) {
248
                        if (!--stuck) {
249
                                if (shown++ <= 2)
250
                                        show_write(str, rw, caller);
251
                                stuck = INIT_STUCK;
252
                        }
253
                        membar("#LoadLoad");
254
                }
255
                goto wlock_again;
256
        }
257
 
258
        /* We have it, say who we are. */
259
        rw->writer_pc = ((unsigned int)caller);
260
        rw->writer_cpu = cpu;
261
        current->thread.smp_lock_count++;
262
        current->thread.smp_lock_pc = ((unsigned int)caller);
263
}
264
 
265
void _do_write_unlock(rwlock_t *rw)
266
{
267
        unsigned long caller, val;
268
        int stuck = INIT_STUCK;
269
        int shown = 0;
270
 
271
        GET_CALLER(caller);
272
 
273
        /* Drop our identity _first_ */
274
        rw->writer_pc = 0;
275
        rw->writer_cpu = NO_PROC_ID;
276
        current->thread.smp_lock_count--;
277
wlock_again:
278
        __asm__ __volatile__(
279
"       mov     1, %%g3\n"
280
"       sllx    %%g3, 63, %%g3\n"
281
"       ldx     [%0], %%g5\n"
282
"       andn    %%g5, %%g3, %%g7\n"
283
"       casx    [%0], %%g5, %%g7\n"
284
"       membar  #StoreLoad | #StoreStore\n"
285
"       sub     %%g5, %%g7, %0\n"
286
        : "=r" (val)
287
        : "0" (&(rw->lock))
288
        : "g3", "g5", "g7", "memory");
289
        if (val) {
290
                if (!--stuck) {
291
                        if (shown++ <= 2)
292
                                show_write("write_unlock", rw, caller);
293
                        stuck = INIT_STUCK;
294
                }
295
                goto wlock_again;
296
        }
297
}
298
 
299
int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
300
{
301
        spin_lock(lock);
302
        if (atomic_dec_and_test(atomic))
303
                return 1;
304
        spin_unlock(lock);
305
        return 0;
306
}
307
 
308
#endif /* CONFIG_SMP && CONFIG_DEBUG_SPINLOCK */

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.