Merge pull request #1132 from mattleibow/bugfix-20925
[mono.git] / mono / metadata / gc.c
index 6ad2c6fa1827064176ee131b0c73c6f593ae5883..3d4532648a78e9e44ada94531dce8ca4b1498ab3 100644 (file)
@@ -26,6 +26,7 @@
 #include <mono/metadata/threadpool.h>
 #include <mono/metadata/threadpool-internals.h>
 #include <mono/metadata/threads-types.h>
+#include <mono/metadata/sgen-conf.h>
 #include <mono/utils/mono-logger-internal.h>
 #include <mono/metadata/gc-internal.h>
 #include <mono/metadata/marshal.h> /* for mono_delegate_free_ftnptr () */
@@ -676,7 +677,7 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
                        gpointer *entries;
 
                        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_memmove_aligned (entries, handles->entries, sizeof (gpointer) * handles->size);
 
                        mono_gc_free_fixed (handles->entries);
                        handles->entries = entries;
@@ -1061,6 +1062,8 @@ finalize_domain_objects (DomainFinalizationReq *req)
 static guint32
 finalizer_thread (gpointer unused)
 {
+       gboolean wait = TRUE;
+
        while (!finished) {
                /* Wait to be notified that there's at least one
                 * finaliser to run
@@ -1068,12 +1071,15 @@ finalizer_thread (gpointer unused)
 
                g_assert (mono_domain_get () == mono_get_root_domain ());
 
+               if (wait) {
                /* An alertable wait is required so this thread can be suspended on windows */
 #ifdef MONO_HAS_SEMAPHORES
-               MONO_SEM_WAIT_ALERTABLE (&finalizer_sem, TRUE);
+                       MONO_SEM_WAIT_ALERTABLE (&finalizer_sem, TRUE);
 #else
-               WaitForSingleObjectEx (finalizer_event, INFINITE, TRUE);
+                       WaitForSingleObjectEx (finalizer_event, INFINITE, TRUE);
 #endif
+               }
+               wait = TRUE;
 
                mono_threads_perform_thread_dump ();
 
@@ -1105,7 +1111,16 @@ finalizer_thread (gpointer unused)
 
                reference_queue_proccess_all ();
 
-               SetEvent (pending_done_event);
+#ifdef MONO_HAS_SEMAPHORES
+               /* Avoid posting the pending done event until there are pending finalizers */
+               if (MONO_SEM_TIMEDWAIT (&finalizer_sem, 0) == 0)
+                       /* Don't wait again at the start of the loop */
+                       wait = FALSE;
+               else
+                       SetEvent (pending_done_event);
+#else
+                       SetEvent (pending_done_event);
+#endif
        }
 
        SetEvent (shutdown_event);
@@ -1137,8 +1152,16 @@ mono_gc_init (void)
        mono_counters_register ("Created object count", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &mono_stats.new_object_count);
        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_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time_usecs);
+       mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_usecs);
+#ifdef HEAVY_STATISTICS
+       mono_counters_register ("Gray Queue alloc section", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_section_alloc);
+       mono_counters_register ("Gray Queue free section", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_section_free);
+       mono_counters_register ("Gray Queue enqueue fast path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_enqueue_fast_path);
+       mono_counters_register ("Gray Queue dequeue fast path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_dequeue_fast_path);
+       mono_counters_register ("Gray Queue enqueue slow path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_enqueue_slow_path);
+       mono_counters_register ("Gray Queue dequeue slow path", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &gc_stats.gray_queue_dequeue_slow_path);
+#endif
 
        mono_gc_base_init ();
 
@@ -1173,6 +1196,8 @@ mono_gc_cleanup (void)
                ResetEvent (shutdown_event);
                finished = TRUE;
                if (mono_thread_internal_current () != gc_thread) {
+                       gboolean timed_out = FALSE;
+
                        mono_gc_finalize_notify ();
                        /* Finishing the finalizer thread, so wait a little bit... */
                        /* MS seems to wait for about 2 seconds */
@@ -1195,14 +1220,11 @@ mono_gc_cleanup (void)
                                         * state the finalizer thread depends on will vanish.
                                         */
                                        g_warning ("Shutting down finalizer thread timed out.");
-                               } else {
-                                       /*
-                                        * FIXME: On unix, when the above wait returns, the thread 
-                                        * might still be running io-layer code, or pthreads code.
-                                        */
-                                       Sleep (100);
+                                       timed_out = TRUE;
                                }
-                       } else {
+                       }
+
+                       if (!timed_out) {
                                int ret;
 
                                /* Wait for the thread to actually exit */
@@ -1295,11 +1317,11 @@ mono_gc_get_mach_exception_thread (void)
  * Returns true if passing was successful
  */
 gboolean
-mono_gc_parse_environment_string_extract_number (const char *str, glong *out)
+mono_gc_parse_environment_string_extract_number (const char *str, size_t *out)
 {
        char *endptr;
        int len = strlen (str), shift = 0;
-       glong val;
+       size_t val;
        gboolean is_suffix = FALSE;
        char suffix;
 
@@ -1334,18 +1356,18 @@ mono_gc_parse_environment_string_extract_number (const char *str, glong *out)
                return FALSE;
 
        if (is_suffix) {
-               gulong unshifted;
+               size_t unshifted;
 
                if (val < 0)    /* negative numbers cannot be suffixed */
                        return FALSE;
                if (*(endptr + 1)) /* Invalid string. */
                        return FALSE;
 
-               unshifted = (gulong)val;
+               unshifted = (size_t)val;
                val <<= shift;
                if (val < 0)    /* overflow */
                        return FALSE;
-               if (((gulong)val >> shift) != unshifted) /* value too large */
+               if (((size_t)val >> shift) != unshifted) /* value too large */
                        return FALSE;
        }