Skip to content

Commit a68e258

Browse files
committed
Replace call_once usage in libc++ with atomics
This avoid a dependency on pthread API (which are used to implement call_once under the hood) which makes libc++ much more usable from Wasm Workers (there pthreads are not available). The downside here is that when thread race to be first one to use a given facet we would "leak" an ID which could cause the `facets_` vector to become more spare that it otherwise would be. IIUC this `facets_` vector can already be sparse so it not clear to me what impact this would have in practice. We could make this change only for the Wasm Workers build of libc++ but I'd like to get as much test coverage of it as I can. See: #26375
1 parent a699999 commit a68e258

13 files changed

+58
-39
lines changed

system/lib/libcxx/include/__locale

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,9 @@ private:
146146
};
147147

148148
class _LIBCPP_EXPORTED_FROM_ABI locale::id {
149+
#ifndef __EMSCRIPTEN__
149150
once_flag __flag_;
151+
#endif
150152
int32_t __id_;
151153

152154
static int32_t __next_id;

system/lib/libcxx/src/locale.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,23 @@ void locale::facet::__on_zero_shared() noexcept { delete this; }
589589
constinit int32_t locale::id::__next_id = 0;
590590

591591
long locale::id::__get() {
592+
#ifdef __EMSCRIPTEN__
593+
// Avoid `call_once` under Emscripten since we want to avoid the pthread
594+
// dependenency that it comes with.
595+
// TODO(sbc): Remove this patch once we have some kind of locking primitive
596+
// in Wasm Worker that can be used to implement call_once (or
597+
// __libcpp_mutex_t/__libcpp_condvar_t).
598+
if (__libcpp_atomic_load(&__id_) == 0) {
599+
int32_t proposed_id = __libcpp_atomic_add(&__next_id, 1);
600+
int32_t expected = 0;
601+
// If we race with another thread here the CAS will fail and
602+
// the proposed_id will be leaked, but __id_ will be non-zero
603+
// in either case.
604+
__libcpp_atomic_compare_exchange(&__id_, &expected, proposed_id);
605+
}
606+
#else
592607
call_once(__flag_, [&] { __id_ = __libcpp_atomic_add(&__next_id, 1); });
608+
#endif
593609
return __id_ - 1;
594610
}
595611

test/codesize/hello_libcxx.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,3 @@ int main() {
99
std::cout << "hello, world!" << std::endl;
1010
return 0;
1111
}
12-

test/codesize/test_codesize_cxx_ctors1.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"a.out.js": 19214,
33
"a.out.js.gz": 7982,
4-
"a.out.nodebug.wasm": 132865,
5-
"a.out.nodebug.wasm.gz": 49889,
6-
"total": 152079,
7-
"total_gz": 57871,
4+
"a.out.nodebug.wasm": 132617,
5+
"a.out.nodebug.wasm.gz": 49801,
6+
"total": 151831,
7+
"total_gz": 57783,
88
"sent": [
99
"__cxa_throw",
1010
"_abort_js",

test/codesize/test_codesize_cxx_ctors2.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"a.out.js": 19191,
33
"a.out.js.gz": 7968,
4-
"a.out.nodebug.wasm": 132285,
5-
"a.out.nodebug.wasm.gz": 49542,
6-
"total": 151476,
7-
"total_gz": 57510,
4+
"a.out.nodebug.wasm": 132036,
5+
"a.out.nodebug.wasm.gz": 49456,
6+
"total": 151227,
7+
"total_gz": 57424,
88
"sent": [
99
"__cxa_throw",
1010
"_abort_js",

test/codesize/test_codesize_cxx_except.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"a.out.js": 22875,
33
"a.out.js.gz": 8959,
4-
"a.out.nodebug.wasm": 172743,
5-
"a.out.nodebug.wasm.gz": 57374,
6-
"total": 195618,
7-
"total_gz": 66333,
4+
"a.out.nodebug.wasm": 173885,
5+
"a.out.nodebug.wasm.gz": 57439,
6+
"total": 196760,
7+
"total_gz": 66398,
88
"sent": [
99
"__cxa_begin_catch",
1010
"__cxa_end_catch",

test/codesize/test_codesize_cxx_except_wasm.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"a.out.js": 19025,
33
"a.out.js.gz": 7906,
4-
"a.out.nodebug.wasm": 148138,
5-
"a.out.nodebug.wasm.gz": 55261,
6-
"total": 167163,
7-
"total_gz": 63167,
4+
"a.out.nodebug.wasm": 149501,
5+
"a.out.nodebug.wasm.gz": 55425,
6+
"total": 168526,
7+
"total_gz": 63331,
88
"sent": [
99
"_abort_js",
1010
"_tzset_js",

test/codesize/test_codesize_cxx_except_wasm_legacy.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"a.out.js": 19099,
33
"a.out.js.gz": 7926,
4-
"a.out.nodebug.wasm": 145944,
5-
"a.out.nodebug.wasm.gz": 54887,
6-
"total": 165043,
7-
"total_gz": 62813,
4+
"a.out.nodebug.wasm": 147317,
5+
"a.out.nodebug.wasm.gz": 55080,
6+
"total": 166416,
7+
"total_gz": 63006,
88
"sent": [
99
"_abort_js",
1010
"_tzset_js",

test/codesize/test_codesize_cxx_lto.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"a.out.js": 18562,
33
"a.out.js.gz": 7670,
4-
"a.out.nodebug.wasm": 102126,
5-
"a.out.nodebug.wasm.gz": 39426,
6-
"total": 120688,
7-
"total_gz": 47096,
4+
"a.out.nodebug.wasm": 104147,
5+
"a.out.nodebug.wasm.gz": 39808,
6+
"total": 122709,
7+
"total_gz": 47478,
88
"sent": [
99
"a (emscripten_resize_heap)",
1010
"b (_setitimer_js)",

test/codesize/test_codesize_cxx_mangle.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"a.out.js": 22925,
33
"a.out.js.gz": 8978,
4-
"a.out.nodebug.wasm": 239177,
5-
"a.out.nodebug.wasm.gz": 79774,
6-
"total": 262102,
7-
"total_gz": 88752,
4+
"a.out.nodebug.wasm": 240319,
5+
"a.out.nodebug.wasm.gz": 79859,
6+
"total": 263244,
7+
"total_gz": 88837,
88
"sent": [
99
"__cxa_begin_catch",
1010
"__cxa_end_catch",

0 commit comments

Comments
 (0)