#include "sgen/sgen-client.h"
#include "sgen/sgen-cardtable.h"
#include "sgen/sgen-pinning.h"
-#include "sgen/sgen-thread-pool.h"
+#include "sgen/sgen-workers.h"
#include "metadata/marshal.h"
#include "metadata/method-builder.h"
#include "metadata/abi-details.h"
gpointer stack_start = &stack_start;
SgenThreadInfo *info = mono_thread_info_current ();
- if (ptr >= stack_start && ptr < (gpointer)info->client_info.stack_end)
+ if (ptr >= stack_start && ptr < (gpointer)info->client_info.info.stack_end)
return TRUE;
return FALSE;
}
}
void
-mono_gc_wbarrier_value_copy_bitmap (gpointer _dest, gpointer _src, int size, unsigned bitmap)
+mono_gc_wbarrier_range_copy (gpointer _dest, gpointer _src, int size)
{
- sgen_wbarrier_value_copy_bitmap (_dest, _src, size, bitmap);
+ sgen_wbarrier_range_copy (_dest, _src, size);
+}
+
+void*
+mono_gc_get_range_copy_func (void)
+{
+ return sgen_get_remset ()->wbarrier_range_copy;
}
int
return sgen_has_managed_allocator ();
}
-static gboolean
-ip_in_critical_region (MonoDomain *domain, gpointer ip)
-{
- MonoJitInfo *ji;
- MonoMethod *method;
-
- /*
- * We pass false for 'try_aot' so this becomes async safe.
- * It won't find aot methods whose jit info is not yet loaded,
- * so we preload their jit info in the JIT.
- */
- ji = mono_jit_info_table_find_internal (domain, ip, FALSE, FALSE);
- if (!ji)
- return FALSE;
-
- method = mono_jit_info_get_method (ji);
-
- return mono_runtime_is_critical_method (method) || sgen_is_critical_method (method);
-}
-
gboolean
mono_gc_is_critical_method (MonoMethod *method)
{
return sgen_is_critical_method (method);
}
-#ifndef DISABLE_JIT
+#ifdef ENABLE_ILGEN
static void
emit_nursery_check (MonoMethodBuilder *mb, int *nursery_check_return_labels, gboolean is_concurrent)
else
mb = mono_mb_new (mono_defaults.object_class, "wbarrier_noconc", MONO_WRAPPER_WRITE_BARRIER);
-#ifndef DISABLE_JIT
+#ifdef ENABLE_ILGEN
#ifdef MANAGED_WBARRIER
emit_nursery_check (mb, nursery_check_labels, is_concurrent);
/*
sgen_clear_nursery_fragments ();
+ FOREACH_THREAD (info) {
+ mono_handle_stack_free_domain ((HandleStack*)info->client_info.info.handle_stack, domain);
+ } FOREACH_THREAD_END
+
if (sgen_mono_xdomain_checks && domain != mono_get_root_domain ()) {
sgen_scan_for_registered_roots_in_domain (domain, ROOT_TYPE_NORMAL);
sgen_scan_for_registered_roots_in_domain (domain, ROOT_TYPE_WBARRIER);
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_ALLOC);
-#ifndef DISABLE_JIT
+#ifdef ENABLE_ILGEN
if (slowpath) {
switch (atype) {
case ATYPE_NORMAL:
info->d.alloc.gc_name = "sgen";
info->d.alloc.alloc_type = atype;
-#ifndef DISABLE_JIT
+#ifdef ENABLE_ILGEN
mb->init_locals = FALSE;
#endif
* lock-free data structure for the queue as multiple threads will be
* adding to it at the same time.
*/
- if (sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ())) {
+ if (sgen_workers_is_worker_thread (mono_native_thread_id_get ())) {
sgen_pointer_queue_add (&moved_objects_queue, obj);
sgen_pointer_queue_add (&moved_objects_queue, destination);
} else {
return &gc_callbacks;
}
-void
-sgen_client_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback)
+gpointer
+mono_gc_thread_attach (SgenThreadInfo *info)
{
- size_t stsize = 0;
- guint8 *staddr = NULL;
+ return sgen_thread_attach (info);
+}
+void
+sgen_client_thread_attach (SgenThreadInfo* info)
+{
mono_tls_set_sgen_thread_info (info);
info->client_info.skip = 0;
info->client_info.signal = 0;
#endif
- mono_thread_info_get_stack_bounds (&staddr, &stsize);
- if (staddr) {
- info->client_info.stack_start_limit = staddr;
- info->client_info.stack_end = staddr + stsize;
- } else {
- gsize stack_bottom = (gsize)stack_bottom_fallback;
- stack_bottom += 4095;
- stack_bottom &= ~4095;
- info->client_info.stack_end = (char*)stack_bottom;
- }
-
memset (&info->client_info.ctx, 0, sizeof (MonoContext));
if (mono_gc_get_gc_callbacks ()->thread_attach_func)
binary_protocol_thread_register ((gpointer)mono_thread_info_get_tid (info));
- SGEN_LOG (3, "registered thread %p (%p) stack end %p", info, (gpointer)mono_thread_info_get_tid (info), info->client_info.stack_end);
+ SGEN_LOG (3, "registered thread %p (%p) stack end %p", info, (gpointer)mono_thread_info_get_tid (info), info->client_info.info.stack_end);
info->client_info.info.handle_stack = mono_handle_stack_alloc ();
}
void
-sgen_client_thread_unregister (SgenThreadInfo *p)
+mono_gc_thread_detach_with_lock (SgenThreadInfo *info)
+{
+ return sgen_thread_detach_with_lock (info);
+}
+
+void
+sgen_client_thread_detach_with_lock (SgenThreadInfo *p)
{
MonoNativeThreadId tid;
}
}
-static gboolean
-thread_in_critical_region (SgenThreadInfo *info)
-{
- return info->client_info.in_critical_region;
-}
-
-static void
-sgen_thread_attach (SgenThreadInfo *info)
-{
- if (mono_gc_get_gc_callbacks ()->thread_attach_func && !info->client_info.runtime_data)
- info->client_info.runtime_data = mono_gc_get_gc_callbacks ()->thread_attach_func ();
-}
-
-static void
-sgen_thread_detach (SgenThreadInfo *p)
-{
- /* If a delegate is passed to native code and invoked on a thread we dont
- * know about, marshal will register it with mono_threads_attach_coop, but
- * we have no way of knowing when that thread goes away. SGen has a TSD
- * so we assume that if the domain is still registered, we can detach
- * the thread
- */
- if (mono_thread_internal_current_is_attached ())
- mono_thread_detach_internal (mono_thread_internal_current ());
-}
-
-/**
- * mono_gc_register_thread:
- */
gboolean
-mono_gc_register_thread (void *baseptr)
+mono_gc_thread_in_critical_region (SgenThreadInfo *info)
{
- return mono_thread_info_attach (baseptr) != NULL;
+ return info->client_info.in_critical_region;
}
/**
void *aligned_stack_start;
if (info->client_info.skip) {
- SGEN_LOG (3, "Skipping dead thread %p, range: %p-%p, size: %zd", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start);
+ SGEN_LOG (3, "Skipping dead thread %p, range: %p-%p, size: %zd", info, info->client_info.stack_start, info->client_info.info.stack_end, (char*)info->client_info.info.stack_end - (char*)info->client_info.stack_start);
skip_reason = 1;
} else if (info->client_info.gc_disabled) {
- SGEN_LOG (3, "GC disabled for thread %p, range: %p-%p, size: %zd", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start);
+ SGEN_LOG (3, "GC disabled for thread %p, range: %p-%p, size: %zd", info, info->client_info.stack_start, info->client_info.info.stack_end, (char*)info->client_info.info.stack_end - (char*)info->client_info.stack_start);
skip_reason = 2;
} else if (!mono_thread_info_is_live (info)) {
- SGEN_LOG (3, "Skipping non-running thread %p, range: %p-%p, size: %zd (state %x)", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start, info->client_info.info.thread_state);
+ SGEN_LOG (3, "Skipping non-running thread %p, range: %p-%p, size: %zd (state %x)", info, info->client_info.stack_start, info->client_info.info.stack_end, (char*)info->client_info.info.stack_end - (char*)info->client_info.stack_start, info->client_info.info.thread_state);
skip_reason = 3;
} else if (!info->client_info.stack_start) {
SGEN_LOG (3, "Skipping starting or detaching thread %p", info);
skip_reason = 4;
}
- binary_protocol_scan_stack ((gpointer)mono_thread_info_get_tid (info), info->client_info.stack_start, info->client_info.stack_end, skip_reason);
+ binary_protocol_scan_stack ((gpointer)mono_thread_info_get_tid (info), info->client_info.stack_start, info->client_info.info.stack_end, skip_reason);
if (skip_reason) {
if (precise) {
}
g_assert (info->client_info.stack_start);
- g_assert (info->client_info.stack_end);
+ g_assert (info->client_info.info.stack_end);
aligned_stack_start = (void*)(mword) ALIGN_TO ((mword)info->client_info.stack_start, SIZEOF_VOID_P);
#ifdef HOST_WIN32
#endif
g_assert (info->client_info.suspend_done);
- SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %zd, pinned=%zd", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start, sgen_get_pinned_count ());
+ SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %zd, pinned=%zd", info, info->client_info.stack_start, info->client_info.info.stack_end, (char*)info->client_info.info.stack_end - (char*)info->client_info.stack_start, sgen_get_pinned_count ());
if (mono_gc_get_gc_callbacks ()->thread_mark_func && !conservative_stack_mark) {
- mono_gc_get_gc_callbacks ()->thread_mark_func (info->client_info.runtime_data, (guint8 *)aligned_stack_start, (guint8 *)info->client_info.stack_end, precise, &ctx);
+ mono_gc_get_gc_callbacks ()->thread_mark_func (info->client_info.runtime_data, (guint8 *)aligned_stack_start, (guint8 *)info->client_info.info.stack_end, precise, &ctx);
} else if (!precise) {
if (!conservative_stack_mark) {
fprintf (stderr, "Precise stack mark not supported - disabling.\n");
conservative_stack_mark = TRUE;
}
//FIXME we should eventually use the new stack_mark from coop
- sgen_conservatively_pin_objects_from ((void **)aligned_stack_start, (void **)info->client_info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
+ sgen_conservatively_pin_objects_from ((void **)aligned_stack_start, (void **)info->client_info.info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
}
if (!precise) {
{
// This is used on Coop GC for platforms where we cannot get the data for individual registers.
// We force a spill of all registers into the stack and pass a chunk of data into sgen.
- //FIXME under coop, for now, what we need to ensure is that we scan any extra memory from info->client_info.stack_end to stack_mark
+ //FIXME under coop, for now, what we need to ensure is that we scan any extra memory from info->client_info.info.stack_end to stack_mark
MonoThreadUnwindState *state = &info->client_info.info.thread_saved_state [SELF_SUSPEND_STATE_INDEX];
if (state && state->gc_stackdata) {
sgen_conservatively_pin_objects_from ((void **)state->gc_stackdata, (void**)((char*)state->gc_stackdata + state->gc_stackdata_size),
LOCK_GC;
info = mono_thread_info_current ();
if (info) {
- SGEN_ASSERT (0, stack_end < info->client_info.stack_end, "Can only lower stack end");
- info->client_info.stack_end = stack_end;
+ SGEN_ASSERT (0, stack_end < info->client_info.info.stack_end, "Can only lower stack end");
+ info->client_info.info.stack_end = stack_end;
}
UNLOCK_GC;
}
mono_gc_get_nursery (int *shift_bits, size_t *size)
{
*size = sgen_nursery_size;
- *shift_bits = DEFAULT_NURSERY_BITS;
+ *shift_bits = sgen_nursery_bits;
return sgen_get_nursery_start ();
}
void
sgen_client_init (void)
{
- int dummy;
- MonoThreadInfoCallbacks cb;
-
- cb.thread_register = sgen_thread_register;
- cb.thread_detach = sgen_thread_detach;
- cb.thread_unregister = sgen_thread_unregister;
- cb.thread_attach = sgen_thread_attach;
- cb.mono_thread_in_critical_region = thread_in_critical_region;
- cb.ip_in_critical_region = ip_in_critical_region;
-
- mono_threads_init (&cb, sizeof (SgenThreadInfo));
+ mono_thread_callbacks_init ();
+ mono_thread_info_init (sizeof (SgenThreadInfo));
///* Keep this the default for now */
/* Precise marking is broken on all supported targets. Disable until fixed. */
mono_tls_init_gc_keys ();
- mono_gc_register_thread (&dummy);
+ mono_thread_info_attach ();
}
gboolean
void
mono_gc_base_cleanup (void)
{
- sgen_thread_pool_shutdown ();
+ sgen_thread_pool_shutdown (major_collector.get_sweep_pool ());
+
+ sgen_workers_shutdown ();
// We should have consumed any outstanding moves.
g_assert (sgen_pointer_queue_is_empty (&moved_objects_queue));