Skip to content

Commit 1ac2418

Browse files
authored
Use pthread_join from musl (#15604)
1 parent 0c07c15 commit 1ac2418

File tree

4 files changed

+48
-80
lines changed

4 files changed

+48
-80
lines changed

system/lib/libc/musl/src/thread/pthread_join.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,75 @@ static void dummy1(pthread_t t)
77
}
88
weak_alias(dummy1, __tl_sync);
99

10+
#ifdef __EMSCRIPTEN__ // XXX Emscripten add extern for __emscripten_thread_cleanup
11+
extern void __emscripten_thread_cleanup(pthread_t thread);
12+
#endif
13+
1014
static int __pthread_timedjoin_np(pthread_t t, void **res, const struct timespec *at)
1115
{
16+
#ifdef __EMSCRIPTEN__
17+
// Attempt to join a thread which does not point to a valid thread, or
18+
// does not exist anymore.
19+
if (t->self != t) return ESRCH;
20+
// Thread is attempting to join to itself. Already detached threads are
21+
// handled below by returning EINVAL instead.
22+
// TODO: The detached check here is just to satisfy the `other.test_{proxy,main}_pthread_join_detach` tests.
23+
if (t->detach_state != DT_DETACHED && __pthread_self() == t) return EDEADLK;
24+
#endif
1225
int state, cs, r = 0;
1326
__pthread_testcancel();
1427
__pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
1528
if (cs == PTHREAD_CANCEL_ENABLE) __pthread_setcancelstate(cs, 0);
1629
while ((state = t->detach_state) && r != ETIMEDOUT && r != EINVAL) {
30+
#ifdef __EMSCRIPTEN__
31+
// The thread is (already) detached and therefore not joinable.
32+
// This also handle cases where the thread becomes detached
33+
// *during* the join.
34+
if (state >= DT_DETACHED) {
35+
// Even though the man page says this is undefined
36+
// behaviour we ave several tests in the posixtest suite
37+
// that depend on this.
38+
r = EINVAL;
39+
break;
40+
}
41+
#else
1742
if (state >= DT_DETACHED) a_crash();
43+
#endif
1844
r = __timedwait_cp(&t->detach_state, state, CLOCK_REALTIME, at, 1);
1945
}
2046
__pthread_setcancelstate(cs, 0);
2147
if (r == ETIMEDOUT || r == EINVAL) return r;
2248
__tl_sync(t);
2349
if (res) *res = t->result;
50+
#ifdef __EMSCRIPTEN__
51+
// Thread was exited during this call, be sure to clean it up.
52+
if (state == DT_EXITED) __emscripten_thread_cleanup(t);
53+
#else // XXX Emscripten map_base unused
2454
if (t->map_base) __munmap(t->map_base, t->map_size);
55+
#endif
2556
return 0;
2657
}
2758

2859
int __pthread_join(pthread_t t, void **res)
2960
{
61+
#ifdef __EMSCRIPTEN__ // XXX Emscripten check whether blocking is allowed.
62+
emscripten_check_blocking_allowed();
63+
#endif
3064
return __pthread_timedjoin_np(t, res, 0);
3165
}
3266

3367
static int __pthread_tryjoin_np(pthread_t t, void **res)
3468
{
69+
#ifdef __EMSCRIPTEN__ // XXX Emscripten call __pthread_timedjoin_np directly to avoid additional check
70+
return t->detach_state==DT_JOINABLE ? EBUSY : __pthread_timedjoin_np(t, res, 0);
71+
#else
3572
return t->detach_state==DT_JOINABLE ? EBUSY : __pthread_join(t, res);
73+
#endif
3674
}
3775

3876
weak_alias(__pthread_tryjoin_np, pthread_tryjoin_np);
3977
weak_alias(__pthread_timedjoin_np, pthread_timedjoin_np);
4078
weak_alias(__pthread_join, pthread_join);
79+
#ifdef __EMSCRIPTEN__ // XXX Emscripten add an extra alias for LSan
80+
weak_alias(__pthread_join, emscripten_builtin_pthread_join);
81+
#endif

system/lib/pthread/pthread_create.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -247,16 +247,14 @@ void _emscripten_thread_exit(void* result) {
247247
* call; the loser is responsible for freeing thread resources. */
248248
int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);
249249

250-
// Mark the thread as no longer running.
251-
// When we publish this, the main thread is free to deallocate the thread
252-
// object and we are done.
253250
if (state == DT_DETACHED) {
254-
self->detach_state = DT_EXITED;
255251
__emscripten_thread_cleanup(self);
256252
} else {
257-
self->detach_state = DT_EXITING;
258-
// wake any threads that might be waiting for us to exit
259-
emscripten_futex_wake(&self->detach_state, INT_MAX);
253+
// Mark the thread as no longer running, so it can be joined.
254+
// Once we publish this, any threads that are waiting to join with us can
255+
// proceed and this worker can be recycled and used on another thread.
256+
a_store(&self->detach_state, DT_EXITED);
257+
__wake(&self->detach_state, 1, 1); // Wake any joiner.
260258
}
261259
}
262260

system/lib/pthread/pthread_join.c

Lines changed: 0 additions & 70 deletions
This file was deleted.

tools/system_libs.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -827,15 +827,14 @@ def get_files(self):
827827
'syscall_cp.c', 'tls.c',
828828
# TODO: Support this. See #12216.
829829
'pthread_setname_np.c',
830-
# TODO: These could be moved away from JS in the upcoming musl upgrade.
831-
'pthread_join.c', 'pthread_testcancel.c',
830+
# TODO: Prefer to use the musl implementation.
831+
'pthread_testcancel.c',
832832
]
833833
libc_files += files_in_path(
834834
path='system/lib/pthread',
835835
filenames=[
836836
'library_pthread.c',
837837
'pthread_create.c',
838-
'pthread_join.c',
839838
'pthread_testcancel.c',
840839
'emscripten_proxy_main.c',
841840
'emscripten_thread_init.c',

0 commit comments

Comments
 (0)