diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
commit | 78c388aed2b7184182c08428db1de6c872d815f5 (patch) | |
tree | 4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /arch/sparc/lib | |
parent | eb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff) |
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'arch/sparc/lib')
-rw-r--r-- | arch/sparc/lib/bitops.S | 90 | ||||
-rw-r--r-- | arch/sparc/lib/copy_user.S | 146 | ||||
-rw-r--r-- | arch/sparc/lib/debuglocks.c | 388 | ||||
-rw-r--r-- | arch/sparc/lib/locks.S | 44 |
4 files changed, 256 insertions, 412 deletions
diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S index 526bf86bd..253c358fe 100644 --- a/arch/sparc/lib/bitops.S +++ b/arch/sparc/lib/bitops.S @@ -26,12 +26,26 @@ ___set_bit: wr %g3, PSR_PIL, %psr nop; nop; nop 1: - ld [%g1], %g7 +#ifdef __SMP__ + set C_LABEL(bitops_spinlock), %g5 +2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. + orcc %g7, 0x0, %g0 ! Did we get it? + bne 2b ! Nope... +#endif + ld [%g1], %g7 or %g7, %g2, %g5 - andcc %g3, PSR_PIL, %g0 and %g7, %g2, %g2 +#ifdef __SMP__ + st %g5, [%g1] + set C_LABEL(bitops_spinlock), %g5 + andcc %g3, PSR_PIL, %g0 + bne 1f + stb %g0, [%g5] +#else + andcc %g3, PSR_PIL, %g0 bne 1f st %g5, [%g1] +#endif wr %g3, 0x0, %psr nop; nop; nop 1: @@ -48,12 +62,26 @@ ___clear_bit: wr %g3, PSR_PIL, %psr nop; nop; nop 1: - ld [%g1], %g7 +#ifdef __SMP__ + set C_LABEL(bitops_spinlock), %g5 +2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. + orcc %g7, 0x0, %g0 ! Did we get it? + bne 2b ! Nope... +#endif + ld [%g1], %g7 andn %g7, %g2, %g5 - andcc %g3, PSR_PIL, %g0 and %g7, %g2, %g2 +#ifdef __SMP__ + st %g5, [%g1] + set C_LABEL(bitops_spinlock), %g5 + andcc %g3, PSR_PIL, %g0 + bne 1f + stb %g0, [%g5] +#else + andcc %g3, PSR_PIL, %g0 bne 1f st %g5, [%g1] +#endif wr %g3, 0x0, %psr nop; nop; nop 1: @@ -70,12 +98,26 @@ ___change_bit: wr %g3, PSR_PIL, %psr nop; nop; nop 1: - ld [%g1], %g7 +#ifdef __SMP__ + set C_LABEL(bitops_spinlock), %g5 +2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. + orcc %g7, 0x0, %g0 ! Did we get it? + bne 2b ! Nope... +#endif + ld [%g1], %g7 xor %g7, %g2, %g5 - andcc %g3, PSR_PIL, %g0 and %g7, %g2, %g2 +#ifdef __SMP__ + st %g5, [%g1] + set C_LABEL(bitops_spinlock), %g5 + andcc %g3, PSR_PIL, %g0 + bne 1f + stb %g0, [%g5] +#else + andcc %g3, PSR_PIL, %g0 bne 1f st %g5, [%g1] +#endif wr %g3, 0x0, %psr nop; nop; nop 1: @@ -92,12 +134,26 @@ ___set_le_bit: wr %g3, PSR_PIL, %psr nop; nop; nop 1: - ldub [%g1], %g7 +#ifdef __SMP__ + set C_LABEL(bitops_spinlock), %g5 +2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. + orcc %g7, 0x0, %g0 ! Did we get it? + bne 2b ! Nope... +#endif + ldub [%g1], %g7 or %g7, %g2, %g5 - andcc %g3, PSR_PIL, %g0 and %g7, %g2, %g2 +#ifdef __SMP__ + stb %g5, [%g1] + set C_LABEL(bitops_spinlock), %g5 + andcc %g3, PSR_PIL, %g0 + bne 1f + stb %g0, [%g5] +#else + andcc %g3, PSR_PIL, %g0 bne 1f stb %g5, [%g1] +#endif wr %g3, 0x0, %psr nop; nop; nop 1: @@ -113,12 +169,26 @@ ___clear_le_bit: wr %g3, PSR_PIL, %psr nop; nop; nop 1: - ldub [%g1], %g7 +#ifdef __SMP__ + set C_LABEL(bitops_spinlock), %g5 +2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. + orcc %g7, 0x0, %g0 ! Did we get it? + bne 2b ! Nope... +#endif + ldub [%g1], %g7 andn %g7, %g2, %g5 - andcc %g3, PSR_PIL, %g0 and %g7, %g2, %g2 +#ifdef __SMP__ + stb %g5, [%g1] + set C_LABEL(bitops_spinlock), %g5 + andcc %g3, PSR_PIL, %g0 + bne 1f + stb %g0, [%g5] +#else + andcc %g3, PSR_PIL, %g0 bne 1f stb %g5, [%g1] +#endif wr %g3, 0x0, %psr nop; nop; nop 1: diff --git a/arch/sparc/lib/copy_user.S b/arch/sparc/lib/copy_user.S index fceaf7a4b..728cbf9bd 100644 --- a/arch/sparc/lib/copy_user.S +++ b/arch/sparc/lib/copy_user.S @@ -3,7 +3,7 @@ * Copyright(C) 1995 Linus Torvalds * Copyright(C) 1996 David S. Miller * Copyright(C) 1996 Eddie C. Dost - * Copyright(C) 1996 Jakub Jelinek + * Copyright(C) 1996,1998 Jakub Jelinek * * derived from: * e-mail between David and Eddie. @@ -13,13 +13,14 @@ #include <asm/cprefix.h> #include <asm/ptrace.h> +#include <asm/asmmacro.h> #define EX(x,y,a,b,z) \ 98: x,y; \ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ -99: retl; \ - a, b, %o0; \ +99: ba fixupretl; \ + a, b, %g3; \ .section __ex_table,z##alloc; \ .align 4; \ .word 98b, 99b; \ @@ -31,8 +32,8 @@ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ 99: c, d, e; \ - retl; \ - a, b, %o0; \ + ba fixupretl; \ + a, b, %g3; \ .section __ex_table,z##alloc; \ .align 4; \ .word 98b, 99b; \ @@ -340,7 +341,7 @@ short_aligned_end: andcc %o2, 4, %g0 EXO2(ld [%o1 + 0x00], %g2,#) - EX(ld [%o1 + 0x04], %g3, sub %o2, 4,#) + EXO2(ld [%o1 + 0x04], %g3,#) add %o1, 8, %o1 EXO2(st %g2, [%o0 + 0x00],#) EX(st %g3, [%o0 + 0x04], sub %o2, 4,#) @@ -352,16 +353,32 @@ short_aligned_end: .section .fixup,#alloc,#execinstr .align 4 97: - retl - mov %o2, %o0 + mov %o2, %g3 +fixupretl: + GET_PAGE_OFFSET(g1) + cmp %o0, %g1 + blu 1f + cmp %o1, %g1 + bgeu 1f + nop + save %sp, -64, %sp + mov %i0, %o0 + call __bzero + mov %g3, %o1 + restore +1: retl + mov %g3, %o0 + /* exception routine sets %g2 to (broken_insn - first_insn)>>2 */ 50: /* This magic counts how many bytes are left when crash in MOVE_BIGCHUNK * happens. This is derived from the amount ldd reads, st stores, etc. * x = g2 % 12; - * o0 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? x * 8 : (x - 4) * 4) + * g3 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? 0 : (x - 4) * 4); + * o0 += (g2 / 12) * 32; */ cmp %g2, 12 + add %o0, %g7, %o0 bcs 1f cmp %g2, 24 bcs 2f @@ -370,84 +387,97 @@ short_aligned_end: nop sub %g2, 12, %g2 sub %g7, 32, %g7 -3: - sub %g2, 12, %g2 +3: sub %g2, 12, %g2 sub %g7, 32, %g7 -2: - sub %g2, 12, %g2 +2: sub %g2, 12, %g2 sub %g7, 32, %g7 -1: - cmp %g2, 4 - bcs,a 1f - sll %g2, 3, %g2 +1: cmp %g2, 4 + bcs,a 60f + clr %g2 sub %g2, 4, %g2 sll %g2, 2, %g2 -1: - and %g1, 0x7f, %o0 - add %o0, %g7, %o0 - retl - sub %o0, %g2, %o0 +60: and %g1, 0x7f, %g3 + sub %o0, %g7, %o0 + add %g3, %g7, %g3 + ba fixupretl + sub %g3, %g2, %g3 51: /* i = 41 - g2; j = i % 6; - * o0 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : (j - 3) * 8; + * g3 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : 16; + * o0 -= (i / 6) * 16 + 16; */ neg %g2 and %g1, 0xf, %g1 add %g2, 41, %g2 -1: - cmp %g2, 6 + add %o0, %g1, %o0 +1: cmp %g2, 6 bcs,a 2f cmp %g2, 4 add %g1, 16, %g1 b 1b sub %g2, 6, %g2 -2: - bcs,a 3f - inc %g2 - sub %g2, 3, %g2 - b 2f - sll %g2, 3, %g2 -3: +2: bcc,a 2f + mov 16, %g2 + inc %g2 sll %g2, 2, %g2 -2: - retl - add %g1, %g2, %o0 +2: add %g1, %g2, %g3 + ba fixupretl + sub %o0, %g3, %o0 52: -/* o0 = g1 + g7 - (g2 / 8) * 32 + (x & 3) * 8 */ - and %g2, 0xfffffff8, %g4 +/* g3 = g1 + g7 - (g2 / 8) * 32 + (g2 & 4) ? (g2 & 3) * 8 : 0; + o0 += (g2 / 8) * 32 */ + andn %g2, 7, %g4 + add %o0, %g7, %o0 + andcc %g2, 4, %g0 and %g2, 3, %g2 sll %g4, 2, %g4 sll %g2, 3, %g2 - add %g2, %g4, %g2 - b,a 1b + bne 60b + sub %g7, %g4, %g7 + ba 60b + clr %g2 53: -/* o0 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 3) * 2 */ +/* g3 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 4) ? (g2 & 3) * 2 : 0; + o0 += (g2 & 8) */ and %g2, 3, %g4 - and %g2, 0xfffffff8, %g2 + andcc %g2, 4, %g0 + and %g2, 8, %g2 sll %g4, 1, %g4 + be 1f + add %o0, %g2, %o0 add %g2, %g4, %g2 - and %o2, 0xf, %o0 - add %o0, %o3, %o0 - retl - sub %o0, %g2, %o0 +1: and %o2, 0xf, %g3 + add %g3, %o3, %g3 + ba fixupretl + sub %g3, %g2, %g3 54: -/* o0 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 1) */ +/* g3 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 2) ? (g2 & 1) : 0; + o0 += (g2 / 4) * 2 */ srl %g2, 2, %o4 - and %g2, 1, %o1 - sll %o4, 1, %o4 + and %g2, 1, %o5 + srl %g2, 1, %g2 + add %o4, %o4, %o4 + and %o5, %g2, %o5 and %o2, 0xf, %o2 - sub %o3, %o1, %o3 + add %o0, %o4, %o0 + sub %o3, %o5, %o3 sub %o2, %o4, %o2 - retl - add %o2, %o3, %o0 + ba fixupretl + add %o2, %o3, %g3 55: -/* o0 = (o2 & 1) + (27 - g2)/4 * 2 + ((27 - g2) & 1) */ +/* i = 27 - g2; + g3 = (o2 & 1) + i / 4 * 2 + !(i & 3); + o0 -= i / 4 * 2 + 1 */ neg %g2 and %o2, 1, %o2 add %g2, 27, %g2 - srl %g2, 2, %o1 - and %g2, 1, %g2 - sll %o1, 1, %o1 - add %o2, %g2, %o0 - retl - add %o0, %o1, %o0 + srl %g2, 2, %o5 + andcc %g2, 3, %g0 + mov 1, %g2 + add %o5, %o5, %o5 + be,a 1f + clr %g2 +1: add %g2, %o5, %g3 + sub %o0, %g3, %o0 + ba fixupretl + add %g3, %o2, %g3 diff --git a/arch/sparc/lib/debuglocks.c b/arch/sparc/lib/debuglocks.c index 006cba5a8..8f0941ebf 100644 --- a/arch/sparc/lib/debuglocks.c +++ b/arch/sparc/lib/debuglocks.c @@ -1,7 +1,8 @@ -/* $Id: debuglocks.c,v 1.1 1997/05/08 18:13:34 davem Exp $ +/* $Id: debuglocks.c,v 1.5 1998/10/14 09:19:04 jj Exp $ * debuglocks.c: Debugging versions of SMP locking primitives. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1998 Anton Blanchard (anton@progsoc.uts.edu.au) */ #include <linux/kernel.h> @@ -22,75 +23,56 @@ * number of the owner in the lowest two bits. */ -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("spin_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; } +#define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A)); -void _spin_lock(spinlock_t *lock) +static inline void show(char *str, spinlock_t *lock, unsigned long caller) { - unsigned long caller; - unsigned long val; int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); -again: - __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock))); - if(val) { - while(lock->lock) { - STUCK; - barrier(); - } - goto again; - } - lock->owner_pc = (cpu & 3) | (caller & ~3); + printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str, + lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); } -int _spin_trylock(spinlock_t *lock) +static inline void show_read(char *str, rwlock_t *lock, unsigned long caller) { - unsigned long val; - unsigned long caller; int cpu = smp_processor_id(); - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock))); - if(!val) { - /* We got it, record our identity for debugging. */ - lock->owner_pc = (cpu & 3) | (caller & ~3); - } - return val == 0; + printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str, + lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); } -void _spin_unlock(spinlock_t *lock) +static inline void show_write(char *str, rwlock_t *lock, unsigned long caller) { - lock->owner_pc = 0; - __asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory"); + int cpu = smp_processor_id(); + + printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx) reader[0]=%08lx reader[1]=%08lx reader[2]=%08lx reader[3]=%08lx\n", + str, lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3, + lock->reader_pc[0], + lock->reader_pc[1], + lock->reader_pc[2], + lock->reader_pc[3]); } #undef INIT_STUCK #define INIT_STUCK 100000000 -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("spin_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; } - -void _spin_lock_irq(spinlock_t *lock) +void _do_spin_lock(spinlock_t *lock, char *str) { unsigned long caller; unsigned long val; int cpu = smp_processor_id(); int stuck = INIT_STUCK; - __cli(); - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); + STORE_CALLER(caller); + again: __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock))); if(val) { while(lock->lock) { - STUCK; + if (!--stuck) { + show(str, lock, caller); + stuck = INIT_STUCK; + } barrier(); } goto again; @@ -98,362 +80,126 @@ again: lock->owner_pc = (cpu & 3) | (caller & ~3); } -void _spin_unlock_irq(spinlock_t *lock) -{ - lock->owner_pc = 0; - __asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory"); - __sti(); -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("spin_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; } - -/* Caller macro does __save_and_cli(flags) for us. */ -void _spin_lock_irqsave(spinlock_t *lock) +int _spin_trylock(spinlock_t *lock) { - unsigned long caller; unsigned long val; + unsigned long caller; int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); -again: + STORE_CALLER(caller); + __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock))); - if(val) { - while(lock->lock) { - STUCK; - barrier(); - } - goto again; + if(!val) { + /* We got it, record our identity for debugging. */ + lock->owner_pc = (cpu & 3) | (caller & ~3); } - lock->owner_pc = (cpu & 3) | (caller & ~3); + return val == 0; } -void _spin_unlock_irqrestore(spinlock_t *lock) +void _do_spin_unlock(spinlock_t *lock) { lock->owner_pc = 0; - __asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory"); + barrier(); + lock->lock = 0; } #undef INIT_STUCK #define INIT_STUCK 100000000 -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _read_lock(rwlock_t *rw) +void _do_read_lock(rwlock_t *rw, char *str) { - unsigned long flags; unsigned long caller; unsigned long val; int cpu = smp_processor_id(); int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __save_and_cli(flags); -wlock_again: - __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff) { - STUCK; - barrier(); - } - goto wlock_again; - } -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; - } - (*((unsigned short *)&rw->lock))++; - barrier(); - (*(((unsigned short *)&rw->lock)+1)) = 0; - __restore_flags(flags); -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_unlock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _read_unlock(rwlock_t *rw) -{ - unsigned long flags, val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __save_and_cli(flags); -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; - } - (*((unsigned short *)&rw->lock))--; - barrier(); - (*(((unsigned char *)&rw->lock)+2))=0; - __restore_flags(flags); -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("write_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } + STORE_CALLER(caller); -void _write_lock(rwlock_t *rw) -{ - unsigned long flags, val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __save_and_cli(flags); wlock_again: __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); if(val) { while(rw->lock & 0xff) { - STUCK; + if (!--stuck) { + show_read(str, rw, caller); + stuck = INIT_STUCK; + } barrier(); } goto wlock_again; } - rw->owner_pc = (cpu & 3) | (caller & ~3); - while(rw->lock & ~0xff) { - STUCK; - barrier(); - } -} -void _write_unlock(rwlock_t *rw) -{ - rw->owner_pc = 0; + rw->reader_pc[cpu] = caller; barrier(); - rw->lock = 0; + rw->lock++; } #undef INIT_STUCK #define INIT_STUCK 100000000 -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _read_lock_irq(rwlock_t *rw) +void _do_read_unlock(rwlock_t *rw, char *str) { unsigned long caller; unsigned long val; int cpu = smp_processor_id(); int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __cli(); -wlock_again: - __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff) { - STUCK; - barrier(); - } - goto wlock_again; - } -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; - } - (*((unsigned short *)&rw->lock))++; - barrier(); - (*(((unsigned short *)&rw->lock)+1)) = 0; -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 + STORE_CALLER(caller); -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_unlock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _read_unlock_irq(rwlock_t *rw) -{ - unsigned long val, caller; - int stuck = INIT_STUCK; - int cpu = smp_processor_id(); - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; - } - (*((unsigned short *)&rw->lock))--; - barrier(); - (*(((unsigned char *)&rw->lock)+2))=0; - __sti(); -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("write_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -void _write_lock_irq(rwlock_t *rw) -{ - unsigned long val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); - __cli(); wlock_again: __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); if(val) { while(rw->lock & 0xff) { - STUCK; + if (!--stuck) { + show_read(str, rw, caller); + stuck = INIT_STUCK; + } barrier(); } goto wlock_again; } - rw->owner_pc = (cpu & 3) | (caller & ~3); - while(rw->lock & ~0xff) { - STUCK; - barrier(); - } -} -void _write_unlock_irq(rwlock_t *rw) -{ - rw->owner_pc = 0; + rw->reader_pc[cpu] = 0; barrier(); - rw->lock = 0; - __sti(); + rw->lock -= 0x1ff; } #undef INIT_STUCK #define INIT_STUCK 100000000 -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_lock_irqsave(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -/* Caller does __save_and_cli(flags) for us. */ -void _read_lock_irqsave(rwlock_t *rw) +void _do_write_lock(rwlock_t *rw, char *str) { unsigned long caller; unsigned long val; int cpu = smp_processor_id(); int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); + STORE_CALLER(caller); + wlock_again: __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); if(val) { - while(rw->lock & 0xff) { - STUCK; +wlock_wait: + while(rw->lock) { + if (!--stuck) { + show_write(str, rw, caller); + stuck = INIT_STUCK; + } barrier(); } goto wlock_again; } -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; - } - (*((unsigned short *)&rw->lock))++; - barrier(); - (*(((unsigned short *)&rw->lock)+1)) = 0; -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("read_unlock_irqrestore(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } -void _read_unlock_irqrestore(rwlock_t *rw) -{ - unsigned long val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); -clock_again: - __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff00) { - STUCK; - barrier(); - } - goto clock_again; + if (rw->lock & ~0xff) { + *(((unsigned char *)&rw->lock)+3) = 0; + barrier(); + goto wlock_wait; } - (*((unsigned short *)&rw->lock))--; - barrier(); - (*(((unsigned char *)&rw->lock)+2))=0; -} - -#undef INIT_STUCK -#define INIT_STUCK 100000000 - -#undef STUCK -#define STUCK \ -if(!--stuck) { printk("write_lock_irqsave(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; } - -/* Caller does __save_and_cli(flags) for us. */ -void _write_lock_irqsave(rwlock_t *rw) -{ - unsigned long val, caller; - int cpu = smp_processor_id(); - int stuck = INIT_STUCK; - __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); -wlock_again: - __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); - if(val) { - while(rw->lock & 0xff) { - STUCK; - barrier(); - } - goto wlock_again; - } + barrier(); rw->owner_pc = (cpu & 3) | (caller & ~3); - while(rw->lock & ~0xff) { - STUCK; - barrier(); - } } -void _write_unlock_irqrestore(rwlock_t *rw) +void _do_write_unlock(rwlock_t *rw) { rw->owner_pc = 0; barrier(); diff --git a/arch/sparc/lib/locks.S b/arch/sparc/lib/locks.S index 8d634704f..102541b18 100644 --- a/arch/sparc/lib/locks.S +++ b/arch/sparc/lib/locks.S @@ -1,7 +1,9 @@ -/* $Id: locks.S,v 1.13 1998/07/30 11:29:28 davem Exp $ +/* $Id: locks.S,v 1.15 1998/10/14 09:18:55 jj Exp $ * locks.S: SMP low-level lock primitives on Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1998 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ #include <asm/cprefix.h> @@ -43,52 +45,48 @@ ___rw_read_enter_spin_on_wlock: ldstub [%g1 + 3], %g2 b ___rw_read_enter_spin_on_wlock ldub [%g1 + 3], %g2 +___rw_read_exit_spin_on_wlock: + orcc %g2, 0x0, %g0 + be,a ___rw_read_exit + ldstub [%g1 + 3], %g2 + b ___rw_read_exit_spin_on_wlock + ldub [%g1 + 3], %g2 ___rw_write_enter_spin_on_wlock: orcc %g2, 0x0, %g0 be,a ___rw_write_enter ldstub [%g1 + 3], %g2 b ___rw_write_enter_spin_on_wlock - ldub [%g1 + 3], %g2 + ld [%g1], %g2 .globl ___rw_read_enter ___rw_read_enter: orcc %g2, 0x0, %g0 bne,a ___rw_read_enter_spin_on_wlock ldub [%g1 + 3], %g2 -1: - ldstub [%g1 + 2], %g7 - orcc %g7, 0x0, %g0 - bne 1b - ldsh [%g1], %g2 + ld [%g1], %g2 add %g2, 1, %g2 - sth %g2, [%g1] - sth %g0, [%g1 + 2] + st %g2, [%g1] retl mov %g4, %o7 - /* We must be careful here to not blow away wlock. */ .globl ___rw_read_exit -___rw_read_exit_spin: - ldstub [%g1 + 2], %g2 ___rw_read_exit: orcc %g2, 0x0, %g0 - bne ___rw_read_exit_spin - ldsh [%g1], %g7 - sub %g7, 1, %g7 - sth %g7, [%g1] - stb %g0, [%g1 + 2] + bne,a ___rw_read_exit_spin_on_wlock + ldub [%g1 + 3], %g2 + ld [%g1], %g2 + sub %g2, 0x1ff, %g2 + st %g2, [%g1] retl mov %g4, %o7 .globl ___rw_write_enter ___rw_write_enter: orcc %g2, 0x0, %g0 - bne,a ___rw_write_enter_spin_on_wlock - ldub [%g1 + 3], %g2 - ld [%g1], %g2 -1: - andncc %g2, 0xff, %g0 - bne,a 1b + bne ___rw_write_enter_spin_on_wlock ld [%g1], %g2 + andncc %g2, 0xff, %g0 + bne,a ___rw_write_enter_spin_on_wlock + stb %g0, [%g1 + 3] retl mov %g4, %o7 |