Browse code

- s/atomic_ops_destroy/destroy_atomic_ops - fixed membar w/ locks (should be unlock; lock) - added a separate lock for membar w/ locks (unkown arch).

Andrei Pelinescu-Onciul authored on 03/04/2006 13:32:53
Showing 3 changed files
... ...
@@ -49,17 +49,10 @@
49 49
 
50 50
 #include "../lock_ops.h"
51 51
 
52
-extern gen_lock_t* _atomic_lock; /* declared and init in ../atomic.c */
53
-
54
-#define atomic_lock    lock_get(_atomic_lock)
55
-#define atomic_unlock  lock_release(_atomic_lock)
56 52
 
57 53
 
58 54
 #ifndef HAVE_ASM_INLINE_MEMBAR
59 55
 
60
-#define ATOMIC_OPS_USE_LOCK
61
-
62
-
63 56
 #ifdef NOSMP
64 57
 #define membar()
65 58
 #else /* SMP */
... ...
@@ -67,13 +60,27 @@ extern gen_lock_t* _atomic_lock; /* declared and init in ../atomic.c */
67 67
 #warning no native memory barrier implementations, falling back to slow lock \
68 68
 	       based workarround
69 69
 
70
+#define MEMBAR_USES_LOCK
71
+
72
+extern gen_lock_t* __membar_lock; /* init in atomic_ops.c */
73
+#define _membar_lock    lock_get(__membar_lock)
74
+#define _membar_unlock  lock_release(__membar_lock)
75
+
70 76
 /* memory barriers 
71
- *  not a known cpu -> fall back lock/unlock: safe but costly  (it should 
72
- *  include a memory barrier effect) */
77
+ *  not a known cpu -> fall back unlock/lock: safe but costly  (it should 
78
+ *  include a memory barrier effect)
79
+ *  lock/unlock does not imply a full memory barrier effect (it allows mixing
80
+ *   operations from before the lock with operations after the lock _inside_
81
+ *  the lock & unlock block; however in most implementations it is equivalent
82
+ *  with at least membar StoreStore | StoreLoad | LoadStore => only LoadLoad
83
+ *  is missing). On the other hand and unlock/lock will always be equivalent
84
+ *  with a full memory barrier
85
+ *  => to be safe we must use either unlock; lock or lock; unlock; lock; unlock
86
+ *  --andrei*/
73 87
 #define membar() \
74 88
 	do{\
75
-		atomic_lock; \
76
-		atomic_unlock; \
89
+		_membar_unlock; \
90
+		_membar_lock; \
77 91
 	} while(0)
78 92
 #endif /* NOSMP */
79 93
 
... ...
@@ -91,6 +98,12 @@ extern gen_lock_t* _atomic_lock; /* declared and init in ../atomic.c */
91 91
 #define ATOMIC_OPS_USE_LOCK
92 92
 #endif
93 93
 
94
+extern gen_lock_t* _atomic_lock; /* declared and init in ../atomic_ops.c */
95
+
96
+#define atomic_lock    lock_get(_atomic_lock)
97
+#define atomic_unlock  lock_release(_atomic_lock)
98
+
99
+
94 100
 /* atomic ops */
95 101
 
96 102
 
... ...
@@ -36,39 +36,64 @@
36 36
 #include "atomic_ops_init.h"
37 37
 #include "atomic_ops.h"
38 38
 
39
-#ifdef ATOMIC_OPS_USE_LOCK
40
-
39
+#if defined ATOMIC_OPS_USE_LOCK  || defines MEMBAR_USES_LOCK
41 40
 #include "locking.h"
41
+#endif
42 42
 
43
-gen_lock_t* _atomic_lock;
43
+#ifdef MEMBAR_USES_LOCK
44
+gen_lock_t* __membar_lock=0; /* init in atomic_ops.c */
45
+#endif
46
+
47
+#ifdef ATOMIC_OPS_USE_LOCK
48
+gen_lock_t* _atomic_lock=0;
44 49
 #endif
45 50
 
46 51
 
47 52
 /* returns 0 on success, -1 on error */
48 53
 int init_atomic_ops()
