Browse code

- added membar_depends(), needed on smp archs. with separate cache banks where it's possible to get a new pointer value, but the old pointer content (e.g. if the two are in different cache banks and the "content" bank is very busy processing a long invalidations queue). For now only Alpha SMP needs it, on all other archs is a no-op (for more info see atomic_ops.h , http://lse.sourceforge.net/locking/wmbdd.html, http://www.linuxjournal.com/article/8212 or Alpha Architecture Reference Manual Chapter 5.6.

- added membar_atomic_op(), membar_atomic_setget(), membar_read_atomic_op(),
membar_read_atomic_setget(), membar_write_atomic_op(),
membar_write_atomic_setget() -- special case memory barriers that can be
optimized if the atomic ops already force some kind of barrier (e.g. x86),
see the description in atomic_ops.h for more info.

Andrei Pelinescu-Onciul authored on 29/05/2007 11:31:29
Showing 10 changed files
... ...
@@ -28,6 +28,8 @@
28 28
  * --------
29 29
  *  2006-03-31  created by andrei
30 30
  *  2007-05-10  added atomic_add & atomic_cmpxchg (andrei)
31
+ *  2007-05-29  added membar_depends(), membar_*_atomic_op and
32
+ *                membar_*_atomic_setget (andrei)
31 33
  */
32 34
 
33 35
 
... ...
@@ -44,19 +46,43 @@
44 46
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
45 47
 #define membar_read()  membar()
46 48
 #define membar_write() membar()
49
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
47 50
 /* lock barriers: empty, not needed for NOSMP; the lock/unlock should already
48 51
  * contain gcc barriers*/
49
-#define membar_enter_lock() 
50
-#define membar_leave_lock()
52
+#define membar_enter_lock() do {} while(0)
53
+#define membar_leave_lock() do {} while(0)
54
+/* membars after or before atomic_ops or atomic_setget -> use these or
55
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
56
+ *  situations (on some archs where the atomic operations imply memory
57
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
58
+ *    atomic_op_x(); membar()) */
59
+#define membar_atomic_op()				membar()
60
+#define membar_atomic_setget()			membar()
61
+#define membar_write_atomic_op()		membar_write()
62
+#define membar_write_atomic_setget()	membar_write()
63
+#define membar_read_atomic_op()			membar_read()
64
+#define membar_read_atomic_setget()		membar_read()
51 65
 
52 66
 #else
53 67
 
54 68
 #define membar()		asm volatile ("    mb \n\t" : : : "memory" ) 
55 69
 #define membar_read()	membar()
56 70
 #define membar_write()	asm volatile ("    wmb \n\t" : : : "memory" )
71
+#define membar_depends()	asm volatile ("mb \n\t" : : : "memory" )
57 72
 #define membar_enter_lock() asm volatile("mb \n\t" : : : "memory")
58 73
 #define membar_leave_lock() asm volatile("mb \n\t" : : : "memory")
59 74
 
75
+/* membars after or before atomic_ops or atomic_setget -> use these or
76
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
77
+ *  situations (on some archs where the atomic operations imply memory
78
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
79
+ *    atomic_op_x(); membar()) */
80
+#define membar_atomic_op()				membar()
81
+#define membar_atomic_setget()			membar()
82
+#define membar_write_atomic_op()		membar_write()
83
+#define membar_write_atomic_setget()	membar_write()
84
+#define membar_read_atomic_op()			membar_read()
85
+#define membar_read_atomic_setget()		membar_read()
60 86
 #endif /* NOSMP */
61 87
 
62 88
 
... ...
@@ -29,6 +29,8 @@
29 29
  * --------
30 30
  *  2006-03-31  created by andrei
31 31
  *  2007-05-10  added atomic_add and atomic_cmpxchg (andrei)
32
+ *  2007-05-29  added membar_depends(), membar_*_atomic_op and
33
+ *                membar_*_atomic_setget (andrei)
32 34
  */
33 35
 
34 36
 
... ...
@@ -44,10 +46,22 @@
44 46
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
45 47
 #define membar_read()  membar()
46 48
 #define membar_write() membar()
49
+#define membar_depends()   do {} while(0) /* really empty, not even a cc bar.*/
47 50
 /* lock barriers: empty, not needed for NOSMP; the lock/unlock should already
48 51
  * contain gcc barriers*/
