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