diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 1cbc6a5b..8512d978 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -301,6 +301,117 @@ jobs: PPC_ASAN_RUN: 1 ASAN_OPTIONS: abort_on_error=1 UBSAN_OPTIONS: halt_on_error=1 + ubuntu-clang-thread-sanitizer-build: + needs: + - ubuntu-clang-build + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: ["ubuntu-24.04"] + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Setup environment + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends -y ninja-build python3-pip \ + openmpi-bin openmpi-common libopenmpi-dev + wget https://apt.llvm.org/llvm.sh + chmod u+x llvm.sh + sudo ./llvm.sh 20 all + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ runner.os }}-clang + create-symlink: true + max-size: 1G + - name: CMake configure + run: > + cmake -S . -B build -G Ninja + -D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache + -D CMAKE_BUILD_TYPE=RELEASE -D ENABLE_THREAD_SANITIZER=ON + -D CMAKE_INSTALL_PREFIX=install + env: + CC: clang-20 + CXX: clang++-20 + - name: Build project + run: | + cmake --build build --parallel + env: + CC: clang-20 + CXX: clang++-20 + - name: Install project + run: | + cmake --build build --target install + - name: Archive installed package + run: | + tar -czvf ubuntu-clang-thread-sanitizer-install-${{ matrix.os }}.tar.gz -C install . + - name: Upload installed package + uses: actions/upload-artifact@v4 + with: + name: ubuntu-clang-thread-sanitizer-install-${{ matrix.os }} + path: ubuntu-clang-thread-sanitizer-install-${{ matrix.os }}.tar.gz + ubuntu-clang-thread-sanitizer-test: + needs: + - ubuntu-clang-thread-sanitizer-build + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: ["ubuntu-24.04"] + steps: + - uses: actions/checkout@v4 + - name: Setup environment + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends -y ninja-build python3-pip valgrind \ + openmpi-bin openmpi-common libopenmpi-dev + wget https://apt.llvm.org/llvm.sh + chmod u+x llvm.sh + sudo ./llvm.sh 20 all + - name: Download installed package + uses: actions/download-artifact@v4 + with: + name: ubuntu-clang-thread-sanitizer-install-${{ matrix.os }} + - name: Extract installed package + run: | + mkdir -p install + tar -xzvf ubuntu-clang-thread-sanitizer-install-${{ matrix.os }}.tar.gz -C install + - name: Run tests (MPI) + run: python3 scripts/run_tests.py --running-type="processes" --additional-mpi-args="--oversubscribe" + env: + PPC_NUM_PROC: 2 + PPC_NUM_THREADS: 2 + PPC_ASAN_RUN: 1 + TSAN_OPTIONS: ignore_noninstrumented_modules=1 + - name: Run tests (threads, num_threads=1) + run: python3 scripts/run_tests.py --running-type="threads" + env: + PPC_NUM_PROC: 1 + PPC_NUM_THREADS: 1 + PPC_ASAN_RUN: 1 + TSAN_OPTIONS: ignore_noninstrumented_modules=1 + - name: Run tests (threads, num_threads=2) + run: python3 scripts/run_tests.py --running-type="threads" + env: + PPC_NUM_PROC: 1 + PPC_NUM_THREADS: 2 + PPC_ASAN_RUN: 1 + TSAN_OPTIONS: ignore_noninstrumented_modules=1 + - name: Run tests (threads, num_threads=3) + run: python3 scripts/run_tests.py --running-type="threads" + env: + PPC_NUM_PROC: 1 + PPC_NUM_THREADS: 3 + PPC_ASAN_RUN: 1 + TSAN_OPTIONS: ignore_noninstrumented_modules=1 + - name: Run tests (threads, num_threads=4) + run: python3 scripts/run_tests.py --running-type="threads" + env: + PPC_NUM_PROC: 1 + PPC_NUM_THREADS: 4 + PPC_ASAN_RUN: 1 + TSAN_OPTIONS: ignore_noninstrumented_modules=1 ubuntu-clang-sanitizer-test-extended: needs: - ubuntu-clang-sanitizer-test diff --git a/cmake/configure.cmake b/cmake/configure.cmake index 802010d6..277c53b3 100644 --- a/cmake/configure.cmake +++ b/cmake/configure.cmake @@ -66,7 +66,8 @@ if(UNIX) if("${ENABLE_ADDRESS_SANITIZER}" OR "${ENABLE_UB_SANITIZER}" - OR "${ENABLE_LEAK_SANITIZER}") + OR "${ENABLE_LEAK_SANITIZER}" + OR "${ENABLE_THREAD_SANITIZER}") set(COMMON_COMPILER_FLAGS "${COMMON_COMPILER_FLAGS} -Wno-cast-align") endif() diff --git a/cmake/sanitizers.cmake b/cmake/sanitizers.cmake index d589a080..17c8772e 100644 --- a/cmake/sanitizers.cmake +++ b/cmake/sanitizers.cmake @@ -16,6 +16,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") add_link_options(-fsanitize=leak) message(STATUS "Enabled leak sanitizer") endif() + if (ENABLE_THREAD_SANITIZER) + add_compile_options(-fsanitize=thread) + add_link_options(-fsanitize=thread) + message(STATUS "Enabled thread sanitizer") + endif() else() message(WARNING "Sanitizers are supported on gcc and clang compilers only!") endif() diff --git a/tasks/example_threads/omp/src/ops_omp.cpp b/tasks/example_threads/omp/src/ops_omp.cpp index ee3f42df..159f109d 100644 --- a/tasks/example_threads/omp/src/ops_omp.cpp +++ b/tasks/example_threads/omp/src/ops_omp.cpp @@ -36,11 +36,13 @@ bool NesterovATestTaskOMP::RunImpl() { const int num_threads = ppc::util::GetNumThreads(); GetOutput() *= num_threads; - std::atomic counter(0); -#pragma omp parallel default(none) shared(counter) num_threads(ppc::util::GetNumThreads()) - counter++; + std::atomic counter{0}; +#pragma omp parallel default(none) shared(counter) num_threads(num_threads) + { + counter.fetch_add(1, std::memory_order_relaxed); + } - GetOutput() /= counter; + GetOutput() /= counter.load(std::memory_order_relaxed); return GetOutput() > 0; }