2007-05-01 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / threads.c
index 8da27bda35508ce44dafbb81c25f34762f30c451..733fe28fc845cbe34271dee495b07e44a4fca924 100644 (file)
@@ -262,10 +262,14 @@ static guint32 WINAPI start_wrapper(void *data)
        tid=thread->tid;
 
        SET_CURRENT_OBJECT (thread);
+
+       /* Every thread references the appdomain which created it */
+       mono_thread_push_appdomain_ref (start_info->domain);
        
        if (!mono_domain_set (start_info->domain, FALSE)) {
                /* No point in raising an appdomain_unloaded exception here */
                /* FIXME: Cleanup here */
+               mono_thread_pop_appdomain_ref ();
                return 0;
        }
 
@@ -294,9 +298,6 @@ static guint32 WINAPI start_wrapper(void *data)
        
        g_free (start_info);
 
-       /* Every thread references the appdomain which created it */
-       mono_thread_push_appdomain_ref (mono_domain_get ());
-
        thread_adjust_static_data (thread);
 #ifdef DEBUG
        g_message ("%s: start_wrapper for %"G_GSIZE_FORMAT, __func__,
@@ -391,6 +392,43 @@ void mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg)
        ResumeThread (thread_handle);
 }
 
+/*
+ * mono_thread_get_stack_bounds:
+ *
+ *   Return the address and size of the current threads stack. Return NULL as the stack
+ * address if the stack address cannot be determined.
+ */
+static void
+mono_thread_get_stack_bounds (guint8 **staddr, size_t *stsize)
+{
+#ifndef PLATFORM_WIN32
+       pthread_attr_t attr;
+       guint8 *current = (guint8*)&attr;
+
+       pthread_attr_init (&attr);
+#ifdef HAVE_PTHREAD_GETATTR_NP
+               pthread_getattr_np (pthread_self(), &attr);
+#else
+#ifdef HAVE_PTHREAD_ATTR_GET_NP
+               pthread_attr_get_np (pthread_self(), &attr);
+#elif defined(sun)
+               *staddr = NULL;
+               pthread_attr_getstacksize (&attr, &stsize);
+#else
+               *staddr = NULL;
+               *stsize = 0;
+               return;
+#endif
+#endif
+
+#ifndef sun
+               pthread_attr_getstack (&attr, (void**)staddr, stsize);
+               if (*staddr)
+                       g_assert ((current > *staddr) && (current < *staddr + *stsize));
+#endif
+#endif
+}      
+
 MonoThread *
 mono_thread_attach (MonoDomain *domain)
 {
@@ -441,7 +479,15 @@ mono_thread_attach (MonoDomain *domain)
        thread_adjust_static_data (thread);
 
        if (mono_thread_attach_cb) {
-               mono_thread_attach_cb (tid, &tid);
+               guint8 *staddr;
+               size_t stsize;
+
+               mono_thread_get_stack_bounds (&staddr, &stsize);
+
+               if (staddr == NULL)
+                       mono_thread_attach_cb (tid, &tid);
+               else
+                       mono_thread_attach_cb (tid, staddr + stsize);
        }
 
        return(thread);
@@ -1024,10 +1070,10 @@ HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned,
        return(mutex);
 }                                                                   
 
-void ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) { 
+MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) { 
        MONO_ARCH_SAVE_REGS;
 
-       ReleaseMutex(handle);
+       return(ReleaseMutex (handle));
 }
 
 HANDLE ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name,
@@ -1506,7 +1552,7 @@ void mono_thread_current_check_pending_interrupt ()
 int  
 mono_thread_get_abort_signal (void)
 {
-#if defined (__MINGW32__) || defined (_MSC_VER)
+#ifdef PLATFORM_WIN32
        return -1;
 #else
 #ifndef        SIGRTMIN
@@ -1528,16 +1574,16 @@ mono_thread_get_abort_signal (void)
        /* fallback to the old way */
        return SIGRTMIN;
 #endif
-#endif /*defined (__MINGW32__) || defined (_MSC_VER) */
+#endif /* PLATFORM_WIN32 */
 }
 
-#if defined (__MINGW32__) || defined (_MSC_VER)
+#ifdef PLATFORM_WIN32
 static void CALLBACK interruption_request_apc (ULONG_PTR param)
 {
        MonoException* exc = mono_thread_request_interruption (FALSE);
        if (exc) mono_raise_exception (exc);
 }
-#endif /* defined (__MINGW32__) || defined (_MSC_VER) */
+#endif /* PLATFORM_WIN32 */
 
 /*
  * signal_thread_state_change
@@ -1554,7 +1600,7 @@ static void signal_thread_state_change (MonoThread *thread)
                        mono_raise_exception (exc);
        }
 
-#if defined (__MINGW32__) || defined (_MSC_VER)
+#ifdef PLATFORM_WIN32
        QueueUserAPC ((PAPCFUNC)interruption_request_apc, thread->handle, NULL);
 #else
        /* fixme: store the state somewhere */
@@ -1563,7 +1609,7 @@ static void signal_thread_state_change (MonoThread *thread)
 #else
        pthread_kill (thread->tid, mono_thread_get_abort_signal ());
 #endif
-#endif /* defined (__MINGW32__) || defined (__MSC_VER) */
+#endif /* PLATFORM_WIN32 */
 }
 
 void
@@ -1988,13 +2034,11 @@ static void build_wait_tids (gpointer key, gpointer value, gpointer user)
                MonoThread *thread=(MonoThread *)value;
 
                /* Ignore background threads, we abort them later */
-               mono_monitor_enter (thread->synch_lock);
+               /* Do not lock here since it is not needed and the caller holds threads_lock */
                if (thread->state & ThreadState_Background) {
                        THREAD_DEBUG (g_message ("%s: ignoring background thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
-                       mono_monitor_exit (thread->synch_lock);
                        return; /* just leave, ignore */
                }
-               mono_monitor_exit (thread->synch_lock);
                
                if (mono_gc_is_finalizer_thread (thread)) {
                        THREAD_DEBUG (g_message ("%s: ignoring finalizer thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
@@ -2348,15 +2392,14 @@ abort_appdomain_thread (gpointer key, gpointer value, gpointer user_data)
        MonoDomain *domain = data->domain;
 
        if (mono_thread_has_appdomain_ref (thread, domain)) {
-               HANDLE handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
-               if (handle == NULL)
-                       return;
-
                /* printf ("ABORTING THREAD %p BECAUSE IT REFERENCES DOMAIN %s.\n", thread->tid, domain->friendly_name); */
 
                ves_icall_System_Threading_Thread_Abort (thread, NULL);
 
                if(data->wait.num<MAXIMUM_WAIT_OBJECTS) {
+                       HANDLE handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
+                       if (handle == NULL)
+                               return;
                        data->wait.handles [data->wait.num] = handle;
                        data->wait.threads [data->wait.num] = thread;
                        data->wait.num++;
@@ -2706,8 +2749,8 @@ mono_thread_free_local_slot_values (int slot, MonoBoolean thread_local)
        }
 }
 
-#ifdef __MINGW32__
-static CALLBACK void dummy_apc (ULONG_PTR param)
+#ifdef PLATFORM_WIN32
+static void CALLBACK dummy_apc (ULONG_PTR param)
 {
 }
 #else