From bf64b7a3bc043ef366548e9a15a899692af14d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Bl=C3=BChdorn?= Date: Wed, 14 Feb 2024 11:04:34 +0100 Subject: [PATCH 1/3] Add postEvaluate() to logic interface. --- include/opdi/logic/logicInterface.hpp | 1 + include/opdi/logic/omp/mutexOmpLogic.cpp | 5 +++++ include/opdi/logic/omp/mutexOmpLogic.hpp | 1 + 3 files changed, 7 insertions(+) diff --git a/include/opdi/logic/logicInterface.hpp b/include/opdi/logic/logicInterface.hpp index 5057809..cfd9907 100644 --- a/include/opdi/logic/logicInterface.hpp +++ b/include/opdi/logic/logicInterface.hpp @@ -75,6 +75,7 @@ namespace opdi { virtual void init() = 0; virtual void finalize() = 0; virtual void prepareEvaluate() = 0; + virtual void postEvaluate() = 0; virtual void reset() = 0; virtual void* exportState() = 0; diff --git a/include/opdi/logic/omp/mutexOmpLogic.cpp b/include/opdi/logic/omp/mutexOmpLogic.cpp index 498c072..f3fb809 100644 --- a/include/opdi/logic/omp/mutexOmpLogic.cpp +++ b/include/opdi/logic/omp/mutexOmpLogic.cpp @@ -350,6 +350,11 @@ void opdi::MutexOmpLogic::prepareEvaluate() { MutexOmpLogic::evalState.reductionTrace = this->reductionTrace.trace; } + +void opdi::MutexOmpLogic::postEvaluate() { + +} + void opdi::MutexOmpLogic::reset() { this->criticalTrace.trace.clear(); this->lockTrace.trace.clear(); diff --git a/include/opdi/logic/omp/mutexOmpLogic.hpp b/include/opdi/logic/omp/mutexOmpLogic.hpp index a4bd3fd..8cf6745 100644 --- a/include/opdi/logic/omp/mutexOmpLogic.hpp +++ b/include/opdi/logic/omp/mutexOmpLogic.hpp @@ -123,6 +123,7 @@ namespace opdi { virtual void registerInactiveMutex(MutexKind kind, std::size_t waitId); void prepareEvaluate(); + void postEvaluate(); void reset(); void* exportState(); From 6cc8782cc005dee4423872c1705cb2602e719290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Bl=C3=BChdorn?= Date: Wed, 14 Feb 2024 14:48:58 +0100 Subject: [PATCH 2/3] Add postEvaluate to test drivers. --- tests/drivers/DriverFirstOrderReverse.hpp | 3 +++ tests/drivers/DriverFirstOrderReverseNestedParallel.hpp | 3 +++ tests/drivers/DriverFirstOrderReverseNoOpenMP.hpp | 3 +++ tests/drivers/DriverFirstOrderReversePassive.hpp | 3 +++ tests/drivers/DriverSecondOrderReverseForward.hpp | 3 +++ 5 files changed, 15 insertions(+) diff --git a/tests/drivers/DriverFirstOrderReverse.hpp b/tests/drivers/DriverFirstOrderReverse.hpp index 18f792f..0a07581 100644 --- a/tests/drivers/DriverFirstOrderReverse.hpp +++ b/tests/drivers/DriverFirstOrderReverse.hpp @@ -111,6 +111,9 @@ struct DriverFirstOrderReverse : public DriverBaseprepareEvaluate(); #endif tape.evaluate(); + #ifndef BUILD_REFERENCE + opdi::logic->postEvaluate(); + #endif for (int i = 0; i < Case::nIn; ++i) { diff --git a/tests/drivers/DriverFirstOrderReverseNestedParallel.hpp b/tests/drivers/DriverFirstOrderReverseNestedParallel.hpp index 15fbf06..994322a 100644 --- a/tests/drivers/DriverFirstOrderReverseNestedParallel.hpp +++ b/tests/drivers/DriverFirstOrderReverseNestedParallel.hpp @@ -115,6 +115,9 @@ struct DriverFirstOrderReverseNestedParallel : public DriverBaseprepareEvaluate(); #endif tape.evaluate(); + #ifndef BUILD_REFERENCE + opdi::logic->postEvaluate(); + #endif for (int i = 0; i < Case::nIn; ++i) { diff --git a/tests/drivers/DriverFirstOrderReverseNoOpenMP.hpp b/tests/drivers/DriverFirstOrderReverseNoOpenMP.hpp index 92aafbc..2a7c862 100644 --- a/tests/drivers/DriverFirstOrderReverseNoOpenMP.hpp +++ b/tests/drivers/DriverFirstOrderReverseNoOpenMP.hpp @@ -112,6 +112,9 @@ struct DriverFirstOrderReverseNoOpenMP : public DriverBaseprepareEvaluate(); #endif tape.evaluate(); + #ifndef BUILD_REFERENCE + opdi::logic->postEvaluate(); + #endif for (int i = 0; i < Case::nIn; ++i) { diff --git a/tests/drivers/DriverFirstOrderReversePassive.hpp b/tests/drivers/DriverFirstOrderReversePassive.hpp index a531749..3f5670f 100644 --- a/tests/drivers/DriverFirstOrderReversePassive.hpp +++ b/tests/drivers/DriverFirstOrderReversePassive.hpp @@ -110,6 +110,9 @@ struct DriverFirstOrderReversePassive : public DriverBaseprepareEvaluate(); #endif tape.evaluate(); + #ifndef BUILD_REFERENCE + opdi::logic->postEvaluate(); + #endif for (int i = 0; i < Case::nIn; ++i) { diff --git a/tests/drivers/DriverSecondOrderReverseForward.hpp b/tests/drivers/DriverSecondOrderReverseForward.hpp index 7c8a2ab..de82a44 100644 --- a/tests/drivers/DriverSecondOrderReverseForward.hpp +++ b/tests/drivers/DriverSecondOrderReverseForward.hpp @@ -117,6 +117,9 @@ struct DriverSecondOrderReverseForward : public DriverBaseprepareEvaluate(); #endif tape.evaluate(); + #ifndef BUILD_REFERENCE + opdi::logic->postEvaluate(); + #endif for (int i = 0; i < Case::nIn; ++i) { From 59034dea8c39a8660a13fbe32d40e032572643ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Bl=C3=BChdorn?= Date: Wed, 14 Feb 2024 14:49:43 +0100 Subject: [PATCH 3/3] Add thread sanitizer annotations for reverse mutex synchronization. --- include/opdi/logic/omp/mutexOmpLogic.cpp | 125 ++++++++++++++++++++--- include/opdi/logic/omp/mutexOmpLogic.hpp | 15 ++- 2 files changed, 124 insertions(+), 16 deletions(-) diff --git a/include/opdi/logic/omp/mutexOmpLogic.cpp b/include/opdi/logic/omp/mutexOmpLogic.cpp index f3fb809..e508ca6 100644 --- a/include/opdi/logic/omp/mutexOmpLogic.cpp +++ b/include/opdi/logic/omp/mutexOmpLogic.cpp @@ -23,6 +23,8 @@ * */ +#include + #include "../../helpers/macros.hpp" #include "../../helpers/exceptions.hpp" #include "../../config.hpp" @@ -34,8 +36,15 @@ opdi::MutexOmpLogic::State opdi::MutexOmpLogic::localState; opdi::MutexOmpLogic::State opdi::MutexOmpLogic::evalState; - -void opdi::MutexOmpLogic::internalWaitReverseFunc(std::map& evalTrace, void* dataPtr) { +#ifdef __SANITIZE_THREAD__ + opdi::MutexOmpLogic::State opdi::MutexOmpLogic::tsanDummies; +#endif + +void opdi::MutexOmpLogic::internalWaitReverseFunc(std::map& evalTrace, + #ifdef __SANITIZE_THREAD__ + std::map& tsanDummies, + #endif + void* dataPtr) { Data* data = (Data*) dataPtr; #if OPDI_OMP_LOGIC_INSTRUMENT @@ -55,26 +64,50 @@ void opdi::MutexOmpLogic::internalWaitReverseFunc(std::mapwaitId], true); + #endif } void opdi::MutexOmpLogic::waitCriticalReverseFunc(void* dataPtr) { - internalWaitReverseFunc(MutexOmpLogic::evalState.criticalTrace, dataPtr); + internalWaitReverseFunc(MutexOmpLogic::evalState.criticalTrace, + #ifdef __SANITIZE_THREAD__ + MutexOmpLogic::tsanDummies.criticalTrace, + #endif + dataPtr); } void opdi::MutexOmpLogic::waitLockReverseFunc(void* dataPtr) { - internalWaitReverseFunc(MutexOmpLogic::evalState.lockTrace, dataPtr); + internalWaitReverseFunc(MutexOmpLogic::evalState.lockTrace, + #ifdef __SANITIZE_THREAD__ + MutexOmpLogic::tsanDummies.lockTrace, + #endif + dataPtr); } void opdi::MutexOmpLogic::waitNestedLockReverseFunc(void* dataPtr) { - internalWaitReverseFunc(MutexOmpLogic::evalState.nestedLockTrace, dataPtr); + internalWaitReverseFunc(MutexOmpLogic::evalState.nestedLockTrace, + #ifdef __SANITIZE_THREAD__ + MutexOmpLogic::tsanDummies.nestedLockTrace, + #endif + dataPtr); } void opdi::MutexOmpLogic::waitOrderedReverseFunc(void* dataPtr) { - internalWaitReverseFunc(MutexOmpLogic::evalState.orderedTrace, dataPtr); + internalWaitReverseFunc(MutexOmpLogic::evalState.orderedTrace, + #ifdef __SANITIZE_THREAD__ + MutexOmpLogic::tsanDummies.orderedTrace, + #endif + dataPtr); } void opdi::MutexOmpLogic::waitReductionReverseFunc(void* dataPtr) { - internalWaitReverseFunc(MutexOmpLogic::evalState.reductionTrace, dataPtr); + internalWaitReverseFunc(MutexOmpLogic::evalState.reductionTrace, + #ifdef __SANITIZE_THREAD__ + MutexOmpLogic::tsanDummies.reductionTrace, + #endif + dataPtr); } void opdi::MutexOmpLogic::waitDeleteFunc(void* dataPtr) { @@ -82,9 +115,17 @@ void opdi::MutexOmpLogic::waitDeleteFunc(void* dataPtr) { delete data; } -void opdi::MutexOmpLogic::internalDecrementReverseFunc(std::map& evalTrace, void* dataPtr) { +void opdi::MutexOmpLogic::internalDecrementReverseFunc(std::map& evalTrace, + #ifdef __SANITIZE_THREAD__ + std::map& tsanDummies, + #endif + void* dataPtr) { Data* data = (Data*) dataPtr; + #ifdef __SANITIZE_THREAD__ + ANNOTATE_RWLOCK_RELEASED(&tsanDummies[data->waitId], true); + #endif + // decrement trace value #pragma omp atomic update evalTrace[data->waitId] -= 1; @@ -97,23 +138,43 @@ void opdi::MutexOmpLogic::internalDecrementReverseFunc(std::mapnestedLockTrace.trace; MutexOmpLogic::evalState.orderedTrace = this->orderedTrace.trace; MutexOmpLogic::evalState.reductionTrace = this->reductionTrace.trace; -} +#ifdef __SANITIZE_THREAD__ + /* create lock annotations for the reverse pass */ + + auto createReverseLocks=[](MutexOmpLogic::Trace const& evalState, MutexOmpLogic::Trace& tsanDummies) { + assert(tsanDummies.empty()); + for (auto const& pair : evalState) { + tsanDummies[pair.first] = 0; + } + + for (auto& pair : tsanDummies) { + ANNOTATE_RWLOCK_CREATE(&pair.second); + } + }; + + createReverseLocks(MutexOmpLogic::evalState.criticalTrace, MutexOmpLogic::tsanDummies.criticalTrace); + createReverseLocks(MutexOmpLogic::evalState.lockTrace, MutexOmpLogic::tsanDummies.lockTrace); + createReverseLocks(MutexOmpLogic::evalState.nestedLockTrace, MutexOmpLogic::tsanDummies.nestedLockTrace); + createReverseLocks(MutexOmpLogic::evalState.orderedTrace, MutexOmpLogic::tsanDummies.orderedTrace); + createReverseLocks(MutexOmpLogic::evalState.reductionTrace, MutexOmpLogic::tsanDummies.reductionTrace); +#endif +} void opdi::MutexOmpLogic::postEvaluate() { +#ifdef __SANITIZE_THREAD__ + /* destroy lock annotations */ + + auto destroyReverseLocks=[](MutexOmpLogic::Trace& tsanDummies) { + for (auto& pair : tsanDummies) { + ANNOTATE_RWLOCK_DESTROY(&pair.second); + } + + tsanDummies.clear(); + }; + destroyReverseLocks(MutexOmpLogic::tsanDummies.criticalTrace); + destroyReverseLocks(MutexOmpLogic::tsanDummies.lockTrace); + destroyReverseLocks(MutexOmpLogic::tsanDummies.nestedLockTrace); + destroyReverseLocks(MutexOmpLogic::tsanDummies.orderedTrace); + destroyReverseLocks(MutexOmpLogic::tsanDummies.reductionTrace); +#endif } void opdi::MutexOmpLogic::reset() { diff --git a/include/opdi/logic/omp/mutexOmpLogic.hpp b/include/opdi/logic/omp/mutexOmpLogic.hpp index 8cf6745..14e9f5c 100644 --- a/include/opdi/logic/omp/mutexOmpLogic.hpp +++ b/include/opdi/logic/omp/mutexOmpLogic.hpp @@ -65,6 +65,9 @@ namespace opdi { #pragma omp threadprivate(localState) static State evalState; +#ifdef __SANITIZE_THREAD__ + static State tsanDummies; +#endif public: @@ -77,7 +80,11 @@ namespace opdi { private: - static void internalWaitReverseFunc(std::map& evalTrace, void* dataPtr); + static void internalWaitReverseFunc(std::map& evalTrace, + #ifdef __SANITIZE_THREAD__ + std::map& tsanDummies, + #endif + void* dataPtr); static void waitCriticalReverseFunc(void* dataPtr); static void waitLockReverseFunc(void* dataPtr); @@ -87,7 +94,11 @@ namespace opdi { static void waitDeleteFunc(void* dataPtr); - static void internalDecrementReverseFunc(std::map& evalTrace, void* dataPtr); + static void internalDecrementReverseFunc(std::map& evalTrace, + #ifdef __SANITIZE_THREAD__ + std::map& tsanDummies, + #endif + void* dataPtr); static void decrementCriticalReverseFunc(void* dataPtr); static void decrementLockReverseFunc(void* dataPtr);