bugfixes with threading
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 23 Nov 2021 00:54:57 +0000 (18:54 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 23 Nov 2021 00:54:57 +0000 (18:54 -0600)
bin/onyx-js
core/runtime/common.onyx
core/runtime/js.onyx
core/runtime/onyx_run.onyx
core/threads/thread.onyx
lib/linux_x86_64/include/wasm.h
lib/windows_x86_64/include/wasm.h
src/wasm_runtime.c

index 95a9a95be6c736a4ca8d598faa1793f2b1793529..5d903b6dfccdfe1919a9cef50ddfba0296834bde 100755 (executable)
@@ -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);
         });
 }
index 39441d8d73ab4737ea79a96d6ba80ce8ab8d242c..997b7bc7e91dd52a7790a54f46843cd00d9184f0 100644 (file)
@@ -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;
index 5d6a1a6150d838dc37cf456ec0c22a2b0eeab724..31a3700d41fba2efa74f8377566006902ec7cd67 100644 (file)
@@ -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();
index 723de5b7fc9616bafe764633e953d45c181195f0..69e6914fe9e056439befea4e2e311e2a1242e5a2 100644 (file)
@@ -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();
index 632bd1dfe4b082edca9126b119ddc4fd10bbfb84..8c69bb3025c648c657f4329e5719bca830015355 100644 (file)
@@ -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) {
index 4a7e2c00d7a5e9469d043529b535a87179e3de3b..6621e5bc24d2be7d60bfef5e10cd08f5d95523c6 100644 (file)
@@ -638,6 +638,18 @@ static inline own wasm_functype_t* wasm_functype_new_3_1(
   return wasm_functype_new(&params, &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(&params, 4, ps);
+  wasm_valtype_vec_new(&results, 1, rs);
+  return wasm_functype_new(&params, &results);
+}
+
 static inline own wasm_functype_t* wasm_functype_new_0_2(
   own wasm_valtype_t* r1, own wasm_valtype_t* r2
 ) {
index ac090e624c4043fd52614fa1428590edc3be7d84..af569bc112f72c6f77d04bc6e76029d4dc04a946 100644 (file)
@@ -638,6 +638,18 @@ static inline own wasm_functype_t* wasm_functype_new_3_1(
   return wasm_functype_new(&params, &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(&params, 4, ps);
+  wasm_valtype_vec_new(&results, 1, rs);
+  return wasm_functype_new(&params, &results);
+}
+
 static inline own wasm_functype_t* wasm_functype_new_0_2(
   own wasm_valtype_t* r1, own wasm_valtype_t* r2
 ) {
index 68bed32339d49e1186a11a92b1ed445577c3e111..a289bd496d936d1a48f5423232f80b1010d72da9 100644 (file)
@@ -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);