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