Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions system/lib/pthread/pthread_create.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

static void dummy_0() {}
weak_alias(dummy_0, __pthread_tsd_run_dtors);
weak_alias(dummy_0, __do_orphaned_stdio_locks);
weak_alias(dummy_0, __dl_thread_cleanup);

static void __run_cleanup_handlers() {
pthread_t self = __pthread_self();
Expand Down Expand Up @@ -312,6 +314,16 @@ void _emscripten_thread_exit(void* result) {
// Call into the musl function that runs destructors of all thread-specific data.
__pthread_tsd_run_dtors();

// If this is the main runtime thread, don't proceed with
// termination of the thread, but prepare for exit to call
// atexit handlers.
if (emscripten_is_main_runtime_thread()) {
exit(0);
}

/* At this point we are committed to thread termination. */

/* The thread list lock must be AS-safe. */
__tl_lock();

/* Process robust list in userspace to handle non-pshared mutexes
Expand All @@ -333,24 +345,23 @@ void _emscripten_thread_exit(void* result) {
}
__vm_unlock();

if (!--libc.threads_minus_1) libc.need_locks = 0;
__do_orphaned_stdio_locks();
__dl_thread_cleanup();

/* Last, unlink thread from the list. This change will not be visible
* until the lock is released via __tl_unlock() below. */
if (!--libc.threads_minus_1) libc.need_locks = 0;
self->next->prev = self->prev;
self->prev->next = self->next;
self->prev = self->next = self;

__tl_unlock();

if (emscripten_is_main_runtime_thread()) {
exit(0);
return;
}

// Not hosting a pthread anymore in this worker set __pthread_self to NULL
__set_thread_state(NULL, 0, 0, 1);

// This atomic potentially competes with a concurrent pthread_detach
// call; the loser is responsible for freeing thread resources.
/* This atomic potentially competes with a concurrent pthread_detach
* call; the loser is responsible for freeing thread resources. */
int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);

if (state == DT_DETACHED) {
Expand All @@ -363,8 +374,10 @@ void _emscripten_thread_exit(void* result) {
// When dynamic linking is enabled we need to keep track of zombie threads
_emscripten_thread_exit_joinable(self);
#endif

/* Wake any joiner. */
a_store(&self->detach_state, DT_EXITED);
__wake(&self->detach_state, 1, 1); // Wake any joiner.
__wake(&self->detach_state, 1, 1);
}
}

Expand Down
4 changes: 2 additions & 2 deletions test/codesize/test_codesize_minimal_pthreads.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"a.out.js": 7367,
"a.out.js.gz": 3587,
"a.out.nodebug.wasm": 19037,
"a.out.nodebug.wasm.gz": 8786,
"a.out.nodebug.wasm.gz": 8787,
"total": 26404,
"total_gz": 12373,
"total_gz": 12374,
"sent": [
"a (memory)",
"b (exit)",
Expand Down
4 changes: 2 additions & 2 deletions test/codesize/test_codesize_minimal_pthreads_memgrowth.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"a.out.js": 7776,
"a.out.js.gz": 3791,
"a.out.nodebug.wasm": 19038,
"a.out.nodebug.wasm.gz": 8787,
"a.out.nodebug.wasm.gz": 8788,
"total": 26814,
"total_gz": 12578,
"total_gz": 12579,
"sent": [
"a (memory)",
"b (exit)",
Expand Down
Loading