diff --git a/system/lib/compiler-rt/extras.c b/system/lib/compiler-rt/emscripten_exception_builtins.c similarity index 76% rename from system/lib/compiler-rt/extras.c rename to system/lib/compiler-rt/emscripten_exception_builtins.c index 041869ca68cf9..0c29c243f4818 100644 --- a/system/lib/compiler-rt/extras.c +++ b/system/lib/compiler-rt/emscripten_exception_builtins.c @@ -5,14 +5,14 @@ * found in the LICENSE file. * * Support functions for emscripten setjmp/longjmp and exception handling - * support. + * support. References to the things below are generated in the LLVM backend. * See: https://llvm.org/doxygen/WebAssemblyLowerEmscriptenEHSjLj_8cpp.html */ -/* References to these globals are generated in the llvm backend so they - * cannot be static */ -int __THREW__ = 0; -int __threwValue = 0; +#include + +thread_local int __THREW__ = 0; +thread_local int __threwValue = 0; void setThrew(int threw, int value) { if (__THREW__ == 0) { diff --git a/system/lib/libc/extras.c b/system/lib/libc/extras.c index 148cbcc7bc601..f7bd7ff8ea0c1 100644 --- a/system/lib/libc/extras.c +++ b/system/lib/libc/extras.c @@ -30,4 +30,3 @@ long* _get_timezone() { void __lock(void* ptr) {} void __unlock(void* ptr) {} - diff --git a/tests/core/pthread/exceptions.cpp b/tests/core/pthread/exceptions.cpp new file mode 100644 index 0000000000000..14e2598dcea6c --- /dev/null +++ b/tests/core/pthread/exceptions.cpp @@ -0,0 +1,73 @@ +// Copyright 2019 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 +#include +#include +#include +#include + +#include + +#define NUM_THREADS 2 +#define TOTAL 1000 +#define THREAD_ADDS 750 +#define MAIN_ADDS 5 + +static std::atomic sum; +static std::atomic total; + +void *ThreadMain(void *arg) { + for (int i = 0; i < TOTAL; i++) { + try { + // Throw two different types, to make sure we check throwing and landing + // pad behavior. + if (i & 3) { + throw 3.14159f; + } + throw i; + } catch (int x) { + total += x; + } catch (float f) { + sum++; + // wait for a change, so we see interleaved processing. + int last = sum.load(); + while (sum.load() == last) {} + } + } + pthread_exit((void*)TOTAL); +} + +pthread_t thread[NUM_THREADS]; + +void CreateThread(int i) +{ + int rc = pthread_create(&thread[i], nullptr, ThreadMain, (void*)i); + assert(rc == 0); +} + +void loop() { + static int main_adds = 0; + int worker_adds = sum.load() - main_adds; + sum++; + main_adds++; + printf("main iter %d : %d\n", main_adds, worker_adds); + if (worker_adds == NUM_THREADS * THREAD_ADDS && + main_adds >= MAIN_ADDS) { + printf("done: %d.\n", total.load()); + emscripten_cancel_main_loop(); + exit(0); + } +} + +int main() { + // Create initial threads. + for(int i = 0; i < NUM_THREADS; ++i) { + printf("maek\n"); + CreateThread(i); + } + + emscripten_set_main_loop(loop, 0, 0); +} diff --git a/tests/core/pthread/exceptions.out b/tests/core/pthread/exceptions.out new file mode 100644 index 0000000000000..a179329e2e7d0 --- /dev/null +++ b/tests/core/pthread/exceptions.out @@ -0,0 +1 @@ +done: 249000. diff --git a/tests/test_core.py b/tests/test_core.py index 9d971f7d78845..d1d5021cdfb4c 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -7750,7 +7750,6 @@ def test_stack_overflow_check(self): self.emcc_args += ['-DONE_BIG_STRING'] self.do_runf(path_from_root('tests', 'stack_overflow.cpp'), 'stack overflow', assert_returncode=NON_ZERO) - @unittest.skip('let llvm roll in') @node_pthreads def test_binaryen_2170_emscripten_atomic_cas_u8(self): self.emcc_args += ['-s', 'USE_PTHREADS=1'] @@ -8163,7 +8162,6 @@ def test_fpic_static(self): self.emcc_args.append('-fPIC') self.do_run_in_out_file_test('tests', 'core', 'test_hello_world.c') - @unittest.skip('let llvm roll in') @node_pthreads def test_pthread_create(self): self.set_setting('-lbrowser.js') @@ -8178,18 +8176,21 @@ def test(): self.emcc_args += ['-DPOOL'] test() - @unittest.skip('let llvm roll in') + @node_pthreads + def test_pthread_exceptions(self): + self.set_setting('PTHREAD_POOL_SIZE', '2') + self.emcc_args += ['-fexceptions'] + self.do_run_in_out_file_test('tests', 'core', 'pthread', 'exceptions.cpp') + def test_emscripten_atomics_stub(self): self.do_run_in_out_file_test('tests', 'core', 'pthread', 'emscripten_atomics.c') - @unittest.skip('let llvm roll in') @no_asan('incompatibility with atomics') @node_pthreads def test_emscripten_atomics(self): self.set_setting('USE_PTHREADS', '1') self.do_run_in_out_file_test('tests', 'core', 'pthread', 'emscripten_atomics.c') - @unittest.skip('let llvm roll in') @no_asan('incompatibility with atomics') @node_pthreads def test_emscripten_futexes(self): diff --git a/tests/test_other.py b/tests/test_other.py index 6bd8cc8594567..a81b420d84b41 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2563,7 +2563,6 @@ def test_fs_stream_proto(self): out = self.run_js('a.out.js', engine=engine) self.assertContained('File size: 724', out) - @unittest.skip('let llvm roll in') def test_node_emscripten_num_logical_cores(self): # Test with node.js that the emscripten_num_logical_cores method is working create_test_file('src.cpp', r''' @@ -7890,7 +7889,6 @@ def test_node_js_run_from_different_directory(self): self.assertContained('hello, world!', ret) # Tests that a pthreads + modularize build can be run in node js - @unittest.skip('let llvm roll in') def test_node_js_pthread_module(self): # create module loader script moduleLoader = 'moduleLoader.js' @@ -8816,7 +8814,6 @@ def test_asan_no_stack_trace(self): def test_asan_pthread_stubs(self): self.do_smart_test(path_from_root('tests', 'other', 'test_asan_pthread_stubs.c'), emcc_args=['-fsanitize=address', '-s', 'ALLOW_MEMORY_GROWTH=1']) - @unittest.skip('let llvm roll in') def test_proxy_to_pthread_stack(self): with js_engines_modify([NODE_JS + ['--experimental-wasm-threads', '--experimental-wasm-bulk-memory']]): self.do_smart_test(path_from_root('tests', 'other', 'test_proxy_to_pthread_stack.c'), @@ -9212,7 +9209,6 @@ def test_backwards_deps_in_archive(self): self.run_process([EMCC, 'empty.c', '-la', '-L.']) self.assertContained('success', self.run_js('a.out.js')) - @unittest.skip('let llvm roll in') def test_warning_flags(self): self.run_process([EMCC, '-c', '-o', 'hello.o', path_from_root('tests', 'hello_world.c')]) cmd = [EMCC, 'hello.o', '-o', 'a.js', '-g', '--closure', '1'] diff --git a/tools/system_libs.py b/tools/system_libs.py index 44bcfd13795ad..a8cbc684553f2 100755 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -635,7 +635,7 @@ def get_default_variation(cls, **kwargs): return super(AsanInstrumentedLibrary, cls).get_default_variation(is_asan=shared.Settings.USE_ASAN, **kwargs) -class libcompiler_rt(Library): +class libcompiler_rt(MTLibrary): name = 'libcompiler_rt' # compiler_rt files can't currently be part of LTO although we are hoping to remove this # restriction soon: https://reviews.llvm.org/D71738 @@ -644,9 +644,9 @@ class libcompiler_rt(Library): cflags = ['-O2', '-fno-builtin'] src_dir = ['system', 'lib', 'compiler-rt', 'lib', 'builtins'] src_files = glob_in_path(src_dir, '*.c') - src_files.append(shared.path_from_root('system', 'lib', 'compiler-rt', 'extras.c')) src_files.append(shared.path_from_root('system', 'lib', 'compiler-rt', 'stack_ops.s')) src_files.append(shared.path_from_root('system', 'lib', 'compiler-rt', 'emscripten_setjmp.c')) + src_files.append(shared.path_from_root('system', 'lib', 'compiler-rt', 'emscripten_exception_builtins.c')) class libc(AsanInstrumentedLibrary, MuslInternalLibrary, MTLibrary):