[xbuild] Use the env var $MSBuildExtensionsPath before trying other paths.
[mono.git] / mono / metadata / threads.c
index 5affa372a2a1096666676a7d8662ab599d5e0068..7fcbc28b61e701848f249cec4a7636bcf726040c 100644 (file)
@@ -164,7 +164,7 @@ static __thread MonoInternalThread * tls_current_object MONO_TLS_FAST;
 #define GET_CURRENT_OBJECT() tls_current_object
 #else
 #define SET_CURRENT_OBJECT(x) TlsSetValue (current_object_key, x)
-#define GET_CURRENT_OBJECT() (MonoThread*) TlsGetValue (current_object_key)
+#define GET_CURRENT_OBJECT() (MonoInternalThread*) TlsGetValue (current_object_key)
 #endif
 
 /* function called at thread start */
@@ -654,7 +654,7 @@ create_internal_thread_object (void)
 static MonoThread*
 create_thread_object (MonoDomain *domain)
 {
-       MonoVTable *vt = mono_class_vtable (mono_get_root_domain (), mono_defaults.thread_class);
+       MonoVTable *vt = mono_class_vtable (domain, mono_defaults.thread_class);
        return (MonoThread*)mono_gc_alloc_mature (vt);
 }
 
@@ -678,15 +678,19 @@ init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate)
        MONO_OBJECT_SETREF (thread, root_domain_thread, candidate);
 }
 
-static guint32 WINAPI start_wrapper(void *data)
+static guint32 WINAPI start_wrapper_internal(void *data)
 {
        struct StartInfo *start_info=(struct StartInfo *)data;
        guint32 (*start_func)(void *);
        void *start_arg;
        gsize tid;
-       MonoThread *thread=start_info->obj;
-       MonoInternalThread *internal = thread->internal_thread;
+       /* 
+        * We don't create a local to hold start_info->obj, so hopefully it won't get pinned during a
+        * GC stack walk.
+        */
+       MonoInternalThread *internal = start_info->obj->internal_thread;
        MonoObject *start_delegate = start_info->delegate;
+       MonoDomain *domain = start_info->obj->obj.vtable->domain;
 
        THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper", __func__, GetCurrentThreadId ()));
 
@@ -703,9 +707,9 @@ static guint32 WINAPI start_wrapper(void *data)
        mono_monitor_init_tls ();
 
        /* Every thread references the appdomain which created it */
-       mono_thread_push_appdomain_ref (thread->obj.vtable->domain);
+       mono_thread_push_appdomain_ref (domain);
        
-       if (!mono_domain_set (thread->obj.vtable->domain, FALSE)) {
+       if (!mono_domain_set (domain, FALSE)) {
                /* No point in raising an appdomain_unloaded exception here */
                /* FIXME: Cleanup here */
                mono_thread_pop_appdomain_ref ();
@@ -718,7 +722,7 @@ static guint32 WINAPI start_wrapper(void *data)
        /* We have to do this here because mono_thread_new_init()
           requires that root_domain_thread is set up. */
        thread_adjust_static_data (internal);
-       init_root_domain_thread (internal, thread);
+       init_root_domain_thread (internal, start_info->obj);
 
        /* This MUST be called before any managed code can be
         * executed, as it calls the callback function that (for the
@@ -746,18 +750,18 @@ static guint32 WINAPI start_wrapper(void *data)
        }
 
        mono_threads_lock ();
-       mono_g_hash_table_remove (thread_start_args, thread);
+       mono_g_hash_table_remove (thread_start_args, start_info->obj);
        mono_threads_unlock ();
 
+       mono_thread_set_execution_context (start_info->obj->ec_to_set);
+       start_info->obj->ec_to_set = NULL;
+
        g_free (start_info);
 #ifdef DEBUG
        g_message ("%s: start_wrapper for %"G_GSIZE_FORMAT, __func__,
                   thread->tid);
 #endif
 
-       mono_thread_set_execution_context (thread->ec_to_set);
-       thread->ec_to_set = NULL;
-
        /* 
         * Call this after calling start_notify, since the profiler callback might want
         * to lock the thread, and the lock is held by thread_start () which waits for
@@ -806,6 +810,18 @@ static guint32 WINAPI start_wrapper(void *data)
        return(0);
 }
 
+static guint32 WINAPI start_wrapper(void *data)
+{
+#ifdef HAVE_SGEN_GC
+       volatile int dummy;
+
+       /* Avoid scanning the frames above this frame during a GC */
+       mono_gc_set_stack_end ((void*)&dummy);
+#endif
+
+       return start_wrapper_internal (data);
+}
+
 void mono_thread_new_init (intptr_t tid, gpointer stack_start, gpointer func)
 {
        if (mono_thread_start_cb) {
@@ -1544,7 +1560,7 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_
 /* FIXME: exitContext isnt documented */
 gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms, gboolean exitContext)
 {
-       HANDLE *handles;
+       HANDLE handles [MAXIMUM_WAIT_OBJECTS];
        guint32 numhandles;
        guint32 ret;
        guint32 i;
@@ -1556,7 +1572,8 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_ha
        mono_thread_current_check_pending_interrupt ();
 
        numhandles = mono_array_length(mono_handles);
-       handles = g_new0(HANDLE, numhandles);
+       if (numhandles > MAXIMUM_WAIT_OBJECTS)
+               return WAIT_FAILED;
 
        for(i = 0; i < numhandles; i++) {       
                waitHandle = mono_array_get(mono_handles, MonoObject*, i);
@@ -1585,8 +1602,6 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_ha
        } while (ms == -1 || ms > 0);
 
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
-       
-       g_free(handles);
 
        THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") returning %d", __func__, GetCurrentThreadId (), ret));
 
@@ -2907,6 +2922,9 @@ mono_threads_set_shutting_down (void)
                        LeaveCriticalSection (current_thread->synch_cs);
                }
 
+               /*since we're killing the thread, unset the current domain.*/
+               mono_domain_unset ();
+
                /* Wake up other threads potentially waiting for us */
                ExitThread (0);
        } else {
@@ -3709,7 +3727,7 @@ mono_alloc_special_static_data (guint32 static_type, guint32 size, guint32 align
 }
 
 gpointer
-mono_get_special_static_data (guint32 offset)
+mono_get_special_static_data_for_thread (MonoInternalThread *thread, guint32 offset)
 {
        /* The high bit means either thread (0) or static (1) data. */
 
@@ -3720,7 +3738,7 @@ mono_get_special_static_data (guint32 offset)
        idx = (offset >> 24) - 1;
 
        if (static_type == 0) {
-               return get_thread_static_data (mono_thread_internal_current (), offset);
+               return get_thread_static_data (thread, offset);
        } else {
                /* Allocate static data block under demand, since we don't have a list
                // of contexts
@@ -3735,6 +3753,12 @@ mono_get_special_static_data (guint32 offset)
        }
 }
 
+gpointer
+mono_get_special_static_data (guint32 offset)
+{
+       return mono_get_special_static_data_for_thread (mono_thread_internal_current (), offset);
+}
+
 typedef struct {
        guint32 offset;
        guint32 size;