-
Notifications
You must be signed in to change notification settings - Fork 812
Fix wait_info data race for deletion + fix atomic_wait logic #2016
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
c0f13de
8fdbc12
b30a14c
962e46f
327c1a3
2f69b0d
3e1a974
bc9fa8b
388684d
8bf4aab
1efcb64
bcd639d
6c21413
e81fa95
2970e7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,9 @@ | |
|
|
||
| #include "bh_log.h" | ||
| #include "wasm_shared_memory.h" | ||
| #if WASM_ENABLE_THREAD_MGR != 0 | ||
| #include "../libraries/thread-mgr/thread_manager.h" | ||
| #endif | ||
|
|
||
| static bh_list shared_memory_list_head; | ||
| static bh_list *const shared_memory_list = &shared_memory_list_head; | ||
|
|
@@ -298,7 +301,7 @@ notify_wait_list(bh_list *wait_list, uint32 count) | |
| } | ||
|
|
||
| static AtomicWaitInfo * | ||
| acquire_wait_info(void *address, bool create) | ||
| acquire_wait_info(void *address, bool create, AtomicWaitNode *wait_node) | ||
| { | ||
| AtomicWaitInfo *wait_info = NULL; | ||
| bh_list_status ret; | ||
|
|
@@ -308,7 +311,7 @@ acquire_wait_info(void *address, bool create) | |
| if (address) | ||
| wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address); | ||
|
|
||
| if (!create) { | ||
| if (!create && !wait_info) { | ||
| os_mutex_unlock(&wait_map_lock); | ||
| return wait_info; | ||
| } | ||
|
|
@@ -335,6 +338,13 @@ acquire_wait_info(void *address, bool create) | |
| goto fail3; | ||
| } | ||
| } | ||
| if (wait_node) { | ||
| os_mutex_lock(&wait_info->wait_list_lock); | ||
| ret = bh_list_insert(wait_info->wait_list, wait_node); | ||
| os_mutex_unlock(&wait_info->wait_list_lock); | ||
| bh_assert(ret == BH_LIST_SUCCESS); | ||
| (void)ret; | ||
| } | ||
|
|
||
| os_mutex_unlock(&wait_map_lock); | ||
|
|
||
|
|
@@ -380,17 +390,24 @@ static bool | |
| map_remove_wait_info(HashMap *wait_map_, AtomicWaitInfo *wait_info, | ||
| void *address) | ||
| { | ||
| os_mutex_lock(&wait_map_lock); | ||
|
g0djan marked this conversation as resolved.
|
||
| os_mutex_lock(&wait_info->wait_list_lock); | ||
| if (wait_info->wait_list->len > 0) { | ||
|
g0djan marked this conversation as resolved.
|
||
| os_mutex_unlock(&wait_info->wait_list_lock); | ||
| os_mutex_unlock(&wait_map_lock); | ||
| return false; | ||
| } | ||
| os_mutex_unlock(&wait_info->wait_list_lock); | ||
|
wenyongh marked this conversation as resolved.
|
||
|
|
||
| bh_hash_map_remove(wait_map_, address, NULL, NULL); | ||
| os_mutex_unlock(&wait_map_lock); | ||
| return true; | ||
| } | ||
|
|
||
| uint32 | ||
| wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, | ||
| uint64 expect, int64 timeout, bool wait64) | ||
| uint64 expect, int64 timeout, bool wait64, | ||
| WASMExecEnv *exec_env) | ||
|
wenyongh marked this conversation as resolved.
Outdated
|
||
| { | ||
| WASMModuleInstance *module_inst = (WASMModuleInstance *)module; | ||
| AtomicWaitInfo *wait_info; | ||
|
|
@@ -418,14 +435,6 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, | |
| return -1; | ||
| } | ||
|
|
||
| /* acquire the wait info, create new one if not exists */ | ||
| wait_info = acquire_wait_info(address, true); | ||
|
|
||
| if (!wait_info) { | ||
| wasm_runtime_set_exception(module, "failed to acquire wait_info"); | ||
| return -1; | ||
| } | ||
|
|
||
| node = search_module((WASMModuleCommon *)module_inst->module); | ||
| os_mutex_lock(&node->shared_mem_lock); | ||
| no_wait = (!wait64 && *(uint32 *)address != (uint32)expect) | ||
|
|
@@ -435,40 +444,48 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, | |
| if (no_wait) { | ||
| return 1; | ||
| } | ||
| else { | ||
| bh_list_status ret; | ||
|
|
||
| if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) { | ||
| wasm_runtime_set_exception(module, "failed to create wait node"); | ||
| return -1; | ||
| } | ||
| memset(wait_node, 0, sizeof(AtomicWaitNode)); | ||
| if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) { | ||
| wasm_runtime_set_exception(module, "failed to create wait node"); | ||
| return -1; | ||
| } | ||
| memset(wait_node, 0, sizeof(AtomicWaitNode)); | ||
|
|
||
| if (0 != os_mutex_init(&wait_node->wait_lock)) { | ||
| wasm_runtime_free(wait_node); | ||
| return -1; | ||
| } | ||
| if (0 != os_mutex_init(&wait_node->wait_lock)) { | ||
| wasm_runtime_free(wait_node); | ||
| return -1; | ||
| } | ||
|
|
||
| if (0 != os_cond_init(&wait_node->wait_cond)) { | ||
| os_mutex_destroy(&wait_node->wait_lock); | ||
| wasm_runtime_free(wait_node); | ||
| return -1; | ||
| } | ||
| if (0 != os_cond_init(&wait_node->wait_cond)) { | ||
| os_mutex_destroy(&wait_node->wait_lock); | ||
| wasm_runtime_free(wait_node); | ||
| return -1; | ||
| } | ||
|
|
||
| wait_node->status = S_WAITING; | ||
| os_mutex_lock(&wait_info->wait_list_lock); | ||
| ret = bh_list_insert(wait_info->wait_list, wait_node); | ||
| os_mutex_unlock(&wait_info->wait_list_lock); | ||
| bh_assert(ret == BH_LIST_SUCCESS); | ||
| (void)ret; | ||
| wait_node->status = S_WAITING; | ||
|
|
||
| /* acquire the wait info, create new one if not exists */ | ||
| wait_info = acquire_wait_info(address, true, wait_node); | ||
|
wenyongh marked this conversation as resolved.
Outdated
|
||
|
|
||
| if (!wait_info) { | ||
| os_mutex_destroy(&wait_node->wait_lock); | ||
| wasm_runtime_free(wait_node); | ||
| wasm_runtime_set_exception(module, "failed to acquire wait_info"); | ||
| return -1; | ||
| } | ||
|
|
||
| /* condition wait start */ | ||
| os_mutex_lock(&wait_node->wait_lock); | ||
|
|
||
| os_cond_reltimedwait(&wait_node->wait_cond, &wait_node->wait_lock, | ||
| timeout < 0 ? BHT_WAIT_FOREVER | ||
| : (uint64)timeout / 1000); | ||
| #if WASM_ENABLE_THREAD_MGR != 0 | ||
| if (!wasm_cluster_is_thread_terminated(exec_env)) { | ||
|
wenyongh marked this conversation as resolved.
Outdated
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Concerned about
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean the flag being set between the call to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, the problem you talking about I solved with your idea with condition variable(I just found a way to do it with the existing one):
thread 2
To check I ran the tests and it never hangs any more, no tsan warnings as well(besides unrelated LOAD-STORE one)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here I'm concerned about
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then I presume we want to add a |
||
| #endif | ||
| os_cond_reltimedwait(&wait_node->wait_cond, &wait_node->wait_lock, | ||
| timeout < 0 ? BHT_WAIT_FOREVER | ||
| : (uint64)timeout / 1000); | ||
| #if WASM_ENABLE_THREAD_MGR != 0 | ||
| } | ||
| #endif | ||
|
|
||
| is_timeout = wait_node->status == S_WAITING ? true : false; | ||
| os_mutex_unlock(&wait_node->wait_lock); | ||
|
|
@@ -486,8 +503,8 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, | |
| wasm_runtime_free(wait_node); | ||
|
|
||
| /* Release wait info if no wait nodes attached */ | ||
| removed_from_map = map_remove_wait_info(wait_map, wait_info, address); | ||
| os_mutex_unlock(&wait_info->wait_list_lock); | ||
| removed_from_map = map_remove_wait_info(wait_map, wait_info, address); | ||
| if (removed_from_map) | ||
| destroy_wait_info(wait_info); | ||
|
wenyongh marked this conversation as resolved.
Outdated
|
||
| os_mutex_unlock(&node->shared_mem_lock); | ||
|
|
@@ -523,7 +540,7 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, | |
| return -1; | ||
| } | ||
|
|
||
| wait_info = acquire_wait_info(address, false); | ||
| wait_info = acquire_wait_info(address, false, NULL); | ||
|
|
||
| /* Nobody wait on this address */ | ||
| if (!wait_info) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.