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