Skip to content

Commit 62f6b5f

Browse files
committed
Automatic thread sanitizer tests.
Add container file for tsan tests. Tsan annotations of custom mutex. Separate header with tsan-related definitions. Option to exclude specific drivers and tests. Merge branch 'feature/threadSanitizer' into develop
2 parents b742ef8 + 10c6dd2 commit 62f6b5f

7 files changed

Lines changed: 118 additions & 6 deletions

File tree

.gitlab-ci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,16 @@ address-sanitizer:
8181
- export CXXFLAGS="-g -fsanitize=address -fno-omit-frame-pointer"
8282
- export OMP_NUM_THREADS=$(expr $(nproc --all) / 2)
8383
- make all
84+
85+
thread-sanitizer:
86+
image: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/opdilib/opdi-tsan
87+
script:
88+
- git clone --depth 1 --branch develop https://github.com/SciCompKL/CoDiPack.git
89+
- export CODI_DIR=$(pwd)/CoDiPack/include
90+
- export OPDI_DIR=$(pwd)/include
91+
- cd tests
92+
- export CXX=g++
93+
- export CXXFLAGS="$CXXFLAGS -g"
94+
- export EXCLUDE_TESTS="CriticalLock CriticalName CriticalNameHint ParallelNested PreaccumulationLocal SectionsNowait"
95+
- export OMP_NUM_THREADS=$(expr $(nproc --all) / 2)
96+
- make all

