3 #include <mono/utils/mono-threads.h>
4 #include <mono/utils/mono-mmap.h>
7 #if defined (USE_WASM_BACKEND)
9 #include <mono/utils/mono-threads.h>
10 #include <mono/utils/mono-mmap.h>
12 #include <emscripten.h>
15 #define round_down(addr, val) ((void*)((addr) & ~((val) - 1)))
19 wasm_get_stack_base (void)
21 // Return the bottom limit of the stack
29 wasm_get_stack_size (void)
37 mono_thread_info_get_system_max_stack_size (void)
39 return wasm_get_stack_size ();
44 mono_threads_suspend_init_signals (void)
49 mono_threads_suspend_init (void)
54 mono_threads_suspend_register (MonoThreadInfo
*info
)
59 mono_threads_suspend_begin_async_resume (MonoThreadInfo
*info
)
65 mono_threads_suspend_free (MonoThreadInfo
*info
)
70 mono_threads_suspend_begin_async_suspend (MonoThreadInfo
*info
, gboolean interrupt_kernel
)
76 mono_threads_suspend_check_suspend_result (MonoThreadInfo
*info
)
82 mono_threads_suspend_abort_syscall (MonoThreadInfo
*info
)
87 mono_native_thread_id_equals (MonoNativeThreadId id1
, MonoNativeThreadId id2
)
94 mono_native_thread_id_get (void)
96 #ifdef __EMSCRIPTEN_PTHREADS__
97 return pthread_self ();
99 return (MonoNativeThreadId
)1;
104 mono_native_thread_os_id_get (void)
106 #ifdef __EMSCRIPTEN_PTHREADS__
107 return (guint64
)pthread_self ();
114 mono_native_thread_create (MonoNativeThreadId
*tid
, gpointer func
, gpointer arg
)
116 g_error ("WASM doesn't support threading");
119 static const char *thread_name
;
122 mono_native_thread_set_name (MonoNativeThreadId tid
, const char *name
)
124 thread_name
= g_strdup (name
);
128 mono_native_thread_join (MonoNativeThreadId tid
)
130 #ifdef __EMSCRIPTEN_PTHREADS__
133 return !pthread_join (tid
, &res
);
135 g_assert_not_reached ();
140 mono_threads_platform_yield (void)
146 mono_threads_platform_get_stack_bounds (guint8
**staddr
, size_t *stsize
)
148 #ifdef __EMSCRIPTEN_PTHREADS__
154 *stsize
= (size_t)-1;
156 res
= pthread_attr_init (&attr
);
157 if (G_UNLIKELY (res
!= 0))
158 g_error ("%s: pthread_attr_init failed with \"%s\" (%d)", __func__
, g_strerror (res
), res
);
160 res
= pthread_getattr_np (pthread_self (), &attr
);
161 if (G_UNLIKELY (res
!= 0))
162 g_error ("%s: pthread_getattr_np failed with \"%s\" (%d)", __func__
, g_strerror (res
), res
);
164 res
= pthread_attr_getstack (&attr
, (void**)staddr
, stsize
);
165 if (G_UNLIKELY (res
!= 0))
166 g_error ("%s: pthread_attr_getstack failed with \"%s\" (%d)", __func__
, g_strerror (res
), res
);
168 res
= pthread_attr_destroy (&attr
);
169 if (G_UNLIKELY (res
!= 0))
170 g_error ("%s: pthread_attr_destroy failed with \"%s\" (%d)", __func__
, g_strerror (res
), res
);
172 if (*staddr
== NULL
) {
173 *staddr
= (guint8
*)wasm_get_stack_base ();
174 *stsize
= wasm_get_stack_size ();
177 g_assert (&tmp
> *staddr
);
178 g_assert (&tmp
< (char*)*staddr
+ *stsize
);
180 *staddr
= (guint8
*)wasm_get_stack_base ();
181 *stsize
= wasm_get_stack_size ();
186 mono_thread_platform_create_thread (MonoThreadStart thread_fn
, gpointer thread_data
, gsize
* const stack_size
, MonoNativeThreadId
*tid
)
188 #ifdef __EMSCRIPTEN_PTHREADS__
192 gsize set_stack_size
;
194 res
= pthread_attr_init (&attr
);
196 g_error ("%s: pthread_attr_init failed, error: \"%s\" (%d)", __func__
, g_strerror (res
), res
);
200 set_stack_size
= *stack_size
;
204 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
205 if (set_stack_size
== 0) {
206 #if HAVE_VALGRIND_MEMCHECK_H
207 if (RUNNING_ON_VALGRIND
)
208 set_stack_size
= 1 << 20;
210 set_stack_size
= (SIZEOF_VOID_P
/ 4) * 1024 * 1024;
212 set_stack_size
= (SIZEOF_VOID_P
/ 4) * 1024 * 1024;
216 #ifdef PTHREAD_STACK_MIN
217 if (set_stack_size
< PTHREAD_STACK_MIN
)
218 set_stack_size
= PTHREAD_STACK_MIN
;
221 res
= pthread_attr_setstacksize (&attr
, set_stack_size
);
223 g_error ("%s: pthread_attr_setstacksize failed, error: \"%s\" (%d)", __func__
, g_strerror (res
), res
);
224 #endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
227 /* Actually start the thread */
228 res
= pthread_create (&thread
, &attr
, (gpointer (*)(gpointer
)) thread_fn
, thread_data
);
230 res
= pthread_attr_destroy (&attr
);
232 g_error ("%s: pthread_attr_destroy failed, error: \"%s\" (%d)", __func__
, g_strerror (res
), res
);
242 res
= pthread_attr_getstacksize (&attr
, stack_size
);
244 g_error ("%s: pthread_attr_getstacksize failed, error: \"%s\" (%d)", __func__
, g_strerror (res
), res
);
248 res
= pthread_attr_destroy (&attr
);
250 g_error ("%s: pthread_attr_destroy failed, error: \"%s\" (%d)", __func__
, g_strerror (res
), res
);
254 g_assert_not_reached ();
258 void mono_threads_platform_init (void)
263 mono_threads_platform_exit (gsize exit_code
)
265 #ifdef __EMSCRIPTEN_PTHREADS__
266 pthread_exit ((gpointer
) exit_code
);
268 g_assert_not_reached ();
273 mono_threads_platform_in_critical_region (THREAD_INFO_TYPE
*info
)
279 extern void schedule_background_exec (void);
284 mono_threads_schedule_background_job (background_job_cb cb
)
287 schedule_background_exec ();
289 if (!g_slist_find (jobs
, (gconstpointer
)cb
))
290 jobs
= g_slist_prepend (jobs
, (gpointer
)cb
);
294 EMSCRIPTEN_KEEPALIVE
void
295 mono_background_exec (void)
297 GSList
*j
= jobs
, *cur
;
300 for (cur
= j
; cur
; cur
= cur
->next
) {
301 background_job_cb cb
= (background_job_cb
)cur
->data
;
308 mono_memory_barrier_process_wide (void)