Beispiel #1
0
static void
add_thread_to_finalize (MonoInternalThread *thread)
{
	mono_finalizer_lock ();
	if (!threads_to_finalize)
		MONO_GC_REGISTER_ROOT_SINGLE (threads_to_finalize);
	threads_to_finalize = mono_mlist_append (threads_to_finalize, (MonoObject*)thread);
	mono_finalizer_unlock ();
}
Beispiel #2
0
static void
add_thread_to_finalize (MonoInternalThread *thread)
{
	mono_finalizer_lock ();
	if (!threads_to_finalize)
		MONO_GC_REGISTER_ROOT_SINGLE (threads_to_finalize, MONO_ROOT_SOURCE_FINALIZER_QUEUE, "finalizable threads list");
	threads_to_finalize = mono_mlist_append (threads_to_finalize, (MonoObject*)thread);
	mono_finalizer_unlock ();
}
Beispiel #3
0
Datei: gc.c Projekt: Numpsy/mono
static gboolean
add_thread_to_finalize (MonoInternalThread *thread, MonoError *error)
{
	mono_error_init (error);
	mono_finalizer_lock ();
	if (!threads_to_finalize)
		MONO_GC_REGISTER_ROOT_SINGLE (threads_to_finalize, MONO_ROOT_SOURCE_FINALIZER_QUEUE, "finalizable threads list");
	threads_to_finalize = mono_mlist_append_checked (threads_to_finalize, (MonoObject*)thread, error);
	mono_finalizer_unlock ();
	return is_ok (error);
}
Beispiel #4
0
gboolean
mono_domain_finalize (MonoDomain *domain, guint32 timeout) 
{
	DomainFinalizationReq *req;
	guint32 res;
	HANDLE done_event;
	MonoInternalThread *thread = mono_thread_internal_current ();

	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
	 */ 
	
#ifndef HAVE_NULL_GC
	if (gc_disabled)
		return TRUE;

	mono_gc_collect (mono_gc_max_generation ());

	done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
	if (done_event == NULL) {
		return FALSE;
	}

	req = g_new0 (DomainFinalizationReq, 1);
	req->domain = domain;
	req->done_event = done_event;

	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;

	while (TRUE) {
		res = WaitForSingleObjectEx (done_event, timeout, TRUE);
		/* printf ("WAIT RES: %d.\n", res); */

		if (res == WAIT_IO_COMPLETION) {
			if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0)
				return FALSE;
		} else if (res == WAIT_TIMEOUT) {
			/* We leak the handle here */
			return FALSE;
		} else {
			break;
		}
	}

	CloseHandle (done_event);

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

	return TRUE;
#else
	/* We don't support domain finalization without a GC */
	return FALSE;
#endif
}
Beispiel #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;
}