12 #include <sys/types.h>
15 #include <semaphore.h>
21 #include <sys/syscall.h>
40 #define MAX_FILE_PATH (200)
44 #define ENTER_RANK(phase) (((phase) + 1) & 0xfffffffffffffffe)
48 #define EXIT_RANK(phase) ((phase)&0xfffffffffffffffe)
50 #define MAX_REGIONS (1 << 20)
88 #define OMP_RUMTIMR_LIB_NAME "/home/xl10/support/gcc-4.7-install/lib64/libgomp.so.1"
89 #define LINUX_LD_NAME "/lib64/ld-linux-x86-64.so.2"
90 #define MAX_SKIP_IMAGES (2)
104 volatile atomic<uint64_t> readStart;
157 inline uint8_t
GetLength()
const {
return m_labelLength; }
158 inline void SetLength(uint64_t len) { m_labelLength = len; }
159 inline void IncrementRef() { m_refCount.fetch_add(1, memory_order_acq_rel); }
161 if (m_refCount.fetch_sub(1, memory_order_acq_rel) == 1) {
168 : m_labelLength(1), m_refCount(0) {
170 m_LabelSegment[0].
offset = 0;
171 m_LabelSegment[0].
span = 1;
172 m_LabelSegment[0].
phase = 0;
177 assert(index < GetLength());
178 return &m_LabelSegment[index];
184 for (uint32_t i = 0; i < GetLength(); i++) {
194 for (; i < GetLength() - 1; i++) {
197 m_LabelSegment[i] = extension;
208 for (; i < GetLength(); i++) {
212 m_LabelSegment[i - 1].
offset += m_LabelSegment[i - 1].
span;
220 CopyLabelSegments(label);
221 m_LabelSegment[GetLength() - 2].
offset += m_LabelSegment[GetLength() - 2].
span;
229 CopyLabelSegments(label);
230 m_LabelSegment[GetLength() - 1].
phase++;
237 CopyLabelSegments(label);
238 m_LabelSegment[GetLength() - 1].
phase++;
244 LabelCreateAfterFork(label, extension);
247 LabelCreateAfterJoin(label);
250 LabelCreateAfterBarrier(label);
253 LabelCreateAfterEneringOrderedSection(label);
256 LabelCreateAfterExitingOrderedSection(label);
265 for (uint8_t i = 0; i < GetLength(); i++) {
266 fprintf(
gTraceFile,
"[%lu,%lu,%lu]", m_LabelSegment[i].offset, m_LabelSegment[i].span, m_LabelSegment[i].phase);
285 if (m_len == m_curLoc) {
301 ThreadData_t(ADDRINT stackBaseAddress, ADDRINT stackEndAddress, ADDRINT stackCurrentFrameBaseAddress)
302 : m_curLable(nullptr),
303 m_stackBaseAddress(stackBaseAddress),
304 m_stackEndAddress(stackEndAddress),
305 m_stackCurrentFrameBaseAddress(stackCurrentFrameBaseAddress) {}
322 return shadowAddress->versionInfo.readStart.load(memory_order_acquire);
327 return shadowAddress->versionInfo.readEnd.load(memory_order_acquire);
332 return shadowAddress->versionInfo.writeStart.load(memory_order_acquire);
337 return shadowAddress->versionInfo.writeEnd.load(memory_order_acquire);
341 return &(shadowAddress->versionInfo.writeEnd);
346 shadowAddress->read1 = info.read1;
347 shadowAddress->read1Context = info.read1Context;
348 shadowAddress->read2 = info.read2;
349 shadowAddress->read2Context = info.read2Context;
350 shadowAddress->write1 = info.write1;
351 shadowAddress->write1Context = info.write1Context;
354 shadowAddress->versionInfo.writeEnd.store(shadowAddress->versionInfo.writeStart, memory_order_release);
359 info->read1 = shadowAddress->read1;
360 info->read1Context = shadowAddress->read1Context;
361 info->read2 = shadowAddress->read2;
362 info->read2Context = shadowAddress->read2Context;
363 info->write1 = shadowAddress->write1;
364 info->write1Context = shadowAddress->write1Context;
369 return info->versionInfo.readStart == info->versionInfo.readEnd;
386 if (trip++ > 100000) {
387 fprintf(stderr,
"\n Loop trip > %d in line %d ... Ver1 = %lu .. ver2 = %lu ... %d", trip, __LINE__, info->versionInfo.readStart, info->versionInfo.readEnd, PIN_ThreadId());
394 fprintf(stderr,
"\n Done ... %d", PIN_ThreadId());
404 uint64_t version = info.versionInfo.writeStart;
405 if (!firstVersionLoc->compare_exchange_strong(version, version + 1))
423 (*oldLabel) = newLabel;
439 assert(newLabel &&
"newLabel can't be NULL");
451 if (oldLabel ==
nullptr)
465 if (oldLabelSegment ==
nullptr)
468 if (newLabelSegment ==
nullptr) {
469 assert(0 &&
"I don't expect this to happen");
479 assert(oldLabelSegment->
span == newLabelSegment->
span);
481 if ((oldLabelSegment->
offset < newLabelSegment->
offset) &&
482 (oldLabelSegment->
offset % newLabelSegment->
span == newLabelSegment->
offset % newLabelSegment->
span)) {
487 if ((oldLabelSegment->
offset < newLabelSegment->
offset) &&
496 assert(newLabel &&
"newLabel can't be NULL");
499 if (oldLabel ==
nullptr)
509 if (oldLabelSegment ==
nullptr || newLabelSegment ==
nullptr)
512 if ((oldLabelSegment->
offset % newLabelSegment->
span < newLabelSegment->
offset % newLabelSegment->
span)) {
522 assert(newLabel &&
"newLabel can't be NULL");
525 if (oldLabel ==
nullptr)
534 if (oldLabelSegment ==
nullptr || newLabelSegment ==
nullptr)
537 if ((oldLabelSegment->
offset % newLabelSegment->
span != newLabelSegment->
offset % newLabelSegment->
span)) {
557 fprintf(
gTraceFile,
"\n *****RACES WITH*****");
565 bool reported =
false;
570 bool updated1 =
false;
571 Label* oldR1Label =
nullptr;
572 Label* oldR2Label =
nullptr;
573 bool updated2 =
false;
577 if (!reported && !
HappensBefore(shadowData.write1, myLabel)) {
579 fprintf(stderr,
"\n W->R race");
587 oldR1Label = shadowData.read1;
594 if ((shadowData.read2 &&
IsLeftOf(shadowData.read2, myLabel)) ||
HappensBefore(shadowData.read2, myLabel)) {
595 oldR2Label = shadowData.read2;
601 if (updated1 || updated2) {
619 bool reported =
false;
625 if (shadowData.write1) {
626 fprintf(stderr,
"\n Comparing labels:");
628 shadowData.write1->PrintLabel();
630 fprintf(stderr,
"\n shadowData.write1 is NULL");
635 if (!reported && !
HappensBefore(shadowData.write1, myLabel)) {
638 fprintf(stderr,
"\n W->W race");
641 if (!reported && !
HappensBefore(shadowData.read1, myLabel)) {
644 fprintf(stderr,
"\n R->W race");
647 if (!reported && !
HappensBefore(shadowData.read2, myLabel)) {
649 fprintf(stderr,
"\n R->W race");
653 Label* oldW1Label = shadowData.write1;
677 static inline VOID
CheckRace(VOID* addr, uint32_t accessLen,
bool accessType, uint32_t opaqueHandle, THREADID threadId) {
681 if (myLabel ==
nullptr)
691 for (uint32_t i = 0; i < accessLen; i++) {
697 for (uint32_t nonOverflowBytes = 0; nonOverflowBytes < accessLen - overflow; nonOverflowBytes++) {
701 status = get<0>(
sm.GetOrCreateShadowBaseAddress((
size_t)(((
char*)addr) + accessLen)));
702 for (
int i = 0; i < overflow; i++) {
716 if (INS_IsStackRead(ins) || INS_IsStackWrite(ins))
720 if (INS_IsControlFlow(ins) || INS_IsRet(ins)) {
731 #define MASTER_BEGIN_FN_NAME "gomp_datarace_master_begin_dynamic_work"
732 #define DYNAMIC_BEGIN_FN_NAME "gomp_datarace_begin_dynamic_work"
733 #define DYNAMIC_END_FN_NAME "gomp_datarace_master_end_dynamic_work"
734 #define ORDERED_ENTER_FN_NAME "gomp_datarace_begin_ordered_section"
735 #define ORDERED_EXIT_FN_NAME "gomp_datarace_end_ordered_section"
736 #define CRITICAL_ENTER_FN_NAME "gomp_datarace_begin_critical"
737 #define CRITICAL_EXIT_FN_NAME "gomp_datarace_end_critical"
759 if (myLabel ==
nullptr) {
760 myLabel =
new Label();
775 extension.
span = span;
829 if (RTN_Valid(rtn)) {
833 PROTO proto_master = PROTO_Allocate(PIN_PARG(
void), CALLINGSTD_DEFAULT,
841 IARG_PROTOTYPE, proto_master,
842 IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
843 IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
844 IARG_THREAD_ID, IARG_END);
846 PROTO_Free(proto_master);
851 if (RTN_Valid(rtn)) {
852 PROTO proto_worker = PROTO_Allocate(PIN_PARG(
void), CALLINGSTD_DEFAULT,
856 IARG_PROTOTYPE, proto_worker,
857 IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
858 IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
859 IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
860 IARG_THREAD_ID, IARG_END);
861 PROTO_Free(proto_worker);
866 if (RTN_Valid(rtn)) {
867 PROTO proto_end = PROTO_Allocate(PIN_PARG(
void), CALLINGSTD_DEFAULT,
870 IARG_PROTOTYPE, proto_end,
871 IARG_THREAD_ID, IARG_END);
872 PROTO_Free(proto_end);
877 if (RTN_Valid(rtn)) {
878 PROTO ordered_enter = PROTO_Allocate(PIN_PARG(
void), CALLINGSTD_DEFAULT,
881 IARG_PROTOTYPE, ordered_enter,
882 IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
883 IARG_THREAD_ID, IARG_END);
884 PROTO_Free(ordered_enter);
889 if (RTN_Valid(rtn)) {
890 PROTO ordered_exit = PROTO_Allocate(PIN_PARG(
void), CALLINGSTD_DEFAULT,
893 IARG_PROTOTYPE, ordered_exit,
894 IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
895 IARG_THREAD_ID, IARG_END);
896 PROTO_Free(ordered_exit);
901 if (RTN_Valid(rtn)) {
902 PROTO critical_enter = PROTO_Allocate(PIN_PARG(
void), CALLINGSTD_DEFAULT,
905 IARG_PROTOTYPE, critical_enter,
906 IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
907 IARG_THREAD_ID, IARG_END);
908 PROTO_Free(critical_enter);
912 if (RTN_Valid(rtn)) {
913 PROTO critical_exit = PROTO_Allocate(PIN_PARG(
void), CALLINGSTD_DEFAULT,
916 IARG_PROTOTYPE, critical_exit,
917 IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
918 IARG_THREAD_ID, IARG_END);
919 PROTO_Free(critical_exit);
930 if (INS_IsAtomicUpdate(ins)) {
931 INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
934 IARG_THREAD_ID, IARG_END);
938 UINT32 memOperands = INS_MemoryOperandCount(ins);
941 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
942 if (INS_MemoryOperandIsWritten(ins, memOp)) {
943 INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
945 IARG_MEMORYOP_EA, memOp, IARG_MEMORYWRITE_SIZE, IARG_BOOL,
WRITE_ACCESS , IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END);
946 }
else if (INS_MemoryOperandIsRead(ins, memOp)) {
947 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
CheckRace, IARG_MEMORYOP_EA, memOp, IARG_MEMORYREAD_SIZE, IARG_BOOL,
READ_ACCESS , IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END);
950 if (INS_IsAtomicUpdate(ins)) {
951 INS_InsertPredicatedCall(ins, IPOINT_AFTER,
954 IARG_THREAD_ID, IARG_END);
960 PIN_ERROR(
"PinTool for datarace detection.\n" + KNOB_BASE::StringKnobSummary() +
"\n");
966 ADDRINT stackBaseAddr = PIN_GetContextReg(ctxt, REG_STACK_PTR);
969 pthread_attr_init(&attr);
970 pthread_attr_getstacksize(&attr, &stacksize);
974 PIN_SetThreadData(
tls_key, tdata, threadid);
983 fprintf(stderr,
"\n Skipping image %s",
skipImages[i].c_str());
993 char* envPath = getenv(
"OUTPUT_FILE");
996 snprintf(name,
sizeof(name),
"%s", envPath);
998 gethostname(name + strlen(name),
MAX_FILE_PATH - strlen(name));
999 pid_t pid = getpid();
1000 sprintf(name + strlen(name),
"%d", pid);
1001 cerr <<
"\n Creating dead info file at:" << name <<
"\n";
1006 for (
int i = 0; i < argc; i++) {
1016 tls_key = PIN_CreateThreadDataKey(
nullptr);
1028 if (PIN_Init(argc, argv))
1037 IMG_AddInstrumentFunction(
Overrides,
nullptr);
1038 fprintf(stderr,
"\n TODO TODO ... eliminate stack local check and make it robust");
#define INTERESTING_INS_MEMORY_ACCESS
LabelSegment * NextSegment()
LabelIterator(const Label &label)
void LabelCreateAfterBarrier(const Label &label)
Label(LabelCreationType type, const Label &label, const LabelSegment &extension=defaultExtension)
LabelSegment * m_LabelSegment
void LabelCreateAfterExitingOrderedSection(const Label &label)
LabelSegment * GetSegmentAtIndex(int index) const
void LabelCreateAfterEneringOrderedSection(const Label &label)
void SetLength(uint64_t len)
volatile atomic< uint64_t > m_refCount
void LabelCreateAfterFork(const Label &label, const LabelSegment &extension)
void CopyLabelSegments(const Label &label)
void LabelCreateAfterJoin(const Label &label)
uint8_t GetLength() const
ThreadData_t(ADDRINT stackBaseAddress, ADDRINT stackEndAddress, ADDRINT stackCurrentFrameBaseAddress)
ADDRINT m_stackEndAddress
ADDRINT m_stackCurrentFrameBaseAddress
void SetLabel(Label *label)
ADDRINT m_stackBaseAddress
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
hpcrun_metricFlags_t flags
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
volatile atomic< uint64_t > writeEnd
int main(int argc, char *argv[])
ConcurrentShadowMemory< DataraceInfo_t > sm
static void UpdateLabel(Label **oldLabel, Label *newLabel)
static bool TryWriteShadowMemory(DataraceInfo_t *shadowAddress, const DataraceInfo_t &info)
static ADDRINT gSkipImageAddressRanges[MAX_SKIP_IMAGES][2]
static volatile atomic< uint64_t > * GetWriteStartAddressForLoc(DataraceInfo_t *const shadowAddress)
static const LabelSegment defaultExtension
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
static VOID CheckRace(VOID *addr, uint32_t accessLen, bool accessType, uint32_t opaqueHandle, THREADID threadId)
@ CREATE_AFTER_EXITING_ORDERED_SECTION
@ CREATE_AFTER_ENTERING_ORDERED_SECTION
void(*)(void *) FP_CRITICAL_ENTER
static uint64_t GetReadStartForLoc(const DataraceInfo_t *const shadowAddress)
static bool MaximizesExitRank(const Label *const newLabel, const Label *const oldLabel)
void(*)(uint64_t) FP_ORDERED_EXIT
static bool IsConsistentSpapshot(const DataraceInfo_t *const info)
void new_DYNAMIC_BEGIN_FN_NAME(uint64_t region_id, long span, long iter, THREADID threadid)
void new_DYNAMIC_END_FN_NAME(THREADID threadId)
void new_CRITICAL_ENTER_FN_NAME(void *name, THREADID threadid)
void ReadShadowMemory(DataraceInfo_t *shadowAddress, DataraceInfo_t *info)
#define OMP_RUMTIMR_LIB_NAME
static void ReadShadowData(DataraceInfo_t *info, DataraceInfo_t *shadowAddress)
static Label * GetMyLabel(THREADID threadId)
static bool IsLeftOf(const Label *const newLabel, const Label *const oldLabel)
void new_MASTER_BEGIN_FN_NAME(uint64_t region_id, long span, THREADID threadid)
void new_CRITICAL_EXIT_FN_NAME(void *name, THREADID threadid)
static bool HappensBefore(const Label *const oldLabel, const Label *const newLabel)
static const char * HW_LOCK
ContextHandle_t write1Context
static string skipImages[]
void(*)(uint64_t) FP_ORDERED_ENTER
#define CRITICAL_EXIT_FN_NAME
void InitDataRaceSpy(int argc, char *argv[])
void new_ORDERED_EXIT_FN_NAME(uint64_t region_id, THREADID threadId)
static uint64_t GetWriteEndForLoc(const DataraceInfo_t *const shadowAddress)
#define MASTER_BEGIN_FN_NAME
static void CheckRead(DataraceInfo_t *shadowAddress, Label *myLabel, uint32_t opaqueHandle, THREADID threadId)
static void ExecuteOffsetSpanPhaseProtocol(DataraceInfo_t *status, Label *myLabel, bool accessType, uint32_t opaqueHandle, THREADID threadId)
static bool IsIgnorableIns(INS ins)
static int gNumCurSkipImages
ContextHandle_t read2Context
static VOID InstrumentInsCallback(INS ins, VOID *v, const uint32_t opaqueHandle)
static uint64_t GetWriteStartForLoc(const DataraceInfo_t *const shadowAddress)
#define ORDERED_EXIT_FN_NAME
#define ORDERED_ENTER_FN_NAME
void(*)(uint64_t, long, long) FP_WORKER
struct DataraceInfo_t { VersionInfo_t versionInfo DataraceInfo_t
static void SetMyLabel(THREADID threadId, Label *label)
static uint64_t GetReadEndForLoc(const DataraceInfo_t *const shadowAddress)
VOID Overrides(IMG img, VOID *v)
ThreadData_t * GetTLS(THREADID threadid)
static VOID InstrumentImageLoad(IMG img, VOID *v)
static void CommitChangesToShadowMemory(Label *oldLabel, Label *newLabel)
struct VersionInfo_t { union { volatile atomic< uint64_t > readStart VersionInfo_t
static void CheckWrite(DataraceInfo_t *shadowAddress, Label *myLabel, uint32_t opaqueHandle, THREADID threadId)
static Label ** gRegionIdToMasterLabelMap
#define DYNAMIC_BEGIN_FN_NAME
static void UpdateContext(ContextHandle_t *oldCtxt, ContextHandle_t ctxt)
ContextHandle_t read1Context
void(*)(void *) FP_CRITICAL_EXIT
#define CRITICAL_ENTER_FN_NAME
static void DumpRaceInfo(ContextHandle_t oldCtxt, Label *oldLbl, ContextHandle_t newCtxt, Label *newLbl)
volatile atomic< uint64_t > writeStart
#define ENTER_RANK(phase)
void new_ORDERED_ENTER_FN_NAME(uint64_t region_id, THREADID threadId)
#define DYNAMIC_END_FN_NAME
static void UpdateShadowDataAtShadowAddress(DataraceInfo_t *shadowAddress, const DataraceInfo_t &info)
void(*)(uint64_t, long) FP_MASTER
struct ExtendedDataraceInfo_t { DataraceInfo_t *shadowAddress ExtendedDataraceInfo_t
volatile atomic< uint64_t > readEnd
#define PAGE_OFFSET(addr)