فهرست منبع

Merge branch 'main' into dev/aot_stack_frame

Wenyong Huang 2 سال پیش
والد
کامیت
c1dc08abf6

+ 7 - 3
core/iwasm/common/wasm_memory.c

@@ -26,6 +26,7 @@ static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN;
 static mem_allocator_t pool_allocator = NULL;
 
 static enlarge_memory_error_callback_t enlarge_memory_error_cb;
+static void *enlarge_memory_error_user_data;
 
 #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
 static void *allocator_user_data = NULL;
@@ -716,7 +717,8 @@ return_func:
 
         enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
                                 failure_reason,
-                                (WASMModuleInstanceCommon *)module, exec_env);
+                                (WASMModuleInstanceCommon *)module, exec_env,
+                                enlarge_memory_error_user_data);
     }
 
     return ret;
@@ -822,7 +824,8 @@ return_func:
 
         enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
                                 failure_reason,
-                                (WASMModuleInstanceCommon *)module, exec_env);
+                                (WASMModuleInstanceCommon *)module, exec_env,
+                                enlarge_memory_error_user_data);
     }
 
     return ret;
@@ -831,9 +834,10 @@ return_func:
 
 void
 wasm_runtime_set_enlarge_mem_error_callback(
-    const enlarge_memory_error_callback_t callback)
+    const enlarge_memory_error_callback_t callback, void *user_data)
 {
     enlarge_memory_error_cb = callback;
+    enlarge_memory_error_user_data = user_data;
 }
 
 bool

+ 1 - 1
core/iwasm/common/wasm_memory.h

@@ -26,7 +26,7 @@ wasm_runtime_memory_pool_size();
 
 void
 wasm_runtime_set_enlarge_mem_error_callback(
-    const enlarge_memory_error_callback_t callback);
+    const enlarge_memory_error_callback_t callback, void *user_data);
 
 #ifdef __cplusplus
 }

+ 24 - 3
core/iwasm/common/wasm_runtime_common.c

@@ -2342,8 +2342,8 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm)
     return module_inst->exec_env_singleton;
 }
 
-void
-wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
+static void
+wasm_set_exception_local(WASMModuleInstance *module_inst, const char *exception)
 {
     exception_lock(module_inst);
     if (exception) {
@@ -2354,13 +2354,22 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
         module_inst->cur_exception[0] = '\0';
     }
     exception_unlock(module_inst);
+}
 
+void
+wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
+{
 #if WASM_ENABLE_THREAD_MGR != 0
     WASMExecEnv *exec_env =
         wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst);
     if (exec_env) {
-        wasm_cluster_spread_exception(exec_env, exception);
+        wasm_cluster_set_exception(exec_env, exception);
     }
+    else {
+        wasm_set_exception_local(module_inst, exception);
+    }
+#else
+    wasm_set_exception_local(module_inst, exception);
 #endif
 }
 
@@ -2468,6 +2477,18 @@ wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst_comm)
     wasm_runtime_set_exception(module_inst_comm, NULL);
 }
 
+#if WASM_ENABLE_THREAD_MGR != 0
+void
+wasm_runtime_terminate(WASMModuleInstanceCommon *module_inst_comm)
+{
+    WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+    bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+              || module_inst_comm->module_type == Wasm_Module_AoT);
+    wasm_set_exception(module_inst, "terminated by user");
+}
+#endif
+
 void
 wasm_runtime_set_custom_data_internal(
     WASMModuleInstanceCommon *module_inst_comm, void *custom_data)

+ 4 - 0
core/iwasm/common/wasm_runtime_common.h

