Use shared memory lock for threads generated from same module (#1960)

Multiple threads generated from the same module should use the same
lock to protect the atomic operations.

Before this PR, each thread used a different lock to protect atomic
operations (e.g. atomic add), making the lock ineffective.

Fix #1958.
This commit is contained in:
Enrico Loparco 2023-02-16 04:54:19 +01:00 committed by GitHub
parent 1c17665f68
commit 216dc43ab4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 203 additions and 146 deletions

View File

@ -172,6 +172,7 @@ shared_memory_dec_reference(WASMModuleCommon *module)
bh_list_remove(shared_memory_list, node);
os_mutex_unlock(&shared_memory_list_lock);
os_mutex_destroy(&node->shared_mem_lock);
os_mutex_destroy(&node->lock);
wasm_runtime_free(node);
}
@ -200,7 +201,14 @@ shared_memory_set_memory_inst(WASMModuleCommon *module,
node->module = module;
node->memory_inst = memory;
node->ref_count = 1;
if (os_mutex_init(&node->shared_mem_lock) != 0) {
wasm_runtime_free(node);
return NULL;
}
if (os_mutex_init(&node->lock) != 0) {
os_mutex_destroy(&node->shared_mem_lock);
wasm_runtime_free(node);
return NULL;
}

View File

@ -26,6 +26,8 @@ typedef struct WASMSharedMemNode {
WASMModuleCommon *module;
/* The memory information */
WASMMemoryInstanceCommon *memory_inst;
/* Lock used for atomic operations */
korp_mutex shared_mem_lock;
/* reference count */
uint32 ref_count;

View File

@ -511,7 +511,7 @@ struct WASMModule {
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0)
/**
* List of instances referred to this module. When source debugging

View File

@ -696,28 +696,28 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint32)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint32)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
else { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = LOAD_I32(maddr); \
STORE_U32(maddr, readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
PUSH_I32(readv); \
break; \
@ -736,39 +736,39 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_U32(maddr); \
STORE_U32(maddr, (uint32)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
else { \
uint64 op_result; \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_I64(maddr); \
op_result = readv op sval; \
STORE_I64(maddr, op_result); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
PUSH_I64(readv); \
break; \
@ -1151,6 +1151,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 cache_index, type_index, param_cell_num, cell_num;
uint8 value_type;
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
uint8 *frame_ip_orig = NULL;
WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env);
@ -3458,23 +3463,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();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)(*(uint8 *)maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)LOAD_U16(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I32(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
PUSH_I32(readv);
@ -3493,30 +3498,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();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)(*(uint8 *)maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U16(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U32(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I64(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
PUSH_I64(readv);
@ -3535,23 +3540,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();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
STORE_U32(maddr, frame_sp[1]);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
break;
}
@ -3569,31 +3574,31 @@ 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();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
STORE_U32(maddr, (uint32)sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
PUT_I64_TO_ADDR((uint32 *)maddr,
GET_I64_FROM_ADDR(frame_sp + 1));
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
break;
}
@ -3613,32 +3618,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint8)expect;
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint16)expect;
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I32(maddr);
if (readv == expect)
STORE_U32(maddr, sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
PUSH_I32(readv);
break;
@ -3659,44 +3664,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint8)expect;
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint16)expect;
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint32)expect;
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U32(maddr);
if (readv == expect)
STORE_U32(maddr, (uint32)(sval));
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_I64(maddr);
if (readv == expect) {
STORE_I64(maddr, sval);
}
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
PUSH_I64(readv);
break;

View File

@ -469,28 +469,28 @@ LOAD_PTR(void *addr)
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(1); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint32)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
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(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint32)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
else { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(4); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = LOAD_I32(maddr); \
STORE_U32(maddr, readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
PUSH_I32(readv); \
break; \
@ -509,39 +509,39 @@ LOAD_PTR(void *addr)
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(1); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
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(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
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(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_U32(maddr); \
STORE_U32(maddr, (uint32)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
else { \
uint64 op_result; \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(8); \
\
os_mutex_lock(&module->e->mem_lock); \
os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_I64(maddr); \
op_result = readv op sval; \
STORE_I64(maddr, op_result); \
os_mutex_unlock(&module->e->mem_lock); \
os_mutex_unlock(&node->shared_mem_lock); \
} \
PUSH_I64(readv); \
break; \
@ -1183,6 +1183,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 local_idx, local_offset, global_idx;
uint8 opcode, local_type, *global_addr;
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
#endif
#if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OPCODE(op) &&HANDLE_##op
DEFINE_GOTO_TABLE(const void *, handle_table);
@ -3296,23 +3301,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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)(*(uint8 *)maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)LOAD_U16(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I32(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
PUSH_I32(readv);
@ -3331,30 +3336,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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)(*(uint8 *)maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U16(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U32(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I64(maddr);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
PUSH_I64(readv);
@ -3372,23 +3377,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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
STORE_U32(maddr, sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
break;
}
@ -3406,30 +3411,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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
STORE_U32(maddr, (uint32)sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
STORE_I64(maddr, sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
break;
}
@ -3449,32 +3454,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(1);
expect = (uint8)expect;
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I32(maddr);
if (readv == expect)
STORE_U32(maddr, sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
PUSH_I32(readv);
break;
@ -3495,44 +3500,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(1);
expect = (uint8)expect;
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
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(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U32(maddr);
if (readv == expect)
STORE_U32(maddr, (uint32)(sval));
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&module->e->mem_lock);
os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_I64(maddr);
if (readv == expect) {
STORE_I64(maddr, sval);
}
os_mutex_unlock(&module->e->mem_lock);
os_mutex_unlock(&node->shared_mem_lock);
}
PUSH_I64(readv);
break;

View File

@ -3865,7 +3865,7 @@ create_module(char *error_buf, uint32 error_buf_size)
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0)
if (os_mutex_init(&module->instance_list_lock) != 0) {
set_error_buf(error_buf, error_buf_size,
@ -4253,7 +4253,8 @@ wasm_loader_unload(WASMModule *module)
if (!module)
return;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
module->orcjit_stop_compiling = true;
if (module->llvm_jit_init_thread)
os_thread_join(module->llvm_jit_init_thread, NULL);
@ -4274,7 +4275,8 @@ wasm_loader_unload(WASMModule *module)
aot_destroy_comp_data(module->comp_data);
#endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
if (module->tierup_wait_lock_inited) {
os_mutex_destroy(&module->tierup_wait_lock);
os_cond_destroy(&module->tierup_wait_cond);
@ -4404,7 +4406,7 @@ wasm_loader_unload(WASMModule *module)
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0)
os_mutex_destroy(&module->instance_list_lock);
#endif

View File

@ -2725,7 +2725,8 @@ create_module(char *error_buf, uint32 error_buf_size)
bh_assert(ret == BH_LIST_SUCCESS);
#endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
if (os_mutex_init(&module->instance_list_lock) != 0) {
set_error_buf(error_buf, error_buf_size,
"init instance list lock failed");
@ -2946,7 +2947,8 @@ wasm_loader_unload(WASMModule *module)
if (!module)
return;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
module->orcjit_stop_compiling = true;
if (module->llvm_jit_init_thread)
os_thread_join(module->llvm_jit_init_thread, NULL);
@ -2967,7 +2969,8 @@ wasm_loader_unload(WASMModule *module)
aot_destroy_comp_data(module->comp_data);
#endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
if (module->tierup_wait_lock_inited) {
os_mutex_destroy(&module->tierup_wait_lock);
os_cond_destroy(&module->tierup_wait_cond);
@ -3063,7 +3066,8 @@ wasm_loader_unload(WASMModule *module)
}
#endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
os_mutex_destroy(&module->instance_list_lock);
#endif

View File

@ -1587,15 +1587,6 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
module_inst->e =
(WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset);
#if WASM_ENABLE_SHARED_MEMORY != 0
if (os_mutex_init(&module_inst->e->mem_lock) != 0) {
set_error_buf(error_buf, error_buf_size,
"create shared memory lock failed");
goto fail;
}
module_inst->e->mem_lock_inited = true;
#endif
#if WASM_ENABLE_MULTI_MODULE != 0
module_inst->e->sub_module_inst_list =
&module_inst->e->sub_module_inst_list_head;
@ -2159,11 +2150,6 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
}
#endif
#if WASM_ENABLE_SHARED_MEMORY != 0
if (module_inst->e->mem_lock_inited)
os_mutex_destroy(&module_inst->e->mem_lock);
#endif
if (module_inst->e->c_api_func_imports)
wasm_runtime_free(module_inst->e->c_api_func_imports);

View File

@ -223,12 +223,6 @@ typedef struct WASMModuleInstanceExtra {
CApiFuncImport *c_api_func_imports;
RunningMode running_mode;
#if WASM_ENABLE_SHARED_MEMORY != 0
/* lock for shared memory atomic operations */
korp_mutex mem_lock;
bool mem_lock_inited;
#endif
#if WASM_ENABLE_MULTI_MODULE != 0
bh_list sub_module_inst_list_head;
bh_list *sub_module_inst_list;
@ -241,7 +235,7 @@ typedef struct WASMModuleInstanceExtra {
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0)
WASMModuleInstance *next;
#endif

View File

@ -41,3 +41,6 @@ target_link_libraries(test.wasm)
add_executable(main_thread_exception.wasm main_thread_exception.c)
target_link_libraries(main_thread_exception.wasm)
add_executable(main_global_atomic.wasm main_global_atomic.c)
target_link_libraries(main_global_atomic.wasm)

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <stdio.h>
#include <pthread.h>
#define MAX_NUM_THREADS 4
#define NUM_ITER 1000
int g_count = 0;
static void *
thread(void *arg)
{
for (int i = 0; i < NUM_ITER; i++) {
__atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST);
}
return NULL;
}
int
main(int argc, char **argv)
{
pthread_t tids[MAX_NUM_THREADS];
for (int i = 0; i < MAX_NUM_THREADS; i++) {
if (pthread_create(&tids[i], NULL, thread, NULL) != 0) {
printf("Thread creation failed\n");
}
}
for (int i = 0; i < MAX_NUM_THREADS; i++) {
if (pthread_join(tids[i], NULL) != 0) {
printf("Thread join failed\n");
}
}
printf("Value of counter after update: %d (expected=%d)\n", g_count,
MAX_NUM_THREADS * NUM_ITER);
if (g_count != MAX_NUM_THREADS * NUM_ITER) {
__builtin_trap();
}
return -1;
}