Changes GC.cs
[mono-project.git] / mono / utils / mono-threads-wasm.c
blob212d7413a948c96fefe445205d02f57f74561edc
1 #include "config.h"
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>
13 #include <glib.h>
15 #define round_down(addr, val) ((void*)((addr) & ~((val) - 1)))
17 EMSCRIPTEN_KEEPALIVE
18 static int
19 wasm_get_stack_base (void)
21 // Return the bottom limit of the stack
22 return EM_ASM_INT ({
23 return STACK_MAX;
24 });
27 EMSCRIPTEN_KEEPALIVE
28 static int
29 wasm_get_stack_size (void)
31 return EM_ASM_INT ({
32 return TOTAL_STACK;
33 });
36 int
37 mono_thread_info_get_system_max_stack_size (void)
39 return wasm_get_stack_size ();
43 void
44 mono_threads_suspend_init_signals (void)
48 void
49 mono_threads_suspend_init (void)
53 void
54 mono_threads_suspend_register (MonoThreadInfo *info)
58 gboolean
59 mono_threads_suspend_begin_async_resume (MonoThreadInfo *info)
61 return TRUE;
64 void
65 mono_threads_suspend_free (MonoThreadInfo *info)
69 gboolean
70 mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
72 return TRUE;
75 gboolean
76 mono_threads_suspend_check_suspend_result (MonoThreadInfo *info)
78 return TRUE;
81 void
82 mono_threads_suspend_abort_syscall (MonoThreadInfo *info)
86 gboolean
87 mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
89 return id1 == id2;
93 MonoNativeThreadId
94 mono_native_thread_id_get (void)
96 #ifdef __EMSCRIPTEN_PTHREADS__
97 return pthread_self ();
98 #else
99 return (MonoNativeThreadId)1;
100 #endif
103 guint64
104 mono_native_thread_os_id_get (void)
106 #ifdef __EMSCRIPTEN_PTHREADS__
107 return (guint64)pthread_self ();
108 #else
109 return 1;
110 #endif
113 MONO_API gboolean
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;
121 void
122 mono_native_thread_set_name (MonoNativeThreadId tid, const char *name)
124 thread_name = g_strdup (name);
127 gboolean
128 mono_native_thread_join (MonoNativeThreadId tid)
130 #ifdef __EMSCRIPTEN_PTHREADS__
131 void *res;
133 return !pthread_join (tid, &res);
134 #else
135 g_assert_not_reached ();
136 #endif
139 gboolean
140 mono_threads_platform_yield (void)
142 return TRUE;
145 void
146 mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize)
148 #ifdef __EMSCRIPTEN_PTHREADS__
149 pthread_attr_t attr;
150 gint res;
151 int tmp;
153 *staddr = NULL;
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);
179 #else
180 *staddr = (guint8*)wasm_get_stack_base ();
181 *stsize = wasm_get_stack_size ();
182 #endif
185 gboolean
186 mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *tid)
188 #ifdef __EMSCRIPTEN_PTHREADS__
189 pthread_attr_t attr;
190 pthread_t thread;
191 gint res;
192 gsize set_stack_size;
194 res = pthread_attr_init (&attr);
195 if (res != 0)
196 g_error ("%s: pthread_attr_init failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
198 #if 0
199 if (stack_size)
200 set_stack_size = *stack_size;
201 else
202 set_stack_size = 0;
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;
209 else
210 set_stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024;
211 #else
212 set_stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024;
213 #endif
216 #ifdef PTHREAD_STACK_MIN
217 if (set_stack_size < PTHREAD_STACK_MIN)
218 set_stack_size = PTHREAD_STACK_MIN;
219 #endif
221 res = pthread_attr_setstacksize (&attr, set_stack_size);
222 if (res != 0)
223 g_error ("%s: pthread_attr_setstacksize failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
224 #endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
225 #endif
227 /* Actually start the thread */
228 res = pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data);
229 if (res) {
230 res = pthread_attr_destroy (&attr);
231 if (res != 0)
232 g_error ("%s: pthread_attr_destroy failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
234 return FALSE;
237 if (tid)
238 *tid = thread;
240 #if 0
241 if (stack_size) {
242 res = pthread_attr_getstacksize (&attr, stack_size);
243 if (res != 0)
244 g_error ("%s: pthread_attr_getstacksize failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
246 #endif
248 res = pthread_attr_destroy (&attr);
249 if (res != 0)
250 g_error ("%s: pthread_attr_destroy failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
252 return TRUE;
253 #else
254 g_assert_not_reached ();
255 #endif
258 void mono_threads_platform_init (void)
262 void
263 mono_threads_platform_exit (gsize exit_code)
265 #ifdef __EMSCRIPTEN_PTHREADS__
266 pthread_exit ((gpointer) exit_code);
267 #else
268 g_assert_not_reached ();
269 #endif
272 gboolean
273 mono_threads_platform_in_critical_region (THREAD_INFO_TYPE *info)
275 return FALSE;
278 G_EXTERN_C
279 extern void schedule_background_exec (void);
281 static GSList *jobs;
283 void
284 mono_threads_schedule_background_job (background_job_cb cb)
286 if (!jobs)
287 schedule_background_exec ();
289 if (!g_slist_find (jobs, (gconstpointer)cb))
290 jobs = g_slist_prepend (jobs, (gpointer)cb);
293 G_EXTERN_C
294 EMSCRIPTEN_KEEPALIVE void
295 mono_background_exec (void)
297 GSList *j = jobs, *cur;
298 jobs = NULL;
300 for (cur = j; cur; cur = cur->next) {
301 background_job_cb cb = (background_job_cb)cur->data;
302 cb ();
304 g_slist_free (j);
307 void
308 mono_memory_barrier_process_wide (void)
312 #endif