Implement pthread_setname_np Fixes: #12216
diff --git a/src/library_pthread.js b/src/library_pthread.js index 9d5f833..a406697 100644 --- a/src/library_pthread.js +++ b/src/library_pthread.js
@@ -60,6 +60,9 @@ pthreads: {}, #if ASSERTIONS nextWorkerID: 1, + // This doesn't seem to current do anything in chrome devtools and the + // worker name is instead fixed at worker creation time + setName: (name) => { globalThis.name = name; }, debugInit: function() { function pthreadLogPrefix() { var t = 0; @@ -479,7 +482,7 @@ worker = new Worker(p.createScriptURL('ignored')); } else #endif - worker = new Worker(pthreadMainJs); + worker = new Worker(pthreadMainJs, {name: 'xxx'}); #if EXPORT_ES6 && USE_ES6_IMPORT_META } #endif @@ -889,6 +892,15 @@ #endif }, +#if ASSERTIONS + _emscripten_set_js_thread_name__sig: 'vp', + _emscripten_set_js_thread_name: function(name) { + if (ENVIRONMENT_IS_PTHREAD) { + PThread.setName(UTF8ToString(name)); + } + }, +#endif + __pthread_kill_js__deps: ['emscripten_main_browser_thread_id'], __pthread_kill_js: function(thread, signal) { if (signal === {{{ cDefine('SIGCANCEL') }}}) { // Used by pthread_cancel in musl @@ -1063,6 +1075,9 @@ #if PTHREADS_DEBUG dbg('invokeEntryPoint: ' + ptrToString(ptr)); #endif +#if ASSERTIONS + PThread.setName('pthread worker ' + Module['workerID']); +#endif #if MAIN_MODULE // Before we call the thread entry point, make sure any shared libraries // have been loaded on this there. Otherwise our table migth be not be
diff --git a/system/include/emscripten/threading.h b/system/include/emscripten/threading.h index ed1b29a..6e9a53f 100644 --- a/system/include/emscripten/threading.h +++ b/system/include/emscripten/threading.h
@@ -257,7 +257,7 @@ // The name parameter is a UTF-8 encoded string which is truncated to 32 bytes. // When thread profiler is not enabled (not building with --threadprofiler), // this is a no-op. -void emscripten_set_thread_name(pthread_t threadId, const char *name); +void emscripten_set_thread_name(pthread_t thread, const char *name); // Gets the stored pointer to a string representing the canvases to transfer to // the created thread.
diff --git a/system/lib/libc/crt1_proxy_main.c b/system/lib/libc/crt1_proxy_main.c index 7934aac..c1fb794 100644 --- a/system/lib/libc/crt1_proxy_main.c +++ b/system/lib/libc/crt1_proxy_main.c
@@ -24,7 +24,7 @@ static void* _main_thread(void* param) { // This is the main runtime thread for the application. - emscripten_set_thread_name(pthread_self(), "Application main thread"); + pthread_setname_np(pthread_self(), "Application main thread"); // Will either call user's __main_void or weak version above. int rtn = __main_void(); if (!emscripten_runtime_keepalive_check()) {
diff --git a/system/lib/libc/musl/src/thread/pthread_setname_np.c b/system/lib/libc/musl/src/thread/pthread_setname_np.c index fc2d230..404c6a6 100644 --- a/system/lib/libc/musl/src/thread/pthread_setname_np.c +++ b/system/lib/libc/musl/src/thread/pthread_setname_np.c
@@ -2,12 +2,18 @@ #include <fcntl.h> #include <string.h> #include <unistd.h> +#ifndef __EMSCRIPTEN__ #include <sys/prctl.h> +#endif #include "pthread_impl.h" int pthread_setname_np(pthread_t thread, const char *name) { +#if __EMSCRIPTEN__ + emscripten_set_thread_name(thread, name); + return 0; +#else int fd, cs, status = 0; char f[sizeof "/proc/self/task//comm" + 3*sizeof(int)]; size_t len; @@ -23,4 +29,5 @@ if (fd >= 0) close(fd); pthread_setcancelstate(cs, 0); return status; +#endif }
diff --git a/system/lib/pthread/emscripten_set_thread_name.c b/system/lib/pthread/emscripten_set_thread_name.c new file mode 100644 index 0000000..25c4d24 --- /dev/null +++ b/system/lib/pthread/emscripten_set_thread_name.c
@@ -0,0 +1,38 @@ +/* + * Copyright 2021 The Emscripten Authors. All rights reserved. + * Emscripten is available under two separate licenses, the MIT license and the + * University of Illinois/NCSA Open Source License. Both these licenses can be + * found in the LICENSE file. + */ +#include <string.h> + +#include <emscripten/proxying.h> + +#include "threading_internal.h" +#include "pthread_impl.h" + +#ifndef NDEBUG +// JS function for setting thread name within devtools. +void _emscripten_set_js_thread_name(const char* name); + +static void set_js_thread_name(void* arg) { + const char* name = (const char*)arg; + _emscripten_set_js_thread_name(name); +} +#endif + +void emscripten_set_thread_name(pthread_t thread, const char* name) { + if (thread->profilerBlock) { + strncpy(thread->profilerBlock->name, name, EM_THREAD_NAME_MAX-1); + } +#ifndef NDEBUG + if (thread == pthread_self()) { + _emscripten_set_js_thread_name(name); + } else { + emscripten_proxy_sync(emscripten_proxy_get_system_queue(), + thread, + set_js_thread_name, + (void*)name); + } +#endif +}
diff --git a/system/lib/pthread/thread_profiler.c b/system/lib/pthread/thread_profiler.c index 5598ed0..8f85d24 100644 --- a/system/lib/pthread/thread_profiler.c +++ b/system/lib/pthread/thread_profiler.c
@@ -15,7 +15,6 @@ static bool enabled = false; #ifndef NDEBUG - void _emscripten_thread_profiler_init(pthread_t thread) { assert(thread); if (!enabled) { @@ -61,12 +60,4 @@ _emscripten_thread_profiler_init(pthread_self()); emscripten_set_thread_name(pthread_self(), "Browser main thread"); } - #endif - -void emscripten_set_thread_name(pthread_t thread, const char* name) { - if (!enabled) { - return; - } - strncpy(thread->profilerBlock->name, name, EM_THREAD_NAME_MAX-1); -}
diff --git a/system/lib/pthread/threading_internal.h b/system/lib/pthread/threading_internal.h index 3cf88e9..24151c4 100644 --- a/system/lib/pthread/threading_internal.h +++ b/system/lib/pthread/threading_internal.h
@@ -8,6 +8,7 @@ #pragma once #include <pthread.h> +#include <stdint.h> typedef union em_variant_val { int i;
diff --git a/test/test_browser.py b/test/test_browser.py index 8100ccb..4f1a580 100644 --- a/test/test_browser.py +++ b/test/test_browser.py
@@ -3872,7 +3872,7 @@ def test(args): print(args) self.btest_exit(test_file('pthread/test_pthread_create.cpp'), - args=['-sINITIAL_MEMORY=64MB', '-sUSE_PTHREADS', '-sPTHREAD_POOL_SIZE=8'] + args, + args=['-sINITIAL_MEMORY=64MB', '-sPROXY_TO_PTHREAD', '-sUSE_PTHREADS', '-sPTHREAD_POOL_SIZE=8'] + args, extra_tries=0) # this should be 100% deterministic print() # new line test([])
diff --git a/test/test_other.py b/test/test_other.py index 20cb663..30a643e 100644 --- a/test/test_other.py +++ b/test/test_other.py
@@ -11516,8 +11516,8 @@ @node_pthreads def test_threadprofiler(self): - self.run_process([EMCC, test_file('test_threadprofiler.cpp'), '-sUSE_PTHREADS', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME', '--threadprofiler', '-sASSERTIONS']) - output = self.run_js('a.out.js') + output = self.do_runf(test_file('test_threadprofiler.cpp'), emcc_args=['-sUSE_PTHREADS', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME', '--threadprofiler', '-sASSERTIONS']) + print(output) self.assertRegex(output, r'Thread "Browser main thread" \(0x.*\) now: running.') self.assertRegex(output, r'Thread "Application main thread" \(0x.*\) now: waiting for a futex.') self.assertRegex(output, r'Thread "test worker" \(0x.*\) now: sleeping.')
diff --git a/test/test_threadprofiler.cpp b/test/test_threadprofiler.cpp index bdd8b01..624a807 100644 --- a/test/test_threadprofiler.cpp +++ b/test/test_threadprofiler.cpp
@@ -1,9 +1,8 @@ #include <pthread.h> #include <unistd.h> -#include <emscripten/threading.h> void* worker_thread(void*) { - emscripten_set_thread_name(pthread_self(), "test worker"); + pthread_setname_np(pthread_self(), "test worker"); for (int i = 0; i < 2; i++) { usleep(1000*1000); }
diff --git a/tools/system_libs.py b/tools/system_libs.py index 2bcfeb0..daabd27 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py
@@ -989,8 +989,7 @@ '__unmapself.c', # Empty files, simply ignore them. 'syscall_cp.c', 'tls.c', - # TODO: Support these. See #12216. - 'pthread_setname_np.c', + # TODO: Support this. See #12216. 'pthread_getname_np.c', ] libc_files += files_in_path( @@ -1006,12 +1005,14 @@ 'emscripten_futex_wait.c', 'emscripten_futex_wake.c', 'emscripten_yield.c', + 'thread_profiler.c', ]) else: ignore += ['thread'] libc_files += files_in_path( path='system/lib/libc/musl/src/thread', filenames=[ + 'pthread_setname_np.c', 'pthread_self.c', 'pthread_cleanup_push.c', 'pthread_attr_get.c', @@ -1149,7 +1150,7 @@ libc_files += files_in_path( path='system/lib/pthread', - filenames=['emscripten_atomic.c', 'thread_profiler.c']) + filenames=['emscripten_atomic.c', 'emscripten_set_thread_name.c']) libc_files += glob_in_path('system/lib/libc/compat', '*.c')