| |
| |
| |
| |
| |
| |
|
|
| #define _GNU_SOURCE |
| #include "../internal/libc.h" |
| #include "../internal/pthread_impl.h" |
| #include <assert.h> |
| #include <dirent.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <poll.h> |
| #include <pthread.h> |
| #include <stdarg.h> |
| #include <stdlib.h> |
| #include <sys/ioctl.h> |
| #include <sys/mman.h> |
| #include <sys/socket.h> |
| #include <sys/stat.h> |
| #include <sys/statvfs.h> |
| #include <sys/time.h> |
| #include <termios.h> |
| #include <threads.h> |
| #include <unistd.h> |
| #include <utime.h> |
|
|
| #include <emscripten.h> |
| #include <emscripten/proxying.h> |
| #include <emscripten/stack.h> |
| #include <emscripten/threading.h> |
|
|
| #include "threading_internal.h" |
| #include "emscripten_internal.h" |
|
|
| int emscripten_pthread_attr_gettransferredcanvases(const pthread_attr_t* a, const char** str) { |
| *str = a->_a_transferredcanvases; |
| return 0; |
| } |
|
|
| int emscripten_pthread_attr_settransferredcanvases(pthread_attr_t* a, const char* str) { |
| a->_a_transferredcanvases = str; |
| return 0; |
| } |
|
|
| int sched_get_priority_max(int policy) { |
| |
| |
| |
| if (policy == SCHED_FIFO || policy == SCHED_RR) |
| return 99; |
| else |
| return 0; |
| } |
|
|
| int sched_get_priority_min(int policy) { |
| |
| |
| |
| if (policy == SCHED_FIFO || policy == SCHED_RR) |
| return 1; |
| else |
| return 0; |
| } |
|
|
| int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *restrict attr, int *restrict prioceiling) { |
| |
| if (prioceiling) *prioceiling = 99; |
| return 0; |
| } |
|
|
| int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling) { |
| |
| return EPERM; |
| } |
|
|
| void emscripten_thread_sleep(double msecs) { |
| |
| |
| |
| |
| emscripten_current_thread_process_queued_calls(); |
| __pthread_testcancel(); |
| if (msecs > 0) { |
| uint32_t dummyZeroAddress = 0; |
| double start = emscripten_get_now(); |
| double elapsed = 0; |
| while (elapsed < msecs) { |
| emscripten_conditional_set_current_thread_status(EM_THREAD_STATUS_RUNNING, |
| EM_THREAD_STATUS_SLEEPING); |
| emscripten_futex_wait(&dummyZeroAddress, 0, msecs - elapsed); |
| emscripten_conditional_set_current_thread_status(EM_THREAD_STATUS_SLEEPING, |
| EM_THREAD_STATUS_RUNNING); |
| emscripten_current_thread_process_queued_calls(); |
| __pthread_testcancel(); |
| elapsed = emscripten_get_now() - start; |
| } |
| } |
| } |
|
|
| static struct pthread __main_pthread; |
|
|
| pthread_t emscripten_main_runtime_thread_id() { |
| return &__main_pthread; |
| } |
|
|
| void emscripten_current_thread_process_queued_calls() { |
| emscripten_proxy_execute_queue(emscripten_proxy_get_system_queue()); |
| } |
|
|
| void emscripten_main_thread_process_queued_calls() { |
| assert(emscripten_is_main_runtime_thread()); |
| emscripten_current_thread_process_queued_calls(); |
| } |
|
|
| int _emscripten_thread_is_valid(pthread_t thread) { |
| return thread->self == thread; |
| } |
|
|
| static void *dummy_tsd[1] = { 0 }; |
| weak_alias(dummy_tsd, __pthread_tsd_main); |
|
|
| |
| __attribute__((constructor(48))) |
| void _emscripten_init_main_thread(void) { |
| |
| |
| __main_pthread.self = &__main_pthread; |
| __main_pthread.detach_state = DT_JOINABLE; |
| |
| __main_pthread.robust_list.head = &__main_pthread.robust_list.head; |
| |
| |
| __main_pthread.tid = getpid(); |
| |
| |
| __main_pthread.next = __main_pthread.prev = &__main_pthread; |
| __main_pthread.tsd = (void **)__pthread_tsd_main; |
|
|
| _emscripten_init_main_thread_js(&__main_pthread); |
|
|
| __main_pthread.stack = (void*)emscripten_stack_get_base(); |
| __main_pthread.stack_size = emscripten_stack_get_base() - emscripten_stack_get_end(); |
|
|
| _emscripten_thread_mailbox_init(&__main_pthread); |
| _emscripten_thread_mailbox_await(&__main_pthread); |
| } |
|
|