2 * sgen-client-mono.h: Mono's client definitions for SGen.
4 * Copyright (C) 2014 Xamarin Inc
6 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
9 #ifdef SGEN_DEFINE_OBJECT_VTABLE
11 #include "sgen/sgen-archdep.h"
12 #include "utils/mono-threads.h"
13 #include "utils/mono-mmap.h"
14 #include "metadata/object-internals.h"
16 typedef MonoObject GCObject;
17 typedef MonoVTable* GCVTable;
19 static inline GCVTable
20 SGEN_LOAD_VTABLE_UNCHECKED (GCObject *obj)
25 static inline SgenDescriptor
26 sgen_vtable_get_descriptor (GCVTable vtable)
28 return (SgenDescriptor)vtable->gc_descr;
31 typedef struct _SgenClientThreadInfo SgenClientThreadInfo;
32 struct _SgenClientThreadInfo {
36 * `skip` is set to TRUE when STW fails to suspend a thread, most probably because
37 * the underlying thread is dead.
39 gboolean skip, suspend_done;
40 volatile int in_critical_region;
42 gpointer stopped_ip; /* only valid if the thread is stopped */
43 MonoDomain *stopped_domain; /* dsto */
46 This is set the argument of mono_gc_set_skip_thread.
48 A thread that knowingly holds no managed state can call this
49 function around blocking loops to reduce the GC burden by not
55 /* This is -1 until the first suspend. */
57 /* FIXME: kill this, we only use signals on systems that have rt-posix, which doesn't have issues with duplicates. */
58 unsigned int stop_count; /* to catch duplicate signals. */
61 gpointer runtime_data;
65 void *stack_start_limit;
67 /*FIXME pretty please finish killing ARCH_NUM_REGS */
69 MonoContext ctx; /* ditto */
71 gpointer regs[ARCH_NUM_REGS]; /* ditto */
77 #include "metadata/profiler-private.h"
78 #include "utils/dtrace.h"
79 #include "utils/mono-counters.h"
80 #include "utils/mono-logger-internals.h"
81 #include "utils/mono-time.h"
82 #include "utils/mono-os-semaphore.h"
83 #include "metadata/sgen-bridge-internals.h"
85 extern void mono_sgen_register_moved_object (void *obj, void *destination);
86 extern void mono_sgen_gc_event_moves (void);
88 extern void mono_sgen_init_stw (void);
91 INTERNAL_MEM_EPHEMERON_LINK = INTERNAL_MEM_FIRST_CLIENT,
96 sgen_mono_array_size (GCVTable vtable, MonoArray *array, mword *bounds_size, mword descr)
98 mword size, size_without_bounds;
101 if ((descr & DESC_TYPE_MASK) == DESC_TYPE_VECTOR)
102 element_size = ((descr) >> VECTOR_ELSIZE_SHIFT) & MAX_ELEMENT_SIZE;
104 element_size = vtable->klass->sizes.element_size;
106 size_without_bounds = size = MONO_SIZEOF_MONO_ARRAY + element_size * mono_array_length_fast (array);
108 if (G_UNLIKELY (array->bounds)) {
109 size += sizeof (mono_array_size_t) - 1;
110 size &= ~(sizeof (mono_array_size_t) - 1);
111 size += sizeof (MonoArrayBounds) * vtable->klass->rank;
115 *bounds_size = size - size_without_bounds;
119 #define SGEN_CLIENT_OBJECT_HEADER_SIZE (sizeof (GCObject))
120 #define SGEN_CLIENT_MINIMUM_OBJECT_SIZE SGEN_CLIENT_OBJECT_HEADER_SIZE
122 static mword /*__attribute__((noinline)) not sure if this hint is a good idea*/
123 sgen_client_slow_object_get_size (GCVTable vtable, GCObject* o)
125 MonoClass *klass = ((MonoVTable*)vtable)->klass;
128 * We depend on mono_string_length_fast and
129 * mono_array_length_fast not using the object's vtable.
131 if (klass == mono_defaults.string_class) {
132 return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
133 } else if (klass->rank) {
134 return sgen_mono_array_size (vtable, (MonoArray*)o, NULL, 0);
136 /* from a created object: the class must be inited already */
137 return klass->instance_size;
142 * This function can be called on an object whose first word, the
143 * vtable field, is not intact. This is necessary for the parallel
146 static MONO_NEVER_INLINE mword
147 sgen_client_par_object_get_size (GCVTable vtable, GCObject* o)
149 SgenDescriptor descr = sgen_vtable_get_descriptor (vtable);
150 mword type = descr & DESC_TYPE_MASK;
152 if (type == DESC_TYPE_RUN_LENGTH || type == DESC_TYPE_SMALL_PTRFREE) {
153 mword size = descr & 0xfff8;
154 SGEN_ASSERT (9, size >= sizeof (MonoObject), "Run length object size to small");
156 } else if (descr == SGEN_DESC_STRING) {
157 return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
158 } else if (type == DESC_TYPE_VECTOR) {
159 return sgen_mono_array_size (vtable, (MonoArray*)o, NULL, descr);
162 return sgen_client_slow_object_get_size (vtable, o);
165 static MONO_ALWAYS_INLINE size_t G_GNUC_UNUSED
166 sgen_client_array_element_size (GCVTable gc_vtable)
168 MonoVTable *vt = (MonoVTable*)gc_vtable;
169 return mono_array_element_size (vt->klass);
172 static MONO_ALWAYS_INLINE G_GNUC_UNUSED char*
173 sgen_client_array_data_start (GCObject *obj)
175 return (char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector);
178 static MONO_ALWAYS_INLINE size_t G_GNUC_UNUSED
179 sgen_client_array_length (GCObject *obj)
181 return mono_array_length_fast ((MonoArray*)obj);
184 static MONO_ALWAYS_INLINE gboolean G_GNUC_UNUSED
185 sgen_client_object_is_array_fill (GCObject *o)
187 return ((MonoObject*)o)->synchronisation == GINT_TO_POINTER (-1);
190 static MONO_ALWAYS_INLINE void G_GNUC_UNUSED
191 sgen_client_pre_copy_checks (char *destination, GCVTable gc_vtable, void *obj, mword objsize)
193 MonoVTable *vt = (MonoVTable*)gc_vtable;
194 SGEN_ASSERT (9, vt->klass->inited, "vtable %p for class %s:%s was not initialized", vt, vt->klass->name_space, vt->klass->name);
197 static MONO_ALWAYS_INLINE void G_GNUC_UNUSED
198 sgen_client_update_copied_object (char *destination, GCVTable gc_vtable, void *obj, mword objsize)
200 MonoVTable *vt = (MonoVTable*)gc_vtable;
201 if (G_UNLIKELY (vt->rank && ((MonoArray*)obj)->bounds)) {
202 MonoArray *array = (MonoArray*)destination;
203 array->bounds = (MonoArrayBounds*)((char*)destination + ((char*)((MonoArray*)obj)->bounds - (char*)obj));
204 SGEN_LOG (9, "Array instance %p: size: %lu, rank: %d, length: %lu", array, (unsigned long)objsize, vt->rank, (unsigned long)mono_array_length (array));
207 if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES))
208 mono_sgen_register_moved_object (obj, destination);
211 #ifdef XDOMAIN_CHECKS_IN_WBARRIER
212 extern gboolean sgen_mono_xdomain_checks;
214 #define sgen_client_wbarrier_generic_nostore_check(ptr) do { \
215 /* FIXME: ptr_in_heap must be called with the GC lock held */ \
216 if (sgen_mono_xdomain_checks && *(MonoObject**)ptr && ptr_in_heap (ptr)) { \
217 char *start = find_object_for_ptr (ptr); \
218 MonoObject *value = *(MonoObject**)ptr; \
220 SGEN_ASSERT (0, start, "Write barrier outside an object?"); \
222 MonoObject *obj = (MonoObject*)start; \
223 if (obj->vtable->domain != value->vtable->domain) \
224 SGEN_ASSERT (0, is_xdomain_ref_allowed (ptr, start, obj->vtable->domain), "Cross-domain ref not allowed"); \
230 #define sgen_client_wbarrier_generic_nostore_check(ptr)
233 static gboolean G_GNUC_UNUSED
234 sgen_client_object_has_critical_finalizer (GCObject *obj)
238 if (!mono_defaults.critical_finalizer_object)
241 klass = SGEN_LOAD_VTABLE (obj)->klass;
243 return mono_class_has_parent_fast (klass, mono_defaults.critical_finalizer_object);
246 const char* sgen_client_vtable_get_namespace (GCVTable vtable);
247 const char* sgen_client_vtable_get_name (GCVTable vtable);
249 static gboolean G_GNUC_UNUSED
250 sgen_client_bridge_need_processing (void)
252 return sgen_need_bridge_processing ();
255 static void G_GNUC_UNUSED
256 sgen_client_bridge_reset_data (void)
258 sgen_bridge_reset_data ();
261 static void G_GNUC_UNUSED
262 sgen_client_bridge_processing_stw_step (void)
264 sgen_bridge_processing_stw_step ();
267 static void G_GNUC_UNUSED
268 sgen_client_bridge_wait_for_processing (void)
270 mono_gc_wait_for_bridge_processing ();
273 static void G_GNUC_UNUSED
274 sgen_client_bridge_processing_finish (int generation)
276 sgen_bridge_processing_finish (generation);
279 static gboolean G_GNUC_UNUSED
280 sgen_client_bridge_is_bridge_object (GCObject *obj)
282 return sgen_is_bridge_object (obj);
285 static void G_GNUC_UNUSED
286 sgen_client_bridge_register_finalized_object (GCObject *object)
288 sgen_bridge_register_finalized_object (object);
291 static void G_GNUC_UNUSED
292 sgen_client_binary_protocol_collection_requested (int generation, size_t requested_size, gboolean force)
294 MONO_GC_REQUESTED (generation, requested_size, force);
297 static void G_GNUC_UNUSED
298 sgen_client_binary_protocol_collection_begin (int minor_gc_count, int generation)
300 MONO_GC_BEGIN (generation);
302 mono_profiler_gc_event (MONO_GC_EVENT_START, generation);
304 #ifndef DISABLE_PERFCOUNTERS
305 if (generation == GENERATION_NURSERY)
306 mono_perfcounters->gc_collections0++;
308 mono_perfcounters->gc_collections1++;
312 static void G_GNUC_UNUSED
313 sgen_client_binary_protocol_collection_end (int minor_gc_count, int generation, long long num_objects_scanned, long long num_unique_objects_scanned)
315 MONO_GC_END (generation);
317 mono_profiler_gc_event (MONO_GC_EVENT_END, generation);
320 static void G_GNUC_UNUSED
321 sgen_client_binary_protocol_concurrent_start (void)
323 MONO_GC_CONCURRENT_START_BEGIN (GENERATION_OLD);
326 static void G_GNUC_UNUSED
327 sgen_client_binary_protocol_concurrent_update (void)
329 MONO_GC_CONCURRENT_UPDATE_FINISH_BEGIN (GENERATION_OLD, sgen_get_major_collector ()->get_and_reset_num_major_objects_marked ());
332 static void G_GNUC_UNUSED
333 sgen_client_binary_protocol_concurrent_finish (void)
335 MONO_GC_CONCURRENT_UPDATE_FINISH_BEGIN (GENERATION_OLD, sgen_get_major_collector ()->get_and_reset_num_major_objects_marked ());
338 static void G_GNUC_UNUSED
339 sgen_client_binary_protocol_sweep_begin (int generation, int full_sweep)
341 MONO_GC_SWEEP_BEGIN (generation, full_sweep);
344 static void G_GNUC_UNUSED
345 sgen_client_binary_protocol_sweep_end (int generation, int full_sweep)
347 MONO_GC_SWEEP_END (generation, full_sweep);
350 static void G_GNUC_UNUSED
351 sgen_client_binary_protocol_world_stopping (int generation, long long timestamp, gpointer thread)
353 MONO_GC_WORLD_STOP_BEGIN ();
355 mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
358 static void G_GNUC_UNUSED
359 sgen_client_binary_protocol_world_stopped (int generation, long long timestamp, long long total_major_cards, long long marked_major_cards, long long total_los_cards, long long marked_los_cards)
361 MONO_GC_WORLD_STOP_END ();
363 mono_profiler_gc_event (MONO_GC_EVENT_POST_STOP_WORLD, generation);
366 static void G_GNUC_UNUSED
367 sgen_client_binary_protocol_world_restarting (int generation, long long timestamp, long long total_major_cards, long long marked_major_cards, long long total_los_cards, long long marked_los_cards)
369 MONO_GC_WORLD_RESTART_BEGIN (generation);
371 mono_profiler_gc_event (MONO_GC_EVENT_PRE_START_WORLD, generation);
374 static void G_GNUC_UNUSED
375 sgen_client_binary_protocol_world_restarted (int generation, long long timestamp)
377 MONO_GC_WORLD_RESTART_END (generation);
379 mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation);
382 static void G_GNUC_UNUSED
383 sgen_client_binary_protocol_block_alloc (gpointer addr, size_t size)
387 static void G_GNUC_UNUSED
388 sgen_client_binary_protocol_block_free (gpointer addr, size_t size)
392 static void G_GNUC_UNUSED
393 sgen_client_binary_protocol_block_set_state (gpointer addr, size_t size, int old, int new_)
397 static void G_GNUC_UNUSED
398 sgen_client_binary_protocol_mark_start (int generation)
400 mono_profiler_gc_event (MONO_GC_EVENT_MARK_START, generation);
403 static void G_GNUC_UNUSED
404 sgen_client_binary_protocol_mark_end (int generation)
406 mono_profiler_gc_event (MONO_GC_EVENT_MARK_END, generation);
409 static void G_GNUC_UNUSED
410 sgen_client_binary_protocol_reclaim_start (int generation)
412 mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_START, generation);
415 static void G_GNUC_UNUSED
416 sgen_client_binary_protocol_reclaim_end (int generation)
418 mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_END, generation);
422 mono_binary_protocol_alloc_generic (gpointer obj, gpointer vtable, size_t size, gboolean pinned)
425 const char *namespace = sgen_client_vtable_get_namespace (vtable);
426 const char *name = sgen_client_vtable_get_name (vtable);
428 if (sgen_ptr_in_nursery (obj)) {
429 if (G_UNLIKELY (MONO_GC_NURSERY_OBJ_ALLOC_ENABLED ()))
430 MONO_GC_NURSERY_OBJ_ALLOC ((mword)obj, size, namespace, name);
432 if (size > SGEN_MAX_SMALL_OBJ_SIZE) {
433 if (G_UNLIKELY (MONO_GC_MAJOR_OBJ_ALLOC_LARGE_ENABLED ()))
434 MONO_GC_MAJOR_OBJ_ALLOC_LARGE ((mword)obj, size, namespace, name);
436 MONO_GC_MAJOR_OBJ_ALLOC_PINNED ((mword)obj, size, namespace, name);
442 static void G_GNUC_UNUSED
443 sgen_client_binary_protocol_alloc (gpointer obj, gpointer vtable, size_t size, gpointer provenance)
445 mono_binary_protocol_alloc_generic (obj, vtable, size, FALSE);
448 static void G_GNUC_UNUSED
449 sgen_client_binary_protocol_alloc_pinned (gpointer obj, gpointer vtable, size_t size, gpointer provenance)
451 mono_binary_protocol_alloc_generic (obj, vtable, size, TRUE);
454 static void G_GNUC_UNUSED
455 sgen_client_binary_protocol_alloc_degraded (gpointer obj, gpointer vtable, size_t size, gpointer provenance)
457 MONO_GC_MAJOR_OBJ_ALLOC_DEGRADED ((mword)obj, size, sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable));
460 static void G_GNUC_UNUSED
461 sgen_client_binary_protocol_card_scan (gpointer start, size_t size)
465 static void G_GNUC_UNUSED
466 sgen_client_binary_protocol_pin_stage (gpointer addr_ptr, gpointer addr)
470 static void G_GNUC_UNUSED
471 sgen_client_binary_protocol_cement_stage (gpointer addr)
475 static void G_GNUC_UNUSED
476 sgen_client_binary_protocol_pin (gpointer obj, gpointer vtable, size_t size)
479 if (G_UNLIKELY (MONO_GC_OBJ_PINNED_ENABLED ())) {
480 int gen = sgen_ptr_in_nursery (obj) ? GENERATION_NURSERY : GENERATION_OLD;
481 MONO_GC_OBJ_PINNED ((mword)obj,
482 sgen_safe_object_get_size (obj),
483 sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable), gen);
488 static void G_GNUC_UNUSED
489 sgen_client_binary_protocol_mark (gpointer obj, gpointer vtable, size_t size)
493 static void G_GNUC_UNUSED
494 sgen_client_binary_protocol_scan_begin (gpointer obj, gpointer vtable, size_t size)
498 static void G_GNUC_UNUSED
499 sgen_client_binary_protocol_scan_vtype_begin (gpointer obj, size_t size)
503 static void G_GNUC_UNUSED
504 sgen_client_binary_protocol_scan_process_reference (gpointer obj, gpointer ptr, gpointer value)
508 static void G_GNUC_UNUSED
509 sgen_client_binary_protocol_scan_stack (gpointer thread, gpointer stack_start, gpointer stack_end, int skip_reason)
513 static void G_GNUC_UNUSED
514 sgen_client_binary_protocol_wbarrier (gpointer ptr, gpointer value, gpointer value_vtable)
518 static void G_GNUC_UNUSED
519 sgen_client_binary_protocol_cement (gpointer ptr, gpointer vtable, size_t size)
522 if (G_UNLIKELY (MONO_GC_OBJ_CEMENTED_ENABLED())) {
523 MONO_GC_OBJ_CEMENTED ((mword)ptr, sgen_safe_object_get_size ((GCObject*)ptr),
524 sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable));
529 static void G_GNUC_UNUSED
530 sgen_client_binary_protocol_copy (gpointer from, gpointer to, gpointer vtable, size_t size)
533 if (G_UNLIKELY (MONO_GC_OBJ_MOVED_ENABLED ())) {
534 int dest_gen = sgen_ptr_in_nursery (to) ? GENERATION_NURSERY : GENERATION_OLD;
535 int src_gen = sgen_ptr_in_nursery (from) ? GENERATION_NURSERY : GENERATION_OLD;
536 MONO_GC_OBJ_MOVED ((mword)to, (mword)from, dest_gen, src_gen, size, sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable));
541 static void G_GNUC_UNUSED
542 sgen_client_binary_protocol_global_remset (gpointer ptr, gpointer value, gpointer value_vtable)
545 if (G_UNLIKELY (MONO_GC_GLOBAL_REMSET_ADD_ENABLED ())) {
546 MONO_GC_GLOBAL_REMSET_ADD ((mword)ptr, (mword)value, sgen_safe_object_get_size (value),
547 sgen_client_vtable_get_namespace (value_vtable), sgen_client_vtable_get_name (value_vtable));
552 static void G_GNUC_UNUSED
553 sgen_client_binary_protocol_mod_union_remset (gpointer obj, gpointer ptr, gpointer value, gpointer value_vtable)
557 static void G_GNUC_UNUSED
558 sgen_client_binary_protocol_ptr_update (gpointer ptr, gpointer old_value, gpointer new_value, gpointer vtable, size_t size)
562 static void G_GNUC_UNUSED
563 sgen_client_binary_protocol_cleanup (gpointer ptr, gpointer vtable, size_t size)
567 static void G_GNUC_UNUSED
568 sgen_client_binary_protocol_dislink_add (gpointer link, gpointer obj, gboolean track)
572 static void G_GNUC_UNUSED
573 sgen_client_binary_protocol_dislink_update (gpointer link, gpointer obj, gboolean track)
576 if (MONO_GC_WEAK_UPDATE_ENABLED ()) {
577 GCVTable vt = obj ? SGEN_LOAD_VTABLE (obj) : NULL;
578 MONO_GC_WEAK_UPDATE ((mword)link,
580 obj ? (mword)sgen_safe_object_get_size (obj) : (mword)0,
581 obj ? sgen_client_vtable_get_namespace (vt) : NULL,
582 obj ? sgen_client_vtable_get_name (vt) : NULL,
588 static void G_GNUC_UNUSED
589 sgen_client_binary_protocol_dislink_remove (gpointer link, gboolean track)
593 static void G_GNUC_UNUSED
594 sgen_client_binary_protocol_empty (gpointer start, size_t size)
596 if (sgen_ptr_in_nursery (start))
597 MONO_GC_NURSERY_SWEPT ((mword)start, size);
599 MONO_GC_MAJOR_SWEPT ((mword)start, size);
602 static void G_GNUC_UNUSED
603 sgen_client_binary_protocol_thread_suspend (gpointer thread, gpointer stopped_ip)
607 static void G_GNUC_UNUSED
608 sgen_client_binary_protocol_thread_restart (gpointer thread)
612 static void G_GNUC_UNUSED
613 sgen_client_binary_protocol_thread_register (gpointer thread)
617 static void G_GNUC_UNUSED
618 sgen_client_binary_protocol_thread_unregister (gpointer thread)
622 static void G_GNUC_UNUSED
623 sgen_client_binary_protocol_missing_remset (gpointer obj, gpointer obj_vtable, int offset, gpointer value, gpointer value_vtable, gboolean value_pinned)
627 static void G_GNUC_UNUSED
628 sgen_client_binary_protocol_cement_reset (void)
632 static void G_GNUC_UNUSED
633 sgen_client_binary_protocol_domain_unload_begin (gpointer domain)
637 static void G_GNUC_UNUSED
638 sgen_client_binary_protocol_domain_unload_end (gpointer domain)
642 static void G_GNUC_UNUSED
643 sgen_client_binary_protocol_gray_enqueue (gpointer queue, gpointer cursor, gpointer value)
647 static void G_GNUC_UNUSED
648 sgen_client_binary_protocol_gray_dequeue (gpointer queue, gpointer cursor, gpointer value)
652 static void G_GNUC_UNUSED
653 sgen_client_binary_protocol_major_card_table_scan_start (long long timestamp, gboolean mod_union)
657 static void G_GNUC_UNUSED
658 sgen_client_binary_protocol_major_card_table_scan_end (long long timestamp, gboolean mod_union)
662 static void G_GNUC_UNUSED
663 sgen_client_binary_protocol_los_card_table_scan_start (long long timestamp, gboolean mod_union)
667 static void G_GNUC_UNUSED
668 sgen_client_binary_protocol_los_card_table_scan_end (long long timestamp, gboolean mod_union)
672 static void G_GNUC_UNUSED
673 sgen_client_binary_protocol_finish_gray_stack_start (long long timestamp, int generation)
677 static void G_GNUC_UNUSED
678 sgen_client_binary_protocol_finish_gray_stack_end (long long timestamp, int generation)
682 static void G_GNUC_UNUSED
683 sgen_client_binary_protocol_worker_finish (long long timestamp, gboolean forced)
687 static void G_GNUC_UNUSED
688 sgen_client_binary_protocol_evacuating_blocks (size_t block_size)
692 int sgen_thread_handshake (BOOL suspend);
693 gboolean sgen_suspend_thread (SgenThreadInfo *info);
694 gboolean sgen_resume_thread (SgenThreadInfo *info);
695 void sgen_wait_for_suspend_ack (int count);
697 #ifdef HAVE_KW_THREAD
698 extern __thread SgenThreadInfo *sgen_thread_info;
699 #define TLAB_ACCESS_INIT
700 #define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
702 extern MonoNativeTlsKey thread_info_key;
703 #define TLAB_ACCESS_INIT SgenThreadInfo *__thread_info__ = mono_native_tls_get_value (thread_info_key)
704 #define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
707 #ifdef HAVE_KW_THREAD
708 #define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
710 #define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
713 /* Enter must be visible before anything is done in the critical region. */
714 #define ENTER_CRITICAL_REGION do { mono_atomic_store_acquire (&IN_CRITICAL_REGION, 1); } while (0)
716 /* Exit must make sure all critical regions stores are visible before it signal the end of the region.
717 * We don't need to emit a full barrier since we
719 #define EXIT_CRITICAL_REGION do { mono_atomic_store_release (&IN_CRITICAL_REGION, 0); } while (0)
721 #define SGEN_TV_DECLARE(name) gint64 name
722 #define SGEN_TV_GETTIME(tv) tv = mono_100ns_ticks ()
723 #define SGEN_TV_ELAPSED(start,end) ((gint64)(end-start))
725 typedef MonoSemType SgenSemaphore;
727 #define SGEN_SEMAPHORE_INIT(sem,initial) mono_os_sem_init ((sem), (initial))
728 #define SGEN_SEMAPHORE_POST(sem) mono_os_sem_post ((sem))
729 #define SGEN_SEMAPHORE_WAIT(sem) mono_os_sem_wait ((sem), MONO_SEM_FLAGS_NONE)
731 gboolean sgen_has_critical_method (void);
732 gboolean sgen_is_critical_method (MonoMethod *method);
734 void sgen_set_use_managed_allocator (gboolean flag);
735 gboolean sgen_is_managed_allocator (MonoMethod *method);
736 gboolean sgen_has_managed_allocator (void);
738 void sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type);
739 void sgen_null_links_for_domain (MonoDomain *domain);