diff --git a/.github/workflows/build_wamr_vscode_ext.yml b/.github/workflows/build_wamr_vscode_ext.yml index 81c938e6..f62a4bc9 100644 --- a/.github/workflows/build_wamr_vscode_ext.yml +++ b/.github/workflows/build_wamr_vscode_ext.yml @@ -32,11 +32,14 @@ jobs: working-directory: test-tools/wamr-ide/VSCode-Extension - name: generate wamr ide vscode extension + env: + credentials: ${{ secrets.TOKEN }} run: | npm install -g vsce rm -rf node_modules npm install vsce package + vsce publish -p ${{ secrets.TOKEN }} working-directory: test-tools/wamr-ide/VSCode-Extension - name: compress the vscode extension diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index fd983167..bf31c499 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -61,6 +61,7 @@ env: SIMD_TEST_OPTIONS: "-s spec -b -S -P" THREADS_TEST_OPTIONS: "-s spec -b -p -P" X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P" + WASI_TEST_OPTIONS: "-s wasi_certification" jobs: build_llvm_libraries: @@ -395,7 +396,7 @@ jobs: cmake --build . --config Release --parallel 4 ./iwasm wasm-apps/no_pthread.wasm - spec_test: + test: needs: [build_iwasm, build_llvm_libraries, build_wamrc] runs-on: ubuntu-20.04 strategy: @@ -408,6 +409,7 @@ jobs: $MULTI_MODULES_TEST_OPTIONS, $SIMD_TEST_OPTIONS, $THREADS_TEST_OPTIONS, + $WASI_TEST_OPTIONS, ] exclude: # uncompatiable modes and features @@ -419,6 +421,9 @@ jobs: # aot and jit don't support multi module - running_mode: "aot" test_option: $MULTI_MODULES_TEST_OPTIONS + # aot is WAMR-specific while wasi-testsuite is generic + - running_mode: "aot" + test_option: $WASI_TEST_OPTIONS - running_mode: "jit" test_option: $MULTI_MODULES_TEST_OPTIONS # fast-jit is only tested on default mode, exclude other three @@ -438,7 +443,8 @@ jobs: - name: set env variable(if x86_32 test needed) if: > - (matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS') + (matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS' + || matrix.test_option == '$WASI_TEST_OPTIONS') && matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit' run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV @@ -460,7 +466,7 @@ jobs: if: env.USE_LLVM == 'true' && steps.cache_llvm.outputs.cache-hit != 'true' run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - - name: run spec tests default and extra + - name: run tests run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites @@ -475,7 +481,7 @@ jobs: sudo apt-get update && sudo apt install -y g++-multilib lib32gcc-9-dev - - name: run spec tests x86_32 + - name: run tests x86_32 if: env.TEST_ON_X86_32 == 'true' run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites diff --git a/.github/workflows/release_process.yml b/.github/workflows/release_process.yml index aae2f890..824a0823 100644 --- a/.github/workflows/release_process.yml +++ b/.github/workflows/release_process.yml @@ -150,6 +150,7 @@ jobs: release_wamr_ide_vscode_ext: needs: [create_tag, create_release] uses: ./.github/workflows/build_wamr_vscode_ext.yml + secrets: inherit with: upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver }} diff --git a/core/app-framework/app-native-shared/attr_container.c b/core/app-framework/app-native-shared/attr_container.c index e8c12019..e1e9f4e3 100644 --- a/core/app-framework/app-native-shared/attr_container.c +++ b/core/app-framework/app-native-shared/attr_container.c @@ -7,11 +7,14 @@ typedef union jvalue { bool z; - int8_t b; - uint16_t c; - int16_t s; - int32_t i; - int64_t j; + int8_t i8; + uint8_t u8; + int16_t i16; + uint16_t u16; + int32_t i32; + uint32_t u32; + int64_t i64; + uint64_t u64; float f; double d; } jvalue; @@ -27,7 +30,9 @@ get_int16(const char *buf) static inline uint16_t get_uint16(const char *buf) { - return get_int16(buf); + uint16_t ret; + bh_memcpy_s(&ret, sizeof(uint16_t), buf, sizeof(uint16_t)); + return ret; } static inline int32_t @@ -41,7 +46,9 @@ get_int32(const char *buf) static inline uint32_t get_uint32(const char *buf) { - return get_int32(buf); + uint32_t ret; + bh_memcpy_s(&ret, sizeof(uint32_t), buf, sizeof(uint32_t)); + return ret; } static inline int64_t @@ -55,7 +62,9 @@ get_int64(const char *buf) static inline uint64_t get_uint64(const char *buf) { - return get_int64(buf); + uint64_t ret; + bh_memcpy_s(&ret, sizeof(uint64_t), buf, sizeof(uint64_t)); + return ret; } static inline void @@ -145,8 +154,8 @@ attr_container_get_attr_next(const char *curr_attr) p += sizeof(uint16_t) + get_uint16(p); type = *p++; - /* Short type to Boolean type */ - if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN) { + /* Byte type to Boolean type */ + if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN) { p += 1 << (type & 3); return p; } @@ -342,7 +351,7 @@ attr_container_set_attr(attr_container_t **p_attr_cont, const char *key, /* key len + key + '\0' + type */ attr_len = sizeof(uint16_t) + strlen(key) + 1 + 1; - if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN) + if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN) attr_len += 1 << (type & 3); else if (type == ATTR_TYPE_STRING) attr_len += sizeof(uint16_t) + value_length; @@ -362,7 +371,7 @@ attr_container_set_attr(attr_container_t **p_attr_cont, const char *key, p += str_len; *p++ = type; - if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN) + if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN) bh_memcpy_s(p, 1 << (type & 3), value, 1 << (type & 3)); else if (type == ATTR_TYPE_STRING) { set_uint16(p, value_length); @@ -460,6 +469,14 @@ attr_container_set_short(attr_container_t **p_attr_cont, const char *key, 2); } +bool +attr_container_set_int16(attr_container_t **p_attr_cont, const char *key, + int16_t value) +{ + return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT16, &value, + 2); +} + bool attr_container_set_int(attr_container_t **p_attr_cont, const char *key, int value) @@ -467,6 +484,22 @@ attr_container_set_int(attr_container_t **p_attr_cont, const char *key, return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT, &value, 4); } +bool +attr_container_set_int32(attr_container_t **p_attr_cont, const char *key, + int32_t value) +{ + return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT32, &value, + 4); +} + +bool +attr_container_set_uint32(attr_container_t **p_attr_cont, const char *key, + uint32_t value) +{ + return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT32, &value, + 4); +} + bool attr_container_set_int64(attr_container_t **p_attr_cont, const char *key, int64_t value) @@ -475,6 +508,14 @@ attr_container_set_int64(attr_container_t **p_attr_cont, const char *key, 8); } +bool +attr_container_set_uint64(attr_container_t **p_attr_cont, const char *key, + uint64_t value) +{ + return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT64, &value, + 8); +} + bool attr_container_set_byte(attr_container_t **p_attr_cont, const char *key, int8_t value) @@ -482,6 +523,21 @@ attr_container_set_byte(attr_container_t **p_attr_cont, const char *key, return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BYTE, &value, 1); } +bool +attr_container_set_int8(attr_container_t **p_attr_cont, const char *key, + int8_t value) +{ + return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT8, &value, 1); +} + +bool +attr_container_set_uint8(attr_container_t **p_attr_cont, const char *key, + uint8_t value) +{ + return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT8, &value, + 1); +} + bool attr_container_set_uint16(attr_container_t **p_attr_cont, const char *key, uint16_t value) @@ -552,7 +608,7 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key) if (!(attr_addr = attr_container_find_attr(attr_cont, key))) { attr_container_printf("Get attribute failed: lookup key failed.\r\n"); - return false; + return NULL; } /* key len + key + '\0' */ @@ -566,14 +622,17 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key) uint8_t type; \ if (!addr) \ return 0; \ - val.j = 0; \ + val.i64 = 0; \ type = *(uint8_t *)addr++; \ switch (type) { \ - case ATTR_TYPE_SHORT: \ - case ATTR_TYPE_INT: \ + case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */ \ + case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */ \ + case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */ \ case ATTR_TYPE_INT64: \ - case ATTR_TYPE_BYTE: \ + case ATTR_TYPE_UINT8: \ case ATTR_TYPE_UINT16: \ + case ATTR_TYPE_UINT32: \ + case ATTR_TYPE_UINT64: \ case ATTR_TYPE_FLOAT: \ case ATTR_TYPE_DOUBLE: \ case ATTR_TYPE_BOOLEAN: \ @@ -608,31 +667,67 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key) short attr_container_get_as_short(const attr_container_t *attr_cont, const char *key) { - TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, s); + TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i16); +} + +int16_t +attr_container_get_as_int16(const attr_container_t *attr_cont, const char *key) +{ + return (int16_t)attr_container_get_as_short(attr_cont, key); } int attr_container_get_as_int(const attr_container_t *attr_cont, const char *key) { - TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i); + TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i32); +} + +int32_t +attr_container_get_as_int32(const attr_container_t *attr_cont, const char *key) +{ + return (int32_t)attr_container_get_as_int(attr_cont, key); +} + +uint32_t +attr_container_get_as_uint32(const attr_container_t *attr_cont, const char *key) +{ + return (uint32_t)attr_container_get_as_int(attr_cont, key); } int64_t attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key) { - TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, j); + TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i64); +} + +uint64_t +attr_container_get_as_uint64(const attr_container_t *attr_cont, const char *key) +{ + return (uint64_t)attr_container_get_as_int64(attr_cont, key); } int8_t attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key) { - TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, b); + TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i8); +} + +int8_t +attr_container_get_as_int8(const attr_container_t *attr_cont, const char *key) +{ + return attr_container_get_as_byte(attr_cont, key); +} + +uint8_t +attr_container_get_as_uint8(const attr_container_t *attr_cont, const char *key) +{ + return (uint8_t)attr_container_get_as_byte(attr_cont, key); } uint16_t attr_container_get_as_uint16(const attr_container_t *attr_cont, const char *key) { - TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, s); + return (uint16_t)attr_container_get_as_short(attr_cont, key); } float @@ -671,11 +766,14 @@ attr_container_get_as_bytearray(const attr_container_t *attr_cont, type = *(uint8_t *)addr++; switch (type) { - case ATTR_TYPE_SHORT: - case ATTR_TYPE_INT: + case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */ + case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */ + case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */ case ATTR_TYPE_INT64: - case ATTR_TYPE_BYTE: + case ATTR_TYPE_UINT8: case ATTR_TYPE_UINT16: + case ATTR_TYPE_UINT32: + case ATTR_TYPE_UINT64: case ATTR_TYPE_FLOAT: case ATTR_TYPE_DOUBLE: case ATTR_TYPE_BOOLEAN: @@ -807,34 +905,52 @@ attr_container_dump(const attr_container_t *attr_cont) attr_container_printf(" key: %s", key); switch (type) { - case ATTR_TYPE_SHORT: - bh_memcpy_s(&value.s, sizeof(int16_t), p, sizeof(int16_t)); + case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */ + bh_memcpy_s(&value.i8, 1, p, 1); + attr_container_printf(", type: byte, value: 0x%x\n", + value.i8 & 0xFF); + p++; + break; + case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */ + bh_memcpy_s(&value.i16, sizeof(int16_t), p, sizeof(int16_t)); attr_container_printf(", type: short, value: 0x%x\n", - value.s & 0xFFFF); + value.i16 & 0xFFFF); p += 2; break; - case ATTR_TYPE_INT: - bh_memcpy_s(&value.i, sizeof(int32_t), p, sizeof(int32_t)); - attr_container_printf(", type: int, value: 0x%x\n", value.i); + case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */ + bh_memcpy_s(&value.i32, sizeof(int32_t), p, sizeof(int32_t)); + attr_container_printf(", type: int, value: 0x%x\n", value.i32); p += 4; break; case ATTR_TYPE_INT64: - bh_memcpy_s(&value.j, sizeof(uint64_t), p, sizeof(uint64_t)); + bh_memcpy_s(&value.i64, sizeof(int64_t), p, sizeof(int64_t)); attr_container_printf(", type: int64, value: 0x%llx\n", - (long long unsigned int)(value.j)); + (long long unsigned int)(value.i64)); p += 8; break; - case ATTR_TYPE_BYTE: - bh_memcpy_s(&value.b, 1, p, 1); - attr_container_printf(", type: byte, value: 0x%x\n", - value.b & 0xFF); + case ATTR_TYPE_UINT8: + bh_memcpy_s(&value.u8, 1, p, 1); + attr_container_printf(", type: uint8, value: 0x%x\n", value.u8); p++; break; case ATTR_TYPE_UINT16: - bh_memcpy_s(&value.c, sizeof(uint16_t), p, sizeof(uint16_t)); - attr_container_printf(", type: uint16, value: 0x%x\n", value.c); + bh_memcpy_s(&value.u16, sizeof(uint16_t), p, sizeof(uint16_t)); + attr_container_printf(", type: uint16, value: 0x%x\n", + value.u16); p += 2; break; + case ATTR_TYPE_UINT32: + bh_memcpy_s(&value.u32, sizeof(uint32_t), p, sizeof(uint32_t)); + attr_container_printf(", type: uint32, value: 0x%x\n", + value.u32); + p += 4; + break; + case ATTR_TYPE_UINT64: + bh_memcpy_s(&value.u64, sizeof(uint64_t), p, sizeof(uint64_t)); + attr_container_printf(", type: int64, value: 0x%llx\n", + (long long unsigned int)(value.u64)); + p += 8; + break; case ATTR_TYPE_FLOAT: bh_memcpy_s(&value.f, sizeof(float), p, sizeof(float)); attr_container_printf(", type: float, value: %f\n", value.f); diff --git a/core/app-framework/app-native-shared/bi-inc/attr_container.h b/core/app-framework/app-native-shared/bi-inc/attr_container.h index 3b7be806..f5d8759b 100644 --- a/core/app-framework/app-native-shared/bi-inc/attr_container.h +++ b/core/app-framework/app-native-shared/bi-inc/attr_container.h @@ -20,13 +20,27 @@ extern "C" { /* Attribute type */ enum { - ATTR_TYPE_BEGIN = 1, - ATTR_TYPE_SHORT = ATTR_TYPE_BEGIN, + ATTR_TYPE_BEGIN = 0, + ATTR_TYPE_BYTE = ATTR_TYPE_BEGIN, + ATTR_TYPE_INT8 = ATTR_TYPE_BYTE, + ATTR_TYPE_SHORT, + ATTR_TYPE_INT16 = ATTR_TYPE_SHORT, ATTR_TYPE_INT, + ATTR_TYPE_INT32 = ATTR_TYPE_INT, ATTR_TYPE_INT64, - ATTR_TYPE_BYTE, + ATTR_TYPE_UINT8, ATTR_TYPE_UINT16, - ATTR_TYPE_FLOAT, + ATTR_TYPE_UINT32, + ATTR_TYPE_UINT64, + /** + * Why ATTR_TYPE_FLOAT = 10? + * We determine the number of bytes that should be copied through 1<<(type & + * 3). ATTR_TYPE_BYTE = 0, so the number of bytes is 1 << 0 = 1. + * ATTR_TYPE_UINT64 = 7, so the number of bytes is 1 << 3 = 8. + * Since the float type takes up 4 bytes, ATTR_TYPE_FLOAT should be 10. + * Calculation: (1 << (10&3)) = (1 << 2) = 4 + */ + ATTR_TYPE_FLOAT = 10, ATTR_TYPE_DOUBLE, ATTR_TYPE_BOOLEAN, ATTR_TYPE_STRING, @@ -89,6 +103,20 @@ bool attr_container_set_short(attr_container_t **p_attr_cont, const char *key, short value); +/** + * Set int16 attribute in attribute container + * + * @param p_attr_cont pointer to attribute container to set attribute, and + * return the new attribute container if it is re-created + * @param key the attribute key + * @param value the attribute value + * + * @return true if success, false otherwise + */ +bool +attr_container_set_int16(attr_container_t **p_attr_cont, const char *key, + int16_t value); + /** * Set int attribute in attribute container * @@ -103,6 +131,34 @@ bool attr_container_set_int(attr_container_t **p_attr_cont, const char *key, int value); +/** + * Set int32 attribute in attribute container + * + * @param p_attr_cont pointer to attribute container to set attribute, and + * return the new attribute container if it is re-created + * @param key the attribute key + * @param value the attribute value + * + * @return true if success, false otherwise + */ +bool +attr_container_set_int32(attr_container_t **p_attr_cont, const char *key, + int32_t value); + +/** + * Set uint32 attribute in attribute container + * + * @param p_attr_cont pointer to attribute container to set attribute, and + * return the new attribute container if it is re-created + * @param key the attribute key + * @param value the attribute value + * + * @return true if success, false otherwise + */ +bool +attr_container_set_uint32(attr_container_t **p_attr_cont, const char *key, + uint32_t value); + /** * Set int64 attribute in attribute container * @@ -117,6 +173,20 @@ bool attr_container_set_int64(attr_container_t **p_attr_cont, const char *key, int64_t value); +/** + * Set uint64 attribute in attribute container + * + * @param p_attr_cont pointer to attribute container to set attribute, and + * return the new attribute container if it is re-created + * @param key the attribute key + * @param value the attribute value + * + * @return true if success, false otherwise + */ +bool +attr_container_set_uint64(attr_container_t **p_attr_cont, const char *key, + uint64_t value); + /** * Set byte attribute in attribute container * @@ -131,6 +201,34 @@ bool attr_container_set_byte(attr_container_t **p_attr_cont, const char *key, int8_t value); +/** + * Set int8 attribute in attribute container + * + * @param p_attr_cont pointer to attribute container to set attribute, and + * return the new attribute container if it is re-created + * @param key the attribute key + * @param value the attribute value + * + * @return true if success, false otherwise + */ +bool +attr_container_set_int8(attr_container_t **p_attr_cont, const char *key, + int8_t value); + +/** + * Set uint8 attribute in attribute container + * + * @param p_attr_cont pointer to attribute container to set attribute, and + * return the new attribute container if it is re-created + * @param key the attribute key + * @param value the attribute value + * + * @return true if success, false otherwise + */ +bool +attr_container_set_uint8(attr_container_t **p_attr_cont, const char *key, + uint8_t value); + /** * Set uint16 attribute in attribute container * @@ -259,6 +357,18 @@ attr_container_contain_key(const attr_container_t *attr_cont, const char *key); short attr_container_get_as_short(const attr_container_t *attr_cont, const char *key); +/** + * Get attribute from attribute container and return it as int16 value, + * return 0 if attribute isn't found in message. + * + * @param attr_cont the attribute container + * @param key the attribute key + * + * @return the short value of the attribute, 0 if key isn't found + */ +int16_t +attr_container_get_as_int16(const attr_container_t *attr_cont, const char *key); + /** * Get attribute from attribute container and return it as int value, * return 0 if attribute isn't found in message. @@ -271,6 +381,31 @@ attr_container_get_as_short(const attr_container_t *attr_cont, const char *key); int attr_container_get_as_int(const attr_container_t *attr_cont, const char *key); +/** + * Get attribute from attribute container and return it as int32 value, + * return 0 if attribute isn't found in message. + * + * @param attr_cont the attribute container + * @param key the attribute key + * + * @return the int value of the attribute, 0 if key isn't found + */ +int32_t +attr_container_get_as_int32(const attr_container_t *attr_cont, const char *key); + +/** + * Get attribute from attribute container and return it as uint32 value, + * return 0 if attribute isn't found in message. + * + * @param attr_cont the attribute container + * @param key the attribute key + * + * @return the unsigned int value of the attribute, 0 if key isn't found + */ +uint32_t +attr_container_get_as_uint32(const attr_container_t *attr_cont, + const char *key); + /** * Get attribute from attribute container and return it as int64 value, * return 0 if attribute isn't found in attribute container. @@ -283,6 +418,19 @@ attr_container_get_as_int(const attr_container_t *attr_cont, const char *key); int64_t attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key); +/** + * Get attribute from attribute container and return it as uint64 value, + * return 0 if attribute isn't found in attribute container. + * + * @param attr_cont the attribute container + * @param key the attribute key + * + * @return the unsigned long value of the attribute, 0 if key isn't found + */ +uint64_t +attr_container_get_as_uint64(const attr_container_t *attr_cont, + const char *key); + /** * Get attribute from attribute container and return it as byte value, * return 0 if attribute isn't found in attribute container. @@ -295,6 +443,30 @@ attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key); int8_t attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key); +/** + * Get attribute from attribute container and return it as int8 value, + * return 0 if attribute isn't found in attribute container. + * + * @param attr_cont the attribute container + * @param key the attribute key + * + * @return the byte value of the attribute, 0 if key isn't found + */ +int8_t +attr_container_get_as_int8(const attr_container_t *attr_cont, const char *key); + +/** + * Get attribute from attribute container and return it as uint8 value, + * return 0 if attribute isn't found in attribute container. + * + * @param attr_cont the attribute container + * @param key the attribute key + * + * @return the uint8 value of the attribute, 0 if key isn't found + */ +uint8_t +attr_container_get_as_uint8(const attr_container_t *attr_cont, const char *key); + /** * Get attribute from attribute container and return it as uint16 value, * return 0 if attribute isn't found in attribute container. diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index a15593b9..5345fb2d 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -1226,7 +1226,10 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, } import_globals[i].global_data_linked = tmp_global.global_data_linked; + import_globals[i].is_linked = true; } +#else + import_globals[i].is_linked = false; #endif import_globals[i].size = wasm_value_type_size(import_globals[i].type); diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 133c5e38..5fa5438b 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -899,24 +899,6 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module, return create_export_funcs(module_inst, module, error_buf, error_buf_size); } -static bool -clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) -{ -#if WASM_ENABLE_LIBC_WASI != 0 - const char *exception = aot_get_exception(module_inst); - if (exception && !strcmp(exception, "Exception: wasi proc exit")) { - /* The "wasi proc exit" exception is thrown by native lib to - let wasm app exit, which is a normal behavior, we clear - the exception here. */ - aot_set_exception(module_inst, NULL); - return true; - } - return false; -#else - return false; -#endif -} - static bool execute_post_inst_function(AOTModuleInstance *module_inst) { @@ -956,7 +938,6 @@ execute_start_function(AOTModuleInstance *module_inst) u.f(exec_env); wasm_exec_env_destroy(exec_env); - (void)clear_wasi_proc_exit_exception(module_inst); return !aot_get_exception(module_inst); } @@ -976,6 +957,26 @@ execute_memory_init_function(AOTModuleInstance *module_inst) } #endif +static bool +check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size) +{ + uint32 i; + + /* init_func_ptrs() will go through import functions */ + + for (i = 0; i < module->import_global_count; i++) { + AOTImportGlobal *global = module->import_globals + i; + if (!global->is_linked) { + set_error_buf_v(error_buf, error_buf_size, + "failed to link import global (%s, %s)", + global->module_name, global->global_name); + return false; + } + } + + return true; +} + AOTModuleInstance * aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size) @@ -1059,6 +1060,9 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, if (!init_func_type_indexes(module_inst, module, error_buf, error_buf_size)) goto fail; + if (!check_linked_symbol(module, error_buf, error_buf_size)) + goto fail; + if (!create_exports(module_inst, module, error_buf, error_buf_size)) goto fail; @@ -1384,13 +1388,6 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, ret = invoke_native_internal(exec_env, function->u.func.func_ptr, func_type, NULL, NULL, argv1, argc, argv); - if (!ret || aot_get_exception(module_inst)) { - if (clear_wasi_proc_exit_exception(module_inst)) - ret = true; - else - ret = false; - } - #if WASM_ENABLE_DUMP_CALL_STACK != 0 if (!ret) { if (aot_create_call_stack(exec_env)) { @@ -1450,9 +1447,6 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, ret = invoke_native_internal(exec_env, function->u.func.func_ptr, func_type, NULL, NULL, argv, argc, argv); - if (clear_wasi_proc_exit_exception(module_inst)) - ret = true; - #if WASM_ENABLE_DUMP_CALL_STACK != 0 if (aot_get_exception(module_inst)) { if (aot_create_call_stack(exec_env)) { @@ -1493,7 +1487,7 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst, } } - ret = aot_call_function(exec_env, func, argc, argv); + ret = wasm_runtime_call_wasm(exec_env, func, argc, argv); /* don't destroy the exec_env if it isn't created in this function */ if (!existing_exec_env) @@ -1764,7 +1758,9 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, AOTModuleInstanceExtra *module_inst_extra = (AOTModuleInstanceExtra *)module_inst->e; CApiFuncImport *c_api_func_import = - module_inst_extra->c_api_func_imports + func_idx; + module_inst_extra->c_api_func_imports + ? module_inst_extra->c_api_func_imports + func_idx + : NULL; uint32 *func_type_indexes = module_inst->func_type_indexes; uint32 func_type_idx = func_type_indexes[func_idx]; AOTFuncType *func_type = aot_module->func_types[func_type_idx]; @@ -1780,7 +1776,8 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, import_func = aot_module->import_funcs + func_idx; if (import_func->call_conv_wasm_c_api) - func_ptr = c_api_func_import->func_ptr_linked; + func_ptr = + c_api_func_import ? c_api_func_import->func_ptr_linked : NULL; if (!func_ptr) { snprintf(buf, sizeof(buf), @@ -1980,9 +1977,6 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, } fail: - if (clear_wasi_proc_exit_exception(module_inst)) - return true; - #ifdef OS_ENABLE_HW_BOUND_CHECK wasm_runtime_access_exce_check_guard_page(); #endif diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index d8b98413..10398b26 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -4555,6 +4555,7 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt, } import->global_idx_rt = global_idx_rt; + import_aot_global->is_linked = true; return true; failed: diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index 515a60b8..7939c759 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -181,6 +181,9 @@ wasm_exec_env_destroy(WASMExecEnv *exec_env) the stopped thread will be overrided by other threads */ wasm_cluster_thread_exited(exec_env); #endif + /* We have terminated other threads, this is the only alive thread, so + * we don't acquire cluster->lock because the cluster will be destroyed + * inside this function */ wasm_cluster_del_exec_env(cluster, exec_env); } #endif /* end of WASM_ENABLE_THREAD_MGR */ diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 88dd1c19..aed92edf 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1743,6 +1743,30 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env, } #endif +static bool +clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm) +{ +#if WASM_ENABLE_LIBC_WASI != 0 + const char *exception; + WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; + + bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode + || module_inst_comm->module_type == Wasm_Module_AoT); + + exception = wasm_get_exception(module_inst); + if (exception && !strcmp(exception, "Exception: wasi proc exit")) { + /* The "wasi proc exit" exception is thrown by native lib to + let wasm app exit, which is a normal behavior, we clear + the exception here. */ + wasm_set_exception(module_inst, NULL); + return true; + } + return false; +#else + return false; +#endif +} + bool wasm_runtime_call_wasm(WASMExecEnv *exec_env, WASMFunctionInstanceCommon *function, uint32 argc, @@ -1783,10 +1807,15 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, param_argc, new_argv); #endif if (!ret) { - if (new_argv != argv) { - wasm_runtime_free(new_argv); + if (clear_wasi_proc_exit_exception(exec_env->module_inst)) { + ret = true; + } + else { + if (new_argv != argv) { + wasm_runtime_free(new_argv); + } + return false; } - return false; } #if WASM_ENABLE_REF_TYPES != 0 @@ -2150,11 +2179,25 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm) void wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) { - if (exception) + WASMExecEnv *exec_env = NULL; + + if (exception) { snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); - else + } + else { module_inst->cur_exception[0] = '\0'; + } + +#if WASM_ENABLE_THREAD_MGR != 0 + exec_env = + wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst); + if (exec_env) { + wasm_cluster_spread_exception(exec_env, exception ? false : true); + } +#else + (void)exec_env; +#endif } /* clang-format off */ @@ -4179,6 +4222,8 @@ bool wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices, uint32 argc, uint32 argv[]) { + bool ret = false; + if (!wasm_runtime_exec_env_check(exec_env)) { LOG_ERROR("Invalid exec env stack info."); return false; @@ -4190,13 +4235,18 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices, #if WASM_ENABLE_INTERP != 0 if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) - return wasm_call_indirect(exec_env, 0, element_indices, argc, argv); + ret = wasm_call_indirect(exec_env, 0, 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, 0, element_indices, argc, argv); + ret = aot_call_indirect(exec_env, 0, element_indices, argc, argv); #endif - return false; + + if (!ret && clear_wasi_proc_exit_exception(exec_env->module_inst)) { + ret = true; + } + + return ret; } static void diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index c7989851..c67251a6 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -149,6 +149,7 @@ typedef struct AOTImportGlobal { uint32 data_offset; /* global data after linked */ WASMValue global_data_linked; + bool is_linked; } AOTImportGlobal; /** diff --git a/core/iwasm/compilation/aot_emit_conversion.c b/core/iwasm/compilation/aot_emit_conversion.c index 56319380..c3dfa6bf 100644 --- a/core/iwasm/compilation/aot_emit_conversion.c +++ b/core/iwasm/compilation/aot_emit_conversion.c @@ -9,6 +9,36 @@ #include "../aot/aot_intrinsic.h" #include "../aot/aot_runtime.h" +static LLVMValueRef +call_fcmp_intrinsic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + enum AOTFloatCond cond, LLVMRealPredicate op, + LLVMValueRef lhs, LLVMValueRef rhs, LLVMTypeRef src_type, + const char *name) +{ + LLVMValueRef res = NULL; + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability( + comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) { + LLVMTypeRef param_types[3]; + LLVMValueRef opcond = LLVMConstInt(I32_TYPE, cond, true); + param_types[0] = I32_TYPE; + param_types[1] = src_type; + param_types[2] = src_type; + res = aot_call_llvm_intrinsic( + comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp", + I32_TYPE, param_types, 3, opcond, lhs, rhs); + if (!res) { + goto fail; + } + res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast"); + } + else { + res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, name); + } +fail: + return res; +} + static bool trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef operand, LLVMTypeRef src_type, @@ -18,26 +48,8 @@ trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMBasicBlockRef check_nan_succ, check_overflow_succ; LLVMValueRef is_less, is_greater, res; - if (comp_ctx->disable_llvm_intrinsics - && aot_intrinsic_check_capability( - comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) { - LLVMTypeRef param_types[3]; - LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_UNO, true); - param_types[0] = I32_TYPE; - param_types[1] = src_type; - param_types[2] = src_type; - res = aot_call_llvm_intrinsic( - comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp", - I32_TYPE, param_types, 3, opcond, operand, operand); - if (!res) { - goto fail; - } - res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast"); - } - else { - res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, operand, operand, - "fcmp_is_nan"); - } + res = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_UNO, LLVMRealUNO, + operand, operand, src_type, "fcmp_is_nan"); if (!res) { aot_set_last_error("llvm build fcmp failed."); @@ -58,54 +70,18 @@ trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, check_nan_succ))) goto fail; - if (comp_ctx->disable_llvm_intrinsics - && aot_intrinsic_check_capability( - comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) { - LLVMTypeRef param_types[3]; - LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_LE, true); - param_types[0] = I32_TYPE; - param_types[1] = src_type; - param_types[2] = src_type; - is_less = aot_call_llvm_intrinsic( - comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp", - I32_TYPE, param_types, 3, opcond, operand, min_value); - if (!is_less) { - goto fail; - } - is_less = - LLVMBuildIntCast(comp_ctx->builder, is_less, INT1_TYPE, "bit_cast"); - } - else { - is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand, - min_value, "fcmp_min_value"); - } + is_less = + call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_LE, LLVMRealOLE, operand, + min_value, src_type, "fcmp_min_value"); if (!is_less) { aot_set_last_error("llvm build fcmp failed."); goto fail; } - if (comp_ctx->disable_llvm_intrinsics - && aot_intrinsic_check_capability( - comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) { - LLVMTypeRef param_types[3]; - LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_GE, true); - param_types[0] = I32_TYPE; - param_types[1] = src_type; - param_types[2] = src_type; - is_greater = aot_call_llvm_intrinsic( - comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp", - I32_TYPE, param_types, 3, opcond, operand, max_value); - if (!is_greater) { - goto fail; - } - is_greater = LLVMBuildIntCast(comp_ctx->builder, is_greater, INT1_TYPE, - "bit_cast"); - } - else { - is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand, - max_value, "fcmp_min_value"); - } + is_greater = + call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_GE, LLVMRealOGE, operand, + max_value, src_type, "fcmp_min_value"); if (!is_greater) { aot_set_last_error("llvm build fcmp failed."); @@ -183,8 +159,9 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO; LLVMValueRef vmin, vmax; - if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, operand, operand, - "fcmp_is_nan"))) { + if (!(res = + call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_UNO, LLVMRealUNO, + operand, operand, src_type, "fcmp_is_nan"))) { aot_set_last_error("llvm build fcmp failed."); goto fail; } @@ -212,8 +189,9 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Start to translate check_nan_succ block */ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ); - if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand, - min_value, "fcmp_min_value"))) { + if (!(is_less = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_LE, + LLVMRealOLE, operand, min_value, + src_type, "fcmp_min_value"))) { aot_set_last_error("llvm build fcmp failed."); goto fail; } @@ -232,8 +210,9 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Start to translate check_less_succ block */ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ); - if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand, - max_value, "fcmp_max_value"))) { + if (!(is_greater = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_GE, + LLVMRealOGE, operand, max_value, + src_type, "fcmp_max_value"))) { aot_set_last_error("llvm build fcmp failed."); goto fail; } diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index d9cb3f5f..06d75a48 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -891,7 +891,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, if (!func_import->call_conv_wasm_c_api) { native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } - else { + else if (module_inst->e->c_api_func_imports) { c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; native_func_pointer = c_api_func_import->func_ptr_linked; } @@ -1041,7 +1041,6 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, } \ if (IS_WAMR_STOP_SIG(exec_env->current_status->signal_flag)) { \ SYNC_ALL_TO_FRAME(); \ - wasm_cluster_thread_stopped(exec_env); \ wasm_cluster_thread_waiting_run(exec_env); \ } \ } while (0) @@ -1077,7 +1076,6 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, && exec_env->current_status->step_count++ == 1) { \ exec_env->current_status->step_count = 0; \ SYNC_ALL_TO_FRAME(); \ - wasm_cluster_thread_stopped(exec_env); \ wasm_cluster_thread_waiting_run(exec_env); \ } \ goto *handle_table[*frame_ip++]; \ @@ -1094,7 +1092,6 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, && exec_env->current_status->step_count++ == 2) { \ exec_env->current_status->step_count = 0; \ SYNC_ALL_TO_FRAME(); \ - wasm_cluster_thread_stopped(exec_env); \ wasm_cluster_thread_waiting_run(exec_env); \ } \ continue @@ -4022,24 +4019,6 @@ fast_jit_call_func_bytecode(WASMModuleInstance *module_inst, #endif /* end of WASM_ENABLE_FAST_JIT != 0 */ #if WASM_ENABLE_JIT != 0 -static bool -clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) -{ -#if WASM_ENABLE_LIBC_WASI != 0 - const char *exception = wasm_get_exception(module_inst); - if (exception && !strcmp(exception, "Exception: wasi proc exit")) { - /* The "wasi proc exit" exception is thrown by native lib to - let wasm app exit, which is a normal behavior, we clear - the exception here. */ - wasm_set_exception(module_inst, NULL); - return true; - } - return false; -#else - return false; -#endif -} - static bool llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, @@ -4099,14 +4078,6 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, ret = wasm_runtime_invoke_native( exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL, argv1, argc, argv); - - if (!ret || wasm_get_exception(module_inst)) { - if (clear_wasi_proc_exit_exception(module_inst)) - ret = true; - else - ret = false; - } - if (!ret) { if (argv1 != argv1_buf) wasm_runtime_free(argv1); @@ -4151,9 +4122,6 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL, argv, argc, argv); - if (clear_wasi_proc_exit_exception(module_inst)) - ret = true; - return ret && !wasm_get_exception(module_inst) ? true : false; } } diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 4f1ae3c7..adcb18c2 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -925,7 +925,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, if (!func_import->call_conv_wasm_c_api) { native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } - else { + else if (module_inst->e->c_api_func_imports) { c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; native_func_pointer = c_api_func_import->func_ptr_linked; } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index d5cd1bf9..c33ad8d0 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1235,6 +1235,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, #if WASM_ENABLE_WAMR_COMPILER == 0 LOG_WARNING("warning: failed to link import function (%s, %s)", func->module_name, func->field_name); + /* will throw exception only if calling */ #else /* do nothing to avoid confused message */ #endif /* WASM_ENABLE_WAMR_COMPILER == 0 */ @@ -1250,8 +1251,10 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, return false; #else #if WASM_ENABLE_WAMR_COMPILER == 0 - LOG_DEBUG("warning: failed to link import global (%s, %s)", - global->module_name, global->field_name); + set_error_buf_v(error_buf, error_buf_size, + "failed to link import global (%s, %s)", + global->module_name, global->field_name); + return false; #else /* do nothing to avoid confused message */ #endif /* WASM_ENABLE_WAMR_COMPILER == 0 */ @@ -2030,24 +2033,6 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name) } #endif -static bool -clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) -{ -#if WASM_ENABLE_LIBC_WASI != 0 - const char *exception = wasm_get_exception(module_inst); - if (exception && !strcmp(exception, "Exception: wasi proc exit")) { - /* The "wasi proc exit" exception is thrown by native lib to - let wasm app exit, which is a normal behavior, we clear - the exception here. */ - wasm_set_exception(module_inst, NULL); - return true; - } - return false; -#else - return false; -#endif -} - #ifdef OS_ENABLE_HW_BOUND_CHECK static void @@ -2157,7 +2142,6 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, wasm_exec_env_set_thread_info(exec_env); interp_call_wasm(module_inst, exec_env, function, argc, argv); - (void)clear_wasi_proc_exit_exception(module_inst); return !wasm_get_exception(module_inst) ? true : false; } @@ -2185,7 +2169,7 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst, } } - ret = wasm_call_function(exec_env, func, argc, argv); + ret = wasm_runtime_call_wasm(exec_env, func, argc, argv); /* don't destroy the exec_env if it isn't created in this function */ if (!existing_exec_env) @@ -2455,7 +2439,6 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, interp_call_wasm(module_inst, exec_env, func_inst, argc, argv); - (void)clear_wasi_proc_exit_exception(module_inst); return !wasm_get_exception(module_inst) ? true : false; got_exception: @@ -2907,8 +2890,14 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, import_func = &module->import_functions[func_idx].u.function; if (import_func->call_conv_wasm_c_api) { - c_api_func_import = module_inst->e->c_api_func_imports + func_idx; - func_ptr = c_api_func_import->func_ptr_linked; + if (module_inst->e->c_api_func_imports) { + c_api_func_import = module_inst->e->c_api_func_imports + func_idx; + func_ptr = c_api_func_import->func_ptr_linked; + } + else { + c_api_func_import = NULL; + func_ptr = NULL; + } } if (!func_ptr) { diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index 9ab7848c..d4d9023e 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -494,7 +494,6 @@ pthread_start_routine(void *arg) { wasm_exec_env_t exec_env = (wasm_exec_env_t)arg; wasm_exec_env_t parent_exec_env; - wasm_module_inst_t module_inst = get_module_inst(exec_env); ThreadRoutineArgs *routine_args = exec_env->thread_arg; ThreadInfoNode *info_node = routine_args->info_node; uint32 argv[1]; @@ -519,8 +518,7 @@ pthread_start_routine(void *arg) if (!wasm_runtime_call_indirect(exec_env, routine_args->elem_index, 1, argv)) { - if (wasm_runtime_get_exception(module_inst)) - wasm_cluster_spread_exception(exec_env); + /* Exception has already been spread during throwing */ } /* destroy pthread key values */ diff --git a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c index 044e5d22..46db6d52 100644 --- a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c +++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c @@ -50,7 +50,6 @@ static void * thread_start(void *arg) { wasm_exec_env_t exec_env = (wasm_exec_env_t)arg; - wasm_module_inst_t module_inst = get_module_inst(exec_env); ThreadStartArg *thread_arg = exec_env->thread_arg; uint32 argv[2]; @@ -59,8 +58,7 @@ thread_start(void *arg) argv[1] = thread_arg->arg; if (!wasm_runtime_call_wasm(exec_env, thread_arg->start_func, 2, argv)) { - if (wasm_runtime_get_exception(module_inst)) - wasm_cluster_spread_exception(exec_env); + /* Exception has already been spread during throwing */ } // Routine exit diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index e2a0df8b..492ed66b 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -76,6 +76,7 @@ traverse_list(bh_list *l, list_visitor visitor, void *user_data) } } +/* The caller must lock cluster->lock */ static bool allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size) { @@ -99,7 +100,6 @@ allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size) if (!cluster->stack_segment_occupied) return false; - os_mutex_lock(&cluster->lock); for (i = 0; i < cluster_max_thread_num; i++) { if (!cluster->stack_segment_occupied[i]) { if (start) @@ -107,15 +107,15 @@ allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size) if (size) *size = cluster->stack_size; cluster->stack_segment_occupied[i] = true; - os_mutex_unlock(&cluster->lock); return true; } } - os_mutex_unlock(&cluster->lock); + return false; #endif } +/* The caller must lock cluster->lock */ static bool free_aux_stack(WASMExecEnv *exec_env, uint32 start) { @@ -139,9 +139,7 @@ free_aux_stack(WASMExecEnv *exec_env, uint32 start) for (i = 0; i < cluster_max_thread_num; i++) { if (start == cluster->stack_tops[i]) { - os_mutex_lock(&cluster->lock); cluster->stack_segment_occupied[i] = false; - os_mutex_unlock(&cluster->lock); return true; } } @@ -304,14 +302,14 @@ wasm_exec_env_get_cluster(WASMExecEnv *exec_env) return exec_env->cluster; } -bool +/* The caller must lock cluster->lock */ +static bool wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) { bool ret = true; exec_env->cluster = cluster; - os_mutex_lock(&cluster->lock); if (cluster->exec_env_list.len == cluster_max_thread_num + 1) { LOG_ERROR("thread manager error: " "maximum number of threads exceeded"); @@ -320,10 +318,11 @@ wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) if (ret && bh_list_insert(&cluster->exec_env_list, exec_env) != 0) ret = false; - os_mutex_unlock(&cluster->lock); + return ret; } +/* The caller should lock cluster->lock for thread safety */ bool wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) { @@ -346,10 +345,8 @@ wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) } #endif - os_mutex_lock(&cluster->lock); if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0) ret = false; - os_mutex_unlock(&cluster->lock); if (cluster->exec_env_list.len == 0) { /* exec_env_list empty, destroy the cluster */ @@ -419,6 +416,12 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) return NULL; } + os_mutex_lock(&cluster->lock); + + if (cluster->has_exception || cluster->processing) { + goto fail1; + } + #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { stack_size = @@ -435,7 +438,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) if (!(new_module_inst = wasm_runtime_instantiate_internal( module, true, stack_size, 0, NULL, 0))) { - return NULL; + goto fail1; } /* Set custom_data to new module instance */ @@ -450,32 +453,36 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) new_exec_env = wasm_exec_env_create_internal(new_module_inst, exec_env->wasm_stack_size); if (!new_exec_env) - goto fail1; + goto fail2; if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) { LOG_ERROR("thread manager error: " "failed to allocate aux stack space for new thread"); - goto fail2; + goto fail3; } /* Set aux stack for current thread */ if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start, aux_stack_size)) { - goto fail3; + goto fail4; } if (!wasm_cluster_add_exec_env(cluster, new_exec_env)) - goto fail3; + goto fail4; + + os_mutex_unlock(&cluster->lock); return new_exec_env; -fail3: +fail4: /* free the allocated aux stack space */ free_aux_stack(exec_env, aux_stack_start); -fail2: +fail3: wasm_exec_env_destroy(new_exec_env); -fail1: +fail2: wasm_runtime_deinstantiate_internal(new_module_inst, true); +fail1: + os_mutex_unlock(&cluster->lock); return NULL; } @@ -488,8 +495,10 @@ wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env) bh_assert(cluster != NULL); /* Free aux stack space */ + os_mutex_lock(&cluster->lock); free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); wasm_cluster_del_exec_env(cluster, exec_env); + os_mutex_unlock(&cluster->lock); wasm_exec_env_destroy_internal(exec_env); wasm_runtime_deinstantiate_internal(module_inst, true); @@ -517,19 +526,23 @@ thread_manager_start_routine(void *arg) #endif /* Routine exit */ - /* Free aux stack space */ - free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); - - /* routine exit, destroy instance */ - wasm_runtime_deinstantiate_internal(module_inst, true); /* Detach the native thread here to ensure the resources are freed */ wasm_cluster_detach_thread(exec_env); #if WASM_ENABLE_DEBUG_INTERP != 0 wasm_cluster_thread_exited(exec_env); #endif - /* Remove and destroy exec_env */ + + os_mutex_lock(&cluster->lock); + /* Free aux stack space */ + free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); + /* routine exit, destroy instance */ + wasm_runtime_deinstantiate_internal(module_inst, true); + /* Remove and exec_env */ wasm_cluster_del_exec_env(cluster, exec_env); + os_mutex_unlock(&cluster->lock); + + /* destroy exec_env */ wasm_exec_env_destroy_internal(exec_env); os_thread_exit(ret); @@ -543,33 +556,39 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, { WASMCluster *cluster; WASMExecEnv *new_exec_env; - uint32 aux_stack_start, aux_stack_size; + uint32 aux_stack_start = 0, aux_stack_size; korp_tid tid; cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); + os_mutex_lock(&cluster->lock); + + if (cluster->has_exception || cluster->processing) { + goto fail1; + } + new_exec_env = wasm_exec_env_create_internal(module_inst, exec_env->wasm_stack_size); if (!new_exec_env) - return -1; + goto fail1; if (alloc_aux_stack) { if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) { LOG_ERROR("thread manager error: " "failed to allocate aux stack space for new thread"); - goto fail1; + goto fail2; } /* Set aux stack for current thread */ if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start, aux_stack_size)) { - goto fail2; + goto fail3; } } if (!wasm_cluster_add_exec_env(cluster, new_exec_env)) - goto fail2; + goto fail3; new_exec_env->thread_start_routine = thread_routine; new_exec_env->thread_arg = arg; @@ -578,19 +597,24 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, != os_thread_create(&tid, thread_manager_start_routine, (void *)new_exec_env, APP_THREAD_STACK_SIZE_DEFAULT)) { - goto fail3; + goto fail4; } + os_mutex_unlock(&cluster->lock); + return 0; -fail3: +fail4: wasm_cluster_del_exec_env(cluster, new_exec_env); -fail2: +fail3: /* free the allocated aux stack space */ if (alloc_aux_stack) free_aux_stack(exec_env, aux_stack_start); -fail1: +fail2: wasm_exec_env_destroy(new_exec_env); +fail1: + os_mutex_unlock(&cluster->lock); + return -1; } @@ -665,17 +689,17 @@ notify_debug_instance_exit(WASMExecEnv *exec_env) on_thread_exit_event(cluster->debug_inst, exec_env); } -void -wasm_cluster_thread_stopped(WASMExecEnv *exec_env) -{ - exec_env->current_status->running_status = STATUS_STOP; - notify_debug_instance(exec_env); -} - void wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env) { os_mutex_lock(&exec_env->wait_lock); + + /* Wake up debugger thread after we get the lock, otherwise we may miss the + * signal from debugger thread, see + * https://github.com/bytecodealliance/wasm-micro-runtime/issues/1860 */ + exec_env->current_status->running_status = STATUS_STOP; + notify_debug_instance(exec_env); + while (!wasm_cluster_thread_is_running(exec_env)) { os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); } @@ -702,16 +726,20 @@ wasm_cluster_thread_exited(WASMExecEnv *exec_env) void wasm_cluster_thread_continue(WASMExecEnv *exec_env) { + os_mutex_lock(&exec_env->wait_lock); wasm_cluster_clear_thread_signal(exec_env); exec_env->current_status->running_status = STATUS_RUNNING; os_cond_signal(&exec_env->wait_cond); + os_mutex_unlock(&exec_env->wait_lock); } void wasm_cluster_thread_step(WASMExecEnv *exec_env) { + os_mutex_lock(&exec_env->wait_lock); exec_env->current_status->running_status = STATUS_STEP; os_cond_signal(&exec_env->wait_cond); + os_mutex_unlock(&exec_env->wait_lock); } void @@ -817,17 +845,30 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) wasm_cluster_thread_exited(exec_env); #endif /* App exit the thread, free the resources before exit native thread */ - /* Free aux stack space */ - free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); /* Detach the native thread here to ensure the resources are freed */ wasm_cluster_detach_thread(exec_env); + os_mutex_lock(&cluster->lock); + /* Free aux stack space */ + free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); /* Remove and destroy exec_env */ wasm_cluster_del_exec_env(cluster, exec_env); + os_mutex_unlock(&cluster->lock); wasm_exec_env_destroy_internal(exec_env); os_thread_exit(retval); } +static void +set_thread_cancel_flags(WASMExecEnv *exec_env) +{ + /* Set the termination flag */ +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM); +#else + exec_env->suspend_flags.flags |= 0x01; +#endif +} + int32 wasm_cluster_cancel_thread(WASMExecEnv *exec_env) { @@ -839,12 +880,8 @@ wasm_cluster_cancel_thread(WASMExecEnv *exec_env) } os_mutex_unlock(&cluster_list_lock); - /* Set the termination flag */ -#if WASM_ENABLE_DEBUG_INTERP != 0 - wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM); -#else - exec_env->suspend_flags.flags |= 0x01; -#endif + set_thread_cancel_flags(exec_env); + return 0; } @@ -864,15 +901,31 @@ terminate_thread_visitor(void *node, void *user_data) void wasm_cluster_terminate_all(WASMCluster *cluster) { + os_mutex_lock(&cluster->lock); + cluster->processing = true; + os_mutex_unlock(&cluster->lock); + traverse_list(&cluster->exec_env_list, terminate_thread_visitor, NULL); + + os_mutex_lock(&cluster->lock); + cluster->processing = false; + os_mutex_unlock(&cluster->lock); } void wasm_cluster_terminate_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { + os_mutex_lock(&cluster->lock); + cluster->processing = true; + os_mutex_unlock(&cluster->lock); + traverse_list(&cluster->exec_env_list, terminate_thread_visitor, (void *)exec_env); + + os_mutex_lock(&cluster->lock); + cluster->processing = false; + os_mutex_unlock(&cluster->lock); } static void @@ -890,15 +943,31 @@ wait_for_thread_visitor(void *node, void *user_data) void wams_cluster_wait_for_all(WASMCluster *cluster) { + os_mutex_lock(&cluster->lock); + cluster->processing = true; + os_mutex_unlock(&cluster->lock); + traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, NULL); + + os_mutex_lock(&cluster->lock); + cluster->processing = false; + os_mutex_unlock(&cluster->lock); } void wasm_cluster_wait_for_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { + os_mutex_lock(&cluster->lock); + cluster->processing = true; + os_mutex_unlock(&cluster->lock); + traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, (void *)exec_env); + + os_mutex_lock(&cluster->lock); + cluster->processing = false; + os_mutex_unlock(&cluster->lock); } bool @@ -937,15 +1006,19 @@ suspend_thread_visitor(void *node, void *user_data) void wasm_cluster_suspend_all(WASMCluster *cluster) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, suspend_thread_visitor, NULL); + os_mutex_unlock(&cluster->lock); } void wasm_cluster_suspend_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, suspend_thread_visitor, (void *)exec_env); + os_mutex_unlock(&cluster->lock); } void @@ -966,7 +1039,9 @@ resume_thread_visitor(void *node, void *user_data) void wasm_cluster_resume_all(WASMCluster *cluster) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, resume_thread_visitor, NULL); + os_mutex_unlock(&cluster->lock); } static void @@ -975,24 +1050,46 @@ set_exception_visitor(void *node, void *user_data) WASMExecEnv *curr_exec_env = (WASMExecEnv *)node; WASMExecEnv *exec_env = (WASMExecEnv *)user_data; WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env); - WASMModuleInstanceCommon *curr_module_inst = get_module_inst(curr_exec_env); - const char *exception = wasm_runtime_get_exception(module_inst); - /* skip "Exception: " */ - exception += 11; + WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst; if (curr_exec_env != exec_env) { - curr_module_inst = get_module_inst(curr_exec_env); - wasm_runtime_set_exception(curr_module_inst, exception); + WASMModuleInstance *curr_wasm_inst = + (WASMModuleInstance *)get_module_inst(curr_exec_env); + + bh_memcpy_s(curr_wasm_inst->cur_exception, + sizeof(curr_wasm_inst->cur_exception), + wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception)); + /* Terminate the thread so it can exit from dead loops */ + set_thread_cancel_flags(curr_exec_env); + } +} + +static void +clear_exception_visitor(void *node, void *user_data) +{ + WASMExecEnv *exec_env = (WASMExecEnv *)user_data; + WASMExecEnv *curr_exec_env = (WASMExecEnv *)node; + + if (curr_exec_env != exec_env) { + WASMModuleInstance *curr_wasm_inst = + (WASMModuleInstance *)get_module_inst(curr_exec_env); + + curr_wasm_inst->cur_exception[0] = '\0'; } } void -wasm_cluster_spread_exception(WASMExecEnv *exec_env) +wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear) { WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); - traverse_list(&cluster->exec_env_list, set_exception_visitor, exec_env); + os_mutex_lock(&cluster->lock); + cluster->has_exception = !clear; + traverse_list(&cluster->exec_env_list, + clear ? clear_exception_visitor : set_exception_visitor, + exec_env); + os_mutex_unlock(&cluster->lock); } static void @@ -1020,7 +1117,9 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst, cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, set_custom_data_visitor, custom_data); + os_mutex_unlock(&cluster->lock); } } diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 54e71ce7..f7b0eb52 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -36,6 +36,18 @@ struct WASMCluster { #endif /* Size of every stack segment */ uint32 stack_size; + /* When has_exception == true, this cluster should refuse any spawn thread + * requests, this flag can be cleared by calling + * wasm_runtime_clear_exception on instances of any threads of this cluster + */ + bool has_exception; + /* When processing is true, this cluster should refuse any spawn thread + * requests. This is a short-lived state, must be cleared immediately once + * the processing finished. + * This is used to avoid dead lock when one thread waiting another thread + * with lock, see wams_cluster_wait_for_all and wasm_cluster_terminate_all + */ + bool processing; #if WASM_ENABLE_DEBUG_INTERP != 0 WASMDebugInstance *debug_inst; #endif @@ -115,9 +127,6 @@ void wasm_cluster_wait_for_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env); -bool -wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env); - bool wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env); @@ -125,7 +134,7 @@ WASMExecEnv * wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst); void -wasm_cluster_spread_exception(WASMExecEnv *exec_env); +wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear); WASMExecEnv * wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env); @@ -168,9 +177,6 @@ wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status); void wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo); -void -wasm_cluster_thread_stopped(WASMExecEnv *exec_env); - void wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env); diff --git a/core/shared/platform/nuttx/nuttx_platform.c b/core/shared/platform/nuttx/nuttx_platform.c index 28188420..9cb123e0 100644 --- a/core/shared/platform/nuttx/nuttx_platform.c +++ b/core/shared/platform/nuttx/nuttx_platform.c @@ -145,9 +145,115 @@ utimensat(int fd, const char *path, const struct timespec ts[2], int flag) #endif /* !defined(AT_FDCWD) */ -DIR * -fdopendir(int fd) +#ifndef CONFIG_NET + +#include + +int +accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) { - errno = ENOSYS; - return NULL; + errno = ENOTSUP; + return -1; } + +int +bind(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen) +{ + errno = ENOTSUP; + return -1; +} + +int +listen(int sockfd, int backlog) +{ + errno = ENOTSUP; + return -1; +} + +int +connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen) +{ + errno = ENOTSUP; + return -1; +} + +ssize_t +recvfrom(int sockfd, FAR void *buf, size_t len, int flags, + FAR struct sockaddr *from, FAR socklen_t *fromlen) +{ + errno = ENOTSUP; + return -1; +} + +ssize_t +send(int sockfd, FAR const void *buf, size_t len, int flags) +{ + errno = ENOTSUP; + return -1; +} + +ssize_t +sendto(int sockfd, FAR const void *buf, size_t len, int flags, + FAR const struct sockaddr *to, socklen_t tolen) +{ + errno = ENOTSUP; + return -1; +} + +int +socket(int domain, int type, int protocol) +{ + errno = ENOTSUP; + return -1; +} + +int +shutdown(int sockfd, int how) +{ + errno = ENOTSUP; + return -1; +} + +int +getaddrinfo(FAR const char *nodename, FAR const char *servname, + FAR const struct addrinfo *hints, FAR struct addrinfo **res) +{ + errno = ENOTSUP; + return -1; +} + +void +freeaddrinfo(FAR struct addrinfo *ai) +{} + +int +setsockopt(int sockfd, int level, int option, FAR const void *value, + socklen_t value_len) +{ + errno = ENOTSUP; + return -1; +} + +int +getsockopt(int sockfd, int level, int option, FAR void *value, + FAR socklen_t *value_len) +{ + errno = ENOTSUP; + return -1; +} + +int +getpeername(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) +{ + errno = ENOTSUP; + return -1; +} + +int +getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) +{ + errno = ENOTSUP; + return -1; +} + +#endif diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 1bce192e..1332afc2 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -72,6 +72,7 @@ typedef struct os_thread_wait_node *os_thread_wait_list; typedef struct korp_cond { korp_mutex wait_list_lock; os_thread_wait_list thread_wait_list; + struct os_thread_wait_node *thread_wait_list_end; } korp_cond; #define bh_socket_t SOCKET diff --git a/core/shared/platform/windows/win_thread.c b/core/shared/platform/windows/win_thread.c index a67b15e6..09cf0c63 100644 --- a/core/shared/platform/windows/win_thread.c +++ b/core/shared/platform/windows/win_thread.c @@ -37,6 +37,8 @@ typedef struct os_thread_data { korp_mutex wait_lock; /* Waiting list of other threads who are joining this thread */ os_thread_wait_list thread_wait_list; + /* End node of the waiting list */ + os_thread_wait_node *thread_wait_list_end; /* Whether the thread has exited */ bool thread_exited; /* Thread return value */ @@ -174,7 +176,8 @@ os_thread_cleanup(void *retval) os_sem_signal(&head->sem); head = next; } - thread_data->thread_wait_list = NULL; + thread_data->thread_wait_list = thread_data->thread_wait_list_end = + NULL; } /* Set thread status and thread return value */ thread_data->thread_exited = true; @@ -313,14 +316,14 @@ os_thread_join(korp_tid thread, void **p_retval) } /* Thread is running */ - if (!thread_data->thread_wait_list) - thread_data->thread_wait_list = &curr_thread_data->wait_node; - else { + if (!thread_data->thread_wait_list) { /* Waiting list is empty */ + thread_data->thread_wait_list = thread_data->thread_wait_list_end = + &curr_thread_data->wait_node; + } + else { /* Waiting list isn't empty */ /* 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; + thread_data->thread_wait_list_end->next = &curr_thread_data->wait_node; + thread_data->thread_wait_list_end = &curr_thread_data->wait_node; } os_mutex_unlock(&thread_data->wait_lock); @@ -545,7 +548,7 @@ os_cond_init(korp_cond *cond) if (os_mutex_init(&cond->wait_list_lock) != BHT_OK) return BHT_ERROR; - cond->thread_wait_list = NULL; + cond->thread_wait_list = cond->thread_wait_list_end = NULL; return BHT_OK; } @@ -568,14 +571,13 @@ os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, bool timed, bh_assert(cond); bh_assert(mutex); os_mutex_lock(&cond->wait_list_lock); - if (!cond->thread_wait_list) - cond->thread_wait_list = node; - else { + if (!cond->thread_wait_list) { /* Waiting list is empty */ + cond->thread_wait_list = cond->thread_wait_list_end = node; + } + else { /* Waiting list isn't empty */ /* Add to end of wait list */ - os_thread_wait_node *p = cond->thread_wait_list; - while (p->next) - p = p->next; - p->next = node; + cond->thread_wait_list_end->next = node; + cond->thread_wait_list_end = node; } os_mutex_unlock(&cond->wait_list_lock); @@ -590,14 +592,24 @@ os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, bool timed, /* Remove wait node from wait list */ os_mutex_lock(&cond->wait_list_lock); - if (cond->thread_wait_list == node) + if (cond->thread_wait_list == node) { cond->thread_wait_list = node->next; + + if (cond->thread_wait_list_end == node) { + bh_assert(node->next == NULL); + cond->thread_wait_list_end = NULL; + } + } 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; + + if (cond->thread_wait_list_end == node) { + cond->thread_wait_list_end = p; + } } os_mutex_unlock(&cond->wait_list_lock); diff --git a/doc/memory_usage.md b/doc/memory_usage.md new file mode 100644 index 00000000..b72be5e0 --- /dev/null +++ b/doc/memory_usage.md @@ -0,0 +1,135 @@ +Memory usage estimation for a module +==================================== + +This document aims to provide information useful to make a rough estimation +of necessary memory to execute a WASM module. + +Instead of trying to cover every possible configurations, +the following configuration is assumed in this document: + +* Module is built with `wasi-sdk` +* Module is loaded with `wasm_runtime_load` +* AOT is used +* WASI is used +* libc heap is used +* app heap is not used +* The pthread implementation in `wasi-libc`, which is based on `wasi-threads` + (`WASM_ENABLE_LIB_WASI_THREADS`, which is not available on `main` branch + yet) might be used +* The another pthread implementation (`WASM_ENABLE_LIB_PTHREAD`) is not used + +Module +------ + +The memory to store the module binary is allocated by the embedder and +passed to `wasm_runtime_load`. +While WAMR owns the buffer, WAMR might make in-place modifications to +its contents. + +Loaded module and its instances +------------------------------- + +Many of data structures for module and instances are allocated from +the global heap. (aka. `wasm_runtime_malloc`) + +AOT code section +---------------- + +Memory to load AOT machine code section. + +Because this memory needs to be executable, depending on platforms, +it's allocated from a separate allocator. +For example, `mmap` and `mprotect` are used on POSIX-like platforms. + +Linear memory +------------- + +A WASM linear memory is either shared or non-shared. + +A WASM linear memory has `min` and `max` sizes. +(They correspond to `wasm-ld`'s `--init-memory` and `--max-memory` options.) +They are in the number of WASM pages, each of which is of 65536 bytes. +The `max` is optional for non-shared memory. When omitted, it effectivily +means unlimited. + +If `OS_ENABLE_HW_BOUND_CHECK` is enabled, the memory is allocated via +`os_mmap` and `os_mem_commit`/`os_mprotect`. +Otherwise, it's allocated from the global heap. + +If the memory is shared and `OS_ENABLE_HW_BOUND_CHECK` is not enabled, +the `max` size of memory is allocated on instantiation. + +Otherwise, the `min` size of memory is allocated on instantiation. +It can later grow up to the `max` size via the `memory.grow` instruction. + +Libc heap +--------- + +The libc heap is the last (highest address) part of linear memory, +which might be dynamically grown with `memory.grow` instruction, when +necessary to serve memory allocations within the module. + +App heap +-------- + +Not used for the above mentioned configuration. + +You can safely disable the app heap creation by specifying `0` for +the `heap_size` argument of `wasm_runtime_instantiate`. +(It's automatically disabled if malloc/free are exported from the module.) + +WASM stack +---------- + +Operand stack is not used for AOT. + +However, a small amount of WASM stack is used for call frames when +certain features are enabled. +(`WASM_ENABLE_DUMP_CALL_STACK` or `WASM_ENABLE_PERF_PROFILING`) + +It's allocated from the global heap. + +You can specify its size with the `stack_size` argument of +`wasm_runtime_instantiate` and `wasm_runtime_create_exec_env`. +(1 is the minimum because 0 means the default.) + +AUX stack (aka. C shadow stack) +------------------------------- + +For the main thread, it's a part of the linear memory, +between `__data_end` and `__heap_base` symbols. +You can control the size of this stack with `wasm-ld`'s +`-z stack-size` option. + +For threads created by `pthread_create`, libc allocates the stack for +them dynamically from the libc heap. +The size of this stack is inherited from the main thread's one +unless overwritten with `pthread_attr_setstacksize` etc. + +WAMR tries to detect overflow/underflow when updating the stack pointer +global. For threads created by `pthread_create`, the detection mechanism +is disabled as of writing this. + +Native stack +------------ + +The stack of the host environment thread which runs WAMR. + +For threads created by `pthread_create`, WAMR automatically creates +host threads to run those WASM threads. The stack size of these host +threads are controlled by a build-time configuration. +(`APP_THREAD_STACK_SIZE_DEFAULT`) + +In some configurations, runtime overflow can be detected using hardware traps. +(`OS_ENABLE_HW_BOUND_CHECK`) + +In some configurations, explicit overflow detection logic can be emitted +into AOT modules themselves. (cf. `os_thread_get_stack_boundary`, +`check_stack_boundary`, `wamrc --stack-bounds-checks=1/0`) + +Memory profiling +================ + +You can collect and dump detailed information about memory usage +by actually running a module with the `WASM_ENABLE_MEMORY_PROFILING` +build-time option. diff --git a/language-bindings/go/build.sh b/language-bindings/go/build.sh index 1540c664..fe46a9a8 100755 --- a/language-bindings/go/build.sh +++ b/language-bindings/go/build.sh @@ -7,6 +7,12 @@ PLATFORM=$(uname -s | tr A-Z a-z) CUR_DIR=$PWD WAMR_DIR=$PWD/../.. WAMR_GO_DIR=$PWD/wamr +ARCH=$(uname -m) +if [ ${ARCH} = "arm64" ]; then + ARCH="aarch64" +elif [ ${ARCH} = "x86_64" ]; then + ARCH="amd64" +fi cp -a ${WAMR_DIR}/core/iwasm/include/*.h ${WAMR_GO_DIR}/packaged/include @@ -15,7 +21,7 @@ cmake ${WAMR_DIR}/product-mini/platforms/${PLATFORM} \ -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \ -DWAMR_BUILD_MEMORY_PROFILING=1 make -j ${nproc} -cp -a libvmlib.a ${WAMR_GO_DIR}/packaged/lib/${PLATFORM}-amd64 +cp -a libvmlib.a ${WAMR_GO_DIR}/packaged/lib/${PLATFORM}-${ARCH} cd ${WAMR_GO_DIR} go test diff --git a/language-bindings/go/go.sum b/language-bindings/go/go.sum index b380ae44..acb88a48 100644 --- a/language-bindings/go/go.sum +++ b/language-bindings/go/go.sum @@ -5,6 +5,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/language-bindings/go/wamr/packaged/lib/darwin-aarch64/dummy.go b/language-bindings/go/wamr/packaged/lib/darwin-aarch64/dummy.go new file mode 100644 index 00000000..35f3c705 --- /dev/null +++ b/language-bindings/go/wamr/packaged/lib/darwin-aarch64/dummy.go @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package darwin_aarch64 diff --git a/samples/gui/wasm-apps/increase/Makefile b/samples/gui/wasm-apps/increase/Makefile index 2c150332..5f250d6e 100644 --- a/samples/gui/wasm-apps/increase/Makefile +++ b/samples/gui/wasm-apps/increase/Makefile @@ -25,9 +25,9 @@ SRCS += $(APP_FRAMEWORK_DIR)/wgl/app/src/*.c all: @$(CC) $(CFLAGS) $(SRCS) \ - --target=wasm32 -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ - -Wl,--allow-undefined \ - -Wl,--strip-all,--no-entry -nostdlib \ + --target=wasm32-wasi -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ + -nostdlib -Wl,--allow-undefined \ + -Wl,--strip-all,--no-entry \ -Wl,--export=on_init -Wl,--export=on_timer_callback \ -Wl,--export=on_widget_event \ -Wl,--export=__heap_base,--export=__data_end \ diff --git a/samples/multi-thread/wasm-apps/CMakeLists.txt b/samples/multi-thread/wasm-apps/CMakeLists.txt index 44ced1cc..ec8f7eef 100644 --- a/samples/multi-thread/wasm-apps/CMakeLists.txt +++ b/samples/multi-thread/wasm-apps/CMakeLists.txt @@ -38,3 +38,6 @@ set (CMAKE_EXE_LINKER_FLAGS add_executable(test.wasm main.c) target_link_libraries(test.wasm) + +add_executable(main_thread_exception.wasm main_thread_exception.c) +target_link_libraries(main_thread_exception.wasm) diff --git a/samples/multi-thread/wasm-apps/main_thread_exception.c b/samples/multi-thread/wasm-apps/main_thread_exception.c new file mode 100644 index 00000000..80f170d4 --- /dev/null +++ b/samples/multi-thread/wasm-apps/main_thread_exception.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include + +typedef struct ThreadArgs { + int start; + int length; +} ThreadArgs; + +void * +thread(void *args) +{ + while (1) { + /* When other threads (including main thread) throw exception, + this thread can successfully exit the dead loop */ + } +} + +int +main() +{ + pthread_t tids; + + if (pthread_create(&tids, NULL, thread, NULL) != 0) { + printf("pthread_create failed\n"); + } + + /* Trigger an exception */ + __builtin_trap(); + + return 0; +} diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/devices/templates/help.html b/test-tools/IoT-APP-Store-Demo/wasm_django/devices/templates/help.html index 9e9d63c9..4ad7427b 100755 --- a/test-tools/IoT-APP-Store-Demo/wasm_django/devices/templates/help.html +++ b/test-tools/IoT-APP-Store-Demo/wasm_django/devices/templates/help.html @@ -33,7 +33,7 @@

1. Download a simple runtime (build for ubuntu 20.04 64 bits, other platforms please build - from the source code) + from the source code)

2. In the terminal: cd ~/Download && ./simple -a 82.156.57.236 @@ -44,7 +44,7 @@

Notes:
We also have a UI-enabled runtime, please download here and enjoy. It may require + href="../static/upload/wasm_runtime_wgl">download here and enjoy. It may require a few more setups.

Before running the UI-enabled runtime, please install some required softwares:

sudo apt-get install libsdl2-2.0-0:i386

diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/server/wasm_server.py b/test-tools/IoT-APP-Store-Demo/wasm_django/server/wasm_server.py index 5edeb90a..970ec6f6 100755 --- a/test-tools/IoT-APP-Store-Demo/wasm_django/server/wasm_server.py +++ b/test-tools/IoT-APP-Store-Demo/wasm_django/server/wasm_server.py @@ -16,14 +16,18 @@ import logging import os attr_type_list = [ - "ATTR_NONE", - "ATTR_TYPE_SHORT", - "ATTR_TYPE_INT", + "ATTR_TYPE_BYTE", # = ATTR_TYPE_INT8 + "ATTR_TYPE_SHORT",# = ATTR_TYPE_INT16 + "ATTR_TYPE_INT", # = ATTR_TYPE_INT32 "ATTR_TYPE_INT64", - "ATTR_TYPE_BYTE", + "ATTR_TYPE_UINT8", "ATTR_TYPE_UINT16", + "ATTR_TYPE_UINT32", + "ATTR_TYPE_UINT64", "ATTR_TYPE_FLOAT", "ATTR_TYPE_DOUBLE", + "ATTR_NONE", + "ATTR_NONE", "ATTR_TYPE_BOOLEAN", "ATTR_TYPE_STRING", "ATTR_TYPE_BYTEARRAY" @@ -140,26 +144,38 @@ def decode_attr_container(msg): attr_type = attr_type_list[int(type_index[0])] buf = buf[1 : ] - if attr_type == "ATTR_TYPE_SHORT": + if attr_type == "ATTR_TYPE_BYTE": # = ATTR_TYPE_INT8 + (attr_value, ) = struct.unpack('@c', buf[0 : 1]) + buf = buf[1 : ] + # continue + elif attr_type == "ATTR_TYPE_SHORT": # = ATTR_TYPE_INT16 (attr_value, ) = struct.unpack('@h', buf[0 : 2]) buf = buf[2 : ] # continue - elif attr_type == "ATTR_TYPE_INT": - (attr_value, ) = struct.unpack('@I', buf[0 : 4]) + elif attr_type == "ATTR_TYPE_INT": # = ATTR_TYPE_INT32 + (attr_value, ) = struct.unpack('@i', buf[0 : 4]) buf = buf[4 : ] # continue elif attr_type == "ATTR_TYPE_INT64": (attr_value, ) = struct.unpack('@q', buf[0 : 8]) buf = buf[8 : ] # continue - elif attr_type == "ATTR_TYPE_BYTE": - (attr_value, ) = struct.unpack('@c', buf[0 : 1]) + elif attr_type == "ATTR_TYPE_UINT8": + (attr_value, ) = struct.unpack('@B', buf[0 : 1]) buf = buf[1 : ] # continue elif attr_type == "ATTR_TYPE_UINT16": (attr_value, ) = struct.unpack('@H', buf[0 : 2]) buf = buf[2 : ] # continue + elif attr_type == "ATTR_TYPE_UINT32": + (attr_value, ) = struct.unpack('@I', buf[0 : 4]) + buf = buf[4 : ] + # continue + elif attr_type == "ATTR_TYPE_UINT64": + (attr_value, ) = struct.unpack('@Q', buf[0 : 8]) + buf = buf[8 : ] + # continue elif attr_type == "ATTR_TYPE_FLOAT": (attr_value, ) = struct.unpack('@f', buf[0 : 4]) buf = buf[4 : ] diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/connection.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/connection.wasm index 2a2e79dc..936e80cf 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/connection.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/connection.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/event_publisher.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/event_publisher.wasm index 4cf91109..31dc1018 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/event_publisher.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/event_publisher.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/event_subscriber.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/event_subscriber.wasm index 1766c256..1dce622f 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/event_subscriber.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/event_subscriber.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/request_handler.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/request_handler.wasm index 1da74dbe..85959790 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/request_handler.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/request_handler.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/request_sender.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/request_sender.wasm index f7c9b994..ce9a6f6e 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/request_sender.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/request_sender.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sensor.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sensor.wasm index eb51ec8e..f24bd100 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sensor.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sensor.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/simple b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/simple index da9c485e..478a0f85 100755 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/simple and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/simple differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/connection.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/connection.wasm index 2a2e79dc..936e80cf 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/connection.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/connection.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/event_publisher.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/event_publisher.wasm index 4cf91109..31dc1018 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/event_publisher.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/event_publisher.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/event_subscriber.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/event_subscriber.wasm index 1766c256..1dce622f 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/event_subscriber.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/event_subscriber.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/request_handler.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/request_handler.wasm index 1da74dbe..85959790 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/request_handler.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/request_handler.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/request_sender.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/request_sender.wasm index f7c9b994..ce9a6f6e 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/request_sender.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/request_sender.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/timer.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/timer.wasm index bcd4c8fa..0bb3c920 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/timer.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/sys/timer.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/timer.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/timer.wasm index bcd4c8fa..0bb3c920 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/timer.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/timer.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/ui_app.wasm b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/ui_app.wasm index ddda9e2d..1182ca29 100644 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/ui_app.wasm and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/ui_app.wasm differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/vgl_wasm_runtime b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/vgl_wasm_runtime deleted file mode 100755 index fa68f3a2..00000000 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/vgl_wasm_runtime and /dev/null differ diff --git a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/wasm_runtime_wgl b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/wasm_runtime_wgl index eb7b42b8..30f8e92e 100755 Binary files a/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/wasm_runtime_wgl and b/test-tools/IoT-APP-Store-Demo/wasm_django/static/upload/wasm_runtime_wgl differ diff --git a/test-tools/host-tool/src/host_tool_utils.c b/test-tools/host-tool/src/host_tool_utils.c index 2b9051bb..9ea3d6ca 100644 --- a/test-tools/host-tool/src/host_tool_utils.c +++ b/test-tools/host-tool/src/host_tool_utils.c @@ -15,11 +15,14 @@ typedef union jvalue { bool z; - int8_t b; - uint16_t c; - int16_t s; - int32_t i; - int64_t j; + int8_t i8; + uint8_t u8; + int16_t i16; + uint16_t u16; + int32_t i32; + uint32_t u32; + int64_t i64; + uint64_t u64; float f; double d; } jvalue; @@ -90,43 +93,64 @@ attr2json(const attr_container_t *attr_cont) type = *p++; switch (type) { - case ATTR_TYPE_SHORT: - bh_memcpy_s(&value.s, sizeof(int16_t), p, sizeof(int16_t)); - if (NULL == (obj = cJSON_CreateNumber(value.s))) + case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */ + bh_memcpy_s(&value.i8, 1, p, 1); + if (NULL == (obj = cJSON_CreateNumber(value.i8))) + goto fail; + cJSON_AddItemToObject(root, key, obj); + p++; + break; + case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */ + bh_memcpy_s(&value.i16, sizeof(int16_t), p, sizeof(int16_t)); + if (NULL == (obj = cJSON_CreateNumber(value.i16))) goto fail; cJSON_AddItemToObject(root, key, obj); /* another approach: cJSON_AddNumberToObject(root, key, value.s) */ p += 2; break; - case ATTR_TYPE_INT: - bh_memcpy_s(&value.i, sizeof(int32_t), p, sizeof(int32_t)); - if (NULL == (obj = cJSON_CreateNumber(value.i))) + case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */ + bh_memcpy_s(&value.i32, sizeof(int32_t), p, sizeof(int32_t)); + if (NULL == (obj = cJSON_CreateNumber(value.i32))) goto fail; cJSON_AddItemToObject(root, key, obj); p += 4; break; case ATTR_TYPE_INT64: - bh_memcpy_s(&value.j, sizeof(uint64_t), p, sizeof(uint64_t)); - if (NULL == (obj = cJSON_CreateNumber(value.j))) + bh_memcpy_s(&value.i64, sizeof(int64_t), p, sizeof(int64_t)); + if (NULL == (obj = cJSON_CreateNumber(value.i64))) goto fail; cJSON_AddItemToObject(root, key, obj); p += 8; break; - case ATTR_TYPE_BYTE: - bh_memcpy_s(&value.b, 1, p, 1); - if (NULL == (obj = cJSON_CreateNumber(value.b))) + case ATTR_TYPE_UINT8: + bh_memcpy_s(&value.u8, 1, p, 1); + if (NULL == (obj = cJSON_CreateNumber(value.u8))) goto fail; cJSON_AddItemToObject(root, key, obj); p++; break; case ATTR_TYPE_UINT16: - bh_memcpy_s(&value.c, sizeof(uint16_t), p, sizeof(uint16_t)); - if (NULL == (obj = cJSON_CreateNumber(value.c))) + bh_memcpy_s(&value.u16, sizeof(uint16_t), p, sizeof(uint16_t)); + if (NULL == (obj = cJSON_CreateNumber(value.u16))) goto fail; cJSON_AddItemToObject(root, key, obj); p += 2; break; + case ATTR_TYPE_UINT32: + bh_memcpy_s(&value.u32, sizeof(uint32_t), p, sizeof(uint32_t)); + if (NULL == (obj = cJSON_CreateNumber(value.u32))) + goto fail; + cJSON_AddItemToObject(root, key, obj); + p += 4; + break; + case ATTR_TYPE_UINT64: + bh_memcpy_s(&value.u64, sizeof(uint64_t), p, sizeof(uint64_t)); + if (NULL == (obj = cJSON_CreateNumber(value.u64))) + goto fail; + cJSON_AddItemToObject(root, key, obj); + p += 8; + break; case ATTR_TYPE_FLOAT: bh_memcpy_s(&value.f, sizeof(float), p, sizeof(float)); if (NULL == (obj = cJSON_CreateNumber(value.f))) diff --git a/test-tools/wamr-ide/VSCode-Extension/package.json b/test-tools/wamr-ide/VSCode-Extension/package.json index fa3292c2..9b67e3a1 100644 --- a/test-tools/wamr-ide/VSCode-Extension/package.json +++ b/test-tools/wamr-ide/VSCode-Extension/package.json @@ -1,6 +1,6 @@ { "name": "wamride", - "publisher": "wamr", + "publisher": "wamr-publisher", "repository": { "url": "https://github.com/bytecodealliance/wasm-micro-runtime/tree/main/test-tools/wamr-ide" }, diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index dca7f87c..00797b31 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -46,6 +46,7 @@ PLATFORM=$(uname -s | tr A-Z a-z) PARALLELISM=0 ENABLE_QEMU=0 QEMU_FIRMWARE="" +WASI_TESTSUITE_COMMIT="1d913f28b3f0d92086d6f50405cf85768e648b54" while getopts ":s:cabt:m:MCpSXxPQF:" opt do @@ -447,7 +448,10 @@ function spec_test() cd ${WORK_DIR} echo "python3 ./all.py ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt" python3 ./all.py ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt - [[ ${PIPESTATUS[0]} -ne 0 ]] && exit 1 + if [[ ${PIPESTATUS[0]} -ne 0 ]];then + echo -e "\nspec tests FAILED" | tee -a ${REPORT_DIR}/spec_test_report.txt + exit 1 + fi cd - echo -e "\nFinish spec tests" | tee -a ${REPORT_DIR}/spec_test_report.txt @@ -469,6 +473,38 @@ function wasi_test() echo "Finish wasi tests" } +function wasi_certification_test() +{ + echo "Now start wasi tests" + + cd ${WORK_DIR} + if [ ! -d "wasi-testsuite" ]; then + echo "wasi not exist, clone it from github" + git clone -b prod/testsuite-base \ + --single-branch https://github.com/WebAssembly/wasi-testsuite.git + fi + cd wasi-testsuite + git reset --hard ${WASI_TESTSUITE_COMMIT} + + python3 -m venv wasi-env && source wasi-env/bin/activate + python3 -m pip install -r test-runner/requirements.txt + IWASM_PATH=$(dirname ${IWASM_CMD}) + PATH=${PATH}:${IWASM_PATH} python3 test-runner/wasi_test_runner.py \ + -r adapters/wasm-micro-runtime.sh \ + -t \ + tests/c/testsuite/ \ + tests/assemblyscript/testsuite/ \ + | tee -a ${REPORT_DIR}/wasi_test_report.txt + exit_code=${PIPESTATUS[0]} + deactivate + + if [[ ${exit_code} -ne 0 ]];then + echo -e "\nwasi tests FAILED" | tee -a ${REPORT_DIR}/wasi_test_report.txt + exit 1 + fi + echo -e "\nFinish wasi tests" | tee -a ${REPORT_DIR}/wasi_test_report.txt +} + function polybench_test() { echo "Now start polybench tests" diff --git a/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h b/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h index 8c55bff5..802e9ac5 100644 --- a/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h +++ b/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h @@ -11,6 +11,13 @@ extern "C" { #endif /* clang-format off */ +/* The word size of platform */ +#ifdef __wasm64__ +#define __WORDSIZE 64 +#else +#define __WORDSIZE 32 +#endif + typedef char int8_t; typedef short int int16_t; typedef int int32_t; @@ -25,22 +32,56 @@ typedef unsigned long long int uint64_t; typedef __INTPTR_TYPE__ intptr_t; typedef __UINTPTR_TYPE__ uintptr_t; +/* Signed and unsigned */ +#if __WORDSIZE == 64 +#define INT64_C(c) c ## L +#define UINT64_C(c) c ## UL +#define INTMAX_C(c) c ## L +#define UINTMAX_C(c) c ## UL +#else +#define INT64_C(c) c ## LL +#define UINT64_C(c) c ## ULL +#define INTMAX_C(c) c ## LL +#define UINTMAX_C(c) c ## ULL +#endif + + /* Minimum of signed integral types. */ # define INT8_MIN (-128) # define INT16_MIN (-32767-1) # define INT32_MIN (-2147483647-1) -# define INT64_MIN (-__INT64_C(9223372036854775807)-1) +# define INT64_MIN (-INT64_C(9223372036854775807)-1) + /* Maximum of signed integral types. */ # define INT8_MAX (127) # define INT16_MAX (32767) # define INT32_MAX (2147483647) -# define INT64_MAX (__INT64_C(9223372036854775807)) +# define INT64_MAX (INT64_C(9223372036854775807)) /* Maximum of unsigned integral types. */ # define UINT8_MAX (255) # define UINT16_MAX (65535) # define UINT32_MAX (4294967295U) -# define UINT64_MAX (__UINT64_C(18446744073709551615)) +# define UINT64_MAX (UINT64_C(18446744073709551615)) + +/* Values to test for integral types holding `void *' pointer. */ +#if __WORDSIZE == 64 +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#else +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* Limit of `size_t' type. */ +#if __WORDSIZE == 64 +#define SIZE_MAX UINT64_MAX +#else +#define SIZE_MAX UINT32_MAX +#endif + /* clang-format on */ #ifdef __cplusplus