Просмотр исходного кода

Merge branch main into dev/wasi-libc-windows

Wenyong Huang 2 лет назад
Родитель
Сommit
e222955f31
100 измененных файлов с 3802 добавлено и 1346 удалено
  1. 1 1
      .github/workflows/coding_guidelines.yml
  2. 46 12
      .github/workflows/compilation_on_android_ubuntu.yml
  3. 3 5
      .github/workflows/compilation_on_macos.yml
  4. 0 3
      .github/workflows/compilation_on_sgx.yml
  5. 44 12
      .github/workflows/nightly_run.yml
  6. 11 0
      build-scripts/config_common.cmake
  7. 2 0
      build-scripts/runtime_lib.cmake
  8. 5 0
      core/config.h
  9. 110 2
      core/iwasm/aot/aot_loader.c
  10. 91 9
      core/iwasm/aot/aot_runtime.c
  11. 14 0
      core/iwasm/aot/aot_runtime.h
  12. 5 0
      core/iwasm/aot/arch/aot_reloc_aarch64.c
  13. 2 0
      core/iwasm/aot/arch/aot_reloc_arm.c
  14. 29 10
      core/iwasm/common/wasm_application.c
  15. 92 0
      core/iwasm/common/wasm_blocking_op.c
  16. 94 17
      core/iwasm/common/wasm_memory.c
  17. 4 0
      core/iwasm/common/wasm_memory.h
  18. 172 0
      core/iwasm/common/wasm_native.c
  19. 30 0
      core/iwasm/common/wasm_native.h
  20. 446 96
      core/iwasm/common/wasm_runtime_common.c
  21. 65 0
      core/iwasm/common/wasm_runtime_common.h
  22. 2 0
      core/iwasm/common/wasm_suspend_flags.h
  23. 13 0
      core/iwasm/compilation/aot_compiler.h
  24. 2 0
      core/iwasm/compilation/aot_emit_aot_file.c
  25. 23 10
      core/iwasm/compilation/aot_emit_control.c
  26. 3 10
      core/iwasm/compilation/aot_emit_memory.c
  27. 17 11
      core/iwasm/compilation/aot_emit_numberic.c
  28. 9 1
      core/iwasm/compilation/aot_llvm.c
  29. 4 1
      core/iwasm/compilation/aot_llvm.h
  30. 26 1
      core/iwasm/compilation/aot_llvm_extra.cpp
  31. 9 0
      core/iwasm/compilation/aot_llvm_extra2.cpp
  32. 9 0
      core/iwasm/compilation/aot_orc_extra.cpp
  33. 197 38
      core/iwasm/compilation/simd/simd_floating_point.c
  34. 8 0
      core/iwasm/fast-jit/fe/jit_emit_numberic.c
  35. 152 1
      core/iwasm/include/wasm_export.h
  36. 2 3
      core/iwasm/interpreter/wasm_interp_classic.c
  37. 0 3
      core/iwasm/interpreter/wasm_interp_fast.c
  38. 35 208
      core/iwasm/interpreter/wasm_loader.c
  39. 19 24
      core/iwasm/interpreter/wasm_mini_loader.c
  40. 19 80
      core/iwasm/interpreter/wasm_runtime.c
  41. 20 7
      core/iwasm/interpreter/wasm_runtime.h
  42. 1 8
      core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c
  43. 1 1
      core/iwasm/libraries/lib-rats/lib_rats.cmake
  44. 1 8
      core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
  45. 66 0
      core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh
  46. 34 0
      core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c
  47. 3 0
      core/iwasm/libraries/lib-wasi-threads/stress-test/manifest.json
  48. 229 0
      core/iwasm/libraries/lib-wasi-threads/stress-test/mutex_common.h
  49. 27 0
      core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c
  50. 72 0
      core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c
  51. 31 23
      core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c
  52. 26 18
      core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c
  53. 4 1
      core/iwasm/libraries/lib-wasi-threads/test/build.sh
  54. 1 1
      core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c
  55. 1 1
      core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c
  56. 1 1
      core/iwasm/libraries/lib-wasi-threads/test/global_lock.c
  57. 0 6
      core/iwasm/libraries/lib-wasi-threads/test/skip.json
  58. 1 1
      core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c
  59. 0 3
      core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json
  60. 1 1
      core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c
  61. 10 0
      core/iwasm/libraries/lib-wasi-threads/tid_allocator.h
  62. 6 0
      core/iwasm/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake
  63. 62 0
      core/iwasm/libraries/lib-wasi-threads/unit-test/test_tid_allocator.cpp
  64. 117 99
      core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c
  65. 91 235
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h
  66. 226 0
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c
  67. 57 0
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h
  68. 327 283
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c
  69. 17 7
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h
  70. 113 60
      core/iwasm/libraries/thread-mgr/thread_manager.c
  71. 5 1
      core/iwasm/libraries/thread-mgr/thread_manager.h
  72. 1 0
      core/iwasm/libraries/wasi-nn/src/wasi_nn.c
  73. 4 0
      core/shared/platform/alios/alios_platform.c
  74. 4 0
      core/shared/platform/alios/alios_thread.c
  75. 0 4
      core/shared/platform/android/platform_internal.h
  76. 69 0
      core/shared/platform/common/posix/posix_blocking_op.c
  77. 16 0
      core/shared/platform/common/posix/posix_memmap.c
  78. 20 0
      core/shared/platform/common/posix/posix_sleep.c
  79. 10 10
      core/shared/platform/common/posix/posix_socket.c
  80. 19 5
      core/shared/platform/common/posix/posix_thread.c
  81. 43 0
      core/shared/platform/cosmopolitan/platform_init.c
  82. 122 0
      core/shared/platform/cosmopolitan/platform_internal.h
  83. 19 0
      core/shared/platform/cosmopolitan/shared_platform.cmake
  84. 6 0
      core/shared/platform/darwin/platform_internal.h
  85. 4 0
      core/shared/platform/esp-idf/espidf_memmap.c
  86. 4 0
      core/shared/platform/esp-idf/espidf_platform.c
  87. 1 1
      core/shared/platform/esp-idf/espidf_socket.c
  88. 6 0
      core/shared/platform/freebsd/platform_internal.h
  89. 29 1
      core/shared/platform/include/platform_api_extension.h
  90. 13 0
      core/shared/platform/include/platform_api_vmcore.h
  91. 4 0
      core/shared/platform/linux-sgx/sgx_platform.c
  92. 2 2
      core/shared/platform/linux-sgx/sgx_socket.c
  93. 4 0
      core/shared/platform/linux-sgx/sgx_thread.c
  94. 6 0
      core/shared/platform/linux/platform_internal.h
  95. 4 0
      core/shared/platform/nuttx/nuttx_platform.c
  96. 6 0
      core/shared/platform/nuttx/platform_internal.h
  97. 4 0
      core/shared/platform/riot/riot_platform.c
  98. 4 0
      core/shared/platform/riot/riot_thread.c
  99. 8 0
      core/shared/platform/rt-thread/rtt_platform.c
  100. 4 0
      core/shared/platform/windows/platform_init.c

+ 1 - 1
.github/workflows/coding_guidelines.yml

@@ -16,7 +16,7 @@ concurrency:
 
 jobs:
   compliance_job:
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-20.04
     steps:
       - name: checkout
         uses: actions/checkout@v3

+ 46 - 12
.github/workflows/compilation_on_android_ubuntu.yml

@@ -65,6 +65,7 @@ env:
   THREADS_TEST_OPTIONS: "-s spec -b -p -P"
   X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P"
   WASI_TEST_OPTIONS: "-s wasi_certification -w"
+  WAMR_COMPILER_TEST_OPTIONS: "-s wamr_compiler -b -P"
 
 jobs:
   build_llvm_libraries_on_ubuntu_2204:
@@ -72,7 +73,7 @@ jobs:
     with:
       os: "ubuntu-22.04"
       arch: "X86"
-  
+
   build_wamrc:
     needs:
       [build_llvm_libraries_on_ubuntu_2204]
@@ -150,9 +151,7 @@ jobs:
         exclude:
           # uncompatiable feature and platform
           # uncompatiable mode and feature
-          # MULTI_MODULE only on INTERP mode
-          - make_options_run_mode: $AOT_BUILD_OPTIONS
-            make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
+          # MULTI_MODULE only on INTERP mode and AOT mode
           - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
@@ -241,6 +240,14 @@ jobs:
           cmake --build . --config Release --parallel 4
         working-directory: product-mini/platforms/${{ matrix.platform }}
 
+      - name: Build and run unit tests
+        run: |
+          mkdir build-unittests && cd build-unittests
+          cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }}
+          cmake --build . --config Release --parallel 4
+          ctest
+        working-directory: tests/unit
+
   build_samples_wasm_c_api:
     needs:
       [
@@ -320,7 +327,12 @@ jobs:
         working-directory: samples/wasm-c-api
 
   build_samples_others:
-    needs: [build_iwasm]
+    needs:
+      [
+        build_iwasm,
+        build_llvm_libraries_on_ubuntu_2204,
+        build_wamrc,
+      ]
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
@@ -333,6 +345,9 @@ jobs:
           [
             "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz",
           ]
+        include:
+          - os: ubuntu-22.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
     steps:
       - name: checkout
         uses: actions/checkout@v3
@@ -350,7 +365,23 @@ jobs:
           sudo wget ${{ matrix.wabt_release }}
           sudo tar -xzf wabt-1.0.31-*.tar.gz
           sudo mv wabt-1.0.31 wabt
-
+      - name: Get LLVM libraries
+        id: retrieve_llvm_libs
+        uses: actions/cache@v3
+        with:
+          path: |
+            ./core/deps/llvm/build/bin
+            ./core/deps/llvm/build/include
+            ./core/deps/llvm/build/lib
+            ./core/deps/llvm/build/libexec
+            ./core/deps/llvm/build/share
+          key: ${{ matrix.llvm_cache_key }}
+      - name: Build wamrc
+        run: |
+          mkdir build && cd build
+          cmake ..
+          cmake --build . --config Release --parallel 4
+        working-directory: wamr-compiler
       - name: Build Sample [basic]
         run: |
           cd samples/basic
@@ -377,9 +408,10 @@ jobs:
         run: |
           cd samples/multi-module
           mkdir build && cd build
-          cmake ..
+          cmake .. -DWAMR_BUILD_AOT=1
           cmake --build . --config Release --parallel 4
-          ./multi_module
+          ./multi_module mC.wasm
+          ./multi_module mC.aot
 
       - name: Build Sample [spawn-thread]
         run: |
@@ -449,6 +481,10 @@ jobs:
           - os: ubuntu-22.04
             llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
             ubuntu_version: "22.04"
+          - os: ubuntu-22.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
+            running_mode: aot
+            test_option: $WAMR_COMPILER_TEST_OPTIONS
         exclude:
           # uncompatiable modes and features
           # classic-interp and fast-interp don't support simd
@@ -456,9 +492,7 @@ jobs:
             test_option: $SIMD_TEST_OPTIONS
           - running_mode: "fast-interp"
             test_option: $SIMD_TEST_OPTIONS
-          # aot and jit don't support multi module
-          - running_mode: "aot"
-            test_option: $MULTI_MODULES_TEST_OPTIONS
+          # llvm jit doesn't support multi module
           - running_mode: "jit"
             test_option: $MULTI_MODULES_TEST_OPTIONS
           # fast-jit doesn't support multi module, simd
@@ -483,7 +517,7 @@ jobs:
           sudo tar -xzf wasi-sdk-*.tar.gz
           sudo mv wasi-sdk-20.0 wasi-sdk
 
-      # It is a temporary solution until new wasi-sdk that includes bug fixes is released 
+      # It is a temporary solution until new wasi-sdk that includes bug fixes is released
       - name: build wasi-libc from source
         if: matrix.test_option == '$WASI_TEST_OPTIONS'
         run: |

+ 3 - 5
.github/workflows/compilation_on_macos.yml

@@ -133,13 +133,11 @@ jobs:
         exclude:
           # uncompatiable feature and platform
           # uncompatiable mode and feature
-          # MULTI_MODULE only on INTERP mode
+          # MULTI_MODULE only on INTERP mode and AOT mode
           - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
-          - make_options_run_mode: $AOT_BUILD_OPTIONS
-            make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           # SIMD only on JIT/AOT mode
           - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_SIMD=1"
@@ -245,7 +243,7 @@ jobs:
         working-directory: samples/wasm-c-api
 
   build_samples_others:
-    needs: [build_iwasm]
+    needs: [build_iwasm, build_wamrc]
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
@@ -304,7 +302,7 @@ jobs:
           mkdir build && cd build
           cmake ..
           cmake --build . --config Release --parallel 4
-          ./multi_module
+          ./multi_module mC.wasm
 
       - name: Build Sample [spawn-thread]
         run: |

+ 0 - 3
.github/workflows/compilation_on_sgx.yml

@@ -101,9 +101,6 @@ jobs:
         platform: [linux-sgx]
         exclude:
           # uncompatiable mode and feature
-          # MULTI_MODULE only on INTERP mode
-          - make_options_run_mode: $AOT_BUILD_OPTIONS
-            make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           # MINI_LOADER only on INTERP mode
           - make_options_run_mode: $AOT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"

+ 44 - 12
.github/workflows/nightly_run.yml

@@ -8,9 +8,11 @@ on:
     types:
       - opened
       - synchronize
-    #running nightly pipeline if you're changing it 
+    # running nightly pipeline if you're changing it 
+    # stress tests are run only in nightly at the moment, so running them in they are changed
     paths:
       - ".github/workflows/nightly_run.yml"
+      - "core/iwasm/libraries/lib-wasi-threads/stress-test/**"
       
   # midnight UTC
   schedule:
@@ -125,9 +127,7 @@ jobs:
         exclude:
           # uncompatiable feature and platform
           # uncompatiable mode and feature
-          # MULTI_MODULE only on INTERP mode
-          - make_options_run_mode: $AOT_BUILD_OPTIONS
-            make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
+          # MULTI_MODULE only on INTERP mode and AOT mode
           - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
@@ -250,7 +250,7 @@ jobs:
         exclude:
           # uncompatiable feature and platform
           # uncompatiable mode and feature
-          # MULTI_MODULE only on INTERP mode
+          # MULTI_MODULE only on INTERP mode and AOT mode
           - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           # SIMD only on JIT/AOT mode
@@ -380,7 +380,12 @@ jobs:
         working-directory: samples/wasm-c-api
 
   build_samples_others:
-    needs: [build_iwasm]
+    needs:
+      [
+        build_iwasm,
+        build_llvm_libraries_on_ubuntu_2004,
+        build_wamrc,
+      ]
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
@@ -393,6 +398,9 @@ jobs:
           [
             "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz",
           ]
+        include:
+          - os: ubuntu-20.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}
     steps:
       - name: checkout
         uses: actions/checkout@v3
@@ -409,6 +417,26 @@ jobs:
           sudo wget ${{ matrix.wabt_release }}
           sudo tar -xzf wabt-1.0.31-*.tar.gz
           sudo mv wabt-1.0.31 wabt
+
+      - name: Get LLVM libraries
+        id: retrieve_llvm_libs
+        uses: actions/cache@v3
+        with:
+          path: |
+            ./core/deps/llvm/build/bin
+            ./core/deps/llvm/build/include
+            ./core/deps/llvm/build/lib
+            ./core/deps/llvm/build/libexec
+            ./core/deps/llvm/build/share
+          key: ${{ matrix.llvm_cache_key }}
+
+      - name: Build wamrc
+        run: |
+          mkdir build && cd build
+          cmake -D WAMR_BUILD_SANITIZER="${{matrix.sanitizer}}" ..
+          cmake --build . --config Release --parallel 4
+        working-directory: wamr-compiler
+
       - name: Build Sample [basic]
         run: |
           cd samples/basic
@@ -432,9 +460,10 @@ jobs:
         run: |
           cd samples/multi-module
           mkdir build && cd build
-          cmake ..
+          cmake .. -DWAMR_BUILD_AOT=1
           cmake --build . --config Release --parallel 4
-          ./multi_module
+          ./multi_module mC.wasm
+          ./multi_module mC.aot
       - name: Build Sample [spawn-thread]
         run: |
           cd samples/spawn-thread
@@ -522,9 +551,7 @@ jobs:
             test_option: $SIMD_TEST_OPTIONS
           - running_mode: "fast-interp"
             test_option: $SIMD_TEST_OPTIONS
-          # aot and jit don't support multi module
-          - running_mode: "aot"
-            test_option: $MULTI_MODULES_TEST_OPTIONS
+          # llvm jit doesn't support multi module
           - running_mode: "jit"
             test_option: $MULTI_MODULES_TEST_OPTIONS
           # fast-jit doesn't support multi module, simd
@@ -599,6 +626,11 @@ jobs:
         run: bash build.sh --sysroot "$SYSROOT_PATH"
         working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/
 
+      - name: Build WASI thread stress tests
+        if: matrix.test_option == '$WASI_TEST_OPTIONS'
+        run: bash build.sh --sysroot "$SYSROOT_PATH"
+        working-directory: ./core/iwasm/libraries/lib-wasi-threads/stress-test/
+
       - name: build socket api tests
         if: matrix.test_option == '$WASI_TEST_OPTIONS'
         run: bash build.sh
@@ -624,4 +656,4 @@ jobs:
         timeout-minutes: 40
         if: env.TEST_ON_X86_32 == 'true'
         run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
-        working-directory: ./tests/wamr-test-suites
+        working-directory: ./tests/wamr-test-suites

+ 11 - 0
build-scripts/config_common.cmake

@@ -273,6 +273,13 @@ else ()
     add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=0)
   endif ()
 endif ()
+if (WAMR_DISABLE_WAKEUP_BLOCKING_OP EQUAL 1)
+  add_definitions (-DWASM_DISABLE_WAKEUP_BLOCKING_OP=1)
+  message ("     Wakeup of blocking operations disabled")
+else ()
+  add_definitions (-DWASM_DISABLE_WAKEUP_BLOCKING_OP=0)
+  message ("     Wakeup of blocking operations enabled")
+endif ()
 if (WAMR_BUILD_SIMD EQUAL 1)
   if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*")
     add_definitions (-DWASM_ENABLE_SIMD=1)
@@ -378,6 +385,10 @@ if (WAMR_BUILD_WASM_CACHE EQUAL 1)
   add_definitions (-DWASM_ENABLE_WASM_CACHE=1)
   message ("     Wasm files cache enabled")
 endif ()
+if (WAMR_BUILD_MODULE_INST_CONTEXT EQUAL 1)
+  add_definitions (-DWASM_ENABLE_MODULE_INST_CONTEXT=1)
+  message ("     Module instance context enabled")
+endif ()
 if (WAMR_BUILD_GC_HEAP_VERIFY EQUAL 1)
   add_definitions (-DWASM_ENABLE_GC_VERIFY=1)
   message ("     GC heap verification enabled")

+ 2 - 0
build-scripts/runtime_lib.cmake

@@ -91,8 +91,10 @@ endif ()
 
 if (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
     include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake)
+    set (WAMR_BUILD_MODULE_INST_CONTEXT 1)
 elseif (WAMR_BUILD_LIBC_WASI EQUAL 1)
     include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake)
+    set (WAMR_BUILD_MODULE_INST_CONTEXT 1)
 endif ()
 
 if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)

+ 5 - 0
core/config.h

@@ -480,4 +480,9 @@
 #define WASM_MEM_DUAL_BUS_MIRROR 0
 #endif
 
+/* The max number of module instance contexts. */
+#ifndef WASM_MAX_INSTANCE_CONTEXTS
+#define WASM_MAX_INSTANCE_CONTEXTS 8
+#endif
+
 #endif /* end of _CONFIG_H_ */

+ 110 - 2
core/iwasm/aot/aot_loader.c

@@ -558,6 +558,56 @@ str2uint32(const char *buf, uint32 *p_res);
 static bool
 str2uint64(const char *buf, uint64 *p_res);
 
+#if WASM_ENABLE_MULTI_MODULE != 0
+static void *
+aot_loader_resolve_function(const char *module_name, const char *function_name,
+                            const AOTFuncType *expected_function_type,
+                            char *error_buf, uint32 error_buf_size)
+{
+    WASMModuleCommon *module_reg;
+    void *function = NULL;
+    AOTExport *export = NULL;
+    AOTModule *module = NULL;
+    AOTFuncType *target_function_type = NULL;
+
+    module_reg = wasm_runtime_find_module_registered(module_name);
+    if (!module_reg || module_reg->module_type != Wasm_Module_AoT) {
+        LOG_DEBUG("can not find a module named %s for function %s", module_name,
+                  function_name);
+        set_error_buf(error_buf, error_buf_size, "unknown import");
+        return NULL;
+    }
+
+    module = (AOTModule *)module_reg;
+    export = loader_find_export(module_reg, module_name, function_name,
+                                EXPORT_KIND_FUNC, error_buf, error_buf_size);
+    if (!export) {
+        return NULL;
+    }
+
+    /* resolve function type and function */
+    if (export->index < module->import_func_count) {
+        target_function_type = module->import_funcs[export->index].func_type;
+        function = module->import_funcs[export->index].func_ptr_linked;
+    }
+    else {
+        target_function_type =
+            module->func_types[module->func_type_indexes
+                                   [export->index - module->import_func_count]];
+        function =
+            (module->func_ptrs[export->index - module->import_func_count]);
+    }
+    /* check function type */
+    if (!wasm_type_equal(expected_function_type, target_function_type)) {
+        LOG_DEBUG("%s.%s failed the type check", module_name, function_name);
+        set_error_buf(error_buf, error_buf_size, "incompatible import type");
+        return NULL;
+    }
+    return function;
+}
+
+#endif /* end of WASM_ENABLE_MULTI_MODULE */
+
 static bool
 load_native_symbol_section(const uint8 *buf, const uint8 *buf_end,
                            AOTModule *module, bool is_load_from_file_buf,
@@ -1357,11 +1407,16 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
                   bool is_load_from_file_buf, char *error_buf,
                   uint32 error_buf_size)
 {
-    const char *module_name, *field_name;
+    char *module_name, *field_name;
     const uint8 *buf = *p_buf;
     AOTImportFunc *import_funcs;
     uint64 size;
     uint32 i;
+#if WASM_ENABLE_MULTI_MODULE != 0
+    AOTModule *sub_module = NULL;
+    AOTFunc *linked_func = NULL;
+    WASMType *declare_func_type = NULL;
+#endif
 
     /* Allocate memory */
     size = sizeof(AOTImportFunc) * (uint64)module->import_func_count;
@@ -1377,17 +1432,46 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
             set_error_buf(error_buf, error_buf_size, "unknown type");
             return false;
         }
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+        declare_func_type = module->func_types[import_funcs[i].func_type_index];
+        read_string(buf, buf_end, module_name);
+        read_string(buf, buf_end, field_name);
+
+        import_funcs[i].module_name = module_name;
+        import_funcs[i].func_name = field_name;
+        linked_func = wasm_native_resolve_symbol(
+            module_name, field_name, declare_func_type,
+            &import_funcs[i].signature, &import_funcs[i].attachment,
+            &import_funcs[i].call_conv_raw);
+        if (!linked_func) {
+            if (!wasm_runtime_is_built_in_module(module_name)) {
+                sub_module = (AOTModule *)wasm_runtime_load_depended_module(
+                    (WASMModuleCommon *)module, module_name, error_buf,
+                    error_buf_size);
+                if (!sub_module) {
+                    return false;
+                }
+            }
+            linked_func = aot_loader_resolve_function(
+                module_name, field_name, declare_func_type, error_buf,
+                error_buf_size);
+        }
+        import_funcs[i].func_ptr_linked = linked_func;
+        import_funcs[i].func_type = declare_func_type;
+
+#else
         import_funcs[i].func_type =
             module->func_types[import_funcs[i].func_type_index];
         read_string(buf, buf_end, import_funcs[i].module_name);
         read_string(buf, buf_end, import_funcs[i].func_name);
-
         module_name = import_funcs[i].module_name;
         field_name = import_funcs[i].func_name;
         import_funcs[i].func_ptr_linked = wasm_native_resolve_symbol(
             module_name, field_name, import_funcs[i].func_type,
             &import_funcs[i].signature, &import_funcs[i].attachment,
             &import_funcs[i].call_conv_raw);
+#endif
 
 #if WASM_ENABLE_LIBC_WASI != 0
         if (!strcmp(import_funcs[i].module_name, "wasi_unstable")
@@ -2871,6 +2955,7 @@ create_module(char *error_buf, uint32 error_buf_size)
 {
     AOTModule *module =
         loader_malloc(sizeof(AOTModule), error_buf, error_buf_size);
+    bh_list_status ret;
 
     if (!module) {
         return NULL;
@@ -2878,6 +2963,13 @@ create_module(char *error_buf, uint32 error_buf_size)
 
     module->module_type = Wasm_Module_AoT;
 
+#if WASM_ENABLE_MULTI_MODULE != 0
+    module->import_module_list = &module->import_module_list_head;
+    ret = bh_list_init(module->import_module_list);
+    bh_assert(ret == BH_LIST_SUCCESS);
+#endif
+    (void)ret;
+
     return module;
 }
 
@@ -3143,10 +3235,13 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf,
     if (!module)
         return NULL;
 
+    os_thread_jit_write_protect_np(false); /* Make memory writable */
     if (!load(buf, size, module, error_buf, error_buf_size)) {
         aot_unload(module);
         return NULL;
     }
+    os_thread_jit_write_protect_np(true); /* Make memory executable */
+    os_icache_flush(module->code, module->code_size);
 
     LOG_VERBOSE("Load module success.\n");
     return module;
@@ -3201,6 +3296,19 @@ aot_unload(AOTModule *module)
 
     if (module->const_str_set)
         bh_hash_map_destroy(module->const_str_set);
+#if WASM_ENABLE_MULTI_MODULE != 0
+    /* just release the sub module list */
+    if (module->import_module_list) {
+        WASMRegisteredModule *node =
+            bh_list_first_elem(module->import_module_list);
+        while (node) {
+            WASMRegisteredModule *next = bh_list_elem_next(node);
+            bh_list_remove(module->import_module_list, node);
+            wasm_runtime_free(node);
+            node = next;
+        }
+    }
+#endif
 
     if (module->code && !module->is_indirect_mode) {
         /* The layout is: literal size + literal + code (with plt table) */

+ 91 - 9
core/iwasm/aot/aot_runtime.c

@@ -1091,6 +1091,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     uint8 *p;
     uint32 i, extra_info_offset;
     const bool is_sub_inst = parent != NULL;
+#if WASM_ENABLE_MULTI_MODULE != 0
+    bool ret = false;
+#endif
 
     /* Check heap size */
     heap_size = align_uint(heap_size, 8);
@@ -1134,6 +1137,18 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     module_inst->e =
         (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset);
 
+#if WASM_ENABLE_MULTI_MODULE != 0
+    ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list =
+        &((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list_head;
+    ret = wasm_runtime_sub_module_instantiate(
+        (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst,
+        stack_size, heap_size, error_buf, error_buf_size);
+    if (!ret) {
+        LOG_DEBUG("build a sub module list failed");
+        goto fail;
+    }
+#endif
+
     /* Initialize global info */
     p = (uint8 *)module_inst + module_inst_struct_size
         + module_inst_mem_inst_size;
@@ -1256,6 +1271,11 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
     }
 #endif
 
+#if WASM_ENABLE_MULTI_MODULE != 0
+    wasm_runtime_sub_module_deinstantiate(
+        (WASMModuleInstanceCommon *)module_inst);
+#endif
+
     if (module_inst->tables)
         wasm_runtime_free(module_inst->tables);
 
@@ -1276,12 +1296,10 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
                               ->common.c_api_func_imports);
 
     if (!is_sub_inst) {
-#if WASM_ENABLE_LIBC_WASI != 0
-        wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
-#endif
 #if WASM_ENABLE_WASI_NN != 0
         wasi_nn_destroy(module_inst);
 #endif
+        wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
     }
 
     wasm_runtime_free(module_inst);
@@ -1413,10 +1431,43 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
                   unsigned argc, uint32 argv[])
 {
     AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
-    AOTFuncType *func_type = function->u.func.func_type;
+    AOTFuncType *func_type = function->is_import_func
+                                 ? function->u.func_import->func_type
+                                 : function->u.func.func_type;
     uint32 result_count = func_type->result_count;
     uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
     bool ret;
+    void *func_ptr = function->is_import_func
+                         ? function->u.func_import->func_ptr_linked
+                         : function->u.func.func_ptr;
+#if WASM_ENABLE_MULTI_MODULE != 0
+    bh_list *sub_module_list_node = NULL;
+    const char *sub_inst_name = NULL;
+    const char *func_name = function->u.func_import->module_name;
+    if (function->is_import_func) {
+        sub_module_list_node =
+            ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list;
+        sub_module_list_node = bh_list_first_elem(sub_module_list_node);
+        while (sub_module_list_node) {
+            sub_inst_name =
+                ((AOTSubModInstNode *)sub_module_list_node)->module_name;
+            if (strcmp(sub_inst_name, func_name) == 0) {
+                exec_env = wasm_runtime_get_exec_env_singleton(
+                    (WASMModuleInstanceCommon *)((AOTSubModInstNode *)
+                                                     sub_module_list_node)
+                        ->module_inst);
+                module_inst = (AOTModuleInstance *)exec_env->module_inst;
+                break;
+            }
+            sub_module_list_node = bh_list_elem_next(sub_module_list_node);
+        }
+        if (exec_env == NULL) {
+            wasm_runtime_set_exception((WASMModuleInstanceCommon *)module_inst,
+                                       "create singleton exec_env failed");
+            return false;
+        }
+    }
+#endif
 
     if (argc < func_type->param_cell_num) {
         char buf[108];
@@ -1438,11 +1489,13 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
 #endif
 
     /* func pointer was looked up previously */
-    bh_assert(function->u.func.func_ptr != NULL);
-
+    bh_assert(func_ptr != NULL);
     /* set thread handle and stack boundary */
     wasm_exec_env_set_thread_info(exec_env);
 
+    /* set exec env so it can be later retrieved from instance */
+    ((AOTModuleInstanceExtra *)module_inst->e)->common.cur_exec_env = exec_env;
+
     if (ext_ret_count > 0) {
         uint32 cell_num = 0, i;
         uint8 *ext_ret_types = func_type->types + func_type->param_count + 1;
@@ -1545,8 +1598,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
         }
 #endif
 
-        ret = invoke_native_internal(exec_env, function->u.func.func_ptr,
-                                     func_type, NULL, NULL, argv, argc, argv);
+        ret = invoke_native_internal(exec_env, func_ptr, func_type, NULL, NULL,
+                                     argv, argc, argv);
 
 #if WASM_ENABLE_DUMP_CALL_STACK != 0
         if (aot_copy_exception(module_inst, NULL)) {
@@ -1938,7 +1991,10 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
     void *attachment;
     char buf[96];
     bool ret = false;
-
+#if WASM_ENABLE_MULTI_MODULE != 0
+    bh_list *sub_module_list_node = NULL;
+    const char *sub_inst_name = NULL;
+#endif
     bh_assert(func_idx < aot_module->import_func_count);
 
     import_func = aot_module->import_funcs + func_idx;
@@ -1962,6 +2018,28 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
     }
     else if (!import_func->call_conv_raw) {
         signature = import_func->signature;
+#if WASM_ENABLE_MULTI_MODULE != 0
+        sub_module_list_node =
+            ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list;
+        sub_module_list_node = bh_list_first_elem(sub_module_list_node);
+        while (sub_module_list_node) {
+            sub_inst_name =
+                ((AOTSubModInstNode *)sub_module_list_node)->module_name;
+            if (strcmp(sub_inst_name, import_func->module_name) == 0) {
+                exec_env = wasm_runtime_get_exec_env_singleton(
+                    (WASMModuleInstanceCommon *)((AOTSubModInstNode *)
+                                                     sub_module_list_node)
+                        ->module_inst);
+                break;
+            }
+            sub_module_list_node = bh_list_elem_next(sub_module_list_node);
+        }
+        if (exec_env == NULL) {
+            wasm_runtime_set_exception((WASMModuleInstanceCommon *)module_inst,
+                                       "create singleton exec_env failed");
+            goto fail;
+        }
+#endif
         ret =
             wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature,
                                        attachment, argv, argc, argv);
@@ -2729,6 +2807,7 @@ aot_create_call_stack(struct WASMExecEnv *exec_env)
         total_len +=                                                      \
             wasm_runtime_dump_line_buf_impl(line_buf, print, &buf, &len); \
         if ((!print) && buf && (len == 0)) {                              \
+            exception_unlock(module_inst);                                \
             return total_len;                                             \
         }                                                                 \
     } while (0)
@@ -2751,6 +2830,7 @@ aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len)
         return 0;
     }
 
+    exception_lock(module_inst);
     snprintf(line_buf, sizeof(line_buf), "\n");
     PRINT_OR_DUMP();
 
@@ -2759,6 +2839,7 @@ aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len)
         uint32 line_length, i;
 
         if (!bh_vector_get(module_inst->frames, n, &frame)) {
+            exception_unlock(module_inst);
             return 0;
         }
 
@@ -2789,6 +2870,7 @@ aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len)
     }
     snprintf(line_buf, sizeof(line_buf), "\n");
     PRINT_OR_DUMP();
