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 44
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
45 45
 #define membar_read()  membar()
46 46
 #define membar_write() membar()
47
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
47 48
 /* lock barriers: empty, not needed for NOSMP; the lock/unlock should already
48 49
  * contain gcc barriers*/
49
-#define membar_enter_lock() 
50
-#define membar_leave_lock()
50
+#define membar_enter_lock() do {} while(0)
51
+#define membar_leave_lock() do {} while(0)
52
+/* membars after or before atomic_ops or atomic_setget -> use these or
53
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
54
+ *  situations (on some archs where the atomic operations imply memory
55
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
56
+ *    atomic_op_x(); membar()) */
57
+#define membar_atomic_op()				membar()
58
+#define membar_atomic_setget()			membar()
59
+#define membar_write_atomic_op()		membar_write()
60
+#define membar_write_atomic_setget()	membar_write()
61
+#define membar_read_atomic_op()			membar_read()
62
+#define membar_read_atomic_setget()		membar_read()
51 63
 
52 64
 #else
53 65
 
54 66
 #define membar()		asm volatile ("    mb \n\t" : : : "memory" ) 
55 67
 #define membar_read()	membar()
56 68
 #define membar_write()	asm volatile ("    wmb \n\t" : : : "memory" )
69
+#define membar_depends()	asm volatile ("mb \n\t" : : : "memory" )
57 70
 #define membar_enter_lock() asm volatile("mb \n\t" : : : "memory")
58 71
 #define membar_leave_lock() asm volatile("mb \n\t" : : : "memory")
59 72
 
73
+/* membars after or before atomic_ops or atomic_setget -> use these or
74
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
75
+ *  situations (on some archs where the atomic operations imply memory
76
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
77
+ *    atomic_op_x(); membar()) */
78
+#define membar_atomic_op()				membar()
79
+#define membar_atomic_setget()			membar()
80
+#define membar_write_atomic_op()		membar_write()
81
+#define membar_write_atomic_setget()	membar_write()
82
+#define membar_read_atomic_op()			membar_read()
83
+#define membar_read_atomic_setget()		membar_read()
60 84
 #endif /* NOSMP */
61 85
 
62 86
 
... ...
@@ -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 44
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
45 45
 #define membar_read()  membar()
46 46
 #define membar_write() membar()
47
+#define membar_depends()   do {} while(0) /* really empty, not even a cc bar.*/
47 48
 /* lock barriers: empty, not needed for NOSMP; the lock/unlock should already
48 49
  * contain gcc barriers*/
49
-#define membar_enter_lock() 
50
-#define membar_leave_lock()
50
+#define membar_enter_lock() do {} while(0)
51
+#define membar_leave_lock() do {} while(0)
52
+/* membars after or before atomic_ops or atomic_setget -> use these or
53
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
54
+ *  situations (on some archs where the atomic operations imply memory
55
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
56
+ *    atomic_op_x(); membar()) */
57
+#define membar_atomic_op()				membar()
58
+#define membar_atomic_setget()			membar()
59
+#define membar_write_atomic_op()		membar_write()
60
+#define membar_write_atomic_setget()	membar_write()
61
+#define membar_read_atomic_op()			membar_read()
62
+#define membar_read_atomic_setget()		membar_read()
51 63
 #else /* SMP */
52 64
 #warning SMP not supported for arm atomic ops, try compiling with -DNOSMP
53 65
 /* 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 52
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
53 53
 #define membar_read()  membar()
54 54
 #define membar_write() membar()
55
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
55 56
 /* lock barriers: empty, not needed for NOSMP; the lock/unlock should already
56 57
  * contain gcc barriers*/
