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