Browse code

- alpha, armv6 and mip isa2+ atomic_add and atomic_cmpxchg (armv6 & alpha not tested at all due to lacking hardware or emulators)

Andrei Pelinescu-Onciul authored on 10/05/2007 18:27:07
Showing 3 changed files
... ...
@@ -36,6 +36,7 @@
36 36
  * History:
37 37
  * --------
38 38
  *  2006-03-31  created by andrei
39
+ *  2007-05-10  added atomic_add & atomic_cmpxchg (andrei)
39 40
  */
40 41
 
41 42
 
... ...
@@ -125,7 +126,7 @@
125 126
 		P_TYPE ret; \
126 127
 		asm volatile( \
127 128
 			ATOMIC_ASM_OP01_##P_TYPE(OP) \
128
-			: "=&r"(ret), "=r"(v), "=m"(*var), "0"(v)  : "m"(*var) \
129
+			: "=&r"(ret), "=r"(v), "=m"(*var)  : "m"(*var), "1"(v) \
129 130
 			); \
130 131
 		return RET_EXPR; \
131 132
 	}
... ...
@@ -170,6 +171,26 @@
170 171
 		return RET_EXPR; \
171 172
 	}
172 173
 
174
+/* input in %0 and %3 (param), output in %0 */
175
+/* cmpxchg var in %1, old in %0, new_v in %
176
+ * makes the xchg if old==*var
177
+ * returns initial *var (so if ret==old => new_v was written into var)*/
178
+#define ATOMIC_CMPXCHG_DECL(NAME,  P_TYPE) \
179
+	inline static P_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
180
+														P_TYPE old, \
181
+														P_TYPE new_v) \
182
+	{ \
183
+		P_TYPE ret; \
184
+		P_TYPE tmp; \
185
+		asm volatile( \
186
+			ATOMIC_ASM_OP01_##P_TYPE("subq  %0, %5, %2 \n\t bne %2, 3f")\
187
+			"3:    \n\t" \
188
+			: "=&r"(ret), "=&r"(new_v), "=r"(tmp), "=m"(*var)  :\
189
+				"m"(*var), "r"(old), "1"(new_v) :"cc" \
190
+			); \
191
+		return ret; \
192
+	}
193
+
173 194
 
174 195
 ATOMIC_FUNC_DECL0_0(inc, "addl %0, 1, %0", int, void, /* no return */ )
175 196
 ATOMIC_FUNC_DECL0_0(dec, "subl %0, 1, %0", int, void, /* no return */ )
... ...
@@ -178,6 +199,8 @@ ATOMIC_FUNC_DECL03_0(or,  "bis %0, %3, %0", int, void, /* no return */ )
178 199
 ATOMIC_FUNC_DECL0_1(inc_and_test, "addl %0, 1, %1", int, int, (ret+1)==0 )
179 200
 ATOMIC_FUNC_DECL0_1(dec_and_test, "subl %0, 1, %1", int, int, (ret-1)==0 )
180 201
 ATOMIC_FUNC_DECL01_1(get_and_set, "" /* nothing needed */, int, int, ret )
202
+ATOMIC_CMPXCHG_DECL(cmpxchg, int )
203
+ATOMIC_FUNC_DECL01_1(add, "addl %1, %0, %1", int, int, ret+v)
181 204
 
182 205
 ATOMIC_FUNC_DECL0_0(inc, "addq %0, 1, %0", long, void, /* no return */ )
183 206
 ATOMIC_FUNC_DECL0_0(dec, "subq %0, 1, %0", long, void, /* no return */ )
... ...
@@ -186,6 +209,8 @@ ATOMIC_FUNC_DECL03_0(or,  "bis %0, %3, %0", long, void, /* no return */ )
186 209
 ATOMIC_FUNC_DECL0_1(inc_and_test, "addq %0, 1, %1", long, long, (ret+1)==0 )