57
-#define membar_enter_lock() 
58
-#define membar_leave_lock()
58
+#define membar_enter_lock() do {} while(0)
59
+#define membar_leave_lock() do {} while(0)
60
+/* membars after or before atomic_ops or atomic_setget -> use these or
61
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
62
+ *  situations (on some archs where the atomic operations imply memory
63
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
64
+ *    atomic_op_x(); membar()) */
65
+#define membar_atomic_op()				membar()
66
+#define membar_atomic_setget()			membar()
67
+#define membar_write_atomic_op()		membar_write()
68
+#define membar_write_atomic_setget()	membar_write()
69
+#define membar_read_atomic_op()			membar_read()
70
+#define membar_read_atomic_setget()		membar_read()
59 71
 
60 72
 #else
61 73
 
... ...
@@ -71,8 +85,20 @@
71 71
 
72 72
 #define membar_read()  membar()
73 73
 #define membar_write() membar()
74
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
74 75
 #define membar_enter_lock() membar()
75 76
 #define membar_leave_lock() membar()
77
+/* membars after or before atomic_ops or atomic_setget -> use these or
78
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
79
+ *  situations (on some archs where the atomic operations imply memory
80
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
81
+ *    atomic_op_x(); membar()) */
82
+#define membar_atomic_op()				membar()
83
+#define membar_atomic_setget()			membar()
84
+#define membar_write_atomic_op()		membar_write()
85
+#define membar_write_atomic_setget()	membar_write()
86
+#define membar_read_atomic_op()			membar_read()
87
+#define membar_read_atomic_setget()		membar_read()
76 88
 
77 89
 #endif /* NOSMP */
78 90
 
... ...
@@ -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 52
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
53 53
 #define membar_read()  membar()
54 54
 #define membar_write() membar()
55
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
55 56
 /* lock barriers: empty, not needed for NOSMP; the lock/unlock should already
56 57
  * contain gcc barriers*/
57
-#define membar_enter_lock() 
58
-#define membar_leave_lock()
58
+#define membar_enter_lock() do {} while(0)
59
+#define membar_leave_lock() do {} while(0)
60
+/* membars after or before atomic_ops or atomic_setget -> use these or
61
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
62
+ *  situations (on some archs where the atomic operations imply memory
63
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
64
+ *    atomic_op_x(); membar()) */
65
+#define membar_atomic_op()				membar()
66
+#define membar_atomic_setget()			membar()
67
+#define membar_write_atomic_op()		membar_write()
68
+#define membar_write_atomic_setget()	membar_write()
69
+#define membar_read_atomic_op()			membar_read()
70
+#define membar_read_atomic_setget()		membar_read()
59 71
 
60 72
 #else
61 73
 #define membar() asm volatile ("sync \n\t" : : : "memory") 
... ...
@@ -63,10 +77,22 @@
63 63
 #define membar_read() asm volatile ("lwsync \n\t" : : : "memory") 
64 64
 /* on "normal" cached mem. eieio orders StoreStore */
65 65
 #define membar_write() asm volatile ("eieio \n\t" : : : "memory") 
66
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
66 67
 #define membar_enter_lock() asm volatile("lwsync \n\t" : : : "memory")
67 68
 /* for unlock lwsync will work too and is faster then sync
68 69
  *  [IBM Prgramming Environments Manual, D.4.2.2] */
69 70
 #define membar_leave_lock() asm volatile("lwsync \n\t" : : : "memory")
71
+/* membars after or before atomic_ops or atomic_setget -> use these or
72
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
73
+ *  situations (on some archs where the atomic operations imply memory
74
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
75
+ *    atomic_op_x(); membar()) */
76
+#define membar_atomic_op()				membar()
77
+#define membar_atomic_setget()			membar()
78
+#define membar_write_atomic_op()		membar_write()
79
+#define membar_write_atomic_setget()	membar_write()
80
+#define membar_read_atomic_op()			membar_read()
81
+#define membar_read_atomic_setget()		membar_read()
70 82
 #endif /* NOSMP */
71 83
 
72 84
 
... ...
@@ -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 40
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
41 41
 #define membar_read()  membar()
42 42
 #define membar_write() membar()