+    exception_unlock(module_inst);
 
     return total_len + 1;
 }

+ 14 - 0
core/iwasm/aot/aot_runtime.h

@@ -90,6 +90,10 @@ typedef struct AOTFunctionInstance {
 typedef struct AOTModuleInstanceExtra {
     DefPointer(const uint32 *, stack_sizes);
     WASMModuleInstanceExtraCommon common;
+#if WASM_ENABLE_MULTI_MODULE != 0
+    bh_list sub_module_inst_list_head;
+    bh_list *sub_module_inst_list;
+#endif
 } AOTModuleInstanceExtra;
 
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
@@ -229,6 +233,12 @@ typedef struct AOTModule {
     WASIArguments wasi_args;
     bool import_wasi_api;
 #endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+    /* TODO: add mutex for mutli-thread? */
+    bh_list import_module_list_head;
+    bh_list *import_module_list;
+#endif
 #if WASM_ENABLE_DEBUG_AOT != 0
     void *elf_hdr;
     uint32 elf_size;
@@ -247,6 +257,10 @@ typedef struct AOTModule {
 #define AOTTableInstance WASMTableInstance
 #define AOTModuleInstance WASMModuleInstance
 
+#if WASM_ENABLE_MULTI_MODULE != 0
+#define AOTSubModInstNode WASMSubModInstNode
+#endif
+
 /* Target info, read from ELF header of object file */
 typedef struct AOTTargetInfo {
     /* Binary type, elf32l/elf32b/elf64l/elf64b */

+ 5 - 0
core/iwasm/aot/arch/aot_reloc_aarch64.c

@@ -53,7 +53,12 @@ get_target_symbol_map(uint32 *sym_num)
     return target_sym_map;
 }
 
+#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__)
+#define BUILD_TARGET_AARCH64_DEFAULT "arm64"
+#else
 #define BUILD_TARGET_AARCH64_DEFAULT "aarch64v8"
+#endif
+
 void
 get_current_target(char *target_buf, uint32 target_buf_size)
 {

+ 2 - 0
core/iwasm/aot/arch/aot_reloc_arm.c

@@ -40,6 +40,7 @@ void __aeabi_ldivmod();
 void __aeabi_memcpy();
 void __aeabi_memmove();
 void __aeabi_memset();
+void __aeabi_memclr();
 void __aeabi_uidiv();
 void __aeabi_uidivmod();
 void __aeabi_ul2d();
@@ -126,6 +127,7 @@ static SymbolMap target_sym_map[] = {
     REG_SYM(__aeabi_memcpy),
     REG_SYM(__aeabi_memmove),
     REG_SYM(__aeabi_memset),
+    REG_SYM(__aeabi_memclr),
     REG_SYM(__aeabi_uidiv),
     REG_SYM(__aeabi_uidivmod),
     REG_SYM(__aeabi_ul2d),

+ 29 - 10
core/iwasm/common/wasm_application.c

@@ -107,7 +107,34 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
        the actual main function. Directly calling main function
        may cause exception thrown. */
     if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
-        return wasm_runtime_call_wasm(exec_env, func, 0, NULL);
+        const char *wasi_proc_exit_exception = "wasi proc exit";
+
+        ret = wasm_runtime_call_wasm(exec_env, func, 0, NULL);
+#if WASM_ENABLE_THREAD_MGR != 0
+        if (ret) {
+            /* On a successful return from the `_start` function,
+               we terminate other threads by mimicing wasi:proc_exit(0).
+
+               Note:
+               - A return from the `main` function is an equivalent of
+                 exit(). (C standard)
+               - When exit code is 0, wasi-libc's `_start` function just
+                 returns w/o calling `proc_exit`.
+               - A process termination should terminate threads in
+                 the process. */
+
+            wasm_runtime_set_exception(module_inst, wasi_proc_exit_exception);
+            /* exit_code is zero-initialized */
+            ret = false;
+        }
+#endif
+        /* report wasm proc exit as a success */
+        WASMModuleInstance *inst = (WASMModuleInstance *)module_inst;
+        if (!ret && strstr(inst->cur_exception, wasi_proc_exit_exception)) {
+            inst->cur_exception[0] = 0;
+            ret = true;
+        }
+        return ret;
     }
 #endif /* end of WASM_ENABLE_LIBC_WASI */
 
@@ -204,7 +231,7 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
                               char *argv[])
 {
     bool ret;
-#if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
+#if (WASM_ENABLE_MEMORY_PROFILING != 0)
     WASMExecEnv *exec_env;
 #endif
 
@@ -224,14 +251,6 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
     if (ret)
         ret = wasm_runtime_get_exception(module_inst) == NULL;
 
-#if WASM_ENABLE_DUMP_CALL_STACK != 0
-    if (!ret) {
-        exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
-        if (exec_env)
-            wasm_runtime_dump_call_stack(exec_env);
-    }
-#endif
-
     return ret;
 }
 

+ 92 - 0
core/iwasm/common/wasm_blocking_op.c

@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 Midokura Japan KK.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_runtime_common.h"
+
+#include "bh_platform.h"
+#include "bh_common.h"
+#include "bh_assert.h"
+
+#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
+
+#define LOCK(env) WASM_SUSPEND_FLAGS_LOCK((env)->wait_lock)
+#define UNLOCK(env) WASM_SUSPEND_FLAGS_UNLOCK((env)->wait_lock)
+
+#define ISSET(env, bit)                                                       \
+    ((WASM_SUSPEND_FLAGS_GET((env)->suspend_flags) & WASM_SUSPEND_FLAG_##bit) \
+     != 0)
+#define SET(env, bit) \
+    WASM_SUSPEND_FLAGS_FETCH_OR((env)->suspend_flags, WASM_SUSPEND_FLAG_##bit)
+#define CLR(env, bit) \
+    WASM_SUSPEND_FLAGS_FETCH_AND((env)->suspend_flags, ~WASM_SUSPEND_FLAG_##bit)
+
+bool
+wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
+{
+    LOCK(env);
+    bh_assert(!ISSET(env, BLOCKING));
+    SET(env, BLOCKING);
+    if (ISSET(env, TERMINATE)) {
+        CLR(env, BLOCKING);
+        UNLOCK(env);
+        return false;
+    }
+    UNLOCK(env);
+    os_begin_blocking_op();
+    return true;
+}
+
+void
+wasm_runtime_end_blocking_op(wasm_exec_env_t env)
+{
+    int saved_errno = errno;
+    LOCK(env);
+    bh_assert(ISSET(env, BLOCKING));
+    CLR(env, BLOCKING);
+    UNLOCK(env);
+    os_end_blocking_op();
+    errno = saved_errno;
+}
+
+void
+wasm_runtime_interrupt_blocking_op(wasm_exec_env_t env)
+{
+    /*
+     * ISSET(BLOCKING) here means that the target thread
+     * is in somewhere between wasm_begin_blocking_op and
+     * wasm_end_blocking_op.
+     * keep waking it up until it reaches wasm_end_blocking_op,
+     * which clears the BLOCKING bit.
+     *
+     * this dumb loop is necessary because posix doesn't provide
+     * a way to unmask signal and block atomically.
+     */
+
+    LOCK(env);
+    SET(env, TERMINATE);
+    while (ISSET(env, BLOCKING)) {
+        UNLOCK(env);
+        os_wakeup_blocking_op(env->handle);
+
+        /* relax a bit */
+        os_usleep(50 * 1000);
+        LOCK(env);
+    }
+    UNLOCK(env);
+}
+
+#else /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */
+
+bool
+wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
+{
+    return true;
+}
+
+void
+wasm_runtime_end_blocking_op(wasm_exec_env_t env)
+{}
+
+#endif /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */

+ 94 - 17
core/iwasm/common/wasm_memory.c

@@ -8,6 +8,7 @@
 #include "../aot/aot_runtime.h"
 #include "bh_platform.h"
 #include "mem_alloc.h"
+#include "wasm_memory.h"
 
 #if WASM_ENABLE_SHARED_MEMORY != 0
 #include "../common/wasm_shared_memory.h"
@@ -24,6 +25,9 @@ static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN;
 
 static mem_allocator_t pool_allocator = NULL;
 
+static enlarge_memory_error_callback_t enlarge_memory_error_cb;
+static void *enlarge_memory_error_user_data;
+
 #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
 static void *allocator_user_data = NULL;
 static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
@@ -570,13 +574,16 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
 {
     WASMMemoryInstance *memory = wasm_get_default_memory(module);
     uint8 *memory_data_old, *memory_data_new, *heap_data_old;
-    uint32 num_bytes_per_page, heap_size, total_size_old;
+    uint32 num_bytes_per_page, heap_size, total_size_old = 0;
     uint32 cur_page_count, max_page_count, total_page_count;
     uint64 total_size_new;
     bool ret = true;
+    enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR;
 
-    if (!memory)
-        return false;
+    if (!memory) {
+        ret = false;
+        goto return_func;
+    }
 
     heap_data_old = memory->heap_data;
     heap_size = (uint32)(memory->heap_data_end - memory->heap_data);
@@ -594,9 +601,15 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
         /* No need to enlarge memory */
         return true;
 
-    if (total_page_count < cur_page_count /* integer overflow */
-        || total_page_count > max_page_count) {
-        return false;
+    if (total_page_count < cur_page_count) { /* integer overflow */
+        ret = false;
+        goto return_func;
+    }
+
+    if (total_page_count > max_page_count) {
+        failure_reason = MAX_SIZE_REACHED;
+        ret = false;
+        goto return_func;
     }
 
     bh_assert(total_size_new <= 4 * (uint64)BH_GB);
@@ -622,14 +635,16 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
     if (heap_size > 0) {
         if (mem_allocator_is_heap_corrupted(memory->heap_handle)) {
             wasm_runtime_show_app_heap_corrupted_prompt();
-            return false;
+            ret = false;
+            goto return_func;
         }
     }
 
     if (!(memory_data_new =
               wasm_runtime_realloc(memory_data_old, (uint32)total_size_new))) {
         if (!(memory_data_new = wasm_runtime_malloc((uint32)total_size_new))) {
-            return false;
+            ret = false;
+            goto return_func;
         }
         if (memory_data_old) {
             bh_memcpy_s(memory_data_new, (uint32)total_size_new,
@@ -685,6 +700,27 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
     os_writegsbase(memory_data_new);
 #endif
 
+return_func:
+    if (!ret && enlarge_memory_error_cb) {
+        WASMExecEnv *exec_env = NULL;
+
+#if WASM_ENABLE_INTERP != 0
+        if (module->module_type == Wasm_Module_Bytecode)
+            exec_env =
+                ((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env;
+#endif
+#if WASM_ENABLE_AOT != 0
+        if (module->module_type == Wasm_Module_AoT)
+            exec_env =
+                ((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env;
+#endif
+
+        enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
+                                failure_reason,
+                                (WASMModuleInstanceCommon *)module, exec_env,
+                                enlarge_memory_error_user_data);
+    }
+
     return ret;
 }
 #else
@@ -692,12 +728,16 @@ bool
 wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
 {
     WASMMemoryInstance *memory = wasm_get_default_memory(module);
-    uint32 num_bytes_per_page, total_size_old;
+    uint32 num_bytes_per_page, total_size_old = 0;
     uint32 cur_page_count, max_page_count, total_page_count;
     uint64 total_size_new;
+    bool ret = true;
+    enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR;
 
-    if (!memory)
-        return false;
+    if (!memory) {
+        ret = false;
+        goto return_func;
+    }
 
     num_bytes_per_page = memory->num_bytes_per_page;
     cur_page_count = memory->cur_page_count;
@@ -710,9 +750,15 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
         /* No need to enlarge memory */
         return true;
 
-    if (total_page_count < cur_page_count /* integer overflow */
-        || total_page_count > max_page_count) {
-        return false;
+    if (total_page_count < cur_page_count) { /* integer overflow */
+        ret = false;
+        goto return_func;
+    }
+
+    if (total_page_count > max_page_count) {
+        failure_reason = MAX_SIZE_REACHED;
+        ret = false;
+        goto return_func;
     }
 
     bh_assert(total_size_new <= 4 * (uint64)BH_GB);
@@ -727,7 +773,8 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
     if (!os_mem_commit(memory->memory_data_end,
                        (uint32)total_size_new - total_size_old,
                        MMAP_PROT_READ | MMAP_PROT_WRITE)) {
-        return false;
+        ret = false;
+        goto return_func;
     }
 #endif
 
@@ -739,7 +786,8 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
         os_mem_decommit(memory->memory_data_end,
                         (uint32)total_size_new - total_size_old);
 #endif
-        return false;
+        ret = false;
+        goto return_func;
     }
 
     /* The increased pages are filled with zero by the OS when os_mmap,
@@ -759,10 +807,39 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
     memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
 #endif
 
-    return true;
+return_func:
+    if (!ret && enlarge_memory_error_cb) {
+        WASMExecEnv *exec_env = NULL;
+
+#if WASM_ENABLE_INTERP != 0
+        if (module->module_type == Wasm_Module_Bytecode)
+            exec_env =
+                ((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env;
+#endif
+#if WASM_ENABLE_AOT != 0
+        if (module->module_type == Wasm_Module_AoT)
+            exec_env =
+                ((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env;
+#endif
+
+        enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
+                                failure_reason,
+                                (WASMModuleInstanceCommon *)module, exec_env,
+                                enlarge_memory_error_user_data);
+    }
+
+    return ret;
 }
 #endif /* end of OS_ENABLE_HW_BOUND_CHECK */
 
+void
+wasm_runtime_set_enlarge_mem_error_callback(
+    const enlarge_memory_error_callback_t callback, void *user_data)
+{
+    enlarge_memory_error_cb = callback;
+    enlarge_memory_error_user_data = user_data;
+}
+
 bool
 wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
 {

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

@@ -24,6 +24,10 @@ wasm_runtime_memory_destroy();
 unsigned
 wasm_runtime_memory_pool_size();
 
+void
+wasm_runtime_set_enlarge_mem_error_callback(
+    const enlarge_memory_error_callback_t callback, void *user_data);
+
 #ifdef __cplusplus
 }
 #endif

+ 172 - 0
core/iwasm/common/wasm_native.c

@@ -6,6 +6,15 @@
 #include "wasm_native.h"
 #include "wasm_runtime_common.h"
 #include "bh_log.h"
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../libraries/thread-mgr/thread_manager.h"
+#endif
 
 #if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \
     && !defined(BH_PLATFORM_OPENRTOS) && !defined(BH_PLATFORM_ESP_IDF)
@@ -22,6 +31,10 @@
 
 static NativeSymbolsList g_native_symbols_list = NULL;
 
+#if WASM_ENABLE_LIBC_WASI != 0
+static void *g_wasi_context_key;
+#endif /* WASM_ENABLE_LIBC_WASI */
+
 uint32
 get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
 
@@ -394,6 +407,155 @@ wasm_native_unregister_natives(const char *module_name,
     return false;
 }
 
+#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
+static uint32
+context_key_to_idx(void *key)
+{
+    bh_assert(key != NULL);
+    uint32 idx = (uint32)(uintptr_t)key;
+    bh_assert(idx > 0);
+    bh_assert(idx <= WASM_MAX_INSTANCE_CONTEXTS);
+    return idx - 1;
+}
+
+static void *
+context_idx_to_key(uint32 idx)
+{
+    bh_assert(idx < WASM_MAX_INSTANCE_CONTEXTS);
+    return (void *)(uintptr_t)(idx + 1);
+}
+
+typedef void (*dtor_t)(WASMModuleInstanceCommon *, void *);
+static dtor_t g_context_dtors[WASM_MAX_INSTANCE_CONTEXTS];
+
+static void
+dtor_noop(WASMModuleInstanceCommon *inst, void *ctx)
+{}
+
+void *
+wasm_native_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
+                                            void *ctx))
+{
+    uint32 i;
+    for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
+        if (g_context_dtors[i] == NULL) {
+            if (dtor == NULL) {
+                dtor = dtor_noop;
+            }
+            g_context_dtors[i] = dtor;
+            return context_idx_to_key(i);
+        }
+    }
+    LOG_ERROR("failed to allocate instance context key");
+    return NULL;
+}
+
+void
+wasm_native_destroy_context_key(void *key)
+{
+    uint32 idx = context_key_to_idx(key);
+    bh_assert(g_context_dtors[idx] != NULL);
+    g_context_dtors[idx] = NULL;
+}
+
+static WASMModuleInstanceExtraCommon *
+wasm_module_inst_extra_common(WASMModuleInstanceCommon *inst)
+{
+#if WASM_ENABLE_INTERP != 0
+    if (inst->module_type == Wasm_Module_Bytecode) {
+        return &((WASMModuleInstance *)inst)->e->common;
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (inst->module_type == Wasm_Module_AoT) {
+        return &((AOTModuleInstanceExtra *)((AOTModuleInstance *)inst)->e)
+                    ->common;
+    }
+#endif
+    bh_assert(false);
+    return NULL;
+}
+
+void
+wasm_native_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx)
+{
+    uint32 idx = context_key_to_idx(key);
+    WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
+    common->contexts[idx] = ctx;
+}
+
+void
+wasm_native_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
+                               void *ctx)
+{
+#if WASM_ENABLE_THREAD_MGR != 0
+    wasm_cluster_set_context(inst, key, ctx);
+#else
+    wasm_native_set_context(inst, key, ctx);
+#endif
+}
+
+void *
+wasm_native_get_context(WASMModuleInstanceCommon *inst, void *key)
+{
+    uint32 idx = context_key_to_idx(key);
+    WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
+    return common->contexts[idx];
+}
+
+void
+wasm_native_call_context_dtors(WASMModuleInstanceCommon *inst)
+{
+    WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
+    uint32 i;
+    for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
+        dtor_t dtor = g_context_dtors[i];
+        if (dtor != NULL) {
+            dtor(inst, common->contexts[i]);
+        }
+    }
+}
+
+void
+wasm_native_inherit_contexts(WASMModuleInstanceCommon *child,
+                             WASMModuleInstanceCommon *parent)
+{
+    WASMModuleInstanceExtraCommon *parent_common =
+        wasm_module_inst_extra_common(parent);
+    WASMModuleInstanceExtraCommon *child_common =
+        wasm_module_inst_extra_common(child);
+    bh_memcpy_s(child_common->contexts,
+                sizeof(*child_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS,
+                parent_common->contexts,
+                sizeof(*parent_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS);
+}
+#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
+
+#if WASM_ENABLE_LIBC_WASI != 0
+WASIContext *
+wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
+{
+    return wasm_native_get_context(module_inst_comm, g_wasi_context_key);
+}
+
+void
+wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
+                          WASIContext *wasi_ctx)
+{
+    return wasm_native_set_context(module_inst_comm, g_wasi_context_key,
+                                   wasi_ctx);
+}
+
+static void
+wasi_context_dtor(WASMModuleInstanceCommon *inst, void *ctx)
+{
+    if (ctx == NULL) {
+        return;
+    }
+    wasm_runtime_destroy_wasi(inst);
+}
+#endif /* end of WASM_ENABLE_LIBC_WASI */
+
 bool
 wasm_native_init()
 {
@@ -420,6 +582,10 @@ wasm_native_init()
 #endif /* WASM_ENABLE_SPEC_TEST */
 
 #if WASM_ENABLE_LIBC_WASI != 0
+    g_wasi_context_key = wasm_native_create_context_key(wasi_context_dtor);
+    if (g_wasi_context_key == NULL) {
+        goto fail;
+    }
     n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
     if (!wasm_native_register_natives("wasi_unstable", native_symbols,
                                       n_native_symbols))
@@ -507,6 +673,12 @@ wasm_native_destroy()
 {
     NativeSymbolsNode *node, *node_next;
 
+#if WASM_ENABLE_LIBC_WASI != 0
+    if (g_wasi_context_key != NULL) {
+        wasm_native_destroy_context_key(g_wasi_context_key);
+        g_wasi_context_key = NULL;
+    }
+#endif
 #if WASM_ENABLE_LIB_PTHREAD != 0
     lib_pthread_destroy();
 #endif

+ 30 - 0
core/iwasm/common/wasm_native.h

@@ -68,6 +68,36 @@ bool
 wasm_native_unregister_natives(const char *module_name,
                                NativeSymbol *native_symbols);
 
+#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
+struct WASMModuleInstanceCommon;
+
+void *
+wasm_native_create_context_key(
+    void (*dtor)(struct WASMModuleInstanceCommon *inst, void *ctx));
+
+void
+wasm_native_destroy_context_key(void *key);
+
+void
+wasm_native_set_context(struct WASMModuleInstanceCommon *inst, void *key,
+                        void *ctx);
+void
+wasm_native_set_context_spread(struct WASMModuleInstanceCommon *inst, void *key,
+                               void *ctx);
+void *
+wasm_native_get_context(struct WASMModuleInstanceCommon *inst, void *key);
+
+void
+wasm_native_call_context_dtors(struct WASMModuleInstanceCommon *inst);
+
+void
+wasm_native_inherit_contexts(struct WASMModuleInstanceCommon *child,
+                             struct WASMModuleInstanceCommon *parent);
+#else /* WASM_ENABLE_MODULE_INST_CONTEXT */
+#define wasm_native_call_context_dtors(inst) (void)(inst)
+#define wasm_native_inherit_contexts(child, parent) (void)(parent)
+#endif /* WASM_ENABLE_MODULE_INST_CONTEXT */
+
 bool
 wasm_native_init();
 

+ 446 - 96
core/iwasm/common/wasm_runtime_common.c

@@ -125,6 +125,34 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
     return mem;
 }
 
+#if WASM_ENABLE_MULTI_MODULE != 0
+/* TODO: Let loader_malloc be a general API both for AOT and WASM. */
+
+#define loader_malloc(size, error_buf, error_buf_size) \
+    runtime_malloc(size, NULL, error_buf, error_buf_size)
+
+static void
+set_error_buf_v(const WASMModuleCommon *module, char *error_buf,
+                uint32 error_buf_size, const char *format, ...)
+{
+    va_list args;
+    char buf[128];
+    if (error_buf != NULL) {
+        va_start(args, format);
+        vsnprintf(buf, sizeof(buf), format, args);
+        va_end(args);
+        if (module->module_type == Wasm_Module_AoT) {
+            snprintf(error_buf, error_buf_size, "AOT module load failed: %s",
+                     buf);
+        }
+        else if (module->module_type == Wasm_Module_Bytecode) {
+            snprintf(error_buf, error_buf_size, "WASM module load failed: %s",
+                     buf);
+        }
+    }
+}
+#endif
+
 #if WASM_ENABLE_FAST_JIT != 0
 static JitCompOptions jit_options = { 0 };
 #endif
@@ -457,8 +485,21 @@ wasm_runtime_env_init()
     }
 #endif
 
+#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
+    if (os_blocking_op_init() != BHT_OK) {
+        goto fail11;
+    }
+    os_end_blocking_op();
+#endif
+
     return true;
 
+#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
+fail11:
+#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
+    aot_compiler_destroy();
+#endif
+#endif
 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
 fail10:
 #if WASM_ENABLE_FAST_JIT != 0
@@ -1185,27 +1226,34 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
     if (get_package_type(buf, size) == Wasm_Module_Bytecode) {
 #if WASM_ENABLE_INTERP != 0
         module_common =
-            (WASMModuleCommon *)wasm_load(buf, size, error_buf, error_buf_size);
-        return register_module_with_null_name(module_common, error_buf,
-                                              error_buf_size);
+            (WASMModuleCommon *)wasm_load(buf, size,
+#if WASM_ENABLE_MULTI_MODULE != 0
+                                          true,
+#endif
+                                          error_buf, error_buf_size);
 #endif
     }
     else if (get_package_type(buf, size) == Wasm_Module_AoT) {
 #if WASM_ENABLE_AOT != 0
         module_common = (WASMModuleCommon *)aot_load_from_aot_file(
             buf, size, error_buf, error_buf_size);
-        return register_module_with_null_name(module_common, error_buf,
-                                              error_buf_size);
 #endif
     }
-
-    if (size < 4)
-        set_error_buf(error_buf, error_buf_size,
-                      "WASM module load failed: unexpected end");
-    else
-        set_error_buf(error_buf, error_buf_size,
-                      "WASM module load failed: magic header not detected");
-    return NULL;
+    else {
+        if (size < 4)
+            set_error_buf(error_buf, error_buf_size,
+                          "WASM module load failed: unexpected end");
+        else
+            set_error_buf(error_buf, error_buf_size,
+                          "WASM module load failed: magic header not detected");
+        return NULL;
+    }
+    if (!module_common) {
+        LOG_DEBUG("WASM module load failed");
+        return NULL;
+    }
+    return register_module_with_null_name(module_common, error_buf,
+                                          error_buf_size);
 }
 
 WASMModuleCommon *
@@ -1218,6 +1266,10 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
 #if WASM_ENABLE_INTERP != 0
         module_common = (WASMModuleCommon *)wasm_load_from_sections(
             section_list, error_buf, error_buf_size);
+        if (!module_common) {
+            LOG_DEBUG("WASM module load failed from sections");
+            return NULL;
+        }
         return register_module_with_null_name(module_common, error_buf,
                                               error_buf_size);
 #endif
@@ -1226,6 +1278,10 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
 #if WASM_ENABLE_AOT != 0
         module_common = (WASMModuleCommon *)aot_load_from_sections(
             section_list, error_buf, error_buf_size);
+        if (!module_common) {
+            LOG_DEBUG("WASM module load failed from sections");
+            return NULL;
+        }
         return register_module_with_null_name(module_common, error_buf,
                                               error_buf_size);
 #endif
@@ -1392,6 +1448,10 @@ wasm_runtime_init_thread_env(void)
     }
 #endif
 
+#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
+    os_end_blocking_op();
+#endif
+
     return true;
 }
 
@@ -1938,33 +1998,6 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
 }
 #endif
 
-static bool
-clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm)
-{
-#if WASM_ENABLE_LIBC_WASI != 0
-    bool has_exception;
-    char exception[EXCEPTION_BUF_LEN];
-    WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
-
-    bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
-              || module_inst_comm->module_type == Wasm_Module_AoT);
-
-    has_exception = wasm_copy_exception(module_inst, exception);
-    if (has_exception && !strcmp(exception, "Exception: wasi proc exit")) {
-        /* The "wasi proc exit" exception is thrown by native lib to
-           let wasm app exit, which is a normal behavior, we clear
-           the exception here. And just clear the exception of current
-           thread, don't call `wasm_set_exception(module_inst, NULL)`
-           which will clear the exception of all threads. */
-        module_inst->cur_exception[0] = '\0';
-        return true;
-    }
-    return false;
-#else
-    return false;
-#endif
-}
-
 bool
 wasm_runtime_call_wasm(WASMExecEnv *exec_env,
                        WASMFunctionInstanceCommon *function, uint32 argc,
@@ -2005,15 +2038,10 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
                                 param_argc, new_argv);
 #endif
     if (!ret) {
-        if (clear_wasi_proc_exit_exception(exec_env->module_inst)) {
-            ret = true;
-        }
-        else {
-            if (new_argv != argv) {
-                wasm_runtime_free(new_argv);
-            }
-            return false;
+        if (new_argv != argv) {
+            wasm_runtime_free(new_argv);
         }
+        return false;
     }
 
 #if WASM_ENABLE_REF_TYPES != 0
@@ -2374,15 +2402,10 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm)
     return module_inst->exec_env_singleton;
 }
 
-void
-wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
+static void
+wasm_set_exception_local(WASMModuleInstance *module_inst, const char *exception)
 {
-    WASMExecEnv *exec_env = NULL;
-
-#if WASM_ENABLE_SHARED_MEMORY != 0
-    if (module_inst->memory_count > 0)
-        shared_memory_lock(module_inst->memories[0]);
-#endif
+    exception_lock(module_inst);
     if (exception) {
         snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception),
                  "Exception: %s", exception);
@@ -2390,19 +2413,23 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
     else {
         module_inst->cur_exception[0] = '\0';
     }
-#if WASM_ENABLE_SHARED_MEMORY != 0
-    if (module_inst->memory_count > 0)
-        shared_memory_unlock(module_inst->memories[0]);
-#endif
+    exception_unlock(module_inst);
+}
 
+void
+wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
+{
 #if WASM_ENABLE_THREAD_MGR != 0
-    exec_env =
+    WASMExecEnv *exec_env =
         wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst);
     if (exec_env) {
-        wasm_cluster_spread_exception(exec_env, exception ? false : true);
+        wasm_cluster_set_exception(exec_env, exception);
+    }
+    else {
+        wasm_set_exception_local(module_inst, exception);
     }
 #else
-    (void)exec_env;
+    wasm_set_exception_local(module_inst, exception);
 #endif
 }
 
@@ -2453,10 +2480,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
 {
     bool has_exception = false;
 
-#if WASM_ENABLE_SHARED_MEMORY != 0
-    if (module_inst->memory_count > 0)
-        shared_memory_lock(module_inst->memories[0]);
-#endif
+    exception_lock(module_inst);
     if (module_inst->cur_exception[0] != '\0') {
         /* NULL is passed if the caller is not interested in getting the
          * exception content, but only in knowing if an exception has been
@@ -2468,10 +2492,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
                         sizeof(module_inst->cur_exception));
         has_exception = true;
     }
-#if WASM_ENABLE_SHARED_MEMORY != 0
-    if (module_inst->memory_count > 0)
-        shared_memory_unlock(module_inst->memories[0]);
-#endif
+    exception_unlock(module_inst);
 
     return has_exception;
 }
@@ -2516,6 +2537,18 @@ wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst_comm)
     wasm_runtime_set_exception(module_inst_comm, NULL);
 }
 
+#if WASM_ENABLE_THREAD_MGR != 0
+void
+wasm_runtime_terminate(WASMModuleInstanceCommon *module_inst_comm)
+{
+    WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
+
+    bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
+              || module_inst_comm->module_type == Wasm_Module_AoT);
+    wasm_set_exception(module_inst, "terminated by user");
+}
+#endif
+
 void
 wasm_runtime_set_custom_data_internal(
     WASMModuleInstanceCommon *module_inst_comm, void *custom_data)
@@ -3338,27 +3371,6 @@ wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst)
 #endif
     return wasi_ctx->exit_code;
 }
-
-WASIContext *
-wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
-{
-    WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
-
-    bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
-              || module_inst_comm->module_type == Wasm_Module_AoT);
-    return module_inst->wasi_ctx;
-}
-
-void
-wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
-                          WASIContext *wasi_ctx)
-{
-    WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
-
-    bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
-              || module_inst_comm->module_type == Wasm_Module_AoT);
-    module_inst->wasi_ctx = wasi_ctx;
-}
 #endif /* end of WASM_ENABLE_LIBC_WASI */
 
 WASMModuleCommon *
@@ -4621,10 +4633,6 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_index,
         ret = aot_call_indirect(exec_env, 0, element_index, argc, argv);
 #endif
 
-    if (!ret && clear_wasi_proc_exit_exception(exec_env->module_inst)) {
-        ret = true;
-    }
-
     return ret;
 }
 
@@ -5708,3 +5716,345 @@ wasm_runtime_is_import_global_linked(const char *module_name,
     return false;
 #endif
 }
+
+#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0
+WASMExport *
+loader_find_export(const WASMModuleCommon *module, const char *module_name,
+                   const char *field_name, uint8 export_kind, char *error_buf,
+                   uint32 error_buf_size)
+{
+    WASMExport *exports = NULL, *result = NULL, *export;
+    uint32 export_count = 0, i;
+#if WASM_ENABLE_AOT != 0
+    if (module->module_type == Wasm_Module_AoT) {
+        AOTModule *aot_module = (AOTModule *)module;
+        exports = (WASMExport *)aot_module->exports;
+        export_count = aot_module->export_count;
+    }
+#endif
+#if WASM_ENABLE_INTERP != 0
+    if (module->module_type == Wasm_Module_Bytecode) {
+        WASMModule *wasm_module = (WASMModule *)module;
+        exports = wasm_module->exports;
+        export_count = wasm_module->export_count;
+    }
+#endif
+    for (i = 0, export = exports; i < export_count; ++i, ++export) {
+        if (export->kind == export_kind && !strcmp(field_name, export->name)) {
+            result = export;
+            goto exit;
+        }
+    }
+    if (i == export_count) {
+        LOG_DEBUG("can not find an export %d named %s in the module %s",
+                  export_kind, field_name, module_name);
+        set_error_buf(error_buf, error_buf_size,
+                      "unknown import or incompatible import type");
+    }
+exit:
+    return result;
+}
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+WASMModuleCommon *
+wasm_runtime_search_sub_module(const WASMModuleCommon *parent_module,
+                               const char *sub_module_name)
+{
+    WASMRegisteredModule *node = NULL;
+#if WASM_ENABLE_AOT != 0
+    if (parent_module->module_type == Wasm_Module_AoT) {
+        node = bh_list_first_elem(
+            ((AOTModule *)parent_module)->import_module_list);
+    }
+#endif
+#if WASM_ENABLE_INTERP != 0
+    if (parent_module->module_type == Wasm_Module_Bytecode) {
+        node = bh_list_first_elem(
+            ((WASMModule *)parent_module)->import_module_list);
+    }
+#endif
+    while (node && strcmp(sub_module_name, node->module_name)) {
+        node = bh_list_elem_next(node);
+    }
+    return node ? node->module : NULL;
+}
+
+bool
+wasm_runtime_register_sub_module(const WASMModuleCommon *parent_module,
+                                 const char *sub_module_name,
+                                 WASMModuleCommon *sub_module)
+{
+    /* register sub_module into its parent sub module list */
+    WASMRegisteredModule *node = NULL;
+    bh_list_status ret;
+
+    if (wasm_runtime_search_sub_module(parent_module, sub_module_name)) {
+        LOG_DEBUG("%s has been registered in its parent", sub_module_name);
+        return true;
+    }
+
+    node = loader_malloc(sizeof(WASMRegisteredModule), NULL, 0);
+    if (!node) {
+        return false;
+    }
+
+    node->module_name = sub_module_name;
+    node->module = sub_module;
+#if WASM_ENABLE_AOT != 0
+    if (parent_module->module_type == Wasm_Module_AoT) {
+        ret = bh_list_insert(((AOTModule *)parent_module)->import_module_list,
+                             node);
+    }
+#endif
+#if WASM_ENABLE_INTERP != 0
+    if (parent_module->module_type == Wasm_Module_Bytecode) {
+        ret = bh_list_insert(((WASMModule *)parent_module)->import_module_list,
+                             node);
+    }
+#endif
+    bh_assert(BH_LIST_SUCCESS == ret);
+    (void)ret;
+    return true;
+}
+
+WASMModuleCommon *
+wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module,
+                                  const char *sub_module_name, char *error_buf,
+                                  uint32 error_buf_size)
+{
+    WASMModuleCommon *sub_module = NULL;
+    bool ret = false;
+    uint8 *buffer = NULL;
+    uint32 buffer_size = 0;
+
+    /* check the registered module list of the parent */
+    sub_module = wasm_runtime_search_sub_module(parent_module, sub_module_name);
+    if (sub_module) {
+        LOG_DEBUG("%s has been loaded before", sub_module_name);
+        return sub_module;
+    }
+
+    /* check the global registered module list */
+    sub_module = wasm_runtime_find_module_registered(sub_module_name);
+    if (sub_module) {
+        LOG_DEBUG("%s has been loaded", sub_module_name);
+        goto wasm_runtime_register_sub_module;
+    }
+    LOG_VERBOSE("loading %s", sub_module_name);
+    if (!reader) {
+        set_error_buf_v(parent_module, error_buf, error_buf_size,
+                        "no sub module reader to load %s", sub_module_name);
+        return NULL;
+    }
+    /* start to maintain a loading module list */
+    ret = wasm_runtime_is_loading_module(sub_module_name);
+    if (ret) {
+        set_error_buf_v(parent_module, error_buf, error_buf_size,
+                        "found circular dependency on %s", sub_module_name);
+        return NULL;
+    }
+    ret = wasm_runtime_add_loading_module(sub_module_name, error_buf,
+                                          error_buf_size);
+    if (!ret) {
+        LOG_DEBUG("can not add %s into loading module list\n", sub_module_name);
+        return NULL;
+    }
+
+    ret = reader(parent_module->module_type, sub_module_name, &buffer,
+                 &buffer_size);
+    if (!ret) {
+        LOG_DEBUG("read the file of %s failed", sub_module_name);
+        set_error_buf_v(parent_module, error_buf, error_buf_size,
+                        "unknown import", sub_module_name);
+        goto delete_loading_module;
+    }
+    if (get_package_type(buffer, buffer_size) != parent_module->module_type) {
+        LOG_DEBUG("moudle %s type error", sub_module_name);
+        goto delete_loading_module;
+    }
+    if (get_package_type(buffer, buffer_size) == Wasm_Module_Bytecode) {
+#if WASM_ENABLE_INTERP != 0
+        sub_module = (WASMModuleCommon *)wasm_load(buffer, buffer_size, false,
+                                                   error_buf, error_buf_size);
+#endif
+    }
+    else if (get_package_type(buffer, buffer_size) == Wasm_Module_AoT) {
+#if WASM_ENABLE_AOT != 0
+        sub_module = (WASMModuleCommon *)aot_load_from_aot_file(
+            buffer, buffer_size, error_buf, error_buf_size);
+#endif
+    }
+    if (!sub_module) {
+        LOG_DEBUG("error: can not load the sub_module %s", sub_module_name);
+        /* others will be destroyed in runtime_destroy() */
+        goto destroy_file_buffer;
+    }
+    wasm_runtime_delete_loading_module(sub_module_name);
+    /* register on a global list */
+    ret = wasm_runtime_register_module_internal(
+        sub_module_name, (WASMModuleCommon *)sub_module, buffer, buffer_size,
+        error_buf, error_buf_size);
+    if (!ret) {
+        LOG_DEBUG("error: can not register module %s globally\n",
+                  sub_module_name);
+        /* others will be unloaded in runtime_destroy() */
+        goto unload_module;
+    }
+
+    /* register into its parent list */
+wasm_runtime_register_sub_module:
+    ret = wasm_runtime_register_sub_module(parent_module, sub_module_name,
+                                           sub_module);
+    if (!ret) {
+        set_error_buf_v(parent_module, error_buf, error_buf_size,
+                        "failed to register sub module %s", sub_module_name);
+        /* since it is in the global module list, no need to
+         * unload the module. the runtime_destroy() will do it
+         */
+        return NULL;
+    }
+
+    return sub_module;
+
+unload_module:
+    wasm_runtime_unload(sub_module);
+
+destroy_file_buffer:
+    if (destroyer) {
+        destroyer(buffer, buffer_size);
+    }
+    else {
+        LOG_WARNING("need to release the reading buffer of %s manually",
+                    sub_module_name);
+    }
+
+delete_loading_module:
+    wasm_runtime_delete_loading_module(sub_module_name);
+    return NULL;
+}
+
+bool
+wasm_runtime_sub_module_instantiate(WASMModuleCommon *module,
+                                    WASMModuleInstanceCommon *module_inst,
+                                    uint32 stack_size, uint32 heap_size,
+                                    char *error_buf, uint32 error_buf_size)
+{
+    bh_list *sub_module_inst_list = NULL;
+    WASMRegisteredModule *sub_module_list_node = NULL;
+
+#if WASM_ENABLE_AOT != 0
+    if (module->module_type == Wasm_Module_AoT) {
+        sub_module_inst_list =
+            ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e)
+                ->sub_module_inst_list;
+        sub_module_list_node =
+            bh_list_first_elem(((AOTModule *)module)->import_module_list);
+    }
+#endif
+#if WASM_ENABLE_INTERP != 0
+    if (module->module_type == Wasm_Module_Bytecode) {
+        sub_module_inst_list =
+            ((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e)
+                ->sub_module_inst_list;
+        sub_module_list_node =
+            bh_list_first_elem(((WASMModule *)module)->import_module_list);
+    }
+#endif
+    while (sub_module_list_node) {
+        WASMSubModInstNode *sub_module_inst_list_node = NULL;
+        WASMModuleCommon *sub_module = sub_module_list_node->module;
+        WASMModuleInstanceCommon *sub_module_inst = NULL;
+        sub_module_inst = wasm_runtime_instantiate_internal(
+            sub_module, NULL, NULL, stack_size, heap_size, error_buf,
+            error_buf_size);
+        if (!sub_module_inst) {
+            LOG_DEBUG("instantiate %s failed",
+                      sub_module_list_node->module_name);
+            return false;
+        }
+        sub_module_inst_list_node = loader_malloc(sizeof(WASMSubModInstNode),
+                                                  error_buf, error_buf_size);
+        if (!sub_module_inst_list_node) {
+            LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d",
+                      sizeof(WASMSubModInstNode));
+            if (sub_module_inst)
+                wasm_runtime_deinstantiate_internal(sub_module_inst, false);
+            return false;
+        }
+        sub_module_inst_list_node->module_inst =
+            (WASMModuleInstance *)sub_module_inst;
+        sub_module_inst_list_node->module_name =
+            sub_module_list_node->module_name;
+        bh_list_status ret =
+            bh_list_insert(sub_module_inst_list, sub_module_inst_list_node);
+        bh_assert(BH_LIST_SUCCESS == ret);
+        (void)ret;
+        sub_module_list_node = bh_list_elem_next(sub_module_list_node);
+    }
+
+    return true;
+}
+
+void
+wasm_runtime_sub_module_deinstantiate(WASMModuleInstanceCommon *module_inst)
+{
+    bh_list *list = NULL;
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT) {
+        list = ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e)
+                   ->sub_module_inst_list;
+    }
+#endif
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode) {
+        list =
+            ((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e)
+                ->sub_module_inst_list;
+    }
+#endif
+
+    WASMSubModInstNode *node = bh_list_first_elem(list);
+    while (node) {
+        WASMSubModInstNode *next_node = bh_list_elem_next(node);
+        bh_list_remove(list, node);
+        wasm_runtime_deinstantiate_internal(
+            (WASMModuleInstanceCommon *)node->module_inst, false);
+        wasm_runtime_free(node);
+        node = next_node;
+    }
+}
+#endif /* end of WASM_ENABLE_MULTI_MODULE */
+#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
+void *
+wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
+                                             void *ctx))
+{
+    return wasm_native_create_context_key(dtor);
+}
+
+void
+wasm_runtime_destroy_context_key(void *key)
+{
+    wasm_native_destroy_context_key(key);
+}
+
+void
+wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx)
+{
+    wasm_native_set_context(inst, key, ctx);
+}
+
+void
+wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
+                                void *ctx)
+{
+    wasm_native_set_context_spread(inst, key, ctx);
+}
+
+void *
+wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key)
+{
+    return wasm_native_get_context(inst, key);
+}
+#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */

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

