Add tsan for fast interp and aot (#2679)

To run it locally:
```bash
export TSAN_OPTIONS=suppressions=<path_to_tsan_suppressions.txt>
./test_wamr.sh <your flags> -T tsan
```

An example for wasi-threads would look like:
```bash
export TSAN_OPTIONS=suppressions=<path_to_tsan_suppressions.txt>
./test_wamr.sh -w -s wasi_certification -t fast-interp -T tsan
```
This commit is contained in:
Maks Litskevich 2023-11-01 10:30:25 +00:00 committed by GitHub
parent 52db362b89
commit 0b2313f6f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 59 deletions

View File

@ -49,10 +49,17 @@ jobs:
with: with:
os: "ubuntu-20.04" os: "ubuntu-20.04"
arch: "X86" arch: "X86"
build_llvm_libraries_on_ubuntu_2204:
uses: ./.github/workflows/build_llvm_libraries.yml
with:
os: "ubuntu-22.04"
arch: "X86"
build_wamrc: build_wamrc:
needs: needs:
[build_llvm_libraries_on_ubuntu_2004] [
build_llvm_libraries_on_ubuntu_2004,
]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
@ -90,7 +97,9 @@ jobs:
build_iwasm: build_iwasm:
needs: needs:
[build_llvm_libraries_on_ubuntu_2004] [
build_llvm_libraries_on_ubuntu_2004,
]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
@ -497,14 +506,15 @@ jobs:
[ [
build_iwasm, build_iwasm,
build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2004,
build_llvm_libraries_on_ubuntu_2204,
build_wamrc, build_wamrc,
] ]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-20.04] os: [ubuntu-20.04, ubuntu-22.04]
sanitizer: ["", "ubsan", "asan"] sanitizer: ["", "ubsan", "asan", "tsan"]
running_mode: running_mode:
[ [
"classic-interp", "classic-interp",
@ -530,11 +540,14 @@ jobs:
- os: ubuntu-20.04 - os: ubuntu-20.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}
ubuntu_version: "20.04" ubuntu_version: "20.04"
- os: ubuntu-22.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
ubuntu_version: "22.04"
exclude: exclude:
# uncompatiable modes and features # uncompatiable modes and features
- os: ubuntu-20.04 - os: ubuntu-20.04
sanitizer: asan sanitizer: tsan
# asan works only for aot now # asan works only for aot now
- running_mode: "classic-interp" - running_mode: "classic-interp"
sanitizer: asan sanitizer: asan
@ -546,6 +559,14 @@ jobs:
sanitizer: asan sanitizer: asan
- running_mode: "multi-tier-jit" - running_mode: "multi-tier-jit"
sanitizer: asan sanitizer: asan
- running_mode: "classic-interp"
sanitizer: tsan
- running_mode: "jit"
sanitizer: tsan
- running_mode: "fast-jit"
sanitizer: tsan
- running_mode: "multi-tier-jit"
sanitizer: tsan
# classic-interp and fast-interp don't support simd # classic-interp and fast-interp don't support simd
- running_mode: "classic-interp" - running_mode: "classic-interp"
test_option: $SIMD_TEST_OPTIONS test_option: $SIMD_TEST_OPTIONS
@ -595,9 +616,10 @@ jobs:
|| matrix.test_option == '$WASI_TEST_OPTIONS') || matrix.test_option == '$WASI_TEST_OPTIONS')
&& matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit' && matrix.running_mode != 'multi-tier-jit' && matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit' && matrix.running_mode != 'multi-tier-jit'
run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV
- name: set sanitizer - name: set additional tsan options
run: echo "WAMR_BUILD_SANITIZER=${{ matrix.sanitizer }}" >> $GITHUB_ENV run: echo "TSAN_OPTIONS=suppressions=$PWD/tsan_suppressions.txt" >> $GITHUB_ENV
working-directory: tests/wamr-test-suites
#only download llvm libraries in jit and aot mode #only download llvm libraries in jit and aot mode
- name: Get LLVM libraries - name: Get LLVM libraries
@ -638,7 +660,7 @@ jobs:
- name: run tests - name: run tests
timeout-minutes: 40 timeout-minutes: 40
run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} -T %{{matrix.sanitizer}}
working-directory: ./tests/wamr-test-suites working-directory: ./tests/wamr-test-suites
#only install x32 support libraries when to run x86_32 cases #only install x32 support libraries when to run x86_32 cases

