Merge pull request #2998 from lateralusX/jlorenss/win-x64-full-aot-support
[mono.git] / mono / metadata / threads.c
index 081068c244de60ebf46231b58e13b9fe37361ca0..8acb6f5efafa01e91926c3b54cdc1dd87f3849a9 100644 (file)
@@ -464,6 +464,8 @@ static void thread_cleanup (MonoInternalThread *thread)
        if (!mono_thread_info_lookup (MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid))->tools_thread)
                mono_profiler_thread_end (thread->tid);
 
+       mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
+
        if (thread == mono_thread_internal_current ()) {
                /*
                 * This will signal async signal handlers that the thread has exited.
@@ -733,12 +735,13 @@ static guint32 WINAPI start_wrapper_internal(void *data)
        mono_profiler_thread_start (tid);
 
        /* if the name was set before starting, we didn't invoke the profiler callback */
-       if (internal->name && (internal->flags & MONO_THREAD_FLAG_NAME_SET)) {
+       if (internal->name) {
                char *tname = g_utf16_to_utf8 (internal->name, internal->name_len, NULL, NULL, NULL);
                mono_profiler_thread_name (internal->tid, tname);
-               mono_thread_info_set_name (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid), tname);
+               mono_native_thread_set_name (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid), tname);
                g_free (tname);
        }
+
        /* start_func is set only for unmanaged start functions */
        if (start_func) {
                start_func (start_arg);
@@ -747,7 +750,8 @@ static guint32 WINAPI start_wrapper_internal(void *data)
                g_assert (start_delegate != NULL);
                args [0] = start_arg;
                /* we may want to handle the exception here. See comment below on unhandled exceptions */
-               mono_runtime_delegate_invoke (start_delegate, args, NULL);
+               mono_runtime_delegate_invoke_checked (start_delegate, args, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
        }
 
        /* If the thread calls ExitThread at all, this remaining code
@@ -885,9 +889,9 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
                 */
                THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
 
-               MONO_PREPARE_BLOCKING;
+               MONO_ENTER_GC_SAFE;
                WaitForSingleObjectEx (internal->start_notify, INFINITE, FALSE);
-               MONO_FINISH_BLOCKING;
+               MONO_EXIT_GC_SAFE;
 
                CloseHandle (internal->start_notify);
                internal->start_notify = NULL;
@@ -1370,13 +1374,13 @@ ves_icall_System_Threading_Thread_GetName_internal (MonoInternalThread *this_obj
 }
 
 void 
-mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean managed, MonoError *error)
+mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean permanent, MonoError *error)
 {
        LOCK_THREAD (this_obj);
 
        mono_error_init (error);
 
-       if ((this_obj->flags & MONO_THREAD_FLAG_NAME_SET) && !this_obj->threadpool_thread) {
+       if ((this_obj->flags & MONO_THREAD_FLAG_NAME_SET)) {
                UNLOCK_THREAD (this_obj);
                
                mono_error_set_invalid_operation (error, "Thread.Name can only be set once.");
@@ -1390,19 +1394,20 @@ mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, g
                this_obj->name = g_new (gunichar2, mono_string_length (name));
                memcpy (this_obj->name, mono_string_chars (name), mono_string_length (name) * 2);
                this_obj->name_len = mono_string_length (name);
+
+               if (permanent)
+                       this_obj->flags |= MONO_THREAD_FLAG_NAME_SET;
        }
        else
                this_obj->name = NULL;
 
-       if (managed)
-               this_obj->flags |= MONO_THREAD_FLAG_NAME_SET;
        
        UNLOCK_THREAD (this_obj);
 
        if (this_obj->name && this_obj->tid) {
                char *tname = mono_string_to_utf8 (name);
                mono_profiler_thread_name (this_obj->tid, tname);
-               mono_thread_info_set_name (thread_get_tid (this_obj), tname);
+               mono_native_thread_set_name (thread_get_tid (this_obj), tname);
                mono_free (tname);
        }
 }
@@ -1562,9 +1567,9 @@ ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms)
        
        mono_thread_set_state (cur_thread, ThreadState_WaitSleepJoin);
 
-       MONO_PREPARE_BLOCKING;
+       MONO_ENTER_GC_SAFE;
        ret=WaitForSingleObjectEx (handle, ms, TRUE);
-       MONO_FINISH_BLOCKING;
+       MONO_EXIT_GC_SAFE;
 
        mono_thread_clr_state (cur_thread, ThreadState_WaitSleepJoin);
        
