Author: mprobst
Date: 2007-11-09 04:37:12 -0500 (Fri, 09 Nov 2007)
New Revision: 89306

Modified:
   trunk/mono/mono/metadata/ChangeLog
   trunk/mono/mono/metadata/gc-internal.h
   trunk/mono/mono/metadata/gc.c
   trunk/mono/mono/metadata/threadpool.c
   trunk/mono/mono/metadata/threads-types.h
   trunk/mono/mono/metadata/threads.c
Log:
2007-11-09  Mark Probst  <[EMAIL PROTECTED]>

        * gc.c, gc-internal.h: Don't finalize threadpool threads with
        other objects, because the threadpool is still around.  Put them
        in a list instead and after finalizing all other objects in the
        root domain shut down the thread pool and then finalize the
        threads.  Fixes bug #337383.

        * threads.c, thread-types.h: New mono_thread_create_internal()
        function for marking a thread with the threadpool flag before it
        started.  Set synch_cs to NULL after freeing it.

        * threadpool.c: Mark threadpool threads before they start.


Modified: trunk/mono/mono/metadata/ChangeLog
===================================================================
--- trunk/mono/mono/metadata/ChangeLog  2007-11-09 08:48:09 UTC (rev 89305)
+++ trunk/mono/mono/metadata/ChangeLog  2007-11-09 09:37:12 UTC (rev 89306)
@@ -1,4 +1,17 @@
+2007-11-09  Mark Probst  <[EMAIL PROTECTED]>
 
+       * gc.c, gc-internal.h: Don't finalize threadpool threads with
+       other objects, because the threadpool is still around.  Put them
+       in a list instead and after finalizing all other objects in the
+       root domain shut down the thread pool and then finalize the
+       threads.  Fixes bug #337383.
+
+       * threads.c, thread-types.h: New mono_thread_create_internal()
+       function for marking a thread with the threadpool flag before it
+       started.  Set synch_cs to NULL after freeing it.
+
+       * threadpool.c: Mark threadpool threads before they start.
+
 Thu Nov 8 15:31:21 CET 2007 Paolo Molaro <[EMAIL PROTECTED]>
 
        * reflection.h, reflection.c: don't export random functions

Modified: trunk/mono/mono/metadata/gc-internal.h
===================================================================
--- trunk/mono/mono/metadata/gc-internal.h      2007-11-09 08:48:09 UTC (rev 
89305)
+++ trunk/mono/mono/metadata/gc-internal.h      2007-11-09 09:37:12 UTC (rev 
89306)
@@ -88,6 +88,8 @@
 void  mono_gc_deregister_root (char* addr) MONO_INTERNAL;
 int   mono_gc_finalizers_for_domain (MonoDomain *domain, MonoObject 
**out_array, int out_size) MONO_INTERNAL;
 
+void  mono_gc_finalize_threadpool_threads (void) MONO_INTERNAL;
+
 /* fast allocation support */
 MonoMethod* mono_gc_get_managed_allocator (MonoVTable *vtable, gboolean 
for_box) MONO_INTERNAL;
 int mono_gc_get_managed_allocator_type (MonoMethod *managed_alloc) 
MONO_INTERNAL;

Modified: trunk/mono/mono/metadata/gc.c
===================================================================
--- trunk/mono/mono/metadata/gc.c       2007-11-09 08:48:09 UTC (rev 89305)
+++ trunk/mono/mono/metadata/gc.c       2007-11-09 09:37:12 UTC (rev 89306)
@@ -18,6 +18,8 @@
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/domain-internals.h>
 #include <mono/metadata/class-internals.h>
+#include <mono/metadata/mono-mlist.h>
+#include <mono/metadata/threadpool.h>
 #include <mono/utils/mono-logger.h>
 #include <mono/os/gc_wrapper.h>
 #include <mono/metadata/marshal.h> /* for mono_delegate_free_ftnptr () */
@@ -41,6 +43,7 @@
 static CRITICAL_SECTION finalizer_mutex;
 
 static GSList *domains_to_finalize= NULL;
+static MonoMList *threads_to_finalize = NULL;
 
 static MonoThread *gc_thread;
 
@@ -52,6 +55,16 @@
 static HANDLE thread_started_event;
 #endif
 
+static void
+add_thread_to_finalize (MonoThread *thread)
+{
+       mono_finalizer_lock ();
+       if (!threads_to_finalize)
+               MONO_GC_REGISTER_ROOT (threads_to_finalize);
+       threads_to_finalize = mono_mlist_append (threads_to_finalize, 
(MonoObject*)thread);
+       mono_finalizer_unlock ();
+}
+
 /* 
  * actually, we might want to queue the finalize requests in a separate thread,
  * but we need to be careful about the execution domain of the thread...
@@ -79,11 +92,21 @@
        /* make sure the finalizer is not called again if the object is 
resurrected */
        object_register_finalizer (obj, NULL);
 
-       if (o->vtable->klass == mono_get_thread_class ())
-               if (mono_gc_is_finalizer_thread ((MonoThread*)o))
+       if (o->vtable->klass == mono_get_thread_class ()) {
+               MonoThread *t = (MonoThread*)o;
+
+               if (mono_gc_is_finalizer_thread (t))
                        /* Avoid finalizing ourselves */
                        return;
 
+               if (t->threadpool_thread) {
+                       /* Don't finalize threadpool threads - they're
+                          finalized when the threadpool shuts down. */
+                       add_thread_to_finalize (t);
+                       return;
+               }
+       }
+
        /* speedup later... and use a timeout */
        /* g_print ("Finalize run on %p %s.%s\n", o, mono_object_class 
(o)->name_space, mono_object_class (o)->name); */
 
@@ -119,6 +142,22 @@
        }
 }
 
