Esempio n. 1
0
/* LOCKING: assumes the GC lock is held */
int
sgen_thread_handshake (BOOL suspend)
{
	SgenThreadInfo *cur_thread = mono_thread_info_current ();
	kern_return_t ret;

	int count = 0;

	cur_thread->client_info.suspend_done = TRUE;
	FOREACH_THREAD (info) {
		if (info == cur_thread || sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info)))
			continue;

		info->client_info.suspend_done = FALSE;
		if (info->client_info.gc_disabled)
			continue;

		if (suspend) {
			if (!sgen_suspend_thread (info))
				continue;
		} else {
			do {
				ret = thread_resume (info->client_info.info.native_handle);
			} while (ret == KERN_ABORTED);
			if (ret != KERN_SUCCESS)
				continue;
		}
		count ++;
	} FOREACH_THREAD_END
	return count;
}
Esempio n. 2
0
/* LOCKING: assumes the GC lock is held */
int
sgen_thread_handshake (BOOL suspend)
{
	SgenThreadInfo *cur_thread = mono_thread_info_current ();
	kern_return_t ret;
	SgenThreadInfo *info;

	int count = 0;

	cur_thread->suspend_done = TRUE;
	FOREACH_THREAD_SAFE (info) {
		if (info == cur_thread || sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info)))
			continue;

		info->suspend_done = FALSE;
		if (info->gc_disabled)
			continue;

		if (suspend) {
			if (!sgen_suspend_thread (info))
				continue;
		} else {
			ret = thread_resume (info->info.native_handle);
			if (ret != KERN_SUCCESS)
				continue;
		}
		count ++;
	} END_FOREACH_THREAD_SAFE
	return count;
}
Esempio n. 3
0
static gboolean
sgen_is_thread_in_current_stw (SgenThreadInfo *info, int *reason)
{
	/*
	A thread explicitly asked to be skiped because it holds no managed state.
	This is used by TP and finalizer threads.
	FIXME Use an atomic variable for this to avoid everyone taking the GC LOCK.
	*/
	if (info->client_info.gc_disabled) {
		if (reason)
			*reason = 1;
		return FALSE;
	}

	/*
	We have detected that this thread is failing/dying, ignore it.
	FIXME: can't we merge this with thread_is_dying?
	*/
	if (info->client_info.skip) {
		if (reason)
			*reason = 2;
		return FALSE;
	}

	/*
	Suspending the current thread will deadlock us, bad idea.
	*/
	if (info == mono_thread_info_current ()) {
		if (reason)
			*reason = 3;
		return FALSE;
	}

	/*
	We can't suspend the workers that will do all the heavy lifting.
	FIXME Use some state bit in SgenThreadInfo for this.
	*/
	if (sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info))) {
		if (reason)
			*reason = 4;
		return FALSE;
	}

	/*
	The thread has signaled that it started to detach, ignore it.
	FIXME: can't we merge this with skip
	*/
	if (!mono_thread_info_is_live (info)) {
		if (reason)
			*reason = 5;
		return FALSE;
	}

	return TRUE;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
static void
protocol_entry (unsigned char type, gpointer data, int size)
{
#ifdef HAVE_UNISTD_H
	int index;
	BinaryProtocolBuffer *buffer;

	if (binary_protocol_file == -1)
		return;

	if (sgen_thread_pool_is_thread_pool_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 ();
#endif
}