Merge pull request #2820 from kumpera/license-change-rebased
[mono.git] / mono / mini / mini-windows.c
index c43b1d0102f6d156e58b801e317e1c9bac36a8b5..621a7a5fc31970e22d3e75e4993623ae10dddece 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2003-2008 Ximian, Inc.
  *
  * See LICENSE for licensing information.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <signal.h>
@@ -29,7 +30,7 @@
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
 #include <mono/metadata/mono-debug.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/verify.h>
 #include <mono/metadata/verify-internals.h>
@@ -38,7 +39,7 @@
 #include <mono/utils/mono-math.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-counters.h>
-#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-logger-internals.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/dtrace.h>
 
 
 #include "jit-icalls.h"
 
+#ifdef _WIN32
+#include <mmsystem.h>
+#endif
+
 void
 mono_runtime_install_handlers (void)
 {
 #ifndef MONO_CROSS_COMPILE
-       win32_seh_init();
-       win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
-       win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
-       win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
-       if (mini_get_debug_options ()->handle_sigint)
-               win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
+       if (!mono_aot_only) {
+               win32_seh_init();
+               win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
+               win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
+               win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
+               if (mini_get_debug_options ()->handle_sigint)
+                       win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
+       }
 #endif
 }
 
@@ -67,7 +74,9 @@ void
 mono_runtime_cleanup_handlers (void)
 {
 #ifndef MONO_CROSS_COMPILE
-       win32_seh_cleanup();
+       if (!mono_aot_only) {
+               win32_seh_cleanup();
+       }
 #endif
 }
 
@@ -79,7 +88,7 @@ mono_runtime_cleanup_handlers (void)
  * was called, false otherwise.
  */
 gboolean
-SIG_HANDLER_SIGNATURE (mono_chain_signal)
+MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
 {
        MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
        jit_tls->mono_win_chained_exception_needs_run = TRUE;
@@ -123,7 +132,7 @@ mono_runtime_setup_stat_profiler (void)
        if (timeBeginPeriod (1) != TIMERR_NOERROR)
                return;
 
-       if ((win32_timer = timeSetEvent (1, 0, win32_time_proc, 0, TIME_PERIODIC)) == 0) {
+       if ((win32_timer = timeSetEvent (1, 0, (LPTIMECALLBACK)win32_time_proc, (DWORD_PTR)NULL, TIME_PERIODIC)) == 0) {
                timeEndPeriod (1);
                return;
        }
@@ -137,7 +146,65 @@ mono_runtime_shutdown_stat_profiler (void)
 gboolean
 mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info)
 {
-       g_error ("Windows systems haven't been ported to support mono_thread_state_init_from_handle");
-       return FALSE;
+       DWORD id = mono_thread_info_get_tid (info);
+       HANDLE handle;
+       CONTEXT context;
+       DWORD result;
+       MonoContext *ctx;
+       MonoJitTlsData *jit_tls;
+       void *domain;
+       MonoLMF *lmf = NULL;
+       gpointer *addr;
+
+       tctx->valid = FALSE;
+       tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = NULL;
+       tctx->unwind_data [MONO_UNWIND_DATA_LMF] = NULL;
+       tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL;
+
+       g_assert (id != GetCurrentThreadId ());
+
+       handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id);
+       g_assert (handle);
+
+       context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
+
+       if (!GetThreadContext (handle, &context)) {
+               CloseHandle (handle);
+               return FALSE;
+       }
+
+       g_assert (context.ContextFlags & CONTEXT_INTEGER);
+       g_assert (context.ContextFlags & CONTEXT_CONTROL);
+
+       ctx = &tctx->ctx;
+
+       memset (ctx, 0, sizeof (MonoContext));
+       mono_sigctx_to_monoctx (&context, ctx);
+
+       /* mono_set_jit_tls () sets this */
+       jit_tls = mono_thread_info_tls_get (info, TLS_KEY_JIT_TLS);
+       /* SET_APPDOMAIN () sets this */
+       domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN);
+
+       /*Thread already started to cleanup, can no longer capture unwind state*/
+       if (!jit_tls || !domain)
+               return FALSE;
+
+       /*
+        * The current LMF address is kept in a separate TLS variable, and its hard to read its value without
+        * arch-specific code. But the address of the TLS variable is stored in another TLS variable which
+        * can be accessed through MonoThreadInfo.
+        */
+       /* mono_set_lmf_addr () sets this */
+       addr = mono_thread_info_tls_get (info, TLS_KEY_LMF_ADDR);
+       if (addr)
+               lmf = *addr;
+
+       tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain;
+       tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls;
+       tctx->unwind_data [MONO_UNWIND_DATA_LMF] = lmf;
+       tctx->valid = TRUE;
+
+       return TRUE;
 }