[runtime] Only apply the maverick stack size hack added by d6673ca8ec854f291eb32c0484...
[mono.git] / mono / utils / mono-threads.c
index 5138427ed7c5c2de57d11eaffaa84d4420ef4af4..0258e2aa28fc31ca3e7556c2588dcd8aad0b6b74 100644 (file)
@@ -38,7 +38,7 @@ when it is in fact not.
 */
 static MonoSemType global_suspend_semaphore;
 
-static int thread_info_size;
+static size_t thread_info_size;
 static MonoThreadInfoCallbacks threads_callbacks;
 static MonoThreadInfoRuntimeCallbacks runtime_callbacks;
 static MonoNativeTlsKey thread_info_key, small_id_key;
@@ -168,6 +168,8 @@ unregister_thread (void *arg)
 
        THREADS_DEBUG ("unregistering info %p\n", info);
 
+       mono_threads_core_unregister (info);
+
        /*
         * TLS destruction order is not reliable so small_id might be cleaned up
         * before us.
@@ -284,14 +286,14 @@ mono_thread_info_attach (void *baseptr)
 }
 
 void
-mono_thread_info_dettach (void)
+mono_thread_info_detach (void)
 {
        MonoThreadInfo *info;
        if (!mono_threads_inited)
        {
                /* This can happen from DllMain(THREAD_DETACH) on Windows, if a thread
                 * is created before an embedding API user initialized Mono. */
-               THREADS_DEBUG ("mono_thread_info_dettach called before mono_threads_init\n");
+               THREADS_DEBUG ("mono_thread_info_detach called before mono_threads_init\n");
                return;
        }
        info = mono_native_tls_get_value (thread_info_key);
@@ -391,7 +393,6 @@ mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel
        ++info->suspend_count;
        info->thread_state |= STATE_SUSPENDED;
        MONO_SEM_POST (&info->suspend_semaphore);
-       mono_hazard_pointer_clear (hp, 1);
 
        return info;
 }
@@ -425,30 +426,10 @@ mono_thread_info_self_suspend (void)
 }
 
 static gboolean
-mono_thread_info_resume_internal (MonoThreadInfo *info)
+mono_thread_info_core_resume (MonoThreadInfo *info)
 {
        gboolean result;
-       if (mono_thread_info_suspend_state (info) == STATE_SELF_SUSPENDED) {
-               MONO_SEM_POST (&info->resume_semaphore);
-               MONO_SEM_WAIT_UNITERRUPTIBLE (&info->finish_resume_semaphore);
-               result = TRUE;
-       } else {
-               result = mono_threads_core_resume (info);
-       }
-       info->thread_state &= ~SUSPEND_STATE_MASK;
-       return result;
-}
-
-gboolean
-mono_thread_info_resume (MonoNativeThreadId tid)
-{
-       gboolean result = TRUE;
-       MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();      
-       MonoThreadInfo *info = mono_thread_info_lookup (tid); /*info on HP1*/
-
-       if (!info)
-               return FALSE;
-
+       MonoNativeThreadId tid = mono_thread_info_get_tid (info);
        if (info->create_suspended) {
                /* 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;
@@ -458,11 +439,10 @@ mono_thread_info_resume (MonoNativeThreadId tid)
 
        MONO_SEM_WAIT_UNITERRUPTIBLE (&info->suspend_semaphore);
 
-       THREADS_DEBUG ("resume %x IN COUNT %d\n",tid, info->suspend_count);
+       THREADS_DEBUG ("resume %x IN COUNT %d\n", tid, info->suspend_count);
 
        if (info->suspend_count <= 0) {
                MONO_SEM_POST (&info->suspend_semaphore);
-               mono_hazard_pointer_clear (hp, 1);
                return FALSE;
        }
 
@@ -472,19 +452,57 @@ mono_thread_info_resume (MonoNativeThreadId tid)
        */
        g_assert (mono_thread_info_get_tid (info));
 
-       if (--info->suspend_count == 0)
-               result = mono_thread_info_resume_internal (info);
+       if (--info->suspend_count == 0) {
+               if (mono_thread_info_suspend_state (info) == STATE_SELF_SUSPENDED) {
+                       MONO_SEM_POST (&info->resume_semaphore);
+                       MONO_SEM_WAIT_UNITERRUPTIBLE (&info->finish_resume_semaphore);
+                       result = TRUE;
+               } else {
+                       result = mono_threads_core_resume (info);
+               }
+               info->thread_state &= ~SUSPEND_STATE_MASK;
+       } else {
+               result = TRUE;
+       }
 
        MONO_SEM_POST (&info->suspend_semaphore);
-       mono_hazard_pointer_clear (hp, 1);
-       mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, FALSE);
+       return result;
+}
+
+gboolean
+mono_thread_info_resume (MonoNativeThreadId tid)
+{
+       gboolean result; /* don't initialize it so the compiler can catch unitilized paths. */
+       MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
+       MonoThreadInfo *info = mono_thread_info_lookup (tid); /*info on HP1*/
 
+       if (!info) {
+               result = FALSE;
+               goto cleanup;
+       }
+       result = mono_thread_info_core_resume (info);
+
+cleanup:
+       mono_hazard_pointer_clear (hp, 1);
        return result;
 }
 
 void
