X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=blobdiff_plain;f=mono%2Fmetadata%2Fgc.c;h=2cff646db1771c099780ffccbf618800d049a270;hp=077251c7b1e7b95e0ec13895562a79111a735f90;hb=6b139f4c98eb90bfb7e1285933fc682dae541cad;hpb=6277ba55de75c3a760ba030e112485a623c02d89 diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 077251c7b1e..2cff646db17 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -6,6 +6,7 @@ * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com) * Copyright 2004-2009 Novell, Inc (http://www.novell.com) * Copyright 2012 Xamarin Inc (http://www.xamarin.com) + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include @@ -39,6 +40,7 @@ #include #include #include +#include #ifndef HOST_WIN32 #include @@ -451,6 +453,8 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout) mono_gc_finalize_threadpool_threads (); } + mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD); + return TRUE; } @@ -638,6 +642,41 @@ mono_gc_finalize_notify (void) mono_coop_sem_post (&finalizer_sem); } +/* +This is the number of entries allowed in the hazard free queue before +we explicitly cycle the finalizer thread to trigger pumping the queue. + +It was picked empirically by running the corlib test suite in a stress +scenario where all hazard entries are queued. + +In this extreme scenario we double the number of times we cycle the finalizer +thread compared to just GC calls. + +Entries are usually in the order of 100's of bytes each, so we're limiting +floating garbage to be in the order of a dozen kb. +*/ +static gboolean finalizer_thread_pulsed; +#define HAZARD_QUEUE_OVERFLOW_SIZE 20 + +static void +hazard_free_queue_is_too_big (size_t size) +{ + if (size < HAZARD_QUEUE_OVERFLOW_SIZE) + return; + + if (finalizer_thread_pulsed || InterlockedCompareExchange (&finalizer_thread_pulsed, TRUE, FALSE)) + return; + + mono_gc_finalize_notify (); +} + +static void +hazard_free_queue_pump (void) +{ + mono_thread_hazardous_try_free_all (); + finalizer_thread_pulsed = FALSE; +} + #ifdef HAVE_BOEHM_GC static void @@ -711,8 +750,15 @@ finalize_domain_objects (DomainFinalizationReq *req) static guint32 finalizer_thread (gpointer unused) { + MonoError error; + mono_thread_set_name_internal (mono_thread_internal_current (), mono_string_new (mono_get_root_domain (), "Finalizer"), FALSE, &error); + mono_error_assert_ok (&error); + gboolean wait = TRUE; + /* Register a hazard free queue pump callback */ + mono_hazard_pointer_install_free_queue_size_callback (hazard_free_queue_is_too_big); + while (!finished) { /* Wait to be notified that there's at least one * finaliser to run @@ -757,6 +803,8 @@ finalizer_thread (gpointer unused) reference_queue_proccess_all (); + hazard_free_queue_pump (); + /* Avoid posting the pending done event until there are pending finalizers */ if (mono_coop_sem_timedwait (&finalizer_sem, 0, MONO_SEM_FLAGS_NONE) == 0) { /* Don't wait again at the start of the loop */ @@ -780,8 +828,9 @@ static void mono_gc_init_finalizer_thread (void) { - gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, FALSE, 0); - ves_icall_System_Threading_Thread_SetName_internal (gc_thread, mono_string_new (mono_domain_get (), "Finalizer")); + MonoError error; + gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, FALSE, 0, &error); + mono_error_assert_ok (&error); } void