[2019-12] [threads] Add back mono_threads_attach_tools_thread as a public API (#18074)
[mono-project.git] / mono / utils / checked-build.h
blob537f47b17939cee5b4e7b2c325f10ab391f72486
1 /**
2 * \file
3 * Expensive asserts used when mono is built with --with-checked-build=yes
5 * Author:
6 * Rodrigo Kumpera (kumpera@gmail.com)
8 * (C) 2015 Xamarin
9 */
11 #ifndef __CHECKED_BUILD_H__
12 #define __CHECKED_BUILD_H__
14 #include <config.h>
15 #include <mono/utils/atomic.h>
16 #include <mono/utils/mono-compiler.h>
17 #include <mono/utils/mono-publib.h>
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;
28 G_ENUM_FUNCTIONS (MonoCheckMode)
30 mono_bool mono_check_mode_enabled (MonoCheckMode query);
32 // This is for metadata writes which we have chosen not to check at the current time.
33 // Because in principle this should never happen, we still use a macro so that the exemptions will be easier to find, and remove, later.
34 // The current reason why this is needed is for pointers to constant strings, which the checker cannot verify yet.
35 #define CHECKED_METADATA_WRITE_PTR_EXEMPT(ptr, val) do { (ptr) = (val); } while (0)
37 #ifdef ENABLE_CHECKED_BUILD
39 #define g_assert_checked g_assert
42 This can be called by embedders
44 #define MONO_REQ_API_ENTRYPOINT
47 The JIT will generate code that will land on this function
49 #define MONO_REQ_RUNTIME_ENTRYPOINT
51 #define CHECKED_MONO_INIT() do { checked_build_init (); } while (0)
53 void checked_build_init (void);
55 #else
57 #define g_assert_checked(...)
59 #define MONO_REQ_API_ENTRYPOINT
60 #define MONO_REQ_RUNTIME_ENTRYPOINT
62 #define CHECKED_MONO_INIT()
64 #endif /* ENABLE_CHECKED_BUILD */
66 #ifdef ENABLE_CHECKED_BUILD_GC
68 GC runtime modes rules:
70 - GC Safe
71 Can:
72 Call into foreigh functions.
73 Call GC Safe or Neutral modes functions.
74 Read from pinned managed memory.
76 Cannot:
77 Touch managed memory (read/write).
78 Be dettached.
80 What's good for?
81 Doing blocking calls.
83 - GC Unsafe
84 Can:
85 Touch managed memory (read/write).
86 Call GC Unsafe or Neutral modes functions.
88 Cannot:
89 Call foreign native code (embedder callbacks, pinvokes, etc)
90 Call into any Blocking functions/syscalls (mutexes, IO, etc)
91 Be dettached.
93 What's good for?
94 Poking into managed memory.
96 -- GC Neutral
97 Can:
98 Call other GC Neutral mode functions.
100 Cannot:
101 Touch managed memory.
102 Call foreign native code (embedder callbacks, pinvokes, etc)
103 Call into any Blocking functions/syscalls (mutexes, IO, etc)
104 Be dettached.
106 What's good for?
107 Functions that can be called from both coop or preept modes.
111 #define MONO_REQ_GC_SAFE_MODE do { \
112 assert_gc_safe_mode (__FILE__, __LINE__); \
113 } while (0);
115 #define MONO_REQ_GC_UNSAFE_MODE do { \
116 assert_gc_unsafe_mode (__FILE__, __LINE__); \
117 } while (0);
119 #define MONO_REQ_GC_NEUTRAL_MODE do { \
120 assert_gc_neutral_mode (__FILE__, __LINE__); \
121 } while (0);
123 /* In a GC critical region, the thread is not allowed to switch to GC safe mode.
124 * For example if the thread is about to call a method that will manipulate managed objects.
125 * The GC critical region must only occur in unsafe mode.
127 #define MONO_PREPARE_GC_CRITICAL_REGION \
128 MONO_REQ_GC_UNSAFE_MODE \
129 do { \
130 void* __critical_gc_region_cookie = critical_gc_region_begin()
132 #define MONO_FINISH_GC_CRITICAL_REGION \
133 critical_gc_region_end(__critical_gc_region_cookie); \
134 } while(0)
136 /* Verify that the thread is not currently in a GC critical region. */
137 #define MONO_REQ_GC_NOT_CRITICAL do { \
138 assert_not_in_gc_critical_region(); \
139 } while(0)
141 /* Verify that the thread is currently in a GC critical region. */
142 #define MONO_REQ_GC_CRITICAL do { \
143 assert_in_gc_critical_region(); \
144 } while(0)
146 void assert_gc_safe_mode (const char *file, int lineno);
147 void assert_gc_unsafe_mode (const char *file, int lineno);
148 void assert_gc_neutral_mode (const char *file, int lineno);
150 void* critical_gc_region_begin(void);
151 void critical_gc_region_end(void* token);
152 void assert_not_in_gc_critical_region(void);
153 void assert_in_gc_critical_region (void);
155 #else
157 #define MONO_REQ_GC_SAFE_MODE
158 #define MONO_REQ_GC_UNSAFE_MODE
159 #define MONO_REQ_GC_NEUTRAL_MODE
161 #define MONO_PREPARE_GC_CRITICAL_REGION
162 #define MONO_FINISH_GC_CRITICAL_REGION
164 #define MONO_REQ_GC_NOT_CRITICAL
165 #define MONO_REQ_GC_CRITICAL
167 #endif /* defined(ENABLE_CHECKED_BUILD_GC) */
169 #ifdef ENABLE_CHECKED_BUILD_METADATA
171 // Use when writing a pointer from one image or imageset to another.
172 #define CHECKED_METADATA_WRITE_PTR(ptr, val) do { \
173 check_metadata_store (&(ptr), (val)); \
174 (ptr) = (val); \
175 } while (0);
177 // Use when writing a pointer from an image or imageset to itself.
178 #define CHECKED_METADATA_WRITE_PTR_LOCAL(ptr, val) do { \
179 check_metadata_store_local (&(ptr), (val)); \
180 (ptr) = (val); \
181 } while (0);
183 // Use when writing a pointer from one image or imageset to another (atomic version).
184 #define CHECKED_METADATA_WRITE_PTR_ATOMIC(ptr, val) do { \
185 check_metadata_store (&(ptr), (val)); \
186 mono_atomic_store_release (&(ptr), (val)); \
187 } while (0);
189 void check_metadata_store(void *from, void *to);
190 void check_metadata_store_local(void *from, void *to);
192 #define CHECKED_METADATA_STORE(ptr, val) check_metadata_store ((ptr), (val))
193 #define CHECKED_METADATA_STORE_LOCAL(ptr, val) check_metadata_store_local ((ptr), (val))
195 #else
197 #define CHECKED_METADATA_WRITE_PTR(ptr, val) do { (ptr) = (val); } while (0)
198 #define CHECKED_METADATA_WRITE_PTR_LOCAL(ptr, val) do { (ptr) = (val); } while (0)
199 #define CHECKED_METADATA_WRITE_PTR_ATOMIC(ptr, val) do { mono_atomic_store_release (&(ptr), (val)); } while (0)
201 #define CHECKED_METADATA_STORE(ptr, val) do { (ptr); (val); } while (0)
202 #define CHECKED_METADATA_STORE_LOCAL(ptr, val) do { (ptr); (val); } while (0)
204 #endif /* defined(ENABLE_CHECKED_BUILD_METADATA) */
206 #ifdef ENABLE_CHECKED_BUILD_THREAD
208 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta) do { \
209 checked_build_thread_transition (transition, info, from_state, suspend_count, next_state, suspend_count_delta, TRUE); \
210 } while (0)
212 #define CHECKED_BUILD_THREAD_TRANSITION_NOBT(transition, info, from_state, suspend_count, next_state, suspend_count_delta) do { \
213 checked_build_thread_transition (transition, info, from_state, suspend_count, next_state, suspend_count_delta, FALSE); \
214 } while (0)
216 void checked_build_thread_transition(const char *transition, void *info, int from_state, int suspend_count, int next_state, int suspend_count_delta, gboolean capture_backtrace);
218 G_GNUC_NORETURN MONO_ATTR_FORMAT_PRINTF(1,2) void mono_fatal_with_history(const char *msg, ...);
220 #else
222 #define CHECKED_BUILD_THREAD_TRANSITION(transition, info, from_state, suspend_count, next_state, suspend_count_delta)
224 #define CHECKED_BUILD_THREAD_TRANSITION_NOBT(transition, info, from_state, suspend_count, next_state, suspend_count_delta)
226 #define mono_fatal_with_history g_error
228 #endif /* defined(ENABLE_CHECKED_BUILD_THREAD) */
230 #endif /* __CHECKED_BUILD_H__ */