Skip to content

Commit 316a8f8

Browse files
authored
Enable stdio locking under Wasm Workers (#26489)
This change removes the use of `pthread_self` from musl's internal file locking mechanism, while enabled libc's internal threading state in once the first worker is started. The test changed here come from #18201 This is needed as part of my effort to remove all pthread symbols from the Wasm Workers builds.
1 parent b4696ac commit 316a8f8

File tree

14 files changed

+167
-70
lines changed

14 files changed

+167
-70
lines changed

system/lib/libc/emscripten_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
* for `tools/gen_sig_info.py` to work. This file contains declarations for
1111
* functions that are not declared in any other public or private header.
1212
*/
13+
#ifndef __EMSCRIPTEN_INTERNAL_H__
14+
#define __EMSCRIPTEN_INTERNAL_H__
1315

1416
#include <emscripten/em_macros.h>
1517
#include <emscripten/proxying.h>
@@ -148,3 +150,5 @@ int _poll_js(void* fds, int nfds, int timeout, void* ctx, void* arg);
148150
#ifdef __cplusplus
149151
}
150152
#endif
153+
154+
#endif /* __EMSCRIPTEN_INTERNAL_H__ */

system/lib/libc/musl/src/internal/pthread_impl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,4 +275,13 @@ extern hidden unsigned __default_guardsize;
275275

276276
#define __ATTRP_C11_THREAD ((void*)(uintptr_t)-1)
277277

278+
#ifdef __EMSCRIPTEN_SHARED_MEMORY__
279+
pid_t gettid(void);
280+
// Unlike `__pthread_self()->tid, `gettid` works under both wasm workers and
281+
// pthreads.
282+
#define CURRENT_THREAD_ID gettid()
283+
#else
284+
#define CURRENT_THREAD_ID __pthread_self()->tid
285+
#endif
286+
278287
#endif

system/lib/libc/musl/src/internal/stdio_impl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#define UNGET 8
88

9-
#if defined(__EMSCRIPTEN__) && !defined(_REENTRANT)
9+
#if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_SHARED_MEMORY__)
1010
#define FFINALLOCK(f)
1111
#define FLOCK(f)
1212
#define FUNLOCK(f)

system/lib/libc/musl/src/linux/gettid.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
#include <unistd.h>
33
#include "pthread_impl.h"
44

5-
#ifdef __EMSCRIPTEN_WASM_WORKERS__
6-
#include <emscripten/wasm_worker.h>
7-
#elif defined(__EMSCRIPTEN_PTHREADS__)
5+
#ifdef __EMSCRIPTEN__
86
weak int emscripten_wasm_worker_self_id();
97
#endif
108

