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,
},
}
} 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;
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);
});
}
// 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;
}
#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();
#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();
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) {
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
) {
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
) {
typedef struct OnyxThread {
i32 id;
+ i32 tls_base;
i32 funcidx;
i32 dataptr;
wasm_instance_t* instance;
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);
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));
}
}
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);
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);