[threads] Store MonoInternalThread in MonoThreadInfo for use when detaching (#5058)
[mono.git] / mono / metadata / sgen-mono.c
index fc379e52a8f47636618fea8f16a5cc35e64192f2..0264158494f283930fde29f68eb244fa42adaf34 100644 (file)
@@ -72,7 +72,7 @@ ptr_on_stack (void *ptr)
        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;
 }
@@ -219,33 +219,13 @@ sgen_has_critical_method (void)
        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)
@@ -317,7 +297,7 @@ mono_gc_get_specific_write_barrier (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);
        /*
@@ -893,6 +873,10 @@ mono_gc_clear_domain (MonoDomain * domain)
 
        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);
@@ -1122,7 +1106,7 @@ create_allocator (int atype, ManagedAllocatorVariant variant)
 
        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:
@@ -1457,7 +1441,7 @@ create_allocator (int atype, ManagedAllocatorVariant variant)
        info->d.alloc.gc_name = "sgen";
        info->d.alloc.alloc_type = atype;
 
-#ifndef DISABLE_JIT
+#ifdef ENABLE_ILGEN
        mb->init_locals = FALSE;
 #endif
 
@@ -2204,12 +2188,15 @@ mono_gc_get_gc_callbacks ()
        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;
@@ -2221,17 +2208,6 @@ sgen_client_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback)
        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)
@@ -2239,13 +2215,19 @@ sgen_client_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback)
 
        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;
 
@@ -2287,39 +2269,10 @@ mono_gc_set_skip_thread (gboolean skip)
        }
 }
 
-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;
 }
 
 /**
@@ -2389,20 +2342,20 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
                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) {
@@ -2417,7 +2370,7 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
                }
 
                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
@@ -2437,16 +2390,16 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
 #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) {
@@ -2456,7 +2409,7 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
                        {
                                // 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),
@@ -2497,8 +2450,8 @@ mono_gc_set_stack_end (void *stack_end)
        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;
 }
@@ -2665,7 +2618,7 @@ void*
 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 ();
 }
 
@@ -2883,17 +2836,8 @@ sgen_client_vtable_get_name (MonoVTable *vt)
 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. */
@@ -2905,7 +2849,7 @@ sgen_client_init (void)
 
        mono_tls_init_gc_keys ();
 
-       mono_gc_register_thread (&dummy);
+       mono_thread_info_attach ();
 }
 
 gboolean