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

@ -482,28 +482,28 @@ LOAD_PTR(void *addr)
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(1); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint32)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(2); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint32)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(4); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = LOAD_I32(maddr); \
STORE_U32(maddr, readv op sval); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
PUSH_I32(readv); \
break; \
@ -522,39 +522,39 @@ LOAD_PTR(void *addr)
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(1); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(2); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(4); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)LOAD_U32(maddr); \
STORE_U32(maddr, (uint32)(readv op sval)); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else { \
uint64 op_result; \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(8); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)LOAD_I64(maddr); \
op_result = readv op sval; \
STORE_I64(maddr, op_result); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
PUSH_I64(readv); \
break; \
@ -1166,10 +1166,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMFunctionInstance *cur_func,
WASMInterpFrame *prev_frame)
{
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
#endif
WASMMemoryInstance *memory = wasm_get_default_memory(module);
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
@ -3353,23 +3349,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)(*(uint8 *)maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)LOAD_U16(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = LOAD_I32(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I32(readv);
@ -3388,30 +3384,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)(*(uint8 *)maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U16(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U32(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = LOAD_I64(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I64(readv);
@ -3429,23 +3425,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U32(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
break;
}
@ -3463,30 +3459,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U32(maddr, (uint32)sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_I64(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
break;
}
@ -3506,32 +3502,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(1);
expect = (uint8)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
expect = (uint16)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = LOAD_I32(maddr);
if (readv == expect)
STORE_U32(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I32(readv);
break;
@ -3552,43 +3548,43 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(1);
expect = (uint8)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
expect = (uint16)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
expect = (uint32)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U32(maddr);
if (readv == expect)
STORE_U32(maddr, (uint32)(sval));
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_I64(maddr);
if (readv == expect)
STORE_I64(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I64(readv);
break;