Просмотр исходного кода

Fix atomic wait not thread safe issue (#1146)

Add lock for acquire_wait_info and release_wait_info, and
remove release_wait_info in wasm_runtime_atomic_notify.
Xu Jun 3 лет назад
Родитель
Сommit
16cfd4764d
1 измененных файлов с 29 добавлено и 11 удалено
  1. 29 11
      core/iwasm/common/wasm_shared_memory.c

+ 29 - 11
core/iwasm/common/wasm_shared_memory.c

@@ -224,17 +224,22 @@ acquire_wait_info(void *address, bool create)
     AtomicWaitInfo *wait_info = NULL;
     bh_list_status ret;
 
+    os_mutex_lock(&shared_memory_list_lock);
+
     if (address)
         wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address);
 
-    if (!create)
+    if (!create) {
+        os_mutex_unlock(&shared_memory_list_lock);
         return wait_info;
+    }
 
     /* No wait info on this address, create new info */
     if (!wait_info) {
         if (!(wait_info = (AtomicWaitInfo *)wasm_runtime_malloc(
-                  sizeof(AtomicWaitInfo))))
-            return NULL;
+                  sizeof(AtomicWaitInfo)))) {
+            goto fail1;
+        }
         memset(wait_info, 0, sizeof(AtomicWaitInfo));
 
         /* init wait list */
@@ -244,20 +249,30 @@ acquire_wait_info(void *address, bool create)
 
         /* init wait list lock */
         if (0 != os_mutex_init(&wait_info->wait_list_lock)) {
-            wasm_runtime_free(wait_info);
-            return NULL;
+            goto fail2;
         }
 
         if (!bh_hash_map_insert(wait_map, address, (void *)wait_info)) {
-            os_mutex_destroy(&wait_info->wait_list_lock);
-            wasm_runtime_free(wait_info);
-            return NULL;
+            goto fail3;
         }
     }
 
+    os_mutex_unlock(&shared_memory_list_lock);
+
     bh_assert(wait_info);
     (void)ret;
     return wait_info;
+
+fail3:
+    os_mutex_destroy(&wait_info->wait_list_lock);
+
+fail2:
+    wasm_runtime_free(wait_info);
+
+fail1:
+    os_mutex_unlock(&shared_memory_list_lock);
+
+    return NULL;
 }
 
 static void
@@ -285,10 +300,14 @@ destroy_wait_info(void *wait_info)
 static void
 release_wait_info(HashMap *wait_map_, AtomicWaitInfo *wait_info, void *address)
 {
+    os_mutex_lock(&shared_memory_list_lock);
+
     if (wait_info->wait_list->len == 0) {
         bh_hash_map_remove(wait_map_, address, NULL, NULL);
         destroy_wait_info(wait_info);
     }
+
+    os_mutex_unlock(&shared_memory_list_lock);
 }
 
 uint32
@@ -405,8 +424,9 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
     uint32 notify_result;
     AtomicWaitInfo *wait_info;
 
-    /* Nobody wait on this address */
     wait_info = acquire_wait_info(address, false);
+
+    /* Nobody wait on this address */
     if (!wait_info)
         return 0;
 
@@ -414,7 +434,5 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
     notify_result = notify_wait_list(wait_info->wait_list, count);
     os_mutex_unlock(&wait_info->wait_list_lock);
 
-    release_wait_info(wait_map, wait_info, address);
-
     return notify_result;
 }