43
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
43 44
 /* lock barrriers: empty, not needed for NOSMP; the lock/unlock should already
44 45
  * contain gcc barriers*/
45
-#define membar_enter_lock() 
46
-#define membar_leave_lock()
46
+#define membar_enter_lock() do {} while(0)
47
+#define membar_leave_lock() do {} while(0)
48
+/* membars after or before atomic_ops or atomic_setget -> use these or
49
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
50
+ *  situations (on some archs where the atomic operations imply memory
51
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
52
+ *    atomic_op_x(); membar()) */
53
+#define membar_atomic_op()				membar()
54
+#define membar_atomic_setget()			membar()
55
+#define membar_write_atomic_op()		membar_write()
56
+#define membar_write_atomic_setget()	membar_write()
57
+#define membar_read_atomic_op()			membar_read()
58
+#define membar_read_atomic_setget()		membar_read()
47 59
 #else /* SMP */
48 60
 #define membar_write() asm volatile ("stbar \n\t" : : : "memory") 
49 61
 #define membar() membar_write()
50 62
 #define membar_read() asm volatile ("" : : : "memory") 
51
-#define membar_enter_lock() 
63
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
64
+#define membar_enter_lock() do {} while(0)
52 65
 #define membar_leave_lock() asm volatile ("stbar \n\t" : : : "memory") 
66
+/* membars after or before atomic_ops or atomic_setget -> use these or
67
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
68
+ *  situations (on some archs where the atomic operations imply memory
69
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
70
+ *    atomic_op_x(); membar()) */
71
+#define membar_atomic_op()				membar()
72
+#define membar_atomic_setget()			membar()
73
+#define membar_write_atomic_op()		membar_write()
74
+#define membar_write_atomic_setget()	membar_write()
75
+#define membar_read_atomic_op()			membar_read()
76
+#define membar_read_atomic_setget()		membar_read()
53 77
 
54 78
 #endif /* NOSMP */
55 79
 
... ...
@@ -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 52
 #define membar() asm volatile ("" : : : "memory") /* gcc do not cache barrier*/
53 53
 #define membar_read()  membar()
54 54
 #define membar_write() membar()
55
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
55 56
 /*  memory barriers for lock & unlock where lock & unlock are inline asm
56 57
  *  functions that use atomic ops (and both of them use at least a store to
57 58
  *  the lock). membar_enter_lock() is at most a StoreStore|StoreLoad barrier
... ...
@@ -64,8 +67,19 @@
64 64
  *
65 65
  *  Usage: lock(); membar_enter_lock(); .... ; membar_leave_lock(); unlock()
66 66
  */
67
-#define membar_enter_lock()
68
-#define membar_leave_lock()
67
+#define membar_enter_lock() do {} while(0)
68
+#define membar_leave_lock() do {} while(0)
69
+/* membars after or before atomic_ops or atomic_setget -> use these or
70
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
71
+ *  situations (on some archs where the atomic operations imply memory
72
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
73
+ *    atomic_op_x(); membar()) */
74
+#define membar_atomic_op()				membar()
75
+#define membar_atomic_setget()			membar()
76
+#define membar_write_atomic_op()		membar_write()
77
+#define membar_write_atomic_setget()	membar_write()
78
+#define membar_read_atomic_op()			membar_read()
79
+#define membar_read_atomic_setget()		membar_read()
69 80
 #else /* SMP */
70 81
 #define membar() \
