Hi,

This is a quite small patch removing the wait form mono_gc_init by modifying mono_thread_create_internal to return the MonoThread object.

Getting rid of the wait is required for support loading the runtime from DLL initialization code on Windows because DLL load and initialization is protected by the same lock as thread creation so this lock always results in a deadlock.

Removing this wait on other platform should make startup faster.

I was unable to reproduce any deadlock resulting from this wait, I only was able to reproduce a socket accept deadlock (Windows-only bug) that was discussed on the list earlier and is not related to this wait.

I belive that this patch should eliminate the deadlock that the removed wait is intended to prevent. If you still are able to reproduce the deadlock, please attach exact stack trace for deadlocked threads and I'll try solve the issue.

Please review the patch and if you like it please approve it.

Kornél
Index: mono/metadata/gc.c
===================================================================
--- mono/metadata/gc.c	(revision 133825)
+++ mono/metadata/gc.c	(working copy)
@@ -73,7 +73,6 @@
 #ifndef HAVE_NULL_GC
 static HANDLE pending_done_event;
 static HANDLE shutdown_event;
-static HANDLE thread_started_event;
 #endif
 
 static void
@@ -992,10 +991,6 @@
 static guint32
 finalizer_thread (gpointer unused)
 {
-	gc_thread = mono_thread_current ();
-
-	SetEvent (thread_started_event);
-
 	while (!finished) {
 		/* Wait to be notified that there's at least one
 		 * finaliser to run
@@ -1057,26 +1052,14 @@
 	finalizer_event = CreateEvent (NULL, FALSE, FALSE, NULL);
 	pending_done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
 	shutdown_event = CreateEvent (NULL, TRUE, FALSE, NULL);
-	thread_started_event = CreateEvent (NULL, TRUE, FALSE, NULL);
-	if (finalizer_event == NULL || pending_done_event == NULL || shutdown_event == NULL || thread_started_event == NULL) {
+	if (finalizer_event == NULL || pending_done_event == NULL || shutdown_event == NULL) {
 		g_assert_not_reached ();
 	}
 #if USE_POSIX_SEM
 	sem_init (&finalizer_sem, 0, 0);
 #endif
 
-	mono_thread_create (mono_domain_get (), finalizer_thread, NULL);
-
-	/*
-	 * Wait until the finalizer thread sets gc_thread since its value is needed
-	 * by mono_thread_attach ()
-	 *
-	 * FIXME: Eliminate this as to avoid some deadlocks on windows. 
-	 * Waiting for a new thread should result in a deadlock when the runtime is
-	 * initialized from _CorDllMain that is called while the OS loader lock is
-	 * held by LoadLibrary.
-	 */
-	WaitForSingleObjectEx (thread_started_event, INFINITE, FALSE);
+	gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, FALSE);
 }
 
 void
Index: mono/metadata/threads.c
===================================================================
--- mono/metadata/threads.c	(revision 133825)
+++ mono/metadata/threads.c	(working copy)
@@ -701,7 +701,7 @@
 	return res;
 }
 
-void mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread)
+MonoThread* mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread)
 {
 	MonoThread *thread;
 	HANDLE thread_handle;
@@ -726,7 +726,7 @@
 	mono_threads_lock ();
 	if (shutting_down) {
 		mono_threads_unlock ();
-		return;
+		return NULL;
 	}
 	if (threads_starting_up == NULL) {
 		MONO_GC_REGISTER_ROOT (threads_starting_up);
@@ -749,7 +749,7 @@
 		mono_threads_unlock ();
 		g_free (start_info);
 		mono_raise_exception (mono_get_exception_execution_engine ("Couldn't create thread"));
-		return;
+		return NULL;
 	}
 
 	thread->handle=thread_handle;
@@ -766,6 +766,8 @@
 
 	if (handle_store (thread))
 		ResumeThread (thread_handle);
+
+	return thread;
 }
 
 void
Index: mono/metadata/threads-types.h
===================================================================
--- mono/metadata/threads-types.h	(revision 133825)
+++ mono/metadata/threads-types.h	(working copy)
@@ -53,7 +53,7 @@
 							 guint32 stacksize, WapiThreadStart start,
 							 gpointer param, guint32 create, gsize *tid) MONO_INTERNAL;
 
-void mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread) MONO_INTERNAL;
+MonoThread* mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread) MONO_INTERNAL;
 
 HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this_obj, MonoObject *start) MONO_INTERNAL;
 void ves_icall_System_Threading_Thread_Thread_init(MonoThread *this_obj) MONO_INTERNAL;
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to