コード例 #1
0
static void
assertion_fail (const char *msg, ...)
{
	int i;
	GString* err = g_string_sized_new (100);
	CheckState *state = get_state ();

	g_string_append_printf (err, "Assertion failure in thread %p due to: ", mono_native_thread_id_get ());

	va_list args;
	va_start (args, msg);
	g_string_append_vprintf (err, msg, args);
	va_end (args);

	g_string_append_printf (err, "\nLast %d state transitions: (most recent first)\n", state->transitions->len);

	for (i = state->transitions->len - 1; i >= 0; --i) {
		ThreadTransition *t = state->transitions->pdata [i];
		char *bt = translate_backtrace (t->backtrace, t->size);
		g_string_append_printf (err, "[%s] %s -> %s (%d) %s%d at:\n%s",
			t->name,
			mono_thread_state_name (t->from_state),
			mono_thread_state_name (t->next_state),
			t->suspend_count,
			t->suspend_count_delta > 0 ? "+" : "", //I'd like to see this sort of values: -1, 0, +1
			t->suspend_count_delta,
			bt);
		g_free (bt);
	}

	g_error (err->str);
	g_string_free (err, TRUE);
}
コード例 #2
0
ファイル: sgen-os-posix.c プロジェクト: Alkarex/mono
static void
restart_handler (int sig)
{
	SgenThreadInfo *info;
	int old_errno = errno;

	info = mono_thread_info_current ();
	/*
	If the thread info is null is means we're currently in the process of cleaning up,
	the pthread destructor has already kicked in and it has explicitly invoked the suspend handler.
	
	This means this thread has been suspended, TLS is dead, so the only option we have is to
	rely on pthread_self () and seatch over the thread list.
	*/
	if (!info)
		info = (SgenThreadInfo*)mono_thread_info_lookup (pthread_self ());

	/*
	 * If a thread is dying there might be no thread info.  In
	 * that case we rely on info->doing_handshake.
	 */
	if (info) {
		info->signal = restart_signal_num;
		DEBUG (4, fprintf (gc_debug_file, "Restart handler in %p %p\n", info, (gpointer)mono_native_thread_id_get ()));
	}
	errno = old_errno;
}
コード例 #3
0
ファイル: mono-threads.c プロジェクト: ileonchik/mono
/*
 * This is a very specific function whose only purpose is to
 * break a given thread from socket syscalls.
 *
 * This only exists because linux won't fail a call to connect
 * if the underlying is closed.
 *
 * TODO We should cleanup and unify this with the other syscall abort
 * facility.
 */
