Merge pull request #2362 from ludovic-henry/fix-process-missedoutput
[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 #ifdef CHECKED_BUILD
22
23 #define g_assert_checked g_assert
24
25 /*
26 GC runtime modes rules:
27
28 - GC Safe
29 Can:
30 Call into foreigh functions.
31 Call GC Safe or Neutral modes functions.
32 Read from pinned managed memory.
33
34 Cannot:
35 Touch managed memory (read/write).
36 Be dettached.
37
38 What's good for?
39 Doing blocking calls.
40
41 - GC Unsafe
42 Can:
43 Touch managed memory (read/write).
44 Call GC Unsafe or Neutral modes functions.
45
46 Cannot:
47 Call foreign native code (embedder callbacks, pinvokes, etc)
48 Call into any Blocking functions/syscalls (mutexes, IO, etc)
49 Be dettached.
50
51 What's good for?
52 Poking into managed memory.
53
54 -- GC Neutral
55 Can:
56 Call other GC Neutral mode functions.
57
58 Cannot:
59 Touch managed memory.
60 Call foreign native code (embedder callbacks, pinvokes, etc)
61 Call into any Blocking functions/syscalls (mutexes, IO, etc)
62 Be dettached.
63
64 What's good for?
65 Functions that can be called from both coop or preept modes.
66
67 */
68
69 #define MONO_REQ_GC_SAFE_MODE do {      \
70         assert_gc_safe_mode (); \
71 } while (0);
72
73 #define MONO_REQ_GC_UNSAFE_MODE do {    \
74         assert_gc_unsafe_mode ();       \
75 } while (0);
76
77 #define MONO_REQ_GC_NEUTRAL_MODE do {   \
78         assert_gc_neutral_mode ();      \
79 } while (0);
80
81 /* In a GC critical region, the thread is not allowed to switch to GC safe mode.
82  * For example if the thread is about to call a method that will manipulate managed objects.
83  * The GC critical region must only occur in unsafe mode.
84  */
85 #define MONO_PREPARE_GC_CRITICAL_REGION                                 \
86         MONO_REQ_GC_UNSAFE_MODE                                         \
87         do {                                                            \
88                 void* __critical_gc_region_cookie = critical_gc_region_begin()
89
90 #define MONO_FINISH_GC_CRITICAL_REGION                  \
91                 critical_gc_region_end(__critical_gc_region_cookie);    \
92         } while(0)
93
94 /* Verify that the thread is not currently in a GC critical region. */
95 #define MONO_REQ_GC_NOT_CRITICAL do {                   \
96                 assert_not_in_gc_critical_region();     \
97         } while(0)
98
99 /* Verify that the thread is currently in a GC critical region. */
100 #define MONO_REQ_GC_CRITICAL do {                       \
101                 assert_in_gc_critical_region(); \
102         } while(0)
103
104 // Use when writing a pointer from one image or imageset to another.
105 #define CHECKED_METADATA_WRITE_PTR(ptr, val) do {    \
106     check_metadata_store (&(ptr), (val));    \
107     (ptr) = (val);    \
108 } while (0);
109
110 // Use when writing a pointer from an image or imageset to itself.
111 #define CHECKED_METADATA_WRITE_PTR_LOCAL(ptr, val) do {    \
112     check_metadata_store_local (&(ptr), (val));    \
113     (ptr) = (val);    \
114 } while (0);
115
116 // Use when writing a pointer from one image or imageset to another (atomic version).
117 #define CHECKED_METADATA_WRITE_PTR_ATOMIC(ptr, val) do {    \
118     check_metadata_store (&(ptr), (val));    \
119     mono_atomic_store_release (&(ptr), (val));    \
120 } while (0);
121
122 /*
123 This can be called by embedders
124 */
125 #define MONO_REQ_API_ENTRYPOINT
126
127 /*
128 The JIT will generate code that will land on this function
129 */
130 #define MONO_REQ_RUNTIME_ENTRYPOINT
131
132 #define CHECKED_MONO_INIT() do { checked_build_init (); } while (0)
133
134 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta) do {      \
135         checked_build_thread_transition (transition, info, from_state, suspend_count, next_state, suspend_count_delta); \
136 } while (0)
137
138 void assert_gc_safe_mode (void);
139 void assert_gc_unsafe_mode (void);
140 void assert_gc_neutral_mode (void);
141
142 void* critical_gc_region_begin(void);
143 void critical_gc_region_end(void* token);
144 void assert_not_in_gc_critical_region(void);
145 void assert_in_gc_critical_region (void);
146
147 void checked_build_init (void);
148 void checked_build_thread_transition(const char *transition, void *info, int from_state, int suspend_count, int next_state, int suspend_count_delta);
149
150 void check_metadata_store(void *from, void *to);
151 void check_metadata_store_local(void *from, void *to);
152
153 #else
154
155 #define g_assert_checked(...)
156
157 #define MONO_REQ_GC_SAFE_MODE
158 #define MONO_REQ_GC_UNSAFE_MODE
159 #define MONO_REQ_GC_NEUTRAL_MODE
160 #define MONO_REQ_API_ENTRYPOINT
161 #define MONO_REQ_RUNTIME_ENTRYPOINT
162
163 #define MONO_PREPARE_GC_CRITICAL_REGION
164 #define MONO_FINISH_GC_CRITICAL_REGION
165
166 #define MONO_REQ_GC_NOT_CRITICAL
167 #define MONO_REQ_GC_CRITICAL
168
169
170 #define CHECKED_MONO_INIT()
171 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta)
172
173 #define CHECKED_METADATA_WRITE_PTR(ptr, val) do { (ptr) = (val); } while (0)
174 #define CHECKED_METADATA_WRITE_PTR_LOCAL(ptr, val) do { (ptr) = (val); } while (0)
175 #define CHECKED_METADATA_WRITE_PTR_ATOMIC(ptr, val) do { mono_atomic_store_release (&(ptr), (val)); } while (0)
176
177 #endif /* CHECKED_BUILD */
178
179 #endif