Example #1
0
void
mono_thread_pool_cleanup (void)
{
	if (InterlockedExchange (&async_io_tp.pool_status, 2) == 1) {
		socket_io_cleanup (&socket_io_data); /* Empty when DISABLE_SOCKETS is defined */
		threadpool_kill_idle_threads (&async_io_tp);
	}

	if (async_io_tp.queue != NULL) {
		MONO_SEM_DESTROY (&async_io_tp.new_job);
		threadpool_free_queue (&async_io_tp);
	}


	if (InterlockedExchange (&async_tp.pool_status, 2) == 1) {
		threadpool_kill_idle_threads (&async_tp);
		threadpool_free_queue (&async_tp);
	}

	if (wsqs) {
		EnterCriticalSection (&wsqs_lock);
		mono_wsq_cleanup ();
		if (wsqs)
			g_ptr_array_free (wsqs, TRUE);
		wsqs = NULL;
		LeaveCriticalSection (&wsqs_lock);
		MONO_SEM_DESTROY (&async_tp.new_job);
	}
}
HANDLE
mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid)
{
    pthread_attr_t attr;
    int res;
    pthread_t thread;
    StartInfo start_info;

    res = pthread_attr_init (&attr);
    g_assert (!res);

    if (stack_size == 0) {
#if HAVE_VALGRIND_MEMCHECK_H
        if (RUNNING_ON_VALGRIND)
            stack_size = 1 << 20;
        else
            stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024;
#else
        stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024;
#endif
    }

#ifdef PTHREAD_STACK_MIN
    if (stack_size < PTHREAD_STACK_MIN)
        stack_size = PTHREAD_STACK_MIN;
#endif

#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
    res = pthread_attr_setstacksize (&attr, stack_size);
    g_assert (!res);
#endif

    memset (&start_info, 0, sizeof (StartInfo));
    start_info.start_routine = (void *(*)(void *)) start_routine;
    start_info.arg = arg;
    start_info.flags = creation_flags;
    MONO_SEM_INIT (&(start_info.registered), 0);

    /* Actually start the thread */
    res = mono_gc_pthread_create (&thread, &attr, inner_start_thread, &start_info);
    if (res) {
        MONO_SEM_DESTROY (&(start_info.registered));
        return NULL;
    }

    MONO_TRY_BLOCKING;
    /* Wait until the thread register itself in various places */
    while (MONO_SEM_WAIT (&(start_info.registered)) != 0) {
        /*if (EINTR != errno) ABORT("sem_wait failed"); */
    }
    MONO_FINISH_TRY_BLOCKING;

    MONO_SEM_DESTROY (&(start_info.registered));

    if (out_tid)
        *out_tid = thread;

    return start_info.handle;
}
Example #3
0
static void
free_thread_info (gpointer mem)
{
	MonoThreadInfo *info = mem;

	MONO_SEM_DESTROY (&info->suspend_semaphore);
	MONO_SEM_DESTROY (&info->resume_semaphore);
	MONO_SEM_DESTROY (&info->finish_resume_semaphore);
	mono_threads_platform_free (info);

	g_free (info);
}
Example #4
0
void _wapi_thread_set_termination_details (gpointer handle,
					   guint32 exitstatus)
{
	struct _WapiHandle_thread *thread_handle;
	gboolean ok;
	int thr_ret;
	
	if (_wapi_handle_issignalled (handle) ||
	    _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
		/* We must have already deliberately finished with
		 * this thread, so don't do any more now
		 */
		return;
	}

#ifdef DEBUG
	g_message ("%s: Thread %p terminating", __func__, handle);
#endif

	_wapi_thread_abandon_mutexes (handle);
	
	ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
				  (gpointer *)&thread_handle);
	if (ok == FALSE) {
		g_warning ("%s: error looking up thread handle %p", __func__,
			   handle);

		return;
	}
	
	pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
			      handle);
	thr_ret = _wapi_handle_lock_handle (handle);
	g_assert (thr_ret == 0);
	
	thread_handle->exitstatus = exitstatus;
	thread_handle->state = THREAD_STATE_EXITED;
	MONO_SEM_DESTROY (&thread_handle->suspend_sem);
	g_ptr_array_free (thread_handle->owned_mutexes, TRUE);

	_wapi_handle_set_signal_state (handle, TRUE, TRUE);

	thr_ret = _wapi_handle_unlock_handle (handle);
	g_assert (thr_ret == 0);
	pthread_cleanup_pop (0);
	
