Enable shared memory && add pthread support (#282)

This commit is contained in:
Xu Jun
2020-06-15 19:04:04 +08:00
committed by GitHub
parent f4d4d69736
commit d98ab63e5c
41 changed files with 3081 additions and 289 deletions

View File

@ -6,9 +6,13 @@
#include "wasm_exec_env.h"
#include "wasm_runtime_common.h"
#if WASM_ENABLE_THREAD_MGR != 0
#include "../libraries/thread-mgr/thread_manager.h"
#endif
WASMExecEnv *
wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
uint32 stack_size)
wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
uint32 stack_size)
{
uint64 total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom)
+ (uint64)stack_size;
@ -22,26 +26,87 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
#if WASM_ENABLE_AOT != 0
if (!(exec_env->argv_buf = wasm_runtime_malloc(sizeof(uint32) * 64))) {
wasm_runtime_free(exec_env);
return NULL;
goto fail1;
}
#endif
#if WASM_ENABLE_THREAD_MGR != 0
if (os_mutex_init(&exec_env->wait_lock) != 0)
goto fail2;
if (os_cond_init(&exec_env->wait_cond) != 0)
goto fail3;
#endif
exec_env->module_inst = module_inst;
exec_env->wasm_stack_size = stack_size;
exec_env->wasm_stack.s.top_boundary =
exec_env->wasm_stack.s.bottom + stack_size;
exec_env->wasm_stack.s.top = exec_env->wasm_stack.s.bottom;
return exec_env;
#if WASM_ENABLE_THREAD_MGR != 0
fail3:
os_mutex_destroy(&exec_env->wait_lock);
fail2:
#endif
#if WASM_ENABLE_AOT != 0
wasm_runtime_free(exec_env->argv_buf);
fail1:
#endif
wasm_runtime_free(exec_env);
return NULL;
}
void
wasm_exec_env_destroy_internal(WASMExecEnv *exec_env)
{
#if WASM_ENABLE_THREAD_MGR != 0
os_mutex_destroy(&exec_env->wait_lock);
os_cond_destroy(&exec_env->wait_cond);
#endif
#if WASM_ENABLE_AOT != 0
wasm_runtime_free(exec_env->argv_buf);
#endif
wasm_runtime_free(exec_env);
}
WASMExecEnv *
wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
uint32 stack_size)
{
WASMExecEnv *exec_env = wasm_exec_env_create_internal(module_inst,
stack_size);
/* Set the aux_stack_boundary to 0 */
exec_env->aux_stack_boundary = 0;
#if WASM_ENABLE_THREAD_MGR != 0
WASMCluster *cluster;
if (!exec_env)
return NULL;
/* Create a new cluster for this exec_env */
cluster = wasm_cluster_create(exec_env);
if (!cluster) {
wasm_exec_env_destroy_internal(exec_env);
return NULL;
}
#endif
return exec_env;
}
void
wasm_exec_env_destroy(WASMExecEnv *exec_env)
{
#if WASM_ENABLE_AOT != 0
wasm_runtime_free(exec_env->argv_buf);
#if WASM_ENABLE_THREAD_MGR != 0
/* Terminate all sub-threads */
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
if (cluster) {
wasm_cluster_terminate_all_except_self(cluster, exec_env);
wasm_cluster_del_exec_env(cluster, exec_env);
}
#endif
wasm_runtime_free(exec_env);
wasm_exec_env_destroy_internal(exec_env);
}
WASMModuleInstanceCommon *
@ -59,3 +124,16 @@ wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
}
#if WASM_ENABLE_THREAD_MGR != 0
void *
wasm_exec_env_get_thread_arg(WASMExecEnv *exec_env)
{
return exec_env->thread_arg;
}
void
wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg)
{
exec_env->thread_arg = thread_arg;
}
#endif

View File

