[coop] Generate native-to-managed thread attaching in marshal
authorLudovic Henry <ludovic@xamarin.com>
Wed, 18 May 2016 22:00:56 +0000 (18:00 -0400)
committerLudovic Henry <ludovic@xamarin.com>
Thu, 19 May 2016 15:31:11 +0000 (11:31 -0400)
mono/cil/cil-opcodes.xml
mono/cil/opcode.def
mono/metadata/marshal.c
mono/metadata/sgen-mono.c
mono/metadata/threads-types.h
mono/metadata/threads.c
mono/mini/debugger-agent.c
mono/mini/method-to-ir.c
mono/mini/mini-runtime.c

index a86b2be374115316ab024a42aec3dcc8d91de75a..6cf7a6ee4849095e487731d457a148da72f361af 100644 (file)
 <opcode name="mono_ldptr_nursery_start" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x16" flow="next" />
 <opcode name="mono_ldptr_nursery_bits" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x17" flow="next" />
 <opcode name="mono_calli_extra_arg" input="VarPop" output="VarPush" args="InlineSig" o1="0xF0" o2="0x18" flow="call" />
+<opcode name="mono_lddomain" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x19" flow="next" />
 </opdesc>
index ad89c95e46c2245750c5c2d275fcce1c671f12ab..620289b0595658678f712e042e0a1ccde5f23e84 100644 (file)
@@ -317,6 +317,7 @@ OPDEF(CEE_MONO_LDPTR_CARD_TABLE, "mono_ldptr_card_table", Pop0, PushI, InlineNon
 OPDEF(CEE_MONO_LDPTR_NURSERY_START, "mono_ldptr_nursery_start", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x16, NEXT)
 OPDEF(CEE_MONO_LDPTR_NURSERY_BITS, "mono_ldptr_nursery_bits", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x17, NEXT)
 OPDEF(CEE_MONO_CALLI_EXTRA_ARG, "mono_calli_extra_arg", VarPop, VarPush, InlineSig, X, 2, 0xF0, 0x18, CALL)
+OPDEF(CEE_MONO_LDDOMAIN, "mono_lddomain", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x19, NEXT)
 #ifndef OPALIAS
 #define _MONO_CIL_OPALIAS_DEFINED_
 #define OPALIAS(a,s,r)
index 3ef72af387fa55637032d48c9cb68254bc785a7e..c70ec10261d08e43e017f6926023f2d280e8a6cb 100644 (file)
@@ -326,6 +326,8 @@ mono_marshal_init (void)
                register_icall (mono_marshal_ftnptr_eh_callback, "mono_marshal_ftnptr_eh_callback", "void uint32", TRUE);
                register_icall (mono_threads_enter_gc_safe_region_unbalanced, "mono_threads_enter_gc_safe_region_unbalanced", "ptr ptr", TRUE);
                register_icall (mono_threads_exit_gc_safe_region_unbalanced, "mono_threads_exit_gc_safe_region_unbalanced", "void ptr ptr", TRUE);
+               register_icall (mono_threads_attach_coop, "mono_threads_attach_coop", "ptr ptr ptr", TRUE);
+               register_icall (mono_threads_detach_coop, "mono_threads_detach_coop", "void ptr ptr", TRUE);
 
                mono_cominterop_init ();
                mono_remoting_init ();
@@ -7955,7 +7957,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
 #else
        MonoMethodSignature *sig, *csig;
        MonoExceptionClause *clauses, *clause_finally, *clause_catch;
-       int i, *tmp_locals, ex_local, e_local;
+       int i, *tmp_locals, ex_local, e_local, attach_cookie_local, attach_dummy_local;
        int leave_try_pos, leave_catch_pos, ex_m1_pos;
        gboolean closed = FALSE;
 
@@ -7990,10 +7992,14 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        ex_local = mono_mb_add_local (mb, &mono_defaults.uint32_class->byval_arg);
        e_local = mono_mb_add_local (mb, &mono_defaults.exception_class->byval_arg);
 
+       attach_cookie_local = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+       attach_dummy_local = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+
        /*
         * guint32 ex = -1;
         * try {
-        *   mono_jit_attach ();
+        *   // does (STARTING|RUNNING|BLOCKING) -> RUNNING + set/switch domain
+        *   mono_threads_attach_coop ();
         *
         *   <interrupt check>
         *
@@ -8001,7 +8007,8 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
         * } catch (Exception e) {
         *   ex = mono_gchandle_new (e, false);
         * } finally {
-        *   mono_jit_detach ();
+        *   // does RUNNING -> (RUNNING|BLOCKING) + unset/switch domain
+        *   mono_threads_detach_coop ();
         *
         *   if (ex != -1)
         *     mono_marshal_ftnptr_eh_callback (ex);
@@ -8029,16 +8036,17 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        /* try { */
        clause_catch->try_offset = clause_finally->try_offset = mono_mb_get_label (mb);
 
-       /*
-        * Might need to attach the thread to the JIT or change the
-        * domain for the callback.
-        *
-        * Also does the (STARTING|BLOCKING|RUNNING) -> RUNNING thread state transtion
-        *
-        * mono_jit_attach ();
-        */
-       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_byte (mb, CEE_MONO_JIT_ATTACH);
+       if (!mono_threads_is_coop_enabled ()) {
+               mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+               mono_mb_emit_byte (mb, CEE_MONO_JIT_ATTACH);
+       } else {
+               /* mono_threads_attach_coop (); */
+               mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+               mono_mb_emit_byte (mb, CEE_MONO_LDDOMAIN);
+               mono_mb_emit_ldloc_addr (mb, attach_dummy_local);
+               mono_mb_emit_icall (mb, mono_threads_attach_coop);
+               mono_mb_emit_stloc (mb, attach_cookie_local);
+       }
 
        /* <interrupt check> */
        emit_thread_interrupt_checkpoint (mb);
@@ -8206,13 +8214,15 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        clause_finally->try_len = mono_mb_get_label (mb) - clause_finally->try_offset;
        clause_finally->handler_offset = mono_mb_get_label (mb);
 
-       /*
-        * Also does the RUNNING -> (BLOCKING|RUNNING) thread state transition
-        *
-        * mono_jit_detach ();
-        */
-       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH);
+       if (!mono_threads_is_coop_enabled ()) {
+               mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+               mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH);
+       } else {
+               /* mono_threads_detach_coop (); */
+               mono_mb_emit_ldloc (mb, attach_cookie_local);
+               mono_mb_emit_ldloc_addr (mb, attach_dummy_local);
+               mono_mb_emit_icall (mb, mono_threads_detach_coop);
+       }
 
        /* if (ex != -1) */
        mono_mb_emit_ldloc (mb, ex_local);