-mono_thread_info_finish_suspend (void)
+mono_thread_info_finish_suspend (MonoThreadInfo *info)
+{
+       mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, FALSE);
+}
+
+void
+mono_thread_info_finish_suspend_and_resume (MonoThreadInfo *info)
 {
+       MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
+
+       /*Resume can access info after the target has resumed, so we must ensure it won't touch freed memory. */
+       mono_hazard_pointer_set (hp, 1, info);
+       mono_thread_info_core_resume (info);
+       mono_hazard_pointer_clear (hp, 1);
+
        mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, FALSE);
 }
 
@@ -522,6 +540,10 @@ WARNING:
 If we are trying to suspend a target that is on a critical region
 and running a syscall we risk looping forever if @interrupt_kernel is FALSE.
 So, be VERY carefull in calling this with @interrupt_kernel == FALSE.
+
+Info is not put on a hazard pointer as a suspended thread cannot exit and be freed.
+
+This function MUST be matched with mono_thread_info_finish_suspend or mono_thread_info_finish_suspend_and_resume
 */
 MonoThreadInfo*
 mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
@@ -544,8 +566,9 @@ mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_ke
                if (!is_thread_in_critical_region (info))
                        break;
 
-               if (!mono_thread_info_resume (id)) {
+               if (!mono_thread_info_core_resume (info)) {
                        g_warning ("failed to result thread %p, hopefully it is dead", (gpointer)id);
+                       mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
                        mono_thread_info_suspend_unlock ();
                        return NULL;
                }
@@ -564,9 +587,10 @@ mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_ke
                sleep_duration += 10;
        }
 
+       /* XXX this clears HP 1, so we restated it again */
        mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, TRUE);
-
        mono_thread_info_suspend_unlock ();
+
        return info;
 }
 
@@ -717,7 +741,7 @@ mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32
 void
 mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize)
 {
-       return mono_threads_core_get_stack_bounds (staddr, stsize);
+       mono_threads_core_get_stack_bounds (staddr, stsize);
 }
 
 gboolean
@@ -745,3 +769,47 @@ mono_thread_info_tls_set (THREAD_INFO_TYPE *info, MonoTlsKey key, gpointer value
 {
        ((MonoThreadInfo*)info)->tls [key] = value;
 }
+
+/*
+ * mono_thread_info_exit:
+ *
+ *   Exit the current thread.
+ * This function doesn't return.
+ */
+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_thread_info_open_handle:
+ *
+ *   Return a io-layer/win32 handle for the thread identified by HANDLE/TID.
+ * The handle need to be closed by calling CloseHandle () when it is no
+ * longer needed.
+ */
+HANDLE
+mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid)
+{
+       return mono_threads_core_open_thread_handle (handle, tid);
+}
+
+void
+mono_thread_info_set_name (MonoNativeThreadId tid, const char *name)
+{
+       mono_threads_core_set_name (tid, name);
+}