Beispiel #1
0
void
mono_thread_info_self_suspend (void)
{
	gboolean ret;
	MonoThreadInfo *info = mono_thread_info_current ();
	if (!info)
		return;

	MONO_SEM_WAIT_UNITERRUPTIBLE (&info->suspend_semaphore);

	THREADS_DEBUG ("self suspend IN COUNT %d\n", info->suspend_count);

	g_assert (info->suspend_count == 0);
	++info->suspend_count;

	info->thread_state |= STATE_SELF_SUSPENDED;

	ret = mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->suspend_state, NULL);
	g_assert (ret);

	MONO_SEM_POST (&info->suspend_semaphore);

	MONO_SEM_WAIT_UNITERRUPTIBLE (&info->resume_semaphore);

	g_assert (!info->async_target); /*FIXME this should happen normally for suspend. */
	MONO_SEM_POST (&info->finish_resume_semaphore);
}
Beispiel #2
0
gboolean
mono_thread_info_resume (MonoNativeThreadId tid)
{
	gboolean result = TRUE;
	MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();	
	MonoThreadInfo *info = mono_thread_info_lookup (tid); /*info on HP1*/
	if (!info)
		return FALSE;

	MONO_SEM_WAIT_UNITERRUPTIBLE (&info->suspend_semaphore);

	THREADS_DEBUG ("resume %x IN COUNT %d\n",tid, info->suspend_count);

	if (info->suspend_count <= 0) {
		MONO_SEM_POST (&info->suspend_semaphore);
		mono_hazard_pointer_clear (hp, 1);
		return FALSE;
	}

	/*
	 * The theory here is that if we manage to suspend the thread it means it did not
	 * start cleanup since it take the same lock. 
	*/
	g_assert (mono_thread_info_get_tid (info));

	if (--info->suspend_count == 0)
		result = mono_thread_info_resume_internal (info);

	MONO_SEM_POST (&info->suspend_semaphore);
	mono_hazard_pointer_clear (hp, 1);
	mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, FALSE);

	return result;
}
Beispiel #3
0
/*
The suspend lock is held during any suspend in progress.
A GC that has safepoints must take this lock as part of its
STW to make sure no unsafe pending suspend is in progress.
*/
void
mono_thread_info_suspend_lock (void)
{
    MONO_TRY_BLOCKING;
    MONO_SEM_WAIT_UNITERRUPTIBLE (&global_suspend_semaphore);
    MONO_FINISH_TRY_BLOCKING;
}
Beispiel #4
0
static gboolean
mono_thread_info_core_resume (MonoThreadInfo *info)
{
	gboolean result;
	MonoNativeThreadId tid = mono_thread_info_get_tid (info);
	if (info->create_suspended) {
		/* Have to special case this, as the normal suspend/resume pair are racy, they don't work if he resume is received before the suspend */
		info->create_suspended = FALSE;
		mono_threads_core_resume_created (info, tid);
		return TRUE;
	}

	MONO_SEM_WAIT_UNITERRUPTIBLE (&info->suspend_semaphore);

	THREADS_DEBUG ("resume %x IN COUNT %d\n", tid, info->suspend_count);

	if (info->suspend_count <= 0) {
		MONO_SEM_POST (&info->suspend_semaphore);
		return FALSE;
	}

	/*
	 * The theory here is that if we manage to suspend the thread it means it did not
	 * start cleanup since it take the same lock. 
	*/
	g_assert (mono_thread_info_get_tid (info));

	if (--info->suspend_count == 0) {
		if (mono_thread_info_suspend_state (info) == STATE_SELF_SUSPENDED) {
			MONO_SEM_POST (&info->resume_semaphore);
			MONO_SEM_WAIT_UNITERRUPTIBLE (&info->finish_resume_semaphore);
			result = TRUE;
		} else {
			result = mono_threads_core_resume (info);
		}
		info->thread_state &= ~SUSPEND_STATE_MASK;
	} else {
		result = TRUE;
	}

	MONO_SEM_POST (&info->suspend_semaphore);
	return result;
}
Beispiel #5
0
static gboolean
mono_thread_info_resume_internal (MonoThreadInfo *info)
{
	gboolean result;
	if (mono_thread_info_suspend_state (info) == STATE_SELF_SUSPENDED) {
		MONO_SEM_POST (&info->resume_semaphore);
		MONO_SEM_WAIT_UNITERRUPTIBLE (&info->finish_resume_semaphore);
		result = TRUE;
	} else {
		result = mono_threads_core_resume (info);
	}
	info->thread_state &= ~SUSPEND_STATE_MASK;
	return result;
}
Beispiel #6
0
/*
The return value is only valid until a matching mono_thread_info_resume is called
*/
static MonoThreadInfo*
mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel, const char **error_condition)
{
	MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();	
	MonoThreadInfo *info = mono_thread_info_lookup (tid); /*info on HP1*/
	if (!info) {
		*error_condition = "Thread not found";
		return NULL;
	}

	MONO_SEM_WAIT_UNITERRUPTIBLE (&info->suspend_semaphore);

	/*thread is on the process of detaching*/
	if (mono_thread_info_run_state (info) > STATE_RUNNING) {
		mono_hazard_pointer_clear (hp, 1);
		*error_condition = "Thread is detaching";
		return NULL;
	}

	THREADS_DEBUG ("suspend %x IN COUNT %d\n", tid, info->suspend_count);

	if (info->suspend_count) {
		++info->suspend_count;
		mono_hazard_pointer_clear (hp, 1);
		MONO_SEM_POST (&info->suspend_semaphore);
		return info;
	}

	if (!mono_threads_core_suspend (info)) {
		MONO_SEM_POST (&info->suspend_semaphore);
		mono_hazard_pointer_clear (hp, 1);
		*error_condition = "Could not suspend thread";
		return NULL;
	}

	if (interrupt_kernel) 
		mono_threads_core_interrupt (info);

	++info->suspend_count;
	info->thread_state |= STATE_SUSPENDED;
	MONO_SEM_POST (&info->suspend_semaphore);

	return info;
}
Beispiel #7
0
/*
The suspend lock is held during any suspend in progress.
A GC that has safepoints must take this lock as part of its
STW to make sure no unsafe pending suspend is in progress.   
*/
void
mono_thread_info_suspend_lock (void)
{
	MONO_SEM_WAIT_UNITERRUPTIBLE (&global_suspend_semaphore);
}
Beispiel #8
0
void
mono_thread_info_wait_for_resume (MonoThreadInfo* info)
{
	THREADS_SUSPEND_DEBUG ("**WAIT self-resume %p\n", mono_thread_info_get_tid (info));
	MONO_SEM_WAIT_UNITERRUPTIBLE (&info->resume_semaphore);
}