1 #include <errno.h>
2 #include <pthread.h>
3 #include <stdint.h>
4 #include <stdlib.h>
5 
emscripten_has_threading_support()6 int emscripten_has_threading_support() { return 0; }
7 
emscripten_num_logical_cores()8 int emscripten_num_logical_cores() { return 1; }
9 
emscripten_force_num_logical_cores(int cores)10 void emscripten_force_num_logical_cores(int cores) {
11   // no-op, in singlethreaded builds we will always report exactly one core.
12 }
13 
emscripten_atomic_exchange_u8(void * addr,uint8_t newVal)14 uint8_t emscripten_atomic_exchange_u8(void /*uint8_t*/* addr, uint8_t newVal) {
15   uint8_t old = *(uint8_t*)addr;
16   *(uint8_t*)addr = newVal;
17   return old;
18 }
19 
emscripten_atomic_exchange_u16(void * addr,uint16_t newVal)20 uint16_t emscripten_atomic_exchange_u16(void /*uint16_t*/* addr, uint16_t newVal) {
21   uint16_t old = *(uint16_t*)addr;
22   *(uint16_t*)addr = newVal;
23   return old;
24 }
25 
emscripten_atomic_exchange_u32(void * addr,uint32_t newVal)26 uint32_t emscripten_atomic_exchange_u32(void /*uint32_t*/* addr, uint32_t newVal) {
27   uint32_t old = *(uint32_t*)addr;
28   *(uint32_t*)addr = newVal;
29   return old;
30 }
31 
emscripten_atomic_exchange_u64(void * addr,uint64_t newVal)32 uint64_t emscripten_atomic_exchange_u64(void /*uint64_t*/* addr, uint64_t newVal) {
33   uint64_t old = *(uint64_t*)addr;
34   *(uint64_t*)addr = newVal;
35   return old;
36 }
37 
emscripten_atomic_cas_u8(void * addr,uint8_t oldVal,uint8_t newVal)38 uint8_t emscripten_atomic_cas_u8(void /*uint8_t*/* addr, uint8_t oldVal, uint8_t newVal) {
39   uint8_t old = *(uint8_t*)addr;
40   if (old == oldVal)
41     *(uint8_t*)addr = newVal;
42   return old;
43 }
44 
emscripten_atomic_cas_u16(void * addr,uint16_t oldVal,uint16_t newVal)45 uint16_t emscripten_atomic_cas_u16(void /*uint16_t*/* addr, uint16_t oldVal, uint16_t newVal) {
46   uint16_t old = *(uint16_t*)addr;
47   if (old == oldVal)
48     *(uint16_t*)addr = newVal;
49   return old;
50 }
51 
emscripten_atomic_cas_u32(void * addr,uint32_t oldVal,uint32_t newVal)52 uint32_t emscripten_atomic_cas_u32(void /*uint32_t*/* addr, uint32_t oldVal, uint32_t newVal) {
53   uint32_t old = *(uint32_t*)addr;
54   if (old == oldVal)
55     *(uint32_t*)addr = newVal;
56   return old;
57 }
58 
emscripten_atomic_cas_u64(void * addr,uint64_t oldVal,uint64_t newVal)59 uint64_t emscripten_atomic_cas_u64(void /*uint64_t*/* addr, uint64_t oldVal, uint64_t newVal) {
60   uint64_t old = *(uint64_t*)addr;
61   if (old == oldVal)
62     *(uint64_t*)addr = newVal;
63   return old;
64 }
65 
emscripten_atomic_load_u8(const void * addr)66 uint8_t emscripten_atomic_load_u8(const void /*uint8_t*/* addr) { return *(uint8_t*)addr; }
67 
emscripten_atomic_load_u16(const void * addr)68 uint16_t emscripten_atomic_load_u16(const void /*uint16_t*/* addr) { return *(uint16_t*)addr; }
69 
emscripten_atomic_load_u32(const void * addr)70 uint32_t emscripten_atomic_load_u32(const void /*uint32_t*/* addr) { return *(uint32_t*)addr; }
71 
emscripten_atomic_load_f32(const void * addr)72 float emscripten_atomic_load_f32(const void /*float*/* addr) { return *(float*)addr; }
73 
emscripten_atomic_load_u64(const void * addr)74 uint64_t emscripten_atomic_load_u64(const void /*uint64_t*/* addr) { return *(uint64_t*)addr; }
75 
emscripten_atomic_load_f64(const void * addr)76 double emscripten_atomic_load_f64(const void /*double*/* addr) { return *(double*)addr; }
77 
emscripten_atomic_store_u8(void * addr,uint8_t val)78 uint8_t emscripten_atomic_store_u8(void /*uint8_t*/* addr, uint8_t val) {
79   return *(uint8_t*)addr = val;
80 }
81 
emscripten_atomic_store_u16(void * addr,uint16_t val)82 uint16_t emscripten_atomic_store_u16(void /*uint16_t*/* addr, uint16_t val) {
83   return *(uint16_t*)addr = val;
84 }
85 
emscripten_atomic_store_u32(void * addr,uint32_t val)86 uint32_t emscripten_atomic_store_u32(void /*uint32_t*/* addr, uint32_t val) {
87   return *(uint32_t*)addr = val;
88 }
89 
emscripten_atomic_store_f32(void * addr,float val)90 float emscripten_atomic_store_f32(void /*float*/* addr, float val) { return *(float*)addr = val; }
91 
emscripten_atomic_store_u64(void * addr,uint64_t val)92 uint64_t emscripten_atomic_store_u64(void /*uint64_t*/* addr, uint64_t val) {
93   return *(uint64_t*)addr = val;
94 }
95 
emscripten_atomic_store_f64(void * addr,double val)96 double emscripten_atomic_store_f64(void /*double*/* addr, double val) {
97   return *(double*)addr = val;
98 }
99 
emscripten_atomic_fence()100 void emscripten_atomic_fence() {
101   // nop
102 }
103 
emscripten_atomic_add_u8(void * addr,uint8_t val)104 uint8_t emscripten_atomic_add_u8(void /*uint8_t*/* addr, uint8_t val) {
105   uint8_t old = *(uint8_t*)addr;
106   *(uint8_t*)addr = old + val;
107   return old;
108 }
109 
emscripten_atomic_add_u16(void * addr,uint16_t val)110 uint16_t emscripten_atomic_add_u16(void /*uint16_t*/* addr, uint16_t val) {
111   uint16_t old = *(uint16_t*)addr;
112   *(uint16_t*)addr = old + val;
113   return old;
114 }
115 
emscripten_atomic_add_u32(void * addr,uint32_t val)116 uint32_t emscripten_atomic_add_u32(void /*uint32_t*/* addr, uint32_t val) {
117   uint32_t old = *(uint32_t*)addr;
118   *(uint32_t*)addr = old + val;
119   return old;
120 }
121 
emscripten_atomic_add_u64(void * addr,uint64_t val)122 uint64_t emscripten_atomic_add_u64(void /*uint64_t*/* addr, uint64_t val) {
123   uint64_t old = *(uint64_t*)addr;
124   *(uint64_t*)addr = old + val;
125   return old;
126 }
127 
emscripten_atomic_sub_u8(void * addr,uint8_t val)128 uint8_t emscripten_atomic_sub_u8(void /*uint8_t*/* addr, uint8_t val) {
129   uint8_t old = *(uint8_t*)addr;
130   *(uint8_t*)addr = old - val;
131   return old;
132 }
133 
emscripten_atomic_sub_u16(void * addr,uint16_t val)134 uint16_t emscripten_atomic_sub_u16(void /*uint16_t*/* addr, uint16_t val) {
135   uint16_t old = *(uint16_t*)addr;
136   *(uint16_t*)addr = old - val;
137   return old;
138 }
139 
emscripten_atomic_sub_u32(void * addr,uint32_t val)140 uint32_t emscripten_atomic_sub_u32(void /*uint32_t*/* addr, uint32_t val) {
141   uint32_t old = *(uint32_t*)addr;
142   *(uint32_t*)addr = old - val;
143   return old;
144 }
145 
emscripten_atomic_sub_u64(void * addr,uint64_t val)146 uint64_t emscripten_atomic_sub_u64(void /*uint64_t*/* addr, uint64_t val) {
147   uint64_t old = *(uint64_t*)addr;
148   *(uint64_t*)addr = old - val;
149   return old;
150 }
151 
emscripten_atomic_and_u8(void * addr,uint8_t val)152 uint8_t emscripten_atomic_and_u8(void /*uint8_t*/* addr, uint8_t val) {
153   uint8_t old = *(uint8_t*)addr;
154   *(uint8_t*)addr = old & val;
155   return old;
156 }
157 
emscripten_atomic_and_u16(void * addr,uint16_t val)158 uint16_t emscripten_atomic_and_u16(void /*uint16_t*/* addr, uint16_t val) {
159   uint16_t old = *(uint16_t*)addr;
160   *(uint16_t*)addr = old & val;
161   return old;
162 }
163 
emscripten_atomic_and_u32(void * addr,uint32_t val)164 uint32_t emscripten_atomic_and_u32(void /*uint32_t*/* addr, uint32_t val) {
165   uint32_t old = *(uint32_t*)addr;
166   *(uint32_t*)addr = old & val;
167   return old;
168 }
169 
emscripten_atomic_and_u64(void * addr,uint64_t val)170 uint64_t emscripten_atomic_and_u64(void /*uint64_t*/* addr, uint64_t val) {
171   uint64_t old = *(uint64_t*)addr;
172   *(uint64_t*)addr = old & val;
173   return old;
174 }
175 
emscripten_atomic_or_u8(void * addr,uint8_t val)176 uint8_t emscripten_atomic_or_u8(void /*uint8_t*/* addr, uint8_t val) {
177   uint8_t old = *(uint8_t*)addr;
178   *(uint8_t*)addr = old | val;
179   return old;
180 }
181 
emscripten_atomic_or_u16(void * addr,uint16_t val)182 uint16_t emscripten_atomic_or_u16(void /*uint16_t*/* addr, uint16_t val) {
183   uint16_t old = *(uint16_t*)addr;
184   *(uint16_t*)addr = old | val;
185   return old;
186 }
187 
emscripten_atomic_or_u32(void * addr,uint32_t val)188 uint32_t emscripten_atomic_or_u32(void /*uint32_t*/* addr, uint32_t val) {
189   uint32_t old = *(uint32_t*)addr;
190   *(uint32_t*)addr = old | val;
191   return old;
192 }
193 
emscripten_atomic_or_u64(void * addr,uint64_t val)194 uint64_t emscripten_atomic_or_u64(void /*uint64_t*/* addr, uint64_t val) {
195   uint64_t old = *(uint64_t*)addr;
196   *(uint64_t*)addr = old | val;
197   return old;
198 }
199 
emscripten_atomic_xor_u8(void * addr,uint8_t val)200 uint8_t emscripten_atomic_xor_u8(void /*uint8_t*/* addr, uint8_t val) {
201   uint8_t old = *(uint8_t*)addr;
202   *(uint8_t*)addr = old ^ val;
203   return old;
204 }
205 
emscripten_atomic_xor_u16(void * addr,uint16_t val)206 uint16_t emscripten_atomic_xor_u16(void /*uint16_t*/* addr, uint16_t val) {
207   uint16_t old = *(uint16_t*)addr;
208   *(uint16_t*)addr = old ^ val;
209   return old;
210 }
211 
emscripten_atomic_xor_u32(void * addr,uint32_t val)212 uint32_t emscripten_atomic_xor_u32(void /*uint32_t*/* addr, uint32_t val) {
213   uint32_t old = *(uint32_t*)addr;
214   *(uint32_t*)addr = old ^ val;
215   return old;
216 }
217 
emscripten_atomic_xor_u64(void * addr,uint64_t val)218 uint64_t emscripten_atomic_xor_u64(void /*uint64_t*/* addr, uint64_t val) {
219   uint64_t old = *(uint64_t*)addr;
220   *(uint64_t*)addr = old ^ val;
221   return old;
222 }
223 
_emscripten_atomic_fetch_and_add_u64(void * addr,uint64_t val)224 uint64_t _emscripten_atomic_fetch_and_add_u64(void* addr, uint64_t val) {
225   return emscripten_atomic_add_u64(addr, val);
226 }
227 
_emscripten_atomic_fetch_and_sub_u64(void * addr,uint64_t val)228 uint64_t _emscripten_atomic_fetch_and_sub_u64(void* addr, uint64_t val) {
229   return emscripten_atomic_sub_u64(addr, val);
230 }
231 
_emscripten_atomic_fetch_and_and_u64(void * addr,uint64_t val)232 uint64_t _emscripten_atomic_fetch_and_and_u64(void* addr, uint64_t val) {
233   return emscripten_atomic_and_u64(addr, val);
234 }
235 
_emscripten_atomic_fetch_and_or_u64(void * addr,uint64_t val)236 uint64_t _emscripten_atomic_fetch_and_or_u64(void* addr, uint64_t val) {
237   return emscripten_atomic_or_u64(addr, val);
238 }
239 
_emscripten_atomic_fetch_and_xor_u64(void * addr,uint64_t val)240 uint64_t _emscripten_atomic_fetch_and_xor_u64(void* addr, uint64_t val) {
241   return emscripten_atomic_xor_u64(addr, val);
242 }
243 
emscripten_futex_wait(volatile void * addr,uint32_t val,double maxWaitMilliseconds)244 int emscripten_futex_wait(
245   volatile void /*uint32_t*/* addr, uint32_t val, double maxWaitMilliseconds) {
246   // nop
247   return 0; // success
248 }
249 
emscripten_futex_wake(volatile void * addr,int count)250 int emscripten_futex_wake(volatile void /*uint32_t*/* addr, int count) {
251   // nop
252   return 0; // success
253 }
254 
emscripten_is_main_runtime_thread()255 int emscripten_is_main_runtime_thread() { return 1; }
256 
emscripten_main_thread_process_queued_calls()257 void emscripten_main_thread_process_queued_calls() {
258   // nop
259 }
260 
emscripten_current_thread_process_queued_calls()261 void emscripten_current_thread_process_queued_calls() {
262   // nop
263 }
264 
pthread_mutex_init(pthread_mutex_t * __restrict mutex,const pthread_mutexattr_t * __restrict attr)265 int pthread_mutex_init(
266   pthread_mutex_t* __restrict mutex, const pthread_mutexattr_t* __restrict attr) {
267   return 0;
268 }
269 
270 #ifndef EMSCRIPTEN_ASAN_OVERRIDE
pthread_mutex_lock(pthread_mutex_t * mutex)271 int pthread_mutex_lock(pthread_mutex_t* mutex) { return 0; }
272 
pthread_mutex_unlock(pthread_mutex_t * mutex)273 int pthread_mutex_unlock(pthread_mutex_t* mutex) { return 0; }
274 #endif
275 
pthread_mutex_trylock(pthread_mutex_t * mutex)276 int pthread_mutex_trylock(pthread_mutex_t* mutex) { return 0; }
277 
278 struct timespec;
279 
pthread_mutex_timedlock(pthread_mutex_t * __restrict mutex,const struct timespec * __restrict t)280 int pthread_mutex_timedlock(
281   pthread_mutex_t* __restrict mutex, const struct timespec* __restrict t) {
282   return 0;
283 }
284 
pthread_mutex_destroy(pthread_mutex_t * mutex)285 int pthread_mutex_destroy(pthread_mutex_t* mutex) { return 0; }
286 
pthread_mutex_consistent(pthread_mutex_t * mutex)287 int pthread_mutex_consistent(pthread_mutex_t* mutex) { return 0; }
288 
pthread_barrier_init(pthread_barrier_t * __restrict mutex,const pthread_barrierattr_t * __restrict attr,unsigned u)289 int pthread_barrier_init(
290   pthread_barrier_t* __restrict mutex, const pthread_barrierattr_t* __restrict attr, unsigned u) {
291   return 0;
292 }
293 
pthread_barrier_destroy(pthread_barrier_t * mutex)294 int pthread_barrier_destroy(pthread_barrier_t* mutex) { return 0; }
295 
pthread_barrier_wait(pthread_barrier_t * mutex)296 int pthread_barrier_wait(pthread_barrier_t* mutex) { return 0; }
297 
298 /* magic value to track a validly constructed TLS slot */
299 #define PTHREAD_TLS_MAGIC_ID 0x02468ACE
300 
pthread_key_create(pthread_key_t * key,void (* destructor)(void *))301 int pthread_key_create(pthread_key_t* key, void (*destructor)(void*)) {
302   if (key == 0)
303     return EINVAL;
304   uintptr_t* tls = (uintptr_t*)malloc(sizeof(uintptr_t) * 2);
305   tls[0] = 0;
306   tls[1] = PTHREAD_TLS_MAGIC_ID;
307   *key = (pthread_key_t)tls;
308   return 0;
309 }
310 
pthread_key_delete(pthread_key_t key)311 int pthread_key_delete(pthread_key_t key) {
312   uintptr_t* tls = (uintptr_t*)key;
313   if (tls[1] != PTHREAD_TLS_MAGIC_ID)
314     return EINVAL;
315   tls[0] = tls[1] = 0;
316   free(tls);
317   return 0;
318 }
319 
pthread_getspecific(pthread_key_t key)320 void* pthread_getspecific(pthread_key_t key) {
321   uintptr_t* tls = (uintptr_t*)key;
322   if (tls[1] != PTHREAD_TLS_MAGIC_ID)
323     return NULL;
324   return (void*)tls[0];
325 }
326 
pthread_setspecific(pthread_key_t key,const void * value)327 int pthread_setspecific(pthread_key_t key, const void* value) {
328   uintptr_t* tls = (uintptr_t*)key;
329   if (tls[1] != PTHREAD_TLS_MAGIC_ID)
330     return EINVAL;
331   tls[0] = (uintptr_t)value;
332   return 0;
333 }
334 
335 /*magic number to detect if we have not run yet*/
336 #define PTHREAD_ONCE_MAGIC_ID 0x13579BDF
337 
pthread_once(pthread_once_t * once_control,void (* init_routine)(void))338 int pthread_once(pthread_once_t* once_control, void (*init_routine)(void)) {
339   if (*once_control != PTHREAD_ONCE_MAGIC_ID) {
340     init_routine();
341     *once_control = PTHREAD_ONCE_MAGIC_ID;
342   }
343   return 0;
344 }
345 
pthread_cond_wait(pthread_cond_t * cond,pthread_mutex_t * mutex)346 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
347   return 0;
348 }
349 
pthread_cond_signal(pthread_cond_t * cond)350 int pthread_cond_signal(pthread_cond_t *cond) {
351   return 0;
352 }
353 
pthread_cond_broadcast(pthread_cond_t * cond)354 int pthread_cond_broadcast(pthread_cond_t *cond) {
355   return 0;
356 }
357 
pthread_cond_init(pthread_cond_t * __restrict x,const pthread_condattr_t * __restrict y)358 int pthread_cond_init(pthread_cond_t *__restrict x, const pthread_condattr_t *__restrict y) {
359   return 0;
360 }
361 
pthread_cond_destroy(pthread_cond_t * x)362 int pthread_cond_destroy(pthread_cond_t * x) {
363   return 0;
364 }
365 
pthread_cond_timedwait(pthread_cond_t * __restrict x,pthread_mutex_t * __restrict y,const struct timespec * __restrict z)366 int pthread_cond_timedwait(pthread_cond_t *__restrict x, pthread_mutex_t *__restrict y, const struct timespec *__restrict z) {
367   return 0;
368 }
369 
pthread_atfork(void (* prepare)(void),void (* parent)(void),void (* child)(void))370 int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) {
371   return 0;
372 }
373 
374 // pthread_equal is defined as a macro in C, as a function for C++; undef it
375 // here so we define the function for C++ that links to us.
376 #undef pthread_equal
377 
pthread_equal(pthread_t t1,pthread_t t2)378 int pthread_equal(pthread_t t1, pthread_t t2) {
379   return t1 == t2;
380 }
381