void
mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid)
{
	MonoThreadHazardPointers *hp;
	MonoThreadInfo *info;

	if (tid == mono_native_thread_id_get () || !mono_threads_core_needs_abort_syscall ())
		return;

	hp = mono_hazard_pointer_get ();
	info = mono_thread_info_lookup (tid);
	if (!info)
		return;

	if (mono_thread_info_run_state (info) == STATE_DETACHED) {
		mono_hazard_pointer_clear (hp, 1);
		return;
	}

	mono_thread_info_suspend_lock ();
	mono_threads_begin_global_suspend ();

	mono_threads_core_abort_syscall (info);
	mono_threads_wait_pending_operations ();

	mono_hazard_pointer_clear (hp, 1);

	mono_threads_end_global_suspend ();
	mono_thread_info_suspend_unlock ();
}
コード例 #4
0
ファイル: mono-threads.c プロジェクト: megatichan/mono
void
mono_thread_info_safe_suspend_and_run (MonoNativeThreadId id, gboolean interrupt_kernel, MonoSuspendThreadCallback callback, gpointer user_data)
{
	int result;
	MonoThreadInfo *info = NULL;
	MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();

	THREADS_SUSPEND_DEBUG ("SUSPENDING tid %p\n", (void*)id);
	/*FIXME: unify this with self-suspend*/
	g_assert (id != mono_native_thread_id_get ());

	mono_thread_info_suspend_lock ();
	mono_threads_begin_global_suspend ();

	info = suspend_sync_nolock (id, interrupt_kernel);
	if (!info)
		goto done;

	switch (result = callback (info, user_data)) {
	case MonoResumeThread:
		mono_hazard_pointer_set (hp, 1, info);
		mono_thread_info_core_resume (info);
		mono_threads_wait_pending_operations ();
		break;
	case KeepSuspended:
		break;
	default:
		g_error ("Invalid suspend_and_run callback return value %d", result);
	}

done:
	mono_hazard_pointer_clear (hp, 1);
	mono_threads_end_global_suspend ();
	mono_thread_info_suspend_unlock ();
}
コード例 #5
0
ファイル: mono-threads.c プロジェクト: Andrea/mono
static void*
register_thread (MonoThreadInfo *info, gpointer baseptr)
{
	gboolean result;
	mono_thread_info_set_tid (info, mono_native_thread_id_get ());
	info->small_id = mono_thread_small_id_alloc ();

	InitializeCriticalSection (&info->suspend_lock);

	/*set TLS early so SMR works */
	mono_native_tls_set_value (thread_info_key, info);
	mono_native_tls_set_value (small_id_key, GUINT_TO_POINTER (info->small_id + 1));

	THREADS_DEBUG ("registering info %p tid %p small id %x\n", info, mono_thread_info_get_tid (info), info->small_id);

	if (threads_callbacks.thread_register) {
		if (threads_callbacks.thread_register (info, baseptr) == NULL) {
			g_warning ("thread registation failed\n");
			g_free (info);
			return NULL;
		}
	}

	mono_threads_platform_register (info);

	/*If this fail it means a given thread has been registered twice, which doesn't make sense. */
	result = mono_thread_info_insert (info);
	g_assert (result);
	return info;
}
コード例 #6
0
ファイル: mono-threads.c プロジェクト: glinos/mono
static void*
register_thread (MonoThreadInfo *info, gpointer baseptr)
{
	int small_id = mono_thread_info_register_small_id ();
	gboolean result;
	mono_thread_info_set_tid (info, mono_native_thread_id_get ());
	info->small_id = small_id;

	MONO_SEM_INIT (&info->suspend_semaphore, 1);
	MONO_SEM_INIT (&info->resume_semaphore, 0);
	MONO_SEM_INIT (&info->finish_resume_semaphore, 0);

	/*set TLS early so SMR works */
	mono_native_tls_set_value (thread_info_key, info);

	THREADS_DEBUG ("registering info %p tid %p small id %x\n", info, mono_thread_info_get_tid (info), info->small_id);

	if (threads_callbacks.thread_register) {
		if (threads_callbacks.thread_register (info, baseptr) == NULL) {
			g_warning ("thread registation failed\n");
			g_free (info);
			return NULL;
		}
	}

	mono_threads_platform_register (info);
	info->thread_state = STATE_RUNNING;
	mono_thread_info_suspend_lock ();
	/*If this fail it means a given thread has been registered twice, which doesn't make sense. */
	result = mono_thread_info_insert (info);
	g_assert (result);
	mono_thread_info_suspend_unlock ();
	return info;
}
コード例 #7
0
int
sgen_thread_handshake (BOOL suspend)
{
	int count, result;
	SgenThreadInfo *info;
	int signum = suspend ? suspend_signal_num : restart_signal_num;

	MonoNativeThreadId me = mono_native_thread_id_get ();

	count = 0;
	mono_thread_info_current ()->client_info.suspend_done = TRUE;
	FOREACH_THREAD_SAFE (info) {
		if (mono_native_thread_id_equals (mono_thread_info_get_tid (info), me)) {
			continue;
		}
		info->client_info.suspend_done = FALSE;
		if (info->client_info.gc_disabled)
			continue;
		/*if (signum == suspend_signal_num && info->stop_count == global_stop_count)
			continue;*/
		result = mono_threads_pthread_kill (info, signum);
		if (result == 0) {
			count++;
		} else {
			info->client_info.skip = 1;
		}
	} END_FOREACH_THREAD_SAFE

	sgen_wait_for_suspend_ack (count);

	SGEN_LOG (4, "%s handshake for %d threads\n", suspend ? "suspend" : "resume", count);

	return count;
}
コード例 #8
0
ファイル: sgen-os-posix.c プロジェクト: muhislam/mono
int
mono_sgen_thread_handshake (BOOL suspend)
{
	int count, result;
	SgenThreadInfo *info;
	int signum = suspend ? suspend_signal_num : restart_signal_num;

	MonoNativeThreadId me = mono_native_thread_id_get ();

	count = 0;
	FOREACH_THREAD_SAFE (info) {
		if (mono_native_thread_id_equals (mono_thread_info_get_tid (info), me)) {
			continue;
		}
		/*if (signum == suspend_signal_num && info->stop_count == global_stop_count)
			continue;*/
		if (suspend) {
			g_assert (!info->doing_handshake);
			info->doing_handshake = TRUE;
		} else {
			g_assert (info->doing_handshake);
			info->doing_handshake = FALSE;
		}
		result = pthread_kill (mono_thread_info_get_tid (info), signum);
		if (result == 0) {
			count++;
		} else {
			info->skip = 1;
		}
	} END_FOREACH_THREAD_SAFE

	mono_sgen_wait_for_suspend_ack (count);

	return count;
}
コード例 #9
0
ファイル: mono-threads.c プロジェクト: glinos/mono
MonoThreadInfo*
mono_thread_info_current (void)
{
	MonoThreadInfo *info = (MonoThreadInfo*)mono_native_tls_get_value (thread_info_key);
	if (info)
		return info;

	info = mono_thread_info_lookup (mono_native_thread_id_get ()); /*info on HP1*/

	/*
	We might be called during thread cleanup, but we cannot be called after cleanup as happened.
	The way to distinguish between before, during and after cleanup is the following:

	-If the TLS key is set, cleanup has not begun;
	-If the TLS key is clean, but the thread remains registered, cleanup is in progress;
	-If the thread is nowhere to be found, cleanup has finished.

	We cannot function after cleanup since there's no way to ensure what will happen.
	*/
	g_assert (info);

	/*We're looking up the current thread which will not be freed until we finish running, so no need to keep it on a HP */
	mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);

	return info;
}
コード例 #10
0
ファイル: mono-threads.c プロジェクト: glinos/mono
/*
 * This is a very specific function whose only purpose is to
 * break a given thread from socket syscalls.
 *
 * This only exists because linux won't fail a call to connect
 * if the underlying is closed.
 *
 * TODO We should cleanup and unify this with the other syscall abort
 * facility.
 */