index 644c9ba93cd893c25d3c271d18d1a82bd69cf524..0d567a887ce070bbf54cee3c3c208981e8e5011c 100644 (file)
@@ -2253,7 +2253,7 @@ static void
 sgen_thread_detach (SgenThreadInfo *p)
 {
        /* If a delegate is passed to native code and invoked on a thread we dont
-        * know about, the jit will register it with mono_jit_thread_attach, but
+        * 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
index 9cc43855c299a0f3142330d6a7e264a171f84be8..3face85f7794f472c4cb1a4e93ba1e3d05173911 100644 (file)
@@ -260,4 +260,10 @@ void mono_thread_detach_internal (MonoInternalThread *thread);
 
 void ves_icall_System_Threading_Thread_GetStackTraces (MonoArray **out_threads, MonoArray **out_stack_traces);
 
+MONO_API gpointer
+mono_threads_attach_coop (MonoDomain *domain, gpointer *dummy);
+
+MONO_API void
+mono_threads_detach_coop (gpointer cookie, gpointer *dummy);
+
 #endif /* _MONO_METADATA_THREADS_TYPES_H_ */
index 253e9c32c3f4938dc73ab6b1caf66fca406b2d53..113dcd77a6776865453b488a1aa93fab48c474de 100644 (file)
@@ -41,6 +41,8 @@
 #include <mono/utils/mono-tls.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/mono-memory-model.h>
+#include <mono/utils/mono-threads-coop.h>
+#include <mono/utils/mono-error-internals.h>
 
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/reflection-internals.h>
@@ -5006,3 +5008,103 @@ ves_icall_System_Threading_Thread_GetStackTraces (MonoArray **out_threads, MonoA
 {
        mono_threads_get_thread_dump (out_threads, out_stack_traces);
 }
+
+/*
+ * mono_threads_attach_coop: called by native->managed wrappers
+ *
+ * In non-coop mode:
+ *  - @dummy: is NULL
+ *  - @return: the original domain which needs to be restored, or NULL.
+ *
+ * In coop mode:
+ *  - @dummy: contains the original domain
+ *  - @return: a cookie containing current MonoThreadInfo*.
+ */
+gpointer
+mono_threads_attach_coop (MonoDomain *domain, gpointer *dummy)
+{
+       MonoError error;
+       MonoDomain *orig;
+       gboolean fresh_thread;
+
+       if (!domain) {
+               /* Happens when called from AOTed code which is only used in the root domain. */
+               domain = mono_get_root_domain ();
+       }
+
+       g_assert (domain);
+
+       /* On coop, when we detached, we moved the thread from  RUNNING->BLOCKING.
+        * If we try to reattach we do a BLOCKING->RUNNING transition.  If the thread
+        * is fresh, mono_thread_attach() will do a STARTING->RUNNING transition so
+        * we're only responsible for making the cookie. */
+       if (mono_threads_is_coop_enabled ()) {
+               MonoThreadInfo *info = mono_thread_info_current_unchecked ();
+               fresh_thread = !info || !mono_thread_info_is_live (info);
+       }
+
+       if (!mono_thread_internal_current ()) {
+               mono_thread_attach_full (domain, FALSE, &error);
+               mono_error_assert_ok (&error);
+
+               // #678164
+               mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
+       }
+
+       orig = mono_domain_get ();
+       if (orig != domain)
+               mono_domain_set (domain, TRUE);
+
+       if (!mono_threads_is_coop_enabled ())
+               return orig != domain ? orig : NULL;
+
+       if (fresh_thread) {
+               *dummy = NULL;
+               /* mono_thread_attach put the thread in RUNNING mode from STARTING, but we need to
+                * return the right cookie. */
+               return mono_threads_enter_gc_unsafe_region_cookie (mono_thread_info_current ());
+       } else {
+               *dummy = orig;
+               /* thread state (BLOCKING|RUNNING) -> RUNNING */
+               return mono_threads_enter_gc_unsafe_region (dummy);
+       }
+}
+
+/*
+ * mono_threads_detach_coop: called by native->managed wrappers
+ *
+ * In non-coop mode:
+ *  - @cookie: the original domain which needs to be restored, or NULL.
+ *  - @dummy: is NULL
+ *
+ * In coop mode:
+ *  - @cookie: contains current MonoThreadInfo* if it was in BLOCKING mode, NULL otherwise
+ *  - @dummy: contains the original domain
+ */
+void
+mono_threads_detach_coop (gpointer cookie, gpointer *dummy)
+{
+       MonoDomain *domain, *orig;
+
+       if (!mono_threads_is_coop_enabled ()) {
+               orig = (MonoDomain*) cookie;
+               if (orig)
+                       mono_domain_set (orig, TRUE);
+       } else {
+               orig = (MonoDomain*) *dummy;
+
+               domain = mono_domain_get ();
+               g_assert (domain);
+
+               /* it won't do anything if cookie is NULL
+                * thread state RUNNING -> (RUNNING|BLOCKING) */
+               mono_threads_exit_gc_unsafe_region (cookie, dummy);
+
+               if (orig != domain) {
+                       if (!orig)
+                               mono_domain_unset ();
+                       else
+                               mono_domain_set (orig, TRUE);
+               }
+       }
+}
index e5906b18d89aeee6d1819fd5a1693030d00b9ccd..221aab3d9623ef627a490b71738b44a802afe485 100644 (file)
@@ -9695,18 +9695,17 @@ debugger_thread (void *arg)
        ErrorCode err;
        gboolean no_reply;
        gboolean attach_failed = FALSE;
-       gpointer attach_cookie, attach_dummy;
 
        DEBUG_PRINTF (1, "[dbg] Agent thread started, pid=%p\n", (gpointer) (gsize) mono_native_thread_id_get ());
 
        debugger_thread_id = mono_native_thread_id_get ();
 
-       attach_cookie = mono_jit_thread_attach (mono_get_root_domain (), &attach_dummy);
-       MonoInternalThread *thread = mono_thread_internal_current ();
-       mono_thread_set_name_internal (thread, mono_string_new (mono_get_root_domain (), "Debugger agent"), TRUE, &error);
+       MonoThread *thread = mono_thread_attach (mono_get_root_domain ());
+       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Debugger agent"), TRUE, &error);
        mono_error_assert_ok (&error);
 
-       thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
+       thread->internal_thread->state |= ThreadState_Background;
+       thread->internal_thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
 
        mono_set_is_debugger_attached (TRUE);
        
@@ -9858,8 +9857,6 @@ debugger_thread (void *arg)
                start_debugger_thread ();
        }
 
-       mono_jit_thread_detach (attach_cookie, &attach_dummy);
-
        return 0;
 }
 
