diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 2a8fcbcaf..1587a7ddc 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,20 +1,21 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp/.devcontainer/base.Dockerfile -# [Choice] Debian / Ubuntu version (use Debian 11/9, Ubuntu 18.04/21.04 on local arm64/Apple Silicon): debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 -ARG VARIANT=ubuntu-20.04 -FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-${VARIANT} +# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/cpp/.devcontainer/base.Dockerfile +# [Choice] Debian / Ubuntu version (use Debian 12/11/9, Ubuntu 18.04/21.04 on local arm64/Apple Silicon): debian-12, debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 +ARG VARIANT=debian-12 +FROM mcr.microsoft.com/vscode/devcontainers/cpp:${VARIANT} ARG DEBIAN_FRONTEND=noninteractive ENV TZ=Asian/Shanghai # hadolint ignore=DL3008 RUN apt-get update \ + && apt-get upgrade -y \ && apt-get install -y apt-transport-https apt-utils build-essential \ - ca-certificates ccache curl g++-multilib git gnupg \ - libgcc-9-dev lib32gcc-9-dev lsb-release \ - ninja-build ocaml ocamlbuild python2.7 \ + ca-certificates ccache cmake curl g++-multilib git gnupg \ + libgcc-12-dev lib32gcc-12-dev lsb-release \ + ninja-build ocaml ocamlbuild \ software-properties-common tree tzdata \ unzip valgrind vim wget zip --no-install-recommends \ && apt-get clean -y \ @@ -22,32 +23,32 @@ RUN apt-get update \ # # binaryen -ARG BINARYEN_VER=111 +ARG BINARYEN_VER=114 WORKDIR /opt RUN wget -c --progress=dot:giga https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VER}/binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \ && tar xf binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \ - && ln -sf /opt/binaryen-version_111 /opt/binaryen \ + && ln -sf /opt/binaryen-version_${BINARYEN_VER} /opt/binaryen \ && rm binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz # # CMAKE (https://apt.kitware.com/) SHELL ["/bin/bash", "-o", "pipefail", "-c"] # hadolint ignore=DL3008 -RUN wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg > /dev/null \ - && echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ bionic main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null \ - && apt-get update \ - && rm /usr/share/keyrings/kitware-archive-keyring.gpg \ - && apt-get install -y kitware-archive-keyring --no-install-recommends \ - && apt-get install -y cmake --no-install-recommends \ - && apt-get clean -y \ - && rm -rf /var/lib/apt/lists/* +ARG CMAKE_VER=3.27.0 +RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh \ + -q -O /tmp/cmake-install.sh \ + && chmod u+x /tmp/cmake-install.sh \ + && mkdir /opt/cmake-${CMAKE_VER} \ + && /tmp/cmake-install.sh --skip-license --prefix=/opt/cmake-${CMAKE_VER} \ + && rm /tmp/cmake-install.sh \ + && ln -s /opt/cmake-${CMAKE_VER}/bin/* /usr/local/bin # # install emsdk WORKDIR /opt RUN git clone https://github.com/emscripten-core/emsdk.git -ARG EMSDK_VER=3.0.0 +ARG EMSDK_VER=3.1.43 WORKDIR /opt/emsdk RUN git pull \ && ./emsdk install ${EMSDK_VER} \ @@ -56,7 +57,7 @@ RUN git pull \ # # install wasi-sdk -ARG WASI_SDK_VER=19 +ARG WASI_SDK_VER=20 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \ && tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \ && ln -sf /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \ @@ -64,7 +65,7 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases # #install wabt -ARG WABT_VER=1.0.29 +ARG WABT_VER=1.0.33 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt \ && tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \ && ln -sf /opt/wabt-${WABT_VER} /opt/wabt \ @@ -72,7 +73,7 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/dow # # install bazelisk -ARG BAZELISK_VER=1.12.0 +ARG BAZELISK_VER=1.17.0 RUN mkdir /opt/bazelisk \ && wget -c --progress=dot:giga https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk \ && chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \ @@ -80,16 +81,30 @@ RUN mkdir /opt/bazelisk \ # # install clang+llvm -ARG LLVM_VER=14 -RUN apt-get purge -y clang-10 llvm-10 && apt-get autoremove -y +ARG LLVM_VER=16 +RUN apt-get purge -y clang-14 llvm-14 && apt-get autoremove -y WORKDIR /etc/apt/apt.conf.d RUN touch 99verfiy-peer.conf \ && echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf WORKDIR /tmp -RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \ - && chmod a+x ./llvm.sh \ - && ./llvm.sh ${LLVM_VER} all +#RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \ +# && chmod a+x ./llvm.sh \ +# && ./llvm.sh ${LLVM_VER} all + +# Workaround due to https://github.com/llvm/llvm-project/issues/62475 +# hadolint ignore=DL3008 +RUN set -ex \ + && echo "deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-${LLVM_VER} main" > /etc/apt/sources.list.d/apt.llvm.org.list \ + && wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc \ + && apt-get update \ + && apt-get install -y \ + clang-${LLVM_VER} lldb-${LLVM_VER} lld-${LLVM_VER} clangd-${LLVM_VER} clang-tidy-${LLVM_VER} clang-format-${LLVM_VER} clang-tools-${LLVM_VER} \ + llvm-${LLVM_VER}-dev lld-${LLVM_VER} lldb-${LLVM_VER} llvm-${LLVM_VER}-tools libomp-${LLVM_VER}-dev libc++-${LLVM_VER}-dev libc++abi-${LLVM_VER}-dev \ + libclang-common-${LLVM_VER}-dev libclang-${LLVM_VER}-dev libclang-cpp${LLVM_VER}-dev libunwind-${LLVM_VER}-dev \ + libclang-rt-${LLVM_VER}-dev libpolly-${LLVM_VER}-dev --no-install-recommends \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* # # [Optional] @@ -105,18 +120,19 @@ RUN apt-get update \ # # Install required python packages # hadolint ignore=DL3013 -RUN python3 -m pip install --no-cache-dir --upgrade pip \ - && pip3 install --no-cache-dir black nose pycparser pylint +RUN python3 -m pip install --no-cache-dir --break-system-packages --upgrade pip \ + && pip3 install --no-cache-dir --break-system-packages black nose pycparser pylint # # Install github-cli. It doens't work as a feature of devcontainer.json +ARG GH_CLI_VER=2.32.0 WORKDIR /tmp -RUN wget -q https://github.com/cli/cli/releases/download/v2.20.2/gh_2.20.2_linux_amd64.deb \ - && dpkg -i gh_2.20.2_linux_amd64.deb +RUN wget -q https://github.com/cli/cli/releases/download/v${GH_CLI_VER}/gh_${GH_CLI_VER}_linux_amd64.deb \ + && dpkg -i gh_${GH_CLI_VER}_linux_amd64.deb # # Install NodeJS -RUN wget -qO- https://deb.nodesource.com/setup_19.x | bash - +RUN wget -qO- https://deb.nodesource.com/setup_20.x | bash - # hadolint ignore=DL3008 RUN apt-get install -y nodejs --no-install-recommends diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 24e1bdfd6..5feb17564 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,20 +1,23 @@ // Copyright (C) 2019 Intel Corporation. All rights reserved. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp +// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/cpp { "name": "WAMR-Dev", "build": { "dockerfile": "Dockerfile", - // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 - // Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon + // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-12, debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 + // Use Debian 12, Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon "args": { - "BINARYEN_VER": "111", - "EMSDK_VER": "3.0.0", - "LLVM_VER": "15", - "VARIANT": "ubuntu-20.04", - "WASI_SDK_VER": "19", - "WABT_VER": "1.0.31" + "BINARYEN_VER": "114", + "BAZELISK_VER": "1.17.0", + "CMAKE_VER": "3.27.0", + "EMSDK_VER": "3.1.43", + "GH_CLI_VER": "2.32.0", + "LLVM_VER": "16", + "VARIANT": "debian-12", + "WASI_SDK_VER": "20", + "WABT_VER": "1.0.33" } }, "runArgs": [ @@ -34,7 +37,7 @@ "llvm-vs-code-extensions.vscode-clangd", "ms-python.python", "ms-python.vscode-pylance", - "ms-vscode.cmake-tools", + "ms-vscode.cmake-tools" ] } }, diff --git a/.github/workflows/build_wamr_lldb.yml b/.github/workflows/build_wamr_lldb.yml index c376506ed..1a73750a6 100644 --- a/.github/workflows/build_wamr_lldb.yml +++ b/.github/workflows/build_wamr_lldb.yml @@ -22,6 +22,11 @@ on: description: a semantic version number type: string required: true + wasi_sdk_url: + description: download WASI_SDK from this URL + type: string + required: false + default: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz" jobs: try_reuse: @@ -29,7 +34,7 @@ jobs: with: binary_name_stem: "wamr-lldb-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}" last_commit: "ea63ba4bd010c2285623ad4acc0262a4d63bcfea" - the_path: "./build-scripts/lldb-wasm.patch" + the_path: "./build-scripts/lldb_wasm.patch" upload_url: ${{ inputs.upload_url }} build: @@ -44,6 +49,15 @@ jobs: steps: - uses: actions/checkout@v3 + - name: download and install wasi-sdk + run: | + cd /opt + basename=$(basename ${{ inputs.wasi_sdk_url }}) + sudo wget --progress=dot:giga ${{ inputs.wasi_sdk_url }} + sudo tar -xzf ${basename} + sudo rm ${basename} + sudo mv wasi-sdk-* wasi-sdk + - name: Cache build id: lldb_build_cache uses: actions/cache@v3 @@ -69,8 +83,8 @@ jobs: if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos') run: | brew remove swig - brew install swig@3 cmake ninja libedit - brew link --overwrite swig@3 + brew install swig@4.1 cmake ninja libedit + brew link --overwrite swig@4.1 sudo rm -rf /Library/Developer/CommandLineTools - name: install utils ubuntu @@ -92,7 +106,7 @@ jobs: git init git config user.email "action@github.com" git config user.name "github action" - git apply ../../../build-scripts/lldb-wasm.patch + git apply ../../../build-scripts/lldb_wasm.patch working-directory: core/deps/llvm-project - name: get stand-alone python ubuntu @@ -141,6 +155,17 @@ jobs: cmake --build build --target lldb install --parallel $(nproc) working-directory: core/deps/llvm-project + - name: validate lldb ubuntu + if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'ubuntu') + run: | + echo "start to validate lldb..." + mkdir -p wamr-debug + cmake -S product-mini/platforms/linux -B wamr-debug -DWAMR_BUILD_DEBUG_INTERP=1 + cmake --build wamr-debug --parallel $(nproc) + export LD_LIBRARY_PATH=$(pwd)/core/deps/python/lib:${LD_LIBRARY_PATH} + python3 ci/validate_lldb.py --port 1239 --lldb core/deps/wamr-lldb/bin/lldb --wamr wamr-debug/iwasm --verbose + working-directory: . + - name: build lldb macos if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos') run: | @@ -180,7 +205,7 @@ jobs: mkdir -p wamr-lldb/lib cp build/bin/lldb* wamr-lldb/bin cp lldb/tools/lldb-vscode/package.json wamr-lldb - cp -r lldb/tools/lldb-vscode/syntaxes/ wamr-lldb + cp -r lldb/tools/lldb-vscode/syntaxes/ wamr-lldb working-directory: core/deps/llvm-project - name: pack ubuntu specific libraries @@ -201,7 +226,7 @@ jobs: cp -R ../python/lib/python* wamr-lldb/lib cp ../python/lib/libpython*.dylib wamr-lldb/lib install_name_tool -change /install/lib/libpython${{ env.PYTHON_VERSION }}.dylib @rpath/libpython${{ env.PYTHON_VERSION }}.dylib wamr-lldb/lib/liblldb.*.dylib - # Patch path of python library -> https://github.com/indygreg/python-build-standalone/blob/85923ca3911784e6978b85d56e06e9ae75cb2dc4/docs/quirks.rst?plain=1#L412-L446 + # Patch path of python library -> https://github.com/indygreg/python-build-standalone/blob/85923ca3911784e6978b85d56e06e9ae75cb2dc4/docs/quirks.rst?plain=1#L412-L446 working-directory: core/deps/llvm-project - name: compress the binary diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index f965d2006..927ef4d75 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -72,7 +72,7 @@ jobs: with: os: "ubuntu-22.04" arch: "X86" - + build_wamrc: needs: [build_llvm_libraries_on_ubuntu_2204] @@ -241,6 +241,14 @@ jobs: cmake --build . --config Release --parallel 4 working-directory: product-mini/platforms/${{ matrix.platform }} + - name: Build and run unit tests + run: | + mkdir build-unittests && cd build-unittests + cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} + cmake --build . --config Release --parallel 4 + ctest + working-directory: tests/unit + build_samples_wasm_c_api: needs: [ @@ -483,6 +491,16 @@ jobs: sudo tar -xzf wasi-sdk-*.tar.gz sudo mv wasi-sdk-20.0 wasi-sdk + # It is a temporary solution until new wasi-sdk that includes bug fixes is released + - name: build wasi-libc from source + if: matrix.test_option == '$WASI_TEST_OPTIONS' + run: | + git clone https://github.com/WebAssembly/wasi-libc + cd wasi-libc + make -j AR=/opt/wasi-sdk/bin/llvm-ar NM=/opt/wasi-sdk/bin/llvm-nm CC=/opt/wasi-sdk/bin/clang THREAD_MODEL=posix + echo "SYSROOT_PATH=$PWD/sysroot" >> $GITHUB_ENV + + - name: set env variable(if llvm are used) if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit' run: echo "USE_LLVM=true" >> $GITHUB_ENV @@ -518,7 +536,7 @@ jobs: - name: Build WASI thread tests if: matrix.test_option == '$WASI_TEST_OPTIONS' - run: bash build.sh + run: bash build.sh --sysroot "$SYSROOT_PATH" working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/ - name: build socket api tests @@ -527,7 +545,7 @@ jobs: working-directory: ./core/iwasm/libraries/lib-socket/test/ - name: run tests - timeout-minutes: 10 + timeout-minutes: 30 run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites @@ -543,7 +561,7 @@ jobs: sudo apt install -y g++-multilib lib32gcc-9-dev - name: run tests x86_32 - timeout-minutes: 10 + timeout-minutes: 30 if: env.TEST_ON_X86_32 == 'true' run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites @@ -584,7 +602,7 @@ jobs: cache-name: cache-lldb-vscode with: path: test-tools/wamr-ide/VSCode-Extension/resource/debug/linux - key: ${{ env.cache-name }}-${{ hashFiles('build-scripts/lldb-wasm.patch') }}-${{ env.PYTHON_UBUNTU_STANDALONE_BUILD }} + key: ${{ env.cache-name }}-${{ hashFiles('build-scripts/lldb_wasm.patch') }}-${{ env.PYTHON_UBUNTU_STANDALONE_BUILD }} - if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }} name: get stand-alone python ubuntu @@ -607,7 +625,7 @@ jobs: git init git config user.email "action@github.com" git config user.name "github action" - git apply ../../../build-scripts/lldb-wasm.patch + git apply ../../../build-scripts/lldb_wasm.patch working-directory: core/deps/llvm-project - if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }} diff --git a/.github/workflows/hadolint_dockerfiles.yml b/.github/workflows/hadolint_dockerfiles.yml new file mode 100644 index 000000000..bdabeb6e5 --- /dev/null +++ b/.github/workflows/hadolint_dockerfiles.yml @@ -0,0 +1,47 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: hadolint dockerfiles + +on: + # will be triggered on PR events + pull_request: + types: + - opened + - synchronize + paths: + - "**/Dockerfile*" + - ".github/workflows/hadolint_dockerfiles.yml" + push: + branches: + - main + - "dev/**" + paths: + - "**/Dockerfile*" + - ".github/workflows/hadolint_dockerfiles.yml" + # allow to be triggered manually + workflow_dispatch: + +# Cancel any in-flight jobs for the same PR/branch so there's only one active +# at a time +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + run-hadolint-on-dockerfiles: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # on default, hadolint will fail on warnings and errors + - name: Run hadolint on dockerfiles + run: | + docker pull hadolint/hadolint:latest-debian + find . -name "*Dockerfile*" | while read dockerfile; do + echo "run hadolint on $dockerfile:" + docker run --rm -i hadolint/hadolint:latest-debian hadolint - <"$dockerfile" + echo "successful" + done \ No newline at end of file diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index 4664ad636..adedd1ef7 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -548,6 +548,16 @@ jobs: sudo wget ${{ matrix.wasi_sdk_release }} sudo tar -xzf wasi-sdk-*.tar.gz sudo mv wasi-sdk-20.0 wasi-sdk + + # It is a temporary solution until new wasi-sdk that includes bug fixes is released + - name: build wasi-libc from source + if: matrix.test_option == '$WASI_TEST_OPTIONS' + run: | + git clone https://github.com/WebAssembly/wasi-libc + cd wasi-libc + make -j AR=/opt/wasi-sdk/bin/llvm-ar NM=/opt/wasi-sdk/bin/llvm-nm CC=/opt/wasi-sdk/bin/clang THREAD_MODEL=posix + echo "SYSROOT_PATH=$PWD/sysroot" >> $GITHUB_ENV + - name: set env variable(if llvm are used) if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit' run: echo "USE_LLVM=true" >> $GITHUB_ENV @@ -586,16 +596,21 @@ jobs: - name: Build WASI thread tests if: matrix.test_option == '$WASI_TEST_OPTIONS' - run: bash build.sh + run: bash build.sh --sysroot "$SYSROOT_PATH" working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/ + - name: Build 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 working-directory: ./core/iwasm/libraries/lib-socket/test/ - name: run tests - timeout-minutes: 10 + timeout-minutes: 40 run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites @@ -611,7 +626,7 @@ jobs: sudo apt install -y g++-multilib lib32gcc-9-dev - name: run tests x86_32 - timeout-minutes: 10 + timeout-minutes: 40 if: env.TEST_ON_X86_32 == 'true' run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites \ No newline at end of file diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index 60b6bb1b7..c772b9691 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -22,7 +22,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the | third party components | version number | latest release | vendor pages | CVE details | | --- | --- | --- | --- | --- | -| cjson | 1.7.10 | 1.7.14 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html | +| cjson | 1.7.16 | 1.7.16 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html | | contiki-ng (er-coap) | unspecified | 3.0 | https://github.com/contiki-os/contiki | https://www.cvedetails.com/vendor/16528/Contiki-os.html | | freebsd libm | unspecified | 13.0 | https://www.freebsd.org/ | https://www.cvedetails.com/vendor/6/Freebsd.html | | LVGL | 6.0.1 | 7.11.0 | https://lvgl.io/ | | @@ -31,7 +31,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the | wasmtime | unspecified | v0.26.0 | https://github.com/bytecodealliance/wasmtime | | | zephyr | unspecified | v2.5.0 | https://www.zephyrproject.org/ | https://www.cvedetails.com/vendor/19255/Zephyrproject.html | | WebAssembly debugging patch for LLDB | unspecified | unspecified | https://reviews.llvm.org/D78801 | | -| libuv | v1.42.0 | v1.44.1 | https://github.com/libuv/libuv | https://www.cvedetails.com/vendor/15402/Libuv-Project.html | +| libuv | v1.46.0 | v1.46.0 | https://github.com/libuv/libuv | https://www.cvedetails.com/vendor/15402/Libuv-Project.html | | uvwasi | unspecified | v0.0.12 | https://github.com/nodejs/uvwasi | | | asmjit | unspecified | unspecified | https://github.com/asmjit/asmjit | | | zydis | unspecified | e14a07895136182a5b53e181eec3b1c6e0b434de | https://github.com/zyantific/zydis | | diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c8799494..fbea2616e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,11 @@ endif () set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +# Set the strip command based on the system (GNU or Clang) +if (CMAKE_STRIP) + set (CMAKE_STRIP_FLAGS "--strip-all") +endif () + include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wshadow -Wno-unused-parameter") @@ -141,6 +146,15 @@ endif () install (TARGETS iwasm_static ARCHIVE DESTINATION lib) +# If it's a Release build, strip the static library +if (CMAKE_STRIP AND CMAKE_BUILD_TYPE STREQUAL "Release") + # Strip static library + message (STATUS "Stripping static library after build!") + add_custom_command (TARGET iwasm_static POST_BUILD + COMMAND ${CMAKE_STRIP} ${CMAKE_STRIP_FLAGS} $ + ) +endif () + # SHARED LIBRARY add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE}) set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm) @@ -162,3 +176,12 @@ install (FILES ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h ${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h DESTINATION include) + +# If it's a Release build, strip the shared library +if (CMAKE_STRIP AND CMAKE_BUILD_TYPE STREQUAL "Release") + # Strip shared library + message (STATUS "Stripping shared library after build!") + add_custom_command (TARGET iwasm_shared POST_BUILD + COMMAND ${CMAKE_STRIP} ${CMAKE_STRIP_FLAGS} $ + ) +endif () diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index d6308ce67..5c7f598da 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,139 @@ +## WAMR-1.2.3 + +### Breaking Changes +- Increase default native stack size (#2332) + +### New Features +- Implement the segue optimization for LLVM AOT/JIT (#2230) +- Implement AOT static PGO (#2243) +- Enable static PGO for Linux SGX (#2270) +- Add Rust Formatters to Debugger (Vector, Map etc.) (#2219) + +### Bug Fixes +- The Python language-binding needs python>=3.9 (#2228) +- aot_compile_op_call: Remove a wrong optimization (#2233) +- Fix typo in samples/ref-types (#2236) +- Update thread proposal ignore cases (#2246) +- Disable writting GS register on linux-sgx platform (#2255) +- Fix compile error of wamrc with llvm-13/llvm-14 (#2261) +- aot/jit: Set module layout (#2260) +- Fix build error with LLVM 16 (#2259) +- spec-test-script: Disable conversions.wast on i386 (#2269) +- Fix a heap corruption bug in ems realloc (#2279) +- Fix fast-interp issue of LAST_OP_OUTPUT_I32/64 check (#2295) +- Fix wamrc build issues with LLVM 13 and LLVM 16 (#2313) +- aot: Move stack_sizes table to a dedicated section (#2317) +- product-mini/platforms/linux: Mark vmlib POSITION_INDEPENDENT_CODE (#2323) +- aot: Avoid possible relocations around "stack_sizes" for XIP mode (#2322) +- Avoid switch lowering to lookup tables for XIP (#2339) +- Fix typo in zephyr's Dockerfile.old (#2354) +- Fix typo (dwarf) in the codebase (#2367) +- Implement suspend flags as atomic variable (#2361) +- Fix llvm jit failed to lookup aot_stack_sizes symbol issue (#2384) +- Fix some check issues on table operations (#2392) +- Fix ExpandMemoryOpPass doesn't work properly (#2399) +- Fix non-builtin BH_ATOMIC_32_FETCH_OR and BH_ATOMIC_32_FETCH_AND (#2400) +- Fix wasi-sockets tests (#2389) +- Fix result arity check on select_t opcode (#2406) +- Re-organize intrinsics in aot_reloc_riscv.c to fix some FPU issues (#2414) +- Fix lib-pthread issues (#2410) +- Fix typo in test_wamr.sh (#2421) +- Fix memory sharing (#2415) +- wasm_export.h: Fix struct wasm_val_t (#2435) +- Fix typos in wamrc print_help() (#2442) +- iwasm: Fix native lib cleanup after error occurs (#2443) +- Correct --heap-size option in messages (#2458) +- wasm_instantiate: Fix a potential integer overflow issue (#2459) +- Fix windows link error and clear windows warnings (#2463) +- aot: Disable musttail for mips (#2457) +- Fix opcode overwrite issue in fast interp (#2476) +- wamrc: Fix windows relocation to `aot_func_internal#n` (#2474) +- Fix windows AOT hw bound check (#2475) +- Fix typo in aot_emit_aot_file.c (#2478) + +### Enhancements +- A few changes related to WAMRC_LLC_COMPILER (#2218) +- Enhance linux-sgx CI (#2102) +- Add asan and ubsan to WAMR CI (#2161) +- Update doc on WAMR_DISABLE_HW_BOUND_CHECK 32-bit (#2262) +- wamrc: Add an incompatibility note in the help message (#2276) +- Add cmake variable to disable writing gs register (#2284) +- Make hmu_tree_node 4 byte aligned to reduce compiler warning (#2268) +- Appease unused warning on min_uint64 (#2277) +- Fix format warning by PRIu32 in [wasm|aot] dump call stack (#2251) +- Fix a compile warning due to missing include (#2293) +- Fix dockerfile linter warnings (#2291) +- Enable windows x86-32 AOT relocations (#2285) +- wamr-ide: Add vscode extension tests (#2292) +- AOT/JIT native stack bound check improvement (#2244) +- Add retries to flaky step in nightly run CI (#2306) +- Use system libuv if available (#1861) +- wasi-nn: Simplify cmake and headers' location (#2308) +- wasi-nn: Improve tests paths for local dev (#2309) +- aot: Implement a few more relocation types for riscv (#2318) +- wasi-nn: Add support of wasi-nn as shared lib (#2310) +- Add a few more assertions on structures to which aot abi is sensitive (#2326) +- Fix sanitizer errors in posix socket (#2331) +- Add "--xip" option for wamrc (#2336) +- Add "--enable-llvm-passes=" option to wamrc (#2335) +- Make memory access boundary check behavior configurable (#2289) +- Migrate ExpandMemoryOpPass to llvm new pass manager (#2334) +- Allow defining hints without exact socket type or address family (#2337) +- wamrc: Warn on text relocations for XIP (#2340) +- Add scripts to validate lldb source debugger (#2150) +- Add docker file to fix Zephy ESP32 linking issue (#2314) +- Add "--native-lib=" option to wamrc (#2342) +- Fix unused warnings on disable_bounds_checks (#2347) +- Add "--enable-builtin-intrinsics=" option to wamrc (#2341) +- nuttx: Add a kconfig for wasi-threads (#2343) +- iwasm: Disable app heap by default if wasi is enabled (#2346) +- Fix some static scan issues (#2362) +- Bring up WAMR on esp32-s3 device (#2348) +- ESP-IDF platform supports to load AOT to PSRAM and run it (#2385) +- Add hadolint CI for Dockerfile linting (#2387) +- Move generic parts of wasm_suspend_flags.h to bh_atomic.h (#2393) +- bh_atomic.h: Add comments (#2398) +- bh_atomic.h: Add BH_ATOMIC_32_FETCH_ADD/BH_ATOMIC_32_FETCH_SUB (#2408) +- Update libuv version to v1.46.0 (#2405) +- Remove a few unused functions (#2409) +- Add initial stress test (#2364) +- Move wasm_runtime_destroy_wasi and wasi_nn_destroy calls together (#2418) +- embed_wamr.md: Improvements about threads (#2420) +- Add runtime inited checks in Enclave command handlings to improve security (#2416) +- Add some relocation symbols for xtensa target (#2422) +- Remove unnecessary and extra zero length check in mem functions' macro (#2428) +- Introduce WASMModuleInstanceExtraCommon (#2429) +- Strip static and shared libraries of iwasm to reduce the binary size (#2431) +- Auto-check wrgsbase in cmake script (#2437) +- iwasm: call native lib init/deinit if exists (#2439) +- wasi-nn: Support uint8 quantized networks (#2433) +- Implement `wasm_externref_objdel` and `wasm_externref_set_cleanup` (#2455) +- wasi-nn: Improve TPU support (#2447) +- wamr-python: Enable debugging WASM and grant dir access (#2449) +- Build wasi-libc from source in WAMR CI (#2465) +- wamrc: More friendly to print help info (#2451) +- Add another wamr test (#2411) +- Fix issues reported by Coverity and clear windows warnings (#2467) +- Clone the input binary during wasm_module_validate (#2483) + +### Others +- Nuttx CI: Ignore the expired certificate for riscv gcc toolchain (#2222) +- core/iwasm/compilation: constify a bit (#2223) +- Bump requests from 2.28.2 to 2.31.0 in /build-scripts (#2229) +- dwarf_extractor: Constify a bit (#2278) +- AOTFuncContext: Remove a stale comment (#2283) +- Add performance tunning document (#2286) +- Reduce CI jobs number (#2296) +- CI: Update used node version to 16 (#2303) +- Update Docker image for latest version of external libraries & tools (#2374) +- Upgrade cJSON version to v1.7.16 (#2404) +- Upgrade XNNPACK workload (#2394) +- Build more benchmarks in workload XNNPACK (#2417) +- Upgrade SGX-RA integration for 0.1.2 and Ubuntu 20.04 (#2454) +- Add sample pre-commit hook (#2470) + +--- + ## WAMR-1.2.2 ### Breaking Changes diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 572384dd8..eaedcc671 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -273,6 +273,13 @@ else () add_definitions (-DWASM_DISABLE_STACK_HW_BOUND_CHECK=0) endif () endif () +if (WAMR_DISABLE_WAKEUP_BLOCKING_OP EQUAL 1) + add_definitions (-DWASM_DISABLE_WAKEUP_BLOCKING_OP=1) + message (" Wakeup of blocking operations disabled") +else () + add_definitions (-DWASM_DISABLE_WAKEUP_BLOCKING_OP=0) + message (" Wakeup of blocking operations enabled") +endif () if (WAMR_BUILD_SIMD EQUAL 1) if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*") add_definitions (-DWASM_ENABLE_SIMD=1) @@ -363,16 +370,16 @@ endif () if (WAMR_BUILD_WASI_NN EQUAL 1) message (" WASI-NN enabled") add_definitions (-DWASM_ENABLE_WASI_NN=1) - if (WASI_NN_ENABLE_GPU EQUAL 1) + if (WAMR_BUILD_WASI_NN_ENABLE_GPU EQUAL 1) message (" WASI-NN: GPU enabled") - add_definitions (-DWASI_NN_ENABLE_GPU=1) + add_definitions (-DWASM_ENABLE_WASI_NN_GPU=1) endif () - if (WAMR_BUILD_WASI_NN_ENABLE_EXT EQUAL 1) + if (WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE EQUAL 1) message (" WASI-NN: External Delegation enabled") - add_definitions (-DWASI_NN_ENABLE_EXTERNAL_DELEGATE=1) + add_definitions (-DWASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE=1) endif () - if (DEFINED WASI_NN_EXT_DELEGATE_PATH) - add_definitions (-DWASI_NN_EXT_DELEGATE_PATH="${WASI_NN_EXT_DELEGATE_PATH}") + if (DEFINED WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH) + add_definitions (-DWASM_WASI_NN_EXTERNAL_DELEGATE_PATH="${WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH}") endif () endif () if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1) @@ -382,6 +389,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") @@ -399,4 +410,32 @@ endif () if (WAMR_DISABLE_WRITE_GS_BASE EQUAL 1) add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=1) message (" Write linear memory base addr to x86 GS register disabled") +elseif (WAMR_BUILD_TARGET STREQUAL "X86_64" + AND WAMR_BUILD_PLATFORM STREQUAL "linux") + set (TEST_WRGSBASE_SOURCE "${CMAKE_BINARY_DIR}/test_wrgsbase.c") + file (WRITE "${TEST_WRGSBASE_SOURCE}" " + #include + #include + int main() { + uint64_t value; + asm volatile (\"wrgsbase %0\" : : \"r\"(value)); + printf(\"WRGSBASE instruction is available.\\n\"); + return 0; + }") + # Try to compile and run the test program + try_run (TEST_WRGSBASE_RESULT + TEST_WRGSBASE_COMPILED + ${CMAKE_BINARY_DIR}/test_wrgsbase + SOURCES ${TEST_WRGSBASE_SOURCE} + CMAKE_FLAGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + ) + #message("${TEST_WRGSBASE_COMPILED}, ${TEST_WRGSBASE_RESULT}") + if (NOT TEST_WRGSBASE_RESULT EQUAL 0) + add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=1) + message (" Write linear memory base addr to x86 GS register disabled") + endif () +endif () +if (WAMR_CONFIGUABLE_BOUNDS_CHECKS EQUAL 1) + add_definitions (-DWASM_CONFIGURABLE_BOUNDS_CHECKS=1) + message (" Configurable bounds checks enabled") endif () diff --git a/build-scripts/lldb-wasm.patch b/build-scripts/lldb_wasm.patch similarity index 98% rename from build-scripts/lldb-wasm.patch rename to build-scripts/lldb_wasm.patch index d6044e3a3..83221ef6a 100644 --- a/build-scripts/lldb-wasm.patch +++ b/build-scripts/lldb_wasm.patch @@ -1,5 +1,44 @@ +diff --git a/lldb/bindings/CMakeLists.txt b/lldb/bindings/CMakeLists.txt +index 9759b069fdc4..25b427f8bcf2 100644 +--- a/lldb/bindings/CMakeLists.txt ++++ b/lldb/bindings/CMakeLists.txt +@@ -26,8 +26,6 @@ set(SWIG_COMMON_FLAGS + -features autodoc + -I${LLDB_SOURCE_DIR}/include + -I${CMAKE_CURRENT_SOURCE_DIR} +- -D__STDC_LIMIT_MACROS +- -D__STDC_CONSTANT_MACROS + ${DARWIN_EXTRAS} + ) + +diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig +index c9a6d0f06056..021c7683d170 100644 +--- a/lldb/bindings/interfaces.swig ++++ b/lldb/bindings/interfaces.swig +@@ -1,8 +1,5 @@ + /* Various liblldb typedefs that SWIG needs to know about. */ + #define __extension__ /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h. */ +-/* The ISO C99 standard specifies that in C++ implementations limit macros such +- as INT32_MAX should only be defined if __STDC_LIMIT_MACROS is. */ +-#define __STDC_LIMIT_MACROS + %include "stdint.i" + + %include "lldb/lldb-defines.h" +diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig +index b1ace4ff3b1e..5f8f4aa678c4 100644 +--- a/lldb/bindings/python/python-typemaps.swig ++++ b/lldb/bindings/python/python-typemaps.swig +@@ -439,7 +439,7 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { + + %typemap(out) lldb::FileSP { + $result = nullptr; +- lldb::FileSP &sp = $1; ++ const lldb::FileSP &sp = $1; + if (sp) { + PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp)); + if (!pyfile.IsValid()) diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h -index f2e2a0d22..426d1129b 100644 +index f2e2a0d22784..426d1129bd10 100644 --- a/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -9,6 +9,7 @@ @@ -11,7 +50,7 @@ index f2e2a0d22..426d1129b 100644 #include #include diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h -index dd7100c46..97d70daad 100644 +index dd7100c4616c..97d70daadbdc 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -41,6 +41,7 @@ @@ -41,7 +80,7 @@ index dd7100c46..97d70daad 100644 /// /// Tries to resolve \a vm_addr as a file address (if \a diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h -index be91929c6..8d876fc1f 100644 +index be91929c62e1..8d876fc1fa2f 100644 --- a/lldb/include/lldb/Core/PluginManager.h +++ b/lldb/include/lldb/Core/PluginManager.h @@ -508,6 +508,17 @@ public: @@ -64,7 +103,7 @@ index be91929c6..8d876fc1f 100644 } // namespace lldb_private diff --git a/lldb/include/lldb/Expression/DWARFEvaluator.h b/lldb/include/lldb/Expression/DWARFEvaluator.h new file mode 100644 -index 000000000..6811cbeae +index 000000000000..6811cbeae3d3 --- /dev/null +++ b/lldb/include/lldb/Expression/DWARFEvaluator.h @@ -0,0 +1,110 @@ @@ -180,7 +219,7 @@ index 000000000..6811cbeae +#endif // LLDB_EXPRESSION_DWARFEVALUATOR_H diff --git a/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h b/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h new file mode 100644 -index 000000000..f3b496c58 +index 000000000000..f3b496c580e4 --- /dev/null +++ b/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h @@ -0,0 +1,56 @@ @@ -241,7 +280,7 @@ index 000000000..f3b496c58 + +#endif // LLDB_EXPRESSION_DWARFEVALUATORFACTORY_H diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h -index 1490ac2d6..35c741d4e 100644 +index 1490ac2d614a..35c741d4e6ba 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -120,6 +120,10 @@ public: @@ -275,7 +314,7 @@ index 1490ac2d6..35c741d4e 100644 GetLocationExpression(lldb::addr_t load_function_start, lldb::addr_t addr) const; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h -index aaa2470d2..c15f2db52 100644 +index aaa2470d2931..c15f2db52fbc 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -1434,7 +1434,7 @@ public: @@ -288,7 +327,7 @@ index aaa2470d2..c15f2db52 100644 /// Read of memory from a process. /// diff --git a/lldb/include/lldb/Target/ProcessTrace.h b/lldb/include/lldb/Target/ProcessTrace.h -index 7b9d6b13d..9525fc975 100644 +index 7b9d6b13dd6f..9525fc9750fd 100644 --- a/lldb/include/lldb/Target/ProcessTrace.h +++ b/lldb/include/lldb/Target/ProcessTrace.h @@ -59,7 +59,7 @@ public: @@ -301,7 +340,7 @@ index 7b9d6b13d..9525fc975 100644 size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Status &error) override; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h -index ad5298151..5a3c0b27a 100644 +index ad5298151e4a..5a3c0b27a738 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -74,6 +74,7 @@ class Disassembler; @@ -313,7 +352,7 @@ index ad5298151..5a3c0b27a 100644 class EmulateInstruction; class Environment; diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h -index 2ed083ec8..f4d500d19 100644 +index 2ed083ec8ae9..f4d500d198e8 100644 --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -113,6 +113,8 @@ typedef lldb::REPLSP (*REPLCreateInstance)(Status &error, @@ -326,7 +365,7 @@ index 2ed083ec8..f4d500d19 100644 /// \{ typedef llvm::Expected (*TraceCreateInstanceForSessionFile)( diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp -index 19c97be15..1647f93ec 100644 +index 19c97be15066..1647f93ec4f3 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -16,6 +16,7 @@ @@ -348,7 +387,7 @@ index 19c97be15..1647f93ec 100644 + return m_dwarf_evaluator_factory.get(); +} diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp -index fcaa868b0..59a404d4a 100644 +index fcaa868b083e..59a404d4a7e1 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -1597,3 +1597,32 @@ bool PluginManager::CreateSettingForStructuredDataPlugin( @@ -385,7 +424,7 @@ index fcaa868b0..59a404d4a 100644 + return GetDWARFEvaluatorFactoryInstances().GetCallbackAtIndex(idx); +} diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp -index fb57c0fed..f92d6a54d 100644 +index fb57c0fedf04..f92d6a54de94 100644 --- a/lldb/source/Core/Value.cpp +++ b/lldb/source/Core/Value.cpp @@ -538,7 +538,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, @@ -398,7 +437,7 @@ index fb57c0fed..f92d6a54d 100644 error.SetErrorStringWithFormat( "read memory from 0x%" PRIx64 " failed (%u of %u bytes read)", diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp -index 9c1ba99da..b15b214b2 100644 +index 9c1ba99da1d0..b15b214b2a2f 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -735,7 +735,7 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx, @@ -411,7 +450,7 @@ index 9c1ba99da..b15b214b2 100644 data.SetData(data_sp); return bytes_read; diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt -index bf94361dd..4e76d547a 100644 +index bf94361dd6c1..4e76d547aeaf 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -1,5 +1,7 @@ @@ -424,7 +463,7 @@ index bf94361dd..4e76d547a 100644 ExpressionVariable.cpp diff --git a/lldb/source/Expression/DWARFEvaluator.cpp b/lldb/source/Expression/DWARFEvaluator.cpp new file mode 100644 -index 000000000..06107e136 +index 000000000000..06107e136197 --- /dev/null +++ b/lldb/source/Expression/DWARFEvaluator.cpp @@ -0,0 +1,1952 @@ @@ -2382,7 +2421,7 @@ index 000000000..06107e136 +} diff --git a/lldb/source/Expression/DWARFEvaluatorFactory.cpp b/lldb/source/Expression/DWARFEvaluatorFactory.cpp new file mode 100644 -index 000000000..c06126412 +index 000000000000..c0612641204a --- /dev/null +++ b/lldb/source/Expression/DWARFEvaluatorFactory.cpp @@ -0,0 +1,57 @@ @@ -2444,7 +2483,7 @@ index 000000000..c06126412 + object_address_ptr); +} diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp -index a10546c1d..4d13e4642 100644 +index a10546c1deae..4d13e4642af3 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -15,6 +15,8 @@ @@ -4261,7 +4300,7 @@ index a10546c1d..4d13e4642 100644 static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc, diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp -index 00e9ccb76..2137a1ac8 100644 +index 00e9ccb762c3..2137a1ac8324 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -759,6 +759,24 @@ void CommandInterpreter::LoadCommandDictionary() { @@ -4290,7 +4329,7 @@ index 00e9ccb76..2137a1ac8 100644 new CommandObjectRegexCommand( *this, "kdp-remote", diff --git a/lldb/source/Plugins/CMakeLists.txt b/lldb/source/Plugins/CMakeLists.txt -index 9181a4e47..2be6ec365 100644 +index 9181a4e47675..2be6ec3657c0 100644 --- a/lldb/source/Plugins/CMakeLists.txt +++ b/lldb/source/Plugins/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(ABI) @@ -4320,14 +4359,14 @@ index 9181a4e47..2be6ec365 100644 endif() diff --git a/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt b/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt new file mode 100644 -index 000000000..73fad41e1 +index 000000000000..73fad41e1a72 --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(wasm) diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt b/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt new file mode 100644 -index 000000000..e50b1bef7 +index 000000000000..e50b1bef7e69 --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt @@ -0,0 +1,10 @@ @@ -4343,7 +4382,7 @@ index 000000000..e50b1bef7 + ) diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp new file mode 100644 -index 000000000..fdda1991d +index 000000000000..fdda1991d19f --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp @@ -0,0 +1,126 @@ @@ -4475,7 +4514,7 @@ index 000000000..fdda1991d +} diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h new file mode 100644 -index 000000000..a01159064 +index 000000000000..a01159064a39 --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h @@ -0,0 +1,47 @@ @@ -4528,7 +4567,7 @@ index 000000000..a01159064 +#endif // LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATOR_H diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp new file mode 100644 -index 000000000..d43e96a34 +index 000000000000..d43e96a34d37 --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp @@ -0,0 +1,64 @@ @@ -4598,7 +4637,7 @@ index 000000000..d43e96a34 +} diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h new file mode 100644 -index 000000000..8a946592a +index 000000000000..8a946592a09a --- /dev/null +++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h @@ -0,0 +1,55 @@ @@ -4658,7 +4697,7 @@ index 000000000..8a946592a + +#endif // LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATORFACTORY_H diff --git a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp -index ae7e011ea..24ea75d19 100644 +index ae7e011eaa52..24ea75d1971c 100644 --- a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp @@ -62,6 +62,15 @@ void DynamicLoaderWasmDYLD::DidAttach() { @@ -4678,7 +4717,7 @@ index ae7e011ea..24ea75d19 100644 ThreadPlanSP DynamicLoaderWasmDYLD::GetStepThroughTrampolinePlan(Thread &thread, diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp -index 5272da9ab..abc5523bf 100644 +index 5272da9ab33a..abc5523bfd70 100644 --- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp +++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp @@ -23,6 +23,7 @@ @@ -4718,7 +4757,7 @@ index 5272da9ab..abc5523bf 100644 } } diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt -index 5f284e517..6084cbc93 100644 +index 5f284e517dca..6084cbc9378d 100644 --- a/lldb/source/Plugins/Platform/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/CMakeLists.txt @@ -15,3 +15,4 @@ @@ -4728,7 +4767,7 @@ index 5f284e517..6084cbc93 100644 +add_subdirectory(wasm-remote) diff --git a/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt b/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt new file mode 100644 -index 000000000..4a65765a5 +index 000000000000..4a65765a5659 --- /dev/null +++ b/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt @@ -0,0 +1,10 @@ @@ -4744,7 +4783,7 @@ index 000000000..4a65765a5 + ) diff --git a/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp new file mode 100644 -index 000000000..f26d11f00 +index 000000000000..f26d11f00e5c --- /dev/null +++ b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp @@ -0,0 +1,139 @@ @@ -4890,7 +4929,7 @@ index 000000000..f26d11f00 \ No newline at end of file diff --git a/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h new file mode 100644 -index 000000000..f306a79d3 +index 000000000000..f306a79d3f4f --- /dev/null +++ b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h @@ -0,0 +1,37 @@ @@ -4933,7 +4972,7 @@ index 000000000..f306a79d3 +#endif \ No newline at end of file diff --git a/lldb/source/Plugins/Plugins.def.in b/lldb/source/Plugins/Plugins.def.in -index bf54598fb..b0bd7b996 100644 +index bf54598fb2f3..b0bd7b9965fe 100644 --- a/lldb/source/Plugins/Plugins.def.in +++ b/lldb/source/Plugins/Plugins.def.in @@ -31,6 +31,7 @@ @@ -4945,7 +4984,7 @@ index bf54598fb..b0bd7b996 100644 #undef LLDB_PLUGIN diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt -index bea5bac9e..7a0855e02 100644 +index bea5bac9eb21..7a0855e02ca2 100644 --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -18,3 +18,4 @@ add_subdirectory(Utility) @@ -4954,7 +4993,7 @@ index bea5bac9e..7a0855e02 100644 add_subdirectory(minidump) +add_subdirectory(wasm) diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp -index 12bc7390c..707ab85e5 100644 +index 12bc7390c729..707ab85e5615 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -285,7 +285,7 @@ bool ProcessElfCore::IsAlive() { return true; } @@ -4967,7 +5006,7 @@ index 12bc7390c..707ab85e5 100644 // in core files we have it all cached our our core file anyway. return DoReadMemory(addr, buf, size, error); diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h -index d8e3cc9ae..f0bf9c4d3 100644 +index d8e3cc9ae3e1..f0bf9c4d3b00 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -84,7 +84,8 @@ public: @@ -4981,7 +5020,7 @@ index d8e3cc9ae..f0bf9c4d3 100644 size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Status &error) override; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp -index 6914b3734..bb8a05604 100644 +index 6914b37348ea..bb8a056049f3 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -334,6 +334,11 @@ ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); } @@ -5015,7 +5054,7 @@ index 6914b3734..bb8a05604 100644 } } diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h -index fe04cdddd..e4a14c645 100644 +index fe04cdddd0f5..e4a14c64579a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -237,6 +237,8 @@ protected: @@ -5028,7 +5067,7 @@ index fe04cdddd..e4a14c645 100644 enum { eBroadcastBitAsyncContinue = (1 << 0), diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp -index 84548edb5..0ae6f7e4a 100644 +index 84548edb5caa..0ae6f7e4a177 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -596,7 +596,7 @@ bool ProcessMachCore::WarnBeforeDetach() const { return false; } @@ -5041,7 +5080,7 @@ index 84548edb5..0ae6f7e4a 100644 // in core files we have it all cached our our core file anyway. return DoReadMemory(addr, buf, size, error); diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h -index db77e96f1..1c930896c 100644 +index db77e96f1072..1c930896c743 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h @@ -65,7 +65,8 @@ public: @@ -5055,7 +5094,7 @@ index db77e96f1..1c930896c 100644 size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Status &error) override; diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp -index 385557422..d8bb21581 100644 +index 385557422758..d8bb21581086 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -374,7 +374,7 @@ bool ProcessMinidump::IsAlive() { return true; } @@ -5068,7 +5107,7 @@ index 385557422..d8bb21581 100644 // we have it all cached in our dump file anyway. return DoReadMemory(addr, buf, size, error); diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h -index 27b0da004..e94ecab43 100644 +index 27b0da0047a5..e94ecab430c1 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h @@ -69,8 +69,8 @@ public: @@ -5084,7 +5123,7 @@ index 27b0da004..e94ecab43 100644 Status &error) override; diff --git a/lldb/source/Plugins/Process/wasm/CMakeLists.txt b/lldb/source/Plugins/Process/wasm/CMakeLists.txt new file mode 100644 -index 000000000..61efb933f +index 000000000000..61efb933fa62 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/CMakeLists.txt @@ -0,0 +1,12 @@ @@ -5102,7 +5141,7 @@ index 000000000..61efb933f + ) diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp new file mode 100644 -index 000000000..9c0fc7b7f +index 000000000000..9c0fc7b7f270 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp @@ -0,0 +1,261 @@ @@ -5369,7 +5408,7 @@ index 000000000..9c0fc7b7f +} diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h new file mode 100644 -index 000000000..d3aece7a6 +index 000000000000..d3aece7a6554 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h @@ -0,0 +1,128 @@ @@ -5503,7 +5542,7 @@ index 000000000..d3aece7a6 +#endif // LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp new file mode 100644 -index 000000000..fa02073e7 +index 000000000000..fa02073e7a52 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp @@ -0,0 +1,35 @@ @@ -5544,7 +5583,7 @@ index 000000000..fa02073e7 +} diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.h b/lldb/source/Plugins/Process/wasm/ThreadWasm.h new file mode 100644 -index 000000000..0a33c07de +index 000000000000..0a33c07de994 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.h @@ -0,0 +1,41 @@ @@ -5591,7 +5630,7 @@ index 000000000..0a33c07de +#endif // LLDB_SOURCE_PLUGINS_PROCESS_WASM_THREADWASM_H diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp new file mode 100644 -index 000000000..1a195cb93 +index 000000000000..1a195cb9361a --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp @@ -0,0 +1,74 @@ @@ -5672,7 +5711,7 @@ index 000000000..1a195cb93 \ No newline at end of file diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.h b/lldb/source/Plugins/Process/wasm/UnwindWasm.h new file mode 100644 -index 000000000..9bd1dac9a +index 000000000000..9bd1dac9a98a --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.h @@ -0,0 +1,55 @@ @@ -5732,7 +5771,7 @@ index 000000000..9bd1dac9a + +#endif // lldb_UnwindWasm_h_ diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp -index ccaf31317..c3ef5aebd 100644 +index ccaf31317d75..c3ef5aebd46d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3212,8 +3212,13 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, @@ -5751,7 +5790,7 @@ index ccaf31317..c3ef5aebd 100644 // DWARF doesn't specify if a DW_TAG_variable is a local, global // or static variable, so we have to do a little digging: diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp -index b660c310e..cd76421ce 100644 +index b660c310ef31..cd76421cec18 100644 --- a/lldb/source/Target/PathMappingList.cpp +++ b/lldb/source/Target/PathMappingList.cpp @@ -218,7 +218,12 @@ bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) co @@ -5769,7 +5808,7 @@ index b660c310e..cd76421ce 100644 return {}; diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp -index a77ecddfb..e257f9350 100644 +index a77ecddfbab6..e257f93508f6 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -1970,6 +1970,12 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target, @@ -5786,7 +5825,7 @@ index a77ecddfb..e257f9350 100644 return 0; } diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp -index 8ecc66b59..f14898791 100644 +index 8ecc66b592ea..f148987915de 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1892,7 +1892,8 @@ Status Process::DisableSoftwareBreakpoint(BreakpointSite *bp_site) { @@ -5800,7 +5839,7 @@ index 8ecc66b59..f14898791 100644 if (!GetDisableMemoryCache()) { #if defined(VERIFY_MEMORY_READS) diff --git a/lldb/source/Target/ProcessTrace.cpp b/lldb/source/Target/ProcessTrace.cpp -index c878a2ac4..ad5945b0a 100644 +index c878a2ac4eb9..ad5945b0ad1f 100644 --- a/lldb/source/Target/ProcessTrace.cpp +++ b/lldb/source/Target/ProcessTrace.cpp @@ -88,7 +88,7 @@ void ProcessTrace::RefreshStateAfterStop() {} @@ -5813,7 +5852,7 @@ index c878a2ac4..ad5945b0a 100644 // we have it all cached in the trace files. return DoReadMemory(addr, buf, size, error); diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp -index 896e647bb..f76307016 100644 +index 896e647bbb52..f76307016102 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -334,7 +334,10 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() { @@ -5829,7 +5868,7 @@ index 896e647bb..f76307016 100644 instructions->GetInstructionAtIndex(last_index); size_t last_inst_size = last_inst->GetOpcode().GetByteSize(); diff --git a/lldb/source/Target/UnixSignals.cpp b/lldb/source/Target/UnixSignals.cpp -index 4ec2e25c7..24c88fe9a 100644 +index 4ec2e25c7e3b..24c88fe9ae4f 100644 --- a/lldb/source/Target/UnixSignals.cpp +++ b/lldb/source/Target/UnixSignals.cpp @@ -46,6 +46,8 @@ lldb::UnixSignalsSP UnixSignals::Create(const ArchSpec &arch) { @@ -5842,7 +5881,7 @@ index 4ec2e25c7..24c88fe9a 100644 return std::make_shared(); } diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h -index 4310ba9ce..297b33879 100644 +index 4310ba9ce9e0..297b3387999d 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h @@ -13,6 +13,7 @@ @@ -5854,7 +5893,7 @@ index 4310ba9ce..297b33879 100644 #include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h" #include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h" diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h -index 753b1998c..27370c62d 100644 +index 753b1998c40c..27370c62dd6e 100644 --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -16,6 +16,7 @@ diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index 4c1fb064d..8ac519b77 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -91,8 +91,10 @@ endif () if (WAMR_BUILD_LIBC_UVWASI EQUAL 1) include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake) + set (WAMR_BUILD_MODULE_INST_CONTEXT 1) elseif (WAMR_BUILD_LIBC_WASI EQUAL 1) include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake) + set (WAMR_BUILD_MODULE_INST_CONTEXT 1) endif () if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1) diff --git a/ci/pre_commit_hook_sample b/ci/pre_commit_hook_sample new file mode 100755 index 000000000..682e78946 --- /dev/null +++ b/ci/pre_commit_hook_sample @@ -0,0 +1,32 @@ +#!/bin/bash + +# Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This is a sample of pre-commit hook that can be used to make your code fit the WAMR CI code style requirements. +# You need to have clang-format-12 installed to use this hook. +# To add this pre-commit hook, copy it to /.git/hooks/pre-commit +# (you don't need any extensions here) + +# Function to check if a file has a C or C++ extension + +is_c_or_cpp_file() { + file="$1" + if [[ "$filename" =~ \.(h|c|cpp)$ ]]; then + return 0 + else + return 1 + fi +} + +# Loop through staged files and apply command "abc" to C and C++ files +for staged_file in $(git diff --cached --name-only); do + if is_c_or_cpp_file "$staged_file"; then + clang-format-12 -Werror --style file --dry-run "$staged_file" 2>/dev/null + if [ $? -ne 0 ]; then + echo "Issues are found in $staged_file. Applying the fix" + clang-format-12 --style file -i "$staged_file" + fi + git add "$staged_file" # Add the modified file back to staging + fi +done diff --git a/ci/setup.sh b/ci/setup.sh new file mode 100755 index 000000000..ebdf73af5 --- /dev/null +++ b/ci/setup.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This script executes some commands to make your onboarding with WAMR easier. +# For example, setting pre-commit hook that will make your code complaint with the +# code style requirements checked in WAMR CI + +echo "Copy the pre-commit hook to your hooks folder" +cp pre_commit_hook_sample ../.git/hooks/pre-commit + +# Feel free to propose your commands to this script to make developing WAMR easier + +echo "Setup is done" diff --git a/ci/validate_lldb.py b/ci/validate_lldb.py new file mode 100755 index 000000000..1b431ada8 --- /dev/null +++ b/ci/validate_lldb.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import argparse +import time +from pathlib import Path +import subprocess, shlex + +SCRIPT_DIR = Path(__file__).parent.resolve() +REPO_ROOT_DIR = SCRIPT_DIR.parent +SAMPLE_CODE_FILE = REPO_ROOT_DIR / 'product-mini/app-samples/hello-world/main.c' +WASM_OUT_FILE = SCRIPT_DIR / 'out.wasm' + +parser = argparse.ArgumentParser( + description="Validate the customized lldb with sample code" +) +parser.add_argument( + "-l", "--lldb", dest='lldb', default='lldb', help="path to lldb executable" +) +parser.add_argument( + "-w", "--wamr", dest='wamr', default='iwasm', help="path to iwasm executable" +) +parser.add_argument( + "-p", "--port", dest='port', default='1234', help="debug server listen port" +) +parser.add_argument( + "-v", "--verbose", dest='verbose', action='store_true', default=False, help="display lldb stdout" +) + +options = parser.parse_args() + +lldb_command_epilogue = '-o q' + +test_cases = { + 'run_to_exit': '-o c', + 'func_breakpoint': '-o "b main" -o c -o c', + 'line_breakpoint': '-o "b main.c:12" -o c -o c', + 'break_on_unknown_func': '-o "b not_a_func" -o c', + 'watch_point': '-o "b main" -o c -o "watchpoint set variable buf" -o c -o "fr v buf" -o c', +} + +# Step1: Build wasm module with debug information +build_cmd = f'/opt/wasi-sdk/bin/clang -g -O0 -o {WASM_OUT_FILE} {SAMPLE_CODE_FILE}' +try: + print(f'building wasm module ...', end='', flush=True) + subprocess.check_call(shlex.split(build_cmd)) + print(f'\t OK') +except subprocess.CalledProcessError: + print("Failed to build wasm module with debug information") + exit(1) + +def print_process_output(p): + try: + outs, errs = p.communicate(timeout=2) + print("stdout:") + print(outs) + print("stderr:") + print(errs) + except subprocess.TimeoutExpired: + print("Failed to get process output") + +# Step2: Launch WAMR in debug mode and validate lldb commands + +iteration = 0 +for case, cmd in test_cases.items(): + lldb_command_prologue = f'{options.lldb} -o "process connect -p wasm connect://127.0.0.1:{int(options.port) + iteration}"' + wamr_cmd = f'{options.wamr} -g=127.0.0.1:{int(options.port) + iteration} {WASM_OUT_FILE}' + iteration += 1 + + has_error = False + print(f'validating case [{case}] ...', end='', flush=True) + lldb_cmd = f'{lldb_command_prologue} {cmd} {lldb_command_epilogue}' + + wamr_process = subprocess.Popen(shlex.split( + wamr_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + + time.sleep(0.1) + if (wamr_process.poll() != None): + print("\nWAMR doesn't wait for lldb connection") + print_process_output(wamr_process) + exit(1) + + lldb_process = subprocess.Popen(shlex.split( + lldb_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + + if (options.verbose): + while (lldb_process.poll() is None): + print(lldb_process.stdout.read(), end='', flush=True) + + try: + if (lldb_process.wait(5) != 0): + print(f"\nFailed to validate case [{case}]") + print_process_output(lldb_process) + has_error = True + + if wamr_process.wait(2) != 0: + print("\nWAMR process doesn't exit normally") + print_process_output(wamr_process) + has_error = True + + except subprocess.TimeoutExpired: + print(f"\nFailed to validate case [{case}]") + print("wamr output:") + print_process_output(wamr_process) + print("lldb output:") + print_process_output(lldb_process) + has_error = True + finally: + if (lldb_process.poll() == None): + print(f'\nterminating lldb process [{lldb_process.pid}]') + lldb_process.kill() + if (wamr_process.poll() == None): + print(f'terminating wamr process [{wamr_process.pid}]') + wamr_process.kill() + + if (has_error): + exit(1) + + print(f'\t OK') + + # wait 100ms to ensure the socket is closed + time.sleep(0.1) + +print('Validate lldb success') +exit(0) diff --git a/core/config.h b/core/config.h index 6701f53af..120149b9b 100644 --- a/core/config.h +++ b/core/config.h @@ -144,6 +144,14 @@ #define WASM_ENABLE_WASI_NN 0 #endif +#ifndef WASM_ENABLE_WASI_NN_GPU +#define WASM_ENABLE_WASI_NN_GPU 0 +#endif + +#ifndef WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE +#define WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE 0 +#endif + /* Default disable libc emcc */ #ifndef WASM_ENABLE_LIBC_EMCC #define WASM_ENABLE_LIBC_EMCC 0 @@ -384,7 +392,7 @@ #define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024) #define APP_THREAD_STACK_SIZE_MIN (48 * 1024) #else -#define APP_THREAD_STACK_SIZE_DEFAULT (32 * 1024) +#define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024) #define APP_THREAD_STACK_SIZE_MIN (24 * 1024) #endif #endif /* end of !(defined(APP_THREAD_STACK_SIZE_DEFAULT) \ @@ -460,4 +468,25 @@ #define WASM_DISABLE_WRITE_GS_BASE 0 #endif +/* Configurable bounds checks */ +#ifndef WASM_CONFIGURABLE_BOUNDS_CHECKS +#define WASM_CONFIGURABLE_BOUNDS_CHECKS 0 +#endif + +/* Some chip cannot support external ram with rwx attr at the same time, + it has to map it into 2 spaces of idbus and dbus, code in dbus can be + read/written and read/executed in ibus. so there are 2 steps to execute + the code, first, copy&do relocaiton in dbus space, and second execute + it in ibus space, since in the 2 spaces the contents are the same, + so we call it bus mirror. + */ +#ifndef WASM_MEM_DUAL_BUS_MIRROR +#define WASM_MEM_DUAL_BUS_MIRROR 0 +#endif + +/* The max number of module instance contexts. */ +#ifndef WASM_MAX_INSTANCE_CONTEXTS +#define WASM_MAX_INSTANCE_CONTEXTS 8 +#endif + #endif /* end of _CONFIG_H_ */ diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index 319eeda5c..189b43b09 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -648,6 +648,42 @@ add_f64_common_intrinsics(AOTCompContext *comp_ctx) add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CMP); } +static void +add_f32xi32_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F32); +} + +static void +add_f64xi32_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F64); +} + +static void +add_f32xi64_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F32); +} + +static void +add_f64xi64_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F64); +} + static void add_common_float_integer_convertion(AOTCompContext *comp_ctx) { @@ -705,8 +741,101 @@ aot_intrinsic_check_capability(const AOTCompContext *comp_ctx, void aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx) { + uint32 i; + memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags)); + /* Intrinsics from command line have highest priority */ + + if (comp_ctx->builtin_intrinsics) { + + /* Handle 'all' group */ + if (strstr(comp_ctx->builtin_intrinsics, "all")) { + for (i = 0; i < g_intrinsic_count; i++) { + add_intrinsic_capability(comp_ctx, g_intrinsic_mapping[i].flag); + } + return; + } + + /* Handle 'i32.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "i32.common")) { + add_i32_common_intrinsics(comp_ctx); + } + + /* Handle 'i64.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "i64.common")) { + add_i64_common_intrinsics(comp_ctx); + } + + /* Handle 'fp.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "fp.common")) { + add_f32_common_intrinsics(comp_ctx); + add_f64_common_intrinsics(comp_ctx); + } + + /* Handle 'f32.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f32.common")) { + add_f32_common_intrinsics(comp_ctx); + } + + /* Handle 'f64.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f64.common")) { + add_f64_common_intrinsics(comp_ctx); + } + + /* Handle 'f32xi32' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f32xi32")) { + add_f32xi32_intrinsics(comp_ctx); + } + + /* Handle 'f64xi32' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f64xi32")) { + add_f64xi32_intrinsics(comp_ctx); + } + + /* Handle 'f32xi64' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f32xi64")) { + add_f32xi64_intrinsics(comp_ctx); + } + + /* Handle 'f64xi64' group */ + if (strstr(comp_ctx->builtin_intrinsics, "f64xi64")) { + add_f64xi64_intrinsics(comp_ctx); + } + + /* Handle 'fpxint' group */ + if (strstr(comp_ctx->builtin_intrinsics, "fpxint")) { + add_f32xi32_intrinsics(comp_ctx); + add_f64xi32_intrinsics(comp_ctx); + add_f32xi64_intrinsics(comp_ctx); + add_f64xi64_intrinsics(comp_ctx); + } + + /* Handle 'constop' group */ + if (strstr(comp_ctx->builtin_intrinsics, "constop")) { + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_CONST); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CONST); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CONST); + } + + /* Handle 'fp.common' group */ + if (strstr(comp_ctx->builtin_intrinsics, "fp.common")) { + add_f32_common_intrinsics(comp_ctx); + add_f64_common_intrinsics(comp_ctx); + } + + /* Handle other single items */ + for (i = 0; i < g_intrinsic_count; i++) { + if (strstr(comp_ctx->builtin_intrinsics, + g_intrinsic_mapping[i].llvm_intrinsic)) { + add_intrinsic_capability(comp_ctx, g_intrinsic_mapping[i].flag); + } + } + + return; + } + if (!comp_ctx->target_cpu) return; diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 2f4dcd31a..0ce2cf9da 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -1644,27 +1644,6 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, const uint8 *p = buf, *p_end = buf_end; uint32 i; uint64 size, text_offset; -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - RUNTIME_FUNCTION *rtl_func_table; - AOTUnwindInfo *unwind_info; - uint32 unwind_info_offset = module->code_size - sizeof(AOTUnwindInfo); - uint32 unwind_code_offset = unwind_info_offset - PLT_ITEM_SIZE; -#endif - -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - unwind_info = (AOTUnwindInfo *)((uint8 *)module->code + module->code_size - - sizeof(AOTUnwindInfo)); - unwind_info->Version = 1; - unwind_info->Flags = UNW_FLAG_NHANDLER; - *(uint32 *)&unwind_info->UnwindCode[0] = unwind_code_offset; - - size = sizeof(RUNTIME_FUNCTION) * (uint64)module->func_count; - if (size > 0 - && !(rtl_func_table = module->rtl_func_table = - loader_malloc(size, error_buf, error_buf_size))) { - return false; - } -#endif size = sizeof(void *) * (uint64)module->func_count; if (size > 0 @@ -1691,33 +1670,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, #if defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_THUMB_VFP) /* bits[0] of thumb function address must be 1 */ module->func_ptrs[i] = (void *)((uintptr_t)module->func_ptrs[i] | 1); -#endif -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - rtl_func_table[i].BeginAddress = (DWORD)text_offset; - if (i > 0) { - rtl_func_table[i - 1].EndAddress = rtl_func_table[i].BeginAddress; - } - rtl_func_table[i].UnwindInfoAddress = (DWORD)unwind_info_offset; #endif } -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - if (module->func_count > 0) { - uint32 plt_table_size = - module->is_indirect_mode ? 0 : get_plt_table_size(); - rtl_func_table[module->func_count - 1].EndAddress = - (DWORD)(module->code_size - plt_table_size); - - if (!RtlAddFunctionTable(rtl_func_table, module->func_count, - (DWORD64)(uintptr_t)module->code)) { - set_error_buf(error_buf, error_buf_size, - "add dynamic function table failed"); - return false; - } - module->rtl_func_table_registered = true; - } -#endif - /* Set start function when function pointers are resolved */ if (module->start_func_index != (uint32)-1) { if (module->start_func_index >= module->import_func_count) @@ -3013,6 +2968,9 @@ create_sections(AOTModule *module, const uint8 *buf, uint32 size, uint32 section_size; uint64 total_size; uint8 *aot_text; +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + uint8 *mirrored_text; +#endif if (!resolve_execute_mode(buf, size, &is_indirect_mode, error_buf, error_buf_size)) { @@ -3071,8 +3029,17 @@ create_sections(AOTModule *module, const uint8 *buf, uint32 size, bh_assert((uintptr_t)aot_text < INT32_MAX); #endif #endif + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + mirrored_text = os_get_dbus_mirror(aot_text); + bh_assert(mirrored_text != NULL); + bh_memcpy_s(mirrored_text, (uint32)total_size, + section->section_body, (uint32)section_size); + os_dcache_flush(); +#else bh_memcpy_s(aot_text, (uint32)total_size, section->section_body, (uint32)section_size); +#endif section->section_body = aot_text; destroy_aot_text = true; @@ -3249,14 +3216,6 @@ aot_unload(AOTModule *module) } #endif -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - if (module->rtl_func_table) { - if (module->rtl_func_table_registered) - RtlDeleteFunctionTable(module->rtl_func_table); - wasm_runtime_free(module->rtl_func_table); - } -#endif - #if (defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)) \ && !defined(BH_PLATFORM_WINDOWS) { diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 815704bd0..55cf2d985 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -42,6 +42,9 @@ bh_static_assert(offsetof(AOTModuleInstance, cur_exception) bh_static_assert(offsetof(AOTModuleInstance, global_table_data) == 13 * sizeof(uint64) + 128 + 11 * sizeof(uint64)); +bh_static_assert(sizeof(AOTMemoryInstance) == 104); +bh_static_assert(offsetof(AOTTableInstance, elems) == 8); + bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0); static void @@ -336,11 +339,8 @@ memories_deinstantiate(AOTModuleInstance *module_inst) memory_inst = module_inst->memories[i]; if (memory_inst) { #if WASM_ENABLE_SHARED_MEMORY != 0 - if (memory_inst->is_shared) { - int32 ref_count = shared_memory_dec_reference( - (WASMModuleCommon *)module_inst->module); - bh_assert(ref_count >= 0); - + if (shared_memory_is_shared(memory_inst)) { + uint32 ref_count = shared_memory_dec_reference(memory_inst); /* if the reference count is not zero, don't free the memory */ if (ref_count > 0) @@ -370,9 +370,10 @@ memories_deinstantiate(AOTModuleInstance *module_inst) } static AOTMemoryInstance * -memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, - AOTMemoryInstance *memory_inst, AOTMemory *memory, - uint32 heap_size, char *error_buf, uint32 error_buf_size) +memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, + AOTModule *module, AOTMemoryInstance *memory_inst, + AOTMemory *memory, uint32 memory_idx, uint32 heap_size, + char *error_buf, uint32 error_buf_size) { void *heap_handle; uint32 num_bytes_per_page = memory->num_bytes_per_page; @@ -393,23 +394,13 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, bool is_shared_memory = memory->memory_flags & 0x02 ? true : false; /* Shared memory */ - if (is_shared_memory) { + if (is_shared_memory && parent != NULL) { AOTMemoryInstance *shared_memory_instance; - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module); - /* If the memory of this module has been instantiated, - return the memory instance directly */ - if (node) { - uint32 ref_count; - ref_count = shared_memory_inc_reference((WASMModuleCommon *)module); - bh_assert(ref_count > 0); - shared_memory_instance = - (AOTMemoryInstance *)shared_memory_get_memory_inst(node); - bh_assert(shared_memory_instance); - - (void)ref_count; - return shared_memory_instance; - } + bh_assert(memory_idx == 0); + bh_assert(parent->memory_count > memory_idx); + shared_memory_instance = parent->memories[memory_idx]; + shared_memory_inc_reference(shared_memory_instance); + return shared_memory_instance; } #endif @@ -429,7 +420,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, if (num_bytes_per_page < heap_size) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " - "try using `--heap_size=0` option"); + "try using `--heap-size=0` option"); return NULL; } } @@ -487,7 +478,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, if (init_page_count > DEFAULT_MAX_PAGES) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " - "try using `--heap_size=0` option"); + "try using `--heap-size=0` option"); return NULL; } else if (init_page_count == DEFAULT_MAX_PAGES) { @@ -606,23 +597,12 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, #if WASM_ENABLE_SHARED_MEMORY != 0 if (is_shared_memory) { - memory_inst->is_shared = true; - if (!shared_memory_set_memory_inst( - (WASMModuleCommon *)module, - (WASMMemoryInstanceCommon *)memory_inst)) { - set_error_buf(error_buf, error_buf_size, "allocate memory failed"); - goto fail3; - } + memory_inst->ref_count = 1; } #endif return memory_inst; -#if WASM_ENABLE_SHARED_MEMORY != 0 -fail3: - if (heap_size > 0) - mem_allocator_destroy(memory_inst->heap_handle); -#endif fail2: if (heap_size > 0) wasm_runtime_free(memory_inst->heap_handle); @@ -651,8 +631,9 @@ aot_get_default_memory(AOTModuleInstance *module_inst) } static bool -memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module, - uint32 heap_size, char *error_buf, uint32 error_buf_size) +memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, + AOTModule *module, uint32 heap_size, char *error_buf, + uint32 error_buf_size) { uint32 global_index, global_data_offset, base_offset, length; uint32 i, memory_count = module->memory_count; @@ -669,8 +650,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module, memories = module_inst->global_table_data.memory_instances; for (i = 0; i < memory_count; i++, memories++) { - memory_inst = memory_instantiate(module_inst, module, memories, - &module->memories[i], heap_size, + memory_inst = memory_instantiate(module_inst, parent, module, memories, + &module->memories[i], i, heap_size, error_buf, error_buf_size); if (!memory_inst) { return false; @@ -1097,9 +1078,9 @@ check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size) } AOTModuleInstance * -aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main, - uint32 stack_size, uint32 heap_size, char *error_buf, - uint32 error_buf_size) +aot_instantiate(AOTModule *module, AOTModuleInstance *parent, + WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size) { AOTModuleInstance *module_inst; const uint32 module_inst_struct_size = @@ -1109,6 +1090,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main, uint64 total_size, table_size = 0; uint8 *p; uint32 i, extra_info_offset; + const bool is_sub_inst = parent != NULL; /* Check heap size */ heap_size = align_uint(heap_size, 8); @@ -1168,7 +1150,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main, goto fail; /* Initialize memory space */ - if (!memories_instantiate(module_inst, module, heap_size, error_buf, + if (!memories_instantiate(module_inst, parent, module, heap_size, error_buf, error_buf_size)) goto fail; @@ -1261,16 +1243,6 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton); } -#if WASM_ENABLE_LIBC_WASI != 0 - /* Destroy wasi resource before freeing app heap, since some fields of - wasi contex are allocated from app heap, and if app heap is freed, - these fields will be set to NULL, we cannot free their internal data - which may allocated from global heap. */ - /* Only destroy wasi ctx in the main module instance */ - if (!is_sub_inst) - wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); -#endif - #if WASM_ENABLE_PERF_PROFILING != 0 if (module_inst->func_perf_profilings) wasm_runtime_free(module_inst->func_perf_profilings); @@ -1299,14 +1271,16 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) if (module_inst->func_type_indexes) wasm_runtime_free(module_inst->func_type_indexes); - if (((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports) - wasm_runtime_free( - ((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports); + if (((AOTModuleInstanceExtra *)module_inst->e)->common.c_api_func_imports) + wasm_runtime_free(((AOTModuleInstanceExtra *)module_inst->e) + ->common.c_api_func_imports); + if (!is_sub_inst) { #if WASM_ENABLE_WASI_NN != 0 - if (!is_sub_inst) wasi_nn_destroy(module_inst); #endif + wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst); + } wasm_runtime_free(module_inst); } @@ -1467,6 +1441,9 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, /* set thread handle and stack boundary */ wasm_exec_env_set_thread_info(exec_env); + /* set exec env so it can be later retrieved from instance */ + ((AOTModuleInstanceExtra *)module_inst->e)->common.cur_exec_env = exec_env; + if (ext_ret_count > 0) { uint32 cell_num = 0, i; uint8 *ext_ret_types = func_type->types + func_type->param_count + 1; @@ -1949,8 +1926,8 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, AOTModuleInstanceExtra *module_inst_extra = (AOTModuleInstanceExtra *)module_inst->e; CApiFuncImport *c_api_func_import = - module_inst_extra->c_api_func_imports - ? module_inst_extra->c_api_func_imports + func_idx + module_inst_extra->common.c_api_func_imports + ? module_inst_extra->common.c_api_func_imports + func_idx : NULL; uint32 *func_type_indexes = module_inst->func_type_indexes; uint32 func_type_idx = func_type_indexes[func_idx]; @@ -2486,13 +2463,13 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, tbl_seg = module->table_init_data_list[tbl_seg_idx]; bh_assert(tbl_seg); - if (!length) { + if (offset_len_out_of_bounds(src_offset, length, tbl_seg->func_index_count) + || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) { + aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } - if (length + src_offset > tbl_seg->func_index_count - || dst_offset + length > tbl_inst->cur_size) { - aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); + if (!length) { return; } @@ -2525,8 +2502,9 @@ aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx, dst_tbl_inst = module_inst->tables[dst_tbl_idx]; bh_assert(dst_tbl_inst); - if ((uint64)dst_offset + length > dst_tbl_inst->cur_size - || (uint64)src_offset + length > src_tbl_inst->cur_size) { + if (offset_len_out_of_bounds(dst_offset, length, dst_tbl_inst->cur_size) + || offset_len_out_of_bounds(src_offset, length, + src_tbl_inst->cur_size)) { aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } @@ -2551,7 +2529,7 @@ aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length, tbl_inst = module_inst->tables[tbl_idx]; bh_assert(tbl_inst); - if (data_offset + length > tbl_inst->cur_size) { + if (offset_len_out_of_bounds(data_offset, length, tbl_inst->cur_size)) { aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 5aaac41b7..4358e3079 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -89,33 +89,9 @@ typedef struct AOTFunctionInstance { typedef struct AOTModuleInstanceExtra { DefPointer(const uint32 *, stack_sizes); - CApiFuncImport *c_api_func_imports; + WASMModuleInstanceExtraCommon common; } AOTModuleInstanceExtra; -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) -/* clang-format off */ -typedef struct AOTUnwindInfo { - uint8 Version : 3; - uint8 Flags : 5; - uint8 SizeOfProlog; - uint8 CountOfCodes; - uint8 FrameRegister : 4; - uint8 FrameOffset : 4; - struct { - struct { - uint8 CodeOffset; - uint8 UnwindOp : 4; - uint8 OpInfo : 4; - }; - uint16 FrameOffset; - } UnwindCode[1]; -} AOTUnwindInfo; -/* clang-format on */ - -/* size of mov instruction and jmp instruction */ -#define PLT_ITEM_SIZE 12 -#endif - #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) typedef struct GOTItem { uint32 func_idx; @@ -211,14 +187,6 @@ typedef struct AOTModule { uint32 float_plt_count; #endif -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - /* dynamic function table to be added by RtlAddFunctionTable(), - used to unwind the call stack and register exception handler - for AOT functions */ - RUNTIME_FUNCTION *rtl_func_table; - bool rtl_func_table_registered; -#endif - #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) uint32 got_item_count; GOTItemList got_item_list; @@ -402,7 +370,7 @@ aot_unload(AOTModule *module); * Instantiate a AOT module. * * @param module the AOT module to instantiate - * @param is_sub_inst the flag of sub instance + * @param parent the parent module instance * @param heap_size the default heap size of the module instance, a heap will * be created besides the app memory space. Both wasm app and native * function can allocate memory from the heap. If heap_size is 0, the @@ -413,9 +381,9 @@ aot_unload(AOTModule *module); * @return return the instantiated AOT module instance, NULL if failed */ AOTModuleInstance * -aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main, - uint32 stack_size, uint32 heap_size, char *error_buf, - uint32 error_buf_size); +aot_instantiate(AOTModule *module, AOTModuleInstance *parent, + WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size); /** * Deinstantiate a AOT module instance, destroy the resources. diff --git a/core/iwasm/aot/arch/aot_reloc_arm.c b/core/iwasm/aot/arch/aot_reloc_arm.c index fbf9be13c..5d79e8a68 100644 --- a/core/iwasm/aot/arch/aot_reloc_arm.c +++ b/core/iwasm/aot/arch/aot_reloc_arm.c @@ -40,6 +40,7 @@ void __aeabi_ldivmod(); void __aeabi_memcpy(); void __aeabi_memmove(); void __aeabi_memset(); +void __aeabi_memclr(); void __aeabi_uidiv(); void __aeabi_uidivmod(); void __aeabi_ul2d(); @@ -126,6 +127,7 @@ static SymbolMap target_sym_map[] = { REG_SYM(__aeabi_memcpy), REG_SYM(__aeabi_memmove), REG_SYM(__aeabi_memset), + REG_SYM(__aeabi_memclr), REG_SYM(__aeabi_uidiv), REG_SYM(__aeabi_uidivmod), REG_SYM(__aeabi_ul2d), diff --git a/core/iwasm/aot/arch/aot_reloc_riscv.c b/core/iwasm/aot/arch/aot_reloc_riscv.c index 219319020..7798d55c6 100644 --- a/core/iwasm/aot/arch/aot_reloc_riscv.c +++ b/core/iwasm/aot/arch/aot_reloc_riscv.c @@ -78,6 +78,13 @@ static SymbolMap target_sym_map[] = { REG_SYM(__addsf3), REG_SYM(__divdf3), REG_SYM(__divsf3), + REG_SYM(__eqdf2), + REG_SYM(__eqsf2), + REG_SYM(__extendsfdf2), + REG_SYM(__fixunsdfdi), + REG_SYM(__fixunsdfsi), + REG_SYM(__fixunssfdi), + REG_SYM(__fixunssfsi), REG_SYM(__gedf2), REG_SYM(__gesf2), REG_SYM(__gtdf2), @@ -89,44 +96,33 @@ static SymbolMap target_sym_map[] = { REG_SYM(__muldf3), REG_SYM(__nedf2), REG_SYM(__nesf2), - REG_SYM(__eqsf2), - REG_SYM(__eqdf2), - REG_SYM(__extendsfdf2), - REG_SYM(__fixunsdfdi), - REG_SYM(__fixunsdfsi), - REG_SYM(__fixunssfsi), REG_SYM(__subdf3), REG_SYM(__subsf3), REG_SYM(__truncdfsf2), REG_SYM(__unorddf2), REG_SYM(__unordsf2), -#endif - REG_SYM(__divdi3), - REG_SYM(__divsi3), #if __riscv_xlen == 32 REG_SYM(__fixdfdi), REG_SYM(__fixdfsi), REG_SYM(__fixsfdi), REG_SYM(__fixsfsi), -#endif - REG_SYM(__fixunssfdi), -#if __riscv_xlen == 32 REG_SYM(__floatdidf), REG_SYM(__floatdisf), - REG_SYM(__floatsisf), REG_SYM(__floatsidf), + REG_SYM(__floatsisf), REG_SYM(__floatundidf), REG_SYM(__floatundisf), - REG_SYM(__floatunsisf), REG_SYM(__floatunsidf), -#endif - REG_SYM(__moddi3), - REG_SYM(__modsi3), - REG_SYM(__muldi3), -#if __riscv_xlen == 32 + REG_SYM(__floatunsisf), REG_SYM(__mulsf3), REG_SYM(__mulsi3), #endif +#endif + REG_SYM(__divdi3), + REG_SYM(__divsi3), + REG_SYM(__moddi3), + REG_SYM(__modsi3), + REG_SYM(__muldi3), REG_SYM(__udivdi3), REG_SYM(__udivsi3), REG_SYM(__umoddi3), diff --git a/core/iwasm/aot/arch/aot_reloc_x86_32.c b/core/iwasm/aot/arch/aot_reloc_x86_32.c index 9246836c3..0a423c398 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_32.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_32.c @@ -164,6 +164,9 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, (uint32)((uintptr_t)symbol_addr + (intptr_t)reloc_addend - (uintptr_t)(target_section_addr + (uint32)reloc_offset) +#if defined(BH_PLATFORM_WINDOWS) + - sizeof(int32) +#endif + value); /* S + A - P */ break; } diff --git a/core/iwasm/aot/arch/aot_reloc_x86_64.c b/core/iwasm/aot/arch/aot_reloc_x86_64.c index 1221a6297..b5be24593 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_64.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_64.c @@ -69,9 +69,6 @@ get_plt_table_size() { uint32 size = get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - size += get_plt_item_size() + sizeof(AOTUnwindInfo); -#endif return size; } @@ -93,18 +90,6 @@ init_plt_table(uint8 *plt) *p++ = 0xE0; plt += get_plt_item_size(); } - -#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - p = plt; - /* mov exception_handler, rax */ - *p++ = 0x48; - *p++ = 0xB8; - *(uint64 *)p = 0; /*(uint64)(uintptr_t)aot_exception_handler;*/ - p += sizeof(uint64); - /* jmp rax */ - *p++ = 0xFF; - *p++ = 0xE0; -#endif } static bool @@ -242,7 +227,7 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, - (uintptr_t)(target_section_addr + reloc_offset)); } else { - target_addr = (intptr_t) /* L + A - P */ + target_addr = (intptr_t) /* S + A - P */ ((uintptr_t)symbol_addr + reloc_addend - (uintptr_t)(target_section_addr + reloc_offset)); } diff --git a/core/iwasm/aot/arch/aot_reloc_xtensa.c b/core/iwasm/aot/arch/aot_reloc_xtensa.c index 3327c396f..a29c9f2b9 100644 --- a/core/iwasm/aot/arch/aot_reloc_xtensa.c +++ b/core/iwasm/aot/arch/aot_reloc_xtensa.c @@ -43,6 +43,11 @@ void __floatdidf(); void __divsf3(); void __fixdfdi(); void __floatundidf(); +void __fixsfdi(); +void __fixunssfdi(); +void __fixunsdfdi(); +void __floatdisf(); +void __floatundisf(); static SymbolMap target_sym_map[] = { @@ -85,6 +90,11 @@ static SymbolMap target_sym_map[] = { REG_SYM(__divsf3), REG_SYM(__fixdfdi), REG_SYM(__floatundidf), + REG_SYM(__fixsfdi), + REG_SYM(__fixunssfdi), + REG_SYM(__fixunsdfdi), + REG_SYM(__floatdisf), + REG_SYM(__floatundisf), }; /* clang-format on */ @@ -207,6 +217,10 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, case R_XTENSA_32: { uint8 *insn_addr = target_section_addr + reloc_offset; +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + insn_addr = os_get_dbus_mirror((void *)insn_addr); + bh_assert(insn_addr != NULL); +#endif int32 initial_addend; /* (S + A) */ if ((intptr_t)insn_addr & 3) { @@ -265,6 +279,11 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, return false; } +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + insn_addr = os_get_dbus_mirror((void *)insn_addr); + bh_assert(insn_addr != NULL); + l32r_insn = (l32r_insn_t *)insn_addr; +#endif imm16 = (int16)(relative_offset >> 2); /* write back the imm16 to the l32r instruction */ @@ -285,7 +304,6 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, #if __GNUC__ >= 9 #pragma GCC diagnostic pop #endif - break; } diff --git a/core/iwasm/aot/iwasm_aot.cmake b/core/iwasm/aot/iwasm_aot.cmake index 8014f2372..efff88dd0 100644 --- a/core/iwasm/aot/iwasm_aot.cmake +++ b/core/iwasm/aot/iwasm_aot.cmake @@ -36,5 +36,49 @@ if (WAMR_BUILD_DEBUG_AOT EQUAL 1) file(GLOB debug_source ${IWASM_AOT_DIR}/debug/*.c) endif() -set (IWASM_AOT_SOURCE ${c_source_all} ${arch_source} ${debug_source}) +if ((WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + AND (WAMR_BUILD_PLATFORM STREQUAL "windows") + AND (NOT WAMR_DISABLE_HW_BOUND_CHECK EQUAL 1)) + include(FetchContent) + FetchContent_Declare( + zycore + GIT_REPOSITORY https://github.com/zyantific/zycore-c.git + ) + FetchContent_GetProperties(zycore) + if (NOT zycore_POPULATED) + message ("-- Fetching zycore ..") + FetchContent_Populate(zycore) + include_directories("${zycore_SOURCE_DIR}/include") + include_directories("${zycore_BINARY_DIR}") + add_definitions(-DZYCORE_STATIC_BUILD=1) + add_subdirectory(${zycore_SOURCE_DIR} ${zycore_BINARY_DIR} EXCLUDE_FROM_ALL) + file (GLOB_RECURSE c_source_zycore ${zycore_SOURCE_DIR}/src/*.c) + endif () + + FetchContent_Declare( + zydis + GIT_REPOSITORY https://github.com/zyantific/zydis.git + GIT_TAG e14a07895136182a5b53e181eec3b1c6e0b434de + ) + FetchContent_GetProperties(zydis) + if (NOT zydis_POPULATED) + message ("-- Fetching zydis ..") + FetchContent_Populate(zydis) + option(ZYDIS_FEATURE_ENCODER "" OFF) + option(ZYDIS_BUILD_TOOLS "" OFF) + option(ZYDIS_BUILD_EXAMPLES "" OFF) + option(ZYDIS_BUILD_MAN "" OFF) + option(ZYDIS_BUILD_DOXYGEN "" OFF) + include_directories("${zydis_BINARY_DIR}") + include_directories("${zydis_SOURCE_DIR}/include") + include_directories("${zydis_SOURCE_DIR}/src") + add_definitions(-DZYDIS_STATIC_BUILD=1) + add_subdirectory(${zydis_SOURCE_DIR} ${zydis_BINARY_DIR} EXCLUDE_FROM_ALL) + file (GLOB_RECURSE c_source_zydis ${zydis_SOURCE_DIR}/src/*.c) + endif () +endif () + + +set (IWASM_AOT_SOURCE ${c_source_all} ${arch_source} ${debug_source} + ${c_source_zycore} ${c_source_zydis}) diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 2ed217e7a..795d65c8c 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -107,7 +107,34 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) the actual main function. Directly calling main function may cause exception thrown. */ if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) { - return wasm_runtime_call_wasm(exec_env, func, 0, NULL); + const char *wasi_proc_exit_exception = "wasi proc exit"; + + ret = wasm_runtime_call_wasm(exec_env, func, 0, NULL); +#if WASM_ENABLE_THREAD_MGR != 0 + if (ret) { + /* On a successful return from the `_start` function, + we terminate other threads by mimicing wasi:proc_exit(0). + + Note: + - A return from the `main` function is an equivalent of + exit(). (C standard) + - When exit code is 0, wasi-libc's `_start` function just + returns w/o calling `proc_exit`. + - A process termination should terminate threads in + the process. */ + + wasm_runtime_set_exception(module_inst, wasi_proc_exit_exception); + /* exit_code is zero-initialized */ + ret = false; + } +#endif + /* report wasm proc exit as a success */ + WASMModuleInstance *inst = (WASMModuleInstance *)module_inst; + if (!ret && strstr(inst->cur_exception, wasi_proc_exit_exception)) { + inst->cur_exception[0] = 0; + ret = true; + } + return ret; } #endif /* end of WASM_ENABLE_LIBC_WASI */ diff --git a/core/iwasm/common/wasm_blocking_op.c b/core/iwasm/common/wasm_blocking_op.c new file mode 100644 index 000000000..25777c8d7 --- /dev/null +++ b/core/iwasm/common/wasm_blocking_op.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_runtime_common.h" + +#include "bh_platform.h" +#include "bh_common.h" +#include "bh_assert.h" + +#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP) + +#define LOCK(env) WASM_SUSPEND_FLAGS_LOCK((env)->wait_lock) +#define UNLOCK(env) WASM_SUSPEND_FLAGS_UNLOCK((env)->wait_lock) + +#define ISSET(env, bit) \ + ((WASM_SUSPEND_FLAGS_GET((env)->suspend_flags) & WASM_SUSPEND_FLAG_##bit) \ + != 0) +#define SET(env, bit) \ + WASM_SUSPEND_FLAGS_FETCH_OR((env)->suspend_flags, WASM_SUSPEND_FLAG_##bit) +#define CLR(env, bit) \ + WASM_SUSPEND_FLAGS_FETCH_AND((env)->suspend_flags, ~WASM_SUSPEND_FLAG_##bit) + +bool +wasm_runtime_begin_blocking_op(wasm_exec_env_t env) +{ + LOCK(env); + bh_assert(!ISSET(env, BLOCKING)); + SET(env, BLOCKING); + if (ISSET(env, TERMINATE)) { + CLR(env, BLOCKING); + UNLOCK(env); + return false; + } + UNLOCK(env); + os_begin_blocking_op(); + return true; +} + +void +wasm_runtime_end_blocking_op(wasm_exec_env_t env) +{ + int saved_errno = errno; + LOCK(env); + bh_assert(ISSET(env, BLOCKING)); + CLR(env, BLOCKING); + UNLOCK(env); + os_end_blocking_op(); + errno = saved_errno; +} + +void +wasm_runtime_interrupt_blocking_op(wasm_exec_env_t env) +{ + /* + * ISSET(BLOCKING) here means that the target thread + * is in somewhere between wasm_begin_blocking_op and + * wasm_end_blocking_op. + * keep waking it up until it reaches wasm_end_blocking_op, + * which clears the BLOCKING bit. + * + * this dumb loop is necessary because posix doesn't provide + * a way to unmask signal and block atomically. + */ + + LOCK(env); + SET(env, TERMINATE); + while (ISSET(env, BLOCKING)) { + UNLOCK(env); + os_wakeup_blocking_op(env->handle); + + /* relax a bit */ + os_usleep(50 * 1000); + LOCK(env); + } + UNLOCK(env); +} + +#else /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */ + +bool +wasm_runtime_begin_blocking_op(wasm_exec_env_t env) +{ + return true; +} + +void +wasm_runtime_end_blocking_op(wasm_exec_env_t env) +{} + +#endif /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */ diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 7b8cf4779..2da733874 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -2290,8 +2290,10 @@ quit: bool wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary) { + wasm_byte_vec_t local_binary = { 0 }; struct WASMModuleCommon *module_rt; char error_buf[128] = { 0 }; + bool ret; bh_assert(singleton_engine); @@ -2300,15 +2302,25 @@ wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary) return false; } - if ((module_rt = wasm_runtime_load((uint8 *)binary->data, - (uint32)binary->size, error_buf, 128))) { + /* make a copy of binary */ + wasm_byte_vec_copy(&local_binary, binary); + + if (binary->size && !local_binary.data) + return false; + + module_rt = wasm_runtime_load((uint8 *)local_binary.data, + (uint32)local_binary.size, error_buf, 128); + wasm_byte_vec_delete(&local_binary); + if (module_rt) { wasm_runtime_unload(module_rt); - return true; + ret = true; } else { + ret = false; LOG_VERBOSE(error_buf); - return false; } + + return ret; } static void @@ -4858,7 +4870,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) { WASMModuleInstanceExtra *e = ((WASMModuleInstance *)instance->inst_comm_rt)->e; - p_func_imports = &(e->c_api_func_imports); + p_func_imports = &(e->common.c_api_func_imports); import_func_count = MODULE_INTERP(module)->import_function_count; } #endif @@ -4868,7 +4880,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, (AOTModuleInstanceExtra *)((AOTModuleInstance *) instance->inst_comm_rt) ->e; - p_func_imports = &(e->c_api_func_imports); + p_func_imports = &(e->common.c_api_func_imports); import_func_count = MODULE_AOT(module)->import_func_count; } #endif diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index 29b28a159..bf9892080 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -7,6 +7,7 @@ #define _WASM_EXEC_ENV_H #include "bh_assert.h" +#include "wasm_suspend_flags.h" #if WASM_ENABLE_INTERP != 0 #include "../interpreter/wasm.h" #endif @@ -57,15 +58,8 @@ typedef struct WASMExecEnv { exception. */ uint8 *native_stack_boundary; - /* Used to terminate or suspend current thread - bit 0: need to terminate - bit 1: need to suspend - bit 2: need to go into breakpoint - bit 3: return from pthread_exit */ - union { - uint32 flags; - uintptr_t __padding__; - } suspend_flags; + /* Used to terminate or suspend current thread */ + WASMSuspendFlags suspend_flags; /* Auxiliary stack boundary */ union { diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 310dab6d2..05635ef51 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -5,8 +5,10 @@ #include "wasm_runtime_common.h" #include "../interpreter/wasm_runtime.h" +#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" @@ -23,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; @@ -87,6 +92,16 @@ wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func, } #endif +static inline bool +is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + return wasm_runtime_is_bounds_checks_enabled(module_inst); +#else + return true; +#endif +} + bool wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type, const MemAllocOption *alloc_option) @@ -269,6 +284,10 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm, bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + if (!is_bounds_checks_enabled(module_inst_comm)) { + return true; + } + memory_inst = wasm_get_default_memory(module_inst); if (!memory_inst) { goto fail; @@ -299,6 +318,10 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm, bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + if (!is_bounds_checks_enabled(module_inst_comm)) { + return true; + } + if (!wasm_runtime_get_app_addr_range(module_inst_comm, app_str_offset, NULL, &app_end_offset)) goto fail; @@ -327,6 +350,10 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm, bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + if (!is_bounds_checks_enabled(module_inst_comm)) { + return true; + } + memory_inst = wasm_get_default_memory(module_inst); if (!memory_inst) { goto fail; @@ -354,10 +381,13 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm, WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst; uint8 *addr; + bool bounds_checks; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + bounds_checks = is_bounds_checks_enabled(module_inst_comm); + memory_inst = wasm_get_default_memory(module_inst); if (!memory_inst) { return NULL; @@ -365,8 +395,17 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm, addr = memory_inst->memory_data + app_offset; - if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end) + if (bounds_checks) { + if (memory_inst->memory_data <= addr + && addr < memory_inst->memory_data_end) { + + return addr; + } + } + /* If bounds checks is disabled, return the address directly */ + else if (app_offset != 0) { return addr; + } return NULL; } @@ -378,17 +417,27 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm, WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst; uint8 *addr = (uint8 *)native_ptr; + bool bounds_checks; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); + bounds_checks = is_bounds_checks_enabled(module_inst_comm); + memory_inst = wasm_get_default_memory(module_inst); if (!memory_inst) { return 0; } - if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end) + if (bounds_checks) { + if (memory_inst->memory_data <= addr + && addr < memory_inst->memory_data_end) + return (uint32)(addr - memory_inst->memory_data); + } + /* If bounds checks is disabled, return the offset directly */ + else if (addr != NULL) { return (uint32)(addr - memory_inst->memory_data); + } return 0; } @@ -460,6 +509,7 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, { WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst); uint8 *native_addr; + bool bounds_checks; if (!memory_inst) { goto fail; @@ -467,6 +517,15 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, native_addr = memory_inst->memory_data + app_buf_addr; + bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst); + + if (!bounds_checks) { + if (app_buf_addr == 0) { + native_addr = NULL; + } + goto success; + } + /* No need to check the app_offset and buf_size if memory access boundary check with hardware trap is enabled */ #ifndef OS_ENABLE_HW_BOUND_CHECK @@ -492,6 +551,7 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, } #endif +success: *p_native_addr = (void *)native_addr; return true; fail: @@ -514,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); @@ -538,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); @@ -552,7 +621,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) } #if WASM_ENABLE_SHARED_MEMORY != 0 - if (memory->is_shared) { + if (shared_memory_is_shared(memory)) { memory->num_bytes_per_page = num_bytes_per_page; memory->cur_page_count = total_page_count; memory->max_page_count = max_page_count; @@ -566,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, @@ -629,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 @@ -636,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; @@ -654,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); @@ -671,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 @@ -683,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, @@ -703,62 +807,53 @@ 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) { bool ret = false; #if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module->module); - if (node) - os_mutex_lock(&node->shared_mem_lock); + if (module->memory_count > 0) + shared_memory_lock(module->memories[0]); #endif ret = wasm_enlarge_memory_internal(module, inc_page_count); #if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_unlock(&node->shared_mem_lock); + if (module->memory_count > 0) + shared_memory_unlock(module->memories[0]); #endif return ret; } - -#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ - || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ - || WASM_ENABLE_BULK_MEMORY != 0 -uint32 -wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node) -{ - uint32 num_bytes_per_page; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock); -#endif - num_bytes_per_page = memory->num_bytes_per_page; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock); -#endif - return num_bytes_per_page; -} - -uint32 -wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node) -{ - uint32 linear_mem_size; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock); -#endif - linear_mem_size = memory->num_bytes_per_page * memory->cur_page_count; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock); -#endif - return linear_mem_size; -} -#endif diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index 1324742fe..daca2b71e 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/core/iwasm/common/wasm_memory.h @@ -24,15 +24,9 @@ wasm_runtime_memory_destroy(); unsigned wasm_runtime_memory_pool_size(); -#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ - || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ - || WASM_ENABLE_BULK_MEMORY != 0 -uint32 -wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node); - -uint32 -wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node); -#endif +void +wasm_runtime_set_enlarge_mem_error_callback( + const enlarge_memory_error_callback_t callback, void *user_data); #ifdef __cplusplus } diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 1acaed6ee..0a5851349 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -6,6 +6,15 @@ #include "wasm_native.h" #include "wasm_runtime_common.h" #include "bh_log.h" +#if WASM_ENABLE_INTERP != 0 +#include "../interpreter/wasm_runtime.h" +#endif +#if WASM_ENABLE_AOT != 0 +#include "../aot/aot_runtime.h" +#endif +#if WASM_ENABLE_THREAD_MGR != 0 +#include "../libraries/thread-mgr/thread_manager.h" +#endif #if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \ && !defined(BH_PLATFORM_OPENRTOS) && !defined(BH_PLATFORM_ESP_IDF) @@ -22,6 +31,10 @@ static NativeSymbolsList g_native_symbols_list = NULL; +#if WASM_ENABLE_LIBC_WASI != 0 +static void *g_wasi_context_key; +#endif /* WASM_ENABLE_LIBC_WASI */ + uint32 get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis); @@ -394,6 +407,155 @@ wasm_native_unregister_natives(const char *module_name, return false; } +#if WASM_ENABLE_MODULE_INST_CONTEXT != 0 +static uint32 +context_key_to_idx(void *key) +{ + bh_assert(key != NULL); + uint32 idx = (uint32)(uintptr_t)key; + bh_assert(idx > 0); + bh_assert(idx <= WASM_MAX_INSTANCE_CONTEXTS); + return idx - 1; +} + +static void * +context_idx_to_key(uint32 idx) +{ + bh_assert(idx < WASM_MAX_INSTANCE_CONTEXTS); + return (void *)(uintptr_t)(idx + 1); +} + +typedef void (*dtor_t)(WASMModuleInstanceCommon *, void *); +static dtor_t g_context_dtors[WASM_MAX_INSTANCE_CONTEXTS]; + +static void +dtor_noop(WASMModuleInstanceCommon *inst, void *ctx) +{} + +void * +wasm_native_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst, + void *ctx)) +{ + uint32 i; + for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) { + if (g_context_dtors[i] == NULL) { + if (dtor == NULL) { + dtor = dtor_noop; + } + g_context_dtors[i] = dtor; + return context_idx_to_key(i); + } + } + LOG_ERROR("failed to allocate instance context key"); + return NULL; +} + +void +wasm_native_destroy_context_key(void *key) +{ + uint32 idx = context_key_to_idx(key); + bh_assert(g_context_dtors[idx] != NULL); + g_context_dtors[idx] = NULL; +} + +static WASMModuleInstanceExtraCommon * +wasm_module_inst_extra_common(WASMModuleInstanceCommon *inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (inst->module_type == Wasm_Module_Bytecode) { + return &((WASMModuleInstance *)inst)->e->common; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (inst->module_type == Wasm_Module_AoT) { + return &((AOTModuleInstanceExtra *)((AOTModuleInstance *)inst)->e) + ->common; + } +#endif + bh_assert(false); + return NULL; +} + +void +wasm_native_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx) +{ + uint32 idx = context_key_to_idx(key); + WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst); + common->contexts[idx] = ctx; +} + +void +wasm_native_set_context_spread(WASMModuleInstanceCommon *inst, void *key, + void *ctx) +{ +#if WASM_ENABLE_THREAD_MGR != 0 + wasm_cluster_set_context(inst, key, ctx); +#else + wasm_native_set_context(inst, key, ctx); +#endif +} + +void * +wasm_native_get_context(WASMModuleInstanceCommon *inst, void *key) +{ + uint32 idx = context_key_to_idx(key); + WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst); + return common->contexts[idx]; +} + +void +wasm_native_call_context_dtors(WASMModuleInstanceCommon *inst) +{ + WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst); + uint32 i; + for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) { + dtor_t dtor = g_context_dtors[i]; + if (dtor != NULL) { + dtor(inst, common->contexts[i]); + } + } +} + +void +wasm_native_inherit_contexts(WASMModuleInstanceCommon *child, + WASMModuleInstanceCommon *parent) +{ + WASMModuleInstanceExtraCommon *parent_common = + wasm_module_inst_extra_common(parent); + WASMModuleInstanceExtraCommon *child_common = + wasm_module_inst_extra_common(child); + bh_memcpy_s(child_common->contexts, + sizeof(*child_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS, + parent_common->contexts, + sizeof(*parent_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS); +} +#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */ + +#if WASM_ENABLE_LIBC_WASI != 0 +WASIContext * +wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm) +{ + return wasm_native_get_context(module_inst_comm, g_wasi_context_key); +} + +void +wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm, + WASIContext *wasi_ctx) +{ + return wasm_native_set_context(module_inst_comm, g_wasi_context_key, + wasi_ctx); +} + +static void +wasi_context_dtor(WASMModuleInstanceCommon *inst, void *ctx) +{ + if (ctx == NULL) { + return; + } + wasm_runtime_destroy_wasi(inst); +} +#endif /* end of WASM_ENABLE_LIBC_WASI */ + bool wasm_native_init() { @@ -420,6 +582,10 @@ wasm_native_init() #endif /* WASM_ENABLE_SPEC_TEST */ #if WASM_ENABLE_LIBC_WASI != 0 + g_wasi_context_key = wasm_native_create_context_key(wasi_context_dtor); + if (g_wasi_context_key == NULL) { + goto fail; + } n_native_symbols = get_libc_wasi_export_apis(&native_symbols); if (!wasm_native_register_natives("wasi_unstable", native_symbols, n_native_symbols)) @@ -507,6 +673,12 @@ wasm_native_destroy() { NativeSymbolsNode *node, *node_next; +#if WASM_ENABLE_LIBC_WASI != 0 + if (g_wasi_context_key != NULL) { + wasm_native_destroy_context_key(g_wasi_context_key); + g_wasi_context_key = NULL; + } +#endif #if WASM_ENABLE_LIB_PTHREAD != 0 lib_pthread_destroy(); #endif diff --git a/core/iwasm/common/wasm_native.h b/core/iwasm/common/wasm_native.h index 4f6645d25..9ca5265c3 100644 --- a/core/iwasm/common/wasm_native.h +++ b/core/iwasm/common/wasm_native.h @@ -68,6 +68,36 @@ bool wasm_native_unregister_natives(const char *module_name, NativeSymbol *native_symbols); +#if WASM_ENABLE_MODULE_INST_CONTEXT != 0 +struct WASMModuleInstanceCommon; + +void * +wasm_native_create_context_key( + void (*dtor)(struct WASMModuleInstanceCommon *inst, void *ctx)); + +void +wasm_native_destroy_context_key(void *key); + +void +wasm_native_set_context(struct WASMModuleInstanceCommon *inst, void *key, + void *ctx); +void +wasm_native_set_context_spread(struct WASMModuleInstanceCommon *inst, void *key, + void *ctx); +void * +wasm_native_get_context(struct WASMModuleInstanceCommon *inst, void *key); + +void +wasm_native_call_context_dtors(struct WASMModuleInstanceCommon *inst); + +void +wasm_native_inherit_contexts(struct WASMModuleInstanceCommon *child, + struct WASMModuleInstanceCommon *parent); +#else /* WASM_ENABLE_MODULE_INST_CONTEXT */ +#define wasm_native_call_context_dtors(inst) (void)(inst) +#define wasm_native_inherit_contexts(child, parent) (void)(parent) +#endif /* WASM_ENABLE_MODULE_INST_CONTEXT */ + bool wasm_native_init(); diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index b2923db33..353985b13 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -199,7 +199,90 @@ runtime_signal_handler(void *sig_addr) } } } -#else +#else /* else of BH_PLATFORM_WINDOWS */ + +#if WASM_ENABLE_AOT != 0 +#include + +static uint32 +decode_insn(uint8 *insn) +{ + uint8 *data = (uint8 *)insn; + uint32 length = 32; /* reserve enough size */ + + /* Initialize decoder context */ + ZydisDecoder decoder; + ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, + ZYDIS_STACK_WIDTH_64); + + /* Initialize formatter */ + ZydisFormatter formatter; + ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); + + /* Loop over the instructions in our buffer */ + ZyanU64 runtime_address = (ZyanU64)(uintptr_t)data; + ZyanUSize offset = 0; + ZydisDecodedInstruction instruction; + ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE]; + char buffer[256]; + + if (ZYAN_SUCCESS(ZydisDecoderDecodeFull( + &decoder, data + offset, length - offset, &instruction, operands, + ZYDIS_MAX_OPERAND_COUNT_VISIBLE, + ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY))) { + + /* Format & print the binary instruction structure to + human readable format */ + ZydisFormatterFormatInstruction(&formatter, &instruction, operands, + instruction.operand_count_visible, + buffer, sizeof(buffer), + runtime_address); + + /* Print current instruction */ + /* + os_printf("%012" PRIX64 " ", runtime_address); + puts(buffer); + */ + + return instruction.length; + } + + /* Decode failed */ + return 0; +} +#endif /* end of WASM_ENABLE_AOT != 0 */ + +static LONG +next_action(WASMModuleInstance *module_inst, EXCEPTION_POINTERS *exce_info) +{ +#if WASM_ENABLE_AOT != 0 + uint32 insn_size; +#endif + + if (module_inst->module_type == Wasm_Module_Bytecode + && module_inst->e->running_mode == Mode_Interp) { + /* Continue to search next exception handler for + interpreter mode as it can be caught by + `__try { .. } __except { .. }` sentences in + wasm_runtime.c */ + return EXCEPTION_CONTINUE_SEARCH; + } + +#if WASM_ENABLE_AOT != 0 + /* Skip current instruction and continue to run for AOT/JIT mode. + TODO: implement unwind support for AOT/JIT code in Windows platform */ + insn_size = decode_insn((uint8 *)exce_info->ContextRecord->Rip); + if (insn_size > 0) { + exce_info->ContextRecord->Rip += insn_size; + return EXCEPTION_CONTINUE_EXECUTION; + } +#endif + + /* return different value from EXCEPTION_CONTINUE_SEARCH (= 0) + and EXCEPTION_CONTINUE_EXECUTION (= -1) */ + return -2; +} + static LONG runtime_exception_handler(EXCEPTION_POINTERS *exce_info) { @@ -211,6 +294,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) uint8 *mapped_mem_start_addr = NULL; uint8 *mapped_mem_end_addr = NULL; uint32 page_size = os_getpagesize(); + LONG ret; if (exec_env_tls && exec_env_tls->handle == os_self_thread() && (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) { @@ -232,32 +316,19 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) the wasm func returns, the caller will check whether the exception is thrown and return to runtime. */ wasm_set_exception(module_inst, "out of bounds memory access"); - if (module_inst->module_type == Wasm_Module_Bytecode) { - /* Continue to search next exception handler for - interpreter mode as it can be caught by - `__try { .. } __except { .. }` sentences in - wasm_runtime.c */ - return EXCEPTION_CONTINUE_SEARCH; - } - else { - /* Skip current instruction and continue to run for - AOT mode. TODO: implement unwind support for AOT - code in Windows platform */ - exce_info->ContextRecord->Rip++; - return EXCEPTION_CONTINUE_EXECUTION; - } + ret = next_action(module_inst, exce_info); + if (ret == EXCEPTION_CONTINUE_SEARCH + || ret == EXCEPTION_CONTINUE_EXECUTION) + return ret; } else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr && (uint8 *)sig_addr < exec_env_tls->exce_check_guard_page + page_size) { bh_assert(wasm_copy_exception(module_inst, NULL)); - if (module_inst->module_type == Wasm_Module_Bytecode) { - return EXCEPTION_CONTINUE_SEARCH; - } - else { - exce_info->ContextRecord->Rip++; - return EXCEPTION_CONTINUE_EXECUTION; - } + ret = next_action(module_inst, exce_info); + if (ret == EXCEPTION_CONTINUE_SEARCH + || ret == EXCEPTION_CONTINUE_EXECUTION) + return ret; } } #if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 @@ -267,12 +338,10 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) whether the exception is thrown and return to runtime, and the damaged stack will be recovered by _resetstkoflw(). */ wasm_set_exception(module_inst, "native stack overflow"); - if (module_inst->module_type == Wasm_Module_Bytecode) { - return EXCEPTION_CONTINUE_SEARCH; - } - else { - return EXCEPTION_CONTINUE_EXECUTION; - } + ret = next_action(module_inst, exce_info); + if (ret == EXCEPTION_CONTINUE_SEARCH + || ret == EXCEPTION_CONTINUE_EXECUTION) + return ret; } #endif } @@ -388,8 +457,21 @@ wasm_runtime_env_init() } #endif +#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP) + if (os_blocking_op_init() != BHT_OK) { + goto fail11; + } + os_end_blocking_op(); +#endif + return true; +#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP) +fail11: +#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 + aot_compiler_destroy(); +#endif +#endif #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 fail10: #if WASM_ENABLE_FAST_JIT != 0 @@ -1196,7 +1278,8 @@ wasm_runtime_unload(WASMModuleCommon *module) } WASMModuleInstanceCommon * -wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst, +wasm_runtime_instantiate_internal(WASMModuleCommon *module, + WASMModuleInstanceCommon *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size) @@ -1204,14 +1287,14 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst, #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) return (WASMModuleInstanceCommon *)wasm_instantiate( - (WASMModule *)module, is_sub_inst, exec_env_main, stack_size, - heap_size, error_buf, error_buf_size); + (WASMModule *)module, (WASMModuleInstance *)parent, exec_env_main, + stack_size, heap_size, error_buf, error_buf_size); #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) return (WASMModuleInstanceCommon *)aot_instantiate( - (AOTModule *)module, is_sub_inst, exec_env_main, stack_size, - heap_size, error_buf, error_buf_size); + (AOTModule *)module, (AOTModuleInstance *)parent, exec_env_main, + stack_size, heap_size, error_buf, error_buf_size); #endif set_error_buf(error_buf, error_buf_size, "Instantiate module failed, invalid module type"); @@ -1224,7 +1307,7 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size, uint32 error_buf_size) { return wasm_runtime_instantiate_internal( - module, false, NULL, stack_size, heap_size, error_buf, error_buf_size); + module, NULL, NULL, stack_size, heap_size, error_buf, error_buf_size); } void @@ -1322,6 +1405,10 @@ wasm_runtime_init_thread_env(void) } #endif +#if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP) + os_end_blocking_op(); +#endif + return true; } @@ -1868,33 +1955,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, @@ -1935,15 +1995,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 @@ -2304,17 +2359,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 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module); - if (node) - os_mutex_lock(&node->shared_mem_lock); -#endif + exception_lock(module_inst); if (exception) { snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); @@ -2322,19 +2370,23 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) else { module_inst->cur_exception[0] = '\0'; } -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (node) - os_mutex_unlock(&node->shared_mem_lock); -#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 } @@ -2385,12 +2437,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf) { bool has_exception = false; -#if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module); - if (node) - os_mutex_lock(&node->shared_mem_lock); -#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 @@ -2402,10 +2449,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 (node) - os_mutex_unlock(&node->shared_mem_lock); -#endif + exception_unlock(module_inst); return has_exception; } @@ -2450,6 +2494,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) @@ -2482,6 +2538,54 @@ wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst_comm) return module_inst->custom_data; } +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 +void +wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst, + bool enable) +{ + /* Alwary disable bounds checks if hw bounds checks enabled */ +#ifdef OS_ENABLE_HW_BOUND_CHECK + enable = false; +#endif +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + ((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e) + ->common.disable_bounds_checks = enable ? false : true; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e) + ->common.disable_bounds_checks = enable ? false : true; + } +#endif +} + +bool +wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst) +{ + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + return !((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst) + ->e) + ->common.disable_bounds_checks; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + return !((AOTModuleInstanceExtra *)((WASMModuleInstance *)module_inst) + ->e) + ->common.disable_bounds_checks; + } +#endif + + return true; +} +#endif + uint32 wasm_runtime_module_malloc_internal(WASMModuleInstanceCommon *module_inst, WASMExecEnv *exec_env, uint32 size, @@ -3213,27 +3317,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 * @@ -4496,10 +4579,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; } @@ -4636,6 +4715,8 @@ typedef struct ExternRefMapNode { bool retained; /* Whether it is marked by runtime */ bool marked; + /* cleanup function called when the externref is freed */ + void (*cleanup)(void *); } ExternRefMapNode; static uint32 @@ -4698,6 +4779,81 @@ lookup_extobj_callback(void *key, void *value, void *user_data) } } +static void +delete_externref(void *key, ExternRefMapNode *node) +{ + bh_hash_map_remove(externref_map, key, NULL, NULL); + if (node->cleanup) { + (*node->cleanup)(node->extern_obj); + } + wasm_runtime_free(node); +} + +static void +delete_extobj_callback(void *key, void *value, void *user_data) +{ + ExternRefMapNode *node = (ExternRefMapNode *)value; + LookupExtObj_UserData *lookup_user_data = + (LookupExtObj_UserData *)user_data; + + if (node->extern_obj == lookup_user_data->node.extern_obj + && node->module_inst == lookup_user_data->node.module_inst) { + lookup_user_data->found = true; + delete_externref(key, node); + } +} + +bool +wasm_externref_objdel(WASMModuleInstanceCommon *module_inst, void *extern_obj) +{ + LookupExtObj_UserData lookup_user_data = { 0 }; + bool ok = false; + + /* in a wrapper, extern_obj could be any value */ + lookup_user_data.node.extern_obj = extern_obj; + lookup_user_data.node.module_inst = module_inst; + lookup_user_data.found = false; + + os_mutex_lock(&externref_lock); + /* Lookup hashmap firstly */ + bh_hash_map_traverse(externref_map, delete_extobj_callback, + (void *)&lookup_user_data); + if (lookup_user_data.found) { + ok = true; + } + os_mutex_unlock(&externref_lock); + + return ok; +} + +bool +wasm_externref_set_cleanup(WASMModuleInstanceCommon *module_inst, + void *extern_obj, void (*extern_obj_cleanup)(void *)) +{ + + LookupExtObj_UserData lookup_user_data = { 0 }; + bool ok = false; + + /* in a wrapper, extern_obj could be any value */ + lookup_user_data.node.extern_obj = extern_obj; + lookup_user_data.node.module_inst = module_inst; + lookup_user_data.found = false; + + os_mutex_lock(&externref_lock); + /* Lookup hashmap firstly */ + bh_hash_map_traverse(externref_map, lookup_extobj_callback, + (void *)&lookup_user_data); + if (lookup_user_data.found) { + void *key = (void *)(uintptr_t)lookup_user_data.externref_idx; + ExternRefMapNode *node = bh_hash_map_find(externref_map, key); + node->cleanup = extern_obj_cleanup; + ok = true; + } + os_mutex_unlock(&externref_lock); + + return ok; +} + bool wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj, uint32 *p_externref_idx) @@ -4747,6 +4903,7 @@ wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj, memset(node, 0, sizeof(ExternRefMapNode)); node->extern_obj = extern_obj; node->module_inst = module_inst; + node->cleanup = NULL; externref_idx = externref_global_id; @@ -4797,8 +4954,7 @@ reclaim_extobj_callback(void *key, void *value, void *user_data) if (node->module_inst == module_inst) { if (!node->marked && !node->retained) { - bh_hash_map_remove(externref_map, key, NULL, NULL); - wasm_runtime_free(value); + delete_externref(key, node); } else { node->marked = false; @@ -4913,8 +5069,7 @@ cleanup_extobj_callback(void *key, void *value, void *user_data) (WASMModuleInstanceCommon *)user_data; if (node->module_inst == module_inst) { - bh_hash_map_remove(externref_map, key, NULL, NULL); - wasm_runtime_free(value); + delete_externref(key, node); } } @@ -5507,3 +5662,37 @@ wasm_runtime_is_import_global_linked(const char *module_name, return false; #endif } + +#if WASM_ENABLE_MODULE_INST_CONTEXT != 0 +void * +wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst, + void *ctx)) +{ + return wasm_native_create_context_key(dtor); +} + +void +wasm_runtime_destroy_context_key(void *key) +{ + wasm_native_destroy_context_key(key); +} + +void +wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx) +{ + wasm_native_set_context(inst, key, ctx); +} + +void +wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key, + void *ctx) +{ + wasm_native_set_context_spread(inst, key, ctx); +} + +void * +wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key) +{ + return wasm_native_get_context(inst, key); +} +#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */ diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 283d2ed57..19d0af117 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -498,7 +498,8 @@ wasm_runtime_unload(WASMModuleCommon *module); /* Internal API */ WASMModuleInstanceCommon * -wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst, +wasm_runtime_instantiate_internal(WASMModuleCommon *module, + WASMModuleInstanceCommon *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size); @@ -593,6 +594,17 @@ wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data); WASM_RUNTIME_API_EXTERN void * wasm_runtime_get_user_data(WASMExecEnv *exec_env); +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN void +wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst, + bool enable); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst); +#endif + #ifdef OS_ENABLE_HW_BOUND_CHECK /* Access exception check guard page to trigger the signal handler */ void @@ -663,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, @@ -927,6 +943,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, @@ -1004,6 +1040,15 @@ WASM_RUNTIME_API_EXTERN bool wasm_runtime_is_import_global_linked(const char *module_name, const char *global_name); +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_begin_blocking_op(WASMExecEnv *exec_env); + +WASM_RUNTIME_API_EXTERN void +wasm_runtime_end_blocking_op(WASMExecEnv *exec_env); + +void +wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index 54fc8200f..c95d4b7ed 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -9,9 +9,16 @@ #include "../libraries/thread-mgr/thread_manager.h" #endif -static bh_list shared_memory_list_head; -static bh_list *const shared_memory_list = &shared_memory_list_head; -static korp_mutex shared_memory_list_lock; +/* + * Note: this lock can be per memory. + * + * For now, just use a global because: + * - it's a bit cumbersome to extend WASMMemoryInstance w/o breaking + * the AOT ABI. + * - If you care performance, it's better to make the interpreters + * use atomic ops. + */ +static korp_mutex _shared_memory_lock; /* clang-format off */ enum { @@ -37,7 +44,7 @@ typedef struct AtomicWaitNode { static HashMap *wait_map; static uint32 -wait_address_hash(void *address); +wait_address_hash(const void *address); static bool wait_address_equal(void *h1, void *h2); @@ -48,17 +55,15 @@ destroy_wait_info(void *wait_info); bool wasm_shared_memory_init() { - if (os_mutex_init(&shared_memory_list_lock) != 0) + if (os_mutex_init(&_shared_memory_lock) != 0) return false; - /* wait map not exists, create new map */ if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash, (KeyEqualFunc)wait_address_equal, NULL, destroy_wait_info))) { - os_mutex_destroy(&shared_memory_list_lock); + os_mutex_destroy(&_shared_memory_lock); return false; } - return true; } @@ -66,115 +71,84 @@ void wasm_shared_memory_destroy() { bh_hash_map_destroy(wait_map); - os_mutex_destroy(&shared_memory_list_lock); + os_mutex_destroy(&_shared_memory_lock); } -static WASMSharedMemNode * -search_module(WASMModuleCommon *module) +uint32 +shared_memory_inc_reference(WASMMemoryInstance *memory) { - WASMSharedMemNode *node; - - os_mutex_lock(&shared_memory_list_lock); - node = bh_list_first_elem(shared_memory_list); - - while (node) { - if (module == node->module) { - os_mutex_unlock(&shared_memory_list_lock); - return node; - } - node = bh_list_elem_next(node); - } - - os_mutex_unlock(&shared_memory_list_lock); - return NULL; + bh_assert(shared_memory_is_shared(memory)); + uint32 old; +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_lock(&_shared_memory_lock); +#endif + old = BH_ATOMIC_32_FETCH_ADD(memory->ref_count, 1); +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_unlock(&_shared_memory_lock); +#endif + bh_assert(old >= 1); + bh_assert(old < UINT32_MAX); + return old + 1; } -WASMSharedMemNode * -wasm_module_get_shared_memory(WASMModuleCommon *module) +uint32 +shared_memory_dec_reference(WASMMemoryInstance *memory) { - return search_module(module); + bh_assert(shared_memory_is_shared(memory)); + uint32 old; +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_lock(&_shared_memory_lock); +#endif + old = BH_ATOMIC_32_FETCH_SUB(memory->ref_count, 1); +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_unlock(&_shared_memory_lock); +#endif + bh_assert(old > 0); + return old - 1; } -int32 -shared_memory_inc_reference(WASMModuleCommon *module) +bool +shared_memory_is_shared(WASMMemoryInstance *memory) { - WASMSharedMemNode *node = search_module(module); - uint32 ref_count = -1; - if (node) { - os_mutex_lock(&node->lock); - ref_count = ++node->ref_count; - os_mutex_unlock(&node->lock); - } - return ref_count; + uint32 old; +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_lock(&_shared_memory_lock); +#endif + old = BH_ATOMIC_32_LOAD(memory->ref_count); +#if BH_ATOMIC_32_IS_ATOMIC == 0 + os_mutex_unlock(&_shared_memory_lock); +#endif + return old > 0; } -int32 -shared_memory_dec_reference(WASMModuleCommon *module) +static korp_mutex * +shared_memory_get_lock_pointer(WASMMemoryInstance *memory) { - WASMSharedMemNode *node = search_module(module); - uint32 ref_count = 0; - if (node) { - os_mutex_lock(&node->lock); - ref_count = --node->ref_count; - os_mutex_unlock(&node->lock); - if (ref_count == 0) { - os_mutex_lock(&shared_memory_list_lock); - bh_list_remove(shared_memory_list, node); - os_mutex_unlock(&shared_memory_list_lock); - - os_mutex_destroy(&node->shared_mem_lock); - os_mutex_destroy(&node->lock); - wasm_runtime_free(node); - } - return ref_count; - } - - return -1; + bh_assert(memory != NULL); + return &_shared_memory_lock; } -WASMMemoryInstanceCommon * -shared_memory_get_memory_inst(WASMSharedMemNode *node) +void +shared_memory_lock(WASMMemoryInstance *memory) { - return node->memory_inst; + /* + * Note: exception logic is currently abusing this lock. + * cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/2407 + */ + bh_assert(memory != NULL); + os_mutex_lock(&_shared_memory_lock); } -WASMSharedMemNode * -shared_memory_set_memory_inst(WASMModuleCommon *module, - WASMMemoryInstanceCommon *memory) +void +shared_memory_unlock(WASMMemoryInstance *memory) { - WASMSharedMemNode *node; - bh_list_status ret; - - if (!(node = wasm_runtime_malloc(sizeof(WASMSharedMemNode)))) - return NULL; - - node->module = module; - node->memory_inst = memory; - node->ref_count = 1; - - if (os_mutex_init(&node->shared_mem_lock) != 0) { - wasm_runtime_free(node); - return NULL; - } - - if (os_mutex_init(&node->lock) != 0) { - os_mutex_destroy(&node->shared_mem_lock); - wasm_runtime_free(node); - return NULL; - } - - os_mutex_lock(&shared_memory_list_lock); - ret = bh_list_insert(shared_memory_list, node); - bh_assert(ret == BH_LIST_SUCCESS); - os_mutex_unlock(&shared_memory_list_lock); - - (void)ret; - return node; + bh_assert(memory != NULL); + os_mutex_unlock(&_shared_memory_lock); } /* Atomics wait && notify APIs */ static uint32 -wait_address_hash(void *address) +wait_address_hash(const void *address) { return (uint32)(uintptr_t)address; } @@ -307,7 +281,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, WASMModuleInstance *module_inst = (WASMModuleInstance *)module; AtomicWaitInfo *wait_info; AtomicWaitNode *wait_node; - WASMSharedMemNode *node; + korp_mutex *lock; #if WASM_ENABLE_THREAD_MGR != 0 WASMExecEnv *exec_env; #endif @@ -322,7 +296,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, } /* Currently we have only one memory instance */ - if (!module_inst->memories[0]->is_shared) { + if (!shared_memory_is_shared(module_inst->memories[0])) { wasm_runtime_set_exception(module, "expected shared memory"); return -1; } @@ -340,30 +314,29 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, bh_assert(exec_env); #endif - node = search_module((WASMModuleCommon *)module_inst->module); - bh_assert(node); + lock = shared_memory_get_lock_pointer(module_inst->memories[0]); /* Lock the shared_mem_lock for the whole atomic wait process, and use it to os_cond_reltimedwait */ - os_mutex_lock(&node->shared_mem_lock); + os_mutex_lock(lock); no_wait = (!wait64 && *(uint32 *)address != (uint32)expect) || (wait64 && *(uint64 *)address != expect); if (no_wait) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); return 1; } if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); wasm_runtime_set_exception(module, "failed to create wait node"); return -1; } memset(wait_node, 0, sizeof(AtomicWaitNode)); if (0 != os_cond_init(&wait_node->wait_cond)) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); wasm_runtime_free(wait_node); wasm_runtime_set_exception(module, "failed to init wait cond"); return -1; @@ -375,7 +348,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, wait_info = acquire_wait_info(address, wait_node); if (!wait_info) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); os_cond_destroy(&wait_node->wait_cond); wasm_runtime_free(wait_node); wasm_runtime_set_exception(module, "failed to acquire wait_info"); @@ -390,7 +363,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, if (timeout < 0) { /* wait forever until it is notified or terminatied here we keep waiting and checking every second */ - os_cond_reltimedwait(&wait_node->wait_cond, &node->shared_mem_lock, + os_cond_reltimedwait(&wait_node->wait_cond, lock, (uint64)timeout_1sec); if (wait_node->status == S_NOTIFIED /* notified by atomic.notify */ #if WASM_ENABLE_THREAD_MGR != 0 @@ -404,8 +377,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, else { timeout_wait = timeout_left < timeout_1sec ? timeout_left : timeout_1sec; - os_cond_reltimedwait(&wait_node->wait_cond, &node->shared_mem_lock, - timeout_wait); + os_cond_reltimedwait(&wait_node->wait_cond, lock, timeout_wait); if (wait_node->status == S_NOTIFIED /* notified by atomic.notify */ || timeout_left <= timeout_wait /* time out */ #if WASM_ENABLE_THREAD_MGR != 0 @@ -433,7 +405,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, /* Release wait info if no wait nodes are attached */ map_try_release_wait_info(wait_map, wait_info, address); - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); return is_timeout ? 2 : 0; } @@ -445,7 +417,7 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, WASMModuleInstance *module_inst = (WASMModuleInstance *)module; uint32 notify_result; AtomicWaitInfo *wait_info; - WASMSharedMemNode *node; + korp_mutex *lock; bool out_of_bounds; bh_assert(module->module_type == Wasm_Module_Bytecode @@ -461,31 +433,30 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, } /* Currently we have only one memory instance */ - if (!module_inst->memories[0]->is_shared) { + if (!shared_memory_is_shared(module_inst->memories[0])) { /* Always return 0 for ushared linear memory since there is no way to create a waiter on it */ return 0; } - node = search_module((WASMModuleCommon *)module_inst->module); - bh_assert(node); + lock = shared_memory_get_lock_pointer(module_inst->memories[0]); /* Lock the shared_mem_lock for the whole atomic notify process, and use it to os_cond_signal */ - os_mutex_lock(&node->shared_mem_lock); + os_mutex_lock(lock); wait_info = acquire_wait_info(address, NULL); /* Nobody wait on this address */ if (!wait_info) { - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); return 0; } /* Notify each wait node in the wait list */ notify_result = notify_wait_list(wait_info->wait_list, count); - os_mutex_unlock(&node->shared_mem_lock); + os_mutex_unlock(lock); return notify_result; } diff --git a/core/iwasm/common/wasm_shared_memory.h b/core/iwasm/common/wasm_shared_memory.h index 6c1c49210..6a6538d21 100644 --- a/core/iwasm/common/wasm_shared_memory.h +++ b/core/iwasm/common/wasm_shared_memory.h @@ -7,53 +7,33 @@ #define _WASM_SHARED_MEMORY_H #include "bh_common.h" -#if WASM_ENABLE_INTERP != 0 -#include "wasm_runtime.h" -#endif -#if WASM_ENABLE_AOT != 0 -#include "aot_runtime.h" -#endif +#include "../interpreter/wasm_runtime.h" +#include "wasm_runtime_common.h" #ifdef __cplusplus extern "C" { #endif -typedef struct WASMSharedMemNode { - bh_list_link l; - /* Lock */ - korp_mutex lock; - /* The module reference */ - WASMModuleCommon *module; - /* The memory information */ - WASMMemoryInstanceCommon *memory_inst; - /* Lock used for atomic operations */ - korp_mutex shared_mem_lock; - - /* reference count */ - uint32 ref_count; -} WASMSharedMemNode; - bool wasm_shared_memory_init(); void wasm_shared_memory_destroy(); -WASMSharedMemNode * -wasm_module_get_shared_memory(WASMModuleCommon *module); +uint32 +shared_memory_inc_reference(WASMMemoryInstance *memory); -int32 -shared_memory_inc_reference(WASMModuleCommon *module); +uint32 +shared_memory_dec_reference(WASMMemoryInstance *memory); -int32 -shared_memory_dec_reference(WASMModuleCommon *module); +bool +shared_memory_is_shared(WASMMemoryInstance *memory); -WASMMemoryInstanceCommon * -shared_memory_get_memory_inst(WASMSharedMemNode *node); +void +shared_memory_lock(WASMMemoryInstance *memory); -WASMSharedMemNode * -shared_memory_set_memory_inst(WASMModuleCommon *module, - WASMMemoryInstanceCommon *memory); +void +shared_memory_unlock(WASMMemoryInstance *memory); uint32 wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, diff --git a/core/iwasm/common/wasm_suspend_flags.h b/core/iwasm/common/wasm_suspend_flags.h new file mode 100644 index 000000000..b182b2b5f --- /dev/null +++ b/core/iwasm/common/wasm_suspend_flags.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WASM_SUSPEND_FLAGS_H +#define _WASM_SUSPEND_FLAGS_H + +#include "bh_atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Need to terminate */ +#define WASM_SUSPEND_FLAG_TERMINATE 0x1 +/* Need to suspend */ +#define WASM_SUSPEND_FLAG_SUSPEND 0x2 +/* Need to go into breakpoint */ +#define WASM_SUSPEND_FLAG_BREAKPOINT 0x4 +/* Return from pthread_exit */ +#define WASM_SUSPEND_FLAG_EXIT 0x8 +/* The thread might be blocking */ +#define WASM_SUSPEND_FLAG_BLOCKING 0x10 + +typedef union WASMSuspendFlags { + bh_atomic_32_t flags; + uintptr_t __padding__; +} WASMSuspendFlags; + +#define WASM_SUSPEND_FLAGS_IS_ATOMIC BH_ATOMIC_32_IS_ATOMIC +#define WASM_SUSPEND_FLAGS_GET(s_flags) BH_ATOMIC_32_LOAD(s_flags.flags) +#define WASM_SUSPEND_FLAGS_FETCH_OR(s_flags, val) \ + BH_ATOMIC_32_FETCH_OR(s_flags.flags, val) +#define WASM_SUSPEND_FLAGS_FETCH_AND(s_flags, val) \ + BH_ATOMIC_32_FETCH_AND(s_flags.flags, val) + +#if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0 +#define WASM_SUSPEND_FLAGS_LOCK(lock) (void)0 +#define WASM_SUSPEND_FLAGS_UNLOCK(lock) (void)0 +#else /* else of WASM_SUSPEND_FLAGS_IS_ATOMIC */ +#define WASM_SUSPEND_FLAGS_LOCK(lock) os_mutex_lock(&lock) +#define WASM_SUSPEND_FLAGS_UNLOCK(lock) os_mutex_unlock(&lock); +#endif /* WASM_SUSPEND_FLAGS_IS_ATOMIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of _WASM_SUSPEND_FLAGS_H */ diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index 02b146cb3..088460636 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -43,7 +43,7 @@ typedef WASMType AOTFuncType; typedef WASMExport AOTExport; #if WASM_ENABLE_DEBUG_AOT != 0 -typedef void *dwar_extractor_handle_t; +typedef void *dwarf_extractor_handle_t; #endif typedef enum AOTIntCond { @@ -285,7 +285,7 @@ typedef struct AOTCompData { WASMModule *wasm_module; #if WASM_ENABLE_DEBUG_AOT != 0 - dwar_extractor_handle_t extractor; + dwarf_extractor_handle_t extractor; #endif } AOTCompData; diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index bbb31384e..464ca61f3 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -2617,64 +2617,6 @@ verify_module(AOTCompContext *comp_ctx) return true; } -/* Check whether the target supports hardware atomic instructions */ -static bool -aot_require_lower_atomic_pass(AOTCompContext *comp_ctx) -{ - bool ret = false; - if (!strncmp(comp_ctx->target_arch, "riscv", 5)) { - char *feature = - LLVMGetTargetMachineFeatureString(comp_ctx->target_machine); - - if (feature) { - if (!strstr(feature, "+a")) { - ret = true; - } - LLVMDisposeMessage(feature); - } - } - return ret; -} - -/* Check whether the target needs to expand switch to if/else */ -static bool -aot_require_lower_switch_pass(AOTCompContext *comp_ctx) -{ - bool ret = false; - - /* IR switch/case will cause .rodata relocation on riscv/xtensa */ - if (!strncmp(comp_ctx->target_arch, "riscv", 5) - || !strncmp(comp_ctx->target_arch, "xtensa", 6)) { - ret = true; - } - - return ret; -} - -static bool -apply_passes_for_indirect_mode(AOTCompContext *comp_ctx) -{ - LLVMPassManagerRef common_pass_mgr; - - if (!(common_pass_mgr = LLVMCreatePassManager())) { - aot_set_last_error("create pass manager failed"); - return false; - } - - aot_add_expand_memory_op_pass(common_pass_mgr); - - if (aot_require_lower_atomic_pass(comp_ctx)) - LLVMAddLowerAtomicPass(common_pass_mgr); - - if (aot_require_lower_switch_pass(comp_ctx)) - LLVMAddLowerSwitchPass(common_pass_mgr); - - LLVMRunPassManager(common_pass_mgr, comp_ctx->module); - - LLVMDisposePassManager(common_pass_mgr); - return true; -} - bool aot_compile_wasm(AOTCompContext *comp_ctx) { @@ -2714,17 +2656,6 @@ aot_compile_wasm(AOTCompContext *comp_ctx) possible core dump. */ bh_print_time("Begin to run llvm optimization passes"); aot_apply_llvm_new_pass_manager(comp_ctx, comp_ctx->module); - - /* Run specific passes for AOT indirect mode in last since general - optimization may create some intrinsic function calls like - llvm.memset, so let's remove these function calls here. */ - if (!comp_ctx->is_jit_mode && comp_ctx->is_indirect_mode) { - bh_print_time("Begin to run optimization passes " - "for indirect mode"); - if (!apply_passes_for_indirect_mode(comp_ctx)) { - return false; - } - } bh_print_time("Finish llvm optimization passes"); } @@ -2765,7 +2696,7 @@ aot_compile_wasm(AOTCompContext *comp_ctx) if (comp_ctx->stack_sizes != NULL) { LLVMOrcJITTargetAddress addr; if ((err = LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &addr, - aot_stack_sizes_name))) { + aot_stack_sizes_alias_name))) { aot_handle_llvm_errmsg("failed to look up stack_sizes", err); return false; } @@ -2804,6 +2735,33 @@ aot_generate_tempfile_name(const char *prefix, const char *extension, snprintf(buffer + name_len, len - name_len, ".%s", extension); return buffer; } +#else + +errno_t +_mktemp_s(char *nameTemplate, size_t sizeInChars); + +char * +aot_generate_tempfile_name(const char *prefix, const char *extension, + char *buffer, uint32 len) +{ + int name_len; + + name_len = snprintf(buffer, len, "%s-XXXXXX", prefix); + + if (_mktemp_s(buffer, name_len + 1) != 0) { + return NULL; + } + + /* Check if buffer length is enough */ + /* name_len + '.' + extension + '\0' */ + if (name_len + 1 + strlen(extension) + 1 > len) { + aot_set_last_error("temp file name too long."); + return NULL; + } + + snprintf(buffer + name_len, len - name_len, ".%s", extension); + return buffer; +} #endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */ bool diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index ae390dfc3..622187755 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -93,7 +93,10 @@ check_utf8_str(const uint8 *str, uint32 len) /* Internal function in object file */ typedef struct AOTObjectFunc { char *func_name; + /* text offset of aot_func#n */ uint64 text_offset; + /* text offset of aot_func_internal#n */ + uint64 text_offset_of_aot_func_internal; } AOTObjectFunc; /* Symbol table list node */ @@ -637,13 +640,33 @@ get_relocation_size(AOTRelocation *relocation, bool is_32bin) } static uint32 -get_relocations_size(AOTRelocation *relocations, uint32 relocation_count, +get_relocations_size(AOTObjectData *obj_data, + AOTRelocationGroup *relocation_group, + AOTRelocation *relocations, uint32 relocation_count, bool is_32bin) { AOTRelocation *relocation = relocations; uint32 size = 0, i; for (i = 0; i < relocation_count; i++, relocation++) { + /* ignore the relocations to aot_func_internal#n in text section + for windows platform since they will be applied in + aot_emit_text_section */ + if (!strcmp(relocation_group->section_name, ".text") + && !strncmp(relocation->symbol_name, AOT_FUNC_INTERNAL_PREFIX, + strlen(AOT_FUNC_INTERNAL_PREFIX)) + && ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6) + /* Windows AOT_COFF64_BIN_TYPE */ + && obj_data->target_info.bin_type == 6 + /* IMAGE_REL_AMD64_REL32 in windows x86_64 */ + && relocation->relocation_type == 4) + || (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4) + /* Windows AOT_COFF32_BIN_TYPE */ + && obj_data->target_info.bin_type == 4 + /* IMAGE_REL_I386_REL32 in windows x86_32 */ + && relocation->relocation_type == 20))) { + continue; + } size = align_uint(size, 4); size += get_relocation_size(relocation, is_32bin); } @@ -651,19 +674,22 @@ get_relocations_size(AOTRelocation *relocations, uint32 relocation_count, } static uint32 -get_relocation_group_size(AOTRelocationGroup *relocation_group, bool is_32bin) +get_relocation_group_size(AOTObjectData *obj_data, + AOTRelocationGroup *relocation_group, bool is_32bin) { uint32 size = 0; /* section name index + relocation count + relocations */ size += (uint32)sizeof(uint32); size += (uint32)sizeof(uint32); - size += get_relocations_size(relocation_group->relocations, + size += get_relocations_size(obj_data, relocation_group, + relocation_group->relocations, relocation_group->relocation_count, is_32bin); return size; } static uint32 -get_relocation_groups_size(AOTRelocationGroup *relocation_groups, +get_relocation_groups_size(AOTObjectData *obj_data, + AOTRelocationGroup *relocation_groups, uint32 relocation_group_count, bool is_32bin) { AOTRelocationGroup *relocation_group = relocation_groups; @@ -671,7 +697,7 @@ get_relocation_groups_size(AOTRelocationGroup *relocation_groups, for (i = 0; i < relocation_group_count; i++, relocation_group++) { size = align_uint(size, 4); - size += get_relocation_group_size(relocation_group, is_32bin); + size += get_relocation_group_size(obj_data, relocation_group, is_32bin); } return size; } @@ -864,7 +890,7 @@ get_relocation_section_size(AOTCompContext *comp_ctx, AOTObjectData *obj_data) /* relocation group count + symbol_table + relocation groups */ return (uint32)sizeof(uint32) + symbol_table_size - + get_relocation_groups_size(relocation_groups, + + get_relocation_groups_size(obj_data, relocation_groups, relocation_group_count, is_32bit_binary(obj_data)); } @@ -1734,6 +1760,10 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, uint32 section_size = get_text_section_size(obj_data); uint32 offset = *p_offset; uint8 placeholder = 0; + AOTRelocationGroup *relocation_group; + AOTRelocation *relocation; + uint32 i, j, relocation_count; + uint8 *text; *p_offset = offset = align_uint(offset, 4); @@ -1747,6 +1777,8 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, EMIT_BUF(&placeholder, 1); } + text = buf + offset; + if (obj_data->text_size > 0) { EMIT_BUF(obj_data->text, obj_data->text_size); while (offset & 3) @@ -1768,6 +1800,67 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, return false; } + /* apply relocations to aot_func_internal#n in text section for + windows platform */ + if ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6) + /* Windows AOT_COFF64_BIN_TYPE */ + && obj_data->target_info.bin_type == 6) + || (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4) + /* Windows AOT_COFF32_BIN_TYPE */ + && obj_data->target_info.bin_type == 4)) { + relocation_group = obj_data->relocation_groups; + for (i = 0; i < obj_data->relocation_group_count; + i++, relocation_group++) { + /* relocation in text section */ + if (!strcmp(relocation_group->section_name, ".text")) { + relocation = relocation_group->relocations; + relocation_count = relocation_group->relocation_count; + for (j = 0; j < relocation_count; j++) { + /* relocation to aot_func_internal#n */ + if (str_starts_with(relocation->symbol_name, + AOT_FUNC_INTERNAL_PREFIX) + && ((obj_data->target_info.bin_type + == 6 /* AOT_COFF64_BIN_TYPE */ + && relocation->relocation_type + == 4 /* IMAGE_REL_AMD64_REL32 */) + || (obj_data->target_info.bin_type + == 4 /* AOT_COFF32_BIN_TYPE */ + && relocation->relocation_type + == 20 /* IMAGE_REL_I386_REL32 */))) { + uint32 func_idx = + atoi(relocation->symbol_name + + strlen(AOT_FUNC_INTERNAL_PREFIX)); + uint64 text_offset, reloc_offset, reloc_addend; + + bh_assert(func_idx < obj_data->func_count); + + text_offset = obj_data->funcs[func_idx] + .text_offset_of_aot_func_internal; + reloc_offset = relocation->relocation_offset; + reloc_addend = relocation->relocation_addend; + /* S + A - P */ + *(uint32 *)(text + reloc_offset) = + (uint32)(text_offset + reloc_addend - reloc_offset + - 4); + + /* remove current relocation as it has been applied */ + if (j < relocation_count - 1) { + uint32 move_size = + (uint32)(sizeof(AOTRelocation) + * (relocation_count - 1 - j)); + bh_memmove_s(relocation, move_size, relocation + 1, + move_size); + } + relocation_group->relocation_count--; + } + else { + relocation++; + } + } + } + } + } + *p_offset = offset; return true; @@ -2403,7 +2496,7 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data) && !strcmp(name, "__llvm_prf_cnts")) { snprintf(buf, sizeof(buf), "%s%u", name, llvm_prf_cnts_idx++); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(data_section->name = wasm_runtime_malloc(size))) { aot_set_last_error( "allocate memory for data section name failed."); @@ -2416,7 +2509,7 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data) && !strcmp(name, "__llvm_prf_data")) { snprintf(buf, sizeof(buf), "%s%u", name, llvm_prf_data_idx++); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(data_section->name = wasm_runtime_malloc(size))) { aot_set_last_error( "allocate memory for data section name failed."); @@ -2520,15 +2613,15 @@ read_stack_usage_file(const AOTCompContext *comp_ctx, const char *filename, } if (prefix == aot_func_prefix) { if (sz < precheck_stack_size_min) { - precheck_stack_size_min = sz; + precheck_stack_size_min = (uint32)sz; } if (sz > precheck_stack_size_max) { - precheck_stack_size_max = sz; + precheck_stack_size_max = (uint32)sz; } precheck_found++; continue; } - sizes[func_idx] = sz; + sizes[func_idx] = (uint32)sz; found++; } fclose(fp); @@ -2605,9 +2698,16 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data) while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) { if ((name = LLVMGetSymbolName(sym_itr)) - && !strcmp(name, aot_stack_sizes_alias_name)) { + && (!strcmp(name, aot_stack_sizes_alias_name) + /* symbol of COFF32 starts with "_" */ + || (obj_data->target_info.bin_type == AOT_COFF32_BIN_TYPE + && !strncmp(name, "_", 1) + && !strcmp(name + 1, aot_stack_sizes_alias_name)))) { uint64 sz = LLVMGetSymbolSize(sym_itr); - if (sz != sizeof(uint32) * obj_data->func_count) { + if (sz != sizeof(uint32) * obj_data->func_count + /* sz of COFF64/COFF32 is 0, ignore the check */ + && obj_data->target_info.bin_type != AOT_COFF64_BIN_TYPE + && obj_data->target_info.bin_type != AOT_COFF32_BIN_TYPE) { aot_set_last_error("stack_sizes had unexpected size."); goto fail; } @@ -2642,16 +2742,12 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data) goto fail; } } - if (addr > UINT32_MAX) { - aot_set_last_error("too large stack_sizes offset."); - goto fail; - } /* * Record section/offset and construct a copy of stack_sizes. * aot_emit_object_data_section_info will emit this copy. */ obj_data->stack_sizes_section_name = sec_name; - obj_data->stack_sizes_offset = addr; + obj_data->stack_sizes_offset = (uint32)addr; obj_data->stack_sizes = wasm_runtime_malloc( obj_data->func_count * sizeof(*obj_data->stack_sizes)); if (obj_data->stack_sizes == NULL) { @@ -2770,6 +2866,7 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data) while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) { if ((name = (char *)LLVMGetSymbolName(sym_itr)) && str_starts_with(name, prefix)) { + /* symbol aot_func#n */ func_index = (uint32)atoi(name + strlen(prefix)); if (func_index < obj_data->func_count) { LLVMSectionIteratorRef contain_section; @@ -2804,6 +2901,44 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data) } } } + else if ((name = (char *)LLVMGetSymbolName(sym_itr)) + && str_starts_with(name, AOT_FUNC_INTERNAL_PREFIX)) { + /* symbol aot_func_internal#n */ + func_index = (uint32)atoi(name + strlen(AOT_FUNC_INTERNAL_PREFIX)); + if (func_index < obj_data->func_count) { + LLVMSectionIteratorRef contain_section; + char *contain_section_name; + + func = obj_data->funcs + func_index; + + if (!(contain_section = LLVMObjectFileCopySectionIterator( + obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + LLVMDisposeSymbolIterator(sym_itr); + return false; + } + LLVMMoveToContainingSection(contain_section, sym_itr); + contain_section_name = + (char *)LLVMGetSectionName(contain_section); + LLVMDisposeSectionIterator(contain_section); + + if (!strcmp(contain_section_name, ".text.unlikely.")) { + func->text_offset_of_aot_func_internal = + align_uint(obj_data->text_size, 4) + + LLVMGetSymbolAddress(sym_itr); + } + else if (!strcmp(contain_section_name, ".text.hot.")) { + func->text_offset_of_aot_func_internal = + align_uint(obj_data->text_size, 4) + + align_uint(obj_data->text_unlikely_size, 4) + + LLVMGetSymbolAddress(sym_itr); + } + else { + func->text_offset_of_aot_func_internal = + LLVMGetSymbolAddress(sym_itr); + } + } + } LLVMMoveToNextSymbol(sym_itr); } LLVMDisposeSymbolIterator(sym_itr); @@ -2975,7 +3110,7 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data, || !strcmp(group->section_name, ".rel.text")) { snprintf(buf, sizeof(buf), "%s%u", relocation->symbol_name, prof_section_idx); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(relocation->symbol_name = wasm_runtime_malloc(size))) { aot_set_last_error( "allocate memory for relocation symbol name failed."); @@ -2990,7 +3125,7 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data, 19)) { snprintf(buf, sizeof(buf), "%s%u", relocation->symbol_name, prof_section_idx); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(relocation->symbol_name = wasm_runtime_malloc(size))) { aot_set_last_error( "allocate memory for relocation symbol name failed."); @@ -3087,6 +3222,13 @@ is_relocation_section(AOTObjectData *obj_data, LLVMSectionIteratorRef sec_itr) return false; } +static bool +is_readonly_section(const char *name) +{ + return !strcmp(name, ".rel.text") || !strcmp(name, ".rela.text") + || !strcmp(name, ".rela.literal") || !strcmp(name, ".text"); +} + static bool get_relocation_groups_count(AOTObjectData *obj_data, uint32 *p_count) { @@ -3149,7 +3291,7 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data) || !strcmp(name, ".rel__llvm_prf_data"))) { char buf[32]; snprintf(buf, sizeof(buf), "%s%u", name, llvm_prf_data_idx); - size = strlen(buf) + 1; + size = (uint32)(strlen(buf) + 1); if (!(relocation_group->section_name = wasm_runtime_malloc(size))) { aot_set_last_error( @@ -3184,6 +3326,19 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data) relocation_group->section_name = ".rel.text"; } + /* + * Relocations in read-only sections are problematic, + * especially for XIP on platforms which don't have + * copy-on-write mappings. + */ + if (obj_data->comp_ctx->is_indirect_mode + && is_readonly_section(relocation_group->section_name)) { + LOG_WARNING("%" PRIu32 + " text relocations in %s section for indirect mode", + relocation_group->relocation_count, + relocation_group->section_name); + } + relocation_group++; } LLVMMoveToNextSection(sec_itr); diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index 2cf51cf67..75d1e622e 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -234,13 +234,15 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, else { /* Store extra return values to function parameters */ if (i != 0) { + LLVMValueRef res; uint32 param_index = func_type->param_count + i; - if (!LLVMBuildStore( - comp_ctx->builder, block->result_phis[i], - LLVMGetParam(func_ctx->func, param_index))) { + if (!(res = LLVMBuildStore( + comp_ctx->builder, block->result_phis[i], + LLVMGetParam(func_ctx->func, param_index)))) { aot_set_last_error("llvm build store failed."); goto fail; } + LLVMSetAlignment(res, 1); } } } @@ -1102,14 +1104,17 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (block_func->result_count) { /* Store extra result values to function parameters */ for (i = 0; i < block_func->result_count - 1; i++) { + LLVMValueRef res; result_index = block_func->result_count - 1 - i; POP(value, block_func->result_types[result_index]); param_index = func_type->param_count + result_index; - if (!LLVMBuildStore(comp_ctx->builder, value, - LLVMGetParam(func_ctx->func, param_index))) { + if (!(res = LLVMBuildStore( + comp_ctx->builder, value, + LLVMGetParam(func_ctx->func, param_index)))) { aot_set_last_error("llvm build store failed."); goto fail; } + LLVMSetAlignment(res, 1); } /* Return the first result value */ POP(value, block_func->result_types[0]); diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index aa837a3ca..def3f7d04 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -18,6 +18,17 @@ } \ } while (0) +static bool +is_win_platform(AOTCompContext *comp_ctx) +{ + char *triple = LLVMGetTargetMachineTriple(comp_ctx->target_machine); + + bh_assert(triple); + if (strstr(triple, "win32") || strstr(triple, "win")) + return true; + return false; +} + static bool create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { @@ -458,7 +469,7 @@ check_app_addr_and_convert(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Check whether exception was thrown when executing the function */ - if (comp_ctx->enable_bound_check + if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_call_return(comp_ctx, func_ctx, res)) { return false; } @@ -696,7 +707,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; /* Check whether there was exception thrown when executing the function */ - if (comp_ctx->enable_bound_check + if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_call_return(comp_ctx, func_ctx, res)) goto fail; } @@ -849,7 +860,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Check whether there was exception thrown when executing the function */ - if (!tail_call && comp_ctx->enable_bound_check + if (!tail_call + && (comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_exception_thrown(comp_ctx, func_ctx)) goto fail; } @@ -1431,7 +1443,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; /* Check whether exception was thrown when executing the function */ - if (comp_ctx->enable_bound_check + if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_call_return(comp_ctx, func_ctx, res)) goto fail; @@ -1483,7 +1495,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Check whether exception was thrown when executing the function */ - if (comp_ctx->enable_bound_check + if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx)) && !check_exception_thrown(comp_ctx, func_ctx)) goto fail; diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 89b11d77c..6dc3a0f7d 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -146,6 +146,13 @@ aot_target_precheck_can_use_musttail(const AOTCompContext *comp_ctx) */ return false; } + if (!strcmp(comp_ctx->target_arch, "mips")) { + /* + * cf. + * https://github.com/bytecodealliance/wasm-micro-runtime/issues/2412 + */ + return false; + } /* * x86-64/i386: true * @@ -237,9 +244,10 @@ get_inst_extra_offset(AOTCompContext *comp_ctx) const AOTCompData *comp_data = comp_ctx->comp_data; uint32 table_count = comp_data->import_table_count + comp_data->table_count; uint64 offset = get_tbl_inst_offset(comp_ctx, NULL, table_count); - bh_assert(offset <= UINT_MAX); - offset = align_uint(offset, 8); - return offset; + uint32 offset_32 = (uint32)offset; + bh_assert(offset <= UINT32_MAX); + offset_32 = align_uint((uint32)offset_32, 8); + return offset_32; } /* @@ -309,8 +317,8 @@ aot_add_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module, goto fail; } - unsigned int param_count = LLVMCountParams(precheck_func); - uint64 sz = param_count * sizeof(LLVMValueRef); + uint32 param_count = LLVMCountParams(precheck_func); + uint32 sz = param_count * (uint32)sizeof(LLVMValueRef); params = wasm_runtime_malloc(sz); if (params == NULL) { goto fail; @@ -518,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; @@ -623,6 +637,15 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module, prefix))) goto fail; + if (comp_ctx->is_indirect_mode) { + /* avoid LUT relocations ("switch-table") */ + LLVMAttributeRef attr_no_jump_tables = LLVMCreateStringAttribute( + comp_ctx->context, "no-jump-tables", + (uint32)strlen("no-jump-tables"), "true", (uint32)strlen("true")); + LLVMAddAttributeAtIndex(func, LLVMAttributeFunctionIndex, + attr_no_jump_tables); + } + if (need_precheck) { if (!comp_ctx->is_jit_mode) LLVMSetLinkage(func, LLVMInternalLinkage); @@ -2072,7 +2095,7 @@ jit_stack_size_callback(void *user_data, const char *name, size_t namelen, return; } /* ensure NUL termination */ - bh_memcpy_s(buf, sizeof(buf), name, namelen); + bh_memcpy_s(buf, (uint32)sizeof(buf), name, (uint32)namelen); buf[namelen] = 0; ret = sscanf(buf, AOT_FUNC_INTERNAL_PREFIX "%" SCNu32, &func_idx); @@ -2093,7 +2116,7 @@ jit_stack_size_callback(void *user_data, const char *name, size_t namelen, /* Note: -1 == AOT_NEG_ONE from aot_create_stack_sizes */ bh_assert(comp_ctx->jit_stack_sizes[func_idx] == (uint32)-1); - comp_ctx->jit_stack_sizes[func_idx] = stack_size + call_size; + comp_ctx->jit_stack_sizes[func_idx] = (uint32)stack_size + call_size; } static bool @@ -2155,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(); @@ -2296,6 +2321,12 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) if (option->enable_stack_estimation) comp_ctx->enable_stack_estimation = true; + if (option->llvm_passes) + comp_ctx->llvm_passes = option->llvm_passes; + + if (option->builtin_intrinsics) + comp_ctx->builtin_intrinsics = option->builtin_intrinsics; + comp_ctx->opt_level = option->opt_level; comp_ctx->size_level = option->size_level; @@ -2729,6 +2760,16 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) aot_set_last_error("create LLVM target machine failed."); goto fail; } + + /* If only to create target machine for querying information, early stop + */ + if ((arch && !strcmp(arch, "help")) || (abi && !strcmp(abi, "help")) + || (cpu && !strcmp(cpu, "help")) + || (features && !strcmp(features, "+help"))) { + LOG_DEBUG( + "create LLVM target machine only for printing help info."); + goto fail; + } } triple = LLVMGetTargetMachineTriple(comp_ctx->target_machine); diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 2f187b694..b46ac3bd0 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -15,15 +15,18 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Analysis.h" #include "llvm-c/BitWriter.h" +#if LLVM_VERSION_MAJOR < 17 #include "llvm-c/Transforms/Utils.h" #include "llvm-c/Transforms/Scalar.h" #include "llvm-c/Transforms/Vectorize.h" #include "llvm-c/Transforms/PassManagerBuilder.h" +#include "llvm-c/Initialization.h" +#endif #include "llvm-c/Orc.h" #include "llvm-c/Error.h" #include "llvm-c/Support.h" -#include "llvm-c/Initialization.h" + #include "llvm-c/TargetMachine.h" #include "llvm-c/LLJIT.h" #if WASM_ENABLE_DEBUG_AOT != 0 @@ -417,6 +420,8 @@ typedef struct AOTCompContext { const char *stack_usage_file; char stack_usage_temp_file[64]; + const char *llvm_passes; + const char *builtin_intrinsics; } AOTCompContext; enum { @@ -455,6 +460,8 @@ typedef struct AOTCompOption { char **custom_sections; uint32 custom_sections_count; const char *stack_usage_file; + const char *llvm_passes; + const char *builtin_intrinsics; } AOTCompOption, *aot_comp_option_t; bool diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index 109039406..ab6c621a0 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -5,11 +5,13 @@ #include #include +#if LLVM_VERSION_MAJOR < 17 #include #include +#include +#endif #include #include -#include #include #include #include @@ -18,7 +20,9 @@ #include #include #include +#if LLVM_VERSION_MAJOR < 17 #include +#endif #include #include #include @@ -27,9 +31,12 @@ #include #include #include -#include +#include #include #include +#if LLVM_VERSION_MAJOR >= 17 +#include +#endif #include #include #include @@ -55,6 +62,13 @@ using namespace llvm; using namespace llvm::orc; +#if LLVM_VERSION_MAJOR >= 17 +namespace llvm { +template +using Optional = std::optional; +} +#endif + LLVM_C_EXTERN_C_BEGIN bool @@ -73,115 +87,63 @@ LLVM_C_EXTERN_C_END ExitOnError ExitOnErr; -class ExpandMemoryOpPass : public llvm::ModulePass +class ExpandMemoryOpPass : public PassInfoMixin { public: - static char ID; - - ExpandMemoryOpPass() - : ModulePass(ID) - {} - - bool runOnModule(Module &M) override; - - bool expandMemIntrinsicUses(Function &F); - StringRef getPassName() const override - { - return "Expand memory operation intrinsics"; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override - { - AU.addRequired(); - } + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -char ExpandMemoryOpPass::ID = 0; - -bool -ExpandMemoryOpPass::expandMemIntrinsicUses(Function &F) +PreservedAnalyses +ExpandMemoryOpPass::run(Function &F, FunctionAnalysisManager &AM) { - Intrinsic::ID ID = F.getIntrinsicID(); - bool Changed = false; + SmallVector MemCalls; - for (auto I = F.user_begin(), E = F.user_end(); I != E;) { - Instruction *Inst = cast(*I); - ++I; + /* Iterate over all instructions in the function, looking for memcpy, + * memmove, and memset. When we find one, expand it into a loop. */ - switch (ID) { - case Intrinsic::memcpy: - { - auto *Memcpy = cast(Inst); - Function *ParentFunc = Memcpy->getParent()->getParent(); - const TargetTransformInfo &TTI = - getAnalysis().getTTI( - *ParentFunc); - expandMemCpyAsLoop(Memcpy, TTI); - Changed = true; - Memcpy->eraseFromParent(); - break; + for (auto &BB : F) { + for (auto &Inst : BB) { + if (auto *Memcpy = dyn_cast_or_null(&Inst)) { + MemCalls.push_back(Memcpy); } - case Intrinsic::memmove: - { - auto *Memmove = cast(Inst); - expandMemMoveAsLoop(Memmove); - Changed = true; - Memmove->eraseFromParent(); - break; + else if (auto *Memmove = dyn_cast_or_null(&Inst)) { + MemCalls.push_back(Memmove); } - case Intrinsic::memset: - { - auto *Memset = cast(Inst); - expandMemSetAsLoop(Memset); - Changed = true; - Memset->eraseFromParent(); - break; + else if (auto *Memset = dyn_cast_or_null(&Inst)) { + MemCalls.push_back(Memset); } - default: - break; } } - return Changed; -} - -bool -ExpandMemoryOpPass::runOnModule(Module &M) -{ - bool Changed = false; - - for (Function &F : M) { - if (!F.isDeclaration()) - continue; - - switch (F.getIntrinsicID()) { - case Intrinsic::memcpy: - case Intrinsic::memmove: - case Intrinsic::memset: - if (expandMemIntrinsicUses(F)) - Changed = true; - break; - - default: - break; + for (MemIntrinsic *MemCall : MemCalls) { + if (MemCpyInst *Memcpy = dyn_cast(MemCall)) { + Function *ParentFunc = Memcpy->getParent()->getParent(); + const TargetTransformInfo &TTI = + AM.getResult(*ParentFunc); + expandMemCpyAsLoop(Memcpy, TTI); + Memcpy->eraseFromParent(); + } + else if (MemMoveInst *Memmove = dyn_cast(MemCall)) { +#if LLVM_VERSION_MAJOR >= 17 + Function *ParentFunc = Memmove->getParent()->getParent(); + const TargetTransformInfo &TTI = + AM.getResult(*ParentFunc); + expandMemMoveAsLoop(Memmove, TTI); +#else + expandMemMoveAsLoop(Memmove); +#endif + Memmove->eraseFromParent(); + } + else if (MemSetInst *Memset = dyn_cast(MemCall)) { + expandMemSetAsLoop(Memset); + Memset->eraseFromParent(); } } - return Changed; -} + PreservedAnalyses PA; + PA.preserveSet(); -void -aot_add_expand_memory_op_pass(LLVMPassManagerRef pass) -{ - reinterpret_cast(pass)->add( - new ExpandMemoryOpPass()); -} - -void -aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass) -{ - reinterpret_cast(pass)->add( - createSimpleLoopUnswitchLegacyPass()); + return PA; } bool @@ -240,6 +202,9 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) #else Optional PGO = llvm::None; #endif + +// TODO +#if LLVM_VERSION_MAJOR < 17 if (comp_ctx->enable_llvm_pgo) { /* Disable static counter allocation for value profiler, it will be allocated by runtime */ @@ -250,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; @@ -373,6 +339,10 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + if (comp_ctx->llvm_passes) { + ExitOnErr(PB.parsePassPipeline(MPM, comp_ctx->llvm_passes)); + } + if (!disable_llvm_lto) { /* Apply LTO for AOT mode */ if (comp_ctx->comp_data->func_count >= 10 @@ -386,6 +356,15 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) else { MPM.addPass(PB.buildPerModuleDefaultPipeline(OL)); } + + /* Run specific passes for AOT indirect mode in last since general + optimization may create some intrinsic function calls like + llvm.memset, so let's remove these function calls here. */ + if (comp_ctx->is_indirect_mode) { + FunctionPassManager FPM1; + FPM1.addPass(ExpandMemoryOpPass()); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM1))); + } } MPM.run(*M, MAM); diff --git a/core/iwasm/compilation/aot_llvm_extra2.cpp b/core/iwasm/compilation/aot_llvm_extra2.cpp index 42e53ddfa..8364e5ebf 100644 --- a/core/iwasm/compilation/aot_llvm_extra2.cpp +++ b/core/iwasm/compilation/aot_llvm_extra2.cpp @@ -4,8 +4,10 @@ */ #include +#if LLVM_VERSION_MAJOR < 17 #include #include +#endif #include #if LLVM_VERSION_MAJOR >= 14 #include @@ -18,6 +20,13 @@ #include "aot_llvm_extra2.h" +#if LLVM_VERSION_MAJOR >= 17 +namespace llvm { +template +using Optional = std::optional; +} +#endif + static llvm::Optional convert(LLVMRelocMode reloc_mode) { diff --git a/core/iwasm/compilation/aot_orc_extra.cpp b/core/iwasm/compilation/aot_orc_extra.cpp index 9cfe331e5..51d61bf3c 100644 --- a/core/iwasm/compilation/aot_orc_extra.cpp +++ b/core/iwasm/compilation/aot_orc_extra.cpp @@ -8,8 +8,10 @@ #include "llvm-c/OrcEE.h" #include "llvm-c/TargetMachine.h" +#if LLVM_VERSION_MAJOR < 17 #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#endif #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" @@ -21,6 +23,13 @@ #include "aot_orc_extra.h" #include "aot.h" +#if LLVM_VERSION_MAJOR >= 17 +namespace llvm { +template +using Optional = std::optional; +} +#endif + using namespace llvm; using namespace llvm::orc; using GlobalValueSet = std::set; diff --git a/core/iwasm/compilation/debug/dwarf_extractor.cpp b/core/iwasm/compilation/debug/dwarf_extractor.cpp index 160aadee0..99182f82f 100644 --- a/core/iwasm/compilation/debug/dwarf_extractor.cpp +++ b/core/iwasm/compilation/debug/dwarf_extractor.cpp @@ -28,25 +28,25 @@ using namespace lldb; -typedef struct dwar_extractor { +typedef struct dwarf_extractor { SBDebugger debugger; SBTarget target; SBModule module; -} dwar_extractor; +} dwarf_extractor; -#define TO_HANDLE(extractor) (dwar_extractor_handle_t)(extractor) +#define TO_HANDLE(extractor) (dwarf_extractor_handle_t)(extractor) -#define TO_EXTACTOR(handle) (dwar_extractor *)(handle) +#define TO_EXTACTOR(handle) (dwarf_extractor *)(handle) static bool is_debugger_initialized; -dwar_extractor_handle_t +dwarf_extractor_handle_t create_dwarf_extractor(AOTCompData *comp_data, char *file_name) { char *arch = NULL; char *platform = NULL; - dwar_extractor *extractor = NULL; + dwarf_extractor *extractor = NULL; //__attribute__((constructor)) may be better? if (!is_debugger_initialized) { @@ -61,7 +61,7 @@ create_dwarf_extractor(AOTCompData *comp_data, char *file_name) SBError error; SBFileSpec exe_file_spec(file_name, true); - if (!(extractor = new dwar_extractor())) { + if (!(extractor = new dwarf_extractor())) { LOG_ERROR("Create Dwarf Extractor error: failed to allocate memory"); goto fail3; } @@ -101,9 +101,9 @@ fail3: } void -destroy_dwarf_extractor(dwar_extractor_handle_t handle) +destroy_dwarf_extractor(dwarf_extractor_handle_t handle) { - dwar_extractor *extractor = TO_EXTACTOR(handle); + dwarf_extractor *extractor = TO_EXTACTOR(handle); if (!extractor) return; extractor->debugger.DeleteTarget(extractor->target); @@ -116,7 +116,7 @@ destroy_dwarf_extractor(dwar_extractor_handle_t handle) LLVMMetadataRef dwarf_gen_file_info(const AOTCompContext *comp_ctx) { - dwar_extractor *extractor; + dwarf_extractor *extractor; int units_number; LLVMMetadataRef file_info = NULL; const char *file_name; @@ -193,7 +193,7 @@ dwarf_gen_mock_vm_info(AOTCompContext *comp_ctx) LLVMMetadataRef dwarf_gen_comp_unit_info(const AOTCompContext *comp_ctx) { - dwar_extractor *extractor; + dwarf_extractor *extractor; int units_number; LLVMMetadataRef comp_unit = NULL; @@ -292,7 +292,7 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx, SBTypeList function_args = function.GetType().GetFunctionArgumentTypes(); SBType return_type = function.GetType().GetFunctionReturnType(); const size_t num_function_args = function_args.GetSize(); - dwar_extractor *extractor; + dwarf_extractor *extractor; if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) return NULL; @@ -393,7 +393,7 @@ dwarf_gen_func_info(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx) { LLVMMetadataRef func_info = NULL; - dwar_extractor *extractor; + dwarf_extractor *extractor; uint64_t vm_offset; AOTFunc *func = func_ctx->aot_func; @@ -423,7 +423,7 @@ dwarf_get_func_name(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx, char *name, int len) { LLVMMetadataRef func_info = NULL; - dwar_extractor *extractor; + dwarf_extractor *extractor; uint64_t vm_offset; AOTFunc *func = func_ctx->aot_func; @@ -454,7 +454,7 @@ dwarf_gen_location(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx, uint64_t vm_offset) { LLVMMetadataRef location_info = NULL; - dwar_extractor *extractor; + dwarf_extractor *extractor; AOTFunc *func = func_ctx->aot_func; if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) @@ -493,7 +493,7 @@ dwarf_gen_func_ret_location(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx) { LLVMMetadataRef func_info = NULL; - dwar_extractor *extractor; + dwarf_extractor *extractor; uint64_t vm_offset; AOTFunc *func = func_ctx->aot_func; LLVMMetadataRef location_info = NULL; diff --git a/core/iwasm/compilation/debug/dwarf_extractor.h b/core/iwasm/compilation/debug/dwarf_extractor.h index c48e8f5c0..0bacb97fa 100644 --- a/core/iwasm/compilation/debug/dwarf_extractor.h +++ b/core/iwasm/compilation/debug/dwarf_extractor.h @@ -18,7 +18,7 @@ typedef unsigned int LLDBLangType; struct AOTCompData; typedef struct AOTCompData *aot_comp_data_t; -typedef void *dwar_extractor_handle_t; +typedef void *dwarf_extractor_handle_t; struct AOTCompContext; typedef struct AOTCompContext AOTCompContext; @@ -26,7 +26,7 @@ typedef struct AOTCompContext AOTCompContext; struct AOTFuncContext; typedef struct AOTFuncContext AOTFuncContext; -dwar_extractor_handle_t +dwarf_extractor_handle_t create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name); LLVMMetadataRef diff --git a/core/iwasm/fast-jit/fe/jit_emit_numberic.c b/core/iwasm/fast-jit/fe/jit_emit_numberic.c index 03491e691..6a1e93ede 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_numberic.c +++ b/core/iwasm/fast-jit/fe/jit_emit_numberic.c @@ -298,7 +298,15 @@ fail: /* macros for integer binary operations (ibinop) */ +#if defined(__GNUC__) +#define NO_SANITIZER_INTEGER \ + __attribute__((no_sanitize("signed-integer-overflow"))) +#else +#define NO_SANITIZER_INTEGER +#endif + #define __DEF_BI_INT_CONST_OPS(bits, opname, op) \ + NO_SANITIZER_INTEGER \ static int##bits do_i##bits##_const_##opname(int##bits lhs, int##bits rhs) \ { \ return lhs op rhs; \ diff --git a/core/iwasm/fast-jit/fe/jit_emit_table.c b/core/iwasm/fast-jit/fe/jit_emit_table.c index 9fb61931f..ea1b33883 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_table.c +++ b/core/iwasm/fast-jit/fe/jit_emit_table.c @@ -88,27 +88,28 @@ fail: static int wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx, - uint32 dst, uint32 len, uint32 src) + uint32 dst_offset, uint32 len, uint32 src_offset) { WASMTableInstance *tbl; uint32 tbl_sz; WASMTableSeg *elem; uint32 elem_len; - tbl = inst->tables[tbl_idx]; - tbl_sz = tbl->cur_size; - if (dst > tbl_sz || tbl_sz - dst < len) - goto out_of_bounds; - elem = inst->module->table_segments + elem_idx; elem_len = elem->function_count; - if (src > elem_len || elem_len - src < len) + if (offset_len_out_of_bounds(src_offset, len, elem_len)) + goto out_of_bounds; + + tbl = inst->tables[tbl_idx]; + tbl_sz = tbl->cur_size; + if (offset_len_out_of_bounds(dst_offset, len, tbl_sz)) goto out_of_bounds; bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems) - + dst * sizeof(uint32), - (uint32)((tbl_sz - dst) * sizeof(uint32)), - elem->func_indexes + src, (uint32)(len * sizeof(uint32))); + + dst_offset * sizeof(uint32), + (uint32)((tbl_sz - dst_offset) * sizeof(uint32)), + elem->func_indexes + src_offset, + (uint32)(len * sizeof(uint32))); return 0; out_of_bounds: @@ -157,14 +158,14 @@ wasm_copy_table(WASMModuleInstance *inst, uint32 src_tbl_idx, WASMTableInstance *src_tbl, *dst_tbl; uint32 src_tbl_sz, dst_tbl_sz; - src_tbl = inst->tables[src_tbl_idx]; - src_tbl_sz = src_tbl->cur_size; - if (src_offset > src_tbl_sz || src_tbl_sz - src_offset < len) - goto out_of_bounds; - dst_tbl = inst->tables[dst_tbl_idx]; dst_tbl_sz = dst_tbl->cur_size; - if (dst_offset > dst_tbl_sz || dst_tbl_sz - dst_offset < len) + if (offset_len_out_of_bounds(dst_offset, len, dst_tbl_sz)) + goto out_of_bounds; + + src_tbl = inst->tables[src_tbl_idx]; + src_tbl_sz = src_tbl->cur_size; + if (offset_len_out_of_bounds(src_offset, len, src_tbl_sz)) goto out_of_bounds; bh_memmove_s((uint8 *)dst_tbl + offsetof(WASMTableInstance, elems) @@ -263,7 +264,7 @@ fail: } static int -wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst, +wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst_offset, uint32 val, uint32 len) { WASMTableInstance *tbl; @@ -272,11 +273,11 @@ wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst, tbl = inst->tables[tbl_idx]; tbl_sz = tbl->cur_size; - if (dst > tbl_sz || tbl_sz - dst < len) + if (offset_len_out_of_bounds(dst_offset, len, tbl_sz)) goto out_of_bounds; - for (; len != 0; dst++, len--) { - tbl->elems[dst] = val; + for (; len != 0; dst_offset++, len--) { + tbl->elems[dst_offset] = val; } return 0; diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h index dca26aa6e..ce8ae81fe 100644 --- a/core/iwasm/include/aot_export.h +++ b/core/iwasm/include/aot_export.h @@ -26,8 +26,8 @@ void aot_destroy_comp_data(aot_comp_data_t comp_data); #if WASM_ENABLE_DEBUG_AOT != 0 -typedef void *dwar_extractor_handle_t; -dwar_extractor_handle_t +typedef void *dwarf_extractor_handle_t; +dwarf_extractor_handle_t create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name); #endif @@ -67,6 +67,8 @@ typedef struct AOTCompOption { char **custom_sections; uint32_t custom_sections_count; const char *stack_usage_file; + const char *llvm_passes; + const char *builtin_intrinsics; } AOTCompOption, *aot_comp_option_t; bool diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 28b952e8f..48ed55933 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -186,6 +186,7 @@ enum wasm_valkind_enum { #ifndef WASM_VAL_T_DEFINED #define WASM_VAL_T_DEFINED +struct wasm_ref_t; typedef struct wasm_val_t { wasm_valkind_t kind; @@ -197,6 +198,7 @@ typedef struct wasm_val_t { double f64; /* represent a foreign object, aka externref in .wat */ uintptr_t foreign; + struct wasm_ref_t *ref; } of; } wasm_val_t; #endif @@ -892,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: @@ -914,6 +937,25 @@ wasm_runtime_set_custom_data(wasm_module_inst_t module_inst, WASM_RUNTIME_API_EXTERN void * wasm_runtime_get_custom_data(wasm_module_inst_t module_inst); +/** + * Set the memory bounds checks flag of a WASM module instance. + * + * @param module_inst the WASM module instance + * @param enable the flag to enable/disable the memory bounds checks + */ +WASM_RUNTIME_API_EXTERN void +wasm_runtime_set_bounds_checks(wasm_module_inst_t module_inst, + bool enable); +/** + * Check if the memory bounds checks flag is enabled for a WASM module instance. + * + * @param module_inst the WASM module instance + * + * @return true if the memory bounds checks flag is enabled, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_bounds_checks_enabled( + wasm_module_inst_t module_inst); /** * Allocate memory from the heap of WASM module instance * @@ -1271,6 +1313,32 @@ WASM_RUNTIME_API_EXTERN bool wasm_externref_obj2ref(wasm_module_inst_t module_inst, void *extern_obj, uint32_t *p_externref_idx); +/** + * Delete external object registered by `wasm_externref_obj2ref`. + * + * @param module_inst the WASM module instance that the extern object + * belongs to + * @param extern_obj the external object to be deleted + * + * @return true if success, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_externref_objdel(wasm_module_inst_t module_inst, void *extern_obj); + +/** + * Set cleanup callback to release external object. + * + * @param module_inst the WASM module instance that the extern object + * belongs to + * @param extern_obj the external object to which to set the `extern_obj_cleanup` cleanup callback. + * @param extern_obj_cleanup a callback to release `extern_obj` + * + * @return true if success, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_externref_set_cleanup(wasm_module_inst_t module_inst, void *extern_obj, + void (*extern_obj_cleanup)(void *)); + /** * Retrieve the external object from an internal externref index * @@ -1392,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 diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 0797a018b..c7d9f1de9 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -627,7 +627,6 @@ typedef struct WASMBranchBlock { uint32 cell_num; } WASMBranchBlock; -/* Execution environment, e.g. stack info */ /** * Align an unsigned value on a alignment boundary. * @@ -643,6 +642,24 @@ align_uint(unsigned v, unsigned b) return (v + m) & ~m; } +/** + * Check whether a piece of data is out of range + * + * @param offset the offset that the data starts + * @param len the length of the data + * @param max_size the maximum size of the data range + * + * @return true if out of range, false otherwise + */ +inline static bool +offset_len_out_of_bounds(uint32 offset, uint32 len, uint32 max_size) +{ + if (offset + len < offset /* integer overflow */ + || offset + len > max_size) + return true; + return false; +} + /** * Return the hash value of c string. */ diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 653ee5b79..286ccf585 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -41,26 +41,28 @@ typedef float64 CellType_F64; #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 -#define CHECK_MEMORY_OVERFLOW(bytes) \ - do { \ - uint64 offset1 = (uint64)offset + (uint64)addr; \ - if (offset1 + bytes <= (uint64)get_linear_mem_size()) \ - /* If offset1 is in valid range, maddr must also \ - be in valid range, no need to check it again. */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ +#define CHECK_MEMORY_OVERFLOW(bytes) \ + do { \ + uint64 offset1 = (uint64)offset + (uint64)addr; \ + if (disable_bounds_checks \ + || offset1 + bytes <= (uint64)get_linear_mem_size()) \ + /* If offset1 is in valid range, maddr must also \ + be in valid range, no need to check it again. */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ } while (0) -#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ - do { \ - uint64 offset1 = (uint32)(start); \ - if (offset1 + bytes <= (uint64)get_linear_mem_size()) \ - /* App heap space is not valid space for \ - bulk memory operation */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ +#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ + do { \ + uint64 offset1 = (uint32)(start); \ + if (disable_bounds_checks \ + || offset1 + bytes <= (uint64)get_linear_mem_size()) \ + /* App heap space is not valid space for \ + bulk memory operation */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ } while (0) #else #define CHECK_MEMORY_OVERFLOW(bytes) \ @@ -708,28 +710,28 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint32)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint32)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = LOAD_I32(maddr); \ STORE_U32(maddr, readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ PUSH_I32(readv); \ break; \ @@ -748,39 +750,39 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_U32(maddr); \ STORE_U32(maddr, (uint32)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else { \ uint64 op_result; \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_I64(maddr); \ op_result = readv op sval; \ STORE_I64(maddr, op_result); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ PUSH_I64(readv); \ break; \ @@ -903,8 +905,9 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, if (!func_import->call_conv_wasm_c_api) { native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } - else if (module_inst->e->c_api_func_imports) { - c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; + else if (module_inst->e->common.c_api_func_imports) { + c_api_func_import = + module_inst->e->common.c_api_func_imports + cur_func_index; native_func_pointer = c_api_func_import->func_ptr_linked; } @@ -1060,21 +1063,33 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, os_mutex_unlock(&exec_env->wait_lock); \ } while (0) #else -#define CHECK_SUSPEND_FLAGS() \ - do { \ - os_mutex_lock(&exec_env->wait_lock); \ - if (exec_env->suspend_flags.flags != 0) { \ - if (exec_env->suspend_flags.flags & 0x01) { \ - /* terminate current thread */ \ - os_mutex_unlock(&exec_env->wait_lock); \ - return; \ - } \ - while (exec_env->suspend_flags.flags & 0x02) { \ - /* suspend current thread */ \ - os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \ - } \ - } \ - os_mutex_unlock(&exec_env->wait_lock); \ +#if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0 +/* The lock is only needed when the suspend_flags is atomic; otherwise + the lock is already taken at the time when SUSPENSION_LOCK() is called. */ +#define SUSPENSION_LOCK() os_mutex_lock(&exec_env->wait_lock); +#define SUSPENSION_UNLOCK() os_mutex_unlock(&exec_env->wait_lock); +#else +#define SUSPENSION_LOCK() +#define SUSPENSION_UNLOCK() +#endif + +#define CHECK_SUSPEND_FLAGS() \ + do { \ + WASM_SUSPEND_FLAGS_LOCK(exec_env->wait_lock); \ + if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \ + & WASM_SUSPEND_FLAG_TERMINATE) { \ + /* terminate current thread */ \ + WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \ + return; \ + } \ + while (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \ + & WASM_SUSPEND_FLAG_SUSPEND) { \ + /* suspend current thread */ \ + SUSPENSION_LOCK() \ + os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \ + SUSPENSION_UNLOCK() \ + } \ + WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \ } while (0) #endif /* WASM_ENABLE_DEBUG_INTERP */ #endif /* WASM_ENABLE_THREAD_MGR */ @@ -1142,10 +1157,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { -#if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module->module); -#endif WASMMemoryInstance *memory = wasm_get_default_memory(module); #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ @@ -1174,6 +1185,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint8 local_type, *global_addr; uint32 cache_index, type_index, param_cell_num, cell_num; uint8 value_type; +#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ + || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled( + (WASMModuleInstanceCommon *)module); +#else + bool disable_bounds_checks = false; +#endif +#endif #if WASM_ENABLE_DEBUG_INTERP != 0 uint8 *frame_ip_orig = NULL; @@ -3238,7 +3258,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, case WASM_OP_TABLE_INIT: { uint32 tbl_idx, elem_idx; - uint64 n, s, d; + uint32 n, s, d; WASMTableInstance *tbl_inst; read_leb_uint32(frame_ip, frame_ip_end, elem_idx); @@ -3253,20 +3273,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - /* TODO: what if the element is not passive? */ - - if (!n) { - break; - } - - if (n + s > module->module->table_segments[elem_idx] - .function_count - || d + n > tbl_inst->cur_size) { + if (offset_len_out_of_bounds( + s, n, + module->module->table_segments[elem_idx] + .function_count) + || offset_len_out_of_bounds(d, n, + tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; } + if (!n) { + break; + } + if (module->module->table_segments[elem_idx] .is_dropped) { wasm_set_exception(module, @@ -3307,7 +3328,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, case WASM_OP_TABLE_COPY: { uint32 src_tbl_idx, dst_tbl_idx; - uint64 n, s, d; + uint32 n, s, d; WASMTableInstance *src_tbl_inst, *dst_tbl_inst; read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx); @@ -3324,8 +3345,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - if (d + n > dst_tbl_inst->cur_size - || s + n > src_tbl_inst->cur_size) { + if (offset_len_out_of_bounds(d, n, + dst_tbl_inst->cur_size) + || offset_len_out_of_bounds( + s, n, src_tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; @@ -3395,11 +3418,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, fill_val = POP_I32(); i = POP_I32(); - /* TODO: what if the element is not passive? */ - /* TODO: what if the element is dropped? */ - - if (i + n > tbl_inst->cur_size) { - /* TODO: verify warning content */ + if (offset_len_out_of_bounds(i, n, + tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; @@ -3517,23 +3537,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)(*(uint8 *)maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)LOAD_U16(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I32(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I32(readv); @@ -3552,30 +3572,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)(*(uint8 *)maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U16(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U32(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I64(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I64(readv); @@ -3594,23 +3614,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U32(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } break; } @@ -3628,30 +3648,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U32(maddr, (uint32)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); PUT_I64_TO_ADDR((uint32 *)maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } break; } @@ -3671,32 +3691,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint8)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint16)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I32(maddr); if (readv == expect) STORE_U32(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I32(readv); break; @@ -3717,43 +3737,43 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint8)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint16)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint32)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U32(maddr); if (readv == expect) STORE_U32(maddr, (uint32)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_I64(maddr); if (readv == expect) STORE_I64(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I64(readv); break; @@ -3786,7 +3806,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(DEBUG_OP_BREAK) { wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP); - exec_env->suspend_flags.flags |= 2; + WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags, + WASM_SUSPEND_FLAG_SUSPEND); frame_ip--; SYNC_ALL_TO_FRAME(); CHECK_SUSPEND_FLAGS(); diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 49d5e412c..b98e2cd4c 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -35,7 +35,8 @@ typedef float64 CellType_F64; #define CHECK_MEMORY_OVERFLOW(bytes) \ do { \ uint64 offset1 = (uint64)offset + (uint64)addr; \ - if (offset1 + bytes <= (uint64)get_linear_mem_size()) \ + if (disable_bounds_checks \ + || offset1 + bytes <= (uint64)get_linear_mem_size()) \ /* If offset1 is in valid range, maddr must also \ be in valid range, no need to check it again. */ \ maddr = memory->memory_data + offset1; \ @@ -43,15 +44,15 @@ typedef float64 CellType_F64; goto out_of_bounds; \ } while (0) -#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ - do { \ - uint64 offset1 = (uint32)(start); \ - if (offset1 + bytes <= get_linear_mem_size()) \ - /* App heap space is not valid space for \ - bulk memory operation */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ +#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ + do { \ + uint64 offset1 = (uint32)(start); \ + if (disable_bounds_checks || offset1 + bytes <= get_linear_mem_size()) \ + /* App heap space is not valid space for \ + bulk memory operation */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ } while (0) #else #define CHECK_MEMORY_OVERFLOW(bytes) \ @@ -481,28 +482,28 @@ LOAD_PTR(void *addr) CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(1); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint32)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(2); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint32)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(4); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = LOAD_I32(maddr); \ STORE_U32(maddr, readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ PUSH_I32(readv); \ break; \ @@ -521,39 +522,39 @@ LOAD_PTR(void *addr) CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(1); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(2); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(4); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_U32(maddr); \ STORE_U32(maddr, (uint32)(readv op sval)); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ else { \ uint64 op_result; \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(8); \ \ - os_mutex_lock(&node->shared_mem_lock); \ + shared_memory_lock(memory); \ readv = (uint64)LOAD_I64(maddr); \ op_result = readv op sval; \ STORE_I64(maddr, op_result); \ - os_mutex_unlock(&node->shared_mem_lock); \ + shared_memory_unlock(memory); \ } \ PUSH_I64(readv); \ break; \ @@ -937,8 +938,9 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, if (!func_import->call_conv_wasm_c_api) { native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; } - else if (module_inst->e->c_api_func_imports) { - c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; + else if (module_inst->e->common.c_api_func_imports) { + c_api_func_import = + module_inst->e->common.c_api_func_imports + cur_func_index; native_func_pointer = c_api_func_import->func_ptr_linked; } @@ -1064,18 +1066,17 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, #endif #if WASM_ENABLE_THREAD_MGR != 0 -#define CHECK_SUSPEND_FLAGS() \ - do { \ - os_mutex_lock(&exec_env->wait_lock); \ - if (exec_env->suspend_flags.flags != 0) { \ - if (exec_env->suspend_flags.flags & 0x01) { \ - /* terminate current thread */ \ - os_mutex_unlock(&exec_env->wait_lock); \ - return; \ - } \ - /* TODO: support suspend and breakpoint */ \ - } \ - os_mutex_unlock(&exec_env->wait_lock); \ +#define CHECK_SUSPEND_FLAGS() \ + do { \ + WASM_SUSPEND_FLAGS_LOCK(exec_env->wait_lock); \ + if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \ + & WASM_SUSPEND_FLAG_TERMINATE) { \ + /* terminate current thread */ \ + WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \ + return; \ + } \ + /* TODO: support suspend and breakpoint */ \ + WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \ } while (0) #endif @@ -1166,10 +1167,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { -#if WASM_ENABLE_SHARED_MEMORY != 0 - WASMSharedMemNode *node = - wasm_module_get_shared_memory((WASMModuleCommon *)module->module); -#endif WASMMemoryInstance *memory = wasm_get_default_memory(module); #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ @@ -1199,6 +1196,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint8 *maddr = NULL; uint32 local_idx, local_offset, global_idx; uint8 opcode, local_type, *global_addr; +#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ + || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled( + (WASMModuleInstanceCommon *)module); +#else + bool disable_bounds_checks = false; +#endif +#endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op @@ -3083,7 +3089,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, case WASM_OP_TABLE_INIT: { uint32 tbl_idx, elem_idx; - uint64 n, s, d; + uint32 n, s, d; WASMTableInstance *tbl_inst; elem_idx = read_uint32(frame_ip); @@ -3098,18 +3104,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - if (!n) { - break; - } - - if (n + s > module->module->table_segments[elem_idx] - .function_count - || d + n > tbl_inst->cur_size) { + if (offset_len_out_of_bounds( + s, n, + module->module->table_segments[elem_idx] + .function_count) + || offset_len_out_of_bounds(d, n, + tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; } + if (!n) { + break; + } + if (module->module->table_segments[elem_idx] .is_dropped) { wasm_set_exception(module, @@ -3148,7 +3157,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, case WASM_OP_TABLE_COPY: { uint32 src_tbl_idx, dst_tbl_idx; - uint64 n, s, d; + uint32 n, s, d; WASMTableInstance *src_tbl_inst, *dst_tbl_inst; dst_tbl_idx = read_uint32(frame_ip); @@ -3165,8 +3174,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - if (d + n > dst_tbl_inst->cur_size - || s + n > src_tbl_inst->cur_size) { + if (offset_len_out_of_bounds(d, n, + dst_tbl_inst->cur_size) + || offset_len_out_of_bounds( + s, n, src_tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; @@ -3237,7 +3248,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, fill_val = POP_I32(); i = POP_I32(); - if (i + n > tbl_inst->cur_size) { + if (offset_len_out_of_bounds(i, n, + tbl_inst->cur_size)) { wasm_set_exception(module, "out of bounds table access"); goto got_exception; @@ -3352,23 +3364,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)(*(uint8 *)maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)LOAD_U16(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I32(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I32(readv); @@ -3387,30 +3399,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)(*(uint8 *)maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U16(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U32(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I64(maddr); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I64(readv); @@ -3428,23 +3440,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U32(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } break; } @@ -3462,30 +3474,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_U32(maddr, (uint32)sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); STORE_I64(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } break; } @@ -3505,32 +3517,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(1); expect = (uint8)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); expect = (uint16)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint32)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = LOAD_I32(maddr); if (readv == expect) STORE_U32(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I32(readv); break; @@ -3551,43 +3563,43 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(1); expect = (uint8)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); expect = (uint16)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); expect = (uint32)expect; - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_U32(maddr); if (readv == expect) STORE_U32(maddr, (uint32)(sval)); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&node->shared_mem_lock); + shared_memory_lock(memory); readv = (uint64)LOAD_I64(maddr); if (readv == expect) STORE_I64(maddr, sval); - os_mutex_unlock(&node->shared_mem_lock); + shared_memory_unlock(memory); } PUSH_I64(readv); break; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 032e8f785..c74e87bf2 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -5487,6 +5487,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, @@ -5501,6 +5502,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, @@ -6177,27 +6179,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, @@ -6231,12 +6212,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; @@ -7025,6 +7018,7 @@ static bool copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, char *error_buf, uint32 error_buf_size) { + bool ret = false; int16 *frame_offset = NULL; uint8 *cells = NULL, cell; int16 *src_offsets = NULL; @@ -7095,13 +7089,13 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, if (is_if_block) PUSH_OFFSET_TYPE(VALUE_TYPE_I32); + ret = true; + +fail: /* Free the emit data */ wasm_runtime_free(emit_data); - return true; - -fail: - return false; + return ret; } #endif @@ -8087,9 +8081,13 @@ re_scan: case WASM_OP_SELECT_T: { uint8 vec_len, ref_type; +#if WASM_ENABLE_FAST_INTERP != 0 + uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled; +#endif read_leb_uint32(p, p_end, vec_len); - if (!vec_len) { + if (vec_len != 1) { + /* typed select must have exactly one result */ set_error_buf(error_buf, error_buf_size, "invalid result arity"); goto fail; @@ -8108,8 +8106,6 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 if (loader_ctx->p_code_compiled) { uint8 opcode_tmp = WASM_OP_SELECT; - uint8 *p_code_compiled_tmp = - loader_ctx->p_code_compiled - 2; if (ref_type == VALUE_TYPE_V128) { #if (WASM_ENABLE_SIMD == 0) \ diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index ebce01edb..ee2d43a88 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -3948,6 +3948,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, @@ -3962,6 +3963,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, @@ -4619,25 +4621,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, @@ -4671,12 +4654,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; @@ -6256,9 +6251,13 @@ re_scan: case WASM_OP_SELECT_T: { uint8 vec_len, ref_type; +#if WASM_ENABLE_FAST_INTERP != 0 + uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled; +#endif read_leb_uint32(p, p_end, vec_len); - if (!vec_len) { + if (vec_len != 1) { + /* typed select must have exactly one result */ set_error_buf(error_buf, error_buf_size, "invalid result arity"); goto fail; @@ -6277,8 +6276,6 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 if (loader_ctx->p_code_compiled) { uint8 opcode_tmp = WASM_OP_SELECT; - uint8 *p_code_compiled_tmp = - loader_ctx->p_code_compiled - 2; if (ref_type == VALUE_TYPE_F64 || ref_type == VALUE_TYPE_I64) diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 5b441dc88..301038a4d 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -122,11 +122,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst, } #endif #if WASM_ENABLE_SHARED_MEMORY != 0 - if (memories[i]->is_shared) { - int32 ref_count = shared_memory_dec_reference( - (WASMModuleCommon *)module_inst->module); - bh_assert(ref_count >= 0); - + if (shared_memory_is_shared(memories[i])) { + uint32 ref_count = shared_memory_dec_reference(memories[i]); /* if the reference count is not zero, don't free the memory */ if (ref_count > 0) @@ -159,7 +156,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst, } static WASMMemoryInstance * -memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory, +memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, + WASMMemoryInstance *memory, uint32 memory_idx, uint32 num_bytes_per_page, uint32 init_page_count, uint32 max_page_count, uint32 heap_size, uint32 flags, char *error_buf, uint32 error_buf_size) @@ -180,22 +178,11 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory, bool is_shared_memory = flags & 0x02 ? true : false; /* shared memory */ - if (is_shared_memory) { - WASMSharedMemNode *node = wasm_module_get_shared_memory( - (WASMModuleCommon *)module_inst->module); - /* If the memory of this module has been instantiated, - return the memory instance directly */ - if (node) { - uint32 ref_count; - ref_count = shared_memory_inc_reference( - (WASMModuleCommon *)module_inst->module); - bh_assert(ref_count > 0); - memory = (WASMMemoryInstance *)shared_memory_get_memory_inst(node); - bh_assert(memory); - - (void)ref_count; - return memory; - } + if (is_shared_memory && parent != NULL) { + bh_assert(parent->memory_count > memory_idx); + memory = parent->memories[memory_idx]; + shared_memory_inc_reference(memory); + return memory; } #endif /* end of WASM_ENABLE_SHARED_MEMORY */ @@ -215,7 +202,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory, if (num_bytes_per_page < heap_size) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " - "try using `--heap_size=0` option"); + "try using `--heap-size=0` option"); return NULL; } } @@ -274,7 +261,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory, if (init_page_count > DEFAULT_MAX_PAGES) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " - "try using `--heap_size=0` option"); + "try using `--heap-size=0` option"); return NULL; } else if (init_page_count == DEFAULT_MAX_PAGES) { @@ -388,24 +375,13 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory, #if WASM_ENABLE_SHARED_MEMORY != 0 if (is_shared_memory) { - memory->is_shared = true; - if (!shared_memory_set_memory_inst( - (WASMModuleCommon *)module_inst->module, - (WASMMemoryInstanceCommon *)memory)) { - set_error_buf(error_buf, error_buf_size, "allocate memory failed"); - goto fail4; - } + memory->ref_count = 1; } #endif LOG_VERBOSE("Memory instantiate success."); return memory; -#if WASM_ENABLE_SHARED_MEMORY != 0 -fail4: - if (heap_size > 0) - mem_allocator_destroy(memory->heap_handle); -#endif fail3: if (heap_size > 0) wasm_runtime_free(memory->heap_handle); @@ -428,7 +404,8 @@ fail1: */ static WASMMemoryInstance ** memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, - uint32 heap_size, char *error_buf, uint32 error_buf_size) + WASMModuleInstance *parent, uint32 heap_size, + char *error_buf, uint32 error_buf_size) { WASMImport *import; uint32 mem_index = 0, i, @@ -474,26 +451,29 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, else #endif { - if (!(memories[mem_index++] = memory_instantiate( - module_inst, memory, num_bytes_per_page, init_page_count, - max_page_count, actual_heap_size, flags, error_buf, - error_buf_size))) { + if (!(memories[mem_index] = memory_instantiate( + module_inst, parent, memory, mem_index, + num_bytes_per_page, init_page_count, max_page_count, + actual_heap_size, flags, error_buf, error_buf_size))) { memories_deinstantiate(module_inst, memories, memory_count); return NULL; } + mem_index++; } } /* instantiate memories from memory section */ for (i = 0; i < module->memory_count; i++, memory++) { - if (!(memories[mem_index++] = memory_instantiate( - module_inst, memory, module->memories[i].num_bytes_per_page, + if (!(memories[mem_index] = memory_instantiate( + module_inst, parent, memory, mem_index, + module->memories[i].num_bytes_per_page, module->memories[i].init_page_count, module->memories[i].max_page_count, heap_size, module->memories[i].flags, error_buf, error_buf_size))) { memories_deinstantiate(module_inst, memories, memory_count); return NULL; } + mem_index++; } bh_assert(mem_index == memory_count); @@ -1104,10 +1084,14 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst, goto fail; } +#if WASM_ENABLE_LIBC_WASI != 0 if (initialize_func && !wasm_call_function(exec_env, initialize_func, 0, NULL)) { goto fail; } +#else + (void)initialize_func; +#endif if (post_inst_func && !wasm_call_function(exec_env, post_inst_func, 0, NULL)) { @@ -1297,7 +1281,7 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst, WASMModuleInstance *sub_module_inst = NULL; sub_module_inst = - wasm_instantiate(sub_module, false, NULL, stack_size, heap_size, + wasm_instantiate(sub_module, NULL, NULL, stack_size, heap_size, error_buf, error_buf_size); if (!sub_module_inst) { LOG_DEBUG("instantiate %s failed", @@ -1642,7 +1626,7 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode) * Instantiate module */ WASMModuleInstance * -wasm_instantiate(WASMModule *module, bool is_sub_inst, +wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size) { @@ -1659,6 +1643,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, #if WASM_ENABLE_MULTI_MODULE != 0 bool ret = false; #endif + const bool is_sub_inst = parent != NULL; if (!module) return NULL; @@ -1777,8 +1762,9 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, /* Instantiate memories/tables/functions */ if ((module_inst->memory_count > 0 - && !(module_inst->memories = memories_instantiate( - module, module_inst, heap_size, error_buf, error_buf_size))) + && !(module_inst->memories = + memories_instantiate(module, module_inst, parent, heap_size, + error_buf, error_buf_size))) || (module_inst->table_count > 0 && !(module_inst->tables = tables_instantiate(module, module_inst, first_table, @@ -1853,7 +1839,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, for (i = 0; i < module->data_seg_count; i++) { WASMMemoryInstance *memory = NULL; uint8 *memory_data = NULL; - uint32 memory_size = 0; + uint64 memory_size = 0; WASMDataSeg *data_seg = module->data_segments[i]; #if WASM_ENABLE_BULK_MEMORY != 0 @@ -1866,7 +1852,8 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, bh_assert(memory); memory_data = memory->memory_data; - memory_size = memory->num_bytes_per_page * memory->cur_page_count; + memory_size = + (uint64)memory->num_bytes_per_page * memory->cur_page_count; bh_assert(memory_data || memory_size == 0); bh_assert(data_seg->base_offset.init_expr_type @@ -1912,7 +1899,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, /* check offset + length(could be zero) */ length = data_seg->data_length; - if (base_offset + length > memory_size) { + if ((uint64)base_offset + length > memory_size) { LOG_DEBUG("base_offset(%d) + length(%d) > memory_size(%d)", base_offset, length, memory_size); #if WASM_ENABLE_REF_TYPES != 0 @@ -1926,8 +1913,9 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, } if (memory_data) { - bh_memcpy_s(memory_data + base_offset, memory_size - base_offset, - data_seg->data, length); + bh_memcpy_s(memory_data + base_offset, + (uint32)memory_size - base_offset, data_seg->data, + length); } } @@ -2212,16 +2200,6 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) sub_module_deinstantiate(module_inst); #endif -#if WASM_ENABLE_LIBC_WASI != 0 - /* Destroy wasi resource before freeing app heap, since some fields of - wasi contex are allocated from app heap, and if app heap is freed, - these fields will be set to NULL, we cannot free their internal data - which may allocated from global heap. */ - /* Only destroy wasi ctx in the main module instance */ - if (!is_sub_inst) - wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); -#endif - if (module_inst->memory_count > 0) memories_deinstantiate(module_inst, module_inst->memories, module_inst->memory_count); @@ -2251,13 +2229,15 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) } #endif - if (module_inst->e->c_api_func_imports) - wasm_runtime_free(module_inst->e->c_api_func_imports); + if (module_inst->e->common.c_api_func_imports) + wasm_runtime_free(module_inst->e->common.c_api_func_imports); + if (!is_sub_inst) { #if WASM_ENABLE_WASI_NN != 0 - if (!is_sub_inst) wasi_nn_destroy(module_inst); #endif + wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst); + } wasm_runtime_free(module_inst); } @@ -2418,6 +2398,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); } @@ -3113,11 +3096,7 @@ llvm_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, { bool ret; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == exec_env->module_inst->module_type) { - return aot_call_indirect(exec_env, tbl_idx, elem_idx, argc, argv); - } -#endif + bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode); ret = call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, false, 0); #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -3144,11 +3123,7 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, char buf[96]; bool ret = false; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == exec_env->module_inst->module_type) { - return aot_invoke_native(exec_env, func_idx, argc, argv); - } -#endif + bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode); module_inst = (WASMModuleInstance *)wasm_runtime_get_module_inst(exec_env); module = module_inst->module; @@ -3161,8 +3136,9 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, import_func = &module->import_functions[func_idx].u.function; if (import_func->call_conv_wasm_c_api) { - if (module_inst->e->c_api_func_imports) { - c_api_func_import = module_inst->e->c_api_func_imports + func_idx; + if (module_inst->e->common.c_api_func_imports) { + c_api_func_import = + module_inst->e->common.c_api_func_imports + func_idx; func_ptr = c_api_func_import->func_ptr_linked; } else { @@ -3217,11 +3193,7 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index, uint8 *maddr; uint64 seg_len = 0; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_memory_init(module_inst, seg_index, offset, len, dst); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); memory_inst = wasm_get_default_memory(module_inst); module = module_inst->module; @@ -3247,11 +3219,7 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index, bool llvm_jit_data_drop(WASMModuleInstance *module_inst, uint32 seg_index) { -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_data_drop(module_inst, seg_index); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); module_inst->module->data_segments[seg_index]->data_length = 0; /* Currently we can't free the dropped data segment @@ -3266,11 +3234,7 @@ llvm_jit_drop_table_seg(WASMModuleInstance *module_inst, uint32 tbl_seg_idx) { WASMTableSeg *tbl_segs; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_drop_table_seg(module_inst, tbl_seg_idx); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); tbl_segs = module_inst->module->table_segments; tbl_segs[tbl_seg_idx].is_dropped = true; @@ -3284,12 +3248,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, WASMTableInstance *tbl_inst; WASMTableSeg *tbl_seg; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_table_init(module_inst, tbl_idx, tbl_seg_idx, length, - src_offset, dst_offset); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); tbl_inst = wasm_get_table_inst(module_inst, tbl_idx); tbl_seg = module_inst->module->table_segments + tbl_seg_idx; @@ -3297,13 +3256,13 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, bh_assert(tbl_inst); bh_assert(tbl_seg); - if (!length) { + if (offset_len_out_of_bounds(src_offset, length, tbl_seg->function_count) + || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) { + jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } - if (length + src_offset > tbl_seg->function_count - || dst_offset + length > tbl_inst->cur_size) { - jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); + if (!length) { return; } @@ -3332,21 +3291,16 @@ llvm_jit_table_copy(WASMModuleInstance *module_inst, uint32 src_tbl_idx, WASMTableInstance *src_tbl_inst; WASMTableInstance *dst_tbl_inst; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - aot_table_copy(module_inst, src_tbl_idx, dst_tbl_idx, length, - src_offset, dst_offset); - return; - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); src_tbl_inst = wasm_get_table_inst(module_inst, src_tbl_idx); dst_tbl_inst = wasm_get_table_inst(module_inst, dst_tbl_idx); bh_assert(src_tbl_inst); bh_assert(dst_tbl_inst); - if ((uint64)dst_offset + length > dst_tbl_inst->cur_size - || (uint64)src_offset + length > src_tbl_inst->cur_size) { + if (offset_len_out_of_bounds(dst_offset, length, dst_tbl_inst->cur_size) + || offset_len_out_of_bounds(src_offset, length, + src_tbl_inst->cur_size)) { jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } @@ -3368,17 +3322,12 @@ llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx, { WASMTableInstance *tbl_inst; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - aot_table_fill(module_inst, tbl_idx, length, val, data_offset); - return; - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); tbl_inst = wasm_get_table_inst(module_inst, tbl_idx); bh_assert(tbl_inst); - if (data_offset + length > tbl_inst->cur_size) { + if (offset_len_out_of_bounds(data_offset, length, tbl_inst->cur_size)) { jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } @@ -3395,11 +3344,7 @@ llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx, WASMTableInstance *tbl_inst; uint32 i, orig_size, total_size; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == module_inst->module_type) { - return aot_table_grow(module_inst, tbl_idx, inc_size, init_val); - } -#endif + bh_assert(module_inst->module_type == Wasm_Module_Bytecode); tbl_inst = wasm_get_table_inst(module_inst, tbl_idx); if (!tbl_inst) { @@ -3439,11 +3384,7 @@ llvm_jit_alloc_frame(WASMExecEnv *exec_env, uint32 func_index) WASMInterpFrame *frame; uint32 size; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == exec_env->module_inst->module_type) { - return aot_alloc_frame(exec_env, func_index); - } -#endif + bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode); module_inst = (WASMModuleInstance *)exec_env->module_inst; size = wasm_interp_interp_frame_size(0); @@ -3472,12 +3413,7 @@ llvm_jit_free_frame(WASMExecEnv *exec_env) WASMInterpFrame *frame; WASMInterpFrame *prev_frame; -#if WASM_ENABLE_JIT != 0 - if (Wasm_Module_AoT == exec_env->module_inst->module_type) { - aot_free_frame(exec_env); - return; - } -#endif + bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode); frame = wasm_exec_env_get_cur_frame(exec_env); prev_frame = frame->prev_frame; diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index ef9f0b713..605cefc6c 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -7,6 +7,7 @@ #define _WASM_RUNTIME_H #include "wasm.h" +#include "bh_atomic.h" #include "bh_hashmap.h" #include "../common/wasm_runtime_common.h" #include "../common/wasm_exec_env.h" @@ -79,7 +80,7 @@ struct WASMMemoryInstance { /* Module type */ uint32 module_type; /* Shared memory flag */ - bool is_shared; + bh_atomic_32_t ref_count; /* 0: non-shared, > 0: reference count */ /* Number bytes per page */ uint32 num_bytes_per_page; @@ -209,8 +210,22 @@ typedef struct CApiFuncImport { void *env_arg; } 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; +#endif +} WASMModuleInstanceExtraCommon; + /* Extra info of WASM module instance for interpreter/jit mode */ typedef struct WASMModuleInstanceExtra { + WASMModuleInstanceExtraCommon common; + WASMGlobalInstance *globals; WASMFunctionInstance *functions; @@ -222,7 +237,6 @@ typedef struct WASMModuleInstanceExtra { WASMFunctionInstance *free_function; WASMFunctionInstance *retain_function; - CApiFuncImport *c_api_func_imports; RunningMode running_mode; #if WASM_ENABLE_MULTI_MODULE != 0 @@ -286,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 */ @@ -396,7 +406,7 @@ void wasm_unload(WASMModule *module); WASMModuleInstance * -wasm_instantiate(WASMModule *module, bool is_sub_inst, +wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size); @@ -657,6 +667,16 @@ void wasm_propagate_wasi_args(WASMModule *module); #endif +#if WASM_ENABLE_THREAD_MGR != 0 +void +exception_lock(WASMModuleInstance *module_inst); +void +exception_unlock(WASMModuleInstance *module_inst); +#else +#define exception_lock(module_inst) (void)(module_inst) +#define exception_unlock(module_inst) (void)(module_inst) +#endif + #ifdef __cplusplus } #endif diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index 206479c2a..56deaff32 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -531,7 +531,8 @@ pthread_start_routine(void *arg) else { info_node->u.ret = (void *)(uintptr_t)argv[0]; #ifdef OS_ENABLE_HW_BOUND_CHECK - if (exec_env->suspend_flags.flags & 0x08) + if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) + & WASM_SUSPEND_FLAG_EXIT) /* argv[0] isn't set after longjmp(1) to invoke_native_with_hw_bound_check */ info_node->u.ret = exec_env->thread_ret_value; @@ -558,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); @@ -580,18 +578,14 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, #endif if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, true, exec_env, stack_size, 0, NULL, 0))) + module, module_inst, exec_env, stack_size, 0, NULL, 0))) return -1; /* Set custom_data to new module instance */ 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; @@ -690,6 +684,14 @@ pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread, bh_assert(node->joinable); join_ret = 0; ret = node->u.ret; + + /* The target thread changes the node's status before calling + wasm_cluster_exit_thread to exit, so here its resources may + haven't been destroyed yet, we wait enough time to ensure that + they are actually destroyed to avoid unexpected behavior. */ + os_mutex_lock(&exec_env->wait_lock); + os_cond_reltimedwait(&exec_env->wait_cond, &exec_env->wait_lock, 1000); + os_mutex_unlock(&exec_env->wait_lock); } if (retval_offset != 0) @@ -757,7 +759,6 @@ __pthread_self_wrapper(wasm_exec_env_t exec_env) static void pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset) { - wasm_module_inst_t module_inst = get_module_inst(exec_env); ThreadRoutineArgs *args = get_thread_arg(exec_env); /* Currently exit main thread is not allowed */ if (!args) @@ -775,9 +776,6 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset) /* destroy pthread key values */ call_key_destructor(exec_env); - /* routine exit, destroy instance */ - wasm_runtime_deinstantiate_internal(module_inst, true); - if (!args->info_node->joinable) { delete_thread_info_node(args->info_node); } @@ -789,6 +787,8 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset) wasm_runtime_free(args); + /* Don't destroy exec_env->module_inst in this functuntion since + it will be destroyed in wasm_cluster_exit_thread */ wasm_cluster_exit_thread(exec_env, (void *)(uintptr_t)retval_offset); } diff --git a/core/iwasm/libraries/lib-rats/lib_rats.cmake b/core/iwasm/libraries/lib-rats/lib_rats.cmake index b773c837e..e17a6b25a 100644 --- a/core/iwasm/libraries/lib-rats/lib_rats.cmake +++ b/core/iwasm/libraries/lib-rats/lib_rats.cmake @@ -23,6 +23,7 @@ include(FetchContent) set(RATS_BUILD_MODE "sgx" CACHE INTERNAL "Select build mode for librats(host|occlum|sgx|wasm)") set(RATS_INSTALL_PATH "${CMAKE_BINARY_DIR}/librats" CACHE INTERNAL "") +set(BUILD_SAMPLES OFF CACHE BOOL "Disable de compilation of the librats samples" FORCE) FetchContent_Declare( librats @@ -34,8 +35,17 @@ if (NOT librats_POPULATED) message("-- Fetching librats ..") FetchContent_Populate(librats) include_directories("${librats_SOURCE_DIR}/include") + + # Prevent the propagation of the CMAKE_C_FLAGS of WAMR into librats + set(SAVED_CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) + set(CMAKE_C_FLAGS "") + + # Import the building scripts of librats add_subdirectory(${librats_SOURCE_DIR} ${librats_BINARY_DIR} EXCLUDE_FROM_ALL) + # Restore the CMAKE_C_FLAGS of WAMR + set(CMAKE_C_FLAGS ${SAVED_CMAKE_C_FLAGS}) + endif() file (GLOB source_all ${LIB_RATS_DIR}/*.c) diff --git a/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h b/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h index c9a07eb72..98429bbb0 100644 --- a/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h +++ b/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h @@ -17,6 +17,8 @@ extern "C" { #endif typedef enum { + /* Used only for sock_addr_resolve hints */ + SOCKET_ANY = -1, SOCKET_DGRAM = 0, SOCKET_STREAM, } __wasi_sock_type_t; @@ -84,7 +86,7 @@ typedef struct __wasi_addr_t { } addr; } __wasi_addr_t; -typedef enum { INET4 = 0, INET6 } __wasi_address_family_t; +typedef enum { INET4 = 0, INET6, INET_UNSPEC } __wasi_address_family_t; typedef struct __wasi_addr_info_t { __wasi_addr_t addr; diff --git a/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c b/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c index defbc6efe..1172d0a77 100644 --- a/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c +++ b/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c @@ -430,6 +430,9 @@ addrinfo_hints_to_wasi_hints(const struct addrinfo *hints, case AF_INET6: wasi_hints->family = INET6; break; + case AF_UNSPEC: + wasi_hints->family = INET_UNSPEC; + break; default: return __WASI_ERRNO_AFNOSUPPORT; } @@ -440,6 +443,8 @@ addrinfo_hints_to_wasi_hints(const struct addrinfo *hints, case SOCK_DGRAM: wasi_hints->type = SOCKET_DGRAM; break; + case 0: + wasi_hints->type = SOCKET_ANY; default: return __WASI_ERRNO_NOTSUP; } diff --git a/core/iwasm/libraries/lib-socket/test/nslookup.c b/core/iwasm/libraries/lib-socket/test/nslookup.c index 37150f1eb..8e64d06be 100644 --- a/core/iwasm/libraries/lib-socket/test/nslookup.c +++ b/core/iwasm/libraries/lib-socket/test/nslookup.c @@ -5,6 +5,8 @@ #include #include +#include +#include #ifdef __wasi__ #include #include @@ -39,11 +41,28 @@ test_nslookup(int af) freeaddrinfo(res); } +void * +test_nslookup_mt(void *params) +{ + int *af = (int *)params; + test_nslookup(*af); + return NULL; +} + int main() { - test_nslookup(AF_INET); /* for ipv4 */ - test_nslookup(AF_INET6); /* for ipv6 */ + int afs[] = { AF_INET, AF_INET6 }; + + for (int i = 0; i < sizeof(afs) / sizeof(afs[0]); i++) { + pthread_t th; + + printf("Testing %d in main thread...\n", afs[i]); + test_nslookup(afs[i]); + printf("Testing %d in a new thread...\n", afs[i]); + pthread_create(&th, NULL, test_nslookup_mt, &afs[i]); + pthread_join(th, NULL); + } return 0; } diff --git a/core/iwasm/libraries/lib-socket/test/tcp_udp.c b/core/iwasm/libraries/lib-socket/test/tcp_udp.c index 49231de89..0ed031250 100644 --- a/core/iwasm/libraries/lib-socket/test/tcp_udp.c +++ b/core/iwasm/libraries/lib-socket/test/tcp_udp.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #ifdef __wasi__ #include #include @@ -12,105 +14,123 @@ #endif #include #include +#include + #define SERVER_MSG "Message from server." #define PORT 8989 -pthread_mutex_t mut; -pthread_cond_t cond; + +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + int server_init_complete = 0; -char buffer[sizeof(SERVER_MSG) + 1]; -struct socket_info { - union { - struct sockaddr_in addr_ipv4; - struct sockaddr_in6 addr_ipv6; - } addr; +typedef struct { + struct sockaddr_storage addr; + socklen_t addr_len; int sock; -}; - -struct thread_args { - int family; int protocol; -}; +} socket_info_t; -struct socket_info -init_socket_addr(int family, int protocol) +void +wait_for_server(int wait_time_seconds) { - int sock = socket(family, protocol, 0); - assert(sock != -1); + int res = 0; + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += wait_time_seconds; - struct socket_info info; - if (family == AF_INET) { - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(PORT); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - info.addr.addr_ipv4 = addr; + pthread_mutex_lock(&mut); + while (server_init_complete == 0) { + res = pthread_cond_timedwait(&cond, &mut, &ts); + if (res == ETIMEDOUT) + break; } - else if (family == AF_INET6) { - struct sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_port = htons(PORT); - addr.sin6_addr = in6addr_loopback; - info.addr.addr_ipv6 = addr; - } - info.sock = sock; - return info; + pthread_mutex_unlock(&mut); + + assert(res == 0); } void -assert_thread_args(struct thread_args *args) +notify_server_started() { - assert(args->family == AF_INET || args->family == AF_INET6); - assert(args->protocol == SOCK_STREAM || args->protocol == SOCK_DGRAM); + pthread_mutex_lock(&mut); + server_init_complete = 1; + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mut); +} + +socket_info_t +init_socket_addr(int family, int protocol) +{ + socket_info_t info; + + info.sock = socket(family, protocol, 0); + assert(info.sock != -1); + info.protocol = protocol; + + memset(&info.addr, 0, sizeof(info.addr)); + + if (family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *)&info.addr; + addr->sin_family = AF_INET; + addr->sin_port = htons(PORT); + addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + info.addr_len = sizeof(struct sockaddr_in); + } + else if (family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&info.addr; + addr->sin6_family = AF_INET6; + addr->sin6_port = htons(PORT); + addr->sin6_addr = in6addr_loopback; + info.addr_len = sizeof(struct sockaddr_in6); + } + + return info; } void * server(void *arg) { - server_init_complete = 0; - struct thread_args *args = (struct thread_args *)arg; - assert_thread_args(args); - - struct socket_info init_server_sock = - init_socket_addr(args->family, args->protocol); - - int server_sock = init_server_sock.sock; - socklen_t addr_size; + char buffer[sizeof(SERVER_MSG) + 1] = { 0 }; struct sockaddr_storage client_addr; - strcpy(buffer, SERVER_MSG); + socket_info_t *info = (socket_info_t *)arg; + struct sockaddr *server_addr = (struct sockaddr *)&info->addr; + int server_sock = info->sock; - struct sockaddr *server_addr = (struct sockaddr *)&init_server_sock.addr; - int ret = bind(server_sock, server_addr, - args->family == AF_INET ? sizeof(struct sockaddr_in) - : sizeof(struct sockaddr_in6)); - assert(ret == 0); + int optval = 1; + assert(setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &optval, + sizeof(optval)) + == 0); - (args->protocol == SOCK_STREAM) && listen(server_sock, 1); - pthread_mutex_lock(&mut); - server_init_complete = 1; - pthread_mutex_unlock(&mut); - pthread_cond_signal(&cond); + assert(bind(server_sock, server_addr, info->addr_len) == 0); - addr_size = sizeof(client_addr); - if (args->protocol == SOCK_STREAM) { + if (info->protocol == SOCK_STREAM) + listen(server_sock, 1); + notify_server_started(); + + socklen_t addr_size = info->addr_len; + if (info->protocol == SOCK_STREAM) { int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &addr_size); assert(client_sock >= 0); - sendto(client_sock, buffer, strlen(buffer), 0, - (struct sockaddr *)&client_addr, addr_size); - - assert(close(client_sock) == 0); + assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0); + strcpy(buffer, SERVER_MSG); + assert(send(client_sock, buffer, sizeof(buffer), 0) > 0); + assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0); } else { - recvfrom(server_sock, buffer, sizeof(buffer), 0, - (struct sockaddr *)&client_addr, &addr_size); - sendto(server_sock, buffer, strlen(buffer), 0, - (struct sockaddr *)&client_addr, addr_size); - - assert(close(server_sock) == 0); + assert(recvfrom(server_sock, buffer, sizeof(buffer), 0, + (struct sockaddr *)&client_addr, &addr_size) + > 0); + strcpy(buffer, SERVER_MSG); + assert(sendto(server_sock, buffer, strlen(buffer), 0, + (struct sockaddr *)&client_addr, addr_size) + > 0); + assert(recvfrom(server_sock, buffer, sizeof(buffer), 0, + (struct sockaddr *)&client_addr, &addr_size) + > 0); } + assert(close(server_sock) == 0); return NULL; } @@ -118,46 +138,23 @@ server(void *arg) void * client(void *arg) { - struct thread_args *args = (struct thread_args *)arg; - assert_thread_args(args); + char buffer[sizeof(SERVER_MSG) + 1]; + socket_info_t *info = (socket_info_t *)arg; + int sock = info->sock; + struct sockaddr *addr = (struct sockaddr *)&info->addr; - pthread_mutex_lock(&mut); + wait_for_server(1); - while (server_init_complete == 0) { - pthread_cond_wait(&cond, &mut); + if (info->protocol == SOCK_STREAM) { + assert(connect(sock, addr, info->addr_len) != -1); } - struct socket_info init_client_sock = - init_socket_addr(args->family, args->protocol); - int sock = init_client_sock.sock; - pthread_mutex_unlock(&mut); - - if (args->family == AF_INET) { - struct sockaddr_in addr = init_client_sock.addr.addr_ipv4; - if (args->protocol == SOCK_STREAM) { - assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1); - } - else { - assert(sendto(sock, buffer, strlen(buffer), 0, - (struct sockaddr *)&addr, sizeof(addr)) - != -1); - } - } - else { - struct sockaddr_in6 addr = init_client_sock.addr.addr_ipv6; - if (args->protocol == SOCK_STREAM) { - assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1); - } - else { - assert(sendto(sock, buffer, strlen(buffer), 0, - (struct sockaddr *)&addr, sizeof(addr)) - != -1); - } - } - - recv(sock, buffer, sizeof(buffer), 0); - assert(strcmp(buffer, SERVER_MSG) == 0); + assert(sendto(sock, "open", strlen("open"), 0, addr, info->addr_len) > 0); + assert(recv(sock, buffer, sizeof(buffer), 0) > 0); + assert(strncmp(buffer, SERVER_MSG, strlen(SERVER_MSG)) == 0); + assert(sendto(sock, "close", sizeof("close"), 0, addr, info->addr_len) > 0); assert(close(sock) == 0); + return NULL; } @@ -165,17 +162,19 @@ void test_protocol(int family, int protocol) { pthread_t server_thread, client_thread; - assert(pthread_cond_init(&cond, NULL) == 0); - assert(pthread_mutex_init(&mut, NULL) == 0); + socket_info_t server_info = init_socket_addr(family, protocol); + socket_info_t client_info = init_socket_addr(family, protocol); - struct thread_args args = { family, protocol }; - assert(pthread_create(&server_thread, NULL, server, (void *)&args) == 0); - assert(pthread_create(&client_thread, NULL, client, (void *)&args) == 0); + printf("Testing address family: %d protocol: %d\n", family, protocol); + + server_init_complete = 0; + + assert(pthread_create(&server_thread, NULL, server, (void *)&server_info) + == 0); + assert(pthread_create(&client_thread, NULL, client, (void *)&client_info) + == 0); assert(pthread_join(server_thread, NULL) == 0); assert(pthread_join(client_thread, NULL) == 0); - - assert(pthread_mutex_destroy(&mut) == 0); - assert(pthread_cond_destroy(&cond) == 0); } int @@ -190,4 +189,4 @@ main(int argc, char **argv) test_protocol(AF_INET6, SOCK_DGRAM); return 0; -} \ No newline at end of file +} diff --git a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c index 6b36c9073..7e557be90 100644 --- a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c +++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c @@ -80,9 +80,6 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) int32 thread_id; uint32 stack_size = 8192; int32 ret = -1; -#if WASM_ENABLE_LIBC_WASI != 0 - WASIContext *wasi_ctx; -#endif bh_assert(module); bh_assert(module_inst); @@ -90,7 +87,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size; if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, true, exec_env, stack_size, 0, NULL, 0))) + module, module_inst, exec_env, stack_size, 0, NULL, 0))) return -1; wasm_runtime_set_custom_data_internal( @@ -99,11 +96,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst))) goto thread_preparation_fail; -#if WASM_ENABLE_LIBC_WASI != 0 - wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst); - if (wasi_ctx) - wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx); -#endif + wasm_native_inherit_contexts(new_module_inst, module_inst); start_func = wasm_runtime_lookup_function(new_module_inst, THREAD_START_FUNCTION, NULL); diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh b/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh new file mode 100755 index 000000000..341f3ef12 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# +# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +set -eo pipefail +CC=${CC:=/opt/wasi-sdk/bin/clang} +WAMR_DIR=../../../../.. + +show_usage() { + echo "Usage: $0 [--sysroot PATH_TO_SYSROOT]" + echo "--sysroot PATH_TO_SYSROOT specify to build with custom sysroot for wasi-libc" +} + +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + --sysroot) + sysroot_path="$2" + shift + shift + ;; + --help) + show_usage + exit + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +rm -rf *.wasm +rm -rf *.aot + +for test_c in *.c; do + test_wasm="$(basename $test_c .c).wasm" + + if [[ -n "$sysroot_path" ]]; then + if [ ! -d "$sysroot_path" ]; then + echo "Directory $sysroot_path doesn't exist. Aborting" + exit 1 + fi + sysroot_command="--sysroot $sysroot_path" + fi + + echo "Compiling $test_c to $test_wasm" + $CC \ + -target wasm32-wasi-threads \ + -O2 \ + -Wall \ + -pthread \ + -z stack-size=32768 \ + -Wl,--export=__heap_base \ + -Wl,--export=__data_end \ + -Wl,--shared-memory,--max-memory=1966080 \ + -Wl,--export=wasi_thread_start \ + -Wl,--export=malloc \ + -Wl,--export=free \ + $sysroot_command \ + $test_c -o $test_wasm +done diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c new file mode 100644 index 000000000..3b594657f --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include "mutex_common.h" + +int +main() +{ + pthread_mutex_t mutex; + + // Set mutex type to errorcheck. This type provides some additional checks + // (for example returns EDEADLK instead of deadlocking in some cases) + pthread_mutexattr_t mutex_attr; + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); + + pthread_mutex_init(&mutex, &mutex_attr); + pthread_mutexattr_destroy(&mutex_attr); + + run_common_tests(&mutex); + fprintf(stderr, "Errorcheck mutex test is completed\n"); + pthread_mutex_destroy(&mutex); +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/manifest.json b/core/iwasm/libraries/lib-wasi-threads/stress-test/manifest.json new file mode 100644 index 000000000..bb91ad083 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/manifest.json @@ -0,0 +1,3 @@ +{ + "name": "lib-wasi-threads stress tests" +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/mutex_common.h b/core/iwasm/libraries/lib-wasi-threads/stress-test/mutex_common.h new file mode 100644 index 000000000..d57ff7d50 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/mutex_common.h @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef MUTEX_COMMON_H +#define MUTEX_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum Constants { + NUM_ITER = 250000, + NUM_THREADS = 12, + NUM_RETRY = 8, + RETRY_SLEEP_TIME_US = 1000, +}; + +// We're counting how many times each thread was called using this array +// Main thread is also counted here so we need to make arrays bigger +typedef struct { + int tids[NUM_THREADS + 1]; + int calls[NUM_THREADS + 1]; +} StatCollector; + +typedef struct { + pthread_mutex_t *mutex; + StatCollector stat; + int counter; + bool is_sleeping; +} MutexCounter; + +// This enum defines whether thread should sleep to increase contention +enum SleepState { + NON_SLEEP = 0, + SLEEP = 1, +}; + +void +mutex_counter_init(MutexCounter *mutex_counter, pthread_mutex_t *mutex, + enum SleepState is_sleeping) +{ + memset(mutex_counter, 0, sizeof(*mutex_counter)); + mutex_counter->mutex = mutex; + mutex_counter->is_sleeping = is_sleeping; +} + +// This function spawns the thread using exponential retries if it receives +// EAGAIN +static inline void +spawn_thread(pthread_t *tid, void *func, void *arg) +{ + int status_code = -1; + int timeout_us = RETRY_SLEEP_TIME_US; + for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) { + status_code = pthread_create(tid, NULL, (void *(*)(void *))func, arg); + assert(status_code == 0 || status_code == EAGAIN); + if (status_code == EAGAIN) { + usleep(timeout_us); + timeout_us *= 2; + } + } + + assert(status_code == 0 && "Thread creation should succeed"); +} + +// This function adds tid to our stat +static inline void +add_to_stat(StatCollector *stat, int tid) +{ + int tid_num = 0; + for (; tid_num < NUM_THREADS + 1 && stat->tids[tid_num] != 0; ++tid_num) { + if (stat->tids[tid_num] == tid) { + stat->calls[tid_num]++; + return; + } + } + + assert(tid_num < NUM_THREADS + 1); + stat->tids[tid_num] = tid; + stat->calls[tid_num] = 1; +} + +// This function prints number of calls by TID +static inline void +print_stat(StatCollector *stat) +{ + fprintf(stderr, "Thread calls count by TID\n"); + for (int i = 0; i < NUM_THREADS + 1; ++i) { + if (stat->tids[i] != 0) { + fprintf(stderr, "TID: %d; Calls: %d\n", stat->tids[i], + stat->calls[i]); + } + } +} + +// This function is run by the threads, it increases counter in a loop and then +// sleeps after unlocking the mutex to provide better contention +static inline void * +inc_shared_variable(void *arg) +{ + MutexCounter *mutex_counter = (MutexCounter *)(arg); + int sleep_us = 0; + while (!pthread_mutex_lock(mutex_counter->mutex) + && mutex_counter->counter < NUM_ITER) { + mutex_counter->counter++; + add_to_stat(&mutex_counter->stat, (int)(pthread_self())); + if (mutex_counter->is_sleeping) { + sleep_us = rand() % 1000; + } + + assert(pthread_mutex_unlock(mutex_counter->mutex) == 0 + && "Should be able to unlock a mutex"); + if (mutex_counter->is_sleeping) { + usleep(sleep_us); + } + } + + assert(mutex_counter->counter == NUM_ITER); + assert(pthread_mutex_unlock(mutex_counter->mutex) == 0 + && "Should be able to unlock the mutex after test execution"); + + return NULL; +} + +// Locking and unlocking a mutex in a single thread. +static inline void * +same_thread_lock_unlock_test(void *mutex) +{ + for (int i = 0; i < NUM_ITER; ++i) { + assert(pthread_mutex_lock(mutex) == 0 + && "Main thread should be able to lock a mutex"); + assert(pthread_mutex_unlock(mutex) == 0 + && "Main thread should be able to unlock a mutex"); + } + + return NULL; +} + +// This function spawns a thread that locks and unlocks a mutex `NUM_ITER` times +// in a row +static inline void +same_non_main_thread_lock_unlock_test(pthread_mutex_t *mutex) +{ + pthread_t tid = 0; + spawn_thread(&tid, same_thread_lock_unlock_test, mutex); + + assert(tid != 0 && "TID can't be 0 after successful thread creation"); + assert(pthread_join(tid, NULL) == 0 + && "Thread should be joined successfully"); +} + +// This function checks basic contention between main and non-main thread +// increasing the shared variable +static inline void +two_threads_inc_test(pthread_mutex_t *mutex) +{ + MutexCounter mutex_counter; + mutex_counter_init(&mutex_counter, mutex, false); + + pthread_t tid = 0; + spawn_thread(&tid, inc_shared_variable, &mutex_counter); + + assert(tid != 0 && "TID can't be 0 after successful thread creation"); + inc_shared_variable(&mutex_counter); + assert(pthread_join(tid, NULL) == 0 + && "Thread should be joined without errors"); + assert(mutex_counter.counter == NUM_ITER); +} + +// This function creates number of threads specified by NUM_THREADS and run +// concurrent increasing of shared variable +static inline void +max_threads_inc_test(pthread_mutex_t *mutex, int threads_num, + enum SleepState is_sleeping) +{ + MutexCounter mutex_counter; + mutex_counter_init(&mutex_counter, mutex, is_sleeping); + + pthread_t tids[threads_num]; + for (int i = 0; i < threads_num; ++i) { + spawn_thread(&tids[i], inc_shared_variable, &mutex_counter); + } + + inc_shared_variable(&mutex_counter); + + for (int i = 0; i < threads_num; ++i) { + assert(pthread_join(tids[i], NULL) == 0 + && "Thread should be joined without errors"); + } + + print_stat(&mutex_counter.stat); +} + +// This function just runs all the tests described above +static inline void +run_common_tests(pthread_mutex_t *mutex) +{ + srand(time(NULL)); + + fprintf(stderr, "Starting same_thread_lock_unlock_test test\n"); + same_thread_lock_unlock_test(mutex); + fprintf(stderr, "Finished same_thread_lock_unlock_test test\n"); + + fprintf(stderr, "Starting same_non_main_thread_lock_unlock_test test\n"); + same_non_main_thread_lock_unlock_test(mutex); + fprintf(stderr, "Finished same_non_main_thread_lock_unlock_test test\n"); + + fprintf(stderr, "Starting two_threads_inc_test test\n"); + two_threads_inc_test(mutex); + fprintf(stderr, "Finished two_threads_inc_test test\n"); + + fprintf(stderr, "Starting max_threads_inc_test_sleep test\n"); + max_threads_inc_test(mutex, NUM_THREADS, SLEEP); + fprintf(stderr, "Finished concurrent_inc sleep test\n"); + + fprintf(stderr, "Starting max_threads_inc_test_non_sleep test\n"); + max_threads_inc_test(mutex, NUM_THREADS, NON_SLEEP); + fprintf(stderr, "Finished max_threads_inc_test test\n"); +} + +#endif // MUTEX_COMMON_H diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c new file mode 100644 index 000000000..6c75f8814 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include "mutex_common.h" + +int +main() +{ + pthread_mutex_t mutex; + pthread_mutex_init(&mutex, NULL); + + run_common_tests(&mutex); + + fprintf(stderr, "Normal mutex test is completed\n"); + pthread_mutex_destroy(&mutex); +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c new file mode 100644 index 000000000..8c3e325e8 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include "mutex_common.h" + +void +multiple_same_thread_lock(void *mutex) +{ + for (int i = 0; i < 100; ++i) { + assert(pthread_mutex_lock(mutex) == 0 + && "Recursive mutex should allow multiple locking"); + } + + for (int i = 0; i < 100; ++i) { + assert(pthread_mutex_unlock(mutex) == 0 + && "Recursive mutex should allow multiple unlocking"); + } +} + +void * +same_thread_multiple_rec_mutex_lock(void *mutex) +{ + for (int i = 0; i < NUM_ITER; ++i) { + multiple_same_thread_lock(mutex); + } + + return NULL; +} + +int +main() +{ + pthread_mutex_t mutex; + + // Set mutex type to recursive. This type allows multiple locking and + // unlocking within the same thread + pthread_mutexattr_t mutex_attr; + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&mutex, &mutex_attr); + pthread_mutexattr_destroy(&mutex_attr); + + run_common_tests(&mutex); + + fprintf(stderr, "Starting same_thread_multiple_rec_mutex_lock test\n"); + same_thread_multiple_rec_mutex_lock(&mutex); + fprintf(stderr, "Finished same_thread_multiple_rec_mutex_lock test\n"); + + fprintf(stderr, "Starting same_thread_multiple_rec_mutex_lock test in " + "non-main thread\n"); + pthread_t tid; + spawn_thread(&tid, same_thread_multiple_rec_mutex_lock, &mutex); + assert(pthread_join(tid, NULL) == 0 + && "Non-main thread should be joined successfully"); + fprintf(stderr, "Finished same_thread_multiple_rec_mutex_lock test in " + "non-main thread\n"); + + fprintf(stderr, "Recursive mutex test is completed\n"); + pthread_mutex_destroy(&mutex); +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c new file mode 100644 index 000000000..a35337f35 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef __wasi__ +#error This example only compiles to WASM/WASI target +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +enum CONSTANTS { + NUM_ITER = 100000, + NUM_RETRY = 8, + MAX_NUM_THREADS = 12, + RETRY_SLEEP_TIME_US = 2000, +}; + +unsigned prime_numbers_count = 0; + +bool +is_prime(unsigned int num) +{ + for (unsigned int i = 2; i <= (unsigned int)(sqrt(num)); ++i) { + if (num % i == 0) { + return false; + } + } + + return true; +} + +void * +check_if_prime(void *value) +{ + unsigned int *num = (unsigned int *)(value); + usleep(10000); + if (is_prime(*num)) { + __atomic_fetch_add(&prime_numbers_count, 1, __ATOMIC_SEQ_CST); + } + return NULL; +} + +unsigned int +validate() +{ + unsigned int counter = 0; + for (unsigned int i = 2; i <= NUM_ITER; ++i) { + counter += is_prime(i); + } + + return counter; +} + +void +spawn_thread(pthread_t *thread, unsigned int *arg) +{ + int status_code = -1; + int timeout_us = RETRY_SLEEP_TIME_US; + for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) { + status_code = pthread_create(thread, NULL, &check_if_prime, arg); + assert(status_code == 0 || status_code == EAGAIN); + if (status_code == EAGAIN) { + usleep(timeout_us); + timeout_us *= 2; + } + } + + assert(status_code == 0 && "Thread creation should succeed"); +} + +int +main(int argc, char **argv) +{ + pthread_t threads[MAX_NUM_THREADS]; + unsigned int args[MAX_NUM_THREADS]; + double percentage = 0.1; + + for (unsigned int factorised_number = 2; factorised_number < NUM_ITER; + ++factorised_number) { + if (factorised_number > NUM_ITER * percentage) { + fprintf(stderr, "Stress test is %d%% finished\n", + (unsigned int)(percentage * 100)); + percentage += 0.1; + } + + unsigned int thread_num = factorised_number % MAX_NUM_THREADS; + if (threads[thread_num] != 0) { + assert(pthread_join(threads[thread_num], NULL) == 0); + } + + args[thread_num] = factorised_number; + + usleep(RETRY_SLEEP_TIME_US); + spawn_thread(&threads[thread_num], &args[thread_num]); + assert(threads[thread_num] != 0); + } + + for (int i = 0; i < MAX_NUM_THREADS; ++i) { + assert(threads[i] == 0 || pthread_join(threads[i], NULL) == 0); + } + + // Check the test results + assert( + prime_numbers_count == validate() + && "Answer mismatch between tested code and reference implementation"); + + fprintf(stderr, "Stress test finished successfully\n"); + return 0; +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c new file mode 100644 index 000000000..f991fa7ab --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include + +enum CONSTANTS { + NUM_ITER = 200000, + NUM_RETRY = 8, + MAX_NUM_THREADS = 12, + RETRY_SLEEP_TIME_US = 4000, + SECOND = 1000 * 1000 * 1000 +}; + +int threads_executed = 0; +unsigned int threads_creation_tried = 0; +unsigned int threads_in_use = 0; + +void * +thread_func(void *arg) +{ + (void)(arg); + __atomic_fetch_add(&threads_executed, 1, __ATOMIC_RELAXED); + __atomic_fetch_sub(&threads_in_use, 1, __ATOMIC_SEQ_CST); + return NULL; +} + +void +spawn_thread(pthread_t *thread) +{ + int status_code = -1; + int timeout_us = RETRY_SLEEP_TIME_US; + for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) { + status_code = pthread_create(thread, NULL, &thread_func, NULL); + __atomic_fetch_add(&threads_creation_tried, 1, __ATOMIC_RELAXED); + + assert(status_code == 0 || status_code == EAGAIN); + if (status_code == EAGAIN) { + usleep(timeout_us); + timeout_us *= 2; + } + } + + assert(status_code == 0 && "Thread creation should succeed"); +} + +int +main(int argc, char **argv) +{ + double percentage = 0.1; + + for (int iter = 0; iter < NUM_ITER; ++iter) { + if (iter > NUM_ITER * percentage) { + fprintf(stderr, "Spawning stress test is %d%% finished\n", + (unsigned int)(percentage * 100)); + percentage += 0.1; + } + while (__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) + == MAX_NUM_THREADS) { + usleep(100); + } + + __atomic_fetch_add(&threads_in_use, 1, __ATOMIC_SEQ_CST); + pthread_t tmp; + spawn_thread(&tmp); + pthread_detach(tmp); + } + + while ((__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) != 0)) { + // Casting to int* to supress compiler warning + __builtin_wasm_memory_atomic_wait32((int *)(&threads_in_use), 0, + SECOND); + } + + assert(__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) == 0); + + // Validation + assert(threads_creation_tried >= threads_executed + && "Test executed more threads than were created"); + assert((1. * threads_creation_tried) / threads_executed < 2.5 + && "Ensuring that we're retrying thread creation less than 2.5 " + "times on average "); + + fprintf(stderr, + "Spawning stress test finished successfully executed %d threads " + "with retry ratio %f\n", + threads_creation_tried, + (1. * threads_creation_tried) / threads_executed); + return 0; +} diff --git a/core/iwasm/libraries/lib-wasi-threads/test/build.sh b/core/iwasm/libraries/lib-wasi-threads/test/build.sh index 32586c20c..608dd2260 100755 --- a/core/iwasm/libraries/lib-wasi-threads/test/build.sh +++ b/core/iwasm/libraries/lib-wasi-threads/test/build.sh @@ -9,18 +9,57 @@ set -eo pipefail CC=${CC:=/opt/wasi-sdk/bin/clang} WAMR_DIR=../../../../.. +show_usage() { + echo "Usage: $0 [--sysroot PATH_TO_SYSROOT]" + echo "--sysroot PATH_TO_SYSROOT specify to build with custom sysroot for wasi-libc" +} + +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + --sysroot) + sysroot_path="$2" + shift + shift + ;; + --help) + show_usage + exit + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +# Stress tests names +thread_start_file_exclusions=("linear_memory_size_update.wasm") + +rm -rf *.wasm +rm -rf *.aot + for test_c in *.c; do test_wasm="$(basename $test_c .c).wasm" - if [ $test_wasm = "linear_memory_size_update.wasm" ]; then + if [[ " ${thread_start_file_exclusions[@]} " =~ " ${test_wasm} " ]] ; then thread_start_file="" else thread_start_file=$WAMR_DIR/samples/wasi-threads/wasm-apps/wasi_thread_start.S fi + if [[ -n "$sysroot_path" ]]; then + if [ ! -d "$sysroot_path" ]; then + echo "Directory $sysroot_path doesn't exist. Aborting" + exit 1 + fi + sysroot_command="--sysroot $sysroot_path" + fi + echo "Compiling $test_c to $test_wasm" $CC \ -target wasm32-wasi-threads \ + -O2 \ -pthread -ftls-model=local-exec \ -z stack-size=32768 \ -Wl,--export=__heap_base \ @@ -30,6 +69,7 @@ for test_c in *.c; do -Wl,--export=malloc \ -Wl,--export=free \ -I $WAMR_DIR/samples/wasi-threads/wasm-apps \ + $sysroot_command \ $thread_start_file \ $test_c -o $test_wasm done \ No newline at end of file diff --git a/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c b/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c index 23ba5f627..94ffa0f67 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c @@ -65,7 +65,7 @@ main(int argc, char **argv) assert(start_args_init(&data[i].base)); thread_ids[i] = __wasi_thread_spawn(&data[i]); printf("Thread created with id=%d\n", thread_ids[i]); - assert(thread_ids[i] > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_ids[i]); for (int j = 0; j < i; j++) { assert(thread_ids[i] != thread_ids[j] && "Duplicated TIDs"); diff --git a/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c b/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c index a38e75364..7e1e8e081 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c @@ -49,7 +49,7 @@ main(int argc, char **argv) for (int i = 0; i < NUM_THREADS; i++) { assert(start_args_init(&data[i].base)); thread_ids[i] = __wasi_thread_spawn(&data[i]); - assert(thread_ids[i] > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_ids[i]); } printf("Wait for threads to finish\n"); diff --git a/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c b/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c index f81fca49b..fb33802fc 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c @@ -61,7 +61,7 @@ main(int argc, char **argv) for (int i = 0; i < NUM_THREADS; i++) { assert(start_args_init(&data[i].base)); thread_ids[i] = __wasi_thread_spawn(&data[i]); - assert(thread_ids[i] > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_ids[i]); } printf("Wait for threads to finish\n"); diff --git a/core/iwasm/libraries/lib-wasi-threads/test/manifest.json b/core/iwasm/libraries/lib-wasi-threads/test/manifest.json new file mode 100644 index 000000000..cd2cc7636 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/test/manifest.json @@ -0,0 +1,3 @@ +{ + "name": "lib-wasi-threads tests" +} diff --git a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c index 69e125d40..5cf61338f 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c @@ -38,7 +38,7 @@ main(int argc, char **argv) assert(start_args_init(&data.base)); int thread_id = __wasi_thread_spawn(&data); - assert(thread_id > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_id); return EXIT_SUCCESS; } diff --git a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json deleted file mode 100644 index 9dc1e30d2..000000000 --- a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "exit_code": 1 -} diff --git a/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c b/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c index b7fb9afba..d6e34539b 100644 --- a/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c +++ b/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c @@ -69,7 +69,7 @@ main(int argc, char **argv) data[i].iteration = i; thread_ids[i] = __wasi_thread_spawn(&data[i]); - assert(thread_ids[i] > 0 && "Thread creation failed"); + ASSERT_VALID_TID(thread_ids[i]); } printf("Wait for threads to finish\n"); diff --git a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c index 4d53da0c9..dc2d4f1bc 100644 --- a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c +++ b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c @@ -21,7 +21,8 @@ tid_allocator_init(TidAllocator *tid_allocator) return false; for (int64 i = tid_allocator->pos - 1; i >= 0; i--) - tid_allocator->ids[i] = TID_MIN + (tid_allocator->pos - 1 - i); + tid_allocator->ids[i] = + (uint32)(TID_MIN + (tid_allocator->pos - 1 - i)); return true; } @@ -54,7 +55,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator) LOG_ERROR("Overflow detected during realloc"); return -1; } - int32 *tmp = wasm_runtime_realloc(tid_allocator->ids, realloc_size); + int32 *tmp = + wasm_runtime_realloc(tid_allocator->ids, (uint32)realloc_size); if (tmp == NULL) { LOG_ERROR("Thread ID allocator realloc failed"); return -1; @@ -64,7 +66,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator) tid_allocator->pos = new_size - old_size; tid_allocator->ids = tmp; for (int64 i = tid_allocator->pos - 1; i >= 0; i--) - tid_allocator->ids[i] = TID_MIN + (tid_allocator->size - 1 - i); + tid_allocator->ids[i] = + (uint32)(TID_MIN + (tid_allocator->size - 1 - i)); } // Pop available thread identifier from the stack @@ -77,4 +80,4 @@ tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id) // Release thread identifier by pushing it into the stack bh_assert(tid_allocator->pos < tid_allocator->size); tid_allocator->ids[tid_allocator->pos++] = thread_id; -} \ No newline at end of file +} diff --git a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h index 53af1719f..6e25f7749 100644 --- a/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h +++ b/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h @@ -8,8 +8,14 @@ #include "platform_common.h" +#ifdef __cplusplus +extern "C" { +#endif + #define TID_ALLOCATOR_INIT_SIZE CLUSTER_MAX_THREAD_NUM enum { + /* Keep it in sync with + https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids */ TID_MIN = 1, TID_MAX = 0x1FFFFFFF }; // Reserved TIDs (WASI specification) @@ -33,4 +39,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator); void tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id); +#ifdef __cplusplus +} +#endif + #endif /* _TID_ALLOCATOR_H */ \ No newline at end of file diff --git a/core/iwasm/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake b/core/iwasm/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake new file mode 100644 index 000000000..75d8f4e0e --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake @@ -0,0 +1,6 @@ +# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +create_wamr_unit_test(wasi_threads + ${CMAKE_CURRENT_LIST_DIR}/test_tid_allocator.cpp +) diff --git a/core/iwasm/libraries/lib-wasi-threads/unit-test/test_tid_allocator.cpp b/core/iwasm/libraries/lib-wasi-threads/unit-test/test_tid_allocator.cpp new file mode 100644 index 000000000..6fa7300f6 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/unit-test/test_tid_allocator.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "tid_allocator.h" + +#include + +class TidAllocatorTest : public ::testing::Test +{ + protected: + void SetUp() override { ASSERT_TRUE(tid_allocator_init(&_allocator)); } + + void TearDown() override { tid_allocator_deinit(&_allocator); } + + TidAllocator _allocator; +}; + +static bool +is_tid_valid(int32 tid) +{ + /* See: https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids + */ + return tid >= TID_MIN && tid <= TID_MAX; +} + +TEST_F(TidAllocatorTest, BasicTest) +{ + int32 tid = tid_allocator_get_tid(&_allocator); + + ASSERT_TRUE(is_tid_valid(tid)); +} + +TEST_F(TidAllocatorTest, ShouldFailOnAllocatingMoreThanAllowedThreadIDs) +{ + int32 last_tid = 0; + for (int32 i = 0; i < TID_MAX + 1; i++) { + last_tid = tid_allocator_get_tid(&_allocator); + if (last_tid < 0) { + break; + } + ASSERT_TRUE(is_tid_valid(last_tid)); + } + + ASSERT_LT(last_tid, 0); +} + +TEST_F(TidAllocatorTest, ShouldAllocateMoreThanAllowedTIDsIfOldTIDsAreReleased) +{ + int32 last_tid = 0; + for (int32 i = 0; i < TID_MAX + 1; i++) { + if (last_tid != 0) { + tid_allocator_release_tid(&_allocator, last_tid); + } + + last_tid = tid_allocator_get_tid(&_allocator); + ASSERT_TRUE(is_tid_valid(last_tid)); + } +} diff --git a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake index 6614df503..7a3bfbdce 100644 --- a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake +++ b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake @@ -3,7 +3,7 @@ set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR}) -set (LIBUV_VERSION v1.44.2) +set (LIBUV_VERSION v1.46.0) add_definitions (-DWASM_ENABLE_LIBC_WASI=1 -DWASM_ENABLE_UVWASI=1) diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 70ac4dc54..292bd8379 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -335,7 +335,7 @@ wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd) if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_close(curfds, prestats, fd); + return wasmtime_ssp_fd_close(exec_env, curfds, prestats, fd); } static wasi_errno_t @@ -348,7 +348,7 @@ wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd) if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_datasync(curfds, fd); + return wasmtime_ssp_fd_datasync(exec_env, curfds, fd); } static wasi_errno_t @@ -389,8 +389,8 @@ wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, iovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_pread(curfds, fd, iovec_begin, iovs_len, offset, - &nread); + err = wasmtime_ssp_fd_pread(exec_env, curfds, fd, iovec_begin, iovs_len, + offset, &nread); if (err) goto fail; @@ -443,8 +443,8 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, ciovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_pwrite(curfds, fd, ciovec_begin, iovs_len, offset, - &nwritten); + err = wasmtime_ssp_fd_pwrite(exec_env, curfds, fd, ciovec_begin, iovs_len, + offset, &nwritten); if (err) goto fail; @@ -496,7 +496,8 @@ wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_read(curfds, fd, iovec_begin, iovs_len, &nread); + err = wasmtime_ssp_fd_read(exec_env, curfds, fd, iovec_begin, iovs_len, + &nread); if (err) goto fail; @@ -521,7 +522,7 @@ wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to) if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_renumber(curfds, prestats, from, to); + return wasmtime_ssp_fd_renumber(exec_env, curfds, prestats, from, to); } static wasi_errno_t @@ -538,7 +539,8 @@ wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset, if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_seek(curfds, fd, offset, whence, newoffset); + return wasmtime_ssp_fd_seek(exec_env, curfds, fd, offset, whence, + newoffset); } static wasi_errno_t @@ -554,7 +556,7 @@ wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset) if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_tell(curfds, fd, newoffset); + return wasmtime_ssp_fd_tell(exec_env, curfds, fd, newoffset); } static wasi_errno_t @@ -573,7 +575,7 @@ wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_fd_fdstat_get(curfds, fd, &fdstat); + err = wasmtime_ssp_fd_fdstat_get(exec_env, curfds, fd, &fdstat); if (err) return err; @@ -592,7 +594,7 @@ wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_fdstat_set_flags(curfds, fd, flags); + return wasmtime_ssp_fd_fdstat_set_flags(exec_env, curfds, fd, flags); } static wasi_errno_t @@ -607,8 +609,8 @@ wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_fdstat_set_rights(curfds, fd, fs_rights_base, - fs_rights_inheriting); + return wasmtime_ssp_fd_fdstat_set_rights( + exec_env, curfds, fd, fs_rights_base, fs_rights_inheriting); } static wasi_errno_t @@ -621,7 +623,7 @@ wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd) if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_sync(curfds, fd); + return wasmtime_ssp_fd_sync(exec_env, curfds, fd); } static wasi_errno_t @@ -663,7 +665,8 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, ciovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_write(curfds, fd, ciovec_begin, iovs_len, &nwritten); + err = wasmtime_ssp_fd_write(exec_env, curfds, fd, ciovec_begin, iovs_len, + &nwritten); if (err) goto fail; @@ -688,7 +691,7 @@ wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_advise(curfds, fd, offset, len, advice); + return wasmtime_ssp_fd_advise(exec_env, curfds, fd, offset, len, advice); } static wasi_errno_t @@ -702,7 +705,7 @@ wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_allocate(curfds, fd, offset, len); + return wasmtime_ssp_fd_allocate(exec_env, curfds, fd, offset, len); } static wasi_errno_t @@ -716,7 +719,8 @@ wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_create_directory(curfds, fd, path, path_len); + return wasmtime_ssp_path_create_directory(exec_env, curfds, fd, path, + path_len); } static wasi_errno_t @@ -733,8 +737,9 @@ wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_link(curfds, prestats, old_fd, old_flags, old_path, - old_path_len, new_fd, new_path, new_path_len); + return wasmtime_ssp_path_link(exec_env, curfds, prestats, old_fd, old_flags, + old_path, old_path_len, new_fd, new_path, + new_path_len); } static wasi_errno_t @@ -756,9 +761,9 @@ wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, if (!validate_native_addr(fd_app, sizeof(wasi_fd_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_path_open(curfds, dirfd, dirflags, path, path_len, - oflags, fs_rights_base, fs_rights_inheriting, - fs_flags, &fd); + err = wasmtime_ssp_path_open(exec_env, curfds, dirfd, dirflags, path, + path_len, oflags, fs_rights_base, + fs_rights_inheriting, fs_flags, &fd); *fd_app = fd; return err; @@ -780,7 +785,8 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf, if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = wasmtime_ssp_fd_readdir(curfds, fd, buf, buf_len, cookie, &bufused); + err = wasmtime_ssp_fd_readdir(exec_env, curfds, fd, buf, buf_len, cookie, + &bufused); if (err) return err; @@ -805,8 +811,8 @@ wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = wasmtime_ssp_path_readlink(curfds, fd, path, path_len, buf, buf_len, - &bufused); + err = wasmtime_ssp_path_readlink(exec_env, curfds, fd, path, path_len, buf, + buf_len, &bufused); if (err) return err; @@ -826,8 +832,9 @@ wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_rename(curfds, old_fd, old_path, old_path_len, - new_fd, new_path, new_path_len); + return wasmtime_ssp_path_rename(exec_env, curfds, old_fd, old_path, + old_path_len, new_fd, new_path, + new_path_len); } static wasi_errno_t @@ -844,7 +851,7 @@ wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_filestat_get(curfds, fd, filestat); + return wasmtime_ssp_fd_filestat_get(exec_env, curfds, fd, filestat); } static wasi_errno_t @@ -859,8 +866,8 @@ wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_filestat_set_times(curfds, fd, st_atim, st_mtim, - fstflags); + return wasmtime_ssp_fd_filestat_set_times(exec_env, curfds, fd, st_atim, + st_mtim, fstflags); } static wasi_errno_t @@ -874,7 +881,7 @@ wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_filestat_set_size(curfds, fd, st_size); + return wasmtime_ssp_fd_filestat_set_size(exec_env, curfds, fd, st_size); } static wasi_errno_t @@ -892,8 +899,8 @@ wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_path_filestat_get(curfds, fd, flags, path, path_len, - filestat); + return wasmtime_ssp_path_filestat_get(exec_env, curfds, fd, flags, path, + path_len, filestat); } static wasi_errno_t @@ -909,8 +916,9 @@ wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_filestat_set_times( - curfds, fd, flags, path, path_len, st_atim, st_mtim, fstflags); + return wasmtime_ssp_path_filestat_set_times(exec_env, curfds, fd, flags, + path, path_len, st_atim, + st_mtim, fstflags); } static wasi_errno_t @@ -926,8 +934,8 @@ wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_symlink(curfds, prestats, old_path, old_path_len, - fd, new_path, new_path_len); + return wasmtime_ssp_path_symlink(exec_env, curfds, prestats, old_path, + old_path_len, fd, new_path, new_path_len); } static wasi_errno_t @@ -941,7 +949,7 @@ wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_unlink_file(curfds, fd, path, path_len); + return wasmtime_ssp_path_unlink_file(exec_env, curfds, fd, path, path_len); } static wasi_errno_t @@ -955,7 +963,8 @@ wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len); + return wasmtime_ssp_path_remove_directory(exec_env, curfds, fd, path, + path_len); } #if WASM_ENABLE_THREAD_MGR != 0 @@ -1026,8 +1035,8 @@ execute_interruptible_poll_oneoff( /* update timeout for clock subscription events */ update_clock_subscription_data( in_copy, nsubscriptions, min_uint64(time_quant, timeout - elapsed)); - err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions, - nevents); + err = wasmtime_ssp_poll_oneoff(exec_env, curfds, in_copy, out, + nsubscriptions, nevents); elapsed += time_quant; if (err) { @@ -1079,7 +1088,8 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, return (wasi_errno_t)-1; #if WASM_ENABLE_THREAD_MGR == 0 - err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents); + err = wasmtime_ssp_poll_oneoff(exec_env, curfds, in, out, nsubscriptions, + &nevents); #else err = execute_interruptible_poll_oneoff(curfds, in, out, nsubscriptions, &nevents, exec_env); @@ -1133,7 +1143,7 @@ wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fdflags_t flags, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_accept(curfds, fd, flags, fd_new); + return wasi_ssp_sock_accept(exec_env, curfds, fd, flags, fd_new); } static wasi_errno_t @@ -1152,7 +1162,7 @@ wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_addr_local(curfds, fd, addr); + return wasi_ssp_sock_addr_local(exec_env, curfds, fd, addr); } static wasi_errno_t @@ -1171,7 +1181,7 @@ wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_addr_remote(curfds, fd, addr); + return wasi_ssp_sock_addr_remote(exec_env, curfds, fd, addr); } static wasi_errno_t @@ -1192,8 +1202,8 @@ wasi_sock_addr_resolve(wasm_exec_env_t exec_env, const char *host, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); ns_lookup_list = wasi_ctx_get_ns_lookup_list(wasi_ctx); - return wasi_ssp_sock_addr_resolve(curfds, ns_lookup_list, host, service, - hints, addr_info, addr_info_size, + return wasi_ssp_sock_addr_resolve(exec_env, curfds, ns_lookup_list, host, + service, hints, addr_info, addr_info_size, max_info_size); } @@ -1211,7 +1221,7 @@ wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); - return wasi_ssp_sock_bind(curfds, addr_pool, fd, addr); + return wasi_ssp_sock_bind(exec_env, curfds, addr_pool, fd, addr); } static wasi_errno_t @@ -1234,7 +1244,7 @@ wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); - return wasi_ssp_sock_connect(curfds, addr_pool, fd, addr); + return wasi_ssp_sock_connect(exec_env, curfds, addr_pool, fd, addr); } static wasi_errno_t @@ -1253,7 +1263,7 @@ wasi_sock_get_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_broadcast(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_broadcast(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1272,7 +1282,7 @@ wasi_sock_get_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_keep_alive(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_keep_alive(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1292,7 +1302,8 @@ wasi_sock_get_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool *is_enabled, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_linger(curfds, fd, is_enabled, linger_s); + return wasmtime_ssp_sock_get_linger(exec_env, curfds, fd, is_enabled, + linger_s); } static wasi_errno_t @@ -1311,7 +1322,7 @@ wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_recv_buf_size(curfds, fd, size); + return wasmtime_ssp_sock_get_recv_buf_size(exec_env, curfds, fd, size); } static wasi_errno_t @@ -1330,7 +1341,7 @@ wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_recv_timeout(curfds, fd, timeout_us); + return wasmtime_ssp_sock_get_recv_timeout(exec_env, curfds, fd, timeout_us); } static wasi_errno_t @@ -1349,7 +1360,7 @@ wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_reuse_addr(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_reuse_addr(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1368,7 +1379,7 @@ wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_reuse_port(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_reuse_port(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1387,7 +1398,7 @@ wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_send_buf_size(curfds, fd, size); + return wasmtime_ssp_sock_get_send_buf_size(exec_env, curfds, fd, size); } static wasi_errno_t @@ -1406,7 +1417,7 @@ wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_send_timeout(curfds, fd, timeout_us); + return wasmtime_ssp_sock_get_send_timeout(exec_env, curfds, fd, timeout_us); } static wasi_errno_t @@ -1425,7 +1436,8 @@ wasi_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_fastopen_connect(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_tcp_fastopen_connect(exec_env, curfds, fd, + is_enabled); } static wasi_errno_t @@ -1444,7 +1456,7 @@ wasi_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_no_delay(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_tcp_no_delay(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1463,7 +1475,8 @@ wasi_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_quick_ack(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_tcp_quick_ack(exec_env, curfds, fd, + is_enabled); } static wasi_errno_t @@ -1482,7 +1495,7 @@ wasi_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_keep_idle(curfds, fd, time_s); + return wasmtime_ssp_sock_get_tcp_keep_idle(exec_env, curfds, fd, time_s); } static wasi_errno_t @@ -1501,7 +1514,7 @@ wasi_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_tcp_keep_intvl(curfds, fd, time_s); + return wasmtime_ssp_sock_get_tcp_keep_intvl(exec_env, curfds, fd, time_s); } static wasi_errno_t @@ -1520,7 +1533,7 @@ wasi_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_ip_multicast_loop(curfds, fd, ipv6, + return wasmtime_ssp_sock_get_ip_multicast_loop(exec_env, curfds, fd, ipv6, is_enabled); } @@ -1539,7 +1552,7 @@ wasi_sock_get_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t *ttl_s) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_ip_ttl(curfds, fd, ttl_s); + return wasmtime_ssp_sock_get_ip_ttl(exec_env, curfds, fd, ttl_s); } static wasi_errno_t @@ -1558,7 +1571,7 @@ wasi_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_ip_multicast_ttl(curfds, fd, ttl_s); + return wasmtime_ssp_sock_get_ip_multicast_ttl(exec_env, curfds, fd, ttl_s); } static wasi_errno_t @@ -1577,7 +1590,7 @@ wasi_sock_get_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_get_ipv6_only(curfds, fd, is_enabled); + return wasmtime_ssp_sock_get_ipv6_only(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1592,7 +1605,7 @@ wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_listen(curfds, fd, backlog); + return wasi_ssp_sock_listen(exec_env, curfds, fd, backlog); } static wasi_errno_t @@ -1609,7 +1622,7 @@ wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasi_ssp_sock_open(curfds, poolfd, af, socktype, sockfd); + return wasi_ssp_sock_open(exec_env, curfds, poolfd, af, socktype, sockfd); } static wasi_errno_t @@ -1624,7 +1637,7 @@ wasi_sock_set_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_broadcast(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_broadcast(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1640,7 +1653,7 @@ wasi_sock_set_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_keep_alive(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_keep_alive(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1656,7 +1669,8 @@ wasi_sock_set_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_linger(curfds, fd, is_enabled, linger_s); + return wasmtime_ssp_sock_set_linger(exec_env, curfds, fd, is_enabled, + linger_s); } static wasi_errno_t @@ -1671,7 +1685,7 @@ wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_recv_buf_size(curfds, fd, size); + return wasmtime_ssp_sock_set_recv_buf_size(exec_env, curfds, fd, size); } static wasi_errno_t @@ -1687,7 +1701,7 @@ wasi_sock_set_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_recv_timeout(curfds, fd, timeout_us); + return wasmtime_ssp_sock_set_recv_timeout(exec_env, curfds, fd, timeout_us); } static wasi_errno_t @@ -1703,7 +1717,7 @@ wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_reuse_addr(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_reuse_addr(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1719,7 +1733,7 @@ wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_reuse_port(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_reuse_port(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1734,7 +1748,7 @@ wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_send_buf_size(curfds, fd, size); + return wasmtime_ssp_sock_set_send_buf_size(exec_env, curfds, fd, size); } static wasi_errno_t @@ -1750,7 +1764,7 @@ wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_send_timeout(curfds, fd, timeout_us); + return wasmtime_ssp_sock_set_send_timeout(exec_env, curfds, fd, timeout_us); } static wasi_errno_t @@ -1766,7 +1780,8 @@ wasi_sock_set_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_fastopen_connect(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_tcp_fastopen_connect(exec_env, curfds, fd, + is_enabled); } static wasi_errno_t @@ -1782,7 +1797,7 @@ wasi_sock_set_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_no_delay(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_tcp_no_delay(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -1798,7 +1813,8 @@ wasi_sock_set_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_quick_ack(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_tcp_quick_ack(exec_env, curfds, fd, + is_enabled); } static wasi_errno_t @@ -1814,7 +1830,7 @@ wasi_sock_set_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_keep_idle(curfds, fd, time_s); + return wasmtime_ssp_sock_set_tcp_keep_idle(exec_env, curfds, fd, time_s); } static wasi_errno_t @@ -1830,7 +1846,7 @@ wasi_sock_set_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_tcp_keep_intvl(curfds, fd, time_s); + return wasmtime_ssp_sock_set_tcp_keep_intvl(exec_env, curfds, fd, time_s); } static wasi_errno_t @@ -1846,7 +1862,7 @@ wasi_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_multicast_loop(curfds, fd, ipv6, + return wasmtime_ssp_sock_set_ip_multicast_loop(exec_env, curfds, fd, ipv6, is_enabled); } @@ -1867,8 +1883,8 @@ wasi_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_add_membership(curfds, fd, imr_multiaddr, - imr_interface); + return wasmtime_ssp_sock_set_ip_add_membership( + exec_env, curfds, fd, imr_multiaddr, imr_interface); } static wasi_errno_t @@ -1888,8 +1904,8 @@ wasi_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_drop_membership(curfds, fd, imr_multiaddr, - imr_interface); + return wasmtime_ssp_sock_set_ip_drop_membership( + exec_env, curfds, fd, imr_multiaddr, imr_interface); } static wasi_errno_t @@ -1904,7 +1920,7 @@ wasi_sock_set_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t ttl_s) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_ttl(curfds, fd, ttl_s); + return wasmtime_ssp_sock_set_ip_ttl(exec_env, curfds, fd, ttl_s); } static wasi_errno_t @@ -1920,7 +1936,7 @@ wasi_sock_set_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ip_multicast_ttl(curfds, fd, ttl_s); + return wasmtime_ssp_sock_set_ip_multicast_ttl(exec_env, curfds, fd, ttl_s); } static wasi_errno_t @@ -1935,7 +1951,7 @@ wasi_sock_set_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - return wasmtime_ssp_sock_set_ipv6_only(curfds, fd, is_enabled); + return wasmtime_ssp_sock_set_ipv6_only(exec_env, curfds, fd, is_enabled); } static wasi_errno_t @@ -2053,8 +2069,9 @@ wasi_sock_recv_from(wasm_exec_env_t exec_env, wasi_fd_t sock, memset(buf_begin, 0, total_size); *ro_data_len = 0; - err = wasmtime_ssp_sock_recv_from(curfds, sock, buf_begin, total_size, - ri_flags, src_addr, &recv_bytes); + err = wasmtime_ssp_sock_recv_from(exec_env, curfds, sock, buf_begin, + total_size, ri_flags, src_addr, + &recv_bytes); if (err != __WASI_ESUCCESS) { goto fail; } @@ -2153,7 +2170,8 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, return err; *so_data_len = 0; - err = wasmtime_ssp_sock_send(curfds, sock, buf, buf_size, &send_bytes); + err = wasmtime_ssp_sock_send(exec_env, curfds, sock, buf, buf_size, + &send_bytes); *so_data_len = (uint32)send_bytes; wasm_runtime_free(buf); @@ -2193,8 +2211,8 @@ wasi_sock_send_to(wasm_exec_env_t exec_env, wasi_fd_t sock, return err; *so_data_len = 0; - err = wasmtime_ssp_sock_send_to(curfds, addr_pool, sock, buf, buf_size, - si_flags, dest_addr, &send_bytes); + err = wasmtime_ssp_sock_send_to(exec_env, curfds, addr_pool, sock, buf, + buf_size, si_flags, dest_addr, &send_bytes); *so_data_len = (uint32)send_bytes; wasm_runtime_free(buf); @@ -2212,7 +2230,7 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how) if (!wasi_ctx) return __WASI_EINVAL; - return wasmtime_ssp_sock_shutdown(curfds, sock); + return wasmtime_ssp_sock_shutdown(exec_env, curfds, sock); } static wasi_errno_t diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index feadf2f95..efe7c8e3a 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -22,6 +22,8 @@ #include #include +#include "wasm_export.h" + /* clang-format off */ #ifdef __cplusplus @@ -264,37 +266,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) @@ -552,6 +523,8 @@ _Static_assert(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset" /* keep syncing with wasi_socket_ext.h */ typedef enum { + /* Used only for sock_addr_resolve hints */ + SOCKET_ANY = -1, SOCKET_DGRAM = 0, SOCKET_STREAM, } __wasi_sock_type_t; @@ -605,7 +578,7 @@ typedef struct __wasi_addr_t { } addr; } __wasi_addr_t; -typedef enum { INET4 = 0, INET6 } __wasi_address_family_t; +typedef enum { INET4 = 0, INET6, INET_UNSPEC } __wasi_address_family_t; typedef struct __wasi_addr_info_t { __wasi_addr_t addr; @@ -627,17 +600,13 @@ typedef struct __wasi_addr_info_hints_t { #endif __wasi_errno_t wasmtime_ssp_args_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct argv_environ_values *arg_environ, -#endif char **argv, char *argv_buf ) WASMTIME_SSP_SYSCALL_NAME(args_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_args_sizes_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct argv_environ_values *arg_environ, -#endif size_t *argc, size_t *argv_buf_size ) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) __attribute__((__warn_unused_result__)); @@ -654,57 +623,46 @@ __wasi_errno_t wasmtime_ssp_clock_time_get( ) WASMTIME_SSP_SYSCALL_NAME(clock_time_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_environ_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct argv_environ_values *arg_environ, -#endif char **environ, char *environ_buf ) WASMTIME_SSP_SYSCALL_NAME(environ_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_environ_sizes_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct argv_environ_values *arg_environ, -#endif size_t *environ_count, size_t *environ_buf_size ) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_prestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_prestats *prestats, -#endif __wasi_fd_t fd, __wasi_prestat_t *buf ) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_prestats *prestats, -#endif __wasi_fd_t fd, char *path, size_t path_len ) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_close( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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, @@ -713,9 +671,8 @@ __wasi_errno_t wasmtime_ssp_fd_pread( ) WASMTIME_SSP_SYSCALL_NAME(fd_pread) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_pwrite( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t fd, const __wasi_ciovec_t *iovs, size_t iovs_len, @@ -724,9 +681,8 @@ __wasi_errno_t wasmtime_ssp_fd_pwrite( ) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_read( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t fd, const __wasi_iovec_t *iovs, size_t iovs_len, @@ -734,18 +690,16 @@ __wasi_errno_t wasmtime_ssp_fd_read( ) WASMTIME_SSP_SYSCALL_NAME(fd_read) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_renumber( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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) __attribute__((__warn_unused_result__)); __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, @@ -753,49 +707,43 @@ __wasi_errno_t wasmtime_ssp_fd_seek( ) WASMTIME_SSP_SYSCALL_NAME(fd_seek) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_tell( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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, @@ -803,9 +751,8 @@ __wasi_errno_t wasmtime_ssp_fd_write( ) WASMTIME_SSP_SYSCALL_NAME(fd_write) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_advise( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len, @@ -813,28 +760,25 @@ __wasi_errno_t wasmtime_ssp_fd_advise( ) WASMTIME_SSP_SYSCALL_NAME(fd_advise) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_allocate( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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, @@ -845,9 +789,8 @@ __wasi_errno_t wasmtime_ssp_path_link( ) WASMTIME_SSP_SYSCALL_NAME(path_link) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_open( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, const char *path, @@ -860,9 +803,8 @@ __wasi_errno_t wasmtime_ssp_path_open( ) WASMTIME_SSP_SYSCALL_NAME(path_open) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_readdir( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t fd, void *buf, size_t buf_len, @@ -871,9 +813,8 @@ __wasi_errno_t wasmtime_ssp_fd_readdir( ) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_readlink( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t fd, const char *path, size_t path_len, @@ -883,9 +824,8 @@ __wasi_errno_t wasmtime_ssp_path_readlink( ) WASMTIME_SSP_SYSCALL_NAME(path_readlink) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_rename( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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, @@ -895,17 +835,15 @@ __wasi_errno_t wasmtime_ssp_path_rename( ) WASMTIME_SSP_SYSCALL_NAME(path_rename) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_filestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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) __attribute__((__warn_unused_result__)); __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, @@ -913,17 +851,15 @@ __wasi_errno_t wasmtime_ssp_fd_filestat_set_times( ) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_fd_filestat_set_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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) __attribute__((__warn_unused_result__)); __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, @@ -932,9 +868,8 @@ __wasi_errno_t wasmtime_ssp_path_filestat_get( ) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_filestat_set_times( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, @@ -945,10 +880,9 @@ __wasi_errno_t wasmtime_ssp_path_filestat_set_times( ) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_symlink( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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, @@ -957,47 +891,30 @@ __wasi_errno_t wasmtime_ssp_path_symlink( ) WASMTIME_SSP_SYSCALL_NAME(path_symlink) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_path_unlink_file( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); -#if 0 -/** - * We throw exception in libc-wasi wrapper function wasi_proc_exit() - * but not call this function. - */ -_Noreturn void wasmtime_ssp_proc_exit( - __wasi_exitcode_t rval -) WASMTIME_SSP_SYSCALL_NAME(proc_exit); -#endif - -__wasi_errno_t wasmtime_ssp_proc_raise( - __wasi_signal_t sig -) WASMTIME_SSP_SYSCALL_NAME(proc_raise) __attribute__((__warn_unused_result__)); - __wasi_errno_t wasmtime_ssp_random_get( void *buf, size_t buf_len @@ -1005,50 +922,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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 @@ -1056,88 +967,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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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 ) __attribute__((__warn_unused_result__)); __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, @@ -1145,9 +1045,8 @@ __wasi_errno_t wasmtime_ssp_sock_recv( ) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_recv_from( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t sock, void *buf, size_t buf_len, @@ -1157,9 +1056,8 @@ __wasi_errno_t wasmtime_ssp_sock_recv_from( ) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_send( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t sock, const void *buf, size_t buf_len, @@ -1167,9 +1065,8 @@ __wasi_errno_t wasmtime_ssp_sock_send( ) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_send_to( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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, @@ -1179,317 +1076,278 @@ __wasi_errno_t wasmtime_ssp_sock_send_to( ) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_shutdown( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + wasm_exec_env_t exec_env, struct fd_table *curfds, -#endif __wasi_fd_t sock ) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__)); __wasi_errno_t wasmtime_ssp_sock_set_recv_timeout( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) + 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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); __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) __attribute__((__warn_unused_result__)); diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c new file mode 100644 index 000000000..9d01f2bfe --- /dev/null +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "ssp_config.h" +#include "blocking_op.h" + +int +blocking_op_close(wasm_exec_env_t exec_env, int fd) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = close(fd); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +ssize_t +blocking_op_readv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = readv(fd, iov, iovcnt); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +#if CONFIG_HAS_PREADV +ssize_t +blocking_op_preadv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt, off_t offset) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = preadv(fd, iov, iovcnt, offset); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} +#else /* CONFIG_HAS_PREADV */ +ssize_t +blocking_op_pread(wasm_exec_env_t exec_env, int fd, void *p, size_t nb, + off_t offset) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = pread(fd, p, nb, offset); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} +#endif /* CONFIG_HAS_PREADV */ + +ssize_t +blocking_op_writev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = writev(fd, iov, iovcnt); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +#if CONFIG_HAS_PWRITEV +ssize_t +blocking_op_pwritev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt, off_t offset) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = pwritev(fd, iov, iovcnt, offset); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} +#else /* CONFIG_HAS_PWRITEV */ +ssize_t +blocking_op_pwrite(wasm_exec_env_t exec_env, int fd, const void *p, size_t nb, + off_t offset) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + ssize_t ret = pwrite(fd, p, nb, offset); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} +#endif /* CONFIG_HAS_PWRITEV */ + +int +blocking_op_socket_accept(wasm_exec_env_t exec_env, bh_socket_t server_sock, + bh_socket_t *sockp, void *addr, + unsigned int *addrlenp) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_accept(server_sock, sockp, addr, addrlenp); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_socket_connect(wasm_exec_env_t exec_env, bh_socket_t sock, + const char *addr, int port) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_connect(sock, addr, port); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_socket_recv_from(wasm_exec_env_t exec_env, bh_socket_t sock, + void *buf, unsigned int len, int flags, + bh_sockaddr_t *src_addr) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_recv_from(sock, buf, len, flags, src_addr); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_socket_send_to(wasm_exec_env_t exec_env, bh_socket_t sock, + const void *buf, unsigned int len, int flags, + const bh_sockaddr_t *dest_addr) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_send_to(sock, buf, len, flags, dest_addr); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_socket_addr_resolve(wasm_exec_env_t exec_env, const char *host, + const char *service, uint8_t *hint_is_tcp, + uint8_t *hint_is_ipv4, + bh_addr_info_t *addr_info, + size_t addr_info_size, size_t *max_info_size) +{ + /* + * Note: Unlike others, os_socket_addr_resolve() is not a simple system + * call. It's likely backed by a complex libc function, getaddrinfo(). + * Depending on the implementation of getaddrinfo() and underlying + * DNS resolver, it might or might not be possible to make it return + * with os_wakeup_blocking_op(). + * + * Unfortunately, many of ISC/bind based resolvers just keep going on + * interrupted system calls. It includes macOS and glibc. + * + * On the other hand, NuttX as of writing this returns EAI_AGAIN + * on EINTR. + */ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = os_socket_addr_resolve(host, service, hint_is_tcp, hint_is_ipv4, + addr_info, addr_info_size, max_info_size); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} + +int +blocking_op_openat(wasm_exec_env_t exec_env, int fd, const char *path, + int oflags, mode_t mode) +{ + if (!wasm_runtime_begin_blocking_op(exec_env)) { + errno = EINTR; + return -1; + } + int ret = openat(fd, path, oflags, mode); + wasm_runtime_end_blocking_op(exec_env); + return ret; +} diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h new file mode 100644 index 000000000..44a16d338 --- /dev/null +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "wasm_export.h" + +int +blocking_op_close(wasm_exec_env_t exec_env, int fd); +ssize_t +blocking_op_readv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt); +ssize_t +blocking_op_preadv(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt, off_t offset); +ssize_t +blocking_op_pread(wasm_exec_env_t exec_env, int fd, void *p, size_t nb, + off_t offset); +ssize_t +blocking_op_writev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt); +ssize_t +blocking_op_pwritev(wasm_exec_env_t exec_env, int fd, const struct iovec *iov, + int iovcnt, off_t offset); +ssize_t +blocking_op_pwrite(wasm_exec_env_t exec_env, int fd, const void *p, size_t nb, + off_t offset); +int +blocking_op_socket_accept(wasm_exec_env_t exec_env, bh_socket_t server_sock, + bh_socket_t *sockp, void *addr, + unsigned int *addrlenp); +int +blocking_op_socket_connect(wasm_exec_env_t exec_env, bh_socket_t sock, + const char *addr, int port); +int +blocking_op_socket_recv_from(wasm_exec_env_t exec_env, bh_socket_t sock, + void *buf, unsigned int len, int flags, + bh_sockaddr_t *src_addr); +int +blocking_op_socket_send_to(wasm_exec_env_t exec_env, bh_socket_t sock, + const void *buf, unsigned int len, int flags, + const bh_sockaddr_t *dest_addr); +int +blocking_op_socket_addr_resolve(wasm_exec_env_t exec_env, const char *host, + const char *service, uint8_t *hint_is_tcp, + uint8_t *hint_is_ipv4, + bh_addr_info_t *addr_info, + size_t addr_info_size, size_t *max_info_size); +int +blocking_op_openat(wasm_exec_env_t exec_env, int fd, const char *path, + int oflags, mode_t mode); diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 61e841836..eda65b8da 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -13,6 +13,7 @@ #include "ssp_config.h" #include "bh_platform.h" +#include "blocking_op.h" #include "wasmtime_ssp.h" #include "locking.h" #include "posix.h" @@ -55,13 +56,6 @@ static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t), "Size mismatch"); #endif -#if defined(WASMTIME_SSP_STATIC_CURFDS) -static __thread struct fd_table *curfds; -static __thread struct fd_prestats *prestats; -static __thread struct argv_environ_values *argv_environ; -static __thread struct addr_pool *addr_pool; -#endif - // Converts a POSIX error code to a CloudABI error code. static __wasi_errno_t convert_errno(int error) @@ -228,22 +222,22 @@ wasi_addr_to_bh_sockaddr(const __wasi_addr_t *wasi_addr, bh_sockaddr_t *sockaddr) { if (wasi_addr->kind == IPv4) { - sockaddr->addr_bufer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24) - | (wasi_addr->addr.ip4.addr.n1 << 16) - | (wasi_addr->addr.ip4.addr.n2 << 8) - | wasi_addr->addr.ip4.addr.n3; + sockaddr->addr_buffer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24) + | (wasi_addr->addr.ip4.addr.n1 << 16) + | (wasi_addr->addr.ip4.addr.n2 << 8) + | wasi_addr->addr.ip4.addr.n3; sockaddr->is_ipv4 = true; sockaddr->port = wasi_addr->addr.ip4.port; } else { - sockaddr->addr_bufer.ipv6[0] = wasi_addr->addr.ip6.addr.n0; - sockaddr->addr_bufer.ipv6[1] = wasi_addr->addr.ip6.addr.n1; - sockaddr->addr_bufer.ipv6[2] = wasi_addr->addr.ip6.addr.n2; - sockaddr->addr_bufer.ipv6[3] = wasi_addr->addr.ip6.addr.n3; - sockaddr->addr_bufer.ipv6[4] = wasi_addr->addr.ip6.addr.h0; - sockaddr->addr_bufer.ipv6[5] = wasi_addr->addr.ip6.addr.h1; - sockaddr->addr_bufer.ipv6[6] = wasi_addr->addr.ip6.addr.h2; - sockaddr->addr_bufer.ipv6[7] = wasi_addr->addr.ip6.addr.h3; + sockaddr->addr_buffer.ipv6[0] = wasi_addr->addr.ip6.addr.n0; + sockaddr->addr_buffer.ipv6[1] = wasi_addr->addr.ip6.addr.n1; + sockaddr->addr_buffer.ipv6[2] = wasi_addr->addr.ip6.addr.n2; + sockaddr->addr_buffer.ipv6[3] = wasi_addr->addr.ip6.addr.n3; + sockaddr->addr_buffer.ipv6[4] = wasi_addr->addr.ip6.addr.h0; + sockaddr->addr_buffer.ipv6[5] = wasi_addr->addr.ip6.addr.h1; + sockaddr->addr_buffer.ipv6[6] = wasi_addr->addr.ip6.addr.h2; + sockaddr->addr_buffer.ipv6[7] = wasi_addr->addr.ip6.addr.h3; sockaddr->is_ipv4 = false; sockaddr->port = wasi_addr->addr.ip6.port; } @@ -258,24 +252,24 @@ bh_sockaddr_to_wasi_addr(const bh_sockaddr_t *sockaddr, wasi_addr->kind = IPv4; wasi_addr->addr.ip4.port = sockaddr->port; wasi_addr->addr.ip4.addr.n0 = - (sockaddr->addr_bufer.ipv4 & 0xFF000000) >> 24; + (sockaddr->addr_buffer.ipv4 & 0xFF000000) >> 24; wasi_addr->addr.ip4.addr.n1 = - (sockaddr->addr_bufer.ipv4 & 0x00FF0000) >> 16; + (sockaddr->addr_buffer.ipv4 & 0x00FF0000) >> 16; wasi_addr->addr.ip4.addr.n2 = - (sockaddr->addr_bufer.ipv4 & 0x0000FF00) >> 8; - wasi_addr->addr.ip4.addr.n3 = (sockaddr->addr_bufer.ipv4 & 0x000000FF); + (sockaddr->addr_buffer.ipv4 & 0x0000FF00) >> 8; + wasi_addr->addr.ip4.addr.n3 = (sockaddr->addr_buffer.ipv4 & 0x000000FF); } else { wasi_addr->kind = IPv6; wasi_addr->addr.ip6.port = sockaddr->port; - wasi_addr->addr.ip6.addr.n0 = sockaddr->addr_bufer.ipv6[0]; - wasi_addr->addr.ip6.addr.n1 = sockaddr->addr_bufer.ipv6[1]; - wasi_addr->addr.ip6.addr.n2 = sockaddr->addr_bufer.ipv6[2]; - wasi_addr->addr.ip6.addr.n3 = sockaddr->addr_bufer.ipv6[3]; - wasi_addr->addr.ip6.addr.h0 = sockaddr->addr_bufer.ipv6[4]; - wasi_addr->addr.ip6.addr.h1 = sockaddr->addr_bufer.ipv6[5]; - wasi_addr->addr.ip6.addr.h2 = sockaddr->addr_bufer.ipv6[6]; - wasi_addr->addr.ip6.addr.h3 = sockaddr->addr_bufer.ipv6[7]; + wasi_addr->addr.ip6.addr.n0 = sockaddr->addr_buffer.ipv6[0]; + wasi_addr->addr.ip6.addr.n1 = sockaddr->addr_buffer.ipv6[1]; + wasi_addr->addr.ip6.addr.n2 = sockaddr->addr_buffer.ipv6[2]; + wasi_addr->addr.ip6.addr.n3 = sockaddr->addr_buffer.ipv6[3]; + wasi_addr->addr.ip6.addr.h0 = sockaddr->addr_buffer.ipv6[4]; + wasi_addr->addr.ip6.addr.h1 = sockaddr->addr_buffer.ipv6[5]; + wasi_addr->addr.ip6.addr.h2 = sockaddr->addr_buffer.ipv6[6]; + wasi_addr->addr.ip6.addr.h3 = sockaddr->addr_buffer.ipv6[7]; } } @@ -340,15 +334,12 @@ fd_prestats_init(struct fd_prestats *pt) pt->prestats = NULL; pt->size = 0; pt->used = 0; -#if defined(WASMTIME_SSP_STATIC_CURFDS) - prestats = pt; -#endif return true; } // Grows the preopened resource table to a required lower bound and a // minimum number of free preopened resource table entries. -static bool +static __wasi_errno_t fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr) REQUIRES_EXCLUSIVE(pt->lock) { @@ -362,7 +353,7 @@ fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr) struct fd_prestat *prestats = wasm_runtime_malloc((uint32)(sizeof(*prestats) * size)); if (prestats == NULL) - return false; + return __WASI_ENOMEM; if (pt->prestats && pt->size > 0) { bh_memcpy_s(prestats, (uint32)(sizeof(*prestats) * size), @@ -378,27 +369,39 @@ fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr) pt->prestats = prestats; pt->size = size; } - return true; + return __WASI_ESUCCESS; +} + +static __wasi_errno_t +fd_prestats_insert_locked(struct fd_prestats *pt, const char *dir, + __wasi_fd_t fd) +{ + // Grow the preopened resource table if needed. + __wasi_errno_t error = fd_prestats_grow(pt, fd, 1); + + if (error != __WASI_ESUCCESS) { + return error; + } + + pt->prestats[fd].dir = bh_strdup(dir); + + if (pt->prestats[fd].dir == NULL) + return __WASI_ENOMEM; + + return __WASI_ESUCCESS; } // Inserts a preopened resource record into the preopened resource table. bool fd_prestats_insert(struct fd_prestats *pt, const char *dir, __wasi_fd_t fd) { - // Grow the preopened resource table if needed. rwlock_wrlock(&pt->lock); - if (!fd_prestats_grow(pt, fd, 1)) { - rwlock_unlock(&pt->lock); - return false; - } - pt->prestats[fd].dir = bh_strdup(dir); + __wasi_errno_t error = fd_prestats_insert_locked(pt, dir, fd); + rwlock_unlock(&pt->lock); - if (pt->prestats[fd].dir == NULL) - return false; - - return true; + return error == __WASI_ESUCCESS; } // Looks up a preopened resource table entry by number. @@ -417,6 +420,24 @@ fd_prestats_get_entry(struct fd_prestats *pt, __wasi_fd_t fd, return 0; } +// Remove a preopened resource record from the preopened resource table by +// number +static __wasi_errno_t +fd_prestats_remove_entry(struct fd_prestats *pt, __wasi_fd_t fd) +{ + // Test for file descriptor existence. + if (fd >= pt->size) + return __WASI_EBADF; + struct fd_prestat *prestat = &pt->prestats[fd]; + + if (prestat->dir != NULL) { + wasm_runtime_free((void *)prestat->dir); + prestat->dir = NULL; + } + + return __WASI_ESUCCESS; +} + struct fd_object { struct refcount refcount; __wasi_filetype_t type; @@ -446,9 +467,6 @@ fd_table_init(struct fd_table *ft) ft->entries = NULL; ft->size = 0; ft->used = 0; -#if defined(WASMTIME_SSP_STATIC_CURFDS) - curfds = ft; -#endif return true; } @@ -643,35 +661,46 @@ fd_number(const struct fd_object *fo) return number; } -#define CLOSE_NON_STD_FD(fd) \ - do { \ - if (fd > 2) \ - close(fd); \ +// The env == NULL case is for +// fd_table_destroy, path_get, path_put, fd_table_insert_existing +#define CLOSE_NON_STD_FD(env, fd) \ + do { \ + if (fd > 2) { \ + if (env == NULL) { \ + close(fd); \ + } \ + else { \ + blocking_op_close(env, fd); \ + } \ + } \ } while (0) // Lowers the reference count on a file descriptor object. When the // reference count reaches zero, its resources are cleaned up. static void -fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) +fd_object_release(wasm_exec_env_t env, struct fd_object *fo) + UNLOCKS(fo->refcount) { if (refcount_release(&fo->refcount)) { + int saved_errno = errno; switch (fo->type) { case __WASI_FILETYPE_DIRECTORY: // For directories we may keep track of a DIR object. Calling // closedir() on it also closes the underlying file descriptor. mutex_destroy(&fo->directory.lock); if (fo->directory.handle == NULL) { - CLOSE_NON_STD_FD(fd_number(fo)); + CLOSE_NON_STD_FD(env, fd_number(fo)); } else { closedir(fo->directory.handle); } break; default: - CLOSE_NON_STD_FD(fd_number(fo)); + CLOSE_NON_STD_FD(env, fd_number(fo)); break; } wasm_runtime_free(fo); + errno = saved_errno; } } @@ -706,7 +735,7 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) fo->number = out; if (type == __WASI_FILETYPE_DIRECTORY) { if (!mutex_init(&fo->directory.lock)) { - fd_object_release(fo); + fd_object_release(NULL, fo); return false; } fo->directory.handle = NULL; @@ -716,7 +745,7 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) rwlock_wrlock(&ft->lock); if (!fd_table_grow(ft, in, 1)) { rwlock_unlock(&ft->lock); - fd_object_release(fo); + fd_object_release(NULL, fo); return false; } @@ -740,16 +769,16 @@ fd_table_unused(struct fd_table *ft) REQUIRES_SHARED(ft->lock) // Inserts a file descriptor object into an unused slot of the file // descriptor table. static __wasi_errno_t -fd_table_insert(struct fd_table *ft, struct fd_object *fo, - __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, - __wasi_fd_t *out) REQUIRES_UNLOCKED(ft->lock) - UNLOCKS(fo->refcount) +fd_table_insert(wasm_exec_env_t exec_env, struct fd_table *ft, + struct fd_object *fo, __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, __wasi_fd_t *out) + REQUIRES_UNLOCKED(ft->lock) UNLOCKS(fo->refcount) { // Grow the file descriptor table if needed. rwlock_wrlock(&ft->lock); if (!fd_table_grow(ft, 0, 1)) { rwlock_unlock(&ft->lock); - fd_object_release(fo); + fd_object_release(exec_env, fo); return convert_errno(errno); } @@ -761,8 +790,8 @@ fd_table_insert(struct fd_table *ft, struct fd_object *fo, // Inserts a numerical file descriptor into the file descriptor table. static __wasi_errno_t -fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type, - __wasi_rights_t rights_base, +fd_table_insert_fd(wasm_exec_env_t exec_env, struct fd_table *ft, int in, + __wasi_filetype_t type, __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, __wasi_fd_t *out) REQUIRES_UNLOCKED(ft->lock) { @@ -777,20 +806,18 @@ fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type, fo->number = in; if (type == __WASI_FILETYPE_DIRECTORY) { if (!mutex_init(&fo->directory.lock)) { - fd_object_release(fo); + fd_object_release(exec_env, fo); return (__wasi_errno_t)-1; } fo->directory.handle = NULL; } - return fd_table_insert(ft, fo, rights_base, rights_inheriting, out); + return fd_table_insert(exec_env, ft, fo, rights_base, rights_inheriting, + out); } __wasi_errno_t -wasmtime_ssp_fd_prestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_prestats *prestats, -#endif - __wasi_fd_t fd, __wasi_prestat_t *buf) +wasmtime_ssp_fd_prestat_get(struct fd_prestats *prestats, __wasi_fd_t fd, + __wasi_prestat_t *buf) { rwlock_rdlock(&prestats->lock); struct fd_prestat *prestat; @@ -812,11 +839,8 @@ wasmtime_ssp_fd_prestat_get( } __wasi_errno_t -wasmtime_ssp_fd_prestat_dir_name( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_prestats *prestats, -#endif - __wasi_fd_t fd, char *path, size_t path_len) +wasmtime_ssp_fd_prestat_dir_name(struct fd_prestats *prestats, __wasi_fd_t fd, + char *path, size_t path_len) { rwlock_rdlock(&prestats->lock); struct fd_prestat *prestat; @@ -825,12 +849,14 @@ wasmtime_ssp_fd_prestat_dir_name( rwlock_unlock(&prestats->lock); return error; } - if (path_len != strlen(prestat->dir)) { + + const size_t prestat_dir_len = strlen(prestat->dir); + if (path_len < prestat_dir_len) { rwlock_unlock(&prestats->lock); - return EINVAL; + return __WASI_EINVAL; } - bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)path_len); + bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)prestat_dir_len); rwlock_unlock(&prestats->lock); @@ -838,31 +864,18 @@ wasmtime_ssp_fd_prestat_dir_name( } __wasi_errno_t -wasmtime_ssp_fd_close( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct fd_prestats *prestats, -#endif - __wasi_fd_t fd) +wasmtime_ssp_fd_close(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, __wasi_fd_t fd) { - // Don't allow closing a pre-opened resource. - // TODO: Eventually, we do want to permit this, once libpreopen in - // userspace is capable of removing entries from its tables as well. - { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); - rwlock_unlock(&prestats->lock); - if (error == 0) { - return __WASI_ENOTSUP; - } - } - // Validate the file descriptor. struct fd_table *ft = curfds; rwlock_wrlock(&ft->lock); + rwlock_wrlock(&prestats->lock); + struct fd_entry *fe; __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); if (error != 0) { + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); return error; } @@ -870,9 +883,20 @@ wasmtime_ssp_fd_close( // Remove it from the file descriptor table. struct fd_object *fo; fd_table_detach(ft, fd, &fo); + + // Remove it from the preopened resource table if it exists + error = fd_prestats_remove_entry(prestats, fd); + + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); - fd_object_release(fo); - return 0; + fd_object_release(exec_env, fo); + + // Ignore the error if there is no preopen associated with this fd + if (error == __WASI_EBADF) { + return __WASI_ESUCCESS; + } + + return error; } // Look up a file descriptor object in a locked file descriptor table @@ -914,11 +938,8 @@ fd_object_get(struct fd_table *curfds, struct fd_object **fo, __wasi_fd_t fd, } __wasi_errno_t -wasmtime_ssp_fd_datasync( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd) +wasmtime_ssp_fd_datasync(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd) { struct fd_object *fo; __wasi_errno_t error = @@ -931,19 +952,16 @@ wasmtime_ssp_fd_datasync( #else int ret = fsync(fd_number(fo)); #endif - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_fd_pread( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, - __wasi_filesize_t offset, size_t *nread) +wasmtime_ssp_fd_pread(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, + __wasi_filesize_t offset, size_t *nread) { if (iovcnt == 0) return __WASI_EINVAL; @@ -955,17 +973,19 @@ wasmtime_ssp_fd_pread( return error; #if CONFIG_HAS_PREADV - ssize_t len = preadv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, - (off_t)offset); - fd_object_release(fo); + ssize_t len = + blocking_op_preadv(exec_env, fd_number(fo), (const struct iovec *)iov, + (int)iovcnt, (off_t)offset); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nread = (size_t)len; return 0; #else if (iovcnt == 1) { - ssize_t len = pread(fd_number(fo), iov->buf, iov->buf_len, offset); - fd_object_release(fo); + ssize_t len = blocking_op_pread(exec_env, fd_number(fo), iov->buf, + iov->buf_len, offset); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nread = len; @@ -978,13 +998,14 @@ wasmtime_ssp_fd_pread( totalsize += iov[i].buf_len; char *buf = wasm_runtime_malloc(totalsize); if (buf == NULL) { - fd_object_release(fo); + fd_object_release(exec_env, fo); return __WASI_ENOMEM; } // Perform a single read operation. - ssize_t len = pread(fd_number(fo), buf, totalsize, offset); - fd_object_release(fo); + ssize_t len = + blocking_op_pread(exec_env, fd_number(fo), buf, totalsize, offset); + fd_object_release(exec_env, fo); if (len < 0) { wasm_runtime_free(buf); return convert_errno(errno); @@ -1012,12 +1033,10 @@ wasmtime_ssp_fd_pread( } __wasi_errno_t -wasmtime_ssp_fd_pwrite( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, - __wasi_filesize_t offset, size_t *nwritten) +wasmtime_ssp_fd_pwrite(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_ciovec_t *iov, + size_t iovcnt, __wasi_filesize_t offset, + size_t *nwritten) { if (iovcnt == 0) return __WASI_EINVAL; @@ -1030,11 +1049,13 @@ wasmtime_ssp_fd_pwrite( ssize_t len; #if CONFIG_HAS_PWRITEV - len = pwritev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, - (off_t)offset); + len = + blocking_op_pwritev(exec_env, fd_number(fo), (const struct iovec *)iov, + (int)iovcnt, (off_t)offset); #else if (iovcnt == 1) { - len = pwrite(fd_number(fo), iov->buf, iov->buf_len, offset); + len = blocking_op_pwrite(exec_env, fd_number(fo), iov->buf, + iov->buf_len, offset); } else { // Allocate a single buffer to fit all data. @@ -1043,7 +1064,7 @@ wasmtime_ssp_fd_pwrite( totalsize += iov[i].buf_len; char *buf = wasm_runtime_malloc(totalsize); if (buf == NULL) { - fd_object_release(fo); + fd_object_release(exec_env, fo); return __WASI_ENOMEM; } size_t bufoff = 0; @@ -1054,11 +1075,12 @@ wasmtime_ssp_fd_pwrite( } // Perform a single write operation. - len = pwrite(fd_number(fo), buf, totalsize, offset); + len = + blocking_op_pwrite(exec_env, fd_number(fo), buf, totalsize, offset); wasm_runtime_free(buf); } #endif - fd_object_release(fo); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nwritten = (size_t)len; @@ -1066,11 +1088,9 @@ wasmtime_ssp_fd_pwrite( } __wasi_errno_t -wasmtime_ssp_fd_read( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, size_t *nread) +wasmtime_ssp_fd_read(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, + size_t *nread) { struct fd_object *fo; __wasi_errno_t error = @@ -1078,8 +1098,9 @@ wasmtime_ssp_fd_read( if (error != 0) return error; - ssize_t len = readv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); - fd_object_release(fo); + ssize_t len = blocking_op_readv(exec_env, fd_number(fo), + (const struct iovec *)iov, (int)iovcnt); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nread = (size_t)len; @@ -1087,39 +1108,25 @@ wasmtime_ssp_fd_read( } __wasi_errno_t -wasmtime_ssp_fd_renumber( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct fd_prestats *prestats, -#endif - __wasi_fd_t from, __wasi_fd_t to) +wasmtime_ssp_fd_renumber(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, __wasi_fd_t from, + __wasi_fd_t to) { - // Don't allow renumbering over a pre-opened resource. - // TODO: Eventually, we do want to permit this, once libpreopen in - // userspace is capable of removing entries from its tables as well. - { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, to, &prestat); - if (error != 0) { - error = fd_prestats_get_entry(prestats, from, &prestat); - } - rwlock_unlock(&prestats->lock); - if (error == 0) { - return __WASI_ENOTSUP; - } - } - struct fd_table *ft = curfds; rwlock_wrlock(&ft->lock); + rwlock_wrlock(&prestats->lock); + struct fd_entry *fe_from; __wasi_errno_t error = fd_table_get_entry(ft, from, 0, 0, &fe_from); if (error != 0) { + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); return error; } struct fd_entry *fe_to; error = fd_table_get_entry(ft, to, 0, 0, &fe_to); if (error != 0) { + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); return error; } @@ -1129,24 +1136,66 @@ wasmtime_ssp_fd_renumber( refcount_acquire(&fe_from->object->refcount); fd_table_attach(ft, to, fe_from->object, fe_from->rights_base, fe_from->rights_inheriting); - fd_object_release(fo); + fd_object_release(exec_env, fo); // Remove the old fd from the file descriptor table. fd_table_detach(ft, from, &fo); - fd_object_release(fo); + fd_object_release(exec_env, fo); --ft->used; + // Handle renumbering of any preopened resources + struct fd_prestat *prestat_from; + __wasi_errno_t prestat_from_error = + fd_prestats_get_entry(prestats, from, &prestat_from); + + struct fd_prestat *prestat_to; + __wasi_errno_t prestat_to_error = + fd_prestats_get_entry(prestats, to, &prestat_to); + + // Renumbering over two preopened resources. + if (prestat_from_error == __WASI_ESUCCESS + && prestat_to_error == __WASI_ESUCCESS) { + (void)fd_prestats_remove_entry(prestats, to); + + error = fd_prestats_insert_locked(prestats, prestat_from->dir, to); + + if (error == __WASI_ESUCCESS) { + (void)fd_prestats_remove_entry(prestats, from); + } + else { + (void)fd_prestats_remove_entry(prestats, to); + } + } + // Renumbering from a non-preopened fd to a preopened fd. In this case, we + // can't a keep the destination fd entry in the preopened table so remove + // it entirely. + else if (prestat_from_error != __WASI_ESUCCESS + && prestat_to_error == __WASI_ESUCCESS) { + (void)fd_prestats_remove_entry(prestats, to); + } + // Renumbering from a preopened fd to a non-preopened fd + else if (prestat_from_error == __WASI_ESUCCESS + && prestat_to_error != __WASI_ESUCCESS) { + error = fd_prestats_insert_locked(prestats, prestat_from->dir, to); + + if (error == __WASI_ESUCCESS) { + (void)fd_prestats_remove_entry(prestats, from); + } + else { + (void)fd_prestats_remove_entry(prestats, to); + } + } + + rwlock_unlock(&prestats->lock); rwlock_unlock(&ft->lock); - return 0; + + return error; } __wasi_errno_t -wasmtime_ssp_fd_seek( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filedelta_t offset, __wasi_whence_t whence, - __wasi_filesize_t *newoffset) +wasmtime_ssp_fd_seek(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filedelta_t offset, + __wasi_whence_t whence, __wasi_filesize_t *newoffset) { int nwhence; switch (whence) { @@ -1174,7 +1223,7 @@ wasmtime_ssp_fd_seek( return error; off_t ret = lseek(fd_number(fo), offset, nwhence); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); *newoffset = (__wasi_filesize_t)ret; @@ -1182,11 +1231,8 @@ wasmtime_ssp_fd_seek( } __wasi_errno_t -wasmtime_ssp_fd_tell( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filesize_t *newoffset) +wasmtime_ssp_fd_tell(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filesize_t *newoffset) { struct fd_object *fo; __wasi_errno_t error = @@ -1195,7 +1241,7 @@ wasmtime_ssp_fd_tell( return error; off_t ret = lseek(fd_number(fo), 0, SEEK_CUR); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); *newoffset = (__wasi_filesize_t)ret; @@ -1203,11 +1249,8 @@ wasmtime_ssp_fd_tell( } __wasi_errno_t -wasmtime_ssp_fd_fdstat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_fdstat_t *buf) +wasmtime_ssp_fd_fdstat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_fdstat_t *buf) { struct fd_table *ft = curfds; rwlock_rdlock(&ft->lock); @@ -1255,11 +1298,9 @@ wasmtime_ssp_fd_fdstat_get( } __wasi_errno_t -wasmtime_ssp_fd_fdstat_set_flags( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_fdflags_t fs_flags) +wasmtime_ssp_fd_fdstat_set_flags(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_fdflags_t fs_flags) { int noflags = 0; if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) @@ -1288,19 +1329,17 @@ wasmtime_ssp_fd_fdstat_set_flags( return error; int ret = fcntl(fd_number(fo), F_SETFL, noflags); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_fd_fdstat_set_rights( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_rights_t fs_rights_base, - __wasi_rights_t fs_rights_inheriting) +wasmtime_ssp_fd_fdstat_set_rights(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting) { struct fd_table *ft = curfds; rwlock_wrlock(&ft->lock); @@ -1320,11 +1359,8 @@ wasmtime_ssp_fd_fdstat_set_rights( } __wasi_errno_t -wasmtime_ssp_fd_sync( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd) +wasmtime_ssp_fd_sync(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd) { struct fd_object *fo; __wasi_errno_t error = @@ -1333,18 +1369,16 @@ wasmtime_ssp_fd_sync( return error; int ret = fsync(fd_number(fo)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_fd_write( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, size_t *nwritten) +wasmtime_ssp_fd_write(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, + size_t *nwritten) { struct fd_object *fo; __wasi_errno_t error = @@ -1375,7 +1409,7 @@ wasmtime_ssp_fd_write( len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); } #endif /* end of BH_VPRINTF */ - fd_object_release(fo); + fd_object_release(exec_env, fo); if (len < 0) return convert_errno(errno); *nwritten = (size_t)len; @@ -1383,12 +1417,9 @@ wasmtime_ssp_fd_write( } __wasi_errno_t -wasmtime_ssp_fd_advise( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len, - __wasi_advice_t advice) +wasmtime_ssp_fd_advise(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filesize_t offset, + __wasi_filesize_t len, __wasi_advice_t advice) { #ifdef POSIX_FADV_NORMAL int nadvice; @@ -1422,7 +1453,7 @@ wasmtime_ssp_fd_advise( return error; int ret = posix_fadvise(fd_number(fo), (off_t)offset, (off_t)len, nadvice); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret != 0) return convert_errno(ret); return 0; @@ -1452,11 +1483,9 @@ wasmtime_ssp_fd_advise( } __wasi_errno_t -wasmtime_ssp_fd_allocate( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len) +wasmtime_ssp_fd_allocate(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filesize_t offset, + __wasi_filesize_t len) { struct fd_object *fo; __wasi_errno_t error = @@ -1477,7 +1506,7 @@ wasmtime_ssp_fd_allocate( ret = ftruncate(fd_number(fo), newsize); #endif - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret != 0) return convert_errno(ret); return 0; @@ -1632,6 +1661,9 @@ path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, // components. In other words, a pathname component that must be a // directory. First attempt to obtain a directory file descriptor // for it. + // + // Note: we don't bother to use blocking_op_openat here + // because openat with O_DIRECTORY should not block. int newdir = #ifdef O_SEARCH openat(fds[curfd], file, O_SEARCH | O_DIRECTORY | O_NOFOLLOW); @@ -1765,7 +1797,7 @@ fail: close(fds[i]); for (size_t i = 0; i <= curpath; ++i) wasm_runtime_free(paths_start[i]); - fd_object_release(fo); + fd_object_release(NULL, fo); return error; #endif } @@ -1789,15 +1821,13 @@ path_put(struct path_access *pa) UNLOCKS(pa->fd_object->refcount) wasm_runtime_free(pa->path_start); if (fd_number(pa->fd_object) != pa->fd) close(pa->fd); - fd_object_release(pa->fd_object); + fd_object_release(NULL, pa->fd_object); } __wasi_errno_t -wasmtime_ssp_path_create_directory( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const char *path, size_t pathlen) +wasmtime_ssp_path_create_directory(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + const char *path, size_t pathlen) { struct path_access pa; __wasi_errno_t error = @@ -1841,13 +1871,11 @@ validate_path(const char *path, struct fd_prestats *pt) } __wasi_errno_t -wasmtime_ssp_path_link( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct fd_prestats *prestats, -#endif - __wasi_fd_t old_fd, __wasi_lookupflags_t old_flags, const char *old_path, - size_t old_path_len, __wasi_fd_t new_fd, const char *new_path, - size_t new_path_len) +wasmtime_ssp_path_link(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, __wasi_fd_t old_fd, + __wasi_lookupflags_t old_flags, const char *old_path, + size_t old_path_len, __wasi_fd_t new_fd, + const char *new_path, size_t new_path_len) { struct path_access old_pa; __wasi_errno_t error = @@ -1900,14 +1928,12 @@ wasmtime_ssp_path_link( } __wasi_errno_t -wasmtime_ssp_path_open( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, const char *path, - size_t pathlen, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base, - __wasi_rights_t fs_rights_inheriting, __wasi_fdflags_t fs_flags, - __wasi_fd_t *fd) +wasmtime_ssp_path_open(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, + const char *path, size_t pathlen, __wasi_oflags_t oflags, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting, + __wasi_fdflags_t fs_flags, __wasi_fd_t *fd) { // Rights that should be installed on the new file descriptor. __wasi_rights_t rights_base = fs_rights_base; @@ -1978,7 +2004,7 @@ wasmtime_ssp_path_open( if (!pa.follow) noflags |= O_NOFOLLOW; - int nfd = openat(pa.fd, pa.path, noflags, 0666); + int nfd = blocking_op_openat(exec_env, pa.fd, pa.path, noflags, 0666); if (nfd < 0) { int openat_errno = errno; // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket. @@ -2021,21 +2047,8 @@ wasmtime_ssp_path_open( return error; } - { - struct stat sb; - - if (fstat(nfd, &sb) < 0) { - close(nfd); - return convert_errno(errno); - } - - if (S_ISDIR(sb.st_mode)) - rights_base |= (__wasi_rights_t)RIGHTS_DIRECTORY_BASE; - else if (S_ISREG(sb.st_mode)) - rights_base |= (__wasi_rights_t)RIGHTS_REGULAR_FILE_BASE; - } - - return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base, + return fd_table_insert_fd(exec_env, curfds, nfd, type, + rights_base & max_base, rights_inheriting & max_inheriting, fd); } @@ -2054,12 +2067,9 @@ fd_readdir_put(void *buf, size_t bufsize, size_t *bufused, const void *elem, } __wasi_errno_t -wasmtime_ssp_fd_readdir( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, void *buf, size_t nbyte, __wasi_dircookie_t cookie, - size_t *bufused) +wasmtime_ssp_fd_readdir(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, void *buf, size_t nbyte, + __wasi_dircookie_t cookie, size_t *bufused) { struct fd_object *fo; __wasi_errno_t error = @@ -2075,7 +2085,7 @@ wasmtime_ssp_fd_readdir( dp = fdopendir(fd_number(fo)); if (dp == NULL) { mutex_unlock(&fo->directory.lock); - fd_object_release(fo); + fd_object_release(exec_env, fo); return convert_errno(errno); } fo->directory.handle = dp; @@ -2099,7 +2109,7 @@ wasmtime_ssp_fd_readdir( struct dirent *de = readdir(dp); if (de == NULL) { mutex_unlock(&fo->directory.lock); - fd_object_release(fo); + fd_object_release(exec_env, fo); return errno == 0 || *bufused > 0 ? 0 : convert_errno(errno); } fo->directory.offset = (__wasi_dircookie_t)telldir(dp); @@ -2148,17 +2158,14 @@ wasmtime_ssp_fd_readdir( fd_readdir_put(buf, nbyte, bufused, de->d_name, namlen); } mutex_unlock(&fo->directory.lock); - fd_object_release(fo); + fd_object_release(exec_env, fo); return 0; } __wasi_errno_t -wasmtime_ssp_path_readlink( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const char *path, size_t pathlen, char *buf, size_t bufsize, - size_t *bufused) +wasmtime_ssp_path_readlink(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const char *path, size_t pathlen, + char *buf, size_t bufsize, size_t *bufused) { struct path_access pa; __wasi_errno_t error = path_get_nofollow( @@ -2179,12 +2186,10 @@ wasmtime_ssp_path_readlink( } __wasi_errno_t -wasmtime_ssp_path_rename( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t old_fd, const char *old_path, size_t old_path_len, - __wasi_fd_t new_fd, const char *new_path, size_t new_path_len) +wasmtime_ssp_path_rename(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t old_fd, const char *old_path, + size_t old_path_len, __wasi_fd_t new_fd, + const char *new_path, size_t new_path_len) { struct path_access old_pa; __wasi_errno_t error = @@ -2226,11 +2231,8 @@ convert_stat(const struct stat *in, __wasi_filestat_t *out) } __wasi_errno_t -wasmtime_ssp_fd_filestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filestat_t *buf) +wasmtime_ssp_fd_filestat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_filestat_t *buf) { struct fd_object *fo; __wasi_errno_t error = @@ -2249,7 +2251,7 @@ wasmtime_ssp_fd_filestat_get( } } buf->st_filetype = fo->type; - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; @@ -2299,11 +2301,9 @@ convert_utimens_arguments(__wasi_timestamp_t st_atim, } __wasi_errno_t -wasmtime_ssp_fd_filestat_set_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_filesize_t st_size) +wasmtime_ssp_fd_filestat_set_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_filesize_t st_size) { struct fd_object *fo; __wasi_errno_t error = @@ -2312,19 +2312,18 @@ wasmtime_ssp_fd_filestat_set_size( return error; int ret = ftruncate(fd_number(fo), (off_t)st_size); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_fd_filestat_set_times( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags) +wasmtime_ssp_fd_filestat_set_times(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) { if ((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW @@ -2342,19 +2341,17 @@ wasmtime_ssp_fd_filestat_set_times( convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); int ret = futimens(fd_number(fo), ts); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret < 0) return convert_errno(errno); return 0; } __wasi_errno_t -wasmtime_ssp_path_filestat_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, - size_t pathlen, __wasi_filestat_t *buf) +wasmtime_ssp_path_filestat_get(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_lookupflags_t flags, const char *path, + size_t pathlen, __wasi_filestat_t *buf) { struct path_access pa; __wasi_errno_t error = path_get(curfds, &pa, fd, flags, path, pathlen, @@ -2389,13 +2386,13 @@ wasmtime_ssp_path_filestat_get( } __wasi_errno_t -wasmtime_ssp_path_filestat_set_times( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, - size_t pathlen, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags) +wasmtime_ssp_path_filestat_set_times(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *path, size_t pathlen, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) { if (((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW @@ -2428,12 +2425,10 @@ wasmtime_ssp_path_filestat_set_times( } __wasi_errno_t -wasmtime_ssp_path_symlink( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct fd_prestats *prestats, -#endif - const char *old_path, size_t old_path_len, __wasi_fd_t fd, - const char *new_path, size_t new_path_len) +wasmtime_ssp_path_symlink(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct fd_prestats *prestats, const char *old_path, + size_t old_path_len, __wasi_fd_t fd, + const char *new_path, size_t new_path_len) { char *target = str_nullterminate(old_path, old_path_len); if (target == NULL) @@ -2465,11 +2460,8 @@ wasmtime_ssp_path_symlink( } __wasi_errno_t -wasmtime_ssp_path_unlink_file( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const char *path, size_t pathlen) +wasmtime_ssp_path_unlink_file(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, const char *path, size_t pathlen) { struct path_access pa; __wasi_errno_t error = path_get_nofollow( @@ -2502,11 +2494,9 @@ wasmtime_ssp_path_unlink_file( } __wasi_errno_t -wasmtime_ssp_path_remove_directory( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, const char *path, size_t pathlen) +wasmtime_ssp_path_remove_directory(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + const char *path, size_t pathlen) { struct path_access pa; __wasi_errno_t error = @@ -2531,12 +2521,10 @@ wasmtime_ssp_path_remove_directory( } __wasi_errno_t -wasmtime_ssp_poll_oneoff( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions, - size_t *nevents) NO_LOCK_ANALYSIS +wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds, + const __wasi_subscription_t *in, __wasi_event_t *out, + size_t nsubscriptions, + size_t *nevents) NO_LOCK_ANALYSIS { // Sleeping. if (nsubscriptions == 1 && in[0].u.type == __WASI_EVENTTYPE_CLOCK) { @@ -2781,129 +2769,12 @@ wasmtime_ssp_poll_oneoff( for (size_t i = 0; i < nsubscriptions; ++i) if (fos[i] != NULL) - fd_object_release(fos[i]); + fd_object_release(exec_env, fos[i]); wasm_runtime_free(fos); wasm_runtime_free(pfds); return error; } -#if 0 -/** - * We throw exception in libc-wasi wrapper function wasi_proc_exit() - * but not call this function. - */ -void wasmtime_ssp_proc_exit( - __wasi_exitcode_t rval -) { - _Exit((int32)rval); -} -#endif - -__wasi_errno_t -wasmtime_ssp_proc_raise(__wasi_signal_t sig) -{ - static const int signals[] = { -#define X(v) [__WASI_##v] = v -#if defined(SIGABRT) - X(SIGABRT), -#endif -#if defined(SIGALRM) - X(SIGALRM), -#endif -#if defined(SIGBUS) - X(SIGBUS), -#endif -#if defined(SIGCHLD) - X(SIGCHLD), -#endif -#if defined(SIGCONT) - X(SIGCONT), -#endif -#if defined(SIGFPE) - X(SIGFPE), -#endif -#if defined(SIGHUP) - X(SIGHUP), -#endif -#if defined(SIGILL) - X(SIGILL), -#endif -#if defined(SIGINT) - X(SIGINT), -#endif -#if defined(SIGKILL) - X(SIGKILL), -#endif -#if defined(SIGPIPE) - X(SIGPIPE), -#endif -#if defined(SIGQUIT) - X(SIGQUIT), -#endif -#if defined(SIGSYS) - X(SIGSEGV), -#endif -#if defined(SIGSTOP) - X(SIGSTOP), -#endif -#if defined(SIGSYS) - X(SIGSYS), -#endif -#if defined(SIGTERM) - X(SIGTERM), -#endif -#if defined(SIGTRAP) - X(SIGTRAP), -#endif -#if defined(SIGTSTP) - X(SIGTSTP), -#endif -#if defined(SIGTTIN) - X(SIGTTIN), -#endif -#if defined(SIGTTOU) - X(SIGTTOU), -#endif -#if defined(SIGURG) - X(SIGURG), -#endif -#if defined(SIGUSR1) - X(SIGUSR1), -#endif -#if defined(SIGUSR2) - X(SIGUSR2), -#endif -#if defined(SIGVTALRM) - X(SIGVTALRM), -#endif -#if defined(SIGXCPU) - X(SIGXCPU), -#endif -#if defined(SIGXFSZ) - X(SIGXFSZ), -#endif -#undef X - }; - if (sig >= sizeof(signals) / sizeof(signals[0]) || signals[sig] == 0) - return __WASI_EINVAL; - -#if CONFIG_TLS_USE_GSBASE - // TLS on OS X depends on installing a SIGSEGV handler. Reset SIGSEGV - // to the default action before raising. - if (sig == __WASI_SIGSEGV) { - struct sigaction sa = { - .sa_handler = SIG_DFL, - }; - sigemptyset(&sa.sa_mask); - sigaction(SIGSEGV, &sa, NULL); - } -#endif - - if (raise(signals[sig]) < 0) - return convert_errno(errno); - return 0; -} - __wasi_errno_t wasmtime_ssp_random_get(void *buf, size_t nbyte) { @@ -2912,11 +2783,9 @@ wasmtime_ssp_random_get(void *buf, size_t nbyte) } __wasi_errno_t -wasi_ssp_sock_accept( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new) +wasi_ssp_sock_accept(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_fdflags_t flags, + __wasi_fd_t *fd_new) { __wasi_filetype_t wasi_type; __wasi_rights_t max_base, max_inheriting; @@ -2929,8 +2798,9 @@ wasi_ssp_sock_accept( goto fail; } - ret = os_socket_accept(fd_number(fo), &new_sock, NULL, NULL); - fd_object_release(fo); + ret = blocking_op_socket_accept(exec_env, fd_number(fo), &new_sock, NULL, + NULL); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { error = convert_errno(errno); goto fail; @@ -2942,7 +2812,7 @@ wasi_ssp_sock_accept( goto fail; } - error = fd_table_insert_fd(curfds, new_sock, wasi_type, max_base, + error = fd_table_insert_fd(exec_env, curfds, new_sock, wasi_type, max_base, max_inheriting, fd_new); if (error != __WASI_ESUCCESS) { /* released in fd_table_insert_fd() */ @@ -2960,11 +2830,8 @@ fail: } __wasi_errno_t -wasi_ssp_sock_addr_local( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_addr_local(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_addr_t *addr) { struct fd_object *fo; bh_sockaddr_t bh_addr; @@ -2976,7 +2843,7 @@ wasi_ssp_sock_addr_local( return error; ret = os_socket_addr_local(fd_number(fo), &bh_addr); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret != BHT_OK) { return convert_errno(errno); } @@ -2987,11 +2854,8 @@ wasi_ssp_sock_addr_local( } __wasi_errno_t -wasi_ssp_sock_addr_remote( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_addr_remote(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_addr_t *addr) { struct fd_object *fo; bh_sockaddr_t bh_addr; @@ -3003,7 +2867,7 @@ wasi_ssp_sock_addr_remote( return error; ret = os_socket_addr_remote(fd_number(fo), &bh_addr); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (ret != BHT_OK) { return convert_errno(errno); } @@ -3043,11 +2907,9 @@ wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen) } __wasi_errno_t -wasi_ssp_sock_bind( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct addr_pool *addr_pool, -#endif - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_bind(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct addr_pool *addr_pool, __wasi_fd_t fd, + __wasi_addr_t *addr) { char buf[48] = { 0 }; struct fd_object *fo; @@ -3068,7 +2930,7 @@ wasi_ssp_sock_bind( return error; ret = os_socket_bind(fd_number(fo), buf, &port); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3077,13 +2939,12 @@ wasi_ssp_sock_bind( } __wasi_errno_t -wasi_ssp_sock_addr_resolve( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, char **ns_lookup_list, -#endif - const char *host, const char *service, __wasi_addr_info_hints_t *hints, - __wasi_addr_info_t *addr_info, __wasi_size_t addr_info_size, - __wasi_size_t *max_info_size) +wasi_ssp_sock_addr_resolve(wasm_exec_env_t exec_env, struct fd_table *curfds, + char **ns_lookup_list, const char *host, + const char *service, __wasi_addr_info_hints_t *hints, + __wasi_addr_info_t *addr_info, + __wasi_size_t addr_info_size, + __wasi_size_t *max_info_size) { bh_addr_info_t *wamr_addr_info = wasm_runtime_malloc(addr_info_size * sizeof(bh_addr_info_t)); @@ -3101,10 +2962,13 @@ wasi_ssp_sock_addr_resolve( return __WASI_EACCES; } - int ret = os_socket_addr_resolve( - host, service, hints->hints_enabled ? &hints_is_tcp : NULL, - hints->hints_enabled ? &hints_is_ipv4 : NULL, wamr_addr_info, - addr_info_size, &_max_info_size); + int ret = blocking_op_socket_addr_resolve( + exec_env, host, service, + hints->hints_enabled && hints->type != SOCKET_ANY ? &hints_is_tcp + : NULL, + hints->hints_enabled && hints->family != INET_UNSPEC ? &hints_is_ipv4 + : NULL, + wamr_addr_info, addr_info_size, &_max_info_size); if (ret != BHT_OK) { wasm_runtime_free(wamr_addr_info); @@ -3127,11 +2991,9 @@ wasi_ssp_sock_addr_resolve( } __wasi_errno_t -wasi_ssp_sock_connect( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct addr_pool *addr_pool, -#endif - __wasi_fd_t fd, __wasi_addr_t *addr) +wasi_ssp_sock_connect(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct addr_pool *addr_pool, __wasi_fd_t fd, + __wasi_addr_t *addr) { char buf[48] = { 0 }; struct fd_object *fo; @@ -3150,10 +3012,10 @@ wasi_ssp_sock_connect( if (error != __WASI_ESUCCESS) return error; - ret = os_socket_connect(fd_number(fo), buf, - addr->kind == IPv4 ? addr->addr.ip4.port - : addr->addr.ip6.port); - fd_object_release(fo); + ret = blocking_op_socket_connect(exec_env, fd_number(fo), buf, + addr->kind == IPv4 ? addr->addr.ip4.port + : addr->addr.ip6.port); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3162,11 +3024,9 @@ wasi_ssp_sock_connect( } __wasi_errno_t -wasi_ssp_sock_get_recv_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t *size) +wasi_ssp_sock_get_recv_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t *size) { struct fd_object *fo; int ret; @@ -3178,7 +3038,7 @@ wasi_ssp_sock_get_recv_buf_size( socklen_t optlen = sizeof(optval); ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval, &optlen); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3189,11 +3049,8 @@ wasi_ssp_sock_get_recv_buf_size( } __wasi_errno_t -wasi_ssp_sock_get_reuse_addr( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, uint8_t *reuse) +wasi_ssp_sock_get_reuse_addr(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t *reuse) { struct fd_object *fo; @@ -3206,7 +3063,7 @@ wasi_ssp_sock_get_reuse_addr( socklen_t optlen = sizeof(optval); ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, &optlen); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3217,11 +3074,8 @@ wasi_ssp_sock_get_reuse_addr( } __wasi_errno_t -wasi_ssp_sock_get_reuse_port( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, uint8_t *reuse) +wasi_ssp_sock_get_reuse_port(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t *reuse) { struct fd_object *fo; int ret; @@ -3240,7 +3094,7 @@ wasi_ssp_sock_get_reuse_port( optval = 0; #endif /* defined(SO_REUSEPORT) */ - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3251,11 +3105,9 @@ wasi_ssp_sock_get_reuse_port( } __wasi_errno_t -wasi_ssp_sock_get_send_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t *size) +wasi_ssp_sock_get_send_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t *size) { struct fd_object *fo; int ret; @@ -3267,7 +3119,7 @@ wasi_ssp_sock_get_send_buf_size( socklen_t optlen = sizeof(optval); ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval, &optlen); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3278,11 +3130,8 @@ wasi_ssp_sock_get_send_buf_size( } __wasi_errno_t -wasi_ssp_sock_listen( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t backlog) +wasi_ssp_sock_listen(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, __wasi_size_t backlog) { struct fd_object *fo; int ret; @@ -3292,7 +3141,7 @@ wasi_ssp_sock_listen( return error; ret = os_socket_listen(fd_number(fo), backlog); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3301,12 +3150,9 @@ wasi_ssp_sock_listen( } __wasi_errno_t -wasi_ssp_sock_open( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype, - __wasi_fd_t *sockfd) +wasi_ssp_sock_open(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t poolfd, __wasi_address_family_t af, + __wasi_sock_type_t socktype, __wasi_fd_t *sockfd) { bh_socket_t sock; bool is_tcp = SOCKET_DGRAM == socktype ? false : true; @@ -3338,7 +3184,7 @@ wasi_ssp_sock_open( } // TODO: base rights and inheriting rights ? - error = fd_table_insert_fd(curfds, sock, wasi_type, max_base, + error = fd_table_insert_fd(exec_env, curfds, sock, wasi_type, max_base, max_inheriting, sockfd); if (error != __WASI_ESUCCESS) { return error; @@ -3348,11 +3194,9 @@ wasi_ssp_sock_open( } __wasi_errno_t -wasi_ssp_sock_set_recv_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t size) +wasi_ssp_sock_set_recv_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t size) { struct fd_object *fo; int ret; @@ -3364,7 +3208,7 @@ wasi_ssp_sock_set_recv_buf_size( ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3373,11 +3217,8 @@ wasi_ssp_sock_set_recv_buf_size( } __wasi_errno_t -wasi_ssp_sock_set_reuse_addr( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, uint8_t reuse) +wasi_ssp_sock_set_reuse_addr(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t reuse) { struct fd_object *fo; int ret; @@ -3389,7 +3230,7 @@ wasi_ssp_sock_set_reuse_addr( ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3398,11 +3239,8 @@ wasi_ssp_sock_set_reuse_addr( } __wasi_errno_t -wasi_ssp_sock_set_reuse_port( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, uint8_t reuse) +wasi_ssp_sock_set_reuse_port(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t fd, uint8_t reuse) { struct fd_object *fo; int ret; @@ -3420,7 +3258,7 @@ wasi_ssp_sock_set_reuse_port( ret = BHT_ERROR; #endif /* defined(SO_REUSEPORT) */ - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3429,11 +3267,9 @@ wasi_ssp_sock_set_reuse_port( } __wasi_errno_t -wasi_ssp_sock_set_send_buf_size( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t fd, __wasi_size_t size) +wasi_ssp_sock_set_send_buf_size(wasm_exec_env_t exec_env, + struct fd_table *curfds, __wasi_fd_t fd, + __wasi_size_t size) { struct fd_object *fo; int ret; @@ -3446,7 +3282,7 @@ wasi_ssp_sock_set_send_buf_size( ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) { return convert_errno(errno); } @@ -3455,25 +3291,21 @@ wasi_ssp_sock_set_send_buf_size( } __wasi_errno_t -wasmtime_ssp_sock_recv( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len) +wasmtime_ssp_sock_recv(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, void *buf, size_t buf_len, + size_t *recv_len) { __wasi_addr_t src_addr; - return wasmtime_ssp_sock_recv_from(curfds, sock, buf, buf_len, 0, &src_addr, - recv_len); + return wasmtime_ssp_sock_recv_from(exec_env, curfds, sock, buf, buf_len, 0, + &src_addr, recv_len); } __wasi_errno_t -wasmtime_ssp_sock_recv_from( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, void *buf, size_t buf_len, __wasi_riflags_t ri_flags, - __wasi_addr_t *src_addr, size_t *recv_len) +wasmtime_ssp_sock_recv_from(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, void *buf, size_t buf_len, + __wasi_riflags_t ri_flags, __wasi_addr_t *src_addr, + size_t *recv_len) { struct fd_object *fo; __wasi_errno_t error; @@ -3485,8 +3317,9 @@ wasmtime_ssp_sock_recv_from( return error; } - ret = os_socket_recv_from(fd_number(fo), buf, buf_len, 0, &sockaddr); - fd_object_release(fo); + ret = blocking_op_socket_recv_from(exec_env, fd_number(fo), buf, buf_len, 0, + &sockaddr); + fd_object_release(exec_env, fo); if (-1 == ret) { return convert_errno(errno); } @@ -3498,11 +3331,9 @@ wasmtime_ssp_sock_recv_from( } __wasi_errno_t -wasmtime_ssp_sock_send( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, const void *buf, size_t buf_len, size_t *sent_len) +wasmtime_ssp_sock_send(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, const void *buf, size_t buf_len, + size_t *sent_len) { struct fd_object *fo; __wasi_errno_t error; @@ -3514,7 +3345,7 @@ wasmtime_ssp_sock_send( } ret = os_socket_send(fd_number(fo), buf, buf_len); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (-1 == ret) { return convert_errno(errno); } @@ -3524,12 +3355,11 @@ wasmtime_ssp_sock_send( } __wasi_errno_t -wasmtime_ssp_sock_send_to( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, struct addr_pool *addr_pool, -#endif - __wasi_fd_t sock, const void *buf, size_t buf_len, - __wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr, size_t *sent_len) +wasmtime_ssp_sock_send_to(wasm_exec_env_t exec_env, struct fd_table *curfds, + struct addr_pool *addr_pool, __wasi_fd_t sock, + const void *buf, size_t buf_len, + __wasi_siflags_t si_flags, + const __wasi_addr_t *dest_addr, size_t *sent_len) { char addr_buf[48] = { 0 }; struct fd_object *fo; @@ -3552,8 +3382,9 @@ wasmtime_ssp_sock_send_to( wasi_addr_to_bh_sockaddr(dest_addr, &sockaddr); - ret = os_socket_send_to(fd_number(fo), buf, buf_len, 0, &sockaddr); - fd_object_release(fo); + ret = blocking_op_socket_send_to(exec_env, fd_number(fo), buf, buf_len, 0, + &sockaddr); + fd_object_release(exec_env, fo); if (-1 == ret) { return convert_errno(errno); } @@ -3563,11 +3394,8 @@ wasmtime_ssp_sock_send_to( } __wasi_errno_t -wasmtime_ssp_sock_shutdown( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock) +wasmtime_ssp_sock_shutdown(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock) { struct fd_object *fo; __wasi_errno_t error; @@ -3578,7 +3406,7 @@ wasmtime_ssp_sock_shutdown( return error; ret = os_socket_shutdown(fd_number(fo)); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); @@ -3594,11 +3422,8 @@ wasmtime_ssp_sched_yield(void) } __wasi_errno_t -wasmtime_ssp_args_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, -#endif - char **argv, char *argv_buf) +wasmtime_ssp_args_get(struct argv_environ_values *argv_environ, char **argv, + char *argv_buf) { for (size_t i = 0; i < argv_environ->argc; ++i) { argv[i] = @@ -3611,11 +3436,8 @@ wasmtime_ssp_args_get( } __wasi_errno_t -wasmtime_ssp_args_sizes_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, -#endif - size_t *argc, size_t *argv_buf_size) +wasmtime_ssp_args_sizes_get(struct argv_environ_values *argv_environ, + size_t *argc, size_t *argv_buf_size) { *argc = argv_environ->argc; *argv_buf_size = argv_environ->argv_buf_size; @@ -3623,11 +3445,8 @@ wasmtime_ssp_args_sizes_get( } __wasi_errno_t -wasmtime_ssp_environ_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, -#endif - char **environ, char *environ_buf) +wasmtime_ssp_environ_get(struct argv_environ_values *argv_environ, + char **environ, char *environ_buf) { for (size_t i = 0; i < argv_environ->environ_count; ++i) { environ[i] = @@ -3642,11 +3461,8 @@ wasmtime_ssp_environ_get( } __wasi_errno_t -wasmtime_ssp_environ_sizes_get( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, -#endif - size_t *environ_count, size_t *environ_buf_size) +wasmtime_ssp_environ_sizes_get(struct argv_environ_values *argv_environ, + size_t *environ_count, size_t *environ_buf_size) { *environ_count = argv_environ->environ_count; *environ_buf_size = argv_environ->environ_buf_size; @@ -3682,7 +3498,7 @@ fd_table_destroy(struct fd_table *ft) if (ft->entries) { for (uint32 i = 0; i < ft->size; i++) { if (ft->entries[i].object != NULL) { - fd_object_release(ft->entries[i].object); + fd_object_release(NULL, ft->entries[i].object); } } rwlock_destroy(&ft->lock); @@ -3871,16 +3687,13 @@ addr_pool_destroy(struct addr_pool *addr_pool) } } -#ifndef WASMTIME_SSP_STATIC_CURFDS #define WASMTIME_SSP_PASSTHROUGH_FD_TABLE struct fd_table *curfds, -#else -#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE -#endif // Defines a function that passes through the socket option to the OS // implementation #define WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(FUNC_NAME, OPTION_TYPE) \ __wasi_errno_t wasmtime_ssp_sock_##FUNC_NAME( \ + wasm_exec_env_t exec_env, \ WASMTIME_SSP_PASSTHROUGH_FD_TABLE __wasi_fd_t sock, \ OPTION_TYPE option) \ { \ @@ -3891,7 +3704,7 @@ addr_pool_destroy(struct addr_pool *addr_pool) if (error != 0) \ return error; \ ret = os_socket_##FUNC_NAME(fd_number(fo), option); \ - fd_object_release(fo); \ + fd_object_release(exec_env, fo); \ if (BHT_OK != ret) \ return convert_errno(errno); \ return __WASI_ESUCCESS; \ @@ -3934,11 +3747,8 @@ WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ipv6_only, bool *) #undef WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION __wasi_errno_t -wasmtime_ssp_sock_set_linger( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, bool is_enabled, int linger_s) +wasmtime_ssp_sock_set_linger(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, bool is_enabled, int linger_s) { struct fd_object *fo; __wasi_errno_t error; @@ -3948,18 +3758,15 @@ wasmtime_ssp_sock_set_linger( return error; ret = os_socket_set_linger(fd_number(fo), is_enabled, linger_s); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); return __WASI_ESUCCESS; } __wasi_errno_t -wasmtime_ssp_sock_get_linger( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, bool *is_enabled, int *linger_s) +wasmtime_ssp_sock_get_linger(wasm_exec_env_t exec_env, struct fd_table *curfds, + __wasi_fd_t sock, bool *is_enabled, int *linger_s) { struct fd_object *fo; __wasi_errno_t error; @@ -3969,7 +3776,7 @@ wasmtime_ssp_sock_get_linger( return error; ret = os_socket_get_linger(fd_number(fo), is_enabled, linger_s); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); @@ -3977,11 +3784,11 @@ wasmtime_ssp_sock_get_linger( } __wasi_errno_t -wasmtime_ssp_sock_set_ip_add_membership( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface) +wasmtime_ssp_sock_set_ip_add_membership(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) { struct fd_object *fo; __wasi_errno_t error; @@ -3996,18 +3803,18 @@ wasmtime_ssp_sock_set_ip_add_membership( is_ipv6 = imr_multiaddr->kind == IPv6; ret = os_socket_set_ip_add_membership(fd_number(fo), &addr_info, imr_interface, is_ipv6); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); return __WASI_ESUCCESS; } __wasi_errno_t -wasmtime_ssp_sock_set_ip_drop_membership( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface) +wasmtime_ssp_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) { struct fd_object *fo; __wasi_errno_t error; @@ -4022,18 +3829,17 @@ wasmtime_ssp_sock_set_ip_drop_membership( is_ipv6 = imr_multiaddr->kind == IPv6; ret = os_socket_set_ip_drop_membership(fd_number(fo), &addr_info, imr_interface, is_ipv6); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); return __WASI_ESUCCESS; } __wasi_errno_t -wasmtime_ssp_sock_set_ip_multicast_loop( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, bool ipv6, bool is_enabled) +wasmtime_ssp_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, bool ipv6, + bool is_enabled) { struct fd_object *fo; __wasi_errno_t error; @@ -4043,18 +3849,17 @@ wasmtime_ssp_sock_set_ip_multicast_loop( return error; ret = os_socket_set_ip_multicast_loop(fd_number(fo), ipv6, is_enabled); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); return __WASI_ESUCCESS; } __wasi_errno_t -wasmtime_ssp_sock_get_ip_multicast_loop( -#if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, -#endif - __wasi_fd_t sock, bool ipv6, bool *is_enabled) +wasmtime_ssp_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, + struct fd_table *curfds, + __wasi_fd_t sock, bool ipv6, + bool *is_enabled) { struct fd_object *fo; __wasi_errno_t error; @@ -4064,7 +3869,7 @@ wasmtime_ssp_sock_get_ip_multicast_loop( return error; ret = os_socket_get_ip_multicast_loop(fd_number(fo), ipv6, is_enabled); - fd_object_release(fo); + fd_object_release(exec_env, fo); if (BHT_OK != ret) return convert_errno(errno); diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h index 7f6e9b941..f5e130a9e 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h @@ -101,12 +101,6 @@ #define st_mtim st_mtimespec #endif -#ifdef __APPLE__ -#define CONFIG_TLS_USE_GSBASE 1 -#else -#define CONFIG_TLS_USE_GSBASE 0 -#endif - #if !defined(BH_PLATFORM_LINUX_SGX) /* Clang's __GNUC_PREREQ macro has a different meaning than GCC one, so we have to handle this case specially */ diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 9303eb3f5..49545de72 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -16,10 +16,6 @@ #include "debug_engine.h" #endif -#if WASM_ENABLE_SHARED_MEMORY != 0 -#include "wasm_shared_memory.h" -#endif - typedef struct { bh_list_link l; void (*destroy_cb)(WASMCluster *); @@ -32,6 +28,8 @@ static bh_list cluster_list_head; static bh_list *const cluster_list = &cluster_list_head; static korp_mutex cluster_list_lock; +static korp_mutex _exception_lock; + typedef void (*list_visitor)(void *, void *); static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM; @@ -52,6 +50,10 @@ thread_manager_init() return false; if (os_mutex_init(&cluster_list_lock) != 0) return false; + if (os_mutex_init(&_exception_lock) != 0) { + os_mutex_destroy(&cluster_list_lock); + return false; + } return true; } @@ -66,6 +68,7 @@ thread_manager_destroy() cluster = next; } wasm_cluster_cancel_all_callbacks(); + os_mutex_destroy(&_exception_lock); os_mutex_destroy(&cluster_list_lock); } @@ -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; @@ -509,7 +509,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) #endif if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, true, exec_env, stack_size, 0, NULL, 0))) { + module, module_inst, exec_env, stack_size, 0, NULL, 0))) { goto fail1; } @@ -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); @@ -606,7 +603,8 @@ thread_manager_start_routine(void *arg) #ifdef OS_ENABLE_HW_BOUND_CHECK os_mutex_lock(&exec_env->wait_lock); - if (exec_env->suspend_flags.flags & 0x08) + if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) + & WASM_SUSPEND_FLAG_EXIT) ret = exec_env->thread_ret_value; os_mutex_unlock(&exec_env->wait_lock); #endif @@ -745,10 +743,10 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, #if WASM_ENABLE_INTERP != 0 if (module_inst_src->module_type == Wasm_Module_Bytecode) { - new_c_api_func_imports = - &(((WASMModuleInstance *)module_inst_dst)->e->c_api_func_imports); + new_c_api_func_imports = &(((WASMModuleInstance *)module_inst_dst) + ->e->common.c_api_func_imports); c_api_func_imports = ((const WASMModuleInstance *)module_inst_src) - ->e->c_api_func_imports; + ->e->common.c_api_func_imports; import_func_count = ((WASMModule *)(((const WASMModuleInstance *)module_inst_src) ->module)) @@ -759,10 +757,10 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, if (module_inst_src->module_type == Wasm_Module_AoT) { AOTModuleInstanceExtra *e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_dst)->e; - new_c_api_func_imports = &(e->c_api_func_imports); + new_c_api_func_imports = &(e->common.c_api_func_imports); e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_src)->e; - c_api_func_imports = e->c_api_func_imports; + c_api_func_imports = e->common.c_api_func_imports; import_func_count = ((AOTModule *)(((AOTModuleInstance *)module_inst_src)->module)) @@ -993,7 +991,9 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) if (exec_env->jmpbuf_stack_top) { /* Store the return value in exec_env */ exec_env->thread_ret_value = retval; - exec_env->suspend_flags.flags |= 0x08; + + WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags, + WASM_SUSPEND_FLAG_EXIT); #ifndef BH_PLATFORM_WINDOWS /* Pop all jmpbuf_node except the last one */ @@ -1055,9 +1055,23 @@ set_thread_cancel_flags(WASMExecEnv *exec_env) #if WASM_ENABLE_DEBUG_INTERP != 0 wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM); #endif - exec_env->suspend_flags.flags |= 0x01; + WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags, + WASM_SUSPEND_FLAG_TERMINATE); os_mutex_unlock(&exec_env->wait_lock); + +#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 @@ -1178,7 +1192,8 @@ void wasm_cluster_suspend_thread(WASMExecEnv *exec_env) { /* Set the suspend flag */ - exec_env->suspend_flags.flags |= 0x02; + WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags, + WASM_SUSPEND_FLAG_SUSPEND); } static void @@ -1214,7 +1229,8 @@ wasm_cluster_suspend_all_except_self(WASMCluster *cluster, void wasm_cluster_resume_thread(WASMExecEnv *exec_env) { - exec_env->suspend_flags.flags &= ~0x02; + WASM_SUSPEND_FLAGS_FETCH_AND(exec_env->suspend_flags, + ~WASM_SUSPEND_FLAG_SUSPEND); os_cond_signal(&exec_env->wait_cond); } @@ -1234,76 +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 - WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory( - (WASMModuleCommon *)curr_wasm_inst->module); - if (shared_mem_node) - os_mutex_lock(&shared_mem_node->shared_mem_lock); -#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 (shared_mem_node) - os_mutex_unlock(&shared_mem_node->shared_mem_lock); -#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 - WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory( - (WASMModuleCommon *)curr_wasm_inst->module); - if (shared_mem_node) - os_mutex_lock(&shared_mem_node->shared_mem_lock); -#endif - curr_wasm_inst->cur_exception[0] = '\0'; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (shared_mem_node) - os_mutex_unlock(&shared_mem_node->shared_mem_lock); -#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); } @@ -1339,13 +1334,75 @@ 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) { os_mutex_lock(&exec_env->wait_lock); - bool is_thread_terminated = - (exec_env->suspend_flags.flags & 0x01) ? true : false; + bool is_thread_terminated = (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) + & WASM_SUSPEND_FLAG_TERMINATE) + ? true + : false; os_mutex_unlock(&exec_env->wait_lock); return is_thread_terminated; } + +void +exception_lock(WASMModuleInstance *module_inst) +{ + /* + * Note: this lock could be per module instance if desirable. + * We can revisit on AOT version bump. + * It probably doesn't matter though because the exception handling + * logic should not be executed too frequently anyway. + */ + os_mutex_lock(&_exception_lock); +} + +void +exception_unlock(WASMModuleInstance *module_inst) +{ + os_mutex_unlock(&_exception_lock); +} diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 2060869c2..19186f597 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -139,7 +139,7 @@ WASMExecEnv * wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst); void -wasm_cluster_spread_exception(WASMExecEnv *exec_env, 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); diff --git a/core/iwasm/libraries/wasi-nn/.gitignore b/core/iwasm/libraries/wasi-nn/.gitignore new file mode 100644 index 000000000..81c0ff6aa --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/.gitignore @@ -0,0 +1,2 @@ +**/*.wasm +**/*.tflite diff --git a/core/iwasm/libraries/wasi-nn/README.md b/core/iwasm/libraries/wasi-nn/README.md index 96493a30f..fbc99ccbb 100644 --- a/core/iwasm/libraries/wasi-nn/README.md +++ b/core/iwasm/libraries/wasi-nn/README.md @@ -25,6 +25,7 @@ Build the runtime image for your execution target type. * `cpu` * `nvidia-gpu` * `vx-delegate` +* `tpu` ``` EXECUTION_TYPE=cpu @@ -64,6 +65,8 @@ docker run \ ``` * (NVIDIA) GPU + * Requirements: + * [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker). ``` docker run \ @@ -76,25 +79,36 @@ docker run \ /assets/test_tensorflow.wasm ``` -* vx-delegate for NPU (x86 simulater) +* vx-delegate for NPU (x86 simulator) ``` docker run \ - -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-vx-delegate \ - --dir=/assets \ + -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets \ + wasi-nn-vx-delegate \ + --dir=/ \ --env="TARGET=gpu" \ - /assets/test_tensorflow.wasm + /assets/test_tensorflow_quantized.wasm ``` +* (Coral) TPU + * Requirements: + * [Coral USB](https://coral.ai/products/accelerator/). - -Requirements: -* [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker). +``` +docker run \ + --privileged \ + --device=/dev/bus/usb:/dev/bus/usb \ + -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets \ + wasi-nn-tpu \ + --dir=/ \ + --env="TARGET=tpu" \ + /assets/test_tensorflow_quantized.wasm +``` ## What is missing Supported: * Graph encoding: `tensorflowlite`. -* Execution target: `cpu` and `gpu`. +* Execution target: `cpu`, `gpu` and `tpu`. * Tensor type: `fp32`. diff --git a/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake b/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake index 39cc10dc1..59fdaf758 100644 --- a/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake +++ b/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake @@ -18,12 +18,16 @@ if(NOT EXISTS ${TENSORFLOW_LITE}) set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") - if(WASI_NN_ENABLE_GPU EQUAL 1) + if(WAMR_BUILD_WASI_NN_ENABLE_GPU EQUAL 1) # Tensorflow specific: # * https://www.tensorflow.org/lite/guide/build_cmake#available_options_to_build_tensorflow_lite set (TFLITE_ENABLE_GPU ON) endif() + if (CMAKE_SIZEOF_VOID_P EQUAL 4) + set (TFLITE_ENABLE_XNNPACK OFF) + endif() + add_subdirectory( "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite" "${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp index d9fb2668e..65e38f867 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp @@ -16,11 +16,11 @@ #include #include -#if defined(WASI_NN_ENABLE_GPU) +#if WASM_ENABLE_WASI_NN_GPU != 0 #include #endif -#if defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE) +#if WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE != 0 #include #endif @@ -130,8 +130,8 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder, return invalid_argument; } - if (target != cpu && target != gpu) { - NN_ERR_PRINTF("Only CPU and GPU target is supported."); + if (target != cpu && target != gpu && target != tpu) { + NN_ERR_PRINTF("Only CPU, GPU and TPU target is supported."); return invalid_argument; } @@ -195,7 +195,7 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g, switch (tfl_ctx->models[g].target) { case gpu: { -#if defined(WASI_NN_ENABLE_GPU) +#if WASM_ENABLE_WASI_NN_GPU != 0 NN_WARN_PRINTF("GPU enabled."); // https://www.tensorflow.org/lite/performance/gpu TfLiteGpuDelegateOptionsV2 options = @@ -216,10 +216,19 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g, NN_ERR_PRINTF("Error when enabling GPU delegate."); use_default = true; } -#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE) +#else + NN_WARN_PRINTF("GPU not enabled."); + use_default = true; +#endif + break; + } + case tpu: + { +#if WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE != 0 NN_WARN_PRINTF("external delegation enabled."); TfLiteExternalDelegateOptions options = - TfLiteExternalDelegateOptionsDefault(WASI_NN_EXT_DELEGATE_PATH); + TfLiteExternalDelegateOptionsDefault( + WASM_WASI_NN_EXTERNAL_DELEGATE_PATH); tfl_ctx->delegate = TfLiteExternalDelegateCreate(&options); if (tfl_ctx->delegate == NULL) { NN_ERR_PRINTF("Error when generating External delegate."); @@ -233,7 +242,7 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g, use_default = true; } #else - NN_WARN_PRINTF("GPU not enabled."); + NN_WARN_PRINTF("External delegate not enabled."); use_default = true; #endif break; @@ -285,14 +294,37 @@ tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx, return invalid_argument; } - auto *input = - tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor( - index); - if (input == NULL) - return missing_memory; + if (tensor->quantization.type == kTfLiteNoQuantization) { + NN_DBG_PRINTF("No quantization information. Using float as default"); + float *it = + tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor( + index); + + int size = model_tensor_size * sizeof(float); + bh_memcpy_s(it, size, input_tensor->data, size); + } + else { // TODO: Assumming uint8 quantized networks. + TfLiteAffineQuantization *quant_info = + (TfLiteAffineQuantization *)tensor->quantization.params; + if (quant_info->scale->size != 1 || quant_info->zero_point->size != 1) { + NN_ERR_PRINTF("Quantization per channel is not supported"); + return runtime_error; + } + uint8_t *it = + tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor( + index); + + float scale = quant_info->scale->data[0]; + float zero_point = (float)quant_info->zero_point->data[0]; + NN_DBG_PRINTF("input tensor: (scale, offset) = (%f, %f)", scale, + zero_point); + + float *input_tensor_f = (float *)input_tensor->data; + for (uint32_t i = 0; i < model_tensor_size; ++i) { + it[i] = (uint8_t)(input_tensor_f[i] / scale + zero_point); + } + } - bh_memcpy_s(input, model_tensor_size * sizeof(float), input_tensor->data, - model_tensor_size * sizeof(float)); return success; } @@ -325,6 +357,7 @@ tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx, NN_DBG_PRINTF("Number of tensors (%d)", num_output_tensors); if (index + 1 > num_output_tensors) { + NN_ERR_PRINTF("Index %d is invalid.", index); return runtime_error; } @@ -343,15 +376,37 @@ tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx, return missing_memory; } - float *tensor_f = - tfl_ctx->interpreters[ctx].interpreter->typed_output_tensor( - index); - for (uint32_t i = 0; i < model_tensor_size; ++i) - NN_DBG_PRINTF("output: %f", tensor_f[i]); + if (tensor->quantization.type == kTfLiteNoQuantization) { + NN_DBG_PRINTF("No quantization information"); + float *ot = + tfl_ctx->interpreters[ctx].interpreter->typed_output_tensor( + index); + + int size = model_tensor_size * sizeof(float); + bh_memcpy_s(output_tensor, size, ot, size); + } + else { // TODO: Assumming uint8 quantized networks. + TfLiteAffineQuantization *quant_info = + (TfLiteAffineQuantization *)tensor->quantization.params; + if (quant_info->scale->size != 1 || quant_info->zero_point->size != 1) { + NN_ERR_PRINTF("Quantization per channel is not supported"); + return runtime_error; + } + uint8_t *ot = tfl_ctx->interpreters[ctx] + .interpreter->typed_output_tensor(index); + + float scale = quant_info->scale->data[0]; + float zero_point = (float)quant_info->zero_point->data[0]; + NN_DBG_PRINTF("output tensor: (scale, offset) = (%f, %f)", scale, + zero_point); + + float *output_tensor_f = (float *)output_tensor; + for (uint32_t i = 0; i < model_tensor_size; ++i) { + output_tensor_f[i] = (ot[i] - zero_point) * scale; + } + } *output_tensor_size = model_tensor_size; - bh_memcpy_s(output_tensor, model_tensor_size * sizeof(float), tensor_f, - model_tensor_size * sizeof(float)); return success; } @@ -392,19 +447,35 @@ tensorflowlite_destroy(void *tflite_ctx) */ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; - if (tfl_ctx->delegate != NULL) { -#if defined(WASI_NN_ENABLE_GPU) - TfLiteGpuDelegateV2Delete(tfl_ctx->delegate); -#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE) - TfLiteExternalDelegateDelete(tfl_ctx->delegate); -#endif - } - NN_DBG_PRINTF("Freeing memory."); for (int i = 0; i < MAX_GRAPHS_PER_INST; ++i) { tfl_ctx->models[i].model.reset(); - if (tfl_ctx->models[i].model_pointer) + if (tfl_ctx->models[i].model_pointer) { + if (tfl_ctx->delegate) { + switch (tfl_ctx->models[i].target) { + case gpu: + { +#if WASM_ENABLE_WASI_NN_GPU != 0 + TfLiteGpuDelegateV2Delete(tfl_ctx->delegate); +#else + NN_ERR_PRINTF("GPU delegate delete but not enabled."); +#endif + break; + } + case tpu: + { +#if WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE != 0 + TfLiteExternalDelegateDelete(tfl_ctx->delegate); +#else + NN_ERR_PRINTF( + "External delegate delete but not enabled."); +#endif + break; + } + } + } wasm_runtime_free(tfl_ctx->models[i].model_pointer); + } tfl_ctx->models[i].model_pointer = NULL; } for (int i = 0; i < MAX_GRAPH_EXEC_CONTEXTS_PER_INST; ++i) { diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu b/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu index f98f121e7..6fe56567e 100644 --- a/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu @@ -30,7 +30,6 @@ RUN make -j "$(grep -c ^processor /proc/cpuinfo)" FROM ubuntu:22.04 -COPY --from=base /home/wamr/product-mini/platforms/linux/build/libvmlib.so /libvmlib.so COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /iwasm ENTRYPOINT [ "/iwasm" ] diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu b/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu index be80ad455..737b2d3f0 100644 --- a/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu @@ -24,7 +24,7 @@ RUN apt-get install -y wget ca-certificates --no-install-recommends \ RUN cmake \ -DWAMR_BUILD_WASI_NN=1 \ - -DWASI_NN_ENABLE_GPU=1 \ + -DWAMR_BUILD_WASI_NN_ENABLE_GPU=1 \ .. RUN make -j "$(grep -c ^processor /proc/cpuinfo)" @@ -44,7 +44,6 @@ RUN mkdir -p /etc/OpenCL/vendors && \ ENV NVIDIA_VISIBLE_DEVICES=all ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility -COPY --from=base /home/wamr/product-mini/platforms/linux/build/libvmlib.so /libvmlib.so COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /iwasm ENTRYPOINT [ "/iwasm" ] diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.tpu b/core/iwasm/libraries/wasi-nn/test/Dockerfile.tpu new file mode 100644 index 000000000..742645b06 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.tpu @@ -0,0 +1,37 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +FROM ubuntu:20.04 AS base + +ENV DEBIAN_FRONTEND=noninteractive + +# hadolint ignore=DL3008 +RUN apt-get update && apt-get install -y \ + cmake build-essential git curl gnupg --no-install-recommends && \ + rm -rf /var/lib/apt/lists/* + +# hadolint ignore=DL3008,DL4006 +RUN echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | tee /etc/apt/sources.list.d/coral-edgetpu.list && \ + curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \ + apt-get update && apt-get install -y libedgetpu1-std --no-install-recommends && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /home/wamr + +COPY . . + +WORKDIR /home/wamr/product-mini/platforms/linux/build + +RUN cmake \ + -DWAMR_BUILD_WASI_NN=1 \ + -DWAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE=1 \ + -DWAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH="libedgetpu.so.1.0" \ + -DWAMR_BUILD_WASI_NN_ENABLE_GPU=1 \ + .. + +RUN make -j "$(grep -c ^processor /proc/cpuinfo)" && \ + cp /home/wamr/product-mini/platforms/linux/build/iwasm /iwasm + +WORKDIR /assets + +ENTRYPOINT [ "/iwasm" ] diff --git a/core/iwasm/libraries/wasi-nn/test/build.sh b/core/iwasm/libraries/wasi-nn/test/build.sh index f018f6004..da6cfa5f8 100755 --- a/core/iwasm/libraries/wasi-nn/test/build.sh +++ b/core/iwasm/libraries/wasi-nn/test/build.sh @@ -1,6 +1,10 @@ +#!/bin/sh + # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +CURR_PATH=$(cd $(dirname $0) && pwd -P) + # WASM application that uses WASI-NN /opt/wasi-sdk/bin/clang \ @@ -13,9 +17,25 @@ # TFLite models to use in the tests -cd models +cd ${CURR_PATH}/models python3 average.py python3 max.py python3 mult_dimension.py python3 mult_outputs.py python3 sum.py + +# Specific tests for TPU + +cd ${CURR_PATH} +/opt/wasi-sdk/bin/clang \ + -Wl,--allow-undefined \ + -Wl,--strip-all,--no-entry \ + --sysroot=/opt/wasi-sdk/share/wasi-sysroot \ + -I../include -I../src/utils \ + -o test_tensorflow_quantized.wasm \ + test_tensorflow_quantized.c utils.c + +cd ${CURR_PATH}/models +python3 quantized.py + +cd ${CURR_PATH} diff --git a/core/iwasm/libraries/wasi-nn/test/models/quantized.py b/core/iwasm/libraries/wasi-nn/test/models/quantized.py new file mode 100644 index 000000000..b195b319f --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/models/quantized.py @@ -0,0 +1,30 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +import tensorflow as tf +import numpy as np +import pathlib + +model = tf.keras.Sequential([ + tf.keras.layers.InputLayer(input_shape=[5, 5, 1]), + tf.keras.layers.AveragePooling2D( + pool_size=(5, 5), strides=None, padding="valid", data_format=None) + +]) + +def representative_dataset(): + for _ in range(1000): + data = np.random.randint(0, 25, (1, 5, 5, 1)) + yield [data.astype(np.float32)] + +converter = tf.lite.TFLiteConverter.from_keras_model(model) +converter.optimizations = [tf.lite.Optimize.DEFAULT] +converter.representative_dataset = representative_dataset +converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] +converter.inference_input_type = tf.uint8 # or tf.int8 +converter.inference_output_type = tf.uint8 # or tf.int8 +tflite_model = converter.convert() + +tflite_models_dir = pathlib.Path("./") +tflite_model_file = tflite_models_dir / "quantized_model.tflite" +tflite_model_file.write_bytes(tflite_model) diff --git a/core/iwasm/libraries/wasi-nn/test/test_tensorflow_quantized.c b/core/iwasm/libraries/wasi-nn/test/test_tensorflow_quantized.c new file mode 100644 index 000000000..3ed7c751e --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/test_tensorflow_quantized.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include + +#include "utils.h" +#include "logger.h" + +#undef EPSILON +#define EPSILON 1e-2 + +void +test_average_quantized(execution_target target) +{ + int dims[] = { 1, 5, 5, 1 }; + input_info input = create_input(dims); + + uint32_t output_size = 0; + float *output = + run_inference(target, input.input_tensor, input.dim, &output_size, + "./models/quantized_model.tflite", 1); + + NN_INFO_PRINTF("Output size: %d", output_size); + NN_INFO_PRINTF("Result: average is %f", output[0]); + // NOTE: 11.95 instead of 12 because of errors due quantization + assert(fabs(output[0] - 11.95) < EPSILON); + + free(input.dim); + free(input.input_tensor); + free(output); +} + +int +main() +{ + char *env = getenv("TARGET"); + if (env == NULL) { + NN_INFO_PRINTF("Usage:\n--env=\"TARGET=[cpu|gpu|tpu]\""); + return 1; + } + execution_target target; + if (strcmp(env, "cpu") == 0) + target = cpu; + else if (strcmp(env, "gpu") == 0) + target = gpu; + else if (strcmp(env, "tpu") == 0) + target = tpu; + else { + NN_ERR_PRINTF("Wrong target!"); + return 1; + } + NN_INFO_PRINTF("################### Testing quantized model..."); + test_average_quantized(target); + + NN_INFO_PRINTF("Tests: passed!"); + return 0; +} diff --git a/core/iwasm/libraries/wasi-nn/test/utils.c b/core/iwasm/libraries/wasi-nn/test/utils.c index e0704cab4..7b4f65d16 100644 --- a/core/iwasm/libraries/wasi-nn/test/utils.c +++ b/core/iwasm/libraries/wasi-nn/test/utils.c @@ -132,8 +132,8 @@ run_inference(execution_target target, float *input, uint32_t *input_size, *output_size = MAX_OUTPUT_TENSOR_SIZE - *output_size; if (wasm_get_output(ctx, i, &out_tensor[offset], output_size) != success) { - NN_ERR_PRINTF("Error when getting output."); - exit(1); + NN_ERR_PRINTF("Error when getting index %d.", i); + break; } offset += *output_size; diff --git a/core/iwasm/libraries/wasi-nn/test/utils.h b/core/iwasm/libraries/wasi-nn/test/utils.h index 6373be542..0b2328406 100644 --- a/core/iwasm/libraries/wasi-nn/test/utils.h +++ b/core/iwasm/libraries/wasi-nn/test/utils.h @@ -11,7 +11,7 @@ #include "wasi_nn.h" #define MAX_MODEL_SIZE 85000000 -#define MAX_OUTPUT_TENSOR_SIZE 200 +#define MAX_OUTPUT_TENSOR_SIZE 1000000 #define INPUT_TENSOR_DIMS 4 #define EPSILON 1e-8 diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h index d718a2d7d..c28a7b9be 100644 --- a/core/shared/platform/android/platform_internal.h +++ b/core/shared/platform/android/platform_internal.h @@ -139,16 +139,12 @@ seekdir(DIR *__dir, long __location); #endif -#if __ANDROID_API__ < 24 - ssize_t preadv(int __fd, const struct iovec *__iov, int __count, off_t __offset); ssize_t pwritev(int __fd, const struct iovec *__iov, int __count, off_t __offset); -#endif - #ifdef __cplusplus } #endif diff --git a/core/shared/platform/common/posix/posix_blocking_op.c b/core/shared/platform/common/posix/posix_blocking_op.c new file mode 100644 index 000000000..560828a06 --- /dev/null +++ b/core/shared/platform/common/posix/posix_blocking_op.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_extension.h" + +#ifdef OS_ENABLE_WAKEUP_BLOCKING_OP + +static bool g_blocking_op_inited = false; +static int g_blocking_op_signo = SIGUSR1; +static sigset_t g_blocking_op_sigmask; + +static void +blocking_op_sighandler(int signo) +{ + /* nothing */ +} + +void +os_set_signal_number_for_blocking_op(int signo) +{ + g_blocking_op_signo = signo; +} + +int +os_blocking_op_init() +{ + if (g_blocking_op_inited) { + return BHT_OK; + } + + sigemptyset(&g_blocking_op_sigmask); + sigaddset(&g_blocking_op_sigmask, g_blocking_op_signo); + + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = blocking_op_sighandler; + if (sigaction(g_blocking_op_signo, &sa, NULL)) { + return BHT_ERROR; + } + g_blocking_op_inited = true; + return BHT_OK; +} + +void +os_begin_blocking_op() +{ + pthread_sigmask(SIG_UNBLOCK, &g_blocking_op_sigmask, NULL); +} + +void +os_end_blocking_op() +{ + pthread_sigmask(SIG_BLOCK, &g_blocking_op_sigmask, NULL); +} + +int +os_wakeup_blocking_op(korp_tid tid) +{ + int ret = pthread_kill(tid, g_blocking_op_signo); + if (ret != 0) { + return BHT_ERROR; + } + return BHT_OK; +} + +#endif /* OS_ENABLE_WAKEUP_BLOCKING_OP */ diff --git a/core/shared/platform/common/posix/posix_sleep.c b/core/shared/platform/common/posix/posix_sleep.c new file mode 100644 index 000000000..fa0645037 --- /dev/null +++ b/core/shared/platform/common/posix/posix_sleep.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "platform_api_extension.h" + +int +os_usleep(uint32 usec) +{ + struct timespec ts; + int ret; + + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + ret = nanosleep(&ts, NULL); + return ret == 0 ? 0 : -1; +} diff --git a/core/shared/platform/common/posix/posix_socket.c b/core/shared/platform/common/posix/posix_socket.c index e33781d7d..9f5538b5c 100644 --- a/core/shared/platform/common/posix/posix_socket.c +++ b/core/shared/platform/common/posix/posix_socket.c @@ -53,7 +53,7 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr; bh_sockaddr->port = ntohs(addr->sin_port); - bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr); + bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr); bh_sockaddr->is_ipv4 = true; return BHT_OK; } @@ -65,12 +65,12 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, bh_sockaddr->port = ntohs(addr->sin6_port); - for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6) - / sizeof(bh_sockaddr->addr_bufer.ipv6[0]); + for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6) + / sizeof(bh_sockaddr->addr_buffer.ipv6[0]); i++) { uint16 part_addr = addr->sin6_addr.s6_addr[i * 2] | (addr->sin6_addr.s6_addr[i * 2 + 1] << 8); - bh_sockaddr->addr_bufer.ipv6[i] = ntohs(part_addr); + bh_sockaddr->addr_buffer.ipv6[i] = ntohs(part_addr); } bh_sockaddr->is_ipv4 = false; @@ -91,7 +91,7 @@ bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr, struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr; addr->sin_port = htons(bh_sockaddr->port); addr->sin_family = AF_INET; - addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4); + addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_buffer.ipv4); *socklen = sizeof(*addr); } #ifdef IPPROTO_IPV6 @@ -101,10 +101,10 @@ bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr, addr->sin6_port = htons(bh_sockaddr->port); addr->sin6_family = AF_INET6; - for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6) - / sizeof(bh_sockaddr->addr_bufer.ipv6[0]); + for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6) + / sizeof(bh_sockaddr->addr_buffer.ipv6[0]); i++) { - uint16 part_addr = htons(bh_sockaddr->addr_bufer.ipv6[i]); + uint16 part_addr = htons(bh_sockaddr->addr_buffer.ipv6[i]); addr->sin6_addr.s6_addr[i * 2] = 0xff & part_addr; addr->sin6_addr.s6_addr[i * 2 + 1] = (0xff00 & part_addr) >> 8; } @@ -275,6 +275,9 @@ os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, return -1; } } + else if (src_addr) { + memset(src_addr, 0, sizeof(*src_addr)); + } return ret; } diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 4fb566d6e..a7bdc6d10 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -39,6 +39,9 @@ os_thread_wrapper(void *arg) #ifdef OS_ENABLE_HW_BOUND_CHECK if (os_thread_signal_init(handler) != 0) return NULL; +#endif +#ifdef OS_ENABLE_WAKEUP_BLOCKING_OP + os_end_blocking_op(); #endif start_func(thread_arg); #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -509,8 +512,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 \ @@ -541,9 +544,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 { diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index 3fd1c258e..d72d48b53 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -102,6 +102,12 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 +#define OS_ENABLE_WAKEUP_BLOCKING_OP +#endif +void +os_set_signal_number_for_blocking_op(int signo); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/esp-idf/espidf_memmap.c b/core/shared/platform/esp-idf/espidf_memmap.c index 693094a63..0a1fd4fe4 100644 --- a/core/shared/platform/esp-idf/espidf_memmap.c +++ b/core/shared/platform/esp-idf/espidf_memmap.c @@ -5,16 +5,34 @@ #include "platform_api_vmcore.h" #include "platform_api_extension.h" +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) +#include "soc/mmu.h" +#include "rom/cache.h" + +#define MEM_DUAL_BUS_OFFSET (IRAM0_CACHE_ADDRESS_LOW - DRAM0_CACHE_ADDRESS_LOW) + +#define in_ibus_ext(addr) \ + (((uint32)addr >= IRAM0_CACHE_ADDRESS_LOW) \ + && ((uint32)addr < IRAM0_CACHE_ADDRESS_HIGH)) + +static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED; +#endif void * os_mmap(void *hint, size_t size, int prot, int flags) { if (prot & MMAP_PROT_EXEC) { +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + uint32_t mem_caps = MALLOC_CAP_SPIRAM; +#else + uint32_t mem_caps = MALLOC_CAP_EXEC; +#endif + // Memory allocation with MALLOC_CAP_EXEC will return 4-byte aligned // Reserve extra 4 byte to fixup alignment and size for the pointer to // the originally allocated address void *buf_origin = - heap_caps_malloc(size + 4 + sizeof(uintptr_t), MALLOC_CAP_EXEC); + heap_caps_malloc(size + 4 + sizeof(uintptr_t), mem_caps); if (!buf_origin) { return NULL; } @@ -25,19 +43,35 @@ os_mmap(void *hint, size_t size, int prot, int flags) uintptr_t *addr_field = buf_fixed - sizeof(uintptr_t); *addr_field = (uintptr_t)buf_origin; +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + return buf_fixed + MEM_DUAL_BUS_OFFSET; +#else return buf_fixed; +#endif } else { - return os_malloc(size); +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + uint32_t mem_caps = MALLOC_CAP_SPIRAM; +#else + uint32_t mem_caps = MALLOC_CAP_8BIT; +#endif + return heap_caps_malloc(size, mem_caps); } } void os_munmap(void *addr, size_t size) { + char *ptr = (char *)addr; + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + if (in_ibus_ext(ptr)) { + ptr -= MEM_DUAL_BUS_OFFSET; + } +#endif // We don't need special handling of the executable allocations // here, free() of esp-idf handles it properly - return os_free(addr); + return os_free(ptr); } int @@ -47,5 +81,34 @@ os_mprotect(void *addr, size_t size, int prot) } void -os_dcache_flush() -{} +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + IRAM_ATTR +#endif + os_dcache_flush() +{ +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + uint32_t preload; + extern void Cache_WriteBack_All(void); + + portENTER_CRITICAL(&s_spinlock); + + Cache_WriteBack_All(); + preload = Cache_Disable_ICache(); + Cache_Enable_ICache(preload); + + portEXIT_CRITICAL(&s_spinlock); +#endif +} + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) +void * +os_get_dbus_mirror(void *ibus) +{ + if (in_ibus_ext(ibus)) { + return (void *)((char *)ibus - MEM_DUAL_BUS_OFFSET); + } + else { + return ibus; + } +} +#endif diff --git a/core/shared/platform/esp-idf/espidf_socket.c b/core/shared/platform/esp-idf/espidf_socket.c index 9f441b712..83a24f435 100644 --- a/core/shared/platform/esp-idf/espidf_socket.c +++ b/core/shared/platform/esp-idf/espidf_socket.c @@ -30,7 +30,7 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen, assert(socklen >= sizeof(struct sockaddr_in)); bh_sockaddr->port = ntohs(addr->sin_port); - bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr); + bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr); bh_sockaddr->is_ipv4 = true; return BHT_OK; } diff --git a/core/shared/platform/esp-idf/shared_platform.cmake b/core/shared/platform/esp-idf/shared_platform.cmake index 13bc45dcb..8d7fe5d80 100644 --- a/core/shared/platform/esp-idf/shared_platform.cmake +++ b/core/shared/platform/esp-idf/shared_platform.cmake @@ -11,3 +11,9 @@ include_directories(${PLATFORM_SHARED_DIR}/../include) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE}) + +# If enable PSRAM of ESP32-S3, it had better to put AOT into PSRAM, so that +# users can use SRAM to for Wi-Fi/BLE and peripheral driver. +if(CONFIG_ESP32S3_SPIRAM_SUPPORT) + add_definitions(-DWASM_MEM_DUAL_BUS_MIRROR=1) +endif() diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h index 7b4789c99..50cabd344 100644 --- a/core/shared/platform/freebsd/platform_internal.h +++ b/core/shared/platform/freebsd/platform_internal.h @@ -101,6 +101,12 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 +#define OS_ENABLE_WAKEUP_BLOCKING_OP +#endif +void +os_set_signal_number_for_blocking_op(int signo); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 7029bb8d7..06bd9ee89 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -323,6 +323,34 @@ os_sem_getvalue(korp_sem *sem, int *sval); int os_sem_unlink(const char *name); +/** + * Initialize process-global state for os_wakeup_blocking_op. + */ +int +os_blocking_op_init(); + +/** + * Start accepting os_wakeup_blocking_op requests for the calling thread. + */ +void +os_begin_blocking_op(); + +/** + * Stop accepting os_wakeup_blocking_op requests for the calling thread. + */ +void +os_end_blocking_op(); + +/** + * Wake up the specified thread. + * + * For example, on posix-like platforms, this can be implemented by + * sending a signal (w/o SA_RESTART) which interrupts a blocking + * system call. + */ +int +os_wakeup_blocking_op(korp_tid tid); + /**************************************************** * Section 2 * * Socket support * @@ -342,7 +370,7 @@ typedef union { } bh_ip_addr_buffer_t; typedef struct { - bh_ip_addr_buffer_t addr_bufer; + bh_ip_addr_buffer_t addr_buffer; uint16 port; bool is_ipv4; } bh_sockaddr_t; diff --git a/core/shared/platform/include/platform_api_vmcore.h b/core/shared/platform/include/platform_api_vmcore.h index c2f03c9e5..15fc1d387 100644 --- a/core/shared/platform/include/platform_api_vmcore.h +++ b/core/shared/platform/include/platform_api_vmcore.h @@ -129,6 +129,11 @@ os_munmap(void *addr, size_t size); int os_mprotect(void *addr, size_t size, int prot); +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) +void * +os_get_dbus_mirror(void *ibus); +#endif + /** * Flush cpu data cache, in some CPUs, after applying relocation to the * AOT code, the code may haven't been written back to the cpu data cache, diff --git a/core/shared/platform/linux-sgx/sgx_socket.c b/core/shared/platform/linux-sgx/sgx_socket.c index afb6d6014..4d3f9a6b5 100644 --- a/core/shared/platform/linux-sgx/sgx_socket.c +++ b/core/shared/platform/linux-sgx/sgx_socket.c @@ -261,7 +261,7 @@ sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen, assert(socklen >= sizeof(struct sockaddr_in)); bh_sockaddr->port = ntohs(addr->sin_port); - bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr); + bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr); bh_sockaddr->is_ipv4 = true; return BHT_OK; } @@ -279,7 +279,7 @@ bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr, struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr; addr->sin_port = htons(bh_sockaddr->port); addr->sin_family = AF_INET; - addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4); + addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_buffer.ipv4); *socklen = sizeof(*addr); return BHT_OK; } diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index 8439f8723..337cdd9cc 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -115,6 +115,12 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 +#define OS_ENABLE_WAKEUP_BLOCKING_OP +#endif +void +os_set_signal_number_for_blocking_op(int signo); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/nuttx/nuttx_platform.c b/core/shared/platform/nuttx/nuttx_platform.c index 9cb123e01..0bd1f6808 100644 --- a/core/shared/platform/nuttx/nuttx_platform.c +++ b/core/shared/platform/nuttx/nuttx_platform.c @@ -10,6 +10,46 @@ #include #endif +#if defined(CONFIG_ARCH_CHIP_ESP32S3) +/* + * TODO: Move these methods below the operating system level + */ +#define MEM_DUAL_BUS_OFFSET (0x42000000 - 0x3C000000) +#define IRAM0_CACHE_ADDRESS_LOW 0x42000000 +#define IRAM0_CACHE_ADDRESS_HIGH 0x44000000 +#define IRAM_ATTR locate_data(".iram1") + +#define in_ibus_ext(addr) \ + (((uint32)addr >= IRAM0_CACHE_ADDRESS_LOW) \ + && ((uint32)addr < IRAM0_CACHE_ADDRESS_HIGH)) +void IRAM_ATTR +bus_sync(void) +{ + extern void cache_writeback_all(void); + extern uint32_t Cache_Disable_ICache(void); + extern void Cache_Enable_ICache(uint32_t autoload); + + irqstate_t flags; + uint32_t preload; + + flags = enter_critical_section(); + + cache_writeback_all(); + preload = Cache_Disable_ICache(); + Cache_Enable_ICache(preload); + + leave_critical_section(flags); +} +#else +#define MEM_DUAL_BUS_OFFSET (0) +#define IRAM0_CACHE_ADDRESS_LOW (0) +#define IRAM0_CACHE_ADDRESS_HIGH (0) +#define in_ibus_ext(addr) (0) +static void +bus_sync(void) +{} +#endif + int bh_platform_init() { @@ -47,6 +87,10 @@ os_dumps_proc_mem_info(char *out, unsigned int size) void * os_mmap(void *hint, size_t size, int prot, int flags) { +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + void *i_addr, *d_addr; +#endif + #if defined(CONFIG_ARCH_USE_TEXT_HEAP) if ((prot & MMAP_PROT_EXEC) != 0) { return up_textheap_memalign(sizeof(void *), size); @@ -55,6 +99,17 @@ os_mmap(void *hint, size_t size, int prot, int flags) if ((uint64)size >= UINT32_MAX) return NULL; + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + if ((prot & MMAP_PROT_EXEC) != 0) { + d_addr = malloc((uint32)size); + if (d_addr == NULL) { + return NULL; + } + i_addr = (void *)((uint8 *)d_addr + MEM_DUAL_BUS_OFFSET); + return in_ibus_ext(i_addr) ? i_addr : d_addr; + } +#endif return malloc((uint32)size); } @@ -67,7 +122,14 @@ os_munmap(void *addr, size_t size) return; } #endif - return free(addr); + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) + if (in_ibus_ext(addr)) { + free((void *)((uint8 *)addr - MEM_DUAL_BUS_OFFSET)); + return; + } +#endif + free(addr); } int @@ -78,7 +140,22 @@ os_mprotect(void *addr, size_t size, int prot) void os_dcache_flush() -{} +{ + bus_sync(); +} + +#if (WASM_MEM_DUAL_BUS_MIRROR != 0) +void * +os_get_dbus_mirror(void *ibus) +{ + if (in_ibus_ext(ibus)) { + return (void *)((uint8 *)ibus - MEM_DUAL_BUS_OFFSET); + } + else { + return ibus; + } +} +#endif /* If AT_FDCWD is provided, maybe we have openat family */ #if !defined(AT_FDCWD) diff --git a/core/shared/platform/nuttx/platform_internal.h b/core/shared/platform/nuttx/platform_internal.h index b5bbdacd0..97ab5f697 100644 --- a/core/shared/platform/nuttx/platform_internal.h +++ b/core/shared/platform/nuttx/platform_internal.h @@ -123,6 +123,12 @@ utimensat(int fd, const char *path, const struct timespec ts[2], int flag); DIR * fdopendir(int fd); +#if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 +#define OS_ENABLE_WAKEUP_BLOCKING_OP +#endif +void +os_set_signal_number_for_blocking_op(int signo); + #ifdef __cplusplus } #endif diff --git a/core/shared/utils/bh_atomic.h b/core/shared/utils/bh_atomic.h new file mode 100644 index 000000000..64dfee1b6 --- /dev/null +++ b/core/shared/utils/bh_atomic.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _BH_ATOMIC_H +#define _BH_ATOMIC_H + +#include "gnuc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Why don't we use C11 stdatomics here? + * + * Unlike C11 stdatomics, + * + * - bh_atomic_xxx_t is guaranteed to have the same size as the base type. + * Thus more friendly to our AOT conventions. + * + * - It's available for C++. + * Although C++23 will have C-compatible stdatomics.h, it isn't widely + * available yet. + */ + +/* + * Note about BH_ATOMIC_32_IS_ATOMIC + * + * If BH_ATOMIC_32_IS_ATOMIC == 0, BH_ATOMIC_xxx operations defined below + * are not really atomic and require an external lock. + * + * Expected usage is: + * + * bh_atomic_32_t var = 0; + * uint32 old; + * #if BH_ATOMIC_32_IS_ATOMIC == 0 + * lock(&some_lock); + * #endif + * old = BH_ATOMIC_32_FETCH_AND(var, 1); + * #if BH_ATOMIC_32_IS_ATOMIC == 0 + * unlock(&some_lock); + * #endif + */ + +typedef uint32 bh_atomic_32_t; + +#if defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4, 7) +#define CLANG_GCC_HAS_ATOMIC_BUILTIN +#endif +#elif defined(__clang__) +#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 0) +#define CLANG_GCC_HAS_ATOMIC_BUILTIN +#endif +#endif + +#if defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) +#define BH_ATOMIC_32_IS_ATOMIC 1 +#define BH_ATOMIC_32_LOAD(v) __atomic_load_n(&(v), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_32_FETCH_OR(v, val) \ + __atomic_fetch_or(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_32_FETCH_AND(v, val) \ + __atomic_fetch_and(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_32_FETCH_ADD(v, val) \ + __atomic_fetch_add(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_32_FETCH_SUB(v, val) \ + __atomic_fetch_sub(&(v), (val), __ATOMIC_SEQ_CST) +#else /* else of defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) */ +#define BH_ATOMIC_32_LOAD(v) (v) +#define BH_ATOMIC_32_FETCH_OR(v, val) nonatomic_32_fetch_or(&(v), val) +#define BH_ATOMIC_32_FETCH_AND(v, val) nonatomic_32_fetch_and(&(v), val) +#define BH_ATOMIC_32_FETCH_ADD(v, val) nonatomic_32_fetch_add(&(v), val) +#define BH_ATOMIC_32_FETCH_SUB(v, val) nonatomic_32_fetch_sub(&(v), val) + +static inline uint32 +nonatomic_32_fetch_or(bh_atomic_32_t *p, uint32 val) +{ + uint32 old = *p; + *p |= val; + return old; +} + +static inline uint32 +nonatomic_32_fetch_and(bh_atomic_32_t *p, uint32 val) +{ + uint32 old = *p; + *p &= val; + return old; +} + +static inline uint32 +nonatomic_32_fetch_add(bh_atomic_32_t *p, uint32 val) +{ + uint32 old = *p; + *p += val; + return old; +} + +static inline uint32 +nonatomic_32_fetch_sub(bh_atomic_32_t *p, uint32 val) +{ + uint32 old = *p; + *p -= val; + return old; +} + +/* The flag can be defined by the user if the platform + supports atomic access to uint32 aligned memory. */ +#ifdef WASM_UINT32_IS_ATOMIC +#define BH_ATOMIC_32_IS_ATOMIC 1 +#else /* else of WASM_UINT32_IS_ATOMIC */ +#define BH_ATOMIC_32_IS_ATOMIC 0 +#endif /* WASM_UINT32_IS_ATOMIC */ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of _BH_ATOMIC_H */ diff --git a/core/shared/utils/bh_common.c b/core/shared/utils/bh_common.c index aeeab26bd..7fe123c91 100644 --- a/core/shared/utils/bh_common.c +++ b/core/shared/utils/bh_common.c @@ -31,6 +31,10 @@ b_memcpy_wa(void *s1, unsigned int s1max, const void *s2, unsigned int n) unsigned int *p; char *ps; + if (n == 0) { + return 0; + } + if (pa > src) { pa -= 4; } diff --git a/core/shared/utils/bh_common.h b/core/shared/utils/bh_common.h index edb962eb1..adae722bb 100644 --- a/core/shared/utils/bh_common.h +++ b/core/shared/utils/bh_common.h @@ -12,25 +12,25 @@ extern "C" { #endif -#define bh_memcpy_s(dest, dlen, src, slen) \ - do { \ - int _ret = slen == 0 ? 0 : b_memcpy_s(dest, dlen, src, slen); \ - (void)_ret; \ - bh_assert(_ret == 0); \ +#define bh_memcpy_s(dest, dlen, src, slen) \ + do { \ + int _ret = b_memcpy_s(dest, dlen, src, slen); \ + (void)_ret; \ + bh_assert(_ret == 0); \ } while (0) -#define bh_memcpy_wa(dest, dlen, src, slen) \ - do { \ - int _ret = slen == 0 ? 0 : b_memcpy_wa(dest, dlen, src, slen); \ - (void)_ret; \ - bh_assert(_ret == 0); \ +#define bh_memcpy_wa(dest, dlen, src, slen) \ + do { \ + int _ret = b_memcpy_wa(dest, dlen, src, slen); \ + (void)_ret; \ + bh_assert(_ret == 0); \ } while (0) -#define bh_memmove_s(dest, dlen, src, slen) \ - do { \ - int _ret = slen == 0 ? 0 : b_memmove_s(dest, dlen, src, slen); \ - (void)_ret; \ - bh_assert(_ret == 0); \ +#define bh_memmove_s(dest, dlen, src, slen) \ + do { \ + int _ret = b_memmove_s(dest, dlen, src, slen); \ + (void)_ret; \ + bh_assert(_ret == 0); \ } while (0) #define bh_strcat_s(dest, dlen, src) \ diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h b/core/shared/utils/gnuc.h similarity index 100% rename from core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h rename to core/shared/utils/gnuc.h diff --git a/core/version.h b/core/version.h index de24b30bc..925779b31 100644 --- a/core/version.h +++ b/core/version.h @@ -7,5 +7,5 @@ #define _WAMR_VERSION_H_ #define WAMR_VERSION_MAJOR 1 #define WAMR_VERSION_MINOR 2 -#define WAMR_VERSION_PATCH 2 +#define WAMR_VERSION_PATCH 3 #endif diff --git a/doc/build_wamr.md b/doc/build_wamr.md index a9d337164..9938eadcb 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -94,7 +94,12 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_BUILD_WASI_NN**=1/0, default to disable if not set #### **Enable lib wasi-nn GPU mode** -- **WASI_NN_ENABLE_GPU**=1/0, default to disable if not set +- **WAMR_BUILD_WASI_NN_ENABLE_GPU**=1/0, default to disable if not set + +#### **Enable lib wasi-nn external delegate mode** +- **WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE**=1/0, default to disable if not set + +- **WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH**=Path to the external delegate shared library (e.g. `libedgetpu.so.1.0` for Coral USB) #### **Disable boundary check with hardware trap** - **WAMR_DISABLE_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform @@ -104,6 +109,10 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_DISABLE_STACK_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform, same as `WAMR_DISABLE_HW_BOUND_CHECK`. > Note: When boundary check with hardware trap is disabled, or `WAMR_DISABLE_HW_BOUND_CHECK` is set to 1, the native stack boundary check with hardware trap will be disabled too, no matter what value is set to `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. And when boundary check with hardware trap is enabled, the status of this feature is set according to the value of `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. +#### **Disable async wakeup of blocking operation** +- **WAMR_DISABLE_WAKEUP_BLOCKING_OP**=1/0, default to enable if supported by the platform +> Note: The feature helps async termination of blocking threads. If you disable it, the runtime can wait for termination of blocking threads possibly forever. + #### **Enable tail call feature** - **WAMR_BUILD_TAIL_CALL**=1/0, default to disable if not set diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index 050384027..b83817589 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -258,68 +258,69 @@ We can't pass structure data or class objects through the pointer since the memo ## Execute wasm functions in multiple threads -The `exec_env` is not thread safety, it will cause unexpected behavior if the same `exec_env` is used in multiple threads. However, we've provided two ways to execute wasm functions concurrently: +It isn't safe to use an `exec_env` object in multiple threads concurrently. +To run a multi-threaded application, you basically need a separate `exec_env` +for each threads. -- You can use `pthread` APIs in your wasm application, see [pthread library](./pthread_library.md) for more details. +### Approaches to manage `exec_env` objects and threads -- The `spawn exec_env` and `spawn thread` APIs are available, you can use these APIs to manage the threads in native: +WAMR supports two approaches to manage `exec_env` and threads as described +below. While they are not exclusive, you usually only need to use one of +them. - *spawn exec_env:* +#### Make your WASM application manage threads - `spawn exec_env` API spawns a `new_exec_env` base on the original `exec_env`, use can use it in other threads: + You can make your WASM application spawn threads by itself, + typically using `pthread` APIs like `pthread_create`. + See [pthread library](./pthread_library.md) and + [pthread implementations](./pthread_impls.md) for more details. + In this case, WAMR manages `exec_env` for the spawned threads. + +#### Make your embedder manage threads + + The `spawn exec_env` and `spawn thread` APIs are available for the embedder. + You can use these APIs to manage the threads. + See [Thread related embedder API](./embed_wamr_spawn_api.md) for details. + +### Other notes about threads + +* You can manage the maximum number of threads ```C - new_exec_env = wasm_runtime_spawn_exec_env(exec_env); - - /* Then you can use new_exec_env in your new thread */ - module_inst = wasm_runtime_get_module_inst(new_exec_env); - func_inst = wasm_runtime_lookup_function(module_inst, ...); - wasm_runtime_call_wasm(new_exec_env, func_inst, ...); - - /* you need to use this API to manually destroy the spawned exec_env */ - wasm_runtime_destroy_spawned_exec_env(new_exec_env); + init_args.max_thread_num = THREAD_NUM; + /* If this init argument is not set, the default maximum thread number is 4 */ ``` - *spawn thread:* +* To share memory among threads, you need to build your WASM application with shared memory - You can also use `spawn thread` API to avoid manually manage the spawned exec_env: - - ```C - wasm_thread_t wasm_tid; - void *wamr_thread_cb(wasm_exec_env_t exec_env, void *arg) - { - module_inst = wasm_runtime_get_module_inst(exec_env); - func_inst = wasm_runtime_lookup_function(module_inst, ...); - wasm_runtime_call_wasm(exec_env, func_inst, ...); - } - wasm_runtime_spawn_thread(exec_env, &wasm_tid, wamr_thread_cb, NULL); - /* Use wasm_runtime_join_thread to join the spawned thread */ - wasm_runtime_join_thread(wasm_tid, NULL); - ``` - -**Note1: You can manage the maximum number of threads can be created:** - -```C -init_args.max_thread_num = THREAD_NUM; -/* If this init argument is not set, the default maximum thread number is 4 */ -``` - -**Note2: The wasm application should be built with `--shared-memory` and `-pthread` enabled:** - -```bash - /opt/wasi-sdk/bin/clang -o test.wasm test.c -nostdlib -pthread \ - -Wl,--shared-memory,--max-memory=131072 \ - -Wl,--no-entry,--export=__heap_base,--export=__data_end \ - -Wl,--export=__wasm_call_ctors,--export=${your_func_name} -``` - - **Note3: The pthread library feature should be enabled while building the runtime:** + For example, it can be done with `--shared-memory` and `-pthread`. ```bash - cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 + /opt/wasi-sdk/bin/clang -o test.wasm test.c -nostdlib -pthread \ + -Wl,--shared-memory,--max-memory=131072 \ + -Wl,--no-entry,--export=__heap_base,--export=__data_end \ + -Wl,--export=__wasm_call_ctors,--export=${your_func_name} ``` -[Here](../samples/spawn-thread) is a sample to show how to use these APIs. +* The corresponding threading feature should be enabled while building the runtime + + - WAMR lib-pthread (legacy) + + ```bash + cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 + ``` + + - wasi-threads + + ```bash + cmake .. -DWAMR_BUILD_LIB_WASI_THREADS=1 + ``` + + - `wasm_runtime_spawn_exec_env` and `wasm_runtime_spawn_thread` + + ```bash + cmake .. -DWAMR_BUILD_THREAD_MGR=1 -DWAMR_BUILD_SHARED_MEMORY=1 + ``` ## The deinitialization procedure diff --git a/doc/embed_wamr_spawn_api.md b/doc/embed_wamr_spawn_api.md new file mode 100644 index 000000000..f0e637f30 --- /dev/null +++ b/doc/embed_wamr_spawn_api.md @@ -0,0 +1,38 @@ +# Thread related embedder API + +This document explains `wasm_runtime_spawn_exec_env` and +`wasm_runtime_spawn_thread`. +[Here](../samples/spawn-thread) is a sample to show how to use these APIs. + + * spawn exec_env + + `spawn exec_env` API creates a new `exec_env` based on the original `exec_env`. You can use it in other threads. It's up to the embedder how to manage host threads to run the new `exec_env`. + + ```C + new_exec_env = wasm_runtime_spawn_exec_env(exec_env); + + /* Then you can use new_exec_env in your new thread */ + module_inst = wasm_runtime_get_module_inst(new_exec_env); + func_inst = wasm_runtime_lookup_function(module_inst, ...); + wasm_runtime_call_wasm(new_exec_env, func_inst, ...); + + /* you need to use this API to manually destroy the spawned exec_env */ + wasm_runtime_destroy_spawned_exec_env(new_exec_env); + ``` + + * spawn thread + + Alternatively, you can use `spawn thread` API to avoid managing the extra exec_env and the corresponding host thread manually: + + ```C + wasm_thread_t wasm_tid; + void *wamr_thread_cb(wasm_exec_env_t exec_env, void *arg) + { + module_inst = wasm_runtime_get_module_inst(exec_env); + func_inst = wasm_runtime_lookup_function(module_inst, ...); + wasm_runtime_call_wasm(exec_env, func_inst, ...); + } + wasm_runtime_spawn_thread(exec_env, &wasm_tid, wamr_thread_cb, NULL); + /* Use wasm_runtime_join_thread to join the spawned thread */ + wasm_runtime_join_thread(wasm_tid, NULL); + ``` diff --git a/doc/export_native_api.md b/doc/export_native_api.md index b87d92552..e293e5c0d 100644 --- a/doc/export_native_api.md +++ b/doc/export_native_api.md @@ -261,4 +261,32 @@ wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size) ``` +## Native API implementation notes +### Async thread termination + +When threading support is enabled, a thread can be requested to terminate +itself either explicitly by the `wasm_runtime_terminate` API or implicitly +by cluster-wide activities like WASI `proc_exit`. +If a call to your native function can take long or even forever, +you should make it to respond to termination requests in a timely manner. +There are a few implementation approaches for that: + +* Design your API so that it always returns in a timely manner. + This is the most simple approach when possible. + +* Make your native function check the cluster state by calling + `wasm_cluster_is_thread_terminated` from time to time. + If `wasm_cluster_is_thread_terminated` returns true, make your + native function return. + Note: as of writing this, `wasm_cluster_is_thread_terminated` is not + exported as a runtime API. + +* If your native function is a simple wrapper of blocking system call, + you can probably use the `wasm_runtime_begin_blocking_op` and + `wasm_runtime_end_blocking_op` runtime API. + See the comment in `wamr_export.h` for details. + +* If your native function is very complex, it might be simpler to put the + guts of it into a separate worker process so that it can be cleaned up + by simply killing it. diff --git a/doc/perf_tune.md b/doc/perf_tune.md index 05a6433a7..2cc428984 100644 --- a/doc/perf_tune.md +++ b/doc/perf_tune.md @@ -72,3 +72,18 @@ wasm_runtime_dump_pgo_prof_data_to_buf(wasm_module_inst_t module_inst, char *buf 6. Run the optimized aot_file: `iwasm `. Developer can refer to the `test_pgo.sh` files under each benchmark folder for more details, e.g. [test_pgo.sh](../tests/benchmarks/coremark/test_pgo.sh) of CoreMark benchmark. + +## 6. Disable the memory boundary check + +Please notice that this method is not a general solution since it may lead to security issues. And only boost the performance for some platforms in AOT mode and don't support hardware trap for memory boundary check. + +1. Build WAMR with `-DWAMR_CONFIGUABLE_BOUNDS_CHECKS=1` option. + +2. Compile AOT module by wamrc with `--bounds-check=0` option. + +3. Run the AOT module by iwasm with `--disable-bounds-checks` option. + +> Note: The size of AOT file will be much smaller than the default, and some tricks are possible such as let the wasm application access the memory of host os directly. +Please notice that if this option is enabled, the wasm spec test will fail since it requires the memory boundary check. For example, the runtime will crash when accessing the memory out of the boundary in some cases instead of throwing an exception as the spec requires. + +You should only use this method for well tested wasm applications and make sure the memory access is safe. diff --git a/doc/source_debugging.md b/doc/source_debugging.md index a9fa09307..513185fe8 100644 --- a/doc/source_debugging.md +++ b/doc/source_debugging.md @@ -44,7 +44,7 @@ iwasm -g=127.0.0.1:1234 test.wasm ``` bash git clone --branch release/13.x --depth=1 https://github.com/llvm/llvm-project cd llvm-project -git apply ${WAMR_ROOT}/build-scripts/lldb-wasm.patch +git apply ${WAMR_ROOT}/build-scripts/lldb_wasm.patch mkdir build-lldb cmake -S ./llvm -B build-lldb \ -G Ninja \ diff --git a/doc/xip.md b/doc/xip.md index d6c5a3701..a76c7615c 100644 --- a/doc/xip.md +++ b/doc/xip.md @@ -7,8 +7,125 @@ Some IoT devices may require to run the AOT file from flash or ROM which is read The XIP file is an AOT file without (or with few) relocations to patch the AOT code (or text section). Developer can use the option `--enable-indirect-mode --disable-llvm-intrinsics` for wamrc to generate the AOT file, e.g.: ```bash wamrc --enable-indirect-mode --disable-llvm-intrinsics -o +or +wamrc --xip -o ``` +Note: --xip is a short option for --enable-indirect-mode --disable-llvm-intrinsics + ## Known issues There may be some relocations to the ".rodata" like sections which require to patch the AOT code. More work will be done to resolve it in the future. + +## Tuning the XIP intrinsic functions + +WAMR provides a default mapping table for some targets, but it may not be the best one for your target. And it doesn't cover all the supported targets. + +So, wamrc provides the option `--enable-builtin-intrinsics=` to make it possible to tune the intrinsic functions for your target. + +Firstly, you should understand why we don't use the LLVM intrinsic functions directly. The reason is that the LLVM intrinsic functions can't map to the native instructions directly, e.g. the LLVM intrinsic function `i32.div_s` can't map to the native instruction if the target doesn't support the division instruction, it will be translated to a function call to the runtime function from libgcc/compiler-rt. This will cause the AOT code to have the relocations to the libgcc/compiler-rt, which is not acceptable for the XIP feature. + +So, we need to replace the LLVM intrinsic functions with the runtime self implemented functions, which can be called through the function pointer table (--enable-indirect-mode) and don't have the relocations to the libgcc/compiler-rt (--disable-llvm-intrinsics). + +Available intrinsic functions for tuning: + +| LLVM intrinsic function | Explanation | +| --- | --- | +| llvm.experimental.constrained.fadd.f32 | float32 add | +| llvm.experimental.constrained.fadd.f64 | float64 add | +| llvm.experimental.constrained.fsub.f32 | float32 sub | +| llvm.experimental.constrained.fsub.f64 | float64 sub | +| llvm.experimental.constrained.fmul.f32 | float32 mul | +| llvm.experimental.constrained.fmul.f64 | float64 mul | +| llvm.experimental.constrained.fdiv.f32 | float32 div | +| llvm.experimental.constrained.fdiv.f64 | float64 div | +| llvm.fabs.f32 | float32 abs | +| llvm.fabs.f64 | float64 abs | +| llvm.ceil.f32 | float32 ceil | +| llvm.ceil.f64 | float64 ceil | +| llvm.floor.f32 | float32 floor | +| llvm.floor.f64 | float64 floor | +| llvm.trunc.f32 | float32 trunc | +| llvm.trunc.f64 | float64 trunc | +| llvm.rint.f32 | float32 rint | +| llvm.rint.f64 | float64 rint | +| llvm.sqrt.f32 | float32 sqrt | +| llvm.sqrt.f64 | float64 sqrt | +| llvm.copysign.f32 | float32 copysign | +| llvm.copysign.f64 | float64 copysign | +| llvm.minnum.f32 | float32 minnum | +| llvm.minnum.f64 | float64 minnum | +| llvm.maxnum.f32 | float32 maxnum | +| llvm.maxnum.f64 | float64 maxnum | +| llvm.ctlz.i32 | int32 count leading zeros | +| llvm.ctlz.i64 | int64 count leading zeros | +| llvm.cttz.i32 | int32 count trailing zeros | +| llvm.cttz.i64 | int64 count trailing zeros | +| llvm.ctpop.i32 | int32 count population | +| llvm.ctpop.i64 | int64 count population | +| f64_convert_i32_s | int32 to float64 | +| f64_convert_i32_u | uint32 to float64 | +| f32_convert_i32_s | int32 to float32 | +| f32_convert_i32_u | uint32 to float32 | +| f64_convert_i64_s | int64 to float64 | +| f64_convert_i64_u | uint64 to float64 | +| f32_convert_i64_s | int64 to float32 | +| f32_convert_i64_u | uint64 to float32 | +| i32_trunc_f32_s | float32 to int32 | +| i32_trunc_f32_u | float32 to uint32 | +| i32_trunc_f64_s | float64 to int32 | +| i32_trunc_f64_u | float64 to uint32 | +| i64_trunc_f64_s | float64 to int64 | +| i64_trunc_f64_u | float64 to uint64 | +| i64_trunc_f32_s | float32 to int64 | +| i64_trunc_f32_u | float32 to uint64 | +| f32_demote_f64 | float64 to float32 | +| f64_promote_f32 | float32 to float64 | +| f32_cmp | float32 compare | +| f64_cmp | float64 compare | +| i64.div_s | int64 div | +| i64.div_u | uint64 div | +| i32.div_s | int32 div | +| i32.div_u | uint32 div | +| i64.rem_s | int64 rem | +| i64.rem_u | uint64 rem | +| i32.rem_s | int32 rem | +| i32.rem_u | uint32 rem | +| i64.or | int64 or | +| i64.and | int64 and | +| i32.const | emit i32 const into constant table | +| i64.const | emit i64 const into constant table | +| f32.const | emit f32 const into constant table | +| f64.const | emit f64 const into constant table | + +And also provide combined intrinsic functions to simplify the tuning: + +* all: all the above intrinsic functions +* i32.common: i32.div_s, i32.div_u, i32.rem_s, i32.rem_u +* i64.common: i64.div_s, i64.div_u, i64.rem_s, i64.rem_u, i64.or, i64.and +* f32.common: f32_cmp, llvm.experimental.constrained.fadd.f32, llvm.experimental.constrained.fsub.f32, llvm.experimental.constrained.fmul.f32, llvm.experimental.constrained.fdiv.f32, llvm.fabs.f32, llvm.ceil.f32, llvm.floor.f32, llvm.trunc.f32, llvm.rint.f32, llvm.sqrt.f32, llvm.copysign.f32, llvm.minnum.f32, llvm.maxnum.f32 +* f64.common: f32_demote_f64, f64_promote_f32, f64_cmp, llvm.experimental.constrained.fadd.f64, llvm.experimental.constrained.fsub.f64, llvm.experimental.constrained.fmul.f64, llvm.experimental.constrained.fdiv.f64, llvm.fabs.f64, llvm.ceil.f64, llvm.floor.f64, llvm.trunc.f64, llvm.rint.f64, llvm.sqrt.f64, llvm.copysign.f64, llvm.minnum.f64, llvm.maxnum.f64 +* f32xi32: i32_trunc_f32_s, i32_trunc_f32_u, f32_convert_i32_s, f32_convert_i32_u +* f64xi32: i32_trunc_f64_s, i32_trunc_f64_u, f64_convert_i32_s, f64_convert_i32_u +* f32xi64: i64_trunc_f32_s, i64_trunc_f32_u, f32_convert_i64_s, f32_convert_i64_u +* f64xi64: i64_trunc_f64_s, i64_trunc_f64_u, f64_convert_i64_s, f64_convert_i64_u +* constop: i32.const, i64.const, f32.const, f64.const +* fpxint: f32xi32, f64xi32, f32xi64, f64xi64 +* fp.common: f32.common, f64.common + + +### Example + +For ARM Cortex-M55, since it has double precision floating point unit, so it can support f32/f64 operations. But as a 32-bit MCU, it can only support 32-bit integer operations. So we can use the following command to generate the XIP binary: + +``` +wamrc --target=thumbv8m.main --cpu=cortex-m55 --xip --enable-builtin-intrinsics=i64.common -o hello.aot hello.wasm +``` + +For ARM Cortex-M3, since it has no floating point unit, and it can only support 32-bit integer operations. So we can use the following command to generate the XIP binary: + +``` +wamrc --target=thumbv7m --cpu=cortex-m3 --xip --enable-builtin-intrinsics=i64.common,fp.common,fpxint -o hello.aot hello.wasm +``` + +Other platforms can be tuned in the same way, which intrinsic should be enabled depends on the target platform's hardware capability. diff --git a/language-bindings/python/src/wamr/wamrapi/wamr.py b/language-bindings/python/src/wamr/wamrapi/wamr.py index abbd23227..1bd6e547d 100644 --- a/language-bindings/python/src/wamr/wamrapi/wamr.py +++ b/language-bindings/python/src/wamr/wamrapi/wamr.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception from ctypes import Array +from ctypes import addressof from ctypes import c_char from ctypes import c_uint from ctypes import c_uint8 @@ -10,6 +11,8 @@ from ctypes import cast from ctypes import create_string_buffer from ctypes import POINTER from ctypes import pointer +from typing import List +from typing import Tuple from wamr.wamrapi.iwasm import String from wamr.wamrapi.iwasm import Alloc_With_Pool from wamr.wamrapi.iwasm import RuntimeInitArgs @@ -31,6 +34,14 @@ from wamr.wamrapi.iwasm import wasm_runtime_module_malloc from wamr.wamrapi.iwasm import wasm_runtime_module_free from wamr.wamrapi.iwasm import wasm_runtime_register_natives from wamr.wamrapi.iwasm import NativeSymbol +from wamr.wamrapi.iwasm import wasm_runtime_start_debug_instance +from wamr.wamrapi.iwasm import wasm_runtime_call_indirect +from wamr.wamrapi.iwasm import wasm_runtime_get_module_inst +from wamr.wamrapi.iwasm import wasm_runtime_addr_app_to_native +from wamr.wamrapi.iwasm import wasm_runtime_addr_native_to_app +from wamr.wamrapi.iwasm import wasm_runtime_set_wasi_args + +ID_TO_EXEC_ENV_MAPPING = {} class Engine: @@ -43,16 +54,26 @@ class Engine: print("deleting Engine") wasm_runtime_destroy() - def _get_init_args(self, heap_size: int = 1024 * 512) -> RuntimeInitArgs: + def _get_init_args( + self, + heap_size: int = 1024 * 1024 * 2, + ip_addr: str = "127.0.0.1", + instance_port: int = 1234, + ) -> RuntimeInitArgs: init_args = RuntimeInitArgs() init_args.mem_alloc_type = Alloc_With_Pool init_args.mem_alloc_option.pool.heap_buf = cast( (c_char * heap_size)(), c_void_p ) init_args.mem_alloc_option.pool.heap_size = heap_size + # Debug port setting + init_args.ip_addr = bytes(ip_addr, "utf-8") + init_args.instance_port = instance_port return init_args - def register_natives(self, module_name: str, native_symbols: list[NativeSymbol]) -> None: + def register_natives( + self, module_name: str, native_symbols: List[NativeSymbol] + ) -> None: module_name = String.from_param(module_name) # WAMR does not copy the symbols. We must store them. for native in native_symbols: @@ -62,12 +83,13 @@ class Engine: module_name, cast( (NativeSymbol * len(native_symbols))(*native_symbols), - POINTER(NativeSymbol) + POINTER(NativeSymbol), ), - len(native_symbols) + len(native_symbols), ): raise Exception("Error while registering symbols") + class Module: __create_key = object() @@ -86,7 +108,7 @@ class Module: print("deleting Module") wasm_runtime_unload(self.module) - def _create_module(self, fp: str) -> tuple[wasm_module_t, Array[c_uint]]: + def _create_module(self, fp: str) -> Tuple[wasm_module_t, "Array[c_uint]"]: with open(fp, "rb") as f: data = f.read() data = (c_uint8 * len(data))(*data) @@ -99,14 +121,52 @@ class Module: class Instance: - def __init__(self, module: Module, stack_size: int = 65536, heap_size: int = 16384): + def __init__( + self, + module: Module, + stack_size: int = 65536, + heap_size: int = 16384, + dir_list: List[str] | None = None, + preinitialized_module_inst: wasm_module_inst_t | None = None, + ): + # Store module ensures GC does not remove it self.module = module - self.module_inst = self._create_module_inst(module, stack_size, heap_size) + if dir_list: + self._set_wasi_args(module, dir_list) + if preinitialized_module_inst is None: + self.module_inst = self._create_module_inst(module, stack_size, heap_size) + else: + self.module_inst = preinitialized_module_inst def __del__(self): print("deleting Instance") wasm_runtime_deinstantiate(self.module_inst) + def _set_wasi_args(self, module: Module, dir_list: List[str]) -> None: + LP_c_char = POINTER(c_char) + LP_LP_c_char = POINTER(LP_c_char) + + p = (LP_c_char * len(dir_list))() + for i, dir in enumerate(dir_list): + enc_dir = dir.encode("utf-8") + p[i] = create_string_buffer(enc_dir) + + na = cast(p, LP_LP_c_char) + wasm_runtime_set_wasi_args( + module.module, na, len(dir_list), None, 0, None, 0, None, 0 + ) + + def _create_module_inst( + self, module: Module, stack_size: int, heap_size: int + ) -> wasm_module_inst_t: + error_buf = create_string_buffer(128) + module_inst = wasm_runtime_instantiate( + module.module, stack_size, heap_size, error_buf, len(error_buf) + ) + if not module_inst: + raise Exception("Error while creating module instance") + return module_inst + def malloc(self, nbytes: int, native_handler) -> c_uint: return wasm_runtime_module_malloc(self.module_inst, nbytes, native_handler) @@ -119,31 +179,70 @@ class Instance: raise Exception("Error while looking-up function") return func - def _create_module_inst(self, module: Module, stack_size: int, heap_size: int) -> wasm_module_inst_t: - error_buf = create_string_buffer(128) - module_inst = wasm_runtime_instantiate( - module.module, stack_size, heap_size, error_buf, len(error_buf) - ) - if not module_inst: - raise Exception("Error while creating module instance") - return module_inst + def native_addr_to_app_addr(self, native_addr) -> c_void_p: + return wasm_runtime_addr_native_to_app(self.module_inst, native_addr) + + def app_addr_to_native_addr(self, app_addr) -> c_void_p: + return wasm_runtime_addr_app_to_native(self.module_inst, app_addr) class ExecEnv: def __init__(self, module_inst: Instance, stack_size: int = 65536): self.module_inst = module_inst self.exec_env = self._create_exec_env(module_inst, stack_size) + self.env = addressof(self.exec_env.contents) + self.own_c = True + + ID_TO_EXEC_ENV_MAPPING[str(self.env)] = self def __del__(self): - print("deleting ExecEnv") - wasm_runtime_destroy_exec_env(self.exec_env) + if self.own_c: + print("deleting ExecEnv") + wasm_runtime_destroy_exec_env(self.exec_env) + del ID_TO_EXEC_ENV_MAPPING[str(self.env)] + + def _create_exec_env( + self, module_inst: Instance, stack_size: int + ) -> wasm_exec_env_t: + exec_env = wasm_runtime_create_exec_env(module_inst.module_inst, stack_size) + if not exec_env: + raise Exception("Error while creating execution environment") + return exec_env def call(self, func: wasm_function_inst_t, argc: int, argv: "POINTER[c_uint]"): if not wasm_runtime_call_wasm(self.exec_env, func, argc, argv): raise Exception("Error while calling function") - def _create_exec_env(self, module_inst: Instance, stack_size: int) -> wasm_exec_env_t: - exec_env = wasm_runtime_create_exec_env(module_inst.module_inst, stack_size) - if not exec_env: - raise Exception("Error while creating execution environment") - return exec_env + def get_module_inst(self) -> Instance: + return self.module_inst + + def start_debugging(self) -> int: + return wasm_runtime_start_debug_instance(self.exec_env) + + def call_indirect(self, element_index: int, argc: int, argv: "POINTER[c_uint]"): + if not wasm_runtime_call_indirect(self.exec_env, element_index, argc, argv): + raise Exception("Error while calling function") + + @staticmethod + def wrap(env: int) -> "ExecEnv": + if str(env) in ID_TO_EXEC_ENV_MAPPING: + return ID_TO_EXEC_ENV_MAPPING[str(env)] + return InternalExecEnv(env) + + +class InternalExecEnv(ExecEnv): + """ + Generate Python ExecEnv-like object from a `wasm_exec_env_t` index. + """ + + def __init__(self, env: int): + self.env = env + self.exec_env = cast(env, wasm_exec_env_t) + self.module_inst = Instance( + module=object(), + preinitialized_module_inst=wasm_runtime_get_module_inst(self.exec_env), + ) + ID_TO_EXEC_ENV_MAPPING[str(env)] = self + + def __del__(self): + del ID_TO_EXEC_ENV_MAPPING[str(self.env)] diff --git a/language-bindings/python/utils/create_lib.sh b/language-bindings/python/utils/create_lib.sh index b7e10d3ee..801186e97 100755 --- a/language-bindings/python/utils/create_lib.sh +++ b/language-bindings/python/utils/create_lib.sh @@ -12,7 +12,12 @@ WAMR_BUILD_PLATFORM=${WAMR_BUILD_PLATFORM:-${UNAME}} cd ${ROOT_DIR}/product-mini/platforms/${WAMR_BUILD_PLATFORM} mkdir -p build && cd build -cmake .. +cmake \ + -DWAMR_BUILD_DEBUG_INTERP=1 \ + -DWAMR_BUILD_LIB_PTHREAD=1 \ + -DWAMR_BUILD_LIB_WASI_THREADS=1 \ + -DWAMR_BUILD_LIB_WASI=1 \ + .. make -j case ${UNAME} in diff --git a/language-bindings/python/wamr-api/README.md b/language-bindings/python/wamr-api/README.md index 801c8aa1e..236150ce4 100644 --- a/language-bindings/python/wamr-api/README.md +++ b/language-bindings/python/wamr-api/README.md @@ -22,10 +22,7 @@ bash language-bindings/python/utils/create_lib.sh This will build and copy libiwasm into the package. -## Examples +## Samples -There is a [simple example](./samples/main.py) to show how to use bindings. - -``` -python samples/main.py -``` +- **[basic](./samples/basic)**: Demonstrating how to use basic python bindings. +- **[native-symbol](./samples/native-symbol)**: Desmostrate how to call WASM from Python and how to export Python functions into WASM. diff --git a/language-bindings/python/wamr-api/samples/compile.sh b/language-bindings/python/wamr-api/samples/basic/compile.sh similarity index 100% rename from language-bindings/python/wamr-api/samples/compile.sh rename to language-bindings/python/wamr-api/samples/basic/compile.sh diff --git a/language-bindings/python/wamr-api/samples/main.py b/language-bindings/python/wamr-api/samples/basic/main.py similarity index 100% rename from language-bindings/python/wamr-api/samples/main.py rename to language-bindings/python/wamr-api/samples/basic/main.py diff --git a/language-bindings/python/wamr-api/samples/sum.c b/language-bindings/python/wamr-api/samples/basic/sum.c similarity index 100% rename from language-bindings/python/wamr-api/samples/sum.c rename to language-bindings/python/wamr-api/samples/basic/sum.c diff --git a/language-bindings/python/wamr-api/samples/native-symbol/README.md b/language-bindings/python/wamr-api/samples/native-symbol/README.md new file mode 100644 index 000000000..75d4fab46 --- /dev/null +++ b/language-bindings/python/wamr-api/samples/native-symbol/README.md @@ -0,0 +1,44 @@ +# Native Symbol + +This sample demonstrates how to declare a Python function as `NativeSymbol`. + +Steps of the example: +1. Load WASM from Python +2. Call `c_func` from WASM. +3. `c_func` calls `python_func` from Python. +4. `python_func` calls `add` from WASM. +5. Result shown by Python. + +## Build + +Follow instructions [build wamr Python package](../../README.md). + +Compile WASM app example, + +```sh +./compile.sh +``` + +## Run sample + +```sh +python main.py +``` + +Output: + +``` +python: calling c_func(10) +c: in c_func with input: 10 +c: calling python_func(11) +python: in python_func with input: 11 +python: calling add(11, 1000) +python: result from add: 1011 +c: result from python_func: 1012 +c: returning 1013 +python: result from c_func: 1013 +deleting ExecEnv +deleting Instance +deleting Module +deleting Engine +``` diff --git a/language-bindings/python/wamr-api/samples/native-symbol/compile.sh b/language-bindings/python/wamr-api/samples/native-symbol/compile.sh new file mode 100755 index 000000000..4e504b018 --- /dev/null +++ b/language-bindings/python/wamr-api/samples/native-symbol/compile.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +/opt/wasi-sdk/bin/clang \ + -O0 -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--export=main -Wl,--export=__main_argc_argv \ + -Wl,--export=__data_end -Wl,--export=__heap_base \ + -Wl,--strip-all,--no-entry \ + -Wl,--allow-undefined \ + -Wl,--export=c_func\ + -Wl,--export=add\ + -o func.wasm func.c diff --git a/language-bindings/python/wamr-api/samples/native-symbol/func.c b/language-bindings/python/wamr-api/samples/native-symbol/func.c new file mode 100644 index 000000000..4411a6b2c --- /dev/null +++ b/language-bindings/python/wamr-api/samples/native-symbol/func.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +int +python_func(int val); + +int +add(int val1, int val2) +{ + return val1 + val2; +} + +int +c_func(int val) +{ + printf("c: in c_func with input: %d\n", val); + printf("c: calling python_func(%d)\n", val + 1); + int res = python_func(val + 1); + printf("c: result from python_func: %d\n", res); + printf("c: returning %d\n", res + 1); + return res + 1; +} + +int +main() +{} diff --git a/language-bindings/python/wamr-api/samples/native-symbol/main.py b/language-bindings/python/wamr-api/samples/native-symbol/main.py new file mode 100644 index 000000000..3871ef139 --- /dev/null +++ b/language-bindings/python/wamr-api/samples/native-symbol/main.py @@ -0,0 +1,59 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +from wamr.wamrapi.wamr import Engine, Module, Instance, ExecEnv +from ctypes import c_uint +import pathlib +from ctypes import c_int32 +from ctypes import c_uint +from ctypes import c_void_p +from ctypes import cast +from ctypes import CFUNCTYPE + +from wamr.wamrapi.iwasm import NativeSymbol +from wamr.wamrapi.iwasm import String +from wamr.wamrapi.wamr import ExecEnv + +def python_func(env: int, value: int) -> int: + print("python: in python_func with input:", value) + # Example of generating ExecEnv from `wasm_exec_env_t`` + exec_env = ExecEnv.wrap(env) + add = exec_env.get_module_inst().lookup_function("add") + const = 1000 + argv = (c_uint * 2)(value, const) + print(f"python: calling add({value}, {const})") + exec_env.call(add, 2, argv) + res = argv[0] + print("python: result from add:", res) + return res + 1 + + +native_symbols = (NativeSymbol * 1)( + *[ + NativeSymbol( + symbol=String.from_param("python_func"), + func_ptr=cast( + CFUNCTYPE(c_int32, c_void_p, c_int32)(python_func), c_void_p + ), + signature=String.from_param("(i)i"), + ) + ] +) + +def main(): + engine = Engine() + engine.register_natives("env", native_symbols) + module = Module.from_file(engine, pathlib.Path(__file__).parent / "func.wasm") + module_inst = Instance(module) + exec_env = ExecEnv(module_inst) + + func = module_inst.lookup_function("c_func") + + inp = 10 + print(f"python: calling c_func({inp})") + argv = (c_uint)(inp) + exec_env.call(func, 1, argv) + print("python: result from c_func:", argv.value) + +if __name__ == "__main__": + main() diff --git a/product-mini/README.md b/product-mini/README.md index 5847b2468..92f8183e0 100644 --- a/product-mini/README.md +++ b/product-mini/README.md @@ -251,17 +251,7 @@ WAMR provides some features which can be easily configured by passing options to ## Zephyr -You need to prepare Zephyr first as described [here](https://docs.zephyrproject.org/latest/getting_started/index.html#get-zephyr-and-install-python-dependencies). - -After that you need to point the `ZEPHYR_BASE` variable to e.g. `~/zephyrproject/zephyr`. Also, it is important that you have `west` available for subsequent actions. - -``` Bash -cd /product-mini/platforms/zephyr/simple -# Execute the ./build_and_run.sh script with board name as parameter. Here take x86 as example: -./build_and_run.sh x86 -``` - -The [Zephyr SDK](https://github.com/zephyrproject-rtos/sdk-ng) provides toolchains for all supported targets. Follow the instructions in the [documentation](https://docs.zephyrproject.org/latest/develop/getting_started/index.html#install-zephyr-sdk) to ensure it is installed and configured correctly. +Please refer to this [README](./platforms/zephyr/simple/README.md) under the Zephyr sample directory for details. Note: WAMR provides some features which can be easily configured by passing options to cmake, please see [WAMR vmcore cmake building configurations](../doc/build_wamr.md#wamr-vmcore-cmake-building-configurations) for details. Currently in Zephyr, interpreter, AOT and builtin libc are enabled by default. diff --git a/product-mini/platforms/esp-idf/build_and_run.sh b/product-mini/platforms/esp-idf/build_and_run.sh index dd8dd5ca9..f764a3013 100755 --- a/product-mini/platforms/esp-idf/build_and_run.sh +++ b/product-mini/platforms/esp-idf/build_and_run.sh @@ -5,14 +5,16 @@ ESP32_TARGET="esp32" ESP32C3_TARGET="esp32c3" +ESP32S3_TARGET="esp32s3" usage () { echo "USAGE:" - echo "$0 $ESP32_TARGET|$ESP32C3_TARGET" + echo "$0 $ESP32_TARGET|$ESP32C3_TARGET|$ESP32S3_TARGET" echo "Example:" echo " $0 $ESP32_TARGET" echo " $0 $ESP32C3_TARGET" + echo " $0 $ESP32S3_TARGET" exit 1 } diff --git a/product-mini/platforms/esp-idf/main/main.c b/product-mini/platforms/esp-idf/main/main.c index 417fad561..fbfb04c21 100644 --- a/product-mini/platforms/esp-idf/main/main.c +++ b/product-mini/platforms/esp-idf/main/main.c @@ -12,6 +12,12 @@ #include "esp_log.h" +#ifdef CONFIG_IDF_TARGET_ESP32S3 +#define IWASM_MAIN_STACK_SIZE 5120 +#else +#define IWASM_MAIN_STACK_SIZE 4096 +#endif + #define LOG_TAG "wamr" static void * @@ -146,7 +152,7 @@ app_main(void) pthread_attr_t tattr; pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setstacksize(&tattr, 4096); + pthread_attr_setstacksize(&tattr, IWASM_MAIN_STACK_SIZE); res = pthread_create(&t, &tattr, iwasm_main, (void *)NULL); assert(res == 0); diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp index 9ed17e1c8..164fa0b7d 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -92,6 +92,8 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) snprintf(error_buf, error_buf_size, "%s", string); } +static bool runtime_inited = false; + static void handle_cmd_init_runtime(uint64 *args, uint32 argc) { @@ -100,6 +102,12 @@ handle_cmd_init_runtime(uint64 *args, uint32 argc) bh_assert(argc == 1); + /* avoid duplicated init */ + if (runtime_inited) { + args[0] = false; + return; + } + os_set_print_function(enclave_print); max_thread_num = (uint32)args[0]; @@ -122,6 +130,7 @@ handle_cmd_init_runtime(uint64 *args, uint32 argc) return; } + runtime_inited = true; args[0] = true; LOG_VERBOSE("Init runtime environment success.\n"); @@ -130,7 +139,11 @@ handle_cmd_init_runtime(uint64 *args, uint32 argc) static void handle_cmd_destroy_runtime() { + if (!runtime_inited) + return; + wasm_runtime_destroy(); + runtime_inited = false; LOG_VERBOSE("Destroy runtime success.\n"); } @@ -214,6 +227,11 @@ handle_cmd_load_module(uint64 *args, uint32 argc) bh_assert(argc == 4); + if (!runtime_inited) { + *(void **)args_org = NULL; + return; + } + if (!is_xip_file((uint8 *)wasm_file, wasm_file_size)) { if (total_size >= UINT32_MAX || !(enclave_module = (EnclaveModule *)wasm_runtime_malloc( @@ -284,6 +302,10 @@ handle_cmd_unload_module(uint64 *args, uint32 argc) bh_assert(argc == 1); + if (!runtime_inited) { + return; + } + #if WASM_ENABLE_LIB_RATS != 0 /* Remove enclave module from enclave module list */ os_mutex_lock(&enclave_module_list_lock); @@ -354,6 +376,11 @@ handle_cmd_instantiate_module(uint64 *args, uint32 argc) bh_assert(argc == 5); + if (!runtime_inited) { + *(void **)args_org = NULL; + return; + } + if (!(module_inst = wasm_runtime_instantiate(enclave_module->module, stack_size, heap_size, error_buf, error_buf_size))) { @@ -373,6 +400,10 @@ handle_cmd_deinstantiate_module(uint64 *args, uint32 argc) bh_assert(argc == 1); + if (!runtime_inited) { + return; + } + wasm_runtime_deinstantiate(module_inst); LOG_VERBOSE("Deinstantiate module success.\n"); @@ -389,6 +420,11 @@ handle_cmd_get_exception(uint64 *args, uint32 argc) bh_assert(argc == 3); + if (!runtime_inited) { + args_org[0] = false; + return; + } + if ((exception1 = wasm_runtime_get_exception(module_inst))) { snprintf(exception, exception_size, "%s", exception1); args_org[0] = true; @@ -410,6 +446,10 @@ handle_cmd_exec_app_main(uint64 *args, int32 argc) bh_assert(argc >= 3); bh_assert(app_argc >= 1); + if (!runtime_inited) { + return; + } + total_size = sizeof(char *) * (app_argc > 2 ? (uint64)app_argc : 2); if (total_size >= UINT32_MAX @@ -439,6 +479,10 @@ handle_cmd_exec_app_func(uint64 *args, int32 argc) bh_assert(argc == app_argc + 3); + if (!runtime_inited) { + return; + } + total_size = sizeof(char *) * (app_argc > 2 ? (uint64)app_argc : 2); if (total_size >= UINT32_MAX @@ -488,6 +532,11 @@ handle_cmd_set_wasi_args(uint64 *args, int32 argc) bh_assert(argc == 10); + if (!runtime_inited) { + *args_org = false; + return; + } + total_size += sizeof(char *) * (uint64)dir_list_size + sizeof(char *) * (uint64)env_list_size + sizeof(char *) * (uint64)addr_pool_list_size @@ -610,6 +659,11 @@ handle_cmd_get_pgo_prof_buf_size(uint64 *args, int32 argc) bh_assert(argc == 1); + if (!runtime_inited) { + args[0] = 0; + return; + } + buf_len = wasm_runtime_get_pgo_prof_data_size(module_inst); args[0] = buf_len; } @@ -625,6 +679,11 @@ handle_cmd_get_pro_prof_buf_data(uint64 *args, int32 argc) bh_assert(argc == 3); + if (!runtime_inited) { + args_org[0] = 0; + return; + } + bytes_dumped = wasm_runtime_dump_pgo_prof_data_to_buf(module_inst, buf, len); args_org[0] = bytes_dumped; @@ -704,6 +763,11 @@ ecall_iwasm_main(uint8_t *wasm_file_buf, uint32_t wasm_file_size) char error_buf[128]; const char *exception; + /* avoid duplicated init */ + if (runtime_inited) { + return; + } + os_set_print_function(enclave_print); memset(&init_args, 0, sizeof(RuntimeInitArgs)); diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Makefile b/product-mini/platforms/linux-sgx/enclave-sample/Makefile index 402545621..dae97a069 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Makefile +++ b/product-mini/platforms/linux-sgx/enclave-sample/Makefile @@ -143,10 +143,10 @@ else endif ifeq ($(WAMR_BUILD_LIB_RATS), 1) - Rats_Lib_Link_Dirs := -L$(LIB_RATS_INSTALL_DIR) -L$(LIB_RATS_INSTALL_DIR)/attesters -L$(LIB_RATS_INSTALL_DIR)/verifiers -L$(SGX_SSL)/lib64 + Rats_Lib_Link_Dirs := -L$(LIB_RATS_INSTALL_DIR) -L$(LIB_RATS_INSTALL_DIR)/attesters -L$(LIB_RATS_INSTALL_DIR)/verifiers -L$(SGX_SSL)/lib64 -L$(VMLIB_BUILD_DIR)/external/libcbor/src/libcbor/lib -L$(LIB_RATS_INSTALL_DIR)/crypto_wrappers Rats_Lib_W_Link_libs := -lattester_nullattester -lattester_sgx_ecdsa -lattester_sgx_la \ - -lverifier_nullverifier -lverifier_sgx_ecdsa -lverifier_sgx_la -lverifier_sgx_ecdsa_qve \ - -lrats_lib -lsgx_tsgxssl + -lverifier_nullverifier -lverifier_sgx_la -lverifier_sgx_ecdsa_qve -lcbor \ + -lrats_lib -lsgx_tsgxssl -lcrypto_wrapper_nullcrypto -lcrypto_wrapper_openssl Rats_Lib_NW_Link_libs := -lsgx_dcap_tvl -lsgx_tsgxssl_crypto endif diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 78cf3eea1..04a6db91f 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -141,6 +141,12 @@ else CFLAGS += -DWASM_ENABLE_WORD_ALIGN_READ=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_MEM_DUAL_BUS_MIRROR),y) +CFLAGS += -DWASM_MEM_DUAL_BUS_MIRROR=1 +else +CFLAGS += -DWASM_MEM_DUAL_BUS_MIRROR=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_FAST), y) CFLAGS += -DWASM_ENABLE_FAST_INTERP=1 CFLAGS += -DWASM_ENABLE_INTERP=1 @@ -230,10 +236,17 @@ else CFLAGS += -DWASM_ENABLE_LIBC_BUILTIN=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_CONFIGUABLE_BOUNDS_CHECKS),y) +CFLAGS += -DWASM_CONFIGUABLE_BOUNDS_CHECKS=1 +else +CFLAGS += -DWASM_CONFIGUABLE_BOUNDS_CHECKS=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_LIBC_WASI),y) CFLAGS += -DWASM_ENABLE_LIBC_WASI=1 CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/include +CSRCS += blocking_op.c CSRCS += posix_socket.c CSRCS += libc_wasi_wrapper.c VPATH += $(IWASM_ROOT)/libraries/libc-wasi @@ -241,10 +254,18 @@ CSRCS += posix.c CSRCS += random.c CSRCS += str.c VPATH += $(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src +# todo: use Kconfig select instead +CONFIG_INTERPRETERS_WAMR_MODULE_INSTANCE_CONTEXT = y else CFLAGS += -DWASM_ENABLE_LIBC_WASI=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_MODULE_INSTANCE_CONTEXT),y) +CFLAGS += -DWASM_ENABLE_MODULE_INST_CONTEXT=1 +else +CFLAGS += -DWASM_ENABLE_MODULE_INST_CONTEXT=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_MULTI_MODULE),y) CFLAGS += -DWASM_ENABLE_MULTI_MODULE=1 else @@ -259,6 +280,15 @@ else CFLAGS += -DWASM_ENABLE_THREAD_MGR=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_LIB_WASI_THREADS),y) +CFLAGS += -DWASM_ENABLE_LIB_WASI_THREADS=1 +CSRCS += lib_wasi_threads_wrapper.c +CSRCS += tid_allocator.c +VPATH += $(IWASM_ROOT)/libraries/lib-wasi-threads +else +CFLAGS += -DWASM_ENABLE_LIB_WASI_THREADS=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_LIB_PTHREAD),y) CFLAGS += -DWASM_ENABLE_LIB_PTHREAD=1 CSRCS += lib_pthread_wrapper.c @@ -280,6 +310,9 @@ CFLAGS += -DWASM_DISABLE_HW_BOUND_CHECK=0 CFLAGS += -DWASM_DISABLE_STACK_HW_BOUND_CHECK=0 endif +# REVISIT: is this worth to have a Kconfig? +CFLAGS += -DWASM_DISABLE_WAKEUP_BLOCKING_OP=0 + ifeq ($(CONFIG_INTERPRETERS_WAMR_CUSTOM_NAME_SECTIONS),y) CFLAGS += -DWASM_ENABLE_CUSTOM_NAME_SECTION=1 else @@ -325,8 +358,10 @@ CFLAGS += -I$(IWASM_ROOT)/interpreter endif CSRCS += nuttx_platform.c \ + posix_blocking_op.c \ posix_thread.c \ posix_time.c \ + posix_sleep.c \ mem_alloc.c \ ems_kfc.c \ ems_alloc.c \ @@ -341,6 +376,7 @@ CSRCS += nuttx_platform.c \ bh_read_file.c \ runtime_timer.c \ wasm_application.c \ + wasm_blocking_op.c \ wasm_runtime_common.c \ wasm_native.c \ wasm_exec_env.c \ diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 752d235e6..45237a215 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -65,6 +65,9 @@ print_help() #endif printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of \"FUNC ARG...\"\n"); +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + printf(" --disable-bounds-checks Disable bounds checks for memory accesses\n"); +#endif #if WASM_ENABLE_LIBC_WASI != 0 printf(" --env= Pass wasi environment variables with \"key=value\"\n"); printf(" to the program, for example:\n"); @@ -94,6 +97,11 @@ print_help() #if WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0 printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n"); #endif +#if WASM_ENABLE_THREAD_MGR != 0 + printf(" --timeout=ms Set the maximum execution time in ms.\n"); + printf(" If it expires, the runtime aborts the execution\n"); + printf(" with a trap.\n"); +#endif #if WASM_ENABLE_DEBUG_INTERP != 0 printf(" -g=ip:port Set the debug sever address, default is debug disabled\n"); printf(" if port is 0, then a random port will be used\n"); @@ -279,93 +287,124 @@ validate_env_str(char *env) #endif #if BH_HAS_DLFCN -typedef uint32 (*get_native_lib_func)(char **p_module_name, - NativeSymbol **p_native_symbols); +struct native_lib { + void *handle; + + uint32 (*get_native_lib)(char **p_module_name, + NativeSymbol **p_native_symbols); + int (*init_native_lib)(void); + void (*deinit_native_lib)(void); + + char *module_name; + NativeSymbol *native_symbols; + uint32 n_native_symbols; +}; + +struct native_lib * +load_native_lib(const char *name) +{ + struct native_lib *lib = wasm_runtime_malloc(sizeof(*lib)); + if (lib == NULL) { + LOG_WARNING("warning: failed to load native library %s because of " + "allocation failure", + name); + goto fail; + } + memset(lib, 0, sizeof(*lib)); + + /* open the native library */ + if (!(lib->handle = dlopen(name, RTLD_NOW | RTLD_GLOBAL)) + && !(lib->handle = dlopen(name, RTLD_LAZY))) { + LOG_WARNING("warning: failed to load native library %s", name); + goto fail; + } + + lib->init_native_lib = dlsym(lib->handle, "init_native_lib"); + lib->get_native_lib = dlsym(lib->handle, "get_native_lib"); + lib->deinit_native_lib = dlsym(lib->handle, "deinit_native_lib"); + + if (!lib->get_native_lib) { + LOG_WARNING("warning: failed to lookup `get_native_lib` function " + "from native lib %s", + name); + goto fail; + } + + if (lib->init_native_lib) { + int ret = lib->init_native_lib(); + if (ret != 0) { + LOG_WARNING("warning: `init_native_lib` function from native " + "lib %s failed with %d", + name, ret); + goto fail; + } + } + + lib->n_native_symbols = + lib->get_native_lib(&lib->module_name, &lib->native_symbols); + + /* register native symbols */ + if (!(lib->n_native_symbols > 0 && lib->module_name && lib->native_symbols + && wasm_runtime_register_natives( + lib->module_name, lib->native_symbols, lib->n_native_symbols))) { + LOG_WARNING("warning: failed to register native lib %s", name); + if (lib->deinit_native_lib) { + lib->deinit_native_lib(); + } + goto fail; + } + return lib; +fail: + if (lib != NULL) { + if (lib->handle != NULL) { + dlclose(lib->handle); + } + wasm_runtime_free(lib); + } + return NULL; +} static uint32 load_and_register_native_libs(const char **native_lib_list, uint32 native_lib_count, - void **native_handle_list) + struct native_lib **native_lib_loaded_list) { - uint32 i, native_handle_count = 0, n_native_symbols; - NativeSymbol *native_symbols; - char *module_name; - void *handle; + uint32 i, native_lib_loaded_count = 0; for (i = 0; i < native_lib_count; i++) { - /* open the native library */ - if (!(handle = dlopen(native_lib_list[i], RTLD_NOW | RTLD_GLOBAL)) - && !(handle = dlopen(native_lib_list[i], RTLD_LAZY))) { - LOG_WARNING("warning: failed to load native library %s", - native_lib_list[i]); + struct native_lib *lib = load_native_lib(native_lib_list[i]); + if (lib == NULL) { continue; } - - /* lookup get_native_lib func */ - get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib"); - if (!get_native_lib) { - LOG_WARNING("warning: failed to lookup `get_native_lib` function " - "from native lib %s", - native_lib_list[i]); - dlclose(handle); - continue; - } - - n_native_symbols = get_native_lib(&module_name, &native_symbols); - - /* register native symbols */ - if (!(n_native_symbols > 0 && module_name && native_symbols - && wasm_runtime_register_natives(module_name, native_symbols, - n_native_symbols))) { - LOG_WARNING("warning: failed to register native lib %s", - native_lib_list[i]); - dlclose(handle); - continue; - } - - native_handle_list[native_handle_count++] = handle; + native_lib_loaded_list[native_lib_loaded_count++] = lib; } - return native_handle_count; + return native_lib_loaded_count; } static void unregister_and_unload_native_libs(uint32 native_lib_count, - void **native_handle_list) + struct native_lib **native_lib_loaded_list) { - uint32 i, n_native_symbols; - NativeSymbol *native_symbols; - char *module_name; - void *handle; + uint32 i; for (i = 0; i < native_lib_count; i++) { - handle = native_handle_list[i]; - - /* lookup get_native_lib func */ - get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib"); - if (!get_native_lib) { - LOG_WARNING("warning: failed to lookup `get_native_lib` function " - "from native lib %p", - handle); - continue; - } - - n_native_symbols = get_native_lib(&module_name, &native_symbols); - if (n_native_symbols == 0 || module_name == NULL - || native_symbols == NULL) { - LOG_WARNING("warning: get_native_lib returned different values for " - "native lib %p", - handle); - continue; - } + struct native_lib *lib = native_lib_loaded_list[i]; /* unregister native symbols */ - if (!wasm_runtime_unregister_natives(module_name, native_symbols)) { - LOG_WARNING("warning: failed to unregister native lib %p", handle); + if (!wasm_runtime_unregister_natives(lib->module_name, + lib->native_symbols)) { + LOG_WARNING("warning: failed to unregister native lib %p", + lib->handle); continue; } - dlclose(handle); + if (lib->deinit_native_lib) { + lib->deinit_native_lib(); + } + + dlclose(lib->handle); + wasm_runtime_free(lib); } } #endif /* BH_HAS_DLFCN */ @@ -454,6 +493,40 @@ dump_pgo_prof_data(wasm_module_inst_t module_inst, const char *path) } #endif +#if WASM_ENABLE_THREAD_MGR != 0 +struct timeout_arg { + uint32 timeout_ms; + wasm_module_inst_t inst; +#if defined(BH_HAS_STD_ATOMIC) + _Atomic +#endif + bool cancel; +}; + +void * +timeout_thread(void *vp) +{ + const struct timeout_arg *arg = vp; + uint32 left = arg->timeout_ms; + while (!arg->cancel) { + uint32 ms; + if (left >= 100) { + ms = 100; + } + else { + ms = left; + } + os_usleep((uint64)ms * 1000); + left -= ms; + if (left == 0) { + wasm_runtime_terminate(arg->inst); + break; + } + } + return NULL; +} +#endif + int main(int argc, char *argv[]) { @@ -462,7 +535,12 @@ main(int argc, char *argv[]) const char *func_name = NULL; uint8 *wasm_file_buf = NULL; uint32 wasm_file_size; - uint32 stack_size = 64 * 1024, heap_size = 16 * 1024; + uint32 stack_size = 64 * 1024; +#if WASM_ENABLE_LIBC_WASI != 0 + uint32 heap_size = 0; +#else + uint32 heap_size = 16 * 1024; +#endif #if WASM_ENABLE_FAST_JIT != 0 uint32 jit_code_cache_size = FAST_JIT_DEFAULT_CODE_CACHE_SIZE; #endif @@ -481,6 +559,9 @@ main(int argc, char *argv[]) #endif bool is_repl_mode = false; bool is_xip_file = false; +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + bool disable_bounds_checks = false; +#endif #if WASM_ENABLE_LIBC_WASI != 0 const char *dir_list[8] = { NULL }; uint32 dir_list_size = 0; @@ -494,8 +575,8 @@ main(int argc, char *argv[]) #if BH_HAS_DLFCN const char *native_lib_list[8] = { NULL }; uint32 native_lib_count = 0; - void *native_handle_list[8] = { NULL }; - uint32 native_handle_count = 0; + struct native_lib *native_lib_loaded_list[8]; + uint32 native_lib_loaded_count = 0; #endif #if WASM_ENABLE_DEBUG_INTERP != 0 char *ip_addr = NULL; @@ -504,6 +585,9 @@ main(int argc, char *argv[]) #if WASM_ENABLE_STATIC_PGO != 0 const char *gen_prof_file = NULL; #endif +#if WASM_ENABLE_THREAD_MGR != 0 + int timeout_ms = -1; +#endif /* Process options. */ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { @@ -545,6 +629,11 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--repl")) { is_repl_mode = true; } +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + else if (!strcmp(argv[0], "--disable-bounds-checks")) { + disable_bounds_checks = true; + } +#endif else if (!strncmp(argv[0], "--stack-size=", 13)) { if (argv[0][13] == '\0') return print_help(); @@ -695,6 +784,13 @@ main(int argc, char *argv[]) wasm_runtime_set_max_thread_num(atoi(argv[0] + 14)); } #endif +#if WASM_ENABLE_THREAD_MGR != 0 + else if (!strncmp(argv[0], "--timeout=", 10)) { + if (argv[0][10] == '\0') + return print_help(); + timeout_ms = atoi(argv[0] + 10); + } +#endif #if WASM_ENABLE_DEBUG_INTERP != 0 else if (!strncmp(argv[0], "-g=", 3)) { char *port_str = strchr(argv[0] + 3, ':'); @@ -774,8 +870,8 @@ main(int argc, char *argv[]) #endif #if BH_HAS_DLFCN - native_handle_count = load_and_register_native_libs( - native_lib_list, native_lib_count, native_handle_list); + native_lib_loaded_count = load_and_register_native_libs( + native_lib_list, native_lib_count, native_lib_loaded_list); #endif /* load WASM byte buffer from WASM bin file */ @@ -832,6 +928,12 @@ main(int argc, char *argv[]) goto fail3; } +#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0 + if (disable_bounds_checks) { + wasm_runtime_set_bounds_checks(wasm_module_inst, false); + } +#endif + #if WASM_ENABLE_DEBUG_INTERP != 0 if (ip_addr != NULL) { wasm_exec_env_t exec_env = @@ -849,6 +951,22 @@ main(int argc, char *argv[]) } #endif +#if WASM_ENABLE_THREAD_MGR != 0 + struct timeout_arg timeout_arg; + korp_tid timeout_tid; + if (timeout_ms >= 0) { + timeout_arg.timeout_ms = timeout_ms; + timeout_arg.inst = wasm_module_inst; + timeout_arg.cancel = false; + ret = os_thread_create(&timeout_tid, timeout_thread, &timeout_arg, + APP_THREAD_STACK_SIZE_DEFAULT); + if (ret != 0) { + printf("Failed to start timeout\n"); + goto fail5; + } + } +#endif + ret = 0; if (is_repl_mode) { app_instance_repl(wasm_module_inst); @@ -868,12 +986,8 @@ main(int argc, char *argv[]) #if WASM_ENABLE_LIBC_WASI != 0 if (ret == 0) { - /* wait for threads to finish and propagate wasi exit code. */ + /* propagate wasi exit code. */ ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); - if (wasm_runtime_get_exception(wasm_module_inst)) { - /* got an exception in spawned thread */ - ret = 1; - } } #endif @@ -883,6 +997,16 @@ main(int argc, char *argv[]) dump_pgo_prof_data(wasm_module_inst, gen_prof_file); #endif +#if WASM_ENABLE_THREAD_MGR != 0 + if (timeout_ms >= 0) { + timeout_arg.cancel = true; + os_thread_join(timeout_tid, NULL); + } +#endif + +#if WASM_ENABLE_THREAD_MGR != 0 +fail5: +#endif #if WASM_ENABLE_DEBUG_INTERP != 0 fail4: #endif @@ -903,7 +1027,8 @@ fail2: fail1: #if BH_HAS_DLFCN /* unload the native libraries */ - unregister_and_unload_native_libs(native_handle_count, native_handle_list); + unregister_and_unload_native_libs(native_lib_loaded_count, + native_lib_loaded_list); #endif /* destroy runtime environment */ diff --git a/product-mini/platforms/rt-thread/iwasm.c b/product-mini/platforms/rt-thread/iwasm.c index 8ae4da761..9a21301d8 100644 --- a/product-mini/platforms/rt-thread/iwasm.c +++ b/product-mini/platforms/rt-thread/iwasm.c @@ -10,7 +10,6 @@ #include #include #include -#include #ifdef WAMR_ENABLE_RTT_EXPORT @@ -183,8 +182,6 @@ rt_uint8_t * my_read_file_to_buffer(char *filename, rt_uint32_t *size) { struct stat f_stat; - dfs_file_stat(filename, &f_stat); - struct dfs_fd fd; rt_uint8_t *buff = rt_malloc(f_stat.st_size); *size = 0; @@ -193,16 +190,16 @@ my_read_file_to_buffer(char *filename, rt_uint32_t *size) return RT_NULL; } - int ret = dfs_file_open(&fd, filename, O_RDONLY); - if (ret) { + int fd = open(filename, O_RDONLY); + if (fd < 0) { rt_free(buff); - rt_set_errno(ret); + rt_set_errno(fd); return RT_NULL; } - *size = dfs_file_read(&fd, buff, f_stat.st_size); + *size = read(fd, buff, f_stat.st_size); - dfs_file_close(&fd); + close(fd); if (*size != f_stat.st_size) { rt_free(buff); diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 26fa7dcc9..8b1b1f371 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -243,7 +243,12 @@ main(int argc, char *argv[]) const char *func_name = NULL; uint8 *wasm_file_buf = NULL; uint32 wasm_file_size; - uint32 stack_size = 64 * 1024, heap_size = 16 * 1024; + uint32 stack_size = 64 * 1024; +#if WASM_ENABLE_LIBC_WASI != 0 + uint32 heap_size = 0; +#else + uint32 heap_size = 16 * 1024; +#endif #if WASM_ENABLE_JIT != 0 uint32 llvm_jit_size_level = 3; uint32 llvm_jit_opt_level = 3; @@ -549,12 +554,8 @@ main(int argc, char *argv[]) #if WASM_ENABLE_LIBC_WASI != 0 if (ret == 0) { - /* wait for threads to finish and propagate wasi exit code. */ + /* propagate wasi exit code. */ ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); - if (wasm_runtime_get_exception(wasm_module_inst)) { - /* got an exception in spawned thread */ - ret = 1; - } } #endif diff --git a/product-mini/platforms/zephyr/simple/Dockerfile b/product-mini/platforms/zephyr/simple/Dockerfile new file mode 100644 index 000000000..9c8e6e5a0 --- /dev/null +++ b/product-mini/platforms/zephyr/simple/Dockerfile @@ -0,0 +1,60 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +FROM ubuntu:20.04 + +ARG DEBIAN_FRONTEND=noninteractive +ENV TZ=Asian/Shanghai + +# Install dependencies for Zephyr and ESPRESSIF +# hadolint ignore=DL3008 +RUN apt-get update && apt-get install -y git wget flex bison gperf python3 python3-pip python3-venv\ + python3-dev python3-setuptools python3-tk python3-wheel xz-utils file libpython3.8-dev \ + ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 device-tree-compiler \ + make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 qemu udev --no-install-recommends \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* + +# Install recent CMake version +WORKDIR /tmp +RUN mkdir /opt/cmake \ + && wget --progress=dot:giga https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1-linux-x86_64.sh \ + && sh cmake-3.22.1-linux-x86_64.sh --skip-license --prefix=/opt/cmake && rm cmake-3.22.1-linux-x86_64.sh +ENV PATH="/opt/cmake/bin:$PATH" + +# Install the Zephyr Software Development Kit (SDK) +WORKDIR /opt +# hadolint ignore=DL4006 +RUN wget --progress=dot:giga https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64.tar.xz \ + && wget --progress=dot:giga -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing \ + && tar xvf zephyr-sdk-0.16.1_linux-x86_64.tar.xz && rm zephyr-sdk-0.16.1_linux-x86_64.tar.xz + +WORKDIR /opt/zephyr-sdk-0.16.1 +# hadolint ignore=DL4006 +RUN yes | ./setup.sh + +# Get ESP-IDF +RUN ln -s /usr/bin/python3 /usr/bin/python && mkdir -p ~/esp +WORKDIR /root/esp +RUN git clone https://github.com/espressif/esp-idf.git +WORKDIR /root/esp/esp-idf +RUN git checkout 03d4fa28694ee15ccfd5a97447575de2d1655026 \ + && git submodule update --init --recursive +# Set up the sep-idf tools +RUN ./install.sh esp32 esp32c3 + +# Get Zephyr +# hadolint ignore=DL3013 +RUN pip3 install --no-cache-dir west && west init -m https://github.com/zephyrproject-rtos/zephyr --mr v3.4.0 /root/zephyrproject + +WORKDIR /root/zephyrproject +RUN west update + +WORKDIR /root/zephyrproject/zephyr +RUN west zephyr-export && pip install --no-cache-dir -r ~/zephyrproject/zephyr/scripts/requirements.txt + +# Git clone wamr +WORKDIR /root +RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git + +WORKDIR /root/wasm-micro-runtime/product-mini/platforms/zephyr/simple + +ENV ZEPHYR_BASE="/root/zephyrproject/zephyr" diff --git a/product-mini/platforms/zephyr/simple/Dockerfile.old b/product-mini/platforms/zephyr/simple/Dockerfile.old new file mode 100644 index 000000000..e223f315a --- /dev/null +++ b/product-mini/platforms/zephyr/simple/Dockerfile.old @@ -0,0 +1,58 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +FROM ubuntu:20.04 + +ARG DEBIAN_FRONTEND=noninteractive +ENV TZ=Asian/Shanghai + +# Install dependencies for Zephyr and ESPRESSIF +# hadolint ignore=DL3008 +RUN apt-get update && apt-get install -y git wget flex bison gperf python3 python3-pip python3-venv\ + python3-dev python3-setuptools python3-tk python3-wheel xz-utils file libpython3.8-dev \ + ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 device-tree-compiler \ + make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 qemu udev --no-install-recommends \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* + +# Install recent CMake version +WORKDIR /tmp +RUN mkdir /opt/cmake \ + && wget --progress=dot:giga https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1-linux-x86_64.sh \ + && sh cmake-3.22.1-linux-x86_64.sh --skip-license --prefix=/opt/cmake && rm cmake-3.22.1-linux-x86_64.sh +ENV PATH="/opt/cmake/bin:$PATH" + +# Install the Zephyr Software Development Kit (SDK) +WORKDIR /opt +# hadolint ignore=DL4006 +RUN wget --progress=dot:giga https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.11.3/zephyr-sdk-0.11.3-setup.run \ + && chmod +x ./zephyr-sdk-0.11.3-setup.run \ + && ./zephyr-sdk-0.11.3-setup.run -- -d /opt/zephyr-sdk-0.11.3 +ENV ZEPHYR_TOOLCHAIN_VARIANT=zephyr +ENV ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk-0.11.3 + +# Get ESP-IDF +RUN ln -s /usr/bin/python3 /usr/bin/python && mkdir -p ~/esp +WORKDIR /root/esp +RUN git clone https://github.com/espressif/esp-idf.git +WORKDIR /root/esp/esp-idf +RUN git checkout v4.0 \ + && pip install --no-cache-dir virtualenv==16.7.12 \ + && git submodule update --init --recursive \ + && ./install.sh esp32 esp32c3 + +# Get Zephyr +# hadolint ignore=DL3013 +RUN pip3 install --no-cache-dir west && west init -m https://github.com/zephyrproject-rtos/zephyr --mr v2.3.0 /root/zephyrproject + +WORKDIR /root/zephyrproject +RUN west update + +WORKDIR /root/zephyrproject/zephyr +RUN west zephyr-export && pip install --no-cache-dir -r ~/zephyrproject/zephyr/scripts/requirements.txt + +# Git clone wamr +WORKDIR /root +RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git + +WORKDIR /root/wasm-micro-runtime/product-mini/platforms/zephyr/simple + +ENV ZEPHYR_BASE="/root/zephyrproject/zephyr" diff --git a/product-mini/platforms/zephyr/simple/README.md b/product-mini/platforms/zephyr/simple/README.md new file mode 100644 index 000000000..acb955258 --- /dev/null +++ b/product-mini/platforms/zephyr/simple/README.md @@ -0,0 +1,106 @@ +# How to use WAMR with Zephyr + +## Build with Docker(recommend approach) + +To have a quicker start, a Docker container of the Zephyr setup can be generated. The current docker image would be considerably large(~15GB), it would take some time to build it and enough disk space to store it. + +### Build Docker images + +```shell +docker build -t wamr-zephyr . +``` + +> PS: currently, the esp32 custom linker script only works with a lower version of Zephyr, if you want to use an esp32 board, you can build the Dockerfile with a lower version of Zephyr, Zephyr SDE, ESP-IDF. The old version of Docker image can also build other targets, but probably it's a better choice to use the new Dockerfile for other boards + +```shell +# If you want to build on esp32 platform +docker build -f Dockerfile.old -t wamr-zephyr . +``` + +### Run Docker images + +Adopt the device or remove if not needed. + +```shell +docker run -ti --device=/dev/ttyUSB0 wamr-zephyr +``` + +And then inside the docker container: + +```shell +# copy the corresponding board conf file to current directory +cp boards/qemu_x86_nommu.conf prj.conf +# then build +./build_and_run.sh x86 +``` + +> PS: for boards esp32, need to configure some environment first + +```shell +# configure zephyr with espressif +export ZEPHYR_TOOLCHAIN_VARIANT="espressif" +export ESPRESSIF_TOOLCHAIN_PATH="/root/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-elf/" +export ESP_IDF_PATH="/root/esp/esp-idf" +# copy the corresponding board conf file to current directory +cp boards/esp32.conf prj.conf +# then build +./build_and_run.sh esp32 +``` + +## Build on local environment + +### Dependencies installation + +Following the Zephyr and Espressif official document: + +1. Zephyr installation: + + + +2. ESP32 installation: + + + +And setup the Zephyr for esp32: + + + +Then Installing QEMU, for example, on Linux: + +```shell +sudo apt-get install qemu +``` + +### Run the build script + +Make sure you have the environment variable ready, you can use the command `env` to check: + +```shell +env +``` + +```shell +# export ZEPHYR_BASE if it's not present +export ZEPHYR_BASE=~/zephyrproject/zephyr +# and if you install zephyr in virtual environment rather than global +source ~/zephyrproject/.venv/bin/activate +``` + +For boards esp32, need to configure some extra environment first, check the following env variable whether in the env list, if not, add them like: + +> Noted: The esp32 custom linker script doesn't work with the recent version of Zephyr, if you want to use it in the local environment, please install Zephyr 2.3.0 with the corresponding SDK, and ESP-IDF 4.0 + +```shell +export ZEPHYR_TOOLCHAIN_VARIANT="espressif" +export ESPRESSIF_TOOLCHAIN_PATH="~/.espressif/tools/xtensa-esp32-elf/esp-{the version you installed}/xtensa-esp32-elf/" +export ESP_IDF_PATH="~/esp/esp-idf" +``` + +Then you can run the build script: + +```shell +# copy the corresponding board conf file to current directory +cp boards/qemu_x86_nommu.conf prj.conf +# then build +./build_and_run.sh x86 +``` diff --git a/product-mini/platforms/zephyr/simple/README_docker.md b/product-mini/platforms/zephyr/simple/README_docker.md deleted file mode 100644 index e02398b0b..000000000 --- a/product-mini/platforms/zephyr/simple/README_docker.md +++ /dev/null @@ -1,25 +0,0 @@ -# Build with Docker - -To have a quicker start, a Docker container of the Zephyr setup can be generated. - -## Build Docker container - -``` Bash -docker build --build-arg DOCKER_UID=$(id -u) . -t wamr-zephyr -``` - -## Run Docker container to build images - -Enter the docker container (maps the toplevel wasm-micro-runtime repo as volume): - -``` Bash -docker run -ti -v $PWD/../../../..:/home/wamr/source --device=/dev/ttyUSB0 wamr-zephyr -``` - -Adopt the device or remove if not needed. - -And then in the docker container: - -``` Bash -./build_and_run.sh esp32c3 -``` \ No newline at end of file diff --git a/samples/bh-atomic/CMakeLists.txt b/samples/bh-atomic/CMakeLists.txt new file mode 100644 index 000000000..f69052742 --- /dev/null +++ b/samples/bh-atomic/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2023 Midokura Japan KK. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.0) +project(bh_atomic) + +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +if(APPLE) + add_definitions(-DBH_PLATFORM_DARWIN) +endif() + +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_LIBC_BUILTIN 0) + +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..) +include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_executable(bh_atomic main.c) + +target_link_libraries(bh_atomic) diff --git a/samples/bh-atomic/main.c b/samples/bh-atomic/main.c new file mode 100644 index 000000000..61c52800b --- /dev/null +++ b/samples/bh-atomic/main.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "bh_platform.h" +#include "bh_atomic.h" + +int +main(int argc, char **argv) +{ + bh_atomic_32_t v; + uint32 o; + + v = 0x00ff00ff; + o = BH_ATOMIC_32_LOAD(v); + assert(o == 0x00ff00ff); + + v = 0x00ff00ff; + o = BH_ATOMIC_32_FETCH_OR(v, 0xffff0000); + assert(o == 0x00ff00ff); + assert(v == 0xffff00ff); + + v = 0x00ff00ff; + o = BH_ATOMIC_32_FETCH_AND(v, 0xffff0000); + assert(o == 0x00ff00ff); + assert(v == 0x00ff0000); + + v = 0x00ff00ff; + o = BH_ATOMIC_32_FETCH_ADD(v, 0x10101); + assert(o == 0x00ff00ff); + assert(v == 0x00ff00ff + 0x10101); + + v = 0x00ff00ff; + o = BH_ATOMIC_32_FETCH_SUB(v, 0x10101); + assert(o == 0x00ff00ff); + assert(v == 0x00ff00ff - 0x10101); + + return 0; +} diff --git a/samples/inst-context-threads/.gitignore b/samples/inst-context-threads/.gitignore new file mode 100644 index 000000000..0fa8a76bd --- /dev/null +++ b/samples/inst-context-threads/.gitignore @@ -0,0 +1 @@ +/out/ \ No newline at end of file diff --git a/samples/inst-context-threads/CMakeLists.txt b/samples/inst-context-threads/CMakeLists.txt new file mode 100644 index 000000000..7326a5436 --- /dev/null +++ b/samples/inst-context-threads/CMakeLists.txt @@ -0,0 +1,92 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +include(CheckPIESupported) + +if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") + project (inst-context) +else() + project (inst-context C ASM) + enable_language (ASM_MASM) +endif() + +################ runtime settings ################ +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +if (APPLE) + add_definitions(-DBH_PLATFORM_DARWIN) +endif () + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug) +endif () + +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_LIB_WASI_THREADS 1) + +if (NOT MSVC) + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +if (NOT MSVC) + # linker flags + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + endif () + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") + if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + endif () + endif () +endif () + +# build out vmlib +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +################ application related ################ +include_directories(${CMAKE_CURRENT_LIST_DIR}/src) +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (inst-context src/main.c src/native_impl.c ${UNCOMMON_SHARED_SOURCE}) + +check_pie_supported() +set_target_properties (inst-context PROPERTIES POSITION_INDEPENDENT_CODE ON) + +if (APPLE) + target_link_libraries (inst-context vmlib -lm -ldl -lpthread) +else () + target_link_libraries (inst-context vmlib -lm -ldl -lpthread -lrt) +endif () diff --git a/samples/inst-context-threads/README.md b/samples/inst-context-threads/README.md new file mode 100644 index 000000000..d64cbff52 --- /dev/null +++ b/samples/inst-context-threads/README.md @@ -0,0 +1,5 @@ +The "inst-context-threads" sample project +========================================= + +This sample demonstrates some interactions between +module instance context API and wasi-threads. diff --git a/samples/inst-context-threads/build.sh b/samples/inst-context-threads/build.sh new file mode 100755 index 000000000..35f76eccf --- /dev/null +++ b/samples/inst-context-threads/build.sh @@ -0,0 +1,61 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/bash + +CURR_DIR=$PWD +WAMR_DIR=${PWD}/../.. +OUT_DIR=${PWD}/out + +WASM_APPS=${PWD}/wasm-apps + + +rm -rf ${OUT_DIR} +mkdir ${OUT_DIR} +mkdir ${OUT_DIR}/wasm-apps + + +echo "#####################build inst-context project" +cd ${CURR_DIR} +mkdir -p cmake_build +cd cmake_build +cmake .. +make -j ${nproc} +if [ $? != 0 ];then + echo "BUILD_FAIL inst-context exit as $?\n" + exit 2 +fi + +cp -a inst-context ${OUT_DIR} + +echo -e "\n" + +echo "#####################build wasm apps" + +cd ${WASM_APPS} + +for i in `ls *.c` +do +APP_SRC="$i" +OUT_FILE=${i%.*}.wasm + +# use WAMR SDK to build out the .wasm binary +# require wasi-sdk with wasi-threads support. (wasi-sdk-20.0 or later) +/opt/wasi-sdk/bin/clang \ + --target=wasm32-wasi-threads \ + -pthread \ + -Wl,--import-memory \ + -Wl,--export-memory \ + -Wl,--max-memory=655360 \ + -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} + + +if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then + echo "build ${OUT_FILE} success" +else + echo "build ${OUT_FILE} fail" +fi +done +echo "####################build wasm apps done" diff --git a/samples/inst-context-threads/run.sh b/samples/inst-context-threads/run.sh new file mode 100755 index 000000000..919ed0166 --- /dev/null +++ b/samples/inst-context-threads/run.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +out/inst-context -f out/wasm-apps/testapp.wasm diff --git a/samples/inst-context-threads/src/main.c b/samples/inst-context-threads/src/main.c new file mode 100644 index 000000000..2a20363c5 --- /dev/null +++ b/samples/inst-context-threads/src/main.c @@ -0,0 +1,151 @@ + +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_export.h" +#include "bh_read_file.h" +#include "bh_getopt.h" +#include "my_context.h" + +void +set_context(wasm_exec_env_t exec_env, int32_t n); +int32_t +get_context(wasm_exec_env_t exec_env); + +void *my_context_key; +struct my_context my_context; +int my_dtor_called; + +wasm_module_inst_t module_inst = NULL; + +void +print_usage(void) +{ + fprintf(stdout, "Options:\r\n"); + fprintf(stdout, " -f [path of wasm file] \n"); +} + +void +my_context_dtor(wasm_module_inst_t inst, void *ctx) +{ + printf("%s called\n", __func__); + my_dtor_called++; + bh_assert(ctx == &my_context); + bh_assert(inst == module_inst); +} + +int +main(int argc, char *argv_main[]) +{ + static char global_heap_buf[512 * 1024]; + char *buffer; + char error_buf[128]; + int opt; + char *wasm_path = NULL; + int exit_code = 1; + + wasm_module_t module = NULL; + uint32 buf_size, stack_size = 8092, heap_size = 8092; + + RuntimeInitArgs init_args; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + while ((opt = getopt(argc, argv_main, "hf:")) != -1) { + switch (opt) { + case 'f': + wasm_path = optarg; + break; + case 'h': + print_usage(); + return 0; + case '?': + print_usage(); + return 0; + } + } + if (optind == 1) { + print_usage(); + return 0; + } + + // Define an array of NativeSymbol for the APIs to be exported. + // Note: the array must be static defined since runtime + // will keep it after registration + // For the function signature specifications, goto the link: + // https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md + + static NativeSymbol native_symbols[] = { + { "set_context", set_context, "(i)", NULL }, + { "get_context", get_context, "()i", NULL }, + }; + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + // Native symbols need below registration phase + init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + init_args.native_module_name = "env"; + init_args.native_symbols = native_symbols; + + if (!wasm_runtime_full_init(&init_args)) { + printf("Init runtime environment failed.\n"); + return -1; + } + + my_context_key = wasm_runtime_create_context_key(my_context_dtor); + if (!my_context_key) { + printf("wasm_runtime_create_context_key failed.\n"); + return -1; + } + + buffer = bh_read_file_to_buffer(wasm_path, &buf_size); + + if (!buffer) { + printf("Open wasm app file [%s] failed.\n", wasm_path); + goto fail; + } + + module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf, + sizeof(error_buf)); + if (!module) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + + module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)); + + if (!module_inst) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + + char *args[] = { + "testapp", + }; + wasm_application_execute_main(module_inst, 1, args); + const char *exc = wasm_runtime_get_exception(module_inst); + if (exc != NULL) { + printf("call wasm function calculate failed. error: %s\n", exc); + goto fail; + } + + exit_code = 0; +fail: + if (module_inst) { + bh_assert(my_dtor_called == 0); + wasm_runtime_deinstantiate(module_inst); + bh_assert(my_dtor_called == 1); + } + if (module) + wasm_runtime_unload(module); + if (buffer) + BH_FREE(buffer); + if (my_context_key) + wasm_runtime_destroy_context_key(my_context_key); + wasm_runtime_destroy(); + return exit_code; +} diff --git a/samples/inst-context-threads/src/my_context.h b/samples/inst-context-threads/src/my_context.h new file mode 100644 index 000000000..008be71ff --- /dev/null +++ b/samples/inst-context-threads/src/my_context.h @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +struct my_context { + int x; +}; + +extern void *my_context_key; +extern struct my_context my_context; diff --git a/samples/inst-context-threads/src/native_impl.c b/samples/inst-context-threads/src/native_impl.c new file mode 100644 index 000000000..0733e1976 --- /dev/null +++ b/samples/inst-context-threads/src/native_impl.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include + +#include "wasm_export.h" +#include "my_context.h" + +void +set_context(wasm_exec_env_t exec_env, int32_t n) +{ + wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env); + printf("%s called on module inst %p\n", __func__, inst); + struct my_context *ctx = &my_context; + ctx->x = n; + wasm_runtime_set_context_spread(inst, my_context_key, ctx); +} + +int32_t +get_context(wasm_exec_env_t exec_env) +{ + wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env); + printf("%s called on module inst %p\n", __func__, inst); + struct my_context *ctx = wasm_runtime_get_context(inst, my_context_key); + if (ctx == NULL) { + return -1; + } + return ctx->x; +} diff --git a/samples/inst-context-threads/wasm-apps/testapp.c b/samples/inst-context-threads/wasm-apps/testapp.c new file mode 100644 index 000000000..429b0875f --- /dev/null +++ b/samples/inst-context-threads/wasm-apps/testapp.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include + +void +set_context(int32_t n) __attribute__((import_module("env"))) +__attribute__((import_name("set_context"))); + +int32_t +get_context() __attribute__((import_module("env"))) +__attribute__((import_name("get_context"))); + +void * +start(void *vp) +{ + int32_t v; + + printf("thread started\n"); + + printf("confirming the initial state on thread\n"); + v = get_context(); + assert(v == -1); + + printf("setting the context on thread\n"); + set_context(1234); + + printf("confirming the context on thread\n"); + v = get_context(); + assert(v == 1234); + return NULL; +} + +int +main() +{ + pthread_t t1; + int32_t v; + int ret; + + printf("confirming the initial state on main\n"); + v = get_context(); + assert(v == -1); + + printf("creating a thread\n"); + ret = pthread_create(&t1, NULL, start, NULL); + assert(ret == 0); + void *val; + ret = pthread_join(t1, &val); + assert(ret == 0); + printf("joined the thread\n"); + + printf("confirming the context propagated from the thread on main\n"); + v = get_context(); + assert(v == 1234); + + printf("success\n"); + return 0; +} diff --git a/samples/inst-context/.gitignore b/samples/inst-context/.gitignore new file mode 100644 index 000000000..0fa8a76bd --- /dev/null +++ b/samples/inst-context/.gitignore @@ -0,0 +1 @@ +/out/ \ No newline at end of file diff --git a/samples/inst-context/CMakeLists.txt b/samples/inst-context/CMakeLists.txt new file mode 100644 index 000000000..b1167d277 --- /dev/null +++ b/samples/inst-context/CMakeLists.txt @@ -0,0 +1,91 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +include(CheckPIESupported) + +if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") + project (inst-context) +else() + project (inst-context C ASM) + enable_language (ASM_MASM) +endif() + +################ runtime settings ################ +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +if (APPLE) + add_definitions(-DBH_PLATFORM_DARWIN) +endif () + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug) +endif () + +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 1) + +if (NOT MSVC) + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +if (NOT MSVC) + # linker flags + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + endif () + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") + if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + endif () + endif () +endif () + +# build out vmlib +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +################ application related ################ +include_directories(${CMAKE_CURRENT_LIST_DIR}/src) +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (inst-context src/main.c src/native_impl.c ${UNCOMMON_SHARED_SOURCE}) + +check_pie_supported() +set_target_properties (inst-context PROPERTIES POSITION_INDEPENDENT_CODE ON) + +if (APPLE) + target_link_libraries (inst-context vmlib -lm -ldl -lpthread) +else () + target_link_libraries (inst-context vmlib -lm -ldl -lpthread -lrt) +endif () diff --git a/samples/inst-context/README.md b/samples/inst-context/README.md new file mode 100644 index 000000000..43b13c66b --- /dev/null +++ b/samples/inst-context/README.md @@ -0,0 +1,4 @@ +The "inst-context" sample project +================================= + +This sample demonstrates module instance context API. diff --git a/samples/inst-context/build.sh b/samples/inst-context/build.sh new file mode 100755 index 000000000..816e1cc08 --- /dev/null +++ b/samples/inst-context/build.sh @@ -0,0 +1,63 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/bash + +CURR_DIR=$PWD +WAMR_DIR=${PWD}/../.. +OUT_DIR=${PWD}/out + +WASM_APPS=${PWD}/wasm-apps + + +rm -rf ${OUT_DIR} +mkdir ${OUT_DIR} +mkdir ${OUT_DIR}/wasm-apps + + +echo "#####################build inst-context project" +cd ${CURR_DIR} +mkdir -p cmake_build +cd cmake_build +cmake .. +make -j ${nproc} +if [ $? != 0 ];then + echo "BUILD_FAIL inst-context exit as $?\n" + exit 2 +fi + +cp -a inst-context ${OUT_DIR} + +echo -e "\n" + +echo "#####################build wasm apps" + +cd ${WASM_APPS} + +for i in `ls *.c` +do +APP_SRC="$i" +OUT_FILE=${i%.*}.wasm + +# use WAMR SDK to build out the .wasm binary +/opt/wasi-sdk/bin/clang \ + --target=wasm32 -O0 -z stack-size=4096 -Wl,--initial-memory=65536 \ + --sysroot=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot \ + -Wl,--allow-undefined-file=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt \ + -Wl,--strip-all,--no-entry -nostdlib \ + -Wl,--export=generate_float \ + -Wl,--export=float_to_string \ + -Wl,--export=calculate\ + -Wl,--allow-undefined \ + -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} + + +if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then + echo "build ${OUT_FILE} success" +else + echo "build ${OUT_FILE} fail" +fi +done +echo "####################build wasm apps done" diff --git a/samples/inst-context/run.sh b/samples/inst-context/run.sh new file mode 100755 index 000000000..919ed0166 --- /dev/null +++ b/samples/inst-context/run.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +out/inst-context -f out/wasm-apps/testapp.wasm diff --git a/samples/inst-context/src/main.c b/samples/inst-context/src/main.c new file mode 100644 index 000000000..0d774735e --- /dev/null +++ b/samples/inst-context/src/main.c @@ -0,0 +1,166 @@ + +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_export.h" +#include "bh_read_file.h" +#include "bh_getopt.h" +#include "my_context.h" + +int32_t +add_native(int32_t n); +void *my_context_key; +struct my_context my_context; +int my_dtor_called; + +wasm_module_inst_t module_inst = NULL; + +void +print_usage(void) +{ + fprintf(stdout, "Options:\r\n"); + fprintf(stdout, " -f [path of wasm file] \n"); +} + +void +my_context_dtor(wasm_module_inst_t inst, void *ctx) +{ + printf("%s called\n", __func__); + my_dtor_called++; + bh_assert(ctx == &my_context); + bh_assert(inst == module_inst); +} + +int +main(int argc, char *argv_main[]) +{ + static char global_heap_buf[512 * 1024]; + char *buffer; + char error_buf[128]; + int opt; + char *wasm_path = NULL; + + wasm_module_t module = NULL; + wasm_exec_env_t exec_env = NULL; + uint32 buf_size, stack_size = 8092, heap_size = 8092; + + RuntimeInitArgs init_args; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + while ((opt = getopt(argc, argv_main, "hf:")) != -1) { + switch (opt) { + case 'f': + wasm_path = optarg; + break; + case 'h': + print_usage(); + return 0; + case '?': + print_usage(); + return 0; + } + } + if (optind == 1) { + print_usage(); + return 0; + } + + // Define an array of NativeSymbol for the APIs to be exported. + // Note: the array must be static defined since runtime + // will keep it after registration + // For the function signature specifications, goto the link: + // https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md + + static NativeSymbol native_symbols[] = { { "add_native", add_native, "(i)i", + NULL } }; + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + // Native symbols need below registration phase + init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + init_args.native_module_name = "env"; + init_args.native_symbols = native_symbols; + + if (!wasm_runtime_full_init(&init_args)) { + printf("Init runtime environment failed.\n"); + return -1; + } + + my_context_key = wasm_runtime_create_context_key(my_context_dtor); + if (!my_context_key) { + printf("wasm_runtime_create_context_key failed.\n"); + return -1; + } + + buffer = bh_read_file_to_buffer(wasm_path, &buf_size); + + if (!buffer) { + printf("Open wasm app file [%s] failed.\n", wasm_path); + goto fail; + } + + module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf, + sizeof(error_buf)); + if (!module) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + + module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)); + + if (!module_inst) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + + my_context.x = 100; + wasm_runtime_set_context(module_inst, my_context_key, &my_context); + + exec_env = wasm_runtime_create_exec_env(module_inst, stack_size); + if (!exec_env) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + + wasm_function_inst_t func3 = + wasm_runtime_lookup_function(module_inst, "calculate", NULL); + if (!func3) { + printf("The wasm function calculate is not found.\n"); + goto fail; + } + + uint32_t argv3[1] = { 3 }; + if (wasm_runtime_call_wasm(exec_env, func3, 1, argv3)) { + uint32_t result = *(uint32_t *)argv3; + printf("Native finished calling wasm function: calculate, return: %d\n", + result); + bh_assert(result == 103); /* argv3[0] + my_context.x */ + } + else { + printf("call wasm function calculate failed. error: %s\n", + wasm_runtime_get_exception(module_inst)); + goto fail; + } + +fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) { + bh_assert(my_dtor_called == 0); + wasm_runtime_deinstantiate(module_inst); + bh_assert(my_dtor_called == 1); + } + if (module) + wasm_runtime_unload(module); + if (buffer) + BH_FREE(buffer); + if (my_context_key) + wasm_runtime_destroy_context_key(my_context_key); + wasm_runtime_destroy(); + return 0; +} diff --git a/samples/inst-context/src/my_context.h b/samples/inst-context/src/my_context.h new file mode 100644 index 000000000..db49c1e3b --- /dev/null +++ b/samples/inst-context/src/my_context.h @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +struct my_context { + int x; +}; + +extern void *my_context_key; diff --git a/samples/inst-context/src/native_impl.c b/samples/inst-context/src/native_impl.c new file mode 100644 index 000000000..1254b4a22 --- /dev/null +++ b/samples/inst-context/src/native_impl.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2023 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_export.h" +#include "my_context.h" + +int32_t +add_native(wasm_exec_env_t exec_env, int32_t n) +{ + wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env); + struct my_context *ctx = wasm_runtime_get_context(inst, my_context_key); + return n + ctx->x; +} diff --git a/samples/inst-context/wasm-apps/testapp.c b/samples/inst-context/wasm-apps/testapp.c new file mode 100644 index 000000000..1774dcd07 --- /dev/null +++ b/samples/inst-context/wasm-apps/testapp.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +int32_t +add_native(int32_t n); + +int32_t +calculate(int32_t n) +{ + printf("calling into WASM function: %s\n", __FUNCTION__); + return add_native(n); +} diff --git a/samples/mem_allocator/CMakeLists.txt b/samples/mem-allocator/CMakeLists.txt similarity index 100% rename from samples/mem_allocator/CMakeLists.txt rename to samples/mem-allocator/CMakeLists.txt diff --git a/samples/mem_allocator/main.c b/samples/mem-allocator/main.c similarity index 100% rename from samples/mem_allocator/main.c rename to samples/mem-allocator/main.c diff --git a/samples/native-lib/README.md b/samples/native-lib/README.md index 2bf65814d..80500ade0 100644 --- a/samples/native-lib/README.md +++ b/samples/native-lib/README.md @@ -62,6 +62,7 @@ cd build The output is: ```bash +init_native_lib in test_hello2.c called Hello World! 10 + 20 = 30 sqrt(10, 20) = 500 @@ -72,5 +73,6 @@ Message from test_hello: Hello, main. This is test_hello_wrapper! test_hello2("main", 0x0, 0) = 85 malloc(86) = 0x24e8 test_hello2("main", 0x24e8, 86) = 85 -Message from test_hello2: Hello, main. This is test_hello2_wrapper! Your wasm_module_inst_t is 0x7fd443704990. +Message from test_hello2: Hello, main. This is test_hello2_wrapper! Your wasm_module_inst_t is 0x7fe0e6804280. +deinit_native_lib in test_hello2.c called ``` diff --git a/samples/native-lib/test_hello2.c b/samples/native-lib/test_hello2.c index 2c8f69ed6..5dae79ca4 100644 --- a/samples/native-lib/test_hello2.c +++ b/samples/native-lib/test_hello2.c @@ -57,3 +57,16 @@ get_native_lib(char **p_module_name, NativeSymbol **p_native_symbols) *p_native_symbols = native_symbols; return sizeof(native_symbols) / sizeof(NativeSymbol); } + +int +init_native_lib() +{ + printf("%s in test_hello2.c called\n", __func__); + return 0; +} + +void +deinit_native_lib() +{ + printf("%s in test_hello2.c called\n", __func__); +} diff --git a/samples/sgx-ra/README.md b/samples/sgx-ra/README.md index 39a2f2d9c..9270c96f1 100644 --- a/samples/sgx-ra/README.md +++ b/samples/sgx-ra/README.md @@ -7,52 +7,52 @@ This sample demonstrates how to execute Remote Attestation on SGX with [librats] SGX-RA requires to have installed: - the WASI-SDK, located in `/opt/wasi-sdk` - - CMake >= 3.11, which is not provided on Ubuntu 18.04 (use [Kitware APT Repository](https://apt.kitware.com/)) ### Intel SGX dependencies Before starting, we need to download and install [SGX SDK](https://download.01.org/intel-sgx/latest/linux-latest/distro) and [SGX DCAP Library](https://download.01.org/intel-sgx/latest/dcap-latest) referring to this [guide](https://download.01.org/intel-sgx/sgx-dcap/1.8/linux/docs/Intel_SGX_DCAP_Linux_SW_Installation_Guide.pdf). -The following commands are an example of the SGX environment installation on Ubuntu 18.04. +The following commands are an example of the SGX environment installation on Ubuntu 20.04. ``` shell # Set your platform, you can get the platforms list on # https://download.01.org/intel-sgx/latest/linux-latest/distro $ cd $HOME -$ SGX_PLATFORM=ubuntu18.04-server -$ SGX_SDK_VERSION=2.17.100.3 +$ OS_PLATFORM=ubuntu20.04 +$ SGX_PLATFORM=$OS_PLATFORM-server +$ SGX_RELEASE_VERSION=1.17 $ SGX_DRIVER_VERSION=1.41 +$ SGX_SDK_VERSION=2.20.100.4 # install the dependencies $ sudo apt-get update -$ sudo apt-get install -y dkms +$ sudo apt-get install -y build-essential ocaml automake autoconf libtool wget python3 libssl-dev dkms zip cmake +$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 # install SGX Driver -$ wget https://download.01.org/intel-sgx/latest/linux-latest/distro/$SGX_PLATFORM/sgx_linux_x64_driver_$SGX_DRIVER_VERSION.bin +$ wget https://download.01.org/intel-sgx/sgx-dcap/$SGX_RELEASE_VERSION/linux/distro/$SGX_PLATFORM/sgx_linux_x64_driver_$SGX_DRIVER_VERSION.bin $ chmod +x sgx_linux_x64_driver_$SGX_DRIVER_VERSION.bin $ sudo ./sgx_linux_x64_driver_$SGX_DRIVER_VERSION.bin # install SGX SDK -$ wget https://download.01.org/intel-sgx/latest/linux-latest/distro/$SGX_PLATFORM/sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin +$ wget https://download.01.org/intel-sgx/sgx-dcap/$SGX_RELEASE_VERSION/linux/distro/$SGX_PLATFORM/sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin $ chmod +x sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin -$ sudo ./sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin +$ sudo ./sgx_linux_x64_sdk_$SGX_SDK_VERSION.bin --prefix /opt/intel # install SGX DCAP Library -$ echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu bionic main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list > /dev/null -$ wget -O - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add - +$ echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu focal main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list +$ wget -O - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add $ sudo apt-get update -$ sudo apt-get install -y libsgx-uae-service libsgx-dcap-default-qpl-dev libsgx-dcap-ql-dev libsgx-dcap-quote-verify-dev +$ sudo apt-get install -y libsgx-epid libsgx-quote-ex libsgx-dcap-ql libsgx-enclave-common-dev libsgx-dcap-ql-dev libsgx-dcap-default-qpl-dev libsgx-dcap-quote-verify-dev # install SGX SSL Library $ git clone https://github.com/intel/linux-sgx.git $ cd linux-sgx && make preparation -$ sudo cp external/toolset/{current_distr}/* /usr/local/bin +$ sudo cp external/toolset/$OS_PLATFORM/* /usr/local/bin $ # Verify that the paths are correctly set $ which ar as ld objcopy objdump ranlib $ cd ../ $ git clone https://github.com/intel/intel-sgx-ssl.git -$ wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz -$ cp openssl-1.1.1q.tar.gz intel-sgx-ssl/openssl_source -$ rm -f openssl-1.1.1q.tar.gz +$ wget https://www.openssl.org/source/openssl-1.1.1v.tar.gz -O intel-sgx-ssl/openssl_source/openssl-1.1.1v.tar.gz $ cd intel-sgx-ssl/Linux $ source /opt/intel/sgxsdk/environment $ make all @@ -70,7 +70,7 @@ sudo usermod -a -G sgx_prv Intel DCAP connects to Intel PCS to download the attestation collateral for SGX-enabled machines. Intel provides a [quick install guide](https://www.intel.com/content/www/us/en/developer/articles/guide/intel-software-guard-extensions-data-center-attestation-primitives-quick-install-guide.html) to set up a simplified environment. -This section summarizes the commands to issue for setting up a working environment on Ubuntu 18.04. +This section summarizes the commands to issue for setting up a working environment on Ubuntu 20.04. ### Subscribe to Intel PCS Web services @@ -86,11 +86,9 @@ Intel provides an implementation of the cache mechanism. The following commands set up Intel PCCS. ```shell # install Node.js -$ curl -o setup.sh -sL https://deb.nodesource.com/setup_14.x -$ chmod a+x setup.sh -$ sudo ./setup.sh +$ curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs # install PCCS software -$ sudo apt-get install -y cracklib-runtime sqlite3 python build-essential +$ sudo apt-get install -y cracklib-runtime $ sudo apt-get install -y sgx-dcap-pccs ``` @@ -160,9 +158,10 @@ Adapt the configuration file of `PCKIDRetrievalTool` located in `/opt/intel/sgx- Save your changes and run the provisioning tool. ```shell -$ PCKIDRetrievalTool -Intel(R) Software Guard Extensions PCK Cert ID Retrieval Tool Version 1.14.100.3 +$ sudo PCKIDRetrievalTool +Intel(R) Software Guard Extensions PCK Cert ID Retrieval Tool Version 1.17.100.4 +Registration status has been set to completed status. the data has been sent to cache server successfully and pckid_retrieval.csv has been generated successfully! ``` diff --git a/samples/wasi-threads/wasm-apps/no_pthread.c b/samples/wasi-threads/wasm-apps/no_pthread.c index dc3c95530..16661bd83 100644 --- a/samples/wasi-threads/wasm-apps/no_pthread.c +++ b/samples/wasi-threads/wasm-apps/no_pthread.c @@ -50,16 +50,11 @@ main(int argc, char **argv) } thread_id = __wasi_thread_spawn(&data); - if (thread_id < 0) { - printf("Failed to create thread: %d\n", thread_id); - ret = EXIT_FAILURE; - goto final; - } + ASSERT_VALID_TID(thread_id); if (__builtin_wasm_memory_atomic_wait32(&data.th_ready, 0, SECOND) == 2) { printf("Timeout\n"); - ret = EXIT_FAILURE; - goto final; + return EXIT_FAILURE; } printf("Thread completed, new value: %d, thread id: %d\n", data.value, @@ -67,7 +62,6 @@ main(int argc, char **argv) assert(thread_id == data.thread_id); -final: start_args_deinit(&data.base); return ret; diff --git a/samples/wasi-threads/wasm-apps/wasi_thread_start.h b/samples/wasi-threads/wasm-apps/wasi_thread_start.h index a46917d0a..2427fd2b9 100644 --- a/samples/wasi-threads/wasm-apps/wasi_thread_start.h +++ b/samples/wasi-threads/wasm-apps/wasi_thread_start.h @@ -7,6 +7,10 @@ #define STACK_SIZE 32 * 1024 // same as the main stack +/* See https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids */ +#define ASSERT_VALID_TID(TID) \ + assert(TID >= 1 && TID <= 0x1FFFFFFF && "Invalid thread ID") + typedef struct { void *stack; } start_args_t; diff --git a/samples/wasm-c-api/src/hello.c b/samples/wasm-c-api/src/hello.c index 3ebea87b0..966e141d7 100644 --- a/samples/wasm-c-api/src/hello.c +++ b/samples/wasm-c-api/src/hello.c @@ -65,6 +65,12 @@ int main(int argc, const char* argv[]) { } fclose(file); + if (!wasm_module_validate(store, &binary)) { + printf("> Error validate module!\n"); + wasm_byte_vec_delete(&binary); + return 1; + } + // Compile. printf("Compiling module...\n"); own wasm_module_t* module = wasm_module_new(store, &binary); diff --git a/samples/workload/XNNPACK/CMakeLists.txt b/samples/workload/XNNPACK/CMakeLists.txt index aef138d5e..41cdd583f 100644 --- a/samples/workload/XNNPACK/CMakeLists.txt +++ b/samples/workload/XNNPACK/CMakeLists.txt @@ -1,147 +1,198 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 3.14) project(xnnpack_wasm) ################ EMCC ################ include(ExternalProject) -ExternalProject_Add(xnnpack +# grep xnnpack_benchmark -A 1 BUILD.bazel \ +# | grep "name =" \ +# | awk '{print $3}' \ +# | sed -e 's/\"//g; s/,//g; s/^/\"/g; s/$/\"/g' +list(APPEND NATIVE_BENCHMARKS + "qs8_dwconv_bench" + "qs8_f32_vcvt_bench" + "qs8_gemm_bench" + "qs8_requantization_bench" + "qs8_vadd_bench" + "qs8_vaddc_bench" + "qs8_vcvt_bench" + "qs16_qs8_vcvt_bench" + "qs8_vlrelu_bench" + "qs8_vmul_bench" + "qs8_vmulc_bench" + "qu8_f32_vcvt_bench" + "qu8_gemm_bench" + "qu8_requantization_bench" + "qu8_vadd_bench" + "qu8_vaddc_bench" + "qu8_vcvt_bench" + "qu8_vlrelu_bench" + "qu8_vmul_bench" + "qu8_vmulc_bench" + "bf16_gemm_bench" + "f16_f32acc_igemm_bench" + "f16_igemm_bench" + "f16_f32acc_gemm_bench" + "f16_gemm_bench" + "f16_raddstoreexpminusmax_bench" + "f16_spmm_bench" + "f16_vsigmoid_bench" + "f16_vtanh_bench" + "f16_f32_vcvt_bench" + "f32_igemm_bench" + "f32_conv_hwc_bench" + "f16_conv_hwc2chw_bench" + "f16_gavgpool_cw_bench" + "f32_gavgpool_cw_bench" + "f32_conv_hwc2chw_bench" + "f16_dwconv_bench" + "f32_dwconv_bench" + "f32_dwconv2d_chw_bench" + "f16_dwconv2d_chw_bench" + "f32_f16_vcvt_bench" + "xx_transpose_bench" + "x8_transpose_bench" + "x16_transpose_bench" + "x24_transpose_bench" + "x32_transpose_bench" + "x64_transpose_bench" + "f32_bgemm_bench" + "f32_gemm_bench" + "f32_qs8_vcvt_bench" + "f32_qu8_vcvt_bench" + "f32_raddexpminusmax_bench" + "f32_raddextexp_bench" + "f32_raddstoreexpminusmax_bench" + "f32_rmax_bench" + "f32_spmm_bench" + "f32_softmax_bench" + "f16_velu_bench" + "f32_velu_bench" + "f32_vhswish_bench" + "f32_vlrelu_bench" + "f32_vrelu_bench" + "f32_vscaleexpminusmax_bench" + "f32_vscaleextexp_bench" + "f32_vsigmoid_bench" + "f16_vsqrt_bench" + "f32_vsqrt_bench" + "f32_vtanh_bench" + "f32_im2col_gemm_bench" + "rounding_bench" + "s16_rmaxabs_bench" + "s16_window_bench" + "u32_filterbank_accumulate_bench" + "u32_filterbank_subtract_bench" + "u32_vlog_bench" + "u64_u32_vsqrtshift_bench" + "i16_vlshift_bench" + "cs16_vsquareabs_bench" + "cs16_bfly4_bench" + "cs16_fftr_bench" + "x8_lut_bench" + "x32_packw_bench" + "x16_packw_bench" + "abs_bench" + "average_pooling_bench" + "bankers_rounding_bench" + "ceiling_bench" + "channel_shuffle_bench" + "convert_bench" + "convolution_bench" + "deconvolution_bench" + "elu_bench" + "floor_bench" + "global_average_pooling_bench" + "hardswish_bench" + "leaky_relu_bench" + "max_pooling_bench" + "negate_bench" + "prelu_bench" + "sigmoid_bench" + "softmax_bench" + "square_bench" + "square_root_bench" + "tanh_bench" + "truncation_bench" + "f16_dwconv_e2e_bench" + "f16_gemm_e2e_bench" + "f32_dwconv_e2e_bench" + "f32_gemm_e2e_bench" + "qs8_dwconv_e2e_bench" + "qs8_gemm_e2e_bench" + "qu8_gemm_e2e_bench" + "qu8_dwconv_e2e_bench" + "end2end_bench" + "f16_exp_ulp_eval" + "f16_expminus_ulp_eval" + "f16_expm1minus_ulp_eval" + "f16_sigmoid_ulp_eval" + "f16_sqrt_ulp_eval" + "f16_tanh_ulp_eval" + "f32_exp_ulp_eval" + "f32_expminus_ulp_eval" + "f32_expm1minus_ulp_eval" + "f32_extexp_ulp_eval" + "f32_sigmoid_ulp_eval" + "f32_sqrt_ulp_eval" + "f32_tanh_ulp_eval" +) + +# Only Download +ExternalProject_Add(xnnpack-download PREFIX xnnpack GIT_REPOSITORY https://github.com/google/XNNPACK.git - GIT_TAG 4570a7151aa4f3e57eca14a575eeff6bb13e26be + GIT_TAG b9d4073a6913891ce9cbd8965c8d506075d2a45a GIT_PROGRESS ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack - UPDATE_COMMAND git restore . - && cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/google3/third_party/XNNPACK/microkernels.bzl - ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/ - && git apply ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack.patch + UPDATE_COMMAND "" + PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack.patch CONFIGURE_COMMAND "" - # grep xnnpack_benchmark -A 1 BUILD.bazel \ - # | grep "name =" \ - # | awk '{print $3}' \ - # | sed -e 's/\"//g' -e 's/,//g' -e 's/^/\/\/:/g' - BUILD_COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack - && bazel --output_user_root=build-user-output build -c opt --config=wasm - //:qs8_dwconv_bench.wasm - //:qs8_f32_vcvt_bench.wasm - //:qs8_gemm_bench.wasm - //:qs8_requantization_bench.wasm - //:qs8_vadd_bench.wasm - //:qs8_vaddc_bench.wasm - //:qs8_vcvt_bench.wasm - //:qs8_vlrelu_bench.wasm - //:qs8_vmul_bench.wasm - //:qs8_vmulc_bench.wasm - //:qu8_f32_vcvt_bench.wasm - //:qu8_gemm_bench.wasm - //:qu8_requantization_bench.wasm - //:qu8_vadd_bench.wasm - //:qu8_vaddc_bench.wasm - //:qu8_vcvt_bench.wasm - //:qu8_vlrelu_bench.wasm - //:qu8_vmul_bench.wasm - //:qu8_vmulc_bench.wasm - //:bf16_gemm_bench.wasm - //:f16_igemm_bench.wasm - //:f16_gemm_bench.wasm - //:f16_raddstoreexpminusmax_bench.wasm - //:f16_spmm_bench.wasm - //:f16_vsigmoid_bench.wasm - //:f16_f32_vcvt_bench.wasm - //:f32_igemm_bench.wasm - //:f32_conv_hwc_bench.wasm - //:f16_conv_hwc2chw_bench.wasm - //:f16_gavgpool_cw_bench.wasm - //:f32_gavgpool_cw_bench.wasm - //:f32_conv_hwc2chw_bench.wasm - //:f16_dwconv_bench.wasm - //:f32_dwconv_bench.wasm - //:f32_dwconv2d_chw_bench.wasm - //:f16_dwconv2d_chw_bench.wasm - //:f32_f16_vcvt_bench.wasm - //:xx_transpose_bench.wasm - //:x8_transpose_bench.wasm - //:x16_transpose_bench.wasm - //:x24_transpose_bench.wasm - //:x32_transpose_bench.wasm - //:x64_transpose_bench.wasm - //:f32_gemm_bench.wasm - //:f32_qs8_vcvt_bench.wasm - //:f32_qu8_vcvt_bench.wasm - //:f32_raddexpminusmax_bench.wasm - //:f32_raddextexp_bench.wasm - //:f32_raddstoreexpminusmax_bench.wasm - //:f32_rmax_bench.wasm - //:f32_spmm_bench.wasm - //:f32_softmax_bench.wasm - //:f16_velu_bench.wasm - //:f32_velu_bench.wasm - //:f32_vhswish_bench.wasm - //:f32_vlrelu_bench.wasm - //:f32_vrelu_bench.wasm - //:f32_vscaleexpminusmax_bench.wasm - //:f32_vscaleextexp_bench.wasm - //:f32_vsigmoid_bench.wasm - //:f16_vsqrt_bench.wasm - //:f32_vsqrt_bench.wasm - //:f32_im2col_gemm_bench.wasm - //:rounding_bench.wasm - //:s16_rmaxabs_bench.wasm - //:s16_window_bench.wasm - //:u32_filterbank_accumulate_bench.wasm - //:u32_filterbank_subtract_bench.wasm - //:u32_vlog_bench.wasm - //:u64_u32_vsqrtshift_bench.wasm - //:i16_vlshift_bench.wasm - //:cs16_vsquareabs_bench.wasm - //:cs16_bfly4_bench.wasm - //:cs16_fftr_bench.wasm - //:x8_lut_bench.wasm - //:abs_bench.wasm - //:average_pooling_bench.wasm - //:bankers_rounding_bench.wasm - //:ceiling_bench.wasm - //:channel_shuffle_bench.wasm - //:convert_bench.wasm - //:convolution_bench.wasm - //:deconvolution_bench.wasm - //:elu_bench.wasm - //:floor_bench.wasm - //:global_average_pooling_bench.wasm - //:hardswish_bench.wasm - //:leaky_relu_bench.wasm - //:max_pooling_bench.wasm - //:negate_bench.wasm - //:sigmoid_bench.wasm - //:prelu_bench.wasm - //:softmax_bench.wasm - //:square_bench.wasm - //:square_root_bench.wasm - //:truncation_bench.wasm - //:f16_gemm_e2e_bench.wasm - //:f32_dwconv_e2e_bench.wasm - //:f32_gemm_e2e_bench.wasm - //:qs8_dwconv_e2e_bench.wasm - //:qs8_gemm_e2e_bench.wasm - //:qu8_gemm_e2e_bench.wasm - //:qu8_dwconv_e2e_bench.wasm - //:end2end_bench.wasm - //:f16_exp_ulp_eval.wasm - //:f16_expminus_ulp_eval.wasm - //:f16_expm1minus_ulp_eval.wasm - //:f16_sigmoid_ulp_eval.wasm - //:f16_sqrt_ulp_eval.wasm - //:f32_exp_ulp_eval.wasm - //:f32_expminus_ulp_eval.wasm - //:f32_expm1minus_ulp_eval.wasm - //:f32_extexp_ulp_eval.wasm - //:f32_sigmoid_ulp_eval.wasm - //:f32_sqrt_ulp_eval.wasm - //:f32_tanh_ulp_eval.wasm - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/bazel-out/wasm-opt/bin/ - ${CMAKE_BINARY_DIR}/wasm-opt + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" ) + +set(WAMRC "${CMAKE_CURRENT_SOURCE_DIR}/../../../wamr-compiler/build/wamrc") +if(EXISTS ${WAMRC}) + message("-- Will generate .aot") +else() + message("Will generate .wasm") +endif() + +foreach(BENCHMARK IN LISTS NATIVE_BENCHMARKS) + string(CONCAT WASM_BENCHMARK "//:" ${BENCHMARK} "-wasm") + string(CONCAT WASM_OUTPUT ${BENCHMARK} ".wasm") + + add_custom_command( + OUTPUT ${WASM_OUTPUT} + COMMAND bazel --output_user_root=build-user-output build -c opt --config=wasm ${WASM_BENCHMARK} + && ${CMAKE_COMMAND} -E copy_if_different ./bazel-bin/${WASM_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${WASM_OUTPUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack + DEPENDS xnnpack-download + COMMENT "Generating ${WASM_OUTPUT} ..." + ) + + set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${CMAKE_CURRENT_BINARY_DIR}/${WASM_OUTPUT}) + + if(EXISTS ${WAMRC}) + string(CONCAT AOT_OUTPUT ${BENCHMARK} ".aot") + + add_custom_command( + OUTPUT ${AOT_OUTPUT} + COMMAND ${WAMRC} -o ${AOT_OUTPUT} ${WASM_OUTPUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${WASM_OUTPUT} + COMMENT "Generating ${AOT_OUTPUT} ..." + ) + + add_custom_target(${BENCHMARK} ALL DEPENDS ${AOT_OUTPUT}) + else() + add_custom_target(${BENCHMARK} ALL DEPENDS ${WASM_OUTPUT}) + endif() +endforeach() + diff --git a/samples/workload/XNNPACK/README.md b/samples/workload/XNNPACK/README.md index 7984d9cee..625ef7f79 100644 --- a/samples/workload/XNNPACK/README.md +++ b/samples/workload/XNNPACK/README.md @@ -9,26 +9,7 @@ please refer to [installation instructions](../README.md). ## Build XNNPACK -```bash -cd /samples/workload/XNNPACK -mkdir build -cd build -cmake .. -``` -The wasm files are generated under folder samples/workload/XNNPACK/xnnpack/bazel-bin. - -## Run benchmarks - -Firstly please build iwasm with simd, libc-emcc and lib-pthread support: - -``` bash -$ cd /product-mini/platforms/linux/ -$ mkdir build && cd build -$ cmake .. -DWAMR_BUILD_LIBC_EMCC=1 -DWAMR_BUILD_LIB_PTHREAD=1 -$ make -``` - -And please build wamrc: +please build wamrc: ``` bash cd /wamr-compiler @@ -38,11 +19,31 @@ cmake .. make ``` -Then compile wasm file to aot file and run: +And then build xnnpack standalone wasm files -``` shell -$ cd /samples/workload/XNNPACK/xnnpack/bazel-bin -$ wamrc -o average_pooling_bench.aot average_pooling_bench.wasm (or other wasm files) -$ iwasm average_pooling_bench.aot +```bash +$ cd /samples/workload/XNNPACK +$ cmake -S . -B build +$ cmake --build build +``` + +Generated .wasm(and .aot) files are under *samples/workload/XNNPACK/build*. + +## Run benchmarks + +Firstly please build iwasm with simd, libc-emcc and lib-pthread supporting: + +``` bash +$ cd /product-mini/platforms/linux/ +$ mkdir build && cd build +$ cmake .. -DWAMR_BUILD_LIBC_EMCC=1 -DWAMR_BUILD_LIB_PTHREAD=1 +$ make +``` + +Then run: + +``` shell +$ cd /samples/workload/XNNPACK/build +$ iwasm average_pooling_bench.aot # (or other aot files) ``` diff --git a/samples/workload/XNNPACK/xnnpack.patch b/samples/workload/XNNPACK/xnnpack.patch index 3fb6b230b..d7680d347 100644 --- a/samples/workload/XNNPACK/xnnpack.patch +++ b/samples/workload/XNNPACK/xnnpack.patch @@ -1,141 +1,138 @@ diff --git a/.bazelrc b/.bazelrc -index 688279da1..376996885 100644 +index fcaff1063..e61d53337 100644 --- a/.bazelrc +++ b/.bazelrc -@@ -53,4 +53,9 @@ build:ios_fat --watchos_cpus=armv7k - build:macos --apple_platform_type=macos +@@ -1,6 +1,7 @@ + # Basic build settings + build --jobs 128 + build --cxxopt='-std=gnu++14' ++build --incompatible_enable_cc_toolchain_resolution + + # Sets the default Apple platform to macOS. + build --apple_platform_type=macos +@@ -55,3 +56,10 @@ build:macos --apple_platform_type=macos build:macos_arm64 --config=macos --build:macos_arm64 --cpu=darwin_arm64 -\ No newline at end of file -+build:macos_arm64 --cpu=darwin_arm64 + build:macos_arm64 --cpu=darwin_arm64 + ++# Emscripten configs ++build:wasm --copt="-Wno-unused" ++build:wasm --copt="-Wno-unused-function" ++build:wasm --copt="-Wno-unused-but-set-variable" +build:wasm --cpu=wasm +build:wasm --features=wasm_simd -+build:wasm --crosstool_top=@emsdk//emscripten_toolchain:everything -+build:wasm --host_crosstool_top=@bazel_tools//tools/cpp:toolchain diff --git a/WORKSPACE b/WORKSPACE -index cd8960ffa..787e03ca8 100644 +index 2e568088b..3961371ca 100644 --- a/WORKSPACE +++ b/WORKSPACE -@@ -29,8 +29,9 @@ http_archive( - # Google Benchmark library, used in micro-benchmarks. - http_archive( - name = "com_google_benchmark", -- strip_prefix = "benchmark-main", -- urls = ["https://github.com/google/benchmark/archive/main.zip"], -+ sha256 = "1ba14374fddcd9623f126b1a60945e4deac4cdc4fb25a5f25e7f779e36f2db52", -+ strip_prefix = "benchmark-d2a8a4ee41b923876c034afb939c4fc03598e622", -+ urls = ["https://github.com/google/benchmark/archive/d2a8a4ee41b923876c034afb939c4fc03598e622.zip"], +@@ -83,7 +83,23 @@ http_archive( ) - # FP16 library, used for half-precision conversions -@@ -92,8 +93,25 @@ http_archive( - ], - ) + # Android NDK location and version is auto-detected from $ANDROID_NDK_HOME environment variable +-android_ndk_repository(name = "androidndk") ++# android_ndk_repository(name = "androidndk") -+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + # Android SDK location and API is auto-detected from $ANDROID_HOME environment variable +-android_sdk_repository(name = "androidsdk") ++# android_sdk_repository(name = "androidsdk") ++ +http_archive( + name = "emsdk", -+ # Use emsdk-3.0.0 since the larger version may: -+ # - compress the wasm file into a tar file but not directly generate wasm file -+ # - generate incomplete implementation of libc API, e.g. throw exception in getentropy -+ strip_prefix = "emsdk-3.0.0/bazel", -+ url = "https://github.com/emscripten-core/emsdk/archive/refs/tags/3.0.0.tar.gz", -+ sha256 = "a41dccfd15be9e85f923efaa0ac21943cbab77ec8d39e52f25eca1ec61a9ac9e" ++ sha256 = "5fa6f5eb45a4d50264610c4c9e1c155535359b63bfaad69b4e5101d16c1e7e32", ++ strip_prefix = "emsdk-a896e3d066448b3530dbcaa48869fafefd738f57/bazel", ++ url = "https://github.com/emscripten-core/emsdk/archive/a896e3d066448b3530dbcaa48869fafefd738f57.tar.gz", +) + +load("@emsdk//:deps.bzl", emsdk_deps = "deps") +emsdk_deps() + +load("@emsdk//:emscripten_deps.bzl", emsdk_emscripten_deps = "emscripten_deps") -+emsdk_emscripten_deps() ++emsdk_emscripten_deps(emscripten_version = "3.1.44") + - # Android NDK location and version is auto-detected from $ANDROID_NDK_HOME environment variable --android_ndk_repository(name = "androidndk") -+#android_ndk_repository(name = "androidndk") ++load("@emsdk//:toolchains.bzl", "register_emscripten_toolchains") ++register_emscripten_toolchains() +diff --git a/bench/utils.cc b/bench/utils.cc +index 3b32503a7..656845336 100644 +--- a/bench/utils.cc ++++ b/bench/utils.cc +@@ -456,3 +456,13 @@ CodeMemoryHelper::~CodeMemoryHelper() { - # Android SDK location and API is auto-detected from $ANDROID_HOME environment variable --android_sdk_repository(name = "androidsdk") -+#android_sdk_repository(name = "androidsdk") + } // namespace utils + } // namespace benchmark ++ ++ ++extern "C" ++__attribute__((import_module("env"), import_name("getentropy"))) int import_getentropy(void* buffer, size_t length); ++ ++extern "C" ++int getentropy(void* buffer, size_t length) ++{ ++ return import_getentropy(buffer, length); ++} diff --git a/build_defs.bzl b/build_defs.bzl -index b8217a18d..6f2d1675e 100644 +index 01b436eb7..2738fd50a 100644 --- a/build_defs.bzl +++ b/build_defs.bzl -@@ -380,7 +380,7 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): - explicitly specified. - """ - native.cc_binary( -- name = name, -+ name = name + ".wasm", - srcs = srcs, - copts = xnnpack_std_cxxopts() + [ - "-Iinclude", -@@ -405,5 +405,5 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): +@@ -1,6 +1,7 @@ + """Build definitions and rules for XNNPACK.""" + +-load(":emscripten.bzl", "xnnpack_emscripten_benchmark_linkopts", "xnnpack_emscripten_deps", "xnnpack_emscripten_minimal_linkopts", "xnnpack_emscripten_test_linkopts") ++load(":emscripten.bzl", "xnnpack_emscripten_benchmark_linkopts", "xnnpack_emscripten_deps", "xnnpack_emscripten_minimal_linkopts", "xnnpack_emscripten_test_linkopts", "xnnpack_emscripten_standalone_benchmark_linkopts") ++load("@emsdk//emscripten_toolchain:wasm_rules.bzl", "wasm_cc_binary") + + def xnnpack_visibility(): + """Visibility of :XNNPACK target. +@@ -393,7 +394,8 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): + "//conditions:default": ["-Wno-unused-function"], + }) + copts, + linkopts = select({ +- ":emscripten": xnnpack_emscripten_benchmark_linkopts(), ++ ":emscripten": xnnpack_emscripten_standalone_benchmark_linkopts(), ++ ":emscripten_wasmsimd": xnnpack_emscripten_standalone_benchmark_linkopts(), + ":windows_x86_64_mingw": ["-lshlwapi"], + ":windows_x86_64_msys": ["-lshlwapi"], + "//conditions:default": [], +@@ -405,5 +407,16 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): ":emscripten": xnnpack_emscripten_deps(), "//conditions:default": [], }), - tags = tags, -+ tags = tags, ++ tags = tags, ++ ) ++ ++ wasm_cc_binary( ++ name = name + "-wasm", ++ cc_target = ":" + name, ++ threads = "off", ++ simd = True, ++ standalone= True, ++ outputs = [ ++ name + ".wasm", ++ ] ) diff --git a/emscripten.bzl b/emscripten.bzl -index f1557a7b1..7f964a094 100644 +index f1557a7b1..a3c4f93b9 100644 --- a/emscripten.bzl +++ b/emscripten.bzl -@@ -25,12 +25,19 @@ def xnnpack_emscripten_benchmark_linkopts(): - """Emscripten-specific linkopts for benchmarks.""" - return [ - "-s ASSERTIONS=1", -- "-s ENVIRONMENT=node,shell,web", -- "-s ERROR_ON_UNDEFINED_SYMBOLS=1", -- "-s EXIT_RUNTIME=1", +@@ -33,6 +33,21 @@ def xnnpack_emscripten_benchmark_linkopts(): + "--pre-js $(location :preamble.js.lds)", + ] + ++def xnnpack_emscripten_standalone_benchmark_linkopts(): ++ return [ ++ "-s ASSERTIONS=1", + "-s ERROR_ON_UNDEFINED_SYMBOLS=0", - "-s ALLOW_MEMORY_GROWTH=1", - "-s TOTAL_MEMORY=536870912", # 512M -- "--pre-js $(location :preamble.js.lds)", ++ "-s ALLOW_MEMORY_GROWTH=1", ++ "-s TOTAL_MEMORY=536870912", # 512M + "-s USE_PTHREADS=0", + "-s STANDALONE_WASM=1", -+ "-Wno-unused", -+ "-Wno-unused-variable", -+ "-Wno-unused-command-line-argument", + "-Wl,--export=__heap_base", + "-Wl,--export=__data_end", + "-Wl,--export=malloc", + "-Wl,--export=free", -+ "--oformat=wasm", - ] - ++ ] ++ ++ def xnnpack_emscripten_deps(): -diff --git a/src/log.c b/src/log.c -index 5715f2f85..4b3e4261b 100644 ---- a/src/log.c -+++ b/src/log.c -@@ -55,7 +55,7 @@ - #endif - - #if XNN_LOG_TO_STDIO --static void xnn_vlog(int output_handle, const char* prefix, size_t prefix_length, const char* format, va_list args) { -+void xnn_vlog(int output_handle, const char* prefix, size_t prefix_length, const char* format, va_list args) { - char stack_buffer[XNN_LOG_STACK_BUFFER_SIZE]; - char* heap_buffer = NULL; - char* out_buffer = &stack_buffer[0]; -diff --git a/third_party/cpuinfo.BUILD b/third_party/cpuinfo.BUILD -index 1997f4e3a..5e03c43af 100644 ---- a/third_party/cpuinfo.BUILD -+++ b/third_party/cpuinfo.BUILD -@@ -150,7 +150,7 @@ cc_library( - "src/arm/midr.h", - ], - deps = [ -- "@clog", -+ "//deps/clog" - ], - ) - -@@ -352,5 +352,5 @@ config_setting( - - config_setting( - name = "emscripten", -- values = {"crosstool_top": "//toolchain:emscripten"}, -+ values = {"crosstool_top": "@emsdk//emscripten_toolchain:everything"}, - ) + """Emscripten-specific dependencies for unit tests and benchmarks.""" + return [ diff --git a/test-tools/host-tool/external/cJSON/cJSON.c b/test-tools/host-tool/external/cJSON/cJSON.c index 2e35351db..830d2a346 100644 --- a/test-tools/host-tool/external/cJSON/cJSON.c +++ b/test-tools/host-tool/external/cJSON/cJSON.c @@ -1,24 +1,24 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ /* cJSON */ /* JSON parser in C. */ @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef ENABLE_LOCALES #include @@ -58,9 +59,33 @@ #include "cJSON.h" /* define our own boolean type */ +#ifdef true +#undef true +#endif #define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif #define false ((cJSON_bool)0) +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has + * been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#else +#define NAN 0.0 / 0.0 +#endif +#endif + typedef struct { const unsigned char *json; size_t position; @@ -72,7 +97,7 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) return (const char *)(global_error.json + global_error.position); } -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item) { if (!cJSON_IsString(item)) { return NULL; @@ -81,18 +106,27 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) return item->valuestring; } +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item) +{ + if (!cJSON_IsNumber(item)) { + return (double)NAN; + } + + return item->valuedouble; +} + /* This is a safeguard to prevent copy-pasters from using incompatible C and * header files */ #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) \ - || (CJSON_VERSION_PATCH != 10) + || (CJSON_VERSION_PATCH != 16) #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #endif CJSON_PUBLIC(const char *) cJSON_Version(void) { static char version[15]; - snprintf(version, sizeof(version), "%i.%i.%i", CJSON_VERSION_MAJOR, - CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, + CJSON_VERSION_PATCH); return version; } @@ -127,8 +161,8 @@ typedef struct internal_hooks { } internal_hooks; #if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dillimport '...' - is not static */ +/* work around MSVC error C2322: '...' address of dllimport '...' is not static + */ static void *CJSON_CDECL internal_malloc(size_t size) { @@ -150,13 +184,11 @@ internal_realloc(void *pointer, size_t size) #define internal_realloc realloc #endif -/* clang-format off */ -static internal_hooks global_hooks = { - internal_malloc, - internal_free, - internal_realloc -}; -/* clang-format on */ +/* strlen of character literals resolved at compile time */ +#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) + +static internal_hooks global_hooks = { internal_malloc, internal_free, + internal_realloc }; static unsigned char * cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) @@ -271,8 +303,8 @@ typedef struct { /* get a pointer to the buffer at the position */ #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) -/* Parse the input text to generate a number, and populate the result - into item. */ +/* Parse the input text to generate a number, and populate the result into item. + */ static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) { @@ -287,9 +319,8 @@ parse_number(cJSON *const item, parse_buffer *const input_buffer) } /* copy the number into a temporary buffer and replace '.' with the decimal - * point of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking - * the end of the input */ + * point of the current locale (for strtod) This also takes care of '\0' not + * necessarily being available for marking the end of the input */ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) { @@ -363,6 +394,32 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) return object->valuedouble = number; } +CJSON_PUBLIC(char *) +cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + char *copy = NULL; + /* if object's type is not cJSON_String or is cJSON_IsReference, it should + * not set valuestring */ + if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) { + return NULL; + } + if (strlen(valuestring) <= strlen(object->valuestring)) { + strcpy(object->valuestring, valuestring); + return object->valuestring; + } + copy = + (char *)cJSON_strdup((const unsigned char *)valuestring, &global_hooks); + if (copy == NULL) { + return NULL; + } + if (object->valuestring != NULL) { + cJSON_free(object->valuestring); + } + object->valuestring = copy; + + return copy; +} + typedef struct { unsigned char *buffer; size_t length; @@ -438,9 +495,8 @@ ensure(printbuffer *const p, size_t needed) return NULL; } - if (newbuffer) { - memcpy(newbuffer, p->buffer, p->offset + 1); - } + + memcpy(newbuffer, p->buffer, p->offset + 1); p->hooks.deallocate(p->buffer); } p->length = newsize; @@ -463,6 +519,14 @@ update_offset(printbuffer *const buffer) buffer->offset += strlen((const char *)buffer_pointer); } +/* securely comparison of floating-point variables */ +static cJSON_bool +compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + /* Render the number nicely from the given item into a string. */ static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer) @@ -471,35 +535,37 @@ print_number(const cJSON *const item, printbuffer *const output_buffer) double d = item->valuedouble; int length = 0; size_t i = 0; - unsigned char - number_buffer[26]; /* temporary buffer to print the number into */ + unsigned char number_buffer[26] = { + 0 + }; /* temporary buffer to print the number into */ unsigned char decimal_point = get_decimal_point(); - double test; + double test = 0.0; if (output_buffer == NULL) { return false; } /* This checks for NaN and Infinity */ - if ((d * 0) != 0) { - length = snprintf((char *)number_buffer, sizeof(number_buffer), "null"); + if (isnan(d) || isinf(d)) { + length = sprintf((char *)number_buffer, "null"); + } + else if (d == (double)item->valueint) { + length = sprintf((char *)number_buffer, "%d", item->valueint); } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero * digits */ - length = - snprintf((char *)number_buffer, sizeof(number_buffer), "%1.15g", d); + length = sprintf((char *)number_buffer, "%1.15g", d); /* Check whether the original double can be recovered */ if ((sscanf((char *)number_buffer, "%lg", &test) != 1) - || ((double)test != d)) { + || !compare_double((double)test, d)) { /* If not, print with 17 decimal places of precision */ - length = snprintf((char *)number_buffer, sizeof(number_buffer), - "%1.17g", d); + length = sprintf((char *)number_buffer, "%1.17g", d); } } - /* snprintf failed or buffer overrun occured */ + /* sprintf failed or buffer overrun occurred */ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { return false; } @@ -709,8 +775,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer) if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { - goto fail; - /* string ended unexpectedly */ + goto fail; /* string ended unexpectedly */ } /* This is at most how much we need for the output */ @@ -719,8 +784,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer) output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof("")); if (output == NULL) { - goto fail; - /* allocation failure */ + goto fail; /* allocation failure */ } } @@ -759,7 +823,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer) *output_pointer++ = input_pointer[1]; break; - /* UTF-16 literal */ + /* UTF-16 literal */ case 'u': sequence_length = utf16_literal_to_utf8( input_pointer, input_end, &output_pointer); @@ -805,7 +869,7 @@ print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer) { const unsigned char *input_pointer = NULL; - unsigned char *output = NULL, *output_end; + unsigned char *output = NULL; unsigned char *output_pointer = NULL; size_t output_length = 0; /* numbers of additional characters needed for escaping */ @@ -853,7 +917,6 @@ print_string_ptr(const unsigned char *const input, if (output == NULL) { return false; } - output_end = output + output_length + sizeof("\"\""); /* no characters have to be escaped */ if (escape_characters == 0) { @@ -902,9 +965,7 @@ print_string_ptr(const unsigned char *const input, break; default: /* escape and print as unicode codepoint */ - snprintf((char *)output_pointer, - output_end - output_pointer, "u%04x", - *input_pointer); + sprintf((char *)output_pointer, "u%04x", *input_pointer); output_pointer += 4; break; } @@ -945,6 +1006,10 @@ buffer_skip_whitespace(parse_buffer *const buffer) return NULL; } + if (cannot_access_at_index(buffer, 0)) { + return buffer; + } + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { buffer->offset++; @@ -975,10 +1040,28 @@ skip_utf8_bom(parse_buffer *const buffer) return buffer; } -/* Parse an object - create a new root, and populate. */ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + size_t buffer_length; + + if (NULL == value) { + return NULL; + } + + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen(value) + sizeof(""); + + return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, + require_null_terminated); +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, + const char **return_parse_end, + cJSON_bool require_null_terminated) { parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; cJSON *item = NULL; @@ -987,12 +1070,12 @@ cJSON_ParseWithOpts(const char *value, const char **return_parse_end, global_error.json = NULL; global_error.position = 0; - if (value == NULL) { + if (value == NULL || 0 == buffer_length) { goto fail; } buffer.content = (const unsigned char *)value; - buffer.length = strlen((const char *)value) + sizeof(""); + buffer.length = buffer_length; buffer.offset = 0; buffer.hooks = global_hooks; @@ -1056,7 +1139,13 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) return cJSON_ParseWithOpts(value, 0, 0); } -#define cjson_min(a, b) ((a < b) ? a : b) +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLength(const char *value, size_t buffer_length) +{ + return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); +} + +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) static unsigned char * print(const cJSON *const item, cJSON_bool format, @@ -1113,6 +1202,10 @@ fail: hooks->deallocate(buffer->buffer); } + if (printed != NULL) { + hooks->deallocate(printed); + } + return NULL; } @@ -1156,20 +1249,20 @@ cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) } CJSON_PUBLIC(cJSON_bool) -cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, - const cJSON_bool fmt) +cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, + const cJSON_bool format) { printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - if ((len < 0) || (buf == NULL)) { + if ((length < 0) || (buffer == NULL)) { return false; } - p.buffer = (unsigned char *)buf; - p.length = (size_t)len; + p.buffer = (unsigned char *)buffer; + p.length = (size_t)length; p.offset = 0; p.noalloc = true; - p.format = fmt; + p.format = format; p.hooks = global_hooks; return print_value(item, &p); @@ -1341,8 +1434,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer) /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { - goto fail; - /* allocation failure */ + goto fail; /* allocation failure */ } /* attach next item to list */ @@ -1361,8 +1453,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer) input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_value(current_item, input_buffer)) { - goto fail; - /* failed to parse value */ + goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); } while (can_access_at_index(input_buffer, 0) @@ -1370,13 +1461,16 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { - goto fail; - /* expected end of array */ + goto fail; /* expected end of array */ } success: input_buffer->depth--; + if (head != NULL) { + head->prev = current_item; + } + item->type = cJSON_Array; item->child = head; @@ -1461,16 +1555,14 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { - goto fail; - /* not an object */ + goto fail; /* not an object */ } input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { - goto success; - /* empty object */ + goto success; /* empty object */ } /* check if we skipped to the end of the buffer */ @@ -1486,8 +1578,7 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { - goto fail; - /* allocation failure */ + goto fail; /* allocation failure */ } /* attach next item to list */ @@ -1506,8 +1597,7 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_string(current_item, input_buffer)) { - goto fail; - /* faile to parse name */ + goto fail; /* failed to parse name */ } buffer_skip_whitespace(input_buffer); @@ -1517,16 +1607,14 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { - goto fail; - /* invalid object */ + goto fail; /* invalid object */ } /* parse the value */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_value(current_item, input_buffer)) { - goto fail; - /* failed to parse value */ + goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); } while (can_access_at_index(input_buffer, 0) @@ -1534,13 +1622,16 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { - goto fail; - /* expected end of object */ + goto fail; /* expected end of object */ } success: input_buffer->depth--; + if (head != NULL) { + head->prev = current_item; + } + item->type = cJSON_Object; item->child = head; @@ -1792,22 +1883,26 @@ add_item_to_array(cJSON *array, cJSON *item) { cJSON *child = NULL; - if ((item == NULL) || (array == NULL)) { + if ((item == NULL) || (array == NULL) || (array == item)) { return false; } child = array->child; - + /* + * To find the last item in array quickly, we use prev in array + */ if (child == NULL) { /* list is empty, start new one */ array->child = item; + item->prev = item; + item->next = NULL; } else { /* append to the end */ - while (child->next) { - child = child->next; + if (child->prev) { + suffix_object(child->prev, item); + array->child->prev = item; } - suffix_object(child, item); } return true; @@ -1847,7 +1942,8 @@ add_item_to_object(cJSON *const object, const char *const string, char *new_key = NULL; int new_type = cJSON_Invalid; - if ((object == NULL) || (string == NULL) || (item == NULL)) { + if ((object == NULL) || (string == NULL) || (item == NULL) + || (object == item)) { return false; } @@ -2028,7 +2124,7 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) return NULL; } - if (item->prev != NULL) { + if (item != parent->child) { /* not the first element */ item->prev->next = item->next; } @@ -2041,6 +2137,11 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) /* first element */ parent->child = item->next; } + else if (item->next == NULL) { + /* last element */ + parent->child->prev = item->prev; + } + /* make sure the detached item doesn't point anywhere anymore */ item->prev = NULL; item->next = NULL; @@ -2121,7 +2222,8 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement) { - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) { + if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) + || (item == NULL)) { return false; } @@ -2135,12 +2237,24 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, if (replacement->next != NULL) { replacement->next->prev = replacement; } - if (replacement->prev != NULL) { - replacement->prev->next = replacement; - } if (parent->child == item) { + if (parent->child->prev == parent->child) { + replacement->prev = replacement; + } parent->child = replacement; } + else { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was + * the parent's child + */ + if (replacement->prev != NULL) { + replacement->prev->next = replacement; + } + if (replacement->next == NULL) { + parent->child->prev = replacement; + } + } item->next = NULL; item->prev = NULL; @@ -2149,15 +2263,15 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, return true; } -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) { if (which < 0) { - return; + return false; } - cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), - newitem); + return cJSON_ReplaceItemViaPointer( + array, get_array_item(array, (size_t)which), newitem); } static cJSON_bool @@ -2175,25 +2289,27 @@ replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, } replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (replacement->string == NULL) { + return false; + } + replacement->type &= ~cJSON_StringIsConst; - cJSON_ReplaceItemViaPointer( + return cJSON_ReplaceItemViaPointer( object, get_object_item(object, string, case_sensitive), replacement); - - return true; } -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) { - replace_item_in_object(object, string, newitem, false); + return replace_item_in_object(object, string, newitem, false); } -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) { - replace_item_in_object(object, string, newitem, true); + return replace_item_in_object(object, string, newitem, true); } /* Create basic types: */ @@ -2227,11 +2343,11 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) { cJSON *item = cJSON_New_Item(&global_hooks); if (item) { - item->type = b ? cJSON_True : cJSON_False; + item->type = boolean ? cJSON_True : cJSON_False; } return item; @@ -2357,6 +2473,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) } a = cJSON_CreateArray(); + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); if (!n) { @@ -2372,6 +2489,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } @@ -2403,6 +2524,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } @@ -2434,10 +2559,15 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) +CJSON_PUBLIC(cJSON *) +cJSON_CreateStringArray(const char *const *strings, int count) { size_t i = 0; cJSON *n = NULL; @@ -2465,6 +2595,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } @@ -2532,6 +2666,9 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) } child = child->next; } + if (newitem && newitem->child) { + newitem->child->prev = newchild; + } return newitem; @@ -2543,55 +2680,93 @@ fail: return NULL; } +static void +skip_oneline_comment(char **input) +{ + *input += static_strlen("//"); + + for (; (*input)[0] != '\0'; ++(*input)) { + if ((*input)[0] == '\n') { + *input += static_strlen("\n"); + return; + } + } +} + +static void +skip_multiline_comment(char **input) +{ + *input += static_strlen("/*"); + + for (; (*input)[0] != '\0'; ++(*input)) { + if (((*input)[0] == '*') && ((*input)[1] == '/')) { + *input += static_strlen("*/"); + return; + } + } +} + +static void +minify_string(char **input, char **output) +{ + (*output)[0] = (*input)[0]; + *input += static_strlen("\""); + *output += static_strlen("\""); + + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { + (*output)[0] = (*input)[0]; + + if ((*input)[0] == '\"') { + (*output)[0] = '\"'; + *input += static_strlen("\""); + *output += static_strlen("\""); + return; + } + else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { + (*output)[1] = (*input)[1]; + *input += static_strlen("\""); + *output += static_strlen("\""); + } + } +} + CJSON_PUBLIC(void) cJSON_Minify(char *json) { - unsigned char *into = (unsigned char *)json; + char *into = json; if (json == NULL) { return; } - while (*json) { - if (*json == ' ') { - json++; - } - else if (*json == '\t') { - /* Whitespace characters. */ - json++; - } - else if (*json == '\r') { - json++; - } - else if (*json == '\n') { - json++; - } - else if ((*json == '/') && (json[1] == '/')) { - /* double-slash comments, to end of line. */ - while (*json && (*json != '\n')) { + while (json[0] != '\0') { + switch (json[0]) { + case ' ': + case '\t': + case '\r': + case '\n': json++; - } - } - else if ((*json == '/') && (json[1] == '*')) { - /* multiline comments. */ - while (*json && !((*json == '*') && (json[1] == '/'))) { - json++; - } - json += 2; - } - else if (*json == '\"') { - /* string literals, which are \" sensitive. */ - *into++ = (unsigned char)*json++; - while (*json && (*json != '\"')) { - if (*json == '\\') { - *into++ = (unsigned char)*json++; + break; + + case '/': + if (json[1] == '/') { + skip_oneline_comment(&json); } - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - else { - /* All other characters. */ - *into++ = (unsigned char)*json++; + else if (json[1] == '*') { + skip_multiline_comment(&json); + } + else { + json++; + } + break; + + case '\"': + minify_string(&json, (char **)&into); + break; + + default: + into[0] = json[0]; + json++; + into++; } } @@ -2692,8 +2867,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) { - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) - || cJSON_IsInvalid(a)) { + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { return false; } @@ -2726,7 +2900,7 @@ cJSON_Compare(const cJSON *const a, const cJSON *const b, return true; case cJSON_Number: - if (a->valuedouble == b->valuedouble) { + if (compare_double(a->valuedouble, b->valuedouble)) { return true; } return false; diff --git a/test-tools/host-tool/external/cJSON/cJSON.h b/test-tools/host-tool/external/cJSON/cJSON.h index d437196a3..2cafdcf59 100644 --- a/test-tools/host-tool/external/cJSON/cJSON.h +++ b/test-tools/host-tool/external/cJSON/cJSON.h @@ -1,24 +1,24 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ #ifndef cJSON__h #define cJSON__h @@ -35,30 +35,34 @@ extern "C" { #ifdef __WINDOWS__ -/** - * When compiling for windows, we specify a specific calling convention to avoid - * issues where we are being called from a project with a different default - * calling convention. For windows you have 3 define options: - * CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever - * dllexport symbols - * CJSON_EXPORT_SYMBOLS - Define this on library build when you want to - * dllexport symbols (default) - * CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol - * - * For *nix builds that support visibility attribute, you can define similar - * behavior by setting default visibility to hidden by adding - * -fvisibility=hidden (for gcc) - * or - * -xldscope=hidden (for sun cc) - * to CFLAGS, then using the CJSON_API_VISIBILITY flag to "export" the same - * symbols the way CJSON_EXPORT_SYMBOLS does - */ +/* When compiling for windows, we specify a specific calling convention to avoid +issues where we are being called from a project with a different default calling +convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever +dllexport symbols CJSON_EXPORT_SYMBOLS - Define this on library build when you +want to dllexport symbols (default) CJSON_IMPORT_SYMBOLS - Define this if you +want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar +behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way +CJSON_EXPORT_SYMBOLS does + +*/ #define CJSON_CDECL __cdecl #define CJSON_STDCALL __stdcall /* export symbols by default, this is necessary for copy pasting the C and - header file */ + * header file */ #if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) \ && !defined(CJSON_EXPORT_SYMBOLS) #define CJSON_EXPORT_SYMBOLS @@ -86,7 +90,7 @@ extern "C" { /* project version */ #define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 10 +#define CJSON_VERSION_PATCH 16 #include @@ -107,11 +111,11 @@ extern "C" { /* The cJSON structure: */ typedef struct cJSON { /* next/prev allow you to walk array/object chains. Alternatively, use - GetArraySize/GetArrayItem/GetObjectItem */ + * GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; /* An array or object item will have a child pointer pointing to a chain of - the items in the array/object. */ + * the items in the array/object. */ struct cJSON *child; /* The type of the item, as above. */ @@ -125,7 +129,7 @@ typedef struct cJSON { double valuedouble; /* The item's name string, if this item is the child of, or is in the list - of subitems of an object. */ + * of subitems of an object. */ char *string; } cJSON; @@ -140,7 +144,7 @@ typedef struct cJSON_Hooks { typedef int cJSON_bool; /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse - them. This is to prevent stack overflows. */ + * them. This is to prevent stack overflows. */ #ifndef CJSON_NESTING_LIMIT #define CJSON_NESTING_LIMIT 1000 #endif @@ -159,6 +163,8 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks); /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLength(const char *value, size_t buffer_length); /* ParseWithOpts allows you to require (and check) that the JSON is null * terminated, and to retrieve the pointer to the final byte parsed. */ /* If you supply a ptr in return_parse_end and parsing fails, then @@ -167,6 +173,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, + const char **return_parse_end, + cJSON_bool require_null_terminated); /* Render a cJSON entity to text for transfer/storage. */ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); @@ -185,7 +195,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); /* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); /* Returns the number of items in an array (or object). */ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); @@ -205,8 +215,9 @@ cJSON_HasObjectItem(const cJSON *object, const char *string); * when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); -/* Check if the item is a string and return its valuestring */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item); /* These functions check the type of an item */ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item); @@ -233,18 +244,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); /* Create a string where valuestring references a string so - it will not be freed by cJSON_Delete */ + * it will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); -/* Create an object/arrray that only references it's elements so - they will not be freed by cJSON_Delete */ +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); -/* These utilities create an Array of count items. */ +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the + * number array, otherwise array access will be out of bounds.*/ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); +CJSON_PUBLIC(cJSON *) +cJSON_CreateStringArray(const char *const *strings, int count); /* Append item to the specified array/object. */ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); @@ -264,7 +278,7 @@ cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); -/* Remove/Detatch items from Arrays/Objects. */ +/* Remove/Detach items from Arrays/Objects. */ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); @@ -286,32 +300,35 @@ cJSON_InsertItemInArray( CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement); -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem); /* Duplicate a cJSON item */ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); /* Duplicate will create a new, identical cJSON item to the one you pass, in new - memory that will need to be released. With recurse!=0, it will duplicate any - children connected to the item. The item->next and ->prev pointers are always - zero on return from Duplicate. */ + * memory that will need to be released. With recurse!=0, it will duplicate any + * children connected to the item. The item->next and ->prev pointers are always + * zero on return from Duplicate. */ /* Recursively compare two cJSON items for equality. If either a or b is NULL or - * invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or - * case insensitive (0) */ + * invalid, they will be considered unequal. case_sensitive determines if object + * keys are treated case sensitive (1) or case insensitive (0) */ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive); +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from + * strings. The input pointer json cannot point to a read-only address area, + * such as a string constant, but should point to a readable and writable + * address area. */ CJSON_PUBLIC(void) cJSON_Minify(char *json); /* Helper functions for creating and adding items to an object at the same time. - They return the added item or NULL on failure. */ + * They return the added item or NULL on failure. */ CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name); CJSON_PUBLIC(cJSON *) @@ -336,7 +353,7 @@ CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name); /* When assigning an integer value, it needs to be propagated to valuedouble - too. */ + * too. */ #define cJSON_SetIntValue(object, number) \ ((object) ? (object)->valueint = (object)->valuedouble = (number) \ : (number)) @@ -345,6 +362,18 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); #define cJSON_SetNumberValue(object, number) \ ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) \ : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type + * of object is cJSON_String */ +CJSON_PUBLIC(char *) +cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* If the object is not a boolean type this does nothing and returns + * cJSON_Invalid else it returns the new type*/ +#define cJSON_SetBoolValue(object, boolValue) \ + ((object != NULL && ((object)->type & (cJSON_False | cJSON_True))) \ + ? (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) \ + | ((boolValue) ? cJSON_True : cJSON_False) \ + : cJSON_Invalid) /* Macro for iterating over an array or object */ #define cJSON_ArrayForEach(element, array) \ @@ -352,7 +381,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); element = element->next) /* malloc/free objects using the malloc/free functions that have been set with - cJSON_InitHooks */ + * cJSON_InitHooks */ CJSON_PUBLIC(void *) cJSON_malloc(size_t size); CJSON_PUBLIC(void) cJSON_free(void *object); diff --git a/tests/benchmarks/jetstream/tsf.patch b/tests/benchmarks/jetstream/tsf.patch index e52c3cdc5..98355b08c 100644 --- a/tests/benchmarks/jetstream/tsf.patch +++ b/tests/benchmarks/jetstream/tsf.patch @@ -1,6 +1,18 @@ +diff -urN tsf-src-org/gpc_code_gen_util.c tsf-src/gpc_code_gen_util.c +--- tsf-src-org/gpc_code_gen_util.c 2023-09-21 11:12:40.211166472 +0800 ++++ tsf-src/gpc_code_gen_util.c 2023-09-21 11:09:13.643170967 +0800 +@@ -34,6 +34,8 @@ + #include + #include + ++int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); ++ + /* code generation debugging */ + + /* NOTE: It is now the case that the count may be incremented multiple times, diff -urN tsf-src-org/tsf_internal.h tsf-src/tsf_internal.h ---- tsf-src-org/tsf_internal.h 2023-03-31 10:49:45.000000000 +0800 -+++ tsf-src/tsf_internal.h 2023-05-11 08:18:35.000000000 +0800 +--- tsf-src-org/tsf_internal.h 2023-09-21 11:11:50.843167546 +0800 ++++ tsf-src/tsf_internal.h 2023-09-21 11:06:53.031174027 +0800 @@ -429,6 +429,7 @@ #endif tsf_fsdb_connection_t *connection; @@ -10,15 +22,15 @@ diff -urN tsf-src-org/tsf_internal.h tsf-src/tsf_internal.h } u; tsf_limits_t *limits; diff -urN tsf-src-org/tsf_ir_speed.c tsf-src/tsf_ir_speed.c ---- tsf-src-org/tsf_ir_speed.c 2023-03-31 10:49:45.000000000 +0800 -+++ tsf-src/tsf_ir_speed.c 2023-05-11 08:18:35.000000000 +0800 +--- tsf-src-org/tsf_ir_speed.c 2023-09-21 11:12:15.699167005 +0800 ++++ tsf-src/tsf_ir_speed.c 2023-09-21 11:06:53.031174027 +0800 @@ -63,6 +63,9 @@ Program_t *program; unsigned elementIndex; - + + if (!(programIndex % 100)) + printf("##programIndex: %u\n", programIndex); + CS(program = tsf_region_create(sizeof(Program_t))); - + program->globals.len = numDecls + numDefns; diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt new file mode 100644 index 000000000..a9a7b8776 --- /dev/null +++ b/tests/unit/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +project (wamr_unit_tests) + +include (CTest) + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_PLATFORM) + string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +endif () + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +include (FetchContent) +FetchContent_Declare ( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable (googletest) + +include (GoogleTest) + +add_library (wamr_gtest_main main.cpp) +target_link_libraries (wamr_gtest_main PUBLIC gtest vmlib) + +function (create_wamr_unit_test test_name) + set (sources ${ARGN}) + add_executable (${test_name} ${sources}) + target_link_libraries ( + ${test_name} + wamr_gtest_main + vmlib + ${LLVM_AVAILABLE_LIBS} + ) + gtest_discover_tests (${test_name}) + endfunction () + +if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1) + include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake) +endif () diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp new file mode 100644 index 000000000..63695d9ee --- /dev/null +++ b/tests/unit/main.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ +#include +#include "wasm_runtime_common.h" + +int +main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + + if (!wasm_runtime_init()) { + return -1; + } + + int ret = RUN_ALL_TESTS(); + wasm_runtime_destroy(); + + return ret; +} \ No newline at end of file diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index bd5b89ce4..44b0a14bd 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -37,6 +37,7 @@ WAST2WASM_CMD = "./wabt/out/gcc/Release/wat2wasm" SPEC_INTERPRETER_CMD = "spec/interpreter/wasm" WAMRC_CMD = "../../../wamr-compiler/build/wamrc" + class TargetAction(argparse.Action): TARGET_MAP = { "ARMV7_VFP": "armv7", @@ -49,6 +50,7 @@ class TargetAction(argparse.Action): "THUMBV7_VFP": "thumbv7", "X86_32": "i386", "X86_64": "x86_64", + "AARCH64": "arm64" } def __call__(self, parser, namespace, values, option_string=None): @@ -65,7 +67,7 @@ def ignore_the_case( simd_flag=False, gc_flag=False, xip_flag=False, - qemu_flag=False + qemu_flag=False, ): if case_name in ["comments", "inline-module", "names"]: return True @@ -79,7 +81,7 @@ def ignore_the_case( if gc_flag: if case_name in ["type-canon", "type-equivalence", "type-rec"]: - return True; + return True if sgx_flag: if case_name in ["conversions", "f32_bitwise", "f64_bitwise"]: @@ -94,9 +96,20 @@ def ignore_the_case( return True if qemu_flag: - if case_name in ["f32_bitwise", "f64_bitwise", "loop", "f64", "f64_cmp", - "conversions", "f32", "f32_cmp", "float_exprs", - "float_misc", "select", "memory_grow"]: + if case_name in [ + "f32_bitwise", + "f64_bitwise", + "loop", + "f64", + "f64_cmp", + "conversions", + "f32", + "f32_cmp", + "float_exprs", + "float_misc", + "select", + "memory_grow", + ]: return True return False @@ -131,26 +144,9 @@ def test_case( verbose_flag=True, gc_flag=False, qemu_flag=False, - qemu_firmware='', - log='', + qemu_firmware="", + log="", ): - case_path = pathlib.Path(case_path).resolve() - case_name = case_path.stem - - if ignore_the_case( - case_name, - target, - aot_flag, - sgx_flag, - multi_module_flag, - multi_thread_flag, - simd_flag, - gc_flag, - xip_flag, - qemu_flag - ): - return True - CMD = ["python3", "runtest.py"] CMD.append("--wast2wasm") CMD.append(WAST2WASM_CMD if not gc_flag else SPEC_INTERPRETER_CMD) @@ -196,10 +192,13 @@ def test_case( if gc_flag: CMD.append("--gc") - if log != '': + if log != "": CMD.append("--log-dir") CMD.append(log) + case_path = pathlib.Path(case_path).resolve() + case_name = case_path.stem + CMD.append(case_path) print(f"============> run {case_name} ", end="") with subprocess.Popen( @@ -259,8 +258,8 @@ def test_suite( gc_flag=False, parl_flag=False, qemu_flag=False, - qemu_firmware='', - log='', + qemu_firmware="", + log="", ): suite_path = pathlib.Path(SPEC_TEST_DIR).resolve() if not suite_path.exists(): @@ -276,6 +275,26 @@ def test_suite( gc_case_list = sorted(suite_path.glob("gc/*.wast")) case_list.extend(gc_case_list) + # ignore based on command line options + filtered_case_list = [] + for case_path in case_list: + case_name = case_path.stem + if not ignore_the_case( + case_name, + target, + aot_flag, + sgx_flag, + multi_module_flag, + multi_thread_flag, + simd_flag, + gc_flag, + xip_flag, + qemu_flag, + ): + filtered_case_list.append(case_path) + print(f"---> {len(case_list)} --filter--> {len(filtered_case_list)}") + case_list = filtered_case_list + case_count = len(case_list) failed_case = 0 successful_case = 0 @@ -435,7 +454,7 @@ def main(): ) parser.add_argument( "--log", - default='', + default="", dest="log", help="Log directory", ) @@ -512,7 +531,7 @@ def main(): options.gc_flag, options.qemu_flag, options.qemu_firmware, - options.log + options.log, ) else: ret = True diff --git a/tests/wamr-test-suites/spec-test-script/ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/ignore_cases.patch index 1d94d91af..bfb4383f7 100644 --- a/tests/wamr-test-suites/spec-test-script/ignore_cases.patch +++ b/tests/wamr-test-suites/spec-test-script/ignore_cases.patch @@ -343,26 +343,6 @@ index adb5cb7..590f626 100644 (func $g (param $x i32) (result i32) (i32.add (local.get $x) (i32.const 1)) ) -diff --git a/test/core/select.wast b/test/core/select.wast -index 046e6fe..b677023 100644 ---- a/test/core/select.wast -+++ b/test/core/select.wast -@@ -324,6 +324,7 @@ - (module (func $arity-0 (select (result) (nop) (nop) (i32.const 1)))) - "invalid result arity" - ) -+(; - (assert_invalid - (module (func $arity-2 (result i32 i32) - (select (result i32 i32) -@@ -334,6 +335,7 @@ - )) - "invalid result arity" - ) -+;) - - - (assert_invalid diff --git a/test/core/table_copy.wast b/test/core/table_copy.wast index 380e84e..f37e745 100644 --- a/test/core/table_copy.wast diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index e263e5ab6..11650651c 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -15,7 +15,7 @@ function help() echo "test_wamr.sh [options]" echo "-c clean previous test results, not start test" echo "-s {suite_name} test only one suite (spec|wasi_certification)" - echo "-m set compile target of iwasm(x86_64|x86_32|armv7_vfp|thumbv7_vfp|riscv64_lp64d|riscv64_lp64)" + echo "-m set compile target of iwasm(x86_64|x86_32|armv7_vfp|thumbv7_vfp|riscv64_lp64d|riscv64_lp64|aarch64)" echo "-t set compile type of iwasm(classic-interp|fast-interp|jit|aot|fast-jit|multi-tier-jit)" echo "-M enable multi module feature" echo "-p enable multi thread feature" @@ -55,7 +55,8 @@ PLATFORM=$(uname -s | tr A-Z a-z) PARALLELISM=0 ENABLE_QEMU=0 QEMU_FIRMWARE="" -WASI_TESTSUITE_COMMIT="aca78d919355ae00af141e6741a439039615b257" +# prod/testsuite-all branch +WASI_TESTSUITE_COMMIT="cf64229727f71043d5849e73934e249e12cb9e06" while getopts ":s:cabgvt:m:MCpSXxwPGQF:" opt do @@ -508,7 +509,7 @@ function wasi_certification_test() cd ${WORK_DIR} if [ ! -d "wasi-testsuite" ]; then - echo "wasi not exist, clone it from github" + echo "wasi-testsuite not exist, clone it from github" git clone -b prod/testsuite-all \ --single-branch https://github.com/WebAssembly/wasi-testsuite.git fi @@ -824,7 +825,7 @@ function trigger() collect_coverage llvm-jit echo "work in orc jit lazy compilation mode" - BUILD_FLAGS="$ORC_EAGER_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" + BUILD_FLAGS="$ORC_LAZY_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" build_iwasm_with_cfg $BUILD_FLAGS for suite in "${TEST_CASE_ARR[@]}"; do $suite"_test" jit diff --git a/tests/wamr-test-suites/wasi-test-script/pipe.py b/tests/wamr-test-suites/wasi-test-script/pipe.py new file mode 100644 index 000000000..e37408717 --- /dev/null +++ b/tests/wamr-test-suites/wasi-test-script/pipe.py @@ -0,0 +1,19 @@ +#! /usr/bin/env python3 + +# Copyright (C) 2023 YAMAMOTO Takashi +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This is a copy of https://github.com/yamt/toywasm/blob/master/test/pipe.py + +# keep stdout open until the peer closes it + +import sys +import select + +p = select.poll() +p.register(sys.stdout, select.POLLHUP) +# http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=57369 +while True: + l = p.poll(1) + if l: + break diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index eb6cf3f91..c4b27390e 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -5,26 +5,38 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # +THIS_DIR=$(cd $(dirname $0) && pwd -P) + readonly MODE=$1 readonly TARGET=$2 readonly WORK_DIR=$PWD readonly PLATFORM=$(uname -s | tr A-Z a-z) readonly WAMR_DIR="${WORK_DIR}/../../../.." -readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm" +readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/build/iwasm \ + --allow-resolve=google-public-dns-a.google.com \ + --addr-pool=::1/128,127.0.0.1/32" + +readonly IWASM_CMD_STRESS="${IWASM_CMD} --max-threads=12" readonly WAMRC_CMD="${WORK_DIR}/../../../../wamr-compiler/build/wamrc" readonly C_TESTS="tests/c/testsuite/" readonly ASSEMBLYSCRIPT_TESTS="tests/assemblyscript/testsuite/" readonly THREAD_PROPOSAL_TESTS="tests/proposals/wasi-threads/" readonly THREAD_INTERNAL_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/test/" +readonly THREAD_STRESS_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/stress-test/" readonly LIB_SOCKET_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-socket/test/" run_aot_tests () { local tests=("$@") for test_wasm in ${tests[@]}; do + local iwasm="${IWASM_CMD}" + if [[ $test_wasm =~ "stress" ]]; then + iwasm="${IWASM_CMD_STRESS}" + fi + test_aot="${test_wasm%.wasm}.aot" test_json="${test_wasm%.wasm}.json" - + if [ -f ${test_wasm} ]; then expected=$(jq .exit_code ${test_json}) fi @@ -35,33 +47,47 @@ run_aot_tests () { echo "Running $test_aot" expected=0 - if [ -f ${test_json} ]; then + if [ -f ${test_json} ]; then expected=$(jq .exit_code ${test_json}) fi - - ${IWASM_CMD} $test_aot - - ret=${PIPESTATUS[0]} + + python3 ${THIS_DIR}/pipe.py | ${iwasm} $test_aot + ret=${PIPESTATUS[1]} echo "expected=$expected, actual=$ret" if [[ $expected != "" ]] && [[ $expected != $ret ]];then exit_code=1 fi done -} +} if [[ $MODE != "aot" ]];then python3 -m venv wasi-env && source wasi-env/bin/activate python3 -m pip install -r test-runner/requirements.txt - TEST_RUNTIME_EXE="${IWASM_CMD}" python3 test-runner/wasi_test_runner.py \ - -r adapters/wasm-micro-runtime.py \ - -t \ - ${C_TESTS} \ - ${ASSEMBLYSCRIPT_TESTS} \ - ${THREAD_PROPOSAL_TESTS} \ - ${THREAD_INTERNAL_TESTS} \ - ${LIB_SOCKET_TESTS} \ - exit_code=${PIPESTATUS[0]} + + export TEST_RUNTIME_EXE="${IWASM_CMD}" + python3 ${THIS_DIR}/pipe.py | python3 test-runner/wasi_test_runner.py \ + -r adapters/wasm-micro-runtime.py \ + -t \ + ${C_TESTS} \ + ${ASSEMBLYSCRIPT_TESTS} \ + ${THREAD_PROPOSAL_TESTS} \ + ${THREAD_INTERNAL_TESTS} \ + ${LIB_SOCKET_TESTS} \ + + ret=${PIPESTATUS[1]} + + TEST_RUNTIME_EXE="${IWASM_CMD_STRESS}" python3 test-runner/wasi_test_runner.py \ + -r adapters/wasm-micro-runtime.py \ + -t \ + ${THREAD_STRESS_TESTS} + + if [ "${ret}" -eq 0 ]; then + ret=${PIPESTATUS[0]} + fi + + exit_code=${ret} + deactivate else target_option="" @@ -70,11 +96,11 @@ else fi exit_code=0 - for testsuite in ${THREAD_PROPOSAL_TESTS} ${THREAD_INTERNAL_TESTS}; do + for testsuite in ${THREAD_STRESS_TESTS} ${THREAD_PROPOSAL_TESTS} ${THREAD_INTERNAL_TESTS}; do tests=$(ls ${testsuite}*.wasm) tests_array=($tests) run_aot_tests "${tests_array[@]}" done fi -exit ${exit_code} \ No newline at end of file +exit ${exit_code} diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 08f935bb6..ba0902cdf 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -45,6 +45,7 @@ add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1) add_definitions(-DWASM_ENABLE_PERF_PROFILING=1) add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1) add_definitions(-DWASM_ENABLE_LIB_WASI_THREADS=1) +add_definitions(-DWASM_ENABLE_MODULE_INST_CONTEXT=1) if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1) add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1) diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index ce6ed7006..0d85b99ce 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -9,6 +9,100 @@ #include "wasm_export.h" #include "aot_export.h" +#if BH_HAS_DLFCN +#include + +typedef uint32 (*get_native_lib_func)(char **p_module_name, + NativeSymbol **p_native_symbols); + +static uint32 +load_and_register_native_libs(const char **native_lib_list, + uint32 native_lib_count, + void **native_handle_list) +{ + uint32 i, native_handle_count = 0, n_native_symbols; + NativeSymbol *native_symbols; + char *module_name; + void *handle; + + for (i = 0; i < native_lib_count; i++) { + /* open the native library */ + if (!(handle = dlopen(native_lib_list[i], RTLD_NOW | RTLD_GLOBAL)) + && !(handle = dlopen(native_lib_list[i], RTLD_LAZY))) { + LOG_WARNING("warning: failed to load native library %s", + native_lib_list[i]); + continue; + } + + /* lookup get_native_lib func */ + get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib"); + if (!get_native_lib) { + LOG_WARNING("warning: failed to lookup `get_native_lib` function " + "from native lib %s", + native_lib_list[i]); + dlclose(handle); + continue; + } + + n_native_symbols = get_native_lib(&module_name, &native_symbols); + + /* register native symbols */ + if (!(n_native_symbols > 0 && module_name && native_symbols + && wasm_runtime_register_natives(module_name, native_symbols, + n_native_symbols))) { + LOG_WARNING("warning: failed to register native lib %s", + native_lib_list[i]); + dlclose(handle); + continue; + } + + native_handle_list[native_handle_count++] = handle; + } + + return native_handle_count; +} + +static void +unregister_and_unload_native_libs(uint32 native_lib_count, + void **native_handle_list) +{ + uint32 i, n_native_symbols; + NativeSymbol *native_symbols; + char *module_name; + void *handle; + + for (i = 0; i < native_lib_count; i++) { + handle = native_handle_list[i]; + + /* lookup get_native_lib func */ + get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib"); + if (!get_native_lib) { + LOG_WARNING("warning: failed to lookup `get_native_lib` function " + "from native lib %p", + handle); + continue; + } + + n_native_symbols = get_native_lib(&module_name, &native_symbols); + if (n_native_symbols == 0 || module_name == NULL + || native_symbols == NULL) { + LOG_WARNING("warning: get_native_lib returned different values for " + "native lib %p", + handle); + continue; + } + + /* unregister native symbols */ + if (!wasm_runtime_unregister_natives(module_name, native_symbols)) { + LOG_WARNING("warning: failed to unregister native lib %p", handle); + continue; + } + + dlclose(handle); + } +} +#endif + /* clang-format off */ static void print_help() @@ -32,7 +126,7 @@ print_help() printf(" Use --cpu-features=+help to list all the features supported\n"); printf(" --opt-level=n Set the optimization level (0 to 3, default is 3)\n"); printf(" --size-level=n Set the code size level (0 to 3, default is 3)\n"); - printf(" -sgx Generate code for SGX platform (Intel Software Guard Extention)\n"); + printf(" -sgx Generate code for SGX platform (Intel Software Guard Extensions)\n"); printf(" --bounds-checks=1/0 Enable or disable the bounds checks for memory access:\n"); printf(" by default it is disabled in all 64-bit platforms except SGX and\n"); printf(" in these platforms runtime does bounds checks with hardware trap,\n"); @@ -65,10 +159,19 @@ print_help() printf(" --enable-dump-call-stack Enable stack trace feature\n"); printf(" --enable-perf-profiling Enable function performance profiling\n"); printf(" --enable-memory-profiling Enable memory usage profiling\n"); - printf(" --enable-indirect-mode Enalbe call function through symbol table but not direct call\n"); + printf(" --xip A shorthand of --enable-indirect-mode --disable-llvm-intrinsics\n"); + printf(" --enable-indirect-mode Enable call function through symbol table but not direct call\n"); printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n"); + printf(" --enable-builtin-intrinsics=\n"); + printf(" Enable the specified built-in intrinsics, it will override the default\n"); + printf(" settings. It only takes effect when --disable-llvm-intrinsics is set.\n"); + printf(" Available flags: all, i32.common, i64.common, f32.common, f64.common,\n"); + printf(" i32.clz, i32.ctz, etc, refer to doc/xip.md for full list\n"); + printf(" Use comma to separate, please refer to doc/xip.md for full list.\n"); printf(" --disable-llvm-lto Disable the LLVM link time optimization\n"); printf(" --enable-llvm-pgo Enable LLVM PGO (Profile-Guided Optimization)\n"); + printf(" --enable-llvm-passes=\n"); + printf(" Enable the specified LLVM passes, using comma to separate\n"); printf(" --use-prof-file= Use profile file collected by LLVM PGO (Profile-Guided Optimization)\n"); printf(" --enable-segue[=] Enable using segment register GS as the base address of linear memory,\n"); printf(" only available on linux/linux-sgx x86-64, which may improve performance,\n"); @@ -80,11 +183,18 @@ print_help() printf(" Emit the specified custom sections to AoT file, using comma to separate\n"); printf(" multiple names, e.g.\n"); printf(" --emit-custom-sections=section1,section2,sectionN\n"); +#if BH_HAS_DLFCN + printf(" --native-lib= Register native libraries to the WASM module, which\n"); + printf(" are shared object (.so) files, for example:\n"); + printf(" --native-lib=test1.so --native-lib=test2.so\n"); +#endif printf(" -v=n Set log verbose level (0 to 5, default is 2), larger with more log\n"); printf(" --version Show version information\n"); printf("Examples: wamrc -o test.aot test.wasm\n"); printf(" wamrc --target=i386 -o test.aot test.wasm\n"); printf(" wamrc --target=i386 --format=object -o test.o test.wasm\n"); + printf(" wamrc --target-abi=help\n"); + printf(" wamrc --target=x86_64 --cpu=help\n"); } /* clang-format on */ @@ -188,6 +298,12 @@ resolve_segue_flags(char *str_flags) return segue_flags; } +/* When print help info for target/cpu/target-abi/cpu-features, load this dummy + * wasm file content rather than from an input file, the dummy wasm file content + * is: magic header + version number */ +static unsigned char dummy_wasm_file[8] = { 0x00, 0x61, 0x73, 0x6D, + 0x01, 0x00, 0x00, 0x00 }; + int main(int argc, char *argv[]) { @@ -201,8 +317,14 @@ main(int argc, char *argv[]) AOTCompOption option = { 0 }; char error_buf[128]; int log_verbose_level = 2; - bool sgx_mode = false, size_level_set = false; + bool sgx_mode = false, size_level_set = false, use_dummy_wasm = false; int exit_status = EXIT_FAILURE; +#if BH_HAS_DLFCN + const char *native_lib_list[8] = { NULL }; + uint32 native_lib_count = 0; + void *native_handle_list[8] = { NULL }; + uint32 native_handle_count = 0; +#endif option.opt_level = 3; option.size_level = 3; @@ -228,21 +350,33 @@ main(int argc, char *argv[]) if (argv[0][9] == '\0') PRINT_HELP_AND_EXIT(); option.target_arch = argv[0] + 9; + if (!strcmp(option.target_arch, "help")) { + use_dummy_wasm = true; + } } else if (!strncmp(argv[0], "--target-abi=", 13)) { if (argv[0][13] == '\0') PRINT_HELP_AND_EXIT(); option.target_abi = argv[0] + 13; + if (!strcmp(option.target_abi, "help")) { + use_dummy_wasm = true; + } } else if (!strncmp(argv[0], "--cpu=", 6)) { if (argv[0][6] == '\0') PRINT_HELP_AND_EXIT(); option.target_cpu = argv[0] + 6; + if (!strcmp(option.target_cpu, "help")) { + use_dummy_wasm = true; + } } else if (!strncmp(argv[0], "--cpu-features=", 15)) { if (argv[0][15] == '\0') PRINT_HELP_AND_EXIT(); option.cpu_features = argv[0] + 15; + if (!strcmp(option.cpu_features, "+help")) { + use_dummy_wasm = true; + } } else if (!strncmp(argv[0], "--opt-level=", 12)) { if (argv[0][12] == '\0') @@ -325,18 +459,32 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--enable-memory-profiling")) { option.enable_stack_estimation = true; } + else if (!strcmp(argv[0], "--xip")) { + option.is_indirect_mode = true; + option.disable_llvm_intrinsics = true; + } else if (!strcmp(argv[0], "--enable-indirect-mode")) { option.is_indirect_mode = true; } else if (!strcmp(argv[0], "--disable-llvm-intrinsics")) { option.disable_llvm_intrinsics = true; } + else if (!strncmp(argv[0], "--enable-builtin-intrinsics=", 28)) { + if (argv[0][28] == '\0') + PRINT_HELP_AND_EXIT(); + option.builtin_intrinsics = argv[0] + 28; + } else if (!strcmp(argv[0], "--disable-llvm-lto")) { option.disable_llvm_lto = true; } else if (!strcmp(argv[0], "--enable-llvm-pgo")) { option.enable_llvm_pgo = true; } + else if (!strncmp(argv[0], "--enable-llvm-passes=", 21)) { + if (argv[0][21] == '\0') + PRINT_HELP_AND_EXIT(); + option.llvm_passes = argv[0] + 21; + } else if (!strncmp(argv[0], "--use-prof-file=", 16)) { if (argv[0][16] == '\0') PRINT_HELP_AND_EXIT(); @@ -366,6 +514,18 @@ main(int argc, char *argv[]) option.custom_sections_count = len; } +#if BH_HAS_DLFCN + else if (!strncmp(argv[0], "--native-lib=", 13)) { + if (argv[0][13] == '\0') + PRINT_HELP_AND_EXIT(); + if (native_lib_count >= sizeof(native_lib_list) / sizeof(char *)) { + printf("Only allow max native lib number %d\n", + (int)(sizeof(native_lib_list) / sizeof(char *))); + goto fail0; + } + native_lib_list[native_lib_count++] = argv[0] + 13; + } +#endif else if (!strncmp(argv[0], "--version", 9)) { uint32 major, minor, patch; wasm_runtime_get_version(&major, &minor, &patch); @@ -376,7 +536,7 @@ main(int argc, char *argv[]) PRINT_HELP_AND_EXIT(); } - if (argc == 0 || !out_file_name) + if (!use_dummy_wasm && (argc == 0 || !out_file_name)) PRINT_HELP_AND_EXIT(); if (!size_level_set) { @@ -404,11 +564,13 @@ main(int argc, char *argv[]) option.is_sgx_platform = true; } - wasm_file_name = argv[0]; + if (!use_dummy_wasm) { + wasm_file_name = argv[0]; - if (!strcmp(wasm_file_name, out_file_name)) { - printf("Error: input file and output file are the same"); - return -1; + if (!strcmp(wasm_file_name, out_file_name)) { + printf("Error: input file and output file are the same"); + return -1; + } } memset(&init_args, 0, sizeof(RuntimeInitArgs)); @@ -426,12 +588,25 @@ main(int argc, char *argv[]) bh_log_set_verbose_level(log_verbose_level); +#if BH_HAS_DLFCN + bh_print_time("Begin to load native libs"); + native_handle_count = load_and_register_native_libs( + native_lib_list, native_lib_count, native_handle_list); +#endif + bh_print_time("Begin to load wasm file"); - /* load WASM byte buffer from WASM bin file */ - if (!(wasm_file = - (uint8 *)bh_read_file_to_buffer(wasm_file_name, &wasm_file_size))) - goto fail1; + if (use_dummy_wasm) { + /* load WASM byte buffer from dummy buffer */ + wasm_file_size = sizeof(dummy_wasm_file); + wasm_file = dummy_wasm_file; + } + else { + /* load WASM byte buffer from WASM bin file */ + if (!(wasm_file = (uint8 *)bh_read_file_to_buffer(wasm_file_name, + &wasm_file_size))) + goto fail1; + } if (get_package_type(wasm_file, wasm_file_size) != Wasm_Module_Bytecode) { printf("Invalid file type: expected wasm file but got other\n"); @@ -513,9 +688,14 @@ fail3: fail2: /* free the file buffer */ - wasm_runtime_free(wasm_file); + if (!use_dummy_wasm) { + wasm_runtime_free(wasm_file); + } fail1: +#if BH_HAS_DLFCN + unregister_and_unload_native_libs(native_handle_count, native_handle_list); +#endif /* Destroy runtime environment */ wasm_runtime_destroy();