2009-12-02 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / gc.c
index eb73c516de7ef8ec7b7d2e4b08082b491768e4d0..ee0f9856c2121bee48013d9a924f901a500cf6c8 100644 (file)
 #include <mono/metadata/gc-internal.h>
 #include <mono/metadata/marshal.h> /* for mono_delegate_free_ftnptr () */
 #include <mono/metadata/attach.h>
-#if HAVE_SEMAPHORE_H
-#include <semaphore.h>
-/* we do this only for known working systems (OSX for example
- * has the header and functions, but they don't work at all): in other cases
- * we fall back to the io-layer slightly slower and signal-unsafe Event.
- */
-#if defined (__linux__)
-#define USE_POSIX_SEM 1
-#endif
-#endif
+#include <mono/utils/mono-semaphore.h>
 
-#ifndef PLATFORM_WIN32
+#ifndef HOST_WIN32
 #include <pthread.h>
 #endif
 
@@ -65,7 +56,7 @@ static CRITICAL_SECTION finalizer_mutex;
 static GSList *domains_to_finalize= NULL;
 static MonoMList *threads_to_finalize = NULL;
 
-static MonoThread *gc_thread;
+static MonoInternalThread *gc_thread;
 
 static void object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*));
 
@@ -77,7 +68,7 @@ static HANDLE shutdown_event;
 #endif
 
 static void
-add_thread_to_finalize (MonoThread *thread)
+add_thread_to_finalize (MonoInternalThread *thread)
 {
        mono_finalizer_lock ();
        if (!threads_to_finalize)
@@ -146,10 +137,10 @@ 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 (o->vtable->klass == mono_get_thread_class ()) {
-               MonoThread *t = (MonoThread*)o;
+       if (o->vtable->klass == mono_defaults.internal_thread_class) {
+               MonoInternalThread *t = (MonoInternalThread*)o;
 
-               if (mono_gc_is_finalizer_thread (t))
+               if (mono_gc_is_finalizer_internal_thread (t))
                        /* Avoid finalizing ourselves */
                        return;
 
@@ -190,6 +181,7 @@ mono_gc_run_finalize (void *obj, void *data)
                MonoDelegate* del = (MonoDelegate*)o;
                if (del->delegate_trampoline)
                        mono_delegate_free_ftnptr ((MonoDelegate*)o);
+               mono_domain_set_internal (caller_domain);
                return;
        }
 
@@ -236,7 +228,7 @@ void
 mono_gc_finalize_threadpool_threads (void)
 {
        while (threads_to_finalize) {
-               MonoThread *thread = (MonoThread*) mono_mlist_get_data (threads_to_finalize);
+               MonoInternalThread *thread = (MonoInternalThread*) mono_mlist_get_data (threads_to_finalize);
 
                /* Force finalization of the thread. */
                thread->threadpool_thread = FALSE;
@@ -274,7 +266,12 @@ object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*))
 {
 #if HAVE_BOEHM_GC
        guint offset = 0;
-       MonoDomain *domain = obj->vtable->domain;
+       MonoDomain *domain;
+
+       if (obj == NULL)
+               mono_raise_exception (mono_get_exception_argument_null ("obj"));
+       
+       domain = obj->vtable->domain;
 
 #ifndef GC_DEBUG
        /* This assertion is not valid when GC_DEBUG is defined */
@@ -299,6 +296,9 @@ object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*))
 
        GC_REGISTER_FINALIZER_NO_ORDER ((char*)obj - offset, callback, GUINT_TO_POINTER (offset), NULL, NULL);
 #elif defined(HAVE_SGEN_GC)
+       if (obj == NULL)
+               mono_raise_exception (mono_get_exception_argument_null ("obj"));
+                                     
        mono_gc_register_for_finalization (obj, callback);
 #endif
 }
@@ -336,7 +336,7 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout)
        guint32 res;
        HANDLE done_event;
 
-       if (mono_thread_current () == gc_thread)
+       if (mono_thread_internal_current () == gc_thread)
                /* We are called from inside a finalizer, not much we can do here */
                return FALSE;
 
@@ -459,7 +459,7 @@ ves_icall_System_GC_WaitForPendingFinalizers (void)
        if (!mono_gc_pending_finalizers ())
                return;
 
-       if (mono_thread_current () == gc_thread)
+       if (mono_thread_internal_current () == gc_thread)
                /* Avoid deadlocks */
                return;
 
@@ -916,10 +916,16 @@ mono_gchandle_free_domain (MonoDomain *domain)
 
 }
 
