X-Git-Url: http://plrg.eecs.uci.edu/git/?p=c11tester.git;a=blobdiff_plain;f=datarace.cc;h=dd88c2fe98f095d678e55c3dbf1162d98298b9d7;hp=d15ca50cf9d97de15a06c80f881735f1d297566f;hb=bb18310b8c8c97d8e396940bdfee740bd6d3e30a;hpb=cb6e6a9a783fa8b767d57a14267d1b5ace9a58fd diff --git a/datarace.cc b/datarace.cc index d15ca50c..dd88c2fe 100644 --- a/datarace.cc +++ b/datarace.cc @@ -60,6 +60,48 @@ static uint64_t * lookupAddressEntry(const void *address) return &basetable->array[((uintptr_t)address) & MASK16BIT]; } + +bool hasNonAtomicStore(const void *address) { + uint64_t * shadow = lookupAddressEntry(address); + uint64_t shadowval = *shadow; + if (ISSHORTRECORD(shadowval)) { + //Do we have a non atomic write with a non-zero clock + return ((WRITEVECTOR(shadowval) != 0) && !(ATOMICMASK & shadowval)); + } else { + if (shadowval == 0) + return false; + struct RaceRecord *record = (struct RaceRecord *)shadowval; + return !record->isAtomic && record->writeClock != 0; + } +} + +void setAtomicStoreFlag(const void *address) { + uint64_t * shadow = lookupAddressEntry(address); + uint64_t shadowval = *shadow; + if (ISSHORTRECORD(shadowval)) { + *shadow = shadowval | ATOMICMASK; + } else { + if (shadowval == 0) + return; + struct RaceRecord *record = (struct RaceRecord *)shadowval; + record->isAtomic = 1; + } +} + +void getStoreThreadAndClock(const void *address, thread_id_t * thread, modelclock_t * clock) { + uint64_t * shadow = lookupAddressEntry(address); + uint64_t shadowval = *shadow; + if (ISSHORTRECORD(shadowval)) { + //Do we have a non atomic write with a non-zero clock + *thread = WRTHREADID(shadowval); + *clock = WRITEVECTOR(shadowval); + } else { + struct RaceRecord *record = (struct RaceRecord *)shadowval; + *thread = record->writeThread; + *clock = record->writeClock; + } +} + /** * Compares a current clock-vector/thread-ID pair with a clock/thread-ID pair * to check the potential for a data race. @@ -93,14 +135,15 @@ static void expandRecord(uint64_t *shadow) record->writeClock = writeClock; if (readClock != 0) { - record->capacity = INITCAPACITY; - record->thread = (thread_id_t *)snapshot_malloc(sizeof(thread_id_t) * record->capacity); - record->readClock = (modelclock_t *)snapshot_malloc(sizeof(modelclock_t) * record->capacity); + record->thread = (thread_id_t *)snapshot_malloc(sizeof(thread_id_t) * INITCAPACITY); + record->readClock = (modelclock_t *)snapshot_malloc(sizeof(modelclock_t) * INITCAPACITY); record->numReads = 1; ASSERT(readThread >= 0); record->thread[0] = readThread; record->readClock[0] = readClock; } + if (shadowval & ATOMICMASK) + record->isAtomic = 1; *shadow = (uint64_t) record; } @@ -149,11 +192,11 @@ static struct DataRace * reportDataRace(thread_id_t oldthread, modelclock_t oldc */ void assert_race(struct DataRace *race) { - model_print("At location: \n"); + model_print("Race detected at location: \n"); backtrace_symbols_fd(race->backtrace, race->numframes, model_out); - model_print("Data race detected @ address %p:\n" + model_print("\nData race detected @ address %p:\n" " Access 1: %5s in thread %2d @ clock %3u\n" - " Access 2: %5s in thread %2d @ clock %3u", + " Access 2: %5s in thread %2d @ clock %3u\n\n", race->address, race->isoldwrite ? "write" : "read", id_to_int(race->oldthread), @@ -201,6 +244,7 @@ struct DataRace * fullRaceCheckWrite(thread_id_t thread, void *location, uint64_ Exit: record->numReads = 0; record->writeThread = thread; + record->isAtomic = 0; modelclock_t ourClock = currClock->getClock(thread); record->writeClock = ourClock; return race; @@ -212,6 +256,9 @@ void raceCheckWrite(thread_id_t thread, void *location) uint64_t *shadow = lookupAddressEntry(location); uint64_t shadowval = *shadow; ClockVector *currClock = get_execution()->get_cv(thread); + if (currClock == NULL) + return; + struct DataRace * race = NULL; /* Do full record */ if (shadowval != 0 && !ISSHORTRECORD(shadowval)) { @@ -270,6 +317,43 @@ Exit: else model_free(race); } } + +/** This function does race detection for a write on an expanded record. */ +void fullRecordWrite(thread_id_t thread, void *location, uint64_t *shadow, ClockVector *currClock) { + struct RaceRecord *record = (struct RaceRecord *)(*shadow); + record->numReads = 0; + record->writeThread = thread; + modelclock_t ourClock = currClock->getClock(thread); + record->writeClock = ourClock; + record->isAtomic = 1; +} + +/** This function just updates metadata on atomic write. */ +void recordWrite(thread_id_t thread, void *location) { + uint64_t *shadow = lookupAddressEntry(location); + uint64_t shadowval = *shadow; + ClockVector *currClock = get_execution()->get_cv(thread); + /* Do full record */ + if (shadowval != 0 && !ISSHORTRECORD(shadowval)) { + fullRecordWrite(thread, location, shadow, currClock); + return; + } + + int threadid = id_to_int(thread); + modelclock_t ourClock = currClock->getClock(thread); + + /* Thread ID is too large or clock is too large. */ + if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) { + expandRecord(shadow); + fullRecordWrite(thread, location, shadow, currClock); + return; + } + + *shadow = ENCODEOP(0, 0, threadid, ourClock) | ATOMICMASK; +} + + + /** This function does race detection on a read for an expanded record. */ struct DataRace * fullRaceCheckRead(thread_id_t thread, const void *location, uint64_t *shadow, ClockVector *currClock) { @@ -310,23 +394,21 @@ struct DataRace * fullRaceCheckRead(thread_id_t thread, const void *location, ui } } - if (copytoindex >= record->capacity) { - if (record->capacity == 0) { + if (__builtin_popcount(copytoindex) <= 1) { + if (copytoindex == 0) { int newCapacity = INITCAPACITY; record->thread = (thread_id_t *)snapshot_malloc(sizeof(thread_id_t) * newCapacity); record->readClock = (modelclock_t *)snapshot_malloc(sizeof(modelclock_t) * newCapacity); - record->capacity = newCapacity; - } else { - int newCapacity = record->capacity * 2; + } else if (copytoindex>=INITCAPACITY) { + int newCapacity = copytoindex * 2; thread_id_t *newthread = (thread_id_t *)snapshot_malloc(sizeof(thread_id_t) * newCapacity); modelclock_t *newreadClock = (modelclock_t *)snapshot_malloc(sizeof(modelclock_t) * newCapacity); - std::memcpy(newthread, record->thread, record->capacity * sizeof(thread_id_t)); - std::memcpy(newreadClock, record->readClock, record->capacity * sizeof(modelclock_t)); + std::memcpy(newthread, record->thread, copytoindex * sizeof(thread_id_t)); + std::memcpy(newreadClock, record->readClock, copytoindex * sizeof(modelclock_t)); snapshot_free(record->readClock); snapshot_free(record->thread); record->readClock = newreadClock; record->thread = newthread; - record->capacity = newCapacity; } } @@ -345,6 +427,9 @@ void raceCheckRead(thread_id_t thread, const void *location) uint64_t *shadow = lookupAddressEntry(location); uint64_t shadowval = *shadow; ClockVector *currClock = get_execution()->get_cv(thread); + if (currClock == NULL) + return; + struct DataRace * race = NULL; /* Do full record */ @@ -388,7 +473,7 @@ ShadowExit: } } - *shadow = ENCODEOP(threadid, ourClock, id_to_int(writeThread), writeClock); + *shadow = ENCODEOP(threadid, ourClock, id_to_int(writeThread), writeClock) | (shadowval & ATOMICMASK); } Exit: if (race) {