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

@ -10,6 +10,9 @@
#include "bh_log.h"
#include "mem_alloc.h"
#include "../common/wasm_runtime_common.h"
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "../common/wasm_shared_memory.h"
#endif
static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
@ -86,6 +89,19 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
#if WASM_ENABLE_MULTI_MODULE != 0
if (memories[i]->owner != module_inst)
continue;
#endif
#if WASM_ENABLE_SHARED_MEMORY != 0
if (memories[i]->is_shared) {
int32 ref_count =
shared_memory_dec_reference(
(WASMModuleCommon *)module_inst->module);
bh_assert(ref_count >= 0);
/* if the reference count is not zero,
don't free the memory */
if (ref_count > 0)
continue;
}
#endif
if (memories[i]->heap_handle) {
mem_allocator_destroy(memories[i]->heap_handle);
@ -99,16 +115,45 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
}
static WASMMemoryInstance*
memory_instantiate(uint32 num_bytes_per_page,
memory_instantiate(WASMModuleInstance *module_inst,
uint32 num_bytes_per_page,
uint32 init_page_count, uint32 max_page_count,
uint32 heap_size,
uint32 heap_size, uint32 flags,
char *error_buf, uint32 error_buf_size)
{
WASMMemoryInstance *memory;
uint64 total_size = offsetof(WASMMemoryInstance, base_addr) +
(uint64)heap_size +
uint64 heap_and_inst_size = offsetof(WASMMemoryInstance, base_addr) +
(uint64)heap_size;
uint64 total_size = heap_and_inst_size +
num_bytes_per_page * (uint64)init_page_count;
#if WASM_ENABLE_SHARED_MEMORY != 0
bool is_shared_memory = flags & 0x02 ? true : false;
/* shared memory */
if (is_shared_memory) {
WASMSharedMemNode *node =
wasm_module_get_shared_memory(
(WASMModuleCommon *)module_inst->module);
/* If the memory of this module has been instantiated,
return the memory instance directly */
if (node) {
uint32 ref_count;
ref_count = shared_memory_inc_reference(
(WASMModuleCommon *)module_inst->module);
bh_assert(ref_count > 0);
memory = shared_memory_get_memory_inst(node);
bh_assert(memory);
(void)ref_count;
return memory;
}
/* Allocate max page for shared memory */
total_size = heap_and_inst_size +
num_bytes_per_page * (uint64)max_page_count;
}
#endif
/* Allocate memory space, addr data and global data */
if (!(memory = runtime_malloc(total_size,
error_buf, error_buf_size))) {
@ -121,8 +166,17 @@ memory_instantiate(uint32 num_bytes_per_page,
memory->heap_data = memory->base_addr;
memory->memory_data = memory->heap_data + heap_size;
memory->end_addr = memory->memory_data +
num_bytes_per_page * memory->cur_page_count;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (is_shared_memory) {
memory->end_addr = memory->memory_data +
num_bytes_per_page * memory->max_page_count;
}
else
#endif
{
memory->end_addr = memory->memory_data +
num_bytes_per_page * memory->cur_page_count;
}
bh_assert(memory->end_addr - (uint8*)memory == (uint32)total_size);
@ -134,10 +188,20 @@ memory_instantiate(uint32 num_bytes_per_page,
return NULL;
}
#if WASM_ENABLE_SPEC_TEST == 0
memory->heap_base_offset = -(int32)heap_size;
#else
memory->heap_base_offset = 0;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (is_shared_memory) {
memory->is_shared = true;
if (!shared_memory_set_memory_inst(
(WASMModuleCommon *)module_inst->module, memory)) {
set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed:"
"allocate memory failed.");
wasm_runtime_free(memory);
return NULL;
}
}
#endif
return memory;
}
@ -169,6 +233,7 @@ memories_instantiate(const WASMModule *module,
uint32 num_bytes_per_page = import->u.memory.num_bytes_per_page;
uint32 init_page_count = import->u.memory.init_page_count;
uint32 max_page_count = import->u.memory.max_page_count;
uint32 flags = import->u.memory.flags;
uint32 actual_heap_size = heap_size;
#if WASM_ENABLE_MULTI_MODULE != 0
@ -197,8 +262,9 @@ memories_instantiate(const WASMModule *module,
#endif
{
if (!(memory = memories[mem_index++] = memory_instantiate(
num_bytes_per_page, init_page_count, max_page_count,
actual_heap_size, error_buf, error_buf_size))) {
module_inst, num_bytes_per_page, init_page_count,
max_page_count, actual_heap_size, flags,
error_buf, error_buf_size))) {
set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed: "
"allocate memory failed.");
@ -213,10 +279,12 @@ memories_instantiate(const WASMModule *module,
/* instantiate memories from memory section */
for (i = 0; i < module->memory_count; i++) {
if (!(memory = memories[mem_index++] =
memory_instantiate(module->memories[i].num_bytes_per_page,
memory_instantiate(module_inst,
module->memories[i].num_bytes_per_page,
module->memories[i].init_page_count,
module->memories[i].max_page_count,
heap_size, error_buf, error_buf_size))) {
heap_size, module->memories[i].flags,
error_buf, error_buf_size))) {
set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed: "
"allocate memory failed.");
@ -236,7 +304,7 @@ memories_instantiate(const WASMModule *module,
* for wasm code
*/
if (!(memory = memories[mem_index++] =
memory_instantiate(0, 0, 0, heap_size,
memory_instantiate(module_inst, 0, 0, 0, heap_size, 0,
error_buf, error_buf_size))) {
set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed: "
@ -792,6 +860,36 @@ execute_post_inst_function(WASMModuleInstance *module_inst)
0, NULL);
}
#if WASM_ENABLE_BULK_MEMORY != 0
static bool
execute_memory_init_function(WASMModuleInstance *module_inst)
{
WASMFunctionInstance *memory_init_func = NULL;
WASMType *memory_init_func_type;
uint32 i;
for (i = 0; i < module_inst->export_func_count; i++)
if (!strcmp(module_inst->export_functions[i].name, "__wasm_call_ctors")) {
memory_init_func = module_inst->export_functions[i].function;
break;
}
if (!memory_init_func)
/* Not found */
return true;
memory_init_func_type = memory_init_func->u.func->func_type;
if (memory_init_func_type->param_count != 0
|| memory_init_func_type->result_count != 0)
/* Not a valid function type, ignore it */
return true;
return wasm_create_exec_env_and_call_function(module_inst,
memory_init_func,
0, NULL);
}
#endif
static bool
execute_start_function(WASMModuleInstance *module_inst)
{
@ -819,7 +917,7 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
while (sub_module_list_node) {
WASMModule *sub_module = (WASMModule*)sub_module_list_node->module;
WASMModuleInstance *sub_module_inst = wasm_instantiate(
sub_module, stack_size, heap_size, error_buf, error_buf_size);
sub_module, false, stack_size, heap_size, error_buf, error_buf_size);
if (!sub_module_inst) {
LOG_DEBUG("instantiate %s failed",
sub_module_list_node->module_name);
@ -833,7 +931,7 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
if (!sub_module_inst_list_node) {
LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d",
sizeof(WASMSubModInstNode));
wasm_deinstantiate(sub_module_inst);
wasm_deinstantiate(sub_module_inst, false);
return false;
}
@ -859,7 +957,7 @@ sub_module_deinstantiate(WASMModuleInstance *module_inst)
while (node) {
WASMSubModInstNode *next_node = bh_list_elem_next(node);
bh_list_remove(list, node);
wasm_deinstantiate(node->module_inst);
wasm_deinstantiate(node->module_inst, false);
node = next_node;
}
}
@ -869,7 +967,7 @@ sub_module_deinstantiate(WASMModuleInstance *module_inst)
* Instantiate module
*/
WASMModuleInstance*
wasm_instantiate(WASMModule *module,
wasm_instantiate(WASMModule *module, bool is_sub_inst,
uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
{
@ -887,10 +985,6 @@ wasm_instantiate(WASMModule *module,
/* Check heap size */
heap_size = align_uint(heap_size, 8);
if (heap_size == 0)
heap_size = APP_HEAP_SIZE_DEFAULT;
if (heap_size < APP_HEAP_SIZE_MIN)
heap_size = APP_HEAP_SIZE_MIN;
if (heap_size > APP_HEAP_SIZE_MAX)
heap_size = APP_HEAP_SIZE_MAX;
@ -904,6 +998,8 @@ wasm_instantiate(WASMModule *module,
memset(module_inst, 0, (uint32)sizeof(WASMModuleInstance));
module_inst->module = module;
#if WASM_ENABLE_MULTI_MODULE != 0
module_inst->sub_module_inst_list =
&module_inst->sub_module_inst_list_head;
@ -911,7 +1007,7 @@ wasm_instantiate(WASMModule *module,
error_buf, error_buf_size);
if (!ret) {
LOG_DEBUG("build a sub module list failed");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
#endif
@ -922,7 +1018,7 @@ wasm_instantiate(WASMModule *module,
module,
module_inst,
&global_data_size, error_buf, error_buf_size))) {
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
module_inst->global_count = global_count;
@ -946,7 +1042,7 @@ wasm_instantiate(WASMModule *module,
if (global_count > 0) {
if (!(module_inst->global_data = runtime_malloc
(global_data_size, error_buf, error_buf_size))) {
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
}
@ -978,7 +1074,7 @@ wasm_instantiate(WASMModule *module,
error_buf, error_buf_size)))
#endif
) {
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -989,7 +1085,7 @@ wasm_instantiate(WASMModule *module,
*/
if (!globals_instantiate_fix(globals, module,
error_buf, error_buf_size)) {
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1063,7 +1159,7 @@ wasm_instantiate(WASMModule *module,
memory_size);
set_error_buf(error_buf, error_buf_size,
"data segment does not fit.");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1075,7 +1171,7 @@ wasm_instantiate(WASMModule *module,
set_error_buf(
error_buf, error_buf_size,
"Instantiate module failed: data segment does not fit.");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1121,7 +1217,7 @@ wasm_instantiate(WASMModule *module,
table_seg->base_offset.u.i32, table->cur_size);
set_error_buf(error_buf, error_buf_size,
"elements segment does not fit");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1132,7 +1228,7 @@ wasm_instantiate(WASMModule *module,
table_seg->base_offset.u.i32, length, table->cur_size);
set_error_buf(error_buf, error_buf_size,
"elements segment does not fit");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1149,18 +1245,22 @@ wasm_instantiate(WASMModule *module,
}
#if WASM_ENABLE_LIBC_WASI != 0
if (!wasm_runtime_init_wasi((WASMModuleInstanceCommon*)module_inst,
module->wasi_args.dir_list,
module->wasi_args.dir_count,
module->wasi_args.map_dir_list,
module->wasi_args.map_dir_count,
module->wasi_args.env,
module->wasi_args.env_count,
module->wasi_args.argv,
module->wasi_args.argc,
error_buf, error_buf_size)) {
wasm_deinstantiate(module_inst);
return NULL;
/* The sub-instance will get the wasi_ctx from main-instance */
if (!is_sub_inst) {
if (heap_size > 0
&& !wasm_runtime_init_wasi((WASMModuleInstanceCommon*)module_inst,
module->wasi_args.dir_list,
module->wasi_args.dir_count,
module->wasi_args.map_dir_list,
module->wasi_args.map_dir_count,
module->wasi_args.env,
module->wasi_args.env_count,
module->wasi_args.argv,
module->wasi_args.argc,
error_buf, error_buf_size)) {
wasm_deinstantiate(module_inst, false);
return NULL;
}
}
#endif
@ -1171,8 +1271,6 @@ wasm_instantiate(WASMModule *module,
&module_inst->functions[module->start_function];
}
module_inst->module = module;
/* module instance type */
module_inst->module_type = Wasm_Module_Bytecode;
@ -1190,16 +1288,36 @@ wasm_instantiate(WASMModule *module,
|| !execute_start_function(module_inst)) {
set_error_buf(error_buf, error_buf_size,
module_inst->cur_exception);
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
#if WASM_ENABLE_BULK_MEMORY != 0
#if WASM_ENABLE_LIBC_WASI != 0
if (!module->is_wasi_module) {
#endif
/* Only execute the memory init function for main instance because
the data segments will be dropped once initialized.
*/
if (!is_sub_inst) {
if (!execute_memory_init_function(module_inst)) {
set_error_buf(error_buf, error_buf_size,
module_inst->cur_exception);
wasm_deinstantiate(module_inst, false);
return NULL;
}
}
#if WASM_ENABLE_LIBC_WASI != 0
}
#endif
#endif
(void)global_data_end;
return module_inst;
}
void
wasm_deinstantiate(WASMModuleInstance *module_inst)
wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
{
if (!module_inst)
return;
@ -1213,7 +1331,9 @@ wasm_deinstantiate(WASMModuleInstance *module_inst)
wasi contex are allocated from app heap, and if app heap is freed,
these fields will be set to NULL, we cannot free their internal data
which may allocated from global heap. */
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst);
/* Only destroy wasi ctx in the main module instance */
if (!is_sub_inst)
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst);
#endif
if (module_inst->memory_count > 0)
@ -1299,8 +1419,9 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
WASMExecEnv *exec_env;
bool ret;
if (!(exec_env = wasm_exec_env_create((WASMModuleInstanceCommon*)module_inst,
module_inst->default_wasm_stack_size))) {
if (!(exec_env = wasm_exec_env_create(
(WASMModuleInstanceCommon*)module_inst,
module_inst->default_wasm_stack_size))) {
wasm_set_exception(module_inst, "allocate memory failed.");
return false;
}
@ -1518,6 +1639,15 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
return false;
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (memory->is_shared) {
/* For shared memory, we have reserved the maximum spaces during
instantiate, only change the cur_page_count here */
memory->cur_page_count = total_page_count;
return true;
}
#endif
if (heap_size > 0) {
/* Destroy heap's lock firstly, if its memory is re-allocated,
we cannot access its lock again. */
@ -1612,3 +1742,66 @@ wasm_call_indirect(WASMExecEnv *exec_env,
got_exception:
return false;
}
#if WASM_ENABLE_THREAD_MGR != 0
bool
wasm_set_aux_stack(WASMExecEnv *exec_env,
uint32 start_offset, uint32 size)
{
WASMModuleInstance *module_inst =
(WASMModuleInstance*)exec_env->module_inst;
uint32 stack_top_idx =
module_inst->module->llvm_aux_stack_global_index;
uint32 data_end =
module_inst->module->llvm_aux_data_end;
uint32 stack_bottom =
module_inst->module->llvm_aux_stack_bottom;
bool is_stack_before_data =
stack_bottom < data_end ? true : false;
/* Check the aux stack space, currently we don't allocate space in heap */
if ((is_stack_before_data && (size > start_offset))
|| ((!is_stack_before_data) && (start_offset - data_end < size)))
return false;
if (stack_bottom) {
/* The aux stack top is a wasm global,
set the initial value for the global */
uint8 *global_addr =
module_inst->global_data +
module_inst->globals[stack_top_idx].data_offset;
*(int32*)global_addr = start_offset;
/* The aux stack boundary is a constant value,
set the value to exec_env */
exec_env->aux_stack_boundary = start_offset - size;
return true;
}
return false;
}
bool
wasm_get_aux_stack(WASMExecEnv *exec_env,
uint32 *start_offset, uint32 *size)
{
WASMModuleInstance *module_inst =
(WASMModuleInstance*)exec_env->module_inst;
/* The aux stack information is resolved in loader
and store in module */
uint32 stack_bottom =
module_inst->module->llvm_aux_stack_bottom;
uint32 total_aux_stack_size =
module_inst->module->llvm_aux_stack_size;
if (stack_bottom != 0 && total_aux_stack_size != 0) {
if (start_offset)
*start_offset = stack_bottom;
if (size)
*size = total_aux_stack_size;
return true;
}
return false;
}
#endif