Path: blob/main/system/lib/pthread/library_pthread.c
6171 views
/*1* Copyright 2015 The Emscripten Authors. All rights reserved.2* Emscripten is available under two separate licenses, the MIT license and the3* University of Illinois/NCSA Open Source License. Both these licenses can be4* found in the LICENSE file.5*/67#define _GNU_SOURCE8#include "../internal/libc.h"9#include "../internal/pthread_impl.h"10#include <assert.h>11#include <dirent.h>12#include <errno.h>13#include <fcntl.h>14#include <poll.h>15#include <pthread.h>16#include <stdarg.h>17#include <stdlib.h>18#include <sys/ioctl.h>19#include <sys/mman.h>20#include <sys/socket.h>21#include <sys/stat.h>22#include <sys/statvfs.h>23#include <sys/time.h>24#include <termios.h>25#include <threads.h>26#include <unistd.h>27#include <utime.h>2829#include <emscripten.h>30#include <emscripten/proxying.h>31#include <emscripten/stack.h>32#include <emscripten/threading.h>3334#include "threading_internal.h"35#include "emscripten_internal.h"3637int emscripten_pthread_attr_gettransferredcanvases(const pthread_attr_t* a, const char** str) {38*str = a->_a_transferredcanvases;39return 0;40}4142int emscripten_pthread_attr_settransferredcanvases(pthread_attr_t* a, const char* str) {43a->_a_transferredcanvases = str;44return 0;45}4647int sched_get_priority_max(int policy) {48// Web workers do not actually support prioritizing threads,49// but mimic values that Linux apparently reports, see50// http://man7.org/linux/man-pages/man2/sched_get_priority_min.2.html51if (policy == SCHED_FIFO || policy == SCHED_RR)52return 99;53else54return 0;55}5657int sched_get_priority_min(int policy) {58// Web workers do not actually support prioritizing threads,59// but mimic values that Linux apparently reports, see60// http://man7.org/linux/man-pages/man2/sched_get_priority_min.2.html61if (policy == SCHED_FIFO || policy == SCHED_RR)62return 1;63else64return 0;65}6667int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *restrict attr, int *restrict prioceiling)68{69// Not supported either in Emscripten or musl, return a faked value.70if (prioceiling) *prioceiling = 99;71return 0;72}7374int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling)75{76// Not supported either in Emscripten or musl, return an error.77return EPERM;78}7980static uint32_t dummyZeroAddress = 0;8182void emscripten_thread_sleep(double msecs) {83double now = emscripten_get_now();84double target = now + msecs;8586// If we have less than this many msecs left to wait, busy spin that instead.87double min_ms_slice_to_sleep = 0.1;8889// runtime thread may need to run proxied calls, so sleep in very small slices to be responsive.90double max_ms_slice_to_sleep = emscripten_is_main_runtime_thread() ? 1 : 100;9192emscripten_conditional_set_current_thread_status(93EM_THREAD_STATUS_RUNNING, EM_THREAD_STATUS_SLEEPING);9495do {96// Keep processing the main loop of the calling thread.97__pthread_testcancel(); // pthreads spec: sleep is a cancellation point, so must test if this98// thread is cancelled during the sleep.99emscripten_current_thread_process_queued_calls();100101now = emscripten_get_now();102double ms_to_sleep = target - now;103if (ms_to_sleep < min_ms_slice_to_sleep)104continue;105if (ms_to_sleep > max_ms_slice_to_sleep)106ms_to_sleep = max_ms_slice_to_sleep;107emscripten_futex_wait(&dummyZeroAddress, 0, ms_to_sleep);108now = emscripten_get_now();109} while (now < target);110111emscripten_conditional_set_current_thread_status(112EM_THREAD_STATUS_SLEEPING, EM_THREAD_STATUS_RUNNING);113}114115static struct pthread __main_pthread;116117pthread_t emscripten_main_runtime_thread_id() {118return &__main_pthread;119}120121void emscripten_current_thread_process_queued_calls() {122emscripten_proxy_execute_queue(emscripten_proxy_get_system_queue());123}124125void emscripten_main_thread_process_queued_calls() {126assert(emscripten_is_main_runtime_thread());127emscripten_current_thread_process_queued_calls();128}129130int _emscripten_thread_is_valid(pthread_t thread) {131return thread->self == thread;132}133134static void *dummy_tsd[1] = { 0 };135weak_alias(dummy_tsd, __pthread_tsd_main);136137// See system/lib/README.md for static constructor ordering.138__attribute__((constructor(48)))139void _emscripten_init_main_thread(void) {140// The pthread struct has a field that points to itself - this is used as141// a magic ID to detect whether the pthread_t structure is 'alive'.142__main_pthread.self = &__main_pthread;143__main_pthread.detach_state = DT_JOINABLE;144// pthread struct robust_list head should point to itself.145__main_pthread.robust_list.head = &__main_pthread.robust_list.head;146// Main thread ID is always 1. It can't be 0 because musl assumes147// tid is always non-zero.148__main_pthread.tid = getpid();149__main_pthread.locale = &libc.global_locale;150// pthread struct prev and next should initially point to itself (see __init_tp),151// this is used by pthread_key_delete for deleting thread-specific data.152__main_pthread.next = __main_pthread.prev = &__main_pthread;153__main_pthread.tsd = (void **)__pthread_tsd_main;154155_emscripten_init_main_thread_js(&__main_pthread);156157__main_pthread.stack = (void*)emscripten_stack_get_base();158__main_pthread.stack_size = emscripten_stack_get_base() - emscripten_stack_get_end();159160_emscripten_thread_mailbox_init(&__main_pthread);161_emscripten_thread_mailbox_await(&__main_pthread);162}163164165