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