Browse code

- added atomic ops & mem. barriers support for: - arm - arm v6 (untested, but it compiles ok) - alpha (untested. but it compiles ok) - fastlock: minor fixes - Makefile.defs: support for mip64 and armv6; various minor fixes

Andrei Pelinescu-Onciul authored on 31/03/2006 21:22:40
Showing 5 changed files
... ...
@@ -48,6 +48,8 @@
48 48
 #  2006-03-30  64 bit mode compile by default on sparc64 (-m64), added
49 49
 #              CC_GCC_LIKE_ASM and SPARC64_MODE (andrei)
50 50
 #              sparc <= v8 support (andrei)
51
+#  2006-03-31  armv6 & mips64 support added
52
+#              mips and arm set to NOSMP by default (andrei)
51 53
 
52 54
 
53 55
 # check if already included/exported
... ...
@@ -64,7 +66,7 @@ MAIN_NAME=ser
64 64
 VERSION = 0
65 65
 PATCHLEVEL = 10
66 66
 SUBLEVEL =   99
67
-EXTRAVERSION = -dev34
67
+EXTRAVERSION = -dev35
68 68
 
69 69
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
70 70
 			$(SUBLEVEL) )
... ...
@@ -78,7 +80,8 @@ else
78 78
 endif
79 79
 
80 80
 ARCH := $(shell $(GETARCH) |sed -e s/i.86/i386/ -e s/sun4u/sparc64/  \
81
-			-e s/armv4l/arm/ -e "s/Power Macintosh/ppc/" \
81
+			-e s/armv[3-5].*/arm/  -e s/armv6.*/arm6/ \
82
+			-e "s/Power Macintosh/ppc/" \
82 83
 			-e "s/cobalt/mips2/" \
83 84
 			-e s/amd64/x86_64/ )
84 85
 # fix sparc -> sparc64
... ...
@@ -447,13 +450,16 @@ endif
447 447
 endif
448 448
 
449 449
 ifeq ($(ARCH), sparc)
450
-	# smp no supported on sparc32
451
-	DEFS+= -DNOSMP # FIXME
452 450
 	use_fast_lock=yes
453 451
 endif
454 452
 
455 453
 ifeq ($(ARCH), arm)
456 454
 	use_fast_lock=yes
455
+	DEFS+=-DNOSMP # very unlikely to have an smp arm
456
+endif
457
+
458
+ifeq ($(ARCH), arm6)
459
+	use_fast_lock=yes
457 460
 endif
458 461
 
459 462
 ifeq ($(ARCH), ppc)
... ...
@@ -467,6 +473,8 @@ endif
467 467
 ifeq ($(ARCH), mips)
468 468
 # mips1 arch. (e.g. R3000) - no hardware locking support
469 469
 	use_fast_lock=no
470
+	DEFS+=-DMIPS_HAS_LLSC # likely
471
+	DEFS+=-DNOSMP # very likely
470 472
 endif
471 473
 
472 474
 ifeq ($(ARCH), mips2)
... ...
@@ -474,6 +482,11 @@ ifeq ($(ARCH), mips2)
474 474
 	use_fast_lock=yes
475 475
 endif
476 476
 
477
+ifeq ($(ARCH), mips64)
478
+# mips2 arch and newer (mips3=R4000, mips4=R5000 a.s.o)
479
+	use_fast_lock=yes
480
+endif
481
+
477 482
 ifeq ($(ARCH), alpha)
478 483
 	use_fast_lock=yes
479 484
 endif
... ...
@@ -754,20 +767,20 @@ ifeq	($(ARCH), arm)
754 754
 ifeq		($(CC_NAME), gcc)
755 755
 				DEFS+=-DCC_GCC_LIKE_ASM
756 756
 				#common stuff
757
-				CFLAGS=-O9 -funroll-loops  -Wcast-align $(PROFILE) \
757
+				CFLAGS=-O9 -funroll-loops $(PROFILE) \
758 758
 					-Wall   
759 759
 			#if gcc 4.x+
760 760
 ifeq			($(CC_SHORTVER), 4.x)
761
-					CFLAGS+=-mcpu=strongarm1100 -minline-all-stringops \
762
-							-ftree-vectorize
761
+					CFLAGS+= -ftree-vectorize
762
+					# not supported on arm: -minline-all-stringops 
763 763
 else
764 764
 			#if gcc 3.4+
765 765
 ifeq			($(CC_SHORTVER), 3.4)
766
-					CFLAGS+= -mcpu=strongarm1100
766
+					CFLAGS+=
767 767
 else
768 768
 			#if gcc 3.0
769 769
 ifeq			($(CC_SHORTVER), 3.0)
770
-					CFLAGS+= -mcpu=strongarm1100
770
+					CFLAGS+= 
771 771
 							#-mcpu=athlon
772 772
 else
773 773
 ifeq			($(CC_SHORTVER), 2.9x) #older gcc version (2.9[1-5])
