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