diff --git a/.gitignore b/.gitignore index 0e82e0b5b..0b2d07118 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,10 @@ .vscode **/*build/ +core/deps/lv_drivers +core/deps/llvm +core/deps/lvgl +core/shared/mem-alloc/tlsf + +wamr-sdk/out/ +wamr-sdk/runtime/build_runtime_sdk/ +test-tools/host-tool/bin/ diff --git a/README.md b/README.md index faf50a57e..6d89814d9 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,16 @@ iwasm VM core - [Embeddable with the supporting C API's](./doc/embed_wamr.md) - [The mechanism for exporting native API's to WASM applications](./doc/export_native_api.md) +### Performance and memory usage +The WAMR performance, footprint and memory usage data are available at the [performance](../../wiki/Performance) wiki page. + ### Supported architectures and platforms The iwasm supports the following architectures: - X86-64, X86-32 - ARM, THUMB (ARMV7 Cortex-M7 and Cortex-A15 are tested) +- AArch64 (Cortex-A57 and Cortex-A53 are tested) - MIPS - XTENSA @@ -49,7 +53,7 @@ Execute following commands to build **wamrc** compiler: ```shell cd wamr-compiler -./build_llvm.sh +./build_llvm.sh (use build_llvm_xtensa.sh instead to support xtensa target) mkdir build && cd build cmake .. make @@ -96,7 +100,9 @@ The **[WAMR SDK](./wamr-sdk)** tools is helpful to finish the two tasks quickly. Samples ================= -The WAMR [samples](./samples) integrate the iwasm VM core, application manager and selected application framework components. +The WAMR [samples](./samples) integrate the iwasm VM core, application manager and selected application framework components. + +- [**Basic**](./samples/basic): Demonstrating how host runtime calls WASM function as well as WASM function calls native function. - **[Simple](./samples/simple/README.md)**: The runtime is integrated with most of the WAMR APP libraries, and a few WASM applications are provided for testing the WAMR APP API set. It uses **built-in libc** and executes apps in **interpreter** mode by default. - **[littlevgl](./samples/littlevgl/README.md)**: Demonstrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application. It uses **WASI libc** and executes apps in **AoT mode** by default. - **[gui](./samples/gui/README.md)**: Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API. It uses **WASI libc** and executes apps in **interpreter** mode by default. diff --git a/_clang-format b/_clang-format new file mode 100644 index 000000000..c99997022 --- /dev/null +++ b/_clang-format @@ -0,0 +1,129 @@ +--- +BasedOnStyle: Mozilla +IndentWidth: 4 + +--- +Language: Cpp +AlignConsecutiveMacros: true +AllowShortBlocksOnASingleLine: true +BinPackArguments: true +BinPackParameters: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: false + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 79 +DerivePointerAlignment: false +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 1 + - Regex: ".*" + Priority: 3 +PointerAlignment: Right +ReflowComments: false +Standard: Cpp03 +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +# AccessModifierOffset: -2 +# AlignAfterOpenBracket: Align +# AlignConsecutiveAssignments: false +# AlignConsecutiveDeclarations: false +# AlignEscapedNewlines: Right +# AlignOperands: true +# AlignTrailingComments: true +# AllowAllArgumentsOnNextLine: true +# AllowAllConstructorInitializersOnNextLine: true +# AllowAllParametersOfDeclarationOnNextLine: false +# AllowShortCaseLabelsOnASingleLine: false +# AllowShortFunctionsOnASingleLine: Inline +# AllowShortLambdasOnASingleLine: All +# AllowShortIfStatementsOnASingleLine: Never +# AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: TopLevel +# AlwaysBreakAfterReturnType: TopLevel +# AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: Yes +# BreakBeforeBinaryOperators: None +# BreakBeforeInheritanceComma: false +# BreakInheritanceList: BeforeComma +# BreakBeforeTernaryOperators: true +# BreakConstructorInitializersBeforeComma: false +# BreakConstructorInitializers: BeforeComma +# BreakAfterJavaFieldAnnotations: false +# BreakStringLiterals: true +# CommentPragmas: '^ IWYU pragma:' +# CompactNamespaces: false +# ConstructorInitializerAllOnOneLineOrOnePerLine: false +# ConstructorInitializerIndentWidth: 2 +# ContinuationIndentWidth: 2 +# Cpp11BracedListStyle: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# FixNamespaceComments: false +# ForEachMacros: +# - foreach +# - Q_FOREACH +# - BOOST_FOREACH +# IncludeIsMainRegex: '(Test)?$' +# IndentCaseLabels: true +# IndentPPDirectives: None +# IndentWrappedFunctionNames: false +# JavaScriptQuotes: Leave +# JavaScriptWrapImports: true +# KeepEmptyLinesAtTheStartOfBlocks: true +# MacroBlockBegin: '' +# MacroBlockEnd: '' +# MaxEmptyLinesToKeep: 1 +# NamespaceIndentation: None +# ObjCBinPackProtocolList: Auto +# ObjCBlockIndentWidth: 2 +# ObjCSpaceAfterProperty: true +# ObjCSpaceBeforeProtocolList: false +# PenaltyBreakAssignment: 2 +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyBreakTemplateDeclaration: 10 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 200 +# SortIncludes: true +# SortUsingDeclarations: true +# SpaceAfterCStyleCast: false +# SpaceAfterLogicalNot: false +# SpaceAfterTemplateKeyword: false +# SpaceBeforeAssignmentOperators: true +# SpaceBeforeCpp11BracedList: false +# SpaceBeforeCtorInitializerColon: true +# SpaceBeforeInheritanceColon: true +# SpaceBeforeParens: ControlStatements +# SpaceBeforeRangeBasedForLoopColon: true +# SpaceInEmptyParentheses: false +# SpacesBeforeTrailingComments: 1 +# SpacesInAngles: false +# SpacesInContainerLiterals: true +# SpacesInCStyleCastParentheses: false +# SpacesInParentheses: false +# SpacesInSquareBrackets: false +# TabWidth: 4 +# UseTab: Never +# ... + diff --git a/assembly-script/package.json b/assembly-script/package.json index fa8343d8e..00aaaaf97 100644 --- a/assembly-script/package.json +++ b/assembly-script/package.json @@ -5,11 +5,11 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --validate --optimize", - "build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --validate --optimize", - "build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --validate --optimize", - "build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --validate --optimize", - "build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --validate --optimize", + "build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --validate --optimize --use abort=", + "build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --validate --optimize --use abort=", + "build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --validate --optimize --use abort=", + "build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --validate --optimize --use abort=", + "build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --validate --optimize --use abort=", "build:all": "npm run build:request_handler; npm run build:request_sender; npm run build:timer; npm run build:subscriber; npm run build:publisher" }, "author": "", diff --git a/assembly-script/wamr_app_lib/console.ts b/assembly-script/wamr_app_lib/console.ts index 0b06c07d7..f20ede938 100644 --- a/assembly-script/wamr_app_lib/console.ts +++ b/assembly-script/wamr_app_lib/console.ts @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -@external("env", "printf") +@external("env", "puts") declare function printf(a: ArrayBuffer): i32; export function log(a: string): void { - printf(String.UTF8.encode(a + '\n', true)); + printf(String.UTF8.encode(a, true)); } export function log_number(a: number): void { - printf(String.UTF8.encode(a.toString() + '\n')); + printf(String.UTF8.encode(a.toString())); } \ No newline at end of file diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 8cb6ed141..2ec4d64fa 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -3,24 +3,6 @@ string(TOUPPER ${WAMR_BUILD_TARGET} WAMR_BUILD_TARGET) -# Add definitions for the build platform -if (WAMR_BUILD_PLATFORM STREQUAL "linux") - add_definitions(-DBH_PLATFORM_LINUX) -elseif (WAMR_BUILD_PLATFORM STREQUAL "linux-sgx") - add_definitions(-DBH_PLATFORM_LINUX_SGX) -elseif (WAMR_BUILD_PLATFORM STREQUAL "zephyr") - add_definitions(-DBH_PLATFORM_ZEPHYR) -elseif (WAMR_BUILD_PLATFORM STREQUAL "vxworks") - add_definitions(-DBH_PLATFORM_VXWORKS) -elseif (WAMR_BUILD_PLATFORM STREQUAL "darwin") - add_definitions(-DBH_PLATFORM_DARWIN) -elseif (WAMR_BUILD_PLATFORM STREQUAL "alios-things") - add_definitions(-DBH_PLATFORM_ALIOS_THINGS) -elseif (WAMR_BUILD_PLATFORM STREQUAL "android") - add_definitions(-DBH_PLATFORM_ANDROID) -else () - message (WARNING "-- WAMR build platform isn't set") -endif () # Add definitions for the build target if (WAMR_BUILD_TARGET STREQUAL "X86_64") @@ -45,6 +27,9 @@ elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*") add_definitions(-DBUILD_TARGET_THUMB) add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") endif () +elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*") + add_definitions(-DBUILD_TARGET_AARCH64) + add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") elseif (WAMR_BUILD_TARGET STREQUAL "MIPS") add_definitions(-DBUILD_TARGET_MIPS) elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA") @@ -53,8 +38,12 @@ else () message (FATAL_ERROR "-- WAMR build target isn't set") endif () +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + add_definitions(-DBH_DEBUG=1) +endif () + if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*") # Add -fPIC flag if build as 64-bit set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") @@ -105,33 +94,33 @@ message (" CMAKE_BUILD_TYPE " ${CMAKE_BUILD_TYPE}) if (WAMR_BUILD_INTERP EQUAL 1) message (" WAMR Interpreter enabled") else () - message (" WAMR Interpreter disbled") + message (" WAMR Interpreter disabled") endif () if (WAMR_BUILD_AOT EQUAL 1) message (" WAMR AOT enabled") else () - message (" WAMR AOT disbled") + message (" WAMR AOT disabled") endif () if (WAMR_BUILD_JIT EQUAL 1) message (" WAMR JIT enabled") else () - message (" WAMR JIT disbled") + message (" WAMR JIT disabled") endif () if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) message (" Libc builtin enabled") else () - message (" Libc builtin disbled") + message (" Libc builtin disabled") endif () if (WAMR_BUILD_LIBC_WASI EQUAL 1) message (" Libc WASI enabled") else () - message (" Libc WASI disbled") + message (" Libc WASI disabled") endif () if (WAMR_BUILD_FAST_INTERP EQUAL 1) add_definitions (-DWASM_ENABLE_FAST_INTERP=1) message (" Fast interpreter enabled") else () add_definitions (-DWASM_ENABLE_FAST_INTERP=0) - message (" Fast interpreter disbled") + message (" Fast interpreter disabled") endif () diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index e60a53b87..128f44ea6 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -31,7 +31,7 @@ endif () # Set default options # Set WAMR_BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" if (NOT DEFINED WAMR_BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform diff --git a/core/app-framework/app-native-shared/attr_container.c b/core/app-framework/app-native-shared/attr_container.c index 478bef0e3..2cd816c6d 100644 --- a/core/app-framework/app-native-shared/attr_container.c +++ b/core/app-framework/app-native-shared/attr_container.c @@ -16,14 +16,7 @@ typedef union jvalue { double d; } jvalue; -#ifndef bh_memcpy_s -int b_memcpy_s(void * s1, unsigned int s1max, - const void * s2, unsigned int n); -#define bh_memcpy_s(dest, dlen, src, slen) do { \ - int _ret = slen == 0 ? 0 : b_memcpy_s (dest, dlen, src, slen); \ - (void)_ret; \ - } while (0) -#endif + static inline int16_t get_int16(const char *buf) { diff --git a/core/app-framework/app-native-shared/native_interface.h b/core/app-framework/app-native-shared/native_interface.h index 0e0d063b1..76af44482 100644 --- a/core/app-framework/app-native-shared/native_interface.h +++ b/core/app-framework/app-native-shared/native_interface.h @@ -9,30 +9,6 @@ /* Note: the bh_plaform.h is the only head file separately implemented by both [app] and [native] worlds */ #include "bh_platform.h" -#include "wasm_export.h" - -#define get_module_inst(exec_env) \ - wasm_runtime_get_module_inst(exec_env) - -#define validate_app_addr(offset, size) \ - wasm_runtime_validate_app_addr(module_inst, offset, size) - -#define validate_app_str_addr(offset) \ - wasm_runtime_validate_app_str_addr(module_inst, offset) - -#define addr_app_to_native(offset) \ - wasm_runtime_addr_app_to_native(module_inst, offset) - -#define addr_native_to_app(ptr) \ - wasm_runtime_addr_native_to_app(module_inst, ptr) - -#define module_malloc(size, p_native_addr) \ - wasm_runtime_module_malloc(module_inst, size, p_native_addr) - -#define module_free(offset) \ - wasm_runtime_module_free(module_inst, offset) - -/*char *wa_strdup(const char *);*/ #endif /* end of _NATIVE_INTERFACE_H */ diff --git a/core/app-framework/base/app/bh_platform.c b/core/app-framework/base/app/bh_platform.c index e539e8b0b..0dbf04752 100644 --- a/core/app-framework/base/app/bh_platform.c +++ b/core/app-framework/base/app/bh_platform.c @@ -79,23 +79,3 @@ char *wa_strdup(const char *s) memcpy(s1, s, strlen(s) + 1); return s1; } - -#define RSIZE_MAX 0x7FFFFFFF -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n) -{ - char *dest = (char*) s1; - char *src = (char*) s2; - if (n == 0) { - return 0; - } - - if (s1 == NULL || s1max > RSIZE_MAX) { - return -1; - } - if (s2 == NULL || n > s1max) { - memset(dest, 0, s1max); - return -1; - } - memcpy(dest, src, n); - return 0; -} diff --git a/core/app-framework/base/app/bh_platform.h b/core/app-framework/base/app/bh_platform.h index 91b43bb25..2539ec58d 100755 --- a/core/app-framework/base/app/bh_platform.h +++ b/core/app-framework/base/app/bh_platform.h @@ -35,14 +35,14 @@ typedef int int32; #define WA_FREE free #endif -char *wa_strdup(const char *s); uint32 htonl(uint32 value); uint32 ntohl(uint32 value); uint16 htons(uint16 value); uint16 ntohs(uint16 value); -int -b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n); + +// We are not worried for the WASM world since the sandbox will catch it. +#define bh_memcpy_s(dst, dst_len, src, src_len) memcpy(dst, src, src_len) #endif /* DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_ */ diff --git a/core/app-framework/base/native/timer_wrapper.c b/core/app-framework/base/native/timer_wrapper.c index 44887df9e..fd3ef4bbc 100644 --- a/core/app-framework/base/native/timer_wrapper.c +++ b/core/app-framework/base/native/timer_wrapper.c @@ -3,12 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "runtime_timer.h" +#include "bh_platform.h" #include "app_manager_export.h" #include "module_wasm_app.h" -#include "bh_list.h" -#include "bh_thread.h" -#include "bh_time.h" #include "timer_native_api.h" static bool timer_thread_run = true; @@ -46,7 +43,7 @@ void * thread_modulers_timer_check(void * arg) while (timer_thread_run) { ms_to_expiry = -1; - vm_mutex_lock(&g_timer_ctx_list_mutex); + os_mutex_lock(&g_timer_ctx_list_mutex); timer_ctx_node_t* elem = (timer_ctx_node_t*) bh_list_first_elem(&g_timer_ctx_list); while (elem) { @@ -58,14 +55,14 @@ void * thread_modulers_timer_check(void * arg) elem = (timer_ctx_node_t*) bh_list_elem_next(elem); } - vm_mutex_unlock(&g_timer_ctx_list_mutex); + os_mutex_unlock(&g_timer_ctx_list_mutex); if (ms_to_expiry == -1) ms_to_expiry = 60 * 1000; - vm_mutex_lock(&g_timer_ctx_list_mutex); - vm_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex, - ms_to_expiry); - vm_mutex_unlock(&g_timer_ctx_list_mutex); + os_mutex_lock(&g_timer_ctx_list_mutex); + os_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex, + ms_to_expiry * 1000); + os_mutex_unlock(&g_timer_ctx_list_mutex); } return NULL; @@ -73,9 +70,9 @@ void * thread_modulers_timer_check(void * arg) void wakeup_modules_timer_thread(timer_ctx_t ctx) { - vm_mutex_lock(&g_timer_ctx_list_mutex); - vm_cond_signal(&g_timer_ctx_list_cond); - vm_mutex_unlock(&g_timer_ctx_list_mutex); + os_mutex_lock(&g_timer_ctx_list_mutex); + os_cond_signal(&g_timer_ctx_list_cond); + os_mutex_unlock(&g_timer_ctx_list_mutex); } void init_wasm_timer() @@ -83,11 +80,11 @@ void init_wasm_timer() korp_tid tm_tid; bh_list_init(&g_timer_ctx_list); - vm_cond_init(&g_timer_ctx_list_cond); + os_cond_init(&g_timer_ctx_list_cond); /* temp solution for: thread_modulers_timer_check thread would recursive lock the mutex */ - vm_recursive_mutex_init(&g_timer_ctx_list_mutex); + os_recursive_mutex_init(&g_timer_ctx_list_mutex); - vm_thread_create(&tm_tid, thread_modulers_timer_check, + os_thread_create(&tm_tid, thread_modulers_timer_check, NULL, BH_APPLET_PRESERVED_STACK_SIZE); } @@ -115,16 +112,16 @@ timer_ctx_t create_wasm_timer_ctx(unsigned int module_id, int prealloc_num) memset(node, 0, sizeof(*node)); node->timer_ctx = ctx; - vm_mutex_lock(&g_timer_ctx_list_mutex); + os_mutex_lock(&g_timer_ctx_list_mutex); bh_list_insert(&g_timer_ctx_list, node); - vm_mutex_unlock(&g_timer_ctx_list_mutex); + os_mutex_unlock(&g_timer_ctx_list_mutex); return ctx; } void destroy_module_timer_ctx(unsigned int module_id) { - vm_mutex_lock(&g_timer_ctx_list_mutex); + os_mutex_lock(&g_timer_ctx_list_mutex); timer_ctx_node_t* elem = (timer_ctx_node_t*) bh_list_first_elem(&g_timer_ctx_list); while (elem) { @@ -137,7 +134,7 @@ void destroy_module_timer_ctx(unsigned int module_id) elem = (timer_ctx_node_t*) bh_list_elem_next(elem); } - vm_mutex_unlock(&g_timer_ctx_list_mutex); + os_mutex_unlock(&g_timer_ctx_list_mutex); } timer_ctx_t get_wasm_timer_ctx(wasm_module_inst_t module_inst) @@ -192,6 +189,6 @@ extern uint32 get_sys_tick_ms(); uint32 wasm_get_sys_tick_ms(wasm_exec_env_t exec_env) { - return (uint32) bh_get_tick_ms(); + return (uint32)bh_get_tick_ms(); } diff --git a/core/app-framework/connection/native/linux/connection_mgr.c b/core/app-framework/connection/native/linux/connection_mgr.c index fe4ef6168..df0fc8f07 100644 --- a/core/app-framework/connection/native/linux/connection_mgr.c +++ b/core/app-framework/connection/native/linux/connection_mgr.c @@ -11,14 +11,12 @@ */ #include "connection_lib.h" -#include "bh_thread.h" +#include "bh_platform.h" #include "app_manager_export.h" #include "module_wasm_app.h" #include "conn_tcp.h" #include "conn_udp.h" #include "conn_uart.h" -#include "bh_common.h" -#include "bh_assert.h" #include #include @@ -96,7 +94,7 @@ connection_interface_t connection_impl = { static void add_connection(sys_connection_t *conn) { - vm_mutex_lock(&g_lock); + os_mutex_lock(&g_lock); g_handle_max++; if (g_handle_max == -1) @@ -110,7 +108,7 @@ static void add_connection(sys_connection_t *conn) g_connections = conn; } - vm_mutex_unlock(&g_lock); + os_mutex_unlock(&g_lock); } #define FREE_CONNECTION(conn) do { \ @@ -124,7 +122,7 @@ static int get_app_conns_num(uint32 module_id) sys_connection_t *conn; int num = 0; - vm_mutex_lock(&g_lock); + os_mutex_lock(&g_lock); conn = g_connections; while (conn) { @@ -133,7 +131,7 @@ static int get_app_conns_num(uint32 module_id) conn = conn->next; } - vm_mutex_unlock(&g_lock); + os_mutex_unlock(&g_lock); return num; } @@ -142,7 +140,7 @@ static sys_connection_t *find_connection(uint32 handle, bool remove_found) { sys_connection_t *conn, *prev = NULL; - vm_mutex_lock(&g_lock); + os_mutex_lock(&g_lock); conn = g_connections; while (conn) { @@ -154,7 +152,7 @@ static sys_connection_t *find_connection(uint32 handle, bool remove_found) g_connections = conn->next; } } - vm_mutex_unlock(&g_lock); + os_mutex_unlock(&g_lock); return conn; } else { prev = conn; @@ -162,7 +160,7 @@ static sys_connection_t *find_connection(uint32 handle, bool remove_found) } } - vm_mutex_unlock(&g_lock); + os_mutex_unlock(&g_lock); return NULL; } @@ -171,7 +169,7 @@ static void cleanup_connections(uint32 module_id) { sys_connection_t *conn, *prev = NULL; - vm_mutex_lock(&g_lock); + os_mutex_lock(&g_lock); conn = g_connections; while (conn) { @@ -194,7 +192,7 @@ static void cleanup_connections(uint32 module_id) } } - vm_mutex_unlock(&g_lock); + os_mutex_unlock(&g_lock); } static conn_type_t get_conn_type(const char *name) @@ -546,13 +544,13 @@ void app_mgr_connection_event_callback(module_data *m_data, bh_message_t msg) bool init_connection_framework() { - korp_thread tid; + korp_tid tid; epollfd = epoll_create(MAX_EVENTS); if (epollfd == -1) return false; - if (vm_mutex_init(&g_lock) != 0) { + if (os_mutex_init(&g_lock) != 0) { close(epollfd); return false; } @@ -566,7 +564,7 @@ bool init_connection_framework() goto fail; } - if (vm_thread_create(&tid, + if (os_thread_create(&tid, polling_thread_routine, NULL, BH_APPLET_PRESERVED_STACK_SIZE) != 0) { @@ -576,7 +574,7 @@ bool init_connection_framework() return true; fail: - vm_mutex_destroy(&g_lock); + os_mutex_destroy(&g_lock); close(epollfd); return false; } diff --git a/core/app-framework/sensor/native/runtime_sensor.c b/core/app-framework/sensor/native/runtime_sensor.c index ac7eed9dd..89f7ea8bb 100644 --- a/core/app-framework/sensor/native/runtime_sensor.c +++ b/core/app-framework/sensor/native/runtime_sensor.c @@ -6,10 +6,7 @@ #include "runtime_sensor.h" #include "app_manager_export.h" #include "module_wasm_app.h" -#include "bh_thread.h" -#include "bh_time.h" -#include "bh_common.h" -#include "bh_assert.h" +#include "bh_platform.h" static sys_sensor_t * g_sys_sensors = NULL; static int g_sensor_id_max = 0; @@ -103,11 +100,11 @@ wasm_sensor_config(wasm_exec_env_t exec_env, module_inst); bh_assert(mod_id != ID_NONE); - vm_mutex_lock(&s->lock); + os_mutex_lock(&s->lock); c = find_sensor_client(s, mod_id, false); if (c == NULL) { - vm_mutex_unlock(&s->lock); + os_mutex_unlock(&s->lock); return false; } @@ -115,7 +112,7 @@ wasm_sensor_config(wasm_exec_env_t exec_env, c->bit_cfg = bit_cfg; c->delay = delay; - vm_mutex_unlock(&s->lock); + os_mutex_unlock(&s->lock); if (s->config != NULL) { attr_cont = attr_container_create("config sensor"); @@ -149,19 +146,19 @@ wasm_sensor_open(wasm_exec_env_t exec_env, module_inst); bh_assert(mod_id != ID_NONE); - vm_mutex_lock(&s->lock); + os_mutex_lock(&s->lock); c = find_sensor_client(s, mod_id, false); if (c) { // the app already opened this sensor - vm_mutex_unlock(&s->lock); + os_mutex_unlock(&s->lock); return -1; } sensor_client_t * client = (sensor_client_t*) wasm_runtime_malloc( sizeof(sensor_client_t)); if (client == NULL) { - vm_mutex_unlock(&s->lock); + os_mutex_unlock(&s->lock); return -1; } @@ -172,7 +169,7 @@ wasm_sensor_open(wasm_exec_env_t exec_env, client->next = s->clients; s->clients = client; - vm_mutex_unlock(&s->lock); + os_mutex_unlock(&s->lock); refresh_read_interval(s); @@ -218,10 +215,10 @@ wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor) if (s == NULL) return false; - vm_mutex_lock(&s->lock); + os_mutex_lock(&s->lock); if ((c = find_sensor_client(s, client_id, true)) != NULL) wasm_runtime_free(c); - vm_mutex_unlock(&s->lock); + os_mutex_unlock(&s->lock); refresh_read_interval(s); @@ -251,7 +248,7 @@ void refresh_read_interval(sensor_obj_t sensor) { sensor_client_t *c; uint32 interval = sensor->default_interval; - vm_mutex_lock(&sensor->lock); + os_mutex_lock(&sensor->lock); c = sensor->clients; if (c) @@ -263,7 +260,7 @@ void refresh_read_interval(sensor_obj_t sensor) c = c->next; } - vm_mutex_unlock(&sensor->lock); + os_mutex_unlock(&sensor->lock); sensor->read_interval = interval; } @@ -310,7 +307,7 @@ add_sys_sensor(char * name, char * description, int instance, g_sys_sensors = s; } - vm_mutex_init(&s->lock); + os_mutex_init(&s->lock); return s; } @@ -366,7 +363,7 @@ sensor_client_t *find_sensor_client(sys_sensor_t * sensor, int check_sensor_timers() { int ms_to_next_check = -1; - uint32 now = (uint32) bh_get_tick_ms(); + uint32 now = (uint32)bh_get_tick_ms(); sys_sensor_t * s = g_sys_sensors; while (s) { @@ -412,11 +409,11 @@ void sensor_cleanup_callback(uint32 module_id) while (s) { sensor_client_t *c; - vm_mutex_lock(&s->lock); + os_mutex_lock(&s->lock); if ((c = find_sensor_client(s, module_id, true)) != NULL) { wasm_runtime_free(c); } - vm_mutex_unlock(&s->lock); + os_mutex_unlock(&s->lock); s = s->next; } } diff --git a/core/app-framework/sensor/native/sensor_mgr_ref.c b/core/app-framework/sensor/native/sensor_mgr_ref.c index 9166947e8..80646bee6 100644 --- a/core/app-framework/sensor/native/sensor_mgr_ref.c +++ b/core/app-framework/sensor/native/sensor_mgr_ref.c @@ -3,9 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_common.h" -#include "bh_queue.h" -#include "bh_thread.h" +#include "bh_platform.h" #include "runtime_sensor.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" @@ -91,15 +89,15 @@ static void thread_sensor_check(void * arg) int ms_to_expiry = check_sensor_timers(); if (ms_to_expiry == -1) ms_to_expiry = 5000; - vm_mutex_lock(&mutex); - vm_cond_reltimedwait(&cond, &mutex, ms_to_expiry); - vm_mutex_unlock(&mutex); + os_mutex_lock(&mutex); + os_cond_reltimedwait(&cond, &mutex, ms_to_expiry * 1000); + os_mutex_unlock(&mutex); } } static void cb_wakeup_thread() { - vm_cond_signal(&cond); + os_cond_signal(&cond); } void set_sensor_reshceduler(void (*callback)()); @@ -107,8 +105,8 @@ void set_sensor_reshceduler(void (*callback)()); void init_sensor_framework() { // init the mutext and conditions - vm_cond_init(&cond); - vm_mutex_init(&mutex); + os_cond_init(&cond); + os_mutex_init(&mutex); set_sensor_reshceduler(cb_wakeup_thread); @@ -123,9 +121,9 @@ void init_sensor_framework() void start_sensor_framework() { - korp_thread tid; + korp_tid tid; - vm_thread_create(&tid, + os_thread_create(&tid, (void *)thread_sensor_check, NULL, BH_APPLET_PRESERVED_STACK_SIZE); diff --git a/core/app-framework/wgl/native/wgl_btn_wrapper.c b/core/app-framework/wgl/native/wgl_btn_wrapper.c index 4fd35e39f..dbe622476 100644 --- a/core/app-framework/wgl/native/wgl_btn_wrapper.c +++ b/core/app-framework/wgl/native/wgl_btn_wrapper.c @@ -11,115 +11,139 @@ /* ------------------------------------------------------------------------- * Button widget native function wrappers * -------------------------------------------------------------------------*/ -static int32 -lv_btn_create_wrapper(wasm_module_inst_t module_inst, - lv_obj_t *par, lv_obj_t *copy) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_create_wrapper) { - return wgl_native_wigdet_create(WIDGET_TYPE_BTN, par, copy, module_inst); + int32 res; + wgl_native_return_type(int32); + wgl_native_get_arg(uint32, par_obj_id); + wgl_native_get_arg(uint32, copy_obj_id); + wasm_module_inst_t module_inst = get_module_inst(exec_env); + + res = wgl_native_wigdet_create(WIDGET_TYPE_BTN, par_obj_id, copy_obj_id, module_inst); + wgl_native_set_return(res); } -static void -lv_btn_set_toggle_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn, bool tgl) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_toggle_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, btn); + wgl_native_get_arg(bool, tgl); + + (void)exec_env; lv_btn_set_toggle(btn, tgl); } -static void -lv_btn_set_state_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn, lv_btn_state_t state) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_state_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, btn); + wgl_native_get_arg(lv_btn_state_t, state); + + (void)exec_env; lv_btn_set_state(btn, state); } -static void -lv_btn_set_ink_in_time_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn, uint16_t time) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_ink_in_time_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, btn); + wgl_native_get_arg(uint16_t, time); + + (void)exec_env; lv_btn_set_ink_in_time(btn, time); } -static void -lv_btn_set_ink_out_time_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn, uint16_t time) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_ink_out_time_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, btn); + wgl_native_get_arg(uint16_t, time); + + (void)exec_env; lv_btn_set_ink_out_time(btn, time); } -static void -lv_btn_set_ink_wait_time_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn, uint16_t time) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_ink_wait_time_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, btn); + wgl_native_get_arg(uint16_t, time); + + (void)exec_env; lv_btn_set_ink_wait_time(btn, time); } -static uint16_t -lv_btn_get_ink_in_time_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_ink_in_time_wrapper) { - (void)module_inst; - return lv_btn_get_ink_in_time(btn); + uint16_t res; + wgl_native_return_type(uint16_t); + wgl_native_get_arg(lv_obj_t *, btn); + + (void)exec_env; + res = lv_btn_get_ink_in_time(btn); + wgl_native_set_return(res); } -static uint16_t -lv_btn_get_ink_out_time_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_ink_out_time_wrapper) { - (void)module_inst; - return lv_btn_get_ink_out_time(btn); + uint16_t res; + wgl_native_return_type(uint16_t); + wgl_native_get_arg(lv_obj_t *, btn); + + (void)exec_env; + res = lv_btn_get_ink_out_time(btn); + wgl_native_set_return(res); } -static uint16_t -lv_btn_get_ink_wait_time_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_ink_wait_time_wrapper) { - (void)module_inst; - return lv_btn_get_ink_wait_time(btn); + uint16_t res; + wgl_native_return_type(uint16_t); + wgl_native_get_arg(lv_obj_t *, btn); + + (void)exec_env; + res = lv_btn_get_ink_wait_time(btn); + wgl_native_set_return(res); } -static lv_btn_state_t -lv_btn_get_state_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_state_wrapper) { - (void)module_inst; - return lv_btn_get_state(btn); + lv_btn_state_t res; + wgl_native_return_type(lv_btn_state_t); + wgl_native_get_arg(lv_obj_t *, btn); + + (void)exec_env; + res = lv_btn_get_state(btn); + wgl_native_set_return(res); } -static bool -lv_btn_get_toggle_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_toggle_wrapper) { - (void)module_inst; - return lv_btn_get_toggle(btn); + bool res; + wgl_native_return_type(bool); + wgl_native_get_arg(lv_obj_t *, btn); + + (void)exec_env; + res = lv_btn_get_toggle(btn); + wgl_native_set_return(res); } -static void -lv_btn_toggle_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * btn) +DEFINE_WGL_NATIVE_WRAPPER(lv_btn_toggle_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, btn); + + (void)exec_env; lv_btn_toggle(btn); } static WGLNativeFuncDef btn_native_func_defs[] = { - { BTN_FUNC_ID_CREATE, lv_btn_create_wrapper, HAS_RET, 3, {1 | NULL_OK, 2 | NULL_OK, -1}, {-1} }, - { BTN_FUNC_ID_SET_TOGGLE, lv_btn_set_toggle_wrapper, NO_RET, 3, {1, -1}, {-1} }, - { BTN_FUNC_ID_SET_STATE, lv_btn_set_state_wrapper, NO_RET, 3, {1, -1}, {-1} }, -// { BTN_FUNC_ID_SET_STYLE, _btn_set_style, NO_RET, 2, {0, -1}, {-1} }, - { BTN_FUNC_ID_SET_INK_IN_TIME, lv_btn_set_ink_in_time_wrapper, NO_RET, 3, {1, -1}, {-1} }, - { BTN_FUNC_ID_SET_INK_OUT_TIME, lv_btn_set_ink_out_time_wrapper, NO_RET, 3, {1, -1}, {-1} }, - { BTN_FUNC_ID_SET_INK_WAIT_TIME, lv_btn_set_ink_wait_time_wrapper, NO_RET, 3, {1, -1}, {-1} }, - { BTN_FUNC_ID_GET_INK_IN_TIME, lv_btn_get_ink_in_time_wrapper, HAS_RET, 2, {1, -1}, {-1} }, - { BTN_FUNC_ID_GET_INK_OUT_TIME, lv_btn_get_ink_out_time_wrapper, HAS_RET, 2, {1, -1}, {-1} }, - { BTN_FUNC_ID_GET_INK_WAIT_TIME, lv_btn_get_ink_wait_time_wrapper, HAS_RET, 2, {1, -1}, {-1} }, - { BTN_FUNC_ID_GET_STATE, lv_btn_get_state_wrapper, HAS_RET, 2, {1, -1}, {-1} }, - { BTN_FUNC_ID_GET_TOGGLE, lv_btn_get_toggle_wrapper, HAS_RET, 2, {1, -1}, {-1} }, - { BTN_FUNC_ID_TOGGLE, lv_btn_toggle_wrapper, NO_RET, 2, {1, -1}, {-1} }, + { BTN_FUNC_ID_CREATE, lv_btn_create_wrapper, 2, false }, + { BTN_FUNC_ID_SET_TOGGLE, lv_btn_set_toggle_wrapper, 2, true }, + { BTN_FUNC_ID_SET_STATE, lv_btn_set_state_wrapper, 2, true }, + { BTN_FUNC_ID_SET_INK_IN_TIME, lv_btn_set_ink_in_time_wrapper, 2, true }, + { BTN_FUNC_ID_SET_INK_OUT_TIME, lv_btn_set_ink_out_time_wrapper, 2, true }, + { BTN_FUNC_ID_SET_INK_WAIT_TIME, lv_btn_set_ink_wait_time_wrapper, 2, true }, + { BTN_FUNC_ID_GET_INK_IN_TIME, lv_btn_get_ink_in_time_wrapper, 1, true }, + { BTN_FUNC_ID_GET_INK_OUT_TIME, lv_btn_get_ink_out_time_wrapper, 1, true }, + { BTN_FUNC_ID_GET_INK_WAIT_TIME, lv_btn_get_ink_wait_time_wrapper, 1, true }, + { BTN_FUNC_ID_GET_STATE, lv_btn_get_state_wrapper, 1, true }, + { BTN_FUNC_ID_GET_TOGGLE, lv_btn_get_toggle_wrapper, 1, true }, + { BTN_FUNC_ID_TOGGLE, lv_btn_toggle_wrapper, 1, true }, }; @@ -128,10 +152,9 @@ void wasm_btn_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 *argv, uint32 argc) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(btn_native_func_defs) / sizeof(WGLNativeFuncDef); - wgl_native_func_call(module_inst, + wgl_native_func_call(exec_env, btn_native_func_defs, size, func_id, diff --git a/core/app-framework/wgl/native/wgl_cb_wrapper.c b/core/app-framework/wgl/native/wgl_cb_wrapper.c index 77ea8e9ee..e306b1045 100644 --- a/core/app-framework/wgl/native/wgl_cb_wrapper.c +++ b/core/app-framework/wgl/native/wgl_cb_wrapper.c @@ -12,62 +12,88 @@ /* ------------------------------------------------------------------------- * Label widget native function wrappers * -------------------------------------------------------------------------*/ -static int32 -lv_cb_create_wrapper(wasm_module_inst_t module_inst, - lv_obj_t *par, lv_obj_t *copy) +DEFINE_WGL_NATIVE_WRAPPER(lv_cb_create_wrapper) { - return wgl_native_wigdet_create(WIDGET_TYPE_CB, par, copy, module_inst); + int32 res; + wgl_native_return_type(int32); + wgl_native_get_arg(uint32, par_obj_id); + wgl_native_get_arg(uint32, copy_obj_id); + wasm_module_inst_t module_inst = get_module_inst(exec_env); + + res = wgl_native_wigdet_create(WIDGET_TYPE_CB, par_obj_id, copy_obj_id, module_inst); + wgl_native_set_return(res); } -static void -lv_cb_set_text_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * cb, const char * txt) +DEFINE_WGL_NATIVE_WRAPPER(lv_cb_set_text_wrapper) { - (void)module_inst; - lv_cb_set_text(cb, txt); + char *text; + wgl_native_get_arg(lv_obj_t *, cb); + wgl_native_get_arg(uint32, text_offset); + wgl_native_get_arg(uint32, text_len); + wasm_module_inst_t module_inst = get_module_inst(exec_env); + + if (!validate_app_addr(text_offset, text_len) + || !(text = addr_app_to_native(text_offset))) + return; + + lv_cb_set_text(cb, text); } -static void -lv_cb_set_static_text_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * cb, const char * txt) +DEFINE_WGL_NATIVE_WRAPPER(lv_cb_set_static_text_wrapper) { - (void)module_inst; - lv_cb_set_static_text(cb, txt); + char *text; + wgl_native_get_arg(lv_obj_t *, cb); + wgl_native_get_arg(uint32, text_offset); + wgl_native_get_arg(uint32, text_len); + wasm_module_inst_t module_inst = get_module_inst(exec_env); + + if (!validate_app_addr(text_offset, text_len) + || !(text = addr_app_to_native(text_offset))) + return; + + lv_cb_set_static_text(cb, text); } -static int32 -lv_cb_get_text_length_wrapper(wasm_module_inst_t module_inst, - lv_obj_t *cb) +DEFINE_WGL_NATIVE_WRAPPER(lv_cb_get_text_length_wrapper) { - const char *text = lv_cb_get_text(cb); + const char *text; + wgl_native_return_type(int32); + wgl_native_get_arg(lv_obj_t *, cb); - if (text == NULL) - return 0; + (void)exec_env; - return strlen(text); + text = lv_cb_get_text(cb); + wgl_native_set_return(text ? strlen(text): 0); } -static char * -lv_cb_get_text_wrapper(wasm_module_inst_t module_inst, - lv_obj_t *cb, char *buffer, int buffer_len) +DEFINE_WGL_NATIVE_WRAPPER(lv_cb_get_text_wrapper) { - const char *text = lv_cb_get_text(cb); + const char *text; + char *buffer; + wgl_native_return_type(uint32); + wgl_native_get_arg(lv_obj_t *, cb); + wgl_native_get_arg(uint32, buffer_offset); + wgl_native_get_arg(int, buffer_len); + wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (text == NULL) - return 0; + if (!validate_app_addr(buffer_offset, buffer_len) + || !(buffer = addr_app_to_native(buffer_offset))) + return; - strncpy(buffer, text, buffer_len - 1); - buffer[buffer_len - 1] = '\0'; + if ((text = lv_cb_get_text(cb))) { + strncpy(buffer, text, buffer_len - 1); + buffer[buffer_len - 1] = '\0'; + } - return buffer; + wgl_native_set_return(buffer_offset); } static WGLNativeFuncDef cb_native_func_defs[] = { - { CB_FUNC_ID_CREATE, lv_cb_create_wrapper, HAS_RET, 3, {1 | NULL_OK, 2 | NULL_OK, -1}, {-1} }, - { CB_FUNC_ID_SET_TEXT, lv_cb_set_text_wrapper, NO_RET, 3, {1, -1}, {2, -1} }, - { CB_FUNC_ID_SET_STATIC_TEXT, lv_cb_set_static_text_wrapper, NO_RET, 3, {1, -1}, {2, -1} }, - { CB_FUNC_ID_GET_TEXT_LENGTH, lv_cb_get_text_length_wrapper, HAS_RET, 2, {1, -1}, {-1} }, - { CB_FUNC_ID_GET_TEXT, lv_cb_get_text_wrapper, RET_PTR, 4, {1, -1}, {2, -1} }, + { CB_FUNC_ID_CREATE, lv_cb_create_wrapper, 2, false }, + { CB_FUNC_ID_SET_TEXT, lv_cb_set_text_wrapper, 3, true }, + { CB_FUNC_ID_SET_STATIC_TEXT, lv_cb_set_static_text_wrapper, 3, true }, + { CB_FUNC_ID_GET_TEXT_LENGTH, lv_cb_get_text_length_wrapper, 1, true }, + { CB_FUNC_ID_GET_TEXT, lv_cb_get_text_wrapper, 3, true }, }; /*************** Native Interface to Wasm App ***********/ @@ -75,10 +101,9 @@ void wasm_cb_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 *argv, uint32 argc) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(cb_native_func_defs) / sizeof(WGLNativeFuncDef); - wgl_native_func_call(module_inst, + wgl_native_func_call(exec_env, cb_native_func_defs, size, func_id, diff --git a/core/app-framework/wgl/native/wgl_label_wrapper.c b/core/app-framework/wgl/native/wgl_label_wrapper.c index 8106c73d4..c1327e4db 100644 --- a/core/app-framework/wgl/native/wgl_label_wrapper.c +++ b/core/app-framework/wgl/native/wgl_label_wrapper.c @@ -12,53 +12,72 @@ /* ------------------------------------------------------------------------- * Label widget native function wrappers * -------------------------------------------------------------------------*/ -static int32 -lv_label_create_wrapper(wasm_module_inst_t module_inst, - lv_obj_t *par, lv_obj_t *copy) +DEFINE_WGL_NATIVE_WRAPPER(lv_label_create_wrapper) { - return wgl_native_wigdet_create(WIDGET_TYPE_LABEL, par, copy, module_inst); + int32 res; + wgl_native_return_type(int32); + wgl_native_get_arg(uint32, par_obj_id); + wgl_native_get_arg(uint32, copy_obj_id); + wasm_module_inst_t module_inst = get_module_inst(exec_env); + + res = wgl_native_wigdet_create(WIDGET_TYPE_LABEL, par_obj_id, copy_obj_id, module_inst); + wgl_native_set_return(res); } -static void -lv_label_set_text_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * label, const char * text) +DEFINE_WGL_NATIVE_WRAPPER(lv_label_set_text_wrapper) { - (void)module_inst; + char *text; + wgl_native_get_arg(lv_obj_t *, label); + wgl_native_get_arg(uint32, text_offset); + wgl_native_get_arg(uint32, text_len); + wasm_module_inst_t module_inst = get_module_inst(exec_env); + + if (!validate_app_addr(text_offset, text_len) + || !(text = addr_app_to_native(text_offset))) + return; + lv_label_set_text(label, text); } -static int32 -lv_label_get_text_length_wrapper(wasm_module_inst_t module_inst, - lv_obj_t *label) +DEFINE_WGL_NATIVE_WRAPPER(lv_label_get_text_length_wrapper) { - char *text = lv_label_get_text(label); + wgl_native_return_type(int32); + wgl_native_get_arg(lv_obj_t *, label); + const char *text; - if (text == NULL) - return 0; + (void)exec_env; - return strlen(text); + text = lv_label_get_text(label); + wgl_native_set_return(text ? strlen(text) : 0); } -static char * -lv_label_get_text_wrapper(wasm_module_inst_t module_inst, - lv_obj_t *label, char *buffer, int buffer_len) +DEFINE_WGL_NATIVE_WRAPPER(lv_label_get_text_wrapper) { - char *text = lv_label_get_text(label); + const char *text; + char *buffer; + wgl_native_return_type(uint32); + wgl_native_get_arg(lv_obj_t *, label); + wgl_native_get_arg(uint32, buffer_offset); + wgl_native_get_arg(int, buffer_len); + wasm_module_inst_t module_inst = get_module_inst(exec_env); - if (text == NULL) - return 0; + if (!validate_app_addr(buffer_offset, buffer_len) + || !(buffer = addr_app_to_native(buffer_offset))) + return; - strncpy(buffer, text, buffer_len - 1); - buffer[buffer_len - 1] = '\0'; + if ((text = lv_label_get_text(label))) { + strncpy(buffer, text, buffer_len - 1); + buffer[buffer_len - 1] = '\0'; + } - return buffer; + wgl_native_set_return(buffer_offset); } static WGLNativeFuncDef label_native_func_defs[] = { - { LABEL_FUNC_ID_CREATE, lv_label_create_wrapper, HAS_RET, 3, {1 | NULL_OK, 2 | NULL_OK, -1}, {-1} }, - { LABEL_FUNC_ID_SET_TEXT, lv_label_set_text_wrapper, NO_RET, 3, {1, -1}, {2, -1} }, - { LABEL_FUNC_ID_GET_TEXT_LENGTH, lv_label_get_text_length_wrapper, HAS_RET, 2, {1, -1}, {-1} }, - { LABEL_FUNC_ID_GET_TEXT, lv_label_get_text_wrapper, RET_PTR, 4, {1, -1}, {2, -1} }, + { LABEL_FUNC_ID_CREATE, lv_label_create_wrapper, 2, false }, + { LABEL_FUNC_ID_SET_TEXT, lv_label_set_text_wrapper, 3, true }, + { LABEL_FUNC_ID_GET_TEXT_LENGTH, lv_label_get_text_length_wrapper, 1, true }, + { LABEL_FUNC_ID_GET_TEXT, lv_label_get_text_wrapper, 3, true }, }; /*************** Native Interface to Wasm App ***********/ @@ -66,10 +85,9 @@ void wasm_label_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 *argv, uint32 argc) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(label_native_func_defs) / sizeof(WGLNativeFuncDef); - wgl_native_func_call(module_inst, + wgl_native_func_call(exec_env, label_native_func_defs, size, func_id, diff --git a/core/app-framework/wgl/native/wgl_list_wrapper.c b/core/app-framework/wgl/native/wgl_list_wrapper.c index 98430b750..926573ec6 100644 --- a/core/app-framework/wgl/native/wgl_list_wrapper.c +++ b/core/app-framework/wgl/native/wgl_list_wrapper.c @@ -12,38 +12,53 @@ /* ------------------------------------------------------------------------- * List widget native function wrappers * -------------------------------------------------------------------------*/ -static int32 -lv_list_create_wrapper(wasm_module_inst_t module_inst, - lv_obj_t *par, lv_obj_t *copy) +DEFINE_WGL_NATIVE_WRAPPER(lv_list_create_wrapper) { - return wgl_native_wigdet_create(WIDGET_TYPE_LIST, par, copy, module_inst); + int32 res; + wgl_native_return_type(int32); + wgl_native_get_arg(uint32, par_obj_id); + wgl_native_get_arg(uint32, copy_obj_id); + wasm_module_inst_t module_inst = get_module_inst(exec_env); + + res = wgl_native_wigdet_create(WIDGET_TYPE_LIST, par_obj_id, copy_obj_id, module_inst); + wgl_native_set_return(res); } -static int32 -lv_list_add_btn_wrapper(wasm_module_inst_t module_inst, - lv_obj_t *list, const char *text) +DEFINE_WGL_NATIVE_WRAPPER(lv_list_add_btn_wrapper) { + wgl_native_return_type(int32); + wgl_native_get_arg(lv_obj_t *, list); + wgl_native_get_arg(uint32, text_offset); + wgl_native_get_arg(uint32, text_len); uint32 btn_obj_id; lv_obj_t *btn; uint32 mod_id; + char *text; + wasm_module_inst_t module_inst = get_module_inst(exec_env); - btn = lv_list_add_btn(list, NULL, text); + if (!validate_app_addr(text_offset, text_len) + || !(text = addr_app_to_native(text_offset))) + return; - if (btn == NULL) - return 0; + if (!(btn = lv_list_add_btn(list, NULL, text))) { + wasm_runtime_set_exception(module_inst, "add button to list fail."); + return; + } mod_id = app_manager_get_module_id(Module_WASM_App, module_inst); bh_assert(mod_id != ID_NONE); - if (wgl_native_add_object(btn, mod_id, &btn_obj_id)) - return btn_obj_id; /* success return */ + if (!wgl_native_add_object(btn, mod_id, &btn_obj_id)) { + wasm_runtime_set_exception(module_inst, "add button to object list fail."); + return; + } - return 0; + wgl_native_set_return(btn_obj_id); } static WGLNativeFuncDef list_native_func_defs[] = { - { LIST_FUNC_ID_CREATE, lv_list_create_wrapper, HAS_RET, 3, {1 | NULL_OK, 2 | NULL_OK, -1}, {-1} }, - { LIST_FUNC_ID_ADD_BTN, lv_list_add_btn_wrapper, HAS_RET, 3, {1, -1}, {2, -1} }, + { LIST_FUNC_ID_CREATE, lv_list_create_wrapper, 2, false }, + { LIST_FUNC_ID_ADD_BTN, lv_list_add_btn_wrapper, 3, true }, }; /*************** Native Interface to Wasm App ***********/ @@ -51,10 +66,9 @@ void wasm_list_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 *argv, uint32 argc) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(list_native_func_defs) / sizeof(WGLNativeFuncDef); - wgl_native_func_call(module_inst, + wgl_native_func_call(exec_env, list_native_func_defs, size, func_id, diff --git a/core/app-framework/wgl/native/wgl_native_utils.c b/core/app-framework/wgl/native/wgl_native_utils.c index 005ab3fe7..081a31a28 100644 --- a/core/app-framework/wgl/native/wgl_native_utils.c +++ b/core/app-framework/wgl/native/wgl_native_utils.c @@ -10,18 +10,28 @@ #define THROW_EXC(msg) wasm_runtime_set_exception(module_inst, msg); -void -wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); - -uint32 wgl_native_wigdet_create(int8 widget_type, lv_obj_t *par, lv_obj_t *copy, +uint32 wgl_native_wigdet_create(int8 widget_type, + uint32 par_obj_id, + uint32 copy_obj_id, wasm_module_inst_t module_inst) { uint32 obj_id; - lv_obj_t *wigdet = NULL; + lv_obj_t *wigdet = NULL, *par = NULL, *copy = NULL; uint32 mod_id; //TODO: limit total widget number + /* validate the parent object id if not equal to 0 */ + if (par_obj_id != 0 && !wgl_native_validate_object(par_obj_id, &par)) { + THROW_EXC("create widget with invalid parent object."); + return 0; + } + /* validate the copy object id if not equal to 0 */ + if (copy_obj_id != 0 && !wgl_native_validate_object(copy_obj_id, ©)) { + THROW_EXC("create widget with invalid copy object."); + return 0; + } + if (par == NULL) par = lv_disp_get_scr_act(NULL); @@ -48,146 +58,58 @@ uint32 wgl_native_wigdet_create(int8 widget_type, lv_obj_t *par, lv_obj_t *copy, return 0; } -static void invokeNative(intptr_t argv[], uint32 argc, void (*native_code)()) -{ - bh_assert(argc >= 1); - - switch(argc) { - case 1: - native_code(argv[0]); - break; - case 2: - native_code(argv[0], argv[1]); - break; - case 3: - native_code(argv[0], argv[1], argv[2]); - break; - case 4: - native_code(argv[0], argv[1], argv[2], argv[3]); - break; - case 5: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4]); - break; - case 6: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); - break; - case 7: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], - argv[6]); - break; - case 8: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], - argv[6], argv[7]); - break; - case 9: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], - argv[6], argv[7], argv[8]); - break; - case 10: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], - argv[6], argv[7], argv[8], argv[9]); - break; - - default: - { - /* FIXME: If this happen, add more cases. */ - wasm_module_inst_t module_inst = (wasm_module_inst_t)argv[0]; - THROW_EXC("the argument number of native function exceeds maximum"); - return; - } - } -} - -typedef void (*GenericFunctionPointer)(); -typedef int32 (*Int32FuncPtr)(intptr_t *, uint32, GenericFunctionPointer); -typedef void (*VoidFuncPtr)(intptr_t *, uint32, GenericFunctionPointer); - -static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative; -static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; - -void wgl_native_func_call(wasm_module_inst_t module_inst, +void wgl_native_func_call(wasm_exec_env_t exec_env, WGLNativeFuncDef *funcs, uint32 size, int32 func_id, uint32 *argv, uint32 argc) { + typedef void (*WGLNativeFuncPtr)(wasm_exec_env_t, uint64*, uint32*); + WGLNativeFuncPtr wglNativeFuncPtr; + wasm_module_inst_t module_inst = get_module_inst(exec_env); WGLNativeFuncDef *func_def = funcs; WGLNativeFuncDef *func_def_end = func_def + size; - while (func_def < func_def_end) { - if (func_def->func_id == func_id) { - int i, obj_arg_num = 0, ptr_arg_num = 0, argc1 = 0; - intptr_t argv_copy_buf[16]; - intptr_t *argv_copy = argv_copy_buf; + /* Note: argv is validated in wasm_runtime_invoke_native() + * with pointer length equals to 1. Here validate the argv + * buffer again but with its total length in bytes */ + if (!wasm_runtime_validate_native_addr(module_inst, argv, argc * sizeof(uint32))) + return; - argc1++; /* module_inst */ - argc1 += func_def->arg_num; - if (argc1 > 16) { - argv_copy = (intptr_t *)wasm_runtime_malloc(func_def->arg_num * - sizeof(intptr_t)); - if (argv_copy == NULL) + while (func_def < func_def_end) { + if (func_def->func_id == func_id + && (uint32)func_def->arg_num == argc) { + uint64 argv_copy_buf[16], size; + uint64 *argv_copy = argv_copy_buf; + int i; + + if (argc > sizeof(argv_copy_buf) / sizeof(uint64)) { + size = sizeof(uint64) * (uint64)argc; + if (size >= UINT32_MAX + || !(argv_copy = wasm_runtime_malloc((uint32)size))) { + THROW_EXC("allocate memory failed."); return; + } + memset(argv_copy, 0, (uint32)size); } /* Init argv_copy */ - argv_copy[0] = (intptr_t)module_inst; for (i = 0; i < func_def->arg_num; i++) - argv_copy[i + 1] = (intptr_t)argv[i]; + *(uint32*)&argv_copy[i] = argv[i]; - /* Validate object arguments */ - i = 0; - for (; i < OBJ_ARG_NUM_MAX && func_def->obj_arg_indexes[i] != 0xff; - i++, obj_arg_num++) { - uint8 index = func_def->obj_arg_indexes[i]; - bool null_ok = index & NULL_OK; - - index = index & (~NULL_OK); - - /* Some API's allow to pass NULL obj, such as xxx_create() */ - if (argv_copy[index] == 0) { - if (!null_ok) { - THROW_EXC("the object id is 0 and invalid"); - goto fail; - } - /* Continue so that to pass null object validation */ - continue; - } - - if (!wgl_native_validate_object(argv_copy[index], - (lv_obj_t **)&argv_copy[index])) { + /* Validate the first argument which is a lvgl object if needed */ + if (func_def->check_obj) { + lv_obj_t *obj = NULL; + if (!wgl_native_validate_object(argv[0], &obj)) { THROW_EXC("the object is invalid"); goto fail; } + *(lv_obj_t **)&argv_copy[0] = obj; } - /* Validate address arguments */ - i = 0; - for (; i < PTR_ARG_NUM_MAX && func_def->ptr_arg_indexes[i] != 0xff; - i++, ptr_arg_num++) { - uint8 index = func_def->ptr_arg_indexes[i]; - - /* The index+1 arg is the data size to be validated */ - if (!validate_app_addr(argv_copy[index], argv_copy[index + 1])) - goto fail; - - /* Convert to native address before call lvgl function */ - argv_copy[index] = (intptr_t)addr_app_to_native(argv_copy[index]); - } - - if (func_def->has_ret == NO_RET) - invokeNative_Void(argv_copy, - argc1, - func_def->func_ptr); - else { - argv[0] = invokeNative_Int32(argv_copy, - argc1, - func_def->func_ptr); - /* Convert to app memory offset if return value is a - * native address pointer */ - if (func_def->has_ret == RET_PTR) - argv[0] = addr_native_to_app((char *)(intptr_t)argv[0]); - } + wglNativeFuncPtr = (WGLNativeFuncPtr)func_def->func_ptr; + wglNativeFuncPtr(exec_env, argv_copy, argv); if (argv_copy != argv_copy_buf) wasm_runtime_free(argv_copy); diff --git a/core/app-framework/wgl/native/wgl_native_utils.h b/core/app-framework/wgl/native/wgl_native_utils.h index fdb5e505a..1150f0120 100644 --- a/core/app-framework/wgl/native/wgl_native_utils.h +++ b/core/app-framework/wgl/native/wgl_native_utils.h @@ -15,19 +15,12 @@ extern "C" { #include "wasm_export.h" #include "bi-inc/wgl_shared_utils.h" -#define OBJ_ARG_NUM_MAX 4 -#define PTR_ARG_NUM_MAX 4 +#define wgl_native_return_type(type) type *wgl_ret = (type*)(args_ret) +#define wgl_native_get_arg(type, name) type name = *((type*)(args++)) +#define wgl_native_set_return(val) *wgl_ret = (val) -#define NULL_OK 0x80 - -enum { - /* The function has a normal return value (not a pointer) */ - HAS_RET, - /* The function doesn't have return value */ - NO_RET, - /* The function's return value is a native address pointer */ - RET_PTR -}; +#define DEFINE_WGL_NATIVE_WRAPPER(func_name) \ +static void func_name(wasm_exec_env_t exec_env, uint64 *args, uint32 *args_ret) enum { WIDGET_TYPE_BTN, @@ -46,19 +39,11 @@ typedef struct WGLNativeFuncDef { /* Native function pointer */ void *func_ptr; - /* whether has return value */ - uint8 has_ret; - /* argument number */ uint8 arg_num; - /* low 7 bit: obj argument index - * highest 1 bit: allow obj be null or not - * -1 means the end of this array */ - uint8 obj_arg_indexes[OBJ_ARG_NUM_MAX]; - - /* pointer argument indexes, -1 means the end of this array */ - uint8 ptr_arg_indexes[PTR_ARG_NUM_MAX]; + /* whether the first argument is lvgl object and needs validate */ + bool check_obj; } WGLNativeFuncDef; bool wgl_native_validate_object(int32 obj_id, lv_obj_t **obj); @@ -66,11 +51,11 @@ bool wgl_native_validate_object(int32 obj_id, lv_obj_t **obj); bool wgl_native_add_object(lv_obj_t *obj, uint32 module_id, uint32 *obj_id); uint32 wgl_native_wigdet_create(int8 widget_type, - lv_obj_t *par, - lv_obj_t *copy, + uint32 par_obj_id, + uint32 copy_obj_id, wasm_module_inst_t module_inst); -void wgl_native_func_call(wasm_module_inst_t module_inst, +void wgl_native_func_call(wasm_exec_env_t exec_env, WGLNativeFuncDef *funcs, uint32 size, int32 func_id, diff --git a/core/app-framework/wgl/native/wgl_obj_wrapper.c b/core/app-framework/wgl/native/wgl_obj_wrapper.c index 31b648c0e..801c55d2c 100644 --- a/core/app-framework/wgl/native/wgl_obj_wrapper.c +++ b/core/app-framework/wgl/native/wgl_obj_wrapper.c @@ -6,8 +6,7 @@ #include "lvgl.h" #include "app_manager_export.h" #include "module_wasm_app.h" -#include "bh_list.h" -#include "bh_thread.h" +#include "bh_platform.h" #include "wgl_native_utils.h" #include "wgl.h" @@ -39,6 +38,10 @@ static korp_mutex g_object_list_mutex; static bool lv_task_handler_thread_run = true; +static korp_mutex task_handler_lock; + +static korp_cond task_handler_cond; + static void app_mgr_object_event_callback(module_data *m_data, bh_message_t msg) { uint32 argv[2]; @@ -79,7 +82,7 @@ static void cleanup_object_list(uint32 module_id) { object_node_t *elem; - vm_mutex_lock(&g_object_list_mutex); + os_mutex_lock(&g_object_list_mutex); while (true) { bool found = false; @@ -104,7 +107,7 @@ static void cleanup_object_list(uint32 module_id) break; } - vm_mutex_unlock(&g_object_list_mutex); + os_mutex_unlock(&g_object_list_mutex); } static bool init_object_event_callback_framework() @@ -128,20 +131,20 @@ bool wgl_native_validate_object(int32 obj_id, lv_obj_t **obj) { object_node_t *elem; - vm_mutex_lock(&g_object_list_mutex); + os_mutex_lock(&g_object_list_mutex); elem = (object_node_t *)bh_list_first_elem(&g_object_list); while (elem) { if (obj_id == elem->obj_id) { if (obj != NULL) *obj = elem->obj; - vm_mutex_unlock(&g_object_list_mutex); + os_mutex_unlock(&g_object_list_mutex); return true; } elem = (object_node_t *) bh_list_elem_next(elem); } - vm_mutex_unlock(&g_object_list_mutex); + os_mutex_unlock(&g_object_list_mutex); return false; } @@ -165,9 +168,9 @@ bool wgl_native_add_object(lv_obj_t *obj, uint32 module_id, uint32 *obj_id) node->obj_id = g_obj_id_max; node->module_id = module_id; - vm_mutex_lock(&g_object_list_mutex); + os_mutex_lock(&g_object_list_mutex); bh_list_insert(&g_object_list, node); - vm_mutex_unlock(&g_object_list_mutex); + os_mutex_unlock(&g_object_list_mutex); if (obj_id != NULL) *obj_id = node->obj_id; @@ -194,20 +197,20 @@ static void _obj_del_recursive(lv_obj_t *obj) i = i_next; } - vm_mutex_lock(&g_object_list_mutex); + os_mutex_lock(&g_object_list_mutex); elem = (object_node_t *)bh_list_first_elem(&g_object_list); while (elem) { if (obj == elem->obj) { bh_list_remove(&g_object_list, elem); wasm_runtime_free(elem); - vm_mutex_unlock(&g_object_list_mutex); + os_mutex_unlock(&g_object_list_mutex); return; } elem = (object_node_t *) bh_list_elem_next(elem); } - vm_mutex_unlock(&g_object_list_mutex); + os_mutex_unlock(&g_object_list_mutex); } static void _obj_clean_recursive(lv_obj_t *obj) @@ -255,52 +258,55 @@ static void internal_lv_obj_event_cb(lv_obj_t *obj, lv_event_t event) { object_node_t *elem; - vm_mutex_lock(&g_object_list_mutex); + os_mutex_lock(&g_object_list_mutex); elem = (object_node_t *)bh_list_first_elem(&g_object_list); while (elem) { if (obj == elem->obj) { post_widget_msg_to_module(elem, event); - vm_mutex_unlock(&g_object_list_mutex); + os_mutex_unlock(&g_object_list_mutex); return; } elem = (object_node_t *) bh_list_elem_next(elem); } - vm_mutex_unlock(&g_object_list_mutex); + os_mutex_unlock(&g_object_list_mutex); } static void* lv_task_handler_thread_routine (void *arg) { - korp_sem sem; - - if (vm_sem_init(&sem, 1) != 0) { - printf("Init semaphore for lvgl task handler thread fail!\n"); - return NULL; - } + os_mutex_lock(&task_handler_lock); while (lv_task_handler_thread_run) { - vm_sem_reltimedwait(&sem, 100); + os_cond_reltimedwait(&task_handler_cond, &task_handler_lock, + 100 * 1000); lv_task_handler(); } - vm_sem_destroy(&sem); - + os_mutex_unlock(&task_handler_lock); return NULL; } void wgl_init(void) { - korp_thread tid; + korp_tid tid; + + if (os_mutex_init(&task_handler_lock) != 0) + return; + + if (os_cond_init(&task_handler_cond) != 0) { + os_mutex_destroy(&task_handler_lock); + return; + } lv_init(); bh_list_init(&g_object_list); - vm_recursive_mutex_init(&g_object_list_mutex); + os_recursive_mutex_init(&g_object_list_mutex); init_object_event_callback_framework(); /* new a thread, call lv_task_handler periodically */ - vm_thread_create(&tid, + os_thread_create(&tid, lv_task_handler_thread_routine, NULL, BH_APPLET_PRESERVED_STACK_SIZE); @@ -309,34 +315,41 @@ void wgl_init(void) void wgl_exit(void) { lv_task_handler_thread_run = false; + os_cond_destroy(&task_handler_cond); + os_mutex_destroy(&task_handler_lock); } /* ------------------------------------------------------------------------- * Obj native function wrappers * -------------------------------------------------------------------------*/ -static lv_res_t -lv_obj_del_wrapper(wasm_module_inst_t module_inst, lv_obj_t *obj) +DEFINE_WGL_NATIVE_WRAPPER(lv_obj_del_wrapper) { - (void)module_inst; + lv_res_t res; + wgl_native_return_type(lv_res_t); + wgl_native_get_arg(lv_obj_t *, obj); + + (void)exec_env; /* Recursively delete object node in the list belong to this * parent object including itself */ _obj_del_recursive(obj); - - return lv_obj_del(obj); + res = lv_obj_del(obj); + wgl_native_set_return(res); } -static void -lv_obj_del_async_wrapper(wasm_module_inst_t module_inst, lv_obj_t * obj) +DEFINE_WGL_NATIVE_WRAPPER(lv_obj_del_async_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, obj); + + (void)exec_env; lv_obj_del_async(obj); } -static void -lv_obj_clean_wrapper(wasm_module_inst_t module_inst, lv_obj_t *obj) +DEFINE_WGL_NATIVE_WRAPPER(lv_obj_clean_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, obj); + + (void)exec_env; /* Recursively delete child object node in the list belong to this * parent object */ @@ -346,33 +359,40 @@ lv_obj_clean_wrapper(wasm_module_inst_t module_inst, lv_obj_t *obj) lv_obj_clean(obj); } -static void -lv_obj_align_wrapper(wasm_module_inst_t module_inst, - lv_obj_t * obj, - const lv_obj_t * base, - lv_align_t align, - lv_coord_t x_mod, - lv_coord_t y_mod) +DEFINE_WGL_NATIVE_WRAPPER(lv_obj_align_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, obj); + wgl_native_get_arg(uint32, base_obj_id); + wgl_native_get_arg(lv_align_t, align); + wgl_native_get_arg(lv_coord_t, x_mod); + wgl_native_get_arg(lv_coord_t, y_mod); + lv_obj_t *base = NULL; + wasm_module_inst_t module_inst = get_module_inst(exec_env); + + /* validate the base object id if not equal to 0 */ + if (base_obj_id != 0 && !wgl_native_validate_object(base_obj_id, &base)) { + wasm_runtime_set_exception(module_inst, "align with invalid base object."); + return; + } + lv_obj_align(obj, base, align, x_mod, y_mod); } -static void -lv_obj_set_event_cb_wrapper(wasm_module_inst_t module_inst, lv_obj_t *obj) +DEFINE_WGL_NATIVE_WRAPPER(lv_obj_set_event_cb_wrapper) { - (void)module_inst; + wgl_native_get_arg(lv_obj_t *, obj); + (void)exec_env; lv_obj_set_event_cb(obj, internal_lv_obj_event_cb); } + /* ------------------------------------------------------------------------- */ - static WGLNativeFuncDef obj_native_func_defs[] = { - { OBJ_FUNC_ID_DEL, lv_obj_del_wrapper, HAS_RET, 2, {1, -1}, {-1} }, - { OBJ_FUNC_ID_DEL_ASYNC, lv_obj_del_async_wrapper, NO_RET, 2, {1, -1}, {-1} }, - { OBJ_FUNC_ID_CLEAN, lv_obj_clean_wrapper, NO_RET, 2, {1, -1}, {-1} }, - { OBJ_FUNC_ID_ALIGN, lv_obj_align_wrapper, NO_RET, 6, {1, 2 | NULL_OK, -1}, {-1} }, - { OBJ_FUNC_ID_SET_EVT_CB, lv_obj_set_event_cb_wrapper, NO_RET, 2, {1, -1}, {-1} }, + { OBJ_FUNC_ID_DEL, lv_obj_del_wrapper, 1, true }, + { OBJ_FUNC_ID_DEL_ASYNC, lv_obj_del_async_wrapper, 1, true }, + { OBJ_FUNC_ID_CLEAN, lv_obj_clean_wrapper, 1, true }, + { OBJ_FUNC_ID_ALIGN, lv_obj_align_wrapper, 5, true }, + { OBJ_FUNC_ID_SET_EVT_CB, lv_obj_set_event_cb_wrapper, 1, true }, }; /*************** Native Interface to Wasm App ***********/ @@ -380,10 +400,9 @@ void wasm_obj_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 *argv, uint32 argc) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(obj_native_func_defs) / sizeof(WGLNativeFuncDef); - wgl_native_func_call(module_inst, + wgl_native_func_call(exec_env, obj_native_func_defs, size, func_id, diff --git a/core/app-mgr/app-manager/app_manager.c b/core/app-mgr/app-manager/app_manager.c index ca41d6ffd..d68861823 100644 --- a/core/app-mgr/app-manager/app_manager.c +++ b/core/app-mgr/app-manager/app_manager.c @@ -5,8 +5,7 @@ #include "app_manager.h" #include "app_manager_host.h" -#include "bh_queue.h" -#include "bh_thread.h" +#include "bh_platform.h" #include "bi-inc/attr_container.h" #include "event.h" #include "watchdog.h" @@ -38,7 +37,7 @@ void app_manager_post_applets_update_event() return; } - vm_mutex_lock(&module_data_list_lock); + os_mutex_lock(&module_data_list_lock); m_data = module_data_list; while (m_data) { @@ -80,7 +79,8 @@ void app_manager_post_applets_update_event() app_manager_printf("Post applets update event success!\n"); attr_container_dump(attr_cont); - fail: vm_mutex_unlock(&module_data_list_lock); +fail: + os_mutex_unlock(&module_data_list_lock); attr_container_destroy(attr_cont); } @@ -89,7 +89,7 @@ static int get_applets_count() module_data *m_data; int num = 0; - vm_mutex_lock(&module_data_list_lock); + os_mutex_lock(&module_data_list_lock); m_data = module_data_list; while (m_data) { @@ -97,7 +97,7 @@ static int get_applets_count() m_data = m_data->next; } - vm_mutex_unlock(&module_data_list_lock); + os_mutex_unlock(&module_data_list_lock); return num; } @@ -118,7 +118,7 @@ static bool app_manager_query_applets(request_t *msg, const char *name) return false; } - vm_mutex_lock(&module_data_list_lock); + os_mutex_lock(&module_data_list_lock); m_data = module_data_list; while (m_data) { @@ -186,7 +186,8 @@ static bool app_manager_query_applets(request_t *msg, const char *name) app_manager_printf("Query Applets success!\n"); attr_container_dump(attr_cont); - fail: vm_mutex_unlock(&module_data_list_lock); +fail: + os_mutex_unlock(&module_data_list_lock); attr_container_destroy(attr_cont); return ret; } @@ -368,9 +369,11 @@ void app_manager_startup(host_interface *interface) /* Enter loop run */ bh_queue_enter_loop_run(g_app_mgr_queue, app_manager_queue_callback, NULL); - fail2: module_data_list_destroy(); +fail2: + module_data_list_destroy(); - fail1: bh_queue_destroy(g_app_mgr_queue); +fail1: + bh_queue_destroy(g_app_mgr_queue); } #include "module_config.h" diff --git a/core/app-mgr/app-manager/app_manager.h b/core/app-mgr/app-manager/app_manager.h index c41002f13..fb2a42f71 100644 --- a/core/app-mgr/app-manager/app_manager.h +++ b/core/app-mgr/app-manager/app_manager.h @@ -7,9 +7,6 @@ #define APP_MANAGER_H #include "bh_platform.h" -#include "bh_common.h" -#include "bh_queue.h" -#include "bh_types.h" #include "app_manager_export.h" #include "native_interface.h" #include "bi-inc/shared_utils.h" @@ -21,8 +18,8 @@ extern "C" { #define APP_MGR_MALLOC wasm_runtime_malloc #define APP_MGR_FREE wasm_runtime_free -/* bh_printf is defined in each platform */ -#define app_manager_printf bh_printf +/* os_printf is defined in each platform */ +#define app_manager_printf os_printf #define SEND_ERR_RESPONSE(mid, err_msg) do { \ app_manager_printf("%s\n", err_msg); \ diff --git a/core/app-mgr/app-manager/app_manager_host.c b/core/app-mgr/app-manager/app_manager_host.c index db50cb1b4..c98a2c8ad 100644 --- a/core/app-mgr/app-manager/app_manager_host.c +++ b/core/app-mgr/app-manager/app_manager_host.c @@ -3,13 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_common.h" -#include "bh_types.h" +#include "bh_platform.h" #include "app_manager_host.h" #include "app_manager.h" #include "app_manager_export.h" #include "coap_ext.h" -#include "bh_thread.h" /* host communication interface */ static host_interface host_commu; @@ -235,7 +233,7 @@ int aee_host_msg_callback(void *msg, uint16_t msg_len) bool app_manager_host_init(host_interface *interface) { - vm_mutex_init(&host_lock); + os_mutex_init(&host_lock); memset(&recv_ctx, 0, sizeof(recv_ctx)); host_commu.init = interface->init; @@ -255,7 +253,7 @@ int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size) int size_s = size, n; char header[16]; - vm_mutex_lock(&host_lock); + os_mutex_lock(&host_lock); /* leading bytes */ bh_memcpy_s(header, 2, leadings, 2); @@ -270,13 +268,13 @@ int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size) bh_memcpy_s(header + 4, 4, &size_s, 4); n = host_commu.send(NULL, header, 8); if (n != 8) { - vm_mutex_unlock(&host_lock); + os_mutex_unlock(&host_lock); return 0; } /* payload */ n = host_commu.send(NULL, buf, size); - vm_mutex_unlock(&host_lock); + os_mutex_unlock(&host_lock); printf("sent %d bytes to host\n", n); return n; diff --git a/core/app-mgr/app-manager/module_jeff.c b/core/app-mgr/app-manager/module_jeff.c index 25ded4be0..7e1a8be34 100644 --- a/core/app-mgr/app-manager/module_jeff.c +++ b/core/app-mgr/app-manager/module_jeff.c @@ -269,12 +269,12 @@ check_exception() jeff_runtime_call_java(method, argc, argv, argt); if (is_wd_started) { - vm_mutex_lock(&wd_timer->lock); + os_mutex_lock(&wd_timer->lock); if (!wd_timer->is_interrupting) { wd_timer->is_stopped = true; watchdog_timer_stop(wd_timer); } - vm_mutex_unlock(&wd_timer->lock); + os_mutex_unlock(&wd_timer->lock); } return !check_exception(); @@ -1395,7 +1395,7 @@ check_exception() if (applet_data->vm_instance->main_file) { app_manager_printf("Watchdog cancel applet main thread.\n"); - vm_thread_cancel(applet_data->vm_instance->main_tlr.handle); + os_thread_cancel(applet_data->vm_instance->main_tlr.handle); /* k_thread_abort(applet_data->vm_instance->main_tlr.handle); */ } diff --git a/core/app-mgr/app-manager/module_utils.c b/core/app-mgr/app-manager/module_utils.c index 1f7219c8d..637feeaed 100644 --- a/core/app-mgr/app-manager/module_utils.c +++ b/core/app-mgr/app-manager/module_utils.c @@ -5,8 +5,7 @@ #include "app_manager.h" #include "app_manager_host.h" -#include "bh_queue.h" -#include "bh_thread.h" +#include "bh_platform.h" #include "bi-inc/attr_container.h" #include "event.h" #include "watchdog.h" @@ -21,13 +20,13 @@ module_data *module_data_list; bool module_data_list_init() { module_data_list = NULL; - return !vm_mutex_init(&module_data_list_lock) ? true : false; + return !os_mutex_init(&module_data_list_lock) ? true : false; } void module_data_list_destroy() { - vm_mutex_lock(&module_data_list_lock); + os_mutex_lock(&module_data_list_lock); if (module_data_list) { while (module_data_list) { module_data *p = module_data_list->next; @@ -35,14 +34,14 @@ void module_data_list_destroy() module_data_list = p; } } - vm_mutex_unlock(&module_data_list_lock); - vm_mutex_destroy(&module_data_list_lock); + os_mutex_unlock(&module_data_list_lock); + os_mutex_destroy(&module_data_list_lock); } static void module_data_list_add(module_data *m_data) { static uint32 module_id_max = 1; - vm_mutex_lock(&module_data_list_lock); + os_mutex_lock(&module_data_list_lock); // reserve some special ID // TODO: check the new id is not already occupied! if (module_id_max == 0xFFFFFFF0) @@ -55,12 +54,12 @@ static void module_data_list_add(module_data *m_data) m_data->next = module_data_list; module_data_list = m_data; } - vm_mutex_unlock(&module_data_list_lock); + os_mutex_unlock(&module_data_list_lock); } void module_data_list_remove(module_data *m_data) { - vm_mutex_lock(&module_data_list_lock); + os_mutex_lock(&module_data_list_lock); if (module_data_list) { if (module_data_list == m_data) module_data_list = module_data_list->next; @@ -74,46 +73,46 @@ void module_data_list_remove(module_data *m_data) p->next = p->next->next; } } - vm_mutex_unlock(&module_data_list_lock); + os_mutex_unlock(&module_data_list_lock); } module_data* module_data_list_lookup(const char *module_name) { - vm_mutex_lock(&module_data_list_lock); + os_mutex_lock(&module_data_list_lock); if (module_data_list) { module_data *p = module_data_list; while (p) { /* Search by module name */ if (!strcmp(module_name, p->module_name)) { - vm_mutex_unlock(&module_data_list_lock); + os_mutex_unlock(&module_data_list_lock); return p; } p = p->next; } } - vm_mutex_unlock(&module_data_list_lock); + os_mutex_unlock(&module_data_list_lock); return NULL; } module_data* module_data_list_lookup_id(unsigned int module_id) { - vm_mutex_lock(&module_data_list_lock); + os_mutex_lock(&module_data_list_lock); if (module_data_list) { module_data *p = module_data_list; while (p) { /* Search by module name */ if (module_id == p->id) { - vm_mutex_unlock(&module_data_list_lock); + os_mutex_unlock(&module_data_list_lock); return p; } p = p->next; } } - vm_mutex_unlock(&module_data_list_lock); + os_mutex_unlock(&module_data_list_lock); return NULL; } @@ -201,7 +200,7 @@ void release_module(module_data *m_data) int check_modules_timer_expiry() { - vm_mutex_lock(&module_data_list_lock); + os_mutex_lock(&module_data_list_lock); module_data *p = module_data_list; int ms_to_expiry = -1; @@ -215,7 +214,7 @@ int check_modules_timer_expiry() p = p->next; } - vm_mutex_unlock(&module_data_list_lock); + os_mutex_unlock(&module_data_list_lock); return ms_to_expiry; } diff --git a/core/app-mgr/app-manager/module_wasm_app.c b/core/app-mgr/app-manager/module_wasm_app.c index 1035a348c..18f877e9c 100644 --- a/core/app-mgr/app-manager/module_wasm_app.c +++ b/core/app-mgr/app-manager/module_wasm_app.c @@ -7,9 +7,8 @@ #include "native_interface.h" /* for request_t type */ #include "app_manager_host.h" -#include "bh_queue.h" +#include "bh_platform.h" #include "bi-inc/attr_container.h" -#include "bh_thread.h" #include "coap_ext.h" #include "event.h" #include "watchdog.h" @@ -429,7 +428,6 @@ wasm_app_routine(void *arg) module_data *m_data = (module_data *) arg; wasm_data *wasm_app_data = (wasm_data*) m_data->internal_data; wasm_module_inst_t inst = wasm_app_data->wasm_module_inst; - korp_tid thread = wasm_app_data->thread_id; /* Set m_data to the VM managed instance's custom data */ wasm_runtime_set_custom_data(inst, m_data); @@ -489,8 +487,6 @@ fail2: wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onDestroy, 0, NULL); fail1: - vm_thread_detach(thread); - vm_thread_exit(NULL); return NULL; } @@ -847,7 +843,7 @@ wasm_app_module_install(request_t * msg) } /* Create WASM app thread. */ - if (vm_thread_create(&wasm_app_data->thread_id, wasm_app_routine, + if (os_thread_create(&wasm_app_data->thread_id, wasm_app_routine, (void*) m_data, APP_THREAD_STACK_SIZE_DEFAULT) != 0) { module_data_list_remove(m_data); SEND_ERR_RESPONSE(msg->mid, @@ -941,7 +937,7 @@ wasm_app_module_uninstall(request_t *msg) /* Wait for wasm app thread to exit */ wasm_app_data = (wasm_data*) m_data->internal_data; - vm_thread_join(wasm_app_data->thread_id, NULL, -1); + os_thread_join(wasm_app_data->thread_id, NULL); cleanup_app_resource(m_data); @@ -1358,7 +1354,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, total_size = (total_size + 3) & ~((uint64)3); if (total_size >= UINT32_MAX || !(section->section_body = - bh_mmap(NULL, (uint32)total_size, + os_mmap(NULL, (uint32)total_size, map_prot, map_flags))) { app_manager_printf("Allocate executable memory failed!\n"); goto fail; @@ -1553,7 +1549,7 @@ destroy_all_aot_sections(aot_section_list_t sections) aot_section_t *next = cur->next; if (cur->section_body != NULL) { if (cur->section_type == AOT_SECTION_TYPE_TEXT) - bh_munmap(cur->section_body, cur->section_body_size); + os_munmap(cur->section_body, cur->section_body_size); else APP_MGR_FREE(cur->section_body); } @@ -1583,7 +1579,7 @@ destroy_part_aot_sections(aot_section_list_t *p_sections, if (cur->section_body != NULL) { if (cur->section_type == AOT_SECTION_TYPE_TEXT) - bh_munmap(cur->section_body, cur->section_body_size); + os_munmap(cur->section_body, cur->section_body_size); else APP_MGR_FREE(cur->section_body); } diff --git a/core/app-mgr/app-manager/watchdog.c b/core/app-mgr/app-manager/watchdog.c index 2f3179962..ccaf5c2c4 100644 --- a/core/app-mgr/app-manager/watchdog.c +++ b/core/app-mgr/app-manager/watchdog.c @@ -4,8 +4,7 @@ */ #include "watchdog.h" -#include "bh_queue.h" -#include "bh_thread.h" +#include "bh_platform.h" #define WATCHDOG_THREAD_PRIORITY 5 @@ -20,7 +19,7 @@ static void watchdog_timer_callback(void *timer) watchdog_timer_stop(wd_timer); - vm_mutex_lock(&wd_timer->lock); + os_mutex_lock(&wd_timer->lock); if (!wd_timer->is_stopped) { @@ -30,7 +29,7 @@ static void watchdog_timer_callback(void *timer) sizeof(module_data)); } - vm_mutex_unlock(&wd_timer->lock); + os_mutex_unlock(&wd_timer->lock); } #endif @@ -39,12 +38,12 @@ bool watchdog_timer_init(module_data *m_data) #ifdef WATCHDOG_ENABLED /* TODO */ watchdog_timer *wd_timer = &m_data->wd_timer; - if (0 != vm_mutex_init(&wd_timer->lock)) + if (0 != os_mutex_init(&wd_timer->lock)) return false; if (!(wd_timer->timer_handle = app_manager_timer_create(watchdog_timer_callback, wd_timer))) { - vm_mutex_destroy(&wd_timer->lock); + os_mutex_destroy(&wd_timer->lock); return false; } @@ -59,20 +58,20 @@ void watchdog_timer_destroy(watchdog_timer *wd_timer) { #ifdef WATCHDOG_ENABLED /* TODO */ app_manager_timer_destroy(wd_timer->timer_handle); - vm_mutex_destroy(&wd_timer->lock); + os_mutex_destroy(&wd_timer->lock); #endif } void watchdog_timer_start(watchdog_timer *wd_timer) { - vm_mutex_lock(&wd_timer->lock); + os_mutex_lock(&wd_timer->lock); wd_timer->is_interrupting = false; wd_timer->is_stopped = false; app_manager_timer_start(wd_timer->timer_handle, wd_timer->module_data->timeout); - vm_mutex_unlock(&wd_timer->lock); + os_mutex_unlock(&wd_timer->lock); } void watchdog_timer_stop(watchdog_timer *wd_timer) diff --git a/core/shared/include/config.h b/core/config.h similarity index 91% rename from core/shared/include/config.h rename to core/config.h index 66bb55f57..be9a24181 100644 --- a/core/shared/include/config.h +++ b/core/config.h @@ -8,6 +8,7 @@ #if !defined(BUILD_TARGET_X86_64) \ && !defined(BUILD_TARGET_AMD_64) \ + && !defined(BUILD_TARGET_AARCH64) \ && !defined(BUILD_TARGET_X86_32) \ && !defined(BUILD_TARGET_ARM) \ && !defined(BUILD_TARGET_ARM_VFP) \ @@ -19,6 +20,8 @@ #define BUILD_TARGET_X86_64 #elif defined(__amd64__) || defined(__amd64) #define BUILD_TARGET_AMD_64 +#elif defined(__aarch64__) +#define BUILD_TARGET_AARCH64 #elif defined(__i386__) || defined(__i386) || defined(i386) #define BUILD_TARGET_X86_32 #elif defined(__thumb__) @@ -36,6 +39,10 @@ #endif #endif +#ifndef BH_DEBUG +#define BH_DEBUG 0 +#endif + enum { /* Memory allocator ems */ MEM_ALLOCATOR_EMS = 0, @@ -105,8 +112,16 @@ enum { #define WASM_ENABLE_ABS_LABEL_ADDR 0 #endif +/* Enable opcode counter or not */ +#ifndef WASM_ENABLE_OPCODE_COUNTER +#define WASM_ENABLE_OPCODE_COUNTER 0 +#endif + /* Heap and stack profiling */ -#define BEIHAI_ENABLE_MEMORY_PROFILING 0 +#define BH_ENABLE_MEMORY_PROFILING 0 + +/* Heap verification */ +#define BH_ENABLE_GC_VERIFY 0 /* Max app number of all modules */ #define MAX_APP_INSTALLATIONS 3 @@ -144,7 +159,7 @@ enum { /* Default min/max heap size of each app */ #define APP_HEAP_SIZE_DEFAULT (8 * 1024) #define APP_HEAP_SIZE_MIN (2 * 1024) -#define APP_HEAP_SIZE_MAX (1024 * 1024) +#define APP_HEAP_SIZE_MAX (512 * 1024 * 1024) /* Default wasm stack size of each app */ #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 3b2baaaa9..f4115bbd0 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -140,6 +140,7 @@ GET_U64_FROM_ADDR(uint32 *addr) #define E_MACHINE_MIPS 8 /* MIPS R3000 big-endian */ #define E_MACHINE_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ #define E_MACHINE_ARM 40 /* ARM/Thumb */ +#define E_MACHINE_AARCH64 183 /* AArch64 */ #define E_MACHINE_ARC 45 /* Argonaut RISC Core */ #define E_MACHINE_IA_64 50 /* Intel Merced */ #define E_MACHINE_MIPS_X 51 /* Stanford MIPS-X */ @@ -196,6 +197,7 @@ get_aot_file_target(AOTTargetInfo *target_info, machine_type = "i386"; break; case E_MACHINE_ARM: + case E_MACHINE_AARCH64: machine_type = target_info->arch; break; case E_MACHINE_MIPS: @@ -614,6 +616,7 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, /* Create each import global */ for (i = 0; i < module->import_global_count; i++) { + buf = (uint8*)align_ptr(buf, 2); read_uint8(buf, buf_end, import_globals[i].type); read_uint8(buf, buf_end, import_globals[i].is_mutable); read_string(buf, buf_end, import_globals[i].module_name); @@ -783,13 +786,16 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, if (!(import_funcs[i].func_ptr_linked = wasm_native_resolve_symbol(module_name, field_name, import_funcs[i].func_type, - &import_funcs[i].signature))) { + &import_funcs[i].signature, + &import_funcs[i].attachment, + &import_funcs[i].call_conv_raw))) { LOG_WARNING("warning: fail to link import function (%s, %s)\n", module_name, field_name); } #if WASM_ENABLE_LIBC_WASI != 0 - if (!strcmp(import_funcs[i].module_name, "wasi_unstable")) + if (!strcmp(import_funcs[i].module_name, "wasi_unstable") + || !strcmp(import_funcs[i].module_name, "wasi_snapshot_preview1")) module->is_wasi_module = true; #endif } @@ -829,7 +835,7 @@ destroy_object_data_sections(AOTObjectDataSection *data_sections, AOTObjectDataSection *data_section = data_sections; for (i = 0; i < data_section_count; i++, data_section++) if (data_section->data) - bh_munmap(data_section->data, data_section->size); + os_munmap(data_section->data, data_section->size); wasm_runtime_free(data_sections); } @@ -872,7 +878,7 @@ load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory for data */ if (!(data_sections[i].data = - bh_mmap(NULL, data_sections[i].size, map_prot, map_flags))) { + os_mmap(NULL, data_sections[i].size, map_prot, map_flags))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -980,14 +986,21 @@ load_text_section(const uint8 *buf, const uint8 *buf_end, return false; } - module->code = (void*)buf; - module->code_size = (uint32)(buf_end - buf); + read_uint32(buf, buf_end, module->literal_size); + + /* literal data is at begining of the text section */ + module->literal = (uint8*)buf; + module->code = (void*)(buf + module->literal_size); + module->code_size = (uint32)(buf_end - (uint8*)module->code); if (module->code_size > 0) { plt_base = (uint8*)buf_end - get_plt_table_size(); init_plt_table(plt_base); } return true; + +fail: + return false; } static bool @@ -1179,13 +1192,20 @@ resolve_target_sym(const char *symbol, int32 *p_index) return NULL; } +static bool +is_literal_relocation(const char *reloc_sec_name) +{ + return !strcmp(reloc_sec_name, ".rela.literal"); +} + static bool do_text_relocation(AOTModule *module, AOTRelocationGroup *group, char *error_buf, uint32 error_buf_size) { - uint8 *aot_text = module->code; - uint32 aot_text_size = module->code_size; + bool is_literal = is_literal_relocation(group->section_name); + uint8 *aot_text = is_literal ? module->literal : module->code; + uint32 aot_text_size = is_literal ? module->literal_size : module->code_size; uint32 i, func_index, symbol_len; char symbol_buf[128] = { 0 }, *symbol, *p; void *symbol_addr; @@ -1243,6 +1263,9 @@ do_text_relocation(AOTModule *module, goto check_symbol_fail; } } + else if (!strcmp(symbol, ".literal")) { + symbol_addr = module->literal; + } else if (!(symbol_addr = resolve_target_sym(symbol, &symbol_index))) { if (error_buf != NULL) snprintf(error_buf, error_buf_size, @@ -1490,7 +1513,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, } if (!strcmp(group->section_name, ".rel.text") - || !strcmp(group->section_name, ".rela.text")) { + || !strcmp(group->section_name, ".rela.text") + || !strcmp(group->section_name, ".rela.literal")) { if (!do_text_relocation(module, group, error_buf, error_buf_size)) return false; } @@ -1594,12 +1618,12 @@ load_from_sections(AOTModule *module, AOTSection *sections, /* Flush data cache before executing AOT code, * otherwise unpredictable behavior can occur. */ - bh_dcache_flush(); + os_dcache_flush(); return true; } -#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 +#if BH_ENABLE_MEMORY_PROFILING != 0 static void aot_free(void *ptr) { wasm_runtime_free(ptr); @@ -1668,7 +1692,7 @@ destroy_sections(AOTSection *section_list, bool destroy_aot_text) if (destroy_aot_text && section->section_type == AOT_SECTION_TYPE_TEXT && section->section_body) - bh_munmap((uint8*)section->section_body, section->section_body_size); + os_munmap((uint8*)section->section_body, section->section_body_size); wasm_runtime_free(section); section = next; } @@ -1719,7 +1743,7 @@ create_sections(const uint8 *buf, uint32 size, total_size = (uint64)section_size + aot_get_plt_table_size(); total_size = (total_size + 3) & ~((uint64)3); if (total_size >= UINT32_MAX - || !(aot_text = bh_mmap(NULL, (uint32)total_size, + || !(aot_text = os_mmap(NULL, (uint32)total_size, map_prot, map_flags))) { wasm_runtime_free(section); set_error_buf(error_buf, error_buf_size, @@ -2074,8 +2098,11 @@ aot_unload(AOTModule *module) if (module->const_str_set) bh_hash_map_destroy(module->const_str_set); - if (module->code) - bh_munmap(module->code, module->code_size); + if (module->code) { + uint8 *mmap_addr = module->literal - sizeof(module->literal_size); + uint32 total_size = sizeof(module->literal_size) + module->literal_size + module->code_size; + os_munmap(mmap_addr, total_size); + } if (module->data_sections) destroy_object_data_sections(module->data_sections, diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 02931dd29..c98a58e26 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -14,9 +14,8 @@ typedef struct { #define REG_COMMON_SYMBOLS \ REG_SYM(aot_set_exception_with_id), \ - REG_SYM(aot_get_exception), \ - REG_SYM(aot_is_wasm_type_equal), \ REG_SYM(aot_invoke_native), \ + REG_SYM(aot_call_indirect), \ REG_SYM(wasm_runtime_enlarge_memory), \ REG_SYM(wasm_runtime_set_exception), \ REG_SYM(fmin), \ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 2be359bf1..c9397460d 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -457,7 +457,7 @@ aot_call_function(WASMExecEnv *exec_env, AOTModuleInstance *module_inst = (AOTModuleInstance*)exec_env->module_inst; AOTFuncType *func_type = function->func_type; bool ret = wasm_runtime_invoke_native(exec_env, function->func_ptr, - func_type, NULL, argv, argc, argv); + func_type, NULL, NULL, argv, argc, argv); return ret && !aot_get_exception(module_inst) ? true : false; } @@ -751,7 +751,7 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) uint32 max_page_count = module_inst->mem_max_page_count; uint32 total_page_count = cur_page_count + inc_page_count; uint64 total_size = (uint64)num_bytes_per_page * total_page_count; - uint32 total_size_old; + uint32 total_size_old = module_inst->memory_data_size; if (inc_page_count <= 0) /* No need to enlarge memory */ @@ -773,14 +773,14 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) aot_set_exception(module_inst, "fail to enlarge memory."); return false; } - total_size_old = module_inst->memory_data_size; bh_memcpy_s(mem_data_new, (uint32)total_size, mem_data_old, total_size_old); - memset(mem_data_new + total_size_old, - 0, (uint32)total_size - total_size_old); wasm_runtime_free(mem_data_old); } + memset(mem_data_new + total_size_old, + 0, (uint32)total_size - total_size_old); + module_inst->mem_cur_page_count = total_page_count; module_inst->memory_data_size = (uint32)total_size; module_inst->memory_data.ptr = mem_data_new; @@ -811,7 +811,7 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst, return wasm_type_equal(type1, type2); } -void +bool aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 *frame_lp, uint32 argc, uint32 *argv_ret) { @@ -824,21 +824,100 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, void **func_ptrs = (void**)module_inst->func_ptrs.ptr; void *func_ptr = func_ptrs[func_idx]; AOTImportFunc *import_func; - const char *signature = NULL; + const char *signature; + void *attachment; char buf[128]; - if (func_idx < aot_module->import_func_count) { - import_func = aot_module->import_funcs + func_idx; - if (!func_ptr) { - snprintf(buf, sizeof(buf), - "fail to call unlinked import function (%s, %s)", - import_func->module_name, import_func->func_name); - aot_set_exception(module_inst, buf); - return; - } - signature = import_func->signature; + bh_assert(func_idx < aot_module->import_func_count); + + import_func = aot_module->import_funcs + func_idx; + if (!func_ptr) { + snprintf(buf, sizeof(buf), + "fail to call unlinked import function (%s, %s)", + import_func->module_name, import_func->func_name); + aot_set_exception(module_inst, buf); + return false; + } + + signature = import_func->signature; + attachment = import_func->attachment; + if (!import_func->call_conv_raw) { + return wasm_runtime_invoke_native(exec_env, func_ptr, + func_type, signature, attachment, + frame_lp, argc, argv_ret); + } + else { + return wasm_runtime_invoke_native_raw(exec_env, func_ptr, + func_type, signature, attachment, + frame_lp, argc, argv_ret); } - wasm_runtime_invoke_native(exec_env, func_ptr, - func_type, signature, frame_lp, argc, argv_ret); } +bool +aot_call_indirect(WASMExecEnv *exec_env, + bool check_func_type, uint32 func_type_idx, + uint32 table_elem_idx, + uint32 *frame_lp, uint32 argc, uint32 *argv_ret) +{ + AOTModuleInstance *module_inst = (AOTModuleInstance*) + wasm_runtime_get_module_inst(exec_env); + AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr; + uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr; + uint32 *table_data = (uint32*)module_inst->table_data.ptr; + AOTFuncType *func_type; + void **func_ptrs = (void**)module_inst->func_ptrs.ptr, *func_ptr; + uint32 table_size = module_inst->table_size; + uint32 func_idx, func_type_idx1; + AOTImportFunc *import_func; + const char *signature = NULL; + void *attachment = NULL; + char buf[128]; + + if (table_elem_idx >= table_size) { + aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT); + return false; + } + + func_idx = table_data[table_elem_idx]; + if (func_idx == (uint32)-1) { + aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT); + return false; + } + + func_type_idx1 = func_type_indexes[func_idx]; + if (check_func_type + && !aot_is_wasm_type_equal(module_inst, func_type_idx, + func_type_idx1)) { + aot_set_exception_with_id(module_inst, + EXCE_INVALID_FUNCTION_TYPE_INDEX); + return false; + } + func_type = aot_module->func_types[func_type_idx1]; + + if (!(func_ptr = func_ptrs[func_idx])) { + bh_assert(func_idx < aot_module->import_func_count); + import_func = aot_module->import_funcs + func_idx; + snprintf(buf, sizeof(buf), + "fail to call unlinked import function (%s, %s)", + import_func->module_name, import_func->func_name); + aot_set_exception(module_inst, buf); + return false; + } + + if (func_idx < aot_module->import_func_count) { + /* Call native function */ + import_func = aot_module->import_funcs + func_idx; + signature = import_func->signature; + if (import_func->call_conv_raw) { + attachment = import_func->attachment; + return wasm_runtime_invoke_native_raw(exec_env, func_ptr, + func_type, signature, + attachment, + frame_lp, argc, argv_ret); + } + } + + return wasm_runtime_invoke_native(exec_env, func_ptr, + func_type, signature, attachment, + frame_lp, argc, argv_ret); +} diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 977d3ec96..0bd4c7651 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -125,6 +125,10 @@ typedef struct AOTModule { void *code; uint32 code_size; + /* literal for AOTed code, NULL for JIT mode */ + uint8 *literal; + uint32 literal_size; + /* data sections in AOT object file, including .data, .rodata * and .rodata.cstN. NULL for JIT mode. */ AOTObjectDataSection *data_sections; @@ -435,10 +439,16 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst, /** * Invoke native function from aot code */ -void +bool aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 *frame_lp, uint32 argc, uint32 *argv_ret); +bool +aot_call_indirect(WASMExecEnv *exec_env, + bool check_func_type, uint32 func_type_idx, + uint32 table_elem_idx, + uint32 *frame_lp, uint32 argc, uint32 *argv_ret); + uint32 aot_get_plt_table_size(); diff --git a/core/iwasm/aot/arch/aot_reloc_aarch64.c b/core/iwasm/aot/arch/aot_reloc_aarch64.c new file mode 100644 index 000000000..b2e250657 --- /dev/null +++ b/core/iwasm/aot/arch/aot_reloc_aarch64.c @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_reloc.h" + +#define R_AARCH64_ADR_PREL_PG_HI21 275 +#define R_AARCH64_ADD_ABS_LO12_NC 277 +#define R_AARCH64_CALL26 283 + +static SymbolMap target_sym_map[] = { + REG_COMMON_SYMBOLS +}; + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, "%s", string); +} + +SymbolMap * +get_target_symbol_map(uint32 *sym_num) +{ + *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap); + return target_sym_map; +} + +void +get_current_target(char *target_buf, uint32 target_buf_size) +{ + char *build_target = BUILD_TARGET; + char *p = target_buf, *p_end; + snprintf(target_buf, target_buf_size, "%s", build_target); + p_end = p + strlen(target_buf); + while (p < p_end) { + if (*p >= 'A' && *p <= 'Z') + *p++ += 'a' - 'A'; + else + p++; + } + if (!strcmp(target_buf, "aarch64")) + snprintf(target_buf, target_buf_size, "aarch64v8"); +} + +static uint32 +get_plt_item_size() +{ + /* 8*4 bytes instructions and 8 bytes symbol address */ + return 40; +} + +void +init_plt_table(uint8 *plt) +{ + uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); + for (i = 0; i < num; i++) { + uint32 *p = (uint32*)plt; + *p++ = 0xd10023ff; /* sub sp, sp, #0x8 */ + *p++ = 0xf90003fe; /* str x30, [sp] */ + *p++ = 0x100000de; /* adr x30, #24 */ + *p++ = 0xf94003de; /* ldr x30, [x30] */ + *p++ = 0xd63f03c0; /* blr x30 */ + *p++ = 0xf94003fe; /* ldr x30, [sp] */ + *p++ = 0x910023ff; /* add sp, sp, #0x8 */ + *p++ = 0xd61f03c0; /* br x30 */ + /* symbol addr */ + *(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr; + p += 2; + plt += get_plt_item_size(); + } +} + +uint32 +get_plt_table_size() +{ + return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); +} + +#define SIGN_EXTEND_TO_INT64(val, bits, val_ext) do { \ + int64 m = ((int64)1 << (bits - 1)); \ + val_ext = ((int64)val ^ m) - m; \ +} while (0) + +#define Page(expr) ((expr) & ~0xFFF) + +static bool +check_reloc_offset(uint32 target_section_size, + uint64 reloc_offset, uint32 reloc_data_size, + char *error_buf, uint32 error_buf_size) +{ + if (!(reloc_offset < (uint64)target_section_size + && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid relocation offset."); + return false; + } + return true; +} + +bool +apply_relocation(AOTModule *module, + uint8 *target_section_addr, uint32 target_section_size, + uint64 reloc_offset, uint64 reloc_addend, + uint32 reloc_type, void *symbol_addr, int32 symbol_index, + char *error_buf, uint32 error_buf_size) +{ + switch (reloc_type) { + case R_AARCH64_CALL26: + { + void *S, *P = (void*)(target_section_addr + reloc_offset); + int64 X, A, initial_addend; + int32 insn, imm26; + + CHECK_RELOC_OFFSET(sizeof(int32)); + + insn = *(int32*)P; + imm26 = insn & 0x3FFFFFF; + SIGN_EXTEND_TO_INT64(imm26 << 2, 28, initial_addend); + A = initial_addend; + A += (int64)reloc_addend; + + if (symbol_index < 0) { + /* Symbol address itself is an AOT function. + * Apply relocation with the symbol directly. + * Suppose the symbol address is in +-128MB relative + * to the relocation address. + */ + S = symbol_addr; + } + else { + uint8 *plt; + if (reloc_addend > 0) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: relocate to plt table " + "with reloc addend larger than 0 is unsupported."); + return false; + } + /* Symbol address is not an AOT function, + * but a function of runtime or native. Its address is + * beyond of the +-128MB space. Apply relocation with + * the PLT which branch to the target symbol address. + */ + S = plt = (uint8*)module->code + module->code_size + - get_plt_table_size() + + get_plt_item_size() * symbol_index; + } + + /* S + A - P */ + X = (int64)S + A - (int64)P; + + /* Check overflow: +-128MB */ + if (X > (128 * BH_MB) || X < (-128 * BH_MB)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "target address out of range."); + return false; + } + + /* write the imm26 back to instruction */ + *(int32*)P = (insn & 0xFC000000) | ((int32)((X >> 2) & 0x3FFFFFF)); + break; + } + + case R_AARCH64_ADR_PREL_PG_HI21: + { + void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset); + int64 X, A, initial_addend; + int32 insn, immhi19, immlo2, imm21; + + CHECK_RELOC_OFFSET(sizeof(int32)); + + insn = *(int32*)P; + immhi19 = (insn >> 5) & 0x7FFFF; + immlo2 = (insn >> 29) & 0x3; + imm21 = (immhi19 << 2) | immlo2; + + SIGN_EXTEND_TO_INT64(imm21 << 12, 33, initial_addend); + A = initial_addend; + A += (int64)reloc_addend; + + /* Page(S+A) - Page(P) */ + X = Page((int64)S + A) - Page((int64)P); + + /* Check overflow: +-4GB */ + if (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "target address out of range."); + return false; + } + + /* write the imm21 back to instruction */ + immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF); + immlo2 = (int32)((X >> 12) & 0x3); + *(int32*)P = (insn & 0x9F00001F) | (immlo2 << 29) | (immhi19 << 5); + + break; + } + + case R_AARCH64_ADD_ABS_LO12_NC: + { + void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset); + int64 X, A, initial_addend; + int32 insn, imm12; + + CHECK_RELOC_OFFSET(sizeof(int32)); + + insn = *(int32*)P; + imm12 = (insn >> 10) & 0xFFF; + + SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend); + A = initial_addend; + A += (int64)reloc_addend; + + /* S + A */ + X = (int64)S + A; + + /* No need to check overflow for this reloction type */ + + /* write the imm12 back to instruction */ + *(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10)); + break; + } + + default: + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "Load relocation section failed: " + "invalid relocation type %d.", + reloc_type); + return false; + } + + return true; +} + diff --git a/core/iwasm/aot/arch/aot_reloc_arm.c b/core/iwasm/aot/arch/aot_reloc_arm.c index 16ea56b18..c73f9324a 100644 --- a/core/iwasm/aot/arch/aot_reloc_arm.c +++ b/core/iwasm/aot/arch/aot_reloc_arm.c @@ -9,10 +9,6 @@ #define R_ARM_JMP24 29 /* PC relative 24 bit (B/BL). */ #define R_ARM_ABS32 2 /* Direct 32 bit */ -#ifndef BH_MB -#define BH_MB 1024 * 1024 -#endif - void __divdi3(); void __udivdi3(); void __moddi3(); @@ -163,7 +159,7 @@ init_plt_table(uint8 *plt) /* nop */ *p++ = 0xe1a00000; /* symbol addr */ - *p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;; + *p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr; plt += get_plt_item_size(); } } diff --git a/core/iwasm/aot/arch/aot_reloc_thumb.c b/core/iwasm/aot/arch/aot_reloc_thumb.c index af0c99d95..134f7abe3 100644 --- a/core/iwasm/aot/arch/aot_reloc_thumb.c +++ b/core/iwasm/aot/arch/aot_reloc_thumb.c @@ -8,10 +8,6 @@ #define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */ #define R_ARM_THM_JMP24 30 /* B.W */ -#ifndef BH_MB -#define BH_MB 1024 * 1024 -#endif - void __divdi3(); void __udivdi3(); void __moddi3(); diff --git a/core/iwasm/aot/arch/aot_reloc_x86_64.c b/core/iwasm/aot/arch/aot_reloc_x86_64.c index 28aa661ae..a18b1c35e 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_64.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_64.c @@ -149,19 +149,22 @@ apply_relocation(AOTModule *module, } case R_X86_64_PLT32: { - uint8 *plt = (uint8*)module->code + module->code_size - get_plt_table_size() - + get_plt_item_size() * symbol_index; - intptr_t target_addr = (intptr_t) /* L + A - P */ - (plt + reloc_addend - - (target_section_addr + reloc_offset)); + uint8 *plt; + intptr_t target_addr = 0; CHECK_RELOC_OFFSET(sizeof(int32)); - if (symbol_index < 0) { - set_error_buf(error_buf, error_buf_size, - "AOT module load failed: " - "invalid symbol index for relocation"); - return false; + if (symbol_index >= 0) { + plt = (uint8*)module->code + module->code_size - get_plt_table_size() + + get_plt_item_size() * symbol_index; + target_addr = (intptr_t) /* L + A - P */ + (plt + reloc_addend + - (target_section_addr + reloc_offset)); + } + else { + target_addr = (intptr_t) /* L + A - P */ + ((uint8*)symbol_addr + reloc_addend + - (target_section_addr + reloc_offset)); } if ((int32)target_addr != target_addr) { diff --git a/core/iwasm/aot/arch/aot_reloc_xtensa.c b/core/iwasm/aot/arch/aot_reloc_xtensa.c index 24c0db78e..ea04070f6 100644 --- a/core/iwasm/aot/arch/aot_reloc_xtensa.c +++ b/core/iwasm/aot/arch/aot_reloc_xtensa.c @@ -5,10 +5,50 @@ #include "aot_reloc.h" +#define R_XTENSA_32 1 /* Direct 32 bit */ +#define R_XTENSA_SLOT0_OP 20 /* PC relative */ + +/* for soft-float */ +void __floatsidf(); +void __divdf3(); +void __ltdf2(); + +/* for mul32 */ +void __mulsi3(); +void __muldi3(); + +void __modsi3(); + +void __divdi3(); + static SymbolMap target_sym_map[] = { - REG_COMMON_SYMBOLS + REG_COMMON_SYMBOLS, + + /* API's for soft-float */ + /* TODO: only register these symbols when Floating-Point Coprocessor + * Option is not enabled */ + REG_SYM(__floatsidf), + REG_SYM(__divdf3), + REG_SYM(__ltdf2), + + /* API's for 32-bit integer multiply */ + /* TODO: only register these symbols when 32-bit Integer Multiply Option + * is not enabled */ + REG_SYM(__mulsi3), + REG_SYM(__muldi3), + + REG_SYM(__modsi3), + + REG_SYM(__divdi3), }; +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, "%s", string); +} + SymbolMap * get_target_symbol_map(uint32 *sym_num) { @@ -40,6 +80,67 @@ get_plt_table_size() return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); } +static bool +check_reloc_offset(uint32 target_section_size, + uint64 reloc_offset, uint32 reloc_data_size, + char *error_buf, uint32 error_buf_size) +{ + if (!(reloc_offset < (uint64)target_section_size + && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid relocation offset."); + return false; + } + return true; +} + +/* + * CPU like esp32 can read and write data through the instruction bus, but only + * in a word aligned manner; non-word-aligned access will cause a CPU exception. + * This function uses a world aligned manner to write 16bit value to instruction + * addreess. + */ +static void +put_imm16_to_addr(int16 imm16, int16 *addr) +{ + int8 bytes[8]; + int32 *addr_aligned1, *addr_aligned2; + + addr_aligned1 = (int32*)((intptr_t)addr & ~3); + + if ((intptr_t)addr % 4 != 3) { + *(int32*)bytes = *addr_aligned1; + *(int16*)(bytes + ((intptr_t)addr % 4)) = imm16; + memcpy(addr_aligned1, bytes, 4); + } + else { + addr_aligned2 = (int32*)(((intptr_t)addr + 3) & ~3); + *(int32*)bytes = *addr_aligned1; + *(int32*)(bytes + 4) = *addr_aligned2; + *(int16*)(bytes + 3) = imm16; + memcpy(addr_aligned1, bytes, 8); + } +} + +static union { + int a; + char b; +} __ue = { .a = 1 }; + +#define is_little_endian() (__ue.b == 1) + +typedef union { + struct l32r_le { + int8 other; + int16 imm16; + } __packed l; + + struct l32r_be { + int16 imm16; + int8 other; + } __packed b; +} l32r_insn_t; + bool apply_relocation(AOTModule *module, uint8 *target_section_addr, uint32 target_section_size, @@ -48,7 +149,73 @@ apply_relocation(AOTModule *module, char *error_buf, uint32 error_buf_size) { switch (reloc_type) { - /* TODO: implement relocation for xtensa */ + case R_XTENSA_32: + { + uint8 *insn_addr = target_section_addr + reloc_offset; + int32 initial_addend; + /* (S + A) */ + if ((intptr_t)insn_addr & 3) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "instruction address unaligned."); + return false; + } + CHECK_RELOC_OFFSET(4); + initial_addend = *(int32*)insn_addr; + *(uint8**)insn_addr + = (uint8*)symbol_addr + initial_addend + reloc_addend; + break; + } + + case R_XTENSA_SLOT0_OP: + { + uint8 *insn_addr = target_section_addr + reloc_offset; + /* Currently only l32r instruction generates R_XTENSA_SLOT0_OP relocation */ + l32r_insn_t *l32r_insn = (l32r_insn_t *)insn_addr; + uint8 *reloc_addr; + int32 relative_offset/*, initial_addend */; + int16 imm16; + + CHECK_RELOC_OFFSET(3); /* size of l32r instruction */ + + /* + imm16 = is_little_endian() ? + l32r_insn->l.imm16 : l32r_insn->b.imm16; + initial_addend = (int32)imm16 << 2; + */ + + reloc_addr = (uint8*)symbol_addr + reloc_addend; + + if ((intptr_t)reloc_addr & 3) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "relocation address unaligned."); + return false; + } + + relative_offset = (int32) + ((intptr_t)reloc_addr - + (((intptr_t)insn_addr + 3) & ~(intptr_t)3)); + /* relative_offset += initial_addend; */ + + /* check relative offset boundary */ + if (relative_offset < -256 * BH_KB || relative_offset > -4) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "target address out of range."); + return false; + } + + imm16 = (int16)(relative_offset >> 2); + + /* write back the imm16 to the l32r instruction */ + if (is_little_endian()) + put_imm16_to_addr(imm16, &l32r_insn->l.imm16); + else + put_imm16_to_addr(imm16, &l32r_insn->b.imm16); + + break; + } default: if (error_buf != NULL) diff --git a/core/iwasm/aot/iwasm_aot.cmake b/core/iwasm/aot/iwasm_aot.cmake index 4166efb36..e7d0549d9 100644 --- a/core/iwasm/aot/iwasm_aot.cmake +++ b/core/iwasm/aot/iwasm_aot.cmake @@ -9,17 +9,19 @@ include_directories (${IWASM_AOT_DIR}) file (GLOB c_source_all ${IWASM_AOT_DIR}/*.c) -if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD_64") +if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_64.c) -elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32") +elseif (WAMR_BUILD_TARGET STREQUAL "X86_32") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_32.c) -elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*") +elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*") + set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_aarch64.c) +elseif (WAMR_BUILD_TARGET MATCHES "ARM.*") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arm.c) -elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*") +elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_thumb.c) -elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS") +elseif (WAMR_BUILD_TARGET STREQUAL "MIPS") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_mips.c) -elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA") +elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_xtensa.c) else () message (FATAL_ERROR "Build target isn't set") diff --git a/core/iwasm/common/arch/invokeNative_aarch64.s b/core/iwasm/common/arch/invokeNative_aarch64.s new file mode 100644 index 000000000..7204a958e --- /dev/null +++ b/core/iwasm/common/arch/invokeNative_aarch64.s @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + .text + .align 2 + .global invokeNative + .type invokeNative,function + +/* + * Arguments passed in: + * + * x0 function ptr + * x1 argv + * x2 nstacks + */ + +invokeNative: + sub sp, sp, #0x30 + stp x19, x20, [sp, #0x20] /* save the registers */ + stp x21, x22, [sp, #0x10] + stp x23, x24, [sp, #0x0] + + mov x19, x0 /* x19 = function ptr */ + mov x20, x1 /* x20 = argv */ + mov x21, x2 /* x21 = nstacks */ + mov x22, sp /* save the sp before call function */ + + /* Fill in float-point registers */ + ldp d0, d1, [x20], #16 /* d0 = argv[0], d1 = argv[1] */ + ldp d2, d3, [x20], #16 /* d2 = argv[2], d3 = argv[3] */ + ldp d4, d5, [x20], #16 /* d4 = argv[4], d5 = argv[5] */ + ldp d6, d7, [x20], #16 /* d6 = argv[6], d7 = argv[7] */ + + /* Fill inteter registers */ + ldp x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */ + ldp x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */ + ldp x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */ + ldp x6, x7, [x20], #16 /* x6 = argv[14], x7 = argv[15] */ + + /* Now x20 points to stack args */ + + /* Directly call the fucntion if no args in stack */ + cmp x21, #0 + beq call_func + + /* Fill all stack args: reserve stack space and fill ony by one */ + mov x23, sp + bic sp, x23, #15 /* Ensure stack is 16 bytes aligned */ + lsl x23, x21, #3 /* x23 = nstacks * 8 */ + add x23, x23, #15 /* x23 = (x23 + 15) & ~15 */ + bic x23, x23, #15 + sub sp, sp, x23 /* reserved stack space for stack arguments */ + mov x23, sp + +loop_stack_args: /* copy stack arguments to stack */ + cmp x21, #0 + beq call_func + ldr x24, [x20], #8 + str x24, [x23], #8 + sub x21, x21, #1 + b loop_stack_args + +call_func: + mov x20, x30 /* save x30(lr) */ + blr x19 + mov sp, x22 /* restore sp which is saved before calling fuction*/ + +return: + mov x30, x20 /* restore x30(lr) */ + ldp x19, x20, [sp, #0x20] /* restore the registers in stack */ + ldp x21, x22, [sp, #0x10] + ldp x23, x24, [sp, #0x0] + add sp, sp, #0x30 /* restore sp */ + ret + diff --git a/core/iwasm/common/iwasm_common.cmake b/core/iwasm/common/iwasm_common.cmake index 3e2acfd99..aa3683d35 100644 --- a/core/iwasm/common/iwasm_common.cmake +++ b/core/iwasm/common/iwasm_common.cmake @@ -10,27 +10,29 @@ add_definitions(-DBH_FREE=wasm_runtime_free) file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c) -if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD_64") +if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s) -elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32") +elseif (WAMR_BUILD_TARGET STREQUAL "X86_32") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s) -elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*") - if (${WAMR_BUILD_TARGET} MATCHES "ARM.*_VFP") +elseif (WAMR_BUILD_TARGET MATCHES "ARM.*") + if (WAMR_BUILD_TARGET MATCHES "ARM.*_VFP") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm_vfp.s) else () set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm.s) endif () -elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*") - if (${WAMR_BUILD_TARGET} MATCHES "THUMB.*_VFP") +elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*") + if (WAMR_BUILD_TARGET MATCHES "THUMB.*_VFP") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb_vfp.s) else () set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s) endif () -elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS") +elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s) +elseif (WAMR_BUILD_TARGET STREQUAL "MIPS") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s) -elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA") +elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_xtensa.s) -elseif (${WAMR_BUILD_TARGET} STREQUAL "GENERAL") +elseif (WAMR_BUILD_TARGET STREQUAL "GENERAL") # Use invokeNative_general.c instead of assembly code, # but the maximum number of native arguments is limited to 20, # and there are possible issues when passing arguments to diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index d25469669..6d3c19d8f 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -6,7 +6,6 @@ #ifndef _WASM_EXEC_ENV_H #define _WASM_EXEC_ENV_H -#include "bh_thread.h" #include "bh_assert.h" #if WASM_ENABLE_INTERP != 0 #include "../interpreter/wasm.h" @@ -34,6 +33,11 @@ typedef struct WASMExecEnv { uint32 *argv_buf; #endif + /* attachment for native function */ + void *attachment; + + void *user_data; + /* Current interpreter frame of current thread */ struct WASMInterpFrame *cur_frame; diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 4f39df8de..9032bc0c0 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -6,9 +6,8 @@ #include "wasm_runtime_common.h" #include "bh_platform.h" #include "mem_alloc.h" -#include "bh_thread.h" -#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 +#if BH_ENABLE_MEMORY_PROFILING != 0 /* Memory profile data of a function */ typedef struct memory_profile { @@ -31,7 +30,7 @@ static memory_profile_t *memory_profiles_list = NULL; /* Lock of the memory profile list */ static korp_mutex profile_lock; -#endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */ +#endif /* end of BH_ENABLE_MEMORY_PROFILING */ #ifndef MALLOC_MEMORY_FROM_SYSTEM @@ -59,13 +58,13 @@ wasm_memory_init_with_pool(void *mem, unsigned int bytes) if (_allocator) { memory_mode = MEMORY_MODE_POOL; pool_allocator = _allocator; -#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 - vm_mutex_init(&profile_lock); +#if BH_ENABLE_MEMORY_PROFILING != 0 + os_mutex_init(&profile_lock); #endif global_pool_size = bytes; return true; } - bh_printf("Init memory with pool (%p, %u) failed.\n", mem, bytes); + LOG_ERROR("Init memory with pool (%p, %u) failed.\n", mem, bytes); return false; } @@ -79,12 +78,12 @@ wasm_memory_init_with_allocator(void *_malloc_func, malloc_func = _malloc_func; realloc_func = _realloc_func; free_func = _free_func; -#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 - vm_mutex_init(&profile_lock); +#if BH_ENABLE_MEMORY_PROFILING != 0 + os_mutex_init(&profile_lock); #endif return true; } - bh_printf("Init memory with allocator (%p, %p, %p) failed.\n", + LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n", _malloc_func, _realloc_func, _free_func); return false; } @@ -109,8 +108,8 @@ wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type, void wasm_runtime_memory_destroy() { -#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 - vm_mutex_destroy(&profile_lock); +#if BH_ENABLE_MEMORY_PROFILING != 0 + os_mutex_destroy(&profile_lock); #endif if (memory_mode == MEMORY_MODE_POOL) mem_allocator_destroy(pool_allocator); @@ -130,7 +129,7 @@ void * wasm_runtime_malloc(unsigned int size) { if (memory_mode == MEMORY_MODE_UNKNOWN) { - bh_printf("wasm_runtime_malloc failed: memory hasn't been initialize.\n"); + LOG_WARNING("wasm_runtime_malloc failed: memory hasn't been initialize.\n"); return NULL; } else if (memory_mode == MEMORY_MODE_POOL) { return mem_allocator_malloc(pool_allocator, size); @@ -143,7 +142,7 @@ void * wasm_runtime_realloc(void *ptr, unsigned int size) { if (memory_mode == MEMORY_MODE_UNKNOWN) { - bh_printf("wasm_runtime_realloc failed: memory hasn't been initialize.\n"); + LOG_WARNING("wasm_runtime_realloc failed: memory hasn't been initialize.\n"); return NULL; } else if (memory_mode == MEMORY_MODE_POOL) { return mem_allocator_realloc(pool_allocator, ptr, size); @@ -159,7 +158,7 @@ void wasm_runtime_free(void *ptr) { if (memory_mode == MEMORY_MODE_UNKNOWN) { - bh_printf("wasm_runtime_free failed: memory hasn't been initialize.\n"); + LOG_WARNING("wasm_runtime_free failed: memory hasn't been initialize.\n"); } else if (memory_mode == MEMORY_MODE_POOL) { mem_allocator_free(pool_allocator, ptr); } else { @@ -167,17 +166,26 @@ wasm_runtime_free(void *ptr) } } -#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 +#if BH_ENABLE_MEMORY_PROFILING != 0 + +void +memory_profile_print(const char *file, int line, + const char *func, int alloc) +{ + os_printf("location:%s@%d:used:%d:contribution:%d\n", + func, line, memory_in_use, alloc); +} + void * wasm_runtime_malloc_profile(const char *file, int line, const char *func, unsigned int size) { - void *p = wasm_rutime_malloc(size + 8); + void *p = wasm_runtime_malloc(size + 8); if (p) { memory_profile_t *profile; - vm_mutex_lock(&profile_lock); + os_mutex_lock(&profile_lock); profile = memory_profiles_list; while (profile) { @@ -194,7 +202,7 @@ wasm_runtime_malloc_profile(const char *file, int line, } else { profile = wasm_runtime_malloc(sizeof(memory_profile_t)); if (!profile) { - vm_mutex_unlock(&profile_lock); + os_mutex_unlock(&profile_lock); bh_memcpy_s(p, size + 8, &size, sizeof(size)); return (char *)p + 8; } @@ -209,7 +217,7 @@ wasm_runtime_malloc_profile(const char *file, int line, memory_profiles_list = profile; } - vm_mutex_unlock(&profile_lock); + os_mutex_unlock(&profile_lock); bh_memcpy_s(p, size + 8, &size, sizeof(size)); memory_in_use += size; @@ -234,7 +242,7 @@ wasm_runtime_free_profile(const char *file, int line, if (memory_in_use >= size) memory_in_use -= size; - vm_mutex_lock(&profile_lock); + os_mutex_lock(&profile_lock); profile = memory_profiles_list; while (profile) { @@ -251,7 +259,7 @@ wasm_runtime_free_profile(const char *file, int line, } else { profile = wasm_runtime_malloc(sizeof(memory_profile_t)); if (!profile) { - vm_mutex_unlock(&profile_lock); + os_mutex_unlock(&profile_lock); return; } @@ -265,7 +273,7 @@ wasm_runtime_free_profile(const char *file, int line, memory_profiles_list = profile; } - vm_mutex_unlock(&profile_lock); + os_mutex_unlock(&profile_lock); } /** @@ -277,11 +285,11 @@ void memory_usage_summarize() { memory_profile_t *profile; - vm_mutex_lock(&profile_lock); + os_mutex_lock(&profile_lock); profile = memory_profiles_list; while (profile) { - bh_printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n", + os_printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n", profile->total_malloc, profile->malloc_num, profile->total_free, @@ -290,18 +298,10 @@ void memory_usage_summarize() profile = profile->next; } - vm_mutex_unlock(&profile_lock); + os_mutex_unlock(&profile_lock); } -void -memory_profile_print(const char *file, int line, - const char *func, int alloc) -{ - bh_printf("location:%s@%d:used:%d:contribution:%d\n", - func, line, memory_in_use, alloc); -} - -#endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */ +#endif /* end of BH_ENABLE_MEMORY_PROFILING */ #else /* else of MALLOC_MEMORY_FROM_SYSTEM */ @@ -325,7 +325,7 @@ wasm_runtime_free(void *ptr) free(ptr); } -#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 +#if BH_ENABLE_MEMORY_PROFILING != 0 void * wasm_runtime_malloc_profile(const char *file, int line, const char *func, unsigned int size) @@ -367,6 +367,6 @@ wasm_runtime_free_profile(const char *file, int line, if (ptr) free(ptr); } -#endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */ +#endif /* end of BH_ENABLE_MEMORY_PROFILING */ #endif /* end of MALLOC_MEMORY_FROM_SYSTEM*/ diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 38d2f6bd6..cbbf2fbd9 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -110,7 +110,7 @@ sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols) static void * lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols, - const char *symbol, const char **p_signature) + const char *symbol, const char **p_signature, void **p_attachment) { int low = 0, mid, ret; int high = n_native_symbols - 1; @@ -120,6 +120,7 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols, ret = strcmp(symbol, native_symbols[mid].symbol); if (ret == 0) { *p_signature = native_symbols[mid].signature; + *p_attachment = native_symbols[mid].attachment; return native_symbols[mid].func_ptr; } else if (ret < 0) @@ -133,11 +134,12 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols, void* wasm_native_resolve_symbol(const char *module_name, const char *field_name, - const WASMType *func_type, const char **p_signature) + const WASMType *func_type, const char **p_signature, + void **p_attachment, bool *p_call_conv_raw) { NativeSymbolsNode *node, *node_next; const char *signature = NULL; - void *func_ptr = NULL; + void *func_ptr = NULL, *attachment; node = g_native_symbols_list; while (node) { @@ -145,11 +147,12 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name, if (!strcmp(node->module_name, module_name)) { if ((func_ptr = lookup_symbol(node->native_symbols, node->n_native_symbols, - field_name, &signature)) + field_name, &signature, &attachment)) || (field_name[0] == '_' && (func_ptr = lookup_symbol(node->native_symbols, node->n_native_symbols, - field_name + 1, &signature)))) + field_name + 1, + &signature, &attachment)))) break; } node = node_next; @@ -172,15 +175,19 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name, else /* signature is empty */ *p_signature = NULL; + + *p_attachment = attachment; + *p_call_conv_raw = node->call_conv_raw; } return func_ptr; } -bool -wasm_native_register_natives(const char *module_name, - NativeSymbol *native_symbols, - uint32 n_native_symbols) +static bool +register_natives(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols, + bool call_conv_raw) { NativeSymbolsNode *node; @@ -190,6 +197,7 @@ wasm_native_register_natives(const char *module_name, node->module_name = module_name; node->native_symbols = native_symbols; node->n_native_symbols = n_native_symbols; + node->call_conv_raw = call_conv_raw; node->next = NULL; if (g_native_symbols_list_end) { @@ -204,6 +212,22 @@ wasm_native_register_natives(const char *module_name, return true; } +bool +wasm_native_register_natives(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols) +{ + return register_natives(module_name, native_symbols, n_native_symbols, false); +} + +bool +wasm_native_register_natives_raw(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols) +{ + return register_natives(module_name, native_symbols, n_native_symbols, true); +} + bool wasm_native_init() { @@ -227,6 +251,9 @@ wasm_native_init() if (!wasm_native_register_natives("wasi_unstable", native_symbols, n_native_symbols)) return false; + if (!wasm_native_register_natives("wasi_snapshot_preview1", + native_symbols, n_native_symbols)) + return false; #endif #if WASM_ENABLE_BASE_LIB != 0 diff --git a/core/iwasm/common/wasm_native.h b/core/iwasm/common/wasm_native.h index 039987848..d76d238a8 100644 --- a/core/iwasm/common/wasm_native.h +++ b/core/iwasm/common/wasm_native.h @@ -19,6 +19,7 @@ typedef struct NativeSymbolsNode { const char *module_name; NativeSymbol *native_symbols; uint32 n_native_symbols; + bool call_conv_raw; } NativeSymbolsNode, *NativeSymbolsList; /** @@ -50,13 +51,19 @@ wasm_native_lookup_libc_builtin_global(const char *module_name, */ void* wasm_native_resolve_symbol(const char *module_name, const char *field_name, - const WASMType *func_type, const char **p_signature); + const WASMType *func_type, const char **p_signature, + void **p_attachment, bool *p_call_conv_raw); bool wasm_native_register_natives(const char *module_name, NativeSymbol *native_symbols, uint32 n_native_symbols); +bool +wasm_native_register_natives_raw(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols); + bool wasm_native_init(); diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index f8d7eea07..ea86d952e 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -3,7 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "config.h" #include "bh_platform.h" #include "bh_common.h" #include "bh_assert.h" @@ -30,18 +29,25 @@ wasm_runtime_env_init() if (bh_platform_init() != 0) return false; - if (bh_log_init() != 0) - return false; - - if (vm_thread_sys_init() != 0) - return false; - - if (wasm_native_init() == false) + if (wasm_native_init() == false) { + bh_platform_destroy(); return false; + } return true; } +static bool +wasm_runtime_env_check(WASMExecEnv *exec_env) +{ + return !(!exec_env + || !exec_env->module_inst + || exec_env->wasm_stack_size == 0 + || exec_env->wasm_stack.s.top_boundary != + exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size + || exec_env->wasm_stack.s.top > exec_env->wasm_stack.s.top_boundary); +} + bool wasm_runtime_init() { @@ -60,7 +66,7 @@ void wasm_runtime_destroy() { wasm_native_destroy(); - vm_thread_sys_destroy(); + bh_platform_destroy(); wasm_runtime_memory_destroy(); } @@ -238,6 +244,24 @@ wasm_runtime_get_module_inst(WASMExecEnv *exec_env) return wasm_exec_env_get_module_inst(exec_env); } +void * +wasm_runtime_get_function_attachment(WASMExecEnv *exec_env) +{ + return exec_env->attachment; +} + +void +wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data) +{ + exec_env->user_data = user_data; +} + +void * +wasm_runtime_get_user_data(WASMExecEnv *exec_env) +{ + return exec_env->user_data; +} + WASMFunctionInstanceCommon * wasm_runtime_lookup_function(WASMModuleInstanceCommon * const module_inst, const char *name, @@ -263,17 +287,12 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, WASMFunctionInstanceCommon *function, unsigned argc, uint32 argv[]) { - if (!exec_env - || !exec_env->module_inst - || exec_env->wasm_stack_size == 0 - || exec_env->wasm_stack.s.top_boundary != - exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size - || exec_env->wasm_stack.s.top > exec_env->wasm_stack.s.top_boundary) { + if (!wasm_runtime_env_check(exec_env)) { LOG_ERROR("Invalid exec env stack info."); return false; } - exec_env->handle = vm_self_thread(); + exec_env->handle = os_self_thread(); #if WASM_ENABLE_INTERP != 0 if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) @@ -1375,34 +1394,38 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, /* print return value */ switch (type->types[type->param_count]) { case VALUE_TYPE_I32: - bh_printf("0x%x:i32", argv1[0]); + os_printf("0x%x:i32", argv1[0]); break; case VALUE_TYPE_I64: { - char buf[16]; union { uint64 val; uint32 parts[2]; } u; u.parts[0] = argv1[0]; u.parts[1] = argv1[1]; +#ifdef PRIx64 + os_printf("0x%"PRIx64":i64", u.val); +#else + char buf[16]; if (sizeof(long) == 4) snprintf(buf, sizeof(buf), "%s", "0x%llx:i64"); else snprintf(buf, sizeof(buf), "%s", "0x%lx:i64"); - bh_printf(buf, u.val); + os_printf(buf, u.val); +#endif break; } case VALUE_TYPE_F32: - bh_printf("%.7g:f32", *(float32*)argv1); + os_printf("%.7g:f32", *(float32*)argv1); break; case VALUE_TYPE_F64: { union { float64 val; uint32 parts[2]; } u; u.parts[0] = argv1[0]; u.parts[1] = argv1[1]; - bh_printf("%.7g:f64", u.val); + os_printf("%.7g:f64", u.val); break; } } - bh_printf("\n"); + os_printf("\n"); wasm_runtime_free(argv1); return true; @@ -1413,7 +1436,7 @@ fail: exception = wasm_runtime_get_exception(module_inst); bh_assert(exception); - bh_printf("%s\n", exception); + os_printf("%s\n", exception); return false; } @@ -1426,6 +1449,120 @@ wasm_runtime_register_natives(const char *module_name, native_symbols, n_native_symbols); } +bool +wasm_runtime_register_natives_raw(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols) +{ + return wasm_native_register_natives_raw(module_name, + native_symbols, n_native_symbols); +} + +bool +wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, + const WASMType *func_type, const char *signature, + void *attachment, + uint32 *argv, uint32 argc, uint32 *argv_ret) +{ + WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); + typedef void (*NativeRawFuncPtr)(WASMExecEnv*, uint64*); + NativeRawFuncPtr invokeNativeRaw = (NativeRawFuncPtr)func_ptr; + uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size; + uint32 *argv_src = argv, i, argc1, ptr_len; + int32 arg_i32; + bool ret = false; + + argc1 = func_type->param_count; + if (argc1 > sizeof(argv_buf) / sizeof(uint64)) { + size = sizeof(uint64) * (uint64)argc1; + if (size >= UINT32_MAX + || !(argv1 = wasm_runtime_malloc((uint32)size))) { + wasm_runtime_set_exception(exec_env->module_inst, + "allocate memory failed."); + return false; + } + memset(argv1, 0, (uint32)size); + } + + argv_dst = argv1; + + /* Traverse secondly to fill in each argument */ + for (i = 0; i < func_type->param_count; i++, argv_dst++) { + switch (func_type->types[i]) { + case VALUE_TYPE_I32: + { + *(int32*)argv_dst = arg_i32 = (int32)*argv_src++; + if (signature) { + if (signature[i + 1] == '*') { + /* param is a pointer */ + if (signature[i + 2] == '~') + /* pointer with length followed */ + ptr_len = *argv_src; + else + /* pointer without length followed */ + ptr_len = 1; + + if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len)) + goto fail; + + *(uintptr_t*)argv_dst = (uintptr_t) + wasm_runtime_addr_app_to_native(module, arg_i32); + } + else if (signature[i + 1] == '$') { + /* param is a string */ + if (!wasm_runtime_validate_app_str_addr(module, arg_i32)) + goto fail; + + *(uintptr_t*)argv_dst = (uintptr_t) + wasm_runtime_addr_app_to_native(module, arg_i32); + } + } + break; + } + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + bh_memcpy_s(argv_dst, sizeof(uint64), argv_src, sizeof(uint32) * 2); + argv_src += 2; + break; + case VALUE_TYPE_F32: + *(float32*)argv_dst = *(float32*)argv_src++; + break; + default: + bh_assert(0); + break; + } + } + + exec_env->attachment = attachment; + invokeNativeRaw(exec_env, argv1); + exec_env->attachment = NULL; + + if (func_type->result_count > 0) { + switch (func_type->types[func_type->param_count]) { + case VALUE_TYPE_I32: + argv_ret[0] = *(uint32*)argv1; + break; + case VALUE_TYPE_F32: + *(float32*)argv_ret = *(float32*)argv1; + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1, sizeof(uint64)); + break; + default: + bh_assert(0); + break; + } + } + + ret = true; + +fail: + if (argv1 != argv_buf) + wasm_runtime_free(argv1); + return ret; +} + /** * Implementation of wasm_runtime_invoke_native() */ @@ -1474,6 +1611,7 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, + void *attachment, uint32 *argv, uint32 argc, uint32 *argv_ret) { WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); @@ -1639,6 +1777,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, } } + exec_env->attachment = attachment; if (func_type->result_count == 0) { invokeNative_Void(func_ptr, argv1, n_stacks); } @@ -1661,6 +1800,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, break; } } + exec_env->attachment = NULL; ret = true; @@ -1694,6 +1834,7 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, + void *attachment, uint32 *argv, uint32 argc, uint32 *argv_ret) { WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); @@ -1779,6 +1920,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, } argc1 = j; + exec_env->attachment = attachment; if (func_type->result_count == 0) { invokeNative_Void(func_ptr, argv1, argc1); } @@ -1801,6 +1943,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, break; } } + exec_env->attachment = NULL; ret = true; @@ -1816,7 +1959,9 @@ fail: || defined(BUILD_TARGET_MIPS) \ || defined(BUILD_TARGET_XTENSA) */ -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +#if defined(BUILD_TARGET_X86_64) \ + || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_AARCH64) typedef void (*GenericFunctionPointer)(); int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks); @@ -1826,23 +1971,28 @@ typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint64*,uint64); typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint64*, uint64); typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint64*, uint64); -static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative; -static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative; -static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative; -static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative; -static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; +static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)(uintptr_t)invokeNative; +static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)(uintptr_t)invokeNative; +static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)(uintptr_t)invokeNative; +static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)(uintptr_t)invokeNative; +static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)(uintptr_t)invokeNative; #if defined(_WIN32) || defined(_WIN32_) #define MAX_REG_FLOATS 4 #define MAX_REG_INTS 4 #else #define MAX_REG_FLOATS 8 +#if defined(BUILD_TARGET_AARCH64) +#define MAX_REG_INTS 8 +#else #define MAX_REG_INTS 6 -#endif +#endif /* end of defined(BUILD_TARGET_AARCH64 */ +#endif /* end of defined(_WIN32) || defined(_WIN32_) */ bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, + void *attachment, uint32 *argv, uint32 argc, uint32 *argv_ret) { WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); @@ -1937,6 +2087,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, } } + exec_env->attachment = attachment; if (func_type->result_count == 0) { invokeNative_Void(func_ptr, argv1, n_stacks); } @@ -1959,6 +2110,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, break; } } + exec_env->attachment = NULL; ret = true; fail: @@ -1968,4 +2120,33 @@ fail: return ret; } -#endif /* end of defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */ +bool +wasm_runtime_call_indirect(WASMExecEnv *exec_env, + uint32_t element_indices, + uint32_t argc, uint32_t argv[]) +{ + if (!wasm_runtime_env_check(exec_env)) { + LOG_ERROR("Invalid exec env stack info."); + return false; + } + + exec_env->handle = os_self_thread(); + +#if WASM_ENABLE_INTERP != 0 + if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) + return wasm_call_indirect(exec_env, + element_indices, + argc, argv); +#endif +#if WASM_ENABLE_AOT != 0 + if (exec_env->module_inst->module_type == Wasm_Module_AoT) + return aot_call_indirect(exec_env, false, 0, + element_indices, + argv, argc, argv); +#endif + return false; +} + +#endif /* end of defined(BUILD_TARGET_X86_64) \ + || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_AARCH64) */ diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 39c803c19..3490620b2 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -8,7 +8,6 @@ #include "bh_platform.h" #include "bh_common.h" -#include "bh_thread.h" #include "wasm_exec_env.h" #include "wasm_native.h" #include "../include/wasm_export.h" @@ -114,12 +113,46 @@ wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env); WASMModuleInstanceCommon * wasm_runtime_get_module_inst(WASMExecEnv *exec_env); +/* See wasm_export.h for description */ +void * +wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env); + +/* See wasm_export.h for description */ +void +wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data); + +/* See wasm_export.h for description */ +void * +wasm_runtime_get_user_data(wasm_exec_env_t exec_env); + /* See wasm_export.h for description */ bool wasm_runtime_call_wasm(WASMExecEnv *exec_env, WASMFunctionInstanceCommon *function, unsigned argc, uint32 argv[]); +/** + * Call a function reference of a given WASM runtime instance with + * arguments. + * + * @param exec_env the execution environment to call the function + * which must be created from wasm_create_exec_env() + * @param element_indices the function ference indicies, usually + * prvovided by the caller of a registed native function + * @param argc the number of arguments + * @param argv the arguments. If the function method has return value, + * the first (or first two in case 64-bit return value) element of + * argv stores the return value of the called WASM function after this + * function returns. + * + * @return true if success, false otherwise and exception will be thrown, + * the caller can call wasm_runtime_get_exception to get exception info. + */ +bool +wasm_runtime_call_indirect(WASMExecEnv *exec_env, + uint32_t element_indices, + uint32_t argc, uint32_t argv[]); + bool wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function, @@ -258,6 +291,7 @@ wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst, WASIContext * wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst); + #endif /* end of WASM_ENABLE_LIBC_WASI */ /** @@ -276,11 +310,23 @@ wasm_runtime_register_natives(const char *module_name, NativeSymbol *native_symbols, uint32 n_native_symbols); +/* See wasm_export.h for description */ +bool +wasm_runtime_register_natives_raw(const char *module_name, + NativeSymbol *native_symbols, + uint32 n_native_symbols); + bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, + void *attachment, uint32 *argv, uint32 argc, uint32 *ret); +bool +wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, + const WASMType *func_type, const char *signature, + void *attachment, + uint32 *argv, uint32 argc, uint32 *ret); #ifdef __cplusplus } diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index 8f8bfaa77..ee431fd4f 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -265,6 +265,8 @@ aot_create_import_funcs(const WASMModule *module) import_funcs[i].func_ptr_linked = import_func->func_ptr_linked; import_funcs[i].func_type = import_func->func_type; import_funcs[i].signature = import_func->signature; + import_funcs[i].attachment = import_func->attachment; + import_funcs[i].call_conv_raw = import_func->call_conv_raw; /* Resolve function type index */ for (j = 0; j < module->type_count; j++) if (import_func->func_type == module->types[j]) { diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index afc099eb7..22ccff60e 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -85,6 +85,9 @@ typedef struct AOTImportFunc { void *func_ptr_linked; /* signature from registered native symbols */ const char *signature; + /* attachment */ + void *attachment; + bool call_conv_raw; } AOTImportFunc; /** diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 14e45f0ed..21f85f37d 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -727,6 +727,8 @@ aot_compile_wasm(AOTCompContext *comp_ctx) bool ret; uint32 i; + bh_print_time("Begin to compile WASM bytecode to LLVM IR"); + for (i = 0; i < comp_ctx->func_ctx_count; i++) if (!aot_compile_func(comp_ctx, i)) { #if 0 @@ -744,6 +746,8 @@ aot_compile_wasm(AOTCompContext *comp_ctx) errno = 0; #endif + bh_print_time("Begin to verify LLVM module"); + ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg); if (!ret && msg) { if (msg[0] != '\0') { @@ -754,6 +758,8 @@ aot_compile_wasm(AOTCompContext *comp_ctx) LLVMDisposeMessage(msg); } + bh_print_time("Begin to run function optimization passes"); + if (comp_ctx->optimize) { LLVMInitializeFunctionPassManager(comp_ctx->pass_mgr); for (i = 0; i < comp_ctx->func_ctx_count; i++) @@ -769,6 +775,8 @@ aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name) { char *err = NULL; + bh_print_time("Begin to emit LLVM IR file"); + if (LLVMPrintModuleToFile(comp_ctx->module, file_name, &err) != 0) { if (err) { LLVMDisposeMessage(err); @@ -786,6 +794,8 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name) { char *err = NULL; + bh_print_time("Begin to emit object file"); + if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine, comp_ctx->module, file_name, diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 9f8c82d08..20675f224 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -49,6 +49,10 @@ typedef struct AOTObjectData { void *text; uint32 text_size; + /* literal data and size */ + void *literal; + uint32 literal_size; + AOTObjectDataSection *data_sections; uint32 data_sections_count; @@ -379,7 +383,7 @@ get_init_data_section_size(AOTCompData *comp_data, AOTObjectData *obj_data) static uint32 get_text_section_size(AOTObjectData *obj_data) { - return obj_data->text_size; + return (sizeof(uint32) + obj_data->literal_size + obj_data->text_size + 3) & ~3; } static uint32 @@ -1118,13 +1122,20 @@ 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; *p_offset = offset = align_uint(offset, 4); EMIT_U32(AOT_SECTION_TYPE_TEXT); EMIT_U32(section_size); + EMIT_U32(obj_data->literal_size); + if (obj_data->literal_size > 0) + EMIT_BUF(obj_data->literal, obj_data->literal_size); EMIT_BUF(obj_data->text, obj_data->text_size); + while (offset & 3) + EMIT_BUF(&placeholder, 1); + if (offset - *p_offset != section_size + sizeof(uint32) * 2) { aot_set_last_error("emit text section failed."); return false; @@ -1449,6 +1460,29 @@ aot_resolve_text(AOTObjectData *obj_data) return true; } +static bool +aot_resolve_literal(AOTObjectData *obj_data) +{ + LLVMSectionIteratorRef sec_itr; + char *name; + + if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + return false; + } + while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { + if ((name = (char *)LLVMGetSectionName(sec_itr)) && !strcmp(name, ".literal")) { + obj_data->literal = (char *)LLVMGetSectionContents(sec_itr); + obj_data->literal_size = (uint32)LLVMGetSectionSize(sec_itr); + break; + } + LLVMMoveToNextSection(sec_itr); + } + LLVMDisposeSectionIterator(sec_itr); + + return true; +} + static bool is_data_section(char *section_name) { @@ -1701,6 +1735,7 @@ is_relocation_section(char *section_name) { return (!strcmp(section_name, ".rela.text") || !strcmp(section_name, ".rel.text") + || !strcmp(section_name, ".rela.literal") || !strcmp(section_name, ".rela.data") || !strcmp(section_name, ".rel.data") || !strcmp(section_name, ".rela.rodata") @@ -1837,6 +1872,8 @@ aot_obj_data_create(AOTCompContext *comp_ctx) char *err = NULL; AOTObjectData *obj_data; + bh_print_time("Begin to emit object file to buffer"); + if (!(obj_data = wasm_runtime_malloc(sizeof(AOTObjectData)))) { aot_set_last_error("allocate memory failed."); return false; @@ -1866,9 +1903,12 @@ aot_obj_data_create(AOTCompContext *comp_ctx) goto fail; } + bh_print_time("Begin to resolve object file info"); + /* resolve target info/text/relocations/functions */ if (!aot_resolve_target_info(comp_ctx, obj_data) || !aot_resolve_text(obj_data) + || !aot_resolve_literal(obj_data) || !aot_resolve_object_data_sections(obj_data) || !aot_resolve_object_relocation_groups(obj_data) || !aot_resolve_functions(comp_ctx, obj_data)) @@ -1894,6 +1934,8 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data, if (!obj_data) return false; + bh_print_time("Begin to emit AOT file"); + aot_file_size = get_aot_file_size(comp_data, obj_data); if (!(buf = aot_file_buf = wasm_runtime_malloc(aot_file_size))) { diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index 0634435ba..0a8d2a1a0 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -8,41 +8,17 @@ #include "aot_emit_control.h" #include "../aot/aot_runtime.h" -/* Check whether there was exception thrown, if yes, return directly */ static bool -check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { + LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); AOTFuncType *aot_func_type = func_ctx->aot_func->func_type; - LLVMBasicBlockRef block_curr, check_exce_succ; - LLVMValueRef value, cmp; - - /* Load the first byte of aot_module_inst->cur_exception, and check - whether it is '\0'. If yes, no exception was thrown. */ - if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception, - "exce_value")) - || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, - value, I8_ZERO, "cmp"))) { - aot_set_last_error("llvm build icmp failed."); - return false; - } - - /* Add check exection success block */ - if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_exce_succ"))) { - aot_set_last_error("llvm add basic block failed."); - return false; - } - - block_curr = LLVMGetInsertBlock(comp_ctx->builder); - LLVMMoveBasicBlockAfter(check_exce_succ, block_curr); /* Create function return block if it isn't created */ if (!func_ctx->func_return_block) { if (!(func_ctx->func_return_block = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "func_ret"))) { + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, "func_ret"))) { aot_set_last_error("llvm add basic block failed."); return false; } @@ -70,6 +46,42 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } } + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); + return true; +} + +/* Check whether there was exception thrown, if yes, return directly */ +static bool +check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMBasicBlockRef block_curr, check_exce_succ; + LLVMValueRef value, cmp; + + /* Create function return block if it isn't created */ + if (!create_func_return_block(comp_ctx, func_ctx)) + return false; + + /* Load the first byte of aot_module_inst->cur_exception, and check + whether it is '\0'. If yes, no exception was thrown. */ + if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception, + "exce_value")) + || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, + value, I8_ZERO, "cmp"))) { + aot_set_last_error("llvm build icmp failed."); + return false; + } + + /* Add check exection success block */ + if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_exce_succ"))) { + aot_set_last_error("llvm add basic block failed."); + return false; + } + + block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMMoveBasicBlockAfter(check_exce_succ, block_curr); + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); /* Create condition br */ if (!LLVMBuildCondBr(comp_ctx->builder, cmp, @@ -82,18 +94,59 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) return true; } +/* Check whether there was exception thrown, if yes, return directly */ +static bool +check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef res) +{ + LLVMBasicBlockRef block_curr, check_call_succ; + LLVMValueRef cmp; + + /* Create function return block if it isn't created */ + if (!create_func_return_block(comp_ctx, func_ctx)) + return false; + + if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, + res, I8_ZERO, "cmp"))) { + aot_set_last_error("llvm build icmp failed."); + return false; + } + + /* Add check exection success block */ + if (!(check_call_succ = LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_exce_succ"))) { + aot_set_last_error("llvm add basic block failed."); + return false; + } + + block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMMoveBasicBlockAfter(check_call_succ, block_curr); + + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); + /* Create condition br */ + if (!LLVMBuildCondBr(comp_ctx->builder, cmp, + check_call_succ, func_ctx->func_return_block)) { + aot_set_last_error("llvm build cond br failed."); + return false; + } + + LLVMPositionBuilderAtEnd(comp_ctx->builder, check_call_succ); + return true; +} + static bool call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef func_idx, AOTFuncType *aot_func_type, LLVMTypeRef *param_types, LLVMValueRef *param_values, uint32 param_count, uint32 param_cell_num, LLVMTypeRef ret_type, uint8 wasm_ret_type, - LLVMValueRef *p_value_ret) + LLVMValueRef *p_value_ret, LLVMValueRef *p_res) { LLVMTypeRef func_type, func_ptr_type, func_param_types[5]; LLVMTypeRef ret_ptr_type, elem_ptr_type; LLVMValueRef func, elem_idx, elem_ptr; - LLVMValueRef func_param_values[5], value_ret, value_ret_ptr, res; + LLVMValueRef func_param_values[5], value_ret = NULL, value_ret_ptr, res; char buf[32], *func_name = "aot_invoke_native"; uint32 i, cell_num = 0; @@ -103,7 +156,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, func_param_types[2] = INT32_PTR_TYPE; /* frame_lp */ func_param_types[3] = I32_TYPE; /* argc */ func_param_types[4] = INT32_PTR_TYPE; /* argv_ret */ - if (!(func_type = LLVMFunctionType(VOID_TYPE, func_param_types, 5, false))) { + if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) { aot_set_last_error("llvm add function type failed."); return false; } @@ -198,7 +251,8 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* call aot_invoke_native() function */ - if (!(LLVMBuildCall(comp_ctx->builder, func, func_param_values, 5, ""))) { + if (!(res = LLVMBuildCall(comp_ctx->builder, func, + func_param_values, 5, "res"))) { aot_set_last_error("llvm build call failed."); return false; } @@ -207,6 +261,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* get function return value */ *p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret"); + *p_res = res; return true; } @@ -221,7 +276,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, AOTFuncType *func_type; LLVMTypeRef *param_types = NULL, ret_type; LLVMValueRef *param_values = NULL, value_ret = NULL, func; - LLVMValueRef import_func_idx; + LLVMValueRef import_func_idx, res; int32 i, j = 0, param_count; uint64 total_size; uint8 wasm_ret_type; @@ -292,13 +347,17 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (!call_aot_invoke_native_func(comp_ctx, func_ctx, import_func_idx, func_type, param_types + 1, param_values + 1, param_count, param_cell_num, - ret_type, wasm_ret_type, &value_ret)) + ret_type, wasm_ret_type, &value_ret, &res)) + goto fail; + + /* Check whether there was exception thrown when executing the function */ + if (!check_call_return(comp_ctx, func_ctx, res)) goto fail; } else { func = func_ctxes[func_idx - import_func_count]->func; - /* Call the function */ + /* Call the function */ if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, param_values, (uint32)param_count + 1, (func_type->result_count > 0 @@ -309,15 +368,15 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Set calling convention for the call with the func's calling convention */ LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func)); + + /* Check whether there was exception thrown when executing the function */ + if (!check_exception_thrown(comp_ctx, func_ctx)) + goto fail; } if (func_type->result_count > 0) PUSH(value_ret, func_type->types[func_type->param_count]); - /* Check whether there was exception thrown when executing the function */ - if (!check_exception_thrown(comp_ctx, func_ctx)) - goto fail; - ret = true; fail: if (param_types) @@ -327,21 +386,150 @@ fail: return ret; } +static bool +call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + AOTFuncType *aot_func_type, + LLVMValueRef func_type_idx, LLVMValueRef table_elem_idx, + LLVMTypeRef *param_types, LLVMValueRef *param_values, + uint32 param_count, uint32 param_cell_num, + LLVMTypeRef ret_type, uint8 wasm_ret_type, + LLVMValueRef *p_value_ret, LLVMValueRef *p_res) +{ + LLVMTypeRef func_type, func_ptr_type, func_param_types[7]; + LLVMTypeRef ret_ptr_type, elem_ptr_type; + LLVMValueRef func, elem_idx, elem_ptr; + LLVMValueRef func_param_values[7], value_ret = NULL, value_ret_ptr, res = NULL; + char buf[32], *func_name = "aot_call_indirect"; + uint32 i, cell_num = 0; + + /* prepare function type of aot_call_indirect */ + func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */ + func_param_types[1] = INT8_TYPE; /* check_func_type */ + func_param_types[2] = I32_TYPE; /* func_type_idx */ + func_param_types[3] = I32_TYPE; /* table_elem_idx */ + func_param_types[4] = INT32_PTR_TYPE; /* frame_lp */ + func_param_types[5] = I32_TYPE; /* argc */ + func_param_types[6] = INT32_PTR_TYPE; /* argv_ret */ + if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 7, false))) { + aot_set_last_error("llvm add function type failed."); + return false; + } + + /* prepare function pointer */ + if (comp_ctx->is_jit_mode) { + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + + /* JIT mode, call the function directly */ + if (!(func = I64_CONST((uint64)(uintptr_t)aot_call_indirect)) + || !(func = LLVMConstIntToPtr(func, func_ptr_type))) { + aot_set_last_error("create LLVM value failed."); + return false; + } + } + else { + if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) + && !(func = LLVMAddFunction(comp_ctx->module, + func_name, func_type))) { + aot_set_last_error("add LLVM function failed."); + return false; + } + } + + if (param_count > 64) { + aot_set_last_error("prepare native arguments failed: " + "maximum 64 parameter cell number supported."); + return false; + } + + /* prepare frame_lp */ + for (i = 0; i < param_count; i++) { + if (!(elem_idx = I32_CONST(cell_num)) + || !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) { + aot_set_last_error("llvm add const or pointer type failed."); + return false; + } + + snprintf(buf, sizeof(buf), "%s%d", "elem", i); + if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->argv_buf, &elem_idx, 1, buf)) + || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr, + elem_ptr_type, buf))) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) { + aot_set_last_error("llvm build store failed."); + return false; + } + LLVMSetAlignment(res, 1); + + cell_num += wasm_value_type_cell_num(aot_func_type->types[i]); + } + + if (wasm_ret_type != VALUE_TYPE_VOID) { + if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) { + aot_set_last_error("llvm add pointer type failed."); + return false; + } + + if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf, + ret_ptr_type, "argv_ret"))) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + /* convert to int32 pointer */ + if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret, + INT32_PTR_TYPE, "argv_ret_ptr"))) { + aot_set_last_error("llvm build store failed."); + return false; + } + } + else { + value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE); + } + + func_param_values[0] = func_ctx->exec_env; + func_param_values[1] = I8_CONST(true); + func_param_values[2] = func_type_idx; + func_param_values[3] = table_elem_idx; + func_param_values[4] = func_ctx->argv_buf; + func_param_values[5] = I32_CONST(param_cell_num); + func_param_values[6] = value_ret_ptr; + + if (!func_param_values[1] || !func_param_values[4]) { + aot_set_last_error("llvm create const failed."); + return false; + } + + /* call aot_call_indirect() function */ + if (!(res = LLVMBuildCall(comp_ctx->builder, func, + func_param_values, 7, "res"))) { + aot_set_last_error("llvm build call failed."); + return false; + } + + if (wasm_ret_type != VALUE_TYPE_VOID) + /* get function return value */ + *p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret"); + + *p_res = res; + return true; +} + bool aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 type_idx) { AOTFuncType *func_type; - LLVMValueRef elem_idx, table_elem, func_idx, ftype_idx_ptr, ftype_idx; - LLVMValueRef cmp_elem_idx, cmp_func_idx, is_ftype_match, is_ftype_mismatch; - LLVMValueRef func, func_ptr, func_const, table_size_const, cmp_func_ptr; - LLVMValueRef *param_values = NULL, param_values_tmp[3], value_ret; - LLVMTypeRef *param_types = NULL, param_types_tmp[3], ret_type, - f_type, f_ptr_type; - LLVMBasicBlockRef check_elem_idx_succ, check_ftype_idx_succ; - LLVMBasicBlockRef check_func_idx_succ, check_func_ptr_succ; - char *func_name = "aot_is_wasm_type_equal"; - int32 i, j = 0, param_count; + LLVMValueRef elem_idx, ftype_idx; + LLVMValueRef *param_values = NULL, value_ret = NULL, res = NULL; + LLVMTypeRef *param_types = NULL, ret_type; + int32 i, param_count; uint32 param_cell_num; uint64 total_size; uint8 wasm_ret_type; @@ -353,210 +541,26 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } + ftype_idx = I32_CONST(type_idx); + CHECK_LLVM_CONST(ftype_idx); + func_type = comp_ctx->comp_data->func_types[type_idx]; param_cell_num = wasm_type_param_cell_num(func_type); POP_I32(elem_idx); - table_size_const = I32_CONST(comp_ctx->comp_data->table_size); - CHECK_LLVM_CONST(table_size_const); - - /* Check if (uint32)elem index >= table size */ - if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, - elem_idx, table_size_const, - "cmp_elem_idx"))) { - aot_set_last_error("llvm build icmp failed."); - goto fail; - } - - /* Throw exception if elem index >= table size */ - if (!(check_elem_idx_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_elem_idx_succ"))) { - aot_set_last_error("llvm add basic block failed."); - goto fail; - } - - LLVMMoveBasicBlockAfter(check_elem_idx_succ, - LLVMGetInsertBlock(comp_ctx->builder)); - - if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNDEFINED_ELEMENT, - true, cmp_elem_idx, check_elem_idx_succ))) - goto fail; - - /* Load function index */ - if (!(table_elem = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->table_base, - &elem_idx, 1, "table_elem"))) { - aot_set_last_error("llvm build add failed."); - goto fail; - } - - if (!(func_idx = LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) { - aot_set_last_error("llvm build load failed."); - goto fail; - } - - /* Check if func_idx == -1 */ - if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, - func_idx, I32_NEG_ONE, - "cmp_func_idx"))) { - aot_set_last_error("llvm build icmp failed."); - goto fail; - } - - /* Throw exception if func_idx == -1 */ - if (!(check_func_idx_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_func_idx_succ"))) { - aot_set_last_error("llvm add basic block failed."); - goto fail; - } - - LLVMMoveBasicBlockAfter(check_func_idx_succ, - LLVMGetInsertBlock(comp_ctx->builder)); - - if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNINITIALIZED_ELEMENT, - true, cmp_func_idx, check_func_idx_succ))) - goto fail; - - /* Load function type index */ - if (!(ftype_idx_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->func_type_indexes, - &func_idx, 1, - "ftype_idx_ptr"))) { - aot_set_last_error("llvm build inbounds gep failed."); - goto fail; - } - - if (!(ftype_idx = LLVMBuildLoad(comp_ctx->builder, ftype_idx_ptr, - "ftype_idx"))) { - aot_set_last_error("llvm build load failed."); - goto fail; - } - - /* Call aot_is_type_equal() to check whether function type match */ - param_types_tmp[0] = INT8_PTR_TYPE; - param_types_tmp[1] = I32_TYPE; - param_types_tmp[2] = I32_TYPE; - ret_type = INT8_TYPE; - - /* Create function type */ - if (!(f_type = LLVMFunctionType(ret_type, param_types_tmp, - 3, false))) { - aot_set_last_error("create LLVM function type failed."); - goto fail; - } - - if (comp_ctx->is_jit_mode) { - /* Create function type */ - if (!(f_ptr_type = LLVMPointerType(f_type, 0))) { - aot_set_last_error("create LLVM function type failed."); - goto fail; - } - /* Create LLVM function with const function pointer */ - if (!(func_const = I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal)) - || !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) { - aot_set_last_error("create LLVM value failed."); - goto fail; - } - } - else { - /* Create LLVM function with external function pointer */ - if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) - && !(func = LLVMAddFunction(comp_ctx->module, func_name, f_type))) { - aot_set_last_error("add LLVM function failed."); - goto fail; - } - } - - /* Call the aot_is_type_equal() function */ - param_values_tmp[0] = func_ctx->aot_inst; - param_values_tmp[1] = I32_CONST(type_idx); - param_values_tmp[2] = ftype_idx; - - CHECK_LLVM_CONST(param_values_tmp[1]); - - if (!(is_ftype_match = LLVMBuildCall(comp_ctx->builder, func, - param_values_tmp, 3, - "is_ftype_match"))) { - aot_set_last_error("llvm build icmp failed."); - goto fail; - } - - if (!(is_ftype_mismatch = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, - is_ftype_match, I8_ZERO, - "is_ftype_mismatch"))) { - aot_set_last_error("llvm build icmp failed."); - goto fail; - } - - if (!(check_ftype_idx_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_ftype_idx_success"))) { - aot_set_last_error("llvm add basic block failed."); - goto fail; - } - - LLVMMoveBasicBlockAfter(check_ftype_idx_succ, - LLVMGetInsertBlock(comp_ctx->builder)); - - if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_FUNCTION_TYPE_INDEX, - true, is_ftype_mismatch, check_ftype_idx_succ))) - goto fail; - - /* Load function pointer */ - if (!(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs, - &func_idx, 1, "func_ptr"))) { - aot_set_last_error("llvm build inbounds gep failed."); - goto fail; - } - - if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) { - aot_set_last_error("llvm build load failed."); - goto fail; - } - - /* Check whether import function is NULL */ - if (!(cmp_func_ptr = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) { - aot_set_last_error("llvm build is null failed."); - goto fail; - } - - /* Throw exception if import function is NULL */ - if (!(check_func_ptr_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_func_ptr_succ"))) { - aot_set_last_error("llvm add basic block failed."); - goto fail; - } - - LLVMMoveBasicBlockAfter(check_func_ptr_succ, - LLVMGetInsertBlock(comp_ctx->builder)); - - if (!(aot_emit_exception(comp_ctx, func_ctx, - EXCE_CALL_UNLINKED_IMPORT_FUNC, - true, cmp_func_ptr, check_func_ptr_succ))) - goto fail; - /* Initialize parameter types of the LLVM function */ param_count = (int32)func_type->param_count; - total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1); + total_size = sizeof(LLVMTypeRef) * (uint64)param_count; if (total_size >= UINT32_MAX || !(param_types = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("Allocate memory failed."); goto fail; } - j = 0; - param_types[j++] = comp_ctx->exec_env_type; for (i = 0; i < param_count; i++) - param_types[j++] = TO_LLVM_TYPE(func_type->types[i]); + param_types[i] = TO_LLVM_TYPE(func_type->types[i]); /* Resolve return type of the LLVM function */ if (func_type->result_count) { @@ -569,32 +573,30 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Allocate memory for parameters */ - total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1); + total_size = sizeof(LLVMValueRef) * (uint64)param_count; if (total_size >= UINT32_MAX || !(param_values = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("Allocate memory failed."); goto fail; } - /* First parameter is exec env */ - j = 0; - param_values[j++] = func_ctx->exec_env; - /* Pop parameters from stack */ for (i = param_count - 1; i >= 0; i--) - POP(param_values[i + j], func_type->types[i]); + POP(param_values[i], func_type->types[i]); - if (!call_aot_invoke_native_func(comp_ctx, func_ctx, func_idx, func_type, - param_types + 1, param_values + 1, + if (!call_aot_call_indirect_func(comp_ctx, func_ctx, + func_type, ftype_idx, elem_idx, + param_types, param_values, param_count, param_cell_num, - ret_type, wasm_ret_type, &value_ret)) + ret_type, wasm_ret_type, + &value_ret, &res)) goto fail; if (func_type->result_count > 0) PUSH(value_ret, func_type->types[func_type->param_count]); /* Check whether there was exception thrown when executing the function */ - if (!check_exception_thrown(comp_ctx, func_ctx)) + if (!check_call_return(comp_ctx, func_ctx, res)) goto fail; ret = true; diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index 62ea6cc8c..de50db3d0 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -858,18 +858,63 @@ fail: } static bool -is_targeting_soft_float(LLVMTargetMachineRef target_machine) +is_target_arm(AOTCompContext *comp_ctx) +{ + return !strncmp(comp_ctx->target_arch, "arm", 3) || + !strncmp(comp_ctx->target_arch, "thumb", 5); +} + +static bool +is_target_x86(AOTCompContext *comp_ctx) +{ + return !strncmp(comp_ctx->target_arch, "x86_64", 6) || + !strncmp(comp_ctx->target_arch, "i386", 4); +} + +static bool +is_target_xtensa(AOTCompContext *comp_ctx) +{ + return !strncmp(comp_ctx->target_arch, "xtensa", 6); +} + +static bool +is_target_mips(AOTCompContext *comp_ctx) +{ + return !strncmp(comp_ctx->target_arch, "mips", 4); +} + +static bool +is_targeting_soft_float(AOTCompContext *comp_ctx, bool is_f32) { bool ret = false; char *feature_string; if (!(feature_string = - LLVMGetTargetMachineFeatureString(target_machine))) { + LLVMGetTargetMachineFeatureString(comp_ctx->target_machine))) { aot_set_last_error("llvm get target machine feature string fail."); return false; } - ret = strstr(feature_string, "+soft-float") ? true : false; + /* Note: + * LLVM CodeGen uses FPU Coprocessor registers by default, + * so user must specify '--cpu-features=+soft-float' to wamrc if the target + * doesn't have or enable FPU on arm, x86 or mips. */ + if (is_target_arm(comp_ctx) || + is_target_x86(comp_ctx) || + is_target_mips(comp_ctx)) + ret = strstr(feature_string, "+soft-float") ? true : false; + else if (is_target_xtensa(comp_ctx)) + /* Note: + * 1. The Floating-Point Coprocessor Option of xtensa only support + * single-precision floating-point operations, so must use soft-float + * for f64(i.e. double). + * 2. LLVM CodeGen uses Floating-Point Coprocessor registers by default, + * so user must specify '--cpu-features=-fp' to wamrc if the target + * doesn't have or enable Floating-Point Coprocessor Option on xtensa. */ + ret = (!is_f32 || strstr(feature_string, "-fp")) ? true : false; + else + ret = true; + LLVMDisposeMessage(feature_string); return ret; } @@ -880,7 +925,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, { switch (arith_op) { case FLOAT_ADD: - if (is_targeting_soft_float(comp_ctx->target_machine)) + if (is_targeting_soft_float(comp_ctx, is_f32)) DEF_FP_BINARY_OP(LLVMBuildFAdd(comp_ctx->builder, left, right, "fadd"), "llvm build fadd fail."); else @@ -897,7 +942,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, NULL); return true; case FLOAT_SUB: - if (is_targeting_soft_float(comp_ctx->target_machine)) + if (is_targeting_soft_float(comp_ctx, is_f32)) DEF_FP_BINARY_OP(LLVMBuildFSub(comp_ctx->builder, left, right, "fsub"), "llvm build fsub fail."); else @@ -914,7 +959,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, NULL); return true; case FLOAT_MUL: - if (is_targeting_soft_float(comp_ctx->target_machine)) + if (is_targeting_soft_float(comp_ctx, is_f32)) DEF_FP_BINARY_OP(LLVMBuildFMul(comp_ctx->builder, left, right, "fmul"), "llvm build fmul fail."); else @@ -931,7 +976,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, NULL); return true; case FLOAT_DIV: - if (is_targeting_soft_float(comp_ctx->target_machine)) + if (is_targeting_soft_float(comp_ctx, is_f32)) DEF_FP_BINARY_OP(LLVMBuildFDiv(comp_ctx->builder, left, right, "fdiv"), "llvm build fdiv fail."); else @@ -1050,7 +1095,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, NULL); return true; case FLOAT_SQRT: - if (is_targeting_soft_float(comp_ctx->target_machine)) + if (is_targeting_soft_float(comp_ctx, is_f32)) DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, is_f32 ? "llvm.sqrt.f32" : "llvm.sqrt.f64", diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index a7a7e799f..37f8c20fd 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -740,7 +740,20 @@ typedef struct ArchItem { static ArchItem valid_archs[] = { { "x86_64", false }, { "i386", false }, + { "xtensa", false}, { "mips", true }, + { "aarch64v8", false }, + { "aarch64v8.1", false }, + { "aarch64v8.2", false }, + { "aarch64v8.3", false }, + { "aarch64v8.4", false }, + { "aarch64v8.5", false }, + { "aarch64_bev8", false }, /* big endian */ + { "aarch64_bev8.1", false }, + { "aarch64_bev8.2", false }, + { "aarch64_bev8.3", false }, + { "aarch64_bev8.4", false }, + { "aarch64_bev8.5", false }, { "armv4", true }, { "armv4t", true }, { "armv5t", true }, @@ -789,23 +802,23 @@ static void print_supported_targets() { uint32 i; - bh_printf("Supported targets:\n"); + os_printf("Supported targets:\n"); for (i = 0; i < sizeof(valid_archs) / sizeof(ArchItem); i++) { - bh_printf("%s ", valid_archs[i].arch); + os_printf("%s ", valid_archs[i].arch); if (valid_archs[i].support_eb) - bh_printf("%seb ", valid_archs[i].arch); + os_printf("%seb ", valid_archs[i].arch); } - bh_printf("\n"); + os_printf("\n"); } static void print_supported_abis() { uint32 i; - bh_printf("Supported ABI: "); + os_printf("Supported ABI: "); for (i = 0; i < sizeof(valid_abis) / sizeof(const char *); i++) - bh_printf("%s ", valid_abis[i]); - bh_printf("\n"); + os_printf("%s ", valid_abis[i]); + os_printf("\n"); } static bool @@ -917,6 +930,8 @@ aot_create_comp_context(AOTCompData *comp_data, goto fail; } comp_ctx->is_jit_mode = true; + comp_ctx->target_machine = + LLVMGetExecutionEngineTargetMachine(comp_ctx->exec_engine); } else { /* Create LLVM target machine */ @@ -937,6 +952,10 @@ aot_create_comp_context(AOTCompData *comp_data, arch = "thumbv4t"; else if (!strcmp(arch, "thumbeb")) arch = "thumbv4teb"; + else if (!strcmp(arch, "aarch64")) + arch = "aarch64v8"; + else if (!strcmp(arch, "aarch64_be")) + arch = "aarch64_bev8"; } /* Check target arch */ @@ -1026,24 +1045,24 @@ aot_create_comp_context(AOTCompData *comp_data, get_target_arch_from_triple(triple_norm, comp_ctx->target_arch, sizeof(comp_ctx->target_arch)); - bh_printf("Create AoT compiler with:\n"); - bh_printf(" target: %s\n", comp_ctx->target_arch); - bh_printf(" target cpu: %s\n", cpu); - bh_printf(" cpu features: %s\n", features); - bh_printf(" opt level: %d\n", opt_level); - bh_printf(" size level: %d\n", size_level); + os_printf("Create AoT compiler with:\n"); + os_printf(" target: %s\n", comp_ctx->target_arch); + os_printf(" target cpu: %s\n", cpu); + os_printf(" cpu features: %s\n", features); + os_printf(" opt level: %d\n", opt_level); + os_printf(" size level: %d\n", size_level); switch (option->output_format) { case AOT_LLVMIR_UNOPT_FILE: - bh_printf(" output format: unoptimized LLVM IR\n"); + os_printf(" output format: unoptimized LLVM IR\n"); break; case AOT_LLVMIR_OPT_FILE: - bh_printf(" output format: optimized LLVM IR\n"); + os_printf(" output format: optimized LLVM IR\n"); break; case AOT_FORMAT_FILE: - bh_printf(" output format: AoT file\n"); + os_printf(" output format: AoT file\n"); break; case AOT_OBJECT_FILE: - bh_printf(" output format: native object file\n"); + os_printf(" output format: native object file\n"); break; } @@ -1155,7 +1174,7 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx) if (comp_ctx->pass_mgr) LLVMDisposePassManager(comp_ctx->pass_mgr); - if (comp_ctx->target_machine) + if (comp_ctx->target_machine && !comp_ctx->is_jit_mode) LLVMDisposeTargetMachine(comp_ctx->target_machine); if (comp_ctx->builder) diff --git a/core/iwasm/include/lib_export.h b/core/iwasm/include/lib_export.h index 8489afc49..0bc4317b8 100644 --- a/core/iwasm/include/lib_export.h +++ b/core/iwasm/include/lib_export.h @@ -16,15 +16,23 @@ typedef struct NativeSymbol { const char *symbol; void *func_ptr; const char *signature; + /* attachment which can be retrieved in native API by + calling wasm_runtime_get_function_attachment(exec_env) */ + void *attachment; } NativeSymbol; -#define EXPORT_WASM_API(symbol) {#symbol, (void*)symbol, NULL} -#define EXPORT_WASM_API2(symbol) {#symbol, (void*)symbol##_wrapper, NULL} +#define EXPORT_WASM_API(symbol) {#symbol, (void*)symbol, NULL, NULL} +#define EXPORT_WASM_API2(symbol) {#symbol, (void*)symbol##_wrapper, NULL, NULL} #define EXPORT_WASM_API_WITH_SIG(symbol, signature) \ - {#symbol, (void*)symbol, signature} + {#symbol, (void*)symbol, signature, NULL} #define EXPORT_WASM_API_WITH_SIG2(symbol, signature) \ - {#symbol, (void*)symbol##_wrapper, signature} + {#symbol, (void*)symbol##_wrapper, signature, NULL} + +#define EXPORT_WASM_API_WITH_ATT(symbol, signature, attachment) \ + {#symbol, (void*)symbol, signature, attachment} +#define EXPORT_WASM_API_WITH_ATT2(symbol, signature, attachment) \ + {#symbol, (void*)symbol##_wrapper, signature, attachment} /** * Get the exported APIs of base lib diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 57b2ec077..c2e142f6f 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -15,6 +15,34 @@ extern "C" { #endif +#define get_module_inst(exec_env) \ + wasm_runtime_get_module_inst(exec_env) + +#define validate_app_addr(offset, size) \ + wasm_runtime_validate_app_addr(module_inst, offset, size) + +#define validate_app_str_addr(offset) \ + wasm_runtime_validate_app_str_addr(module_inst, offset) + +#define addr_app_to_native(offset) \ + wasm_runtime_addr_app_to_native(module_inst, offset) + +#define addr_native_to_app(ptr) \ + wasm_runtime_addr_native_to_app(module_inst, ptr) + +#define module_malloc(size, p_native_addr) \ + wasm_runtime_module_malloc(module_inst, size, p_native_addr) + +#define module_free(offset) \ + wasm_runtime_module_free(module_inst, offset) + +#define native_raw_return_type(type, args) type *raw_ret = (type*)(args) + +#define native_raw_get_arg(type, name, args) type name = *((type*)(args++)) + +#define native_raw_set_return(val) *raw_ret = (val) + + /* Uninstantiated WASM module loaded from WASM binary file or AoT binary file*/ struct WASMModuleCommon; @@ -334,6 +362,17 @@ wasm_application_execute_func(wasm_module_inst_t module_inst, const char * wasm_runtime_get_exception(wasm_module_inst_t module_inst); +/** + * Set exception info of the WASM module instance. + * + * @param module_inst the WASM module instance + * + * @param exception the exception string + */ +void +wasm_runtime_set_exception(wasm_module_inst_t module_inst, + const char *exception); + /** * Clear exception info of the WASM module instance. * @@ -538,6 +577,49 @@ bool wasm_runtime_register_natives(const char *module_name, NativeSymbol *native_symbols, uint32_t n_native_symbols); +/** + * Register native functions with same module name, similar to + * wasm_runtime_register_natives, the difference is that runtime passes raw + * arguments to native API, which means that the native API should be defined as: + * void foo(wasm_exec_env_t exec_env, uint64 *args); + * and native API should extract arguments one by one from args array with macro + * native_raw_get_arg + * and write the return value back to args[0] with macro + * native_raw_return_type and native_raw_set_return + */ +bool wasm_runtime_register_natives_raw(const char *module_name, + NativeSymbol *native_symbols, + uint32_t n_native_symbols); + +/** + * Get attachment of native function from execution environment + * + * @param exec_env the execution environment to retrieve + * + * @return the attachment of native function + */ +void * +wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env); + +/** + * Set user data to execution environment. + * + * @param exec_env the execution environment + * @param user_data the user data to be set + */ +void +wasm_runtime_set_user_data(wasm_exec_env_t exec_env, + void *user_data); +/** + * Get the user data within execution environment. + * + * @param exec_env the execution environment + * + * @return the user data (NULL if not set yet) + */ +void * +wasm_runtime_get_user_data(wasm_exec_env_t exec_env); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index d1c6b661e..96ed3954a 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -137,8 +137,11 @@ typedef struct WASMFunctionImport { WASMType *func_type; /* function pointer after linked */ void *func_ptr_linked; - /* signature from registered native symbols */ + /* signature from registered native symbols */ const char *signature; + /* attachment */ + void *attachment; + bool call_conv_raw; } WASMFunctionImport; typedef struct WASMGlobalImport { diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index c18151ee6..3cab86ce1 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -748,9 +748,18 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, return; } - ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked, - func_import->func_type, func_import->signature, - frame->lp, cur_func->param_cell_num, argv_ret); + if (!func_import->call_conv_raw) { + ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked, + func_import->func_type, func_import->signature, + func_import->attachment, + frame->lp, cur_func->param_cell_num, argv_ret); + } + else { + ret = wasm_runtime_invoke_native_raw(exec_env, func_import->func_ptr_linked, + func_import->func_type, func_import->signature, + func_import->attachment, + frame->lp, cur_func->param_cell_num, argv_ret); + } if (!ret) return; @@ -818,7 +827,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op - DEFINE_GOTO_TABLE (handle_table); + DEFINE_GOTO_TABLE (const void *, handle_table); #undef HANDLE_OPCODE #endif @@ -1401,7 +1410,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, /* fail to memory.grow, return -1 */ PUSH_I32(-1); if (wasm_get_exception(module)) { - bh_printf("%s\n", wasm_get_exception(module)); + os_printf("%s\n", wasm_get_exception(module)); wasm_set_exception(module, NULL); } } diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index c372115e1..5edfec5f0 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -225,31 +225,7 @@ LOAD_I16(void *addr) #endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */ -#define CHECK_MEMORY_OVERFLOW() do { \ - uint64 offset1 = offset + addr; \ - /* if (flags != 2) \ - LOG_VERBOSE("unaligned load/store in wasm interp, flag: %d.\n", flags); */\ - /* The WASM spec doesn't require that the dynamic address operand must be \ - unsigned, so we don't check whether integer overflow or not here. */ \ - /* if (offset1 < offset) \ - goto out_of_bounds; */ \ - if (offset1 + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] <= memory_data_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 if (offset1 > DEFAULT_APP_HEAP_BASE_OFFSET \ - && (offset1 + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] <= \ - DEFAULT_APP_HEAP_BASE_OFFSET + heap_data_size)) { \ - /* If offset1 is in valid range, maddr must also be in valid range, \ - no need to check it again. */ \ - maddr = memory->heap_data + offset1 - DEFAULT_APP_HEAP_BASE_OFFSET; \ - } \ - else \ - goto out_of_bounds; \ - } while (0) - -#define CHECK_MEMORY_OVERFLOW_FAST(bytes) do { \ +#define CHECK_MEMORY_OVERFLOW(bytes) do { \ uint64 offset1 = offset + addr; \ /* if (flags != 2) \ LOG_VERBOSE("unaligned load/store in wasm interp, flag: %d.\n", flags); */\ @@ -675,6 +651,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { + WASMFunctionImport *func_import = cur_func->u.func_import; unsigned local_cell_num = 2; WASMInterpFrame *frame; uint32 argv_ret[2]; @@ -691,20 +668,27 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, wasm_exec_env_set_cur_frame(exec_env, frame); - if (!cur_func->u.func_import->func_ptr_linked) { + if (!func_import->func_ptr_linked) { char buf[128]; snprintf(buf, sizeof(buf), "fail to call unlinked import function (%s, %s)", - cur_func->u.func_import->module_name, - cur_func->u.func_import->field_name); + func_import->module_name, func_import->field_name); wasm_set_exception((WASMModuleInstance*)module_inst, buf); return; } - ret = wasm_runtime_invoke_native(exec_env, cur_func->u.func_import->func_ptr_linked, - cur_func->u.func_import->func_type, - cur_func->u.func_import->signature, - frame->lp, cur_func->param_cell_num, argv_ret); + if (!func_import->call_conv_raw) { + ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked, + func_import->func_type, func_import->signature, + func_import->attachment, + frame->lp, cur_func->param_cell_num, argv_ret); + } + else { + ret = wasm_runtime_invoke_native_raw(exec_env, func_import->func_ptr_linked, + func_import->func_type, func_import->signature, + func_import->attachment, + frame->lp, cur_func->param_cell_num, argv_ret); + } if (!ret) return; @@ -713,17 +697,50 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, prev_frame->lp[prev_frame->ret_offset] = argv_ret[0]; } else if (cur_func->ret_cell_num == 2) { - *(int64*)(prev_frame->lp + prev_frame->ret_offset) = *(int64*)argv_ret; + prev_frame->lp[prev_frame->ret_offset] = argv_ret[0]; + prev_frame->lp[prev_frame->ret_offset + 1] = argv_ret[1]; } FREE_FRAME(exec_env, frame); wasm_exec_env_set_cur_frame(exec_env, prev_frame); } +#if WASM_ENABLE_OPCODE_COUNTER != 0 +typedef struct OpcodeInfo { + char *name; + uint64 count; +} OpcodeInfo; + +#define HANDLE_OPCODE(op) { #op, 0 } +DEFINE_GOTO_TABLE (OpcodeInfo, opcode_table); +#undef HANDLE_OPCODE + +static void +wasm_interp_dump_op_count() +{ + uint32 i; + uint64 total_count = 0; + for (i = 0; i < WASM_OP_IMPDEP; i++) + total_count += opcode_table[i].count; + + printf("total opcode count: %ld\n", total_count); + for (i = 0; i < WASM_OP_IMPDEP; i++) + if (opcode_table[i].count > 0) + printf("\t\t%s count:\t\t%ld,\t\t%.2f%%\n", + opcode_table[i].name, opcode_table[i].count, + opcode_table[i].count * 100.0f / total_count); +} +#endif + + #if WASM_ENABLE_LABELS_AS_VALUES != 0 //#define HANDLE_OP(opcode) HANDLE_##opcode:printf(#opcode"\n");h_##opcode +#if WASM_ENABLE_OPCODE_COUNTER != 0 +#define HANDLE_OP(opcode) HANDLE_##opcode:opcode_table[opcode].count++;h_##opcode +#else #define HANDLE_OP(opcode) HANDLE_##opcode +#endif #if WASM_ENABLE_FAST_INTERP == 0 #define FETCH_OPCODE_AND_DISPATCH() goto *handle_table[*frame_ip++] #else @@ -752,7 +769,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, #endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_ENABLE_FAST_INTERP != 0 -static void *global_handle_table[WASM_INSTRUCTION_NUM] = { 0 }; +static void **global_handle_table; #endif static void @@ -778,10 +795,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #endif WASMGlobalInstance *global; uint8 *frame_ip_end; - uint8 opcode; uint32 cond, count, fidx, tidx, frame_size = 0; uint64 all_cell_num = 0; - int16 addr1, addr2, addr_ret; + int16 addr1, addr2, addr_ret = 0; int32 didx, val; uint8 *maddr = NULL; uint32 local_idx, local_offset, global_idx; @@ -789,23 +805,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op - DEFINE_GOTO_TABLE (handle_table); + DEFINE_GOTO_TABLE (const void*, handle_table); #undef HANDLE_OPCODE #if WASM_ENABLE_FAST_INTERP != 0 if (exec_env == NULL) { - bh_memcpy_s(global_handle_table, sizeof(void*) * WASM_INSTRUCTION_NUM, - handle_table, sizeof(void*) * WASM_INSTRUCTION_NUM); + global_handle_table = (void **)handle_table; return; } #endif #endif - /* Size of memory load. - This starts with the first memory load operator at opcode 0x28 */ - uint32 LOAD_SIZE[] = { - 4, 8, 4, 8, 1, 1, 2, 2, 1, 1, 2, 2, 4, 4, /* loads */ - 4, 8, 4, 8, 1, 2, 1, 2, 4 }; /* stores */ - #if WASM_ENABLE_LABELS_AS_VALUES == 0 while (frame_ip < frame_ip_end) { opcode = *frame_ip++; @@ -1016,133 +1025,144 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP (WASM_OP_I32_LOAD): { uint32 offset, addr; - offset = GET_OPERAND(uint32, 1); - addr = GET_OPERAND(uint32, 3); - frame_ip += 5; + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW_FAST(4); + CHECK_MEMORY_OVERFLOW(4); frame_lp[addr_ret] = LOAD_I32(maddr); HANDLE_OP_END (); } + HANDLE_OP (WASM_OP_I64_LOAD): - HANDLE_OP (WASM_OP_F32_LOAD): - HANDLE_OP (WASM_OP_F64_LOAD): - HANDLE_OP (WASM_OP_I32_LOAD8_S): - HANDLE_OP (WASM_OP_I32_LOAD8_U): - HANDLE_OP (WASM_OP_I32_LOAD16_S): - HANDLE_OP (WASM_OP_I32_LOAD16_U): - HANDLE_OP (WASM_OP_I64_LOAD8_S): - HANDLE_OP (WASM_OP_I64_LOAD8_U): - HANDLE_OP (WASM_OP_I64_LOAD16_S): - HANDLE_OP (WASM_OP_I64_LOAD16_U): - HANDLE_OP (WASM_OP_I64_LOAD32_S): - HANDLE_OP (WASM_OP_I64_LOAD32_U): { - uint32 offset, flags, addr; - GET_OPCODE(); + uint32 offset, addr; offset = GET_OPERAND(uint32, 0); - addr = GET_OPERAND(int32, 2); + addr = GET_OPERAND(uint32, 2); frame_ip += 4; addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(); -#if WASM_ENABLE_LABELS_AS_VALUES != 0 - static const void *handle_load_table[] = { - &&HANDLE_LOAD_WASM_OP_I32_LOAD, - &&HANDLE_LOAD_WASM_OP_I64_LOAD, - &&HANDLE_LOAD_WASM_OP_F32_LOAD, - &&HANDLE_LOAD_WASM_OP_F64_LOAD, - &&HANDLE_LOAD_WASM_OP_I32_LOAD8_S, - &&HANDLE_LOAD_WASM_OP_I32_LOAD8_U, - &&HANDLE_LOAD_WASM_OP_I32_LOAD16_S, - &&HANDLE_LOAD_WASM_OP_I32_LOAD16_U, - &&HANDLE_LOAD_WASM_OP_I64_LOAD8_S, - &&HANDLE_LOAD_WASM_OP_I64_LOAD8_U, - &&HANDLE_LOAD_WASM_OP_I64_LOAD16_S, - &&HANDLE_LOAD_WASM_OP_I64_LOAD16_U, - &&HANDLE_LOAD_WASM_OP_I64_LOAD32_S, - &&HANDLE_LOAD_WASM_OP_I64_LOAD32_U - }; - #define HANDLE_OP_LOAD(opcode) HANDLE_LOAD_##opcode - goto *handle_load_table[opcode - WASM_OP_I32_LOAD]; -#else - #define HANDLE_OP_LOAD(opcode) case opcode - switch (opcode) -#endif - { - HANDLE_OP_LOAD(WASM_OP_I32_LOAD): - frame_lp[addr_ret] = LOAD_I32(maddr); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I64_LOAD): - *(int64 *)(frame_lp + addr_ret) = (LOAD_I64(maddr)); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_F32_LOAD): - *(float32 *)(frame_lp + addr_ret) = (LOAD_F32(maddr)); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_F64_LOAD): - *(float64 *)(frame_lp + addr_ret) = (LOAD_F64(maddr)); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I32_LOAD8_S): - frame_lp[addr_ret] = sign_ext_8_32(*(int8*)maddr); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I32_LOAD8_U): - frame_lp[addr_ret] = (uint32)(*(uint8*)maddr); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I32_LOAD16_S): - frame_lp[addr_ret] = sign_ext_16_32(LOAD_I16(maddr)); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I32_LOAD16_U): - frame_lp[addr_ret] = (uint32)(LOAD_U16(maddr)); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I64_LOAD8_S): - *(int64 *)(frame_lp + addr_ret) = sign_ext_8_64(*(int8*)maddr); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I64_LOAD8_U): - *(int64 *)(frame_lp + addr_ret) = (uint64)(*(uint8*)maddr); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I64_LOAD16_S): - *(int64 *)(frame_lp + addr_ret) = sign_ext_16_64(LOAD_I16(maddr)); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I64_LOAD16_U): - *(int64 *)(frame_lp + addr_ret) = (uint64)(LOAD_U16(maddr)); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I64_LOAD32_S): - *(int64 *)(frame_lp + addr_ret) = sign_ext_32_64(LOAD_I32(maddr)); - HANDLE_OP_END(); - HANDLE_OP_LOAD(WASM_OP_I64_LOAD32_U): - *(int64 *)(frame_lp + addr_ret) = (uint64)(LOAD_U32(maddr)); - HANDLE_OP_END(); - } - (void)flags; + CHECK_MEMORY_OVERFLOW(8); + PUT_I64_TO_ADDR(frame_lp + addr_ret, LOAD_I64(maddr)); HANDLE_OP_END (); } - /* memory store instructions */ - HANDLE_OP (WASM_OP_F32_STORE): + HANDLE_OP (WASM_OP_I32_LOAD8_S): { uint32 offset, addr; - GET_OPCODE(); offset = GET_OPERAND(uint32, 0); - val = GET_OPERAND(int32, 2); - addr = GET_OPERAND(int32, 4); - frame_ip += 6; - CHECK_MEMORY_OVERFLOW_FAST(4); - STORE_U32(maddr, val); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(1); + frame_lp[addr_ret] = sign_ext_8_32(*(int8*)maddr); HANDLE_OP_END (); } - HANDLE_OP (WASM_OP_F64_STORE): + HANDLE_OP (WASM_OP_I32_LOAD8_U): { uint32 offset, addr; - int32 val_offset; - GET_OPCODE(); offset = GET_OPERAND(uint32, 0); - frame_ip += 2; - val_offset = GET_OFFSET(); - addr2 = GET_OFFSET(); - addr = (uint32)frame_lp[addr2]; - CHECK_MEMORY_OVERFLOW_FAST(8); - STORE_U32(maddr, frame_lp[val_offset]); - STORE_U32(maddr + 4, frame_lp[val_offset + 1]); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(1); + frame_lp[addr_ret] = (uint32)(*(uint8*)maddr); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_LOAD16_S): + { + uint32 offset, addr; + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(2); + frame_lp[addr_ret] = sign_ext_16_32(LOAD_I16(maddr)); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_LOAD16_U): + { + uint32 offset, addr; + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(2); + frame_lp[addr_ret] = (uint32)(LOAD_U16(maddr)); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_LOAD8_S): + { + uint32 offset, addr; + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(1); + *(int64 *)(frame_lp + addr_ret) = sign_ext_8_64(*(int8*)maddr); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_LOAD8_U): + { + uint32 offset, addr; + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(1); + *(int64 *)(frame_lp + addr_ret) = (uint64)(*(uint8*)maddr); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_LOAD16_S): + { + uint32 offset, addr; + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(2); + *(int64 *)(frame_lp + addr_ret) = sign_ext_16_64(LOAD_I16(maddr)); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_LOAD16_U): + { + uint32 offset, addr; + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(2); + *(int64 *)(frame_lp + addr_ret) = (uint64)(LOAD_U16(maddr)); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_LOAD32_S): + { + uint32 offset, addr; + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(4); + *(int64 *)(frame_lp + addr_ret) = sign_ext_32_64(LOAD_I32(maddr)); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_LOAD32_U): + { + uint32 offset, addr; + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(uint32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(4); + *(int64 *)(frame_lp + addr_ret) = (uint64)(LOAD_U32(maddr)); HANDLE_OP_END (); } @@ -1150,63 +1170,90 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { uint32 offset, addr; uint32 sval; - offset = GET_OPERAND(uint32, 1); - sval = GET_OPERAND(uint32, 3); - addr = GET_OPERAND(uint32, 5); - frame_ip += 7; - CHECK_MEMORY_OVERFLOW_FAST(4); - STORE_U32(maddr, sval); - HANDLE_OP_END (); - } - HANDLE_OP (WASM_OP_I32_STORE8): - HANDLE_OP (WASM_OP_I32_STORE16): - { - uint32 offset, addr; - uint32 sval; - GET_OPCODE(); offset = GET_OPERAND(uint32, 0); sval = GET_OPERAND(uint32, 2); addr = GET_OPERAND(uint32, 4); frame_ip += 6; - CHECK_MEMORY_OVERFLOW(); - switch (opcode) { - case WASM_OP_I32_STORE8: - *(uint8*)maddr = (uint8)sval; - break; - case WASM_OP_I32_STORE16: - STORE_U16(maddr, (uint16)sval); - break; - } + CHECK_MEMORY_OVERFLOW(4); + STORE_U32(maddr, sval); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_STORE8): + { + uint32 offset, addr; + uint32 sval; + offset = GET_OPERAND(uint32, 0); + sval = GET_OPERAND(uint32, 2); + addr = GET_OPERAND(uint32, 4); + frame_ip += 6; + CHECK_MEMORY_OVERFLOW(1); + *(uint8*)maddr = (uint8)sval; + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_STORE16): + { + uint32 offset, addr; + uint32 sval; + offset = GET_OPERAND(uint32, 0); + sval = GET_OPERAND(uint32, 2); + addr = GET_OPERAND(uint32, 4); + frame_ip += 6; + CHECK_MEMORY_OVERFLOW(2); + STORE_U16(maddr, (uint16)sval); HANDLE_OP_END (); } HANDLE_OP (WASM_OP_I64_STORE): - HANDLE_OP (WASM_OP_I64_STORE8): - HANDLE_OP (WASM_OP_I64_STORE16): - HANDLE_OP (WASM_OP_I64_STORE32): { uint32 offset, addr; uint64 sval; - GET_OPCODE(); offset = GET_OPERAND(uint32, 0); sval = GET_OPERAND(uint64, 2); addr = GET_OPERAND(uint32, 4); frame_ip += 6; - CHECK_MEMORY_OVERFLOW(); - switch (opcode) { - case WASM_OP_I64_STORE: - STORE_I64(maddr, sval); - break; - case WASM_OP_I64_STORE8: - *(uint8*)maddr = (uint8)sval; - break; - case WASM_OP_I64_STORE16: - STORE_U16(maddr, (uint16)sval); - break; - case WASM_OP_I64_STORE32: - STORE_U32(maddr, (uint32)sval); - break; - } + CHECK_MEMORY_OVERFLOW(8); + STORE_I64(maddr, sval); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_STORE8): + { + uint32 offset, addr; + uint64 sval; + offset = GET_OPERAND(uint32, 0); + sval = GET_OPERAND(uint64, 2); + addr = GET_OPERAND(uint32, 4); + frame_ip += 6; + CHECK_MEMORY_OVERFLOW(1); + *(uint8*)maddr = (uint8)sval; + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_STORE16): + { + uint32 offset, addr; + uint64 sval; + offset = GET_OPERAND(uint32, 0); + sval = GET_OPERAND(uint64, 2); + addr = GET_OPERAND(uint32, 4); + frame_ip += 6; + CHECK_MEMORY_OVERFLOW(2); + STORE_U16(maddr, (uint16)sval); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_STORE32): + { + uint32 offset, addr; + uint64 sval; + offset = GET_OPERAND(uint32, 0); + sval = GET_OPERAND(uint64, 2); + addr = GET_OPERAND(uint32, 4); + frame_ip += 6; + CHECK_MEMORY_OVERFLOW(4); + STORE_U32(maddr, (uint32)sval); HANDLE_OP_END (); } @@ -1232,7 +1279,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, /* fail to memory.grow, return -1 */ frame_lp[addr_ret] = -1; if (wasm_get_exception(module)) { - bh_printf("%s\n", wasm_get_exception(module)); + os_printf("%s\n", wasm_get_exception(module)); wasm_set_exception(module, NULL); } } @@ -2027,19 +2074,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP (WASM_OP_TEE_LOCAL): { GET_LOCAL_INDEX_TYPE_AND_OFFSET(); + addr1 = GET_OFFSET(); - switch (local_type) { - case VALUE_TYPE_I32: - case VALUE_TYPE_F32: - *(int32*)(frame_lp + local_offset) = GET_OPERAND(uint32, 0); - break; - case VALUE_TYPE_I64: - case VALUE_TYPE_F64: - PUT_I64_TO_ADDR((uint32*)(frame_lp + local_offset), GET_OPERAND(uint64, 0)); - break; - default: - wasm_set_exception(module, "invalid local type"); - goto got_exception; + if (local_type == VALUE_TYPE_I32 + || local_type == VALUE_TYPE_F32) { + *(int32*)(frame_lp + local_offset) = frame_lp[addr1]; + } + else if (local_type == VALUE_TYPE_I64 + || local_type == VALUE_TYPE_F64) { + PUT_I64_TO_ADDR((uint32*)(frame_lp + local_offset), + GET_I64_FROM_ADDR(frame_lp + addr1)); + } + else { + wasm_set_exception(module, "invalid local type"); + goto got_exception; } HANDLE_OP_END (); @@ -2085,6 +2133,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP (WASM_OP_UNUSED_0x26): HANDLE_OP (WASM_OP_UNUSED_0x27): /* optimized op code */ + HANDLE_OP (WASM_OP_F32_STORE): + HANDLE_OP (WASM_OP_F64_STORE): + HANDLE_OP (WASM_OP_F32_LOAD): + HANDLE_OP (WASM_OP_F64_LOAD): HANDLE_OP (EXT_OP_GET_LOCAL_FAST): HANDLE_OP (WASM_OP_GET_LOCAL): HANDLE_OP (WASM_OP_F64_CONST): @@ -2275,4 +2327,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, wasm_exec_env_set_cur_frame(exec_env, prev_frame); FREE_FRAME(exec_env, frame); +#if WASM_ENABLE_OPCODE_COUNTER != 0 + wasm_interp_dump_op_count(); +#endif } diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index b718c47b3..f136f4c18 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -492,8 +492,12 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, { const uint8 *p = *p_buf, *p_end = buf_end; uint32 pool_size = wasm_runtime_memory_pool_size(); +#if WASM_ENABLE_APP_FRAMEWORK != 0 uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT / DEFAULT_NUM_BYTES_PER_PAGE; +#else + uint32 max_page_count = pool_size / DEFAULT_NUM_BYTES_PER_PAGE; +#endif read_leb_uint32(p, p_end, memory->flags); read_leb_uint32(p, p_end, memory->init_page_count); @@ -539,8 +543,12 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, { const uint8 *p = *p_buf, *p_end = buf_end; uint32 pool_size = wasm_runtime_memory_pool_size(); +#if WASM_ENABLE_APP_FRAMEWORK != 0 uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT / DEFAULT_NUM_BYTES_PER_PAGE; +#else + uint32 max_page_count = pool_size / DEFAULT_NUM_BYTES_PER_PAGE; +#endif read_leb_uint32(p, p_end, memory->flags); read_leb_uint32(p, p_end, memory->init_page_count); @@ -667,9 +675,11 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, p = p_old; - /* insert "env" and "wasi_unstable" to const str list */ + /* insert "env", "wasi_unstable" and "wasi_snapshot_preview1" to const str list */ if (!const_str_list_insert((uint8*)"env", 3, module, error_buf, error_buf_size) || !const_str_list_insert((uint8*)"wasi_unstable", 13, module, + error_buf, error_buf_size) + || !const_str_list_insert((uint8*)"wasi_snapshot_preview1", 22, module, error_buf, error_buf_size)) { return false; } @@ -713,7 +723,9 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (!(import->u.function.func_ptr_linked = wasm_native_resolve_symbol(module_name, field_name, import->u.function.func_type, - &import->u.function.signature))) { + &import->u.function.signature, + &import->u.function.attachment, + &import->u.function.call_conv_raw))) { #if WASM_ENABLE_WAMR_COMPILER == 0 /* Output warning except running aot compiler */ LOG_WARNING("warning: fail to link import function (%s, %s)\n", module_name, field_name); @@ -787,7 +799,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, #if WASM_ENABLE_LIBC_WASI != 0 import = module->import_functions; for (i = 0; i < module->import_function_count; i++, import++) { - if (!strcmp(import->u.names.module_name, "wasi_unstable")) { + if (!strcmp(import->u.names.module_name, "wasi_unstable") + || !strcmp(import->u.names.module_name, "wasi_snapshot_preview1")) { module->is_wasi_module = true; break; } @@ -1620,9 +1633,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (llvm_data_end_global && llvm_heap_base_global) { if ((data_end_global_index == heap_base_global_index + 1 - && data_end_global_index > 0) + && (int32)data_end_global_index > 1) || (heap_base_global_index == data_end_global_index + 1 - && heap_base_global_index > 0)) { + && (int32)heap_base_global_index > 1)) { global_index = data_end_global_index < heap_base_global_index ? data_end_global_index - 1 : heap_base_global_index - 1; @@ -1694,7 +1707,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, return true; } -#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 +#if BH_ENABLE_MEMORY_PROFILING != 0 static void wasm_loader_free(void *ptr) { wasm_runtime_free(ptr); @@ -2311,7 +2324,7 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, #if WASM_ENABLE_FAST_INTERP != 0 #if WASM_DEBUG_PREPROCESSOR != 0 -#define LOG_OP(...) bh_printf(__VA_ARGS__) +#define LOG_OP(...) os_printf(__VA_ARGS__) #else #define LOG_OP(...) #endif @@ -2367,6 +2380,9 @@ typedef struct WASMLoaderContext { int16 start_dynamic_offset; int16 max_dynamic_offset; + /* preserved local offset */ + int16 preserved_local_offset; + /* const buffer */ uint8 *const_buf; uint16 num_const; @@ -2716,6 +2732,128 @@ wasm_loader_check_br(WASMLoaderContext *ctx, uint32 depth, } #if WASM_ENABLE_FAST_INTERP != 0 + +#if WASM_ENABLE_ABS_LABEL_ADDR != 0 + +#define emit_label(opcode) do { \ + wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) + +#define skip_label() do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) + +#else + +#define emit_label(opcode) do { \ + int32 offset = (int32)(handle_table[opcode] - handle_table[0]); \ + if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \ + set_error_buf(error_buf, error_buf_size, \ + "WASM module load failed: " \ + "pre-compiled label offset out of range"); \ + goto fail; \ + } \ + wasm_loader_emit_int16(loader_ctx, offset); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) + +// drop local.get / const / block / loop / end +#define skip_label() do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) + +#endif /* WASM_ENABLE_ABS_LABEL_ADDR */ + +#define emit_empty_label_addr_and_frame_ip(type) do { \ + if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \ + loader_ctx->p_code_compiled, \ + error_buf, error_buf_size)) \ + goto fail; \ + /* label address, to be patched */ \ + wasm_loader_emit_ptr(loader_ctx, NULL); \ + } while (0) + +#define emit_br_info(frame_csp) do { \ + if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define LAST_OP_OUTPUT_I32() (last_op >= WASM_OP_I32_EQZ \ + && last_op <= WASM_OP_I32_ROTR) \ + || (last_op == WASM_OP_I32_LOAD \ + || last_op == WASM_OP_F32_LOAD) \ + || (last_op >= WASM_OP_I32_LOAD8_S \ + && last_op <= WASM_OP_I32_LOAD16_U) \ + || (last_op >= WASM_OP_F32_ABS \ + && last_op <= WASM_OP_F32_COPYSIGN) \ + || (last_op >= WASM_OP_I32_WRAP_I64 \ + && last_op <= WASM_OP_I32_TRUNC_U_F64) \ + || (last_op >= WASM_OP_F32_CONVERT_S_I32 \ + && last_op <= WASM_OP_F32_DEMOTE_F64) \ + || (last_op == WASM_OP_I32_REINTERPRET_F32) \ + || (last_op == WASM_OP_F32_REINTERPRET_I32) \ + || (last_op == EXT_OP_COPY_STACK_TOP) + +#define LAST_OP_OUTPUT_I64() (last_op >= WASM_OP_I64_CLZ \ + && last_op <= WASM_OP_I64_ROTR) \ + || (last_op >= WASM_OP_F64_ABS \ + && last_op <= WASM_OP_F64_COPYSIGN) \ + || (last_op == WASM_OP_I64_LOAD \ + || last_op == WASM_OP_F64_LOAD) \ + || (last_op >= WASM_OP_I64_LOAD8_S \ + && last_op <= WASM_OP_I64_LOAD32_U) \ + || (last_op >= WASM_OP_I64_EXTEND_S_I32 \ + && last_op <= WASM_OP_I64_TRUNC_U_F64) \ + || (last_op >= WASM_OP_F64_CONVERT_S_I32 \ + && last_op <= WASM_OP_F64_PROMOTE_F32) \ + || (last_op == WASM_OP_I64_REINTERPRET_F64) \ + || (last_op == WASM_OP_F64_REINTERPRET_I64) \ + || (last_op == EXT_OP_COPY_STACK_TOP_I64) + +#define GET_CONST_OFFSET(type, val) do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, \ + val, 0, 0, &operand_offset, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define GET_CONST_F32_OFFSET(type, fval) do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, \ + 0, fval, 0, &operand_offset, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define GET_CONST_F64_OFFSET(type, fval) do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, \ + 0, 0, fval, &operand_offset, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define emit_operand(ctx, offset) do { \ + wasm_loader_emit_int16(ctx, offset); \ + LOG_OP("%d\t", offset); \ + } while (0) + +#define emit_byte(ctx, byte) do { \ + wasm_loader_emit_uint8(ctx, byte); \ + LOG_OP("%d\t", byte); \ + } while (0) + +#define emit_leb() do { \ + wasm_loader_emit_leb(loader_ctx, p_org, p); \ + } while (0) + +#define emit_const(value) do { \ + GET_CONST_OFFSET(VALUE_TYPE_I32, value); \ + emit_operand(loader_ctx, operand_offset); \ + } while (0) + static bool wasm_loader_ctx_reinit(WASMLoaderContext *ctx) { @@ -2741,6 +2879,9 @@ wasm_loader_ctx_reinit(WASMLoaderContext *ctx) ctx->frame_offset = ctx->frame_offset_bottom; ctx->dynamic_offset = ctx->start_dynamic_offset; + /* init preserved local offsets */ + ctx->preserved_local_offset = ctx->max_dynamic_offset; + /* const buf is reserved */ return true; } @@ -2803,6 +2944,49 @@ wasm_loader_emit_leb(WASMLoaderContext *ctx, uint8* start, uint8* end) } +static bool +preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode, + uint32 local_index, uint32 local_type, bool *preserved, + char *error_buf, uint32 error_buf_size) +{ + int16 preserved_offset = (int16)local_index; + *preserved = false; + for (uint32 i = 0; i < loader_ctx->stack_cell_num; i++) { + /* move previous local into dynamic space before a set/tee_local opcode */ + if (loader_ctx->frame_offset_bottom[i] == (int16)local_index) { + if (preserved_offset == (int16)local_index) { + *preserved = true; + skip_label(); + if (local_type == VALUE_TYPE_I32 + || local_type == VALUE_TYPE_F32) { + preserved_offset = loader_ctx->preserved_local_offset; + /* Only increase preserve offset in the second traversal */ + if (loader_ctx->p_code_compiled) + loader_ctx->preserved_local_offset++; + emit_label(EXT_OP_COPY_STACK_TOP); + } + else { + preserved_offset = loader_ctx->preserved_local_offset; + if (loader_ctx->p_code_compiled) + loader_ctx->preserved_local_offset += 2; + emit_label(EXT_OP_COPY_STACK_TOP_I64); + } + emit_operand(loader_ctx, local_index); + emit_operand(loader_ctx, preserved_offset); + emit_label(opcode); + } + loader_ctx->frame_offset_bottom[i] = preserved_offset; + } + } + + return true; + +#if WASM_ENABLE_ABS_LABEL_ADDR == 0 +fail: + return false; +#endif +} + static bool add_label_patch_to_list(BranchBlock *frame_csp, uint8 patch_type, uint8 *p_code_compiled, @@ -2830,7 +3014,7 @@ add_label_patch_to_list(BranchBlock *frame_csp, static void apply_label_patch(WASMLoaderContext *ctx, uint8 depth, - uint8 patch_type, uint8 *frame_ip) + uint8 patch_type) { BranchBlock *frame_csp = ctx->frame_csp - depth; BranchBlockPatch *node = frame_csp->patch_list; @@ -2858,31 +3042,17 @@ apply_label_patch(WASMLoaderContext *ctx, uint8 depth, } } -#define emit_operand(ctx, offset) do { \ - wasm_loader_emit_int16(ctx, offset); \ - LOG_OP("%d\t", offset); \ - } while (0) - -#define emit_byte(ctx, byte) do { \ - wasm_loader_emit_uint8(ctx, byte); \ - LOG_OP("%d\t", byte); \ - } while (0) - -#define emit_leb() do { \ - wasm_loader_emit_leb(loader_ctx, p_org, p); \ - } while (0) - -#define emit_const(value) do { \ - GET_CONST_OFFSET(VALUE_TYPE_I32, value); \ - emit_operand(loader_ctx, operand_offset); \ - } while (0) - static bool wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, char *error_buf, uint32 error_buf_size) { emit_operand(ctx, frame_csp->dynamic_offset); - if (frame_csp->return_type == VALUE_TYPE_I32 + if (frame_csp->block_type == BLOCK_TYPE_LOOP || + frame_csp->return_type == VALUE_TYPE_VOID) { + emit_byte(ctx, 0); + emit_operand(ctx, 0); + } + else if (frame_csp->return_type == VALUE_TYPE_I32 || frame_csp->return_type == VALUE_TYPE_F32) { emit_byte(ctx, 1); emit_operand(ctx, *(int16*)(ctx->frame_offset - 1)); @@ -2892,10 +3062,7 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, emit_byte(ctx, 2); emit_operand(ctx, *(int16*)(ctx->frame_offset - 2)); } - else { - emit_byte(ctx, 0); - emit_operand(ctx, 0); - } + if (frame_csp->block_type == BLOCK_TYPE_LOOP) { wasm_loader_emit_ptr(ctx, frame_csp->code_compiled); } @@ -2960,12 +3127,14 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type, if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32) { ctx->frame_offset -= 1; - if (*(ctx->frame_offset) > ctx->start_dynamic_offset) + if ((*(ctx->frame_offset) > ctx->start_dynamic_offset) + && (*(ctx->frame_offset) < ctx->max_dynamic_offset)) ctx->dynamic_offset -= 1; } else { ctx->frame_offset -= 2; - if (*(ctx->frame_offset) > ctx->start_dynamic_offset) + if ((*(ctx->frame_offset) > ctx->start_dynamic_offset) + && (*(ctx->frame_offset) < ctx->max_dynamic_offset)) ctx->dynamic_offset -= 2; } emit_operand(ctx, *(ctx->frame_offset)); @@ -3268,107 +3437,7 @@ check_memory(WASMModule *module, } while (0) #if WASM_ENABLE_FAST_INTERP != 0 -#if WASM_ENABLE_ABS_LABEL_ADDR != 0 -#define emit_label(opcode) do { \ - wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \ - LOG_OP("\nemit_op [%02x]\t", opcode); \ - } while (0) - -#define skip_label() do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \ - LOG_OP("\ndelete last op\n"); \ - } while (0) - -#else - -#define emit_label(opcode) do { \ - int32 offset = (int32)(handle_table[opcode] - handle_table[0]); \ - if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \ - set_error_buf(error_buf, error_buf_size, \ - "WASM module load failed: " \ - "pre-compiled label offset out of range"); \ - goto fail; \ - } \ - wasm_loader_emit_int16(loader_ctx, offset); \ - LOG_OP("\nemit_op [%02x]\t", opcode); \ - } while (0) - -// drop local.get / const / block / loop / end -#define skip_label() do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \ - LOG_OP("\ndelete last op\n"); \ - } while (0) - -#endif /* WASM_ENABLE_ABS_LABEL_ADDR */ - -#define emit_empty_label_addr_and_frame_ip(type) do { \ - if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \ - loader_ctx->p_code_compiled, \ - error_buf, error_buf_size)) \ - goto fail; \ - /* label address, to be patched */ \ - wasm_loader_emit_ptr(loader_ctx, NULL); \ - } while (0) - -#define emit_br_info(frame_csp) do { \ - if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define LAST_OP_OUTPUT_I32() (last_op >= WASM_OP_I32_EQZ \ - && last_op <= WASM_OP_I32_ROTR) \ - || (last_op == WASM_OP_I32_LOAD \ - || last_op == WASM_OP_F32_LOAD) \ - || (last_op >= WASM_OP_I32_LOAD8_S \ - && last_op <= WASM_OP_I32_LOAD16_U) \ - || (last_op >= WASM_OP_F32_ABS \ - && last_op <= WASM_OP_F32_COPYSIGN) \ - || (last_op >= WASM_OP_I32_WRAP_I64 \ - && last_op <= WASM_OP_I32_TRUNC_U_F64) \ - || (last_op >= WASM_OP_F32_CONVERT_S_I32 \ - && last_op <= WASM_OP_F32_DEMOTE_F64) \ - || (last_op == WASM_OP_I32_REINTERPRET_F32) \ - || (last_op == WASM_OP_F32_REINTERPRET_I32) \ - || (last_op == EXT_OP_COPY_STACK_TOP) - -#define LAST_OP_OUTPUT_I64() (last_op >= WASM_OP_I64_CLZ \ - && last_op <= WASM_OP_I64_ROTR) \ - || (last_op >= WASM_OP_F64_ABS \ - && last_op <= WASM_OP_F64_COPYSIGN) \ - || (last_op == WASM_OP_I64_LOAD \ - || last_op == WASM_OP_F64_LOAD) \ - || (last_op >= WASM_OP_I64_LOAD8_S \ - && last_op <= WASM_OP_I64_LOAD32_U) \ - || (last_op >= WASM_OP_I64_EXTEND_S_I32 \ - && last_op <= WASM_OP_I64_TRUNC_U_F64) \ - || (last_op >= WASM_OP_F64_CONVERT_S_I32 \ - && last_op <= WASM_OP_F64_PROMOTE_F32) \ - || (last_op == WASM_OP_I64_REINTERPRET_F64) \ - || (last_op == WASM_OP_F64_REINTERPRET_I64) \ - || (last_op == EXT_OP_COPY_STACK_TOP_I64) - -#define GET_CONST_OFFSET(type, val) do { \ - if (!(wasm_loader_get_const_offset(loader_ctx, type, \ - val, 0, 0, &operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define GET_CONST_F32_OFFSET(type, fval) do { \ - if (!(wasm_loader_get_const_offset(loader_ctx, type, \ - 0, fval, 0, &operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define GET_CONST_F64_OFFSET(type, fval) do { \ - if (!(wasm_loader_get_const_offset(loader_ctx, type, \ - 0, 0, fval, &operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) #endif /* WASM_ENABLE_FAST_INTERP */ @@ -3393,7 +3462,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 *func_const_end, *func_const; int16 operand_offset; uint8 last_op = 0; - bool disable_emit; + bool disable_emit, preserve_local = false; float32 f32; float64 f64; @@ -3514,10 +3583,17 @@ re_scan: error_buf, error_buf_size)) goto fail; - if ((loader_ctx->frame_csp - 1)->else_addr) - p = (loader_ctx->frame_csp - 1)->else_addr; - else + if ((loader_ctx->frame_csp - 1)->else_addr) { +#if WASM_ENABLE_FAST_INTERP != 0 + loader_ctx->frame_offset = loader_ctx->frame_offset_bottom + + (loader_ctx->frame_csp - 1)->stack_cell_num; + apply_label_patch(loader_ctx, 1, PATCH_ELSE); +#endif + p = (loader_ctx->frame_csp - 1)->else_addr + 1; + } + else { p = (loader_ctx->frame_csp - 1)->end_addr; + } is_i32_const = false; continue; @@ -3539,7 +3615,7 @@ re_scan: loader_ctx->frame_ref = loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; #if WASM_ENABLE_FAST_INTERP != 0 - // if the result of if branch is in local or const area, add a copy op + /* if the result of if branch is in local or const area, add a copy op */ if ((loader_ctx->frame_csp - 1)->return_type != VALUE_TYPE_VOID) { uint8 return_cells; if ((loader_ctx->frame_csp - 1)->return_type == VALUE_TYPE_I32 @@ -3557,14 +3633,14 @@ re_scan: emit_operand(loader_ctx, *(loader_ctx->frame_offset - return_cells)); emit_operand(loader_ctx, (loader_ctx->frame_csp - 1)->dynamic_offset); *(loader_ctx->frame_offset - return_cells) = - loader_ctx->frame_csp->dynamic_offset; + (loader_ctx->frame_csp - 1)->dynamic_offset; emit_label(opcode); } } loader_ctx->frame_offset = loader_ctx->frame_offset_bottom + loader_ctx->stack_cell_num; emit_empty_label_addr_and_frame_ip(PATCH_END); - apply_label_patch(loader_ctx, 1, PATCH_ELSE, p); + apply_label_patch(loader_ctx, 1, PATCH_ELSE); #endif break; @@ -3601,7 +3677,7 @@ re_scan: wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); } - apply_label_patch(loader_ctx, 0, PATCH_END, p); + apply_label_patch(loader_ctx, 0, PATCH_END); free_label_patch_list(loader_ctx->frame_csp); if (loader_ctx->frame_csp->block_type == BLOCK_TYPE_FUNCTION) { emit_label(WASM_OP_RETURN); @@ -3670,8 +3746,15 @@ handle_next_reachable_block: if ((loader_ctx->frame_csp - 1)->block_type == BLOCK_TYPE_IF && (loader_ctx->frame_csp - 1)->else_addr != NULL - && p <= (loader_ctx->frame_csp - 1)->else_addr) - p = (loader_ctx->frame_csp - 1)->else_addr; + && p <= (loader_ctx->frame_csp - 1)->else_addr) { +#if WASM_ENABLE_FAST_INTERP != 0 + loader_ctx->frame_offset = loader_ctx->frame_offset_bottom + + (loader_ctx->frame_csp - 1)->stack_cell_num; + apply_label_patch(loader_ctx, 1, PATCH_ELSE); +#endif + p = (loader_ctx->frame_csp - 1)->else_addr + 1; + + } else { p = (loader_ctx->frame_csp - 1)->end_addr; PUSH_TYPE(block_return_type); @@ -3736,40 +3819,6 @@ handle_next_reachable_block: POP_TYPE(ret_type); PUSH_TYPE(ret_type); - cache_index = ((uintptr_t)(loader_ctx->frame_csp - 1)->start_addr) - & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); - cache_items = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * cache_index; - for (item_index = 0; item_index < BLOCK_ADDR_CONFLICT_SIZE; - item_index++) { - if (cache_items[item_index].start_addr == - (loader_ctx->frame_csp - 1)->start_addr) { - (loader_ctx->frame_csp - 1)->else_addr = cache_items[item_index].else_addr; - (loader_ctx->frame_csp - 1)->end_addr = cache_items[item_index].end_addr; - break; - } - } - if(item_index == BLOCK_ADDR_CONFLICT_SIZE - && !wasm_loader_find_block_addr(block_addr_cache, - (loader_ctx->frame_csp - 1)->start_addr, - p_end, - (loader_ctx->frame_csp - 1)->block_type, - &(loader_ctx->frame_csp - 1)->else_addr, - &(loader_ctx->frame_csp - 1)->end_addr, - error_buf, error_buf_size)) - goto fail; - - loader_ctx->stack_cell_num = (loader_ctx->frame_csp - 1)->stack_cell_num; - loader_ctx->frame_ref = loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; - - if ((loader_ctx->frame_csp - 1)->block_type == BLOCK_TYPE_IF - && p <= (loader_ctx->frame_csp - 1)->else_addr) { - p = (loader_ctx->frame_csp - 1)->else_addr; - } - else { - p = (loader_ctx->frame_csp - 1)->end_addr; - PUSH_TYPE((loader_ctx->frame_csp - 1)->return_type); - } - #if WASM_ENABLE_FAST_INTERP != 0 // emit the offset after return opcode POP_OFFSET_TYPE(ret_type); @@ -3778,7 +3827,7 @@ handle_next_reachable_block: #endif is_i32_const = false; - continue; + goto handle_next_reachable_block; } case WASM_OP_CALL: @@ -3886,6 +3935,7 @@ handle_next_reachable_block: } case WASM_OP_DROP: + case WASM_OP_DROP_64: { if (loader_ctx->stack_cell_num <= 0) { set_error_buf(error_buf, error_buf_size, @@ -3915,7 +3965,7 @@ handle_next_reachable_block: } loader_ctx->frame_ref -= 2; loader_ctx->stack_cell_num -= 2; -#if WASM_ENABLE_FAST_INTERP == 0 +#if (WASM_ENABLE_FAST_INTERP == 0) || (WASM_ENABLE_JIT != 0) *(p - 1) = WASM_OP_DROP_64; #endif #if WASM_ENABLE_FAST_INTERP != 0 @@ -3930,6 +3980,7 @@ handle_next_reachable_block: } case WASM_OP_SELECT: + case WASM_OP_SELECT_64: { uint8 ref_type; @@ -3948,7 +3999,7 @@ handle_next_reachable_block: break; case REF_I64_2: case REF_F64_2: -#if WASM_ENABLE_FAST_INTERP == 0 +#if (WASM_ENABLE_FAST_INTERP == 0) || (WASM_ENABLE_JIT != 0) *(p - 1) = WASM_OP_SELECT_64; #endif #if WASM_ENABLE_FAST_INTERP != 0 @@ -4013,15 +4064,20 @@ handle_next_reachable_block: POP_TYPE(local_type); #if WASM_ENABLE_FAST_INTERP != 0 + if (!(preserve_referenced_local(loader_ctx, opcode, local_offset, + local_type, &preserve_local, + error_buf, error_buf_size))) + goto fail; + if (local_offset < 256) { skip_label(); - if (LAST_OP_OUTPUT_I32()) { + if ((!preserve_local) && (LAST_OP_OUTPUT_I32())) { if (loader_ctx->p_code_compiled) *(int16*)(loader_ctx->p_code_compiled - 2) = local_offset; loader_ctx->frame_offset --; loader_ctx->dynamic_offset --; } - else if (LAST_OP_OUTPUT_I64()) { + else if ((!preserve_local) && (LAST_OP_OUTPUT_I64())) { if (loader_ctx->p_code_compiled) *(int16*)(loader_ctx->p_code_compiled - 2) = local_offset; loader_ctx->frame_offset -= 2; @@ -4070,6 +4126,11 @@ handle_next_reachable_block: PUSH_TYPE(local_type); #if WASM_ENABLE_FAST_INTERP != 0 + if (!(preserve_referenced_local(loader_ctx, opcode, local_offset, + local_type, &preserve_local, + error_buf, error_buf_size))) + goto fail; + if (local_offset < 256) { skip_label(); if (local_type == VALUE_TYPE_I32 @@ -4175,11 +4236,29 @@ handle_next_reachable_block: case WASM_OP_F32_STORE: case WASM_OP_F64_STORE: { +#if WASM_ENABLE_FAST_INTERP != 0 + /* change F32/F64 into I32/I64 */ + if (opcode == WASM_OP_F32_LOAD) { + skip_label(); + emit_label(WASM_OP_I32_LOAD); + } + else if (opcode == WASM_OP_F64_LOAD) { + skip_label(); + emit_label(WASM_OP_I64_LOAD); + } + else if (opcode == WASM_OP_F32_STORE) { + skip_label(); + emit_label(WASM_OP_I32_STORE); + } + else if (opcode == WASM_OP_F64_STORE) { + skip_label(); + emit_label(WASM_OP_I64_STORE); + } +#endif CHECK_MEMORY(); read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, mem_offset); /* offset */ #if WASM_ENABLE_FAST_INTERP != 0 - emit_byte(loader_ctx, opcode); emit_const(mem_offset); #endif switch (opcode) @@ -4616,7 +4695,7 @@ handle_next_reachable_block: } } - func->max_stack_cell_num = loader_ctx->max_dynamic_offset - + func->max_stack_cell_num = loader_ctx->preserved_local_offset - loader_ctx->start_dynamic_offset + 1; #else func->max_stack_cell_num = loader_ctx->max_stack_cell_num; diff --git a/core/iwasm/interpreter/wasm_opcode.h b/core/iwasm/interpreter/wasm_opcode.h index e99db696a..51c3e2245 100644 --- a/core/iwasm/interpreter/wasm_opcode.h +++ b/core/iwasm/interpreter/wasm_opcode.h @@ -262,8 +262,8 @@ typedef enum WASMOpcode { */ #define WASM_INSTRUCTION_NUM 256 -#define DEFINE_GOTO_TABLE(_name) \ -static const void *_name[WASM_INSTRUCTION_NUM] = { \ +#define DEFINE_GOTO_TABLE(type, _name) \ +static type _name[WASM_INSTRUCTION_NUM] = { \ HANDLE_OPCODE (WASM_OP_UNREACHABLE), /* 0x00 */ \ HANDLE_OPCODE (WASM_OP_NOP), /* 0x01 */ \ HANDLE_OPCODE (WASM_OP_BLOCK), /* 0x02 */ \ diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index cfd607f5b..e69730da7 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1108,7 +1108,8 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) { #if WASM_ENABLE_MEMORY_GROW != 0 WASMMemoryInstance *memory = module->default_memory, *new_memory; - uint32 old_page_count = memory->cur_page_count, total_size_old; + uint32 old_page_count = memory->cur_page_count; + uint32 total_size_old = memory->end_addr - (uint8*)memory; uint32 total_page_count = inc_page_count + memory->cur_page_count; uint64 total_size = offsetof(WASMMemoryInstance, base_addr) + memory->num_bytes_per_page * (uint64)total_page_count + @@ -1135,14 +1136,14 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) wasm_set_exception(module, "fail to enlarge memory."); return false; } - total_size_old = memory->end_addr - (uint8*)memory; bh_memcpy_s((uint8*)new_memory, (uint32)total_size, (uint8*)memory, total_size_old); - memset((uint8*)new_memory + total_size_old, - 0, (uint32)total_size - total_size_old); wasm_runtime_free(memory); } + memset((uint8*)new_memory + total_size_old, + 0, (uint32)total_size - total_size_old); + new_memory->cur_page_count = total_page_count; new_memory->memory_data = new_memory->base_addr; new_memory->global_data = new_memory->memory_data + @@ -1165,3 +1166,42 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) #endif /* end of WASM_ENABLE_MEMORY_GROW */ } + +bool +wasm_call_indirect(WASMExecEnv *exec_env, + uint32_t element_indices, + uint32_t argc, uint32_t argv[]) +{ + WASMModuleInstance *module_inst = NULL; + WASMTableInstance *table_inst = NULL; + uint32_t function_indices = 0; + WASMFunctionInstance *function_inst = NULL; + + module_inst = + (WASMModuleInstance*)exec_env->module_inst; + bh_assert(module_inst); + + table_inst = module_inst->default_table; + if (!table_inst) { + wasm_set_exception(module_inst, "there is no table"); + goto got_exception; + } + + if (element_indices >= table_inst->cur_size) { + wasm_set_exception(module_inst, "undefined element"); + goto got_exception; + } + + function_indices = ((uint32_t*)table_inst->base_addr)[element_indices]; + if (function_indices == 0xFFFFFFFF) { + wasm_set_exception(module_inst, "uninitialized element"); + goto got_exception; + } + + function_inst = module_inst->functions + function_indices; + wasm_interp_call_wasm(module_inst, exec_env, function_inst, argc, argv); + return !wasm_get_exception(module_inst) ? true : false; + +got_exception: + return false; +} diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index bf172b284..03a5e4d42 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -280,6 +280,11 @@ wasm_get_native_addr_range(WASMModuleInstance *module_inst, bool wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count); +bool +wasm_call_indirect(WASMExecEnv *exec_env, + uint32_t element_indices, + uint32_t argc, uint32_t argv[]); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index 66f1badf8..b83d606f9 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -388,7 +388,7 @@ sprintf_out(int c, struct str_context *ctx) static int printf_out(int c, struct str_context *ctx) { - bh_printf("%c", c); + os_printf("%c", c); ctx->count++; return c; } @@ -470,13 +470,13 @@ snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size, static int puts_wrapper(wasm_exec_env_t exec_env, const char *str) { - return bh_printf("%s\n", str); + return os_printf("%s\n", str); } static int putchar_wrapper(wasm_exec_env_t exec_env, int c) { - bh_printf("%c", c); + os_printf("%c", c); return 1; } @@ -908,7 +908,7 @@ static void llvm_stackrestore_wrapper(wasm_exec_env_t exec_env, uint32 llvm_stack) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - bh_printf("_llvm_stackrestore called!\n"); + os_printf("_llvm_stackrestore called!\n"); wasm_runtime_set_llvm_stack(module_inst, llvm_stack); } @@ -916,7 +916,7 @@ static uint32 llvm_stacksave_wrapper(wasm_exec_env_t exec_env) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - bh_printf("_llvm_stacksave called!\n"); + os_printf("_llvm_stacksave called!\n"); return wasm_runtime_get_llvm_stack(module_inst); } @@ -996,11 +996,11 @@ __cxa_throw_wrapper(wasm_exec_env_t exec_env, static void print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32) { - bh_printf("%d\n", i32); + os_printf("%d\n", i32); } #define REG_NATIVE_FUNC(func_name, signature) \ - { #func_name, func_name##_wrapper, signature } + { #func_name, func_name##_wrapper, signature, NULL } static NativeSymbol native_symbols_libc_builtin[] = { REG_NATIVE_FUNC(printf, "($*)i"), @@ -1028,7 +1028,7 @@ static NativeSymbol native_symbols_libc_builtin[] = { REG_NATIVE_FUNC(exit, "(i)"), REG_NATIVE_FUNC(strtol, "($*i)i"), REG_NATIVE_FUNC(strtoul, "($*i)i"), - REG_NATIVE_FUNC(memchr, "(*ii)"), + REG_NATIVE_FUNC(memchr, "(*ii)i"), REG_NATIVE_FUNC(strncasecmp, "($$i)"), REG_NATIVE_FUNC(strspn, "($$)i"), REG_NATIVE_FUNC(strcspn, "($$)i"), diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 915788e97..a0f1d4322 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -982,7 +982,7 @@ wasi_sched_yield(wasm_exec_env_t exec_env) } #define REG_NATIVE_FUNC(func_name, signature) \ - { #func_name, wasi_##func_name, signature } + { #func_name, wasi_##func_name, signature, NULL } static NativeSymbol native_symbols_libc_wasi[] = { REG_NATIVE_FUNC(args_get, "(**)i"), 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 ca85b09e1..bcad83617 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 @@ -47,6 +47,7 @@ #include "str.h" #include "bh_common.h" +#include "bh_assert.h" #if 0 /* TODO: -std=gnu99 causes compile error, comment them first */ // struct iovec must have the same layout as __wasi_iovec_t. @@ -1907,6 +1908,21 @@ __wasi_errno_t wasmtime_ssp_path_open( close(nfd); return error; } + + { + struct stat sb; + + if (fstat(nfd, &sb) < 0) { + close(nfd); + return convert_errno(errno); + } + + if (S_ISDIR(sb.st_mode)) + rights_base |= RIGHTS_DIRECTORY_BASE; + else if (S_ISREG(sb.st_mode)) + rights_base |= RIGHTS_REGULAR_FILE_BASE; + } + return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base, rights_inheriting & max_inheriting, fd); } @@ -2272,8 +2288,14 @@ __wasi_errno_t wasmtime_ssp_path_filestat_set_times( __wasi_timestamp_t st_mtim, __wasi_fstflags_t fstflags ) { - if ((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW | - __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0) + if (((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW | + __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0) + /* ATIM & ATIM_NOW can't be set at the same time */ + || ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0 + && (fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) + /* MTIM & MTIM_NOW can't be set at the same time */ + || ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0 + && (fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0)) return __WASI_EINVAL; struct path_access pa; diff --git a/core/shared/include/bh_log.h b/core/shared/include/bh_log.h deleted file mode 100644 index 6b806e464..000000000 --- a/core/shared/include/bh_log.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ -/** - * @file bh_log.h - * @date Tue Nov 8 18:19:10 2011 - * - * @brief This log system supports wrapping multiple outputs into one - * log message. This is useful for outputting variable-length logs - * without additional memory overhead (the buffer for concatenating - * the message), e.g. exception stack trace, which cannot be printed - * by a single log calling without the help of an additional buffer. - * Avoiding additional memory buffer is useful for resource-constraint - * systems. It can minimize the impact of log system on applications - * and logs can be printed even when no enough memory is available. - * Functions with prefix "_" are private functions. Only macros that - * are not start with "_" are exposed and can be used. - */ - -#ifndef _BH_LOG_H -#define _BH_LOG_H - -#include - -#include "bh_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The following functions are the primitive operations of this log - * system. A normal usage of the log system is to call bh_log_printf - * or bh_log_vprintf one or multiple times and then call bh_log_commit - * to wrap (mark) the previous outputs into one log message. The - * bh_log and macros LOG_ERROR etc. can be used to output log messages - * that can be wrapped into one log calling. - */ -int _bh_log_init(void); -void _bh_log_set_verbose_level(int level); -void _bh_log_printf(const char *fmt, ...); -void _bh_log_vprintf(const char *fmt, va_list ap); -void _bh_log_commit(void); - -#if WASM_ENABLE_LOG != 0 -# define bh_log_init() _bh_log_init () -# define bh_log_set_verbose_level(l) _bh_log_set_verbose_level (l) -# define bh_log_printf(...) _bh_log_printf (__VA_ARGS__) -# define bh_log_vprintf(...) _bh_log_vprintf (__VA_ARGS__) -# define bh_log_commit() _bh_log_commit () -#else /* WASM_ENABLE_LOG != 0 */ -# define bh_log_init() 0 -# define bh_log_set_verbose_level(l) (void)0 -# define bh_log_printf(...) (void)0 -# define bh_log_vprintf(...) (void)0 -# define bh_log_commit() (void)0 -#endif /* WASM_ENABLE_LOG != 0 */ - -void _bh_log(const char *tag, const char *file, int line, const char *fmt, ...); - -/* Always print fatal message */ -# define LOG_FATAL(...) _bh_log ("V0.", NULL, 0, __VA_ARGS__) - -#if WASM_ENABLE_LOG != 0 -# define LOG_ERROR(...) _bh_log ("V1.", NULL, 0, __VA_ARGS__) -# define LOG_WARNING(...) _bh_log ("V2.", NULL, 0, __VA_ARGS__) -# define LOG_INFO_RELEASE(...) _bh_log ("V3.", NULL, 0, __VA_ARGS__) -# define LOG_INFO_APP_DEV(...) _bh_log ("V4.", NULL, 0, __VA_ARGS__) -# define LOG_VERBOSE(...) _bh_log ("V5.", NULL, 0, __VA_ARGS__) -# if BEIHAI_ENABLE_MEMORY_PROFILING != 0 -# define LOG_PROFILE(...) _bh_log ("V3.", NULL, 0, __VA_ARGS__) -# else -# define LOG_PROFILE(...) (void)0 -#endif -# if BEIHAI_ENABLE_QUEUE_PROFILING != 0 -# define LOG_QUEUE_PROFILE(...) _bh_log ("V3.", NULL, 0, __VA_ARGS__) -# else -# define LOG_QUEUE_PROFILE(...) (void)0 -#endif -# if BEIHAI_ENABLE_GC_STAT_PROFILING != 0 -# define LOG_GC_STAT_PROFILE(...) _bh_log ("V3.", NULL, 0, __VA_ARGS__) -# else -# define LOG_GC_STAT_PROFILE(...) (void)0 -#endif -#else /* WASM_ENABLE_LOG != 0 */ -# define LOG_ERROR(...) (void)0 -# define LOG_WARNING(...) (void)0 -# define LOG_INFO_APP_DEV(...) (void)0 -# define LOG_INFO_RELEASE(...) (void)0 -# define LOG_VERBOSE(...) (void)0 -# define LOG_PROFILE(...) (void)0 -# define LOG_QUEUE_PROFILE(...) (void)0 -# define LOG_GC_STAT_PROFILE(...) (void)0 -#endif /* WASM_ENABLE_LOG != 0 */ - -#define LOG_PROFILE_INSTANCE_HEAP_CREATED(heap) \ - LOG_PROFILE ("PROF.INSTANCE.HEAP_CREATED: HEAP=%08X", heap) -#define LOG_PROFILE_INSTANCE_THREAD_STARTED(heap) \ - LOG_PROFILE ("PROF.INSTANCE.THREAD_STARTED: HEAP=%08X", heap) -#define LOG_PROFILE_HEAP_ALLOC(heap, size) \ - LOG_PROFILE ("PROF.HEAP.ALLOC: HEAP=%08X SIZE=%d", heap, size) -#define LOG_PROFILE_HEAP_FREE(heap, size) \ - LOG_PROFILE ("PROF.HEAP.FREE: HEAP=%08X SIZE=%d", heap, size) -#define LOG_PROFILE_HEAP_NEW(heap, size) \ - LOG_PROFILE ("PROF.HEAP.NEW: HEAP=%08X SIZE=%d", heap, size) -#define LOG_PROFILE_HEAP_GC(heap, size) \ - LOG_PROFILE ("PROF.HEAP.GC: HEAP=%08X SIZE=%d", heap, size) -#define LOG_PROFILE_STACK_PUSH(used) \ - LOG_PROFILE ("PROF.STACK.PUSH: USED=%d", used) -#define LOG_PROFILE_STACK_POP() \ - LOG_PROFILE ("PROF.STACK.POP") - -/* Please add your component ahead of LOG_COM_MAX */ -enum { - LOG_COM_APP_MANAGER = 0, - LOG_COM_GC, - LOG_COM_HMC, - LOG_COM_UTILS, - LOG_COM_VERIFIER_JEFF, - LOG_COM_VMCORE_JEFF, - LOG_COM_MAX -}; - -#if defined(BH_DEBUG) -void log_parse_coms(const char *coms); -int bh_log_dcom_is_enabled(int component); - -#define LOG_DEBUG(component, ...) do { \ - if (bh_log_dcom_is_enabled (component)) \ - _bh_log ("V6: ", __FILE__, __LINE__, __VA_ARGS__); \ - } while (0) - -#else /* defined(BH_DEBUG) */ - -#define LOG_DEBUG(component, ...) (void)0 - -#endif /* defined(BH_DEBUG) */ - -#ifdef __cplusplus -} -#endif - -#endif /* _BH_LOG_H */ diff --git a/core/shared/mem-alloc/ems/ems_alloc.c b/core/shared/mem-alloc/ems/ems_alloc.c index 3bd2e9ae7..45d6b585a 100644 --- a/core/shared/mem-alloc/ems/ems_alloc.c +++ b/core/shared/mem-alloc/ems/ems_alloc.c @@ -6,21 +6,25 @@ #include "ems_gc_internal.h" -static int hmu_is_in_heap(gc_heap_t* heap, hmu_t* hmu) +static int +hmu_is_in_heap(gc_heap_t* heap, hmu_t* hmu) { - return heap && hmu && (gc_uint8*) hmu >= heap->base_addr - && (gc_uint8*) hmu < heap->base_addr + heap->current_size; + return heap && hmu + && (gc_uint8*) hmu >= heap->base_addr + && (gc_uint8*) hmu < heap->base_addr + heap->current_size; } -/* Remove a node from the tree it belongs to*/ - -/* @p can not be NULL*/ -/* @p can not be the ROOT node*/ - -/* Node @p will be removed from the tree and left,right,parent pointers of node @p will be*/ -/* set to be NULL. Other fields will not be touched.*/ -/* The tree will be re-organized so that the order conditions are still satisified.*/ -BH_STATIC void remove_tree_node(hmu_tree_node_t *p) +/** + * Remove a node from the tree it belongs to + * + * @param p the node to remove, can not be NULL, can not be the ROOT node + * the node will be removed from the tree, and the left, right and + * parent pointers of the node @p will be set to be NULL. Other fields + * won't be touched. The tree will be re-organized so that the order + * conditions are still satisified. + */ +static void +remove_tree_node(hmu_tree_node_t *p) { hmu_tree_node_t *q = NULL, **slot = NULL; @@ -35,11 +39,14 @@ BH_STATIC void remove_tree_node(hmu_tree_node_t *p) slot = &p->parent->left; } - /* algorithms used to remove node p*/ - /* case 1: if p has no left child, replace p with its right child*/ - /* case 2: if p has no right child, replace p with its left child*/ - /* case 3: otherwise, find p's predecessor, remove it from the tree and replace p with it.*/ - /* use predecessor can keep the left <= root < right condition.*/ + /** + * algorithms used to remove node p + * case 1: if p has no left child, replace p with its right child + * case 2: if p has no right child, replace p with its left child + * case 3: otherwise, find p's predecessor, remove it from the tree + * and replace p with it. + * use predecessor can keep the left <= root < right condition. + */ if (!p->left) { /* move right child up*/ @@ -64,7 +71,8 @@ BH_STATIC void remove_tree_node(hmu_tree_node_t *p) q = p->left; while (q->right) q = q->right; - remove_tree_node(q); /* remove from the tree*/ + /* remove from the tree*/ + remove_tree_node(q); *slot = q; q->parent = p->parent; @@ -78,71 +86,73 @@ BH_STATIC void remove_tree_node(hmu_tree_node_t *p) p->left = p->right = p->parent = NULL; } -static void unlink_hmu(gc_heap_t *heap, hmu_t *hmu) +static void +unlink_hmu(gc_heap_t *heap, hmu_t *hmu) { gc_size_t size; bh_assert(gci_is_heap_valid(heap)); - bh_assert( - hmu && (gc_uint8*) hmu >= heap->base_addr - && (gc_uint8*) hmu < heap->base_addr + heap->current_size); + bh_assert(hmu && (gc_uint8*) hmu >= heap->base_addr + && (gc_uint8*) hmu < heap->base_addr + heap->current_size); bh_assert(hmu_get_ut(hmu) == HMU_FC); size = hmu_get_size(hmu); if (HMU_IS_FC_NORMAL(size)) { uint32 node_idx = size >> 3; - hmu_normal_node_t* node = heap->kfc_normal_list[node_idx].next; - hmu_normal_node_t** p = &(heap->kfc_normal_list[node_idx].next); + hmu_normal_node_t *node_prev = &heap->kfc_normal_list[node_idx]; + hmu_normal_node_t *node = + get_hmu_normal_node_next(&heap->kfc_normal_list[node_idx]); while (node) { if ((hmu_t*) node == hmu) { - *p = node->next; + set_hmu_normal_node_next(node_prev, get_hmu_normal_node_next(node)); break; } - p = &(node->next); - node = node->next; + node_prev = node; + node = get_hmu_normal_node_next(node); } if (!node) { - bh_printf("[GC_ERROR]couldn't find the node in the normal list"); + os_printf("[GC_ERROR]couldn't find the node in the normal list\n"); } - } else { + } + else { remove_tree_node((hmu_tree_node_t *) hmu); } } -static void hmu_set_free_size(hmu_t *hmu) +static void +hmu_set_free_size(hmu_t *hmu) { gc_size_t size; bh_assert(hmu && hmu_get_ut(hmu) == HMU_FC); size = hmu_get_size(hmu); - *((uint32*) ((char*) hmu + size) - 1) = size; + *((uint32*)((char*) hmu + size) - 1) = size; } -/* Add free chunk back to KFC*/ - -/* @heap should not be NULL and it should be a valid heap*/ -/* @hmu should not be NULL and it should be a HMU of length @size inside @heap*/ -/* @hmu should be aligned to 8*/ -/* @size should be positive and multiple of 8*/ - -/* @hmu with size @size will be added into KFC as a new FC.*/ -void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size) +/** + * Add free chunk back to KFC + * + * @param heap should not be NULL and it should be a valid heap + * @param hmu should not be NULL and it should be a HMU of length @size inside @heap + * hmu should be 8-bytes aligned + * @param size should be positive and multiple of 8 + * hmu with size @size will be added into KFC as a new FC. + */ +void +gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size) { hmu_normal_node_t *np = NULL; hmu_tree_node_t *root = NULL, *tp = NULL, *node = NULL; uint32 node_idx; bh_assert(gci_is_heap_valid(heap)); - bh_assert( - hmu && (gc_uint8*) hmu >= heap->base_addr - && (gc_uint8*) hmu < heap->base_addr + heap->current_size); + bh_assert(hmu && (gc_uint8*) hmu >= heap->base_addr + && (gc_uint8*) hmu < heap->base_addr + heap->current_size); bh_assert(((gc_uint32)(uintptr_t)hmu_to_obj(hmu) & 7) == 0); - bh_assert( - size > 0 - && ((gc_uint8*) hmu) + size - <= heap->base_addr + heap->current_size); + bh_assert(size > 0 + && ((gc_uint8*) hmu) + size <= heap->base_addr + heap->current_size); bh_assert(!(size & 7)); hmu_set_ut(hmu, HMU_FC); @@ -153,8 +163,9 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size) np = (hmu_normal_node_t*) hmu; node_idx = size >> 3; - np->next = heap->kfc_normal_list[node_idx].next; - heap->kfc_normal_list[node_idx].next = np; + set_hmu_normal_node_next(np, get_hmu_normal_node_next + (&heap->kfc_normal_list[node_idx])); + set_hmu_normal_node_next(&heap->kfc_normal_list[node_idx], np); return; } @@ -175,8 +186,8 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size) break; } tp = tp->right; - } else /* tp->size >= size*/ - { + } + else { /* tp->size >= size*/ if (!tp->left) { tp->left = node; node->parent = tp; @@ -187,17 +198,19 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size) } } -/* Find a proper hmu for required memory size*/ - -/* @heap should not be NULL and it should be a valid heap*/ -/* @size should cover the header and it should be 8 bytes aligned*/ - -/* GC will not be performed here.*/ -/* Heap extension will not be performed here.*/ - -/* A proper HMU will be returned. This HMU can include the header and given size. The returned HMU will be aligned to 8 bytes.*/ -/* NULL will be returned if there are no proper HMU.*/ -BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size) +/** + * Find a proper hmu for required memory size + * + * @param heap should not be NULL and should be a valid heap + * @param size should cover the header and should be 8 bytes aligned + * GC will not be performed here. + * Heap extension will not be performed here. + * + * @return hmu allocated if success, which will be aligned to 8 bytes, + * NULL otherwise + */ +static hmu_t * +alloc_hmu(gc_heap_t *heap, gc_size_t size) { hmu_normal_node_t *node = NULL, *p = NULL; uint32 node_idx = 0, init_node_idx = 0; @@ -217,7 +230,7 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size) for (node_idx = init_node_idx; node_idx < HMU_NORMAL_NODE_CNT; node_idx++) { node = heap->kfc_normal_list + node_idx; - if (node->next) + if (get_hmu_normal_node_next(node)) break; node = NULL; } @@ -226,32 +239,32 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size) if (node) { bh_assert(node_idx >= init_node_idx); - p = node->next; - node->next = p->next; + p = get_hmu_normal_node_next(node); + set_hmu_normal_node_next(node, get_hmu_normal_node_next(p)); bh_assert(((gc_int32)(uintptr_t)hmu_to_obj(p) & 7) == 0); if ((gc_size_t)node_idx != (uint32)init_node_idx - && ((gc_size_t)node_idx << 3) >= size + GC_SMALLEST_SIZE) { /* with bigger size*/ + /* with bigger size*/ + && ((gc_size_t)node_idx << 3) >= size + GC_SMALLEST_SIZE) { rest = (hmu_t*) (((char *) p) + size); gci_add_fc(heap, rest, (node_idx << 3) - size); hmu_mark_pinuse(rest); - } else { + } + else { size = node_idx << 3; next = (hmu_t*) ((char*) p + size); if (hmu_is_in_heap(heap, next)) hmu_mark_pinuse(next); } -#if GC_STAT_DATA != 0 heap->total_free_size -= size; if ((heap->current_size - heap->total_free_size) - > heap->highmark_size) + > heap->highmark_size) heap->highmark_size = heap->current_size - - heap->total_free_size; -#endif + - heap->total_free_size; - hmu_set_size((hmu_t* ) p, size); - return (hmu_t*) p; + hmu_set_size((hmu_t* )p, size); + return (hmu_t*)p; } } @@ -284,18 +297,18 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size) rest = (hmu_t*) ((char*) last_tp + size); gci_add_fc(heap, rest, last_tp->size - size); hmu_mark_pinuse(rest); - } else { + } + else { size = last_tp->size; next = (hmu_t*) ((char*) last_tp + size); if (hmu_is_in_heap(heap, next)) hmu_mark_pinuse(next); } -#if GC_STAT_DATA != 0 heap->total_free_size -= size; if ((heap->current_size - heap->total_free_size) > heap->highmark_size) heap->highmark_size = heap->current_size - heap->total_free_size; -#endif + hmu_set_size((hmu_t* ) last_tp, size); return (hmu_t*) last_tp; } @@ -303,194 +316,159 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size) return NULL; } -/* Find a proper HMU for given size*/ - -/* @heap should not be NULL and it should be a valid heap*/ -/* @size should cover the header and it should be 8 bytes aligned*/ - -/* This function will try several ways to satisfy the allocation request.*/ -/* 1. Find a proper on available HMUs.*/ -/* 2. GC will be triggered if 1 failed.*/ -/* 3. Find a proper on available HMUS.*/ -/* 4. Return NULL if 3 failed*/ - -/* A proper HMU will be returned. This HMU can include the header and given size. The returned HMU will be aligned to 8 bytes.*/ -/* NULL will be returned if there are no proper HMU.*/ -BH_STATIC hmu_t* alloc_hmu_ex(gc_heap_t *heap, gc_size_t size) +/** + * Find a proper HMU with given size + * + * @param heap should not be NULL and should be a valid heap + * @param size should cover the header and should be 8 bytes aligned + * + * Note: This function will try several ways to satisfy the allocation request: + * 1. Find a proper on available HMUs. + * 2. GC will be triggered if 1 failed. + * 3. Find a proper on available HMUS. + * 4. Return NULL if 3 failed + * + * @return hmu allocated if success, which will be aligned to 8 bytes, + * NULL otherwise + */ +static hmu_t * +alloc_hmu_ex(gc_heap_t *heap, gc_size_t size) { - hmu_t *ret = NULL; - bh_assert(gci_is_heap_valid(heap)); bh_assert(size > 0 && !(size & 7)); -#ifdef GC_IN_EVERY_ALLOCATION - gci_gc_heap(heap); - ret = alloc_hmu(heap, size); -#else - -# if GC_STAT_DATA != 0 - if (heap->gc_threshold < heap->total_free_size) - ret = alloc_hmu(heap, size); -# else - ret = alloc_hmu(heap, size); -# endif - - if (ret) - return ret; - - /*gci_gc_heap(heap);*//* disable gc claim currently */ - ret = alloc_hmu(heap, size); -#endif - return ret; + return alloc_hmu(heap, size); } -unsigned long g_total_malloc = 0; -unsigned long g_total_free = 0; +static unsigned long g_total_malloc = 0; +static unsigned long g_total_free = 0; -gc_object_t _gc_alloc_vo_i_heap(void *vheap, - gc_size_t size ALLOC_EXTRA_PARAMETERS) +#if BH_ENABLE_GC_VERIFY == 0 +gc_object_t +gc_alloc_vo(void *vheap, gc_size_t size) +#else +gc_object_t +gc_alloc_vo_internal(void *vheap, gc_size_t size, + const char *file, int line) +#endif { gc_heap_t* heap = (gc_heap_t*) vheap; hmu_t *hmu = NULL; gc_object_t ret = (gc_object_t) NULL; - gc_size_t tot_size = 0; + gc_size_t tot_size = 0, tot_size_unaligned; - /* align size*/ - tot_size = GC_ALIGN_8(size + HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE); /* hmu header, prefix, suffix*/ + /* hmu header + prefix + obj + suffix */ + tot_size_unaligned = HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE; + /* aligned size*/ + tot_size = GC_ALIGN_8(tot_size_unaligned); if (tot_size < size) + /* integer overflow */ return NULL; - gct_vm_mutex_lock(&heap->lock); + os_mutex_lock(&heap->lock); hmu = alloc_hmu_ex(heap, tot_size); if (!hmu) - goto FINISH; + goto finish; g_total_malloc += tot_size; hmu_set_ut(hmu, HMU_VO); hmu_unfree_vo(hmu); -#if defined(GC_VERIFY) - hmu_init_prefix_and_suffix(hmu, tot_size, file_name, line_number); +#if BH_ENABLE_GC_VERIFY != 0 + hmu_init_prefix_and_suffix(hmu, tot_size, file, line); #endif ret = hmu_to_obj(hmu); + if (tot_size > tot_size_unaligned) + /* clear buffer appended by GC_ALIGN_8() */ + memset((uint8*)ret + size, 0, tot_size - tot_size_unaligned); #if BH_ENABLE_MEMORY_PROFILING != 0 - bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size); + os_printf("HEAP.ALLOC: heap: %p, size: %u\n", heap, size); #endif -FINISH: - gct_vm_mutex_unlock(&heap->lock); - +finish: + os_mutex_unlock(&heap->lock); return ret; } -gc_object_t _gc_realloc_vo_i_heap(void *vheap, void *ptr, - gc_size_t size ALLOC_EXTRA_PARAMETERS) +#if BH_ENABLE_GC_VERIFY == 0 +gc_object_t +gc_realloc_vo(void *vheap, void *ptr, gc_size_t size) +#else +gc_object_t +gc_realloc_vo_internal(void *vheap, void *ptr, gc_size_t size, + const char *file, int line) +#endif { gc_heap_t* heap = (gc_heap_t*) vheap; hmu_t *hmu = NULL, *hmu_old = NULL; gc_object_t ret = (gc_object_t) NULL, obj_old = (gc_object_t)ptr; - gc_size_t tot_size = 0, size_old = 0; + gc_size_t tot_size, tot_size_unaligned, tot_size_old = 0; + gc_size_t obj_size, obj_size_old; + + /* hmu header + prefix + obj + suffix */ + tot_size_unaligned = HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE; + /* aligned size*/ + tot_size = GC_ALIGN_8(tot_size_unaligned); + if (tot_size < size) + /* integer overflow */ + return NULL; if (obj_old) { hmu_old = obj_to_hmu(obj_old); - size_old = hmu_get_size(hmu_old); - size_old -= HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE; - if (size < size_old) - return NULL; - if (size == size_old) + tot_size_old = hmu_get_size(hmu_old); + if (tot_size <= tot_size_old) + /* current node alreay meets requirement */ return obj_old; } - /* align size*/ - tot_size = GC_ALIGN_8(size + HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE); /* hmu header, prefix, suffix*/ - if (tot_size < size) - return NULL; - - gct_vm_mutex_lock(&heap->lock); + os_mutex_lock(&heap->lock); hmu = alloc_hmu_ex(heap, tot_size); if (!hmu) - goto FINISH; + goto finish; g_total_malloc += tot_size; hmu_set_ut(hmu, HMU_VO); hmu_unfree_vo(hmu); -#if defined(GC_VERIFY) - hmu_init_prefix_and_suffix(hmu, tot_size, file_name, line_number); +#if BH_ENABLE_GC_VERIFY != 0 + hmu_init_prefix_and_suffix(hmu, tot_size, file, line); #endif ret = hmu_to_obj(hmu); #if BH_ENABLE_MEMORY_PROFILING != 0 - bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size); + os_printf("HEAP.ALLOC: heap: %p, size: %u\n", heap, size); #endif -FINISH: - gct_vm_mutex_unlock(&heap->lock); +finish: + os_mutex_unlock(&heap->lock); if (ret) { - memset(ret, 0, size); + obj_size = tot_size - HMU_SIZE - OBJ_PREFIX_SIZE - OBJ_SUFFIX_SIZE; + memset(ret, 0, obj_size); if (obj_old) { - memcpy(ret, obj_old, size_old); - gc_free_h(vheap, obj_old); + obj_size_old = tot_size_old - HMU_SIZE + - OBJ_PREFIX_SIZE - OBJ_SUFFIX_SIZE; + bh_memcpy_s(ret, obj_size, obj_old, obj_size_old); + gc_free_vo(vheap, obj_old); } } return ret; } -/* see ems_gc.h for description*/ -gc_object_t _gc_alloc_jo_i_heap(void *vheap, - gc_size_t size ALLOC_EXTRA_PARAMETERS) -{ - gc_heap_t* heap = (gc_heap_t*) vheap; - gc_object_t ret = (gc_object_t) NULL; - hmu_t *hmu = NULL; - gc_size_t tot_size = 0; - - bh_assert(gci_is_heap_valid(heap)); - - /* align size*/ - tot_size = GC_ALIGN_8(size + HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE); /* hmu header, prefix, suffix*/ - if (tot_size < size) - return NULL; - - hmu = alloc_hmu_ex(heap, tot_size); - if (!hmu) - goto FINISH; - - /* reset all fields*/ - memset((char*) hmu + sizeof(*hmu), 0, tot_size - sizeof(*hmu)); - - /* hmu->header = 0; */ - hmu_set_ut(hmu, HMU_JO); - hmu_unmark_jo(hmu); - -#if defined(GC_VERIFY) - hmu_init_prefix_and_suffix(hmu, tot_size, file_name, line_number); -#endif - ret = hmu_to_obj(hmu); - -#if BH_ENABLE_MEMORY_PROFILING != 0 - bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size); -#endif - - FINISH: - - return ret; -} - -/* Do some checking to see if given pointer is a possible valid heap*/ - -/* Return GC_TRUE if all checking passed*/ -/* Return GC_FALSE otherwise*/ -int gci_is_heap_valid(gc_heap_t *heap) +/** + * Do some checking to see if given pointer is a possible valid heap + * @return GC_TRUE if all checking passed, GC_FALSE otherwise + */ +int +gci_is_heap_valid(gc_heap_t *heap) { if (!heap) return GC_FALSE; @@ -500,7 +478,14 @@ int gci_is_heap_valid(gc_heap_t *heap) return GC_TRUE; } -int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS) +#if BH_ENABLE_GC_VERIFY == 0 +int +gc_free_vo(void *vheap, gc_object_t obj) +#else +int +gc_free_vo_internal(void *vheap, gc_object_t obj, + const char *file, int line) +#endif { gc_heap_t* heap = (gc_heap_t*) vheap; hmu_t *hmu = NULL; @@ -516,11 +501,11 @@ int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS) hmu = obj_to_hmu(obj); - gct_vm_mutex_lock(&heap->lock); + os_mutex_lock(&heap->lock); - if ((gc_uint8 *) hmu >= heap->base_addr - && (gc_uint8 *) hmu < heap->base_addr + heap->current_size) { -#ifdef GC_VERIFY + if ((gc_uint8 *)hmu >= heap->base_addr + && (gc_uint8 *)hmu < heap->base_addr + heap->current_size) { +#if BH_ENABLE_GC_VERIFY != 0 hmu_verify(hmu); #endif ut = hmu_get_ut(hmu); @@ -535,11 +520,9 @@ int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS) g_total_free += size; -#if GC_STAT_DATA != 0 heap->total_free_size += size; -#endif #if BH_ENABLE_MEMORY_PROFILING != 0 - bh_printf("HEAP.FREE, heap: %p, size: %u\n",heap, size); + os_printf("HEAP.FREE, heap: %p, size: %u\n", heap, size); #endif if (!hmu_get_pinuse(hmu)) { @@ -575,54 +558,51 @@ int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS) goto out; } - out: - gct_vm_mutex_unlock(&heap->lock); +out: + os_mutex_unlock(&heap->lock); return ret; } -void gc_dump_heap_stats(gc_heap_t *heap) +void +gc_dump_heap_stats(gc_heap_t *heap) { - bh_printf("heap: %p, heap start: %p\n", heap, heap->base_addr); - bh_printf( - "total malloc: totalfree: %u, current: %u, highmark: %u, gc cnt: %u\n", - heap->total_free_size, heap->current_size, heap->highmark_size, - heap->total_gc_count); - bh_printf("g_total_malloc=%lu, g_total_free=%lu, occupied=%lu\n", - g_total_malloc, g_total_free, g_total_malloc - g_total_free); + os_printf("heap: %p, heap start: %p\n", heap, heap->base_addr); + os_printf("total free: %u, current: %u, highmark: %u\n", + heap->total_free_size, heap->current_size, heap->highmark_size); + os_printf("g_total_malloc=%lu, g_total_free=%lu, occupied=%lu\n", + g_total_malloc, g_total_free, g_total_malloc - g_total_free); } -#ifdef GC_TEST - -void gci_dump(char* buf, gc_heap_t *heap) +void +gci_dump(gc_heap_t *heap) { hmu_t *cur = NULL, *end = NULL; hmu_type_t ut; gc_size_t size; - int i = 0; - int p; - char inuse; - int mark; + int i = 0, p, mark; + char inuse = 'U'; cur = (hmu_t*)heap->base_addr; end = (hmu_t*)((char*)heap->base_addr + heap->current_size); - while(cur < end) - { + while(cur < end) { ut = hmu_get_ut(cur); size = hmu_get_size(cur); p = hmu_get_pinuse(cur); mark = hmu_is_jo_marked (cur); - if(ut == HMU_VO) - inuse = 'V'; - else if(ut == HMU_JO) - inuse = hmu_is_jo_marked(cur) ? 'J' : 'j'; - else if(ut == HMU_FC) - inuse = 'F'; + if (ut == HMU_VO) + inuse = 'V'; + else if (ut == HMU_JO) + inuse = hmu_is_jo_marked(cur) ? 'J' : 'j'; + else if (ut == HMU_FC) + inuse = 'F'; bh_assert(size > 0); - buf += sprintf(buf, "#%d %08x %x %x %d %c %d\n", i, (char*) cur - (char*) heap->base_addr, ut, p, mark, inuse, hmu_obj_size(size)); + os_printf("#%d %08x %x %x %d %c %d\n", + i, (int32)((char*) cur - (char*) heap->base_addr), + ut, p, mark, inuse, (int32)hmu_obj_size(size)); cur = (hmu_t*)((char *)cur + size); i++; @@ -631,4 +611,3 @@ void gci_dump(char* buf, gc_heap_t *heap) bh_assert(cur == end); } -#endif diff --git a/core/shared/mem-alloc/ems/ems_gc.h b/core/shared/mem-alloc/ems/ems_gc.h index cac4a784e..636d3b5e5 100644 --- a/core/shared/mem-alloc/ems/ems_gc.h +++ b/core/shared/mem-alloc/ems/ems_gc.h @@ -21,49 +21,8 @@ extern "C" { #endif -/*Pre-compile configuration can be done here or on Makefiles*/ -/*#define GC_EMBEDDED or GC_STANDALONE*/ -/*#define GC_DEBUG*/ -/*#define GC_TEST // TEST mode is a sub-mode of STANDALONE*/ -/* #define GC_ALLOC_TRACE */ -/* #define GC_STAT */ -#ifndef GC_STAT_DATA -#define GC_STAT_DATA 1 -#endif - #define GC_HEAD_PADDING 4 -/* Standalone GC is used for testing.*/ -#ifndef GC_EMBEDDED -# ifndef GC_STANDALONE -# define GC_STANDALONE -# endif -#endif - -#if defined(GC_EMBEDDED) && defined(GC_STANDALONE) -# error "Can not define GC_EMBEDDED and GC_STANDALONE at the same time" -#endif - -#ifdef BH_TEST -# ifndef GC_TEST -# define GC_TEST -# endif -#endif - -#ifdef BH_DEBUG -/*instrument mode ignore GC_DEBUG feature, for instrument testing gc_alloc_vo_i_heap only has func_name parameter*/ -#if !defined INSTRUMENT_TEST_ENABLED && !defined GC_DEBUG -# define GC_DEBUG -#endif -#endif - -#if defined(GC_EMBEDDED) && defined(GC_TEST) -# error "Can not defined GC_EMBEDDED and GC_TEST at the same time" -#endif - -typedef void *gc_handle_t; -typedef void *gc_object_t; - #define NULL_REF ((gc_object_t)NULL) #define GC_SUCCESS (0) @@ -74,72 +33,23 @@ typedef void *gc_object_t; #define GC_MAX_HEAP_SIZE (256 * BH_KB) -typedef int64 gc_int64; - -typedef unsigned int gc_uint32; -typedef signed int gc_int32; -typedef unsigned short gc_uint16; -typedef signed short gc_int16; -typedef unsigned char gc_uint8; -typedef signed char gc_int8; -typedef gc_uint32 gc_size_t; - -typedef enum { - MMT_SHARED = 0, - MMT_INSTANCE = 1, - MMT_APPMANAGER = MMT_SHARED, - MMT_VERIFIER = MMT_SHARED, - MMT_JHI = MMT_SHARED, - MMT_LOADER = MMT_SHARED, - MMT_APPLET = MMT_INSTANCE, - MMT_INTERPRETER = MMT_INSTANCE -} gc_mm_t; - -#ifdef GC_STAT -#define GC_HEAP_STAT_SIZE (128 / 4) - -typedef struct { - int usage; - int usage_block; - int vo_usage; - int jo_usage; - int free; - int free_block; - int vo_free; - int jo_free; - int usage_sizes[GC_HEAP_STAT_SIZE]; - int free_sizes[GC_HEAP_STAT_SIZE]; -}gc_stat_t; - -extern void gc_heap_stat(void* heap, gc_stat_t* gc_stat); -extern void __gc_print_stat(void *heap, int verbose); - -#define gc_print_stat __gc_print_stat - -#else - -#define gc_print_stat(heap, verbose) - -#endif - -#if GC_STAT_DATA != 0 +typedef void * gc_handle_t; +typedef void * gc_object_t; +typedef int64 gc_int64; +typedef uint32 gc_uint32; +typedef int32 gc_int32; +typedef uint16 gc_uint16; +typedef int16 gc_int16; +typedef uint8 gc_uint8; +typedef int8 gc_int8; +typedef uint32 gc_size_t; typedef enum { GC_STAT_TOTAL = 0, GC_STAT_FREE, GC_STAT_HIGHMARK, - GC_STAT_COUNT, - GC_STAT_TIME, - GC_STAT_MAX_1, - GC_STAT_MAX_2, - GC_STAT_MAX_3, - GC_STAT_MAX } GC_STAT_INDEX; -#endif - -/*////////////// Exported APIs*/ - /** * GC initialization from a buffer * @@ -148,7 +58,8 @@ typedef enum { * * @return gc handle if success, NULL otherwise */ -extern gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size); +gc_handle_t +gc_init_with_pool(char *buf, gc_size_t buf_size); /** * Destroy heap which is initilized from a buffer @@ -158,9 +69,8 @@ extern gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size); * @return GC_SUCCESS if success * GC_ERROR for bad parameters or failed system resource freeing. */ -extern int gc_destroy_with_pool(gc_handle_t handle); - -#if GC_STAT_DATA != 0 +int +gc_destroy_with_pool(gc_handle_t handle); /** * Get Heap Stats @@ -169,166 +79,44 @@ extern int gc_destroy_with_pool(gc_handle_t handle); * @param size [in] the size of stats * @param mmt [in] type of heap, MMT_SHARED or MMT_INSTANCE */ -extern void* gc_heap_stats(void *heap, uint32* stats, int size, gc_mm_t mmt); +void * +gc_heap_stats(void *heap, uint32* stats, int size); -/** - * Set GC threshold factor - * - * @param heap [in] the heap to set - * @param factor [in] the threshold size is free_size * factor / 1000 - * - * @return GC_SUCCESS if success. - */ -extern int gc_set_threshold_factor(void *heap, unsigned int factor); +#if BH_ENABLE_GC_VERIFY == 0 -#endif +gc_object_t +gc_alloc_vo(void *heap, gc_size_t size); -/*////// Allocate heap object*/ +gc_object_t +gc_realloc_vo(void *heap, void *ptr, gc_size_t size); -/* There are two versions of allocate functions. The functions with _i suffix should be only used*/ -/* internally. Functions without _i suffix are just wrappers with the corresponded functions with*/ -/* _i suffix. Allocation operation code position are record under DEBUG model for debugging.*/ -#ifdef GC_DEBUG -# define ALLOC_EXTRA_PARAMETERS ,const char*file_name,int line_number -# define ALLOC_EXTRA_ARGUMENTS , __FILE__, __LINE__ -# define ALLOC_PASSDOWN_EXTRA_ARGUMENTS , file_name, line_number -# define gc_alloc_vo_h(heap, size) gc_alloc_vo_i_heap(heap, size, __FILE__, __LINE__) -# define gc_realloc_vo_h(heap, ptr, size) gc_realloc_vo_i_heap(heap, ptr, size, __FILE__, __LINE__) -# define gc_free_h(heap, obj) gc_free_i_heap(heap, obj, __FILE__, __LINE__) -#else -# define ALLOC_EXTRA_PARAMETERS -# define ALLOC_EXTRA_ARGUMENTS -# define ALLOC_PASSDOWN_EXTRA_ARGUMENTS -# define gc_alloc_vo_h gc_alloc_vo_i_heap -# define gc_realloc_vo_h gc_realloc_vo_i_heap -# define gc_free_h gc_free_i_heap -#endif +int +gc_free_vo(void *heap, gc_object_t obj); -/** - * Invoke a GC - * - * @param heap - * - * @return GC_SUCCESS if success - */ -extern int gci_gc_heap(void *heap); +#else /* else of BH_ENABLE_GC_VERIFY */ -/** - * Allocate VM Object in specific heap. - * - * @param heap heap to allocate. - * @param size bytes to allocate. - * - * @return pointer to VM object allocated - * NULL if failed. - */ -extern gc_object_t _gc_alloc_vo_i_heap(void *heap, - gc_size_t size ALLOC_EXTRA_PARAMETERS); -extern gc_object_t _gc_realloc_vo_i_heap(void *heap, void *ptr, - gc_size_t size ALLOC_EXTRA_PARAMETERS); -extern gc_object_t _gc_alloc_jo_i_heap(void *heap, - gc_size_t size ALLOC_EXTRA_PARAMETERS); -#ifdef INSTRUMENT_TEST_ENABLED -extern gc_object_t gc_alloc_vo_i_heap_instr(void *heap, gc_size_t size, const char* func_name ); -extern gc_object_t gc_realloc_vo_i_heap_instr(void *heap, void *ptr, gc_size_t size, - const char* func_name ); -extern gc_object_t gc_alloc_jo_i_heap_instr(void *heap, gc_size_t size, const char* func_name); -# define gc_alloc_vo_i_heap(heap, size) gc_alloc_vo_i_heap_instr(heap, size, __FUNCTION__) -# define gc_realloc_vo_i_heap(heap, ptr, size) gc_realloc_vo_i_heap_instr(heap, ptr, size, __FUNCTION__) -# define gc_alloc_jo_i_heap(heap, size) gc_alloc_jo_i_heap_instr(heap, size, __FUNCTION__) -#else -# define gc_alloc_vo_i_heap _gc_alloc_vo_i_heap -# define gc_realloc_vo_i_heap _gc_realloc_vo_i_heap -# define gc_alloc_jo_i_heap _gc_alloc_jo_i_heap -#endif +gc_object_t +gc_alloc_vo_internal(void *heap, gc_size_t size, + const char *file, int line); -/** - * Allocate Java object in specific heap. - * - * @param heap heap to allocate. - * @param size bytes to allocate. - * - * @return pointer to Java object allocated - * NULL if failed. - */ -extern gc_object_t _gc_alloc_jo_i_heap(void *heap, - gc_size_t size ALLOC_EXTRA_PARAMETERS); +gc_object_t +gc_realloc_vo_internal(void *heap, void *ptr, gc_size_t size, + const char *file, int line); -/** - * Free VM object - * - * @param heap heap to free. - * @param obj pointer to object need free. - * - * @return GC_SUCCESS if success - */ -extern int gc_free_i_heap(void *heap, gc_object_t obj ALLOC_EXTRA_PARAMETERS); +int +gc_free_vo_internal(void *heap, gc_object_t obj, + const char *file, int line); -/** - * Add ref to rootset of gc for current instance. - * - * @param obj pointer to real load of a valid Java object managed by gc for current instance. - * - * @return GC_SUCCESS if success. - * GC_ERROR for invalid parameters. - */ -extern int gc_add_root(void* heap, gc_object_t obj); +#define gc_alloc_vo(heap, size) \ + gc_alloc_vo_internal(heap, size, __FILE__, __LINE__) -/*////////////// Imported APIs which should be implemented in other components*/ +#define gc_realloc_vo(heap, ptr, size) \ + gc_realloc_vo_internal(heap, ptr, size, __FILE__, __LINE__) -/*////// Java object layout related APIs*/ +#define gc_free_vo(heap, obj) \ + gc_free_vo_internal(heap, obj, __FILE__, __LINE__) -/** - * Get Java object size from corresponding VM module - * - * @param obj pointer to the real load of a Java object. - * - * @return size of java object. - */ -extern gc_size_t vm_get_java_object_size(gc_object_t obj); - -/** - * Get reference list of this object - * - * @param obj [in] pointer to java object. - * @param is_compact_mode [in] indicate the java object mode. GC_TRUE or GC_FALSE. - * @param ref_num [out] the size of ref_list. - * @param ref_list [out] if is_compact_mode is GC_FALSE, this parameter will be set to a list of offset. - * @param ref_start_offset [out] If is_compact_mode is GC_TRUE, this parameter will be set to the start offset of the references in this object. - * - * @return GC_SUCCESS if success. - * GC_ERROR when error occurs. - */ -extern int vm_get_java_object_ref_list(gc_object_t obj, int *is_compact_mode, - gc_size_t *ref_num, gc_uint16 **ref_list, gc_uint32 *ref_start_offset); - -/** - * Get gc handle for current instance - * - * - * @return instance heap handle. - */ -extern gc_handle_t app_manager_get_cur_applet_heap(void); - -/** - * Begin current instance heap rootset enumeration - * - * - * @return GC_SUCCESS if success. - * GC_ERROR when error occurs. - */ -extern int vm_begin_rootset_enumeration(void *heap); - -#ifdef _INSTRUMENT_TEST_ENABLED -extern int vm_begin_rootset_enumeration_instr(void *heap, const char*func_name); -#define vm_begin_rootset_enumeration(heap) vm_begin_rootset_enumeration_instr(heap, __FUNCTION__) -#else -#define vm_begin_rootset_enumeration _vm_begin_rootset_enumeration -#endif /* INSTUMENT_TEST_ENABLED*/ - -#ifndef offsetof -#define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) -#endif +#endif /* end of BH_ENABLE_GC_VERIFY */ #ifdef __cplusplus } diff --git a/core/shared/mem-alloc/ems/ems_gc_internal.h b/core/shared/mem-alloc/ems/ems_gc_internal.h index ac153fa10..717149b9f 100644 --- a/core/shared/mem-alloc/ems/ems_gc_internal.h +++ b/core/shared/mem-alloc/ems/ems_gc_internal.h @@ -11,58 +11,55 @@ extern "C" { #endif #include "bh_platform.h" -#include "bh_thread.h" -#include "bh_assert.h" #include "ems_gc.h" -/* basic block managed by EMS gc is the so-called HMU (heap memory unit)*/ -typedef enum _hmu_type_enum -{ +/* HMU (heap memory unit) basic block type */ +typedef enum hmu_type_enum { HMU_TYPE_MIN = 0, HMU_TYPE_MAX = 3, HMU_JO = 3, HMU_VO = 2, HMU_FC = 1, HMU_FM = 0 -}hmu_type_t; +} hmu_type_t; -typedef struct _hmu_struct -{ +typedef struct hmu_struct { gc_uint32 header; -}hmu_t; +} hmu_t; -#if defined(GC_VERIFY) +#if BH_ENABLE_GC_VERIFY != 0 #define GC_OBJECT_PREFIX_PADDING_CNT 3 #define GC_OBJECT_SUFFIX_PADDING_CNT 4 #define GC_OBJECT_PADDING_VALUE (0x12345678) -typedef struct _gc_object_prefix -{ +typedef struct gc_object_prefix { const char *file_name; gc_int32 line_no; gc_int32 size; gc_uint32 padding[GC_OBJECT_PREFIX_PADDING_CNT]; -}gc_object_prefix_t; +} gc_object_prefix_t; + +typedef struct gc_object_suffix { + gc_uint32 padding[GC_OBJECT_SUFFIX_PADDING_CNT]; +} gc_object_suffix_t; #define OBJ_PREFIX_SIZE (sizeof(gc_object_prefix_t)) - -typedef struct _gc_object_suffix -{ - gc_uint32 padding[GC_OBJECT_SUFFIX_PADDING_CNT]; -}gc_object_suffix_t; - #define OBJ_SUFFIX_SIZE (sizeof(gc_object_suffix_t)) -extern void hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size, const char *file_name, int line_no); -extern void hmu_verify(hmu_t *hmu); +void +hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size, + const char *file_name, int line_no); + +void +hmu_verify(hmu_t *hmu); #define SKIP_OBJ_PREFIX(p) ((void*)((gc_uint8*)(p) + OBJ_PREFIX_SIZE)) #define SKIP_OBJ_SUFFIX(p) ((void*)((gc_uint8*)(p) + OBJ_SUFFIX_SIZE)) #define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE) -#else +#else /* else of BH_ENABLE_GC_VERIFY */ #define OBJ_PREFIX_SIZE 0 #define OBJ_SUFFIX_SIZE 0 @@ -72,7 +69,7 @@ extern void hmu_verify(hmu_t *hmu); #define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE) -#endif /* GC_DEBUG*/ +#endif /* end of BH_ENABLE_GC_VERIFY */ #define hmu_obj_size(s) ((s)-OBJ_EXTRA_SIZE) @@ -81,7 +78,9 @@ extern void hmu_verify(hmu_t *hmu); #define GC_SMALLEST_SIZE GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + 8) #define GC_GET_REAL_SIZE(x) GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + (((x) > 8) ? (x): 8)) -/*////// functions for bit operation*/ +/** + * hmu bit operation + */ #define SETBIT(v, offset) (v) |= (1 << (offset)) #define GETBIT(v, offset) ((v) & (1 << (offset)) ? 1 : 0) @@ -94,7 +93,9 @@ extern void hmu_verify(hmu_t *hmu); #define CLRBITS(v, offset, size) (v) &= ~(((1 << size) - 1) << offset) #define GETBITS(v, offset, size) (((v) & ((uint32)(((1 << size) - 1) << offset))) >> offset) -/*////// gc object layout definition*/ +/** + * gc object layout definition + */ #define HMU_SIZE (sizeof(hmu_t)) @@ -123,6 +124,12 @@ extern void hmu_verify(hmu_t *hmu); #define hmu_unmark_jo(hmu) CLRBIT ((hmu)->header, HMU_JO_MB_OFFSET) #define hmu_is_jo_marked(hmu) GETBIT ((hmu)->header, HMU_JO_MB_OFFSET) +/** + * The hmu size is divisible by 8, its lowest 3 bits are 0, so we only + * store its higher bits of bit [29..3], and bit [2..0] are not stored. + * After that, the maximal heap size can be enlarged from (1<<27) = 128MB + * to (1<<27) * 8 = 1GB. + */ #define HMU_SIZE_SIZE 27 #define HMU_SIZE_OFFSET 0 @@ -131,10 +138,12 @@ extern void hmu_verify(hmu_t *hmu); #define hmu_is_vo_freed(hmu) GETBIT ((hmu)->header, HMU_VO_FB_OFFSET) #define hmu_unfree_vo(hmu) CLRBIT ((hmu)->header, HMU_VO_FB_OFFSET) -#define hmu_get_size(hmu) GETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE) -#define hmu_set_size(hmu, size) SETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE, size) +#define hmu_get_size(hmu) (GETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE) << 3) +#define hmu_set_size(hmu, size) SETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE, ((size) >> 3)) -/*////// HMU free chunk management*/ +/** + * HMU free chunk management + */ #define HMU_NORMAL_NODE_CNT 32 #define HMU_FC_NORMAL_MAX_SIZE ((HMU_NORMAL_NODE_CNT - 1) << 3) @@ -143,24 +152,43 @@ extern void hmu_verify(hmu_t *hmu); #error "Too small GC_MAX_HEAP_SIZE" #endif -typedef struct _hmu_normal_node -{ +typedef struct hmu_normal_node { hmu_t hmu_header; - struct _hmu_normal_node *next; -}hmu_normal_node_t; + gc_int32 next_offset; +} hmu_normal_node_t; -typedef struct _hmu_tree_node +static inline hmu_normal_node_t * +get_hmu_normal_node_next(hmu_normal_node_t *node) { + return node->next_offset + ? (hmu_normal_node_t *)((uint8*)node + node->next_offset) + : NULL; +} + +static inline void +set_hmu_normal_node_next(hmu_normal_node_t *node, hmu_normal_node_t *next) +{ + if (next) { + bh_assert((uint8*)next - (uint8*)node < INT32_MAX); + node->next_offset = (gc_int32)(intptr_t) + ((uint8*)next - (uint8*)node); + } + else { + node->next_offset = 0; + } +} + +typedef struct hmu_tree_node { hmu_t hmu_header; gc_size_t size; - struct _hmu_tree_node *left; - struct _hmu_tree_node *right; - struct _hmu_tree_node *parent; -}hmu_tree_node_t; + struct hmu_tree_node *left; + struct hmu_tree_node *right; + struct hmu_tree_node *parent; +} hmu_tree_node_t; -typedef struct _gc_heap_struct -{ - gc_handle_t heap_id; /* for double checking*/ +typedef struct gc_heap_struct { + /* for double checking*/ + gc_handle_t heap_id; gc_uint8 *base_addr; gc_size_t current_size; @@ -173,95 +201,32 @@ typedef struct _gc_heap_struct /* order in kfc_tree is: size[left] <= size[cur] < size[right]*/ hmu_tree_node_t kfc_tree_root; - /* for rootset enumeration of private heap*/ - void *root_set; - - /* whether the fast mode of marking process that requires - additional memory fails. When the fast mode fails, the - marking process can still be done in the slow mode, which - doesn't need additional memory (by walking through all - blocks and marking sucessors of marked nodes until no new - node is marked). TODO: slow mode is not implemented. */ - unsigned is_fast_marking_failed : 1; - -#if GC_STAT_DATA != 0 - gc_size_t highmark_size; gc_size_t init_size; - gc_size_t total_gc_count; + gc_size_t highmark_size; gc_size_t total_free_size; - gc_size_t gc_threshold; - gc_size_t gc_threshold_factor; - gc_int64 total_gc_time; -#endif -}gc_heap_t; +} gc_heap_t; -/*////// MISC internal used APIs*/ +/** + * MISC internal used APIs + */ -extern void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size); -extern int gci_is_heap_valid(gc_heap_t *heap); +void +gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size); -#ifdef GC_DEBUG -extern void gci_verify_heap(gc_heap_t *heap); -extern void gci_dump(char* buf, gc_heap_t *heap); -#endif +int +gci_is_heap_valid(gc_heap_t *heap); -#if GC_STAT_DATA != 0 +/** + * Verify heap integrity + */ +void +gci_verify_heap(gc_heap_t *heap); -/* the default GC threshold size is free_size * GC_DEFAULT_THRESHOLD_FACTOR / 1000 */ -#define GC_DEFAULT_THRESHOLD_FACTOR 400 - -static inline void gc_update_threshold(gc_heap_t *heap) -{ - heap->gc_threshold = heap->total_free_size * heap->gc_threshold_factor / 1000; -} -#endif - -/*////// MISC data structures*/ - -#define MARK_NODE_OBJ_CNT 256 - -/* mark node is used for gc marker*/ -typedef struct _mark_node_struct -{ - /* number of to-expand objects can be saved in this node*/ - gc_size_t cnt; - - /* the first unused index*/ - int idx; - - /* next node on the node list*/ - struct _mark_node_struct *next; - - /* the actual to-expand objects list*/ - gc_object_t set[MARK_NODE_OBJ_CNT]; -}mark_node_t; - -/*////// Imported APIs wrappers under TEST mode*/ - -#ifdef GC_TEST -extern int (*gct_vm_get_java_object_ref_list)( - gc_object_t obj, - int *is_compact_mode, /* can be set to GC_TRUE, or GC_FALSE */ - gc_size_t *ref_num, - gc_uint16 **ref_list, - gc_uint32 *ref_start_offset); -extern int (*gct_vm_mutex_init)(korp_mutex *mutex); -extern int (*gct_vm_mutex_destroy)(korp_mutex *mutex); -extern int (*gct_vm_mutex_lock)(korp_mutex *mutex); -extern int (*gct_vm_mutex_unlock)(korp_mutex *mutex); -extern gc_handle_t (*gct_vm_get_gc_handle_for_current_instance)(void); -extern int (*gct_vm_begin_rootset_enumeration)(void* heap); -extern int (*gct_vm_gc_finished)(void); -#else -#define gct_vm_get_java_object_ref_list bh_get_java_object_ref_list -#define gct_vm_mutex_init vm_mutex_init -#define gct_vm_mutex_destroy vm_mutex_destroy -#define gct_vm_mutex_lock vm_mutex_lock -#define gct_vm_mutex_unlock vm_mutex_unlock -#define gct_vm_get_gc_handle_for_current_instance app_manager_get_cur_applet_heap -#define gct_vm_begin_rootset_enumeration vm_begin_rootset_enumeration -#define gct_vm_gc_finished jeff_runtime_gc_finished -#endif +/** + * Dump heap nodes + */ +void +gci_dump(gc_heap_t *heap); #ifdef __cplusplus } diff --git a/core/shared/mem-alloc/ems/ems_hmu.c b/core/shared/mem-alloc/ems/ems_hmu.c index 0a6d1abc3..555989b5b 100644 --- a/core/shared/mem-alloc/ems/ems_hmu.c +++ b/core/shared/mem-alloc/ems/ems_hmu.c @@ -5,13 +5,19 @@ #include "ems_gc_internal.h" -#if defined(GC_VERIFY) -/* Set default value to prefix and suffix*/ +#if BH_ENABLE_GC_VERIFY != 0 -/* @hmu should not be NULL and it should have been correctly initilized (except for prefix and suffix part)*/ -/* @tot_size is offered here because hmu_get_size can not be used till now. @tot_size should not be smaller than OBJ_EXTRA_SIZE.*/ -/* For VO, @tot_size should be equal to object total size.*/ -void hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size, const char *file_name, int line_no) +/** + * Set default value to prefix and suffix + * @param hmu should not be NULL and should have been correctly initilized + * (except prefix and suffix part) + * @param tot_size is offered here because hmu_get_size can not be used till now. + * tot_size should not be smaller than OBJ_EXTRA_SIZE. + * For VO, tot_size should be equal to object total size. + */ +void +hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size, + const char *file_name, int line_no) { gc_object_prefix_t *prefix = NULL; gc_object_suffix_t *suffix = NULL; @@ -28,17 +34,18 @@ void hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size, const char *file prefix->file_name = file_name; prefix->line_no = line_no; prefix->size = tot_size; - for(i = 0;i < GC_OBJECT_PREFIX_PADDING_CNT;i++) - { + + for(i = 0;i < GC_OBJECT_PREFIX_PADDING_CNT;i++) { prefix->padding[i] = GC_OBJECT_PADDING_VALUE; } - for(i = 0;i < GC_OBJECT_SUFFIX_PADDING_CNT;i++) - { + + for(i = 0;i < GC_OBJECT_SUFFIX_PADDING_CNT;i++) { suffix->padding[i] = GC_OBJECT_PADDING_VALUE; } } -void hmu_verify(hmu_t *hmu) +void +hmu_verify(hmu_t *hmu) { gc_object_prefix_t *prefix = NULL; gc_object_suffix_t *suffix = NULL; @@ -83,5 +90,6 @@ void hmu_verify(hmu_t *hmu) bh_assert(is_padding_ok); } } -#endif + +#endif /* end of BH_ENABLE_GC_VERIFY */ diff --git a/core/shared/mem-alloc/ems/ems_kfc.c b/core/shared/mem-alloc/ems/ems_kfc.c index 5ea662aec..d0ec2548a 100644 --- a/core/shared/mem-alloc/ems/ems_kfc.c +++ b/core/shared/mem-alloc/ems/ems_kfc.c @@ -5,37 +5,8 @@ #include "ems_gc_internal.h" - -#define HEAP_INC_FACTOR 1 - -/* Check if current platform is compatible with current GC design*/ - -/* Return GC_ERROR if not;*/ -/* Return GC_SUCCESS otherwise.*/ -int gci_check_platform() -{ -#define CHECK(x, y) do { \ - if((x) != (y)) { \ - bh_printf("Platform checking failed on LINE %d at FILE %s.",\ - __LINE__, __FILE__); \ - return GC_ERROR; \ - } \ -} while(0) - - CHECK(8, sizeof(gc_int64)); - CHECK(4, sizeof(gc_uint32)); - CHECK(4, sizeof(gc_int32)); - CHECK(2, sizeof(gc_uint16)); - CHECK(2, sizeof(gc_int16)); - CHECK(1, sizeof(gc_int8)); - CHECK(1, sizeof(gc_uint8)); - CHECK(4, sizeof(gc_size_t)); - /*CHECK(4, sizeof(void *));*/ - - return GC_SUCCESS; -} - -gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size) +gc_handle_t +gc_init_with_pool(char *buf, gc_size_t buf_size) { char *buf_end = buf + buf_size; char *buf_aligned = (char*) (((uintptr_t) buf + 7) & (uintptr_t)~7); @@ -46,14 +17,8 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size) hmu_tree_node_t *root = NULL, *q = NULL; int i = 0, ret; - /* check system compatibility*/ - if (gci_check_platform() == GC_ERROR) { - bh_printf("Check platform compatibility failed"); - return NULL; - } - if (buf_size < 1024) { - bh_printf("[GC_ERROR]heap_init_size(%d) < 1024", buf_size); + os_printf("[GC_ERROR]heap_init_size(%d) < 1024\n", buf_size); return NULL; } @@ -63,30 +28,20 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size) memset(heap, 0, sizeof *heap); memset(base_addr, 0, heap_max_size); - ret = gct_vm_mutex_init(&heap->lock); + ret = os_mutex_init(&heap->lock); if (ret != BHT_OK) { - bh_printf("[GC_ERROR]failed to init lock "); + os_printf("[GC_ERROR]failed to init lock\n"); return NULL; } -#ifdef BH_FOOTPRINT - bh_printf("\nINIT HEAP 0x%08x %d\n", base_addr, heap_max_size); -#endif - /* init all data structures*/ heap->max_size = heap_max_size; heap->current_size = heap_max_size; - heap->base_addr = (gc_uint8*) base_addr; - heap->heap_id = (gc_handle_t) heap; + heap->base_addr = (gc_uint8*)base_addr; + heap->heap_id = (gc_handle_t)heap; -#if GC_STAT_DATA != 0 heap->total_free_size = heap->current_size; heap->highmark_size = 0; - heap->total_gc_count = 0; - heap->total_gc_time = 0; - heap->gc_threshold_factor = GC_DEFAULT_THRESHOLD_FACTOR; - gc_update_threshold(heap); -#endif for (i = 0; i < HMU_NORMAL_NODE_CNT; i++) { /* make normal node look like a FC*/ @@ -112,30 +67,29 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size) q->parent = root; q->size = heap->current_size; - bh_assert( - root->size <= HMU_FC_NORMAL_MAX_SIZE - && HMU_FC_NORMAL_MAX_SIZE < q->size); /*@NOTIFY*/ + bh_assert(root->size <= HMU_FC_NORMAL_MAX_SIZE + && HMU_FC_NORMAL_MAX_SIZE < q->size); #if BH_ENABLE_MEMORY_PROFILING != 0 - bh_printf("heap is successfully initialized with max_size=%u.", - heap_max_size); + os_printf("heap is successfully initialized with max_size=%u.\n", + heap_max_size); #endif return heap; } -int gc_destroy_with_pool(gc_handle_t handle) +int +gc_destroy_with_pool(gc_handle_t handle) { gc_heap_t *heap = (gc_heap_t *) handle; - gct_vm_mutex_destroy(&heap->lock); + os_mutex_destroy(&heap->lock); memset(heap->base_addr, 0, heap->max_size); memset(heap, 0, sizeof(gc_heap_t)); return GC_SUCCESS; } -#if defined(GC_VERIFY) -/* Verify heap integrity*/ -/* @heap should not be NULL and it should be a valid heap*/ -void gci_verify_heap(gc_heap_t *heap) +#if BH_ENABLE_GC_VERIFY != 0 +void +gci_verify_heap(gc_heap_t *heap) { hmu_t *cur = NULL, *end = NULL; @@ -151,9 +105,9 @@ void gci_verify_heap(gc_heap_t *heap) } #endif -void* gc_heap_stats(void *heap_arg, uint32* stats, int size, gc_mm_t mmt) +void * +gc_heap_stats(void *heap_arg, uint32* stats, int size) { - (void) mmt; int i; gc_heap_t *heap = (gc_heap_t *) heap_arg; @@ -168,15 +122,10 @@ void* gc_heap_stats(void *heap_arg, uint32* stats, int size, gc_mm_t mmt) case GC_STAT_HIGHMARK: stats[i] = heap->highmark_size; break; - case GC_STAT_COUNT: - stats[i] = heap->total_gc_count; - break; - case GC_STAT_TIME: - stats[i] = (uint32)heap->total_gc_time; - break; default: break; } } return heap; } + diff --git a/core/shared/mem-alloc/mem_alloc.c b/core/shared/mem-alloc/mem_alloc.c index 71ae701b2..183b16f03 100644 --- a/core/shared/mem-alloc/mem_alloc.c +++ b/core/shared/mem-alloc/mem_alloc.c @@ -4,7 +4,6 @@ */ #include "mem_alloc.h" -#include "config.h" #if DEFAULT_MEM_ALLOCATOR == MEM_ALLOCATOR_EMS @@ -23,25 +22,24 @@ void mem_allocator_destroy(mem_allocator_t allocator) void * mem_allocator_malloc(mem_allocator_t allocator, uint32_t size) { - return gc_alloc_vo_h((gc_handle_t) allocator, size); + return gc_alloc_vo((gc_handle_t) allocator, size); } void * mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size) { - return gc_realloc_vo_h((gc_handle_t) allocator, ptr, size); + return gc_realloc_vo((gc_handle_t) allocator, ptr, size); } void mem_allocator_free(mem_allocator_t allocator, void *ptr) { if (ptr) - gc_free_h((gc_handle_t) allocator, ptr); + gc_free_vo((gc_handle_t) allocator, ptr); } #else /* else of DEFAULT_MEM_ALLOCATOR */ #include "tlsf/tlsf.h" -#include "bh_thread.h" typedef struct mem_allocator_tlsf { tlsf_t tlsf; @@ -79,7 +77,7 @@ mem_allocator_create(void *mem, uint32_t size) allocator_tlsf->tlsf = tlsf; - if (vm_mutex_init(&allocator_tlsf->lock)) { + if (os_mutex_init(&allocator_tlsf->lock)) { printf("Create mem allocator failed: tlsf_malloc failed.\n"); tlsf_free(tlsf, allocator_tlsf); tlsf_destroy(tlsf); @@ -95,7 +93,7 @@ mem_allocator_destroy(mem_allocator_t allocator) mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator; tlsf_t tlsf = allocator_tlsf->tlsf; - vm_mutex_destroy(&allocator_tlsf->lock); + os_mutex_destroy(&allocator_tlsf->lock); tlsf_free(tlsf, allocator_tlsf); tlsf_destroy(tlsf); } @@ -110,9 +108,9 @@ mem_allocator_malloc(mem_allocator_t allocator, uint32_t size) /* tlsf doesn't allow to allocate 0 byte */ size = 1; - vm_mutex_lock(&allocator_tlsf->lock); + os_mutex_lock(&allocator_tlsf->lock); ret = tlsf_malloc(allocator_tlsf->tlsf, size); - vm_mutex_unlock(&allocator_tlsf->lock); + os_mutex_unlock(&allocator_tlsf->lock); return ret; } @@ -126,9 +124,9 @@ mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size) /* tlsf doesn't allow to allocate 0 byte */ size = 1; - vm_mutex_lock(&allocator_tlsf->lock); + os_mutex_lock(&allocator_tlsf->lock); ret = tlsf_realloc(allocator_tlsf->tlsf, ptr, size); - vm_mutex_unlock(&allocator_tlsf->lock); + os_mutex_unlock(&allocator_tlsf->lock); return ret; } @@ -137,9 +135,9 @@ mem_allocator_free(mem_allocator_t allocator, void *ptr) { if (ptr) { mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator; - vm_mutex_lock(&allocator_tlsf->lock); + os_mutex_lock(&allocator_tlsf->lock); tlsf_free(allocator_tlsf->tlsf, ptr); - vm_mutex_unlock(&allocator_tlsf->lock); + os_mutex_unlock(&allocator_tlsf->lock); } } diff --git a/core/shared/include/mem_alloc.h b/core/shared/mem-alloc/mem_alloc.h similarity index 96% rename from core/shared/include/mem_alloc.h rename to core/shared/mem-alloc/mem_alloc.h index 9553de1a0..ed07325fa 100644 --- a/core/shared/include/mem_alloc.h +++ b/core/shared/mem-alloc/mem_alloc.h @@ -6,7 +6,7 @@ #ifndef __MEM_ALLOC_H #define __MEM_ALLOC_H -#include +#include "bh_platform.h" #ifdef __cplusplus extern "C" { diff --git a/core/shared/platform/README.md b/core/shared/platform/README.md new file mode 100644 index 000000000..de6f1cc68 --- /dev/null +++ b/core/shared/platform/README.md @@ -0,0 +1,10 @@ +This folder contains the platform abstract layer for multiple platforms. To support a new platform, you can simply create a new folder here and implement all the APIs defined in [`include`](./include) folder. + + + +Refer to [port_wamr.md](../../../doc/port_wamr.md) for how to port WAMR to a target platform. + + + + + diff --git a/core/shared/platform/alios/bh_platform.c b/core/shared/platform/alios/alios_platform.c similarity index 52% rename from core/shared/platform/alios/bh_platform.c rename to core/shared/platform/alios/alios_platform.c index f209bac1b..0af45aeb4 100644 --- a/core/shared/platform/alios/bh_platform.c +++ b/core/shared/platform/alios/alios_platform.c @@ -3,15 +3,25 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_platform.h" -#include "bh_common.h" -#include -#include +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +int +os_thread_sys_init(); + +void +os_thread_sys_destroy(); int bh_platform_init() { - return 0; + return os_thread_sys_init(); +} + +void +bh_platform_destroy() +{ + os_thread_sys_destroy(); } void * @@ -32,24 +42,24 @@ os_free(void *ptr) } void * -bh_mmap(void *hint, unsigned int size, int prot, int flags) +os_mmap(void *hint, unsigned int size, int prot, int flags) { return BH_MALLOC(size); } void -bh_munmap(void *addr, uint32 size) +os_munmap(void *addr, uint32 size) { return BH_FREE(addr); } int -bh_mprotect(void *addr, uint32 size, int prot) +os_mprotect(void *addr, uint32 size, int prot) { return 0; } void -bh_dcache_flush() +os_dcache_flush() { } diff --git a/core/shared/platform/alios/alios_thread.c b/core/shared/platform/alios/alios_thread.c new file mode 100644 index 000000000..236f19efa --- /dev/null +++ b/core/shared/platform/alios/alios_thread.c @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +#define bh_assert(v) do { \ + if (!(v)) { \ + printf("\nASSERTION FAILED: %s, at %s, line %d\n", \ + #v, __FILE__, __LINE__); \ + aos_reboot(); \ + while (1); \ + } \ + } while (0) + +struct os_thread_data; +typedef struct os_thread_wait_node { + aos_sem_t sem; + os_thread_wait_list next; +} os_thread_wait_node; + +typedef struct os_thread_data { + /* Thread body */ + aos_task_t thread; + /* Thread start routine */ + thread_start_routine_t start_routine; + /* Thread start routine argument */ + void *arg; + /* Thread local root */ + void *tlr; + /* Wait node of current thread */ + os_thread_wait_node wait_node; + /* Lock for waiting list */ + aos_mutex_t wait_list_lock; + /* Waiting list of other threads who are joining this thread */ + os_thread_wait_list thread_wait_list; +} os_thread_data; + +static bool is_thread_sys_inited = false; + +/* Thread data of supervisor thread */ +static os_thread_data supervisor_thread_data; + +/* Thread data key */ +static aos_task_key_t thread_data_key; + +/* Thread name index */ +static int thread_name_index; + +int +os_thread_sys_init() +{ + if (is_thread_sys_inited) + return BHT_OK; + + if (aos_task_key_create(&thread_data_key) != 0) + return BHT_ERROR; + + /* Initialize supervisor thread data */ + memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data)); + + if (aos_sem_new(&supervisor_thread_data.wait_node.sem, 1) != 0) { + aos_task_key_delete(thread_data_key); + return BHT_ERROR; + } + + if (aos_task_setspecific(thread_data_key, &supervisor_thread_data)) { + aos_sem_free(&supervisor_thread_data.wait_node.sem); + aos_task_key_delete(thread_data_key); + return BHT_ERROR; + } + + is_thread_sys_inited = true; + return BHT_OK; +} + +void +os_thread_sys_destroy() +{ + if (is_thread_sys_inited) { + aos_task_key_delete(thread_data_key); + aos_sem_free(&supervisor_thread_data.wait_node.sem); + is_thread_sys_inited = false; + } +} + +static os_thread_data * +thread_data_current() +{ + return aos_task_getspecific(thread_data_key); +} + +static void +os_thread_cleanup(void) +{ + os_thread_data *thread_data = thread_data_current(); + os_thread_wait_list thread_wait_list; + aos_mutex_t *wait_list_lock; + aos_sem_t *wait_node_sem; + + bh_assert(thread_data != NULL); + wait_list_lock = &thread_data->wait_list_lock; + thread_wait_list = thread_data->thread_wait_list; + wait_node_sem = &thread_data->wait_node.sem; + + /* Free thread data firstly */ + BH_FREE(thread_data); + + aos_mutex_lock(wait_list_lock, AOS_WAIT_FOREVER); + if (thread_wait_list) { + /* Signal each joining thread */ + os_thread_wait_list head = thread_wait_list; + while (head) { + os_thread_wait_list next = head->next; + aos_sem_signal(&head->sem); + head = next; + } + } + aos_mutex_unlock(wait_list_lock); + + /* Free sem and lock */ + aos_sem_free(wait_node_sem); + aos_mutex_free(wait_list_lock); +} + +static void +os_thread_wrapper(void *arg) +{ + os_thread_data *thread_data = arg; + + /* Set thread custom data */ + if (!aos_task_setspecific(thread_data_key, thread_data)) + thread_data->start_routine(thread_data->arg); + + os_thread_cleanup(); +} + +int +os_thread_create(korp_tid *p_tid, thread_start_routine_t start, + void *arg, unsigned int stack_size) +{ + return os_thread_create_with_prio(p_tid, start, arg, stack_size, + BH_THREAD_DEFAULT_PRIORITY); +} + +int +os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, + void *arg, unsigned int stack_size, int prio) +{ + os_thread_data *thread_data; + char thread_name[32]; + + if (!p_tid || !stack_size) + return BHT_ERROR; + + /* Create and initialize thread data */ + if (!(thread_data = BH_MALLOC(sizeof(os_thread_data)))) + return BHT_ERROR; + + memset(thread_data, 0, sizeof(os_thread_data)); + + thread_data->start_routine = start; + thread_data->arg = arg; + + if (aos_sem_new(&thread_data->wait_node.sem, 1) != 0) + goto fail1; + + if (aos_mutex_new(&thread_data->wait_list_lock)) + goto fail2; + + snprintf(thread_name, sizeof(thread_name), "%s%d", + "wasm-thread-", ++thread_name_index); + + /* Create the thread */ + if (aos_task_new_ext((aos_task_t*)thread_data, thread_name, + os_thread_wrapper, thread_data, + stack_size, prio)) + goto fail3; + + aos_msleep(10); + *p_tid = (korp_tid)thread_data; + return BHT_OK; + +fail3: + aos_mutex_free(&thread_data->wait_list_lock); +fail2: + aos_sem_free(&thread_data->wait_node.sem); +fail1: + BH_FREE(thread_data); + return BHT_ERROR; +} + +korp_tid +os_self_thread() +{ + return (korp_tid)aos_task_getspecific(thread_data_key); +} + +int +os_thread_join (korp_tid thread, void **value_ptr) +{ + (void)value_ptr; + os_thread_data *thread_data, *curr_thread_data; + + /* Get thread data of current thread */ + curr_thread_data = thread_data_current(); + curr_thread_data->wait_node.next = NULL; + + /* Get thread data */ + thread_data = (os_thread_data*)thread; + + aos_mutex_lock(&thread_data->wait_list_lock, AOS_WAIT_FOREVER); + if (!thread_data->thread_wait_list) + thread_data->thread_wait_list = &curr_thread_data->wait_node; + else { + /* Add to end of waiting list */ + os_thread_wait_node *p = thread_data->thread_wait_list; + while (p->next) + p = p->next; + p->next = &curr_thread_data->wait_node; + } + aos_mutex_unlock(&thread_data->wait_list_lock); + + /* Wait the sem */ + aos_sem_wait(&curr_thread_data->wait_node.sem, AOS_WAIT_FOREVER); + + return BHT_OK; +} + +int +os_mutex_init(korp_mutex *mutex) +{ + return aos_mutex_new(mutex) == 0 ? BHT_OK : BHT_ERROR; +} + +int +os_mutex_destroy(korp_mutex *mutex) +{ + aos_mutex_free(mutex); + return BHT_OK; +} + +void +os_mutex_lock(korp_mutex *mutex) +{ + aos_mutex_lock(mutex, AOS_WAIT_FOREVER); +} + +void +os_mutex_unlock(korp_mutex *mutex) +{ + aos_mutex_unlock(mutex); +} + +int +os_cond_init(korp_cond *cond) +{ + if (aos_mutex_new(&cond->wait_list_lock) != 0) + return BHT_ERROR; + + cond->thread_wait_list = NULL; + return BHT_OK; +} + +int +os_cond_destroy(korp_cond *cond) +{ + aos_mutex_free(&cond->wait_list_lock); + return BHT_OK; +} + +static int +os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, + bool timed, int mills) +{ + os_thread_wait_node *node = &thread_data_current()->wait_node; + + node->next = NULL; + + aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER); + if (!cond->thread_wait_list) + cond->thread_wait_list = node; + else { + /* Add to end of wait list */ + os_thread_wait_node *p = cond->thread_wait_list; + while (p->next) + p = p->next; + p->next = node; + } + aos_mutex_unlock(&cond->wait_list_lock); + + /* Unlock mutex, wait sem and lock mutex again */ + aos_mutex_unlock(mutex); + aos_sem_wait(&node->sem, timed ? mills : AOS_WAIT_FOREVER); + aos_mutex_lock(mutex, AOS_WAIT_FOREVER); + + /* Remove wait node from wait list */ + aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER); + if (cond->thread_wait_list == node) + cond->thread_wait_list = node->next; + else { + /* Remove from the wait list */ + os_thread_wait_node *p = cond->thread_wait_list; + while (p->next != node) + p = p->next; + p->next = node->next; + } + aos_mutex_unlock(&cond->wait_list_lock); + + return BHT_OK; +} + +int +os_cond_wait(korp_cond *cond, korp_mutex *mutex) +{ + return os_cond_wait_internal(cond, mutex, false, 0); +} + +int +os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds) +{ + if (useconds == BHT_WAIT_FOREVER) + return os_cond_wait_internal(cond, mutex, false, 0); + else + return os_cond_wait_internal(cond, mutex, true, useconds / 1000); +} + +int +os_cond_signal(korp_cond *cond) +{ + /* Signal the head wait node of wait list */ + aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER); + if (cond->thread_wait_list) + aos_sem_signal(&cond->thread_wait_list->sem); + aos_mutex_unlock(&cond->wait_list_lock); + + return BHT_OK; +} + diff --git a/core/shared/platform/alios/alios_time.c b/core/shared/platform/alios/alios_time.c new file mode 100644 index 000000000..f79304979 --- /dev/null +++ b/core/shared/platform/alios/alios_time.c @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +uint64 +os_time_get_boot_microsecond() +{ + return (uint64)aos_now_ms() * 1000; +} + diff --git a/core/shared/platform/alios/bh_assert.c b/core/shared/platform/alios/bh_assert.c deleted file mode 100644 index 60f3b2deb..000000000 --- a/core/shared/platform/alios/bh_assert.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_assert.h" -#include -#include -#include - -#ifdef BH_TEST -#include -#endif - -#ifdef BH_TEST -/* for exception throwing */ -jmp_buf bh_test_jb; -#endif - -void bh_assert_internal(int v, const char *file_name, int line_number, const char *expr_string) -{ - if(v) return; - - if(!file_name) file_name = "NULL FILENAME"; - if(!expr_string) expr_string = "NULL EXPR_STRING"; - - printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string, file_name, line_number); - -#ifdef BH_TEST - longjmp(bh_test_jb, 1); -#endif - - aos_reboot(); -} - -void bh_debug_internal(const char *file_name, int line_number, const char *fmt, ...) -{ -#ifndef JEFF_TEST_VERIFIER - va_list args; - - va_start(args, fmt); - bh_assert(file_name); - - printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number); - vprintf(fmt, args); - - va_end(args); - printf("\n"); -#endif -} - diff --git a/core/shared/platform/alios/bh_math.c b/core/shared/platform/alios/bh_math.c deleted file mode 100644 index 913d52167..000000000 --- a/core/shared/platform/alios/bh_math.c +++ /dev/null @@ -1,861 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2004 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "bh_platform.h" - -#define __FDLIBM_STDC__ - -typedef uint32_t u_int32_t; -typedef uint64_t u_int64_t; - -typedef union u32double_tag { - int *pint; - double *pdouble; -} U32DOUBLE; - -static inline int * -pdouble2pint(double *pdouble) -{ - U32DOUBLE u; - u.pdouble = pdouble; - return u.pint; -} - -typedef union -{ - double value; - struct - { - u_int32_t lsw; - u_int32_t msw; - } parts; - struct - { - u_int64_t w; - } xparts; -} ieee_double_shape_type_little; - -typedef union -{ - double value; - struct - { - u_int32_t msw; - u_int32_t lsw; - } parts; - struct - { - u_int64_t w; - } xparts; -} ieee_double_shape_type_big; - -typedef union { - double d; - struct { - unsigned int manl :32; - unsigned int manh :20; - unsigned int exp :11; - unsigned int sign :1; - } bits; -} IEEEd2bits_L; - -typedef union { - double d; - struct { - unsigned int sign :1; - unsigned int exp :11; - unsigned int manh :20; - unsigned int manl :32; - } bits; -} IEEEd2bits_B; - -typedef union { - float f; - struct { - unsigned int man :23; - unsigned int exp :8; - unsigned int sign :1; - } bits; -} IEEEf2bits_L; - -typedef union { - float f; - struct { - unsigned int sign :1; - unsigned int exp :8; - unsigned int man :23; - } bits; -} IEEEf2bits_B; - -static union { - int a; - char b; -} __ue = { .a = 1 }; - -#define is_little_endian() (__ue.b == 1) - -#define __HIL(x) *(1+pdouble2pint(&x)) -#define __LOL(x) *(pdouble2pint(&x)) -#define __HIB(x) *(int*)&x -#define __LOB(x) *(1+(int*)&x) - -/* Get two 32 bit ints from a double. */ - -#define EXTRACT_WORDS_L(ix0,ix1,d) \ - do { \ - ieee_double_shape_type_little ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ - } while (0) - -/* Set a double from two 32 bit ints. */ - -#define INSERT_WORDS_L(d,ix0,ix1) \ - do { \ - ieee_double_shape_type_little iw_u; \ - iw_u.parts.msw = (ix0); \ - iw_u.parts.lsw = (ix1); \ - (d) = iw_u.value; \ - } while (0) - -/* Get two 32 bit ints from a double. */ - -#define EXTRACT_WORDS_B(ix0,ix1,d) \ - do { \ - ieee_double_shape_type_big ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ - } while (0) - -/* Set a double from two 32 bit ints. */ - -#define INSERT_WORDS_B(d,ix0,ix1) \ - do { \ - ieee_double_shape_type_big iw_u; \ - iw_u.parts.msw = (ix0); \ - iw_u.parts.lsw = (ix1); \ - (d) = iw_u.value; \ - } while (0) - -/* Get the more significant 32 bit int from a double. */ -#define GET_HIGH_WORD_L(i,d) \ - do { \ - ieee_double_shape_type_little gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ - } while (0) - -/* Get the more significant 32 bit int from a double. */ -#define GET_HIGH_WORD_B(i,d) \ - do { \ - ieee_double_shape_type_big gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ - } while (0) - -/* Set the more significant 32 bits of a double from an int. */ -#define SET_HIGH_WORD_L(d,v) \ - do { \ - ieee_double_shape_type_little sh_u; \ - sh_u.value = (d); \ - sh_u.parts.msw = (v); \ - (d) = sh_u.value; \ - } while (0) - -/* Set the more significant 32 bits of a double from an int. */ -#define SET_HIGH_WORD_B(d,v) \ - do { \ - ieee_double_shape_type_big sh_u; \ - sh_u.value = (d); \ - sh_u.parts.msw = (v); \ - (d) = sh_u.value; \ - } while (0) - -/* - * A union which permits us to convert between a float and a 32 bit - * int. - */ -typedef union -{ - float value; - /* FIXME: Assumes 32 bit int. */ - unsigned int word; -} ieee_float_shape_type; - -/* Get a 32 bit int from a float. */ -#define GET_FLOAT_WORD(i,d) \ - do { \ - ieee_float_shape_type gf_u; \ - gf_u.value = (d); \ - (i) = gf_u.word; \ - } while (0) - -/* Set a float from a 32 bit int. */ -#define SET_FLOAT_WORD(d,i) \ - do { \ - ieee_float_shape_type sf_u; \ - sf_u.word = (i); \ - (d) = sf_u.value; \ - } while (0) - -/* Macro wrappers. */ -#define EXTRACT_WORDS(ix0,ix1,d) do { \ - if (is_little_endian()) \ - EXTRACT_WORDS_L(ix0,ix1,d); \ - else \ - EXTRACT_WORDS_B(ix0,ix1,d); \ -} while (0) - -#define INSERT_WORDS(d,ix0,ix1) do { \ - if (is_little_endian()) \ - INSERT_WORDS_L(d,ix0,ix1); \ - else \ - INSERT_WORDS_B(d,ix0,ix1); \ -} while (0) - -#define GET_HIGH_WORD(i,d) \ - do { \ - if (is_little_endian()) \ - GET_HIGH_WORD_L(i,d); \ - else \ - GET_HIGH_WORD_B(i,d); \ - } while (0) - -#define SET_HIGH_WORD(d,v) \ - do { \ - if (is_little_endian()) \ - SET_HIGH_WORD_L(d,v); \ - else \ - SET_HIGH_WORD_B(d,v); \ - } while (0) - -#define __HI(x) (is_little_endian() ? __HIL(x) : __HIB(x)) - -#define __LO(x) (is_little_endian() ? __LOL(x) : __LOB(x)) - -/* - * Attempt to get strict C99 semantics for assignment with non-C99 compilers. - */ -#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 -#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) -#else -#define STRICT_ASSIGN(type, lval, rval) do { \ - volatile type __lval; \ - \ - if (sizeof(type) >= sizeof(long double)) \ - (lval) = (rval); \ - else { \ - __lval = (rval); \ - (lval) = __lval; \ - } \ -} while (0) -#endif - -#ifdef __FDLIBM_STDC__ -static const double huge = 1.0e300; -#else -static double huge = 1.0e300; -#endif - -#ifdef __STDC__ -static const double -#else -static double -#endif -tiny = 1.0e-300; - -#ifdef __STDC__ -static const double -#else -static double -#endif -one= 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ - -#ifdef __STDC__ -static const double -#else -static double -#endif -TWO52[2]={ - 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ - -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ -}; - -static double freebsd_sqrt(double x); -static double freebsd_floor(double x); -static double freebsd_ceil(double x); -static double freebsd_fabs(double x); -static double freebsd_rint(double x); -static int freebsd_isnan(double x); - -static double freebsd_sqrt(double x) /* wrapper sqrt */ -{ - double z; - int32_t sign = (int)0x80000000; - int32_t ix0,s0,q,m,t,i; - u_int32_t r,t1,s1,ix1,q1; - - EXTRACT_WORDS(ix0,ix1,x); - - /* take care of Inf and NaN */ - if((ix0&0x7ff00000)==0x7ff00000) { - return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf - sqrt(-inf)=sNaN */ - } - /* take care of zero */ - if(ix0<=0) { - if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ - else if(ix0<0) - return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ - } - /* normalize x */ - m = (ix0>>20); - if(m==0) { /* subnormal x */ - while(ix0==0) { - m -= 21; - ix0 |= (ix1>>11); ix1 <<= 21; - } - for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; - m -= i-1; - ix0 |= (ix1>>(32-i)); - ix1 <<= i; - } - m -= 1023; /* unbias exponent */ - ix0 = (ix0&0x000fffff)|0x00100000; - if(m&1){ /* odd m, double x to make it even */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - } - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ - r = 0x00200000; /* r = moving bit from right to left */ - - while(r!=0) { - t = s0+r; - if(t<=ix0) { - s0 = t+r; - ix0 -= t; - q += r; - } - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - r>>=1; - } - - r = sign; - while(r!=0) { - t1 = s1+r; - t = s0; - if((t>31); - ix1 += ix1; - r>>=1; - } - - /* use floating add to find out rounding direction */ - if((ix0|ix1)!=0) { - z = one-tiny; /* trigger inexact flag */ - if (z>=one) { - z = one+tiny; - if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;} - else if (z>one) { - if (q1==(u_int32_t)0xfffffffe) q+=1; - q1+=2; - } else - q1 += (q1&1); - } - } - ix0 = (q>>1)+0x3fe00000; - ix1 = q1>>1; - if ((q&1)==1) ix1 |= sign; - ix0 += (m <<20); - - INSERT_WORDS(z,ix0,ix1); - - return z; -} - -static double freebsd_floor(double x) -{ - int32_t i0,i1,j0; - u_int32_t i,j; - - EXTRACT_WORDS(i0,i1,x); - - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { /* raise inexact if x != 0 */ - if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0>=0) {i0=i1=0;} - else if(((i0&0x7fffffff)|i1)!=0) - { i0=0xbff00000;i1=0;} - } - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - if(huge+x>0.0) { /* raise inexact flag */ - if(i0<0) i0 += (0x00100000)>>j0; - i0 &= (~i); i1=0; - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((u_int32_t)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - if(huge+x>0.0) { /* raise inexact flag */ - if(i0<0) { - if(j0==20) i0+=1; - else { - j = i1+(1<<(52-j0)); - if(j>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { /* raise inexact if x != 0 */ - if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0<0) {i0=0x80000000;i1=0;} - else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} - } - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - if(huge+x>0.0) { /* raise inexact flag */ - if(i0>0) i0 += (0x00100000)>>j0; - i0 &= (~i); i1=0; - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((u_int32_t)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - if(huge+x>0.0) { /* raise inexact flag */ - if(i0>0) { - if(j0==20) i0+=1; - else { - j = i1 + (1<<(52-j0)); - if(j>31)&1; - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { - if(((i0&0x7fffffff)|i1)==0) return x; - i1 |= (i0&0x0fffff); - i0 &= 0xfffe0000; - i0 |= ((i1|-i1)>>12)&0x80000; - SET_HIGH_WORD(x,i0); - STRICT_ASSIGN(double,w,TWO52[sx]+x); - t = w-TWO52[sx]; - GET_HIGH_WORD(i0,t); - SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); - return t; - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - i>>=1; - if(((i0&i)|i1)!=0) { - /* - * Some bit is set after the 0.5 bit. To avoid the - * possibility of errors from double rounding in - * w = TWO52[sx]+x, adjust the 0.25 bit to a lower - * guard bit. We do this for all j0<=51. The - * adjustment is trickiest for j0==18 and j0==19 - * since then it spans the word boundary. - */ - if(j0==19) i1 = 0x40000000; else - if(j0==18) i1 = 0x80000000; else - i0 = (i0&(~i))|((0x20000)>>j0); - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((u_int32_t)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - i>>=1; - if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); - } - INSERT_WORDS(x,i0,i1); - STRICT_ASSIGN(double,w,TWO52[sx]+x); - return w-TWO52[sx]; -} - -static int freebsd_isnan(double d) -{ - if (is_little_endian()) { - IEEEd2bits_L u; - u.d = d; - return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0)); - } - else { - IEEEd2bits_B u; - u.d = d; - return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0)); - } -} - -static double freebsd_fabs(double x) -{ - u_int32_t high; - GET_HIGH_WORD(high,x); - SET_HIGH_WORD(x,high&0x7fffffff); - return x; -} - -static const float huge_f = 1.0e30F; - -static const float -TWO23[2]={ - 8.3886080000e+06, /* 0x4b000000 */ - -8.3886080000e+06, /* 0xcb000000 */ -}; - -static float -freebsd_truncf(float x) -{ - int32_t i0,j0; - u_int32_t i; - GET_FLOAT_WORD(i0,x); - j0 = ((i0>>23)&0xff)-0x7f; - if(j0<23) { - if(j0<0) { /* raise inexact if x != 0 */ - if(huge_f+x>0.0F) /* |x|<1, so return 0*sign(x) */ - i0 &= 0x80000000; - } else { - i = (0x007fffff)>>j0; - if((i0&i)==0) return x; /* x is integral */ - if(huge_f+x>0.0F) /* raise inexact flag */ - i0 &= (~i); - } - } else { - if(j0==0x80) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } - SET_FLOAT_WORD(x,i0); - return x; -} - -static float -freebsd_rintf(float x) -{ - int32_t i0,j0,sx; - float w,t; - GET_FLOAT_WORD(i0,x); - sx = (i0>>31)&1; - j0 = ((i0>>23)&0xff)-0x7f; - if(j0<23) { - if(j0<0) { - if((i0&0x7fffffff)==0) return x; - STRICT_ASSIGN(float,w,TWO23[sx]+x); - t = w-TWO23[sx]; - GET_FLOAT_WORD(i0,t); - SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31)); - return t; - } - STRICT_ASSIGN(float,w,TWO23[sx]+x); - return w-TWO23[sx]; - } - if(j0==0x80) return x+x; /* inf or NaN */ - else return x; /* x is integral */ -} - -static float -freebsd_ceilf(float x) -{ - int32_t i0,j0; - u_int32_t i; - - GET_FLOAT_WORD(i0,x); - j0 = ((i0>>23)&0xff)-0x7f; - if(j0<23) { - if(j0<0) { /* raise inexact if x != 0 */ - if(huge_f+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0<0) {i0=0x80000000;} - else if(i0!=0) { i0=0x3f800000;} - } - } else { - i = (0x007fffff)>>j0; - if((i0&i)==0) return x; /* x is integral */ - if(huge_f+x>(float)0.0) { /* raise inexact flag */ - if(i0>0) i0 += (0x00800000)>>j0; - i0 &= (~i); - } - } - } else { - if(j0==0x80) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } - SET_FLOAT_WORD(x,i0); - return x; -} - -static float -freebsd_floorf(float x) -{ - int32_t i0,j0; - u_int32_t i; - GET_FLOAT_WORD(i0,x); - j0 = ((i0>>23)&0xff)-0x7f; - if(j0<23) { - if(j0<0) { /* raise inexact if x != 0 */ - if(huge_f+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0>=0) {i0=0;} - else if((i0&0x7fffffff)!=0) - { i0=0xbf800000;} - } - } else { - i = (0x007fffff)>>j0; - if((i0&i)==0) return x; /* x is integral */ - if(huge_f+x>(float)0.0) { /* raise inexact flag */ - if(i0<0) i0 += (0x00800000)>>j0; - i0 &= (~i); - } - } - } else { - if(j0==0x80) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } - SET_FLOAT_WORD(x,i0); - return x; -} - -static float -freebsd_fminf(float x, float y) -{ - if (is_little_endian()) { - IEEEf2bits_L u[2]; - - u[0].f = x; - u[1].f = y; - - /* Check for NaNs to avoid raising spurious exceptions. */ - if (u[0].bits.exp == 255 && u[0].bits.man != 0) - return (y); - if (u[1].bits.exp == 255 && u[1].bits.man != 0) - return (x); - - /* Handle comparisons of signed zeroes. */ - if (u[0].bits.sign != u[1].bits.sign) - return (u[u[1].bits.sign].f); - } - else { - IEEEf2bits_B u[2]; - - u[0].f = x; - u[1].f = y; - - /* Check for NaNs to avoid raising spurious exceptions. */ - if (u[0].bits.exp == 255 && u[0].bits.man != 0) - return (y); - if (u[1].bits.exp == 255 && u[1].bits.man != 0) - return (x); - - /* Handle comparisons of signed zeroes. */ - if (u[0].bits.sign != u[1].bits.sign) - return (u[u[1].bits.sign].f); - } - - return (x < y ? x : y); -} - -static float -freebsd_fmaxf(float x, float y) -{ - if (is_little_endian()) { - IEEEf2bits_L u[2]; - - u[0].f = x; - u[1].f = y; - - /* Check for NaNs to avoid raising spurious exceptions. */ - if (u[0].bits.exp == 255 && u[0].bits.man != 0) - return (y); - if (u[1].bits.exp == 255 && u[1].bits.man != 0) - return (x); - - /* Handle comparisons of signed zeroes. */ - if (u[0].bits.sign != u[1].bits.sign) - return (u[u[0].bits.sign].f); - } - else { - IEEEf2bits_B u[2]; - - u[0].f = x; - u[1].f = y; - - /* Check for NaNs to avoid raising spurious exceptions. */ - if (u[0].bits.exp == 255 && u[0].bits.man != 0) - return (y); - if (u[1].bits.exp == 255 && u[1].bits.man != 0) - return (x); - - /* Handle comparisons of signed zeroes. */ - if (u[0].bits.sign != u[1].bits.sign) - return (u[u[0].bits.sign].f); - } - - return (x > y ? x : y); -} - -double sqrt(double x) -{ - return freebsd_sqrt(x); -} - -double floor(double x) -{ - return freebsd_floor(x); -} - -double ceil(double x) -{ - return freebsd_ceil(x); -} - -double fmin(double x, double y) -{ - return x < y ? x : y; -} - -double fmax(double x, double y) -{ - return x > y ? x : y; -} - -double rint(double x) -{ - return freebsd_rint(x); -} - -double fabs(double x) -{ - return freebsd_fabs(x); -} - -int isnan(double x) -{ - return freebsd_isnan(x); -} - -double trunc(double x) -{ - return (x > 0) ? freebsd_floor(x) : freebsd_ceil(x); -} - -int signbit(double x) -{ - return ((__HI(x) & 0x80000000) >> 31); -} - -float -truncf(float x) -{ - return freebsd_truncf(x); -} - -float -rintf(float x) -{ - return freebsd_rintf(x); -} - -float -ceilf(float x) -{ - return freebsd_ceilf(x); -} - -float -floorf(float x) -{ - return freebsd_floorf(x); -} - -float -fminf(float x, float y) -{ - return freebsd_fminf(x, y); -} - -float -fmaxf(float x, float y) -{ - return freebsd_fmaxf(x, y); -} - diff --git a/core/shared/platform/alios/bh_platform.h b/core/shared/platform/alios/bh_platform.h deleted file mode 100644 index a3620112a..000000000 --- a/core/shared/platform/alios/bh_platform.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_PLATFORM_H -#define _BH_PLATFORM_H - -#include "bh_config.h" -#include "bh_types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef BH_PLATFORM_ALIOS_THINGS -#define BH_PLATFORM_ALIOS_THINGS -#endif - -#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB) - -/* Default thread priority */ -#define BH_THREAD_DEFAULT_PRIORITY 30 - -#define BH_ROUTINE_MODIFIER - -/* Invalid thread tid */ -#define INVALID_THREAD_ID NULL - -#define BH_WAIT_FOREVER AOS_WAIT_FOREVER - -typedef uint64_t uint64; -typedef int64_t int64; - -typedef aos_task_t korp_thread; -typedef korp_thread *korp_tid; -typedef aos_task_t *aos_tid_t; -typedef aos_mutex_t korp_mutex; -typedef aos_sem_t korp_sem; - -struct bh_thread_wait_node; -typedef struct bh_thread_wait_node *bh_thread_wait_list; -typedef struct korp_cond { - aos_mutex_t wait_list_lock; - bh_thread_wait_list thread_wait_list; -} korp_cond; - -typedef void* (*thread_start_routine_t)(void*); - -void *os_malloc(unsigned size); -void *os_realloc(void *ptr, unsigned size); -void os_free(void *ptr); - -/* Unit test framework is based on C++, where the declaration of - snprintf is different. */ -#ifndef __cplusplus -int snprintf(char *buffer, size_t count, const char *format, ...); -#endif - -#ifndef NULL -#define NULL ((void*)0) -#endif - -/** - * Return the offset of the given field in the given type. - * - * @param Type the type containing the filed - * @param field the field in the type - * - * @return the offset of field in Type - */ -#ifndef offsetof -#define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) -#endif - -#define bh_printf printf - -extern void bh_assert_internal(int v, const char *file_name, int line_number, const char *expr_string); -#define bh_assert(expr) bh_assert_internal((int)(expr), __FILE__, __LINE__, # expr) - -/* math functions */ -double sqrt(double x); -double floor(double x); -double ceil(double x); -double fmin(double x, double y); -double fmax(double x, double y); -double rint(double x); -double fabs(double x); -double trunc(double x); -float floorf(float x); -float ceilf(float x); -float fminf(float x, float y); -float fmaxf(float x, float y); -float rintf(float x); -float truncf(float x); -int signbit(double x); -int isnan(double x); - -int bh_platform_init(); - -/* MMAP mode */ -enum { - MMAP_PROT_NONE = 0, - MMAP_PROT_READ = 1, - MMAP_PROT_WRITE = 2, - MMAP_PROT_EXEC = 4 -}; - -/* MMAP flags */ -enum { - MMAP_MAP_NONE = 0, - /* Put the mapping into 0 to 2 G, supported only on x86_64 */ - MMAP_MAP_32BIT = 1, - /* Don't interpret addr as a hint: place the mapping at exactly - that address. */ - MMAP_MAP_FIXED = 2 -}; - -void *bh_mmap(void *hint, unsigned int size, int prot, int flags); -void bh_munmap(void *addr, uint32 size); -int bh_mprotect(void *addr, uint32 size, int prot); -void bh_dcache_flush(); - -#endif /* end of _BH_PLATFORM_H */ - diff --git a/core/shared/platform/alios/bh_platform_log.c b/core/shared/platform/alios/bh_platform_log.c deleted file mode 100644 index 8c9e114d2..000000000 --- a/core/shared/platform/alios/bh_platform_log.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include - - -void bh_log_emit(const char *fmt, va_list ap) -{ - vprintf(fmt, ap); -} - -int bh_fprintf(FILE *stream, const char *fmt, ...) -{ - (void)stream; - va_list ap; - int ret; - - va_start(ap, fmt); - ret = vprintf(fmt, ap); - va_end(ap); - - return ret; -} - -int bh_fflush(void *stream) -{ - (void)stream; - return 0; -} - diff --git a/core/shared/platform/alios/bh_thread.c b/core/shared/platform/alios/bh_thread.c deleted file mode 100644 index 042e974a2..000000000 --- a/core/shared/platform/alios/bh_thread.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_thread.h" -#include "bh_assert.h" -#include "bh_log.h" -#include -#include - - -struct bh_thread_data; -typedef struct bh_thread_wait_node { - aos_sem_t sem; - bh_thread_wait_list next; -} bh_thread_wait_node; - -typedef struct bh_thread_data { - /* Thread body */ - aos_task_t thread; - /* Thread start routine */ - thread_start_routine_t start_routine; - /* Thread start routine argument */ - void *arg; - /* Thread local root */ - void *tlr; - /* Wait node of current thread */ - bh_thread_wait_node wait_node; - /* Lock for waiting list */ - aos_mutex_t wait_list_lock; - /* Waiting list of other threads who are joining this thread */ - bh_thread_wait_list thread_wait_list; -} bh_thread_data; - -static bool is_thread_sys_inited = false; - -/* Thread data of supervisor thread */ -static bh_thread_data supervisor_thread_data; - -/* Thread data key */ -static aos_task_key_t thread_data_key; - -/* Thread name index */ -static int thread_name_index; - -int -_vm_thread_sys_init() -{ - if (is_thread_sys_inited) - return BHT_OK; - - if (aos_task_key_create(&thread_data_key) != 0) - return BHT_ERROR; - - /* Initialize supervisor thread data */ - memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data)); - - if (aos_sem_new(&supervisor_thread_data.wait_node.sem, 1) != 0) { - aos_task_key_delete(thread_data_key); - return BHT_ERROR; - } - - if (aos_task_setspecific(thread_data_key, &supervisor_thread_data)) { - aos_sem_free(&supervisor_thread_data.wait_node.sem); - aos_task_key_delete(thread_data_key); - return BHT_ERROR; - } - - is_thread_sys_inited = true; - return BHT_OK; -} - -void -vm_thread_sys_destroy() -{ - if (is_thread_sys_inited) { - aos_task_key_delete(thread_data_key); - aos_sem_free(&supervisor_thread_data.wait_node.sem); - is_thread_sys_inited = false; - } -} - -static bh_thread_data * -thread_data_current() -{ - return aos_task_getspecific(thread_data_key); -} - -static void -vm_thread_cleanup(void) -{ - bh_thread_data *thread_data = thread_data_current(); - bh_thread_wait_list thread_wait_list; - aos_mutex_t *wait_list_lock; - aos_sem_t *wait_node_sem; - - bh_assert(thread_data != NULL); - wait_list_lock = &thread_data->wait_list_lock; - thread_wait_list = thread_data->thread_wait_list; - wait_node_sem = &thread_data->wait_node.sem; - - /* Free thread data firstly */ - BH_FREE(thread_data); - - aos_mutex_lock(wait_list_lock, AOS_WAIT_FOREVER); - if (thread_wait_list) { - /* Signal each joining thread */ - bh_thread_wait_list head = thread_wait_list; - while (head) { - bh_thread_wait_list next = head->next; - aos_sem_signal(&head->sem); - head = next; - } - } - aos_mutex_unlock(wait_list_lock); - - /* Free sem and lock */ - aos_sem_free(wait_node_sem); - aos_mutex_free(wait_list_lock); -} - -static void -vm_thread_wrapper(void *arg) -{ - bh_thread_data *thread_data = arg; - - /* Set thread custom data */ - if (!aos_task_setspecific(thread_data_key, thread_data)) - thread_data->start_routine(thread_data->arg); - - vm_thread_cleanup(); -} - -int -_vm_thread_create(korp_tid *p_tid, thread_start_routine_t start, - void *arg, unsigned int stack_size) -{ - return _vm_thread_create_with_prio(p_tid, start, arg, stack_size, - BH_THREAD_DEFAULT_PRIORITY); -} - -int -_vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) -{ - bh_thread_data *thread_data; - char thread_name[32]; - - if (!p_tid || !stack_size) - return BHT_ERROR; - - /* Create and initialize thread data */ - if (!(thread_data = BH_MALLOC(sizeof(bh_thread_data)))) - return BHT_ERROR; - - memset(thread_data, 0, sizeof(bh_thread_data)); - - thread_data->start_routine = start; - thread_data->arg = arg; - - if (aos_sem_new(&thread_data->wait_node.sem, 1) != 0) - goto fail1; - - if (aos_mutex_new(&thread_data->wait_list_lock)) - goto fail2; - - snprintf(thread_name, sizeof(thread_name), "%s%d", - "wasm-thread-", ++thread_name_index); - - /* Create the thread */ - if (aos_task_new_ext((aos_task_t*)thread_data, thread_name, - vm_thread_wrapper, thread_data, - stack_size, prio)) - goto fail3; - - aos_msleep(10); - *p_tid = (korp_tid)thread_data; - return BHT_OK; - -fail3: - aos_mutex_free(&thread_data->wait_list_lock); -fail2: - aos_sem_free(&thread_data->wait_node.sem); -fail1: - BH_FREE(thread_data); - return BHT_ERROR; -} - -korp_tid -_vm_self_thread() -{ - return (korp_tid)aos_task_getspecific(thread_data_key); -} - -void -vm_thread_exit(void * code) -{ - vm_thread_cleanup(); - aos_task_exit((int)(intptr_t)code); -} - -int -_vm_thread_cancel (korp_tid thread) -{ - /* TODO */ - return 0; -} - -int -_vm_thread_join (korp_tid thread, void **value_ptr, int mills) -{ - (void)value_ptr; - bh_thread_data *thread_data, *curr_thread_data; - - /* Get thread data of current thread */ - curr_thread_data = thread_data_current(); - curr_thread_data->wait_node.next = NULL; - - /* Get thread data */ - thread_data = (bh_thread_data*)thread; - - aos_mutex_lock(&thread_data->wait_list_lock, AOS_WAIT_FOREVER); - if (!thread_data->thread_wait_list) - thread_data->thread_wait_list = &curr_thread_data->wait_node; - else { - /* Add to end of waiting list */ - bh_thread_wait_node *p = thread_data->thread_wait_list; - while (p->next) - p = p->next; - p->next = &curr_thread_data->wait_node; - } - aos_mutex_unlock(&thread_data->wait_list_lock); - - /* Wait the sem */ - aos_sem_wait(&curr_thread_data->wait_node.sem, mills); - - return BHT_OK; -} - -int -_vm_thread_detach (korp_tid thread) -{ - (void)thread; - return BHT_OK; -} - -void * -_vm_tls_get(unsigned idx) -{ - (void)idx; - bh_thread_data *thread_data; - - bh_assert (idx == 0); - thread_data = thread_data_current(); - - return thread_data ? thread_data->tlr : NULL; -} - -int -_vm_tls_put(unsigned idx, void * tls) -{ - bh_thread_data *thread_data; - - (void)idx; - bh_assert (idx == 0); - thread_data = thread_data_current(); - bh_assert (thread_data != NULL); - - thread_data->tlr = tls; - return BHT_OK; -} - -int -_vm_mutex_init(korp_mutex *mutex) -{ - return aos_mutex_new(mutex) == 0 ? BHT_OK : BHT_ERROR; -} - -int -_vm_recursive_mutex_init(korp_mutex *mutex) -{ - return aos_mutex_new(mutex) == 0 ? BHT_OK : BHT_ERROR; -} - -int -_vm_mutex_destroy(korp_mutex *mutex) -{ - aos_mutex_free(mutex); - return BHT_OK; -} - -void -vm_mutex_lock(korp_mutex *mutex) -{ - aos_mutex_lock(mutex, AOS_WAIT_FOREVER); -} - -int -vm_mutex_trylock(korp_mutex *mutex) -{ - return aos_mutex_lock(mutex, AOS_NO_WAIT); -} - -void vm_mutex_unlock(korp_mutex *mutex) -{ - aos_mutex_unlock(mutex); -} - -int _vm_sem_init(korp_sem* sem, unsigned int c) -{ - return aos_sem_new(sem, c) == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_destroy(korp_sem *sem) -{ - aos_sem_free(sem); - return BHT_OK; -} - -int _vm_sem_wait(korp_sem *sem) -{ - return aos_sem_wait(sem, AOS_WAIT_FOREVER); -} - -int _vm_sem_reltimedwait(korp_sem *sem, int mills) -{ - return aos_sem_wait(sem, mills); -} - -int _vm_sem_post(korp_sem *sem) -{ - aos_sem_signal(sem); - return BHT_OK; -} - -int -_vm_cond_init(korp_cond *cond) -{ - if (aos_mutex_new(&cond->wait_list_lock) != 0) - return BHT_ERROR; - - cond->thread_wait_list = NULL; - return BHT_OK; -} - -int -_vm_cond_destroy(korp_cond *cond) -{ - aos_mutex_free(&cond->wait_list_lock); - return BHT_OK; -} - -static int -vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, - bool timed, int mills) -{ - bh_thread_wait_node *node = &thread_data_current()->wait_node; - - node->next = NULL; - - aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER); - if (!cond->thread_wait_list) - cond->thread_wait_list = node; - else { - /* Add to end of wait list */ - bh_thread_wait_node *p = cond->thread_wait_list; - while (p->next) - p = p->next; - p->next = node; - } - aos_mutex_unlock(&cond->wait_list_lock); - - /* Unlock mutex, wait sem and lock mutex again */ - aos_mutex_unlock(mutex); - aos_sem_wait(&node->sem, timed ? mills : AOS_WAIT_FOREVER); - aos_mutex_lock(mutex, AOS_WAIT_FOREVER); - - /* Remove wait node from wait list */ - aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER); - if (cond->thread_wait_list == node) - cond->thread_wait_list = node->next; - else { - /* Remove from the wait list */ - bh_thread_wait_node *p = cond->thread_wait_list; - while (p->next != node) - p = p->next; - p->next = node->next; - } - aos_mutex_unlock(&cond->wait_list_lock); - - return BHT_OK; -} - -int -_vm_cond_wait(korp_cond *cond, korp_mutex *mutex) -{ - return vm_cond_wait_internal(cond, mutex, false, 0); -} - -int -_vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) -{ - return vm_cond_wait_internal(cond, mutex, true, mills); -} - -int -_vm_cond_signal(korp_cond *cond) -{ - /* Signal the head wait node of wait list */ - aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER); - if (cond->thread_wait_list) - aos_sem_signal(&cond->thread_wait_list->sem); - aos_mutex_unlock(&cond->wait_list_lock); - - return BHT_OK; -} - -int -_vm_cond_broadcast (korp_cond *cond) -{ - /* Signal each wait node of wait list */ - aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER); - if (cond->thread_wait_list) { - bh_thread_wait_node *p = cond->thread_wait_list; - while (p) { - aos_sem_signal(&p->sem); - p = p->next; - } - } - aos_mutex_unlock(&cond->wait_list_lock); - - return BHT_OK; -} - diff --git a/core/shared/platform/alios/bh_time.c b/core/shared/platform/alios/bh_time.c deleted file mode 100644 index f06fe9fca..000000000 --- a/core/shared/platform/alios/bh_time.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_time.h" - -/* - * This function returns milliseconds per tick. - * @return milliseconds per tick. - */ -uint64 _bh_time_get_tick_millisecond() -{ - return aos_get_hz() / 1000; -} - -/* - * This function returns milliseconds after boot. - * @return milliseconds after boot. - */ -uint64 _bh_time_get_boot_millisecond() -{ - return (uint64)aos_now_ms(); -} - -uint64 _bh_time_get_millisecond_from_1970() -{ - return (uint64)aos_now_ms(); -} - -size_t -_bh_time_strftime (char *str, size_t max, const char *format, int64 time) -{ - str = aos_now_time_str(str, max); - return str ? strlen(str) + 1 : 0; -} - diff --git a/core/shared/platform/alios/platform_internal.h b/core/shared/platform/alios/platform_internal.h new file mode 100644 index 000000000..7201fb0fd --- /dev/null +++ b/core/shared/platform/alios/platform_internal.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef BH_PLATFORM_ALIOS_THINGS +#define BH_PLATFORM_ALIOS_THINGS +#endif + +#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 30 + +typedef aos_task_t korp_thread; +typedef korp_thread *korp_tid; +typedef aos_task_t *aos_tid_t; +typedef aos_mutex_t korp_mutex; + +struct os_thread_wait_node; +typedef struct os_thread_wait_node *os_thread_wait_list; +typedef struct korp_cond { + aos_mutex_t wait_list_lock; + os_thread_wait_list thread_wait_list; +} korp_cond; + +#define os_printf printf +#define os_vprintf vprintf + +/* math functions which are not provided by os*/ +double sqrt(double x); +double floor(double x); +double ceil(double x); +double fmin(double x, double y); +double fmax(double x, double y); +double rint(double x); +double fabs(double x); +double trunc(double x); +float floorf(float x); +float ceilf(float x); +float fminf(float x, float y); +float fmaxf(float x, float y); +float rintf(float x); +float truncf(float x); +int signbit(double x); +int isnan(double x); + +#endif /* end of _BH_PLATFORM_H */ + diff --git a/core/shared/platform/alios/shared_platform.cmake b/core/shared/platform/alios/shared_platform.cmake index cce0df72a..a3aaddd4a 100644 --- a/core/shared/platform/alios/shared_platform.cmake +++ b/core/shared/platform/alios/shared_platform.cmake @@ -1,13 +1,16 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) - -include_directories(${PLATFORM_SHARED_DIR}) -include_directories(${PLATFORM_SHARED_DIR}/../include) - - -file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) - -set (PLATFORM_SHARED_SOURCE ${source_all}) - +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_ALIOS_THINGS) + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +include (${CMAKE_CURRENT_LIST_DIR}/../common/math/platform_api_math.cmake) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) + +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE}) + diff --git a/core/shared/platform/android/bh_assert.c b/core/shared/platform/android/bh_assert.c deleted file mode 100644 index c609fb93d..000000000 --- a/core/shared/platform/android/bh_assert.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_assert.h" -#include -#include -#include - -#ifdef BH_TEST -#include -#endif - -#ifdef BH_TEST -/* for exception throwing */ -jmp_buf bh_test_jb; -#endif - -void bh_assert_internal(int v, const char *file_name, int line_number, - const char *expr_string) -{ - if (v) - return; - - if (!file_name) - file_name = "NULL FILENAME"; - if (!expr_string) - expr_string = "NULL EXPR_STRING"; - - printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string, - file_name, line_number); - -#ifdef BH_TEST - longjmp(bh_test_jb, 1); -#endif - - abort(); -} - -void bh_debug_internal(const char *file_name, int line_number, const char *fmt, - ...) -{ -#ifndef JEFF_TEST_VERIFIER - va_list args; - - va_start(args, fmt); - bh_assert(file_name); - - printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number); - vprintf(fmt, args); - - va_end(args); - printf("\n"); -#endif -} - diff --git a/core/shared/platform/android/bh_platform.c b/core/shared/platform/android/bh_platform.c deleted file mode 100755 index 1831e9502..000000000 --- a/core/shared/platform/android/bh_platform.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_common.h" -#include "bh_assert.h" - -#include -#include -#include -#include - -int -bh_platform_init() -{ - return 0; -} - -void * -os_malloc(unsigned size) -{ - return malloc(size); -} - -void * -os_realloc(void *ptr, unsigned size) -{ - return realloc(ptr, size); -} - -void -os_free(void *ptr) -{ - free(ptr); -} - -char* -bh_read_file_to_buffer(const char *filename, uint32 *ret_size) -{ - char *buffer; - int file; - uint32 file_size, read_size; - struct stat stat_buf; - - if (!filename || !ret_size) { - printf("Read file to buffer failed: invalid filename or ret size.\n"); - return NULL; - } - - if ((file = open(filename, O_RDONLY, 0)) == -1) { - printf("Read file to buffer failed: open file %s failed.\n", - filename); - return NULL; - } - - if (fstat(file, &stat_buf) != 0) { - printf("Read file to buffer failed: fstat file %s failed.\n", - filename); - close(file); - return NULL; - } - - file_size = (uint32)stat_buf.st_size; - - if (!(buffer = BH_MALLOC(file_size))) { - printf("Read file to buffer failed: alloc memory failed.\n"); - close(file); - return NULL; - } - - read_size = (uint32)read(file, buffer, file_size); - close(file); - - if (read_size < file_size) { - printf("Read file to buffer failed: read file content failed.\n"); - BH_FREE(buffer); - return NULL; - } - - *ret_size = file_size; - return buffer; -} - -void * -bh_mmap(void *hint, uint32 size, int prot, int flags) -{ - int map_prot = PROT_NONE; - int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; - uint64 request_size, page_size; - uint8 *addr, *addr_aligned; - uint32 i; - - /* align to 2M if no less than 2M, else align to 4K */ - page_size = size < 2 * 1024 * 1024 ? 4096 : 2 * 1024 * 1024; - request_size = (size + page_size - 1) & ~(page_size - 1); - request_size += page_size; - - if (request_size >= UINT32_MAX) - return NULL; - - if (prot & MMAP_PROT_READ) - map_prot |= PROT_READ; - - if (prot & MMAP_PROT_WRITE) - map_prot |= PROT_WRITE; - - if (prot & MMAP_PROT_EXEC) - map_prot |= PROT_EXEC; - -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) - if (flags & MMAP_MAP_32BIT) - map_flags |= MAP_32BIT; -#endif - - if (flags & MMAP_MAP_FIXED) - map_flags |= MAP_FIXED; - - /* try 5 times */ - for (i = 0; i < 5; i ++) { - addr = mmap(hint, size, map_prot, map_flags, -1, 0); - if (addr != MAP_FAILED) - break; - } - if (addr == MAP_FAILED) - return NULL; - - addr_aligned = (uint8*)(uintptr_t) - (((uint64)(uintptr_t)addr + page_size - 1) & ~(page_size - 1)); - - /* Unmap memory allocated before the aligned base address */ - if (addr != addr_aligned) { - uint32 prefix_size = (uint32)(addr_aligned - addr); - munmap(addr, prefix_size); - request_size -= prefix_size; - } - - /* Unmap memory allocated after the potentially unaligned end */ - if (size != request_size) { - uint32 suffix_size = (uint32)(request_size - size); - munmap(addr_aligned + size, suffix_size); - request_size -= size; - } - - if (size >= 2 * 1024 * 1024) { - /* Try to use huge page to improve performance */ - if (!madvise(addr, size, MADV_HUGEPAGE)) - /* make huge page become effective */ - memset(addr, 0, size); - } - - return addr_aligned; -} - -void -bh_munmap(void *addr, uint32 size) -{ - if (addr) - munmap(addr, size); -} - -int -bh_mprotect(void *addr, uint32 size, int prot) -{ - int map_prot = PROT_NONE; - - if (!addr) - return 0; - - if (prot & MMAP_PROT_READ) - map_prot |= PROT_READ; - - if (prot & MMAP_PROT_WRITE) - map_prot |= PROT_WRITE; - - if (prot & MMAP_PROT_EXEC) - map_prot |= PROT_EXEC; - - return mprotect(addr, size, map_prot); -} - diff --git a/core/shared/platform/android/bh_platform.h b/core/shared/platform/android/bh_platform.h deleted file mode 100644 index 003850954..000000000 --- a/core/shared/platform/android/bh_platform.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_PLATFORM_H -#define _BH_PLATFORM_H - -#include "bh_config.h" -#include "bh_types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint64_t uint64; -typedef int64_t int64; - -#ifndef BH_PLATFORM_ANDROID -#define BH_PLATFORM_ANDROID -#endif - -#define _STACK_SIZE_ADJUSTMENT (32 * 1024) - -/* Stack size of applet threads's native part. */ -#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) - -/* Default thread priority */ -#define BH_THREAD_DEFAULT_PRIORITY 0 - -#define BH_ROUTINE_MODIFIER - -#define BHT_TIMEDOUT ETIMEDOUT - -#define INVALID_THREAD_ID 0xFFffFFff - -typedef pthread_t korp_tid; -typedef pthread_mutex_t korp_mutex; -typedef sem_t korp_sem; -typedef pthread_cond_t korp_cond; -typedef pthread_t korp_thread; -typedef void* (*thread_start_routine_t)(void*); - -void *os_malloc(unsigned size); -void *os_realloc(void *ptr, unsigned size); -void os_free(void *ptr); - -#define bh_printf(...) (__android_log_print(ANDROID_LOG_INFO, "wasm_runtime::", __VA_ARGS__)) - -int snprintf(char *buffer, size_t count, const char *format, ...); -double fmod(double x, double y); -float fmodf(float x, float y); -double sqrt(double x); - -#define BH_WAIT_FOREVER 0xFFFFFFFF - -#ifndef NULL -# define NULL ((void*) 0) -#endif - -/** - * Return the offset of the given field in the given type. - * - * @param Type the type containing the filed - * @param field the field in the type - * - * @return the offset of field in Type - */ -#ifndef offsetof -#define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) -#endif - -#define bh_assert assert - -char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); - -int bh_platform_init(); - -/* MMAP mode */ -enum { - MMAP_PROT_NONE = 0, - MMAP_PROT_READ = 1, - MMAP_PROT_WRITE = 2, - MMAP_PROT_EXEC = 4 -}; - -/* MMAP flags */ -enum { - MMAP_MAP_NONE = 0, - /* Put the mapping into 0 to 2 G, supported only on x86_64 */ - MMAP_MAP_32BIT = 1, - /* Don't interpret addr as a hint: place the mapping at exactly - that address. */ - MMAP_MAP_FIXED = 2 -}; - -void *bh_mmap(void *hint, unsigned int size, int prot, int flags); -void bh_munmap(void *addr, uint32 size); -int bh_mprotect(void *addr, uint32 size, int prot); -#define bh_dcache_flush() (void)0 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/core/shared/platform/android/bh_platform_log.c b/core/shared/platform/android/bh_platform_log.c deleted file mode 100644 index d5a01ec55..000000000 --- a/core/shared/platform/android/bh_platform_log.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include - -#include - -void bh_log_emit(const char *fmt, va_list ap) -{ - (void)__android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap); -} - -int bh_fprintf(FILE *stream, const char *fmt, ...) -{ - (void)stream; - va_list ap; - int ret = 0; - - va_start(ap, fmt); - ret = __android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap); - va_end(ap); - - return ret; -} - -int bh_fflush(void *stream) -{ - (void)stream; - return __android_log_print(ANDROID_LOG_INFO, "wasm_runtime::", "%s", "NOT IMPLEMENT"); -} diff --git a/core/shared/platform/android/bh_thread.c b/core/shared/platform/android/bh_thread.c deleted file mode 100755 index 88c62a3ba..000000000 --- a/core/shared/platform/android/bh_thread.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_thread.h" -#include "bh_assert.h" -#include "bh_log.h" -#include -#include -#include - -static bool is_thread_sys_inited = false; - -static korp_mutex thread_list_lock; -static pthread_key_t thread_local_storage_key[BH_MAX_TLS_NUM]; - -int _vm_thread_sys_init() -{ - unsigned i, j; - int ret; - - if (is_thread_sys_inited) - return 0; - - for (i = 0; i < BH_MAX_TLS_NUM; i++) { - ret = pthread_key_create(&thread_local_storage_key[i], NULL); - if (ret) - goto fail; - } - - ret = vm_mutex_init(&thread_list_lock); - if (ret) - goto fail; - - is_thread_sys_inited = true; - return 0; - - fail: for (j = 0; j < i; j++) - pthread_key_delete(thread_local_storage_key[j]); - return -1; -} - -void vm_thread_sys_destroy(void) -{ - if (is_thread_sys_inited) { - unsigned i; - for (i = 0; i < BH_MAX_TLS_NUM; i++) - pthread_key_delete(thread_local_storage_key[i]); - vm_mutex_destroy(&thread_list_lock); - is_thread_sys_inited = false; - } -} - -typedef struct { - thread_start_routine_t start; - void* stack; - uint32 stack_size; - void* arg; -} thread_wrapper_arg; - -static void *vm_thread_wrapper(void *arg) -{ - thread_wrapper_arg * targ = arg; - LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ); - targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); - _vm_tls_put(1, targ); - targ->start(targ->arg); - BH_FREE(targ); - _vm_tls_put(1, NULL); - return NULL; -} - -int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) -{ - (void)prio; - pthread_attr_t tattr; - thread_wrapper_arg *targ; - - bh_assert(stack_size > 0); - bh_assert(tid); - bh_assert(start); - - *tid = INVALID_THREAD_ID; - - pthread_attr_init(&tattr); - pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); - if (pthread_attr_setstacksize(&tattr, stack_size) != 0) { - bh_debug("Invalid thread stack size %u. Min stack size on Linux = %u", - stack_size, PTHREAD_STACK_MIN); - pthread_attr_destroy(&tattr); - return BHT_ERROR; - } - - targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ)); - if (!targ) { - pthread_attr_destroy(&tattr); - return BHT_ERROR; - } - - targ->start = start; - targ->arg = arg; - targ->stack_size = stack_size; - - if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) { - pthread_attr_destroy(&tattr); - BH_FREE(targ); - return BHT_ERROR; - } - - pthread_attr_destroy(&tattr); - return BHT_OK; -} - -int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) -{ - return _vm_thread_create_with_prio(tid, start, arg, stack_size, - BH_THREAD_DEFAULT_PRIORITY); -} - -korp_tid _vm_self_thread() -{ - return (korp_tid) pthread_self(); -} - -void vm_thread_exit(void * code) -{ - BH_FREE(_vm_tls_get(1)); - _vm_tls_put(1, NULL); - pthread_exit(code); -} - -void *_vm_tls_get(unsigned idx) -{ - bh_assert(idx < BH_MAX_TLS_NUM); - return pthread_getspecific(thread_local_storage_key[idx]); -} - -int _vm_tls_put(unsigned idx, void * tls) -{ - bh_assert(idx < BH_MAX_TLS_NUM); - pthread_setspecific(thread_local_storage_key[idx], tls); - return BHT_OK; -} - -int _vm_mutex_init(korp_mutex *mutex) -{ - return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_recursive_mutex_init(korp_mutex *mutex) -{ - int ret; - - pthread_mutexattr_t mattr; - - bh_assert(mutex); - ret = pthread_mutexattr_init(&mattr); - if (ret) - return BHT_ERROR; - - pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE_NP); - ret = pthread_mutex_init(mutex, &mattr); - pthread_mutexattr_destroy(&mattr); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_mutex_destroy(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_destroy(mutex); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -/* Returned error (EINVAL, EAGAIN and EDEADLK) from - locking the mutex indicates some logic error present in - the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_lock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_lock(mutex); - if (0 != ret) { - printf("vm mutex lock failed (ret=%d)!\n", ret); - exit(-1); - } -} - -int vm_mutex_trylock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_trylock(mutex); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -/* Returned error (EINVAL, EAGAIN and EPERM) from - unlocking the mutex indicates some logic error present - in the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_unlock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_unlock(mutex); - if (0 != ret) { - printf("vm mutex unlock failed (ret=%d)!\n", ret); - exit(-1); - } -} - -int _vm_sem_init(korp_sem* sem, unsigned int c) -{ - int ret; - - bh_assert(sem); - ret = sem_init(sem, 0, c); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_destroy(korp_sem *sem) -{ - int ret; - - bh_assert(sem); - ret = sem_destroy(sem); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_wait(korp_sem *sem) -{ - int ret; - - bh_assert(sem); - - ret = sem_wait(sem); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_reltimedwait(korp_sem *sem, int mills) -{ - int ret = BHT_OK; - - struct timespec timeout; - const int mills_per_sec = 1000; - const int mills_to_nsec = 1E6; - - bh_assert(sem); - - if (mills == (int)BHT_WAIT_FOREVER) { - ret = sem_wait(sem); - } else { - - timeout.tv_sec = mills / mills_per_sec; - timeout.tv_nsec = (mills % mills_per_sec) * mills_to_nsec; - timeout.tv_sec += time(NULL); - - ret = sem_timedwait(sem, &timeout); - } - - if (ret != BHT_OK) { - if (errno == BHT_TIMEDOUT) { - ret = BHT_TIMEDOUT; - errno = 0; - } else { - bh_debug("Faliure happens when timed wait is called"); - bh_assert(0); - } - } - - return ret; -} - -int _vm_sem_post(korp_sem *sem) -{ - bh_assert(sem); - - return sem_post(sem) == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_cond_init(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_init(cond, NULL) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_destroy(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_destroy(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex) -{ - bh_assert(cond); - bh_assert(mutex); - - if (pthread_cond_wait(cond, mutex) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - ts->tv_sec = (long int)(tv.tv_sec + msec / 1000); - ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec); - - if (ts->tv_nsec >= 1000000000L) { - ts->tv_sec++; - ts->tv_nsec -= 1000000000L; - } -} - -int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) -{ - int ret; - struct timespec abstime; - - if (mills == (int)BHT_WAIT_FOREVER) - ret = pthread_cond_wait(cond, mutex); - else { - msec_nsec_to_abstime(&abstime, mills, 0); - ret = pthread_cond_timedwait(cond, mutex, &abstime); - } - - if (ret != BHT_OK && ret != BHT_TIMEDOUT) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_signal(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_signal(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_broadcast(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_broadcast(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_thread_cancel(korp_tid thread) -{ - return pthread_kill(thread, SIGABRT); -} - -int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) -{ - (void)mills; - return pthread_join(thread, value_ptr); -} - -int _vm_thread_detach(korp_tid thread) -{ - return pthread_detach(thread); -} - diff --git a/core/shared/platform/android/bh_time.c b/core/shared/platform/android/bh_time.c deleted file mode 100755 index 05cf0af57..000000000 --- a/core/shared/platform/android/bh_time.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_time.h" - -#include -#include -#include - -/* - * This function returns milliseconds per tick. - * @return milliseconds per tick. - */ -uint64 _bh_time_get_tick_millisecond() -{ - return (uint64)sysconf(_SC_CLK_TCK); -} - -/* - * This function returns milliseconds after boot. - * @return milliseconds after boot. - */ -uint64 _bh_time_get_boot_millisecond() -{ - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - return 0; - } - - return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000); -} - -uint32 bh_get_tick_sec() -{ - return (uint32)(_bh_time_get_boot_millisecond() / 1000); -} - -/* - * This function returns GMT time milliseconds since from 1970.1.1, AKA UNIX time. - * @return milliseconds since from 1970.1.1. - */ -uint64 _bh_time_get_millisecond_from_1970() -{ - struct timeval tv; - struct timezone tz; - gettimeofday(&tv, &tz); - - return tv.tv_sec * 1000 + tv.tv_usec - - (tz.tz_dsttime == 0 ? 0 : 60 * 60 * 1000) - + tz.tz_minuteswest * 60 * 1000; -} - -size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time) -{ - time_t time_sec = (time_t)(time / 1000); - struct timeval tv; - struct timezone tz; - struct tm *ltp; - - gettimeofday(&tv, &tz); - time_sec -= tz.tz_minuteswest * 60; - - ltp = localtime(&time_sec); - if (ltp == NULL) { - return 0; - } - return strftime(s, max, format, ltp); -} - diff --git a/core/shared/platform/android/platform_init.c b/core/shared/platform/android/platform_init.c new file mode 100644 index 000000000..d250d439b --- /dev/null +++ b/core/shared/platform/android/platform_init.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" +int +bh_platform_init() +{ + return 0; +} + +void +bh_platform_destroy() +{ +} + +int os_printf(const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = __android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap); + va_end(ap); + + return ret; +} + +int os_vprintf(const char *fmt, va_list ap) +{ + return __android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap); +} + diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h new file mode 100644 index 000000000..b52348d0c --- /dev/null +++ b/core/shared/platform/android/platform_internal.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_ANDROID +#define BH_PLATFORM_ANDROID +#endif + +#define _STACK_SIZE_ADJUSTMENT (32 * 1024) + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef pthread_t korp_tid; +typedef pthread_mutex_t korp_mutex; +typedef pthread_cond_t korp_cond; +typedef pthread_t korp_thread; + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ + diff --git a/core/shared/platform/android/shared_platform.cmake b/core/shared/platform/android/shared_platform.cmake index a49c5c6e1..13beb8e77 100644 --- a/core/shared/platform/android/shared_platform.cmake +++ b/core/shared/platform/android/shared_platform.cmake @@ -3,15 +3,16 @@ set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) +add_definitions(-DBH_PLATFORM_ANDROID) + include_directories(${PLATFORM_SHARED_DIR}) include_directories(${PLATFORM_SHARED_DIR}/../include) +include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) -set (PLATFORM_SHARED_SOURCE ${source_all}) - -LIST (APPEND RUNTIME_LIB_HEADER_LIST "${PLATFORM_SHARED_DIR}/bh_platform.h") +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE}) file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) -LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) \ No newline at end of file +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) diff --git a/core/shared/platform/alios/COPYRIGHT b/core/shared/platform/common/math/COPYRIGHT similarity index 100% rename from core/shared/platform/alios/COPYRIGHT rename to core/shared/platform/common/math/COPYRIGHT diff --git a/core/shared/platform/zephyr/bh_math.c b/core/shared/platform/common/math/math.c similarity index 99% rename from core/shared/platform/zephyr/bh_math.c rename to core/shared/platform/common/math/math.c index 913d52167..1c1137bad 100644 --- a/core/shared/platform/zephyr/bh_math.c +++ b/core/shared/platform/common/math/math.c @@ -28,7 +28,7 @@ * $FreeBSD$ */ -#include "bh_platform.h" +#include "platform_common.h" #define __FDLIBM_STDC__ @@ -123,8 +123,8 @@ static union { #define __HIL(x) *(1+pdouble2pint(&x)) #define __LOL(x) *(pdouble2pint(&x)) -#define __HIB(x) *(int*)&x -#define __LOB(x) *(1+(int*)&x) +#define __HIB(x) *(pdouble2pint(&x)) +#define __LOB(x) *(1+pdouble2pint(&x)) /* Get two 32 bit ints from a double. */ diff --git a/core/shared/platform/common/math/platform_api_math.cmake b/core/shared/platform/common/math/platform_api_math.cmake new file mode 100644 index 000000000..09c74bfc5 --- /dev/null +++ b/core/shared/platform/common/math/platform_api_math.cmake @@ -0,0 +1,8 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_COMMON_MATH_DIR ${CMAKE_CURRENT_LIST_DIR}) + +file (GLOB_RECURSE source_all ${PLATFORM_COMMON_MATH_DIR}/*.c) + +set (PLATFORM_COMMON_MATH_SOURCE ${source_all} ) diff --git a/core/shared/platform/common/posix/platform_api_posix.cmake b/core/shared/platform/common/posix/platform_api_posix.cmake new file mode 100644 index 000000000..4abefff1e --- /dev/null +++ b/core/shared/platform/common/posix/platform_api_posix.cmake @@ -0,0 +1,8 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_COMMON_POSIX_DIR ${CMAKE_CURRENT_LIST_DIR}) + +file (GLOB_RECURSE source_all ${PLATFORM_COMMON_POSIX_DIR}/*.c) + +set (PLATFORM_COMMON_POSIX_SOURCE ${source_all} ) diff --git a/core/shared/platform/common/posix/posix_malloc.c b/core/shared/platform/common/posix/posix_malloc.c new file mode 100644 index 000000000..e83fc7d7b --- /dev/null +++ b/core/shared/platform/common/posix/posix_malloc.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + + + diff --git a/core/shared/platform/darwin/bh_platform.c b/core/shared/platform/common/posix/posix_memmap.c old mode 100755 new mode 100644 similarity index 58% rename from core/shared/platform/darwin/bh_platform.c rename to core/shared/platform/common/posix/posix_memmap.c index ddfacf3ea..7cf83f44d --- a/core/shared/platform/darwin/bh_platform.c +++ b/core/shared/platform/common/posix/posix_memmap.c @@ -3,88 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_platform.h" -#include "bh_common.h" -#include "bh_assert.h" - -#include -#include -#include -#include - -int -bh_platform_init() -{ - return 0; -} +#include "platform_api_vmcore.h" void * -os_malloc(unsigned size) -{ - return malloc(size); -} - -void * -os_realloc(void *ptr, unsigned size) -{ - return realloc(ptr, size); -} - -void -os_free(void *ptr) -{ - free(ptr); -} - -char* -bh_read_file_to_buffer(const char *filename, uint32 *ret_size) -{ - char *buffer; - int file; - uint32 file_size, read_size; - struct stat stat_buf; - - if (!filename || !ret_size) { - printf("Read file to buffer failed: invalid filename or ret size.\n"); - return NULL; - } - - if ((file = open(filename, O_RDONLY, 0)) == -1) { - printf("Read file to buffer failed: open file %s failed.\n", - filename); - return NULL; - } - - if (fstat(file, &stat_buf) != 0) { - printf("Read file to buffer failed: fstat file %s failed.\n", - filename); - close(file); - return NULL; - } - - file_size = (uint32)stat_buf.st_size; - - if (!(buffer = BH_MALLOC(file_size))) { - printf("Read file to buffer failed: alloc memory failed.\n"); - close(file); - return NULL; - } - - read_size = (uint32)read(file, buffer, file_size); - close(file); - - if (read_size < file_size) { - printf("Read file to buffer failed: read file content failed.\n"); - BH_FREE(buffer); - return NULL; - } - - *ret_size = file_size; - return buffer; -} - -void * -bh_mmap(void *hint, uint32 size, int prot, int flags) +os_mmap(void *hint, uint32 size, int prot, int flags) { int map_prot = PROT_NONE; int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; @@ -110,8 +32,10 @@ bh_mmap(void *hint, uint32 size, int prot, int flags) map_prot |= PROT_EXEC; #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +#ifndef __APPLE__ if (flags & MMAP_MAP_32BIT) map_flags |= MAP_32BIT; +#endif #endif if (flags & MMAP_MAP_FIXED) @@ -119,7 +43,7 @@ bh_mmap(void *hint, uint32 size, int prot, int flags) /* try 5 times */ for (i = 0; i < 5; i ++) { - addr = mmap(hint, size, map_prot, map_flags, -1, 0); + addr = mmap(hint, request_size, map_prot, map_flags, -1, 0); if (addr != MAP_FAILED) break; } @@ -156,14 +80,14 @@ bh_mmap(void *hint, uint32 size, int prot, int flags) } void -bh_munmap(void *addr, uint32 size) +os_munmap(void *addr, uint32 size) { if (addr) munmap(addr, size); } int -bh_mprotect(void *addr, uint32 size, int prot) +os_mprotect(void *addr, uint32 size, int prot) { int map_prot = PROT_NONE; @@ -182,3 +106,7 @@ bh_mprotect(void *addr, uint32 size, int prot) return mprotect(addr, size, map_prot); } +void +os_dcache_flush(void) +{ +} diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c new file mode 100644 index 000000000..161a16174 --- /dev/null +++ b/core/shared/platform/common/posix/posix_thread.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +typedef struct { + thread_start_routine_t start; + void* stack; + uint32 stack_size; + void* arg; +} thread_wrapper_arg; + +static void *os_thread_wrapper(void *arg) +{ + thread_wrapper_arg * targ = arg; + printf("THREAD CREATE %p\n", &targ); + targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); + targ->start(targ->arg); + BH_FREE(targ); + return NULL; +} + +int os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, + void *arg, unsigned int stack_size, int prio) +{ + pthread_attr_t tattr; + thread_wrapper_arg *targ; + + assert(stack_size > 0); + assert(tid); + assert(start); + + pthread_attr_init(&tattr); + pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); + if (pthread_attr_setstacksize(&tattr, stack_size) != 0) { + printf("Invalid thread stack size %u. Min stack size on Linux = %u", + stack_size, PTHREAD_STACK_MIN); + pthread_attr_destroy(&tattr); + return BHT_ERROR; + } + + targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ)); + if (!targ) { + pthread_attr_destroy(&tattr); + return BHT_ERROR; + } + + targ->start = start; + targ->arg = arg; + targ->stack_size = stack_size; + + if (pthread_create(tid, &tattr, os_thread_wrapper, targ) != 0) { + pthread_attr_destroy(&tattr); + BH_FREE(targ); + return BHT_ERROR; + } + + pthread_attr_destroy(&tattr); + return BHT_OK; +} + +int os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, + unsigned int stack_size) +{ + return os_thread_create_with_prio(tid, start, arg, stack_size, + BH_THREAD_DEFAULT_PRIORITY); +} + +korp_tid os_self_thread() +{ + return (korp_tid) pthread_self(); +} + +int os_mutex_init(korp_mutex *mutex) +{ + return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR; +} + +int os_recursive_mutex_init(korp_mutex *mutex) +{ + int ret; + + pthread_mutexattr_t mattr; + + assert(mutex); + ret = pthread_mutexattr_init(&mattr); + if (ret) + return BHT_ERROR; + + pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); + ret = pthread_mutex_init(mutex, &mattr); + pthread_mutexattr_destroy(&mattr); + + return ret == 0 ? BHT_OK : BHT_ERROR; +} + +int os_mutex_destroy(korp_mutex *mutex) +{ + int ret; + + assert(mutex); + ret = pthread_mutex_destroy(mutex); + + return ret == 0 ? BHT_OK : BHT_ERROR; +} + +/* Returned error (EINVAL, EAGAIN and EDEADLK) from + locking the mutex indicates some logic error present in + the program somewhere. + Don't try to recover error for an existing unknown error.*/ +void os_mutex_lock(korp_mutex *mutex) +{ + int ret; + + assert(mutex); + ret = pthread_mutex_lock(mutex); + if (0 != ret) { + printf("vm mutex lock failed (ret=%d)!\n", ret); + exit(-1); + } +} + +/* Returned error (EINVAL, EAGAIN and EPERM) from + unlocking the mutex indicates some logic error present + in the program somewhere. + Don't try to recover error for an existing unknown error.*/ +void os_mutex_unlock(korp_mutex *mutex) +{ + int ret; + + assert(mutex); + ret = pthread_mutex_unlock(mutex); + if (0 != ret) { + printf("vm mutex unlock failed (ret=%d)!\n", ret); + exit(-1); + } +} + +int os_cond_init(korp_cond *cond) +{ + assert(cond); + + if (pthread_cond_init(cond, NULL) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + +int os_cond_destroy(korp_cond *cond) +{ + assert(cond); + + if (pthread_cond_destroy(cond) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + +int os_cond_wait(korp_cond *cond, korp_mutex *mutex) +{ + assert(cond); + assert(mutex); + + if (pthread_cond_wait(cond, mutex) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + +static void msec_nsec_to_abstime(struct timespec *ts, int usec) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + ts->tv_sec = (long int)(tv.tv_sec + usec / 1000000); + ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (usec % 1000000) * 1000); + + if (ts->tv_nsec >= 1000000000L) { + ts->tv_sec++; + ts->tv_nsec -= 1000000000L; + } +} + +int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds) +{ + int ret; + struct timespec abstime; + + if (useconds == (int)BHT_WAIT_FOREVER) + ret = pthread_cond_wait(cond, mutex); + else { + msec_nsec_to_abstime(&abstime, useconds); + ret = pthread_cond_timedwait(cond, mutex, &abstime); + } + + if (ret != BHT_OK && ret != ETIMEDOUT) + return BHT_ERROR; + + return BHT_OK; +} + +int os_cond_signal(korp_cond *cond) +{ + assert(cond); + + if (pthread_cond_signal(cond) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + +int os_thread_join(korp_tid thread, void **value_ptr) +{ + return pthread_join(thread, value_ptr); +} + diff --git a/core/shared/platform/common/posix/posix_time.c b/core/shared/platform/common/posix/posix_time.c new file mode 100644 index 000000000..744dd4cb1 --- /dev/null +++ b/core/shared/platform/common/posix/posix_time.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +uint64 +os_time_get_boot_microsecond() +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { + return 0; + } + + return ((uint64) ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000; +} + diff --git a/core/shared/platform/darwin/bh_assert.c b/core/shared/platform/darwin/bh_assert.c deleted file mode 100644 index c609fb93d..000000000 --- a/core/shared/platform/darwin/bh_assert.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_assert.h" -#include -#include -#include - -#ifdef BH_TEST -#include -#endif - -#ifdef BH_TEST -/* for exception throwing */ -jmp_buf bh_test_jb; -#endif - -void bh_assert_internal(int v, const char *file_name, int line_number, - const char *expr_string) -{ - if (v) - return; - - if (!file_name) - file_name = "NULL FILENAME"; - if (!expr_string) - expr_string = "NULL EXPR_STRING"; - - printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string, - file_name, line_number); - -#ifdef BH_TEST - longjmp(bh_test_jb, 1); -#endif - - abort(); -} - -void bh_debug_internal(const char *file_name, int line_number, const char *fmt, - ...) -{ -#ifndef JEFF_TEST_VERIFIER - va_list args; - - va_start(args, fmt); - bh_assert(file_name); - - printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number); - vprintf(fmt, args); - - va_end(args); - printf("\n"); -#endif -} - diff --git a/core/shared/platform/darwin/bh_platform.h b/core/shared/platform/darwin/bh_platform.h deleted file mode 100644 index e07dd4e55..000000000 --- a/core/shared/platform/darwin/bh_platform.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_PLATFORM_H -#define _BH_PLATFORM_H - -#include "bh_config.h" -#include "bh_types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint64_t uint64; -typedef int64_t int64; - -#ifndef BH_PLATFORM_DARWIN -#define BH_PLATFORM_DARWIN -#endif - -#define _STACK_SIZE_ADJUSTMENT (32 * 1024) - -/* Stack size of applet threads's native part. */ -#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) - -/* Default thread priority */ -#define BH_THREAD_DEFAULT_PRIORITY 0 - -#define BH_ROUTINE_MODIFIER - -#define BHT_TIMEDOUT ETIMEDOUT - -#define INVALID_THREAD_ID 0xFFffFFff - -typedef pthread_t korp_tid; -typedef pthread_mutex_t korp_mutex; -typedef sem_t korp_sem; -typedef pthread_cond_t korp_cond; -typedef pthread_t korp_thread; -typedef void* (*thread_start_routine_t)(void*); - -void *os_malloc(unsigned size); -void *os_realloc(void *ptr, unsigned size); -void os_free(void *ptr); - -#define bh_printf printf - -/* int snprintf(char *buffer, size_t count, const char *format, ...); */ -double fmod(double x, double y); -float fmodf(float x, float y); -double sqrt(double x); - -#define BH_WAIT_FOREVER 0xFFFFFFFF - -#ifndef NULL -# define NULL ((void*) 0) -#endif - -/** - * Return the offset of the given field in the given type. - * - * @param Type the type containing the filed - * @param field the field in the type - * - * @return the offset of field in Type - */ -#ifndef offsetof -#define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) -#endif - -#define bh_assert assert - -char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); - -int bh_platform_init(); - -/* MMAP mode */ -enum { - MMAP_PROT_NONE = 0, - MMAP_PROT_READ = 1, - MMAP_PROT_WRITE = 2, - MMAP_PROT_EXEC = 4 -}; - -/* MMAP flags */ -enum { - MMAP_MAP_NONE = 0, - /* Put the mapping into 0 to 2 G, supported only on x86_64 */ - MMAP_MAP_32BIT = 1, - /* Don't interpret addr as a hint: place the mapping at exactly - that address. */ - MMAP_MAP_FIXED = 2 -}; - -void *bh_mmap(void *hint, unsigned int size, int prot, int flags); -void bh_munmap(void *addr, uint32 size); -int bh_mprotect(void *addr, uint32 size, int prot); -#define bh_dcache_flush() (void)0 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/core/shared/platform/darwin/bh_platform_log.c b/core/shared/platform/darwin/bh_platform_log.c deleted file mode 100644 index 902ca7d60..000000000 --- a/core/shared/platform/darwin/bh_platform_log.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include - -void bh_log_emit(const char *fmt, va_list ap) -{ - vprintf(fmt, ap); - fflush(stdout); -} - -int bh_fprintf(FILE *stream, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = vfprintf(stream ? stream : stdout, fmt, ap); - va_end(ap); - - return ret; -} - -int bh_fflush(void *stream) -{ - return fflush(stream ? stream : stdout); -} diff --git a/core/shared/platform/darwin/bh_thread.c b/core/shared/platform/darwin/bh_thread.c deleted file mode 100644 index c81e9786d..000000000 --- a/core/shared/platform/darwin/bh_thread.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_thread.h" -#include "bh_assert.h" -#include "bh_log.h" -#include -#include -#include - -static bool is_thread_sys_inited = false; - -static korp_mutex thread_list_lock; -static pthread_key_t thread_local_storage_key[BH_MAX_TLS_NUM]; - -int _vm_thread_sys_init() -{ - unsigned i, j; - int ret; - - if (is_thread_sys_inited) - return 0; - - for (i = 0; i < BH_MAX_TLS_NUM; i++) { - ret = pthread_key_create(&thread_local_storage_key[i], NULL); - if (ret) - goto fail; - } - - ret = vm_mutex_init(&thread_list_lock); - if (ret) - goto fail; - - is_thread_sys_inited = true; - return 0; - - fail: for (j = 0; j < i; j++) - pthread_key_delete(thread_local_storage_key[j]); - return -1; -} - -void vm_thread_sys_destroy(void) -{ - if (is_thread_sys_inited) { - unsigned i; - for (i = 0; i < BH_MAX_TLS_NUM; i++) - pthread_key_delete(thread_local_storage_key[i]); - vm_mutex_destroy(&thread_list_lock); - is_thread_sys_inited = false; - } -} - -typedef struct { - thread_start_routine_t start; - void* stack; - uint32 stack_size; - void* arg; -} thread_wrapper_arg; - -static void *vm_thread_wrapper(void *arg) -{ - thread_wrapper_arg * targ = arg; - LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ); - targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); - _vm_tls_put(1, targ); - targ->start(targ->arg); - BH_FREE(targ); - _vm_tls_put(1, NULL); - return NULL; -} - -int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) -{ - pthread_attr_t tattr; - thread_wrapper_arg *targ; - - bh_assert(stack_size > 0); - bh_assert(tid); - bh_assert(start); - - *tid = INVALID_THREAD_ID; - - pthread_attr_init(&tattr); - pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); - if (pthread_attr_setstacksize(&tattr, stack_size) != 0) { - bh_debug("Invalid thread stack size %u. Min stack size on Linux = %u", - stack_size, PTHREAD_STACK_MIN); - pthread_attr_destroy(&tattr); - return BHT_ERROR; - } - - targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ)); - if (!targ) { - pthread_attr_destroy(&tattr); - return BHT_ERROR; - } - - targ->start = start; - targ->arg = arg; - targ->stack_size = stack_size; - - if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) { - pthread_attr_destroy(&tattr); - BH_FREE(targ); - return BHT_ERROR; - } - - pthread_attr_destroy(&tattr); - return BHT_OK; -} - -int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) -{ - return _vm_thread_create_with_prio(tid, start, arg, stack_size, - BH_THREAD_DEFAULT_PRIORITY); -} - -korp_tid _vm_self_thread() -{ - return (korp_tid) pthread_self(); -} - -void vm_thread_exit(void * code) -{ - BH_FREE(_vm_tls_get(1)); - _vm_tls_put(1, NULL); - pthread_exit(code); -} - -void *_vm_tls_get(unsigned idx) -{ - bh_assert(idx < BH_MAX_TLS_NUM); - return pthread_getspecific(thread_local_storage_key[idx]); -} - -int _vm_tls_put(unsigned idx, void * tls) -{ - bh_assert(idx < BH_MAX_TLS_NUM); - pthread_setspecific(thread_local_storage_key[idx], tls); - return BHT_OK; -} - -int _vm_mutex_init(korp_mutex *mutex) -{ - return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_recursive_mutex_init(korp_mutex *mutex) -{ - int ret; - - pthread_mutexattr_t mattr; - - bh_assert(mutex); - ret = pthread_mutexattr_init(&mattr); - if (ret) - return BHT_ERROR; - - pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); - ret = pthread_mutex_init(mutex, &mattr); - pthread_mutexattr_destroy(&mattr); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_mutex_destroy(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_destroy(mutex); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -/* Returned error (EINVAL, EAGAIN and EDEADLK) from - locking the mutex indicates some logic error present in - the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_lock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_lock(mutex); - if (0 != ret) { - printf("vm mutex lock failed (ret=%d)!\n", ret); - exit(-1); - } -} - -int vm_mutex_trylock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_trylock(mutex); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -/* Returned error (EINVAL, EAGAIN and EPERM) from - unlocking the mutex indicates some logic error present - in the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_unlock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_unlock(mutex); - if (0 != ret) { - printf("vm mutex unlock failed (ret=%d)!\n", ret); - exit(-1); - } -} - -int _vm_sem_init(korp_sem* sem, unsigned int c) -{ - int ret; - - bh_assert(sem); - ret = sem_init(sem, 0, c); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_destroy(korp_sem *sem) -{ - int ret; - - bh_assert(sem); - ret = sem_destroy(sem); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_wait(korp_sem *sem) -{ - int ret; - - bh_assert(sem); - - ret = sem_wait(sem); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -/*int _vm_sem_reltimedwait(korp_sem *sem, int mills) -{ - int ret = BHT_OK; - - struct timespec timeout; - const int mills_per_sec = 1000; - const int mills_to_nsec = 1E6; - - bh_assert(sem); - - if (mills == (int)BHT_WAIT_FOREVER) { - ret = sem_wait(sem); - } else { - - timeout.tv_sec = mills / mills_per_sec; - timeout.tv_nsec = (mills % mills_per_sec) * mills_to_nsec; - timeout.tv_sec += time(NULL); - - ret = sem_timedwait(sem, &timeout); - } - - if (ret != BHT_OK) { - if (errno == BHT_TIMEDOUT) { - ret = BHT_TIMEDOUT; - errno = 0; - } else { - bh_debug("Faliure happens when timed wait is called"); - bh_assert(0); - } - } - - return ret; -} -*/ - -int _vm_sem_post(korp_sem *sem) -{ - bh_assert(sem); - - return sem_post(sem) == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_cond_init(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_init(cond, NULL) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_destroy(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_destroy(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex) -{ - bh_assert(cond); - bh_assert(mutex); - - if (pthread_cond_wait(cond, mutex) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - ts->tv_sec = (long int)(tv.tv_sec + msec / 1000); - ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec); - - if (ts->tv_nsec >= 1000000000L) { - ts->tv_sec++; - ts->tv_nsec -= 1000000000L; - } -} - -int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) -{ - int ret; - struct timespec abstime; - - if (mills == (int)BHT_WAIT_FOREVER) - ret = pthread_cond_wait(cond, mutex); - else { - msec_nsec_to_abstime(&abstime, mills, 0); - ret = pthread_cond_timedwait(cond, mutex, &abstime); - } - - if (ret != BHT_OK && ret != BHT_TIMEDOUT) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_signal(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_signal(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_broadcast(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_broadcast(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_thread_cancel(korp_tid thread) -{ - return pthread_cancel(thread); -} - -int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) -{ - return pthread_join(thread, value_ptr); -} - -int _vm_thread_detach(korp_tid thread) -{ - return pthread_detach(thread); -} - diff --git a/core/shared/platform/darwin/bh_time.c b/core/shared/platform/darwin/bh_time.c deleted file mode 100644 index 698cdec24..000000000 --- a/core/shared/platform/darwin/bh_time.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_time.h" - -#include -#include -#include -#include - -/* - * This function returns milliseconds per tick. - * @return milliseconds per tick. - */ -uint64 _bh_time_get_tick_millisecond() -{ - return (uint64)sysconf(_SC_CLK_TCK); -} - -/* - * This function returns milliseconds after boot. - * @return milliseconds after boot. - */ -uint64 _bh_time_get_boot_millisecond() -{ - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - return 0; - } - - return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000); -} - -uint32 bh_get_tick_sec() -{ - return (uint32)(_bh_time_get_boot_millisecond() / 1000); -} - -/* - * This function returns GMT time milliseconds since from 1970.1.1, AKA UNIX time. - * @return milliseconds since from 1970.1.1. - */ -uint64 _bh_time_get_millisecond_from_1970() -{ - struct timeb tp; - ftime(&tp); - - return ((uint64) tp.time) * 1000 + tp.millitm - - (tp.dstflag == 0 ? 0 : 60 * 60 * 1000) - + ((uint64)tp.timezone) * 60 * 1000; -} - -size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time) -{ - time_t time_sec = (time_t)(time / 1000); - struct timeb tp; - struct tm *ltp; - - ftime(&tp); - time_sec -= tp.timezone * 60; - - ltp = localtime(&time_sec); - if (ltp == NULL) { - return 0; - } - return strftime(s, max, format, ltp); -} - diff --git a/core/shared/platform/linux-sgx/bh_platform_log.c b/core/shared/platform/darwin/platform_init.c similarity index 51% rename from core/shared/platform/linux-sgx/bh_platform_log.c rename to core/shared/platform/darwin/platform_init.c index 994cedfca..76594b816 100644 --- a/core/shared/platform/linux-sgx/bh_platform_log.c +++ b/core/shared/platform/darwin/platform_init.c @@ -3,15 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_platform.h" -#include +#include "platform_api_vmcore.h" -void bh_log_emit(const char *fmt, va_list ap) -{ - bh_vprintf_sgx(fmt, ap); -} - -int bh_fflush(void *stream) +int +bh_platform_init() { return 0; } + +void +bh_platform_destroy() +{ +} + diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h new file mode 100644 index 000000000..7d1e18a79 --- /dev/null +++ b/core/shared/platform/darwin/platform_internal.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_DARWIN +#define BH_PLATFORM_DARWIN +#endif + +#define _STACK_SIZE_ADJUSTMENT (32 * 1024) + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef pthread_t korp_tid; +typedef pthread_mutex_t korp_mutex; +typedef pthread_cond_t korp_cond; +typedef pthread_t korp_thread; + +#define os_printf printf +#define os_vprintf vprintf + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ + diff --git a/core/shared/platform/darwin/shared_platform.cmake b/core/shared/platform/darwin/shared_platform.cmake index 2fdc1330e..5eecd65c7 100644 --- a/core/shared/platform/darwin/shared_platform.cmake +++ b/core/shared/platform/darwin/shared_platform.cmake @@ -3,11 +3,16 @@ set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) +add_definitions(-DBH_PLATFORM_DARWIN) + include_directories(${PLATFORM_SHARED_DIR}) include_directories(${PLATFORM_SHARED_DIR}/../include) +include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) -set (PLATFORM_SHARED_SOURCE ${source_all}) +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE}) +file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) diff --git a/core/shared/platform/include/bh_assert.h b/core/shared/platform/include/bh_assert.h deleted file mode 100644 index 370f6cea8..000000000 --- a/core/shared/platform/include/bh_assert.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_ASSERT_H -#define _BH_ASSERT_H - -#include "bh_config.h" -#include "bh_platform.h" - -#ifdef BH_TEST -# ifndef BH_DEBUG -# error "BH_TEST should be defined under BH_DEBUG" -# endif -#endif - -#ifdef BH_TEST -# if defined(WIN32) || defined(__linux__) -# else -# error "Test case can not run on the current platform" -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef BH_DEBUG - -void bh_assert_internal(int v, const char *file_name, int line_number, - const char *expr_string); -#define bh_assert(expr) bh_assert_internal((int)(expr), __FILE__, __LINE__, #expr) - -void bh_debug_internal(const char *file_name, int line_number, - const char *fmt, ...); -#if defined(WIN32) - #define bh_debug(fmt, ...) bh_debug_internal(__FILE__, __LINE__, fmt, __VA_ARGS__) -#elif defined(__linux__) - #define bh_debug bh_debug_internal(__FILE__, __LINE__, "");printf -#else - #error "Unsupported platform" -#endif - -#else /* else of BH_DEBUG */ - -#define bh_debug if(0)printf - -#endif /* end of BH_DEBUG */ - -#ifdef BH_TEST - #define BH_STATIC -#else - #define BH_STATIC static -#endif /* end of BH_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/core/shared/platform/include/bh_config.h b/core/shared/platform/include/bh_config.h deleted file mode 100644 index ec4984133..000000000 --- a/core/shared/platform/include/bh_config.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -/** - * @file bh_config.h - * @date Tue Sep 13 14:53:17 2011 - * - * @brief Configurations for different platforms and targets. Make - * sure all source files in Beihai project include this header file - * directly or indirectly. - */ - -#ifndef BH_CONFIG - -#include "config.h" - -#define BH_KB (1024) -#define BH_MB ((BH_KB)*1024) -#define BH_GB ((BH_MB)*1024) - -#ifndef BH_MALLOC -#define BH_MALLOC os_malloc -#endif - -#ifndef BH_FREE -#define BH_FREE os_free -#endif - -#ifndef WA_MALLOC -#include -#define WA_MALLOC malloc -#endif - -#ifndef WA_FREE -#include -#define WA_FREE free -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -void *wasm_runtime_malloc(unsigned int size); -void wasm_runtime_free(void *ptr); - -#ifdef __cplusplus -} -#endif - -#endif /* end of BH_CONFIG */ - diff --git a/core/shared/platform/include/bh_thread.h b/core/shared/platform/include/bh_thread.h deleted file mode 100644 index 901e615eb..000000000 --- a/core/shared/platform/include/bh_thread.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_THREAD_H -#define _BH_THREAD_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "bh_config.h" -#include "bh_platform.h" - -#define BH_MAX_THREAD 32 -#define BH_MAX_TLS_NUM 2 - -#define BHT_ERROR (-1) -#define BHT_TIMED_OUT (1) -#define BHT_OK (0) - -#define BHT_NO_WAIT 0x00000000 -#define BHT_WAIT_FOREVER 0xFFFFFFFF - -/** - * vm_thread_sys_init - * initiation function for beihai thread system. Invoked at the beginning of beihai intiation. - * - * @return 0 if succuess. - */ -int _vm_thread_sys_init(void); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_thread_sys_init_instr(const char*func_name); -#define vm_thread_sys_init(void) vm_thread_sys_init_instr(__FUNCTION__) -#else -#define vm_thread_sys_init _vm_thread_sys_init -#endif - -void vm_thread_sys_destroy(void); - -/** - * This function creates a thread - * - * @param p_tid [OUTPUT] the pointer of tid - * @param start main routine of the thread - * @param arg argument passed to main routine - * @param stack_size bytes of stack size - * - * @return 0 if success. - */ -int _vm_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg, - unsigned int stack_size); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_thread_create_instr(korp_tid *p_tid, thread_start_routine_t start, void *arg, unsigned int stack_size, const char*func_name); -#define vm_thread_create(p_tid, start, arg, stack_size) vm_thread_create_instr(p_tid, start, arg, stack_size, __FUNCTION__) -#else -#define vm_thread_create _vm_thread_create -#endif - -/** - * This function creates a thread - * - * @param p_tid [OUTPUT] the pointer of tid - * @param start main routine of the thread - * @param arg argument passed to main routine - * @param stack_size bytes of stack size - * @param prio the priority - * - * @return 0 if success. - */ -int _vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_thread_create_with_prio_instr(korp_tid *p_tid, thread_start_routine_t start, void *arg, unsigned int stack_size, int prio, const char*func_name); -#define vm_thread_create_with_prio(p_tid, start, arg, stack_size) vm_thread_create_instr(p_tid, start, arg, stack_size, prio, __FUNCTION__) -#else -#define vm_thread_create_with_prio _vm_thread_create_with_prio -#endif - -/** - * This function never returns. - * - * @param code not used - */ -void vm_thread_exit(void *code); - -/** - * This function gets current thread id - * - * @return current thread id - */ -korp_tid _vm_self_thread(void); -#ifdef _INSTRUMENT_TEST_ENABLED -korp_tid vm_self_thread_instr(const char*func_name); -#define vm_self_thread(void) vm_self_thread_instr(__FUNCTION__) -#else -#define vm_self_thread _vm_self_thread -#endif - -/** - * This function saves a pointer in thread local storage. One thread can only save one pointer. - * - * @param idx tls array index - * @param ptr pointer need save as TLS - * - * @return 0 if success - */ -int _vm_tls_put(unsigned idx, void *ptr); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_tls_put_instr(unsigned idx, void *ptr, const char*func_name); -#define vm_tls_put(idx, ptr) vm_tls_put_instr(idx, ptr, __FUNCTION__) -#else -#define vm_tls_put _vm_tls_put -#endif - -/** - * This function gets a pointer saved in TLS. - * - * @param idx tls array index - * - * @return the pointer saved in TLS. - */ -void *_vm_tls_get(unsigned idx); -#ifdef _INSTRUMENT_TEST_ENABLED -void *vm_tls_get_instr(unsigned idx, const char*func_name); -#define vm_tls_get(idx) vm_tls_get_instr(idx, __FUNCTION__) -#else -#define vm_tls_get _vm_tls_get -#endif - -#define vm_thread_testcancel(void) - -/** - * This function creates a non-recursive mutex - * - * @param mutex [OUTPUT] pointer to mutex initialized. - * - * @return 0 if success - */ -int _vm_mutex_init(korp_mutex *mutex); -#ifdef INSTRUMENT_TEST_ENABLED -int vm_mutex_init_instr(korp_mutex *mutex, const char*func_name); -#define vm_mutex_init(mutex) vm_mutex_init_instr(mutex, __FUNCTION__) -#else -#define vm_mutex_init _vm_mutex_init -#endif - -/** - * This function creates a recursive mutex - * - * @param mutex [OUTPUT] pointer to mutex initialized. - * - * @return 0 if success - */ -int _vm_recursive_mutex_init(korp_mutex *mutex); -#ifdef INSTRUMENT_TEST_ENABLED -int vm_recursive_mutex_init_instr(korp_mutex *mutex, const char*func_name); -#define vm_recursive_mutex_init(mutex) vm_recursive_mutex_init_instr(mutex, __FUNCTION__) -#else -#define vm_recursive_mutex_init _vm_recursive_mutex_init -#endif - -/** - * This function destroys a mutex - * - * @param mutex pointer to mutex need destroy - * - * @return 0 if success - */ -int _vm_mutex_destroy(korp_mutex *mutex); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_mutex_destroy_instr(korp_mutex *mutex, const char*func_name); -#define vm_mutex_destroy(mutex) vm_mutex_destroy_instr(mutex, __FUNCTION__) -#else -#define vm_mutex_destroy _vm_mutex_destroy -#endif - -/** - * This function locks the mutex - * - * @param mutex pointer to mutex need lock - * - * @return Void - */ -void vm_mutex_lock(korp_mutex *mutex); - -/** - * This function locks the mutex without waiting - * - * @param mutex pointer to mutex need lock - * - * @return 0 if success - */ -int vm_mutex_trylock(korp_mutex *mutex); - -/** - * This function unlocks the mutex - * - * @param mutex pointer to mutex need unlock - * - * @return Void - */ -void vm_mutex_unlock(korp_mutex *mutex); - -/** - * This function creates a semaphone - * - * @param sem [OUTPUT] pointer to semaphone - * @param c counter of semaphone - * - * @return 0 if success - */ -int _vm_sem_init(korp_sem *sem, unsigned int c); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_sem_init_instr(korp_sem *sem, unsigned int c, const char*func_name); -#define vm_sem_init(sem, c) vm_sem_init_instr(sem, c, __FUNCTION__) -#else -#define vm_sem_init _vm_sem_init -#endif - -/** - * This function destroys a semaphone - * - * @param sem pointer to semaphone need destroy - * - * @return 0 if success - */ -int _vm_sem_destroy(korp_sem *sem); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_sem_destroy_instr(korp_sem *sem, const char*func_name); -#define vm_sem_destroy(sem) vm_sem_destroy_instr(sem, __FUNCTION__) -#else -#define vm_sem_destroy _vm_sem_destroy -#endif - -/** - * This function performs wait operation on semaphone - * - * @param sem pointer to semaphone need perform wait operation - * - * @return 0 if success - */ -int _vm_sem_wait(korp_sem *sem); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_sem_wait_instr(korp_sem *sem, const char*func_name); -#define vm_sem_wait(sem) vm_sem_wait_instr(sem, __FUNCTION__) -#else -#define vm_sem_wait _vm_sem_wait -#endif - -/** - * This function performs wait operation on semaphone with a timeout - * - * @param sem pointer to semaphone need perform wait operation - * @param mills wait milliseconds to return - * - * @return 0 if success - * @return BH_TIMEOUT if time out - */ -int _vm_sem_reltimedwait(korp_sem *sem, int mills); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_sem_reltimedwait_instr(korp_sem *sem, int mills, const char*func_name); -#define vm_sem_reltimedwait(sem, mills) vm_sem_reltimedwait_instr(sem, mills, __FUNCTION__) -#else -#define vm_sem_reltimedwait _vm_sem_reltimedwait -#endif - -/** - * This function performs post operation on semaphone - * - * @param sem pointer to semaphone need perform post operation - * - * @return 0 if success - */ -int _vm_sem_post(korp_sem *sem); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_sem_post_instr(korp_sem *sem, const char*func_name); -#define vm_sem_post(sem) vm_sem_post_instr(sem, __FUNCTION__) -#else -#define vm_sem_post _vm_sem_post -#endif - -/** - * This function creates a condition variable - * - * @param cond [OUTPUT] pointer to condition variable - * - * @return 0 if success - */ -int _vm_cond_init(korp_cond *cond); -#ifdef INSTRUMENT_TEST_ENABLED -int vm_cond_init_instr(korp_cond *cond, const char*func_name); -#define vm_cond_init(cond) vm_cond_init_instr(cond, __FUNCTION__) -#else -#define vm_cond_init _vm_cond_init -#endif - -/** - * This function destroys condition variable - * - * @param cond pointer to condition variable - * - * @return 0 if success - */ -int _vm_cond_destroy(korp_cond *cond); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_cond_destroy_instr(korp_cond *cond, const char*func_name); -#define vm_cond_destroy(cond) vm_cond_destroy_instr(cond, __FUNCTION__) -#else -#define vm_cond_destroy _vm_cond_destroy -#endif - -/** - * This function will block on a condition varible. - * - * @param cond pointer to condition variable - * @param mutex pointer to mutex to protect the condition variable - * - * @return 0 if success - */ -int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_cond_wait_instr(korp_cond *cond, korp_mutex *mutex, const char*func_name); -#define vm_cond_wait(cond, mutex) vm_cond_wait_instr(cond, mutex, __FUNCTION__) -#else -#define vm_cond_wait _vm_cond_wait -#endif - -/** - * This function will block on a condition varible or return if time specified passes. - * - * @param cond pointer to condition variable - * @param mutex pointer to mutex to protect the condition variable - * @param mills milliseconds to wait - * - * @return 0 if success - */ -int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_cond_reltimedwait_instr(korp_cond *cond, korp_mutex *mutex, int mills, const char*func_name); -#define vm_cond_reltimedwait(cond, mutex, mills) vm_cond_reltimedwait_instr(cond, mutex, mills, __FUNCTION__) -#else -#define vm_cond_reltimedwait _vm_cond_reltimedwait -#endif - -/** - * This function signals the condition variable - * - * @param cond condition variable - * - * @return 0 if success - */ -int _vm_cond_signal(korp_cond *cond); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_cond_signal_instr(korp_cond *cond, const char*func_name); -#define vm_cond_signal(cond) vm_cond_signal_instr(cond, __FUNCTION__) -#else -#define vm_cond_signal _vm_cond_signal -#endif - -int _vm_cond_broadcast(korp_cond *cond); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_cond_broadcast_instr(korp_cond *cond, const char*func_name); -#define vm_cond_broadcast(cond) vm_cond_broadcast_instr(cond, __FUNCTION__) -#else -#define vm_cond_broadcast _vm_cond_broadcast -#endif - -int _vm_thread_cancel(korp_tid thread); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_thread_cancel_instr(korp_tid thread, const char*func_name); -#define vm_thread_cancel(thread) vm_thread_cancel_instr(thread, __FUNCTION__) -#else -#define vm_thread_cancel _vm_thread_cancel -#endif - -int _vm_thread_join(korp_tid thread, void **value_ptr, int mills); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_thread_join_instr(korp_tid thread, void **value_ptr, int mills, const char*func_name); -#define vm_thread_join(thread, value_ptr, mills) vm_thread_join_instr(thread, value_ptr, mills, __FUNCTION__) -#else -#define vm_thread_join _vm_thread_join -#endif - -int _vm_thread_detach(korp_tid thread); -#ifdef _INSTRUMENT_TEST_ENABLED -int vm_thread_detach_instr(korp_tid thread, const char*func_name); -#define vm_thread_detach(thread) vm_thread_detach_instr(thread, __FUNCTION__) -#else -#define vm_thread_detach _vm_thread_detach -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* #ifndef _BH_THREAD_H */ diff --git a/core/shared/platform/include/bh_time.h b/core/shared/platform/include/bh_time.h deleted file mode 100644 index e2fafbd5e..000000000 --- a/core/shared/platform/include/bh_time.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_TIME_H -#define _BH_TIME_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "bh_config.h" -#include "bh_types.h" -#include "bh_platform.h" - -/* - * This function returns milliseconds per tick. - * @return milliseconds per tick. - */ -extern uint64 _bh_time_get_tick_millisecond(void); -#ifdef _INSTRUMENT_TEST_ENABLED -extern uint64 bh_time_get_tick_millisecond_instr(const char*func_name); -#define bh_time_get_tick_millisecond() bh_time_get_tick_millisecond_instr(__FUNCTION__) -#else -#define bh_time_get_tick_millisecond _bh_time_get_tick_millisecond -#endif - -/* - * This function returns milliseconds after boot. - * @return milliseconds after boot. - */ -extern uint64 _bh_time_get_boot_millisecond(void); -#ifdef _INSTRUMENT_TEST_ENABLED -extern uint64 bh_time_get_boot_millisecond_instr(const char*func_name); -#define bh_time_get_boot_millisecond() bh_time_get_boot_millisecond_instr(__FUNCTION__) -#else -#define bh_time_get_boot_millisecond _bh_time_get_boot_millisecond -#endif - -extern uint32 bh_get_tick_sec(); -#define bh_get_tick_ms _bh_time_get_boot_millisecond - -/* - * This function returns GMT milliseconds since from 1970.1.1, AKA UNIX time. - * @return milliseconds since from 1970.1.1. - */ -extern uint64 _bh_time_get_millisecond_from_1970(void); -#ifdef _INSTRUMENT_TEST_ENABLED -extern uint64 bh_time_get_millisecond_from_1970_instr(const char*func_name); -#define bh_time_get_millisecond_from_1970() bh_time_get_millisecond_from_1970_instr(__FUNCTION__) -#else -#define bh_time_get_millisecond_from_1970 _bh_time_get_millisecond_from_1970 -#endif - -/** - * This function sets timezone with specific hours. - * - * @param hours represents the deviation (in hours) of the local time from GMT (can be a positive or a negative number) - * @param half_hour if true, adds half an hour to the local time calculation. For example, if hours=(+5) then the time will be GMT +5:30; if hours=(-5) then the time will be GMT -4:30. - * @param daylight_save if true, applies the daylight saving scheme when calculating the local time (adds one hour to the local time calculation) - */ -extern void bh_set_timezone(int hours, int half_hour, int daylight_save); - -/** - * This functions returns the offset in seconds which needs to be added GMT to get the local time. - * - * - * @return offset in secords which needs to be added GMT to get the local time. - */ -extern int bh_get_timezone_offset(void); - -size_t bh_time_strftime(char *s, size_t max, const char *format, int64 time); - -#ifdef _INSTRUMENT_TEST_ENABLED -size_t bh_time_strftime_instr(char *s, size_t max, const char *format, int64 time, const char*func_name); -#define bh_time_strftime(s, max, format, time) bh_time_strftime_instr(s, max, format, time, __FUNCTION__) -#else -#define bh_time_strftime _bh_time_strftime -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/core/shared/platform/include/bh_types.h b/core/shared/platform/include/bh_types.h deleted file mode 100644 index 4c4214e0f..000000000 --- a/core/shared/platform/include/bh_types.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_TYPES_H -#define _BH_TYPES_H - -#include "bh_config.h" - -typedef unsigned char uint8; -typedef char int8; -typedef unsigned short uint16; -typedef short int16; -typedef unsigned int uint32; -typedef int int32; -typedef float float32; -typedef double float64; - -#include "bh_platform.h" - -#ifndef NULL -#define NULL (void*)0 -#endif - -#ifndef __cplusplus -#define true 1 -#define false 0 -#define inline __inline -#endif - -#endif - diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h new file mode 100644 index 000000000..d4553ae96 --- /dev/null +++ b/core/shared/platform/include/platform_api_extension.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef PLATFORM_API_EXTENSION_H +#define PLATFORM_API_EXTENSION_H + +#include "platform_common.h" +/** + * The related data structures should be defined + * in platform_internal.h + **/ +#include "platform_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************** + * * + * Extension interface * + * * + ***************************************************/ + +/** + * NOTES: + * 1. If you are building VM core only, it must be implemented to + * enable multi-thread support, otherwise no need to implement it + * 2. To build the app-mgr and app-framework, you must implement it + */ + + +/** + * Ceates a thread + * + * @param p_tid [OUTPUT] the pointer of tid + * @param start main routine of the thread + * @param arg argument passed to main routine + * @param stack_size bytes of stack size + * + * @return 0 if success. + */ +int os_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg, + unsigned int stack_size); + +/** + * Creates a thread with priority + * + * @param p_tid [OUTPUT] the pointer of tid + * @param start main routine of the thread + * @param arg argument passed to main routine + * @param stack_size bytes of stack size + * @param prio the priority + * + * @return 0 if success. + */ +int os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, + void *arg, unsigned int stack_size, int prio); + +/** + * Waits for the thread specified by thread to terminate + * + * @param thread the thread to wait + * @param retval if not NULL, output the exit status of the terminated thread + * + * @return return 0 if success + */ +int os_thread_join(korp_tid thread, void **retval); + +/** + * Suspend execution of the calling thread for (at least) + * usec microseconds + * + * @param return 0 if success, -1 otherwise + */ +int os_usleep(uint32 usec); + +/** + * Creates a recursive mutex + * + * @param mutex [OUTPUT] pointer to mutex initialized. + * + * @return 0 if success + */ +int os_recursive_mutex_init(korp_mutex *mutex); + +/** + * This function creates a condition variable + * + * @param cond [OUTPUT] pointer to condition variable + * + * @return 0 if success + */ +int os_cond_init(korp_cond *cond); + +/** + * This function destroys condition variable + * + * @param cond pointer to condition variable + * + * @return 0 if success + */ +int os_cond_destroy(korp_cond *cond); + +/** + * Wait a condition variable. + * + * @param cond pointer to condition variable + * @param mutex pointer to mutex to protect the condition variable + * + * @return 0 if success + */ +int os_cond_wait(korp_cond *cond, korp_mutex *mutex); + +/** + * Wait a condition varible or return if time specified passes. + * + * @param cond pointer to condition variable + * @param mutex pointer to mutex to protect the condition variable + * @param useconds microseconds to wait + * + * @return 0 if success + */ +int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds); + +/** + * Signals the condition variable + * + * @param cond condition variable + * + * @return 0 if success + */ +int os_cond_signal(korp_cond *cond); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef PLATFORM_API_EXTENSION_H */ diff --git a/core/shared/platform/include/platform_api_vmcore.h b/core/shared/platform/include/platform_api_vmcore.h new file mode 100644 index 000000000..2099a7507 --- /dev/null +++ b/core/shared/platform/include/platform_api_vmcore.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_API_VMCORE_H +#define _PLATFORM_API_VMCORE_H + +#include "platform_common.h" +#include "platform_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************************************** + * Section 1 * + * Interfaces required by the runtime * + ****************************************************/ + +/** + * Initialize the platform internal resources if needed, + * this function is called by wasm_runtime_init() and + * wasm_runtime_full_init() + * + * @return 0 if success + */ +int bh_platform_init(); + +/** + * Destroy the platform internal resources if needed, + * this function is called by wasm_runtime_destroy() + */ +void bh_platform_destroy(); + +/** + ******** memory allocator APIs ********** + */ + +void *os_malloc(unsigned size); + +void *os_realloc(void *ptr, unsigned size); + +void os_free(void *ptr); + +/** + * Note: the above APIs can simply return NULL if wasm runtime + * isn't initialized with Alloc_With_System_Allocator. + * Refer to wasm_runtime_full_init(). + */ + + +int os_printf(const char *format, ...); + +int os_vprintf(const char *format, va_list ap); + +/** + * Get microseconds after boot. + */ +uint64 os_time_get_boot_microsecond(void); + +/** + * Get current thread id. + * Implementation optional: Used by runtime for logging only. + */ +korp_tid os_self_thread(void); + +/** + ************** mutext APIs *********** + * vmcore: Not required until pthread is supported by runtime + * app-mgr: Must be implemented + */ + +int os_mutex_init(korp_mutex *mutex); + +int os_mutex_destroy(korp_mutex *mutex); + +void os_mutex_lock(korp_mutex *mutex); + +void os_mutex_unlock(korp_mutex *mutex); + + +/************************************************** + * Section 2 * + * APIs required by WAMR AOT * + **************************************************/ + +/* Memory map modes */ +enum { + MMAP_PROT_NONE = 0, + MMAP_PROT_READ = 1, + MMAP_PROT_WRITE = 2, + MMAP_PROT_EXEC = 4 +}; + +/* Memory map flags */ +enum { + MMAP_MAP_NONE = 0, + /* Put the mapping into 0 to 2 G, supported only on x86_64 */ + MMAP_MAP_32BIT = 1, + /* Don't interpret addr as a hint: place the mapping at exactly + that address. */ + MMAP_MAP_FIXED = 2 +}; + +void *os_mmap(void *hint, unsigned int size, int prot, int flags); +void os_munmap(void *addr, uint32 size); +int os_mprotect(void *addr, uint32 size, int prot); + +/** + * 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, + * which may cause unexpected behaviour when executing the AOT code. + * Implement this function if required, or just leave it empty. + */ +void os_dcache_flush(void); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef _PLATFORM_API_VMCORE_H */ diff --git a/core/shared/platform/include/platform_common.h b/core/shared/platform/include/platform_common.h new file mode 100644 index 000000000..60570d7c2 --- /dev/null +++ b/core/shared/platform/include/platform_common.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_COMMON_H +#define _PLATFORM_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../../config.h" +#include "platform_internal.h" + +#define BH_MAX_THREAD 32 + +#define BHT_ERROR (-1) +#define BHT_TIMED_OUT (1) +#define BHT_OK (0) + +#define BHT_NO_WAIT 0x00000000 +#define BHT_WAIT_FOREVER 0xFFFFFFFF + +#define BH_KB (1024) +#define BH_MB ((BH_KB)*1024) +#define BH_GB ((BH_MB)*1024) + +#ifndef BH_MALLOC +#define BH_MALLOC os_malloc +#endif + +#ifndef BH_FREE +#define BH_FREE os_free +#endif + +void *BH_MALLOC(unsigned int size); +void BH_FREE(void *ptr); + +#ifndef NULL +#define NULL (void*)0 +#endif + +#ifndef __cplusplus +#define true 1 +#define false 0 +#define inline __inline +#endif + +/* Return the offset of the given field in the given type */ +#ifndef offsetof +#define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) +#endif + +typedef uint8_t uint8; +typedef int8_t int8; +typedef uint16_t uint16; +typedef int16_t int16; +typedef uint32_t uint32; +typedef int32_t int32; +typedef float float32; +typedef double float64; +typedef uint64_t uint64; +typedef int64_t int64; + +typedef void* (*thread_start_routine_t)(void*); + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef _PLATFORM_COMMON_H */ diff --git a/core/shared/platform/linux-sgx/bh_assert.c b/core/shared/platform/linux-sgx/bh_assert.c deleted file mode 100644 index fa378c5e7..000000000 --- a/core/shared/platform/linux-sgx/bh_assert.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_assert.h" -#include -#include -#include - -#ifdef BH_TEST -#include -#endif - -#ifdef BH_TEST -/* for exception throwing */ -jmp_buf bh_test_jb; -#endif -#define FIXED_BUFFER_SIZE (1<<9) - -void bh_assert_internal(int v, const char *file_name, int line_number, - const char *expr_string) -{ - if (v) - return; - - if (!file_name) - file_name = "NULL FILENAME"; - if (!expr_string) - expr_string = "NULL EXPR_STRING"; - - bh_printf_sgx("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string, - file_name, line_number); - -#ifdef BH_TEST - longjmp(bh_test_jb, 1); -#endif - - abort(); -} - -void bh_debug_internal(const char *file_name, int line_number, const char *fmt, - ...) -{ -#ifndef JEFF_TEST_VERIFIER - va_list args; - char msg[FIXED_BUFFER_SIZE] = { '\0' }; - - va_start(args, fmt); - vsnprintf(msg, FIXED_BUFFER_SIZE, fmt, args); - va_end(args); - bh_printf_sgx("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number); - bh_printf_sgx(msg); - bh_printf_sgx("\n"); -#endif -} - diff --git a/core/shared/platform/linux-sgx/bh_platform.h b/core/shared/platform/linux-sgx/bh_platform.h deleted file mode 100644 index ab479e3da..000000000 --- a/core/shared/platform/linux-sgx/bh_platform.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_PLATFORM_H -#define _BH_PLATFORM_H - -#include "bh_config.h" -#include "bh_types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*bh_print_function_t)(const char* message); -void bh_set_print_function(bh_print_function_t pf); - -extern int bh_printf_sgx(const char *message, ...); -extern int bh_vprintf_sgx(const char * format, va_list arg); - -typedef uint64_t uint64; -typedef int64_t int64; - -#ifndef BH_PLATFORM_LINUX_SGX -#define BH_PLATFORM_LINUX_SGX -#endif - -/* NEED qsort */ - -#define _STACK_SIZE_ADJUSTMENT (32 * 1024) - -/* Stack size of applet threads's native part. */ -#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) - -/* Default thread priority */ -#define BH_THREAD_DEFAULT_PRIORITY 0 - -#define BH_ROUTINE_MODIFIER - -#define BHT_TIMEDOUT ETIMEDOUT - -#define INVALID_THREAD_ID 0xFFffFFff - -typedef int korp_sem; -typedef void* (*thread_start_routine_t)(void*); -typedef sgx_thread_mutex_t korp_mutex; -typedef sgx_thread_t korp_tid; -typedef sgx_thread_t korp_thread; -typedef sgx_thread_cond_t korp_cond; - -void *os_malloc(unsigned size); -void *os_realloc(void *ptr, unsigned size); -void os_free(void *ptr); - -#define bh_printf bh_printf_sgx - -int snprintf(char *buffer, size_t count, const char *format, ...); -int strncasecmp(const char *s1, const char *s2, size_t n); -double fmod(double x, double y); -float fmodf(float x, float y); -double sqrt(double x); - -#define BH_WAIT_FOREVER 0xFFFFFFFF - -#ifndef NULL -# define NULL ((void*) 0) -#endif - -/** - * Return the offset of the given field in the given type. - * - * @param Type the type containing the filed - * @param field the field in the type - * - * @return the offset of field in Type - */ -#ifndef offsetof -#define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) -#endif - -#define bh_assert assert - -int bh_platform_init(); - -/* MMAP mode */ -enum { - MMAP_PROT_NONE = 0, - MMAP_PROT_READ = 1, - MMAP_PROT_WRITE = 2, - MMAP_PROT_EXEC = 4 -}; - -/* MMAP flags */ -enum { - MMAP_MAP_NONE = 0, - /* Put the mapping into 0 to 2 G, supported only on x86_64 */ - MMAP_MAP_32BIT = 1, - /* Don't interpret addr as a hint: place the mapping at exactly - that address. */ - MMAP_MAP_FIXED = 2 -}; - -void *bh_mmap(void *hint, unsigned int size, int prot, int flags); -void bh_munmap(void *addr, uint32 size); -int bh_mprotect(void *addr, uint32 size, int prot); -#define bh_dcache_flush() (void)0 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/core/shared/platform/linux-sgx/bh_thread.c b/core/shared/platform/linux-sgx/bh_thread.c deleted file mode 100644 index a2a76c3ca..000000000 --- a/core/shared/platform/linux-sgx/bh_thread.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_thread.h" -#include "bh_assert.h" -#include -#include -#include - -int _vm_thread_sys_init() -{ - return 0; -} - -void vm_thread_sys_destroy(void) -{ -} - -int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) -{ - return BHT_ERROR; - // return BHT_OK; -} - -int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) -{ - return _vm_thread_create_with_prio(tid, start, arg, stack_size, - BH_THREAD_DEFAULT_PRIORITY); -} - -korp_tid _vm_self_thread() -{ - return sgx_thread_self(); -} - -void vm_thread_exit(void * code) -{ -} - -// storage for one thread -static __thread void *_tls_store = NULL; - -void *_vm_tls_get(unsigned idx) -{ - return _tls_store; -} - -int _vm_tls_put(unsigned idx, void * tls) -{ - _tls_store = tls; - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_mutex_init(korp_mutex *mutex) -{ - sgx_thread_mutex_t m = SGX_THREAD_MUTEX_INITIALIZER; - *mutex = m; - return BHT_OK; -} - -int _vm_recursive_mutex_init(korp_mutex *mutex) -{ - sgx_thread_mutex_t m = SGX_THREAD_RECURSIVE_MUTEX_INITIALIZER; - *mutex = m; - return BHT_OK; -} - -int _vm_mutex_destroy(korp_mutex *mutex) -{ - sgx_thread_mutex_destroy(mutex); - return BHT_OK; -} - -/* Returned error (EINVAL, EAGAIN and EDEADLK) from - locking the mutex indicates some logic error present in - the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_lock(korp_mutex *mutex) -{ - sgx_thread_mutex_lock(mutex); -} - -int vm_mutex_trylock(korp_mutex *mutex) -{ - return (sgx_thread_mutex_trylock(mutex) == 0? BHT_OK: BHT_ERROR); -} - -/* Returned error (EINVAL, EAGAIN and EPERM) from - unlocking the mutex indicates some logic error present - in the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_unlock(korp_mutex *mutex) -{ - sgx_thread_mutex_unlock(mutex); -} - -int _vm_sem_init(korp_sem* sem, unsigned int c) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_sem_destroy(korp_sem *sem) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_sem_wait(korp_sem *sem) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_sem_reltimedwait(korp_sem *sem, int mills) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_sem_post(korp_sem *sem) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_cond_init(korp_cond *cond) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_cond_destroy(korp_cond *cond) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_cond_signal(korp_cond *cond) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_cond_broadcast(korp_cond *cond) -{ - return BHT_OK; - //return BHT_ERROR; -} - -int _vm_thread_cancel(korp_tid thread) -{ - return 0; -} - -int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) -{ - return 0; -} - -int _vm_thread_detach(korp_tid thread) -{ - return 0; -} diff --git a/core/shared/platform/linux-sgx/bh_time.c b/core/shared/platform/linux-sgx/bh_time.c deleted file mode 100644 index 189e668d4..000000000 --- a/core/shared/platform/linux-sgx/bh_time.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_time.h" - -#include -#include -#include - -/* - * This function returns milliseconds per tick. - * @return milliseconds per tick. - */ -uint64 _bh_time_get_tick_millisecond() -{ - //TODO: - return 0; -} - -/* - * This function returns milliseconds after boot. - * @return milliseconds after boot. - */ -uint64 _bh_time_get_boot_millisecond() -{ - //TODO - return 0; -} - -uint32 bh_get_tick_sec() -{ - //TODO - return 0; -} - -/* - * This function returns GMT time milliseconds since from 1970.1.1, AKA UNIX time. - * @return milliseconds since from 1970.1.1. - */ -uint64 _bh_time_get_millisecond_from_1970() -{ - //TODO - return 0; -} - -size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time) -{ - //TODO - return 0; -} - diff --git a/core/shared/platform/linux-sgx/platform_internal.h b/core/shared/platform/linux-sgx/platform_internal.h new file mode 100644 index 000000000..c493db0f5 --- /dev/null +++ b/core/shared/platform/linux-sgx/platform_internal.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_LINUX_SGX +#define BH_PLATFORM_LINUX_SGX +#endif + +#define _STACK_SIZE_ADJUSTMENT (32 * 1024) + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef sgx_thread_t korp_thread; +typedef sgx_thread_t korp_tid; +typedef sgx_thread_mutex_t korp_mutex; +typedef sgx_thread_cond_t korp_cond; + +typedef void (*os_print_function_t)(const char* message); +void os_set_print_function(os_print_function_t pf); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ + diff --git a/core/shared/platform/linux-sgx/bh_platform.c b/core/shared/platform/linux-sgx/sgx_platform.c similarity index 73% rename from core/shared/platform/linux-sgx/bh_platform.c rename to core/shared/platform/linux-sgx/sgx_platform.c index 8b742c6d0..08aa37c36 100644 --- a/core/shared/platform/linux-sgx/bh_platform.c +++ b/core/shared/platform/linux-sgx/sgx_platform.c @@ -3,22 +3,27 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_common.h" -#include "bh_platform.h" +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" -#include #if WASM_ENABLE_AOT != 0 #include "sgx_rsrv_mem_mngr.h" #endif #define FIXED_BUFFER_SIZE (1<<9) -static bh_print_function_t print_function = NULL; + +static os_print_function_t print_function = NULL; int bh_platform_init() { return 0; } +void +bh_platform_destroy() +{ +} + void * os_malloc(unsigned size) { @@ -47,12 +52,12 @@ int puts(const char *s) return 0; } -void bh_set_print_function(bh_print_function_t pf) +void os_set_print_function(os_print_function_t pf) { print_function = pf; } -int bh_printf_sgx(const char *message, ...) +int os_printf(const char *message, ...) { if (print_function != NULL) { char msg[FIXED_BUFFER_SIZE] = { '\0' }; @@ -66,7 +71,7 @@ int bh_printf_sgx(const char *message, ...) return 0; } -int bh_vprintf_sgx(const char * format, va_list arg) +int os_vprintf(const char * format, va_list arg) { if (print_function != NULL) { char msg[FIXED_BUFFER_SIZE] = { '\0' }; @@ -77,7 +82,7 @@ int bh_vprintf_sgx(const char * format, va_list arg) return 0; } -void* bh_mmap(void *hint, unsigned int size, int prot, int flags) +void* os_mmap(void *hint, unsigned int size, int prot, int flags) { #if WASM_ENABLE_AOT != 0 int mprot = 0; @@ -87,7 +92,7 @@ void* bh_mmap(void *hint, unsigned int size, int prot, int flags) ret = sgx_alloc_rsrv_mem(alignedSize); if (ret == NULL) { - bh_printf_sgx("bh_mmap(size=%d, alignedSize=%d, prot=0x%x) failed.",size, alignedSize, prot); + os_printf("os_mmap(size=%d, alignedSize=%d, prot=0x%x) failed.",size, alignedSize, prot); return NULL; } if (prot & MMAP_PROT_READ) @@ -98,7 +103,7 @@ void* bh_mmap(void *hint, unsigned int size, int prot, int flags) mprot |= SGX_PROT_EXEC; st = sgx_tprotect_rsrv_mem(ret, alignedSize, mprot); if (st != SGX_SUCCESS){ - bh_printf_sgx("bh_mmap(size=%d,prot=0x%x) failed to set protect.",size, prot); + os_printf("os_mmap(size=%d,prot=0x%x) failed to set protect.",size, prot); sgx_free_rsrv_mem(ret, alignedSize); return NULL; } @@ -109,14 +114,14 @@ void* bh_mmap(void *hint, unsigned int size, int prot, int flags) #endif } -void bh_munmap(void *addr, uint32 size) +void os_munmap(void *addr, uint32 size) { #if WASM_ENABLE_AOT != 0 sgx_free_rsrv_mem(addr, size); #endif } -int bh_mprotect(void *addr, uint32 size, int prot) +int os_mprotect(void *addr, uint32 size, int prot) { #if WASM_ENABLE_AOT != 0 int mprot = 0; @@ -129,10 +134,17 @@ int bh_mprotect(void *addr, uint32 size, int prot) if (prot & MMAP_PROT_EXEC) mprot |= SGX_PROT_EXEC; st = sgx_tprotect_rsrv_mem(addr, size, mprot); - if (st != SGX_SUCCESS) bh_printf_sgx("bh_mprotect(addr=0x%lx,size=%d,prot=0x%x) failed.", addr, size, prot); + if (st != SGX_SUCCESS) + os_printf("os_mprotect(addr=0x%lx,size=%d,prot=0x%x) failed.", addr, size, prot); return (st == SGX_SUCCESS? 0:-1); #else return -1; #endif } + +void +os_dcache_flush(void) +{ +} + diff --git a/core/shared/platform/linux-sgx/sgx_thread.c b/core/shared/platform/linux-sgx/sgx_thread.c new file mode 100644 index 000000000..c7fa01ff8 --- /dev/null +++ b/core/shared/platform/linux-sgx/sgx_thread.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +korp_tid os_self_thread() +{ + return sgx_thread_self(); +} + +int os_mutex_init(korp_mutex *mutex) +{ + sgx_thread_mutex_t m = SGX_THREAD_MUTEX_INITIALIZER; + *mutex = m; + return BHT_OK; +} + +int os_mutex_destroy(korp_mutex *mutex) +{ + sgx_thread_mutex_destroy(mutex); + return BHT_OK; +} + +void os_mutex_lock(korp_mutex *mutex) +{ + sgx_thread_mutex_lock(mutex); +} + +void os_mutex_unlock(korp_mutex *mutex) +{ + sgx_thread_mutex_unlock(mutex); +} + +int os_cond_init(korp_cond *cond) +{ + sgx_thread_cond_t c = SGX_THREAD_COND_INITIALIZER; + *cond = c; + return BHT_OK; +} + +int os_cond_destroy(korp_cond *cond) +{ + sgx_thread_cond_destroy(cond); + return BHT_OK; +} + diff --git a/core/shared/platform/linux-sgx/sgx_time.c b/core/shared/platform/linux-sgx/sgx_time.c new file mode 100644 index 000000000..2094d4b17 --- /dev/null +++ b/core/shared/platform/linux-sgx/sgx_time.c @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +uint64 +os_time_get_boot_microsecond() +{ + /* TODO */ + return 0; +} + diff --git a/core/shared/platform/linux-sgx/shared_platform.cmake b/core/shared/platform/linux-sgx/shared_platform.cmake index 2fdc1330e..dd1303ed4 100644 --- a/core/shared/platform/linux-sgx/shared_platform.cmake +++ b/core/shared/platform/linux-sgx/shared_platform.cmake @@ -3,6 +3,8 @@ set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) +add_definitions(-DBH_PLATFORM_LINUX_SGX) + include_directories(${PLATFORM_SHARED_DIR}) include_directories(${PLATFORM_SHARED_DIR}/../include) diff --git a/core/shared/platform/linux/bh_assert.c b/core/shared/platform/linux/bh_assert.c deleted file mode 100644 index c609fb93d..000000000 --- a/core/shared/platform/linux/bh_assert.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_assert.h" -#include -#include -#include - -#ifdef BH_TEST -#include -#endif - -#ifdef BH_TEST -/* for exception throwing */ -jmp_buf bh_test_jb; -#endif - -void bh_assert_internal(int v, const char *file_name, int line_number, - const char *expr_string) -{ - if (v) - return; - - if (!file_name) - file_name = "NULL FILENAME"; - if (!expr_string) - expr_string = "NULL EXPR_STRING"; - - printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string, - file_name, line_number); - -#ifdef BH_TEST - longjmp(bh_test_jb, 1); -#endif - - abort(); -} - -void bh_debug_internal(const char *file_name, int line_number, const char *fmt, - ...) -{ -#ifndef JEFF_TEST_VERIFIER - va_list args; - - va_start(args, fmt); - bh_assert(file_name); - - printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number); - vprintf(fmt, args); - - va_end(args); - printf("\n"); -#endif -} - diff --git a/core/shared/platform/linux/bh_platform.c b/core/shared/platform/linux/bh_platform.c deleted file mode 100755 index 1831e9502..000000000 --- a/core/shared/platform/linux/bh_platform.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_common.h" -#include "bh_assert.h" - -#include -#include -#include -#include - -int -bh_platform_init() -{ - return 0; -} - -void * -os_malloc(unsigned size) -{ - return malloc(size); -} - -void * -os_realloc(void *ptr, unsigned size) -{ - return realloc(ptr, size); -} - -void -os_free(void *ptr) -{ - free(ptr); -} - -char* -bh_read_file_to_buffer(const char *filename, uint32 *ret_size) -{ - char *buffer; - int file; - uint32 file_size, read_size; - struct stat stat_buf; - - if (!filename || !ret_size) { - printf("Read file to buffer failed: invalid filename or ret size.\n"); - return NULL; - } - - if ((file = open(filename, O_RDONLY, 0)) == -1) { - printf("Read file to buffer failed: open file %s failed.\n", - filename); - return NULL; - } - - if (fstat(file, &stat_buf) != 0) { - printf("Read file to buffer failed: fstat file %s failed.\n", - filename); - close(file); - return NULL; - } - - file_size = (uint32)stat_buf.st_size; - - if (!(buffer = BH_MALLOC(file_size))) { - printf("Read file to buffer failed: alloc memory failed.\n"); - close(file); - return NULL; - } - - read_size = (uint32)read(file, buffer, file_size); - close(file); - - if (read_size < file_size) { - printf("Read file to buffer failed: read file content failed.\n"); - BH_FREE(buffer); - return NULL; - } - - *ret_size = file_size; - return buffer; -} - -void * -bh_mmap(void *hint, uint32 size, int prot, int flags) -{ - int map_prot = PROT_NONE; - int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; - uint64 request_size, page_size; - uint8 *addr, *addr_aligned; - uint32 i; - - /* align to 2M if no less than 2M, else align to 4K */ - page_size = size < 2 * 1024 * 1024 ? 4096 : 2 * 1024 * 1024; - request_size = (size + page_size - 1) & ~(page_size - 1); - request_size += page_size; - - if (request_size >= UINT32_MAX) - return NULL; - - if (prot & MMAP_PROT_READ) - map_prot |= PROT_READ; - - if (prot & MMAP_PROT_WRITE) - map_prot |= PROT_WRITE; - - if (prot & MMAP_PROT_EXEC) - map_prot |= PROT_EXEC; - -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) - if (flags & MMAP_MAP_32BIT) - map_flags |= MAP_32BIT; -#endif - - if (flags & MMAP_MAP_FIXED) - map_flags |= MAP_FIXED; - - /* try 5 times */ - for (i = 0; i < 5; i ++) { - addr = mmap(hint, size, map_prot, map_flags, -1, 0); - if (addr != MAP_FAILED) - break; - } - if (addr == MAP_FAILED) - return NULL; - - addr_aligned = (uint8*)(uintptr_t) - (((uint64)(uintptr_t)addr + page_size - 1) & ~(page_size - 1)); - - /* Unmap memory allocated before the aligned base address */ - if (addr != addr_aligned) { - uint32 prefix_size = (uint32)(addr_aligned - addr); - munmap(addr, prefix_size); - request_size -= prefix_size; - } - - /* Unmap memory allocated after the potentially unaligned end */ - if (size != request_size) { - uint32 suffix_size = (uint32)(request_size - size); - munmap(addr_aligned + size, suffix_size); - request_size -= size; - } - - if (size >= 2 * 1024 * 1024) { - /* Try to use huge page to improve performance */ - if (!madvise(addr, size, MADV_HUGEPAGE)) - /* make huge page become effective */ - memset(addr, 0, size); - } - - return addr_aligned; -} - -void -bh_munmap(void *addr, uint32 size) -{ - if (addr) - munmap(addr, size); -} - -int -bh_mprotect(void *addr, uint32 size, int prot) -{ - int map_prot = PROT_NONE; - - if (!addr) - return 0; - - if (prot & MMAP_PROT_READ) - map_prot |= PROT_READ; - - if (prot & MMAP_PROT_WRITE) - map_prot |= PROT_WRITE; - - if (prot & MMAP_PROT_EXEC) - map_prot |= PROT_EXEC; - - return mprotect(addr, size, map_prot); -} - diff --git a/core/shared/platform/linux/bh_platform.h b/core/shared/platform/linux/bh_platform.h deleted file mode 100644 index e73b3d965..000000000 --- a/core/shared/platform/linux/bh_platform.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_PLATFORM_H -#define _BH_PLATFORM_H - -#include "bh_config.h" -#include "bh_types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint64_t uint64; -typedef int64_t int64; - -extern void DEBUGME(void); - -#define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0) - -#ifndef BH_PLATFORM_LINUX -#define BH_PLATFORM_LINUX -#endif - -/* NEED qsort */ - -#define _STACK_SIZE_ADJUSTMENT (32 * 1024) - -/* Stack size of applet threads's native part. */ -#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) - -/* Default thread priority */ -#define BH_THREAD_DEFAULT_PRIORITY 0 - -#define BH_ROUTINE_MODIFIER - -#define BHT_TIMEDOUT ETIMEDOUT - -#define INVALID_THREAD_ID 0xFFffFFff - -typedef pthread_t korp_tid; -typedef pthread_mutex_t korp_mutex; -typedef sem_t korp_sem; -typedef pthread_cond_t korp_cond; -typedef pthread_t korp_thread; -typedef void* (*thread_start_routine_t)(void*); - -void *os_malloc(unsigned size); -void *os_realloc(void *ptr, unsigned size); -void os_free(void *ptr); - -#define bh_printf printf - -int snprintf(char *buffer, size_t count, const char *format, ...); -double fmod(double x, double y); -float fmodf(float x, float y); -double sqrt(double x); - -#define BH_WAIT_FOREVER 0xFFFFFFFF - -#ifndef NULL -# define NULL ((void*) 0) -#endif - -/** - * Return the offset of the given field in the given type. - * - * @param Type the type containing the filed - * @param field the field in the type - * - * @return the offset of field in Type - */ -#ifndef offsetof -#define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) -#endif - -#define bh_assert assert - -char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); - -int bh_platform_init(); - -/* MMAP mode */ -enum { - MMAP_PROT_NONE = 0, - MMAP_PROT_READ = 1, - MMAP_PROT_WRITE = 2, - MMAP_PROT_EXEC = 4 -}; - -/* MMAP flags */ -enum { - MMAP_MAP_NONE = 0, - /* Put the mapping into 0 to 2 G, supported only on x86_64 */ - MMAP_MAP_32BIT = 1, - /* Don't interpret addr as a hint: place the mapping at exactly - that address. */ - MMAP_MAP_FIXED = 2 -}; - -void *bh_mmap(void *hint, unsigned int size, int prot, int flags); -void bh_munmap(void *addr, uint32 size); -int bh_mprotect(void *addr, uint32 size, int prot); -#define bh_dcache_flush() (void)0 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/core/shared/platform/linux/bh_platform_log.c b/core/shared/platform/linux/bh_platform_log.c deleted file mode 100644 index 902ca7d60..000000000 --- a/core/shared/platform/linux/bh_platform_log.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include - -void bh_log_emit(const char *fmt, va_list ap) -{ - vprintf(fmt, ap); - fflush(stdout); -} - -int bh_fprintf(FILE *stream, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = vfprintf(stream ? stream : stdout, fmt, ap); - va_end(ap); - - return ret; -} - -int bh_fflush(void *stream) -{ - return fflush(stream ? stream : stdout); -} diff --git a/core/shared/platform/linux/bh_thread.c b/core/shared/platform/linux/bh_thread.c deleted file mode 100755 index 199809900..000000000 --- a/core/shared/platform/linux/bh_thread.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_thread.h" -#include "bh_assert.h" -#include "bh_log.h" -#include -#include -#include - -static bool is_thread_sys_inited = false; - -static korp_mutex thread_list_lock; -static pthread_key_t thread_local_storage_key[BH_MAX_TLS_NUM]; - -int _vm_thread_sys_init() -{ - unsigned i, j; - int ret; - - if (is_thread_sys_inited) - return 0; - - for (i = 0; i < BH_MAX_TLS_NUM; i++) { - ret = pthread_key_create(&thread_local_storage_key[i], NULL); - if (ret) - goto fail; - } - - ret = vm_mutex_init(&thread_list_lock); - if (ret) - goto fail; - - is_thread_sys_inited = true; - return 0; - - fail: for (j = 0; j < i; j++) - pthread_key_delete(thread_local_storage_key[j]); - return -1; -} - -void vm_thread_sys_destroy(void) -{ - if (is_thread_sys_inited) { - unsigned i; - for (i = 0; i < BH_MAX_TLS_NUM; i++) - pthread_key_delete(thread_local_storage_key[i]); - vm_mutex_destroy(&thread_list_lock); - is_thread_sys_inited = false; - } -} - -typedef struct { - thread_start_routine_t start; - void* stack; - uint32 stack_size; - void* arg; -} thread_wrapper_arg; - -static void *vm_thread_wrapper(void *arg) -{ - thread_wrapper_arg * targ = arg; - LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ); - targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); - _vm_tls_put(1, targ); - targ->start(targ->arg); - BH_FREE(targ); - _vm_tls_put(1, NULL); - return NULL; -} - -int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) -{ - pthread_attr_t tattr; - thread_wrapper_arg *targ; - - bh_assert(stack_size > 0); - bh_assert(tid); - bh_assert(start); - - *tid = INVALID_THREAD_ID; - - pthread_attr_init(&tattr); - pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); - if (pthread_attr_setstacksize(&tattr, stack_size) != 0) { - bh_debug("Invalid thread stack size %u. Min stack size on Linux = %u", - stack_size, PTHREAD_STACK_MIN); - pthread_attr_destroy(&tattr); - return BHT_ERROR; - } - - targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ)); - if (!targ) { - pthread_attr_destroy(&tattr); - return BHT_ERROR; - } - - targ->start = start; - targ->arg = arg; - targ->stack_size = stack_size; - - if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) { - pthread_attr_destroy(&tattr); - BH_FREE(targ); - return BHT_ERROR; - } - - pthread_attr_destroy(&tattr); - return BHT_OK; -} - -int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) -{ - return _vm_thread_create_with_prio(tid, start, arg, stack_size, - BH_THREAD_DEFAULT_PRIORITY); -} - -korp_tid _vm_self_thread() -{ - return (korp_tid) pthread_self(); -} - -void vm_thread_exit(void * code) -{ - BH_FREE(_vm_tls_get(1)); - _vm_tls_put(1, NULL); - pthread_exit(code); -} - -void *_vm_tls_get(unsigned idx) -{ - bh_assert(idx < BH_MAX_TLS_NUM); - return pthread_getspecific(thread_local_storage_key[idx]); -} - -int _vm_tls_put(unsigned idx, void * tls) -{ - bh_assert(idx < BH_MAX_TLS_NUM); - pthread_setspecific(thread_local_storage_key[idx], tls); - return BHT_OK; -} - -int _vm_mutex_init(korp_mutex *mutex) -{ - return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_recursive_mutex_init(korp_mutex *mutex) -{ - int ret; - - pthread_mutexattr_t mattr; - - bh_assert(mutex); - ret = pthread_mutexattr_init(&mattr); - if (ret) - return BHT_ERROR; - - pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE_NP); - ret = pthread_mutex_init(mutex, &mattr); - pthread_mutexattr_destroy(&mattr); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_mutex_destroy(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_destroy(mutex); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -/* Returned error (EINVAL, EAGAIN and EDEADLK) from - locking the mutex indicates some logic error present in - the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_lock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_lock(mutex); - if (0 != ret) { - printf("vm mutex lock failed (ret=%d)!\n", ret); - exit(-1); - } -} - -int vm_mutex_trylock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_trylock(mutex); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -/* Returned error (EINVAL, EAGAIN and EPERM) from - unlocking the mutex indicates some logic error present - in the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_unlock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_unlock(mutex); - if (0 != ret) { - printf("vm mutex unlock failed (ret=%d)!\n", ret); - exit(-1); - } -} - -int _vm_sem_init(korp_sem* sem, unsigned int c) -{ - int ret; - - bh_assert(sem); - ret = sem_init(sem, 0, c); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_destroy(korp_sem *sem) -{ - int ret; - - bh_assert(sem); - ret = sem_destroy(sem); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_wait(korp_sem *sem) -{ - int ret; - - bh_assert(sem); - - ret = sem_wait(sem); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_reltimedwait(korp_sem *sem, int mills) -{ - int ret = BHT_OK; - - struct timespec timeout; - const int mills_per_sec = 1000; - const int mills_to_nsec = 1E6; - - bh_assert(sem); - - if (mills == (int)BHT_WAIT_FOREVER) { - ret = sem_wait(sem); - } else { - - timeout.tv_sec = mills / mills_per_sec; - timeout.tv_nsec = (mills % mills_per_sec) * mills_to_nsec; - timeout.tv_sec += time(NULL); - - ret = sem_timedwait(sem, &timeout); - } - - if (ret != BHT_OK) { - if (errno == BHT_TIMEDOUT) { - ret = BHT_TIMEDOUT; - errno = 0; - } else { - bh_debug("Faliure happens when timed wait is called"); - bh_assert(0); - } - } - - return ret; -} - -int _vm_sem_post(korp_sem *sem) -{ - bh_assert(sem); - - return sem_post(sem) == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_cond_init(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_init(cond, NULL) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_destroy(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_destroy(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex) -{ - bh_assert(cond); - bh_assert(mutex); - - if (pthread_cond_wait(cond, mutex) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - ts->tv_sec = (long int)(tv.tv_sec + msec / 1000); - ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec); - - if (ts->tv_nsec >= 1000000000L) { - ts->tv_sec++; - ts->tv_nsec -= 1000000000L; - } -} - -int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) -{ - int ret; - struct timespec abstime; - - if (mills == (int)BHT_WAIT_FOREVER) - ret = pthread_cond_wait(cond, mutex); - else { - msec_nsec_to_abstime(&abstime, mills, 0); - ret = pthread_cond_timedwait(cond, mutex, &abstime); - } - - if (ret != BHT_OK && ret != BHT_TIMEDOUT) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_signal(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_signal(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_broadcast(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_broadcast(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_thread_cancel(korp_tid thread) -{ - return pthread_cancel(thread); -} - -int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) -{ - return pthread_join(thread, value_ptr); -} - -int _vm_thread_detach(korp_tid thread) -{ - return pthread_detach(thread); -} - diff --git a/core/shared/platform/linux/bh_time.c b/core/shared/platform/linux/bh_time.c deleted file mode 100755 index 698cdec24..000000000 --- a/core/shared/platform/linux/bh_time.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_time.h" - -#include -#include -#include -#include - -/* - * This function returns milliseconds per tick. - * @return milliseconds per tick. - */ -uint64 _bh_time_get_tick_millisecond() -{ - return (uint64)sysconf(_SC_CLK_TCK); -} - -/* - * This function returns milliseconds after boot. - * @return milliseconds after boot. - */ -uint64 _bh_time_get_boot_millisecond() -{ - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - return 0; - } - - return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000); -} - -uint32 bh_get_tick_sec() -{ - return (uint32)(_bh_time_get_boot_millisecond() / 1000); -} - -/* - * This function returns GMT time milliseconds since from 1970.1.1, AKA UNIX time. - * @return milliseconds since from 1970.1.1. - */ -uint64 _bh_time_get_millisecond_from_1970() -{ - struct timeb tp; - ftime(&tp); - - return ((uint64) tp.time) * 1000 + tp.millitm - - (tp.dstflag == 0 ? 0 : 60 * 60 * 1000) - + ((uint64)tp.timezone) * 60 * 1000; -} - -size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time) -{ - time_t time_sec = (time_t)(time / 1000); - struct timeb tp; - struct tm *ltp; - - ftime(&tp); - time_sec -= tp.timezone * 60; - - ltp = localtime(&time_sec); - if (ltp == NULL) { - return 0; - } - return strftime(s, max, format, ltp); -} - diff --git a/core/shared/platform/linux/platform_init.c b/core/shared/platform/linux/platform_init.c new file mode 100644 index 000000000..76594b816 --- /dev/null +++ b/core/shared/platform/linux/platform_init.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +int +bh_platform_init() +{ + return 0; +} + +void +bh_platform_destroy() +{ +} + diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h new file mode 100644 index 000000000..1a03b5077 --- /dev/null +++ b/core/shared/platform/linux/platform_internal.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_LINUX +#define BH_PLATFORM_LINUX +#endif + +#define _STACK_SIZE_ADJUSTMENT (32 * 1024) + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef pthread_t korp_tid; +typedef pthread_mutex_t korp_mutex; +typedef pthread_cond_t korp_cond; +typedef pthread_t korp_thread; + +#define os_printf printf +#define os_vprintf vprintf + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ + diff --git a/core/shared/platform/linux/shared_platform.cmake b/core/shared/platform/linux/shared_platform.cmake index a49c5c6e1..9a8726016 100644 --- a/core/shared/platform/linux/shared_platform.cmake +++ b/core/shared/platform/linux/shared_platform.cmake @@ -3,15 +3,16 @@ set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) +add_definitions(-DBH_PLATFORM_LINUX) + include_directories(${PLATFORM_SHARED_DIR}) include_directories(${PLATFORM_SHARED_DIR}/../include) +include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) -set (PLATFORM_SHARED_SOURCE ${source_all}) - -LIST (APPEND RUNTIME_LIB_HEADER_LIST "${PLATFORM_SHARED_DIR}/bh_platform.h") +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE}) file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) -LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) \ No newline at end of file +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) diff --git a/core/shared/platform/vxworks/bh_assert.c b/core/shared/platform/vxworks/bh_assert.c deleted file mode 100644 index c609fb93d..000000000 --- a/core/shared/platform/vxworks/bh_assert.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_assert.h" -#include -#include -#include - -#ifdef BH_TEST -#include -#endif - -#ifdef BH_TEST -/* for exception throwing */ -jmp_buf bh_test_jb; -#endif - -void bh_assert_internal(int v, const char *file_name, int line_number, - const char *expr_string) -{ - if (v) - return; - - if (!file_name) - file_name = "NULL FILENAME"; - if (!expr_string) - expr_string = "NULL EXPR_STRING"; - - printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string, - file_name, line_number); - -#ifdef BH_TEST - longjmp(bh_test_jb, 1); -#endif - - abort(); -} - -void bh_debug_internal(const char *file_name, int line_number, const char *fmt, - ...) -{ -#ifndef JEFF_TEST_VERIFIER - va_list args; - - va_start(args, fmt); - bh_assert(file_name); - - printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number); - vprintf(fmt, args); - - va_end(args); - printf("\n"); -#endif -} - diff --git a/core/shared/platform/vxworks/bh_platform.c b/core/shared/platform/vxworks/bh_platform.c deleted file mode 100644 index e0eca6a65..000000000 --- a/core/shared/platform/vxworks/bh_platform.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_common.h" -#include "bh_assert.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -int -bh_platform_init() -{ - return 0; -} - -void * -os_malloc(unsigned size) -{ - return malloc(size); -} - -void * -os_realloc(void *ptr, unsigned size) -{ - return realloc(ptr, size); -} - -void -os_free(void *ptr) -{ - free(ptr); -} - -char* -bh_read_file_to_buffer(const char *filename, uint32 *ret_size) -{ - char *buffer; - int file; - uint32 file_size, read_size; - struct stat stat_buf; - - if (!filename || !ret_size) { - printf("Read file to buffer failed: invalid filename or ret size.\n"); - return NULL; - } - - if ((file = open(filename, O_RDONLY, 0)) == -1) { - printf("Read file to buffer failed: open file %s failed.\n", - filename); - return NULL; - } - - if (fstat(file, &stat_buf) != 0) { - printf("Read file to buffer failed: fstat file %s failed.\n", - filename); - close(file); - return NULL; - } - - file_size = (uint32)stat_buf.st_size; - - if (!(buffer = BH_MALLOC(file_size))) { - printf("Read file to buffer failed: alloc memory failed.\n"); - close(file); - return NULL; - } - - read_size = (uint32)read(file, buffer, file_size); - close(file); - - if (read_size < file_size) { - printf("Read file to buffer failed: read file content failed.\n"); - BH_FREE(buffer); - return NULL; - } - - *ret_size = file_size; - return buffer; -} - -void * -bh_mmap(void *hint, uint32 size, int prot, int flags) -{ - int map_prot = PROT_NONE; - int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; - uint64 request_size, page_size; - uint8 *addr, *addr_aligned; - uint32 i; - - /* align to 2M if no less than 2M, else align to 4K */ - page_size = size < 2 * 1024 * 1024 ? 4096 : 2 * 1024 * 1024; - request_size = (size + page_size - 1) & ~(page_size - 1); - request_size += page_size; - - if (request_size >= UINT32_MAX) - return NULL; - - if (prot & MMAP_PROT_READ) - map_prot |= PROT_READ; - - if (prot & MMAP_PROT_WRITE) - map_prot |= PROT_WRITE; - - if (prot & MMAP_PROT_EXEC) - map_prot |= PROT_EXEC; - -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) - if (flags & MMAP_MAP_32BIT) - map_flags |= MAP_32BIT; -#endif - - if (flags & MMAP_MAP_FIXED) - map_flags |= MAP_FIXED; - - /* try 5 times */ - for (i = 0; i < 5; i ++) { - addr = mmap(hint, size, map_prot, map_flags, -1, 0); - if (addr != MAP_FAILED) - break; - } - if (addr == MAP_FAILED) - return NULL; - - addr_aligned = (uint8*)(uintptr_t) - (((uint64)(uintptr_t)addr + page_size - 1) & ~(page_size - 1)); - - /* Unmap memory allocated before the aligned base address */ - if (addr != addr_aligned) { - uint32 prefix_size = (uint32)(addr_aligned - addr); - munmap(addr, prefix_size); - request_size -= prefix_size; - } - - /* Unmap memory allocated after the potentially unaligned end */ - if (size != request_size) { - uint32 suffix_size = (uint32)(request_size - size); - munmap(addr_aligned + size, suffix_size); - request_size -= size; - } - - if (size >= 2 * 1024 * 1024) { - /* Try to use huge page to improve performance */ - if (!madvise(addr, size, MADV_HUGEPAGE)) - /* make huge page become effective */ - memset(addr, 0, size); - } - - return addr_aligned; -} - -void -bh_munmap(void *addr, uint32 size) -{ - if (addr) - munmap(addr, size); -} - -int -bh_mprotect(void *addr, uint32 size, int prot) -{ - int map_prot = PROT_NONE; - - if (!addr) - return 0; - - if (prot & MMAP_PROT_READ) - map_prot |= PROT_READ; - - if (prot & MMAP_PROT_WRITE) - map_prot |= PROT_WRITE; - - if (prot & MMAP_PROT_EXEC) - map_prot |= PROT_EXEC; - - return mprotect(addr, size, map_prot); -} - diff --git a/core/shared/platform/vxworks/bh_platform.h b/core/shared/platform/vxworks/bh_platform.h deleted file mode 100644 index 70c030e74..000000000 --- a/core/shared/platform/vxworks/bh_platform.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_PLATFORM_H -#define _BH_PLATFORM_H - -#include "bh_config.h" -#include "bh_types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint64_t uint64; -typedef int64_t int64; - -extern void DEBUGME(void); - -#define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0) - -#ifndef BH_PLATFORM_VXWORKS -#define BH_PLATFORM_VXWORKS -#endif - -#define _STACK_SIZE_ADJUSTMENT (32 * 1024) - -/* Stack size of applet threads's native part. */ -#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) - -/* Default thread priority */ -#define BH_THREAD_DEFAULT_PRIORITY 0 - -#define BH_ROUTINE_MODIFIER - -#define BHT_TIMEDOUT ETIMEDOUT - -#define INVALID_THREAD_ID 0xFFffFFff - -typedef pthread_t korp_tid; -typedef pthread_mutex_t korp_mutex; -typedef sem_t korp_sem; -typedef pthread_cond_t korp_cond; -typedef pthread_t korp_thread; -typedef void* (*thread_start_routine_t)(void*); - -void *os_malloc(unsigned size); -void *os_realloc(void *ptr, unsigned size); -void os_free(void *ptr); - -#define bh_printf printf - -int snprintf(char *buffer, size_t count, const char *format, ...); -double fmod(double x, double y); -float fmodf(float x, float y); -double sqrt(double x); - -#define BH_WAIT_FOREVER 0xFFFFFFFF - -#ifndef NULL -# define NULL ((void*) 0) -#endif - -/** - * Return the offset of the given field in the given type. - * - * @param Type the type containing the filed - * @param field the field in the type - * - * @return the offset of field in Type - */ -#ifndef offsetof -#define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) -#endif - -#define bh_assert assert - -char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); - -int bh_platform_init(); - -/* MMAP mode */ -enum { - MMAP_PROT_NONE = 0, - MMAP_PROT_READ = 1, - MMAP_PROT_WRITE = 2, - MMAP_PROT_EXEC = 4, -}; - -/* MMAP flags */ -enum { - MMAP_MAP_NONE = 0, - /* Put the mapping into 0 to 2 G, supported only on x86_64 */ - MMAP_MAP_32BIT = 1, - /* Don't interpret addr as a hint: place the mapping at exactly - that address. */ - MMAP_MAP_FIXED = 2 -}; - -void *bh_mmap(void *hint, unsigned int size, int prot, int flags); -void bh_munmap(void *addr, uint32 size); -int bh_mprotect(void *addr, uint32 size, int prot); -#define bh_dcache_flush() (void)0 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/core/shared/platform/vxworks/bh_platform_log.c b/core/shared/platform/vxworks/bh_platform_log.c deleted file mode 100644 index 902ca7d60..000000000 --- a/core/shared/platform/vxworks/bh_platform_log.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include - -void bh_log_emit(const char *fmt, va_list ap) -{ - vprintf(fmt, ap); - fflush(stdout); -} - -int bh_fprintf(FILE *stream, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = vfprintf(stream ? stream : stdout, fmt, ap); - va_end(ap); - - return ret; -} - -int bh_fflush(void *stream) -{ - return fflush(stream ? stream : stdout); -} diff --git a/core/shared/platform/vxworks/bh_thread.c b/core/shared/platform/vxworks/bh_thread.c deleted file mode 100644 index 4267154ec..000000000 --- a/core/shared/platform/vxworks/bh_thread.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_thread.h" -#include "bh_assert.h" -#include "bh_log.h" -#include -#include -#include - -static bool is_thread_sys_inited = false; - -static korp_mutex thread_list_lock; -static pthread_key_t thread_local_storage_key[BH_MAX_TLS_NUM]; - -int _vm_thread_sys_init() -{ - unsigned i, j; - int ret; - - if (is_thread_sys_inited) - return 0; - - for (i = 0; i < BH_MAX_TLS_NUM; i++) { - ret = pthread_key_create(&thread_local_storage_key[i], NULL); - if (ret) - goto fail; - } - - ret = vm_mutex_init(&thread_list_lock); - if (ret) - goto fail; - - is_thread_sys_inited = true; - return 0; - - fail: for (j = 0; j < i; j++) - pthread_key_delete(thread_local_storage_key[j]); - return -1; -} - -void vm_thread_sys_destroy(void) -{ - if (is_thread_sys_inited) { - unsigned i; - for (i = 0; i < BH_MAX_TLS_NUM; i++) - pthread_key_delete(thread_local_storage_key[i]); - vm_mutex_destroy(&thread_list_lock); - is_thread_sys_inited = false; - } -} - -typedef struct { - thread_start_routine_t start; - void* stack; - uint32 stack_size; - void* arg; -} thread_wrapper_arg; - -static void *vm_thread_wrapper(void *arg) -{ - thread_wrapper_arg * targ = arg; - LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ); - targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); - _vm_tls_put(1, targ); - targ->start(targ->arg); - BH_FREE(targ); - _vm_tls_put(1, NULL); - return NULL; -} - -int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) -{ - pthread_attr_t tattr; - thread_wrapper_arg *targ; - - bh_assert(stack_size > 0); - bh_assert(tid); - bh_assert(start); - - *tid = INVALID_THREAD_ID; - - pthread_attr_init(&tattr); - pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); - if (pthread_attr_setstacksize(&tattr, stack_size) != 0) { - bh_debug("Invalid thread stack size %u. Min stack size on Linux = %u", - stack_size, PTHREAD_STACK_MIN); - pthread_attr_destroy(&tattr); - return BHT_ERROR; - } - - targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ)); - if (!targ) { - pthread_attr_destroy(&tattr); - return BHT_ERROR; - } - - targ->start = start; - targ->arg = arg; - targ->stack_size = stack_size; - - if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) { - pthread_attr_destroy(&tattr); - BH_FREE(targ); - return BHT_ERROR; - } - - pthread_attr_destroy(&tattr); - return BHT_OK; -} - -int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) -{ - return _vm_thread_create_with_prio(tid, start, arg, stack_size, - BH_THREAD_DEFAULT_PRIORITY); -} - -korp_tid _vm_self_thread() -{ - return (korp_tid) pthread_self(); -} - -void vm_thread_exit(void * code) -{ - BH_FREE(_vm_tls_get(1)); - _vm_tls_put(1, NULL); - pthread_exit(code); -} - -void *_vm_tls_get(unsigned idx) -{ - bh_assert(idx < BH_MAX_TLS_NUM); - return pthread_getspecific(thread_local_storage_key[idx]); -} - -int _vm_tls_put(unsigned idx, void * tls) -{ - bh_assert(idx < BH_MAX_TLS_NUM); - pthread_setspecific(thread_local_storage_key[idx], tls); - return BHT_OK; -} - -int _vm_mutex_init(korp_mutex *mutex) -{ - return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_recursive_mutex_init(korp_mutex *mutex) -{ - int ret; - - pthread_mutexattr_t mattr; - - bh_assert(mutex); - ret = pthread_mutexattr_init(&mattr); - if (ret) - return BHT_ERROR; - - pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); - ret = pthread_mutex_init(mutex, &mattr); - pthread_mutexattr_destroy(&mattr); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_mutex_destroy(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_destroy(mutex); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -/* Returned error (EINVAL, EAGAIN and EDEADLK) from - locking the mutex indicates some logic error present in - the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_lock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_lock(mutex); - if (0 != ret) { - printf("vm mutex lock failed (ret=%d)!\n", ret); - exit(-1); - } -} - -int vm_mutex_trylock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_trylock(mutex); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -/* Returned error (EINVAL, EAGAIN and EPERM) from - unlocking the mutex indicates some logic error present - in the program somewhere. - Don't try to recover error for an existing unknown error.*/ -void vm_mutex_unlock(korp_mutex *mutex) -{ - int ret; - - bh_assert(mutex); - ret = pthread_mutex_unlock(mutex); - if (0 != ret) { - printf("vm mutex unlock failed (ret=%d)!\n", ret); - exit(-1); - } -} - -int _vm_sem_init(korp_sem* sem, unsigned int c) -{ - int ret; - - bh_assert(sem); - ret = sem_init(sem, 0, c); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_destroy(korp_sem *sem) -{ - int ret; - - bh_assert(sem); - ret = sem_destroy(sem); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_wait(korp_sem *sem) -{ - int ret; - - bh_assert(sem); - - ret = sem_wait(sem); - - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_reltimedwait(korp_sem *sem, int mills) -{ - int ret = BHT_OK; - - struct timespec timeout; - const int mills_per_sec = 1000; - const int mills_to_nsec = 1E6; - - bh_assert(sem); - - if (mills == (int)BHT_WAIT_FOREVER) { - ret = sem_wait(sem); - } else { - - timeout.tv_sec = mills / mills_per_sec; - timeout.tv_nsec = (mills % mills_per_sec) * mills_to_nsec; - timeout.tv_sec += time(NULL); - - ret = sem_timedwait(sem, &timeout); - } - - if (ret != BHT_OK) { - if (errno == BHT_TIMEDOUT) { - ret = BHT_TIMEDOUT; - errno = 0; - } else { - bh_debug("Faliure happens when timed wait is called"); - bh_assert(0); - } - } - - return ret; -} - -int _vm_sem_post(korp_sem *sem) -{ - bh_assert(sem); - - return sem_post(sem) == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_cond_init(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_init(cond, NULL) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_destroy(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_destroy(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex) -{ - bh_assert(cond); - bh_assert(mutex); - - if (pthread_cond_wait(cond, mutex) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - ts->tv_sec = (long int)(tv.tv_sec + msec / 1000); - ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec); - - if (ts->tv_nsec >= 1000000000L) { - ts->tv_sec++; - ts->tv_nsec -= 1000000000L; - } -} - -int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) -{ - int ret; - struct timespec abstime; - - if (mills == (int)BHT_WAIT_FOREVER) - ret = pthread_cond_wait(cond, mutex); - else { - msec_nsec_to_abstime(&abstime, mills, 0); - ret = pthread_cond_timedwait(cond, mutex, &abstime); - } - - if (ret != BHT_OK && ret != BHT_TIMEDOUT) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_signal(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_signal(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_cond_broadcast(korp_cond *cond) -{ - bh_assert(cond); - - if (pthread_cond_broadcast(cond) != BHT_OK) - return BHT_ERROR; - - return BHT_OK; -} - -int _vm_thread_cancel(korp_tid thread) -{ - return pthread_cancel(thread); -} - -int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) -{ - return pthread_join(thread, value_ptr); -} - -int _vm_thread_detach(korp_tid thread) -{ - return pthread_detach(thread); -} - diff --git a/core/shared/platform/vxworks/bh_time.c b/core/shared/platform/vxworks/bh_time.c deleted file mode 100644 index fefa0496a..000000000 --- a/core/shared/platform/vxworks/bh_time.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_time.h" - -#include -#include -#include - -/* - * This function returns milliseconds per tick. - * @return milliseconds per tick. - */ -uint64 _bh_time_get_tick_millisecond() -{ - return (uint64)sysconf(_SC_CLK_TCK); -} - -/* - * This function returns milliseconds after boot. - * @return milliseconds after boot. - */ -uint64 _bh_time_get_boot_millisecond() -{ - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - return 0; - } - - return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000); -} - -uint32 bh_get_tick_sec() -{ - return (uint32)(_bh_time_get_boot_millisecond() / 1000); -} - -/* - * This function returns GMT time milliseconds since from 1970.1.1, AKA UNIX time. - * @return milliseconds since from 1970.1.1. - */ -uint64 _bh_time_get_millisecond_from_1970() -{ - struct timespec ts; - - if (clock_gettime(CLOCK_REALTIME, &ts) != 0) { - return 0; - } - - return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000); -} - -size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time) -{ - time_t time_sec = (time_t)(time / 1000); - struct tm *ltp; - - ltp = localtime(&time_sec); - if (ltp == NULL) { - return 0; - } - return strftime(s, max, format, ltp); -} - diff --git a/core/shared/platform/vxworks/platform_init.c b/core/shared/platform/vxworks/platform_init.c new file mode 100644 index 000000000..76594b816 --- /dev/null +++ b/core/shared/platform/vxworks/platform_init.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +int +bh_platform_init() +{ + return 0; +} + +void +bh_platform_destroy() +{ +} + diff --git a/core/shared/platform/vxworks/platform_internal.h b/core/shared/platform/vxworks/platform_internal.h new file mode 100644 index 000000000..74ed01dbc --- /dev/null +++ b/core/shared/platform/vxworks/platform_internal.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_VXWORKS +#define BH_PLATFORM_VXWORKS +#endif + +#define _STACK_SIZE_ADJUSTMENT (32 * 1024) + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef pthread_t korp_tid; +typedef pthread_mutex_t korp_mutex; +typedef pthread_cond_t korp_cond; +typedef pthread_t korp_thread; + +#define os_printf printf +#define os_vprintf vprintf + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ + diff --git a/core/shared/platform/vxworks/shared_platform.cmake b/core/shared/platform/vxworks/shared_platform.cmake index 2fdc1330e..6979ce235 100644 --- a/core/shared/platform/vxworks/shared_platform.cmake +++ b/core/shared/platform/vxworks/shared_platform.cmake @@ -3,11 +3,16 @@ set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) +add_definitions(-DBH_PLATFORM_VXWORKS) + include_directories(${PLATFORM_SHARED_DIR}) include_directories(${PLATFORM_SHARED_DIR}/../include) +include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) -set (PLATFORM_SHARED_SOURCE ${source_all}) +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE}) +file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) diff --git a/core/shared/platform/zephyr/COPYRIGHT b/core/shared/platform/zephyr/COPYRIGHT deleted file mode 100644 index a0e1c83a9..000000000 --- a/core/shared/platform/zephyr/COPYRIGHT +++ /dev/null @@ -1,126 +0,0 @@ -# $FreeBSD$ -# @(#)COPYRIGHT 8.2 (Berkeley) 3/21/94 - -The compilation of software known as FreeBSD is distributed under the -following terms: - -Copyright (c) 1992-2019 The FreeBSD Project. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - -The 4.4BSD and 4.4BSD-Lite software is distributed under the following -terms: - -All of the documentation and software included in the 4.4BSD and 4.4BSD-Lite -Releases is copyrighted by The Regents of the University of California. - -Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 - The Regents of the University of California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: -This product includes software developed by the University of -California, Berkeley and its contributors. -4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - -The Institute of Electrical and Electronics Engineers and the American -National Standards Committee X3, on Information Processing Systems have -given us permission to reprint portions of their documentation. - -In the following statement, the phrase ``this text'' refers to portions -of the system documentation. - -Portions of this text are reprinted and reproduced in electronic form in -the second BSD Networking Software Release, from IEEE Std 1003.1-1988, IEEE -Standard Portable Operating System Interface for Computer Environments -(POSIX), copyright C 1988 by the Institute of Electrical and Electronics -Engineers, Inc. In the event of any discrepancy between these versions -and the original IEEE Standard, the original IEEE Standard is the referee -document. - -In the following statement, the phrase ``This material'' refers to portions -of the system documentation. - -This material is reproduced with permission from American National -Standards Committee X3, on Information Processing Systems. Computer and -Business Equipment Manufacturers Association (CBEMA), 311 First St., NW, -Suite 500, Washington, DC 20001-2178. The developmental work of -Programming Language C was completed by the X3J11 Technical Committee. - -The views and conclusions contained in the software and documentation are -those of the authors and should not be interpreted as representing official -policies, either expressed or implied, of the Regents of the University -of California. - - -NOTE: The copyright of UC Berkeley's Berkeley Software Distribution ("BSD") -source has been updated. The copyright addendum may be found at -ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change and is -included below. - -July 22, 1999 - -To All Licensees, Distributors of Any Version of BSD: - -As you know, certain of the Berkeley Software Distribution ("BSD") source -code files require that further distributions of products containing all or -portions of the software, acknowledge within their advertising materials -that such products contain software developed by UC Berkeley and its -contributors. - -Specifically, the provision reads: - -" * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors." - -Effective immediately, licensees and distributors are no longer required to -include the acknowledgement within advertising materials. Accordingly, the -foregoing paragraph of those BSD Unix files containing it is hereby deleted -in its entirety. - -William Hoskins -Director, Office of Technology Licensing -University of California, Berkeley diff --git a/core/shared/platform/zephyr/bh_assert.c b/core/shared/platform/zephyr/bh_assert.c deleted file mode 100644 index ad3205984..000000000 --- a/core/shared/platform/zephyr/bh_assert.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_assert.h" -#include -#include -#include - -#ifdef BH_TEST -#include -#endif - -#ifdef BH_TEST -/* for exception throwing */ -jmp_buf bh_test_jb; -#endif -extern void abort(void); -void bh_assert_internal(int v, const char *file_name, int line_number, - const char *expr_string) -{ - if (v) - return; - - if (!file_name) - file_name = "NULL FILENAME"; - if (!expr_string) - expr_string = "NULL EXPR_STRING"; - - printk("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string, - file_name, line_number); - -#ifdef BH_TEST - longjmp(bh_test_jb, 1); -#endif - - abort(); -} - -void bh_debug_internal(const char *file_name, int line_number, const char *fmt, - ...) -{ -#ifndef JEFF_TEST_VERIFIER - va_list args; - - va_start(args, fmt); - bh_assert(file_name); - - printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number); - vprintf(fmt, args); - - va_end(args); - printf("\n"); -#endif -} - diff --git a/core/shared/platform/zephyr/bh_platform.h b/core/shared/platform/zephyr/bh_platform.h deleted file mode 100644 index 34cd386fa..000000000 --- a/core/shared/platform/zephyr/bh_platform.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_PLATFORM_H -#define _BH_PLATFORM_H - -#include "bh_config.h" -#include "bh_types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef CONFIG_NET_BUF_USER_DATA_SIZE -#define CONFIG_NET_BUF_USER_DATA_SIZE 0 -#endif -#include -#include -#include -#include -#include - -#ifndef BH_PLATFORM_ZEPHYR -#define BH_PLATFORM_ZEPHYR -#endif - -#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB) - -/* Default thread priority */ -#define BH_THREAD_DEFAULT_PRIORITY 7 - -#define BH_ROUTINE_MODIFIER - -/* Invalid thread tid */ -#define INVALID_THREAD_ID NULL - -#define BH_WAIT_FOREVER K_FOREVER - -typedef uint64_t uint64; -typedef int64_t int64; - -typedef struct k_thread korp_thread; -typedef korp_thread *korp_tid; -typedef struct k_mutex korp_mutex; -typedef struct k_sem korp_sem; - -struct bh_thread_wait_node; -typedef struct bh_thread_wait_node *bh_thread_wait_list; -typedef struct korp_cond { - struct k_mutex wait_list_lock; - bh_thread_wait_list thread_wait_list; -} korp_cond; - -typedef void* (*thread_start_routine_t)(void*); - -void *os_malloc(unsigned size); -void *os_realloc(void *ptr, unsigned size); -void os_free(void *ptr); - -#define bh_printf printf - -/* Unit test framework is based on C++, where the declaration of - snprintf is different. */ -#ifndef __cplusplus -int snprintf(char *buffer, size_t count, const char *format, ...); -#endif - -#ifndef NULL -#define NULL ((void*)0) -#endif - -/** - * Return the offset of the given field in the given type. - * - * @param Type the type containing the filed - * @param field the field in the type - * - * @return the offset of field in Type - */ -#ifndef offsetof -#define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) -#endif - -#define bh_assert(x) \ - do { \ - if (!(x)) { \ - printk("bh_assert(%s, %d)\n", __func__, __LINE__);\ - } \ - } while (0) - -/* math functions */ -double sqrt(double x); -double floor(double x); -double ceil(double x); -double fmin(double x, double y); -double fmax(double x, double y); -double rint(double x); -double fabs(double x); -double trunc(double x); -float floorf(float x); -float ceilf(float x); -float fminf(float x, float y); -float fmaxf(float x, float y); -float rintf(float x); -float truncf(float x); -int signbit(double x); -int isnan(double x); - -unsigned long long int strtoull(const char *nptr, char **endptr, - int base); -double strtod(const char *nptr, char **endptr); -float strtof(const char *nptr, char **endptr); - -int bh_platform_init(); - -/* MMAP mode */ -enum { - MMAP_PROT_NONE = 0, - MMAP_PROT_READ = 1, - MMAP_PROT_WRITE = 2, - MMAP_PROT_EXEC = 4 -}; - -/* MMAP flags */ -enum { - MMAP_MAP_NONE = 0, - /* Put the mapping into 0 to 2 G, supported only on x86_64 */ - MMAP_MAP_32BIT = 1, - /* Don't interpret addr as a hint: place the mapping at exactly - that address. */ - MMAP_MAP_FIXED = 2 -}; - -void *bh_mmap(void *hint, unsigned int size, int prot, int flags); -void bh_munmap(void *addr, uint32 size); -int bh_mprotect(void *addr, uint32 size, int prot); -void bh_dcache_flush(); - -#endif diff --git a/core/shared/platform/zephyr/bh_platform_log.c b/core/shared/platform/zephyr/bh_platform_log.c deleted file mode 100644 index 76e377690..000000000 --- a/core/shared/platform/zephyr/bh_platform_log.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include - -struct out_context { - int count; -}; - -typedef int (*out_func_t)(int c, void *ctx); - -extern void *__printk_get_hook(void); -static int (*_char_out)(int) = NULL; - -static int char_out(int c, struct out_context *ctx) -{ - ctx->count++; - if (_char_out == NULL) { - _char_out = __printk_get_hook(); - } - return _char_out(c); -} - -static int bh_vprintk(const char *fmt, va_list ap) -{ - struct out_context ctx = { 0 }; - z_vprintk((out_func_t) char_out, &ctx, fmt, ap); - return ctx.count; -} - -void bh_log_emit(const char *fmt, va_list ap) -{ - bh_vprintk(fmt, ap); -} - -int bh_fprintf(FILE *stream, const char *fmt, ...) -{ - (void) stream; - va_list ap; - int ret; - - va_start(ap, fmt); - ret = bh_vprintk(fmt, ap); - va_end(ap); - - return ret; -} - -int bh_fflush(void *stream) -{ - (void) stream; - return 0; -} - diff --git a/core/shared/platform/zephyr/bh_time.c b/core/shared/platform/zephyr/bh_time.c deleted file mode 100755 index b6db78ead..000000000 --- a/core/shared/platform/zephyr/bh_time.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_time.h" - -/* - * This function returns milliseconds per tick. - * @return milliseconds per tick. - */ -uint64 _bh_time_get_tick_millisecond() -{ - return k_uptime_get_32(); -} - -/* - * This function returns milliseconds after boot. - * @return milliseconds after boot. - */ -uint64 _bh_time_get_boot_millisecond() -{ - return k_uptime_get_32(); -} - -uint64 _bh_time_get_millisecond_from_1970() -{ - return k_uptime_get(); -} - -size_t _bh_time_strftime(char *str, size_t max, const char *format, int64 time) -{ - (void) format; - (void) time; - uint32 t = k_uptime_get_32(); - int h, m, s; - - t = t % (24 * 60 * 60); - h = t / (60 * 60); - t = t % (60 * 60); - m = t / 60; - s = t % 60; - - return snprintf(str, max, "%02d:%02d:%02d", h, m, s); -} - diff --git a/core/shared/platform/zephyr/platform_internal.h b/core/shared/platform/zephyr/platform_internal.h new file mode 100644 index 000000000..c208bacd4 --- /dev/null +++ b/core/shared/platform/zephyr/platform_internal.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef CONFIG_NET_BUF_USER_DATA_SIZE +#define CONFIG_NET_BUF_USER_DATA_SIZE 0 +#endif +#include +#include +#include +#include +#include + +#ifdef CONFIG_ARM_MPU +#include +#endif + + +#ifndef BH_PLATFORM_ZEPHYR +#define BH_PLATFORM_ZEPHYR +#endif + +#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 7 + +typedef struct k_thread korp_thread; +typedef korp_thread *korp_tid; +typedef struct k_mutex korp_mutex; + +struct os_thread_wait_node; +typedef struct os_thread_wait_node *os_thread_wait_list; +typedef struct korp_cond { + struct k_mutex wait_list_lock; + os_thread_wait_list thread_wait_list; +} korp_cond; + +#define os_printf printf + +/* math functions which are not provided by os */ +double sqrt(double x); +double floor(double x); +double ceil(double x); +double fmin(double x, double y); +double fmax(double x, double y); +double rint(double x); +double fabs(double x); +double trunc(double x); +float floorf(float x); +float ceilf(float x); +float fminf(float x, float y); +float fmaxf(float x, float y); +float rintf(float x); +float truncf(float x); +int signbit(double x); +int isnan(double x); + +unsigned long long int strtoull(const char *nptr, char **endptr, int base); +double strtod(const char *nptr, char **endptr); +float strtof(const char *nptr, char **endptr); + +/** + * @brief Allocate executable memroy + * + * @param size size of the memory to be allocated + * + * @return the address of the allocated memory if not NULL + */ +typedef void* (*exec_mem_alloc_func_t)(unsigned int size); + +/** + * @brief Release executable memroy + * + * @param the address of the executable memory to be released + */ +typedef void (*exec_mem_free_func_t)(void *addr); + +/* Below function are called by external project to set related function pointers that + * will be used to malloc/free executable memory. Otherwise default mechanise will be used. */ +void set_exec_mem_alloc_func(exec_mem_alloc_func_t alloc_func, exec_mem_free_func_t free_func); + +#endif diff --git a/core/shared/platform/zephyr/shared_platform.cmake b/core/shared/platform/zephyr/shared_platform.cmake index cce0df72a..9b043b52f 100644 --- a/core/shared/platform/zephyr/shared_platform.cmake +++ b/core/shared/platform/zephyr/shared_platform.cmake @@ -1,13 +1,16 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) - -include_directories(${PLATFORM_SHARED_DIR}) -include_directories(${PLATFORM_SHARED_DIR}/../include) - - -file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) - -set (PLATFORM_SHARED_SOURCE ${source_all}) - +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_ZEPHYR) + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +include (${CMAKE_CURRENT_LIST_DIR}/../common/math/platform_api_math.cmake) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) + +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE}) + diff --git a/core/shared/platform/zephyr/bh_platform.c b/core/shared/platform/zephyr/zephyr_platform.c old mode 100755 new mode 100644 similarity index 51% rename from core/shared/platform/zephyr/bh_platform.c rename to core/shared/platform/zephyr/zephyr_platform.c index ba528cd56..0f52d1105 --- a/core/shared/platform/zephyr/bh_platform.c +++ b/core/shared/platform/zephyr/zephyr_platform.c @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_platform.h" -#include "bh_common.h" -#include -#include -#ifdef CONFIG_ARM_MPU -#include -#endif +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" +/* function pointers for executable memory management */ +static exec_mem_alloc_func_t exec_mem_alloc_func = NULL; +static exec_mem_free_func_t exec_mem_free_func = NULL; + +#if WASM_ENABLE_AOT != 0 #ifdef CONFIG_ARM_MPU /** * This function will allow execute from sram region. @@ -32,6 +32,7 @@ disable_mpu_rasr_xn(void) } #endif /* end of CONFIG_ARM_MPU */ +#endif static int _stdout_hook_iwasm(int c) @@ -40,6 +41,12 @@ _stdout_hook_iwasm(int c) return 1; } +int +os_thread_sys_init(); + +void +os_thread_sys_destroy(); + int bh_platform_init() { @@ -54,7 +61,13 @@ bh_platform_init() #endif #endif - return 0; + return os_thread_sys_init(); +} + +void +bh_platform_destroy() +{ + os_thread_sys_destroy(); } void * @@ -74,26 +87,54 @@ os_free(void *ptr) { } -void * -bh_mmap(void *hint, unsigned int size, int prot, int flags) -{ - return BH_MALLOC(size); -} +struct out_context { + int count; +}; -void -bh_munmap(void *addr, uint32 size) +typedef int (*out_func_t)(int c, void *ctx); + +static int +char_out(int c, void *ctx) { - return BH_FREE(addr); + struct out_context *out_ctx = (struct out_context*)ctx; + out_ctx->count++; + return _stdout_hook_iwasm(c); } int -bh_mprotect(void *addr, uint32 size, int prot) +os_vprintf(const char *fmt, va_list ap) +{ + struct out_context ctx = { 0 }; + z_vprintk(char_out, &ctx, fmt, ap); + return ctx.count; +} + +void * +os_mmap(void *hint, unsigned int size, int prot, int flags) +{ + if (exec_mem_alloc_func) + return exec_mem_alloc_func(size); + else + return BH_MALLOC(size); +} + +void +os_munmap(void *addr, uint32 size) +{ + if (exec_mem_free_func) + exec_mem_free_func(addr); + else + BH_FREE(addr); +} + +int +os_mprotect(void *addr, uint32 size, int prot) { return 0; } void -bh_dcache_flush() +os_dcache_flush() { #if defined(CONFIG_CPU_CORTEX_M7) && defined(CONFIG_ARM_MPU) uint32 key; @@ -102,3 +143,11 @@ bh_dcache_flush() irq_unlock(key); #endif } + +void set_exec_mem_alloc_func(exec_mem_alloc_func_t alloc_func, + exec_mem_free_func_t free_func) +{ + exec_mem_alloc_func = alloc_func; + exec_mem_free_func = free_func; +} + diff --git a/core/shared/platform/zephyr/bh_thread.c b/core/shared/platform/zephyr/zephyr_thread.c old mode 100755 new mode 100644 similarity index 61% rename from core/shared/platform/zephyr/bh_thread.c rename to core/shared/platform/zephyr/zephyr_thread.c index 9493076e6..cbed2596c --- a/core/shared/platform/zephyr/bh_thread.c +++ b/core/shared/platform/zephyr/zephyr_thread.c @@ -3,18 +3,29 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_thread.h" -#include "bh_assert.h" -#include "bh_log.h" +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" -typedef struct bh_thread_wait_node { +#define bh_assert(v) do { \ + if (!(v)) { \ + int _count; \ + printf("\nASSERTION FAILED: %s, at %s, line %d\n", \ + #v, __FILE__, __LINE__); \ + _count = printf(" "); \ + /* divived by 0 to make it abort */ \ + printf("%d\n", _count / (_count - 1)); \ + while (1); \ + } \ + } while (0) + +typedef struct os_thread_wait_node { struct k_sem sem; - bh_thread_wait_list next; -} bh_thread_wait_node; + os_thread_wait_list next; +} os_thread_wait_node; -typedef struct bh_thread_data { +typedef struct os_thread_data { /* Next thread data */ - struct bh_thread_data *next; + struct os_thread_data *next; /* Zephyr thread handle */ korp_tid tid; /* Jeff thread local root */ @@ -22,46 +33,46 @@ typedef struct bh_thread_data { /* Lock for waiting list */ struct k_mutex wait_list_lock; /* Waiting list of other threads who are joining this thread */ - bh_thread_wait_list thread_wait_list; + os_thread_wait_list thread_wait_list; /* Thread stack size */ unsigned stack_size; /* Thread stack */ char stack[1]; -} bh_thread_data; +} os_thread_data; -typedef struct bh_thread_obj { +typedef struct os_thread_obj { struct k_thread thread; /* Whether the thread is terminated and this thread object is to be freed in the future. */ bool to_be_freed; - struct bh_thread_obj *next; -} bh_thread_obj; + struct os_thread_obj *next; +} os_thread_obj; static bool is_thread_sys_inited = false; /* Thread data of supervisor thread */ -static bh_thread_data supervisor_thread_data; +static os_thread_data supervisor_thread_data; /* Lock for thread data list */ static struct k_mutex thread_data_lock; /* Thread data list */ -static bh_thread_data *thread_data_list = NULL; +static os_thread_data *thread_data_list = NULL; /* Lock for thread object list */ static struct k_mutex thread_obj_lock; /* Thread object list */ -static bh_thread_obj *thread_obj_list = NULL; +static os_thread_obj *thread_obj_list = NULL; -static void thread_data_list_add(bh_thread_data *thread_data) +static void thread_data_list_add(os_thread_data *thread_data) { k_mutex_lock(&thread_data_lock, K_FOREVER); if (!thread_data_list) thread_data_list = thread_data; else { /* If already in list, just return */ - bh_thread_data *p = thread_data_list; + os_thread_data *p = thread_data_list; while (p) { if (p == thread_data) { k_mutex_unlock(&thread_data_lock); @@ -77,7 +88,7 @@ static void thread_data_list_add(bh_thread_data *thread_data) k_mutex_unlock(&thread_data_lock); } -static void thread_data_list_remove(bh_thread_data *thread_data) +static void thread_data_list_remove(os_thread_data *thread_data) { k_mutex_lock(&thread_data_lock, K_FOREVER); if (thread_data_list) { @@ -85,7 +96,7 @@ static void thread_data_list_remove(bh_thread_data *thread_data) thread_data_list = thread_data_list->next; else { /* Search and remove it from list */ - bh_thread_data *p = thread_data_list; + os_thread_data *p = thread_data_list; while (p && p->next != thread_data) p = p->next; if (p && p->next == thread_data) @@ -95,12 +106,12 @@ static void thread_data_list_remove(bh_thread_data *thread_data) k_mutex_unlock(&thread_data_lock); } -static bh_thread_data * +static os_thread_data * thread_data_list_lookup(k_tid_t tid) { k_mutex_lock(&thread_data_lock, K_FOREVER); if (thread_data_list) { - bh_thread_data *p = thread_data_list; + os_thread_data *p = thread_data_list; while (p) { if (p->tid == tid) { /* Found */ @@ -114,7 +125,7 @@ thread_data_list_lookup(k_tid_t tid) return NULL; } -static void thread_obj_list_add(bh_thread_obj *thread_obj) +static void thread_obj_list_add(os_thread_obj *thread_obj) { k_mutex_lock(&thread_obj_lock, K_FOREVER); if (!thread_obj_list) @@ -129,7 +140,7 @@ static void thread_obj_list_add(bh_thread_obj *thread_obj) static void thread_obj_list_reclaim() { - bh_thread_obj *p, *p_prev; + os_thread_obj *p, *p_prev; k_mutex_lock(&thread_obj_lock, K_FOREVER); p_prev = NULL; p = thread_obj_list; @@ -152,7 +163,7 @@ static void thread_obj_list_reclaim() k_mutex_unlock(&thread_obj_lock); } -int _vm_thread_sys_init() +int os_thread_sys_init() { if (is_thread_sys_inited) return BHT_OK; @@ -170,31 +181,31 @@ int _vm_thread_sys_init() return BHT_OK; } -void vm_thread_sys_destroy(void) +void os_thread_sys_destroy(void) { if (is_thread_sys_inited) { is_thread_sys_inited = false; } } -static bh_thread_data * +static os_thread_data * thread_data_current() { k_tid_t tid = k_current_get(); return thread_data_list_lookup(tid); } -static void vm_thread_cleanup(void) +static void os_thread_cleanup(void) { - bh_thread_data *thread_data = thread_data_current(); + os_thread_data *thread_data = thread_data_current(); bh_assert(thread_data != NULL); k_mutex_lock(&thread_data->wait_list_lock, K_FOREVER); if (thread_data->thread_wait_list) { /* Signal each joining thread */ - bh_thread_wait_list head = thread_data->thread_wait_list; + os_thread_wait_list head = thread_data->thread_wait_list; while (head) { - bh_thread_wait_list next = head->next; + os_thread_wait_list next = head->next; k_sem_give(&head->sem); /* head will be freed by joining thread */ head = next; @@ -206,32 +217,32 @@ static void vm_thread_cleanup(void) thread_data_list_remove(thread_data); /* Set flag to true for the next thread creating to free the thread object */ - ((bh_thread_obj*) thread_data->tid)->to_be_freed = true; + ((os_thread_obj*) thread_data->tid)->to_be_freed = true; BH_FREE(thread_data); } -static void vm_thread_wrapper(void *start, void *arg, void *thread_data) +static void os_thread_wrapper(void *start, void *arg, void *thread_data) { /* Set thread custom data */ - ((bh_thread_data*) thread_data)->tid = k_current_get(); + ((os_thread_data*) thread_data)->tid = k_current_get(); thread_data_list_add(thread_data); ((thread_start_routine_t) start)(arg); - vm_thread_cleanup(); + os_thread_cleanup(); } -int _vm_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) +int os_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg, + unsigned int stack_size) { - return _vm_thread_create_with_prio(p_tid, start, arg, stack_size, + return os_thread_create_with_prio(p_tid, start, arg, stack_size, BH_THREAD_DEFAULT_PRIORITY); } -int _vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) +int os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, + void *arg, unsigned int stack_size, int prio) { korp_tid tid; - bh_thread_data *thread_data; + os_thread_data *thread_data; unsigned thread_data_size; if (!p_tid || !stack_size) @@ -241,13 +252,13 @@ int _vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, thread_obj_list_reclaim(); /* Create and initialize thread object */ - if (!(tid = BH_MALLOC(sizeof(bh_thread_obj)))) + if (!(tid = BH_MALLOC(sizeof(os_thread_obj)))) return BHT_ERROR; - memset(tid, 0, sizeof(bh_thread_obj)); + memset(tid, 0, sizeof(os_thread_obj)); /* Create and initialize thread data */ - thread_data_size = offsetof(bh_thread_data, stack) + stack_size; + thread_data_size = offsetof(os_thread_data, stack) + stack_size; if (!(thread_data = BH_MALLOC(thread_data_size))) { BH_FREE(tid); return BHT_ERROR; @@ -260,7 +271,7 @@ int _vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, /* Create the thread */ if (!((tid = k_thread_create(tid, (k_thread_stack_t *) thread_data->stack, - stack_size, vm_thread_wrapper, start, arg, thread_data, prio, 0, + stack_size, os_thread_wrapper, start, arg, thread_data, prio, 0, K_NO_WAIT)))) { BH_FREE(tid); BH_FREE(thread_data); @@ -271,38 +282,24 @@ int _vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, /* Set thread custom data */ thread_data_list_add(thread_data); - thread_obj_list_add((bh_thread_obj*) tid); + thread_obj_list_add((os_thread_obj*) tid); *p_tid = tid; return BHT_OK; } -korp_tid _vm_self_thread() +korp_tid os_self_thread() { return (korp_tid) k_current_get(); } -void vm_thread_exit(void * code) -{ - (void) code; - korp_tid self = vm_self_thread(); - vm_thread_cleanup(); - k_thread_abort((k_tid_t) self); -} - -int _vm_thread_cancel(korp_tid thread) -{ - k_thread_abort((k_tid_t) thread); - return 0; -} - -int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) +int os_thread_join(korp_tid thread, void **value_ptr) { (void) value_ptr; - bh_thread_data *thread_data; - bh_thread_wait_node *node; + os_thread_data *thread_data; + os_thread_wait_node *node; /* Create wait node and append it to wait list */ - if (!(node = BH_MALLOC(sizeof(bh_thread_wait_node)))) + if (!(node = BH_MALLOC(sizeof(os_thread_wait_node)))) return BHT_ERROR; k_sem_init(&node->sem, 0, 1); @@ -317,7 +314,7 @@ int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) thread_data->thread_wait_list = node; else { /* Add to end of waiting list */ - bh_thread_wait_node *p = thread_data->thread_wait_list; + os_thread_wait_node *p = thread_data->thread_wait_list; while (p->next) p = p->next; p->next = node; @@ -325,128 +322,64 @@ int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) k_mutex_unlock(&thread_data->wait_list_lock); /* Wait the sem */ - k_sem_take(&node->sem, mills); + k_sem_take(&node->sem, K_FOREVER); /* Wait some time for the thread to be actually terminated */ - k_sleep(100); + k_sleep(Z_TIMEOUT_MS(100)); /* Destroy resource */ BH_FREE(node); return BHT_OK; } -int _vm_thread_detach(korp_tid thread) -{ - (void) thread; - return BHT_OK; -} - -void *_vm_tls_get(unsigned idx) -{ - (void) idx; - bh_thread_data *thread_data; - - bh_assert(idx == 0); - thread_data = thread_data_current(); - - return thread_data ? thread_data->tlr : NULL; -} - -int _vm_tls_put(unsigned idx, void * tls) -{ - bh_thread_data *thread_data; - - (void) idx; - bh_assert(idx == 0); - thread_data = thread_data_current(); - bh_assert(thread_data != NULL); - - thread_data->tlr = tls; - return BHT_OK; -} - -int _vm_mutex_init(korp_mutex *mutex) -{ - (void) mutex; - k_mutex_init(mutex); - return BHT_OK; -} - -int _vm_recursive_mutex_init(korp_mutex *mutex) +int os_mutex_init(korp_mutex *mutex) { k_mutex_init(mutex); return BHT_OK; } -int _vm_mutex_destroy(korp_mutex *mutex) +int os_recursive_mutex_init(korp_mutex *mutex) +{ + k_mutex_init(mutex); + return BHT_OK; +} + +int os_mutex_destroy(korp_mutex *mutex) { (void) mutex; return BHT_OK; } -void vm_mutex_lock(korp_mutex *mutex) +void os_mutex_lock(korp_mutex *mutex) { k_mutex_lock(mutex, K_FOREVER); } -int vm_mutex_trylock(korp_mutex *mutex) -{ - return k_mutex_lock(mutex, K_NO_WAIT); -} - -void vm_mutex_unlock(korp_mutex *mutex) +void os_mutex_unlock(korp_mutex *mutex) { k_mutex_unlock(mutex); } -int _vm_sem_init(korp_sem* sem, unsigned int c) -{ - int ret = k_sem_init(sem, 0, c); - return ret == 0 ? BHT_OK : BHT_ERROR; -} - -int _vm_sem_destroy(korp_sem *sem) -{ - (void) sem; - return BHT_OK; -} - -int _vm_sem_wait(korp_sem *sem) -{ - return k_sem_take(sem, K_FOREVER); -} - -int _vm_sem_reltimedwait(korp_sem *sem, int mills) -{ - return k_sem_take(sem, mills); -} - -int _vm_sem_post(korp_sem *sem) -{ - k_sem_give(sem); - return BHT_OK; -} - -int _vm_cond_init(korp_cond *cond) +int os_cond_init(korp_cond *cond) { k_mutex_init(&cond->wait_list_lock); cond->thread_wait_list = NULL; return BHT_OK; } -int _vm_cond_destroy(korp_cond *cond) +int os_cond_destroy(korp_cond *cond) { (void) cond; return BHT_OK; } -static int _vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, - bool timed, int mills) +static int os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, + bool timed, int mills) { - bh_thread_wait_node *node; + os_thread_wait_node *node; /* Create wait node and append it to wait list */ - if (!(node = BH_MALLOC(sizeof(bh_thread_wait_node)))) + if (!(node = BH_MALLOC(sizeof(os_thread_wait_node)))) return BHT_ERROR; k_sem_init(&node->sem, 0, 1); @@ -457,7 +390,7 @@ static int _vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, cond->thread_wait_list = node; else { /* Add to end of wait list */ - bh_thread_wait_node *p = cond->thread_wait_list; + os_thread_wait_node *p = cond->thread_wait_list; while (p->next) p = p->next; p->next = node; @@ -466,7 +399,7 @@ static int _vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, /* Unlock mutex, wait sem and lock mutex again */ k_mutex_unlock(mutex); - k_sem_take(&node->sem, timed ? mills : K_FOREVER); + k_sem_take(&node->sem, timed ? Z_TIMEOUT_MS(mills) : K_FOREVER); k_mutex_lock(mutex, K_FOREVER); /* Remove wait node from wait list */ @@ -475,7 +408,7 @@ static int _vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, cond->thread_wait_list = node->next; else { /* Remove from the wait list */ - bh_thread_wait_node *p = cond->thread_wait_list; + os_thread_wait_node *p = cond->thread_wait_list; while (p->next != node) p = p->next; p->next = node->next; @@ -486,17 +419,21 @@ static int _vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, return BHT_OK; } -int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex) +int os_cond_wait(korp_cond *cond, korp_mutex *mutex) { - return _vm_cond_wait_internal(cond, mutex, false, 0); + return os_cond_wait_internal(cond, mutex, false, 0); } -int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) +int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds) { - return _vm_cond_wait_internal(cond, mutex, true, mills); + + if (useconds == BHT_WAIT_FOREVER) + return os_cond_wait_internal(cond, mutex, false, 0); + else + return os_cond_wait_internal(cond, mutex, true, useconds / 1000); } -int _vm_cond_signal(korp_cond *cond) +int os_cond_signal(korp_cond *cond) { /* Signal the head wait node of wait list */ k_mutex_lock(&cond->wait_list_lock, K_FOREVER); @@ -507,19 +444,3 @@ int _vm_cond_signal(korp_cond *cond) return BHT_OK; } -int _vm_cond_broadcast(korp_cond *cond) -{ - /* Signal each wait node of wait list */ - k_mutex_lock(&cond->wait_list_lock, K_FOREVER); - if (cond->thread_wait_list) { - bh_thread_wait_node *p = cond->thread_wait_list; - while (p) { - k_sem_give(&p->sem); - p = p->next; - } - } - k_mutex_unlock(&cond->wait_list_lock); - - return BHT_OK; -} - diff --git a/core/shared/platform/zephyr/zephyr_time.c b/core/shared/platform/zephyr/zephyr_time.c new file mode 100644 index 000000000..b6c03f586 --- /dev/null +++ b/core/shared/platform/zephyr/zephyr_time.c @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +uint64 +os_time_get_boot_microsecond() +{ + return k_uptime_get_32() * 1000; +} + diff --git a/core/shared/utils/CMakeLists.txt b/core/shared/utils/CMakeLists.txt deleted file mode 100644 index 029109789..000000000 --- a/core/shared/utils/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -include_directories (. ../include ../platform/include ../platform/${WAMR_BUILD_PLATFORM} coap/er-coap coap/extension) - - -file (GLOB_RECURSE source_all *.c ) - -add_library (vmutilslib ${source_all}) - diff --git a/core/shared/utils/bh_assert.c b/core/shared/utils/bh_assert.c new file mode 100644 index 000000000..b9ac28ed6 --- /dev/null +++ b/core/shared/utils/bh_assert.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_assert.h" + +void bh_assert_internal(int v, const char *file_name, int line_number, + const char *expr_string) +{ + int i; + + if (v) + return; + + if (!file_name) + file_name = "NULL FILENAME"; + + if (!expr_string) + expr_string = "NULL EXPR_STRING"; + + os_printf("\nASSERTION FAILED: %s, at file %s, line %d\n", + expr_string, file_name, line_number); + + i = os_printf(" "); + + /* divived by 0 to make it abort */ + os_printf("%d\n", i / (i - 1)); + while (1); +} + diff --git a/core/shared/utils/bh_assert.h b/core/shared/utils/bh_assert.h new file mode 100644 index 000000000..3a83d62b1 --- /dev/null +++ b/core/shared/utils/bh_assert.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _BH_ASSERT_H +#define _BH_ASSERT_H + +#include "bh_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if BH_DEBUG != 0 +void bh_assert_internal(int v, const char *file_name, int line_number, + const char *expr_string); +#define bh_assert(expr) bh_assert_internal((int)(uintptr_t)(expr), \ + __FILE__, __LINE__, #expr) +#else +#define bh_assert(expr) (void)0 +#endif /* end of BH_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of _BH_ASSERT_H */ + diff --git a/core/shared/utils/bh_definition.c b/core/shared/utils/bh_common.c similarity index 91% rename from core/shared/utils/bh_definition.c rename to core/shared/utils/bh_common.c index 3d2a1e0df..a3f47a52d 100644 --- a/core/shared/utils/bh_definition.c +++ b/core/shared/utils/bh_common.c @@ -3,7 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_platform.h" #include "bh_common.h" #ifdef RSIZE_MAX @@ -34,7 +33,7 @@ b_memcpy_s(void * s1, unsigned int s1max, } int -b_strcat_s(char * s1, size_t s1max, const char * s2) +b_strcat_s(char * s1, unsigned int s1max, const char * s2) { if (NULL == s1 || NULL == s2 || s1max < (strlen(s1) + strlen(s2) + 1) @@ -47,7 +46,7 @@ b_strcat_s(char * s1, size_t s1max, const char * s2) } int -b_strcpy_s(char * s1, size_t s1max, const char * s2) +b_strcpy_s(char * s1, unsigned int s1max, const char * s2) { if (NULL == s1 || NULL == s2 || s1max < (strlen(s2) + 1) diff --git a/core/shared/include/bh_common.h b/core/shared/utils/bh_common.h similarity index 87% rename from core/shared/include/bh_common.h rename to core/shared/utils/bh_common.h index 7e78e3e82..682e3d2e3 100644 --- a/core/shared/include/bh_common.h +++ b/core/shared/utils/bh_common.h @@ -8,6 +8,10 @@ #include "bh_platform.h" +#ifdef __cplusplus +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; \ @@ -27,8 +31,8 @@ } while (0) int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n); -int b_strcat_s(char * s1, size_t s1max, const char * s2); -int b_strcpy_s(char * s1, size_t s1max, const char * s2); +int b_strcat_s(char * s1, unsigned int s1max, const char * s2); +int b_strcpy_s(char * s1, unsigned int s1max, const char * s2); /* strdup with string allocated by BH_MALLOC */ char *bh_strdup(const char *s); @@ -36,4 +40,8 @@ char *bh_strdup(const char *s); /* strdup with string allocated by WA_MALLOC */ char *wa_strdup(const char *s); +#ifdef __cplusplus +} +#endif + #endif diff --git a/core/shared/utils/bh_hashmap.c b/core/shared/utils/bh_hashmap.c index 0bebdfc64..5c7b9e8f3 100644 --- a/core/shared/utils/bh_hashmap.c +++ b/core/shared/utils/bh_hashmap.c @@ -4,9 +4,6 @@ */ #include "bh_hashmap.h" -#include "bh_log.h" -#include "bh_thread.h" - typedef struct HashMapElem { void *key; @@ -65,7 +62,7 @@ bh_hash_map_create(uint32 size, bool use_lock, map->lock = (korp_mutex*) ((uint8*)map + offsetof(HashMap, elements) + sizeof(HashMapElem) * size); - if (vm_mutex_init(map->lock)) { + if (os_mutex_init(map->lock)) { LOG_ERROR("HashMap create failed: init map lock failed.\n"); BH_FREE(map); return NULL; @@ -92,7 +89,7 @@ bh_hash_map_insert(HashMap *map, void *key, void *value) } if (map->lock) { - vm_mutex_lock(map->lock); + os_mutex_lock(map->lock); } index = map->hash_func(key) % map->size; @@ -116,13 +113,13 @@ bh_hash_map_insert(HashMap *map, void *key, void *value) map->elements[index] = elem; if (map->lock) { - vm_mutex_unlock(map->lock); + os_mutex_unlock(map->lock); } return true; fail: if (map->lock) { - vm_mutex_unlock(map->lock); + os_mutex_unlock(map->lock); } return false; } @@ -140,7 +137,7 @@ bh_hash_map_find(HashMap *map, void *key) } if (map->lock) { - vm_mutex_lock(map->lock); + os_mutex_lock(map->lock); } index = map->hash_func(key) % map->size; @@ -150,7 +147,7 @@ bh_hash_map_find(HashMap *map, void *key) if (map->key_equal_func(elem->key, key)) { value = elem->value; if (map->lock) { - vm_mutex_unlock(map->lock); + os_mutex_unlock(map->lock); } return value; } @@ -158,7 +155,7 @@ bh_hash_map_find(HashMap *map, void *key) } if (map->lock) { - vm_mutex_unlock(map->lock); + os_mutex_unlock(map->lock); } return NULL; } @@ -176,7 +173,7 @@ bh_hash_map_update(HashMap *map, void *key, void *value, } if (map->lock) { - vm_mutex_lock(map->lock); + os_mutex_lock(map->lock); } index = map->hash_func(key) % map->size; @@ -188,7 +185,7 @@ bh_hash_map_update(HashMap *map, void *key, void *value, *p_old_value = elem->value; elem->value = value; if (map->lock) { - vm_mutex_unlock(map->lock); + os_mutex_unlock(map->lock); } return true; } @@ -196,7 +193,7 @@ bh_hash_map_update(HashMap *map, void *key, void *value, } if (map->lock) { - vm_mutex_unlock(map->lock); + os_mutex_unlock(map->lock); } return false; } @@ -214,7 +211,7 @@ bh_hash_map_remove(HashMap *map, void *key, } if (map->lock) { - vm_mutex_lock(map->lock); + os_mutex_lock(map->lock); } index = map->hash_func(key) % map->size; @@ -235,7 +232,7 @@ bh_hash_map_remove(HashMap *map, void *key, BH_FREE(elem); if (map->lock) { - vm_mutex_unlock(map->lock); + os_mutex_unlock(map->lock); } return true; } @@ -245,7 +242,7 @@ bh_hash_map_remove(HashMap *map, void *key, } if (map->lock) { - vm_mutex_unlock(map->lock); + os_mutex_unlock(map->lock); } return false; } @@ -262,7 +259,7 @@ bh_hash_map_destroy(HashMap *map) } if (map->lock) { - vm_mutex_lock(map->lock); + os_mutex_lock(map->lock); } for (index = 0; index < map->size; index++) { @@ -283,8 +280,8 @@ bh_hash_map_destroy(HashMap *map) } if (map->lock) { - vm_mutex_unlock(map->lock); - vm_mutex_destroy(map->lock); + os_mutex_unlock(map->lock); + os_mutex_destroy(map->lock); } BH_FREE(map); return true; diff --git a/core/shared/include/bh_hashmap.h b/core/shared/utils/bh_hashmap.h similarity index 99% rename from core/shared/include/bh_hashmap.h rename to core/shared/utils/bh_hashmap.h index 7d260ec71..633c727e7 100644 --- a/core/shared/include/bh_hashmap.h +++ b/core/shared/utils/bh_hashmap.h @@ -8,7 +8,6 @@ #include "bh_platform.h" - #ifdef __cplusplus extern "C" { #endif diff --git a/core/shared/utils/bh_list.c b/core/shared/utils/bh_list.c index 9d6727af0..79f46adce 100644 --- a/core/shared/utils/bh_list.c +++ b/core/shared/utils/bh_list.c @@ -4,9 +4,8 @@ */ #include "bh_list.h" -#include "bh_assert.h" -#ifdef BH_DEBUG +#if BH_DEBUG != 0 /** * Test whehter a pointer value has exist in given list. * @@ -15,7 +14,7 @@ * @return true if the pointer has been in the list; * false otherwise. */ -BH_STATIC bool bh_list_is_elem_exist(bh_list *list, void *elem); +static bool bh_list_is_elem_exist(bh_list *list, void *elem); #endif bh_list_status bh_list_init(bh_list *list) @@ -28,13 +27,13 @@ bh_list_status bh_list_init(bh_list *list) return BH_LIST_SUCCESS; } -bh_list_status _bh_list_insert(bh_list *list, void *elem) +bh_list_status bh_list_insert(bh_list *list, void *elem) { bh_list_link *p = NULL; if (!list || !elem) return BH_LIST_ERROR; -#ifdef BH_DEBUG +#if BH_DEBUG != 0 bh_assert (!bh_list_is_elem_exist(list, elem)); #endif p = (bh_list_link *) elem; @@ -87,8 +86,8 @@ void* bh_list_elem_next(void *node) return (node ? ((bh_list_link *) node)->next : NULL); } -#ifdef BH_DEBUG -BH_STATIC bool bh_list_is_elem_exist(bh_list *list, void *elem) +#if BH_DEBUG != 0 +static bool bh_list_is_elem_exist(bh_list *list, void *elem) { bh_list_link *p = NULL; diff --git a/core/shared/include/bh_list.h b/core/shared/utils/bh_list.h similarity index 80% rename from core/shared/include/bh_list.h rename to core/shared/utils/bh_list.h index 2e429c69b..f47b93743 100644 --- a/core/shared/include/bh_list.h +++ b/core/shared/utils/bh_list.h @@ -10,7 +10,6 @@ extern "C" { #endif -#include "bh_types.h" /*For bool type*/ #include "bh_platform.h" /* List user should embedded bh_list_link into list elem data structure @@ -25,18 +24,19 @@ extern "C" { * bh_list_link is defined as a structure (not typedef void*). * It will make extend list into bi-direction easy. */ -typedef struct _bh_list_link { - struct _bh_list_link *next; +typedef struct bh_list_link { + struct bh_list_link *next; } bh_list_link; -typedef struct _bh_list { +typedef struct bh_list { bh_list_link head; uint32 len; } bh_list; -/* Beihai list operation return value */ -typedef enum _bh_list_status { - BH_LIST_SUCCESS = 0, BH_LIST_ERROR = -1 +/* list operation return value */ +typedef enum bh_list_status { + BH_LIST_SUCCESS = 0, + BH_LIST_ERROR = -1 } bh_list_status; /** @@ -57,14 +57,7 @@ bh_list_status bh_list_init(bh_list *list); * @return BH_LIST_ERROR if OK; * BH_LIST_ERROR if input is invalid or no memory available. */ -extern bh_list_status _bh_list_insert(bh_list *list, void *elem); - -#ifdef _INSTRUMENT_TEST_ENABLED -extern bh_list_status bh_list_insert_instr(bh_list *list, void *elem, const char*func_name); -#define bh_list_insert(list, elem) bh_list_insert_instr(list, elem, __FUNCTION__) -#else -#define bh_list_insert _bh_list_insert -#endif +extern bh_list_status bh_list_insert(bh_list *list, void *elem); /** * Remove an elem pointer from list. The list node memory is maintained by list while diff --git a/core/shared/utils/bh_log.c b/core/shared/utils/bh_log.c index 425dce428..808e234ac 100644 --- a/core/shared/utils/bh_log.c +++ b/core/shared/utils/bh_log.c @@ -2,213 +2,78 @@ * Copyright (C) 2019 Intel Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -/** - * @file bh_log.c - * @date Tue Nov 8 18:20:06 2011 - * - * @brief Implementation of Beihai's log system. - */ -#include "bh_assert.h" -#include "bh_time.h" -#include "bh_thread.h" #include "bh_log.h" -#include "bh_platform_log.h" /** * The verbose level of the log system. Only those verbose logs whose * levels are less than or equal to this value are outputed. */ -static int log_verbose_level; +static uint32 log_verbose_level = LOG_LEVEL_WARNING; -/** - * The lock for protecting the global output stream of logs. - */ -static korp_mutex log_stream_lock; - -/** - * The current logging thread that owns the log_stream_lock. - */ -static korp_tid cur_logging_thread = INVALID_THREAD_ID; - -/** - * Whether the currently being printed log is ennabled. - */ -static bool cur_log_enabled; - -int _bh_log_init() -{ - log_verbose_level = 3; - return vm_mutex_init(&log_stream_lock); -} - -void _bh_log_set_verbose_level(int level) +void +bh_log_set_verbose_level(uint32 level) { log_verbose_level = level; } -void _bh_log_printf(const char *fmt, ...) +void +bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - _bh_log_vprintf(fmt, ap); - va_end(ap); -} + korp_tid self; + char buf[32] = { 0 }; + uint64 usec; + uint32 t, h, m, s, mills; -#ifndef BH_PLATFORM_ANDROID -/** - * Return true if the given tag is enabled by the configuration. - * - * @param tag the tag (or prefix) of the log message. - * - * @return true if the log should be enabled. - */ -static bool is_log_enabled(const char *tag) -{ - /* Print all non-verbose or verbose logs whose levels are less than - or equal to the configured verbose level. */ - return tag[0] != 'V' || tag[1] - '0' <= log_verbose_level; -} - -/** - * Helper function for converting "..." to va_list. - */ -static void bh_log_emit_helper(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - bh_log_emit(fmt, ap); - va_end(ap); -} -#endif - -extern size_t _bh_time_strftime(char *s, size_t max, const char *format, - int64 time); - -void _bh_log_vprintf(const char *fmt, va_list ap) -{ -#ifndef BH_PLATFORM_ANDROID - korp_tid self = vm_self_thread(); - /* Try to own the log stream and start the log output. */ - if (self != cur_logging_thread) { - vm_mutex_lock(&log_stream_lock); - cur_logging_thread = self; - - if (fmt && (cur_log_enabled = is_log_enabled(fmt))) { - char buf[32]; - bh_time_strftime(buf, 32, "%Y-%m-%d %H:%M:%S", - (int64)bh_time_get_millisecond_from_1970()); - bh_log_emit_helper("\n[%s - %X]: ", buf, (int) self); - - /* Strip the "Vn." prefix. */ - if (fmt && strlen(fmt) >= 3 && fmt[0] == 'V' && fmt[1] && fmt[2]) - fmt += 3; - } - } -#else - // since we are using android log, do not worry about that - cur_log_enabled = true; -#endif//BH_PLATFORM_ANDROID - if (cur_log_enabled && fmt) - bh_log_emit(fmt, ap); -} - -void _bh_log_commit() -{ - if (vm_self_thread() != cur_logging_thread) - /* Ignore the single commit without printing anything. */ + if (log_level > log_verbose_level) return; - cur_logging_thread = INVALID_THREAD_ID; - vm_mutex_unlock(&log_stream_lock); -} + self = os_self_thread(); -void _bh_log(const char *tag, const char *file, int line, const char *fmt, ...) -{ - va_list ap; + usec = os_time_get_boot_microsecond(); + t = (uint32)(usec / 1000000) % (24 * 60 * 60); + h = t / (60 * 60); + t = t % (60 * 60); + m = t / 60; + s = t % 60; + mills = (uint32)(usec % 1000); -#ifndef BH_PLATFORM_ANDROID - if (tag) - _bh_log_printf(tag); + snprintf(buf, sizeof(buf), "%02u:%02u:%02u:%03u", h, m, s, mills); + + os_printf("[%s - %X]: ", buf, (uint32)self); if (file) - _bh_log_printf("%s:%d", file, line); -#else - (void)tag; - (void)file; - (void)line; -#endif//BH_PLATFORM_ANDROID + os_printf("%s, line %d, ", file, line); va_start(ap, fmt); - _bh_log_vprintf(fmt, ap); + os_vprintf(fmt, ap); va_end(ap); - _bh_log_commit(); + os_printf("\n"); } -#if defined(BH_DEBUG) +static uint32 last_time_ms = 0; +static uint32 total_time_ms = 0; -BH_STATIC char com_switchs[LOG_COM_MAX]; /* 0: off; 1: on */ -BH_STATIC char *com_names[LOG_COM_MAX] = {"app_manager", "gc", "hmc", "utils", - "verifier_jeff", "vmcore_jeff"}; - -BH_STATIC int com_find_name(const char **com) +void +bh_print_time(const char *prompt) { - int i; - const char *c, *name; + uint32 curr_time_ms; - for (i = 0; i < LOG_COM_MAX; i++) { - c = *com; - name = com_names[i]; - while (*name != '\0') { - if (*c != *name) - break; - c++; - name++; - } - if (*name == '\0') { - *com = c; - return i; - } - } - - return LOG_COM_MAX; -} - -void log_parse_coms(const char *coms) -{ - int i; - - for (i = LOG_COM_MAX; i--; ) - com_switchs[i] = 0; - - com_switchs[LOG_COM_UTILS] = 1; /* utils is a common part */ - - if (coms == NULL) - return; - - while (*coms != '\0') { - i = com_find_name(&coms); - if (i == LOG_COM_MAX) - break; - com_switchs[i] = 1; - - if (*coms == '\0') + if (log_verbose_level < 3) return; - if (*coms != ';') - break; - /* *com == ';' */ - coms++; - } - /* Log the message without aborting. */ - LOG_DEBUG(LOG_COM_UTILS, "The component names for logging are not right: %s.", coms); + curr_time_ms = (uint32)bh_get_tick_ms(); + + if (last_time_ms == 0) + last_time_ms = curr_time_ms; + + total_time_ms += curr_time_ms - last_time_ms; + + os_printf("%-48s time of last stage: %u ms, total time: %u ms\n", + prompt, curr_time_ms - last_time_ms, total_time_ms); + + last_time_ms = curr_time_ms; } -int bh_log_dcom_is_enabled(int component) -{ - return com_switchs[component]; -} - -#endif /* defined(BH_DEBUG) */ - diff --git a/core/shared/utils/bh_log.h b/core/shared/utils/bh_log.h new file mode 100644 index 000000000..279b9c11b --- /dev/null +++ b/core/shared/utils/bh_log.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ +/** + * @file bh_log.h + * @date Tue Nov 8 18:19:10 2011 + * + * @brief This log system supports wrapping multiple outputs into one + * log message. This is useful for outputting variable-length logs + * without additional memory overhead (the buffer for concatenating + * the message), e.g. exception stack trace, which cannot be printed + * by a single log calling without the help of an additional buffer. + * Avoiding additional memory buffer is useful for resource-constraint + * systems. It can minimize the impact of log system on applications + * and logs can be printed even when no enough memory is available. + * Functions with prefix "_" are private functions. Only macros that + * are not start with "_" are exposed and can be used. + */ + +#ifndef _BH_LOG_H +#define _BH_LOG_H + +#include "bh_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + LOG_LEVEL_FATAL = 0, + LOG_LEVEL_ERROR = 1, + LOG_LEVEL_WARNING = 2, + LOG_LEVEL_DEBUG = 3, + LOG_LEVEL_VERBOSE = 4 +} LogLevel; + +void +bh_log_set_verbose_level(uint32 level); + +void +bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...); + +#define LOG_FATAL(...) bh_log(LOG_LEVEL_FATAL, __FILE__, __LINE__, __VA_ARGS__) +#define LOG_ERROR(...) bh_log(LOG_LEVEL_ERROR, NULL, 0, __VA_ARGS__) +#define LOG_DEBUG(...) bh_log(LOG_LEVEL_DEBUG, __FILE__, __LINE__, 0, __VA_ARGS__) +#define LOG_WARNING(...) bh_log(LOG_LEVEL_WARNING, NULL, 0, __VA_ARGS__) +#define LOG_VERBOSE(...) bh_log(LOG_LEVEL_VERBOSE, NULL, 0, __VA_ARGS__) + +void +bh_print_time(const char *prompt); + +#ifdef __cplusplus +} +#endif + +#endif /* _BH_LOG_H */ diff --git a/core/shared/utils/bh_platform.h b/core/shared/utils/bh_platform.h new file mode 100644 index 000000000..6d7bd1141 --- /dev/null +++ b/core/shared/utils/bh_platform.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _BH_PLATFORM_H +#define _BH_PLATFORM_H + +#include "../platform/include/platform_common.h" +#include "../platform/include/platform_api_vmcore.h" +#include "../platform/include/platform_api_extension.h" +#include "bh_assert.h" +#include "bh_common.h" +#include "bh_hashmap.h" +#include "bh_list.h" +#include "bh_log.h" +#include "bh_queue.h" +#include "runtime_timer.h" + + + +/** + * WA_MALLOC/WA_FREE need to be redefined for both + * runtime native and WASM app respectively. + * + * Some source files are shared for building native and WASM, + * and this the mem allocator API for these files. + * + * Here we define it for the native world + */ +#ifndef WA_MALLOC +#define WA_MALLOC wasm_runtime_malloc +#endif + +#ifndef WA_FREE +#define WA_FREE wasm_runtime_free +#endif + +#endif /* #ifndef _BH_PLATFORM_H */ + diff --git a/core/shared/utils/bh_queue.c b/core/shared/utils/bh_queue.c index 4f74cee7e..60d873605 100644 --- a/core/shared/utils/bh_queue.c +++ b/core/shared/utils/bh_queue.c @@ -4,13 +4,10 @@ */ #include "bh_queue.h" -#include "bh_thread.h" -#include "bh_time.h" -#include "bh_common.h" -typedef struct _bh_queue_node { - struct _bh_queue_node * next; - struct _bh_queue_node * prev; +typedef struct bh_queue_node { + struct bh_queue_node * next; + struct bh_queue_node * prev; unsigned short tag; unsigned int len; void * body; @@ -124,7 +121,7 @@ bool bh_post_msg2(bh_queue *queue, bh_queue_node *msg) } bool bh_post_msg(bh_queue *queue, unsigned short tag, void *body, - unsigned int len) + unsigned int len) { bh_queue_node *msg = bh_new_msg(tag, body, len, NULL); if (msg == NULL) { @@ -143,10 +140,10 @@ bool bh_post_msg(bh_queue *queue, unsigned short tag, void *body, } bh_queue_node * bh_new_msg(unsigned short tag, void *body, unsigned int len, - void * handler) + void * handler) { - bh_queue_node *msg = (bh_queue_node*) bh_queue_malloc( - sizeof(bh_queue_node)); + bh_queue_node *msg = (bh_queue_node*) + bh_queue_malloc(sizeof(bh_queue_node)); if (msg == NULL) return NULL; memset(msg, 0, sizeof(bh_queue_node)); @@ -189,7 +186,7 @@ bh_message_t bh_get_msg(bh_queue *queue, int timeout) } bh_queue_cond_timedwait(&queue->queue_wait_cond, &queue->queue_lock, - timeout); + timeout); } if (queue->cnt == 0) { @@ -222,14 +219,14 @@ unsigned bh_queue_get_message_count(bh_queue *queue) } void bh_queue_enter_loop_run(bh_queue *queue, - bh_queue_handle_msg_callback handle_cb, - void *arg) + bh_queue_handle_msg_callback handle_cb, + void *arg) { if (!queue) return; while (!queue->exit_loop_run) { - bh_queue_node * message = bh_get_msg(queue, (int)BH_WAIT_FOREVER); + bh_queue_node * message = bh_get_msg(queue, (int)BHT_WAIT_FOREVER); if (message) { handle_cb(message, arg); diff --git a/core/shared/include/bh_queue.h b/core/shared/utils/bh_queue.h similarity index 61% rename from core/shared/include/bh_queue.h rename to core/shared/utils/bh_queue.h index 41792012f..8a98ac421 100644 --- a/core/shared/include/bh_queue.h +++ b/core/shared/utils/bh_queue.h @@ -10,11 +10,10 @@ extern "C" { #endif -#include "bh_types.h" /*For bool type*/ #include "bh_platform.h" -struct _bh_queue_node; -typedef struct _bh_queue_node * bh_message_t; +struct bh_queue_node; +typedef struct bh_queue_node * bh_message_t; struct bh_queue; typedef struct bh_queue bh_queue; @@ -24,26 +23,19 @@ typedef void (*bh_queue_handle_msg_callback)(void *message, void *arg); #define bh_queue_free BH_FREE #define bh_queue_mutex korp_mutex -#define bh_queue_sem korp_sem #define bh_queue_cond korp_cond -#define bh_queue_mutex_init vm_mutex_init -#define bh_queue_mutex_destroy vm_mutex_destroy -#define bh_queue_mutex_lock vm_mutex_lock -#define bh_queue_mutex_unlock vm_mutex_unlock +#define bh_queue_mutex_init os_mutex_init +#define bh_queue_mutex_destroy os_mutex_destroy +#define bh_queue_mutex_lock os_mutex_lock +#define bh_queue_mutex_unlock os_mutex_unlock -#define bh_queue_sem_init vm_sem_init -#define bh_queue_sem_destroy vm_sem_destroy -#define bh_queue_sem_wait vm_sem_wait -#define bh_queue_sem_reltimedwait vm_sem_reltimedwait -#define bh_queue_sem_post vm_sem_post - -#define bh_queue_cond_init vm_cond_init -#define bh_queue_cond_destroy vm_cond_destroy -#define bh_queue_cond_wait vm_cond_wait -#define bh_queue_cond_timedwait vm_cond_reltimedwait -#define bh_queue_cond_signal vm_cond_signal -#define bh_queue_cond_broadcast vm_cond_broadcast +#define bh_queue_cond_init os_cond_init +#define bh_queue_cond_destroy os_cond_destroy +#define bh_queue_cond_wait os_cond_wait +#define bh_queue_cond_timedwait os_cond_reltimedwait +#define bh_queue_cond_signal os_cond_signal +#define bh_queue_cond_broadcast os_cond_broadcast typedef void (*bh_msg_cleaner)(void *msg); @@ -58,10 +50,10 @@ uint32 bh_message_payload_len(bh_message_t message); int bh_message_type(bh_message_t message); bh_message_t bh_new_msg(unsigned short tag, void *body, unsigned int len, - void * handler); + void * handler); void bh_free_msg(bh_message_t msg); bool bh_post_msg(bh_queue *queue, unsigned short tag, void *body, - unsigned int len); + unsigned int len); bool bh_post_msg2(bh_queue *queue, bh_message_t msg); bh_message_t bh_get_msg(bh_queue *queue, int timeout); diff --git a/core/shared/utils/bh_vector.c b/core/shared/utils/bh_vector.c index 9b7c9db9e..15fc9fc29 100644 --- a/core/shared/utils/bh_vector.c +++ b/core/shared/utils/bh_vector.c @@ -3,10 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_log.h" #include "bh_vector.h" - static uint8* alloc_vector_data(uint32 length, uint32 size_elem) { diff --git a/core/shared/include/bh_vector.h b/core/shared/utils/bh_vector.h similarity index 99% rename from core/shared/include/bh_vector.h rename to core/shared/utils/bh_vector.h index 36f5bf11d..548c84970 100644 --- a/core/shared/include/bh_vector.h +++ b/core/shared/utils/bh_vector.h @@ -8,7 +8,6 @@ #include "bh_platform.h" - #ifdef __cplusplus extern "C" { #endif diff --git a/core/shared/utils/runtime_timer.c b/core/shared/utils/runtime_timer.c index c2894e4eb..68b25f8fa 100644 --- a/core/shared/utils/runtime_timer.c +++ b/core/shared/utils/runtime_timer.c @@ -4,8 +4,6 @@ */ #include "runtime_timer.h" -#include "bh_thread.h" -#include "bh_time.h" #define PRINT(...) //#define PRINT printf @@ -34,13 +32,18 @@ struct _timer_ctx { check_timer_expiry_f refresh_checker; }; +uint64 bh_get_tick_ms() +{ + return os_time_get_boot_microsecond() / 1000; +} + uint32 bh_get_elpased_ms(uint32 * last_system_clock) { uint32 elpased_ms; // attention: the bh_get_tick_ms() return 64 bits integer. // but the bh_get_elpased_ms() is designed to use 32 bits clock count. - uint32 now = (uint32) bh_get_tick_ms(); + uint32 now = (uint32)bh_get_tick_ms(); // system clock overrun if (now < *last_system_clock) { @@ -57,7 +60,7 @@ uint32 bh_get_elpased_ms(uint32 * last_system_clock) static app_timer_t * remove_timer_from(timer_ctx_t ctx, uint32 timer_id, bool active_list) { - vm_mutex_lock(&ctx->mutex); + os_mutex_lock(&ctx->mutex); app_timer_t ** head; if (active_list) head = &ctx->g_app_timers; @@ -76,7 +79,7 @@ static app_timer_t * remove_timer_from(timer_ctx_t ctx, uint32 timer_id, prev->next = t->next; PRINT("removed timer [%d] after [%d] from list %d\n", t->id, prev->id, active_list); } - vm_mutex_unlock(&ctx->mutex); + os_mutex_unlock(&ctx->mutex); if (active_list && prev == NULL && ctx->refresh_checker) ctx->refresh_checker(ctx); @@ -88,7 +91,7 @@ static app_timer_t * remove_timer_from(timer_ctx_t ctx, uint32 timer_id, } } - vm_mutex_unlock(&ctx->mutex); + os_mutex_unlock(&ctx->mutex); return NULL; } @@ -111,7 +114,7 @@ static app_timer_t * remove_timer(timer_ctx_t ctx, uint32 timer_id, static void reschedule_timer(timer_ctx_t ctx, app_timer_t * timer) { - vm_mutex_lock(&ctx->mutex); + os_mutex_lock(&ctx->mutex); app_timer_t * t = ctx->g_app_timers; app_timer_t * prev = NULL; @@ -130,7 +133,7 @@ static void reschedule_timer(timer_ctx_t ctx, app_timer_t * timer) PRINT("rescheduled timer [%d] after [%d]\n", timer->id, prev->id); } - vm_mutex_unlock(&ctx->mutex); + os_mutex_unlock(&ctx->mutex); // ensure the refresh_checker() is called out of the lock if (prev == NULL && ctx->refresh_checker) @@ -154,7 +157,7 @@ static void reschedule_timer(timer_ctx_t ctx, app_timer_t * timer) PRINT("rescheduled timer [%d] as first\n", timer->id); } - vm_mutex_unlock(&ctx->mutex); + os_mutex_unlock(&ctx->mutex); // ensure the refresh_checker() is called out of the lock if (prev == NULL && ctx->refresh_checker) @@ -165,11 +168,11 @@ static void reschedule_timer(timer_ctx_t ctx, app_timer_t * timer) static void release_timer(timer_ctx_t ctx, app_timer_t * t) { if (ctx->pre_allocated) { - vm_mutex_lock(&ctx->mutex); + os_mutex_lock(&ctx->mutex); t->next = ctx->free_timers; ctx->free_timers = t; PRINT("recycle timer :%d\n", t->id); - vm_mutex_unlock(&ctx->mutex); + os_mutex_unlock(&ctx->mutex); } else { PRINT("destroy timer :%d\n", t->id); BH_FREE(t); @@ -220,14 +223,14 @@ timer_ctx_t create_timer_ctx(timer_callback_f timer_handler, prealloc_num--; } - vm_cond_init(&ctx->cond); - vm_mutex_init(&ctx->mutex); + os_cond_init(&ctx->cond); + os_mutex_init(&ctx->mutex); PRINT("timer ctx created. pre-alloc: %d\n", ctx->pre_allocated); return ctx; - cleanup: +cleanup: if (ctx) { release_timer_list(&ctx->free_timers); @@ -247,8 +250,8 @@ void destroy_timer_ctx(timer_ctx_t ctx) cleanup_app_timers(ctx); - vm_cond_destroy(&ctx->cond); - vm_mutex_destroy(&ctx->mutex); + os_cond_destroy(&ctx->cond); + os_mutex_destroy(&ctx->mutex); BH_FREE(ctx); } @@ -259,10 +262,10 @@ unsigned int timer_ctx_get_owner(timer_ctx_t ctx) void add_idle_timer(timer_ctx_t ctx, app_timer_t * timer) { - vm_mutex_lock(&ctx->mutex); + os_mutex_lock(&ctx->mutex); timer->next = ctx->idle_timers; ctx->idle_timers = timer; - vm_mutex_unlock(&ctx->mutex); + os_mutex_unlock(&ctx->mutex); } uint32 sys_create_timer(timer_ctx_t ctx, int interval, bool is_period, @@ -376,21 +379,21 @@ int get_expiry_ms(timer_ctx_t ctx) int ms_to_next_expiry; uint64 now = bh_get_tick_ms(); - vm_mutex_lock(&ctx->mutex); + os_mutex_lock(&ctx->mutex); if (ctx->g_app_timers == NULL) ms_to_next_expiry = 7 * 24 * 60 * 60 * 1000; // 1 week else if (ctx->g_app_timers->expiry >= now) ms_to_next_expiry = (int)(ctx->g_app_timers->expiry - now); else ms_to_next_expiry = 0; - vm_mutex_unlock(&ctx->mutex); + os_mutex_unlock(&ctx->mutex); return ms_to_next_expiry; } int check_app_timers(timer_ctx_t ctx) { - vm_mutex_lock(&ctx->mutex); + os_mutex_lock(&ctx->mutex); app_timer_t * t = ctx->g_app_timers; app_timer_t * expired = NULL; @@ -409,7 +412,7 @@ int check_app_timers(timer_ctx_t ctx) break; } } - vm_mutex_unlock(&ctx->mutex); + os_mutex_unlock(&ctx->mutex); handle_expired_timers(ctx, expired); @@ -418,11 +421,11 @@ int check_app_timers(timer_ctx_t ctx) void cleanup_app_timers(timer_ctx_t ctx) { - vm_mutex_lock(&ctx->mutex); + os_mutex_lock(&ctx->mutex); release_timer_list(&ctx->g_app_timers); release_timer_list(&ctx->idle_timers); - vm_mutex_unlock(&ctx->mutex); + os_mutex_unlock(&ctx->mutex); } diff --git a/core/shared/utils/runtime_timer.h b/core/shared/utils/runtime_timer.h index b4aa657c3..f173de546 100644 --- a/core/shared/utils/runtime_timer.h +++ b/core/shared/utils/runtime_timer.h @@ -12,7 +12,8 @@ extern "C" { #endif -uint32 bh_get_elpased_ms(uint32 * last_system_clock); +uint64 bh_get_tick_ms(); +uint32 bh_get_elpased_ms(uint32 *last_system_clock); struct _timer_ctx; typedef struct _timer_ctx * timer_ctx_t; @@ -20,12 +21,13 @@ typedef void (*timer_callback_f)(uint32 id, unsigned int owner); typedef void (*check_timer_expiry_f)(timer_ctx_t ctx); timer_ctx_t create_timer_ctx(timer_callback_f timer_handler, - check_timer_expiry_f, int prealloc_num, unsigned int owner); + check_timer_expiry_f, int prealloc_num, + unsigned int owner); void destroy_timer_ctx(timer_ctx_t); unsigned int timer_ctx_get_owner(timer_ctx_t ctx); uint32 sys_create_timer(timer_ctx_t ctx, int interval, bool is_period, - bool auto_start); + bool auto_start); bool sys_timer_destroy(timer_ctx_t ctx, uint32 timer_id); bool sys_timer_cancel(timer_ctx_t ctx, uint32 timer_id); bool sys_timer_restart(timer_ctx_t ctx, uint32 timer_id, int interval); diff --git a/core/shared/utils/shared_utils.cmake b/core/shared/utils/shared_utils.cmake index 44a150bf5..5b7d02dde 100644 --- a/core/shared/utils/shared_utils.cmake +++ b/core/shared/utils/shared_utils.cmake @@ -4,10 +4,8 @@ set (UTILS_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories(${UTILS_SHARED_DIR}) -include_directories(${UTILS_SHARED_DIR}/../include) - -file (GLOB_RECURSE source_all ${UTILS_SHARED_DIR}/*.c) +file (GLOB source_all ${UTILS_SHARED_DIR}/*.c) set (UTILS_SHARED_SOURCE ${source_all}) diff --git a/core/shared/utils/uncommon/bh_read_file.c b/core/shared/utils/uncommon/bh_read_file.c new file mode 100644 index 000000000..f93b28d08 --- /dev/null +++ b/core/shared/utils/uncommon/bh_read_file.c @@ -0,0 +1,53 @@ +#include "bh_read_file.h" + +#include +#include +#include + +char* +bh_read_file_to_buffer(const char *filename, uint32 *ret_size) +{ + char *buffer; + int file; + uint32 file_size, read_size; + struct stat stat_buf; + + if (!filename || !ret_size) { + printf("Read file to buffer failed: invalid filename or ret size.\n"); + return NULL; + } + + if ((file = open(filename, O_RDONLY, 0)) == -1) { + printf("Read file to buffer failed: open file %s failed.\n", + filename); + return NULL; + } + + if (fstat(file, &stat_buf) != 0) { + printf("Read file to buffer failed: fstat file %s failed.\n", + filename); + close(file); + return NULL; + } + + file_size = (uint32)stat_buf.st_size; + + if (!(buffer = BH_MALLOC(file_size))) { + printf("Read file to buffer failed: alloc memory failed.\n"); + close(file); + return NULL; + } + + read_size = (uint32)read(file, buffer, file_size); + close(file); + + if (read_size < file_size) { + printf("Read file to buffer failed: read file content failed.\n"); + BH_FREE(buffer); + return NULL; + } + + *ret_size = file_size; + return buffer; +} + diff --git a/core/shared/platform/include/bh_platform_log.h b/core/shared/utils/uncommon/bh_read_file.h similarity index 55% rename from core/shared/platform/include/bh_platform_log.h rename to core/shared/utils/uncommon/bh_read_file.h index 2513055e7..7c947d621 100644 --- a/core/shared/platform/include/bh_platform_log.h +++ b/core/shared/utils/uncommon/bh_read_file.h @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#ifndef BH_PLATFORM_LOG -#define BH_PLATFORM_LOG +#ifndef _BH_FILE_H +#define _BH_FILE_H #include "bh_platform.h" @@ -12,14 +12,12 @@ extern "C" { #endif -void bh_log_emit(const char *fmt, va_list ap); - -int bh_fprintf(void *stream, const char *fmt, ...); - -int bh_fflush(void *stream); +char * +bh_read_file_to_buffer(const char *filename, uint32 *ret_size); #ifdef __cplusplus } #endif -#endif +#endif /* end of _BH_FILE_H */ + diff --git a/core/shared/utils/uncommon/shared_uncommon.cmake b/core/shared/utils/uncommon/shared_uncommon.cmake new file mode 100644 index 000000000..0a15b87b8 --- /dev/null +++ b/core/shared/utils/uncommon/shared_uncommon.cmake @@ -0,0 +1,11 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (UNCOMMON_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${UNCOMMON_SHARED_DIR}) + +file (GLOB_RECURSE source_all ${UNCOMMON_SHARED_DIR}/*.c) + +set (UNCOMMON_SHARED_SOURCE ${source_all}) + diff --git a/doc/build_wamr.md b/doc/build_wamr.md index 2f845fa50..4485a4345 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -1,64 +1,82 @@ Build WAMR core (iwasm) ========================= -It is recommended to use the [WAMR SDK](../wamr-sdk) tools to build a project that embedes the WAMR. This document introduces how to build the WAMR minimal product which is vmcore only (no app-framework and app-mgr) for multiple platforms. +It is recommended to use the [WAMR SDK](../wamr-sdk) tools to build a project that integrates the WAMR. This document introduces how to build the WAMR minimal product which is vmcore only (no app-framework and app-mgr) for multiple platforms. ## iwasm VM core CMake building configurations -By including the cmake scripts under folder [build-scripts](../build-scripts), it is easy to build minimal product with CMake. WAMR provides a number of features which can be easily configured through cmake variables: +By including the script `runtime_lib.cmake` under folder [build-scripts](../build-scripts) in CMakeList.txt, it is easy to build minimal product with CMake. -``` Bash -cmake -DWAMR_BUILD_INTERP=1/0 to enable or disable WASM intepreter -cmake -DWAMR_BUILD_FAST_INTERP=1/0 to build fast (default) or classic WASM intepreter. -cmake -DWAMR_BUILD_AOT=1/0 to enable or disable WASM AOT -cmake -DWAMR_BUILD_JIT=1/0 to enable or disable WASM JIT. (Disabled by default) -cmake -DWAMR_BUILD_LIBC_BUILTIN=1/0 enable or disable Libc builtin API's. (Enabled by default) -cmake -DWAMR_BUILD_LIBC_WASI=1/0 enable or disable Libc WASI API's -cmake -DWAMR_BUILD_TARGET= to set the building target, including: - X86_64, X86_32, ARM, THUMB, XTENSA and MIPS - For ARM and THUMB, the format is [][_VFP] where is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both and [_VFP] are optional. e.g. ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. +```cmake +# add this in your CMakeList.text +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) ``` -For example, if we want to enable classic interpreter, we can: + + +The script `runtime_lib.cmake` defined a number of variables for configuring the WAMR runtime features. You can set these variables in your CMakeList.txt or pass the configurations from cmake command line. + +#### **Configure platform and architecture** + +- **WAMR_BUILD_PLATFORM**: set the target platform. It can be set to any platform name (folder name) under folder [core/shared/platform](../core/shared/platform). + +- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets: X86_64, X86_32, AArch64, ARM, THUMB, XTENSA and MIPS. For AArch64, ARM and THUMB, the format is [][_VFP] where is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both and "_VFP" are optional. e.g. AARCH64, AARCH64V8, AARCHV8.1, ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. + + ```bash + cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM + ``` + +#### **Configure interpreter** + +- **WAMR_BUILD_INTERP**=1/0: enable or disable WASM interpreter + +- **WAMR_BUILD_FAST_INTERP**=1/0:build fast (default) or classic WASM interpreter. + + NOTE: the fast interpreter will run ~2X faster than classic interpreter, but it consumes about 2X memory to hold the WASM bytecode code. + +#### **Configure AoT and JIT** + +- **WAMR_BUILD_AOT**=1/0 +- **WAMR_BUILD_JIT**=1/0 , (Disabled if no set) + +#### **Configure LIBC** + +- **WAMR_BUILD_LIBC_BUILTIN**=1/0, default to enable if no set + +- **WAMR_BUILD_LIBC_WASI**=1/0, default to disable if no set + + + +**Combination of configurations:** + +We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command: ``` Bash -cmake .. -DWAMR_BUILD_FAST_INTERP=0 +cmake .. -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_LIBC_WASI=0 -DWAMR_BUILD_PLATFORM=linux ``` -**Note** the fast interpreter will run ~2X faster than classic interpreter, but it consumes about 2X memory to hold the WASM bytecode code. - -If we want to disable interpreter, enable AOT and WASI, we can: - -``` Bash -cmake .. -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_LIBC_WASI=0 -``` - -Or if we want to enable inerpreter, disable AOT and WASI, and build as X86_32, we can: +Or if we want to enable interpreter, disable AOT and WASI, and build as X86_32, we can run command: ``` Bash cmake .. -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_LIBC_WASI=0 -DWAMR_BUILD_TARGET=X86_32 ``` -By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled. And the build target is -set to X86_64 or X86_32 depending on the platform's bitwidth. -To enable WASM JIT, firstly we should build LLVM: -``` Bash -cd product-mini/platforms/linux/ -./build_llvm.sh (The llvm source code is cloned under /core/deps/llvm and auto built) +## Cross compilation + +If you are building for ARM architecture on a X86 development machine, you can use the `CMAKE_TOOLCHAIN_FILE` to set the toolchain file for cross compling. + +``` +cmake .. -DCMAKE_TOOLCHAIN_FILE=$TOOL_CHAIN_FILE \ + -DWAMR_BUILD_PLATFORM=linux \ + -DWAMR_BUILD_TARGET=ARM ``` -Then pass option -DWAMR_BUILD_JIT=1 to cmake to enable WASM JIT: - -``` Bash -mkdir build -cd build -cmake .. -DWAMR_BUILD_JIT=1 -make -``` +Refer to toochain sample file [`samples/simple/profiles/arm-interp/toolchain.cmake`](../samples/simple/profiles/arm-interp/toolchain.cmake) for how to build mini product for ARM target architecture. @@ -87,9 +105,26 @@ cd build cmake .. make ``` -The binary file iwasm will be generated under build folder. +By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled. And the build target is +set to X86_64 or X86_32 depending on the platform's bitwidth. + +To enable WASM JIT, firstly we should build LLVM: + +``` Bash +cd product-mini/platforms/linux/ +./build_llvm.sh (The llvm source code is cloned under /core/deps/llvm and auto built) +``` + +Then pass argument `-DWAMR_BUILD_JIT=1` to cmake to enable WASM JIT: + +``` Bash +mkdir build +cd build +cmake .. -DWAMR_BUILD_JIT=1 +make +``` @@ -183,18 +218,11 @@ cp -a /product-mini/platforms/zephyr/simple . cd simple ln -s wamr source ../../zephyr-env.sh +# Execute the ./build_and_run.sh script with board name as parameter. Here take x86 as example: +./build_and_run.sh x86 ``` -1. build for x86 (qemu_x86_nommu) -``` Bash -./build.sh x86 -``` -2. build for ARM (nucleo_f767zi) -``` Bash -./build.sh stm32 -``` - Note: WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in Zephyr, interpreter, AoT and builtin libc are enabled by default. @@ -231,7 +259,8 @@ AliOS-Things $(NAME)_COMPONENTS := osal_aos iwasm ``` 7. build source code and run - For linuxhost: + For linux host: + ``` Bash aos make helloworld@linuxhost -c config aos make @@ -240,6 +269,7 @@ AliOS-Things For developerkit: Modify file middleware/iwasm/aos.mk, patch as: + ``` C WAMR_BUILD_TARGET := THUMBV7M ``` diff --git a/doc/build_wasm_app.md b/doc/build_wasm_app.md index 2cf6239cc..39b6ed977 100644 --- a/doc/build_wasm_app.md +++ b/doc/build_wasm_app.md @@ -90,7 +90,7 @@ wamrc supports a number of compilation options through the command line argument wamrc --help Usage: wamrc [options] -o output_file wasm_file --target= Set the target arch, which has the general format: - = x86_64, i386, arm, thumb, mips. + = x86_64, i386, aarch64, arm, thumb, xtensa, mips. Default is host arch, e.g. x86_64 = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc. Use --target=help to list supported targets diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index 390dd7ebd..d6f20e346 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -196,7 +196,7 @@ if(buffer_for_wasm != 0) // it is runtime responsibility to release the memory, // unless the WASM app will free the passed pointer in its code - wasm_runtime_module_free(module_inst, buffer); + wasm_runtime_module_free(module_inst, buffer_for_wasm); } ``` diff --git a/doc/port_wamr.md b/doc/port_wamr.md index 50a6e619f..44ac50ece 100644 --- a/doc/port_wamr.md +++ b/doc/port_wamr.md @@ -3,44 +3,64 @@ WAMR porting guide ========================= -This document describes how to port WAMR to a new platform "**super-os**" +This document describes how to port WAMR to a new platform "**new-os**" -# Step 1: Create folders for the new platform +# Step 1: Implement platform API layer ------------------------- -Create folders: -- **core/shared/platform/super-os**: for platform API layer implementations -- **product-mini/platforms/super-os**: for the platform mini product build +Firstly create the folder **`core/shared/platform/new-os`** for platform API layer implementations. In the folder you just created, you must provide the following files: -# Step 2: Implement platform API layer +- `platform_internal.h`: It can be used for any platform specific definitions such as macros, data types and internal APIs. + +- `shared_platform.cmake`: the cmake file will be included by the building script. It is recommended to add a definition for your platform: + + - ```cmake + add_definitions(-DBH_PLATFORM_YOUR_NAME) + ``` + +Then go to implement the APIs defined in following header files for the platform abstraction layer: + +- [`platform_api_vmcore.h`](../core/shared/platform/include/platform_api_vmcore.h): mandatory for building mini-product (vmcore only). Part of APIs are needed only for Ahead of Time compilation support. +- [`platform_api_extension.h`](../core/shared/platform/include/platform_api_extension.h): mandatory for app-mgr and app-framework. Given that the app-mgr and app-framework are not required for your target platform, you won't have to implement the API defined in the `platform_api_extension.h`. + + + +**common/posix:** + +There is posix based implementation of the platform API located in the `platform/common/posix` folder. You can include it if your platform support posix API. refer to platform linux implementation. + + + +**common/math:** + +Some platforms such as ZephyrOS don't provide math functions e.g. sqrt, fabs and isnan, then you should include source files under the folder `platform/common/math`. + + + +# Step 2: Create the mini product for the platform ------------------------- -Implement folder core/shared/platform/super-os. Normally in this folder you should implement the following files: -- bh_platform.h and bh_platform.c: define the platform related macros, data types and APIs. -- bh_assert.c: implement function bh_assert_internal() and bh_debug_internal(). -- bh_platform_log.c: implement function bh_log_emit, bh_fprintf and bh_fflush. -- bh_time.c: implement several time related functions. -- bh_thread.c: implement thread, mutex, condition related functions. -- bh_math.c: implement some math functions if the platform doesn't support them, e.g. sqrt, - fabs and isnan. We may use the open source fdlibm implementation, for example, - ref to platform/zephyr/bh_math.c. +You can build a mini WAMR product which is only the vmcore for you platform. Normally you need to implement the main function which loads a WASM file and run it with the WASM runtime. You don't have to do this step if there is no mini-product need for your platform porting. -Please ref to implementation of other platform for more details, e.g. platform/zephyr, platform/linux. -# Step 3: Create the mini product build for the platform -------------------------- -Implement folder product-mini/platforms/super-os. Normally this folder is to implement the C main function, and generate a WAMR VM core binary named iwasm which can load and run wasm apps. We should implement following files: -- main.c: implement the C main function, which reads wasm file to buffer, loads the wasm file to wasm module, instantiate the module, lookup wasm app main function, and then execute the function. -- ext_lib_export.c: implement the native APIs if you want, and if no native API is to be implemented, just keep array extended_native_symbol_defs empty. -- CMakeLists.txt: there are some settings which can be passed from cmake variables: - - set (WAMR_BUILD_PLATFORM "platform_name"): set the name of the platform - - set (WAMR_BUILD_TARGET ): set the build target, currently the value supported: X86_64, X86_32, ARM[sub], THUMB[sub], MIPS and XTENSA. For ARM and THUMB, you can specify the sub version, e.g. ARMV4, ARMV7, THUMBV4T, THUMBV7T. - - set (WAMR_BUILD_INTERP 1 or 0): whether to interpreter or not - - set (WAMR_BUILD_AOT 1 or 0): whether to build AOT or not - - set (WAMR_BUILD_JIT 1 or 0): whether to build JIT or not - - set (WAMR_BUILD_LIBC_BUILTIN 1 or 0): whether to build Libc builtin or not - - set (WAMR_BUILD_LIBC_WASI 1 or 0): whether to build Libc WASI or not +Firstly create folder **product-mini/platforms/new-os** for the platform mini product build, then refer to the linux platform mini-product for creating the CMakeList.txt and the C implementations. + + + +You should set cmake variable `WAMR_BUILD_PLATFORM` to your platform name while building the mini product. It can be done in the mini product CMakeList.txt file, or pass arguments to cmake command line like: + +``` +mkdir build +cd build +cmake .. -DWAMR_BUILD_PLATFORM=new-os +``` + + + +Refer to [build_wamr.md](./build_wamr.md) for the building configurations and parameters. + + diff --git a/product-mini/platforms/alios-things/aos.mk b/product-mini/platforms/alios-things/aos.mk index 2d82a459b..4cdf95dda 100644 --- a/product-mini/platforms/alios-things/aos.mk +++ b/product-mini/platforms/alios-things/aos.mk @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception NAME := iwasm +CORE_ROOT := wamr/core IWASM_ROOT := wamr/core/iwasm SHARED_ROOT := wamr/core/shared @@ -59,10 +60,13 @@ endif GLOBAL_DEFINES += WASM_ENABLE_LIBC_BUILTIN=1 -GLOBAL_INCLUDES += ${IWASM_ROOT}/include \ +GLOBAL_INCLUDES += ${CORE_ROOT} \ + ${IWASM_ROOT}/include \ ${IWASM_ROOT}/common \ ${SHARED_ROOT}/include \ ${SHARED_ROOT}/platform/include \ + ${SHARED_ROOT}/utils \ + ${SHARED_ROOT}/mem-alloc \ ${SHARED_ROOT}/platform/alios ifeq (${WAMR_BUILD_INTERP}, 1) @@ -73,22 +77,22 @@ ifeq (${WAMR_BUILD_AOT}, 1) GLOBAL_INCLUDES += ${IWASM_ROOT}/aot endif -$(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/bh_assert.c \ - ${SHARED_ROOT}/platform/alios/bh_math.c \ - ${SHARED_ROOT}/platform/alios/bh_platform.c \ - ${SHARED_ROOT}/platform/alios/bh_platform_log.c \ - ${SHARED_ROOT}/platform/alios/bh_thread.c \ - ${SHARED_ROOT}/platform/alios/bh_time.c \ +$(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/alios_platform.c \ + ${SHARED_ROOT}/platform/alios/alios_thread.c \ + ${SHARED_ROOT}/platform/alios/alios_time.c \ + ${SHARED_ROOT}/platform/common/math/math.c \ ${SHARED_ROOT}/mem-alloc/mem_alloc.c \ ${SHARED_ROOT}/mem-alloc/ems/ems_kfc.c \ ${SHARED_ROOT}/mem-alloc/ems/ems_alloc.c \ ${SHARED_ROOT}/mem-alloc/ems/ems_hmu.c \ - ${SHARED_ROOT}/utils/bh_definition.c \ + ${SHARED_ROOT}/utils/bh_assert.c \ + ${SHARED_ROOT}/utils/bh_common.c \ ${SHARED_ROOT}/utils/bh_hashmap.c \ ${SHARED_ROOT}/utils/bh_list.c \ ${SHARED_ROOT}/utils/bh_log.c \ ${SHARED_ROOT}/utils/bh_queue.c \ ${SHARED_ROOT}/utils/bh_vector.c \ + ${SHARED_ROOT}/utils/runtime_timer.c \ ${IWASM_ROOT}/libraries/libc-builtin/libc_builtin_wrapper.c \ ${IWASM_ROOT}/common/wasm_runtime_common.c \ ${IWASM_ROOT}/common/wasm_native.c \ diff --git a/product-mini/platforms/alios-things/src/main.c b/product-mini/platforms/alios-things/src/main.c index 6c5d322b7..1c148432c 100644 --- a/product-mini/platforms/alios-things/src/main.c +++ b/product-mini/platforms/alios-things/src/main.c @@ -7,7 +7,6 @@ #include #include "bh_platform.h" #include "bh_log.h" -#include "bh_platform_log.h" #include "wasm_export.h" #include "test_wasm.h" @@ -35,7 +34,7 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - bh_printf("%s\n", exception); + printf("%s\n", exception); return NULL; } @@ -63,7 +62,7 @@ void iwasm_main(void *arg1) /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return; } @@ -78,7 +77,7 @@ void iwasm_main(void *arg1) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail1; } @@ -88,7 +87,7 @@ void iwasm_main(void *arg1) 8 * 1024, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail2; } diff --git a/product-mini/platforms/android/CMakeLists.txt b/product-mini/platforms/android/CMakeLists.txt index bdfd10e19..26f9c737e 100644 --- a/product-mini/platforms/android/CMakeLists.txt +++ b/product-mini/platforms/android/CMakeLists.txt @@ -27,7 +27,7 @@ set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # Set WAMR_BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" if (NOT DEFINED WAMR_BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform @@ -101,7 +101,5 @@ set (distribution_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build/distribution) set_target_properties (iwasm PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${distribution_DIR}/wasm/lib") add_custom_command (TARGET iwasm POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy_directory "${WAMR_ROOT_DIR}/core/shared/include" "${distribution_DIR}/wasm/include/" - COMMAND "${CMAKE_COMMAND}" -E copy_directory "${WAMR_ROOT_DIR}/core/shared/platform/include" "${distribution_DIR}/wasm/include/platform/" - COMMAND "${CMAKE_COMMAND}" -E copy "${WAMR_ROOT_DIR}/core/shared/platform/android/bh_platform.h" "${distribution_DIR}/wasm/include/platform/" + COMMAND "${CMAKE_COMMAND}" -E copy_directory "${WAMR_ROOT_DIR}/core/iwasm/include" "${distribution_DIR}/wasm/include/" COMMENT "Copying iwasm to output directory") diff --git a/product-mini/platforms/android/wasm-jni.cpp b/product-mini/platforms/android/wasm-jni.cpp index 648f7e54c..82722364e 100644 --- a/product-mini/platforms/android/wasm-jni.cpp +++ b/product-mini/platforms/android/wasm-jni.cpp @@ -3,9 +3,7 @@ #include #include #include -#include #include -#include #include #define LOGI(...) \ @@ -23,54 +21,54 @@ app_instance_main(wasm_module_inst_t module_inst) { // WARNING! CAN NOT BE READ ONLY!!! static unsigned char wasm_test_file[] = { 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x06, 0x64, 0x79, 0x6C, 0x69, 0x6E, 0x6B, 0xC0, 0x80, - 0x04, 0x04, 0x00, 0x00, 0x01, 0x13, 0x04, 0x60, 0x01, 0x7F, 0x00, 0x60, - 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x00, - 0x00, 0x02, 0x58, 0x06, 0x03, 0x65, 0x6E, 0x76, 0x05, 0x5F, 0x66, 0x72, - 0x65, 0x65, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x5F, 0x6D, 0x61, - 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x5F, - 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, - 0x05, 0x5F, 0x70, 0x75, 0x74, 0x73, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, - 0x0D, 0x5F, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x5F, 0x62, 0x61, - 0x73, 0x65, 0x03, 0x7F, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x65, - 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x01, 0x03, 0x04, 0x03, 0x02, 0x03, - 0x03, 0x06, 0x10, 0x03, 0x7F, 0x01, 0x41, 0x00, 0x0B, 0x7F, 0x01, 0x41, - 0x00, 0x0B, 0x7F, 0x00, 0x41, 0x1B, 0x0B, 0x07, 0x33, 0x04, 0x12, 0x5F, - 0x5F, 0x70, 0x6F, 0x73, 0x74, 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6E, - 0x74, 0x69, 0x61, 0x74, 0x65, 0x00, 0x06, 0x05, 0x5F, 0x6D, 0x61, 0x69, - 0x6E, 0x00, 0x04, 0x0B, 0x72, 0x75, 0x6E, 0x50, 0x6F, 0x73, 0x74, 0x53, - 0x65, 0x74, 0x73, 0x00, 0x05, 0x04, 0x5F, 0x73, 0x74, 0x72, 0x03, 0x03, - 0x0A, 0xBA, 0x01, 0x03, 0x9E, 0x01, 0x01, 0x01, 0x7F, 0x23, 0x01, 0x21, - 0x00, 0x23, 0x01, 0x41, 0x10, 0x6A, 0x24, 0x01, 0x20, 0x00, 0x41, 0x08, - 0x6A, 0x21, 0x02, 0x23, 0x00, 0x41, 0x1B, 0x6A, 0x10, 0x03, 0x1A, 0x41, - 0x80, 0x08, 0x10, 0x01, 0x21, 0x01, 0x20, 0x01, 0x04, 0x7F, 0x20, 0x00, - 0x20, 0x01, 0x36, 0x02, 0x00, 0x23, 0x00, 0x20, 0x00, 0x10, 0x02, 0x1A, - 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, 0x0D, 0x3A, 0x00, 0x00, 0x20, 0x01, - 0x23, 0x00, 0x2C, 0x00, 0x0E, 0x3A, 0x00, 0x01, 0x20, 0x01, 0x23, 0x00, - 0x2C, 0x00, 0x0F, 0x3A, 0x00, 0x02, 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, - 0x10, 0x3A, 0x00, 0x03, 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, 0x11, 0x3A, - 0x00, 0x04, 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, 0x12, 0x3A, 0x00, 0x05, - 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x00, 0x23, 0x00, 0x41, 0x13, 0x6A, - 0x20, 0x02, 0x10, 0x02, 0x1A, 0x20, 0x01, 0x10, 0x00, 0x20, 0x00, 0x24, - 0x01, 0x41, 0x00, 0x05, 0x23, 0x00, 0x41, 0x28, 0x6A, 0x10, 0x03, 0x1A, - 0x20, 0x00, 0x24, 0x01, 0x41, 0x7F, 0x0B, 0x0B, 0x03, 0x00, 0x01, 0x0B, - 0x14, 0x00, 0x23, 0x00, 0x41, 0x40, 0x6B, 0x24, 0x01, 0x23, 0x01, 0x41, - 0x80, 0x80, 0x04, 0x6A, 0x24, 0x02, 0x10, 0x05, 0x0B, 0x0B, 0x3F, 0x01, - 0x00, 0x23, 0x00, 0x0B, 0x39, 0x62, 0x75, 0x66, 0x20, 0x70, 0x74, 0x72, - 0x3A, 0x20, 0x25, 0x70, 0x0A, 0x00, 0x31, 0x32, 0x33, 0x34, 0x0A, 0x00, - 0x62, 0x75, 0x66, 0x3A, 0x20, 0x25, 0x73, 0x00, 0x48, 0x65, 0x6C, 0x6C, - 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00, 0x6D, 0x61, 0x6C, - 0x6C, 0x6F, 0x63, 0x20, 0x62, 0x75, 0x66, 0x20, 0x66, 0x61, 0x69, 0x6C, - 0x65, 0x64, 0x00, 0x50, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x01, 0x49, 0x07, - 0x00, 0x05, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x01, 0x07, 0x5F, 0x6D, 0x61, - 0x6C, 0x6C, 0x6F, 0x63, 0x02, 0x07, 0x5F, 0x70, 0x72, 0x69, 0x6E, 0x74, - 0x66, 0x03, 0x05, 0x5F, 0x70, 0x75, 0x74, 0x73, 0x04, 0x05, 0x5F, 0x6D, - 0x61, 0x69, 0x6E, 0x05, 0x0B, 0x72, 0x75, 0x6E, 0x50, 0x6F, 0x73, 0x74, - 0x53, 0x65, 0x74, 0x73, 0x06, 0x12, 0x5F, 0x5F, 0x70, 0x6F, 0x73, 0x74, - 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x69, 0x61, 0x74, 0x65, - 0x00, 0x20, 0x10, 0x73, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x4D, 0x61, 0x70, - 0x70, 0x69, 0x6E, 0x67, 0x55, 0x52, 0x4C, 0x0E, 0x61, 0x2E, 0x6F, 0x75, - 0x74, 0x2E, 0x77, 0x61, 0x73, 0x6D, 0x2E, 0x6D, 0x61, 0x70 }; + 0x00, 0x00, 0x0D, 0x06, 0x64, 0x79, 0x6C, 0x69, 0x6E, 0x6B, 0xC0, 0x80, + 0x04, 0x04, 0x00, 0x00, 0x01, 0x13, 0x04, 0x60, 0x01, 0x7F, 0x00, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x00, + 0x00, 0x02, 0x58, 0x06, 0x03, 0x65, 0x6E, 0x76, 0x05, 0x5F, 0x66, 0x72, + 0x65, 0x65, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x5F, 0x6D, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x5F, + 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, + 0x05, 0x5F, 0x70, 0x75, 0x74, 0x73, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, + 0x0D, 0x5F, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x5F, 0x62, 0x61, + 0x73, 0x65, 0x03, 0x7F, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x65, + 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x01, 0x03, 0x04, 0x03, 0x02, 0x03, + 0x03, 0x06, 0x10, 0x03, 0x7F, 0x01, 0x41, 0x00, 0x0B, 0x7F, 0x01, 0x41, + 0x00, 0x0B, 0x7F, 0x00, 0x41, 0x1B, 0x0B, 0x07, 0x33, 0x04, 0x12, 0x5F, + 0x5F, 0x70, 0x6F, 0x73, 0x74, 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6E, + 0x74, 0x69, 0x61, 0x74, 0x65, 0x00, 0x06, 0x05, 0x5F, 0x6D, 0x61, 0x69, + 0x6E, 0x00, 0x04, 0x0B, 0x72, 0x75, 0x6E, 0x50, 0x6F, 0x73, 0x74, 0x53, + 0x65, 0x74, 0x73, 0x00, 0x05, 0x04, 0x5F, 0x73, 0x74, 0x72, 0x03, 0x03, + 0x0A, 0xBA, 0x01, 0x03, 0x9E, 0x01, 0x01, 0x01, 0x7F, 0x23, 0x01, 0x21, + 0x00, 0x23, 0x01, 0x41, 0x10, 0x6A, 0x24, 0x01, 0x20, 0x00, 0x41, 0x08, + 0x6A, 0x21, 0x02, 0x23, 0x00, 0x41, 0x1B, 0x6A, 0x10, 0x03, 0x1A, 0x41, + 0x80, 0x08, 0x10, 0x01, 0x21, 0x01, 0x20, 0x01, 0x04, 0x7F, 0x20, 0x00, + 0x20, 0x01, 0x36, 0x02, 0x00, 0x23, 0x00, 0x20, 0x00, 0x10, 0x02, 0x1A, + 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, 0x0D, 0x3A, 0x00, 0x00, 0x20, 0x01, + 0x23, 0x00, 0x2C, 0x00, 0x0E, 0x3A, 0x00, 0x01, 0x20, 0x01, 0x23, 0x00, + 0x2C, 0x00, 0x0F, 0x3A, 0x00, 0x02, 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, + 0x10, 0x3A, 0x00, 0x03, 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, 0x11, 0x3A, + 0x00, 0x04, 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, 0x12, 0x3A, 0x00, 0x05, + 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x00, 0x23, 0x00, 0x41, 0x13, 0x6A, + 0x20, 0x02, 0x10, 0x02, 0x1A, 0x20, 0x01, 0x10, 0x00, 0x20, 0x00, 0x24, + 0x01, 0x41, 0x00, 0x05, 0x23, 0x00, 0x41, 0x28, 0x6A, 0x10, 0x03, 0x1A, + 0x20, 0x00, 0x24, 0x01, 0x41, 0x7F, 0x0B, 0x0B, 0x03, 0x00, 0x01, 0x0B, + 0x14, 0x00, 0x23, 0x00, 0x41, 0x40, 0x6B, 0x24, 0x01, 0x23, 0x01, 0x41, + 0x80, 0x80, 0x04, 0x6A, 0x24, 0x02, 0x10, 0x05, 0x0B, 0x0B, 0x3F, 0x01, + 0x00, 0x23, 0x00, 0x0B, 0x39, 0x62, 0x75, 0x66, 0x20, 0x70, 0x74, 0x72, + 0x3A, 0x20, 0x25, 0x70, 0x0A, 0x00, 0x31, 0x32, 0x33, 0x34, 0x0A, 0x00, + 0x62, 0x75, 0x66, 0x3A, 0x20, 0x25, 0x73, 0x00, 0x48, 0x65, 0x6C, 0x6C, + 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00, 0x6D, 0x61, 0x6C, + 0x6C, 0x6F, 0x63, 0x20, 0x62, 0x75, 0x66, 0x20, 0x66, 0x61, 0x69, 0x6C, + 0x65, 0x64, 0x00, 0x50, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x01, 0x49, 0x07, + 0x00, 0x05, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x01, 0x07, 0x5F, 0x6D, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x02, 0x07, 0x5F, 0x70, 0x72, 0x69, 0x6E, 0x74, + 0x66, 0x03, 0x05, 0x5F, 0x70, 0x75, 0x74, 0x73, 0x04, 0x05, 0x5F, 0x6D, + 0x61, 0x69, 0x6E, 0x05, 0x0B, 0x72, 0x75, 0x6E, 0x50, 0x6F, 0x73, 0x74, + 0x53, 0x65, 0x74, 0x73, 0x06, 0x12, 0x5F, 0x5F, 0x70, 0x6F, 0x73, 0x74, + 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x69, 0x61, 0x74, 0x65, + 0x00, 0x20, 0x10, 0x73, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x4D, 0x61, 0x70, + 0x70, 0x69, 0x6E, 0x67, 0x55, 0x52, 0x4C, 0x0E, 0x61, 0x2E, 0x6F, 0x75, + 0x74, 0x2E, 0x77, 0x61, 0x73, 0x6D, 0x2E, 0x6D, 0x61, 0x70 }; extern "C" JNIEXPORT void JNICALL @@ -96,10 +94,6 @@ Java_com_intel_wasm_api_Runtime_run(JNIEnv *env, jclass thiz) { return; } - // set log level to INFO - LOGI("set log level to INFO"); - bh_log_set_verbose_level(3); - /* load WASM byte buffer from a preinstall WASM bin file */ LOGI("use an internal test file, gona to output Hello World in logcat\n"); wasm_file_buf = (uint8_t*) wasm_test_file; diff --git a/product-mini/platforms/darwin/CMakeLists.txt b/product-mini/platforms/darwin/CMakeLists.txt index 2eb5d8d82..352b6fbe9 100644 --- a/product-mini/platforms/darwin/CMakeLists.txt +++ b/product-mini/platforms/darwin/CMakeLists.txt @@ -62,7 +62,9 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) -add_executable (iwasm main.c) +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) install (TARGETS iwasm DESTINATION bin) diff --git a/product-mini/platforms/darwin/main.c b/product-mini/platforms/darwin/main.c index 24c728862..defc0d949 100644 --- a/product-mini/platforms/darwin/main.c +++ b/product-mini/platforms/darwin/main.c @@ -11,6 +11,7 @@ #include "bh_platform.h" #include "bh_assert.h" #include "bh_log.h" +#include "bh_read_file.h" #include "wasm_export.h" static int app_argc; @@ -18,25 +19,25 @@ static char **app_argv; static int print_help() { - bh_printf("Usage: iwasm [-options] wasm_file [args...]\n"); - bh_printf("options:\n"); - bh_printf(" -f|--function name Specify function name to run in module\n" - " rather than main\n"); + printf("Usage: iwasm [-options] wasm_file [args...]\n"); + printf("options:\n"); + printf(" -f|--function name Specify function name to run in module\n" + " rather than main\n"); #if WASM_ENABLE_LOG != 0 - bh_printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" - " larger level with more log\n"); + printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" + " larger level with more log\n"); #endif - bh_printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); - bh_printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); - bh_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); + printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); + printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); + 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_ENABLE_LIBC_WASI != 0 - bh_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - bh_printf(" to the program, for example:\n"); - bh_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - bh_printf(" --dir= Grant wasi access to the given host directories\n"); - bh_printf(" to the program, for example:\n"); - bh_printf(" --dir= --dir=\n"); + printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + printf(" to the program, for example:\n"); + printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + printf(" --dir= Grant wasi access to the given host directories\n"); + printf(" to the program, for example:\n"); + printf(" --dir= --dir=\n"); #endif return 1; @@ -49,7 +50,7 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - bh_printf("%s\n", exception); + printf("%s\n", exception); return NULL; } @@ -100,7 +101,7 @@ app_instance_repl(wasm_module_inst_t module_inst) size_t len = 0; ssize_t n; - while ((bh_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { + while ((printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { bh_assert(n > 0); if (cmd[n - 1] == '\n') { if (n == 1) @@ -204,8 +205,8 @@ int main(int argc, char *argv[]) if (argv[0][6] == '\0') return print_help(); if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { - bh_printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char*))); + printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char*))); return -1; } dir_list[dir_list_size++] = argv[0] + 6; @@ -216,16 +217,16 @@ int main(int argc, char *argv[]) if (argv[0][6] == '\0') return print_help(); if (env_list_size >= sizeof(env_list) / sizeof(char*)) { - bh_printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char*))); + printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char*))); return -1; } tmp_env = argv[0] + 6; if (validate_env_str(tmp_env)) env_list[env_list_size++] = tmp_env; else { - bh_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", - tmp_env); + printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", + tmp_env); return print_help(); } } @@ -256,7 +257,7 @@ int main(int argc, char *argv[]) /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return -1; } @@ -270,7 +271,7 @@ int main(int argc, char *argv[]) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail2; } @@ -288,7 +289,7 @@ int main(int argc, char *argv[]) heap_size, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail3; } 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 bfa0252e7..428f72e1c 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -29,10 +29,8 @@ app_instance_main(wasm_module_inst_t module_inst) extern "C" { -int bh_printf(const char *message, ...); - -typedef void (*bh_print_function_t)(const char* message); -extern void bh_set_print_function(bh_print_function_t pf); +typedef void (*os_print_function_t)(const char* message); +extern void os_set_print_function(os_print_function_t pf); void enclave_print(const char *message) { @@ -43,7 +41,7 @@ void enclave_print(const char *message) void ecall_iwasm_main() { - bh_set_print_function(enclave_print); + os_set_print_function(enclave_print); uint8_t *wasm_file_buf = NULL; int wasm_file_size; diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt index 2b5a3e1dd..fd8657a91 100644 --- a/product-mini/platforms/linux/CMakeLists.txt +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -12,7 +12,7 @@ set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # Set WAMR_BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" if (NOT DEFINED WAMR_BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform @@ -81,7 +81,9 @@ endif () #set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") #set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") -add_executable (iwasm main.c) +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) install (TARGETS iwasm DESTINATION bin) diff --git a/product-mini/platforms/linux/build_llvm.sh b/product-mini/platforms/linux/build_llvm.sh index 29c5e5058..a21f03d66 100755 --- a/product-mini/platforms/linux/build_llvm.sh +++ b/product-mini/platforms/linux/build_llvm.sh @@ -8,7 +8,7 @@ DEPS_DIR=${PWD}/../../../core/deps cd ${DEPS_DIR} if [ ! -d "llvm" ]; then echo "Clone llvm to core/deps/ .." - git clone --depth 1 https://github.com/llvm-mirror/llvm.git + git clone --depth 1 https://github.com/llvm/llvm-project.git llvm fi cd llvm @@ -24,7 +24,7 @@ if [ ! -f bin/llvm-lto ]; then echo "Build llvm with" ${CORE_NUM} "cores" - cmake .. \ + cmake ../llvm \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DCMAKE_BUILD_TYPE:STRING="Release" \ -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ diff --git a/product-mini/platforms/linux/main.c b/product-mini/platforms/linux/main.c index 24c728862..defc0d949 100644 --- a/product-mini/platforms/linux/main.c +++ b/product-mini/platforms/linux/main.c @@ -11,6 +11,7 @@ #include "bh_platform.h" #include "bh_assert.h" #include "bh_log.h" +#include "bh_read_file.h" #include "wasm_export.h" static int app_argc; @@ -18,25 +19,25 @@ static char **app_argv; static int print_help() { - bh_printf("Usage: iwasm [-options] wasm_file [args...]\n"); - bh_printf("options:\n"); - bh_printf(" -f|--function name Specify function name to run in module\n" - " rather than main\n"); + printf("Usage: iwasm [-options] wasm_file [args...]\n"); + printf("options:\n"); + printf(" -f|--function name Specify function name to run in module\n" + " rather than main\n"); #if WASM_ENABLE_LOG != 0 - bh_printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" - " larger level with more log\n"); + printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" + " larger level with more log\n"); #endif - bh_printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); - bh_printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); - bh_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); + printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); + printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); + 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_ENABLE_LIBC_WASI != 0 - bh_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - bh_printf(" to the program, for example:\n"); - bh_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - bh_printf(" --dir= Grant wasi access to the given host directories\n"); - bh_printf(" to the program, for example:\n"); - bh_printf(" --dir= --dir=\n"); + printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + printf(" to the program, for example:\n"); + printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + printf(" --dir= Grant wasi access to the given host directories\n"); + printf(" to the program, for example:\n"); + printf(" --dir= --dir=\n"); #endif return 1; @@ -49,7 +50,7 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - bh_printf("%s\n", exception); + printf("%s\n", exception); return NULL; } @@ -100,7 +101,7 @@ app_instance_repl(wasm_module_inst_t module_inst) size_t len = 0; ssize_t n; - while ((bh_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { + while ((printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { bh_assert(n > 0); if (cmd[n - 1] == '\n') { if (n == 1) @@ -204,8 +205,8 @@ int main(int argc, char *argv[]) if (argv[0][6] == '\0') return print_help(); if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { - bh_printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char*))); + printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char*))); return -1; } dir_list[dir_list_size++] = argv[0] + 6; @@ -216,16 +217,16 @@ int main(int argc, char *argv[]) if (argv[0][6] == '\0') return print_help(); if (env_list_size >= sizeof(env_list) / sizeof(char*)) { - bh_printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char*))); + printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char*))); return -1; } tmp_env = argv[0] + 6; if (validate_env_str(tmp_env)) env_list[env_list_size++] = tmp_env; else { - bh_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", - tmp_env); + printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", + tmp_env); return print_help(); } } @@ -256,7 +257,7 @@ int main(int argc, char *argv[]) /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return -1; } @@ -270,7 +271,7 @@ int main(int argc, char *argv[]) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail2; } @@ -288,7 +289,7 @@ int main(int argc, char *argv[]) heap_size, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail3; } diff --git a/product-mini/platforms/vxworks/CMakeLists.txt b/product-mini/platforms/vxworks/CMakeLists.txt index dc92494eb..37e71d819 100644 --- a/product-mini/platforms/vxworks/CMakeLists.txt +++ b/product-mini/platforms/vxworks/CMakeLists.txt @@ -66,7 +66,9 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) -add_executable (iwasm main.c) +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) install (TARGETS iwasm DESTINATION bin) diff --git a/product-mini/platforms/vxworks/main.c b/product-mini/platforms/vxworks/main.c index 24c728862..defc0d949 100644 --- a/product-mini/platforms/vxworks/main.c +++ b/product-mini/platforms/vxworks/main.c @@ -11,6 +11,7 @@ #include "bh_platform.h" #include "bh_assert.h" #include "bh_log.h" +#include "bh_read_file.h" #include "wasm_export.h" static int app_argc; @@ -18,25 +19,25 @@ static char **app_argv; static int print_help() { - bh_printf("Usage: iwasm [-options] wasm_file [args...]\n"); - bh_printf("options:\n"); - bh_printf(" -f|--function name Specify function name to run in module\n" - " rather than main\n"); + printf("Usage: iwasm [-options] wasm_file [args...]\n"); + printf("options:\n"); + printf(" -f|--function name Specify function name to run in module\n" + " rather than main\n"); #if WASM_ENABLE_LOG != 0 - bh_printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" - " larger level with more log\n"); + printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" + " larger level with more log\n"); #endif - bh_printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); - bh_printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); - bh_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); + printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); + printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); + 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_ENABLE_LIBC_WASI != 0 - bh_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - bh_printf(" to the program, for example:\n"); - bh_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - bh_printf(" --dir= Grant wasi access to the given host directories\n"); - bh_printf(" to the program, for example:\n"); - bh_printf(" --dir= --dir=\n"); + printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + printf(" to the program, for example:\n"); + printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + printf(" --dir= Grant wasi access to the given host directories\n"); + printf(" to the program, for example:\n"); + printf(" --dir= --dir=\n"); #endif return 1; @@ -49,7 +50,7 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - bh_printf("%s\n", exception); + printf("%s\n", exception); return NULL; } @@ -100,7 +101,7 @@ app_instance_repl(wasm_module_inst_t module_inst) size_t len = 0; ssize_t n; - while ((bh_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { + while ((printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { bh_assert(n > 0); if (cmd[n - 1] == '\n') { if (n == 1) @@ -204,8 +205,8 @@ int main(int argc, char *argv[]) if (argv[0][6] == '\0') return print_help(); if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { - bh_printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char*))); + printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char*))); return -1; } dir_list[dir_list_size++] = argv[0] + 6; @@ -216,16 +217,16 @@ int main(int argc, char *argv[]) if (argv[0][6] == '\0') return print_help(); if (env_list_size >= sizeof(env_list) / sizeof(char*)) { - bh_printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char*))); + printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char*))); return -1; } tmp_env = argv[0] + 6; if (validate_env_str(tmp_env)) env_list[env_list_size++] = tmp_env; else { - bh_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", - tmp_env); + printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", + tmp_env); return print_help(); } } @@ -256,7 +257,7 @@ int main(int argc, char *argv[]) /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return -1; } @@ -270,7 +271,7 @@ int main(int argc, char *argv[]) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail2; } @@ -288,7 +289,7 @@ int main(int argc, char *argv[]) heap_size, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail3; } diff --git a/product-mini/platforms/zephyr/simple/CMakeLists.txt b/product-mini/platforms/zephyr/simple/CMakeLists.txt index c55de4a76..affa755ab 100644 --- a/product-mini/platforms/zephyr/simple/CMakeLists.txt +++ b/product-mini/platforms/zephyr/simple/CMakeLists.txt @@ -10,7 +10,7 @@ enable_language (ASM) set (WAMR_BUILD_PLATFORM "zephyr") -# Build as X86_32 by default, change to "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA" +# Build as X86_32 by default, change to "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA" # if we want to support arm, thumb, mips or xtensa if (NOT DEFINED WAMR_BUILD_TARGET) set (WAMR_BUILD_TARGET "X86_32") @@ -37,48 +37,10 @@ if (NOT DEFINED WAMR_BUILD_LIBC_WASI) endif () set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wamr) -set (SHARED_DIR ${WAMR_ROOT_DIR}/core/shared) -set (IWASM_DIR ${WAMR_ROOT_DIR}/core/iwasm) -set (APP_FRAMEWORK_DIR ${WAMR_ROOT_DIR}/core/app-framework) -# include the build config template makefile -include (${WAMR_ROOT_DIR}/build-scripts/config_common.cmake) - -include_directories (${SHARED_DIR}/include - ${IWASM_DIR}/include) - -include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) -include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_DIR}/utils/shared_utils.cmake) -if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) - include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake) -endif () -if (WAMR_BUILD_LIBC_WASI EQUAL 1) - include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake) -endif () - -include (${IWASM_DIR}/common/iwasm_common.cmake) - -if (WAMR_BUILD_INTERP EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1) - include (${IWASM_DIR}/interpreter/iwasm_interp.cmake) -endif() - -if (WAMR_BUILD_AOT EQUAL 1) - include (${IWASM_DIR}/aot/iwasm_aot.cmake) -endif () - -set (VM_LIB_SRCS - ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE} - ${LIBC_BUILTIN_SOURCE} - ${LIBC_WASI_SOURCE} - ${IWASM_COMMON_SOURCE} - ${IWASM_INTERP_SOURCE} - ${IWASM_AOT_SOURCE} - ${IWASM_COMPL_SOURCE}) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) target_sources(app PRIVATE - ${VM_LIB_SRCS} + ${WAMR_RUNTIME_LIB_SOURCE} src/main.c) diff --git a/product-mini/platforms/zephyr/simple/build.sh b/product-mini/platforms/zephyr/simple/build.sh deleted file mode 100755 index 32a2c4000..000000000 --- a/product-mini/platforms/zephyr/simple/build.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -X86_TARGET="x86" -STM32_TARGET="stm32" - -if [ $# != 1 ] ; then - echo "USAGE:" - echo "$0 $X86_TARGET|$STM32_TARGET" - echo "Example:" - echo " $0 $X86_TARGET" - echo " $0 $STM32_TARGET" - exit 1 -fi - -TARGET=$1 - -if [ "$TARGET" = "$X86_TARGET" ] ; then - cp prj_qemu_x86_nommu.conf prj.conf - rm -fr build && mkdir build && cd build - cmake -GNinja -DBOARD=qemu_x86_nommu -DWAMR_BUILD_TARGET=X86_32 .. - ninja - ninja run -elif [ "$TARGET" = "$STM32_TARGET" ] ; then - cp prj_nucleo767zi.conf prj.conf - rm -fr build && mkdir build && cd build - cmake -GNinja -DBOARD=nucleo_f767zi -DWAMR_BUILD_TARGET=THUMBV7 .. - ninja - ninja flash -else - echo "unsupported target: $TARGET" - exit 1 -fi diff --git a/product-mini/platforms/zephyr/simple/build_and_run.sh b/product-mini/platforms/zephyr/simple/build_and_run.sh new file mode 100644 index 000000000..e222366f2 --- /dev/null +++ b/product-mini/platforms/zephyr/simple/build_and_run.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +X86_TARGET="x86" +STM32_TARGET="stm32" +QEMU_CORTEX_A53="qemu_cortex_a53" +XTENSA_QEMU_TARGET="xtensa-qemu" +ESP32_TARGET="esp32" + +usage () +{ + echo "USAGE:" + echo "$0 $X86_TARGET|$STM32_TARGET|$QEMU_CORTEX_A53|$XTENSA_QEMU_TARGET|$ESP32_TARGET" + echo "Example:" + echo " $0 $X86_TARGET" + echo " $0 $STM32_TARGET" + echo " $0 $QEMU_CORTEX_A53" + echo " $0 $XTENSA_QEMU_TARGET" + echo " $0 $ESP32_TARGET" + exit 1 +} + +if [ $# != 1 ] ; then + usage +fi + +TARGET=$1 + +case $TARGET in + $X86_TARGET) + west build -b qemu_x86_nommu \ + . -p always -- \ + -DCONF_FILE=prj_qemu_x86_nommu.conf \ + -DWAMR_BUILD_TARGET=X86_32 + west build -t run + ;; + $STM32_TARGET) + west build -b nucleo_f767zi \ + . -p always -- \ + -DCONF_FILE=prj_nucleo767zi.conf \ + -DWAMR_BUILD_TARGET=THUMBV7 + west flash + ;; + $XTENSA_QEMU_TARGET) + west build -b qemu_xtensa \ + . -p always -- \ + -DCONF_FILE=prj_qemu_xtensa.conf \ + -DWAMR_BUILD_TARGET=XTENSA + west build -t run + ;; + $ESP32_TARGET) + # suppose you have set environment variable ESP_IDF_PATH + west build -b esp32 \ + . -p always -- \ + -DESP_IDF_PATH=$ESP_IDF_PATH \ + -DCONF_FILE=prj_esp32.conf \ + -DWAMR_BUILD_TARGET=XTENSA + # suppose the serial port is /dev/ttyUSB1 and you should change to + # the real name accordingly + west flash --esp-device /dev/ttyUSB1 + ;; + $QEMU_CORTEX_A53) + west build -b qemu_cortex_a53 \ + . -p always -- \ + -DCONF_FILE=prj_qemu_cortex_a53.conf \ + -DWAMR_BUILD_TARGET=AARCH64 + west build -t run + ;; + *) + echo "unsupported target: $TARGET" + usage + exit 1 + ;; +esac + diff --git a/product-mini/platforms/zephyr/simple/esp32_custom_linker.ld b/product-mini/platforms/zephyr/simple/esp32_custom_linker.ld new file mode 100644 index 000000000..35932050f --- /dev/null +++ b/product-mini/platforms/zephyr/simple/esp32_custom_linker.ld @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2016 Cadence Design Systems, Inc. + * Copyright (c) 2017 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the Xtensa platform. + */ + +#include +#include +#include +#include +#include + +#define RAMABLE_REGION dram0_0_seg :dram0_0_phdr +#define RAMABLE_REGION1 dram0_1_seg :dram0_0_phdr +#define ROMABLE_REGION iram0_0_seg :iram0_0_phdr + +PROVIDE ( __stack = 0x3ffe3f20 ); + +PROVIDE ( esp32_rom_uart_tx_one_char = 0x40009200 ); +PROVIDE ( esp32_rom_uart_rx_one_char = 0x400092d0 ); +PROVIDE ( esp32_rom_uart_attach = 0x40008fd0 ); +PROVIDE ( esp32_rom_intr_matrix_set = 0x4000681c ); +PROVIDE ( esp32_rom_gpio_matrix_in = 0x40009edc ); +PROVIDE ( esp32_rom_gpio_matrix_out = 0x40009f0c ); +PROVIDE ( esp32_rom_Cache_Flush = 0x40009a14 ); +PROVIDE ( esp32_rom_Cache_Read_Enable = 0x40009a84 ); +PROVIDE ( esp32_rom_ets_set_appcpu_boot_addr = 0x4000689c ); + +MEMORY +{ + iram0_0_seg(RX): org = 0x40080000, len = 0x20000 + iram0_2_seg(RX): org = 0x400D0018, len = 0x330000 + dram0_0_seg(RW): org = 0x3FFB0000, len = 0x30000 + dram0_1_seg(RWX):org = 0x400A0000, len = 0x20000 + drom0_0_seg(R): org = 0x3F400010, len = 0x800000 + rtc_iram_seg(RWX): org = 0x400C0000, len = 0x2000 + rtc_slow_seg(RW): org = 0x50000000, len = 0x1000 +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +PHDRS +{ + iram0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; +} + +/* Default entry point: */ +PROVIDE ( _ResetVector = 0x40000400 ); +ENTRY(CONFIG_KERNEL_ENTRY) + +_rom_store_table = 0; + +PROVIDE(_memmap_vecbase_reset = 0x40000450); +PROVIDE(_memmap_reset_vector = 0x40000400); + +SECTIONS +{ + +#include + + /* RTC fast memory holds RTC wake stub code, + including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + *(.rtc.literal .rtc.text) + *rtc_wake_stub*.o(.literal .text .literal.* .text.*) + } >rtc_iram_seg + + /* RTC slow memory holds RTC wake stub + data/rodata, including from any source file + named rtc_wake_stub*.c + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + *(.rtc.data) + *(.rtc.rodata) + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.o(.bss .bss.*) + *rtc_wake_stub*.o(COMMON) + _rtc_bss_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* Send .iram0 code to iram */ + .iram0.vectors : ALIGN(4) + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + + /* This goes here, not at top of linker script, so addr2line finds it last, + and uses it in preference to the first symbol in IRAM */ + _iram_start = ABSOLUTE(0); + } GROUP_LINK_IN(ROMABLE_REGION) + +#include +#include + + SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) + { + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + *(.literal .text .literal.* .text.*) + _iram_text_end = ABSOLUTE(.); + } GROUP_LINK_IN(ROMABLE_REGION) + + .dram0.text : + { + _data_start = ABSOLUTE(.); + *(.aot_code_buf) + _data_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_LINK_IN(RAMABLE_REGION1) + + + .dram0.data : + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + _data_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_LINK_IN(RAMABLE_REGION) + + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(4)) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + KEEP (*(.xt_except_table)) + KEEP (*(.gcc_except_table .gcc_except_table.*)) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + KEEP (*(.eh_frame)) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _rodata_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + + SECTION_DATA_PROLOGUE(_APP_NOINIT_SECTION_NAME, (NOLOAD),) + { + . = ALIGN (8); + *(.app_noinit) + *("app_noinit.*") + . = ALIGN (8); + _app_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + + SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) + { + . = ALIGN (8); + *(.noinit) + *(".noinit.*") + . = ALIGN (8); + _heap_start = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +#include + + SECTION_PROLOGUE(.xtensa.info, 0,) + { + *(.xtensa.info) + } + +} diff --git a/product-mini/platforms/zephyr/simple/prj_esp32.conf b/product-mini/platforms/zephyr/simple/prj_esp32.conf new file mode 100644 index 000000000..5d6a67f9d --- /dev/null +++ b/product-mini/platforms/zephyr/simple/prj_esp32.conf @@ -0,0 +1,8 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +CONFIG_STACK_SENTINEL=y +CONFIG_PRINTK=y +CONFIG_LOG=y +CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y +CONFIG_CUSTOM_LINKER_SCRIPT="esp32_custom_linker.ld" diff --git a/core/shared/utils/Makefile b/product-mini/platforms/zephyr/simple/prj_qemu_cortex_a53.conf similarity index 63% rename from core/shared/utils/Makefile rename to product-mini/platforms/zephyr/simple/prj_qemu_cortex_a53.conf index b5612a07b..d248565fa 100644 --- a/core/shared/utils/Makefile +++ b/product-mini/platforms/zephyr/simple/prj_qemu_cortex_a53.conf @@ -1,5 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -obj-y += bh_list.o bh_log.o attr-container.o bh_queue.o -obj-y += coap/ +CONFIG_ARM_MMU=n +CONFIG_STACK_SENTINEL=y +CONFIG_PRINTK=y +CONFIG_LOG=y diff --git a/product-mini/platforms/zephyr/simple/prj_qemu_xtensa.conf b/product-mini/platforms/zephyr/simple/prj_qemu_xtensa.conf new file mode 100644 index 000000000..7f4a32832 --- /dev/null +++ b/product-mini/platforms/zephyr/simple/prj_qemu_xtensa.conf @@ -0,0 +1,6 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +CONFIG_STACK_SENTINEL=y +CONFIG_PRINTK=y +CONFIG_LOG=y diff --git a/product-mini/platforms/zephyr/simple/src/main.c b/product-mini/platforms/zephyr/simple/src/main.c index 078b3d811..5079888ef 100644 --- a/product-mini/platforms/zephyr/simple/src/main.c +++ b/product-mini/platforms/zephyr/simple/src/main.c @@ -48,12 +48,60 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - bh_printf("%s\n", exception); + printf("%s\n", exception); return NULL; } static char global_heap_buf[CONFIG_GLOBAL_HEAP_BUF_SIZE] = { 0 }; +#ifdef CONFIG_BOARD_ESP32 +#include "mem_alloc.h" +/* +esp32_technical_reference_manual: +" +The capacity of Internal SRAM 1 is 128 KB. Either CPU can read and write this memory at addresses +0x3FFE_0000 ~ 0x3FFF_FFFF of the data bus, and also at addresses 0x400A_0000 ~ 0x400B_FFFF of the +instruction bus. +" + +The custom linker script defines dram0_1_seg and map it to 0x400A_0000 ~ 0x400B_FFFF for instruction bus access. +Here we define the buffer that will be placed to dram0_1_seg. +*/ +static char esp32_executable_memory_buf[100 * 1024] __attribute__((section (".aot_code_buf"))) = { 0 }; + +/* the poll allocator for executable memory */ +static mem_allocator_t esp32_exec_mem_pool_allocator; + +static int +esp32_exec_mem_init() +{ + if (!(esp32_exec_mem_pool_allocator = + mem_allocator_create(esp32_executable_memory_buf, + sizeof(esp32_executable_memory_buf)))) + return -1; + + return 0; +} + +static void +esp32_exec_mem_destroy() +{ + mem_allocator_destroy(esp32_exec_mem_pool_allocator); +} + +static void * +esp32_exec_mem_alloc(unsigned int size) +{ + return mem_allocator_malloc(esp32_exec_mem_pool_allocator, size); +} + +static void +esp32_exec_mem_free(void *addr) +{ + mem_allocator_free(esp32_exec_mem_pool_allocator, addr); +} +#endif /* end of #ifdef CONFIG_BOARD_ESP32 */ + void iwasm_main(void *arg1, void *arg2, void *arg3) { int start, end; @@ -72,6 +120,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) (void) arg2; (void) arg3; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); init_args.mem_alloc_type = Alloc_With_Pool; @@ -80,10 +129,20 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return; } +#ifdef CONFIG_BOARD_ESP32 + /* Initialize executable memory */ + if (esp32_exec_mem_init() != 0) { + printf("Init executable memory failed.\n"); + goto fail1; + } + /* Set hook functions for executable memory management */ + set_exec_mem_alloc_func(esp32_exec_mem_alloc, esp32_exec_mem_free); +#endif + #if WASM_ENABLE_LOG != 0 bh_log_set_verbose_level(log_verbose_level); #endif @@ -95,8 +154,12 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); +#ifdef CONFIG_BOARD_ESP32 + goto fail1_1; +#else goto fail1; +#endif } /* instantiate the module */ @@ -105,7 +168,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) CONFIG_APP_HEAP_SIZE, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail2; } @@ -119,6 +182,12 @@ fail2: /* unload the module */ wasm_runtime_unload(wasm_module); +#ifdef CONFIG_BOARD_ESP32 +fail1_1: + /* destroy executable memory */ + esp32_exec_mem_destroy(); +#endif + fail1: /* destroy runtime environment */ wasm_runtime_destroy(); diff --git a/samples/basic/.gitignore b/samples/basic/.gitignore new file mode 100644 index 000000000..0fa8a76bd --- /dev/null +++ b/samples/basic/.gitignore @@ -0,0 +1 @@ +/out/ \ No newline at end of file diff --git a/samples/basic/CMakeLists.txt b/samples/basic/CMakeLists.txt new file mode 100644 index 000000000..d55054c07 --- /dev/null +++ b/samples/basic/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.8) + +project (basic) + +################ runtime settings ################ +set (WAMR_BUILD_PLATFORM "linux") + +# 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 "X86_64") +set(CMAKE_BUILD_TYPE Debug) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 1) +set (WAMR_BUILD_LIBC_WASI 1) +set (WAMR_BUILD_FAST_INTERP 0) + +# linker flags +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + +# 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 (basic src/main.c src/native_impl.c ${UNCOMMON_SHARED_SOURCE}) + +target_link_libraries (basic vmlib -lm -ldl -lpthread -lrt) \ No newline at end of file diff --git a/samples/basic/README.md b/samples/basic/README.md new file mode 100644 index 000000000..d12f501fd --- /dev/null +++ b/samples/basic/README.md @@ -0,0 +1,51 @@ + + +The "basic" sample project +============== + +This sample demonstrates a few basic usages of embedding WAMR: +- initialize runtime +- load wasm app and instantiate the module +- call wasm function and pass arguments +- export native functions to the WASM apps +- wasm function calls native function and pass arguments +- deinitialize runtime + +Build this sample +============== +Execute the ```build.sh``` script then all binaries including wasm application files would be generated in 'out' directory. + +``` +$ ./build.sh +``` + +Run the sample +========================== +Enter the out directory. +``` +$ cd ./out/ +$ +$ ./basic wasm-apps/testapp.wasm +calling into WASM function: generate_float +Native finished calling wasm function generate_float(), returned a float value: 102009.921875f +calling into WASM function: float_to_string +calling into native function: intToStr +calling into native function: get_pow +calling into native function: intToStr +Native finished calling wasm function: float_to_string, returned a formatted string: 102009.921 +``` +Or execute the ```run.sh``` script in ```samples/basic``` folder. +``` +$ ./run.sh +calling into WASM function: generate_float +Native finished calling wasm function generate_float(), returned a float value: 102009.921875f +calling into WASM function: float_to_string +calling into native function: intToStr +calling into native function: get_pow +calling into native function: intToStr +Native finished calling wasm function: float_to_string, returned a formatted string: 102009.921 +``` + + + + diff --git a/samples/basic/build.sh b/samples/basic/build.sh new file mode 100755 index 000000000..7e3442c5a --- /dev/null +++ b/samples/basic/build.sh @@ -0,0 +1,58 @@ +#!/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 basic project" +cd ${CURR_DIR} +mkdir -p cmake_build +cd cmake_build +cmake .. +make +if [ $? != 0 ];then + echo "BUILD_FAIL basic exit as $?\n" + exit 2 +fi + +cp -a basic ${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,--no-threads,--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/basic/run.sh b/samples/basic/run.sh new file mode 100755 index 000000000..a5fb29166 --- /dev/null +++ b/samples/basic/run.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +out/basic -f out/wasm-apps/testapp.wasm \ No newline at end of file diff --git a/samples/basic/src/main.c b/samples/basic/src/main.c new file mode 100644 index 000000000..bbcd83359 --- /dev/null +++ b/samples/basic/src/main.c @@ -0,0 +1,204 @@ + +/* + * 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" + +int intToStr(int x, char* str, int str_len, int digit); +int get_pow(int x, int y); +int32_t calculate_native(int32_t n, int32_t func1, int32_t func2); + +void print_usage(void) +{ + fprintf(stdout, "Options:\r\n"); + fprintf(stdout, " -f [path of wasm file] \n"); +} + + +int main(int argc, char *argv_main[]) +{ + static char global_heap_buf[512 * 1024]; + char *buffer, error_buf[128]; + int opt; + char * wasm_path; + + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + uint32 buf_size, stack_size = 8092, heap_size = 8092; + wasm_function_inst_t func = NULL; + wasm_function_inst_t func2 = NULL; + char * native_buffer = NULL; + int32_t wasm_buffer = 0; + + 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/master/doc/export_native_api.md + + static NativeSymbol native_symbols[] = + { + { + "intToStr", // the name of WASM function name + intToStr, // the native function pointer + "(i*~i)i", // the function prototype signature, avoid to use i32 + NULL // attachment is NULL + }, + { + "get_pow", // the name of WASM function name + get_pow, // the native function pointer + "(ii)i", // the function prototype signature, avoid to use i32 + NULL // attachment is NULL + }, + { + "calculate_native", + calculate_native, + "(iii)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; + } + + 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(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; + } + + exec_env = wasm_runtime_create_exec_env(module_inst, stack_size); + if(!exec_env) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + + uint32 argv[4]; + double arg_d = 0.000101; + argv[0] = 10; + // the second arg will occupy two array elements + memcpy(&argv[1], &arg_d, sizeof(arg_d)); + *(float*)(argv+3) = 300.002; + + if(!(func = wasm_runtime_lookup_function(module_inst, "generate_float", NULL))){ + printf("The generate_float wasm function is not found.\n"); + goto fail; + } + + // pass 4 elements for function arguments + if (!wasm_runtime_call_wasm(exec_env, func, 4, argv) ) { + printf("call wasm function generate_float failed. %s\n", wasm_runtime_get_exception(module_inst)); + goto fail; + } + + float ret_val = *(float*)argv; + printf("Native finished calling wasm function generate_float(), returned a float value: %ff\n", ret_val ); + + // Next we will pass a buffer to the WASM function + uint32 argv2[4]; + + // must allocate buffer from wasm instance memory space (never use pointer from host runtime) + wasm_buffer = wasm_runtime_module_malloc(module_inst, 100, (void**)&native_buffer); + + *(float*)argv2 = ret_val; // the first argument + argv2[1] = wasm_buffer; // the second argument is the wasm buffer address + argv2[2] = 100; // the third argument is the wasm buffer size + argv2[3] = 3; // the last argument is the digits after decimal point for converting float to string + + if(!(func2 = wasm_runtime_lookup_function(module_inst, "float_to_string", NULL))){ + printf("The wasm function float_to_string wasm function is not found.\n"); + goto fail; + } + + if (wasm_runtime_call_wasm(exec_env, func2, 4, argv2) ) { + printf("Native finished calling wasm function: float_to_string, returned a formatted string: %s\n", native_buffer); + } + else { + printf("call wasm function float_to_string failed. error: %s\n", wasm_runtime_get_exception(module_inst)); + 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); + } 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) { + if(wasm_buffer) wasm_runtime_module_free(module_inst, wasm_buffer); + wasm_runtime_deinstantiate(module_inst); + } + if(module) wasm_runtime_unload(module); + if(buffer) BH_FREE(buffer); + wasm_runtime_destroy(); + return 0; +} diff --git a/samples/basic/src/native_impl.c b/samples/basic/src/native_impl.c new file mode 100644 index 000000000..b246d0e20 --- /dev/null +++ b/samples/basic/src/native_impl.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "wasm_export.h" +#include "math.h" + +extern bool +wasm_runtime_call_indirect(wasm_exec_env_t exec_env, + uint32_t element_indices, + uint32_t argc, uint32_t argv[]); + +// The first parameter is not exec_env because it is invoked by native funtions +void reverse(char * str, int len) +{ + int i = 0, j = len - 1, temp; + while (i < j) { + temp = str[i]; + str[i] = str[j]; + str[j] = temp; + i++; + j--; + } +} + +// The first parameter exec_env must be defined using type wasm_exec_env_t +// which is the calling convention for exporting native API by WAMR. +// +// Converts a given integer x to string str[]. +// digit is the number of digits required in the output. +// If digit is more than the number of digits in x, +// then 0s are added at the beginning. +int intToStr(wasm_exec_env_t exec_env, int x, char* str, int str_len, int digit) +{ + int i = 0; + + printf ("calling into native function: %s\n", __FUNCTION__); + + while (x) { + // native is responsible for checking the str_len overflow + if (i >= str_len) { + return -1; + } + str[i++] = (x % 10) + '0'; + x = x / 10; + } + + // If number of digits required is more, then + // add 0s at the beginning + while (i < digit) { + if (i >= str_len) { + return -1; + } + str[i++] = '0'; + } + + reverse(str, i); + + if (i >= str_len) + return -1; + str[i] = '\0'; + return i; +} + +int get_pow(wasm_exec_env_t exec_env, int x, int y) { + printf ("calling into native function: %s\n", __FUNCTION__); + return (int)pow(x, y); +} + +int32_t +calculate_native(wasm_exec_env_t exec_env, int32_t n, int32_t func1, + int32_t func2) +{ + printf("calling into native function: %s, n=%d, func1=%d, func2=%d\n", + __FUNCTION__, n, func1, func2); + + uint32_t argv[] = { n }; + if (!wasm_runtime_call_indirect(exec_env, func1, 1, argv)) { + printf("call func1 failed\n"); + return 0xDEAD; + } + + uint32_t n1 = argv[0]; + printf("call func1 and return n1=%d\n", n1); + + if (!wasm_runtime_call_indirect(exec_env, func2, 1, argv)) { + printf("call func2 failed\n"); + return 0xDEAD; + } + + uint32_t n2 = argv[0]; + printf("call func2 and return n2=%d\n", n2); + return n1 + n2; +} diff --git a/samples/basic/wasm-apps/testapp.c b/samples/basic/wasm-apps/testapp.c new file mode 100644 index 000000000..e5d4883de --- /dev/null +++ b/samples/basic/wasm-apps/testapp.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +int intToStr(int x, char* str, int str_len, int digit); +int get_pow(int x, int y); +int32_t calculate_native(int32_t n, int32_t func1, int32_t func2); + +// +// Primitive parameters functions +// +float generate_float(int iteration, double seed1, float seed2) +{ + float ret; + + printf ("calling into WASM function: %s\n", __FUNCTION__); + + for (int i=0; i 500) { k_sem_give(&sem_touch_read); @@ -86,15 +87,15 @@ void xpt2046_pen_gpio_callback(struct device *port, struct gpio_callback *cb, void disable_pen_interrupt() { int ret = 0; - ret = gpio_pin_disable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); + ret = gpio_disable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); if (ret != 0) { - printf("gpio_pin_configure GPIO_DIR_IN failed\n"); + printf("gpio_pin_configure GPIO_INPUT failed\n"); } } void enable_pen_interrupt() { int ret = 0; - ret = gpio_pin_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); + ret = gpio_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); if (ret != 0) { printf("gpio_pin_configure failed\n"); } @@ -152,8 +153,8 @@ void xpt2046_init(void) return; } gpio_pin_configure(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN, - GPIO_DIR_OUT); - gpio_pin_write(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN, 1); + GPIO_OUTPUT); + gpio_pin_set(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN, 1); xpt2046_cs_ctrl.gpio_pin = XPT2046_CS_GPIO_PIN; xpt2046_cs_ctrl.delay = 0; spi_conf_xpt2046.cs = &xpt2046_cs_ctrl; @@ -169,8 +170,8 @@ void xpt2046_init(void) } /* Setup GPIO input */ ret = gpio_pin_configure(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN, - (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE - | GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE) + (GPIO_INPUT | GPIO_INT_ENABLE | GPIO_INT_EDGE + | GPIO_INT_LOW_0 | GPIO_INT_DEBOUNCE) ); if (ret) { printk("Error configuring pin %d!\n", XPT2046_PEN_GPIO_PIN); @@ -183,9 +184,9 @@ void xpt2046_init(void) if (ret) { printk("gpio_add_callback error\n"); } - ret = gpio_pin_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); + ret = gpio_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); if (ret) { - printk("gpio_pin_enable_callback error\n"); + printk("gpio_enable_callback error\n"); } #endif @@ -209,7 +210,6 @@ bool xpt2046_read(lv_indev_data_t * data) static int16_t last_y = 0; bool valid = true; int s32_ret = 0; - uint8_t buf; int16_t x = 0; int16_t y = 0; @@ -293,6 +293,7 @@ static void xpt2046_corr(int16_t * x, int16_t * y) } +#if 0 static void xpt2046_avg(int16_t * x, int16_t * y) { /*Shift out the oldest data*/ @@ -320,6 +321,7 @@ static void xpt2046_avg(int16_t * x, int16_t * y) (*x) = (int32_t) x_sum / avg_last; (*y) = (int32_t) y_sum / avg_last; } +#endif bool touchscreen_read(lv_indev_data_t * data) { diff --git a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/display_ili9340.c b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/display_ili9340.c index 1ddc6937a..607030c88 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/display_ili9340.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/display_ili9340.c @@ -18,6 +18,7 @@ #include #include #include +#include struct ili9340_data { struct device *reset_gpio; @@ -68,23 +69,23 @@ int ili9340_init() } gpio_pin_configure(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, - GPIO_DIR_OUT); + GPIO_OUTPUT); data->command_data_gpio = device_get_binding( - DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_CONTROLLER); + DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_CONTROLLER); if (data->command_data_gpio == NULL) { return -EPERM; } gpio_pin_configure(data->command_data_gpio, - DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, GPIO_DIR_OUT); + DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, GPIO_OUTPUT); - LOG_DBG("Resetting display driver"); - gpio_pin_write(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1); + LOG_DBG("Resetting display driver\n"); + gpio_pin_set(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1); k_sleep(1); - gpio_pin_write(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 0); + gpio_pin_set(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 0); k_sleep(1); - gpio_pin_write(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1); + gpio_pin_set(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1); k_sleep(5); LOG_DBG("Initializing LCD\n"); @@ -97,7 +98,7 @@ int ili9340_init() } static void ili9340_set_mem_area(struct ili9340_data *data, const u16_t x, - const u16_t y, const u16_t w, const u16_t h) + const u16_t y, const u16_t w, const u16_t h) { u16_t spi_data[2]; @@ -111,7 +112,7 @@ static void ili9340_set_mem_area(struct ili9340_data *data, const u16_t x, } static int ili9340_write(const struct device *dev, const u16_t x, const u16_t y, - const struct display_buffer_descriptor *desc, const void *buf) + const struct display_buffer_descriptor *desc, const void *buf) { struct ili9340_data *data = (struct ili9340_data *) &ili9340_data1; const u8_t *write_data_start = (u8_t *) buf; @@ -123,7 +124,7 @@ static int ili9340_write(const struct device *dev, const u16_t x, const u16_t y, __ASSERT(desc->width <= desc->pitch, "Pitch is smaller then width"); __ASSERT((3 * desc->pitch * desc->height) <= desc->buf_size, - "Input buffer to small"); + "Input buffer to small"); ili9340_set_mem_area(data, x, y, desc->width, desc->height); if (desc->pitch > desc->width) { @@ -134,7 +135,7 @@ static int ili9340_write(const struct device *dev, const u16_t x, const u16_t y, nbr_of_writes = 1U; } ili9340_transmit(data, ILI9340_CMD_MEM_WRITE, (void *) write_data_start, - 3 * desc->width * write_h); + 3 * desc->width * write_h); tx_bufs.buffers = &tx_buf; tx_bufs.count = 1; @@ -151,15 +152,15 @@ static int ili9340_write(const struct device *dev, const u16_t x, const u16_t y, } static int ili9340_read(const struct device *dev, const u16_t x, const u16_t y, - const struct display_buffer_descriptor *desc, void *buf) + const struct display_buffer_descriptor *desc, void *buf) { - LOG_ERR("Reading not supported"); + LOG_ERR("Reading not supported\n"); return -ENOTSUP; } static void *ili9340_get_framebuffer(const struct device *dev) { - LOG_ERR("Direct framebuffer access not supported"); + LOG_ERR("Direct framebuffer access not supported\n"); return NULL; } @@ -167,7 +168,7 @@ static int ili9340_display_blanking_off(const struct device *dev) { struct ili9340_data *data = (struct ili9340_data *) dev->driver_data; - LOG_DBG("Turning display blanking off"); + LOG_DBG("Turning display blanking off\n"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_ON, NULL, 0); return 0; } @@ -176,46 +177,46 @@ static int ili9340_display_blanking_on(const struct device *dev) { struct ili9340_data *data = (struct ili9340_data *) dev->driver_data; - LOG_DBG("Turning display blanking on"); + LOG_DBG("Turning display blanking on\n"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_OFF, NULL, 0); return 0; } static int ili9340_set_brightness(const struct device *dev, - const u8_t brightness) + const u8_t brightness) { - LOG_WRN("Set brightness not implemented"); + LOG_WRN("Set brightness not implemented\n"); return -ENOTSUP; } static int ili9340_set_contrast(const struct device *dev, const u8_t contrast) { - LOG_ERR("Set contrast not supported"); + LOG_ERR("Set contrast not supported\n"); return -ENOTSUP; } static int ili9340_set_pixel_format(const struct device *dev, - const enum display_pixel_format pixel_format) + const enum display_pixel_format pixel_format) { if (pixel_format == PIXEL_FORMAT_RGB_888) { return 0; } - LOG_ERR("Pixel format change not implemented"); + LOG_ERR("Pixel format change not implemented\n"); return -ENOTSUP; } static int ili9340_set_orientation(const struct device *dev, - const enum display_orientation orientation) + const enum display_orientation orientation) { -if (orientation == DISPLAY_ORIENTATION_NORMAL) { - return 0; -} -LOG_ERR("Changing display orientation not implemented"); + if (orientation == DISPLAY_ORIENTATION_NORMAL) { + return 0; + } + LOG_ERR("Changing display orientation not implemented\n"); return -ENOTSUP; } static void ili9340_get_capabilities(const struct device *dev, - struct display_capabilities *capabilities) + struct display_capabilities *capabilities) { memset(capabilities, 0, sizeof(struct display_capabilities)); capabilities->x_resolution = 320; @@ -226,36 +227,37 @@ static void ili9340_get_capabilities(const struct device *dev, } void ili9340_transmit(struct ili9340_data *data, u8_t cmd, void *tx_data, - size_t tx_len) + size_t tx_len) { - int i; - char * buf1 = tx_data; data = (struct ili9340_data *) &ili9340_data1; struct spi_buf tx_buf = { .buf = &cmd, .len = 1 }; struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 }; - gpio_pin_write(data->command_data_gpio, DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, - ILI9340_CMD_DATA_PIN_COMMAND); + gpio_pin_set(data->command_data_gpio, DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, + ILI9340_CMD_DATA_PIN_COMMAND); spi_transceive(data->spi_dev, &data->spi_config, &tx_bufs, NULL); if (tx_data != NULL) { tx_buf.buf = tx_data; tx_buf.len = tx_len; - gpio_pin_write(data->command_data_gpio, + gpio_pin_set(data->command_data_gpio, DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, ILI9340_CMD_DATA_PIN_DATA); spi_transceive(data->spi_dev, &data->spi_config, &tx_bufs, NULL); } } -struct display_driver_api ili9340_api1 = - { .blanking_on = ili9340_display_blanking_on, .blanking_off = - ili9340_display_blanking_off, .write = ili9340_write, .read = - ili9340_read, .get_framebuffer = ili9340_get_framebuffer, - .set_brightness = ili9340_set_brightness, .set_contrast = - ili9340_set_contrast, .get_capabilities = - ili9340_get_capabilities, .set_pixel_format = - ili9340_set_pixel_format, .set_orientation = - ili9340_set_orientation, }; +struct display_driver_api ili9340_api1 = { + .blanking_on = ili9340_display_blanking_on, + .blanking_off = ili9340_display_blanking_off, + .write = ili9340_write, + .read = ili9340_read, + .get_framebuffer = ili9340_get_framebuffer, + .set_brightness = ili9340_set_brightness, + .set_contrast = ili9340_set_contrast, + .get_capabilities = ili9340_get_capabilities, + .set_pixel_format = ili9340_set_pixel_format, + .set_orientation = ili9340_set_orientation +}; /* DEVICE_AND_API_INIT(ili9340, DT_ILITEK_ILI9340_0_LABEL, &ili9340_init, diff --git a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c index 41edfe0aa..26e04b87b 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c @@ -9,7 +9,6 @@ #include "board_config.h" #include "bh_common.h" #include "bh_queue.h" -#include "bh_thread.h" #include "runtime_sensor.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" @@ -156,7 +155,7 @@ int iwasm_main() /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return -1; } diff --git a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c index 612259044..097d3faff 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c @@ -8,7 +8,6 @@ #include "bh_platform.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_platform_log.h" #include "wasm_export.h" extern int iwasm_main(); diff --git a/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt index d79b1f7ae..2c4c81071 100644 --- a/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt +++ b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt @@ -20,6 +20,8 @@ link_directories(${WAMR_ROOT_DIR}/wamr-sdk/out/littlevgl/runtime-sdk/lib) include_directories( ${WAMR_ROOT_DIR}/wamr-sdk/out/littlevgl/runtime-sdk/include ${WAMR_ROOT_DIR}/wamr-sdk/out/littlevgl/runtime-sdk/include/bi-inc/deps + ${WAMR_ROOT_DIR}/core/shared/utils + ${WAMR_ROOT_DIR}/core/shared/platform/${WAMR_BUILD_PLATFORM} ) ############### application related ############### diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c index 83f72c5c4..c229daec3 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c @@ -24,10 +24,7 @@ #include "runtime_timer.h" #include "native_interface.h" #include "app_manager_export.h" -#include "bh_common.h" -#include "bh_queue.h" -#include "bh_thread.h" -#include "runtime_sensor.h" +#include "bh_platform.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" #include "wasm_export.h" @@ -348,7 +345,7 @@ static host_interface interface = { .send = uart_send, .destroy = uart_destroy } #endif #ifdef __x86_64__ -static char global_heap_buf[400 * 1024] = { 0 }; +static char global_heap_buf[420 * 1024] = { 0 }; #else static char global_heap_buf[270 * 1024] = { 0 }; #endif @@ -459,7 +456,7 @@ static NativeSymbol native_symbols[] = { int iwasm_main(int argc, char *argv[]) { RuntimeInitArgs init_args; - korp_thread tid; + korp_tid tid; uint32 n_native_symbols; if (!parse_args(argc, argv)) @@ -477,12 +474,11 @@ int iwasm_main(int argc, char *argv[]) /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return -1; } if (!init_connection_framework()) { - vm_thread_sys_destroy(); goto fail1; } @@ -496,12 +492,12 @@ int iwasm_main(int argc, char *argv[]) #ifndef CONNECTION_UART if (server_mode) - vm_thread_create(&tid, func_server_mode, NULL, + os_thread_create(&tid, func_server_mode, NULL, BH_APPLET_PRESERVED_STACK_SIZE); else - vm_thread_create(&tid, func, NULL, BH_APPLET_PRESERVED_STACK_SIZE); + os_thread_create(&tid, func, NULL, BH_APPLET_PRESERVED_STACK_SIZE); #else - vm_thread_create(&tid, func_uart_mode, NULL, BH_APPLET_PRESERVED_STACK_SIZE); + os_thread_create(&tid, func_uart_mode, NULL, BH_APPLET_PRESERVED_STACK_SIZE); #endif app_manager_startup(&interface); diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.c index e5c1415ee..11d356221 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.c @@ -31,7 +31,9 @@ * STATIC PROTOTYPES **********************/ static void xpt2046_corr(int16_t * x, int16_t * y); +#if 0 static void xpt2046_avg(int16_t * x, int16_t * y); +#endif /********************** * STATIC VARIABLES @@ -73,7 +75,6 @@ int last_pen_interrupt_time = 0; void xpt2046_pen_gpio_callback(struct device *port, struct gpio_callback *cb, u32_t pins) { - int i; cnt++; if ((k_uptime_get_32() - last_pen_interrupt_time) > 500) { k_sem_give(&sem_touch_read); @@ -86,15 +87,15 @@ void xpt2046_pen_gpio_callback(struct device *port, struct gpio_callback *cb, void disable_pen_interrupt() { int ret = 0; - ret = gpio_pin_disable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); + ret = gpio_disable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); if (ret != 0) { - printf("gpio_pin_configure GPIO_DIR_IN failed\n"); + printf("gpio_pin_configure GPIO_INPUT failed\n"); } } void enable_pen_interrupt() { int ret = 0; - ret = gpio_pin_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); + ret = gpio_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); if (ret != 0) { printf("gpio_pin_configure failed\n"); } @@ -152,8 +153,8 @@ void xpt2046_init(void) return; } gpio_pin_configure(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN, - GPIO_DIR_OUT); - gpio_pin_write(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN, 1); + GPIO_OUTPUT); + gpio_pin_set(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN, 1); xpt2046_cs_ctrl.gpio_pin = XPT2046_CS_GPIO_PIN; xpt2046_cs_ctrl.delay = 0; spi_conf_xpt2046.cs = &xpt2046_cs_ctrl; @@ -169,8 +170,8 @@ void xpt2046_init(void) } /* Setup GPIO input */ ret = gpio_pin_configure(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN, - (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE - | GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE) + (GPIO_INPUT | GPIO_INT_ENABLE | GPIO_INT_EDGE + | GPIO_INT_LOW_0 | GPIO_INT_DEBOUNCE) ); if (ret) { printk("Error configuring pin %d!\n", XPT2046_PEN_GPIO_PIN); @@ -183,9 +184,9 @@ void xpt2046_init(void) if (ret) { printk("gpio_add_callback error\n"); } - ret = gpio_pin_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); + ret = gpio_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN); if (ret) { - printk("gpio_pin_enable_callback error\n"); + printk("gpio_enable_callback error\n"); } #endif @@ -209,7 +210,6 @@ bool xpt2046_read(lv_indev_data_t * data) static int16_t last_y = 0; bool valid = true; int s32_ret = 0; - uint8_t buf; int16_t x = 0; int16_t y = 0; @@ -293,6 +293,7 @@ static void xpt2046_corr(int16_t * x, int16_t * y) } +#if 0 static void xpt2046_avg(int16_t * x, int16_t * y) { /*Shift out the oldest data*/ @@ -320,6 +321,7 @@ static void xpt2046_avg(int16_t * x, int16_t * y) (*x) = (int32_t) x_sum / avg_last; (*y) = (int32_t) y_sum / avg_last; } +#endif bool touchscreen_read(lv_indev_data_t * data) { diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c index 1ddc6937a..607030c88 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c @@ -18,6 +18,7 @@ #include #include #include +#include struct ili9340_data { struct device *reset_gpio; @@ -68,23 +69,23 @@ int ili9340_init() } gpio_pin_configure(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, - GPIO_DIR_OUT); + GPIO_OUTPUT); data->command_data_gpio = device_get_binding( - DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_CONTROLLER); + DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_CONTROLLER); if (data->command_data_gpio == NULL) { return -EPERM; } gpio_pin_configure(data->command_data_gpio, - DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, GPIO_DIR_OUT); + DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, GPIO_OUTPUT); - LOG_DBG("Resetting display driver"); - gpio_pin_write(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1); + LOG_DBG("Resetting display driver\n"); + gpio_pin_set(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1); k_sleep(1); - gpio_pin_write(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 0); + gpio_pin_set(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 0); k_sleep(1); - gpio_pin_write(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1); + gpio_pin_set(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1); k_sleep(5); LOG_DBG("Initializing LCD\n"); @@ -97,7 +98,7 @@ int ili9340_init() } static void ili9340_set_mem_area(struct ili9340_data *data, const u16_t x, - const u16_t y, const u16_t w, const u16_t h) + const u16_t y, const u16_t w, const u16_t h) { u16_t spi_data[2]; @@ -111,7 +112,7 @@ static void ili9340_set_mem_area(struct ili9340_data *data, const u16_t x, } static int ili9340_write(const struct device *dev, const u16_t x, const u16_t y, - const struct display_buffer_descriptor *desc, const void *buf) + const struct display_buffer_descriptor *desc, const void *buf) { struct ili9340_data *data = (struct ili9340_data *) &ili9340_data1; const u8_t *write_data_start = (u8_t *) buf; @@ -123,7 +124,7 @@ static int ili9340_write(const struct device *dev, const u16_t x, const u16_t y, __ASSERT(desc->width <= desc->pitch, "Pitch is smaller then width"); __ASSERT((3 * desc->pitch * desc->height) <= desc->buf_size, - "Input buffer to small"); + "Input buffer to small"); ili9340_set_mem_area(data, x, y, desc->width, desc->height); if (desc->pitch > desc->width) { @@ -134,7 +135,7 @@ static int ili9340_write(const struct device *dev, const u16_t x, const u16_t y, nbr_of_writes = 1U; } ili9340_transmit(data, ILI9340_CMD_MEM_WRITE, (void *) write_data_start, - 3 * desc->width * write_h); + 3 * desc->width * write_h); tx_bufs.buffers = &tx_buf; tx_bufs.count = 1; @@ -151,15 +152,15 @@ static int ili9340_write(const struct device *dev, const u16_t x, const u16_t y, } static int ili9340_read(const struct device *dev, const u16_t x, const u16_t y, - const struct display_buffer_descriptor *desc, void *buf) + const struct display_buffer_descriptor *desc, void *buf) { - LOG_ERR("Reading not supported"); + LOG_ERR("Reading not supported\n"); return -ENOTSUP; } static void *ili9340_get_framebuffer(const struct device *dev) { - LOG_ERR("Direct framebuffer access not supported"); + LOG_ERR("Direct framebuffer access not supported\n"); return NULL; } @@ -167,7 +168,7 @@ static int ili9340_display_blanking_off(const struct device *dev) { struct ili9340_data *data = (struct ili9340_data *) dev->driver_data; - LOG_DBG("Turning display blanking off"); + LOG_DBG("Turning display blanking off\n"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_ON, NULL, 0); return 0; } @@ -176,46 +177,46 @@ static int ili9340_display_blanking_on(const struct device *dev) { struct ili9340_data *data = (struct ili9340_data *) dev->driver_data; - LOG_DBG("Turning display blanking on"); + LOG_DBG("Turning display blanking on\n"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_OFF, NULL, 0); return 0; } static int ili9340_set_brightness(const struct device *dev, - const u8_t brightness) + const u8_t brightness) { - LOG_WRN("Set brightness not implemented"); + LOG_WRN("Set brightness not implemented\n"); return -ENOTSUP; } static int ili9340_set_contrast(const struct device *dev, const u8_t contrast) { - LOG_ERR("Set contrast not supported"); + LOG_ERR("Set contrast not supported\n"); return -ENOTSUP; } static int ili9340_set_pixel_format(const struct device *dev, - const enum display_pixel_format pixel_format) + const enum display_pixel_format pixel_format) { if (pixel_format == PIXEL_FORMAT_RGB_888) { return 0; } - LOG_ERR("Pixel format change not implemented"); + LOG_ERR("Pixel format change not implemented\n"); return -ENOTSUP; } static int ili9340_set_orientation(const struct device *dev, - const enum display_orientation orientation) + const enum display_orientation orientation) { -if (orientation == DISPLAY_ORIENTATION_NORMAL) { - return 0; -} -LOG_ERR("Changing display orientation not implemented"); + if (orientation == DISPLAY_ORIENTATION_NORMAL) { + return 0; + } + LOG_ERR("Changing display orientation not implemented\n"); return -ENOTSUP; } static void ili9340_get_capabilities(const struct device *dev, - struct display_capabilities *capabilities) + struct display_capabilities *capabilities) { memset(capabilities, 0, sizeof(struct display_capabilities)); capabilities->x_resolution = 320; @@ -226,36 +227,37 @@ static void ili9340_get_capabilities(const struct device *dev, } void ili9340_transmit(struct ili9340_data *data, u8_t cmd, void *tx_data, - size_t tx_len) + size_t tx_len) { - int i; - char * buf1 = tx_data; data = (struct ili9340_data *) &ili9340_data1; struct spi_buf tx_buf = { .buf = &cmd, .len = 1 }; struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 }; - gpio_pin_write(data->command_data_gpio, DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, - ILI9340_CMD_DATA_PIN_COMMAND); + gpio_pin_set(data->command_data_gpio, DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, + ILI9340_CMD_DATA_PIN_COMMAND); spi_transceive(data->spi_dev, &data->spi_config, &tx_bufs, NULL); if (tx_data != NULL) { tx_buf.buf = tx_data; tx_buf.len = tx_len; - gpio_pin_write(data->command_data_gpio, + gpio_pin_set(data->command_data_gpio, DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, ILI9340_CMD_DATA_PIN_DATA); spi_transceive(data->spi_dev, &data->spi_config, &tx_bufs, NULL); } } -struct display_driver_api ili9340_api1 = - { .blanking_on = ili9340_display_blanking_on, .blanking_off = - ili9340_display_blanking_off, .write = ili9340_write, .read = - ili9340_read, .get_framebuffer = ili9340_get_framebuffer, - .set_brightness = ili9340_set_brightness, .set_contrast = - ili9340_set_contrast, .get_capabilities = - ili9340_get_capabilities, .set_pixel_format = - ili9340_set_pixel_format, .set_orientation = - ili9340_set_orientation, }; +struct display_driver_api ili9340_api1 = { + .blanking_on = ili9340_display_blanking_on, + .blanking_off = ili9340_display_blanking_off, + .write = ili9340_write, + .read = ili9340_read, + .get_framebuffer = ili9340_get_framebuffer, + .set_brightness = ili9340_set_brightness, + .set_contrast = ili9340_set_contrast, + .get_capabilities = ili9340_get_capabilities, + .set_pixel_format = ili9340_set_pixel_format, + .set_orientation = ili9340_set_orientation +}; /* DEVICE_AND_API_INIT(ili9340, DT_ILITEK_ILI9340_0_LABEL, &ili9340_init, diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c index cb140306a..217639752 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c @@ -7,9 +7,7 @@ #include "native_interface.h" #include "app_manager_export.h" #include "board_config.h" -#include "bh_common.h" -#include "bh_queue.h" -#include "bh_thread.h" +#include "bh_platform.h" #include "runtime_sensor.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" @@ -90,8 +88,6 @@ static NativeSymbol native_symbols[] = { int iwasm_main() { RuntimeInitArgs init_args; - korp_thread tid, tm_tid; - uint32 n_native_symbols; host_init(); @@ -107,7 +103,7 @@ int iwasm_main() /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return -1; } diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c index c12fbe632..b0cb47405 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c @@ -8,7 +8,6 @@ #include "bh_platform.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_platform_log.h" #include "wasm_export.h" extern void display_init(void); diff --git a/samples/simple/.gitignore b/samples/simple/.gitignore new file mode 100644 index 000000000..e2e7327cd --- /dev/null +++ b/samples/simple/.gitignore @@ -0,0 +1 @@ +/out diff --git a/samples/simple/CMakeLists.txt b/samples/simple/CMakeLists.txt index 85f1e00bc..5f0ce725d 100644 --- a/samples/simple/CMakeLists.txt +++ b/samples/simple/CMakeLists.txt @@ -18,6 +18,8 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) link_directories(${WAMR_ROOT_DIR}/wamr-sdk/out/${WAMR_BUILD_SDK_PROFILE}/runtime-sdk/lib) include_directories( ${WAMR_ROOT_DIR}/wamr-sdk/out/${WAMR_BUILD_SDK_PROFILE}/runtime-sdk/include + ${WAMR_ROOT_DIR}/core/shared/utils + ${WAMR_ROOT_DIR}/core/shared/platform/linux ) ################ application related ################ diff --git a/samples/simple/build.sh b/samples/simple/build.sh index 27b610f8f..85f306774 100755 --- a/samples/simple/build.sh +++ b/samples/simple/build.sh @@ -100,7 +100,7 @@ PROFILE="simple-$PROFILE" echo "#####################build wamr sdk" cd ${WAMR_DIR}/wamr-sdk -./build_sdk.sh -n $PROFILE -x $SDK_CONFIG_FILE $ARG_TOOLCHAIN $* +./build_sdk.sh -n $PROFILE -x $SDK_CONFIG_FILE $ARG_TOOLCHAIN [ $? -eq 0 ] || exit $? diff --git a/samples/simple/src/iwasm_main.c b/samples/simple/src/iwasm_main.c index 98caa655f..41bfbbf07 100644 --- a/samples/simple/src/iwasm_main.c +++ b/samples/simple/src/iwasm_main.c @@ -24,9 +24,7 @@ #include "runtime_timer.h" #include "native_interface.h" #include "app_manager_export.h" -#include "bh_common.h" -#include "bh_queue.h" -#include "bh_thread.h" +#include "bh_platform.h" #include "runtime_sensor.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" @@ -462,7 +460,7 @@ static bool parse_args(int argc, char *argv[]) int iwasm_main(int argc, char *argv[]) { RuntimeInitArgs init_args; - korp_thread tid; + korp_tid tid; if (!parse_args(argc, argv)) return -1; @@ -482,7 +480,7 @@ int iwasm_main(int argc, char *argv[]) /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return -1; } @@ -507,12 +505,12 @@ int iwasm_main(int argc, char *argv[]) #ifndef CONNECTION_UART if (server_mode) - vm_thread_create(&tid, func_server_mode, NULL, + os_thread_create(&tid, func_server_mode, NULL, BH_APPLET_PRESERVED_STACK_SIZE); else - vm_thread_create(&tid, func, NULL, BH_APPLET_PRESERVED_STACK_SIZE); + os_thread_create(&tid, func, NULL, BH_APPLET_PRESERVED_STACK_SIZE); #else - vm_thread_create(&tid, func_uart_mode, NULL, BH_APPLET_PRESERVED_STACK_SIZE); + os_thread_create(&tid, func_uart_mode, NULL, BH_APPLET_PRESERVED_STACK_SIZE); #endif app_manager_startup(&interface); diff --git a/test-tools/component_test/README.md b/test-tools/component_test/README.md new file mode 100644 index 000000000..c72d0fcb8 --- /dev/null +++ b/test-tools/component_test/README.md @@ -0,0 +1,56 @@ +# Component Test + +The purpose of this test suite is to verify the basic components of WAMR work well in combination. It is highly recommended to run pass all suites before each commitment. + +Prerequisites +============== +- clang is available to build wasm application. +- python is installed to run test script. + + +Run the test +============= +``` +start.py [-h] [-s SUITE_ID [SUITE_ID ...]] [-t CASE_ID [CASE_ID ...]] + [-n REPEAT_TIME] [--shuffle_all] + [--cases_list CASES_LIST_FILE_PATH] [--skip_proc] + [-b BINARIES] [-d] [--rebuild] +``` +It builds out the simple project binary including WAMR runtime binary ```simple``` and the testing tool ```host_tool``` before running the test suites. + +Test output is like: +``` +Test Execution Summary: + Success: 8 + Cases fails: 0 + Setup fails: 0 + Case load fails: 0 + + +------------------------------------------------------------ +The run folder is [run-03-23-16-29] +that's all. bye +kill to quit.. +Killed +``` + +The detailed report and log is generated in ```run``` folder. The binaries copy is also put in that folder. + +Usage samples +============== + +Run default test suite: +
+```python start.py``` + +Rebuild all test apps and then run default test suite: +
+```python start.py --rebuild``` + +Run a specified test suite: +
+```python start.py -s 01-life-cycle``` + +Run a specified test case: +
+```python start.py -t 01-install``` \ No newline at end of file diff --git a/test-tools/component_test/__init__.py b/test-tools/component_test/__init__.py new file mode 100644 index 000000000..fd734d561 --- /dev/null +++ b/test-tools/component_test/__init__.py @@ -0,0 +1,11 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +__all__ = [ + "net_manager", "wifi_daemon_utils" +] + +__author__ = "" +__package__ = "model" +__version__ = "1.0" diff --git a/test-tools/component_test/framework/__init__.py b/test-tools/component_test/framework/__init__.py new file mode 100644 index 000000000..fd734d561 --- /dev/null +++ b/test-tools/component_test/framework/__init__.py @@ -0,0 +1,11 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +__all__ = [ + "net_manager", "wifi_daemon_utils" +] + +__author__ = "" +__package__ = "model" +__version__ = "1.0" diff --git a/test-tools/component_test/framework/case_base.py b/test-tools/component_test/framework/case_base.py new file mode 100644 index 000000000..311de5eaa --- /dev/null +++ b/test-tools/component_test/framework/case_base.py @@ -0,0 +1,29 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import os +import json +from test.test_support import _run_suite + +class CTestCaseBase(object): + def __init__(self, suite): + self.m_suite = suite + return + def on_get_case_description(self): + return "Undefined" + + def on_setup_case(self): + return True, '' + + def on_cleanup_case(self): + return True, '' + + # called by the framework + def on_run_case(self): + return True, '' + + def get_suite(self): + return self.m_suite + diff --git a/test-tools/component_test/framework/engine.py b/test-tools/component_test/framework/engine.py new file mode 100644 index 000000000..48911d194 --- /dev/null +++ b/test-tools/component_test/framework/engine.py @@ -0,0 +1,38 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import datetime +import os +import pprint +import random +import re +import shlex +import subprocess +import signal +import sys +import time + +from .test_utils import * +from .test_api import * + + + + +def read_cases_from_file(file_path): + if not os.path.exists(file_path): + return False, None + + with open(file_path, 'r') as f: + content = f.readlines() + + content = [x.strip() for x in content] + print content + if len(content) == 0: + return False, None + + return True, content + + + diff --git a/test-tools/component_test/framework/framework.py b/test-tools/component_test/framework/framework.py new file mode 100644 index 000000000..78e187fe0 --- /dev/null +++ b/test-tools/component_test/framework/framework.py @@ -0,0 +1,287 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import datetime +import os +import pprint +import random +import re +import shlex +import subprocess +import signal +import sys +import time +import shutil + +from .test_api import * +import this + + +''' +The run evironment dir structure: + + run/ + run{date-time}/ + suites/ + {suite name}/ + -- target/ (the target software being tested) + -- tools/ (the tools for testing the target software) +''' + + +framework=None + +def get_framework(): + global framework + return framework + +def my_import(name): + mod = __import__(name) + components = name.split('.') + for comp in components[1:]: + mod = getattr(mod, comp) + return mod + + +# we maintain a root path apart from framework location +# so the suites can be located in anywhere +class CTestFramework(object): + + def __init__(self, path): + self.running_case = '' + self.running_suite = '' + self.target_suites = {} + self.target_cases = {} + self.root_path = path + self.running_folder='' + self.report = None + self.sucess_cases = 0 + self.failed_cases = 0 + self.setup_fails = 0 + self.load_fails = 0; + global framework + framework = self + + api_set_root_path(path) + + print "root_path is " + self.root_path + + def gen_execution_stats(self): + return '\nTest Execution Summary: ' \ + '\n\tSuccess: {}' \ + '\n\tCases fails: {}' \ + '\n\tSetup fails: {}' \ + '\n\tCase load fails: {}'.format( + self.sucess_cases, self.failed_cases, self.setup_fails, self.load_fails) + + def report_result(self, success, message, case_description): + if self.report is None: + return + + case_pass = "pass" + if not success: + case_pass = "fail" + + self.report.write(case_pass + ": [" + self.running_case + "]\n\treason: " + \ + message + "\n\tcase: " + case_description + "\n") + return + + def get_running_path(self): + return self.root_path + "/run/" + self.running_folder + + def load_suites(self): + self.target_suites = os.listdir(self.root_path + "/suites") + return + + def run_case(self, suite_instance, case): + # load the test case module + case_description = '' + suite = suite_instance.m_name + api_log("\n>>start run [" + case + "] >>") + module_name = 'suites.' + suite + ".cases." + case + ".case" + try: + module = my_import(module_name) + except Exception, e: + report_fail("load case fail: " + str(e)) + api_log_error("load case fail: " + str(e)) + self.load_fails = self.load_fails +1 + print(traceback.format_exc()) + return False + + try: + case = module.CTestCase(suite_instance) + except Exception, e: + report_fail("initialize case fail: " + str(e)) + api_log_error("initialize case fail: " + str(e)) + self.load_fails = self.load_fails +1 + return False + + # call the case on setup callback + try: + case_description = case.on_get_case_description() + result, message = case.on_setup_case() + except Exception, e: + result = False + message = str(e); + if not result: + api_log_error(message) + report_fail (message, case_description) + self.failed_cases = self.failed_cases+1 + return False + + # call the case execution callaback + try: + result, message = case.on_run_case() + except Exception, e: + result = False + message = str(e); + if not result: + report_fail (message, case_description) + api_log_error(message) + self.failed_cases = self.failed_cases+1 + else: + report_success(case_description) + self.sucess_cases = self.sucess_cases +1 + + # call the case cleanup callback + try: + clean_result, message = case.on_cleanup_case() + except Exception, e: + clean_result = False + message = str(e) + + if not clean_result: + api_log(message) + + return result + + def run_suite(self, suite, cases): + # suite setup + message = '' + api_log("\n>>> Suite [" + suite + "] starting >>>") + running_folder = self.get_running_path()+ "/suites/" + suite; + + module_name = 'suites.' + suite + ".suite_setup" + try: + module = my_import(module_name) + except Exception, e: + report_fail("load suite [" + suite +"] fail: " + str(e)) + self.load_fails = self.load_fails +1 + return False + + try: + suite_instance = module.CTestSuite(suite, \ + self.root_path + '/suites/' + suite, running_folder) + except Exception, e: + report_fail("initialize suite fail: " + str(e)) + self.load_fails = self.load_fails +1 + return False + + result, message = suite_instance.load_settings() + if not result: + report_fail("load settings fail: " + str(e)) + self.load_fails = self.load_fails +1 + return False + + try: + result, message = suite_instance.on_suite_setup() + except Exception, e: + result = False + message = str(e); + if not result: + api_log_error(message) + report_fail (message) + self.setup_fails = self.setup_fails + 1 + return False + + self.running_suite = suite + + cases.sort() + + # run cases + for case in cases: + if not os.path.isdir(self.root_path + '/suites/' + suite + '/cases/' + case): + continue + + self.running_case = case + self.run_case(suite_instance, case) + self.running_case = '' + + # suites cleanup + self.running_suite = '' + try: + result, message = suite_instance.on_suite_cleanup() + except Exception, e: + result = False + message = str(e); + if not result: + api_log_error(message) + report_fail (message) + self.setup_fails = self.setup_fails + 1 + return + + def start_run(self): + if self.target_suites is None: + print "\n\nstart run: no target suites, exit.." + return + + cur_time = time.localtime() + time_prefix = "{:02}-{:02}-{:02}-{:02}".format( + cur_time.tm_mon, cur_time.tm_mday, cur_time.tm_hour, cur_time.tm_min) + + debug = api_get_value('debug', False) + if debug: + self.running_folder = 'debug' + else: + self.running_folder = 'run-' + time_prefix + + folder = self.root_path + "/run/" +self.running_folder; + + if os.path.exists(folder): + shutil.rmtree(folder, ignore_errors=True) + + if not os.path.exists(folder): + os.makedirs(folder ) + os.makedirs(folder + "/suites") + + api_init_log(folder + "/test.log") + + self.report = open(folder + "/report.txt", 'a') + + self.target_suites.sort() + + for suite in self.target_suites: + if not os.path.isdir(self.root_path + '/suites/' + suite): + continue + self.report.write("suite " + suite + " cases:\n") + if self.target_cases is None: + cases = os.listdir(self.root_path + "/suites/" + suite + "/cases") + self.run_suite(suite, cases) + else: + self.run_suite(suite, self.target_cases) + self.report.write("\n") + + self.report.write("\n\n") + summary = self.gen_execution_stats() + self.report.write(summary); + self.report.flush() + self.report.close() + print summary + + +def report_fail(message, case_description=''): + global framework + if framework is not None: + framework.report_result(False, message, case_description) + + api_log_error(message) + + return + +def report_success(case_description=''): + global framework + if framework is not None: + framework.report_result(True , "OK", case_description) + return diff --git a/test-tools/component_test/framework/suite.py b/test-tools/component_test/framework/suite.py new file mode 100644 index 000000000..2b690b08f --- /dev/null +++ b/test-tools/component_test/framework/suite.py @@ -0,0 +1,40 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import os +import json + +class CTestSuiteBase(object): + def __init__(self, name, suite_path, run_path): + self.suite_path=suite_path + self.run_path=run_path + self.m_name = name + self.settings = {} + + def get_settings_item(self, item): + if item in self.settings: + return self.settings[item] + else: + return None + + def load_settings(self): + path = self.suite_path + "/settings.cfg" + if os.path.isfile(path): + try: + fp = open(path, 'r') + self.settings = json.load(fp) + fp.close() + except Exception, e: + return False, 'Load settings fail: ' + e.message + return True, 'OK' + else: + return True, 'No file' + + def on_suite_setup(self): + return True, 'OK' + + def on_suite_cleanup(self): + return True, 'OK' + diff --git a/test-tools/component_test/framework/test_api.py b/test-tools/component_test/framework/test_api.py new file mode 100644 index 000000000..ed9391e29 --- /dev/null +++ b/test-tools/component_test/framework/test_api.py @@ -0,0 +1,98 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import logging +import threading +from .test_utils import * + +global logger +logger = None + +def api_init_log(log_path): + global logger + print "api_init_log: " + log_path + logger = logging.getLogger(__name__) + + logger.setLevel(level = logging.INFO) + handler = logging.FileHandler(log_path) + handler.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + handler.setFormatter(formatter) + + console = logging.StreamHandler() + console.setLevel(logging.INFO) + + logger.addHandler(handler) + logger.addHandler(console) + + return + +def api_log(message): + global logger + if logger is None: + print message + else: + logger.info (message) + return + +def api_log_error(message): + global logger + if logger is None: + print message + else: + logger.error (message) + return + +def api_logv(message): + global logger + if logger is None: + print message + else: + logger.info(message) + return + +#####################################3 +global g_case_runner_event +def api_wait_case_event(timeout): + global g_case_runner_event + g_case_runner_event.clear() + g_case_runner_event.wait(timeout) + +def api_notify_case_runner(): + global g_case_runner_event + g_case_runner_event.set() + +def api_create_case_event(): + global g_case_runner_event + g_case_runner_event = threading.Event() + +####################################### + +def api_init_globals(): + global _global_dict + _global_dict = {} + +def api_set_value(name, value): + _global_dict[name] = value + +def api_get_value(name, defValue=None): + try: + return _global_dict[name] + except KeyError: + return defValue + + +######################################### +global root_path +def api_set_root_path(root): + global root_path + root_path = root + +def api_get_root_path(): + global root_path + return root_path; + + + diff --git a/test-tools/component_test/framework/test_utils.py b/test-tools/component_test/framework/test_utils.py new file mode 100644 index 000000000..1b8bbd01e --- /dev/null +++ b/test-tools/component_test/framework/test_utils.py @@ -0,0 +1,70 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import datetime +import os +import random +import re +import shlex +import subprocess +import sys +import time +import shutil +from subprocess import check_output, CalledProcessError + +def t_getPIDs(process): + try: + pidlist = map(int, check_output(["pidof", process]).split()) + except CalledProcessError: + pidlist = [] + #print process + ':list of PIDs = ' + ', '.join(str(e) for e in pidlist) + return pidlist + + +def t_kill_process_by_name(p_keywords): + pid_list = [] + ps_info = subprocess.check_output(shlex.split("ps aux")).split("\n") + for p in ps_info: + if p_keywords in p: + tmp = p.split(" ") + tmp = [x for x in tmp if len(x) > 0] + pid_list.append(tmp[1]) + + for pid in pid_list: + cmd = "kill -9 {}".format(pid) + subprocess.call(shlex.split(cmd)) + + return pid_list + + + +#proc -> name of the process +#kill = 1 -> search for pid for kill +#kill = 0 -> search for name (default) + +def t_process_exists(proc, kill = 0): + ret = False + processes = t_getPIDs(proc) + + for pid in processes: + if kill == 0: + return True + else: + print "kill [" + proc + "], pid=" + str(pid) + os.kill((pid), 9) + ret = True + return ret + +def t_copy_files(source_dir, pattern, dest_dir): + files = os.listdir(source_dir) + for file in files: + if file is '/' or file is '.' or file is '..': + continue + + if pattern == '*' or pattern is '' or files.endswith(pattern): + shutil.copy(source_dir+"/"+ file,dest_dir) + + + diff --git a/test-tools/component_test/harness/__init__.py b/test-tools/component_test/harness/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/harness/harness_api.py b/test-tools/component_test/harness/harness_api.py new file mode 100644 index 000000000..e35aa6b4c --- /dev/null +++ b/test-tools/component_test/harness/harness_api.py @@ -0,0 +1,150 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import os +import shutil +import subprocess +import json +import time + +from framework import test_api +from framework.test_utils import * + +output = "output.txt" + +def start_env(): + os.system("./start.sh") + +def stop_env(): + os.system("./stop.sh") + time.sleep(0.5) + os.chdir("../") #reset path for other cases in the same suite + +def check_is_timeout(): + line_num = 0 + ft = open(output, 'r') + lines = ft.readlines() + + for line in reversed(lines): + if (line[0:36] == "--------one operation begin.--------"): + break + line_num = line_num + 1 + + ft.close() + if (lines[-(line_num)] == "operation timeout"): + return True + else: + return False + +def parse_ret(file): + ft = open(file, 'a') + ft.writelines("\n") + ft.writelines("--------one operation finish.--------") + ft.writelines("\n") + ft.close() + + ft = open(file, 'r') + for line in reversed(ft.readlines()): + if (line[0:16] == "response status "): + ret = line[16:] + ft.close() + return int(ret) + +def run_host_tool(cmd, file): + ft = open(file, 'a') + ft.writelines("--------one operation begin.--------") + ft.writelines("\n") + ft.close() + os.system(cmd + " -o" + file) + if (check_is_timeout() == True): + return -1 + return parse_ret(file) + +def install_app(app_name, file_name): + return run_host_tool("./host_tool -i " + app_name + " -f ../test-app/" + file_name, output) + +def uninstall_app(app_name): + return run_host_tool("./host_tool -u " + app_name, output) + +def query_app(): + return run_host_tool("./host_tool -q ", output) + +def send_request(url, action, payload): + if (payload is None): + return run_host_tool("./host_tool -r " + url + " -A " + action, output) + else: + return run_host_tool("./host_tool -r " + url + " -A " + action + " -p " + payload, output) + +def register(url, timeout, alive_time): + return run_host_tool("./host_tool -s " + url + " -t " + str(timeout) + " -a " + str(alive_time), output) + +def deregister(url): + return run_host_tool("./host_tool -d " + url, output) + +def get_response_payload(): + line_num = 0 + ft = open(output, 'r') + lines = ft.readlines() + + for line in reversed(lines): + if (line[0:16] == "response status "): + break + line_num = line_num + 1 + + payload_lines = lines[-(line_num):-1] + ft.close() + + return payload_lines + +def check_query_apps(expected_app_list): + if (check_is_timeout() == True): + return False + json_lines = get_response_payload() + json_str = " ".join(json_lines) + json_dict = json.loads(json_str) + app_list = [] + + for key, value in json_dict.items(): + if key[0:6] == "applet": + app_list.append(value) + + if (sorted(app_list) == sorted(expected_app_list)): + return True + else: + return False + +def check_response_payload(expected_payload): + if (check_is_timeout() == True): + return False + json_lines = get_response_payload() + json_str = " ".join(json_lines) + + if (json_str.strip() != ""): + json_dict = json.loads(json_str) + else: + json_dict = {} + + if (json_dict == expected_payload): + return True + else: + return False + +def check_get_event(): + line_num = 0 + ft = open(output, 'r') + lines = ft.readlines() + + for line in reversed(lines): + if (line[0:16] == "response status "): + break + line_num = line_num + 1 + + payload_lines = lines[-(line_num):-1] + ft.close() + + if (payload_lines[1][0:17] == "received an event"): + return True + else: + return False diff --git a/test-tools/component_test/host-clients/src/host_app_sample.c b/test-tools/component_test/host-clients/src/host_app_sample.c new file mode 100644 index 000000000..1fb4ba121 --- /dev/null +++ b/test-tools/component_test/host-clients/src/host_app_sample.c @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include "host_api.h" +#include "bi-inc/attr_container.h" +#include "er-coap-constants.h" + +static char *read_file_to_buffer(const char *filename, int *ret_size); +int send_request_to_applet_success = 0; +const char *label_for_request = "request1"; +int event_listener_counter = 0; +char *applet_buf[1024 * 1024]; +const char *host_agent_ip = "127.0.0.1"; +void f_aee_response_handler(void *usr_ctx, aee_response_t *response) +{ + if (response == NULL) { + printf("########## request timeout!!! \n"); + } else { + char *str = (char *) usr_ctx; + printf("#### dump response ####\n"); + printf("#### user data: %s \n", str); + printf("#### status: %d \n", response->status); + if (response->payload != NULL) + attr_container_dump((attr_container_t *) response->payload); + } +} + +void f_aee_event_listener(const char *url, void *event, int fmt) +{ + printf("######## event is received. url: %s, fmt:%d ############\n", url, + fmt); + + attr_container_t *attr_obj = (attr_container_t *) event; + + attr_container_dump(attr_obj); + /* + if (0 == strcmp(url, "alert/overheat")) + { + event_listener_counter++; + printf("event :%d \n", event_listener_counter); + } + */ +} + +static int print_menu_and_select(void) +{ + char s[256]; + int choice; + do { + printf("\n"); + printf("1. Install TestApplet1\n"); + printf("2. Install TestApplet2\n"); + printf("3. Install TestApplet3\n"); + printf("4. Uninstall TestApplet1\n"); + printf("5. Uninstall TestApplet2\n"); + printf("6. Uninstall TestApplet3\n"); + printf("7. Send Request to TestApplet1\n"); + printf("8. Register Event to TestApplet1\n"); + printf("9. UnRegister Event to TestApplet1\n"); + printf("a. Query Applets\n"); + printf("t. Auto Test\n"); + printf("q. Exit\n"); + printf("Please Select: "); + + if (fgets(s, sizeof(s), stdin)) { + if (!strncmp(s, "q", 1)) + return 0; + if (!strncmp(s, "a", 1)) + return 10; + if (!strncmp(s, "t", 1)) + return 20; + choice = atoi(s); + if (choice >= 1 && choice <= 9) + return choice; + } + } while (1); + return 0; +} + +static void install_applet(int index) +{ + char applet_name[64]; + char applet_file_name[64]; + char *buf; + int size; + int ret; + + printf("Installing TestApplet%d...\n", index); + snprintf(applet_name, sizeof(applet_name), "TestApplet%d", index); + snprintf(applet_file_name, sizeof(applet_file_name), "./TestApplet%d.wasm", + index); + buf = read_file_to_buffer(applet_file_name, &size); + if (!buf) { + printf("Install Applet failed: read file %s error.\n", + applet_file_name); + return; + } + + //step2. install applet + ret = aee_applet_install(buf, "wasm", size, applet_name, 5000); + if (ret) { + printf("%s install success\n", applet_name); + } + free(buf); +} + +static void uninstall_applet(int index) +{ + int ret; + char applet_name[64]; + snprintf(applet_name, sizeof(applet_name), "TestApplet%d", index); + ret = aee_applet_uninstall(applet_name, "wasm", 5000); + if (ret) { + printf("uninstall %s success\n", applet_name); + } else { + printf("uninstall %s failed\n", applet_name); + } +} + +static void send_request(int index) +{ + char url[64]; + int ret; + aee_request_t req; + const char *user_context = "label for request"; + attr_container_t *attr_obj = attr_container_create( + "Send Request to Applet"); + attr_container_set_string(&attr_obj, "String key", "Hello"); + attr_container_set_int(&attr_obj, "Int key", 1000); + attr_container_set_int64(&attr_obj, "Int64 key", 0x77BBCCDD11223344LL); + + //specify the target wasm app + snprintf(url, sizeof(url), "/app/TestApplet%d/url1", index); + + //not specify the target wasm app + //snprintf(url, sizeof(url), "url1"); + aee_request_init(&req, url, COAP_PUT); + aee_request_set_payload(&req, attr_obj, + attr_container_get_serialize_length(attr_obj), + PAYLOAD_FORMAT_ATTRIBUTE_OBJECT); + ret = aee_request_send(&req, f_aee_response_handler, (void *) user_context, + 10000); + + if (ret) { + printf("send request to TestApplet1 success\n"); + } +} + +static void register_event(const char *event_path) +{ + hostclient_register_event(event_path, f_aee_event_listener); +} + +static void unregister_event(const char *event_path) +{ + hostclient_unregister_event(event_path); +} + +static void query_applets() +{ + aee_applet_list_t applet_lst; + aee_applet_list_init(&applet_lst); + aee_applet_list(5000, &applet_lst); + aee_applet_list_clean(&applet_lst); +} + +static char * +read_file_to_buffer(const char *filename, int *ret_size) +{ + FILE *fl = NULL; + char *buffer = NULL; + int file_size = 0; + if (!(fl = fopen(filename, "rb"))) { + printf("file open failed\n"); + return NULL; + } + + fseek(fl, 0, SEEK_END); + file_size = ftell(fl); + + if (file_size == 0) { + printf("file length 0\n"); + return NULL; + } + + if (!(buffer = (char *) malloc(file_size))) { + fclose(fl); + return NULL; + } + + fseek(fl, 0, SEEK_SET); + + if (!fread(buffer, 1, file_size, fl)) { + printf("file read failed\n"); + return NULL; + } + + fclose(fl); + *ret_size = file_size; + return buffer; +} + +static void auto_test() +{ + int i; + int interval = 1000; /* ms */ + while (1) { + uninstall_applet(1); + uninstall_applet(2); + uninstall_applet(3); + install_applet(1); + install_applet(2); + install_applet(3); + + for (i = 0; i < 60 * 1000 / interval; i++) { + query_applets(); + send_request(1); + send_request(2); + send_request(3); + usleep(interval * 1000); + } + } +} + +void exit_program() +{ + hostclient_shutdown(); + exit(0); +} + +int + +main() +{ + bool ret; + + //step1. host client init + ret = hostclient_initialize(host_agent_ip, 3456); + + if (!ret) { + printf("host client initialize failed\n"); + return -1; + } + + do { + int choice = print_menu_and_select(); + printf("\n"); + + if (choice == 0) + exit_program(); + if (choice <= 3) + install_applet(choice); + else if (choice <= 6) + uninstall_applet(choice - 3); + else if (choice <= 7) + send_request(1); + else if (choice <= 8) + register_event("alert/overheat"); + else if (choice <= 9) + unregister_event("alert/overheat"); + else if (choice == 10) + query_applets(); + else if (choice == 20) + auto_test(); + } while (1); + + return 0; +} + +// Run program: Ctrl + F5 or Debug > Start Without Debugging menu +// Debug program: F5 or Debug > Start Debugging menu + +// Tips for Getting Started: +// 1. Use the Solution Explorer window to add/manage files +// 2. Use the Team Explorer window to connect to source control +// 3. Use the Output window to see build output and other messages +// 4. Use the Error List window to view errors +// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project +// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file diff --git a/test-tools/component_test/host-clients/src/makefile b/test-tools/component_test/host-clients/src/makefile new file mode 100644 index 000000000..763a60c38 --- /dev/null +++ b/test-tools/component_test/host-clients/src/makefile @@ -0,0 +1,44 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +CC = gcc +CFLAGS := -Wall -g + +# Add this to make compiler happy +CFLAGS += -DWASM_ENABLE_INTERP=1 + +host_api_c=../../../../host-agent/host-api-c +attr_container_dir=../../../../wamr/core/app-framework/app-native-shared +coap_dir=../../../../host-agent/coap +shared_dir=../../../../wamr/core/shared + +# core +INCLUDE_PATH = -I$(host_api_c)/src -I$(attr_container_dir)/ \ + -I$(coap_dir)/er-coap -I$(coap_dir)/er-coap/extension \ + -I$(shared_dir)/include \ + -I$(shared_dir)/utils \ + -I$(shared_dir)/platform/include/ \ + -I$(shared_dir)/platform/linux/ + +LIB := $(host_api_c)/src/libhostapi.a +EXE := ./hostapp + +App_C_Files := host_app_sample.c + +OBJS := $(App_C_Files:.c=.o) + +all: $(EXE) + +%.o: %.c + @$(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE_PATH) + +$(EXE): $(OBJS) + @rm -f $(EXE) + @$(CC) $(OBJS) -o $(EXE) $(LIB) -lpthread -lrt + @rm -f $(OBJS) + +.PHONY: clean +clean: + rm -f $(OBJS) $(EXE) diff --git a/test-tools/component_test/set_dev_env.sh b/test-tools/component_test/set_dev_env.sh new file mode 100755 index 000000000..1abe23b80 --- /dev/null +++ b/test-tools/component_test/set_dev_env.sh @@ -0,0 +1,7 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/sh + diff --git a/test-tools/component_test/start.py b/test-tools/component_test/start.py new file mode 100755 index 000000000..062ec2e47 --- /dev/null +++ b/test-tools/component_test/start.py @@ -0,0 +1,151 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/usr/bin/env python + +# -*- coding: utf-8 -*- +""" +It is the entrance of the iagent test framework. + +""" + +import argparse +import datetime +import os +import pprint +import random +import re +import shlex +import subprocess +import signal +import sys +import time + +sys.path.append('../../../app-sdk/python') +from framework.test_utils import * +from framework.framework import * + + +def signal_handler(signal, frame): + print('Pressed Ctrl+C!') + sys.exit(0) + +def Register_signal_handler(): + signal.signal(signal.SIGINT, signal_handler) +# signal.pause() + + +def flatten_args_list(l): + if l is None: + return None + + return [x for y in l for x in y] + + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description = "to run specific case(s) "\ + "in specific suite(s) with FC test framework") + parser.add_argument('-s', dest = 'suite_id', action = 'append', + nargs = '+', + help = 'one or multiple suite ids, which are also setup ids.'\ + 'by default if it isn\'t passed from argument, all '\ + 'suites are going to be run.') + parser.add_argument('-t', dest = 'case_id', action = 'append', + nargs = '+', + help = 'one or multiple cases ids.'\ + 'by default if it isn\'t passed from argument, all '\ + 'cases in specific suites are going to be run.') + parser.add_argument('-n', dest = 'repeat_time', action = 'store', + default = 1, + help = 'how many times do you want to run. there is 40s '\ + 'break time between two rounds. each round includs '\ + 'init_setup, run_test_case and deinit_setup.') + parser.add_argument('--shuffle_all', dest = 'shuffle_all', + default = False, action = 'store_true', + help = 'shuffle_all test cases in per test suite '\ + 'by default, all cases under per suite should '\ + 'be executed by input order.') + parser.add_argument('--cases_list', dest='cases_list_file_path', + default=None, + action='store', + help="read cases list from a flie ") + parser.add_argument('--skip_proc', dest='skip_proc', + default = False, action = 'store_true', + help='do not start the test process.'\ + 'sometimes the gw_broker process will be started in eclipse for debug purpose') + parser.add_argument('-b', dest = 'binaries', action = 'store', + help = 'The path of target folder ') + parser.add_argument('-d', dest = 'debug', action = 'store_true', + help = 'wait user to attach the target process after launch processes ') + parser.add_argument('--rebuild', dest = 'rebuild', action = 'store_true', + help = 'rebuild all test binaries') + args = parser.parse_args() + + print "------------------------------------------------------------" + print "parsing arguments ... ..." + print args + + ''' + logger = logging.getLogger('coapthon.server.coap') + logger.setLevel(logging.DEBUG) + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + logger.addHandler(console) + ''' + print "------------------------------------------------------------" + print "preparing wamr binary and test tools ... ..." + os.system("cd ../../samples/simple/ && bash build.sh -p host-interp") + + Register_signal_handler() + + api_init_globals(); + + api_create_case_event(); + + suites_list = flatten_args_list(args.suite_id) + cases_list = flatten_args_list(args.case_id) + + dirname, filename = os.path.split(os.path.abspath(sys.argv[0])) + api_set_root_path(dirname); + + framework = CTestFramework(dirname); + framework.repeat_time = int(args.repeat_time) + framework.shuffle_all = args.shuffle_all + framework.skip_proc=args.skip_proc + + api_set_value('keep_env', args.skip_proc) + api_set_value('debug', args.debug) + api_set_value('rebuild', args.rebuild) + + binary_path = args.binaries + if binary_path is None: + binary_path = os.path.abspath(dirname + '/../..') + + print "checking execution binary path: " + binary_path + if not os.path.exists(binary_path): + print "The execution binary path was not available. quit..." + os._exit(0) + api_set_value('binary_path', binary_path) + + if suites_list is not None: + framework.target_suites = suites_list + else: + framework.load_suites() + + framework.target_cases = cases_list + framework.start_run() + + print "\n\n------------------------------------------------------------" + print "The run folder is [" + framework.running_folder +"]" + print "that's all. bye" + + print "kill to quit.." + t_kill_process_by_name("start.py") + + sys.exit(0) + os._exit() + + diff --git a/test-tools/component_test/suites/01-life-cycle/__init__.py b/test-tools/component_test/suites/01-life-cycle/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/cases/01-install/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/01-install/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/cases/01-install/case.py b/test-tools/component_test/suites/01-life-cycle/cases/01-install/case.py new file mode 100644 index 000000000..b8d2c38b8 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/01-install/case.py @@ -0,0 +1,94 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #uninstall inexistent App1 + ret = uninstall_app("App1") + if (ret != 160): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps([]) + if (ret == False): + return False, '' + + #install App1 + ret = install_app("App1", "01_install.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #install App2 + ret = install_app("App2", "01_install.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1","App2"]) + if (ret == False): + return False, '' + + #uninstall App2 + ret = uninstall_app("App2") + if (ret != 66): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/02-request/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/02-request/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/cases/02-request/case.py b/test-tools/component_test/suites/01-life-cycle/cases/02-request/case.py new file mode 100644 index 000000000..e2192d5fa --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/02-request/case.py @@ -0,0 +1,73 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "02_request.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res2", "DELETE", None) + if (ret != 66): + return False, '' + expect_response_payload = {} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/03-event/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/03-event/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/cases/03-event/case.py b/test-tools/component_test/suites/01-life-cycle/cases/03-event/case.py new file mode 100644 index 000000000..3886cb820 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/03-event/case.py @@ -0,0 +1,67 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "03_event.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #register event + ret = register("/alert/overheat", 2000, 5000) + if (ret != 69): + return False, '' + ret = check_get_event() + if (ret == False): + return False, '' + + #deregister event + ret = deregister("/alert/overheat") + if (ret != 69): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/case.py b/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/case.py new file mode 100644 index 000000000..bf395f58b --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/case.py @@ -0,0 +1,80 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "04_request_internal_resp.wasm") + if (ret != 65): + return False, '' + + #install App2 + ret = install_app("App2", "04_request_internal_req.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1","App2"]) + if (ret == False): + return False, '' + + #send request to App2 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + #send request to App2 + ret = send_request("/res2", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/case.py b/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/case.py new file mode 100644 index 000000000..79c328749 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/case.py @@ -0,0 +1,70 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "05_event_internal_provider.wasm") + if (ret != 65): + return False, '' + + #install App2 + ret = install_app("App2", "05_event_internal_subscriber.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1","App2"]) + if (ret == False): + return False, '' + + #send request to App2 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/06-timer/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/06-timer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/cases/06-timer/case.py b/test-tools/component_test/suites/01-life-cycle/cases/06-timer/case.py new file mode 100644 index 000000000..90af4d5d9 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/06-timer/case.py @@ -0,0 +1,70 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "06_timer.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + + time.sleep(3) + + ret = send_request("/check_timer", "GET", None) + if (ret != 69): + return False, '' + expect_response_payload = {"num":2} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/case.py b/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/case.py new file mode 100644 index 000000000..2bb756203 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/case.py @@ -0,0 +1,65 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "07_sensor.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/case.py b/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/case.py new file mode 100644 index 000000000..99a4512ee --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/case.py @@ -0,0 +1,78 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "08_on_destroy.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + #uninstall App1 + ret = uninstall_app("App1") + if (ret != 66): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps([]) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/01-life-cycle/suite_setup.py b/test-tools/component_test/suites/01-life-cycle/suite_setup.py new file mode 100644 index 000000000..2307186f7 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/suite_setup.py @@ -0,0 +1,56 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import os +import shutil +import types +import time +import glob + +from framework.test_api import * +from framework.test_utils import * +from harness.harness_api import * +from framework.suite import * + +class CTestSuite(CTestSuiteBase): + setup_path = "" + def __init__(self, name, suite_path, run_path): + CTestSuiteBase.__init__(self, name, suite_path, run_path) + + def on_suite_setup(self): + global setup_path + setup_path = os.getcwd() + cases = os.listdir(self.suite_path + "/cases/") + cases.sort() + + if api_get_value("rebuild", False): + path_tmp = os.getcwd() + os.chdir(self.suite_path + "/test-app") + os.system(self.suite_path + "/test-app" + "/build.sh") + os.chdir(path_tmp) + + os.makedirs(self.run_path + "/test-app") + + for case in cases: + if case != "__init__.pyc" and case != "__init__.py": + os.makedirs(self.run_path + "/" + case) + #copy each case's host_tool, simple, wasm files, start/stop scripts to the run directory, + shutil.copy(setup_path + "/../../samples/simple/out/simple", self.run_path + "/" + case) + shutil.copy(setup_path + "/../../samples/simple/out/host_tool", self.run_path + "/" + case) + for file in glob.glob(self.suite_path + "/test-app/" + "/*.wasm"): + shutil.copy(file, self.run_path + "/test-app") + shutil.copy(self.suite_path + "/tools/product/start.sh", self.run_path + "/" + case) + shutil.copy(self.suite_path + "/tools/product/stop.sh", self.run_path + "/" + case) + + os.chdir(self.run_path) + + return True, 'OK' + + def on_suite_cleanup(self): + global setup_path + os.chdir(setup_path) + api_log("stopping env..") + + return True, 'OK' diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/01_install.c b/test-tools/component_test/suites/01-life-cycle/test-app/01_install.c new file mode 100644 index 000000000..f8ec39373 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/01_install.c @@ -0,0 +1,16 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" + +void on_init() +{ + printf("Hello, I was installed.\n"); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/02_request.c b/test-tools/component_test/suites/01-life-cycle/test-app/02_request.c new file mode 100644 index 000000000..ee7ecafee --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/02_request.c @@ -0,0 +1,62 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" + +void res1_handler(request_t *request) +{ + response_t response[1]; + attr_container_t *payload; + + printf("### user resource 1 handler called\n"); + + printf("###### dump request ######\n"); + printf("sender: %lu\n", request->sender); + printf("url: %s\n", request->url); + printf("action: %d\n", request->action); + printf("payload:\n"); + if (request->payload + != NULL&& request->payload_len > 0 && request->fmt == FMT_ATTR_CONTAINER) + attr_container_dump((attr_container_t *) request->payload); + printf("#### dump request end ###\n"); + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + make_response_for_request(request, response); + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void res2_handler(request_t *request) +{ + response_t response[1]; + make_response_for_request(request, response); + set_response(response, DELETED_2_02, 0, NULL, 0); + api_response_send(response); + + printf("### user resource 2 handler called\n"); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); + api_register_resource_handler("/res2", res2_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/03_event.c b/test-tools/component_test/suites/01-life-cycle/test-app/03_event.c new file mode 100644 index 000000000..712110a9b --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/03_event.c @@ -0,0 +1,53 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/timer_wasm_app.h" +#include "wa-inc/request.h" + +int num = 0; + +void publish_overheat_event() +{ + attr_container_t *event; + + event = attr_container_create("event"); + attr_container_set_string(&event, "warning", "temperature is over high"); + + printf("###app publish event begin ###\n"); + + api_publish_event("alert/overheat", FMT_ATTR_CONTAINER, event, + attr_container_get_serialize_length(event)); + + printf("###app publish event end ###\n"); + + attr_container_destroy(event); +} + +/* Timer callback */ +void timer1_update(user_timer_t timer) +{ + printf("Timer update %d\n", num++); + publish_overheat_event(); +} + +void start_timer() +{ + user_timer_t timer; + + /* set up a timer */ + timer = api_timer_create(1000, true, false, timer1_update); + api_timer_restart(timer, 1000); +} + +void on_init() +{ + start_timer(); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_req.c b/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_req.c new file mode 100644 index 000000000..3e3ad0e60 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_req.c @@ -0,0 +1,66 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" + +uint32 mid; +unsigned long sender; + +void my_response_handler(response_t *response, void *user_data) +{ + attr_container_t *payload; + printf("### user resource 1 handler called\n"); + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + response->mid = mid; + response->reciever = sender; + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +static void test_send_request(const char *url, const char *tag) +{ + request_t request[1]; + + init_request(request, (char *)url, COAP_PUT, 0, NULL, 0); + api_send_request(request, my_response_handler, (void *)tag); +} + +void res1_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + test_send_request("url1", "a general request"); +} + +void res2_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + test_send_request("/app/App1/url1", "a general request"); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); + api_register_resource_handler("/res2", res2_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_resp.c b/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_resp.c new file mode 100644 index 000000000..45b25cbd2 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_resp.c @@ -0,0 +1,52 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" + +void res1_handler(request_t *request) +{ + response_t response[1]; + attr_container_t *payload; + + printf("[resp] ### user resource 1 handler called\n"); + + printf("[resp] ###### dump request ######\n"); + printf("[resp] sender: %lu\n", request->sender); + printf("[resp] url: %s\n", request->url); + printf("[resp] action: %d\n", request->action); + printf("[resp] payload:\n"); + if (request->payload != NULL && request->fmt == FMT_ATTR_CONTAINER) + attr_container_dump((attr_container_t *) request->payload); + printf("[resp] #### dump request end ###\n"); + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + make_response_for_request(request, response); + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("[resp] response payload len %d\n", + attr_container_get_serialize_length(payload)); + printf("[resp] reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/url1", res1_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_provider.c b/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_provider.c new file mode 100644 index 000000000..712110a9b --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_provider.c @@ -0,0 +1,53 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/timer_wasm_app.h" +#include "wa-inc/request.h" + +int num = 0; + +void publish_overheat_event() +{ + attr_container_t *event; + + event = attr_container_create("event"); + attr_container_set_string(&event, "warning", "temperature is over high"); + + printf("###app publish event begin ###\n"); + + api_publish_event("alert/overheat", FMT_ATTR_CONTAINER, event, + attr_container_get_serialize_length(event)); + + printf("###app publish event end ###\n"); + + attr_container_destroy(event); +} + +/* Timer callback */ +void timer1_update(user_timer_t timer) +{ + printf("Timer update %d\n", num++); + publish_overheat_event(); +} + +void start_timer() +{ + user_timer_t timer; + + /* set up a timer */ + timer = api_timer_create(1000, true, false, timer1_update); + api_timer_restart(timer, 1000); +} + +void on_init() +{ + start_timer(); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_subscriber.c b/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_subscriber.c new file mode 100644 index 000000000..dd031f80a --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_subscriber.c @@ -0,0 +1,50 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" + +uint32 mid; +unsigned long sender; + +void over_heat_event_handler(request_t *request) +{ + response_t response[1]; + attr_container_t *payload; + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + response->mid = mid; + response->reciever = sender; + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void res1_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + api_subscribe_event("alert/overheat", over_heat_event_handler); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/06_timer.c b/test-tools/component_test/suites/01-life-cycle/test-app/06_timer.c new file mode 100644 index 000000000..c20365717 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/06_timer.c @@ -0,0 +1,76 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" +#include "wa-inc/timer_wasm_app.h" + +/* User global variable */ +int num = 0; + +/* Timer callback */ +void timer1_update(user_timer_t timer) +{ + if (num < 2) + num++; +} + +void res1_handler(request_t *request) +{ + user_timer_t timer; + + /* set up a timer */ + timer = api_timer_create(1000, true, false, timer1_update); + api_timer_restart(timer, 1000); + + response_t response[1]; + + make_response_for_request(request, response); + + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, NULL, 0); + + api_response_send(response); +} + +void res2_handler(request_t *request) +{ + response_t response[1]; + attr_container_t *payload; + + if (num == 2) { + attr_container_t *payload; + printf("### user resource 1 handler called\n"); + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_int(&payload, "num", num); + + make_response_for_request(request, response); + + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, + attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); + } + +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); + api_register_resource_handler("/check_timer", res2_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/07_sensor.c b/test-tools/component_test/suites/01-life-cycle/test-app/07_sensor.c new file mode 100644 index 000000000..24af34c91 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/07_sensor.c @@ -0,0 +1,69 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" +#include "wa-inc/sensor.h" + +uint32 mid; +unsigned long sender; + +/* Sensor event callback*/ +void sensor_event_handler(sensor_t sensor, attr_container_t *event, + void *user_data) +{ + printf("### app get sensor event\n"); + + response_t response[1]; + attr_container_t *payload; + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + response->mid = mid; + response->reciever = sender; + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void res1_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + + sensor_t sensor; + char *user_data; + attr_container_t *config; + + printf("### app on_init 1\n"); + /* open a sensor */ + user_data = malloc(100); + printf("### app on_init 2\n"); + sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data); + printf("### app on_init 3\n"); + + /* config the sensor */ + sensor_config(sensor, 2000, 0, 0); + printf("### app on_init 4\n"); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/08_on_destroy.c b/test-tools/component_test/suites/01-life-cycle/test-app/08_on_destroy.c new file mode 100644 index 000000000..637e0f7a6 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/08_on_destroy.c @@ -0,0 +1,67 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" +#include "wa-inc/sensor.h" + +uint32 mid; +unsigned long sender; +sensor_t sensor; + +/* Sensor event callback*/ +void sensor_event_handler(sensor_t sensor, attr_container_t *event, void *user_data) { + printf("### app get sensor event\n"); + + response_t response[1]; + attr_container_t *payload; + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + + response->mid = mid; + response->reciever = sender; + set_response(response, + CONTENT_2_05, + FMT_ATTR_CONTAINER, + (const char *)payload, + attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void res1_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + + char *user_data; + attr_container_t *config; + + printf("### app on_init 1\n"); + /* open a sensor */ + user_data = malloc(100); + printf("### app on_init 2\n"); + sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data); + printf("### app on_init 3\n"); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); +} + +void on_destroy() +{ + if(NULL != sensor){ + sensor_close(sensor); + } +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/build.sh b/test-tools/component_test/suites/01-life-cycle/test-app/build.sh new file mode 100755 index 000000000..7ea7f3129 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/build.sh @@ -0,0 +1,39 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +. ../../../set_dev_env.sh + +CC=/opt/wasi-sdk/bin/clang +APP_DIR=$PWD +WAMR_DIR=${APP_DIR}/../../../../../ +SDK_DIR=${WAMR_DIR}/wamr-sdk/out/simple-host-interp +APP_FRAMEWORK_DIR=${SDK_DIR}/app-sdk/wamr-app-framework +DEPS_DIR=${WAMR_DIR}/core/deps + +for i in `ls *.c` +do +APP_SRC="$i" +OUT_FILE=${i%.*}.wasm +/opt/wasi-sdk/bin/clang -O3 \ + -Wno-int-conversion \ + -I${APP_FRAMEWORK_DIR}/include \ + -I${DEPS_DIR} \ + --target=wasm32 -O3 -z stack-size=4096 -Wl,--initial-memory=65536 \ + --sysroot=${SDK_DIR}/app-sdk/libc-builtin-sysroot \ + -L${APP_FRAMEWORK_DIR}/lib -lapp_framework \ + -Wl,--allow-undefined-file=${SDK_DIR}/app-sdk/libc-builtin-sysroot/share/defined-symbols.txt \ + -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ + -Wl,--export=on_init -Wl,--export=on_destroy \ + -Wl,--export=on_request -Wl,--export=on_response \ + -Wl,--export=on_sensor_event -Wl,--export=on_timer_callback \ + -Wl,--export=on_connection_data \ + -o ${OUT_FILE} \ + ${APP_SRC} +if [ -f ${OUT_FILE} ]; then + echo "build ${OUT_FILE} success" +else + echo "build ${OUT_FILE} fail" +fi +done \ No newline at end of file diff --git a/test-tools/component_test/suites/01-life-cycle/tools/product/start.sh b/test-tools/component_test/suites/01-life-cycle/tools/product/start.sh new file mode 100755 index 000000000..f83e39356 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/tools/product/start.sh @@ -0,0 +1,10 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/bash + +cd $(dirname "$0") + +./simple -s > /dev/null 2>&1 & diff --git a/test-tools/component_test/suites/01-life-cycle/tools/product/stop.sh b/test-tools/component_test/suites/01-life-cycle/tools/product/stop.sh new file mode 100755 index 000000000..b7bc2c8d2 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/tools/product/stop.sh @@ -0,0 +1,9 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/bash + +ps aux | grep -ie host_tool | awk '{print $2}' | xargs kill -9 & +ps aux | grep -ie simple | awk '{print $2}' | xargs kill -9 & diff --git a/test-tools/component_test/suites/__init__.py b/test-tools/component_test/suites/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test-tools/component_test/suites/readme.txt b/test-tools/component_test/suites/readme.txt new file mode 100644 index 000000000..1e8792f5b --- /dev/null +++ b/test-tools/component_test/suites/readme.txt @@ -0,0 +1,19 @@ +The description of each case in the test suites, should add descriptions in this file when new cases created in the future. + +suite 01-life-cycle: +case 01-install: + install or uninstall apps for times and query apps to see if the app list is expected. +case 02-request: + send request to an app, the app will respond specific attribute objects, host side should get them. +case 03-event: + register event to an app, the app will send event back periodically, host side should get some payload. +case 04-request_internal: + install 2 apps, host sends request to app2, then app2 sends request to app1, finally app1 respond specific payload to host, host side will check it. +case 05-event_internal: + install 2 apps, host sends request to app2, then app2 subscribe app1's event, finally app1 respond specific payload to host, host side will check it. +case 06-timer: + host send request to an app, the app then start a timer, when time goes by 2 seconds, app will respond specific payload to host, host side will check it. +case 07-sensor: + open sensor in app and then config the sensor in on_init, finally app will respond specific payload to host, host side will check it. +case 08-on_destroy: + open sensor in app in on_init, and close the sensor in on_destroy, host should install and uninstall the app successfully. diff --git a/test-tools/host-tool/CMakeLists.txt b/test-tools/host-tool/CMakeLists.txt index e45b4de50..b5755aa06 100644 --- a/test-tools/host-tool/CMakeLists.txt +++ b/test-tools/host-tool/CMakeLists.txt @@ -15,6 +15,9 @@ endif (NOT WAMR_BUILD_PLATFORM) message ("WAMR_BUILD_PLATFORM = " ${WAMR_BUILD_PLATFORM}) +add_definitions(-DWA_MALLOC=malloc) +add_definitions(-DWA_FREE=free) + set (REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) set (IWASM_DIR ${REPO_ROOT_DIR}/core/iwasm) set (APP_MGR_DIR ${REPO_ROOT_DIR}/core/app-mgr) diff --git a/test-tools/host-tool/src/host_tool_utils.c b/test-tools/host-tool/src/host_tool_utils.c index 1444715b0..183ed0d57 100644 --- a/test-tools/host-tool/src/host_tool_utils.c +++ b/test-tools/host-tool/src/host_tool_utils.c @@ -5,6 +5,7 @@ #include "host_tool_utils.h" #include "bi-inc/shared_utils.h" +#include "bh_platform.h" #include #include @@ -23,14 +24,7 @@ typedef union jvalue { double d; } jvalue; -#ifndef bh_memcpy_s -int b_memcpy_s(void * s1, unsigned int s1max, - const void * s2, unsigned int n); -#define bh_memcpy_s(dest, dlen, src, slen) do { \ - int _ret = slen == 0 ? 0 : b_memcpy_s (dest, dlen, src, slen); \ - (void)_ret; \ - } while (0) -#endif + static inline int16_t get_int16(const char *buf) { diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index b3e0d80c6..ea65406b7 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -34,6 +34,9 @@ elseif (WAMR_BUILD_TARGET STREQUAL "AMD_64") add_definitions(-DBUILD_TARGET_AMD_64) elseif (WAMR_BUILD_TARGET STREQUAL "X86_32") add_definitions(-DBUILD_TARGET_X86_32) +elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*") + add_definitions(-DBUILD_TARGET_AARCH64) + add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") elseif (WAMR_BUILD_TARGET MATCHES "ARM.*") add_definitions(-DBUILD_TARGET_ARM) add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") @@ -44,7 +47,7 @@ endif () message ("-- Build as target ${WAMR_BUILD_TARGET}") if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*") # Add -fPIC flag if build as 64-bit set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") @@ -89,6 +92,7 @@ enable_language (ASM) include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) include (${SHARED_DIR}/utils/shared_utils.cmake) +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake) include (${IWASM_DIR}/common/iwasm_common.cmake) include (${IWASM_DIR}/interpreter/iwasm_interp.cmake) @@ -114,6 +118,7 @@ add_library (vmlib ${PLATFORM_SHARED_SOURCE} ${MEM_ALLOC_SHARED_SOURCE} ${UTILS_SHARED_SOURCE} + ${UNCOMMON_SHARED_SOURCE} ${LIBC_BUILTIN_SOURCE} ${IWASM_COMMON_SOURCE} ${IWASM_INTERP_SOURCE} diff --git a/wamr-compiler/build_llvm.sh b/wamr-compiler/build_llvm.sh index dc21f79c2..f0da388a9 100755 --- a/wamr-compiler/build_llvm.sh +++ b/wamr-compiler/build_llvm.sh @@ -8,7 +8,7 @@ DEPS_DIR=${PWD}/../core/deps cd ${DEPS_DIR} if [ ! -d "llvm" ]; then echo "Clone llvm to core/deps/ .." - git clone --depth 1 https://github.com/llvm-mirror/llvm.git + git clone --depth 1 https://github.com/llvm/llvm-project.git llvm fi cd llvm @@ -24,7 +24,7 @@ if [ ! -f bin/llvm-lto ]; then echo "Build llvm with" ${CORE_NUM} "cores" - cmake .. \ + cmake ../llvm \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DCMAKE_BUILD_TYPE:STRING="Release" \ -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ diff --git a/wamr-compiler/build_llvm_xtensa.sh b/wamr-compiler/build_llvm_xtensa.sh new file mode 100755 index 000000000..d41089c68 --- /dev/null +++ b/wamr-compiler/build_llvm_xtensa.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +DEPS_DIR=${PWD}/../core/deps + +cd ${DEPS_DIR} +if [ ! -d "llvm" ]; then + echo "Clone llvm Xtensa to core/deps/ .." + git clone https://github.com/espressif/llvm-project.git llvm +fi + +cd llvm +mkdir -p build +cd build + +if [ ! -f bin/llvm-lto ]; then + + CORE_NUM=$(nproc --all) + if [ -z "${CORE_NUM}" ]; then + CORE_NUM=1 + fi + + echo "Build llvm with" ${CORE_NUM} "cores" + + cmake ../llvm \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DCMAKE_BUILD_TYPE:STRING="Release" \ + -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="Xtensa" \ + -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ + -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ + -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ + -DLLVM_INCLUDE_TESTS:BOOL=OFF \ + -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ + -DLLVM_APPEND_VC_REV:BOOL=OFF + make -j ${CORE_NUM} + +else + echo "llvm has already been built" +fi + +cd ${PWD} + diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 39f82abda..9a9d212fa 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -5,40 +5,40 @@ #include #include "bh_platform.h" -#include "bh_assert.h" -#include "bh_log.h" +#include "bh_read_file.h" #include "wasm_export.h" #include "aot_export.h" static int print_help() { - bh_printf("Usage: wamrc [options] -o output_file wasm_file\n"); - bh_printf(" --target= Set the target arch, which has the general format: \n"); - bh_printf(" = x86_64, i386, arm, thumb, mips.\n"); - bh_printf(" Default is host arch, e.g. x86_64\n"); - bh_printf(" = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc.\n"); - bh_printf(" Use --target=help to list supported targets\n"); - bh_printf(" --target-abi= Set the target ABI, e.g. gnu, eabi, gnueabihf, etc. (default: gnu)\n"); - bh_printf(" Use --target-abi=help to list all the ABI supported\n"); - bh_printf(" --cpu= Set the target CPU (default: host CPU, e.g. skylake)\n"); - bh_printf(" Use --cpu=help to list all the CPU supported\n"); - bh_printf(" --cpu-features= Enable or disable the CPU features\n"); - bh_printf(" Use +feature to enable a feature, or -feature to disable it\n"); - bh_printf(" For example, --cpu-features=+feature1,-feature2\n"); - bh_printf(" Use --cpu-features=+help to list all the features supported\n"); - bh_printf(" --opt-level=n Set the optimization level (0 to 3, default: 3, which is fastest)\n"); - bh_printf(" --size-level=n Set the code size level (0 to 3, default: 3, which is smallest)\n"); - bh_printf(" -sgx Generate code for SGX platform (Intel Software Guard Extention)\n"); - bh_printf(" --format= Specifies the format of the output file\n"); - bh_printf(" The format supported:\n"); - bh_printf(" aot (default) AoT file\n"); - bh_printf(" object Native object file\n"); - bh_printf(" llvmir-unopt Unoptimized LLVM IR\n"); - bh_printf(" llvmir-opt Optimized LLVM IR\n"); - bh_printf("Examples: wamrc -o test.aot test.wasm\n"); - bh_printf(" wamrc --target=i386 -o test.aot test.wasm\n"); - bh_printf(" wamrc --target=i386 --format=object -o test.o test.wasm\n"); + printf("Usage: wamrc [options] -o output_file wasm_file\n"); + printf(" --target= Set the target arch, which has the general format: \n"); + printf(" = x86_64, i386, aarch64, arm, thumb, xtensa, mips.\n"); + printf(" Default is host arch, e.g. x86_64\n"); + printf(" = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc.\n"); + printf(" Use --target=help to list supported targets\n"); + printf(" --target-abi= Set the target ABI, e.g. gnu, eabi, gnueabihf, etc. (default: gnu)\n"); + printf(" Use --target-abi=help to list all the ABI supported\n"); + printf(" --cpu= Set the target CPU (default: host CPU, e.g. skylake)\n"); + printf(" Use --cpu=help to list all the CPU supported\n"); + printf(" --cpu-features= Enable or disable the CPU features\n"); + printf(" Use +feature to enable a feature, or -feature to disable it\n"); + printf(" For example, --cpu-features=+feature1,-feature2\n"); + printf(" Use --cpu-features=+help to list all the features supported\n"); + printf(" --opt-level=n Set the optimization level (0 to 3, default: 3, which is fastest)\n"); + printf(" --size-level=n Set the code size level (0 to 3, default: 3, which is smallest)\n"); + printf(" -sgx Generate code for SGX platform (Intel Software Guard Extention)\n"); + printf(" --format= Specifies the format of the output file\n"); + printf(" The format supported:\n"); + printf(" aot (default) AoT file\n"); + printf(" object Native object file\n"); + printf(" llvmir-unopt Unoptimized LLVM IR\n"); + printf(" llvmir-opt Optimized LLVM IR\n"); + printf(" -v=n Set log verbose level (0 to 5, default is 2), larger with more log\n"); + 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"); return 1; } @@ -118,10 +118,15 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0] + 9, "llvmir-opt")) option.output_format = AOT_LLVMIR_OPT_FILE; else { - bh_printf("Invalid format %s.\n", argv[0] + 9); + printf("Invalid format %s.\n", argv[0] + 9); return print_help(); } } + else if (!strncmp(argv[0], "-v=", 3)) { + log_verbose_level = atoi(argv[0] + 3); + if (log_verbose_level < 0 || log_verbose_level > 5) + return print_help(); + } else return print_help(); } @@ -143,12 +148,14 @@ main(int argc, char *argv[]) /* initialize runtime environment */ if (!wasm_runtime_full_init(&init_args)) { - bh_printf("Init runtime environment failed.\n"); + printf("Init runtime environment failed.\n"); return -1; } bh_log_set_verbose_level(log_verbose_level); + 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))) @@ -157,23 +164,27 @@ main(int argc, char *argv[]) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file, wasm_file_size, error_buf, sizeof(error_buf)))) { - bh_printf("%s\n", error_buf); + printf("%s\n", error_buf); goto fail2; } if (!(comp_data = aot_create_comp_data(wasm_module))) { - bh_printf("%s\n", aot_get_last_error()); + printf("%s\n", aot_get_last_error()); goto fail3; } + bh_print_time("Begin to create compile context"); + if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) { - bh_printf("%s\n", aot_get_last_error()); + printf("%s\n", aot_get_last_error()); goto fail4; } + bh_print_time("Begin to compile"); + if (!aot_compile_wasm(comp_ctx)) { - bh_printf("%s\n", aot_get_last_error()); + printf("%s\n", aot_get_last_error()); goto fail5; } @@ -181,19 +192,19 @@ main(int argc, char *argv[]) case AOT_LLVMIR_UNOPT_FILE: case AOT_LLVMIR_OPT_FILE: if (!aot_emit_llvm_file(comp_ctx, out_file_name)) { - bh_printf("%s\n", aot_get_last_error()); + printf("%s\n", aot_get_last_error()); goto fail5; } break; case AOT_OBJECT_FILE: if (!aot_emit_object_file(comp_ctx, out_file_name)) { - bh_printf("%s\n", aot_get_last_error()); + printf("%s\n", aot_get_last_error()); goto fail5; } break; case AOT_FORMAT_FILE: if (!aot_emit_aot_file(comp_ctx, comp_data, out_file_name)) { - bh_printf("%s\n", aot_get_last_error()); + printf("%s\n", aot_get_last_error()); goto fail5; } break; @@ -201,7 +212,9 @@ main(int argc, char *argv[]) break; } - bh_printf("Compile success, file %s was generated.\n", out_file_name); + bh_print_time("Compile end"); + + printf("Compile success, file %s was generated.\n", out_file_name); fail5: /* Destroy compiler context */ @@ -222,6 +235,8 @@ fail2: fail1: /* Destroy runtime environment */ wasm_runtime_destroy(); + + bh_print_time("wamrc return"); return 0; } diff --git a/wamr-sdk/runtime/CMakeLists.txt b/wamr-sdk/runtime/CMakeLists.txt index a6d47db83..c3bd86374 100644 --- a/wamr-sdk/runtime/CMakeLists.txt +++ b/wamr-sdk/runtime/CMakeLists.txt @@ -9,8 +9,6 @@ set (CMAKE_BUILD_TYPE Release) add_definitions(-DBH_MALLOC=wasm_runtime_malloc) add_definitions(-DBH_FREE=wasm_runtime_free) -add_definitions(-DWA_MALLOC=wasm_runtime_malloc) -add_definitions(-DWA_FREE=wasm_runtime_free) if (NOT DEFINED WAMR_BUILD_SDK_PROFILE) set (WAMR_BUILD_SDK_PROFILE "default")