@@ -679,6 +679,10 @@ wasm_runtime_get_exception(WASMModuleInstanceCommon *module);
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst);
 
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_terminate(WASMModuleInstanceCommon *module);
+
 /* Internal API */
 void
 wasm_runtime_set_custom_data_internal(WASMModuleInstanceCommon *module_inst,

+ 24 - 2
core/iwasm/include/wasm_export.h

@@ -894,6 +894,27 @@ wasm_runtime_set_exception(wasm_module_inst_t module_inst,
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_clear_exception(wasm_module_inst_t module_inst);
 
+/**
+ * Terminate the WASM module instance.
+ *
+ * This function causes the module instance fail as if it raised a trap.
+ *
+ * This is intended to be used in situations like:
+ *
+ *  - A thread is executing the WASM module instance
+ *    (eg. it's in the middle of `wasm_application_execute_main`)
+ *
+ *  - Another thread has a copy of `wasm_module_inst_t` of
+ *    the module instance and wants to terminate it asynchronously.
+ *
+ * This function is provided only when WAMR is built with threading enabled.
+ * (`WASM_ENABLE_THREAD_MGR=1`)
+ *
+ * @param module_inst the WASM module instance
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_terminate(wasm_module_inst_t module_inst);
+
 /**
  * Set custom data to WASM module instance.
  * Note:
@@ -1447,14 +1468,15 @@ typedef enum {
 typedef void (*enlarge_memory_error_callback_t)(
     uint32_t inc_page_count, uint64_t current_memory_size,
     uint32_t memory_index, enlarge_memory_error_reason_t failure_reason,
-    wasm_module_inst_t instance, wasm_exec_env_t exec_env);
+    wasm_module_inst_t instance, wasm_exec_env_t exec_env,
+    void* user_data);
 
 /**
  * Setup callback invoked when memory.grow fails
  */
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_set_enlarge_mem_error_callback(
-    const enlarge_memory_error_callback_t callback);
+    const enlarge_memory_error_callback_t callback, void *user_data);
 
 /*
  * module instance context APIs

+ 14 - 2
core/iwasm/libraries/thread-mgr/thread_manager.c

@@ -1061,6 +1061,15 @@ set_thread_cancel_flags(WASMExecEnv *exec_env)
     os_mutex_unlock(&exec_env->wait_lock);
 }
 
+static void
+clear_thread_cancel_flags(WASMExecEnv *exec_env)
+{
+    os_mutex_lock(&exec_env->wait_lock);
+    WASM_SUSPEND_FLAGS_FETCH_AND(exec_env->suspend_flags,
+                                 ~WASM_SUSPEND_FLAG_TERMINATE);
+    os_mutex_unlock(&exec_env->wait_lock);
+}
+
 int32
 wasm_cluster_cancel_thread(WASMExecEnv *exec_env)
 {
@@ -1266,18 +1275,21 @@ set_exception_visitor(void *node, void *user_data)
         if (data->exception != NULL) {
             set_thread_cancel_flags(exec_env);
         }
+        else {
+            clear_thread_cancel_flags(exec_env);
+        }
     }
 }
 
 void
-wasm_cluster_spread_exception(WASMExecEnv *exec_env, const char *exception)
+wasm_cluster_set_exception(WASMExecEnv *exec_env, const char *exception)
 {
     const bool has_exception = exception != NULL;
     WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
     bh_assert(cluster);
 
     struct spread_exception_data data;
-    data.skip = exec_env;
+    data.skip = NULL;
     data.exception = exception;
 
     os_mutex_lock(&cluster->lock);

+ 1 - 1
core/iwasm/libraries/thread-mgr/thread_manager.h

@@ -139,7 +139,7 @@ WASMExecEnv *
 wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst);
 
 void
-wasm_cluster_spread_exception(WASMExecEnv *exec_env, const char *exception);
+wasm_cluster_set_exception(WASMExecEnv *exec_env, const char *exception);
 
 WASMExecEnv *
 wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env);

+ 10 - 5
core/shared/platform/common/posix/posix_thread.c

@@ -509,8 +509,8 @@ mask_signals(int how)
     pthread_sigmask(how, &set, NULL);
 }
 
-static os_thread_local_attribute struct sigaction prev_sig_act_SIGSEGV;
-static os_thread_local_attribute struct sigaction prev_sig_act_SIGBUS;
+static struct sigaction prev_sig_act_SIGSEGV;
+static struct sigaction prev_sig_act_SIGBUS;
 
 /* ASAN is not designed to work with custom stack unwind or other low-level \
  things. > Ignore a function that does some low-level magic. (e.g. walking \
@@ -540,11 +540,16 @@ signal_callback(int sig_num, siginfo_t *sig_info, void *sig_ucontext)
     if (prev_sig_act && (prev_sig_act->sa_flags & SA_SIGINFO)) {
         prev_sig_act->sa_sigaction(sig_num, sig_info, sig_ucontext);
     }
-    else if (prev_sig_act
-             && ((void *)prev_sig_act->sa_sigaction == SIG_DFL
-                 || (void *)prev_sig_act->sa_sigaction == SIG_IGN)) {
+    else if (prev_sig_act && (void *)prev_sig_act->sa_handler == SIG_DFL) {
+        /* Default action */
         sigaction(sig_num, prev_sig_act, NULL);
     }
