Merge pull request #727 from alesliehughes/master
[mono.git] / mono / utils / mono-membar.h
1 /*
2  * mono-membar.h: Memory barrier inline functions
3  *
4  * Author:
5  *      Mark Probst (mark.probst@gmail.com)
6  *
7  * (C) 2007 Novell, Inc
8  */
9
10 #ifndef _MONO_UTILS_MONO_MEMBAR_H_
11 #define _MONO_UTILS_MONO_MEMBAR_H_
12
13 #include <config.h>
14
15 #include <glib.h>
16
17 #ifdef _MSC_VER
18 #include <windows.h>
19 #include <intrin.h>
20
21 static inline void mono_memory_barrier (void)
22 {
23         /* NOTE: _ReadWriteBarrier and friends only prevent the
24            compiler from reordering loads and stores. To prevent
25            the CPU from doing the same, we have to use the
26            MemoryBarrier macro which expands to e.g. a serializing
27            XCHG instruction on x86. Also note that the MemoryBarrier
28            macro does *not* imply _ReadWriteBarrier, so that call
29            cannot be eliminated. */
30         _ReadWriteBarrier ();
31         MemoryBarrier ();
32 }
33
34 static inline void mono_memory_read_barrier (void)
35 {
36         _ReadBarrier ();
37         MemoryBarrier ();
38 }
39
40 static inline void mono_memory_write_barrier (void)
41 {
42         _WriteBarrier ();
43         MemoryBarrier ();
44 }
45 #elif defined(__WIN32__) || defined(_WIN32)
46 #include <windows.h>
47
48 /* Since we only support GCC 3.x in Cygwin for
49    some arcane reason, we have to use inline
50    assembly to get fences (__sync_synchronize
51    is not available). */
52
53 static inline void mono_memory_barrier (void)
54 {
55         __asm__ __volatile__ (
56                 "lock\n\t"
57                 "addl\t$0,0(%%esp)\n\t"
58                 :
59                 :
60                 : "memory"
61         );
62 }
63
64 static inline void mono_memory_read_barrier (void)
65 {
66         mono_memory_barrier ();
67 }
68
69 static inline void mono_memory_write_barrier (void)
70 {
71         mono_memory_barrier ();
72 }
73 #elif defined(USE_GCC_ATOMIC_OPS)
74 static inline void mono_memory_barrier (void)
75 {
76         __sync_synchronize ();
77 }
78
79 static inline void mono_memory_read_barrier (void)
80 {
81         mono_memory_barrier ();
82 }
83
84 static inline void mono_memory_write_barrier (void)
85 {
86         mono_memory_barrier ();
87 }
88 #elif defined(sparc) || defined(__sparc__)
89 static inline void mono_memory_barrier (void)
90 {
91         __asm__ __volatile__ ("membar   #LoadLoad | #LoadStore | #StoreStore | #StoreLoad" : : : "memory");
92 }
93
94 static inline void mono_memory_read_barrier (void)
95 {
96         __asm__ __volatile__ ("membar   #LoadLoad" : : : "memory");
97 }
98
99 static inline void mono_memory_write_barrier (void)
100 {
101         __asm__ __volatile__ ("membar   #StoreStore" : : : "memory");
102 }
103 #elif defined(__s390__)
104 static inline void mono_memory_barrier (void)
105 {
106         __asm__ __volatile__ ("bcr 15,0" : : : "memory");
107 }
108
109 static inline void mono_memory_read_barrier (void)
110 {
111         mono_memory_barrier ();
112 }
113
114 static inline void mono_memory_write_barrier (void)
115 {
116         mono_memory_barrier ();
117 }
118 #elif defined(__ia64__)
119 static inline void mono_memory_barrier (void)
120 {
121         __asm__ __volatile__ ("mf" : : : "memory");
122 }
123
124 static inline void mono_memory_read_barrier (void)
125 {
126         mono_memory_barrier ();
127 }
128
129 static inline void mono_memory_write_barrier (void)
130 {
131         mono_memory_barrier ();
132 }
133 #elif defined(MONO_CROSS_COMPILE)
134 static inline void mono_memory_barrier (void)
135 {
136 }
137
138 static inline void mono_memory_read_barrier (void)
139 {
140 }
141
142 static inline void mono_memory_write_barrier (void)
143 {
144 }
145 #endif
146
147 #endif  /* _MONO_UTILS_MONO_MEMBAR_H_ */