コード例 #1
0
ファイル: mono-threads.c プロジェクト: ItsVeryWindy/mono
/*
 * mono_threads_create_thread:
 *
 *   Create a new thread executing START with argument ARG. Store its id into OUT_TID.
 * Returns: a windows or io-layer handle for the thread.
 */
HANDLE
mono_threads_create_thread (MonoThreadStart start, gpointer arg, gsize * const stack_size, MonoNativeThreadId *out_tid)
{
	CreateThreadData *thread_data;
	gint res;
	gpointer ret;

	thread_data = g_new0 (CreateThreadData, 1);
	thread_data->ref = 2;
	thread_data->start_routine = start;
	thread_data->start_routine_arg = arg;
	mono_coop_sem_init (&thread_data->registered, 0);

	res = mono_threads_platform_create_thread (inner_start_thread, (gpointer) thread_data, stack_size, out_tid);
	if (res != 0) {
		/* ref is not going to be decremented in inner_start_thread */
		InterlockedDecrement (&thread_data->ref);
		ret = NULL;
		goto done;
	}

	res = mono_coop_sem_wait (&thread_data->registered, MONO_SEM_FLAGS_NONE);
	g_assert (res == 0);

	ret = thread_data->handle;
	g_assert (ret);

done:
	if (InterlockedDecrement (&thread_data->ref) == 0) {
		mono_coop_sem_destroy (&thread_data->registered);
		g_free (thread_data);
	}

	return ret;
}
コード例 #2
0
static void
create_thread_data_destroy (gpointer data)
{
	CreateThreadData *thread_data;

	thread_data = (CreateThreadData*) data;

	mono_coop_sem_destroy (&thread_data->registered);
	g_free (thread_data);
}
コード例 #3
0
static gsize WINAPI
inner_start_thread (gpointer data)
{
	CreateThreadData *thread_data;
	MonoThreadInfo *info;
	MonoThreadStart start_routine;
	gpointer start_routine_arg;
	guint32 start_routine_res;
	gint32 priority;
	gsize dummy;

	thread_data = (CreateThreadData*) data;
	g_assert (thread_data);

	start_routine = thread_data->start_routine;
	start_routine_arg = thread_data->start_routine_arg;

	priority = thread_data->priority;

	info = mono_thread_info_attach (&dummy);
	info->runtime_thread = TRUE;

	mono_threads_platform_set_priority (info, priority);

	thread_data->handle = mono_thread_info_duplicate_handle (info);

	mono_coop_sem_post (&thread_data->registered);

	if (InterlockedDecrement (&thread_data->ref) == 0) {
		mono_coop_sem_destroy (&thread_data->registered);
		g_free (thread_data);
	}

	/* thread_data is not valid anymore */
	thread_data = NULL;

	/* Run the actual main function of the thread */
	start_routine_res = start_routine (start_routine_arg);

	mono_threads_platform_exit (start_routine_res);

	g_assert_not_reached ();
}
コード例 #4
0
HANDLE
mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid)
{
	ThreadStartInfo *start_info;
	HANDLE result;
	DWORD thread_id;
	guint32 creation_flags = tp->creation_flags;
	int res;

	start_info = g_malloc0 (sizeof (ThreadStartInfo));
	if (!start_info)
		return NULL;
	mono_coop_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, tp->stack_size, inner_start_thread, start_info, creation_flags, &thread_id);
	if (result) {
		res = mono_coop_sem_wait (&(start_info->registered), MONO_SEM_FLAGS_NONE);
		g_assert (res != -1);

		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_coop_sem_destroy (&(start_info->registered));
	g_free (start_info);
	return result;
}
コード例 #5
0
gboolean
mono_domain_finalize (MonoDomain *domain, guint32 timeout) 
{
	DomainFinalizationReq *req;
	MonoInternalThread *thread = mono_thread_internal_current ();
	gint res;
	gboolean ret;
	gint64 start;

#if defined(__native_client__)
	return FALSE;
#endif

	if (mono_thread_internal_current () == gc_thread)
		/* We are called from inside a finalizer, not much we can do here */
		return FALSE;

	/* 
	 * No need to create another thread 'cause the finalizer thread
	 * is still working and will take care of running the finalizers
	 */ 
	
	if (gc_disabled)
		return TRUE;

	/* We don't support domain finalization without a GC */
	if (mono_gc_is_null ())
		return FALSE;

	mono_gc_collect (mono_gc_max_generation ());

	req = g_new0 (DomainFinalizationReq, 1);
	req->ref = 2;
	req->domain = domain;
	mono_coop_sem_init (&req->done, 0);

	if (domain == mono_get_root_domain ())
		finalizing_root_domain = TRUE;
	
	mono_finalizer_lock ();

	domains_to_finalize = g_slist_append (domains_to_finalize, req);

	mono_finalizer_unlock ();

	/* Tell the finalizer thread to finalize this appdomain */
	mono_gc_finalize_notify ();

	if (timeout == -1)
		timeout = INFINITE;
	if (timeout != INFINITE)
		start = mono_msec_ticks ();

	ret = TRUE;

	for (;;) {
		if (timeout == INFINITE) {
			res = mono_coop_sem_wait (&req->done, MONO_SEM_FLAGS_ALERTABLE);
		} else {
			gint64 elapsed = mono_msec_ticks () - start;
			if (elapsed >= timeout) {
				ret = FALSE;
				break;
			}

			res = mono_coop_sem_timedwait (&req->done, timeout - elapsed, MONO_SEM_FLAGS_ALERTABLE);
		}

		if (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
			break;
		} else if (res == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
			if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) {
				ret = FALSE;
				break;
			}
		} else if (res == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
			ret = FALSE;
			break;
		} else {
			g_error ("%s: unknown result %d", __func__, res);
		}
	}

	if (!ret) {
		/* Try removing the req from domains_to_finalize:
		 *  - if it's not found: the domain is being finalized,
		 *     so we the ref count is already decremented
		 *  - if it's found: the domain is not yet being finalized,
		 *     so we can safely decrement the ref */

		gboolean found;

		mono_finalizer_lock ();

		found = g_slist_index (domains_to_finalize, req) != -1;
		if (found)
			domains_to_finalize = g_slist_remove (domains_to_finalize, req);

		mono_finalizer_unlock ();

		if (found) {
			/* We have to decrement it wherever we
			 * remove it from domains_to_finalize */
			if (InterlockedDecrement (&req->ref) != 1)
				g_error ("%s: req->ref should be 1, as we are the first one to decrement it", __func__);
		}

		goto done;
	}

	if (domain == mono_get_root_domain ()) {
		mono_threadpool_ms_cleanup ();
		mono_gc_finalize_threadpool_threads ();
	}

done:
	if (InterlockedDecrement (&req->ref) == 0) {
		mono_coop_sem_destroy (&req->done);
		g_free (req);
	}

	return ret;
}