Przeglądaj źródła

Re-org thread env init/destroy for HW bound check (#631)

And fix cmake_minimum_required() deprecation warning since envoy is using cmake 3.16 or higher version.
Wenyong Huang 4 lat temu
rodzic
commit
a14a4487bb

+ 1 - 1
CMakeLists.txt

@@ -1,7 +1,7 @@
 # Copyright (C) 2019 Intel Corporation.  All rights reserved.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-cmake_minimum_required (VERSION 2.8)
+cmake_minimum_required (VERSION 2.8...3.16)
 
 project (iwasm)
 # set (CMAKE_VERBOSE_MAKEFILE 1)

+ 18 - 10
core/iwasm/aot/aot_runtime.c

@@ -1254,21 +1254,26 @@ bool
 aot_signal_init()
 {
 #ifndef BH_PLATFORM_WINDOWS
-    return os_signal_init(aot_signal_handler) == 0 ? true : false;
+    return os_thread_signal_init(aot_signal_handler) == 0 ? true : false;
 #else
-    return AddVectoredExceptionHandler(1, aot_exception_handler)
-           ? true : false;
+    if (os_thread_signal_init() != 0)
+        return false;
+
+    if (!AddVectoredExceptionHandler(1, aot_exception_handler)) {
+        os_thread_signal_destroy();
+        return false;
+    }
 #endif
+    return true;
 }
 
 void
 aot_signal_destroy()
 {
-#ifndef BH_PLATFORM_WINDOWS
-    os_signal_destroy();
-#else
+#ifdef BH_PLATFORM_WINDOWS
     RemoveVectoredExceptionHandler(aot_exception_handler);
 #endif
+    os_thread_signal_destroy();
 }
 
 static bool
@@ -1302,7 +1307,10 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
         return false;
     }
 
-    os_thread_init_stack_guard_pages();
+    if (!os_thread_signal_inited()) {
+        aot_set_exception(module_inst, "thread signal env not inited");
+        return false;
+    }
 
     wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
 
@@ -1486,11 +1494,11 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
     WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL;
     bool ret;
 
-#if WASM_ENABLE_THREAD_MGR != 0
+#if defined(OS_ENABLE_HW_BOUND_CHECK)
+    existing_exec_env = exec_env = aot_exec_env;
+#elif WASM_ENABLE_THREAD_MGR != 0
     existing_exec_env = exec_env = wasm_clusters_search_exec_env(
             (WASMModuleInstanceCommon*)module_inst);
-#elif defined(OS_ENABLE_HW_BOUND_CHECK)
-    existing_exec_env = exec_env = aot_exec_env;
 #endif
 
     if (!existing_exec_env) {

+ 21 - 10
core/iwasm/common/wasm_c_api.c

@@ -363,7 +363,13 @@ wasm_store_new(wasm_engine_t *engine)
         return NULL;
     }
 
+    if (!wasm_runtime_init_thread_env()) {
+        LOG_ERROR("init thread environment failed");
+        return NULL;
+    }
+
     if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
+        wasm_runtime_destroy_thread_env();
         return NULL;
     }
 
@@ -412,6 +418,8 @@ wasm_store_delete(wasm_store_t *store)
     DEINIT_VEC(store->modules, wasm_module_vec_delete);
     DEINIT_VEC(store->instances, wasm_instance_vec_delete);
     wasm_runtime_free(store);
+
+    wasm_runtime_destroy_thread_env();
 }
 
 /* Type Representations */
@@ -1376,7 +1384,7 @@ module_to_module_ext(wasm_module_t *module)
 wasm_module_t *
 wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
 {
-    char error[128] = { 0 };
+    char error_buf[128] = { 0 };
     wasm_module_ex_t *module_ex = NULL;
 
     bh_assert(singleton_engine);
@@ -1393,11 +1401,12 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
 
     INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data);
 