@ -18,6 +18,10 @@ extern "C" {
struct WASMModuleInstanceCommon;
struct WASMInterpFrame;
#if WASM_ENABLE_THREAD_MGR != 0
typedef struct WASMCluster WASMCluster;
#endif
/* Execution environment */
typedef struct WASMExecEnv {
/* Next thread's exec env of a WASM module instance. */
@ -41,6 +45,28 @@ typedef struct WASMExecEnv {
exception. */
uint8 *native_stack_boundary;
#if WASM_ENABLE_THREAD_MGR != 0
/* Used to terminate or suspend the interpreter
bit 0: need terminate
bit 1: need suspend
bit 2: need to go into breakpoint */
uintptr_t suspend_flags;
/* Must be provided by thread library */
void* (*thread_start_routine)(void *);
void *thread_arg;
/* pointer to the cluster */
WASMCluster *cluster;
/* used to support debugger */
korp_mutex wait_lock;
korp_cond wait_cond;
#endif
/* Aux stack boundary */
uint32 aux_stack_boundary;
/* attachment for native function */
void *attachment;
@ -76,6 +102,13 @@ typedef struct WASMExecEnv {
} wasm_stack;
} WASMExecEnv;
WASMExecEnv *
wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
uint32 stack_size);
void
wasm_exec_env_destroy_internal(WASMExecEnv *exec_env);
WASMExecEnv *
wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
uint32 stack_size);
@ -165,6 +198,15 @@ wasm_exec_env_get_module_inst(WASMExecEnv *exec_env);
void
wasm_exec_env_set_thread_info(WASMExecEnv *exec_env);
#if WASM_ENABLE_THREAD_MGR != 0
void *
wasm_exec_env_get_thread_arg(WASMExecEnv *exec_env);
void
wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -28,6 +28,17 @@ get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
uint32
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
#if WASM_ENABLE_LIB_PTHREAD != 0
bool
lib_pthread_init();
void
lib_pthread_destroy();
uint32
get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
#endif
static bool
check_symbol_signature(const WASMType *type, const char *signature)
{
@ -278,6 +289,17 @@ wasm_native_init()
return false;
#endif
#if WASM_ENABLE_LIB_PTHREAD != 0
if (!lib_pthread_init())
return false;
n_native_symbols = get_lib_pthread_export_apis(&native_symbols);
if (n_native_symbols > 0
&& !wasm_native_register_natives("env",
native_symbols, n_native_symbols))
return false;
#endif
return true;
}
@ -286,6 +308,10 @@ wasm_native_destroy()
{
NativeSymbolsNode *node, *node_next;
#if WASM_ENABLE_LIB_PTHREAD != 0
lib_pthread_destroy();
#endif
node = g_native_symbols_list;
while (node) {
node_next = node->next;

View File

@ -15,6 +15,12 @@
#if WASM_ENABLE_AOT != 0
#include "../aot/aot_runtime.h"
#endif
#if WASM_ENABLE_THREAD_MGR != 0
#include "../libraries/thread-mgr/thread_manager.h"
#endif
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "wasm_shared_memory.h"
#endif
#if WASM_ENABLE_MULTI_MODULE != 0
/*
@ -90,25 +96,50 @@ wasm_runtime_env_init()
return false;
if (wasm_native_init() == false) {
bh_platform_destroy();
return false;
goto fail1;
}
#if WASM_ENABLE_MULTI_MODULE
if (BHT_OK != os_mutex_init(&registered_module_list_lock)) {
wasm_native_destroy();
bh_platform_destroy();
return false;
goto fail2;
}
if (BHT_OK != os_mutex_init(&loading_module_list_lock)) {
os_mutex_destroy(&registered_module_list_lock);
wasm_native_destroy();
bh_platform_destroy();
return false;
goto fail3;
}
#endif
#if WASM_ENABLE_SHARED_MEMORY
if (!wasm_shared_memory_init()) {
goto fail4;
}
#endif
#if WASM_ENABLE_THREAD_MGR != 0
if (!thread_manager_init()) {
goto fail5;
}
#endif
return true;
#if WASM_ENABLE_THREAD_MGR != 0
fail5:
#endif
#if WASM_ENABLE_SHARED_MEMORY
wasm_shared_memory_destroy();
fail4:
#endif
#if WASM_ENABLE_MULTI_MODULE
os_mutex_destroy(&loading_module_list_lock);
fail3:
os_mutex_destroy(&registered_module_list_lock);
fail2:
#endif
wasm_native_destroy();
fail1:
bh_platform_destroy();
return false;
}
static bool
@ -147,6 +178,15 @@ wasm_runtime_destroy()
wasm_runtime_destroy_registered_module_list();
os_mutex_destroy(&registered_module_list_lock);
#endif
#if WASM_ENABLE_SHARED_MEMORY
wasm_shared_memory_destroy();
#endif
#if WASM_ENABLE_THREAD_MGR != 0
thread_manager_destroy();
#endif
wasm_native_destroy();
bh_platform_destroy();
@ -191,7 +231,6 @@ get_package_type(const uint8 *buf, uint32 size)
#if WASM_ENABLE_MULTI_MODULE != 0
static module_reader reader;
static module_destroyer destroyer;
void
wasm_runtime_set_module_reader(const module_reader reader_cb,
const module_destroyer destroyer_cb)
@ -492,6 +531,42 @@ wasm_runtime_is_built_in_module(const char *module_name)
);
}
#if WASM_ENABLE_THREAD_MGR != 0
bool
wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env,
uint32 start_offset, uint32 size)
{
WASMModuleInstanceCommon *module_inst
= wasm_exec_env_get_module_inst(exec_env);
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
return wasm_set_aux_stack(exec_env, start_offset, size);
}
#endif
return false;
}
bool
wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env,
uint32 *start_offset, uint32 *size)
{
WASMModuleInstanceCommon *module_inst
= wasm_exec_env_get_module_inst(exec_env);
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
return wasm_get_aux_stack(exec_env, start_offset, size);
}
#endif
return false;
}
void
wasm_runtime_set_max_thread_num(uint32 num)
{
wasm_cluster_set_max_thread_num(num);
}
#endif /* end of WASM_ENABLE_THREAD_MGR */
static WASMModuleCommon *
register_module_with_null_name(WASMModuleCommon *module_common,
char *error_buf, uint32 error_buf_size)
@ -618,47 +693,63 @@ wasm_runtime_unload(WASMModuleCommon *module)
}
WASMModuleInstanceCommon *
wasm_runtime_instantiate(WASMModuleCommon *module,
uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
{
#if WASM_ENABLE_INTERP != 0
if (module->module_type == Wasm_Module_Bytecode)
return (WASMModuleInstanceCommon*)
wasm_instantiate((WASMModule*)module,
wasm_instantiate((WASMModule*)module, is_sub_inst,
stack_size, heap_size,
error_buf, error_buf_size);
#endif
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT)
return (WASMModuleInstanceCommon*)
aot_instantiate((AOTModule*)module,
aot_instantiate((AOTModule*)module, is_sub_inst,
stack_size, heap_size,
error_buf, error_buf_size);
#endif
set_error_buf(error_buf, error_buf_size,
"Instantiate module failed, invalid module type");
return NULL;
}
WASMModuleInstanceCommon *
wasm_runtime_instantiate(WASMModuleCommon *module,
uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
{
return wasm_runtime_instantiate_internal(module, false,
stack_size, heap_size,
error_buf, error_buf_size);
}
void
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
bool is_sub_inst)
{
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
wasm_deinstantiate((WASMModuleInstance*)module_inst);
wasm_deinstantiate((WASMModuleInstance*)module_inst, is_sub_inst);
return;
}
#endif
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
aot_deinstantiate((AOTModuleInstance*)module_inst);
aot_deinstantiate((AOTModuleInstance*)module_inst, is_sub_inst);
return;
}
#endif
}
void
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
{
return wasm_runtime_deinstantiate_internal(module_inst, false);
}
WASMExecEnv *
wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst,
uint32 stack_size)
@ -1442,6 +1533,24 @@ wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst,
}
#endif /* end of WASM_ENABLE_LIBC_WASI */
WASMModuleCommon*
wasm_exec_env_get_module(WASMExecEnv *exec_env)
{
WASMModuleInstanceCommon *module_inst =
wasm_runtime_get_module_inst(exec_env);
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode)
return (WASMModuleCommon*)
((WASMModuleInstance*)module_inst)->module;
#endif
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT)
return (WASMModuleCommon*)
((AOTModuleInstance*)module_inst)->aot_module.ptr;
#endif
return NULL;
}
/**
* Implementation of wasm_application_execute_main()
*/

