Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}