diff options
| author | Al Viro <viro@ftp.linux.org.uk> | 2006-10-08 14:32:15 +0100 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-08 12:32:35 -0700 | 
| commit | 7a39f52202a70ff6834e37053e2ee55c7d351621 (patch) | |
| tree | de2f029495110336d2dd2b89205db2c62710dd50 /arch/sparc | |
| parent | 6d24c8dc2e656b02807aa0506405727d34c0376c (diff) | |
| download | olio-linux-3.10-7a39f52202a70ff6834e37053e2ee55c7d351621.tar.xz olio-linux-3.10-7a39f52202a70ff6834e37053e2ee55c7d351621.zip  | |
[PATCH] sparc32 rwlock fix
read_trylock() is broken on sparc32 (doesn't build and didn't work
right, actually).  Proposed fix:
 - make "writer holds lock" distinguishable from "reader tries to grab
   lock"
 - have __raw_read_trylock() try to acquire the mutex (in LSB of lock),
   terminating spin if we see that there's writer holding it.  Then do
   the rest as we do in read_lock().
Thanks to Ingo for discussion...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/sparc')
| -rw-r--r-- | arch/sparc/kernel/sparc_ksyms.c | 4 | ||||
| -rw-r--r-- | arch/sparc/lib/locks.S | 20 | 
2 files changed, 23 insertions, 1 deletions
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 4d441a554d3..33dadd9f287 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -87,6 +87,7 @@ extern void ___set_bit(void);  extern void ___clear_bit(void);  extern void ___change_bit(void);  extern void ___rw_read_enter(void); +extern void ___rw_read_try(void);  extern void ___rw_read_exit(void);  extern void ___rw_write_enter(void); @@ -104,8 +105,9 @@ extern unsigned _Urem(unsigned, unsigned);  EXPORT_SYMBOL(sparc_cpu_model);  EXPORT_SYMBOL(kernel_thread);  #ifdef CONFIG_SMP -// XXX find what uses (or used) these. +// XXX find what uses (or used) these.   AV: see asm/spinlock.h  EXPORT_SYMBOL(___rw_read_enter); +EXPORT_SYMBOL(___rw_read_try);  EXPORT_SYMBOL(___rw_read_exit);  EXPORT_SYMBOL(___rw_write_enter);  #endif diff --git a/arch/sparc/lib/locks.S b/arch/sparc/lib/locks.S index 95fa4842496..b1df55cb221 100644 --- a/arch/sparc/lib/locks.S +++ b/arch/sparc/lib/locks.S @@ -25,6 +25,15 @@ ___rw_read_enter_spin_on_wlock:  	 ldstub	[%g1 + 3], %g2  	b	___rw_read_enter_spin_on_wlock  	 ldub	[%g1 + 3], %g2 +___rw_read_try_spin_on_wlock: +	andcc	%g2, 0xff, %g0 +	be,a	___rw_read_try +	 ldstub	[%g1 + 3], %g2 +	xnorcc	%g2, 0x0, %o0	/* if g2 is ~0, set o0 to 0 and bugger off */ +	bne,a	___rw_read_enter_spin_on_wlock +	 ld	[%g1], %g2 +	retl +	 mov	%g4, %o7  ___rw_read_exit_spin_on_wlock:  	orcc	%g2, 0x0, %g0  	be,a	___rw_read_exit @@ -60,6 +69,17 @@ ___rw_read_exit:  	retl  	 mov	%g4, %o7 +	.globl	___rw_read_try +___rw_read_try: +	orcc	%g2, 0x0, %g0 +	bne	___rw_read_try_spin_on_wlock +	 ld	[%g1], %g2 +	add	%g2, 1, %g2 +	st	%g2, [%g1] +	set	1, %o1 +	retl +	 mov	%g4, %o7 +  	.globl	___rw_write_enter  ___rw_write_enter:  	orcc	%g2, 0x0, %g0  |