View File

@ -105,6 +105,17 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
void
wasm_runtime_unload(WASMModuleCommon *module);
/* Internal API */
WASMModuleInstanceCommon *
wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size);
/* Internal API */
void
wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
bool is_sub_inst);
/* See wasm_export.h for description */
WASMModuleInstanceCommon *
wasm_runtime_instantiate(WASMModuleCommon *module,
@ -319,6 +330,16 @@ wasm_runtime_destroy_loading_module_list();
bool
wasm_runtime_is_built_in_module(const char *module_name);
#if WASM_ENABLE_THREAD_MGR != 0
bool
wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env,
uint32 *start_offset, uint32 *size);
bool
wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env,
uint32 start_offset, uint32 size);
#endif
#if WASM_ENABLE_LIBC_WASI != 0
/* See wasm_export.h for description */
void
@ -356,6 +377,10 @@ wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst);
#endif /* end of WASM_ENABLE_LIBC_WASI */
/* Get module of the current exec_env */
WASMModuleCommon*
wasm_exec_env_get_module(WASMExecEnv *exec_env);
/**
* Enlarge wasm memory data space.
*

View File

@ -0,0 +1,124 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "bh_log.h"
#include "wasm_shared_memory.h"
static bh_list shared_memory_list_head;
static bh_list *const shared_memory_list = &shared_memory_list_head;
static korp_mutex shared_memory_list_lock;
bool
wasm_shared_memory_init()
{
if (os_mutex_init(&shared_memory_list_lock) != 0)
return false;
return true;
}
void
wasm_shared_memory_destroy()
{
os_mutex_destroy(&shared_memory_list_lock);
}
static WASMSharedMemNode*
search_module(WASMModuleCommon *module)
{
WASMSharedMemNode *node;
os_mutex_lock(&shared_memory_list_lock);
node = bh_list_first_elem(shared_memory_list);
while (node) {
if (module == node->module) {
os_mutex_unlock(&shared_memory_list_lock);
return node;
}
node = bh_list_elem_next(node);
}
os_mutex_unlock(&shared_memory_list_lock);
return NULL;
}
WASMSharedMemNode*
wasm_module_get_shared_memory(WASMModuleCommon *module)
{
return search_module(module);
}
int32
shared_memory_inc_reference(WASMModuleCommon *module)
{
WASMSharedMemNode *node = search_module(module);
if (node) {
os_mutex_lock(&node->lock);
node->ref_count++;
os_mutex_unlock(&node->lock);
return node->ref_count;
}
return -1;
}
int32
shared_memory_dec_reference(WASMModuleCommon *module)
{
WASMSharedMemNode *node = search_module(module);
uint32 ref_count = 0;
if (node) {
os_mutex_lock(&node->lock);
ref_count = --node->ref_count;
os_mutex_unlock(&node->lock);
if (ref_count == 0) {
os_mutex_lock(&shared_memory_list_lock);
bh_list_remove(shared_memory_list, node);
os_mutex_unlock(&shared_memory_list_lock);
os_mutex_destroy(&node->lock);
wasm_runtime_free(node);
}
return ref_count;
}
return -1;
}
WASMMemoryInstance*
shared_memory_get_memory_inst(WASMSharedMemNode *node)
{
return node->u.wasm_memory;
}
WASMSharedMemNode*
shared_memory_set_memory_inst(WASMModuleCommon *module,
WASMMemoryInstance *memory)
{
WASMSharedMemNode *node;
bh_list_status ret;
if (!(node = wasm_runtime_malloc(sizeof(WASMSharedMemNode))))
return NULL;
node->module = module;
node->u.wasm_memory = memory;
node->ref_count = 1;
if (os_mutex_init(&node->lock) != 0) {
wasm_runtime_free(node);
return NULL;
}
os_mutex_lock(&shared_memory_list_lock);
ret = bh_list_insert(shared_memory_list, node);
bh_assert(ret == BH_LIST_SUCCESS);
os_mutex_unlock(&shared_memory_list_lock);
(void)ret;
return node;
}
#endif /* end of WASM_ENABLE_SHARED_MEMORY */