index e882bfe5f41a797affcd7e6e57e1a60d8bbea604..bacf754f33a43b94cb4cd215b4b05d6e59b76961 100644 (file)
@@ -12767,54 +12767,48 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MonoInst *ad_ins, *jit_tls_ins;
                                MonoBasicBlock *next_bb = NULL, *call_bb = NULL;
 
+                               g_assert (!mono_threads_is_coop_enabled ());
+
                                cfg->attach_cookie = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
                                cfg->attach_dummy = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
 
-                               if (mono_threads_is_coop_enabled ()) {
-                                       /* AOT code is only used in the root domain */
-                                       EMIT_NEW_PCONST (cfg, args [0], cfg->compile_aot ? NULL : cfg->domain);
-                                       EMIT_NEW_VARLOADA (cfg, args [1], cfg->attach_dummy, cfg->attach_dummy->inst_vtype);
-                                       ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
-                                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->attach_cookie->dreg, ins->dreg);
-                               } else {
-                                       EMIT_NEW_PCONST (cfg, ins, NULL);
-                                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->attach_cookie->dreg, ins->dreg);
+                               EMIT_NEW_PCONST (cfg, ins, NULL);
+                               MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->attach_cookie->dreg, ins->dreg);
 
-                                       ad_ins = mono_get_domain_intrinsic (cfg);
-                                       jit_tls_ins = mono_get_jit_tls_intrinsic (cfg);
+                               ad_ins = mono_get_domain_intrinsic (cfg);
+                               jit_tls_ins = mono_get_jit_tls_intrinsic (cfg);
 
