2004-09-03 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / threads.c
index 5eca77f0dc89c5f07aba9c715e3d46a029a2b830..972f6f2625f2414c647463b6fc5f7cae347800c8 100644 (file)
  */
 
 #include <config.h>
+#ifdef PLATFORM_WIN32
+#define _WIN32_WINNT 0x0500
+#endif
+
 #include <glib.h>
 #include <signal.h>
 #include <string.h>
 
 #include <mono/metadata/object.h>
-#include <mono/metadata/appdomain.h>
+#include <mono/metadata/domain-internals.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/threads.h>
 #include <mono/metadata/threadpool.h>
@@ -24,6 +28,7 @@
 #include <mono/metadata/environment.h>
 #include <mono/metadata/monitor.h>
 #include <mono/metadata/gc-internal.h>
+#include <mono/metadata/marshal.h>
 #include <mono/io-layer/io-layer.h>
 
 #include <mono/os/gc_wrapper.h>
@@ -72,6 +77,21 @@ static MonoGHashTable *threads=NULL;
 /* The TLS key that holds the MonoObject assigned to each thread */
 static guint32 current_object_key = -1;
 
+#ifdef HAVE_KW_THREAD
+/* we need to use both the Tls* functions and __thread because
+ * the gc needs to see all the threads 
+ */
+static __thread MonoThread * tls_current_object;
+#define SET_CURRENT_OBJECT(x) do { \
+       tls_current_object = x; \
+       TlsSetValue (current_object_key, thread); \
+} while (FALSE)
+#define GET_CURRENT_OBJECT() tls_current_object
+#else
+#define SET_CURRENT_OBJECT(x) TlsSetValue (current_object_key, thread);
+#define GET_CURRENT_OBJECT() (MonoThread*) TlsGetValue (current_object_key);
+#endif
+
 /* function called at thread start */
 static MonoThreadStartCB mono_thread_start_cb = NULL;
 
@@ -117,6 +137,7 @@ static void handle_store(MonoThread *thread)
 #endif
 
        if(threads==NULL) {
+               MONO_GC_REGISTER_ROOT (threads);
                threads=mono_g_hash_table_new(NULL, NULL);
        }
 
@@ -157,11 +178,11 @@ static void handle_remove(guint32 tid)
 
 static void thread_cleanup (MonoThread *thread)
 {
-       if (!mono_monitor_try_enter ((MonoObject *)thread, INFINITE))
+       if (!mono_monitor_enter (thread->synch_lock))
                return;
 
        thread->state |= ThreadState_Stopped;
-       mono_monitor_exit ((MonoObject *)thread);
+       mono_monitor_exit (thread->synch_lock);
 
        mono_profiler_thread_end (thread->tid);
        handle_remove (thread->tid);
@@ -193,7 +214,7 @@ static guint32 start_wrapper(void *data)
 
        tid=thread->tid;
 
-       TlsSetValue (current_object_key, thread);
+       SET_CURRENT_OBJECT (thread);
        
        if (!mono_domain_set (start_info->domain, FALSE)) {
                /* No point in raising an appdomain_unloaded exception here */
@@ -265,7 +286,7 @@ static guint32 start_wrapper(void *data)
         * Boehm GC - the io-layer keeps a GC-visible hash of pointers
         * to TLS data.)
         */
-       TlsSetValue (current_object_key, NULL);
+       SET_CURRENT_OBJECT (NULL);
        
        thread_cleanup (thread);
 #else
@@ -310,12 +331,17 @@ void mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg)
        start_info->obj = thread;
        start_info->domain = domain;
        start_info->this = arg;
-               
+       
        /* Create suspended, so we can do some housekeeping before the thread
         * starts
         */
+#ifdef PLATFORM_WIN32
+       thread_handle = GC_CreateThread(NULL, default_stacksize, start_wrapper, start_info,
+                                    CREATE_SUSPENDED, &tid);
+#else
        thread_handle = CreateThread(NULL, default_stacksize, start_wrapper, start_info,
                                     CREATE_SUSPENDED, &tid);