+MonoBoolean
+GCHandle_CheckCurrentDomain (guint32 gchandle)
+{
+       return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
+}
+
 #ifndef HAVE_NULL_GC
 
-#if USE_POSIX_SEM
-static sem_t finalizer_sem;
+#ifdef MONO_HAS_SEMAPHORES
+static MonoSemType finalizer_sem;
 #endif
 static HANDLE finalizer_event;
 static volatile gboolean finished=FALSE;
@@ -928,11 +934,11 @@ void
 mono_gc_finalize_notify (void)
 {
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": prodding finalizer");
+       g_message ( "%s: prodding finalizer", __func__);
 #endif
 
-#if USE_POSIX_SEM
-       sem_post (&finalizer_sem);
+#ifdef MONO_HAS_SEMAPHORES
+       MONO_SEM_POST (&finalizer_sem);
 #else
        SetEvent (finalizer_event);
 #endif
@@ -1009,8 +1015,11 @@ finalizer_thread (gpointer unused)
                /* Wait to be notified that there's at least one
                 * finaliser to run
                 */
-#if USE_POSIX_SEM
-               sem_wait (&finalizer_sem);
+
+               g_assert (mono_domain_get () == mono_get_root_domain ());
+
+#ifdef MONO_HAS_SEMAPHORES
+               MONO_SEM_WAIT (&finalizer_sem);
 #else
                /* Use alertable=FALSE since we will be asked to exit using the event too */
                WaitForSingleObjectEx (finalizer_event, INFINITE, FALSE);
@@ -1045,6 +1054,10 @@ finalizer_thread (gpointer unused)
        return 0;
 }
 
+#ifdef HAVE_SGEN_GC
+#define GC_dont_gc 0
+#endif
+
 void
 mono_gc_init (void)
 {
@@ -1058,7 +1071,7 @@ mono_gc_init (void)
 
        mono_gc_base_init ();
 
-       if (g_getenv ("GC_DONT_GC")) {
+       if (GC_dont_gc || g_getenv ("GC_DONT_GC")) {
                gc_disabled = TRUE;
                return;
        }
@@ -1069,8 +1082,8 @@ mono_gc_init (void)
        if (finalizer_event == NULL || pending_done_event == NULL || shutdown_event == NULL) {
                g_assert_not_reached ();
        }
-#if USE_POSIX_SEM
-       sem_init (&finalizer_sem, 0, 0);
+#ifdef MONO_HAS_SEMAPHORES
+       MONO_SEM_INIT (&finalizer_sem, 0);
 #endif
 
        gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, FALSE);
@@ -1080,13 +1093,13 @@ void
 mono_gc_cleanup (void)
 {
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": cleaning up finalizer");
+       g_message ("%s: cleaning up finalizer", __func__);
 #endif
 
        if (!gc_disabled) {
                ResetEvent (shutdown_event);
                finished = TRUE;
-               if (mono_thread_current () != gc_thread) {
+               if (mono_thread_internal_current () != gc_thread) {
                        mono_gc_finalize_notify ();
                        /* Finishing the finalizer thread, so wait a little bit... */
                        /* MS seems to wait for about 2 seconds */
@@ -1097,7 +1110,7 @@ mono_gc_cleanup (void)
                                suspend_finalizers = TRUE;
 
                                /* Try to abort the thread, in the hope that it is running managed code */
-                               mono_thread_stop (gc_thread);
+                               mono_thread_internal_stop (gc_thread);
 
                                /* Wait for it to stop */
                                ret = WaitForSingleObjectEx (gc_thread->handle, 100, TRUE);
@@ -1149,6 +1162,12 @@ void mono_gc_cleanup (void)
 
 #endif
 
+gboolean
+mono_gc_is_finalizer_internal_thread (MonoInternalThread *thread)
+{
+       return thread == gc_thread;
+}
+
 /**
  * mono_gc_is_finalizer_thread:
  * @thread: the thread to test.
@@ -1162,20 +1181,5 @@ void mono_gc_cleanup (void)
 gboolean
 mono_gc_is_finalizer_thread (MonoThread *thread)
 {
-       return thread == gc_thread;
-}
-
-static MonoGetIPFromSigCtxFunc get_ip_from_sigctx = NULL;
-
-void
-mono_install_get_ip_from_sigctx (MonoGetIPFromSigCtxFunc func)
-{
-       get_ip_from_sigctx = func;
-}
-
-gpointer
-mono_gc_get_ip_from_sigctx (gpointer ctx)
-{
-       g_assert (get_ip_from_sigctx);
-       return get_ip_from_sigctx (ctx);
+       return mono_gc_is_finalizer_internal_thread (thread->internal_thread);
 }