49 54
 {
50
-	int ret;
51 55
 	
52
-	ret=0;
56
+#ifdef MEMBAR_USES_LOCK
57
+	if ((__membar_lock=lock_alloc())==0){
58
+		goto error;
59
+	}
60
+	if (lock_init(__membar_lock)==0){
61
+		lock_dealloc(__membar_lock);
62
+		__membar_lock=0;
63
+		goto error;
64
+	}
65
+	_membar_lock; /* start with the lock "taken" so that we can safely use
66
+					 unlock/lock sequences on it later */
67
+#endif
53 68
 #ifdef ATOMIC_OPS_USE_LOCK
54 69
 	if ((_atomic_lock=lock_alloc())==0){
55
-		ret=-1;
56
-		goto end;
70
+		goto error;
57 71
 	}
58 72
 	if (lock_init(_atomic_lock)==0){
59
-		ret=-1;
60
-		atomic_ops_destroy();
61
-		goto end;
73
+		lock_dealloc(_atomic_lock);
74
+		_atomic_lock=0;
75
+		goto error;
62 76
 	}
63
-end:
64 77
 #endif
65
-	return ret;
78
+	return 0;
79
+#if defined MEMBAR_USES_LOCK || defined ATOMIC_OPS_USE_LOCK
80
+error:
81
+	destroy_atomic_ops();
82
+	return -1;
83
+#endif
66 84
 }
67 85
 
68 86
 
69 87
 
70 88
 void destroy_atomic_ops()
71 89
 {
90
+#ifdef MEMBAR_USES_LOCK
91
+	if (__membar_lock!=0){
92
+		lock_destroy(__membar_lock);
93
+		lock_dealloc(__membar_lock);
94
+		__membar_lock=0;
95
+	}
96
+#endif
72 97
 #ifdef ATOMIC_OPS_USE_LOCK
73 98
 	if (_atomic_lock!=0){
74 99
 		lock_destroy(_atomic_lock);
... ...
@@ -41,13 +41,19 @@
41 41
 
42 42
 #include "../atomic_ops.h"
43 43
 
44
-#ifdef ATOMIC_OPS_USE_LOCK 
44
+#if defined ATOMIC_OPS_USE_LOCK  || defined MEMBAR_USES_LOCK
45 45
 /* hack to make lock work */
46 46
 #include "../lock_ops.h"
47
+#endif
47 48
 
48
-gen_lock_t* _atomic_lock;
49
+#ifdef MEMBAR_USES_LOCK
50
+gen_lock_t* __membar_lock=0; /* init in atomic_ops.c */
51
+gen_lock_t dummy_membar_lock;
52
+#endif
49 53
 
50
-gen_lock_t dummy_lock;
54
+#ifdef ATOMIC_OPS_USE_LOCK
55
+gen_lock_t* _atomic_lock=0;
56
+gen_lock_t dummy_atomic_lock;
51 57
 
52 58
 #endif
53 59
 
... ...
@@ -152,11 +158,21 @@ int main(int argc, char** argv)
152 152
 	v=&var;
153 153
 	
154 154
 	
155
+#ifdef MEMBAR_USES_LOCK
156
+	__membar_lock=&dummy_membar_lock;
157
+	if (lock_init(__membar_lock)==0){
158
+		fprintf(stderr, "ERROR: failed to initialize membar_lock\n");
159
+		__membar_lock=0;
160
+		goto error;
161
+	}
162
+	_membar_lock; /* start with the lock "taken" so that we can safely use
163
+					 unlock/lock sequences on it later */
164
+#endif
155 165
 #ifdef ATOMIC_OPS_USE_LOCK
156 166
 	/* init the lock (emulate atomic_ops.c) */
157
-	_atomic_lock=&dummy_lock;
167
+	_atomic_lock=&dummy_atomic_lock;
158 168
 	if (lock_init(_atomic_lock)==0){
159
-		fprintf(stderr, "ERROR: failed to initialize the lock\n");
169
+		fprintf(stderr, "ERROR: failed to initialize atomic_lock\n");
160 170
 		_atomic_lock=0;
161 171
 		goto error;
162 172
 	}
... ...
@@ -204,11 +220,18 @@ int main(int argc, char** argv)
204 204
 
205 205
 	
206 206
 	printf("\ndone.\n");
207
+#ifdef MEMBAR_USES_LOCK
208
+	lock_destroy(__membar_lock);
209
+#endif
207 210
 #ifdef ATOMIC_OPS_USE_LOCK
208 211
 	lock_destroy(_atomic_lock);
209 212
 #endif
210 213
 	return 0;
211 214
 error:
215
+#ifdef MEMBAR_USES_LOCK
216
+	if (__membar_lock)
217
+		lock_destroy(__membar_lock);
218
+#endif
212 219
 #ifdef ATOMIC_OPS_USE_LOCK
213 220
 	if (_atomic_lock)
214 221
 		lock_destroy(_atomic_lock);