1 /*
2  * Copyright 2015 The Emscripten Authors.  All rights reserved.
3  * Emscripten is available under two separate licenses, the MIT license and the
4  * University of Illinois/NCSA Open Source License.  Both these licenses can be
5  * found in the LICENSE file.
6  */
7 
8 #pragma once
9 
10 #include <inttypes.h>
11 #include <pthread.h>
12 #include <emscripten/html5.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 // Returns true if the current browser is able to spawn threads with
19 // pthread_create(), and the compiled page was built with threading support
20 // enabled. If this returns 0, calls to pthread_create() will fail with return
21 // code EAGAIN.
22 int emscripten_has_threading_support(void);
23 
24 // Returns the number of logical cores on the system.
25 int emscripten_num_logical_cores(void);
26 
27 // Configures the number of logical cores on the system. This can be called at
28 // startup to specify the number of cores emscripten_num_logical_cores()
29 // reports. The Emscripten system itself does not use this value internally
30 // anywhere, it is just a hint to help developers have a single access point
31 // 'emscripten_num_logical_cores()' to query the number of cores in the system.
32 void emscripten_force_num_logical_cores(int cores);
33 
34 // Atomically stores the given value to the memory location, and returns the
35 // value that was there prior to the store.
36 uint8_t emscripten_atomic_exchange_u8(void/*uint8_t*/ *addr, uint8_t newVal);
37 uint16_t emscripten_atomic_exchange_u16(void/*uint16_t*/ *addr, uint16_t newVal);
38 uint32_t emscripten_atomic_exchange_u32(void/*uint32_t*/ *addr, uint32_t newVal);
39 uint64_t emscripten_atomic_exchange_u64(void/*uint64_t*/ *addr, uint64_t newVal); // In asm.js/asm2wasm this is emulated with locks, very slow!
40 
41 // CAS returns the *old* value that was in the memory location before the
42 // operation took place.
43 // That is, if the return value when calling this function equals to 'oldVal',
44 // then the operation succeeded, otherwise it was ignored.
45 uint8_t emscripten_atomic_cas_u8(void/*uint8_t*/ *addr, uint8_t oldVal, uint8_t newVal);
46 uint16_t emscripten_atomic_cas_u16(void/*uint16_t*/ *addr, uint16_t oldVal, uint16_t newVal);
47 uint32_t emscripten_atomic_cas_u32(void/*uint32_t*/ *addr, uint32_t oldVal, uint32_t newVal);
48 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
49 // very slow!
50 uint64_t emscripten_atomic_cas_u64(void/*uint64_t*/ *addr, uint64_t oldVal, uint64_t newVal);
51 
52 uint8_t emscripten_atomic_load_u8(const void/*uint8_t*/ *addr);
53 uint16_t emscripten_atomic_load_u16(const void/*uint16_t*/ *addr);
54 uint32_t emscripten_atomic_load_u32(const void/*uint32_t*/ *addr);
55 float emscripten_atomic_load_f32(const void/*float*/ *addr);
56 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
57 // very slow!
58 uint64_t emscripten_atomic_load_u64(const void/*uint64_t*/ *addr);
59 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
60 // very slow!
61 double emscripten_atomic_load_f64(const void/*double*/ *addr);
62 
63 // Returns the value that was stored (i.e. 'val')
64 uint8_t emscripten_atomic_store_u8(void/*uint8_t*/ *addr, uint8_t val);
65 uint16_t emscripten_atomic_store_u16(void/*uint16_t*/ *addr, uint16_t val);
66 uint32_t emscripten_atomic_store_u32(void/*uint32_t*/ *addr, uint32_t val);
67 float emscripten_atomic_store_f32(void/*float*/ *addr, float val);
68 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
69 // very slow!
70 uint64_t emscripten_atomic_store_u64(void/*uint64_t*/ *addr, uint64_t val);
71 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
72 // very slow!
73 double emscripten_atomic_store_f64(void/*double*/ *addr, double val);
74 
75 void emscripten_atomic_fence(void);
76 
77 // Each of the functions below (add, sub, and, or, xor) return the value that
78 // was in the memory location before the operation occurred.
79 uint8_t emscripten_atomic_add_u8(void/*uint8_t*/ *addr, uint8_t val);
80 uint16_t emscripten_atomic_add_u16(void/*uint16_t*/ *addr, uint16_t val);
81 uint32_t emscripten_atomic_add_u32(void/*uint32_t*/ *addr, uint32_t val);
82 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
83 // very slow!
84 uint64_t emscripten_atomic_add_u64(void/*uint64_t*/ *addr, uint64_t val);
85 
86 uint8_t emscripten_atomic_sub_u8(void/*uint8_t*/ *addr, uint8_t val);
87 uint16_t emscripten_atomic_sub_u16(void/*uint16_t*/ *addr, uint16_t val);
88 uint32_t emscripten_atomic_sub_u32(void/*uint32_t*/ *addr, uint32_t val);
89 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
90 // very slow!
91 uint64_t emscripten_atomic_sub_u64(void/*uint64_t*/ *addr, uint64_t val);
92 
93 uint8_t emscripten_atomic_and_u8(void/*uint8_t*/ *addr, uint8_t val);
94 uint16_t emscripten_atomic_and_u16(void/*uint16_t*/ *addr, uint16_t val);
95 uint32_t emscripten_atomic_and_u32(void/*uint32_t*/ *addr, uint32_t val);
96 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
97 // very slow!
98 uint64_t emscripten_atomic_and_u64(void/*uint64_t*/ *addr, uint64_t val);
99 
100 uint8_t emscripten_atomic_or_u8(void/*uint8_t*/ *addr, uint8_t val);
101 uint16_t emscripten_atomic_or_u16(void/*uint16_t*/ *addr, uint16_t val);
102 uint32_t emscripten_atomic_or_u32(void/*uint32_t*/ *addr, uint32_t val);
103 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
104 // very slow!
105 uint64_t emscripten_atomic_or_u64(void/*uint64_t*/ *addr, uint64_t val);
106 
107 uint8_t emscripten_atomic_xor_u8(void/*uint8_t*/ *addr, uint8_t val);
108 uint16_t emscripten_atomic_xor_u16(void/*uint16_t*/ *addr, uint16_t val);
109 uint32_t emscripten_atomic_xor_u32(void/*uint32_t*/ *addr, uint32_t val);
110 // In Wasm, this is a native instruction. In asm.js this is emulated with locks,
111 // very slow!
112 uint64_t emscripten_atomic_xor_u64(void/*uint64_t*/ *addr, uint64_t val);
113 
114 // If the given memory address contains value val, puts the calling thread to
115 // sleep waiting for that address to be notified.
116 int emscripten_futex_wait(volatile void/*uint32_t*/ *addr, uint32_t val, double maxWaitMilliseconds);
117 
118 // Wakes the given number of threads waiting on a location. Pass count ==
119 // INT_MAX to wake all waiters on that location.
120 int emscripten_futex_wake(volatile void/*uint32_t*/ *addr, int count);
121 
122 typedef union em_variant_val
123 {
124   int i;
125   int64_t i64;
126   float f;
127   double d;
128   void *vp;
129   char *cp;
130 } em_variant_val;
131 
132 // Proxied C/C++ functions support at most this many arguments. Dispatch is
133 // static/strongly typed by signature.
134 #define EM_QUEUED_CALL_MAX_ARGS 11
135 // Proxied JS function can support a few more arguments than proxied C/C++
136 // functions, because the dispatch is variadic and signature independent.
137 #define EM_QUEUED_JS_CALL_MAX_ARGS 20
138 typedef struct em_queued_call
139 {
140   int functionEnum;
141   void *functionPtr;
142   int operationDone;
143   em_variant_val args[EM_QUEUED_JS_CALL_MAX_ARGS];
144   em_variant_val returnValue;
145 
146   // An optional pointer to a secondary data block that should be free()d when
147   // this queued call is freed.
148   void *satelliteData;
149 
150   // If true, the caller has "detached" itself from this call object and the
151   // Emscripten main runtime thread should free up this em_queued_call object
152   // after it has been executed. If false, the caller is in control of the
153   // memory.
154   int calleeDelete;
155 } em_queued_call;
156 
157 void emscripten_sync_run_in_main_thread(em_queued_call *call);
158 void *emscripten_sync_run_in_main_thread_0(int function);
159 void *emscripten_sync_run_in_main_thread_1(int function, void *arg1);
160 void *emscripten_sync_run_in_main_thread_2(int function, void *arg1, void *arg2);
161 void *emscripten_sync_run_in_main_thread_3(int function, void *arg1, void *arg2, void *arg3);
162 void *emscripten_sync_run_in_main_thread_7(int function, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7);
163 
164 typedef void (*em_func_v)(void);
165 typedef void (*em_func_vi)(int);
166 typedef void (*em_func_vf)(float);
167 typedef void (*em_func_vii)(int, int);
168 typedef void (*em_func_vif)(int, float);
169 typedef void (*em_func_vff)(float, float);
170 typedef void (*em_func_viii)(int, int, int);
171 typedef void (*em_func_viif)(int, int, float);
172 typedef void (*em_func_viff)(int, float, float);
173 typedef void (*em_func_vfff)(float, float, float);
174 typedef void (*em_func_viiii)(int, int, int, int);
175 typedef void (*em_func_viifi)(int, int, float, int);
176 typedef void (*em_func_vifff)(int, float, float, float);
177 typedef void (*em_func_vffff)(float, float, float, float);
178 typedef void (*em_func_viiiii)(int, int, int, int, int);
179 typedef void (*em_func_viffff)(int, float, float, float, float);
180 typedef void (*em_func_viiiiii)(int, int, int, int, int, int);
181 typedef void (*em_func_viiiiiii)(int, int, int, int, int, int, int);
182 typedef void (*em_func_viiiiiiii)(int, int, int, int, int, int, int, int);
183 typedef void (*em_func_viiiiiiiii)(int, int, int, int, int, int, int, int, int);
184 typedef void (*em_func_viiiiiiiiii)(int, int, int, int, int, int, int, int, int, int);
185 typedef void (*em_func_viiiiiiiiiii)(int, int, int, int, int, int, int, int, int, int, int);
186 typedef int (*em_func_i)(void);
187 typedef int (*em_func_ii)(int);
188 typedef int (*em_func_iii)(int, int);
189 typedef int (*em_func_iiii)(int, int, int);
190 typedef int (*em_func_iiiii)(int, int, int, int);
191 typedef int (*em_func_iiiiii)(int, int, int, int, int);
192 typedef int (*em_func_iiiiiii)(int, int, int, int, int, int);
193 typedef int (*em_func_iiiiiiii)(int, int, int, int, int, int, int);
194 typedef int (*em_func_iiiiiiiii)(int, int, int, int, int, int, int, int);
195 typedef int (*em_func_iiiiiiiiii)(int, int, int, int, int, int, int, int, int);
196 
197 // Encode function signatures into a single uint32_t integer.
198 // N.B. This encoding scheme is internal to the implementation, and can change
199 // in the future. Do not depend on the exact numbers in this scheme.
200 #define EM_FUNC_SIGNATURE unsigned int
201 
202 // The encoding scheme is as follows:
203 // - highest three bits identify the type of the return value
204 #define EM_FUNC_SIG_RETURN_VALUE_MASK (0x7U << 29)
205 
206 #define EM_FUNC_SIG_RETURN_VALUE_V   0
207 #define EM_FUNC_SIG_RETURN_VALUE_I   (0x1U << 29)
208 #define EM_FUNC_SIG_RETURN_VALUE_I64 (0x2U << 29)
209 #define EM_FUNC_SIG_RETURN_VALUE_F   (0x3U << 29)
210 #define EM_FUNC_SIG_RETURN_VALUE_D   (0x4U << 29)
211 
212 // - next highest four bits specify the number of input parameters to the
213 //   function (allowed values are 0-12, inclusively)
214 #define EM_FUNC_SIG_NUM_PARAMETERS_SHIFT 25
215 #define EM_FUNC_SIG_NUM_PARAMETERS_MASK (0xFU << EM_FUNC_SIG_NUM_PARAMETERS_SHIFT)
216 #define EM_FUNC_SIG_WITH_N_PARAMETERS(x) (((EM_FUNC_SIGNATURE)(x)) << EM_FUNC_SIG_NUM_PARAMETERS_SHIFT)
217 
218 // - starting from the lowest bits upwards, each pair of two subsequent bits
219 //   specifies the type of an input parameter.
220 //   That is, bits 1:0 encode the type of the first input, bits 3:2 encode the
221 //   type of the second input, and so on.
222 #define EM_FUNC_SIG_ARGUMENTS_TYPE_MASK (~(EM_FUNC_SIG_RETURN_VALUE_MASK | EM_FUNC_SIG_NUM_PARAMETERS_MASK))
223 #define EM_FUNC_SIG_ARGUMENT_TYPE_SIZE_MASK 0x3U
224 #define EM_FUNC_SIG_ARGUMENT_TYPE_SIZE_SHIFT 2
225 
226 #define EM_FUNC_SIG_PARAM_I   0
227 #define EM_FUNC_SIG_PARAM_I64 0x1U
228 #define EM_FUNC_SIG_PARAM_F   0x2U
229 #define EM_FUNC_SIG_PARAM_D   0x3U
230 #define EM_FUNC_SIG_SET_PARAM(i, type) ((EM_FUNC_SIGNATURE)(type) << (2*i))
231 
232 // Extra types used in WebGL glGet*() calls (not used in proxying)
233 #define EM_FUNC_SIG_PARAM_B   0x4U
234 #define EM_FUNC_SIG_PARAM_F2I 0x5U
235 
236 // In total, the above encoding scheme gives the following 32-bit structure for
237 // the proxied function signatures (highest -> lowest bit order):
238 // RRRiiiiSbbaa99887766554433221100
239 // where RRR is return type
240 // iiii is the number of inputs
241 // S denotes a special function (internal proxying mechanism for functions
242 // related to built-in threading APIs, like thread creation itself)
243 // 00-bb encode the type of up to 12 function parameters
244 
245 #define EM_FUNC_SIG_V     (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(0))
246 #define EM_FUNC_SIG_D     (EM_FUNC_SIG_RETURN_VALUE_D | EM_FUNC_SIG_WITH_N_PARAMETERS(0))
247 #define EM_FUNC_SIG_VI    (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(1) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I))
248 #define EM_FUNC_SIG_VF    (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(1) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_F))
249 #define EM_FUNC_SIG_FI    (EM_FUNC_SIG_RETURN_VALUE_F | EM_FUNC_SIG_WITH_N_PARAMETERS(1) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I))
250 #define EM_FUNC_SIG_DI    (EM_FUNC_SIG_RETURN_VALUE_D | EM_FUNC_SIG_WITH_N_PARAMETERS(1) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I))
251 #define EM_FUNC_SIG_VII   (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(2) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I))
252 #define EM_FUNC_SIG_VIF   (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(2) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_F))
253 #define EM_FUNC_SIG_VFF   (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(2) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_F))
254 #define EM_FUNC_SIG_VIII  (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(3) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I))
255 #define EM_FUNC_SIG_VIIF  (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(3) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_F))
256 #define EM_FUNC_SIG_VIFF  (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(3) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_F))
257 #define EM_FUNC_SIG_VFFF  (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(3) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_F))
258 #define EM_FUNC_SIG_VIIII (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(4) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I))
259 #define EM_FUNC_SIG_VIIFI (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(4) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I))
260 #define EM_FUNC_SIG_VIFFF (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(4) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_F))
261 #define EM_FUNC_SIG_VFFFF (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(4) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_F))
262 #define EM_FUNC_SIG_IIFFF (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(4) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_F))
263 #define EM_FUNC_SIG_VIIIII (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(5) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I))
264 #define EM_FUNC_SIG_VIFFFF (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(5) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_F) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_F))
265 #define EM_FUNC_SIG_VIIIIII (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(6) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I))
266 #define EM_FUNC_SIG_VIIIIIII (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(7) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(6, EM_FUNC_SIG_PARAM_I))
267 #define EM_FUNC_SIG_VIIIIIIII (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(8) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(6, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(7, EM_FUNC_SIG_PARAM_I))
268 #define EM_FUNC_SIG_VIIIIIIIII (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(9) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(6, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(7, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(8, EM_FUNC_SIG_PARAM_I))
269 #define EM_FUNC_SIG_VIIIIIIIIII (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(10) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(6, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(7, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(8, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(9, EM_FUNC_SIG_PARAM_I))
270 #define EM_FUNC_SIG_VIIIIIIIIIII (EM_FUNC_SIG_RETURN_VALUE_V | EM_FUNC_SIG_WITH_N_PARAMETERS(11) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(6, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(7, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(8, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(9, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(10, EM_FUNC_SIG_PARAM_I))
271 #define EM_FUNC_SIG_I     (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(0))
272 #define EM_FUNC_SIG_II    (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(1) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I))
273 #define EM_FUNC_SIG_III   (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(2) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I))
274 #define EM_FUNC_SIG_IIII  (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(3) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I))
275 #define EM_FUNC_SIG_IIIII (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(4) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I))
276 #define EM_FUNC_SIG_IIIIII (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(5) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I))
277 #define EM_FUNC_SIG_IIIIIII (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(6) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I))
278 #define EM_FUNC_SIG_IIIIIIII (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(7) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(6, EM_FUNC_SIG_PARAM_I))
279 #define EM_FUNC_SIG_IIIIIIIII (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(8) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(6, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(7, EM_FUNC_SIG_PARAM_I))
280 #define EM_FUNC_SIG_IIIIIIIIII (EM_FUNC_SIG_RETURN_VALUE_I | EM_FUNC_SIG_WITH_N_PARAMETERS(9) | EM_FUNC_SIG_SET_PARAM(0, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(1, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(2, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(3, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(4, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(5, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(6, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(7, EM_FUNC_SIG_PARAM_I) | EM_FUNC_SIG_SET_PARAM(8, EM_FUNC_SIG_PARAM_I))
281 
282 #define EM_FUNC_SIG_NUM_FUNC_ARGUMENTS(x) ((((EM_FUNC_SIGNATURE)x) & EM_FUNC_SIG_NUM_PARAMETERS_MASK) >> EM_FUNC_SIG_NUM_PARAMETERS_SHIFT)
283 
284 // There are some built-in special proxied functions, that embed the signatures
285 // inside the above encoding scheme
286 #define EM_FUNC_SIG_SPECIAL_INTERNAL (1 << 24)
287 #define EM_PROXIED_FUNC_SPECIAL(x) (EM_FUNC_SIG_SPECIAL_INTERNAL | ((x) << 20))
288 
289 #define EM_PROXIED_PTHREAD_CREATE (EM_PROXIED_FUNC_SPECIAL(0) | EM_FUNC_SIG_IIIII)
290 #define EM_PROXIED_CREATE_CONTEXT (EM_PROXIED_FUNC_SPECIAL(2) | EM_FUNC_SIG_III)
291 #define EM_PROXIED_RESIZE_OFFSCREENCANVAS (EM_PROXIED_FUNC_SPECIAL(3) | EM_FUNC_SIG_IIII)
292 #define EM_PROXIED_JS_FUNCTION (EM_PROXIED_FUNC_SPECIAL(4) | EM_FUNC_SIG_D)
293 
294 // Runs the given function synchronously on the main Emscripten runtime thread.
295 // If this thread is the main thread, the operation is immediately performed,
296 // and the result is returned.
297 // If the current thread is not the main Emscripten runtime thread (but a
298 // pthread), the function
299 // will be proxied to be called by the main thread.
300 //  - Calling emscripten_sync_* functions requires that the application was
301 //    compiled with pthreads support enabled (-s USE_PTHREADS=1/2) and that the
302 //    browser supports SharedArrayBuffer specification.
303 int emscripten_sync_run_in_main_runtime_thread_(EM_FUNC_SIGNATURE sig, void *func_ptr, ...);
304 
305 // The 'async' variant of the run_in_main_thread functions are otherwise the
306 // same as the synchronous ones, except that the operation is performed in a
307 // fire and forget manner. The call is placed to the command queue of the main
308 // Emscripten runtime thread, but its completion is not waited for. As a result,
309 // if the function did have a return value, the return value is not received.
310 //  - Note that multiple asynchronous commands from a single pthread/Worker are
311 //    guaranteed to be executed on the main thread in the program order they
312 //    were called in.
313 void emscripten_async_run_in_main_runtime_thread_(EM_FUNC_SIGNATURE sig, void *func_ptr, ...);
314 
315 // The 'async_waitable' variant of the run_in_main_runtime_thread functions run
316 // like the 'async' variants, except that while the operation starts off
317 // asynchronously, the result is then later waited upon to receive the return
318 // value.
319 //  - The object returned by this function call is dynamically allocated, and
320 //    should be freed up via a call to emscripten_async_waitable_close() after
321 //    the wait has been performed.
322 em_queued_call *emscripten_async_waitable_run_in_main_runtime_thread_(EM_FUNC_SIGNATURE sig, void *func_ptr, ...);
323 
324 // Since we can't validate the function pointer type, allow implicit casting of
325 // functions to void* without complaining.
326 #define emscripten_sync_run_in_main_runtime_thread(sig, func_ptr, ...) emscripten_sync_run_in_main_runtime_thread_((sig), (void*)(func_ptr),##__VA_ARGS__)
327 #define emscripten_async_run_in_main_runtime_thread(sig, func_ptr, ...) emscripten_async_run_in_main_runtime_thread_((sig), (void*)(func_ptr),##__VA_ARGS__)
328 #define emscripten_async_waitable_run_in_main_runtime_thread(sig, func_ptr, ...) emscripten_async_waitable_run_in_main_runtime_thread_((sig), (void*)(func_ptr),##__VA_ARGS__)
329 
330 EMSCRIPTEN_RESULT emscripten_wait_for_call_v(em_queued_call *call, double timeoutMSecs);
331 EMSCRIPTEN_RESULT emscripten_wait_for_call_i(em_queued_call *call, double timeoutMSecs, int *outResult);
332 
333 void emscripten_async_waitable_close(em_queued_call *call);
334 
335 int _emscripten_call_on_thread(int force_async, pthread_t target_thread, EM_FUNC_SIGNATURE sig, void *func_ptr, void *satellite, ...); // internal
336 
337 // Runs the given function on the specified thread. If we are currently on
338 // that target thread then we just execute the call synchronously; otherwise it
339 // is queued on that thread to execute asynchronously.
340 // Returns 1 if it executed the code (i.e., it was on the target thread), and 0
341 // otherwise.
342 #define emscripten_dispatch_to_thread(target_thread, sig, func_ptr, satellite, ...) _emscripten_call_on_thread(0, (target_thread), (sig), (void*)(func_ptr), (satellite),##__VA_ARGS__)
343 
344 // Similar to emscripten_dispatch_to_thread, but always runs the
345 // function asynchronously, even if on the same thread. This is less efficient
346 // but may be simpler to reason about in some cases.
347 #define emscripten_dispatch_to_thread_async(target_thread, sig, func_ptr, satellite, ...) _emscripten_call_on_thread(1, (target_thread), (sig), (void*)(func_ptr), (satellite),##__VA_ARGS__)
348 
349 // Returns 1 if the current thread is the thread that hosts the Emscripten runtime.
350 int emscripten_is_main_runtime_thread(void);
351 
352 // Returns 1 if the current thread is the main browser thread.
353 int emscripten_is_main_browser_thread(void);
354 
355 // A temporary workaround to issue
356 // https://github.com/emscripten-core/emscripten/issues/3495:
357 // Call this in the body of all lock-free atomic (cas) loops that the main
358 // thread might enter which don't otherwise call to any pthread api calls
359 // (mutexes) or C runtime functions that are considered cancellation points.
360 void emscripten_main_thread_process_queued_calls(void);
361 
362 void emscripten_current_thread_process_queued_calls(void);
363 
364 pthread_t emscripten_main_browser_thread_id(void);
365 
366 // Synchronously sleeps the calling thread for the given number of milliseconds.
367 // Note: Calling this on the main browser thread is _very_ _very_ bad for
368 // application logic throttling, because it does not save any battery, it will
369 // spin up the CPU at 100%, lock up the UI, printfs will not come through on web
370 // page or the console, and eventually it will show up the slow script dialog.
371 // Calling this function in a pthread (Web Worker) is fine, and a good way to go
372 // if you need to synchronously sleep for a specific amount of time while saving
373 // power.
374 // Note 2: This function will process the pthread-specific event queue for the
375 //         calling thread while sleeping, and this function also acts as a
376 //         cancellation point.
377 // Note 3: This function is enabled when targeting pthreads (SharedArrayBuffer),
378 //         not to be confused with
379 //         similarly named function emscripten_sleep(), which is intended for
380 //         Asyncify builds.
381 void emscripten_thread_sleep(double msecs);
382 
383 #define EM_THREAD_STATUS int
384 #define EM_THREAD_STATUS_NOTSTARTED 0
385 #define EM_THREAD_STATUS_RUNNING    1
386 #define EM_THREAD_STATUS_SLEEPING   2 // Performing an unconditional sleep (usleep, etc.)
387 #define EM_THREAD_STATUS_WAITFUTEX  3 // Waiting for an explicit low-level futex (emscripten_futex_wait)
388 #define EM_THREAD_STATUS_WAITMUTEX  4 // Waiting for a pthread_mutex_t
389 #define EM_THREAD_STATUS_WAITPROXY  5 // Waiting for a proxied operation to finish.
390 #define EM_THREAD_STATUS_FINISHED   6
391 #define EM_THREAD_STATUS_NUMFIELDS  7
392 
393 // Sets the profiler status of the calling thread. This is a no-op if thread
394 // profiling is not active.
395 // This is an internal function and generally not intended for user code.
396 // When thread profiler is not enabled (not building with --threadprofiling),
397 // this is a no-op.
398 void emscripten_set_current_thread_status(EM_THREAD_STATUS newStatus);
399 
400 // Sets the profiler status of the calling thread, but only if it was in the
401 // expected status beforehand.
402 // This is an internal function and generally not intended for user code.
403 // When thread profiler is not enabled (not building with --threadprofiling),
404 // this is a no-op.
405 void emscripten_conditional_set_current_thread_status(EM_THREAD_STATUS expectedStatus, EM_THREAD_STATUS newStatus);
406 
407 // Sets the name of the given thread. Pass pthread_self() as the thread ID to
408 // set the name of the calling thread.
409 // The name parameter is a UTF-8 encoded string which is truncated to 32 bytes.
410 // When thread profiler is not enabled (not building with --threadprofiling),
411 // this is a no-op.
412 void emscripten_set_thread_name(pthread_t threadId, const char *name);
413 
414 // Gets the stored pointer to a string representing the canvases to transfer to
415 // the created thread.
416 int emscripten_pthread_attr_gettransferredcanvases(const pthread_attr_t *a, const char **str);
417 
418 // Specifies a comma-delimited list of canvas DOM element IDs to transfer to the
419 // thread to be created.
420 // Note: this pointer is weakly stored (not copied) to the given pthread_attr_t,
421 // so must be held alive until pthread_create() has been called. If 0 or "", no
422 // canvases are transferred.
423 // The special value "#canvas" denotes the element stored in Module.canvas.
424 int emscripten_pthread_attr_settransferredcanvases(pthread_attr_t *a, const char *str);
425 
426 struct thread_profiler_block
427 {
428   // One of THREAD_STATUS_*
429   int threadStatus;
430   // Wallclock time denoting when the current thread state was entered in.
431   double currentStatusStartTime;
432   // Accumulated duration times denoting how much time has been spent in each
433   // state, in msecs.
434   double timeSpentInStatus[EM_THREAD_STATUS_NUMFIELDS];
435   // A human-readable name for this thread.
436   char name[32];
437 };
438 
439 // Called when blocking on the main thread. This will error if main thread
440 // blocking is not enabled, see ALLOW_BLOCKING_ON_MAIN_THREAD.
441 void emscripten_check_blocking_allowed(void);
442 
443 #ifdef __cplusplus
444 }
445 #endif
446