From 34142fd3788cf6ce3dacf351dde461017a0bf472 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Thu, 19 Nov 2020 18:40:06 -0800 Subject: [PATCH] Move pthread TLS state native code using wasm globals This moves pthead_self and other thread state into native code. --- emcc.py | 3 +- src/deps_info.json | 2 ++ src/library_pthread.js | 52 ++++--------------------------- src/postamble_minimal.js | 4 +-- src/worker.js | 2 +- system/lib/pthread/pthread_self.s | 39 +++++++++++++++++++++++ tools/system_libs.py | 1 + 7 files changed, 53 insertions(+), 50 deletions(-) create mode 100644 system/lib/pthread/pthread_self.s diff --git a/emcc.py b/emcc.py index 4ae4374dabc95..6f61f9cdda7ed 100755 --- a/emcc.py +++ b/emcc.py @@ -1577,9 +1577,10 @@ def filter_out_duplicate_dynamic_libs(inputs): # manually export them shared.Settings.EXPORTED_FUNCTIONS += [ + '__emscripten_thread_init', '_emscripten_get_global_libc', '___pthread_tsd_run_dtors', - 'registerPthreadPtr', '_pthread_self', + '_pthread_self', '___emscripten_pthread_data_constructor', '_emscripten_futex_wake', '_emscripten_stack_set_limits', diff --git a/src/deps_info.json b/src/deps_info.json index 219e6e06bf762..074f747f84aa4 100644 --- a/src/deps_info.json +++ b/src/deps_info.json @@ -179,6 +179,8 @@ "emscripten_webgl_get_shader_source_utf8": ["malloc", "free"], "emscripten_webgl_get_parameter_utf8": ["malloc", "free"], "emscripten_webgl_create_context": ["malloc", "free"], + "emscripten_start_fetch": ["emscripten_is_main_browser_thread"], + "emscripten_fetch": ["emscripten_is_main_browser_thread"], "glMapBufferRange": ["malloc", "free"], "glGetString": ["malloc", "free"], "glGetStringi": ["malloc", "free"], diff --git a/src/library_pthread.js b/src/library_pthread.js index 044c92a04c38d..4e121f1b088a6 100644 --- a/src/library_pthread.js +++ b/src/library_pthread.js @@ -6,7 +6,7 @@ var LibraryPThread = { $PThread__postset: 'if (!ENVIRONMENT_IS_PTHREAD) PThread.initMainThreadBlock();', - $PThread__deps: ['$registerPthreadPtr', + $PThread__deps: ['_emscripten_thread_init', '$ERRNO_CODES', 'emscripten_futex_wake', '$killThread', '$cancelThread', '$cleanupThread', #if USE_ASAN || USE_LSAN @@ -81,10 +81,10 @@ var LibraryPThread = { }); #endif - // Pass the thread address inside the asm.js scope to store it for fast - // access that avoids the need for a FFI out. Global constructors trying + // Pass the thread address to the native code where they stored in wasm + // 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. - registerPthreadPtr(PThread.mainThreadBlock, /*isMainBrowserThread=*/!ENVIRONMENT_IS_WORKER, /*isMainRuntimeThread=*/1); + __emscripten_thread_init(PThread.mainThreadBlock, /*isMainBrowserThread=*/!ENVIRONMENT_IS_WORKER, /*isMainRuntimeThread=*/1); _emscripten_register_main_browser_thread_id(PThread.mainThreadBlock); }, initWorker: function() { @@ -218,7 +218,7 @@ var LibraryPThread = { PThread.runExitHandlers(); _emscripten_futex_wake(tb + {{{ C_STRUCTS.pthread.threadStatus }}}, {{{ cDefine('INT_MAX') }}}); - registerPthreadPtr(0, 0, 0); // Unregister the thread block also inside the asm.js scope. + __emscripten_thread_init(0, 0, 0); // Unregister the thread block also inside the asm.js scope. threadInfoStruct = 0; if (ENVIRONMENT_IS_PTHREAD) { // Note: in theory we would like to return any offscreen canvases back to the main thread, @@ -234,7 +234,7 @@ var LibraryPThread = { Atomics.store(HEAPU32, (threadInfoStruct + {{{ C_STRUCTS.pthread.threadStatus }}} ) >> 2, 1); // Mark the thread as no longer running. _emscripten_futex_wake(threadInfoStruct + {{{ C_STRUCTS.pthread.threadStatus }}}, {{{ cDefine('INT_MAX') }}}); // wake all threads threadInfoStruct = selfThreadId = 0; // Not hosting a pthread anymore in this worker, reset the info structures to null. - registerPthreadPtr(0, 0, 0); // Unregister the thread block also inside the asm.js scope. + __emscripten_thread_init(0, 0, 0); // Unregister the thread block also inside the asm.js scope. postMessage({ 'cmd': 'cancelDone' }); }, @@ -1005,46 +1005,6 @@ var LibraryPThread = { throw 'unwind'; }, - _pthread_ptr: 0, - _pthread_is_main_runtime_thread: 0, - _pthread_is_main_browser_thread: 0, - - $registerPthreadPtr__deps: ['_pthread_ptr', '_pthread_is_main_runtime_thread', '_pthread_is_main_browser_thread'], - $registerPthreadPtr__asm: true, - $registerPthreadPtr__sig: 'viii', - $registerPthreadPtr: function(pthreadPtr, isMainBrowserThread, isMainRuntimeThread) { - pthreadPtr = pthreadPtr|0; - isMainBrowserThread = isMainBrowserThread|0; - isMainRuntimeThread = isMainRuntimeThread|0; - __pthread_ptr = pthreadPtr; - __pthread_is_main_browser_thread = isMainBrowserThread; - __pthread_is_main_runtime_thread = isMainRuntimeThread; - }, - - // Public pthread_self() function which returns a unique ID for the thread. - pthread_self__deps: ['_pthread_ptr'], - pthread_self__asm: true, - pthread_self__sig: 'i', - pthread_self: function() { - return __pthread_ptr|0; - }, - - emscripten_is_main_runtime_thread__asm: true, - emscripten_is_main_runtime_thread__sig: 'i', - emscripten_is_main_runtime_thread__deps: ['_pthread_is_main_runtime_thread'], - emscripten_is_main_runtime_thread: function() { - // Semantically the same as testing "!ENVIRONMENT_IS_PTHREAD" outside the asm.js scope - return __pthread_is_main_runtime_thread|0; - }, - - emscripten_is_main_browser_thread__asm: true, - emscripten_is_main_browser_thread__sig: 'i', - emscripten_is_main_browser_thread__deps: ['_pthread_is_main_browser_thread'], - emscripten_is_main_browser_thread: function() { - // Semantically the same as testing "!ENVIRONMENT_IS_WORKER" outside the asm.js scope - return __pthread_is_main_browser_thread|0; - }, - pthread_getschedparam: function(thread, policy, schedparam) { if (!policy && !schedparam) return ERRNO_CODES.EINVAL; diff --git a/src/postamble_minimal.js b/src/postamble_minimal.js index 310bd0345ed2f..c21083e6a0f6f 100644 --- a/src/postamble_minimal.js +++ b/src/postamble_minimal.js @@ -62,7 +62,7 @@ function initRuntime(asm) { Module['_emscripten_tls_init'] = _emscripten_tls_init; Module['HEAPU32'] = HEAPU32; Module['dynCall'] = dynCall; - Module['registerPthreadPtr'] = registerPthreadPtr; + Module['__emscripten_thread_init'] = __emscripten_thread_init; Module['_pthread_self'] = _pthread_self; if (ENVIRONMENT_IS_PTHREAD) { @@ -72,7 +72,7 @@ function initRuntime(asm) { // Pass the thread address inside the asm.js scope to store it for fast access // that avoids the need for a FFI out. - registerPthreadPtr(PThread.mainThreadBlock, /*isMainBrowserThread=*/!ENVIRONMENT_IS_WORKER, /*isMainRuntimeThread=*/1); + __emscripten_thread_init(PThread.mainThreadBlock, /*isMainBrowserThread=*/!ENVIRONMENT_IS_WORKER, /*isMainRuntimeThread=*/1); _emscripten_register_main_browser_thread_id(PThread.mainThreadBlock); #endif diff --git a/src/worker.js b/src/worker.js index 38e4bcfdde030..fa97c0d40eb08 100644 --- a/src/worker.js +++ b/src/worker.js @@ -155,7 +155,7 @@ this.onmessage = function(e) { threadInfoStruct = e.data.threadInfoStruct; // Pass the thread address inside the asm.js scope to store it for fast access that avoids the need for a FFI out. - Module['registerPthreadPtr'](threadInfoStruct, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0); + Module['__emscripten_thread_init'](threadInfoStruct, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0); selfThreadId = e.data.selfThreadId; parentThreadId = e.data.parentThreadId; diff --git a/system/lib/pthread/pthread_self.s b/system/lib/pthread/pthread_self.s new file mode 100644 index 0000000000000..2e695a6b386e7 --- /dev/null +++ b/system/lib/pthread/pthread_self.s @@ -0,0 +1,39 @@ +.globaltype thread_id, i32 +thread_id: + +.globaltype is_main_thread, i32 +is_main_thread: + +.globaltype is_runtime_thread, i32 +is_runtime_thread: + +.globl pthread_self +pthread_self: + .functype pthread_self () -> (i32) + global.get thread_id + end_function + +.globl _emscripten_thread_init +_emscripten_thread_init: + .functype _emscripten_thread_init (i32, i32, i32) -> () + local.get 0 + global.set thread_id + local.get 1 + global.set is_main_thread + local.get 2 + global.set is_runtime_thread + end_function + +# Semantically the same as testing "!ENVIRONMENT_IS_PTHREAD" in JS +.globl emscripten_is_main_runtime_thread +emscripten_is_main_runtime_thread: + .functype emscripten_is_main_runtime_thread () -> (i32) + global.get is_runtime_thread + end_function + +# Semantically the same as testing "!ENVIRONMENT_IS_WORKER" in JS +.globl emscripten_is_main_browser_thread +emscripten_is_main_browser_thread: + .functype emscripten_is_main_browser_thread () -> (i32) + global.get is_main_thread + end_function diff --git a/tools/system_libs.py b/tools/system_libs.py index 12854794ed4a9..2e6173eef2ba6 100755 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -1200,6 +1200,7 @@ def get_files(self): filenames=[ 'library_pthread.c', 'emscripten_tls_init.c', + 'pthread_self.s', ]) else: files += [shared.path_from_root('system', 'lib', 'pthread', 'library_pthread_stub.c')]