Fix memory sharing (#2415)

- Inherit shared memory from the parent instance, instead of
  trying to look it up by the underlying module. The old method
  works correctly only when every cluster uses different module.
- Use reference count in WASMMemoryInstance/AOTMemoryInstance
  to mark whether the memory is shared or not
- Retire WASMSharedMemNode
- For atomic opcode implementations in the interpreters, use
  a global lock for now
- Update the internal API users
  (wasi-threads, lib-pthread, wasm_runtime_spawn_thread)

Fixes https://github.com/bytecodealliance/wasm-micro-runtime/issues/1962
This commit is contained in:
YAMAMOTO Takashi
2023-08-04 11:18:13 +09:00
committed by GitHub
parent 29761c7216
commit 91592429f4
14 changed files with 298 additions and 401 deletions

View File

@ -122,11 +122,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
}
#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 (shared_memory_is_shared(memories[i])) {
uint32 ref_count = shared_memory_dec_reference(memories[i]);
/* if the reference count is not zero,
don't free the memory */
if (ref_count > 0)
@ -159,7 +156,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
}
static WASMMemoryInstance *
memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
WASMMemoryInstance *memory, uint32 memory_idx,
uint32 num_bytes_per_page, uint32 init_page_count,
uint32 max_page_count, uint32 heap_size, uint32 flags,
char *error_buf, uint32 error_buf_size)
@ -180,22 +178,11 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
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 = (WASMMemoryInstance *)shared_memory_get_memory_inst(node);
bh_assert(memory);
(void)ref_count;
return memory;
}
if (is_shared_memory && parent != NULL) {
bh_assert(parent->memory_count > memory_idx);
memory = parent->memories[memory_idx];
shared_memory_inc_reference(memory);
return memory;
}
#endif /* end of WASM_ENABLE_SHARED_MEMORY */
@ -388,24 +375,13 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
#if WASM_ENABLE_SHARED_MEMORY != 0
if (is_shared_memory) {
memory->is_shared = true;
if (!shared_memory_set_memory_inst(
(WASMModuleCommon *)module_inst->module,
(WASMMemoryInstanceCommon *)memory)) {
set_error_buf(error_buf, error_buf_size, "allocate memory failed");
goto fail4;
}
memory->ref_count = 1;
}
#endif
LOG_VERBOSE("Memory instantiate success.");
return memory;
#if WASM_ENABLE_SHARED_MEMORY != 0
fail4:
if (heap_size > 0)
mem_allocator_destroy(memory->heap_handle);
#endif
fail3:
if (heap_size > 0)
wasm_runtime_free(memory->heap_handle);
@ -428,7 +404,8 @@ fail1:
*/
static WASMMemoryInstance **
memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
uint32 heap_size, char *error_buf, uint32 error_buf_size)
WASMModuleInstance *parent, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
{
WASMImport *import;
uint32 mem_index = 0, i,
@ -474,26 +451,29 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
else
#endif
{
if (!(memories[mem_index++] = memory_instantiate(
module_inst, memory, num_bytes_per_page, init_page_count,
max_page_count, actual_heap_size, flags, error_buf,
error_buf_size))) {
if (!(memories[mem_index] = memory_instantiate(
module_inst, parent, memory, mem_index,
num_bytes_per_page, init_page_count, max_page_count,
actual_heap_size, flags, error_buf, error_buf_size))) {
memories_deinstantiate(module_inst, memories, memory_count);
return NULL;
}
mem_index++;
}
}
/* instantiate memories from memory section */
for (i = 0; i < module->memory_count; i++, memory++) {
if (!(memories[mem_index++] = memory_instantiate(
module_inst, memory, module->memories[i].num_bytes_per_page,
if (!(memories[mem_index] = memory_instantiate(
module_inst, parent, memory, mem_index,
module->memories[i].num_bytes_per_page,
module->memories[i].init_page_count,
module->memories[i].max_page_count, heap_size,
module->memories[i].flags, error_buf, error_buf_size))) {
memories_deinstantiate(module_inst, memories, memory_count);
return NULL;
}
mem_index++;
}
bh_assert(mem_index == memory_count);
@ -1301,7 +1281,7 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
WASMModuleInstance *sub_module_inst = NULL;
sub_module_inst =
wasm_instantiate(sub_module, false, NULL, stack_size, heap_size,
wasm_instantiate(sub_module, NULL, NULL, stack_size, heap_size,
error_buf, error_buf_size);
if (!sub_module_inst) {
LOG_DEBUG("instantiate %s failed",
@ -1646,7 +1626,7 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode)
* Instantiate module
*/
WASMModuleInstance *
wasm_instantiate(WASMModule *module, bool is_sub_inst,
wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
WASMExecEnv *exec_env_main, uint32 stack_size,
uint32 heap_size, char *error_buf, uint32 error_buf_size)
{
@ -1663,6 +1643,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
#if WASM_ENABLE_MULTI_MODULE != 0
bool ret = false;
#endif
const bool is_sub_inst = parent != NULL;
if (!module)
return NULL;
@ -1781,8 +1762,9 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
/* Instantiate memories/tables/functions */
if ((module_inst->memory_count > 0
&& !(module_inst->memories = memories_instantiate(
module, module_inst, heap_size, error_buf, error_buf_size)))
&& !(module_inst->memories =
memories_instantiate(module, module_inst, parent, heap_size,
error_buf, error_buf_size)))
|| (module_inst->table_count > 0
&& !(module_inst->tables =
tables_instantiate(module, module_inst, first_table,