+#endif
 #ifdef THREAD_DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": Started thread ID %d (handle %p)",
                  tid, thread_handle);
@@ -325,6 +351,8 @@ void mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg)
        thread->handle=thread_handle;
        thread->tid=tid;
 
+       thread->synch_lock=mono_object_new (domain, mono_defaults.object_class);
+                                                 
        handle_store(thread);
 
        ResumeThread (thread_handle);
@@ -366,7 +394,7 @@ mono_thread_attach (MonoDomain *domain)
                   GetCurrentThreadId (), thread);
 #endif
 
-       TlsSetValue (current_object_key, thread);
+       SET_CURRENT_OBJECT (thread);
        mono_domain_set (domain, TRUE);
 
        thread_adjust_static_data (thread);
@@ -386,7 +414,7 @@ mono_thread_detach (MonoThread *thread)
 #ifdef DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION "mono_thread_detach for %d\n", thread->tid);
 #endif
-       TlsSetValue (current_object_key, NULL);
+       SET_CURRENT_OBJECT (NULL);
        
        thread_cleanup (thread);
 }
@@ -524,13 +552,23 @@ void ves_icall_System_Threading_Thread_Start_internal(MonoThread *this,
 
 void ves_icall_System_Threading_Thread_Sleep_internal(gint32 ms)
 {
+       MonoThread *thread = mono_thread_current ();
+       
        MONO_ARCH_SAVE_REGS;
 
 #ifdef THREAD_DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": Sleeping for %d ms", ms);
 #endif
 
-       Sleep(ms);
+       mono_monitor_enter (thread->synch_lock);
+       thread->state |= ThreadState_WaitSleepJoin;
+       mono_monitor_exit (thread->synch_lock);
+       
+       SleepEx(ms,TRUE);
+       
+       mono_monitor_enter (thread->synch_lock);
+       thread->state &= ~ThreadState_WaitSleepJoin;
+       mono_monitor_exit (thread->synch_lock);
 }
 
 gint32
@@ -564,21 +602,20 @@ ves_icall_System_Threading_Thread_SetName_internal (MonoThread *this_obj, MonoSt
                this_obj->name = NULL;
 }
 
+/* the jit may read the compiled code of this function */
 MonoThread *
 mono_thread_current (void)
 {
+#ifdef THREAD_DEBUG
        MonoThread *thread;
-       
        MONO_ARCH_SAVE_REGS;
-
-       /* Find the current thread object */
-       thread=TlsGetValue (current_object_key);
-       
-#ifdef THREAD_DEBUG
+       thread = GET_CURRENT_OBJECT ();
        g_message (G_GNUC_PRETTY_FUNCTION ": returning %p", thread);
+       return thread;
+#else
+       MONO_ARCH_SAVE_REGS;
+       return GET_CURRENT_OBJECT ();
 #endif
-
-       return (thread);
 }
 
 gboolean ves_icall_System_Threading_Thread_Join_internal(MonoThread *this,
@@ -588,6 +625,10 @@ gboolean ves_icall_System_Threading_Thread_Join_internal(MonoThread *this,
        
        MONO_ARCH_SAVE_REGS;
 
+       mono_monitor_enter (this->synch_lock);
+       this->state |= ThreadState_WaitSleepJoin;
+       mono_monitor_exit (this->synch_lock);
+
        if(ms== -1) {
                ms=INFINITE;
        }
@@ -598,6 +639,10 @@ gboolean ves_icall_System_Threading_Thread_Join_internal(MonoThread *this,
        
        ret=WaitForSingleObjectEx (thread, ms, TRUE);
 
+       mono_monitor_enter (this->synch_lock);
+       this->state &= ~ThreadState_WaitSleepJoin;
+       mono_monitor_exit (this->synch_lock);
+       
        if(ret==WAIT_OBJECT_0) {
 #ifdef THREAD_DEBUG
                g_message (G_GNUC_PRETTY_FUNCTION ": join successful");
@@ -680,7 +725,12 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_
                          GetCurrentThreadId ());
 #endif
                return(FALSE);
-       } else if(ret==WAIT_TIMEOUT) {
+       } else if(ret==WAIT_TIMEOUT || ret == WAIT_IO_COMPLETION) {
+               /* Do we want to try again if we get
+                * WAIT_IO_COMPLETION? The documentation for
+                * WaitHandle doesn't give any clues.  (We'd have to
+                * fiddle with the timeout if we retry.)
+                */
 #ifdef THREAD_WAIT_DEBUG
                g_message(G_GNUC_PRETTY_FUNCTION ": (%d) Wait timed out",
                          GetCurrentThreadId ());
@@ -768,7 +818,12 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this
                          GetCurrentThreadId ());
 #endif
                return(FALSE);
-       } else if(ret==WAIT_TIMEOUT) {
+       } else if(ret==WAIT_TIMEOUT || ret == WAIT_IO_COMPLETION) {
+               /* Do we want to try again if we get
+                * WAIT_IO_COMPLETION? The documentation for
+                * WaitHandle doesn't give any clues.  (We'd have to
+                * fiddle with the timeout if we retry.)
+                */
 #ifdef THREAD_WAIT_DEBUG
                g_message(G_GNUC_PRETTY_FUNCTION ": (%d) Wait timed out",
                          GetCurrentThreadId ());
@@ -779,12 +834,25 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this
        return(TRUE);
 }
 
-HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name)
+HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
 { 
+       HANDLE mutex;
+       
        MONO_ARCH_SAVE_REGS;
    
-       return(CreateMutex (NULL, owned,
-                           name==NULL?NULL:mono_string_chars (name)));
+       *created = TRUE;
+       
+       if (name == NULL) {
+               mutex = CreateMutex (NULL, owned, NULL);
+       } else {
+               mutex = CreateMutex (NULL, owned, mono_string_chars (name));
+               
+               if (GetLastError () == ERROR_ALREADY_EXISTS) {
+                       *created = FALSE;
+               }
+       }
+
+       return(mutex);
 }                                                                   
 
 void ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) { 
@@ -974,24 +1042,20 @@ ves_icall_System_Threading_Thread_Abort (MonoThread *thread, MonoObject *state)
 {
        MONO_ARCH_SAVE_REGS;
 
-       if (!mono_monitor_try_enter ((MonoObject *)thread, INFINITE))
-               return;
+       mono_monitor_enter (thread->synch_lock);
 
        if ((thread->state & ThreadState_AbortRequested) != 0 || 
                (thread->state & ThreadState_StopRequested) != 0) 
        {
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                return;
        }
-       
-       /* Make sure the thread is awake */
-       ves_icall_System_Threading_Thread_Resume (thread);
 
        thread->state |= ThreadState_AbortRequested;
        thread->abort_state = state;
        thread->abort_exc = NULL;
 
-       mono_monitor_exit ((MonoObject *)thread);
+       mono_monitor_exit (thread->synch_lock);
 
 #ifdef THREAD_DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION
@@ -999,31 +1063,33 @@ ves_icall_System_Threading_Thread_Abort (MonoThread *thread, MonoObject *state)
                   thread, thread->tid);
 #endif
        
+       /* Make sure the thread is awake */
+       ves_icall_System_Threading_Thread_Resume (thread);
+       
        signal_thread_state_change (thread);
 }
 
 void
 ves_icall_System_Threading_Thread_ResetAbort (void)
 {
-       MONO_ARCH_SAVE_REGS;
-
        MonoThread *thread = mono_thread_current ();
+
+       MONO_ARCH_SAVE_REGS;
        
-       if (!mono_monitor_try_enter ((MonoObject *)thread, INFINITE))
-               return;
+       mono_monitor_enter (thread->synch_lock);
        
        thread->state &= ~ThreadState_AbortRequested;
        
        if (!thread->abort_exc) {
-               mono_monitor_exit ((MonoObject *)thread);
                const char *msg = "Unable to reset abort because no abort was requested";
+               mono_monitor_exit (thread->synch_lock);
                mono_raise_exception (mono_get_exception_thread_state (msg));
        } else {
                thread->abort_exc = NULL;
                thread->abort_state = NULL;
        }
        
-       mono_monitor_exit ((MonoObject *)thread);
+       mono_monitor_exit (thread->synch_lock);
 }
 
 void
