gboolean mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info, void *sigctx) { kern_return_t ret; mach_msg_type_number_t num_state, num_fpstate; thread_state_t state, fpstate; MonoJitTlsData *jit_tls; void *domain; MonoLMF *lmf = NULL; gpointer *addr; g_assert (info); /*Zero enough state to make sure the caller doesn't confuse itself*/ tctx->valid = FALSE; tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = NULL; tctx->unwind_data [MONO_UNWIND_DATA_LMF] = NULL; tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL; state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ()); fpstate = (thread_state_t) alloca (mono_mach_arch_get_thread_fpstate_size ()); do { ret = mono_mach_arch_get_thread_states (info->native_handle, state, &num_state, fpstate, &num_fpstate); } while (ret == KERN_ABORTED); if (ret != KERN_SUCCESS) return FALSE; mono_mach_arch_thread_states_to_mono_context (state, fpstate, &tctx->ctx); /* mono_set_jit_tls () sets this */ jit_tls = mono_thread_info_tls_get (info, TLS_KEY_JIT_TLS); /* SET_APPDOMAIN () sets this */ domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN); /*Thread already started to cleanup, can no longer capture unwind state*/ if (!jit_tls || !domain) return FALSE; /* * The current LMF address is kept in a separate TLS variable, and its hard to read its value without * arch-specific code. But the address of the TLS variable is stored in another TLS variable which * can be accessed through MonoThreadInfo. */ /* mono_set_lmf_addr () sets this */ addr = mono_thread_info_tls_get (info, TLS_KEY_LMF_ADDR); if (addr) lmf = *addr; tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain; tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls; tctx->unwind_data [MONO_UNWIND_DATA_LMF] = lmf; tctx->valid = TRUE; return TRUE; }
gboolean mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { kern_return_t ret; if (info->async_target) { MonoContext tmp = info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX].ctx; mach_msg_type_number_t num_state, num_fpstate; thread_state_t state, fpstate; ucontext_t uctx; mcontext_t mctx; mono_threads_get_runtime_callbacks ()->setup_async_callback (&tmp, info->async_target, info->user_data); info->user_data = NULL; info->async_target = (void (*)(void *)) info->user_data; state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ()); fpstate = (thread_state_t) alloca (mono_mach_arch_get_thread_fpstate_size ()); mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ()); do { ret = mono_mach_arch_get_thread_states (info->native_handle, state, &num_state, fpstate, &num_fpstate); } while (ret == KERN_ABORTED); if (ret != KERN_SUCCESS) return FALSE; mono_mach_arch_thread_states_to_mcontext (state, fpstate, mctx); uctx.uc_mcontext = mctx; mono_monoctx_to_sigctx (&tmp, &uctx); mono_mach_arch_mcontext_to_thread_states (mctx, state, fpstate); do { ret = mono_mach_arch_set_thread_states (info->native_handle, state, num_state, fpstate, num_fpstate); } while (ret == KERN_ABORTED); if (ret != KERN_SUCCESS) return FALSE; } do { ret = thread_resume (info->native_handle); } while (ret == KERN_ABORTED); THREADS_SUSPEND_DEBUG ("RESUME %p -> %d\n", (gpointer)(gsize)info->native_handle, ret); return ret == KERN_SUCCESS; }