49
-#define membar_enter_lock() 
50
-#define membar_leave_lock()
52
+#define membar_enter_lock() do {} while(0)
53
+#define membar_leave_lock() do {} while(0)
54
+/* membars after or before atomic_ops or atomic_setget -> use these or
55
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
56
+ *  situations (on some archs where the atomic operations imply memory
57
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
58
+ *    atomic_op_x(); membar()) */
59
+#define membar_atomic_op()				membar()
60
+#define membar_atomic_setget()			membar()
61
+#define membar_write_atomic_op()		membar_write()
62
+#define membar_write_atomic_setget()	membar_write()
63
+#define membar_read_atomic_op()			membar_read()
64
+#define membar_read_atomic_setget()		membar_read()
51 65
 #else /* SMP */
52 66
 #warning SMP not supported for arm atomic ops, try compiling with -DNOSMP
53 67
 /* fall back to default lock based barriers (don't define HAVE_ASM...) */
... ...
@@ -34,6 +34,8 @@
34 34
  * --------
35 35
  *  2006-03-08  created by andrei
36 36
  *  2007-05-10  added atomic_add & atomic_cmpxchg (andrei)
37
+ *  2007-05-29  added membar_depends(), membar_*_atomic_op and
38
+ *                membar_*_atomic_setget (andrei)
37 39
  */
38 40
 
39 41
 
... ...
@@ -52,10 +54,22 @@
52 54
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
53 55
 #define membar_read()  membar()
54 56
 #define membar_write() membar()
57
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
55 58
 /* lock barriers: empty, not needed for NOSMP; the lock/unlock should already
56 59
  * contain gcc barriers*/
57
-#define membar_enter_lock() 
58
-#define membar_leave_lock()
60
+#define membar_enter_lock() do {} while(0)
61
+#define membar_leave_lock() do {} while(0)
62
+/* membars after or before atomic_ops or atomic_setget -> use these or
63
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
64
+ *  situations (on some archs where the atomic operations imply memory
65
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
66
+ *    atomic_op_x(); membar()) */
67
+#define membar_atomic_op()				membar()
68
+#define membar_atomic_setget()			membar()
69
+#define membar_write_atomic_op()		membar_write()
70
+#define membar_write_atomic_setget()	membar_write()
71
+#define membar_read_atomic_op()			membar_read()
72
+#define membar_read_atomic_setget()		membar_read()
59 73
 
60 74
 #else
61 75
 
... ...
@@ -71,8 +85,20 @@
71 85
 
72 86
 #define membar_read()  membar()
73 87
 #define membar_write() membar()
88
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
74 89
 #define membar_enter_lock() membar()
75 90
 #define membar_leave_lock() membar()
91
+/* membars after or before atomic_ops or atomic_setget -> use these or
92
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
93
+ *  situations (on some archs where the atomic operations imply memory
94
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
95
+ *    atomic_op_x(); membar()) */
96
+#define membar_atomic_op()				membar()
97
+#define membar_atomic_setget()			membar()
98
+#define membar_write_atomic_op()		membar_write()
99
+#define membar_write_atomic_setget()	membar_write()
100
+#define membar_read_atomic_op()			membar_read()
101
+#define membar_read_atomic_setget()		membar_read()
76 102
 
77 103
 #endif /* NOSMP */
78 104
 
... ...
@@ -34,6 +34,8 @@
34 34
  *               r0 as the second operand in addi and  addi rD,r0, val
35 35
  *               is a special case, equivalent with rD=0+val and not
36 36
  *               rD=r0+val (andrei)
37
+ *  2007-05-29  added membar_depends(), membar_*_atomic_op and
38
+ *                membar_*_atomic_setget (andrei)
37 39
  */
38 40
 
39 41
 #ifndef _atomic_ppc_h
... ...
@@ -52,10 +54,22 @@
52 54
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
53 55
 #define membar_read()  membar()
54 56
 #define membar_write() membar()
57
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
55 58
 /* lock barriers: empty, not needed for NOSMP; the lock/unlock should already
56 59
  * contain gcc barriers*/
57
-#define membar_enter_lock() 
58
-#define membar_leave_lock()
60
+#define membar_enter_lock() do {} while(0)
61
+#define membar_leave_lock() do {} while(0)
62
+/* membars after or before atomic_ops or atomic_setget -> use these or
63
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
64
+ *  situations (on some archs where the atomic operations imply memory
65
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
66
+ *    atomic_op_x(); membar()) */
67
+#define membar_atomic_op()				membar()
68
+#define membar_atomic_setget()			membar()
69
+#define membar_write_atomic_op()		membar_write()
70
+#define membar_write_atomic_setget()	membar_write()
71
+#define membar_read_atomic_op()			membar_read()
72
+#define membar_read_atomic_setget()		membar_read()
59 73
 