@@ -1031,19 +1097,18 @@ ves_icall_System_Threading_Thread_Suspend (MonoThread *thread)
 {
        MONO_ARCH_SAVE_REGS;
 
-       if (!mono_monitor_try_enter ((MonoObject *)thread, INFINITE))
-               return;
+       mono_monitor_enter (thread->synch_lock);
 
        if ((thread->state & ThreadState_Suspended) != 0 || 
                (thread->state & ThreadState_SuspendRequested) != 0 ||
                (thread->state & ThreadState_StopRequested) != 0) 
        {
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                return;
        }
        
        thread->state |= ThreadState_SuspendRequested;
-       mono_monitor_exit ((MonoObject *)thread);
+       mono_monitor_exit (thread->synch_lock);
 
        signal_thread_state_change (thread);
 }
@@ -1053,42 +1118,41 @@ ves_icall_System_Threading_Thread_Resume (MonoThread *thread)
 {
        MONO_ARCH_SAVE_REGS;
 
-       if (!mono_monitor_try_enter ((MonoObject *)thread, INFINITE))
-               return;
+       mono_monitor_enter (thread->synch_lock);
 
        if ((thread->state & ThreadState_SuspendRequested) != 0) {
                thread->state &= ~ThreadState_SuspendRequested;
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                return;
        }
                
        if ((thread->state & ThreadState_Suspended) == 0) 
        {
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                return;
        }
-
-       while (ResumeThread (thread->handle) == 0) {
-               /* A rare case: we may try to resume the thread when it has not still
-                  called SuspendThread. This my happen since SuspendThread can't be
-                  called from inside the thread lock. In this case, keep trying until
-                  the thread is actually resumed */
-               
-               Sleep (1);
-       }
        
-       mono_monitor_exit ((MonoObject *)thread);
+       thread->resume_event = CreateEvent (NULL, TRUE, FALSE, NULL);
+       
+       /* Awake the thread */
+       SetEvent (thread->suspend_event);
+
+       mono_monitor_exit (thread->synch_lock);
+
+       /* Wait for the thread to awake */
+       WaitForSingleObject (thread->resume_event, INFINITE);
+       CloseHandle (thread->resume_event);
+       thread->resume_event = NULL;
 }
 
 void mono_thread_stop (MonoThread *thread)
 {
-       if (!mono_monitor_try_enter ((MonoObject *)thread, INFINITE))
-               return;
+       mono_monitor_enter (thread->synch_lock);
 
        if ((thread->state & ThreadState_StopRequested) != 0 ||
                (thread->state & ThreadState_Stopped) != 0)
        {
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                return;
        }
        
@@ -1098,7 +1162,7 @@ void mono_thread_stop (MonoThread *thread)
        thread->state |= ThreadState_StopRequested;
        thread->state &= ~ThreadState_AbortRequested;
        
-       mono_monitor_exit ((MonoObject *)thread);
+       mono_monitor_exit (thread->synch_lock);
        
        signal_thread_state_change (thread);
 }