@@ -675,6 +675,10 @@ wasm_runtime_get_exception(WASMModuleInstanceCommon *module);
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst);
 
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_terminate(WASMModuleInstanceCommon *module);
+
 /* Internal API */
 void
 wasm_runtime_set_custom_data_internal(WASMModuleInstanceCommon *module_inst,
@@ -784,6 +788,9 @@ wasm_runtime_register_module_internal(const char *module_name,
 void
 wasm_runtime_unregister_module(const WASMModuleCommon *module);
 
+WASMModuleCommon *
+wasm_runtime_find_module_registered(const char *module_name);
+
 bool
 wasm_runtime_add_loading_module(const char *module_name, char *error_buf,
                                 uint32 error_buf_size);
@@ -796,6 +803,35 @@ wasm_runtime_is_loading_module(const char *module_name);
 
 void
 wasm_runtime_destroy_loading_module_list();
+
+WASMModuleCommon *
+wasm_runtime_search_sub_module(const WASMModuleCommon *parent_module,
+                               const char *sub_module_name);
+
+bool
+wasm_runtime_register_sub_module(const WASMModuleCommon *parent_module,
+                                 const char *sub_module_name,
+                                 WASMModuleCommon *sub_module);
+
+WASMModuleCommon *
+wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module,
+                                  const char *sub_module_name, char *error_buf,
+                                  uint32 error_buf_size);
+
+bool
+wasm_runtime_sub_module_instantiate(WASMModuleCommon *module,
+                                    WASMModuleInstanceCommon *module_inst,
+                                    uint32 stack_size, uint32 heap_size,
+                                    char *error_buf, uint32 error_buf_size);
+void
+wasm_runtime_sub_module_deinstantiate(WASMModuleInstanceCommon *module_inst);
+#endif
+
+#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0
+WASMExport *
+loader_find_export(const WASMModuleCommon *module, const char *module_name,
+                   const char *field_name, uint8 export_kind, char *error_buf,
+                   uint32 error_buf_size);
 #endif /* WASM_ENALBE_MULTI_MODULE */
 
 bool
@@ -939,6 +975,26 @@ WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_unregister_natives(const char *module_name,
                                 NativeSymbol *native_symbols);
 
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
+                                             void *ctx));
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy_context_key(void *key);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx);
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
+                                void *ctx);
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key);
+
 bool
 wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
                            const WASMType *func_type, const char *signature,
@@ -1016,6 +1072,15 @@ WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_is_import_global_linked(const char *module_name,
                                      const char *global_name);
 
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_begin_blocking_op(WASMExecEnv *exec_env);
+
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_end_blocking_op(WASMExecEnv *exec_env);
+
+void
+wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env);
+
 #ifdef __cplusplus
 }
 #endif

+ 2 - 0
core/iwasm/common/wasm_suspend_flags.h

@@ -20,6 +20,8 @@ extern "C" {
 #define WASM_SUSPEND_FLAG_BREAKPOINT 0x4
 /* Return from pthread_exit */
 #define WASM_SUSPEND_FLAG_EXIT 0x8
+/* The thread might be blocking */
+#define WASM_SUSPEND_FLAG_BLOCKING 0x10
 
 typedef union WASMSuspendFlags {
     bh_atomic_32_t flags;

+ 13 - 0
core/iwasm/compilation/aot_compiler.h

@@ -363,6 +363,19 @@ check_type_compatible(uint8 src_type, uint8 dst_type)
         }                                                                   \
     } while (0)
 
+/* if val is a constant integer and its value is not undef or poison */
+static inline bool
+LLVMIsEfficientConstInt(LLVMValueRef val)
+{
+    return LLVMIsConstant(val)
+           && LLVMGetValueKind(val) == LLVMConstantIntValueKind
+           && !LLVMIsUndef(val)
+#if LLVM_VERSION_NUMBER >= 12
+           && !LLVMIsPoison(addr)
+#endif
+        ;
+}
+
 bool
 aot_compile_wasm(AOTCompContext *comp_ctx);
 

+ 2 - 0
core/iwasm/compilation/aot_emit_aot_file.c

@@ -2703,6 +2703,7 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
                 || (obj_data->target_info.bin_type == AOT_COFF32_BIN_TYPE
                     && !strncmp(name, "_", 1)
                     && !strcmp(name + 1, aot_stack_sizes_alias_name)))) {
+#if 0 /* cf. https://github.com/llvm/llvm-project/issues/67765 */
             uint64 sz = LLVMGetSymbolSize(sym_itr);
             if (sz != sizeof(uint32) * obj_data->func_count
                 /* sz of COFF64/COFF32 is 0, ignore the check */
@@ -2711,6 +2712,7 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
                 aot_set_last_error("stack_sizes had unexpected size.");
                 goto fail;
             }
+#endif
             uint64 addr = LLVMGetSymbolAddress(sym_itr);
             if (!(sec_itr =
                       LLVMObjectFileCopySectionIterator(obj_data->binary))) {

+ 23 - 10
core/iwasm/compilation/aot_emit_control.c

@@ -4,6 +4,7 @@
  */
 
 #include "aot_emit_control.h"
+#include "aot_compiler.h"
 #include "aot_emit_exception.h"
 #include "../aot/aot_runtime.h"
 #include "../interpreter/wasm_loader.h"
@@ -234,13 +235,15 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         else {
             /* Store extra return values to function parameters */
             if (i != 0) {
+                LLVMValueRef res;
                 uint32 param_index = func_type->param_count + i;
-                if (!LLVMBuildStore(
-                        comp_ctx->builder, block->result_phis[i],
-                        LLVMGetParam(func_ctx->func, param_index))) {
+                if (!(res = LLVMBuildStore(
+                          comp_ctx->builder, block->result_phis[i],
+                          LLVMGetParam(func_ctx->func, param_index)))) {
                     aot_set_last_error("llvm build store failed.");
                     goto fail;
                 }
+                LLVMSetAlignment(res, 1);
             }
         }
     }
@@ -278,7 +281,7 @@ push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx,
                                         AOTBlock *block)
 {
     uint32 i, param_index;
-    LLVMValueRef value;
+    LLVMValueRef value, br_inst;
     uint64 size;
     char name[32];
     LLVMBasicBlockRef block_curr = CURR_BLOCK();
@@ -326,7 +329,14 @@ push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx,
                 }
             }
         }
-        SET_BUILDER_POS(block_curr);
+
+        /* At this point, the branch instruction was already built to jump to
+         * the new BB, to avoid generating zext instruction from the popped
+         * operand that would come after branch instruction, we should position
+         * the builder before the last branch instruction */
+        br_inst = LLVMGetLastInstruction(block_curr);
+        bh_assert(LLVMGetInstructionOpcode(br_inst) == LLVMBr);
+        LLVMPositionBuilderBefore(comp_ctx->builder, br_inst);
 
         /* Pop param values from current block's
          * value stack and add to param phis.
@@ -467,7 +477,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                                                    p_frame_ip);
         }
 
-        if (!LLVMIsConstant(value)) {
+        if (!LLVMIsEfficientConstInt(value)) {
             /* Compare value is not constant, create condition br IR */
             /* Create entry block */
             format_block_name(name, sizeof(name), block->block_index,
@@ -833,7 +843,7 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
     }
 