187 210
 ATOMIC_FUNC_DECL0_1(dec_and_test, "subq %0, 1, %1", long, long, (ret-1)==0 )
188 211
 ATOMIC_FUNC_DECL01_1(get_and_set, "" /* nothing needed */, long, long, ret )
212
+ATOMIC_CMPXCHG_DECL(cmpxchg, long )
213
+ATOMIC_FUNC_DECL01_1(add, "addq %1, %0, %1", long, long, ret+v)
189 214
 
190 215
 
191 216
 #define atomic_inc(var) atomic_inc_int(&(var)->val)
... ...
@@ -195,6 +220,9 @@ ATOMIC_FUNC_DECL01_1(get_and_set, "" /* nothing needed */, long, long, ret )
195 220
 #define atomic_dec_and_test(var) atomic_dec_and_test_int(&(var)->val)
196 221
 #define atomic_inc_and_test(var) atomic_inc_and_test_int(&(var)->val)
197 222
 #define atomic_get_and_set(var, i) atomic_get_and_set_int(&(var)->val, i)
223
+#define atomic_cmpxchg(var, old, new_v) \
224
+		atomic_cmpxchg_int(&(var)->val, old, new_v)
225
+#define atomic_add(var, v) atomic_add_int(&(var)->val, (v))
198 226
 
199 227
 
200 228
 /* with integrated membar */
... ...
@@ -37,6 +37,7 @@
37 37
  * History:
38 38
  * --------
39 39
  *  2006-03-31  created by andrei
40
+ *  2007-05-10  added atomic_add and atomic_cmpxchg (andrei)
40 41
  */
41 42
 
42 43
 
... ...
@@ -126,6 +127,44 @@
126 127
 	}
127 128
 
128 129
 
130
+#define ATOMIC_XCHG_DECL(NAME, P_TYPE) \
131
+	inline static P_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
132
+														P_TYPE v ) \
133
+	{ \
134
+		P_TYPE ret; \
135
+		asm volatile( \
136
+			"     swp %0, %2, [%3] \n\t" \
137
+			: "=&r"(ret),  "=m"(*var) :\
138
+				"r"(v), "r"(var) \
139
+			); \
140
+		return ret; \
141
+	}
142
+
143
+
144
+/* cmpxchg: %5=old, %4=new_v, %3=var
145
+ * if (*var==old) *var=new_v
146
+ * returns the original *var (can be used to check if it succeeded: 
147
+ *  if old==cmpxchg(var, old, new_v) -> success
148
+ */
149
+#define ATOMIC_CMPXCHG_DECL(NAME, P_TYPE) \
150
+	inline static P_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
151
+														P_TYPE old, \
152
+														P_TYPE new_v) \
153
+	{ \
154
+		P_TYPE ret, tmp; \
155
+		asm volatile( \
156
+			"1:   ldrex %0, [%3] \n\t" \
157
+			"     cmp %0, %5 \n\t" \
158
+			"     strexeq %1, %4, [%3] \n\t" \
159
+			"     cmp %1, #0 \n\t" \
160
+			"     bne 1b \n\t" \
161
+			: "=&r"(ret), "=&r"(tmp), "=m"(*var) :\
162
+				"r"(var), "r"(new_v), "r"(old) : "cc" \
163
+			); \
164
+		return ret; \
165
+	}
166
+
167
+
129 168
 
130 169
 ATOMIC_FUNC_DECL(inc,      "add  %1, %0, #1", int, void, /* no return */ )
131 170
 ATOMIC_FUNC_DECL(dec,      "sub  %1, %0, #1", int, void, /* no return */ )
... ...
@@ -133,7 +172,10 @@ ATOMIC_FUNC_DECL1(and,     "and  %1, %0, %4", int, void, /* no return */ )
133 172
 ATOMIC_FUNC_DECL1(or,      "orr  %1, %0, %4", int, void, /* no return */ )
134 173
 ATOMIC_FUNC_DECL(inc_and_test, "add  %1, %0, #1", int, int, ret )
