-
Notifications
You must be signed in to change notification settings - Fork 199
/
wasi_thread_start.s
48 lines (39 loc) · 1.3 KB
/
wasi_thread_start.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
.text
.export_name wasi_thread_start, wasi_thread_start
.globaltype __stack_pointer, i32
.globaltype __tls_base, i32
.functype __wasi_thread_start_C (i32, i32) -> ()
.hidden wasi_thread_start
.globl wasi_thread_start
.type wasi_thread_start,@function
wasi_thread_start:
.functype wasi_thread_start (i32, i32) -> ()
# Set up the minimum C environment.
# Note: offsetof(start_arg, stack) == 0
local.get 1 # start_arg
i32.load 0 # stack
global.set __stack_pointer
local.get 1 # start_arg
i32.load 4 # tls_base
global.set __tls_base
# Make the C function do the rest of work.
local.get 0 # tid
local.get 1 # start_arg
call __wasi_thread_start_C
# Unlock thread list. (as CLONE_CHILD_CLEARTID would do for Linux)
#
# Note: once we unlock the thread list, our "map_base" can be freed
# by a joining thread. It's safe as we are in ASM and no longer use
# our C stack or pthread_t. It's impossible to do this safely in C
# because there is no way to tell the C compiler not to use C stack.
i32.const __thread_list_lock
i32.const 0
i32.atomic.store 0
# As an optimization, we can check tl_lock_waiters here.
# But for now, simply wake up unconditionally as
# CLONE_CHILD_CLEARTID does.
i32.const __thread_list_lock
i32.const 1
memory.atomic.notify 0
drop
end_function