-                                       if (cfg->backend->have_tls_get && ad_ins && jit_tls_ins) {
-                                               NEW_BBLOCK (cfg, next_bb);
-                                               NEW_BBLOCK (cfg, call_bb);
+                               if (cfg->backend->have_tls_get && ad_ins && jit_tls_ins) {
+                                       NEW_BBLOCK (cfg, next_bb);
+                                       NEW_BBLOCK (cfg, call_bb);
 
-                                               if (cfg->compile_aot) {
-                                                       /* AOT code is only used in the root domain */
-                                                       EMIT_NEW_PCONST (cfg, domain_ins, NULL);
-                                               } else {
-                                                       EMIT_NEW_PCONST (cfg, domain_ins, cfg->domain);
-                                               }
-                                               MONO_ADD_INS (cfg->cbb, ad_ins);
-                                               MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, ad_ins->dreg, domain_ins->dreg);
-                                               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, call_bb);
-
-                                               MONO_ADD_INS (cfg->cbb, jit_tls_ins);
-                                               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, jit_tls_ins->dreg, 0);
-                                               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, call_bb);
-
-                                               MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, next_bb);
-                                               MONO_START_BB (cfg, call_bb);
+                                       if (cfg->compile_aot) {
+                                               /* AOT code is only used in the root domain */
+                                               EMIT_NEW_PCONST (cfg, domain_ins, NULL);
+                                       } else {
+                                               EMIT_NEW_PCONST (cfg, domain_ins, cfg->domain);
                                        }
