3 * Internal GC interface
5 * Author: Paolo Molaro <lupus@ximian.com>
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.
12 #ifndef __MONO_METADATA_GC_INTERNAL_H__
13 #define __MONO_METADATA_GC_INTERNAL_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 #include <mono/metadata/icalls.h>
22 #define mono_domain_finalizers_lock(domain) mono_os_mutex_lock (&(domain)->finalizable_objects_hash_lock);
23 #define mono_domain_finalizers_unlock(domain) mono_os_mutex_unlock (&(domain)->finalizable_objects_hash_lock);
25 /* Register a memory area as a conservatively scanned GC root */
26 #define MONO_GC_REGISTER_ROOT_PINNING(x,src,key,msg) mono_gc_register_root ((char*)&(x), sizeof(x), MONO_GC_DESCRIPTOR_NULL, (src), (key), (msg))
28 #define MONO_GC_UNREGISTER_ROOT(x) mono_gc_deregister_root ((char*)&(x))
31 * Return a GC descriptor for an array containing N pointers to memory allocated
32 * by mono_gc_alloc_fixed ().
34 /* For SGEN, the result of alloc_fixed () is not GC tracked memory */
35 #define MONO_GC_ROOT_DESCR_FOR_FIXED(n) (mono_gc_is_moving () ? mono_gc_make_root_descr_all_refs (0) : MONO_GC_DESCRIPTOR_NULL)
37 /* Register a memory location holding a single object reference as a GC root */
38 #define MONO_GC_REGISTER_ROOT_SINGLE(x,src,key,msg) do { \
39 g_assert (sizeof (x) == sizeof (MonoObject*)); \
40 mono_gc_register_root ((char*)&(x), sizeof(MonoObject*), mono_gc_make_root_descr_all_refs (1), (src), (key),(msg)); \
44 * This is used for fields which point to objects which are kept alive by other references
47 #define MONO_GC_REGISTER_ROOT_IF_MOVING(x,src,key,msg) do { \
48 if (mono_gc_is_moving ()) \
49 MONO_GC_REGISTER_ROOT_SINGLE(x,src,key,msg); \
52 #define MONO_GC_UNREGISTER_ROOT_IF_MOVING(x) do { \
53 if (mono_gc_is_moving ()) \
54 MONO_GC_UNREGISTER_ROOT (x); \
57 /* useful until we keep track of gc-references in corlib etc. */
58 #define IS_GC_REFERENCE(class,t) (mono_gc_is_moving () ? FALSE : ((t)->type == MONO_TYPE_U && (class)->image == mono_defaults.corlib))
60 void mono_object_register_finalizer (MonoObject
*obj
);
63 mono_object_register_finalizer_handle (MonoObjectHandle obj
);
65 extern void mono_gc_init (void);
66 extern void mono_gc_base_init (void);
67 extern void mono_gc_cleanup (void);
68 extern void mono_gc_base_cleanup (void);
69 extern void mono_gc_init_icalls (void);
72 * Return whenever the current thread is registered with the GC (i.e. started
73 * by the GC pthread wrappers on unix.
75 extern gboolean
mono_gc_is_gc_thread (void);
77 extern gboolean
mono_gc_is_finalizer_internal_thread (MonoInternalThread
*thread
);
79 extern void mono_gc_set_stack_end (void *stack_end
);
81 /* only valid after the RECLAIM_START GC event and before RECLAIM_END
82 * Not exported in public headers, but can be linked to (unsupported).
84 gboolean
mono_object_is_alive (MonoObject
* obj
);
85 gboolean
mono_gc_is_finalizer_thread (MonoThread
*thread
);
87 void mono_gchandle_set_target (guint32 gchandle
, MonoObject
*obj
);
89 /*Ephemeron functionality. Sgen only*/
90 gboolean
mono_gc_ephemeron_array_add (MonoObject
*obj
);
92 /* User defined marking function */
93 /* It should work like this:
94 * foreach (ref in GC references in the are structure pointed to by ADDR)
97 typedef void (*MonoGCMarkFunc
) (MonoObject
**addr
, void *gc_data
);
98 typedef void (*MonoGCRootMarkFunc
) (void *addr
, MonoGCMarkFunc mark_func
, void *gc_data
);
100 /* Create a descriptor with a user defined marking function */
101 MonoGCDescriptor
mono_gc_make_root_descr_user (MonoGCRootMarkFunc marker
);
103 /* Return whenever user defined marking functions are supported */
104 gboolean
mono_gc_user_markers_supported (void);
106 /* desc is the result from mono_gc_make_descr*. A NULL value means
107 * all the words might contain GC pointers.
108 * The memory is non-moving and it will be explicitly deallocated.
109 * size bytes will be available from the returned address (ie, descr
110 * must not be stored in the returned memory)
112 MonoObject
* mono_gc_alloc_fixed (size_t size
, MonoGCDescriptor descr
, MonoGCRootSource source
, void *key
, const char *msg
);
114 // C++ callers outside of metadata (mini/tasklets.c) must use mono_gc_alloc_fixed_no_descriptor
115 // instead of mono_gc_alloc_fixed, or else compile twice -- boehm and sgen.
117 mono_gc_alloc_fixed_no_descriptor (size_t size
, MonoGCRootSource source
, void *key
, const char *msg
);
119 void mono_gc_free_fixed (void* addr
);
121 /* make sure the gchandle was allocated for an object in domain */
122 gboolean
mono_gchandle_is_in_domain (guint32 gchandle
, MonoDomain
*domain
);
123 void mono_gchandle_free_domain (MonoDomain
*domain
);
125 typedef void (*FinalizerThreadCallback
) (gpointer user_data
);
128 mono_gc_alloc_pinned_obj (MonoVTable
*vtable
, size_t size
);
131 mono_gc_alloc_handle_pinned_obj (MonoVTable
*vtable
, gsize size
);
134 mono_gc_alloc_obj (MonoVTable
*vtable
, size_t size
);
137 mono_gc_alloc_handle_obj (MonoVTable
*vtable
, gsize size
);
140 mono_gc_alloc_vector (MonoVTable
*vtable
, size_t size
, uintptr_t max_length
);
143 mono_gc_alloc_handle_vector (MonoVTable
*vtable
, gsize size
, gsize max_length
);
146 mono_gc_alloc_array (MonoVTable
*vtable
, size_t size
, uintptr_t max_length
, uintptr_t bounds_size
);
149 mono_gc_alloc_handle_array (MonoVTable
*vtable
, gsize size
, gsize max_length
, gsize bounds_size
);
152 mono_gc_alloc_string (MonoVTable
*vtable
, size_t size
, gint32 len
);
155 mono_gc_alloc_handle_string (MonoVTable
*vtable
, gsize size
, gint32 len
);
158 mono_gc_alloc_mature (MonoVTable
*vtable
, size_t size
);
160 MonoGCDescriptor
mono_gc_make_descr_for_string (gsize
*bitmap
, int numbits
);
163 mono_gc_alloc_handle_mature (MonoVTable
*vtable
, gsize size
);
165 void mono_gc_register_obj_with_weak_fields (void *obj
);
167 mono_gc_register_object_with_weak_fields (MonoObjectHandle obj
);
169 typedef void (*MonoFinalizationProc
)(gpointer
, gpointer
); // same as SGenFinalizationProc, GC_finalization_proc
171 void mono_gc_register_for_finalization (MonoObject
*obj
, MonoFinalizationProc user_data
);
172 void mono_gc_add_memory_pressure (gint64 value
);
173 MONO_API
int mono_gc_register_root (char *start
, size_t size
, MonoGCDescriptor descr
, MonoGCRootSource source
, void *key
, const char *msg
);
174 void mono_gc_deregister_root (char* addr
);
175 void mono_gc_finalize_domain (MonoDomain
*domain
);
176 void mono_gc_run_finalize (void *obj
, void *data
);
177 void mono_gc_clear_domain (MonoDomain
* domain
);
178 /* Signal early termination of finalizer processing inside the gc */
179 void mono_gc_suspend_finalizers (void);
183 * Register a root which can only be written using a write barrier.
184 * Writes to the root must be done using a write barrier (MONO_ROOT_SETREF).
185 * If the root uses an user defined mark routine, the writes are not required to be
186 * to the area between START and START+SIZE.
187 * The write barrier allows the GC to avoid scanning this root at each collection, so it
189 * FIXME: Add an API for clearing remset entries if a root with a user defined
190 * mark routine is deleted.
192 int mono_gc_register_root_wbarrier (char *start
, size_t size
, MonoGCDescriptor descr
, MonoGCRootSource source
, void *key
, const char *msg
);
194 void mono_gc_wbarrier_set_root (gpointer ptr
, MonoObject
*value
);
196 /* Set a field of a root registered using mono_gc_register_root_wbarrier () */
197 #define MONO_ROOT_SETREF(s,fieldname,value) do { \
198 mono_gc_wbarrier_set_root (&((s)->fieldname), (MonoObject*)value); \
201 /* fast allocation support */
204 // Regular fast path allocator.
205 MANAGED_ALLOCATOR_REGULAR
,
206 // Managed allocator that just calls into the runtime.
207 MANAGED_ALLOCATOR_SLOW_PATH
,
208 // Managed allocator that works like the regular one but also calls into the profiler.
209 MANAGED_ALLOCATOR_PROFILER
,
210 } ManagedAllocatorVariant
;
212 int mono_gc_get_aligned_size_for_allocator (int size
);
213 MonoMethod
* mono_gc_get_managed_allocator (MonoClass
*klass
, gboolean for_box
, gboolean known_instance_size
);
214 MonoMethod
* mono_gc_get_managed_array_allocator (MonoClass
*klass
);
215 MonoMethod
*mono_gc_get_managed_allocator_by_type (int atype
, ManagedAllocatorVariant variant
);
217 guint32
mono_gc_get_managed_allocator_types (void);
219 /* Return a short string identifying the GC, indented to be saved in AOT images */
220 const char *mono_gc_get_gc_name (void);
222 /* Fast write barriers */
223 MonoMethod
* mono_gc_get_specific_write_barrier (gboolean is_concurrent
);
224 MonoMethod
* mono_gc_get_write_barrier (void);
226 /* Fast valuetype copy */
227 /* WARNING: [dest, dest + size] must be within the bounds of a single type, otherwise the GC will lose remset entries */
228 G_EXTERN_C
void mono_gc_wbarrier_range_copy (gpointer dest
, gconstpointer src
, int size
);
230 typedef void (*MonoRangeCopyFunction
)(gpointer
, gconstpointer
, int size
);
232 MonoRangeCopyFunction
233 mono_gc_get_range_copy_func (void);
236 * Functions supplied by the runtime and called by the GC. Currently only used
241 * Function called during thread startup/attach to allocate thread-local data
242 * needed by the other functions.
244 gpointer (*thread_attach_func
) (void);
246 * Function called during thread deatch to free the data allocated by
247 * thread_attach_func.
249 void (*thread_detach_func
) (gpointer user_data
);
251 * Function called from every thread when suspending for GC. It can save
252 * data needed for marking from thread stacks. user_data is the data returned
253 * by attach_func. This might called with GC locks held and the word stopped,
254 * so it shouldn't do any synchronization etc.
256 void (*thread_suspend_func
) (gpointer user_data
, void *sigcontext
, MonoContext
*ctx
);
258 * Function called to mark from thread stacks. user_data is the data returned
259 * by attach_func. This is called twice, with the word stopped:
260 * - in the first pass, it should mark areas of the stack using
261 * conservative marking by calling mono_gc_conservatively_scan_area ().
262 * - in the second pass, it should mark the remaining areas of the stack
263 * using precise marking by calling mono_gc_scan_object ().
265 void (*thread_mark_func
) (gpointer user_data
, guint8
*stack_start
, guint8
*stack_end
, gboolean precise
, void *gc_data
);
267 * Function called for debugging to get the current managed method for
268 * tracking the provenances of objects.
270 gpointer (*get_provenance_func
) (void);
272 * Same as thread_mark_func, mark the intepreter frames.
274 void (*interp_mark_func
) (gpointer thread_info
, GcScanFunc func
, gpointer gc_data
, gboolean precise
);
277 /* Set the callback functions callable by the GC */
278 void mono_gc_set_gc_callbacks (MonoGCCallbacks
*callbacks
);
279 MonoGCCallbacks
*mono_gc_get_gc_callbacks (void);
281 /* Functions callable from the thread mark func */
283 /* Scan the memory area between START and END conservatively */
284 void mono_gc_conservatively_scan_area (void *start
, void *end
);
286 /* Scan OBJ, returning its new address */
287 void *mono_gc_scan_object (void *obj
, void *gc_data
);
289 /* Return the suspend signal number used by the GC to suspend threads,
290 or -1 if not applicable. */
291 int mono_gc_get_suspend_signal (void);
293 /* Return the suspend signal number used by the GC to suspend threads,
294 or -1 if not applicable. */
295 int mono_gc_get_restart_signal (void);
298 * Return a human readable description of the GC in malloc-ed memory.
300 char* mono_gc_get_description (void);
303 * Configure the GC to desktop mode
305 void mono_gc_set_desktop_mode (void);
308 * Return whenever this GC can move objects
310 gboolean
mono_gc_is_moving (void);
312 typedef void* (*MonoGCLockedCallbackFunc
) (void *data
);
314 void* mono_gc_invoke_with_gc_lock (MonoGCLockedCallbackFunc func
, void *data
);
316 int mono_gc_get_los_limit (void);
318 guint64
mono_gc_get_allocated_bytes_for_current_thread (void);
320 guint64
mono_gc_get_total_allocated_bytes (MonoBoolean precise
);
322 void mono_gc_get_gcmemoryinfo (gint64
* fragmented_bytes
,
323 gint64
* heap_size_bytes
,
324 gint64
* high_memory_load_threshold_bytes
,
325 gint64
* memory_load_bytes
,
326 gint64
* total_available_memory_bytes
);
328 guint8
* mono_gc_get_card_table (int *shift_bits
, gpointer
*card_mask
);
329 guint8
* mono_gc_get_target_card_table (int *shift_bits
, target_mgreg_t
*card_mask
);
330 gboolean
mono_gc_card_table_nursery_check (void);
332 void* mono_gc_get_nursery (int *shift_bits
, size_t *size
);
334 // Don't use directly; set/unset MONO_THREAD_INFO_FLAGS_NO_GC instead.
335 void mono_gc_skip_thread_changing (gboolean skip
);
336 void mono_gc_skip_thread_changed (gboolean skip
);
339 int mono_gc_pthread_create (pthread_t
*new_thread
, const pthread_attr_t
*attr
, void *(*start_routine
)(void *), void *arg
);
343 * Return whenever GC is disabled
345 gboolean
mono_gc_is_disabled (void);
348 * Return whenever this is the null GC
350 gboolean
mono_gc_is_null (void);
352 void mono_gc_set_string_length (MonoString
*str
, gint32 new_length
);
354 #if defined(__MACH__)
355 void mono_gc_register_mach_exception_thread (pthread_t thread
);
356 pthread_t
mono_gc_get_mach_exception_thread (void);
359 gboolean
mono_gc_precise_stack_mark_enabled (void);
361 typedef struct _RefQueueEntry RefQueueEntry
;
363 struct _RefQueueEntry
{
371 struct _MonoReferenceQueue
{
372 RefQueueEntry
*queue
;
373 mono_reference_queue_callback callback
;
374 MonoReferenceQueue
*next
;
375 gboolean should_be_deleted
;
379 MONO_GC_FINALIZER_EXTENSION_VERSION
= 1,
384 gboolean (*is_class_finalization_aware
) (MonoClass
*klass
);
385 void (*object_queued_for_finalization
) (MonoObject
*object
);
386 } MonoGCFinalizerCallbacks
;
388 MONO_API
void mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks
*callbacks
);
392 BOOL APIENTRY
mono_gc_dllmain (HMODULE module_handle
, DWORD reason
, LPVOID reserved
);
395 MonoVTable
*mono_gc_get_vtable (MonoObject
*obj
);
397 guint
mono_gc_get_vtable_bits (MonoClass
*klass
);
399 void mono_gc_register_altstack (gpointer stack
, gint32 stack_size
, gpointer altstack
, gint32 altstack_size
);
401 gboolean
mono_gc_is_critical_method (MonoMethod
*method
);
403 G_EXTERN_C
// due to THREAD_INFO_TYPE varying
404 gpointer
mono_gc_thread_attach (THREAD_INFO_TYPE
*info
);
406 G_EXTERN_C
// due to THREAD_INFO_TYPE varying
407 void mono_gc_thread_detach (THREAD_INFO_TYPE
*info
);
409 G_EXTERN_C
// due to THREAD_INFO_TYPE varying
410 void mono_gc_thread_detach_with_lock (THREAD_INFO_TYPE
*info
);
412 G_EXTERN_C
// due to THREAD_INFO_TYPE varying
413 gboolean
mono_gc_thread_in_critical_region (THREAD_INFO_TYPE
*info
);
415 /* If set, print debugging messages around finalizers. */
416 extern gboolean mono_log_finalizers
;
418 /* If set, do not run finalizers. */
419 extern gboolean mono_do_not_finalize
;
420 /* List of names of classes not to finalize. */
421 extern gchar
**mono_do_not_finalize_class_names
;
423 #endif /* __MONO_METADATA_GC_INTERNAL_H__ */