Merge pull request #3707 from lateralusX/jlorenss/win-api-family-support-libmonoutils
[mono.git] / mono / metadata / sgen-client-mono.h
1 /*
2  * sgen-client-mono.h: Mono's client definitions for SGen.
3  *
4  * Copyright (C) 2014 Xamarin Inc
5  *
6  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
7  */
8
9 #ifdef SGEN_DEFINE_OBJECT_VTABLE
10
11 #include "sgen/sgen-archdep.h"
12 #include "utils/mono-threads.h"
13 #include "utils/mono-mmap.h"
14 #include "metadata/object-internals.h"
15
16 typedef MonoObject GCObject;
17 typedef MonoVTable* GCVTable;
18
19 static inline GCVTable
20 SGEN_LOAD_VTABLE_UNCHECKED (GCObject *obj)
21 {
22         return obj->vtable;
23 }
24
25 static inline SgenDescriptor
26 sgen_vtable_get_descriptor (GCVTable vtable)
27 {
28         return (SgenDescriptor)vtable->gc_descr;
29 }
30
31 typedef struct _SgenClientThreadInfo SgenClientThreadInfo;
32 struct _SgenClientThreadInfo {
33         MonoThreadInfo info;
34
35         /*
36          * `skip` is set to TRUE when STW fails to suspend a thread, most probably because
37          * the underlying thread is dead.
38         */
39         gboolean skip, suspend_done;
40         volatile int in_critical_region;
41
42         gpointer stopped_ip;    /* only valid if the thread is stopped */
43         MonoDomain *stopped_domain; /* dsto */
44
45         /*
46         This is set the argument of mono_gc_set_skip_thread.
47
48         A thread that knowingly holds no managed state can call this
49         function around blocking loops to reduce the GC burden by not
50         been scanned.
51         */
52         gboolean gc_disabled;
53
54 #ifdef SGEN_POSIX_STW
55         /* This is -1 until the first suspend. */
56         int signal;
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. */
59 #endif
60
61         gpointer runtime_data;
62
63         void *stack_end;
64         void *stack_start;
65         void *stack_start_limit;
66
67         MonoContext ctx;                /* ditto */
68 };
69
70 #else
71
72 #include "metadata/profiler-private.h"
73 #include "utils/dtrace.h"
74 #include "utils/mono-counters.h"
75 #include "utils/mono-logger-internals.h"
76 #include "utils/mono-time.h"
77 #include "utils/mono-os-semaphore.h"
78 #include "metadata/sgen-bridge-internals.h"
79
80 extern void mono_sgen_register_moved_object (void *obj, void *destination);
81 extern void mono_sgen_gc_event_moves (void);
82
83 extern void mono_sgen_init_stw (void);
84
85 enum {
86         INTERNAL_MEM_EPHEMERON_LINK = INTERNAL_MEM_FIRST_CLIENT,
87         INTERNAL_MEM_MOVED_OBJECT,
88         INTERNAL_MEM_MAX
89 };
90
91 static inline mword
92 sgen_mono_array_size (GCVTable vtable, MonoArray *array, mword *bounds_size, mword descr)
93 {
94         mword size, size_without_bounds;
95         int element_size;
96
97         if ((descr & DESC_TYPE_MASK) == DESC_TYPE_VECTOR)
98                 element_size = ((descr) >> VECTOR_ELSIZE_SHIFT) & MAX_ELEMENT_SIZE;
99         else
100                 element_size = vtable->klass->sizes.element_size;
101
102         size_without_bounds = size = MONO_SIZEOF_MONO_ARRAY + element_size * mono_array_length_fast (array);
103
104         if (G_UNLIKELY (array->bounds)) {
105                 size += sizeof (mono_array_size_t) - 1;
106                 size &= ~(sizeof (mono_array_size_t) - 1);
107                 size += sizeof (MonoArrayBounds) * vtable->klass->rank;
108         }
109
110         if (bounds_size)
111                 *bounds_size = size - size_without_bounds;
112         return size;
113 }
114
115 #define SGEN_CLIENT_OBJECT_HEADER_SIZE          (sizeof (GCObject))
116 #define SGEN_CLIENT_MINIMUM_OBJECT_SIZE         SGEN_CLIENT_OBJECT_HEADER_SIZE
117
118 static mword /*__attribute__((noinline)) not sure if this hint is a good idea*/
119 sgen_client_slow_object_get_size (GCVTable vtable, GCObject* o)
120 {
121         MonoClass *klass = ((MonoVTable*)vtable)->klass;
122
123         /*
124          * We depend on mono_string_length_fast and
125          * mono_array_length_fast not using the object's vtable.
126          */
127         if (klass == mono_defaults.string_class) {
128                 return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
129         } else if (klass->rank) {
130                 return sgen_mono_array_size (vtable, (MonoArray*)o, NULL, 0);
131         } else {
132                 /* from a created object: the class must be inited already */
133                 return klass->instance_size;
134         }
135 }
136
137 /*
138  * This function can be called on an object whose first word, the
139  * vtable field, is not intact.  This is necessary for the parallel
140  * collector.
141  */
142 static MONO_NEVER_INLINE mword
143 sgen_client_par_object_get_size (GCVTable vtable, GCObject* o)
144 {
145         SgenDescriptor descr = sgen_vtable_get_descriptor (vtable);
146         mword type = descr & DESC_TYPE_MASK;
147
148         if (type == DESC_TYPE_RUN_LENGTH || type == DESC_TYPE_SMALL_PTRFREE) {
149                 mword size = descr & 0xfff8;
150                 SGEN_ASSERT (9, size >= sizeof (MonoObject), "Run length object size to small");
151                 return size;
152         } else if (descr == SGEN_DESC_STRING) {
153                 return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
154         } else if (type == DESC_TYPE_VECTOR) {
155                 return sgen_mono_array_size (vtable, (MonoArray*)o, NULL, descr);
156         }
157
158         return sgen_client_slow_object_get_size (vtable, o);
159 }
160
161 static MONO_ALWAYS_INLINE size_t G_GNUC_UNUSED
162 sgen_client_array_element_size (GCVTable gc_vtable)
163 {
164         MonoVTable *vt = (MonoVTable*)gc_vtable;
165         return mono_array_element_size (vt->klass);
166 }
167
168 static MONO_ALWAYS_INLINE G_GNUC_UNUSED char*
169 sgen_client_array_data_start (GCObject *obj)
170 {
171         return (char*)(obj) +  G_STRUCT_OFFSET (MonoArray, vector);
172 }
173
174 static MONO_ALWAYS_INLINE size_t G_GNUC_UNUSED
175 sgen_client_array_length (GCObject *obj)
176 {
177         return mono_array_length_fast ((MonoArray*)obj);
178 }
179
180 static MONO_ALWAYS_INLINE gboolean G_GNUC_UNUSED
181 sgen_client_object_is_array_fill (GCObject *o)
182 {
183         return ((MonoObject*)o)->synchronisation == GINT_TO_POINTER (-1);
184 }
185
186 static MONO_ALWAYS_INLINE void G_GNUC_UNUSED
187 sgen_client_pre_copy_checks (char *destination, GCVTable gc_vtable, void *obj, mword objsize)
188 {
189         MonoVTable *vt = (MonoVTable*)gc_vtable;
190         SGEN_ASSERT (9, vt->klass->inited, "vtable %p for class %s:%s was not initialized", vt, vt->klass->name_space, vt->klass->name);
191 }
192
193 static MONO_ALWAYS_INLINE void G_GNUC_UNUSED
194 sgen_client_update_copied_object (char *destination, GCVTable gc_vtable, void *obj, mword objsize)
195 {
196         MonoVTable *vt = (MonoVTable*)gc_vtable;
197         if (G_UNLIKELY (vt->rank && ((MonoArray*)obj)->bounds)) {
198                 MonoArray *array = (MonoArray*)destination;
199                 array->bounds = (MonoArrayBounds*)((char*)destination + ((char*)((MonoArray*)obj)->bounds - (char*)obj));
200                 SGEN_LOG (9, "Array instance %p: size: %lu, rank: %d, length: %lu", array, (unsigned long)objsize, vt->rank, (unsigned long)mono_array_length (array));
201         }
202
203         if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES))
204                 mono_sgen_register_moved_object (obj, destination);
205 }
206
207 #ifdef XDOMAIN_CHECKS_IN_WBARRIER
208 extern gboolean sgen_mono_xdomain_checks;
209
210 #define sgen_client_wbarrier_generic_nostore_check(ptr) do {            \
211                 /* FIXME: ptr_in_heap must be called with the GC lock held */ \
212                 if (sgen_mono_xdomain_checks && *(MonoObject**)ptr && ptr_in_heap (ptr)) { \
213                         char *start = find_object_for_ptr (ptr);        \
214                         MonoObject *value = *(MonoObject**)ptr;         \
215                         LOCK_GC;                                        \
216                         SGEN_ASSERT (0, start, "Write barrier outside an object?"); \
217                         if (start) {                                    \
218                                 MonoObject *obj = (MonoObject*)start;   \
219                                 if (obj->vtable->domain != value->vtable->domain) \
220                                         SGEN_ASSERT (0, is_xdomain_ref_allowed (ptr, start, obj->vtable->domain), "Cross-domain ref not allowed"); \
221                         }                                               \
222                         UNLOCK_GC;                                      \
223                 }                                                       \
224         } while (0)
225 #else
226 #define sgen_client_wbarrier_generic_nostore_check(ptr)
227 #endif
228
229 static gboolean G_GNUC_UNUSED
230 sgen_client_object_has_critical_finalizer (GCObject *obj)
231 {
232         MonoClass *klass;
233
234         if (!mono_defaults.critical_finalizer_object)
235                 return FALSE;
236
237         klass = SGEN_LOAD_VTABLE (obj)->klass;
238
239         return mono_class_has_parent_fast (klass, mono_defaults.critical_finalizer_object);
240 }
241
242 const char* sgen_client_vtable_get_namespace (GCVTable vtable);
243 const char* sgen_client_vtable_get_name (GCVTable vtable);
244
245 static gboolean G_GNUC_UNUSED
246 sgen_client_bridge_need_processing (void)
247 {
248         return sgen_need_bridge_processing ();
249 }
250
251 static void G_GNUC_UNUSED
252 sgen_client_bridge_reset_data (void)
253 {
254         sgen_bridge_reset_data ();
255 }
256
257 static void G_GNUC_UNUSED
258 sgen_client_bridge_processing_stw_step (void)
259 {
260         sgen_bridge_processing_stw_step ();
261 }
262
263 static void G_GNUC_UNUSED
264 sgen_client_bridge_wait_for_processing (void)
265 {
266         mono_gc_wait_for_bridge_processing ();
267 }
268
269 static void G_GNUC_UNUSED
270 sgen_client_bridge_processing_finish (int generation)
271 {
272         sgen_bridge_processing_finish (generation);
273 }
274
275 static gboolean G_GNUC_UNUSED
276 sgen_client_bridge_is_bridge_object (GCObject *obj)
277 {
278         return sgen_is_bridge_object (obj);
279 }
280
281 static void G_GNUC_UNUSED
282 sgen_client_bridge_register_finalized_object (GCObject *object)
283 {
284         sgen_bridge_register_finalized_object (object);
285 }
286
287 static void G_GNUC_UNUSED
288 sgen_client_binary_protocol_collection_requested (int generation, size_t requested_size, gboolean force)
289 {
290         MONO_GC_REQUESTED (generation, requested_size, force);
291 }
292
293 static void G_GNUC_UNUSED
294 sgen_client_binary_protocol_collection_begin (int minor_gc_count, int generation)
295 {
296         MONO_GC_BEGIN (generation);
297
298         mono_profiler_gc_event (MONO_GC_EVENT_START, generation);
299
300 #ifndef DISABLE_PERFCOUNTERS
301         if (generation == GENERATION_NURSERY)
302                 mono_perfcounters->gc_collections0++;
303         else
304                 mono_perfcounters->gc_collections1++;
305 #endif
306 }
307
308 static void G_GNUC_UNUSED
309 sgen_client_binary_protocol_collection_end (int minor_gc_count, int generation, long long num_objects_scanned, long long num_unique_objects_scanned)
310 {
311         MONO_GC_END (generation);
312
313         mono_profiler_gc_event (MONO_GC_EVENT_END, generation);
314 }
315
316 static void G_GNUC_UNUSED
317 sgen_client_binary_protocol_concurrent_start (void)
318 {
319         MONO_GC_CONCURRENT_START_BEGIN (GENERATION_OLD);
320 }
321
322 static void G_GNUC_UNUSED
323 sgen_client_binary_protocol_concurrent_update (void)
324 {
325         MONO_GC_CONCURRENT_UPDATE_FINISH_BEGIN (GENERATION_OLD, sgen_get_major_collector ()->get_and_reset_num_major_objects_marked ());
326 }
327
328 static void G_GNUC_UNUSED
329 sgen_client_binary_protocol_concurrent_finish (void)
330 {
331         MONO_GC_CONCURRENT_UPDATE_FINISH_BEGIN (GENERATION_OLD, sgen_get_major_collector ()->get_and_reset_num_major_objects_marked ());
332 }
333
334 static void G_GNUC_UNUSED
335 sgen_client_binary_protocol_sweep_begin (int generation, int full_sweep)
336 {
337         MONO_GC_SWEEP_BEGIN (generation, full_sweep);
338 }
339
340 static void G_GNUC_UNUSED
341 sgen_client_binary_protocol_sweep_end (int generation, int full_sweep)
342 {
343         MONO_GC_SWEEP_END (generation, full_sweep);
344 }
345
346 static void G_GNUC_UNUSED
347 sgen_client_binary_protocol_world_stopping (int generation, long long timestamp, gpointer thread)
348 {
349         MONO_GC_WORLD_STOP_BEGIN ();
350
351         mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
352 }
353
354 static void G_GNUC_UNUSED
355 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)
356 {
357         MONO_GC_WORLD_STOP_END ();
358
359         mono_profiler_gc_event (MONO_GC_EVENT_POST_STOP_WORLD, generation);
360 }
361
362 static void G_GNUC_UNUSED
363 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)
364 {
365         MONO_GC_WORLD_RESTART_BEGIN (generation);
366
367         mono_profiler_gc_event (MONO_GC_EVENT_PRE_START_WORLD, generation);
368 }
369
370 static void G_GNUC_UNUSED
371 sgen_client_binary_protocol_world_restarted (int generation, long long timestamp)
372 {
373         MONO_GC_WORLD_RESTART_END (generation);
374
375         mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation);
376 }
377
378 static void G_GNUC_UNUSED
379 sgen_client_binary_protocol_block_alloc (gpointer addr, size_t size)
380 {
381 }
382
383 static void G_GNUC_UNUSED
384 sgen_client_binary_protocol_block_free (gpointer addr, size_t size)
385 {
386 }
387
388 static void G_GNUC_UNUSED
389 sgen_client_binary_protocol_block_set_state (gpointer addr, size_t size, int old, int new_)
390 {
391 }
392
393 static void G_GNUC_UNUSED
394 sgen_client_binary_protocol_mark_start (int generation)
395 {
396         mono_profiler_gc_event (MONO_GC_EVENT_MARK_START, generation);
397 }
398
399 static void G_GNUC_UNUSED
400 sgen_client_binary_protocol_mark_end (int generation)
401 {
402         mono_profiler_gc_event (MONO_GC_EVENT_MARK_END, generation);
403 }
404
405 static void G_GNUC_UNUSED
406 sgen_client_binary_protocol_reclaim_start (int generation)
407 {
408         mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_START, generation);
409 }
410
411 static void G_GNUC_UNUSED
412 sgen_client_binary_protocol_reclaim_end (int generation)
413 {
414         mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_END, generation);
415 }
416
417 static void
418 mono_binary_protocol_alloc_generic (gpointer obj, gpointer vtable, size_t size, gboolean pinned)
419 {
420 #ifdef ENABLE_DTRACE
421         const char *namespace = sgen_client_vtable_get_namespace (vtable);
422         const char *name = sgen_client_vtable_get_name (vtable);
423
424         if (sgen_ptr_in_nursery (obj)) {
425                 if (G_UNLIKELY (MONO_GC_NURSERY_OBJ_ALLOC_ENABLED ()))
426                         MONO_GC_NURSERY_OBJ_ALLOC ((mword)obj, size, namespace, name);
427         } else {
428                 if (size > SGEN_MAX_SMALL_OBJ_SIZE) {
429                         if (G_UNLIKELY (MONO_GC_MAJOR_OBJ_ALLOC_LARGE_ENABLED ()))
430                                 MONO_GC_MAJOR_OBJ_ALLOC_LARGE ((mword)obj, size, namespace, name);
431                 } else if (pinned) {
432                         MONO_GC_MAJOR_OBJ_ALLOC_PINNED ((mword)obj, size, namespace, name);
433                 }
434         }
435 #endif
436 }
437
438 static void G_GNUC_UNUSED
439 sgen_client_binary_protocol_alloc (gpointer obj, gpointer vtable, size_t size, gpointer provenance)
440 {
441         mono_binary_protocol_alloc_generic (obj, vtable, size, FALSE);
442 }
443
444 static void G_GNUC_UNUSED
445 sgen_client_binary_protocol_alloc_pinned (gpointer obj, gpointer vtable, size_t size, gpointer provenance)
446 {
447         mono_binary_protocol_alloc_generic (obj, vtable, size, TRUE);
448 }
449
450 static void G_GNUC_UNUSED
451 sgen_client_binary_protocol_alloc_degraded (gpointer obj, gpointer vtable, size_t size, gpointer provenance)
452 {
453         MONO_GC_MAJOR_OBJ_ALLOC_DEGRADED ((mword)obj, size, sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable));
454 }
455
456 static void G_GNUC_UNUSED
457 sgen_client_binary_protocol_card_scan (gpointer start, size_t size)
458 {
459 }
460
461 static void G_GNUC_UNUSED
462 sgen_client_binary_protocol_pin_stage (gpointer addr_ptr, gpointer addr)
463 {
464 }
465
466 static void G_GNUC_UNUSED
467 sgen_client_binary_protocol_cement_stage (gpointer addr)
468 {
469 }
470
471 static void G_GNUC_UNUSED
472 sgen_client_binary_protocol_pin (gpointer obj, gpointer vtable, size_t size)
473 {
474 #ifdef ENABLE_DTRACE
475         if (G_UNLIKELY (MONO_GC_OBJ_PINNED_ENABLED ())) {
476                 int gen = sgen_ptr_in_nursery (obj) ? GENERATION_NURSERY : GENERATION_OLD;
477                 MONO_GC_OBJ_PINNED ((mword)obj,
478                                 sgen_safe_object_get_size (obj),
479                                 sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable), gen);
480         }
481 #endif
482 }
483
484 static void G_GNUC_UNUSED
485 sgen_client_binary_protocol_mark (gpointer obj, gpointer vtable, size_t size)
486 {
487 }
488
489 static void G_GNUC_UNUSED
490 sgen_client_binary_protocol_scan_begin (gpointer obj, gpointer vtable, size_t size)
491 {
492 }
493
494 static void G_GNUC_UNUSED
495 sgen_client_binary_protocol_scan_vtype_begin (gpointer obj, size_t size)
496 {
497 }
498
499 static void G_GNUC_UNUSED
500 sgen_client_binary_protocol_scan_process_reference (gpointer obj, gpointer ptr, gpointer value)
501 {
502 }
503
504 static void G_GNUC_UNUSED
505 sgen_client_binary_protocol_scan_stack (gpointer thread, gpointer stack_start, gpointer stack_end, int skip_reason)
506 {
507 }
508
509 static void G_GNUC_UNUSED
510 sgen_client_binary_protocol_wbarrier (gpointer ptr, gpointer value, gpointer value_vtable)
511 {
512 }
513
514 static void G_GNUC_UNUSED
515 sgen_client_binary_protocol_cement (gpointer ptr, gpointer vtable, size_t size)
516 {
517 #ifdef ENABLE_DTRACE
518         if (G_UNLIKELY (MONO_GC_OBJ_CEMENTED_ENABLED())) {
519                 MONO_GC_OBJ_CEMENTED ((mword)ptr, sgen_safe_object_get_size ((GCObject*)ptr),
520                                 sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable));
521         }
522 #endif
523 }
524
525 static void G_GNUC_UNUSED
526 sgen_client_binary_protocol_copy (gpointer from, gpointer to, gpointer vtable, size_t size)
527 {
528 #ifdef ENABLE_DTRACE
529         if (G_UNLIKELY (MONO_GC_OBJ_MOVED_ENABLED ())) {
530                 int dest_gen = sgen_ptr_in_nursery (to) ? GENERATION_NURSERY : GENERATION_OLD;
531                 int src_gen = sgen_ptr_in_nursery (from) ? GENERATION_NURSERY : GENERATION_OLD;
532                 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));
533         }
534 #endif
535 }
536
537 static void G_GNUC_UNUSED
538 sgen_client_binary_protocol_global_remset (gpointer ptr, gpointer value, gpointer value_vtable)
539 {
540 #ifdef ENABLE_DTRACE
541         if (G_UNLIKELY (MONO_GC_GLOBAL_REMSET_ADD_ENABLED ())) {
542                 MONO_GC_GLOBAL_REMSET_ADD ((mword)ptr, (mword)value, sgen_safe_object_get_size (value),
543                                 sgen_client_vtable_get_namespace (value_vtable), sgen_client_vtable_get_name (value_vtable));
544         }
545 #endif
546 }
547
548 static void G_GNUC_UNUSED
549 sgen_client_binary_protocol_mod_union_remset (gpointer obj, gpointer ptr, gpointer value, gpointer value_vtable)
550 {
551 }
552
553 static void G_GNUC_UNUSED
554 sgen_client_binary_protocol_ptr_update (gpointer ptr, gpointer old_value, gpointer new_value, gpointer vtable, size_t size)
555 {
556 }
557
558 static void G_GNUC_UNUSED
559 sgen_client_binary_protocol_cleanup (gpointer ptr, gpointer vtable, size_t size)
560 {
561 }
562
563 static void G_GNUC_UNUSED
564 sgen_client_binary_protocol_dislink_add (gpointer link, gpointer obj, gboolean track)
565 {
566 }
567
568 static void G_GNUC_UNUSED
569 sgen_client_binary_protocol_dislink_update (gpointer link, gpointer obj, gboolean track)
570 {
571 #ifdef ENABLE_DTRACE
572         if (MONO_GC_WEAK_UPDATE_ENABLED ()) {
573                 GCVTable vt = obj ? SGEN_LOAD_VTABLE (obj) : NULL;
574                 MONO_GC_WEAK_UPDATE ((mword)link,
575                                 (mword)obj,
576                                 obj ? (mword)sgen_safe_object_get_size (obj) : (mword)0,
577                                 obj ? sgen_client_vtable_get_namespace (vt) : NULL,
578                                 obj ? sgen_client_vtable_get_name (vt) : NULL,
579                                 track ? 1 : 0);
580         }
581 #endif
582 }
583
584 static void G_GNUC_UNUSED
585 sgen_client_binary_protocol_dislink_remove (gpointer link, gboolean track)
586 {
587 }
588
589 static void G_GNUC_UNUSED
590 sgen_client_binary_protocol_empty (gpointer start, size_t size)
591 {
592         if (sgen_ptr_in_nursery (start))
593                 MONO_GC_NURSERY_SWEPT ((mword)start, size);
594         else
595                 MONO_GC_MAJOR_SWEPT ((mword)start, size);
596 }
597
598 static void G_GNUC_UNUSED
599 sgen_client_binary_protocol_thread_suspend (gpointer thread, gpointer stopped_ip)
600 {
601 }
602
603 static void G_GNUC_UNUSED
604 sgen_client_binary_protocol_thread_restart (gpointer thread)
605 {
606 }
607
608 static void G_GNUC_UNUSED
609 sgen_client_binary_protocol_thread_register (gpointer thread)
610 {
611 }
612
613 static void G_GNUC_UNUSED
614 sgen_client_binary_protocol_thread_unregister (gpointer thread)
615 {
616 }
617
618 static void G_GNUC_UNUSED
619 sgen_client_binary_protocol_missing_remset (gpointer obj, gpointer obj_vtable, int offset, gpointer value, gpointer value_vtable, gboolean value_pinned)
620 {
621 }
622
623 static void G_GNUC_UNUSED
624 sgen_client_binary_protocol_cement_reset (void)
625 {
626 }
627
628 static void G_GNUC_UNUSED
629 sgen_client_binary_protocol_domain_unload_begin (gpointer domain)
630 {
631 }
632
633 static void G_GNUC_UNUSED
634 sgen_client_binary_protocol_domain_unload_end (gpointer domain)
635 {
636 }
637
638 static void G_GNUC_UNUSED
639 sgen_client_binary_protocol_gray_enqueue (gpointer queue, gpointer cursor, gpointer value)
640 {
641 }
642
643 static void G_GNUC_UNUSED
644 sgen_client_binary_protocol_gray_dequeue (gpointer queue, gpointer cursor, gpointer value)
645 {
646 }
647
648 static void G_GNUC_UNUSED
649 sgen_client_binary_protocol_major_card_table_scan_start (long long timestamp, gboolean mod_union)
650 {
651 }
652
653 static void G_GNUC_UNUSED
654 sgen_client_binary_protocol_major_card_table_scan_end (long long timestamp, gboolean mod_union)
655 {
656 }
657
658 static void G_GNUC_UNUSED
659 sgen_client_binary_protocol_los_card_table_scan_start (long long timestamp, gboolean mod_union)
660 {
661 }
662
663 static void G_GNUC_UNUSED
664 sgen_client_binary_protocol_los_card_table_scan_end (long long timestamp, gboolean mod_union)
665 {
666 }
667
668 static void G_GNUC_UNUSED
669 sgen_client_binary_protocol_finish_gray_stack_start (long long timestamp, int generation)
670 {
671 }
672
673 static void G_GNUC_UNUSED
674 sgen_client_binary_protocol_finish_gray_stack_end (long long timestamp, int generation)
675 {
676 }
677
678 static void G_GNUC_UNUSED
679 sgen_client_binary_protocol_worker_finish (long long timestamp, gboolean forced)
680 {
681 }
682
683 static void G_GNUC_UNUSED
684 sgen_client_binary_protocol_evacuating_blocks (size_t block_size)
685 {
686 }
687
688 static void G_GNUC_UNUSED
689 sgen_client_binary_protocol_concurrent_sweep_end (long long timestamp)
690 {
691 }
692
693 static void G_GNUC_UNUSED
694 sgen_client_binary_protocol_header (long long check, int version, int ptr_size, gboolean little_endian)
695 {
696 }
697
698 static void G_GNUC_UNUSED
699 sgen_client_binary_protocol_pin_stats (int objects_pinned_in_nursery, size_t bytes_pinned_in_nursery, int objects_pinned_in_major, size_t bytes_pinned_in_major)
700 {
701 }
702
703 int sgen_thread_handshake (BOOL suspend);
704 gboolean sgen_suspend_thread (SgenThreadInfo *info);
705 gboolean sgen_resume_thread (SgenThreadInfo *info);
706 void sgen_wait_for_suspend_ack (int count);
707
708 #ifdef HAVE_KW_THREAD
709 extern __thread SgenThreadInfo *sgen_thread_info;
710 #define TLAB_ACCESS_INIT
711 #define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
712 #else
713 extern MonoNativeTlsKey thread_info_key;
714 #define TLAB_ACCESS_INIT        SgenThreadInfo *__thread_info__ = mono_native_tls_get_value (thread_info_key)
715 #define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
716 #endif
717
718 #ifdef HAVE_KW_THREAD
719 #define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
720 #else
721 #define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
722 #endif
723
724 /* Enter must be visible before anything is done in the critical region. */
725 #define ENTER_CRITICAL_REGION do { mono_atomic_store_acquire (&IN_CRITICAL_REGION, 1); } while (0)
726
727 /* Exit must make sure all critical regions stores are visible before it signal the end of the region. 
728  * We don't need to emit a full barrier since we
729  */
730 #define EXIT_CRITICAL_REGION  do { mono_atomic_store_release (&IN_CRITICAL_REGION, 0); } while (0)
731
732 #ifndef DISABLE_CRITICAL_REGION
733 /*
734  * We can only use a critical region in the managed allocator if the JIT supports OP_ATOMIC_STORE_I4.
735  *
736  * TODO: Query the JIT instead of this ifdef hack.
737  */
738 #if defined (TARGET_X86) || defined (TARGET_AMD64) || (defined (TARGET_ARM) && defined (HAVE_ARMV7)) || defined (TARGET_ARM64)
739 #define MANAGED_ALLOCATOR_CAN_USE_CRITICAL_REGION
740 #endif
741 #endif
742
743 #define SGEN_TV_DECLARE(name) gint64 name
744 #define SGEN_TV_GETTIME(tv) tv = mono_100ns_ticks ()
745 #define SGEN_TV_ELAPSED(start,end) ((gint64)(end-start))
746
747 guint64 mono_time_since_last_stw (void);
748
749 typedef MonoSemType SgenSemaphore;
750
751 #define SGEN_SEMAPHORE_INIT(sem,initial)        mono_os_sem_init ((sem), (initial))
752 #define SGEN_SEMAPHORE_POST(sem)                mono_os_sem_post ((sem))
753 #define SGEN_SEMAPHORE_WAIT(sem)                mono_os_sem_wait ((sem), MONO_SEM_FLAGS_NONE)
754
755 gboolean sgen_has_critical_method (void);
756 gboolean sgen_is_critical_method (MonoMethod *method);
757
758 void sgen_set_use_managed_allocator (gboolean flag);
759 gboolean sgen_is_managed_allocator (MonoMethod *method);
760 gboolean sgen_has_managed_allocator (void);
761
762 void sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type);
763 void sgen_null_links_for_domain (MonoDomain *domain);
764
765 #endif