... ...
@@ -791,6 +804,48 @@ $(error 			Unsupported compiler ($(CC):$(CC_NAME)), try gcc)
791 791
 endif		#CC_NAME, gcc
792 792
 endif	#ARCH, arm 
793 793
 
794
+	#if armv6 cpu 
795
+ifeq	($(ARCH), arm6)
796
+		# if gcc 
797
+ifeq		($(CC_NAME), gcc)
798
+				DEFS+=-DCC_GCC_LIKE_ASM
799
+				#common stuff
800
+				CFLAGS=-march=armv6 -O9 -funroll-loops \
801
+						$(PROFILE) -Wall   
802
+			#if gcc 4.x+
803
+ifeq			($(CC_SHORTVER), 4.x)
804
+					CFLAGS+= -ftree-vectorize
805
+else
806
+			#if gcc 3.4+
807
+ifeq			($(CC_SHORTVER), 3.4)
808
+					CFLAGS+=
809
+else
810
+			#if gcc 3.0
811
+ifeq			($(CC_SHORTVER), 3.0)
812
+					CFLAGS+= 
813
+							#-mcpu=athlon
814
+else
815
+ifeq			($(CC_SHORTVER), 2.9x) #older gcc version (2.9[1-5])
816
+$(warning 			Old gcc detected ($(CC_SHORTVER)), use  gcc 3.0.x \
817
+					for better results)
818
+					
819
+					CFLAGS+=
820
+else
821
+				#really old version
822
+$(warning			You are using an old and unsupported gcc \
823
+					 version ($(CC_SHORTVER)), compile at your own risk!)
824
+	
825
+endif			# CC_SHORTVER, 2.9x
826
+endif			# CC_SHORTVER, 3.0
827
+endif			# CC_SHORTVER, 3.4
828
+endif			# CC_SHORTVER, 4.0
829
+	
830
+else		# CC_NAME, gcc
831
+				#other compilers
832
+$(error 			Unsupported compiler ($(CC):$(CC_NAME)), try gcc)
833
+endif		#CC_NAME, gcc
834
+endif	#ARCH, arm6
835
+
794 836
 	#if  mips (R3000)
795 837
 ifeq	($(ARCH), mips)
796 838
 		# if gcc 
... ...
@@ -873,6 +928,45 @@ $(error 			Unsupported compiler ($(CC):$(CC_NAME)), try gcc)
873 873
 endif		#CC_NAME, gcc
874 874
 endif	#ARCH, mips2
875 875
 
876
+#if  >=mips64
877
+ifeq	($(ARCH), mips64)
878
+		# if gcc 
879
+ifeq		($(CC_NAME), gcc)
880
+				DEFS+=-DCC_GCC_LIKE_ASM
881
+				#common stuff
882
+				CFLAGS= -mips64 -O9 -funroll-loops $(PROFILE) \
883
+					-Wall 
884
+			#if gcc 4.0+
885
+ifeq			($(CC_SHORTVER), 4.x)
886
+					CFLAGS+=-minline-all-stringops -ftree-vectorize
887
+else
888
+			#if gcc 3.4+
889
+ifeq			($(CC_SHORTVER), 3.4)
890
+					CFLAGS+=
891
+else
892
+			#if gcc 3.0
893
+ifeq			($(CC_SHORTVER), 3.0)
894
+					CFLAGS+=
895
+else
896
+ifeq			($(CC_SHORTVER), 2.9x) #older gcc version (2.9[1-5])
897
+$(warning 			Old gcc detected ($(CC_SHORTVER)), use  gcc 3.0.x \
898
+					for better results)
899
+					CFLAGS+=
900
+else
901
+				#really old version
902
+$(warning			You are using an old and unsupported gcc \
903
+					 version ($(CC_SHORTVER)), compile at your own risk!)
904
+	
905
+endif			# CC_SHORTVER, 2.9x
906
+endif			# CC_SHORTVER, 3.0
907
+endif			# CC_SHORTVER, 3.4
908
+endif			# CC_SHORTVER, 4.x
909
+	
910
+else		# CC_NAME, gcc
911
+				#other compilers
912
+$(error 			Unsupported compiler ($(CC):$(CC_NAME)), try gcc)
913
+endif		#CC_NAME, gcc
914
+endif	#ARCH, mips64
876 915
 
877 916
 #if  alpha
878 917
 ifeq	($(ARCH), alpha)
... ...
@@ -883,7 +977,8 @@ ifeq		($(CC_NAME), gcc)
883 883
 				CFLAGS= -O9 -funroll-loops $(PROFILE)  -Wall 
884 884
 			#if gcc 4.0+
885 885
 ifeq			($(CC_SHORTVER), 4.x)
886
-					CFLAGS+=-minline-all-stringops
886
+					CFLAGS+= 
887
+					# not supported: -minline-all-stringops
887 888
 else
888 889
 			#if gcc 3.4+
889 890
 ifeq			($(CC_SHORTVER), 3.4)