-    if (!LLVMIsConstant(value_cmp)) {
+    if (!LLVMIsEfficientConstInt(value_cmp)) {
         /* Compare value is not constant, create condition br IR */
         if (!(block_dst = get_target_block(func_ctx, br_depth))) {
             return false;
@@ -970,7 +980,7 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
     }
 
-    if (!LLVMIsConstant(value_cmp)) {
+    if (!LLVMIsEfficientConstInt(value_cmp)) {
         /* Compare value is not constant, create switch IR */
         for (i = 0; i <= br_count; i++) {
             target_block = get_target_block(func_ctx, br_depths[i]);
@@ -1102,14 +1112,17 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     if (block_func->result_count) {
         /* Store extra result values to function parameters */
         for (i = 0; i < block_func->result_count - 1; i++) {
+            LLVMValueRef res;
             result_index = block_func->result_count - 1 - i;
             POP(value, block_func->result_types[result_index]);
             param_index = func_type->param_count + result_index;
-            if (!LLVMBuildStore(comp_ctx->builder, value,
-                                LLVMGetParam(func_ctx->func, param_index))) {
+            if (!(res = LLVMBuildStore(
+                      comp_ctx->builder, value,
+                      LLVMGetParam(func_ctx->func, param_index)))) {
                 aot_set_last_error("llvm build store failed.");
                 goto fail;
             }
+            LLVMSetAlignment(res, 1);
         }
         /* Return the first result value */
         POP(value, block_func->result_types[0]);

+ 3 - 10
core/iwasm/compilation/aot_emit_memory.c

@@ -4,6 +4,7 @@
  */
 
 #include "aot_emit_memory.h"
+#include "aot_compiler.h"
 #include "aot_emit_exception.h"
 #include "../aot/aot_runtime.h"
 #include "aot_intrinsic.h"
@@ -145,11 +146,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
      * have been thrown when converting float to integer before
      */
     /* return addres directly if constant offset and inside memory space */
-    if (LLVMIsConstant(addr) && !LLVMIsUndef(addr)
-#if LLVM_VERSION_NUMBER >= 12
-        && !LLVMIsPoison(addr)
-#endif
-    ) {
+    if (LLVMIsEfficientConstInt(addr)) {
         uint64 mem_offset =
             (uint64)LLVMConstIntGetZExtValue(addr) + (uint64)offset;
         uint32 num_bytes_per_page =
@@ -911,11 +908,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
      * have been thrown when converting float to integer before
      */
     /* return addres directly if constant offset and inside memory space */
-    if (!LLVMIsUndef(offset) && !LLVMIsUndef(bytes)
-#if LLVM_VERSION_NUMBER >= 12
-        && !LLVMIsPoison(offset) && !LLVMIsPoison(bytes)
-#endif
-        && LLVMIsConstant(offset) && LLVMIsConstant(bytes)) {
+    if (LLVMIsEfficientConstInt(offset) && LLVMIsEfficientConstInt(bytes)) {
         uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(offset);
         uint64 mem_len = (uint64)LLVMConstIntGetZExtValue(bytes);
         uint32 num_bytes_per_page =

+ 17 - 11
core/iwasm/compilation/aot_emit_numberic.c

@@ -54,13 +54,13 @@
     } while (0)
 
 #if LLVM_VERSION_NUMBER >= 12
-#define IS_CONST_ZERO(val)                                          \
-    (!LLVMIsUndef(val) && !LLVMIsPoison(val) && LLVMIsConstant(val) \
-     && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0)      \
+#define IS_CONST_ZERO(val)                                     \
+    (LLVMIsEfficientConstInt(val)                              \
+     && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \
          || (!is_i32 && (int64)LLVMConstIntGetSExtValue(val) == 0)))
 #else
 #define IS_CONST_ZERO(val)                                     \
-    (!LLVMIsUndef(val) && LLVMIsConstant(val)                  \
+    (LLVMIsEfficientConstInt(val)                              \
      && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \
          || (!is_i32 && (int64)LLVMConstIntGetSExtValue(val) == 0)))
 #endif
@@ -171,6 +171,15 @@
         right = shift_count_mask;                                      \
     } while (0)
 
+static bool
+is_shift_count_mask_needed(AOTCompContext *comp_ctx, LLVMValueRef left,
+                           LLVMValueRef right)
+{
+    return (strcmp(comp_ctx->target_arch, "x86_64") != 0
+            && strcmp(comp_ctx->target_arch, "i386") != 0)
+           || (LLVMIsEfficientConstInt(left) && LLVMIsEfficientConstInt(right));
+}
+
 /* Call llvm constrained floating-point intrinsic */
 static LLVMValueRef
 call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
@@ -473,7 +482,7 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
     }
 
-    if (LLVMIsConstant(right)) {
+    if (LLVMIsEfficientConstInt(right)) {
         int64 right_val = (int64)LLVMConstIntGetSExtValue(right);
         switch (right_val) {
             case 0:
@@ -728,8 +737,7 @@ compile_int_shl(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right,
 {
     LLVMValueRef res;
 
-    if (strcmp(comp_ctx->target_arch, "x86_64") != 0
-        && strcmp(comp_ctx->target_arch, "i386") != 0)
+    if (is_shift_count_mask_needed(comp_ctx, left, right))
         SHIFT_COUNT_MASK;
 
     /* Build shl */
@@ -744,8 +752,7 @@ compile_int_shr_s(AOTCompContext *comp_ctx, LLVMValueRef left,
 {
     LLVMValueRef res;
 
-    if (strcmp(comp_ctx->target_arch, "x86_64") != 0
-        && strcmp(comp_ctx->target_arch, "i386") != 0)
+    if (is_shift_count_mask_needed(comp_ctx, left, right))
         SHIFT_COUNT_MASK;
 
     /* Build shl */
@@ -760,8 +767,7 @@ compile_int_shr_u(AOTCompContext *comp_ctx, LLVMValueRef left,
 {
     LLVMValueRef res;
 
-    if (strcmp(comp_ctx->target_arch, "x86_64") != 0
-        && strcmp(comp_ctx->target_arch, "i386") != 0)
+    if (is_shift_count_mask_needed(comp_ctx, left, right))
         SHIFT_COUNT_MASK;
 
     /* Build shl */

+ 9 - 1
core/iwasm/compilation/aot_llvm.c

@@ -526,12 +526,18 @@ aot_add_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module,
     }
     wasm_runtime_free(params);
     params = NULL;
+
+#if LLVM_VERSION_MAJOR < 17
     if (aot_target_precheck_can_use_musttail(comp_ctx)) {
         LLVMSetTailCallKind(retval, LLVMTailCallKindMustTail);
     }
     else {
         LLVMSetTailCallKind(retval, LLVMTailCallKindTail);
     }
+#else
+    LLVMSetTailCall(retval, true);
+#endif
+
     if (ret_type == VOID_TYPE) {
         if (!LLVMBuildRetVoid(b)) {
             goto fail;
@@ -2172,8 +2178,10 @@ bool
 aot_compiler_init(void)
 {
     /* Initialize LLVM environment */
-
+#if LLVM_VERSION_MAJOR < 17
     LLVMInitializeCore(LLVMGetGlobalPassRegistry());
+#endif
+
 #if WASM_ENABLE_WAMR_COMPILER != 0
     /* Init environment of all targets for AOT compiler */
     LLVMInitializeAllTargetInfos();

+ 4 - 1
core/iwasm/compilation/aot_llvm.h

@@ -15,15 +15,18 @@
 #include "llvm-c/ExecutionEngine.h"
 #include "llvm-c/Analysis.h"
 #include "llvm-c/BitWriter.h"
+#if LLVM_VERSION_MAJOR < 17
 #include "llvm-c/Transforms/Utils.h"
 #include "llvm-c/Transforms/Scalar.h"
 #include "llvm-c/Transforms/Vectorize.h"
 #include "llvm-c/Transforms/PassManagerBuilder.h"
+#include "llvm-c/Initialization.h"
+#endif
 
 #include "llvm-c/Orc.h"
 #include "llvm-c/Error.h"
 #include "llvm-c/Support.h"
-#include "llvm-c/Initialization.h"
+
 #include "llvm-c/TargetMachine.h"
 #include "llvm-c/LLJIT.h"
 #if WASM_ENABLE_DEBUG_AOT != 0

+ 26 - 1
core/iwasm/compilation/aot_llvm_extra.cpp

@@ -5,11 +5,13 @@
 
 #include <llvm/Passes/StandardInstrumentations.h>
 #include <llvm/Support/Error.h>
+#if LLVM_VERSION_MAJOR < 17
 #include <llvm/ADT/None.h>
 #include <llvm/ADT/Optional.h>
+#include <llvm/ADT/Triple.h>
+#endif
 #include <llvm/ADT/SmallVector.h>
 #include <llvm/ADT/Twine.h>
-#include <llvm/ADT/Triple.h>
 #include <llvm/Analysis/TargetTransformInfo.h>
 #include <llvm/CodeGen/TargetPassConfig.h>
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
@@ -18,7 +20,9 @@
 #include <llvm/Target/TargetMachine.h>
 #include <llvm-c/Core.h>
 #include <llvm-c/ExecutionEngine.h>
+#if LLVM_VERSION_MAJOR < 17
 #include <llvm-c/Initialization.h>
+#endif
 #include <llvm/ExecutionEngine/GenericValue.h>
 #include <llvm/ExecutionEngine/JITEventListener.h>
 #include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
@@ -30,6 +34,9 @@
 #include <llvm/IR/PassManager.h>
 #include <llvm/Support/CommandLine.h>
 #include <llvm/Support/ErrorHandling.h>
+#if LLVM_VERSION_MAJOR >= 17
+#include <llvm/Support/PGOOptions.h>
+#endif
 #include <llvm/Target/CodeGenCWrappers.h>
 #include <llvm/Target/TargetMachine.h>
 #include <llvm/Target/TargetOptions.h>
@@ -55,6 +62,13 @@
 using namespace llvm;
 using namespace llvm::orc;
 
+#if LLVM_VERSION_MAJOR >= 17
+namespace llvm {
+template<typename T>
+using Optional = std::optional<T>;
+}
+#endif
+
 LLVM_C_EXTERN_C_BEGIN
 
 bool
@@ -110,7 +124,14 @@ ExpandMemoryOpPass::run(Function &F, FunctionAnalysisManager &AM)
             Memcpy->eraseFromParent();
         }
         else if (MemMoveInst *Memmove = dyn_cast<MemMoveInst>(MemCall)) {
+#if LLVM_VERSION_MAJOR >= 17
+            Function *ParentFunc = Memmove->getParent()->getParent();
+            const TargetTransformInfo &TTI =
+                AM.getResult<TargetIRAnalysis>(*ParentFunc);
+            expandMemMoveAsLoop(Memmove, TTI);
+#else
             expandMemMoveAsLoop(Memmove);
+#endif
             Memmove->eraseFromParent();
         }
         else if (MemSetInst *Memset = dyn_cast<MemSetInst>(MemCall)) {
@@ -181,6 +202,9 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
 #else
     Optional<PGOOptions> PGO = llvm::None;
 #endif
+
+// TODO
+#if LLVM_VERSION_MAJOR < 17
     if (comp_ctx->enable_llvm_pgo) {
         /* Disable static counter allocation for value profiler,
            it will be allocated by runtime */
@@ -191,6 +215,7 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
     else if (comp_ctx->use_prof_file) {
         PGO = PGOOptions(comp_ctx->use_prof_file, "", "", PGOOptions::IRUse);
     }
+#endif
 
 #ifdef DEBUG_PASS
     PassInstrumentationCallbacks PIC;

+ 9 - 0
core/iwasm/compilation/aot_llvm_extra2.cpp

@@ -4,8 +4,10 @@
  */
 
 #include <llvm-c/TargetMachine.h>
+#if LLVM_VERSION_MAJOR < 17
 #include <llvm/ADT/None.h>
 #include <llvm/ADT/Optional.h>
+#endif
 #include <llvm/IR/Instructions.h>
 #if LLVM_VERSION_MAJOR >= 14
 #include <llvm/MC/TargetRegistry.h>
@@ -18,6 +20,13 @@
 
 #include "aot_llvm_extra2.h"
 
+#if LLVM_VERSION_MAJOR >= 17
+namespace llvm {
+template<typename T>
+using Optional = std::optional<T>;
+}
+#endif
+
 static llvm::Optional<llvm::Reloc::Model>
 convert(LLVMRelocMode reloc_mode)
 {

+ 9 - 0
core/iwasm/compilation/aot_orc_extra.cpp

@@ -8,8 +8,10 @@
 #include "llvm-c/OrcEE.h"
 #include "llvm-c/TargetMachine.h"
 
+#if LLVM_VERSION_MAJOR < 17
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
+#endif
 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
@@ -21,6 +23,13 @@
 #include "aot_orc_extra.h"
 #include "aot.h"
 
+#if LLVM_VERSION_MAJOR >= 17
+namespace llvm {
+template<typename T>
+using Optional = std::optional<T>;
+}
+#endif
+
 using namespace llvm;
 using namespace llvm::orc;
 using GlobalValueSet = std::set<const GlobalValue *>;

+ 197 - 38
core/iwasm/compilation/simd/simd_floating_point.c

@@ -217,10 +217,9 @@ aot_compile_simd_f64x2_nearest(AOTCompContext *comp_ctx,
 
 static bool
 simd_float_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-               FloatArithmetic arith_op, LLVMTypeRef vector_type)
+               FloatArithmetic op, LLVMTypeRef vector_type)
 {
-    LLVMValueRef lhs, rhs, result;
-    LLVMRealPredicate op = FLOAT_MIN == arith_op ? LLVMRealULT : LLVMRealUGT;
+    LLVMValueRef lhs, rhs, cmp, selected;
 
     if (!(rhs =
               simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
@@ -229,47 +228,122 @@ simd_float_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return false;
     }
 
-    if (!(result = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) {
+    if (!(cmp = LLVMBuildFCmp(comp_ctx->builder,
+                              op == FLOAT_MIN ? LLVMRealOLT : LLVMRealOGT, rhs,
+                              lhs, "cmp"))) {
         HANDLE_FAILURE("LLVMBuildFCmp");
         return false;
     }
 
-    if (!(result =
-              LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) {
+    if (!(selected =
+              LLVMBuildSelect(comp_ctx->builder, cmp, rhs, lhs, "selected"))) {
         HANDLE_FAILURE("LLVMBuildSelect");
         return false;
     }
 
-    return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+    return simd_bitcast_and_push_v128(comp_ctx, func_ctx, selected, "result");
 }
 
-/*TODO: sugggest non-IA platforms check with "llvm.minimum.*" and
- * "llvm.maximum.*" firstly */
-bool
-aot_compile_simd_f32x4_min_max(AOTCompContext *comp_ctx,
-                               AOTFuncContext *func_ctx, bool run_min)
+static bool
+simd_float_min(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+               LLVMTypeRef vector_type)
 {
-    return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX,
-                          V128_f32x4_TYPE);
-}
+    LLVMValueRef lhs, rhs, lhs_nan, rhs_nan, olt_ret, ogt_ret, or_ret, ret1,
+        ret2, ret3, ret4;
 
-bool
-aot_compile_simd_f64x2_min_max(AOTCompContext *comp_ctx,
-                               AOTFuncContext *func_ctx, bool run_min)
-{
-    return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX,
-                          V128_f64x2_TYPE);
+    if (!(rhs =
+              simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
+        || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
+                                             "lhs"))) {
+        return false;
+    }
+
+    if (!(lhs_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, lhs, lhs,
+                                  "lhs_nan"))) {
+        HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealUNO");
+        return false;
+    }
+
+    if (!(rhs_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, rhs, rhs,
+                                  "rhs_nan"))) {
+        HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealUNO");
+        return false;
+    }
+
+    if (!(olt_ret = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLT, lhs, rhs,
+                                  "olt_ret"))) {
+        HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealOLT");
+        return false;
+    }
+
+    if (!(ogt_ret = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGT, lhs, rhs,
+                                  "ogt_ret"))) {
+        HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealOGT");
+        return false;
+    }
+
+    /* lhs or rhs */
+    {
+        LLVMValueRef integer_l, integer_r, integer_or;
+
+        if (!(integer_l = LLVMBuildBitCast(comp_ctx->builder, lhs,
+                                           V128_i64x2_TYPE, "lhs_to_int"))) {
+            HANDLE_FAILURE("LLVMBuildBitCas");
+            return false;
+        }
+
+        if (!(integer_r = LLVMBuildBitCast(comp_ctx->builder, rhs,
+                                           V128_i64x2_TYPE, "rhs_to_int"))) {
+            HANDLE_FAILURE("LLVMBuildBitCas");
+            return false;
+        }
+
+        if (!(integer_or =
+                  LLVMBuildOr(comp_ctx->builder, integer_l, integer_r, "or"))) {
+            HANDLE_FAILURE("LLVMBuildOr");
+            return false;
+        }
+
+        if (!(or_ret = LLVMBuildBitCast(comp_ctx->builder, integer_or,
+                                        vector_type, "holder"))) {
+            HANDLE_FAILURE("LLVMBuildBitCast");
+            return false;
+        }
+    }
+
+    if (!(ret1 = LLVMBuildSelect(comp_ctx->builder, olt_ret, lhs, or_ret,
+                                 "sel_olt"))) {
+        HANDLE_FAILURE("LLVMBuildSelect");
+        return false;
+    }
+
+    if (!(ret2 = LLVMBuildSelect(comp_ctx->builder, ogt_ret, rhs, ret1,
+                                 "sel_ogt"))) {
+        HANDLE_FAILURE("LLVMBuildSelect");
+        return false;
+    }
+
+    if (!(ret3 = LLVMBuildSelect(comp_ctx->builder, lhs_nan, lhs, ret2,
+                                 "sel_lhs_nan"))) {
+        HANDLE_FAILURE("LLVMBuildSelect");
+        return false;
+    }
+
+    if (!(ret4 = LLVMBuildSelect(comp_ctx->builder, rhs_nan, rhs, ret3,
+                                 "sel_rhs_nan"))) {
+        HANDLE_FAILURE("LLVMBuildSelect");
+        return false;
+    }
+
+    return simd_bitcast_and_push_v128(comp_ctx, func_ctx, ret4, "result");
 }
 
 static bool
-simd_float_pmin_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                    LLVMTypeRef vector_type, const char *intrinsic)
+simd_float_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+               LLVMTypeRef vector_type)
 {
-    LLVMValueRef lhs, rhs, result;
-    LLVMTypeRef param_types[2];
-
-    param_types[0] = vector_type;
-    param_types[1] = vector_type;
+    LLVMValueRef lhs, rhs, lhs_nan, rhs_nan, olt_ret, ogt_ret, and_ret, ret1,
+        ret2, ret3, ret4;
 
     if (!(rhs =
               simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
@@ -278,31 +352,116 @@ simd_float_pmin_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return false;
     }
 
-    if (!(result =
-              aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
-                                      vector_type, param_types, 2, lhs, rhs))) {
+    if (!(lhs_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, lhs, lhs,
+                                  "lhs_nan"))) {
+        HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealUNO");
         return false;
     }
 
-    return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
+    if (!(rhs_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, rhs, rhs,
+                                  "rhs_nan"))) {
+        HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealUNO");
+        return false;
+    }
+
+    if (!(olt_ret = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLT, lhs, rhs,
+                                  "olt_ret"))) {
+        HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealOLT");
+        return false;
+    }
+
+    if (!(ogt_ret = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGT, lhs, rhs,
+                                  "ogt_ret"))) {
+        HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealOGT");
+        return false;
+    }
+
+    /* lhs and rhs */
+    {
+        LLVMValueRef integer_l, integer_r, integer_and;
+
+        if (!(integer_l = LLVMBuildBitCast(comp_ctx->builder, lhs,
+                                           V128_i64x2_TYPE, "lhs_to_int"))) {
+            HANDLE_FAILURE("LLVMBuildBitCas");
+            return false;
+        }
+
+        if (!(integer_r = LLVMBuildBitCast(comp_ctx->builder, rhs,
+                                           V128_i64x2_TYPE, "rhs_to_int"))) {
+            HANDLE_FAILURE("LLVMBuildBitCas");
+            return false;
+        }
+
+        if (!(integer_and = LLVMBuildAnd(comp_ctx->builder, integer_l,
+                                         integer_r, "and"))) {
+            HANDLE_FAILURE("LLVMBuildOr");
+            return false;
+        }
+
+        if (!(and_ret = LLVMBuildBitCast(comp_ctx->builder, integer_and,
+                                         vector_type, "holder"))) {
+            HANDLE_FAILURE("LLVMBuildBitCast");
+            return false;
+        }
+    }
+
+    if (!(ret1 = LLVMBuildSelect(comp_ctx->builder, ogt_ret, lhs, and_ret,
+                                 "sel_ogt"))) {
+        HANDLE_FAILURE("LLVMBuildSelect");
+        return false;
+    }
+
+    if (!(ret2 = LLVMBuildSelect(comp_ctx->builder, olt_ret, rhs, ret1,
+                                 "sel_olt"))) {
+        HANDLE_FAILURE("LLVMBuildSelect");
+        return false;
+    }
+
+    if (!(ret3 = LLVMBuildSelect(comp_ctx->builder, lhs_nan, lhs, ret2,
+                                 "sel_lhs_nan"))) {
+        HANDLE_FAILURE("LLVMBuildSelect");
+        return false;
+    }
+
+    if (!(ret4 = LLVMBuildSelect(comp_ctx->builder, rhs_nan, rhs, ret3,
+                                 "sel_rhs_nan"))) {
+        HANDLE_FAILURE("LLVMBuildSelect");
+        return false;
+    }
+
+    return simd_bitcast_and_push_v128(comp_ctx, func_ctx, ret4, "result");
+}
+
+bool
+aot_compile_simd_f32x4_min_max(AOTCompContext *comp_ctx,
+                               AOTFuncContext *func_ctx, bool run_min)
+{
+    return run_min ? simd_float_min(comp_ctx, func_ctx, V128_f32x4_TYPE)
+                   : simd_float_max(comp_ctx, func_ctx, V128_f32x4_TYPE);
+}
+
+bool
+aot_compile_simd_f64x2_min_max(AOTCompContext *comp_ctx,
+                               AOTFuncContext *func_ctx, bool run_min)
+{
+    return run_min ? simd_float_min(comp_ctx, func_ctx, V128_f64x2_TYPE)
+                   : simd_float_max(comp_ctx, func_ctx, V128_f64x2_TYPE);
 }
 
 bool
 aot_compile_simd_f32x4_pmin_pmax(AOTCompContext *comp_ctx,
                                  AOTFuncContext *func_ctx, bool run_min)
 {
-    return simd_float_pmin_max(comp_ctx, func_ctx, V128_f32x4_TYPE,
-                               run_min ? "llvm.minnum.v4f32"
-                                       : "llvm.maxnum.v4f32");
+    return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX,
+                          V128_f32x4_TYPE);
 }
 
 bool
 aot_compile_simd_f64x2_pmin_pmax(AOTCompContext *comp_ctx,
                                  AOTFuncContext *func_ctx, bool run_min)
 {
-    return simd_float_pmin_max(comp_ctx, func_ctx, V128_f64x2_TYPE,
-                               run_min ? "llvm.minnum.v2f64"
-                                       : "llvm.maxnum.v2f64");
+    return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX,
+                          V128_f64x2_TYPE);
 }
 
 bool

+ 8 - 0
core/iwasm/fast-jit/fe/jit_emit_numberic.c

@@ -298,7 +298,15 @@ fail:
 
 /* macros for integer binary operations (ibinop) */
 
+#if defined(__GNUC__)
+#define NO_SANITIZER_INTEGER \
+    __attribute__((no_sanitize("signed-integer-overflow")))
+#else
+#define NO_SANITIZER_INTEGER
+#endif
+
 #define __DEF_BI_INT_CONST_OPS(bits, opname, op)                               \
+    NO_SANITIZER_INTEGER                                                       \
     static int##bits do_i##bits##_const_##opname(int##bits lhs, int##bits rhs) \
     {                                                                          \
         return lhs op rhs;                                                     \

+ 152 - 1
core/iwasm/include/wasm_export.h

@@ -311,7 +311,7 @@ wasm_runtime_is_xip_file(const uint8_t *buf, uint32_t size);
 /**
  * Callback to load a module file into a buffer in multi-module feature
  */
-typedef bool (*module_reader)(const char *module_name,
+typedef bool (*module_reader)(package_type_t module_type,const char *module_name,
                               uint8_t **p_buffer, uint32_t *p_size);
 
 /**
@@ -894,6 +894,27 @@ wasm_runtime_set_exception(wasm_module_inst_t module_inst,
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_clear_exception(wasm_module_inst_t module_inst);
 
+/**
+ * Terminate the WASM module instance.
+ *
+ * This function causes the module instance fail as if it raised a trap.
+ *
+ * This is intended to be used in situations like:
+ *
+ *  - A thread is executing the WASM module instance
+ *    (eg. it's in the middle of `wasm_application_execute_main`)
+ *
+ *  - Another thread has a copy of `wasm_module_inst_t` of
+ *    the module instance and wants to terminate it asynchronously.
+ *
+ * This function is provided only when WAMR is built with threading enabled.
+ * (`WASM_ENABLE_THREAD_MGR=1`)
+ *
+ * @param module_inst the WASM module instance
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_terminate(wasm_module_inst_t module_inst);
+
 /**
  * Set custom data to WASM module instance.
  * Note:
@@ -1439,6 +1460,136 @@ WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_is_import_global_linked(const char *module_name,
                                      const char *global_name);
 
+typedef enum {
+    INTERNAL_ERROR,
+    MAX_SIZE_REACHED,
+} enlarge_memory_error_reason_t;
+
+typedef void (*enlarge_memory_error_callback_t)(
+    uint32_t inc_page_count, uint64_t current_memory_size,
+    uint32_t memory_index, enlarge_memory_error_reason_t failure_reason,
+    wasm_module_inst_t instance, wasm_exec_env_t exec_env,
+    void* user_data);
+
+/**
+ * Setup callback invoked when memory.grow fails
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_enlarge_mem_error_callback(
+    const enlarge_memory_error_callback_t callback, void *user_data);
+
+/*
+ * module instance context APIs
+ *   wasm_runtime_create_context_key
+ *   wasm_runtime_destroy_context_key
+ *   wasm_runtime_set_context
+ *   wasm_runtime_set_context_spread
+ *   wasm_runtime_get_context
+ *
+ * This set of APIs is intended to be used by an embedder which provides
+ * extra sets of native functions, which need per module instance state
+ * and are maintained outside of the WAMR tree.
+ *
+ * It's modelled after the pthread specific API.
+ *
+ * wasm_runtime_set_context_spread is similar to
+ * wasm_runtime_set_context, except that
+ * wasm_runtime_set_context_spread applies the change
+ * to all threads in the cluster.
+ * It's an undefined behavior if multiple threads in a cluster call
+ * wasm_runtime_set_context_spread on the same key
+ * simultaneously. It's a caller's resposibility to perform necessary
+ * serialization if necessary. For example:
+ *
+ * if (wasm_runtime_get_context(inst, key) == NULL) {
+ *     newctx = alloc_and_init(...);
+ *     lock(some_lock);
+ *     if (wasm_runtime_get_context(inst, key) == NULL) {
+ *         // this thread won the race
+ *         wasm_runtime_set_context_spread(inst, key, newctx);
+ *         newctx = NULL;
+ *     }
+ *     unlock(some_lock);
+ *     if (newctx != NULL) {
+ *         // this thread lost the race, free it
+ *         cleanup_and_free(newctx);
+ *     }
+ * }
+ *
+ * Note: dynamic key create/destroy while instances are live is not
+ * implemented as of writing this.
+ * it's caller's resposibility to ensure destorying all module instances
+ * before calling wasm_runtime_create_context_key or
+ * wasm_runtime_destroy_context_key.
+ * otherwise, it's an undefined behavior.
+ *
+ * Note about threads:
+ * - When spawning a thread, the contexts (the pointers given to
+ *   wasm_runtime_set_context) are copied from the parent
+ *   instance.
+ * - The destructor is called only on the main instance.
+ */
+
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_create_context_key(
+    void (*dtor)(wasm_module_inst_t inst, void *ctx));
+
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy_context_key(void *key);
+
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_context(wasm_module_inst_t inst, void *key,
+                                         void *ctx);
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_context_spread(wasm_module_inst_t inst, void *key,
+                                         void *ctx);
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_context(wasm_module_inst_t inst, void *key);
+
+/*
+ * wasm_runtime_begin_blocking_op/wasm_runtime_end_blocking_op
+ *
+ * These APIs are intended to be used by the implementations of
+ * host functions. It wraps an operation which possibly blocks for long
+ * to prepare for async termination.
+ *
+ * eg.
+ *
+ *   if (!wasm_runtime_begin_blocking_op(exec_env)) {
+ *       return EINTR;
+ *   }
+ *   ret = possibly_blocking_op();
+ *   wasm_runtime_end_blocking_op(exec_env);
+ *   return ret;
+ *
+ * If threading support (WASM_ENABLE_THREAD_MGR) is not enabled,
+ * these functions are no-op.
+ *
+ * If the underlying platform support (OS_ENABLE_WAKEUP_BLOCKING_OP) is
+ * not available, these functions are no-op. In that case, the runtime
+ * might not terminate a blocking thread in a timely manner.
+ *
+ * If the underlying platform support is available, it's used to wake up
+ * the thread for async termination. The expectation here is that a
+ * `os_wakeup_blocking_op` call makes the blocking operation
+ * (`possibly_blocking_op` in the above example) return in a timely manner.
+ *
+ * The actual wake up mechanism used by `os_wakeup_blocking_op` is
+ * platform-dependent. It might impose some platform-dependent restrictions
+ * on the implementation of the blocking opearation.
+ *
+ * For example, on POSIX-like platforms, a signal (by default SIGUSR1) is
+ * used. The signal delivery configurations (eg. signal handler, signal mask,
+ * etc) for the signal are set up by the runtime. You can change the signal
+ * to use for this purpose by calling os_set_signal_number_for_blocking_op
+ * before the runtime initialization.
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_begin_blocking_op(wasm_exec_env_t exec_env);
+
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_end_blocking_op(wasm_exec_env_t exec_env);
+
 /* clang-format on */
 
 #ifdef __cplusplus

+ 2 - 3
core/iwasm/interpreter/wasm_interp_classic.c

@@ -1418,6 +1418,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 while (node_cache) {
                     node_next = bh_list_elem_next(node_cache);
                     if (node_cache->br_table_op_addr == frame_ip - 1) {
+                        if (lidx > node_cache->br_count)
+                            lidx = node_cache->br_count;
                         depth = node_cache->br_depths[lidx];
                         goto label_pop_csp_n;
                     }
@@ -4209,7 +4211,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
     unsigned i;
     bool copy_argv_from_frame = true;
-    char exception[EXCEPTION_BUF_LEN];
 
     if (argc < function->param_cell_num) {
         char buf[128];
@@ -4342,8 +4343,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
             wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
         }
 #endif
-        wasm_copy_exception(module_inst, exception);
-        LOG_DEBUG("meet an exception %s", exception);
     }
 
     wasm_exec_env_set_cur_frame(exec_env, prev_frame);

+ 0 - 3
core/iwasm/interpreter/wasm_interp_fast.c

@@ -3945,7 +3945,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     /* This frame won't be used by JITed code, so only allocate interp
        frame here.  */
     unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
-    char exception[EXCEPTION_BUF_LEN];
 
     if (argc < function->param_cell_num) {
         char buf[128];
@@ -4030,8 +4029,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
             wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
         }
 #endif
-        wasm_copy_exception(module_inst, exception);
-        LOG_DEBUG("meet an exception %s", exception);
     }
 
     wasm_exec_env_set_cur_frame(exec_env, prev_frame);

+ 35 - 208
core/iwasm/interpreter/wasm_loader.c

@@ -694,34 +694,10 @@ wasm_loader_find_export(const WASMModule *module, const char *module_name,
                         const char *field_name, uint8 export_kind,
                         char *error_buf, uint32 error_buf_size)
 {
-    WASMExport *export;
-    uint32 i;
-
-    for (i = 0, export = module->exports; i < module->export_count;
-         ++i, ++export) {
-        /**
-         * need to consider a scenario that different kinds of exports
-         * may have the same name, like
-         * (table (export "m1" "exported") 10 funcref)
-         * (memory (export "m1" "exported") 10)
-         **/
-        if (export->kind == export_kind && !strcmp(field_name, export->name)) {
-            break;
-        }
-    }
-
-    if (i == module->export_count) {
-        LOG_DEBUG("can not find an export %d named %s in the module %s",
-                  export_kind, field_name, module_name);
-        set_error_buf(error_buf, error_buf_size,
-                      "unknown import or incompatible import type");
-        return NULL;
-    }
-
-    (void)module_name;
-
-    /* since there is a validation in load_export_section(), it is for sure
-     * export->index is valid*/
+    WASMExport *export =
+        loader_find_export((WASMModuleCommon *)module, module_name, field_name,
+                           export_kind, error_buf, error_buf_size);
+    ;
     return export;
 }
 #endif
@@ -912,152 +888,6 @@ wasm_loader_resolve_global(const char *module_name, const char *global_name,
     return global;
 }
 
-static WASMModule *
-search_sub_module(const WASMModule *parent_module, const char *sub_module_name)
-{
-    WASMRegisteredModule *node =
-        bh_list_first_elem(parent_module->import_module_list);
-    while (node && strcmp(sub_module_name, node->module_name)) {
-        node = bh_list_elem_next(node);
-    }
-    return node ? (WASMModule *)node->module : NULL;
-}
-
-static bool
-register_sub_module(const WASMModule *parent_module,
-                    const char *sub_module_name, WASMModule *sub_module)
-{
-    /* register sub_module into its parent sub module list */
-    WASMRegisteredModule *node = NULL;
-    bh_list_status ret;
-
-    if (search_sub_module(parent_module, sub_module_name)) {
-        LOG_DEBUG("%s has been registered in its parent", sub_module_name);
-        return true;
-    }
-
-    node = loader_malloc(sizeof(WASMRegisteredModule), NULL, 0);
-    if (!node) {
-        return false;
-    }
-
-    node->module_name = sub_module_name;
-    node->module = (WASMModuleCommon *)sub_module;
-    ret = bh_list_insert(parent_module->import_module_list, node);
-    bh_assert(BH_LIST_SUCCESS == ret);
-    (void)ret;
-    return true;
-}
-
-static WASMModule *
-load_depended_module(const WASMModule *parent_module,
-                     const char *sub_module_name, char *error_buf,
-                     uint32 error_buf_size)
-{
-    WASMModule *sub_module = NULL;
-    bool ret = false;
-    uint8 *buffer = NULL;
-    uint32 buffer_size = 0;
-    const module_reader reader = wasm_runtime_get_module_reader();
-    const module_destroyer destroyer = wasm_runtime_get_module_destroyer();
-
-    /* check the registered module list of the parent */
-    sub_module = search_sub_module(parent_module, sub_module_name);
-    if (sub_module) {
-        LOG_DEBUG("%s has been loaded before", sub_module_name);
-        return sub_module;
-    }
-
-    /* check the global registered module list */
-    sub_module =
-        (WASMModule *)wasm_runtime_find_module_registered(sub_module_name);
-    if (sub_module) {
-        LOG_DEBUG("%s has been loaded", sub_module_name);
-        goto register_sub_module;
-    }
-
-    LOG_VERBOSE("loading %s", sub_module_name);
-
-    if (!reader) {
-        set_error_buf_v(error_buf, error_buf_size,
-                        "no sub module reader to load %s", sub_module_name);
-        return NULL;
-    }
-
-    /* start to maintain a loading module list */
-    ret = wasm_runtime_is_loading_module(sub_module_name);
-    if (ret) {
-        set_error_buf_v(error_buf, error_buf_size,
-                        "found circular dependency on %s", sub_module_name);
-        return NULL;
-    }
-
-    ret = wasm_runtime_add_loading_module(sub_module_name, error_buf,
-                                          error_buf_size);
-    if (!ret) {
-        LOG_DEBUG("can not add %s into loading module list\n", sub_module_name);
-        return NULL;
-    }
-
-    ret = reader(sub_module_name, &buffer, &buffer_size);
-    if (!ret) {
-        LOG_DEBUG("read the file of %s failed", sub_module_name);
-        set_error_buf_v(error_buf, error_buf_size, "unknown import",
-                        sub_module_name);
-        goto delete_loading_module;
-    }
-
-    sub_module =
-        wasm_loader_load(buffer, buffer_size, false, error_buf, error_buf_size);
-    if (!sub_module) {
-        LOG_DEBUG("error: can not load the sub_module %s", sub_module_name);
-        /* others will be destroyed in runtime_destroy() */
-        goto destroy_file_buffer;
-    }
-
-    wasm_runtime_delete_loading_module(sub_module_name);
-
-    /* register on a global list */
-    ret = wasm_runtime_register_module_internal(
-        sub_module_name, (WASMModuleCommon *)sub_module, buffer, buffer_size,
-        error_buf, error_buf_size);
-    if (!ret) {
-        LOG_DEBUG("error: can not register module %s globally\n",
-                  sub_module_name);
-        /* others will be unloaded in runtime_destroy() */
-        goto unload_module;
-    }
-
-    /* register into its parent list */
-register_sub_module:
-    ret = register_sub_module(parent_module, sub_module_name, sub_module);
-    if (!ret) {
-        set_error_buf_v(error_buf, error_buf_size,
-                        "failed to register sub module %s", sub_module_name);
-        /* since it is in the global module list, no need to
-         * unload the module. the runtime_destroy() will do it
-         */
-        return NULL;
-    }
-
-    return sub_module;
-
-unload_module:
-    wasm_loader_unload(sub_module);
-
-destroy_file_buffer:
-    if (destroyer) {
-        destroyer(buffer, buffer_size);
-    }
-    else {
-        LOG_WARNING("need to release the reading buffer of %s manually",
-                    sub_module_name);
-    }
-
-delete_loading_module:
-    wasm_runtime_delete_loading_module(sub_module_name);
-    return NULL;
-}
 #endif /* end of WASM_ENABLE_MULTI_MODULE */
 
 static bool
@@ -1104,8 +934,9 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end,
 #if WASM_ENABLE_MULTI_MODULE != 0
     else {
         if (!wasm_runtime_is_built_in_module(sub_module_name)) {
-            sub_module = load_depended_module(parent_module, sub_module_name,
-                                              error_buf, error_buf_size);
+            sub_module = (WASMModule *)wasm_runtime_load_depended_module(
+                (WASMModuleCommon *)parent_module, sub_module_name, error_buf,
+                error_buf_size);
             if (!sub_module) {
                 return false;
             }
@@ -1193,8 +1024,9 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
 
 #if WASM_ENABLE_MULTI_MODULE != 0
     if (!wasm_runtime_is_built_in_module(sub_module_name)) {
-        sub_module = load_depended_module(parent_module, sub_module_name,
-                                          error_buf, error_buf_size);
+        sub_module = (WASMModule *)wasm_runtime_load_depended_module(
+            (WASMModuleCommon *)parent_module, sub_module_name, error_buf,
+            error_buf_size);
         if (!sub_module) {
             return false;
         }
@@ -1327,8 +1159,9 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
 
 #if WASM_ENABLE_MULTI_MODULE != 0
     if (!wasm_runtime_is_built_in_module(sub_module_name)) {
-        sub_module = load_depended_module(parent_module, sub_module_name,
-                                          error_buf, error_buf_size);
+        sub_module = (WASMModule *)wasm_runtime_load_depended_module(
+            (WASMModuleCommon *)parent_module, sub_module_name, error_buf,
+            error_buf_size);
         if (!sub_module) {
             return false;
         }
@@ -1427,8 +1260,9 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
 #if WASM_ENABLE_MULTI_MODULE != 0
     if (!global->is_linked
         && !wasm_runtime_is_built_in_module(sub_module_name)) {
-        sub_module = load_depended_module(parent_module, sub_module_name,
-                                          error_buf, error_buf_size);
+        sub_module = (WASMModule *)wasm_runtime_load_depended_module(
+            (WASMModuleCommon *)parent_module, sub_module_name, error_buf,
+            error_buf_size);
         if (!sub_module) {
             return false;
         }
@@ -5476,6 +5310,7 @@ wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf,
     return true;
 }
 
+#if WASM_ENABLE_FAST_INTERP == 0
 static bool
 wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt,
                                uint8 type_push, uint8 type_pop, char *error_buf,
@@ -5490,6 +5325,7 @@ wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt,
         return false;
     return true;
 }
+#endif
 
 static bool
 wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type,
@@ -6166,27 +6002,6 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
     return true;
 }
 
-static bool
-wasm_loader_push_pop_frame_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
-                                  uint8 type_push, uint8 type_pop,
-                                  bool disable_emit, int16 operand_offset,
-                                  char *error_buf, uint32 error_buf_size)
-{
-    uint8 i;
-
-    for (i = 0; i < pop_cnt; i++) {
-        if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf,
-                                          error_buf_size))
-            return false;
-    }
-    if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit,
-                                       operand_offset, error_buf,
-                                       error_buf_size))
-        return false;
-
-    return true;
-}
-
 static bool
 wasm_loader_push_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
                                   bool disable_emit, int16 operand_offset,
@@ -6220,12 +6035,24 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
                                       bool disable_emit, int16 operand_offset,
                                       char *error_buf, uint32 error_buf_size)
 {
-    if (!wasm_loader_push_pop_frame_offset(ctx, pop_cnt, type_push, type_pop,
-                                           disable_emit, operand_offset,
-                                           error_buf, error_buf_size))
+    uint8 i;
+
+    for (i = 0; i < pop_cnt; i++) {
+        if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf,
+                                          error_buf_size))
+            return false;
+
+        if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf,
+                                       error_buf_size))
+            return false;
+    }
+
+    if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit,
+                                       operand_offset, error_buf,
+                                       error_buf_size))
         return false;
-    if (!wasm_loader_push_pop_frame_ref(ctx, pop_cnt, type_push, type_pop,
-                                        error_buf, error_buf_size))
+
+    if (!wasm_loader_push_frame_ref(ctx, type_push, error_buf, error_buf_size))
         return false;
 
     return true;

+ 19 - 24
core/iwasm/interpreter/wasm_mini_loader.c

@@ -3937,6 +3937,7 @@ wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf,
     return true;
 }
 
+#if WASM_ENABLE_FAST_INTERP == 0
 static bool
 wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt,
                                uint8 type_push, uint8 type_pop, char *error_buf,
@@ -3951,6 +3952,7 @@ wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt,
         return false;
     return true;
 }
