Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Profiler: pthread compatibility mode #438

Merged
merged 2 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/Manual_Quickstart/Manual_Setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ If you have installed LLVM <b>using the package manager</b>, specifying this var

Note: In case you want to use a specific Version of LLVM, it is possible to specify the `-DUSE_LLVM_VERSION=<version>` flag.

Note: In case your application uses PThreads, please specify `-DDP_PTHREAD_COMPATIBILITY_MODE=1`. Note, however, that this can influence the runtime of the profiling.

Once the configuration process is successfully finished, compile the DiscoPoP libraries using `make`. All created shared objects will be stored in the build directory and can be found inside a folder named `libi/`.

make
Expand Down
9 changes: 9 additions & 0 deletions rtlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ set(CMAKE_CXX_FLAGS

add_library(DiscoPoP_RT STATIC
${DiscoPoP_SOURCES})

# forward compiler flags
if(DEFINED DP_PTHREAD_COMPATIBILITY_MODE)
if(NOT ${DP_PTHREAD_COMPATIBILITY_MODE} EQUAL 0)
target_compile_definitions(DiscoPoP_RT PUBLIC DP_PTHREAD_COMPATIBILITY_MODE=${DP_PTHREAD_COMPATIBILITY_MODE})
endif()

endif()

install(TARGETS DiscoPoP_RT ARCHIVE DESTINATION lib)

# compile simple-alias-detection
Expand Down
47 changes: 46 additions & 1 deletion rtlib/iFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ using namespace dputil;
#define unpackLIDMetadata_getLoopIteration_1(lid) ((lid >> 40) & 0xFF)
#define unpackLIDMetadata_getLoopIteration_2(lid) ((lid >> 32) & 0xFF)

// issue a warning if DP_PTHREAD_COMPATIBILITY_MODE is enabled
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
# warning "DP_PTHREAD_COMPATIBILITY_MODE enabled! This may have negative implications on the profiling time."
#endif

bool DP_DEBUG = false; // debug flag

bool USE_PERFECT = true;
Expand Down Expand Up @@ -664,7 +669,11 @@ namespace __dp {
#else
void __dp_read(LID lid, ADDR addr, char *var) {
#endif

#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif

if (targetTerminated) {
if (DP_DEBUG) {
cout << "__dp_read() is not executed since target program has returned from main()." << endl;
Expand Down Expand Up @@ -736,7 +745,10 @@ namespace __dp {
#else
void __dp_write(LID lid, ADDR addr, char *var) {
#endif

#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
if (targetTerminated) {
if (DP_DEBUG) {
cout << "__dp_write() is not executed since target program has returned from main()." << endl;
Expand Down Expand Up @@ -808,7 +820,10 @@ namespace __dp {
#else
void __dp_decl(LID lid, ADDR addr, char *var) {
#endif

#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
if (targetTerminated) {
if (DP_DEBUG) {
cout << "__dp_write() is not executed since target program has returned from main()." << endl;
Expand Down Expand Up @@ -876,7 +891,9 @@ namespace __dp {
}

void __dp_alloca(LID lid, char *var, ADDR startAddr, ADDR endAddr, int64_t numBytes, int64_t numElements) {
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
int64_t buffer = nextFreeMemoryRegionId;
string allocId = to_string(buffer);
nextFreeMemoryRegionId++;
Expand All @@ -898,7 +915,9 @@ namespace __dp {
}

void __dp_new(LID lid, ADDR startAddr, ADDR endAddr, int64_t numBytes){
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
// instrumentation function for new and malloc
int64_t buffer = nextFreeMemoryRegionId;
string allocId = to_string(buffer);
Expand Down Expand Up @@ -928,7 +947,9 @@ namespace __dp {
}

void __dp_delete(LID lid, ADDR startAddr){
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
// DO NOT DELETE MEMORY REGIONS AS THEY ARE STILL REQUIRED FOR LOGGING

// TODO more efficient implementation
Expand All @@ -948,35 +969,47 @@ namespace __dp {
}

void __dp_report_bb(int32_t bbIndex) {
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
bbList->insert(bbIndex);
}

void __dp_report_bb_pair(int32_t semaphore, int32_t bbIndex) {
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
if (semaphore)
bbList->insert(bbIndex);
}

void __dp_finalize(LID lid) {
pthread_compatibility_mutex.lock();
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
pthread_compatibility_mutex.lock();
#endif
if (targetTerminated) {
if (DP_DEBUG) {
cout << "__dp_finalize() has been called before. Doing nothing this time to avoid double free." << endl;
}
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
pthread_compatibility_mutex.unlock();
#endif
return;
}

// release mutex so it can be re-aquired in the called __dp_func_exit
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
pthread_compatibility_mutex.unlock();
#endif

while (FuncStackLevel >= 0) {
__dp_func_exit(lid, 1);
}

// use lock_guard here, since no other mutex-aquiring function is called
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif

// Returning from main or exit from somewhere, clear up everything.
assert(FuncStackLevel == -1 && "Program terminates without clearing function stack!");
Expand Down Expand Up @@ -1027,7 +1060,9 @@ namespace __dp {

// hybrid analysis
void __dp_add_bb_deps(char *depStringPtr) {
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
string depString(depStringPtr);
regex r0("[^\\/]+"), r1("[^=]+"), r2("[^,]+"), r3("[0-9]+:[0-9]+"), r4("(INIT|(R|W)A(R|W)).*");
smatch res0, res1, res2, res3;
Expand Down Expand Up @@ -1064,12 +1099,16 @@ namespace __dp {
// End HA

void __dp_call(LID lid) {
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
lastCallOrInvoke = lid;
}

void __dp_func_entry(LID lid, int32_t isStart) {
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
if (!dpInited) {
// This part should be executed only once.
readRuntimeInfo();
Expand Down Expand Up @@ -1158,7 +1197,9 @@ namespace __dp {
}

void __dp_func_exit(LID lid, int32_t isExit) {
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
if (targetTerminated) {
if (DP_DEBUG) {
cout << "Exiting function LID " << std::dec << decodeLID(lid);
Expand Down Expand Up @@ -1215,7 +1256,9 @@ namespace __dp {
}

void __dp_loop_entry(LID lid, int32_t loopID) {
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
if (targetTerminated) {
if (DP_DEBUG) {
cout << "__dp_loop_entry() is not executed since target program has returned from main()." << endl;
Expand Down Expand Up @@ -1264,7 +1307,9 @@ namespace __dp {
}

void __dp_loop_exit(LID lid, int32_t loopID) {
#ifdef DP_PTHREAD_COMPATIBILITY_MODE
std::lock_guard<std::mutex> guard(pthread_compatibility_mutex);
#endif
if (targetTerminated) {
if (DP_DEBUG) {
cout << "__dp_loop_exit() is not executed since target program has returned from main()." << endl;
Expand Down