2009-01-03 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / threads.c
index 1935b2950a2b5877528a9eef60fd8dde7951eb4f..17f56971ac329912fdc2db775c08bd5d491409d4 100644 (file)
@@ -419,9 +419,8 @@ static void
 try_free_delayed_free_item (int index)
 {
        if (delayed_free_table->len > index) {
-               DelayedFreeItem item;
+               DelayedFreeItem item = { NULL, NULL };
 
-               item.p = NULL;
                EnterCriticalSection (&delayed_free_table_mutex);
                /* We have to check the length again because another
                   thread might have freed an item before we acquired
@@ -528,6 +527,8 @@ static void thread_cleanup (MonoThread *thread)
        if (thread->serialized_culture_info)
                g_free (thread->serialized_culture_info);
 
+       g_free (thread->name);
+
        thread->cached_culture_info = NULL;
 
        mono_gc_free_fixed (thread->static_data);
@@ -591,7 +592,7 @@ static guint32 WINAPI start_wrapper(void *data)
 
        /* On 2.0 profile (and higher), set explicitly since state might have been
           Unknown */
-       if (mono_get_runtime_info ()->framework_version [0] != '1') {
+       if (mono_framework_version () != 1) {
                if (thread->apartment_state == ThreadApartmentState_Unknown)
                        thread->apartment_state = ThreadApartmentState_MTA;
        }
@@ -731,6 +732,8 @@ void mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer ar
        InitializeCriticalSection (thread->synch_cs);
 
        thread->threadpool_thread = threadpool_thread;
+       if (threadpool_thread)
+               mono_thread_set_state (thread, ThreadState_Background);
 
        if (handle_store (thread))
                ResumeThread (thread_handle);
@@ -1052,16 +1055,8 @@ void ves_icall_System_Threading_Thread_Sleep_internal(gint32 ms)
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
 }
 
-void ves_icall_System_Threading_Thread_SpinWait_internal (gint32 iterations)
+void ves_icall_System_Threading_Thread_SpinWait_nop (void)
 {
-       gint32 i;
-       
-       for(i = 0; i < iterations; i++) {
-               /* We're busy waiting, but at least we can tell the
-                * scheduler to let someone else have a go...
-                */
-               Sleep (0);
-       }
 }
 
 gint32
@@ -1932,6 +1927,9 @@ void ves_icall_System_Threading_Thread_Interrupt_internal (MonoThread *this)
        gboolean throw = FALSE;
        
        ensure_synch_cs_set (this);
+
+       if (this == mono_thread_current ())
+               return;
        
        EnterCriticalSection (this->synch_cs);
        
@@ -1953,6 +1951,8 @@ void mono_thread_current_check_pending_interrupt ()
        MonoThread *thread = mono_thread_current ();
        gboolean throw = FALSE;
 
+       mono_debugger_check_interruption ();
+
        ensure_synch_cs_set (thread);
        
        EnterCriticalSection (thread->synch_cs);
@@ -2062,9 +2062,11 @@ ves_icall_System_Threading_Thread_Abort (MonoThread *thread, MonoObject *state)
        LeaveCriticalSection (thread->synch_cs);
 
        THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Abort requested for %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), thread, (gsize)thread->tid));
-       
-       /* Make sure the thread is awake */
-       mono_thread_resume (thread);
+
+       /* During shutdown, we can't wait for other threads */
+       if (!shutting_down)
+               /* Make sure the thread is awake */
+               mono_thread_resume (thread);
        
        signal_thread_state_change (thread);
 }
@@ -3027,6 +3029,7 @@ mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout)
 {
        abort_appdomain_data user_data;
        guint32 start_time;
+       int orig_timeout = timeout;
 
        THREAD_DEBUG (g_message ("%s: starting abort", __func__));
 
@@ -3050,7 +3053,7 @@ mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout)
                timeout -= mono_msec_ticks () - start_time;
                start_time = mono_msec_ticks ();
 
-               if (timeout < 0)
+               if (orig_timeout != -1 && timeout < 0)
                        return FALSE;
        }
        while (user_data.wait.num > 0);
@@ -3507,6 +3510,7 @@ static MonoException* mono_thread_execute_interruption (MonoThread *thread)
                return NULL;
        } else if (thread->thread_interrupt_requested) {
 
+               thread->thread_interrupt_requested = FALSE;
                LeaveCriticalSection (thread->synch_cs);
                
                return(mono_get_exception_thread_interrupted ());
@@ -3525,7 +3529,8 @@ static MonoException* mono_thread_execute_interruption (MonoThread *thread)
  * the thread. If the result is an exception that needs to be throw, it is 
  * provided as return value.
  */
-MonoException* mono_thread_request_interruption (gboolean running_managed)
+MonoException*
+mono_thread_request_interruption (gboolean running_managed)
 {
        MonoThread *thread = mono_thread_current ();
 
@@ -3533,16 +3538,8 @@ MonoException* mono_thread_request_interruption (gboolean running_managed)
        if (thread == NULL) 
                return NULL;
        
-       ensure_synch_cs_set (thread);
-
-       /* FIXME: This is NOT signal safe */
-       EnterCriticalSection (thread->synch_cs);
-       
-       if (thread->interruption_requested) {
-               LeaveCriticalSection (thread->synch_cs);
-               
+       if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1)
                return NULL;
-       }
 
        if (!running_managed || is_running_protected_wrapper ()) {
                /* Can't stop while in unmanaged code. Increase the global interruption
@@ -3550,9 +3547,6 @@ MonoException* mono_thread_request_interruption (gboolean running_managed)
                   checked and the thread will be interrupted. */
                
                InterlockedIncrement (&thread_interruption_requested);
-               thread->interruption_requested = TRUE;
-
-               LeaveCriticalSection (thread->synch_cs);
 
                if (mono_thread_notify_pending_exc_fn && !running_managed)
                        /* The JIT will notify the thread about the interruption */
@@ -3566,8 +3560,6 @@ MonoException* mono_thread_request_interruption (gboolean running_managed)
                return NULL;
        }
        else {
-               LeaveCriticalSection (thread->synch_cs);
-               
                return mono_thread_execute_interruption (thread);
        }
 }
@@ -3591,6 +3583,8 @@ static void mono_thread_interruption_checkpoint_request (gboolean bypass_abort_p
        if (thread == NULL)
                return;
 
+       mono_debugger_check_interruption ();
+
        if (thread->interruption_requested && (bypass_abort_protection || !is_running_protected_wrapper ())) {
                MonoException* exc = mono_thread_execute_interruption (thread);
                if (exc) mono_raise_exception (exc);