Merge pull request #2820 from kumpera/license-change-rebased
[mono.git] / mono / mini / mini-windows.c
1 /*
2  * mini-posix.c: POSIX signal handling support for Mono.
3  *
4  * Authors:
5  *   Mono Team (mono-list@lists.ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc.
8  * Copyright 2003-2008 Ximian, Inc.
9  *
10  * See LICENSE for licensing information.
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13 #include <config.h>
14 #include <signal.h>
15 #include <math.h>
16
17 #include <mono/metadata/assembly.h>
18 #include <mono/metadata/loader.h>
19 #include <mono/metadata/tabledefs.h>
20 #include <mono/metadata/class.h>
21 #include <mono/metadata/object.h>
22 #include <mono/metadata/tokentype.h>
23 #include <mono/metadata/tabledefs.h>
24 #include <mono/metadata/threads.h>
25 #include <mono/metadata/appdomain.h>
26 #include <mono/metadata/debug-helpers.h>
27 #include <mono/io-layer/io-layer.h>
28 #include "mono/metadata/profiler.h"
29 #include <mono/metadata/profiler-private.h>
30 #include <mono/metadata/mono-config.h>
31 #include <mono/metadata/environment.h>
32 #include <mono/metadata/mono-debug.h>
33 #include <mono/metadata/gc-internals.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/verify.h>
36 #include <mono/metadata/verify-internals.h>
37 #include <mono/metadata/mempool-internals.h>
38 #include <mono/metadata/attach.h>
39 #include <mono/utils/mono-math.h>
40 #include <mono/utils/mono-compiler.h>
41 #include <mono/utils/mono-counters.h>
42 #include <mono/utils/mono-logger-internals.h>
43 #include <mono/utils/mono-mmap.h>
44 #include <mono/utils/dtrace.h>
45
46 #include "mini.h"
47 #include <string.h>
48 #include <ctype.h>
49 #include "trace.h"
50 #include "version.h"
51
52 #include "jit-icalls.h"
53
54 #ifdef _WIN32
55 #include <mmsystem.h>
56 #endif
57
58 void
59 mono_runtime_install_handlers (void)
60 {
61 #ifndef MONO_CROSS_COMPILE
62         if (!mono_aot_only) {
63                 win32_seh_init();
64                 win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
65                 win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
66                 win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
67                 if (mini_get_debug_options ()->handle_sigint)
68                         win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
69         }
70 #endif
71 }
72
73 void
74 mono_runtime_cleanup_handlers (void)
75 {
76 #ifndef MONO_CROSS_COMPILE
77         if (!mono_aot_only) {
78                 win32_seh_cleanup();
79         }
80 #endif
81 }
82
83
84 /* mono_chain_signal:
85  *
86  *   Call the original signal handler for the signal given by the arguments, which
87  * should be the same as for a signal handler. Returns TRUE if the original handler
88  * was called, false otherwise.
89  */
90 gboolean
91 MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
92 {
93         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
94         jit_tls->mono_win_chained_exception_needs_run = TRUE;
95         return TRUE;
96 }
97
98 static HANDLE win32_main_thread;
99 static MMRESULT win32_timer;
100
101 static void CALLBACK
102 win32_time_proc (UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
103 {
104         CONTEXT context;
105
106         context.ContextFlags = CONTEXT_CONTROL;
107         if (GetThreadContext (win32_main_thread, &context)) {
108 #ifdef _WIN64
109                 mono_profiler_stat_hit ((guchar *) context.Rip, &context);
110 #else
111                 mono_profiler_stat_hit ((guchar *) context.Eip, &context);
112 #endif
113         }
114 }
115
116 void
117 mono_runtime_setup_stat_profiler (void)
118 {
119         static int inited = 0;
120         TIMECAPS timecaps;
121
122         if (inited)
123                 return;
124
125         inited = 1;
126         if (timeGetDevCaps (&timecaps, sizeof (timecaps)) != TIMERR_NOERROR)
127                 return;
128
129         if ((win32_main_thread = OpenThread (READ_CONTROL | THREAD_GET_CONTEXT, FALSE, GetCurrentThreadId ())) == NULL)
130                 return;
131
132         if (timeBeginPeriod (1) != TIMERR_NOERROR)
133                 return;
134
135         if ((win32_timer = timeSetEvent (1, 0, (LPTIMECALLBACK)win32_time_proc, (DWORD_PTR)NULL, TIME_PERIODIC)) == 0) {
136                 timeEndPeriod (1);
137                 return;
138         }
139 }
140
141 void
142 mono_runtime_shutdown_stat_profiler (void)
143 {
144 }
145
146 gboolean
147 mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info)
148 {
149         DWORD id = mono_thread_info_get_tid (info);
150         HANDLE handle;
151         CONTEXT context;
152         DWORD result;
153         MonoContext *ctx;
154         MonoJitTlsData *jit_tls;
155         void *domain;
156         MonoLMF *lmf = NULL;
157         gpointer *addr;
158
159         tctx->valid = FALSE;
160         tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = NULL;
161         tctx->unwind_data [MONO_UNWIND_DATA_LMF] = NULL;
162         tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL;
163
164         g_assert (id != GetCurrentThreadId ());
165
166         handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id);
167         g_assert (handle);
168
169         context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
170
171         if (!GetThreadContext (handle, &context)) {
172                 CloseHandle (handle);
173                 return FALSE;
174         }
175
176         g_assert (context.ContextFlags & CONTEXT_INTEGER);
177         g_assert (context.ContextFlags & CONTEXT_CONTROL);
178
179         ctx = &tctx->ctx;
180
181         memset (ctx, 0, sizeof (MonoContext));
182         mono_sigctx_to_monoctx (&context, ctx);
183
184         /* mono_set_jit_tls () sets this */
185         jit_tls = mono_thread_info_tls_get (info, TLS_KEY_JIT_TLS);
186         /* SET_APPDOMAIN () sets this */
187         domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN);
188
189         /*Thread already started to cleanup, can no longer capture unwind state*/
190         if (!jit_tls || !domain)
191                 return FALSE;
192
193         /*
194          * The current LMF address is kept in a separate TLS variable, and its hard to read its value without
195          * arch-specific code. But the address of the TLS variable is stored in another TLS variable which
196          * can be accessed through MonoThreadInfo.
197          */
198         /* mono_set_lmf_addr () sets this */
199         addr = mono_thread_info_tls_get (info, TLS_KEY_LMF_ADDR);
200         if (addr)
201                 lmf = *addr;
202
203         tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain;
204         tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls;
205         tctx->unwind_data [MONO_UNWIND_DATA_LMF] = lmf;
206         tctx->valid = TRUE;
207
208         return TRUE;
209 }
210