View File

@ -0,0 +1,82 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _WASM_SHARED_MEMORY_H
#define _WASM_SHARED_MEMORY_H
#include "bh_common.h"
#if WASM_ENABLE_INTERP != 0
#include "wasm_runtime.h"
#endif
#if WASM_ENABLE_AOT != 0
#include "aot_runtime.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct WASMSharedMemNode {
bh_list_link l;
/* Lock */
korp_mutex lock;
/* The module reference */
WASMModuleCommon *module;
/* The memory information */
union {
#if WASM_ENABLE_INTERP
WASMMemoryInstance *wasm_memory;
#endif
#if WASM_ENABLE_AOT
struct {
/* memory space info */
uint32 mem_cur_page_count;
uint32 mem_max_page_count;
uint32 memory_data_size;
AOTPointer memory_data;
AOTPointer memory_data_end;
/* heap space info */
int32 heap_base_offset;
uint32 heap_data_size;
AOTPointer heap_data;
AOTPointer heap_data_end;
AOTPointer heap_handle;
} aot_memory;
#endif
} u;
/* reference count */
uint32 ref_count;
} WASMSharedMemNode;
bool
wasm_shared_memory_init();
void
wasm_shared_memory_destroy();
WASMSharedMemNode*
wasm_module_get_shared_memory(WASMModuleCommon *module);
int32
shared_memory_inc_reference(WASMModuleCommon *module);
int32
shared_memory_dec_reference(WASMModuleCommon *module);
WASMMemoryInstance*
shared_memory_get_memory_inst(WASMSharedMemNode *node);
WASMSharedMemNode*
shared_memory_set_memory_inst(WASMModuleCommon *module,
WASMMemoryInstance *memory);
#ifdef __cplusplus
}
#endif
#endif /* end of _WASM_SHARED_MEMORY_H */