gboolean mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoNativeThreadId thread_id, MonoNativeThreadHandle thread_handle) { kern_return_t ret; mach_msg_type_number_t num_state; thread_state_t state; ucontext_t ctx; mcontext_t mctx; guint32 domain_key, jit_key; MonoJitTlsData *jit_tls; void *domain; #if defined (MONO_ARCH_ENABLE_MONO_LMF_VAR) guint32 lmf_key; #endif /*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 ()); mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ()); ret = mono_mach_arch_get_thread_state (thread_handle, state, &num_state); if (ret != KERN_SUCCESS) return FALSE; mono_mach_arch_thread_state_to_mcontext (state, mctx); ctx.uc_mcontext = mctx; mono_sigctx_to_monoctx (&ctx, &tctx->ctx); domain_key = mono_domain_get_tls_offset (); jit_key = mono_get_jit_tls_key (); jit_tls = mono_mach_arch_get_tls_value_from_thread (thread_id, jit_key); domain = mono_mach_arch_get_tls_value_from_thread (thread_id, domain_key); /*Thread already started to cleanup, can no longer capture unwind state*/ if (!jit_tls) return FALSE; g_assert (domain); #if defined (MONO_ARCH_ENABLE_MONO_LMF_VAR) lmf_key = mono_get_lmf_tls_offset (); tctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_mach_arch_get_tls_value_from_thread (thread_id, lmf_key);; #else tctx->unwind_data [MONO_UNWIND_DATA_LMF] = jit_tls ? jit_tls->lmf : NULL; #endif tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain; tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls; tctx->valid = TRUE; return TRUE; }
gboolean mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoNativeThreadId thread_id, MonoNativeThreadHandle thread_handle) { kern_return_t ret; mach_msg_type_number_t num_state; thread_state_t state; ucontext_t ctx; mcontext_t mctx; guint32 domain_key, jit_key; MonoJitTlsData *jit_tls; void *domain; state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ()); mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ()); ret = mono_mach_arch_get_thread_state (thread_handle, state, &num_state); if (ret != KERN_SUCCESS) return FALSE; mono_mach_arch_thread_state_to_mcontext (state, mctx); ctx.uc_mcontext = mctx; mono_sigctx_to_monoctx (&ctx, &tctx->ctx); domain_key = mono_domain_get_tls_offset (); jit_key = mono_pthread_key_for_tls (mono_get_jit_tls_key ()); jit_tls = mono_mach_arch_get_tls_value_from_thread (thread_id, jit_key); domain = mono_mach_arch_get_tls_value_from_thread (thread_id, domain_key); /*Thread already started to cleanup, can no longer capture unwind state*/ if (!jit_tls) return FALSE; g_assert (domain); tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain; tctx->unwind_data [MONO_UNWIND_DATA_LMF] = jit_tls ? jit_tls->lmf : NULL; tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls; tctx->valid = TRUE; return TRUE; }
gboolean mono_sgen_suspend_thread (SgenThreadInfo *info) { mach_msg_type_number_t num_state; thread_state_t state; kern_return_t ret; ucontext_t ctx; mcontext_t mctx; gpointer stack_start; state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ()); mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ()); ret = thread_suspend (info->mach_port); if (ret != KERN_SUCCESS) return FALSE; ret = mono_mach_arch_get_thread_state (info->mach_port, state, &num_state); if (ret != KERN_SUCCESS) return FALSE; mono_mach_arch_thread_state_to_mcontext (state, mctx); ctx.uc_mcontext = mctx; info->stopped_domain = mono_mach_arch_get_tls_value_from_thread ((pthread_t)info->id, mono_domain_get_tls_offset ()); info->stopped_ip = (gpointer) mono_mach_arch_get_ip (state); stack_start = (char*) mono_mach_arch_get_sp (state) - REDZONE_SIZE; /* If stack_start is not within the limits, then don't set it in info and we will be restarted. */ if (stack_start >= info->stack_start_limit && info->stack_start <= info->stack_end) { info->stack_start = stack_start; #ifdef USE_MONO_CTX mono_sigctx_to_monoctx (&ctx, &info->ctx); info->monoctx = &info->ctx; #else ARCH_COPY_SIGCTX_REGS (&info->regs, &ctx); info->stopped_regs = &info->regs; #endif } else { g_assert (!info->stack_start); } /* Notify the JIT */ if (mono_gc_get_gc_callbacks ()->thread_suspend_func) mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, &ctx); return TRUE; }