+    else if (prev_sig_act && (void *)prev_sig_act->sa_handler == SIG_IGN) {
+        /* Ignore this signal */
+    }
+    else if (prev_sig_act && prev_sig_act->sa_handler) {
+        prev_sig_act->sa_handler(sig_num);
+    }
     /* Output signal info and then crash if signal is unhandled */
     else {
         switch (sig_num) {

+ 75 - 0
product-mini/platforms/posix/main.c

@@ -97,6 +97,11 @@ print_help()
 #if WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
     printf("  --max-threads=n          Set maximum thread number per cluster, default is 4\n");
 #endif
+#if WASM_ENABLE_THREAD_MGR != 0
+    printf("  --timeout=ms             Set the maximum execution time in ms.\n");
+    printf("                           If it expires, the runtime aborts the execution\n");
+    printf("                           with a trap.\n");
+#endif
 #if WASM_ENABLE_DEBUG_INTERP != 0
     printf("  -g=ip:port               Set the debug sever address, default is debug disabled\n");
     printf("                             if port is 0, then a random port will be used\n");
@@ -488,6 +493,40 @@ dump_pgo_prof_data(wasm_module_inst_t module_inst, const char *path)
 }
 #endif
 
+#if WASM_ENABLE_THREAD_MGR != 0
+struct timeout_arg {
+    uint32 timeout_ms;
+    wasm_module_inst_t inst;
+#if defined(BH_HAS_STD_ATOMIC)
+    _Atomic
+#endif
+        bool cancel;
+};
+
+void *
+timeout_thread(void *vp)
+{
+    const struct timeout_arg *arg = vp;
+    uint32 left = arg->timeout_ms;
+    while (!arg->cancel) {
+        uint32 ms;
+        if (left >= 100) {
+            ms = 100;
+        }
+        else {
+            ms = left;
+        }
+        os_usleep((uint64)ms * 1000);
+        left -= ms;
+        if (left == 0) {
+            wasm_runtime_terminate(arg->inst);
+            break;
+        }
+    }
+    return NULL;
+}
+#endif
+
 int
 main(int argc, char *argv[])
 {
@@ -546,6 +585,9 @@ main(int argc, char *argv[])
 #if WASM_ENABLE_STATIC_PGO != 0
     const char *gen_prof_file = NULL;
 #endif
+#if WASM_ENABLE_THREAD_MGR != 0
+    int timeout_ms = -1;
+#endif
 
     /* Process options. */
     for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
@@ -742,6 +784,13 @@ main(int argc, char *argv[])
             wasm_runtime_set_max_thread_num(atoi(argv[0] + 14));
         }
 #endif
+#if WASM_ENABLE_THREAD_MGR != 0
+        else if (!strncmp(argv[0], "--timeout=", 10)) {
+            if (argv[0][10] == '\0')
+                return print_help();
+            timeout_ms = atoi(argv[0] + 10);
+        }
+#endif
 #if WASM_ENABLE_DEBUG_INTERP != 0
         else if (!strncmp(argv[0], "-g=", 3)) {
             char *port_str = strchr(argv[0] + 3, ':');
@@ -902,6 +951,22 @@ main(int argc, char *argv[])
     }
 #endif
 
+#if WASM_ENABLE_THREAD_MGR != 0
+    struct timeout_arg timeout_arg;
+    korp_tid timeout_tid;
+    if (timeout_ms >= 0) {
+        timeout_arg.timeout_ms = timeout_ms;
+        timeout_arg.inst = wasm_module_inst;
+        timeout_arg.cancel = false;
+        ret = os_thread_create(&timeout_tid, timeout_thread, &timeout_arg,
+                               APP_THREAD_STACK_SIZE_DEFAULT);
+        if (ret != 0) {
+            printf("Failed to start timeout\n");
+            goto fail5;
+        }
+    }
+#endif
+
     ret = 0;
     if (is_repl_mode) {
         app_instance_repl(wasm_module_inst);
@@ -932,6 +997,16 @@ main(int argc, char *argv[])
         dump_pgo_prof_data(wasm_module_inst, gen_prof_file);
 #endif
 
+#if WASM_ENABLE_THREAD_MGR != 0
+    if (timeout_ms >= 0) {
+        timeout_arg.cancel = true;
+        os_thread_join(timeout_tid, NULL);
+    }
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+fail5:
+#endif
 #if WASM_ENABLE_DEBUG_INTERP != 0
 fail4:
 #endif

+ 48 - 29
tests/wamr-test-suites/spec-test-script/all.py

@@ -37,6 +37,7 @@ WAST2WASM_CMD = "./wabt/out/gcc/Release/wat2wasm"
 SPEC_INTERPRETER_CMD = "spec/interpreter/wasm"
 WAMRC_CMD = "../../../wamr-compiler/build/wamrc"
 
+
 class TargetAction(argparse.Action):
     TARGET_MAP = {
         "ARMV7_VFP": "armv7",
@@ -49,6 +50,7 @@ class TargetAction(argparse.Action):
         "THUMBV7_VFP": "thumbv7",
         "X86_32": "i386",
         "X86_64": "x86_64",
+        "AARCH64": "arm64"
     }
 
     def __call__(self, parser, namespace, values, option_string=None):
@@ -65,7 +67,7 @@ def ignore_the_case(
     simd_flag=False,
     gc_flag=False,
     xip_flag=False,
-    qemu_flag=False
+    qemu_flag=False,
 ):
     if case_name in ["comments", "inline-module", "names"]:
         return True
@@ -79,7 +81,7 @@ def ignore_the_case(
 
     if gc_flag:
         if case_name in ["type-canon", "type-equivalence", "type-rec"]:
-            return True;
+            return True
 
     if sgx_flag:
         if case_name in ["conversions", "f32_bitwise", "f64_bitwise"]:
@@ -94,9 +96,20 @@ def ignore_the_case(
             return True
 
     if qemu_flag:
-        if case_name in ["f32_bitwise", "f64_bitwise", "loop", "f64", "f64_cmp",
-                         "conversions", "f32", "f32_cmp", "float_exprs",
-                         "float_misc", "select", "memory_grow"]:
+        if case_name in [
+            "f32_bitwise",
+            "f64_bitwise",
+            "loop",
+            "f64",
+            "f64_cmp",
+            "conversions",
+            "f32",
+            "f32_cmp",
+            "float_exprs",
+            "float_misc",
+            "select",
+            "memory_grow",
+        ]:
             return True
 
     return False
@@ -131,26 +144,9 @@ def test_case(
     verbose_flag=True,
     gc_flag=False,
     qemu_flag=False,
-    qemu_firmware='',
-    log='',
+    qemu_firmware="",
+    log="",
 ):
-    case_path = pathlib.Path(case_path).resolve()
-    case_name = case_path.stem
-
-    if ignore_the_case(
-        case_name,
-        target,
-        aot_flag,
-        sgx_flag,
-        multi_module_flag,
-        multi_thread_flag,
-        simd_flag,
-        gc_flag,
-        xip_flag,
-        qemu_flag
-    ):
-        return True
-
     CMD = ["python3", "runtest.py"]
     CMD.append("--wast2wasm")
     CMD.append(WAST2WASM_CMD if not gc_flag else SPEC_INTERPRETER_CMD)
@@ -196,10 +192,13 @@ def test_case(
     if gc_flag:
         CMD.append("--gc")
 
-    if log != '':
+    if log != "":
         CMD.append("--log-dir")
         CMD.append(log)
 
+    case_path = pathlib.Path(case_path).resolve()
+    case_name = case_path.stem
+
     CMD.append(case_path)
     print(f"============> run {case_name} ", end="")
     with subprocess.Popen(
@@ -259,8 +258,8 @@ def test_suite(
     gc_flag=False,
     parl_flag=False,
     qemu_flag=False,
-    qemu_firmware='',
-    log='',
+    qemu_firmware="",
+    log="",
 ):
     suite_path = pathlib.Path(SPEC_TEST_DIR).resolve()
     if not suite_path.exists():
@@ -276,6 +275,26 @@ def test_suite(
         gc_case_list = sorted(suite_path.glob("gc/*.wast"))
         case_list.extend(gc_case_list)
 
+    # ignore based on command line options
+    filtered_case_list = []
+    for case_path in case_list:
+        case_name = case_path.stem
+        if not ignore_the_case(
+            case_name,
+            target,
+            aot_flag,
+            sgx_flag,
+            multi_module_flag,
+            multi_thread_flag,
+            simd_flag,
+            gc_flag,
+            xip_flag,
+            qemu_flag,
+        ):
+            filtered_case_list.append(case_path)
+    print(f"---> {len(case_list)} --filter--> {len(filtered_case_list)}")
+    case_list = filtered_case_list
+
     case_count = len(case_list)
     failed_case = 0
     successful_case = 0
@@ -435,7 +454,7 @@ def main():
     )
     parser.add_argument(
         "--log",
-        default='',
+        default="",
         dest="log",
         help="Log directory",
     )
@@ -512,7 +531,7 @@ def main():
                     options.gc_flag,
                     options.qemu_flag,
                     options.qemu_firmware,
-                    options.log
+                    options.log,
                 )
             else:
                 ret = True

+ 1 - 1
tests/wamr-test-suites/test_wamr.sh

@@ -15,7 +15,7 @@ function help()
     echo "test_wamr.sh [options]"
     echo "-c clean previous test results, not start test"
     echo "-s {suite_name} test only one suite (spec|wasi_certification)"
-    echo "-m set compile target of iwasm(x86_64|x86_32|armv7_vfp|thumbv7_vfp|riscv64_lp64d|riscv64_lp64)"
+    echo "-m set compile target of iwasm(x86_64|x86_32|armv7_vfp|thumbv7_vfp|riscv64_lp64d|riscv64_lp64|aarch64)"
     echo "-t set compile type of iwasm(classic-interp|fast-interp|jit|aot|fast-jit|multi-tier-jit)"
     echo "-M enable multi module feature"
     echo "-p enable multi thread feature"