[runtime] Implement the new suspend infrastructure on windows.
[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  */
12 #include <config.h>
13 #include <signal.h>
14 #include <math.h>
15
16 #include <mono/metadata/assembly.h>
17 #include <mono/metadata/loader.h>
18 #include <mono/metadata/tabledefs.h>
19 #include <mono/metadata/class.h>
20 #include <mono/metadata/object.h>
21 #include <mono/metadata/tokentype.h>
22 #include <mono/metadata/tabledefs.h>
23 #include <mono/metadata/threads.h>
24 #include <mono/metadata/appdomain.h>
25 #include <mono/metadata/debug-helpers.h>
26 #include <mono/io-layer/io-layer.h>
27 #include "mono/metadata/profiler.h"
28 #include <mono/metadata/profiler-private.h>
29 #include <mono/metadata/mono-config.h>
30 #include <mono/metadata/environment.h>
31 #include <mono/metadata/mono-debug.h>
32 #include <mono/metadata/gc-internal.h>
33 #include <mono/metadata/threads-types.h>
34 #include <mono/metadata/verify.h>
35 #include <mono/metadata/verify-internals.h>
36 #include <mono/metadata/mempool-internals.h>
37 #include <mono/metadata/attach.h>
38 #include <mono/utils/mono-math.h>
39 #include <mono/utils/mono-compiler.h>
40 #include <mono/utils/mono-counters.h>
41 #include <mono/utils/mono-logger-internal.h>
42 #include <mono/utils/mono-mmap.h>
43 #include <mono/utils/dtrace.h>
44
45 #include "mini.h"
46 #include <string.h>
47 #include <ctype.h>
48 #include "trace.h"
49 #include "version.h"
50
51 #include "jit-icalls.h"
52
53 void
54 mono_runtime_install_handlers (void)
55 {
56 #ifndef MONO_CROSS_COMPILE
57         win32_seh_init();
58         win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
59         win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
60         win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
61         if (mini_get_debug_options ()->handle_sigint)
62                 win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
63 #endif
64 }
65
66 void
67 mono_runtime_cleanup_handlers (void)
68 {
69 #ifndef MONO_CROSS_COMPILE
70         win32_seh_cleanup();
71 #endif
72 }
73
74
75 /* mono_chain_signal:
76  *
77  *   Call the original signal handler for the signal given by the arguments, which
78  * should be the same as for a signal handler. Returns TRUE if the original handler
79  * was called, false otherwise.
80  */
81 gboolean
82 SIG_HANDLER_SIGNATURE (mono_chain_signal)
83 {
84         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
85         jit_tls->mono_win_chained_exception_needs_run = TRUE;
86         return TRUE;
87 }
88
89 static HANDLE win32_main_thread;
90 static MMRESULT win32_timer;
91
92 static void CALLBACK
93 win32_time_proc (UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
94 {
95         CONTEXT context;
96
97         context.ContextFlags = CONTEXT_CONTROL;
98         if (GetThreadContext (win32_main_thread, &context)) {
99 #ifdef _WIN64
100                 mono_profiler_stat_hit ((guchar *) context.Rip, &context);
101 #else
102                 mono_profiler_stat_hit ((guchar *) context.Eip, &context);
103 #endif
104         }
105 }
106
107 void
108 mono_runtime_setup_stat_profiler (void)
109 {
110         static int inited = 0;
111         TIMECAPS timecaps;
112
113         if (inited)
114                 return;
115
116         inited = 1;
117         if (timeGetDevCaps (&timecaps, sizeof (timecaps)) != TIMERR_NOERROR)
118                 return;
119
120         if ((win32_main_thread = OpenThread (READ_CONTROL | THREAD_GET_CONTEXT, FALSE, GetCurrentThreadId ())) == NULL)
121                 return;
122
123         if (timeBeginPeriod (1) != TIMERR_NOERROR)
124                 return;
125
126         if ((win32_timer = timeSetEvent (1, 0, (LPTIMECALLBACK)win32_time_proc, (DWORD_PTR)NULL, TIME_PERIODIC)) == 0) {
127                 timeEndPeriod (1);
128                 return;
129         }
130 }
131
132 void
133 mono_runtime_shutdown_stat_profiler (void)
134 {
135 }
136
137 gboolean
138 mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info)
139 {
140         DWORD id = mono_thread_info_get_tid (info);
141         HANDLE handle;
142         CONTEXT context;
143         DWORD result;
144         MonoContext *ctx;
145         MonoJitTlsData *jit_tls;
146         void *domain;
147         MonoLMF *lmf = NULL;
148         gpointer *addr;
149
150         tctx->valid = FALSE;
151         tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = NULL;
152         tctx->unwind_data [MONO_UNWIND_DATA_LMF] = NULL;
153         tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL;
154
155         g_assert (id != GetCurrentThreadId ());
156
157         handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id);
158         g_assert (handle);
159
160         context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
161
162         if (!GetThreadContext (handle, &context)) {
163                 CloseHandle (handle);
164                 return FALSE;
165         }
166
167         g_assert (context.ContextFlags & CONTEXT_INTEGER);
168         g_assert (context.ContextFlags & CONTEXT_CONTROL);
169
170         ctx = &tctx->ctx;
171
172         memset (ctx, 0, sizeof (MonoContext));
173 #ifdef TARGET_AMD64
174         ctx->rip = context.Rip;
175         ctx->rax = context.Rax;
176         ctx->rcx = context.Rcx;
177         ctx->rdx = context.Rdx;
178         ctx->rbx = context.Rbx;
179         ctx->rsp = context.Rsp;
180         ctx->rbp = context.Rbp;
181         ctx->rsi = context.Rsi;
182         ctx->rdi = context.Rdi;
183         ctx->r8 = context.R8;
184         ctx->r9 = context.R9;
185         ctx->r10 = context.R10;
186         ctx->r11 = context.R11;
187         ctx->r12 = context.R12;
188         ctx->r13 = context.R13;
189         ctx->r14 = context.R14;
190         ctx->r15 = context.R15;
191 #else
192         ctx->edi = context.Edi;
193         ctx->esi = context.Esi;
194         ctx->ebx = context.Ebx;
195         ctx->edx = context.Edx;
196         ctx->ecx = context.Ecx;
197         ctx->eax = context.Eax;
198         ctx->ebp = context.Ebp;
199         ctx->esp = context.Esp;
200 #endif
201
202         /* mono_set_jit_tls () sets this */
203         jit_tls = mono_thread_info_tls_get (info, TLS_KEY_JIT_TLS);
204         /* SET_APPDOMAIN () sets this */
205         domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN);
206
207         /*Thread already started to cleanup, can no longer capture unwind state*/
208         if (!jit_tls || !domain)
209                 return FALSE;
210
211         /*
212          * The current LMF address is kept in a separate TLS variable, and its hard to read its value without
213          * arch-specific code. But the address of the TLS variable is stored in another TLS variable which
214          * can be accessed through MonoThreadInfo.
215          */
216         /* mono_set_lmf_addr () sets this */
217         addr = mono_thread_info_tls_get (info, TLS_KEY_LMF_ADDR);
218         if (addr)
219                 lmf = *addr;
220
221         tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain;
222         tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls;
223         tctx->unwind_data [MONO_UNWIND_DATA_LMF] = lmf;
224         tctx->valid = TRUE;
225
226         return TRUE;
227 }
228