71 82
 	asm volatile ( \
... ...
@@ -74,10 +88,22 @@
74 74
 
75 75
 #define membar_read() asm volatile ("membar #LoadLoad \n\t" : : : "memory")
76 76
 #define membar_write() asm volatile ("membar #StoreStore \n\t" : : : "memory")
77
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
77 78
 #define membar_enter_lock() \
78 79
 	asm volatile ("membar #StoreStore | #StoreLoad \n\t" : : : "memory");
79 80
 #define membar_leave_lock() \
80 81
 	asm volatile ("membar #LoadStore | #StoreStore \n\t" : : : "memory");
82
+/* membars after or before atomic_ops or atomic_setget -> use these or
83
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
84
+ *  situations (on some archs where the atomic operations imply memory
85
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
86
+ *    atomic_op_x(); membar()) */
87
+#define membar_atomic_op()				membar()
88
+#define membar_atomic_setget()			membar()
89
+#define membar_write_atomic_op()		membar_write()
90
+#define membar_write_atomic_setget()	membar_write()
91
+#define membar_read_atomic_op()			membar_read()
92
+#define membar_read_atomic_setget()		membar_read()
81 93
 #endif /* NOSMP */
82 94
 
83 95
 
... ...
@@ -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 47
 #ifndef HAVE_ASM_INLINE_MEMBAR
48 48
 
49 49
 #ifdef NOSMP
50
-#define membar()
50
+#define membar() do {} while(0)
51 51
 #else /* SMP */
52 52
 
53 53
 #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 82
 
83 83
 #define membar_read()  membar()
84 84
 
85
+
86
+#ifndef __CPU_alpha
87
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
88
+#else
89
+/* really slow */
90
+#define membar_depends()  membar_read()
91
+#endif
92
+
93
+#define membar_enter_lock() do {} while(0)
94
+#define membar_leave_lock() do {} while(0)
95
+
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()
107
+
85 108
 #endif /* HAVE_ASM_INLINE_MEMBAR */
86 109
 
87 110
 
... ...
@@ -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 57
 #define membar()	asm volatile ("" : : : "memory")
58 58
 #define membar_read()	membar()
59 59
 #define membar_write()	membar()
60
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
60 61
 /* lock barrriers: empty, not needed for NOSMP; the lock/unlock should already
61 62
  * contain gcc barriers*/
62
-#define membar_enter_lock() 
63
-#define membar_leave_lock()
63
+#define membar_enter_lock() do {} while(0)
64
+#define membar_leave_lock() do {} while(0)
65
+/* membars after or before atomic_ops or atomic_setget -> use these or
66
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
67
+ *  situations (on some archs where the atomic operations imply memory
68
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
69
+ *    atomic_op_x(); membar()) */
70
+#define membar_atomic_op()				do {} while(0)
71
+#define membar_atomic_setget()			membar()
72
+#define membar_write_atomic_op()		do {} while(0)
73
+#define membar_write_atomic_setget()	membar_write()
74
+#define membar_read_atomic_op()			do {} while(0)
75
+#define membar_read_atomic_setget()		membar_read()
64 76
 
65 77
 #else
66 78
 
... ...
@@ -99,15 +113,23 @@
99 99
 
100 100
 #endif /* __CPU_x86_64 */
101 101
 
102
+#define membar_depends()  do {} while(0) /* really empty, not even a cc bar. */
102 103
 /* lock barrriers: empty, not needed on x86 or x86_64 (atomic ops already
103 104
  *  force the barriers if needed); the lock/unlock should already contain the 
104 105
  *  gcc do_not_cache barriers*/
105
-#define membar_enter_lock() 
106
-#define membar_leave_lock()
107
-
108
-
109
-
110
-
106
+#define membar_enter_lock() do {} while(0)
107
+#define membar_leave_lock() do {} while(0)
108
+/* membars after or before atomic_ops or atomic_setget -> use these or
109
+ *  mb_<atomic_op_name>() if you need a memory barrier in one of these
110
+ *  situations (on some archs where the atomic operations imply memory
111
+ *   barriers is better to use atomic_op_x(); membar_atomic_op() then
112
+ *    atomic_op_x(); membar()) */
113
+#define membar_atomic_op()				do {} while(0)
114
+#define membar_atomic_setget()			membar()
115
+#define membar_write_atomic_op()		do {} while(0)
116
+#define membar_write_atomic_setget()	membar_write()
117
+#define membar_read_atomic_op()			do {} while(0)
118
+#define membar_read_atomic_setget()		membar_read()
111 119
 
112 120
 
113 121
 #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 44
  *                             Example: raw_lock(l); membar_enter_lock(); ..
45 45
  *                                      ... critical section ...
46 46
  *                                      membar_leave_lock(); raw_unlock(l);
47
+ *  void membar_atomic_op() - memory barrier that should be called if a memory
48
+ *                            barrier is needed immediately after or 
49
+ *                            immediately before an atomic operation
50
+ *                            (for example: atomic_inc(&i); membar_atomic_op()
51
+ *                               instead of atomic_inc(&i); membar()).
52
+ *                            atomic_op means every atomic operation except get
53
+ *                            and set (for them use membar_atomic_setget()).
54
+ *                            Using membar_atomic_op() instead of membar() in
55
+ *                            these cases will generate faster code on some
56
+ *                            architectures (for now x86 and x86_64), where 
57
+ *                            atomic operations act also as memory barriers.
58
+ *                            Note that mb_atomic_<OP>(...) is equivalent to
59
+ *                            membar_atomic_op(); atomic_<OP>(...) and in this
60
+ *                            case the first form is preferred).
61
+ * void membar_atomic_setget() - same as above but for atomic_set and 
62
+ *                            atomic_get (and not for any other atomic op.,
63
+ *                            including atomic_get_and_set, for them use
64
+ *                            membar_atomic_op()).
65
+ *                            Note that mb_atomic_{get,set}(&i) is equivalent 
66
+ *                            and preferred to membar_atomic_setget(); 
67
+ *                            atomic_{get,set}(&i) (it will generate faster
68
+ *                            code on x86 and x86_64).
69
+ * void membar_read_atomic_op() - like membar_atomic_op(), but acts only as
70
+ *                             a read barrier.
71
+ * void membar_read_atomic_setget() - like membar_atomic_setget() but acts only
72
+ *                            as a read barrier.
73
+ * void membar_write_atomic_op() - like membar_atomic_op(), but acts only as
74
+ *                            a write barrier.
75
+ * void membar_write_atomic_setget() - like membar_atomic_setget() but acts 
76
+ *                            only as a write barrier.
77
+ *
47 78
  *
