1 /** 2 * \file 3 * Internal GC interface 4 * 5 * Author: Paolo Molaro <lupus@ximian.com> 6 * 7 * (C) 2002 Ximian, Inc. 8 * Copyright 2012 Xamarin Inc (http://www.xamarin.com) 9 * Licensed under the MIT license. See LICENSE file in the project root for full license information. 10 */ 11 12 #ifndef __MONO_METADATA_GC_INTERNAL_H__ 13 #define __MONO_METADATA_GC_INTERNAL_H__ 14 15 #include <glib.h> 16 #include <mono/utils/gc_wrapper.h> 17 #include <mono/metadata/object-internals.h> 18 #include <mono/metadata/threads-types.h> 19 #include <mono/sgen/gc-internal-agnostic.h> 20 21 #define mono_domain_finalizers_lock(domain) mono_os_mutex_lock (&(domain)->finalizable_objects_hash_lock); 22 #define mono_domain_finalizers_unlock(domain) mono_os_mutex_unlock (&(domain)->finalizable_objects_hash_lock); 23 24 /* Register a memory area as a conservatively scanned GC root */ 25 #define MONO_GC_REGISTER_ROOT_PINNING(x,src,msg) mono_gc_register_root ((char*)&(x), sizeof(x), MONO_GC_DESCRIPTOR_NULL, (src), (msg)) 26 27 #define MONO_GC_UNREGISTER_ROOT(x) mono_gc_deregister_root ((char*)&(x)) 28 29 /* 30 * Return a GC descriptor for an array containing N pointers to memory allocated 31 * by mono_gc_alloc_fixed (). 32 */ 33 /* For SGEN, the result of alloc_fixed () is not GC tracked memory */ 34 #define MONO_GC_ROOT_DESCR_FOR_FIXED(n) (mono_gc_is_moving () ? mono_gc_make_root_descr_all_refs (0) : MONO_GC_DESCRIPTOR_NULL) 35 36 /* Register a memory location holding a single object reference as a GC root */ 37 #define MONO_GC_REGISTER_ROOT_SINGLE(x,src,msg) do { \ 38 g_assert (sizeof (x) == sizeof (MonoObject*)); \ 39 mono_gc_register_root ((char*)&(x), sizeof(MonoObject*), mono_gc_make_root_descr_all_refs (1), (src), (msg)); \ 40 } while (0) 41 42 /* 43 * This is used for fields which point to objects which are kept alive by other references 44 * when using Boehm. 45 */ 46 #define MONO_GC_REGISTER_ROOT_IF_MOVING(x,src,msg) do { \ 47 if (mono_gc_is_moving ()) \ 48 MONO_GC_REGISTER_ROOT_SINGLE(x,src,msg); \ 49 } while (0) 50 51 #define MONO_GC_UNREGISTER_ROOT_IF_MOVING(x) do { \ 52 if (mono_gc_is_moving ()) \ 53 MONO_GC_UNREGISTER_ROOT (x); \ 54 } while (0) 55 56 /* useful until we keep track of gc-references in corlib etc. */ 57 #define IS_GC_REFERENCE(class,t) (mono_gc_is_moving () ? FALSE : ((t)->type == MONO_TYPE_U && (class)->image == mono_defaults.corlib)) 58 59 void mono_object_register_finalizer (MonoObject *obj); 60 void ves_icall_System_GC_InternalCollect (int generation); 61 gint64 ves_icall_System_GC_GetTotalMemory (MonoBoolean forceCollection); 62 void ves_icall_System_GC_KeepAlive (MonoObject *obj); 63 void ves_icall_System_GC_ReRegisterForFinalize (MonoObject *obj); 64 void ves_icall_System_GC_SuppressFinalize (MonoObject *obj); 65 void ves_icall_System_GC_WaitForPendingFinalizers (void); 66 67 MonoObject *ves_icall_System_GCHandle_GetTarget (guint32 handle); 68 guint32 ves_icall_System_GCHandle_GetTargetHandle (MonoObject *obj, guint32 handle, gint32 type); 69 void ves_icall_System_GCHandle_FreeHandle (guint32 handle); 70 gpointer ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle); 71 void ves_icall_System_GC_register_ephemeron_array (MonoObject *array); 72 MonoObject *ves_icall_System_GC_get_ephemeron_tombstone (void); 73 74 75 extern void mono_gc_init (void); 76 extern void mono_gc_base_init (void); 77 extern void mono_gc_cleanup (void); 78 extern void mono_gc_base_cleanup (void); 79 80 /* 81 * Return whenever the current thread is registered with the GC (i.e. started 82 * by the GC pthread wrappers on unix. 83 */ 84 extern gboolean mono_gc_is_gc_thread (void); 85 86 extern gboolean mono_gc_is_finalizer_internal_thread (MonoInternalThread *thread); 87 88 extern void mono_gc_set_stack_end (void *stack_end); 89 90 /* only valid after the RECLAIM_START GC event and before RECLAIM_END 91 * Not exported in public headers, but can be linked to (unsupported). 92 */ 93 gboolean mono_object_is_alive (MonoObject* obj); 94 gboolean mono_gc_is_finalizer_thread (MonoThread *thread); 95 96 void mono_gchandle_set_target (guint32 gchandle, MonoObject *obj); 97 98 /*Ephemeron functionality. Sgen only*/ 99 gboolean mono_gc_ephemeron_array_add (MonoObject *obj); 100 101 MonoBoolean 102 mono_gc_GCHandle_CheckCurrentDomain (guint32 gchandle); 103 104 /* User defined marking function */ 105 /* It should work like this: 106 * foreach (ref in GC references in the are structure pointed to by ADDR) 107 * mark_func (ref) 108 */ 109 typedef void (*MonoGCMarkFunc) (MonoObject **addr, void *gc_data); 110 typedef void (*MonoGCRootMarkFunc) (void *addr, MonoGCMarkFunc mark_func, void *gc_data); 111 112 /* Create a descriptor with a user defined marking function */ 113 MonoGCDescriptor mono_gc_make_root_descr_user (MonoGCRootMarkFunc marker); 114 115 /* Return whenever user defined marking functions are supported */ 116 gboolean mono_gc_user_markers_supported (void); 117 118 /* desc is the result from mono_gc_make_descr*. A NULL value means 119 * all the words might contain GC pointers. 120 * The memory is non-moving and it will be explicitly deallocated. 121 * size bytes will be available from the returned address (ie, descr 122 * must not be stored in the returned memory) 123 */ 124 void* mono_gc_alloc_fixed (size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char *msg); 125 void mono_gc_free_fixed (void* addr); 126 127 /* make sure the gchandle was allocated for an object in domain */ 128 gboolean mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain); 129 void mono_gchandle_free_domain (MonoDomain *domain); 130 131 typedef void (*FinalizerThreadCallback) (gpointer user_data); 132 133 void* mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size); 134 void* mono_gc_alloc_obj (MonoVTable *vtable, size_t size); 135 void* mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length); 136 void* mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uintptr_t bounds_size); 137 void* mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len); 138 void* mono_gc_alloc_mature (MonoVTable *vtable, size_t size); 139 MonoGCDescriptor mono_gc_make_descr_for_string (gsize *bitmap, int numbits); 140 141 void mono_gc_register_obj_with_weak_fields (void *obj); 142 143 void mono_gc_register_for_finalization (MonoObject *obj, void *user_data); 144 void mono_gc_add_memory_pressure (gint64 value); 145 MONO_API int mono_gc_register_root (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char *msg); 146 void mono_gc_deregister_root (char* addr); 147 void mono_gc_finalize_domain (MonoDomain *domain); 148 void mono_gc_run_finalize (void *obj, void *data); 149 void mono_gc_clear_domain (MonoDomain * domain); 150 /* Signal early termination of finalizer processing inside the gc */ 151 void mono_gc_suspend_finalizers (void); 152 153 154 /* 155 * Register a root which can only be written using a write barrier. 156 * Writes to the root must be done using a write barrier (MONO_ROOT_SETREF). 157 * If the root uses an user defined mark routine, the writes are not required to be 158 * to the area between START and START+SIZE. 159 * The write barrier allows the GC to avoid scanning this root at each collection, so it 160 * is more efficient. 161 * FIXME: Add an API for clearing remset entries if a root with a user defined 162 * mark routine is deleted. 163 */ 164 int mono_gc_register_root_wbarrier (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char *msg); 165 166 void mono_gc_wbarrier_set_root (gpointer ptr, MonoObject *value); 167 168 /* Set a field of a root registered using mono_gc_register_root_wbarrier () */ 169 #define MONO_ROOT_SETREF(s,fieldname,value) do { \ 170 mono_gc_wbarrier_set_root (&((s)->fieldname), (MonoObject*)value); \ 171 } while (0) 172 173 /* fast allocation support */ 174 175 typedef enum { 176 // Regular fast path allocator. 177 MANAGED_ALLOCATOR_REGULAR, 178 // Managed allocator that just calls into the runtime. 179 MANAGED_ALLOCATOR_SLOW_PATH, 180 // Managed allocator that works like the regular one but also calls into the profiler. 181 MANAGED_ALLOCATOR_PROFILER, 182 } ManagedAllocatorVariant; 183 184 int mono_gc_get_aligned_size_for_allocator (int size); 185 MonoMethod* mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean known_instance_size); 186 MonoMethod* mono_gc_get_managed_array_allocator (MonoClass *klass); 187 MonoMethod *mono_gc_get_managed_allocator_by_type (int atype, ManagedAllocatorVariant variant); 188 189 guint32 mono_gc_get_managed_allocator_types (void); 190 191 /* Return a short string identifying the GC, indented to be saved in AOT images */ 192 const char *mono_gc_get_gc_name (void); 193 194 /* Fast write barriers */ 195 MonoMethod* mono_gc_get_specific_write_barrier (gboolean is_concurrent); 196 MonoMethod* mono_gc_get_write_barrier (void); 197 198 /* Fast valuetype copy */ 199 /* WARNING: [dest, dest + size] must be within the bounds of a single type, otherwise the GC will lose remset entries */ 200 void mono_gc_wbarrier_range_copy (gpointer dest, gpointer src, int size); 201 void* mono_gc_get_range_copy_func (void); 202 203 204 /* helper for the managed alloc support */ 205 MonoString * 206 ves_icall_string_alloc (int length); 207 208 /* 209 * Functions supplied by the runtime and called by the GC. Currently only used 210 * by SGEN. 211 */ 212 typedef struct { 213 /* 214 * Function called during thread startup/attach to allocate thread-local data 215 * needed by the other functions. 216 */ 217 gpointer (*thread_attach_func) (void); 218 /* 219 * Function called during thread deatch to free the data allocated by 220 * thread_attach_func. 221 */ 222 void (*thread_detach_func) (gpointer user_data); 223 /* 224 * Function called from every thread when suspending for GC. It can save 225 * data needed for marking from thread stacks. user_data is the data returned 226 * by attach_func. This might called with GC locks held and the word stopped, 227 * so it shouldn't do any synchronization etc. 228 */ 229 void (*thread_suspend_func) (gpointer user_data, void *sigcontext, MonoContext *ctx); 230 /* 231 * Function called to mark from thread stacks. user_data is the data returned 232 * by attach_func. This is called twice, with the word stopped: 233 * - in the first pass, it should mark areas of the stack using 234 * conservative marking by calling mono_gc_conservatively_scan_area (). 235 * - in the second pass, it should mark the remaining areas of the stack 236 * using precise marking by calling mono_gc_scan_object (). 237 */ 238 void (*thread_mark_func) (gpointer user_data, guint8 *stack_start, guint8 *stack_end, gboolean precise, void *gc_data); 239 /* 240 * Function called for debugging to get the current managed method for 241 * tracking the provenances of objects. 242 */ 243 gpointer (*get_provenance_func) (void); 244 } MonoGCCallbacks; 245 246 /* Set the callback functions callable by the GC */ 247 void mono_gc_set_gc_callbacks (MonoGCCallbacks *callbacks); 248 MonoGCCallbacks *mono_gc_get_gc_callbacks (void); 249 250 /* Functions callable from the thread mark func */ 251 252 /* Scan the memory area between START and END conservatively */ 253 void mono_gc_conservatively_scan_area (void *start, void *end); 254 255 /* Scan OBJ, returning its new address */ 256 void *mono_gc_scan_object (void *obj, void *gc_data); 257 258 /* Return the suspend signal number used by the GC to suspend threads, 259 or -1 if not applicable. */ 260 int mono_gc_get_suspend_signal (void); 261 262 /* Return the suspend signal number used by the GC to suspend threads, 263 or -1 if not applicable. */ 264 int mono_gc_get_restart_signal (void); 265 266 /* 267 * Return a human readable description of the GC in malloc-ed memory. 268 */ 269 char* mono_gc_get_description (void); 270 271 /* 272 * Configure the GC to desktop mode 273 */ 274 void mono_gc_set_desktop_mode (void); 275 276 /* 277 * Return whenever this GC can move objects 278 */ 279 gboolean mono_gc_is_moving (void); 280 281 typedef void* (*MonoGCLockedCallbackFunc) (void *data); 282 283 void* mono_gc_invoke_with_gc_lock (MonoGCLockedCallbackFunc func, void *data); 284 285 int mono_gc_get_los_limit (void); 286 287 guint8* mono_gc_get_card_table (int *shift_bits, gpointer *card_mask); 288 gboolean mono_gc_card_table_nursery_check (void); 289 290 void* mono_gc_get_nursery (int *shift_bits, size_t *size); 291 292 void mono_gc_set_skip_thread (gboolean skip); 293 294 #ifndef HOST_WIN32 295 int mono_gc_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); 296 #endif 297 298 /* 299 * Return whenever GC is disabled 300 */ 301 gboolean mono_gc_is_disabled (void); 302 303 /* 304 * Return whenever this is the null GC 305 */ 306 gboolean mono_gc_is_null (void); 307 308 void mono_gc_set_string_length (MonoString *str, gint32 new_length); 309 310 #if defined(__MACH__) 311 void mono_gc_register_mach_exception_thread (pthread_t thread); 312 pthread_t mono_gc_get_mach_exception_thread (void); 313 #endif 314 315 gboolean mono_gc_precise_stack_mark_enabled (void); 316 317 typedef struct _RefQueueEntry RefQueueEntry; 318 319 struct _RefQueueEntry { 320 void *dis_link; 321 guint32 gchandle; 322 MonoDomain *domain; 323 void *user_data; 324 RefQueueEntry *next; 325 }; 326 327 struct _MonoReferenceQueue { 328 RefQueueEntry *queue; 329 mono_reference_queue_callback callback; 330 MonoReferenceQueue *next; 331 gboolean should_be_deleted; 332 }; 333 334 enum { 335 MONO_GC_FINALIZER_EXTENSION_VERSION = 1, 336 }; 337 338 typedef struct { 339 int version; 340 gboolean (*is_class_finalization_aware) (MonoClass *klass); 341 void (*object_queued_for_finalization) (MonoObject *object); 342 } MonoGCFinalizerCallbacks; 343 344 MONO_API void mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks *callbacks); 345 346 347 #ifdef HOST_WIN32 348 BOOL APIENTRY mono_gc_dllmain (HMODULE module_handle, DWORD reason, LPVOID reserved); 349 #endif 350 351 guint mono_gc_get_vtable_bits (MonoClass *klass); 352 353 void mono_gc_register_altstack (gpointer stack, gint32 stack_size, gpointer altstack, gint32 altstack_size); 354 355 gboolean mono_gc_is_critical_method (MonoMethod *method); 356 357 gpointer mono_gc_thread_attach (THREAD_INFO_TYPE *info); 358 359 void mono_gc_thread_detach_with_lock (THREAD_INFO_TYPE *info); 360 361 gboolean mono_gc_thread_in_critical_region (THREAD_INFO_TYPE *info); 362 363 /* If set, print debugging messages around finalizers. */ 364 extern gboolean log_finalizers; 365 366 /* If set, do not run finalizers. */ 367 extern gboolean mono_do_not_finalize; 368 /* List of names of classes not to finalize. */ 369 extern gchar **mono_do_not_finalize_class_names; 370 371 #endif /* __MONO_METADATA_GC_INTERNAL_H__ */ 372 373