[runtime] It's spring cleaning in MonoInternalThread. Remove 8 (yes, eight) unused...
[mono.git] / mono / metadata / gc.c
index a0472955071df183adf0d6457be366fe0c78cb3a..4cbdc07c4ff8296c9f13d6a63a8c00d6b853053a 100644 (file)
@@ -59,6 +59,9 @@ static gboolean gc_disabled = FALSE;
 
 static gboolean finalizing_root_domain = FALSE;
 
+gboolean log_finalizers = FALSE;
+gboolean do_not_finalize = FALSE;
+
 #define mono_finalizer_lock() mono_mutex_lock (&finalizer_mutex)
 #define mono_finalizer_unlock() mono_mutex_unlock (&finalizer_mutex)
 static mono_mutex_t finalizer_mutex;
@@ -83,6 +86,18 @@ static HANDLE shutdown_event;
 
 GCStats gc_stats;
 
+static guint32
+guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable)
+{
+       guint32 result;
+
+       MONO_PREPARE_BLOCKING
+       result = WaitForSingleObjectEx (handle, timeout, alertable);
+       MONO_FINISH_BLOCKING
+
+       return result;
+}
+
 static void
 add_thread_to_finalize (MonoInternalThread *thread)
 {
@@ -101,6 +116,9 @@ static gboolean suspend_finalizers = FALSE;
 void
 mono_gc_run_finalize (void *obj, void *data)
 {
+       if (do_not_finalize)
+               return;
+
        MonoObject *exc = NULL;
        MonoObject *o;
 #ifndef HAVE_SGEN_GC
@@ -113,6 +131,9 @@ mono_gc_run_finalize (void *obj, void *data)
 
        o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data));
 
+       if (log_finalizers)
+               g_log ("mono-gc-finalizers", G_LOG_LEVEL_DEBUG, "<%s at %p> Starting finalizer checks.", o->vtable->klass->name, o);
+
        if (suspend_finalizers)
                return;
 
@@ -133,6 +154,9 @@ mono_gc_run_finalize (void *obj, void *data)
        /* make sure the finalizer is not called again if the object is resurrected */
        object_register_finalizer (obj, NULL);
 
+       if (log_finalizers)
+               g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Registered finalizer as processed.", o->vtable->klass->name, o);
+
        if (o->vtable->klass == mono_defaults.internal_thread_class) {
                MonoInternalThread *t = (MonoInternalThread*)o;
 
@@ -201,6 +225,9 @@ mono_gc_run_finalize (void *obj, void *data)
         * create and precompile a wrapper which calls the finalize method using
         * a CALLVIRT.
         */
+       if (log_finalizers)
+               g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Compiling finalizer.", o->vtable->klass->name, o);
+
        if (!domain->finalize_runtime_invoke) {
                MonoMethod *invoke = mono_marshal_get_runtime_invoke (mono_class_get_method_from_name_flags (mono_defaults.object_class, "Finalize", 0, 0), TRUE);
 
@@ -216,8 +243,14 @@ mono_gc_run_finalize (void *obj, void *data)
                                o->vtable->klass->name_space, o->vtable->klass->name);
        }
 
+       if (log_finalizers)
+               g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o->vtable->klass->name, o);
+
        runtime_invoke (o, NULL, &exc, NULL);
 
+       if (log_finalizers)
+               g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o->vtable->klass->name, o);
+
        if (exc)
                mono_internal_thread_unhandled_exception (exc);
 