View File

@ -12,6 +12,7 @@
#include "wasm_native.h" #include "wasm_native.h"
#include "../include/wasm_export.h" #include "../include/wasm_export.h"
#include "../interpreter/wasm.h" #include "../interpreter/wasm.h"
#if WASM_ENABLE_LIBC_WASI != 0 #if WASM_ENABLE_LIBC_WASI != 0
#if WASM_ENABLE_UVWASI == 0 #if WASM_ENABLE_UVWASI == 0
#include "wasmtime_ssp.h" #include "wasmtime_ssp.h"
@ -44,15 +45,16 @@ extern "C" {
/* For STORE opcodes */ /* For STORE opcodes */
#define STORE_I64 PUT_I64_TO_ADDR #define STORE_I64 PUT_I64_TO_ADDR
#define STORE_U32(addr, value) \ static inline void
do { \ STORE_U32(void *addr, uint32_t value)
*(uint32 *)(addr) = (uint32)(value); \ {
} while (0) *(uint32_t *)(addr) = (uint32_t)(value);
#define STORE_U16(addr, value) \ }
do { \ static inline void
*(uint16 *)(addr) = (uint16)(value); \ STORE_U16(void *addr, uint16_t value)
} while (0) {
*(uint16_t *)(addr) = (uint16_t)(value);
}
/* For LOAD opcodes */ /* For LOAD opcodes */
#define LOAD_I64(addr) (*(int64 *)(addr)) #define LOAD_I64(addr) (*(int64 *)(addr))
#define LOAD_F64(addr) (*(float64 *)(addr)) #define LOAD_F64(addr) (*(float64 *)(addr))
@ -147,42 +149,42 @@ GET_F64_FROM_ADDR(uint32 *addr)
} \ } \
} while (0) } while (0)
#define STORE_U32(addr, value) \ static inline void
do { \ STORE_U32(void *addr, uint32_t value)
uintptr_t addr_ = (uintptr_t)(addr); \ {
union { \ uintptr_t addr_ = (uintptr_t)(addr);
uint32 val; \ union {
uint16 u16[2]; \ uint32_t val;
uint8 u8[4]; \ uint16_t u16[2];
} u; \ uint8_t u8[4];
if ((addr_ & (uintptr_t)3) == 0) \ } u;
*(uint32 *)(addr) = (uint32)(value); \ if ((addr_ & (uintptr_t)3) == 0)
else { \ *(uint32_t *)(addr) = (uint32_t)(value);
u.val = (uint32)(value); \ else {
if ((addr_ & (uintptr_t)1) == 0) { \ u.val = (uint32_t)(value);
((uint16 *)(addr))[0] = u.u16[0]; \ if ((addr_ & (uintptr_t)1) == 0) {
((uint16 *)(addr))[1] = u.u16[1]; \ ((uint16_t *)(addr))[0] = u.u16[0];
} \ ((uint16_t *)(addr))[1] = u.u16[1];
else { \ }
((uint8 *)(addr))[0] = u.u8[0]; \ else {
((uint8 *)(addr))[1] = u.u8[1]; \ ((uint8_t *)(addr))[0] = u.u8[0];
((uint8 *)(addr))[2] = u.u8[2]; \ ((uint8_t *)(addr))[1] = u.u8[1];
((uint8 *)(addr))[3] = u.u8[3]; \ ((uint8_t *)(addr))[2] = u.u8[2];
} \ ((uint8_t *)(addr))[3] = u.u8[3];
} \ }
} while (0) }
}
#define STORE_U16(addr, value) \ static inline void
do { \ STORE_U16(void *addr, uint16_t value)
union { \ {
uint16 val; \ union {
uint8 u8[2]; \ uint16_t val;
} u; \ uint8_t u8[2];
u.val = (uint16)(value); \ } u;
((uint8 *)(addr))[0] = u.u8[0]; \ u.val = (uint16_t)(value);
((uint8 *)(addr))[1] = u.u8[1]; \ ((uint8_t *)(addr))[0] = u.u8[0];
} while (0) ((uint8_t *)(addr))[1] = u.u8[1];
}
/* For LOAD opcodes */ /* For LOAD opcodes */
static inline int64 static inline int64
LOAD_I64(void *addr) LOAD_I64(void *addr)