135 174
 ATOMIC_FUNC_DECL(dec_and_test, "sub  %1, %0, #1", int, int, ret )
136
-ATOMIC_FUNC_DECL2(get_and_set, /* no extra op needed */ , int, int,  ret)
175
+//ATOMIC_FUNC_DECL2(get_and_set, /* no extra op needed */ , int, int,  ret)
176
+ATOMIC_XCHG_DECL(get_and_set, int)
177
+ATOMIC_CMPXCHG_DECL(cmpxchg, int)
178
+ATOMIC_FUNC_DECL1(add,     "add  %1, %0, %4", int, int, ret )
137 179
 
138 180
 ATOMIC_FUNC_DECL(inc,      "add  %1, %0, #1", long, void, /* no return */ )
139 181
 ATOMIC_FUNC_DECL(dec,      "sub  %1, %0, #1", long, void, /* no return */ )
... ...
@@ -141,7 +183,10 @@ ATOMIC_FUNC_DECL1(and,     "and  %1, %0, %4", long, void, /* no return */ )
141 183
 ATOMIC_FUNC_DECL1(or,      "orr  %1, %0, %4", long, void, /* no return */ )
142 184
 ATOMIC_FUNC_DECL(inc_and_test, "add  %1, %0, #1", long, long, ret )
143 185
 ATOMIC_FUNC_DECL(dec_and_test, "sub  %1, %0, #1", long, long, ret )
144
-ATOMIC_FUNC_DECL2(get_and_set, /* no extra op needed */ , long, long,  ret)
186
+//ATOMIC_FUNC_DECL2(get_and_set, /* no extra op needed */ , long, long,  ret)
187
+ATOMIC_XCHG_DECL(get_and_set, long)
188
+ATOMIC_CMPXCHG_DECL(cmpxchg, long)
189
+ATOMIC_FUNC_DECL1(add,     "add  %1, %0, %4", long, long, ret )
145 190
 
146 191
 #define atomic_inc(var) atomic_inc_int(&(var)->val)
147 192
 #define atomic_dec(var) atomic_dec_int(&(var)->val)
... ...
@@ -150,6 +195,9 @@ ATOMIC_FUNC_DECL2(get_and_set, /* no extra op needed */ , long, long,  ret)
150 195
 #define atomic_dec_and_test(var) atomic_dec_and_test_int(&(var)->val)
151 196
 #define atomic_inc_and_test(var) atomic_inc_and_test_int(&(var)->val)
152 197
 #define atomic_get_and_set(var, i) atomic_get_and_set_int(&(var)->val, i)
198
+#define atomic_cmpxchg(var, old, new_v) \
199
+	atomic_cmpxchg_int(&(var)->val, old, new_v)
200
+#define atomic_add(var, v) atomic_add_int(&(var)->val, (v))
153 201
 
154 202
 
155 203
 /* with integrated membar */
... ...
@@ -42,6 +42,7 @@
42 42
  * History:
43 43
  * --------
44 44
  *  2006-03-08  created by andrei
45
+ *  2007-05-10  added atomic_add & atomic_cmpxchg (andrei)
45 46
  */
46 47
 
47 48
 
... ...
@@ -167,6 +168,23 @@
167 168
 	}
168 169
 
169 170
 
171
+/* %0=var, %1=*var, %2=new, %3=old :
172
+ * ret=*var; if *var==old  then *var=new; return ret
173
+ * => if succesfull (changed var to new)  ret==old */
174
+#define ATOMIC_CMPXCHG_DECL(NAME, P_TYPE) \
175
+	inline static P_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
176
+														P_TYPE old, \
177
+														P_TYPE new_v) \
178
+	{ \
179
+		asm volatile( \
180
+			ATOMIC_ASM_OP_##P_TYPE("bne %1, %3, 2f \n\t nop") \
181
+			"2:    \n\t" \
182
+			: "=m"(*var), "=&r"(old), "=r"(new_v)  \
183
+			: "r"(old), "m"(*var), "2"(new_v) \
184
+			 \
185
+			); \
186
+		return old; \
187
+	}
170 188
 