+#endif
 
 static bool
 wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type,
@@ -4608,25 +4610,6 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
     return true;
 }
 
-static bool
-wasm_loader_push_pop_frame_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
-                                  uint8 type_push, uint8 type_pop,
-                                  bool disable_emit, int16 operand_offset,
-                                  char *error_buf, uint32 error_buf_size)
-{
-    for (int i = 0; i < pop_cnt; i++) {
-        if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf,
-                                          error_buf_size))
-            return false;
-    }
-    if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit,
-                                       operand_offset, error_buf,
-                                       error_buf_size))
-        return false;
-
-    return true;
-}
-
 static bool
 wasm_loader_push_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
                                   bool disable_emit, int16 operand_offset,
@@ -4660,12 +4643,24 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
                                       bool disable_emit, int16 operand_offset,
                                       char *error_buf, uint32 error_buf_size)
 {
-    if (!wasm_loader_push_pop_frame_offset(ctx, pop_cnt, type_push, type_pop,
-                                           disable_emit, operand_offset,
-                                           error_buf, error_buf_size))
+    uint8 i;
+
+    for (i = 0; i < pop_cnt; i++) {
+        if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf,
+                                          error_buf_size))
+            return false;
+
+        if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf,
+                                       error_buf_size))
+            return false;
+    }
+
+    if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit,
+                                       operand_offset, error_buf,
+                                       error_buf_size))
         return false;
-    if (!wasm_loader_push_pop_frame_ref(ctx, pop_cnt, type_push, type_pop,
-                                        error_buf, error_buf_size))
+
+    if (!wasm_loader_push_frame_ref(ctx, type_push, error_buf, error_buf_size))
         return false;
 
     return true;

+ 19 - 80
core/iwasm/interpreter/wasm_runtime.c

@@ -51,11 +51,15 @@ set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...)
 }
 
 WASMModule *
-wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size)
+wasm_load(uint8 *buf, uint32 size,
+#if WASM_ENABLE_MULTI_MODULE != 0
+          bool main_module,
+#endif
+          char *error_buf, uint32 error_buf_size)
 {
     return wasm_loader_load(buf, size,
 #if WASM_ENABLE_MULTI_MODULE != 0
-                            true,
+                            main_module,
 #endif
                             error_buf, error_buf_size);
 }
@@ -1266,78 +1270,6 @@ execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     return ret;
 }
 
-#if WASM_ENABLE_MULTI_MODULE != 0
-static bool
-sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
-                       uint32 stack_size, uint32 heap_size, char *error_buf,
-                       uint32 error_buf_size)
-{
-    bh_list *sub_module_inst_list = module_inst->e->sub_module_inst_list;
-    WASMRegisteredModule *sub_module_list_node =
-        bh_list_first_elem(module->import_module_list);
-
-    while (sub_module_list_node) {
-        WASMSubModInstNode *sub_module_inst_list_node = NULL;
-        WASMModule *sub_module = (WASMModule *)sub_module_list_node->module;
-        WASMModuleInstance *sub_module_inst = NULL;
-
-        sub_module_inst =
-            wasm_instantiate(sub_module, NULL, NULL, stack_size, heap_size,
-                             error_buf, error_buf_size);
-        if (!sub_module_inst) {
-            LOG_DEBUG("instantiate %s failed",
-                      sub_module_list_node->module_name);
-            goto failed;
-        }
-
-        sub_module_inst_list_node = runtime_malloc(sizeof(WASMSubModInstNode),
-                                                   error_buf, error_buf_size);
-        if (!sub_module_inst_list_node) {
-            LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d",
-                      sizeof(WASMSubModInstNode));
-            goto failed;
-        }
-
-        sub_module_inst_list_node->module_inst = sub_module_inst;
-        sub_module_inst_list_node->module_name =
-            sub_module_list_node->module_name;
-        bh_list_status ret =
-            bh_list_insert(sub_module_inst_list, sub_module_inst_list_node);
-        bh_assert(BH_LIST_SUCCESS == ret);
-        (void)ret;
-
-        sub_module_list_node = bh_list_elem_next(sub_module_list_node);
-
-        continue;
-    failed:
-        if (sub_module_inst_list_node) {
-            bh_list_remove(sub_module_inst_list, sub_module_inst_list_node);
-            wasm_runtime_free(sub_module_inst_list_node);
-        }
-
-        if (sub_module_inst)
-            wasm_deinstantiate(sub_module_inst, false);
-        return false;
-    }
-
-    return true;
-}
-
-static void
-sub_module_deinstantiate(WASMModuleInstance *module_inst)
-{
-    bh_list *list = module_inst->e->sub_module_inst_list;
-    WASMSubModInstNode *node = bh_list_first_elem(list);
-    while (node) {
-        WASMSubModInstNode *next_node = bh_list_elem_next(node);
-        bh_list_remove(list, node);
-        wasm_deinstantiate(node->module_inst, false);
-        wasm_runtime_free(node);
-        node = next_node;
-    }
-}
-#endif
-
 static bool
 check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
                     uint32 error_buf_size)
@@ -1714,8 +1646,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
 #if WASM_ENABLE_MULTI_MODULE != 0
     module_inst->e->sub_module_inst_list =
         &module_inst->e->sub_module_inst_list_head;
-    ret = sub_module_instantiate(module, module_inst, stack_size, heap_size,
-                                 error_buf, error_buf_size);
+    ret = wasm_runtime_sub_module_instantiate(
+        (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst,
+        stack_size, heap_size, error_buf, error_buf_size);
     if (!ret) {
         LOG_DEBUG("build a sub module list failed");
         goto fail;
@@ -2198,7 +2131,8 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
 #endif
 
 #if WASM_ENABLE_MULTI_MODULE != 0
-    sub_module_deinstantiate(module_inst);
+    wasm_runtime_sub_module_deinstantiate(
+        (WASMModuleInstanceCommon *)module_inst);
 #endif
 
     if (module_inst->memory_count > 0)
@@ -2234,12 +2168,10 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
         wasm_runtime_free(module_inst->e->common.c_api_func_imports);
 
     if (!is_sub_inst) {
-#if WASM_ENABLE_LIBC_WASI != 0
-        wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
-#endif
 #if WASM_ENABLE_WASI_NN != 0
         wasi_nn_destroy(module_inst);
 #endif
+        wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
     }
 
     wasm_runtime_free(module_inst);
@@ -2401,6 +2333,9 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
     /* set thread handle and stack boundary */
     wasm_exec_env_set_thread_info(exec_env);
 
+    /* set exec env so it can be later retrieved from instance */
+    module_inst->e->common.cur_exec_env = exec_env;
+
     interp_call_wasm(module_inst, exec_env, function, argc, argv);
     return !wasm_copy_exception(module_inst, NULL);
 }
@@ -2981,6 +2916,7 @@ wasm_interp_create_call_stack(struct WASMExecEnv *exec_env)
         total_len +=                                                      \
             wasm_runtime_dump_line_buf_impl(line_buf, print, &buf, &len); \
         if ((!print) && buf && (len == 0)) {                              \
+            exception_unlock(module_inst);                                \
             return total_len;                                             \
         }                                                                 \
     } while (0)
@@ -3005,6 +2941,7 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf,
         return 0;
     }
 
+    exception_lock(module_inst);
     snprintf(line_buf, sizeof(line_buf), "\n");
     PRINT_OR_DUMP();
 
@@ -3013,6 +2950,7 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf,
         uint32 line_length, i;
 
         if (!bh_vector_get(module_inst->frames, n, &frame)) {
+            exception_unlock(module_inst);
             return 0;
         }
 
@@ -3043,6 +2981,7 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf,
     }
     snprintf(line_buf, sizeof(line_buf), "\n");
     PRINT_OR_DUMP();
+    exception_unlock(module_inst);
 
     return total_len + 1;
 }

+ 20 - 7
core/iwasm/interpreter/wasm_runtime.h

@@ -212,7 +212,10 @@ typedef struct CApiFuncImport {
 
 /* The common part of WASMModuleInstanceExtra and AOTModuleInstanceExtra */
 typedef struct WASMModuleInstanceExtraCommon {
+    void *contexts[WASM_MAX_INSTANCE_CONTEXTS];
     CApiFuncImport *c_api_func_imports;
+    /* pointer to the exec env currently used */
+    WASMExecEnv *cur_exec_env;
 #if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
     /* Disable bounds checks or not */
     bool disable_bounds_checks;
@@ -297,12 +300,8 @@ struct WASMModuleInstance {
        it denotes `AOTModule *` */
     DefPointer(WASMModule *, module);
 
-#if WASM_ENABLE_LIBC_WASI
-    /* WASI context */
-    DefPointer(WASIContext *, wasi_ctx);
-#else
-    DefPointer(void *, wasi_ctx);
-#endif
+    DefPointer(void *, used_to_be_wasi_ctx); /* unused */
+
     DefPointer(WASMExecEnv *, exec_env_singleton);
     /* Array of function pointers to import functions,
        not available in AOTModuleInstance */
@@ -397,7 +396,11 @@ wasm_get_func_code_end(WASMFunctionInstance *func)
 }
 
 WASMModule *
-wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size);
+wasm_load(uint8 *buf, uint32 size,
+#if WASM_ENABLE_MULTI_MODULE != 0
+          bool main_module,
+#endif
+          char *error_buf, uint32 error_buf_size);
 
 WASMModule *
 wasm_load_from_sections(WASMSection *section_list, char *error_buf,
@@ -668,6 +671,16 @@ void
 wasm_propagate_wasi_args(WASMModule *module);
 #endif
 
+#if WASM_ENABLE_THREAD_MGR != 0
+void
+exception_lock(WASMModuleInstance *module_inst);
+void
+exception_unlock(WASMModuleInstance *module_inst);
+#else
+#define exception_lock(module_inst) (void)(module_inst)
+#define exception_unlock(module_inst) (void)(module_inst)
+#endif
+
 #ifdef __cplusplus
 }
 #endif

+ 1 - 8
core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c

@@ -559,9 +559,6 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
     uint32 thread_handle;
     uint32 stack_size = 8192;
     int32 ret = -1;
-#if WASM_ENABLE_LIBC_WASI != 0
-    WASIContext *wasi_ctx;
-#endif
 
     bh_assert(module);
     bh_assert(module_inst);
@@ -588,11 +585,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
     wasm_runtime_set_custom_data_internal(
         new_module_inst, wasm_runtime_get_custom_data(module_inst));
 
-#if WASM_ENABLE_LIBC_WASI != 0
-    wasi_ctx = get_wasi_ctx(module_inst);
-    if (wasi_ctx)
-        wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
-#endif
+    wasm_native_inherit_contexts(new_module_inst, module_inst);
 
     if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
         goto fail;

+ 1 - 1
core/iwasm/libraries/lib-rats/lib_rats.cmake

@@ -23,7 +23,7 @@ include(FetchContent)
 set(RATS_BUILD_MODE "sgx"
     CACHE INTERNAL "Select build mode for librats(host|occlum|sgx|wasm)")
 set(RATS_INSTALL_PATH  "${CMAKE_BINARY_DIR}/librats" CACHE INTERNAL "")
-set(BUILD_SAMPLES OFF)
+set(BUILD_SAMPLES OFF CACHE BOOL "Disable de compilation of the librats samples" FORCE)
 
 FetchContent_Declare(
     librats

+ 1 - 8
core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c

@@ -80,9 +80,6 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
     int32 thread_id;
     uint32 stack_size = 8192;
     int32 ret = -1;
-#if WASM_ENABLE_LIBC_WASI != 0
-    WASIContext *wasi_ctx;
-#endif
 
     bh_assert(module);
     bh_assert(module_inst);
@@ -99,11 +96,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
     if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
         goto thread_preparation_fail;
 
-#if WASM_ENABLE_LIBC_WASI != 0
-    wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
-    if (wasi_ctx)
-        wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
-#endif
+    wasm_native_inherit_contexts(new_module_inst, module_inst);
 
     start_func = wasm_runtime_lookup_function(new_module_inst,
                                               THREAD_START_FUNCTION, NULL);

+ 66 - 0
core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh

@@ -0,0 +1,66 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+set -eo pipefail
+CC=${CC:=/opt/wasi-sdk/bin/clang}
+WAMR_DIR=../../../../..
+
+show_usage() {
+    echo "Usage: $0 [--sysroot PATH_TO_SYSROOT]"
+    echo "--sysroot PATH_TO_SYSROOT specify to build with custom sysroot for wasi-libc"
+}
+
+while [[ $# -gt 0 ]]; do
+    key="$1"
+    case $key in
+        --sysroot)
+            sysroot_path="$2"
+            shift
+            shift
+            ;;
+        --help)
+            show_usage
+            exit
+            ;;
+        *)
+            echo "Unknown option: $1"
+            exit 1
+            ;;
+    esac
+done
+
+rm -rf *.wasm
+rm -rf *.aot
+
+for test_c in *.c; do
+    test_wasm="$(basename $test_c .c).wasm"
+
+    if [[ -n "$sysroot_path" ]]; then 
+        if [ ! -d "$sysroot_path" ]; then 
+            echo "Directory $sysroot_path  doesn't exist. Aborting"
+            exit 1
+        fi
+        sysroot_command="--sysroot $sysroot_path"
+    fi
+    
+    echo "Compiling $test_c to $test_wasm"
+    $CC \
+        -target wasm32-wasi-threads \
+        -O2 \
+        -Wall \
+        -pthread \
+        -z stack-size=32768 \
+        -Wl,--export=__heap_base \
+        -Wl,--export=__data_end \
+        -Wl,--shared-memory,--max-memory=1966080 \
+        -Wl,--export=wasi_thread_start \
+        -Wl,--export=malloc \
+        -Wl,--export=free \
+        -Wl,--export=test \
+        $sysroot_command \
+        $test_c -o $test_wasm
+done

+ 34 - 0
core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c

@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <pthread.h>
+#include <errno.h>
+#include "mutex_common.h"
+
+void
+test()
+{
+    pthread_mutex_t mutex;
+
+    // Set mutex type to errorcheck. This type provides some additional checks
+    // (for example returns EDEADLK instead of deadlocking in some cases)
+    pthread_mutexattr_t mutex_attr;
+    pthread_mutexattr_init(&mutex_attr);
+    pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
+
+    pthread_mutex_init(&mutex, &mutex_attr);
+    pthread_mutexattr_destroy(&mutex_attr);
+
+    run_common_tests(&mutex);
+    fprintf(stderr, "Errorcheck mutex test is completed\n");
+    pthread_mutex_destroy(&mutex);
+}
+
+int
+main()
+{
+    test();
+    return 0;
+}

+ 3 - 0
core/iwasm/libraries/lib-wasi-threads/stress-test/manifest.json

@@ -0,0 +1,3 @@
+{
+    "name": "lib-wasi-threads stress tests"
+}

+ 229 - 0
core/iwasm/libraries/lib-wasi-threads/stress-test/mutex_common.h

@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef MUTEX_COMMON_H
+#define MUTEX_COMMON_H
+
+#include <pthread.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+enum Constants {
+    NUM_ITER = 250000,
+    NUM_THREADS = 12,
+    NUM_RETRY = 8,
+    RETRY_SLEEP_TIME_US = 1000,
+};
+
+// We're counting how many times each thread was called using this array
+// Main thread is also counted here so we need to make arrays bigger
+typedef struct {
+    int tids[NUM_THREADS + 1];
+    int calls[NUM_THREADS + 1];
+} StatCollector;
+
+typedef struct {
+    pthread_mutex_t *mutex;
+    StatCollector stat;
+    int counter;
+    bool is_sleeping;
+} MutexCounter;
+
+// This enum defines whether thread should sleep to increase contention
+enum SleepState {
+    NON_SLEEP = 0,
+    SLEEP = 1,
+};
+
+void
+mutex_counter_init(MutexCounter *mutex_counter, pthread_mutex_t *mutex,
+                   enum SleepState is_sleeping)
+{
+    memset(mutex_counter, 0, sizeof(*mutex_counter));
+    mutex_counter->mutex = mutex;
+    mutex_counter->is_sleeping = is_sleeping;
+}
+
+// This function spawns the thread using exponential retries if it receives
+// EAGAIN
+static inline void
+spawn_thread(pthread_t *tid, void *func, void *arg)
+{
+    int status_code = -1;
+    int timeout_us = RETRY_SLEEP_TIME_US;
+    for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) {
+        status_code = pthread_create(tid, NULL, (void *(*)(void *))func, arg);
+        assert(status_code == 0 || status_code == EAGAIN);
+        if (status_code == EAGAIN) {
+            usleep(timeout_us);
+            timeout_us *= 2;
+        }
+    }
+
+    assert(status_code == 0 && "Thread creation should succeed");
+}
+
+// This function adds tid to our stat
+static inline void
+add_to_stat(StatCollector *stat, int tid)
+{
+    int tid_num = 0;
+    for (; tid_num < NUM_THREADS + 1 && stat->tids[tid_num] != 0; ++tid_num) {
+        if (stat->tids[tid_num] == tid) {
+            stat->calls[tid_num]++;
+            return;
+        }
+    }
+
+    assert(tid_num < NUM_THREADS + 1);
+    stat->tids[tid_num] = tid;
+    stat->calls[tid_num] = 1;
+}
+
+// This function prints number of calls by TID
+static inline void
+print_stat(StatCollector *stat)
+{
+    fprintf(stderr, "Thread calls count by TID\n");
+    for (int i = 0; i < NUM_THREADS + 1; ++i) {
+        if (stat->tids[i] != 0) {
+            fprintf(stderr, "TID: %d; Calls: %d\n", stat->tids[i],
+                    stat->calls[i]);
+        }
+    }
+}
+
+// This function is run by the threads, it increases counter in a loop and then
+// sleeps after unlocking the mutex to provide better contention
+static inline void *
+inc_shared_variable(void *arg)
+{
+    MutexCounter *mutex_counter = (MutexCounter *)(arg);
+    int sleep_us = 0;
+    while (!pthread_mutex_lock(mutex_counter->mutex)
+           && mutex_counter->counter < NUM_ITER) {
+        mutex_counter->counter++;
+        add_to_stat(&mutex_counter->stat, (int)(pthread_self()));
+        if (mutex_counter->is_sleeping) {
+            sleep_us = rand() % 1000;
+        }
+
+        assert(pthread_mutex_unlock(mutex_counter->mutex) == 0
+               && "Should be able to unlock a mutex");
+        if (mutex_counter->is_sleeping) {
+            usleep(sleep_us);
+        }
+    }
+
+    assert(mutex_counter->counter == NUM_ITER);
+    assert(pthread_mutex_unlock(mutex_counter->mutex) == 0
+           && "Should be able to unlock the mutex after test execution");
+
+    return NULL;
+}
+
+// Locking and unlocking a mutex in a single thread.
+static inline void *
+same_thread_lock_unlock_test(void *mutex)
+{
+    for (int i = 0; i < NUM_ITER; ++i) {
+        assert(pthread_mutex_lock(mutex) == 0
+               && "Main thread should be able to lock a mutex");
+        assert(pthread_mutex_unlock(mutex) == 0
+               && "Main thread should be able to unlock a mutex");
+    }
+
+    return NULL;
+}
+
+// This function spawns a thread that locks and unlocks a mutex `NUM_ITER` times
+// in a row
+static inline void
+same_non_main_thread_lock_unlock_test(pthread_mutex_t *mutex)
+{
+    pthread_t tid = 0;
+    spawn_thread(&tid, same_thread_lock_unlock_test, mutex);
+
+    assert(tid != 0 && "TID can't be 0 after successful thread creation");
+    assert(pthread_join(tid, NULL) == 0
+           && "Thread should be joined successfully");
+}
+
+// This function checks basic contention between main and non-main thread
+// increasing the shared variable
+static inline void
+two_threads_inc_test(pthread_mutex_t *mutex)
+{
+    MutexCounter mutex_counter;
+    mutex_counter_init(&mutex_counter, mutex, false);
+
+    pthread_t tid = 0;
+    spawn_thread(&tid, inc_shared_variable, &mutex_counter);
+
+    assert(tid != 0 && "TID can't be 0 after successful thread creation");
+    inc_shared_variable(&mutex_counter);
+    assert(pthread_join(tid, NULL) == 0
+           && "Thread should be joined without errors");
+    assert(mutex_counter.counter == NUM_ITER);
+}
+
+// This function creates number of threads specified by NUM_THREADS and run
+// concurrent increasing of shared variable
+static inline void
+max_threads_inc_test(pthread_mutex_t *mutex, int threads_num,
+                     enum SleepState is_sleeping)
+{
+    MutexCounter mutex_counter;
+    mutex_counter_init(&mutex_counter, mutex, is_sleeping);
+
+    pthread_t tids[threads_num];
+    for (int i = 0; i < threads_num; ++i) {
+        spawn_thread(&tids[i], inc_shared_variable, &mutex_counter);
+    }
+
+    inc_shared_variable(&mutex_counter);
+
+    for (int i = 0; i < threads_num; ++i) {
+        assert(pthread_join(tids[i], NULL) == 0
+               && "Thread should be joined without errors");
+    }
+
+    print_stat(&mutex_counter.stat);
+}
+
+// This function just runs all the tests described above
+static inline void
+run_common_tests(pthread_mutex_t *mutex)
+{
+    srand(time(NULL));
+
+    fprintf(stderr, "Starting same_thread_lock_unlock_test test\n");
+    same_thread_lock_unlock_test(mutex);
+    fprintf(stderr, "Finished same_thread_lock_unlock_test test\n");
+
+    fprintf(stderr, "Starting same_non_main_thread_lock_unlock_test test\n");
+    same_non_main_thread_lock_unlock_test(mutex);
+    fprintf(stderr, "Finished same_non_main_thread_lock_unlock_test test\n");
+
+    fprintf(stderr, "Starting two_threads_inc_test test\n");
+    two_threads_inc_test(mutex);
+    fprintf(stderr, "Finished two_threads_inc_test test\n");
+
+    fprintf(stderr, "Starting max_threads_inc_test_sleep test\n");
+    max_threads_inc_test(mutex, NUM_THREADS, SLEEP);
+    fprintf(stderr, "Finished concurrent_inc sleep test\n");
+
+    fprintf(stderr, "Starting max_threads_inc_test_non_sleep test\n");
+    max_threads_inc_test(mutex, NUM_THREADS, NON_SLEEP);
+    fprintf(stderr, "Finished max_threads_inc_test test\n");
+}
+
+#endif // MUTEX_COMMON_H

+ 27 - 0
core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c