60 74
 #else
61 75
 #define membar() asm volatile ("sync \n\t" : : : "memory") 
... ...
@@ -63,10 +77,22 @@
63 77
 #define membar_read() asm volatile ("lwsync \n\t" : : : "memory") 
64 78
 /* on "normal" cached mem. eieio orders StoreStore */
65 79
 #define membar_write() asm volatile ("eieio \n\t" : : : "memory") 
80
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
66 81
 #define membar_enter_lock() asm volatile("lwsync \n\t" : : : "memory")
67 82
 /* for unlock lwsync will work too and is faster then sync
68 83
  *  [IBM Prgramming Environments Manual, D.4.2.2] */
69 84
 #define membar_leave_lock() asm volatile("lwsync \n\t" : : : "memory")
85
+/* membars after or before atomic_ops or atomic_setget -> use these or
86
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
87
+ *  situations (on some archs where the atomic operations imply memory
88
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
89
+ *    atomic_op_x(); membar()) */
90
+#define membar_atomic_op()				membar()
91
+#define membar_atomic_setget()			membar()
92
+#define membar_write_atomic_op()		membar_write()
93
+#define membar_write_atomic_setget()	membar_write()
94
+#define membar_read_atomic_op()			membar_read()
95
+#define membar_read_atomic_setget()		membar_read()
70 96
 #endif /* NOSMP */
71 97
 
72 98
 
... ...
@@ -25,6 +25,8 @@
25 25
  * History:
26 26
  * --------
27 27
  *  2006-03-28  created by andrei
28
+ *  2007-05-29  added membar_depends(), membar_*_atomic_op and
29
+ *                membar_*_atomic_setget (andrei)
28 30
  */
29 31
 
30 32
 
... ...
@@ -40,16 +42,40 @@
40 42
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
41 43
 #define membar_read()  membar()
42 44
 #define membar_write() membar()
45
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
43 46
 /* lock barrriers: empty, not needed for NOSMP; the lock/unlock should already
44 47
  * contain gcc barriers*/
45
-#define membar_enter_lock() 
46
-#define membar_leave_lock()
48
+#define membar_enter_lock() do {} while(0)
49
+#define membar_leave_lock() do {} while(0)
50
+/* membars after or before atomic_ops or atomic_setget -> use these or
51
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
52
+ *  situations (on some archs where the atomic operations imply memory
53
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
54
+ *    atomic_op_x(); membar()) */
55
+#define membar_atomic_op()				membar()
56
+#define membar_atomic_setget()			membar()
57
+#define membar_write_atomic_op()		membar_write()
58
+#define membar_write_atomic_setget()	membar_write()
59
+#define membar_read_atomic_op()			membar_read()
60
+#define membar_read_atomic_setget()		membar_read()
47 61
 #else /* SMP */
48 62
 #define membar_write() asm volatile ("stbar \n\t" : : : "memory") 
49 63
 #define membar() membar_write()
50 64
 #define membar_read() asm volatile ("" : : : "memory") 
51
-#define membar_enter_lock() 
65
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
66
+#define membar_enter_lock() do {} while(0)
52 67
 #define membar_leave_lock() asm volatile ("stbar \n\t" : : : "memory") 
68
+/* membars after or before atomic_ops or atomic_setget -> use these or
69
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
70
+ *  situations (on some archs where the atomic operations imply memory
71
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
72
+ *    atomic_op_x(); membar()) */
73
+#define membar_atomic_op()				membar()
74
+#define membar_atomic_setget()			membar()
75
+#define membar_write_atomic_op()		membar_write()
76
+#define membar_write_atomic_setget()	membar_write()
77
+#define membar_read_atomic_op()			membar_read()
78
+#define membar_read_atomic_setget()		membar_read()
53 79
 
54 80
 #endif /* NOSMP */
55 81
 
... ...
@@ -30,6 +30,8 @@
30 30
  * --------
31 31
  *  2006-03-28  created by andrei
32 32
  *  2007-05-08 added atomic_add and atomic_cmpxchg (andrei)
33
+ *  2007-05-29  added membar_depends(), membar_*_atomic_op and
34
+ *                membar_*_atomic_setget (andrei)
33 35
  */
34 36
 
35 37
 
... ...
@@ -52,6 +54,7 @@
52 54
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
53 55
 #define membar_read()  membar()