#ifdef DEBUG
	g_message("%s: Recording thread handle %p id %ld status as %d",
		  __func__, handle, thread_handle->id, exitstatus);
#endif
	
	/* The thread is no longer active, so unref it */
	_wapi_handle_unref (handle);
}
Example #5
0
void
mono_thread_pool_cleanup (void)
{
	if (InterlockedExchange (&async_io_tp.pool_status, 2) == 1) {
		socket_io_cleanup (&socket_io_data); /* Empty when DISABLE_SOCKETS is defined */
		threadpool_kill_idle_threads (&async_io_tp);
	}

	if (async_io_tp.queue != NULL) {
		MONO_SEM_DESTROY (&async_io_tp.new_job);
		threadpool_free_queue (&async_io_tp);
	}


	if (InterlockedExchange (&async_tp.pool_status, 2) == 1) {
		threadpool_kill_idle_threads (&async_tp);
		threadpool_free_queue (&async_tp);
	}
	
	if (threads) {
		mono_mutex_lock (&threads_lock);
		if (threads)
			g_ptr_array_free (threads, FALSE);
		threads = NULL;
		mono_mutex_unlock (&threads_lock);
	}

	if (wsqs) {
		mono_mutex_lock (&wsqs_lock);
		mono_wsq_cleanup ();
		if (wsqs)
			g_ptr_array_free (wsqs, TRUE);
		wsqs = NULL;
		mono_mutex_unlock (&wsqs_lock);
		MONO_SEM_DESTROY (&async_tp.new_job);
	}

	MONO_SEM_DESTROY (&monitor_sem);
}
Example #6
0
static void*
inner_start_thread (void *arg)
{
	StartInfo *start_info = (StartInfo *) arg;
	void *t_arg = start_info->arg;
	int res;
	void *(*start_func)(void*) = start_info->start_routine;
	guint32 flags = start_info->flags;
	void *result;
	HANDLE handle;
	MonoThreadInfo *info;

	/* Register the thread with the io-layer */
	handle = wapi_create_thread_handle ();
	if (!handle) {
		res = MONO_SEM_POST (&(start_info->registered));
		g_assert (!res);
		return NULL;
	}
	start_info->handle = handle;

	info = mono_thread_info_attach (&result);
	MONO_PREPARE_BLOCKING

	info->runtime_thread = TRUE;
	info->handle = handle;

	if (flags & CREATE_SUSPENDED) {
		info->create_suspended = TRUE;
		MONO_SEM_INIT (&info->create_suspended_sem, 0);
	}

	/* start_info is not valid after this */
	res = MONO_SEM_POST (&(start_info->registered));
	g_assert (!res);
	start_info = NULL;

	if (flags & CREATE_SUSPENDED) {
		while (MONO_SEM_WAIT (&info->create_suspended_sem) != 0 &&
			   errno == EINTR);
		MONO_SEM_DESTROY (&info->create_suspended_sem);
	}

	MONO_FINISH_BLOCKING
	/* Run the actual main function of the thread */
	result = start_func (t_arg);

	mono_threads_core_exit (GPOINTER_TO_UINT (result));
	g_assert_not_reached ();
}
Example #7
0
static void
tp_poll_shutdown (gpointer event_data)
{
	tp_poll_data *data = event_data;

#ifdef HOST_WIN32
	closesocket (data->pipe [0]);
	closesocket (data->pipe [1]);
#else
	if (data->pipe [0] > -1)
		close (data->pipe [0]);
	if (data->pipe [1] > -1)
		close (data->pipe [1]);
#endif
	data->pipe [0] = -1;
	data->pipe [1] = -1;
	MONO_SEM_DESTROY (&data->new_sem);
}
Example #8
0
HANDLE
mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid)
{
	ThreadStartInfo *start_info;
	HANDLE result;
	DWORD thread_id;

	start_info = g_malloc0 (sizeof (ThreadStartInfo));
	if (!start_info)
		return NULL;
	MONO_SEM_INIT (&(start_info->registered), 0);
	start_info->arg = arg;
	start_info->start_routine = start_routine;
	start_info->suspend = creation_flags & CREATE_SUSPENDED;
	creation_flags &= ~CREATE_SUSPENDED;
	if (start_info->suspend) {
		start_info->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL);
		if (!start_info->suspend_event)
			return NULL;
	}

	result = CreateThread (NULL, stack_size, inner_start_thread, start_info, creation_flags, &thread_id);
	if (result) {
		while (MONO_SEM_WAIT (&(start_info->registered)) != 0) {
			/*if (EINTR != errno) ABORT("sem_wait failed"); */
		}
		if (start_info->suspend) {
			g_assert (SuspendThread (result) != (DWORD)-1);
			SetEvent (start_info->suspend_event);
		}
	} else if (start_info->suspend) {
		CloseHandle (start_info->suspend_event);
	}
	if (out_tid)
		*out_tid = thread_id;
	MONO_SEM_DESTROY (&(start_info->registered));
	g_free (start_info);
	return result;
}
Example #9
0
int
mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
{
	ThreadStartInfo *start_info;
	int result;

	start_info = g_malloc0 (sizeof (ThreadStartInfo));
	if (!start_info)
		return ENOMEM;
	MONO_SEM_INIT (&(start_info->registered), 0);
	start_info->arg = arg;
	start_info->start_routine = start_routine;

	result = mono_threads_get_callbacks ()->mono_gc_pthread_create (new_thread, attr, inner_start_thread, start_info);
	if (result == 0) {
		while (MONO_SEM_WAIT (&(start_info->registered)) != 0) {
			/*if (EINTR != errno) ABORT("sem_wait failed"); */
		}
	}
	MONO_SEM_DESTROY (&(start_info->registered));
	g_free (start_info);
	return result;
}
Example #10
0
static void*
inner_start_thread (void *arg)
{
	StartInfo *start_info = arg;
	void *t_arg = start_info->arg;
	int res;
	void *(*start_func)(void*) = start_info->start_routine;
	guint32 flags = start_info->flags;
	void *result;
	HANDLE handle;
	MonoThreadInfo *info;

	/* Register the thread with the io-layer */
	handle = wapi_create_thread_handle ();
	if (!handle) {
		res = MONO_SEM_POST (&(start_info->registered));
		g_assert (!res);
		return NULL;
	}
	start_info->handle = handle;

	info = mono_thread_info_attach (&result);
	info->runtime_thread = TRUE;
	info->handle = handle;

	if (flags & CREATE_SUSPENDED) {
		info->create_suspended = TRUE;
		MONO_SEM_INIT (&info->create_suspended_sem, 0);
	}

	/* start_info is not valid after this */
	res = MONO_SEM_POST (&(start_info->registered));
	g_assert (!res);
	start_info = NULL;

	if (flags & CREATE_SUSPENDED) {
		while (MONO_SEM_WAIT (&info->create_suspended_sem) != 0 &&
			   errno == EINTR);
		MONO_SEM_DESTROY (&info->create_suspended_sem);
	}

	/* Run the actual main function of the thread */
	result = start_func (t_arg);

	/*
	mono_thread_info_detach ();
	*/

#if defined(__native_client__)
	nacl_shutdown_gc_thread();
#endif

	wapi_thread_handle_set_exited (handle, GPOINTER_TO_UINT (result));
	/* This is needed by mono_threads_core_unregister () which is called later */
	info->handle = NULL;

	g_assert (mono_threads_get_callbacks ()->thread_exit);
	mono_threads_get_callbacks ()->thread_exit (NULL);
	g_assert_not_reached ();
	return result;
}
Example #11
0
void
mono_threads_platform_free (MonoThreadInfo *info)
{
	MONO_SEM_DESTROY (&info->begin_suspend_semaphore);
}