@@ -16,7 +14,14 @@ pid_t gettid(void)
1614
{
1715
#ifdef __EMSCRIPTEN_WASM_WORKERS__
1816
// Offset the worker ID by 1 so we never return 0 from this function.
19-
return emscripten_wasm_worker_self_id() + 1;
17+
// Strangly we cannot assume the existence of emscripten_wasm_worker_self_id
18+
// here because libc-ww is also used for `-sSHARED_MEMORY` builds (without
19+
// libwasm_workers linked in.
20+
if (emscripten_wasm_worker_self_id) {
21+
return emscripten_wasm_worker_self_id() + 1;
22+
} else {
23+
return 42;
24+
}
2025
#else
2126
#if defined(__EMSCRIPTEN_PTHREADS__)
2227
// The pthread-variant of libc can also be used alongside wasm workers.

system/lib/libc/musl/src/stdio/__lockfile.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
int __lockfile(FILE *f)
55
{
6-
#if defined(__EMSCRIPTEN_PTHREADS__)
7-
int owner = f->lock, tid = __pthread_self()->tid;
6+
#ifdef __EMSCRIPTEN_SHARED_MEMORY__
7+
int owner = f->lock, tid = CURRENT_THREAD_ID;
88
if ((owner & ~MAYBE_WAITERS) == tid)
99
return 0;
1010
owner = a_cas(&f->lock, 0, tid);
@@ -20,7 +20,7 @@ int __lockfile(FILE *f)
2020

2121
void __unlockfile(FILE *f)
2222
{
23-
#if defined(__EMSCRIPTEN_PTHREADS__)
23+
#ifdef __EMSCRIPTEN_SHARED_MEMORY__
2424
if (a_swap(&f->lock, 0) & MAYBE_WAITERS)
2525
__wake(&f->lock, 1, 1);
2626
#endif

system/lib/libc/musl/src/stdio/getc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ static int locking_getc(FILE *f)
1616
static inline int do_getc(FILE *f)
1717
{
1818
int l = f->lock;
19-
if (l < 0 || l && (l & ~MAYBE_WAITERS) == __pthread_self()->tid)
19+
if (l < 0 || l && (l & ~MAYBE_WAITERS) == CURRENT_THREAD_ID)
2020
return getc_unlocked(f);
2121
return locking_getc(f);
2222
}

system/lib/libc/musl/src/stdio/putc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ static int locking_putc(int c, FILE *f)
1616
static inline int do_putc(int c, FILE *f)
1717
{
1818
int l = f->lock;
19-
if (l < 0 || l && (l & ~MAYBE_WAITERS) == __pthread_self()->tid)
19+
if (l < 0 || l && (l & ~MAYBE_WAITERS) == CURRENT_THREAD_ID)
2020
return putc_unlocked(c, f);
2121
return locking_putc(c, f);
2222
}

system/lib/wasm_worker/library_wasm_worker.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
/*
2+
* Copyright 2022 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
// libc files are compiled as -std=c99 which doesn't normally declare
9+
// max_align_t.
10+
#if __STDC_VERSION__ < 201112L
11+
#define __NEED_max_align_t
12+
#endif
13+
14+
#include "libc.h"
15+
#include "stdio_impl.h"
16+
#include "emscripten_internal.h"
17+
118
#include <assert.h>
219
#include <emscripten/wasm_worker.h>
320
#include <emscripten/threading.h>
@@ -7,8 +24,6 @@
724
#include <malloc.h>
825
#include <sys/param.h> // For MAX()
926

10-
#include "emscripten_internal.h"
11-
1227
#ifndef __EMSCRIPTEN_WASM_WORKERS__
1328
#error __EMSCRIPTEN_WASM_WORKERS__ should be defined when building this file!
1429
#endif
@@ -33,6 +48,15 @@ static void emscripten_wasm_worker_main_thread_initialize() {
3348
*sbrk_ptr += ROUND_UP(__builtin_wasm_tls_size(), SBRK_ALIGN);
3449
}
3550

51+
static FILE *volatile dummy_file = 0;
52+
weak_alias(dummy_file, __stdin_used);
53+
weak_alias(dummy_file, __stdout_used);
54+
weak_alias(dummy_file, __stderr_used);
55+
56+
static void init_file_lock(FILE *f) {
57+
if (f && f->lock<0) f->lock = 0;
58+
}
59+
3660
emscripten_wasm_worker_t emscripten_create_wasm_worker(void *stackPlusTLSAddress, size_t stackPlusTLSSize) {
3761
assert(stackPlusTLSAddress != 0);
3862
assert((uintptr_t)stackPlusTLSAddress % STACK_ALIGN == 0);
@@ -61,6 +85,22 @@ emscripten_wasm_worker_t emscripten_create_wasm_worker(void *stackPlusTLSAddress
6185
stackPlusTLSAddress = (void*)tlsBase;
6286
stackPlusTLSSize -= padding;
6387
}
88+
89+
if (!libc.threaded) {
90+
for (FILE *f=*__ofl_lock(); f; f=f->next) {
91+
init_file_lock(f);
92+
}
93+
__ofl_unlock();
94+
init_file_lock(__stdin_used);
95+
init_file_lock(__stdout_used);
96+
init_file_lock(__stderr_used);
97+
libc.threaded = 1;
98+
}
99+
100+
// Unlike with ptheads, wasm workers never really exit and so this counter
101+
// only going one way here.
102+
if (!libc.threads_minus_1++) libc.need_locks = 1;
103+
64104
return _emscripten_create_wasm_worker(stackPlusTLSAddress, stackPlusTLSSize);
65105
}
66106

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,80 @@
1-
var c = Module, d = "em-ww" == globalThis.name, e, f, y, z, l, A, t;
1+
var c = Module, d = "em-ww" == globalThis.name, e = !!globalThis.WorkerGlobalScope, f, g, C, r, D, n, E, w;
22

33
d && (onmessage = a => {
44
onmessage = null;
5-
e = a = a.data;
6-
f = a.l;
7-
g();
8-
c ||= {};
9-
c.wasm = a.j;
5+
f = a = a.data;
6+
g = a.o;
107
h();
11-
a.j = a.l = 0;
8+
c ||= {};
9+
c.wasm = a.m;
10+
k();
11+
a.m = a.o = 0;
1212
});
1313

14-
function g() {}
14+
function h() {}
1515

16-
d || (f = c.mem || new WebAssembly.Memory({
16+
d || (g = c.mem || new WebAssembly.Memory({
1717
initial: 256,
1818
maximum: 256,
1919
shared: !0
20-
}), g());
20+
}), h());
2121

22-
var k = [], n = a => {
22+
var l = [], p = a => {
2323
a = a.data;
2424
let b = a._wsc;
25-
b && l.get(b)(...a.x);
26-
}, p = a => {
27-
k.push(a);
28-
}, q = {}, r = 1, u = (a, b) => {
29-
let m = q[r] = new Worker(c.js, {
25+
b && n.get(b)(...a.x);
26+
}, q = a => {
27+
l.push(a);
28+
}, t = () => {
29+
r(0, !e, !d, e && 1);
30+
}, u = {}, v = 1, x = (a, b) => {
31+
let m = u[v] = new Worker(c.js, {
3032
name: "em-ww"
3133
});
3234
m.postMessage({
33-
s: r,
34-
j: t,
35-
l: f,
36-
m: a,
37-
o: b
35+
v: v,
36+
m: w,
37+
o: g,
38+
s: a,
39+
u: b
3840
});
39-
m.onmessage = n;
40-
return r++;
41-
}, v = () => !1, w = (a, b) => {
42-
q[a].postMessage({
41+
m.onmessage = p;
42+
return v++;
43+
}, y = () => performance.now(), z = () => !1, A = (a, b) => {
44+
u[a].postMessage({
4345
_wsc: b,
4446
x: []
4547
});
4648
};
4749

48-
d && (q[0] = globalThis, addEventListener("message", p));
50+
d && (u[0] = globalThis, addEventListener("message", q));
4951

50-
function x() {
52+
function B() {
5153
console.log("Hello from wasm worker!");
5254
}
5355

54-
function h() {
55-
A = {
56-
b: u,
57-
c: v,
58-
d: w,
59-
e: x,
60-
a: f
56+
function k() {
57+
E = {
58+
e: t,
59+
c: x,
60+
b: y,
61+
d: z,
62+
f: A,
63+
g: B,
64+
a: g
6165
};
6266
WebAssembly.instantiate(c.wasm, {
63-
a: A
67+
a: E
6468
}).then((a => {
6569
var b = (a.instance || a).exports;
66-
t = a.module || c.wasm;
67-
y = b.g;
68-
z = b.i;
69-
l = b.h;
70-
d ? (z(e.s, e.m, e.o), removeEventListener("message", p), k = k.forEach(n), addEventListener("message", n)) : b.f();
71-
d || y();
70+
w = a.module || c.wasm;
71+
C = b.i;
72+
r = b.k;
73+
D = b.l;
74+
n = b.j;
75+
d ? (D(f.v, f.s, f.u), removeEventListener("message", q), l = l.forEach(p), addEventListener("message", p)) : b.h();
76+
d || C();
7277
}));
7378
}
7479

75-
d || h();
80+
d || k();
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"a.html": 515,
33
"a.html.gz": 355,
4-
"a.js": 859,
5-
"a.js.gz": 545,
6-
"a.wasm": 1847,
7-
"a.wasm.gz": 1071,
8-
"total": 3221,
9-
"total_gz": 1971
4+
"a.js": 956,
5+
"a.js.gz": 605,
6+
"a.wasm": 2744,
7+
"a.wasm.gz": 1530,
8+
"total": 4215,
9+
"total_gz": 2490
1010
}

0 commit comments

Comments
 (0)