+void
+mono_gc_finalize_threadpool_threads (void)
+{
+       while (threads_to_finalize) {
+               MonoThread *thread = (MonoThread*) mono_mlist_get_data 
(threads_to_finalize);
+
+               /* Force finalization of the thread. */
+               thread->threadpool_thread = FALSE;
+               mono_object_register_finalizer ((MonoObject*)thread);
+
+               run_finalize (thread, NULL);
+
+               threads_to_finalize = mono_mlist_next (threads_to_finalize);
+       }
+}
+
 gpointer
 mono_gc_out_of_memory (size_t size)
 {
@@ -249,6 +288,12 @@
        }
 
        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 */

Modified: trunk/mono/mono/metadata/threadpool.c
===================================================================
--- trunk/mono/mono/metadata/threadpool.c       2007-11-09 08:48:09 UTC (rev 
89305)
+++ trunk/mono/mono/metadata/threadpool.c       2007-11-09 09:37:12 UTC (rev 
89306)
@@ -235,7 +235,6 @@
        MonoDomain *domain;
        MonoThread *thread;
        thread = mono_thread_current ();
-       thread->threadpool_thread = TRUE;
        ves_icall_System_Threading_Thread_SetState (thread, 
ThreadState_Background);
 
        for (;;) {
@@ -324,7 +323,7 @@
                InterlockedIncrement (&busy_io_worker_threads);
                InterlockedIncrement (&io_worker_threads);
                domain = ((ares) ? ((MonoObject *) ares)->vtable->domain : 
mono_domain_get ());
-               mono_thread_create (mono_get_root_domain (), 
async_invoke_io_thread, ares);
+               mono_thread_create_internal (mono_get_root_domain (), 
async_invoke_io_thread, ares, TRUE);
        } else {
                append_job (&io_queue_lock, &async_io_queue, (MonoObject*)ares);
                ReleaseSemaphore (io_job_added, 1, NULL);
@@ -396,7 +395,6 @@
        MonoThread *thread;
 
        thread = mono_thread_current ();
-       thread->threadpool_thread = TRUE;
        ves_icall_System_Threading_Thread_SetState (thread, 
ThreadState_Background);
 
        allocated = INITIAL_POLLFD_SIZE;
@@ -766,11 +764,11 @@
        g_assert (io_job_added != NULL);
        InitializeCriticalSection (&io_queue_lock);
        if (data->epoll_disabled) {
-               mono_thread_create (mono_get_root_domain (), 
socket_io_poll_main, data);
+               mono_thread_create_internal (mono_get_root_domain (), 
socket_io_poll_main, data, TRUE);
        }
 #ifdef HAVE_EPOLL
        else {
-               mono_thread_create (mono_get_root_domain (), 
socket_io_epoll_main, data);
+               mono_thread_create_internal (mono_get_root_domain (), 
socket_io_epoll_main, data, TRUE);
        }
 #endif
        InterlockedCompareExchange (&data->inited, 1, 0);
@@ -1053,7 +1051,7 @@
            worker < mono_max_worker_threads) {
                InterlockedIncrement (&mono_worker_threads);
                InterlockedIncrement (&busy_worker_threads);
-               mono_thread_create (mono_get_root_domain (), 
async_invoke_thread, ares);
+               mono_thread_create_internal (mono_get_root_domain (), 
async_invoke_thread, ares, TRUE);
        } else {
                append_job (&mono_delegate_section, &async_call_queue, 
(MonoObject*)ares);
                ReleaseSemaphore (job_added, 1, NULL);

Modified: trunk/mono/mono/metadata/threads-types.h
===================================================================
--- trunk/mono/mono/metadata/threads-types.h    2007-11-09 08:48:09 UTC (rev 
89305)
+++ trunk/mono/mono/metadata/threads-types.h    2007-11-09 09:37:12 UTC (rev 
89306)
@@ -42,6 +42,8 @@
 #define SPECIAL_STATIC_THREAD 1
 #define SPECIAL_STATIC_CONTEXT 2
 
+extern void mono_thread_create_internal (MonoDomain *domain, gpointer func, 
gpointer arg, gboolean threadpool_thread) MONO_INTERNAL;
+
 extern HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread 
*this_obj, MonoObject *start) MONO_INTERNAL;
 extern void ves_icall_System_Threading_Thread_Thread_init(MonoThread 
*this_obj) MONO_INTERNAL;
 extern void ves_icall_System_Threading_Thread_Thread_free_internal(MonoThread 
*this_obj, HANDLE thread) MONO_INTERNAL;

Modified: trunk/mono/mono/metadata/threads.c
===================================================================
--- trunk/mono/mono/metadata/threads.c  2007-11-09 08:48:09 UTC (rev 89305)
+++ trunk/mono/mono/metadata/threads.c  2007-11-09 09:37:12 UTC (rev 89306)
@@ -602,7 +602,7 @@
        return default_stacksize;
 }
 
-void mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg)
+void mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer 
arg, gboolean threadpool_thread)
 {
        MonoThread *thread;
        HANDLE thread_handle;
@@ -637,12 +637,20 @@
 
        thread->synch_cs = g_new0 (CRITICAL_SECTION, 1);
        InitializeCriticalSection (thread->synch_cs);
-                                                 
+
+       thread->threadpool_thread = threadpool_thread;
+
        handle_store(thread);
 
        ResumeThread (thread_handle);
 }
 
+void
+mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg)
+{
+       mono_thread_create_internal (domain, func, arg, FALSE);
+}
+
 /*
  * mono_thread_get_stack_bounds:
  *
@@ -890,6 +898,7 @@
 
        DeleteCriticalSection (this->synch_cs);
        g_free (this->synch_cs);
+       this->synch_cs = NULL;
 }
 
 static void mono_thread_start (MonoThread *thread)

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to