diff --git a/emcc.py b/emcc.py index 9188494f5b781..1ae59c499740c 100755 --- a/emcc.py +++ b/emcc.py @@ -101,6 +101,10 @@ final = None +def exit_with_error(message): + logging.error(message) + exit(1) + class Intermediate(object): counter = 0 def save_intermediate(name=None, suffix='js'): @@ -737,8 +741,7 @@ def setting_sub(s): if not arg.startswith('-'): if not os.path.exists(arg): - logging.error('%s: No such file or directory ("%s" was expected to be an input file, based on the commandline arguments provided)', arg, arg) - exit(1) + exit_with_error('%s: No such file or directory ("%s" was expected to be an input file, based on the commandline arguments provided)', arg, arg) arg_ending = filename_type_ending(arg) if arg_ending.endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS) or shared.Building.is_ar(arg): # we already removed -o , so all these should be inputs @@ -766,18 +769,17 @@ def setting_sub(s): elif arg_ending.endswith(STATICLIB_ENDINGS): if not shared.Building.is_ar(arg): if shared.Building.is_bitcode(arg): - logging.error(arg + ': File has a suffix of a static library ' + str(STATICLIB_ENDINGS) + ', but instead is an LLVM bitcode file! When linking LLVM bitcode files, use one of the suffixes ' + str(BITCODE_ENDINGS)) + message = arg + ': File has a suffix of a static library ' + str(STATICLIB_ENDINGS) + ', but instead is an LLVM bitcode file! When linking LLVM bitcode files, use one of the suffixes ' + str(BITCODE_ENDINGS) else: - logging.error(arg + ': Unknown format, not a static library!') - exit(1) + message = arg + ': Unknown format, not a static library!' + exit_with_error(message) else: if has_fixed_language_mode: newargs[i] = '' input_files.append((i, arg)) has_source_inputs = True else: - logging.error(arg + ": Input file has an unknown suffix, don't know what to do with it!") - exit(1) + exit_with_error(arg + ": Input file has an unknown suffix, don't know what to do with it!") elif arg.startswith('-L'): lib_dirs.append(arg[2:]) newargs[i] = '' @@ -862,8 +864,7 @@ def check(input_file): input_files = [(i, input_file) for (i, input_file) in input_files if check(input_file)] if len(input_files) == 0: - logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + STATICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS)) - exit(1) + exit_with_error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + STATICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS)) newargs = CC_ADDITIONAL_ARGS + newargs @@ -933,8 +934,7 @@ def check(input_file): assert shared.Settings.PGO == 0, 'pgo not supported in fastcomp' assert shared.Settings.QUANTUM_SIZE == 4, 'altering the QUANTUM_SIZE is not supported' except Exception as e: - logging.error('Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see http://kripken.github.io/emscripten-site/docs/building_from_source/LLVM-Backend.html') - raise e + exit_with_error('Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see http://kripken.github.io/emscripten-site/docs/building_from_source/LLVM-Backend.html') assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode' @@ -949,8 +949,7 @@ def check(input_file): if options.use_closure_compiler: shared.Settings.USE_CLOSURE_COMPILER = options.use_closure_compiler if not shared.check_closure_compiler(): - logging.error('fatal: closure compiler is not configured correctly') - sys.exit(1) + exit_with_error('fatal: closure compiler is not configured correctly') if options.use_closure_compiler == 2 and shared.Settings.ASM_JS == 1: shared.WarningManager.warn('ALMOST_ASM', 'not all asm.js optimizations are possible with --closure 2, disabling those - your code will be run more slowly') shared.Settings.ASM_JS = 2 @@ -1007,8 +1006,7 @@ def check(input_file): shared.Settings.NO_FILESYSTEM = 1 shared.Settings.FETCH = 1 if not shared.Settings.USE_PTHREADS: - logging.error('-s ASMFS=1 requires either -s USE_PTHREADS=1 or -s USE_PTHREADS=2 to be set!') - sys.exit(1) + exit_with_error('-s ASMFS=1 requires either -s USE_PTHREADS=1 or -s USE_PTHREADS=2 to be set!') if shared.Settings.FETCH and final_suffix in JS_CONTAINING_SUFFIXES: input_files.append((next_arg_index, shared.path_from_root('system', 'lib', 'fetch', 'emscripten_fetch.cpp'))) @@ -1083,24 +1081,18 @@ def check(input_file): if shared.Settings.USE_PTHREADS: if shared.Settings.LINKABLE: - logging.error('-s LINKABLE=1 is not supported with -s USE_PTHREADS>0!') - exit(1) + exit_with_error('-s LINKABLE=1 is not supported with -s USE_PTHREADS>0!') if shared.Settings.SIDE_MODULE: - logging.error('-s SIDE_MODULE=1 is not supported with -s USE_PTHREADS>0!') - exit(1) + exit_with_error('-s SIDE_MODULE=1 is not supported with -s USE_PTHREADS>0!') if shared.Settings.MAIN_MODULE: - logging.error('-s MAIN_MODULE=1 is not supported with -s USE_PTHREADS>0!') - exit(1) + exit_with_error('-s MAIN_MODULE=1 is not supported with -s USE_PTHREADS>0!') if shared.Settings.EMTERPRETIFY: - logging.error('-s EMTERPRETIFY=1 is not supported with -s USE_PTHREADS>0!') - exit(1) + exit_with_error('-s EMTERPRETIFY=1 is not supported with -s USE_PTHREADS>0!') if shared.Settings.PROXY_TO_WORKER: - logging.error('--proxy-to-worker is not supported with -s USE_PTHREADS>0! Use the option -s PROXY_TO_PTHREAD=1 if you want to run the main thread of a multithreaded application in a web worker.') - exit(1) + exit_with_error('--proxy-to-worker is not supported with -s USE_PTHREADS>0! Use the option -s PROXY_TO_PTHREAD=1 if you want to run the main thread of a multithreaded application in a web worker.') else: if shared.Settings.PROXY_TO_PTHREAD: - logging.error('-s PROXY_TO_PTHREAD=1 requires -s USE_PTHREADS to work!') - exit(1) + exit_with_error('-s PROXY_TO_PTHREAD=1 requires -s USE_PTHREADS to work!') if shared.Settings.OUTLINING_LIMIT: if not options.js_opts: @@ -1120,13 +1112,20 @@ def check(input_file): if not DEBUG: misc_temp_files.note(asm_target) - assert shared.Settings.TOTAL_MEMORY >= 16*1024*1024, 'TOTAL_MEMORY must be at least 16MB, was ' + str(shared.Settings.TOTAL_MEMORY) + if shared.Settings.TOTAL_MEMORY < 16*1024*1024: + exit_with_error('TOTAL_MEMORY must be at least 16MB, was ' + str(shared.Settings.TOTAL_MEMORY)) if shared.Settings.BINARYEN: - assert shared.Settings.TOTAL_MEMORY % 65536 == 0, 'For wasm, TOTAL_MEMORY must be a multiple of 64KB, was ' + str(shared.Settings.TOTAL_MEMORY) + if shared.Settings.TOTAL_MEMORY % 65536 != 0: + exit_with_error('For wasm, TOTAL_MEMORY must be a multiple of 64KB, was ' + str(shared.Settings.TOTAL_MEMORY)) else: - assert shared.Settings.TOTAL_MEMORY % (16*1024*1024) == 0, 'For asm.js, TOTAL_MEMORY must be a multiple of 16MB, was ' + str(shared.Settings.TOTAL_MEMORY) - assert shared.Settings.TOTAL_MEMORY >= shared.Settings.TOTAL_STACK, 'TOTAL_MEMORY must be larger than TOTAL_STACK, was ' + str(shared.Settings.TOTAL_MEMORY) + ' (TOTAL_STACK=' + str(shared.Settings.TOTAL_STACK) + ')' - assert shared.Settings.WASM_MEM_MAX == -1 or shared.Settings.WASM_MEM_MAX % 65536 == 0, 'WASM_MEM_MAX must be a multiple of 64KB, was ' + str(shared.Settings.WASM_MEM_MAX) + if shared.Settings.TOTAL_MEMORY % (16*1024*1024) != 0: + exit_with_error('For asm.js, TOTAL_MEMORY must be a multiple of 16MB, was ' + str(shared.Settings.TOTAL_MEMORY)) + if shared.Settings.TOTAL_MEMORY < shared.Settings.TOTAL_STACK: + exit_with_error('TOTAL_MEMORY must be larger than TOTAL_STACK, was ' + str(shared.Settings.TOTAL_MEMORY) + ' (TOTAL_STACK=' + str(shared.Settings.TOTAL_STACK) + ')') + if shared.Settings.WASM_MEM_MAX != -1 and shared.Settings.WASM_MEM_MAX % 65536 != 0: + exit_with_error('WASM_MEM_MAX must be a multiple of 64KB, was ' + str(shared.Settings.WASM_MEM_MAX)) + if shared.Settings.USE_PTHREADS and shared.Settings.WASM and shared.Settings.ALLOW_MEMORY_GROWTH and shared.Settings.WASM_MEM_MAX == -1: + exit_with_error('If pthreads and memory growth are enabled, WASM_MEM_MAX must be set') if shared.Settings.WASM_BACKEND: options.js_opts = None @@ -1150,7 +1149,6 @@ def check(input_file): shared.Settings.ASM_JS = 2 # when targeting wasm, we use a wasm Memory, but that is not compatible with asm.js opts shared.Settings.GLOBAL_BASE = 1024 # leave some room for mapping global vars assert not shared.Settings.SPLIT_MEMORY, 'WebAssembly does not support split memory' - assert not shared.Settings.USE_PTHREADS, 'WebAssembly does not support pthreads' if shared.Settings.ELIMINATE_DUPLICATE_FUNCTIONS: logging.warning('for wasm there is no need to set ELIMINATE_DUPLICATE_FUNCTIONS, the binaryen optimizer does it automatically') shared.Settings.ELIMINATE_DUPLICATE_FUNCTIONS = 0 @@ -1340,8 +1338,7 @@ def compile_source_file(i, input_file): logging.debug("running: " + ' '.join(shared.Building.doublequote_spaces(args))) # NOTE: Printing this line here in this specific format is important, it is parsed to implement the "emcc --cflags" command execute(args) # let compiler frontend print directly, so colors are saved (PIPE kills that) if not os.path.exists(output_file): - logging.error('compiler frontend failed to generate LLVM bitcode, halting') - sys.exit(1) + exit_with_error('compiler frontend failed to generate LLVM bitcode, halting') # First, generate LLVM bitcode. For each input file, we get base.o with bitcode for i, input_file in input_files: @@ -1365,8 +1362,7 @@ def compile_source_file(i, input_file): if has_fixed_language_mode: compile_source_file(i, input_file) else: - logging.error(input_file + ': Unknown file suffix when compiling to LLVM bitcode!') - sys.exit(1) + exit_with_error(input_file + ': Unknown file suffix when compiling to LLVM bitcode!') # exit block 'bitcodeize inputs' log_time('bitcodeize inputs') @@ -2132,8 +2128,7 @@ def parse_args(newargs): elif newargs[i+1].lower() == 'linux': options.output_eol = '\n' else: - logging.error('Invalid value "' + newargs[i+1] + '" to --output_eol!') - exit(1) + exit_with_error('Invalid value "' + newargs[i+1] + '" to --output_eol!') newargs[i] = '' newargs[i+1] = '' @@ -2233,8 +2228,7 @@ def binaryen_method_sanity_check(): valid_methods = ['asmjs', 'native-wasm', 'interpret-s-expr', 'interpret-binary', 'interpret-asm2wasm'] for m in methods: if m.strip() not in valid_methods: - logging.error('Unrecognized BINARYEN_METHOD "' + m.strip() + '" specified! Please pass a comma-delimited list containing one or more of: ' + ','.join(valid_methods)) - sys.exit(1) + exit_with_error('Unrecognized BINARYEN_METHOD "' + m.strip() + '" specified! Please pass a comma-delimited list containing one or more of: ' + ','.join(valid_methods)) def do_binaryen(final, target, asm_target, options, memfile, wasm_binary_target, @@ -2269,8 +2263,7 @@ def do_binaryen(final, target, asm_target, options, memfile, wasm_binary_target, if shared.Settings.BINARYEN_TRAP_MODE in ('js', 'clamp', 'allow'): cmd += ['--trap-mode=' + shared.Settings.BINARYEN_TRAP_MODE] else: - logging.error('invalid BINARYEN_TRAP_MODE value: ' + shared.Settings.BINARYEN_TRAP_MODE + ' (should be js/clamp/allow)') - sys.exit(1) + exit_with_error('invalid BINARYEN_TRAP_MODE value: ' + shared.Settings.BINARYEN_TRAP_MODE + ' (should be js/clamp/allow)') if shared.Settings.BINARYEN_IGNORE_IMPLICIT_TRAPS: cmd += ['--ignore-implicit-traps'] # pass optimization level to asm2wasm (if not optimizing, or which passes we should run was overridden, do not optimize) @@ -2295,6 +2288,8 @@ def do_binaryen(final, target, asm_target, options, memfile, wasm_binary_target, cmd += ['--no-legalize-javascript-ffi'] if shared.Building.is_wasm_only(): cmd += ['--wasm-only'] # this asm.js is code not intended to run as asm.js, it is only ever going to be wasm, an can contain special fastcomp-wasm support + if shared.Settings.USE_PTHREADS: + cmd += ['--enable-threads'] if debug_info: cmd += ['-g'] if options.emit_symbol_map or shared.Settings.CYBERDWARF: diff --git a/src/library_pthread.js b/src/library_pthread.js index 77a6329e191a9..64621ab6a9c71 100644 --- a/src/library_pthread.js +++ b/src/library_pthread.js @@ -366,7 +366,12 @@ var LibraryPThread = { // object in Module['mainScriptUrlOrBlob'], or a URL to it, so that pthread Workers can // independently load up the same main application file. urlOrBlob: Module['mainScriptUrlOrBlob'] || currentScriptUrl, +#if BINARYEN + wasmMemory: Module['wasmMemory'], + wasmModule: Module['wasmModule'], +#else buffer: HEAPU8.buffer, +#endif tempDoublePtr: tempDoublePtr, TOTAL_MEMORY: TOTAL_MEMORY, STATICTOP: STATICTOP, diff --git a/src/preamble.js b/src/preamble.js index a1abf2fc53080..ad9d946d85f5e 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -1114,6 +1114,7 @@ if (typeof SharedArrayBuffer === 'undefined' || typeof Atomics === 'undefined') #endif #if USE_PTHREADS +#if !BINARYEN if (typeof SharedArrayBuffer !== 'undefined') { if (!ENVIRONMENT_IS_PTHREAD) buffer = new SharedArrayBuffer(TOTAL_MEMORY); // Currently SharedArrayBuffer does not have a slice() operation, so polyfill it in. @@ -1166,6 +1167,18 @@ if (typeof Atomics === 'undefined') { Atomics['xor'] = function(t, i, v) { var w = t[i]; t[i] ^= v; return w; } } +#else +if (!ENVIRONMENT_IS_PTHREAD) { +#if ALLOW_MEMORY_GROWTH + Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE , 'maximum': {{{ WASM_MEM_MAX }}} / WASM_PAGE_SIZE, 'shared': true }); +#else + Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE , 'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE, 'shared': true }); +#endif + buffer = Module['wasmMemory'].buffer; +} + +updateGlobalBufferViews(); +#endif // !BINARYEN #else // USE_PTHREADS #if SPLIT_MEMORY == 0 @@ -1181,7 +1194,7 @@ if (Module['buffer']) { if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') { #if ASSERTIONS assert(TOTAL_MEMORY % WASM_PAGE_SIZE === 0); -#endif +#endif // ASSERTIONS #if ALLOW_MEMORY_GROWTH #if WASM_MEM_MAX #if ASSERTIONS @@ -1190,19 +1203,19 @@ if (Module['buffer']) { Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': {{{ WASM_MEM_MAX }}} / WASM_PAGE_SIZE }); #else Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE }); -#endif +#endif // BINARYEN_MEM_MAX #else Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE }); -#endif +#endif // ALLOW_MEMORY_GROWTH buffer = Module['wasmMemory'].buffer; } else -#endif +#endif // BINARYEN { buffer = new ArrayBuffer(TOTAL_MEMORY); } #if ASSERTIONS assert(buffer.byteLength === TOTAL_MEMORY); -#endif +#endif // ASSERTIONS } updateGlobalBufferViews(); #else // SPLIT_MEMORY @@ -2193,15 +2206,27 @@ function integrateWasmJS() { info['env'] = env; // handle a generated wasm instance, receiving its exports and // performing other necessary setup - function receiveInstance(instance) { + function receiveInstance(instance, module) { exports = instance.exports; if (exports.memory) mergeMemory(exports.memory); Module['asm'] = exports; Module["usingWasm"] = true; +#if USE_PTHREADS + // Keep a reference to the compiled module so we can post it to the workers. + Module['wasmModule'] = module; + // Instantiation is synchronous in pthreads and we assert on run dependencies. + if(!ENVIRONMENT_IS_PTHREAD) removeRunDependency('wasm-instantiate'); +#else removeRunDependency('wasm-instantiate'); +#endif } - - addRunDependency('wasm-instantiate'); // we can't run yet +#if USE_PTHREADS + if (!ENVIRONMENT_IS_PTHREAD) { + addRunDependency('wasm-instantiate'); // we can't run yet (except in a pthread, where we have a custom sync instantiator) + } +#else + addRunDependency('wasm-instantiate'); +#endif // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel @@ -2232,7 +2257,7 @@ function integrateWasmJS() { assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); trueModule = null; #endif - receiveInstance(output['instance']); + receiveInstance(output['instance'], output['module']); } function instantiateArrayBuffer(receiver) { getBinaryPromise().then(function(binary) { diff --git a/src/pthread-main.js b/src/pthread-main.js index 1a53cf108c330..38d06e8ed3e9f 100644 --- a/src/pthread-main.js +++ b/src/pthread-main.js @@ -54,6 +54,18 @@ Module['print'] = threadPrint; Module['printErr'] = threadPrintErr; this.alert = threadAlert; +// #if WASM +Module['instantiateWasm'] = function(info, receiveInstance) { + // Instantiate from the module posted from the main thread. + // We can just use sync instantiation in the worker. + instance = new WebAssembly.Instance(Module['wasmModule'], info); + // We don't need the module anymore; new threads will be spawned from the main thread. + delete Module['wasmModule']; + receiveInstance(instance); + return instance.exports; +} +//#endif + this.onmessage = function(e) { try { if (e.data.cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code. @@ -61,12 +73,24 @@ this.onmessage = function(e) { tempDoublePtr = e.data.tempDoublePtr; // Initialize the global "process"-wide fields: - buffer = e.data.buffer; Module['TOTAL_MEMORY'] = TOTAL_MEMORY = e.data.TOTAL_MEMORY; STATICTOP = e.data.STATICTOP; DYNAMIC_BASE = e.data.DYNAMIC_BASE; DYNAMICTOP_PTR = e.data.DYNAMICTOP_PTR; + +//#if WASM + if (e.data.wasmModule) { + // Module and memory were sent from main thread + Module['wasmModule'] = e.data.wasmModule; + Module['wasmMemory'] = e.data.wasmMemory; + buffer = Module['wasmMemory'].buffer; + } else { +//#else + buffer = e.data.buffer; + } +//#endif + PthreadWorkerInit = e.data.PthreadWorkerInit; if (typeof e.data.urlOrBlob === 'string') { importScripts(e.data.urlOrBlob); diff --git a/tests/runner.py b/tests/runner.py index b0128c0cd0d99..8a079d7ede087 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -787,6 +787,7 @@ def __init__(self, *args, **kwargs): @classmethod def setUpClass(self): super(BrowserCore, self).setUpClass() + self.also_wasm = os.environ.get('EMCC_BROWSER_ALSO_WASM', '0') == '1' if not has_browser(): return self.browser_timeout = 30 self.harness_queue = multiprocessing.Queue() @@ -970,7 +971,7 @@ def reftest(self, expected): ''' % basename) def btest(self, filename, expected=None, reference=None, force_c=False, reference_slack=0, manual_reference=False, post_build=None, - args=[], outfile='test.html', message='.', also_proxied=False, url_suffix='', timeout=None): # TODO: use in all other tests + args=[], outfile='test.html', message='.', also_proxied=False, url_suffix='', timeout=None, also_wasm=True): # TODO: use in all other tests # if we are provided the source and not a path, use that filename_is_src = '\n' in filename src = filename if filename_is_src else '' @@ -998,6 +999,14 @@ def btest(self, filename, expected=None, reference=None, force_c=False, referenc if post_build: post_build() if not isinstance(expected, list): expected = [expected] self.run_browser(outfile + url_suffix, message, ['/report_result?' + e for e in expected], timeout=timeout) + if also_wasm and self.also_wasm: + wasm_args = args + ['-s', 'WASM=1'] + # Filter out separate-asm, which is implied by wasm + wasm_args = [a for a in wasm_args if a != '--separate-asm'] + # wasm doesn't support USE_PTHREADS=2 + wasm_args = ['USE_PTHREADS=1' if a == 'USE_PTHREADS=2' else a for a in wasm_args] + self.btest(filename, expected, reference, force_c, reference_slack, manual_reference, post_build, + wasm_args, outfile, message, also_proxied=False, timeout=timeout, also_wasm=False) if also_proxied: print('proxied...') if reference: diff --git a/tests/test_browser.py b/tests/test_browser.py index dc29226250816..ca1455f410bc4 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -60,6 +60,7 @@ class browser(BrowserCore): def setUpClass(self): super(browser, self).setUpClass() self.browser_timeout = 20 + self.test_wasm_pthreads = os.environ.get('TEST_WASM_PTHREADS', '0') == '1' print() print('Running the browser tests. Make sure the browser allows popups from localhost.') print() @@ -3136,19 +3137,19 @@ def test_pthread_gcc_atomic_fetch_and_op(self): for debug in [[], ['-g1'], ['-g2'], ['-g4']]: for f32 in [[], ['-s', 'PRECISE_F32=1']]: print(opt, debug, f32) - self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_atomic_fetch_and_op.cpp'), expected='0', args=opt+debug+f32+['-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=60) + self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_atomic_fetch_and_op.cpp'), expected='0', args=opt+debug+f32+['-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=60, also_wasm=False) # 64 bit version of the above test. def test_pthread_gcc_64bit_atomic_fetch_and_op(self): - self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_64bit_atomic_fetch_and_op.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) + self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_64bit_atomic_fetch_and_op.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30, also_wasm=False) # Test the old GCC atomic __sync_op_and_fetch builtin operations. def test_pthread_gcc_atomic_op_and_fetch(self): - self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_atomic_op_and_fetch.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) + self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_atomic_op_and_fetch.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30, also_wasm=False) # 64 bit version of the above test. def test_pthread_gcc_64bit_atomic_op_and_fetch(self): - self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_64bit_atomic_op_and_fetch.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) + self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_64bit_atomic_op_and_fetch.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30, also_wasm=False) # Tests the rest of the remaining GCC atomics after the two above tests. def test_pthread_gcc_atomics(self): @@ -3157,7 +3158,7 @@ def test_pthread_gcc_atomics(self): # Test the __sync_lock_test_and_set and __sync_lock_release primitives. def test_pthread_gcc_spinlock(self): for arg in [[], ['-DUSE_EMSCRIPTEN_INTRINSICS']]: - self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_spinlock.cpp'), expected='800', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'] + arg, timeout=30) + self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_spinlock.cpp'), expected='800', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'] + arg, timeout=30, also_wasm=False) # Test that basic thread creation works. def test_pthread_create(self): @@ -3193,6 +3194,9 @@ def test_pthread_cancel(self): # Test pthread_kill() operation def test_pthread_kill(self): + if get_browser() and 'chrom' in get_browser().lower(): + # This test hangs the chrome render process, and keep subsequent tests from passing too + return self.skip("pthread_kill hangs chrome renderer") self.btest(path_from_root('tests', 'pthread', 'test_pthread_kill.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test that pthread cleanup stack (pthread_cleanup_push/_pop) works. @@ -3251,14 +3255,14 @@ def test_pthread_setspecific_mainthread(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_setspecific_mainthread.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm'], timeout=30) self.prep_no_SAB() - self.btest(path_from_root('tests', 'pthread', 'test_pthread_setspecific_mainthread.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '--shell-file', 'html.html'], timeout=30) + self.btest(path_from_root('tests', 'pthread', 'test_pthread_setspecific_mainthread.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '--shell-file', 'html.html'], timeout=30, also_wasm=False) # Test the -s PTHREAD_HINT_NUM_CORES=x command line variable. def test_pthread_num_logical_cores(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_num_logical_cores.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_HINT_NUM_CORES=2'], timeout=30) self.prep_no_SAB() - self.btest(path_from_root('tests', 'pthread', 'test_pthread_num_logical_cores.cpp'), expected='0', args=['-O3', '-g', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_HINT_NUM_CORES=2', '--shell-file', 'html.html'], timeout=30) + self.btest(path_from_root('tests', 'pthread', 'test_pthread_num_logical_cores.cpp'), expected='0', args=['-O3', '-g', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_HINT_NUM_CORES=2', '--shell-file', 'html.html'], timeout=30, also_wasm=False) # Test that pthreads have access to filesystem. def test_pthread_file_io(self):