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