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