@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <pthread.h>
+#include <errno.h>
+#include "mutex_common.h"
+
+void
+test()
+{
+    pthread_mutex_t mutex;
+    pthread_mutex_init(&mutex, NULL);
+
+    run_common_tests(&mutex);
+
+    fprintf(stderr, "Normal mutex test is completed\n");
+    pthread_mutex_destroy(&mutex);
+}
+
+int
+main()
+{
+    test();
+    return 0;
+}

+ 72 - 0
core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c

@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <pthread.h>
+#include <errno.h>
+#include "mutex_common.h"
+
+void
+multiple_same_thread_lock(void *mutex)
+{
+    for (int i = 0; i < 100; ++i) {
+        assert(pthread_mutex_lock(mutex) == 0
+               && "Recursive mutex should allow multiple locking");
+    }
+
+    for (int i = 0; i < 100; ++i) {
+        assert(pthread_mutex_unlock(mutex) == 0
+               && "Recursive mutex should allow multiple unlocking");
+    }
+}
+
+void *
+same_thread_multiple_rec_mutex_lock(void *mutex)
+{
+    for (int i = 0; i < NUM_ITER; ++i) {
+        multiple_same_thread_lock(mutex);
+    }
+
+    return NULL;
+}
+
+void
+test()
+{
+    pthread_mutex_t mutex;
+
+    // Set mutex type to recursive. This type allows multiple locking and
+    // unlocking within the same thread
+    pthread_mutexattr_t mutex_attr;
+    pthread_mutexattr_init(&mutex_attr);
+    pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
+
+    pthread_mutex_init(&mutex, &mutex_attr);
+    pthread_mutexattr_destroy(&mutex_attr);
+
+    run_common_tests(&mutex);
+
+    fprintf(stderr, "Starting same_thread_multiple_rec_mutex_lock test\n");
+    same_thread_multiple_rec_mutex_lock(&mutex);
+    fprintf(stderr, "Finished same_thread_multiple_rec_mutex_lock test\n");
+
+    fprintf(stderr, "Starting same_thread_multiple_rec_mutex_lock test in "
+                    "non-main thread\n");
+    pthread_t tid;
+    spawn_thread(&tid, same_thread_multiple_rec_mutex_lock, &mutex);
+    assert(pthread_join(tid, NULL) == 0
+           && "Non-main thread should be joined successfully");
+    fprintf(stderr, "Finished same_thread_multiple_rec_mutex_lock test in "
+                    "non-main thread\n");
+
+    fprintf(stderr, "Recursive mutex test is completed\n");
+    pthread_mutex_destroy(&mutex);
+}
+
+int
+main()
+{
+    test();
+    return 0;
+}

+ 31 - 23
core/iwasm/libraries/lib-wasi-threads/test/spawn_stress_test.c → core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c

@@ -16,13 +16,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-enum CONSTANTS {
-    NUM_ITER = 100000,
-    NUM_RETRY = 8,
-    MAX_NUM_THREADS = 8,
-    RETRY_SLEEP_TIME_US = 2000,
-};
-
 unsigned prime_numbers_count = 0;
 
 bool
@@ -49,10 +42,10 @@ check_if_prime(void *value)
 }
 
 unsigned int
-validate()
+validate(int iter_num)
 {
     unsigned int counter = 0;
-    for (unsigned int i = 2; i <= NUM_ITER; ++i) {
+    for (unsigned int i = 2; i <= iter_num; ++i) {
         counter += is_prime(i);
     }
 
@@ -60,11 +53,12 @@ validate()
 }
 
 void
-spawn_thread(pthread_t *thread, unsigned int *arg)
+spawn_thread(pthread_t *thread, int retry_time_us, int retry_num,
+             unsigned int *arg)
 {
     int status_code = -1;
-    int timeout_us = RETRY_SLEEP_TIME_US;
-    for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) {
+    int timeout_us = retry_time_us;
+    for (int tries = 0; status_code != 0 && tries < retry_num; ++tries) {
         status_code = pthread_create(thread, NULL, &check_if_prime, arg);
         assert(status_code == 0 || status_code == EAGAIN);
         if (status_code == EAGAIN) {
@@ -76,42 +70,56 @@ spawn_thread(pthread_t *thread, unsigned int *arg)
     assert(status_code == 0 && "Thread creation should succeed");
 }
 
-int
-main(int argc, char **argv)
+void
+test(int iter_num, int retry_num, int max_threads_num, int retry_time_us)
 {
-    pthread_t threads[MAX_NUM_THREADS];
-    unsigned int args[MAX_NUM_THREADS];
+    pthread_t threads[max_threads_num];
+    unsigned int args[max_threads_num];
     double percentage = 0.1;
 
-    for (unsigned int factorised_number = 2; factorised_number < NUM_ITER;
+    for (unsigned int factorised_number = 2; factorised_number < iter_num;
          ++factorised_number) {
-        if (factorised_number > NUM_ITER * percentage) {
+        if (factorised_number > iter_num * percentage) {
             fprintf(stderr, "Stress test is %d%% finished\n",
                     (unsigned int)(percentage * 100));
             percentage += 0.1;
         }
 
-        unsigned int thread_num = factorised_number % MAX_NUM_THREADS;
+        unsigned int thread_num = factorised_number % max_threads_num;
         if (threads[thread_num] != 0) {
             assert(pthread_join(threads[thread_num], NULL) == 0);
         }
 
         args[thread_num] = factorised_number;
 
-        usleep(RETRY_SLEEP_TIME_US);
-        spawn_thread(&threads[thread_num], &args[thread_num]);
+        usleep(retry_time_us);
+        spawn_thread(&threads[thread_num], retry_time_us, retry_num,
+                     &args[thread_num]);
         assert(threads[thread_num] != 0);
     }
 
-    for (int i = 0; i < MAX_NUM_THREADS; ++i) {
+    for (int i = 0; i < max_threads_num; ++i) {
         assert(threads[i] == 0 || pthread_join(threads[i], NULL) == 0);
     }
 
     // Check the test results
     assert(
-        prime_numbers_count == validate()
+        prime_numbers_count == validate(iter_num)
         && "Answer mismatch between tested code and reference implementation");
 
     fprintf(stderr, "Stress test finished successfully\n");
+}
+
+enum DEFAULT_PARAMETERS {
+    ITER_NUM = 20000,
+    RETRY_NUM = 8,
+    MAX_THREADS_NUM = 12,
+    RETRY_SLEEP_TIME_US = 2000,
+};
+
+int
+main(int argc, char **argv)
+{
+    test(ITER_NUM, RETRY_NUM, MAX_THREADS_NUM, RETRY_SLEEP_TIME_US);
     return 0;
 }

+ 26 - 18
core/iwasm/libraries/lib-wasi-threads/test/stress_test_threads_creation.c → core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c

@@ -9,14 +9,6 @@
 #include <stdio.h>
 #include <unistd.h>
 
-enum CONSTANTS {
-    NUM_ITER = 200000,
-    NUM_RETRY = 8,
-    MAX_NUM_THREADS = 8,
-    RETRY_SLEEP_TIME_US = 4000,
-    SECOND = 1000 * 1000 * 1000
-};
-
 int threads_executed = 0;
 unsigned int threads_creation_tried = 0;
 unsigned int threads_in_use = 0;
@@ -31,11 +23,11 @@ thread_func(void *arg)
 }
 
 void
-spawn_thread(pthread_t *thread)
+spawn_thread(pthread_t *thread, int retry_time, int iter_num)
 {
     int status_code = -1;
-    int timeout_us = RETRY_SLEEP_TIME_US;
-    for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) {
+    int timeout_us = retry_time;
+    for (int tries = 0; status_code != 0 && tries < iter_num; ++tries) {
         status_code = pthread_create(thread, NULL, &thread_func, NULL);
         __atomic_fetch_add(&threads_creation_tried, 1, __ATOMIC_RELAXED);
 
@@ -49,30 +41,33 @@ spawn_thread(pthread_t *thread)
     assert(status_code == 0 && "Thread creation should succeed");
 }
 
-int
-main(int argc, char **argv)
+void
+test(int iter_num, int max_threads_num, int retry_num, int retry_time_us)
 {
     double percentage = 0.1;
+    int second_us = 1000 * 1000 * 1000; // 1 second in us
 
-    for (int iter = 0; iter < NUM_ITER; ++iter) {
-        if (iter > NUM_ITER * percentage) {
+    for (int iter = 0; iter < iter_num; ++iter) {
+        if (iter > iter_num * percentage) {
             fprintf(stderr, "Spawning stress test is %d%% finished\n",
                     (unsigned int)(percentage * 100));
             percentage += 0.1;
         }
         while (__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST)
-               == MAX_NUM_THREADS) {
+               == max_threads_num) {
             usleep(100);
         }
 
         __atomic_fetch_add(&threads_in_use, 1, __ATOMIC_SEQ_CST);
         pthread_t tmp;
-        spawn_thread(&tmp);
+        spawn_thread(&tmp, retry_time_us, iter_num);
         pthread_detach(tmp);
     }
 
     while ((__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) != 0)) {
-        __builtin_wasm_memory_atomic_wait32(&threads_in_use, 0, SECOND);
+        // Casting to int* to supress compiler warning
+        __builtin_wasm_memory_atomic_wait32((int *)(&threads_in_use), 0,
+                                            second_us);
     }
 
     assert(__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) == 0);
@@ -89,5 +84,18 @@ main(int argc, char **argv)
             "with retry ratio %f\n",
             threads_creation_tried,
             (1. * threads_creation_tried) / threads_executed);
+}
+
+enum DEFAULT_PARAMETERS {
+    ITER_NUM = 50000,
+    RETRY_NUM = 8,
+    MAX_NUM_THREADS = 12,
+    RETRY_SLEEP_TIME_US = 4000,
+};
+
+int
+main(int argc, char **argv)
+{
+    test(ITER_NUM, MAX_NUM_THREADS, RETRY_NUM, RETRY_SLEEP_TIME_US);
     return 0;
 }

+ 4 - 1
core/iwasm/libraries/lib-wasi-threads/test/build.sh

@@ -34,7 +34,10 @@ while [[ $# -gt 0 ]]; do
 done
 
 # Stress tests names
-thread_start_file_exclusions=("spawn_stress_test.wasm" "linear_memory_size_update.wasm" "stress_test_threads_creation.wasm")
+thread_start_file_exclusions=("linear_memory_size_update.wasm")
+
+rm -rf *.wasm
+rm -rf *.aot
 
 for test_c in *.c; do
     test_wasm="$(basename $test_c .c).wasm"

+ 1 - 1
core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c

@@ -65,7 +65,7 @@ main(int argc, char **argv)
         assert(start_args_init(&data[i].base));
         thread_ids[i] = __wasi_thread_spawn(&data[i]);
         printf("Thread created with id=%d\n", thread_ids[i]);
-        assert(thread_ids[i] > 0 && "Thread creation failed");
+        ASSERT_VALID_TID(thread_ids[i]);
 
         for (int j = 0; j < i; j++) {
             assert(thread_ids[i] != thread_ids[j] && "Duplicated TIDs");

+ 1 - 1
core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c

@@ -49,7 +49,7 @@ main(int argc, char **argv)
     for (int i = 0; i < NUM_THREADS; i++) {
         assert(start_args_init(&data[i].base));
         thread_ids[i] = __wasi_thread_spawn(&data[i]);
-        assert(thread_ids[i] > 0 && "Thread creation failed");
+        ASSERT_VALID_TID(thread_ids[i]);
     }
 
     printf("Wait for threads to finish\n");

+ 1 - 1
core/iwasm/libraries/lib-wasi-threads/test/global_lock.c

@@ -61,7 +61,7 @@ main(int argc, char **argv)
     for (int i = 0; i < NUM_THREADS; i++) {
         assert(start_args_init(&data[i].base));
         thread_ids[i] = __wasi_thread_spawn(&data[i]);
-        assert(thread_ids[i] > 0 && "Thread creation failed");
+        ASSERT_VALID_TID(thread_ids[i]);
     }
 
     printf("Wait for threads to finish\n");

+ 0 - 6
core/iwasm/libraries/lib-wasi-threads/test/skip.json

@@ -1,6 +0,0 @@
-{
-    "lib-wasi-threads tests": {
-        "spawn_stress_test": "Stress tests are incompatible with the other part and executed differently",
-        "stress_test_threads_creation": "Stress tests are incompatible with the other part and executed differently"
-    }
-}

+ 1 - 1
core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c

@@ -38,7 +38,7 @@ main(int argc, char **argv)
 
     assert(start_args_init(&data.base));
     int thread_id = __wasi_thread_spawn(&data);
-    assert(thread_id > 0 && "Thread creation failed");
+    ASSERT_VALID_TID(thread_id);
 
     return EXIT_SUCCESS;
 }

+ 0 - 3
core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json

@@ -1,3 +0,0 @@
-{
-  "exit_code": 1
-}

+ 1 - 1
core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c

@@ -69,7 +69,7 @@ main(int argc, char **argv)
         data[i].iteration = i;
 
         thread_ids[i] = __wasi_thread_spawn(&data[i]);
-        assert(thread_ids[i] > 0 && "Thread creation failed");
+        ASSERT_VALID_TID(thread_ids[i]);
     }
 
     printf("Wait for threads to finish\n");

+ 10 - 0
core/iwasm/libraries/lib-wasi-threads/tid_allocator.h

@@ -8,8 +8,14 @@
 
 #include "platform_common.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define TID_ALLOCATOR_INIT_SIZE CLUSTER_MAX_THREAD_NUM
 enum {
+    /* Keep it in sync with
+       https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids */
     TID_MIN = 1,
     TID_MAX = 0x1FFFFFFF
 }; // Reserved TIDs (WASI specification)
@@ -33,4 +39,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator);
 void
 tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _TID_ALLOCATOR_H */

+ 6 - 0
core/iwasm/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake

@@ -0,0 +1,6 @@
+# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+create_wamr_unit_test(wasi_threads
+    ${CMAKE_CURRENT_LIST_DIR}/test_tid_allocator.cpp
+)

+ 62 - 0
core/iwasm/libraries/lib-wasi-threads/unit-test/test_tid_allocator.cpp

@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <gtest/gtest.h>
+
+#include "tid_allocator.h"
+
+#include <stdint.h>
+
+class TidAllocatorTest : public ::testing::Test
+{
+  protected:
+    void SetUp() override { ASSERT_TRUE(tid_allocator_init(&_allocator)); }
+
+    void TearDown() override { tid_allocator_deinit(&_allocator); }
+
+    TidAllocator _allocator;
+};
+
+static bool
+is_tid_valid(int32 tid)
+{
+    /* See: https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids
+     */
+    return tid >= TID_MIN && tid <= TID_MAX;
+}
+
+TEST_F(TidAllocatorTest, BasicTest)
+{
+    int32 tid = tid_allocator_get_tid(&_allocator);
+
+    ASSERT_TRUE(is_tid_valid(tid));
+}
+
+TEST_F(TidAllocatorTest, ShouldFailOnAllocatingMoreThanAllowedThreadIDs)
+{
+    int32 last_tid = 0;
+    for (int32 i = 0; i < TID_MAX + 1; i++) {
+        last_tid = tid_allocator_get_tid(&_allocator);
+        if (last_tid < 0) {
+            break;
+        }
+        ASSERT_TRUE(is_tid_valid(last_tid));
+    }
+
+    ASSERT_LT(last_tid, 0);
+}
+
+TEST_F(TidAllocatorTest, ShouldAllocateMoreThanAllowedTIDsIfOldTIDsAreReleased)
+{
+    int32 last_tid = 0;
+    for (int32 i = 0; i < TID_MAX + 1; i++) {
+        if (last_tid != 0) {
+            tid_allocator_release_tid(&_allocator, last_tid);
+        }
+
+        last_tid = tid_allocator_get_tid(&_allocator);
+        ASSERT_TRUE(is_tid_valid(last_tid));
+    }
+}

+ 117 - 99
core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

@@ -335,7 +335,7 @@ wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd)
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_close(curfds, prestats, fd);
+    return wasmtime_ssp_fd_close(exec_env, curfds, prestats, fd);
 }
 
 static wasi_errno_t
@@ -348,7 +348,7 @@ wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd)
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_datasync(curfds, fd);
+    return wasmtime_ssp_fd_datasync(exec_env, curfds, fd);
 }
 
 static wasi_errno_t
@@ -389,8 +389,8 @@ wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app,
         iovec->buf_len = iovec_app->buf_len;
     }
 
-    err = wasmtime_ssp_fd_pread(curfds, fd, iovec_begin, iovs_len, offset,
-                                &nread);
+    err = wasmtime_ssp_fd_pread(exec_env, curfds, fd, iovec_begin, iovs_len,
+                                offset, &nread);
     if (err)
         goto fail;
 
@@ -443,8 +443,8 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd,
         ciovec->buf_len = iovec_app->buf_len;
     }
 
-    err = wasmtime_ssp_fd_pwrite(curfds, fd, ciovec_begin, iovs_len, offset,
-                                 &nwritten);
+    err = wasmtime_ssp_fd_pwrite(exec_env, curfds, fd, ciovec_begin, iovs_len,
+                                 offset, &nwritten);
     if (err)
         goto fail;
 
@@ -496,7 +496,8 @@ wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd,
         iovec->buf_len = iovec_app->buf_len;
     }
 
-    err = wasmtime_ssp_fd_read(curfds, fd, iovec_begin, iovs_len, &nread);
+    err = wasmtime_ssp_fd_read(exec_env, curfds, fd, iovec_begin, iovs_len,
+                               &nread);
     if (err)
         goto fail;
 
@@ -521,7 +522,7 @@ wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to)
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_renumber(curfds, prestats, from, to);
+    return wasmtime_ssp_fd_renumber(exec_env, curfds, prestats, from, to);
 }
 
 static wasi_errno_t
@@ -538,7 +539,8 @@ wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset,
     if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_seek(curfds, fd, offset, whence, newoffset);
+    return wasmtime_ssp_fd_seek(exec_env, curfds, fd, offset, whence,
+                                newoffset);
 }
 
 static wasi_errno_t
@@ -554,7 +556,7 @@ wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset)
     if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_tell(curfds, fd, newoffset);
+    return wasmtime_ssp_fd_tell(exec_env, curfds, fd, newoffset);
 }
 
 static wasi_errno_t
@@ -573,7 +575,7 @@ wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_fd_fdstat_get(curfds, fd, &fdstat);
+    err = wasmtime_ssp_fd_fdstat_get(exec_env, curfds, fd, &fdstat);
     if (err)
         return err;
 
@@ -592,7 +594,7 @@ wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_fdstat_set_flags(curfds, fd, flags);
+    return wasmtime_ssp_fd_fdstat_set_flags(exec_env, curfds, fd, flags);
 }
 
 static wasi_errno_t
@@ -607,8 +609,8 @@ wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_fdstat_set_rights(curfds, fd, fs_rights_base,
-                                             fs_rights_inheriting);
+    return wasmtime_ssp_fd_fdstat_set_rights(
+        exec_env, curfds, fd, fs_rights_base, fs_rights_inheriting);
 }
 
 static wasi_errno_t
@@ -621,7 +623,7 @@ wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd)
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_sync(curfds, fd);
+    return wasmtime_ssp_fd_sync(exec_env, curfds, fd);
 }
 
 static wasi_errno_t
@@ -663,7 +665,8 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd,
         ciovec->buf_len = iovec_app->buf_len;
     }
 
-    err = wasmtime_ssp_fd_write(curfds, fd, ciovec_begin, iovs_len, &nwritten);
+    err = wasmtime_ssp_fd_write(exec_env, curfds, fd, ciovec_begin, iovs_len,
+                                &nwritten);
     if (err)
         goto fail;
 
@@ -688,7 +691,7 @@ wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_advise(curfds, fd, offset, len, advice);
+    return wasmtime_ssp_fd_advise(exec_env, curfds, fd, offset, len, advice);
 }
 
 static wasi_errno_t
@@ -702,7 +705,7 @@ wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_allocate(curfds, fd, offset, len);
+    return wasmtime_ssp_fd_allocate(exec_env, curfds, fd, offset, len);
 }
 
 static wasi_errno_t
@@ -716,7 +719,8 @@ wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_path_create_directory(curfds, fd, path, path_len);
+    return wasmtime_ssp_path_create_directory(exec_env, curfds, fd, path,
+                                              path_len);
 }
 
 static wasi_errno_t
@@ -733,8 +737,9 @@ wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_path_link(curfds, prestats, old_fd, old_flags, old_path,
-                                  old_path_len, new_fd, new_path, new_path_len);
+    return wasmtime_ssp_path_link(exec_env, curfds, prestats, old_fd, old_flags,
+                                  old_path, old_path_len, new_fd, new_path,
+                                  new_path_len);
 }
 
 static wasi_errno_t
@@ -756,9 +761,9 @@ wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd,
     if (!validate_native_addr(fd_app, sizeof(wasi_fd_t)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_path_open(curfds, dirfd, dirflags, path, path_len,
-                                 oflags, fs_rights_base, fs_rights_inheriting,
-                                 fs_flags, &fd);
+    err = wasmtime_ssp_path_open(exec_env, curfds, dirfd, dirflags, path,
+                                 path_len, oflags, fs_rights_base,
+                                 fs_rights_inheriting, fs_flags, &fd);
 
     *fd_app = fd;
     return err;
@@ -780,7 +785,8 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf,
     if (!validate_native_addr(bufused_app, sizeof(uint32)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_fd_readdir(curfds, fd, buf, buf_len, cookie, &bufused);
+    err = wasmtime_ssp_fd_readdir(exec_env, curfds, fd, buf, buf_len, cookie,
+                                  &bufused);
     if (err)
         return err;
 
@@ -805,8 +811,8 @@ wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
     if (!validate_native_addr(bufused_app, sizeof(uint32)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_path_readlink(curfds, fd, path, path_len, buf, buf_len,
-                                     &bufused);
+    err = wasmtime_ssp_path_readlink(exec_env, curfds, fd, path, path_len, buf,
+                                     buf_len, &bufused);
     if (err)
         return err;
 
@@ -826,8 +832,9 @@ wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_path_rename(curfds, old_fd, old_path, old_path_len,
-                                    new_fd, new_path, new_path_len);
+    return wasmtime_ssp_path_rename(exec_env, curfds, old_fd, old_path,
+                                    old_path_len, new_fd, new_path,
+                                    new_path_len);
 }
 
 static wasi_errno_t
@@ -844,7 +851,7 @@ wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_filestat_get(curfds, fd, filestat);
+    return wasmtime_ssp_fd_filestat_get(exec_env, curfds, fd, filestat);
 }
 
 static wasi_errno_t
@@ -859,8 +866,8 @@ wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_filestat_set_times(curfds, fd, st_atim, st_mtim,
-                                              fstflags);
+    return wasmtime_ssp_fd_filestat_set_times(exec_env, curfds, fd, st_atim,
+                                              st_mtim, fstflags);
 }
 
 static wasi_errno_t
@@ -874,7 +881,7 @@ wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_filestat_set_size(curfds, fd, st_size);
+    return wasmtime_ssp_fd_filestat_set_size(exec_env, curfds, fd, st_size);
 }
 
 static wasi_errno_t
@@ -892,8 +899,8 @@ wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_path_filestat_get(curfds, fd, flags, path, path_len,
-                                          filestat);
+    return wasmtime_ssp_path_filestat_get(exec_env, curfds, fd, flags, path,
+                                          path_len, filestat);
 }
 
 static wasi_errno_t
@@ -909,8 +916,9 @@ wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_path_filestat_set_times(
-        curfds, fd, flags, path, path_len, st_atim, st_mtim, fstflags);
+    return wasmtime_ssp_path_filestat_set_times(exec_env, curfds, fd, flags,
+                                                path, path_len, st_atim,
+                                                st_mtim, fstflags);
 }
 
 static wasi_errno_t
@@ -926,8 +934,8 @@ wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_path_symlink(curfds, prestats, old_path, old_path_len,
-                                     fd, new_path, new_path_len);
+    return wasmtime_ssp_path_symlink(exec_env, curfds, prestats, old_path,
+                                     old_path_len, fd, new_path, new_path_len);
 }
 
 static wasi_errno_t
@@ -941,7 +949,7 @@ wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_path_unlink_file(curfds, fd, path, path_len);
+    return wasmtime_ssp_path_unlink_file(exec_env, curfds, fd, path, path_len);
 }
 
 static wasi_errno_t
@@ -955,7 +963,8 @@ wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
     if (!wasi_ctx)
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len);
+    return wasmtime_ssp_path_remove_directory(exec_env, curfds, fd, path,
+                                              path_len);
 }
 
 #if WASM_ENABLE_THREAD_MGR != 0
@@ -1026,8 +1035,8 @@ execute_interruptible_poll_oneoff(
         /* update timeout for clock subscription events */
         update_clock_subscription_data(
             in_copy, nsubscriptions, min_uint64(time_quant, timeout - elapsed));
-        err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions,
-                                       nevents);
+        err = wasmtime_ssp_poll_oneoff(exec_env, curfds, in_copy, out,
+                                       nsubscriptions, nevents);
         elapsed += time_quant;
 
         if (err) {
@@ -1079,7 +1088,8 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
         return (wasi_errno_t)-1;
 
 #if WASM_ENABLE_THREAD_MGR == 0
-    err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents);
+    err = wasmtime_ssp_poll_oneoff(exec_env, curfds, in, out, nsubscriptions,
+                                   &nevents);
 #else
     err = execute_interruptible_poll_oneoff(curfds, in, out, nsubscriptions,
                                             &nevents, exec_env);
@@ -1133,7 +1143,7 @@ wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fdflags_t flags,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasi_ssp_sock_accept(curfds, fd, flags, fd_new);
+    return wasi_ssp_sock_accept(exec_env, curfds, fd, flags, fd_new);
 }
 
 static wasi_errno_t
@@ -1152,7 +1162,7 @@ wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasi_ssp_sock_addr_local(curfds, fd, addr);
+    return wasi_ssp_sock_addr_local(exec_env, curfds, fd, addr);
 }
 
 static wasi_errno_t
@@ -1171,7 +1181,7 @@ wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasi_ssp_sock_addr_remote(curfds, fd, addr);
+    return wasi_ssp_sock_addr_remote(exec_env, curfds, fd, addr);
 }
 
 static wasi_errno_t
@@ -1192,8 +1202,8 @@ wasi_sock_addr_resolve(wasm_exec_env_t exec_env, const char *host,
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     ns_lookup_list = wasi_ctx_get_ns_lookup_list(wasi_ctx);
 
-    return wasi_ssp_sock_addr_resolve(curfds, ns_lookup_list, host, service,
-                                      hints, addr_info, addr_info_size,
+    return wasi_ssp_sock_addr_resolve(exec_env, curfds, ns_lookup_list, host,
+                                      service, hints, addr_info, addr_info_size,
                                       max_info_size);
 }
 
@@ -1211,7 +1221,7 @@ wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
 
-    return wasi_ssp_sock_bind(curfds, addr_pool, fd, addr);
+    return wasi_ssp_sock_bind(exec_env, curfds, addr_pool, fd, addr);
 }
 
 static wasi_errno_t
@@ -1234,7 +1244,7 @@ wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
 
-    return wasi_ssp_sock_connect(curfds, addr_pool, fd, addr);
+    return wasi_ssp_sock_connect(exec_env, curfds, addr_pool, fd, addr);
 }
 
 static wasi_errno_t
@@ -1253,7 +1263,7 @@ wasi_sock_get_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_broadcast(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_get_broadcast(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1272,7 +1282,7 @@ wasi_sock_get_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_keep_alive(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_get_keep_alive(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1292,7 +1302,8 @@ wasi_sock_get_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool *is_enabled,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_linger(curfds, fd, is_enabled, linger_s);
+    return wasmtime_ssp_sock_get_linger(exec_env, curfds, fd, is_enabled,
+                                        linger_s);
 }
 
 static wasi_errno_t
@@ -1311,7 +1322,7 @@ wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_recv_buf_size(curfds, fd, size);
+    return wasmtime_ssp_sock_get_recv_buf_size(exec_env, curfds, fd, size);
 }
 
 static wasi_errno_t
@@ -1330,7 +1341,7 @@ wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_recv_timeout(curfds, fd, timeout_us);
+    return wasmtime_ssp_sock_get_recv_timeout(exec_env, curfds, fd, timeout_us);
 }
 
 static wasi_errno_t
@@ -1349,7 +1360,7 @@ wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_reuse_addr(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_get_reuse_addr(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1368,7 +1379,7 @@ wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_reuse_port(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_get_reuse_port(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1387,7 +1398,7 @@ wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_send_buf_size(curfds, fd, size);
+    return wasmtime_ssp_sock_get_send_buf_size(exec_env, curfds, fd, size);
 }
 
 static wasi_errno_t
@@ -1406,7 +1417,7 @@ wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_send_timeout(curfds, fd, timeout_us);
+    return wasmtime_ssp_sock_get_send_timeout(exec_env, curfds, fd, timeout_us);
 }
 
 static wasi_errno_t
@@ -1425,7 +1436,8 @@ wasi_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_tcp_fastopen_connect(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_get_tcp_fastopen_connect(exec_env, curfds, fd,
+                                                      is_enabled);
 }
 
 static wasi_errno_t
@@ -1444,7 +1456,7 @@ wasi_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_tcp_no_delay(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_get_tcp_no_delay(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1463,7 +1475,8 @@ wasi_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_tcp_quick_ack(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_get_tcp_quick_ack(exec_env, curfds, fd,
+                                               is_enabled);
 }
 
 static wasi_errno_t
@@ -1482,7 +1495,7 @@ wasi_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_tcp_keep_idle(curfds, fd, time_s);
+    return wasmtime_ssp_sock_get_tcp_keep_idle(exec_env, curfds, fd, time_s);
 }
 
 static wasi_errno_t
@@ -1501,7 +1514,7 @@ wasi_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_tcp_keep_intvl(curfds, fd, time_s);
+    return wasmtime_ssp_sock_get_tcp_keep_intvl(exec_env, curfds, fd, time_s);
 }
 
 static wasi_errno_t
@@ -1520,7 +1533,7 @@ wasi_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_ip_multicast_loop(curfds, fd, ipv6,
+    return wasmtime_ssp_sock_get_ip_multicast_loop(exec_env, curfds, fd, ipv6,
                                                    is_enabled);
 }
 
@@ -1539,7 +1552,7 @@ wasi_sock_get_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t *ttl_s)
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_ip_ttl(curfds, fd, ttl_s);
+    return wasmtime_ssp_sock_get_ip_ttl(exec_env, curfds, fd, ttl_s);
 }
 
 static wasi_errno_t
@@ -1558,7 +1571,7 @@ wasi_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_ip_multicast_ttl(curfds, fd, ttl_s);
+    return wasmtime_ssp_sock_get_ip_multicast_ttl(exec_env, curfds, fd, ttl_s);
 }
 
 static wasi_errno_t
