[Sockets]: Always reset internal SAEA completion when reattempting connection in...
[mono-project.git] / mono / mini / tasklets.c
blob361b3f02353fa11fc5c9413099c61175333ef9c4
1 /**
2 * \file
3 */
5 #include "config.h"
6 #include "tasklets.h"
7 #include "mono/metadata/exception.h"
8 #include "mono/metadata/gc-internals.h"
9 #include "mono/metadata/icall-internals.h"
10 #include "mini.h"
11 #include "mini-runtime.h"
12 #include "mono/metadata/loader-internals.h"
13 #include "mono/utils/mono-tls-inline.h"
15 #if defined(MONO_SUPPORT_TASKLETS)
17 #include "mono/metadata/loader-internals.h"
19 static mono_mutex_t tasklets_mutex;
20 #define tasklets_lock() mono_os_mutex_lock(&tasklets_mutex)
21 #define tasklets_unlock() mono_os_mutex_unlock(&tasklets_mutex)
23 /* LOCKING: tasklets_mutex is assumed to e taken */
24 static void
25 internal_init (void)
27 if (!mono_gc_is_moving ())
28 /* Boehm requires the keepalive stacks to be kept in a hash since mono_gc_alloc_fixed () returns GC memory */
29 g_assert_not_reached ();
32 static void*
33 continuation_alloc (void)
35 MonoContinuation *cont = g_new0 (MonoContinuation, 1);
36 return cont;
39 static void
40 continuation_free (MonoContinuation *cont)
42 if (cont->saved_stack)
43 mono_gc_free_fixed (cont->saved_stack);
44 g_free (cont);
47 static MonoException*
48 continuation_mark_frame (MonoContinuation *cont)
50 MonoJitTlsData *jit_tls;
51 MonoLMF *lmf;
52 MonoContext ctx, new_ctx;
53 MonoJitInfo *ji, rji;
54 int endloop = FALSE;
56 if (cont->domain)
57 return mono_get_exception_argument ("cont", "Already marked");
59 jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
60 lmf = mono_get_lmf();
61 cont->domain = mono_domain_get ();
62 cont->thread_id = mono_native_thread_id_get ();
64 /* get to the frame that called Mark () */
65 memset (&rji, 0, sizeof (rji));
66 memset (&ctx, 0, sizeof (ctx));
67 do {
68 ji = mono_find_jit_info (cont->domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
69 if (!ji || ji == (gpointer)-1) {
70 return mono_get_exception_not_supported ("Invalid stack frame");
72 ctx = new_ctx;
73 if (endloop)
74 break;
75 if (!ji->is_trampoline && strcmp (jinfo_get_method (ji)->name, "Mark") == 0)
76 endloop = TRUE;
77 } while (1);
79 cont->top_sp = MONO_CONTEXT_GET_SP (&ctx);
80 /*g_print ("method: %s, sp: %p\n", jinfo_get_method (ji)->name, cont->top_sp);*/
82 return NULL;
85 static int
86 continuation_store (MonoContinuation *cont, int state, MonoException **e)
88 MonoLMF *lmf = mono_get_lmf ();
89 gsize num_bytes;
91 if (!cont->domain) {
92 *e = mono_get_exception_argument ("cont", "Continuation not initialized");
93 return 0;
95 if (cont->domain != mono_domain_get () || !mono_native_thread_id_equals (cont->thread_id, mono_native_thread_id_get ())) {
96 *e = mono_get_exception_argument ("cont", "Continuation from another thread or domain");
97 return 0;
100 cont->lmf = lmf;
101 cont->return_ip = __builtin_extract_return_addr (__builtin_return_address (0));
102 cont->return_sp = __builtin_frame_address (0);
104 num_bytes = (char*)cont->top_sp - (char*)cont->return_sp;
106 /*g_print ("store: %d bytes, sp: %p, ip: %p, lmf: %p\n", num_bytes, cont->return_sp, cont->return_ip, lmf);*/
108 if (cont->saved_stack && num_bytes <= cont->stack_alloc_size) {
109 /* clear to avoid GC retention */
110 if (num_bytes < cont->stack_used_size) {
111 memset ((char*)cont->saved_stack + num_bytes, 0, cont->stack_used_size - num_bytes);
113 cont->stack_used_size = num_bytes;
114 } else {
115 tasklets_lock ();
116 internal_init ();
117 if (cont->saved_stack)
118 mono_gc_free_fixed (cont->saved_stack);
119 cont->stack_used_size = num_bytes;
120 cont->stack_alloc_size = num_bytes * 1.1;
121 cont->saved_stack = mono_gc_alloc_fixed_no_descriptor (cont->stack_alloc_size, MONO_ROOT_SOURCE_THREADING, NULL, "Tasklet Saved Stack");
122 tasklets_unlock ();
124 memcpy (cont->saved_stack, cont->return_sp, num_bytes);
126 return state;
129 static MonoException*
130 continuation_restore (MonoContinuation *cont, int state)
132 MonoLMF **lmf_addr = mono_get_lmf_addr ();
133 MonoContinuationRestore restore_state = mono_tasklets_arch_restore ();
135 if (!cont->domain || !cont->return_sp)
136 return mono_get_exception_argument ("cont", "Continuation not initialized");
137 if (cont->domain != mono_domain_get () || !mono_native_thread_id_equals (cont->thread_id, mono_native_thread_id_get ()))
138 return mono_get_exception_argument ("cont", "Continuation from another thread or domain");
140 /*g_print ("restore: %p, state: %d\n", cont, state);*/
141 *lmf_addr = cont->lmf;
142 restore_state (cont, state, lmf_addr);
143 g_assert_not_reached ();
146 void
147 mono_tasklets_init (void)
149 mono_os_mutex_init_recursive (&tasklets_mutex);
151 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::alloc", continuation_alloc);
152 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::free", continuation_free);
153 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::mark", continuation_mark_frame);
154 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::store", continuation_store);
155 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::restore", continuation_restore);
158 void
159 mono_tasklets_cleanup (void)
162 #else
164 static
165 void continuations_not_supported (void)
167 ERROR_DECL (error);
168 mono_error_set_not_implemented (error, "Tasklets are not implemented on this platform.");
169 mono_error_set_pending_exception (error);
172 static void*
173 continuation_alloc (void)
175 continuations_not_supported ();
176 return NULL;
179 static void
180 continuation_free (MonoContinuation *cont)
182 continuations_not_supported ();
185 static MonoException*
186 continuation_mark_frame (MonoContinuation *cont)
188 continuations_not_supported ();
189 return NULL;
192 static int
193 continuation_store (MonoContinuation *cont, int state, MonoException **e)
195 continuations_not_supported ();
196 return 0;
199 static MonoException*
200 continuation_restore (MonoContinuation *cont, int state)
202 continuations_not_supported ();
203 return NULL;
206 void
207 mono_tasklets_init(void)
209 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::alloc", continuation_alloc);
210 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::free", continuation_free);
211 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::mark", continuation_mark_frame);
212 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::store", continuation_store);
213 mono_add_internal_call_internal ("Mono.Tasklets.Continuation::restore", continuation_restore);
216 #endif