diff options
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 fe55b28d3725..670cb49210af 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c | |||
@@ -29,28 +29,7 @@ | |||
29 | 29 | ||
30 | /* | 30 | /* |
31 | * sys_tas() - test-and-set | 31 | * sys_tas() - test-and-set |
32 | * linuxthreads testing version | ||
33 | */ | 32 | */ |
34 | #ifndef CONFIG_SMP | ||
35 | asmlinkage int sys_tas(int *addr) | ||
36 | { | ||
37 | int oldval; | ||
38 | unsigned long flags; | ||
39 | |||
40 | if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) | ||
41 | return -EFAULT; | ||
42 | local_irq_save(flags); | ||
43 | oldval = *addr; | ||
44 | if (!oldval) | ||
45 | *addr = 1; | ||
46 | local_irq_restore(flags); | ||
47 | return oldval; | ||
48 | } | ||
49 | #else /* CONFIG_SMP */ | ||
50 | #include <linux/spinlock.h> | ||
51 | |||
52 | static DEFINE_SPINLOCK(tas_lock); | ||
53 | |||
54 | asmlinkage int sys_tas(int *addr) | 33 | asmlinkage int sys_tas(int *addr) |
55 | { | 34 | { |
56 | int oldval; | 35 | int oldval; |
@@ -58,15 +37,43 @@ asmlinkage int sys_tas(int *addr) | |||
58 | if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) | 37 | if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) |
59 | return -EFAULT; | 38 | return -EFAULT; |
60 | 39 | ||
61 | _raw_spin_lock(&tas_lock); | 40 | /* atomic operation: |
62 | oldval = *addr; | 41 | * oldval = *addr; *addr = 1; |
63 | if (!oldval) | 42 | */ |
64 | *addr = 1; | 43 | __asm__ __volatile__ ( |
65 | _raw_spin_unlock(&tas_lock); | 44 | DCACHE_CLEAR("%0", "r4", "%1") |
45 | " .fillinsn\n" | ||
46 | "1:\n" | ||
47 | " lock %0, @%1 -> unlock %2, @%1\n" | ||
48 | "2:\n" | ||
49 | /* NOTE: | ||
50 | * The m32r processor can accept interrupts only | ||
51 | * at the 32-bit instruction boundary. | ||
52 | * So, in the above code, the "unlock" instruction | ||
53 | * can be executed continuously after the "lock" | ||
54 | * instruction execution without any interruptions. | ||
55 | */ | ||
56 | ".section .fixup,\"ax\"\n" | ||
57 | " .balign 4\n" | ||
58 | "3: ldi %0, #%3\n" | ||
59 | " seth r14, #high(2b)\n" | ||
60 | " or3 r14, r14, #low(2b)\n" | ||
61 | " jmp r14\n" | ||
62 | ".previous\n" | ||
63 | ".section __ex_table,\"a\"\n" | ||
64 | " .balign 4\n" | ||
65 | " .long 1b,3b\n" | ||
66 | ".previous\n" | ||
67 | : "=&r" (oldval) | ||
68 | : "r" (addr), "r" (1), "i"(-EFAULT) | ||
69 | : "r14", "memory" | ||
70 | #ifdef CONFIG_CHIP_M32700_TS1 | ||
71 | , "r4" | ||
72 | #endif /* CONFIG_CHIP_M32700_TS1 */ | ||
73 | ); | ||
66 | 74 | ||
67 | return oldval; | 75 | return oldval; |
68 | } | 76 | } |
69 | #endif /* CONFIG_SMP */ | ||
70 | 77 | ||
71 | /* | 78 | /* |
72 | * sys_pipe() is the normal C calling standard for creating | 79 | * sys_pipe() is the normal C calling standard for creating |