@@ -378,7 +411,7 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout)
                timeout = INFINITE;
 
        while (TRUE) {
-               res = WaitForSingleObjectEx (done_event, timeout, TRUE);
+               res = guarded_wait (done_event, timeout, TRUE);
                /* printf ("WAIT RES: %d.\n", res); */
 
                if (res == WAIT_IO_COMPLETION) {
@@ -415,8 +448,6 @@ ves_icall_System_GC_InternalCollect (int generation)
 gint64
 ves_icall_System_GC_GetTotalMemory (MonoBoolean forceCollection)
 {
-       MONO_ARCH_SAVE_REGS;
-
        if (forceCollection)
                mono_gc_collect (mono_gc_max_generation ());
        return mono_gc_get_used_size ();
@@ -425,8 +456,6 @@ ves_icall_System_GC_GetTotalMemory (MonoBoolean forceCollection)
 void
 ves_icall_System_GC_KeepAlive (MonoObject *obj)
 {
-       MONO_ARCH_SAVE_REGS;
-
        /*
         * Does nothing.
         */
@@ -435,8 +464,7 @@ ves_icall_System_GC_KeepAlive (MonoObject *obj)
 void
 ves_icall_System_GC_ReRegisterForFinalize (MonoObject *obj)
 {
-       if (!obj)
-               mono_raise_exception (mono_get_exception_argument_null ("obj"));
+       MONO_CHECK_ARG_NULL (obj,);
 
        object_register_finalizer (obj, mono_gc_run_finalize);
 }
@@ -444,8 +472,7 @@ ves_icall_System_GC_ReRegisterForFinalize (MonoObject *obj)
 void
 ves_icall_System_GC_SuppressFinalize (MonoObject *obj)
 {
-       if (!obj)
-               mono_raise_exception (mono_get_exception_argument_null ("obj"));
+       MONO_CHECK_ARG_NULL (obj,);
 
        /* delegates have no finalizers, but we register them to deal with the
         * unmanaged->managed trampoline. We don't let the user suppress it
@@ -482,7 +509,7 @@ ves_icall_System_GC_WaitForPendingFinalizers (void)
        ResetEvent (pending_done_event);
        mono_gc_finalize_notify ();
        /* g_print ("Waiting for pending finalizers....\n"); */
-       WaitForSingleObjectEx (pending_done_event, INFINITE, TRUE);
+       guarded_wait (pending_done_event, INFINITE, TRUE);
        /* g_print ("Done pending....\n"); */
 #endif
 }
@@ -491,8 +518,10 @@ void
 ves_icall_System_GC_register_ephemeron_array (MonoObject *array)
 {
 #ifdef HAVE_SGEN_GC
-       if (!mono_gc_ephemeron_array_add (array))
-               mono_raise_exception (mono_object_domain (array)->out_of_memory_ex);
+       if (!mono_gc_ephemeron_array_add (array)) {
+               mono_set_pending_exception (mono_object_domain (array)->out_of_memory_ex);
+               return;
+       }
 #endif
 }
 
@@ -828,14 +857,12 @@ mono_gchandle_set_target (guint32 gchandle, MonoObject *obj)
        guint slot = gchandle >> 3;
        guint type = (gchandle & 7) - 1;
        HandleData *handles = &gc_handles [type];
-       MonoObject *old_obj = NULL;
 
        if (type > 3)
                return;
        lock_handles (handles);
        if (slot < handles->size && (handles->bitmap [slot / 32] & (1 << (slot % 32)))) {
                if (handles->type <= HANDLE_WEAK_TRACK) {
-                       old_obj = handles->entries [slot];
                        if (handles->entries [slot])
                                mono_gc_weak_link_remove (&handles->entries [slot], handles->type == HANDLE_WEAK_TRACK);
                        if (obj)
@@ -1070,6 +1097,8 @@ finalizer_thread (gpointer unused)
                 */
 
                g_assert (mono_domain_get () == mono_get_root_domain ());
+               mono_gc_set_skip_thread (TRUE);
+               MONO_PREPARE_BLOCKING
 
                if (wait) {
                /* An alertable wait is required so this thread can be suspended on windows */
@@ -1080,6 +1109,8 @@ finalizer_thread (gpointer unused)
 #endif
                }
                wait = TRUE;
+               MONO_FINISH_BLOCKING
+               mono_gc_set_skip_thread (FALSE);
 
                mono_threads_perform_thread_dump ();
 
@@ -1149,12 +1180,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 ("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_LONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time);
-       mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time);
-       mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent);
+       mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.minor_gc_count);
+       mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.major_gc_count);
+       mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time);
+       mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time);
+       mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent);
 
        mono_gc_base_init ();
 
@@ -1194,7 +1224,7 @@ mono_gc_cleanup (void)
                        mono_gc_finalize_notify ();
                        /* Finishing the finalizer thread, so wait a little bit... */
                        /* MS seems to wait for about 2 seconds */
-                       if (WaitForSingleObjectEx (shutdown_event, 2000, FALSE) == WAIT_TIMEOUT) {
+                       if (guarded_wait (shutdown_event, 2000, FALSE) == WAIT_TIMEOUT) {
                                int ret;
 
                                /* Set a flag which the finalizer thread can check */
@@ -1204,7 +1234,7 @@ mono_gc_cleanup (void)
                                mono_thread_internal_stop (gc_thread);
 
                                /* Wait for it to stop */
-                               ret = WaitForSingleObjectEx (gc_thread->handle, 100, TRUE);
+                               ret = guarded_wait (gc_thread->handle, 100, TRUE);
 
                                if (ret == WAIT_TIMEOUT) {
                                        /* 
@@ -1221,10 +1251,10 @@ mono_gc_cleanup (void)
                                int ret;
 
                                /* Wait for the thread to actually exit */
-                               ret = WaitForSingleObjectEx (gc_thread->handle, INFINITE, TRUE);
+                               ret = guarded_wait (gc_thread->handle, INFINITE, TRUE);
                                g_assert (ret == WAIT_OBJECT_0);
 
-                               mono_thread_join ((gpointer)gc_thread->tid);
+                               mono_thread_join (GUINT_TO_POINTER (gc_thread->tid));
                        }
                }
                gc_thread = NULL;