890 891
new file mode 100644
... ...
@@ -0,0 +1,319 @@
0
+/* 
1
+ * $Id$
2
+ * 
3
+ * Copyright (C) 2006 iptelorg GmbH
4
+ *
5
+ * This file is part of ser, a free SIP server.
6
+ *
7
+ * ser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * For a license to use the ser software under conditions
13
+ * other than those described here, or to purchase support for this
14
+ * software, please contact iptel.org by e-mail at the following addresses:
15
+ *    info@iptel.org
16
+ *
17
+ * ser is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program; if not, write to the Free Software
24
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
+ */
26
+/*
27
+ *  atomic operations and memory barriers (alpha specific)
28
+ *  WARNING: atomic ops do not include memory barriers
29
+ *  see atomic_ops.h for more details 
30
+ *
31
+ *  Config defines:  - NOSMP 
32
+ *                   - __CPU_alpha
33
+ */
34
+/* 
35
+ * History:
36
+ * --------
37
+ *  2006-03-31  created by andrei
38
+ */
39
+
40
+
41
+#ifndef _atomic_alpha_h
42
+#define _atomic_alpha_h
43
+
44
+#define HAVE_ASM_INLINE_ATOMIC_OPS
45
+#define HAVE_ASM_INLINE_MEMBAR
46
+
47
+#warning alpha atomic code was not tested, please report problems to \
48
+		serdev@iptel.org or andrei@iptel.org
49
+
50
+#ifdef NOSMP
51
+#define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
52
+#define membar_read()  membar()
53
+#define membar_write() membar()
54
+#else
55
+
56
+#define membar()		asm volatile ("    mb \n\t" : : : "memory" ) 
57
+#define membar_read()	membar()
58
+#define membar_write()	asm volatile ("    wmb \n\t" : : : "memory" )
59
+
60
+#endif /* NOSMP */
61
+
62
+
63
+
64
+/* main asm block 
65
+ * if store failes, jump _forward_ (optimization, because back jumps are
66
+ *  always predicted to happen on alpha )*/
67
+#define ATOMIC_ASM_OP00_int(op) \
68
+			"1:   ldl_l %0, %2 \n\t" \
69
+			"     " op "\n\t" \
70
+			"     stl_c %0, %2 \n\t" \
71
+			"     beq %0, 2f \n\t" \
72
+			".subsection 2 \n\t" \
73
+			"2:   br 1b \n\t" \
74
+			".previous \n\t"
75
+
76
+/* as above, but output in %1 instead of %0 (%0 is not clobbered) */
77
+#define ATOMIC_ASM_OP01_int(op) \
78
+			"1:   ldl_l %0, %3 \n\t" \
79
+			"     " op "\n\t" \
80
+			"     stl_c %1, %3 \n\t" \
81
+			"     beq %1, 2f \n\t" \
82
+			".subsection 2 \n\t" \
83
+			"2:   br 1b \n\t" \
84
+			".previous \n\t"
85
+
86
+#define ATOMIC_ASM_OP00_long(op) \
87
+			"1:   ldq_l %0, %2 \n\t" \
88
+			"     " op "\n\t" \
89
+			"     stq_c %0, %2 \n\t" \
90
+			"     beq %0, 2f \n\t" \
91
+			".subsection 2 \n\t" \
92
+			"2:   br 1b \n\t" \
93
+			".previous \n\t"
94
+
95
+/* as above, but output in %1 instead of %0 (%0 is not clobbered) */
96
+#define ATOMIC_ASM_OP01_long(op) \
97
+			"1:   ldq_l %0, %3 \n\t" \
98
+			"     " op "\n\t" \
99
+			"     stq_c %1, %3 \n\t" \
100
+			"     beq %1, 2f \n\t" \
101
+			".subsection 2 \n\t" \
102
+			"2:   br 1b \n\t" \
103
+			".previous \n\t"
104
+
105
+
106
+
107
+/* input in %0, output in %0 */
108
+#define ATOMIC_FUNC_DECL0_0(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
109
+	inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var) \
110
+	{ \
111
+		P_TYPE ret; \
112
+		asm volatile( \
113
+			ATOMIC_ASM_OP00_##P_TYPE(OP) : "=&r"(ret), "=m"(*var) : "m"(*var) \
114
+			); \
115
+		return RET_EXPR; \
116
+	}
117
+
118
+
119
+/* input in %0, and %1 (param), output in %1,  %0 goes in ret */
120
+#define ATOMIC_FUNC_DECL01_1(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
121
+	inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
122
+														P_TYPE v ) \
123
+	{ \
124
+		P_TYPE ret; \
125
+		asm volatile( \
126
+			ATOMIC_ASM_OP01_##P_TYPE(OP) \
127
+			: "=&r"(ret), "+r"(v), "=m"(*var)  : "m"(*var) \
128
+			); \
129
+		return RET_EXPR; \
130
+	}
131
+
132
+
133
+/* input in %0, output in %1, %0 goes in ret */
134
+#define ATOMIC_FUNC_DECL0_1(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
135
+	inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var) \
136
+	{ \
137
+		P_TYPE ret, tmp; \
138
+		asm volatile( \
139
+			ATOMIC_ASM_OP01_##P_TYPE(OP) \
140
+			: "=&r"(ret), "=&r"(tmp), "=m"(*var)  : "m"(*var) \
141
+			); \
142
+		return RET_EXPR; \
143
+	}
144
+
145
+
146
+/* input in %0 and %3 (param), output in %0 */
147
+#define ATOMIC_FUNC_DECL03_0(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
148
+	inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
149
+														P_TYPE v) \
150
+	{ \
151
+		P_TYPE ret; \
152
+		asm volatile( \
153
+			ATOMIC_ASM_OP00_##P_TYPE(OP) \
154
+			: "=&r"(ret), "=m"(*var)  : "m"(*var), "r"(v) \
155
+			); \
156
+		return RET_EXPR; \
157
+	}
158
+
159
+
160
+ATOMIC_FUNC_DECL0_0(inc, "addl %0, 1, %0", int, void, /* no return */ )
161
+ATOMIC_FUNC_DECL0_0(dec, "subl %0, 1, %0", int, void, /* no return */ )
162
+ATOMIC_FUNC_DECL03_0(and, "and %0, %3, %0", int, void, /* no return */ )
163
+ATOMIC_FUNC_DECL03_0(or,  "bis %0, %3, %0", int, void, /* no return */ )
164
+ATOMIC_FUNC_DECL0_1(inc_and_test, "addl %0, 1, %1", int, int, (ret+1)==0 )
165
+ATOMIC_FUNC_DECL0_1(dec_and_test, "subl %0, 1, %1", int, int, (ret-1)==0 )
166
+ATOMIC_FUNC_DECL01_1(get_and_set, "" /* nothing needed */, int, int, ret )
167
+
168
+ATOMIC_FUNC_DECL0_0(inc, "addq %0, 1, %0", long, void, /* no return */ )
169
+ATOMIC_FUNC_DECL0_0(dec, "subq %0, 1, %0", long, void, /* no return */ )
170
+ATOMIC_FUNC_DECL03_0(and, "and %0, %3, %0", long, void, /* no return */ )
171
+ATOMIC_FUNC_DECL03_0(or,  "bis %0, %3, %0", long, void, /* no return */ )
172
+ATOMIC_FUNC_DECL0_1(inc_and_test, "addq %0, 1, %1", long, long, (ret+1)==0 )
173
+ATOMIC_FUNC_DECL0_1(dec_and_test, "subq %0, 1, %1", long, long, (ret-1)==0 )
174
+ATOMIC_FUNC_DECL01_1(get_and_set, "" /* nothing needed */, long, long, ret )
175
+
176
+
177
+#define atomic_inc(var) atomic_inc_int(&(var)->val)
178
+#define atomic_dec(var) atomic_dec_int(&(var)->val)
179
+#define atomic_and(var, mask) atomic_and_int(&(var)->val, (mask))
180
+#define atomic_or(var, mask)  atomic_or_int(&(var)->val, (mask))
181
+#define atomic_dec_and_test(var) atomic_dec_and_test_int(&(var)->val)
182
+#define atomic_inc_and_test(var) atomic_inc_and_test_int(&(var)->val)
183
+#define atomic_get_and_set(var, i) atomic_get_and_set_int(&(var)->val, i)
184
+
185
+
186
+/* with integrated membar */
187
+
188
+#define mb_atomic_set_int(v, i) \
189
+	do{ \
190
+		membar(); \
191
+		atomic_set_int(v, i); \
192
+	}while(0)
193
+
194
+
195
+
196
+inline static int mb_atomic_get_int(volatile int* v)
197
+{
198
+	membar();
199
+	return atomic_get_int(v);
200
+}
201
+
202
+
203
+#define mb_atomic_inc_int(v) \
204
+	do{ \
205
+		membar(); \
206
+		atomic_inc_int(v); \
207
+	}while(0)
208
+
209
+#define mb_atomic_dec_int(v) \
210
+	do{ \
211
+		membar(); \
212
+		atomic_dec_int(v); \
213
+	}while(0)
214
+
215
+#define mb_atomic_or_int(v, m) \
216
+	do{ \
217
+		membar(); \
218
+		atomic_or_int(v, m); \
219
+	}while(0)
220
+
221
+#define mb_atomic_and_int(v, m) \
222
+	do{ \
223
+		membar(); \
224
+		atomic_and_int(v, m); \
225
+	}while(0)
226
+
227
+inline static int mb_atomic_inc_and_test_int(volatile int* v)
228
+{
229
+	membar();
230
+	return atomic_inc_and_test_int(v);
231
+}
232
+
233
+inline static int mb_atomic_dec_and_test_int(volatile int* v)
234
+{
235
+	membar();
236
+	return atomic_dec_and_test_int(v);
237
+}
238
+
239
+
240
+inline static int mb_atomic_get_and_set_int(volatile int* v, int i)
241
+{
242
+	membar();
243
+	return atomic_get_and_set_int(v, i);
244
+}
245
+
246
+
247
+
248
+#define mb_atomic_set_long(v, i) \
249
+	do{ \
250
+		membar(); \
251
+		atomic_set_long(v, i); \
252
+	}while(0)
253
+
254
+
255
+
256
+inline static long mb_atomic_get_long(volatile long* v)
257
+{
258
+	membar();
259
+	return atomic_get_long(v);
260
+}
261
+
262
+
263
+#define mb_atomic_inc_long(v) \
264
+	do{ \
265
+		membar(); \
266
+		atomic_inc_long(v); \
267
+	}while(0)
268
+
269
+
270
+#define mb_atomic_dec_long(v) \
271
+	do{ \
272
+		membar(); \
273
+		atomic_dec_long(v); \
274
+	}while(0)
275
+
276
+#define mb_atomic_or_long(v, m) \
277
+	do{ \
278
+		membar(); \
279
+		atomic_or_long(v, m); \
280
+	}while(0)
281
+
282
+#define mb_atomic_and_long(v, m) \
283
+	do{ \
284
+		membar(); \
285
+		atomic_and_long(v, m); \
286
+	}while(0)
287
+
288
+inline static long mb_atomic_inc_and_test_long(volatile long* v)
289
+{
290
+	membar();
291
+	return atomic_inc_and_test_long(v);
292
+}
293
+
294
+inline static long mb_atomic_dec_and_test_long(volatile long* v)
295
+{
296
+	membar();
297
+	return atomic_dec_and_test_long(v);
298
+}
299
+
300
+
301
+inline static long mb_atomic_get_and_set_long(volatile long* v, long l)
302
+{
303
+	membar();
304
+	return atomic_get_and_set_long(v, l);
305
+}
306
+
307
+
308
+#define mb_atomic_inc(var) mb_atomic_inc_int(&(var)->val)
309
+#define mb_atomic_dec(var) mb_atomic_dec_int(&(var)->val)
310
+#define mb_atomic_and(var, mask) mb_atomic_and_int(&(var)->val, (mask))
311
+#define mb_atomic_or(var, mask)  mb_atomic_or_int(&(var)->val, (mask))
312
+#define mb_atomic_dec_and_test(var) mb_atomic_dec_and_test_int(&(var)->val)
313
+#define mb_atomic_inc_and_test(var) mb_atomic_inc_and_test_int(&(var)->val)
314
+#define mb_atomic_get(var)	mb_atomic_get_int(&(var)->val)
315
+#define mb_atomic_set(var, i)	mb_atomic_set_int(&(var)->val, i)
316
+#define mb_atomic_get_and_set(var, i) mb_atomic_get_and_set_int(&(var)->val, i)
317
+
318
+#endif
0 319
new file mode 100644
... ...
@@ -0,0 +1,315 @@
0
+/* 
1
+ * $Id$
2
+ * 
3
+ * Copyright (C) 2006 iptelorg GmbH
4
+ *
5
+ * This file is part of ser, a free SIP server.
6
+ *
7
+ * ser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * For a license to use the ser software under conditions
13
+ * other than those described here, or to purchase support for this
14
+ * software, please contact iptel.org by e-mail at the following addresses:
15
+ *    info@iptel.org
16
+ *
17
+ * ser is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program; if not, write to the Free Software
24
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
+ */
26
+/*
27
+ *  atomic ops and memory barriers for arm (>= v3)
28
+ *  see atomic_ops.h for more details 
29
+ *
30
+ * Config defines: - NOSMP
31
+ *                 - __CPU_arm
32
+ *                 - __CPU_arm6    - armv6 support (supports atomic ops
33
+ *                                    via ldrex/strex)
34
+ */ 
35
+/* 
36
+ * History:
37
+ * --------
38
+ *  2006-03-31  created by andrei
39
+ */
40
+
41
+
42
+#ifndef _atomic_arm_h
43
+#define _atomic_arm_h
44
+
45
+
46
+
47
+#warning "arm atomic operations support not tested"
48
+
49
+#ifdef NOSMP
50
+#define HAVE_ASM_INLINE_MEMBAR
51
+#define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
52
+#define membar_read()  membar()
53
+#define membar_write() membar()
54
+#else /* SMP */
55
+#warning SMP not supported for arm atomic ops, try compiling with -DNOSMP
56
+/* fall back to default lock based barriers (don't define HAVE_ASM...) */
57
+#endif /* NOSMP */
58
+
59
+
60
+#ifdef __CPU_arm6
61
+
62
+
63
+#define HAVE_ASM_INLINE_ATOMIC_OPS
64
+
65
+/* hack to get some membars */
66
+#ifndef NOSMP
67
+#include "atomic_unknown.h"
68
+#endif
69
+
70
+/* main asm block 
71
+ *  use %0 as input and write the output in %1*/
72
+#define ATOMIC_ASM_OP(op) \
73
+			"1:   ldrex %0, [%3] \n\t" \
74
+			"     " op "\n\t" \
75
+			"     strex %0, %1, [%3] \n\t" \
76
+			"     cmp %0, #0 \n\t" \
77
+			"     bne 1b \n\t"
78
+
79
+/* same as above but writes %4 instead of %1, and %0 will contain 
80
+ * the prev. val*/
81
+#define ATOMIC_ASM_OP2(op) \
82
+			"1:   ldrex %0, [%3] \n\t" \
83
+			"     " op "\n\t" \
84
+			"     strex %1, %4, [%3] \n\t" \
85
+			"     cmp %1, #0 \n\t" \
86
+			"     bne 1b \n\t"
87
+
88
+/* no extra param, %0 contains *var, %1 should contain the result */
89
+#define ATOMIC_FUNC_DECL(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
90
+	inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var) \
91
+	{ \
92
+		P_TYPE ret, tmp; \
93
+		asm volatile( \
94
+			ATOMIC_ASM_OP(OP) \
95
+			: "=&r"(tmp), "=&r"(ret), "=m"(*var) : "r"(var)  : "cc" \
96
+			); \
97
+		return RET_EXPR; \
98
+	}
99
+
100
+/* one extra param in %4 */
101
+#define ATOMIC_FUNC_DECL1(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
102
+	inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
103
+														P_TYPE v) \
104
+	{ \
105
+		P_TYPE ret, tmp; \
106
+		asm volatile( \
107
+			ATOMIC_ASM_OP(OP) \
108
+			: "=&r"(tmp), "=&r"(ret), "=m"(*var) : "r"(var), "r"(v) : "cc" \
109
+			); \
110
+		return RET_EXPR; \
111
+	}
112
+
113
+
114
+/* as above, but %4 should contain the result, and %0 is returned*/
115
+#define ATOMIC_FUNC_DECL2(NAME, OP, P_TYPE, RET_TYPE, RET_EXPR) \
116
+	inline static RET_TYPE atomic_##NAME##_##P_TYPE (volatile P_TYPE *var, \
117
+														P_TYPE v) \
118
+	{ \
119
+		P_TYPE ret, tmp; \
120
+		asm volatile( \
121
+			ATOMIC_ASM_OP2(OP) \
122
+			: "=&r"(ret), "=&r"(tmp), "=m"(*var) : "r"(var), "r"(v) : "cc" \
123
+			); \
124
+		return RET_EXPR; \
125
+	}
126
+
127
+
128
+
129
+ATOMIC_FUNC_DECL(inc,      "add  %1, %0, #1", int, void, /* no return */ )
130
+ATOMIC_FUNC_DECL(dec,      "sub  %1, %0, #1", int, void, /* no return */ )
131
+ATOMIC_FUNC_DECL1(and,     "and  %1, %0, %4", int, void, /* no return */ )
132
+ATOMIC_FUNC_DECL1(or,      "orr  %1, %0, %4", int, void, /* no return */ )
133
+ATOMIC_FUNC_DECL(inc_and_test, "add  %1, %0, #1", int, int, ret )
134
+ATOMIC_FUNC_DECL(dec_and_test, "sub  %1, %0, #1", int, int, ret )
135
+ATOMIC_FUNC_DECL2(get_and_set, /* no extra op needed */ , int, int,  ret)
136
+
137
+ATOMIC_FUNC_DECL(inc,      "add  %1, %0, #1", long, void, /* no return */ )
138
+ATOMIC_FUNC_DECL(dec,      "sub  %1, %0, #1", long, void, /* no return */ )
139
+ATOMIC_FUNC_DECL1(and,     "and  %1, %0, %4", long, void, /* no return */ )
140
+ATOMIC_FUNC_DECL1(or,      "orr  %1, %0, %4", long, void, /* no return */ )
141
+ATOMIC_FUNC_DECL(inc_and_test, "add  %1, %0, #1", long, long, ret )
142
+ATOMIC_FUNC_DECL(dec_and_test, "sub  %1, %0, #1", long, long, ret )
143
+ATOMIC_FUNC_DECL2(get_and_set, /* no extra op needed */ , long, long,  ret)
144
+
145
+#define atomic_inc(var) atomic_inc_int(&(var)->val)
146
+#define atomic_dec(var) atomic_dec_int(&(var)->val)
147
+#define atomic_and(var, mask) atomic_and_int(&(var)->val, (mask))
148
+#define atomic_or(var, mask)  atomic_or_int(&(var)->val, (mask))
149
+#define atomic_dec_and_test(var) atomic_dec_and_test_int(&(var)->val)
150
+#define atomic_inc_and_test(var) atomic_inc_and_test_int(&(var)->val)
151
+#define atomic_get_and_set(var, i) atomic_get_and_set_int(&(var)->val, i)
152
+
153
+
154
+/* with integrated membar */
155
+
156
+#define mb_atomic_set_int(v, i) \
157
+	do{ \
158
+		membar(); \
159
+		atomic_set_int(v, i); \
160
+	}while(0)
161
+
162
+
163
+
164
+inline static int mb_atomic_get_int(volatile int* v)
165
+{
166
+	membar();
167
+	return atomic_get_int(v);
168
+}
169
+
170
+
171
+#define mb_atomic_inc_int(v) \
172
+	do{ \
173
+		membar(); \
174
+		atomic_inc_int(v); \
175
+	}while(0)
176
+
177
+#define mb_atomic_dec_int(v) \
178
+	do{ \
179
+		membar(); \
180
+		atomic_dec_int(v); \
181
+	}while(0)
182
+
183
+#define mb_atomic_or_int(v, m) \
184
+	do{ \
185
+		membar(); \
186
+		atomic_or_int(v, m); \
187
+	}while(0)
188
+
189
+#define mb_atomic_and_int(v, m) \
190
+	do{ \
191
+		membar(); \
192
+		atomic_and_int(v, m); \
193
+	}while(0)
194
+
195
+inline static int mb_atomic_inc_and_test_int(volatile int* v)
196
+{
197
+	membar();
198
+	return atomic_inc_and_test_int(v);
199
+}
200
+
201
+inline static int mb_atomic_dec_and_test_int(volatile int* v)
202
+{
203
+	membar();
204
+	return atomic_dec_and_test_int(v);
205
+}
206
+
207
+
208
+inline static int mb_atomic_get_and_set_int(volatile int* v, int i)
209
+{
210
+	membar();
211
+	return atomic_get_and_set_int(v, i);
212
+}
213
+
214
+
215
+
216
+#define mb_atomic_set_long(v, i) \
217
+	do{ \
218
+		membar(); \
219
+		atomic_set_long(v, i); \
220
+	}while(0)
221
+
222
+
223
+
224
+inline static long mb_atomic_get_long(volatile long* v)
225
+{
226
+	membar();
227
+	return atomic_get_long(v);
228
+}
229
+
230
+
231
+#define mb_atomic_inc_long(v) \
232
+	do{ \
233
+		membar(); \
234
+		atomic_inc_long(v); \
235
+	}while(0)
236
+
237
+
238
+#define mb_atomic_dec_long(v) \
239
+	do{ \
240
+		membar(); \
241
+		atomic_dec_long(v); \
242
+	}while(0)
243
+
244
+#define mb_atomic_or_long(v, m) \
245
+	do{ \
246
+		membar(); \
247
+		atomic_or_long(v, m); \
248
+	}while(0)
249
+
250
+#define mb_atomic_and_long(v, m) \
251
+	do{ \
252
+		membar(); \
253
+		atomic_and_long(v, m); \
254
+	}while(0)
255
+
256
+inline static long mb_atomic_inc_and_test_long(volatile long* v)
257
+{
258
+	membar();
259
+	return atomic_inc_and_test_long(v);
260
+}
261
+
262
+inline static long mb_atomic_dec_and_test_long(volatile long* v)
263
+{
264
+	membar();
265
+	return atomic_dec_and_test_long(v);
266
+}
267
+
268
+
269
+inline static long mb_atomic_get_and_set_long(volatile long* v, long l)
270
+{
271
+	membar();
272
+	return atomic_get_and_set_long(v, l);
273
+}
274
+
275
+
276
+#define mb_atomic_inc(var) mb_atomic_inc_int(&(var)->val)
277
+#define mb_atomic_dec(var) mb_atomic_dec_int(&(var)->val)
278
+#define mb_atomic_and(var, mask) mb_atomic_and_int(&(var)->val, (mask))
279
+#define mb_atomic_or(var, mask)  mb_atomic_or_int(&(var)->val, (mask))
280
+#define mb_atomic_dec_and_test(var) mb_atomic_dec_and_test_int(&(var)->val)
281
+#define mb_atomic_inc_and_test(var) mb_atomic_inc_and_test_int(&(var)->val)
282
+#define mb_atomic_get(var)	mb_atomic_get_int(&(var)->val)
283
+#define mb_atomic_set(var, i)	mb_atomic_set_int(&(var)->val, i)
284
+#define mb_atomic_get_and_set(var, i) mb_atomic_get_and_set_int(&(var)->val, i)
285
+
286
+
287
+#else /* ! __CPU_arm6 => __CPU_arm */
288
+
289
+/* no atomic ops for v <6 , only SWP supported
290
+ * Atomic ops could be implemented if one bit is sacrificed and used like
291
+ *  a spinlock, e.g:
292
+ *          mov %r0, #0x1
293
+ *       1: swp %r1, %r0, [&atomic_val]
294
+ *          if (%r1 & 0x1) goto 1 # wait if first bit is 1 
295
+ *          %r1>>=1  # restore the value (only 31 bits can be used )
296
+ *          %r1=op (%r1, ...) 
297
+ *          %r1<<=1   # shift back the value, such that the first bit is 0
298
+ *          str %r1, [&atomic_val]  # write the value
299
+ *
300
+ * However only 31 bits could be used (=> atomic_*_int and atomic_*_long
301
+ *  would still have to be lock based, since in these cases we guarantee all 
302
+ *  the bits)  and I'm not sure there would be a significant performance
303
+ *  benefit when compared with the fallback lock based version:
304
+ *    lock(atomic_lock);
305
+ *    atomic_val=op(*atomic_val, ...)
306
+ *    unlock(atomic_lock);
307
+ *
308
+ *  -- andrei
309
+ */
310
+
311
+#endif /* __CPU_arm6 */
312
+
313
+
314
+#endif
... ...
@@ -86,11 +86,13 @@
86 86
  *                            safe