View File

@ -32,6 +32,7 @@ function help()
echo "-F set the firmware path used by qemu" echo "-F set the firmware path used by qemu"
echo "-C enable code coverage collect" echo "-C enable code coverage collect"
echo "-j set the platform to test" echo "-j set the platform to test"
echo "-T set sanitizer to use in tests(ubsan|tsan|asan)"
} }
OPT_PARSED="" OPT_PARSED=""
@ -59,7 +60,7 @@ QEMU_FIRMWARE=""
# prod/testsuite-all branch # prod/testsuite-all branch
WASI_TESTSUITE_COMMIT="ee807fc551978490bf1c277059aabfa1e589a6c2" WASI_TESTSUITE_COMMIT="ee807fc551978490bf1c277059aabfa1e589a6c2"
while getopts ":s:cabgvt:m:MCpSXxwPGQF:j:" opt while getopts ":s:cabgvt:m:MCpSXxwPGQF:j:T:" opt
do do
OPT_PARSED="TRUE" OPT_PARSED="TRUE"
case $opt in case $opt in
@ -165,9 +166,14 @@ do
echo "test platform " ${OPTARG} echo "test platform " ${OPTARG}
PLATFORM=${OPTARG} PLATFORM=${OPTARG}
;; ;;
T)
echo "sanitizer is " ${OPTARG}
WAMR_BUILD_SANITIZER=${OPTARG}
;;
?) ?)
help help
exit 1;; exit 1
;;
esac esac
done done
@ -553,7 +559,7 @@ function wasi_certification_test()
cd wasi-testsuite cd wasi-testsuite
git reset --hard ${WASI_TESTSUITE_COMMIT} git reset --hard ${WASI_TESTSUITE_COMMIT}
bash ../../wasi-test-script/run_wasi_tests.sh $1 $TARGET \ TSAN_OPTIONS=${TSAN_OPTIONS} bash ../../wasi-test-script/run_wasi_tests.sh $1 $TARGET \
| tee -a ${REPORT_DIR}/wasi_test_report.txt | tee -a ${REPORT_DIR}/wasi_test_report.txt
ret=${PIPESTATUS[0]} ret=${PIPESTATUS[0]}

View File

@ -0,0 +1,11 @@
# Proposing to accept this risk for now. It might be wasi-libc related.
# https://github.com/bytecodealliance/wasm-micro-runtime/pull/1963#issuecomment-1455342931
race:STORE_U32
# https://github.com/bytecodealliance/wasm-micro-runtime/issues/2680
race:execute_post_instantiate_functions
# Suppressing signal-unsafe inside of a signal for AOT mode
# see https://github.com/bytecodealliance/wasm-micro-runtime/issues/2248#issuecomment-1630189656
signal:*

View File

@ -67,7 +67,7 @@ if [[ $MODE != "aot" ]];then
python3 -m pip install -r test-runner/requirements.txt python3 -m pip install -r test-runner/requirements.txt
export TEST_RUNTIME_EXE="${IWASM_CMD}" export TEST_RUNTIME_EXE="${IWASM_CMD}"
python3 ${THIS_DIR}/pipe.py | python3 test-runner/wasi_test_runner.py \ python3 ${THIS_DIR}/pipe.py | TSAN_OPTIONS=${TSAN_OPTIONS} python3 test-runner/wasi_test_runner.py \
-r adapters/wasm-micro-runtime.py \ -r adapters/wasm-micro-runtime.py \
-t \ -t \
${C_TESTS} \ ${C_TESTS} \
@ -79,7 +79,7 @@ if [[ $MODE != "aot" ]];then
ret=${PIPESTATUS[1]} ret=${PIPESTATUS[1]}
TEST_RUNTIME_EXE="${IWASM_CMD_STRESS}" python3 test-runner/wasi_test_runner.py \ TEST_RUNTIME_EXE="${IWASM_CMD_STRESS}" TSAN_OPTIONS=${TSAN_OPTIONS} python3 test-runner/wasi_test_runner.py \
-r adapters/wasm-micro-runtime.py \ -r adapters/wasm-micro-runtime.py \
-t \ -t \
${THREAD_STRESS_TESTS} ${THREAD_STRESS_TESTS}