diff --git a/system/lib/libcxx/include/__locale b/system/lib/libcxx/include/__locale index 757a53951f66e..3dbb55ef20af4 100644 --- a/system/lib/libcxx/include/__locale +++ b/system/lib/libcxx/include/__locale @@ -146,7 +146,9 @@ private: }; class _LIBCPP_EXPORTED_FROM_ABI locale::id { +#if !defined(__EMSCRIPTEN__) || !defined(__EMSCRIPTEN_WASM_WORKERS__) once_flag __flag_; +#endif int32_t __id_; static int32_t __next_id; diff --git a/system/lib/libcxx/src/locale.cpp b/system/lib/libcxx/src/locale.cpp index da735865c322c..c4b5383889161 100644 --- a/system/lib/libcxx/src/locale.cpp +++ b/system/lib/libcxx/src/locale.cpp @@ -589,7 +589,24 @@ void locale::facet::__on_zero_shared() noexcept { delete this; } constinit int32_t locale::id::__next_id = 0; long locale::id::__get() { +#if defined(__EMSCRIPTEN__) && defined(__EMSCRIPTEN_WASM_WORKERS__) + // Avoid `call_once` under Emscripten since we want to avoid the pthread + // dependenency that it comes with. + // TODO(https://github.com/emscripten-core/emscripten/issues/26426): + // Remove this patch once we have some kind of locking primitive + // in Wasm Worker that can be used to implement call_once (or + // __libcpp_mutex_t/__libcpp_condvar_t). + if (__libcpp_atomic_load(&__id_) == 0) { + int32_t proposed_id = __libcpp_atomic_add(&__next_id, 1); + int32_t expected = 0; + // If we race with another thread here the CAS will fail and + // the proposed_id will be leaked, but __id_ will be non-zero + // in either case. + __libcpp_atomic_compare_exchange(&__id_, &expected, proposed_id); + } +#else call_once(__flag_, [&] { __id_ = __libcpp_atomic_add(&__next_id, 1); }); +#endif return __id_ - 1; } diff --git a/test/codesize/hello_libcxx.cpp b/test/codesize/hello_libcxx.cpp index dfe21e184e8ec..8275e0fee6305 100644 --- a/test/codesize/hello_libcxx.cpp +++ b/test/codesize/hello_libcxx.cpp @@ -9,4 +9,3 @@ int main() { std::cout << "hello, world!" << std::endl; return 0; } - diff --git a/test/test_other.py b/test/test_other.py index 7ba92eb07b506..f15f227bef075 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -13537,6 +13537,9 @@ def test_wasm_worker_pthread_api_usage(self): def test_wasm_worker_cxx_init(self): self.do_run_in_out_file_test('wasm_worker/wasm_worker_cxx_init.cpp', cflags=['-sWASM_WORKERS']) + def test_wasm_worker_hello_libcxx(self): + self.do_runf('codesize/hello_libcxx.cpp', 'hello, world!\n', cflags=['-sWASM_WORKERS']) + @parameterized({ # we will warn here since -O2 runs the optimizer and -g enables DWARF 'O2_g': (True, ['-O2', '-g']),