[sgen] Make sure we don't sweep a block if we're not supposed to
[mono.git] / mono / utils / mono-memory-model.h
index 8bedf0681398a774825eee2b747ceb4f08c736fa..fbb87cff574175996469db0a1ac3b10586a4fcef 100644 (file)
@@ -34,18 +34,20 @@ TODO: if we find places where a data depencency could replace barriers, add macr
 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.
 */
 
-#define MEMORY_BARRIER mono_memory_barrier
-#define LOAD_BARRIER mono_memory_read_barrier
-#define STORE_BARRIEE mono_memory_write_barrier
-
+/*
+ * Keep in sync with the enum in mini/mini-llvm-cpp.h.
+ */
 enum {
-       StoreStoreBarrier,
-       LoadLoadBarrier,
-       StoreLoadBarrier,
-       LoadStoreBarrier,
-       FullBarrier
+    MONO_MEMORY_BARRIER_NONE = 0,
+    MONO_MEMORY_BARRIER_ACQ = 1,
+    MONO_MEMORY_BARRIER_REL = 2,
+    MONO_MEMORY_BARRIER_SEQ = 3,
 };
 
+#define MEMORY_BARRIER mono_memory_barrier ()
+#define LOAD_BARRIER mono_memory_read_barrier ()
+#define STORE_BARRIER mono_memory_write_barrier ()
+
 #if defined(__i386__) || defined(__x86_64__)
 /*
 Both x86 and amd64 follow the SPO memory model:
@@ -57,6 +59,9 @@ Both x86 and amd64 follow the SPO memory model:
 /*Neither sfence or mfence provide the required semantics here*/
 #define STORE_LOAD_FENCE MEMORY_BARRIER
 
+#define LOAD_RELEASE_FENCE MEMORY_BARRIER
+#define STORE_ACQUIRE_FENCE MEMORY_BARRIER
+
 #elif defined(__arm__)
 /*
 ARM memory model is as weak as it can get. the only guarantee are data dependent
@@ -74,7 +79,18 @@ LDR R3, [R4, R0]
 #define STORE_STORE_FENCE STORE_BARRIER
 #define LOAD_LOAD_FENCE LOAD_BARRIER
 #define STORE_LOAD_FENCE MEMORY_BARRIER
-#define LOAD_STORE_FENCE MEMORY_BARRIER
+#define STORE_ACQUIRE_FENCE MEMORY_BARRIER
+#define STORE_RELEASE_FENCE MEMORY_BARRIER
+#define LOAD_ACQUIRE_FENCE MEMORY_BARRIER
+#define LOAD_RELEASE_FENCE MEMORY_BARRIER
+
+#elif defined(__s390x__)
+
+#define STORE_STORE_FENCE do {} while (0)
+#define LOAD_LOAD_FENCE  do {} while (0)
+#define STORE_LOAD_FENCE do {} while (0)
+#define LOAD_STORE_FENCE do {} while (0)
+#define STORE_RELEASE_FENCE do {} while (0)
 
 #else
 
@@ -83,6 +99,10 @@ LDR R3, [R4, R0]
 #define LOAD_LOAD_FENCE LOAD_BARRIER
 #define STORE_LOAD_FENCE MEMORY_BARRIER
 #define LOAD_STORE_FENCE MEMORY_BARRIER
+#define STORE_ACQUIRE_FENCE MEMORY_BARRIER
+#define STORE_RELEASE_FENCE MEMORY_BARRIER
+#define LOAD_ACQUIRE_FENCE MEMORY_BARRIER
+#define LOAD_RELEASE_FENCE MEMORY_BARRIER
 
 #endif
 
@@ -102,25 +122,53 @@ LDR R3, [R4, R0]
 #define LOAD_STORE_FENCE
 #endif 
 
-/*
-Acquire/release semantics macros.
+#ifndef STORE_RELEASE_FENCE
+#define STORE_RELEASE_FENCE
+#endif
 
-Acquire/release models what most code needs, which is to do load/store pairing of barriers
-from multiple threads.
-Release semantics makes sure all previous store have completed before the next memory access.
-Acquire semantics make sure all following loads won't execute before the previous one.
+#ifndef LOAD_RELEASE_FENCE
+#define LOAD_RELEASE_FENCE
+#endif
 
-This is a slightly harmless variantion on ECMA's that further constraints ordering amongs
-different kinds of access.
+#ifndef STORE_ACQUIRE_FENCE
+#define STORE_ACQUIRE_FENCE
+#endif
+
+#ifndef LOAD_ACQUIRE_FENCE
+#define LOAD_ACQUIRE_FENCE
+#endif
+
+
+/*Makes sure all previous stores as visible before */
+#define mono_atomic_store_seq(target,value) do {       \
+       STORE_STORE_FENCE;      \
+       *(target) = (value);    \
+} while (0)
+
+
+/*
+Acquire/release semantics macros.
 */
 #define mono_atomic_store_release(target,value) do {   \
-       STORE_STORE_FENCE;      \
+       STORE_RELEASE_FENCE;    \
        *(target) = (value);    \
 } while (0)
 
-#define mono_atomic_load_acquire(target) ({    \
-       typeof (*target) __tmp = *target;       \
-       LOAD_LOAD_FENCE;        \
+#define mono_atomic_load_release(_type,target) ({      \
+       _type __tmp;    \
+       LOAD_RELEASE_FENCE;     \
+       __tmp = *(target);      \
        __tmp; })
 
+#define mono_atomic_load_acquire(var,_type,target) do {        \
+       _type __tmp = *(target);        \
+       LOAD_ACQUIRE_FENCE;     \
+       (var) = __tmp; \
+} while (0)
+
+#define mono_atomic_store_acquire(target,value) {      \
+       *(target) = (value);    \
+       STORE_ACQUIRE_FENCE;    \
+       }
+
 #endif /* _MONO_UTILS_MONO_MEMMODEL_H_ */