87 87
  *                   __CPU_i386, __CPU_x86_64, X86_OOSTORE - see 
88 88
  *                       atomic/atomic_x86.h
89
- *                   __CPU_mips, __CPU_mip2, __CPU_mip64, MIPS_HAS_LLSC - see
89
+ *                   __CPU_mips, __CPU_mips2, __CPU_mips64, MIPS_HAS_LLSC - see
90 90
  *                       atomic/atomic_mip2.h
91 91
  *                   __CPU_ppc, __CPU_ppc64 - see atomic/atomic_ppc.h
92 92
  *                   __CPU_sparc - see atomic/atomic_sparc.h
93 93
  *                   __CPU_sparc64, SPARC64_MODE - see atomic/atomic_sparc64.h
94
+ *                   __CPU_arm, __CPU_arm6 - see atomic/atomic_arm.h
95
+ *                   __CPU_alpha - see atomic/atomic_alpha.h
94 96
  */
95 97
 /* 
96 98
  * History:
... ...
@@ -147,6 +149,14 @@ inline static int atomic_get(atomic_t *v)
147 147
 
148 148
 #include "atomic/atomic_sparc.h"
149 149
 
150
+#elif defined __CPU_arm || defined __CPU_arm6
151
+
152
+#include "atomic/atomic_arm.h"
153
+
154
+#elif defined __CPU_alpha
155
+
156
+#include "atomic/atomic_alpha.h"
157
+
150 158
 #endif /* __CPU_xxx  => no known cpu */
