From 09c8871a3c2cf844feea8dc1eaa14431c82ba66b Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 27 Jul 2021 21:54:09 -0700 Subject: [PATCH] Move most of `Pthread.initRuntime` into native code. NFC This also avoids the use of malloc both for the main pthread struct and for its TLS vars. This in turn avoids the use of `withBuiltinMalloc` since we no longer use malloc here. --- emcc.py | 1 - src/library_pthread.js | 46 ++----------------- .../musl/src/thread/pthread_getspecific.c | 4 ++ system/lib/pthread/library_pthread.c | 26 ++++++----- ...n_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.exports | 1 - ...ain_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.funcs | 1 - ...main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.size | 2 +- 7 files changed, 25 insertions(+), 56 deletions(-) diff --git a/emcc.py b/emcc.py index cd8be9dc44f2e..eacb7a2e56d2e 100755 --- a/emcc.py +++ b/emcc.py @@ -1863,7 +1863,6 @@ def default_setting(name, new_default): '_emscripten_get_global_libc', '_emscripten_main_browser_thread_id', '_emscripten_main_thread_process_queued_calls', - '_emscripten_register_main_browser_thread_id', '_emscripten_run_in_main_runtime_thread_js', '_emscripten_stack_set_limits', '_emscripten_sync_run_in_main_thread_2', diff --git a/src/library_pthread.js b/src/library_pthread.js index dc947c5932729..5929a021411a2 100644 --- a/src/library_pthread.js +++ b/src/library_pthread.js @@ -7,12 +7,8 @@ var LibraryPThread = { $PThread__postset: 'if (!ENVIRONMENT_IS_PTHREAD) PThread.initMainThreadBlock();', $PThread__deps: ['_emscripten_thread_init', - 'emscripten_register_main_browser_thread_id', 'emscripten_futex_wake', '$killThread', '$cancelThread', '$cleanupThread', -#if USE_ASAN || USE_LSAN - , '$withBuiltinMalloc' -#endif ], $PThread: { // Contains all Workers that are idle/unused and not currently hosting an @@ -37,33 +33,7 @@ var LibraryPThread = { } #endif }, - initRuntime: function() { -#if USE_ASAN || USE_LSAN - // When sanitizers are enabled, malloc is normally instrumented to call - // sanitizer code that checks some things about pthreads. As we are just - // setting up the main thread here, and are not ready for such calls, - // call malloc directly. - withBuiltinMalloc(function () { -#endif - - var tb = _malloc({{{ C_STRUCTS.pthread.__size__ }}}); - - for (var i = 0; i < {{{ C_STRUCTS.pthread.__size__ }}}/4; ++i) HEAPU32[tb/4+i] = 0; - - // The pthread struct has a field that points to itself - this is used as - // a magic ID to detect whether the pthread_t structure is 'alive'. - {{{ makeSetValue('tb', C_STRUCTS.pthread.self, 'tb', 'i32') }}}; - - // pthread struct robust_list head should point to itself. - var headPtr = tb + {{{ C_STRUCTS.pthread.robust_list }}}; - {{{ makeSetValue('headPtr', 0, 'headPtr', 'i32') }}}; - - // Allocate memory for thread-local storage. - var tlsMemory = _malloc({{{ cDefine('PTHREAD_KEYS_MAX') * 4 }}}); - for (var i = 0; i < {{{ cDefine('PTHREAD_KEYS_MAX') }}}; ++i) HEAPU32[tlsMemory/4+i] = 0; - Atomics.store(HEAPU32, (tb + {{{ C_STRUCTS.pthread.tsd }}} ) >> 2, tlsMemory); // Init thread-local-storage memory array. - Atomics.store(HEAPU32, (tb + {{{ C_STRUCTS.pthread.tid }}} ) >> 2, tb); // Main thread ID. - + initRuntime: function(tb) { #if PTHREADS_PROFILING PThread.createProfilerBlock(tb); PThread.setThreadName(tb, "Browser main thread"); @@ -74,14 +44,9 @@ var LibraryPThread = { // globals which act as a form of TLS. Global constructors trying // to access this value will read the wrong value, but that is UB anyway. __emscripten_thread_init(tb, /*isMainBrowserThread=*/!ENVIRONMENT_IS_WORKER, /*isMainRuntimeThread=*/1); - _emscripten_register_main_browser_thread_id(tb); #if ASSERTIONS PThread.mainRuntimeThread = true; #endif - -#if USE_ASAN || USE_LSAN - }); -#endif }, initWorker: function() { #if USE_CLOSURE_COMPILER @@ -568,6 +533,7 @@ var LibraryPThread = { pthread.worker.postMessage({ 'cmd': 'cancel' }); }, + $spawnThread__deps: ['$zeroMemory'], $spawnThread: function(threadParams) { if (ENVIRONMENT_IS_PTHREAD) throw 'Internal Error! spawnThread() can only ever be called from main application thread!'; @@ -582,10 +548,8 @@ var LibraryPThread = { PThread.runningWorkers.push(worker); // Allocate memory for thread-local storage and initialize it to zero. - var tlsMemory = _malloc({{{ cDefine('PTHREAD_KEYS_MAX') }}} * 4); - for (var i = 0; i < {{{ cDefine('PTHREAD_KEYS_MAX') }}}; ++i) { - {{{ makeSetValue('tlsMemory', 'i*4', 0, 'i32') }}}; - } + var tlsMemory = _malloc({{{ cDefine('PTHREAD_KEYS_MAX') * 4 }}}); + zeroMemory(tlsMemory, {{{ cDefine('PTHREAD_KEYS_MAX') * 4 }}}); var stackHigh = threadParams.stackBase + threadParams.stackSize; @@ -822,7 +786,7 @@ var LibraryPThread = { // Allocate thread block (pthread_t structure). var threadInfoStruct = _malloc({{{ C_STRUCTS.pthread.__size__ }}}); // zero-initialize thread structure. - for (var i = 0; i < {{{ C_STRUCTS.pthread.__size__ }}} >> 2; ++i) HEAPU32[(threadInfoStruct>>2) + i] = 0; + zeroMemory(threadInfoStruct, {{{ C_STRUCTS.pthread.__size__ }}}); {{{ makeSetValue('pthread_ptr', 0, 'threadInfoStruct', 'i32') }}}; // The pthread struct has a field that points to itself - this is used as a diff --git a/system/lib/libc/musl/src/thread/pthread_getspecific.c b/system/lib/libc/musl/src/thread/pthread_getspecific.c index d9342a560f7bc..f3772630530e7 100644 --- a/system/lib/libc/musl/src/thread/pthread_getspecific.c +++ b/system/lib/libc/musl/src/thread/pthread_getspecific.c @@ -4,6 +4,10 @@ static void *__pthread_getspecific(pthread_key_t k) { struct pthread *self = __pthread_self(); + // XXX EMSCRIPTEN: self->tsd can be NULL in the case of the + // main thread where pthread_key_create is not called. + // See __pthread_key_create for where it get assigned. + if (!self->tsd) return NULL; return self->tsd[k]; } diff --git a/system/lib/pthread/library_pthread.c b/system/lib/pthread/library_pthread.c index 257725caa5bde..4f972d4dfcab5 100644 --- a/system/lib/pthread/library_pthread.c +++ b/system/lib/pthread/library_pthread.c @@ -405,15 +405,10 @@ EMSCRIPTEN_RESULT emscripten_wait_for_call_i( return res; } -static pthread_t main_browser_thread_id_ = 0; - -void emscripten_register_main_browser_thread_id( - pthread_t main_browser_thread_id) { - main_browser_thread_id_ = main_browser_thread_id; -} +static struct pthread __main_pthread; pthread_t emscripten_main_browser_thread_id() { - return main_browser_thread_id_; + return &__main_pthread; } int _emscripten_do_dispatch_to_thread(pthread_t target_thread, em_queued_call* call) { @@ -886,8 +881,8 @@ int _emscripten_call_on_thread(int forceAsync, pthread_t targetThread, EM_FUNC_S // the main thread is waiting, we wake it up before waking up any workers. EMSCRIPTEN_KEEPALIVE void* _emscripten_main_thread_futex; -EM_JS(void, initPthreadsJS, (void), { - PThread.initRuntime(); +EM_JS(void, initPthreadsJS, (void* tb), { + PThread.initRuntime(tb); }) // We must initialize the runtime at the proper time, which is after memory is @@ -898,6 +893,15 @@ EM_JS(void, initPthreadsJS, (void), { EMSCRIPTEN_KEEPALIVE __attribute__((constructor(48))) void __emscripten_pthread_data_constructor(void) { - initPthreadsJS(); - pthread_self()->locale = &libc.global_locale; + initPthreadsJS(&__main_pthread); + // The pthread struct has a field that points to itself - this is used as + // a magic ID to detect whether the pthread_t structure is 'alive'. + __main_pthread.self = &__main_pthread; + // pthread struct robust_list head should point to itself. + __main_pthread.robust_list.head = &__main_pthread.robust_list; + + // Main thread ID. + __main_pthread.tid = (long)&__main_pthread; + + __main_pthread.locale = &libc.global_locale; } diff --git a/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.exports b/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.exports index 3cd9efe94acd6..2b1bb838e7092 100644 --- a/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.exports +++ b/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.exports @@ -14,7 +14,6 @@ M N O P -Q t u v diff --git a/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.funcs b/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.funcs index 5c6cd47a4d51d..a61ce92d54b5b 100644 --- a/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.funcs +++ b/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.funcs @@ -31,7 +31,6 @@ $emscripten_current_thread_process_queued_calls $emscripten_get_global_libc $emscripten_main_thread_process_queued_calls $emscripten_proxy_main -$emscripten_register_main_browser_thread_id $emscripten_run_in_main_runtime_thread_js $emscripten_stack_set_limits $emscripten_sync_run_in_main_thread diff --git a/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.size b/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.size index a56cc82625d30..d19c15c03a1ac 100644 --- a/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.size +++ b/tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.size @@ -1 +1 @@ -16031 +16084