Add an #else -> #error path to mono-membar.h.
[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 #ifndef WIN32_LEAN_AND_MEAN
19 #define WIN32_LEAN_AND_MEAN
20 #endif
21 #include <windows.h>
22 #include <intrin.h>
23
24 static inline void mono_memory_barrier (void)
25 {
26         /* NOTE: _ReadWriteBarrier and friends only prevent the
27            compiler from reordering loads and stores. To prevent
28            the CPU from doing the same, we have to use the
29            MemoryBarrier macro which expands to e.g. a serializing
30            XCHG instruction on x86. Also note that the MemoryBarrier
31            macro does *not* imply _ReadWriteBarrier, so that call
32            cannot be eliminated. */
33         _ReadWriteBarrier ();
34         MemoryBarrier ();
35 }
36
37 static inline void mono_memory_read_barrier (void)
38 {
39         _ReadBarrier ();
40         MemoryBarrier ();
41 }
42
43 static inline void mono_memory_write_barrier (void)
44 {
45         _WriteBarrier ();
46         MemoryBarrier ();
47 }
48 #elif defined(__WIN32__) || defined(_WIN32)
49 #include <windows.h>
50
51 /* Since we only support GCC 3.x in Cygwin for
52    some arcane reason, we have to use inline
53    assembly to get fences (__sync_synchronize
54    is not available). */
55
56 static inline void mono_memory_barrier (void)
57 {
58         __asm__ __volatile__ (
59                 "lock\n\t"
60                 "addl\t$0,0(%%esp)\n\t"
61                 :
62                 :
63                 : "memory"
64         );
65 }
66
67 static inline void mono_memory_read_barrier (void)
68 {
69         mono_memory_barrier ();
70 }
71
72 static inline void mono_memory_write_barrier (void)
73 {
74         mono_memory_barrier ();
75 }
76 #elif defined(USE_GCC_ATOMIC_OPS)
77 static inline void mono_memory_barrier (void)
78 {
79         __sync_synchronize ();
80 }
81
82 static inline void mono_memory_read_barrier (void)
83 {
84         mono_memory_barrier ();
85 }
86
87 static inline void mono_memory_write_barrier (void)
88 {
89         mono_memory_barrier ();
90 }
91 #elif defined(sparc) || defined(__sparc__)
92 static inline void mono_memory_barrier (void)
93 {
94         __asm__ __volatile__ ("membar   #LoadLoad | #LoadStore | #StoreStore | #StoreLoad" : : : "memory");
95 }
96
97 static inline void mono_memory_read_barrier (void)
98 {
99         __asm__ __volatile__ ("membar   #LoadLoad" : : : "memory");
100 }
101
102 static inline void mono_memory_write_barrier (void)
103 {
104         __asm__ __volatile__ ("membar   #StoreStore" : : : "memory");
105 }
106 #elif defined(__s390__)
107 static inline void mono_memory_barrier (void)
108 {
109         __asm__ __volatile__ ("bcr 15,0" : : : "memory");
110 }
111
112 static inline void mono_memory_read_barrier (void)
113 {
114         mono_memory_barrier ();
115 }
116
117 static inline void mono_memory_write_barrier (void)
118 {
119         mono_memory_barrier ();
120 }
121 #elif defined(__ia64__)
122 static inline void mono_memory_barrier (void)
123 {
124         __asm__ __volatile__ ("mf" : : : "memory");
125 }
126
127 static inline void mono_memory_read_barrier (void)
128 {
129         mono_memory_barrier ();
130 }
131
132 static inline void mono_memory_write_barrier (void)
133 {
134         mono_memory_barrier ();
135 }
136 #elif defined(MONO_CROSS_COMPILE)
137 static inline void mono_memory_barrier (void)
138 {
139 }
140
141 static inline void mono_memory_read_barrier (void)
142 {
143 }
144
145 static inline void mono_memory_write_barrier (void)
146 {
147 }
148 #else
149 #error "Don't know how to do memory barriers!"
150 #endif
151
152 #endif  /* _MONO_UTILS_MONO_MEMBAR_H_ */