-    module_ex->module_comm_rt = wasm_runtime_load(
-      (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, error,
-      (uint32)sizeof(error));
+    module_ex->module_comm_rt =
+        wasm_runtime_load((uint8 *)module_ex->binary->data,
+                          (uint32)module_ex->binary->size,
+                          error_buf, (uint32)sizeof(error_buf));
     if (!(module_ex->module_comm_rt)) {
-        LOG_ERROR(error);
+        LOG_ERROR(error_buf);
         goto failed;
     }
 
@@ -1418,6 +1427,7 @@ static void
 wasm_module_delete_internal(wasm_module_t *module)
 {
     wasm_module_ex_t *module_ex;
+
     if (!module) {
         return;
     }
@@ -1436,7 +1446,7 @@ wasm_module_delete_internal(wasm_module_t *module)
 void
 wasm_module_delete(wasm_module_t *module)
 {
-    /* will release module when releasing the store */
+    /* the module will be released when releasing the store */
 }
 
 void
@@ -3589,7 +3599,7 @@ wasm_instance_new(wasm_store_t *store,
                   const wasm_extern_t *const imports[],
                   own wasm_trap_t **traps)
 {
-    char error[128] = { 0 };
+    char error_buf[128] = { 0 };
     const uint32 stack_size = 16 * 1024;
     const uint32 heap_size = 16 * 1024;
     uint32 import_count = 0;
@@ -3650,10 +3660,11 @@ wasm_instance_new(wasm_store_t *store,
 #endif
     }
 
-    instance->inst_comm_rt = wasm_runtime_instantiate(
-      *module, stack_size, heap_size, error, sizeof(error));
+    instance->inst_comm_rt =
+        wasm_runtime_instantiate(*module, stack_size, heap_size,
+                                 error_buf, sizeof(error_buf));
     if (!instance->inst_comm_rt) {
-        LOG_ERROR(error);
+        LOG_ERROR(error_buf);
         goto failed;
     }
 

+ 21 - 0
core/iwasm/common/wasm_runtime_common.c

@@ -819,6 +819,27 @@ wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env)
     wasm_exec_env_destroy(exec_env);
 }
 
+bool
+wasm_runtime_init_thread_env()
+{
+#if WASM_ENABLE_AOT != 0
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+    return aot_signal_init();
+#endif
+#endif
+    return true;
+}
+
+void
+wasm_runtime_destroy_thread_env()
+{
+#if WASM_ENABLE_AOT != 0
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+    return aot_signal_destroy();
+#endif
+#endif
+}
+
 #if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_MEMORY_TRACING != 0)
 void
 wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module)

+ 21 - 0
core/iwasm/include/wasm_export.h

