Skip to content

Commit

Permalink
Add emscripten_malloc_wasm_worker and rename creation API a little.
Browse files Browse the repository at this point in the history
  • Loading branch information
juj committed Feb 15, 2022
1 parent 148a3a0 commit c84a2d6
Show file tree
Hide file tree
Showing 26 changed files with 78 additions and 43 deletions.
10 changes: 5 additions & 5 deletions src/library_wasm_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,16 @@ mergeInto(LibraryManager.library, {
_wasmWorkerBlobUrl: "URL.createObjectURL(new Blob(['onmessage=function(d){onmessage=null;d=d.data;{{{ captureModuleArg() }}}importScripts(d.js);{{{ instantiateModule() }}}d.wasm=d.mem=d.js=0;}'],{type:'application/javascript'}))",
#endif

_emscripten_create_wasm_worker__deps: ['wasm_workers', 'wasm_workers_id', '_wasm_worker_appendToQueue', '_wasm_worker_runPostMessage'
_emscripten_create_wasm_worker_with_tls__deps: ['wasm_workers', 'wasm_workers_id', '_wasm_worker_appendToQueue', '_wasm_worker_runPostMessage'
#if WASM_WORKERS == 2
, '_wasmWorkerBlobUrl'
#endif
],
_emscripten_create_wasm_worker__postset: 'if (ENVIRONMENT_IS_WASM_WORKER) {\n'
_emscripten_create_wasm_worker_with_tls__postset: 'if (ENVIRONMENT_IS_WASM_WORKER) {\n'
+ '_wasm_workers[0] = this;\n'
+ 'addEventListener("message", __wasm_worker_appendToQueue);\n'
+ '}\n',
_emscripten_create_wasm_worker: function(stackLowestAddress, stackSize, tlsAddress, tlsSize) {
_emscripten_create_wasm_worker_with_tls: function(stackLowestAddress, stackSize, tlsAddress, tlsSize) {
#if ASSERTIONS
assert(stackLowestAddress % 16 == 0);
assert(stackSize % 16 == 0);
Expand Down Expand Up @@ -102,9 +102,9 @@ mergeInto(LibraryManager.library, {
worker.addEventListener('message', __wasm_worker_runPostMessage);
return _wasm_workers_id++;
},
_emscripten_create_wasm_worker_no_tls__deps: ['_emscripten_create_wasm_worker'],
_emscripten_create_wasm_worker_no_tls__deps: ['_emscripten_create_wasm_worker_with_tls'],
_emscripten_create_wasm_worker_no_tls: function(stackLowestAddress, stackSize) {
return __emscripten_create_wasm_worker(stackLowestAddress, stackSize, 0, 0);
return __emscripten_create_wasm_worker_with_tls(stackLowestAddress, stackSize, 0, 0);
},

emscripten_terminate_wasm_worker: function(id) {
Expand Down
29 changes: 27 additions & 2 deletions system/include/emscripten/wasm_worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,33 @@ extern "C" {
#define emscripten_wasm_worker_t int
#define EMSCRIPTEN_WASM_WORKER_ID_PARENT 0

// If not building with Wasm workers enabled (-s WASM_WORKERS=0), returns 0.
emscripten_wasm_worker_t emscripten_create_wasm_worker(void *stackLowestAddress, uint32_t stackSize, void *tlsAddress, uint32_t tlsSize);
/* Creates a new Worker() that is attached to executing this WebAssembly.Instance and WebAssembly.Memory.
emscripten_malloc_wasm_worker: Creates a new Worker, dynamically allocating stack and TLS for it. Unfortunately
due to the asynchronous no-notifications nature of how Worker API specification teardown
behaves, the dynamically allocated memory can never be freed, so use this function
only in scenarios where the page does not need to deinitialize/tear itself down.
emscripten_create_wasm_worker_no_tls: Creates a Wasm Worker on the given placed stack address area, but no TLS.
Use this function on codebase that explicitly do not have any TLS state,
e.g. when the Worker is being reset to reinit execution at runtime, or to micro-
optimize code size when TLS is not needed. This function will assert() fail if
the compiled code does have any TLS uses in it. This function does not use any
dynamic memory allocation.
emscripten_create_wasm_worker_with_tls: Creates a Wasm Worker on given placed stack address and TLS area.
Use the Wasm built-in functions __builtin_wasm_tls_align() and
__builtin_wasm_tls_size() to obtain the needed memory size for the TLS area.
Use this function to manually manage the memory that a Worker should use.
This function does not use any dynamic memory allocation.
Returns an ID that represents the given Worker. If not building with Wasm workers enabled (-s WASM_WORKERS=0),
these functions will return 0 to denote failure.
Note that the Worker will be loaded up asynchronously, and initially will not be executing any code. Use
emscripten_wasm_worker_post_function_*() set of functions to start executing code on the Worker. */
emscripten_wasm_worker_t emscripten_malloc_wasm_worker(uint32_t stackSize);
emscripten_wasm_worker_t emscripten_create_wasm_worker_no_tls(void *stackLowestAddress, uint32_t stackSize);
emscripten_wasm_worker_t emscripten_create_wasm_worker_with_tls(void *stackLowestAddress, uint32_t stackSize, void *tlsAddress, uint32_t tlsSize);

// Exists, but is a no-op if not building with Wasm Workers enabled (-s WASM_WORKERS=0)
void emscripten_terminate_wasm_worker(emscripten_wasm_worker_t id);
Expand Down
24 changes: 18 additions & 6 deletions system/lib/wasm_worker/library_wasm_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
#include <emscripten/wasm_worker.h>
#include <emscripten/threading.h>
#include <emscripten/heap.h>
#include <malloc.h>

// Options:
// #define WASM_WORKER_NO_TLS 0/1 : set to 1 to disable TLS compilation support for a small code size gain
// #define STACK_OVERFLOW_CHECK 0/1/2 : set to the current stack overflow check mode

// Internal implementation function in JavaScript side that emscripten_create_wasm_worker() calls to
// to perform the wasm worker creation.
emscripten_wasm_worker_t _emscripten_create_wasm_worker(void *stackLowestAddress, uint32_t stackSize, void *tlsAddress, uint32_t tlsSize);
emscripten_wasm_worker_t _emscripten_create_wasm_worker_with_tls(void *stackLowestAddress, uint32_t stackSize, void *tlsAddress, uint32_t tlsSize);
emscripten_wasm_worker_t _emscripten_create_wasm_worker_no_tls(void *stackLowestAddress, uint32_t stackSize);

void emscripten_stack_set_limits(uint32_t stackLowestAddress, uint32_t stackSize);
Expand Down Expand Up @@ -57,24 +58,25 @@ void emscripten_wasm_worker_initialize(void *stackLowestAddress, uint32_t stackS
#endif
}

emscripten_wasm_worker_t emscripten_create_wasm_worker(void *stackLowestAddress, uint32_t stackSize, void *tlsAddress, uint32_t tlsSize)
emscripten_wasm_worker_t emscripten_create_wasm_worker_with_tls(void *stackLowestAddress, uint32_t stackSize, void *tlsAddress, uint32_t tlsSize)
{
#if WASM_WORKER_NO_TLS
return emscripten_create_wasm_worker_no_tls(stackLowestAddress, stackSize);
#else
assert((uintptr_t)stackLowestAddress % 16 == 0);
assert(stackSize % 16 == 0);
assert((uintptr_t)tlsAddress % __builtin_wasm_tls_align() == 0);
assert(tlsSize == __builtin_wasm_tls_size());
assert((uintptr_t)tlsAddress % __builtin_wasm_tls_align() == 0 && "TLS memory address not aligned in a call to emscripten_create_wasm_worker_with_tls()! Please allocate memory with alignment from __builtin_wasm_tls_align() when creating a Wasm Worker!");
assert(tlsSize != 0 || __builtin_wasm_tls_size() == 0 && "Program code contains TLS: please use function emscripten_create_wasm_worker_with_tls() to create a Wasm Worker!");
assert(tlsSize == __builtin_wasm_tls_size() && "TLS size mismatch! Please reserve exactly __builtin_wasm_tls_size() TLS memory in a call to emscripten_create_wasm_worker_with_tls()");
assert(tlsAddress != 0 || tlsSize == 0);
return _emscripten_create_wasm_worker((void*)stackLowestAddress, stackSize, tlsAddress, tlsSize);
return _emscripten_create_wasm_worker_with_tls((void*)stackLowestAddress, stackSize, tlsAddress, tlsSize);
#endif
}

emscripten_wasm_worker_t emscripten_create_wasm_worker_no_tls(void *stackLowestAddress, uint32_t stackSize)
{
#if !WASM_WORKER_NO_TLS
return emscripten_create_wasm_worker(stackLowestAddress, stackSize, 0, 0);
return emscripten_create_wasm_worker_with_tls(stackLowestAddress, stackSize, 0, 0);
#else
assert((uintptr_t)stackLowestAddress % 16 == 0);
assert(stackSize % 16 == 0);
Expand All @@ -83,6 +85,16 @@ emscripten_wasm_worker_t emscripten_create_wasm_worker_no_tls(void *stackLowestA
#endif
}

emscripten_wasm_worker_t emscripten_malloc_wasm_worker(uint32_t stackSize)
{
#if WASM_WORKER_NO_TLS
return emscripten_create_wasm_worker_no_tls(memalign(16, stackSize), stackSize, 0, 0);
#else
uint32_t tlsSize = __builtin_wasm_tls_size();
return emscripten_create_wasm_worker_with_tls(memalign(16, stackSize), stackSize, memalign(__builtin_wasm_tls_align(), tlsSize), tlsSize);
#endif
}

void emscripten_wasm_worker_sleep(int64_t nsecs)
{
int32_t addr = 0;
Expand Down
2 changes: 1 addition & 1 deletion tests/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5154,7 +5154,7 @@ def test_wasm2js_fallback_on_wasm_compilation_failure(self):
def test_system(self):
self.btest_exit(test_file('system.c'))

# Tests emscripten_create_wasm_worker() and emscripten_current_thread_is_wasm_worker() functions
# Tests emscripten_malloc_wasm_worker() and emscripten_current_thread_is_wasm_worker() functions
def test_wasm_worker_hello(self):
self.btest(path_from_root('tests', 'wasm_worker', 'hello_wasm_worker.c'),
expected='0',
Expand Down
2 changes: 1 addition & 1 deletion tests/wasm_worker/c11__Thread_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ int main()
EM_ASM(console.log($0), tls);
assert(!emscripten_current_thread_is_wasm_worker());
tls = 42;
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack), tlsBase, __builtin_wasm_tls_size());
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_with_tls(stack, sizeof(stack), tlsBase, __builtin_wasm_tls_size());
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
2 changes: 1 addition & 1 deletion tests/wasm_worker/cpp11_thread_local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ int main()
EM_ASM(console.log($0), tls);
assert(!emscripten_current_thread_is_wasm_worker());
tls = 42;
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack), tlsBase, __builtin_wasm_tls_size());
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_with_tls(stack, sizeof(stack), tlsBase, __builtin_wasm_tls_size());
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
2 changes: 1 addition & 1 deletion tests/wasm_worker/hardware_concurrency_is_lock_free.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ char stack[1024];
int main()
{
test();
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
6 changes: 2 additions & 4 deletions tests/wasm_worker/hello_wasm_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include <emscripten/wasm_worker.h>
#include <assert.h>

// Test emscripten_create_wasm_worker() and emscripten_current_thread_is_wasm_worker() functions
// Test emscripten_malloc_wasm_worker() and emscripten_current_thread_is_wasm_worker() functions

EM_JS(void, console_log, (char* str), {
console.log(UTF8ToString(str));
Expand All @@ -17,11 +17,9 @@ void worker_main()
#endif
}

char stack[1024];

int main()
{
assert(!emscripten_current_thread_is_wasm_worker());
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_malloc_wasm_worker(/*stack size: */1024);
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
2 changes: 1 addition & 1 deletion tests/wasm_worker/lock_async_acquire.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ int main()
for(int i = 0; i < NUM_THREADS; ++i)
{
void *stack = malloc(1024);
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, 1024);
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, 1024);
emscripten_wasm_worker_post_function_vi(worker, (void (*)(int))schedule_work, 0);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/wasm_worker/lock_busyspin_wait_acquire.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ int main()
{
test();

emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
2 changes: 1 addition & 1 deletion tests/wasm_worker/lock_busyspin_waitinf_acquire.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ int main()

// Spawn a Worker to try to take the lock. It will succeed only after releaseLock()
// gets called.
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);

emscripten_set_timeout(releaseLock, 1000, 0);
Expand Down
2 changes: 1 addition & 1 deletion tests/wasm_worker/lock_wait_acquire.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ char stack[1024];

int main()
{
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
4 changes: 2 additions & 2 deletions tests/wasm_worker/lock_wait_acquire2.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ char stack2[1024];

int main()
{
emscripten_wasm_worker_t worker1 = emscripten_create_wasm_worker(stack1, sizeof(stack1));
emscripten_wasm_worker_t worker2 = emscripten_create_wasm_worker(stack2, sizeof(stack2));
emscripten_wasm_worker_t worker1 = emscripten_create_wasm_worker_no_tls(stack1, sizeof(stack1));
emscripten_wasm_worker_t worker2 = emscripten_create_wasm_worker_no_tls(stack2, sizeof(stack2));
emscripten_wasm_worker_post_function_v(worker1, worker1_main);
emscripten_wasm_worker_post_function_v(worker2, worker2_main);
}
2 changes: 1 addition & 1 deletion tests/wasm_worker/lock_waitinf_acquire.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ int main()
for(int i = 0; i < NUM_THREADS; ++i)
{
void *stack = malloc(1024);
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, 1024);
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, 1024);
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
}
2 changes: 1 addition & 1 deletion tests/wasm_worker/no_proxied_js_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ char stack[1024];
int main()
{
proxied_js_function();
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
2 changes: 1 addition & 1 deletion tests/wasm_worker/post_function.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ char stack[1024];
int main()
{
assert(!emscripten_current_thread_is_wasm_worker());
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, v);
emscripten_wasm_worker_post_function_vi(worker, vi, 1);
emscripten_wasm_worker_post_function_vii(worker, vii, 2, 3);
Expand Down
2 changes: 1 addition & 1 deletion tests/wasm_worker/post_function_to_main_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ char stack[1024];

int main()
{
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
4 changes: 2 additions & 2 deletions tests/wasm_worker/semaphore_waitinf_acquire.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ int main()
emscripten_semaphore_init(&threadsWaiting, 0);

void *stack = malloc(1024);
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, 1024);
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, 1024);
emscripten_wasm_worker_post_function_v(worker, control_thread);

#define NUM_THREADS 6
for(int i = 0; i < NUM_THREADS; ++i)
{
void *stack = malloc(1024);
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, 1024);
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, 1024);
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
}
4 changes: 2 additions & 2 deletions tests/wasm_worker/terminate_all_wasm_workers.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ void terminate_worker(void *userData)

int main()
{
worker[0] = emscripten_create_wasm_worker(stack1, sizeof(stack1));
worker[1] = emscripten_create_wasm_worker(stack2, sizeof(stack2));
worker[0] = emscripten_create_wasm_worker_no_tls(stack1, sizeof(stack1));
worker[1] = emscripten_create_wasm_worker_no_tls(stack2, sizeof(stack2));
emscripten_wasm_worker_post_function_v(worker[0], worker_main);
emscripten_wasm_worker_post_function_v(worker[1], worker_main);

Expand Down
2 changes: 1 addition & 1 deletion tests/wasm_worker/terminate_wasm_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ void terminate_worker(void *userData)

int main()
{
worker = emscripten_create_wasm_worker(stack, sizeof(stack));
worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);

// Terminate the worker after a small delay
Expand Down
2 changes: 1 addition & 1 deletion tests/wasm_worker/wait32_notify.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ EM_BOOL main_loop(double time, void *userData)
int main()
{
console_log("main: creating worker");
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
console_log("main: posting function");
emscripten_wasm_worker_post_function_v(worker, worker_main);

Expand Down
2 changes: 1 addition & 1 deletion tests/wasm_worker/wait64_notify.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ EM_BOOL main_loop(double time, void *userData)
int main()
{
console_log("main: creating worker");
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
console_log("main: posting function");
emscripten_wasm_worker_post_function_v(worker, worker_main);

Expand Down
2 changes: 1 addition & 1 deletion tests/wasm_worker/wait_async.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void asyncWaitFinishedShouldBeOk(int32_t *ptr, uint32_t val, ATOMICS_WAIT_RESULT
int main()
{
console_log("main: creating worker");
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
console_log("main: posting function");
emscripten_wasm_worker_post_function_v(worker, worker_main);

Expand Down
4 changes: 2 additions & 2 deletions tests/wasm_worker/wasm_worker_self_id.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ char stack2[1024];
int main()
{
assert(emscripten_wasm_worker_self_id() == 0);
worker1 = emscripten_create_wasm_worker(stack1, sizeof(stack1));
worker2 = emscripten_create_wasm_worker(stack2, sizeof(stack2));
worker1 = emscripten_create_wasm_worker_no_tls(stack1, sizeof(stack1));
worker2 = emscripten_create_wasm_worker_no_tls(stack2, sizeof(stack2));
emscripten_wasm_worker_post_function_v(worker1, worker1_main);
emscripten_wasm_worker_post_function_v(worker2, worker2_main);
}
2 changes: 1 addition & 1 deletion tests/wasm_worker/wasm_worker_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ char stack[1024];

int main()
{
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
}
2 changes: 1 addition & 1 deletion tests/wasm_worker/wasm_worker_tls_wasm_assembly.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ int main()
assert(globalData == 1);
globalData = 2;
set_tls_variable(42);
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker_no_tls(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
}

0 comments on commit c84a2d6

Please sign in to comment.