@@ -1577,7 +1590,7 @@ wasi_sock_get_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_get_ipv6_only(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_get_ipv6_only(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1592,7 +1605,7 @@ wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog)
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasi_ssp_sock_listen(curfds, fd, backlog);
+    return wasi_ssp_sock_listen(exec_env, curfds, fd, backlog);
 }
 
 static wasi_errno_t
@@ -1609,7 +1622,7 @@ wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasi_ssp_sock_open(curfds, poolfd, af, socktype, sockfd);
+    return wasi_ssp_sock_open(exec_env, curfds, poolfd, af, socktype, sockfd);
 }
 
 static wasi_errno_t
@@ -1624,7 +1637,7 @@ wasi_sock_set_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled)
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_broadcast(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_set_broadcast(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1640,7 +1653,7 @@ wasi_sock_set_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_keep_alive(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_set_keep_alive(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1656,7 +1669,8 @@ wasi_sock_set_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_linger(curfds, fd, is_enabled, linger_s);
+    return wasmtime_ssp_sock_set_linger(exec_env, curfds, fd, is_enabled,
+                                        linger_s);
 }
 
 static wasi_errno_t
@@ -1671,7 +1685,7 @@ wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size)
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_recv_buf_size(curfds, fd, size);
+    return wasmtime_ssp_sock_set_recv_buf_size(exec_env, curfds, fd, size);
 }
 
 static wasi_errno_t
@@ -1687,7 +1701,7 @@ wasi_sock_set_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_recv_timeout(curfds, fd, timeout_us);
+    return wasmtime_ssp_sock_set_recv_timeout(exec_env, curfds, fd, timeout_us);
 }
 
 static wasi_errno_t
@@ -1703,7 +1717,7 @@ wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_reuse_addr(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_set_reuse_addr(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1719,7 +1733,7 @@ wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_reuse_port(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_set_reuse_port(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1734,7 +1748,7 @@ wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size)
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_send_buf_size(curfds, fd, size);
+    return wasmtime_ssp_sock_set_send_buf_size(exec_env, curfds, fd, size);
 }
 
 static wasi_errno_t
@@ -1750,7 +1764,7 @@ wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_send_timeout(curfds, fd, timeout_us);
+    return wasmtime_ssp_sock_set_send_timeout(exec_env, curfds, fd, timeout_us);
 }
 
 static wasi_errno_t
@@ -1766,7 +1780,8 @@ wasi_sock_set_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_tcp_fastopen_connect(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_set_tcp_fastopen_connect(exec_env, curfds, fd,
+                                                      is_enabled);
 }
 
 static wasi_errno_t
@@ -1782,7 +1797,7 @@ wasi_sock_set_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_tcp_no_delay(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_set_tcp_no_delay(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -1798,7 +1813,8 @@ wasi_sock_set_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_tcp_quick_ack(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_set_tcp_quick_ack(exec_env, curfds, fd,
+                                               is_enabled);
 }
 
 static wasi_errno_t
@@ -1814,7 +1830,7 @@ wasi_sock_set_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_tcp_keep_idle(curfds, fd, time_s);
+    return wasmtime_ssp_sock_set_tcp_keep_idle(exec_env, curfds, fd, time_s);
 }
 
 static wasi_errno_t
@@ -1830,7 +1846,7 @@ wasi_sock_set_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_tcp_keep_intvl(curfds, fd, time_s);
+    return wasmtime_ssp_sock_set_tcp_keep_intvl(exec_env, curfds, fd, time_s);
 }
 
 static wasi_errno_t
@@ -1846,7 +1862,7 @@ wasi_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_ip_multicast_loop(curfds, fd, ipv6,
+    return wasmtime_ssp_sock_set_ip_multicast_loop(exec_env, curfds, fd, ipv6,
                                                    is_enabled);
 }
 
@@ -1867,8 +1883,8 @@ wasi_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_ip_add_membership(curfds, fd, imr_multiaddr,
-                                                   imr_interface);
+    return wasmtime_ssp_sock_set_ip_add_membership(
+        exec_env, curfds, fd, imr_multiaddr, imr_interface);
 }
 
 static wasi_errno_t
@@ -1888,8 +1904,8 @@ wasi_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_ip_drop_membership(curfds, fd, imr_multiaddr,
-                                                    imr_interface);
+    return wasmtime_ssp_sock_set_ip_drop_membership(
+        exec_env, curfds, fd, imr_multiaddr, imr_interface);
 }
 
 static wasi_errno_t
@@ -1904,7 +1920,7 @@ wasi_sock_set_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t ttl_s)
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_ip_ttl(curfds, fd, ttl_s);
+    return wasmtime_ssp_sock_set_ip_ttl(exec_env, curfds, fd, ttl_s);
 }
 
 static wasi_errno_t
@@ -1920,7 +1936,7 @@ wasi_sock_set_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd,
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_ip_multicast_ttl(curfds, fd, ttl_s);
+    return wasmtime_ssp_sock_set_ip_multicast_ttl(exec_env, curfds, fd, ttl_s);
 }
 
 static wasi_errno_t
@@ -1935,7 +1951,7 @@ wasi_sock_set_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled)
 
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_set_ipv6_only(curfds, fd, is_enabled);
+    return wasmtime_ssp_sock_set_ipv6_only(exec_env, curfds, fd, is_enabled);
 }
 
 static wasi_errno_t
@@ -2053,8 +2069,9 @@ wasi_sock_recv_from(wasm_exec_env_t exec_env, wasi_fd_t sock,
     memset(buf_begin, 0, total_size);
 
     *ro_data_len = 0;
-    err = wasmtime_ssp_sock_recv_from(curfds, sock, buf_begin, total_size,
-                                      ri_flags, src_addr, &recv_bytes);
+    err = wasmtime_ssp_sock_recv_from(exec_env, curfds, sock, buf_begin,
+                                      total_size, ri_flags, src_addr,
+                                      &recv_bytes);
     if (err != __WASI_ESUCCESS) {
         goto fail;
     }
@@ -2153,7 +2170,8 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
         return err;
 
     *so_data_len = 0;
-    err = wasmtime_ssp_sock_send(curfds, sock, buf, buf_size, &send_bytes);
+    err = wasmtime_ssp_sock_send(exec_env, curfds, sock, buf, buf_size,
+                                 &send_bytes);
     *so_data_len = (uint32)send_bytes;
 
     wasm_runtime_free(buf);
@@ -2193,8 +2211,8 @@ wasi_sock_send_to(wasm_exec_env_t exec_env, wasi_fd_t sock,
         return err;
 
     *so_data_len = 0;
-    err = wasmtime_ssp_sock_send_to(curfds, addr_pool, sock, buf, buf_size,
-                                    si_flags, dest_addr, &send_bytes);
+    err = wasmtime_ssp_sock_send_to(exec_env, curfds, addr_pool, sock, buf,
+                                    buf_size, si_flags, dest_addr, &send_bytes);
     *so_data_len = (uint32)send_bytes;
 
     wasm_runtime_free(buf);
@@ -2212,7 +2230,7 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how)
     if (!wasi_ctx)
         return __WASI_EINVAL;
 
-    return wasmtime_ssp_sock_shutdown(curfds, sock);
+    return wasmtime_ssp_sock_shutdown(exec_env, curfds, sock);
 }
 
 static wasi_errno_t

+ 91 - 235
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h

@@ -22,6 +22,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "wasm_export.h"
+
 /* clang-format off */
 
 #ifdef __cplusplus
@@ -274,37 +276,6 @@ typedef uint8_t __wasi_sdflags_t;
 typedef uint16_t __wasi_siflags_t;
 
 typedef uint8_t __wasi_signal_t;
-// 0 is reserved; POSIX has special semantics for kill(pid, 0).
-#define __WASI_SIGHUP    (1)
-#define __WASI_SIGINT    (2)
-#define __WASI_SIGQUIT   (3)
-#define __WASI_SIGILL    (4)
-#define __WASI_SIGTRAP   (5)
-#define __WASI_SIGABRT   (6)
-#define __WASI_SIGBUS    (7)
-#define __WASI_SIGFPE    (8)
-#define __WASI_SIGKILL   (9)
-#define __WASI_SIGUSR1   (10)
-#define __WASI_SIGSEGV   (11)
-#define __WASI_SIGUSR2   (12)
-#define __WASI_SIGPIPE   (13)
-#define __WASI_SIGALRM   (14)
-#define __WASI_SIGTERM   (15)
-#define __WASI_SIGCHLD   (16)
-#define __WASI_SIGCONT   (17)
-#define __WASI_SIGSTOP   (18)
-#define __WASI_SIGTSTP   (19)
-#define __WASI_SIGTTIN   (20)
-#define __WASI_SIGTTOU   (21)
-#define __WASI_SIGURG    (22)
-#define __WASI_SIGXCPU   (23)
-#define __WASI_SIGXFSZ   (24)
-#define __WASI_SIGVTALRM (25)
-#define __WASI_SIGPROF   (26)
-#define __WASI_SIGWINCH  (27)
-#define __WASI_SIGPOLL   (28)
-#define __WASI_SIGPWR    (29)
-#define __WASI_SIGSYS    (30)
 
 typedef uint16_t __wasi_subclockflags_t;
 #define __WASI_SUBSCRIPTION_CLOCK_ABSTIME (0x0001)
@@ -639,17 +610,13 @@ typedef struct __wasi_addr_info_hints_t {
 #endif
 
 __wasi_errno_t wasmtime_ssp_args_get(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct argv_environ_values *arg_environ,
-#endif
     char **argv,
     char *argv_buf
 ) WASMTIME_SSP_SYSCALL_NAME(args_get) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_args_sizes_get(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct argv_environ_values *arg_environ,
-#endif
     size_t *argc,
     size_t *argv_buf_size
 ) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) WARN_UNUSED;
