From 59a20967dc6aafa631111b55d186619d70f96ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Mon, 6 Nov 2017 00:15:50 +0200 Subject: [PATCH] Don't use wasm global data sections when compiling with multithreading enabled so that pthread_create() will not reset the global data members. Instead use a separate .mem file or base64-embedded data in JS file for memory initialization. See https://github.com/WebAssembly/threads/issues/62 --- emcc.py | 5 ++++- tests/test_browser.py | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/emcc.py b/emcc.py index 712b096c1cec4..afc20639afa38 100755 --- a/emcc.py +++ b/emcc.py @@ -1718,7 +1718,7 @@ def repl(m): if DEBUG: # Copy into temp dir as well, so can be run there too shared.safe_copy(memfile, os.path.join(shared.get_emscripten_temp_dir(), os.path.basename(memfile))) - if not shared.Settings.BINARYEN or 'asmjs' in shared.Settings.BINARYEN_METHOD or 'interpret-asm2wasm' in shared.Settings.BINARYEN_METHOD: + if not shared.Settings.BINARYEN or 'asmjs' in shared.Settings.BINARYEN_METHOD or 'interpret-asm2wasm' in shared.Settings.BINARYEN_METHOD or shared.Settings.USE_PTHREADS: return 'memoryInitializer = "%s";' % shared.JS.get_subresource_location(memfile, embed_memfile(options)) else: return '' @@ -2310,6 +2310,9 @@ def do_binaryen(target, asm_target, options, memfile, wasm_binary_target, if options.opt_level > 0: cmd.append(shared.Building.opt_level_to_str(options.opt_level, options.shrink_level)) # import mem init file if it exists, and if we will not be using asm.js as a binaryen method (as it needs the mem init file, of course) + # Note that importing (embedding) memory init file into the .wasm module as a data section is not compatible with multithreading in WebAssembly, + # because each thread would reinitialize the global data section at thread creation time, so only embed a data section to the generated + # .wasm file if not using multithreading mem_file_exists = options.memory_init_file and os.path.exists(memfile) import_mem_init = mem_file_exists and shared.Settings.MEM_INIT_IN_WASM if import_mem_init: diff --git a/tests/test_browser.py b/tests/test_browser.py index 236b2616c3f68..4e338d3c2be94 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -3349,6 +3349,12 @@ def test_pthread_global_data_initialization(self): for args in [[], ['-O3']]: self.btest(path_from_root('tests', 'pthread', 'test_pthread_global_data_initialization.c'), expected='20', args=args+mem_init_mode+['-s', 'USE_PTHREADS=1', '-s', 'PROXY_TO_PTHREAD=1'], also_wasm=False) + # Tests that spawning a new thread does not cause a reinitialization of the global data section of the application memory area. + def test_pthread_global_data_initialization(self): + for mem_init_mode in [[], ['--memory-init-file', '0'], ['--memory-init-file', '1'], ['--memory-init-file', '2']]: + for args in [[], ['-O3']]: + self.btest_wasm(path_from_root('tests', 'pthread', 'test_pthread_global_data_initialization.c'), expected='20', args=args+mem_init_mode+['-s', 'USE_PTHREADS=1', '-s', 'PROXY_TO_PTHREAD=1']) + # test atomicrmw i64 def test_atomicrmw_i64(self): Popen([PYTHON, EMCC, path_from_root('tests', 'atomicrmw_i64.ll'), '-s', 'USE_PTHREADS=1', '-s', 'IN_TEST_HARNESS=1', '-o', 'test.html']).communicate()