| /* |
| * Copyright 2021 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. |
| */ |
| |
| #pragma once |
| |
| #include <emscripten/proxying.h> |
| |
| #include <inttypes.h> |
| #include <pthread.h> |
| #include <stdbool.h> |
| |
| // Defined THREADING_DEBUG here (or in the build system) to enabled verbose |
| // logging using emscripten_dbgf. |
| // #define THREADING_DEBUG |
| |
| #ifdef THREADING_DEBUG |
| #define DBG(format, ...) emscripten_dbgf(format, ##__VA_ARGS__) |
| #else |
| #define DBG(format, ...) |
| #endif |
| |
| #define EM_THREAD_NAME_MAX 32 |
| |
| #define EM_THREAD_STATUS int |
| #define EM_THREAD_STATUS_NOTSTARTED 0 |
| #define EM_THREAD_STATUS_RUNNING 1 |
| #define EM_THREAD_STATUS_SLEEPING 2 // Performing an unconditional sleep (usleep, etc.) |
| #define EM_THREAD_STATUS_WAITFUTEX 3 // Waiting for an explicit low-level futex (emscripten_futex_wait) |
| #define EM_THREAD_STATUS_WAITMUTEX 4 // Waiting for a pthread_mutex_t |
| #define EM_THREAD_STATUS_WAITPROXY 5 // Waiting for a proxied operation to finish. |
| #define EM_THREAD_STATUS_FINISHED 6 |
| #define EM_THREAD_STATUS_NUMFIELDS 7 |
| |
| typedef struct thread_profiler_block { |
| // One of THREAD_STATUS_* |
| _Atomic int threadStatus; |
| // Wallclock time denoting when the current thread state was entered in. |
| double currentStatusStartTime; |
| // Accumulated duration times denoting how much time has been spent in each |
| // state, in msecs. |
| double timeSpentInStatus[EM_THREAD_STATUS_NUMFIELDS]; |
| // A human-readable name for this thread. |
| char name[EM_THREAD_NAME_MAX]; |
| } thread_profiler_block; |
| |
| // Called whenever a thread performs a blocking action (or calls sched_yield). |
| // This function takes care of running the event queue and other housekeeping |
| // tasks. |
| // |
| // If the caller already knows the current time it can pass it via the now |
| // argument. This can save _emscripten_check_timers from needing to call out to |
| // JS to get the current time. Passing 0 means that caller doesn't know the |
| // current time. |
| // |
| // Returns true is a timer was fired, false otherwise. |
| bool _emscripten_yield(double now); |
| |
| void _emscripten_init_main_thread_js(void* tb); |
| void _emscripten_thread_profiler_enable(); |
| void _emscripten_thread_cleanup(pthread_t thread); |
| |
| hidden void* _emscripten_tls_init(void); |
| hidden void _emscripten_tls_free(void); |
| |
| // Marks the given thread as strongly referenced. This is used to prevent the |
| // Node.js application from exiting as long as there are strongly referenced |
| // threads still running. Normally you don't need to call this function, and |
| // the pthread behaviour will match native in that background threads won't |
| // keep runtime alive, but waiting for them via e.g. pthread_join will. |
| // However, this is useful for features like PROXY_TO_PTHREAD where we want to |
| // keep running as long as the detached pthread is. |
| void _emscripten_thread_set_strongref(pthread_t thread); |
| |
| // Checks certain structural invariants. This allows us to detect when |
| // already-freed threads are used in some APIs. Technically this is undefined |
| // behaviour, but we have a couple of places where we add these checks so that |
| // we can pass more of the posixtest suite than vanilla musl. |
| int _emscripten_thread_is_valid(pthread_t thread); |
| |
| void _emscripten_thread_exit_joinable(pthread_t thread); |
| void _emscripten_thread_exit(void* result); |
| void _emscripten_process_dlopen_queue(void); |
| extern em_proxying_queue* _Atomic _dlopen_proxying_queue; |
| |
| #if !defined(__EMSCRIPTEN_PTHREADS__) || defined(NDEBUG) |
| #define emscripten_set_current_thread_status(newStatus) |
| #define emscripten_conditional_set_current_thread_status(expectedStatus, newStatus) |
| #else |
| // Allocate the thread profile block for the given thread. |
| void _emscripten_thread_profiler_init(pthread_t thread); |
| |
| // Sets the profiler status of the calling thread. This is a no-op if thread |
| // profiling is not active. |
| // This is an internal function and generally not intended for user code. |
| // When thread profiler is not enabled (not building with --threadprofiler), |
| // this is a no-op. |
| void emscripten_set_current_thread_status(EM_THREAD_STATUS newStatus); |
| |
| // Sets the profiler status of the calling thread, but only if it was in the |
| // expected status beforehand. |
| // This is an internal function and generally not intended for user code. |
| // When thread profiler is not enabled (not building with --threadprofiler), |
| // this is a no-op. |
| void emscripten_conditional_set_current_thread_status(EM_THREAD_STATUS expectedStatus, EM_THREAD_STATUS newStatus); |
| #endif |
| |
| int __pthread_kill_js(pthread_t t, int sig); |
| int __pthread_create_js(pthread_t thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); |
| void __set_thread_state(pthread_t ptr, int is_main, int is_runtime, int can_block); |
| |
| double _emscripten_receive_on_main_thread_js(int funcIndex, void* emAsmAddr, pthread_t callingThread, int numCallArgs, double* args, void* ctx, void* ctxArgs); |
| |
| void _emscripten_run_js_on_main_thread_done(void* ctx, void* arg, double result); |
| |
| // Return non-zero if the calling thread supports Atomic.wait (For example |
| // if called from the main browser thread, this function will return zero |
| // since blocking is not allowed there). |
| int _emscripten_thread_supports_atomics_wait(void); |
| |
| pid_t _emscripten_get_next_tid(); |
| |
| // Initialize pthread data, at start of memory region pointed to `base`. |
| // `size` is an in/out parameter representing the size of the `base` region |
| // on input, and the size of new/adjusted region on output. |
| // Return a new/adjusted memory base to be used to stack/tls data. |
| void* _emscripten_init_pthread(void *base, size_t* size, pid_t tid); |
| |
| // Wake the target thread in case it is blocked in emscripten_futex_wait. |
| // Note: If threads directly use lower level APIs such |
| // __builtin_wasm_memory_atomic_waitXX then they will not be woken by |
| // this method. |
| void _emscripten_thread_notify(pthread_t thread); |
| |
| // Internal, promise-returning API used to implement |
| // emscripten_atomic_wait_suspending. |
| intptr_t _emscripten_atomic_wait_promise(volatile void *addr, |
| uint32_t value, |
| double maxWaitMilliseconds); |
| |
| // Internal function used in wasm worker builds (included here solely for |
| // gen_sig_info.py). |
| void __do_set_thread_state(void); |