Skip to content

Commit

Permalink
Implement wasi thread using thread manager
Browse files Browse the repository at this point in the history
This is a simple implementation for now; going forward we most likely won't
need to rely on thread manager as it doesn't provide much value in this
scenario.
  • Loading branch information
loganek committed Dec 6, 2022
1 parent 17e2824 commit 52fc95b
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 1 deletion.
1 change: 1 addition & 0 deletions build-scripts/runtime_lib.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ endif ()
if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1)
include (${IWASM_DIR}/libraries/lib-wasi-threads/lib_wasi_threads.cmake)
# Enable the dependent feature if lib wasi threads is enabled
set (WAMR_BUILD_THREAD_MGR 1)
set (WAMR_BUILD_BULK_MEMORY 1)
set (WAMR_BUILD_SHARED_MEMORY 1)
endif ()
Expand Down
132 changes: 131 additions & 1 deletion core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#include "bh_log.h"
#include "wasmtime_ssp.h"
#include "thread_manager.h"

#if WASM_ENABLE_INTERP != 0
#include "wasm_runtime.h"
Expand All @@ -13,10 +15,138 @@
#include "aot_runtime.h"
#endif

static const char *THREAD_START_FUNCTION = "wasi_thread_start";

typedef struct {
/* app's entry function */
wasm_function_inst_t start_func;
/* arg of the app's entry function */
uint32 arg;
/* thread id passed to the app */
uint32 thread_id;
} ThreadStartArg;

static uint32
allocate_thread_id()
{
static korp_mutex thread_global_lock;
static uint32 thread_id = 0;

uint32 id;

os_mutex_lock(&thread_global_lock);
id = thread_id++;
os_mutex_unlock(&thread_global_lock);
return id;
}

static void *
thread_start(void *arg)
{
wasm_exec_env_t exec_env = (wasm_exec_env_t)arg;
wasm_module_inst_t module_inst = get_module_inst(exec_env);
ThreadStartArg *thread_arg = exec_env->thread_arg;
uint32 argv[2];

wasm_exec_env_set_thread_info(exec_env);
argv[0] = thread_arg->thread_id;
argv[1] = thread_arg->arg;

if (!wasm_runtime_call_wasm(exec_env, thread_arg->start_func, 2, argv)) {
if (wasm_runtime_get_exception(module_inst))
wasm_cluster_spread_exception(exec_env);
}

/* routine exit, destroy instance */
wasm_runtime_deinstantiate_internal(module_inst, true);

wasm_runtime_free(thread_arg);

return NULL;
}

static __wasi_errno_t
thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
{
return __WASI_ENOSYS;
wasm_module_t module = wasm_exec_env_get_module(exec_env);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasm_module_inst_t new_module_inst = NULL;
ThreadStartArg *thread_start_arg = NULL;
wasm_function_inst_t start_func;

uint32 stack_size = 8192;
int32 ret = -1;
#if WASM_ENABLE_LIBC_WASI != 0
WASIContext *wasi_ctx;
#endif

bh_assert(module);
bh_assert(module_inst);

#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
stack_size =
((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
}
#endif

#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
stack_size =
((AOTModuleInstance *)module_inst)->default_wasm_stack_size;
}
#endif

if (!(new_module_inst = wasm_runtime_instantiate_internal(
module, true, stack_size, 0, NULL, 0)))
return -1;

wasm_runtime_set_custom_data_internal(
new_module_inst, wasm_runtime_get_custom_data(module_inst));

#if WASM_ENABLE_LIBC_WASI != 0
wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
if (wasi_ctx)
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
#endif

start_func = wasm_runtime_lookup_function(new_module_inst,
THREAD_START_FUNCTION, NULL);
if (!start_func) {
LOG_ERROR("Failed to find thread start function %s",
THREAD_START_FUNCTION);
goto thread_spawn_fail;
}

if (!(thread_start_arg = wasm_runtime_malloc(sizeof(ThreadStartArg)))) {
LOG_ERROR("Runtime args allocation failed");
goto thread_spawn_fail;
}

thread_start_arg->thread_id = allocate_thread_id();
thread_start_arg->arg = (uint32)start_arg;
thread_start_arg->start_func = start_func;

os_mutex_lock(&exec_env->wait_lock);
ret = wasm_cluster_create_thread(exec_env, new_module_inst, thread_start,
(void *)thread_start_arg);
if (ret != 0) {
os_mutex_unlock(&exec_env->wait_lock);
LOG_ERROR("Failed to spawn a new thread");
goto thread_spawn_fail;
}
os_mutex_unlock(&exec_env->wait_lock);

return 0;

thread_spawn_fail:
if (new_module_inst)
wasm_runtime_deinstantiate_internal(new_module_inst, true);

if (thread_start_arg)
wasm_runtime_free(thread_start_arg);

return -1;
}

/* clang-format off */
Expand Down

0 comments on commit 52fc95b

Please sign in to comment.