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