diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-03-14 17:05:45 -0600 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-03-14 17:05:45 -0600 |
commit | c5111f504d2a9b0d258d7c4752b4093523315989 (patch) | |
tree | 6a52864aff79691689aea21cb0cb928327d5de5b /arch/m32r/kernel/sys_m32r.c | |
parent | 69eb66d7da7dba2696281981347698e1693c2340 (diff) | |
parent | a488edc914aa1d766a4e2c982b5ae03d5657ec1b (diff) |
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'arch/m32r/kernel/sys_m32r.c')
-rw-r--r-- | arch/m32r/kernel/sys_m32r.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index fe55b28d372..670cb49210a 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -29,28 +29,7 @@ /* * sys_tas() - test-and-set - * linuxthreads testing version */ -#ifndef CONFIG_SMP -asmlinkage int sys_tas(int *addr) -{ - int oldval; - unsigned long flags; - - if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) - return -EFAULT; - local_irq_save(flags); - oldval = *addr; - if (!oldval) - *addr = 1; - local_irq_restore(flags); - return oldval; -} -#else /* CONFIG_SMP */ -#include <linux/spinlock.h> - -static DEFINE_SPINLOCK(tas_lock); - asmlinkage int sys_tas(int *addr) { int oldval; @@ -58,15 +37,43 @@ asmlinkage int sys_tas(int *addr) if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) return -EFAULT; - _raw_spin_lock(&tas_lock); - oldval = *addr; - if (!oldval) - *addr = 1; - _raw_spin_unlock(&tas_lock); + /* atomic operation: + * oldval = *addr; *addr = 1; + */ + __asm__ __volatile__ ( + DCACHE_CLEAR("%0", "r4", "%1") + " .fillinsn\n" + "1:\n" + " lock %0, @%1 -> unlock %2, @%1\n" + "2:\n" + /* NOTE: + * The m32r processor can accept interrupts only + * at the 32-bit instruction boundary. + * So, in the above code, the "unlock" instruction + * can be executed continuously after the "lock" + * instruction execution without any interruptions. + */ + ".section .fixup,\"ax\"\n" + " .balign 4\n" + "3: ldi %0, #%3\n" + " seth r14, #high(2b)\n" + " or3 r14, r14, #low(2b)\n" + " jmp r14\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .balign 4\n" + " .long 1b,3b\n" + ".previous\n" + : "=&r" (oldval) + : "r" (addr), "r" (1), "i"(-EFAULT) + : "r14", "memory" +#ifdef CONFIG_CHIP_M32700_TS1 + , "r4" +#endif /* CONFIG_CHIP_M32700_TS1 */ + ); return oldval; } -#endif /* CONFIG_SMP */ /* * sys_pipe() is the normal C calling standard for creating |