containers/Dockerfile.opdi.tsan

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
FROM ubuntu:24.04
2+
3+
RUN DEBIAN_FRONTEND=noninteractive apt update && apt install -y build-essential binutils git curl flex
4+
5+
RUN \
6+
cd / \
7+
&& git clone --depth 1 --branch releases/gcc-15.2.0 git://gcc.gnu.org/git/gcc.git gcc_sources \
8+
&& cd gcc_sources \
9+
&& ./contrib/download_prerequisites \
10+
&& cd / \
11+
&& mkdir gcc_objdir \
12+
&& cd gcc_objdir \
13+
&& /gcc_sources/configure --prefix=/gcc_install --enable-languages=c,c++ --disable-linux-futex --disable-multilib \
14+
&& make -j $(nproc --all) \
15+
&& make install \
16+
&& cd / \
17+
&& rm -rf gcc_sources \
18+
&& rm -rf gcc_objdir
19+
20+
ENV LD_LIBRARY_PATH=/gcc_install/lib64:$LD_LIBRARY_PATH
21+
ENV CXXFLAGS="-I/gcc_install/include/c++/15.2.0 -I/gcc_install/include/c++/15.2.0/x86_64-pc-linux-gnu -fsanitize=thread"
22+
ENV CFLAGS="-I/gcc_install/include/c++/15.2.0 -I/gcc_install/include/c++/15.2.0/x86_64-pc-linux-gnu -fsanitize=thread"
23+
ENV LDFLAGS="-L/gcc_install/lib64 -fsanitize=thread"
24+
ENV PATH=/gcc_install/bin:$PATH
25+
ENV TSAN_OPTIONS="history_size=7 halt_on_error=1"
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* OpDiLib, an Open Multiprocessing Differentiation Library
3+
*
4+
* Copyright (C) 2020-2022 Chair for Scientific Computing (SciComp), TU Kaiserslautern
5+
* Copyright (C) 2023-2025 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau
6+
* Homepage: https://scicomp.rptu.de
7+
* Contact: Prof. Nicolas R. Gauger (opdi@scicomp.uni-kl.de)
8+
*
9+
* Lead developer: Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau)
10+
*
11+
* This file is part of OpDiLib (https://scicomp.rptu.de/software/opdi).
12+
*
13+
* OpDiLib is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
14+
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
15+
* version.
16+
*
17+
* OpDiLib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
18+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19+
* details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public License along with OpDiLib. If not, see
22+
* <http://www.gnu.org/licenses/>.
23+
*
24+
*/
25+
26+
#pragma once
27+
28+
#ifdef __SANITIZE_THREAD__
29+
#define ANNOTATE_RWLOCK_CREATE(lock) AnnotateRWLockCreate(__FILE__, __LINE__, (void*)lock)
30+
#define ANNOTATE_RWLOCK_DESTROY(lock) AnnotateRWLockDestroy(__FILE__, __LINE__, (void*)lock)
31+
#define ANNOTATE_RWLOCK_ACQUIRED(lock, isWrite) AnnotateRWLockAcquired(__FILE__, __LINE__, (void*)lock, isWrite)
32+
#define ANNOTATE_RWLOCK_RELEASED(lock, isWrite) AnnotateRWLockReleased(__FILE__, __LINE__, (void*)lock, isWrite)
33+
34+
extern "C" void AnnotateRWLockCreate(const char* f, int l, void* addr);
35+
extern "C" void AnnotateRWLockDestroy(const char* f, int l, void* addr);
36+
extern "C" void AnnotateRWLockAcquired(const char* f, int l, void* addr, size_t isWrite);
37+
extern "C" void AnnotateRWLockReleased(const char* f, int l, void* addr, size_t isWrite);
38+
#endif

include/opdi/logic/omp/mutexOmpLogic.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525

2626
#include <cassert>
2727

28-
#include "../../helpers/macros.hpp"
2928
#include "../../helpers/exceptions.hpp"
29+
#include "../../helpers/macros.hpp"
30+
#include "../../helpers/tsanDefinitions.hpp"
3031
#include "../../config.hpp"
3132
#include "../../tool/toolInterface.hpp"
3233

tests/Makefile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,16 @@ else
7171
FLAGS += -DOPDI_USE_OMPT_BACKEND
7272
endif
7373

74+
EXCLUDE_TESTS ?=
75+
EXCLUDE_DRIVERS ?=
76+
7477
# list all test files and extract test names
7578
TEST_FILES = $(wildcard $(TEST_DIR)/Test**.hpp)
76-
TESTS ?= $(patsubst $(TEST_DIR)/Test%.hpp,%,$(TEST_FILES))
79+
TESTS ?= $(filter-out $(EXCLUDE_TESTS), $(patsubst $(TEST_DIR)/Test%.hpp,%,$(TEST_FILES)))
7780

7881
# list all driver files and extract driver names
7982
DRIVER_FILES = $(wildcard $(DRIVER_DIR)/Driver**.hpp)
80-
DRIVERS ?= $(patsubst $(DRIVER_DIR)/Driver%.hpp,%,$(DRIVER_FILES))
83+
DRIVERS ?= $(filter-out $(EXCLUDE_DRIVERS), $(patsubst $(DRIVER_DIR)/Driver%.hpp,%,$(DRIVER_FILES)))
8184

8285
# exclude specific tests on a per-driver basis
8386
DRIVERS_USING_ALL_TESTS = $(filter-out FirstOrderReverseNoParallel FirstOrderForward Primal, $(DRIVERS))
@@ -115,7 +118,8 @@ all:
115118
prepareGenerate:
116119
@ mkdir -p build; \
117120
rm -r -f tempmakefile; \
118-
printf "# auto generated by OpDiLib\n" >> tempmakefile;
121+
printf "# auto generated by OpDiLib\n" >> tempmakefile; \
122+
$(CXX) --version;
119123

120124
# process each driver with its associated tests
121125
$(DRIVERS):

tests/tests/TestCustomMutex.hpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
#pragma once
2727

28+
#include "opdi/helpers/tsanDefinitions.hpp"
29+
2830
#include "testBase.hpp"
2931

3032
template<typename _Case>
@@ -37,8 +39,27 @@ struct TestCustomMutex : public TestBase<4, 1, 3, TestCustomMutex<_Case>> {
3739
private:
3840
int status;
3941

42+
#ifdef __SANITIZE_THREAD__
43+
int dummy;
44+
#endif
45+
4046
public:
41-
CustomMutex() : status(0) {}
47+
CustomMutex() : status(0)
48+
#ifdef __SANITIZE_THREAD__
49+
, dummy(0)
50+
#endif
51+
{
52+
53+
#ifdef __SANITIZE_THREAD__
54+
ANNOTATE_RWLOCK_CREATE(&dummy);
55+
#endif
56+
}
57+
58+
~CustomMutex() {
59+
#ifdef __SANITIZE_THREAD__
60+
ANNOTATE_RWLOCK_DESTROY(&dummy);
61+
#endif
62+
}
4263

4364
void lock() {
4465
int localStatus;
@@ -69,16 +90,26 @@ struct TestCustomMutex : public TestBase<4, 1, 3, TestCustomMutex<_Case>> {
6990
#endif
7091
--status;
7192
}
93+
94+
#ifdef __SANITIZE_THREAD__
95+
ANNOTATE_RWLOCK_ACQUIRED(&dummy, true);
96+
#endif
97+
7298
#ifdef _OPENMP
7399
opdi::logic->onMutexAcquired(opdi::LogicInterface::MutexKind::Custom, reinterpret_cast<opdi::LogicInterface::WaitId>(&status));
74100
#endif
75101
}
76102

77103
void unlock() {
104+
#ifdef __SANITIZE_THREAD__
105+
ANNOTATE_RWLOCK_RELEASED(&dummy, true);
106+
#endif
107+
78108
#ifdef _OPENMP
79109
#pragma omp atomic update
80110
#endif
81111
--status;
112+
82113
#ifdef _OPENMP
83114
opdi::logic->onMutexReleased(opdi::LogicInterface::MutexKind::Custom, reinterpret_cast<opdi::LogicInterface::WaitId>(&status));
84115
#endif

tests/tests/TestTaskReset.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ struct TestTaskReset : public TestBase<4, 1, 3, TestTaskReset<_Case>> {
105105
assertAdjointAccessMode(opdi::LogicInterface::AdjointAccessMode::Atomic);
106106

107107
// remove the inner parallel region by positional reset
108-
T::getTape().resetTo(position);
108+
T::getTape().resetTo(position, false);
109109

110110
#if _OPENMP
111111
opdi::logic->resetImplicitTask(&position, mode);

0 commit comments

Comments
 (0)