diff options
author | Peter Zijlstra <peterz@infradead.org> | 2014-03-26 13:12:45 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-08-14 06:48:12 -0400 |
commit | c6470150dff9aff682063890c9b8eac71b695def (patch) | |
tree | 8c38eda25c4e350e9d0dd9e04818c3b7b2d7f9a7 /arch/sh | |
parent | af095dd60bdc52b11c186c3151e8e38d6faa094c (diff) |
locking,arch,sh: Fold atomic_ops
Many of the atomic op implementations are the same except for one
instruction; fold the lot into a few CPP macros and reduce LoC.
This also prepares for easy addition of new ops.
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: linux-sh@vger.kernel.org
Link: http://lkml.kernel.org/r/20140508135852.770036493@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/include/asm/atomic-grb.h | 119 | ||||
-rw-r--r-- | arch/sh/include/asm/atomic-irq.h | 62 | ||||
-rw-r--r-- | arch/sh/include/asm/atomic-llsc.h | 101 |
3 files changed, 112 insertions, 170 deletions
diff --git a/arch/sh/include/asm/atomic-grb.h b/arch/sh/include/asm/atomic-grb.h index a273c88578fc..97a5fda83450 100644 --- a/arch/sh/include/asm/atomic-grb.h +++ b/arch/sh/include/asm/atomic-grb.h | |||
@@ -1,85 +1,56 @@ | |||
1 | #ifndef __ASM_SH_ATOMIC_GRB_H | 1 | #ifndef __ASM_SH_ATOMIC_GRB_H |
2 | #define __ASM_SH_ATOMIC_GRB_H | 2 | #define __ASM_SH_ATOMIC_GRB_H |
3 | 3 | ||
4 | static inline void atomic_add(int i, atomic_t *v) | 4 | #define ATOMIC_OP(op) \ |
5 | { | 5 | static inline void atomic_##op(int i, atomic_t *v) \ |
6 | int tmp; | 6 | { \ |
7 | 7 | int tmp; \ | |
8 | __asm__ __volatile__ ( | 8 | \ |
9 | " .align 2 \n\t" | 9 | __asm__ __volatile__ ( \ |
10 | " mova 1f, r0 \n\t" /* r0 = end point */ | 10 | " .align 2 \n\t" \ |
11 | " mov r15, r1 \n\t" /* r1 = saved sp */ | 11 | " mova 1f, r0 \n\t" /* r0 = end point */ \ |
12 | " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ | 12 | " mov r15, r1 \n\t" /* r1 = saved sp */ \ |
13 | " mov.l @%1, %0 \n\t" /* load old value */ | 13 | " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ \ |
14 | " add %2, %0 \n\t" /* add */ | 14 | " mov.l @%1, %0 \n\t" /* load old value */ \ |
15 | " mov.l %0, @%1 \n\t" /* store new value */ | 15 | " " #op " %2, %0 \n\t" /* $op */ \ |
16 | "1: mov r1, r15 \n\t" /* LOGOUT */ | 16 | " mov.l %0, @%1 \n\t" /* store new value */ \ |
17 | : "=&r" (tmp), | 17 | "1: mov r1, r15 \n\t" /* LOGOUT */ \ |
18 | "+r" (v) | 18 | : "=&r" (tmp), \ |
19 | : "r" (i) | 19 | "+r" (v) \ |
20 | : "memory" , "r0", "r1"); | 20 | : "r" (i) \ |
21 | } | 21 | : "memory" , "r0", "r1"); \ |
22 | 22 | } \ | |
23 | static inline void atomic_sub(int i, atomic_t *v) | ||
24 | { | ||
25 | int tmp; | ||
26 | |||
27 | __asm__ __volatile__ ( | ||
28 | " .align 2 \n\t" | ||
29 | " mova 1f, r0 \n\t" /* r0 = end point */ | ||
30 | " mov r15, r1 \n\t" /* r1 = saved sp */ | ||
31 | " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ | ||
32 | " mov.l @%1, %0 \n\t" /* load old value */ | ||
33 | " sub %2, %0 \n\t" /* sub */ | ||
34 | " mov.l %0, @%1 \n\t" /* store new value */ | ||
35 | "1: mov r1, r15 \n\t" /* LOGOUT */ | ||
36 | : "=&r" (tmp), | ||
37 | "+r" (v) | ||
38 | : "r" (i) | ||
39 | : "memory" , "r0", "r1"); | ||
40 | } | ||
41 | |||
42 | static inline int atomic_add_return(int i, atomic_t *v) | ||
43 | { | ||
44 | int tmp; | ||
45 | 23 | ||
46 | __asm__ __volatile__ ( | 24 | #define ATOMIC_OP_RETURN(op) \ |
47 | " .align 2 \n\t" | 25 | static inline int atomic_##op##_return(int i, atomic_t *v) \ |
48 | " mova 1f, r0 \n\t" /* r0 = end point */ | 26 | { \ |
49 | " mov r15, r1 \n\t" /* r1 = saved sp */ | 27 | int tmp; \ |
50 | " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ | 28 | \ |
51 | " mov.l @%1, %0 \n\t" /* load old value */ | 29 | __asm__ __volatile__ ( \ |
52 | " add %2, %0 \n\t" /* add */ | 30 | " .align 2 \n\t" \ |
53 | " mov.l %0, @%1 \n\t" /* store new value */ | 31 | " mova 1f, r0 \n\t" /* r0 = end point */ \ |
54 | "1: mov r1, r15 \n\t" /* LOGOUT */ | 32 | " mov r15, r1 \n\t" /* r1 = saved sp */ \ |
55 | : "=&r" (tmp), | 33 | " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ \ |
56 | "+r" (v) | 34 | " mov.l @%1, %0 \n\t" /* load old value */ \ |
57 | : "r" (i) | 35 | " " #op " %2, %0 \n\t" /* $op */ \ |
58 | : "memory" , "r0", "r1"); | 36 | " mov.l %0, @%1 \n\t" /* store new value */ \ |
59 | 37 | "1: mov r1, r15 \n\t" /* LOGOUT */ \ | |
60 | return tmp; | 38 | : "=&r" (tmp), \ |
39 | "+r" (v) \ | ||
40 | : "r" (i) \ | ||
41 | : "memory" , "r0", "r1"); \ | ||
42 | \ | ||
43 | return tmp; \ | ||
61 | } | 44 | } |
62 | 45 | ||
63 | static inline int atomic_sub_return(int i, atomic_t *v) | 46 | #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) |
64 | { | ||
65 | int tmp; | ||
66 | 47 | ||
67 | __asm__ __volatile__ ( | 48 | ATOMIC_OPS(add) |
68 | " .align 2 \n\t" | 49 | ATOMIC_OPS(sub) |
69 | " mova 1f, r0 \n\t" /* r0 = end point */ | ||
70 | " mov r15, r1 \n\t" /* r1 = saved sp */ | ||
71 | " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ | ||
72 | " mov.l @%1, %0 \n\t" /* load old value */ | ||
73 | " sub %2, %0 \n\t" /* sub */ | ||
74 | " mov.l %0, @%1 \n\t" /* store new value */ | ||
75 | "1: mov r1, r15 \n\t" /* LOGOUT */ | ||
76 | : "=&r" (tmp), | ||
77 | "+r" (v) | ||
78 | : "r" (i) | ||
79 | : "memory", "r0", "r1"); | ||
80 | 50 | ||
81 | return tmp; | 51 | #undef ATOMIC_OPS |
82 | } | 52 | #undef ATOMIC_OP_RETURN |
53 | #undef ATOMIC_OP | ||
83 | 54 | ||
84 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | 55 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
85 | { | 56 | { |
diff --git a/arch/sh/include/asm/atomic-irq.h b/arch/sh/include/asm/atomic-irq.h index 9f7c56609e53..61d107523f06 100644 --- a/arch/sh/include/asm/atomic-irq.h +++ b/arch/sh/include/asm/atomic-irq.h | |||
@@ -8,49 +8,39 @@ | |||
8 | * forward to code at the end of this object's .text section, then | 8 | * forward to code at the end of this object's .text section, then |
9 | * branch back to restart the operation. | 9 | * branch back to restart the operation. |
10 | */ | 10 | */ |
11 | static inline void atomic_add(int i, atomic_t *v) | ||
12 | { | ||
13 | unsigned long flags; | ||
14 | |||
15 | raw_local_irq_save(flags); | ||
16 | v->counter += i; | ||
17 | raw_local_irq_restore(flags); | ||
18 | } | ||
19 | 11 | ||
20 | static inline void atomic_sub(int i, atomic_t *v) | 12 | #define ATOMIC_OP(op, c_op) \ |
21 | { | 13 | static inline void atomic_##op(int i, atomic_t *v) \ |
22 | unsigned long flags; | 14 | { \ |
23 | 15 | unsigned long flags; \ | |
24 | raw_local_irq_save(flags); | 16 | \ |
25 | v->counter -= i; | 17 | raw_local_irq_save(flags); \ |
26 | raw_local_irq_restore(flags); | 18 | v->counter c_op i; \ |
19 | raw_local_irq_restore(flags); \ | ||
27 | } | 20 | } |
28 | 21 | ||
29 | static inline int atomic_add_return(int i, atomic_t *v) | 22 | #define ATOMIC_OP_RETURN(op, c_op) \ |
30 | { | 23 | static inline int atomic_##op##_return(int i, atomic_t *v) \ |
31 | unsigned long temp, flags; | 24 | { \ |
32 | 25 | unsigned long temp, flags; \ | |
33 | raw_local_irq_save(flags); | 26 | \ |
34 | temp = v->counter; | 27 | raw_local_irq_save(flags); \ |
35 | temp += i; | 28 | temp = v->counter; \ |
36 | v->counter = temp; | 29 | temp c_op i; \ |
37 | raw_local_irq_restore(flags); | 30 | v->counter = temp; \ |
38 | 31 | raw_local_irq_restore(flags); \ | |
39 | return temp; | 32 | \ |
33 | return temp; \ | ||
40 | } | 34 | } |
41 | 35 | ||
42 | static inline int atomic_sub_return(int i, atomic_t *v) | 36 | #define ATOMIC_OPS(op, c_op) ATOMIC_OP(op, c_op) ATOMIC_OP_RETURN(op, c_op) |
43 | { | ||
44 | unsigned long temp, flags; | ||
45 | 37 | ||
46 | raw_local_irq_save(flags); | 38 | ATOMIC_OPS(add, +=) |
47 | temp = v->counter; | 39 | ATOMIC_OPS(sub, -=) |
48 | temp -= i; | ||
49 | v->counter = temp; | ||
50 | raw_local_irq_restore(flags); | ||
51 | 40 | ||
52 | return temp; | 41 | #undef ATOMIC_OPS |
53 | } | 42 | #undef ATOMIC_OP_RETURN |
43 | #undef ATOMIC_OP | ||
54 | 44 | ||
55 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | 45 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
56 | { | 46 | { |
diff --git a/arch/sh/include/asm/atomic-llsc.h b/arch/sh/include/asm/atomic-llsc.h index 4b00b78e3f4f..8575dccb9ef7 100644 --- a/arch/sh/include/asm/atomic-llsc.h +++ b/arch/sh/include/asm/atomic-llsc.h | |||
@@ -2,39 +2,6 @@ | |||
2 | #define __ASM_SH_ATOMIC_LLSC_H | 2 | #define __ASM_SH_ATOMIC_LLSC_H |
3 | 3 | ||
4 | /* | 4 | /* |
5 | * To get proper branch prediction for the main line, we must branch | ||
6 | * forward to code at the end of this object's .text section, then | ||
7 | * branch back to restart the operation. | ||
8 | */ | ||
9 | static inline void atomic_add(int i, atomic_t *v) | ||
10 | { | ||
11 | unsigned long tmp; | ||
12 | |||
13 | __asm__ __volatile__ ( | ||
14 | "1: movli.l @%2, %0 ! atomic_add \n" | ||
15 | " add %1, %0 \n" | ||
16 | " movco.l %0, @%2 \n" | ||
17 | " bf 1b \n" | ||
18 | : "=&z" (tmp) | ||
19 | : "r" (i), "r" (&v->counter) | ||
20 | : "t"); | ||
21 | } | ||
22 | |||
23 | static inline void atomic_sub(int i, atomic_t *v) | ||
24 | { | ||
25 | unsigned long tmp; | ||
26 | |||
27 | __asm__ __volatile__ ( | ||
28 | "1: movli.l @%2, %0 ! atomic_sub \n" | ||
29 | " sub %1, %0 \n" | ||
30 | " movco.l %0, @%2 \n" | ||
31 | " bf 1b \n" | ||
32 | : "=&z" (tmp) | ||
33 | : "r" (i), "r" (&v->counter) | ||
34 | : "t"); | ||
35 | } | ||
36 | |||
37 | /* | ||
38 | * SH-4A note: | 5 | * SH-4A note: |
39 | * | 6 | * |
40 | * We basically get atomic_xxx_return() for free compared with | 7 | * We basically get atomic_xxx_return() for free compared with |
@@ -42,39 +9,53 @@ static inline void atomic_sub(int i, atomic_t *v) | |||
42 | * encoding, so the retval is automatically set without having to | 9 | * encoding, so the retval is automatically set without having to |
43 | * do any special work. | 10 | * do any special work. |
44 | */ | 11 | */ |
45 | static inline int atomic_add_return(int i, atomic_t *v) | 12 | /* |
46 | { | 13 | * To get proper branch prediction for the main line, we must branch |
47 | unsigned long temp; | 14 | * forward to code at the end of this object's .text section, then |
15 | * branch back to restart the operation. | ||
16 | */ | ||
48 | 17 | ||
49 | __asm__ __volatile__ ( | 18 | #define ATOMIC_OP(op) \ |
50 | "1: movli.l @%2, %0 ! atomic_add_return \n" | 19 | static inline void atomic_##op(int i, atomic_t *v) \ |
51 | " add %1, %0 \n" | 20 | { \ |
52 | " movco.l %0, @%2 \n" | 21 | unsigned long tmp; \ |
53 | " bf 1b \n" | 22 | \ |
54 | " synco \n" | 23 | __asm__ __volatile__ ( \ |
55 | : "=&z" (temp) | 24 | "1: movli.l @%2, %0 ! atomic_" #op "\n" \ |
56 | : "r" (i), "r" (&v->counter) | 25 | " " #op " %1, %0 \n" \ |
57 | : "t"); | 26 | " movco.l %0, @%2 \n" \ |
27 | " bf 1b \n" \ | ||
28 | : "=&z" (tmp) \ | ||
29 | : "r" (i), "r" (&v->counter) \ | ||
30 | : "t"); \ | ||
31 | } | ||
58 | 32 | ||
59 | return temp; | 33 | #define ATOMIC_OP_RETURN(op) \ |
34 | static inline int atomic_##op##_return(int i, atomic_t *v) \ | ||
35 | { \ | ||
36 | unsigned long temp; \ | ||
37 | \ | ||
38 | __asm__ __volatile__ ( \ | ||
39 | "1: movli.l @%2, %0 ! atomic_" #op "_return \n" \ | ||
40 | " " #op " %1, %0 \n" \ | ||
41 | " movco.l %0, @%2 \n" \ | ||
42 | " bf 1b \n" \ | ||
43 | " synco \n" \ | ||
44 | : "=&z" (temp) \ | ||
45 | : "r" (i), "r" (&v->counter) \ | ||
46 | : "t"); \ | ||
47 | \ | ||
48 | return temp; \ | ||
60 | } | 49 | } |
61 | 50 | ||
62 | static inline int atomic_sub_return(int i, atomic_t *v) | 51 | #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) |
63 | { | ||
64 | unsigned long temp; | ||
65 | 52 | ||
66 | __asm__ __volatile__ ( | 53 | ATOMIC_OPS(add) |
67 | "1: movli.l @%2, %0 ! atomic_sub_return \n" | 54 | ATOMIC_OPS(sub) |
68 | " sub %1, %0 \n" | ||
69 | " movco.l %0, @%2 \n" | ||
70 | " bf 1b \n" | ||
71 | " synco \n" | ||
72 | : "=&z" (temp) | ||
73 | : "r" (i), "r" (&v->counter) | ||
74 | : "t"); | ||
75 | 55 | ||
76 | return temp; | 56 | #undef ATOMIC_OPS |
77 | } | 57 | #undef ATOMIC_OP_RETURN |
58 | #undef ATOMIC_OP | ||
78 | 59 | ||
79 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | 60 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
80 | { | 61 | { |