| /** |
| * @license |
| * Copyright 2015 The Emscripten Authors |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| var LibraryPThreadStub = { |
| // =================================================================================== |
| // Stub implementation for pthread.h when not compiling with pthreads support enabled. |
| // =================================================================================== |
| |
| emscripten_is_main_browser_thread: function() { |
| #if MINIMAL_RUNTIME |
| return typeof importScripts === 'undefined'; |
| #else |
| return !ENVIRONMENT_IS_WORKER; |
| #endif |
| }, |
| |
| pthread_mutexattr_init: function() {}, |
| pthread_mutexattr_setschedparam: function() {}, |
| pthread_mutexattr_setprotocol: function() {}, |
| pthread_mutexattr_settype: function() {}, |
| pthread_mutexattr_destroy: function() {}, |
| |
| pthread_mutexattr_setpshared: function(attr, pshared) { |
| // XXX implement if/when getpshared is required |
| return 0; |
| }, |
| |
| pthread_cond_init: function() { return 0; }, |
| pthread_cond_destroy: function() { return 0; }, |
| pthread_cond_timedwait: function() { return 0; }, |
| |
| pthread_condattr_init: function() { return 0; }, |
| pthread_condattr_destroy: function() { return 0; }, |
| pthread_condattr_setclock: function() { return 0; }, |
| pthread_condattr_setpshared: function() { return 0; }, |
| pthread_condattr_getclock: function() { return 0; }, |
| pthread_condattr_getpshared: function() { return 0; }, |
| |
| pthread_attr_init: function(attr) { |
| /* int pthread_attr_init(pthread_attr_t *attr); */ |
| //FIXME: should allocate a pthread_attr_t |
| return 0; |
| }, |
| pthread_getattr_np: function(thread, attr) { |
| /* int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr); */ |
| //FIXME: should fill in attributes of the given thread in pthread_attr_t |
| return 0; |
| }, |
| pthread_attr_destroy: function(attr) { |
| /* int pthread_attr_destroy(pthread_attr_t *attr); */ |
| //FIXME: should destroy the pthread_attr_t struct |
| return 0; |
| }, |
| pthread_attr_getstack: function(attr, stackaddr, stacksize) { |
| /* int pthread_attr_getstack(const pthread_attr_t *restrict attr, |
| void **restrict stackaddr, size_t *restrict stacksize); */ |
| /*FIXME: assumes that there is only one thread, and that attr is the |
| current thread*/ |
| {{{ makeSetValue('stackaddr', '0', 'STACK_BASE', 'i8*') }}}; |
| {{{ makeSetValue('stacksize', '0', 'TOTAL_STACK', 'i32') }}}; |
| return 0; |
| }, |
| pthread_attr_getdetachstate: function(attr, detachstate) { |
| /* int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); */ |
| return 0; |
| }, |
| |
| pthread_setcancelstate: function() { return 0; }, |
| pthread_setcanceltype: function() { return 0; }, |
| |
| pthread_cleanup_push__sig: 'vii', |
| pthread_cleanup_push: function(routine, arg) { |
| __ATEXIT__.push({ func: routine, arg: arg }); |
| _pthread_cleanup_push.level = __ATEXIT__.length; |
| }, |
| |
| pthread_cleanup_pop__sig: 'vi', |
| pthread_cleanup_pop: function(execute) { |
| assert(_pthread_cleanup_push.level == __ATEXIT__.length, 'cannot pop if something else added meanwhile!'); |
| callback = __ATEXIT__.pop(); |
| if (execute) { |
| {{{ makeDynCall('vi', 'callback.func') }}}(callback.arg) |
| } |
| _pthread_cleanup_push.level = __ATEXIT__.length; |
| }, |
| |
| // pthread_sigmask - examine and change mask of blocked signals |
| pthread_sigmask: function(how, set, oldset) { |
| err('pthread_sigmask() is not supported: this is a no-op.'); |
| return 0; |
| }, |
| |
| pthread_rwlock_init: function() { return 0; }, |
| pthread_rwlock_destroy: function() { return 0; }, |
| pthread_rwlock_rdlock: function() { return 0; }, |
| pthread_rwlock_tryrdlock: function() { return 0; }, |
| pthread_rwlock_timedrdlock: function() { return 0; }, |
| pthread_rwlock_wrlock: function() { return 0; }, |
| pthread_rwlock_trywrlock: function() { return 0; }, |
| pthread_rwlock_timedwrlock: function() { return 0; }, |
| pthread_rwlock_unlock: function() { return 0; }, |
| |
| pthread_rwlockattr_init: function() { return 0; }, |
| pthread_rwlockattr_destroy: function() { return 0; }, |
| pthread_rwlockattr_setpshared: function() { return 0; }, |
| pthread_rwlockattr_getpshared: function() { return 0; }, |
| |
| pthread_spin_init: function() { return 0; }, |
| pthread_spin_destroy: function() { return 0; }, |
| pthread_spin_lock: function() { return 0; }, |
| pthread_spin_trylock: function() { return 0; }, |
| pthread_spin_unlock: function() { return 0; }, |
| |
| pthread_attr_setdetachstate: function() {}, |
| pthread_attr_setschedparam: function() {}, |
| pthread_attr_setstacksize: function() {}, |
| |
| {{{ USE_LSAN || USE_ASAN ? 'emscripten_builtin_' : '' }}}pthread_create: function() { |
| return {{{ cDefine('EAGAIN') }}}; |
| }, |
| pthread_cancel: function() {}, |
| pthread_exit__deps: ['exit'], |
| pthread_exit: function(status) { |
| _exit(status); |
| }, |
| |
| pthread_equal: function(x, y) { return x == y }, |
| {{{ USE_LSAN ? 'emscripten_builtin_' : '' }}}pthread_join: function() {}, |
| pthread_detach: function() {}, |
| |
| sem_init: function() {}, |
| sem_post: function() {}, |
| sem_wait: function() {}, |
| sem_trywait: function() {}, |
| sem_destroy: function() {}, |
| |
| emscripten_main_browser_thread_id__deps: ['pthread_self'], |
| emscripten_main_browser_thread_id: function() { return _pthread_self(); }, |
| |
| // When pthreads is not enabled, we can't use the Atomics futex api to do proper sleeps, so simulate a busy spin wait loop instead. |
| usleep__deps: ['emscripten_get_now'], |
| usleep: function(useconds) { |
| // int usleep(useconds_t useconds); |
| // http://pubs.opengroup.org/onlinepubs/000095399/functions/usleep.html |
| // We're single-threaded, so use a busy loop. Super-ugly. |
| var start = _emscripten_get_now(); |
| while (_emscripten_get_now() - start < useconds / 1000) { |
| // Do nothing. |
| } |
| }, |
| |
| nanosleep__deps: ['usleep', '$setErrNo'], |
| nanosleep: function(rqtp, rmtp) { |
| // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); |
| if (rqtp === 0) { |
| setErrNo({{{ cDefine('EINVAL') }}}); |
| return -1; |
| } |
| var seconds = {{{ makeGetValue('rqtp', C_STRUCTS.timespec.tv_sec, 'i32') }}}; |
| var nanoseconds = {{{ makeGetValue('rqtp', C_STRUCTS.timespec.tv_nsec, 'i32') }}}; |
| if (nanoseconds < 0 || nanoseconds > 999999999 || seconds < 0) { |
| setErrNo({{{ cDefine('EINVAL') }}}); |
| return -1; |
| } |
| if (rmtp !== 0) { |
| {{{ makeSetValue('rmtp', C_STRUCTS.timespec.tv_sec, '0', 'i32') }}}; |
| {{{ makeSetValue('rmtp', C_STRUCTS.timespec.tv_nsec, '0', 'i32') }}}; |
| } |
| return _usleep((seconds * 1e6) + (nanoseconds / 1000)); |
| }, |
| |
| llvm_memory_barrier: function(){}, |
| |
| llvm_atomic_load_add_i32_p0i32: function(ptr, delta) { |
| var ret = {{{ makeGetValue('ptr', '0', 'i32') }}}; |
| {{{ makeSetValue('ptr', '0', 'ret+delta', 'i32') }}}; |
| return ret; |
| }, |
| |
| // TODO(sbc): Remove these helpers and move them and thier callers into |
| // native code instream. |
| i64Add__asm: true, |
| i64Add__sig: 'iiiii', |
| i64Add: function(a, b, c, d) { |
| /* |
| x = a + b*2^32 |
| y = c + d*2^32 |
| result = l + h*2^32 |
| */ |
| a = a|0; b = b|0; c = c|0; d = d|0; |
| var l = 0, h = 0; |
| l = (a + c)>>>0; |
| h = (b + d + (((l>>>0) < (a>>>0))|0))>>>0; // Add carry from low word to high word on overflow. |
| {{{ makeStructuralReturn(['l|0', 'h'], true) }}}; |
| }, |
| |
| i64Subtract__asm: true, |
| i64Subtract__sig: 'iiiii', |
| i64Subtract: function(a, b, c, d) { |
| a = a|0; b = b|0; c = c|0; d = d|0; |
| var l = 0, h = 0; |
| l = (a - c)>>>0; |
| h = (b - d)>>>0; |
| h = (b - d - (((c>>>0) > (a>>>0))|0))>>>0; // Borrow one from high word to low word on underflow. |
| {{{ makeStructuralReturn(['l|0', 'h'], true) }}}; |
| }, |
| |
| // gnu atomics |
| |
| __atomic_is_lock_free: function(size, ptr) { |
| return size <= 4 && (size & (size-1)) == 0 && (ptr&(size-1)) == 0; |
| }, |
| |
| __atomic_load_8: function(ptr, memmodel) { |
| {{{ makeStructuralReturn([makeGetValue('ptr', 0, 'i32'), makeGetValue('ptr', 4, 'i32')]) }}}; |
| }, |
| |
| __atomic_store_8: function(ptr, vall, valh, memmodel) { |
| {{{ makeSetValue('ptr', 0, 'vall', 'i32') }}}; |
| {{{ makeSetValue('ptr', 4, 'valh', 'i32') }}}; |
| }, |
| |
| __atomic_exchange_8: function(ptr, vall, valh, memmodel) { |
| var l = {{{ makeGetValue('ptr', 0, 'i32') }}}; |
| var h = {{{ makeGetValue('ptr', 4, 'i32') }}}; |
| {{{ makeSetValue('ptr', 0, 'vall', 'i32') }}}; |
| {{{ makeSetValue('ptr', 4, 'valh', 'i32') }}}; |
| {{{ makeStructuralReturn(['l', 'h']) }}}; |
| }, |
| |
| __atomic_compare_exchange_8: function(ptr, expected, desiredl, desiredh, weak, success_memmodel, failure_memmodel) { |
| var pl = {{{ makeGetValue('ptr', 0, 'i32') }}}; |
| var ph = {{{ makeGetValue('ptr', 4, 'i32') }}}; |
| var el = {{{ makeGetValue('expected', 0, 'i32') }}}; |
| var eh = {{{ makeGetValue('expected', 4, 'i32') }}}; |
| if (pl === el && ph === eh) { |
| {{{ makeSetValue('ptr', 0, 'desiredl', 'i32') }}}; |
| {{{ makeSetValue('ptr', 4, 'desiredh', 'i32') }}}; |
| return 1; |
| } else { |
| {{{ makeSetValue('expected', 0, 'pl', 'i32') }}}; |
| {{{ makeSetValue('expected', 4, 'ph', 'i32') }}}; |
| return 0; |
| } |
| }, |
| |
| __atomic_fetch_add_8__deps: ['i64Add'], |
| __atomic_fetch_add_8: function(ptr, vall, valh, memmodel) { |
| var l = {{{ makeGetValue('ptr', 0, 'i32') }}}; |
| var h = {{{ makeGetValue('ptr', 4, 'i32') }}}; |
| {{{ makeSetValue('ptr', 0, '_i64Add(l, h, vall, valh)', 'i32') }}}; |
| {{{ makeSetValue('ptr', 4, 'getTempRet0()', 'i32') }}}; |
| {{{ makeStructuralReturn(['l', 'h']) }}}; |
| }, |
| |
| __atomic_fetch_sub_8__deps: ['i64Subtract'], |
| __atomic_fetch_sub_8: function(ptr, vall, valh, memmodel) { |
| var l = {{{ makeGetValue('ptr', 0, 'i32') }}}; |
| var h = {{{ makeGetValue('ptr', 4, 'i32') }}}; |
| {{{ makeSetValue('ptr', 0, '_i64Subtract(l, h, vall, valh)', 'i32') }}}; |
| {{{ makeSetValue('ptr', 4, 'getTempRet0()', 'i32') }}}; |
| {{{ makeStructuralReturn(['l', 'h']) }}}; |
| }, |
| |
| __atomic_fetch_and_8__deps: ['i64Subtract'], |
| __atomic_fetch_and_8: function(ptr, vall, valh, memmodel) { |
| var l = {{{ makeGetValue('ptr', 0, 'i32') }}}; |
| var h = {{{ makeGetValue('ptr', 4, 'i32') }}}; |
| {{{ makeSetValue('ptr', 0, 'l&vall', 'i32') }}}; |
| {{{ makeSetValue('ptr', 4, 'h&valh', 'i32') }}}; |
| {{{ makeStructuralReturn(['l', 'h']) }}}; |
| }, |
| |
| __atomic_fetch_or_8: function(ptr, vall, valh, memmodel) { |
| var l = {{{ makeGetValue('ptr', 0, 'i32') }}}; |
| var h = {{{ makeGetValue('ptr', 4, 'i32') }}}; |
| {{{ makeSetValue('ptr', 0, 'l|vall', 'i32') }}}; |
| {{{ makeSetValue('ptr', 4, 'h|valh', 'i32') }}}; |
| {{{ makeStructuralReturn(['l', 'h']) }}}; |
| }, |
| |
| __atomic_fetch_xor_8: function(ptr, vall, valh, memmodel) { |
| var l = {{{ makeGetValue('ptr', 0, 'i32') }}}; |
| var h = {{{ makeGetValue('ptr', 4, 'i32') }}}; |
| {{{ makeSetValue('ptr', 0, 'l^vall', 'i32') }}}; |
| {{{ makeSetValue('ptr', 4, 'h^valh', 'i32') }}}; |
| {{{ makeStructuralReturn(['l', 'h']) }}}; |
| }, |
| |
| emscripten_atomic_add_u32__sig: 'iii', |
| emscripten_atomic_add_u32: 'llvm_atomic_load_add_i32_p0i32', |
| |
| emscripten_atomic_load_u64__sig: 'iii', |
| emscripten_atomic_load_u64: '__atomic_load_8', |
| |
| emscripten_atomic_store_u64__sig: 'viiii', |
| emscripten_atomic_store_u64: '__atomic_store_8', |
| |
| emscripten_atomic_cas_u64__sig: 'iiiiiiii', |
| emscripten_atomic_cas_u64: '__atomic_compare_exchange_8', |
| |
| emscripten_atomic_exchange_u64__sig: 'iiiii', |
| emscripten_atomic_exchange_u64: '__atomic_exchange_8', |
| |
| _emscripten_atomic_fetch_and_add_u64__sig: 'iiiii', |
| _emscripten_atomic_fetch_and_add_u64: '__atomic_fetch_add_8', |
| |
| _emscripten_atomic_fetch_and_add_u64__sig: 'iiiii', |
| _emscripten_atomic_fetch_and_add_u64: '__atomic_fetch_add_8', |
| |
| _emscripten_atomic_fetch_and_sub_u64__sig: 'iiiii', |
| _emscripten_atomic_fetch_and_sub_u64: '__atomic_fetch_sub_8', |
| |
| _emscripten_atomic_fetch_and_and_u64__sig: 'iiiii', |
| _emscripten_atomic_fetch_and_and_u64: '__atomic_fetch_and_8', |
| |
| _emscripten_atomic_fetch_and_or_u64__sig: 'iiiii', |
| _emscripten_atomic_fetch_and_or_u64: '__atomic_fetch_or_8', |
| |
| _emscripten_atomic_fetch_and_xor_u64__sig: 'iiiii', |
| _emscripten_atomic_fetch_and_xor_u64: '__atomic_fetch_xor_8', |
| |
| __wait: function() {}, |
| }; |
| |
| mergeInto(LibraryManager.library, LibraryPThreadStub); |