X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fgc.c;h=c6e01da6f6ef32d68c6ae1474bb227da0ac1b85c;hb=3f011fdb1d5afcb204821af8628830e7c4cbd050;hp=38c62a20fb3b6385efd606d89d31afd194e12334;hpb=0aedc3f6fb2194817c766659c50a7e7f4786672e;p=mono.git diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 38c62a20fb3..c6e01da6f6e 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -5,6 +5,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) */ #include @@ -23,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +33,7 @@ #include #include #include +#include #ifndef HOST_WIN32 #include @@ -74,6 +77,8 @@ static HANDLE pending_done_event; static HANDLE shutdown_event; #endif +GCStats gc_stats; + static void add_thread_to_finalize (MonoInternalThread *thread) { @@ -224,9 +229,8 @@ mono_gc_run_finalize (void *obj, void *data) runtime_invoke (o, NULL, &exc, NULL); - if (exc) { - /* fixme: do something useful */ - } + if (exc) + mono_internal_thread_unhandled_exception (exc); mono_domain_set_internal (caller_domain); } @@ -484,6 +488,13 @@ ves_icall_System_GC_WaitForPendingFinalizers (void) /* Avoid deadlocks */ return; + /* + If the finalizer thread is not live, lets pretend no finalizers are pending since the current thread might + be the one responsible for starting it up. + */ + if (gc_thread == NULL) + return; + ResetEvent (pending_done_event); mono_gc_finalize_notify (); /* g_print ("Waiting for pending finalizers....\n"); */ @@ -618,6 +629,16 @@ find_first_unset (guint32 bitmap) return -1; } +static void* +make_root_descr_all_refs (int numbits, gboolean pinned) +{ +#ifdef HAVE_SGEN_GC + if (pinned) + return NULL; +#endif + return mono_gc_make_root_descr_all_refs (numbits); +} + static guint32 alloc_handle (HandleData *handles, MonoObject *obj, gboolean track) { @@ -627,7 +648,7 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track) if (!handles->size) { handles->size = 32; if (handles->type > HANDLE_WEAK_TRACK) { - handles->entries = mono_gc_alloc_fixed (sizeof (gpointer) * handles->size, mono_gc_make_root_descr_all_refs (handles->size)); + handles->entries = mono_gc_alloc_fixed (sizeof (gpointer) * handles->size, make_root_descr_all_refs (handles->size, handles->type == HANDLE_PINNED)); } else { handles->entries = g_malloc0 (sizeof (gpointer) * handles->size); handles->domain_ids = g_malloc0 (sizeof (guint16) * handles->size); @@ -665,8 +686,8 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track) if (handles->type > HANDLE_WEAK_TRACK) { gpointer *entries; - entries = mono_gc_alloc_fixed (sizeof (gpointer) * new_size, mono_gc_make_root_descr_all_refs (new_size)); - memcpy (entries, handles->entries, sizeof (gpointer) * handles->size); + entries = mono_gc_alloc_fixed (sizeof (gpointer) * new_size, make_root_descr_all_refs (new_size, handles->type == HANDLE_PINNED)); + mono_gc_memmove (entries, handles->entries, sizeof (gpointer) * handles->size); mono_gc_free_fixed (handles->entries); handles->entries = entries; @@ -677,8 +698,8 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track) entries = g_malloc (sizeof (gpointer) * new_size); /* we disable GC because we could lose some disappearing link updates */ mono_gc_disable (); - memcpy (entries, handles->entries, sizeof (gpointer) * handles->size); - memset (entries + handles->size, 0, sizeof (gpointer) * handles->size); + mono_gc_memmove (entries, handles->entries, sizeof (gpointer) * handles->size); + mono_gc_bzero (entries + handles->size, sizeof (gpointer) * handles->size); memcpy (domain_ids, handles->domain_ids, sizeof (guint16) * handles->size); for (i = 0; i < handles->size; ++i) { MonoObject *obj = mono_gc_weak_link_get (&(handles->entries [i])); @@ -712,7 +733,9 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track) mono_gc_weak_link_add (&(handles->entries [slot]), obj, track); } +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->gc_num_handles++; +#endif unlock_handles (handles); /*g_print ("allocated entry %d of type %d to object %p (in slot: %p)\n", slot, handles->type, obj, handles->entries [slot]);*/ res = (slot << 3) | (handles->type + 1); @@ -920,7 +943,9 @@ mono_gchandle_free (guint32 gchandle) } else { /* print a warning? */ } +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->gc_num_handles--; +#endif /*g_print ("freed entry %d of type %d\n", slot, handles->type);*/ unlock_handles (handles); mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_DESTROYED, handles->type, gchandle, NULL); @@ -1012,6 +1037,15 @@ finalize_domain_objects (DomainFinalizationReq *req) { MonoDomain *domain = req->domain; +#if HAVE_SGEN_GC +#define NUM_FOBJECTS 64 + MonoObject *to_finalize [NUM_FOBJECTS]; + int count; +#endif + + /* Process finalizers which are already in the queue */ + mono_gc_invoke_finalizers (); + #ifdef HAVE_BOEHM_GC while (g_hash_table_size (domain->finalizable_objects_hash) > 0) { int i; @@ -1034,9 +1068,6 @@ finalize_domain_objects (DomainFinalizationReq *req) g_ptr_array_free (objs, TRUE); } #elif defined(HAVE_SGEN_GC) -#define NUM_FOBJECTS 64 - MonoObject *to_finalize [NUM_FOBJECTS]; - int count; while ((count = mono_gc_finalizers_for_domain (domain, to_finalize, NUM_FOBJECTS))) { int i; for (i = 0; i < count; ++i) { @@ -1045,9 +1076,6 @@ finalize_domain_objects (DomainFinalizationReq *req) } #endif - /* Process finalizers which are already in the queue */ - mono_gc_invoke_finalizers (); - /* cleanup the reference queue */ reference_queue_clear_for_domain (domain); @@ -1110,6 +1138,16 @@ finalizer_thread (gpointer unused) return 0; } +#ifndef LAZY_GC_THREAD_CREATION +static +#endif +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")); +} + void mono_gc_init (void) { @@ -1122,6 +1160,11 @@ mono_gc_init (void) MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_NORMAL].entries); MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_PINNED].entries); + mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.minor_gc_count); + mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.major_gc_count); + mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &gc_stats.minor_gc_time_usecs); + mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &gc_stats.major_gc_time_usecs); + mono_gc_base_init (); if (mono_gc_is_disabled ()) { @@ -1139,8 +1182,9 @@ mono_gc_init (void) MONO_SEM_INIT (&finalizer_sem, 0); #endif - 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")); +#ifndef LAZY_GC_THREAD_CREATION + mono_gc_init_finalizer_thread (); +#endif } void @@ -1308,9 +1352,19 @@ mono_gc_parse_environment_string_extract_number (const char *str, glong *out) return FALSE; if (is_suffix) { + gulong unshifted; + + if (val < 0) /* negative numbers cannot be suffixed */ + return FALSE; if (*(endptr + 1)) /* Invalid string. */ return FALSE; + + unshifted = (gulong)val; val <<= shift; + if (val < 0) /* overflow */ + return FALSE; + if (((gulong)val >> shift) != unshifted) /* value too large */ + return FALSE; } *out = val; @@ -1532,7 +1586,7 @@ mono_gc_bzero (void *dest, size_t size) { char *p = (char*)dest; char *end = p + size; - char *align_end = p + unaligned_bytes (p); + char *align_end = align_up (p); char *word_end; while (p < align_end)