+                                       MONO_ADD_INS (cfg->cbb, ad_ins);
+                                       MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, ad_ins->dreg, domain_ins->dreg);
+                                       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, call_bb);
 
-                                       /* AOT code is only used in the root domain */
-                                       EMIT_NEW_PCONST (cfg, args [0], cfg->compile_aot ? NULL : cfg->domain);
-                                       EMIT_NEW_PCONST (cfg, args [1], NULL);
-                                       ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
-                                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->attach_cookie->dreg, ins->dreg);
+                                       MONO_ADD_INS (cfg->cbb, jit_tls_ins);
+                                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, jit_tls_ins->dreg, 0);
+                                       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, call_bb);
 
-                                       if (next_bb)
-                                               MONO_START_BB (cfg, next_bb);
+                                       MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, next_bb);
+                                       MONO_START_BB (cfg, call_bb);
                                }
 
+                               /* AOT code is only used in the root domain */
+                               EMIT_NEW_PCONST (cfg, args [0], cfg->compile_aot ? NULL : cfg->domain);
+                               EMIT_NEW_PCONST (cfg, args [1], NULL);
+                               ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
+                               MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->attach_cookie->dreg, ins->dreg);
+
+                               if (next_bb)
+                                       MONO_START_BB (cfg, next_bb);
+
                                ip += 2;
                                break;
                        }
@@ -12973,6 +12967,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                constrained_class = NULL;
                                break;
                        }
+                       case CEE_MONO_LDDOMAIN:
+                               CHECK_STACK_OVF (1);
+                               EMIT_NEW_PCONST (cfg, ins, cfg->compile_aot ? NULL : cfg->domain);
+                               ip += 2;
+                               *sp++ = ins;
+                               break;
                        default:
                                g_error ("opcode 0x%02x 0x%02x not handled", MONO_CUSTOM_PREFIX, ip [1]);
                                break;