@@ -1590,12 +1595,12 @@ mono_wait_uninterrupted (MonoInternalThread *thread, gboolean multiple, guint32
 
        start = (ms == -1) ? 0 : mono_100ns_ticks ();
        do {
-               MONO_PREPARE_BLOCKING;
+               MONO_ENTER_GC_SAFE;
                        if (multiple)
                        ret = WaitForMultipleObjectsEx (numhandles, handles, waitall, wait, alertable);
                else
                        ret = WaitForSingleObjectEx (handles [0], ms, alertable);
-               MONO_FINISH_BLOCKING;
+               MONO_EXIT_GC_SAFE;
 
                if (ret != WAIT_IO_COMPLETION)
                        break;
@@ -1740,9 +1745,9 @@ ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, H
 
        mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
        
-       MONO_PREPARE_BLOCKING;
+       MONO_ENTER_GC_SAFE;
        ret = SignalObjectAndWait (toSignal, toWait, ms, TRUE);
-       MONO_FINISH_BLOCKING;
+       MONO_EXIT_GC_SAFE;
        
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
 
@@ -2911,9 +2916,9 @@ static void wait_for_tids (struct wait_data *wait, guint32 timeout)
        
        THREAD_DEBUG (g_message("%s: %d threads to wait for in this batch", __func__, wait->num));
 
-       MONO_PREPARE_BLOCKING;
+       MONO_ENTER_GC_SAFE;
        ret=WaitForMultipleObjectsEx(wait->num, wait->handles, TRUE, timeout, TRUE);
-       MONO_FINISH_BLOCKING;
+       MONO_EXIT_GC_SAFE;
 
        if(ret==WAIT_FAILED) {
                /* See the comment in build_wait_tids() */
@@ -2974,9 +2979,9 @@ static void wait_for_tids_or_state_change (struct wait_data *wait, guint32 timeo
                count++;
        }
 
-       MONO_PREPARE_BLOCKING;
+       MONO_ENTER_GC_SAFE;
        ret=WaitForMultipleObjectsEx (count, wait->handles, FALSE, timeout, TRUE);
-       MONO_FINISH_BLOCKING;
+       MONO_EXIT_GC_SAFE;
 
        if(ret==WAIT_FAILED) {
                /* See the comment in build_wait_tids() */
@@ -3083,9 +3088,8 @@ remove_and_abort_threads (gpointer key, gpointer value, gpointer user)
                if (handle == NULL)
                        return FALSE;
 
-               /* printf ("A: %d\n", wait->num); */
-               wait->handles[wait->num]=thread->handle;
-               wait->threads[wait->num]=thread;
+               wait->handles[wait->num] = handle;
+               wait->threads[wait->num] = thread;
                wait->num++;
 
                THREAD_DEBUG (g_print ("%s: Aborting id: %"G_GSIZE_FORMAT"\n", __func__, (gsize)thread->tid));
@@ -3796,7 +3800,7 @@ mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout)
 #endif
 
        abort_appdomain_data user_data;
-       guint32 start_time;
+       gint64 start_time;
        int orig_timeout = timeout;
        int i;
 
@@ -4376,8 +4380,18 @@ mono_thread_execute_interruption (void)
                mono_thread_info_clear_self_interrupt ();
        }
 
-       if ((thread->state & ThreadState_AbortRequested) != 0) {
+       /* If there's a pending exception and an AbortRequested, the pending exception takes precedence */
+       if (sys_thread->pending_exception) {
+               MonoException *exc;
+
+               exc = sys_thread->pending_exception;
+               sys_thread->pending_exception = NULL;
+
                UNLOCK_THREAD (thread);
+               return exc;
+       } else if ((thread->state & ThreadState_AbortRequested) != 0) {
+               UNLOCK_THREAD (thread);
+               g_assert (sys_thread->pending_exception == NULL);
                if (thread->abort_exc == NULL) {
                        /* 
                         * This might be racy, but it has to be called outside the lock
@@ -4399,14 +4413,6 @@ mono_thread_execute_interruption (void)
                
                mono_thread_exit ();
                return NULL;
-       } else if (sys_thread->pending_exception) {
-               MonoException *exc;
-
-               exc = sys_thread->pending_exception;
-               sys_thread->pending_exception = NULL;
-
-        UNLOCK_THREAD (thread);
-        return exc;
        } else if (thread->thread_interrupt_requested) {
 
                thread->thread_interrupt_requested = FALSE;