mirror of
https://git.proxmox.com/git/wasi-libc
synced 2025-08-09 03:26:32 +00:00
Fix races around pthread exit and join (#409)
This commit is contained in:
parent
a6f8713433
commit
aecd368c6d
1
Makefile
1
Makefile
@ -325,6 +325,7 @@ ifeq ($(THREAD_MODEL), posix)
|
|||||||
# Specify the tls-model until LLVM 15 is released (which should contain
|
# Specify the tls-model until LLVM 15 is released (which should contain
|
||||||
# https://reviews.llvm.org/D130053).
|
# https://reviews.llvm.org/D130053).
|
||||||
CFLAGS += -mthread-model posix -pthread -ftls-model=local-exec
|
CFLAGS += -mthread-model posix -pthread -ftls-model=local-exec
|
||||||
|
ASMFLAGS += -matomics
|
||||||
|
|
||||||
# Include cloudlib's directory to access the structure definition of clockid_t
|
# Include cloudlib's directory to access the structure definition of clockid_t
|
||||||
CFLAGS += -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)
|
CFLAGS += -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)
|
||||||
|
@ -164,14 +164,6 @@ static void __pthread_exit(void *result)
|
|||||||
self->prev->next = self->next;
|
self->prev->next = self->next;
|
||||||
self->prev = self->next = self;
|
self->prev = self->next = self;
|
||||||
|
|
||||||
#ifndef __wasilibc_unmodified_upstream
|
|
||||||
/* On Linux, the thread is created with CLONE_CHILD_CLEARTID,
|
|
||||||
* and this lock will unlock by kernel when this thread terminates.
|
|
||||||
* So we should unlock it here in WebAssembly.
|
|
||||||
* See also set_tid_address(2) */
|
|
||||||
__tl_unlock();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __wasilibc_unmodified_upstream
|
#ifdef __wasilibc_unmodified_upstream
|
||||||
if (state==DT_DETACHED && self->map_base) {
|
if (state==DT_DETACHED && self->map_base) {
|
||||||
/* Detached threads must block even implementation-internal
|
/* Detached threads must block even implementation-internal
|
||||||
@ -190,9 +182,6 @@ static void __pthread_exit(void *result)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (state==DT_DETACHED && self->map_base) {
|
if (state==DT_DETACHED && self->map_base) {
|
||||||
// __syscall(SYS_exit) would unlock the thread, list
|
|
||||||
// do it manually here
|
|
||||||
__tl_unlock();
|
|
||||||
free(self->map_base);
|
free(self->map_base);
|
||||||
// Can't use `exit()` here, because it is too high level
|
// Can't use `exit()` here, because it is too high level
|
||||||
return;
|
return;
|
||||||
@ -212,10 +201,15 @@ static void __pthread_exit(void *result)
|
|||||||
#ifdef __wasilibc_unmodified_upstream
|
#ifdef __wasilibc_unmodified_upstream
|
||||||
for (;;) __syscall(SYS_exit, 0);
|
for (;;) __syscall(SYS_exit, 0);
|
||||||
#else
|
#else
|
||||||
// __syscall(SYS_exit) would unlock the thread, list
|
|
||||||
// do it manually here
|
|
||||||
__tl_unlock();
|
|
||||||
// Can't use `exit()` here, because it is too high level
|
// Can't use `exit()` here, because it is too high level
|
||||||
|
|
||||||
|
/* On Linux, the thread is created with CLONE_CHILD_CLEARTID,
|
||||||
|
* and the lock (__thread_list_lock) will be unlocked by kernel when
|
||||||
|
* this thread terminates.
|
||||||
|
* See also set_tid_address(2)
|
||||||
|
*
|
||||||
|
* In WebAssembly, we leave it to wasi_thread_start instead.
|
||||||
|
*/
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,4 +28,21 @@ wasi_thread_start:
|
|||||||
local.get 1 # start_arg
|
local.get 1 # start_arg
|
||||||
call __wasi_thread_start_C
|
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
|
end_function
|
||||||
|
Loading…
Reference in New Issue
Block a user