Skip to content

Commit

Permalink
Merge branch 'feature/reverseTsanAnnotations' into develop
Browse files Browse the repository at this point in the history
Thread sanitizer annotations for reverse mutex synchronization.
New postEvaluate() method in the logic interface.
  • Loading branch information
jblueh committed Feb 14, 2024
2 parents 2cc84e7 + 59034de commit 8c89798
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 15 deletions.
1 change: 1 addition & 0 deletions include/opdi/logic/logicInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
128 changes: 115 additions & 13 deletions include/opdi/logic/omp/mutexOmpLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
*
*/

#include <cassert>

#include "../../helpers/macros.hpp"
#include "../../helpers/exceptions.hpp"
#include "../../config.hpp"
Expand All @@ -34,8 +36,15 @@

opdi::MutexOmpLogic::State opdi::MutexOmpLogic::localState;
opdi::MutexOmpLogic::State opdi::MutexOmpLogic::evalState;

void opdi::MutexOmpLogic::internalWaitReverseFunc(std::map<std::size_t, std::size_t>& evalTrace, void* dataPtr) {
#ifdef __SANITIZE_THREAD__
opdi::MutexOmpLogic::State opdi::MutexOmpLogic::tsanDummies;
#endif

void opdi::MutexOmpLogic::internalWaitReverseFunc(std::map<std::size_t, std::size_t>& evalTrace,
#ifdef __SANITIZE_THREAD__
std::map<std::size_t, std::size_t>& tsanDummies,
#endif
void* dataPtr) {
Data* data = (Data*) dataPtr;

#if OPDI_OMP_LOGIC_INSTRUMENT
Expand All @@ -55,36 +64,68 @@ void opdi::MutexOmpLogic::internalWaitReverseFunc(std::map<std::size_t, std::siz
break;
}
}

#ifdef __SANITIZE_THREAD__
ANNOTATE_RWLOCK_ACQUIRED(&tsanDummies[data->waitId], 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) {
Data* data = (Data*) dataPtr;
delete data;
}

void opdi::MutexOmpLogic::internalDecrementReverseFunc(std::map<std::size_t, std::size_t>& evalTrace, void* dataPtr) {
void opdi::MutexOmpLogic::internalDecrementReverseFunc(std::map<std::size_t, std::size_t>& evalTrace,
#ifdef __SANITIZE_THREAD__
std::map<std::size_t, std::size_t>& 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;
Expand All @@ -97,23 +138,43 @@ void opdi::MutexOmpLogic::internalDecrementReverseFunc(std::map<std::size_t, std
}

void opdi::MutexOmpLogic::decrementCriticalReverseFunc(void* dataPtr) {
internalDecrementReverseFunc(MutexOmpLogic::evalState.criticalTrace, dataPtr);
internalDecrementReverseFunc(MutexOmpLogic::evalState.criticalTrace,
#ifdef __SANITIZE_THREAD__
MutexOmpLogic::tsanDummies.criticalTrace,
#endif
dataPtr);
}

void opdi::MutexOmpLogic::decrementLockReverseFunc(void* dataPtr) {
internalDecrementReverseFunc(MutexOmpLogic::evalState.lockTrace, dataPtr);
internalDecrementReverseFunc(MutexOmpLogic::evalState.lockTrace,
#ifdef __SANITIZE_THREAD__
MutexOmpLogic::tsanDummies.lockTrace,
#endif
dataPtr);
}

void opdi::MutexOmpLogic::decrementNestedLockReverseFunc(void* dataPtr) {
internalDecrementReverseFunc(MutexOmpLogic::evalState.nestedLockTrace, dataPtr);
internalDecrementReverseFunc(MutexOmpLogic::evalState.nestedLockTrace,
#ifdef __SANITIZE_THREAD__
MutexOmpLogic::tsanDummies.nestedLockTrace,
#endif
dataPtr);
}

void opdi::MutexOmpLogic::decrementOrderedReverseFunc(void* dataPtr) {
internalDecrementReverseFunc(MutexOmpLogic::evalState.orderedTrace, dataPtr);
internalDecrementReverseFunc(MutexOmpLogic::evalState.orderedTrace,
#ifdef __SANITIZE_THREAD__
MutexOmpLogic::tsanDummies.orderedTrace,
#endif
dataPtr);
}

void opdi::MutexOmpLogic::decrementReductionReverseFunc(void* dataPtr) {
internalDecrementReverseFunc(MutexOmpLogic::evalState.reductionTrace, dataPtr);
internalDecrementReverseFunc(MutexOmpLogic::evalState.reductionTrace,
#ifdef __SANITIZE_THREAD__
MutexOmpLogic::tsanDummies.reductionTrace,
#endif
dataPtr);
}

void opdi::MutexOmpLogic::decrementDeleteFunc(void* dataPtr) {
Expand Down Expand Up @@ -348,6 +409,47 @@ void opdi::MutexOmpLogic::prepareEvaluate() {
MutexOmpLogic::evalState.nestedLockTrace = this->nestedLockTrace.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() {
Expand Down
16 changes: 14 additions & 2 deletions include/opdi/logic/omp/mutexOmpLogic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ namespace opdi {
#pragma omp threadprivate(localState)

static State evalState;
#ifdef __SANITIZE_THREAD__
static State tsanDummies;
#endif

public:

Expand All @@ -77,7 +80,11 @@ namespace opdi {

private:

static void internalWaitReverseFunc(std::map<std::size_t, std::size_t>& evalTrace, void* dataPtr);
static void internalWaitReverseFunc(std::map<std::size_t, std::size_t>& evalTrace,
#ifdef __SANITIZE_THREAD__
std::map<std::size_t, std::size_t>& tsanDummies,
#endif
void* dataPtr);

static void waitCriticalReverseFunc(void* dataPtr);
static void waitLockReverseFunc(void* dataPtr);
Expand All @@ -87,7 +94,11 @@ namespace opdi {

static void waitDeleteFunc(void* dataPtr);

static void internalDecrementReverseFunc(std::map<std::size_t, std::size_t>& evalTrace, void* dataPtr);
static void internalDecrementReverseFunc(std::map<std::size_t, std::size_t>& evalTrace,
#ifdef __SANITIZE_THREAD__
std::map<std::size_t, std::size_t>& tsanDummies,
#endif
void* dataPtr);

static void decrementCriticalReverseFunc(void* dataPtr);
static void decrementLockReverseFunc(void* dataPtr);
Expand Down Expand Up @@ -123,6 +134,7 @@ namespace opdi {
virtual void registerInactiveMutex(MutexKind kind, std::size_t waitId);

void prepareEvaluate();
void postEvaluate();
void reset();

void* exportState();
Expand Down
3 changes: 3 additions & 0 deletions tests/drivers/DriverFirstOrderReverse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ struct DriverFirstOrderReverse : public DriverBase<DriverFirstOrderReverse<_Case
opdi::logic->prepareEvaluate();
#endif
tape.evaluate();
#ifndef BUILD_REFERENCE
opdi::logic->postEvaluate();
#endif

for (int i = 0; i < Case::nIn; ++i)
{
Expand Down
3 changes: 3 additions & 0 deletions tests/drivers/DriverFirstOrderReverseNestedParallel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ struct DriverFirstOrderReverseNestedParallel : public DriverBase<DriverFirstOrde
opdi::logic->prepareEvaluate();
#endif
tape.evaluate();
#ifndef BUILD_REFERENCE
opdi::logic->postEvaluate();
#endif

for (int i = 0; i < Case::nIn; ++i)
{
Expand Down
3 changes: 3 additions & 0 deletions tests/drivers/DriverFirstOrderReverseNoOpenMP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ struct DriverFirstOrderReverseNoOpenMP : public DriverBase<DriverFirstOrderRever
opdi::logic->prepareEvaluate();
#endif
tape.evaluate();
#ifndef BUILD_REFERENCE
opdi::logic->postEvaluate();
#endif

for (int i = 0; i < Case::nIn; ++i)
{
Expand Down
3 changes: 3 additions & 0 deletions tests/drivers/DriverFirstOrderReversePassive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ struct DriverFirstOrderReversePassive : public DriverBase<DriverFirstOrderRevers
opdi::logic->prepareEvaluate();
#endif
tape.evaluate();
#ifndef BUILD_REFERENCE
opdi::logic->postEvaluate();
#endif

for (int i = 0; i < Case::nIn; ++i)
{
Expand Down
3 changes: 3 additions & 0 deletions tests/drivers/DriverSecondOrderReverseForward.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ struct DriverSecondOrderReverseForward : public DriverBase<DriverSecondOrderReve
opdi::logic->prepareEvaluate();
#endif
tape.evaluate();
#ifndef BUILD_REFERENCE
opdi::logic->postEvaluate();
#endif

for (int i = 0; i < Case::nIn; ++i)
{
Expand Down

0 comments on commit 8c89798

Please sign in to comment.