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:
/*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
#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
#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
#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_ */