55
66#include "bh_log.h"
77#include "wasm_shared_memory.h"
8+ #if WASM_ENABLE_THREAD_MGR != 0
9+ #include "../libraries/thread-mgr/thread_manager.h"
10+ #endif
811
912static bh_list shared_memory_list_head ;
1013static bh_list * const shared_memory_list = & shared_memory_list_head ;
@@ -21,6 +24,8 @@ typedef struct AtomicWaitInfo {
2124 korp_mutex wait_list_lock ;
2225 bh_list wait_list_head ;
2326 bh_list * wait_list ;
27+ /* WARNING: insert to the list allowed only in acquire_wait_info
28+ otherwise there will be data race as described in PR #2016 */
2429} AtomicWaitInfo ;
2530
2631typedef struct AtomicWaitNode {
@@ -298,7 +303,7 @@ notify_wait_list(bh_list *wait_list, uint32 count)
298303}
299304
300305static AtomicWaitInfo *
301- acquire_wait_info (void * address , bool create )
306+ acquire_wait_info (void * address , AtomicWaitNode * wait_node )
302307{
303308 AtomicWaitInfo * wait_info = NULL ;
304309 bh_list_status ret ;
@@ -308,7 +313,7 @@ acquire_wait_info(void *address, bool create)
308313 if (address )
309314 wait_info = (AtomicWaitInfo * )bh_hash_map_find (wait_map , address );
310315
311- if (!create ) {
316+ if (!wait_node ) {
312317 os_mutex_unlock (& wait_map_lock );
313318 return wait_info ;
314319 }
@@ -336,6 +341,12 @@ acquire_wait_info(void *address, bool create)
336341 }
337342 }
338343
344+ os_mutex_lock (& wait_info -> wait_list_lock );
345+ ret = bh_list_insert (wait_info -> wait_list , wait_node );
346+ os_mutex_unlock (& wait_info -> wait_list_lock );
347+ bh_assert (ret == BH_LIST_SUCCESS );
348+ (void )ret ;
349+
339350 os_mutex_unlock (& wait_map_lock );
340351
341352 bh_assert (wait_info );
@@ -376,16 +387,22 @@ destroy_wait_info(void *wait_info)
376387 }
377388}
378389
379- static bool
380- map_remove_wait_info (HashMap * wait_map_ , AtomicWaitInfo * wait_info ,
381- void * address )
390+ static void
391+ map_try_release_wait_info (HashMap * wait_map_ , AtomicWaitInfo * wait_info ,
392+ void * address )
382393{
394+ os_mutex_lock (& wait_map_lock );
395+ os_mutex_lock (& wait_info -> wait_list_lock );
383396 if (wait_info -> wait_list -> len > 0 ) {
384- return false;
397+ os_mutex_unlock (& wait_info -> wait_list_lock );
398+ os_mutex_unlock (& wait_map_lock );
399+ return ;
385400 }
401+ os_mutex_unlock (& wait_info -> wait_list_lock );
386402
387403 bh_hash_map_remove (wait_map_ , address , NULL , NULL );
388- return true;
404+ os_mutex_unlock (& wait_map_lock );
405+ destroy_wait_info (wait_info );
389406}
390407
391408uint32
@@ -396,7 +413,8 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
396413 AtomicWaitInfo * wait_info ;
397414 AtomicWaitNode * wait_node ;
398415 WASMSharedMemNode * node ;
399- bool check_ret , is_timeout , no_wait , removed_from_map ;
416+ WASMExecEnv * exec_env ;
417+ bool check_ret , is_timeout , no_wait ;
400418
401419 bh_assert (module -> module_type == Wasm_Module_Bytecode
402420 || module -> module_type == Wasm_Module_AoT );
@@ -418,14 +436,6 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
418436 return -1 ;
419437 }
420438
421- /* acquire the wait info, create new one if not exists */
422- wait_info = acquire_wait_info (address , true);
423-
424- if (!wait_info ) {
425- wasm_runtime_set_exception (module , "failed to acquire wait_info" );
426- return -1 ;
427- }
428-
429439 node = search_module ((WASMModuleCommon * )module_inst -> module );
430440 os_mutex_lock (& node -> shared_mem_lock );
431441 no_wait = (!wait64 && * (uint32 * )address != (uint32 )expect )
@@ -435,40 +445,59 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
435445 if (no_wait ) {
436446 return 1 ;
437447 }
438- else {
439- bh_list_status ret ;
440448
441- if (!(wait_node = wasm_runtime_malloc (sizeof (AtomicWaitNode )))) {
442- wasm_runtime_set_exception (module , "failed to create wait node" );
443- return -1 ;
444- }
445- memset (wait_node , 0 , sizeof (AtomicWaitNode ));
449+ if (!(wait_node = wasm_runtime_malloc (sizeof (AtomicWaitNode )))) {
450+ wasm_runtime_set_exception (module , "failed to create wait node" );
451+ return -1 ;
452+ }
453+ memset (wait_node , 0 , sizeof (AtomicWaitNode ));
446454
447- if (0 != os_mutex_init (& wait_node -> wait_lock )) {
448- wasm_runtime_free (wait_node );
449- return -1 ;
450- }
455+ if (0 != os_mutex_init (& wait_node -> wait_lock )) {
456+ wasm_runtime_free (wait_node );
457+ return -1 ;
458+ }
451459
452- if (0 != os_cond_init (& wait_node -> wait_cond )) {
453- os_mutex_destroy (& wait_node -> wait_lock );
454- wasm_runtime_free (wait_node );
455- return -1 ;
456- }
460+ if (0 != os_cond_init (& wait_node -> wait_cond )) {
461+ os_mutex_destroy (& wait_node -> wait_lock );
462+ wasm_runtime_free (wait_node );
463+ return -1 ;
464+ }
457465
458- wait_node -> status = S_WAITING ;
459- os_mutex_lock (& wait_info -> wait_list_lock );
460- ret = bh_list_insert (wait_info -> wait_list , wait_node );
461- os_mutex_unlock (& wait_info -> wait_list_lock );
462- bh_assert (ret == BH_LIST_SUCCESS );
463- (void )ret ;
466+ wait_node -> status = S_WAITING ;
467+
468+ /* acquire the wait info, create new one if not exists */
469+ wait_info = acquire_wait_info (address , wait_node );
470+
471+ if (!wait_info ) {
472+ os_mutex_destroy (& wait_node -> wait_lock );
473+ wasm_runtime_free (wait_node );
474+ wasm_runtime_set_exception (module , "failed to acquire wait_info" );
475+ return -1 ;
464476 }
465477
478+ #if WASM_ENABLE_THREAD_MGR != 0
479+ exec_env =
480+ wasm_clusters_search_exec_env ((WASMModuleInstanceCommon * )module_inst );
481+ bh_assert (exec_env );
482+ #endif
483+
484+ os_mutex_lock (& node -> shared_mem_lock );
485+ no_wait = (!wait64 && * (uint32 * )address != (uint32 )expect )
486+ || (wait64 && * (uint64 * )address != expect );
487+ os_mutex_unlock (& node -> shared_mem_lock );
488+
466489 /* condition wait start */
467490 os_mutex_lock (& wait_node -> wait_lock );
468491
469- os_cond_reltimedwait (& wait_node -> wait_cond , & wait_node -> wait_lock ,
470- timeout < 0 ? BHT_WAIT_FOREVER
471- : (uint64 )timeout / 1000 );
492+ if (!no_wait
493+ #if WASM_ENABLE_THREAD_MGR != 0
494+ && !wasm_cluster_is_thread_terminated (exec_env )
495+ #endif
496+ ) {
497+ os_cond_reltimedwait (& wait_node -> wait_cond , & wait_node -> wait_lock ,
498+ timeout < 0 ? BHT_WAIT_FOREVER
499+ : (uint64 )timeout / 1000 );
500+ }
472501
473502 is_timeout = wait_node -> status == S_WAITING ? true : false;
474503 os_mutex_unlock (& wait_node -> wait_lock );
@@ -486,14 +515,12 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
486515 wasm_runtime_free (wait_node );
487516
488517 /* Release wait info if no wait nodes attached */
489- removed_from_map = map_remove_wait_info (wait_map , wait_info , address );
490518 os_mutex_unlock (& wait_info -> wait_list_lock );
491- if (removed_from_map )
492- destroy_wait_info (wait_info );
519+ map_try_release_wait_info (wait_map , wait_info , address );
493520 os_mutex_unlock (& node -> shared_mem_lock );
494521
495522 (void )check_ret ;
496- return is_timeout ? 2 : 0 ;
523+ return no_wait ? 1 : is_timeout ? 2 : 0 ;
497524}
498525
499526uint32
@@ -523,7 +550,7 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
523550 return -1 ;
524551 }
525552
526- wait_info = acquire_wait_info (address , false );
553+ wait_info = acquire_wait_info (address , NULL );
527554
528555 /* Nobody wait on this address */
529556 if (!wait_info ) {
0 commit comments