2007-05-01 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / threads.c
index e012838eaab329bdac84e01541b02c25919f6baf..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);
@@ -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++;