index a887fc67fe35a0cf3a1b54504398be23050603b6..d35385c64513d3d138fba90de483ea717194da7e 100644 (file)
@@ -839,18 +839,16 @@ mono_set_lmf_addr (gpointer lmf_addr)
 /*
  * mono_jit_thread_attach: called by native->managed wrappers
  *
- * In non-coop mode:
- *  - @dummy: is NULL
- *  - @return: the original domain which needs to be restored, or NULL.
- *
- * In coop mode:
- *  - @dummy: contains the original domain
- *  - @return: a cookie containing current MonoThreadInfo*.
+ * @dummy: is NULL
+ * @return: the original domain which needs to be restored, or NULL.
  */
 gpointer
 mono_jit_thread_attach (MonoDomain *domain, gpointer *dummy)
 {
        MonoDomain *orig;
+       gboolean attached;
+
+       g_assert (!mono_threads_is_coop_enabled ());
 
        if (!domain) {
                /* Happens when called from AOTed code which is only used in the root domain. */
@@ -859,92 +857,42 @@ mono_jit_thread_attach (MonoDomain *domain, gpointer *dummy)
 
        g_assert (domain);
 
-       /* On coop, when we detached, we moved the thread from  RUNNING->BLOCKING.  If we try to
-        * reattach we do a BLOCKING->RUNNING transition.  If the thread is fresh,
-        * mono_thread_attach() will do a STARTING->RUNNING transition so we're only responsible
-        * for making the cookie. */
-       gboolean fresh_thread = FALSE;
-       {
-               MonoThreadInfo *info;
-
-               info = mono_thread_info_current_unchecked ();
-               fresh_thread = !info || !mono_thread_info_is_live (info);
-       }
-       {
-               gboolean attached;
-
 #ifdef MONO_HAVE_FAST_TLS
-               attached = MONO_FAST_TLS_GET (mono_lmf_addr) != NULL;
+       attached = MONO_FAST_TLS_GET (mono_lmf_addr) != NULL;
 #else
-               attached = mono_native_tls_get_value (mono_jit_tls_id) != NULL;
+       attached = mono_native_tls_get_value (mono_jit_tls_id) != NULL;
 #endif
 
-               if (!attached) {
-                       mono_thread_attach (domain);
+       if (!attached) {
+               mono_thread_attach (domain);
 
-                       // #678164
-                       mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
-               }
+               // #678164
+               mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
+       }
 
-               orig = mono_domain_get ();
-               if (orig != domain)
-                       mono_domain_set (domain, TRUE);
+       orig = mono_domain_get ();
+       if (orig != domain)
+               mono_domain_set (domain, TRUE);
 
-       }
-       if (!mono_threads_is_coop_enabled ()) {
-               return orig != domain ? orig : NULL;
-       } else {
-               if (fresh_thread) {
-                       *dummy = NULL;
-                       /* mono_thread_attach put the thread in RUNNING mode from STARTING, but we need to
-                        * return the right cookie. */
-                       return mono_threads_enter_gc_unsafe_region_cookie (mono_thread_info_current ());
-               } else {
-                       *dummy = orig;
-                       /* thread state (BLOCKING|RUNNING) -> RUNNING */
-                       return mono_threads_enter_gc_unsafe_region (dummy);
-               }
-       }
+       return orig != domain ? orig : NULL;
 }
 
 /*
  * mono_jit_thread_detach: called by native->managed wrappers
  *
- * In non-coop mode:
- *  - @cookie: the original domain which needs to be restored, or NULL.
- *  - @dummy: is NULL
- *
- * In coop mode:
- *  - @cookie: contains current MonoThreadInfo* if it was in BLOCKING mode, NULL otherwise
- *  - @dummy: contains the original domain
+ * @cookie: the original domain which needs to be restored, or NULL.
+ * @dummy: is NULL
  */
 void
 mono_jit_thread_detach (gpointer cookie, gpointer *dummy)
 {
-       MonoDomain *domain, *orig;
-
-       if (!mono_threads_is_coop_enabled ()) {
-               orig = (MonoDomain*) cookie;
-
-               if (orig)
-                       mono_domain_set (orig, TRUE);
-       } else {
-               orig = (MonoDomain*) *dummy;
-
-               domain = mono_domain_get ();
-               g_assert (domain);
+       MonoDomain *orig;
 
-               /* it won't do anything if cookie is NULL
-                * thread state RUNNING -> (RUNNING|BLOCKING) */
-               mono_threads_exit_gc_unsafe_region (cookie, dummy);
+       g_assert (!mono_threads_is_coop_enabled ());
 
-               if (orig != domain) {
-                       if (!orig)
-                               mono_domain_unset ();
-                       else
-                               mono_domain_set (orig, TRUE);
-               }
-       }
+       orig = (MonoDomain*) cookie;
+       if (orig)
+               mono_domain_set (orig, TRUE);
 }
 
 /**