48 79
  *  Note: - properly using memory barriers is tricky, in general try not to 
49 80
  *        depend on them. Locks include memory barriers, so you don't need
... ...
@@ -67,6 +104,10 @@
67 67
  *  int atomic_dec_and_test(atomic_t* v)     - returns 1 if the result is 0
68 68
  *  void atomic_or (atomic_t* v, int mask)   - v->val|=mask 
69 69
  *  void atomic_and(atomic_t* v, int mask)   - v->val&=mask
70
+ *  int atomic_add(atomic_t* v, int i)       - v->val+=i; return v->val
71
+ *  int atomic_cmpxchg(atomic_t* v, o, n)    - r=v->val; if (r==o) v->val=n;
72
+ *                                             return r (old value)
73
+ *
70 74
  * 
71 75
  * same ops, but with builtin memory barriers:
72 76
  *
... ...
@@ -79,6 +120,9 @@
79 79
  *  int mb_atomic_dec_and_test(atomic_t* v)  - returns 1 if the result is 0
80 80
  *  void mb_atomic_or(atomic_t* v, int mask - v->val|=mask 
81 81
  *  void mb_atomic_and(atomic_t* v, int mask)- v->val&=mask
82
+ *  int mb_atomic_add(atomic_t* v, int i)    - v->val+=i; return v->val
83
+ *  int mb_atomic_cmpxchg(atomic_t* v, o, n) - r=v->val; if (r==o) v->val=n;
84
+ *                                             return r (old value)
82 85
  *
83 86
  *  Same operations are available for int and long. The functions are named
84 87
  *   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