void
mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid)
{
	MonoThreadHazardPointers *hp;
	MonoThreadInfo *info;
	
	if (tid == mono_native_thread_id_get () || !mono_threads_core_needs_abort_syscall ())
		return;

	hp = mono_hazard_pointer_get ();	
	info = mono_thread_info_lookup (tid); /*info on HP1*/
	if (!info)
		return;

	if (mono_thread_info_run_state (info) > STATE_RUNNING) {
		mono_hazard_pointer_clear (hp, 1);
		return;
	}

	mono_thread_info_suspend_lock ();

	mono_threads_core_abort_syscall (info);

	mono_hazard_pointer_clear (hp, 1);
	mono_thread_info_suspend_unlock ();
}
コード例 #11
0
ファイル: sgen-protocol.c プロジェクト: arktronic/mono
static void
protocol_entry (unsigned char type, gpointer data, int size)
{
	int index;
	BinaryProtocolBuffer *buffer;

	if (!binary_protocol_file)
		return;

	if (sgen_is_worker_thread (mono_native_thread_id_get ()))
		type |= 0x80;

	lock_recursive ();

 retry:
	buffer = binary_protocol_get_buffer (size + 1);
 retry_same_buffer:
	index = buffer->index;
	if (index + 1 + size > BINARY_PROTOCOL_BUFFER_SIZE)
		goto retry;

	if (InterlockedCompareExchange (&buffer->index, index + 1 + size, index) != index)
		goto retry_same_buffer;

	/* FIXME: if we're interrupted at this point, we have a buffer
	   entry that contains random data. */

	buffer->buffer [index++] = type;
	memcpy (buffer->buffer + index, data, size);
	index += size;

	g_assert (index <= BINARY_PROTOCOL_BUFFER_SIZE);

	unlock_recursive ();
}
コード例 #12
0
ファイル: mono-threads.c プロジェクト: glinos/mono
/**
 * Removes the current thread from the thread list.
 * This must be called from the thread unregister callback and nowhere else.
 * The current thread must be passed as TLS might have already been cleaned up.
*/
static void
mono_threads_unregister_current_thread (MonoThreadInfo *info)
{
	gboolean result;
	g_assert (mono_thread_info_get_tid (info) == mono_native_thread_id_get ());
	result = mono_thread_info_remove (info);
	g_assert (result);
}
コード例 #13
0
ファイル: trace.c プロジェクト: RavenB/mono
static void indent (int diff) {
	if (diff < 0)
		indent_level += diff;
	if (start_time == 0)
		start_time = mono_100ns_ticks ();
	printf ("[%p: %.5f %d] ", (void*)mono_native_thread_id_get (), seconds_since_start (), indent_level);
	if (diff > 0)
		indent_level += diff;
}
コード例 #14
0
MONO_SIG_HANDLER_FUNC (static, restart_handler)
{
	SgenThreadInfo *info;
	int old_errno = errno;

	info = mono_thread_info_current ();
	info->client_info.signal = restart_signal_num;
	SGEN_LOG (4, "Restart handler in %p %p", info, (gpointer) (gsize) mono_native_thread_id_get ());
	errno = old_errno;
}
コード例 #15
0
static void
add_alloc_record (char *addr, size_t size, int reason)
{
	int idx = InterlockedIncrement (&next_record) - 1;
	alloc_records [idx].address = addr;
	alloc_records [idx].size = size;
	alloc_records [idx].reason = reason;
	alloc_records [idx].seq = idx;
	alloc_records [idx].tid = mono_native_thread_id_get ();
}
コード例 #16
0
ファイル: sgen-os-posix.c プロジェクト: efcastrillon/mono
static void
restart_handler (int sig)
{
	SgenThreadInfo *info;
	int old_errno = errno;

	info = mono_thread_info_current ();
	info->signal = restart_signal_num;
	SGEN_LOG (4, "Restart handler in %p %p", info, (gpointer)mono_native_thread_id_get ());
	errno = old_errno;
}
コード例 #17
0
static void*
register_thread (MonoThreadInfo *info, gpointer baseptr)
{
	size_t stsize = 0;
	guint8 *staddr = NULL;
	int small_id = mono_thread_info_register_small_id ();
	gboolean result;
	mono_thread_info_set_tid (info, mono_native_thread_id_get ());
	info->small_id = small_id;

	info->handle = g_new0 (MonoThreadHandle, 1);
	mono_refcount_init (info->handle, thread_handle_destroy);
	mono_os_event_init (&info->handle->event, FALSE);

	mono_os_sem_init (&info->resume_semaphore, 0);

	/*set TLS early so SMR works */
	mono_native_tls_set_value (thread_info_key, info);

	THREADS_DEBUG ("registering info %p tid %p small id %x\n", info, mono_thread_info_get_tid (info), info->small_id);

	if (threads_callbacks.thread_register) {
		if (threads_callbacks.thread_register (info, baseptr) == NULL) {
			// g_warning ("thread registation failed\n");
			mono_native_tls_set_value (thread_info_key, NULL);
			g_free (info);
			return NULL;
		}
	}

	mono_thread_info_get_stack_bounds (&staddr, &stsize);
	g_assert (staddr);
	g_assert (stsize);
	info->stack_start_limit = staddr;
	info->stack_end = staddr + stsize;

	info->stackdata = g_byte_array_new ();

	mono_threads_suspend_register (info);

	/*
	Transition it before taking any locks or publishing itself to reduce the chance
	of others witnessing a detached thread.
	We can reasonably expect that until this thread gets published, no other thread will
	try to manipulate it.
	*/
	mono_threads_transition_attach (info);
	mono_thread_info_suspend_lock ();
	/*If this fail it means a given thread has been registered twice, which doesn't make sense. */
	result = mono_thread_info_insert (info);
	g_assert (result);
	mono_thread_info_suspend_unlock ();
	return info;
}
コード例 #18
0
ファイル: sgen-memory-governor.c プロジェクト: elix22/mono
gboolean
sgen_memgov_try_alloc_space (mword size, int space)
{
	if (sgen_memgov_available_free_space () < size) {
		SGEN_ASSERT (4, !sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ()), "Memory shouldn't run out in worker thread");
		return FALSE;
	}

	SGEN_ATOMIC_ADD_P (allocated_heap, size);
	sgen_client_total_allocated_heap_changed (allocated_heap);
	return TRUE;
}
コード例 #19
0
ファイル: hazard-pointer.c プロジェクト: LogosBible/mono
MonoThreadHazardPointers*
mono_hazard_pointer_get (void)
{
	int small_id = mono_thread_info_get_small_id ();

	if (small_id < 0) {
		static MonoThreadHazardPointers emerg_hazard_table;
		g_warning ("Thread %p may have been prematurely finalized", (gpointer) (gsize) mono_native_thread_id_get ());
		return &emerg_hazard_table;
	}

	return &hazard_table [small_id];
}
コード例 #20
0
ファイル: sgen-workers.c プロジェクト: rcruzs00/mono
static gboolean
set_state (State old_state, State new_state)
{
    SGEN_ASSERT (0, old_state != new_state, "Why are we transitioning to the same state?");
    if (new_state == STATE_NOT_WORKING)
        SGEN_ASSERT (0, old_state == STATE_WORKING, "We can only transition to NOT WORKING from WORKING");
    else if (new_state == STATE_WORKING)
        SGEN_ASSERT (0, old_state == STATE_WORK_ENQUEUED, "We can only transition to WORKING from WORK ENQUEUED");
    if (new_state == STATE_NOT_WORKING || new_state == STATE_WORKING)
        SGEN_ASSERT (6, sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ()), "Only the worker thread is allowed to transition to NOT_WORKING or WORKING");

    return InterlockedCompareExchange (&workers_state, new_state, old_state) == old_state;
}
コード例 #21
0
ファイル: mono-threads.c プロジェクト: Adamcbrz/mono
/*
WARNING:
If we are trying to suspend a target that is on a critical region
and running a syscall we risk looping forever if @interrupt_kernel is FALSE.
So, be VERY carefull in calling this with @interrupt_kernel == FALSE.

Info is not put on a hazard pointer as a suspended thread cannot exit and be freed.

This function MUST be matched with mono_thread_info_finish_suspend or mono_thread_info_finish_suspend_and_resume
*/
MonoThreadInfo*
mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
{
	MonoThreadInfo *info = NULL;
	int sleep_duration = 0;

	/*FIXME: unify this with self-suspend*/
	g_assert (id != mono_native_thread_id_get ());

	mono_thread_info_suspend_lock ();

	for (;;) {
		const char *suspend_error = "Unknown error";
		if (!(info = mono_thread_info_suspend_sync (id, interrupt_kernel, &suspend_error))) {
			g_warning ("failed to suspend thread %p due to %s, hopefully it is dead", (gpointer)id, suspend_error);
			mono_thread_info_suspend_unlock ();
			return NULL;
		}
		/*WARNING: We now are in interrupt context until we resume the thread. */
		if (!is_thread_in_critical_region (info))
			break;

		if (!mono_thread_info_core_resume (info)) {
			g_warning ("failed to resume thread %p, hopefully it is dead", (gpointer)id);
			mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
			mono_thread_info_suspend_unlock ();
			return NULL;
		}
		THREADS_DEBUG ("restarted thread %p\n", (gpointer)id);

		if (!sleep_duration) {
#ifdef HOST_WIN32
			SwitchToThread ();
#else
			sched_yield ();
#endif
		}
		else {
			g_usleep (sleep_duration);
		}
		sleep_duration += 10;
	}

	/* XXX this clears HP 1, so we restated it again */
	mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, TRUE);
	mono_thread_info_suspend_unlock ();

	return info;
}
コード例 #22
0
ファイル: mono-threads.c プロジェクト: Andrea/mono
/*
WARNING:
If we are trying to suspend a target that is on a critical region
and running a syscall we risk looping forever if @interrupt_kernel is FALSE.
So, be VERY carefull in calling this with @interrupt_kernel == FALSE.
*/
MonoThreadInfo*
mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
{
	MonoThreadInfo *info = NULL;
	int sleep_duration = 0;

	/*FIXME: unify this with self-suspend*/
	g_assert (id != mono_native_thread_id_get ());

	mono_thread_info_suspend_lock ();

	for (;;) {
		if (!(info = mono_thread_info_suspend_sync (id, interrupt_kernel))) {
			g_warning ("failed to suspend thread %p, hopefully it is dead", (gpointer)id);
			mono_thread_info_suspend_unlock ();
			return NULL;
		}
		/*WARNING: We now are in interrupt context until we resume the thread. */
		if (!is_thread_in_critical_region (info))
			break;

		if (!mono_thread_info_resume (id)) {
			g_warning ("failed to result thread %p, hopefully it is dead", (gpointer)id);
			mono_thread_info_suspend_unlock ();
			return NULL;
		}
		THREADS_DEBUG ("restarted thread %p\n", (gpointer)id);

		if (!sleep_duration) {
#ifdef HOST_WIN32
			SwitchToThread ();
#else
			sched_yield ();
#endif
		}
		else {
			g_usleep (sleep_duration);
		}
		sleep_duration += 10;
	}

	mono_thread_info_suspend_unlock ();
	return info;
}
コード例 #23
0
ファイル: sgen-os-posix.c プロジェクト: muhislam/mono
static void
restart_handler (int sig)
{
	SgenThreadInfo *info;
	int old_errno = errno;

	info = mono_thread_info_current ();

	/*
	 * If a thread is dying there might be no thread info.  In
	 * that case we rely on info->doing_handshake.
	 */
	if (info) {
		info->signal = restart_signal_num;
		DEBUG (4, fprintf (gc_debug_file, "Restart handler in %p %p\n", info, (gpointer)mono_native_thread_id_get ()));
	}

	errno = old_errno;
}
コード例 #24
0
void
mono_native_thread_set_name (MonoNativeThreadId tid, const char *name)
{
#ifdef __MACH__
	/*
	 * We can't set the thread name for other threads, but we can at least make
	 * it work for threads that try to change their own name.
	 */
	if (tid != mono_native_thread_id_get ())
		return;

	if (!name) {
		pthread_setname_np ("");
	} else {
		char n [63];

		memcpy (n, name, sizeof (n) - 1);
		n [sizeof (n) - 1] = '\0';
		pthread_setname_np (n);
	}
#elif defined (__NetBSD__)
	if (!name) {
		pthread_setname_np (tid, "%s", (void*)"");
	} else {
		char n [PTHREAD_MAX_NAMELEN_NP];

		memcpy (n, name, sizeof (n) - 1);
		n [sizeof (n) - 1] = '\0';
		pthread_setname_np (tid, "%s", (void*)n);
	}
#elif defined (HAVE_PTHREAD_SETNAME_NP)
	if (!name) {
		pthread_setname_np (tid, "");
	} else {
		char n [16];

		memcpy (n, name, sizeof (n) - 1);
		n [sizeof (n) - 1] = '\0';
		pthread_setname_np (tid, n);
	}
#endif
}
コード例 #25
0
MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler)
{
	int old_errno = errno;

	MONO_SIG_HANDLER_GET_CONTEXT;

	/* See the comment in mono_runtime_shutdown_stat_profiler (). */
	if (mono_native_thread_id_get () == sampling_thread) {
		mono_atomic_inc_i32 (&profiler_interrupt_signals_received);
		return;
	}

	mono_atomic_inc_i32 (&profiler_signals_received);

	// Did a non-attached or detaching thread get the signal?
	if (mono_thread_info_get_small_id () == -1 ||
	    !mono_domain_get () ||
	    !mono_tls_get_jit_tls ()) {
		errno = old_errno;
		return;
	}

	// See the comment in sampling_thread_func ().
	mono_atomic_store_i32 (&mono_thread_info_current ()->profiler_signal_ack, 1);

	mono_atomic_inc_i32 (&profiler_signals_accepted);

	int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();

	mono_thread_info_set_is_async_context (TRUE);

	MONO_PROFILER_RAISE (sample_hit, (mono_arch_ip_from_context (ctx), ctx));

	mono_thread_info_set_is_async_context (FALSE);

	mono_hazard_pointer_restore_for_signal_handler (hp_save_index);

	errno = old_errno;

	mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
}
コード例 #26
0
ファイル: mono-threads.c プロジェクト: megatichan/mono
/*
WARNING:
If we are trying to suspend a target that is on a critical region
and running a syscall we risk looping forever if @interrupt_kernel is FALSE.
So, be VERY carefull in calling this with @interrupt_kernel == FALSE.

Info is not put on a hazard pointer as a suspended thread cannot exit and be freed.

This function MUST be matched with mono_thread_info_finish_suspend or mono_thread_info_finish_suspend_and_resume
*/
MonoThreadInfo*
mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
{
	MonoThreadInfo *info = NULL;

	THREADS_SUSPEND_DEBUG ("SUSPENDING tid %p\n", (void*)id);
	/*FIXME: unify this with self-suspend*/
	g_assert (id != mono_native_thread_id_get ());

	mono_thread_info_suspend_lock ();
	mono_threads_begin_global_suspend ();

	info = suspend_sync_nolock (id, interrupt_kernel);

	/* XXX this clears HP 1, so we restated it again */
	// mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, TRUE);
	mono_threads_end_global_suspend ();
	mono_thread_info_suspend_unlock ();

	return info;
}
コード例 #27
0
ファイル: lock-tracer.c プロジェクト: LogosBible/mono
static void
add_record (RecordType record_kind, RuntimeLocks kind, gpointer lock)
{
	int i = 0;
	const int no_frames = 6;
	gpointer frames[no_frames];

	char *msg;
 	if (!trace_file)
		return;

	memset (frames, 0, sizeof (gpointer) * no_frames);
	mono_backtrace (frames, no_frames);
	for (i = 0; i < no_frames; ++i)
		frames [i] = (gpointer)((size_t)frames[i] - base_address);

	/*We only dump 5 frames, which should be more than enough to most analysis.*/
	msg = g_strdup_printf ("%x,%d,%d,%p,%p,%p,%p,%p,%p\n", (guint32)mono_native_thread_id_get (), record_kind, kind, lock, frames [1], frames [2], frames [3], frames [4], frames [5]);
	fwrite (msg, strlen (msg), 1, trace_file);
	fflush (trace_file);
	g_free (msg);
}
コード例 #28
0
ファイル: tasklets.c プロジェクト: ItsVeryWindy/mono
static MonoException*
continuation_mark_frame (MonoContinuation *cont)
{
	MonoJitTlsData *jit_tls;
	MonoLMF *lmf;
	MonoContext ctx, new_ctx;
	MonoJitInfo *ji, rji;
	int endloop = FALSE;

	if (cont->domain)
		return mono_get_exception_argument ("cont", "Already marked");

	jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
	lmf = mono_get_lmf();
	cont->domain = mono_domain_get ();
	cont->thread_id = mono_native_thread_id_get ();

	/* get to the frame that called Mark () */
	memset (&rji, 0, sizeof (rji));
	memset (&ctx, 0, sizeof (ctx));
	do {
		ji = mono_find_jit_info (cont->domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
		if (!ji || ji == (gpointer)-1) {
			return mono_get_exception_not_supported ("Invalid stack frame");
		}
		ctx = new_ctx;
		if (endloop)
			break;
		if (!ji->is_trampoline && strcmp (jinfo_get_method (ji)->name, "Mark") == 0)
			endloop = TRUE;
	} while (1);

	cont->top_sp = MONO_CONTEXT_GET_SP (&ctx);
	/*g_print ("method: %s, sp: %p\n", jinfo_get_method (ji)->name, cont->top_sp);*/

	return NULL;
}
コード例 #29
0
ファイル: sgen-stw.c プロジェクト: Adamcbrz/mono
/* LOCKING: assumes the GC lock is held */
int
sgen_stop_world (int generation)
{
	TV_DECLARE (end_handshake);
	int count, dead;

	mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
	MONO_GC_WORLD_STOP_BEGIN ();
	binary_protocol_world_stopping (sgen_timestamp ());
	acquire_gc_locks ();

	/* We start to scan after locks are taking, this ensures we won't be interrupted. */
	sgen_process_togglerefs ();

	update_current_thread_stack (&count);

	sgen_global_stop_count++;
	SGEN_LOG (3, "stopping world n %d from %p %p", sgen_global_stop_count, mono_thread_info_current (), (gpointer)mono_native_thread_id_get ());
	TV_GETTIME (stop_world_time);
	count = sgen_thread_handshake (TRUE);
	dead = restart_threads_until_none_in_managed_allocator ();
	if (count < dead)
		g_error ("More threads have died (%d) that been initialy suspended %d", dead, count);
	count -= dead;

	SGEN_LOG (3, "world stopped %d thread(s)", count);
	mono_profiler_gc_event (MONO_GC_EVENT_POST_STOP_WORLD, generation);
	MONO_GC_WORLD_STOP_END ();
	if (binary_protocol_is_enabled ()) {
		long long major_total, major_marked, los_total, los_marked;
		count_cards (&major_total, &major_marked, &los_total, &los_marked);
		binary_protocol_world_stopped (sgen_timestamp (), major_total, major_marked, los_total, los_marked);
	}

	TV_GETTIME (end_handshake);
	time_stop_world += TV_ELAPSED (stop_world_time, end_handshake);

	sgen_memgov_collection_start (generation);
	if (sgen_need_bridge_processing ())
		sgen_bridge_reset_data ();

	return count;
}
コード例 #30
0
ファイル: sgen-stw.c プロジェクト: ItsVeryWindy/mono
/* LOCKING: assumes the GC lock is held */
void
sgen_client_stop_world (int generation)
{
	TV_DECLARE (end_handshake);

	/* notify the profiler of the leftovers */
	/* FIXME this is the wrong spot at we can STW for non collection reasons. */
	if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES))
		mono_sgen_gc_event_moves ();

	acquire_gc_locks ();

	mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation);

	/* We start to scan after locks are taking, this ensures we won't be interrupted. */
	sgen_process_togglerefs ();

	update_current_thread_stack (&generation);

	sgen_global_stop_count++;
	SGEN_LOG (3, "stopping world n %d from %p %p", sgen_global_stop_count, mono_thread_info_current (), (gpointer) (gsize) mono_native_thread_id_get ());
	TV_GETTIME (stop_world_time);

	if (mono_thread_info_unified_management_enabled ()) {
		sgen_unified_suspend_stop_world ();
	} else {
		int count, dead;
		count = sgen_thread_handshake (TRUE);
		dead = restart_threads_until_none_in_managed_allocator ();
		if (count < dead)
			g_error ("More threads have died (%d) that been initialy suspended %d", dead, count);
	}

	SGEN_LOG (3, "world stopped");

	TV_GETTIME (end_handshake);
	time_stop_world += TV_ELAPSED (stop_world_time, end_handshake);

	sgen_memgov_collection_start (generation);
	if (sgen_need_bridge_processing ())
		sgen_bridge_reset_data ();
}