From 0a2499395c5f96c06d6600356b32468953e7e506 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 22 Nov 2021 18:54:57 -0600 Subject: [PATCH] bugfixes with threading --- bin/onyx-js | 7 ++++--- core/runtime/common.onyx | 11 ++++++++--- core/runtime/js.onyx | 9 +++++---- core/runtime/onyx_run.onyx | 9 +++++---- core/threads/thread.onyx | 5 ++++- lib/linux_x86_64/include/wasm.h | 12 ++++++++++++ lib/windows_x86_64/include/wasm.h | 12 ++++++++++++ src/wasm_runtime.c | 17 +++++++++++------ 8 files changed, 61 insertions(+), 21 deletions(-) diff --git a/bin/onyx-js b/bin/onyx-js index 95a9a95b..5d903b6d 100755 --- a/bin/onyx-js +++ b/bin/onyx-js @@ -22,13 +22,14 @@ const ENV = { process.exit(status); }, - spawn_thread(id, funcidx, dataptr) { + spawn_thread(id, tls_base, funcidx, dataptr) { try { workers[id] = new Worker(__filename, { workerData: { thread_id: id, memory: wasm_memory, wasm_bytes: wasm_bytes, + tls_base: tls_base, funcidx: funcidx, dataptr: dataptr, }, @@ -82,7 +83,7 @@ if (isMainThread) { } } else { - let { thread_id, memory, wasm_bytes, funcidx, dataptr } = workerData; + let { thread_id, memory, wasm_bytes, tls_base, funcidx, dataptr } = workerData; ENV.onyx.memory = memory; wasm_memory = memory; @@ -93,7 +94,7 @@ if (isMainThread) { wasm_instance = res.instance; const lib = res.instance.exports; - lib._thread_start(thread_id, funcidx, dataptr); + lib._thread_start(thread_id, tls_base, funcidx, dataptr); lib._thread_exit(thread_id); }); } diff --git a/core/runtime/common.onyx b/core/runtime/common.onyx index 39441d8d..997b7bc7 100644 --- a/core/runtime/common.onyx +++ b/core/runtime/common.onyx @@ -37,9 +37,14 @@ __runtime_initialize :: () { // Use this procedure to initialize everything needed in the // standard library when you are dropped directly into a function. -__thread_initialize :: () { - __tls_base = raw_alloc(alloc.heap_allocator, __tls_size); - memory.set(__tls_base, 0, __tls_size); +__thread_initialize :: macro () { + use package core.intrinsics.onyx { __initialize } + + // This should only be true for the main thread. + if __tls_base == null { + __tls_base = raw_alloc(alloc.heap_allocator, __tls_size); + memory.set(__tls_base, 0, __tls_size); + } __initialize(^context); context.allocator = alloc.heap_allocator; diff --git a/core/runtime/js.onyx b/core/runtime/js.onyx index 5d6a1a61..31a3700d 100644 --- a/core/runtime/js.onyx +++ b/core/runtime/js.onyx @@ -20,15 +20,16 @@ __exit :: (status: i32) -> void #foreign "host" "exit" --- } #if Multi_Threading_Enabled { - __spawn_thread :: (id: i32, func: (data: rawptr) -> void, data: rawptr) -> bool #foreign "host" "spawn_thread" --- + __spawn_thread :: (id: i32, tls_base: rawptr, func: (data: rawptr) -> void, data: rawptr) -> bool #foreign "host" "spawn_thread" --- __kill_thread :: (id: i32) -> i32 #foreign "host" "kill_thread" --- - #export "_thread_start" (id: i32, func: (data: rawptr) -> void, data: rawptr) { + #export "_thread_start" (id: i32, tls_base: rawptr, func: (data: rawptr) -> void, data: rawptr) { + __tls_base = tls_base; + context.thread_id = id; + __stack_top = raw_alloc(alloc.heap_allocator, 1 << 20); __thread_initialize(); - context.thread_id = id; - func(data); __flush_stdio(); diff --git a/core/runtime/onyx_run.onyx b/core/runtime/onyx_run.onyx index 723de5b7..69e6914f 100644 --- a/core/runtime/onyx_run.onyx +++ b/core/runtime/onyx_run.onyx @@ -10,15 +10,16 @@ use package wasi #load "core/runtime/wasi" #if Multi_Threading_Enabled { - __spawn_thread :: (id: i32, func: (data: rawptr) -> void, data: rawptr) -> bool #foreign "env" "spawn_thread" --- + __spawn_thread :: (id: i32, tls_base: rawptr, func: (data: rawptr) -> void, data: rawptr) -> bool #foreign "env" "spawn_thread" --- __kill_thread :: (id: i32) -> i32 #foreign "env" "kill_thread" --- - #export "_thread_start" (id: i32, func: (data: rawptr) -> void, data: rawptr) { + #export "_thread_start" (id: i32, tls_base: rawptr, func: (data: rawptr) -> void, data: rawptr) { + __tls_base = tls_base; + context.thread_id = id; + __stack_top = raw_alloc(alloc.heap_allocator, 1 << 20); __thread_initialize(); - context.thread_id = id; - func(data); __flush_stdio(); diff --git a/core/threads/thread.onyx b/core/threads/thread.onyx index 632bd1df..8c69bb30 100644 --- a/core/threads/thread.onyx +++ b/core/threads/thread.onyx @@ -27,7 +27,10 @@ spawn :: (t: ^Thread, data: rawptr, func: (rawptr) -> void) { thread_map->put(t.id, t); - runtime.__spawn_thread(t.id, func, data); + tls_base := raw_alloc(alloc.heap_allocator, __tls_size); + memory.set(tls_base, 0, __tls_size); + + runtime.__spawn_thread(t.id, tls_base, func, data); } join :: (t: ^Thread) { diff --git a/lib/linux_x86_64/include/wasm.h b/lib/linux_x86_64/include/wasm.h index 4a7e2c00..6621e5bc 100644 --- a/lib/linux_x86_64/include/wasm.h +++ b/lib/linux_x86_64/include/wasm.h @@ -638,6 +638,18 @@ static inline own wasm_functype_t* wasm_functype_new_3_1( return wasm_functype_new(¶ms, &results); } +static inline own wasm_functype_t* wasm_functype_new_4_1( + own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3, own wasm_valtype_t* p4, + own wasm_valtype_t* r +) { + wasm_valtype_t* ps[4] = {p1, p2, p3, p4}; + wasm_valtype_t* rs[1] = {r}; + wasm_valtype_vec_t params, results; + wasm_valtype_vec_new(¶ms, 4, ps); + wasm_valtype_vec_new(&results, 1, rs); + return wasm_functype_new(¶ms, &results); +} + static inline own wasm_functype_t* wasm_functype_new_0_2( own wasm_valtype_t* r1, own wasm_valtype_t* r2 ) { diff --git a/lib/windows_x86_64/include/wasm.h b/lib/windows_x86_64/include/wasm.h index ac090e62..af569bc1 100644 --- a/lib/windows_x86_64/include/wasm.h +++ b/lib/windows_x86_64/include/wasm.h @@ -638,6 +638,18 @@ static inline own wasm_functype_t* wasm_functype_new_3_1( return wasm_functype_new(¶ms, &results); } +static inline own wasm_functype_t* wasm_functype_new_4_1( + own wasm_valtype_t* p1, own wasm_valtype_t* p2, own wasm_valtype_t* p3, own wasm_valtype_t* p4, + own wasm_valtype_t* r +) { + wasm_valtype_t* ps[4] = {p1, p2, p3, p4}; + wasm_valtype_t* rs[1] = {r}; + wasm_valtype_vec_t params, results; + wasm_valtype_vec_new(¶ms, 4, ps); + wasm_valtype_vec_new(&results, 1, rs); + return wasm_functype_new(¶ms, &results); +} + static inline own wasm_functype_t* wasm_functype_new_0_2( own wasm_valtype_t* r1, own wasm_valtype_t* r2 ) { diff --git a/src/wasm_runtime.c b/src/wasm_runtime.c index 68bed323..a289bd49 100644 --- a/src/wasm_runtime.c +++ b/src/wasm_runtime.c @@ -60,6 +60,7 @@ wasm_extern_t* wasm_extern_lookup_by_name(wasm_module_t* module, wasm_instance_t typedef struct OnyxThread { i32 id; + i32 tls_base; i32 funcidx; i32 dataptr; wasm_instance_t* instance; @@ -96,7 +97,7 @@ static i32 onyx_run_thread(void *data) { wasm_trap_t* trap=NULL; { // Call the _thread_start procedure - wasm_val_t args[] = { WASM_I32_VAL(thread->id), WASM_I32_VAL(thread->funcidx), WASM_I32_VAL(thread->dataptr) }; + wasm_val_t args[] = { WASM_I32_VAL(thread->id), WASM_I32_VAL(thread->tls_base), WASM_I32_VAL (thread->funcidx), WASM_I32_VAL(thread->dataptr) }; wasm_val_vec_t results; wasm_val_vec_t args_array = WASM_ARRAY_VEC(args); @@ -105,6 +106,9 @@ static i32 onyx_run_thread(void *data) { wasm_message_t msg; wasm_trap_message(trap, &msg); bh_printf("TRAP: %b\n", msg.data, msg.size); + + wasm_frame_t *origin = wasm_trap_origin(trap); + bh_printf("HERE: func[%d] at %p.\n", wasm_frame_func_index(origin), wasm_frame_module_offset(origin)); } } @@ -124,9 +128,10 @@ static wasm_trap_t* onyx_spawn_thread_impl(const wasm_val_vec_t* params, wasm_va bh_arr_insert_end(threads, 1); OnyxThread *thread = &bh_arr_last(threads); - thread->id = params->data[0].of.i32; - thread->funcidx = params->data[1].of.i32; - thread->dataptr = params->data[2].of.i32; + thread->id = params->data[0].of.i32; + thread->tls_base = params->data[1].of.i32; + thread->funcidx = params->data[2].of.i32; + thread->dataptr = params->data[3].of.i32; #ifdef _BH_LINUX pthread_create(&thread->thread, NULL, onyx_run_thread, thread); @@ -250,8 +255,8 @@ void onyx_run_wasm(bh_buffer wasm_bytes) { if (wasm_name_equals_string(module_name, "env")) { if (wasm_name_equals_string(import_name, "spawn_thread")) { - wasm_functype_t* func_type = wasm_functype_new_3_1( - wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32(), + wasm_functype_t* func_type = wasm_functype_new_4_1( + wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32()); wasm_func_t* wasm_func = wasm_func_new(wasm_store, func_type, onyx_spawn_thread_impl); -- 2.25.1