diff options
author | Peter Zijlstra <peterz@infradead.org> | 2014-03-23 14:06:34 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-08-14 06:48:08 -0400 |
commit | d839bae4269aea46bff4133066a411cfba5c7c46 (patch) | |
tree | af4454c73ca7196041df6611d43642d60527a4e4 | |
parent | c9ebe21b204f95e3aba84ee91c8b9347d73806f1 (diff) |
locking,arch,m68k: 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.
Requires asm_op due to eor.
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: linux-m68k@lists.linux-m68k.org
Link: http://lkml.kernel.org/r/20140509091646.GO30445@twins.programming.kicks-ass.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/m68k/include/asm/atomic.h | 109 |
1 files changed, 47 insertions, 62 deletions
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h index 55695212a2ae..663d4ba2462c 100644 --- a/arch/m68k/include/asm/atomic.h +++ b/arch/m68k/include/asm/atomic.h | |||
@@ -30,16 +30,57 @@ | |||
30 | #define ASM_DI "di" | 30 | #define ASM_DI "di" |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | static inline void atomic_add(int i, atomic_t *v) | 33 | #define ATOMIC_OP(op, c_op, asm_op) \ |
34 | { | 34 | static inline void atomic_##op(int i, atomic_t *v) \ |
35 | __asm__ __volatile__("addl %1,%0" : "+m" (*v) : ASM_DI (i)); | 35 | { \ |
36 | __asm__ __volatile__(#asm_op "l %1,%0" : "+m" (*v) : ASM_DI (i));\ | ||
37 | } \ | ||
38 | |||
39 | #ifdef CONFIG_RMW_INSNS | ||
40 | |||
41 | #define ATOMIC_OP_RETURN(op, c_op, asm_op) \ | ||
42 | static inline int atomic_##op##_return(int i, atomic_t *v) \ | ||
43 | { \ | ||
44 | int t, tmp; \ | ||
45 | \ | ||
46 | __asm__ __volatile__( \ | ||
47 | "1: movel %2,%1\n" \ | ||
48 | " " #asm_op "l %3,%1\n" \ | ||
49 | " casl %2,%1,%0\n" \ | ||
50 | " jne 1b" \ | ||
51 | : "+m" (*v), "=&d" (t), "=&d" (tmp) \ | ||
52 | : "g" (i), "2" (atomic_read(v))); \ | ||
53 | return t; \ | ||
36 | } | 54 | } |
37 | 55 | ||
38 | static inline void atomic_sub(int i, atomic_t *v) | 56 | #else |
39 | { | 57 | |
40 | __asm__ __volatile__("subl %1,%0" : "+m" (*v) : ASM_DI (i)); | 58 | #define ATOMIC_OP_RETURN(op, c_op, asm_op) \ |
59 | static inline int atomic_##op##_return(int i, atomic_t * v) \ | ||
60 | { \ | ||
61 | unsigned long flags; \ | ||
62 | int t; \ | ||
63 | \ | ||
64 | local_irq_save(flags); \ | ||
65 | t = (v->counter c_op i); \ | ||
66 | local_irq_restore(flags); \ | ||
67 | \ | ||
68 | return t; \ | ||
41 | } | 69 | } |
42 | 70 | ||
71 | #endif /* CONFIG_RMW_INSNS */ | ||
72 | |||
73 | #define ATOMIC_OPS(op, c_op, asm_op) \ | ||
74 | ATOMIC_OP(op, c_op, asm_op) \ | ||
75 | ATOMIC_OP_RETURN(op, c_op, asm_op) | ||
76 | |||
77 | ATOMIC_OPS(add, +=, add) | ||
78 | ATOMIC_OPS(sub, -=, sub) | ||
79 | |||
80 | #undef ATOMIC_OPS | ||
81 | #undef ATOMIC_OP_RETURN | ||
82 | #undef ATOMIC_OP | ||
83 | |||
43 | static inline void atomic_inc(atomic_t *v) | 84 | static inline void atomic_inc(atomic_t *v) |
44 | { | 85 | { |
45 | __asm__ __volatile__("addql #1,%0" : "+m" (*v)); | 86 | __asm__ __volatile__("addql #1,%0" : "+m" (*v)); |
@@ -76,67 +117,11 @@ static inline int atomic_inc_and_test(atomic_t *v) | |||
76 | 117 | ||
77 | #ifdef CONFIG_RMW_INSNS | 118 | #ifdef CONFIG_RMW_INSNS |
78 | 119 | ||
79 | static inline int atomic_add_return(int i, atomic_t *v) | ||
80 | { | ||
81 | int t, tmp; | ||
82 | |||
83 | __asm__ __volatile__( | ||
84 | "1: movel %2,%1\n" | ||
85 | " addl %3,%1\n" | ||
86 | " casl %2,%1,%0\n" | ||
87 | " jne 1b" | ||
88 | : "+m" (*v), "=&d" (t), "=&d" (tmp) | ||
89 | : "g" (i), "2" (atomic_read(v))); | ||
90 | return t; | ||
91 | } | ||
92 | |||
93 | static inline int atomic_sub_return(int i, atomic_t *v) | ||
94 | { | ||
95 | int t, tmp; | ||
96 | |||
97 | __asm__ __volatile__( | ||
98 | "1: movel %2,%1\n" | ||
99 | " subl %3,%1\n" | ||
100 | " casl %2,%1,%0\n" | ||
101 | " jne 1b" | ||
102 | : "+m" (*v), "=&d" (t), "=&d" (tmp) | ||
103 | : "g" (i), "2" (atomic_read(v))); | ||
104 | return t; | ||
105 | } | ||
106 | |||
107 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | 120 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) |
108 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | 121 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) |
109 | 122 | ||
110 | #else /* !CONFIG_RMW_INSNS */ | 123 | #else /* !CONFIG_RMW_INSNS */ |
111 | 124 | ||
112 | static inline int atomic_add_return(int i, atomic_t * v) | ||
113 | { | ||
114 | unsigned long flags; | ||
115 | int t; | ||
116 | |||
117 | local_irq_save(flags); | ||
118 | t = atomic_read(v); | ||
119 | t += i; | ||
120 | atomic_set(v, t); | ||
121 | local_irq_restore(flags); | ||
122 | |||
123 | return t; | ||
124 | } | ||
125 | |||
126 | static inline int atomic_sub_return(int i, atomic_t * v) | ||
127 | { | ||
128 | unsigned long flags; | ||
129 | int t; | ||
130 | |||
131 | local_irq_save(flags); | ||
132 | t = atomic_read(v); | ||
133 | t -= i; | ||
134 | atomic_set(v, t); | ||
135 | local_irq_restore(flags); | ||
136 | |||
137 | return t; | ||
138 | } | ||
139 | |||
140 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | 125 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) |
141 | { | 126 | { |
142 | unsigned long flags; | 127 | unsigned long flags; |