Merge pull request #3547 from cmp-/remove-obsolete-stack-checks-win32
[mono.git] / mono / utils / mono-threads.c
index d9791d0764b48f78100f799c7a802c422df7a29e..d0c7fa1040ed7ecd39e64967b395e2d85c1ac076 100644 (file)
@@ -118,7 +118,7 @@ begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
                return TRUE;
        }
 
-       return mono_threads_core_begin_async_suspend (info, interrupt_kernel);
+       return mono_threads_suspend_begin_async_suspend (info, interrupt_kernel);
 }
 
 static gboolean
@@ -129,7 +129,7 @@ check_async_suspend (MonoThreadInfo *info)
                return TRUE;
        }
 
-       return mono_threads_core_check_suspend_result (info);
+       return mono_threads_suspend_check_suspend_result (info);
 }
 
 static void
@@ -138,7 +138,7 @@ resume_async_suspended (MonoThreadInfo *info)
        if (mono_threads_is_coop_enabled ())
                g_assert_not_reached ();
 
-       g_assert (mono_threads_core_begin_async_resume (info));
+       g_assert (mono_threads_suspend_begin_async_resume (info));
 }
 
 static void
@@ -279,9 +279,9 @@ If return non null Hazard Pointer 1 holds the return value.
 MonoThreadInfo*
 mono_thread_info_lookup (MonoNativeThreadId id)
 {
-               MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
+       MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
 
-       if (!mono_lls_find (&thread_list, hp, (uintptr_t)id, HAZARD_FREE_ASYNC_CTX)) {
+       if (!mono_lls_find (&thread_list, hp, (uintptr_t)id)) {
                mono_hazard_pointer_clear_all (hp, -1);
                return NULL;
        } 
@@ -295,7 +295,7 @@ mono_thread_info_insert (MonoThreadInfo *info)
 {
        MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
 
-       if (!mono_lls_insert (&thread_list, hp, (MonoLinkedListSetNode*)info, HAZARD_FREE_SAFE_CTX)) {
+       if (!mono_lls_insert (&thread_list, hp, (MonoLinkedListSetNode*)info)) {
                mono_hazard_pointer_clear_all (hp, -1);
                return FALSE;
        } 
@@ -311,7 +311,7 @@ mono_thread_info_remove (MonoThreadInfo *info)
        gboolean res;
 
        THREADS_DEBUG ("removing info %p\n", info);
-       res = mono_lls_remove (&thread_list, hp, (MonoLinkedListSetNode*)info, HAZARD_FREE_SAFE_CTX);
+       res = mono_lls_remove (&thread_list, hp, (MonoLinkedListSetNode*)info);
        mono_hazard_pointer_clear_all (hp, -1);
        return res;
 }
@@ -322,7 +322,7 @@ free_thread_info (gpointer mem)
        MonoThreadInfo *info = (MonoThreadInfo *) mem;
 
        mono_os_sem_destroy (&info->resume_semaphore);
-       mono_threads_platform_free (info);
+       mono_threads_suspend_free (info);
 
        g_free (info);
 }
@@ -374,6 +374,7 @@ register_thread (MonoThreadInfo *info, gpointer baseptr)
        info->stackdata = g_byte_array_new ();
 
        mono_threads_platform_register (info);
+       mono_threads_suspend_register (info);
 
        /*
        Transition it before taking any locks or publishing itself to reduce the chance
@@ -402,6 +403,8 @@ unregister_thread (void *arg)
 
        info = (MonoThreadInfo *) arg;
        g_assert (info);
+       g_assert (mono_thread_info_is_current (info));
+       g_assert (mono_thread_info_is_live (info));
 
        small_id = info->small_id;
 
@@ -413,7 +416,7 @@ unregister_thread (void *arg)
 
        mono_native_tls_set_value (thread_exited_key, GUINT_TO_POINTER (1));
 
-       mono_threads_core_unregister (info);
+       mono_threads_platform_unregister (info);
 
        /*
         * TLS destruction order is not reliable so small_id might be cleaned up
@@ -637,6 +640,20 @@ mono_thread_info_is_exiting (void)
        return FALSE;
 }
 
+#ifndef HOST_WIN32
+static void
+thread_info_key_dtor (void *arg)
+{
+       /* Put the MonoThreadInfo back for the duration of the
+        * unregister code.  In some circumstances the thread needs to
+        * take the GC lock which may block which requires a coop
+        * state transition. */
+       mono_native_tls_set_value (thread_info_key, arg);
+       unregister_thread (arg);
+       mono_native_tls_set_value (thread_info_key, NULL);
+}
+#endif
+
 void
 mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
 {
@@ -648,7 +665,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
        res = mono_native_tls_alloc (&thread_info_key, NULL);
        res = mono_native_tls_alloc (&thread_exited_key, NULL);
 #else
-       res = mono_native_tls_alloc (&thread_info_key, (void *) unregister_thread);
+       res = mono_native_tls_alloc (&thread_info_key, (void *) thread_info_key_dtor);
        res = mono_native_tls_alloc (&thread_exited_key, (void *) thread_exited_dtor);
 #endif
 
@@ -674,11 +691,12 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
        mono_os_sem_init (&global_suspend_semaphore, 1);
        mono_os_sem_init (&suspend_semaphore, 0);
 
-       mono_lls_init (&thread_list, NULL, HAZARD_FREE_NO_LOCK);
+       mono_lls_init (&thread_list, NULL);
        mono_thread_smr_init ();
-       mono_threads_init_platform ();
-       mono_threads_init_coop ();
-       mono_threads_init_abort_syscall ();
+       mono_threads_platform_init ();
+       mono_threads_suspend_init ();
+       mono_threads_coop_init ();
+       mono_threads_abort_syscall_init ();
 
 #if defined(__MACH__)
        mono_mach_init (thread_info_key);
@@ -748,13 +766,6 @@ static gboolean
 mono_thread_info_core_resume (MonoThreadInfo *info)
 {
        gboolean res = FALSE;
-       if (info->create_suspended) {
-               MonoNativeThreadId tid = mono_thread_info_get_tid (info);
-               /* Have to special case this, as the normal suspend/resume pair are racy, they don't work if he resume is received before the suspend */
-               info->create_suspended = FALSE;
-               mono_threads_core_resume_created (info, tid);
-               return TRUE;
-       }
 
        switch (mono_threads_transition_request_resume (info)) {
        case ResumeError:
@@ -906,7 +917,7 @@ suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel)
                break;
        case AsyncSuspendBlocking:
                if (interrupt_kernel)
-                       mono_threads_core_abort_syscall (info);
+                       mono_threads_suspend_abort_syscall (info);
 
                break;
        default:
@@ -1025,6 +1036,8 @@ static void
 mono_thread_info_suspend_lock_with_info (MonoThreadInfo *info)
 {
        g_assert (info);
+       g_assert (mono_thread_info_is_current (info));
+       g_assert (mono_thread_info_is_live (info));
 
        MONO_ENTER_GC_SAFE_WITH_INFO(info);
 
@@ -1062,7 +1075,7 @@ mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid)
        MonoThreadHazardPointers *hp;
        MonoThreadInfo *info;
 
-       if (tid == mono_native_thread_id_get () || !mono_threads_core_needs_abort_syscall ())
+       if (tid == mono_native_thread_id_get () || !mono_threads_suspend_needs_abort_syscall ())
                return;
 
        hp = mono_hazard_pointer_get ();
@@ -1078,7 +1091,7 @@ mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid)
        mono_thread_info_suspend_lock ();
        mono_threads_begin_global_suspend ();
 
-       mono_threads_core_abort_syscall (info);
+       mono_threads_suspend_abort_syscall (info);
        mono_threads_wait_pending_operations ();
 
        mono_hazard_pointer_clear (hp, 1);
@@ -1119,6 +1132,54 @@ mono_thread_info_is_async_context (void)
                return FALSE;
 }
 
+typedef struct {
+       gint32 ref;
+       MonoThreadStart start_routine;
+       gpointer start_routine_arg;
+       gint32 priority;
+       MonoCoopSem registered;
+       gpointer handle;
+} CreateThreadData;
+
+static gsize WINAPI
+inner_start_thread (gpointer data)
+{
+       CreateThreadData *thread_data;
+       MonoThreadInfo *info;
+       MonoThreadStart start_routine;
+       gpointer start_routine_arg;
+       guint32 start_routine_res;
+       gsize dummy;
+
+       thread_data = (CreateThreadData*) data;
+       g_assert (thread_data);
+
+       start_routine = thread_data->start_routine;
+       start_routine_arg = thread_data->start_routine_arg;
+
+       info = mono_thread_info_attach (&dummy);
+       info->runtime_thread = TRUE;
+
+       thread_data->handle = mono_thread_info_duplicate_handle (info);
+
+       mono_coop_sem_post (&thread_data->registered);
+
+       if (InterlockedDecrement (&thread_data->ref) == 0) {
+               mono_coop_sem_destroy (&thread_data->registered);
+               g_free (thread_data);
+       }
+
+       /* thread_data is not valid anymore */
+       thread_data = NULL;
+
+       /* Run the actual main function of the thread */
+       start_routine_res = start_routine (start_routine_arg);
+
+       mono_threads_platform_exit (start_routine_res);
+
+       g_assert_not_reached ();
+}
+
 /*
  * mono_threads_create_thread:
  *
@@ -1126,9 +1187,39 @@ mono_thread_info_is_async_context (void)
  * Returns: a windows or io-layer handle for the thread.
  */
 HANDLE
-mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid)
-{
-       return mono_threads_core_create_thread (start, arg, tp, out_tid);
+mono_threads_create_thread (MonoThreadStart start, gpointer arg, gsize stack_size, MonoNativeThreadId *out_tid)
+{
+       CreateThreadData *thread_data;
+       gint res;
+       gpointer ret;
+
+       thread_data = g_new0 (CreateThreadData, 1);
+       thread_data->ref = 2;
+       thread_data->start_routine = start;
+       thread_data->start_routine_arg = arg;
+       mono_coop_sem_init (&thread_data->registered, 0);
+
+       res = mono_threads_platform_create_thread (inner_start_thread, (gpointer) thread_data, stack_size, out_tid);
+       if (res != 0) {
+               /* ref is not going to be decremented in inner_start_thread */
+               InterlockedDecrement (&thread_data->ref);
+               ret = NULL;
+               goto done;
+       }
+
+       res = mono_coop_sem_wait (&thread_data->registered, MONO_SEM_FLAGS_NONE);
+       g_assert (res == 0);
+
+       ret = thread_data->handle;
+       g_assert (ret);
+
+done:
+       if (InterlockedDecrement (&thread_data->ref) == 0) {
+               mono_coop_sem_destroy (&thread_data->registered);
+               g_free (thread_data);
+       }
+
+       return ret;
 }
 
 /*
@@ -1141,7 +1232,7 @@ void
 mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize)
 {
        guint8 *current = (guint8 *)&stsize;
-       mono_threads_core_get_stack_bounds (staddr, stsize);
+       mono_threads_platform_get_stack_bounds (staddr, stsize);
        if (!*staddr)
                return;
 
@@ -1155,7 +1246,7 @@ mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize)
 gboolean
 mono_thread_info_yield (void)
 {
-       return mono_threads_core_yield ();
+       return mono_threads_platform_yield ();
 }
 static mono_lazy_init_t sleep_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
 static MonoCoopMutex sleep_mutex;
@@ -1187,7 +1278,7 @@ sleep_interruptable (guint32 ms, gboolean *alerted)
        *alerted = FALSE;
 
        if (ms != INFINITE)
-               end = mono_100ns_ticks () + (ms * 1000 * 10);
+               end = mono_msec_ticks() + ms;
 
        mono_lazy_initialize (&sleep_init, sleep_initialize);
 
@@ -1195,8 +1286,8 @@ sleep_interruptable (guint32 ms, gboolean *alerted)
 
        for (;;) {
                if (ms != INFINITE) {
-                       now = mono_100ns_ticks ();
-                       if (now > end)
+                       now = mono_msec_ticks();
+                       if (now >= end)
                                break;
                }
 
@@ -1207,7 +1298,7 @@ sleep_interruptable (guint32 ms, gboolean *alerted)
                }
 
                if (ms != INFINITE)
-                       mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, (end - now) / 10 / 1000);
+                       mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, end - now);
                else
                        mono_coop_cond_wait (&sleep_cond, &sleep_mutex);
 
@@ -1329,20 +1420,7 @@ mono_thread_info_tls_set (THREAD_INFO_TYPE *info, MonoTlsKey key, gpointer value
 void
 mono_thread_info_exit (void)
 {
-       mono_threads_core_exit (0);
-}
-
-/*
- * mono_thread_info_open_handle:
- *
- *   Return a io-layer/win32 handle for the current thread.
- * The handle need to be closed by calling CloseHandle () when it is no
- * longer needed.
- */
-HANDLE
-mono_thread_info_open_handle (void)
-{
-       return mono_threads_core_open_handle ();
+       mono_threads_platform_exit (0);
 }
 
 /*
@@ -1355,7 +1433,13 @@ mono_thread_info_open_handle (void)
 HANDLE
 mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid)
 {
-       return mono_threads_core_open_thread_handle (handle, tid);
+       return mono_threads_platform_open_thread_handle (handle, tid);
+}
+
+void
+mono_threads_close_thread_handle (HANDLE handle)
+{
+       return mono_threads_platform_close_thread_handle (handle);
 }
 
 #define INTERRUPT_STATE ((MonoThreadInfoInterruptToken*) (size_t) -1)
@@ -1563,3 +1647,29 @@ mono_thread_info_is_current (MonoThreadInfo *info)
 {
        return mono_thread_info_get_tid (info) == mono_native_thread_id_get ();
 }
+
+void
+mono_thread_info_set_exited (THREAD_INFO_TYPE *info)
+{
+       g_assert (mono_thread_info_is_current (info));
+       mono_threads_platform_set_exited (info);
+}
+
+gpointer
+mono_thread_info_duplicate_handle (MonoThreadInfo *info)
+{
+       g_assert (mono_thread_info_is_current (info));
+       return mono_threads_platform_duplicate_handle (info);
+}
+
+void
+mono_thread_info_own_mutex (MonoThreadInfo *info, gpointer mutex_handle)
+{
+       mono_threads_platform_own_mutex (info, mutex_handle);
+}
+
+void
+mono_thread_info_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle)
+{
+       mono_threads_platform_disown_mutex (info, mutex_handle);
+}