171 189
 ATOMIC_FUNC_DECL(inc,      "addiu %2, %1, 1", int, void, /* no return */ )
172 190
 ATOMIC_FUNC_DECL_CT(dec,   "subu %2, %1, %3", 1,  int, void, /* no return */ )
... ...
@@ -175,6 +193,8 @@ ATOMIC_FUNC_DECL1(or,  "or  %2, %1, %3", int, void,  /* no return */ )
175 193
 ATOMIC_FUNC_DECL(inc_and_test, "addiu %2, %1, 1", int, int, (ret+1)==0 )
176 194
 ATOMIC_FUNC_DECL_CT(dec_and_test, "subu %2, %1, %3", 1, int, int, (ret-1)==0 )
177 195
 ATOMIC_FUNC_DECL2(get_and_set, "" /* nothing needed */, int, int, ret )
196
+ATOMIC_CMPXCHG_DECL(cmpxchg, int)
197
+ATOMIC_FUNC_DECL1(add, "addu %2, %1, %3 \n\t move %1, %2", int, int, ret )
178 198
 
179 199
 #ifdef __CPU_mips64
180 200
 
... ...
@@ -185,6 +205,8 @@ ATOMIC_FUNC_DECL1(or,  "or  %2, %1, %3", long, void,  /* no return */ )
185 205
 ATOMIC_FUNC_DECL(inc_and_test, "daddiu %2, %1, 1", long, long, (ret+1)==0 )
186 206
 ATOMIC_FUNC_DECL_CT(dec_and_test, "dsubu %2, %1, %3", 1,long, long, (ret-1)==0 )
187 207
 ATOMIC_FUNC_DECL2(get_and_set, "" /* nothing needed */, long, long, ret )
208
+ATOMIC_CMPXCHG_DECL(cmpxchg, long)
209
+ATOMIC_FUNC_DECL1(add, "daddu %2, %1, %3 \n\t move %1, %2", long, long, ret )
188 210
 
189 211
 #else /* ! __CPU_mips64 => __CPU_mips2 or __CPU_mips */
190 212
 
... ...
@@ -195,6 +217,8 @@ ATOMIC_FUNC_DECL1(or,  "or  %2, %1, %3", long, void,  /* no return */ )
195 217
 ATOMIC_FUNC_DECL(inc_and_test, "addiu %2, %1, 1", long, long, (ret+1)==0 )
196 218
 ATOMIC_FUNC_DECL_CT(dec_and_test, "subu %2, %1, %3", 1,long, long, (ret-1)==0 )
197 219
 ATOMIC_FUNC_DECL2(get_and_set, "" /* nothing needed */, long, long, ret )
220
+ATOMIC_CMPXCHG_DECL(cmpxchg, long)
221
+ATOMIC_FUNC_DECL1(add, "addu %2, %1, %3 \n\t move %1, %2", long, long, ret )
198 222
 
199 223
 #endif /* __CPU_mips64 */
200 224
 
... ...
@@ -205,6 +229,9 @@ ATOMIC_FUNC_DECL2(get_and_set, "" /* nothing needed */, long, long, ret )
205 229
 #define atomic_dec_and_test(var) atomic_dec_and_test_int(&(var)->val)
206 230
 #define atomic_inc_and_test(var) atomic_inc_and_test_int(&(var)->val)
207 231
 #define atomic_get_and_set(var, i) atomic_get_and_set_int(&(var)->val, i)
232
+#define atomic_add(var, i) atomic_add_int(&(var)->val, i)
233
+#define atomic_cmpxchg(var, old, new_v)  \
234
+	atomic_cmpxchg_int(&(var)->val, old, new_v)
208 235
 
209 236
 
210 237
 /* with integrated membar */