@@ -392,6 +392,27 @@ wasm_runtime_create_exec_env(wasm_module_inst_t module_inst,
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_destroy_exec_env(wasm_exec_env_t exec_env);
 
+/**
+ * Initialize thread environment.
+ * Note:
+ *   If developer creates a child thread by himself to call the
+ *   the wasm function in that thread, he should call this API
+ *   firstly before calling the wasm function and then call
+ *   wasm_runtime_destroy_thread_env() after calling the wasm
+ *   function. If the thread is created from the runtime API,
+ *   it is unnecessary to call these two APIs.
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_init_thread_env();
+
+/**
+ * Destroy thread environment
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy_thread_env();
+
 /**
  * Get WASM module instance from execution environment
  *

+ 0 - 3
core/shared/platform/android/platform_init.c

@@ -20,9 +20,6 @@ bh_platform_init()
 void
 bh_platform_destroy()
 {
-#ifdef OS_ENABLE_HW_BOUND_CHECK
-    os_thread_destroy_stack_guard_pages();
-#endif
 }
 
 int os_printf(const char *fmt, ...)

+ 4 - 6
core/shared/platform/android/platform_internal.h

@@ -75,15 +75,13 @@ typedef jmp_buf korp_jmpbuf;
 
 #define os_getpagesize getpagesize
 
-bool os_thread_init_stack_guard_pages();
-
-void os_thread_destroy_stack_guard_pages();
-
 typedef void (*os_signal_handler)(void *sig_addr);
 
-int os_signal_init(os_signal_handler handler);
+int os_thread_signal_init(os_signal_handler handler);
+
+void os_thread_signal_destroy();
 
-void os_signal_destroy();
+bool os_thread_signal_inited();
 
 void os_signal_unmask();
 

+ 82 - 59
core/shared/platform/common/posix/posix_thread.c

@@ -11,12 +11,15 @@
 
 typedef struct {
     thread_start_routine_t start;
-    void* arg;
+    void *arg;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+    os_signal_handler signal_handler;
+#endif
 } thread_wrapper_arg;
 
 #ifdef OS_ENABLE_HW_BOUND_CHECK
-static int os_thread_signal_init();
-static void os_thread_signal_destroy();
+/* The signal handler passed to os_thread_signal_init() */
+static os_thread_local_attribute os_signal_handler signal_handler;
 #endif
 
 static void *os_thread_wrapper(void *arg)
@@ -24,16 +27,18 @@ static void *os_thread_wrapper(void *arg)
     thread_wrapper_arg *targ = arg;
     thread_start_routine_t start_func = targ->start;
     void *thread_arg = targ->arg;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+    os_signal_handler handler = targ->signal_handler;
+#endif
 
     os_printf("THREAD CREATED %p\n", pthread_self());
     BH_FREE(targ);
 #ifdef OS_ENABLE_HW_BOUND_CHECK
-    if (os_thread_signal_init() != 0)
+    if (os_thread_signal_init(handler) != 0)
         return NULL;
 #endif
     start_func(thread_arg);
 #ifdef OS_ENABLE_HW_BOUND_CHECK
-    os_thread_destroy_stack_guard_pages();
     os_thread_signal_destroy();
 #endif
     return NULL;
@@ -66,6 +71,9 @@ int os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
 
     targ->start = start;
     targ->arg = arg;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+    targ->signal_handler = signal_handler;
+#endif
 
     if (pthread_create(tid, &tattr, os_thread_wrapper, targ) != 0) {
         pthread_attr_destroy(&tattr);
@@ -250,7 +258,6 @@ int os_thread_detach(korp_tid thread)
 void os_thread_exit(void *retval)
 {
 #ifdef OS_ENABLE_HW_BOUND_CHECK
-    os_thread_destroy_stack_guard_pages();
     os_thread_signal_destroy();
 #endif
     return pthread_exit(retval);
@@ -313,20 +320,25 @@ uint8 *os_thread_get_stack_boundary()
 
 #define SIG_ALT_STACK_SIZE (32 * 1024)
 
-/* Whether the stack pages are touched and guard pages are set */
-static os_thread_local_attribute bool stack_guard_pages_inited = false;
+/**
+ * Whether thread signal enviornment is initialized:
+ *   the signal handler is registered, the stack pages are touched,
+ *   the stack guard pages are set and signal alternate stack are set.
+ */
+static os_thread_local_attribute bool thread_signal_inited = false;
 
 /* The signal alternate stack base addr */
 static os_thread_local_attribute uint8 *sigalt_stack_base_addr;
 
-/* The signal handler passed to os_signal_init() */
-static os_signal_handler signal_handler;
-
+#if defined(__clang__)
+#pragma clang optimize off
+#endif
 #if defined(__GNUC__)
-__attribute__((no_sanitize_address)) static uint32
-#else
-static uint32
+#pragma GCC push_options
+#pragma GCC optimize("O0")
+__attribute__((no_sanitize_address))
 #endif
+static uint32
 touch_pages(uint8 *stack_min_addr, uint32 page_size)
 {
     uint8 sum = 0;
@@ -342,40 +354,40 @@ touch_pages(uint8 *stack_min_addr, uint32 page_size)
     }
     return sum;
 }
+#if defined(__GNUC__)
+#pragma GCC pop_options
+#endif
+#if defined(__clang__)
+#pragma clang optimize on
+#endif
 
-bool
-os_thread_init_stack_guard_pages()
+static bool
+init_stack_guard_pages()
 {
     uint32 page_size = os_getpagesize();
     uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
     uint8 *stack_min_addr = os_thread_get_stack_boundary();
 
-    if (!stack_guard_pages_inited) {
-        /* Touch each stack page to ensure that it has been mapped: the OS
-           may lazily grow the stack mapping as a guard page is hit. */
-        (void)touch_pages(stack_min_addr, page_size);
-        /* First time to call aot function, protect guard pages */
-        if (os_mprotect(stack_min_addr, page_size * guard_page_count,
-                        MMAP_PROT_NONE) != 0) {
-            return false;
-        }
-        stack_guard_pages_inited = true;
+    /* Touch each stack page to ensure that it has been mapped: the OS
+       may lazily grow the stack mapping as a guard page is hit. */
+    (void)touch_pages(stack_min_addr, page_size);
+    /* First time to call aot function, protect guard pages */
+    if (os_mprotect(stack_min_addr, page_size * guard_page_count,
+                    MMAP_PROT_NONE) != 0) {
+        return false;
     }
     return true;
 }
 
-void
-os_thread_destroy_stack_guard_pages()
+static void
+destroy_stack_guard_pages()
 {
-    if (stack_guard_pages_inited) {
-        uint32 page_size = os_getpagesize();
-        uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
-        uint8 *stack_min_addr = os_thread_get_stack_boundary();
-
-        os_mprotect(stack_min_addr, page_size * guard_page_count,
-                    MMAP_PROT_READ | MMAP_PROT_WRITE);
-        stack_guard_pages_inited = false;
-    }
+    uint32 page_size = os_getpagesize();
+    uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+    uint8 *stack_min_addr = os_thread_get_stack_boundary();
+
+    os_mprotect(stack_min_addr, page_size * guard_page_count,
+                MMAP_PROT_READ | MMAP_PROT_WRITE);
 }
 
 static void
@@ -419,20 +431,27 @@ signal_callback(int sig_num, siginfo_t *sig_info, void *sig_ucontext)
 }
 
 int
-os_signal_init(os_signal_handler handler)
+os_thread_signal_init(os_signal_handler handler)
 {
-    int ret = -1;
     struct sigaction sig_act;
     stack_t sigalt_stack_info;
     uint32 map_size = SIG_ALT_STACK_SIZE;
     uint8 *map_addr;
 
+    if (thread_signal_inited)
+        return 0;
+
+    if (!init_stack_guard_pages()) {
+        os_printf("Failed to init stack guard pages\n");
+        return -1;
+    }
+
     /* Initialize memory for signal alternate stack of current thread */
     if (!(map_addr = os_mmap(NULL, map_size,
                              MMAP_PROT_READ | MMAP_PROT_WRITE,
                              MMAP_MAP_NONE))) {
         os_printf("Failed to mmap memory for alternate stack\n");
-        return -1;
+        goto fail1;
     }
 
     /* Initialize signal alternate stack */
@@ -440,38 +459,46 @@ os_signal_init(os_signal_handler handler)
     sigalt_stack_info.ss_sp = map_addr;
     sigalt_stack_info.ss_size = map_size;
     sigalt_stack_info.ss_flags = 0;
-    if ((ret = sigaltstack(&sigalt_stack_info, NULL)) != 0) {
-        goto fail1;
+    if (sigaltstack(&sigalt_stack_info, NULL) != 0) {
+        os_printf("Failed to init signal alternate stack\n");
+        goto fail2;
     }
 
     /* Install signal hanlder */
     sig_act.sa_sigaction = signal_callback;
     sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_NODEFER;
     sigemptyset(&sig_act.sa_mask);
-    if ((ret = sigaction(SIGSEGV, &sig_act, NULL)) != 0
-        || (ret = sigaction(SIGBUS, &sig_act, NULL)) != 0) {
-        goto fail2;
+    if (sigaction(SIGSEGV, &sig_act, NULL) != 0
+        || sigaction(SIGBUS, &sig_act, NULL) != 0) {
+        os_printf("Failed to register signal handler\n");
+        goto fail3;
     }
 
     sigalt_stack_base_addr = map_addr;
     signal_handler = handler;
+    thread_signal_inited = true;
     return 0;
 
-fail2:
+fail3:
     memset(&sigalt_stack_info, 0, sizeof(stack_t));
     sigalt_stack_info.ss_flags = SS_DISABLE;
     sigalt_stack_info.ss_size = map_size;
     sigaltstack(&sigalt_stack_info, NULL);
-fail1:
+fail2:
     os_munmap(map_addr, map_size);
-    return ret;
+fail1:
+    destroy_stack_guard_pages();
+    return -1;
 }
 
 void
-os_signal_destroy()
+os_thread_signal_destroy()
 {
     stack_t sigalt_stack_info;
 
+    if (!thread_signal_inited)
+        return;
+
     /* Disable signal alternate stack */
     memset(&sigalt_stack_info, 0, sizeof(stack_t));
     sigalt_stack_info.ss_flags = SS_DISABLE;
@@ -479,20 +506,16 @@ os_signal_destroy()
     sigaltstack(&sigalt_stack_info, NULL);
 
     os_munmap(sigalt_stack_base_addr, SIG_ALT_STACK_SIZE);
-}
 
-static int
-os_thread_signal_init()
-{
-    assert(signal_handler);
-    /* Use the global signal handler registered previously */
-    return os_signal_init(signal_handler);
+    destroy_stack_guard_pages();
+
+    thread_signal_inited = false;
 }
 
-static void
-os_thread_signal_destroy()
+bool
+os_thread_signal_inited()
 {
-    os_signal_destroy();
+    return thread_signal_inited;
 }
 
 void

+ 0 - 3
core/shared/platform/darwin/platform_init.c

@@ -14,9 +14,6 @@ bh_platform_init()
 void
 bh_platform_destroy()
 {
-#ifdef OS_ENABLE_HW_BOUND_CHECK
-    os_thread_destroy_stack_guard_pages();
-#endif
 }
 
 int

+ 4 - 6
core/shared/platform/darwin/platform_internal.h

@@ -76,15 +76,13 @@ typedef jmp_buf korp_jmpbuf;
 
 #define os_getpagesize getpagesize
 
-bool os_thread_init_stack_guard_pages();
-
-void os_thread_destroy_stack_guard_pages();
-
 typedef void (*os_signal_handler)(void *sig_addr);
 
-int os_signal_init(os_signal_handler handler);
+int os_thread_signal_init(os_signal_handler handler);
+
+void os_thread_signal_destroy();
 
-void os_signal_destroy();
+bool os_thread_signal_inited();
 
 void os_signal_unmask();
 

+ 0 - 3
core/shared/platform/linux/platform_init.c

@@ -14,9 +14,6 @@ bh_platform_init()
 void
 bh_platform_destroy()
 {
-#ifdef OS_ENABLE_HW_BOUND_CHECK
-    os_thread_destroy_stack_guard_pages();
-#endif
 }
 
 int

+ 4 - 6
core/shared/platform/linux/platform_internal.h

@@ -75,15 +75,13 @@ typedef jmp_buf korp_jmpbuf;
 
 #define os_getpagesize getpagesize
 
-bool os_thread_init_stack_guard_pages();
-
-void os_thread_destroy_stack_guard_pages();
-
 typedef void (*os_signal_handler)(void *sig_addr);
 
-int os_signal_init(os_signal_handler handler);
+int os_thread_signal_init(os_signal_handler handler);
+
+void os_thread_signal_destroy();
 
-void os_signal_destroy();
+bool os_thread_signal_inited();
 
 void os_signal_unmask();
 

+ 0 - 3
core/shared/platform/vxworks/platform_init.c

@@ -14,9 +14,6 @@ bh_platform_init()
 void
 bh_platform_destroy()
 {
-#ifdef OS_ENABLE_HW_BOUND_CHECK
-    os_thread_destroy_stack_guard_pages();
-#endif
 }
 
 int

+ 4 - 6
core/shared/platform/vxworks/platform_internal.h

@@ -74,15 +74,13 @@ typedef jmp_buf korp_jmpbuf;
 
 #define os_getpagesize getpagesize
 
-bool os_thread_init_stack_guard_pages();
-
-void os_thread_destroy_stack_guard_pages();
-
 typedef void (*os_signal_handler)(void *sig_addr);
 
-int os_signal_init(os_signal_handler handler);
+int os_thread_signal_init(os_signal_handler handler);
+
+void os_thread_signal_destroy();
 
-void os_signal_destroy();
+bool os_thread_signal_inited();
 
 void os_signal_unmask();
 

+ 4 - 2
core/shared/platform/windows/platform_internal.h

@@ -72,9 +72,11 @@ typedef jmp_buf korp_jmpbuf;
 #define os_setjmp setjmp
 #define os_longjmp longjmp
 
-bool os_thread_init_stack_guard_pages();
+int os_thread_signal_init();
 
-void os_thread_destroy_stack_guard_pages();
+void os_thread_signal_destroy();
+
+bool os_thread_signal_inited();
 
 #define os_signal_unmask() (void)0
 #define os_sigreturn() (void)0

+ 20 - 7
core/shared/platform/windows/win_thread.c

@@ -154,6 +154,10 @@ os_thread_wrapper(void *arg)
     os_mutex_lock(&parent->wait_lock);
     thread_data->thread_id = GetCurrentThreadId();
     result = TlsSetValue(thread_data_key, thread_data);
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+    if (result)
+        result = os_thread_signal_init() == 0 ? true : false;
+#endif
     /* Notify parent thread */
     os_cond_signal(&parent->wait_cond);
     os_mutex_unlock(&parent->wait_lock);
@@ -511,25 +515,34 @@ os_thread_get_stack_boundary()
     return thread_stack_boundary;
 }
 
-static os_thread_local_attribute bool stack_guard_pages_inited = false;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+static os_thread_local_attribute bool thread_signal_inited = false;
 
-bool
-os_thread_init_stack_guard_pages()
+int
+os_thread_signal_init()
 {
     ULONG StackSizeInBytes = 16 * 1024;
     bool ret;
 
-    if (stack_guard_pages_inited)
+    if (thread_signal_inited)
         return true;
 
     ret = SetThreadStackGuarantee(&StackSizeInBytes);
     if (ret)
-        stack_guard_pages_inited = true;
-    return ret;
+        thread_signal_inited = true;
+    return ret ? 0 : -1;
 }
 
 void
-os_thread_destroy_stack_guard_pages()
+os_thread_signal_destroy()
+{
+    /* Do nothing */
+}
+
+bool
+os_thread_signal_inited()
 {
+    return thread_signal_inited;
 }
+#endif