[runtime] Fix DISABLE_REFLECTION_EMIT build.
[mono.git] / mono / utils / checked-build.h
1 /**
2  * \file
3  * Expensive asserts used when mono is built with --with-checked-build=yes
4  *
5  * Author:
6  *      Rodrigo Kumpera (kumpera@gmail.com)
7  *
8  * (C) 2015 Xamarin
9  */
10
11 #ifndef __CHECKED_BUILD_H__
12 #define __CHECKED_BUILD_H__
13
14 #include <config.h>
15 #include <mono/utils/atomic.h>
16 #include <mono/utils/mono-compiler.h>
17 #include <mono/utils/mono-publib.h>
18
19 typedef enum {
20         MONO_CHECK_MODE_NONE = 0,
21         MONO_CHECK_MODE_GC = 0x1,
22         MONO_CHECK_MODE_METADATA = 0x2,
23         MONO_CHECK_MODE_THREAD = 0x4,
24         MONO_CHECK_MODE_ALL = MONO_CHECK_MODE_GC | MONO_CHECK_MODE_METADATA | MONO_CHECK_MODE_THREAD,
25         MONO_CHECK_MODE_UNKNOWN = 0x8
26 } MonoCheckMode;
27
28 mono_bool mono_check_mode_enabled (MonoCheckMode query);
29
30 // This is for metadata writes which we have chosen not to check at the current time.
31 // Because in principle this should never happen, we still use a macro so that the exemptions will be easier to find, and remove, later.
32 // The current reason why this is needed is for pointers to constant strings, which the checker cannot verify yet.
33 #define CHECKED_METADATA_WRITE_PTR_EXEMPT(ptr, val) do { (ptr) = (val); } while (0)
34
35 #ifdef ENABLE_CHECKED_BUILD
36
37 #define g_assert_checked g_assert
38
39 /*
40 This can be called by embedders
41 */
42 #define MONO_REQ_API_ENTRYPOINT
43
44 /*
45 The JIT will generate code that will land on this function
46 */
47 #define MONO_REQ_RUNTIME_ENTRYPOINT
48
49 #define CHECKED_MONO_INIT() do { checked_build_init (); } while (0)
50
51 void checked_build_init (void);
52
53 #else
54
55 #define g_assert_checked(...)
56
57 #define MONO_REQ_API_ENTRYPOINT
58 #define MONO_REQ_RUNTIME_ENTRYPOINT
59
60 #define CHECKED_MONO_INIT()
61
62 #endif /* ENABLE_CHECKED_BUILD */
63
64 #ifdef ENABLE_CHECKED_BUILD_GC
65 /*
66 GC runtime modes rules:
67
68 - GC Safe
69 Can:
70 Call into foreigh functions.
71 Call GC Safe or Neutral modes functions.
72 Read from pinned managed memory.
73
74 Cannot:
75 Touch managed memory (read/write).
76 Be dettached.
77
78 What's good for?
79 Doing blocking calls.
80
81 - GC Unsafe
82 Can:
83 Touch managed memory (read/write).
84 Call GC Unsafe or Neutral modes functions.
85
86 Cannot:
87 Call foreign native code (embedder callbacks, pinvokes, etc)
88 Call into any Blocking functions/syscalls (mutexes, IO, etc)
89 Be dettached.
90
91 What's good for?
92 Poking into managed memory.
93
94 -- GC Neutral
95 Can:
96 Call other GC Neutral mode functions.
97
98 Cannot:
99 Touch managed memory.
100 Call foreign native code (embedder callbacks, pinvokes, etc)
101 Call into any Blocking functions/syscalls (mutexes, IO, etc)
102 Be dettached.
103
104 What's good for?
105 Functions that can be called from both coop or preept modes.
106
107 */
108
109 #define MONO_REQ_GC_SAFE_MODE do {      \
110         assert_gc_safe_mode (__FILE__, __LINE__);       \
111 } while (0);
112
113 #define MONO_REQ_GC_UNSAFE_MODE do {    \
114         assert_gc_unsafe_mode (__FILE__, __LINE__);     \
115 } while (0);
116
117 #define MONO_REQ_GC_NEUTRAL_MODE do {   \
118         assert_gc_neutral_mode (__FILE__, __LINE__);    \
119 } while (0);
120
121 /* In a GC critical region, the thread is not allowed to switch to GC safe mode.
122  * For example if the thread is about to call a method that will manipulate managed objects.
123  * The GC critical region must only occur in unsafe mode.
124  */
125 #define MONO_PREPARE_GC_CRITICAL_REGION                                 \
126         MONO_REQ_GC_UNSAFE_MODE                                         \
127         do {                                                            \
128                 void* __critical_gc_region_cookie = critical_gc_region_begin()
129
130 #define MONO_FINISH_GC_CRITICAL_REGION                  \
131                 critical_gc_region_end(__critical_gc_region_cookie);    \
132         } while(0)
133
134 /* Verify that the thread is not currently in a GC critical region. */
135 #define MONO_REQ_GC_NOT_CRITICAL do {                   \
136                 assert_not_in_gc_critical_region();     \
137         } while(0)
138
139 /* Verify that the thread is currently in a GC critical region. */
140 #define MONO_REQ_GC_CRITICAL do {                       \
141                 assert_in_gc_critical_region(); \
142         } while(0)
143
144 void assert_gc_safe_mode (const char *file, int lineno);
145 void assert_gc_unsafe_mode (const char *file, int lineno);
146 void assert_gc_neutral_mode (const char *file, int lineno);
147
148 void* critical_gc_region_begin(void);
149 void critical_gc_region_end(void* token);
150 void assert_not_in_gc_critical_region(void);
151 void assert_in_gc_critical_region (void);
152
153 #else
154
155 #define MONO_REQ_GC_SAFE_MODE
156 #define MONO_REQ_GC_UNSAFE_MODE
157 #define MONO_REQ_GC_NEUTRAL_MODE
158
159 #define MONO_PREPARE_GC_CRITICAL_REGION
160 #define MONO_FINISH_GC_CRITICAL_REGION
161
162 #define MONO_REQ_GC_NOT_CRITICAL
163 #define MONO_REQ_GC_CRITICAL
164
165 #endif /* defined(ENABLE_CHECKED_BUILD_GC) */
166
167 #ifdef ENABLE_CHECKED_BUILD_METADATA
168
169 // Use when writing a pointer from one image or imageset to another.
170 #define CHECKED_METADATA_WRITE_PTR(ptr, val) do {    \
171     check_metadata_store (&(ptr), (val));    \
172     (ptr) = (val);    \
173 } while (0);
174
175 // Use when writing a pointer from an image or imageset to itself.
176 #define CHECKED_METADATA_WRITE_PTR_LOCAL(ptr, val) do {    \
177     check_metadata_store_local (&(ptr), (val));    \
178     (ptr) = (val);    \
179 } while (0);
180
181 // Use when writing a pointer from one image or imageset to another (atomic version).
182 #define CHECKED_METADATA_WRITE_PTR_ATOMIC(ptr, val) do {    \
183     check_metadata_store (&(ptr), (val));    \
184     mono_atomic_store_release (&(ptr), (val));    \
185 } while (0);
186
187 void check_metadata_store(void *from, void *to);
188 void check_metadata_store_local(void *from, void *to);
189
190 #define CHECKED_METADATA_STORE(ptr, val) check_metadata_store ((ptr), (val))
191 #define CHECKED_METADATA_STORE_LOCAL(ptr, val) check_metadata_store_local ((ptr), (val))
192
193 #else
194
195 #define CHECKED_METADATA_WRITE_PTR(ptr, val) do { (ptr) = (val); } while (0)
196 #define CHECKED_METADATA_WRITE_PTR_LOCAL(ptr, val) do { (ptr) = (val); } while (0)
197 #define CHECKED_METADATA_WRITE_PTR_ATOMIC(ptr, val) do { mono_atomic_store_release (&(ptr), (val)); } while (0)
198
199 #define CHECKED_METADATA_STORE(ptr, val) do { (ptr); (val); } while (0)
200 #define CHECKED_METADATA_STORE_LOCAL(ptr, val) do { (ptr); (val); } while (0)
201
202 #endif /* defined(ENABLE_CHECKED_BUILD_METADATA) */
203
204 #ifdef ENABLE_CHECKED_BUILD_THREAD
205
206 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta) do {      \
207         checked_build_thread_transition (transition, info, from_state, suspend_count, next_state, suspend_count_delta); \
208 } while (0)
209
210 void checked_build_thread_transition(const char *transition, void *info, int from_state, int suspend_count, int next_state, int suspend_count_delta);
211
212 G_GNUC_NORETURN MONO_ATTR_FORMAT_PRINTF(1,2) void mono_fatal_with_history(const char *msg, ...);
213
214 #else
215
216 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta)
217
218 #define mono_fatal_with_history g_error
219
220 #endif /* defined(ENABLE_CHECKED_BUILD_THREAD) */
221
222 #endif /* __CHECKED_BUILD_H__ */