@@ -1240,6 +1304,7 @@ static void wait_for_tids (struct wait_data *wait, guint32 timeout)
 
        for(i=0; i<wait->num; i++) {
                guint32 tid=wait->threads[i]->tid;
+               CloseHandle (wait->handles[i]);
                
                if(mono_g_hash_table_lookup (threads, GUINT_TO_POINTER(tid))!=NULL) {
                        /* This thread must have been killed, because
@@ -1267,6 +1332,7 @@ static void build_wait_tids (gpointer key, gpointer value, gpointer user)
        struct wait_data *wait=(struct wait_data *)user;
 
        if(wait->num<MAXIMUM_WAIT_OBJECTS) {
+               HANDLE handle;
                MonoThread *thread=(MonoThread *)value;
 
                /* Ignore background threads, we abort them later */
@@ -1279,7 +1345,11 @@ static void build_wait_tids (gpointer key, gpointer value, gpointer user)
                if (thread == mono_thread_current ())
                        return;
 
-               wait->handles[wait->num]=thread->handle;
+               handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
+               if (handle == NULL)
+                       return;
+               
+               wait->handles[wait->num]=handle;
                wait->threads[wait->num]=thread;
                wait->num++;
        } else {
@@ -1295,10 +1365,15 @@ remove_and_abort_threads (gpointer key, gpointer value, gpointer user)
        struct wait_data *wait=(struct wait_data *)user;
        guint32 self = GetCurrentThreadId ();
        MonoThread *thread = (MonoThread *) value;
+       HANDLE handle;
 
        /* The finalizer thread is not a background thread */
        if (thread->tid != self && thread->state & ThreadState_Background) {
        
+               handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
+               if (handle == NULL)
+                       return FALSE;
+               
                wait->handles[wait->num]=thread->handle;
                wait->threads[wait->num]=thread;
                wait->num++;
@@ -1419,7 +1494,7 @@ mono_thread_push_appdomain_ref (MonoDomain *domain)
        MonoThread *thread = mono_thread_current ();
 
        if (thread) {
-               //printf ("PUSH REF: %p -> %s.\n", thread, domain->friendly_name);
+               /* printf ("PUSH REF: %p -> %s.\n", thread, domain->friendly_name); */
                EnterCriticalSection (&threads_mutex);
                thread->appdomain_refs = g_slist_prepend (thread->appdomain_refs, domain);
                LeaveCriticalSection (&threads_mutex);
@@ -1432,9 +1507,9 @@ mono_thread_pop_appdomain_ref (void)
        MonoThread *thread = mono_thread_current ();
 
        if (thread) {
-               //printf ("POP REF: %p -> %s.\n", thread, ((MonoDomain*)(thread->appdomain_refs->data))->friendly_name);
+               /* printf ("POP REF: %p -> %s.\n", thread, ((MonoDomain*)(thread->appdomain_refs->data))->friendly_name); */
                EnterCriticalSection (&threads_mutex);
-               // FIXME: How can the list be empty ?
+               /* FIXME: How can the list be empty ? */
                if (thread->appdomain_refs)
                        thread->appdomain_refs = g_slist_remove (thread->appdomain_refs, thread->appdomain_refs->data);
                LeaveCriticalSection (&threads_mutex);
@@ -1465,10 +1540,14 @@ abort_appdomain_thread (gpointer key, gpointer value, gpointer user_data)
 
        if (mono_thread_has_appdomain_ref (thread, domain)) {
                /* printf ("ABORTING THREAD %p BECAUSE IT REFERENCES DOMAIN %s.\n", thread, domain->friendly_name); */
+               HANDLE handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
+               if (handle == NULL)
+                       return;
+
                ves_icall_System_Threading_Thread_Abort (thread, NULL);
 
                if(data->wait.num<MAXIMUM_WAIT_OBJECTS) {
-                       data->wait.handles [data->wait.num] = thread->handle;
+                       data->wait.handles [data->wait.num] = handle;
                        data->wait.threads [data->wait.num] = thread;
                        data->wait.num++;
                } else {
@@ -1688,7 +1767,7 @@ mono_alloc_special_static_data (guint32 static_type, guint32 size, guint32 align
                EnterCriticalSection (&contexts_mutex);
                offset = mono_alloc_static_data_slot (&context_static_info, size, align);
                LeaveCriticalSection (&contexts_mutex);
-               offset |= 0x80000000;   // Set the high bit to indicate context static data
+               offset |= 0x80000000;   /* Set the high bit to indicate context static data */
        }
        return offset;
 }
@@ -1696,7 +1775,7 @@ mono_alloc_special_static_data (guint32 static_type, guint32 size, guint32 align
 gpointer
 mono_get_special_static_data (guint32 offset)
 {
-       // The high bit means either thread (0) or static (1) data.
+       /* The high bit means either thread (0) or static (1) data. */
 
        guint32 static_type = (offset & 0x80000000);
        int idx;
@@ -1711,8 +1790,9 @@ mono_get_special_static_data (guint32 offset)
        }
        else
        {
-               // Allocate static data block under demand, since we don't have a list
+               /* Allocate static data block under demand, since we don't have a list
                // of contexts
+               */
                MonoAppContext *context = mono_context_get ();
                if (!context->static_data || !context->static_data [idx]) {
                        EnterCriticalSection (&contexts_mutex);
@@ -1799,8 +1879,7 @@ static guint32 dummy_apc (gpointer param)
  */
 static MonoException* mono_thread_execute_interruption (MonoThread *thread)
 {
-       while (!mono_monitor_try_enter ((MonoObject *)thread, INFINITE))
-               ;       /* we really need to get in */
+       mono_monitor_enter (thread->synch_lock);
        
        if (thread->interruption_requested) {
                /* this will consume pending APC calls */
@@ -1813,29 +1892,37 @@ static MonoException* mono_thread_execute_interruption (MonoThread *thread)
 
        if ((thread->state & ThreadState_AbortRequested) != 0) {
                thread->abort_exc = mono_get_exception_thread_abort ();
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                return thread->abort_exc;
        }
        else if ((thread->state & ThreadState_SuspendRequested) != 0) {
                thread->state &= ~ThreadState_SuspendRequested;
                thread->state |= ThreadState_Suspended;
-               mono_monitor_exit ((MonoObject *)thread);
+               thread->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL);
+               mono_monitor_exit (thread->synch_lock);
                
-               SuspendThread (thread->handle);
+               WaitForSingleObject (thread->suspend_event, INFINITE);
                
-               mono_monitor_try_enter ((MonoObject *)thread, INFINITE);
+               mono_monitor_enter (thread->synch_lock);
+               CloseHandle (thread->suspend_event);
+               thread->suspend_event = NULL;
                thread->state &= ~ThreadState_Suspended;
-               mono_monitor_exit ((MonoObject *)thread);
+       
+               /* The thread that requested the resume will have replaced this event
+            * and will be waiting for it
+                */
+               SetEvent (thread->resume_event);
+               mono_monitor_exit (thread->synch_lock);
                return NULL;
        }
        else if ((thread->state & ThreadState_StopRequested) != 0) {
                /* FIXME: do this through the JIT? */
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                ExitThread (-1);
                return NULL;
        }
        
-       mono_monitor_exit ((MonoObject *)thread);
+       mono_monitor_exit (thread->synch_lock);
        return NULL;
 }
 
@@ -1855,11 +1942,10 @@ MonoException* mono_thread_request_interruption (gboolean running_managed)
        if (thread == NULL) 
                return NULL;
        
-       if (!mono_monitor_try_enter ((MonoObject *)thread, INFINITE))
-               ;
+       mono_monitor_enter (thread->synch_lock);
        
        if (thread->interruption_requested) {
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                return NULL;
        }
 
@@ -1873,7 +1959,7 @@ MonoException* mono_thread_request_interruption (gboolean running_managed)
                LeaveCriticalSection (&interruption_mutex);
                
                thread->interruption_requested = TRUE;
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                
                /* this will awake the thread if it is in WaitForSingleObject 
               or similar */
@@ -1882,7 +1968,7 @@ MonoException* mono_thread_request_interruption (gboolean running_managed)
                return NULL;
        }
        else {
-               mono_monitor_exit ((MonoObject *)thread);
+               mono_monitor_exit (thread->synch_lock);
                return mono_thread_execute_interruption (thread);
        }
 }
@@ -1907,7 +1993,7 @@ void mono_thread_interruption_checkpoint ()
        
        /* The thread may already be stopping */
        if (thread == NULL) 
-               return NULL;
+               return;
        
        if (thread->interruption_requested) {
                MonoException* exc = mono_thread_execute_interruption (thread);