@@ -666,57 +633,46 @@ __wasi_errno_t wasmtime_ssp_clock_time_get(
 ) WASMTIME_SSP_SYSCALL_NAME(clock_time_get) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_environ_get(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct argv_environ_values *arg_environ,
-#endif
     char **environ,
     char *environ_buf
 ) WASMTIME_SSP_SYSCALL_NAME(environ_get) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_environ_sizes_get(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct argv_environ_values *arg_environ,
-#endif
     size_t *environ_count,
     size_t *environ_buf_size
 ) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_prestat_get(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct fd_prestats *prestats,
-#endif
     __wasi_fd_t fd,
     __wasi_prestat_t *buf
 ) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_prestat_dir_name(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct fd_prestats *prestats,
-#endif
     __wasi_fd_t fd,
     char *path,
     size_t path_len
 ) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_close(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
     struct fd_prestats *prestats,
-#endif
     __wasi_fd_t fd
 ) WASMTIME_SSP_SYSCALL_NAME(fd_close) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_datasync(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd
 ) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_pread(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     const __wasi_iovec_t *iovs,
     size_t iovs_len,
@@ -725,9 +681,8 @@ __wasi_errno_t wasmtime_ssp_fd_pread(
 ) WASMTIME_SSP_SYSCALL_NAME(fd_pread) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_pwrite(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     const __wasi_ciovec_t *iovs,
     size_t iovs_len,
@@ -736,9 +691,8 @@ __wasi_errno_t wasmtime_ssp_fd_pwrite(
 ) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_read(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     const __wasi_iovec_t *iovs,
     size_t iovs_len,
@@ -746,18 +700,16 @@ __wasi_errno_t wasmtime_ssp_fd_read(
 ) WASMTIME_SSP_SYSCALL_NAME(fd_read) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_renumber(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
     struct fd_prestats *prestats,
-#endif
     __wasi_fd_t from,
     __wasi_fd_t to
 ) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_seek(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_filedelta_t offset,
     __wasi_whence_t whence,
@@ -765,49 +717,43 @@ __wasi_errno_t wasmtime_ssp_fd_seek(
 ) WASMTIME_SSP_SYSCALL_NAME(fd_seek) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_tell(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_filesize_t *newoffset
 ) WASMTIME_SSP_SYSCALL_NAME(fd_tell) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_fdstat_get(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_fdstat_t *buf
 ) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_fdflags_t flags
 ) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_rights_t fs_rights_base,
     __wasi_rights_t fs_rights_inheriting
 ) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_sync(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd
 ) WASMTIME_SSP_SYSCALL_NAME(fd_sync) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_write(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     const __wasi_ciovec_t *iovs,
     size_t iovs_len,
@@ -815,9 +761,8 @@ __wasi_errno_t wasmtime_ssp_fd_write(
 ) WASMTIME_SSP_SYSCALL_NAME(fd_write) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_advise(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_filesize_t offset,
     __wasi_filesize_t len,
@@ -825,28 +770,25 @@ __wasi_errno_t wasmtime_ssp_fd_advise(
 ) WASMTIME_SSP_SYSCALL_NAME(fd_advise) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_allocate(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_filesize_t offset,
     __wasi_filesize_t len
 ) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_create_directory(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     const char *path,
     size_t path_len
 ) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_link(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
     struct fd_prestats *prestats,
-#endif
     __wasi_fd_t old_fd,
     __wasi_lookupflags_t old_flags,
     const char *old_path,
@@ -857,9 +799,8 @@ __wasi_errno_t wasmtime_ssp_path_link(
 ) WASMTIME_SSP_SYSCALL_NAME(path_link) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_open(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t dirfd,
     __wasi_lookupflags_t dirflags,
     const char *path,
@@ -872,9 +813,8 @@ __wasi_errno_t wasmtime_ssp_path_open(
 ) WASMTIME_SSP_SYSCALL_NAME(path_open) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_readdir(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     void *buf,
     size_t buf_len,
@@ -883,9 +823,8 @@ __wasi_errno_t wasmtime_ssp_fd_readdir(
 ) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_readlink(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     const char *path,
     size_t path_len,
@@ -895,9 +834,8 @@ __wasi_errno_t wasmtime_ssp_path_readlink(
 ) WASMTIME_SSP_SYSCALL_NAME(path_readlink) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_rename(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t old_fd,
     const char *old_path,
     size_t old_path_len,
@@ -907,17 +845,15 @@ __wasi_errno_t wasmtime_ssp_path_rename(
 ) WASMTIME_SSP_SYSCALL_NAME(path_rename) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_filestat_get(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_filestat_t *buf
 ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_filestat_set_times(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_timestamp_t st_atim,
     __wasi_timestamp_t st_mtim,
@@ -925,17 +861,15 @@ __wasi_errno_t wasmtime_ssp_fd_filestat_set_times(
 ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_fd_filestat_set_size(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_filesize_t st_size
 ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_filestat_get(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_lookupflags_t flags,
     const char *path,
@@ -944,9 +878,8 @@ __wasi_errno_t wasmtime_ssp_path_filestat_get(
 ) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_filestat_set_times(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     __wasi_lookupflags_t flags,
     const char *path,
@@ -957,10 +890,9 @@ __wasi_errno_t wasmtime_ssp_path_filestat_set_times(
 ) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_symlink(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
     struct fd_prestats *prestats,
-#endif
     const char *old_path,
     size_t old_path_len,
     __wasi_fd_t fd,
@@ -969,47 +901,30 @@ __wasi_errno_t wasmtime_ssp_path_symlink(
 ) WASMTIME_SSP_SYSCALL_NAME(path_symlink) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_unlink_file(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     const char *path,
     size_t path_len
 ) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_path_remove_directory(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd,
     const char *path,
     size_t path_len
 ) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_poll_oneoff(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     const __wasi_subscription_t *in,
     __wasi_event_t *out,
     size_t nsubscriptions,
     size_t *nevents
 ) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) WARN_UNUSED;
 
-#if 0
-/**
- * We throw exception in libc-wasi wrapper function wasi_proc_exit()
- * but not call this function.
- */
-_Noreturn void wasmtime_ssp_proc_exit(
-    __wasi_exitcode_t rval
-) WASMTIME_SSP_SYSCALL_NAME(proc_exit);
-#endif
-
-__wasi_errno_t wasmtime_ssp_proc_raise(
-    __wasi_signal_t sig
-) WASMTIME_SSP_SYSCALL_NAME(proc_raise) WARN_UNUSED;
-
 __wasi_errno_t wasmtime_ssp_random_get(
     void *buf,
     size_t buf_len
@@ -1017,50 +932,44 @@ __wasi_errno_t wasmtime_ssp_random_get(
 
 __wasi_errno_t
 wasi_ssp_sock_accept(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_addr_local(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, __wasi_addr_t *addr
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_addr_remote(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, __wasi_addr_t *addr
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_open(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
     __wasi_fd_t *sockfd
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_bind(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds, struct addr_pool *addr_pool,
-#endif
     __wasi_fd_t fd, __wasi_addr_t *addr
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_addr_resolve(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds, char **ns_lookup_list,
-#endif
     const char *host, const char* service,
     __wasi_addr_info_hints_t *hints, __wasi_addr_info_t *addr_info,
     __wasi_size_t addr_info_size, __wasi_size_t *max_info_size
@@ -1068,88 +977,77 @@ wasi_ssp_sock_addr_resolve(
 
 __wasi_errno_t
 wasi_ssp_sock_connect(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds, struct addr_pool *addr_pool,
-#endif
     __wasi_fd_t fd, __wasi_addr_t *addr
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_get_recv_buf_size(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, __wasi_size_t *size
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_get_reuse_addr(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, uint8_t *reuse
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_get_reuse_port(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, uint8_t *reuse
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_get_send_buf_size(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, __wasi_size_t *size
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_set_recv_buf_size(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, __wasi_size_t size
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_set_reuse_addr(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, uint8_t reuse
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_set_reuse_port(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, uint8_t reuse
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_set_send_buf_size(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, __wasi_size_t size
 ) WARN_UNUSED;
 
 __wasi_errno_t
 wasi_ssp_sock_listen(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t fd, __wasi_size_t backlog
 ) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_recv(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     void *buf,
     size_t buf_len,
@@ -1157,9 +1055,8 @@ __wasi_errno_t wasmtime_ssp_sock_recv(
 ) WASMTIME_SSP_SYSCALL_NAME(sock_recv) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_recv_from(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     void *buf,
     size_t buf_len,
@@ -1169,9 +1066,8 @@ __wasi_errno_t wasmtime_ssp_sock_recv_from(
 ) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_send(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     const void *buf,
     size_t buf_len,
@@ -1179,9 +1075,8 @@ __wasi_errno_t wasmtime_ssp_sock_send(
 ) WASMTIME_SSP_SYSCALL_NAME(sock_send) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_send_to(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds, struct addr_pool *addr_pool,
-#endif
     __wasi_fd_t sock,
     const void *buf,
     size_t buf_len,
@@ -1191,317 +1086,278 @@ __wasi_errno_t wasmtime_ssp_sock_send_to(
 ) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_shutdown(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock
 ) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_recv_timeout(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint64_t timeout_us
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_recv_timeout(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint64_t *timeout_us
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_send_timeout(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint64_t timeout_us
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_send_timeout(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint64_t *timeout_us
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_send_buf_size(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     size_t bufsiz
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_send_buf_size(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     size_t *bufsiz
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     size_t bufsiz
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     size_t *bufsiz
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) WARN_UNUSED;
 
 
 __wasi_errno_t wasmtime_ssp_sock_set_keep_alive(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_keep_alive(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool *is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_reuse_addr(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_reuse_addr(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool *is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_reuse_port(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_reuse_port(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool *is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_linger(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool is_enabled,
     int linger_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_linger(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock, bool *is_enabled, int *linger_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_broadcast(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_broadcast(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool *is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool *is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool *is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint32_t time_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint32_t *time_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint32_t time_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint32_t *time_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool *is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool ipv6,
     bool is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool ipv6,
     bool *is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     __wasi_addr_ip_t *imr_multiaddr,
     uint32_t imr_interface
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     __wasi_addr_ip_t *imr_multiaddr,
     uint32_t imr_interface
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_ip_ttl(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint8_t ttl_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_ip_ttl(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint8_t *ttl_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint8_t ttl_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     uint8_t *ttl_s
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_set_ipv6_only(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) WARN_UNUSED;
 
 __wasi_errno_t wasmtime_ssp_sock_get_ipv6_only(
-#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+    wasm_exec_env_t exec_env,
     struct fd_table *curfds,
-#endif
     __wasi_fd_t sock,
     bool *is_enabled
 ) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) WARN_UNUSED;

+ 226 - 0
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c

@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2023 Midokura Japan KK.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <errno.h>
+
+#include "ssp_config.h"
+#include "blocking_op.h"
+
+int
+blocking_op_close(wasm_exec_env_t exec_env, int fd)
+{
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    int ret = close(fd);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+}
+
+ssize_t
+blocking_op_readv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov,
+                  int iovcnt)
+{
+#ifdef BH_PLATFORM_WINDOWS
+    errno = ENOTSUP;
+    return -1;
+#else
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    ssize_t ret = readv(fd, iov, iovcnt);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+#endif
+}
+
+#if CONFIG_HAS_PREADV
+ssize_t
+blocking_op_preadv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov,
+                   int iovcnt, off_t offset)
+{
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    ssize_t ret = preadv(fd, iov, iovcnt, offset);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+}
+#else /* CONFIG_HAS_PREADV */
+ssize_t
+blocking_op_pread(wasm_exec_env_t exec_env, int fd, void *p, size_t nb,
+                  off_t offset)
+{
+#ifdef BH_PLATFORM_WINDOWS
+    errno = ENOTSUP;
+    return -1;
+#else
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    ssize_t ret = pread(fd, p, nb, offset);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+#endif
+}
+#endif /* CONFIG_HAS_PREADV */
+
+ssize_t
+blocking_op_writev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov,
+                   int iovcnt)
+{
+#ifdef BH_PLATFORM_WINDOWS
+    errno = ENOTSUP;
+    return -1;
+#else
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    ssize_t ret = writev(fd, iov, iovcnt);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+#endif
+}
+
+#if CONFIG_HAS_PWRITEV
+ssize_t
+blocking_op_pwritev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov,
+                    int iovcnt, off_t offset)
+{
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    ssize_t ret = pwritev(fd, iov, iovcnt, offset);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+}
+#else /* CONFIG_HAS_PWRITEV */
+ssize_t
+blocking_op_pwrite(wasm_exec_env_t exec_env, int fd, const void *p, size_t nb,
+                   off_t offset)
+{
+#ifdef BH_PLATFORM_WINDOWS
+    errno = ENOTSUP;
+    return -1;
+#else
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    ssize_t ret = pwrite(fd, p, nb, offset);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+#endif
+}
+#endif /* CONFIG_HAS_PWRITEV */
+
+int
+blocking_op_socket_accept(wasm_exec_env_t exec_env, bh_socket_t server_sock,
+                          bh_socket_t *sockp, void *addr,
+                          unsigned int *addrlenp)
+{
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    int ret = os_socket_accept(server_sock, sockp, addr, addrlenp);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+}
+
+int
+blocking_op_socket_connect(wasm_exec_env_t exec_env, bh_socket_t sock,
+                           const char *addr, int port)
+{
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    int ret = os_socket_connect(sock, addr, port);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+}
+
+int
+blocking_op_socket_recv_from(wasm_exec_env_t exec_env, bh_socket_t sock,
+                             void *buf, unsigned int len, int flags,
+                             bh_sockaddr_t *src_addr)
+{
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    int ret = os_socket_recv_from(sock, buf, len, flags, src_addr);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+}
+
+int
+blocking_op_socket_send_to(wasm_exec_env_t exec_env, bh_socket_t sock,
+                           const void *buf, unsigned int len, int flags,
+                           const bh_sockaddr_t *dest_addr)
+{
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    int ret = os_socket_send_to(sock, buf, len, flags, dest_addr);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+}
+
+int
+blocking_op_socket_addr_resolve(wasm_exec_env_t exec_env, const char *host,
+                                const char *service, uint8_t *hint_is_tcp,
+                                uint8_t *hint_is_ipv4,
+                                bh_addr_info_t *addr_info,
+                                size_t addr_info_size, size_t *max_info_size)
+{
+    /*
+     * Note: Unlike others, os_socket_addr_resolve() is not a simple system
+     * call. It's likely backed by a complex libc function, getaddrinfo().
+     * Depending on the implementation of getaddrinfo() and underlying
+     * DNS resolver, it might or might not be possible to make it return
+     * with os_wakeup_blocking_op().
+     *
+     * Unfortunately, many of ISC/bind based resolvers just keep going on
+     * interrupted system calls. It includes macOS and glibc.
+     *
+     * On the other hand, NuttX as of writing this returns EAI_AGAIN
+     * on EINTR.
+     */
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    int ret = os_socket_addr_resolve(host, service, hint_is_tcp, hint_is_ipv4,
+                                     addr_info, addr_info_size, max_info_size);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+}
+
+int
+blocking_op_openat(wasm_exec_env_t exec_env, int fd, const char *path,
+                   int oflags, mode_t mode)
+{
+#ifdef BH_PLATFORM_WINDOWS
+    errno = ENOTSUP;
+    return -1;
+#else
+    if (!wasm_runtime_begin_blocking_op(exec_env)) {
+        errno = EINTR;
+        return -1;
+    }
+    int ret = openat(fd, path, oflags, mode);
+    wasm_runtime_end_blocking_op(exec_env);
+    return ret;
+#endif
+}

+ 57 - 0
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h

@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 Midokura Japan KK.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "wasm_export.h"
+
+int
+blocking_op_close(wasm_exec_env_t exec_env, int fd);
+ssize_t
+blocking_op_readv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov,
+                  int iovcnt);
+ssize_t
+blocking_op_preadv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov,
+                   int iovcnt, off_t offset);
+ssize_t
+blocking_op_pread(wasm_exec_env_t exec_env, int fd, void *p, size_t nb,
+                  off_t offset);
+ssize_t
+blocking_op_writev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov,
+                   int iovcnt);
+ssize_t
+blocking_op_pwritev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov,
+                    int iovcnt, off_t offset);
+ssize_t
+blocking_op_pwrite(wasm_exec_env_t exec_env, int fd, const void *p, size_t nb,
+                   off_t offset);
+int
+blocking_op_socket_accept(wasm_exec_env_t exec_env, bh_socket_t server_sock,
+                          bh_socket_t *sockp, void *addr,
+                          unsigned int *addrlenp);
+int
+blocking_op_socket_connect(wasm_exec_env_t exec_env, bh_socket_t sock,
+                           const char *addr, int port);
+int
+blocking_op_socket_recv_from(wasm_exec_env_t exec_env, bh_socket_t sock,
+                             void *buf, unsigned int len, int flags,
+                             bh_sockaddr_t *src_addr);
+int
+blocking_op_socket_send_to(wasm_exec_env_t exec_env, bh_socket_t sock,
+                           const void *buf, unsigned int len, int flags,
+                           const bh_sockaddr_t *dest_addr);
+int
+blocking_op_socket_addr_resolve(wasm_exec_env_t exec_env, const char *host,
+                                const char *service, uint8_t *hint_is_tcp,
+                                uint8_t *hint_is_ipv4,
+                                bh_addr_info_t *addr_info,
+                                size_t addr_info_size, size_t *max_info_size);
+
+#ifdef BH_PLATFORM_WINDOWS
+/* TODO to be (re)moved as part of WASI on windows work */
+typedef unsigned mode_t;
+#endif
+int
+blocking_op_openat(wasm_exec_env_t exec_env, int fd, const char *path,
+                   int oflags, mode_t mode);

Разница между файлами не показана из-за своего большого размера
+ 327 - 283
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c


+ 17 - 7
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h

@@ -14,8 +14,8 @@
 #ifndef SSP_CONFIG_H
 #define SSP_CONFIG_H
 
+#include "bh_platform.h"
 #include "gnuc.h"
-#include <stdlib.h>
 
 #if defined(__FreeBSD__) || defined(__APPLE__) \
     || (defined(ANDROID) && __ANDROID_API__ < 28)
@@ -66,7 +66,8 @@
 #endif
 #endif
 
-#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(_WIN32)
+#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(_WIN32) \
+    && !defined(__COSMOPOLITAN__)
 #define CONFIG_HAS_POSIX_FALLOCATE 1
 #else
 #define CONFIG_HAS_POSIX_FALLOCATE 0
@@ -84,7 +85,8 @@
 #define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 0
 #endif
 
-#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) && !defined(_WIN32)
+#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) && !defined(_WIN32) \
+    && !defined(__COSMOPOLITAN__)
 #define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 1
 #else
 #define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0
@@ -102,10 +104,18 @@
 #define st_mtim st_mtimespec
 #endif
 
-#ifdef __APPLE__
-#define CONFIG_TLS_USE_GSBASE 1
-#else
-#define CONFIG_TLS_USE_GSBASE 0
+#if defined(O_DSYNC)
+#define CONFIG_HAS_O_DSYNC
+#endif
+
+// POSIX requires O_RSYNC to be defined, but Linux explicitly doesn't support
+// it.
+#if defined(O_RSYNC) && !defined(__linux__)
+#define CONFIG_HAS_O_RSYNC
+#endif
+
+#if defined(O_SYNC)
+#define CONFIG_HAS_O_SYNC
 #endif
 
 #if !defined(BH_PLATFORM_LINUX_SGX)

+ 113 - 60
core/iwasm/libraries/thread-mgr/thread_manager.c

@@ -16,10 +16,6 @@
 #include "debug_engine.h"
 #endif
 
-#if WASM_ENABLE_SHARED_MEMORY != 0
-#include "wasm_shared_memory.h"
-#endif
-
 typedef struct {
     bh_list_link l;
     void (*destroy_cb)(WASMCluster *);
@@ -32,6 +28,8 @@ static bh_list cluster_list_head;
 static bh_list *const cluster_list = &cluster_list_head;
 static korp_mutex cluster_list_lock;
 
+static korp_mutex _exception_lock;
+
 typedef void (*list_visitor)(void *, void *);
 
 static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM;
@@ -52,6 +50,10 @@ thread_manager_init()
         return false;
     if (os_mutex_init(&cluster_list_lock) != 0)
         return false;
+    if (os_mutex_init(&_exception_lock) != 0) {
+        os_mutex_destroy(&cluster_list_lock);
+        return false;
+    }
     return true;
 }
 
@@ -66,6 +68,7 @@ thread_manager_destroy()
         cluster = next;
     }
     wasm_cluster_cancel_all_callbacks();
+    os_mutex_destroy(&_exception_lock);
     os_mutex_destroy(&cluster_list_lock);
 }
 
@@ -477,9 +480,6 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasm_module_t module;
     wasm_module_inst_t new_module_inst;
-#if WASM_ENABLE_LIBC_WASI != 0
-    WASIContext *wasi_ctx;
-#endif
     WASMExecEnv *new_exec_env;
     uint32 aux_stack_start, aux_stack_size;
     uint32 stack_size = 8192;
@@ -517,10 +517,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
     wasm_runtime_set_custom_data_internal(
         new_module_inst, wasm_runtime_get_custom_data(module_inst));
 
-#if WASM_ENABLE_LIBC_WASI != 0
-    wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
-    wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
-#endif
+    wasm_native_inherit_contexts(new_module_inst, module_inst);
 
     new_exec_env = wasm_exec_env_create_internal(new_module_inst,
                                                  exec_env->wasm_stack_size);
@@ -1062,6 +1059,19 @@ set_thread_cancel_flags(WASMExecEnv *exec_env)
                                 WASM_SUSPEND_FLAG_TERMINATE);
 
     os_mutex_unlock(&exec_env->wait_lock);
+
+#ifdef OS_ENABLE_WAKEUP_BLOCKING_OP
+    wasm_runtime_interrupt_blocking_op(exec_env);
+#endif
+}
+
+static void
+clear_thread_cancel_flags(WASMExecEnv *exec_env)
+{
+    os_mutex_lock(&exec_env->wait_lock);
+    WASM_SUSPEND_FLAGS_FETCH_AND(exec_env->suspend_flags,
+                                 ~WASM_SUSPEND_FLAG_TERMINATE);
+    os_mutex_unlock(&exec_env->wait_lock);
 }
 
 int32
@@ -1240,72 +1250,55 @@ wasm_cluster_resume_all(WASMCluster *cluster)
     os_mutex_unlock(&cluster->lock);
 }
 
+struct spread_exception_data {
+    WASMExecEnv *skip;
+    const char *exception;
+};
+
 static void
 set_exception_visitor(void *node, void *user_data)
 {
-    WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
-    WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
-    WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env);
-    WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst;
+    const struct spread_exception_data *data = user_data;
+    WASMExecEnv *exec_env = (WASMExecEnv *)node;
 
-    if (curr_exec_env != exec_env) {
-        WASMModuleInstance *curr_wasm_inst =
-            (WASMModuleInstance *)get_module_inst(curr_exec_env);
+    if (exec_env != data->skip) {
+        WASMModuleInstance *wasm_inst =
+            (WASMModuleInstance *)get_module_inst(exec_env);
 
-        /* Only spread non "wasi proc exit" exception */
-#if WASM_ENABLE_SHARED_MEMORY != 0
-        if (curr_wasm_inst->memory_count > 0)
-            shared_memory_lock(curr_wasm_inst->memories[0]);
-#endif
-        if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) {
-            bh_memcpy_s(curr_wasm_inst->cur_exception,
-                        sizeof(curr_wasm_inst->cur_exception),
-                        wasm_inst->cur_exception,
-                        sizeof(wasm_inst->cur_exception));
+        exception_lock(wasm_inst);
+        if (data->exception != NULL) {
+            snprintf(wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception),
+                     "Exception: %s", data->exception);
         }
-#if WASM_ENABLE_SHARED_MEMORY != 0
-        if (curr_wasm_inst->memory_count > 0)
-            shared_memory_unlock(curr_wasm_inst->memories[0]);
-#endif
+        else {
+            wasm_inst->cur_exception[0] = '\0';
+        }
+        exception_unlock(wasm_inst);
 
         /* Terminate the thread so it can exit from dead loops */
-        set_thread_cancel_flags(curr_exec_env);
-    }
-}
-
-static void
-clear_exception_visitor(void *node, void *user_data)
-{
-    WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
-    WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
-
-    if (curr_exec_env != exec_env) {
-        WASMModuleInstance *curr_wasm_inst =
-            (WASMModuleInstance *)get_module_inst(curr_exec_env);
-
-#if WASM_ENABLE_SHARED_MEMORY != 0
-        if (curr_wasm_inst->memory_count > 0)
-            shared_memory_lock(curr_wasm_inst->memories[0]);
-#endif
-        curr_wasm_inst->cur_exception[0] = '\0';
-#if WASM_ENABLE_SHARED_MEMORY != 0
-        if (curr_wasm_inst->memory_count > 0)
-            shared_memory_unlock(curr_wasm_inst->memories[0]);
-#endif
+        if (data->exception != NULL) {
+            set_thread_cancel_flags(exec_env);
+        }
+        else {
+            clear_thread_cancel_flags(exec_env);
+        }
     }
 }
 
 void
-wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear)
+wasm_cluster_set_exception(WASMExecEnv *exec_env, const char *exception)
 {
+    const bool has_exception = exception != NULL;
     WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
     bh_assert(cluster);
 
+    struct spread_exception_data data;
+    data.skip = NULL;
+    data.exception = exception;
+
     os_mutex_lock(&cluster->lock);
-    cluster->has_exception = !clear;
-    traverse_list(&cluster->exec_env_list,
-                  clear ? clear_exception_visitor : set_exception_visitor,
-                  exec_env);
+    cluster->has_exception = has_exception;
+    traverse_list(&cluster->exec_env_list, set_exception_visitor, &data);
     os_mutex_unlock(&cluster->lock);
 }
 
@@ -1341,6 +1334,48 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
     }
 }
 
+#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
+struct inst_set_context_data {
+    void *key;
+    void *ctx;
+};
+
+static void
+set_context_visitor(void *node, void *user_data)
+{
+    WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+    WASMModuleInstanceCommon *module_inst = get_module_inst(curr_exec_env);
+    const struct inst_set_context_data *data = user_data;
+
+    wasm_runtime_set_context(module_inst, data->key, data->ctx);
+}
+
+void
+wasm_cluster_set_context(WASMModuleInstanceCommon *module_inst, void *key,
+                         void *ctx)
+{
+    WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst);
+
+    if (exec_env == NULL) {
+        /* Maybe threads have not been started yet. */
+        wasm_runtime_set_context(module_inst, key, ctx);
+    }
+    else {
+        WASMCluster *cluster;
+        struct inst_set_context_data data;
+        data.key = key;
+        data.ctx = ctx;
+
+        cluster = wasm_exec_env_get_cluster(exec_env);
+        bh_assert(cluster);
+
+        os_mutex_lock(&cluster->lock);
+        traverse_list(&cluster->exec_env_list, set_context_visitor, &data);
+        os_mutex_unlock(&cluster->lock);
+    }
+}
+#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
+
 bool
 wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
 {
@@ -1353,3 +1388,21 @@ wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
 
     return is_thread_terminated;
 }
+
+void
+exception_lock(WASMModuleInstance *module_inst)
+{
+    /*
+     * Note: this lock could be per module instance if desirable.
+     * We can revisit on AOT version bump.
+     * It probably doesn't matter though because the exception handling
+     * logic should not be executed too frequently anyway.
+     */
+    os_mutex_lock(&_exception_lock);
+}
+
+void
+exception_unlock(WASMModuleInstance *module_inst)
+{
+    os_mutex_unlock(&_exception_lock);
+}

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

@@ -139,7 +139,7 @@ WASMExecEnv *
 wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst);
 
 void
-wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear);
+wasm_cluster_set_exception(WASMExecEnv *exec_env, const char *exception);
 
 WASMExecEnv *
 wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env);
@@ -151,6 +151,10 @@ void
 wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
                                 void *custom_data);
 
+void
+wasm_cluster_set_context(WASMModuleInstanceCommon *module_inst, void *key,
+                         void *ctx);
+
 bool
 wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env);
 

+ 1 - 0
core/iwasm/libraries/wasi-nn/src/wasi_nn.c

@@ -163,6 +163,7 @@ void
 wasi_nn_destroy(wasm_module_inst_t instance)
 {
     WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+    bh_hash_map_remove(hashmap, (void *)instance, NULL, NULL);
     wasi_nn_ctx_destroy(wasi_nn_ctx);
 }
 

+ 4 - 0
core/shared/platform/alios/alios_platform.c

@@ -69,3 +69,7 @@ os_mprotect(void *addr, size_t size, int prot)
 void
 os_dcache_flush()
 {}
+
+void
+os_icache_flush(void *start, size_t len)
+{}

+ 4 - 0
core/shared/platform/alios/alios_thread.c

@@ -359,3 +359,7 @@ os_thread_get_stack_boundary()
     /* TODO: get alios stack boundary */
     return NULL;
 }
+
+void
+os_thread_jit_write_protect_np(bool enabled)
+{}

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

@@ -140,16 +140,12 @@ seekdir(DIR *__dir, long __location);
 
 #endif
 
-#if __ANDROID_API__ < 24
-
 ssize_t
 preadv(int __fd, const struct iovec *__iov, int __count, off_t __offset);
 
 ssize_t
 pwritev(int __fd, const struct iovec *__iov, int __count, off_t __offset);
 
-#endif
-
 #ifdef __cplusplus
 }
 #endif

+ 69 - 0
core/shared/platform/common/posix/posix_blocking_op.c

@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 Midokura Japan KK.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_extension.h"
+
+#ifdef OS_ENABLE_WAKEUP_BLOCKING_OP
+
+static bool g_blocking_op_inited = false;
+static int g_blocking_op_signo = SIGUSR1;
+static sigset_t g_blocking_op_sigmask;
+
+static void
+blocking_op_sighandler(int signo)
+{
+    /* nothing */
+}
+
+void
+os_set_signal_number_for_blocking_op(int signo)
+{
+    g_blocking_op_signo = signo;
+}
+
+int
+os_blocking_op_init()
+{
+    if (g_blocking_op_inited) {
+        return BHT_OK;
+    }
+
+    sigemptyset(&g_blocking_op_sigmask);
+    sigaddset(&g_blocking_op_sigmask, g_blocking_op_signo);
+
+    struct sigaction sa;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = blocking_op_sighandler;
+    if (sigaction(g_blocking_op_signo, &sa, NULL)) {
+        return BHT_ERROR;
+    }
+    g_blocking_op_inited = true;
+    return BHT_OK;
+}
+
+void
+os_begin_blocking_op()
+{
+    pthread_sigmask(SIG_UNBLOCK, &g_blocking_op_sigmask, NULL);
+}
+
+void
+os_end_blocking_op()
+{
+    pthread_sigmask(SIG_BLOCK, &g_blocking_op_sigmask, NULL);
+}
+
+int
+os_wakeup_blocking_op(korp_tid tid)
+{
+    int ret = pthread_kill(tid, g_blocking_op_signo);
+    if (ret != 0) {
+        return BHT_ERROR;
+    }
+    return BHT_OK;
+}
+
+#endif /* OS_ENABLE_WAKEUP_BLOCKING_OP */

+ 16 - 0
core/shared/platform/common/posix/posix_memmap.c

@@ -5,6 +5,10 @@
 
 #include "platform_api_vmcore.h"
 
+#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__)
+#include <libkern/OSCacheControl.h>
+#endif
+
 #ifndef BH_ENABLE_TRACE_MMAP
 #define BH_ENABLE_TRACE_MMAP 0
 #endif
@@ -36,7 +40,11 @@ void *
 os_mmap(void *hint, size_t size, int prot, int flags)
 {
     int map_prot = PROT_NONE;
+#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__)
+    int map_flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_JIT;
+#else
     int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
+#endif
     uint64 request_size, page_size;
     uint8 *addr = MAP_FAILED;
     uint32 i;
@@ -251,3 +259,11 @@ os_mprotect(void *addr, size_t size, int prot)
 void
 os_dcache_flush(void)
 {}
+
+void
+os_icache_flush(void *start, size_t len)
+{
+#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__)
+    sys_icache_invalidate(start, len);
+#endif
+}

+ 20 - 0
core/shared/platform/common/posix/posix_sleep.c

@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2023 Midokura Japan KK.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <time.h>
+
+#include "platform_api_extension.h"
+
+int
+os_usleep(uint32 usec)
+{
+    struct timespec ts;
+    int ret;
+
+    ts.tv_sec = usec / 1000000;
+    ts.tv_nsec = (usec % 1000000) * 1000;
+    ret = nanosleep(&ts, NULL);
+    return ret == 0 ? 0 : -1;
+}

+ 10 - 10
core/shared/platform/common/posix/posix_socket.c

@@ -53,7 +53,7 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr,
             struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
 
             bh_sockaddr->port = ntohs(addr->sin_port);
-            bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr);
+            bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr);
             bh_sockaddr->is_ipv4 = true;
             return BHT_OK;
         }
@@ -65,12 +65,12 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr,
 
             bh_sockaddr->port = ntohs(addr->sin6_port);
 
-            for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6)
-                                / sizeof(bh_sockaddr->addr_bufer.ipv6[0]);
+            for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6)
+                                / sizeof(bh_sockaddr->addr_buffer.ipv6[0]);
                  i++) {
                 uint16 part_addr = addr->sin6_addr.s6_addr[i * 2]
                                    | (addr->sin6_addr.s6_addr[i * 2 + 1] << 8);
-                bh_sockaddr->addr_bufer.ipv6[i] = ntohs(part_addr);
+                bh_sockaddr->addr_buffer.ipv6[i] = ntohs(part_addr);
             }
 
             bh_sockaddr->is_ipv4 = false;
@@ -91,7 +91,7 @@ bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr,
         struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
         addr->sin_port = htons(bh_sockaddr->port);
         addr->sin_family = AF_INET;
-        addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4);
+        addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_buffer.ipv4);
         *socklen = sizeof(*addr);
     }
 #ifdef IPPROTO_IPV6
@@ -101,10 +101,10 @@ bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr,
         addr->sin6_port = htons(bh_sockaddr->port);
         addr->sin6_family = AF_INET6;
 
-        for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6)
-                            / sizeof(bh_sockaddr->addr_bufer.ipv6[0]);
+        for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6)
+                            / sizeof(bh_sockaddr->addr_buffer.ipv6[0]);
              i++) {
-            uint16 part_addr = htons(bh_sockaddr->addr_bufer.ipv6[i]);
+            uint16 part_addr = htons(bh_sockaddr->addr_buffer.ipv6[i]);
             addr->sin6_addr.s6_addr[i * 2] = 0xff & part_addr;
             addr->sin6_addr.s6_addr[i * 2 + 1] = (0xff00 & part_addr) >> 8;
         }
@@ -799,7 +799,7 @@ os_socket_set_ip_add_membership(bh_socket_t socket,
 {
     assert(imr_multiaddr);
     if (is_ipv6) {
-#ifdef IPPROTO_IPV6
+#if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN)
         struct ipv6_mreq mreq;
         for (int i = 0; i < 8; i++) {
             ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =
@@ -837,7 +837,7 @@ os_socket_set_ip_drop_membership(bh_socket_t socket,
 {
     assert(imr_multiaddr);
     if (is_ipv6) {
-#ifdef IPPROTO_IPV6
+#if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN)
         struct ipv6_mreq mreq;
         for (int i = 0; i < 8; i++) {
             ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =

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

@@ -39,6 +39,9 @@ os_thread_wrapper(void *arg)
 #ifdef OS_ENABLE_HW_BOUND_CHECK
     if (os_thread_signal_init(handler) != 0)
         return NULL;
+#endif
+#ifdef OS_ENABLE_WAKEUP_BLOCKING_OP
+    os_end_blocking_op();
 #endif
     start_func(thread_arg);
 #ifdef OS_ENABLE_HW_BOUND_CHECK
@@ -470,6 +473,14 @@ os_thread_get_stack_boundary()
     return addr;
 }
 
+void
+os_thread_jit_write_protect_np(bool enabled)
+{
+#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__)
+    pthread_jit_write_protect_np(enabled);
+#endif
+}
+
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 
 #define SIG_ALT_STACK_SIZE (32 * 1024)
@@ -564,8 +575,8 @@ mask_signals(int how)
     pthread_sigmask(how, &set, NULL);
 }
 
-static os_thread_local_attribute struct sigaction prev_sig_act_SIGSEGV;
-static os_thread_local_attribute struct sigaction prev_sig_act_SIGBUS;
+static struct sigaction prev_sig_act_SIGSEGV;
+static struct sigaction prev_sig_act_SIGBUS;
 
 /* ASAN is not designed to work with custom stack unwind or other low-level \
  things. > Ignore a function that does some low-level magic. (e.g. walking \
@@ -596,9 +607,12 @@ signal_callback(int sig_num, siginfo_t *sig_info, void *sig_ucontext)
         prev_sig_act->sa_sigaction(sig_num, sig_info, sig_ucontext);
     }
     else if (prev_sig_act
-             && ((void *)prev_sig_act->sa_sigaction == SIG_DFL
-                 || (void *)prev_sig_act->sa_sigaction == SIG_IGN)) {
-        sigaction(sig_num, prev_sig_act, NULL);
+             && prev_sig_act->sa_handler
+             /* Filter out SIG_DFL and SIG_IGN here, they will
+                run into the else branch below */
+             && (void *)prev_sig_act->sa_handler != SIG_DFL
+             && (void *)prev_sig_act->sa_handler != SIG_IGN) {
+        prev_sig_act->sa_handler(sig_num);
     }
     /* Output signal info and then crash if signal is unhandled */
     else {

+ 43 - 0
core/shared/platform/cosmopolitan/platform_init.c

@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+
+int
+bh_platform_init()
+{
+    return 0;
+}
+
+void
+bh_platform_destroy()
+{}
+
+int
+os_printf(const char *format, ...)
+{
+    int ret = 0;
+    va_list ap;
+
+    va_start(ap, format);
+#ifndef BH_VPRINTF
+    ret += vprintf(format, ap);
+#else
+    ret += BH_VPRINTF(format, ap);
+#endif
+    va_end(ap);
+
+    return ret;
+}
+
+int
+os_vprintf(const char *format, va_list ap)
+{
+#ifndef BH_VPRINTF
+    return vprintf(format, ap);
+#else
+    return BH_VPRINTF(format, ap);
+#endif
+}

+ 122 - 0
core/shared/platform/cosmopolitan/platform_internal.h

@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * Copyright (C) 2023 Dylibso.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _PLATFORM_INTERNAL_H
+#define _PLATFORM_INTERNAL_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <limits.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <poll.h>
+#include <sched.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/resource.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BH_PLATFORM_COSMOPOLITAN
+#define BH_PLATFORM_COSMOPOLITAN
+#endif
+
+/* Stack size of applet threads's native part.  */
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
+
+/* Default thread priority */
+#define BH_THREAD_DEFAULT_PRIORITY 0
+
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef pthread_t korp_thread;
+typedef sem_t korp_sem;
+
+#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#define os_thread_local_attribute __thread
+
+#define bh_socket_t int
+
+#if WASM_DISABLE_WRITE_GS_BASE == 0
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+#define os_writegsbase(base_addr)                                 \
+    do {                                                          \
+        uint64 __gs_value = (uint64)(uintptr_t)base_addr;         \
+        asm volatile("wrgsbase %0" ::"r"(__gs_value) : "memory"); \
+    } while (0)
+#if 0
+/* _writegsbase_u64 also works, but need to add -mfsgsbase flag for gcc */
+#include <immintrin.h>
+#define os_writegsbase(base_addr) \
+    _writegsbase_u64(((uint64)(uintptr_t)base_addr))
+#endif
+#endif
+#endif
+
+#if WASM_DISABLE_HW_BOUND_CHECK == 0
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)            \
+    || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
+    || defined(BUILD_TARGET_RISCV64_LP64)
+
+#include <setjmp.h>
+
+#define OS_ENABLE_HW_BOUND_CHECK
+
+typedef jmp_buf korp_jmpbuf;
+
+#define os_setjmp setjmp
+#define os_longjmp longjmp
+#define os_alloca alloca
+
+#define os_getpagesize getpagesize
+
+typedef void (*os_signal_handler)(void *sig_addr);
+
+int
+os_thread_signal_init(os_signal_handler handler);
+
+void
+os_thread_signal_destroy();
+
+bool
+os_thread_signal_inited();
+
+void
+os_signal_unmask();
+
+void
+os_sigreturn();
+#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
+#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _PLATFORM_INTERNAL_H */

+ 19 - 0
core/shared/platform/cosmopolitan/shared_platform.cmake

@@ -0,0 +1,19 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# Copyright (C) 2023 Dylibso.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions(-DBH_PLATFORM_COSMOPOLITAN)
+
+include_directories(${PLATFORM_SHARED_DIR})
+include_directories(${PLATFORM_SHARED_DIR}/../include)
+
+include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
+
+file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
+
+set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE})
+
+file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h)
+LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})

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

@@ -103,6 +103,12 @@ os_sigreturn();
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 
+#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0
+#define OS_ENABLE_WAKEUP_BLOCKING_OP
+#endif
+void
+os_set_signal_number_for_blocking_op(int signo);
+
 #ifdef __cplusplus
 }
 #endif

+ 4 - 0
core/shared/platform/esp-idf/espidf_memmap.c

@@ -100,6 +100,10 @@ void
 #endif
 }
 
+void
+os_icache_flush(void *start, size_t len)
+{}
+
 #if (WASM_MEM_DUAL_BUS_MIRROR != 0)
 void *
 os_get_dbus_mirror(void *ibus)

+ 4 - 0
core/shared/platform/esp-idf/espidf_platform.c

@@ -53,6 +53,10 @@ os_thread_get_stack_boundary(void)
 #endif
 }
 
+void
+os_thread_jit_write_protect_np(bool enabled)
+{}
+
 int
 os_usleep(uint32 usec)
 {

+ 1 - 1
core/shared/platform/esp-idf/espidf_socket.c

@@ -30,7 +30,7 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen,
             assert(socklen >= sizeof(struct sockaddr_in));
 
             bh_sockaddr->port = ntohs(addr->sin_port);
-            bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr);
+            bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr);
             bh_sockaddr->is_ipv4 = true;
             return BHT_OK;
         }

+ 6 - 0
core/shared/platform/freebsd/platform_internal.h

@@ -102,6 +102,12 @@ os_sigreturn();
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 
+#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0
+#define OS_ENABLE_WAKEUP_BLOCKING_OP
+#endif
+void
+os_set_signal_number_for_blocking_op(int signo);
+
 #ifdef __cplusplus
 }
 #endif

+ 29 - 1
core/shared/platform/include/platform_api_extension.h

@@ -373,6 +373,34 @@ os_sem_getvalue(korp_sem *sem, int *sval);
 int
 os_sem_unlink(const char *name);
 
+/**
+ * Initialize process-global state for os_wakeup_blocking_op.
+ */
+int
+os_blocking_op_init();
+
+/**
+ * Start accepting os_wakeup_blocking_op requests for the calling thread.
+ */
+void
+os_begin_blocking_op();
+
+/**
+ * Stop accepting os_wakeup_blocking_op requests for the calling thread.
+ */
+void
+os_end_blocking_op();
+
+/**
+ * Wake up the specified thread.
+ *
+ * For example, on posix-like platforms, this can be implemented by
+ * sending a signal (w/o SA_RESTART) which interrupts a blocking
+ * system call.
+ */
+int
+os_wakeup_blocking_op(korp_tid tid);
+
 /****************************************************
  *                     Section 2                    *
  *                   Socket support                 *
@@ -392,7 +420,7 @@ typedef union {
 } bh_ip_addr_buffer_t;
 
 typedef struct {
-    bh_ip_addr_buffer_t addr_bufer;
+    bh_ip_addr_buffer_t addr_buffer;
     uint16 port;
     bool is_ipv4;
 } bh_sockaddr_t;

+ 13 - 0
core/shared/platform/include/platform_api_vmcore.h

@@ -81,6 +81,13 @@ os_self_thread(void);
 uint8 *
 os_thread_get_stack_boundary(void);
 
+/**
+ * Set whether the MAP_JIT region write protection is enabled for this thread.
+ * Pass true to make the region executable, false to make it writable.
+ */
+void
+os_thread_jit_write_protect_np(bool enabled);
+
 /**
  ************** mutext APIs ***********
  *  vmcore:  Not required until pthread is supported by runtime
@@ -143,6 +150,12 @@ os_get_dbus_mirror(void *ibus);
 void
 os_dcache_flush(void);
 
+/**
+ * Flush instruction cache.
+ */
+void
+os_icache_flush(void *start, size_t len);
+
 #ifdef __cplusplus
 }
 #endif

+ 4 - 0
core/shared/platform/linux-sgx/sgx_platform.c

@@ -195,3 +195,7 @@ os_mprotect(void *addr, size_t size, int prot)
 void
 os_dcache_flush(void)
 {}
+
+void
+os_icache_flush(void *start, size_t len)
+{}

+ 2 - 2
core/shared/platform/linux-sgx/sgx_socket.c

@@ -261,7 +261,7 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen,
             assert(socklen >= sizeof(struct sockaddr_in));
 
             bh_sockaddr->port = ntohs(addr->sin_port);
-            bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr);
+            bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr);
             bh_sockaddr->is_ipv4 = true;
             return BHT_OK;
         }
@@ -279,7 +279,7 @@ bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr,
         struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
         addr->sin_port = htons(bh_sockaddr->port);
         addr->sin_family = AF_INET;
-        addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4);
+        addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_buffer.ipv4);
         *socklen = sizeof(*addr);
         return BHT_OK;
     }

+ 4 - 0
core/shared/platform/linux-sgx/sgx_thread.c

@@ -211,6 +211,10 @@ os_thread_get_stack_boundary()
     return NULL;
 }
 
+void
+os_thread_jit_write_protect_np(bool enabled)
+{}
+
 int
 os_rwlock_init(korp_rwlock *lock)
 {

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

@@ -116,6 +116,12 @@ os_sigreturn();
 #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
 #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
 
+#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0
+#define OS_ENABLE_WAKEUP_BLOCKING_OP
+#endif
+void
+os_set_signal_number_for_blocking_op(int signo);
+
 #ifdef __cplusplus
 }
 #endif

+ 4 - 0
core/shared/platform/nuttx/nuttx_platform.c

@@ -144,6 +144,10 @@ os_dcache_flush()
     bus_sync();
 }
 
+void
+os_icache_flush(void *start, size_t len)
+{}
+
 #if (WASM_MEM_DUAL_BUS_MIRROR != 0)
 void *
 os_get_dbus_mirror(void *ibus)

+ 6 - 0
core/shared/platform/nuttx/platform_internal.h

@@ -124,6 +124,12 @@ utimensat(int fd, const char *path, const struct timespec ts[2], int flag);
 DIR *
 fdopendir(int fd);
 
+#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0
+#define OS_ENABLE_WAKEUP_BLOCKING_OP
+#endif
+void
+os_set_signal_number_for_blocking_op(int signo);
+
 #ifdef __cplusplus
 }
 #endif

+ 4 - 0
core/shared/platform/riot/riot_platform.c

@@ -79,3 +79,7 @@ os_dcache_flush(void)
     irq_unlock(key);
 #endif
 }
+
+void
+os_icache_flush(void *start, size_t len)
+{}

+ 4 - 0
core/shared/platform/riot/riot_thread.c

@@ -430,3 +430,7 @@ os_thread_get_stack_boundary()
     return NULL;
 #endif
 }
+
+void
+os_thread_jit_write_protect_np(bool enabled)
+{}

+ 8 - 0
core/shared/platform/rt-thread/rtt_platform.c

@@ -140,6 +140,10 @@ os_thread_get_stack_boundary(void)
     return tid->stack_addr;
 }
 
+void
+os_thread_jit_write_protect_np(bool enabled)
+{}
+
 int
 os_mutex_init(korp_mutex *mutex)
 {
@@ -207,3 +211,7 @@ os_mprotect(void *addr, size_t size, int prot)
 void
 os_dcache_flush(void)
 {}
+
+void
+os_icache_flush(void *start, size_t len)
+{}

+ 4 - 0
core/shared/platform/windows/platform_init.c

@@ -73,3 +73,7 @@ os_getpagesize()
 void
 os_dcache_flush(void)
 {}
+
+void
+os_icache_flush(void *start, size_t len)
+{}

Некоторые файлы не были показаны из-за большого количества измененных файлов