151 159
 
152 160
 #endif /* CC_GCC_LIKE_ASM */
... ...
@@ -97,7 +97,7 @@ inline static int tsl(fl_lock_t* lock)
97 97
 			: "=r"(val) : "r"(lock):"memory"
98 98
 	);
99 99
 	
100
-#elif defined __CPU_arm
100
+#elif defined __CPU_arm || defined __CPU_arm6
101 101
 	asm volatile(
102 102
 			"# here \n\t"
103 103
 			"swpb %0, %1, [%2] \n\t"
... ...
@@ -121,7 +121,8 @@ inline static int tsl(fl_lock_t* lock)
121 121
 			: "r"(1), "b" (lock) :
122 122
 			"memory", "cc"
123 123
         );
124
-#elif defined __CPU_mips2 || ( defined __CPU_mips && defined MIPS_HAS_LLSC )
124
+#elif defined __CPU_mips2 || ( defined __CPU_mips && defined MIPS_HAS_LLSC ) \
125
+	|| defined __CPU_mips64
125 126
 	long tmp;
126 127
 	
127 128
 	asm volatile(
... ...
@@ -156,8 +157,7 @@ inline static int tsl(fl_lock_t* lock)
156 156
 		"    mb           \n\t"
157 157
 		"2:               \n\t"
158 158
 		:"=&r" (val), "=m"(*lock), "=r"(tmp)
159
-		:"1"(*lock)  /* warning on gcc 3.4: replace it with m or remove
160
-						it and use +m in the input line ? */
159
+		:"m"(*lock) 
161 160
 		: "memory"
162 161
 	);
163 162
 #else
... ...
@@ -204,7 +204,7 @@ inline static void release_lock(fl_lock_t* lock)
204 204
 			: "r" (lock)
205 205
 			: "memory"
206 206
 	);
207
-#elif defined __CPU_arm
207
+#elif defined __CPU_arm || defined __CPU_arm6
208 208
 	asm volatile(
209 209
 		" str %0, [%1] \n\r" 
210 210
 		: /*no outputs*/ 
... ...
@@ -223,7 +223,8 @@ inline static void release_lock(fl_lock_t* lock)
223 223
 			: "r"(0), "b" (lock)
224 224
 			: "memory"
225 225
 	);
226
-#elif defined __CPU_mips2 || ( defined __CPU_mips && defined MIPS_HAS_LLSC )
226
+#elif defined __CPU_mips2 || ( defined __CPU_mips && defined MIPS_HAS_LLSC ) \
227
+	|| defined __CPU_mips64
227 228
 	asm volatile(
228 229
 		".set push \n\t"
229 230
 		".set noreorder \n\t"