Refine lock/unlock shared memory (#2682)

Split memory instance's field `uint32 ref_count` into `bool is_shared_memory`
and `uint16 ref_count`, and lock the memory only when `is_shared_memory`
flag is true, no need to acquire a lock for non-shared memory when shared
memory feature is enabled.
This commit is contained in:
Wenyong Huang
2023-10-31 11:46:03 +08:00
committed by GitHub
parent 3570a94a08
commit 52db362b89
7 changed files with 110 additions and 64 deletions

View File

@ -547,8 +547,6 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
return false;
}
SHARED_MEMORY_LOCK(memory_inst);
native_addr = memory_inst->memory_data + app_buf_addr;
bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst);
@ -563,6 +561,8 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
/* No need to check the app_offset and buf_size if memory access
boundary check with hardware trap is enabled */
#ifndef OS_ENABLE_HW_BOUND_CHECK
SHARED_MEMORY_LOCK(memory_inst);
if (app_buf_addr >= memory_inst->memory_data_size) {
goto fail;
}
@ -583,9 +583,9 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
if (str == str_end)
goto fail;
}
#endif
SHARED_MEMORY_UNLOCK(memory_inst);
#endif
success:
*p_native_addr = (void *)native_addr;

View File

@ -18,7 +18,7 @@
* - If you care performance, it's better to make the interpreters
* use atomic ops.
*/
static korp_mutex _shared_memory_lock;
korp_mutex g_shared_memory_lock;
/* clang-format off */
enum {
@ -55,13 +55,13 @@ destroy_wait_info(void *wait_info);
bool
wasm_shared_memory_init()
{
if (os_mutex_init(&_shared_memory_lock) != 0)
if (os_mutex_init(&g_shared_memory_lock) != 0)
return false;
/* wait map not exists, create new map */
if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash,
(KeyEqualFunc)wait_address_equal, NULL,
destroy_wait_info))) {
os_mutex_destroy(&_shared_memory_lock);
os_mutex_destroy(&g_shared_memory_lock);
return false;
}
return true;
@ -71,79 +71,47 @@ void
wasm_shared_memory_destroy()
{
bh_hash_map_destroy(wait_map);
os_mutex_destroy(&_shared_memory_lock);
os_mutex_destroy(&g_shared_memory_lock);
}
uint32
uint16
shared_memory_inc_reference(WASMMemoryInstance *memory)
{
bh_assert(shared_memory_is_shared(memory));
uint32 old;
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_lock(&_shared_memory_lock);
uint16 old;
#if BH_ATOMIC_16_IS_ATOMIC == 0
os_mutex_lock(&g_shared_memory_lock);
#endif
old = BH_ATOMIC_32_FETCH_ADD(memory->ref_count, 1);
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_unlock(&_shared_memory_lock);
old = BH_ATOMIC_16_FETCH_ADD(memory->ref_count, 1);
#if BH_ATOMIC_16_IS_ATOMIC == 0
os_mutex_unlock(&g_shared_memory_lock);
#endif
bh_assert(old >= 1);
bh_assert(old < UINT32_MAX);
bh_assert(old < UINT16_MAX);
return old + 1;
}
uint32
uint16
shared_memory_dec_reference(WASMMemoryInstance *memory)
{
bh_assert(shared_memory_is_shared(memory));
uint32 old;
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_lock(&_shared_memory_lock);
uint16 old;
#if BH_ATOMIC_16_IS_ATOMIC == 0
os_mutex_lock(&g_shared_memory_lock);
#endif
old = BH_ATOMIC_32_FETCH_SUB(memory->ref_count, 1);
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_unlock(&_shared_memory_lock);
old = BH_ATOMIC_16_FETCH_SUB(memory->ref_count, 1);
#if BH_ATOMIC_16_IS_ATOMIC == 0
os_mutex_unlock(&g_shared_memory_lock);
#endif
bh_assert(old > 0);
return old - 1;
}
bool
shared_memory_is_shared(WASMMemoryInstance *memory)
{
uint32 old;
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_lock(&_shared_memory_lock);
#endif
old = BH_ATOMIC_32_LOAD(memory->ref_count);
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_unlock(&_shared_memory_lock);
#endif
return old > 0;
}
static korp_mutex *
shared_memory_get_lock_pointer(WASMMemoryInstance *memory)
{
bh_assert(memory != NULL);
return &_shared_memory_lock;
}
void
shared_memory_lock(WASMMemoryInstance *memory)
{
/*
* Note: exception logic is currently abusing this lock.
* cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/2407
*/
bh_assert(memory != NULL);
os_mutex_lock(&_shared_memory_lock);
}
void
shared_memory_unlock(WASMMemoryInstance *memory)
{
bh_assert(memory != NULL);
os_mutex_unlock(&_shared_memory_lock);
return &g_shared_memory_lock;
}
/* Atomics wait && notify APIs */

View File

@ -14,26 +14,39 @@
extern "C" {
#endif
extern korp_mutex g_shared_memory_lock;
bool
wasm_shared_memory_init();
void
wasm_shared_memory_destroy();
uint32
uint16
shared_memory_inc_reference(WASMMemoryInstance *memory);
uint32
uint16
shared_memory_dec_reference(WASMMemoryInstance *memory);
bool
shared_memory_is_shared(WASMMemoryInstance *memory);
#define shared_memory_is_shared(memory) memory->is_shared_memory
void
shared_memory_lock(WASMMemoryInstance *memory);
#define shared_memory_lock(memory) \
do { \
/* \
* Note: exception logic is currently abusing this lock. \
* cf. \
* https://github.com/bytecodealliance/wasm-micro-runtime/issues/2407 \
*/ \
bh_assert(memory != NULL); \
if (memory->is_shared_memory) \
os_mutex_lock(&g_shared_memory_lock); \
} while (0)
void
shared_memory_unlock(WASMMemoryInstance *memory);
#define shared_memory_unlock(memory) \
do { \
if (memory->is_shared_memory) \
os_mutex_unlock(&g_shared_memory_lock); \
} while (0)
uint32
wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,