54 56
 #define membar_write() membar()
57
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
55 58
 /*  memory barriers for lock & unlock where lock & unlock are inline asm
56 59
  *  functions that use atomic ops (and both of them use at least a store to
57 60
  *  the lock). membar_enter_lock() is at most a StoreStore|StoreLoad barrier
... ...
@@ -64,8 +67,19 @@
64 67
  *
65 68
  *  Usage: lock(); membar_enter_lock(); .... ; membar_leave_lock(); unlock()
66 69
  */
67
-#define membar_enter_lock()
68
-#define membar_leave_lock()
70
+#define membar_enter_lock() do {} while(0)
71
+#define membar_leave_lock() do {} while(0)
72
+/* membars after or before atomic_ops or atomic_setget -> use these or
73
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
74
+ *  situations (on some archs where the atomic operations imply memory
75
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
76
+ *    atomic_op_x(); membar()) */
77
+#define membar_atomic_op()				membar()
78
+#define membar_atomic_setget()			membar()
79
+#define membar_write_atomic_op()		membar_write()
80
+#define membar_write_atomic_setget()	membar_write()
81
+#define membar_read_atomic_op()			membar_read()
82
+#define membar_read_atomic_setget()		membar_read()
69 83
 #else /* SMP */
70 84
 #define membar() \
