[xbuild] Add new reserved properties $(MSBuildThisFile*).
[mono.git] / mono / metadata / sgen-os-mach.c
1 /*
2  * sgen-os-mach.c: Simple generational GC.
3  *
4  * Author:
5  *      Paolo Molaro (lupus@ximian.com)
6  *      Mark Probst (mprobst@novell.com)
7  *      Geoff Norton (gnorton@novell.com)
8  *
9  * Copyright 2010 Novell, Inc (http://www.novell.com)
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining
12  * a copy of this software and associated documentation files (the
13  * "Software"), to deal in the Software without restriction, including
14  * without limitation the rights to use, copy, modify, merge, publish,
15  * distribute, sublicense, and/or sell copies of the Software, and to
16  * permit persons to whom the Software is furnished to do so, subject to
17  * the following conditions:
18  * 
19  * The above copyright notice and this permission notice shall be
20  * included in all copies or substantial portions of the Software.
21  * 
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29  */
30
31 #include "config.h"
32 #ifdef HAVE_SGEN_GC
33 #include <glib.h>
34 #include "metadata/gc-internal.h"
35 #include "metadata/sgen-gc.h"
36 #include "metadata/sgen-archdep.h"
37 #include "metadata/object-internals.h"
38
39 #if defined(__MACH__)
40 #include "utils/mach-support.h"
41 #endif
42
43 /* LOCKING: assumes the GC lock is held */
44 #if defined(__MACH__) && MONO_MACH_ARCH_SUPPORTED
45 int
46 mono_sgen_thread_handshake (int signum)
47 {
48         task_t task = current_task ();
49         thread_port_t cur_thread = mach_thread_self ();
50         thread_act_array_t thread_list;
51         mach_msg_type_number_t num_threads;
52         mach_msg_type_number_t num_state;
53         thread_state_t state;
54         kern_return_t ret;
55         ucontext_t ctx;
56         mcontext_t mctx;
57         pthread_t exception_thread = mono_gc_get_mach_exception_thread ();
58
59         SgenThreadInfo *info;
60         gpointer regs [ARCH_NUM_REGS];
61         gpointer stack_start;
62
63         int count, i;
64
65         mono_mach_get_threads (&thread_list, &num_threads);
66
67         for (i = 0, count = 0; i < num_threads; i++) {
68                 thread_port_t t = thread_list [i];
69                 pthread_t pt = pthread_from_mach_thread_np (t);
70                 if (t != cur_thread && pt != exception_thread && !mono_sgen_is_worker_thread (pt)) {
71                         if (signum == suspend_signal_num) {
72                                 ret = thread_suspend (t);
73                                 if (ret != KERN_SUCCESS) {
74                                         mach_port_deallocate (task, t);
75                                         continue;
76                                 }
77
78                                 state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ());
79                                 ret = mono_mach_arch_get_thread_state (t, state, &num_state);
80                                 if (ret != KERN_SUCCESS) {
81                                         mach_port_deallocate (task, t);
82                                         continue;
83                                 }
84
85
86                                 info = mono_sgen_thread_info_lookup (pt);
87
88                                 /* Ensure that the runtime is aware of this thread */
89                                 if (info != NULL) {
90                                         mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ());
91                                         mono_mach_arch_thread_state_to_mcontext (state, mctx);
92                                         ctx.uc_mcontext = mctx;
93
94                                         info->stopped_domain = mono_mach_arch_get_tls_value_from_thread (t, mono_pthread_key_for_tls (mono_domain_get_tls_key ()));
95                                         info->stopped_ip = (gpointer) mono_mach_arch_get_ip (state);
96                                         stack_start = (char*) mono_mach_arch_get_sp (state) - REDZONE_SIZE;
97                                         /* If stack_start is not within the limits, then don't set it in info and we will be restarted. */
98                                         if (stack_start >= info->stack_start_limit && info->stack_start <= info->stack_end) {
99                                                 info->stack_start = stack_start;
100
101                                                 ARCH_COPY_SIGCTX_REGS (regs, &ctx);
102                                                 info->stopped_regs = regs;
103                                         } else {
104                                                 g_assert (!info->stack_start);
105                                         }
106
107                                         /* Notify the JIT */
108                                         if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
109                                                 mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, &ctx);
110                                 }
111                         } else {
112                                 ret = thread_resume (t);
113                                 if (ret != KERN_SUCCESS) {
114                                         mach_port_deallocate (task, t);
115                                         continue;
116                                 }
117                         }
118                         count ++;
119
120                         mach_port_deallocate (task, t);
121                 } else {
122                         mach_port_deallocate (task, t);
123                 }
124         }
125
126         mono_mach_free_threads (thread_list, num_threads);
127
128         mach_port_deallocate (task, cur_thread);
129
130         return count;
131 }
132 #endif
133 #endif