aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2014-03-23 11:25:53 -0400
committerIngo Molnar <mingo@kernel.org>2014-08-14 06:48:03 -0400
commitb93c7b8c5b281bf3646d6c5b6e05249b98cc5ab7 (patch)
tree4bfb8396fc5175fec6f241902950101893a076b7
parentf6b4ecee0eb7bfa66ae8d5652105ed4da53209a3 (diff)
locking,arch,alpha: 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. Cc: Matt Turner <mattst88@gmail.com> Cc: Richard Henderson <rth@twiddle.net> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Cc: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Matt Turner <mattst88@gmail.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Richard Henderson <rth@twiddle.net> Cc: linux-alpha@vger.kernel.org Link: http://lkml.kernel.org/r/20140508135851.832107183@infradead.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/alpha/include/asm/atomic.h213
1 files changed, 80 insertions, 133 deletions
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index ed60a1ee1ed3..6fbb53a13049 100644
--- a/arch/alpha/include/asm/atomic.h
+++ b/arch/alpha/include/asm/atomic.h
@@ -29,145 +29,92 @@
29 * branch back to restart the operation. 29 * branch back to restart the operation.
30 */ 30 */
31 31
32static __inline__ void atomic_add(int i, atomic_t * v) 32#define ATOMIC_OP(op) \
33{ 33static __inline__ void atomic_##op(int i, atomic_t * v) \
34 unsigned long temp; 34{ \
35 __asm__ __volatile__( 35 unsigned long temp; \
36 "1: ldl_l %0,%1\n" 36 __asm__ __volatile__( \
37 " addl %0,%2,%0\n" 37 "1: ldl_l %0,%1\n" \
38 " stl_c %0,%1\n" 38 " " #op "l %0,%2,%0\n" \
39 " beq %0,2f\n" 39 " stl_c %0,%1\n" \
40 ".subsection 2\n" 40 " beq %0,2f\n" \
41 "2: br 1b\n" 41 ".subsection 2\n" \
42 ".previous" 42 "2: br 1b\n" \
43 :"=&r" (temp), "=m" (v->counter) 43 ".previous" \
44 :"Ir" (i), "m" (v->counter)); 44 :"=&r" (temp), "=m" (v->counter) \
45} 45 :"Ir" (i), "m" (v->counter)); \
46 46} \
47static __inline__ void atomic64_add(long i, atomic64_t * v) 47
48{ 48#define ATOMIC_OP_RETURN(op) \
49 unsigned long temp; 49static inline int atomic_##op##_return(int i, atomic_t *v) \
50 __asm__ __volatile__( 50{ \
51 "1: ldq_l %0,%1\n" 51 long temp, result; \
52 " addq %0,%2,%0\n" 52 smp_mb(); \
53 " stq_c %0,%1\n" 53 __asm__ __volatile__( \
54 " beq %0,2f\n" 54 "1: ldl_l %0,%1\n" \
55 ".subsection 2\n" 55 " " #op "l %0,%3,%2\n" \
56 "2: br 1b\n" 56 " " #op "l %0,%3,%0\n" \
57 ".previous" 57 " stl_c %0,%1\n" \
58 :"=&r" (temp), "=m" (v->counter) 58 " beq %0,2f\n" \
59 :"Ir" (i), "m" (v->counter)); 59 ".subsection 2\n" \
60} 60 "2: br 1b\n" \
61 61 ".previous" \
62static __inline__ void atomic_sub(int i, atomic_t * v) 62 :"=&r" (temp), "=m" (v->counter), "=&r" (result) \
63{ 63 :"Ir" (i), "m" (v->counter) : "memory"); \
64 unsigned long temp; 64 smp_mb(); \
65 __asm__ __volatile__( 65 return result; \
66 "1: ldl_l %0,%1\n"
67 " subl %0,%2,%0\n"
68 " stl_c %0,%1\n"
69 " beq %0,2f\n"
70 ".subsection 2\n"
71 "2: br 1b\n"
72 ".previous"
73 :"=&r" (temp), "=m" (v->counter)
74 :"Ir" (i), "m" (v->counter));
75} 66}
76 67
77static __inline__ void atomic64_sub(long i, atomic64_t * v) 68#define ATOMIC64_OP(op) \
78{ 69static __inline__ void atomic64_##op(long i, atomic64_t * v) \
79 unsigned long temp; 70{ \
80 __asm__ __volatile__( 71 unsigned long temp; \
81 "1: ldq_l %0,%1\n" 72 __asm__ __volatile__( \
82 " subq %0,%2,%0\n" 73 "1: ldq_l %0,%1\n" \
83 " stq_c %0,%1\n" 74 " " #op "q %0,%2,%0\n" \
84 " beq %0,2f\n" 75 " stq_c %0,%1\n" \
85 ".subsection 2\n" 76 " beq %0,2f\n" \
86 "2: br 1b\n" 77 ".subsection 2\n" \
87 ".previous" 78 "2: br 1b\n" \
88 :"=&r" (temp), "=m" (v->counter) 79 ".previous" \
89 :"Ir" (i), "m" (v->counter)); 80 :"=&r" (temp), "=m" (v->counter) \
90} 81 :"Ir" (i), "m" (v->counter)); \
91 82} \
92 83
93/* 84#define ATOMIC64_OP_RETURN(op) \
94 * Same as above, but return the result value 85static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \
95 */ 86{ \
96static inline int atomic_add_return(int i, atomic_t *v) 87 long temp, result; \
97{ 88 smp_mb(); \
98 long temp, result; 89 __asm__ __volatile__( \
99 smp_mb(); 90 "1: ldq_l %0,%1\n" \
100 __asm__ __volatile__( 91 " " #op "q %0,%3,%2\n" \
101 "1: ldl_l %0,%1\n" 92 " " #op "q %0,%3,%0\n" \
102 " addl %0,%3,%2\n" 93 " stq_c %0,%1\n" \
103 " addl %0,%3,%0\n" 94 " beq %0,2f\n" \
104 " stl_c %0,%1\n" 95 ".subsection 2\n" \
105 " beq %0,2f\n" 96 "2: br 1b\n" \
106 ".subsection 2\n" 97 ".previous" \
107 "2: br 1b\n" 98 :"=&r" (temp), "=m" (v->counter), "=&r" (result) \
108 ".previous" 99 :"Ir" (i), "m" (v->counter) : "memory"); \
109 :"=&r" (temp), "=m" (v->counter), "=&r" (result) 100 smp_mb(); \
110 :"Ir" (i), "m" (v->counter) : "memory"); 101 return result; \
111 smp_mb();
112 return result;
113} 102}
114 103
115static __inline__ long atomic64_add_return(long i, atomic64_t * v) 104#define ATOMIC_OPS(opg) \
116{ 105 ATOMIC_OP(opg) \
117 long temp, result; 106 ATOMIC_OP_RETURN(opg) \
118 smp_mb(); 107 ATOMIC64_OP(opg) \
119 __asm__ __volatile__( 108 ATOMIC64_OP_RETURN(opg)
120 "1: ldq_l %0,%1\n"
121 " addq %0,%3,%2\n"
122 " addq %0,%3,%0\n"
123 " stq_c %0,%1\n"
124 " beq %0,2f\n"
125 ".subsection 2\n"
126 "2: br 1b\n"
127 ".previous"
128 :"=&r" (temp), "=m" (v->counter), "=&r" (result)
129 :"Ir" (i), "m" (v->counter) : "memory");
130 smp_mb();
131 return result;
132}
133 109
134static __inline__ long atomic_sub_return(int i, atomic_t * v) 110ATOMIC_OPS(add)
135{ 111ATOMIC_OPS(sub)
136 long temp, result;
137 smp_mb();
138 __asm__ __volatile__(
139 "1: ldl_l %0,%1\n"
140 " subl %0,%3,%2\n"
141 " subl %0,%3,%0\n"
142 " stl_c %0,%1\n"
143 " beq %0,2f\n"
144 ".subsection 2\n"
145 "2: br 1b\n"
146 ".previous"
147 :"=&r" (temp), "=m" (v->counter), "=&r" (result)
148 :"Ir" (i), "m" (v->counter) : "memory");
149 smp_mb();
150 return result;
151}
152 112
153static __inline__ long atomic64_sub_return(long i, atomic64_t * v) 113#undef ATOMIC_OPS
154{ 114#undef ATOMIC64_OP_RETURN
155 long temp, result; 115#undef ATOMIC64_OP
156 smp_mb(); 116#undef ATOMIC_OP_RETURN
157 __asm__ __volatile__( 117#undef ATOMIC_OP
158 "1: ldq_l %0,%1\n"
159 " subq %0,%3,%2\n"
160 " subq %0,%3,%0\n"
161 " stq_c %0,%1\n"
162 " beq %0,2f\n"
163 ".subsection 2\n"
164 "2: br 1b\n"
165 ".previous"
166 :"=&r" (temp), "=m" (v->counter), "=&r" (result)
167 :"Ir" (i), "m" (v->counter) : "memory");
168 smp_mb();
169 return result;
170}
171 118
172#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new)) 119#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
173#define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) 120#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))