Remove extraneous () in macro definition.
[mono.git] / mono / utils / mono-memory-model.h
1 /*
2  * mono-memory-model.h: Mapping of the arch memory model.
3  *
4  * Author:
5  *      Rodrigo Kumpera (kumpera@gmail.com)
6  *
7  * (C) 2011 Xamarin, Inc
8  */
9
10 #ifndef _MONO_UTILS_MONO_MEMMODEL_H_
11 #define _MONO_UTILS_MONO_MEMMODEL_H_
12
13 #include <config.h>
14 #include <mono/utils/mono-membar.h>
15
16 /*
17 In order to allow for fast concurrent code, we must use fencing to properly order
18 memory access - specially on arch with weaker memory models such as ARM or PPC.
19
20 On the other hand, we can't use arm's weak model on targets such as x86 that have
21 a stronger model that requires much much less fencing.
22
23 The idea of exposing each arch memory model is to avoid fencing whenever possible
24 but at the same time make all required ordering explicit. 
25
26 There are four kinds of barriers, LoadLoad, LoadStore, StoreLoad and StoreStore.
27 Each arch must define which ones needs fencing.
28
29 We assume 3 kinds of barriers are available: load, store and memory (load+store).
30
31 TODO: Add support for weaker forms of CAS such as present on ARM.
32 TODO: replace all explicit uses of memory barriers with macros from this section. This will make a nicer read of lazy init code.
33 TODO: if we find places where a data depencency could replace barriers, add macros here to help with it
34 TODO: some arch with strong consistency, such as x86, support weaker access. We might need to expose more kinds of barriers once we exploit this.
35 */
36
37 #define MEMORY_BARRIER mono_memory_barrier ()
38 #define LOAD_BARRIER mono_memory_read_barrier ()
39 #define STORE_BARRIER mono_memory_write_barrier ()
40
41 enum {
42         StoreStoreBarrier,
43         LoadLoadBarrier,
44         StoreLoadBarrier,
45         LoadStoreBarrier,
46         FullBarrier
47 };
48
49 #if defined(__i386__) || defined(__x86_64__)
50 /*
51 Both x86 and amd64 follow the SPO memory model:
52 -Loads are not reordered with other loads
53 -Stores are not reordered with others stores
54 -Stores are not reordered with earlier loads
55 */
56
57 /*Neither sfence or mfence provide the required semantics here*/
58 #define STORE_LOAD_FENCE MEMORY_BARRIER
59
60 #define LOAD_RELEASE_FENCE MEMORY_BARRIER
61 #define STORE_ACQUIRE_FENCE MEMORY_BARRIER
62
63 #elif defined(__arm__)
64 /*
65 ARM memory model is as weak as it can get. the only guarantee are data dependent
66 accesses.
67 LoadStore fences are much better handled using a data depencency such as:
68 load x;  if (x = x) store y;
69
70 This trick can be applied to other fences such as LoadLoad, but require some assembly:
71
72 LDR R0, [R1]
73 AND R0, R0, #0
74 LDR R3, [R4, R0]
75 */
76
77 #define STORE_STORE_FENCE STORE_BARRIER
78 #define LOAD_LOAD_FENCE LOAD_BARRIER
79 #define STORE_LOAD_FENCE MEMORY_BARRIER
80 #define STORE_ACQUIRE_FENCE MEMORY_BARRIER
81 #define STORE_RELEASE_FENCE MEMORY_BARRIER
82 #define LOAD_ACQUIRE_FENCE MEMORY_BARRIER
83 #define LOAD_RELEASE_FENCE MEMORY_BARRIER
84
85 #elif defined(__s390x__)
86
87 #define STORE_STORE_FENCE do {} while (0)
88 #define LOAD_LOAD_FENCE  do {} while (0)
89 #define STORE_LOAD_FENCE do {} while (0)
90 #define LOAD_STORE_FENCE do {} while (0)
91 #define STORE_RELEASE_FENCE do {} while (0)
92
93 #else
94
95 /*default implementation with the weakest possible memory model */
96 #define STORE_STORE_FENCE STORE_BARRIER
97 #define LOAD_LOAD_FENCE LOAD_BARRIER
98 #define STORE_LOAD_FENCE MEMORY_BARRIER
99 #define LOAD_STORE_FENCE MEMORY_BARRIER
100 #define STORE_ACQUIRE_FENCE MEMORY_BARRIER
101 #define STORE_RELEASE_FENCE MEMORY_BARRIER
102 #define LOAD_ACQUIRE_FENCE MEMORY_BARRIER
103 #define LOAD_RELEASE_FENCE MEMORY_BARRIER
104
105 #endif
106
107 #ifndef STORE_STORE_FENCE
108 #define STORE_STORE_FENCE
109 #endif 
110
111 #ifndef LOAD_LOAD_FENCE
112 #define LOAD_LOAD_FENCE
113 #endif 
114
115 #ifndef STORE_LOAD_FENCE
116 #define STORE_LOAD_FENCE
117 #endif 
118
119 #ifndef LOAD_STORE_FENCE
120 #define LOAD_STORE_FENCE
121 #endif 
122
123 #ifndef STORE_RELEASE_FENCE
124 #define STORE_RELEASE_FENCE
125 #endif
126
127 #ifndef LOAD_RELEASE_FENCE
128 #define LOAD_RELEASE_FENCE
129 #endif
130
131 #ifndef STORE_ACQUIRE_FENCE
132 #define STORE_ACQUIRE_FENCE
133 #endif
134
135 #ifndef LOAD_ACQUIRE_FENCE
136 #define LOAD_ACQUIRE_FENCE
137 #endif
138
139
140 /*Makes sure all previous stores as visible before */
141 #define mono_atomic_store_seq(target,value) do {        \
142         STORE_STORE_FENCE;      \
143         *(target) = (value);    \
144 } while (0)
145
146
147 /*
148 Acquire/release semantics macros.
149 */
150 #define mono_atomic_store_release(target,value) do {    \
151         STORE_RELEASE_FENCE;    \
152         *(target) = (value);    \
153 } while (0)
154
155 #define mono_atomic_load_release(target) ({     \
156         typeof (*target) __tmp; \
157         LOAD_RELEASE_FENCE;     \
158         __tmp = *target;        \
159         __tmp; })
160
161 #define mono_atomic_load_acquire(target) ({     \
162         typeof (*target) __tmp = *target;       \
163         LOAD_ACQUIRE_FENCE;     \
164         __tmp; })
165
166 #define mono_atomic_store_acquire(target,value) {       \
167         *target = value;        \
168         STORE_ACQUIRE_FENCE;    \
169         }
170
171 #endif /* _MONO_UTILS_MONO_MEMMODEL_H_ */