diff --git a/CMakeLists.txt b/CMakeLists.txt index deffbc62c..e3dcfd96a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,17 +204,6 @@ add_link_options( -resource-dir ${tmp_resource_dir} ) -if (HAVE_WASM_LIBCALL_THREAD_CONTEXT) - # TODO: shouldn't have to pass these as it means it's required by all end - # users as well. Ideally this would be part of the driver in rustc/clang, but - # that's left for a future change. - add_link_options( - -Wl,--export-if-defined=__wasm_init_tls - -Wl,--export-if-defined=__tls_size - -Wl,--export-if-defined=__tls_align - ) -endif() - # Expose the public headers to the implementation. We use `-isystem` for # purpose for two reasons: # diff --git a/libc-bottom-half/crt/wasip3_symbol_references.h b/libc-bottom-half/crt/wasip3_symbol_references.h index b047054c4..56e21d937 100644 --- a/libc-bottom-half/crt/wasip3_symbol_references.h +++ b/libc-bottom-half/crt/wasip3_symbol_references.h @@ -5,6 +5,7 @@ #ifdef __wasm_libcall_thread_context__ #include +#include // Force some symbols to be linked in for wasip3 extern void __wasm_init_task(void); @@ -15,6 +16,30 @@ __attribute__((used)) static void *__wasm_init_async_task_ref = __wasm_init_async_task; __attribute__((used)) static void *cabi_realloc_ref = cabi_realloc; +// Export a symbol from this object which describes the TLS information +// required for this object. This encapsulates the size/align information as +// well as an initialization function. +// +// Note that being part of `crt1-*.o` this is exported from all libraries, +// which is what we want because each library has a unique return value from +// `__builtin_wasm_tls_*` intrinsics and a separate `__wasm_init_tls` function. +// +// For more information on this see +// https://github.com/WebAssembly/wasi-libc/issues/857 which has since been +// adjusted with this scheme. +static size_t tls_size_and_align(size_t *align) { + *align = __builtin_wasm_tls_align(); + return __builtin_wasm_tls_size(); +} + +void __wasm_init_tls(void *base); + +__attribute__((visibility("default"))) +struct __wasilibc_library_tls_info __wasm_library_tls_info = { + .tls_size_and_align = tls_size_and_align, + .init_tls = __wasm_init_tls, +}; + // Force `__wasm_{g,s}et_{stack_pointer,tls_base}` to exist as defined symbols. // These end up as imported functions which `wit-component` recognizes, and what // exactly they're hooked up to will depend on `wit-component` when this is diff --git a/libc-top-half/headers/private/wasi/wasip3_tls.h b/libc-top-half/headers/private/wasi/wasip3_tls.h index 0e8fd0d70..4dfa04559 100644 --- a/libc-top-half/headers/private/wasi/wasip3_tls.h +++ b/libc-top-half/headers/private/wasi/wasip3_tls.h @@ -13,14 +13,18 @@ #ifdef __wasm_libcall_thread_context__ struct __wasilibc_library_tls_info { - size_t tls_size; - size_t tls_align; + // Stores this library's TLS alignment in `*align` and returns its TLS size. + // + // Note that a library with no thread-local storage at all reports a size of + // zero, but `*align` is always at least 1 so that callers can use it as a + // divisor/mask without special-casing. + size_t (*tls_size_and_align)(size_t *align); void (*init_tls)(void *); }; struct __wasilibc_program_tls_info { size_t num_libraries; - const struct __wasilibc_library_tls_info *library_info; + const struct __wasilibc_library_tls_info **library_info; void **main_thread_tls_base; }; diff --git a/libc-top-half/musl/src/thread/coop-threads/pthread_create.c b/libc-top-half/musl/src/thread/coop-threads/pthread_create.c index 848d7a680..185863bc8 100644 --- a/libc-top-half/musl/src/thread/coop-threads/pthread_create.c +++ b/libc-top-half/musl/src/thread/coop-threads/pthread_create.c @@ -164,10 +164,14 @@ static size_t thread_tls_size(size_t *align) { size_t result_align = _Alignof(void *); for (size_t i = 0; i < info->num_libraries; i++) { - const struct __wasilibc_library_tls_info *library = &info->library_info[i]; - size = align_up(size, library->tls_align) + library->tls_size; - if (library->tls_align > result_align) - result_align = library->tls_align; + const struct __wasilibc_library_tls_info *library = info->library_info[i]; + size_t library_align; + size_t library_size = library->tls_size_and_align(&library_align); + if (library_size == 0) + continue; + size = align_up(size, library_align) + library_size; + if (library_align > result_align) + result_align = library_align; } *align = result_align; @@ -190,10 +194,14 @@ static void *layout_thread_tls(void *block) { void **bases = block; uintptr_t next = (uintptr_t)block + info->num_libraries * sizeof(void *); for (size_t i = 0; i < info->num_libraries; i++) { - const struct __wasilibc_library_tls_info *library = &info->library_info[i]; - next = align_up(next, library->tls_align); + const struct __wasilibc_library_tls_info *library = info->library_info[i]; + size_t library_align; + size_t library_size = library->tls_size_and_align(&library_align); + if (library_size == 0) + continue; + next = align_up(next, library_align); bases[i] = (void *)next; - next += library->tls_size; + next += library_size; } return bases; } @@ -258,7 +266,7 @@ hidden void __wasi_coop_thread_start_C(struct start_args *args) { void **bases = args->tls_layout; size_t num_libraries = info->num_libraries; for (size_t i = 0; i < num_libraries; i++) - info->library_info[i].init_tls(bases[i]); + info->library_info[i]->init_tls(bases[i]); } *__pthread_self() = self_copy; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2634f2598..5c1b1995f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -811,7 +811,6 @@ function(add_posix_test test_file) string(REPLACE "/" "_" test_name ${test_name}) set(test_name "open_posix_test_${test_name}") set(test_file "${CMAKE_CURRENT_SOURCE_DIR}/open-posix-test-suite/${test_file}") - set_source_files_properties(${test_file} PROPERTIES GENERATED TRUE) add_test_pair(${test_name} ${test_file} CFLAGS -Wno-unused-parameter -Wno-unused-variable -Wno-sign-compare -Wno-unused-but-set-global