From c39eb46b6fa9d27f8bc835bf18b4e76ab84e7305 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 30 Jun 2023 11:22:46 +0900 Subject: [PATCH 001/123] Add a few more assertions on structures to which aot abi is sensitive (#2326) --- core/iwasm/aot/aot_runtime.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 815704bd0..35735b94e 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -42,6 +42,9 @@ bh_static_assert(offsetof(AOTModuleInstance, cur_exception) bh_static_assert(offsetof(AOTModuleInstance, global_table_data) == 13 * sizeof(uint64) + 128 + 11 * sizeof(uint64)); +bh_static_assert(sizeof(AOTMemoryInstance) == 104); +bh_static_assert(offsetof(AOTTableInstance, elems) == 8); + bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0); static void From 569f702ec2ea2e36ebe5b819b482308250454eb7 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Mon, 3 Jul 2023 07:36:01 +0100 Subject: [PATCH 002/123] Fix sanitizer errors in posix socket (#2331) --- core/iwasm/common/wasm_shared_memory.c | 4 ++-- core/shared/platform/common/posix/posix_socket.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index 54fc8200f..314938d60 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -37,7 +37,7 @@ typedef struct AtomicWaitNode { static HashMap *wait_map; static uint32 -wait_address_hash(void *address); +wait_address_hash(const void *address); static bool wait_address_equal(void *h1, void *h2); @@ -174,7 +174,7 @@ shared_memory_set_memory_inst(WASMModuleCommon *module, /* Atomics wait && notify APIs */ static uint32 -wait_address_hash(void *address) +wait_address_hash(const void *address) { return (uint32)(uintptr_t)address; } diff --git a/core/shared/platform/common/posix/posix_socket.c b/core/shared/platform/common/posix/posix_socket.c index e33781d7d..c018588ae 100644 --- a/core/shared/platform/common/posix/posix_socket.c +++ b/core/shared/platform/common/posix/posix_socket.c @@ -275,6 +275,9 @@ os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, return -1; } } + else { + memset(src_addr, 0, sizeof(*src_addr)); + } return ret; } From 6ed4c9c908a0394d7de2c73dc5efa9343a967fdb Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Mon, 3 Jul 2023 14:02:10 +0100 Subject: [PATCH 003/123] Increase default native stack size (#2332) Calling `__wasi_sock_addr_resolve` syscall causes native stack overflow. Given this is a standard function available in WAMR, we should have at least the default stack size large enough to handle this case. The socket tests were updated so they also run in separate thread, but the simple retro program is: ```C void *th(void *p) { struct addrinfo *res; getaddrinfo("amazon.com", NULL, NULL, &res); return NULL; } int main(int argc, char **argv) { pthread_t pt; pthread_create(&pt, NULL, th, NULL); pthread_join(pt, NULL); return 0; } ``` --- core/config.h | 2 +- .../libraries/lib-socket/test/nslookup.c | 22 +++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/core/config.h b/core/config.h index 2c382d174..0d99d5803 100644 --- a/core/config.h +++ b/core/config.h @@ -384,7 +384,7 @@ #define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024) #define APP_THREAD_STACK_SIZE_MIN (48 * 1024) #else -#define APP_THREAD_STACK_SIZE_DEFAULT (32 * 1024) +#define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024) #define APP_THREAD_STACK_SIZE_MIN (24 * 1024) #endif #endif /* end of !(defined(APP_THREAD_STACK_SIZE_DEFAULT) \ diff --git a/core/iwasm/libraries/lib-socket/test/nslookup.c b/core/iwasm/libraries/lib-socket/test/nslookup.c index 37150f1eb..543a3fb24 100644 --- a/core/iwasm/libraries/lib-socket/test/nslookup.c +++ b/core/iwasm/libraries/lib-socket/test/nslookup.c @@ -5,6 +5,8 @@ #include #include +#include +#include #ifdef __wasi__ #include #include @@ -39,11 +41,27 @@ test_nslookup(int af) freeaddrinfo(res); } +void * +test_nslookup_mt(void *params) +{ + int *af = (int *)params; + test_nslookup(*af); +} + int main() { - test_nslookup(AF_INET); /* for ipv4 */ - test_nslookup(AF_INET6); /* for ipv6 */ + int afs[] = { AF_INET, AF_INET6 }; + + for (int i = 0; i < sizeof(afs) / sizeof(afs[0]); i++) { + pthread_t th; + + printf("Testing %d in main thread...\n", afs[i]); + test_nslookup(afs[i]); + printf("Testing %d in a new thread...\n", afs[i]); + pthread_create(&th, NULL, test_nslookup_mt, &afs[i]); + pthread_join(th, NULL); + } return 0; } From df98d9fb4a111edb4b6427108f862dab18ed88c9 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 4 Jul 2023 12:03:40 +0800 Subject: [PATCH 004/123] Add "--xip" option for wamrc (#2336) Add shorthand "--xip" option for wamrc, which is equal to "--enalbe-indirect-mode --disable-llvm-intrinsics" --- doc/xip.md | 4 ++++ wamr-compiler/main.c | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/doc/xip.md b/doc/xip.md index d6c5a3701..9e9d1699b 100644 --- a/doc/xip.md +++ b/doc/xip.md @@ -7,8 +7,12 @@ Some IoT devices may require to run the AOT file from flash or ROM which is read The XIP file is an AOT file without (or with few) relocations to patch the AOT code (or text section). Developer can use the option `--enable-indirect-mode --disable-llvm-intrinsics` for wamrc to generate the AOT file, e.g.: ```bash wamrc --enable-indirect-mode --disable-llvm-intrinsics -o +or +wamrc --xip -o ``` +Note: --xip is a short option for --enable-indirect-mode --disable-llvm-intrinsics + ## Known issues There may be some relocations to the ".rodata" like sections which require to patch the AOT code. More work will be done to resolve it in the future. diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index ce6ed7006..37d659524 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -65,6 +65,7 @@ print_help() printf(" --enable-dump-call-stack Enable stack trace feature\n"); printf(" --enable-perf-profiling Enable function performance profiling\n"); printf(" --enable-memory-profiling Enable memory usage profiling\n"); + printf(" --xip A shorthand of --enalbe-indirect-mode --disable-llvm-intrinsics\n"); printf(" --enable-indirect-mode Enalbe call function through symbol table but not direct call\n"); printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n"); printf(" --disable-llvm-lto Disable the LLVM link time optimization\n"); @@ -325,6 +326,10 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--enable-memory-profiling")) { option.enable_stack_estimation = true; } + else if (!strcmp(argv[0], "--xip")) { + option.is_indirect_mode = true; + option.disable_llvm_intrinsics = true; + } else if (!strcmp(argv[0], "--enable-indirect-mode")) { option.is_indirect_mode = true; } From 44f4b4f06289f9c6e4ea80749fa2e9db41839215 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 4 Jul 2023 12:20:52 +0800 Subject: [PATCH 005/123] Add "--enable-llvm-passes=" option to wamrc (#2335) Add "--enable-llvm-passes=" option to wamrc for customizing LLVM passes --- core/iwasm/compilation/aot_llvm.c | 3 +++ core/iwasm/compilation/aot_llvm.h | 2 ++ core/iwasm/compilation/aot_llvm_extra.cpp | 4 ++++ core/iwasm/include/aot_export.h | 1 + wamr-compiler/main.c | 7 +++++++ 5 files changed, 17 insertions(+) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 89b11d77c..5c58eb6bc 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -2296,6 +2296,9 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) if (option->enable_stack_estimation) comp_ctx->enable_stack_estimation = true; + if (option->llvm_passes) + comp_ctx->llvm_passes = option->llvm_passes; + comp_ctx->opt_level = option->opt_level; comp_ctx->size_level = option->size_level; diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 2f187b694..d8808a202 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -417,6 +417,7 @@ typedef struct AOTCompContext { const char *stack_usage_file; char stack_usage_temp_file[64]; + const char *llvm_passes; } AOTCompContext; enum { @@ -455,6 +456,7 @@ typedef struct AOTCompOption { char **custom_sections; uint32 custom_sections_count; const char *stack_usage_file; + const char *llvm_passes; } AOTCompOption, *aot_comp_option_t; bool diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index 109039406..47568d54b 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -373,6 +373,10 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + if (comp_ctx->llvm_passes) { + ExitOnErr(PB.parsePassPipeline(MPM, comp_ctx->llvm_passes)); + } + if (!disable_llvm_lto) { /* Apply LTO for AOT mode */ if (comp_ctx->comp_data->func_count >= 10 diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h index dca26aa6e..99b27577f 100644 --- a/core/iwasm/include/aot_export.h +++ b/core/iwasm/include/aot_export.h @@ -67,6 +67,7 @@ typedef struct AOTCompOption { char **custom_sections; uint32_t custom_sections_count; const char *stack_usage_file; + const char *llvm_passes; } AOTCompOption, *aot_comp_option_t; bool diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 37d659524..999c35490 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -70,6 +70,8 @@ print_help() printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n"); printf(" --disable-llvm-lto Disable the LLVM link time optimization\n"); printf(" --enable-llvm-pgo Enable LLVM PGO (Profile-Guided Optimization)\n"); + printf(" --enable-llvm-passes=\n"); + printf(" Enable the specified LLVM passes, using comma to separate\n"); printf(" --use-prof-file= Use profile file collected by LLVM PGO (Profile-Guided Optimization)\n"); printf(" --enable-segue[=] Enable using segment register GS as the base address of linear memory,\n"); printf(" only available on linux/linux-sgx x86-64, which may improve performance,\n"); @@ -342,6 +344,11 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--enable-llvm-pgo")) { option.enable_llvm_pgo = true; } + else if (!strncmp(argv[0], "--enable-llvm-passes=", 21)) { + if (argv[0][21] == '\0') + PRINT_HELP_AND_EXIT(); + option.llvm_passes = argv[0] + 21; + } else if (!strncmp(argv[0], "--use-prof-file=", 16)) { if (argv[0][16] == '\0') PRINT_HELP_AND_EXIT(); From 18092f86ccdd0a9a0a1917b7bcb7c0161f47333d Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 4 Jul 2023 16:21:30 +0800 Subject: [PATCH 006/123] Make memory access boundary check behavior configurable (#2289) Allow to use `cmake -DWAMR_CONFIGURABLE_BOUNDS_CHECKS=1` to build iwasm, and then run `iwasm --disable-bounds-checks` to disable the memory access boundary checks. And add two APIs: `wasm_runtime_set_bounds_checks` and `wasm_runtime_is_bounds_checks_enabled` --- build-scripts/config_common.cmake | 4 ++ core/config.h | 5 ++ core/iwasm/aot/aot_runtime.h | 4 ++ core/iwasm/common/wasm_memory.c | 60 +++++++++++++++++++- core/iwasm/common/wasm_runtime_common.c | 48 ++++++++++++++++ core/iwasm/common/wasm_runtime_common.h | 11 ++++ core/iwasm/include/wasm_export.h | 19 +++++++ core/iwasm/interpreter/wasm_interp_classic.c | 44 ++++++++------ core/iwasm/interpreter/wasm_interp_fast.c | 27 +++++---- core/iwasm/interpreter/wasm_runtime.h | 4 ++ doc/perf_tune.md | 15 +++++ product-mini/platforms/nuttx/wamr.mk | 6 ++ product-mini/platforms/posix/main.c | 17 ++++++ 13 files changed, 234 insertions(+), 30 deletions(-) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 19f0772c9..6b4247e03 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -396,3 +396,7 @@ if (WAMR_DISABLE_WRITE_GS_BASE EQUAL 1) add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=1) message (" Write linear memory base addr to x86 GS register disabled") endif () +if (WAMR_CONFIGUABLE_BOUNDS_CHECKS EQUAL 1) + add_definitions (-DWASM_CONFIGURABLE_BOUNDS_CHECKS=1) + message (" Configurable bounds checks enabled") +endif () diff --git a/core/config.h b/core/config.h index 0d99d5803..f33290f0d 100644 --- a/core/config.h +++ b/core/config.h @@ -456,4 +456,9 @@ #define WASM_DISABLE_WRITE_GS_BASE 0 #endif +/* Configurable bounds checks */ +#ifndef WASM_CONFIGURABLE_BOUNDS_CHECKS +#define WASM_CONFIGURABLE_BOUNDS_CHECKS 0 +#endif + #endif /* end of _CONFIG_H_ */ diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 5aaac41b7..8d679d55c 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -90,6 +90,10 @@ typedef struct AOTFunctionInstance { typedef struct AOTModuleInstanceExtra { DefPointer(const uint32 *, stack_sizes); CApiFuncImport *c_api_func_imports; +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + /* Disable bounds checks or not */ + bool disable_bounds_checks; +#endif } AOTModuleInstanceExtra; #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 310dab6d2..b2ec2a897 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -5,6 +5,7 @@ #include "wasm_runtime_common.h" #include "../interpreter/wasm_runtime.h" +#include "../aot/aot_runtime.h" #include "bh_platform.h" #include "mem_alloc.h" @@ -87,6 +88,16 @@ wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func, } #endif +static inline bool +is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + return wasm_runtime_is_bounds_checks_enabled(module_inst); +#else + return true; +#endif +} + bool wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type, const MemAllocOption *alloc_option) @@ -269,6 +280,10 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm, bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + if (!is_bounds_checks_enabled(module_inst_comm)) { + return true; + } + memory_inst = wasm_get_default_memory(module_inst); if (!memory_inst) { goto fail; @@ -299,6 +314,10 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm, bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + if (!is_bounds_checks_enabled(module_inst_comm)) { + return true; + } + if (!wasm_runtime_get_app_addr_range(module_inst_comm, app_str_offset, NULL, &app_end_offset)) goto fail; @@ -327,6 +346,10 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm, bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + if (!is_bounds_checks_enabled(module_inst_comm)) { + return true; + } + memory_inst = wasm_get_default_memory(module_inst); if (!memory_inst) { goto fail; @@ -354,10 +377,13 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm, WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst; uint8 *addr; + bool bounds_checks; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + bounds_checks = is_bounds_checks_enabled(module_inst_comm); + memory_inst = wasm_get_default_memory(module_inst); if (!memory_inst) { return NULL; @@ -365,8 +391,17 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm, addr = memory_inst->memory_data + app_offset; - if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end) + if (bounds_checks) { + if (memory_inst->memory_data <= addr + && addr < memory_inst->memory_data_end) { + + return addr; + } + } + /* If bounds checks is disabled, return the address directly */ + else if (app_offset != 0) { return addr; + } return NULL; } @@ -378,17 +413,27 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm, WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst; uint8 *addr = (uint8 *)native_ptr; + bool bounds_checks; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + bounds_checks = is_bounds_checks_enabled(module_inst_comm); + memory_inst = wasm_get_default_memory(module_inst); if (!memory_inst) { return 0; } - if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end) + if (bounds_checks) { + if (memory_inst->memory_data <= addr + && addr < memory_inst->memory_data_end) + return (uint32)(addr - memory_inst->memory_data); + } + /* If bounds checks is disabled, return the offset directly */ + else if (addr != NULL) { return (uint32)(addr - memory_inst->memory_data); + } return 0; } @@ -460,6 +505,7 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, { WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst); uint8 *native_addr; + bool bounds_checks; if (!memory_inst) { goto fail; @@ -467,6 +513,15 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, native_addr = memory_inst->memory_data + app_buf_addr; + bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst); + + if (!bounds_checks) { + if (app_buf_addr == 0) { + native_addr = NULL; + } + goto success; + } + /* No need to check the app_offset and buf_size if memory access boundary check with hardware trap is enabled */ #ifndef OS_ENABLE_HW_BOUND_CHECK @@ -492,6 +547,7 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, } #endif +success: *p_native_addr = (void *)native_addr; return true; fail: diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index b2923db33..5467065f6 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2482,6 +2482,54 @@ wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst_comm) return module_inst->custom_data; } +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 +void +wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst, + bool enable) +{ + /* Alwary disable bounds checks if hw bounds checks enabled */ +#ifdef OS_ENABLE_HW_BOUND_CHECK + enable = false; +#endif +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + ((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e) + ->disable_bounds_checks = enable ? false : true; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e) + ->disable_bounds_checks = enable ? false : true; + } +#endif +} + +bool +wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst) +{ + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + return !((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst) + ->e) + ->disable_bounds_checks; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + return !((AOTModuleInstanceExtra *)((WASMModuleInstance *)module_inst) + ->e) + ->disable_bounds_checks; + } +#endif + + return true; +} +#endif + uint32 wasm_runtime_module_malloc_internal(WASMModuleInstanceCommon *module_inst, WASMExecEnv *exec_env, uint32 size, diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 283d2ed57..60a32cb86 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -593,6 +593,17 @@ wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data); WASM_RUNTIME_API_EXTERN void * wasm_runtime_get_user_data(WASMExecEnv *exec_env); +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN void +wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst, + bool enable); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst); +#endif + #ifdef OS_ENABLE_HW_BOUND_CHECK /* Access exception check guard page to trigger the signal handler */ void diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 28b952e8f..4d02e027e 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -914,6 +914,25 @@ wasm_runtime_set_custom_data(wasm_module_inst_t module_inst, WASM_RUNTIME_API_EXTERN void * wasm_runtime_get_custom_data(wasm_module_inst_t module_inst); +/** + * Set the memory bounds checks flag of a WASM module instance. + * + * @param module_inst the WASM module instance + * @param enable the flag to enable/disable the memory bounds checks + */ +WASM_RUNTIME_API_EXTERN void +wasm_runtime_set_bounds_checks(wasm_module_inst_t module_inst, + bool enable); +/** + * Check if the memory bounds checks flag is enabled for a WASM module instance. + * + * @param module_inst the WASM module instance + * + * @return true if the memory bounds checks flag is enabled, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_bounds_checks_enabled( + wasm_module_inst_t module_inst); /** * Allocate memory from the heap of WASM module instance * diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 6defb046b..d63b0a0e0 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -41,26 +41,28 @@ typedef float64 CellType_F64; #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 -#define CHECK_MEMORY_OVERFLOW(bytes) \ - do { \ - uint64 offset1 = (uint64)offset + (uint64)addr; \ - if (offset1 + bytes <= (uint64)get_linear_mem_size()) \ - /* If offset1 is in valid range, maddr must also \ - be in valid range, no need to check it again. */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ +#define CHECK_MEMORY_OVERFLOW(bytes) \ + do { \ + uint64 offset1 = (uint64)offset + (uint64)addr; \ + if (disable_bounds_checks \ + || offset1 + bytes <= (uint64)get_linear_mem_size()) \ + /* If offset1 is in valid range, maddr must also \ + be in valid range, no need to check it again. */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ } while (0) -#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ - do { \ - uint64 offset1 = (uint32)(start); \ - if (offset1 + bytes <= (uint64)get_linear_mem_size()) \ - /* App heap space is not valid space for \ - bulk memory operation */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ +#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ + do { \ + uint64 offset1 = (uint32)(start); \ + if (disable_bounds_checks \ + || offset1 + bytes <= (uint64)get_linear_mem_size()) \ + /* App heap space is not valid space for \ + bulk memory operation */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ } while (0) #else #define CHECK_MEMORY_OVERFLOW(bytes) \ @@ -1174,6 +1176,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint8 local_type, *global_addr; uint32 cache_index, type_index, param_cell_num, cell_num; uint8 value_type; +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled( + (WASMModuleInstanceCommon *)module); +#else + bool disable_bounds_checks = false; +#endif #if WASM_ENABLE_DEBUG_INTERP != 0 uint8 *frame_ip_orig = NULL; diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 63d300284..0852ab2f3 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -35,7 +35,8 @@ typedef float64 CellType_F64; #define CHECK_MEMORY_OVERFLOW(bytes) \ do { \ uint64 offset1 = (uint64)offset + (uint64)addr; \ - if (offset1 + bytes <= (uint64)get_linear_mem_size()) \ + if (disable_bounds_checks \ + || offset1 + bytes <= (uint64)get_linear_mem_size()) \ /* If offset1 is in valid range, maddr must also \ be in valid range, no need to check it again. */ \ maddr = memory->memory_data + offset1; \ @@ -43,15 +44,15 @@ typedef float64 CellType_F64; goto out_of_bounds; \ } while (0) -#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ - do { \ - uint64 offset1 = (uint32)(start); \ - if (offset1 + bytes <= get_linear_mem_size()) \ - /* App heap space is not valid space for \ - bulk memory operation */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ +#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ + do { \ + uint64 offset1 = (uint32)(start); \ + if (disable_bounds_checks || offset1 + bytes <= get_linear_mem_size()) \ + /* App heap space is not valid space for \ + bulk memory operation */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ } while (0) #else #define CHECK_MEMORY_OVERFLOW(bytes) \ @@ -1199,6 +1200,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint8 *maddr = NULL; uint32 local_idx, local_offset, global_idx; uint8 opcode, local_type, *global_addr; +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled( + (WASMModuleInstanceCommon *)module); +#else + bool disable_bounds_checks = false; +#endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index ef9f0b713..d5665c242 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -241,6 +241,10 @@ typedef struct WASMModuleInstanceExtra { && WASM_ENABLE_LAZY_JIT != 0) WASMModuleInstance *next; #endif +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + /* Disable bounds checks or not */ + bool disable_bounds_checks; +#endif } WASMModuleInstanceExtra; struct AOTFuncPerfProfInfo; diff --git a/doc/perf_tune.md b/doc/perf_tune.md index 05a6433a7..2cc428984 100644 --- a/doc/perf_tune.md +++ b/doc/perf_tune.md @@ -72,3 +72,18 @@ wasm_runtime_dump_pgo_prof_data_to_buf(wasm_module_inst_t module_inst, char *buf 6. Run the optimized aot_file: `iwasm `. Developer can refer to the `test_pgo.sh` files under each benchmark folder for more details, e.g. [test_pgo.sh](../tests/benchmarks/coremark/test_pgo.sh) of CoreMark benchmark. + +## 6. Disable the memory boundary check + +Please notice that this method is not a general solution since it may lead to security issues. And only boost the performance for some platforms in AOT mode and don't support hardware trap for memory boundary check. + +1. Build WAMR with `-DWAMR_CONFIGUABLE_BOUNDS_CHECKS=1` option. + +2. Compile AOT module by wamrc with `--bounds-check=0` option. + +3. Run the AOT module by iwasm with `--disable-bounds-checks` option. + +> Note: The size of AOT file will be much smaller than the default, and some tricks are possible such as let the wasm application access the memory of host os directly. +Please notice that if this option is enabled, the wasm spec test will fail since it requires the memory boundary check. For example, the runtime will crash when accessing the memory out of the boundary in some cases instead of throwing an exception as the spec requires. + +You should only use this method for well tested wasm applications and make sure the memory access is safe. diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 78cf3eea1..da5cdcc27 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -230,6 +230,12 @@ else CFLAGS += -DWASM_ENABLE_LIBC_BUILTIN=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_CONFIGUABLE_BOUNDS_CHECKS),y) +CFLAGS += -DWASM_CONFIGUABLE_BOUNDS_CHECKS=1 +else +CFLAGS += -DWASM_CONFIGUABLE_BOUNDS_CHECKS=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_LIBC_WASI),y) CFLAGS += -DWASM_ENABLE_LIBC_WASI=1 CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 752d235e6..fec8ec661 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -65,6 +65,9 @@ print_help() #endif printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of \"FUNC ARG...\"\n"); +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + printf(" --disable-bounds-checks Disable bounds checks for memory accesses\n"); +#endif #if WASM_ENABLE_LIBC_WASI != 0 printf(" --env= Pass wasi environment variables with \"key=value\"\n"); printf(" to the program, for example:\n"); @@ -481,6 +484,9 @@ main(int argc, char *argv[]) #endif bool is_repl_mode = false; bool is_xip_file = false; +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + bool disable_bounds_checks = false; +#endif #if WASM_ENABLE_LIBC_WASI != 0 const char *dir_list[8] = { NULL }; uint32 dir_list_size = 0; @@ -545,6 +551,11 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--repl")) { is_repl_mode = true; } +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + else if (!strcmp(argv[0], "--disable-bounds-checks")) { + disable_bounds_checks = true; + } +#endif else if (!strncmp(argv[0], "--stack-size=", 13)) { if (argv[0][13] == '\0') return print_help(); @@ -832,6 +843,12 @@ main(int argc, char *argv[]) goto fail3; } +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + if (disable_bounds_checks) { + wasm_runtime_set_bounds_checks(wasm_module_inst, false); + } +#endif + #if WASM_ENABLE_DEBUG_INTERP != 0 if (ip_addr != NULL) { wasm_exec_env_t exec_env = From 1f89e446d9f7188061838acbc4e6d63e15125fce Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 4 Jul 2023 17:48:32 +0900 Subject: [PATCH 007/123] Avoid switch lowering to lookup tables for XIP (#2339) Because it involves relocations for the table. (.Lswitch.table.XXX) Discussions: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2316 --- core/iwasm/compilation/aot_llvm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 5c58eb6bc..3e8eeba62 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -623,6 +623,15 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module, prefix))) goto fail; + if (comp_ctx->is_indirect_mode) { + /* avoid LUT relocations ("switch-table") */ + LLVMAttributeRef attr_no_jump_tables = LLVMCreateStringAttribute( + comp_ctx->context, "no-jump-tables", strlen("no-jump-tables"), + "true", strlen("true")); + LLVMAddAttributeAtIndex(func, LLVMAttributeFunctionIndex, + attr_no_jump_tables); + } + if (need_precheck) { if (!comp_ctx->is_jit_mode) LLVMSetLinkage(func, LLVMInternalLinkage); From ae4069df411640ccba7985e05b8d319d2911c394 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 4 Jul 2023 17:17:15 +0800 Subject: [PATCH 008/123] Migrate ExpandMemoryOpPass to llvm new pass manager (#2334) Fix #2328 --- core/iwasm/compilation/aot_compiler.c | 69 ------------------ core/iwasm/compilation/aot_llvm_extra.cpp | 87 +++++------------------ 2 files changed, 19 insertions(+), 137 deletions(-) diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index bbb31384e..94a378c46 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -2617,64 +2617,6 @@ verify_module(AOTCompContext *comp_ctx) return true; } -/* Check whether the target supports hardware atomic instructions */ -static bool -aot_require_lower_atomic_pass(AOTCompContext *comp_ctx) -{ - bool ret = false; - if (!strncmp(comp_ctx->target_arch, "riscv", 5)) { - char *feature = - LLVMGetTargetMachineFeatureString(comp_ctx->target_machine); - - if (feature) { - if (!strstr(feature, "+a")) { - ret = true; - } - LLVMDisposeMessage(feature); - } - } - return ret; -} - -/* Check whether the target needs to expand switch to if/else */ -static bool -aot_require_lower_switch_pass(AOTCompContext *comp_ctx) -{ - bool ret = false; - - /* IR switch/case will cause .rodata relocation on riscv/xtensa */ - if (!strncmp(comp_ctx->target_arch, "riscv", 5) - || !strncmp(comp_ctx->target_arch, "xtensa", 6)) { - ret = true; - } - - return ret; -} - -static bool -apply_passes_for_indirect_mode(AOTCompContext *comp_ctx) -{ - LLVMPassManagerRef common_pass_mgr; - - if (!(common_pass_mgr = LLVMCreatePassManager())) { - aot_set_last_error("create pass manager failed"); - return false; - } - - aot_add_expand_memory_op_pass(common_pass_mgr); - - if (aot_require_lower_atomic_pass(comp_ctx)) - LLVMAddLowerAtomicPass(common_pass_mgr); - - if (aot_require_lower_switch_pass(comp_ctx)) - LLVMAddLowerSwitchPass(common_pass_mgr); - - LLVMRunPassManager(common_pass_mgr, comp_ctx->module); - - LLVMDisposePassManager(common_pass_mgr); - return true; -} - bool aot_compile_wasm(AOTCompContext *comp_ctx) { @@ -2714,17 +2656,6 @@ aot_compile_wasm(AOTCompContext *comp_ctx) possible core dump. */ bh_print_time("Begin to run llvm optimization passes"); aot_apply_llvm_new_pass_manager(comp_ctx, comp_ctx->module); - - /* Run specific passes for AOT indirect mode in last since general - optimization may create some intrinsic function calls like - llvm.memset, so let's remove these function calls here. */ - if (!comp_ctx->is_jit_mode && comp_ctx->is_indirect_mode) { - bh_print_time("Begin to run optimization passes " - "for indirect mode"); - if (!apply_passes_for_indirect_mode(comp_ctx)) { - return false; - } - } bh_print_time("Finish llvm optimization passes"); } diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index 47568d54b..1ccb2f549 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -73,33 +73,14 @@ LLVM_C_EXTERN_C_END ExitOnError ExitOnErr; -class ExpandMemoryOpPass : public llvm::ModulePass +class ExpandMemoryOpPass : public PassInfoMixin { public: - static char ID; - - ExpandMemoryOpPass() - : ModulePass(ID) - {} - - bool runOnModule(Module &M) override; - - bool expandMemIntrinsicUses(Function &F); - StringRef getPassName() const override - { - return "Expand memory operation intrinsics"; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override - { - AU.addRequired(); - } + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -char ExpandMemoryOpPass::ID = 0; - -bool -ExpandMemoryOpPass::expandMemIntrinsicUses(Function &F) +PreservedAnalyses +ExpandMemoryOpPass::run(Function &F, FunctionAnalysisManager &AM) { Intrinsic::ID ID = F.getIntrinsicID(); bool Changed = false; @@ -114,27 +95,26 @@ ExpandMemoryOpPass::expandMemIntrinsicUses(Function &F) auto *Memcpy = cast(Inst); Function *ParentFunc = Memcpy->getParent()->getParent(); const TargetTransformInfo &TTI = - getAnalysis().getTTI( - *ParentFunc); + AM.getResult(*ParentFunc); expandMemCpyAsLoop(Memcpy, TTI); - Changed = true; Memcpy->eraseFromParent(); + Changed = true; break; } case Intrinsic::memmove: { auto *Memmove = cast(Inst); expandMemMoveAsLoop(Memmove); - Changed = true; Memmove->eraseFromParent(); + Changed = true; break; } case Intrinsic::memset: { auto *Memset = cast(Inst); expandMemSetAsLoop(Memset); - Changed = true; Memset->eraseFromParent(); + Changed = true; break; } default: @@ -142,46 +122,10 @@ ExpandMemoryOpPass::expandMemIntrinsicUses(Function &F) } } - return Changed; -} + PreservedAnalyses PA; + PA.preserveSet(); -bool -ExpandMemoryOpPass::runOnModule(Module &M) -{ - bool Changed = false; - - for (Function &F : M) { - if (!F.isDeclaration()) - continue; - - switch (F.getIntrinsicID()) { - case Intrinsic::memcpy: - case Intrinsic::memmove: - case Intrinsic::memset: - if (expandMemIntrinsicUses(F)) - Changed = true; - break; - - default: - break; - } - } - - return Changed; -} - -void -aot_add_expand_memory_op_pass(LLVMPassManagerRef pass) -{ - reinterpret_cast(pass)->add( - new ExpandMemoryOpPass()); -} - -void -aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass) -{ - reinterpret_cast(pass)->add( - createSimpleLoopUnswitchLegacyPass()); + return PA; } bool @@ -353,6 +297,13 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) FPM.addPass(SLPVectorizerPass()); FPM.addPass(LoadStoreVectorizerPass()); + /* Run specific passes for AOT indirect mode in last since general + optimization may create some intrinsic function calls like + llvm.memset, so let's remove these function calls here. */ + if (comp_ctx->is_indirect_mode) { + FPM.addPass(ExpandMemoryOpPass()); + } + if (comp_ctx->enable_llvm_pgo || comp_ctx->use_prof_file) { /* LICM pass: loop invariant code motion, attempting to remove as much code from the body of a loop as possible. Experiments From a9b76228b0261879101bc3509dd819b49f6f0b96 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Tue, 4 Jul 2023 14:21:21 +0100 Subject: [PATCH 009/123] Allow defining hints without exact socket type or address family (#2337) --- core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h | 4 +++- .../libraries/lib-socket/src/wasi/wasi_socket_ext.c | 5 +++++ .../sandboxed-system-primitives/include/wasmtime_ssp.h | 4 +++- .../libc-wasi/sandboxed-system-primitives/src/posix.c | 9 ++++++--- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h b/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h index c9a07eb72..98429bbb0 100644 --- a/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h +++ b/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h @@ -17,6 +17,8 @@ extern "C" { #endif typedef enum { + /* Used only for sock_addr_resolve hints */ + SOCKET_ANY = -1, SOCKET_DGRAM = 0, SOCKET_STREAM, } __wasi_sock_type_t; @@ -84,7 +86,7 @@ typedef struct __wasi_addr_t { } addr; } __wasi_addr_t; -typedef enum { INET4 = 0, INET6 } __wasi_address_family_t; +typedef enum { INET4 = 0, INET6, INET_UNSPEC } __wasi_address_family_t; typedef struct __wasi_addr_info_t { __wasi_addr_t addr; diff --git a/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c b/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c index defbc6efe..1172d0a77 100644 --- a/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c +++ b/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c @@ -430,6 +430,9 @@ addrinfo_hints_to_wasi_hints(const struct addrinfo *hints, case AF_INET6: wasi_hints->family = INET6; break; + case AF_UNSPEC: + wasi_hints->family = INET_UNSPEC; + break; default: return __WASI_ERRNO_AFNOSUPPORT; } @@ -440,6 +443,8 @@ addrinfo_hints_to_wasi_hints(const struct addrinfo *hints, case SOCK_DGRAM: wasi_hints->type = SOCKET_DGRAM; break; + case 0: + wasi_hints->type = SOCKET_ANY; default: return __WASI_ERRNO_NOTSUP; } diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index feadf2f95..586e5816d 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -552,6 +552,8 @@ _Static_assert(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset" /* keep syncing with wasi_socket_ext.h */ typedef enum { + /* Used only for sock_addr_resolve hints */ + SOCKET_ANY = -1, SOCKET_DGRAM = 0, SOCKET_STREAM, } __wasi_sock_type_t; @@ -605,7 +607,7 @@ typedef struct __wasi_addr_t { } addr; } __wasi_addr_t; -typedef enum { INET4 = 0, INET6 } __wasi_address_family_t; +typedef enum { INET4 = 0, INET6, INET_UNSPEC } __wasi_address_family_t; typedef struct __wasi_addr_info_t { __wasi_addr_t addr; diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 61e841836..3038e3d44 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -3102,9 +3102,12 @@ wasi_ssp_sock_addr_resolve( } int ret = os_socket_addr_resolve( - host, service, hints->hints_enabled ? &hints_is_tcp : NULL, - hints->hints_enabled ? &hints_is_ipv4 : NULL, wamr_addr_info, - addr_info_size, &_max_info_size); + host, service, + hints->hints_enabled && hints->type != SOCKET_ANY ? &hints_is_tcp + : NULL, + hints->hints_enabled && hints->family != INET_UNSPEC ? &hints_is_ipv4 + : NULL, + wamr_addr_info, addr_info_size, &_max_info_size); if (ret != BHT_OK) { wasm_runtime_free(wamr_addr_info); From 3bbf59ad45eb6e476b102733ed56250e28e383b6 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 5 Jul 2023 11:49:45 +0900 Subject: [PATCH 010/123] wamrc: Warn on text relocations for XIP (#2340) --- core/iwasm/compilation/aot_emit_aot_file.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index ae390dfc3..bebae5506 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -3087,6 +3087,13 @@ is_relocation_section(AOTObjectData *obj_data, LLVMSectionIteratorRef sec_itr) return false; } +static bool +is_readonly_section(const char *name) +{ + return !strcmp(name, ".rel.text") || !strcmp(name, ".rela.text") + || !strcmp(name, ".rela.literal") || !strcmp(name, ".text"); +} + static bool get_relocation_groups_count(AOTObjectData *obj_data, uint32 *p_count) { @@ -3184,6 +3191,19 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data) relocation_group->section_name = ".rel.text"; } + /* + * Relocations in read-only sections are problematic, + * especially for XIP on platforms which don't have + * copy-on-write mappings. + */ + if (obj_data->comp_ctx->is_indirect_mode + && is_readonly_section(relocation_group->section_name)) { + LOG_WARNING("%" PRIu32 + " text relocations in %s section for indirect mode", + relocation_group->relocation_count, + relocation_group->section_name); + } + relocation_group++; } LLVMMoveToNextSection(sec_itr); From 25a19854139df0db0db9c5dffd614cbd8fa75f12 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Wed, 5 Jul 2023 15:58:57 +0800 Subject: [PATCH 011/123] Add scripts to validate lldb source debugger (#2150) --- .github/workflows/build_wamr_lldb.yml | 25 ++++++ ci/validate_lldb.py | 124 ++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100755 ci/validate_lldb.py diff --git a/.github/workflows/build_wamr_lldb.yml b/.github/workflows/build_wamr_lldb.yml index c376506ed..e0f9595c7 100644 --- a/.github/workflows/build_wamr_lldb.yml +++ b/.github/workflows/build_wamr_lldb.yml @@ -22,6 +22,12 @@ on: description: a semantic version number type: string required: true + wasi_sdk_url: + description: download WASI_SDK from this URL + type: string + required: false + default: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz" + jobs: try_reuse: @@ -43,6 +49,15 @@ jobs: PYTHON_MACOS_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-apple-darwin-install_only.tar.gz steps: - uses: actions/checkout@v3 + + - name: download and install wasi-sdk + run: | + cd /opt + basename=$(basename ${{ inputs.wasi_sdk_url }}) + sudo wget --progress=dot:giga ${{ inputs.wasi_sdk_url }} + sudo tar -xzf ${basename} + sudo rm ${basename} + sudo mv wasi-sdk-* wasi-sdk - name: Cache build id: lldb_build_cache @@ -141,6 +156,16 @@ jobs: cmake --build build --target lldb install --parallel $(nproc) working-directory: core/deps/llvm-project + - name: validate lldb ubuntu + if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'ubuntu') + run: | + echo "start to validate lldb..." + mkdir -p wamr-debug + cmake -S product-mini/platforms/linux -B wamr-debug -DWAMR_BUILD_DEBUG_INTERP=1 + cmake --build wamr-debug --parallel $(nproc) + python3 ci/validate_lldb.py --port 1239 --lldb core/deps/wamr-lldb/bin/lldb --wamr wamr-debug/iwasm --verbose + working-directory: . + - name: build lldb macos if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos') run: | diff --git a/ci/validate_lldb.py b/ci/validate_lldb.py new file mode 100755 index 000000000..0bf743c0f --- /dev/null +++ b/ci/validate_lldb.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import argparse +import time +from pathlib import Path +import subprocess, shlex + +SCRIPT_DIR = Path(__file__).parent.resolve() +REPO_ROOT_DIR = SCRIPT_DIR.parent +SAMPLE_CODE_FILE = REPO_ROOT_DIR / 'product-mini/app-samples/hello-world/main.c' +WASM_OUT_FILE = SCRIPT_DIR / 'out.wasm' + +parser = argparse.ArgumentParser( + description="Validate the customized lldb with sample code" +) +parser.add_argument( + "-l", "--lldb", dest='lldb', default='lldb', help="path to lldb executable" +) +parser.add_argument( + "-w", "--wamr", dest='wamr', default='iwasm', help="path to iwasm executable" +) +parser.add_argument( + "-p", "--port", dest='port', default='1234', help="debug server listen port" +) +parser.add_argument( + "-v", "--verbose", dest='verbose', action='store_true', default=False, help="display lldb stdout" +) + +options = parser.parse_args() + +lldb_command_prologue = f'{options.lldb} -o "process connect -p wasm connect://127.0.0.1:{options.port}"' +lldb_command_epilogue = '-o q' + +test_cases = { + 'run_to_exit': '-o c', + 'func_breakpoint': '-o "b main" -o c -o c', + 'line_breakpoint': '-o "b main.c:12" -o c -o c', + 'break_on_unknown_func': '-o "b not_a_func" -o c', + 'watch_point': '-o "b main" -o c -o "watchpoint set variable buf" -o c -o "fr v buf" -o c', +} + +# Step1: Build wasm module with debug information +build_cmd = f'/opt/wasi-sdk/bin/clang -g -O0 -o {WASM_OUT_FILE} {SAMPLE_CODE_FILE}' +try: + print(f'building wasm module ...', end='', flush=True) + subprocess.check_call(shlex.split(build_cmd)) + print(f'\t OK') +except subprocess.CalledProcessError: + print("Failed to build wasm module with debug information") + exit(1) + +def print_process_output(p): + try: + outs, errs = p.communicate(timeout=2) + print("stdout:") + print(outs) + print("stderr:") + print(errs) + except subprocess.TimeoutExpired: + print("Failed to get process output") + +# Step2: Launch WAMR in debug mode and validate lldb commands +wamr_cmd = f'{options.wamr} -g=127.0.0.1:{options.port} {WASM_OUT_FILE}' +for case, cmd in test_cases.items(): + has_error = False + print(f'validating case [{case}] ...', end='', flush=True) + lldb_cmd = f'{lldb_command_prologue} {cmd} {lldb_command_epilogue}' + + wamr_process = subprocess.Popen(shlex.split( + wamr_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + + time.sleep(0.1) + if (wamr_process.poll() != None): + print("\nWAMR doesn't wait for lldb connection") + print_process_output(wamr_process) + exit(1) + + lldb_process = subprocess.Popen(shlex.split( + lldb_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + + if (options.verbose): + while (lldb_process.poll() is None): + print(lldb_process.stdout.read(), end='', flush=True) + + try: + if (lldb_process.wait(5) != 0): + print(f"\nFailed to validate case [{case}]") + print_process_output(lldb_process) + has_error = True + + if wamr_process.wait(2) != 0: + print("\nWAMR process doesn't exit normally") + print_process_output(wamr_process) + has_error = True + + except subprocess.TimeoutExpired: + print(f"\nFailed to validate case [{case}]") + print("wamr output:") + print_process_output(wamr_process) + print("lldb output:") + print_process_output(lldb_process) + has_error = True + finally: + if (lldb_process.poll() == None): + print(f'\nterminating lldb process [{lldb_process.pid}]') + lldb_process.kill() + if (wamr_process.poll() == None): + print(f'terminating wamr process [{wamr_process.pid}]') + wamr_process.kill() + + if (has_error): + exit(1) + + print(f'\t OK') + + # wait 100ms to ensure the socket is closed + time.sleep(0.1) + +print('Validate lldb success') +exit(0) From e495276646c7c1adacc002259bdedb530aad3166 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Thu, 6 Jul 2023 10:11:39 +0800 Subject: [PATCH 012/123] Add docker file to fix Zephy ESP32 linking issue (#2314) - Provide a Dockerfile.old to fix issue of ESP32 custom linker scripts not working properly with the newer version of Zephyr, as reported in #2263 - Provide a Dockerfile with newer Zephyr for other boards - Update the corresponding document --- product-mini/README.md | 12 +- .../platforms/zephyr/simple/Dockerfile | 60 ++++++++++ .../platforms/zephyr/simple/Dockerfile.old | 58 ++++++++++ .../platforms/zephyr/simple/README.md | 106 ++++++++++++++++++ .../platforms/zephyr/simple/README_docker.md | 25 ----- 5 files changed, 225 insertions(+), 36 deletions(-) create mode 100644 product-mini/platforms/zephyr/simple/Dockerfile create mode 100644 product-mini/platforms/zephyr/simple/Dockerfile.old create mode 100644 product-mini/platforms/zephyr/simple/README.md delete mode 100644 product-mini/platforms/zephyr/simple/README_docker.md diff --git a/product-mini/README.md b/product-mini/README.md index 5847b2468..92f8183e0 100644 --- a/product-mini/README.md +++ b/product-mini/README.md @@ -251,17 +251,7 @@ WAMR provides some features which can be easily configured by passing options to ## Zephyr -You need to prepare Zephyr first as described [here](https://docs.zephyrproject.org/latest/getting_started/index.html#get-zephyr-and-install-python-dependencies). - -After that you need to point the `ZEPHYR_BASE` variable to e.g. `~/zephyrproject/zephyr`. Also, it is important that you have `west` available for subsequent actions. - -``` Bash -cd /product-mini/platforms/zephyr/simple -# Execute the ./build_and_run.sh script with board name as parameter. Here take x86 as example: -./build_and_run.sh x86 -``` - -The [Zephyr SDK](https://github.com/zephyrproject-rtos/sdk-ng) provides toolchains for all supported targets. Follow the instructions in the [documentation](https://docs.zephyrproject.org/latest/develop/getting_started/index.html#install-zephyr-sdk) to ensure it is installed and configured correctly. +Please refer to this [README](./platforms/zephyr/simple/README.md) under the Zephyr sample directory for details. Note: WAMR provides some features which can be easily configured by passing options to cmake, please see [WAMR vmcore cmake building configurations](../doc/build_wamr.md#wamr-vmcore-cmake-building-configurations) for details. Currently in Zephyr, interpreter, AOT and builtin libc are enabled by default. diff --git a/product-mini/platforms/zephyr/simple/Dockerfile b/product-mini/platforms/zephyr/simple/Dockerfile new file mode 100644 index 000000000..9c8e6e5a0 --- /dev/null +++ b/product-mini/platforms/zephyr/simple/Dockerfile @@ -0,0 +1,60 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +FROM ubuntu:20.04 + +ARG DEBIAN_FRONTEND=noninteractive +ENV TZ=Asian/Shanghai + +# Install dependencies for Zephyr and ESPRESSIF +# hadolint ignore=DL3008 +RUN apt-get update && apt-get install -y git wget flex bison gperf python3 python3-pip python3-venv\ + python3-dev python3-setuptools python3-tk python3-wheel xz-utils file libpython3.8-dev \ + ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 device-tree-compiler \ + make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 qemu udev --no-install-recommends \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* + +# Install recent CMake version +WORKDIR /tmp +RUN mkdir /opt/cmake \ + && wget --progress=dot:giga https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1-linux-x86_64.sh \ + && sh cmake-3.22.1-linux-x86_64.sh --skip-license --prefix=/opt/cmake && rm cmake-3.22.1-linux-x86_64.sh +ENV PATH="/opt/cmake/bin:$PATH" + +# Install the Zephyr Software Development Kit (SDK) +WORKDIR /opt +# hadolint ignore=DL4006 +RUN wget --progress=dot:giga https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64.tar.xz \ + && wget --progress=dot:giga -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing \ + && tar xvf zephyr-sdk-0.16.1_linux-x86_64.tar.xz && rm zephyr-sdk-0.16.1_linux-x86_64.tar.xz + +WORKDIR /opt/zephyr-sdk-0.16.1 +# hadolint ignore=DL4006 +RUN yes | ./setup.sh + +# Get ESP-IDF +RUN ln -s /usr/bin/python3 /usr/bin/python && mkdir -p ~/esp +WORKDIR /root/esp +RUN git clone https://github.com/espressif/esp-idf.git +WORKDIR /root/esp/esp-idf +RUN git checkout 03d4fa28694ee15ccfd5a97447575de2d1655026 \ + && git submodule update --init --recursive +# Set up the sep-idf tools +RUN ./install.sh esp32 esp32c3 + +# Get Zephyr +# hadolint ignore=DL3013 +RUN pip3 install --no-cache-dir west && west init -m https://github.com/zephyrproject-rtos/zephyr --mr v3.4.0 /root/zephyrproject + +WORKDIR /root/zephyrproject +RUN west update + +WORKDIR /root/zephyrproject/zephyr +RUN west zephyr-export && pip install --no-cache-dir -r ~/zephyrproject/zephyr/scripts/requirements.txt + +# Git clone wamr +WORKDIR /root +RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git + +WORKDIR /root/wasm-micro-runtime/product-mini/platforms/zephyr/simple + +ENV ZEPHYR_BASE="/root/zephyrproject/zephyr" diff --git a/product-mini/platforms/zephyr/simple/Dockerfile.old b/product-mini/platforms/zephyr/simple/Dockerfile.old new file mode 100644 index 000000000..633f3ea6c --- /dev/null +++ b/product-mini/platforms/zephyr/simple/Dockerfile.old @@ -0,0 +1,58 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +FROM ubuntu:20.04 + +ARG DEBIAN_FRONTEND=noninteractive +ENV TZ=Asian/Shanghai + +# Install dependencies for Zephyr and ESPRESSIF +# hadolint ignore=DL3008 +RUN apt-get update && apt-get install -y git wget flex bison gperf python3 python3-pip python3-venv\ + python3-dev python3-setuptools python3-tk python3-wheel xz-utils file libpython3.8-dev \ + ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 device-tree-compiler \ + make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 qemu udev --no-install-recommends \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* + +# Install recent CMake version +WORKDIR /tmp +RUN mkdir /opt/cmake \ + && wget --progress=dot:giga https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1-linux-x86_64.sh \ + && sh cmake-3.22.1-linux-x86_64.sh --skip-license --prefix=/opt/cmake && rm cmake-3.22.1-linux-x86_64.sh +ENV PATH="/opt/cmake/bin:$PATH" + +# Install the Zephyr Software Development Kit (SDK) +WORKDIR /opt +# hadolint ignore=DL4006 +RUN wget --progress=dot:giga https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.11.3/zephyr-sdk-0.11.3-setup.run \ + && chmod +x ./zephyr-sdk-0.11.3-setup.run \ + && ./zephyr-sdk-0.11.3-setup.run -- -d /opt/zephyr-sdk-0.11.3 +ENV ZEPHYR_TOOLCHAIN_VARIANT=zephyr +ENV ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk-0.11.3 + +# Get ESP-IDF +RUN ln -s /usr/bin/python3 /usr/bin/python && mkdir -p ~/esp +WORKDIR /root/esp +RUN git clone https://github.com/espressif/esp-idf.git +WORKDIR /root/esp/esp-idf +RUN git checkout v4.0 \ + && pip install --no-cache-doir virtualenv==16.7.12 \ + && git submodule update --init --recursive \ + && ./install.sh esp32 esp32c3 + +# Get Zephyr +# hadolint ignore=DL3013 +RUN pip3 install --no-cache-dir west && west init -m https://github.com/zephyrproject-rtos/zephyr --mr v2.3.0 /root/zephyrproject + +WORKDIR /root/zephyrproject +RUN west update + +WORKDIR /root/zephyrproject/zephyr +RUN west zephyr-export && pip install --no-cache-dir -r ~/zephyrproject/zephyr/scripts/requirements.txt + +# Git clone wamr +WORKDIR /root +RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git + +WORKDIR /root/wasm-micro-runtime/product-mini/platforms/zephyr/simple + +ENV ZEPHYR_BASE="/root/zephyrproject/zephyr" diff --git a/product-mini/platforms/zephyr/simple/README.md b/product-mini/platforms/zephyr/simple/README.md new file mode 100644 index 000000000..acb955258 --- /dev/null +++ b/product-mini/platforms/zephyr/simple/README.md @@ -0,0 +1,106 @@ +# How to use WAMR with Zephyr + +## Build with Docker(recommend approach) + +To have a quicker start, a Docker container of the Zephyr setup can be generated. The current docker image would be considerably large(~15GB), it would take some time to build it and enough disk space to store it. + +### Build Docker images + +```shell +docker build -t wamr-zephyr . +``` + +> PS: currently, the esp32 custom linker script only works with a lower version of Zephyr, if you want to use an esp32 board, you can build the Dockerfile with a lower version of Zephyr, Zephyr SDE, ESP-IDF. The old version of Docker image can also build other targets, but probably it's a better choice to use the new Dockerfile for other boards + +```shell +# If you want to build on esp32 platform +docker build -f Dockerfile.old -t wamr-zephyr . +``` + +### Run Docker images + +Adopt the device or remove if not needed. + +```shell +docker run -ti --device=/dev/ttyUSB0 wamr-zephyr +``` + +And then inside the docker container: + +```shell +# copy the corresponding board conf file to current directory +cp boards/qemu_x86_nommu.conf prj.conf +# then build +./build_and_run.sh x86 +``` + +> PS: for boards esp32, need to configure some environment first + +```shell +# configure zephyr with espressif +export ZEPHYR_TOOLCHAIN_VARIANT="espressif" +export ESPRESSIF_TOOLCHAIN_PATH="/root/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-elf/" +export ESP_IDF_PATH="/root/esp/esp-idf" +# copy the corresponding board conf file to current directory +cp boards/esp32.conf prj.conf +# then build +./build_and_run.sh esp32 +``` + +## Build on local environment + +### Dependencies installation + +Following the Zephyr and Espressif official document: + +1. Zephyr installation: + + + +2. ESP32 installation: + + + +And setup the Zephyr for esp32: + + + +Then Installing QEMU, for example, on Linux: + +```shell +sudo apt-get install qemu +``` + +### Run the build script + +Make sure you have the environment variable ready, you can use the command `env` to check: + +```shell +env +``` + +```shell +# export ZEPHYR_BASE if it's not present +export ZEPHYR_BASE=~/zephyrproject/zephyr +# and if you install zephyr in virtual environment rather than global +source ~/zephyrproject/.venv/bin/activate +``` + +For boards esp32, need to configure some extra environment first, check the following env variable whether in the env list, if not, add them like: + +> Noted: The esp32 custom linker script doesn't work with the recent version of Zephyr, if you want to use it in the local environment, please install Zephyr 2.3.0 with the corresponding SDK, and ESP-IDF 4.0 + +```shell +export ZEPHYR_TOOLCHAIN_VARIANT="espressif" +export ESPRESSIF_TOOLCHAIN_PATH="~/.espressif/tools/xtensa-esp32-elf/esp-{the version you installed}/xtensa-esp32-elf/" +export ESP_IDF_PATH="~/esp/esp-idf" +``` + +Then you can run the build script: + +```shell +# copy the corresponding board conf file to current directory +cp boards/qemu_x86_nommu.conf prj.conf +# then build +./build_and_run.sh x86 +``` diff --git a/product-mini/platforms/zephyr/simple/README_docker.md b/product-mini/platforms/zephyr/simple/README_docker.md deleted file mode 100644 index e02398b0b..000000000 --- a/product-mini/platforms/zephyr/simple/README_docker.md +++ /dev/null @@ -1,25 +0,0 @@ -# Build with Docker - -To have a quicker start, a Docker container of the Zephyr setup can be generated. - -## Build Docker container - -``` Bash -docker build --build-arg DOCKER_UID=$(id -u) . -t wamr-zephyr -``` - -## Run Docker container to build images - -Enter the docker container (maps the toplevel wasm-micro-runtime repo as volume): - -``` Bash -docker run -ti -v $PWD/../../../..:/home/wamr/source --device=/dev/ttyUSB0 wamr-zephyr -``` - -Adopt the device or remove if not needed. - -And then in the docker container: - -``` Bash -./build_and_run.sh esp32c3 -``` \ No newline at end of file From 6a310cc88ac30c33e45752273582c3a1951ba359 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 6 Jul 2023 12:25:28 +0800 Subject: [PATCH 013/123] Add "--native-lib=" option to wamrc (#2342) --- wamr-compiler/main.c | 126 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 999c35490..47b381683 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -9,6 +9,100 @@ #include "wasm_export.h" #include "aot_export.h" +#if BH_HAS_DLFCN +#include + +typedef uint32 (*get_native_lib_func)(char **p_module_name, + NativeSymbol **p_native_symbols); + +static uint32 +load_and_register_native_libs(const char **native_lib_list, + uint32 native_lib_count, + void **native_handle_list) +{ + uint32 i, native_handle_count = 0, n_native_symbols; + NativeSymbol *native_symbols; + char *module_name; + void *handle; + + for (i = 0; i < native_lib_count; i++) { + /* open the native library */ + if (!(handle = dlopen(native_lib_list[i], RTLD_NOW | RTLD_GLOBAL)) + && !(handle = dlopen(native_lib_list[i], RTLD_LAZY))) { + LOG_WARNING("warning: failed to load native library %s", + native_lib_list[i]); + continue; + } + + /* lookup get_native_lib func */ + get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib"); + if (!get_native_lib) { + LOG_WARNING("warning: failed to lookup `get_native_lib` function " + "from native lib %s", + native_lib_list[i]); + dlclose(handle); + continue; + } + + n_native_symbols = get_native_lib(&module_name, &native_symbols); + + /* register native symbols */ + if (!(n_native_symbols > 0 && module_name && native_symbols + && wasm_runtime_register_natives(module_name, native_symbols, + n_native_symbols))) { + LOG_WARNING("warning: failed to register native lib %s", + native_lib_list[i]); + dlclose(handle); + continue; + } + + native_handle_list[native_handle_count++] = handle; + } + + return native_handle_count; +} + +static void +unregister_and_unload_native_libs(uint32 native_lib_count, + void **native_handle_list) +{ + uint32 i, n_native_symbols; + NativeSymbol *native_symbols; + char *module_name; + void *handle; + + for (i = 0; i < native_lib_count; i++) { + handle = native_handle_list[i]; + + /* lookup get_native_lib func */ + get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib"); + if (!get_native_lib) { + LOG_WARNING("warning: failed to lookup `get_native_lib` function " + "from native lib %p", + handle); + continue; + } + + n_native_symbols = get_native_lib(&module_name, &native_symbols); + if (n_native_symbols == 0 || module_name == NULL + || native_symbols == NULL) { + LOG_WARNING("warning: get_native_lib returned different values for " + "native lib %p", + handle); + continue; + } + + /* unregister native symbols */ + if (!wasm_runtime_unregister_natives(module_name, native_symbols)) { + LOG_WARNING("warning: failed to unregister native lib %p", handle); + continue; + } + + dlclose(handle); + } +} +#endif + /* clang-format off */ static void print_help() @@ -83,6 +177,11 @@ print_help() printf(" Emit the specified custom sections to AoT file, using comma to separate\n"); printf(" multiple names, e.g.\n"); printf(" --emit-custom-sections=section1,section2,sectionN\n"); +#if BH_HAS_DLFCN + printf(" --native-lib= Register native libraries to the WASM module, which\n"); + printf(" are shared object (.so) files, for example:\n"); + printf(" --native-lib=test1.so --native-lib=test2.so\n"); +#endif printf(" -v=n Set log verbose level (0 to 5, default is 2), larger with more log\n"); printf(" --version Show version information\n"); printf("Examples: wamrc -o test.aot test.wasm\n"); @@ -206,6 +305,12 @@ main(int argc, char *argv[]) int log_verbose_level = 2; bool sgx_mode = false, size_level_set = false; int exit_status = EXIT_FAILURE; +#if BH_HAS_DLFCN + const char *native_lib_list[8] = { NULL }; + uint32 native_lib_count = 0; + void *native_handle_list[8] = { NULL }; + uint32 native_handle_count = 0; +#endif option.opt_level = 3; option.size_level = 3; @@ -378,6 +483,18 @@ main(int argc, char *argv[]) option.custom_sections_count = len; } +#if BH_HAS_DLFCN + else if (!strncmp(argv[0], "--native-lib=", 13)) { + if (argv[0][13] == '\0') + PRINT_HELP_AND_EXIT(); + if (native_lib_count >= sizeof(native_lib_list) / sizeof(char *)) { + printf("Only allow max native lib number %d\n", + (int)(sizeof(native_lib_list) / sizeof(char *))); + goto fail0; + } + native_lib_list[native_lib_count++] = argv[0] + 13; + } +#endif else if (!strncmp(argv[0], "--version", 9)) { uint32 major, minor, patch; wasm_runtime_get_version(&major, &minor, &patch); @@ -438,6 +555,12 @@ main(int argc, char *argv[]) bh_log_set_verbose_level(log_verbose_level); +#if BH_HAS_DLFCN + bh_print_time("Begin to load native libs"); + native_handle_count = load_and_register_native_libs( + native_lib_list, native_lib_count, native_handle_list); +#endif + bh_print_time("Begin to load wasm file"); /* load WASM byte buffer from WASM bin file */ @@ -528,6 +651,9 @@ fail2: wasm_runtime_free(wasm_file); fail1: +#if BH_HAS_DLFCN + unregister_and_unload_native_libs(native_handle_count, native_handle_list); +#endif /* Destroy runtime environment */ wasm_runtime_destroy(); From 228a3bed531e4af6d9d525f160b26672ac006615 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 6 Jul 2023 16:31:22 +0900 Subject: [PATCH 014/123] Fix unused warnings on disable_bounds_checks (#2347) --- core/iwasm/interpreter/wasm_interp_classic.c | 3 +++ core/iwasm/interpreter/wasm_interp_fast.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index d63b0a0e0..69037b59c 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1176,12 +1176,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint8 local_type, *global_addr; uint32 cache_index, type_index, param_cell_num, cell_num; uint8 value_type; +#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ + || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 #if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled( (WASMModuleInstanceCommon *)module); #else bool disable_bounds_checks = false; #endif +#endif #if WASM_ENABLE_DEBUG_INTERP != 0 uint8 *frame_ip_orig = NULL; diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 0852ab2f3..40a7d38c8 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1200,12 +1200,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint8 *maddr = NULL; uint32 local_idx, local_offset, global_idx; uint8 opcode, local_type, *global_addr; +#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ + || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 #if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled( (WASMModuleInstanceCommon *)module); #else bool disable_bounds_checks = false; #endif +#endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op From aafea39b8c65ae87b71883732dbe1c4803d3be98 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 6 Jul 2023 18:20:35 +0800 Subject: [PATCH 015/123] Add "--enable-builtin-intrinsics=" option to wamrc (#2341) Refer to doc/xip.md for details. --- core/iwasm/aot/aot_intrinsic.c | 129 ++++++++++++++++++++++++++++++ core/iwasm/compilation/aot_llvm.c | 3 + core/iwasm/compilation/aot_llvm.h | 2 + core/iwasm/include/aot_export.h | 1 + doc/xip.md | 113 ++++++++++++++++++++++++++ wamr-compiler/main.c | 11 +++ 6 files changed, 259 insertions(+) diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index 319eeda5c..189b43b09 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -648,6 +648,42 @@ add_f64_common_intrinsics(AOTCompContext *comp_ctx) add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CMP); } +static void +add_f32xi32_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F32); +} + +static void +add_f64xi32_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F64); +} + +static void +add_f32xi64_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F32); +} + +static void +add_f64xi64_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F64); +} + static void add_common_float_integer_convertion(AOTCompContext *comp_ctx) { @@ -705,8 +741,101 @@ aot_intrinsic_check_capability(const AOTCompContext *comp_ctx, void aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx) { + uint32 i; + memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags)); + /* Intrinsics from command line have highest priority */ + + if (comp_ctx->builtin_intrinsics) { + + /* Handle 'all' group */ + if (strstr(comp_ctx->builtin_intrinsics, "all")) { + for (i = 0; i < g_intrinsic_count; i++) { + add_intrinsic_capability(comp_ctx, g_intrinsic_mapping[i].flag); + } + return; + } + + /* Handle 'i32.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "i32.common")) { + add_i32_common_intrinsics(comp_ctx); + } + + /* Handle 'i64.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "i64.common")) { + add_i64_common_intrinsics(comp_ctx); + } + + /* Handle 'fp.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "fp.common")) { + add_f32_common_intrinsics(comp_ctx); + add_f64_common_intrinsics(comp_ctx); + } + + /* Handle 'f32.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f32.common")) { + add_f32_common_intrinsics(comp_ctx); + } + + /* Handle 'f64.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f64.common")) { + add_f64_common_intrinsics(comp_ctx); + } + + /* Handle 'f32xi32' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f32xi32")) { + add_f32xi32_intrinsics(comp_ctx); + } + + /* Handle 'f64xi32' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f64xi32")) { + add_f64xi32_intrinsics(comp_ctx); + } + + /* Handle 'f32xi64' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f32xi64")) { + add_f32xi64_intrinsics(comp_ctx); + } + + /* Handle 'f64xi64' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f64xi64")) { + add_f64xi64_intrinsics(comp_ctx); + } + + /* Handle 'fpxint' group */ + if (strstr(comp_ctx->builtin_intrinsics, "fpxint")) { + add_f32xi32_intrinsics(comp_ctx); + add_f64xi32_intrinsics(comp_ctx); + add_f32xi64_intrinsics(comp_ctx); + add_f64xi64_intrinsics(comp_ctx); + } + + /* Handle 'constop' group */ + if (strstr(comp_ctx->builtin_intrinsics, "constop")) { + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_CONST); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CONST); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CONST); + } + + /* Handle 'fp.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "fp.common")) { + add_f32_common_intrinsics(comp_ctx); + add_f64_common_intrinsics(comp_ctx); + } + + /* Handle other single items */ + for (i = 0; i < g_intrinsic_count; i++) { + if (strstr(comp_ctx->builtin_intrinsics, + g_intrinsic_mapping[i].llvm_intrinsic)) { + add_intrinsic_capability(comp_ctx, g_intrinsic_mapping[i].flag); + } + } + + return; + } + if (!comp_ctx->target_cpu) return; diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 3e8eeba62..e066f7a62 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -2308,6 +2308,9 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) if (option->llvm_passes) comp_ctx->llvm_passes = option->llvm_passes; + if (option->builtin_intrinsics) + comp_ctx->builtin_intrinsics = option->builtin_intrinsics; + comp_ctx->opt_level = option->opt_level; comp_ctx->size_level = option->size_level; diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index d8808a202..03994b6c0 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -418,6 +418,7 @@ typedef struct AOTCompContext { const char *stack_usage_file; char stack_usage_temp_file[64]; const char *llvm_passes; + const char *builtin_intrinsics; } AOTCompContext; enum { @@ -457,6 +458,7 @@ typedef struct AOTCompOption { uint32 custom_sections_count; const char *stack_usage_file; const char *llvm_passes; + const char *builtin_intrinsics; } AOTCompOption, *aot_comp_option_t; bool diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h index 99b27577f..09765ad7e 100644 --- a/core/iwasm/include/aot_export.h +++ b/core/iwasm/include/aot_export.h @@ -68,6 +68,7 @@ typedef struct AOTCompOption { uint32_t custom_sections_count; const char *stack_usage_file; const char *llvm_passes; + const char *builtin_intrinsics; } AOTCompOption, *aot_comp_option_t; bool diff --git a/doc/xip.md b/doc/xip.md index 9e9d1699b..a76c7615c 100644 --- a/doc/xip.md +++ b/doc/xip.md @@ -16,3 +16,116 @@ Note: --xip is a short option for --enable-indirect-mode --disable-llvm-intrinsi ## Known issues There may be some relocations to the ".rodata" like sections which require to patch the AOT code. More work will be done to resolve it in the future. + +## Tuning the XIP intrinsic functions + +WAMR provides a default mapping table for some targets, but it may not be the best one for your target. And it doesn't cover all the supported targets. + +So, wamrc provides the option `--enable-builtin-intrinsics=` to make it possible to tune the intrinsic functions for your target. + +Firstly, you should understand why we don't use the LLVM intrinsic functions directly. The reason is that the LLVM intrinsic functions can't map to the native instructions directly, e.g. the LLVM intrinsic function `i32.div_s` can't map to the native instruction if the target doesn't support the division instruction, it will be translated to a function call to the runtime function from libgcc/compiler-rt. This will cause the AOT code to have the relocations to the libgcc/compiler-rt, which is not acceptable for the XIP feature. + +So, we need to replace the LLVM intrinsic functions with the runtime self implemented functions, which can be called through the function pointer table (--enable-indirect-mode) and don't have the relocations to the libgcc/compiler-rt (--disable-llvm-intrinsics). + +Available intrinsic functions for tuning: + +| LLVM intrinsic function | Explanation | +| --- | --- | +| llvm.experimental.constrained.fadd.f32 | float32 add | +| llvm.experimental.constrained.fadd.f64 | float64 add | +| llvm.experimental.constrained.fsub.f32 | float32 sub | +| llvm.experimental.constrained.fsub.f64 | float64 sub | +| llvm.experimental.constrained.fmul.f32 | float32 mul | +| llvm.experimental.constrained.fmul.f64 | float64 mul | +| llvm.experimental.constrained.fdiv.f32 | float32 div | +| llvm.experimental.constrained.fdiv.f64 | float64 div | +| llvm.fabs.f32 | float32 abs | +| llvm.fabs.f64 | float64 abs | +| llvm.ceil.f32 | float32 ceil | +| llvm.ceil.f64 | float64 ceil | +| llvm.floor.f32 | float32 floor | +| llvm.floor.f64 | float64 floor | +| llvm.trunc.f32 | float32 trunc | +| llvm.trunc.f64 | float64 trunc | +| llvm.rint.f32 | float32 rint | +| llvm.rint.f64 | float64 rint | +| llvm.sqrt.f32 | float32 sqrt | +| llvm.sqrt.f64 | float64 sqrt | +| llvm.copysign.f32 | float32 copysign | +| llvm.copysign.f64 | float64 copysign | +| llvm.minnum.f32 | float32 minnum | +| llvm.minnum.f64 | float64 minnum | +| llvm.maxnum.f32 | float32 maxnum | +| llvm.maxnum.f64 | float64 maxnum | +| llvm.ctlz.i32 | int32 count leading zeros | +| llvm.ctlz.i64 | int64 count leading zeros | +| llvm.cttz.i32 | int32 count trailing zeros | +| llvm.cttz.i64 | int64 count trailing zeros | +| llvm.ctpop.i32 | int32 count population | +| llvm.ctpop.i64 | int64 count population | +| f64_convert_i32_s | int32 to float64 | +| f64_convert_i32_u | uint32 to float64 | +| f32_convert_i32_s | int32 to float32 | +| f32_convert_i32_u | uint32 to float32 | +| f64_convert_i64_s | int64 to float64 | +| f64_convert_i64_u | uint64 to float64 | +| f32_convert_i64_s | int64 to float32 | +| f32_convert_i64_u | uint64 to float32 | +| i32_trunc_f32_s | float32 to int32 | +| i32_trunc_f32_u | float32 to uint32 | +| i32_trunc_f64_s | float64 to int32 | +| i32_trunc_f64_u | float64 to uint32 | +| i64_trunc_f64_s | float64 to int64 | +| i64_trunc_f64_u | float64 to uint64 | +| i64_trunc_f32_s | float32 to int64 | +| i64_trunc_f32_u | float32 to uint64 | +| f32_demote_f64 | float64 to float32 | +| f64_promote_f32 | float32 to float64 | +| f32_cmp | float32 compare | +| f64_cmp | float64 compare | +| i64.div_s | int64 div | +| i64.div_u | uint64 div | +| i32.div_s | int32 div | +| i32.div_u | uint32 div | +| i64.rem_s | int64 rem | +| i64.rem_u | uint64 rem | +| i32.rem_s | int32 rem | +| i32.rem_u | uint32 rem | +| i64.or | int64 or | +| i64.and | int64 and | +| i32.const | emit i32 const into constant table | +| i64.const | emit i64 const into constant table | +| f32.const | emit f32 const into constant table | +| f64.const | emit f64 const into constant table | + +And also provide combined intrinsic functions to simplify the tuning: + +* all: all the above intrinsic functions +* i32.common: i32.div_s, i32.div_u, i32.rem_s, i32.rem_u +* i64.common: i64.div_s, i64.div_u, i64.rem_s, i64.rem_u, i64.or, i64.and +* f32.common: f32_cmp, llvm.experimental.constrained.fadd.f32, llvm.experimental.constrained.fsub.f32, llvm.experimental.constrained.fmul.f32, llvm.experimental.constrained.fdiv.f32, llvm.fabs.f32, llvm.ceil.f32, llvm.floor.f32, llvm.trunc.f32, llvm.rint.f32, llvm.sqrt.f32, llvm.copysign.f32, llvm.minnum.f32, llvm.maxnum.f32 +* f64.common: f32_demote_f64, f64_promote_f32, f64_cmp, llvm.experimental.constrained.fadd.f64, llvm.experimental.constrained.fsub.f64, llvm.experimental.constrained.fmul.f64, llvm.experimental.constrained.fdiv.f64, llvm.fabs.f64, llvm.ceil.f64, llvm.floor.f64, llvm.trunc.f64, llvm.rint.f64, llvm.sqrt.f64, llvm.copysign.f64, llvm.minnum.f64, llvm.maxnum.f64 +* f32xi32: i32_trunc_f32_s, i32_trunc_f32_u, f32_convert_i32_s, f32_convert_i32_u +* f64xi32: i32_trunc_f64_s, i32_trunc_f64_u, f64_convert_i32_s, f64_convert_i32_u +* f32xi64: i64_trunc_f32_s, i64_trunc_f32_u, f32_convert_i64_s, f32_convert_i64_u +* f64xi64: i64_trunc_f64_s, i64_trunc_f64_u, f64_convert_i64_s, f64_convert_i64_u +* constop: i32.const, i64.const, f32.const, f64.const +* fpxint: f32xi32, f64xi32, f32xi64, f64xi64 +* fp.common: f32.common, f64.common + + +### Example + +For ARM Cortex-M55, since it has double precision floating point unit, so it can support f32/f64 operations. But as a 32-bit MCU, it can only support 32-bit integer operations. So we can use the following command to generate the XIP binary: + +``` +wamrc --target=thumbv8m.main --cpu=cortex-m55 --xip --enable-builtin-intrinsics=i64.common -o hello.aot hello.wasm +``` + +For ARM Cortex-M3, since it has no floating point unit, and it can only support 32-bit integer operations. So we can use the following command to generate the XIP binary: + +``` +wamrc --target=thumbv7m --cpu=cortex-m3 --xip --enable-builtin-intrinsics=i64.common,fp.common,fpxint -o hello.aot hello.wasm +``` + +Other platforms can be tuned in the same way, which intrinsic should be enabled depends on the target platform's hardware capability. diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 47b381683..1d3cedf74 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -162,6 +162,12 @@ print_help() printf(" --xip A shorthand of --enalbe-indirect-mode --disable-llvm-intrinsics\n"); printf(" --enable-indirect-mode Enalbe call function through symbol table but not direct call\n"); printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n"); + printf(" --enable-builtin-intrinsics=\n"); + printf(" Enable the specified built-in intrinsics, it will override the default\n"); + printf(" settings. It only takes effect when --disable-llvm-intrinsics is set.\n"); + printf(" Available flags: all, i32.common, i64.common, f32.common, f64.common,\n"); + printf(" i32.clz, i32.ctz, etc, refer to doc/xip.md for full list\n"); + printf(" Use comma to separate, please refer to doc/xip.md for full list.\n"); printf(" --disable-llvm-lto Disable the LLVM link time optimization\n"); printf(" --enable-llvm-pgo Enable LLVM PGO (Profile-Guided Optimization)\n"); printf(" --enable-llvm-passes=\n"); @@ -443,6 +449,11 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--disable-llvm-intrinsics")) { option.disable_llvm_intrinsics = true; } + else if (!strncmp(argv[0], "--enable-builtin-intrinsics=", 28)) { + if (argv[0][28] == '\0') + PRINT_HELP_AND_EXIT(); + option.builtin_intrinsics = argv[0] + 28; + } else if (!strcmp(argv[0], "--disable-llvm-lto")) { option.disable_llvm_lto = true; } From a300b627d5ee31a29b8c760b2b0471557ba7867f Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 7 Jul 2023 16:12:00 +0900 Subject: [PATCH 016/123] nuttx: Add a kconfig for wasi-threads (#2343) nuttx apps counterpart: https://github.com/apache/nuttx-apps/pull/1823 --- product-mini/platforms/nuttx/wamr.mk | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index da5cdcc27..1844dc54b 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -265,6 +265,15 @@ else CFLAGS += -DWASM_ENABLE_THREAD_MGR=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_LIB_WASI_THREADS),y) +CFLAGS += -DWASM_ENABLE_LIB_WASI_THREADS=1 +CSRCS += lib_wasi_threads_wrapper.c +CSRCS += tid_allocator.c +VPATH += $(IWASM_ROOT)/libraries/lib-wasi-threads +else +CFLAGS += -DWASM_ENABLE_LIB_WASI_THREADS=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_LIB_PTHREAD),y) CFLAGS += -DWASM_ENABLE_LIB_PTHREAD=1 CSRCS += lib_pthread_wrapper.c From 7448a994ed9e2329bbd181381c7c9fda194e1ea0 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 7 Jul 2023 17:09:15 +0900 Subject: [PATCH 017/123] iwasm: Disable app heap by default if wasi is enabled (#2346) It's rare to require app heap with wasi and sometimes harmful in some cases: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2275 --- product-mini/platforms/posix/main.c | 7 ++++++- product-mini/platforms/windows/main.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index fec8ec661..45214243c 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -465,7 +465,12 @@ main(int argc, char *argv[]) const char *func_name = NULL; uint8 *wasm_file_buf = NULL; uint32 wasm_file_size; - uint32 stack_size = 64 * 1024, heap_size = 16 * 1024; + uint32 stack_size = 64 * 1024; +#if WASM_ENABLE_LIBC_WASI != 0 + uint32 heap_size = 0; +#else + uint32 heap_size = 16 * 1024; +#endif #if WASM_ENABLE_FAST_JIT != 0 uint32 jit_code_cache_size = FAST_JIT_DEFAULT_CODE_CACHE_SIZE; #endif diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 26fa7dcc9..b7cf81433 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -243,7 +243,12 @@ main(int argc, char *argv[]) const char *func_name = NULL; uint8 *wasm_file_buf = NULL; uint32 wasm_file_size; - uint32 stack_size = 64 * 1024, heap_size = 16 * 1024; + uint32 stack_size = 64 * 1024; +#if WASM_ENABLE_LIBC_WASI != 0 + uint32 heap_size = 0; +#else + uint32 heap_size = 16 * 1024; +#endif #if WASM_ENABLE_JIT != 0 uint32 llvm_jit_size_level = 3; uint32 llvm_jit_opt_level = 3; From 81f0371f63ecfd1c3a91e13b086c546f5c67ebd2 Mon Sep 17 00:00:00 2001 From: Bananymous <68776844+Bananymous@users.noreply.github.com> Date: Tue, 11 Jul 2023 09:41:12 +0300 Subject: [PATCH 018/123] Fix typo in zephyr's Dockerfile.old (#2354) Dockerfile had command 'pip install --no-cache-doir' which caused the image build to fail. Fix this to correctly say '--no-cache-dir'. --- product-mini/platforms/zephyr/simple/Dockerfile.old | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product-mini/platforms/zephyr/simple/Dockerfile.old b/product-mini/platforms/zephyr/simple/Dockerfile.old index 633f3ea6c..e223f315a 100644 --- a/product-mini/platforms/zephyr/simple/Dockerfile.old +++ b/product-mini/platforms/zephyr/simple/Dockerfile.old @@ -35,7 +35,7 @@ WORKDIR /root/esp RUN git clone https://github.com/espressif/esp-idf.git WORKDIR /root/esp/esp-idf RUN git checkout v4.0 \ - && pip install --no-cache-doir virtualenv==16.7.12 \ + && pip install --no-cache-dir virtualenv==16.7.12 \ && git submodule update --init --recursive \ && ./install.sh esp32 esp32c3 From fbcf8c2c60b32ade99881a0d42c93c13b6911c9c Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Tue, 18 Jul 2023 16:06:21 +0800 Subject: [PATCH 019/123] Fix some static scan issues (#2362) --- core/iwasm/interpreter/wasm_loader.c | 9 +++++---- core/iwasm/interpreter/wasm_runtime.c | 4 ++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 1ce4aab0a..f1a71a8ab 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -7014,6 +7014,7 @@ static bool copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, char *error_buf, uint32 error_buf_size) { + bool ret = false; int16 *frame_offset = NULL; uint8 *cells = NULL, cell; int16 *src_offsets = NULL; @@ -7084,13 +7085,13 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, if (is_if_block) PUSH_OFFSET_TYPE(VALUE_TYPE_I32); + ret = true; + +fail: /* Free the emit data */ wasm_runtime_free(emit_data); - return true; - -fail: - return false; + return ret; } #endif diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 5b441dc88..00f0cf668 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1104,10 +1104,14 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst, goto fail; } +#if WASM_ENABLE_LIBC_WASI != 0 if (initialize_func && !wasm_call_function(exec_env, initialize_func, 0, NULL)) { goto fail; } +#else + (void)initialize_func; +#endif if (post_inst_func && !wasm_call_function(exec_env, post_inst_func, 0, NULL)) { From 57abdfdb5c19dab7c2f2a126082910f65ffc7af0 Mon Sep 17 00:00:00 2001 From: Cengizhan Pasaoglu Date: Wed, 19 Jul 2023 12:58:52 +0300 Subject: [PATCH 020/123] Fix typo (dwarf) in the codebase (#2367) In the codebase, the struct and functions were written without "f" for dwarf. --- core/iwasm/compilation/aot.h | 4 +-- .../compilation/debug/dwarf_extractor.cpp | 32 +++++++++---------- .../iwasm/compilation/debug/dwarf_extractor.h | 4 +-- core/iwasm/include/aot_export.h | 4 +-- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index 02b146cb3..088460636 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -43,7 +43,7 @@ typedef WASMType AOTFuncType; typedef WASMExport AOTExport; #if WASM_ENABLE_DEBUG_AOT != 0 -typedef void *dwar_extractor_handle_t; +typedef void *dwarf_extractor_handle_t; #endif typedef enum AOTIntCond { @@ -285,7 +285,7 @@ typedef struct AOTCompData { WASMModule *wasm_module; #if WASM_ENABLE_DEBUG_AOT != 0 - dwar_extractor_handle_t extractor; + dwarf_extractor_handle_t extractor; #endif } AOTCompData; diff --git a/core/iwasm/compilation/debug/dwarf_extractor.cpp b/core/iwasm/compilation/debug/dwarf_extractor.cpp index 160aadee0..99182f82f 100644 --- a/core/iwasm/compilation/debug/dwarf_extractor.cpp +++ b/core/iwasm/compilation/debug/dwarf_extractor.cpp @@ -28,25 +28,25 @@ using namespace lldb; -typedef struct dwar_extractor { +typedef struct dwarf_extractor { SBDebugger debugger; SBTarget target; SBModule module; -} dwar_extractor; +} dwarf_extractor; -#define TO_HANDLE(extractor) (dwar_extractor_handle_t)(extractor) +#define TO_HANDLE(extractor) (dwarf_extractor_handle_t)(extractor) -#define TO_EXTACTOR(handle) (dwar_extractor *)(handle) +#define TO_EXTACTOR(handle) (dwarf_extractor *)(handle) static bool is_debugger_initialized; -dwar_extractor_handle_t +dwarf_extractor_handle_t create_dwarf_extractor(AOTCompData *comp_data, char *file_name) { char *arch = NULL; char *platform = NULL; - dwar_extractor *extractor = NULL; + dwarf_extractor *extractor = NULL; //__attribute__((constructor)) may be better? if (!is_debugger_initialized) { @@ -61,7 +61,7 @@ create_dwarf_extractor(AOTCompData *comp_data, char *file_name) SBError error; SBFileSpec exe_file_spec(file_name, true); - if (!(extractor = new dwar_extractor())) { + if (!(extractor = new dwarf_extractor())) { LOG_ERROR("Create Dwarf Extractor error: failed to allocate memory"); goto fail3; } @@ -101,9 +101,9 @@ fail3: } void -destroy_dwarf_extractor(dwar_extractor_handle_t handle) +destroy_dwarf_extractor(dwarf_extractor_handle_t handle) { - dwar_extractor *extractor = TO_EXTACTOR(handle); + dwarf_extractor *extractor = TO_EXTACTOR(handle); if (!extractor) return; extractor->debugger.DeleteTarget(extractor->target); @@ -116,7 +116,7 @@ destroy_dwarf_extractor(dwar_extractor_handle_t handle) LLVMMetadataRef dwarf_gen_file_info(const AOTCompContext *comp_ctx) { - dwar_extractor *extractor; + dwarf_extractor *extractor; int units_number; LLVMMetadataRef file_info = NULL; const char *file_name; @@ -193,7 +193,7 @@ dwarf_gen_mock_vm_info(AOTCompContext *comp_ctx) LLVMMetadataRef dwarf_gen_comp_unit_info(const AOTCompContext *comp_ctx) { - dwar_extractor *extractor; + dwarf_extractor *extractor; int units_number; LLVMMetadataRef comp_unit = NULL; @@ -292,7 +292,7 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx, SBTypeList function_args = function.GetType().GetFunctionArgumentTypes(); SBType return_type = function.GetType().GetFunctionReturnType(); const size_t num_function_args = function_args.GetSize(); - dwar_extractor *extractor; + dwarf_extractor *extractor; if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) return NULL; @@ -393,7 +393,7 @@ dwarf_gen_func_info(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx) { LLVMMetadataRef func_info = NULL; - dwar_extractor *extractor; + dwarf_extractor *extractor; uint64_t vm_offset; AOTFunc *func = func_ctx->aot_func; @@ -423,7 +423,7 @@ dwarf_get_func_name(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx, char *name, int len) { LLVMMetadataRef func_info = NULL; - dwar_extractor *extractor; + dwarf_extractor *extractor; uint64_t vm_offset; AOTFunc *func = func_ctx->aot_func; @@ -454,7 +454,7 @@ dwarf_gen_location(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx, uint64_t vm_offset) { LLVMMetadataRef location_info = NULL; - dwar_extractor *extractor; + dwarf_extractor *extractor; AOTFunc *func = func_ctx->aot_func; if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) @@ -493,7 +493,7 @@ dwarf_gen_func_ret_location(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx) { LLVMMetadataRef func_info = NULL; - dwar_extractor *extractor; + dwarf_extractor *extractor; uint64_t vm_offset; AOTFunc *func = func_ctx->aot_func; LLVMMetadataRef location_info = NULL; diff --git a/core/iwasm/compilation/debug/dwarf_extractor.h b/core/iwasm/compilation/debug/dwarf_extractor.h index c48e8f5c0..0bacb97fa 100644 --- a/core/iwasm/compilation/debug/dwarf_extractor.h +++ b/core/iwasm/compilation/debug/dwarf_extractor.h @@ -18,7 +18,7 @@ typedef unsigned int LLDBLangType; struct AOTCompData; typedef struct AOTCompData *aot_comp_data_t; -typedef void *dwar_extractor_handle_t; +typedef void *dwarf_extractor_handle_t; struct AOTCompContext; typedef struct AOTCompContext AOTCompContext; @@ -26,7 +26,7 @@ typedef struct AOTCompContext AOTCompContext; struct AOTFuncContext; typedef struct AOTFuncContext AOTFuncContext; -dwar_extractor_handle_t +dwarf_extractor_handle_t create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name); LLVMMetadataRef diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h index 09765ad7e..ce8ae81fe 100644 --- a/core/iwasm/include/aot_export.h +++ b/core/iwasm/include/aot_export.h @@ -26,8 +26,8 @@ void aot_destroy_comp_data(aot_comp_data_t comp_data); #if WASM_ENABLE_DEBUG_AOT != 0 -typedef void *dwar_extractor_handle_t; -dwar_extractor_handle_t +typedef void *dwarf_extractor_handle_t; +dwarf_extractor_handle_t create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name); #endif From fbe072c0d34f1900a93931f963ff2c8276381367 Mon Sep 17 00:00:00 2001 From: dongsheng28849455 <68947925+dongsheng28849455@users.noreply.github.com> Date: Fri, 21 Jul 2023 07:54:13 +0800 Subject: [PATCH 021/123] Bring up WAMR on esp32-s3 device (#2348) esp32-s3's instruction memory and data memory can be accessed through mutual mirroring way, so we define a new feature named as WASM_MEM_DUAL_BUS_MIRROR. --- core/config.h | 11 +++ core/iwasm/aot/aot_loader.c | 12 +++ core/iwasm/aot/arch/aot_reloc_xtensa.c | 10 ++- .../platform/include/platform_api_vmcore.h | 5 ++ core/shared/platform/nuttx/nuttx_platform.c | 81 ++++++++++++++++++- product-mini/platforms/nuttx/wamr.mk | 6 ++ 6 files changed, 122 insertions(+), 3 deletions(-) diff --git a/core/config.h b/core/config.h index f33290f0d..b6198811e 100644 --- a/core/config.h +++ b/core/config.h @@ -461,4 +461,15 @@ #define WASM_CONFIGURABLE_BOUNDS_CHECKS 0 #endif +/* Some chip cannot support external ram with rwx attr at the same time, + it has to map it into 2 spaces of idbus and dbus, code in dbus can be + read/written and read/executed in ibus. so there are 2 steps to execute + the code, first, copy&do relocaiton in dbus space, and second execute + it in ibus space, since in the 2 spaces the contents are the same, + so we call it bus mirror. + */ +#ifndef WASM_MEM_DUAL_BUS_MIRROR +#define WASM_MEM_DUAL_BUS_MIRROR 0 +#endif + #endif /* end of _CONFIG_H_ */ diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 2f4dcd31a..50e36f9ee 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -3013,6 +3013,9 @@ create_sections(AOTModule *module, const uint8 *buf, uint32 size, uint32 section_size; uint64 total_size; uint8 *aot_text; +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + uint8 *mirrored_text; +#endif if (!resolve_execute_mode(buf, size, &is_indirect_mode, error_buf, error_buf_size)) { @@ -3071,8 +3074,17 @@ create_sections(AOTModule *module, const uint8 *buf, uint32 size, bh_assert((uintptr_t)aot_text < INT32_MAX); #endif #endif + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + mirrored_text = os_get_dbus_mirror(aot_text); + bh_assert(mirrored_text != NULL); + bh_memcpy_s(mirrored_text, (uint32)total_size, + section->section_body, (uint32)section_size); + os_dcache_flush(); +#else bh_memcpy_s(aot_text, (uint32)total_size, section->section_body, (uint32)section_size); +#endif section->section_body = aot_text; destroy_aot_text = true; diff --git a/core/iwasm/aot/arch/aot_reloc_xtensa.c b/core/iwasm/aot/arch/aot_reloc_xtensa.c index 3327c396f..6ca6a0859 100644 --- a/core/iwasm/aot/arch/aot_reloc_xtensa.c +++ b/core/iwasm/aot/arch/aot_reloc_xtensa.c @@ -207,6 +207,10 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, case R_XTENSA_32: { uint8 *insn_addr = target_section_addr + reloc_offset; +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + insn_addr = os_get_dbus_mirror((void *)insn_addr); + bh_assert(insn_addr != NULL); +#endif int32 initial_addend; /* (S + A) */ if ((intptr_t)insn_addr & 3) { @@ -265,6 +269,11 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, return false; } +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + insn_addr = os_get_dbus_mirror((void *)insn_addr); + bh_assert(insn_addr != NULL); + l32r_insn = (l32r_insn_t *)insn_addr; +#endif imm16 = (int16)(relative_offset >> 2); /* write back the imm16 to the l32r instruction */ @@ -285,7 +294,6 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, #if __GNUC__ >= 9 #pragma GCC diagnostic pop #endif - break; } diff --git a/core/shared/platform/include/platform_api_vmcore.h b/core/shared/platform/include/platform_api_vmcore.h index c2f03c9e5..15fc1d387 100644 --- a/core/shared/platform/include/platform_api_vmcore.h +++ b/core/shared/platform/include/platform_api_vmcore.h @@ -129,6 +129,11 @@ os_munmap(void *addr, size_t size); int os_mprotect(void *addr, size_t size, int prot); +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) +void * +os_get_dbus_mirror(void *ibus); +#endif + /** * Flush cpu data cache, in some CPUs, after applying relocation to the * AOT code, the code may haven't been written back to the cpu data cache, diff --git a/core/shared/platform/nuttx/nuttx_platform.c b/core/shared/platform/nuttx/nuttx_platform.c index 9cb123e01..0bd1f6808 100644 --- a/core/shared/platform/nuttx/nuttx_platform.c +++ b/core/shared/platform/nuttx/nuttx_platform.c @@ -10,6 +10,46 @@ #include #endif +#if defined(CONFIG_ARCH_CHIP_ESP32S3) +/* + * TODO: Move these methods below the operating system level + */ +#define MEM_DUAL_BUS_OFFSET (0x42000000 - 0x3C000000) +#define IRAM0_CACHE_ADDRESS_LOW 0x42000000 +#define IRAM0_CACHE_ADDRESS_HIGH 0x44000000 +#define IRAM_ATTR locate_data(".iram1") + +#define in_ibus_ext(addr) \ + (((uint32)addr >= IRAM0_CACHE_ADDRESS_LOW) \ + && ((uint32)addr < IRAM0_CACHE_ADDRESS_HIGH)) +void IRAM_ATTR +bus_sync(void) +{ + extern void cache_writeback_all(void); + extern uint32_t Cache_Disable_ICache(void); + extern void Cache_Enable_ICache(uint32_t autoload); + + irqstate_t flags; + uint32_t preload; + + flags = enter_critical_section(); + + cache_writeback_all(); + preload = Cache_Disable_ICache(); + Cache_Enable_ICache(preload); + + leave_critical_section(flags); +} +#else +#define MEM_DUAL_BUS_OFFSET (0) +#define IRAM0_CACHE_ADDRESS_LOW (0) +#define IRAM0_CACHE_ADDRESS_HIGH (0) +#define in_ibus_ext(addr) (0) +static void +bus_sync(void) +{} +#endif + int bh_platform_init() { @@ -47,6 +87,10 @@ os_dumps_proc_mem_info(char *out, unsigned int size) void * os_mmap(void *hint, size_t size, int prot, int flags) { +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + void *i_addr, *d_addr; +#endif + #if defined(CONFIG_ARCH_USE_TEXT_HEAP) if ((prot & MMAP_PROT_EXEC) != 0) { return up_textheap_memalign(sizeof(void *), size); @@ -55,6 +99,17 @@ os_mmap(void *hint, size_t size, int prot, int flags) if ((uint64)size >= UINT32_MAX) return NULL; + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + if ((prot & MMAP_PROT_EXEC) != 0) { + d_addr = malloc((uint32)size); + if (d_addr == NULL) { + return NULL; + } + i_addr = (void *)((uint8 *)d_addr + MEM_DUAL_BUS_OFFSET); + return in_ibus_ext(i_addr) ? i_addr : d_addr; + } +#endif return malloc((uint32)size); } @@ -67,7 +122,14 @@ os_munmap(void *addr, size_t size) return; } #endif - return free(addr); + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + if (in_ibus_ext(addr)) { + free((void *)((uint8 *)addr - MEM_DUAL_BUS_OFFSET)); + return; + } +#endif + free(addr); } int @@ -78,7 +140,22 @@ os_mprotect(void *addr, size_t size, int prot) void os_dcache_flush() -{} +{ + bus_sync(); +} + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) +void * +os_get_dbus_mirror(void *ibus) +{ + if (in_ibus_ext(ibus)) { + return (void *)((uint8 *)ibus - MEM_DUAL_BUS_OFFSET); + } + else { + return ibus; + } +} +#endif /* If AT_FDCWD is provided, maybe we have openat family */ #if !defined(AT_FDCWD) diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 1844dc54b..2a0cec58c 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -141,6 +141,12 @@ else CFLAGS += -DWASM_ENABLE_WORD_ALIGN_READ=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_MEM_DUAL_BUS_MIRROR),y) +CFLAGS += -DWASM_MEM_DUAL_BUS_MIRROR=1 +else +CFLAGS += -DWASM_MEM_DUAL_BUS_MIRROR=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_FAST), y) CFLAGS += -DWASM_ENABLE_FAST_INTERP=1 CFLAGS += -DWASM_ENABLE_INTERP=1 From 0f4edf97359d8005fc2eb092a4fe908ffddcfd04 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Fri, 21 Jul 2023 01:27:09 +0100 Subject: [PATCH 022/123] Implement suspend flags as atomic variable (#2361) We have observed a significant performance degradation after merging https://github.com/bytecodealliance/wasm-micro-runtime/pull/1991 Instead of protecting suspend flags with a mutex, we implement the flags as atomic variable and only use mutex when atomics are not available on a given platform. --- core/iwasm/common/wasm_exec_env.h | 12 +-- core/iwasm/common/wasm_suspend_flags.h | 74 +++++++++++++++++++ core/iwasm/interpreter/wasm_interp_classic.c | 45 +++++++---- core/iwasm/interpreter/wasm_interp_fast.c | 23 +++--- .../lib-pthread/lib_pthread_wrapper.c | 3 +- .../libraries/thread-mgr/thread_manager.c | 22 ++++-- core/shared/utils/bh_platform.h | 1 + .../src => shared/utils}/gnuc.h | 0 8 files changed, 135 insertions(+), 45 deletions(-) create mode 100644 core/iwasm/common/wasm_suspend_flags.h rename core/{iwasm/libraries/libc-wasi/sandboxed-system-primitives/src => shared/utils}/gnuc.h (100%) diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index 29b28a159..bf9892080 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -7,6 +7,7 @@ #define _WASM_EXEC_ENV_H #include "bh_assert.h" +#include "wasm_suspend_flags.h" #if WASM_ENABLE_INTERP != 0 #include "../interpreter/wasm.h" #endif @@ -57,15 +58,8 @@ typedef struct WASMExecEnv { exception. */ uint8 *native_stack_boundary; - /* Used to terminate or suspend current thread - bit 0: need to terminate - bit 1: need to suspend - bit 2: need to go into breakpoint - bit 3: return from pthread_exit */ - union { - uint32 flags; - uintptr_t __padding__; - } suspend_flags; + /* Used to terminate or suspend current thread */ + WASMSuspendFlags suspend_flags; /* Auxiliary stack boundary */ union { diff --git a/core/iwasm/common/wasm_suspend_flags.h b/core/iwasm/common/wasm_suspend_flags.h new file mode 100644 index 000000000..0558eaf6b --- /dev/null +++ b/core/iwasm/common/wasm_suspend_flags.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WASM_SUSPEND_FLAGS_H +#define _WASM_SUSPEND_FLAGS_H + +#include "bh_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Need to terminate */ +#define WASM_SUSPEND_FLAG_TERMINATE 0x1 +/* Need to suspend */ +#define WASM_SUSPEND_FLAG_SUSPEND 0x2 +/* Need to go into breakpoint */ +#define WASM_SUSPEND_FLAG_BREAKPOINT 0x4 +/* Return from pthread_exit */ +#define WASM_SUSPEND_FLAG_EXIT 0x8 + +typedef union WASMSuspendFlags { + uint32 flags; + uintptr_t __padding__; +} WASMSuspendFlags; + +#if defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4, 7) +#define CLANG_GCC_HAS_ATOMIC_BUILTIN +#endif +#elif defined(__clang__) +#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 0) +#define CLANG_GCC_HAS_ATOMIC_BUILTIN +#endif +#endif + +#if defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) +#define WASM_SUSPEND_FLAGS_IS_ATOMIC 1 +#define WASM_SUSPEND_FLAGS_GET(s_flags) \ + __atomic_load_n(&s_flags.flags, __ATOMIC_SEQ_CST) +#define WASM_SUSPEND_FLAGS_FETCH_OR(s_flags, val) \ + __atomic_fetch_or(&s_flags.flags, val, __ATOMIC_SEQ_CST) +#define WASM_SUSPEND_FLAGS_FETCH_AND(s_flags, val) \ + __atomic_fetch_and(&s_flags.flags, val, __ATOMIC_SEQ_CST) +#else /* else of defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) */ +#define WASM_SUSPEND_FLAGS_GET(s_flags) (s_flags.flags) +#define WASM_SUSPEND_FLAGS_FETCH_OR(s_flags, val) (s_flags.flags |= val) +#define WASM_SUSPEND_FLAGS_FETCH_AND(s_flags, val) (s_flags.flags &= val) + +/* The flag can be defined by the user if the platform + supports atomic access to uint32 aligned memory. */ +#ifdef WASM_UINT32_IS_ATOMIC +#define WASM_SUSPEND_FLAGS_IS_ATOMIC 1 +#else /* else of WASM_UINT32_IS_ATOMIC */ +#define WASM_SUSPEND_FLAGS_IS_ATOMIC 0 +#endif /* WASM_UINT32_IS_ATOMIC */ + +#endif + +#if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0 +#define WASM_SUSPEND_FLAGS_LOCK(lock) (void)0 +#define WASM_SUSPEND_FLAGS_UNLOCK(lock) (void)0 +#else /* else of WASM_SUSPEND_FLAGS_IS_ATOMIC */ +#define WASM_SUSPEND_FLAGS_LOCK(lock) os_mutex_lock(&lock) +#define WASM_SUSPEND_FLAGS_UNLOCK(lock) os_mutex_unlock(&lock); +#endif /* WASM_SUSPEND_FLAGS_IS_ATOMIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of _WASM_SUSPEND_FLAGS_H */ \ No newline at end of file diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 69037b59c..55fca2921 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1062,21 +1062,33 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, os_mutex_unlock(&exec_env->wait_lock); \ } while (0) #else -#define CHECK_SUSPEND_FLAGS() \ - do { \ - os_mutex_lock(&exec_env->wait_lock); \ - if (exec_env->suspend_flags.flags != 0) { \ - if (exec_env->suspend_flags.flags & 0x01) { \ - /* terminate current thread */ \ - os_mutex_unlock(&exec_env->wait_lock); \ - return; \ - } \ - while (exec_env->suspend_flags.flags & 0x02) { \ - /* suspend current thread */ \ - os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \ - } \ - } \ - os_mutex_unlock(&exec_env->wait_lock); \ +#if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0 +/* The lock is only needed when the suspend_flags is atomic; otherwise + the lock is already taken at the time when SUSPENSION_LOCK() is called. */ +#define SUSPENSION_LOCK() os_mutex_lock(&exec_env->wait_lock); +#define SUSPENSION_UNLOCK() os_mutex_unlock(&exec_env->wait_lock); +#else +#define SUSPENSION_LOCK() +#define SUSPENSION_UNLOCK() +#endif + +#define CHECK_SUSPEND_FLAGS() \ + do { \ + WASM_SUSPEND_FLAGS_LOCK(exec_env->wait_lock); \ + if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \ + & WASM_SUSPEND_FLAG_TERMINATE) { \ + /* terminate current thread */ \ + WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \ + return; \ + } \ + while (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \ + & WASM_SUSPEND_FLAG_SUSPEND) { \ + /* suspend current thread */ \ + SUSPENSION_LOCK() \ + os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \ + SUSPENSION_UNLOCK() \ + } \ + WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \ } while (0) #endif /* WASM_ENABLE_DEBUG_INTERP */ #endif /* WASM_ENABLE_THREAD_MGR */ @@ -3783,7 +3795,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(DEBUG_OP_BREAK) { wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP); - exec_env->suspend_flags.flags |= 2; + WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags, + WASM_SUSPEND_FLAG_SUSPEND); frame_ip--; SYNC_ALL_TO_FRAME(); CHECK_SUSPEND_FLAGS(); diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 40a7d38c8..070fcdbee 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1065,18 +1065,17 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, #endif #if WASM_ENABLE_THREAD_MGR != 0 -#define CHECK_SUSPEND_FLAGS() \ - do { \ - os_mutex_lock(&exec_env->wait_lock); \ - if (exec_env->suspend_flags.flags != 0) { \ - if (exec_env->suspend_flags.flags & 0x01) { \ - /* terminate current thread */ \ - os_mutex_unlock(&exec_env->wait_lock); \ - return; \ - } \ - /* TODO: support suspend and breakpoint */ \ - } \ - os_mutex_unlock(&exec_env->wait_lock); \ +#define CHECK_SUSPEND_FLAGS() \ + do { \ + WASM_SUSPEND_FLAGS_LOCK(exec_env->wait_lock); \ + if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \ + & WASM_SUSPEND_FLAG_TERMINATE) { \ + /* terminate current thread */ \ + WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \ + return; \ + } \ + /* TODO: support suspend and breakpoint */ \ + WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \ } while (0) #endif diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index 206479c2a..8876d51b4 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -531,7 +531,8 @@ pthread_start_routine(void *arg) else { info_node->u.ret = (void *)(uintptr_t)argv[0]; #ifdef OS_ENABLE_HW_BOUND_CHECK - if (exec_env->suspend_flags.flags & 0x08) + if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) + & WASM_SUSPEND_FLAG_EXIT) /* argv[0] isn't set after longjmp(1) to invoke_native_with_hw_bound_check */ info_node->u.ret = exec_env->thread_ret_value; diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 9303eb3f5..fc44652e5 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -606,7 +606,8 @@ thread_manager_start_routine(void *arg) #ifdef OS_ENABLE_HW_BOUND_CHECK os_mutex_lock(&exec_env->wait_lock); - if (exec_env->suspend_flags.flags & 0x08) + if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) + & WASM_SUSPEND_FLAG_EXIT) ret = exec_env->thread_ret_value; os_mutex_unlock(&exec_env->wait_lock); #endif @@ -993,7 +994,9 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) if (exec_env->jmpbuf_stack_top) { /* Store the return value in exec_env */ exec_env->thread_ret_value = retval; - exec_env->suspend_flags.flags |= 0x08; + + WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags, + WASM_SUSPEND_FLAG_EXIT); #ifndef BH_PLATFORM_WINDOWS /* Pop all jmpbuf_node except the last one */ @@ -1055,7 +1058,8 @@ set_thread_cancel_flags(WASMExecEnv *exec_env) #if WASM_ENABLE_DEBUG_INTERP != 0 wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM); #endif - exec_env->suspend_flags.flags |= 0x01; + WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags, + WASM_SUSPEND_FLAG_TERMINATE); os_mutex_unlock(&exec_env->wait_lock); } @@ -1178,7 +1182,8 @@ void wasm_cluster_suspend_thread(WASMExecEnv *exec_env) { /* Set the suspend flag */ - exec_env->suspend_flags.flags |= 0x02; + WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags, + WASM_SUSPEND_FLAG_SUSPEND); } static void @@ -1214,7 +1219,8 @@ wasm_cluster_suspend_all_except_self(WASMCluster *cluster, void wasm_cluster_resume_thread(WASMExecEnv *exec_env) { - exec_env->suspend_flags.flags &= ~0x02; + WASM_SUSPEND_FLAGS_FETCH_AND(exec_env->suspend_flags, + ~WASM_SUSPEND_FLAG_SUSPEND); os_cond_signal(&exec_env->wait_cond); } @@ -1343,8 +1349,10 @@ bool wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env) { os_mutex_lock(&exec_env->wait_lock); - bool is_thread_terminated = - (exec_env->suspend_flags.flags & 0x01) ? true : false; + bool is_thread_terminated = (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) + & WASM_SUSPEND_FLAG_TERMINATE) + ? true + : false; os_mutex_unlock(&exec_env->wait_lock); return is_thread_terminated; diff --git a/core/shared/utils/bh_platform.h b/core/shared/utils/bh_platform.h index 86aef839d..9821d710d 100644 --- a/core/shared/utils/bh_platform.h +++ b/core/shared/utils/bh_platform.h @@ -16,6 +16,7 @@ #include "bh_log.h" #include "bh_queue.h" #include "bh_vector.h" +#include "gnuc.h" #include "runtime_timer.h" /** diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h b/core/shared/utils/gnuc.h similarity index 100% rename from core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h rename to core/shared/utils/gnuc.h From 24c6c6977ba1d7fcbcb09c4b3fcfaea2ed0527fe Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 24 Jul 2023 15:15:48 +0800 Subject: [PATCH 023/123] Fix llvm jit failed to lookup aot_stack_sizes symbol issue (#2384) LVM JIT failed to lookup symbol "aot_stack_sizes" as it is an internal symbol, change to lookup "aot_stack_sizes_alias" instead. Reported in #2372. --- core/iwasm/compilation/aot_compiler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 94a378c46..e99e2ae72 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -2696,7 +2696,7 @@ aot_compile_wasm(AOTCompContext *comp_ctx) if (comp_ctx->stack_sizes != NULL) { LLVMOrcJITTargetAddress addr; if ((err = LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &addr, - aot_stack_sizes_name))) { + aot_stack_sizes_alias_name))) { aot_handle_llvm_errmsg("failed to look up stack_sizes", err); return false; } From 1cafa375680b6ea8b120e0d4d6006521d858ae2d Mon Sep 17 00:00:00 2001 From: Cengizhan Pasaoglu Date: Mon, 24 Jul 2023 12:43:13 +0300 Subject: [PATCH 024/123] Update Docker image for latest version of external libraries & tools (#2374) Devcontainer is too old to catch up the latest versions of dependencies. This PR updates the libraries & tools that WASM environment requires for Docker image. **Impediments:** - LLVM 16 can not be retrieved directly by using shell command as provided before. So we upgrade all tools manually as a workaround and just put LLVM issue URL as a comment in the script. **Improvements:** - Use `Debian 12 (Bookworm)` as a base image instead of `Ubuntu 20.04`. - `GCC9` upgraded to `GCC12`. - `LLVM14` upgraded to `LLVM16`. - `Clang10` upgraded to `Clang10`. - `Binaryen111` upgraded to `Binaryen114`. - `WASI-19` upgraded to `WASI-20` - `WABT-1.0.29` upgraded to `WABT-1.0.33` - `Bazelisk-1.12.0` upgraded to `Bazelisk-1.17.0` - `GithubCLI-2.20.2` upgraded to `GithubCLI-2.32.0` - `NodeJS-19.x` upgraded to `NodeJS-20.x` - `EMSDK-3.0.0` upgraded to `EMSDK-3.1.43` **Notes:** `Python 2.7` is removed due to no support anymore and not found in the repository. --- .devcontainer/Dockerfile | 78 ++++++++++++++++++++------------- .devcontainer/devcontainer.json | 23 +++++----- 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 2a8fcbcaf..1587a7ddc 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,20 +1,21 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp/.devcontainer/base.Dockerfile -# [Choice] Debian / Ubuntu version (use Debian 11/9, Ubuntu 18.04/21.04 on local arm64/Apple Silicon): debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 -ARG VARIANT=ubuntu-20.04 -FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-${VARIANT} +# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/cpp/.devcontainer/base.Dockerfile +# [Choice] Debian / Ubuntu version (use Debian 12/11/9, Ubuntu 18.04/21.04 on local arm64/Apple Silicon): debian-12, debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 +ARG VARIANT=debian-12 +FROM mcr.microsoft.com/vscode/devcontainers/cpp:${VARIANT} ARG DEBIAN_FRONTEND=noninteractive ENV TZ=Asian/Shanghai # hadolint ignore=DL3008 RUN apt-get update \ + && apt-get upgrade -y \ && apt-get install -y apt-transport-https apt-utils build-essential \ - ca-certificates ccache curl g++-multilib git gnupg \ - libgcc-9-dev lib32gcc-9-dev lsb-release \ - ninja-build ocaml ocamlbuild python2.7 \ + ca-certificates ccache cmake curl g++-multilib git gnupg \ + libgcc-12-dev lib32gcc-12-dev lsb-release \ + ninja-build ocaml ocamlbuild \ software-properties-common tree tzdata \ unzip valgrind vim wget zip --no-install-recommends \ && apt-get clean -y \ @@ -22,32 +23,32 @@ RUN apt-get update \ # # binaryen -ARG BINARYEN_VER=111 +ARG BINARYEN_VER=114 WORKDIR /opt RUN wget -c --progress=dot:giga https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VER}/binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \ && tar xf binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \ - && ln -sf /opt/binaryen-version_111 /opt/binaryen \ + && ln -sf /opt/binaryen-version_${BINARYEN_VER} /opt/binaryen \ && rm binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz # # CMAKE (https://apt.kitware.com/) SHELL ["/bin/bash", "-o", "pipefail", "-c"] # hadolint ignore=DL3008 -RUN wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg > /dev/null \ - && echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ bionic main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null \ - && apt-get update \ - && rm /usr/share/keyrings/kitware-archive-keyring.gpg \ - && apt-get install -y kitware-archive-keyring --no-install-recommends \ - && apt-get install -y cmake --no-install-recommends \ - && apt-get clean -y \ - && rm -rf /var/lib/apt/lists/* +ARG CMAKE_VER=3.27.0 +RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh \ + -q -O /tmp/cmake-install.sh \ + && chmod u+x /tmp/cmake-install.sh \ + && mkdir /opt/cmake-${CMAKE_VER} \ + && /tmp/cmake-install.sh --skip-license --prefix=/opt/cmake-${CMAKE_VER} \ + && rm /tmp/cmake-install.sh \ + && ln -s /opt/cmake-${CMAKE_VER}/bin/* /usr/local/bin # # install emsdk WORKDIR /opt RUN git clone https://github.com/emscripten-core/emsdk.git -ARG EMSDK_VER=3.0.0 +ARG EMSDK_VER=3.1.43 WORKDIR /opt/emsdk RUN git pull \ && ./emsdk install ${EMSDK_VER} \ @@ -56,7 +57,7 @@ RUN git pull \ # # install wasi-sdk -ARG WASI_SDK_VER=19 +ARG WASI_SDK_VER=20 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \ && tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \ && ln -sf /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \ @@ -64,7 +65,7 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases # #install wabt -ARG WABT_VER=1.0.29 +ARG WABT_VER=1.0.33 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt \ && tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \ && ln -sf /opt/wabt-${WABT_VER} /opt/wabt \ @@ -72,7 +73,7 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/dow # # install bazelisk -ARG BAZELISK_VER=1.12.0 +ARG BAZELISK_VER=1.17.0 RUN mkdir /opt/bazelisk \ && wget -c --progress=dot:giga https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk \ && chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \ @@ -80,16 +81,30 @@ RUN mkdir /opt/bazelisk \ # # install clang+llvm -ARG LLVM_VER=14 -RUN apt-get purge -y clang-10 llvm-10 && apt-get autoremove -y +ARG LLVM_VER=16 +RUN apt-get purge -y clang-14 llvm-14 && apt-get autoremove -y WORKDIR /etc/apt/apt.conf.d RUN touch 99verfiy-peer.conf \ && echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf WORKDIR /tmp -RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \ - && chmod a+x ./llvm.sh \ - && ./llvm.sh ${LLVM_VER} all +#RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \ +# && chmod a+x ./llvm.sh \ +# && ./llvm.sh ${LLVM_VER} all + +# Workaround due to https://github.com/llvm/llvm-project/issues/62475 +# hadolint ignore=DL3008 +RUN set -ex \ + && echo "deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-${LLVM_VER} main" > /etc/apt/sources.list.d/apt.llvm.org.list \ + && wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc \ + && apt-get update \ + && apt-get install -y \ + clang-${LLVM_VER} lldb-${LLVM_VER} lld-${LLVM_VER} clangd-${LLVM_VER} clang-tidy-${LLVM_VER} clang-format-${LLVM_VER} clang-tools-${LLVM_VER} \ + llvm-${LLVM_VER}-dev lld-${LLVM_VER} lldb-${LLVM_VER} llvm-${LLVM_VER}-tools libomp-${LLVM_VER}-dev libc++-${LLVM_VER}-dev libc++abi-${LLVM_VER}-dev \ + libclang-common-${LLVM_VER}-dev libclang-${LLVM_VER}-dev libclang-cpp${LLVM_VER}-dev libunwind-${LLVM_VER}-dev \ + libclang-rt-${LLVM_VER}-dev libpolly-${LLVM_VER}-dev --no-install-recommends \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* # # [Optional] @@ -105,18 +120,19 @@ RUN apt-get update \ # # Install required python packages # hadolint ignore=DL3013 -RUN python3 -m pip install --no-cache-dir --upgrade pip \ - && pip3 install --no-cache-dir black nose pycparser pylint +RUN python3 -m pip install --no-cache-dir --break-system-packages --upgrade pip \ + && pip3 install --no-cache-dir --break-system-packages black nose pycparser pylint # # Install github-cli. It doens't work as a feature of devcontainer.json +ARG GH_CLI_VER=2.32.0 WORKDIR /tmp -RUN wget -q https://github.com/cli/cli/releases/download/v2.20.2/gh_2.20.2_linux_amd64.deb \ - && dpkg -i gh_2.20.2_linux_amd64.deb +RUN wget -q https://github.com/cli/cli/releases/download/v${GH_CLI_VER}/gh_${GH_CLI_VER}_linux_amd64.deb \ + && dpkg -i gh_${GH_CLI_VER}_linux_amd64.deb # # Install NodeJS -RUN wget -qO- https://deb.nodesource.com/setup_19.x | bash - +RUN wget -qO- https://deb.nodesource.com/setup_20.x | bash - # hadolint ignore=DL3008 RUN apt-get install -y nodejs --no-install-recommends diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 24e1bdfd6..5feb17564 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,20 +1,23 @@ // Copyright (C) 2019 Intel Corporation. All rights reserved. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp +// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/cpp { "name": "WAMR-Dev", "build": { "dockerfile": "Dockerfile", - // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 - // Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon + // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-12, debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 + // Use Debian 12, Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon "args": { - "BINARYEN_VER": "111", - "EMSDK_VER": "3.0.0", - "LLVM_VER": "15", - "VARIANT": "ubuntu-20.04", - "WASI_SDK_VER": "19", - "WABT_VER": "1.0.31" + "BINARYEN_VER": "114", + "BAZELISK_VER": "1.17.0", + "CMAKE_VER": "3.27.0", + "EMSDK_VER": "3.1.43", + "GH_CLI_VER": "2.32.0", + "LLVM_VER": "16", + "VARIANT": "debian-12", + "WASI_SDK_VER": "20", + "WABT_VER": "1.0.33" } }, "runArgs": [ @@ -34,7 +37,7 @@ "llvm-vs-code-extensions.vscode-clangd", "ms-python.python", "ms-python.vscode-pylance", - "ms-vscode.cmake-tools", + "ms-vscode.cmake-tools" ] } }, From ada7e3fe881473818789c9a5d4c38e7ff0bf4054 Mon Sep 17 00:00:00 2001 From: dongheng <930490596@qq.com> Date: Thu, 27 Jul 2023 10:17:21 +0800 Subject: [PATCH 025/123] ESP-IDF platform supports to load AOT to PSRAM and run it (#2385) --- core/shared/platform/esp-idf/espidf_memmap.c | 73 +++++++++++++++++-- .../platform/esp-idf/shared_platform.cmake | 6 ++ .../platforms/esp-idf/build_and_run.sh | 4 +- product-mini/platforms/esp-idf/main/main.c | 8 +- 4 files changed, 84 insertions(+), 7 deletions(-) diff --git a/core/shared/platform/esp-idf/espidf_memmap.c b/core/shared/platform/esp-idf/espidf_memmap.c index 693094a63..0a1fd4fe4 100644 --- a/core/shared/platform/esp-idf/espidf_memmap.c +++ b/core/shared/platform/esp-idf/espidf_memmap.c @@ -5,16 +5,34 @@ #include "platform_api_vmcore.h" #include "platform_api_extension.h" +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) +#include "soc/mmu.h" +#include "rom/cache.h" + +#define MEM_DUAL_BUS_OFFSET (IRAM0_CACHE_ADDRESS_LOW - DRAM0_CACHE_ADDRESS_LOW) + +#define in_ibus_ext(addr) \ + (((uint32)addr >= IRAM0_CACHE_ADDRESS_LOW) \ + && ((uint32)addr < IRAM0_CACHE_ADDRESS_HIGH)) + +static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED; +#endif void * os_mmap(void *hint, size_t size, int prot, int flags) { if (prot & MMAP_PROT_EXEC) { +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + uint32_t mem_caps = MALLOC_CAP_SPIRAM; +#else + uint32_t mem_caps = MALLOC_CAP_EXEC; +#endif + // Memory allocation with MALLOC_CAP_EXEC will return 4-byte aligned // Reserve extra 4 byte to fixup alignment and size for the pointer to // the originally allocated address void *buf_origin = - heap_caps_malloc(size + 4 + sizeof(uintptr_t), MALLOC_CAP_EXEC); + heap_caps_malloc(size + 4 + sizeof(uintptr_t), mem_caps); if (!buf_origin) { return NULL; } @@ -25,19 +43,35 @@ os_mmap(void *hint, size_t size, int prot, int flags) uintptr_t *addr_field = buf_fixed - sizeof(uintptr_t); *addr_field = (uintptr_t)buf_origin; +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + return buf_fixed + MEM_DUAL_BUS_OFFSET; +#else return buf_fixed; +#endif } else { - return os_malloc(size); +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + uint32_t mem_caps = MALLOC_CAP_SPIRAM; +#else + uint32_t mem_caps = MALLOC_CAP_8BIT; +#endif + return heap_caps_malloc(size, mem_caps); } } void os_munmap(void *addr, size_t size) { + char *ptr = (char *)addr; + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + if (in_ibus_ext(ptr)) { + ptr -= MEM_DUAL_BUS_OFFSET; + } +#endif // We don't need special handling of the executable allocations // here, free() of esp-idf handles it properly - return os_free(addr); + return os_free(ptr); } int @@ -47,5 +81,34 @@ os_mprotect(void *addr, size_t size, int prot) } void -os_dcache_flush() -{} +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + IRAM_ATTR +#endif + os_dcache_flush() +{ +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + uint32_t preload; + extern void Cache_WriteBack_All(void); + + portENTER_CRITICAL(&s_spinlock); + + Cache_WriteBack_All(); + preload = Cache_Disable_ICache(); + Cache_Enable_ICache(preload); + + portEXIT_CRITICAL(&s_spinlock); +#endif +} + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) +void * +os_get_dbus_mirror(void *ibus) +{ + if (in_ibus_ext(ibus)) { + return (void *)((char *)ibus - MEM_DUAL_BUS_OFFSET); + } + else { + return ibus; + } +} +#endif diff --git a/core/shared/platform/esp-idf/shared_platform.cmake b/core/shared/platform/esp-idf/shared_platform.cmake index 13bc45dcb..8d7fe5d80 100644 --- a/core/shared/platform/esp-idf/shared_platform.cmake +++ b/core/shared/platform/esp-idf/shared_platform.cmake @@ -11,3 +11,9 @@ include_directories(${PLATFORM_SHARED_DIR}/../include) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE}) + +# If enable PSRAM of ESP32-S3, it had better to put AOT into PSRAM, so that +# users can use SRAM to for Wi-Fi/BLE and peripheral driver. +if(CONFIG_ESP32S3_SPIRAM_SUPPORT) + add_definitions(-DWASM_MEM_DUAL_BUS_MIRROR=1) +endif() diff --git a/product-mini/platforms/esp-idf/build_and_run.sh b/product-mini/platforms/esp-idf/build_and_run.sh index dd8dd5ca9..f764a3013 100755 --- a/product-mini/platforms/esp-idf/build_and_run.sh +++ b/product-mini/platforms/esp-idf/build_and_run.sh @@ -5,14 +5,16 @@ ESP32_TARGET="esp32" ESP32C3_TARGET="esp32c3" +ESP32S3_TARGET="esp32s3" usage () { echo "USAGE:" - echo "$0 $ESP32_TARGET|$ESP32C3_TARGET" + echo "$0 $ESP32_TARGET|$ESP32C3_TARGET|$ESP32S3_TARGET" echo "Example:" echo " $0 $ESP32_TARGET" echo " $0 $ESP32C3_TARGET" + echo " $0 $ESP32S3_TARGET" exit 1 } diff --git a/product-mini/platforms/esp-idf/main/main.c b/product-mini/platforms/esp-idf/main/main.c index 417fad561..fbfb04c21 100644 --- a/product-mini/platforms/esp-idf/main/main.c +++ b/product-mini/platforms/esp-idf/main/main.c @@ -12,6 +12,12 @@ #include "esp_log.h" +#ifdef CONFIG_IDF_TARGET_ESP32S3 +#define IWASM_MAIN_STACK_SIZE 5120 +#else +#define IWASM_MAIN_STACK_SIZE 4096 +#endif + #define LOG_TAG "wamr" static void * @@ -146,7 +152,7 @@ app_main(void) pthread_attr_t tattr; pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setstacksize(&tattr, 4096); + pthread_attr_setstacksize(&tattr, IWASM_MAIN_STACK_SIZE); res = pthread_create(&t, &tattr, iwasm_main, (void *)NULL); assert(res == 0); From 6110ea39fdcb9e86683213b6036c2787c0b9e9a5 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Thu, 27 Jul 2023 08:54:53 +0200 Subject: [PATCH 026/123] Add hadolint CI for Dockerfile linting (#2387) --- .github/workflows/hadolint_dockerfiles.yml | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/hadolint_dockerfiles.yml diff --git a/.github/workflows/hadolint_dockerfiles.yml b/.github/workflows/hadolint_dockerfiles.yml new file mode 100644 index 000000000..bdabeb6e5 --- /dev/null +++ b/.github/workflows/hadolint_dockerfiles.yml @@ -0,0 +1,47 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: hadolint dockerfiles + +on: + # will be triggered on PR events + pull_request: + types: + - opened + - synchronize + paths: + - "**/Dockerfile*" + - ".github/workflows/hadolint_dockerfiles.yml" + push: + branches: + - main + - "dev/**" + paths: + - "**/Dockerfile*" + - ".github/workflows/hadolint_dockerfiles.yml" + # allow to be triggered manually + workflow_dispatch: + +# Cancel any in-flight jobs for the same PR/branch so there's only one active +# at a time +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + run-hadolint-on-dockerfiles: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # on default, hadolint will fail on warnings and errors + - name: Run hadolint on dockerfiles + run: | + docker pull hadolint/hadolint:latest-debian + find . -name "*Dockerfile*" | while read dockerfile; do + echo "run hadolint on $dockerfile:" + docker run --rm -i hadolint/hadolint:latest-debian hadolint - <"$dockerfile" + echo "successful" + done \ No newline at end of file From 228417ab8c2980879853545163f6ec8d933ff01e Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 27 Jul 2023 22:37:23 +0900 Subject: [PATCH 027/123] Move generic parts of wasm_suspend_flags.h to bh_atomic.h (#2393) --- core/iwasm/common/wasm_suspend_flags.h | 40 ++++--------------- core/shared/utils/bh_atomic.h | 53 ++++++++++++++++++++++++++ core/shared/utils/bh_platform.h | 1 - 3 files changed, 60 insertions(+), 34 deletions(-) create mode 100644 core/shared/utils/bh_atomic.h diff --git a/core/iwasm/common/wasm_suspend_flags.h b/core/iwasm/common/wasm_suspend_flags.h index 0558eaf6b..b7ecbb0b2 100644 --- a/core/iwasm/common/wasm_suspend_flags.h +++ b/core/iwasm/common/wasm_suspend_flags.h @@ -6,7 +6,7 @@ #ifndef _WASM_SUSPEND_FLAGS_H #define _WASM_SUSPEND_FLAGS_H -#include "bh_platform.h" +#include "bh_atomic.h" #ifdef __cplusplus extern "C" { @@ -22,42 +22,16 @@ extern "C" { #define WASM_SUSPEND_FLAG_EXIT 0x8 typedef union WASMSuspendFlags { - uint32 flags; + bh_atomic_32_t flags; uintptr_t __padding__; } WASMSuspendFlags; -#if defined(__GNUC_PREREQ) -#if __GNUC_PREREQ(4, 7) -#define CLANG_GCC_HAS_ATOMIC_BUILTIN -#endif -#elif defined(__clang__) -#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 0) -#define CLANG_GCC_HAS_ATOMIC_BUILTIN -#endif -#endif - -#if defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) -#define WASM_SUSPEND_FLAGS_IS_ATOMIC 1 -#define WASM_SUSPEND_FLAGS_GET(s_flags) \ - __atomic_load_n(&s_flags.flags, __ATOMIC_SEQ_CST) +#define WASM_SUSPEND_FLAGS_IS_ATOMIC BH_ATOMIC_32_IS_ATOMIC +#define WASM_SUSPEND_FLAGS_GET(s_flags) BH_ATOMIC_32_LOAD(s_flags.flags) #define WASM_SUSPEND_FLAGS_FETCH_OR(s_flags, val) \ - __atomic_fetch_or(&s_flags.flags, val, __ATOMIC_SEQ_CST) + BH_ATOMIC_32_FETCH_OR(s_flags.flags, val) #define WASM_SUSPEND_FLAGS_FETCH_AND(s_flags, val) \ - __atomic_fetch_and(&s_flags.flags, val, __ATOMIC_SEQ_CST) -#else /* else of defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) */ -#define WASM_SUSPEND_FLAGS_GET(s_flags) (s_flags.flags) -#define WASM_SUSPEND_FLAGS_FETCH_OR(s_flags, val) (s_flags.flags |= val) -#define WASM_SUSPEND_FLAGS_FETCH_AND(s_flags, val) (s_flags.flags &= val) - -/* The flag can be defined by the user if the platform - supports atomic access to uint32 aligned memory. */ -#ifdef WASM_UINT32_IS_ATOMIC -#define WASM_SUSPEND_FLAGS_IS_ATOMIC 1 -#else /* else of WASM_UINT32_IS_ATOMIC */ -#define WASM_SUSPEND_FLAGS_IS_ATOMIC 0 -#endif /* WASM_UINT32_IS_ATOMIC */ - -#endif + BH_ATOMIC_32_FETCH_AND(s_flags.flags, val) #if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0 #define WASM_SUSPEND_FLAGS_LOCK(lock) (void)0 @@ -71,4 +45,4 @@ typedef union WASMSuspendFlags { } #endif -#endif /* end of _WASM_SUSPEND_FLAGS_H */ \ No newline at end of file +#endif /* end of _WASM_SUSPEND_FLAGS_H */ diff --git a/core/shared/utils/bh_atomic.h b/core/shared/utils/bh_atomic.h new file mode 100644 index 000000000..4dfffa722 --- /dev/null +++ b/core/shared/utils/bh_atomic.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _BH_ATOMIC_H +#define _BH_ATOMIC_H + +#include "gnuc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32 bh_atomic_32_t; + +#if defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4, 7) +#define CLANG_GCC_HAS_ATOMIC_BUILTIN +#endif +#elif defined(__clang__) +#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 0) +#define CLANG_GCC_HAS_ATOMIC_BUILTIN +#endif +#endif + +#if defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) +#define BH_ATOMIC_32_IS_ATOMIC 1 +#define BH_ATOMIC_32_LOAD(v) __atomic_load_n(&(v), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_32_FETCH_OR(v, val) \ + __atomic_fetch_or(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_32_FETCH_AND(v, val) \ + __atomic_fetch_and(&(v), (val), __ATOMIC_SEQ_CST) +#else /* else of defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) */ +#define BH_ATOMIC_32_LOAD(v) (v) +#define BH_ATOMIC_32_FETCH_OR(v, val) ((v) |= (val)) +#define BH_ATOMIC_32_FETCH_AND(v, val) ((v) &= (val)) + +/* The flag can be defined by the user if the platform + supports atomic access to uint32 aligned memory. */ +#ifdef WASM_UINT32_IS_ATOMIC +#define BH_ATOMIC_32_IS_ATOMIC 1 +#else /* else of WASM_UINT32_IS_ATOMIC */ +#define BH_ATOMIC_32_IS_ATOMIC 0 +#endif /* WASM_UINT32_IS_ATOMIC */ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of _BH_ATOMIC_H */ diff --git a/core/shared/utils/bh_platform.h b/core/shared/utils/bh_platform.h index 9821d710d..86aef839d 100644 --- a/core/shared/utils/bh_platform.h +++ b/core/shared/utils/bh_platform.h @@ -16,7 +16,6 @@ #include "bh_log.h" #include "bh_queue.h" #include "bh_vector.h" -#include "gnuc.h" #include "runtime_timer.h" /** From 59b2099b68ae3e027f2787397226e503501e38b8 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 27 Jul 2023 21:53:48 +0800 Subject: [PATCH 028/123] Fix some check issues on table operations (#2392) Fix some check issues on table.init, table.fill and table.copy, and unify the check method for all running modes. Fix issue #2390 and #2096. --- core/iwasm/aot/aot_runtime.c | 15 +++---- core/iwasm/fast-jit/fe/jit_emit_table.c | 41 ++++++++++---------- core/iwasm/interpreter/wasm.h | 19 ++++++++- core/iwasm/interpreter/wasm_interp_classic.c | 36 ++++++++--------- core/iwasm/interpreter/wasm_interp_fast.c | 30 ++++++++------ core/iwasm/interpreter/wasm_runtime.c | 15 +++---- 6 files changed, 91 insertions(+), 65 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 35735b94e..e0d56a698 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -2489,13 +2489,13 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, tbl_seg = module->table_init_data_list[tbl_seg_idx]; bh_assert(tbl_seg); - if (!length) { + if (offset_len_out_of_bounds(src_offset, length, tbl_seg->func_index_count) + || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) { + aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } - if (length + src_offset > tbl_seg->func_index_count - || dst_offset + length > tbl_inst->cur_size) { - aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); + if (!length) { return; } @@ -2528,8 +2528,9 @@ aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx, dst_tbl_inst = module_inst->tables[dst_tbl_idx]; bh_assert(dst_tbl_inst); - if ((uint64)dst_offset + length > dst_tbl_inst->cur_size - || (uint64)src_offset + length > src_tbl_inst->cur_size) { + if (offset_len_out_of_bounds(dst_offset, length, dst_tbl_inst->cur_size) + || offset_len_out_of_bounds(src_offset, length, + src_tbl_inst->cur_size)) { aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } @@ -2554,7 +2555,7 @@ aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length, tbl_inst = module_inst->tables[tbl_idx]; bh_assert(tbl_inst); - if (data_offset + length > tbl_inst->cur_size) { + if (offset_len_out_of_bounds(data_offset, length, tbl_inst->cur_size)) { aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } diff --git a/core/iwasm/fast-jit/fe/jit_emit_table.c b/core/iwasm/fast-jit/fe/jit_emit_table.c index 9fb61931f..ea1b33883 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_table.c +++ b/core/iwasm/fast-jit/fe/jit_emit_table.c @@ -88,27 +88,28 @@ fail: static int wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx, - uint32 dst, uint32 len, uint32 src) + uint32 dst_offset, uint32 len, uint32 src_offset) { WASMTableInstance *tbl; uint32 tbl_sz; WASMTableSeg *elem; uint32 elem_len; - tbl = inst->tables[tbl_idx]; - tbl_sz = tbl->cur_size; - if (dst > tbl_sz || tbl_sz - dst < len) - goto out_of_bounds; - elem = inst->module->table_segments + elem_idx; elem_len = elem->function_count; - if (src > elem_len || elem_len - src < len) + if (offset_len_out_of_bounds(src_offset, len, elem_len)) + goto out_of_bounds; + + tbl = inst->tables[tbl_idx]; + tbl_sz = tbl->cur_size; + if (offset_len_out_of_bounds(dst_offset, len, tbl_sz)) goto out_of_bounds; bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems) - + dst * sizeof(uint32), - (uint32)((tbl_sz - dst) * sizeof(uint32)), - elem->func_indexes + src, (uint32)(len * sizeof(uint32))); + + dst_offset * sizeof(uint32), + (uint32)((tbl_sz - dst_offset) * sizeof(uint32)), + elem->func_indexes + src_offset, + (uint32)(len * sizeof(uint32))); return 0; out_of_bounds: @@ -157,14 +158,14 @@ wasm_copy_table(WASMModuleInstance *inst, uint32 src_tbl_idx, WASMTableInstance *src_tbl, *dst_tbl; uint32 src_tbl_sz, dst_tbl_sz; - src_tbl = inst->tables[src_tbl_idx]; - src_tbl_sz = src_tbl->cur_size; - if (src_offset > src_tbl_sz || src_tbl_sz - src_offset < len) - goto out_of_bounds; - dst_tbl = inst->tables[dst_tbl_idx]; dst_tbl_sz = dst_tbl->cur_size; - if (dst_offset > dst_tbl_sz || dst_tbl_sz - dst_offset < len) + if (offset_len_out_of_bounds(dst_offset, len, dst_tbl_sz)) + goto out_of_bounds; + + src_tbl = inst->tables[src_tbl_idx]; + src_tbl_sz = src_tbl->cur_size; + if (offset_len_out_of_bounds(src_offset, len, src_tbl_sz)) goto out_of_bounds; bh_memmove_s((uint8 *)dst_tbl + offsetof(WASMTableInstance, elems) @@ -263,7 +264,7 @@ fail: } static int -wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst, +wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst_offset, uint32 val, uint32 len) { WASMTableInstance *tbl; @@ -272,11 +273,11 @@ wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst, tbl = inst->tables[tbl_idx]; tbl_sz = tbl->cur_size; - if (dst > tbl_sz || tbl_sz - dst < len) + if (offset_len_out_of_bounds(dst_offset, len, tbl_sz)) goto out_of_bounds; - for (; len != 0; dst++, len--) { - tbl->elems[dst] = val; + for (; len != 0; dst_offset++, len--) { + tbl->elems[dst_offset] = val; } return 0; diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 0797a018b..c7d9f1de9 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -627,7 +627,6 @@ typedef struct WASMBranchBlock { uint32 cell_num; } WASMBranchBlock; -/* Execution environment, e.g. stack info */ /** * Align an unsigned value on a alignment boundary. * @@ -643,6 +642,24 @@ align_uint(unsigned v, unsigned b) return (v + m) & ~m; } +/** + * Check whether a piece of data is out of range + * + * @param offset the offset that the data starts + * @param len the length of the data + * @param max_size the maximum size of the data range + * + * @return true if out of range, false otherwise + */ +inline static bool +offset_len_out_of_bounds(uint32 offset, uint32 len, uint32 max_size) +{ + if (offset + len < offset /* integer overflow */ + || offset + len > max_size) + return true; + return false; +} + /** * Return the hash value of c string. */ diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 55fca2921..23e165bea 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -3247,7 +3247,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, case WASM_OP_TABLE_INIT: { uint32 tbl_idx, elem_idx; - uint64 n, s, d; + uint32 n, s, d; WASMTableInstance *tbl_inst; read_leb_uint32(frame_ip, frame_ip_end, elem_idx); @@ -3262,20 +3262,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - /* TODO: what if the element is not passive? */ - - if (!n) { - break; - } - - if (n + s > module->module->table_segments[elem_idx] - .function_count - || d + n > tbl_inst->cur_size) { + if (offset_len_out_of_bounds( + s, n, + module->module->table_segments[elem_idx] + .function_count) + || offset_len_out_of_bounds(d, n, + tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; } + if (!n) { + break; + } + if (module->module->table_segments[elem_idx] .is_dropped) { wasm_set_exception(module, @@ -3316,7 +3317,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, case WASM_OP_TABLE_COPY: { uint32 src_tbl_idx, dst_tbl_idx; - uint64 n, s, d; + uint32 n, s, d; WASMTableInstance *src_tbl_inst, *dst_tbl_inst; read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx); @@ -3333,8 +3334,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - if (d + n > dst_tbl_inst->cur_size - || s + n > src_tbl_inst->cur_size) { + if (offset_len_out_of_bounds(d, n, + dst_tbl_inst->cur_size) + || offset_len_out_of_bounds( + s, n, src_tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; @@ -3404,11 +3407,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, fill_val = POP_I32(); i = POP_I32(); - /* TODO: what if the element is not passive? */ - /* TODO: what if the element is dropped? */ - - if (i + n > tbl_inst->cur_size) { - /* TODO: verify warning content */ + if (offset_len_out_of_bounds(i, n, + tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 070fcdbee..458eb2e44 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -3078,7 +3078,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, case WASM_OP_TABLE_INIT: { uint32 tbl_idx, elem_idx; - uint64 n, s, d; + uint32 n, s, d; WASMTableInstance *tbl_inst; elem_idx = read_uint32(frame_ip); @@ -3093,18 +3093,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - if (!n) { - break; - } - - if (n + s > module->module->table_segments[elem_idx] - .function_count - || d + n > tbl_inst->cur_size) { + if (offset_len_out_of_bounds( + s, n, + module->module->table_segments[elem_idx] + .function_count) + || offset_len_out_of_bounds(d, n, + tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; } + if (!n) { + break; + } + if (module->module->table_segments[elem_idx] .is_dropped) { wasm_set_exception(module, @@ -3143,7 +3146,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, case WASM_OP_TABLE_COPY: { uint32 src_tbl_idx, dst_tbl_idx; - uint64 n, s, d; + uint32 n, s, d; WASMTableInstance *src_tbl_inst, *dst_tbl_inst; dst_tbl_idx = read_uint32(frame_ip); @@ -3160,8 +3163,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - if (d + n > dst_tbl_inst->cur_size - || s + n > src_tbl_inst->cur_size) { + if (offset_len_out_of_bounds(d, n, + dst_tbl_inst->cur_size) + || offset_len_out_of_bounds( + s, n, src_tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; @@ -3232,7 +3237,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, fill_val = POP_I32(); i = POP_I32(); - if (i + n > tbl_inst->cur_size) { + if (offset_len_out_of_bounds(i, n, + tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 00f0cf668..84155a05a 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -3301,13 +3301,13 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, bh_assert(tbl_inst); bh_assert(tbl_seg); - if (!length) { + if (offset_len_out_of_bounds(src_offset, length, tbl_seg->function_count) + || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) { + jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } - if (length + src_offset > tbl_seg->function_count - || dst_offset + length > tbl_inst->cur_size) { - jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); + if (!length) { return; } @@ -3349,8 +3349,9 @@ llvm_jit_table_copy(WASMModuleInstance *module_inst, uint32 src_tbl_idx, bh_assert(src_tbl_inst); bh_assert(dst_tbl_inst); - if ((uint64)dst_offset + length > dst_tbl_inst->cur_size - || (uint64)src_offset + length > src_tbl_inst->cur_size) { + if (offset_len_out_of_bounds(dst_offset, length, dst_tbl_inst->cur_size) + || offset_len_out_of_bounds(src_offset, length, + src_tbl_inst->cur_size)) { jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } @@ -3382,7 +3383,7 @@ llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx, tbl_inst = wasm_get_table_inst(module_inst, tbl_idx); bh_assert(tbl_inst); - if (data_offset + length > tbl_inst->cur_size) { + if (offset_len_out_of_bounds(data_offset, length, tbl_inst->cur_size)) { jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } From 7db4815e837bc34942e95aba292ca0eca318cc54 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 28 Jul 2023 21:36:35 +0900 Subject: [PATCH 029/123] bh_atomic.h: Add comments (#2398) --- core/shared/utils/bh_atomic.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/core/shared/utils/bh_atomic.h b/core/shared/utils/bh_atomic.h index 4dfffa722..61f65a6bf 100644 --- a/core/shared/utils/bh_atomic.h +++ b/core/shared/utils/bh_atomic.h @@ -12,6 +12,38 @@ extern "C" { #endif +/* + * Why don't we use C11 stdatomics here? + * + * Unlike C11 stdatomics, + * + * - bh_atomic_xxx_t is guaranteed to have the same size as the base type. + * Thus more friendly to our AOT conventions. + * + * - It's available for C++. + * Although C++23 will have C-compatible stdatomics.h, it isn't widely + * available yet. + */ + +/* + * Note about BH_ATOMIC_32_IS_ATOMIC + * + * If BH_ATOMIC_32_IS_ATOMIC == 0, BH_ATOMIC_xxx operations defined below + * are not really atomic and require an external lock. + * + * Expected usage is: + * + * bh_atomic_32_t var = 0; + * uint32 old; + * #if BH_ATOMIC_32_IS_ATOMIC == 0 + * lock(&some_lock); + * #endif + * old = BH_ATOMIC_32_FETCH_AND(var, 1); + * #if BH_ATOMIC_32_IS_ATOMIC == 0 + * unlock(&some_lock); + * #endif + */ + typedef uint32 bh_atomic_32_t; #if defined(__GNUC_PREREQ) From 10b18d85cdf491d78d36ac36948a6afeff369e8a Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Sat, 29 Jul 2023 10:28:09 +0800 Subject: [PATCH 030/123] Fix ExpandMemoryOpPass doesn't work properly (#2399) The old method may not work for some cases. This PR iterates over all instructions in the function, looking for memcpy, memmove and memset instructions, putting them into a set, and finally expands them into a loop one by one. And move this LLVM Pass after building the pipe line of pass builder to ensure that the memcpy/memmove/memset instrinsics are generated before applying the pass. --- core/iwasm/compilation/aot_llvm_extra.cpp | 77 +++++++++++------------ 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index 1ccb2f549..898fabd8c 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -82,43 +82,40 @@ class ExpandMemoryOpPass : public PassInfoMixin PreservedAnalyses ExpandMemoryOpPass::run(Function &F, FunctionAnalysisManager &AM) { - Intrinsic::ID ID = F.getIntrinsicID(); - bool Changed = false; + SmallVector MemCalls; - for (auto I = F.user_begin(), E = F.user_end(); I != E;) { - Instruction *Inst = cast(*I); - ++I; + /* Iterate over all instructions in the function, looking for memcpy, + * memmove, and memset. When we find one, expand it into a loop. */ - switch (ID) { - case Intrinsic::memcpy: - { - auto *Memcpy = cast(Inst); - Function *ParentFunc = Memcpy->getParent()->getParent(); - const TargetTransformInfo &TTI = - AM.getResult(*ParentFunc); - expandMemCpyAsLoop(Memcpy, TTI); - Memcpy->eraseFromParent(); - Changed = true; - break; + for (auto &BB : F) { + for (auto &Inst : BB) { + if (auto *Memcpy = dyn_cast_or_null(&Inst)) { + MemCalls.push_back(Memcpy); } - case Intrinsic::memmove: - { - auto *Memmove = cast(Inst); - expandMemMoveAsLoop(Memmove); - Memmove->eraseFromParent(); - Changed = true; - break; + else if (auto *Memmove = dyn_cast_or_null(&Inst)) { + MemCalls.push_back(Memmove); } - case Intrinsic::memset: - { - auto *Memset = cast(Inst); - expandMemSetAsLoop(Memset); - Memset->eraseFromParent(); - Changed = true; - break; + else if (auto *Memset = dyn_cast_or_null(&Inst)) { + MemCalls.push_back(Memset); } - default: - break; + } + } + + for (MemIntrinsic *MemCall : MemCalls) { + if (MemCpyInst *Memcpy = dyn_cast(MemCall)) { + Function *ParentFunc = Memcpy->getParent()->getParent(); + const TargetTransformInfo &TTI = + AM.getResult(*ParentFunc); + expandMemCpyAsLoop(Memcpy, TTI); + Memcpy->eraseFromParent(); + } + else if (MemMoveInst *Memmove = dyn_cast(MemCall)) { + expandMemMoveAsLoop(Memmove); + Memmove->eraseFromParent(); + } + else if (MemSetInst *Memset = dyn_cast(MemCall)) { + expandMemSetAsLoop(Memset); + Memset->eraseFromParent(); } } @@ -297,13 +294,6 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) FPM.addPass(SLPVectorizerPass()); FPM.addPass(LoadStoreVectorizerPass()); - /* Run specific passes for AOT indirect mode in last since general - optimization may create some intrinsic function calls like - llvm.memset, so let's remove these function calls here. */ - if (comp_ctx->is_indirect_mode) { - FPM.addPass(ExpandMemoryOpPass()); - } - if (comp_ctx->enable_llvm_pgo || comp_ctx->use_prof_file) { /* LICM pass: loop invariant code motion, attempting to remove as much code from the body of a loop as possible. Experiments @@ -341,6 +331,15 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) else { MPM.addPass(PB.buildPerModuleDefaultPipeline(OL)); } + + /* Run specific passes for AOT indirect mode in last since general + optimization may create some intrinsic function calls like + llvm.memset, so let's remove these function calls here. */ + if (comp_ctx->is_indirect_mode) { + FunctionPassManager FPM1; + FPM1.addPass(ExpandMemoryOpPass()); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM1))); + } } MPM.run(*M, MAM); From 6d6cea1a73452c68545ab617c497fe19848cbd14 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Sun, 30 Jul 2023 20:23:30 +0900 Subject: [PATCH 031/123] Fix non-builtin BH_ATOMIC_32_FETCH_OR and BH_ATOMIC_32_FETCH_AND (#2400) --- core/shared/utils/bh_atomic.h | 20 ++++++++++++++++++-- samples/bh_atomic/CMakeLists.txt | 20 ++++++++++++++++++++ samples/bh_atomic/main.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 samples/bh_atomic/CMakeLists.txt create mode 100644 samples/bh_atomic/main.c diff --git a/core/shared/utils/bh_atomic.h b/core/shared/utils/bh_atomic.h index 61f65a6bf..b4378c4b2 100644 --- a/core/shared/utils/bh_atomic.h +++ b/core/shared/utils/bh_atomic.h @@ -65,8 +65,24 @@ typedef uint32 bh_atomic_32_t; __atomic_fetch_and(&(v), (val), __ATOMIC_SEQ_CST) #else /* else of defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) */ #define BH_ATOMIC_32_LOAD(v) (v) -#define BH_ATOMIC_32_FETCH_OR(v, val) ((v) |= (val)) -#define BH_ATOMIC_32_FETCH_AND(v, val) ((v) &= (val)) +#define BH_ATOMIC_32_FETCH_OR(v, val) nonatomic_32_fetch_or(&(v), val) +#define BH_ATOMIC_32_FETCH_AND(v, val) nonatomic_32_fetch_and(&(v), val) + +static inline uint32 +nonatomic_32_fetch_or(bh_atomic_32_t *p, uint32 val) +{ + uint32 old = *p; + *p |= val; + return old; +} + +static inline uint32 +nonatomic_32_fetch_and(bh_atomic_32_t *p, uint32 val) +{ + uint32 old = *p; + *p &= val; + return old; +} /* The flag can be defined by the user if the platform supports atomic access to uint32 aligned memory. */ diff --git a/samples/bh_atomic/CMakeLists.txt b/samples/bh_atomic/CMakeLists.txt new file mode 100644 index 000000000..f69052742 --- /dev/null +++ b/samples/bh_atomic/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2023 Midokura Japan KK. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.0) +project(bh_atomic) + +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +if(APPLE) + add_definitions(-DBH_PLATFORM_DARWIN) +endif() + +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_LIBC_BUILTIN 0) + +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..) +include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_executable(bh_atomic main.c) + +target_link_libraries(bh_atomic) diff --git a/samples/bh_atomic/main.c b/samples/bh_atomic/main.c new file mode 100644 index 000000000..adb0dd023 --- /dev/null +++ b/samples/bh_atomic/main.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "bh_platform.h" +#include "bh_atomic.h" + +int +main(int argc, char **argv) +{ + bh_atomic_32_t v; + uint32 o; + + v = 0x00ff00ff; + o = BH_ATOMIC_32_LOAD(v); + assert(o == 0x00ff00ff); + + v = 0x00ff00ff; + o = BH_ATOMIC_32_FETCH_OR(v, 0xffff0000); + assert(o == 0x00ff00ff); + assert(v == 0xffff00ff); + + v = 0x00ff00ff; + o = BH_ATOMIC_32_FETCH_AND(v, 0xffff0000); + assert(o == 0x00ff00ff); + assert(v == 0x00ff0000); + + return 0; +} From 151600fef2954ffd418f417bc22a899bf327c3a5 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Sun, 30 Jul 2023 12:34:09 +0100 Subject: [PATCH 032/123] Fix wasi-sockets tests (#2389) Tests were failing because the right permissions were not provided to iwasm. Also, test failures didn't trigger build failure due to typo - also fixed in this change. In addition to that, this PR fixes a few issues with the test itself: * the `server_init_complete` was not reset early enough causing the client to occasionally assume the server started even though it didn't yet * set `SO_REUSEADDR` on the server socket so the port can be reused shortly after closing the previous socket * defined receive-send-receive sequence from server to make sure server is alive at the time of sending message --- .../libraries/lib-socket/test/nslookup.c | 1 + .../iwasm/libraries/lib-socket/test/tcp_udp.c | 227 +++++++++--------- .../wasi-test-script/run_wasi_tests.sh | 14 +- 3 files changed, 122 insertions(+), 120 deletions(-) diff --git a/core/iwasm/libraries/lib-socket/test/nslookup.c b/core/iwasm/libraries/lib-socket/test/nslookup.c index 543a3fb24..8e64d06be 100644 --- a/core/iwasm/libraries/lib-socket/test/nslookup.c +++ b/core/iwasm/libraries/lib-socket/test/nslookup.c @@ -46,6 +46,7 @@ test_nslookup_mt(void *params) { int *af = (int *)params; test_nslookup(*af); + return NULL; } int diff --git a/core/iwasm/libraries/lib-socket/test/tcp_udp.c b/core/iwasm/libraries/lib-socket/test/tcp_udp.c index 49231de89..0ed031250 100644 --- a/core/iwasm/libraries/lib-socket/test/tcp_udp.c +++ b/core/iwasm/libraries/lib-socket/test/tcp_udp.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #ifdef __wasi__ #include #include @@ -12,105 +14,123 @@ #endif #include #include +#include + #define SERVER_MSG "Message from server." #define PORT 8989 -pthread_mutex_t mut; -pthread_cond_t cond; + +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + int server_init_complete = 0; -char buffer[sizeof(SERVER_MSG) + 1]; -struct socket_info { - union { - struct sockaddr_in addr_ipv4; - struct sockaddr_in6 addr_ipv6; - } addr; +typedef struct { + struct sockaddr_storage addr; + socklen_t addr_len; int sock; -}; - -struct thread_args { - int family; int protocol; -}; +} socket_info_t; -struct socket_info -init_socket_addr(int family, int protocol) +void +wait_for_server(int wait_time_seconds) { - int sock = socket(family, protocol, 0); - assert(sock != -1); + int res = 0; + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += wait_time_seconds; - struct socket_info info; - if (family == AF_INET) { - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(PORT); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - info.addr.addr_ipv4 = addr; + pthread_mutex_lock(&mut); + while (server_init_complete == 0) { + res = pthread_cond_timedwait(&cond, &mut, &ts); + if (res == ETIMEDOUT) + break; } - else if (family == AF_INET6) { - struct sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_port = htons(PORT); - addr.sin6_addr = in6addr_loopback; - info.addr.addr_ipv6 = addr; - } - info.sock = sock; - return info; + pthread_mutex_unlock(&mut); + + assert(res == 0); } void -assert_thread_args(struct thread_args *args) +notify_server_started() { - assert(args->family == AF_INET || args->family == AF_INET6); - assert(args->protocol == SOCK_STREAM || args->protocol == SOCK_DGRAM); + pthread_mutex_lock(&mut); + server_init_complete = 1; + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mut); +} + +socket_info_t +init_socket_addr(int family, int protocol) +{ + socket_info_t info; + + info.sock = socket(family, protocol, 0); + assert(info.sock != -1); + info.protocol = protocol; + + memset(&info.addr, 0, sizeof(info.addr)); + + if (family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *)&info.addr; + addr->sin_family = AF_INET; + addr->sin_port = htons(PORT); + addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + info.addr_len = sizeof(struct sockaddr_in); + } + else if (family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&info.addr; + addr->sin6_family = AF_INET6; + addr->sin6_port = htons(PORT); + addr->sin6_addr = in6addr_loopback; + info.addr_len = sizeof(struct sockaddr_in6); + } + + return info; } void * server(void *arg) { - server_init_complete = 0; - struct thread_args *args = (struct thread_args *)arg; - assert_thread_args(args); - - struct socket_info init_server_sock = - init_socket_addr(args->family, args->protocol); - - int server_sock = init_server_sock.sock; - socklen_t addr_size; + char buffer[sizeof(SERVER_MSG) + 1] = { 0 }; struct sockaddr_storage client_addr; - strcpy(buffer, SERVER_MSG); + socket_info_t *info = (socket_info_t *)arg; + struct sockaddr *server_addr = (struct sockaddr *)&info->addr; + int server_sock = info->sock; - struct sockaddr *server_addr = (struct sockaddr *)&init_server_sock.addr; - int ret = bind(server_sock, server_addr, - args->family == AF_INET ? sizeof(struct sockaddr_in) - : sizeof(struct sockaddr_in6)); - assert(ret == 0); + int optval = 1; + assert(setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &optval, + sizeof(optval)) + == 0); - (args->protocol == SOCK_STREAM) && listen(server_sock, 1); - pthread_mutex_lock(&mut); - server_init_complete = 1; - pthread_mutex_unlock(&mut); - pthread_cond_signal(&cond); + assert(bind(server_sock, server_addr, info->addr_len) == 0); - addr_size = sizeof(client_addr); - if (args->protocol == SOCK_STREAM) { + if (info->protocol == SOCK_STREAM) + listen(server_sock, 1); + notify_server_started(); + + socklen_t addr_size = info->addr_len; + if (info->protocol == SOCK_STREAM) { int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &addr_size); assert(client_sock >= 0); - sendto(client_sock, buffer, strlen(buffer), 0, - (struct sockaddr *)&client_addr, addr_size); - - assert(close(client_sock) == 0); + assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0); + strcpy(buffer, SERVER_MSG); + assert(send(client_sock, buffer, sizeof(buffer), 0) > 0); + assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0); } else { - recvfrom(server_sock, buffer, sizeof(buffer), 0, - (struct sockaddr *)&client_addr, &addr_size); - sendto(server_sock, buffer, strlen(buffer), 0, - (struct sockaddr *)&client_addr, addr_size); - - assert(close(server_sock) == 0); + assert(recvfrom(server_sock, buffer, sizeof(buffer), 0, + (struct sockaddr *)&client_addr, &addr_size) + > 0); + strcpy(buffer, SERVER_MSG); + assert(sendto(server_sock, buffer, strlen(buffer), 0, + (struct sockaddr *)&client_addr, addr_size) + > 0); + assert(recvfrom(server_sock, buffer, sizeof(buffer), 0, + (struct sockaddr *)&client_addr, &addr_size) + > 0); } + assert(close(server_sock) == 0); return NULL; } @@ -118,46 +138,23 @@ server(void *arg) void * client(void *arg) { - struct thread_args *args = (struct thread_args *)arg; - assert_thread_args(args); + char buffer[sizeof(SERVER_MSG) + 1]; + socket_info_t *info = (socket_info_t *)arg; + int sock = info->sock; + struct sockaddr *addr = (struct sockaddr *)&info->addr; - pthread_mutex_lock(&mut); + wait_for_server(1); - while (server_init_complete == 0) { - pthread_cond_wait(&cond, &mut); + if (info->protocol == SOCK_STREAM) { + assert(connect(sock, addr, info->addr_len) != -1); } - struct socket_info init_client_sock = - init_socket_addr(args->family, args->protocol); - int sock = init_client_sock.sock; - pthread_mutex_unlock(&mut); - - if (args->family == AF_INET) { - struct sockaddr_in addr = init_client_sock.addr.addr_ipv4; - if (args->protocol == SOCK_STREAM) { - assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1); - } - else { - assert(sendto(sock, buffer, strlen(buffer), 0, - (struct sockaddr *)&addr, sizeof(addr)) - != -1); - } - } - else { - struct sockaddr_in6 addr = init_client_sock.addr.addr_ipv6; - if (args->protocol == SOCK_STREAM) { - assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1); - } - else { - assert(sendto(sock, buffer, strlen(buffer), 0, - (struct sockaddr *)&addr, sizeof(addr)) - != -1); - } - } - - recv(sock, buffer, sizeof(buffer), 0); - assert(strcmp(buffer, SERVER_MSG) == 0); + assert(sendto(sock, "open", strlen("open"), 0, addr, info->addr_len) > 0); + assert(recv(sock, buffer, sizeof(buffer), 0) > 0); + assert(strncmp(buffer, SERVER_MSG, strlen(SERVER_MSG)) == 0); + assert(sendto(sock, "close", sizeof("close"), 0, addr, info->addr_len) > 0); assert(close(sock) == 0); + return NULL; } @@ -165,17 +162,19 @@ void test_protocol(int family, int protocol) { pthread_t server_thread, client_thread; - assert(pthread_cond_init(&cond, NULL) == 0); - assert(pthread_mutex_init(&mut, NULL) == 0); + socket_info_t server_info = init_socket_addr(family, protocol); + socket_info_t client_info = init_socket_addr(family, protocol); - struct thread_args args = { family, protocol }; - assert(pthread_create(&server_thread, NULL, server, (void *)&args) == 0); - assert(pthread_create(&client_thread, NULL, client, (void *)&args) == 0); + printf("Testing address family: %d protocol: %d\n", family, protocol); + + server_init_complete = 0; + + assert(pthread_create(&server_thread, NULL, server, (void *)&server_info) + == 0); + assert(pthread_create(&client_thread, NULL, client, (void *)&client_info) + == 0); assert(pthread_join(server_thread, NULL) == 0); assert(pthread_join(client_thread, NULL) == 0); - - assert(pthread_mutex_destroy(&mut) == 0); - assert(pthread_cond_destroy(&cond) == 0); } int @@ -190,4 +189,4 @@ main(int argc, char **argv) test_protocol(AF_INET6, SOCK_DGRAM); return 0; -} \ No newline at end of file +} diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index eb6cf3f91..7738b5080 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -11,7 +11,9 @@ readonly TARGET=$2 readonly WORK_DIR=$PWD readonly PLATFORM=$(uname -s | tr A-Z a-z) readonly WAMR_DIR="${WORK_DIR}/../../../.." -readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm" +readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm \ + --allow-resolve=google-public-dns-a.google.com \ + --addr-pool=::1/128,127.0.0.1/32" readonly WAMRC_CMD="${WORK_DIR}/../../../../wamr-compiler/build/wamrc" readonly C_TESTS="tests/c/testsuite/" readonly ASSEMBLYSCRIPT_TESTS="tests/assemblyscript/testsuite/" @@ -35,12 +37,12 @@ run_aot_tests () { echo "Running $test_aot" expected=0 - if [ -f ${test_json} ]; then + if [ -f ${test_json} ]; then expected=$(jq .exit_code ${test_json}) fi - + ${IWASM_CMD} $test_aot - + ret=${PIPESTATUS[0]} echo "expected=$expected, actual=$ret" @@ -48,7 +50,7 @@ run_aot_tests () { exit_code=1 fi done -} +} if [[ $MODE != "aot" ]];then python3 -m venv wasi-env && source wasi-env/bin/activate @@ -60,7 +62,7 @@ if [[ $MODE != "aot" ]];then ${ASSEMBLYSCRIPT_TESTS} \ ${THREAD_PROPOSAL_TESTS} \ ${THREAD_INTERNAL_TESTS} \ - ${LIB_SOCKET_TESTS} \ + ${LIB_SOCKET_TESTS} exit_code=${PIPESTATUS[0]} deactivate else From b1fa27e91d8cf2868bd1d764aabd5579db78a2bd Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 31 Jul 2023 18:56:15 +0900 Subject: [PATCH 033/123] bh_atomic.h: Add BH_ATOMIC_32_FETCH_ADD/BH_ATOMIC_32_FETCH_SUB (#2408) --- core/shared/utils/bh_atomic.h | 22 ++++++++++++++++++++++ samples/bh_atomic/main.c | 10 ++++++++++ 2 files changed, 32 insertions(+) diff --git a/core/shared/utils/bh_atomic.h b/core/shared/utils/bh_atomic.h index b4378c4b2..64dfee1b6 100644 --- a/core/shared/utils/bh_atomic.h +++ b/core/shared/utils/bh_atomic.h @@ -63,10 +63,16 @@ typedef uint32 bh_atomic_32_t; __atomic_fetch_or(&(v), (val), __ATOMIC_SEQ_CST) #define BH_ATOMIC_32_FETCH_AND(v, val) \ __atomic_fetch_and(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_32_FETCH_ADD(v, val) \ + __atomic_fetch_add(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_32_FETCH_SUB(v, val) \ + __atomic_fetch_sub(&(v), (val), __ATOMIC_SEQ_CST) #else /* else of defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) */ #define BH_ATOMIC_32_LOAD(v) (v) #define BH_ATOMIC_32_FETCH_OR(v, val) nonatomic_32_fetch_or(&(v), val) #define BH_ATOMIC_32_FETCH_AND(v, val) nonatomic_32_fetch_and(&(v), val) +#define BH_ATOMIC_32_FETCH_ADD(v, val) nonatomic_32_fetch_add(&(v), val) +#define BH_ATOMIC_32_FETCH_SUB(v, val) nonatomic_32_fetch_sub(&(v), val) static inline uint32 nonatomic_32_fetch_or(bh_atomic_32_t *p, uint32 val) @@ -84,6 +90,22 @@ nonatomic_32_fetch_and(bh_atomic_32_t *p, uint32 val) return old; } +static inline uint32 +nonatomic_32_fetch_add(bh_atomic_32_t *p, uint32 val) +{ + uint32 old = *p; + *p += val; + return old; +} + +static inline uint32 +nonatomic_32_fetch_sub(bh_atomic_32_t *p, uint32 val) +{ + uint32 old = *p; + *p -= val; + return old; +} + /* The flag can be defined by the user if the platform supports atomic access to uint32 aligned memory. */ #ifdef WASM_UINT32_IS_ATOMIC diff --git a/samples/bh_atomic/main.c b/samples/bh_atomic/main.c index adb0dd023..61c52800b 100644 --- a/samples/bh_atomic/main.c +++ b/samples/bh_atomic/main.c @@ -28,5 +28,15 @@ main(int argc, char **argv) assert(o == 0x00ff00ff); assert(v == 0x00ff0000); + v = 0x00ff00ff; + o = BH_ATOMIC_32_FETCH_ADD(v, 0x10101); + assert(o == 0x00ff00ff); + assert(v == 0x00ff00ff + 0x10101); + + v = 0x00ff00ff; + o = BH_ATOMIC_32_FETCH_SUB(v, 0x10101); + assert(o == 0x00ff00ff); + assert(v == 0x00ff00ff - 0x10101); + return 0; } From 45a4e774de3e2235b3e1bf9580177768464d3b90 Mon Sep 17 00:00:00 2001 From: Cengizhan Pasaoglu Date: Mon, 31 Jul 2023 13:14:50 +0300 Subject: [PATCH 034/123] Upgrade cJSON version to v1.7.16 (#2404) --- ATTRIBUTIONS.md | 2 +- test-tools/host-tool/external/cJSON/cJSON.c | 488 +++++++++++++------- test-tools/host-tool/external/cJSON/cJSON.h | 153 +++--- 3 files changed, 423 insertions(+), 220 deletions(-) diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index 60b6bb1b7..ef788bf73 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -22,7 +22,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the | third party components | version number | latest release | vendor pages | CVE details | | --- | --- | --- | --- | --- | -| cjson | 1.7.10 | 1.7.14 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html | +| cjson | 1.7.16 | 1.7.16 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html | | contiki-ng (er-coap) | unspecified | 3.0 | https://github.com/contiki-os/contiki | https://www.cvedetails.com/vendor/16528/Contiki-os.html | | freebsd libm | unspecified | 13.0 | https://www.freebsd.org/ | https://www.cvedetails.com/vendor/6/Freebsd.html | | LVGL | 6.0.1 | 7.11.0 | https://lvgl.io/ | | diff --git a/test-tools/host-tool/external/cJSON/cJSON.c b/test-tools/host-tool/external/cJSON/cJSON.c index 2e35351db..830d2a346 100644 --- a/test-tools/host-tool/external/cJSON/cJSON.c +++ b/test-tools/host-tool/external/cJSON/cJSON.c @@ -1,24 +1,24 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ /* cJSON */ /* JSON parser in C. */ @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef ENABLE_LOCALES #include @@ -58,9 +59,33 @@ #include "cJSON.h" /* define our own boolean type */ +#ifdef true +#undef true +#endif #define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif #define false ((cJSON_bool)0) +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has + * been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#else +#define NAN 0.0 / 0.0 +#endif +#endif + typedef struct { const unsigned char *json; size_t position; @@ -72,7 +97,7 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) return (const char *)(global_error.json + global_error.position); } -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item) { if (!cJSON_IsString(item)) { return NULL; @@ -81,18 +106,27 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) return item->valuestring; } +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item) +{ + if (!cJSON_IsNumber(item)) { + return (double)NAN; + } + + return item->valuedouble; +} + /* This is a safeguard to prevent copy-pasters from using incompatible C and * header files */ #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) \ - || (CJSON_VERSION_PATCH != 10) + || (CJSON_VERSION_PATCH != 16) #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #endif CJSON_PUBLIC(const char *) cJSON_Version(void) { static char version[15]; - snprintf(version, sizeof(version), "%i.%i.%i", CJSON_VERSION_MAJOR, - CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, + CJSON_VERSION_PATCH); return version; } @@ -127,8 +161,8 @@ typedef struct internal_hooks { } internal_hooks; #if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dillimport '...' - is not static */ +/* work around MSVC error C2322: '...' address of dllimport '...' is not static + */ static void *CJSON_CDECL internal_malloc(size_t size) { @@ -150,13 +184,11 @@ internal_realloc(void *pointer, size_t size) #define internal_realloc realloc #endif -/* clang-format off */ -static internal_hooks global_hooks = { - internal_malloc, - internal_free, - internal_realloc -}; -/* clang-format on */ +/* strlen of character literals resolved at compile time */ +#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) + +static internal_hooks global_hooks = { internal_malloc, internal_free, + internal_realloc }; static unsigned char * cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) @@ -271,8 +303,8 @@ typedef struct { /* get a pointer to the buffer at the position */ #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) -/* Parse the input text to generate a number, and populate the result - into item. */ +/* Parse the input text to generate a number, and populate the result into item. + */ static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) { @@ -287,9 +319,8 @@ parse_number(cJSON *const item, parse_buffer *const input_buffer) } /* copy the number into a temporary buffer and replace '.' with the decimal - * point of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking - * the end of the input */ + * point of the current locale (for strtod) This also takes care of '\0' not + * necessarily being available for marking the end of the input */ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) { @@ -363,6 +394,32 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) return object->valuedouble = number; } +CJSON_PUBLIC(char *) +cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + char *copy = NULL; + /* if object's type is not cJSON_String or is cJSON_IsReference, it should + * not set valuestring */ + if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) { + return NULL; + } + if (strlen(valuestring) <= strlen(object->valuestring)) { + strcpy(object->valuestring, valuestring); + return object->valuestring; + } + copy = + (char *)cJSON_strdup((const unsigned char *)valuestring, &global_hooks); + if (copy == NULL) { + return NULL; + } + if (object->valuestring != NULL) { + cJSON_free(object->valuestring); + } + object->valuestring = copy; + + return copy; +} + typedef struct { unsigned char *buffer; size_t length; @@ -438,9 +495,8 @@ ensure(printbuffer *const p, size_t needed) return NULL; } - if (newbuffer) { - memcpy(newbuffer, p->buffer, p->offset + 1); - } + + memcpy(newbuffer, p->buffer, p->offset + 1); p->hooks.deallocate(p->buffer); } p->length = newsize; @@ -463,6 +519,14 @@ update_offset(printbuffer *const buffer) buffer->offset += strlen((const char *)buffer_pointer); } +/* securely comparison of floating-point variables */ +static cJSON_bool +compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + /* Render the number nicely from the given item into a string. */ static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer) @@ -471,35 +535,37 @@ print_number(const cJSON *const item, printbuffer *const output_buffer) double d = item->valuedouble; int length = 0; size_t i = 0; - unsigned char - number_buffer[26]; /* temporary buffer to print the number into */ + unsigned char number_buffer[26] = { + 0 + }; /* temporary buffer to print the number into */ unsigned char decimal_point = get_decimal_point(); - double test; + double test = 0.0; if (output_buffer == NULL) { return false; } /* This checks for NaN and Infinity */ - if ((d * 0) != 0) { - length = snprintf((char *)number_buffer, sizeof(number_buffer), "null"); + if (isnan(d) || isinf(d)) { + length = sprintf((char *)number_buffer, "null"); + } + else if (d == (double)item->valueint) { + length = sprintf((char *)number_buffer, "%d", item->valueint); } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero * digits */ - length = - snprintf((char *)number_buffer, sizeof(number_buffer), "%1.15g", d); + length = sprintf((char *)number_buffer, "%1.15g", d); /* Check whether the original double can be recovered */ if ((sscanf((char *)number_buffer, "%lg", &test) != 1) - || ((double)test != d)) { + || !compare_double((double)test, d)) { /* If not, print with 17 decimal places of precision */ - length = snprintf((char *)number_buffer, sizeof(number_buffer), - "%1.17g", d); + length = sprintf((char *)number_buffer, "%1.17g", d); } } - /* snprintf failed or buffer overrun occured */ + /* sprintf failed or buffer overrun occurred */ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { return false; } @@ -709,8 +775,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer) if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { - goto fail; - /* string ended unexpectedly */ + goto fail; /* string ended unexpectedly */ } /* This is at most how much we need for the output */ @@ -719,8 +784,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer) output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof("")); if (output == NULL) { - goto fail; - /* allocation failure */ + goto fail; /* allocation failure */ } } @@ -759,7 +823,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer) *output_pointer++ = input_pointer[1]; break; - /* UTF-16 literal */ + /* UTF-16 literal */ case 'u': sequence_length = utf16_literal_to_utf8( input_pointer, input_end, &output_pointer); @@ -805,7 +869,7 @@ print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer) { const unsigned char *input_pointer = NULL; - unsigned char *output = NULL, *output_end; + unsigned char *output = NULL; unsigned char *output_pointer = NULL; size_t output_length = 0; /* numbers of additional characters needed for escaping */ @@ -853,7 +917,6 @@ print_string_ptr(const unsigned char *const input, if (output == NULL) { return false; } - output_end = output + output_length + sizeof("\"\""); /* no characters have to be escaped */ if (escape_characters == 0) { @@ -902,9 +965,7 @@ print_string_ptr(const unsigned char *const input, break; default: /* escape and print as unicode codepoint */ - snprintf((char *)output_pointer, - output_end - output_pointer, "u%04x", - *input_pointer); + sprintf((char *)output_pointer, "u%04x", *input_pointer); output_pointer += 4; break; } @@ -945,6 +1006,10 @@ buffer_skip_whitespace(parse_buffer *const buffer) return NULL; } + if (cannot_access_at_index(buffer, 0)) { + return buffer; + } + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { buffer->offset++; @@ -975,10 +1040,28 @@ skip_utf8_bom(parse_buffer *const buffer) return buffer; } -/* Parse an object - create a new root, and populate. */ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + size_t buffer_length; + + if (NULL == value) { + return NULL; + } + + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen(value) + sizeof(""); + + return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, + require_null_terminated); +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, + const char **return_parse_end, + cJSON_bool require_null_terminated) { parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; cJSON *item = NULL; @@ -987,12 +1070,12 @@ cJSON_ParseWithOpts(const char *value, const char **return_parse_end, global_error.json = NULL; global_error.position = 0; - if (value == NULL) { + if (value == NULL || 0 == buffer_length) { goto fail; } buffer.content = (const unsigned char *)value; - buffer.length = strlen((const char *)value) + sizeof(""); + buffer.length = buffer_length; buffer.offset = 0; buffer.hooks = global_hooks; @@ -1056,7 +1139,13 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) return cJSON_ParseWithOpts(value, 0, 0); } -#define cjson_min(a, b) ((a < b) ? a : b) +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLength(const char *value, size_t buffer_length) +{ + return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); +} + +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) static unsigned char * print(const cJSON *const item, cJSON_bool format, @@ -1113,6 +1202,10 @@ fail: hooks->deallocate(buffer->buffer); } + if (printed != NULL) { + hooks->deallocate(printed); + } + return NULL; } @@ -1156,20 +1249,20 @@ cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) } CJSON_PUBLIC(cJSON_bool) -cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, - const cJSON_bool fmt) +cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, + const cJSON_bool format) { printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - if ((len < 0) || (buf == NULL)) { + if ((length < 0) || (buffer == NULL)) { return false; } - p.buffer = (unsigned char *)buf; - p.length = (size_t)len; + p.buffer = (unsigned char *)buffer; + p.length = (size_t)length; p.offset = 0; p.noalloc = true; - p.format = fmt; + p.format = format; p.hooks = global_hooks; return print_value(item, &p); @@ -1341,8 +1434,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer) /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { - goto fail; - /* allocation failure */ + goto fail; /* allocation failure */ } /* attach next item to list */ @@ -1361,8 +1453,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer) input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_value(current_item, input_buffer)) { - goto fail; - /* failed to parse value */ + goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); } while (can_access_at_index(input_buffer, 0) @@ -1370,13 +1461,16 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { - goto fail; - /* expected end of array */ + goto fail; /* expected end of array */ } success: input_buffer->depth--; + if (head != NULL) { + head->prev = current_item; + } + item->type = cJSON_Array; item->child = head; @@ -1461,16 +1555,14 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { - goto fail; - /* not an object */ + goto fail; /* not an object */ } input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { - goto success; - /* empty object */ + goto success; /* empty object */ } /* check if we skipped to the end of the buffer */ @@ -1486,8 +1578,7 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { - goto fail; - /* allocation failure */ + goto fail; /* allocation failure */ } /* attach next item to list */ @@ -1506,8 +1597,7 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_string(current_item, input_buffer)) { - goto fail; - /* faile to parse name */ + goto fail; /* failed to parse name */ } buffer_skip_whitespace(input_buffer); @@ -1517,16 +1607,14 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { - goto fail; - /* invalid object */ + goto fail; /* invalid object */ } /* parse the value */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_value(current_item, input_buffer)) { - goto fail; - /* failed to parse value */ + goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); } while (can_access_at_index(input_buffer, 0) @@ -1534,13 +1622,16 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { - goto fail; - /* expected end of object */ + goto fail; /* expected end of object */ } success: input_buffer->depth--; + if (head != NULL) { + head->prev = current_item; + } + item->type = cJSON_Object; item->child = head; @@ -1792,22 +1883,26 @@ add_item_to_array(cJSON *array, cJSON *item) { cJSON *child = NULL; - if ((item == NULL) || (array == NULL)) { + if ((item == NULL) || (array == NULL) || (array == item)) { return false; } child = array->child; - + /* + * To find the last item in array quickly, we use prev in array + */ if (child == NULL) { /* list is empty, start new one */ array->child = item; + item->prev = item; + item->next = NULL; } else { /* append to the end */ - while (child->next) { - child = child->next; + if (child->prev) { + suffix_object(child->prev, item); + array->child->prev = item; } - suffix_object(child, item); } return true; @@ -1847,7 +1942,8 @@ add_item_to_object(cJSON *const object, const char *const string, char *new_key = NULL; int new_type = cJSON_Invalid; - if ((object == NULL) || (string == NULL) || (item == NULL)) { + if ((object == NULL) || (string == NULL) || (item == NULL) + || (object == item)) { return false; } @@ -2028,7 +2124,7 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) return NULL; } - if (item->prev != NULL) { + if (item != parent->child) { /* not the first element */ item->prev->next = item->next; } @@ -2041,6 +2137,11 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) /* first element */ parent->child = item->next; } + else if (item->next == NULL) { + /* last element */ + parent->child->prev = item->prev; + } + /* make sure the detached item doesn't point anywhere anymore */ item->prev = NULL; item->next = NULL; @@ -2121,7 +2222,8 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement) { - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) { + if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) + || (item == NULL)) { return false; } @@ -2135,12 +2237,24 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, if (replacement->next != NULL) { replacement->next->prev = replacement; } - if (replacement->prev != NULL) { - replacement->prev->next = replacement; - } if (parent->child == item) { + if (parent->child->prev == parent->child) { + replacement->prev = replacement; + } parent->child = replacement; } + else { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was + * the parent's child + */ + if (replacement->prev != NULL) { + replacement->prev->next = replacement; + } + if (replacement->next == NULL) { + parent->child->prev = replacement; + } + } item->next = NULL; item->prev = NULL; @@ -2149,15 +2263,15 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, return true; } -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) { if (which < 0) { - return; + return false; } - cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), - newitem); + return cJSON_ReplaceItemViaPointer( + array, get_array_item(array, (size_t)which), newitem); } static cJSON_bool @@ -2175,25 +2289,27 @@ replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, } replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (replacement->string == NULL) { + return false; + } + replacement->type &= ~cJSON_StringIsConst; - cJSON_ReplaceItemViaPointer( + return cJSON_ReplaceItemViaPointer( object, get_object_item(object, string, case_sensitive), replacement); - - return true; } -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) { - replace_item_in_object(object, string, newitem, false); + return replace_item_in_object(object, string, newitem, false); } -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) { - replace_item_in_object(object, string, newitem, true); + return replace_item_in_object(object, string, newitem, true); } /* Create basic types: */ @@ -2227,11 +2343,11 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) { cJSON *item = cJSON_New_Item(&global_hooks); if (item) { - item->type = b ? cJSON_True : cJSON_False; + item->type = boolean ? cJSON_True : cJSON_False; } return item; @@ -2357,6 +2473,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) } a = cJSON_CreateArray(); + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); if (!n) { @@ -2372,6 +2489,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } @@ -2403,6 +2524,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } @@ -2434,10 +2559,15 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) +CJSON_PUBLIC(cJSON *) +cJSON_CreateStringArray(const char *const *strings, int count) { size_t i = 0; cJSON *n = NULL; @@ -2465,6 +2595,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } @@ -2532,6 +2666,9 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) } child = child->next; } + if (newitem && newitem->child) { + newitem->child->prev = newchild; + } return newitem; @@ -2543,55 +2680,93 @@ fail: return NULL; } +static void +skip_oneline_comment(char **input) +{ + *input += static_strlen("//"); + + for (; (*input)[0] != '\0'; ++(*input)) { + if ((*input)[0] == '\n') { + *input += static_strlen("\n"); + return; + } + } +} + +static void +skip_multiline_comment(char **input) +{ + *input += static_strlen("/*"); + + for (; (*input)[0] != '\0'; ++(*input)) { + if (((*input)[0] == '*') && ((*input)[1] == '/')) { + *input += static_strlen("*/"); + return; + } + } +} + +static void +minify_string(char **input, char **output) +{ + (*output)[0] = (*input)[0]; + *input += static_strlen("\""); + *output += static_strlen("\""); + + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { + (*output)[0] = (*input)[0]; + + if ((*input)[0] == '\"') { + (*output)[0] = '\"'; + *input += static_strlen("\""); + *output += static_strlen("\""); + return; + } + else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { + (*output)[1] = (*input)[1]; + *input += static_strlen("\""); + *output += static_strlen("\""); + } + } +} + CJSON_PUBLIC(void) cJSON_Minify(char *json) { - unsigned char *into = (unsigned char *)json; + char *into = json; if (json == NULL) { return; } - while (*json) { - if (*json == ' ') { - json++; - } - else if (*json == '\t') { - /* Whitespace characters. */ - json++; - } - else if (*json == '\r') { - json++; - } - else if (*json == '\n') { - json++; - } - else if ((*json == '/') && (json[1] == '/')) { - /* double-slash comments, to end of line. */ - while (*json && (*json != '\n')) { + while (json[0] != '\0') { + switch (json[0]) { + case ' ': + case '\t': + case '\r': + case '\n': json++; - } - } - else if ((*json == '/') && (json[1] == '*')) { - /* multiline comments. */ - while (*json && !((*json == '*') && (json[1] == '/'))) { - json++; - } - json += 2; - } - else if (*json == '\"') { - /* string literals, which are \" sensitive. */ - *into++ = (unsigned char)*json++; - while (*json && (*json != '\"')) { - if (*json == '\\') { - *into++ = (unsigned char)*json++; + break; + + case '/': + if (json[1] == '/') { + skip_oneline_comment(&json); } - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - else { - /* All other characters. */ - *into++ = (unsigned char)*json++; + else if (json[1] == '*') { + skip_multiline_comment(&json); + } + else { + json++; + } + break; + + case '\"': + minify_string(&json, (char **)&into); + break; + + default: + into[0] = json[0]; + json++; + into++; } } @@ -2692,8 +2867,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) { - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) - || cJSON_IsInvalid(a)) { + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { return false; } @@ -2726,7 +2900,7 @@ cJSON_Compare(const cJSON *const a, const cJSON *const b, return true; case cJSON_Number: - if (a->valuedouble == b->valuedouble) { + if (compare_double(a->valuedouble, b->valuedouble)) { return true; } return false; diff --git a/test-tools/host-tool/external/cJSON/cJSON.h b/test-tools/host-tool/external/cJSON/cJSON.h index d437196a3..2cafdcf59 100644 --- a/test-tools/host-tool/external/cJSON/cJSON.h +++ b/test-tools/host-tool/external/cJSON/cJSON.h @@ -1,24 +1,24 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ #ifndef cJSON__h #define cJSON__h @@ -35,30 +35,34 @@ extern "C" { #ifdef __WINDOWS__ -/** - * When compiling for windows, we specify a specific calling convention to avoid - * issues where we are being called from a project with a different default - * calling convention. For windows you have 3 define options: - * CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever - * dllexport symbols - * CJSON_EXPORT_SYMBOLS - Define this on library build when you want to - * dllexport symbols (default) - * CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol - * - * For *nix builds that support visibility attribute, you can define similar - * behavior by setting default visibility to hidden by adding - * -fvisibility=hidden (for gcc) - * or - * -xldscope=hidden (for sun cc) - * to CFLAGS, then using the CJSON_API_VISIBILITY flag to "export" the same - * symbols the way CJSON_EXPORT_SYMBOLS does - */ +/* When compiling for windows, we specify a specific calling convention to avoid +issues where we are being called from a project with a different default calling +convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever +dllexport symbols CJSON_EXPORT_SYMBOLS - Define this on library build when you +want to dllexport symbols (default) CJSON_IMPORT_SYMBOLS - Define this if you +want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar +behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way +CJSON_EXPORT_SYMBOLS does + +*/ #define CJSON_CDECL __cdecl #define CJSON_STDCALL __stdcall /* export symbols by default, this is necessary for copy pasting the C and - header file */ + * header file */ #if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) \ && !defined(CJSON_EXPORT_SYMBOLS) #define CJSON_EXPORT_SYMBOLS @@ -86,7 +90,7 @@ extern "C" { /* project version */ #define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 10 +#define CJSON_VERSION_PATCH 16 #include @@ -107,11 +111,11 @@ extern "C" { /* The cJSON structure: */ typedef struct cJSON { /* next/prev allow you to walk array/object chains. Alternatively, use - GetArraySize/GetArrayItem/GetObjectItem */ + * GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; /* An array or object item will have a child pointer pointing to a chain of - the items in the array/object. */ + * the items in the array/object. */ struct cJSON *child; /* The type of the item, as above. */ @@ -125,7 +129,7 @@ typedef struct cJSON { double valuedouble; /* The item's name string, if this item is the child of, or is in the list - of subitems of an object. */ + * of subitems of an object. */ char *string; } cJSON; @@ -140,7 +144,7 @@ typedef struct cJSON_Hooks { typedef int cJSON_bool; /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse - them. This is to prevent stack overflows. */ + * them. This is to prevent stack overflows. */ #ifndef CJSON_NESTING_LIMIT #define CJSON_NESTING_LIMIT 1000 #endif @@ -159,6 +163,8 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks); /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLength(const char *value, size_t buffer_length); /* ParseWithOpts allows you to require (and check) that the JSON is null * terminated, and to retrieve the pointer to the final byte parsed. */ /* If you supply a ptr in return_parse_end and parsing fails, then @@ -167,6 +173,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, + const char **return_parse_end, + cJSON_bool require_null_terminated); /* Render a cJSON entity to text for transfer/storage. */ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); @@ -185,7 +195,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); /* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); /* Returns the number of items in an array (or object). */ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); @@ -205,8 +215,9 @@ cJSON_HasObjectItem(const cJSON *object, const char *string); * when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); -/* Check if the item is a string and return its valuestring */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item); /* These functions check the type of an item */ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item); @@ -233,18 +244,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); /* Create a string where valuestring references a string so - it will not be freed by cJSON_Delete */ + * it will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); -/* Create an object/arrray that only references it's elements so - they will not be freed by cJSON_Delete */ +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); -/* These utilities create an Array of count items. */ +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the + * number array, otherwise array access will be out of bounds.*/ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); +CJSON_PUBLIC(cJSON *) +cJSON_CreateStringArray(const char *const *strings, int count); /* Append item to the specified array/object. */ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); @@ -264,7 +278,7 @@ cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); -/* Remove/Detatch items from Arrays/Objects. */ +/* Remove/Detach items from Arrays/Objects. */ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); @@ -286,32 +300,35 @@ cJSON_InsertItemInArray( CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement); -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem); /* Duplicate a cJSON item */ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); /* Duplicate will create a new, identical cJSON item to the one you pass, in new - memory that will need to be released. With recurse!=0, it will duplicate any - children connected to the item. The item->next and ->prev pointers are always - zero on return from Duplicate. */ + * memory that will need to be released. With recurse!=0, it will duplicate any + * children connected to the item. The item->next and ->prev pointers are always + * zero on return from Duplicate. */ /* Recursively compare two cJSON items for equality. If either a or b is NULL or - * invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or - * case insensitive (0) */ + * invalid, they will be considered unequal. case_sensitive determines if object + * keys are treated case sensitive (1) or case insensitive (0) */ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive); +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from + * strings. The input pointer json cannot point to a read-only address area, + * such as a string constant, but should point to a readable and writable + * address area. */ CJSON_PUBLIC(void) cJSON_Minify(char *json); /* Helper functions for creating and adding items to an object at the same time. - They return the added item or NULL on failure. */ + * They return the added item or NULL on failure. */ CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name); CJSON_PUBLIC(cJSON *) @@ -336,7 +353,7 @@ CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name); /* When assigning an integer value, it needs to be propagated to valuedouble - too. */ + * too. */ #define cJSON_SetIntValue(object, number) \ ((object) ? (object)->valueint = (object)->valuedouble = (number) \ : (number)) @@ -345,6 +362,18 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); #define cJSON_SetNumberValue(object, number) \ ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) \ : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type + * of object is cJSON_String */ +CJSON_PUBLIC(char *) +cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* If the object is not a boolean type this does nothing and returns + * cJSON_Invalid else it returns the new type*/ +#define cJSON_SetBoolValue(object, boolValue) \ + ((object != NULL && ((object)->type & (cJSON_False | cJSON_True))) \ + ? (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) \ + | ((boolValue) ? cJSON_True : cJSON_False) \ + : cJSON_Invalid) /* Macro for iterating over an array or object */ #define cJSON_ArrayForEach(element, array) \ @@ -352,7 +381,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); element = element->next) /* malloc/free objects using the malloc/free functions that have been set with - cJSON_InitHooks */ + * cJSON_InitHooks */ CJSON_PUBLIC(void *) cJSON_malloc(size_t size); CJSON_PUBLIC(void) cJSON_free(void *object); From edea32b6291c2b39b21db210149e5f414faf46c9 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 31 Jul 2023 18:20:11 +0800 Subject: [PATCH 035/123] Fix result arity check on select_t opcode (#2406) Typed select must have exactly one result. Reported in issue #2402. --- core/iwasm/interpreter/wasm_loader.c | 3 ++- core/iwasm/interpreter/wasm_mini_loader.c | 3 ++- .../spec-test-script/ignore_cases.patch | 20 ------------------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index f1a71a8ab..08441ec3e 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -8066,7 +8066,8 @@ re_scan: uint8 vec_len, ref_type; read_leb_uint32(p, p_end, vec_len); - if (!vec_len) { + if (vec_len != 1) { + /* typed select must have exactly one result */ set_error_buf(error_buf, error_buf_size, "invalid result arity"); goto fail; diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index fc637a5a1..0aba14626 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -6235,7 +6235,8 @@ re_scan: uint8 vec_len, ref_type; read_leb_uint32(p, p_end, vec_len); - if (!vec_len) { + if (vec_len != 1) { + /* typed select must have exactly one result */ set_error_buf(error_buf, error_buf_size, "invalid result arity"); goto fail; diff --git a/tests/wamr-test-suites/spec-test-script/ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/ignore_cases.patch index 1d94d91af..bfb4383f7 100644 --- a/tests/wamr-test-suites/spec-test-script/ignore_cases.patch +++ b/tests/wamr-test-suites/spec-test-script/ignore_cases.patch @@ -343,26 +343,6 @@ index adb5cb7..590f626 100644 (func $g (param $x i32) (result i32) (i32.add (local.get $x) (i32.const 1)) ) -diff --git a/test/core/select.wast b/test/core/select.wast -index 046e6fe..b677023 100644 ---- a/test/core/select.wast -+++ b/test/core/select.wast -@@ -324,6 +324,7 @@ - (module (func $arity-0 (select (result) (nop) (nop) (i32.const 1)))) - "invalid result arity" - ) -+(; - (assert_invalid - (module (func $arity-2 (result i32 i32) - (select (result i32 i32) -@@ -334,6 +335,7 @@ - )) - "invalid result arity" - ) -+;) - - - (assert_invalid diff --git a/test/core/table_copy.wast b/test/core/table_copy.wast index 380e84e..f37e745 100644 --- a/test/core/table_copy.wast From 84ecf1532224a52c2db74355289aadead7890d49 Mon Sep 17 00:00:00 2001 From: Cengizhan Pasaoglu Date: Mon, 31 Jul 2023 13:32:20 +0300 Subject: [PATCH 036/123] Update libuv version to v1.46.0 (#2405) --- ATTRIBUTIONS.md | 2 +- core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index ef788bf73..c772b9691 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -31,7 +31,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the | wasmtime | unspecified | v0.26.0 | https://github.com/bytecodealliance/wasmtime | | | zephyr | unspecified | v2.5.0 | https://www.zephyrproject.org/ | https://www.cvedetails.com/vendor/19255/Zephyrproject.html | | WebAssembly debugging patch for LLDB | unspecified | unspecified | https://reviews.llvm.org/D78801 | | -| libuv | v1.42.0 | v1.44.1 | https://github.com/libuv/libuv | https://www.cvedetails.com/vendor/15402/Libuv-Project.html | +| libuv | v1.46.0 | v1.46.0 | https://github.com/libuv/libuv | https://www.cvedetails.com/vendor/15402/Libuv-Project.html | | uvwasi | unspecified | v0.0.12 | https://github.com/nodejs/uvwasi | | | asmjit | unspecified | unspecified | https://github.com/asmjit/asmjit | | | zydis | unspecified | e14a07895136182a5b53e181eec3b1c6e0b434de | https://github.com/zyantific/zydis | | diff --git a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake index 6614df503..7a3bfbdce 100644 --- a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake +++ b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake @@ -3,7 +3,7 @@ set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR}) -set (LIBUV_VERSION v1.44.2) +set (LIBUV_VERSION v1.46.0) add_definitions (-DWASM_ENABLE_LIBC_WASI=1 -DWASM_ENABLE_UVWASI=1) From 851819705324419376a63c23fe2e5acb17ce9d8c Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 31 Jul 2023 20:14:44 +0900 Subject: [PATCH 037/123] Remove a few unused functions (#2409) They have been unused since commit 5fc48e3584baa05514878997b6949e365626f977 --- core/iwasm/common/wasm_memory.c | 36 --------------------------------- core/iwasm/common/wasm_memory.h | 10 --------- 2 files changed, 46 deletions(-) diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index b2ec2a897..9db7fa141 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -782,39 +782,3 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) return ret; } - -#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ - || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ - || WASM_ENABLE_BULK_MEMORY != 0 -uint32 -wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node) -{ - uint32 num_bytes_per_page; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock); -#endif - num_bytes_per_page = memory->num_bytes_per_page; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock); -#endif - return num_bytes_per_page; -} - -uint32 -wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node) -{ - uint32 linear_mem_size; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock); -#endif - linear_mem_size = memory->num_bytes_per_page * memory->cur_page_count; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock); -#endif - return linear_mem_size; -} -#endif diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index 1324742fe..516ee8497 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/core/iwasm/common/wasm_memory.h @@ -24,16 +24,6 @@ wasm_runtime_memory_destroy(); unsigned wasm_runtime_memory_pool_size(); -#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ - || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ - || WASM_ENABLE_BULK_MEMORY != 0 -uint32 -wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node); - -uint32 -wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node); -#endif - #ifdef __cplusplus } #endif From 4b1f027690bba0069c825807d7f9493c53fa83ca Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 1 Aug 2023 17:28:57 +0800 Subject: [PATCH 038/123] Re-organize intrinsics in aot_reloc_riscv.c to fix some FPU issues (#2414) --- core/iwasm/aot/arch/aot_reloc_riscv.c | 34 ++++++++++++--------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/core/iwasm/aot/arch/aot_reloc_riscv.c b/core/iwasm/aot/arch/aot_reloc_riscv.c index 219319020..7798d55c6 100644 --- a/core/iwasm/aot/arch/aot_reloc_riscv.c +++ b/core/iwasm/aot/arch/aot_reloc_riscv.c @@ -78,6 +78,13 @@ static SymbolMap target_sym_map[] = { REG_SYM(__addsf3), REG_SYM(__divdf3), REG_SYM(__divsf3), + REG_SYM(__eqdf2), + REG_SYM(__eqsf2), + REG_SYM(__extendsfdf2), + REG_SYM(__fixunsdfdi), + REG_SYM(__fixunsdfsi), + REG_SYM(__fixunssfdi), + REG_SYM(__fixunssfsi), REG_SYM(__gedf2), REG_SYM(__gesf2), REG_SYM(__gtdf2), @@ -89,44 +96,33 @@ static SymbolMap target_sym_map[] = { REG_SYM(__muldf3), REG_SYM(__nedf2), REG_SYM(__nesf2), - REG_SYM(__eqsf2), - REG_SYM(__eqdf2), - REG_SYM(__extendsfdf2), - REG_SYM(__fixunsdfdi), - REG_SYM(__fixunsdfsi), - REG_SYM(__fixunssfsi), REG_SYM(__subdf3), REG_SYM(__subsf3), REG_SYM(__truncdfsf2), REG_SYM(__unorddf2), REG_SYM(__unordsf2), -#endif - REG_SYM(__divdi3), - REG_SYM(__divsi3), #if __riscv_xlen == 32 REG_SYM(__fixdfdi), REG_SYM(__fixdfsi), REG_SYM(__fixsfdi), REG_SYM(__fixsfsi), -#endif - REG_SYM(__fixunssfdi), -#if __riscv_xlen == 32 REG_SYM(__floatdidf), REG_SYM(__floatdisf), - REG_SYM(__floatsisf), REG_SYM(__floatsidf), + REG_SYM(__floatsisf), REG_SYM(__floatundidf), REG_SYM(__floatundisf), - REG_SYM(__floatunsisf), REG_SYM(__floatunsidf), -#endif - REG_SYM(__moddi3), - REG_SYM(__modsi3), - REG_SYM(__muldi3), -#if __riscv_xlen == 32 + REG_SYM(__floatunsisf), REG_SYM(__mulsf3), REG_SYM(__mulsi3), #endif +#endif + REG_SYM(__divdi3), + REG_SYM(__divsi3), + REG_SYM(__moddi3), + REG_SYM(__modsi3), + REG_SYM(__muldi3), REG_SYM(__udivdi3), REG_SYM(__udivsi3), REG_SYM(__umoddi3), From b88f2c06c66a24eb40e12508ce3ea9cc2754b035 Mon Sep 17 00:00:00 2001 From: Maks Litskevich Date: Tue, 1 Aug 2023 10:38:37 +0100 Subject: [PATCH 039/123] Add initial stress test (#2364) We need to make a test that runs longer than the tests we had before to check some problems that might happen after running for some time (e.g. memory corruption or something else). --- .../compilation_on_android_ubuntu.yml | 4 +- .github/workflows/nightly_run.yml | 4 +- .../libraries/lib-wasi-threads/test/build.sh | 5 +- .../lib-wasi-threads/test/manifest.json | 3 + .../libraries/lib-wasi-threads/test/skip.json | 5 + .../lib-wasi-threads/test/spawn_stress_test.c | 114 ++++++++++++++++++ .../wasi-test-script/run_wasi_tests.sh | 40 ++++-- 7 files changed, 161 insertions(+), 14 deletions(-) create mode 100644 core/iwasm/libraries/lib-wasi-threads/test/manifest.json create mode 100644 core/iwasm/libraries/lib-wasi-threads/test/skip.json create mode 100644 core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index f965d2006..5a0939b73 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -527,7 +527,7 @@ jobs: working-directory: ./core/iwasm/libraries/lib-socket/test/ - name: run tests - timeout-minutes: 10 + timeout-minutes: 20 run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites @@ -543,7 +543,7 @@ jobs: sudo apt install -y g++-multilib lib32gcc-9-dev - name: run tests x86_32 - timeout-minutes: 10 + timeout-minutes: 20 if: env.TEST_ON_X86_32 == 'true' run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index 4664ad636..cea5dccb1 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -595,7 +595,7 @@ jobs: working-directory: ./core/iwasm/libraries/lib-socket/test/ - name: run tests - timeout-minutes: 10 + timeout-minutes: 20 run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites @@ -611,7 +611,7 @@ jobs: sudo apt install -y g++-multilib lib32gcc-9-dev - name: run tests x86_32 - timeout-minutes: 10 + timeout-minutes: 20 if: env.TEST_ON_X86_32 == 'true' run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites \ No newline at end of file diff --git a/core/iwasm/libraries/lib-wasi-threads/test/build.sh b/core/iwasm/libraries/lib-wasi-threads/test/build.sh index 32586c20c..611a3bd43 100755 --- a/core/iwasm/libraries/lib-wasi-threads/test/build.sh +++ b/core/iwasm/libraries/lib-wasi-threads/test/build.sh @@ -9,10 +9,13 @@ set -eo pipefail CC=${CC:=/opt/wasi-sdk/bin/clang} WAMR_DIR=../../../../.. +# Stress tests names +thread_start_file_exclusions=("spawn_stress_test.wasm" "linear_memory_size_update.wasm") + for test_c in *.c; do test_wasm="$(basename $test_c .c).wasm" - if [ $test_wasm = "linear_memory_size_update.wasm" ]; then + if [[ " ${thread_start_file_exclusions[@]} " =~ " ${test_wasm} " ]] ; then thread_start_file="" else thread_start_file=$WAMR_DIR/samples/wasi-threads/wasm-apps/wasi_thread_start.S diff --git a/core/iwasm/libraries/lib-wasi-threads/test/manifest.json b/core/iwasm/libraries/lib-wasi-threads/test/manifest.json new file mode 100644 index 000000000..cd2cc7636 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/test/manifest.json @@ -0,0 +1,3 @@ +{ + "name": "lib-wasi-threads tests" +} diff --git a/core/iwasm/libraries/lib-wasi-threads/test/skip.json b/core/iwasm/libraries/lib-wasi-threads/test/skip.json new file mode 100644 index 000000000..87db7667c --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/test/skip.json @@ -0,0 +1,5 @@ +{ + "lib-wasi-threads tests": { + "spawn_stress_test": "Stress tests are incompatible with the other part and executed differently" + } +} diff --git a/core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c new file mode 100644 index 000000000..35175fc3e --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef __wasi__ +#error This example only compiles to WASM/WASI target +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +enum CONSTANTS { + NUM_ITER = 100000, + NUM_RETRY = 5, + MAX_NUM_THREADS = 8, +}; + +unsigned prime_numbers_count = 0; + +bool +is_prime(unsigned int num) +{ + for (unsigned int i = 2; i <= (unsigned int)(sqrt(num)); ++i) { + if (num % i == 0) { + return false; + } + } + + return true; +} + +void * +check_if_prime(void *value) +{ + unsigned int *num = (unsigned int *)(value); + usleep(10000); + if (is_prime(*num)) { + __atomic_fetch_add(&prime_numbers_count, 1, __ATOMIC_SEQ_CST); + } + return NULL; +} + +unsigned int +validate() +{ + unsigned int counter = 0; + for (unsigned int i = 2; i <= NUM_ITER; ++i) { + counter += is_prime(i); + } + + return counter; +} + +void +spawn_thread(pthread_t *thread, unsigned int *arg) +{ + int status_code = -1; + for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) { + status_code = pthread_create(thread, NULL, &check_if_prime, arg); + assert(status_code == 0 || status_code == EAGAIN); + if (status_code == EAGAIN) { + usleep(2000); + } + } + + assert(status_code == 0 && "Thread creation should succeed"); +} + +int +main(int argc, char **argv) +{ + pthread_t threads[MAX_NUM_THREADS]; + unsigned int args[MAX_NUM_THREADS]; + double percentage = 0.1; + + for (unsigned int factorised_number = 2; factorised_number < NUM_ITER; + ++factorised_number) { + if (factorised_number > NUM_ITER * percentage) { + fprintf(stderr, "Stress test is %d%% finished\n", + (unsigned int)(percentage * 100)); + percentage += 0.1; + } + + unsigned int thread_num = factorised_number % MAX_NUM_THREADS; + if (threads[thread_num] != 0) { + assert(pthread_join(threads[thread_num], NULL) == 0); + } + + args[thread_num] = factorised_number; + + usleep(2000); + spawn_thread(&threads[thread_num], &args[thread_num]); + assert(threads[thread_num] != 0); + } + + for (int i = 0; i < MAX_NUM_THREADS; ++i) { + assert(threads[i] == 0 || pthread_join(threads[i], NULL) == 0); + } + + // Check the test results + assert( + prime_numbers_count == validate() + && "Answer mismatch between tested code and reference implementation"); + + fprintf(stderr, "Stress test finished successfully\n"); + return 0; +} diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index 7738b5080..9f13ee086 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -14,6 +14,7 @@ readonly WAMR_DIR="${WORK_DIR}/../../../.." readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm \ --allow-resolve=google-public-dns-a.google.com \ --addr-pool=::1/128,127.0.0.1/32" +readonly IWASM_CMD_STRESS="${IWASM_CMD} --max-threads=8" readonly WAMRC_CMD="${WORK_DIR}/../../../../wamr-compiler/build/wamrc" readonly C_TESTS="tests/c/testsuite/" readonly ASSEMBLYSCRIPT_TESTS="tests/assemblyscript/testsuite/" @@ -24,6 +25,11 @@ readonly LIB_SOCKET_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-socket/test/" run_aot_tests () { local tests=("$@") for test_wasm in ${tests[@]}; do + local extra_stress_flags="" + if [[ "$test_wasm" =~ "stress" ]]; then + extra_stress_flags="--max-threads=8" + fi + test_aot="${test_wasm%.wasm}.aot" test_json="${test_wasm%.wasm}.json" @@ -41,7 +47,7 @@ run_aot_tests () { expected=$(jq .exit_code ${test_json}) fi - ${IWASM_CMD} $test_aot + ${IWASM_CMD} $extra_stress_flags $test_aot ret=${PIPESTATUS[0]} @@ -55,15 +61,31 @@ run_aot_tests () { if [[ $MODE != "aot" ]];then python3 -m venv wasi-env && source wasi-env/bin/activate python3 -m pip install -r test-runner/requirements.txt + + # Stress test requires max-threads=8 so it's run separately + if [[ -e "${THREAD_INTERNAL_TESTS}spawn_stress_test.wasm" ]]; then + ${IWASM_CMD_STRESS} ${THREAD_INTERNAL_TESTS}spawn_stress_test.wasm + ret=${PIPESTATUS[0]} + if [ "${ret}" -ne 0 ]; then + echo "Stress test spawn_stress_test FAILED with code " ${ret} + exit_code=${ret} + fi + fi + TEST_RUNTIME_EXE="${IWASM_CMD}" python3 test-runner/wasi_test_runner.py \ - -r adapters/wasm-micro-runtime.py \ - -t \ - ${C_TESTS} \ - ${ASSEMBLYSCRIPT_TESTS} \ - ${THREAD_PROPOSAL_TESTS} \ - ${THREAD_INTERNAL_TESTS} \ - ${LIB_SOCKET_TESTS} - exit_code=${PIPESTATUS[0]} + -r adapters/wasm-micro-runtime.py \ + -t \ + ${C_TESTS} \ + ${ASSEMBLYSCRIPT_TESTS} \ + ${THREAD_PROPOSAL_TESTS} \ + ${THREAD_INTERNAL_TESTS} \ + ${LIB_SOCKET_TESTS} \ + --exclude-filter "${THREAD_INTERNAL_TESTS}skip.json" + + ret=${PIPESTATUS[0]} + if [ "${ret}" -ne 0 ]; then + exit_code=${ret} + fi deactivate else target_option="" From cb6d85069ece487d50a64cf08b4f82e5b3deeba9 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 1 Aug 2023 18:11:58 +0800 Subject: [PATCH 040/123] Fix lib-pthread issues (#2410) - Avoid destroying module instance repeatedly in pthread_exit_wrapper and wasm_thread_cluster_exit. - Wait enough time in pthread_join_wrapper for target thread to exit and destroy its resources. --- .../libraries/lib-pthread/lib_pthread_wrapper.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index 8876d51b4..1a41fe9d7 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -691,6 +691,14 @@ pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread, bh_assert(node->joinable); join_ret = 0; ret = node->u.ret; + + /* The target thread changes the node's status before calling + wasm_cluster_exit_thread to exit, so here its resources may + haven't been destroyed yet, we wait enough time to ensure that + they are actually destroyed to avoid unexpected behavior. */ + os_mutex_lock(&exec_env->wait_lock); + os_cond_reltimedwait(&exec_env->wait_cond, &exec_env->wait_lock, 1000); + os_mutex_unlock(&exec_env->wait_lock); } if (retval_offset != 0) @@ -758,7 +766,6 @@ __pthread_self_wrapper(wasm_exec_env_t exec_env) static void pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); ThreadRoutineArgs *args = get_thread_arg(exec_env); /* Currently exit main thread is not allowed */ if (!args) @@ -776,9 +783,6 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset) /* destroy pthread key values */ call_key_destructor(exec_env); - /* routine exit, destroy instance */ - wasm_runtime_deinstantiate_internal(module_inst, true); - if (!args->info_node->joinable) { delete_thread_info_node(args->info_node); } @@ -790,6 +794,8 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset) wasm_runtime_free(args); + /* Don't destroy exec_env->module_inst in this functuntion since + it will be destroyed in wasm_cluster_exit_thread */ wasm_cluster_exit_thread(exec_env, (void *)(uintptr_t)retval_offset); } From ecd4fccc964653b006515153ab5df81f1618cb40 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Tue, 1 Aug 2023 19:13:00 +0800 Subject: [PATCH 041/123] Upgrade XNNPACK workload (#2394) - Sync source code to b9d4073a6913891ce9cbd8965c8d506075d2a45a, which is referred by tensorflow - Upgrade emscripten to 3.1.44 - CMake outputs are .wasm files and .aot files --- samples/workload/XNNPACK/CMakeLists.txt | 315 ++++++++++++++---------- samples/workload/XNNPACK/README.md | 51 ++-- samples/workload/XNNPACK/xnnpack.patch | 193 +++++++-------- 3 files changed, 304 insertions(+), 255 deletions(-) diff --git a/samples/workload/XNNPACK/CMakeLists.txt b/samples/workload/XNNPACK/CMakeLists.txt index aef138d5e..93181cd99 100644 --- a/samples/workload/XNNPACK/CMakeLists.txt +++ b/samples/workload/XNNPACK/CMakeLists.txt @@ -1,147 +1,198 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 3.14) project(xnnpack_wasm) ################ EMCC ################ include(ExternalProject) -ExternalProject_Add(xnnpack +# grep xnnpack_benchmark -A 1 BUILD.bazel \ +# | grep "name =" \ +# | awk '{print $3}' \ +# | sed -e 's/\"//g; s/,//g; s/^/\"/g; s/$/\"/g' +list(APPEND NATIVE_BENCHMARKS + "qs8_dwconv_bench" + "qs8_f32_vcvt_bench" + "qs8_gemm_bench" + "qs8_requantization_bench" + "qs8_vadd_bench" + "qs8_vaddc_bench" + "qs8_vcvt_bench" + "qs16_qs8_vcvt_bench" + "qs8_vlrelu_bench" + "qs8_vmul_bench" + "qs8_vmulc_bench" + "qu8_f32_vcvt_bench" + "qu8_gemm_bench" + "qu8_requantization_bench" + "qu8_vadd_bench" + "qu8_vaddc_bench" + "qu8_vcvt_bench" + "qu8_vlrelu_bench" + "qu8_vmul_bench" + "qu8_vmulc_bench" + "bf16_gemm_bench" + "f16_f32acc_igemm_bench" + "f16_igemm_bench" + "f16_f32acc_gemm_bench" + "f16_gemm_bench" + "f16_raddstoreexpminusmax_bench" + "f16_spmm_bench" + "f16_vsigmoid_bench" + "f16_vtanh_bench" + "f16_f32_vcvt_bench" + "f32_igemm_bench" + "f32_conv_hwc_bench" + "f16_conv_hwc2chw_bench" +# "f16_gavgpool_cw_bench" +# "f32_gavgpool_cw_bench" + "f32_conv_hwc2chw_bench" + "f16_dwconv_bench" + "f32_dwconv_bench" + "f32_dwconv2d_chw_bench" + "f16_dwconv2d_chw_bench" + "f32_f16_vcvt_bench" + "xx_transpose_bench" + "x8_transpose_bench" + "x16_transpose_bench" + "x24_transpose_bench" + "x32_transpose_bench" + "x64_transpose_bench" + "f32_bgemm_bench" + "f32_gemm_bench" + "f32_qs8_vcvt_bench" + "f32_qu8_vcvt_bench" + "f32_raddexpminusmax_bench" + "f32_raddextexp_bench" + "f32_raddstoreexpminusmax_bench" + "f32_rmax_bench" + "f32_spmm_bench" + "f32_softmax_bench" + "f16_velu_bench" + "f32_velu_bench" + "f32_vhswish_bench" + "f32_vlrelu_bench" + "f32_vrelu_bench" + "f32_vscaleexpminusmax_bench" + "f32_vscaleextexp_bench" + "f32_vsigmoid_bench" + "f16_vsqrt_bench" + "f32_vsqrt_bench" + "f32_vtanh_bench" + "f32_im2col_gemm_bench" + "rounding_bench" + "s16_rmaxabs_bench" + "s16_window_bench" + "u32_filterbank_accumulate_bench" + "u32_filterbank_subtract_bench" + "u32_vlog_bench" + "u64_u32_vsqrtshift_bench" + "i16_vlshift_bench" + "cs16_vsquareabs_bench" + "cs16_bfly4_bench" + "cs16_fftr_bench" + "x8_lut_bench" + "x32_packw_bench" + "x16_packw_bench" + "abs_bench" + "average_pooling_bench" + "bankers_rounding_bench" + "ceiling_bench" + "channel_shuffle_bench" + "convert_bench" + "convolution_bench" + "deconvolution_bench" + "elu_bench" + "floor_bench" + "global_average_pooling_bench" + "hardswish_bench" + "leaky_relu_bench" + "max_pooling_bench" + "negate_bench" + "prelu_bench" + "sigmoid_bench" + "softmax_bench" + "square_bench" + "square_root_bench" + "tanh_bench" + "truncation_bench" + "f16_dwconv_e2e_bench" + "f16_gemm_e2e_bench" + "f32_dwconv_e2e_bench" + "f32_gemm_e2e_bench" + "qs8_dwconv_e2e_bench" + "qs8_gemm_e2e_bench" + "qu8_gemm_e2e_bench" + "qu8_dwconv_e2e_bench" +# "end2end_bench" + "f16_exp_ulp_eval" + "f16_expminus_ulp_eval" + "f16_expm1minus_ulp_eval" + "f16_sigmoid_ulp_eval" + "f16_sqrt_ulp_eval" + "f16_tanh_ulp_eval" + "f32_exp_ulp_eval" + "f32_expminus_ulp_eval" + "f32_expm1minus_ulp_eval" + "f32_extexp_ulp_eval" + "f32_sigmoid_ulp_eval" + "f32_sqrt_ulp_eval" + "f32_tanh_ulp_eval" +) + +# Only Download +ExternalProject_Add(xnnpack-download PREFIX xnnpack GIT_REPOSITORY https://github.com/google/XNNPACK.git - GIT_TAG 4570a7151aa4f3e57eca14a575eeff6bb13e26be + GIT_TAG b9d4073a6913891ce9cbd8965c8d506075d2a45a GIT_PROGRESS ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack - UPDATE_COMMAND git restore . - && cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/google3/third_party/XNNPACK/microkernels.bzl - ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/ - && git apply ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack.patch + UPDATE_COMMAND "" + PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack.patch CONFIGURE_COMMAND "" - # grep xnnpack_benchmark -A 1 BUILD.bazel \ - # | grep "name =" \ - # | awk '{print $3}' \ - # | sed -e 's/\"//g' -e 's/,//g' -e 's/^/\/\/:/g' - BUILD_COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack - && bazel --output_user_root=build-user-output build -c opt --config=wasm - //:qs8_dwconv_bench.wasm - //:qs8_f32_vcvt_bench.wasm - //:qs8_gemm_bench.wasm - //:qs8_requantization_bench.wasm - //:qs8_vadd_bench.wasm - //:qs8_vaddc_bench.wasm - //:qs8_vcvt_bench.wasm - //:qs8_vlrelu_bench.wasm - //:qs8_vmul_bench.wasm - //:qs8_vmulc_bench.wasm - //:qu8_f32_vcvt_bench.wasm - //:qu8_gemm_bench.wasm - //:qu8_requantization_bench.wasm - //:qu8_vadd_bench.wasm - //:qu8_vaddc_bench.wasm - //:qu8_vcvt_bench.wasm - //:qu8_vlrelu_bench.wasm - //:qu8_vmul_bench.wasm - //:qu8_vmulc_bench.wasm - //:bf16_gemm_bench.wasm - //:f16_igemm_bench.wasm - //:f16_gemm_bench.wasm - //:f16_raddstoreexpminusmax_bench.wasm - //:f16_spmm_bench.wasm - //:f16_vsigmoid_bench.wasm - //:f16_f32_vcvt_bench.wasm - //:f32_igemm_bench.wasm - //:f32_conv_hwc_bench.wasm - //:f16_conv_hwc2chw_bench.wasm - //:f16_gavgpool_cw_bench.wasm - //:f32_gavgpool_cw_bench.wasm - //:f32_conv_hwc2chw_bench.wasm - //:f16_dwconv_bench.wasm - //:f32_dwconv_bench.wasm - //:f32_dwconv2d_chw_bench.wasm - //:f16_dwconv2d_chw_bench.wasm - //:f32_f16_vcvt_bench.wasm - //:xx_transpose_bench.wasm - //:x8_transpose_bench.wasm - //:x16_transpose_bench.wasm - //:x24_transpose_bench.wasm - //:x32_transpose_bench.wasm - //:x64_transpose_bench.wasm - //:f32_gemm_bench.wasm - //:f32_qs8_vcvt_bench.wasm - //:f32_qu8_vcvt_bench.wasm - //:f32_raddexpminusmax_bench.wasm - //:f32_raddextexp_bench.wasm - //:f32_raddstoreexpminusmax_bench.wasm - //:f32_rmax_bench.wasm - //:f32_spmm_bench.wasm - //:f32_softmax_bench.wasm - //:f16_velu_bench.wasm - //:f32_velu_bench.wasm - //:f32_vhswish_bench.wasm - //:f32_vlrelu_bench.wasm - //:f32_vrelu_bench.wasm - //:f32_vscaleexpminusmax_bench.wasm - //:f32_vscaleextexp_bench.wasm - //:f32_vsigmoid_bench.wasm - //:f16_vsqrt_bench.wasm - //:f32_vsqrt_bench.wasm - //:f32_im2col_gemm_bench.wasm - //:rounding_bench.wasm - //:s16_rmaxabs_bench.wasm - //:s16_window_bench.wasm - //:u32_filterbank_accumulate_bench.wasm - //:u32_filterbank_subtract_bench.wasm - //:u32_vlog_bench.wasm - //:u64_u32_vsqrtshift_bench.wasm - //:i16_vlshift_bench.wasm - //:cs16_vsquareabs_bench.wasm - //:cs16_bfly4_bench.wasm - //:cs16_fftr_bench.wasm - //:x8_lut_bench.wasm - //:abs_bench.wasm - //:average_pooling_bench.wasm - //:bankers_rounding_bench.wasm - //:ceiling_bench.wasm - //:channel_shuffle_bench.wasm - //:convert_bench.wasm - //:convolution_bench.wasm - //:deconvolution_bench.wasm - //:elu_bench.wasm - //:floor_bench.wasm - //:global_average_pooling_bench.wasm - //:hardswish_bench.wasm - //:leaky_relu_bench.wasm - //:max_pooling_bench.wasm - //:negate_bench.wasm - //:sigmoid_bench.wasm - //:prelu_bench.wasm - //:softmax_bench.wasm - //:square_bench.wasm - //:square_root_bench.wasm - //:truncation_bench.wasm - //:f16_gemm_e2e_bench.wasm - //:f32_dwconv_e2e_bench.wasm - //:f32_gemm_e2e_bench.wasm - //:qs8_dwconv_e2e_bench.wasm - //:qs8_gemm_e2e_bench.wasm - //:qu8_gemm_e2e_bench.wasm - //:qu8_dwconv_e2e_bench.wasm - //:end2end_bench.wasm - //:f16_exp_ulp_eval.wasm - //:f16_expminus_ulp_eval.wasm - //:f16_expm1minus_ulp_eval.wasm - //:f16_sigmoid_ulp_eval.wasm - //:f16_sqrt_ulp_eval.wasm - //:f32_exp_ulp_eval.wasm - //:f32_expminus_ulp_eval.wasm - //:f32_expm1minus_ulp_eval.wasm - //:f32_extexp_ulp_eval.wasm - //:f32_sigmoid_ulp_eval.wasm - //:f32_sqrt_ulp_eval.wasm - //:f32_tanh_ulp_eval.wasm - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/bazel-out/wasm-opt/bin/ - ${CMAKE_BINARY_DIR}/wasm-opt + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" ) + +set(WAMRC "${CMAKE_CURRENT_SOURCE_DIR}/../../../wamr-compiler/build/wamrc") +if(EXISTS ${WAMRC}) + message("-- Will generate .aot") +else() + message("Will generate .wasm") +endif() + +foreach(BENCHMARK IN LISTS NATIVE_BENCHMARKS) + string(CONCAT WASM_BENCHMARK "//:" ${BENCHMARK} "-wasm") + string(CONCAT WASM_OUTPUT ${BENCHMARK} ".wasm") + + add_custom_command( + OUTPUT ${WASM_OUTPUT} + COMMAND bazel --output_user_root=build-user-output build -c opt --config=wasm ${WASM_BENCHMARK} + && ${CMAKE_COMMAND} -E copy_if_different ./bazel-bin/${WASM_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${WASM_OUTPUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack + DEPENDS xnnpack-download + COMMENT "Generating ${WASM_OUTPUT} ..." + ) + + set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${CMAKE_CURRENT_BINARY_DIR}/${WASM_OUTPUT}) + + if(EXISTS ${WAMRC}) + string(CONCAT AOT_OUTPUT ${BENCHMARK} ".aot") + + add_custom_command( + OUTPUT ${AOT_OUTPUT} + COMMAND ${WAMRC} -o ${AOT_OUTPUT} ${WASM_OUTPUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${WASM_OUTPUT} + COMMENT "Generating ${AOT_OUTPUT} ..." + ) + + add_custom_target(${BENCHMARK} ALL DEPENDS ${AOT_OUTPUT}) + else() + add_custom_target(${BENCHMARK} ALL DEPENDS ${WASM_OUTPUT}) + endif() +endforeach() + diff --git a/samples/workload/XNNPACK/README.md b/samples/workload/XNNPACK/README.md index 7984d9cee..c4cd52219 100644 --- a/samples/workload/XNNPACK/README.md +++ b/samples/workload/XNNPACK/README.md @@ -9,26 +9,7 @@ please refer to [installation instructions](../README.md). ## Build XNNPACK -```bash -cd /samples/workload/XNNPACK -mkdir build -cd build -cmake .. -``` -The wasm files are generated under folder samples/workload/XNNPACK/xnnpack/bazel-bin. - -## Run benchmarks - -Firstly please build iwasm with simd, libc-emcc and lib-pthread support: - -``` bash -$ cd /product-mini/platforms/linux/ -$ mkdir build && cd build -$ cmake .. -DWAMR_BUILD_LIBC_EMCC=1 -DWAMR_BUILD_LIB_PTHREAD=1 -$ make -``` - -And please build wamrc: +please build wamrc: ``` bash cd /wamr-compiler @@ -38,11 +19,31 @@ cmake .. make ``` -Then compile wasm file to aot file and run: +And then build xnnpack standalone wasm files -``` shell -$ cd /samples/workload/XNNPACK/xnnpack/bazel-bin -$ wamrc -o average_pooling_bench.aot average_pooling_bench.wasm (or other wasm files) -$ iwasm average_pooling_bench.aot +```bash +$ cd /samples/workload/XNNPACK +$ cmake -S . -B build +$ cmake --build build +``` + +Generated .wasm(and .aot) files are under *samples/workload/XNNPACK/build*. + +## Run benchmarks + +Firstly please build iwasm with simd, libc-emcc and lib-pthread supporting: + +``` bash +$ cd /product-mini/platforms/linux/ +$ mkdir build && cd build +$ cmake .. -DWAMR_BUILD_LIBC_EMCC=1 -DWAMR_BUILD_LIB_PTHREAD=1 +$ make +``` + +Then run: + +``` shell +$ cd /samples/workload/XNNPACK/build +$ iwasm averag_pooling_bench.aot # (or other aot files) ``` diff --git a/samples/workload/XNNPACK/xnnpack.patch b/samples/workload/XNNPACK/xnnpack.patch index 3fb6b230b..d7680d347 100644 --- a/samples/workload/XNNPACK/xnnpack.patch +++ b/samples/workload/XNNPACK/xnnpack.patch @@ -1,141 +1,138 @@ diff --git a/.bazelrc b/.bazelrc -index 688279da1..376996885 100644 +index fcaff1063..e61d53337 100644 --- a/.bazelrc +++ b/.bazelrc -@@ -53,4 +53,9 @@ build:ios_fat --watchos_cpus=armv7k - build:macos --apple_platform_type=macos +@@ -1,6 +1,7 @@ + # Basic build settings + build --jobs 128 + build --cxxopt='-std=gnu++14' ++build --incompatible_enable_cc_toolchain_resolution + + # Sets the default Apple platform to macOS. + build --apple_platform_type=macos +@@ -55,3 +56,10 @@ build:macos --apple_platform_type=macos build:macos_arm64 --config=macos --build:macos_arm64 --cpu=darwin_arm64 -\ No newline at end of file -+build:macos_arm64 --cpu=darwin_arm64 + build:macos_arm64 --cpu=darwin_arm64 + ++# Emscripten configs ++build:wasm --copt="-Wno-unused" ++build:wasm --copt="-Wno-unused-function" ++build:wasm --copt="-Wno-unused-but-set-variable" +build:wasm --cpu=wasm +build:wasm --features=wasm_simd -+build:wasm --crosstool_top=@emsdk//emscripten_toolchain:everything -+build:wasm --host_crosstool_top=@bazel_tools//tools/cpp:toolchain diff --git a/WORKSPACE b/WORKSPACE -index cd8960ffa..787e03ca8 100644 +index 2e568088b..3961371ca 100644 --- a/WORKSPACE +++ b/WORKSPACE -@@ -29,8 +29,9 @@ http_archive( - # Google Benchmark library, used in micro-benchmarks. - http_archive( - name = "com_google_benchmark", -- strip_prefix = "benchmark-main", -- urls = ["https://github.com/google/benchmark/archive/main.zip"], -+ sha256 = "1ba14374fddcd9623f126b1a60945e4deac4cdc4fb25a5f25e7f779e36f2db52", -+ strip_prefix = "benchmark-d2a8a4ee41b923876c034afb939c4fc03598e622", -+ urls = ["https://github.com/google/benchmark/archive/d2a8a4ee41b923876c034afb939c4fc03598e622.zip"], +@@ -83,7 +83,23 @@ http_archive( ) - # FP16 library, used for half-precision conversions -@@ -92,8 +93,25 @@ http_archive( - ], - ) + # Android NDK location and version is auto-detected from $ANDROID_NDK_HOME environment variable +-android_ndk_repository(name = "androidndk") ++# android_ndk_repository(name = "androidndk") -+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + # Android SDK location and API is auto-detected from $ANDROID_HOME environment variable +-android_sdk_repository(name = "androidsdk") ++# android_sdk_repository(name = "androidsdk") ++ +http_archive( + name = "emsdk", -+ # Use emsdk-3.0.0 since the larger version may: -+ # - compress the wasm file into a tar file but not directly generate wasm file -+ # - generate incomplete implementation of libc API, e.g. throw exception in getentropy -+ strip_prefix = "emsdk-3.0.0/bazel", -+ url = "https://github.com/emscripten-core/emsdk/archive/refs/tags/3.0.0.tar.gz", -+ sha256 = "a41dccfd15be9e85f923efaa0ac21943cbab77ec8d39e52f25eca1ec61a9ac9e" ++ sha256 = "5fa6f5eb45a4d50264610c4c9e1c155535359b63bfaad69b4e5101d16c1e7e32", ++ strip_prefix = "emsdk-a896e3d066448b3530dbcaa48869fafefd738f57/bazel", ++ url = "https://github.com/emscripten-core/emsdk/archive/a896e3d066448b3530dbcaa48869fafefd738f57.tar.gz", +) + +load("@emsdk//:deps.bzl", emsdk_deps = "deps") +emsdk_deps() + +load("@emsdk//:emscripten_deps.bzl", emsdk_emscripten_deps = "emscripten_deps") -+emsdk_emscripten_deps() ++emsdk_emscripten_deps(emscripten_version = "3.1.44") + - # Android NDK location and version is auto-detected from $ANDROID_NDK_HOME environment variable --android_ndk_repository(name = "androidndk") -+#android_ndk_repository(name = "androidndk") ++load("@emsdk//:toolchains.bzl", "register_emscripten_toolchains") ++register_emscripten_toolchains() +diff --git a/bench/utils.cc b/bench/utils.cc +index 3b32503a7..656845336 100644 +--- a/bench/utils.cc ++++ b/bench/utils.cc +@@ -456,3 +456,13 @@ CodeMemoryHelper::~CodeMemoryHelper() { - # Android SDK location and API is auto-detected from $ANDROID_HOME environment variable --android_sdk_repository(name = "androidsdk") -+#android_sdk_repository(name = "androidsdk") + } // namespace utils + } // namespace benchmark ++ ++ ++extern "C" ++__attribute__((import_module("env"), import_name("getentropy"))) int import_getentropy(void* buffer, size_t length); ++ ++extern "C" ++int getentropy(void* buffer, size_t length) ++{ ++ return import_getentropy(buffer, length); ++} diff --git a/build_defs.bzl b/build_defs.bzl -index b8217a18d..6f2d1675e 100644 +index 01b436eb7..2738fd50a 100644 --- a/build_defs.bzl +++ b/build_defs.bzl -@@ -380,7 +380,7 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): - explicitly specified. - """ - native.cc_binary( -- name = name, -+ name = name + ".wasm", - srcs = srcs, - copts = xnnpack_std_cxxopts() + [ - "-Iinclude", -@@ -405,5 +405,5 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): +@@ -1,6 +1,7 @@ + """Build definitions and rules for XNNPACK.""" + +-load(":emscripten.bzl", "xnnpack_emscripten_benchmark_linkopts", "xnnpack_emscripten_deps", "xnnpack_emscripten_minimal_linkopts", "xnnpack_emscripten_test_linkopts") ++load(":emscripten.bzl", "xnnpack_emscripten_benchmark_linkopts", "xnnpack_emscripten_deps", "xnnpack_emscripten_minimal_linkopts", "xnnpack_emscripten_test_linkopts", "xnnpack_emscripten_standalone_benchmark_linkopts") ++load("@emsdk//emscripten_toolchain:wasm_rules.bzl", "wasm_cc_binary") + + def xnnpack_visibility(): + """Visibility of :XNNPACK target. +@@ -393,7 +394,8 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): + "//conditions:default": ["-Wno-unused-function"], + }) + copts, + linkopts = select({ +- ":emscripten": xnnpack_emscripten_benchmark_linkopts(), ++ ":emscripten": xnnpack_emscripten_standalone_benchmark_linkopts(), ++ ":emscripten_wasmsimd": xnnpack_emscripten_standalone_benchmark_linkopts(), + ":windows_x86_64_mingw": ["-lshlwapi"], + ":windows_x86_64_msys": ["-lshlwapi"], + "//conditions:default": [], +@@ -405,5 +407,16 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): ":emscripten": xnnpack_emscripten_deps(), "//conditions:default": [], }), - tags = tags, -+ tags = tags, ++ tags = tags, ++ ) ++ ++ wasm_cc_binary( ++ name = name + "-wasm", ++ cc_target = ":" + name, ++ threads = "off", ++ simd = True, ++ standalone= True, ++ outputs = [ ++ name + ".wasm", ++ ] ) diff --git a/emscripten.bzl b/emscripten.bzl -index f1557a7b1..7f964a094 100644 +index f1557a7b1..a3c4f93b9 100644 --- a/emscripten.bzl +++ b/emscripten.bzl -@@ -25,12 +25,19 @@ def xnnpack_emscripten_benchmark_linkopts(): - """Emscripten-specific linkopts for benchmarks.""" - return [ - "-s ASSERTIONS=1", -- "-s ENVIRONMENT=node,shell,web", -- "-s ERROR_ON_UNDEFINED_SYMBOLS=1", -- "-s EXIT_RUNTIME=1", +@@ -33,6 +33,21 @@ def xnnpack_emscripten_benchmark_linkopts(): + "--pre-js $(location :preamble.js.lds)", + ] + ++def xnnpack_emscripten_standalone_benchmark_linkopts(): ++ return [ ++ "-s ASSERTIONS=1", + "-s ERROR_ON_UNDEFINED_SYMBOLS=0", - "-s ALLOW_MEMORY_GROWTH=1", - "-s TOTAL_MEMORY=536870912", # 512M -- "--pre-js $(location :preamble.js.lds)", ++ "-s ALLOW_MEMORY_GROWTH=1", ++ "-s TOTAL_MEMORY=536870912", # 512M + "-s USE_PTHREADS=0", + "-s STANDALONE_WASM=1", -+ "-Wno-unused", -+ "-Wno-unused-variable", -+ "-Wno-unused-command-line-argument", + "-Wl,--export=__heap_base", + "-Wl,--export=__data_end", + "-Wl,--export=malloc", + "-Wl,--export=free", -+ "--oformat=wasm", - ] - ++ ] ++ ++ def xnnpack_emscripten_deps(): -diff --git a/src/log.c b/src/log.c -index 5715f2f85..4b3e4261b 100644 ---- a/src/log.c -+++ b/src/log.c -@@ -55,7 +55,7 @@ - #endif - - #if XNN_LOG_TO_STDIO --static void xnn_vlog(int output_handle, const char* prefix, size_t prefix_length, const char* format, va_list args) { -+void xnn_vlog(int output_handle, const char* prefix, size_t prefix_length, const char* format, va_list args) { - char stack_buffer[XNN_LOG_STACK_BUFFER_SIZE]; - char* heap_buffer = NULL; - char* out_buffer = &stack_buffer[0]; -diff --git a/third_party/cpuinfo.BUILD b/third_party/cpuinfo.BUILD -index 1997f4e3a..5e03c43af 100644 ---- a/third_party/cpuinfo.BUILD -+++ b/third_party/cpuinfo.BUILD -@@ -150,7 +150,7 @@ cc_library( - "src/arm/midr.h", - ], - deps = [ -- "@clog", -+ "//deps/clog" - ], - ) - -@@ -352,5 +352,5 @@ config_setting( - - config_setting( - name = "emscripten", -- values = {"crosstool_top": "//toolchain:emscripten"}, -+ values = {"crosstool_top": "@emsdk//emscripten_toolchain:everything"}, - ) + """Emscripten-specific dependencies for unit tests and benchmarks.""" + return [ From 43a3cbf2ce0791e56ee12127c653e1736058a180 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 3 Aug 2023 08:39:22 +0800 Subject: [PATCH 042/123] Build more benchmarks in workload XNNPACK (#2417) Build 3 more benchmarks in workload XNNPACK and fix a typo. --- samples/workload/XNNPACK/CMakeLists.txt | 6 +++--- samples/workload/XNNPACK/README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/workload/XNNPACK/CMakeLists.txt b/samples/workload/XNNPACK/CMakeLists.txt index 93181cd99..41cdd583f 100644 --- a/samples/workload/XNNPACK/CMakeLists.txt +++ b/samples/workload/XNNPACK/CMakeLists.txt @@ -46,8 +46,8 @@ list(APPEND NATIVE_BENCHMARKS "f32_igemm_bench" "f32_conv_hwc_bench" "f16_conv_hwc2chw_bench" -# "f16_gavgpool_cw_bench" -# "f32_gavgpool_cw_bench" + "f16_gavgpool_cw_bench" + "f32_gavgpool_cw_bench" "f32_conv_hwc2chw_bench" "f16_dwconv_bench" "f32_dwconv_bench" @@ -126,7 +126,7 @@ list(APPEND NATIVE_BENCHMARKS "qs8_gemm_e2e_bench" "qu8_gemm_e2e_bench" "qu8_dwconv_e2e_bench" -# "end2end_bench" + "end2end_bench" "f16_exp_ulp_eval" "f16_expminus_ulp_eval" "f16_expm1minus_ulp_eval" diff --git a/samples/workload/XNNPACK/README.md b/samples/workload/XNNPACK/README.md index c4cd52219..625ef7f79 100644 --- a/samples/workload/XNNPACK/README.md +++ b/samples/workload/XNNPACK/README.md @@ -44,6 +44,6 @@ Then run: ``` shell $ cd /samples/workload/XNNPACK/build -$ iwasm averag_pooling_bench.aot # (or other aot files) +$ iwasm average_pooling_bench.aot # (or other aot files) ``` From 28125ec538c86de90d2b9be332d50760e7dd42bc Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 3 Aug 2023 09:46:56 +0900 Subject: [PATCH 043/123] Move wasm_runtime_destroy_wasi and wasi_nn_destroy calls together (#2418) And remove obsolete comment. --- core/iwasm/aot/aot_runtime.c | 16 +++++----------- core/iwasm/interpreter/wasm_runtime.c | 16 +++++----------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index e0d56a698..a7d6ef2d9 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1264,16 +1264,6 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton); } -#if WASM_ENABLE_LIBC_WASI != 0 - /* Destroy wasi resource before freeing app heap, since some fields of - wasi contex are allocated from app heap, and if app heap is freed, - these fields will be set to NULL, we cannot free their internal data - which may allocated from global heap. */ - /* Only destroy wasi ctx in the main module instance */ - if (!is_sub_inst) - wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); -#endif - #if WASM_ENABLE_PERF_PROFILING != 0 if (module_inst->func_perf_profilings) wasm_runtime_free(module_inst->func_perf_profilings); @@ -1306,10 +1296,14 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_runtime_free( ((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports); + if (!is_sub_inst) { +#if WASM_ENABLE_LIBC_WASI != 0 + wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); +#endif #if WASM_ENABLE_WASI_NN != 0 - if (!is_sub_inst) wasi_nn_destroy(module_inst); #endif + } wasm_runtime_free(module_inst); } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 84155a05a..497e6b19e 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2216,16 +2216,6 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) sub_module_deinstantiate(module_inst); #endif -#if WASM_ENABLE_LIBC_WASI != 0 - /* Destroy wasi resource before freeing app heap, since some fields of - wasi contex are allocated from app heap, and if app heap is freed, - these fields will be set to NULL, we cannot free their internal data - which may allocated from global heap. */ - /* Only destroy wasi ctx in the main module instance */ - if (!is_sub_inst) - wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); -#endif - if (module_inst->memory_count > 0) memories_deinstantiate(module_inst, module_inst->memories, module_inst->memory_count); @@ -2258,10 +2248,14 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) if (module_inst->e->c_api_func_imports) wasm_runtime_free(module_inst->e->c_api_func_imports); + if (!is_sub_inst) { +#if WASM_ENABLE_LIBC_WASI != 0 + wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); +#endif #if WASM_ENABLE_WASI_NN != 0 - if (!is_sub_inst) wasi_nn_destroy(module_inst); #endif + } wasm_runtime_free(module_inst); } From bdd99137a4f2ae8c05839d4611d7b0a497cae74c Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 4 Aug 2023 10:28:30 +0900 Subject: [PATCH 044/123] embed_wamr.md: Improvements about threads (#2420) - Some more clarifications - Mention wasi-threads - Fix a confusing indentation --- doc/embed_wamr.md | 99 +++++++++++++++++++------------------ doc/embed_wamr_spawn_api.md | 38 ++++++++++++++ 2 files changed, 88 insertions(+), 49 deletions(-) create mode 100644 doc/embed_wamr_spawn_api.md diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index 050384027..b83817589 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -258,68 +258,69 @@ We can't pass structure data or class objects through the pointer since the memo ## Execute wasm functions in multiple threads -The `exec_env` is not thread safety, it will cause unexpected behavior if the same `exec_env` is used in multiple threads. However, we've provided two ways to execute wasm functions concurrently: +It isn't safe to use an `exec_env` object in multiple threads concurrently. +To run a multi-threaded application, you basically need a separate `exec_env` +for each threads. -- You can use `pthread` APIs in your wasm application, see [pthread library](./pthread_library.md) for more details. +### Approaches to manage `exec_env` objects and threads -- The `spawn exec_env` and `spawn thread` APIs are available, you can use these APIs to manage the threads in native: +WAMR supports two approaches to manage `exec_env` and threads as described +below. While they are not exclusive, you usually only need to use one of +them. - *spawn exec_env:* +#### Make your WASM application manage threads - `spawn exec_env` API spawns a `new_exec_env` base on the original `exec_env`, use can use it in other threads: + You can make your WASM application spawn threads by itself, + typically using `pthread` APIs like `pthread_create`. + See [pthread library](./pthread_library.md) and + [pthread implementations](./pthread_impls.md) for more details. + In this case, WAMR manages `exec_env` for the spawned threads. + +#### Make your embedder manage threads + + The `spawn exec_env` and `spawn thread` APIs are available for the embedder. + You can use these APIs to manage the threads. + See [Thread related embedder API](./embed_wamr_spawn_api.md) for details. + +### Other notes about threads + +* You can manage the maximum number of threads ```C - new_exec_env = wasm_runtime_spawn_exec_env(exec_env); - - /* Then you can use new_exec_env in your new thread */ - module_inst = wasm_runtime_get_module_inst(new_exec_env); - func_inst = wasm_runtime_lookup_function(module_inst, ...); - wasm_runtime_call_wasm(new_exec_env, func_inst, ...); - - /* you need to use this API to manually destroy the spawned exec_env */ - wasm_runtime_destroy_spawned_exec_env(new_exec_env); + init_args.max_thread_num = THREAD_NUM; + /* If this init argument is not set, the default maximum thread number is 4 */ ``` - *spawn thread:* +* To share memory among threads, you need to build your WASM application with shared memory - You can also use `spawn thread` API to avoid manually manage the spawned exec_env: - - ```C - wasm_thread_t wasm_tid; - void *wamr_thread_cb(wasm_exec_env_t exec_env, void *arg) - { - module_inst = wasm_runtime_get_module_inst(exec_env); - func_inst = wasm_runtime_lookup_function(module_inst, ...); - wasm_runtime_call_wasm(exec_env, func_inst, ...); - } - wasm_runtime_spawn_thread(exec_env, &wasm_tid, wamr_thread_cb, NULL); - /* Use wasm_runtime_join_thread to join the spawned thread */ - wasm_runtime_join_thread(wasm_tid, NULL); - ``` - -**Note1: You can manage the maximum number of threads can be created:** - -```C -init_args.max_thread_num = THREAD_NUM; -/* If this init argument is not set, the default maximum thread number is 4 */ -``` - -**Note2: The wasm application should be built with `--shared-memory` and `-pthread` enabled:** - -```bash - /opt/wasi-sdk/bin/clang -o test.wasm test.c -nostdlib -pthread \ - -Wl,--shared-memory,--max-memory=131072 \ - -Wl,--no-entry,--export=__heap_base,--export=__data_end \ - -Wl,--export=__wasm_call_ctors,--export=${your_func_name} -``` - - **Note3: The pthread library feature should be enabled while building the runtime:** + For example, it can be done with `--shared-memory` and `-pthread`. ```bash - cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 + /opt/wasi-sdk/bin/clang -o test.wasm test.c -nostdlib -pthread \ + -Wl,--shared-memory,--max-memory=131072 \ + -Wl,--no-entry,--export=__heap_base,--export=__data_end \ + -Wl,--export=__wasm_call_ctors,--export=${your_func_name} ``` -[Here](../samples/spawn-thread) is a sample to show how to use these APIs. +* The corresponding threading feature should be enabled while building the runtime + + - WAMR lib-pthread (legacy) + + ```bash + cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 + ``` + + - wasi-threads + + ```bash + cmake .. -DWAMR_BUILD_LIB_WASI_THREADS=1 + ``` + + - `wasm_runtime_spawn_exec_env` and `wasm_runtime_spawn_thread` + + ```bash + cmake .. -DWAMR_BUILD_THREAD_MGR=1 -DWAMR_BUILD_SHARED_MEMORY=1 + ``` ## The deinitialization procedure diff --git a/doc/embed_wamr_spawn_api.md b/doc/embed_wamr_spawn_api.md new file mode 100644 index 000000000..f0e637f30 --- /dev/null +++ b/doc/embed_wamr_spawn_api.md @@ -0,0 +1,38 @@ +# Thread related embedder API + +This document explains `wasm_runtime_spawn_exec_env` and +`wasm_runtime_spawn_thread`. +[Here](../samples/spawn-thread) is a sample to show how to use these APIs. + + * spawn exec_env + + `spawn exec_env` API creates a new `exec_env` based on the original `exec_env`. You can use it in other threads. It's up to the embedder how to manage host threads to run the new `exec_env`. + + ```C + new_exec_env = wasm_runtime_spawn_exec_env(exec_env); + + /* Then you can use new_exec_env in your new thread */ + module_inst = wasm_runtime_get_module_inst(new_exec_env); + func_inst = wasm_runtime_lookup_function(module_inst, ...); + wasm_runtime_call_wasm(new_exec_env, func_inst, ...); + + /* you need to use this API to manually destroy the spawned exec_env */ + wasm_runtime_destroy_spawned_exec_env(new_exec_env); + ``` + + * spawn thread + + Alternatively, you can use `spawn thread` API to avoid managing the extra exec_env and the corresponding host thread manually: + + ```C + wasm_thread_t wasm_tid; + void *wamr_thread_cb(wasm_exec_env_t exec_env, void *arg) + { + module_inst = wasm_runtime_get_module_inst(exec_env); + func_inst = wasm_runtime_lookup_function(module_inst, ...); + wasm_runtime_call_wasm(exec_env, func_inst, ...); + } + wasm_runtime_spawn_thread(exec_env, &wasm_tid, wamr_thread_cb, NULL); + /* Use wasm_runtime_join_thread to join the spawned thread */ + wasm_runtime_join_thread(wasm_tid, NULL); + ``` From 29761c72167589f9c3ee230668248102eae930ed Mon Sep 17 00:00:00 2001 From: Maks Litskevich Date: Fri, 4 Aug 2023 02:41:25 +0100 Subject: [PATCH 045/123] Fix typo in test_wamr.sh (#2421) Change `ORC_EAGER_JIT_COMPILE_FLAGS` to `ORC_LAZY_JIT_COMPILE_FLAGS` --- tests/wamr-test-suites/test_wamr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index e263e5ab6..1448e3e1e 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -824,7 +824,7 @@ function trigger() collect_coverage llvm-jit echo "work in orc jit lazy compilation mode" - BUILD_FLAGS="$ORC_EAGER_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" + BUILD_FLAGS="$ORC_LAZY_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" build_iwasm_with_cfg $BUILD_FLAGS for suite in "${TEST_CASE_ARR[@]}"; do $suite"_test" jit From 91592429f43c0ea22ead5a031adada101db24592 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 4 Aug 2023 11:18:13 +0900 Subject: [PATCH 046/123] Fix memory sharing (#2415) - Inherit shared memory from the parent instance, instead of trying to look it up by the underlying module. The old method works correctly only when every cluster uses different module. - Use reference count in WASMMemoryInstance/AOTMemoryInstance to mark whether the memory is shared or not - Retire WASMSharedMemNode - For atomic opcode implementations in the interpreters, use a global lock for now - Update the internal API users (wasi-threads, lib-pthread, wasm_runtime_spawn_thread) Fixes https://github.com/bytecodealliance/wasm-micro-runtime/issues/1962 --- core/iwasm/aot/aot_runtime.c | 67 ++---- core/iwasm/aot/aot_runtime.h | 8 +- core/iwasm/common/wasm_memory.c | 12 +- core/iwasm/common/wasm_runtime_common.c | 33 ++- core/iwasm/common/wasm_runtime_common.h | 3 +- core/iwasm/common/wasm_shared_memory.c | 197 ++++++++---------- core/iwasm/common/wasm_shared_memory.h | 44 ++-- core/iwasm/interpreter/wasm_interp_classic.c | 116 +++++------ core/iwasm/interpreter/wasm_interp_fast.c | 116 +++++------ core/iwasm/interpreter/wasm_runtime.c | 72 +++---- core/iwasm/interpreter/wasm_runtime.h | 5 +- .../lib-pthread/lib_pthread_wrapper.c | 2 +- .../lib_wasi_threads_wrapper.c | 2 +- .../libraries/thread-mgr/thread_manager.c | 22 +- 14 files changed, 298 insertions(+), 401 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index a7d6ef2d9..3e6371f42 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -339,11 +339,8 @@ memories_deinstantiate(AOTModuleInstance *module_inst) memory_inst = module_inst->memories[i]; if (memory_inst) { #if WASM_ENABLE_SHARED_MEMORY != 0 - if (memory_inst->is_shared) { - int32 ref_count = shared_memory_dec_reference( - (WASMModuleCommon *)module_inst->module); - bh_assert(ref_count >= 0); - + if (shared_memory_is_shared(memory_inst)) { + uint32 ref_count = shared_memory_dec_reference(memory_inst); /* if the reference count is not zero, don't free the memory */ if (ref_count > 0) @@ -373,9 +370,10 @@ memories_deinstantiate(AOTModuleInstance *module_inst) } static AOTMemoryInstance * -memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, - AOTMemoryInstance *memory_inst, AOTMemory *memory, - uint32 heap_size, char *error_buf, uint32 error_buf_size) +memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, + AOTModule *module, AOTMemoryInstance *memory_inst, + AOTMemory *memory, uint32 memory_idx, uint32 heap_size, + char *error_buf, uint32 error_buf_size) { void *heap_handle; uint32 num_bytes_per_page = memory->num_bytes_per_page; @@ -396,23 +394,13 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, bool is_shared_memory = memory->memory_flags & 0x02 ? true : false; /* Shared memory */ - if (is_shared_memory) { + if (is_shared_memory && parent != NULL) { AOTMemoryInstance *shared_memory_instance; - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module); - /* If the memory of this module has been instantiated, - return the memory instance directly */ - if (node) { - uint32 ref_count; - ref_count = shared_memory_inc_reference((WASMModuleCommon *)module); - bh_assert(ref_count > 0); - shared_memory_instance = - (AOTMemoryInstance *)shared_memory_get_memory_inst(node); - bh_assert(shared_memory_instance); - - (void)ref_count; - return shared_memory_instance; - } + bh_assert(memory_idx == 0); + bh_assert(parent->memory_count > memory_idx); + shared_memory_instance = parent->memories[memory_idx]; + shared_memory_inc_reference(shared_memory_instance); + return shared_memory_instance; } #endif @@ -609,23 +597,12 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, #if WASM_ENABLE_SHARED_MEMORY != 0 if (is_shared_memory) { - memory_inst->is_shared = true; - if (!shared_memory_set_memory_inst( - (WASMModuleCommon *)module, - (WASMMemoryInstanceCommon *)memory_inst)) { - set_error_buf(error_buf, error_buf_size, "allocate memory failed"); - goto fail3; - } + memory_inst->ref_count = 1; } #endif return memory_inst; -#if WASM_ENABLE_SHARED_MEMORY != 0 -fail3: - if (heap_size > 0) - mem_allocator_destroy(memory_inst->heap_handle); -#endif fail2: if (heap_size > 0) wasm_runtime_free(memory_inst->heap_handle); @@ -654,8 +631,9 @@ aot_get_default_memory(AOTModuleInstance *module_inst) } static bool -memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module, - uint32 heap_size, char *error_buf, uint32 error_buf_size) +memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, + AOTModule *module, uint32 heap_size, char *error_buf, + uint32 error_buf_size) { uint32 global_index, global_data_offset, base_offset, length; uint32 i, memory_count = module->memory_count; @@ -672,8 +650,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module, memories = module_inst->global_table_data.memory_instances; for (i = 0; i < memory_count; i++, memories++) { - memory_inst = memory_instantiate(module_inst, module, memories, - &module->memories[i], heap_size, + memory_inst = memory_instantiate(module_inst, parent, module, memories, + &module->memories[i], i, heap_size, error_buf, error_buf_size); if (!memory_inst) { return false; @@ -1100,9 +1078,9 @@ check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size) } AOTModuleInstance * -aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main, - uint32 stack_size, uint32 heap_size, char *error_buf, - uint32 error_buf_size) +aot_instantiate(AOTModule *module, AOTModuleInstance *parent, + WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size) { AOTModuleInstance *module_inst; const uint32 module_inst_struct_size = @@ -1112,6 +1090,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main, uint64 total_size, table_size = 0; uint8 *p; uint32 i, extra_info_offset; + const bool is_sub_inst = parent != NULL; /* Check heap size */ heap_size = align_uint(heap_size, 8); @@ -1171,7 +1150,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main, goto fail; /* Initialize memory space */ - if (!memories_instantiate(module_inst, module, heap_size, error_buf, + if (!memories_instantiate(module_inst, parent, module, heap_size, error_buf, error_buf_size)) goto fail; diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 8d679d55c..2dea832be 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -406,7 +406,7 @@ aot_unload(AOTModule *module); * Instantiate a AOT module. * * @param module the AOT module to instantiate - * @param is_sub_inst the flag of sub instance + * @param parent the parent module instance * @param heap_size the default heap size of the module instance, a heap will * be created besides the app memory space. Both wasm app and native * function can allocate memory from the heap. If heap_size is 0, the @@ -417,9 +417,9 @@ aot_unload(AOTModule *module); * @return return the instantiated AOT module instance, NULL if failed */ AOTModuleInstance * -aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main, - uint32 stack_size, uint32 heap_size, char *error_buf, - uint32 error_buf_size); +aot_instantiate(AOTModule *module, AOTModuleInstance *parent, + WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size); /** * Deinstantiate a AOT module instance, destroy the resources. diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 9db7fa141..7d5cb4353 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -608,7 +608,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) } #if WASM_ENABLE_SHARED_MEMORY != 0 - if (memory->is_shared) { + if (shared_memory_is_shared(memory)) { memory->num_bytes_per_page = num_bytes_per_page; memory->cur_page_count = total_page_count; memory->max_page_count = max_page_count; @@ -769,15 +769,13 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) bool ret = false; #if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module->module); - if (node) - os_mutex_lock(&node->shared_mem_lock); + if (module->memory_count > 0) + shared_memory_lock(module->memories[0]); #endif ret = wasm_enlarge_memory_internal(module, inc_page_count); #if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_unlock(&node->shared_mem_lock); + if (module->memory_count > 0) + shared_memory_unlock(module->memories[0]); #endif return ret; diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 5467065f6..8e7933798 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1196,7 +1196,8 @@ wasm_runtime_unload(WASMModuleCommon *module) } WASMModuleInstanceCommon * -wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst, +wasm_runtime_instantiate_internal(WASMModuleCommon *module, + WASMModuleInstanceCommon *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size) @@ -1204,14 +1205,14 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst, #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) return (WASMModuleInstanceCommon *)wasm_instantiate( - (WASMModule *)module, is_sub_inst, exec_env_main, stack_size, - heap_size, error_buf, error_buf_size); + (WASMModule *)module, (WASMModuleInstance *)parent, exec_env_main, + stack_size, heap_size, error_buf, error_buf_size); #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) return (WASMModuleInstanceCommon *)aot_instantiate( - (AOTModule *)module, is_sub_inst, exec_env_main, stack_size, - heap_size, error_buf, error_buf_size); + (AOTModule *)module, (AOTModuleInstance *)parent, exec_env_main, + stack_size, heap_size, error_buf, error_buf_size); #endif set_error_buf(error_buf, error_buf_size, "Instantiate module failed, invalid module type"); @@ -1224,7 +1225,7 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size, uint32 error_buf_size) { return wasm_runtime_instantiate_internal( - module, false, NULL, stack_size, heap_size, error_buf, error_buf_size); + module, NULL, NULL, stack_size, heap_size, error_buf, error_buf_size); } void @@ -2310,10 +2311,8 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) WASMExecEnv *exec_env = NULL; #if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module); - if (node) - os_mutex_lock(&node->shared_mem_lock); + if (module_inst->memory_count > 0) + shared_memory_lock(module_inst->memories[0]); #endif if (exception) { snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), @@ -2323,8 +2322,8 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) module_inst->cur_exception[0] = '\0'; } #if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_unlock(&node->shared_mem_lock); + if (module_inst->memory_count > 0) + shared_memory_unlock(module_inst->memories[0]); #endif #if WASM_ENABLE_THREAD_MGR != 0 @@ -2386,10 +2385,8 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf) bool has_exception = false; #if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module); - if (node) - os_mutex_lock(&node->shared_mem_lock); + if (module_inst->memory_count > 0) + shared_memory_lock(module_inst->memories[0]); #endif if (module_inst->cur_exception[0] != '\0') { /* NULL is passed if the caller is not interested in getting the @@ -2403,8 +2400,8 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf) has_exception = true; } #if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_unlock(&node->shared_mem_lock); + if (module_inst->memory_count > 0) + shared_memory_unlock(module_inst->memories[0]); #endif return has_exception; diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 60a32cb86..f631defb1 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -498,7 +498,8 @@ wasm_runtime_unload(WASMModuleCommon *module); /* Internal API */ WASMModuleInstanceCommon * -wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst, +wasm_runtime_instantiate_internal(WASMModuleCommon *module, + WASMModuleInstanceCommon *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size); diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index 314938d60..c95d4b7ed 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -9,9 +9,16 @@ #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; -static korp_mutex shared_memory_list_lock; +/* + * Note: this lock can be per memory. + * + * For now, just use a global because: + * - it's a bit cumbersome to extend WASMMemoryInstance w/o breaking + * the AOT ABI. + * - If you care performance, it's better to make the interpreters + * use atomic ops. + */ +static korp_mutex _shared_memory_lock; /* clang-format off */ enum { @@ -48,17 +55,15 @@ destroy_wait_info(void *wait_info); bool wasm_shared_memory_init() { - if (os_mutex_init(&shared_memory_list_lock) != 0) + if (os_mutex_init(&_shared_memory_lock) != 0) return false; - /* wait map not exists, create new map */ if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash, (KeyEqualFunc)wait_address_equal, NULL, destroy_wait_info))) { - os_mutex_destroy(&shared_memory_list_lock); + os_mutex_destroy(&_shared_memory_lock); return false; } - return true; } @@ -66,110 +71,79 @@ void wasm_shared_memory_destroy() { bh_hash_map_destroy(wait_map); - os_mutex_destroy(&shared_memory_list_lock); + os_mutex_destroy(&_shared_memory_lock); } -static WASMSharedMemNode * -search_module(WASMModuleCommon *module) +uint32 +shared_memory_inc_reference(WASMMemoryInstance *memory) { - WASMSharedMemNode *node; - - os_mutex_lock(&shared_memory_list_lock); - node = bh_list_first_elem(shared_memory_list); - - while (node) { - if (module == node->module) { - os_mutex_unlock(&shared_memory_list_lock); - return node; - } - node = bh_list_elem_next(node); - } - - os_mutex_unlock(&shared_memory_list_lock); - return NULL; + bh_assert(shared_memory_is_shared(memory)); + uint32 old; +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_lock(&_shared_memory_lock); +#endif + old = BH_ATOMIC_32_FETCH_ADD(memory->ref_count, 1); +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_unlock(&_shared_memory_lock); +#endif + bh_assert(old >= 1); + bh_assert(old < UINT32_MAX); + return old + 1; } -WASMSharedMemNode * -wasm_module_get_shared_memory(WASMModuleCommon *module) +uint32 +shared_memory_dec_reference(WASMMemoryInstance *memory) { - return search_module(module); + bh_assert(shared_memory_is_shared(memory)); + uint32 old; +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_lock(&_shared_memory_lock); +#endif + old = BH_ATOMIC_32_FETCH_SUB(memory->ref_count, 1); +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_unlock(&_shared_memory_lock); +#endif + bh_assert(old > 0); + return old - 1; } -int32 -shared_memory_inc_reference(WASMModuleCommon *module) +bool +shared_memory_is_shared(WASMMemoryInstance *memory) { - WASMSharedMemNode *node = search_module(module); - uint32 ref_count = -1; - if (node) { - os_mutex_lock(&node->lock); - ref_count = ++node->ref_count; - os_mutex_unlock(&node->lock); - } - return ref_count; + uint32 old; +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_lock(&_shared_memory_lock); +#endif + old = BH_ATOMIC_32_LOAD(memory->ref_count); +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_unlock(&_shared_memory_lock); +#endif + return old > 0; } -int32 -shared_memory_dec_reference(WASMModuleCommon *module) +static korp_mutex * +shared_memory_get_lock_pointer(WASMMemoryInstance *memory) { - WASMSharedMemNode *node = search_module(module); - uint32 ref_count = 0; - if (node) { - os_mutex_lock(&node->lock); - ref_count = --node->ref_count; - os_mutex_unlock(&node->lock); - if (ref_count == 0) { - os_mutex_lock(&shared_memory_list_lock); - bh_list_remove(shared_memory_list, node); - os_mutex_unlock(&shared_memory_list_lock); - - os_mutex_destroy(&node->shared_mem_lock); - os_mutex_destroy(&node->lock); - wasm_runtime_free(node); - } - return ref_count; - } - - return -1; + bh_assert(memory != NULL); + return &_shared_memory_lock; } -WASMMemoryInstanceCommon * -shared_memory_get_memory_inst(WASMSharedMemNode *node) +void +shared_memory_lock(WASMMemoryInstance *memory) { - return node->memory_inst; + /* + * Note: exception logic is currently abusing this lock. + * cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/2407 + */ + bh_assert(memory != NULL); + os_mutex_lock(&_shared_memory_lock); } -WASMSharedMemNode * -shared_memory_set_memory_inst(WASMModuleCommon *module, - WASMMemoryInstanceCommon *memory) +void +shared_memory_unlock(WASMMemoryInstance *memory) { - WASMSharedMemNode *node; - bh_list_status ret; - - if (!(node = wasm_runtime_malloc(sizeof(WASMSharedMemNode)))) - return NULL; - - node->module = module; - node->memory_inst = memory; - node->ref_count = 1; - - if (os_mutex_init(&node->shared_mem_lock) != 0) { - wasm_runtime_free(node); - return NULL; - } - - if (os_mutex_init(&node->lock) != 0) { - os_mutex_destroy(&node->shared_mem_lock); - wasm_runtime_free(node); - return NULL; - } - - os_mutex_lock(&shared_memory_list_lock); - ret = bh_list_insert(shared_memory_list, node); - bh_assert(ret == BH_LIST_SUCCESS); - os_mutex_unlock(&shared_memory_list_lock); - - (void)ret; - return node; + bh_assert(memory != NULL); + os_mutex_unlock(&_shared_memory_lock); } /* Atomics wait && notify APIs */ @@ -307,7 +281,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, WASMModuleInstance *module_inst = (WASMModuleInstance *)module; AtomicWaitInfo *wait_info; AtomicWaitNode *wait_node; - WASMSharedMemNode *node; + korp_mutex *lock; #if WASM_ENABLE_THREAD_MGR != 0 WASMExecEnv *exec_env; #endif @@ -322,7 +296,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, } /* Currently we have only one memory instance */ - if (!module_inst->memories[0]->is_shared) { + if (!shared_memory_is_shared(module_inst->memories[0])) { wasm_runtime_set_exception(module, "expected shared memory"); return -1; } @@ -340,30 +314,29 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, bh_assert(exec_env); #endif - node = search_module((WASMModuleCommon *)module_inst->module); - bh_assert(node); + lock = shared_memory_get_lock_pointer(module_inst->memories[0]); /* Lock the shared_mem_lock for the whole atomic wait process, and use it to os_cond_reltimedwait */ - os_mutex_lock(&node->shared_mem_lock); + os_mutex_lock(lock); no_wait = (!wait64 && *(uint32 *)address != (uint32)expect) || (wait64 && *(uint64 *)address != expect); if (no_wait) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); return 1; } if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); wasm_runtime_set_exception(module, "failed to create wait node"); return -1; } memset(wait_node, 0, sizeof(AtomicWaitNode)); if (0 != os_cond_init(&wait_node->wait_cond)) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); wasm_runtime_free(wait_node); wasm_runtime_set_exception(module, "failed to init wait cond"); return -1; @@ -375,7 +348,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, wait_info = acquire_wait_info(address, wait_node); if (!wait_info) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); os_cond_destroy(&wait_node->wait_cond); wasm_runtime_free(wait_node); wasm_runtime_set_exception(module, "failed to acquire wait_info"); @@ -390,7 +363,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, if (timeout < 0) { /* wait forever until it is notified or terminatied here we keep waiting and checking every second */ - os_cond_reltimedwait(&wait_node->wait_cond, &node->shared_mem_lock, + os_cond_reltimedwait(&wait_node->wait_cond, lock, (uint64)timeout_1sec); if (wait_node->status == S_NOTIFIED /* notified by atomic.notify */ #if WASM_ENABLE_THREAD_MGR != 0 @@ -404,8 +377,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, else { timeout_wait = timeout_left < timeout_1sec ? timeout_left : timeout_1sec; - os_cond_reltimedwait(&wait_node->wait_cond, &node->shared_mem_lock, - timeout_wait); + os_cond_reltimedwait(&wait_node->wait_cond, lock, timeout_wait); if (wait_node->status == S_NOTIFIED /* notified by atomic.notify */ || timeout_left <= timeout_wait /* time out */ #if WASM_ENABLE_THREAD_MGR != 0 @@ -433,7 +405,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, /* Release wait info if no wait nodes are attached */ map_try_release_wait_info(wait_map, wait_info, address); - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); return is_timeout ? 2 : 0; } @@ -445,7 +417,7 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, WASMModuleInstance *module_inst = (WASMModuleInstance *)module; uint32 notify_result; AtomicWaitInfo *wait_info; - WASMSharedMemNode *node; + korp_mutex *lock; bool out_of_bounds; bh_assert(module->module_type == Wasm_Module_Bytecode @@ -461,31 +433,30 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, } /* Currently we have only one memory instance */ - if (!module_inst->memories[0]->is_shared) { + if (!shared_memory_is_shared(module_inst->memories[0])) { /* Always return 0 for ushared linear memory since there is no way to create a waiter on it */ return 0; } - node = search_module((WASMModuleCommon *)module_inst->module); - bh_assert(node); + lock = shared_memory_get_lock_pointer(module_inst->memories[0]); /* Lock the shared_mem_lock for the whole atomic notify process, and use it to os_cond_signal */ - os_mutex_lock(&node->shared_mem_lock); + os_mutex_lock(lock); wait_info = acquire_wait_info(address, NULL); /* Nobody wait on this address */ if (!wait_info) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); return 0; } /* Notify each wait node in the wait list */ notify_result = notify_wait_list(wait_info->wait_list, count); - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); return notify_result; } diff --git a/core/iwasm/common/wasm_shared_memory.h b/core/iwasm/common/wasm_shared_memory.h index 6c1c49210..6a6538d21 100644 --- a/core/iwasm/common/wasm_shared_memory.h +++ b/core/iwasm/common/wasm_shared_memory.h @@ -7,53 +7,33 @@ #define _WASM_SHARED_MEMORY_H #include "bh_common.h" -#if WASM_ENABLE_INTERP != 0 -#include "wasm_runtime.h" -#endif -#if WASM_ENABLE_AOT != 0 -#include "aot_runtime.h" -#endif +#include "../interpreter/wasm_runtime.h" +#include "wasm_runtime_common.h" #ifdef __cplusplus extern "C" { #endif -typedef struct WASMSharedMemNode { - bh_list_link l; - /* Lock */ - korp_mutex lock; - /* The module reference */ - WASMModuleCommon *module; - /* The memory information */ - WASMMemoryInstanceCommon *memory_inst; - /* Lock used for atomic operations */ - korp_mutex shared_mem_lock; - - /* reference count */ - uint32 ref_count; -} WASMSharedMemNode; - bool wasm_shared_memory_init(); void wasm_shared_memory_destroy(); -WASMSharedMemNode * -wasm_module_get_shared_memory(WASMModuleCommon *module); +uint32 +shared_memory_inc_reference(WASMMemoryInstance *memory); -int32 -shared_memory_inc_reference(WASMModuleCommon *module); +uint32 +shared_memory_dec_reference(WASMMemoryInstance *memory); -int32 -shared_memory_dec_reference(WASMModuleCommon *module); +bool +shared_memory_is_shared(WASMMemoryInstance *memory); -WASMMemoryInstanceCommon * -shared_memory_get_memory_inst(WASMSharedMemNode *node); +void +shared_memory_lock(WASMMemoryInstance *memory); -WASMSharedMemNode * -shared_memory_set_memory_inst(WASMModuleCommon *module, - WASMMemoryInstanceCommon *memory); +void +shared_memory_unlock(WASMMemoryInstance *memory); uint32 wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 23e165bea..949900950 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -710,28 +710,28 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint32)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint32)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = LOAD_I32(maddr); \ STORE_U32(maddr, readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ PUSH_I32(readv); \ break; \ @@ -750,39 +750,39 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_U32(maddr); \ STORE_U32(maddr, (uint32)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else { \ uint64 op_result; \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_I64(maddr); \ op_result = readv op sval; \ STORE_I64(maddr, op_result); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ PUSH_I64(readv); \ break; \ @@ -1156,10 +1156,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { -#if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module->module); -#endif WASMMemoryInstance *memory = wasm_get_default_memory(module); #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ @@ -3526,23 +3522,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)(*(uint8 *)maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)LOAD_U16(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I32(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I32(readv); @@ -3561,30 +3557,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)(*(uint8 *)maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U16(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U32(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I64(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I64(readv); @@ -3603,23 +3599,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U32(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } break; } @@ -3637,30 +3633,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U32(maddr, (uint32)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); PUT_I64_TO_ADDR((uint32 *)maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } break; } @@ -3680,32 +3676,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint8)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint16)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I32(maddr); if (readv == expect) STORE_U32(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I32(readv); break; @@ -3726,43 +3722,43 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint8)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint16)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint32)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U32(maddr); if (readv == expect) STORE_U32(maddr, (uint32)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_I64(maddr); if (readv == expect) STORE_I64(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I64(readv); break; diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 458eb2e44..729d4c60d 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -482,28 +482,28 @@ LOAD_PTR(void *addr) CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(1); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint32)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(2); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint32)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(4); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = LOAD_I32(maddr); \ STORE_U32(maddr, readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ PUSH_I32(readv); \ break; \ @@ -522,39 +522,39 @@ LOAD_PTR(void *addr) CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(1); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(2); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(4); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_U32(maddr); \ STORE_U32(maddr, (uint32)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else { \ uint64 op_result; \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(8); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_I64(maddr); \ op_result = readv op sval; \ STORE_I64(maddr, op_result); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ PUSH_I64(readv); \ break; \ @@ -1166,10 +1166,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { -#if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module->module); -#endif WASMMemoryInstance *memory = wasm_get_default_memory(module); #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ @@ -3353,23 +3349,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)(*(uint8 *)maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)LOAD_U16(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I32(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I32(readv); @@ -3388,30 +3384,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)(*(uint8 *)maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U16(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U32(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I64(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I64(readv); @@ -3429,23 +3425,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U32(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } break; } @@ -3463,30 +3459,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U32(maddr, (uint32)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_I64(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } break; } @@ -3506,32 +3502,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(1); expect = (uint8)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); expect = (uint16)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I32(maddr); if (readv == expect) STORE_U32(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I32(readv); break; @@ -3552,43 +3548,43 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(1); expect = (uint8)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); expect = (uint16)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); expect = (uint32)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U32(maddr); if (readv == expect) STORE_U32(maddr, (uint32)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_I64(maddr); if (readv == expect) STORE_I64(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I64(readv); break; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 497e6b19e..eef2e3688 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -122,11 +122,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst, } #endif #if WASM_ENABLE_SHARED_MEMORY != 0 - if (memories[i]->is_shared) { - int32 ref_count = shared_memory_dec_reference( - (WASMModuleCommon *)module_inst->module); - bh_assert(ref_count >= 0); - + if (shared_memory_is_shared(memories[i])) { + uint32 ref_count = shared_memory_dec_reference(memories[i]); /* if the reference count is not zero, don't free the memory */ if (ref_count > 0) @@ -159,7 +156,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst, } static WASMMemoryInstance * -memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory, +memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, + WASMMemoryInstance *memory, uint32 memory_idx, uint32 num_bytes_per_page, uint32 init_page_count, uint32 max_page_count, uint32 heap_size, uint32 flags, char *error_buf, uint32 error_buf_size) @@ -180,22 +178,11 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory, bool is_shared_memory = flags & 0x02 ? true : false; /* shared memory */ - if (is_shared_memory) { - WASMSharedMemNode *node = wasm_module_get_shared_memory( - (WASMModuleCommon *)module_inst->module); - /* If the memory of this module has been instantiated, - return the memory instance directly */ - if (node) { - uint32 ref_count; - ref_count = shared_memory_inc_reference( - (WASMModuleCommon *)module_inst->module); - bh_assert(ref_count > 0); - memory = (WASMMemoryInstance *)shared_memory_get_memory_inst(node); - bh_assert(memory); - - (void)ref_count; - return memory; - } + if (is_shared_memory && parent != NULL) { + bh_assert(parent->memory_count > memory_idx); + memory = parent->memories[memory_idx]; + shared_memory_inc_reference(memory); + return memory; } #endif /* end of WASM_ENABLE_SHARED_MEMORY */ @@ -388,24 +375,13 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory, #if WASM_ENABLE_SHARED_MEMORY != 0 if (is_shared_memory) { - memory->is_shared = true; - if (!shared_memory_set_memory_inst( - (WASMModuleCommon *)module_inst->module, - (WASMMemoryInstanceCommon *)memory)) { - set_error_buf(error_buf, error_buf_size, "allocate memory failed"); - goto fail4; - } + memory->ref_count = 1; } #endif LOG_VERBOSE("Memory instantiate success."); return memory; -#if WASM_ENABLE_SHARED_MEMORY != 0 -fail4: - if (heap_size > 0) - mem_allocator_destroy(memory->heap_handle); -#endif fail3: if (heap_size > 0) wasm_runtime_free(memory->heap_handle); @@ -428,7 +404,8 @@ fail1: */ static WASMMemoryInstance ** memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, - uint32 heap_size, char *error_buf, uint32 error_buf_size) + WASMModuleInstance *parent, uint32 heap_size, + char *error_buf, uint32 error_buf_size) { WASMImport *import; uint32 mem_index = 0, i, @@ -474,26 +451,29 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, else #endif { - if (!(memories[mem_index++] = memory_instantiate( - module_inst, memory, num_bytes_per_page, init_page_count, - max_page_count, actual_heap_size, flags, error_buf, - error_buf_size))) { + if (!(memories[mem_index] = memory_instantiate( + module_inst, parent, memory, mem_index, + num_bytes_per_page, init_page_count, max_page_count, + actual_heap_size, flags, error_buf, error_buf_size))) { memories_deinstantiate(module_inst, memories, memory_count); return NULL; } + mem_index++; } } /* instantiate memories from memory section */ for (i = 0; i < module->memory_count; i++, memory++) { - if (!(memories[mem_index++] = memory_instantiate( - module_inst, memory, module->memories[i].num_bytes_per_page, + if (!(memories[mem_index] = memory_instantiate( + module_inst, parent, memory, mem_index, + module->memories[i].num_bytes_per_page, module->memories[i].init_page_count, module->memories[i].max_page_count, heap_size, module->memories[i].flags, error_buf, error_buf_size))) { memories_deinstantiate(module_inst, memories, memory_count); return NULL; } + mem_index++; } bh_assert(mem_index == memory_count); @@ -1301,7 +1281,7 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst, WASMModuleInstance *sub_module_inst = NULL; sub_module_inst = - wasm_instantiate(sub_module, false, NULL, stack_size, heap_size, + wasm_instantiate(sub_module, NULL, NULL, stack_size, heap_size, error_buf, error_buf_size); if (!sub_module_inst) { LOG_DEBUG("instantiate %s failed", @@ -1646,7 +1626,7 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode) * Instantiate module */ WASMModuleInstance * -wasm_instantiate(WASMModule *module, bool is_sub_inst, +wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size) { @@ -1663,6 +1643,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, #if WASM_ENABLE_MULTI_MODULE != 0 bool ret = false; #endif + const bool is_sub_inst = parent != NULL; if (!module) return NULL; @@ -1781,8 +1762,9 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, /* Instantiate memories/tables/functions */ if ((module_inst->memory_count > 0 - && !(module_inst->memories = memories_instantiate( - module, module_inst, heap_size, error_buf, error_buf_size))) + && !(module_inst->memories = + memories_instantiate(module, module_inst, parent, heap_size, + error_buf, error_buf_size))) || (module_inst->table_count > 0 && !(module_inst->tables = tables_instantiate(module, module_inst, first_table, diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index d5665c242..6698d0e75 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -7,6 +7,7 @@ #define _WASM_RUNTIME_H #include "wasm.h" +#include "bh_atomic.h" #include "bh_hashmap.h" #include "../common/wasm_runtime_common.h" #include "../common/wasm_exec_env.h" @@ -79,7 +80,7 @@ struct WASMMemoryInstance { /* Module type */ uint32 module_type; /* Shared memory flag */ - bool is_shared; + bh_atomic_32_t ref_count; /* 0: non-shared, > 0: reference count */ /* Number bytes per page */ uint32 num_bytes_per_page; @@ -400,7 +401,7 @@ void wasm_unload(WASMModule *module); WASMModuleInstance * -wasm_instantiate(WASMModule *module, bool is_sub_inst, +wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size); diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index 1a41fe9d7..b8a641165 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -581,7 +581,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, #endif if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, true, exec_env, stack_size, 0, NULL, 0))) + module, module_inst, exec_env, stack_size, 0, NULL, 0))) return -1; /* Set custom_data to new module instance */ diff --git a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c index 6b36c9073..a5f72986a 100644 --- a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c +++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c @@ -90,7 +90,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size; if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, true, exec_env, stack_size, 0, NULL, 0))) + module, module_inst, exec_env, stack_size, 0, NULL, 0))) return -1; wasm_runtime_set_custom_data_internal( diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index fc44652e5..4d1da83ac 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -509,7 +509,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) #endif if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, true, exec_env, stack_size, 0, NULL, 0))) { + module, module_inst, exec_env, stack_size, 0, NULL, 0))) { goto fail1; } @@ -1254,10 +1254,8 @@ set_exception_visitor(void *node, void *user_data) /* Only spread non "wasi proc exit" exception */ #if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory( - (WASMModuleCommon *)curr_wasm_inst->module); - if (shared_mem_node) - os_mutex_lock(&shared_mem_node->shared_mem_lock); + if (curr_wasm_inst->memory_count > 0) + shared_memory_lock(curr_wasm_inst->memories[0]); #endif if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) { bh_memcpy_s(curr_wasm_inst->cur_exception, @@ -1266,8 +1264,8 @@ set_exception_visitor(void *node, void *user_data) sizeof(wasm_inst->cur_exception)); } #if WASM_ENABLE_SHARED_MEMORY != 0 - if (shared_mem_node) - os_mutex_unlock(&shared_mem_node->shared_mem_lock); + if (curr_wasm_inst->memory_count > 0) + shared_memory_unlock(curr_wasm_inst->memories[0]); #endif /* Terminate the thread so it can exit from dead loops */ @@ -1286,15 +1284,13 @@ clear_exception_visitor(void *node, void *user_data) (WASMModuleInstance *)get_module_inst(curr_exec_env); #if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory( - (WASMModuleCommon *)curr_wasm_inst->module); - if (shared_mem_node) - os_mutex_lock(&shared_mem_node->shared_mem_lock); + if (curr_wasm_inst->memory_count > 0) + shared_memory_lock(curr_wasm_inst->memories[0]); #endif curr_wasm_inst->cur_exception[0] = '\0'; #if WASM_ENABLE_SHARED_MEMORY != 0 - if (shared_mem_node) - os_mutex_unlock(&shared_mem_node->shared_mem_lock); + if (curr_wasm_inst->memory_count > 0) + shared_memory_unlock(curr_wasm_inst->memories[0]); #endif } } From 8fc621a1b21655df6ffdb43a34b73eda303f69db Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 4 Aug 2023 14:32:04 +0800 Subject: [PATCH 047/123] Add runtime inited checks in Enclave command handlings to improve security (#2416) Call ecall commands arbitrarily from host when enclave's runtime isn't initialized may cause unexpected behavior, for example, load/instantiate wasm module. Add runtime inited status checks in enclave to improve the security. Also fix `wait_map` issue mentioned in https://github.com/bytecodealliance/wasm-micro-runtime/issues/2252#issuecomment-1634940219 --- .../enclave-sample/Enclave/Enclave.cpp | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp index 9ed17e1c8..164fa0b7d 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -92,6 +92,8 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) snprintf(error_buf, error_buf_size, "%s", string); } +static bool runtime_inited = false; + static void handle_cmd_init_runtime(uint64 *args, uint32 argc) { @@ -100,6 +102,12 @@ handle_cmd_init_runtime(uint64 *args, uint32 argc) bh_assert(argc == 1); + /* avoid duplicated init */ + if (runtime_inited) { + args[0] = false; + return; + } + os_set_print_function(enclave_print); max_thread_num = (uint32)args[0]; @@ -122,6 +130,7 @@ handle_cmd_init_runtime(uint64 *args, uint32 argc) return; } + runtime_inited = true; args[0] = true; LOG_VERBOSE("Init runtime environment success.\n"); @@ -130,7 +139,11 @@ handle_cmd_init_runtime(uint64 *args, uint32 argc) static void handle_cmd_destroy_runtime() { + if (!runtime_inited) + return; + wasm_runtime_destroy(); + runtime_inited = false; LOG_VERBOSE("Destroy runtime success.\n"); } @@ -214,6 +227,11 @@ handle_cmd_load_module(uint64 *args, uint32 argc) bh_assert(argc == 4); + if (!runtime_inited) { + *(void **)args_org = NULL; + return; + } + if (!is_xip_file((uint8 *)wasm_file, wasm_file_size)) { if (total_size >= UINT32_MAX || !(enclave_module = (EnclaveModule *)wasm_runtime_malloc( @@ -284,6 +302,10 @@ handle_cmd_unload_module(uint64 *args, uint32 argc) bh_assert(argc == 1); + if (!runtime_inited) { + return; + } + #if WASM_ENABLE_LIB_RATS != 0 /* Remove enclave module from enclave module list */ os_mutex_lock(&enclave_module_list_lock); @@ -354,6 +376,11 @@ handle_cmd_instantiate_module(uint64 *args, uint32 argc) bh_assert(argc == 5); + if (!runtime_inited) { + *(void **)args_org = NULL; + return; + } + if (!(module_inst = wasm_runtime_instantiate(enclave_module->module, stack_size, heap_size, error_buf, error_buf_size))) { @@ -373,6 +400,10 @@ handle_cmd_deinstantiate_module(uint64 *args, uint32 argc) bh_assert(argc == 1); + if (!runtime_inited) { + return; + } + wasm_runtime_deinstantiate(module_inst); LOG_VERBOSE("Deinstantiate module success.\n"); @@ -389,6 +420,11 @@ handle_cmd_get_exception(uint64 *args, uint32 argc) bh_assert(argc == 3); + if (!runtime_inited) { + args_org[0] = false; + return; + } + if ((exception1 = wasm_runtime_get_exception(module_inst))) { snprintf(exception, exception_size, "%s", exception1); args_org[0] = true; @@ -410,6 +446,10 @@ handle_cmd_exec_app_main(uint64 *args, int32 argc) bh_assert(argc >= 3); bh_assert(app_argc >= 1); + if (!runtime_inited) { + return; + } + total_size = sizeof(char *) * (app_argc > 2 ? (uint64)app_argc : 2); if (total_size >= UINT32_MAX @@ -439,6 +479,10 @@ handle_cmd_exec_app_func(uint64 *args, int32 argc) bh_assert(argc == app_argc + 3); + if (!runtime_inited) { + return; + } + total_size = sizeof(char *) * (app_argc > 2 ? (uint64)app_argc : 2); if (total_size >= UINT32_MAX @@ -488,6 +532,11 @@ handle_cmd_set_wasi_args(uint64 *args, int32 argc) bh_assert(argc == 10); + if (!runtime_inited) { + *args_org = false; + return; + } + total_size += sizeof(char *) * (uint64)dir_list_size + sizeof(char *) * (uint64)env_list_size + sizeof(char *) * (uint64)addr_pool_list_size @@ -610,6 +659,11 @@ handle_cmd_get_pgo_prof_buf_size(uint64 *args, int32 argc) bh_assert(argc == 1); + if (!runtime_inited) { + args[0] = 0; + return; + } + buf_len = wasm_runtime_get_pgo_prof_data_size(module_inst); args[0] = buf_len; } @@ -625,6 +679,11 @@ handle_cmd_get_pro_prof_buf_data(uint64 *args, int32 argc) bh_assert(argc == 3); + if (!runtime_inited) { + args_org[0] = 0; + return; + } + bytes_dumped = wasm_runtime_dump_pgo_prof_data_to_buf(module_inst, buf, len); args_org[0] = bytes_dumped; @@ -704,6 +763,11 @@ ecall_iwasm_main(uint8_t *wasm_file_buf, uint32_t wasm_file_size) char error_buf[128]; const char *exception; + /* avoid duplicated init */ + if (runtime_inited) { + return; + } + os_set_print_function(enclave_print); memset(&init_args, 0, sizeof(RuntimeInitArgs)); From ebd9466d57b6565e4211c71faefe13076cac2e3c Mon Sep 17 00:00:00 2001 From: dongsheng28849455 <68947925+dongsheng28849455@users.noreply.github.com> Date: Sun, 6 Aug 2023 08:08:11 +0800 Subject: [PATCH 048/123] Add some relocation symbols for xtensa target (#2422) --- core/iwasm/aot/arch/aot_reloc_xtensa.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/iwasm/aot/arch/aot_reloc_xtensa.c b/core/iwasm/aot/arch/aot_reloc_xtensa.c index 6ca6a0859..a29c9f2b9 100644 --- a/core/iwasm/aot/arch/aot_reloc_xtensa.c +++ b/core/iwasm/aot/arch/aot_reloc_xtensa.c @@ -43,6 +43,11 @@ void __floatdidf(); void __divsf3(); void __fixdfdi(); void __floatundidf(); +void __fixsfdi(); +void __fixunssfdi(); +void __fixunsdfdi(); +void __floatdisf(); +void __floatundisf(); static SymbolMap target_sym_map[] = { @@ -85,6 +90,11 @@ static SymbolMap target_sym_map[] = { REG_SYM(__divsf3), REG_SYM(__fixdfdi), REG_SYM(__floatundidf), + REG_SYM(__fixsfdi), + REG_SYM(__fixunssfdi), + REG_SYM(__fixunsdfdi), + REG_SYM(__floatdisf), + REG_SYM(__floatundisf), }; /* clang-format on */ From 81fbfbfcc0ca6ee88ffa9b11d8007695ad61fb51 Mon Sep 17 00:00:00 2001 From: Cengizhan Pasaoglu Date: Tue, 8 Aug 2023 03:52:25 +0300 Subject: [PATCH 049/123] Remove unnecessary and extra zero length check in mem functions' macro (#2428) In macro bh_memcpy_s, bh_memcy_wa and bh_memmove_s, no need to do extra check for length is zero or not because it was already done inside of the functions called. --- core/shared/utils/bh_common.c | 4 ++++ core/shared/utils/bh_common.h | 30 +++++++++++++++--------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/core/shared/utils/bh_common.c b/core/shared/utils/bh_common.c index aeeab26bd..7fe123c91 100644 --- a/core/shared/utils/bh_common.c +++ b/core/shared/utils/bh_common.c @@ -31,6 +31,10 @@ b_memcpy_wa(void *s1, unsigned int s1max, const void *s2, unsigned int n) unsigned int *p; char *ps; + if (n == 0) { + return 0; + } + if (pa > src) { pa -= 4; } diff --git a/core/shared/utils/bh_common.h b/core/shared/utils/bh_common.h index edb962eb1..adae722bb 100644 --- a/core/shared/utils/bh_common.h +++ b/core/shared/utils/bh_common.h @@ -12,25 +12,25 @@ extern "C" { #endif -#define bh_memcpy_s(dest, dlen, src, slen) \ - do { \ - int _ret = slen == 0 ? 0 : b_memcpy_s(dest, dlen, src, slen); \ - (void)_ret; \ - bh_assert(_ret == 0); \ +#define bh_memcpy_s(dest, dlen, src, slen) \ + do { \ + int _ret = b_memcpy_s(dest, dlen, src, slen); \ + (void)_ret; \ + bh_assert(_ret == 0); \ } while (0) -#define bh_memcpy_wa(dest, dlen, src, slen) \ - do { \ - int _ret = slen == 0 ? 0 : b_memcpy_wa(dest, dlen, src, slen); \ - (void)_ret; \ - bh_assert(_ret == 0); \ +#define bh_memcpy_wa(dest, dlen, src, slen) \ + do { \ + int _ret = b_memcpy_wa(dest, dlen, src, slen); \ + (void)_ret; \ + bh_assert(_ret == 0); \ } while (0) -#define bh_memmove_s(dest, dlen, src, slen) \ - do { \ - int _ret = slen == 0 ? 0 : b_memmove_s(dest, dlen, src, slen); \ - (void)_ret; \ - bh_assert(_ret == 0); \ +#define bh_memmove_s(dest, dlen, src, slen) \ + do { \ + int _ret = b_memmove_s(dest, dlen, src, slen); \ + (void)_ret; \ + bh_assert(_ret == 0); \ } while (0) #define bh_strcat_s(dest, dlen, src) \ From 51714c41c0c9210ecd0414849ea21d1d1dfcb937 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 8 Aug 2023 10:35:29 +0900 Subject: [PATCH 050/123] Introduce WASMModuleInstanceExtraCommon (#2429) Move the common parts of WASMModuleInstanceExtra and AOTModuleInstanceExtra into the new structure. --- core/iwasm/aot/aot_runtime.c | 10 +++++----- core/iwasm/aot/aot_runtime.h | 6 +----- core/iwasm/common/wasm_c_api.c | 4 ++-- core/iwasm/common/wasm_runtime_common.c | 8 ++++---- core/iwasm/interpreter/wasm_interp_classic.c | 5 +++-- core/iwasm/interpreter/wasm_interp_fast.c | 5 +++-- core/iwasm/interpreter/wasm_runtime.c | 9 +++++---- core/iwasm/interpreter/wasm_runtime.h | 16 +++++++++++----- core/iwasm/libraries/thread-mgr/thread_manager.c | 10 +++++----- 9 files changed, 39 insertions(+), 34 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 3e6371f42..94c66e679 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1271,9 +1271,9 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) if (module_inst->func_type_indexes) wasm_runtime_free(module_inst->func_type_indexes); - if (((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports) - wasm_runtime_free( - ((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports); + if (((AOTModuleInstanceExtra *)module_inst->e)->common.c_api_func_imports) + wasm_runtime_free(((AOTModuleInstanceExtra *)module_inst->e) + ->common.c_api_func_imports); if (!is_sub_inst) { #if WASM_ENABLE_LIBC_WASI != 0 @@ -1925,8 +1925,8 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, AOTModuleInstanceExtra *module_inst_extra = (AOTModuleInstanceExtra *)module_inst->e; CApiFuncImport *c_api_func_import = - module_inst_extra->c_api_func_imports - ? module_inst_extra->c_api_func_imports + func_idx + module_inst_extra->common.c_api_func_imports + ? module_inst_extra->common.c_api_func_imports + func_idx : NULL; uint32 *func_type_indexes = module_inst->func_type_indexes; uint32 func_type_idx = func_type_indexes[func_idx]; diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 2dea832be..895823af3 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -89,11 +89,7 @@ typedef struct AOTFunctionInstance { typedef struct AOTModuleInstanceExtra { DefPointer(const uint32 *, stack_sizes); - CApiFuncImport *c_api_func_imports; -#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 - /* Disable bounds checks or not */ - bool disable_bounds_checks; -#endif + WASMModuleInstanceExtraCommon common; } AOTModuleInstanceExtra; #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 7b8cf4779..a595a6269 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -4858,7 +4858,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) { WASMModuleInstanceExtra *e = ((WASMModuleInstance *)instance->inst_comm_rt)->e; - p_func_imports = &(e->c_api_func_imports); + p_func_imports = &(e->common.c_api_func_imports); import_func_count = MODULE_INTERP(module)->import_function_count; } #endif @@ -4868,7 +4868,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, (AOTModuleInstanceExtra *)((AOTModuleInstance *) instance->inst_comm_rt) ->e; - p_func_imports = &(e->c_api_func_imports); + p_func_imports = &(e->common.c_api_func_imports); import_func_count = MODULE_AOT(module)->import_func_count; } #endif diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 8e7933798..a39613a37 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2491,14 +2491,14 @@ wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst, #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { ((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e) - ->disable_bounds_checks = enable ? false : true; + ->common.disable_bounds_checks = enable ? false : true; } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e) - ->disable_bounds_checks = enable ? false : true; + ->common.disable_bounds_checks = enable ? false : true; } #endif } @@ -2511,7 +2511,7 @@ wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst) if (module_inst->module_type == Wasm_Module_Bytecode) { return !((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst) ->e) - ->disable_bounds_checks; + ->common.disable_bounds_checks; } #endif @@ -2519,7 +2519,7 @@ wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst) if (module_inst->module_type == Wasm_Module_AoT) { return !((AOTModuleInstanceExtra *)((WASMModuleInstance *)module_inst) ->e) - ->disable_bounds_checks; + ->common.disable_bounds_checks; } #endif diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 949900950..2a48c1bde 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -905,8 +905,9 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, if (!func_import->call_conv_wasm_c_api) { native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } - else if (module_inst->e->c_api_func_imports) { - c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; + else if (module_inst->e->common.c_api_func_imports) { + c_api_func_import = + module_inst->e->common.c_api_func_imports + cur_func_index; native_func_pointer = c_api_func_import->func_ptr_linked; } diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 729d4c60d..229a2151d 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -938,8 +938,9 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, if (!func_import->call_conv_wasm_c_api) { native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } - else if (module_inst->e->c_api_func_imports) { - c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; + else if (module_inst->e->common.c_api_func_imports) { + c_api_func_import = + module_inst->e->common.c_api_func_imports + cur_func_index; native_func_pointer = c_api_func_import->func_ptr_linked; } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index eef2e3688..0fdef512d 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2227,8 +2227,8 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) } #endif - if (module_inst->e->c_api_func_imports) - wasm_runtime_free(module_inst->e->c_api_func_imports); + if (module_inst->e->common.c_api_func_imports) + wasm_runtime_free(module_inst->e->common.c_api_func_imports); if (!is_sub_inst) { #if WASM_ENABLE_LIBC_WASI != 0 @@ -3141,8 +3141,9 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, import_func = &module->import_functions[func_idx].u.function; if (import_func->call_conv_wasm_c_api) { - if (module_inst->e->c_api_func_imports) { - c_api_func_import = module_inst->e->c_api_func_imports + func_idx; + if (module_inst->e->common.c_api_func_imports) { + c_api_func_import = + module_inst->e->common.c_api_func_imports + func_idx; func_ptr = c_api_func_import->func_ptr_linked; } else { diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 6698d0e75..3e0852487 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -210,8 +210,19 @@ typedef struct CApiFuncImport { void *env_arg; } CApiFuncImport; +/* The common part of WASMModuleInstanceExtra and AOTModuleInstanceExtra */ +typedef struct WASMModuleInstanceExtraCommon { + CApiFuncImport *c_api_func_imports; +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + /* Disable bounds checks or not */ + bool disable_bounds_checks; +#endif +} WASMModuleInstanceExtraCommon; + /* Extra info of WASM module instance for interpreter/jit mode */ typedef struct WASMModuleInstanceExtra { + WASMModuleInstanceExtraCommon common; + WASMGlobalInstance *globals; WASMFunctionInstance *functions; @@ -223,7 +234,6 @@ typedef struct WASMModuleInstanceExtra { WASMFunctionInstance *free_function; WASMFunctionInstance *retain_function; - CApiFuncImport *c_api_func_imports; RunningMode running_mode; #if WASM_ENABLE_MULTI_MODULE != 0 @@ -242,10 +252,6 @@ typedef struct WASMModuleInstanceExtra { && WASM_ENABLE_LAZY_JIT != 0) WASMModuleInstance *next; #endif -#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 - /* Disable bounds checks or not */ - bool disable_bounds_checks; -#endif } WASMModuleInstanceExtra; struct AOTFuncPerfProfInfo; diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 4d1da83ac..21425786a 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -746,10 +746,10 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, #if WASM_ENABLE_INTERP != 0 if (module_inst_src->module_type == Wasm_Module_Bytecode) { - new_c_api_func_imports = - &(((WASMModuleInstance *)module_inst_dst)->e->c_api_func_imports); + new_c_api_func_imports = &(((WASMModuleInstance *)module_inst_dst) + ->e->common.c_api_func_imports); c_api_func_imports = ((const WASMModuleInstance *)module_inst_src) - ->e->c_api_func_imports; + ->e->common.c_api_func_imports; import_func_count = ((WASMModule *)(((const WASMModuleInstance *)module_inst_src) ->module)) @@ -760,10 +760,10 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, if (module_inst_src->module_type == Wasm_Module_AoT) { AOTModuleInstanceExtra *e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_dst)->e; - new_c_api_func_imports = &(e->c_api_func_imports); + new_c_api_func_imports = &(e->common.c_api_func_imports); e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_src)->e; - c_api_func_imports = e->c_api_func_imports; + c_api_func_imports = e->common.c_api_func_imports; import_func_count = ((AOTModule *)(((AOTModuleInstance *)module_inst_src)->module)) From 7e3a29d5e4564406c91ada436b1e33d53d1232cf Mon Sep 17 00:00:00 2001 From: Cengizhan Pasaoglu Date: Wed, 9 Aug 2023 04:34:21 +0300 Subject: [PATCH 051/123] Strip static and shared libraries of iwasm to reduce the binary size (#2431) Reduce iwasm static and shared library size when CMAKE_STRIP is set and the build type is "Release". It remains as it is when build type was selected Debug. --- CMakeLists.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c8799494..fbea2616e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,11 @@ endif () set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +# Set the strip command based on the system (GNU or Clang) +if (CMAKE_STRIP) + set (CMAKE_STRIP_FLAGS "--strip-all") +endif () + include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wshadow -Wno-unused-parameter") @@ -141,6 +146,15 @@ endif () install (TARGETS iwasm_static ARCHIVE DESTINATION lib) +# If it's a Release build, strip the static library +if (CMAKE_STRIP AND CMAKE_BUILD_TYPE STREQUAL "Release") + # Strip static library + message (STATUS "Stripping static library after build!") + add_custom_command (TARGET iwasm_static POST_BUILD + COMMAND ${CMAKE_STRIP} ${CMAKE_STRIP_FLAGS} $ + ) +endif () + # SHARED LIBRARY add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE}) set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm) @@ -162,3 +176,12 @@ install (FILES ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h ${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h DESTINATION include) + +# If it's a Release build, strip the shared library +if (CMAKE_STRIP AND CMAKE_BUILD_TYPE STREQUAL "Release") + # Strip shared library + message (STATUS "Stripping shared library after build!") + add_custom_command (TARGET iwasm_shared POST_BUILD + COMMAND ${CMAKE_STRIP} ${CMAKE_STRIP_FLAGS} $ + ) +endif () From 8b5bb0009dc2b4d35417ee50878d7cd41ccf5ca7 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 9 Aug 2023 09:43:20 +0800 Subject: [PATCH 052/123] wasm_export.h: Fix struct wasm_val_t (#2435) Struct wasm_val_t should be same in wasm_export.h and wasm_c_api.h. And fix some invalid calls to aot function in LLVM JIT mode. --- core/iwasm/include/wasm_export.h | 2 + core/iwasm/interpreter/wasm_runtime.c | 71 +++++---------------------- 2 files changed, 13 insertions(+), 60 deletions(-) diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 4d02e027e..46bd3782d 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -186,6 +186,7 @@ enum wasm_valkind_enum { #ifndef WASM_VAL_T_DEFINED #define WASM_VAL_T_DEFINED +struct wasm_ref_t; typedef struct wasm_val_t { wasm_valkind_t kind; @@ -197,6 +198,7 @@ typedef struct wasm_val_t { double f64; /* represent a foreign object, aka externref in .wat */ uintptr_t foreign; + struct wasm_ref_t *ref; } of; } wasm_val_t; #endif diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 0fdef512d..b94be3289 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -3093,11 +3093,7 @@ llvm_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, { bool ret; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == exec_env->module_inst->module_type) { - return aot_call_indirect(exec_env, tbl_idx, elem_idx, argc, argv); - } -#endif + bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode); ret = call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, false, 0); #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -3124,11 +3120,7 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, char buf[96]; bool ret = false; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == exec_env->module_inst->module_type) { - return aot_invoke_native(exec_env, func_idx, argc, argv); - } -#endif + bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode); module_inst = (WASMModuleInstance *)wasm_runtime_get_module_inst(exec_env); module = module_inst->module; @@ -3198,11 +3190,7 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index, uint8 *maddr; uint64 seg_len = 0; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_memory_init(module_inst, seg_index, offset, len, dst); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); memory_inst = wasm_get_default_memory(module_inst); module = module_inst->module; @@ -3228,11 +3216,7 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index, bool llvm_jit_data_drop(WASMModuleInstance *module_inst, uint32 seg_index) { -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_data_drop(module_inst, seg_index); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); module_inst->module->data_segments[seg_index]->data_length = 0; /* Currently we can't free the dropped data segment @@ -3247,11 +3231,7 @@ llvm_jit_drop_table_seg(WASMModuleInstance *module_inst, uint32 tbl_seg_idx) { WASMTableSeg *tbl_segs; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_drop_table_seg(module_inst, tbl_seg_idx); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); tbl_segs = module_inst->module->table_segments; tbl_segs[tbl_seg_idx].is_dropped = true; @@ -3265,12 +3245,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, WASMTableInstance *tbl_inst; WASMTableSeg *tbl_seg; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_table_init(module_inst, tbl_idx, tbl_seg_idx, length, - src_offset, dst_offset); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); tbl_inst = wasm_get_table_inst(module_inst, tbl_idx); tbl_seg = module_inst->module->table_segments + tbl_seg_idx; @@ -3313,13 +3288,7 @@ llvm_jit_table_copy(WASMModuleInstance *module_inst, uint32 src_tbl_idx, WASMTableInstance *src_tbl_inst; WASMTableInstance *dst_tbl_inst; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - aot_table_copy(module_inst, src_tbl_idx, dst_tbl_idx, length, - src_offset, dst_offset); - return; - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); src_tbl_inst = wasm_get_table_inst(module_inst, src_tbl_idx); dst_tbl_inst = wasm_get_table_inst(module_inst, dst_tbl_idx); @@ -3350,12 +3319,7 @@ llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx, { WASMTableInstance *tbl_inst; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - aot_table_fill(module_inst, tbl_idx, length, val, data_offset); - return; - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); tbl_inst = wasm_get_table_inst(module_inst, tbl_idx); bh_assert(tbl_inst); @@ -3377,11 +3341,7 @@ llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx, WASMTableInstance *tbl_inst; uint32 i, orig_size, total_size; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_table_grow(module_inst, tbl_idx, inc_size, init_val); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); tbl_inst = wasm_get_table_inst(module_inst, tbl_idx); if (!tbl_inst) { @@ -3421,11 +3381,7 @@ llvm_jit_alloc_frame(WASMExecEnv *exec_env, uint32 func_index) WASMInterpFrame *frame; uint32 size; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == exec_env->module_inst->module_type) { - return aot_alloc_frame(exec_env, func_index); - } -#endif + bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode); module_inst = (WASMModuleInstance *)exec_env->module_inst; size = wasm_interp_interp_frame_size(0); @@ -3454,12 +3410,7 @@ llvm_jit_free_frame(WASMExecEnv *exec_env) WASMInterpFrame *frame; WASMInterpFrame *prev_frame; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == exec_env->module_inst->module_type) { - aot_free_frame(exec_env); - return; - } -#endif + bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode); frame = wasm_exec_env_get_cur_frame(exec_env); prev_frame = frame->prev_frame; From f34e7431fd3bd077f5f18e64c858a79910438b31 Mon Sep 17 00:00:00 2001 From: Florian Castellane <583664+LIII-XXII@users.noreply.github.com> Date: Wed, 9 Aug 2023 15:31:02 +0900 Subject: [PATCH 053/123] Fix typos in wamrc print_help() (#2442) --- wamr-compiler/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 1d3cedf74..8d2c93571 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -126,7 +126,7 @@ print_help() printf(" Use --cpu-features=+help to list all the features supported\n"); printf(" --opt-level=n Set the optimization level (0 to 3, default is 3)\n"); printf(" --size-level=n Set the code size level (0 to 3, default is 3)\n"); - printf(" -sgx Generate code for SGX platform (Intel Software Guard Extention)\n"); + printf(" -sgx Generate code for SGX platform (Intel Software Guard Extensions)\n"); printf(" --bounds-checks=1/0 Enable or disable the bounds checks for memory access:\n"); printf(" by default it is disabled in all 64-bit platforms except SGX and\n"); printf(" in these platforms runtime does bounds checks with hardware trap,\n"); @@ -159,8 +159,8 @@ print_help() printf(" --enable-dump-call-stack Enable stack trace feature\n"); printf(" --enable-perf-profiling Enable function performance profiling\n"); printf(" --enable-memory-profiling Enable memory usage profiling\n"); - printf(" --xip A shorthand of --enalbe-indirect-mode --disable-llvm-intrinsics\n"); - printf(" --enable-indirect-mode Enalbe call function through symbol table but not direct call\n"); + printf(" --xip A shorthand of --enable-indirect-mode --disable-llvm-intrinsics\n"); + printf(" --enable-indirect-mode Enable call function through symbol table but not direct call\n"); printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n"); printf(" --enable-builtin-intrinsics=\n"); printf(" Enable the specified built-in intrinsics, it will override the default\n"); From 490fa2ddaccd73834a69e60ce248620e1e0b0c40 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 9 Aug 2023 19:43:08 +0800 Subject: [PATCH 054/123] Auto-check wrgsbase in cmake script (#2437) Auto-check whether `WRGSBASE` instruction is supported in linux x86-64 in the cmake script. And if not, disable writing x86 GS register. --- build-scripts/config_common.cmake | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 6b4247e03..73ed83c9a 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -395,6 +395,30 @@ endif () if (WAMR_DISABLE_WRITE_GS_BASE EQUAL 1) add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=1) message (" Write linear memory base addr to x86 GS register disabled") +elseif (WAMR_BUILD_TARGET STREQUAL "X86_64" + AND WAMR_BUILD_PLATFORM STREQUAL "linux") + set (TEST_WRGSBASE_SOURCE "${CMAKE_BINARY_DIR}/test_wrgsbase.c") + file (WRITE "${TEST_WRGSBASE_SOURCE}" " + #include + #include + int main() { + uint64_t value; + asm volatile (\"wrgsbase %0\" : : \"r\"(value)); + printf(\"WRGSBASE instruction is available.\\n\"); + return 0; + }") + # Try to compile and run the test program + try_run (TEST_WRGSBASE_RESULT + TEST_WRGSBASE_COMPILED + ${CMAKE_BINARY_DIR}/test_wrgsbase + SOURCES ${TEST_WRGSBASE_SOURCE} + CMAKE_FLAGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + ) + #message("${TEST_WRGSBASE_COMPILED}, ${TEST_WRGSBASE_RESULT}") + if (NOT TEST_WRGSBASE_RESULT EQUAL 0) + add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=1) + message (" Write linear memory base addr to x86 GS register disabled") + endif () endif () if (WAMR_CONFIGUABLE_BOUNDS_CHECKS EQUAL 1) add_definitions (-DWASM_CONFIGURABLE_BOUNDS_CHECKS=1) From a550f4d9f7a346bc217efe3e89e4f55a44466315 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 10 Aug 2023 10:26:52 +0900 Subject: [PATCH 055/123] iwasm: call native lib init/deinit if exists (#2439) --- product-mini/platforms/posix/main.c | 20 ++++++++++++++++++++ samples/native-lib/README.md | 4 +++- samples/native-lib/test_hello2.c | 13 +++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 45214243c..0cf41909d 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -284,6 +284,8 @@ validate_env_str(char *env) #if BH_HAS_DLFCN typedef uint32 (*get_native_lib_func)(char **p_module_name, NativeSymbol **p_native_symbols); +typedef int (*init_native_lib_func)(void); +typedef void (*deinit_native_lib_func)(void); static uint32 load_and_register_native_libs(const char **native_lib_list, @@ -304,6 +306,18 @@ load_and_register_native_libs(const char **native_lib_list, continue; } + init_native_lib_func init_native_lib = dlsym(handle, "init_native_lib"); + if (init_native_lib) { + int ret = init_native_lib(); + if (ret != 0) { + LOG_WARNING("warning: `init_native_lib` function from native " + "lib %s failed with %d", + native_lib_list[i], ret); + dlclose(handle); + continue; + } + } + /* lookup get_native_lib func */ get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib"); if (!get_native_lib) { @@ -368,6 +382,12 @@ unregister_and_unload_native_libs(uint32 native_lib_count, continue; } + deinit_native_lib_func deinit_native_lib = + dlsym(handle, "deinit_native_lib"); + if (deinit_native_lib) { + deinit_native_lib(); + } + dlclose(handle); } } diff --git a/samples/native-lib/README.md b/samples/native-lib/README.md index 2bf65814d..80500ade0 100644 --- a/samples/native-lib/README.md +++ b/samples/native-lib/README.md @@ -62,6 +62,7 @@ cd build The output is: ```bash +init_native_lib in test_hello2.c called Hello World! 10 + 20 = 30 sqrt(10, 20) = 500 @@ -72,5 +73,6 @@ Message from test_hello: Hello, main. This is test_hello_wrapper! test_hello2("main", 0x0, 0) = 85 malloc(86) = 0x24e8 test_hello2("main", 0x24e8, 86) = 85 -Message from test_hello2: Hello, main. This is test_hello2_wrapper! Your wasm_module_inst_t is 0x7fd443704990. +Message from test_hello2: Hello, main. This is test_hello2_wrapper! Your wasm_module_inst_t is 0x7fe0e6804280. +deinit_native_lib in test_hello2.c called ``` diff --git a/samples/native-lib/test_hello2.c b/samples/native-lib/test_hello2.c index 2c8f69ed6..5dae79ca4 100644 --- a/samples/native-lib/test_hello2.c +++ b/samples/native-lib/test_hello2.c @@ -57,3 +57,16 @@ get_native_lib(char **p_module_name, NativeSymbol **p_native_symbols) *p_native_symbols = native_symbols; return sizeof(native_symbols) / sizeof(NativeSymbol); } + +int +init_native_lib() +{ + printf("%s in test_hello2.c called\n", __func__); + return 0; +} + +void +deinit_native_lib() +{ + printf("%s in test_hello2.c called\n", __func__); +} From 0b0af1b3df79e6c8b000c2dbcec36940dd195990 Mon Sep 17 00:00:00 2001 From: tonibofarull Date: Fri, 11 Aug 2023 01:55:40 +0200 Subject: [PATCH 056/123] wasi-nn: Support uint8 quantized networks (#2433) Support (non-full) uint8 quantized networks. Inputs and outputs are still required to be `float`. The (de)quantization is done internally by wasi-nn. Example generated from `quantized_model.py`: ![Screenshot from 2023-08-07 17-57-05](https://github.com/bytecodealliance/wasm-micro-runtime/assets/80318361/91f12ff6-870c-427a-b1dc-e307f7d1f5ee) Visualization with [netron](https://netron.app/). --- core/iwasm/libraries/wasi-nn/.gitignore | 2 + .../wasi-nn/src/wasi_nn_tensorflowlite.cpp | 74 +++++++++++++++---- .../libraries/wasi-nn/test/Dockerfile.cpu | 1 - .../wasi-nn/test/Dockerfile.nvidia-gpu | 1 - core/iwasm/libraries/wasi-nn/test/build.sh | 22 +++++- .../wasi-nn/test/models/quantized.py | 30 ++++++++ .../wasi-nn/test/test_tensorflow_quantized.c | 63 ++++++++++++++++ 7 files changed, 176 insertions(+), 17 deletions(-) create mode 100644 core/iwasm/libraries/wasi-nn/.gitignore create mode 100644 core/iwasm/libraries/wasi-nn/test/models/quantized.py create mode 100644 core/iwasm/libraries/wasi-nn/test/test_tensorflow_quantized.c diff --git a/core/iwasm/libraries/wasi-nn/.gitignore b/core/iwasm/libraries/wasi-nn/.gitignore new file mode 100644 index 000000000..81c0ff6aa --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/.gitignore @@ -0,0 +1,2 @@ +**/*.wasm +**/*.tflite diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp index d9fb2668e..b6fda1eba 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp @@ -285,14 +285,37 @@ tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx, return invalid_argument; } - auto *input = - tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor( - index); - if (input == NULL) - return missing_memory; + if (tensor->quantization.type == kTfLiteNoQuantization) { + NN_DBG_PRINTF("No quantization information. Using float as default"); + float *it = + tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor( + index); + + int size = model_tensor_size * sizeof(float); + bh_memcpy_s(it, size, input_tensor->data, size); + } + else { // TODO: Assumming uint8 quantized networks. + TfLiteAffineQuantization *quant_info = + (TfLiteAffineQuantization *)tensor->quantization.params; + if (quant_info->scale->size != 1 || quant_info->zero_point->size != 1) { + NN_ERR_PRINTF("Quantization per channel is not supported"); + return runtime_error; + } + uint8_t *it = + tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor( + index); + + float scale = quant_info->scale->data[0]; + float zero_point = (float)quant_info->zero_point->data[0]; + NN_DBG_PRINTF("input tensor: (scale, offset) = (%f, %f)", scale, + zero_point); + + float *input_tensor_f = (float *)input_tensor->data; + for (uint32_t i = 0; i < model_tensor_size; ++i) { + it[i] = (uint8_t)(input_tensor_f[i] / scale + zero_point); + } + } - bh_memcpy_s(input, model_tensor_size * sizeof(float), input_tensor->data, - model_tensor_size * sizeof(float)); return success; } @@ -325,6 +348,7 @@ tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx, NN_DBG_PRINTF("Number of tensors (%d)", num_output_tensors); if (index + 1 > num_output_tensors) { + NN_ERR_PRINTF("Index %d is invalid.", index); return runtime_error; } @@ -343,15 +367,37 @@ tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx, return missing_memory; } - float *tensor_f = - tfl_ctx->interpreters[ctx].interpreter->typed_output_tensor( - index); - for (uint32_t i = 0; i < model_tensor_size; ++i) - NN_DBG_PRINTF("output: %f", tensor_f[i]); + if (tensor->quantization.type == kTfLiteNoQuantization) { + NN_DBG_PRINTF("No quantization information"); + float *ot = + tfl_ctx->interpreters[ctx].interpreter->typed_output_tensor( + index); + + int size = model_tensor_size * sizeof(float); + bh_memcpy_s(output_tensor, size, ot, size); + } + else { // TODO: Assumming uint8 quantized networks. + TfLiteAffineQuantization *quant_info = + (TfLiteAffineQuantization *)tensor->quantization.params; + if (quant_info->scale->size != 1 || quant_info->zero_point->size != 1) { + NN_ERR_PRINTF("Quantization per channel is not supported"); + return runtime_error; + } + uint8_t *ot = tfl_ctx->interpreters[ctx] + .interpreter->typed_output_tensor(index); + + float scale = quant_info->scale->data[0]; + float zero_point = (float)quant_info->zero_point->data[0]; + NN_DBG_PRINTF("output tensor: (scale, offset) = (%f, %f)", scale, + zero_point); + + float *output_tensor_f = (float *)output_tensor; + for (uint32_t i = 0; i < model_tensor_size; ++i) { + output_tensor_f[i] = (ot[i] - zero_point) * scale; + } + } *output_tensor_size = model_tensor_size; - bh_memcpy_s(output_tensor, model_tensor_size * sizeof(float), tensor_f, - model_tensor_size * sizeof(float)); return success; } diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu b/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu index f98f121e7..6fe56567e 100644 --- a/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu @@ -30,7 +30,6 @@ RUN make -j "$(grep -c ^processor /proc/cpuinfo)" FROM ubuntu:22.04 -COPY --from=base /home/wamr/product-mini/platforms/linux/build/libvmlib.so /libvmlib.so COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /iwasm ENTRYPOINT [ "/iwasm" ] diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu b/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu index be80ad455..d78021eaa 100644 --- a/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu @@ -44,7 +44,6 @@ RUN mkdir -p /etc/OpenCL/vendors && \ ENV NVIDIA_VISIBLE_DEVICES=all ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility -COPY --from=base /home/wamr/product-mini/platforms/linux/build/libvmlib.so /libvmlib.so COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /iwasm ENTRYPOINT [ "/iwasm" ] diff --git a/core/iwasm/libraries/wasi-nn/test/build.sh b/core/iwasm/libraries/wasi-nn/test/build.sh index f018f6004..da6cfa5f8 100755 --- a/core/iwasm/libraries/wasi-nn/test/build.sh +++ b/core/iwasm/libraries/wasi-nn/test/build.sh @@ -1,6 +1,10 @@ +#!/bin/sh + # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +CURR_PATH=$(cd $(dirname $0) && pwd -P) + # WASM application that uses WASI-NN /opt/wasi-sdk/bin/clang \ @@ -13,9 +17,25 @@ # TFLite models to use in the tests -cd models +cd ${CURR_PATH}/models python3 average.py python3 max.py python3 mult_dimension.py python3 mult_outputs.py python3 sum.py + +# Specific tests for TPU + +cd ${CURR_PATH} +/opt/wasi-sdk/bin/clang \ + -Wl,--allow-undefined \ + -Wl,--strip-all,--no-entry \ + --sysroot=/opt/wasi-sdk/share/wasi-sysroot \ + -I../include -I../src/utils \ + -o test_tensorflow_quantized.wasm \ + test_tensorflow_quantized.c utils.c + +cd ${CURR_PATH}/models +python3 quantized.py + +cd ${CURR_PATH} diff --git a/core/iwasm/libraries/wasi-nn/test/models/quantized.py b/core/iwasm/libraries/wasi-nn/test/models/quantized.py new file mode 100644 index 000000000..b195b319f --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/models/quantized.py @@ -0,0 +1,30 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +import tensorflow as tf +import numpy as np +import pathlib + +model = tf.keras.Sequential([ + tf.keras.layers.InputLayer(input_shape=[5, 5, 1]), + tf.keras.layers.AveragePooling2D( + pool_size=(5, 5), strides=None, padding="valid", data_format=None) + +]) + +def representative_dataset(): + for _ in range(1000): + data = np.random.randint(0, 25, (1, 5, 5, 1)) + yield [data.astype(np.float32)] + +converter = tf.lite.TFLiteConverter.from_keras_model(model) +converter.optimizations = [tf.lite.Optimize.DEFAULT] +converter.representative_dataset = representative_dataset +converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] +converter.inference_input_type = tf.uint8 # or tf.int8 +converter.inference_output_type = tf.uint8 # or tf.int8 +tflite_model = converter.convert() + +tflite_models_dir = pathlib.Path("./") +tflite_model_file = tflite_models_dir / "quantized_model.tflite" +tflite_model_file.write_bytes(tflite_model) diff --git a/core/iwasm/libraries/wasi-nn/test/test_tensorflow_quantized.c b/core/iwasm/libraries/wasi-nn/test/test_tensorflow_quantized.c new file mode 100644 index 000000000..3ed7c751e --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/test_tensorflow_quantized.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include + +#include "utils.h" +#include "logger.h" + +#undef EPSILON +#define EPSILON 1e-2 + +void +test_average_quantized(execution_target target) +{ + int dims[] = { 1, 5, 5, 1 }; + input_info input = create_input(dims); + + uint32_t output_size = 0; + float *output = + run_inference(target, input.input_tensor, input.dim, &output_size, + "./models/quantized_model.tflite", 1); + + NN_INFO_PRINTF("Output size: %d", output_size); + NN_INFO_PRINTF("Result: average is %f", output[0]); + // NOTE: 11.95 instead of 12 because of errors due quantization + assert(fabs(output[0] - 11.95) < EPSILON); + + free(input.dim); + free(input.input_tensor); + free(output); +} + +int +main() +{ + char *env = getenv("TARGET"); + if (env == NULL) { + NN_INFO_PRINTF("Usage:\n--env=\"TARGET=[cpu|gpu|tpu]\""); + return 1; + } + execution_target target; + if (strcmp(env, "cpu") == 0) + target = cpu; + else if (strcmp(env, "gpu") == 0) + target = gpu; + else if (strcmp(env, "tpu") == 0) + target = tpu; + else { + NN_ERR_PRINTF("Wrong target!"); + return 1; + } + NN_INFO_PRINTF("################### Testing quantized model..."); + test_average_quantized(target); + + NN_INFO_PRINTF("Tests: passed!"); + return 0; +} From 5780effc07126d30cefa6c30e6197ae16413194b Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 14 Aug 2023 15:05:59 +0900 Subject: [PATCH 057/123] iwasm: Fix native lib cleanup after error occurs (#2443) - If something failed after calling init_native_lib, call deinit_native_lib to clean up. - Restructure the relevant code for better maintainability. --- product-mini/platforms/posix/main.c | 186 +++++++++++++++------------- 1 file changed, 99 insertions(+), 87 deletions(-) diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 0cf41909d..b79af9b83 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -282,113 +282,124 @@ validate_env_str(char *env) #endif #if BH_HAS_DLFCN -typedef uint32 (*get_native_lib_func)(char **p_module_name, - NativeSymbol **p_native_symbols); -typedef int (*init_native_lib_func)(void); -typedef void (*deinit_native_lib_func)(void); +struct native_lib { + void *handle; + + uint32 (*get_native_lib)(char **p_module_name, + NativeSymbol **p_native_symbols); + int (*init_native_lib)(void); + void (*deinit_native_lib)(void); + + char *module_name; + NativeSymbol *native_symbols; + uint32 n_native_symbols; +}; + +struct native_lib * +load_native_lib(const char *name) +{ + struct native_lib *lib = wasm_runtime_malloc(sizeof(*lib)); + if (lib == NULL) { + LOG_WARNING("warning: failed to load native library %s because of " + "allocation failure", + name); + goto fail; + } + memset(lib, 0, sizeof(*lib)); + + /* open the native library */ + if (!(lib->handle = dlopen(name, RTLD_NOW | RTLD_GLOBAL)) + && !(lib->handle = dlopen(name, RTLD_LAZY))) { + LOG_WARNING("warning: failed to load native library %s", name); + goto fail; + } + + lib->init_native_lib = dlsym(lib->handle, "init_native_lib"); + lib->get_native_lib = dlsym(lib->handle, "get_native_lib"); + lib->deinit_native_lib = dlsym(lib->handle, "deinit_native_lib"); + + if (!lib->get_native_lib) { + LOG_WARNING("warning: failed to lookup `get_native_lib` function " + "from native lib %s", + name); + goto fail; + } + + if (lib->init_native_lib) { + int ret = lib->init_native_lib(); + if (ret != 0) { + LOG_WARNING("warning: `init_native_lib` function from native " + "lib %s failed with %d", + name); + goto fail; + } + } + + lib->n_native_symbols = + lib->get_native_lib(&lib->module_name, &lib->native_symbols); + + /* register native symbols */ + if (!(lib->n_native_symbols > 0 && lib->module_name && lib->native_symbols + && wasm_runtime_register_natives( + lib->module_name, lib->native_symbols, lib->n_native_symbols))) { + LOG_WARNING("warning: failed to register native lib %s", name); + if (lib->deinit_native_lib) { + lib->deinit_native_lib(); + } + goto fail; + } + return lib; +fail: + if (lib != NULL) { + if (lib->handle != NULL) { + dlclose(lib->handle); + } + wasm_runtime_free(lib); + } + return NULL; +} static uint32 load_and_register_native_libs(const char **native_lib_list, uint32 native_lib_count, - void **native_handle_list) + struct native_lib **native_lib_loaded_list) { - uint32 i, native_handle_count = 0, n_native_symbols; - NativeSymbol *native_symbols; - char *module_name; - void *handle; + uint32 i, native_lib_loaded_count = 0; for (i = 0; i < native_lib_count; i++) { - /* open the native library */ - if (!(handle = dlopen(native_lib_list[i], RTLD_NOW | RTLD_GLOBAL)) - && !(handle = dlopen(native_lib_list[i], RTLD_LAZY))) { - LOG_WARNING("warning: failed to load native library %s", - native_lib_list[i]); + struct native_lib *lib = load_native_lib(native_lib_list[i]); + if (lib == NULL) { continue; } - - init_native_lib_func init_native_lib = dlsym(handle, "init_native_lib"); - if (init_native_lib) { - int ret = init_native_lib(); - if (ret != 0) { - LOG_WARNING("warning: `init_native_lib` function from native " - "lib %s failed with %d", - native_lib_list[i], ret); - dlclose(handle); - continue; - } - } - - /* lookup get_native_lib func */ - get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib"); - if (!get_native_lib) { - LOG_WARNING("warning: failed to lookup `get_native_lib` function " - "from native lib %s", - native_lib_list[i]); - dlclose(handle); - continue; - } - - n_native_symbols = get_native_lib(&module_name, &native_symbols); - - /* register native symbols */ - if (!(n_native_symbols > 0 && module_name && native_symbols - && wasm_runtime_register_natives(module_name, native_symbols, - n_native_symbols))) { - LOG_WARNING("warning: failed to register native lib %s", - native_lib_list[i]); - dlclose(handle); - continue; - } - - native_handle_list[native_handle_count++] = handle; + native_lib_loaded_list[native_lib_loaded_count++] = lib; } - return native_handle_count; + return native_lib_loaded_count; } static void unregister_and_unload_native_libs(uint32 native_lib_count, - void **native_handle_list) + struct native_lib **native_lib_loaded_list) { - uint32 i, n_native_symbols; - NativeSymbol *native_symbols; - char *module_name; - void *handle; + uint32 i; for (i = 0; i < native_lib_count; i++) { - handle = native_handle_list[i]; - - /* lookup get_native_lib func */ - get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib"); - if (!get_native_lib) { - LOG_WARNING("warning: failed to lookup `get_native_lib` function " - "from native lib %p", - handle); - continue; - } - - n_native_symbols = get_native_lib(&module_name, &native_symbols); - if (n_native_symbols == 0 || module_name == NULL - || native_symbols == NULL) { - LOG_WARNING("warning: get_native_lib returned different values for " - "native lib %p", - handle); - continue; - } + struct native_lib *lib = native_lib_loaded_list[i]; /* unregister native symbols */ - if (!wasm_runtime_unregister_natives(module_name, native_symbols)) { - LOG_WARNING("warning: failed to unregister native lib %p", handle); + if (!wasm_runtime_unregister_natives(lib->module_name, + lib->native_symbols)) { + LOG_WARNING("warning: failed to unregister native lib %p", + lib->handle); continue; } - deinit_native_lib_func deinit_native_lib = - dlsym(handle, "deinit_native_lib"); - if (deinit_native_lib) { - deinit_native_lib(); + if (lib->deinit_native_lib) { + lib->deinit_native_lib(); } - dlclose(handle); + dlclose(lib->handle); + wasm_runtime_free(lib); } } #endif /* BH_HAS_DLFCN */ @@ -525,8 +536,8 @@ main(int argc, char *argv[]) #if BH_HAS_DLFCN const char *native_lib_list[8] = { NULL }; uint32 native_lib_count = 0; - void *native_handle_list[8] = { NULL }; - uint32 native_handle_count = 0; + struct native_lib *native_lib_loaded_list[8]; + uint32 native_lib_loaded_count = 0; #endif #if WASM_ENABLE_DEBUG_INTERP != 0 char *ip_addr = NULL; @@ -810,8 +821,8 @@ main(int argc, char *argv[]) #endif #if BH_HAS_DLFCN - native_handle_count = load_and_register_native_libs( - native_lib_list, native_lib_count, native_handle_list); + native_lib_loaded_count = load_and_register_native_libs( + native_lib_list, native_lib_count, native_lib_loaded_list); #endif /* load WASM byte buffer from WASM bin file */ @@ -945,7 +956,8 @@ fail2: fail1: #if BH_HAS_DLFCN /* unload the native libraries */ - unregister_and_unload_native_libs(native_handle_count, native_handle_list); + unregister_and_unload_native_libs(native_lib_loaded_count, + native_lib_loaded_list); #endif /* destroy runtime environment */ From 5c6613b2b17184289c86cb0f86c707aa240364f3 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 14 Aug 2023 16:12:59 +0900 Subject: [PATCH 058/123] Correct --heap-size option in messages (#2458) --- core/iwasm/aot/aot_runtime.c | 4 ++-- core/iwasm/interpreter/wasm_runtime.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 94c66e679..2c647d345 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -420,7 +420,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, if (num_bytes_per_page < heap_size) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " - "try using `--heap_size=0` option"); + "try using `--heap-size=0` option"); return NULL; } } @@ -478,7 +478,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, if (init_page_count > DEFAULT_MAX_PAGES) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " - "try using `--heap_size=0` option"); + "try using `--heap-size=0` option"); return NULL; } else if (init_page_count == DEFAULT_MAX_PAGES) { diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index b94be3289..63df4cb37 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -202,7 +202,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, if (num_bytes_per_page < heap_size) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " - "try using `--heap_size=0` option"); + "try using `--heap-size=0` option"); return NULL; } } @@ -261,7 +261,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, if (init_page_count > DEFAULT_MAX_PAGES) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " - "try using `--heap_size=0` option"); + "try using `--heap-size=0` option"); return NULL; } else if (init_page_count == DEFAULT_MAX_PAGES) { From 8d1cf46f02a27f52b24103b5d5b5511dd3990a31 Mon Sep 17 00:00:00 2001 From: tonibofarull Date: Mon, 14 Aug 2023 10:45:30 +0200 Subject: [PATCH 059/123] Implement `wasm_externref_objdel` and `wasm_externref_set_cleanup` (#2455) ## Context Some native libraries may want to explicitly delete an externref object without waiting for the module instance to be deleted. In addition, it may want to add a cleanup function. ## Proposed Changes Implement: * `wasm_externref_objdel` to explicitly delete an externeref'd object. * `wasm_externref_set_cleanup` to set a cleanup function that is called when the externref'd object is deleted. --- core/iwasm/common/wasm_runtime_common.c | 84 +++++++++++++++++++++++-- core/iwasm/include/wasm_export.h | 26 ++++++++ 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index a39613a37..b18662157 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -4681,6 +4681,8 @@ typedef struct ExternRefMapNode { bool retained; /* Whether it is marked by runtime */ bool marked; + /* cleanup function called when the externref is freed */ + void (*cleanup)(void *); } ExternRefMapNode; static uint32 @@ -4743,6 +4745,81 @@ lookup_extobj_callback(void *key, void *value, void *user_data) } } +static void +delete_externref(void *key, ExternRefMapNode *node) +{ + bh_hash_map_remove(externref_map, key, NULL, NULL); + if (node->cleanup) { + (*node->cleanup)(node->extern_obj); + } + wasm_runtime_free(node); +} + +static void +delete_extobj_callback(void *key, void *value, void *user_data) +{ + ExternRefMapNode *node = (ExternRefMapNode *)value; + LookupExtObj_UserData *lookup_user_data = + (LookupExtObj_UserData *)user_data; + + if (node->extern_obj == lookup_user_data->node.extern_obj + && node->module_inst == lookup_user_data->node.module_inst) { + lookup_user_data->found = true; + delete_externref(key, node); + } +} + +bool +wasm_externref_objdel(WASMModuleInstanceCommon *module_inst, void *extern_obj) +{ + LookupExtObj_UserData lookup_user_data = { 0 }; + bool ok = false; + + /* in a wrapper, extern_obj could be any value */ + lookup_user_data.node.extern_obj = extern_obj; + lookup_user_data.node.module_inst = module_inst; + lookup_user_data.found = false; + + os_mutex_lock(&externref_lock); + /* Lookup hashmap firstly */ + bh_hash_map_traverse(externref_map, delete_extobj_callback, + (void *)&lookup_user_data); + if (lookup_user_data.found) { + ok = true; + } + os_mutex_unlock(&externref_lock); + + return ok; +} + +bool +wasm_externref_set_cleanup(WASMModuleInstanceCommon *module_inst, + void *extern_obj, void (*extern_obj_cleanup)(void *)) +{ + + LookupExtObj_UserData lookup_user_data = { 0 }; + bool ok = false; + + /* in a wrapper, extern_obj could be any value */ + lookup_user_data.node.extern_obj = extern_obj; + lookup_user_data.node.module_inst = module_inst; + lookup_user_data.found = false; + + os_mutex_lock(&externref_lock); + /* Lookup hashmap firstly */ + bh_hash_map_traverse(externref_map, lookup_extobj_callback, + (void *)&lookup_user_data); + if (lookup_user_data.found) { + void *key = (void *)(uintptr_t)lookup_user_data.externref_idx; + ExternRefMapNode *node = bh_hash_map_find(externref_map, key); + node->cleanup = extern_obj_cleanup; + ok = true; + } + os_mutex_unlock(&externref_lock); + + return ok; +} + bool wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj, uint32 *p_externref_idx) @@ -4792,6 +4869,7 @@ wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj, memset(node, 0, sizeof(ExternRefMapNode)); node->extern_obj = extern_obj; node->module_inst = module_inst; + node->cleanup = NULL; externref_idx = externref_global_id; @@ -4842,8 +4920,7 @@ reclaim_extobj_callback(void *key, void *value, void *user_data) if (node->module_inst == module_inst) { if (!node->marked && !node->retained) { - bh_hash_map_remove(externref_map, key, NULL, NULL); - wasm_runtime_free(value); + delete_externref(key, node); } else { node->marked = false; @@ -4958,8 +5035,7 @@ cleanup_extobj_callback(void *key, void *value, void *user_data) (WASMModuleInstanceCommon *)user_data; if (node->module_inst == module_inst) { - bh_hash_map_remove(externref_map, key, NULL, NULL); - wasm_runtime_free(value); + delete_externref(key, node); } } diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 46bd3782d..18e15782f 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1292,6 +1292,32 @@ WASM_RUNTIME_API_EXTERN bool wasm_externref_obj2ref(wasm_module_inst_t module_inst, void *extern_obj, uint32_t *p_externref_idx); +/** + * Delete external object registered by `wasm_externref_obj2ref`. + * + * @param module_inst the WASM module instance that the extern object + * belongs to + * @param extern_obj the external object to be deleted + * + * @return true if success, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_externref_objdel(wasm_module_inst_t module_inst, void *extern_obj); + +/** + * Set cleanup callback to release external object. + * + * @param module_inst the WASM module instance that the extern object + * belongs to + * @param extern_obj the external object to which to set the `extern_obj_cleanup` cleanup callback. + * @param extern_obj_cleanup a callback to release `extern_obj` + * + * @return true if success, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_externref_set_cleanup(wasm_module_inst_t module_inst, void *extern_obj, + void (*extern_obj_cleanup)(void *)); + /** * Retrieve the external object from an internal externref index * From e360b7a919247d2ab4d0363e1edf53bd8c073210 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 14 Aug 2023 18:27:14 +0900 Subject: [PATCH 060/123] wasm_instantiate: Fix a potential integer overflow issue (#2459) Fixes: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2450 --- core/iwasm/interpreter/wasm_runtime.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 63df4cb37..2b88c398f 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1839,7 +1839,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, for (i = 0; i < module->data_seg_count; i++) { WASMMemoryInstance *memory = NULL; uint8 *memory_data = NULL; - uint32 memory_size = 0; + uint64 memory_size = 0; WASMDataSeg *data_seg = module->data_segments[i]; #if WASM_ENABLE_BULK_MEMORY != 0 @@ -1852,7 +1852,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, bh_assert(memory); memory_data = memory->memory_data; - memory_size = memory->num_bytes_per_page * memory->cur_page_count; + memory_size = + (uint64)memory->num_bytes_per_page * memory->cur_page_count; bh_assert(memory_data || memory_size == 0); bh_assert(data_seg->base_offset.init_expr_type @@ -1898,7 +1899,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, /* check offset + length(could be zero) */ length = data_seg->data_length; - if (base_offset + length > memory_size) { + if ((uint64)base_offset + length > memory_size) { LOG_DEBUG("base_offset(%d) + length(%d) > memory_size(%d)", base_offset, length, memory_size); #if WASM_ENABLE_REF_TYPES != 0 From 923e8d64713e3349f192d75ff61c5e0591f32845 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 14 Aug 2023 19:04:49 +0800 Subject: [PATCH 061/123] Fix windows link error and clear windows warnings (#2463) - Fix windows wamrc link error: aot_generate_tempfile_name undefined. - Clear windows compile warnings. - And rename folder `samples/bh_atomic` and `samples/mem_allocator` to `samples/bh-atomic` and `samples/mem-allocator`. --- core/iwasm/compilation/aot_compiler.c | 27 +++++++++++++++++++ core/iwasm/compilation/aot_emit_aot_file.c | 18 ++++++------- core/iwasm/compilation/aot_llvm.c | 19 ++++++------- .../{bh_atomic => bh-atomic}/CMakeLists.txt | 0 samples/{bh_atomic => bh-atomic}/main.c | 0 .../CMakeLists.txt | 0 .../{mem_allocator => mem-allocator}/main.c | 0 7 files changed, 46 insertions(+), 18 deletions(-) rename samples/{bh_atomic => bh-atomic}/CMakeLists.txt (100%) rename samples/{bh_atomic => bh-atomic}/main.c (100%) rename samples/{mem_allocator => mem-allocator}/CMakeLists.txt (100%) rename samples/{mem_allocator => mem-allocator}/main.c (100%) diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index e99e2ae72..464ca61f3 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -2735,6 +2735,33 @@ aot_generate_tempfile_name(const char *prefix, const char *extension, snprintf(buffer + name_len, len - name_len, ".%s", extension); return buffer; } +#else + +errno_t +_mktemp_s(char *nameTemplate, size_t sizeInChars); + +char * +aot_generate_tempfile_name(const char *prefix, const char *extension, + char *buffer, uint32 len) +{ + int name_len; + + name_len = snprintf(buffer, len, "%s-XXXXXX", prefix); + + if (_mktemp_s(buffer, name_len + 1) != 0) { + return NULL; + } + + /* Check if buffer length is enough */ + /* name_len + '.' + extension + '\0' */ + if (name_len + 1 + strlen(extension) + 1 > len) { + aot_set_last_error("temp file name too long."); + return NULL; + } + + snprintf(buffer + name_len, len - name_len, ".%s", extension); + return buffer; +} #endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */ bool diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index bebae5506..f1a5c4796 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -2403,7 +2403,7 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data) && !strcmp(name, "__llvm_prf_cnts")) { snprintf(buf, sizeof(buf), "%s%u", name, llvm_prf_cnts_idx++); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(data_section->name = wasm_runtime_malloc(size))) { aot_set_last_error( "allocate memory for data section name failed."); @@ -2416,7 +2416,7 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data) && !strcmp(name, "__llvm_prf_data")) { snprintf(buf, sizeof(buf), "%s%u", name, llvm_prf_data_idx++); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(data_section->name = wasm_runtime_malloc(size))) { aot_set_last_error( "allocate memory for data section name failed."); @@ -2520,15 +2520,15 @@ read_stack_usage_file(const AOTCompContext *comp_ctx, const char *filename, } if (prefix == aot_func_prefix) { if (sz < precheck_stack_size_min) { - precheck_stack_size_min = sz; + precheck_stack_size_min = (uint32)sz; } if (sz > precheck_stack_size_max) { - precheck_stack_size_max = sz; + precheck_stack_size_max = (uint32)sz; } precheck_found++; continue; } - sizes[func_idx] = sz; + sizes[func_idx] = (uint32)sz; found++; } fclose(fp); @@ -2651,7 +2651,7 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data) * aot_emit_object_data_section_info will emit this copy. */ obj_data->stack_sizes_section_name = sec_name; - obj_data->stack_sizes_offset = addr; + obj_data->stack_sizes_offset = (uint32)addr; obj_data->stack_sizes = wasm_runtime_malloc( obj_data->func_count * sizeof(*obj_data->stack_sizes)); if (obj_data->stack_sizes == NULL) { @@ -2975,7 +2975,7 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data, || !strcmp(group->section_name, ".rel.text")) { snprintf(buf, sizeof(buf), "%s%u", relocation->symbol_name, prof_section_idx); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(relocation->symbol_name = wasm_runtime_malloc(size))) { aot_set_last_error( "allocate memory for relocation symbol name failed."); @@ -2990,7 +2990,7 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data, 19)) { snprintf(buf, sizeof(buf), "%s%u", relocation->symbol_name, prof_section_idx); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(relocation->symbol_name = wasm_runtime_malloc(size))) { aot_set_last_error( "allocate memory for relocation symbol name failed."); @@ -3156,7 +3156,7 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data) || !strcmp(name, ".rel__llvm_prf_data"))) { char buf[32]; snprintf(buf, sizeof(buf), "%s%u", name, llvm_prf_data_idx); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(relocation_group->section_name = wasm_runtime_malloc(size))) { aot_set_last_error( diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index e066f7a62..b47c198c3 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -237,9 +237,10 @@ get_inst_extra_offset(AOTCompContext *comp_ctx) const AOTCompData *comp_data = comp_ctx->comp_data; uint32 table_count = comp_data->import_table_count + comp_data->table_count; uint64 offset = get_tbl_inst_offset(comp_ctx, NULL, table_count); - bh_assert(offset <= UINT_MAX); - offset = align_uint(offset, 8); - return offset; + uint32 offset_32 = (uint32)offset; + bh_assert(offset <= UINT32_MAX); + offset_32 = align_uint((uint32)offset_32, 8); + return offset_32; } /* @@ -309,8 +310,8 @@ aot_add_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module, goto fail; } - unsigned int param_count = LLVMCountParams(precheck_func); - uint64 sz = param_count * sizeof(LLVMValueRef); + uint32 param_count = LLVMCountParams(precheck_func); + uint32 sz = param_count * (uint32)sizeof(LLVMValueRef); params = wasm_runtime_malloc(sz); if (params == NULL) { goto fail; @@ -626,8 +627,8 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module, if (comp_ctx->is_indirect_mode) { /* avoid LUT relocations ("switch-table") */ LLVMAttributeRef attr_no_jump_tables = LLVMCreateStringAttribute( - comp_ctx->context, "no-jump-tables", strlen("no-jump-tables"), - "true", strlen("true")); + comp_ctx->context, "no-jump-tables", + (uint32)strlen("no-jump-tables"), "true", (uint32)strlen("true")); LLVMAddAttributeAtIndex(func, LLVMAttributeFunctionIndex, attr_no_jump_tables); } @@ -2081,7 +2082,7 @@ jit_stack_size_callback(void *user_data, const char *name, size_t namelen, return; } /* ensure NUL termination */ - bh_memcpy_s(buf, sizeof(buf), name, namelen); + bh_memcpy_s(buf, (uint32)sizeof(buf), name, (uint32)namelen); buf[namelen] = 0; ret = sscanf(buf, AOT_FUNC_INTERNAL_PREFIX "%" SCNu32, &func_idx); @@ -2102,7 +2103,7 @@ jit_stack_size_callback(void *user_data, const char *name, size_t namelen, /* Note: -1 == AOT_NEG_ONE from aot_create_stack_sizes */ bh_assert(comp_ctx->jit_stack_sizes[func_idx] == (uint32)-1); - comp_ctx->jit_stack_sizes[func_idx] = stack_size + call_size; + comp_ctx->jit_stack_sizes[func_idx] = (uint32)stack_size + call_size; } static bool diff --git a/samples/bh_atomic/CMakeLists.txt b/samples/bh-atomic/CMakeLists.txt similarity index 100% rename from samples/bh_atomic/CMakeLists.txt rename to samples/bh-atomic/CMakeLists.txt diff --git a/samples/bh_atomic/main.c b/samples/bh-atomic/main.c similarity index 100% rename from samples/bh_atomic/main.c rename to samples/bh-atomic/main.c diff --git a/samples/mem_allocator/CMakeLists.txt b/samples/mem-allocator/CMakeLists.txt similarity index 100% rename from samples/mem_allocator/CMakeLists.txt rename to samples/mem-allocator/CMakeLists.txt diff --git a/samples/mem_allocator/main.c b/samples/mem-allocator/main.c similarity index 100% rename from samples/mem_allocator/main.c rename to samples/mem-allocator/main.c From b45d01411200a6760bec790bf9db2c7c1ebdd8bb Mon Sep 17 00:00:00 2001 From: tonibofarull Date: Mon, 14 Aug 2023 14:03:56 +0200 Subject: [PATCH 062/123] wasi-nn: Improve TPU support (#2447) 1. Allow TPU and GPU support at the same time. 2. Add Dockerfile to run example with [Coral USB](https://coral.ai/products/accelerator/). --- build-scripts/config_common.cmake | 12 ++-- core/config.h | 8 +++ core/iwasm/libraries/wasi-nn/README.md | 30 +++++++--- .../wasi-nn/cmake/Findtensorflow_lite.cmake | 6 +- .../wasi-nn/src/wasi_nn_tensorflowlite.cpp | 59 +++++++++++++------ .../wasi-nn/test/Dockerfile.nvidia-gpu | 2 +- .../libraries/wasi-nn/test/Dockerfile.tpu | 37 ++++++++++++ core/iwasm/libraries/wasi-nn/test/utils.c | 4 +- core/iwasm/libraries/wasi-nn/test/utils.h | 2 +- doc/build_wamr.md | 7 ++- 10 files changed, 130 insertions(+), 37 deletions(-) create mode 100644 core/iwasm/libraries/wasi-nn/test/Dockerfile.tpu diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 73ed83c9a..2751341e4 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -359,16 +359,16 @@ endif () if (WAMR_BUILD_WASI_NN EQUAL 1) message (" WASI-NN enabled") add_definitions (-DWASM_ENABLE_WASI_NN=1) - if (WASI_NN_ENABLE_GPU EQUAL 1) + if (WAMR_BUILD_WASI_NN_ENABLE_GPU EQUAL 1) message (" WASI-NN: GPU enabled") - add_definitions (-DWASI_NN_ENABLE_GPU=1) + add_definitions (-DWASM_ENABLE_WASI_NN_GPU=1) endif () - if (WAMR_BUILD_WASI_NN_ENABLE_EXT EQUAL 1) + if (WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE EQUAL 1) message (" WASI-NN: External Delegation enabled") - add_definitions (-DWASI_NN_ENABLE_EXTERNAL_DELEGATE=1) + add_definitions (-DWASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE=1) endif () - if (DEFINED WASI_NN_EXT_DELEGATE_PATH) - add_definitions (-DWASI_NN_EXT_DELEGATE_PATH="${WASI_NN_EXT_DELEGATE_PATH}") + if (DEFINED WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH) + add_definitions (-DWASM_WASI_NN_EXTERNAL_DELEGATE_PATH="${WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH}") endif () endif () if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1) diff --git a/core/config.h b/core/config.h index b6198811e..220f6751a 100644 --- a/core/config.h +++ b/core/config.h @@ -144,6 +144,14 @@ #define WASM_ENABLE_WASI_NN 0 #endif +#ifndef WASM_ENABLE_WASI_NN_GPU +#define WASM_ENABLE_WASI_NN_GPU 0 +#endif + +#ifndef WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE +#define WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE 0 +#endif + /* Default disable libc emcc */ #ifndef WASM_ENABLE_LIBC_EMCC #define WASM_ENABLE_LIBC_EMCC 0 diff --git a/core/iwasm/libraries/wasi-nn/README.md b/core/iwasm/libraries/wasi-nn/README.md index 96493a30f..fbc99ccbb 100644 --- a/core/iwasm/libraries/wasi-nn/README.md +++ b/core/iwasm/libraries/wasi-nn/README.md @@ -25,6 +25,7 @@ Build the runtime image for your execution target type. * `cpu` * `nvidia-gpu` * `vx-delegate` +* `tpu` ``` EXECUTION_TYPE=cpu @@ -64,6 +65,8 @@ docker run \ ``` * (NVIDIA) GPU + * Requirements: + * [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker). ``` docker run \ @@ -76,25 +79,36 @@ docker run \ /assets/test_tensorflow.wasm ``` -* vx-delegate for NPU (x86 simulater) +* vx-delegate for NPU (x86 simulator) ``` docker run \ - -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-vx-delegate \ - --dir=/assets \ + -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets \ + wasi-nn-vx-delegate \ + --dir=/ \ --env="TARGET=gpu" \ - /assets/test_tensorflow.wasm + /assets/test_tensorflow_quantized.wasm ``` +* (Coral) TPU + * Requirements: + * [Coral USB](https://coral.ai/products/accelerator/). - -Requirements: -* [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker). +``` +docker run \ + --privileged \ + --device=/dev/bus/usb:/dev/bus/usb \ + -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets \ + wasi-nn-tpu \ + --dir=/ \ + --env="TARGET=tpu" \ + /assets/test_tensorflow_quantized.wasm +``` ## What is missing Supported: * Graph encoding: `tensorflowlite`. -* Execution target: `cpu` and `gpu`. +* Execution target: `cpu`, `gpu` and `tpu`. * Tensor type: `fp32`. diff --git a/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake b/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake index 39cc10dc1..59fdaf758 100644 --- a/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake +++ b/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake @@ -18,12 +18,16 @@ if(NOT EXISTS ${TENSORFLOW_LITE}) set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") - if(WASI_NN_ENABLE_GPU EQUAL 1) + if(WAMR_BUILD_WASI_NN_ENABLE_GPU EQUAL 1) # Tensorflow specific: # * https://www.tensorflow.org/lite/guide/build_cmake#available_options_to_build_tensorflow_lite set (TFLITE_ENABLE_GPU ON) endif() + if (CMAKE_SIZEOF_VOID_P EQUAL 4) + set (TFLITE_ENABLE_XNNPACK OFF) + endif() + add_subdirectory( "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite" "${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp index b6fda1eba..65e38f867 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp @@ -16,11 +16,11 @@ #include #include -#if defined(WASI_NN_ENABLE_GPU) +#if WASM_ENABLE_WASI_NN_GPU != 0 #include #endif -#if defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE) +#if WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE != 0 #include #endif @@ -130,8 +130,8 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder, return invalid_argument; } - if (target != cpu && target != gpu) { - NN_ERR_PRINTF("Only CPU and GPU target is supported."); + if (target != cpu && target != gpu && target != tpu) { + NN_ERR_PRINTF("Only CPU, GPU and TPU target is supported."); return invalid_argument; } @@ -195,7 +195,7 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g, switch (tfl_ctx->models[g].target) { case gpu: { -#if defined(WASI_NN_ENABLE_GPU) +#if WASM_ENABLE_WASI_NN_GPU != 0 NN_WARN_PRINTF("GPU enabled."); // https://www.tensorflow.org/lite/performance/gpu TfLiteGpuDelegateOptionsV2 options = @@ -216,10 +216,19 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g, NN_ERR_PRINTF("Error when enabling GPU delegate."); use_default = true; } -#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE) +#else + NN_WARN_PRINTF("GPU not enabled."); + use_default = true; +#endif + break; + } + case tpu: + { +#if WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE != 0 NN_WARN_PRINTF("external delegation enabled."); TfLiteExternalDelegateOptions options = - TfLiteExternalDelegateOptionsDefault(WASI_NN_EXT_DELEGATE_PATH); + TfLiteExternalDelegateOptionsDefault( + WASM_WASI_NN_EXTERNAL_DELEGATE_PATH); tfl_ctx->delegate = TfLiteExternalDelegateCreate(&options); if (tfl_ctx->delegate == NULL) { NN_ERR_PRINTF("Error when generating External delegate."); @@ -233,7 +242,7 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g, use_default = true; } #else - NN_WARN_PRINTF("GPU not enabled."); + NN_WARN_PRINTF("External delegate not enabled."); use_default = true; #endif break; @@ -438,19 +447,35 @@ tensorflowlite_destroy(void *tflite_ctx) */ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; - if (tfl_ctx->delegate != NULL) { -#if defined(WASI_NN_ENABLE_GPU) - TfLiteGpuDelegateV2Delete(tfl_ctx->delegate); -#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE) - TfLiteExternalDelegateDelete(tfl_ctx->delegate); -#endif - } - NN_DBG_PRINTF("Freeing memory."); for (int i = 0; i < MAX_GRAPHS_PER_INST; ++i) { tfl_ctx->models[i].model.reset(); - if (tfl_ctx->models[i].model_pointer) + if (tfl_ctx->models[i].model_pointer) { + if (tfl_ctx->delegate) { + switch (tfl_ctx->models[i].target) { + case gpu: + { +#if WASM_ENABLE_WASI_NN_GPU != 0 + TfLiteGpuDelegateV2Delete(tfl_ctx->delegate); +#else + NN_ERR_PRINTF("GPU delegate delete but not enabled."); +#endif + break; + } + case tpu: + { +#if WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE != 0 + TfLiteExternalDelegateDelete(tfl_ctx->delegate); +#else + NN_ERR_PRINTF( + "External delegate delete but not enabled."); +#endif + break; + } + } + } wasm_runtime_free(tfl_ctx->models[i].model_pointer); + } tfl_ctx->models[i].model_pointer = NULL; } for (int i = 0; i < MAX_GRAPH_EXEC_CONTEXTS_PER_INST; ++i) { diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu b/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu index d78021eaa..737b2d3f0 100644 --- a/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu @@ -24,7 +24,7 @@ RUN apt-get install -y wget ca-certificates --no-install-recommends \ RUN cmake \ -DWAMR_BUILD_WASI_NN=1 \ - -DWASI_NN_ENABLE_GPU=1 \ + -DWAMR_BUILD_WASI_NN_ENABLE_GPU=1 \ .. RUN make -j "$(grep -c ^processor /proc/cpuinfo)" diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.tpu b/core/iwasm/libraries/wasi-nn/test/Dockerfile.tpu new file mode 100644 index 000000000..742645b06 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.tpu @@ -0,0 +1,37 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +FROM ubuntu:20.04 AS base + +ENV DEBIAN_FRONTEND=noninteractive + +# hadolint ignore=DL3008 +RUN apt-get update && apt-get install -y \ + cmake build-essential git curl gnupg --no-install-recommends && \ + rm -rf /var/lib/apt/lists/* + +# hadolint ignore=DL3008,DL4006 +RUN echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | tee /etc/apt/sources.list.d/coral-edgetpu.list && \ + curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \ + apt-get update && apt-get install -y libedgetpu1-std --no-install-recommends && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /home/wamr + +COPY . . + +WORKDIR /home/wamr/product-mini/platforms/linux/build + +RUN cmake \ + -DWAMR_BUILD_WASI_NN=1 \ + -DWAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE=1 \ + -DWAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH="libedgetpu.so.1.0" \ + -DWAMR_BUILD_WASI_NN_ENABLE_GPU=1 \ + .. + +RUN make -j "$(grep -c ^processor /proc/cpuinfo)" && \ + cp /home/wamr/product-mini/platforms/linux/build/iwasm /iwasm + +WORKDIR /assets + +ENTRYPOINT [ "/iwasm" ] diff --git a/core/iwasm/libraries/wasi-nn/test/utils.c b/core/iwasm/libraries/wasi-nn/test/utils.c index e0704cab4..7b4f65d16 100644 --- a/core/iwasm/libraries/wasi-nn/test/utils.c +++ b/core/iwasm/libraries/wasi-nn/test/utils.c @@ -132,8 +132,8 @@ run_inference(execution_target target, float *input, uint32_t *input_size, *output_size = MAX_OUTPUT_TENSOR_SIZE - *output_size; if (wasm_get_output(ctx, i, &out_tensor[offset], output_size) != success) { - NN_ERR_PRINTF("Error when getting output."); - exit(1); + NN_ERR_PRINTF("Error when getting index %d.", i); + break; } offset += *output_size; diff --git a/core/iwasm/libraries/wasi-nn/test/utils.h b/core/iwasm/libraries/wasi-nn/test/utils.h index 6373be542..0b2328406 100644 --- a/core/iwasm/libraries/wasi-nn/test/utils.h +++ b/core/iwasm/libraries/wasi-nn/test/utils.h @@ -11,7 +11,7 @@ #include "wasi_nn.h" #define MAX_MODEL_SIZE 85000000 -#define MAX_OUTPUT_TENSOR_SIZE 200 +#define MAX_OUTPUT_TENSOR_SIZE 1000000 #define INPUT_TENSOR_DIMS 4 #define EPSILON 1e-8 diff --git a/doc/build_wamr.md b/doc/build_wamr.md index a9d337164..81b4f6211 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -94,7 +94,12 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_BUILD_WASI_NN**=1/0, default to disable if not set #### **Enable lib wasi-nn GPU mode** -- **WASI_NN_ENABLE_GPU**=1/0, default to disable if not set +- **WAMR_BUILD_WASI_NN_ENABLE_GPU**=1/0, default to disable if not set + +#### **Enable lib wasi-nn external delegate mode** +- **WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE**=1/0, default to disable if not set + +- **WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH**=Path to the external delegate shared library (e.g. `libedgetpu.so.1.0` for Coral USB) #### **Disable boundary check with hardware trap** - **WAMR_DISABLE_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform From 365cdfeb712c10c8925e6befe73544de9a4cb597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A4mes=20M=C3=A9n=C3=A9trey?= Date: Tue, 15 Aug 2023 04:12:43 +0200 Subject: [PATCH 063/123] Upgrade SGX-RA integration for 0.1.2 and Ubuntu 20.04 (#2454) --- core/iwasm/libraries/lib-rats/lib_rats.cmake | 10 +++++ .../linux-sgx/enclave-sample/Makefile | 6 +-- samples/sgx-ra/README.md | 43 +++++++++---------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/core/iwasm/libraries/lib-rats/lib_rats.cmake b/core/iwasm/libraries/lib-rats/lib_rats.cmake index b773c837e..3ca08f160 100644 --- a/core/iwasm/libraries/lib-rats/lib_rats.cmake +++ b/core/iwasm/libraries/lib-rats/lib_rats.cmake @@ -23,6 +23,7 @@ include(FetchContent) set(RATS_BUILD_MODE "sgx" CACHE INTERNAL "Select build mode for librats(host|occlum|sgx|wasm)") set(RATS_INSTALL_PATH "${CMAKE_BINARY_DIR}/librats" CACHE INTERNAL "") +set(BUILD_SAMPLES OFF) FetchContent_Declare( librats @@ -34,8 +35,17 @@ if (NOT librats_POPULATED) message("-- Fetching librats ..") FetchContent_Populate(librats) include_directories("${librats_SOURCE_DIR}/include") + + # Prevent the propagation of the CMAKE_C_FLAGS of WAMR into librats + set(SAVED_CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) + set(CMAKE_C_FLAGS "") + + # Import the building scripts of librats add_subdirectory(${librats_SOURCE_DIR} ${librats_BINARY_DIR} EXCLUDE_FROM_ALL) + # Restore the CMAKE_C_FLAGS of WAMR + set(CMAKE_C_FLAGS ${SAVED_CMAKE_C_FLAGS}) + endif() file (GLOB source_all ${LIB_RATS_DIR}/*.c) diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Makefile b/product-mini/platforms/linux-sgx/enclave-sample/Makefile index 402545621..dae97a069 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Makefile +++ b/product-mini/platforms/linux-sgx/enclave-sample/Makefile @@ -143,10 +143,10 @@ else endif ifeq ($(WAMR_BUILD_LIB_RATS), 1) - Rats_Lib_Link_Dirs := -L$(LIB_RATS_INSTALL_DIR) -L$(LIB_RATS_INSTALL_DIR)/attesters -L$(LIB_RATS_INSTALL_DIR)/verifiers -L$(SGX_SSL)/lib64 + Rats_Lib_Link_Dirs := -L$(LIB_RATS_INSTALL_DIR) -L$(LIB_RATS_INSTALL_DIR)/attesters -L$(LIB_RATS_INSTALL_DIR)/verifiers -L$(SGX_SSL)/lib64 -L$(VMLIB_BUILD_DIR)/external/libcbor/src/libcbor/lib -L$(LIB_RATS_INSTALL_DIR)/crypto_wrappers Rats_Lib_W_Link_libs := -lattester_nullattester -lattester_sgx_ecdsa -lattester_sgx_la \ - -lverifier_nullverifier -lverifier_sgx_ecdsa -lverifier_sgx_la -lverifier_sgx_ecdsa_qve \ - -lrats_lib -lsgx_tsgxssl + -lverifier_nullverifier -lverifier_sgx_la -lverifier_sgx_ecdsa_qve -lcbor \ + -lrats_lib -lsgx_tsgxssl -lcrypto_wrapper_nullcrypto -lcrypto_wrapper_openssl Rats_Lib_NW_Link_libs := -lsgx_dcap_tvl -lsgx_tsgxssl_crypto endif diff --git a/samples/sgx-ra/README.md b/samples/sgx-ra/README.md index 39a2f2d9c..9270c96f1 100644 --- a/samples/sgx-ra/README.md +++ b/samples/sgx-ra/README.md @@ -7,52 +7,52 @@ This sample demonstrates how to execute Remote Attestation on SGX with [librats] SGX-RA requires to have installed: - the WASI-SDK, located in `/opt/wasi-sdk` - - CMake >= 3.11, which is not provided on Ubuntu 18.04 (use [Kitware APT Repository](https://apt.kitware.com/)) ### Intel SGX dependencies Before starting, we need to download and install [SGX SDK](https://download.01.org/intel-sgx/latest/linux-latest/distro) and [SGX DCAP Library](https://download.01.org/intel-sgx/latest/dcap-latest) referring to this [guide](https://download.01.org/intel-sgx/sgx-dcap/1.8/linux/docs/Intel_SGX_DCAP_Linux_SW_Installation_Guide.pdf). -The following commands are an example of the SGX environment installation on Ubuntu 18.04. +The following commands are an example of the SGX environment installation on Ubuntu 20.04. ``` shell # Set your platform, you can get the platforms list on # https://download.01.org/intel-sgx/latest/linux-latest/distro $ cd $HOME -$ SGX_PLATFORM=ubuntu18.04-server -$ SGX_SDK_VERSION=2.17.100.3 +$ OS_PLATFORM=ubuntu20.04 +$ SGX_PLATFORM=$OS_PLATFORM-server +$ SGX_RELEASE_VERSION=1.17 $ SGX_DRIVER_VERSION=1.41 +$ SGX_SDK_VERSION=2.20.100.4 # install the dependencies $ sudo apt-get update -$ sudo apt-get install -y dkms +$ sudo apt-get install -y build-essential ocaml automake autoconf libtool wget python3 libssl-dev dkms zip cmake +$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 # install SGX Driver -$ wget https://download.01.org/intel-sgx/latest/linux-latest/distro/$SGX_PLATFORM/sgx_linux_x64_driver_$SGX_DRIVER_VERSION.bin +$ wget https://download.01.org/intel-sgx/sgx-dcap/$SGX_RELEASE_VERSION/linux/distro/$SGX_PLATFORM/sgx_linux_x64_driver_$SGX_DRIVER_VERSION.bin $ chmod +x sgx_linux_x64_driver_$SGX_DRIVER_VERSION.bin $ sudo ./sgx_linux_x64_driver_$SGX_DRIVER_VERSION.bin # install SGX SDK -$ wget https://download.01.org/intel-sgx/latest/linux-latest/distro/$SGX_PLATFORM/sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin +$ wget https://download.01.org/intel-sgx/sgx-dcap/$SGX_RELEASE_VERSION/linux/distro/$SGX_PLATFORM/sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin $ chmod +x sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin -$ sudo ./sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin +$ sudo ./sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin --prefix /opt/intel # install SGX DCAP Library -$ echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu bionic main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list > /dev/null -$ wget -O - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add - +$ echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu focal main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list +$ wget -O - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add $ sudo apt-get update -$ sudo apt-get install -y libsgx-uae-service libsgx-dcap-default-qpl-dev libsgx-dcap-ql-dev libsgx-dcap-quote-verify-dev +$ sudo apt-get install -y libsgx-epid libsgx-quote-ex libsgx-dcap-ql libsgx-enclave-common-dev libsgx-dcap-ql-dev libsgx-dcap-default-qpl-dev libsgx-dcap-quote-verify-dev # install SGX SSL Library $ git clone https://github.com/intel/linux-sgx.git $ cd linux-sgx && make preparation -$ sudo cp external/toolset/{current_distr}/* /usr/local/bin +$ sudo cp external/toolset/$OS_PLATFORM/* /usr/local/bin $ # Verify that the paths are correctly set $ which ar as ld objcopy objdump ranlib $ cd ../ $ git clone https://github.com/intel/intel-sgx-ssl.git -$ wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz -$ cp openssl-1.1.1q.tar.gz intel-sgx-ssl/openssl_source -$ rm -f openssl-1.1.1q.tar.gz +$ wget https://www.openssl.org/source/openssl-1.1.1v.tar.gz -O intel-sgx-ssl/openssl_source/openssl-1.1.1v.tar.gz $ cd intel-sgx-ssl/Linux $ source /opt/intel/sgxsdk/environment $ make all @@ -70,7 +70,7 @@ sudo usermod -a -G sgx_prv Intel DCAP connects to Intel PCS to download the attestation collateral for SGX-enabled machines. Intel provides a [quick install guide](https://www.intel.com/content/www/us/en/developer/articles/guide/intel-software-guard-extensions-data-center-attestation-primitives-quick-install-guide.html) to set up a simplified environment. -This section summarizes the commands to issue for setting up a working environment on Ubuntu 18.04. +This section summarizes the commands to issue for setting up a working environment on Ubuntu 20.04. ### Subscribe to Intel PCS Web services @@ -86,11 +86,9 @@ Intel provides an implementation of the cache mechanism. The following commands set up Intel PCCS. ```shell # install Node.js -$ curl -o setup.sh -sL https://deb.nodesource.com/setup_14.x -$ chmod a+x setup.sh -$ sudo ./setup.sh +$ curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs # install PCCS software -$ sudo apt-get install -y cracklib-runtime sqlite3 python build-essential +$ sudo apt-get install -y cracklib-runtime $ sudo apt-get install -y sgx-dcap-pccs ``` @@ -160,9 +158,10 @@ Adapt the configuration file of `PCKIDRetrievalTool` located in `/opt/intel/sgx- Save your changes and run the provisioning tool. ```shell -$ PCKIDRetrievalTool -Intel(R) Software Guard Extensions PCK Cert ID Retrieval Tool Version 1.14.100.3 +$ sudo PCKIDRetrievalTool +Intel(R) Software Guard Extensions PCK Cert ID Retrieval Tool Version 1.17.100.4 +Registration status has been set to completed status. the data has been sent to cache server successfully and pckid_retrieval.csv has been generated successfully! ``` From 571c057549a39664403c8627ec9c04a34f6c4451 Mon Sep 17 00:00:00 2001 From: tonibofarull Date: Tue, 15 Aug 2023 04:32:43 +0200 Subject: [PATCH 064/123] wamr-python: Enable debugging WASM and grant dir access (#2449) - Enable debugging a WASM loaded and executed from Python. - Expose API to enable access to list of host directories. Similar to --dir in iwasm. - Add another python language binding sample: native-symbol. --- .../python/src/wamr/wamrapi/wamr.py | 143 +++++++++++++++--- language-bindings/python/utils/create_lib.sh | 7 +- language-bindings/python/wamr-api/README.md | 9 +- .../wamr-api/samples/{ => basic}/compile.sh | 0 .../wamr-api/samples/{ => basic}/main.py | 0 .../python/wamr-api/samples/{ => basic}/sum.c | 0 .../wamr-api/samples/native-symbol/README.md | 44 ++++++ .../wamr-api/samples/native-symbol/compile.sh | 14 ++ .../wamr-api/samples/native-symbol/func.c | 30 ++++ .../wamr-api/samples/native-symbol/main.py | 59 ++++++++ 10 files changed, 277 insertions(+), 29 deletions(-) rename language-bindings/python/wamr-api/samples/{ => basic}/compile.sh (100%) rename language-bindings/python/wamr-api/samples/{ => basic}/main.py (100%) rename language-bindings/python/wamr-api/samples/{ => basic}/sum.c (100%) create mode 100644 language-bindings/python/wamr-api/samples/native-symbol/README.md create mode 100755 language-bindings/python/wamr-api/samples/native-symbol/compile.sh create mode 100644 language-bindings/python/wamr-api/samples/native-symbol/func.c create mode 100644 language-bindings/python/wamr-api/samples/native-symbol/main.py diff --git a/language-bindings/python/src/wamr/wamrapi/wamr.py b/language-bindings/python/src/wamr/wamrapi/wamr.py index abbd23227..74cbad9f1 100644 --- a/language-bindings/python/src/wamr/wamrapi/wamr.py +++ b/language-bindings/python/src/wamr/wamrapi/wamr.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception from ctypes import Array +from ctypes import addressof from ctypes import c_char from ctypes import c_uint from ctypes import c_uint8 @@ -10,6 +11,8 @@ from ctypes import cast from ctypes import create_string_buffer from ctypes import POINTER from ctypes import pointer +from typing import List +from typing import Tuple from wamr.wamrapi.iwasm import String from wamr.wamrapi.iwasm import Alloc_With_Pool from wamr.wamrapi.iwasm import RuntimeInitArgs @@ -31,6 +34,14 @@ from wamr.wamrapi.iwasm import wasm_runtime_module_malloc from wamr.wamrapi.iwasm import wasm_runtime_module_free from wamr.wamrapi.iwasm import wasm_runtime_register_natives from wamr.wamrapi.iwasm import NativeSymbol +from wamr.wamrapi.iwasm import wasm_runtime_start_debug_instance +from wamr.wamrapi.iwasm import wasm_runtime_call_indirect +from wamr.wamrapi.iwasm import wasm_runtime_get_module_inst +from wamr.wamrapi.iwasm import wasm_runtime_addr_app_to_native +from wamr.wamrapi.iwasm import wasm_runtime_addr_native_to_app +from wamr.wamrapi.iwasm import wasm_runtime_set_wasi_args + +ID_TO_EXEC_ENV_MAPPING = {} class Engine: @@ -43,16 +54,26 @@ class Engine: print("deleting Engine") wasm_runtime_destroy() - def _get_init_args(self, heap_size: int = 1024 * 512) -> RuntimeInitArgs: + def _get_init_args( + self, + heap_size: int = 1024 * 1024 * 2, + ip_addr: str = "127.0.0.1", + instance_port: int = 1234, + ) -> RuntimeInitArgs: init_args = RuntimeInitArgs() init_args.mem_alloc_type = Alloc_With_Pool init_args.mem_alloc_option.pool.heap_buf = cast( (c_char * heap_size)(), c_void_p ) init_args.mem_alloc_option.pool.heap_size = heap_size + # Debug port setting + init_args.ip_addr = bytes(ip_addr, "utf-8") + init_args.instance_port = instance_port return init_args - def register_natives(self, module_name: str, native_symbols: list[NativeSymbol]) -> None: + def register_natives( + self, module_name: str, native_symbols: List[NativeSymbol] + ) -> None: module_name = String.from_param(module_name) # WAMR does not copy the symbols. We must store them. for native in native_symbols: @@ -62,12 +83,13 @@ class Engine: module_name, cast( (NativeSymbol * len(native_symbols))(*native_symbols), - POINTER(NativeSymbol) + POINTER(NativeSymbol), ), - len(native_symbols) + len(native_symbols), ): raise Exception("Error while registering symbols") + class Module: __create_key = object() @@ -86,7 +108,7 @@ class Module: print("deleting Module") wasm_runtime_unload(self.module) - def _create_module(self, fp: str) -> tuple[wasm_module_t, Array[c_uint]]: + def _create_module(self, fp: str) -> Tuple[wasm_module_t, "Array[c_uint]"]: with open(fp, "rb") as f: data = f.read() data = (c_uint8 * len(data))(*data) @@ -99,14 +121,52 @@ class Module: class Instance: - def __init__(self, module: Module, stack_size: int = 65536, heap_size: int = 16384): + def __init__( + self, + module: Module, + stack_size: int = 65536, + heap_size: int = 16384, + dir_list: List[str] | None = None, + preinitialized_module_inst: wasm_module_inst_t | None = None, + ): + # Store module ensures GC does not remove it self.module = module - self.module_inst = self._create_module_inst(module, stack_size, heap_size) + if preinitialized_module_inst is None: + self.module_inst = self._create_module_inst(module, stack_size, heap_size) + else: + self.module_inst = preinitialized_module_inst + if dir_list: + self._set_wasi_args(module, dir_list) def __del__(self): print("deleting Instance") wasm_runtime_deinstantiate(self.module_inst) + def _set_wasi_args(self, module: Module, dir_list: List[str]) -> None: + LP_c_char = POINTER(c_char) + LP_LP_c_char = POINTER(LP_c_char) + + p = (LP_c_char * len(dir_list))() + for i, dir in enumerate(dir_list): + enc_dir = dir.encode("utf-8") + p[i] = create_string_buffer(enc_dir) + + na = cast(p, LP_LP_c_char) + wasm_runtime_set_wasi_args( + module.module, na, len(dir_list), None, 0, None, 0, None, 0 + ) + + def _create_module_inst( + self, module: Module, stack_size: int, heap_size: int + ) -> wasm_module_inst_t: + error_buf = create_string_buffer(128) + module_inst = wasm_runtime_instantiate( + module.module, stack_size, heap_size, error_buf, len(error_buf) + ) + if not module_inst: + raise Exception("Error while creating module instance") + return module_inst + def malloc(self, nbytes: int, native_handler) -> c_uint: return wasm_runtime_module_malloc(self.module_inst, nbytes, native_handler) @@ -119,31 +179,70 @@ class Instance: raise Exception("Error while looking-up function") return func - def _create_module_inst(self, module: Module, stack_size: int, heap_size: int) -> wasm_module_inst_t: - error_buf = create_string_buffer(128) - module_inst = wasm_runtime_instantiate( - module.module, stack_size, heap_size, error_buf, len(error_buf) - ) - if not module_inst: - raise Exception("Error while creating module instance") - return module_inst + def native_addr_to_app_addr(self, native_addr) -> c_void_p: + return wasm_runtime_addr_native_to_app(self.module_inst, native_addr) + + def app_addr_to_native_addr(self, app_addr) -> c_void_p: + return wasm_runtime_addr_app_to_native(self.module_inst, app_addr) class ExecEnv: def __init__(self, module_inst: Instance, stack_size: int = 65536): self.module_inst = module_inst self.exec_env = self._create_exec_env(module_inst, stack_size) + self.env = addressof(self.exec_env.contents) + self.own_c = True + + ID_TO_EXEC_ENV_MAPPING[str(self.env)] = self def __del__(self): - print("deleting ExecEnv") - wasm_runtime_destroy_exec_env(self.exec_env) + if self.own_c: + print("deleting ExecEnv") + wasm_runtime_destroy_exec_env(self.exec_env) + del ID_TO_EXEC_ENV_MAPPING[str(self.env)] + + def _create_exec_env( + self, module_inst: Instance, stack_size: int + ) -> wasm_exec_env_t: + exec_env = wasm_runtime_create_exec_env(module_inst.module_inst, stack_size) + if not exec_env: + raise Exception("Error while creating execution environment") + return exec_env def call(self, func: wasm_function_inst_t, argc: int, argv: "POINTER[c_uint]"): if not wasm_runtime_call_wasm(self.exec_env, func, argc, argv): raise Exception("Error while calling function") - def _create_exec_env(self, module_inst: Instance, stack_size: int) -> wasm_exec_env_t: - exec_env = wasm_runtime_create_exec_env(module_inst.module_inst, stack_size) - if not exec_env: - raise Exception("Error while creating execution environment") - return exec_env + def get_module_inst(self) -> Instance: + return self.module_inst + + def start_debugging(self) -> int: + return wasm_runtime_start_debug_instance(self.exec_env) + + def call_indirect(self, element_index: int, argc: int, argv: "POINTER[c_uint]"): + if not wasm_runtime_call_indirect(self.exec_env, element_index, argc, argv): + raise Exception("Error while calling function") + + @staticmethod + def wrap(env: int) -> "ExecEnv": + if str(env) in ID_TO_EXEC_ENV_MAPPING: + return ID_TO_EXEC_ENV_MAPPING[str(env)] + return InternalExecEnv(env) + + +class InternalExecEnv(ExecEnv): + """ + Generate Python ExecEnv-like object from a `wasm_exec_env_t` index. + """ + + def __init__(self, env: int): + self.env = env + self.exec_env = cast(env, wasm_exec_env_t) + self.module_inst = Instance( + module=object(), + preinitialized_module_inst=wasm_runtime_get_module_inst(self.exec_env), + ) + ID_TO_EXEC_ENV_MAPPING[str(env)] = self + + def __del__(self): + del ID_TO_EXEC_ENV_MAPPING[str(self.env)] diff --git a/language-bindings/python/utils/create_lib.sh b/language-bindings/python/utils/create_lib.sh index b7e10d3ee..801186e97 100755 --- a/language-bindings/python/utils/create_lib.sh +++ b/language-bindings/python/utils/create_lib.sh @@ -12,7 +12,12 @@ WAMR_BUILD_PLATFORM=${WAMR_BUILD_PLATFORM:-${UNAME}} cd ${ROOT_DIR}/product-mini/platforms/${WAMR_BUILD_PLATFORM} mkdir -p build && cd build -cmake .. +cmake \ + -DWAMR_BUILD_DEBUG_INTERP=1 \ + -DWAMR_BUILD_LIB_PTHREAD=1 \ + -DWAMR_BUILD_LIB_WASI_THREADS=1 \ + -DWAMR_BUILD_LIB_WASI=1 \ + .. make -j case ${UNAME} in diff --git a/language-bindings/python/wamr-api/README.md b/language-bindings/python/wamr-api/README.md index 801c8aa1e..236150ce4 100644 --- a/language-bindings/python/wamr-api/README.md +++ b/language-bindings/python/wamr-api/README.md @@ -22,10 +22,7 @@ bash language-bindings/python/utils/create_lib.sh This will build and copy libiwasm into the package. -## Examples +## Samples -There is a [simple example](./samples/main.py) to show how to use bindings. - -``` -python samples/main.py -``` +- **[basic](./samples/basic)**: Demonstrating how to use basic python bindings. +- **[native-symbol](./samples/native-symbol)**: Desmostrate how to call WASM from Python and how to export Python functions into WASM. diff --git a/language-bindings/python/wamr-api/samples/compile.sh b/language-bindings/python/wamr-api/samples/basic/compile.sh similarity index 100% rename from language-bindings/python/wamr-api/samples/compile.sh rename to language-bindings/python/wamr-api/samples/basic/compile.sh diff --git a/language-bindings/python/wamr-api/samples/main.py b/language-bindings/python/wamr-api/samples/basic/main.py similarity index 100% rename from language-bindings/python/wamr-api/samples/main.py rename to language-bindings/python/wamr-api/samples/basic/main.py diff --git a/language-bindings/python/wamr-api/samples/sum.c b/language-bindings/python/wamr-api/samples/basic/sum.c similarity index 100% rename from language-bindings/python/wamr-api/samples/sum.c rename to language-bindings/python/wamr-api/samples/basic/sum.c diff --git a/language-bindings/python/wamr-api/samples/native-symbol/README.md b/language-bindings/python/wamr-api/samples/native-symbol/README.md new file mode 100644 index 000000000..75d4fab46 --- /dev/null +++ b/language-bindings/python/wamr-api/samples/native-symbol/README.md @@ -0,0 +1,44 @@ +# Native Symbol + +This sample demonstrates how to declare a Python function as `NativeSymbol`. + +Steps of the example: +1. Load WASM from Python +2. Call `c_func` from WASM. +3. `c_func` calls `python_func` from Python. +4. `python_func` calls `add` from WASM. +5. Result shown by Python. + +## Build + +Follow instructions [build wamr Python package](../../README.md). + +Compile WASM app example, + +```sh +./compile.sh +``` + +## Run sample + +```sh +python main.py +``` + +Output: + +``` +python: calling c_func(10) +c: in c_func with input: 10 +c: calling python_func(11) +python: in python_func with input: 11 +python: calling add(11, 1000) +python: result from add: 1011 +c: result from python_func: 1012 +c: returning 1013 +python: result from c_func: 1013 +deleting ExecEnv +deleting Instance +deleting Module +deleting Engine +``` diff --git a/language-bindings/python/wamr-api/samples/native-symbol/compile.sh b/language-bindings/python/wamr-api/samples/native-symbol/compile.sh new file mode 100755 index 000000000..4e504b018 --- /dev/null +++ b/language-bindings/python/wamr-api/samples/native-symbol/compile.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +/opt/wasi-sdk/bin/clang \ + -O0 -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--export=main -Wl,--export=__main_argc_argv \ + -Wl,--export=__data_end -Wl,--export=__heap_base \ + -Wl,--strip-all,--no-entry \ + -Wl,--allow-undefined \ + -Wl,--export=c_func\ + -Wl,--export=add\ + -o func.wasm func.c diff --git a/language-bindings/python/wamr-api/samples/native-symbol/func.c b/language-bindings/python/wamr-api/samples/native-symbol/func.c new file mode 100644 index 000000000..4411a6b2c --- /dev/null +++ b/language-bindings/python/wamr-api/samples/native-symbol/func.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +int +python_func(int val); + +int +add(int val1, int val2) +{ + return val1 + val2; +} + +int +c_func(int val) +{ + printf("c: in c_func with input: %d\n", val); + printf("c: calling python_func(%d)\n", val + 1); + int res = python_func(val + 1); + printf("c: result from python_func: %d\n", res); + printf("c: returning %d\n", res + 1); + return res + 1; +} + +int +main() +{} diff --git a/language-bindings/python/wamr-api/samples/native-symbol/main.py b/language-bindings/python/wamr-api/samples/native-symbol/main.py new file mode 100644 index 000000000..3871ef139 --- /dev/null +++ b/language-bindings/python/wamr-api/samples/native-symbol/main.py @@ -0,0 +1,59 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +from wamr.wamrapi.wamr import Engine, Module, Instance, ExecEnv +from ctypes import c_uint +import pathlib +from ctypes import c_int32 +from ctypes import c_uint +from ctypes import c_void_p +from ctypes import cast +from ctypes import CFUNCTYPE + +from wamr.wamrapi.iwasm import NativeSymbol +from wamr.wamrapi.iwasm import String +from wamr.wamrapi.wamr import ExecEnv + +def python_func(env: int, value: int) -> int: + print("python: in python_func with input:", value) + # Example of generating ExecEnv from `wasm_exec_env_t`` + exec_env = ExecEnv.wrap(env) + add = exec_env.get_module_inst().lookup_function("add") + const = 1000 + argv = (c_uint * 2)(value, const) + print(f"python: calling add({value}, {const})") + exec_env.call(add, 2, argv) + res = argv[0] + print("python: result from add:", res) + return res + 1 + + +native_symbols = (NativeSymbol * 1)( + *[ + NativeSymbol( + symbol=String.from_param("python_func"), + func_ptr=cast( + CFUNCTYPE(c_int32, c_void_p, c_int32)(python_func), c_void_p + ), + signature=String.from_param("(i)i"), + ) + ] +) + +def main(): + engine = Engine() + engine.register_natives("env", native_symbols) + module = Module.from_file(engine, pathlib.Path(__file__).parent / "func.wasm") + module_inst = Instance(module) + exec_env = ExecEnv(module_inst) + + func = module_inst.lookup_function("c_func") + + inp = 10 + print(f"python: calling c_func({inp})") + argv = (c_uint)(inp) + exec_env.call(func, 1, argv) + print("python: result from c_func:", argv.value) + +if __name__ == "__main__": + main() From a9bd6af0ac70a7e9c634917e8ff1d3a2e475a47e Mon Sep 17 00:00:00 2001 From: Maks Litskevich Date: Tue, 15 Aug 2023 03:36:10 +0100 Subject: [PATCH 065/123] Build wasi-libc from source in WAMR CI (#2465) We need to apply some bug fixes that were merged to wasi-libc because wasi-sdk-20 is about half a year old. It is a temporary solution and the code will be removed when wasi-sdk 21 is released. --- .../compilation_on_android_ubuntu.yml | 12 ++++++- .github/workflows/nightly_run.yml | 12 ++++++- .../libraries/lib-wasi-threads/test/build.sh | 33 +++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 5a0939b73..ee22af86f 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -483,6 +483,16 @@ jobs: sudo tar -xzf wasi-sdk-*.tar.gz sudo mv wasi-sdk-20.0 wasi-sdk + # It is a temporary solution until new wasi-sdk that includes bug fixes is released + - name: build wasi-libc from source + if: matrix.test_option == '$WASI_TEST_OPTIONS' + run: | + git clone https://github.com/WebAssembly/wasi-libc + cd wasi-libc + make -j AR=/opt/wasi-sdk/bin/llvm-ar NM=/opt/wasi-sdk/bin/llvm-nm CC=/opt/wasi-sdk/bin/clang THREAD_MODEL=posix + echo "SYSROOT_PATH=$PWD/sysroot" >> $GITHUB_ENV + + - name: set env variable(if llvm are used) if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit' run: echo "USE_LLVM=true" >> $GITHUB_ENV @@ -518,7 +528,7 @@ jobs: - name: Build WASI thread tests if: matrix.test_option == '$WASI_TEST_OPTIONS' - run: bash build.sh + run: bash build.sh --sysroot "$SYSROOT_PATH" working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/ - name: build socket api tests diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index cea5dccb1..b6cc15dcd 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -548,6 +548,16 @@ jobs: sudo wget ${{ matrix.wasi_sdk_release }} sudo tar -xzf wasi-sdk-*.tar.gz sudo mv wasi-sdk-20.0 wasi-sdk + + # It is a temporary solution until new wasi-sdk that includes bug fixes is released + - name: build wasi-libc from source + if: matrix.test_option == '$WASI_TEST_OPTIONS' + run: | + git clone https://github.com/WebAssembly/wasi-libc + cd wasi-libc + make -j AR=/opt/wasi-sdk/bin/llvm-ar NM=/opt/wasi-sdk/bin/llvm-nm CC=/opt/wasi-sdk/bin/clang THREAD_MODEL=posix + echo "SYSROOT_PATH=$PWD/sysroot" >> $GITHUB_ENV + - name: set env variable(if llvm are used) if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit' run: echo "USE_LLVM=true" >> $GITHUB_ENV @@ -586,7 +596,7 @@ jobs: - name: Build WASI thread tests if: matrix.test_option == '$WASI_TEST_OPTIONS' - run: bash build.sh + run: bash build.sh --sysroot "$SYSROOT_PATH" working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/ - name: build socket api tests diff --git a/core/iwasm/libraries/lib-wasi-threads/test/build.sh b/core/iwasm/libraries/lib-wasi-threads/test/build.sh index 611a3bd43..7c9a773c8 100755 --- a/core/iwasm/libraries/lib-wasi-threads/test/build.sh +++ b/core/iwasm/libraries/lib-wasi-threads/test/build.sh @@ -9,6 +9,30 @@ set -eo pipefail CC=${CC:=/opt/wasi-sdk/bin/clang} WAMR_DIR=../../../../.. +show_usage() { + echo "Usage: $0 [--sysroot PATH_TO_SYSROOT]" + echo "--sysroot PATH_TO_SYSROOT specify to build with custom sysroot for wasi-libc" +} + +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + --sysroot) + sysroot_path="$2" + shift + shift + ;; + --help) + show_usage + exit + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + # Stress tests names thread_start_file_exclusions=("spawn_stress_test.wasm" "linear_memory_size_update.wasm") @@ -21,6 +45,14 @@ for test_c in *.c; do thread_start_file=$WAMR_DIR/samples/wasi-threads/wasm-apps/wasi_thread_start.S fi + if [[ -n "$sysroot_path" ]]; then + if [ ! -d "$sysroot_path" ]; then + echo "Directory $sysroot_path doesn't exist. Aborting" + exit 1 + fi + sysroot_command="--sysroot $sysroot_path" + fi + echo "Compiling $test_c to $test_wasm" $CC \ -target wasm32-wasi-threads \ @@ -33,6 +65,7 @@ for test_c in *.c; do -Wl,--export=malloc \ -Wl,--export=free \ -I $WAMR_DIR/samples/wasi-threads/wasm-apps \ + $sysroot_command \ $thread_start_file \ $test_c -o $test_wasm done \ No newline at end of file From 0f18051e6695b575070eaa7541fe3bb9e097c613 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 15 Aug 2023 12:15:45 +0900 Subject: [PATCH 066/123] aot: Disable musttail for mips (#2457) Fixes https://github.com/bytecodealliance/wasm-micro-runtime/issues/2412 --- core/iwasm/compilation/aot_llvm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index b47c198c3..fb9fc0be4 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -146,6 +146,13 @@ aot_target_precheck_can_use_musttail(const AOTCompContext *comp_ctx) */ return false; } + if (!strcmp(comp_ctx->target_arch, "mips")) { + /* + * cf. + * https://github.com/bytecodealliance/wasm-micro-runtime/issues/2412 + */ + return false; + } /* * x86-64/i386: true * From c820643b2b94825833589b6fc6686a3ae3241318 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Wed, 16 Aug 2023 05:28:45 +0200 Subject: [PATCH 067/123] wamrc: More friendly to print help info (#2451) Allow wamrc to print help info like below: ```bash wamrc --target=help wamrc --target-abi=help wamrc --target= --cpu=help wamrc --target= --cpu=help --cpu-features=+help ``` --- core/iwasm/compilation/aot_llvm.c | 10 ++++++ wamr-compiler/main.c | 53 ++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index fb9fc0be4..f4bc8500e 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -2752,6 +2752,16 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) aot_set_last_error("create LLVM target machine failed."); goto fail; } + + /* If only to create target machine for querying information, early stop + */ + if ((arch && !strcmp(arch, "help")) || (abi && !strcmp(abi, "help")) + || (cpu && !strcmp(cpu, "help")) + || (features && !strcmp(features, "+help"))) { + LOG_DEBUG( + "create LLVM target machine only for printing help info."); + goto fail; + } } triple = LLVMGetTargetMachineTriple(comp_ctx->target_machine); diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 8d2c93571..0d85b99ce 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -193,6 +193,8 @@ print_help() printf("Examples: wamrc -o test.aot test.wasm\n"); printf(" wamrc --target=i386 -o test.aot test.wasm\n"); printf(" wamrc --target=i386 --format=object -o test.o test.wasm\n"); + printf(" wamrc --target-abi=help\n"); + printf(" wamrc --target=x86_64 --cpu=help\n"); } /* clang-format on */ @@ -296,6 +298,12 @@ resolve_segue_flags(char *str_flags) return segue_flags; } +/* When print help info for target/cpu/target-abi/cpu-features, load this dummy + * wasm file content rather than from an input file, the dummy wasm file content + * is: magic header + version number */ +static unsigned char dummy_wasm_file[8] = { 0x00, 0x61, 0x73, 0x6D, + 0x01, 0x00, 0x00, 0x00 }; + int main(int argc, char *argv[]) { @@ -309,7 +317,7 @@ main(int argc, char *argv[]) AOTCompOption option = { 0 }; char error_buf[128]; int log_verbose_level = 2; - bool sgx_mode = false, size_level_set = false; + bool sgx_mode = false, size_level_set = false, use_dummy_wasm = false; int exit_status = EXIT_FAILURE; #if BH_HAS_DLFCN const char *native_lib_list[8] = { NULL }; @@ -342,21 +350,33 @@ main(int argc, char *argv[]) if (argv[0][9] == '\0') PRINT_HELP_AND_EXIT(); option.target_arch = argv[0] + 9; + if (!strcmp(option.target_arch, "help")) { + use_dummy_wasm = true; + } } else if (!strncmp(argv[0], "--target-abi=", 13)) { if (argv[0][13] == '\0') PRINT_HELP_AND_EXIT(); option.target_abi = argv[0] + 13; + if (!strcmp(option.target_abi, "help")) { + use_dummy_wasm = true; + } } else if (!strncmp(argv[0], "--cpu=", 6)) { if (argv[0][6] == '\0') PRINT_HELP_AND_EXIT(); option.target_cpu = argv[0] + 6; + if (!strcmp(option.target_cpu, "help")) { + use_dummy_wasm = true; + } } else if (!strncmp(argv[0], "--cpu-features=", 15)) { if (argv[0][15] == '\0') PRINT_HELP_AND_EXIT(); option.cpu_features = argv[0] + 15; + if (!strcmp(option.cpu_features, "+help")) { + use_dummy_wasm = true; + } } else if (!strncmp(argv[0], "--opt-level=", 12)) { if (argv[0][12] == '\0') @@ -516,7 +536,7 @@ main(int argc, char *argv[]) PRINT_HELP_AND_EXIT(); } - if (argc == 0 || !out_file_name) + if (!use_dummy_wasm && (argc == 0 || !out_file_name)) PRINT_HELP_AND_EXIT(); if (!size_level_set) { @@ -544,11 +564,13 @@ main(int argc, char *argv[]) option.is_sgx_platform = true; } - wasm_file_name = argv[0]; + if (!use_dummy_wasm) { + wasm_file_name = argv[0]; - if (!strcmp(wasm_file_name, out_file_name)) { - printf("Error: input file and output file are the same"); - return -1; + if (!strcmp(wasm_file_name, out_file_name)) { + printf("Error: input file and output file are the same"); + return -1; + } } memset(&init_args, 0, sizeof(RuntimeInitArgs)); @@ -574,10 +596,17 @@ main(int argc, char *argv[]) bh_print_time("Begin to load wasm file"); - /* load WASM byte buffer from WASM bin file */ - if (!(wasm_file = - (uint8 *)bh_read_file_to_buffer(wasm_file_name, &wasm_file_size))) - goto fail1; + if (use_dummy_wasm) { + /* load WASM byte buffer from dummy buffer */ + wasm_file_size = sizeof(dummy_wasm_file); + wasm_file = dummy_wasm_file; + } + else { + /* load WASM byte buffer from WASM bin file */ + if (!(wasm_file = (uint8 *)bh_read_file_to_buffer(wasm_file_name, + &wasm_file_size))) + goto fail1; + } if (get_package_type(wasm_file, wasm_file_size) != Wasm_Module_Bytecode) { printf("Invalid file type: expected wasm file but got other\n"); @@ -659,7 +688,9 @@ fail3: fail2: /* free the file buffer */ - wasm_runtime_free(wasm_file); + if (!use_dummy_wasm) { + wasm_runtime_free(wasm_file); + } fail1: #if BH_HAS_DLFCN From 4ce675aacd7d69664c74f9daaf7badab38c4c80f Mon Sep 17 00:00:00 2001 From: Maks Litskevich Date: Thu, 17 Aug 2023 03:31:05 +0100 Subject: [PATCH 068/123] Add another wamr test (#2411) Follows up #2364 where we discussed that we might want to have a test which has really short thread function and creates many threads. --- .../compilation_on_android_ubuntu.yml | 4 +- .github/workflows/nightly_run.yml | 4 +- .../libraries/lib-wasi-threads/test/build.sh | 3 +- .../libraries/lib-wasi-threads/test/skip.json | 3 +- .../lib-wasi-threads/test/spawn_stress_test.c | 9 +- .../test/stress_test_threads_creation.c | 93 +++++++++++++++++++ .../wasi-test-script/run_wasi_tests.sh | 33 ++++--- 7 files changed, 127 insertions(+), 22 deletions(-) create mode 100644 core/iwasm/libraries/lib-wasi-threads/test/stress_test_threads_creation.c diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index ee22af86f..bbb2c4b3a 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -537,7 +537,7 @@ jobs: working-directory: ./core/iwasm/libraries/lib-socket/test/ - name: run tests - timeout-minutes: 20 + timeout-minutes: 30 run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites @@ -553,7 +553,7 @@ jobs: sudo apt install -y g++-multilib lib32gcc-9-dev - name: run tests x86_32 - timeout-minutes: 20 + timeout-minutes: 30 if: env.TEST_ON_X86_32 == 'true' run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index b6cc15dcd..0b82bb582 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -605,7 +605,7 @@ jobs: working-directory: ./core/iwasm/libraries/lib-socket/test/ - name: run tests - timeout-minutes: 20 + timeout-minutes: 40 run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites @@ -621,7 +621,7 @@ jobs: sudo apt install -y g++-multilib lib32gcc-9-dev - name: run tests x86_32 - timeout-minutes: 20 + timeout-minutes: 40 if: env.TEST_ON_X86_32 == 'true' run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites \ No newline at end of file diff --git a/core/iwasm/libraries/lib-wasi-threads/test/build.sh b/core/iwasm/libraries/lib-wasi-threads/test/build.sh index 7c9a773c8..78a081050 100755 --- a/core/iwasm/libraries/lib-wasi-threads/test/build.sh +++ b/core/iwasm/libraries/lib-wasi-threads/test/build.sh @@ -34,7 +34,7 @@ while [[ $# -gt 0 ]]; do done # Stress tests names -thread_start_file_exclusions=("spawn_stress_test.wasm" "linear_memory_size_update.wasm") +thread_start_file_exclusions=("spawn_stress_test.wasm" "linear_memory_size_update.wasm" "stress_test_threads_creation.wasm") for test_c in *.c; do test_wasm="$(basename $test_c .c).wasm" @@ -56,6 +56,7 @@ for test_c in *.c; do echo "Compiling $test_c to $test_wasm" $CC \ -target wasm32-wasi-threads \ + -O2 \ -pthread -ftls-model=local-exec \ -z stack-size=32768 \ -Wl,--export=__heap_base \ diff --git a/core/iwasm/libraries/lib-wasi-threads/test/skip.json b/core/iwasm/libraries/lib-wasi-threads/test/skip.json index 87db7667c..86a3ba25a 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/skip.json +++ b/core/iwasm/libraries/lib-wasi-threads/test/skip.json @@ -1,5 +1,6 @@ { "lib-wasi-threads tests": { - "spawn_stress_test": "Stress tests are incompatible with the other part and executed differently" + "spawn_stress_test": "Stress tests are incompatible with the other part and executed differently", + "stress_test_threads_creation": "Stress tests are incompatible with the other part and executed differently" } } diff --git a/core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c index 35175fc3e..fa49ac481 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c @@ -18,8 +18,9 @@ enum CONSTANTS { NUM_ITER = 100000, - NUM_RETRY = 5, + NUM_RETRY = 8, MAX_NUM_THREADS = 8, + RETRY_SLEEP_TIME_US = 2000, }; unsigned prime_numbers_count = 0; @@ -62,11 +63,13 @@ void spawn_thread(pthread_t *thread, unsigned int *arg) { int status_code = -1; + int timeout_us = RETRY_SLEEP_TIME_US; for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) { status_code = pthread_create(thread, NULL, &check_if_prime, arg); assert(status_code == 0 || status_code == EAGAIN); if (status_code == EAGAIN) { - usleep(2000); + usleep(timeout_us); + timeout_us *= 2; } } @@ -95,7 +98,7 @@ main(int argc, char **argv) args[thread_num] = factorised_number; - usleep(2000); + usleep(RETRY_SLEEP_TIME_US); spawn_thread(&threads[thread_num], &args[thread_num]); assert(threads[thread_num] != 0); } diff --git a/core/iwasm/libraries/lib-wasi-threads/test/stress_test_threads_creation.c b/core/iwasm/libraries/lib-wasi-threads/test/stress_test_threads_creation.c new file mode 100644 index 000000000..ef148f13b --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/test/stress_test_threads_creation.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include + +enum CONSTANTS { + NUM_ITER = 200000, + NUM_RETRY = 8, + MAX_NUM_THREADS = 8, + RETRY_SLEEP_TIME_US = 4000, + SECOND = 1000 * 1000 * 1000 +}; + +int threads_executed = 0; +unsigned int threads_creation_tried = 0; +unsigned int threads_in_use = 0; + +void * +thread_func(void *arg) +{ + (void)(arg); + __atomic_fetch_add(&threads_executed, 1, __ATOMIC_RELAXED); + __atomic_fetch_sub(&threads_in_use, 1, __ATOMIC_SEQ_CST); + return NULL; +} + +void +spawn_thread(pthread_t *thread) +{ + int status_code = -1; + int timeout_us = RETRY_SLEEP_TIME_US; + for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) { + status_code = pthread_create(thread, NULL, &thread_func, NULL); + __atomic_fetch_add(&threads_creation_tried, 1, __ATOMIC_RELAXED); + + assert(status_code == 0 || status_code == EAGAIN); + if (status_code == EAGAIN) { + usleep(timeout_us); + timeout_us *= 2; + } + } + + assert(status_code == 0 && "Thread creation should succeed"); +} + +int +main(int argc, char **argv) +{ + double percentage = 0.1; + + for (int iter = 0; iter < NUM_ITER; ++iter) { + if (iter > NUM_ITER * percentage) { + fprintf(stderr, "Spawning stress test is %d%% finished\n", + (unsigned int)(percentage * 100)); + percentage += 0.1; + } + while (__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) + == MAX_NUM_THREADS) { + usleep(100); + } + + __atomic_fetch_add(&threads_in_use, 1, __ATOMIC_SEQ_CST); + pthread_t tmp; + spawn_thread(&tmp); + pthread_detach(tmp); + } + + while ((__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) != 0)) { + __builtin_wasm_memory_atomic_wait32(&threads_in_use, 0, SECOND); + } + + assert(__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) == 0); + + // Validation + assert(threads_creation_tried >= threads_executed + && "Test executed more threads than were created"); + assert((1. * threads_creation_tried) / threads_executed < 2.5 + && "Ensuring that we're retrying thread creation less than 2.5 " + "times on average "); + + fprintf(stderr, + "Spawning stress test finished successfully executed %d threads " + "with retry ratio %f\n", + threads_creation_tried, + (1. * threads_creation_tried) / threads_executed); + return 0; +} diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index 9f13ee086..454fbb142 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -14,6 +14,7 @@ readonly WAMR_DIR="${WORK_DIR}/../../../.." readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm \ --allow-resolve=google-public-dns-a.google.com \ --addr-pool=::1/128,127.0.0.1/32" + readonly IWASM_CMD_STRESS="${IWASM_CMD} --max-threads=8" readonly WAMRC_CMD="${WORK_DIR}/../../../../wamr-compiler/build/wamrc" readonly C_TESTS="tests/c/testsuite/" @@ -21,18 +22,22 @@ readonly ASSEMBLYSCRIPT_TESTS="tests/assemblyscript/testsuite/" readonly THREAD_PROPOSAL_TESTS="tests/proposals/wasi-threads/" readonly THREAD_INTERNAL_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/test/" readonly LIB_SOCKET_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-socket/test/" +readonly STRESS_TESTS=("spawn_stress_test.wasm" "stress_test_threads_creation.wasm") run_aot_tests () { local tests=("$@") + local iwasm="${IWASM_CMD}" for test_wasm in ${tests[@]}; do local extra_stress_flags="" - if [[ "$test_wasm" =~ "stress" ]]; then - extra_stress_flags="--max-threads=8" - fi + for stress_test in "${STRESS_TESTS[@]}"; do + if [ "$test_wasm" == "$stress_test" ]; then + iwasm="${IWASM_CMD_STRESS}" + fi + done test_aot="${test_wasm%.wasm}.aot" test_json="${test_wasm%.wasm}.json" - + if [ -f ${test_wasm} ]; then expected=$(jq .exit_code ${test_json}) fi @@ -48,7 +53,6 @@ run_aot_tests () { fi ${IWASM_CMD} $extra_stress_flags $test_aot - ret=${PIPESTATUS[0]} echo "expected=$expected, actual=$ret" @@ -62,15 +66,18 @@ if [[ $MODE != "aot" ]];then python3 -m venv wasi-env && source wasi-env/bin/activate python3 -m pip install -r test-runner/requirements.txt - # Stress test requires max-threads=8 so it's run separately - if [[ -e "${THREAD_INTERNAL_TESTS}spawn_stress_test.wasm" ]]; then - ${IWASM_CMD_STRESS} ${THREAD_INTERNAL_TESTS}spawn_stress_test.wasm - ret=${PIPESTATUS[0]} - if [ "${ret}" -ne 0 ]; then - echo "Stress test spawn_stress_test FAILED with code " ${ret} - exit_code=${ret} + # Stress tests require max-threads=8 so they're executed separately + for stress_test in "${STRESS_TESTS[@]}"; do + if [[ -e "${THREAD_INTERNAL_TESTS}${stress_test}" ]]; then + echo "${stress_test}" is a stress test + ${IWASM_CMD_STRESS} ${THREAD_INTERNAL_TESTS}${stress_test} + ret=${PIPESTATUS[0]} + if [ "${ret}" -ne 0 ]; then + echo "Stress test ${stress_test} FAILED with code " ${ret} + exit_code=${ret} + fi fi - fi + done TEST_RUNTIME_EXE="${IWASM_CMD}" python3 test-runner/wasi_test_runner.py \ -r adapters/wasm-micro-runtime.py \ From e2f8721ec97d25f4f64a92563f42c69c8fc51b4b Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 17 Aug 2023 10:54:02 +0800 Subject: [PATCH 069/123] Fix issues reported by Coverity and clear windows warnings (#2467) --- core/iwasm/compilation/aot_emit_aot_file.c | 15 +++++++++------ core/iwasm/interpreter/wasm_runtime.c | 5 +++-- .../libraries/lib-wasi-threads/tid_allocator.c | 11 +++++++---- core/shared/platform/common/posix/posix_socket.c | 2 +- product-mini/platforms/posix/main.c | 2 +- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index f1a5c4796..4a5006adb 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -2605,9 +2605,16 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data) while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) { if ((name = LLVMGetSymbolName(sym_itr)) - && !strcmp(name, aot_stack_sizes_alias_name)) { + && (!strcmp(name, aot_stack_sizes_alias_name) + /* symbol of COFF32 starts with "_" */ + || (obj_data->target_info.bin_type == AOT_COFF32_BIN_TYPE + && !strncmp(name, "_", 1) + && !strcmp(name + 1, aot_stack_sizes_alias_name)))) { uint64 sz = LLVMGetSymbolSize(sym_itr); - if (sz != sizeof(uint32) * obj_data->func_count) { + if (sz != sizeof(uint32) * obj_data->func_count + /* sz of COFF64/COFF32 is 0, ignore the check */ + && obj_data->target_info.bin_type != AOT_COFF64_BIN_TYPE + && obj_data->target_info.bin_type != AOT_COFF32_BIN_TYPE) { aot_set_last_error("stack_sizes had unexpected size."); goto fail; } @@ -2642,10 +2649,6 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data) goto fail; } } - if (addr > UINT32_MAX) { - aot_set_last_error("too large stack_sizes offset."); - goto fail; - } /* * Record section/offset and construct a copy of stack_sizes. * aot_emit_object_data_section_info will emit this copy. diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 2b88c398f..b71b608a2 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1913,8 +1913,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, } if (memory_data) { - bh_memcpy_s(memory_data + base_offset, memory_size - base_offset, - data_seg->data, length); + bh_memcpy_s(memory_data + base_offset, + (uint32)memory_size - base_offset, data_seg->data, + length); } } diff --git a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c index 4d53da0c9..dc2d4f1bc 100644 --- a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c +++ b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c @@ -21,7 +21,8 @@ tid_allocator_init(TidAllocator *tid_allocator) return false; for (int64 i = tid_allocator->pos - 1; i >= 0; i--) - tid_allocator->ids[i] = TID_MIN + (tid_allocator->pos - 1 - i); + tid_allocator->ids[i] = + (uint32)(TID_MIN + (tid_allocator->pos - 1 - i)); return true; } @@ -54,7 +55,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator) LOG_ERROR("Overflow detected during realloc"); return -1; } - int32 *tmp = wasm_runtime_realloc(tid_allocator->ids, realloc_size); + int32 *tmp = + wasm_runtime_realloc(tid_allocator->ids, (uint32)realloc_size); if (tmp == NULL) { LOG_ERROR("Thread ID allocator realloc failed"); return -1; @@ -64,7 +66,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator) tid_allocator->pos = new_size - old_size; tid_allocator->ids = tmp; for (int64 i = tid_allocator->pos - 1; i >= 0; i--) - tid_allocator->ids[i] = TID_MIN + (tid_allocator->size - 1 - i); + tid_allocator->ids[i] = + (uint32)(TID_MIN + (tid_allocator->size - 1 - i)); } // Pop available thread identifier from the stack @@ -77,4 +80,4 @@ tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id) // Release thread identifier by pushing it into the stack bh_assert(tid_allocator->pos < tid_allocator->size); tid_allocator->ids[tid_allocator->pos++] = thread_id; -} \ No newline at end of file +} diff --git a/core/shared/platform/common/posix/posix_socket.c b/core/shared/platform/common/posix/posix_socket.c index c018588ae..d0a232bc5 100644 --- a/core/shared/platform/common/posix/posix_socket.c +++ b/core/shared/platform/common/posix/posix_socket.c @@ -275,7 +275,7 @@ os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, return -1; } } - else { + else if (src_addr) { memset(src_addr, 0, sizeof(*src_addr)); } diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index b79af9b83..5d20fd293 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -330,7 +330,7 @@ load_native_lib(const char *name) if (ret != 0) { LOG_WARNING("warning: `init_native_lib` function from native " "lib %s failed with %d", - name); + name, ret); goto fail; } } From 7baaed2fb82104e98c926965631618fecda9062e Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Thu, 17 Aug 2023 19:49:35 +0800 Subject: [PATCH 070/123] Fix opcode overwrite issue in fast interp (#2476) --- core/iwasm/interpreter/wasm_loader.c | 5 +++-- core/iwasm/interpreter/wasm_mini_loader.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 08441ec3e..c775ee6c0 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -8064,6 +8064,9 @@ re_scan: case WASM_OP_SELECT_T: { uint8 vec_len, ref_type; +#if WASM_ENABLE_FAST_INTERP != 0 + uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled; +#endif read_leb_uint32(p, p_end, vec_len); if (vec_len != 1) { @@ -8086,8 +8089,6 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 if (loader_ctx->p_code_compiled) { uint8 opcode_tmp = WASM_OP_SELECT; - uint8 *p_code_compiled_tmp = - loader_ctx->p_code_compiled - 2; if (ref_type == VALUE_TYPE_V128) { #if (WASM_ENABLE_SIMD == 0) \ diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 0aba14626..9f568e132 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -6233,6 +6233,9 @@ re_scan: case WASM_OP_SELECT_T: { uint8 vec_len, ref_type; +#if WASM_ENABLE_FAST_INTERP != 0 + uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled; +#endif read_leb_uint32(p, p_end, vec_len); if (vec_len != 1) { @@ -6255,8 +6258,6 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 if (loader_ctx->p_code_compiled) { uint8 opcode_tmp = WASM_OP_SELECT; - uint8 *p_code_compiled_tmp = - loader_ctx->p_code_compiled - 2; if (ref_type == VALUE_TYPE_F64 || ref_type == VALUE_TYPE_I64) From 6716c23dd17aa02e2e500740ab11bddf5b49ffc5 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 18 Aug 2023 09:56:00 +0800 Subject: [PATCH 071/123] wamrc: Fix windows relocation to `aot_func_internal#n` (#2474) AOT relocation to aot_func_internal#n is generated by wamrc --bounds-checks=1. Resolve the issue by applying the relocation in the compilation stage by wamrc and don't generate these relocations in the AOT file. Fixes #2471. --- core/iwasm/aot/arch/aot_reloc_x86_32.c | 3 + core/iwasm/aot/arch/aot_reloc_x86_64.c | 2 +- core/iwasm/compilation/aot_emit_aot_file.c | 144 ++++++++++++++++++++- 3 files changed, 142 insertions(+), 7 deletions(-) diff --git a/core/iwasm/aot/arch/aot_reloc_x86_32.c b/core/iwasm/aot/arch/aot_reloc_x86_32.c index 9246836c3..0a423c398 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_32.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_32.c @@ -164,6 +164,9 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, (uint32)((uintptr_t)symbol_addr + (intptr_t)reloc_addend - (uintptr_t)(target_section_addr + (uint32)reloc_offset) +#if defined(BH_PLATFORM_WINDOWS) + - sizeof(int32) +#endif + value); /* S + A - P */ break; } diff --git a/core/iwasm/aot/arch/aot_reloc_x86_64.c b/core/iwasm/aot/arch/aot_reloc_x86_64.c index 1221a6297..1bf5eb594 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_64.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_64.c @@ -242,7 +242,7 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, - (uintptr_t)(target_section_addr + reloc_offset)); } else { - target_addr = (intptr_t) /* L + A - P */ + target_addr = (intptr_t) /* S + A - P */ ((uintptr_t)symbol_addr + reloc_addend - (uintptr_t)(target_section_addr + reloc_offset)); } diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 4a5006adb..1b1e4403f 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -93,7 +93,10 @@ check_utf8_str(const uint8 *str, uint32 len) /* Internal function in object file */ typedef struct AOTObjectFunc { char *func_name; + /* text offset of aot_func#n */ uint64 text_offset; + /* text offset of aot_func_internal#n */ + uint64 text_offset_of_aot_func_internal; } AOTObjectFunc; /* Symbol table list node */ @@ -637,13 +640,33 @@ get_relocation_size(AOTRelocation *relocation, bool is_32bin) } static uint32 -get_relocations_size(AOTRelocation *relocations, uint32 relocation_count, +get_relocations_size(AOTObjectData *obj_data, + AOTRelocationGroup *relocation_group, + AOTRelocation *relocations, uint32 relocation_count, bool is_32bin) { AOTRelocation *relocation = relocations; uint32 size = 0, i; for (i = 0; i < relocation_count; i++, relocation++) { + /* ignore the relocations to aot_func_internal#n in text section + for windows platform since they will be applied in + aot_emit_text_section */ + if (!strcmp(relocation_group->section_name, ".text") + && !strncmp(relocation->symbol_name, AOT_FUNC_INTERNAL_PREFIX, + strlen(AOT_FUNC_INTERNAL_PREFIX)) + && ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6) + /* Windows AOT_COFF64_BIN_TYPE */ + && obj_data->target_info.bin_type == 6 + /* IMAGE_REL_AMD64_REL32 in windows x86_64 */ + && relocation->relocation_type == 4) + || (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4) + /* Windows AOT_COFF32_BIN_TYPE */ + && obj_data->target_info.bin_type == 4 + /* IMAGE_REL_I386_REL32 in windows x86_32 */ + && relocation->relocation_type == 20))) { + continue; + } size = align_uint(size, 4); size += get_relocation_size(relocation, is_32bin); } @@ -651,19 +674,22 @@ get_relocations_size(AOTRelocation *relocations, uint32 relocation_count, } static uint32 -get_relocation_group_size(AOTRelocationGroup *relocation_group, bool is_32bin) +get_relocation_group_size(AOTObjectData *obj_data, + AOTRelocationGroup *relocation_group, bool is_32bin) { uint32 size = 0; /* section name index + relocation count + relocations */ size += (uint32)sizeof(uint32); size += (uint32)sizeof(uint32); - size += get_relocations_size(relocation_group->relocations, + size += get_relocations_size(obj_data, relocation_group, + relocation_group->relocations, relocation_group->relocation_count, is_32bin); return size; } static uint32 -get_relocation_groups_size(AOTRelocationGroup *relocation_groups, +get_relocation_groups_size(AOTObjectData *obj_data, + AOTRelocationGroup *relocation_groups, uint32 relocation_group_count, bool is_32bin) { AOTRelocationGroup *relocation_group = relocation_groups; @@ -671,7 +697,7 @@ get_relocation_groups_size(AOTRelocationGroup *relocation_groups, for (i = 0; i < relocation_group_count; i++, relocation_group++) { size = align_uint(size, 4); - size += get_relocation_group_size(relocation_group, is_32bin); + size += get_relocation_group_size(obj_data, relocation_group, is_32bin); } return size; } @@ -864,7 +890,7 @@ get_relocation_section_size(AOTCompContext *comp_ctx, AOTObjectData *obj_data) /* relocation group count + symbol_table + relocation groups */ return (uint32)sizeof(uint32) + symbol_table_size - + get_relocation_groups_size(relocation_groups, + + get_relocation_groups_size(obj_data, relocation_groups, relocation_group_count, is_32bit_binary(obj_data)); } @@ -1734,6 +1760,10 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, uint32 section_size = get_text_section_size(obj_data); uint32 offset = *p_offset; uint8 placeholder = 0; + AOTRelocationGroup *relocation_group; + AOTRelocation *relocation; + uint32 i, j, relocation_count; + uint8 *text; *p_offset = offset = align_uint(offset, 4); @@ -1747,6 +1777,8 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, EMIT_BUF(&placeholder, 1); } + text = buf + offset; + if (obj_data->text_size > 0) { EMIT_BUF(obj_data->text, obj_data->text_size); while (offset & 3) @@ -1768,6 +1800,67 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, return false; } + /* apply relocations to aot_func_internal#n in text section for + windows platform */ + if ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6) + /* Windows AOT_COFF64_BIN_TYPE */ + && obj_data->target_info.bin_type == 6) + || (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4) + /* Windows AOT_COFF32_BIN_TYPE */ + && obj_data->target_info.bin_type == 4)) { + relocation_group = obj_data->relocation_groups; + for (i = 0; i < obj_data->relocation_group_count; + i++, relocation_group++) { + /* relocation in text section */ + if (!strcmp(relocation_group->section_name, ".text")) { + relocation = relocation_group->relocations; + relocation_count = relocation_group->relocation_count; + for (j = 0; j < relocation_count; j++) { + /* relocation to aot_func_internal#n */ + if (str_starts_with(relocation->symbol_name, + AOT_FUNC_INTERNAL_PREFIX) + && ((obj_data->target_info.bin_type + == 6 /* AOT_COFF64_BIN_TYPE */ + && relocation->relocation_type + == 4 /* IMAGE_REL_AMD64_REL32 */) + || (obj_data->target_info.bin_type + == 4 /* AOT_COFF32_BIN_TYPE */ + && obj_data->target_info.bin_type + == 20 /* IMAGE_REL_I386_REL32 */))) { + uint32 func_idx = + atoi(relocation->symbol_name + + strlen(AOT_FUNC_INTERNAL_PREFIX)); + uint64 text_offset, reloc_offset, reloc_addend; + + bh_assert(func_idx < obj_data->func_count); + + text_offset = obj_data->funcs[func_idx] + .text_offset_of_aot_func_internal; + reloc_offset = relocation->relocation_offset; + reloc_addend = relocation->relocation_addend; + /* S + A - P */ + *(uint32 *)(text + reloc_offset) = + (uint32)(text_offset + reloc_addend - reloc_offset + - 4); + + /* remove current relocation as it has been applied */ + if (j < relocation_count - 1) { + uint32 move_size = + (uint32)(sizeof(AOTRelocation) + * (relocation_count - 1 - j)); + bh_memmove_s(relocation, move_size, relocation + 1, + move_size); + } + relocation_group->relocation_count--; + } + else { + relocation++; + } + } + } + } + } + *p_offset = offset; return true; @@ -2773,6 +2866,7 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data) while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) { if ((name = (char *)LLVMGetSymbolName(sym_itr)) && str_starts_with(name, prefix)) { + /* symbol aot_func#n */ func_index = (uint32)atoi(name + strlen(prefix)); if (func_index < obj_data->func_count) { LLVMSectionIteratorRef contain_section; @@ -2807,6 +2901,44 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data) } } } + else if ((name = (char *)LLVMGetSymbolName(sym_itr)) + && str_starts_with(name, AOT_FUNC_INTERNAL_PREFIX)) { + /* symbol aot_func_internal#n */ + func_index = (uint32)atoi(name + strlen(AOT_FUNC_INTERNAL_PREFIX)); + if (func_index < obj_data->func_count) { + LLVMSectionIteratorRef contain_section; + char *contain_section_name; + + func = obj_data->funcs + func_index; + + if (!(contain_section = LLVMObjectFileCopySectionIterator( + obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + LLVMDisposeSymbolIterator(sym_itr); + return false; + } + LLVMMoveToContainingSection(contain_section, sym_itr); + contain_section_name = + (char *)LLVMGetSectionName(contain_section); + LLVMDisposeSectionIterator(contain_section); + + if (!strcmp(contain_section_name, ".text.unlikely.")) { + func->text_offset_of_aot_func_internal = + align_uint(obj_data->text_size, 4) + + LLVMGetSymbolAddress(sym_itr); + } + else if (!strcmp(contain_section_name, ".text.hot.")) { + func->text_offset_of_aot_func_internal = + align_uint(obj_data->text_size, 4) + + align_uint(obj_data->text_unlikely_size, 4) + + LLVMGetSymbolAddress(sym_itr); + } + else { + func->text_offset_of_aot_func_internal = + LLVMGetSymbolAddress(sym_itr); + } + } + } LLVMMoveToNextSymbol(sym_itr); } LLVMDisposeSymbolIterator(sym_itr); From 2cb701f7f3b4f8b2d0f65b499677338034b2403b Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 18 Aug 2023 10:16:03 +0800 Subject: [PATCH 072/123] Fix windows AOT hw bound check (#2475) When AOT out of bound linear memory access or stack overflow occurs, the call stack of AOT functions cannot be unwound currently, so from the exception handler, runtime cannot jump back into the place that calls the AOT function. We temporarily skip the current instruction and let AOT code continue to run and return to caller as soon as possible. And use the zydis library the decode the current instruction to get its size. And remove using RtlAddFunctionTable to register the AOT functions since it doesn't work currently. --- core/iwasm/aot/aot_loader.c | 53 --------- core/iwasm/aot/aot_runtime.h | 32 ------ core/iwasm/aot/arch/aot_reloc_x86_64.c | 15 --- core/iwasm/aot/iwasm_aot.cmake | 46 +++++++- core/iwasm/common/wasm_runtime_common.c | 125 ++++++++++++++++----- core/iwasm/compilation/aot_emit_function.c | 22 +++- 6 files changed, 159 insertions(+), 134 deletions(-) diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 50e36f9ee..0ce2cf9da 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -1644,27 +1644,6 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, const uint8 *p = buf, *p_end = buf_end; uint32 i; uint64 size, text_offset; -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - RUNTIME_FUNCTION *rtl_func_table; - AOTUnwindInfo *unwind_info; - uint32 unwind_info_offset = module->code_size - sizeof(AOTUnwindInfo); - uint32 unwind_code_offset = unwind_info_offset - PLT_ITEM_SIZE; -#endif - -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - unwind_info = (AOTUnwindInfo *)((uint8 *)module->code + module->code_size - - sizeof(AOTUnwindInfo)); - unwind_info->Version = 1; - unwind_info->Flags = UNW_FLAG_NHANDLER; - *(uint32 *)&unwind_info->UnwindCode[0] = unwind_code_offset; - - size = sizeof(RUNTIME_FUNCTION) * (uint64)module->func_count; - if (size > 0 - && !(rtl_func_table = module->rtl_func_table = - loader_malloc(size, error_buf, error_buf_size))) { - return false; - } -#endif size = sizeof(void *) * (uint64)module->func_count; if (size > 0 @@ -1691,33 +1670,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, #if defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_THUMB_VFP) /* bits[0] of thumb function address must be 1 */ module->func_ptrs[i] = (void *)((uintptr_t)module->func_ptrs[i] | 1); -#endif -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - rtl_func_table[i].BeginAddress = (DWORD)text_offset; - if (i > 0) { - rtl_func_table[i - 1].EndAddress = rtl_func_table[i].BeginAddress; - } - rtl_func_table[i].UnwindInfoAddress = (DWORD)unwind_info_offset; #endif } -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - if (module->func_count > 0) { - uint32 plt_table_size = - module->is_indirect_mode ? 0 : get_plt_table_size(); - rtl_func_table[module->func_count - 1].EndAddress = - (DWORD)(module->code_size - plt_table_size); - - if (!RtlAddFunctionTable(rtl_func_table, module->func_count, - (DWORD64)(uintptr_t)module->code)) { - set_error_buf(error_buf, error_buf_size, - "add dynamic function table failed"); - return false; - } - module->rtl_func_table_registered = true; - } -#endif - /* Set start function when function pointers are resolved */ if (module->start_func_index != (uint32)-1) { if (module->start_func_index >= module->import_func_count) @@ -3261,14 +3216,6 @@ aot_unload(AOTModule *module) } #endif -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - if (module->rtl_func_table) { - if (module->rtl_func_table_registered) - RtlDeleteFunctionTable(module->rtl_func_table); - wasm_runtime_free(module->rtl_func_table); - } -#endif - #if (defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)) \ && !defined(BH_PLATFORM_WINDOWS) { diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 895823af3..4358e3079 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -92,30 +92,6 @@ typedef struct AOTModuleInstanceExtra { WASMModuleInstanceExtraCommon common; } AOTModuleInstanceExtra; -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) -/* clang-format off */ -typedef struct AOTUnwindInfo { - uint8 Version : 3; - uint8 Flags : 5; - uint8 SizeOfProlog; - uint8 CountOfCodes; - uint8 FrameRegister : 4; - uint8 FrameOffset : 4; - struct { - struct { - uint8 CodeOffset; - uint8 UnwindOp : 4; - uint8 OpInfo : 4; - }; - uint16 FrameOffset; - } UnwindCode[1]; -} AOTUnwindInfo; -/* clang-format on */ - -/* size of mov instruction and jmp instruction */ -#define PLT_ITEM_SIZE 12 -#endif - #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) typedef struct GOTItem { uint32 func_idx; @@ -211,14 +187,6 @@ typedef struct AOTModule { uint32 float_plt_count; #endif -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - /* dynamic function table to be added by RtlAddFunctionTable(), - used to unwind the call stack and register exception handler - for AOT functions */ - RUNTIME_FUNCTION *rtl_func_table; - bool rtl_func_table_registered; -#endif - #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) uint32 got_item_count; GOTItemList got_item_list; diff --git a/core/iwasm/aot/arch/aot_reloc_x86_64.c b/core/iwasm/aot/arch/aot_reloc_x86_64.c index 1bf5eb594..b5be24593 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_64.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_64.c @@ -69,9 +69,6 @@ get_plt_table_size() { uint32 size = get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - size += get_plt_item_size() + sizeof(AOTUnwindInfo); -#endif return size; } @@ -93,18 +90,6 @@ init_plt_table(uint8 *plt) *p++ = 0xE0; plt += get_plt_item_size(); } - -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - p = plt; - /* mov exception_handler, rax */ - *p++ = 0x48; - *p++ = 0xB8; - *(uint64 *)p = 0; /*(uint64)(uintptr_t)aot_exception_handler;*/ - p += sizeof(uint64); - /* jmp rax */ - *p++ = 0xFF; - *p++ = 0xE0; -#endif } static bool diff --git a/core/iwasm/aot/iwasm_aot.cmake b/core/iwasm/aot/iwasm_aot.cmake index 8014f2372..efff88dd0 100644 --- a/core/iwasm/aot/iwasm_aot.cmake +++ b/core/iwasm/aot/iwasm_aot.cmake @@ -36,5 +36,49 @@ if (WAMR_BUILD_DEBUG_AOT EQUAL 1) file(GLOB debug_source ${IWASM_AOT_DIR}/debug/*.c) endif() -set (IWASM_AOT_SOURCE ${c_source_all} ${arch_source} ${debug_source}) +if ((WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + AND (WAMR_BUILD_PLATFORM STREQUAL "windows") + AND (NOT WAMR_DISABLE_HW_BOUND_CHECK EQUAL 1)) + include(FetchContent) + FetchContent_Declare( + zycore + GIT_REPOSITORY https://github.com/zyantific/zycore-c.git + ) + FetchContent_GetProperties(zycore) + if (NOT zycore_POPULATED) + message ("-- Fetching zycore ..") + FetchContent_Populate(zycore) + include_directories("${zycore_SOURCE_DIR}/include") + include_directories("${zycore_BINARY_DIR}") + add_definitions(-DZYCORE_STATIC_BUILD=1) + add_subdirectory(${zycore_SOURCE_DIR} ${zycore_BINARY_DIR} EXCLUDE_FROM_ALL) + file (GLOB_RECURSE c_source_zycore ${zycore_SOURCE_DIR}/src/*.c) + endif () + + FetchContent_Declare( + zydis + GIT_REPOSITORY https://github.com/zyantific/zydis.git + GIT_TAG e14a07895136182a5b53e181eec3b1c6e0b434de + ) + FetchContent_GetProperties(zydis) + if (NOT zydis_POPULATED) + message ("-- Fetching zydis ..") + FetchContent_Populate(zydis) + option(ZYDIS_FEATURE_ENCODER "" OFF) + option(ZYDIS_BUILD_TOOLS "" OFF) + option(ZYDIS_BUILD_EXAMPLES "" OFF) + option(ZYDIS_BUILD_MAN "" OFF) + option(ZYDIS_BUILD_DOXYGEN "" OFF) + include_directories("${zydis_BINARY_DIR}") + include_directories("${zydis_SOURCE_DIR}/include") + include_directories("${zydis_SOURCE_DIR}/src") + add_definitions(-DZYDIS_STATIC_BUILD=1) + add_subdirectory(${zydis_SOURCE_DIR} ${zydis_BINARY_DIR} EXCLUDE_FROM_ALL) + file (GLOB_RECURSE c_source_zydis ${zydis_SOURCE_DIR}/src/*.c) + endif () +endif () + + +set (IWASM_AOT_SOURCE ${c_source_all} ${arch_source} ${debug_source} + ${c_source_zycore} ${c_source_zydis}) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index b18662157..09233f249 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -199,7 +199,90 @@ runtime_signal_handler(void *sig_addr) } } } -#else +#else /* else of BH_PLATFORM_WINDOWS */ + +#if WASM_ENABLE_AOT != 0 +#include + +static uint32 +decode_insn(uint8 *insn) +{ + uint8 *data = (uint8 *)insn; + uint32 length = 32; /* reserve enough size */ + + /* Initialize decoder context */ + ZydisDecoder decoder; + ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, + ZYDIS_STACK_WIDTH_64); + + /* Initialize formatter */ + ZydisFormatter formatter; + ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); + + /* Loop over the instructions in our buffer */ + ZyanU64 runtime_address = (ZyanU64)(uintptr_t)data; + ZyanUSize offset = 0; + ZydisDecodedInstruction instruction; + ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE]; + char buffer[256]; + + if (ZYAN_SUCCESS(ZydisDecoderDecodeFull( + &decoder, data + offset, length - offset, &instruction, operands, + ZYDIS_MAX_OPERAND_COUNT_VISIBLE, + ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY))) { + + /* Format & print the binary instruction structure to + human readable format */ + ZydisFormatterFormatInstruction(&formatter, &instruction, operands, + instruction.operand_count_visible, + buffer, sizeof(buffer), + runtime_address); + + /* Print current instruction */ + /* + os_printf("%012" PRIX64 " ", runtime_address); + puts(buffer); + */ + + return instruction.length; + } + + /* Decode failed */ + return 0; +} +#endif /* end of WASM_ENABLE_AOT != 0 */ + +static LONG +next_action(WASMModuleInstance *module_inst, EXCEPTION_POINTERS *exce_info) +{ +#if WASM_ENABLE_AOT != 0 + uint32 insn_size; +#endif + + if (module_inst->module_type == Wasm_Module_Bytecode + && module_inst->e->running_mode == Mode_Interp) { + /* Continue to search next exception handler for + interpreter mode as it can be caught by + `__try { .. } __except { .. }` sentences in + wasm_runtime.c */ + return EXCEPTION_CONTINUE_SEARCH; + } + +#if WASM_ENABLE_AOT != 0 + /* Skip current instruction and continue to run for AOT/JIT mode. + TODO: implement unwind support for AOT/JIT code in Windows platform */ + insn_size = decode_insn((uint8 *)exce_info->ContextRecord->Rip); + if (insn_size > 0) { + exce_info->ContextRecord->Rip += insn_size; + return EXCEPTION_CONTINUE_EXECUTION; + } +#endif + + /* return different value from EXCEPTION_CONTINUE_SEARCH (= 0) + and EXCEPTION_CONTINUE_EXECUTION (= -1) */ + return -2; +} + static LONG runtime_exception_handler(EXCEPTION_POINTERS *exce_info) { @@ -211,6 +294,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) uint8 *mapped_mem_start_addr = NULL; uint8 *mapped_mem_end_addr = NULL; uint32 page_size = os_getpagesize(); + LONG ret; if (exec_env_tls && exec_env_tls->handle == os_self_thread() && (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) { @@ -232,32 +316,19 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) the wasm func returns, the caller will check whether the exception is thrown and return to runtime. */ wasm_set_exception(module_inst, "out of bounds memory access"); - if (module_inst->module_type == Wasm_Module_Bytecode) { - /* Continue to search next exception handler for - interpreter mode as it can be caught by - `__try { .. } __except { .. }` sentences in - wasm_runtime.c */ - return EXCEPTION_CONTINUE_SEARCH; - } - else { - /* Skip current instruction and continue to run for - AOT mode. TODO: implement unwind support for AOT - code in Windows platform */ - exce_info->ContextRecord->Rip++; - return EXCEPTION_CONTINUE_EXECUTION; - } + ret = next_action(module_inst, exce_info); + if (ret == EXCEPTION_CONTINUE_SEARCH + || ret == EXCEPTION_CONTINUE_EXECUTION) + return ret; } else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr && (uint8 *)sig_addr < exec_env_tls->exce_check_guard_page + page_size) { bh_assert(wasm_copy_exception(module_inst, NULL)); - if (module_inst->module_type == Wasm_Module_Bytecode) { - return EXCEPTION_CONTINUE_SEARCH; - } - else { - exce_info->ContextRecord->Rip++; - return EXCEPTION_CONTINUE_EXECUTION; - } + ret = next_action(module_inst, exce_info); + if (ret == EXCEPTION_CONTINUE_SEARCH + || ret == EXCEPTION_CONTINUE_EXECUTION) + return ret; } } #if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 @@ -267,12 +338,10 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) whether the exception is thrown and return to runtime, and the damaged stack will be recovered by _resetstkoflw(). */ wasm_set_exception(module_inst, "native stack overflow"); - if (module_inst->module_type == Wasm_Module_Bytecode) { - return EXCEPTION_CONTINUE_SEARCH; - } - else { - return EXCEPTION_CONTINUE_EXECUTION; - } + ret = next_action(module_inst, exce_info); + if (ret == EXCEPTION_CONTINUE_SEARCH + || ret == EXCEPTION_CONTINUE_EXECUTION) + return ret; } #endif } diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index aa837a3ca..413f47690 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -18,6 +18,17 @@ } \ } while (0) +static bool +is_win_platform(AOTCompContext *comp_ctx) +{ + char *triple = LLVMGetTargetMachineTriple(comp_ctx->target_machine); + + bh_assert(trip); + if (strstr(triple, "win32") || strstr(triple, "win")) + return true; + return false; +} + static bool create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { @@ -458,7 +469,7 @@ check_app_addr_and_convert(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Check whether exception was thrown when executing the function */ - if (comp_ctx->enable_bound_check + if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_call_return(comp_ctx, func_ctx, res)) { return false; } @@ -696,7 +707,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; /* Check whether there was exception thrown when executing the function */ - if (comp_ctx->enable_bound_check + if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_call_return(comp_ctx, func_ctx, res)) goto fail; } @@ -849,7 +860,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Check whether there was exception thrown when executing the function */ - if (!tail_call && comp_ctx->enable_bound_check + if (!tail_call + && (comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_exception_thrown(comp_ctx, func_ctx)) goto fail; } @@ -1431,7 +1443,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; /* Check whether exception was thrown when executing the function */ - if (comp_ctx->enable_bound_check + if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_call_return(comp_ctx, func_ctx, res)) goto fail; @@ -1483,7 +1495,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Check whether exception was thrown when executing the function */ - if (comp_ctx->enable_bound_check + if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_exception_thrown(comp_ctx, func_ctx)) goto fail; From 0e12cdec487e1c7c55d6212c82e7534bb5f2199e Mon Sep 17 00:00:00 2001 From: Maks Litskevich Date: Fri, 18 Aug 2023 03:40:05 +0100 Subject: [PATCH 073/123] Add sample pre-commit hook (#2470) Using pre-commit hooks helps us to decrease CI load and improve developers' experience. --- ci/pre_commit_hook_sample | 32 ++++++++++++++++++++++++++++++++ ci/setup.sh | 15 +++++++++++++++ 2 files changed, 47 insertions(+) create mode 100755 ci/pre_commit_hook_sample create mode 100755 ci/setup.sh diff --git a/ci/pre_commit_hook_sample b/ci/pre_commit_hook_sample new file mode 100755 index 000000000..682e78946 --- /dev/null +++ b/ci/pre_commit_hook_sample @@ -0,0 +1,32 @@ +#!/bin/bash + +# Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This is a sample of pre-commit hook that can be used to make your code fit the WAMR CI code style requirements. +# You need to have clang-format-12 installed to use this hook. +# To add this pre-commit hook, copy it to /.git/hooks/pre-commit +# (you don't need any extensions here) + +# Function to check if a file has a C or C++ extension + +is_c_or_cpp_file() { + file="$1" + if [[ "$filename" =~ \.(h|c|cpp)$ ]]; then + return 0 + else + return 1 + fi +} + +# Loop through staged files and apply command "abc" to C and C++ files +for staged_file in $(git diff --cached --name-only); do + if is_c_or_cpp_file "$staged_file"; then + clang-format-12 -Werror --style file --dry-run "$staged_file" 2>/dev/null + if [ $? -ne 0 ]; then + echo "Issues are found in $staged_file. Applying the fix" + clang-format-12 --style file -i "$staged_file" + fi + git add "$staged_file" # Add the modified file back to staging + fi +done diff --git a/ci/setup.sh b/ci/setup.sh new file mode 100755 index 000000000..ebdf73af5 --- /dev/null +++ b/ci/setup.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This script executes some commands to make your onboarding with WAMR easier. +# For example, setting pre-commit hook that will make your code complaint with the +# code style requirements checked in WAMR CI + +echo "Copy the pre-commit hook to your hooks folder" +cp pre_commit_hook_sample ../.git/hooks/pre-commit + +# Feel free to propose your commands to this script to make developing WAMR easier + +echo "Setup is done" From a2f76cf93c271b02db1456bbb05134b08809a883 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 18 Aug 2023 13:57:23 +0800 Subject: [PATCH 074/123] Fix typo in aot_emit_aot_file.c (#2478) --- core/iwasm/compilation/aot_emit_aot_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 1b1e4403f..622187755 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -1825,7 +1825,7 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, == 4 /* IMAGE_REL_AMD64_REL32 */) || (obj_data->target_info.bin_type == 4 /* AOT_COFF32_BIN_TYPE */ - && obj_data->target_info.bin_type + && relocation->relocation_type == 20 /* IMAGE_REL_I386_REL32 */))) { uint32 func_idx = atoi(relocation->symbol_name From f0632edc37543aa1493efb9dbcd836eb58dbed23 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Mon, 21 Aug 2023 19:43:28 +0800 Subject: [PATCH 075/123] Clone the input binary during wasm_module_validate (#2483) --- core/iwasm/common/wasm_c_api.c | 21 +++++++++++++++++---- samples/wasm-c-api/src/hello.c | 6 ++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index a595a6269..afb38cc92 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -2290,8 +2290,10 @@ quit: bool wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary) { + wasm_byte_vec_t local_binary = { 0 }; struct WASMModuleCommon *module_rt; char error_buf[128] = { 0 }; + bool ret; bh_assert(singleton_engine); @@ -2300,15 +2302,26 @@ wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary) return false; } - if ((module_rt = wasm_runtime_load((uint8 *)binary->data, - (uint32)binary->size, error_buf, 128))) { + /* make a copy of binary */ + wasm_byte_vec_new_uninitialized(&local_binary, binary->size); + if (binary->size && !local_binary.data) + return false; + + wasm_byte_vec_copy(&local_binary, binary); + + module_rt = wasm_runtime_load((uint8 *)local_binary.data, + (uint32)local_binary.size, error_buf, 128); + wasm_byte_vec_delete(&local_binary); + if (module_rt) { wasm_runtime_unload(module_rt); - return true; + ret = true; } else { + ret = false; LOG_VERBOSE(error_buf); - return false; } + + return ret; } static void diff --git a/samples/wasm-c-api/src/hello.c b/samples/wasm-c-api/src/hello.c index 3ebea87b0..966e141d7 100644 --- a/samples/wasm-c-api/src/hello.c +++ b/samples/wasm-c-api/src/hello.c @@ -65,6 +65,12 @@ int main(int argc, const char* argv[]) { } fclose(file); + if (!wasm_module_validate(store, &binary)) { + printf("> Error validate module!\n"); + wasm_byte_vec_delete(&binary); + return 1; + } + // Compile. printf("Compiling module...\n"); own wasm_module_t* module = wasm_module_new(store, &binary); From 59bedecc5eb718e03980f4d1ac27749d30bd33a6 Mon Sep 17 00:00:00 2001 From: tonibofarull Date: Tue, 22 Aug 2023 02:50:26 +0200 Subject: [PATCH 076/123] Fix set wasi args order (#2485) set_wasi_args should be called before module instantiation. --- language-bindings/python/src/wamr/wamrapi/wamr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/language-bindings/python/src/wamr/wamrapi/wamr.py b/language-bindings/python/src/wamr/wamrapi/wamr.py index 74cbad9f1..1bd6e547d 100644 --- a/language-bindings/python/src/wamr/wamrapi/wamr.py +++ b/language-bindings/python/src/wamr/wamrapi/wamr.py @@ -131,12 +131,12 @@ class Instance: ): # Store module ensures GC does not remove it self.module = module + if dir_list: + self._set_wasi_args(module, dir_list) if preinitialized_module_inst is None: self.module_inst = self._create_module_inst(module, stack_size, heap_size) else: self.module_inst = preinitialized_module_inst - if dir_list: - self._set_wasi_args(module, dir_list) def __del__(self): print("deleting Instance") From 7f996a4559fe26dae57150c9bff99a04dad61d31 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Tue, 22 Aug 2023 01:55:36 +0100 Subject: [PATCH 077/123] Update version number and release notes (#2378) Update the version number to 1.2.3 and update the release notes. --- RELEASE_NOTES.md | 136 +++++++++++++++++++++++++++++++++++++++++++++++ core/version.h | 2 +- 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index d6308ce67..5c7f598da 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,139 @@ +## WAMR-1.2.3 + +### Breaking Changes +- Increase default native stack size (#2332) + +### New Features +- Implement the segue optimization for LLVM AOT/JIT (#2230) +- Implement AOT static PGO (#2243) +- Enable static PGO for Linux SGX (#2270) +- Add Rust Formatters to Debugger (Vector, Map etc.) (#2219) + +### Bug Fixes +- The Python language-binding needs python>=3.9 (#2228) +- aot_compile_op_call: Remove a wrong optimization (#2233) +- Fix typo in samples/ref-types (#2236) +- Update thread proposal ignore cases (#2246) +- Disable writting GS register on linux-sgx platform (#2255) +- Fix compile error of wamrc with llvm-13/llvm-14 (#2261) +- aot/jit: Set module layout (#2260) +- Fix build error with LLVM 16 (#2259) +- spec-test-script: Disable conversions.wast on i386 (#2269) +- Fix a heap corruption bug in ems realloc (#2279) +- Fix fast-interp issue of LAST_OP_OUTPUT_I32/64 check (#2295) +- Fix wamrc build issues with LLVM 13 and LLVM 16 (#2313) +- aot: Move stack_sizes table to a dedicated section (#2317) +- product-mini/platforms/linux: Mark vmlib POSITION_INDEPENDENT_CODE (#2323) +- aot: Avoid possible relocations around "stack_sizes" for XIP mode (#2322) +- Avoid switch lowering to lookup tables for XIP (#2339) +- Fix typo in zephyr's Dockerfile.old (#2354) +- Fix typo (dwarf) in the codebase (#2367) +- Implement suspend flags as atomic variable (#2361) +- Fix llvm jit failed to lookup aot_stack_sizes symbol issue (#2384) +- Fix some check issues on table operations (#2392) +- Fix ExpandMemoryOpPass doesn't work properly (#2399) +- Fix non-builtin BH_ATOMIC_32_FETCH_OR and BH_ATOMIC_32_FETCH_AND (#2400) +- Fix wasi-sockets tests (#2389) +- Fix result arity check on select_t opcode (#2406) +- Re-organize intrinsics in aot_reloc_riscv.c to fix some FPU issues (#2414) +- Fix lib-pthread issues (#2410) +- Fix typo in test_wamr.sh (#2421) +- Fix memory sharing (#2415) +- wasm_export.h: Fix struct wasm_val_t (#2435) +- Fix typos in wamrc print_help() (#2442) +- iwasm: Fix native lib cleanup after error occurs (#2443) +- Correct --heap-size option in messages (#2458) +- wasm_instantiate: Fix a potential integer overflow issue (#2459) +- Fix windows link error and clear windows warnings (#2463) +- aot: Disable musttail for mips (#2457) +- Fix opcode overwrite issue in fast interp (#2476) +- wamrc: Fix windows relocation to `aot_func_internal#n` (#2474) +- Fix windows AOT hw bound check (#2475) +- Fix typo in aot_emit_aot_file.c (#2478) + +### Enhancements +- A few changes related to WAMRC_LLC_COMPILER (#2218) +- Enhance linux-sgx CI (#2102) +- Add asan and ubsan to WAMR CI (#2161) +- Update doc on WAMR_DISABLE_HW_BOUND_CHECK 32-bit (#2262) +- wamrc: Add an incompatibility note in the help message (#2276) +- Add cmake variable to disable writing gs register (#2284) +- Make hmu_tree_node 4 byte aligned to reduce compiler warning (#2268) +- Appease unused warning on min_uint64 (#2277) +- Fix format warning by PRIu32 in [wasm|aot] dump call stack (#2251) +- Fix a compile warning due to missing include (#2293) +- Fix dockerfile linter warnings (#2291) +- Enable windows x86-32 AOT relocations (#2285) +- wamr-ide: Add vscode extension tests (#2292) +- AOT/JIT native stack bound check improvement (#2244) +- Add retries to flaky step in nightly run CI (#2306) +- Use system libuv if available (#1861) +- wasi-nn: Simplify cmake and headers' location (#2308) +- wasi-nn: Improve tests paths for local dev (#2309) +- aot: Implement a few more relocation types for riscv (#2318) +- wasi-nn: Add support of wasi-nn as shared lib (#2310) +- Add a few more assertions on structures to which aot abi is sensitive (#2326) +- Fix sanitizer errors in posix socket (#2331) +- Add "--xip" option for wamrc (#2336) +- Add "--enable-llvm-passes=" option to wamrc (#2335) +- Make memory access boundary check behavior configurable (#2289) +- Migrate ExpandMemoryOpPass to llvm new pass manager (#2334) +- Allow defining hints without exact socket type or address family (#2337) +- wamrc: Warn on text relocations for XIP (#2340) +- Add scripts to validate lldb source debugger (#2150) +- Add docker file to fix Zephy ESP32 linking issue (#2314) +- Add "--native-lib=" option to wamrc (#2342) +- Fix unused warnings on disable_bounds_checks (#2347) +- Add "--enable-builtin-intrinsics=" option to wamrc (#2341) +- nuttx: Add a kconfig for wasi-threads (#2343) +- iwasm: Disable app heap by default if wasi is enabled (#2346) +- Fix some static scan issues (#2362) +- Bring up WAMR on esp32-s3 device (#2348) +- ESP-IDF platform supports to load AOT to PSRAM and run it (#2385) +- Add hadolint CI for Dockerfile linting (#2387) +- Move generic parts of wasm_suspend_flags.h to bh_atomic.h (#2393) +- bh_atomic.h: Add comments (#2398) +- bh_atomic.h: Add BH_ATOMIC_32_FETCH_ADD/BH_ATOMIC_32_FETCH_SUB (#2408) +- Update libuv version to v1.46.0 (#2405) +- Remove a few unused functions (#2409) +- Add initial stress test (#2364) +- Move wasm_runtime_destroy_wasi and wasi_nn_destroy calls together (#2418) +- embed_wamr.md: Improvements about threads (#2420) +- Add runtime inited checks in Enclave command handlings to improve security (#2416) +- Add some relocation symbols for xtensa target (#2422) +- Remove unnecessary and extra zero length check in mem functions' macro (#2428) +- Introduce WASMModuleInstanceExtraCommon (#2429) +- Strip static and shared libraries of iwasm to reduce the binary size (#2431) +- Auto-check wrgsbase in cmake script (#2437) +- iwasm: call native lib init/deinit if exists (#2439) +- wasi-nn: Support uint8 quantized networks (#2433) +- Implement `wasm_externref_objdel` and `wasm_externref_set_cleanup` (#2455) +- wasi-nn: Improve TPU support (#2447) +- wamr-python: Enable debugging WASM and grant dir access (#2449) +- Build wasi-libc from source in WAMR CI (#2465) +- wamrc: More friendly to print help info (#2451) +- Add another wamr test (#2411) +- Fix issues reported by Coverity and clear windows warnings (#2467) +- Clone the input binary during wasm_module_validate (#2483) + +### Others +- Nuttx CI: Ignore the expired certificate for riscv gcc toolchain (#2222) +- core/iwasm/compilation: constify a bit (#2223) +- Bump requests from 2.28.2 to 2.31.0 in /build-scripts (#2229) +- dwarf_extractor: Constify a bit (#2278) +- AOTFuncContext: Remove a stale comment (#2283) +- Add performance tunning document (#2286) +- Reduce CI jobs number (#2296) +- CI: Update used node version to 16 (#2303) +- Update Docker image for latest version of external libraries & tools (#2374) +- Upgrade cJSON version to v1.7.16 (#2404) +- Upgrade XNNPACK workload (#2394) +- Build more benchmarks in workload XNNPACK (#2417) +- Upgrade SGX-RA integration for 0.1.2 and Ubuntu 20.04 (#2454) +- Add sample pre-commit hook (#2470) + +--- + ## WAMR-1.2.2 ### Breaking Changes diff --git a/core/version.h b/core/version.h index de24b30bc..925779b31 100644 --- a/core/version.h +++ b/core/version.h @@ -7,5 +7,5 @@ #define _WAMR_VERSION_H_ #define WAMR_VERSION_MAJOR 1 #define WAMR_VERSION_MINOR 2 -#define WAMR_VERSION_PATCH 2 +#define WAMR_VERSION_PATCH 3 #endif From 051dfbbb9e4bfa2b26b220836a78192021762112 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 22 Aug 2023 11:50:11 +0800 Subject: [PATCH 078/123] Fix a typo in is_win_platform (#2490) --- core/iwasm/compilation/aot_emit_function.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index 413f47690..def3f7d04 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -23,7 +23,7 @@ is_win_platform(AOTCompContext *comp_ctx) { char *triple = LLVMGetTargetMachineTriple(comp_ctx->target_machine); - bh_assert(trip); + bh_assert(triple); if (strstr(triple, "win32") || strstr(triple, "win")) return true; return false; From 2b30bb0fdac0a403c27c579c64a46af80068d479 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Tue, 22 Aug 2023 13:57:23 +0800 Subject: [PATCH 079/123] Upgrade swig to 4.1 (#2491) Upgrade to sig@4.1 when building wamr-lldb on MacOS since swig@3 had been disabled: https://formulae.brew.sh/formula/swig --- .github/workflows/build_wamr_lldb.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_wamr_lldb.yml b/.github/workflows/build_wamr_lldb.yml index e0f9595c7..b7971aa89 100644 --- a/.github/workflows/build_wamr_lldb.yml +++ b/.github/workflows/build_wamr_lldb.yml @@ -27,7 +27,7 @@ on: type: string required: false default: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz" - + jobs: try_reuse: @@ -49,7 +49,7 @@ jobs: PYTHON_MACOS_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-apple-darwin-install_only.tar.gz steps: - uses: actions/checkout@v3 - + - name: download and install wasi-sdk run: | cd /opt @@ -84,8 +84,8 @@ jobs: if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos') run: | brew remove swig - brew install swig@3 cmake ninja libedit - brew link --overwrite swig@3 + brew install swig@4.1 cmake ninja libedit + brew link --overwrite swig@4.1 sudo rm -rf /Library/Developer/CommandLineTools - name: install utils ubuntu @@ -205,7 +205,7 @@ jobs: mkdir -p wamr-lldb/lib cp build/bin/lldb* wamr-lldb/bin cp lldb/tools/lldb-vscode/package.json wamr-lldb - cp -r lldb/tools/lldb-vscode/syntaxes/ wamr-lldb + cp -r lldb/tools/lldb-vscode/syntaxes/ wamr-lldb working-directory: core/deps/llvm-project - name: pack ubuntu specific libraries @@ -226,7 +226,7 @@ jobs: cp -R ../python/lib/python* wamr-lldb/lib cp ../python/lib/libpython*.dylib wamr-lldb/lib install_name_tool -change /install/lib/libpython${{ env.PYTHON_VERSION }}.dylib @rpath/libpython${{ env.PYTHON_VERSION }}.dylib wamr-lldb/lib/liblldb.*.dylib - # Patch path of python library -> https://github.com/indygreg/python-build-standalone/blob/85923ca3911784e6978b85d56e06e9ae75cb2dc4/docs/quirks.rst?plain=1#L412-L446 + # Patch path of python library -> https://github.com/indygreg/python-build-standalone/blob/85923ca3911784e6978b85d56e06e9ae75cb2dc4/docs/quirks.rst?plain=1#L412-L446 working-directory: core/deps/llvm-project - name: compress the binary From 377c3d7a38aeb9cb26be231408432cc2369300eb Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Tue, 22 Aug 2023 14:24:42 +0800 Subject: [PATCH 080/123] Auto increase port number in lldb validation script (#2492) --- ci/validate_lldb.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ci/validate_lldb.py b/ci/validate_lldb.py index 0bf743c0f..1b431ada8 100755 --- a/ci/validate_lldb.py +++ b/ci/validate_lldb.py @@ -32,7 +32,6 @@ parser.add_argument( options = parser.parse_args() -lldb_command_prologue = f'{options.lldb} -o "process connect -p wasm connect://127.0.0.1:{options.port}"' lldb_command_epilogue = '-o q' test_cases = { @@ -64,8 +63,13 @@ def print_process_output(p): print("Failed to get process output") # Step2: Launch WAMR in debug mode and validate lldb commands -wamr_cmd = f'{options.wamr} -g=127.0.0.1:{options.port} {WASM_OUT_FILE}' + +iteration = 0 for case, cmd in test_cases.items(): + lldb_command_prologue = f'{options.lldb} -o "process connect -p wasm connect://127.0.0.1:{int(options.port) + iteration}"' + wamr_cmd = f'{options.wamr} -g=127.0.0.1:{int(options.port) + iteration} {WASM_OUT_FILE}' + iteration += 1 + has_error = False print(f'validating case [{case}] ...', end='', flush=True) lldb_cmd = f'{lldb_command_prologue} {cmd} {lldb_command_epilogue}' From 858d1dd69cad4d672c791f0c5af38dd3d5a0f936 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 23 Aug 2023 12:35:46 +0800 Subject: [PATCH 081/123] Fix duplicate vector init in wasm_module_validate (#2498) --- core/iwasm/common/wasm_c_api.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index afb38cc92..2da733874 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -2303,12 +2303,11 @@ wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary) } /* make a copy of binary */ - wasm_byte_vec_new_uninitialized(&local_binary, binary->size); + wasm_byte_vec_copy(&local_binary, binary); + if (binary->size && !local_binary.data) return false; - wasm_byte_vec_copy(&local_binary, binary); - module_rt = wasm_runtime_load((uint8 *)local_binary.data, (uint32)local_binary.size, error_buf, 128); wasm_byte_vec_delete(&local_binary); From fa2f29fd8ab3f72e3efb551d19cb6b214ead91f8 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 23 Aug 2023 12:56:11 +0800 Subject: [PATCH 082/123] Fix issues in releasing wamr-lldb (#2497) - Update lldb patch due to swig was upgraded to 4.1 in macos - Export LD_LIBRARY_PATH for searching libpython3.10.so when validating wamr-lldb in Ubuntu-20.04 - Rename lldb-wasm.patch to lldb_wasm.path --- .github/workflows/build_wamr_lldb.yml | 6 +- .../compilation_on_android_ubuntu.yml | 4 +- .../{lldb-wasm.patch => lldb_wasm.patch} | 155 +++++++++++------- doc/source_debugging.md | 2 +- 4 files changed, 103 insertions(+), 64 deletions(-) rename build-scripts/{lldb-wasm.patch => lldb_wasm.patch} (98%) diff --git a/.github/workflows/build_wamr_lldb.yml b/.github/workflows/build_wamr_lldb.yml index b7971aa89..1a73750a6 100644 --- a/.github/workflows/build_wamr_lldb.yml +++ b/.github/workflows/build_wamr_lldb.yml @@ -28,14 +28,13 @@ on: required: false default: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz" - jobs: try_reuse: uses: ./.github/workflows/reuse_latest_release_binaries.yml with: binary_name_stem: "wamr-lldb-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}" last_commit: "ea63ba4bd010c2285623ad4acc0262a4d63bcfea" - the_path: "./build-scripts/lldb-wasm.patch" + the_path: "./build-scripts/lldb_wasm.patch" upload_url: ${{ inputs.upload_url }} build: @@ -107,7 +106,7 @@ jobs: git init git config user.email "action@github.com" git config user.name "github action" - git apply ../../../build-scripts/lldb-wasm.patch + git apply ../../../build-scripts/lldb_wasm.patch working-directory: core/deps/llvm-project - name: get stand-alone python ubuntu @@ -163,6 +162,7 @@ jobs: mkdir -p wamr-debug cmake -S product-mini/platforms/linux -B wamr-debug -DWAMR_BUILD_DEBUG_INTERP=1 cmake --build wamr-debug --parallel $(nproc) + export LD_LIBRARY_PATH=$(pwd)/core/deps/python/lib:${LD_LIBRARY_PATH} python3 ci/validate_lldb.py --port 1239 --lldb core/deps/wamr-lldb/bin/lldb --wamr wamr-debug/iwasm --verbose working-directory: . diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index bbb2c4b3a..b7ac084eb 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -594,7 +594,7 @@ jobs: cache-name: cache-lldb-vscode with: path: test-tools/wamr-ide/VSCode-Extension/resource/debug/linux - key: ${{ env.cache-name }}-${{ hashFiles('build-scripts/lldb-wasm.patch') }}-${{ env.PYTHON_UBUNTU_STANDALONE_BUILD }} + key: ${{ env.cache-name }}-${{ hashFiles('build-scripts/lldb_wasm.patch') }}-${{ env.PYTHON_UBUNTU_STANDALONE_BUILD }} - if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }} name: get stand-alone python ubuntu @@ -617,7 +617,7 @@ jobs: git init git config user.email "action@github.com" git config user.name "github action" - git apply ../../../build-scripts/lldb-wasm.patch + git apply ../../../build-scripts/lldb_wasm.patch working-directory: core/deps/llvm-project - if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }} diff --git a/build-scripts/lldb-wasm.patch b/build-scripts/lldb_wasm.patch similarity index 98% rename from build-scripts/lldb-wasm.patch rename to build-scripts/lldb_wasm.patch index d6044e3a3..83221ef6a 100644 --- a/build-scripts/lldb-wasm.patch +++ b/build-scripts/lldb_wasm.patch @@ -1,5 +1,44 @@ +diff --git a/lldb/bindings/CMakeLists.txt b/lldb/bindings/CMakeLists.txt +index 9759b069fdc4..25b427f8bcf2 100644 +--- a/lldb/bindings/CMakeLists.txt ++++ b/lldb/bindings/CMakeLists.txt +@@ -26,8 +26,6 @@ set(SWIG_COMMON_FLAGS + -features autodoc + -I${LLDB_SOURCE_DIR}/include + -I${CMAKE_CURRENT_SOURCE_DIR} +- -D__STDC_LIMIT_MACROS +- -D__STDC_CONSTANT_MACROS + ${DARWIN_EXTRAS} + ) + +diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig +index c9a6d0f06056..021c7683d170 100644 +--- a/lldb/bindings/interfaces.swig ++++ b/lldb/bindings/interfaces.swig +@@ -1,8 +1,5 @@ + /* Various liblldb typedefs that SWIG needs to know about. */ + #define __extension__ /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h. */ +-/* The ISO C99 standard specifies that in C++ implementations limit macros such +- as INT32_MAX should only be defined if __STDC_LIMIT_MACROS is. */ +-#define __STDC_LIMIT_MACROS + %include "stdint.i" + + %include "lldb/lldb-defines.h" +diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig +index b1ace4ff3b1e..5f8f4aa678c4 100644 +--- a/lldb/bindings/python/python-typemaps.swig ++++ b/lldb/bindings/python/python-typemaps.swig +@@ -439,7 +439,7 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { + + %typemap(out) lldb::FileSP { + $result = nullptr; +- lldb::FileSP &sp = $1; ++ const lldb::FileSP &sp = $1; + if (sp) { + PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp)); + if (!pyfile.IsValid()) diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h -index f2e2a0d22..426d1129b 100644 +index f2e2a0d22784..426d1129bd10 100644 --- a/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -9,6 +9,7 @@ @@ -11,7 +50,7 @@ index f2e2a0d22..426d1129b 100644 #include #include diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h -index dd7100c46..97d70daad 100644 +index dd7100c4616c..97d70daadbdc 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -41,6 +41,7 @@ @@ -41,7 +80,7 @@ index dd7100c46..97d70daad 100644 /// /// Tries to resolve \a vm_addr as a file address (if \a diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h -index be91929c6..8d876fc1f 100644 +index be91929c62e1..8d876fc1fa2f 100644 --- a/lldb/include/lldb/Core/PluginManager.h +++ b/lldb/include/lldb/Core/PluginManager.h @@ -508,6 +508,17 @@ public: @@ -64,7 +103,7 @@ index be91929c6..8d876fc1f 100644 } // namespace lldb_private diff --git a/lldb/include/lldb/Expression/DWARFEvaluator.h b/lldb/include/lldb/Expression/DWARFEvaluator.h new file mode 100644 -index 000000000..6811cbeae +index 000000000000..6811cbeae3d3 --- /dev/null +++ b/lldb/include/lldb/Expression/DWARFEvaluator.h @@ -0,0 +1,110 @@ @@ -180,7 +219,7 @@ index 000000000..6811cbeae +#endif // LLDB_EXPRESSION_DWARFEVALUATOR_H diff --git a/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h b/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h new file mode 100644 -index 000000000..f3b496c58 +index 000000000000..f3b496c580e4 --- /dev/null +++ b/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h @@ -0,0 +1,56 @@ @@ -241,7 +280,7 @@ index 000000000..f3b496c58 + +#endif // LLDB_EXPRESSION_DWARFEVALUATORFACTORY_H diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h -index 1490ac2d6..35c741d4e 100644 +index 1490ac2d614a..35c741d4e6ba 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -120,6 +120,10 @@ public: @@ -275,7 +314,7 @@ index 1490ac2d6..35c741d4e 100644 GetLocationExpression(lldb::addr_t load_function_start, lldb::addr_t addr) const; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h -index aaa2470d2..c15f2db52 100644 +index aaa2470d2931..c15f2db52fbc 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -1434,7 +1434,7 @@ public: @@ -288,7 +327,7 @@ index aaa2470d2..c15f2db52 100644 /// Read of memory from a process. /// diff --git a/lldb/include/lldb/Target/ProcessTrace.h b/lldb/include/lldb/Target/ProcessTrace.h -index 7b9d6b13d..9525fc975 100644 +index 7b9d6b13dd6f..9525fc9750fd 100644 --- a/lldb/include/lldb/Target/ProcessTrace.h +++ b/lldb/include/lldb/Target/ProcessTrace.h @@ -59,7 +59,7 @@ public: @@ -301,7 +340,7 @@ index 7b9d6b13d..9525fc975 100644 size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Status &error) override; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h -index ad5298151..5a3c0b27a 100644 +index ad5298151e4a..5a3c0b27a738 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -74,6 +74,7 @@ class Disassembler; @@ -313,7 +352,7 @@ index ad5298151..5a3c0b27a 100644 class EmulateInstruction; class Environment; diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h -index 2ed083ec8..f4d500d19 100644 +index 2ed083ec8ae9..f4d500d198e8 100644 --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -113,6 +113,8 @@ typedef lldb::REPLSP (*REPLCreateInstance)(Status &error, @@ -326,7 +365,7 @@ index 2ed083ec8..f4d500d19 100644 /// \{ typedef llvm::Expected (*TraceCreateInstanceForSessionFile)( diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp -index 19c97be15..1647f93ec 100644 +index 19c97be15066..1647f93ec4f3 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -16,6 +16,7 @@ @@ -348,7 +387,7 @@ index 19c97be15..1647f93ec 100644 + return m_dwarf_evaluator_factory.get(); +} diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp -index fcaa868b0..59a404d4a 100644 +index fcaa868b083e..59a404d4a7e1 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -1597,3 +1597,32 @@ bool PluginManager::CreateSettingForStructuredDataPlugin( @@ -385,7 +424,7 @@ index fcaa868b0..59a404d4a 100644 + return GetDWARFEvaluatorFactoryInstances().GetCallbackAtIndex(idx); +} diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp -index fb57c0fed..f92d6a54d 100644 +index fb57c0fedf04..f92d6a54de94 100644 --- a/lldb/source/Core/Value.cpp +++ b/lldb/source/Core/Value.cpp @@ -538,7 +538,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, @@ -398,7 +437,7 @@ index fb57c0fed..f92d6a54d 100644 error.SetErrorStringWithFormat( "read memory from 0x%" PRIx64 " failed (%u of %u bytes read)", diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp -index 9c1ba99da..b15b214b2 100644 +index 9c1ba99da1d0..b15b214b2a2f 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -735,7 +735,7 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx, @@ -411,7 +450,7 @@ index 9c1ba99da..b15b214b2 100644 data.SetData(data_sp); return bytes_read; diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt -index bf94361dd..4e76d547a 100644 +index bf94361dd6c1..4e76d547aeaf 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -1,5 +1,7 @@ @@ -424,7 +463,7 @@ index bf94361dd..4e76d547a 100644 ExpressionVariable.cpp diff --git a/lldb/source/Expression/DWARFEvaluator.cpp b/lldb/source/Expression/DWARFEvaluator.cpp new file mode 100644 -index 000000000..06107e136 +index 000000000000..06107e136197 --- /dev/null +++ b/lldb/source/Expression/DWARFEvaluator.cpp @@ -0,0 +1,1952 @@ @@ -2382,7 +2421,7 @@ index 000000000..06107e136 +} diff --git a/lldb/source/Expression/DWARFEvaluatorFactory.cpp b/lldb/source/Expression/DWARFEvaluatorFactory.cpp new file mode 100644 -index 000000000..c06126412 +index 000000000000..c0612641204a --- /dev/null +++ b/lldb/source/Expression/DWARFEvaluatorFactory.cpp @@ -0,0 +1,57 @@ @@ -2444,7 +2483,7 @@ index 000000000..c06126412 + object_address_ptr); +} diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp -index a10546c1d..4d13e4642 100644 +index a10546c1deae..4d13e4642af3 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -15,6 +15,8 @@ @@ -4261,7 +4300,7 @@ index a10546c1d..4d13e4642 100644 static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc, diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp -index 00e9ccb76..2137a1ac8 100644 +index 00e9ccb762c3..2137a1ac8324 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -759,6 +759,24 @@ void CommandInterpreter::LoadCommandDictionary() { @@ -4290,7 +4329,7 @@ index 00e9ccb76..2137a1ac8 100644 new CommandObjectRegexCommand( *this, "kdp-remote", diff --git a/lldb/source/Plugins/CMakeLists.txt b/lldb/source/Plugins/CMakeLists.txt -index 9181a4e47..2be6ec365 100644 +index 9181a4e47675..2be6ec3657c0 100644 --- a/lldb/source/Plugins/CMakeLists.txt +++ b/lldb/source/Plugins/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(ABI) @@ -4320,14 +4359,14 @@ index 9181a4e47..2be6ec365 100644 endif() diff --git a/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt b/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt new file mode 100644 -index 000000000..73fad41e1 +index 000000000000..73fad41e1a72 --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(wasm) diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt b/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt new file mode 100644 -index 000000000..e50b1bef7 +index 000000000000..e50b1bef7e69 --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt @@ -0,0 +1,10 @@ @@ -4343,7 +4382,7 @@ index 000000000..e50b1bef7 + ) diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp new file mode 100644 -index 000000000..fdda1991d +index 000000000000..fdda1991d19f --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp @@ -0,0 +1,126 @@ @@ -4475,7 +4514,7 @@ index 000000000..fdda1991d +} diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h new file mode 100644 -index 000000000..a01159064 +index 000000000000..a01159064a39 --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h @@ -0,0 +1,47 @@ @@ -4528,7 +4567,7 @@ index 000000000..a01159064 +#endif // LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATOR_H diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp new file mode 100644 -index 000000000..d43e96a34 +index 000000000000..d43e96a34d37 --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp @@ -0,0 +1,64 @@ @@ -4598,7 +4637,7 @@ index 000000000..d43e96a34 +} diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h new file mode 100644 -index 000000000..8a946592a +index 000000000000..8a946592a09a --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h @@ -0,0 +1,55 @@ @@ -4658,7 +4697,7 @@ index 000000000..8a946592a + +#endif // LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATORFACTORY_H diff --git a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp -index ae7e011ea..24ea75d19 100644 +index ae7e011eaa52..24ea75d1971c 100644 --- a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp @@ -62,6 +62,15 @@ void DynamicLoaderWasmDYLD::DidAttach() { @@ -4678,7 +4717,7 @@ index ae7e011ea..24ea75d19 100644 ThreadPlanSP DynamicLoaderWasmDYLD::GetStepThroughTrampolinePlan(Thread &thread, diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp -index 5272da9ab..abc5523bf 100644 +index 5272da9ab33a..abc5523bfd70 100644 --- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp +++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp @@ -23,6 +23,7 @@ @@ -4718,7 +4757,7 @@ index 5272da9ab..abc5523bf 100644 } } diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt -index 5f284e517..6084cbc93 100644 +index 5f284e517dca..6084cbc9378d 100644 --- a/lldb/source/Plugins/Platform/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/CMakeLists.txt @@ -15,3 +15,4 @@ @@ -4728,7 +4767,7 @@ index 5f284e517..6084cbc93 100644 +add_subdirectory(wasm-remote) diff --git a/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt b/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt new file mode 100644 -index 000000000..4a65765a5 +index 000000000000..4a65765a5659 --- /dev/null +++ b/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt @@ -0,0 +1,10 @@ @@ -4744,7 +4783,7 @@ index 000000000..4a65765a5 + ) diff --git a/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp new file mode 100644 -index 000000000..f26d11f00 +index 000000000000..f26d11f00e5c --- /dev/null +++ b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp @@ -0,0 +1,139 @@ @@ -4890,7 +4929,7 @@ index 000000000..f26d11f00 \ No newline at end of file diff --git a/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h new file mode 100644 -index 000000000..f306a79d3 +index 000000000000..f306a79d3f4f --- /dev/null +++ b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h @@ -0,0 +1,37 @@ @@ -4933,7 +4972,7 @@ index 000000000..f306a79d3 +#endif \ No newline at end of file diff --git a/lldb/source/Plugins/Plugins.def.in b/lldb/source/Plugins/Plugins.def.in -index bf54598fb..b0bd7b996 100644 +index bf54598fb2f3..b0bd7b9965fe 100644 --- a/lldb/source/Plugins/Plugins.def.in +++ b/lldb/source/Plugins/Plugins.def.in @@ -31,6 +31,7 @@ @@ -4945,7 +4984,7 @@ index bf54598fb..b0bd7b996 100644 #undef LLDB_PLUGIN diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt -index bea5bac9e..7a0855e02 100644 +index bea5bac9eb21..7a0855e02ca2 100644 --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -18,3 +18,4 @@ add_subdirectory(Utility) @@ -4954,7 +4993,7 @@ index bea5bac9e..7a0855e02 100644 add_subdirectory(minidump) +add_subdirectory(wasm) diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp -index 12bc7390c..707ab85e5 100644 +index 12bc7390c729..707ab85e5615 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -285,7 +285,7 @@ bool ProcessElfCore::IsAlive() { return true; } @@ -4967,7 +5006,7 @@ index 12bc7390c..707ab85e5 100644 // in core files we have it all cached our our core file anyway. return DoReadMemory(addr, buf, size, error); diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h -index d8e3cc9ae..f0bf9c4d3 100644 +index d8e3cc9ae3e1..f0bf9c4d3b00 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -84,7 +84,8 @@ public: @@ -4981,7 +5020,7 @@ index d8e3cc9ae..f0bf9c4d3 100644 size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Status &error) override; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp -index 6914b3734..bb8a05604 100644 +index 6914b37348ea..bb8a056049f3 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -334,6 +334,11 @@ ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); } @@ -5015,7 +5054,7 @@ index 6914b3734..bb8a05604 100644 } } diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h -index fe04cdddd..e4a14c645 100644 +index fe04cdddd0f5..e4a14c64579a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -237,6 +237,8 @@ protected: @@ -5028,7 +5067,7 @@ index fe04cdddd..e4a14c645 100644 enum { eBroadcastBitAsyncContinue = (1 << 0), diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp -index 84548edb5..0ae6f7e4a 100644 +index 84548edb5caa..0ae6f7e4a177 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -596,7 +596,7 @@ bool ProcessMachCore::WarnBeforeDetach() const { return false; } @@ -5041,7 +5080,7 @@ index 84548edb5..0ae6f7e4a 100644 // in core files we have it all cached our our core file anyway. return DoReadMemory(addr, buf, size, error); diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h -index db77e96f1..1c930896c 100644 +index db77e96f1072..1c930896c743 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h @@ -65,7 +65,8 @@ public: @@ -5055,7 +5094,7 @@ index db77e96f1..1c930896c 100644 size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Status &error) override; diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp -index 385557422..d8bb21581 100644 +index 385557422758..d8bb21581086 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -374,7 +374,7 @@ bool ProcessMinidump::IsAlive() { return true; } @@ -5068,7 +5107,7 @@ index 385557422..d8bb21581 100644 // we have it all cached in our dump file anyway. return DoReadMemory(addr, buf, size, error); diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h -index 27b0da004..e94ecab43 100644 +index 27b0da0047a5..e94ecab430c1 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h @@ -69,8 +69,8 @@ public: @@ -5084,7 +5123,7 @@ index 27b0da004..e94ecab43 100644 Status &error) override; diff --git a/lldb/source/Plugins/Process/wasm/CMakeLists.txt b/lldb/source/Plugins/Process/wasm/CMakeLists.txt new file mode 100644 -index 000000000..61efb933f +index 000000000000..61efb933fa62 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/CMakeLists.txt @@ -0,0 +1,12 @@ @@ -5102,7 +5141,7 @@ index 000000000..61efb933f + ) diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp new file mode 100644 -index 000000000..9c0fc7b7f +index 000000000000..9c0fc7b7f270 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp @@ -0,0 +1,261 @@ @@ -5369,7 +5408,7 @@ index 000000000..9c0fc7b7f +} diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h new file mode 100644 -index 000000000..d3aece7a6 +index 000000000000..d3aece7a6554 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h @@ -0,0 +1,128 @@ @@ -5503,7 +5542,7 @@ index 000000000..d3aece7a6 +#endif // LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp new file mode 100644 -index 000000000..fa02073e7 +index 000000000000..fa02073e7a52 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp @@ -0,0 +1,35 @@ @@ -5544,7 +5583,7 @@ index 000000000..fa02073e7 +} diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.h b/lldb/source/Plugins/Process/wasm/ThreadWasm.h new file mode 100644 -index 000000000..0a33c07de +index 000000000000..0a33c07de994 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.h @@ -0,0 +1,41 @@ @@ -5591,7 +5630,7 @@ index 000000000..0a33c07de +#endif // LLDB_SOURCE_PLUGINS_PROCESS_WASM_THREADWASM_H diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp new file mode 100644 -index 000000000..1a195cb93 +index 000000000000..1a195cb9361a --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp @@ -0,0 +1,74 @@ @@ -5672,7 +5711,7 @@ index 000000000..1a195cb93 \ No newline at end of file diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.h b/lldb/source/Plugins/Process/wasm/UnwindWasm.h new file mode 100644 -index 000000000..9bd1dac9a +index 000000000000..9bd1dac9a98a --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.h @@ -0,0 +1,55 @@ @@ -5732,7 +5771,7 @@ index 000000000..9bd1dac9a + +#endif // lldb_UnwindWasm_h_ diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp -index ccaf31317..c3ef5aebd 100644 +index ccaf31317d75..c3ef5aebd46d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3212,8 +3212,13 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, @@ -5751,7 +5790,7 @@ index ccaf31317..c3ef5aebd 100644 // DWARF doesn't specify if a DW_TAG_variable is a local, global // or static variable, so we have to do a little digging: diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp -index b660c310e..cd76421ce 100644 +index b660c310ef31..cd76421cec18 100644 --- a/lldb/source/Target/PathMappingList.cpp +++ b/lldb/source/Target/PathMappingList.cpp @@ -218,7 +218,12 @@ bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) co @@ -5769,7 +5808,7 @@ index b660c310e..cd76421ce 100644 return {}; diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp -index a77ecddfb..e257f9350 100644 +index a77ecddfbab6..e257f93508f6 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -1970,6 +1970,12 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target, @@ -5786,7 +5825,7 @@ index a77ecddfb..e257f9350 100644 return 0; } diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp -index 8ecc66b59..f14898791 100644 +index 8ecc66b592ea..f148987915de 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1892,7 +1892,8 @@ Status Process::DisableSoftwareBreakpoint(BreakpointSite *bp_site) { @@ -5800,7 +5839,7 @@ index 8ecc66b59..f14898791 100644 if (!GetDisableMemoryCache()) { #if defined(VERIFY_MEMORY_READS) diff --git a/lldb/source/Target/ProcessTrace.cpp b/lldb/source/Target/ProcessTrace.cpp -index c878a2ac4..ad5945b0a 100644 +index c878a2ac4eb9..ad5945b0ad1f 100644 --- a/lldb/source/Target/ProcessTrace.cpp +++ b/lldb/source/Target/ProcessTrace.cpp @@ -88,7 +88,7 @@ void ProcessTrace::RefreshStateAfterStop() {} @@ -5813,7 +5852,7 @@ index c878a2ac4..ad5945b0a 100644 // we have it all cached in the trace files. return DoReadMemory(addr, buf, size, error); diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp -index 896e647bb..f76307016 100644 +index 896e647bbb52..f76307016102 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -334,7 +334,10 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() { @@ -5829,7 +5868,7 @@ index 896e647bb..f76307016 100644 instructions->GetInstructionAtIndex(last_index); size_t last_inst_size = last_inst->GetOpcode().GetByteSize(); diff --git a/lldb/source/Target/UnixSignals.cpp b/lldb/source/Target/UnixSignals.cpp -index 4ec2e25c7..24c88fe9a 100644 +index 4ec2e25c7e3b..24c88fe9ae4f 100644 --- a/lldb/source/Target/UnixSignals.cpp +++ b/lldb/source/Target/UnixSignals.cpp @@ -46,6 +46,8 @@ lldb::UnixSignalsSP UnixSignals::Create(const ArchSpec &arch) { @@ -5842,7 +5881,7 @@ index 4ec2e25c7..24c88fe9a 100644 return std::make_shared(); } diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h -index 4310ba9ce..297b33879 100644 +index 4310ba9ce9e0..297b3387999d 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h @@ -13,6 +13,7 @@ @@ -5854,7 +5893,7 @@ index 4310ba9ce..297b33879 100644 #include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h" #include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h" diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h -index 753b1998c..27370c62d 100644 +index 753b1998c40c..27370c62dd6e 100644 --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -16,6 +16,7 @@ diff --git a/doc/source_debugging.md b/doc/source_debugging.md index a9fa09307..513185fe8 100644 --- a/doc/source_debugging.md +++ b/doc/source_debugging.md @@ -44,7 +44,7 @@ iwasm -g=127.0.0.1:1234 test.wasm ``` bash git clone --branch release/13.x --depth=1 https://github.com/llvm/llvm-project cd llvm-project -git apply ${WAMR_ROOT}/build-scripts/lldb-wasm.patch +git apply ${WAMR_ROOT}/build-scripts/lldb_wasm.patch mkdir build-lldb cmake -S ./llvm -B build-lldb \ -G Ninja \ From ff151fb7bac109636a944149e545317c4b3d798a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A4mes=20M=C3=A9n=C3=A9trey?= Date: Mon, 28 Aug 2023 03:42:16 +0200 Subject: [PATCH 083/123] sgx-ra: Disable the building of samples (#2507) --- core/iwasm/libraries/lib-rats/lib_rats.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/iwasm/libraries/lib-rats/lib_rats.cmake b/core/iwasm/libraries/lib-rats/lib_rats.cmake index 3ca08f160..e17a6b25a 100644 --- a/core/iwasm/libraries/lib-rats/lib_rats.cmake +++ b/core/iwasm/libraries/lib-rats/lib_rats.cmake @@ -23,7 +23,7 @@ include(FetchContent) set(RATS_BUILD_MODE "sgx" CACHE INTERNAL "Select build mode for librats(host|occlum|sgx|wasm)") set(RATS_INSTALL_PATH "${CMAKE_BINARY_DIR}/librats" CACHE INTERNAL "") -set(BUILD_SAMPLES OFF) +set(BUILD_SAMPLES OFF CACHE BOOL "Disable de compilation of the librats samples" FORCE) FetchContent_Declare( librats From 411b903ceeb03c1b4dd205e771be30fafc9698c9 Mon Sep 17 00:00:00 2001 From: Maks Litskevich Date: Wed, 30 Aug 2023 12:01:44 +0100 Subject: [PATCH 084/123] Add mutex stress test (#2472) As a part of stress-testing we want to ensure that mutex implementation is working correctly and protecting shared resource to be allocated from other threads when mutex is locked. This test covers the most common situations that happen when some program uses mutexes like locks from various threads, locks from the same thread etc. --- .github/workflows/nightly_run.yml | 5 + .../lib-wasi-threads/stress-test/build.sh | 65 +++++ .../errorcheck_mutex_stress_test.c | 27 +++ .../stress-test/manifest.json | 3 + .../stress-test/mutex_common.h | 229 ++++++++++++++++++ .../stress-test/normal_mutex_stress_test.c | 20 ++ .../stress-test/recursive_mutex_stress_test.c | 65 +++++ .../{test => stress-test}/spawn_stress_test.c | 2 +- .../stress_test_threads_creation.c | 6 +- .../libraries/lib-wasi-threads/test/build.sh | 5 +- .../libraries/lib-wasi-threads/test/skip.json | 6 - .../wasi-test-script/run_wasi_tests.sh | 46 ++-- 12 files changed, 442 insertions(+), 37 deletions(-) create mode 100755 core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh create mode 100644 core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c create mode 100644 core/iwasm/libraries/lib-wasi-threads/stress-test/manifest.json create mode 100644 core/iwasm/libraries/lib-wasi-threads/stress-test/mutex_common.h create mode 100644 core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c create mode 100644 core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c rename core/iwasm/libraries/lib-wasi-threads/{test => stress-test}/spawn_stress_test.c (99%) rename core/iwasm/libraries/lib-wasi-threads/{test => stress-test}/stress_test_threads_creation.c (92%) delete mode 100644 core/iwasm/libraries/lib-wasi-threads/test/skip.json diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index 0b82bb582..adedd1ef7 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -599,6 +599,11 @@ jobs: run: bash build.sh --sysroot "$SYSROOT_PATH" working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/ + - name: Build WASI thread stress tests + if: matrix.test_option == '$WASI_TEST_OPTIONS' + run: bash build.sh --sysroot "$SYSROOT_PATH" + working-directory: ./core/iwasm/libraries/lib-wasi-threads/stress-test/ + - name: build socket api tests if: matrix.test_option == '$WASI_TEST_OPTIONS' run: bash build.sh diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh b/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh new file mode 100755 index 000000000..341f3ef12 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# +# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +set -eo pipefail +CC=${CC:=/opt/wasi-sdk/bin/clang} +WAMR_DIR=../../../../.. + +show_usage() { + echo "Usage: $0 [--sysroot PATH_TO_SYSROOT]" + echo "--sysroot PATH_TO_SYSROOT specify to build with custom sysroot for wasi-libc" +} + +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + --sysroot) + sysroot_path="$2" + shift + shift + ;; + --help) + show_usage + exit + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +rm -rf *.wasm +rm -rf *.aot + +for test_c in *.c; do + test_wasm="$(basename $test_c .c).wasm" + + if [[ -n "$sysroot_path" ]]; then + if [ ! -d "$sysroot_path" ]; then + echo "Directory $sysroot_path doesn't exist. Aborting" + exit 1 + fi + sysroot_command="--sysroot $sysroot_path" + fi + + echo "Compiling $test_c to $test_wasm" + $CC \ + -target wasm32-wasi-threads \ + -O2 \ + -Wall \ + -pthread \ + -z stack-size=32768 \ + -Wl,--export=__heap_base \ + -Wl,--export=__data_end \ + -Wl,--shared-memory,--max-memory=1966080 \ + -Wl,--export=wasi_thread_start \ + -Wl,--export=malloc \ + -Wl,--export=free \ + $sysroot_command \ + $test_c -o $test_wasm +done diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c new file mode 100644 index 000000000..3b594657f --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include "mutex_common.h" + +int +main() +{ + pthread_mutex_t mutex; + + // Set mutex type to errorcheck. This type provides some additional checks + // (for example returns EDEADLK instead of deadlocking in some cases) + pthread_mutexattr_t mutex_attr; + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); + + pthread_mutex_init(&mutex, &mutex_attr); + pthread_mutexattr_destroy(&mutex_attr); + + run_common_tests(&mutex); + fprintf(stderr, "Errorcheck mutex test is completed\n"); + pthread_mutex_destroy(&mutex); +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/manifest.json b/core/iwasm/libraries/lib-wasi-threads/stress-test/manifest.json new file mode 100644 index 000000000..bb91ad083 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/manifest.json @@ -0,0 +1,3 @@ +{ + "name": "lib-wasi-threads stress tests" +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/mutex_common.h b/core/iwasm/libraries/lib-wasi-threads/stress-test/mutex_common.h new file mode 100644 index 000000000..d57ff7d50 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/mutex_common.h @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef MUTEX_COMMON_H +#define MUTEX_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum Constants { + NUM_ITER = 250000, + NUM_THREADS = 12, + NUM_RETRY = 8, + RETRY_SLEEP_TIME_US = 1000, +}; + +// We're counting how many times each thread was called using this array +// Main thread is also counted here so we need to make arrays bigger +typedef struct { + int tids[NUM_THREADS + 1]; + int calls[NUM_THREADS + 1]; +} StatCollector; + +typedef struct { + pthread_mutex_t *mutex; + StatCollector stat; + int counter; + bool is_sleeping; +} MutexCounter; + +// This enum defines whether thread should sleep to increase contention +enum SleepState { + NON_SLEEP = 0, + SLEEP = 1, +}; + +void +mutex_counter_init(MutexCounter *mutex_counter, pthread_mutex_t *mutex, + enum SleepState is_sleeping) +{ + memset(mutex_counter, 0, sizeof(*mutex_counter)); + mutex_counter->mutex = mutex; + mutex_counter->is_sleeping = is_sleeping; +} + +// This function spawns the thread using exponential retries if it receives +// EAGAIN +static inline void +spawn_thread(pthread_t *tid, void *func, void *arg) +{ + int status_code = -1; + int timeout_us = RETRY_SLEEP_TIME_US; + for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) { + status_code = pthread_create(tid, NULL, (void *(*)(void *))func, arg); + assert(status_code == 0 || status_code == EAGAIN); + if (status_code == EAGAIN) { + usleep(timeout_us); + timeout_us *= 2; + } + } + + assert(status_code == 0 && "Thread creation should succeed"); +} + +// This function adds tid to our stat +static inline void +add_to_stat(StatCollector *stat, int tid) +{ + int tid_num = 0; + for (; tid_num < NUM_THREADS + 1 && stat->tids[tid_num] != 0; ++tid_num) { + if (stat->tids[tid_num] == tid) { + stat->calls[tid_num]++; + return; + } + } + + assert(tid_num < NUM_THREADS + 1); + stat->tids[tid_num] = tid; + stat->calls[tid_num] = 1; +} + +// This function prints number of calls by TID +static inline void +print_stat(StatCollector *stat) +{ + fprintf(stderr, "Thread calls count by TID\n"); + for (int i = 0; i < NUM_THREADS + 1; ++i) { + if (stat->tids[i] != 0) { + fprintf(stderr, "TID: %d; Calls: %d\n", stat->tids[i], + stat->calls[i]); + } + } +} + +// This function is run by the threads, it increases counter in a loop and then +// sleeps after unlocking the mutex to provide better contention +static inline void * +inc_shared_variable(void *arg) +{ + MutexCounter *mutex_counter = (MutexCounter *)(arg); + int sleep_us = 0; + while (!pthread_mutex_lock(mutex_counter->mutex) + && mutex_counter->counter < NUM_ITER) { + mutex_counter->counter++; + add_to_stat(&mutex_counter->stat, (int)(pthread_self())); + if (mutex_counter->is_sleeping) { + sleep_us = rand() % 1000; + } + + assert(pthread_mutex_unlock(mutex_counter->mutex) == 0 + && "Should be able to unlock a mutex"); + if (mutex_counter->is_sleeping) { + usleep(sleep_us); + } + } + + assert(mutex_counter->counter == NUM_ITER); + assert(pthread_mutex_unlock(mutex_counter->mutex) == 0 + && "Should be able to unlock the mutex after test execution"); + + return NULL; +} + +// Locking and unlocking a mutex in a single thread. +static inline void * +same_thread_lock_unlock_test(void *mutex) +{ + for (int i = 0; i < NUM_ITER; ++i) { + assert(pthread_mutex_lock(mutex) == 0 + && "Main thread should be able to lock a mutex"); + assert(pthread_mutex_unlock(mutex) == 0 + && "Main thread should be able to unlock a mutex"); + } + + return NULL; +} + +// This function spawns a thread that locks and unlocks a mutex `NUM_ITER` times +// in a row +static inline void +same_non_main_thread_lock_unlock_test(pthread_mutex_t *mutex) +{ + pthread_t tid = 0; + spawn_thread(&tid, same_thread_lock_unlock_test, mutex); + + assert(tid != 0 && "TID can't be 0 after successful thread creation"); + assert(pthread_join(tid, NULL) == 0 + && "Thread should be joined successfully"); +} + +// This function checks basic contention between main and non-main thread +// increasing the shared variable +static inline void +two_threads_inc_test(pthread_mutex_t *mutex) +{ + MutexCounter mutex_counter; + mutex_counter_init(&mutex_counter, mutex, false); + + pthread_t tid = 0; + spawn_thread(&tid, inc_shared_variable, &mutex_counter); + + assert(tid != 0 && "TID can't be 0 after successful thread creation"); + inc_shared_variable(&mutex_counter); + assert(pthread_join(tid, NULL) == 0 + && "Thread should be joined without errors"); + assert(mutex_counter.counter == NUM_ITER); +} + +// This function creates number of threads specified by NUM_THREADS and run +// concurrent increasing of shared variable +static inline void +max_threads_inc_test(pthread_mutex_t *mutex, int threads_num, + enum SleepState is_sleeping) +{ + MutexCounter mutex_counter; + mutex_counter_init(&mutex_counter, mutex, is_sleeping); + + pthread_t tids[threads_num]; + for (int i = 0; i < threads_num; ++i) { + spawn_thread(&tids[i], inc_shared_variable, &mutex_counter); + } + + inc_shared_variable(&mutex_counter); + + for (int i = 0; i < threads_num; ++i) { + assert(pthread_join(tids[i], NULL) == 0 + && "Thread should be joined without errors"); + } + + print_stat(&mutex_counter.stat); +} + +// This function just runs all the tests described above +static inline void +run_common_tests(pthread_mutex_t *mutex) +{ + srand(time(NULL)); + + fprintf(stderr, "Starting same_thread_lock_unlock_test test\n"); + same_thread_lock_unlock_test(mutex); + fprintf(stderr, "Finished same_thread_lock_unlock_test test\n"); + + fprintf(stderr, "Starting same_non_main_thread_lock_unlock_test test\n"); + same_non_main_thread_lock_unlock_test(mutex); + fprintf(stderr, "Finished same_non_main_thread_lock_unlock_test test\n"); + + fprintf(stderr, "Starting two_threads_inc_test test\n"); + two_threads_inc_test(mutex); + fprintf(stderr, "Finished two_threads_inc_test test\n"); + + fprintf(stderr, "Starting max_threads_inc_test_sleep test\n"); + max_threads_inc_test(mutex, NUM_THREADS, SLEEP); + fprintf(stderr, "Finished concurrent_inc sleep test\n"); + + fprintf(stderr, "Starting max_threads_inc_test_non_sleep test\n"); + max_threads_inc_test(mutex, NUM_THREADS, NON_SLEEP); + fprintf(stderr, "Finished max_threads_inc_test test\n"); +} + +#endif // MUTEX_COMMON_H diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c new file mode 100644 index 000000000..6c75f8814 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include "mutex_common.h" + +int +main() +{ + pthread_mutex_t mutex; + pthread_mutex_init(&mutex, NULL); + + run_common_tests(&mutex); + + fprintf(stderr, "Normal mutex test is completed\n"); + pthread_mutex_destroy(&mutex); +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c new file mode 100644 index 000000000..8c3e325e8 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include "mutex_common.h" + +void +multiple_same_thread_lock(void *mutex) +{ + for (int i = 0; i < 100; ++i) { + assert(pthread_mutex_lock(mutex) == 0 + && "Recursive mutex should allow multiple locking"); + } + + for (int i = 0; i < 100; ++i) { + assert(pthread_mutex_unlock(mutex) == 0 + && "Recursive mutex should allow multiple unlocking"); + } +} + +void * +same_thread_multiple_rec_mutex_lock(void *mutex) +{ + for (int i = 0; i < NUM_ITER; ++i) { + multiple_same_thread_lock(mutex); + } + + return NULL; +} + +int +main() +{ + pthread_mutex_t mutex; + + // Set mutex type to recursive. This type allows multiple locking and + // unlocking within the same thread + pthread_mutexattr_t mutex_attr; + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&mutex, &mutex_attr); + pthread_mutexattr_destroy(&mutex_attr); + + run_common_tests(&mutex); + + fprintf(stderr, "Starting same_thread_multiple_rec_mutex_lock test\n"); + same_thread_multiple_rec_mutex_lock(&mutex); + fprintf(stderr, "Finished same_thread_multiple_rec_mutex_lock test\n"); + + fprintf(stderr, "Starting same_thread_multiple_rec_mutex_lock test in " + "non-main thread\n"); + pthread_t tid; + spawn_thread(&tid, same_thread_multiple_rec_mutex_lock, &mutex); + assert(pthread_join(tid, NULL) == 0 + && "Non-main thread should be joined successfully"); + fprintf(stderr, "Finished same_thread_multiple_rec_mutex_lock test in " + "non-main thread\n"); + + fprintf(stderr, "Recursive mutex test is completed\n"); + pthread_mutex_destroy(&mutex); +} diff --git a/core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c similarity index 99% rename from core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c rename to core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c index fa49ac481..a35337f35 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c @@ -19,7 +19,7 @@ enum CONSTANTS { NUM_ITER = 100000, NUM_RETRY = 8, - MAX_NUM_THREADS = 8, + MAX_NUM_THREADS = 12, RETRY_SLEEP_TIME_US = 2000, }; diff --git a/core/iwasm/libraries/lib-wasi-threads/test/stress_test_threads_creation.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c similarity index 92% rename from core/iwasm/libraries/lib-wasi-threads/test/stress_test_threads_creation.c rename to core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c index ef148f13b..f991fa7ab 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/stress_test_threads_creation.c +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c @@ -12,7 +12,7 @@ enum CONSTANTS { NUM_ITER = 200000, NUM_RETRY = 8, - MAX_NUM_THREADS = 8, + MAX_NUM_THREADS = 12, RETRY_SLEEP_TIME_US = 4000, SECOND = 1000 * 1000 * 1000 }; @@ -72,7 +72,9 @@ main(int argc, char **argv) } while ((__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) != 0)) { - __builtin_wasm_memory_atomic_wait32(&threads_in_use, 0, SECOND); + // Casting to int* to supress compiler warning + __builtin_wasm_memory_atomic_wait32((int *)(&threads_in_use), 0, + SECOND); } assert(__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) == 0); diff --git a/core/iwasm/libraries/lib-wasi-threads/test/build.sh b/core/iwasm/libraries/lib-wasi-threads/test/build.sh index 78a081050..608dd2260 100755 --- a/core/iwasm/libraries/lib-wasi-threads/test/build.sh +++ b/core/iwasm/libraries/lib-wasi-threads/test/build.sh @@ -34,7 +34,10 @@ while [[ $# -gt 0 ]]; do done # Stress tests names -thread_start_file_exclusions=("spawn_stress_test.wasm" "linear_memory_size_update.wasm" "stress_test_threads_creation.wasm") +thread_start_file_exclusions=("linear_memory_size_update.wasm") + +rm -rf *.wasm +rm -rf *.aot for test_c in *.c; do test_wasm="$(basename $test_c .c).wasm" diff --git a/core/iwasm/libraries/lib-wasi-threads/test/skip.json b/core/iwasm/libraries/lib-wasi-threads/test/skip.json deleted file mode 100644 index 86a3ba25a..000000000 --- a/core/iwasm/libraries/lib-wasi-threads/test/skip.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "lib-wasi-threads tests": { - "spawn_stress_test": "Stress tests are incompatible with the other part and executed differently", - "stress_test_threads_creation": "Stress tests are incompatible with the other part and executed differently" - } -} diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index 454fbb142..37607859b 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -15,25 +15,22 @@ readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/b --allow-resolve=google-public-dns-a.google.com \ --addr-pool=::1/128,127.0.0.1/32" -readonly IWASM_CMD_STRESS="${IWASM_CMD} --max-threads=8" +readonly IWASM_CMD_STRESS="${IWASM_CMD} --max-threads=12" readonly WAMRC_CMD="${WORK_DIR}/../../../../wamr-compiler/build/wamrc" readonly C_TESTS="tests/c/testsuite/" readonly ASSEMBLYSCRIPT_TESTS="tests/assemblyscript/testsuite/" readonly THREAD_PROPOSAL_TESTS="tests/proposals/wasi-threads/" readonly THREAD_INTERNAL_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/test/" +readonly THREAD_STRESS_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/stress-test/" readonly LIB_SOCKET_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-socket/test/" -readonly STRESS_TESTS=("spawn_stress_test.wasm" "stress_test_threads_creation.wasm") run_aot_tests () { local tests=("$@") - local iwasm="${IWASM_CMD}" for test_wasm in ${tests[@]}; do - local extra_stress_flags="" - for stress_test in "${STRESS_TESTS[@]}"; do - if [ "$test_wasm" == "$stress_test" ]; then - iwasm="${IWASM_CMD_STRESS}" - fi - done + local iwasm="${IWASM_CMD}" + if [[ $test_wasm =~ "stress" ]]; then + iwasm="${IWASM_CMD_STRESS}" + fi test_aot="${test_wasm%.wasm}.aot" test_json="${test_wasm%.wasm}.json" @@ -52,7 +49,7 @@ run_aot_tests () { expected=$(jq .exit_code ${test_json}) fi - ${IWASM_CMD} $extra_stress_flags $test_aot + ${iwasm} $test_aot ret=${PIPESTATUS[0]} echo "expected=$expected, actual=$ret" @@ -66,19 +63,6 @@ if [[ $MODE != "aot" ]];then python3 -m venv wasi-env && source wasi-env/bin/activate python3 -m pip install -r test-runner/requirements.txt - # Stress tests require max-threads=8 so they're executed separately - for stress_test in "${STRESS_TESTS[@]}"; do - if [[ -e "${THREAD_INTERNAL_TESTS}${stress_test}" ]]; then - echo "${stress_test}" is a stress test - ${IWASM_CMD_STRESS} ${THREAD_INTERNAL_TESTS}${stress_test} - ret=${PIPESTATUS[0]} - if [ "${ret}" -ne 0 ]; then - echo "Stress test ${stress_test} FAILED with code " ${ret} - exit_code=${ret} - fi - fi - done - TEST_RUNTIME_EXE="${IWASM_CMD}" python3 test-runner/wasi_test_runner.py \ -r adapters/wasm-micro-runtime.py \ -t \ @@ -87,12 +71,20 @@ if [[ $MODE != "aot" ]];then ${THREAD_PROPOSAL_TESTS} \ ${THREAD_INTERNAL_TESTS} \ ${LIB_SOCKET_TESTS} \ - --exclude-filter "${THREAD_INTERNAL_TESTS}skip.json" ret=${PIPESTATUS[0]} - if [ "${ret}" -ne 0 ]; then - exit_code=${ret} + + TEST_RUNTIME_EXE="${IWASM_CMD_STRESS}" python3 test-runner/wasi_test_runner.py \ + -r adapters/wasm-micro-runtime.py \ + -t \ + ${THREAD_STRESS_TESTS} + + if [ "${ret}" -eq 0 ]; then + ret=${PIPESTATUS[0]} fi + + exit_code=${ret} + deactivate else target_option="" @@ -101,7 +93,7 @@ else fi exit_code=0 - for testsuite in ${THREAD_PROPOSAL_TESTS} ${THREAD_INTERNAL_TESTS}; do + for testsuite in ${THREAD_STRESS_TESTS} ${THREAD_PROPOSAL_TESTS} ${THREAD_INTERNAL_TESTS}; do tests=$(ls ${testsuite}*.wasm) tests_array=($tests) run_aot_tests "${tests_array[@]}" From 53d7027de075073d3bc1ce7b89a4b5ef94ca7caf Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Thu, 31 Aug 2023 13:23:54 +0100 Subject: [PATCH 085/123] Implement strict validation of thread IDs according to the specification (#2521) --- .../lib-wasi-threads/test/create_threads_until_limit.c | 2 +- .../libraries/lib-wasi-threads/test/global_atomic.c | 2 +- .../libraries/lib-wasi-threads/test/global_lock.c | 2 +- .../test/trap_after_main_thread_finishes.c | 2 +- .../test/update_shared_data_and_alloc_heap.c | 2 +- samples/wasi-threads/wasm-apps/no_pthread.c | 10 ++-------- samples/wasi-threads/wasm-apps/wasi_thread_start.h | 4 ++++ 7 files changed, 11 insertions(+), 13 deletions(-) diff --git a/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c b/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c index 23ba5f627..94ffa0f67 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c @@ -65,7 +65,7 @@ main(int argc, char **argv) assert(start_args_init(&data[i].base)); thread_ids[i] = __wasi_thread_spawn(&data[i]); printf("Thread created with id=%d\n", thread_ids[i]); - assert(thread_ids[i] > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_ids[i]); for (int j = 0; j < i; j++) { assert(thread_ids[i] != thread_ids[j] && "Duplicated TIDs"); diff --git a/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c b/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c index a38e75364..7e1e8e081 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c @@ -49,7 +49,7 @@ main(int argc, char **argv) for (int i = 0; i < NUM_THREADS; i++) { assert(start_args_init(&data[i].base)); thread_ids[i] = __wasi_thread_spawn(&data[i]); - assert(thread_ids[i] > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_ids[i]); } printf("Wait for threads to finish\n"); diff --git a/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c b/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c index f81fca49b..fb33802fc 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c @@ -61,7 +61,7 @@ main(int argc, char **argv) for (int i = 0; i < NUM_THREADS; i++) { assert(start_args_init(&data[i].base)); thread_ids[i] = __wasi_thread_spawn(&data[i]); - assert(thread_ids[i] > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_ids[i]); } printf("Wait for threads to finish\n"); diff --git a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c index 69e125d40..5cf61338f 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c @@ -38,7 +38,7 @@ main(int argc, char **argv) assert(start_args_init(&data.base)); int thread_id = __wasi_thread_spawn(&data); - assert(thread_id > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_id); return EXIT_SUCCESS; } diff --git a/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c b/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c index b7fb9afba..d6e34539b 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c @@ -69,7 +69,7 @@ main(int argc, char **argv) data[i].iteration = i; thread_ids[i] = __wasi_thread_spawn(&data[i]); - assert(thread_ids[i] > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_ids[i]); } printf("Wait for threads to finish\n"); diff --git a/samples/wasi-threads/wasm-apps/no_pthread.c b/samples/wasi-threads/wasm-apps/no_pthread.c index dc3c95530..16661bd83 100644 --- a/samples/wasi-threads/wasm-apps/no_pthread.c +++ b/samples/wasi-threads/wasm-apps/no_pthread.c @@ -50,16 +50,11 @@ main(int argc, char **argv) } thread_id = __wasi_thread_spawn(&data); - if (thread_id < 0) { - printf("Failed to create thread: %d\n", thread_id); - ret = EXIT_FAILURE; - goto final; - } + ASSERT_VALID_TID(thread_id); if (__builtin_wasm_memory_atomic_wait32(&data.th_ready, 0, SECOND) == 2) { printf("Timeout\n"); - ret = EXIT_FAILURE; - goto final; + return EXIT_FAILURE; } printf("Thread completed, new value: %d, thread id: %d\n", data.value, @@ -67,7 +62,6 @@ main(int argc, char **argv) assert(thread_id == data.thread_id); -final: start_args_deinit(&data.base); return ret; diff --git a/samples/wasi-threads/wasm-apps/wasi_thread_start.h b/samples/wasi-threads/wasm-apps/wasi_thread_start.h index a46917d0a..2427fd2b9 100644 --- a/samples/wasi-threads/wasm-apps/wasi_thread_start.h +++ b/samples/wasi-threads/wasm-apps/wasi_thread_start.h @@ -7,6 +7,10 @@ #define STACK_SIZE 32 * 1024 // same as the main stack +/* See https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids */ +#define ASSERT_VALID_TID(TID) \ + assert(TID >= 1 && TID <= 0x1FFFFFFF && "Invalid thread ID") + typedef struct { void *stack; } start_args_t; From 382d52fc05dbb543dfafb969182104d6c4856c63 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 31 Aug 2023 21:39:08 +0900 Subject: [PATCH 086/123] Stop abusing shared memory lock to protect exception (#2509) Use a separate global lock instead. Fixes: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2407 --- core/iwasm/common/wasm_runtime_common.c | 28 +---- core/iwasm/interpreter/wasm_runtime.h | 10 ++ .../libraries/thread-mgr/thread_manager.c | 111 +++++++++--------- .../libraries/thread-mgr/thread_manager.h | 2 +- 4 files changed, 75 insertions(+), 76 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 09233f249..ac85c61dc 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2377,12 +2377,7 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm) void wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) { - WASMExecEnv *exec_env = NULL; - -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (module_inst->memory_count > 0) - shared_memory_lock(module_inst->memories[0]); -#endif + exception_lock(module_inst); if (exception) { snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); @@ -2390,19 +2385,14 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) else { module_inst->cur_exception[0] = '\0'; } -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (module_inst->memory_count > 0) - shared_memory_unlock(module_inst->memories[0]); -#endif + exception_unlock(module_inst); #if WASM_ENABLE_THREAD_MGR != 0 - exec_env = + WASMExecEnv *exec_env = wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst); if (exec_env) { - wasm_cluster_spread_exception(exec_env, exception ? false : true); + wasm_cluster_spread_exception(exec_env, exception); } -#else - (void)exec_env; #endif } @@ -2453,10 +2443,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf) { bool has_exception = false; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (module_inst->memory_count > 0) - shared_memory_lock(module_inst->memories[0]); -#endif + exception_lock(module_inst); if (module_inst->cur_exception[0] != '\0') { /* NULL is passed if the caller is not interested in getting the * exception content, but only in knowing if an exception has been @@ -2468,10 +2455,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf) sizeof(module_inst->cur_exception)); has_exception = true; } -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (module_inst->memory_count > 0) - shared_memory_unlock(module_inst->memories[0]); -#endif + exception_unlock(module_inst); return has_exception; } diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 3e0852487..784febd44 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -668,6 +668,16 @@ void wasm_propagate_wasi_args(WASMModule *module); #endif +#if WASM_ENABLE_THREAD_MGR != 0 +void +exception_lock(WASMModuleInstance *module_inst); +void +exception_unlock(WASMModuleInstance *module_inst); +#else +#define exception_lock(module_inst) (void)(module_inst) +#define exception_unlock(module_inst) (void)(module_inst) +#endif + #ifdef __cplusplus } #endif diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 21425786a..02430fe87 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -16,10 +16,6 @@ #include "debug_engine.h" #endif -#if WASM_ENABLE_SHARED_MEMORY != 0 -#include "wasm_shared_memory.h" -#endif - typedef struct { bh_list_link l; void (*destroy_cb)(WASMCluster *); @@ -32,6 +28,8 @@ static bh_list cluster_list_head; static bh_list *const cluster_list = &cluster_list_head; static korp_mutex cluster_list_lock; +static korp_mutex _exception_lock; + typedef void (*list_visitor)(void *, void *); static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM; @@ -52,6 +50,10 @@ thread_manager_init() return false; if (os_mutex_init(&cluster_list_lock) != 0) return false; + if (os_mutex_init(&_exception_lock) != 0) { + os_mutex_destroy(&cluster_list_lock); + return false; + } return true; } @@ -66,6 +68,7 @@ thread_manager_destroy() cluster = next; } wasm_cluster_cancel_all_callbacks(); + os_mutex_destroy(&_exception_lock); os_mutex_destroy(&cluster_list_lock); } @@ -1240,72 +1243,56 @@ wasm_cluster_resume_all(WASMCluster *cluster) os_mutex_unlock(&cluster->lock); } +struct spread_exception_data { + WASMExecEnv *skip; + const char *exception; +}; + static void set_exception_visitor(void *node, void *user_data) { - WASMExecEnv *curr_exec_env = (WASMExecEnv *)node; - WASMExecEnv *exec_env = (WASMExecEnv *)user_data; - WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env); - WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst; + const struct spread_exception_data *data = user_data; + WASMExecEnv *exec_env = (WASMExecEnv *)node; - if (curr_exec_env != exec_env) { - WASMModuleInstance *curr_wasm_inst = - (WASMModuleInstance *)get_module_inst(curr_exec_env); + if (exec_env != data->skip) { + WASMModuleInstance *wasm_inst = + (WASMModuleInstance *)get_module_inst(exec_env); - /* Only spread non "wasi proc exit" exception */ -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (curr_wasm_inst->memory_count > 0) - shared_memory_lock(curr_wasm_inst->memories[0]); -#endif - if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) { - bh_memcpy_s(curr_wasm_inst->cur_exception, - sizeof(curr_wasm_inst->cur_exception), - wasm_inst->cur_exception, - sizeof(wasm_inst->cur_exception)); + exception_lock(wasm_inst); + if (data->exception != NULL) { + /* Only spread non "wasi proc exit" exception */ + if (strcmp(data->exception, "wasi proc exit")) { + snprintf(wasm_inst->cur_exception, + sizeof(wasm_inst->cur_exception), "Exception: %s", + data->exception); + } } -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (curr_wasm_inst->memory_count > 0) - shared_memory_unlock(curr_wasm_inst->memories[0]); -#endif + else { + wasm_inst->cur_exception[0] = '\0'; + } + exception_unlock(wasm_inst); /* Terminate the thread so it can exit from dead loops */ - set_thread_cancel_flags(curr_exec_env); - } -} - -static void -clear_exception_visitor(void *node, void *user_data) -{ - WASMExecEnv *exec_env = (WASMExecEnv *)user_data; - WASMExecEnv *curr_exec_env = (WASMExecEnv *)node; - - if (curr_exec_env != exec_env) { - WASMModuleInstance *curr_wasm_inst = - (WASMModuleInstance *)get_module_inst(curr_exec_env); - -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (curr_wasm_inst->memory_count > 0) - shared_memory_lock(curr_wasm_inst->memories[0]); -#endif - curr_wasm_inst->cur_exception[0] = '\0'; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (curr_wasm_inst->memory_count > 0) - shared_memory_unlock(curr_wasm_inst->memories[0]); -#endif + if (data->exception != NULL) { + set_thread_cancel_flags(exec_env); + } } } void -wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear) +wasm_cluster_spread_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.exception = exception; + os_mutex_lock(&cluster->lock); - cluster->has_exception = !clear; - traverse_list(&cluster->exec_env_list, - clear ? clear_exception_visitor : set_exception_visitor, - exec_env); + cluster->has_exception = has_exception; + traverse_list(&cluster->exec_env_list, set_exception_visitor, &data); os_mutex_unlock(&cluster->lock); } @@ -1353,3 +1340,21 @@ wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env) return is_thread_terminated; } + +void +exception_lock(WASMModuleInstance *module_inst) +{ + /* + * Note: this lock could be per module instance if desirable. + * We can revisit on AOT version bump. + * It probably doesn't matter though because the exception handling + * logic should not be executed too frequently anyway. + */ + os_mutex_lock(&_exception_lock); +} + +void +exception_unlock(WASMModuleInstance *module_inst) +{ + os_mutex_unlock(&_exception_lock); +} diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 2060869c2..c6bc7a526 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/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, bool clear); +wasm_cluster_spread_exception(WASMExecEnv *exec_env, const char *exception); WASMExecEnv * wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env); From 1ff41ebdc257b45c9f574d8d1f7ee6df4be79645 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 1 Sep 2023 13:10:54 +0900 Subject: [PATCH 087/123] Implement os_usleep for posix (#2517) --- .../platform/common/posix/posix_sleep.c | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 core/shared/platform/common/posix/posix_sleep.c diff --git a/core/shared/platform/common/posix/posix_sleep.c b/core/shared/platform/common/posix/posix_sleep.c new file mode 100644 index 000000000..fa0645037 --- /dev/null +++ b/core/shared/platform/common/posix/posix_sleep.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "platform_api_extension.h" + +int +os_usleep(uint32 usec) +{ + struct timespec ts; + int ret; + + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + ret = nanosleep(&ts, NULL); + return ret == 0 ? 0 : -1; +} From 8c2dc1d011b39950a4fd29ae9b032b1c1424a6e1 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Mon, 4 Sep 2023 06:21:10 +0100 Subject: [PATCH 088/123] Add unit tests for the tid allocator (#2519) Add simple infrastructure to add more unit tests in the future. At the moment tests are only executed on Linux, but can be extended to other platforms if needed. Use https://github.com/google/googletest/ as a framework. --- .../compilation_on_android_ubuntu.yml | 12 +++- .../lib-wasi-threads/tid_allocator.h | 10 +++ .../lib_wasi_threads_unit_tests.cmake | 6 ++ .../unit-test/test_tid_allocator.cpp | 62 +++++++++++++++++++ tests/unit/CMakeLists.txt | 51 +++++++++++++++ tests/unit/main.cpp | 21 +++++++ 6 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 core/iwasm/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake create mode 100644 core/iwasm/libraries/lib-wasi-threads/unit-test/test_tid_allocator.cpp create mode 100644 tests/unit/CMakeLists.txt create mode 100644 tests/unit/main.cpp diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index b7ac084eb..927ef4d75 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -72,7 +72,7 @@ jobs: with: os: "ubuntu-22.04" arch: "X86" - + build_wamrc: needs: [build_llvm_libraries_on_ubuntu_2204] @@ -241,6 +241,14 @@ jobs: cmake --build . --config Release --parallel 4 working-directory: product-mini/platforms/${{ matrix.platform }} + - name: Build and run unit tests + run: | + mkdir build-unittests && cd build-unittests + cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} + cmake --build . --config Release --parallel 4 + ctest + working-directory: tests/unit + build_samples_wasm_c_api: needs: [ @@ -483,7 +491,7 @@ jobs: sudo tar -xzf wasi-sdk-*.tar.gz sudo mv wasi-sdk-20.0 wasi-sdk - # It is a temporary solution until new wasi-sdk that includes bug fixes is released + # It is a temporary solution until new wasi-sdk that includes bug fixes is released - name: build wasi-libc from source if: matrix.test_option == '$WASI_TEST_OPTIONS' run: | diff --git a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h index 53af1719f..6e25f7749 100644 --- a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h +++ b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h @@ -8,8 +8,14 @@ #include "platform_common.h" +#ifdef __cplusplus +extern "C" { +#endif + #define TID_ALLOCATOR_INIT_SIZE CLUSTER_MAX_THREAD_NUM enum { + /* Keep it in sync with + https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids */ TID_MIN = 1, TID_MAX = 0x1FFFFFFF }; // Reserved TIDs (WASI specification) @@ -33,4 +39,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator); void tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id); +#ifdef __cplusplus +} +#endif + #endif /* _TID_ALLOCATOR_H */ \ No newline at end of file diff --git a/core/iwasm/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake b/core/iwasm/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake new file mode 100644 index 000000000..75d8f4e0e --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake @@ -0,0 +1,6 @@ +# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +create_wamr_unit_test(wasi_threads + ${CMAKE_CURRENT_LIST_DIR}/test_tid_allocator.cpp +) diff --git a/core/iwasm/libraries/lib-wasi-threads/unit-test/test_tid_allocator.cpp b/core/iwasm/libraries/lib-wasi-threads/unit-test/test_tid_allocator.cpp new file mode 100644 index 000000000..6fa7300f6 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/unit-test/test_tid_allocator.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "tid_allocator.h" + +#include + +class TidAllocatorTest : public ::testing::Test +{ + protected: + void SetUp() override { ASSERT_TRUE(tid_allocator_init(&_allocator)); } + + void TearDown() override { tid_allocator_deinit(&_allocator); } + + TidAllocator _allocator; +}; + +static bool +is_tid_valid(int32 tid) +{ + /* See: https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids + */ + return tid >= TID_MIN && tid <= TID_MAX; +} + +TEST_F(TidAllocatorTest, BasicTest) +{ + int32 tid = tid_allocator_get_tid(&_allocator); + + ASSERT_TRUE(is_tid_valid(tid)); +} + +TEST_F(TidAllocatorTest, ShouldFailOnAllocatingMoreThanAllowedThreadIDs) +{ + int32 last_tid = 0; + for (int32 i = 0; i < TID_MAX + 1; i++) { + last_tid = tid_allocator_get_tid(&_allocator); + if (last_tid < 0) { + break; + } + ASSERT_TRUE(is_tid_valid(last_tid)); + } + + ASSERT_LT(last_tid, 0); +} + +TEST_F(TidAllocatorTest, ShouldAllocateMoreThanAllowedTIDsIfOldTIDsAreReleased) +{ + int32 last_tid = 0; + for (int32 i = 0; i < TID_MAX + 1; i++) { + if (last_tid != 0) { + tid_allocator_release_tid(&_allocator, last_tid); + } + + last_tid = tid_allocator_get_tid(&_allocator); + ASSERT_TRUE(is_tid_valid(last_tid)); + } +} diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt new file mode 100644 index 000000000..a9a7b8776 --- /dev/null +++ b/tests/unit/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +project (wamr_unit_tests) + +include (CTest) + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_PLATFORM) + string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +endif () + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +include (FetchContent) +FetchContent_Declare ( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable (googletest) + +include (GoogleTest) + +add_library (wamr_gtest_main main.cpp) +target_link_libraries (wamr_gtest_main PUBLIC gtest vmlib) + +function (create_wamr_unit_test test_name) + set (sources ${ARGN}) + add_executable (${test_name} ${sources}) + target_link_libraries ( + ${test_name} + wamr_gtest_main + vmlib + ${LLVM_AVAILABLE_LIBS} + ) + gtest_discover_tests (${test_name}) + endfunction () + +if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1) + include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake) +endif () diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp new file mode 100644 index 000000000..63695d9ee --- /dev/null +++ b/tests/unit/main.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ +#include +#include "wasm_runtime_common.h" + +int +main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + + if (!wasm_runtime_init()) { + return -1; + } + + int ret = RUN_ALL_TESTS(); + wasm_runtime_destroy(); + + return ret; +} \ No newline at end of file From 2e78230e0655bcb8efc040b51b6a9b8ee1c31f45 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 4 Sep 2023 17:52:19 +0900 Subject: [PATCH 089/123] set_exception_visitor: Remove the special case for wasi proc exit (#2525) While wasi proc exit is not a real trap, what the runtime does on it is mostly same as real traps. That is, kill the siblings threads and represent the exit/trap as the result of the "process" to the user api. There seems no reason to distinguish it from real traps here. Note that: - The target thread either doesn't care the specific exception type or ignore wasi proc exit by themselves. (clear_wasi_proc_exit_exception) - clear_wasi_proc_exit_exception only clears local exception. --- core/iwasm/libraries/thread-mgr/thread_manager.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 02430fe87..9a1e82d31 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -1260,12 +1260,8 @@ set_exception_visitor(void *node, void *user_data) exception_lock(wasm_inst); if (data->exception != NULL) { - /* Only spread non "wasi proc exit" exception */ - if (strcmp(data->exception, "wasi proc exit")) { - snprintf(wasm_inst->cur_exception, - sizeof(wasm_inst->cur_exception), "Exception: %s", - data->exception); - } + snprintf(wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception), + "Exception: %s", data->exception); } else { wasm_inst->cur_exception[0] = '\0'; From 9e3904337edc025f490dde7ad86693f54d3cb761 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 4 Sep 2023 19:01:09 +0900 Subject: [PATCH 090/123] Revert "Return error when exception was raised after main thread finishes" (#2524) This reverts commit 71d43f3ca18b96c983d0fa8ca45ea658d6f9ee4a. --- .../test/trap_after_main_thread_finishes.json | 3 --- product-mini/platforms/posix/main.c | 6 +----- product-mini/platforms/windows/main.c | 6 +----- 3 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json diff --git a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json deleted file mode 100644 index 9dc1e30d2..000000000 --- a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "exit_code": 1 -} diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 5d20fd293..6d4ada662 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -921,12 +921,8 @@ main(int argc, char *argv[]) #if WASM_ENABLE_LIBC_WASI != 0 if (ret == 0) { - /* wait for threads to finish and propagate wasi exit code. */ + /* propagate wasi exit code. */ ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); - if (wasm_runtime_get_exception(wasm_module_inst)) { - /* got an exception in spawned thread */ - ret = 1; - } } #endif diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index b7cf81433..8b1b1f371 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -554,12 +554,8 @@ main(int argc, char *argv[]) #if WASM_ENABLE_LIBC_WASI != 0 if (ret == 0) { - /* wait for threads to finish and propagate wasi exit code. */ + /* propagate wasi exit code. */ ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); - if (wasm_runtime_get_exception(wasm_module_inst)) { - /* got an exception in spawned thread */ - ret = 1; - } } #endif From 48b71a05fbbee26524e50a5d1df0ca77cb39e580 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 4 Sep 2023 20:14:56 +0900 Subject: [PATCH 091/123] libc-wasi: Remove unused code (#2528) --- .../include/wasmtime_ssp.h | 45 ------- .../sandboxed-system-primitives/src/posix.c | 117 ------------------ .../src/ssp_config.h | 6 - 3 files changed, 168 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index 586e5816d..576ffcf30 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -264,37 +264,6 @@ typedef uint8_t __wasi_sdflags_t; typedef uint16_t __wasi_siflags_t; typedef uint8_t __wasi_signal_t; -// 0 is reserved; POSIX has special semantics for kill(pid, 0). -#define __WASI_SIGHUP (1) -#define __WASI_SIGINT (2) -#define __WASI_SIGQUIT (3) -#define __WASI_SIGILL (4) -#define __WASI_SIGTRAP (5) -#define __WASI_SIGABRT (6) -#define __WASI_SIGBUS (7) -#define __WASI_SIGFPE (8) -#define __WASI_SIGKILL (9) -#define __WASI_SIGUSR1 (10) -#define __WASI_SIGSEGV (11) -#define __WASI_SIGUSR2 (12) -#define __WASI_SIGPIPE (13) -#define __WASI_SIGALRM (14) -#define __WASI_SIGTERM (15) -#define __WASI_SIGCHLD (16) -#define __WASI_SIGCONT (17) -#define __WASI_SIGSTOP (18) -#define __WASI_SIGTSTP (19) -#define __WASI_SIGTTIN (20) -#define __WASI_SIGTTOU (21) -#define __WASI_SIGURG (22) -#define __WASI_SIGXCPU (23) -#define __WASI_SIGXFSZ (24) -#define __WASI_SIGVTALRM (25) -#define __WASI_SIGPROF (26) -#define __WASI_SIGWINCH (27) -#define __WASI_SIGPOLL (28) -#define __WASI_SIGPWR (29) -#define __WASI_SIGSYS (30) typedef uint16_t __wasi_subclockflags_t; #define __WASI_SUBSCRIPTION_CLOCK_ABSTIME (0x0001) @@ -986,20 +955,6 @@ __wasi_errno_t wasmtime_ssp_poll_oneoff( size_t *nevents ) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) __attribute__((__warn_unused_result__)); -#if 0 -/** - * We throw exception in libc-wasi wrapper function wasi_proc_exit() - * but not call this function. - */ -_Noreturn void wasmtime_ssp_proc_exit( - __wasi_exitcode_t rval -) WASMTIME_SSP_SYSCALL_NAME(proc_exit); -#endif - -__wasi_errno_t wasmtime_ssp_proc_raise( - __wasi_signal_t sig -) WASMTIME_SSP_SYSCALL_NAME(proc_raise) __attribute__((__warn_unused_result__)); - __wasi_errno_t wasmtime_ssp_random_get( void *buf, size_t buf_len diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 3038e3d44..6fef381df 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -2787,123 +2787,6 @@ wasmtime_ssp_poll_oneoff( return error; } -#if 0 -/** - * We throw exception in libc-wasi wrapper function wasi_proc_exit() - * but not call this function. - */ -void wasmtime_ssp_proc_exit( - __wasi_exitcode_t rval -) { - _Exit((int32)rval); -} -#endif - -__wasi_errno_t -wasmtime_ssp_proc_raise(__wasi_signal_t sig) -{ - static const int signals[] = { -#define X(v) [__WASI_##v] = v -#if defined(SIGABRT) - X(SIGABRT), -#endif -#if defined(SIGALRM) - X(SIGALRM), -#endif -#if defined(SIGBUS) - X(SIGBUS), -#endif -#if defined(SIGCHLD) - X(SIGCHLD), -#endif -#if defined(SIGCONT) - X(SIGCONT), -#endif -#if defined(SIGFPE) - X(SIGFPE), -#endif -#if defined(SIGHUP) - X(SIGHUP), -#endif -#if defined(SIGILL) - X(SIGILL), -#endif -#if defined(SIGINT) - X(SIGINT), -#endif -#if defined(SIGKILL) - X(SIGKILL), -#endif -#if defined(SIGPIPE) - X(SIGPIPE), -#endif -#if defined(SIGQUIT) - X(SIGQUIT), -#endif -#if defined(SIGSYS) - X(SIGSEGV), -#endif -#if defined(SIGSTOP) - X(SIGSTOP), -#endif -#if defined(SIGSYS) - X(SIGSYS), -#endif -#if defined(SIGTERM) - X(SIGTERM), -#endif -#if defined(SIGTRAP) - X(SIGTRAP), -#endif -#if defined(SIGTSTP) - X(SIGTSTP), -#endif -#if defined(SIGTTIN) - X(SIGTTIN), -#endif -#if defined(SIGTTOU) - X(SIGTTOU), -#endif -#if defined(SIGURG) - X(SIGURG), -#endif -#if defined(SIGUSR1) - X(SIGUSR1), -#endif -#if defined(SIGUSR2) - X(SIGUSR2), -#endif -#if defined(SIGVTALRM) - X(SIGVTALRM), -#endif -#if defined(SIGXCPU) - X(SIGXCPU), -#endif -#if defined(SIGXFSZ) - X(SIGXFSZ), -#endif -#undef X - }; - if (sig >= sizeof(signals) / sizeof(signals[0]) || signals[sig] == 0) - return __WASI_EINVAL; - -#if CONFIG_TLS_USE_GSBASE - // TLS on OS X depends on installing a SIGSEGV handler. Reset SIGSEGV - // to the default action before raising. - if (sig == __WASI_SIGSEGV) { - struct sigaction sa = { - .sa_handler = SIG_DFL, - }; - sigemptyset(&sa.sa_mask); - sigaction(SIGSEGV, &sa, NULL); - } -#endif - - if (raise(signals[sig]) < 0) - return convert_errno(errno); - return 0; -} - __wasi_errno_t wasmtime_ssp_random_get(void *buf, size_t nbyte) { diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h index 7f6e9b941..f5e130a9e 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h @@ -101,12 +101,6 @@ #define st_mtim st_mtimespec #endif -#ifdef __APPLE__ -#define CONFIG_TLS_USE_GSBASE 1 -#else -#define CONFIG_TLS_USE_GSBASE 0 -#endif - #if !defined(BH_PLATFORM_LINUX_SGX) /* Clang's __GNUC_PREREQ macro has a different meaning than GCC one, so we have to handle this case specially */ From 709127d631aeef901ecca617439766935abeecc6 Mon Sep 17 00:00:00 2001 From: Enrico Loparco Date: Tue, 5 Sep 2023 10:41:52 +0200 Subject: [PATCH 092/123] Add callback to handle memory.grow failures (#2522) When embedding WAMR, this PR allows to register a callback that is invoked when memory.grow fails. In case of memory allocation failures, some languages allow to handle the error (e.g. by checking the return code of malloc/calloc in C), some others (e.g. Rust) just panic. --- core/iwasm/aot/aot_runtime.c | 3 + core/iwasm/common/wasm_memory.c | 107 ++++++++++++++++++++++---- core/iwasm/common/wasm_memory.h | 4 + core/iwasm/include/wasm_export.h | 17 ++++ core/iwasm/interpreter/wasm_runtime.c | 3 + core/iwasm/interpreter/wasm_runtime.h | 2 + 6 files changed, 119 insertions(+), 17 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 2c647d345..55c399a8b 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1443,6 +1443,9 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, /* set thread handle and stack boundary */ wasm_exec_env_set_thread_info(exec_env); + /* set exec env so it can be later retrieved from instance */ + ((AOTModuleInstanceExtra *)module_inst->e)->common.cur_exec_env = exec_env; + if (ext_ret_count > 0) { uint32 cell_num = 0, i; uint8 *ext_ret_types = func_type->types + func_type->param_count + 1; diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 7d5cb4353..a083a214e 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -8,6 +8,7 @@ #include "../aot/aot_runtime.h" #include "bh_platform.h" #include "mem_alloc.h" +#include "wasm_memory.h" #if WASM_ENABLE_SHARED_MEMORY != 0 #include "../common/wasm_shared_memory.h" @@ -24,6 +25,8 @@ 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; + #if WASM_MEM_ALLOC_WITH_USER_DATA != 0 static void *allocator_user_data = NULL; static void *(*malloc_func)(void *user_data, unsigned int size) = NULL; @@ -570,13 +573,16 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) { WASMMemoryInstance *memory = wasm_get_default_memory(module); uint8 *memory_data_old, *memory_data_new, *heap_data_old; - uint32 num_bytes_per_page, heap_size, total_size_old; + uint32 num_bytes_per_page, heap_size, total_size_old = 0; uint32 cur_page_count, max_page_count, total_page_count; uint64 total_size_new; bool ret = true; + enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR; - if (!memory) - return false; + if (!memory) { + ret = false; + goto return_func; + } heap_data_old = memory->heap_data; heap_size = (uint32)(memory->heap_data_end - memory->heap_data); @@ -594,9 +600,15 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) /* No need to enlarge memory */ return true; - if (total_page_count < cur_page_count /* integer overflow */ - || total_page_count > max_page_count) { - return false; + if (total_page_count < cur_page_count) { /* integer overflow */ + ret = false; + goto return_func; + } + + if (total_page_count > max_page_count) { + failure_reason = MAX_SIZE_REACHED; + ret = false; + goto return_func; } bh_assert(total_size_new <= 4 * (uint64)BH_GB); @@ -622,14 +634,16 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) if (heap_size > 0) { if (mem_allocator_is_heap_corrupted(memory->heap_handle)) { wasm_runtime_show_app_heap_corrupted_prompt(); - return false; + ret = false; + goto return_func; } } if (!(memory_data_new = wasm_runtime_realloc(memory_data_old, (uint32)total_size_new))) { if (!(memory_data_new = wasm_runtime_malloc((uint32)total_size_new))) { - return false; + ret = false; + goto return_func; } if (memory_data_old) { bh_memcpy_s(memory_data_new, (uint32)total_size_new, @@ -685,6 +699,26 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) os_writegsbase(memory_data_new); #endif +return_func: + if (!ret && enlarge_memory_error_cb) { + WASMExecEnv *exec_env = NULL; + +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) + exec_env = + ((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env; +#endif +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) + exec_env = + ((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env; +#endif + + enlarge_memory_error_cb(inc_page_count, total_size_old, 0, + failure_reason, + (WASMModuleInstanceCommon *)module, exec_env); + } + return ret; } #else @@ -692,12 +726,16 @@ bool wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) { WASMMemoryInstance *memory = wasm_get_default_memory(module); - uint32 num_bytes_per_page, total_size_old; + uint32 num_bytes_per_page, total_size_old = 0; uint32 cur_page_count, max_page_count, total_page_count; uint64 total_size_new; + bool ret = true; + enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR; - if (!memory) - return false; + if (!memory) { + ret = false; + goto return_func; + } num_bytes_per_page = memory->num_bytes_per_page; cur_page_count = memory->cur_page_count; @@ -710,9 +748,15 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) /* No need to enlarge memory */ return true; - if (total_page_count < cur_page_count /* integer overflow */ - || total_page_count > max_page_count) { - return false; + if (total_page_count < cur_page_count) { /* integer overflow */ + ret = false; + goto return_func; + } + + if (total_page_count > max_page_count) { + failure_reason = MAX_SIZE_REACHED; + ret = false; + goto return_func; } bh_assert(total_size_new <= 4 * (uint64)BH_GB); @@ -727,7 +771,8 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) if (!os_mem_commit(memory->memory_data_end, (uint32)total_size_new - total_size_old, MMAP_PROT_READ | MMAP_PROT_WRITE)) { - return false; + ret = false; + goto return_func; } #endif @@ -739,7 +784,8 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) os_mem_decommit(memory->memory_data_end, (uint32)total_size_new - total_size_old); #endif - return false; + ret = false; + goto return_func; } /* The increased pages are filled with zero by the OS when os_mmap, @@ -759,10 +805,37 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) memory->mem_bound_check_16bytes.u64 = total_size_new - 16; #endif - return true; +return_func: + if (!ret && enlarge_memory_error_cb) { + WASMExecEnv *exec_env = NULL; + +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) + exec_env = + ((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env; +#endif +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) + exec_env = + ((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env; +#endif + + enlarge_memory_error_cb(inc_page_count, total_size_old, 0, + failure_reason, + (WASMModuleInstanceCommon *)module, exec_env); + } + + return ret; } #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ +void +wasm_runtime_set_enlarge_mem_error_callback( + const enlarge_memory_error_callback_t callback) +{ + enlarge_memory_error_cb = callback; +} + bool wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) { diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index 516ee8497..cf7d7ffcd 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/core/iwasm/common/wasm_memory.h @@ -24,6 +24,10 @@ wasm_runtime_memory_destroy(); unsigned wasm_runtime_memory_pool_size(); +void +wasm_runtime_set_enlarge_mem_error_callback( + const enlarge_memory_error_callback_t callback); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 18e15782f..79edc68ed 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1439,6 +1439,23 @@ WASM_RUNTIME_API_EXTERN bool wasm_runtime_is_import_global_linked(const char *module_name, const char *global_name); +typedef enum { + INTERNAL_ERROR, + MAX_SIZE_REACHED, +} enlarge_memory_error_reason_t; + +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); + +/** + * 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); + /* clang-format on */ #ifdef __cplusplus diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index b71b608a2..f395b1eaa 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2400,6 +2400,9 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, /* set thread handle and stack boundary */ wasm_exec_env_set_thread_info(exec_env); + /* set exec env so it can be later retrieved from instance */ + module_inst->e->common.cur_exec_env = exec_env; + interp_call_wasm(module_inst, exec_env, function, argc, argv); return !wasm_copy_exception(module_inst, NULL); } diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 784febd44..aa33dc18c 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -213,6 +213,8 @@ typedef struct CApiFuncImport { /* The common part of WASMModuleInstanceExtra and AOTModuleInstanceExtra */ typedef struct WASMModuleInstanceExtraCommon { CApiFuncImport *c_api_func_imports; + /* pointer to the exec env currently used */ + WASMExecEnv *cur_exec_env; #if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 /* Disable bounds checks or not */ bool disable_bounds_checks; From 4798b69f36058cfb438e8a3181726f00726b7d95 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Wed, 6 Sep 2023 06:17:16 +0100 Subject: [PATCH 093/123] Add ARM aeabi symbol for clearing memory content in a specific range (#2531) --- core/iwasm/aot/arch/aot_reloc_arm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/iwasm/aot/arch/aot_reloc_arm.c b/core/iwasm/aot/arch/aot_reloc_arm.c index fbf9be13c..5d79e8a68 100644 --- a/core/iwasm/aot/arch/aot_reloc_arm.c +++ b/core/iwasm/aot/arch/aot_reloc_arm.c @@ -40,6 +40,7 @@ void __aeabi_ldivmod(); void __aeabi_memcpy(); void __aeabi_memmove(); void __aeabi_memset(); +void __aeabi_memclr(); void __aeabi_uidiv(); void __aeabi_uidivmod(); void __aeabi_ul2d(); @@ -126,6 +127,7 @@ static SymbolMap target_sym_map[] = { REG_SYM(__aeabi_memcpy), REG_SYM(__aeabi_memmove), REG_SYM(__aeabi_memset), + REG_SYM(__aeabi_memclr), REG_SYM(__aeabi_uidiv), REG_SYM(__aeabi_uidivmod), REG_SYM(__aeabi_ul2d), From 151dfae49cc1b62aa52857d9b558b50b1b24841a Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 6 Sep 2023 16:25:58 +0900 Subject: [PATCH 094/123] Unifdef -U WASMTIME_SSP_STATIC_CURFDS (#2533) The macro WASMTIME_SSP_STATIC_CURFDS isn't used in the source code, remove the related macro control code. --- .../include/wasmtime_ssp.h | 190 ------- .../sandboxed-system-primitives/src/posix.c | 522 ++++++------------ 2 files changed, 166 insertions(+), 546 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index 576ffcf30..a53153552 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -598,17 +598,13 @@ typedef struct __wasi_addr_info_hints_t { #endif __wasi_errno_t wasmtime_ssp_args_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct argv_environ_values *arg_environ, -#endif char **argv, char *argv_buf ) WASMTIME_SSP_SYSCALL_NAME(args_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_args_sizes_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct argv_environ_values *arg_environ, -#endif size_t *argc, size_t *argv_buf_size ) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) __attribute__((__warn_unused_result__)); @@ -625,57 +621,43 @@ __wasi_errno_t wasmtime_ssp_clock_time_get( ) WASMTIME_SSP_SYSCALL_NAME(clock_time_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_environ_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct argv_environ_values *arg_environ, -#endif char **environ, char *environ_buf ) WASMTIME_SSP_SYSCALL_NAME(environ_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_environ_sizes_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct argv_environ_values *arg_environ, -#endif size_t *environ_count, size_t *environ_buf_size ) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_prestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_prestats *prestats, -#endif __wasi_fd_t fd, __wasi_prestat_t *buf ) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_prestats *prestats, -#endif __wasi_fd_t fd, char *path, size_t path_len ) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_close( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, struct fd_prestats *prestats, -#endif __wasi_fd_t fd ) WASMTIME_SSP_SYSCALL_NAME(fd_close) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_datasync( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd ) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_pread( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, const __wasi_iovec_t *iovs, size_t iovs_len, @@ -684,9 +666,7 @@ __wasi_errno_t wasmtime_ssp_fd_pread( ) WASMTIME_SSP_SYSCALL_NAME(fd_pread) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_pwrite( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, const __wasi_ciovec_t *iovs, size_t iovs_len, @@ -695,9 +675,7 @@ __wasi_errno_t wasmtime_ssp_fd_pwrite( ) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_read( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, const __wasi_iovec_t *iovs, size_t iovs_len, @@ -705,18 +683,14 @@ __wasi_errno_t wasmtime_ssp_fd_read( ) WASMTIME_SSP_SYSCALL_NAME(fd_read) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_renumber( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, struct fd_prestats *prestats, -#endif __wasi_fd_t from, __wasi_fd_t to ) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_seek( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_filedelta_t offset, __wasi_whence_t whence, @@ -724,49 +698,37 @@ __wasi_errno_t wasmtime_ssp_fd_seek( ) WASMTIME_SSP_SYSCALL_NAME(fd_seek) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_tell( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_filesize_t *newoffset ) WASMTIME_SSP_SYSCALL_NAME(fd_tell) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_fdstat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_fdstat_t *buf ) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_fdflags_t flags ) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_rights_t fs_rights_base, __wasi_rights_t fs_rights_inheriting ) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_sync( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd ) WASMTIME_SSP_SYSCALL_NAME(fd_sync) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_write( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, const __wasi_ciovec_t *iovs, size_t iovs_len, @@ -774,9 +736,7 @@ __wasi_errno_t wasmtime_ssp_fd_write( ) WASMTIME_SSP_SYSCALL_NAME(fd_write) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_advise( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len, @@ -784,28 +744,22 @@ __wasi_errno_t wasmtime_ssp_fd_advise( ) WASMTIME_SSP_SYSCALL_NAME(fd_advise) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_allocate( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len ) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_create_directory( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, const char *path, size_t path_len ) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_link( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, struct fd_prestats *prestats, -#endif __wasi_fd_t old_fd, __wasi_lookupflags_t old_flags, const char *old_path, @@ -816,9 +770,7 @@ __wasi_errno_t wasmtime_ssp_path_link( ) WASMTIME_SSP_SYSCALL_NAME(path_link) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_open( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, const char *path, @@ -831,9 +783,7 @@ __wasi_errno_t wasmtime_ssp_path_open( ) WASMTIME_SSP_SYSCALL_NAME(path_open) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_readdir( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, void *buf, size_t buf_len, @@ -842,9 +792,7 @@ __wasi_errno_t wasmtime_ssp_fd_readdir( ) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_readlink( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, const char *path, size_t path_len, @@ -854,9 +802,7 @@ __wasi_errno_t wasmtime_ssp_path_readlink( ) WASMTIME_SSP_SYSCALL_NAME(path_readlink) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_rename( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t old_fd, const char *old_path, size_t old_path_len, @@ -866,17 +812,13 @@ __wasi_errno_t wasmtime_ssp_path_rename( ) WASMTIME_SSP_SYSCALL_NAME(path_rename) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_filestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_filestat_t *buf ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_filestat_set_times( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, @@ -884,17 +826,13 @@ __wasi_errno_t wasmtime_ssp_fd_filestat_set_times( ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_filestat_set_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_filesize_t st_size ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_filestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, @@ -903,9 +841,7 @@ __wasi_errno_t wasmtime_ssp_path_filestat_get( ) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_filestat_set_times( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, @@ -916,10 +852,8 @@ __wasi_errno_t wasmtime_ssp_path_filestat_set_times( ) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_symlink( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, struct fd_prestats *prestats, -#endif const char *old_path, size_t old_path_len, __wasi_fd_t fd, @@ -928,27 +862,21 @@ __wasi_errno_t wasmtime_ssp_path_symlink( ) WASMTIME_SSP_SYSCALL_NAME(path_symlink) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_unlink_file( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, const char *path, size_t path_len ) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_remove_directory( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, const char *path, size_t path_len ) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_poll_oneoff( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions, @@ -962,50 +890,38 @@ __wasi_errno_t wasmtime_ssp_random_get( __wasi_errno_t wasi_ssp_sock_accept( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_addr_local( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_addr_t *addr ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_addr_remote( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_addr_t *addr ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_open( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype, __wasi_fd_t *sockfd ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_bind( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, struct addr_pool *addr_pool, -#endif __wasi_fd_t fd, __wasi_addr_t *addr ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_addr_resolve( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, char **ns_lookup_list, -#endif const char *host, const char* service, __wasi_addr_info_hints_t *hints, __wasi_addr_info_t *addr_info, __wasi_size_t addr_info_size, __wasi_size_t *max_info_size @@ -1013,88 +929,66 @@ wasi_ssp_sock_addr_resolve( __wasi_errno_t wasi_ssp_sock_connect( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, struct addr_pool *addr_pool, -#endif __wasi_fd_t fd, __wasi_addr_t *addr ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_get_recv_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_size_t *size ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_get_reuse_addr( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, uint8_t *reuse ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_get_reuse_port( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, uint8_t *reuse ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_get_send_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_size_t *size ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_set_recv_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_size_t size ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_set_reuse_addr( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, uint8_t reuse ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_set_reuse_port( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, uint8_t reuse ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_set_send_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_size_t size ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_listen( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_size_t backlog ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_recv( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, void *buf, size_t buf_len, @@ -1102,9 +996,7 @@ __wasi_errno_t wasmtime_ssp_sock_recv( ) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_recv_from( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, void *buf, size_t buf_len, @@ -1114,9 +1006,7 @@ __wasi_errno_t wasmtime_ssp_sock_recv_from( ) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_send( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, const void *buf, size_t buf_len, @@ -1124,9 +1014,7 @@ __wasi_errno_t wasmtime_ssp_sock_send( ) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_send_to( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, struct addr_pool *addr_pool, -#endif __wasi_fd_t sock, const void *buf, size_t buf_len, @@ -1136,317 +1024,239 @@ __wasi_errno_t wasmtime_ssp_sock_send_to( ) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_shutdown( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock ) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_recv_timeout( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint64_t timeout_us ) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_recv_timeout( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint64_t *timeout_us ) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_send_timeout( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint64_t timeout_us ) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_send_timeout( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint64_t *timeout_us ) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_send_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, size_t bufsiz ) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_send_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, size_t *bufsiz ) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, size_t bufsiz ) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, size_t *bufsiz ) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_keep_alive( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_keep_alive( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_reuse_addr( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_reuse_addr( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_reuse_port( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_reuse_port( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_linger( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool is_enabled, int linger_s ) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_linger( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool *is_enabled, int *linger_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_broadcast( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_broadcast( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint32_t time_s ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint32_t *time_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint32_t time_s ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint32_t *time_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool ipv6, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool ipv6, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_ttl( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint8_t ttl_s ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_ip_ttl( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint8_t *ttl_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint8_t ttl_s ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, uint8_t *ttl_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ipv6_only( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_ipv6_only( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, -#endif __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) __attribute__((__warn_unused_result__)); diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 6fef381df..9fabd8830 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -55,13 +55,6 @@ static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t), "Size mismatch"); #endif -#if defined(WASMTIME_SSP_STATIC_CURFDS) -static __thread struct fd_table *curfds; -static __thread struct fd_prestats *prestats; -static __thread struct argv_environ_values *argv_environ; -static __thread struct addr_pool *addr_pool; -#endif - // Converts a POSIX error code to a CloudABI error code. static __wasi_errno_t convert_errno(int error) @@ -340,9 +333,6 @@ fd_prestats_init(struct fd_prestats *pt) pt->prestats = NULL; pt->size = 0; pt->used = 0; -#if defined(WASMTIME_SSP_STATIC_CURFDS) - prestats = pt; -#endif return true; } @@ -446,9 +436,6 @@ fd_table_init(struct fd_table *ft) ft->entries = NULL; ft->size = 0; ft->used = 0; -#if defined(WASMTIME_SSP_STATIC_CURFDS) - curfds = ft; -#endif return true; } @@ -786,11 +773,8 @@ fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type, } __wasi_errno_t -wasmtime_ssp_fd_prestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_prestats *prestats, -#endif - __wasi_fd_t fd, __wasi_prestat_t *buf) +wasmtime_ssp_fd_prestat_get(struct fd_prestats *prestats, __wasi_fd_t fd, + __wasi_prestat_t *buf) { rwlock_rdlock(&prestats->lock); struct fd_prestat *prestat; @@ -812,11 +796,8 @@ wasmtime_ssp_fd_prestat_get( } __wasi_errno_t -wasmtime_ssp_fd_prestat_dir_name( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_prestats *prestats, -#endif - __wasi_fd_t fd, char *path, size_t path_len) +wasmtime_ssp_fd_prestat_dir_name(struct fd_prestats *prestats, __wasi_fd_t fd, + char *path, size_t path_len) { rwlock_rdlock(&prestats->lock); struct fd_prestat *prestat; @@ -838,11 +819,8 @@ wasmtime_ssp_fd_prestat_dir_name( } __wasi_errno_t -wasmtime_ssp_fd_close( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct fd_prestats *prestats, -#endif - __wasi_fd_t fd) +wasmtime_ssp_fd_close(struct fd_table *curfds, struct fd_prestats *prestats, + __wasi_fd_t fd) { // Don't allow closing a pre-opened resource. // TODO: Eventually, we do want to permit this, once libpreopen in @@ -914,11 +892,7 @@ fd_object_get(struct fd_table *curfds, struct fd_object **fo, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_datasync( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd) +wasmtime_ssp_fd_datasync(struct fd_table *curfds, __wasi_fd_t fd) { struct fd_object *fo; __wasi_errno_t error = @@ -938,12 +912,9 @@ wasmtime_ssp_fd_datasync( } __wasi_errno_t -wasmtime_ssp_fd_pread( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, - __wasi_filesize_t offset, size_t *nread) +wasmtime_ssp_fd_pread(struct fd_table *curfds, __wasi_fd_t fd, + const __wasi_iovec_t *iov, size_t iovcnt, + __wasi_filesize_t offset, size_t *nread) { if (iovcnt == 0) return __WASI_EINVAL; @@ -1012,12 +983,9 @@ wasmtime_ssp_fd_pread( } __wasi_errno_t -wasmtime_ssp_fd_pwrite( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, - __wasi_filesize_t offset, size_t *nwritten) +wasmtime_ssp_fd_pwrite(struct fd_table *curfds, __wasi_fd_t fd, + const __wasi_ciovec_t *iov, size_t iovcnt, + __wasi_filesize_t offset, size_t *nwritten) { if (iovcnt == 0) return __WASI_EINVAL; @@ -1066,11 +1034,8 @@ wasmtime_ssp_fd_pwrite( } __wasi_errno_t -wasmtime_ssp_fd_read( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, size_t *nread) +wasmtime_ssp_fd_read(struct fd_table *curfds, __wasi_fd_t fd, + const __wasi_iovec_t *iov, size_t iovcnt, size_t *nread) { struct fd_object *fo; __wasi_errno_t error = @@ -1087,11 +1052,8 @@ wasmtime_ssp_fd_read( } __wasi_errno_t -wasmtime_ssp_fd_renumber( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct fd_prestats *prestats, -#endif - __wasi_fd_t from, __wasi_fd_t to) +wasmtime_ssp_fd_renumber(struct fd_table *curfds, struct fd_prestats *prestats, + __wasi_fd_t from, __wasi_fd_t to) { // Don't allow renumbering over a pre-opened resource. // TODO: Eventually, we do want to permit this, once libpreopen in @@ -1141,12 +1103,9 @@ wasmtime_ssp_fd_renumber( } __wasi_errno_t -wasmtime_ssp_fd_seek( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filedelta_t offset, __wasi_whence_t whence, - __wasi_filesize_t *newoffset) +wasmtime_ssp_fd_seek(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_filedelta_t offset, __wasi_whence_t whence, + __wasi_filesize_t *newoffset) { int nwhence; switch (whence) { @@ -1182,11 +1141,8 @@ wasmtime_ssp_fd_seek( } __wasi_errno_t -wasmtime_ssp_fd_tell( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filesize_t *newoffset) +wasmtime_ssp_fd_tell(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_filesize_t *newoffset) { struct fd_object *fo; __wasi_errno_t error = @@ -1203,11 +1159,8 @@ wasmtime_ssp_fd_tell( } __wasi_errno_t -wasmtime_ssp_fd_fdstat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_fdstat_t *buf) +wasmtime_ssp_fd_fdstat_get(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_fdstat_t *buf) { struct fd_table *ft = curfds; rwlock_rdlock(&ft->lock); @@ -1255,11 +1208,8 @@ wasmtime_ssp_fd_fdstat_get( } __wasi_errno_t -wasmtime_ssp_fd_fdstat_set_flags( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_fdflags_t fs_flags) +wasmtime_ssp_fd_fdstat_set_flags(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_fdflags_t fs_flags) { int noflags = 0; if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) @@ -1295,12 +1245,9 @@ wasmtime_ssp_fd_fdstat_set_flags( } __wasi_errno_t -wasmtime_ssp_fd_fdstat_set_rights( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_rights_t fs_rights_base, - __wasi_rights_t fs_rights_inheriting) +wasmtime_ssp_fd_fdstat_set_rights(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting) { struct fd_table *ft = curfds; rwlock_wrlock(&ft->lock); @@ -1320,11 +1267,7 @@ wasmtime_ssp_fd_fdstat_set_rights( } __wasi_errno_t -wasmtime_ssp_fd_sync( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd) +wasmtime_ssp_fd_sync(struct fd_table *curfds, __wasi_fd_t fd) { struct fd_object *fo; __wasi_errno_t error = @@ -1340,11 +1283,9 @@ wasmtime_ssp_fd_sync( } __wasi_errno_t -wasmtime_ssp_fd_write( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, size_t *nwritten) +wasmtime_ssp_fd_write(struct fd_table *curfds, __wasi_fd_t fd, + const __wasi_ciovec_t *iov, size_t iovcnt, + size_t *nwritten) { struct fd_object *fo; __wasi_errno_t error = @@ -1383,12 +1324,9 @@ wasmtime_ssp_fd_write( } __wasi_errno_t -wasmtime_ssp_fd_advise( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len, - __wasi_advice_t advice) +wasmtime_ssp_fd_advise(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_filesize_t offset, __wasi_filesize_t len, + __wasi_advice_t advice) { #ifdef POSIX_FADV_NORMAL int nadvice; @@ -1452,11 +1390,8 @@ wasmtime_ssp_fd_advise( } __wasi_errno_t -wasmtime_ssp_fd_allocate( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len) +wasmtime_ssp_fd_allocate(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_filesize_t offset, __wasi_filesize_t len) { struct fd_object *fo; __wasi_errno_t error = @@ -1793,11 +1728,8 @@ path_put(struct path_access *pa) UNLOCKS(pa->fd_object->refcount) } __wasi_errno_t -wasmtime_ssp_path_create_directory( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const char *path, size_t pathlen) +wasmtime_ssp_path_create_directory(struct fd_table *curfds, __wasi_fd_t fd, + const char *path, size_t pathlen) { struct path_access pa; __wasi_errno_t error = @@ -1841,13 +1773,11 @@ validate_path(const char *path, struct fd_prestats *pt) } __wasi_errno_t -wasmtime_ssp_path_link( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct fd_prestats *prestats, -#endif - __wasi_fd_t old_fd, __wasi_lookupflags_t old_flags, const char *old_path, - size_t old_path_len, __wasi_fd_t new_fd, const char *new_path, - size_t new_path_len) +wasmtime_ssp_path_link(struct fd_table *curfds, struct fd_prestats *prestats, + __wasi_fd_t old_fd, __wasi_lookupflags_t old_flags, + const char *old_path, size_t old_path_len, + __wasi_fd_t new_fd, const char *new_path, + size_t new_path_len) { struct path_access old_pa; __wasi_errno_t error = @@ -1900,14 +1830,12 @@ wasmtime_ssp_path_link( } __wasi_errno_t -wasmtime_ssp_path_open( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, const char *path, - size_t pathlen, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base, - __wasi_rights_t fs_rights_inheriting, __wasi_fdflags_t fs_flags, - __wasi_fd_t *fd) +wasmtime_ssp_path_open(struct fd_table *curfds, __wasi_fd_t dirfd, + __wasi_lookupflags_t dirflags, const char *path, + size_t pathlen, __wasi_oflags_t oflags, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting, + __wasi_fdflags_t fs_flags, __wasi_fd_t *fd) { // Rights that should be installed on the new file descriptor. __wasi_rights_t rights_base = fs_rights_base; @@ -2054,12 +1982,9 @@ fd_readdir_put(void *buf, size_t bufsize, size_t *bufused, const void *elem, } __wasi_errno_t -wasmtime_ssp_fd_readdir( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, void *buf, size_t nbyte, __wasi_dircookie_t cookie, - size_t *bufused) +wasmtime_ssp_fd_readdir(struct fd_table *curfds, __wasi_fd_t fd, void *buf, + size_t nbyte, __wasi_dircookie_t cookie, + size_t *bufused) { struct fd_object *fo; __wasi_errno_t error = @@ -2153,12 +2078,9 @@ wasmtime_ssp_fd_readdir( } __wasi_errno_t -wasmtime_ssp_path_readlink( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const char *path, size_t pathlen, char *buf, size_t bufsize, - size_t *bufused) +wasmtime_ssp_path_readlink(struct fd_table *curfds, __wasi_fd_t fd, + const char *path, size_t pathlen, char *buf, + size_t bufsize, size_t *bufused) { struct path_access pa; __wasi_errno_t error = path_get_nofollow( @@ -2179,12 +2101,10 @@ wasmtime_ssp_path_readlink( } __wasi_errno_t -wasmtime_ssp_path_rename( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t old_fd, const char *old_path, size_t old_path_len, - __wasi_fd_t new_fd, const char *new_path, size_t new_path_len) +wasmtime_ssp_path_rename(struct fd_table *curfds, __wasi_fd_t old_fd, + const char *old_path, size_t old_path_len, + __wasi_fd_t new_fd, const char *new_path, + size_t new_path_len) { struct path_access old_pa; __wasi_errno_t error = @@ -2226,11 +2146,8 @@ convert_stat(const struct stat *in, __wasi_filestat_t *out) } __wasi_errno_t -wasmtime_ssp_fd_filestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filestat_t *buf) +wasmtime_ssp_fd_filestat_get(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_filestat_t *buf) { struct fd_object *fo; __wasi_errno_t error = @@ -2299,11 +2216,8 @@ convert_utimens_arguments(__wasi_timestamp_t st_atim, } __wasi_errno_t -wasmtime_ssp_fd_filestat_set_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filesize_t st_size) +wasmtime_ssp_fd_filestat_set_size(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_filesize_t st_size) { struct fd_object *fo; __wasi_errno_t error = @@ -2319,12 +2233,10 @@ wasmtime_ssp_fd_filestat_set_size( } __wasi_errno_t -wasmtime_ssp_fd_filestat_set_times( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags) +wasmtime_ssp_fd_filestat_set_times(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) { if ((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW @@ -2349,12 +2261,9 @@ wasmtime_ssp_fd_filestat_set_times( } __wasi_errno_t -wasmtime_ssp_path_filestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, - size_t pathlen, __wasi_filestat_t *buf) +wasmtime_ssp_path_filestat_get(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_lookupflags_t flags, const char *path, + size_t pathlen, __wasi_filestat_t *buf) { struct path_access pa; __wasi_errno_t error = path_get(curfds, &pa, fd, flags, path, pathlen, @@ -2389,13 +2298,12 @@ wasmtime_ssp_path_filestat_get( } __wasi_errno_t -wasmtime_ssp_path_filestat_set_times( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, - size_t pathlen, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags) +wasmtime_ssp_path_filestat_set_times(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *path, size_t pathlen, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) { if (((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW @@ -2428,12 +2336,10 @@ wasmtime_ssp_path_filestat_set_times( } __wasi_errno_t -wasmtime_ssp_path_symlink( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct fd_prestats *prestats, -#endif - const char *old_path, size_t old_path_len, __wasi_fd_t fd, - const char *new_path, size_t new_path_len) +wasmtime_ssp_path_symlink(struct fd_table *curfds, struct fd_prestats *prestats, + const char *old_path, size_t old_path_len, + __wasi_fd_t fd, const char *new_path, + size_t new_path_len) { char *target = str_nullterminate(old_path, old_path_len); if (target == NULL) @@ -2465,11 +2371,8 @@ wasmtime_ssp_path_symlink( } __wasi_errno_t -wasmtime_ssp_path_unlink_file( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const char *path, size_t pathlen) +wasmtime_ssp_path_unlink_file(struct fd_table *curfds, __wasi_fd_t fd, + const char *path, size_t pathlen) { struct path_access pa; __wasi_errno_t error = path_get_nofollow( @@ -2502,11 +2405,8 @@ wasmtime_ssp_path_unlink_file( } __wasi_errno_t -wasmtime_ssp_path_remove_directory( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const char *path, size_t pathlen) +wasmtime_ssp_path_remove_directory(struct fd_table *curfds, __wasi_fd_t fd, + const char *path, size_t pathlen) { struct path_access pa; __wasi_errno_t error = @@ -2531,12 +2431,10 @@ wasmtime_ssp_path_remove_directory( } __wasi_errno_t -wasmtime_ssp_poll_oneoff( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions, - size_t *nevents) NO_LOCK_ANALYSIS +wasmtime_ssp_poll_oneoff(struct fd_table *curfds, + const __wasi_subscription_t *in, __wasi_event_t *out, + size_t nsubscriptions, + size_t *nevents) NO_LOCK_ANALYSIS { // Sleeping. if (nsubscriptions == 1 && in[0].u.type == __WASI_EVENTTYPE_CLOCK) { @@ -2795,11 +2693,8 @@ wasmtime_ssp_random_get(void *buf, size_t nbyte) } __wasi_errno_t -wasi_ssp_sock_accept( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new) +wasi_ssp_sock_accept(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_fdflags_t flags, __wasi_fd_t *fd_new) { __wasi_filetype_t wasi_type; __wasi_rights_t max_base, max_inheriting; @@ -2843,11 +2738,8 @@ fail: } __wasi_errno_t -wasi_ssp_sock_addr_local( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_addr_local(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_addr_t *addr) { struct fd_object *fo; bh_sockaddr_t bh_addr; @@ -2870,11 +2762,8 @@ wasi_ssp_sock_addr_local( } __wasi_errno_t -wasi_ssp_sock_addr_remote( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_addr_remote(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_addr_t *addr) { struct fd_object *fo; bh_sockaddr_t bh_addr; @@ -2926,11 +2815,8 @@ wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen) } __wasi_errno_t -wasi_ssp_sock_bind( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct addr_pool *addr_pool, -#endif - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_bind(struct fd_table *curfds, struct addr_pool *addr_pool, + __wasi_fd_t fd, __wasi_addr_t *addr) { char buf[48] = { 0 }; struct fd_object *fo; @@ -2960,13 +2846,12 @@ wasi_ssp_sock_bind( } __wasi_errno_t -wasi_ssp_sock_addr_resolve( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, char **ns_lookup_list, -#endif - const char *host, const char *service, __wasi_addr_info_hints_t *hints, - __wasi_addr_info_t *addr_info, __wasi_size_t addr_info_size, - __wasi_size_t *max_info_size) +wasi_ssp_sock_addr_resolve(struct fd_table *curfds, char **ns_lookup_list, + const char *host, const char *service, + __wasi_addr_info_hints_t *hints, + __wasi_addr_info_t *addr_info, + __wasi_size_t addr_info_size, + __wasi_size_t *max_info_size) { bh_addr_info_t *wamr_addr_info = wasm_runtime_malloc(addr_info_size * sizeof(bh_addr_info_t)); @@ -3013,11 +2898,8 @@ wasi_ssp_sock_addr_resolve( } __wasi_errno_t -wasi_ssp_sock_connect( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct addr_pool *addr_pool, -#endif - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_connect(struct fd_table *curfds, struct addr_pool *addr_pool, + __wasi_fd_t fd, __wasi_addr_t *addr) { char buf[48] = { 0 }; struct fd_object *fo; @@ -3048,11 +2930,8 @@ wasi_ssp_sock_connect( } __wasi_errno_t -wasi_ssp_sock_get_recv_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t *size) +wasi_ssp_sock_get_recv_buf_size(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t *size) { struct fd_object *fo; int ret; @@ -3075,11 +2954,8 @@ wasi_ssp_sock_get_recv_buf_size( } __wasi_errno_t -wasi_ssp_sock_get_reuse_addr( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, uint8_t *reuse) +wasi_ssp_sock_get_reuse_addr(struct fd_table *curfds, __wasi_fd_t fd, + uint8_t *reuse) { struct fd_object *fo; @@ -3103,11 +2979,8 @@ wasi_ssp_sock_get_reuse_addr( } __wasi_errno_t -wasi_ssp_sock_get_reuse_port( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, uint8_t *reuse) +wasi_ssp_sock_get_reuse_port(struct fd_table *curfds, __wasi_fd_t fd, + uint8_t *reuse) { struct fd_object *fo; int ret; @@ -3137,11 +3010,8 @@ wasi_ssp_sock_get_reuse_port( } __wasi_errno_t -wasi_ssp_sock_get_send_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t *size) +wasi_ssp_sock_get_send_buf_size(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t *size) { struct fd_object *fo; int ret; @@ -3164,11 +3034,8 @@ wasi_ssp_sock_get_send_buf_size( } __wasi_errno_t -wasi_ssp_sock_listen( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t backlog) +wasi_ssp_sock_listen(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t backlog) { struct fd_object *fo; int ret; @@ -3187,12 +3054,9 @@ wasi_ssp_sock_listen( } __wasi_errno_t -wasi_ssp_sock_open( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype, - __wasi_fd_t *sockfd) +wasi_ssp_sock_open(struct fd_table *curfds, __wasi_fd_t poolfd, + __wasi_address_family_t af, __wasi_sock_type_t socktype, + __wasi_fd_t *sockfd) { bh_socket_t sock; bool is_tcp = SOCKET_DGRAM == socktype ? false : true; @@ -3234,11 +3098,8 @@ wasi_ssp_sock_open( } __wasi_errno_t -wasi_ssp_sock_set_recv_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t size) +wasi_ssp_sock_set_recv_buf_size(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t size) { struct fd_object *fo; int ret; @@ -3259,11 +3120,8 @@ wasi_ssp_sock_set_recv_buf_size( } __wasi_errno_t -wasi_ssp_sock_set_reuse_addr( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, uint8_t reuse) +wasi_ssp_sock_set_reuse_addr(struct fd_table *curfds, __wasi_fd_t fd, + uint8_t reuse) { struct fd_object *fo; int ret; @@ -3284,11 +3142,8 @@ wasi_ssp_sock_set_reuse_addr( } __wasi_errno_t -wasi_ssp_sock_set_reuse_port( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, uint8_t reuse) +wasi_ssp_sock_set_reuse_port(struct fd_table *curfds, __wasi_fd_t fd, + uint8_t reuse) { struct fd_object *fo; int ret; @@ -3315,11 +3170,8 @@ wasi_ssp_sock_set_reuse_port( } __wasi_errno_t -wasi_ssp_sock_set_send_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t size) +wasi_ssp_sock_set_send_buf_size(struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t size) { struct fd_object *fo; int ret; @@ -3341,11 +3193,8 @@ wasi_ssp_sock_set_send_buf_size( } __wasi_errno_t -wasmtime_ssp_sock_recv( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len) +wasmtime_ssp_sock_recv(struct fd_table *curfds, __wasi_fd_t sock, void *buf, + size_t buf_len, size_t *recv_len) { __wasi_addr_t src_addr; @@ -3354,12 +3203,10 @@ wasmtime_ssp_sock_recv( } __wasi_errno_t -wasmtime_ssp_sock_recv_from( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, void *buf, size_t buf_len, __wasi_riflags_t ri_flags, - __wasi_addr_t *src_addr, size_t *recv_len) +wasmtime_ssp_sock_recv_from(struct fd_table *curfds, __wasi_fd_t sock, + void *buf, size_t buf_len, + __wasi_riflags_t ri_flags, __wasi_addr_t *src_addr, + size_t *recv_len) { struct fd_object *fo; __wasi_errno_t error; @@ -3384,11 +3231,8 @@ wasmtime_ssp_sock_recv_from( } __wasi_errno_t -wasmtime_ssp_sock_send( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, const void *buf, size_t buf_len, size_t *sent_len) +wasmtime_ssp_sock_send(struct fd_table *curfds, __wasi_fd_t sock, + const void *buf, size_t buf_len, size_t *sent_len) { struct fd_object *fo; __wasi_errno_t error; @@ -3410,12 +3254,10 @@ wasmtime_ssp_sock_send( } __wasi_errno_t -wasmtime_ssp_sock_send_to( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct addr_pool *addr_pool, -#endif - __wasi_fd_t sock, const void *buf, size_t buf_len, - __wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr, size_t *sent_len) +wasmtime_ssp_sock_send_to(struct fd_table *curfds, struct addr_pool *addr_pool, + __wasi_fd_t sock, const void *buf, size_t buf_len, + __wasi_siflags_t si_flags, + const __wasi_addr_t *dest_addr, size_t *sent_len) { char addr_buf[48] = { 0 }; struct fd_object *fo; @@ -3449,11 +3291,7 @@ wasmtime_ssp_sock_send_to( } __wasi_errno_t -wasmtime_ssp_sock_shutdown( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock) +wasmtime_ssp_sock_shutdown(struct fd_table *curfds, __wasi_fd_t sock) { struct fd_object *fo; __wasi_errno_t error; @@ -3480,11 +3318,8 @@ wasmtime_ssp_sched_yield(void) } __wasi_errno_t -wasmtime_ssp_args_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, -#endif - char **argv, char *argv_buf) +wasmtime_ssp_args_get(struct argv_environ_values *argv_environ, char **argv, + char *argv_buf) { for (size_t i = 0; i < argv_environ->argc; ++i) { argv[i] = @@ -3497,11 +3332,8 @@ wasmtime_ssp_args_get( } __wasi_errno_t -wasmtime_ssp_args_sizes_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, -#endif - size_t *argc, size_t *argv_buf_size) +wasmtime_ssp_args_sizes_get(struct argv_environ_values *argv_environ, + size_t *argc, size_t *argv_buf_size) { *argc = argv_environ->argc; *argv_buf_size = argv_environ->argv_buf_size; @@ -3509,11 +3341,8 @@ wasmtime_ssp_args_sizes_get( } __wasi_errno_t -wasmtime_ssp_environ_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, -#endif - char **environ, char *environ_buf) +wasmtime_ssp_environ_get(struct argv_environ_values *argv_environ, + char **environ, char *environ_buf) { for (size_t i = 0; i < argv_environ->environ_count; ++i) { environ[i] = @@ -3528,11 +3357,8 @@ wasmtime_ssp_environ_get( } __wasi_errno_t -wasmtime_ssp_environ_sizes_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, -#endif - size_t *environ_count, size_t *environ_buf_size) +wasmtime_ssp_environ_sizes_get(struct argv_environ_values *argv_environ, + size_t *environ_count, size_t *environ_buf_size) { *environ_count = argv_environ->environ_count; *environ_buf_size = argv_environ->environ_buf_size; @@ -3757,11 +3583,7 @@ addr_pool_destroy(struct addr_pool *addr_pool) } } -#ifndef WASMTIME_SSP_STATIC_CURFDS #define WASMTIME_SSP_PASSTHROUGH_FD_TABLE struct fd_table *curfds, -#else -#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE -#endif // Defines a function that passes through the socket option to the OS // implementation @@ -3820,11 +3642,8 @@ WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ipv6_only, bool *) #undef WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION __wasi_errno_t -wasmtime_ssp_sock_set_linger( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, bool is_enabled, int linger_s) +wasmtime_ssp_sock_set_linger(struct fd_table *curfds, __wasi_fd_t sock, + bool is_enabled, int linger_s) { struct fd_object *fo; __wasi_errno_t error; @@ -3841,11 +3660,8 @@ wasmtime_ssp_sock_set_linger( } __wasi_errno_t -wasmtime_ssp_sock_get_linger( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, bool *is_enabled, int *linger_s) +wasmtime_ssp_sock_get_linger(struct fd_table *curfds, __wasi_fd_t sock, + bool *is_enabled, int *linger_s) { struct fd_object *fo; __wasi_errno_t error; @@ -3863,11 +3679,10 @@ wasmtime_ssp_sock_get_linger( } __wasi_errno_t -wasmtime_ssp_sock_set_ip_add_membership( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface) +wasmtime_ssp_sock_set_ip_add_membership(struct fd_table *curfds, + __wasi_fd_t sock, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) { struct fd_object *fo; __wasi_errno_t error; @@ -3889,11 +3704,10 @@ wasmtime_ssp_sock_set_ip_add_membership( } __wasi_errno_t -wasmtime_ssp_sock_set_ip_drop_membership( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface) +wasmtime_ssp_sock_set_ip_drop_membership(struct fd_table *curfds, + __wasi_fd_t sock, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) { struct fd_object *fo; __wasi_errno_t error; @@ -3915,11 +3729,9 @@ wasmtime_ssp_sock_set_ip_drop_membership( } __wasi_errno_t -wasmtime_ssp_sock_set_ip_multicast_loop( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, bool ipv6, bool is_enabled) +wasmtime_ssp_sock_set_ip_multicast_loop(struct fd_table *curfds, + __wasi_fd_t sock, bool ipv6, + bool is_enabled) { struct fd_object *fo; __wasi_errno_t error; @@ -3936,11 +3748,9 @@ wasmtime_ssp_sock_set_ip_multicast_loop( } __wasi_errno_t -wasmtime_ssp_sock_get_ip_multicast_loop( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, bool ipv6, bool *is_enabled) +wasmtime_ssp_sock_get_ip_multicast_loop(struct fd_table *curfds, + __wasi_fd_t sock, bool ipv6, + bool *is_enabled) { struct fd_object *fo; __wasi_errno_t error; From af2f3c8759b549db67858a9537b98ad15a148594 Mon Sep 17 00:00:00 2001 From: Cengizhan Pasaoglu Date: Thu, 7 Sep 2023 09:29:52 +0300 Subject: [PATCH 095/123] Fix typo for IP address buffer (#2532) --- .../sandboxed-system-primitives/src/posix.c | 48 +++++++++---------- .../platform/common/posix/posix_socket.c | 16 +++---- core/shared/platform/esp-idf/espidf_socket.c | 2 +- .../platform/include/platform_api_extension.h | 2 +- core/shared/platform/linux-sgx/sgx_socket.c | 4 +- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 9fabd8830..2af2f2d02 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -221,22 +221,22 @@ wasi_addr_to_bh_sockaddr(const __wasi_addr_t *wasi_addr, bh_sockaddr_t *sockaddr) { if (wasi_addr->kind == IPv4) { - sockaddr->addr_bufer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24) - | (wasi_addr->addr.ip4.addr.n1 << 16) - | (wasi_addr->addr.ip4.addr.n2 << 8) - | wasi_addr->addr.ip4.addr.n3; + sockaddr->addr_buffer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24) + | (wasi_addr->addr.ip4.addr.n1 << 16) + | (wasi_addr->addr.ip4.addr.n2 << 8) + | wasi_addr->addr.ip4.addr.n3; sockaddr->is_ipv4 = true; sockaddr->port = wasi_addr->addr.ip4.port; } else { - sockaddr->addr_bufer.ipv6[0] = wasi_addr->addr.ip6.addr.n0; - sockaddr->addr_bufer.ipv6[1] = wasi_addr->addr.ip6.addr.n1; - sockaddr->addr_bufer.ipv6[2] = wasi_addr->addr.ip6.addr.n2; - sockaddr->addr_bufer.ipv6[3] = wasi_addr->addr.ip6.addr.n3; - sockaddr->addr_bufer.ipv6[4] = wasi_addr->addr.ip6.addr.h0; - sockaddr->addr_bufer.ipv6[5] = wasi_addr->addr.ip6.addr.h1; - sockaddr->addr_bufer.ipv6[6] = wasi_addr->addr.ip6.addr.h2; - sockaddr->addr_bufer.ipv6[7] = wasi_addr->addr.ip6.addr.h3; + sockaddr->addr_buffer.ipv6[0] = wasi_addr->addr.ip6.addr.n0; + sockaddr->addr_buffer.ipv6[1] = wasi_addr->addr.ip6.addr.n1; + sockaddr->addr_buffer.ipv6[2] = wasi_addr->addr.ip6.addr.n2; + sockaddr->addr_buffer.ipv6[3] = wasi_addr->addr.ip6.addr.n3; + sockaddr->addr_buffer.ipv6[4] = wasi_addr->addr.ip6.addr.h0; + sockaddr->addr_buffer.ipv6[5] = wasi_addr->addr.ip6.addr.h1; + sockaddr->addr_buffer.ipv6[6] = wasi_addr->addr.ip6.addr.h2; + sockaddr->addr_buffer.ipv6[7] = wasi_addr->addr.ip6.addr.h3; sockaddr->is_ipv4 = false; sockaddr->port = wasi_addr->addr.ip6.port; } @@ -251,24 +251,24 @@ bh_sockaddr_to_wasi_addr(const bh_sockaddr_t *sockaddr, wasi_addr->kind = IPv4; wasi_addr->addr.ip4.port = sockaddr->port; wasi_addr->addr.ip4.addr.n0 = - (sockaddr->addr_bufer.ipv4 & 0xFF000000) >> 24; + (sockaddr->addr_buffer.ipv4 & 0xFF000000) >> 24; wasi_addr->addr.ip4.addr.n1 = - (sockaddr->addr_bufer.ipv4 & 0x00FF0000) >> 16; + (sockaddr->addr_buffer.ipv4 & 0x00FF0000) >> 16; wasi_addr->addr.ip4.addr.n2 = - (sockaddr->addr_bufer.ipv4 & 0x0000FF00) >> 8; - wasi_addr->addr.ip4.addr.n3 = (sockaddr->addr_bufer.ipv4 & 0x000000FF); + (sockaddr->addr_buffer.ipv4 & 0x0000FF00) >> 8; + wasi_addr->addr.ip4.addr.n3 = (sockaddr->addr_buffer.ipv4 & 0x000000FF); } else { wasi_addr->kind = IPv6; wasi_addr->addr.ip6.port = sockaddr->port; - wasi_addr->addr.ip6.addr.n0 = sockaddr->addr_bufer.ipv6[0]; - wasi_addr->addr.ip6.addr.n1 = sockaddr->addr_bufer.ipv6[1]; - wasi_addr->addr.ip6.addr.n2 = sockaddr->addr_bufer.ipv6[2]; - wasi_addr->addr.ip6.addr.n3 = sockaddr->addr_bufer.ipv6[3]; - wasi_addr->addr.ip6.addr.h0 = sockaddr->addr_bufer.ipv6[4]; - wasi_addr->addr.ip6.addr.h1 = sockaddr->addr_bufer.ipv6[5]; - wasi_addr->addr.ip6.addr.h2 = sockaddr->addr_bufer.ipv6[6]; - wasi_addr->addr.ip6.addr.h3 = sockaddr->addr_bufer.ipv6[7]; + wasi_addr->addr.ip6.addr.n0 = sockaddr->addr_buffer.ipv6[0]; + wasi_addr->addr.ip6.addr.n1 = sockaddr->addr_buffer.ipv6[1]; + wasi_addr->addr.ip6.addr.n2 = sockaddr->addr_buffer.ipv6[2]; + wasi_addr->addr.ip6.addr.n3 = sockaddr->addr_buffer.ipv6[3]; + wasi_addr->addr.ip6.addr.h0 = sockaddr->addr_buffer.ipv6[4]; + wasi_addr->addr.ip6.addr.h1 = sockaddr->addr_buffer.ipv6[5]; + wasi_addr->addr.ip6.addr.h2 = sockaddr->addr_buffer.ipv6[6]; + wasi_addr->addr.ip6.addr.h3 = sockaddr->addr_buffer.ipv6[7]; } } diff --git a/core/shared/platform/common/posix/posix_socket.c b/core/shared/platform/common/posix/posix_socket.c index d0a232bc5..9f5538b5c 100644 --- a/core/shared/platform/common/posix/posix_socket.c +++ b/core/shared/platform/common/posix/posix_socket.c @@ -53,7 +53,7 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr; bh_sockaddr->port = ntohs(addr->sin_port); - bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr); + bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr); bh_sockaddr->is_ipv4 = true; return BHT_OK; } @@ -65,12 +65,12 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, bh_sockaddr->port = ntohs(addr->sin6_port); - for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6) - / sizeof(bh_sockaddr->addr_bufer.ipv6[0]); + for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6) + / sizeof(bh_sockaddr->addr_buffer.ipv6[0]); i++) { uint16 part_addr = addr->sin6_addr.s6_addr[i * 2] | (addr->sin6_addr.s6_addr[i * 2 + 1] << 8); - bh_sockaddr->addr_bufer.ipv6[i] = ntohs(part_addr); + bh_sockaddr->addr_buffer.ipv6[i] = ntohs(part_addr); } bh_sockaddr->is_ipv4 = false; @@ -91,7 +91,7 @@ bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr, struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr; addr->sin_port = htons(bh_sockaddr->port); addr->sin_family = AF_INET; - addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4); + addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_buffer.ipv4); *socklen = sizeof(*addr); } #ifdef IPPROTO_IPV6 @@ -101,10 +101,10 @@ bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr, addr->sin6_port = htons(bh_sockaddr->port); addr->sin6_family = AF_INET6; - for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6) - / sizeof(bh_sockaddr->addr_bufer.ipv6[0]); + for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6) + / sizeof(bh_sockaddr->addr_buffer.ipv6[0]); i++) { - uint16 part_addr = htons(bh_sockaddr->addr_bufer.ipv6[i]); + uint16 part_addr = htons(bh_sockaddr->addr_buffer.ipv6[i]); addr->sin6_addr.s6_addr[i * 2] = 0xff & part_addr; addr->sin6_addr.s6_addr[i * 2 + 1] = (0xff00 & part_addr) >> 8; } diff --git a/core/shared/platform/esp-idf/espidf_socket.c b/core/shared/platform/esp-idf/espidf_socket.c index 9f441b712..83a24f435 100644 --- a/core/shared/platform/esp-idf/espidf_socket.c +++ b/core/shared/platform/esp-idf/espidf_socket.c @@ -30,7 +30,7 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen, assert(socklen >= sizeof(struct sockaddr_in)); bh_sockaddr->port = ntohs(addr->sin_port); - bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr); + bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr); bh_sockaddr->is_ipv4 = true; return BHT_OK; } diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 7029bb8d7..5b7b556e0 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -342,7 +342,7 @@ typedef union { } bh_ip_addr_buffer_t; typedef struct { - bh_ip_addr_buffer_t addr_bufer; + bh_ip_addr_buffer_t addr_buffer; uint16 port; bool is_ipv4; } bh_sockaddr_t; diff --git a/core/shared/platform/linux-sgx/sgx_socket.c b/core/shared/platform/linux-sgx/sgx_socket.c index afb6d6014..4d3f9a6b5 100644 --- a/core/shared/platform/linux-sgx/sgx_socket.c +++ b/core/shared/platform/linux-sgx/sgx_socket.c @@ -261,7 +261,7 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen, assert(socklen >= sizeof(struct sockaddr_in)); bh_sockaddr->port = ntohs(addr->sin_port); - bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr); + bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr); bh_sockaddr->is_ipv4 = true; return BHT_OK; } @@ -279,7 +279,7 @@ bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr, struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr; addr->sin_port = htons(bh_sockaddr->port); addr->sin_family = AF_INET; - addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4); + addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_buffer.ipv4); *socklen = sizeof(*addr); return BHT_OK; } From 6c846acc59b281b23e4cf81322e9bd39c48c9779 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 7 Sep 2023 15:54:11 +0900 Subject: [PATCH 096/123] Implement module instance context APIs (#2436) Introduce module instance context APIs which can set one or more contexts created by the embedder for a wasm module instance: ```C wasm_runtime_create_context_key wasm_runtime_destroy_context_key wasm_runtime_set_context wasm_runtime_set_context_spread wasm_runtime_get_context ``` And make libc-wasi use it and set wasi context as the first context bound to the wasm module instance. Also add samples. Refer to https://github.com/bytecodealliance/wasm-micro-runtime/issues/2460. --- build-scripts/config_common.cmake | 4 + build-scripts/runtime_lib.cmake | 2 + core/config.h | 5 + core/iwasm/aot/aot_runtime.c | 4 +- core/iwasm/common/wasm_native.c | 172 ++++++++++++++++++ core/iwasm/common/wasm_native.h | 30 +++ core/iwasm/common/wasm_runtime_common.c | 55 +++--- core/iwasm/common/wasm_runtime_common.h | 20 ++ core/iwasm/include/wasm_export.h | 68 +++++++ core/iwasm/interpreter/wasm_runtime.c | 4 +- core/iwasm/interpreter/wasm_runtime.h | 9 +- .../lib-pthread/lib_pthread_wrapper.c | 9 +- .../lib_wasi_threads_wrapper.c | 9 +- .../libraries/thread-mgr/thread_manager.c | 50 ++++- .../libraries/thread-mgr/thread_manager.h | 4 + product-mini/platforms/nuttx/wamr.mk | 8 + samples/inst-context-threads/.gitignore | 1 + samples/inst-context-threads/CMakeLists.txt | 92 ++++++++++ samples/inst-context-threads/README.md | 4 + samples/inst-context-threads/build.sh | 61 +++++++ samples/inst-context-threads/run.sh | 3 + samples/inst-context-threads/src/main.c | 151 +++++++++++++++ samples/inst-context-threads/src/my_context.h | 11 ++ .../inst-context-threads/src/native_impl.c | 32 ++++ .../inst-context-threads/wasm-apps/testapp.c | 65 +++++++ samples/inst-context/.gitignore | 1 + samples/inst-context/CMakeLists.txt | 91 +++++++++ samples/inst-context/README.md | 4 + samples/inst-context/build.sh | 63 +++++++ samples/inst-context/run.sh | 3 + samples/inst-context/src/main.c | 166 +++++++++++++++++ samples/inst-context/src/my_context.h | 10 + samples/inst-context/src/native_impl.c | 15 ++ samples/inst-context/wasm-apps/testapp.c | 19 ++ wamr-compiler/CMakeLists.txt | 1 + 35 files changed, 1190 insertions(+), 56 deletions(-) create mode 100644 samples/inst-context-threads/.gitignore create mode 100644 samples/inst-context-threads/CMakeLists.txt create mode 100644 samples/inst-context-threads/README.md create mode 100755 samples/inst-context-threads/build.sh create mode 100755 samples/inst-context-threads/run.sh create mode 100644 samples/inst-context-threads/src/main.c create mode 100644 samples/inst-context-threads/src/my_context.h create mode 100644 samples/inst-context-threads/src/native_impl.c create mode 100644 samples/inst-context-threads/wasm-apps/testapp.c create mode 100644 samples/inst-context/.gitignore create mode 100644 samples/inst-context/CMakeLists.txt create mode 100644 samples/inst-context/README.md create mode 100755 samples/inst-context/build.sh create mode 100755 samples/inst-context/run.sh create mode 100644 samples/inst-context/src/main.c create mode 100644 samples/inst-context/src/my_context.h create mode 100644 samples/inst-context/src/native_impl.c create mode 100644 samples/inst-context/wasm-apps/testapp.c diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 2751341e4..0e27e0c09 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -378,6 +378,10 @@ if (WAMR_BUILD_WASM_CACHE EQUAL 1) add_definitions (-DWASM_ENABLE_WASM_CACHE=1) message (" Wasm files cache enabled") endif () +if (WAMR_BUILD_MODULE_INST_CONTEXT EQUAL 1) + add_definitions (-DWASM_ENABLE_MODULE_INST_CONTEXT=1) + message (" Module instance context enabled") +endif () if (WAMR_BUILD_GC_HEAP_VERIFY EQUAL 1) add_definitions (-DWASM_ENABLE_GC_VERIFY=1) message (" GC heap verification enabled") diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index 4c1fb064d..8ac519b77 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -91,8 +91,10 @@ endif () if (WAMR_BUILD_LIBC_UVWASI EQUAL 1) include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake) + set (WAMR_BUILD_MODULE_INST_CONTEXT 1) elseif (WAMR_BUILD_LIBC_WASI EQUAL 1) include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake) + set (WAMR_BUILD_MODULE_INST_CONTEXT 1) endif () if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1) diff --git a/core/config.h b/core/config.h index 220f6751a..4bbb10234 100644 --- a/core/config.h +++ b/core/config.h @@ -480,4 +480,9 @@ #define WASM_MEM_DUAL_BUS_MIRROR 0 #endif +/* The max number of module instance contexts. */ +#ifndef WASM_MAX_INSTANCE_CONTEXTS +#define WASM_MAX_INSTANCE_CONTEXTS 8 +#endif + #endif /* end of _CONFIG_H_ */ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 55c399a8b..55cf2d985 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1276,12 +1276,10 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) ->common.c_api_func_imports); if (!is_sub_inst) { -#if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); -#endif #if WASM_ENABLE_WASI_NN != 0 wasi_nn_destroy(module_inst); #endif + wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst); } wasm_runtime_free(module_inst); diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 1acaed6ee..0a5851349 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -6,6 +6,15 @@ #include "wasm_native.h" #include "wasm_runtime_common.h" #include "bh_log.h" +#if WASM_ENABLE_INTERP != 0 +#include "../interpreter/wasm_runtime.h" +#endif +#if WASM_ENABLE_AOT != 0 +#include "../aot/aot_runtime.h" +#endif +#if WASM_ENABLE_THREAD_MGR != 0 +#include "../libraries/thread-mgr/thread_manager.h" +#endif #if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \ && !defined(BH_PLATFORM_OPENRTOS) && !defined(BH_PLATFORM_ESP_IDF) @@ -22,6 +31,10 @@ static NativeSymbolsList g_native_symbols_list = NULL; +#if WASM_ENABLE_LIBC_WASI != 0 +static void *g_wasi_context_key; +#endif /* WASM_ENABLE_LIBC_WASI */ + uint32 get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis); @@ -394,6 +407,155 @@ wasm_native_unregister_natives(const char *module_name, return false; } +#if WASM_ENABLE_MODULE_INST_CONTEXT != 0 +static uint32 +context_key_to_idx(void *key) +{ + bh_assert(key != NULL); + uint32 idx = (uint32)(uintptr_t)key; + bh_assert(idx > 0); + bh_assert(idx <= WASM_MAX_INSTANCE_CONTEXTS); + return idx - 1; +} + +static void * +context_idx_to_key(uint32 idx) +{ + bh_assert(idx < WASM_MAX_INSTANCE_CONTEXTS); + return (void *)(uintptr_t)(idx + 1); +} + +typedef void (*dtor_t)(WASMModuleInstanceCommon *, void *); +static dtor_t g_context_dtors[WASM_MAX_INSTANCE_CONTEXTS]; + +static void +dtor_noop(WASMModuleInstanceCommon *inst, void *ctx) +{} + +void * +wasm_native_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst, + void *ctx)) +{ + uint32 i; + for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) { + if (g_context_dtors[i] == NULL) { + if (dtor == NULL) { + dtor = dtor_noop; + } + g_context_dtors[i] = dtor; + return context_idx_to_key(i); + } + } + LOG_ERROR("failed to allocate instance context key"); + return NULL; +} + +void +wasm_native_destroy_context_key(void *key) +{ + uint32 idx = context_key_to_idx(key); + bh_assert(g_context_dtors[idx] != NULL); + g_context_dtors[idx] = NULL; +} + +static WASMModuleInstanceExtraCommon * +wasm_module_inst_extra_common(WASMModuleInstanceCommon *inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (inst->module_type == Wasm_Module_Bytecode) { + return &((WASMModuleInstance *)inst)->e->common; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (inst->module_type == Wasm_Module_AoT) { + return &((AOTModuleInstanceExtra *)((AOTModuleInstance *)inst)->e) + ->common; + } +#endif + bh_assert(false); + return NULL; +} + +void +wasm_native_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx) +{ + uint32 idx = context_key_to_idx(key); + WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst); + common->contexts[idx] = ctx; +} + +void +wasm_native_set_context_spread(WASMModuleInstanceCommon *inst, void *key, + void *ctx) +{ +#if WASM_ENABLE_THREAD_MGR != 0 + wasm_cluster_set_context(inst, key, ctx); +#else + wasm_native_set_context(inst, key, ctx); +#endif +} + +void * +wasm_native_get_context(WASMModuleInstanceCommon *inst, void *key) +{ + uint32 idx = context_key_to_idx(key); + WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst); + return common->contexts[idx]; +} + +void +wasm_native_call_context_dtors(WASMModuleInstanceCommon *inst) +{ + WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst); + uint32 i; + for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) { + dtor_t dtor = g_context_dtors[i]; + if (dtor != NULL) { + dtor(inst, common->contexts[i]); + } + } +} + +void +wasm_native_inherit_contexts(WASMModuleInstanceCommon *child, + WASMModuleInstanceCommon *parent) +{ + WASMModuleInstanceExtraCommon *parent_common = + wasm_module_inst_extra_common(parent); + WASMModuleInstanceExtraCommon *child_common = + wasm_module_inst_extra_common(child); + bh_memcpy_s(child_common->contexts, + sizeof(*child_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS, + parent_common->contexts, + sizeof(*parent_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS); +} +#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */ + +#if WASM_ENABLE_LIBC_WASI != 0 +WASIContext * +wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm) +{ + return wasm_native_get_context(module_inst_comm, g_wasi_context_key); +} + +void +wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm, + WASIContext *wasi_ctx) +{ + return wasm_native_set_context(module_inst_comm, g_wasi_context_key, + wasi_ctx); +} + +static void +wasi_context_dtor(WASMModuleInstanceCommon *inst, void *ctx) +{ + if (ctx == NULL) { + return; + } + wasm_runtime_destroy_wasi(inst); +} +#endif /* end of WASM_ENABLE_LIBC_WASI */ + bool wasm_native_init() { @@ -420,6 +582,10 @@ wasm_native_init() #endif /* WASM_ENABLE_SPEC_TEST */ #if WASM_ENABLE_LIBC_WASI != 0 + g_wasi_context_key = wasm_native_create_context_key(wasi_context_dtor); + if (g_wasi_context_key == NULL) { + goto fail; + } n_native_symbols = get_libc_wasi_export_apis(&native_symbols); if (!wasm_native_register_natives("wasi_unstable", native_symbols, n_native_symbols)) @@ -507,6 +673,12 @@ wasm_native_destroy() { NativeSymbolsNode *node, *node_next; +#if WASM_ENABLE_LIBC_WASI != 0 + if (g_wasi_context_key != NULL) { + wasm_native_destroy_context_key(g_wasi_context_key); + g_wasi_context_key = NULL; + } +#endif #if WASM_ENABLE_LIB_PTHREAD != 0 lib_pthread_destroy(); #endif diff --git a/core/iwasm/common/wasm_native.h b/core/iwasm/common/wasm_native.h index 4f6645d25..9ca5265c3 100644 --- a/core/iwasm/common/wasm_native.h +++ b/core/iwasm/common/wasm_native.h @@ -68,6 +68,36 @@ bool wasm_native_unregister_natives(const char *module_name, NativeSymbol *native_symbols); +#if WASM_ENABLE_MODULE_INST_CONTEXT != 0 +struct WASMModuleInstanceCommon; + +void * +wasm_native_create_context_key( + void (*dtor)(struct WASMModuleInstanceCommon *inst, void *ctx)); + +void +wasm_native_destroy_context_key(void *key); + +void +wasm_native_set_context(struct WASMModuleInstanceCommon *inst, void *key, + void *ctx); +void +wasm_native_set_context_spread(struct WASMModuleInstanceCommon *inst, void *key, + void *ctx); +void * +wasm_native_get_context(struct WASMModuleInstanceCommon *inst, void *key); + +void +wasm_native_call_context_dtors(struct WASMModuleInstanceCommon *inst); + +void +wasm_native_inherit_contexts(struct WASMModuleInstanceCommon *child, + struct WASMModuleInstanceCommon *parent); +#else /* WASM_ENABLE_MODULE_INST_CONTEXT */ +#define wasm_native_call_context_dtors(inst) (void)(inst) +#define wasm_native_inherit_contexts(child, parent) (void)(parent) +#endif /* WASM_ENABLE_MODULE_INST_CONTEXT */ + bool wasm_native_init(); diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index ac85c61dc..cb7dbee9d 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -3311,27 +3311,6 @@ wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst) #endif return wasi_ctx->exit_code; } - -WASIContext * -wasm_runtime_get_wasi_ctx(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); - return module_inst->wasi_ctx; -} - -void -wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm, - WASIContext *wasi_ctx) -{ - 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); - module_inst->wasi_ctx = wasi_ctx; -} #endif /* end of WASM_ENABLE_LIBC_WASI */ WASMModuleCommon * @@ -5681,3 +5660,37 @@ wasm_runtime_is_import_global_linked(const char *module_name, return false; #endif } + +#if WASM_ENABLE_MODULE_INST_CONTEXT != 0 +void * +wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst, + void *ctx)) +{ + return wasm_native_create_context_key(dtor); +} + +void +wasm_runtime_destroy_context_key(void *key) +{ + wasm_native_destroy_context_key(key); +} + +void +wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx) +{ + wasm_native_set_context(inst, key, ctx); +} + +void +wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key, + void *ctx) +{ + wasm_native_set_context_spread(inst, key, ctx); +} + +void * +wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key) +{ + return wasm_native_get_context(inst, key); +} +#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */ diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index f631defb1..b9b0d0bf6 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -939,6 +939,26 @@ WASM_RUNTIME_API_EXTERN bool wasm_runtime_unregister_natives(const char *module_name, NativeSymbol *native_symbols); +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN void * +wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst, + void *ctx)); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN void +wasm_runtime_destroy_context_key(void *key); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN void +wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx); +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN void +wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key, + void *ctx); +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN void * +wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key); + bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 79edc68ed..589d8af00 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1456,6 +1456,74 @@ WASM_RUNTIME_API_EXTERN void wasm_runtime_set_enlarge_mem_error_callback( const enlarge_memory_error_callback_t callback); +/* + * module instance context APIs + * wasm_runtime_create_context_key + * wasm_runtime_destroy_context_key + * wasm_runtime_set_context + * wasm_runtime_set_context_spread + * wasm_runtime_get_context + * + * This set of APIs is intended to be used by an embedder which provides + * extra sets of native functions, which need per module instance state + * and are maintained outside of the WAMR tree. + * + * It's modelled after the pthread specific API. + * + * wasm_runtime_set_context_spread is similar to + * wasm_runtime_set_context, except that + * wasm_runtime_set_context_spread applies the change + * to all threads in the cluster. + * It's an undefined behavior if multiple threads in a cluster call + * wasm_runtime_set_context_spread on the same key + * simultaneously. It's a caller's resposibility to perform necessary + * serialization if necessary. For example: + * + * if (wasm_runtime_get_context(inst, key) == NULL) { + * newctx = alloc_and_init(...); + * lock(some_lock); + * if (wasm_runtime_get_context(inst, key) == NULL) { + * // this thread won the race + * wasm_runtime_set_context_spread(inst, key, newctx); + * newctx = NULL; + * } + * unlock(some_lock); + * if (newctx != NULL) { + * // this thread lost the race, free it + * cleanup_and_free(newctx); + * } + * } + * + * Note: dynamic key create/destroy while instances are live is not + * implemented as of writing this. + * it's caller's resposibility to ensure destorying all module instances + * before calling wasm_runtime_create_context_key or + * wasm_runtime_destroy_context_key. + * otherwise, it's an undefined behavior. + * + * Note about threads: + * - When spawning a thread, the contexts (the pointers given to + * wasm_runtime_set_context) are copied from the parent + * instance. + * - The destructor is called only on the main instance. + */ + +WASM_RUNTIME_API_EXTERN void * +wasm_runtime_create_context_key( + void (*dtor)(wasm_module_inst_t inst, void *ctx)); + +WASM_RUNTIME_API_EXTERN void +wasm_runtime_destroy_context_key(void *key); + +WASM_RUNTIME_API_EXTERN void +wasm_runtime_set_context(wasm_module_inst_t inst, void *key, + void *ctx); +WASM_RUNTIME_API_EXTERN void +wasm_runtime_set_context_spread(wasm_module_inst_t inst, void *key, + void *ctx); +WASM_RUNTIME_API_EXTERN void * +wasm_runtime_get_context(wasm_module_inst_t inst, void *key); + /* clang-format on */ #ifdef __cplusplus diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index f395b1eaa..301038a4d 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2233,12 +2233,10 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) wasm_runtime_free(module_inst->e->common.c_api_func_imports); if (!is_sub_inst) { -#if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); -#endif #if WASM_ENABLE_WASI_NN != 0 wasi_nn_destroy(module_inst); #endif + wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst); } wasm_runtime_free(module_inst); diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index aa33dc18c..605cefc6c 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -212,6 +212,7 @@ typedef struct CApiFuncImport { /* The common part of WASMModuleInstanceExtra and AOTModuleInstanceExtra */ typedef struct WASMModuleInstanceExtraCommon { + void *contexts[WASM_MAX_INSTANCE_CONTEXTS]; CApiFuncImport *c_api_func_imports; /* pointer to the exec env currently used */ WASMExecEnv *cur_exec_env; @@ -299,12 +300,8 @@ struct WASMModuleInstance { it denotes `AOTModule *` */ DefPointer(WASMModule *, module); -#if WASM_ENABLE_LIBC_WASI - /* WASI context */ - DefPointer(WASIContext *, wasi_ctx); -#else - DefPointer(void *, wasi_ctx); -#endif + DefPointer(void *, used_to_be_wasi_ctx); /* unused */ + DefPointer(WASMExecEnv *, exec_env_singleton); /* Array of function pointers to import functions, not available in AOTModuleInstance */ diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index b8a641165..56deaff32 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -559,9 +559,6 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, uint32 thread_handle; uint32 stack_size = 8192; int32 ret = -1; -#if WASM_ENABLE_LIBC_WASI != 0 - WASIContext *wasi_ctx; -#endif bh_assert(module); bh_assert(module_inst); @@ -588,11 +585,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, wasm_runtime_set_custom_data_internal( new_module_inst, wasm_runtime_get_custom_data(module_inst)); -#if WASM_ENABLE_LIBC_WASI != 0 - wasi_ctx = get_wasi_ctx(module_inst); - if (wasi_ctx) - wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx); -#endif + wasm_native_inherit_contexts(new_module_inst, module_inst); if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst))) goto fail; diff --git a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c index a5f72986a..7e557be90 100644 --- a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c +++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c @@ -80,9 +80,6 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) int32 thread_id; uint32 stack_size = 8192; int32 ret = -1; -#if WASM_ENABLE_LIBC_WASI != 0 - WASIContext *wasi_ctx; -#endif bh_assert(module); bh_assert(module_inst); @@ -99,11 +96,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst))) goto thread_preparation_fail; -#if WASM_ENABLE_LIBC_WASI != 0 - wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst); - if (wasi_ctx) - wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx); -#endif + wasm_native_inherit_contexts(new_module_inst, module_inst); start_func = wasm_runtime_lookup_function(new_module_inst, THREAD_START_FUNCTION, NULL); diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 9a1e82d31..95f0d4267 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -480,9 +480,6 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) wasm_module_inst_t module_inst = get_module_inst(exec_env); wasm_module_t module; wasm_module_inst_t new_module_inst; -#if WASM_ENABLE_LIBC_WASI != 0 - WASIContext *wasi_ctx; -#endif WASMExecEnv *new_exec_env; uint32 aux_stack_start, aux_stack_size; uint32 stack_size = 8192; @@ -520,10 +517,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) wasm_runtime_set_custom_data_internal( new_module_inst, wasm_runtime_get_custom_data(module_inst)); -#if WASM_ENABLE_LIBC_WASI != 0 - wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst); - wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx); -#endif + wasm_native_inherit_contexts(new_module_inst, module_inst); new_exec_env = wasm_exec_env_create_internal(new_module_inst, exec_env->wasm_stack_size); @@ -1324,6 +1318,48 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst, } } +#if WASM_ENABLE_MODULE_INST_CONTEXT != 0 +struct inst_set_context_data { + void *key; + void *ctx; +}; + +static void +set_context_visitor(void *node, void *user_data) +{ + WASMExecEnv *curr_exec_env = (WASMExecEnv *)node; + WASMModuleInstanceCommon *module_inst = get_module_inst(curr_exec_env); + const struct inst_set_context_data *data = user_data; + + wasm_runtime_set_context(module_inst, data->key, data->ctx); +} + +void +wasm_cluster_set_context(WASMModuleInstanceCommon *module_inst, void *key, + void *ctx) +{ + WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst); + + if (exec_env == NULL) { + /* Maybe threads have not been started yet. */ + wasm_runtime_set_context(module_inst, key, ctx); + } + else { + WASMCluster *cluster; + struct inst_set_context_data data; + data.key = key; + data.ctx = ctx; + + cluster = wasm_exec_env_get_cluster(exec_env); + bh_assert(cluster); + + os_mutex_lock(&cluster->lock); + traverse_list(&cluster->exec_env_list, set_context_visitor, &data); + os_mutex_unlock(&cluster->lock); + } +} +#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */ + bool wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env) { diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index c6bc7a526..0280119fc 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -151,6 +151,10 @@ void wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst, void *custom_data); +void +wasm_cluster_set_context(WASMModuleInstanceCommon *module_inst, void *key, + void *ctx); + bool wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env); diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 2a0cec58c..e5af62cc8 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -253,10 +253,18 @@ CSRCS += posix.c CSRCS += random.c CSRCS += str.c VPATH += $(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src +# todo: use Kconfig select instead +CONFIG_INTERPRETERS_WAMR_MODULE_INSTANCE_CONTEXT = y else CFLAGS += -DWASM_ENABLE_LIBC_WASI=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_MODULE_INSTANCE_CONTEXT),y) +CFLAGS += -DWASM_ENABLE_MODULE_INST_CONTEXT=1 +else +CFLAGS += -DWASM_ENABLE_MODULE_INST_CONTEXT=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_MULTI_MODULE),y) CFLAGS += -DWASM_ENABLE_MULTI_MODULE=1 else diff --git a/samples/inst-context-threads/.gitignore b/samples/inst-context-threads/.gitignore new file mode 100644 index 000000000..0fa8a76bd --- /dev/null +++ b/samples/inst-context-threads/.gitignore @@ -0,0 +1 @@ +/out/ \ No newline at end of file diff --git a/samples/inst-context-threads/CMakeLists.txt b/samples/inst-context-threads/CMakeLists.txt new file mode 100644 index 000000000..7326a5436 --- /dev/null +++ b/samples/inst-context-threads/CMakeLists.txt @@ -0,0 +1,92 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +include(CheckPIESupported) + +if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") + project (inst-context) +else() + project (inst-context C ASM) + enable_language (ASM_MASM) +endif() + +################ runtime settings ################ +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +if (APPLE) + add_definitions(-DBH_PLATFORM_DARWIN) +endif () + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug) +endif () + +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_LIB_WASI_THREADS 1) + +if (NOT MSVC) + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +if (NOT MSVC) + # linker flags + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + endif () + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") + if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + endif () + endif () +endif () + +# build out vmlib +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +################ application related ################ +include_directories(${CMAKE_CURRENT_LIST_DIR}/src) +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (inst-context src/main.c src/native_impl.c ${UNCOMMON_SHARED_SOURCE}) + +check_pie_supported() +set_target_properties (inst-context PROPERTIES POSITION_INDEPENDENT_CODE ON) + +if (APPLE) + target_link_libraries (inst-context vmlib -lm -ldl -lpthread) +else () + target_link_libraries (inst-context vmlib -lm -ldl -lpthread -lrt) +endif () diff --git a/samples/inst-context-threads/README.md b/samples/inst-context-threads/README.md new file mode 100644 index 000000000..43b13c66b --- /dev/null +++ b/samples/inst-context-threads/README.md @@ -0,0 +1,4 @@ +The "inst-context" sample project +================================= + +This sample demonstrates module instance context API. diff --git a/samples/inst-context-threads/build.sh b/samples/inst-context-threads/build.sh new file mode 100755 index 000000000..35f76eccf --- /dev/null +++ b/samples/inst-context-threads/build.sh @@ -0,0 +1,61 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/bash + +CURR_DIR=$PWD +WAMR_DIR=${PWD}/../.. +OUT_DIR=${PWD}/out + +WASM_APPS=${PWD}/wasm-apps + + +rm -rf ${OUT_DIR} +mkdir ${OUT_DIR} +mkdir ${OUT_DIR}/wasm-apps + + +echo "#####################build inst-context project" +cd ${CURR_DIR} +mkdir -p cmake_build +cd cmake_build +cmake .. +make -j ${nproc} +if [ $? != 0 ];then + echo "BUILD_FAIL inst-context exit as $?\n" + exit 2 +fi + +cp -a inst-context ${OUT_DIR} + +echo -e "\n" + +echo "#####################build wasm apps" + +cd ${WASM_APPS} + +for i in `ls *.c` +do +APP_SRC="$i" +OUT_FILE=${i%.*}.wasm + +# use WAMR SDK to build out the .wasm binary +# require wasi-sdk with wasi-threads support. (wasi-sdk-20.0 or later) +/opt/wasi-sdk/bin/clang \ + --target=wasm32-wasi-threads \ + -pthread \ + -Wl,--import-memory \ + -Wl,--export-memory \ + -Wl,--max-memory=655360 \ + -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} + + +if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then + echo "build ${OUT_FILE} success" +else + echo "build ${OUT_FILE} fail" +fi +done +echo "####################build wasm apps done" diff --git a/samples/inst-context-threads/run.sh b/samples/inst-context-threads/run.sh new file mode 100755 index 000000000..919ed0166 --- /dev/null +++ b/samples/inst-context-threads/run.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +out/inst-context -f out/wasm-apps/testapp.wasm diff --git a/samples/inst-context-threads/src/main.c b/samples/inst-context-threads/src/main.c new file mode 100644 index 000000000..2a20363c5 --- /dev/null +++ b/samples/inst-context-threads/src/main.c @@ -0,0 +1,151 @@ + +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_export.h" +#include "bh_read_file.h" +#include "bh_getopt.h" +#include "my_context.h" + +void +set_context(wasm_exec_env_t exec_env, int32_t n); +int32_t +get_context(wasm_exec_env_t exec_env); + +void *my_context_key; +struct my_context my_context; +int my_dtor_called; + +wasm_module_inst_t module_inst = NULL; + +void +print_usage(void) +{ + fprintf(stdout, "Options:\r\n"); + fprintf(stdout, " -f [path of wasm file] \n"); +} + +void +my_context_dtor(wasm_module_inst_t inst, void *ctx) +{ + printf("%s called\n", __func__); + my_dtor_called++; + bh_assert(ctx == &my_context); + bh_assert(inst == module_inst); +} + +int +main(int argc, char *argv_main[]) +{ + static char global_heap_buf[512 * 1024]; + char *buffer; + char error_buf[128]; + int opt; + char *wasm_path = NULL; + int exit_code = 1; + + wasm_module_t module = NULL; + uint32 buf_size, stack_size = 8092, heap_size = 8092; + + RuntimeInitArgs init_args; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + while ((opt = getopt(argc, argv_main, "hf:")) != -1) { + switch (opt) { + case 'f': + wasm_path = optarg; + break; + case 'h': + print_usage(); + return 0; + case '?': + print_usage(); + return 0; + } + } + if (optind == 1) { + print_usage(); + return 0; + } + + // Define an array of NativeSymbol for the APIs to be exported. + // Note: the array must be static defined since runtime + // will keep it after registration + // For the function signature specifications, goto the link: + // https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md + + static NativeSymbol native_symbols[] = { + { "set_context", set_context, "(i)", NULL }, + { "get_context", get_context, "()i", NULL }, + }; + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + // Native symbols need below registration phase + init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + init_args.native_module_name = "env"; + init_args.native_symbols = native_symbols; + + if (!wasm_runtime_full_init(&init_args)) { + printf("Init runtime environment failed.\n"); + return -1; + } + + my_context_key = wasm_runtime_create_context_key(my_context_dtor); + if (!my_context_key) { + printf("wasm_runtime_create_context_key failed.\n"); + return -1; + } + + buffer = bh_read_file_to_buffer(wasm_path, &buf_size); + + if (!buffer) { + printf("Open wasm app file [%s] failed.\n", wasm_path); + goto fail; + } + + module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf, + sizeof(error_buf)); + if (!module) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + + module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)); + + if (!module_inst) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + + char *args[] = { + "testapp", + }; + wasm_application_execute_main(module_inst, 1, args); + const char *exc = wasm_runtime_get_exception(module_inst); + if (exc != NULL) { + printf("call wasm function calculate failed. error: %s\n", exc); + goto fail; + } + + exit_code = 0; +fail: + if (module_inst) { + bh_assert(my_dtor_called == 0); + wasm_runtime_deinstantiate(module_inst); + bh_assert(my_dtor_called == 1); + } + if (module) + wasm_runtime_unload(module); + if (buffer) + BH_FREE(buffer); + if (my_context_key) + wasm_runtime_destroy_context_key(my_context_key); + wasm_runtime_destroy(); + return exit_code; +} diff --git a/samples/inst-context-threads/src/my_context.h b/samples/inst-context-threads/src/my_context.h new file mode 100644 index 000000000..008be71ff --- /dev/null +++ b/samples/inst-context-threads/src/my_context.h @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +struct my_context { + int x; +}; + +extern void *my_context_key; +extern struct my_context my_context; diff --git a/samples/inst-context-threads/src/native_impl.c b/samples/inst-context-threads/src/native_impl.c new file mode 100644 index 000000000..0733e1976 --- /dev/null +++ b/samples/inst-context-threads/src/native_impl.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include + +#include "wasm_export.h" +#include "my_context.h" + +void +set_context(wasm_exec_env_t exec_env, int32_t n) +{ + wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env); + printf("%s called on module inst %p\n", __func__, inst); + struct my_context *ctx = &my_context; + ctx->x = n; + wasm_runtime_set_context_spread(inst, my_context_key, ctx); +} + +int32_t +get_context(wasm_exec_env_t exec_env) +{ + wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env); + printf("%s called on module inst %p\n", __func__, inst); + struct my_context *ctx = wasm_runtime_get_context(inst, my_context_key); + if (ctx == NULL) { + return -1; + } + return ctx->x; +} diff --git a/samples/inst-context-threads/wasm-apps/testapp.c b/samples/inst-context-threads/wasm-apps/testapp.c new file mode 100644 index 000000000..429b0875f --- /dev/null +++ b/samples/inst-context-threads/wasm-apps/testapp.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include + +void +set_context(int32_t n) __attribute__((import_module("env"))) +__attribute__((import_name("set_context"))); + +int32_t +get_context() __attribute__((import_module("env"))) +__attribute__((import_name("get_context"))); + +void * +start(void *vp) +{ + int32_t v; + + printf("thread started\n"); + + printf("confirming the initial state on thread\n"); + v = get_context(); + assert(v == -1); + + printf("setting the context on thread\n"); + set_context(1234); + + printf("confirming the context on thread\n"); + v = get_context(); + assert(v == 1234); + return NULL; +} + +int +main() +{ + pthread_t t1; + int32_t v; + int ret; + + printf("confirming the initial state on main\n"); + v = get_context(); + assert(v == -1); + + printf("creating a thread\n"); + ret = pthread_create(&t1, NULL, start, NULL); + assert(ret == 0); + void *val; + ret = pthread_join(t1, &val); + assert(ret == 0); + printf("joined the thread\n"); + + printf("confirming the context propagated from the thread on main\n"); + v = get_context(); + assert(v == 1234); + + printf("success\n"); + return 0; +} diff --git a/samples/inst-context/.gitignore b/samples/inst-context/.gitignore new file mode 100644 index 000000000..0fa8a76bd --- /dev/null +++ b/samples/inst-context/.gitignore @@ -0,0 +1 @@ +/out/ \ No newline at end of file diff --git a/samples/inst-context/CMakeLists.txt b/samples/inst-context/CMakeLists.txt new file mode 100644 index 000000000..b1167d277 --- /dev/null +++ b/samples/inst-context/CMakeLists.txt @@ -0,0 +1,91 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +include(CheckPIESupported) + +if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") + project (inst-context) +else() + project (inst-context C ASM) + enable_language (ASM_MASM) +endif() + +################ runtime settings ################ +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +if (APPLE) + add_definitions(-DBH_PLATFORM_DARWIN) +endif () + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug) +endif () + +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 1) + +if (NOT MSVC) + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +if (NOT MSVC) + # linker flags + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + endif () + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") + if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + endif () + endif () +endif () + +# build out vmlib +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +################ application related ################ +include_directories(${CMAKE_CURRENT_LIST_DIR}/src) +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (inst-context src/main.c src/native_impl.c ${UNCOMMON_SHARED_SOURCE}) + +check_pie_supported() +set_target_properties (inst-context PROPERTIES POSITION_INDEPENDENT_CODE ON) + +if (APPLE) + target_link_libraries (inst-context vmlib -lm -ldl -lpthread) +else () + target_link_libraries (inst-context vmlib -lm -ldl -lpthread -lrt) +endif () diff --git a/samples/inst-context/README.md b/samples/inst-context/README.md new file mode 100644 index 000000000..43b13c66b --- /dev/null +++ b/samples/inst-context/README.md @@ -0,0 +1,4 @@ +The "inst-context" sample project +================================= + +This sample demonstrates module instance context API. diff --git a/samples/inst-context/build.sh b/samples/inst-context/build.sh new file mode 100755 index 000000000..816e1cc08 --- /dev/null +++ b/samples/inst-context/build.sh @@ -0,0 +1,63 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/bash + +CURR_DIR=$PWD +WAMR_DIR=${PWD}/../.. +OUT_DIR=${PWD}/out + +WASM_APPS=${PWD}/wasm-apps + + +rm -rf ${OUT_DIR} +mkdir ${OUT_DIR} +mkdir ${OUT_DIR}/wasm-apps + + +echo "#####################build inst-context project" +cd ${CURR_DIR} +mkdir -p cmake_build +cd cmake_build +cmake .. +make -j ${nproc} +if [ $? != 0 ];then + echo "BUILD_FAIL inst-context exit as $?\n" + exit 2 +fi + +cp -a inst-context ${OUT_DIR} + +echo -e "\n" + +echo "#####################build wasm apps" + +cd ${WASM_APPS} + +for i in `ls *.c` +do +APP_SRC="$i" +OUT_FILE=${i%.*}.wasm + +# use WAMR SDK to build out the .wasm binary +/opt/wasi-sdk/bin/clang \ + --target=wasm32 -O0 -z stack-size=4096 -Wl,--initial-memory=65536 \ + --sysroot=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot \ + -Wl,--allow-undefined-file=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt \ + -Wl,--strip-all,--no-entry -nostdlib \ + -Wl,--export=generate_float \ + -Wl,--export=float_to_string \ + -Wl,--export=calculate\ + -Wl,--allow-undefined \ + -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} + + +if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then + echo "build ${OUT_FILE} success" +else + echo "build ${OUT_FILE} fail" +fi +done +echo "####################build wasm apps done" diff --git a/samples/inst-context/run.sh b/samples/inst-context/run.sh new file mode 100755 index 000000000..919ed0166 --- /dev/null +++ b/samples/inst-context/run.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +out/inst-context -f out/wasm-apps/testapp.wasm diff --git a/samples/inst-context/src/main.c b/samples/inst-context/src/main.c new file mode 100644 index 000000000..0d774735e --- /dev/null +++ b/samples/inst-context/src/main.c @@ -0,0 +1,166 @@ + +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_export.h" +#include "bh_read_file.h" +#include "bh_getopt.h" +#include "my_context.h" + +int32_t +add_native(int32_t n); +void *my_context_key; +struct my_context my_context; +int my_dtor_called; + +wasm_module_inst_t module_inst = NULL; + +void +print_usage(void) +{ + fprintf(stdout, "Options:\r\n"); + fprintf(stdout, " -f [path of wasm file] \n"); +} + +void +my_context_dtor(wasm_module_inst_t inst, void *ctx) +{ + printf("%s called\n", __func__); + my_dtor_called++; + bh_assert(ctx == &my_context); + bh_assert(inst == module_inst); +} + +int +main(int argc, char *argv_main[]) +{ + static char global_heap_buf[512 * 1024]; + char *buffer; + char error_buf[128]; + int opt; + char *wasm_path = NULL; + + wasm_module_t module = NULL; + wasm_exec_env_t exec_env = NULL; + uint32 buf_size, stack_size = 8092, heap_size = 8092; + + RuntimeInitArgs init_args; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + while ((opt = getopt(argc, argv_main, "hf:")) != -1) { + switch (opt) { + case 'f': + wasm_path = optarg; + break; + case 'h': + print_usage(); + return 0; + case '?': + print_usage(); + return 0; + } + } + if (optind == 1) { + print_usage(); + return 0; + } + + // Define an array of NativeSymbol for the APIs to be exported. + // Note: the array must be static defined since runtime + // will keep it after registration + // For the function signature specifications, goto the link: + // https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md + + static NativeSymbol native_symbols[] = { { "add_native", add_native, "(i)i", + NULL } }; + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + // Native symbols need below registration phase + init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + init_args.native_module_name = "env"; + init_args.native_symbols = native_symbols; + + if (!wasm_runtime_full_init(&init_args)) { + printf("Init runtime environment failed.\n"); + return -1; + } + + my_context_key = wasm_runtime_create_context_key(my_context_dtor); + if (!my_context_key) { + printf("wasm_runtime_create_context_key failed.\n"); + return -1; + } + + buffer = bh_read_file_to_buffer(wasm_path, &buf_size); + + if (!buffer) { + printf("Open wasm app file [%s] failed.\n", wasm_path); + goto fail; + } + + module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf, + sizeof(error_buf)); + if (!module) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + + module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)); + + if (!module_inst) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + + my_context.x = 100; + wasm_runtime_set_context(module_inst, my_context_key, &my_context); + + exec_env = wasm_runtime_create_exec_env(module_inst, stack_size); + if (!exec_env) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + + wasm_function_inst_t func3 = + wasm_runtime_lookup_function(module_inst, "calculate", NULL); + if (!func3) { + printf("The wasm function calculate is not found.\n"); + goto fail; + } + + uint32_t argv3[1] = { 3 }; + if (wasm_runtime_call_wasm(exec_env, func3, 1, argv3)) { + uint32_t result = *(uint32_t *)argv3; + printf("Native finished calling wasm function: calculate, return: %d\n", + result); + bh_assert(result == 103); /* argv3[0] + my_context.x */ + } + else { + printf("call wasm function calculate failed. error: %s\n", + wasm_runtime_get_exception(module_inst)); + goto fail; + } + +fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) { + bh_assert(my_dtor_called == 0); + wasm_runtime_deinstantiate(module_inst); + bh_assert(my_dtor_called == 1); + } + if (module) + wasm_runtime_unload(module); + if (buffer) + BH_FREE(buffer); + if (my_context_key) + wasm_runtime_destroy_context_key(my_context_key); + wasm_runtime_destroy(); + return 0; +} diff --git a/samples/inst-context/src/my_context.h b/samples/inst-context/src/my_context.h new file mode 100644 index 000000000..db49c1e3b --- /dev/null +++ b/samples/inst-context/src/my_context.h @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +struct my_context { + int x; +}; + +extern void *my_context_key; diff --git a/samples/inst-context/src/native_impl.c b/samples/inst-context/src/native_impl.c new file mode 100644 index 000000000..1254b4a22 --- /dev/null +++ b/samples/inst-context/src/native_impl.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_export.h" +#include "my_context.h" + +int32_t +add_native(wasm_exec_env_t exec_env, int32_t n) +{ + wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env); + struct my_context *ctx = wasm_runtime_get_context(inst, my_context_key); + return n + ctx->x; +} diff --git a/samples/inst-context/wasm-apps/testapp.c b/samples/inst-context/wasm-apps/testapp.c new file mode 100644 index 000000000..1774dcd07 --- /dev/null +++ b/samples/inst-context/wasm-apps/testapp.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +int32_t +add_native(int32_t n); + +int32_t +calculate(int32_t n) +{ + printf("calling into WASM function: %s\n", __FUNCTION__); + return add_native(n); +} diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 08f935bb6..ba0902cdf 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -45,6 +45,7 @@ add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1) add_definitions(-DWASM_ENABLE_PERF_PROFILING=1) add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1) add_definitions(-DWASM_ENABLE_LIB_WASI_THREADS=1) +add_definitions(-DWASM_ENABLE_MODULE_INST_CONTEXT=1) if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1) add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1) From 534a8cf9f4b812950155abf17d98430e1d5599e9 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 8 Sep 2023 12:49:04 +0900 Subject: [PATCH 097/123] Handle a return from wasi _start function correctly (#2529) This fixes a few test cases in wasi-threads testsuite like wasi_threads_return_main_block. And also move the special handling for "wasi proc exit" to a more appropriate place. --- core/iwasm/common/wasm_application.c | 29 ++++++++++++++++- core/iwasm/common/wasm_runtime_common.c | 42 ++----------------------- 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 2ed217e7a..795d65c8c 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -107,7 +107,34 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) the actual main function. Directly calling main function may cause exception thrown. */ if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) { - return wasm_runtime_call_wasm(exec_env, func, 0, NULL); + const char *wasi_proc_exit_exception = "wasi proc exit"; + + ret = wasm_runtime_call_wasm(exec_env, func, 0, NULL); +#if WASM_ENABLE_THREAD_MGR != 0 + if (ret) { + /* On a successful return from the `_start` function, + we terminate other threads by mimicing wasi:proc_exit(0). + + Note: + - A return from the `main` function is an equivalent of + exit(). (C standard) + - When exit code is 0, wasi-libc's `_start` function just + returns w/o calling `proc_exit`. + - A process termination should terminate threads in + the process. */ + + wasm_runtime_set_exception(module_inst, wasi_proc_exit_exception); + /* exit_code is zero-initialized */ + ret = false; + } +#endif + /* report wasm proc exit as a success */ + WASMModuleInstance *inst = (WASMModuleInstance *)module_inst; + if (!ret && strstr(inst->cur_exception, wasi_proc_exit_exception)) { + inst->cur_exception[0] = 0; + ret = true; + } + return ret; } #endif /* end of WASM_ENABLE_LIBC_WASI */ diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index cb7dbee9d..7cac9e643 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1938,33 +1938,6 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env, } #endif -static bool -clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm) -{ -#if WASM_ENABLE_LIBC_WASI != 0 - bool has_exception; - char exception[EXCEPTION_BUF_LEN]; - 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); - - has_exception = wasm_copy_exception(module_inst, exception); - if (has_exception && !strcmp(exception, "Exception: wasi proc exit")) { - /* The "wasi proc exit" exception is thrown by native lib to - let wasm app exit, which is a normal behavior, we clear - the exception here. And just clear the exception of current - thread, don't call `wasm_set_exception(module_inst, NULL)` - which will clear the exception of all threads. */ - module_inst->cur_exception[0] = '\0'; - return true; - } - return false; -#else - return false; -#endif -} - bool wasm_runtime_call_wasm(WASMExecEnv *exec_env, WASMFunctionInstanceCommon *function, uint32 argc, @@ -2005,15 +1978,10 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, param_argc, new_argv); #endif if (!ret) { - if (clear_wasi_proc_exit_exception(exec_env->module_inst)) { - ret = true; - } - else { - if (new_argv != argv) { - wasm_runtime_free(new_argv); - } - return false; + if (new_argv != argv) { + wasm_runtime_free(new_argv); } + return false; } #if WASM_ENABLE_REF_TYPES != 0 @@ -4573,10 +4541,6 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_index, ret = aot_call_indirect(exec_env, 0, element_index, argc, argv); #endif - if (!ret && clear_wasi_proc_exit_exception(exec_env->module_inst)) { - ret = true; - } - return ret; } From f128150d436ca112f695e3eda418c248b1f650c5 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 8 Sep 2023 13:26:32 +0900 Subject: [PATCH 098/123] fd_object_release: Preserve errno (#2535) Preserve errno because this function is often used like the following. The caller wants to report the error from the main operation (`lseek` in this example), not from fd_object_release. ``` off_t ret = lseek(fd_number(fo), offset, nwhence); fd_object_release(fo); if (ret < 0) return convert_errno(errno); ``` --- .../libraries/libc-wasi/sandboxed-system-primitives/src/posix.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 2af2f2d02..a9831d770 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -642,6 +642,7 @@ static void fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) { if (refcount_release(&fo->refcount)) { + int saved_errno = errno; switch (fo->type) { case __WASI_FILETYPE_DIRECTORY: // For directories we may keep track of a DIR object. Calling @@ -659,6 +660,7 @@ fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) break; } wasm_runtime_free(fo); + errno = saved_errno; } } From a6fda9b7ab145222b6dab9929e71147bc061da97 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 13 Sep 2023 18:09:31 +0900 Subject: [PATCH 099/123] Add an API to terminate instance (#2538) Add API wasm_runtime_terminate to terminate a module instance by setting "terminated by user" exception to the module instance. And update the product-mini of posix platforms. Note: this doesn't work for some situations like blocking system calls. --- core/iwasm/common/wasm_runtime_common.c | 27 ++++++- core/iwasm/common/wasm_runtime_common.h | 4 ++ core/iwasm/include/wasm_export.h | 21 ++++++ .../libraries/thread-mgr/thread_manager.c | 16 ++++- .../libraries/thread-mgr/thread_manager.h | 2 +- product-mini/platforms/posix/main.c | 72 +++++++++++++++++++ 6 files changed, 136 insertions(+), 6 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 7cac9e643..3a2f44c5f 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/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) diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index b9b0d0bf6..4e3bc80af 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -675,6 +675,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, diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 589d8af00..559f3d22e 100644 --- a/core/iwasm/include/wasm_export.h +++ b/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: diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 95f0d4267..06be3bc89 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/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); diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 0280119fc..19186f597 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/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); diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 6d4ada662..d61557022 100644 --- a/product-mini/platforms/posix/main.c +++ b/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,37 @@ 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; + _Atomic 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 +582,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 +781,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 +948,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 +994,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 From 83db970953c460738701f0edbf7eb10666e59452 Mon Sep 17 00:00:00 2001 From: Enrico Loparco Date: Wed, 13 Sep 2023 12:03:49 +0200 Subject: [PATCH 100/123] Add user to enlarge memory error callback (#2546) --- core/iwasm/common/wasm_memory.c | 10 +++++++--- core/iwasm/common/wasm_memory.h | 2 +- core/iwasm/include/wasm_export.h | 5 +++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index a083a214e..05635ef51 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/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 diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index cf7d7ffcd..daca2b71e 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/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 } diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 559f3d22e..34206db29 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1468,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 From f697244f3354a96ba169445b83a662689cf64231 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Fri, 15 Sep 2023 10:01:08 +0800 Subject: [PATCH 101/123] runtest.py: Show accurate case amount in summary (#2549) Instead of showing the total case amount under *spec/test/core*, show the accurate number of how many test cases were executed. --- .../wamr-test-suites/spec-test-script/all.py | 76 ++++++++++++------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index bd5b89ce4..834bb742f 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/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", @@ -65,7 +66,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 +80,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 +95,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 +143,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 +191,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 +257,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 +274,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 +453,7 @@ def main(): ) parser.add_argument( "--log", - default='', + default="", dest="log", help="Log directory", ) @@ -512,7 +530,7 @@ def main(): options.gc_flag, options.qemu_flag, options.qemu_firmware, - options.log + options.log, ) else: ret = True From 9c34fc351452dbfb91f9aa7692d6d068a92703bf Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 15 Sep 2023 17:24:12 +0900 Subject: [PATCH 102/123] Fix build with ancient GCC (4.8) (#2553) Fixes: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2552 --- product-mini/platforms/posix/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index d61557022..45237a215 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -497,7 +497,10 @@ dump_pgo_prof_data(wasm_module_inst_t module_inst, const char *path) struct timeout_arg { uint32 timeout_ms; wasm_module_inst_t inst; - _Atomic bool cancel; +#if defined(BH_HAS_STD_ATOMIC) + _Atomic +#endif + bool cancel; }; void * From 132378f30b48b6a61c733c7927fb5701cd3ce86d Mon Sep 17 00:00:00 2001 From: Enrico Loparco Date: Fri, 15 Sep 2023 12:55:16 +0200 Subject: [PATCH 103/123] Allow using custom signal handler from non-main thread (#2551) Remove thread local attribute of prev_sig_act_SIGSEGV/SIGBUS to allow using custom signal handler from non-main thread since in a thread spawned by embedder, embedder may be unable to call wasm_runtime_init_thread_env to initialize them. And fix the handling of prev_sig_act when its sa_handler is SIG_DFL, SIG_IGN, or a user customized handler. --- core/shared/platform/common/posix/posix_thread.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 4fb566d6e..b1460f6b5 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/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) { From d436e846abd049e1e5125bcb9b7170710387185b Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Sun, 17 Sep 2023 06:54:28 +0100 Subject: [PATCH 104/123] Add support for running tests on apple M1 macs (#2554) --- tests/wamr-test-suites/spec-test-script/all.py | 1 + tests/wamr-test-suites/test_wamr.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index 834bb742f..44b0a14bd 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -50,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): diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 1448e3e1e..f33655207 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/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" From 444b1599636e150aa1bc206ec9ad213b624a5ae5 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 20 Sep 2023 19:11:52 +0900 Subject: [PATCH 105/123] Implement async termination of blocking thread (#2516) Send a signal whose handler is no-op to a blocking thread to wake up the blocking syscall with either EINTR equivalent or partial success. Unlike the approach taken in the `dev/interrupt_block_insn` branch (that is, signal + longjmp similarly to `OS_ENABLE_HW_BOUND_CHECK`), this PR does not use longjmp because: * longjmp from signal handler doesn't work on nuttx refer to https://github.com/apache/nuttx/issues/10326 * the singal+longjmp approach may be too difficult for average programmers who might implement host functions to deal with See also https://github.com/bytecodealliance/wasm-micro-runtime/issues/1910 --- build-scripts/config_common.cmake | 7 + core/iwasm/common/wasm_blocking_op.c | 92 ++++ core/iwasm/common/wasm_runtime_common.c | 17 + core/iwasm/common/wasm_runtime_common.h | 9 + core/iwasm/common/wasm_suspend_flags.h | 2 + core/iwasm/include/wasm_export.h | 44 ++ .../libraries/libc-wasi/libc_wasi_wrapper.c | 216 ++++---- .../include/wasmtime_ssp.h | 91 ++++ .../src/blocking_op.c | 201 ++++++++ .../src/blocking_op.h | 52 ++ .../sandboxed-system-primitives/src/posix.c | 461 ++++++++++-------- .../libraries/thread-mgr/thread_manager.c | 4 + .../platform/common/posix/posix_blocking_op.c | 69 +++ .../platform/common/posix/posix_thread.c | 3 + .../platform/darwin/platform_internal.h | 6 + .../platform/freebsd/platform_internal.h | 6 + .../platform/include/platform_api_extension.h | 28 ++ .../shared/platform/linux/platform_internal.h | 6 + .../shared/platform/nuttx/platform_internal.h | 6 + doc/build_wamr.md | 4 + product-mini/platforms/nuttx/wamr.mk | 7 + 21 files changed, 1029 insertions(+), 302 deletions(-) create mode 100644 core/iwasm/common/wasm_blocking_op.c create mode 100644 core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c create mode 100644 core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h create mode 100644 core/shared/platform/common/posix/posix_blocking_op.c diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 0e27e0c09..210f2d788 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -273,6 +273,13 @@ else () add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=0) endif () endif () +if (WAMR_DISABLE_WAKEUP_BLOCKING_OP EQUAL 1) + add_definitions (-DWASM_DISABLE_WAKEUP_BLOCKING_OP=1) + message (" Wakeup of blocking operations disabled") +else () + add_definitions (-DWASM_DISABLE_WAKEUP_BLOCKING_OP=0) + message (" Wakeup of blocking operations enabled") +endif () if (WAMR_BUILD_SIMD EQUAL 1) if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*") add_definitions (-DWASM_ENABLE_SIMD=1) diff --git a/core/iwasm/common/wasm_blocking_op.c b/core/iwasm/common/wasm_blocking_op.c new file mode 100644 index 000000000..25777c8d7 --- /dev/null +++ b/core/iwasm/common/wasm_blocking_op.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_runtime_common.h" + +#include "bh_platform.h" +#include "bh_common.h" +#include "bh_assert.h" + +#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP) + +#define LOCK(env) WASM_SUSPEND_FLAGS_LOCK((env)->wait_lock) +#define UNLOCK(env) WASM_SUSPEND_FLAGS_UNLOCK((env)->wait_lock) + +#define ISSET(env, bit) \ + ((WASM_SUSPEND_FLAGS_GET((env)->suspend_flags) & WASM_SUSPEND_FLAG_##bit) \ + != 0) +#define SET(env, bit) \ + WASM_SUSPEND_FLAGS_FETCH_OR((env)->suspend_flags, WASM_SUSPEND_FLAG_##bit) +#define CLR(env, bit) \ + WASM_SUSPEND_FLAGS_FETCH_AND((env)->suspend_flags, ~WASM_SUSPEND_FLAG_##bit) + +bool +wasm_runtime_begin_blocking_op(wasm_exec_env_t env) +{ + LOCK(env); + bh_assert(!ISSET(env, BLOCKING)); + SET(env, BLOCKING); + if (ISSET(env, TERMINATE)) { + CLR(env, BLOCKING); + UNLOCK(env); + return false; + } + UNLOCK(env); + os_begin_blocking_op(); + return true; +} + +void +wasm_runtime_end_blocking_op(wasm_exec_env_t env) +{ + int saved_errno = errno; + LOCK(env); + bh_assert(ISSET(env, BLOCKING)); + CLR(env, BLOCKING); + UNLOCK(env); + os_end_blocking_op(); + errno = saved_errno; +} + +void +wasm_runtime_interrupt_blocking_op(wasm_exec_env_t env) +{ + /* + * ISSET(BLOCKING) here means that the target thread + * is in somewhere between wasm_begin_blocking_op and + * wasm_end_blocking_op. + * keep waking it up until it reaches wasm_end_blocking_op, + * which clears the BLOCKING bit. + * + * this dumb loop is necessary because posix doesn't provide + * a way to unmask signal and block atomically. + */ + + LOCK(env); + SET(env, TERMINATE); + while (ISSET(env, BLOCKING)) { + UNLOCK(env); + os_wakeup_blocking_op(env->handle); + + /* relax a bit */ + os_usleep(50 * 1000); + LOCK(env); + } + UNLOCK(env); +} + +#else /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */ + +bool +wasm_runtime_begin_blocking_op(wasm_exec_env_t env) +{ + return true; +} + +void +wasm_runtime_end_blocking_op(wasm_exec_env_t env) +{} + +#endif /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */ diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 3a2f44c5f..353985b13 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -457,8 +457,21 @@ wasm_runtime_env_init() } #endif +#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP) + if (os_blocking_op_init() != BHT_OK) { + goto fail11; + } + os_end_blocking_op(); +#endif + return true; +#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP) +fail11: +#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 + aot_compiler_destroy(); +#endif +#endif #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 fail10: #if WASM_ENABLE_FAST_JIT != 0 @@ -1392,6 +1405,10 @@ wasm_runtime_init_thread_env(void) } #endif +#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP) + os_end_blocking_op(); +#endif + return true; } diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 4e3bc80af..19d0af117 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -1040,6 +1040,15 @@ WASM_RUNTIME_API_EXTERN bool wasm_runtime_is_import_global_linked(const char *module_name, const char *global_name); +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_begin_blocking_op(WASMExecEnv *exec_env); + +WASM_RUNTIME_API_EXTERN void +wasm_runtime_end_blocking_op(WASMExecEnv *exec_env); + +void +wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/common/wasm_suspend_flags.h b/core/iwasm/common/wasm_suspend_flags.h index b7ecbb0b2..b182b2b5f 100644 --- a/core/iwasm/common/wasm_suspend_flags.h +++ b/core/iwasm/common/wasm_suspend_flags.h @@ -20,6 +20,8 @@ extern "C" { #define WASM_SUSPEND_FLAG_BREAKPOINT 0x4 /* Return from pthread_exit */ #define WASM_SUSPEND_FLAG_EXIT 0x8 +/* The thread might be blocking */ +#define WASM_SUSPEND_FLAG_BLOCKING 0x10 typedef union WASMSuspendFlags { bh_atomic_32_t flags; diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 34206db29..48ed55933 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1546,6 +1546,50 @@ wasm_runtime_set_context_spread(wasm_module_inst_t inst, void *key, WASM_RUNTIME_API_EXTERN void * wasm_runtime_get_context(wasm_module_inst_t inst, void *key); +/* + * wasm_runtime_begin_blocking_op/wasm_runtime_end_blocking_op + * + * These APIs are intended to be used by the implementations of + * host functions. It wraps an operation which possibly blocks for long + * to prepare for async termination. + * + * eg. + * + * if (!wasm_runtime_begin_blocking_op(exec_env)) { + * return EINTR; + * } + * ret = possibly_blocking_op(); + * wasm_runtime_end_blocking_op(exec_env); + * return ret; + * + * If threading support (WASM_ENABLE_THREAD_MGR) is not enabled, + * these functions are no-op. + * + * If the underlying platform support (OS_ENABLE_WAKEUP_BLOCKING_OP) is + * not available, these functions are no-op. In that case, the runtime + * might not terminate a blocking thread in a timely manner. + * + * If the underlying platform support is available, it's used to wake up + * the thread for async termination. The expectation here is that a + * `os_wakeup_blocking_op` call makes the blocking operation + * (`possibly_blocking_op` in the above example) return in a timely manner. + * + * The actual wake up mechanism used by `os_wakeup_blocking_op` is + * platform-dependent. It might impose some platform-dependent restrictions + * on the implementation of the blocking opearation. + * + * For example, on POSIX-like platforms, a signal (by default SIGUSR1) is + * used. The signal delivery configurations (eg. signal handler, signal mask, + * etc) for the signal are set up by the runtime. You can change the signal + * to use for this purpose by calling os_set_signal_number_for_blocking_op + * before the runtime initialization. + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_begin_blocking_op(wasm_exec_env_t exec_env); + +WASM_RUNTIME_API_EXTERN void +wasm_runtime_end_blocking_op(wasm_exec_env_t exec_env); + /* clang-format on */ #ifdef __cplusplus diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 70ac4dc54..292bd8379 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -335,7 +335,7 @@ wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd) if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_close(curfds, prestats, fd); + return wasmtime_ssp_fd_close(exec_env, curfds, prestats, fd); } static wasi_errno_t @@ -348,7 +348,7 @@ wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd) if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_datasync(curfds, fd); + return wasmtime_ssp_fd_datasync(exec_env, curfds, fd); } static wasi_errno_t @@ -389,8 +389,8 @@ wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, iovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_pread(curfds, fd, iovec_begin, iovs_len, offset, - &nread); + err = wasmtime_ssp_fd_pread(exec_env, curfds, fd, iovec_begin, iovs_len, + offset, &nread); if (err) goto fail; @@ -443,8 +443,8 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, ciovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_pwrite(curfds, fd, ciovec_begin, iovs_len, offset, - &nwritten); + err = wasmtime_ssp_fd_pwrite(exec_env, curfds, fd, ciovec_begin, iovs_len, + offset, &nwritten); if (err) goto fail; @@ -496,7 +496,8 @@ wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_read(curfds, fd, iovec_begin, iovs_len, &nread); + err = wasmtime_ssp_fd_read(exec_env, curfds, fd, iovec_begin, iovs_len, + &nread); if (err) goto fail; @@ -521,7 +522,7 @@ wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to) if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_renumber(curfds, prestats, from, to); + return wasmtime_ssp_fd_renumber(exec_env, curfds, prestats, from, to); } static wasi_errno_t @@ -538,7 +539,8 @@ wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset, if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_seek(curfds, fd, offset, whence, newoffset); + return wasmtime_ssp_fd_seek(exec_env, curfds, fd, offset, whence, + newoffset); } static wasi_errno_t @@ -554,7 +556,7 @@ wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset) if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_tell(curfds, fd, newoffset); + return wasmtime_ssp_fd_tell(exec_env, curfds, fd, newoffset); } static wasi_errno_t @@ -573,7 +575,7 @@ wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_fd_fdstat_get(curfds, fd, &fdstat); + err = wasmtime_ssp_fd_fdstat_get(exec_env, curfds, fd, &fdstat); if (err) return err; @@ -592,7 +594,7 @@ wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_fdstat_set_flags(curfds, fd, flags); + return wasmtime_ssp_fd_fdstat_set_flags(exec_env, curfds, fd, flags); } static wasi_errno_t @@ -607,8 +609,8 @@ wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_fdstat_set_rights(curfds, fd, fs_rights_base, - fs_rights_inheriting); + return wasmtime_ssp_fd_fdstat_set_rights( + exec_env, curfds, fd, fs_rights_base, fs_rights_inheriting); } static wasi_errno_t @@ -621,7 +623,7 @@ wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd) if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_sync(curfds, fd); + return wasmtime_ssp_fd_sync(exec_env, curfds, fd); } static wasi_errno_t @@ -663,7 +665,8 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, ciovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_write(curfds, fd, ciovec_begin, iovs_len, &nwritten); + err = wasmtime_ssp_fd_write(exec_env, curfds, fd, ciovec_begin, iovs_len, + &nwritten); if (err) goto fail; @@ -688,7 +691,7 @@ wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_advise(curfds, fd, offset, len, advice); + return wasmtime_ssp_fd_advise(exec_env, curfds, fd, offset, len, advice); } static wasi_errno_t @@ -702,7 +705,7 @@ wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_allocate(curfds, fd, offset, len); + return wasmtime_ssp_fd_allocate(exec_env, curfds, fd, offset, len); } static wasi_errno_t @@ -716,7 +719,8 @@ wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_create_directory(curfds, fd, path, path_len); + return wasmtime_ssp_path_create_directory(exec_env, curfds, fd, path, + path_len); } static wasi_errno_t @@ -733,8 +737,9 @@ wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_link(curfds, prestats, old_fd, old_flags, old_path, - old_path_len, new_fd, new_path, new_path_len); + return wasmtime_ssp_path_link(exec_env, curfds, prestats, old_fd, old_flags, + old_path, old_path_len, new_fd, new_path, + new_path_len); } static wasi_errno_t @@ -756,9 +761,9 @@ wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, if (!validate_native_addr(fd_app, sizeof(wasi_fd_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_path_open(curfds, dirfd, dirflags, path, path_len, - oflags, fs_rights_base, fs_rights_inheriting, - fs_flags, &fd); + err = wasmtime_ssp_path_open(exec_env, curfds, dirfd, dirflags, path, + path_len, oflags, fs_rights_base, + fs_rights_inheriting, fs_flags, &fd); *fd_app = fd; return err; @@ -780,7 +785,8 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf, if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = wasmtime_ssp_fd_readdir(curfds, fd, buf, buf_len, cookie, &bufused); + err = wasmtime_ssp_fd_readdir(exec_env, curfds, fd, buf, buf_len, cookie, + &bufused); if (err) return err; @@ -805,8 +811,8 @@ wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = wasmtime_ssp_path_readlink(curfds, fd, path, path_len, buf, buf_len, - &bufused); + err = wasmtime_ssp_path_readlink(exec_env, curfds, fd, path, path_len, buf, + buf_len, &bufused); if (err) return err; @@ -826,8 +832,9 @@ wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_rename(curfds, old_fd, old_path, old_path_len, - new_fd, new_path, new_path_len); + return wasmtime_ssp_path_rename(exec_env, curfds, old_fd, old_path, + old_path_len, new_fd, new_path, + new_path_len); } static wasi_errno_t @@ -844,7 +851,7 @@ wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_filestat_get(curfds, fd, filestat); + return wasmtime_ssp_fd_filestat_get(exec_env, curfds, fd, filestat); } static wasi_errno_t @@ -859,8 +866,8 @@ wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_filestat_set_times(curfds, fd, st_atim, st_mtim, - fstflags); + return wasmtime_ssp_fd_filestat_set_times(exec_env, curfds, fd, st_atim, + st_mtim, fstflags); } static wasi_errno_t @@ -874,7 +881,7 @@ wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_filestat_set_size(curfds, fd, st_size); + return wasmtime_ssp_fd_filestat_set_size(exec_env, curfds, fd, st_size); } static wasi_errno_t @@ -892,8 +899,8 @@ wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_path_filestat_get(curfds, fd, flags, path, path_len, - filestat); + return wasmtime_ssp_path_filestat_get(exec_env, curfds, fd, flags, path, + path_len, filestat); } static wasi_errno_t @@ -909,8 +916,9 @@ wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_filestat_set_times( - curfds, fd, flags, path, path_len, st_atim, st_mtim, fstflags); + return wasmtime_ssp_path_filestat_set_times(exec_env, curfds, fd, flags, + path, path_len, st_atim, + st_mtim, fstflags); } static wasi_errno_t @@ -926,8 +934,8 @@ wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_symlink(curfds, prestats, old_path, old_path_len, - fd, new_path, new_path_len); + return wasmtime_ssp_path_symlink(exec_env, curfds, prestats, old_path, + old_path_len, fd, new_path, new_path_len); } static wasi_errno_t @@ -941,7 +949,7 @@ wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_unlink_file(curfds, fd, path, path_len); + return wasmtime_ssp_path_unlink_file(exec_env, curfds, fd, path, path_len); } static wasi_errno_t @@ -955,7 +963,8 @@ wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len); + return wasmtime_ssp_path_remove_directory(exec_env, curfds, fd, path, + path_len); } #if WASM_ENABLE_THREAD_MGR != 0 @@ -1026,8 +1035,8 @@ execute_interruptible_poll_oneoff( /* update timeout for clock subscription events */ update_clock_subscription_data( in_copy, nsubscriptions, min_uint64(time_quant, timeout - elapsed)); - err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions, - nevents); + err = wasmtime_ssp_poll_oneoff(exec_env, curfds, in_copy, out, + nsubscriptions, nevents); elapsed += time_quant; if (err) { @@ -1079,7 +1088,8 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, return (wasi_errno_t)-1; #if WASM_ENABLE_THREAD_MGR == 0 - err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents); + err = wasmtime_ssp_poll_oneoff(exec_env, curfds, in, out, nsubscriptions, + &nevents); #else err = execute_interruptible_poll_oneoff(curfds, in, out, nsubscriptions, &nevents, exec_env); @@ -1133,7 +1143,7 @@ wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fdflags_t flags, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_accept(curfds, fd, flags, fd_new); + return wasi_ssp_sock_accept(exec_env, curfds, fd, flags, fd_new); } static wasi_errno_t @@ -1152,7 +1162,7 @@ wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_addr_local(curfds, fd, addr); + return wasi_ssp_sock_addr_local(exec_env, curfds, fd, addr); } static wasi_errno_t @@ -1171,7 +1181,7 @@ wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_addr_remote(curfds, fd, addr); + return wasi_ssp_sock_addr_remote(exec_env, curfds, fd, addr); } static wasi_errno_t @@ -1192,8 +1202,8 @@ wasi_sock_addr_resolve(wasm_exec_env_t exec_env, const char *host, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); ns_lookup_list = wasi_ctx_get_ns_lookup_list(wasi_ctx); - return wasi_ssp_sock_addr_resolve(curfds, ns_lookup_list, host, service, - hints, addr_info, addr_info_size, + return wasi_ssp_sock_addr_resolve(exec_env, curfds, ns_lookup_list, host, + service, hints, addr_info, addr_info_size, max_info_size); } @@ -1211,7 +1221,7 @@ wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); - return wasi_ssp_sock_bind(curfds, addr_pool, fd, addr); + return wasi_ssp_sock_bind(exec_env, curfds, addr_pool, fd, addr); } static wasi_errno_t @@ -1234,7 +1244,7 @@ wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); - return wasi_ssp_sock_connect(curfds, addr_pool, fd, addr); + return wasi_ssp_sock_connect(exec_env, curfds, addr_pool, fd, addr); } static wasi_errno_t @@ -1253,7 +1263,7 @@ wasi_sock_get_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_broadcast(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_broadcast(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1272,7 +1282,7 @@ wasi_sock_get_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_keep_alive(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_keep_alive(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1292,7 +1302,8 @@ wasi_sock_get_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool *is_enabled, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_linger(curfds, fd, is_enabled, linger_s); + return wasmtime_ssp_sock_get_linger(exec_env, curfds, fd, is_enabled, + linger_s); } static wasi_errno_t @@ -1311,7 +1322,7 @@ wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_recv_buf_size(curfds, fd, size); + return wasmtime_ssp_sock_get_recv_buf_size(exec_env, curfds, fd, size); } static wasi_errno_t @@ -1330,7 +1341,7 @@ wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_recv_timeout(curfds, fd, timeout_us); + return wasmtime_ssp_sock_get_recv_timeout(exec_env, curfds, fd, timeout_us); } static wasi_errno_t @@ -1349,7 +1360,7 @@ wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_reuse_addr(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_reuse_addr(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1368,7 +1379,7 @@ wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_reuse_port(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_reuse_port(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1387,7 +1398,7 @@ wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_send_buf_size(curfds, fd, size); + return wasmtime_ssp_sock_get_send_buf_size(exec_env, curfds, fd, size); } static wasi_errno_t @@ -1406,7 +1417,7 @@ wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_send_timeout(curfds, fd, timeout_us); + return wasmtime_ssp_sock_get_send_timeout(exec_env, curfds, fd, timeout_us); } static wasi_errno_t @@ -1425,7 +1436,8 @@ wasi_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_fastopen_connect(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_tcp_fastopen_connect(exec_env, curfds, fd, + is_enabled); } static wasi_errno_t @@ -1444,7 +1456,7 @@ wasi_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_no_delay(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_tcp_no_delay(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1463,7 +1475,8 @@ wasi_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_quick_ack(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_tcp_quick_ack(exec_env, curfds, fd, + is_enabled); } static wasi_errno_t @@ -1482,7 +1495,7 @@ wasi_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_keep_idle(curfds, fd, time_s); + return wasmtime_ssp_sock_get_tcp_keep_idle(exec_env, curfds, fd, time_s); } static wasi_errno_t @@ -1501,7 +1514,7 @@ wasi_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_keep_intvl(curfds, fd, time_s); + return wasmtime_ssp_sock_get_tcp_keep_intvl(exec_env, curfds, fd, time_s); } static wasi_errno_t @@ -1520,7 +1533,7 @@ wasi_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_ip_multicast_loop(curfds, fd, ipv6, + return wasmtime_ssp_sock_get_ip_multicast_loop(exec_env, curfds, fd, ipv6, is_enabled); } @@ -1539,7 +1552,7 @@ wasi_sock_get_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t *ttl_s) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_ip_ttl(curfds, fd, ttl_s); + return wasmtime_ssp_sock_get_ip_ttl(exec_env, curfds, fd, ttl_s); } static wasi_errno_t @@ -1558,7 +1571,7 @@ wasi_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_ip_multicast_ttl(curfds, fd, ttl_s); + return wasmtime_ssp_sock_get_ip_multicast_ttl(exec_env, curfds, fd, ttl_s); } static wasi_errno_t @@ -1577,7 +1590,7 @@ wasi_sock_get_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_ipv6_only(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_ipv6_only(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1592,7 +1605,7 @@ wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_listen(curfds, fd, backlog); + return wasi_ssp_sock_listen(exec_env, curfds, fd, backlog); } static wasi_errno_t @@ -1609,7 +1622,7 @@ wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_open(curfds, poolfd, af, socktype, sockfd); + return wasi_ssp_sock_open(exec_env, curfds, poolfd, af, socktype, sockfd); } static wasi_errno_t @@ -1624,7 +1637,7 @@ wasi_sock_set_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_broadcast(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_broadcast(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1640,7 +1653,7 @@ wasi_sock_set_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_keep_alive(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_keep_alive(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1656,7 +1669,8 @@ wasi_sock_set_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_linger(curfds, fd, is_enabled, linger_s); + return wasmtime_ssp_sock_set_linger(exec_env, curfds, fd, is_enabled, + linger_s); } static wasi_errno_t @@ -1671,7 +1685,7 @@ wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_recv_buf_size(curfds, fd, size); + return wasmtime_ssp_sock_set_recv_buf_size(exec_env, curfds, fd, size); } static wasi_errno_t @@ -1687,7 +1701,7 @@ wasi_sock_set_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_recv_timeout(curfds, fd, timeout_us); + return wasmtime_ssp_sock_set_recv_timeout(exec_env, curfds, fd, timeout_us); } static wasi_errno_t @@ -1703,7 +1717,7 @@ wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_reuse_addr(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_reuse_addr(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1719,7 +1733,7 @@ wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_reuse_port(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_reuse_port(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1734,7 +1748,7 @@ wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_send_buf_size(curfds, fd, size); + return wasmtime_ssp_sock_set_send_buf_size(exec_env, curfds, fd, size); } static wasi_errno_t @@ -1750,7 +1764,7 @@ wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_send_timeout(curfds, fd, timeout_us); + return wasmtime_ssp_sock_set_send_timeout(exec_env, curfds, fd, timeout_us); } static wasi_errno_t @@ -1766,7 +1780,8 @@ wasi_sock_set_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_fastopen_connect(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_tcp_fastopen_connect(exec_env, curfds, fd, + is_enabled); } static wasi_errno_t @@ -1782,7 +1797,7 @@ wasi_sock_set_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_no_delay(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_tcp_no_delay(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1798,7 +1813,8 @@ wasi_sock_set_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_quick_ack(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_tcp_quick_ack(exec_env, curfds, fd, + is_enabled); } static wasi_errno_t @@ -1814,7 +1830,7 @@ wasi_sock_set_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_keep_idle(curfds, fd, time_s); + return wasmtime_ssp_sock_set_tcp_keep_idle(exec_env, curfds, fd, time_s); } static wasi_errno_t @@ -1830,7 +1846,7 @@ wasi_sock_set_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_keep_intvl(curfds, fd, time_s); + return wasmtime_ssp_sock_set_tcp_keep_intvl(exec_env, curfds, fd, time_s); } static wasi_errno_t @@ -1846,7 +1862,7 @@ wasi_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_multicast_loop(curfds, fd, ipv6, + return wasmtime_ssp_sock_set_ip_multicast_loop(exec_env, curfds, fd, ipv6, is_enabled); } @@ -1867,8 +1883,8 @@ wasi_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_add_membership(curfds, fd, imr_multiaddr, - imr_interface); + return wasmtime_ssp_sock_set_ip_add_membership( + exec_env, curfds, fd, imr_multiaddr, imr_interface); } static wasi_errno_t @@ -1888,8 +1904,8 @@ wasi_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_drop_membership(curfds, fd, imr_multiaddr, - imr_interface); + return wasmtime_ssp_sock_set_ip_drop_membership( + exec_env, curfds, fd, imr_multiaddr, imr_interface); } static wasi_errno_t @@ -1904,7 +1920,7 @@ wasi_sock_set_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t ttl_s) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_ttl(curfds, fd, ttl_s); + return wasmtime_ssp_sock_set_ip_ttl(exec_env, curfds, fd, ttl_s); } static wasi_errno_t @@ -1920,7 +1936,7 @@ wasi_sock_set_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_multicast_ttl(curfds, fd, ttl_s); + return wasmtime_ssp_sock_set_ip_multicast_ttl(exec_env, curfds, fd, ttl_s); } static wasi_errno_t @@ -1935,7 +1951,7 @@ wasi_sock_set_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ipv6_only(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_ipv6_only(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -2053,8 +2069,9 @@ wasi_sock_recv_from(wasm_exec_env_t exec_env, wasi_fd_t sock, memset(buf_begin, 0, total_size); *ro_data_len = 0; - err = wasmtime_ssp_sock_recv_from(curfds, sock, buf_begin, total_size, - ri_flags, src_addr, &recv_bytes); + err = wasmtime_ssp_sock_recv_from(exec_env, curfds, sock, buf_begin, + total_size, ri_flags, src_addr, + &recv_bytes); if (err != __WASI_ESUCCESS) { goto fail; } @@ -2153,7 +2170,8 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, return err; *so_data_len = 0; - err = wasmtime_ssp_sock_send(curfds, sock, buf, buf_size, &send_bytes); + err = wasmtime_ssp_sock_send(exec_env, curfds, sock, buf, buf_size, + &send_bytes); *so_data_len = (uint32)send_bytes; wasm_runtime_free(buf); @@ -2193,8 +2211,8 @@ wasi_sock_send_to(wasm_exec_env_t exec_env, wasi_fd_t sock, return err; *so_data_len = 0; - err = wasmtime_ssp_sock_send_to(curfds, addr_pool, sock, buf, buf_size, - si_flags, dest_addr, &send_bytes); + err = wasmtime_ssp_sock_send_to(exec_env, curfds, addr_pool, sock, buf, + buf_size, si_flags, dest_addr, &send_bytes); *so_data_len = (uint32)send_bytes; wasm_runtime_free(buf); @@ -2212,7 +2230,7 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how) if (!wasi_ctx) return __WASI_EINVAL; - return wasmtime_ssp_sock_shutdown(curfds, sock); + return wasmtime_ssp_sock_shutdown(exec_env, curfds, sock); } static wasi_errno_t diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index a53153552..efe7c8e3a 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -22,6 +22,8 @@ #include #include +#include "wasm_export.h" + /* clang-format off */ #ifdef __cplusplus @@ -646,17 +648,20 @@ __wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( ) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_close( + wasm_exec_env_t exec_env, struct fd_table *curfds, struct fd_prestats *prestats, __wasi_fd_t fd ) WASMTIME_SSP_SYSCALL_NAME(fd_close) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_datasync( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd ) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_pread( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const __wasi_iovec_t *iovs, @@ -666,6 +671,7 @@ __wasi_errno_t wasmtime_ssp_fd_pread( ) WASMTIME_SSP_SYSCALL_NAME(fd_pread) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_pwrite( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const __wasi_ciovec_t *iovs, @@ -675,6 +681,7 @@ __wasi_errno_t wasmtime_ssp_fd_pwrite( ) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_read( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const __wasi_iovec_t *iovs, @@ -683,6 +690,7 @@ __wasi_errno_t wasmtime_ssp_fd_read( ) WASMTIME_SSP_SYSCALL_NAME(fd_read) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_renumber( + wasm_exec_env_t exec_env, struct fd_table *curfds, struct fd_prestats *prestats, __wasi_fd_t from, @@ -690,6 +698,7 @@ __wasi_errno_t wasmtime_ssp_fd_renumber( ) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_seek( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filedelta_t offset, @@ -698,24 +707,28 @@ __wasi_errno_t wasmtime_ssp_fd_seek( ) WASMTIME_SSP_SYSCALL_NAME(fd_seek) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_tell( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filesize_t *newoffset ) WASMTIME_SSP_SYSCALL_NAME(fd_tell) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_fdstat_get( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_fdstat_t *buf ) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_fdflags_t flags ) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_rights_t fs_rights_base, @@ -723,11 +736,13 @@ __wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( ) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_sync( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd ) WASMTIME_SSP_SYSCALL_NAME(fd_sync) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_write( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const __wasi_ciovec_t *iovs, @@ -736,6 +751,7 @@ __wasi_errno_t wasmtime_ssp_fd_write( ) WASMTIME_SSP_SYSCALL_NAME(fd_write) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_advise( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filesize_t offset, @@ -744,6 +760,7 @@ __wasi_errno_t wasmtime_ssp_fd_advise( ) WASMTIME_SSP_SYSCALL_NAME(fd_advise) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_allocate( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filesize_t offset, @@ -751,6 +768,7 @@ __wasi_errno_t wasmtime_ssp_fd_allocate( ) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_create_directory( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const char *path, @@ -758,6 +776,7 @@ __wasi_errno_t wasmtime_ssp_path_create_directory( ) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_link( + wasm_exec_env_t exec_env, struct fd_table *curfds, struct fd_prestats *prestats, __wasi_fd_t old_fd, @@ -770,6 +789,7 @@ __wasi_errno_t wasmtime_ssp_path_link( ) WASMTIME_SSP_SYSCALL_NAME(path_link) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_open( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, @@ -783,6 +803,7 @@ __wasi_errno_t wasmtime_ssp_path_open( ) WASMTIME_SSP_SYSCALL_NAME(path_open) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_readdir( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, void *buf, @@ -792,6 +813,7 @@ __wasi_errno_t wasmtime_ssp_fd_readdir( ) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_readlink( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const char *path, @@ -802,6 +824,7 @@ __wasi_errno_t wasmtime_ssp_path_readlink( ) WASMTIME_SSP_SYSCALL_NAME(path_readlink) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_rename( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t old_fd, const char *old_path, @@ -812,12 +835,14 @@ __wasi_errno_t wasmtime_ssp_path_rename( ) WASMTIME_SSP_SYSCALL_NAME(path_rename) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_filestat_get( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filestat_t *buf ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_filestat_set_times( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_timestamp_t st_atim, @@ -826,12 +851,14 @@ __wasi_errno_t wasmtime_ssp_fd_filestat_set_times( ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_filestat_set_size( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_filesize_t st_size ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_filestat_get( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_lookupflags_t flags, @@ -841,6 +868,7 @@ __wasi_errno_t wasmtime_ssp_path_filestat_get( ) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_filestat_set_times( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_lookupflags_t flags, @@ -852,6 +880,7 @@ __wasi_errno_t wasmtime_ssp_path_filestat_set_times( ) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_symlink( + wasm_exec_env_t exec_env, struct fd_table *curfds, struct fd_prestats *prestats, const char *old_path, @@ -862,6 +891,7 @@ __wasi_errno_t wasmtime_ssp_path_symlink( ) WASMTIME_SSP_SYSCALL_NAME(path_symlink) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_unlink_file( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const char *path, @@ -869,6 +899,7 @@ __wasi_errno_t wasmtime_ssp_path_unlink_file( ) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_remove_directory( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, const char *path, @@ -876,6 +907,7 @@ __wasi_errno_t wasmtime_ssp_path_remove_directory( ) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_poll_oneoff( + wasm_exec_env_t exec_env, struct fd_table *curfds, const __wasi_subscription_t *in, __wasi_event_t *out, @@ -890,24 +922,28 @@ __wasi_errno_t wasmtime_ssp_random_get( __wasi_errno_t wasi_ssp_sock_accept( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_addr_local( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_addr_t *addr ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_addr_remote( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_addr_t *addr ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_open( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype, __wasi_fd_t *sockfd @@ -915,12 +951,14 @@ wasi_ssp_sock_open( __wasi_errno_t wasi_ssp_sock_bind( + wasm_exec_env_t exec_env, struct fd_table *curfds, struct addr_pool *addr_pool, __wasi_fd_t fd, __wasi_addr_t *addr ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_addr_resolve( + wasm_exec_env_t exec_env, struct fd_table *curfds, char **ns_lookup_list, const char *host, const char* service, __wasi_addr_info_hints_t *hints, __wasi_addr_info_t *addr_info, @@ -929,65 +967,76 @@ wasi_ssp_sock_addr_resolve( __wasi_errno_t wasi_ssp_sock_connect( + wasm_exec_env_t exec_env, struct fd_table *curfds, struct addr_pool *addr_pool, __wasi_fd_t fd, __wasi_addr_t *addr ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_get_recv_buf_size( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_size_t *size ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_get_reuse_addr( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, uint8_t *reuse ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_get_reuse_port( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, uint8_t *reuse ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_get_send_buf_size( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_size_t *size ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_set_recv_buf_size( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_size_t size ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_set_reuse_addr( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, uint8_t reuse ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_set_reuse_port( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, uint8_t reuse ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_set_send_buf_size( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_size_t size ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasi_ssp_sock_listen( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_size_t backlog ) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_recv( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, void *buf, @@ -996,6 +1045,7 @@ __wasi_errno_t wasmtime_ssp_sock_recv( ) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_recv_from( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, void *buf, @@ -1006,6 +1056,7 @@ __wasi_errno_t wasmtime_ssp_sock_recv_from( ) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_send( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, const void *buf, @@ -1014,6 +1065,7 @@ __wasi_errno_t wasmtime_ssp_sock_send( ) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_send_to( + wasm_exec_env_t exec_env, struct fd_table *curfds, struct addr_pool *addr_pool, __wasi_fd_t sock, const void *buf, @@ -1024,53 +1076,62 @@ __wasi_errno_t wasmtime_ssp_sock_send_to( ) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_shutdown( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock ) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_recv_timeout( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint64_t timeout_us ) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_recv_timeout( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint64_t *timeout_us ) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_send_timeout( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint64_t timeout_us ) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_send_timeout( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint64_t *timeout_us ) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_send_buf_size( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, size_t bufsiz ) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_send_buf_size( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, size_t *bufsiz ) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, size_t bufsiz ) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, size_t *bufsiz @@ -1078,42 +1139,49 @@ __wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size( __wasi_errno_t wasmtime_ssp_sock_set_keep_alive( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_keep_alive( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_reuse_addr( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_reuse_addr( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_reuse_port( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_reuse_port( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_linger( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool is_enabled, @@ -1121,83 +1189,97 @@ __wasi_errno_t wasmtime_ssp_sock_set_linger( ) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_linger( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool *is_enabled, int *linger_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_broadcast( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_broadcast( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint32_t time_s ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint32_t *time_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint32_t time_s ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint32_t *time_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool *is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool ipv6, @@ -1205,6 +1287,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop( ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool ipv6, @@ -1212,6 +1295,7 @@ __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop( ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, @@ -1219,6 +1303,7 @@ __wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership( ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, @@ -1226,36 +1311,42 @@ __wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership( ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_ttl( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint8_t ttl_s ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_ip_ttl( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint8_t *ttl_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint8_t ttl_s ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, uint8_t *ttl_s ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_ipv6_only( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool is_enabled ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_get_ipv6_only( + wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t sock, bool *is_enabled diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c new file mode 100644 index 000000000..9d01f2bfe --- /dev/null +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "ssp_config.h" +#include "blocking_op.h" + +int +blocking_op_close(wasm_exec_env_t exec_env, int fd) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = close(fd); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +ssize_t +blocking_op_readv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = readv(fd, iov, iovcnt); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +#if CONFIG_HAS_PREADV +ssize_t +blocking_op_preadv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt, off_t offset) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = preadv(fd, iov, iovcnt, offset); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} +#else /* CONFIG_HAS_PREADV */ +ssize_t +blocking_op_pread(wasm_exec_env_t exec_env, int fd, void *p, size_t nb, + off_t offset) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = pread(fd, p, nb, offset); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} +#endif /* CONFIG_HAS_PREADV */ + +ssize_t +blocking_op_writev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = writev(fd, iov, iovcnt); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +#if CONFIG_HAS_PWRITEV +ssize_t +blocking_op_pwritev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt, off_t offset) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = pwritev(fd, iov, iovcnt, offset); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} +#else /* CONFIG_HAS_PWRITEV */ +ssize_t +blocking_op_pwrite(wasm_exec_env_t exec_env, int fd, const void *p, size_t nb, + off_t offset) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = pwrite(fd, p, nb, offset); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} +#endif /* CONFIG_HAS_PWRITEV */ + +int +blocking_op_socket_accept(wasm_exec_env_t exec_env, bh_socket_t server_sock, + bh_socket_t *sockp, void *addr, + unsigned int *addrlenp) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_accept(server_sock, sockp, addr, addrlenp); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_socket_connect(wasm_exec_env_t exec_env, bh_socket_t sock, + const char *addr, int port) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_connect(sock, addr, port); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_socket_recv_from(wasm_exec_env_t exec_env, bh_socket_t sock, + void *buf, unsigned int len, int flags, + bh_sockaddr_t *src_addr) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_recv_from(sock, buf, len, flags, src_addr); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_socket_send_to(wasm_exec_env_t exec_env, bh_socket_t sock, + const void *buf, unsigned int len, int flags, + const bh_sockaddr_t *dest_addr) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_send_to(sock, buf, len, flags, dest_addr); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_socket_addr_resolve(wasm_exec_env_t exec_env, const char *host, + const char *service, uint8_t *hint_is_tcp, + uint8_t *hint_is_ipv4, + bh_addr_info_t *addr_info, + size_t addr_info_size, size_t *max_info_size) +{ + /* + * Note: Unlike others, os_socket_addr_resolve() is not a simple system + * call. It's likely backed by a complex libc function, getaddrinfo(). + * Depending on the implementation of getaddrinfo() and underlying + * DNS resolver, it might or might not be possible to make it return + * with os_wakeup_blocking_op(). + * + * Unfortunately, many of ISC/bind based resolvers just keep going on + * interrupted system calls. It includes macOS and glibc. + * + * On the other hand, NuttX as of writing this returns EAI_AGAIN + * on EINTR. + */ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_addr_resolve(host, service, hint_is_tcp, hint_is_ipv4, + addr_info, addr_info_size, max_info_size); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_openat(wasm_exec_env_t exec_env, int fd, const char *path, + int oflags, mode_t mode) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = openat(fd, path, oflags, mode); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h new file mode 100644 index 000000000..44a16d338 --- /dev/null +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "wasm_export.h" + +int +blocking_op_close(wasm_exec_env_t exec_env, int fd); +ssize_t +blocking_op_readv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt); +ssize_t +blocking_op_preadv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt, off_t offset); +ssize_t +blocking_op_pread(wasm_exec_env_t exec_env, int fd, void *p, size_t nb, + off_t offset); +ssize_t +blocking_op_writev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt); +ssize_t +blocking_op_pwritev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt, off_t offset); +ssize_t +blocking_op_pwrite(wasm_exec_env_t exec_env, int fd, const void *p, size_t nb, + off_t offset); +int +blocking_op_socket_accept(wasm_exec_env_t exec_env, bh_socket_t server_sock, + bh_socket_t *sockp, void *addr, + unsigned int *addrlenp); +int +blocking_op_socket_connect(wasm_exec_env_t exec_env, bh_socket_t sock, + const char *addr, int port); +int +blocking_op_socket_recv_from(wasm_exec_env_t exec_env, bh_socket_t sock, + void *buf, unsigned int len, int flags, + bh_sockaddr_t *src_addr); +int +blocking_op_socket_send_to(wasm_exec_env_t exec_env, bh_socket_t sock, + const void *buf, unsigned int len, int flags, + const bh_sockaddr_t *dest_addr); +int +blocking_op_socket_addr_resolve(wasm_exec_env_t exec_env, const char *host, + const char *service, uint8_t *hint_is_tcp, + uint8_t *hint_is_ipv4, + bh_addr_info_t *addr_info, + size_t addr_info_size, size_t *max_info_size); +int +blocking_op_openat(wasm_exec_env_t exec_env, int fd, const char *path, + int oflags, mode_t mode); diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index a9831d770..c096511c9 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -13,6 +13,7 @@ #include "ssp_config.h" #include "bh_platform.h" +#include "blocking_op.h" #include "wasmtime_ssp.h" #include "locking.h" #include "posix.h" @@ -630,16 +631,25 @@ fd_number(const struct fd_object *fo) return number; } -#define CLOSE_NON_STD_FD(fd) \ - do { \ - if (fd > 2) \ - close(fd); \ +// The env == NULL case is for +// fd_table_destroy, path_get, path_put, fd_table_insert_existing +#define CLOSE_NON_STD_FD(env, fd) \ + do { \ + if (fd > 2) { \ + if (env == NULL) { \ + close(fd); \ + } \ + else { \ + blocking_op_close(env, fd); \ + } \ + } \ } while (0) // Lowers the reference count on a file descriptor object. When the // reference count reaches zero, its resources are cleaned up. static void -fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) +fd_object_release(wasm_exec_env_t env, struct fd_object *fo) + UNLOCKS(fo->refcount) { if (refcount_release(&fo->refcount)) { int saved_errno = errno; @@ -649,14 +659,14 @@ fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) // closedir() on it also closes the underlying file descriptor. mutex_destroy(&fo->directory.lock); if (fo->directory.handle == NULL) { - CLOSE_NON_STD_FD(fd_number(fo)); + CLOSE_NON_STD_FD(env, fd_number(fo)); } else { closedir(fo->directory.handle); } break; default: - CLOSE_NON_STD_FD(fd_number(fo)); + CLOSE_NON_STD_FD(env, fd_number(fo)); break; } wasm_runtime_free(fo); @@ -695,7 +705,7 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) fo->number = out; if (type == __WASI_FILETYPE_DIRECTORY) { if (!mutex_init(&fo->directory.lock)) { - fd_object_release(fo); + fd_object_release(NULL, fo); return false; } fo->directory.handle = NULL; @@ -705,7 +715,7 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) rwlock_wrlock(&ft->lock); if (!fd_table_grow(ft, in, 1)) { rwlock_unlock(&ft->lock); - fd_object_release(fo); + fd_object_release(NULL, fo); return false; } @@ -729,16 +739,16 @@ fd_table_unused(struct fd_table *ft) REQUIRES_SHARED(ft->lock) // Inserts a file descriptor object into an unused slot of the file // descriptor table. static __wasi_errno_t -fd_table_insert(struct fd_table *ft, struct fd_object *fo, - __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, - __wasi_fd_t *out) REQUIRES_UNLOCKED(ft->lock) - UNLOCKS(fo->refcount) +fd_table_insert(wasm_exec_env_t exec_env, struct fd_table *ft, + struct fd_object *fo, __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, __wasi_fd_t *out) + REQUIRES_UNLOCKED(ft->lock) UNLOCKS(fo->refcount) { // Grow the file descriptor table if needed. rwlock_wrlock(&ft->lock); if (!fd_table_grow(ft, 0, 1)) { rwlock_unlock(&ft->lock); - fd_object_release(fo); + fd_object_release(exec_env, fo); return convert_errno(errno); } @@ -750,8 +760,8 @@ fd_table_insert(struct fd_table *ft, struct fd_object *fo, // Inserts a numerical file descriptor into the file descriptor table. static __wasi_errno_t -fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type, - __wasi_rights_t rights_base, +fd_table_insert_fd(wasm_exec_env_t exec_env, struct fd_table *ft, int in, + __wasi_filetype_t type, __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, __wasi_fd_t *out) REQUIRES_UNLOCKED(ft->lock) { @@ -766,12 +776,13 @@ fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type, fo->number = in; if (type == __WASI_FILETYPE_DIRECTORY) { if (!mutex_init(&fo->directory.lock)) { - fd_object_release(fo); + fd_object_release(exec_env, fo); return (__wasi_errno_t)-1; } fo->directory.handle = NULL; } - return fd_table_insert(ft, fo, rights_base, rights_inheriting, out); + return fd_table_insert(exec_env, ft, fo, rights_base, rights_inheriting, + out); } __wasi_errno_t @@ -821,8 +832,8 @@ wasmtime_ssp_fd_prestat_dir_name(struct fd_prestats *prestats, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_close(struct fd_table *curfds, struct fd_prestats *prestats, - __wasi_fd_t fd) +wasmtime_ssp_fd_close(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, __wasi_fd_t fd) { // Don't allow closing a pre-opened resource. // TODO: Eventually, we do want to permit this, once libpreopen in @@ -851,7 +862,7 @@ wasmtime_ssp_fd_close(struct fd_table *curfds, struct fd_prestats *prestats, struct fd_object *fo; fd_table_detach(ft, fd, &fo); rwlock_unlock(&ft->lock); - fd_object_release(fo); + fd_object_release(exec_env, fo); return 0; } @@ -894,7 +905,8 @@ fd_object_get(struct fd_table *curfds, struct fd_object **fo, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_datasync(struct fd_table *curfds, __wasi_fd_t fd) +wasmtime_ssp_fd_datasync(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd) { struct fd_object *fo; __wasi_errno_t error = @@ -907,15 +919,15 @@ wasmtime_ssp_fd_datasync(struct fd_table *curfds, __wasi_fd_t fd) #else int ret = fsync(fd_number(fo)); #endif - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_fd_pread(struct fd_table *curfds, __wasi_fd_t fd, - const __wasi_iovec_t *iov, size_t iovcnt, +wasmtime_ssp_fd_pread(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, __wasi_filesize_t offset, size_t *nread) { if (iovcnt == 0) @@ -928,17 +940,19 @@ wasmtime_ssp_fd_pread(struct fd_table *curfds, __wasi_fd_t fd, return error; #if CONFIG_HAS_PREADV - ssize_t len = preadv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, - (off_t)offset); - fd_object_release(fo); + ssize_t len = + blocking_op_preadv(exec_env, fd_number(fo), (const struct iovec *)iov, + (int)iovcnt, (off_t)offset); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nread = (size_t)len; return 0; #else if (iovcnt == 1) { - ssize_t len = pread(fd_number(fo), iov->buf, iov->buf_len, offset); - fd_object_release(fo); + ssize_t len = blocking_op_pread(exec_env, fd_number(fo), iov->buf, + iov->buf_len, offset); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nread = len; @@ -951,13 +965,14 @@ wasmtime_ssp_fd_pread(struct fd_table *curfds, __wasi_fd_t fd, totalsize += iov[i].buf_len; char *buf = wasm_runtime_malloc(totalsize); if (buf == NULL) { - fd_object_release(fo); + fd_object_release(exec_env, fo); return __WASI_ENOMEM; } // Perform a single read operation. - ssize_t len = pread(fd_number(fo), buf, totalsize, offset); - fd_object_release(fo); + ssize_t len = + blocking_op_pread(exec_env, fd_number(fo), buf, totalsize, offset); + fd_object_release(exec_env, fo); if (len < 0) { wasm_runtime_free(buf); return convert_errno(errno); @@ -985,9 +1000,10 @@ wasmtime_ssp_fd_pread(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_pwrite(struct fd_table *curfds, __wasi_fd_t fd, - const __wasi_ciovec_t *iov, size_t iovcnt, - __wasi_filesize_t offset, size_t *nwritten) +wasmtime_ssp_fd_pwrite(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_ciovec_t *iov, + size_t iovcnt, __wasi_filesize_t offset, + size_t *nwritten) { if (iovcnt == 0) return __WASI_EINVAL; @@ -1000,11 +1016,13 @@ wasmtime_ssp_fd_pwrite(struct fd_table *curfds, __wasi_fd_t fd, ssize_t len; #if CONFIG_HAS_PWRITEV - len = pwritev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, - (off_t)offset); + len = + blocking_op_pwritev(exec_env, fd_number(fo), (const struct iovec *)iov, + (int)iovcnt, (off_t)offset); #else if (iovcnt == 1) { - len = pwrite(fd_number(fo), iov->buf, iov->buf_len, offset); + len = blocking_op_pwrite(exec_env, fd_number(fo), iov->buf, + iov->buf_len, offset); } else { // Allocate a single buffer to fit all data. @@ -1013,7 +1031,7 @@ wasmtime_ssp_fd_pwrite(struct fd_table *curfds, __wasi_fd_t fd, totalsize += iov[i].buf_len; char *buf = wasm_runtime_malloc(totalsize); if (buf == NULL) { - fd_object_release(fo); + fd_object_release(exec_env, fo); return __WASI_ENOMEM; } size_t bufoff = 0; @@ -1024,11 +1042,12 @@ wasmtime_ssp_fd_pwrite(struct fd_table *curfds, __wasi_fd_t fd, } // Perform a single write operation. - len = pwrite(fd_number(fo), buf, totalsize, offset); + len = + blocking_op_pwrite(exec_env, fd_number(fo), buf, totalsize, offset); wasm_runtime_free(buf); } #endif - fd_object_release(fo); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nwritten = (size_t)len; @@ -1036,8 +1055,9 @@ wasmtime_ssp_fd_pwrite(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_read(struct fd_table *curfds, __wasi_fd_t fd, - const __wasi_iovec_t *iov, size_t iovcnt, size_t *nread) +wasmtime_ssp_fd_read(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, + size_t *nread) { struct fd_object *fo; __wasi_errno_t error = @@ -1045,8 +1065,9 @@ wasmtime_ssp_fd_read(struct fd_table *curfds, __wasi_fd_t fd, if (error != 0) return error; - ssize_t len = readv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); - fd_object_release(fo); + ssize_t len = blocking_op_readv(exec_env, fd_number(fo), + (const struct iovec *)iov, (int)iovcnt); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nread = (size_t)len; @@ -1054,8 +1075,9 @@ wasmtime_ssp_fd_read(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_renumber(struct fd_table *curfds, struct fd_prestats *prestats, - __wasi_fd_t from, __wasi_fd_t to) +wasmtime_ssp_fd_renumber(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, __wasi_fd_t from, + __wasi_fd_t to) { // Don't allow renumbering over a pre-opened resource. // TODO: Eventually, we do want to permit this, once libpreopen in @@ -1093,11 +1115,11 @@ wasmtime_ssp_fd_renumber(struct fd_table *curfds, struct fd_prestats *prestats, refcount_acquire(&fe_from->object->refcount); fd_table_attach(ft, to, fe_from->object, fe_from->rights_base, fe_from->rights_inheriting); - fd_object_release(fo); + fd_object_release(exec_env, fo); // Remove the old fd from the file descriptor table. fd_table_detach(ft, from, &fo); - fd_object_release(fo); + fd_object_release(exec_env, fo); --ft->used; rwlock_unlock(&ft->lock); @@ -1105,9 +1127,9 @@ wasmtime_ssp_fd_renumber(struct fd_table *curfds, struct fd_prestats *prestats, } __wasi_errno_t -wasmtime_ssp_fd_seek(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_filedelta_t offset, __wasi_whence_t whence, - __wasi_filesize_t *newoffset) +wasmtime_ssp_fd_seek(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filedelta_t offset, + __wasi_whence_t whence, __wasi_filesize_t *newoffset) { int nwhence; switch (whence) { @@ -1135,7 +1157,7 @@ wasmtime_ssp_fd_seek(struct fd_table *curfds, __wasi_fd_t fd, return error; off_t ret = lseek(fd_number(fo), offset, nwhence); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); *newoffset = (__wasi_filesize_t)ret; @@ -1143,8 +1165,8 @@ wasmtime_ssp_fd_seek(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_tell(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_filesize_t *newoffset) +wasmtime_ssp_fd_tell(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filesize_t *newoffset) { struct fd_object *fo; __wasi_errno_t error = @@ -1153,7 +1175,7 @@ wasmtime_ssp_fd_tell(struct fd_table *curfds, __wasi_fd_t fd, return error; off_t ret = lseek(fd_number(fo), 0, SEEK_CUR); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); *newoffset = (__wasi_filesize_t)ret; @@ -1161,8 +1183,8 @@ wasmtime_ssp_fd_tell(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_fdstat_get(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_fdstat_t *buf) +wasmtime_ssp_fd_fdstat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_fdstat_t *buf) { struct fd_table *ft = curfds; rwlock_rdlock(&ft->lock); @@ -1210,7 +1232,8 @@ wasmtime_ssp_fd_fdstat_get(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_fdstat_set_flags(struct fd_table *curfds, __wasi_fd_t fd, +wasmtime_ssp_fd_fdstat_set_flags(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_fdflags_t fs_flags) { int noflags = 0; @@ -1240,14 +1263,15 @@ wasmtime_ssp_fd_fdstat_set_flags(struct fd_table *curfds, __wasi_fd_t fd, return error; int ret = fcntl(fd_number(fo), F_SETFL, noflags); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_fd_fdstat_set_rights(struct fd_table *curfds, __wasi_fd_t fd, +wasmtime_ssp_fd_fdstat_set_rights(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_rights_t fs_rights_base, __wasi_rights_t fs_rights_inheriting) { @@ -1269,7 +1293,8 @@ wasmtime_ssp_fd_fdstat_set_rights(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_sync(struct fd_table *curfds, __wasi_fd_t fd) +wasmtime_ssp_fd_sync(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd) { struct fd_object *fo; __wasi_errno_t error = @@ -1278,15 +1303,15 @@ wasmtime_ssp_fd_sync(struct fd_table *curfds, __wasi_fd_t fd) return error; int ret = fsync(fd_number(fo)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_fd_write(struct fd_table *curfds, __wasi_fd_t fd, - const __wasi_ciovec_t *iov, size_t iovcnt, +wasmtime_ssp_fd_write(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, size_t *nwritten) { struct fd_object *fo; @@ -1318,7 +1343,7 @@ wasmtime_ssp_fd_write(struct fd_table *curfds, __wasi_fd_t fd, len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); } #endif /* end of BH_VPRINTF */ - fd_object_release(fo); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nwritten = (size_t)len; @@ -1326,9 +1351,9 @@ wasmtime_ssp_fd_write(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_advise(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_filesize_t offset, __wasi_filesize_t len, - __wasi_advice_t advice) +wasmtime_ssp_fd_advise(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filesize_t offset, + __wasi_filesize_t len, __wasi_advice_t advice) { #ifdef POSIX_FADV_NORMAL int nadvice; @@ -1362,7 +1387,7 @@ wasmtime_ssp_fd_advise(struct fd_table *curfds, __wasi_fd_t fd, return error; int ret = posix_fadvise(fd_number(fo), (off_t)offset, (off_t)len, nadvice); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret != 0) return convert_errno(ret); return 0; @@ -1392,8 +1417,9 @@ wasmtime_ssp_fd_advise(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_allocate(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_filesize_t offset, __wasi_filesize_t len) +wasmtime_ssp_fd_allocate(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filesize_t offset, + __wasi_filesize_t len) { struct fd_object *fo; __wasi_errno_t error = @@ -1414,7 +1440,7 @@ wasmtime_ssp_fd_allocate(struct fd_table *curfds, __wasi_fd_t fd, ret = ftruncate(fd_number(fo), newsize); #endif - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret != 0) return convert_errno(ret); return 0; @@ -1569,6 +1595,9 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, // components. In other words, a pathname component that must be a // directory. First attempt to obtain a directory file descriptor // for it. + // + // Note: we don't bother to use blocking_op_openat here + // because openat with O_DIRECTORY should not block. int newdir = #ifdef O_SEARCH openat(fds[curfd], file, O_SEARCH | O_DIRECTORY | O_NOFOLLOW); @@ -1702,7 +1731,7 @@ fail: close(fds[i]); for (size_t i = 0; i <= curpath; ++i) wasm_runtime_free(paths_start[i]); - fd_object_release(fo); + fd_object_release(NULL, fo); return error; #endif } @@ -1726,11 +1755,12 @@ path_put(struct path_access *pa) UNLOCKS(pa->fd_object->refcount) wasm_runtime_free(pa->path_start); if (fd_number(pa->fd_object) != pa->fd) close(pa->fd); - fd_object_release(pa->fd_object); + fd_object_release(NULL, pa->fd_object); } __wasi_errno_t -wasmtime_ssp_path_create_directory(struct fd_table *curfds, __wasi_fd_t fd, +wasmtime_ssp_path_create_directory(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, const char *path, size_t pathlen) { struct path_access pa; @@ -1775,11 +1805,11 @@ validate_path(const char *path, struct fd_prestats *pt) } __wasi_errno_t -wasmtime_ssp_path_link(struct fd_table *curfds, struct fd_prestats *prestats, - __wasi_fd_t old_fd, __wasi_lookupflags_t old_flags, - const char *old_path, size_t old_path_len, - __wasi_fd_t new_fd, const char *new_path, - size_t new_path_len) +wasmtime_ssp_path_link(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, __wasi_fd_t old_fd, + __wasi_lookupflags_t old_flags, const char *old_path, + size_t old_path_len, __wasi_fd_t new_fd, + const char *new_path, size_t new_path_len) { struct path_access old_pa; __wasi_errno_t error = @@ -1832,9 +1862,9 @@ wasmtime_ssp_path_link(struct fd_table *curfds, struct fd_prestats *prestats, } __wasi_errno_t -wasmtime_ssp_path_open(struct fd_table *curfds, __wasi_fd_t dirfd, - __wasi_lookupflags_t dirflags, const char *path, - size_t pathlen, __wasi_oflags_t oflags, +wasmtime_ssp_path_open(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, + const char *path, size_t pathlen, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base, __wasi_rights_t fs_rights_inheriting, __wasi_fdflags_t fs_flags, __wasi_fd_t *fd) @@ -1908,7 +1938,7 @@ wasmtime_ssp_path_open(struct fd_table *curfds, __wasi_fd_t dirfd, if (!pa.follow) noflags |= O_NOFOLLOW; - int nfd = openat(pa.fd, pa.path, noflags, 0666); + int nfd = blocking_op_openat(exec_env, pa.fd, pa.path, noflags, 0666); if (nfd < 0) { int openat_errno = errno; // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket. @@ -1965,7 +1995,8 @@ wasmtime_ssp_path_open(struct fd_table *curfds, __wasi_fd_t dirfd, rights_base |= (__wasi_rights_t)RIGHTS_REGULAR_FILE_BASE; } - return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base, + return fd_table_insert_fd(exec_env, curfds, nfd, type, + rights_base & max_base, rights_inheriting & max_inheriting, fd); } @@ -1984,9 +2015,9 @@ fd_readdir_put(void *buf, size_t bufsize, size_t *bufused, const void *elem, } __wasi_errno_t -wasmtime_ssp_fd_readdir(struct fd_table *curfds, __wasi_fd_t fd, void *buf, - size_t nbyte, __wasi_dircookie_t cookie, - size_t *bufused) +wasmtime_ssp_fd_readdir(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, void *buf, size_t nbyte, + __wasi_dircookie_t cookie, size_t *bufused) { struct fd_object *fo; __wasi_errno_t error = @@ -2002,7 +2033,7 @@ wasmtime_ssp_fd_readdir(struct fd_table *curfds, __wasi_fd_t fd, void *buf, dp = fdopendir(fd_number(fo)); if (dp == NULL) { mutex_unlock(&fo->directory.lock); - fd_object_release(fo); + fd_object_release(exec_env, fo); return convert_errno(errno); } fo->directory.handle = dp; @@ -2026,7 +2057,7 @@ wasmtime_ssp_fd_readdir(struct fd_table *curfds, __wasi_fd_t fd, void *buf, struct dirent *de = readdir(dp); if (de == NULL) { mutex_unlock(&fo->directory.lock); - fd_object_release(fo); + fd_object_release(exec_env, fo); return errno == 0 || *bufused > 0 ? 0 : convert_errno(errno); } fo->directory.offset = (__wasi_dircookie_t)telldir(dp); @@ -2075,14 +2106,14 @@ wasmtime_ssp_fd_readdir(struct fd_table *curfds, __wasi_fd_t fd, void *buf, fd_readdir_put(buf, nbyte, bufused, de->d_name, namlen); } mutex_unlock(&fo->directory.lock); - fd_object_release(fo); + fd_object_release(exec_env, fo); return 0; } __wasi_errno_t -wasmtime_ssp_path_readlink(struct fd_table *curfds, __wasi_fd_t fd, - const char *path, size_t pathlen, char *buf, - size_t bufsize, size_t *bufused) +wasmtime_ssp_path_readlink(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const char *path, size_t pathlen, + char *buf, size_t bufsize, size_t *bufused) { struct path_access pa; __wasi_errno_t error = path_get_nofollow( @@ -2103,10 +2134,10 @@ wasmtime_ssp_path_readlink(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_path_rename(struct fd_table *curfds, __wasi_fd_t old_fd, - const char *old_path, size_t old_path_len, - __wasi_fd_t new_fd, const char *new_path, - size_t new_path_len) +wasmtime_ssp_path_rename(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t old_fd, const char *old_path, + size_t old_path_len, __wasi_fd_t new_fd, + const char *new_path, size_t new_path_len) { struct path_access old_pa; __wasi_errno_t error = @@ -2148,8 +2179,8 @@ convert_stat(const struct stat *in, __wasi_filestat_t *out) } __wasi_errno_t -wasmtime_ssp_fd_filestat_get(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_filestat_t *buf) +wasmtime_ssp_fd_filestat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filestat_t *buf) { struct fd_object *fo; __wasi_errno_t error = @@ -2168,7 +2199,7 @@ wasmtime_ssp_fd_filestat_get(struct fd_table *curfds, __wasi_fd_t fd, } } buf->st_filetype = fo->type; - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; @@ -2218,7 +2249,8 @@ convert_utimens_arguments(__wasi_timestamp_t st_atim, } __wasi_errno_t -wasmtime_ssp_fd_filestat_set_size(struct fd_table *curfds, __wasi_fd_t fd, +wasmtime_ssp_fd_filestat_set_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_filesize_t st_size) { struct fd_object *fo; @@ -2228,14 +2260,15 @@ wasmtime_ssp_fd_filestat_set_size(struct fd_table *curfds, __wasi_fd_t fd, return error; int ret = ftruncate(fd_number(fo), (off_t)st_size); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_fd_filestat_set_times(struct fd_table *curfds, __wasi_fd_t fd, +wasmtime_ssp_fd_filestat_set_times(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, __wasi_fstflags_t fstflags) @@ -2256,14 +2289,15 @@ wasmtime_ssp_fd_filestat_set_times(struct fd_table *curfds, __wasi_fd_t fd, convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); int ret = futimens(fd_number(fo), ts); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_path_filestat_get(struct fd_table *curfds, __wasi_fd_t fd, +wasmtime_ssp_path_filestat_get(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, size_t pathlen, __wasi_filestat_t *buf) { @@ -2300,7 +2334,8 @@ wasmtime_ssp_path_filestat_get(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_path_filestat_set_times(struct fd_table *curfds, __wasi_fd_t fd, +wasmtime_ssp_path_filestat_set_times(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, size_t pathlen, __wasi_timestamp_t st_atim, @@ -2338,10 +2373,10 @@ wasmtime_ssp_path_filestat_set_times(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_path_symlink(struct fd_table *curfds, struct fd_prestats *prestats, - const char *old_path, size_t old_path_len, - __wasi_fd_t fd, const char *new_path, - size_t new_path_len) +wasmtime_ssp_path_symlink(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, const char *old_path, + size_t old_path_len, __wasi_fd_t fd, + const char *new_path, size_t new_path_len) { char *target = str_nullterminate(old_path, old_path_len); if (target == NULL) @@ -2373,8 +2408,8 @@ wasmtime_ssp_path_symlink(struct fd_table *curfds, struct fd_prestats *prestats, } __wasi_errno_t -wasmtime_ssp_path_unlink_file(struct fd_table *curfds, __wasi_fd_t fd, - const char *path, size_t pathlen) +wasmtime_ssp_path_unlink_file(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const char *path, size_t pathlen) { struct path_access pa; __wasi_errno_t error = path_get_nofollow( @@ -2407,7 +2442,8 @@ wasmtime_ssp_path_unlink_file(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_path_remove_directory(struct fd_table *curfds, __wasi_fd_t fd, +wasmtime_ssp_path_remove_directory(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, const char *path, size_t pathlen) { struct path_access pa; @@ -2433,7 +2469,7 @@ wasmtime_ssp_path_remove_directory(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_poll_oneoff(struct fd_table *curfds, +wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds, const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions, size_t *nevents) NO_LOCK_ANALYSIS @@ -2681,7 +2717,7 @@ wasmtime_ssp_poll_oneoff(struct fd_table *curfds, for (size_t i = 0; i < nsubscriptions; ++i) if (fos[i] != NULL) - fd_object_release(fos[i]); + fd_object_release(exec_env, fos[i]); wasm_runtime_free(fos); wasm_runtime_free(pfds); return error; @@ -2695,8 +2731,9 @@ wasmtime_ssp_random_get(void *buf, size_t nbyte) } __wasi_errno_t -wasi_ssp_sock_accept(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_fdflags_t flags, __wasi_fd_t *fd_new) +wasi_ssp_sock_accept(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_fdflags_t flags, + __wasi_fd_t *fd_new) { __wasi_filetype_t wasi_type; __wasi_rights_t max_base, max_inheriting; @@ -2709,8 +2746,9 @@ wasi_ssp_sock_accept(struct fd_table *curfds, __wasi_fd_t fd, goto fail; } - ret = os_socket_accept(fd_number(fo), &new_sock, NULL, NULL); - fd_object_release(fo); + ret = blocking_op_socket_accept(exec_env, fd_number(fo), &new_sock, NULL, + NULL); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { error = convert_errno(errno); goto fail; @@ -2722,7 +2760,7 @@ wasi_ssp_sock_accept(struct fd_table *curfds, __wasi_fd_t fd, goto fail; } - error = fd_table_insert_fd(curfds, new_sock, wasi_type, max_base, + error = fd_table_insert_fd(exec_env, curfds, new_sock, wasi_type, max_base, max_inheriting, fd_new); if (error != __WASI_ESUCCESS) { /* released in fd_table_insert_fd() */ @@ -2740,8 +2778,8 @@ fail: } __wasi_errno_t -wasi_ssp_sock_addr_local(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_addr_t *addr) +wasi_ssp_sock_addr_local(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_addr_t *addr) { struct fd_object *fo; bh_sockaddr_t bh_addr; @@ -2753,7 +2791,7 @@ wasi_ssp_sock_addr_local(struct fd_table *curfds, __wasi_fd_t fd, return error; ret = os_socket_addr_local(fd_number(fo), &bh_addr); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret != BHT_OK) { return convert_errno(errno); } @@ -2764,8 +2802,8 @@ wasi_ssp_sock_addr_local(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasi_ssp_sock_addr_remote(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_addr_t *addr) +wasi_ssp_sock_addr_remote(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_addr_t *addr) { struct fd_object *fo; bh_sockaddr_t bh_addr; @@ -2777,7 +2815,7 @@ wasi_ssp_sock_addr_remote(struct fd_table *curfds, __wasi_fd_t fd, return error; ret = os_socket_addr_remote(fd_number(fo), &bh_addr); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret != BHT_OK) { return convert_errno(errno); } @@ -2817,8 +2855,9 @@ wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen) } __wasi_errno_t -wasi_ssp_sock_bind(struct fd_table *curfds, struct addr_pool *addr_pool, - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_bind(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct addr_pool *addr_pool, __wasi_fd_t fd, + __wasi_addr_t *addr) { char buf[48] = { 0 }; struct fd_object *fo; @@ -2839,7 +2878,7 @@ wasi_ssp_sock_bind(struct fd_table *curfds, struct addr_pool *addr_pool, return error; ret = os_socket_bind(fd_number(fo), buf, &port); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -2848,9 +2887,9 @@ wasi_ssp_sock_bind(struct fd_table *curfds, struct addr_pool *addr_pool, } __wasi_errno_t -wasi_ssp_sock_addr_resolve(struct fd_table *curfds, char **ns_lookup_list, - const char *host, const char *service, - __wasi_addr_info_hints_t *hints, +wasi_ssp_sock_addr_resolve(wasm_exec_env_t exec_env, struct fd_table *curfds, + char **ns_lookup_list, const char *host, + const char *service, __wasi_addr_info_hints_t *hints, __wasi_addr_info_t *addr_info, __wasi_size_t addr_info_size, __wasi_size_t *max_info_size) @@ -2871,8 +2910,8 @@ wasi_ssp_sock_addr_resolve(struct fd_table *curfds, char **ns_lookup_list, return __WASI_EACCES; } - int ret = os_socket_addr_resolve( - host, service, + int ret = blocking_op_socket_addr_resolve( + exec_env, host, service, hints->hints_enabled && hints->type != SOCKET_ANY ? &hints_is_tcp : NULL, hints->hints_enabled && hints->family != INET_UNSPEC ? &hints_is_ipv4 @@ -2900,8 +2939,9 @@ wasi_ssp_sock_addr_resolve(struct fd_table *curfds, char **ns_lookup_list, } __wasi_errno_t -wasi_ssp_sock_connect(struct fd_table *curfds, struct addr_pool *addr_pool, - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_connect(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct addr_pool *addr_pool, __wasi_fd_t fd, + __wasi_addr_t *addr) { char buf[48] = { 0 }; struct fd_object *fo; @@ -2920,10 +2960,10 @@ wasi_ssp_sock_connect(struct fd_table *curfds, struct addr_pool *addr_pool, if (error != __WASI_ESUCCESS) return error; - ret = os_socket_connect(fd_number(fo), buf, - addr->kind == IPv4 ? addr->addr.ip4.port - : addr->addr.ip6.port); - fd_object_release(fo); + ret = blocking_op_socket_connect(exec_env, fd_number(fo), buf, + addr->kind == IPv4 ? addr->addr.ip4.port + : addr->addr.ip6.port); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -2932,7 +2972,8 @@ wasi_ssp_sock_connect(struct fd_table *curfds, struct addr_pool *addr_pool, } __wasi_errno_t -wasi_ssp_sock_get_recv_buf_size(struct fd_table *curfds, __wasi_fd_t fd, +wasi_ssp_sock_get_recv_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_size_t *size) { struct fd_object *fo; @@ -2945,7 +2986,7 @@ wasi_ssp_sock_get_recv_buf_size(struct fd_table *curfds, __wasi_fd_t fd, socklen_t optlen = sizeof(optval); ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval, &optlen); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -2956,8 +2997,8 @@ wasi_ssp_sock_get_recv_buf_size(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasi_ssp_sock_get_reuse_addr(struct fd_table *curfds, __wasi_fd_t fd, - uint8_t *reuse) +wasi_ssp_sock_get_reuse_addr(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t *reuse) { struct fd_object *fo; @@ -2970,7 +3011,7 @@ wasi_ssp_sock_get_reuse_addr(struct fd_table *curfds, __wasi_fd_t fd, socklen_t optlen = sizeof(optval); ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, &optlen); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -2981,8 +3022,8 @@ wasi_ssp_sock_get_reuse_addr(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasi_ssp_sock_get_reuse_port(struct fd_table *curfds, __wasi_fd_t fd, - uint8_t *reuse) +wasi_ssp_sock_get_reuse_port(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t *reuse) { struct fd_object *fo; int ret; @@ -3001,7 +3042,7 @@ wasi_ssp_sock_get_reuse_port(struct fd_table *curfds, __wasi_fd_t fd, optval = 0; #endif /* defined(SO_REUSEPORT) */ - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3012,7 +3053,8 @@ wasi_ssp_sock_get_reuse_port(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasi_ssp_sock_get_send_buf_size(struct fd_table *curfds, __wasi_fd_t fd, +wasi_ssp_sock_get_send_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_size_t *size) { struct fd_object *fo; @@ -3025,7 +3067,7 @@ wasi_ssp_sock_get_send_buf_size(struct fd_table *curfds, __wasi_fd_t fd, socklen_t optlen = sizeof(optval); ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval, &optlen); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3036,8 +3078,8 @@ wasi_ssp_sock_get_send_buf_size(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasi_ssp_sock_listen(struct fd_table *curfds, __wasi_fd_t fd, - __wasi_size_t backlog) +wasi_ssp_sock_listen(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_size_t backlog) { struct fd_object *fo; int ret; @@ -3047,7 +3089,7 @@ wasi_ssp_sock_listen(struct fd_table *curfds, __wasi_fd_t fd, return error; ret = os_socket_listen(fd_number(fo), backlog); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3056,9 +3098,9 @@ wasi_ssp_sock_listen(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasi_ssp_sock_open(struct fd_table *curfds, __wasi_fd_t poolfd, - __wasi_address_family_t af, __wasi_sock_type_t socktype, - __wasi_fd_t *sockfd) +wasi_ssp_sock_open(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t poolfd, __wasi_address_family_t af, + __wasi_sock_type_t socktype, __wasi_fd_t *sockfd) { bh_socket_t sock; bool is_tcp = SOCKET_DGRAM == socktype ? false : true; @@ -3090,7 +3132,7 @@ wasi_ssp_sock_open(struct fd_table *curfds, __wasi_fd_t poolfd, } // TODO: base rights and inheriting rights ? - error = fd_table_insert_fd(curfds, sock, wasi_type, max_base, + error = fd_table_insert_fd(exec_env, curfds, sock, wasi_type, max_base, max_inheriting, sockfd); if (error != __WASI_ESUCCESS) { return error; @@ -3100,7 +3142,8 @@ wasi_ssp_sock_open(struct fd_table *curfds, __wasi_fd_t poolfd, } __wasi_errno_t -wasi_ssp_sock_set_recv_buf_size(struct fd_table *curfds, __wasi_fd_t fd, +wasi_ssp_sock_set_recv_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_size_t size) { struct fd_object *fo; @@ -3113,7 +3156,7 @@ wasi_ssp_sock_set_recv_buf_size(struct fd_table *curfds, __wasi_fd_t fd, ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3122,8 +3165,8 @@ wasi_ssp_sock_set_recv_buf_size(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasi_ssp_sock_set_reuse_addr(struct fd_table *curfds, __wasi_fd_t fd, - uint8_t reuse) +wasi_ssp_sock_set_reuse_addr(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t reuse) { struct fd_object *fo; int ret; @@ -3135,7 +3178,7 @@ wasi_ssp_sock_set_reuse_addr(struct fd_table *curfds, __wasi_fd_t fd, ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3144,8 +3187,8 @@ wasi_ssp_sock_set_reuse_addr(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasi_ssp_sock_set_reuse_port(struct fd_table *curfds, __wasi_fd_t fd, - uint8_t reuse) +wasi_ssp_sock_set_reuse_port(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t reuse) { struct fd_object *fo; int ret; @@ -3163,7 +3206,7 @@ wasi_ssp_sock_set_reuse_port(struct fd_table *curfds, __wasi_fd_t fd, ret = BHT_ERROR; #endif /* defined(SO_REUSEPORT) */ - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3172,7 +3215,8 @@ wasi_ssp_sock_set_reuse_port(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasi_ssp_sock_set_send_buf_size(struct fd_table *curfds, __wasi_fd_t fd, +wasi_ssp_sock_set_send_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, __wasi_size_t size) { struct fd_object *fo; @@ -3186,7 +3230,7 @@ wasi_ssp_sock_set_send_buf_size(struct fd_table *curfds, __wasi_fd_t fd, ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3195,18 +3239,19 @@ wasi_ssp_sock_set_send_buf_size(struct fd_table *curfds, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_sock_recv(struct fd_table *curfds, __wasi_fd_t sock, void *buf, - size_t buf_len, size_t *recv_len) +wasmtime_ssp_sock_recv(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, void *buf, size_t buf_len, + size_t *recv_len) { __wasi_addr_t src_addr; - return wasmtime_ssp_sock_recv_from(curfds, sock, buf, buf_len, 0, &src_addr, - recv_len); + return wasmtime_ssp_sock_recv_from(exec_env, curfds, sock, buf, buf_len, 0, + &src_addr, recv_len); } __wasi_errno_t -wasmtime_ssp_sock_recv_from(struct fd_table *curfds, __wasi_fd_t sock, - void *buf, size_t buf_len, +wasmtime_ssp_sock_recv_from(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, void *buf, size_t buf_len, __wasi_riflags_t ri_flags, __wasi_addr_t *src_addr, size_t *recv_len) { @@ -3220,8 +3265,9 @@ wasmtime_ssp_sock_recv_from(struct fd_table *curfds, __wasi_fd_t sock, return error; } - ret = os_socket_recv_from(fd_number(fo), buf, buf_len, 0, &sockaddr); - fd_object_release(fo); + ret = blocking_op_socket_recv_from(exec_env, fd_number(fo), buf, buf_len, 0, + &sockaddr); + fd_object_release(exec_env, fo); if (-1 == ret) { return convert_errno(errno); } @@ -3233,8 +3279,9 @@ wasmtime_ssp_sock_recv_from(struct fd_table *curfds, __wasi_fd_t sock, } __wasi_errno_t -wasmtime_ssp_sock_send(struct fd_table *curfds, __wasi_fd_t sock, - const void *buf, size_t buf_len, size_t *sent_len) +wasmtime_ssp_sock_send(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, const void *buf, size_t buf_len, + size_t *sent_len) { struct fd_object *fo; __wasi_errno_t error; @@ -3246,7 +3293,7 @@ wasmtime_ssp_sock_send(struct fd_table *curfds, __wasi_fd_t sock, } ret = os_socket_send(fd_number(fo), buf, buf_len); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (-1 == ret) { return convert_errno(errno); } @@ -3256,8 +3303,9 @@ wasmtime_ssp_sock_send(struct fd_table *curfds, __wasi_fd_t sock, } __wasi_errno_t -wasmtime_ssp_sock_send_to(struct fd_table *curfds, struct addr_pool *addr_pool, - __wasi_fd_t sock, const void *buf, size_t buf_len, +wasmtime_ssp_sock_send_to(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct addr_pool *addr_pool, __wasi_fd_t sock, + const void *buf, size_t buf_len, __wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr, size_t *sent_len) { @@ -3282,8 +3330,9 @@ wasmtime_ssp_sock_send_to(struct fd_table *curfds, struct addr_pool *addr_pool, wasi_addr_to_bh_sockaddr(dest_addr, &sockaddr); - ret = os_socket_send_to(fd_number(fo), buf, buf_len, 0, &sockaddr); - fd_object_release(fo); + ret = blocking_op_socket_send_to(exec_env, fd_number(fo), buf, buf_len, 0, + &sockaddr); + fd_object_release(exec_env, fo); if (-1 == ret) { return convert_errno(errno); } @@ -3293,7 +3342,8 @@ wasmtime_ssp_sock_send_to(struct fd_table *curfds, struct addr_pool *addr_pool, } __wasi_errno_t -wasmtime_ssp_sock_shutdown(struct fd_table *curfds, __wasi_fd_t sock) +wasmtime_ssp_sock_shutdown(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock) { struct fd_object *fo; __wasi_errno_t error; @@ -3304,7 +3354,7 @@ wasmtime_ssp_sock_shutdown(struct fd_table *curfds, __wasi_fd_t sock) return error; ret = os_socket_shutdown(fd_number(fo)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); @@ -3396,7 +3446,7 @@ fd_table_destroy(struct fd_table *ft) if (ft->entries) { for (uint32 i = 0; i < ft->size; i++) { if (ft->entries[i].object != NULL) { - fd_object_release(ft->entries[i].object); + fd_object_release(NULL, ft->entries[i].object); } } rwlock_destroy(&ft->lock); @@ -3591,6 +3641,7 @@ addr_pool_destroy(struct addr_pool *addr_pool) // implementation #define WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(FUNC_NAME, OPTION_TYPE) \ __wasi_errno_t wasmtime_ssp_sock_##FUNC_NAME( \ + wasm_exec_env_t exec_env, \ WASMTIME_SSP_PASSTHROUGH_FD_TABLE __wasi_fd_t sock, \ OPTION_TYPE option) \ { \ @@ -3601,7 +3652,7 @@ addr_pool_destroy(struct addr_pool *addr_pool) if (error != 0) \ return error; \ ret = os_socket_##FUNC_NAME(fd_number(fo), option); \ - fd_object_release(fo); \ + fd_object_release(exec_env, fo); \ if (BHT_OK != ret) \ return convert_errno(errno); \ return __WASI_ESUCCESS; \ @@ -3644,8 +3695,8 @@ WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ipv6_only, bool *) #undef WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION __wasi_errno_t -wasmtime_ssp_sock_set_linger(struct fd_table *curfds, __wasi_fd_t sock, - bool is_enabled, int linger_s) +wasmtime_ssp_sock_set_linger(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, bool is_enabled, int linger_s) { struct fd_object *fo; __wasi_errno_t error; @@ -3655,15 +3706,15 @@ wasmtime_ssp_sock_set_linger(struct fd_table *curfds, __wasi_fd_t sock, return error; ret = os_socket_set_linger(fd_number(fo), is_enabled, linger_s); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); return __WASI_ESUCCESS; } __wasi_errno_t -wasmtime_ssp_sock_get_linger(struct fd_table *curfds, __wasi_fd_t sock, - bool *is_enabled, int *linger_s) +wasmtime_ssp_sock_get_linger(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, bool *is_enabled, int *linger_s) { struct fd_object *fo; __wasi_errno_t error; @@ -3673,7 +3724,7 @@ wasmtime_ssp_sock_get_linger(struct fd_table *curfds, __wasi_fd_t sock, return error; ret = os_socket_get_linger(fd_number(fo), is_enabled, linger_s); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); @@ -3681,7 +3732,8 @@ wasmtime_ssp_sock_get_linger(struct fd_table *curfds, __wasi_fd_t sock, } __wasi_errno_t -wasmtime_ssp_sock_set_ip_add_membership(struct fd_table *curfds, +wasmtime_ssp_sock_set_ip_add_membership(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface) @@ -3699,14 +3751,15 @@ wasmtime_ssp_sock_set_ip_add_membership(struct fd_table *curfds, is_ipv6 = imr_multiaddr->kind == IPv6; ret = os_socket_set_ip_add_membership(fd_number(fo), &addr_info, imr_interface, is_ipv6); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); return __WASI_ESUCCESS; } __wasi_errno_t -wasmtime_ssp_sock_set_ip_drop_membership(struct fd_table *curfds, +wasmtime_ssp_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface) @@ -3724,14 +3777,15 @@ wasmtime_ssp_sock_set_ip_drop_membership(struct fd_table *curfds, is_ipv6 = imr_multiaddr->kind == IPv6; ret = os_socket_set_ip_drop_membership(fd_number(fo), &addr_info, imr_interface, is_ipv6); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); return __WASI_ESUCCESS; } __wasi_errno_t -wasmtime_ssp_sock_set_ip_multicast_loop(struct fd_table *curfds, +wasmtime_ssp_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, bool ipv6, bool is_enabled) { @@ -3743,14 +3797,15 @@ wasmtime_ssp_sock_set_ip_multicast_loop(struct fd_table *curfds, return error; ret = os_socket_set_ip_multicast_loop(fd_number(fo), ipv6, is_enabled); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); return __WASI_ESUCCESS; } __wasi_errno_t -wasmtime_ssp_sock_get_ip_multicast_loop(struct fd_table *curfds, +wasmtime_ssp_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t sock, bool ipv6, bool *is_enabled) { @@ -3762,7 +3817,7 @@ wasmtime_ssp_sock_get_ip_multicast_loop(struct fd_table *curfds, return error; ret = os_socket_get_ip_multicast_loop(fd_number(fo), ipv6, is_enabled); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 06be3bc89..49545de72 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -1059,6 +1059,10 @@ set_thread_cancel_flags(WASMExecEnv *exec_env) WASM_SUSPEND_FLAG_TERMINATE); os_mutex_unlock(&exec_env->wait_lock); + +#ifdef OS_ENABLE_WAKEUP_BLOCKING_OP + wasm_runtime_interrupt_blocking_op(exec_env); +#endif } static void diff --git a/core/shared/platform/common/posix/posix_blocking_op.c b/core/shared/platform/common/posix/posix_blocking_op.c new file mode 100644 index 000000000..560828a06 --- /dev/null +++ b/core/shared/platform/common/posix/posix_blocking_op.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_extension.h" + +#ifdef OS_ENABLE_WAKEUP_BLOCKING_OP + +static bool g_blocking_op_inited = false; +static int g_blocking_op_signo = SIGUSR1; +static sigset_t g_blocking_op_sigmask; + +static void +blocking_op_sighandler(int signo) +{ + /* nothing */ +} + +void +os_set_signal_number_for_blocking_op(int signo) +{ + g_blocking_op_signo = signo; +} + +int +os_blocking_op_init() +{ + if (g_blocking_op_inited) { + return BHT_OK; + } + + sigemptyset(&g_blocking_op_sigmask); + sigaddset(&g_blocking_op_sigmask, g_blocking_op_signo); + + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = blocking_op_sighandler; + if (sigaction(g_blocking_op_signo, &sa, NULL)) { + return BHT_ERROR; + } + g_blocking_op_inited = true; + return BHT_OK; +} + +void +os_begin_blocking_op() +{ + pthread_sigmask(SIG_UNBLOCK, &g_blocking_op_sigmask, NULL); +} + +void +os_end_blocking_op() +{ + pthread_sigmask(SIG_BLOCK, &g_blocking_op_sigmask, NULL); +} + +int +os_wakeup_blocking_op(korp_tid tid) +{ + int ret = pthread_kill(tid, g_blocking_op_signo); + if (ret != 0) { + return BHT_ERROR; + } + return BHT_OK; +} + +#endif /* OS_ENABLE_WAKEUP_BLOCKING_OP */ diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index b1460f6b5..a0b184405 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -39,6 +39,9 @@ os_thread_wrapper(void *arg) #ifdef OS_ENABLE_HW_BOUND_CHECK if (os_thread_signal_init(handler) != 0) return NULL; +#endif +#ifdef OS_ENABLE_WAKEUP_BLOCKING_OP + os_end_blocking_op(); #endif start_func(thread_arg); #ifdef OS_ENABLE_HW_BOUND_CHECK diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index 3fd1c258e..5cd037a20 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -102,6 +102,12 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if WASM_DISABLE_WAKEUP_BLOCKING_OP != 0 +#define OS_ENABLE_WAKEUP_BLOCKING_OP +#endif +void +os_set_signal_number_for_blocking_op(int signo); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h index 7b4789c99..ed1d4efa4 100644 --- a/core/shared/platform/freebsd/platform_internal.h +++ b/core/shared/platform/freebsd/platform_internal.h @@ -101,6 +101,12 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if WASM_DISABLE_WAKEUP_BLOCKING_OP != 0 +#define OS_ENABLE_WAKEUP_BLOCKING_OP +#endif +void +os_set_signal_number_for_blocking_op(int signo); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 5b7b556e0..06bd9ee89 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -323,6 +323,34 @@ os_sem_getvalue(korp_sem *sem, int *sval); int os_sem_unlink(const char *name); +/** + * Initialize process-global state for os_wakeup_blocking_op. + */ +int +os_blocking_op_init(); + +/** + * Start accepting os_wakeup_blocking_op requests for the calling thread. + */ +void +os_begin_blocking_op(); + +/** + * Stop accepting os_wakeup_blocking_op requests for the calling thread. + */ +void +os_end_blocking_op(); + +/** + * Wake up the specified thread. + * + * For example, on posix-like platforms, this can be implemented by + * sending a signal (w/o SA_RESTART) which interrupts a blocking + * system call. + */ +int +os_wakeup_blocking_op(korp_tid tid); + /**************************************************** * Section 2 * * Socket support * diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index 8439f8723..222a6fc57 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -115,6 +115,12 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if WASM_DISABLE_WAKEUP_BLOCKING_OP != 0 +#define OS_ENABLE_WAKEUP_BLOCKING_OP +#endif +void +os_set_signal_number_for_blocking_op(int signo); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/nuttx/platform_internal.h b/core/shared/platform/nuttx/platform_internal.h index b5bbdacd0..c53857e0f 100644 --- a/core/shared/platform/nuttx/platform_internal.h +++ b/core/shared/platform/nuttx/platform_internal.h @@ -123,6 +123,12 @@ utimensat(int fd, const char *path, const struct timespec ts[2], int flag); DIR * fdopendir(int fd); +#if WASM_DISABLE_WAKEUP_BLOCKING_OP != 0 +#define OS_ENABLE_WAKEUP_BLOCKING_OP +#endif +void +os_set_signal_number_for_blocking_op(int signo); + #ifdef __cplusplus } #endif diff --git a/doc/build_wamr.md b/doc/build_wamr.md index 81b4f6211..9938eadcb 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -109,6 +109,10 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_DISABLE_STACK_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform, same as `WAMR_DISABLE_HW_BOUND_CHECK`. > Note: When boundary check with hardware trap is disabled, or `WAMR_DISABLE_HW_BOUND_CHECK` is set to 1, the native stack boundary check with hardware trap will be disabled too, no matter what value is set to `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. And when boundary check with hardware trap is enabled, the status of this feature is set according to the value of `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. +#### **Disable async wakeup of blocking operation** +- **WAMR_DISABLE_WAKEUP_BLOCKING_OP**=1/0, default to enable if supported by the platform +> Note: The feature helps async termination of blocking threads. If you disable it, the runtime can wait for termination of blocking threads possibly forever. + #### **Enable tail call feature** - **WAMR_BUILD_TAIL_CALL**=1/0, default to disable if not set diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index e5af62cc8..04a6db91f 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -246,6 +246,7 @@ ifeq ($(CONFIG_INTERPRETERS_WAMR_LIBC_WASI),y) CFLAGS += -DWASM_ENABLE_LIBC_WASI=1 CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/include +CSRCS += blocking_op.c CSRCS += posix_socket.c CSRCS += libc_wasi_wrapper.c VPATH += $(IWASM_ROOT)/libraries/libc-wasi @@ -309,6 +310,9 @@ CFLAGS += -DWASM_DISABLE_HW_BOUND_CHECK=0 CFLAGS += -DWASM_DISABLE_STACK_HW_BOUND_CHECK=0 endif +# REVISIT: is this worth to have a Kconfig? +CFLAGS += -DWASM_DISABLE_WAKEUP_BLOCKING_OP=0 + ifeq ($(CONFIG_INTERPRETERS_WAMR_CUSTOM_NAME_SECTIONS),y) CFLAGS += -DWASM_ENABLE_CUSTOM_NAME_SECTION=1 else @@ -354,8 +358,10 @@ CFLAGS += -I$(IWASM_ROOT)/interpreter endif CSRCS += nuttx_platform.c \ + posix_blocking_op.c \ posix_thread.c \ posix_time.c \ + posix_sleep.c \ mem_alloc.c \ ems_kfc.c \ ems_alloc.c \ @@ -370,6 +376,7 @@ CSRCS += nuttx_platform.c \ bh_read_file.c \ runtime_timer.c \ wasm_application.c \ + wasm_blocking_op.c \ wasm_runtime_common.c \ wasm_native.c \ wasm_exec_env.c \ From 6fca48d8e6b85c69d18a795daef64bae13e9cb62 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 21 Sep 2023 12:56:21 +0900 Subject: [PATCH 106/123] Fix inverted WASM_DISABLE_WAKEUP_BLOCKING_OP checks (#2571) --- core/shared/platform/darwin/platform_internal.h | 2 +- core/shared/platform/freebsd/platform_internal.h | 2 +- core/shared/platform/linux/platform_internal.h | 2 +- core/shared/platform/nuttx/platform_internal.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index 5cd037a20..d72d48b53 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -102,7 +102,7 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ -#if WASM_DISABLE_WAKEUP_BLOCKING_OP != 0 +#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 #define OS_ENABLE_WAKEUP_BLOCKING_OP #endif void diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h index ed1d4efa4..50cabd344 100644 --- a/core/shared/platform/freebsd/platform_internal.h +++ b/core/shared/platform/freebsd/platform_internal.h @@ -101,7 +101,7 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ -#if WASM_DISABLE_WAKEUP_BLOCKING_OP != 0 +#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 #define OS_ENABLE_WAKEUP_BLOCKING_OP #endif void diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index 222a6fc57..337cdd9cc 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -115,7 +115,7 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ -#if WASM_DISABLE_WAKEUP_BLOCKING_OP != 0 +#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 #define OS_ENABLE_WAKEUP_BLOCKING_OP #endif void diff --git a/core/shared/platform/nuttx/platform_internal.h b/core/shared/platform/nuttx/platform_internal.h index c53857e0f..97ab5f697 100644 --- a/core/shared/platform/nuttx/platform_internal.h +++ b/core/shared/platform/nuttx/platform_internal.h @@ -123,7 +123,7 @@ utimensat(int fd, const char *path, const struct timespec ts[2], int flag); DIR * fdopendir(int fd); -#if WASM_DISABLE_WAKEUP_BLOCKING_OP != 0 +#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 #define OS_ENABLE_WAKEUP_BLOCKING_OP #endif void From c7a7db21b787eda010bb7c52ce33867a8c26f928 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 21 Sep 2023 14:32:08 +0900 Subject: [PATCH 107/123] export_native_api.md: Add a note about thread termination (#2572) --- doc/export_native_api.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/export_native_api.md b/doc/export_native_api.md index b87d92552..e293e5c0d 100644 --- a/doc/export_native_api.md +++ b/doc/export_native_api.md @@ -261,4 +261,32 @@ wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size) ``` +## Native API implementation notes +### Async thread termination + +When threading support is enabled, a thread can be requested to terminate +itself either explicitly by the `wasm_runtime_terminate` API or implicitly +by cluster-wide activities like WASI `proc_exit`. +If a call to your native function can take long or even forever, +you should make it to respond to termination requests in a timely manner. +There are a few implementation approaches for that: + +* Design your API so that it always returns in a timely manner. + This is the most simple approach when possible. + +* Make your native function check the cluster state by calling + `wasm_cluster_is_thread_terminated` from time to time. + If `wasm_cluster_is_thread_terminated` returns true, make your + native function return. + Note: as of writing this, `wasm_cluster_is_thread_terminated` is not + exported as a runtime API. + +* If your native function is a simple wrapper of blocking system call, + you can probably use the `wasm_runtime_begin_blocking_op` and + `wasm_runtime_end_blocking_op` runtime API. + See the comment in `wamr_export.h` for details. + +* If your native function is very complex, it might be simpler to put the + guts of it into a separate worker process so that it can be cleaned up + by simply killing it. From 47daaeecc7fcd22f4f26b5e229f6ec3dc2602b65 Mon Sep 17 00:00:00 2001 From: ZHU Hao Date: Thu, 21 Sep 2023 13:33:03 +0800 Subject: [PATCH 108/123] Fix compiling error for RT-Thread (#2569) struct dfs_fd has been deprecated --- product-mini/platforms/rt-thread/iwasm.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/product-mini/platforms/rt-thread/iwasm.c b/product-mini/platforms/rt-thread/iwasm.c index 8ae4da761..9a21301d8 100644 --- a/product-mini/platforms/rt-thread/iwasm.c +++ b/product-mini/platforms/rt-thread/iwasm.c @@ -10,7 +10,6 @@ #include #include #include -#include #ifdef WAMR_ENABLE_RTT_EXPORT @@ -183,8 +182,6 @@ rt_uint8_t * my_read_file_to_buffer(char *filename, rt_uint32_t *size) { struct stat f_stat; - dfs_file_stat(filename, &f_stat); - struct dfs_fd fd; rt_uint8_t *buff = rt_malloc(f_stat.st_size); *size = 0; @@ -193,16 +190,16 @@ my_read_file_to_buffer(char *filename, rt_uint32_t *size) return RT_NULL; } - int ret = dfs_file_open(&fd, filename, O_RDONLY); - if (ret) { + int fd = open(filename, O_RDONLY); + if (fd < 0) { rt_free(buff); - rt_set_errno(ret); + rt_set_errno(fd); return RT_NULL; } - *size = dfs_file_read(&fd, buff, f_stat.st_size); + *size = read(fd, buff, f_stat.st_size); - dfs_file_close(&fd); + close(fd); if (*size != f_stat.st_size) { rt_free(buff); From cf97ee081f0efce4ed34a7858eb763beb5998676 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 21 Sep 2023 19:39:12 +0900 Subject: [PATCH 109/123] test_wamr.sh: Print a bit more meaningful message (#2574) --- tests/wamr-test-suites/test_wamr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index f33655207..06231f1e1 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -508,7 +508,7 @@ function wasi_certification_test() cd ${WORK_DIR} if [ ! -d "wasi-testsuite" ]; then - echo "wasi not exist, clone it from github" + echo "wasi-testsuite not exist, clone it from github" git clone -b prod/testsuite-all \ --single-branch https://github.com/WebAssembly/wasi-testsuite.git fi From 0677288f2216dfef86fed6d85bbd110ab668bd27 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 22 Sep 2023 09:57:48 +0900 Subject: [PATCH 110/123] run_wasi_tests.sh: Provide stdin by ourselves (#2576) This improves test consistency between typical local environments and github runners. This is necessary for some of latest wasi-threads tests. cf. https://github.com/yamt/toywasm/commit/570e6706312cbdccb9d5268347186b441a24444b --- .../wamr-test-suites/wasi-test-script/pipe.py | 19 +++++++++++++++++++ .../wasi-test-script/run_wasi_tests.sh | 7 +++++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/wamr-test-suites/wasi-test-script/pipe.py diff --git a/tests/wamr-test-suites/wasi-test-script/pipe.py b/tests/wamr-test-suites/wasi-test-script/pipe.py new file mode 100644 index 000000000..e37408717 --- /dev/null +++ b/tests/wamr-test-suites/wasi-test-script/pipe.py @@ -0,0 +1,19 @@ +#! /usr/bin/env python3 + +# Copyright (C) 2023 YAMAMOTO Takashi +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This is a copy of https://github.com/yamt/toywasm/blob/master/test/pipe.py + +# keep stdout open until the peer closes it + +import sys +import select + +p = select.poll() +p.register(sys.stdout, select.POLLHUP) +# http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=57369 +while True: + l = p.poll(1) + if l: + break diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index 37607859b..03ad9e27a 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -5,6 +5,8 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # +THIS_DIR=$(cd $(dirname $0) && pwd -P) + readonly MODE=$1 readonly TARGET=$2 @@ -63,7 +65,8 @@ if [[ $MODE != "aot" ]];then python3 -m venv wasi-env && source wasi-env/bin/activate python3 -m pip install -r test-runner/requirements.txt - TEST_RUNTIME_EXE="${IWASM_CMD}" python3 test-runner/wasi_test_runner.py \ + export TEST_RUNTIME_EXE="${IWASM_CMD}" + python3 ${THIS_DIR}/pipe.py | python3 test-runner/wasi_test_runner.py \ -r adapters/wasm-micro-runtime.py \ -t \ ${C_TESTS} \ @@ -100,4 +103,4 @@ else done fi -exit ${exit_code} \ No newline at end of file +exit ${exit_code} From 06527f724e8b0bc79cdf8e73f78749e4caa9490f Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Fri, 22 Sep 2023 02:11:25 +0100 Subject: [PATCH 111/123] Remove provision of unnecessary fd rights (#2579) The WASI docs allow for fewer rights to be applied to an fd than requested but not more. This behavior is also asserted in the rust WASI tests, so it's necessary for those to pass as well. --- .../sandboxed-system-primitives/src/posix.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index c096511c9..bb6d67a62 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -1981,20 +1981,6 @@ wasmtime_ssp_path_open(wasm_exec_env_t exec_env, struct fd_table *curfds, return error; } - { - struct stat sb; - - if (fstat(nfd, &sb) < 0) { - close(nfd); - return convert_errno(errno); - } - - if (S_ISDIR(sb.st_mode)) - rights_base |= (__wasi_rights_t)RIGHTS_DIRECTORY_BASE; - else if (S_ISREG(sb.st_mode)) - rights_base |= (__wasi_rights_t)RIGHTS_REGULAR_FILE_BASE; - } - return fd_table_insert_fd(exec_env, curfds, nfd, type, rights_base & max_base, rights_inheriting & max_inheriting, fd); From 71e07a7fa42e3a3dd2ba7c1b869fe9d7a0af5a7c Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Sat, 23 Sep 2023 09:06:35 +0800 Subject: [PATCH 112/123] Fix potential unaligned store issue when extra return value is v128 (#2583) Unaligned store v128 value to the AOT function argument of the pointer for the extra return value may cause segmentation fault. Fix the issue reported in #2556. --- core/iwasm/compilation/aot_emit_control.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index 2cf51cf67..75d1e622e 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -234,13 +234,15 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, else { /* Store extra return values to function parameters */ if (i != 0) { + LLVMValueRef res; uint32 param_index = func_type->param_count + i; - if (!LLVMBuildStore( - comp_ctx->builder, block->result_phis[i], - LLVMGetParam(func_ctx->func, param_index))) { + if (!(res = LLVMBuildStore( + comp_ctx->builder, block->result_phis[i], + LLVMGetParam(func_ctx->func, param_index)))) { aot_set_last_error("llvm build store failed."); goto fail; } + LLVMSetAlignment(res, 1); } } } @@ -1102,14 +1104,17 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (block_func->result_count) { /* Store extra result values to function parameters */ for (i = 0; i < block_func->result_count - 1; i++) { + LLVMValueRef res; result_index = block_func->result_count - 1 - i; POP(value, block_func->result_types[result_index]); param_index = func_type->param_count + result_index; - if (!LLVMBuildStore(comp_ctx->builder, value, - LLVMGetParam(func_ctx->func, param_index))) { + if (!(res = LLVMBuildStore( + comp_ctx->builder, value, + LLVMGetParam(func_ctx->func, param_index)))) { aot_set_last_error("llvm build store failed."); goto fail; } + LLVMSetAlignment(res, 1); } /* Return the first result value */ POP(value, block_func->result_types[0]); From 363f08975bc23b53b829d8a3ddf78dec3a8112ab Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Sat, 23 Sep 2023 11:28:18 +0900 Subject: [PATCH 113/123] Fix a few issues in "run_wasi_tests.sh: provide stdin by ourselves" (#2582) Apply "provide stdin by ourselves" to the aot case and check the correct exit code. --- tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index 03ad9e27a..c4b27390e 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -51,8 +51,8 @@ run_aot_tests () { expected=$(jq .exit_code ${test_json}) fi - ${iwasm} $test_aot - ret=${PIPESTATUS[0]} + python3 ${THIS_DIR}/pipe.py | ${iwasm} $test_aot + ret=${PIPESTATUS[1]} echo "expected=$expected, actual=$ret" if [[ $expected != "" ]] && [[ $expected != $ret ]];then @@ -75,7 +75,7 @@ if [[ $MODE != "aot" ]];then ${THREAD_INTERNAL_TESTS} \ ${LIB_SOCKET_TESTS} \ - ret=${PIPESTATUS[0]} + ret=${PIPESTATUS[1]} TEST_RUNTIME_EXE="${IWASM_CMD_STRESS}" python3 test-runner/wasi_test_runner.py \ -r adapters/wasm-micro-runtime.py \ From f474f3d6689ed013ef1753d8b40c5cc967b1db42 Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Mon, 25 Sep 2023 11:40:12 +0100 Subject: [PATCH 114/123] Return __WASI_EINVAL from fd_prestat_dir_name (#2580) Return a WASI error code (rather than a host POSIX one). In addition, there is no need to return an error in the case that the provided buffer is too large. --- .../libc-wasi/sandboxed-system-primitives/src/posix.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index bb6d67a62..fc6bc2839 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -819,12 +819,14 @@ wasmtime_ssp_fd_prestat_dir_name(struct fd_prestats *prestats, __wasi_fd_t fd, rwlock_unlock(&prestats->lock); return error; } - if (path_len != strlen(prestat->dir)) { + + const size_t prestat_dir_len = strlen(prestat->dir); + if (path_len < prestat_dir_len) { rwlock_unlock(&prestats->lock); - return EINVAL; + return __WASI_EINVAL; } - bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)path_len); + bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)prestat_dir_len); rwlock_unlock(&prestats->lock); From 99b47fd33429a4ca999d53d85f5b00302b991191 Mon Sep 17 00:00:00 2001 From: "Alfred E. Neumayer" Date: Mon, 25 Sep 2023 13:00:46 +0200 Subject: [PATCH 115/123] Support AOT compiler with LLVM 17 (#2567) Adapt API usage to new interfaces where applicable, including LLVM function usage, obsoleted llvm::Optional type and removal of unavailable headers. Know issues: - AOT static PGO isn't enabled - LLVM JIT may run failed due to llvm_orc_registerEHFrameSectionWrapper isn't linked into iwasm --- core/iwasm/compilation/aot_llvm.c | 10 +++++++- core/iwasm/compilation/aot_llvm.h | 5 +++- core/iwasm/compilation/aot_llvm_extra.cpp | 27 +++++++++++++++++++++- core/iwasm/compilation/aot_llvm_extra2.cpp | 9 ++++++++ core/iwasm/compilation/aot_orc_extra.cpp | 9 ++++++++ 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index f4bc8500e..6dc3a0f7d 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -526,12 +526,18 @@ aot_add_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module, } wasm_runtime_free(params); params = NULL; + +#if LLVM_VERSION_MAJOR < 17 if (aot_target_precheck_can_use_musttail(comp_ctx)) { LLVMSetTailCallKind(retval, LLVMTailCallKindMustTail); } else { LLVMSetTailCallKind(retval, LLVMTailCallKindTail); } +#else + LLVMSetTailCall(retval, true); +#endif + if (ret_type == VOID_TYPE) { if (!LLVMBuildRetVoid(b)) { goto fail; @@ -2172,8 +2178,10 @@ bool aot_compiler_init(void) { /* Initialize LLVM environment */ - +#if LLVM_VERSION_MAJOR < 17 LLVMInitializeCore(LLVMGetGlobalPassRegistry()); +#endif + #if WASM_ENABLE_WAMR_COMPILER != 0 /* Init environment of all targets for AOT compiler */ LLVMInitializeAllTargetInfos(); diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 03994b6c0..b46ac3bd0 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -15,15 +15,18 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Analysis.h" #include "llvm-c/BitWriter.h" +#if LLVM_VERSION_MAJOR < 17 #include "llvm-c/Transforms/Utils.h" #include "llvm-c/Transforms/Scalar.h" #include "llvm-c/Transforms/Vectorize.h" #include "llvm-c/Transforms/PassManagerBuilder.h" +#include "llvm-c/Initialization.h" +#endif #include "llvm-c/Orc.h" #include "llvm-c/Error.h" #include "llvm-c/Support.h" -#include "llvm-c/Initialization.h" + #include "llvm-c/TargetMachine.h" #include "llvm-c/LLJIT.h" #if WASM_ENABLE_DEBUG_AOT != 0 diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index 898fabd8c..ab6c621a0 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -5,11 +5,13 @@ #include #include +#if LLVM_VERSION_MAJOR < 17 #include #include +#include +#endif #include #include -#include #include #include #include @@ -18,7 +20,9 @@ #include #include #include +#if LLVM_VERSION_MAJOR < 17 #include +#endif #include #include #include @@ -30,6 +34,9 @@ #include #include #include +#if LLVM_VERSION_MAJOR >= 17 +#include +#endif #include #include #include @@ -55,6 +62,13 @@ using namespace llvm; using namespace llvm::orc; +#if LLVM_VERSION_MAJOR >= 17 +namespace llvm { +template +using Optional = std::optional; +} +#endif + LLVM_C_EXTERN_C_BEGIN bool @@ -110,7 +124,14 @@ ExpandMemoryOpPass::run(Function &F, FunctionAnalysisManager &AM) Memcpy->eraseFromParent(); } else if (MemMoveInst *Memmove = dyn_cast(MemCall)) { +#if LLVM_VERSION_MAJOR >= 17 + Function *ParentFunc = Memmove->getParent()->getParent(); + const TargetTransformInfo &TTI = + AM.getResult(*ParentFunc); + expandMemMoveAsLoop(Memmove, TTI); +#else expandMemMoveAsLoop(Memmove); +#endif Memmove->eraseFromParent(); } else if (MemSetInst *Memset = dyn_cast(MemCall)) { @@ -181,6 +202,9 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) #else Optional PGO = llvm::None; #endif + +// TODO +#if LLVM_VERSION_MAJOR < 17 if (comp_ctx->enable_llvm_pgo) { /* Disable static counter allocation for value profiler, it will be allocated by runtime */ @@ -191,6 +215,7 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) else if (comp_ctx->use_prof_file) { PGO = PGOOptions(comp_ctx->use_prof_file, "", "", PGOOptions::IRUse); } +#endif #ifdef DEBUG_PASS PassInstrumentationCallbacks PIC; diff --git a/core/iwasm/compilation/aot_llvm_extra2.cpp b/core/iwasm/compilation/aot_llvm_extra2.cpp index 42e53ddfa..8364e5ebf 100644 --- a/core/iwasm/compilation/aot_llvm_extra2.cpp +++ b/core/iwasm/compilation/aot_llvm_extra2.cpp @@ -4,8 +4,10 @@ */ #include +#if LLVM_VERSION_MAJOR < 17 #include #include +#endif #include #if LLVM_VERSION_MAJOR >= 14 #include @@ -18,6 +20,13 @@ #include "aot_llvm_extra2.h" +#if LLVM_VERSION_MAJOR >= 17 +namespace llvm { +template +using Optional = std::optional; +} +#endif + static llvm::Optional convert(LLVMRelocMode reloc_mode) { diff --git a/core/iwasm/compilation/aot_orc_extra.cpp b/core/iwasm/compilation/aot_orc_extra.cpp index 9cfe331e5..51d61bf3c 100644 --- a/core/iwasm/compilation/aot_orc_extra.cpp +++ b/core/iwasm/compilation/aot_orc_extra.cpp @@ -8,8 +8,10 @@ #include "llvm-c/OrcEE.h" #include "llvm-c/TargetMachine.h" +#if LLVM_VERSION_MAJOR < 17 #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#endif #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" @@ -21,6 +23,13 @@ #include "aot_orc_extra.h" #include "aot.h" +#if LLVM_VERSION_MAJOR >= 17 +namespace llvm { +template +using Optional = std::optional; +} +#endif + using namespace llvm; using namespace llvm::orc; using GlobalValueSet = std::set; From efb5cca93d6a72da9f23de59e573326a9c5ff8bc Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 25 Sep 2023 20:25:01 +0800 Subject: [PATCH 116/123] Fix compile error of tsf benchmark (#2588) Explicitly declare readdir_r in gpc_code_gen_util.c. --- tests/benchmarks/jetstream/tsf.patch | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tests/benchmarks/jetstream/tsf.patch b/tests/benchmarks/jetstream/tsf.patch index e52c3cdc5..98355b08c 100644 --- a/tests/benchmarks/jetstream/tsf.patch +++ b/tests/benchmarks/jetstream/tsf.patch @@ -1,6 +1,18 @@ +diff -urN tsf-src-org/gpc_code_gen_util.c tsf-src/gpc_code_gen_util.c +--- tsf-src-org/gpc_code_gen_util.c 2023-09-21 11:12:40.211166472 +0800 ++++ tsf-src/gpc_code_gen_util.c 2023-09-21 11:09:13.643170967 +0800 +@@ -34,6 +34,8 @@ + #include + #include + ++int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); ++ + /* code generation debugging */ + + /* NOTE: It is now the case that the count may be incremented multiple times, diff -urN tsf-src-org/tsf_internal.h tsf-src/tsf_internal.h ---- tsf-src-org/tsf_internal.h 2023-03-31 10:49:45.000000000 +0800 -+++ tsf-src/tsf_internal.h 2023-05-11 08:18:35.000000000 +0800 +--- tsf-src-org/tsf_internal.h 2023-09-21 11:11:50.843167546 +0800 ++++ tsf-src/tsf_internal.h 2023-09-21 11:06:53.031174027 +0800 @@ -429,6 +429,7 @@ #endif tsf_fsdb_connection_t *connection; @@ -10,15 +22,15 @@ diff -urN tsf-src-org/tsf_internal.h tsf-src/tsf_internal.h } u; tsf_limits_t *limits; diff -urN tsf-src-org/tsf_ir_speed.c tsf-src/tsf_ir_speed.c ---- tsf-src-org/tsf_ir_speed.c 2023-03-31 10:49:45.000000000 +0800 -+++ tsf-src/tsf_ir_speed.c 2023-05-11 08:18:35.000000000 +0800 +--- tsf-src-org/tsf_ir_speed.c 2023-09-21 11:12:15.699167005 +0800 ++++ tsf-src/tsf_ir_speed.c 2023-09-21 11:06:53.031174027 +0800 @@ -63,6 +63,9 @@ Program_t *program; unsigned elementIndex; - + + if (!(programIndex % 100)) + printf("##programIndex: %u\n", programIndex); + CS(program = tsf_region_create(sizeof(Program_t))); - + program->globals.len = numDecls + numDefns; From 94f276eab0c296db1ac0486322e2094238557501 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 26 Sep 2023 10:20:13 +0900 Subject: [PATCH 117/123] test_wamr.sh: Bump wasi-testsuite version (#2568) On posix-like platforms, the rest of wasi-threads tests should pass after the recent changes including the following PRs: #2516, #2524, #2529, #2571, #2576 and #2582. --- tests/wamr-test-suites/test_wamr.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 06231f1e1..11650651c 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -55,7 +55,8 @@ PLATFORM=$(uname -s | tr A-Z a-z) PARALLELISM=0 ENABLE_QEMU=0 QEMU_FIRMWARE="" -WASI_TESTSUITE_COMMIT="aca78d919355ae00af141e6741a439039615b257" +# prod/testsuite-all branch +WASI_TESTSUITE_COMMIT="cf64229727f71043d5849e73934e249e12cb9e06" while getopts ":s:cabgvt:m:MCpSXxwPGQF:" opt do From 913a1414ad8351385370948784490fa66aa4da69 Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Tue, 26 Sep 2023 02:31:32 +0100 Subject: [PATCH 118/123] Add support for closing/renumbering preopen fds (#2578) There doesn't appear to be a clear reason not to support this behavior. It seems it was disallowed previously as a precaution. See https://github.com/bytecodealliance/wasmtime/commit/67e2e57b02cd244c004379690aa56d3d5e187153 for more context. --- .../sandboxed-system-primitives/src/posix.c | 152 +++++++++++++----- 1 file changed, 108 insertions(+), 44 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index fc6bc2839..eda65b8da 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -339,7 +339,7 @@ fd_prestats_init(struct fd_prestats *pt) // Grows the preopened resource table to a required lower bound and a // minimum number of free preopened resource table entries. -static bool +static __wasi_errno_t fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr) REQUIRES_EXCLUSIVE(pt->lock) { @@ -353,7 +353,7 @@ fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr) struct fd_prestat *prestats = wasm_runtime_malloc((uint32)(sizeof(*prestats) * size)); if (prestats == NULL) - return false; + return __WASI_ENOMEM; if (pt->prestats && pt->size > 0) { bh_memcpy_s(prestats, (uint32)(sizeof(*prestats) * size), @@ -369,27 +369,39 @@ fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr) pt->prestats = prestats; pt->size = size; } - return true; + return __WASI_ESUCCESS; +} + +static __wasi_errno_t +fd_prestats_insert_locked(struct fd_prestats *pt, const char *dir, + __wasi_fd_t fd) +{ + // Grow the preopened resource table if needed. + __wasi_errno_t error = fd_prestats_grow(pt, fd, 1); + + if (error != __WASI_ESUCCESS) { + return error; + } + + pt->prestats[fd].dir = bh_strdup(dir); + + if (pt->prestats[fd].dir == NULL) + return __WASI_ENOMEM; + + return __WASI_ESUCCESS; } // Inserts a preopened resource record into the preopened resource table. bool fd_prestats_insert(struct fd_prestats *pt, const char *dir, __wasi_fd_t fd) { - // Grow the preopened resource table if needed. rwlock_wrlock(&pt->lock); - if (!fd_prestats_grow(pt, fd, 1)) { - rwlock_unlock(&pt->lock); - return false; - } - pt->prestats[fd].dir = bh_strdup(dir); + __wasi_errno_t error = fd_prestats_insert_locked(pt, dir, fd); + rwlock_unlock(&pt->lock); - if (pt->prestats[fd].dir == NULL) - return false; - - return true; + return error == __WASI_ESUCCESS; } // Looks up a preopened resource table entry by number. @@ -408,6 +420,24 @@ fd_prestats_get_entry(struct fd_prestats *pt, __wasi_fd_t fd, return 0; } +// Remove a preopened resource record from the preopened resource table by +// number +static __wasi_errno_t +fd_prestats_remove_entry(struct fd_prestats *pt, __wasi_fd_t fd) +{ + // Test for file descriptor existence. + if (fd >= pt->size) + return __WASI_EBADF; + struct fd_prestat *prestat = &pt->prestats[fd]; + + if (prestat->dir != NULL) { + wasm_runtime_free((void *)prestat->dir); + prestat->dir = NULL; + } + + return __WASI_ESUCCESS; +} + struct fd_object { struct refcount refcount; __wasi_filetype_t type; @@ -837,25 +867,15 @@ __wasi_errno_t wasmtime_ssp_fd_close(wasm_exec_env_t exec_env, struct fd_table *curfds, struct fd_prestats *prestats, __wasi_fd_t fd) { - // Don't allow closing a pre-opened resource. - // TODO: Eventually, we do want to permit this, once libpreopen in - // userspace is capable of removing entries from its tables as well. - { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); - rwlock_unlock(&prestats->lock); - if (error == 0) { - return __WASI_ENOTSUP; - } - } - // Validate the file descriptor. struct fd_table *ft = curfds; rwlock_wrlock(&ft->lock); + rwlock_wrlock(&prestats->lock); + struct fd_entry *fe; __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); if (error != 0) { + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); return error; } @@ -863,9 +883,20 @@ wasmtime_ssp_fd_close(wasm_exec_env_t exec_env, struct fd_table *curfds, // Remove it from the file descriptor table. struct fd_object *fo; fd_table_detach(ft, fd, &fo); + + // Remove it from the preopened resource table if it exists + error = fd_prestats_remove_entry(prestats, fd); + + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); fd_object_release(exec_env, fo); - return 0; + + // Ignore the error if there is no preopen associated with this fd + if (error == __WASI_EBADF) { + return __WASI_ESUCCESS; + } + + return error; } // Look up a file descriptor object in a locked file descriptor table @@ -1081,33 +1112,21 @@ wasmtime_ssp_fd_renumber(wasm_exec_env_t exec_env, struct fd_table *curfds, struct fd_prestats *prestats, __wasi_fd_t from, __wasi_fd_t to) { - // Don't allow renumbering over a pre-opened resource. - // TODO: Eventually, we do want to permit this, once libpreopen in - // userspace is capable of removing entries from its tables as well. - { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, to, &prestat); - if (error != 0) { - error = fd_prestats_get_entry(prestats, from, &prestat); - } - rwlock_unlock(&prestats->lock); - if (error == 0) { - return __WASI_ENOTSUP; - } - } - struct fd_table *ft = curfds; rwlock_wrlock(&ft->lock); + rwlock_wrlock(&prestats->lock); + struct fd_entry *fe_from; __wasi_errno_t error = fd_table_get_entry(ft, from, 0, 0, &fe_from); if (error != 0) { + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); return error; } struct fd_entry *fe_to; error = fd_table_get_entry(ft, to, 0, 0, &fe_to); if (error != 0) { + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); return error; } @@ -1124,8 +1143,53 @@ wasmtime_ssp_fd_renumber(wasm_exec_env_t exec_env, struct fd_table *curfds, fd_object_release(exec_env, fo); --ft->used; + // Handle renumbering of any preopened resources + struct fd_prestat *prestat_from; + __wasi_errno_t prestat_from_error = + fd_prestats_get_entry(prestats, from, &prestat_from); + + struct fd_prestat *prestat_to; + __wasi_errno_t prestat_to_error = + fd_prestats_get_entry(prestats, to, &prestat_to); + + // Renumbering over two preopened resources. + if (prestat_from_error == __WASI_ESUCCESS + && prestat_to_error == __WASI_ESUCCESS) { + (void)fd_prestats_remove_entry(prestats, to); + + error = fd_prestats_insert_locked(prestats, prestat_from->dir, to); + + if (error == __WASI_ESUCCESS) { + (void)fd_prestats_remove_entry(prestats, from); + } + else { + (void)fd_prestats_remove_entry(prestats, to); + } + } + // Renumbering from a non-preopened fd to a preopened fd. In this case, we + // can't a keep the destination fd entry in the preopened table so remove + // it entirely. + else if (prestat_from_error != __WASI_ESUCCESS + && prestat_to_error == __WASI_ESUCCESS) { + (void)fd_prestats_remove_entry(prestats, to); + } + // Renumbering from a preopened fd to a non-preopened fd + else if (prestat_from_error == __WASI_ESUCCESS + && prestat_to_error != __WASI_ESUCCESS) { + error = fd_prestats_insert_locked(prestats, prestat_from->dir, to); + + if (error == __WASI_ESUCCESS) { + (void)fd_prestats_remove_entry(prestats, from); + } + else { + (void)fd_prestats_remove_entry(prestats, to); + } + } + + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); - return 0; + + return error; } __wasi_errno_t From b62262209651ba18b59ba19170038b9ea12aa024 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 26 Sep 2023 11:00:33 +0900 Subject: [PATCH 119/123] samples/inst-context-threads: Add a brief explanation (#2592) --- samples/inst-context-threads/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/samples/inst-context-threads/README.md b/samples/inst-context-threads/README.md index 43b13c66b..d64cbff52 100644 --- a/samples/inst-context-threads/README.md +++ b/samples/inst-context-threads/README.md @@ -1,4 +1,5 @@ -The "inst-context" sample project -================================= +The "inst-context-threads" sample project +========================================= -This sample demonstrates module instance context API. +This sample demonstrates some interactions between +module instance context API and wasi-threads. From 6382162711a9cfaedc63de9065b0bc6eda8123f3 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 26 Sep 2023 10:17:54 +0800 Subject: [PATCH 120/123] Fix loader push_pop_frame_ref_offset (#2590) `wasm_loader_push_pop_frame_offset` may pop n operands by using `loader_ctx->stack_cell_num` to check whether the operand can be popped or not. While `loader_ctx->stack_cell_num` is updated in the later `wasm_loader_push_pop_frame_ref`, the check may fail if the stack is in polymorphic state and lead to `ctx->frame_offset` underflow. Fix issue #2577 and #2586. --- core/iwasm/interpreter/wasm_loader.c | 45 ++++++++++------------- core/iwasm/interpreter/wasm_mini_loader.c | 43 ++++++++++------------ 2 files changed, 38 insertions(+), 50 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index c775ee6c0..130ad4392 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -5476,6 +5476,7 @@ wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf, return true; } +#if WASM_ENABLE_FAST_INTERP == 0 static bool wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt, uint8 type_push, uint8 type_pop, char *error_buf, @@ -5490,6 +5491,7 @@ wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt, return false; return true; } +#endif static bool wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type, @@ -6166,27 +6168,6 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type, return true; } -static bool -wasm_loader_push_pop_frame_offset(WASMLoaderContext *ctx, uint8 pop_cnt, - uint8 type_push, uint8 type_pop, - bool disable_emit, int16 operand_offset, - char *error_buf, uint32 error_buf_size) -{ - uint8 i; - - for (i = 0; i < pop_cnt; i++) { - if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf, - error_buf_size)) - return false; - } - if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit, - operand_offset, error_buf, - error_buf_size)) - return false; - - return true; -} - static bool wasm_loader_push_frame_ref_offset(WASMLoaderContext *ctx, uint8 type, bool disable_emit, int16 operand_offset, @@ -6220,12 +6201,24 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt, bool disable_emit, int16 operand_offset, char *error_buf, uint32 error_buf_size) { - if (!wasm_loader_push_pop_frame_offset(ctx, pop_cnt, type_push, type_pop, - disable_emit, operand_offset, - error_buf, error_buf_size)) + uint8 i; + + for (i = 0; i < pop_cnt; i++) { + if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf, + error_buf_size)) + return false; + + if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf, + error_buf_size)) + return false; + } + + if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit, + operand_offset, error_buf, + error_buf_size)) return false; - if (!wasm_loader_push_pop_frame_ref(ctx, pop_cnt, type_push, type_pop, - error_buf, error_buf_size)) + + if (!wasm_loader_push_frame_ref(ctx, type_push, error_buf, error_buf_size)) return false; return true; diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 9f568e132..d16bc1a24 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -3937,6 +3937,7 @@ wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf, return true; } +#if WASM_ENABLE_FAST_INTERP == 0 static bool wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt, uint8 type_push, uint8 type_pop, char *error_buf, @@ -3951,6 +3952,7 @@ wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt, return false; return true; } +#endif static bool wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type, @@ -4608,25 +4610,6 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type, return true; } -static bool -wasm_loader_push_pop_frame_offset(WASMLoaderContext *ctx, uint8 pop_cnt, - uint8 type_push, uint8 type_pop, - bool disable_emit, int16 operand_offset, - char *error_buf, uint32 error_buf_size) -{ - for (int i = 0; i < pop_cnt; i++) { - if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf, - error_buf_size)) - return false; - } - if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit, - operand_offset, error_buf, - error_buf_size)) - return false; - - return true; -} - static bool wasm_loader_push_frame_ref_offset(WASMLoaderContext *ctx, uint8 type, bool disable_emit, int16 operand_offset, @@ -4660,12 +4643,24 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt, bool disable_emit, int16 operand_offset, char *error_buf, uint32 error_buf_size) { - if (!wasm_loader_push_pop_frame_offset(ctx, pop_cnt, type_push, type_pop, - disable_emit, operand_offset, - error_buf, error_buf_size)) + uint8 i; + + for (i = 0; i < pop_cnt; i++) { + if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf, + error_buf_size)) + return false; + + if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf, + error_buf_size)) + return false; + } + + if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit, + operand_offset, error_buf, + error_buf_size)) return false; - if (!wasm_loader_push_pop_frame_ref(ctx, pop_cnt, type_push, type_pop, - error_buf, error_buf_size)) + + if (!wasm_loader_push_frame_ref(ctx, type_push, error_buf, error_buf_size)) return false; return true; From ade73f6142a1a11202053219b840580eeb24750e Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 26 Sep 2023 16:13:12 +0800 Subject: [PATCH 121/123] Fix compilation error on Android platform (#2594) The CI might use clang-17 to build iwasm for Android platform and it may report compilation error: https://github.com/bytecodealliance/wasm-micro-runtime/actions/runs/6308980430/job/17128073777 /home/runner/work/wasm-micro-runtime/wasm-micro-runtime/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c:45:19: error: call to undeclared function 'preadv'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] ssize_t ret = preadv(fd, iov, iovcnt, offset); ^ Explicitly declare preadv and pwritev in android platform header file to resolve it. --- core/shared/platform/android/platform_internal.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h index d718a2d7d..c28a7b9be 100644 --- a/core/shared/platform/android/platform_internal.h +++ b/core/shared/platform/android/platform_internal.h @@ -139,16 +139,12 @@ seekdir(DIR *__dir, long __location); #endif -#if __ANDROID_API__ < 24 - ssize_t preadv(int __fd, const struct iovec *__iov, int __count, off_t __offset); ssize_t pwritev(int __fd, const struct iovec *__iov, int __count, off_t __offset); -#endif - #ifdef __cplusplus } #endif From a50a4384613a18d21c5ecb5fec2482775607fc91 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 26 Sep 2023 19:59:48 +0800 Subject: [PATCH 122/123] Ignore handling SIG_DFL/SIG_IGN for previous sig action (#2589) --- core/shared/platform/common/posix/posix_thread.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index a0b184405..a7bdc6d10 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -543,14 +543,12 @@ 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_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) { + else if (prev_sig_act + && prev_sig_act->sa_handler + /* Filter out SIG_DFL and SIG_IGN here, they will + run into the else branch below */ + && (void *)prev_sig_act->sa_handler != SIG_DFL + && (void *)prev_sig_act->sa_handler != SIG_IGN) { prev_sig_act->sa_handler(sig_num); } /* Output signal info and then crash if signal is unhandled */ From fff0e2ad1cf9d5749f0e92582167353af995f730 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 27 Sep 2023 15:41:48 +0800 Subject: [PATCH 123/123] Fix nightly run sanitizer error in Fast JIT (#2601) Suppress a sanitizer integer overflow error in signed integer add operation in Fast JIT. --- core/iwasm/fast-jit/fe/jit_emit_numberic.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/iwasm/fast-jit/fe/jit_emit_numberic.c b/core/iwasm/fast-jit/fe/jit_emit_numberic.c index 03491e691..6a1e93ede 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_numberic.c +++ b/core/iwasm/fast-jit/fe/jit_emit_numberic.c @@ -298,7 +298,15 @@ fail: /* macros for integer binary operations (ibinop) */ +#if defined(__GNUC__) +#define NO_SANITIZER_INTEGER \ + __attribute__((no_sanitize("signed-integer-overflow"))) +#else +#define NO_SANITIZER_INTEGER +#endif + #define __DEF_BI_INT_CONST_OPS(bits, opname, op) \ + NO_SANITIZER_INTEGER \ static int##bits do_i##bits##_const_##opname(int##bits lhs, int##bits rhs) \ { \ return lhs op rhs; \