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