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 /include/asm-sparc | |
parent | 6d24c8dc2e656b02807aa0506405727d34c0376c (diff) | |
download | linux-7a39f52202a70ff6834e37053e2ee55c7d351621.tar.bz2 |
[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 'include/asm-sparc')
-rw-r--r-- | include/asm-sparc/spinlock.h | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/include/asm-sparc/spinlock.h b/include/asm-sparc/spinlock.h index 557d08959d2f..de2249b267c6 100644 --- a/include/asm-sparc/spinlock.h +++ b/include/asm-sparc/spinlock.h @@ -129,6 +129,7 @@ static inline void __raw_write_lock(raw_rwlock_t *rw) : /* no outputs */ : "r" (lp) : "g2", "g4", "memory", "cc"); + *(volatile __u32 *)&lp->lock = ~0U; } static inline int __raw_write_trylock(raw_rwlock_t *rw) @@ -144,15 +145,40 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw) val = rw->lock & ~0xff; if (val) ((volatile u8*)&rw->lock)[3] = 0; + else + *(volatile u32*)&rw->lock = ~0U; } return (val == 0); } +static inline int __read_trylock(raw_rwlock_t *rw) +{ + register raw_rwlock_t *lp asm("g1"); + register int res asm("o0"); + lp = rw; + __asm__ __volatile__( + "mov %%o7, %%g4\n\t" + "call ___rw_read_try\n\t" + " ldstub [%%g1 + 3], %%g2\n" + : "=r" (res) + : "r" (lp) + : "g2", "g4", "memory", "cc"); + return res; +} + +#define __raw_read_trylock(lock) \ +({ unsigned long flags; \ + int res; \ + local_irq_save(flags); \ + res = __read_trylock(lock); \ + local_irq_restore(flags); \ + res; \ +}) + #define __raw_write_unlock(rw) do { (rw)->lock = 0; } while(0) #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) -#define __raw_read_trylock(lock) generic__raw_read_trylock(lock) #define _raw_spin_relax(lock) cpu_relax() #define _raw_read_relax(lock) cpu_relax() |