71 85
 	asm volatile ( \
... ...
@@ -74,10 +88,22 @@
74 88
 
75 89
 #define membar_read() asm volatile ("membar #LoadLoad \n\t" : : : "memory")
76 90
 #define membar_write() asm volatile ("membar #StoreStore \n\t" : : : "memory")
91
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
77 92
 #define membar_enter_lock() \
78 93
 	asm volatile ("membar #StoreStore | #StoreLoad \n\t" : : : "memory");
79 94
 #define membar_leave_lock() \
80 95
 	asm volatile ("membar #LoadStore | #StoreStore \n\t" : : : "memory");
96
+/* membars after or before atomic_ops or atomic_setget -> use these or
97
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
98
+ *  situations (on some archs where the atomic operations imply memory
99
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
100
+ *    atomic_op_x(); membar()) */
101
+#define membar_atomic_op()				membar()
102
+#define membar_atomic_setget()			membar()
103
+#define membar_write_atomic_op()		membar_write()
104
+#define membar_write_atomic_setget()	membar_write()
105
+#define membar_read_atomic_op()			membar_read()
106
+#define membar_read_atomic_setget()		membar_read()
81 107
 #endif /* NOSMP */
82 108
 
83 109
 
... ...
@@ -35,6 +35,8 @@
35 35
  *  2006-03-08  created by andrei
36 36
  *  2007-05-11  added atomic_add and atomic_cmpxchg 
37 37
  *              use lock_set if lock economy is not needed (andrei)
38
+ *  2007-05-29  added membar_depends(), membar_*_atomic_op and
39
+ *                membar_*_atomic_setget (andrei)
38 40
  */
39 41
 
40 42
 #ifndef _atomic_unknown_h
... ...
@@ -47,7 +49,7 @@
47 49
 #ifndef HAVE_ASM_INLINE_MEMBAR
48 50
 
49 51
 #ifdef NOSMP
50
-#define membar()
52
+#define membar() do {} while(0)
51 53
 #else /* SMP */
52 54
 
53 55
 #warning no native memory barrier implementations, falling back to slow lock \
... ...
@@ -82,6 +84,29 @@ extern gen_lock_t* __membar_lock; /* init in atomic_ops.c */
82 84
 
83 85
 #define membar_read()  membar()
84 86
 
87
+
88
+#ifndef __CPU_alpha
89
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
90
+#else
91
+/* really slow */
92
+#define membar_depends()  membar_read()
93
+#endif
94
+
95
+#define membar_enter_lock() do {} while(0)
96
+#define membar_leave_lock() do {} while(0)
97
+
98
+/* membars after or before atomic_ops or atomic_setget -> use these or
99
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
100
+ *  situations (on some archs where the atomic operations imply memory
101
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
102
+ *    atomic_op_x(); membar()) */
103
+#define membar_atomic_op()				membar()
104
+#define membar_atomic_setget()			membar()
105
+#define membar_write_atomic_op()		membar_write()
106
+#define membar_write_atomic_setget()	membar_write()
107
+#define membar_read_atomic_op()			membar_read()
108
+#define membar_read_atomic_setget()		membar_read()
109
+
85 110
 #endif /* HAVE_ASM_INLINE_MEMBAR */
86 111
 
87 112
 
... ...
@@ -35,6 +35,8 @@
35 35
  *  2006-03-08  created by andrei
36 36
  *  2007-05-07  added cmpxchg (andrei)
37 37
  *  2007-05-08  added atomic_add (andrei)
38
+ *  2007-05-29  added membar_depends(), membar_*_atomic_op and
39
+ *                membar_*_atomic_setget (andrei)
38 40
  */
39 41
 
40 42
 #ifndef _atomic_x86_h
... ...
@@ -57,10 +59,22 @@
57 59
 #define membar()	asm volatile ("" : : : "memory")
58 60
 #define membar_read()	membar()
59 61
 #define membar_write()	membar()
62
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
60 63
 /* lock barrriers: empty, not needed for NOSMP; the lock/unlock should already
61 64
  * contain gcc barriers*/
62
-#define membar_enter_lock() 
63
-#define membar_leave_lock()
65
+#define membar_enter_lock() do {} while(0)
66
+#define membar_leave_lock() do {} while(0)
67
+/* membars after or before atomic_ops or atomic_setget -> use these or
68
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
69
+ *  situations (on some archs where the atomic operations imply memory
70
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
71
+ *    atomic_op_x(); membar()) */
72
+#define membar_atomic_op()				do {} while(0)
73
+#define membar_atomic_setget()			membar()
74
+#define membar_write_atomic_op()		do {} while(0)
75
+#define membar_write_atomic_setget()	membar_write()
76
+#define membar_read_atomic_op()			do {} while(0)
77
+#define membar_read_atomic_setget()		membar_read()
64 78
 
65 79
 #else
66 80
 
... ...
@@ -99,15 +113,23 @@
99 113
 
100 114
 #endif /* __CPU_x86_64 */
101 115
 
116
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
102 117
 /* lock barrriers: empty, not needed on x86 or x86_64 (atomic ops already
103 118
  *  force the barriers if needed); the lock/unlock should already contain the 
104 119
  *  gcc do_not_cache barriers*/
105
-#define membar_enter_lock() 
106
-#define membar_leave_lock()
107
-
108
-
109
-
110
-
120
+#define membar_enter_lock() do {} while(0)
121
+#define membar_leave_lock() do {} while(0)
122
+/* membars after or before atomic_ops or atomic_setget -> use these or
123
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
124
+ *  situations (on some archs where the atomic operations imply memory
125
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
126
+ *    atomic_op_x(); membar()) */
127
+#define membar_atomic_op()				do {} while(0)
128
+#define membar_atomic_setget()			membar()
129
+#define membar_write_atomic_op()		do {} while(0)
130
+#define membar_write_atomic_setget()	membar_write()
131
+#define membar_read_atomic_op()			do {} while(0)
132
+#define membar_read_atomic_setget()		membar_read()
111 133
 
112 134
 
113 135
 #endif /* NOSMP */
... ...
@@ -22,9 +22,15 @@
22 22
  *  memory barriers:
23 23
  *  ----------------
24 24
  *
25
- *  void membar();       - memory barrier (load & store)
26
- *  void membar_read()   - load (read) memory barrier
27
- *  void membar_write()  - store (write) memory barrier
25
+ *  void membar();        - memory barrier (load & store)
26
+ *  void membar_read()    - load (read) memory barrier
27
+ *  void membar_write()   - store (write) memory barrier
28
+ *  void membar_depends() - read depends memory barrier, needed before using
29
+ *                          the contents of a pointer (for now is needed only
30
+ *                          on Alpha so on all other CPUs it will be a no-op)
31
+ *                          For more info see: 
32
+ *                          http://lse.sourceforge.net/locking/wmbdd.html
33
+ *                          http://www.linuxjournal.com/article/8212
28 34
  *
29 35
  *  void membar_enter_lock() - memory barrier function that should be 
30 36
  *                             called after a lock operation (where lock is
... ...
@@ -44,6 +50,37 @@
44 50
  *                             Example: raw_lock(l); membar_enter_lock(); ..
45 51
  *                                      ... critical section ...
46 52
  *                                      membar_leave_lock(); raw_unlock(l);
53
+ *  void membar_atomic_op() - memory barrier that should be called if a memory
54
+ *                            barrier is needed immediately after or 
55
+ *                            immediately before an atomic operation
56
+ *                            (for example: atomic_inc(&i); membar_atomic_op()
57
+ *                               instead of atomic_inc(&i); membar()).
58
+ *                            atomic_op means every atomic operation except get
59
+ *                            and set (for them use membar_atomic_setget()).
60
+ *                            Using membar_atomic_op() instead of membar() in
61
+ *                            these cases will generate faster code on some
62
+ *                            architectures (for now x86 and x86_64), where 
63
+ *                            atomic operations act also as memory barriers.
64
+ *                            Note that mb_atomic_<OP>(...) is equivalent to
65
+ *                            membar_atomic_op(); atomic_<OP>(...) and in this
66
+ *                            case the first form is preferred).
67
+ * void membar_atomic_setget() - same as above but for atomic_set and 
68
+ *                            atomic_get (and not for any other atomic op.,
69
+ *                            including atomic_get_and_set, for them use
70
+ *                            membar_atomic_op()).
71
+ *                            Note that mb_atomic_{get,set}(&i) is equivalent 
72
+ *                            and preferred to membar_atomic_setget(); 
73
+ *                            atomic_{get,set}(&i) (it will generate faster
74
+ *                            code on x86 and x86_64).
75
+ * void membar_read_atomic_op() - like membar_atomic_op(), but acts only as
76
+ *                             a read barrier.
77
+ * void membar_read_atomic_setget() - like membar_atomic_setget() but acts only
78
+ *                            as a read barrier.
79
+ * void membar_write_atomic_op() - like membar_atomic_op(), but acts only as
80
+ *                            a write barrier.
81
+ * void membar_write_atomic_setget() - like membar_atomic_setget() but acts 
82
+ *                            only as a write barrier.
83
+ *
47 84
  *
48 85
  *  Note: - properly using memory barriers is tricky, in general try not to 
49 86
  *        depend on them. Locks include memory barriers, so you don't need
... ...
@@ -67,6 +104,10 @@
67 104
  *  int atomic_dec_and_test(atomic_t* v)     - returns 1 if the result is 0
68 105
  *  void atomic_or (atomic_t* v, int mask)   - v->val|=mask 
69 106
  *  void atomic_and(atomic_t* v, int mask)   - v->val&=mask
107
+ *  int atomic_add(atomic_t* v, int i)       - v->val+=i; return v->val
108
+ *  int atomic_cmpxchg(atomic_t* v, o, n)    - r=v->val; if (r==o) v->val=n;
109
+ *                                             return r (old value)
110
+ *
70 111
  * 
71 112
  * same ops, but with builtin memory barriers:
72 113
  *
... ...
@@ -79,6 +120,9 @@
79 120
  *  int mb_atomic_dec_and_test(atomic_t* v)  - returns 1 if the result is 0
80 121
  *  void mb_atomic_or(atomic_t* v, int mask - v->val|=mask 
81 122
  *  void mb_atomic_and(atomic_t* v, int mask)- v->val&=mask
123
+ *  int mb_atomic_add(atomic_t* v, int i)    - v->val+=i; return v->val
124
+ *  int mb_atomic_cmpxchg(atomic_t* v, o, n) - r=v->val; if (r==o) v->val=n;
125
+ *                                             return r (old value)
82 126
  *
83 127
  *  Same operations are available for int and long. The functions are named
84 128
  *   after the following rules:
... ...
@@ -209,6 +209,24 @@ int main(int argc, char** argv)
209 209
 	printf(" membar_write() ........................ ok\n");
210 210
 	membar_read();
211 211
 	printf(" membar_read() ......................... ok\n");
212
+	membar_depends();
213
+	printf(" membar_depends() ...................... ok\n");
214
+	membar_enter_lock();
215
+	printf(" membar_enter_lock() ................... ok\n");
216
+	membar_leave_lock();
217
+	printf(" membar_leave_lock() ................... ok\n");
218
+	membar_atomic_op();
219
+	printf(" membar_atomic_op() .................... ok\n");
220
+	membar_atomic_setget();
221
+	printf(" membar_atomic_setget() ................ ok\n");
222
+	membar_read_atomic_op();
223
+	printf(" membar_read_atomic_op() ............... ok\n");
224
+	membar_read_atomic_setget();
225
+	printf(" membar_read_atomic_setget() ........... ok\n");
226
+	membar_write_atomic_op();
227
+	printf(" membar_write_atomic_op() .............. ok\n");
228
+	membar_write_atomic_setget();
229
+	printf(" membar_write_atomic_setget() .......... ok\n");
212 230
 	
213 231
 	printf("\nstarting atomic ops basic tests...\n");
214 232