diff options
Diffstat (limited to 'libc-top-half/musl/src/thread')
6 files changed, 82 insertions, 17 deletions
diff --git a/libc-top-half/musl/src/thread/__wait.c b/libc-top-half/musl/src/thread/__wait.c index c0e4aac..7ffa987 100644 --- a/libc-top-half/musl/src/thread/__wait.c +++ b/libc-top-half/musl/src/thread/__wait.c @@ -48,7 +48,7 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv) __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS || __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); #else - __wasilibc_futex_wait(addr, FUTEX_WAIT, val, 0); + __wasilibc_futex_wait(addr, FUTEX_WAIT, val, -1); #endif } if (waiters) a_dec(waiters); diff --git a/libc-top-half/musl/src/thread/pthread_attr_get.c b/libc-top-half/musl/src/thread/pthread_attr_get.c index f12ff44..0ac251c 100644 --- a/libc-top-half/musl/src/thread/pthread_attr_get.c +++ b/libc-top-half/musl/src/thread/pthread_attr_get.c @@ -17,6 +17,7 @@ int pthread_attr_getinheritsched(const pthread_attr_t *restrict a, int *restrict return 0; } +#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */ int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict param) { param->sched_priority = a->_a_prio; @@ -28,6 +29,7 @@ int pthread_attr_getschedpolicy(const pthread_attr_t *restrict a, int *restrict *policy = a->_a_policy; return 0; } +#endif int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict scope) { @@ -56,11 +58,13 @@ int pthread_barrierattr_getpshared(const pthread_barrierattr_t *restrict a, int return 0; } +#ifdef __wasilibc_unmodified_upstream /* Forward declaration of WASI's `__clockid` type. */ int pthread_condattr_getclock(const pthread_condattr_t *restrict a, clockid_t *restrict clk) { *clk = a->__attr & 0x7fffffff; return 0; } +#endif int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restrict pshared) { diff --git a/libc-top-half/musl/src/thread/pthread_barrier_destroy.c b/libc-top-half/musl/src/thread/pthread_barrier_destroy.c index 4ce0b2e..a347a2c 100644 --- a/libc-top-half/musl/src/thread/pthread_barrier_destroy.c +++ b/libc-top-half/musl/src/thread/pthread_barrier_destroy.c @@ -9,7 +9,9 @@ int pthread_barrier_destroy(pthread_barrier_t *b) while ((v = b->_b_lock) & INT_MAX) __wait(&b->_b_lock, 0, v, 0); } +#ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */ __vm_wait(); +#endif } return 0; } diff --git a/libc-top-half/musl/src/thread/pthread_barrier_wait.c b/libc-top-half/musl/src/thread/pthread_barrier_wait.c index cc2a8bb..0891b71 100644 --- a/libc-top-half/musl/src/thread/pthread_barrier_wait.c +++ b/libc-top-half/musl/src/thread/pthread_barrier_wait.c @@ -23,7 +23,9 @@ static int pshared_barrier_wait(pthread_barrier_t *b) __wait(&b->_b_count, &b->_b_waiters2, v, 0); } +#ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */ __vm_lock(); +#endif /* Ensure all threads have a vm lock before proceeding */ if (a_fetch_add(&b->_b_count, -1)==1-limit) { @@ -44,7 +46,9 @@ static int pshared_barrier_wait(pthread_barrier_t *b) if (v==INT_MIN+1 || (v==1 && w)) __wake(&b->_b_lock, 1, 0); +#ifdef __wasilibc_unmodified_upstream /* WASI does not understand processes or locking between them. */ __vm_unlock(); +#endif return ret; } @@ -84,8 +88,12 @@ int pthread_barrier_wait(pthread_barrier_t *b) a_spin(); a_inc(&inst->finished); while (inst->finished == 1) +#ifdef __wasilibc_unmodified_upstream __syscall(SYS_futex,&inst->finished,FUTEX_WAIT|FUTEX_PRIVATE,1,0) != -ENOSYS || __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0); +#else + __futexwait(&inst->finished, 1, 0); +#endif return PTHREAD_BARRIER_SERIAL_THREAD; } diff --git a/libc-top-half/musl/src/thread/pthread_create.c b/libc-top-half/musl/src/thread/pthread_create.c index 1aa7be7..676e2cc 100644 --- a/libc-top-half/musl/src/thread/pthread_create.c +++ b/libc-top-half/musl/src/thread/pthread_create.c @@ -60,7 +60,11 @@ void __tl_sync(pthread_t td) if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0); } +#ifdef __wasilibc_unmodified_upstream _Noreturn void __pthread_exit(void *result) +#else +static void __pthread_exit(void *result) +#endif { pthread_t self = __pthread_self(); sigset_t set; @@ -191,7 +195,7 @@ _Noreturn void __pthread_exit(void *result) __tl_unlock(); free(self->map_base); // Can't use `exit()` here, because it is too high level - for (;;) __wasi_proc_exit(0); + return; } #endif @@ -212,7 +216,6 @@ _Noreturn void __pthread_exit(void *result) // do it manually here __tl_unlock(); // Can't use `exit()` here, because it is too high level - for (;;) __wasi_proc_exit(0); #endif } @@ -235,9 +238,14 @@ struct start_args { volatile int control; unsigned long sig_mask[_NSIG/8/sizeof(long)]; #else + /* + * Note: the offset of the "stack" and "tls_base" members + * in this structure is hardcoded in wasi_thread_start. + */ + void *stack; + void *tls_base; void *(*start_func)(void *); void *start_arg; - void *tls_base; #endif }; @@ -271,32 +279,41 @@ static int start_c11(void *p) return 0; } #else -__attribute__((export_name("wasi_thread_start"))) -_Noreturn void wasi_thread_start(int tid, void *p) + +/* + * We want to ensure wasi_thread_start is linked whenever + * pthread_create is used. The following reference is to ensure that. + * Otherwise, the linker doesn't notice the dependency because + * wasi_thread_start is used indirectly via a wasm export. + */ +void wasi_thread_start(int tid, void *p); +hidden void *__dummy_reference = wasi_thread_start; + +hidden void __wasi_thread_start_C(int tid, void *p) { struct start_args *args = p; - __asm__(".globaltype __tls_base, i32\n" - "local.get %0\n" - "global.set __tls_base\n" - :: "r"(args->tls_base)); pthread_t self = __pthread_self(); // Set the thread ID (TID) on the pthread structure. The TID is stored // atomically since it is also stored by the parent thread; this way, // whichever thread (parent or child) reaches this point first can proceed // without waiting. atomic_store((atomic_int *) &(self->tid), tid); - // Set the stack pointer. - __asm__(".globaltype __stack_pointer, i32\n" - "local.get %0\n" - "global.set __stack_pointer\n" - :: "r"(self->stack)); // Execute the user's start function. - int (*start)(void*) = (int(*)(void*)) args->start_func; - __pthread_exit((void *)(uintptr_t)start(args->start_arg)); + __pthread_exit(args->start_func(args->start_arg)); } #endif +#ifdef __wasilibc_unmodified_upstream #define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE) +#else +/* + * As we allocate stack with malloc() instead of mmap/mprotect, + * there is no point to round it up to PAGE_SIZE. + * Instead, round up to a sane alignment. + * Note: PAGE_SIZE is rather big on WASM. (65536) + */ +#define ROUND(x) (((x)+16-1)&-16) +#endif /* pthread_key_create.c overrides this */ static volatile size_t dummy = 0; @@ -484,6 +501,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att /* Correct the stack size */ new->stack_size = stack - stack_limit; + args->stack = new->stack; /* just for convenience of asm trampoline */ args->start_func = entry; args->start_arg = arg; args->tls_base = (void*)new_tls_base; @@ -561,5 +579,7 @@ fail: return EAGAIN; } +#ifdef __wasilibc_unmodified_upstream weak_alias(__pthread_exit, pthread_exit); +#endif weak_alias(__pthread_create, pthread_create); diff --git a/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s b/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s new file mode 100644 index 0000000..0fe9854 --- /dev/null +++ b/libc-top-half/musl/src/thread/wasm32/wasi_thread_start.s @@ -0,0 +1,31 @@ + .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 + + end_function |