3 #include "threads-model.h"
7 #include "clockvector.h"
10 #include "execution.h"
11 #include "stl-model.h"
14 static struct ShadowTable *root;
15 static void *memory_base;
16 static void *memory_top;
17 static RaceSet * raceset;
19 static unsigned int store8_count = 0;
20 static unsigned int store16_count = 0;
21 static unsigned int store32_count = 0;
22 static unsigned int store64_count = 0;
24 static unsigned int load8_count = 0;
25 static unsigned int load16_count = 0;
26 static unsigned int load32_count = 0;
27 static unsigned int load64_count = 0;
29 static const ModelExecution * get_execution()
31 return model->get_execution();
34 /** This function initialized the data race detector. */
35 void initRaceDetector()
37 root = (struct ShadowTable *)snapshot_calloc(sizeof(struct ShadowTable), 1);
38 memory_base = snapshot_calloc(sizeof(struct ShadowBaseTable) * SHADOWBASETABLES, 1);
39 memory_top = ((char *)memory_base) + sizeof(struct ShadowBaseTable) * SHADOWBASETABLES;
40 raceset = new RaceSet();
43 void * table_calloc(size_t size)
45 if ((((char *)memory_base) + size) > memory_top) {
46 return snapshot_calloc(size, 1);
48 void *tmp = memory_base;
49 memory_base = ((char *)memory_base) + size;
54 /** This function looks up the entry in the shadow table corresponding to a
56 static uint64_t * lookupAddressEntry(const void *address)
58 struct ShadowTable *currtable = root;
60 currtable = (struct ShadowTable *) currtable->array[(((uintptr_t)address) >> 32) & MASK16BIT];
61 if (currtable == NULL) {
62 currtable = (struct ShadowTable *)(root->array[(((uintptr_t)address) >> 32) & MASK16BIT] = table_calloc(sizeof(struct ShadowTable)));
66 struct ShadowBaseTable *basetable = (struct ShadowBaseTable *)currtable->array[(((uintptr_t)address) >> 16) & MASK16BIT];
67 if (basetable == NULL) {
68 basetable = (struct ShadowBaseTable *)(currtable->array[(((uintptr_t)address) >> 16) & MASK16BIT] = table_calloc(sizeof(struct ShadowBaseTable)));
70 return &basetable->array[((uintptr_t)address) & MASK16BIT];
74 bool hasNonAtomicStore(const void *address) {
75 uint64_t * shadow = lookupAddressEntry(address);
76 uint64_t shadowval = *shadow;
77 if (ISSHORTRECORD(shadowval)) {
78 //Do we have a non atomic write with a non-zero clock
79 return !(ATOMICMASK & shadowval);
83 struct RaceRecord *record = (struct RaceRecord *)shadowval;
84 return !record->isAtomic;
88 void setAtomicStoreFlag(const void *address) {
89 uint64_t * shadow = lookupAddressEntry(address);
90 uint64_t shadowval = *shadow;
91 if (ISSHORTRECORD(shadowval)) {
92 *shadow = shadowval | ATOMICMASK;
95 *shadow = ATOMICMASK | ENCODEOP(0, 0, 0, 0);
98 struct RaceRecord *record = (struct RaceRecord *)shadowval;
103 void getStoreThreadAndClock(const void *address, thread_id_t * thread, modelclock_t * clock) {
104 uint64_t * shadow = lookupAddressEntry(address);
105 uint64_t shadowval = *shadow;
106 if (ISSHORTRECORD(shadowval) || shadowval == 0) {
107 //Do we have a non atomic write with a non-zero clock
108 *thread = WRTHREADID(shadowval);
109 *clock = WRITEVECTOR(shadowval);
111 struct RaceRecord *record = (struct RaceRecord *)shadowval;
112 *thread = record->writeThread;
113 *clock = record->writeClock;
118 * Compares a current clock-vector/thread-ID pair with a clock/thread-ID pair
119 * to check the potential for a data race.
120 * @param clock1 The current clock vector
121 * @param tid1 The current thread; paired with clock1
122 * @param clock2 The clock value for the potentially-racing action
123 * @param tid2 The thread ID for the potentially-racing action
124 * @return true if the current clock allows a race with the event at clock2/tid2
126 static bool clock_may_race(ClockVector *clock1, thread_id_t tid1,
127 modelclock_t clock2, thread_id_t tid2)
129 return tid1 != tid2 && clock2 != 0 && clock1->getClock(tid2) <= clock2;
133 * Expands a record from the compact form to the full form. This is
134 * necessary for multiple readers or for very large thread ids or time
136 static void expandRecord(uint64_t *shadow)
138 uint64_t shadowval = *shadow;
140 modelclock_t readClock = READVECTOR(shadowval);
141 thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
142 modelclock_t writeClock = WRITEVECTOR(shadowval);
143 thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
145 struct RaceRecord *record = (struct RaceRecord *)snapshot_calloc(1, sizeof(struct RaceRecord));
146 record->writeThread = writeThread;
147 record->writeClock = writeClock;
149 if (readClock != 0) {
150 record->thread = (thread_id_t *)snapshot_malloc(sizeof(thread_id_t) * INITCAPACITY);
151 record->readClock = (modelclock_t *)snapshot_malloc(sizeof(modelclock_t) * INITCAPACITY);
152 record->numReads = 1;
153 ASSERT(readThread >= 0);
154 record->thread[0] = readThread;
155 record->readClock[0] = readClock;
157 if (shadowval & ATOMICMASK)
158 record->isAtomic = 1;
159 *shadow = (uint64_t) record;
162 #define FIRST_STACK_FRAME 2
164 unsigned int race_hash(struct DataRace *race) {
165 unsigned int hash = 0;
166 for(int i=FIRST_STACK_FRAME;i < race->numframes;i++) {
167 hash ^= ((uintptr_t)race->backtrace[i]);
168 hash = (hash >> 3) | (hash << 29);
173 bool race_equals(struct DataRace *r1, struct DataRace *r2) {
174 if (r1->numframes != r2->numframes)
176 for(int i=FIRST_STACK_FRAME;i < r1->numframes;i++) {
177 if (r1->backtrace[i] != r2->backtrace[i])
183 /** This function is called when we detect a data race.*/
184 static struct DataRace * reportDataRace(thread_id_t oldthread, modelclock_t oldclock, bool isoldwrite, ModelAction *newaction, bool isnewwrite, const void *address)
186 #ifdef REPORT_DATA_RACES
187 struct DataRace *race = (struct DataRace *)model_malloc(sizeof(struct DataRace));
188 race->oldthread = oldthread;
189 race->oldclock = oldclock;
190 race->isoldwrite = isoldwrite;
191 race->newaction = newaction;
192 race->isnewwrite = isnewwrite;
193 race->address = address;
201 * @brief Assert a data race
203 * Asserts a data race which is currently realized, causing the execution to
204 * end and stashing a message in the model-checker's bug list
206 * @param race The race to report
208 void assert_race(struct DataRace *race)
210 model_print("Race detected at location: \n");
211 backtrace_symbols_fd(race->backtrace, race->numframes, model_out);
212 model_print("\nData race detected @ address %p:\n"
213 " Access 1: %5s in thread %2d @ clock %3u\n"
214 " Access 2: %5s in thread %2d @ clock %3u\n\n",
216 race->isoldwrite ? "write" : "read",
217 id_to_int(race->oldthread),
219 race->isnewwrite ? "write" : "read",
220 id_to_int(race->newaction->get_tid()),
221 race->newaction->get_seq_number()
225 /** This function does race detection for a write on an expanded record. */
226 struct DataRace * fullRaceCheckWrite(thread_id_t thread, const void *location, uint64_t *shadow, ClockVector *currClock)
228 struct RaceRecord *record = (struct RaceRecord *)(*shadow);
229 struct DataRace * race = NULL;
231 /* Check for datarace against last read. */
233 for (int i = 0;i < record->numReads;i++) {
234 modelclock_t readClock = record->readClock[i];
235 thread_id_t readThread = record->thread[i];
237 /* Note that readClock can't actuall be zero here, so it could be
240 if (clock_may_race(currClock, thread, readClock, readThread)) {
241 /* We have a datarace */
242 race = reportDataRace(readThread, readClock, false, get_execution()->get_parent_action(thread), true, location);
247 /* Check for datarace against last write. */
249 modelclock_t writeClock = record->writeClock;
250 thread_id_t writeThread = record->writeThread;
252 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
253 /* We have a datarace */
254 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), true, location);
259 record->numReads = 0;
260 record->writeThread = thread;
261 record->isAtomic = 0;
262 modelclock_t ourClock = currClock->getClock(thread);
263 record->writeClock = ourClock;
267 /** This function does race detection on a write. */
268 void raceCheckWrite(thread_id_t thread, void *location)
270 uint64_t *shadow = lookupAddressEntry(location);
271 uint64_t shadowval = *shadow;
272 ClockVector *currClock = get_execution()->get_cv(thread);
273 if (currClock == NULL)
276 struct DataRace * race = NULL;
278 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
279 race = fullRaceCheckWrite(thread, location, shadow, currClock);
284 int threadid = id_to_int(thread);
285 modelclock_t ourClock = currClock->getClock(thread);
287 /* Thread ID is too large or clock is too large. */
288 if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) {
289 expandRecord(shadow);
290 race = fullRaceCheckWrite(thread, location, shadow, currClock);
295 /* Check for datarace against last read. */
296 modelclock_t readClock = READVECTOR(shadowval);
297 thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
299 if (clock_may_race(currClock, thread, readClock, readThread)) {
300 /* We have a datarace */
301 race = reportDataRace(readThread, readClock, false, get_execution()->get_parent_action(thread), true, location);
307 /* Check for datarace against last write. */
308 modelclock_t writeClock = WRITEVECTOR(shadowval);
309 thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
311 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
312 /* We have a datarace */
313 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), true, location);
319 *shadow = ENCODEOP(0, 0, threadid, ourClock);
324 #ifdef REPORT_DATA_RACES
325 race->numframes=backtrace(race->backtrace, sizeof(race->backtrace)/sizeof(void*));
326 if (raceset->add(race))
328 else model_free(race);
335 /** This function does race detection for a write on an expanded record. */
336 struct DataRace * atomfullRaceCheckWrite(thread_id_t thread, const void *location, uint64_t *shadow, ClockVector *currClock)
338 struct RaceRecord *record = (struct RaceRecord *)(*shadow);
339 struct DataRace * race = NULL;
341 if (record->isAtomic)
344 /* Check for datarace against last read. */
346 for (int i = 0;i < record->numReads;i++) {
347 modelclock_t readClock = record->readClock[i];
348 thread_id_t readThread = record->thread[i];
350 /* Note that readClock can't actuall be zero here, so it could be
353 if (clock_may_race(currClock, thread, readClock, readThread)) {
354 /* We have a datarace */
355 race = reportDataRace(readThread, readClock, false, get_execution()->get_parent_action(thread), true, location);
360 /* Check for datarace against last write. */
363 modelclock_t writeClock = record->writeClock;
364 thread_id_t writeThread = record->writeThread;
366 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
367 /* We have a datarace */
368 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), true, location);
373 record->numReads = 0;
374 record->writeThread = thread;
375 record->isAtomic = 1;
376 modelclock_t ourClock = currClock->getClock(thread);
377 record->writeClock = ourClock;
381 /** This function does race detection on a write. */
382 void atomraceCheckWrite(thread_id_t thread, void *location)
384 uint64_t *shadow = lookupAddressEntry(location);
385 uint64_t shadowval = *shadow;
386 ClockVector *currClock = get_execution()->get_cv(thread);
387 if (currClock == NULL)
390 struct DataRace * race = NULL;
392 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
393 race = atomfullRaceCheckWrite(thread, location, shadow, currClock);
398 int threadid = id_to_int(thread);
399 modelclock_t ourClock = currClock->getClock(thread);
401 /* Thread ID is too large or clock is too large. */
402 if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) {
403 expandRecord(shadow);
404 race = atomfullRaceCheckWrite(thread, location, shadow, currClock);
408 /* Can't race with atomic */
409 if (shadowval & ATOMICMASK)
413 /* Check for datarace against last read. */
414 modelclock_t readClock = READVECTOR(shadowval);
415 thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
417 if (clock_may_race(currClock, thread, readClock, readThread)) {
418 /* We have a datarace */
419 race = reportDataRace(readThread, readClock, false, get_execution()->get_parent_action(thread), true, location);
425 /* Check for datarace against last write. */
426 modelclock_t writeClock = WRITEVECTOR(shadowval);
427 thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
429 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
430 /* We have a datarace */
431 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), true, location);
437 *shadow = ENCODEOP(0, 0, threadid, ourClock) | ATOMICMASK;
442 #ifdef REPORT_DATA_RACES
443 race->numframes=backtrace(race->backtrace, sizeof(race->backtrace)/sizeof(void*));
444 if (raceset->add(race))
446 else model_free(race);
453 /** This function does race detection for a write on an expanded record. */
454 void fullRecordWrite(thread_id_t thread, void *location, uint64_t *shadow, ClockVector *currClock) {
455 struct RaceRecord *record = (struct RaceRecord *)(*shadow);
456 record->numReads = 0;
457 record->writeThread = thread;
458 modelclock_t ourClock = currClock->getClock(thread);
459 record->writeClock = ourClock;
460 record->isAtomic = 1;
463 /** This function does race detection for a write on an expanded record. */
464 void fullRecordWriteNonAtomic(thread_id_t thread, void *location, uint64_t *shadow, ClockVector *currClock) {
465 struct RaceRecord *record = (struct RaceRecord *)(*shadow);
466 record->numReads = 0;
467 record->writeThread = thread;
468 modelclock_t ourClock = currClock->getClock(thread);
469 record->writeClock = ourClock;
470 record->isAtomic = 0;
473 /** This function just updates metadata on atomic write. */
474 void recordWrite(thread_id_t thread, void *location) {
475 uint64_t *shadow = lookupAddressEntry(location);
476 uint64_t shadowval = *shadow;
477 ClockVector *currClock = get_execution()->get_cv(thread);
479 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
480 fullRecordWrite(thread, location, shadow, currClock);
484 int threadid = id_to_int(thread);
485 modelclock_t ourClock = currClock->getClock(thread);
487 /* Thread ID is too large or clock is too large. */
488 if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) {
489 expandRecord(shadow);
490 fullRecordWrite(thread, location, shadow, currClock);
494 *shadow = ENCODEOP(0, 0, threadid, ourClock) | ATOMICMASK;
497 /** This function just updates metadata on atomic write. */
498 void recordCalloc(void *location, size_t size) {
499 thread_id_t thread = thread_current()->get_id();
500 for(;size != 0;size--) {
501 uint64_t *shadow = lookupAddressEntry(location);
502 uint64_t shadowval = *shadow;
503 ClockVector *currClock = get_execution()->get_cv(thread);
505 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
506 fullRecordWriteNonAtomic(thread, location, shadow, currClock);
510 int threadid = id_to_int(thread);
511 modelclock_t ourClock = currClock->getClock(thread);
513 /* Thread ID is too large or clock is too large. */
514 if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) {
515 expandRecord(shadow);
516 fullRecordWriteNonAtomic(thread, location, shadow, currClock);
520 *shadow = ENCODEOP(0, 0, threadid, ourClock);
521 location = (void *)(((char *) location) + 1);
525 /** This function does race detection on a read for an expanded record. */
526 struct DataRace * fullRaceCheckRead(thread_id_t thread, const void *location, uint64_t *shadow, ClockVector *currClock)
528 struct RaceRecord *record = (struct RaceRecord *) (*shadow);
529 struct DataRace * race = NULL;
530 /* Check for datarace against last write. */
532 modelclock_t writeClock = record->writeClock;
533 thread_id_t writeThread = record->writeThread;
535 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
536 /* We have a datarace */
537 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), false, location);
540 /* Shorten vector when possible */
544 for (int i = 0;i < record->numReads;i++) {
545 modelclock_t readClock = record->readClock[i];
546 thread_id_t readThread = record->thread[i];
548 /* Note that is not really a datarace check as reads cannot
549 actually race. It is just determining that this read subsumes
550 another in the sense that either this read races or neither
551 read races. Note that readClock can't actually be zero, so it
552 could be optimized. */
554 if (clock_may_race(currClock, thread, readClock, readThread)) {
555 /* Still need this read in vector */
556 if (copytoindex != i) {
557 ASSERT(record->thread[i] >= 0);
558 record->readClock[copytoindex] = record->readClock[i];
559 record->thread[copytoindex] = record->thread[i];
565 if (__builtin_popcount(copytoindex) <= 1) {
566 if (copytoindex == 0) {
567 int newCapacity = INITCAPACITY;
568 record->thread = (thread_id_t *)snapshot_malloc(sizeof(thread_id_t) * newCapacity);
569 record->readClock = (modelclock_t *)snapshot_malloc(sizeof(modelclock_t) * newCapacity);
570 } else if (copytoindex>=INITCAPACITY) {
571 int newCapacity = copytoindex * 2;
572 thread_id_t *newthread = (thread_id_t *)snapshot_malloc(sizeof(thread_id_t) * newCapacity);
573 modelclock_t *newreadClock = (modelclock_t *)snapshot_malloc(sizeof(modelclock_t) * newCapacity);
574 std::memcpy(newthread, record->thread, copytoindex * sizeof(thread_id_t));
575 std::memcpy(newreadClock, record->readClock, copytoindex * sizeof(modelclock_t));
576 snapshot_free(record->readClock);
577 snapshot_free(record->thread);
578 record->readClock = newreadClock;
579 record->thread = newthread;
583 modelclock_t ourClock = currClock->getClock(thread);
586 record->thread[copytoindex] = thread;
587 record->readClock[copytoindex] = ourClock;
588 record->numReads = copytoindex + 1;
592 /** This function does race detection on a read. */
593 void raceCheckRead(thread_id_t thread, const void *location)
595 uint64_t *shadow = lookupAddressEntry(location);
596 uint64_t shadowval = *shadow;
597 ClockVector *currClock = get_execution()->get_cv(thread);
598 if (currClock == NULL)
601 struct DataRace * race = NULL;
604 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
605 race = fullRaceCheckRead(thread, location, shadow, currClock);
610 int threadid = id_to_int(thread);
611 modelclock_t ourClock = currClock->getClock(thread);
613 /* Thread ID is too large or clock is too large. */
614 if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) {
615 expandRecord(shadow);
616 race = fullRaceCheckRead(thread, location, shadow, currClock);
620 /* Check for datarace against last write. */
622 modelclock_t writeClock = WRITEVECTOR(shadowval);
623 thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
625 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
626 /* We have a datarace */
627 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), false, location);
633 modelclock_t readClock = READVECTOR(shadowval);
634 thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
636 if (clock_may_race(currClock, thread, readClock, readThread)) {
637 /* We don't subsume this read... Have to expand record. */
638 expandRecord(shadow);
639 fullRaceCheckRead(thread, location, shadow, currClock);
644 *shadow = ENCODEOP(threadid, ourClock, id_to_int(writeThread), writeClock) | (shadowval & ATOMICMASK);
648 #ifdef REPORT_DATA_RACES
649 race->numframes=backtrace(race->backtrace, sizeof(race->backtrace)/sizeof(void*));
650 if (raceset->add(race))
652 else model_free(race);
660 /** This function does race detection on a read for an expanded record. */
661 struct DataRace * atomfullRaceCheckRead(thread_id_t thread, const void *location, uint64_t *shadow, ClockVector *currClock)
663 struct RaceRecord *record = (struct RaceRecord *) (*shadow);
664 struct DataRace * race = NULL;
665 /* Check for datarace against last write. */
666 if (record->isAtomic)
669 modelclock_t writeClock = record->writeClock;
670 thread_id_t writeThread = record->writeThread;
672 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
673 /* We have a datarace */
674 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), false, location);
679 /** This function does race detection on a read. */
680 void atomraceCheckRead(thread_id_t thread, const void *location)
682 uint64_t *shadow = lookupAddressEntry(location);
683 uint64_t shadowval = *shadow;
684 ClockVector *currClock = get_execution()->get_cv(thread);
685 if (currClock == NULL)
688 struct DataRace * race = NULL;
691 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
692 race = atomfullRaceCheckRead(thread, location, shadow, currClock);
696 if (shadowval & ATOMICMASK)
700 /* Check for datarace against last write. */
701 modelclock_t writeClock = WRITEVECTOR(shadowval);
702 thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
704 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
705 /* We have a datarace */
706 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), false, location);
714 #ifdef REPORT_DATA_RACES
715 race->numframes=backtrace(race->backtrace, sizeof(race->backtrace)/sizeof(void*));
716 if (raceset->add(race))
718 else model_free(race);
725 static inline uint64_t * raceCheckRead_firstIt(thread_id_t thread, const void * location, uint64_t *old_val, uint64_t *new_val)
727 uint64_t *shadow = lookupAddressEntry(location);
728 uint64_t shadowval = *shadow;
730 ClockVector *currClock = get_execution()->get_cv(thread);
731 if (currClock == NULL)
734 struct DataRace * race = NULL;
737 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
738 race = fullRaceCheckRead(thread, location, shadow, currClock);
743 int threadid = id_to_int(thread);
744 modelclock_t ourClock = currClock->getClock(thread);
746 /* Thread ID is too large or clock is too large. */
747 if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) {
748 expandRecord(shadow);
749 race = fullRaceCheckRead(thread, location, shadow, currClock);
753 /* Check for datarace against last write. */
754 modelclock_t writeClock = WRITEVECTOR(shadowval);
755 thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
757 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
758 /* We have a datarace */
759 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), false, location);
762 modelclock_t readClock = READVECTOR(shadowval);
763 thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
765 if (clock_may_race(currClock, thread, readClock, readThread)) {
766 /* We don't subsume this read... Have to expand record. */
767 expandRecord(shadow);
768 struct RaceRecord *record = (struct RaceRecord *) (*shadow);
769 record->thread[1] = thread;
770 record->readClock[1] = ourClock;
776 *shadow = ENCODEOP(threadid, ourClock, id_to_int(writeThread), writeClock) | (shadowval & ATOMICMASK);
778 *old_val = shadowval;
783 #ifdef REPORT_DATA_RACES
784 race->numframes=backtrace(race->backtrace, sizeof(race->backtrace)/sizeof(void*));
785 if (raceset->add(race))
787 else model_free(race);
796 static inline void raceCheckRead_otherIt(thread_id_t thread, const void * location) {
797 uint64_t *shadow = lookupAddressEntry(location);
799 uint64_t shadowval = *shadow;
801 ClockVector *currClock = get_execution()->get_cv(thread);
802 if (currClock == NULL)
805 struct DataRace * race = NULL;
808 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
809 race = fullRaceCheckRead(thread, location, shadow, currClock);
814 int threadid = id_to_int(thread);
815 modelclock_t ourClock = currClock->getClock(thread);
817 /* Thread ID is too large or clock is too large. */
818 if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) {
819 expandRecord(shadow);
820 race = fullRaceCheckRead(thread, location, shadow, currClock);
824 /* Check for datarace against last write. */
825 modelclock_t writeClock = WRITEVECTOR(shadowval);
826 thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
828 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
829 /* We have a datarace */
830 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), false, location);
833 modelclock_t readClock = READVECTOR(shadowval);
834 thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
836 if (clock_may_race(currClock, thread, readClock, readThread)) {
837 /* We don't subsume this read... Have to expand record. */
838 expandRecord(shadow);
839 struct RaceRecord *record = (struct RaceRecord *) (*shadow);
840 record->thread[1] = thread;
841 record->readClock[1] = ourClock;
847 *shadow = ENCODEOP(threadid, ourClock, id_to_int(writeThread), writeClock) | (shadowval & ATOMICMASK);
851 #ifdef REPORT_DATA_RACES
852 race->numframes=backtrace(race->backtrace, sizeof(race->backtrace)/sizeof(void*));
853 if (raceset->add(race))
855 else model_free(race);
862 void raceCheckRead64(thread_id_t thread, const void *location)
864 uint64_t old_shadowval, new_shadowval;
865 old_shadowval = new_shadowval = INVALIDSHADOWVAL;
869 uint64_t * shadow = raceCheckRead_firstIt(thread, location, &old_shadowval, &new_shadowval);
870 if (CHECKBOUNDARY(location, 7)) {
871 if (shadow[1]==old_shadowval)
872 shadow[1] = new_shadowval;
874 if (shadow[2]==old_shadowval)
875 shadow[2] = new_shadowval;
877 if (shadow[3]==old_shadowval)
878 shadow[3] = new_shadowval;
880 if (shadow[4]==old_shadowval)
881 shadow[4] = new_shadowval;
883 if (shadow[5]==old_shadowval)
884 shadow[5] = new_shadowval;
886 if (shadow[6]==old_shadowval)
887 shadow[6] = new_shadowval;
889 if (shadow[7]==old_shadowval)
890 shadow[7] = new_shadowval;
896 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 1));
898 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 2));
900 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 3));
902 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 4));
904 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 5));
906 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 6));
908 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 7));
911 void raceCheckRead32(thread_id_t thread, const void *location)
913 uint64_t old_shadowval, new_shadowval;
914 old_shadowval = new_shadowval = INVALIDSHADOWVAL;
918 uint64_t * shadow = raceCheckRead_firstIt(thread, location, &old_shadowval, &new_shadowval);
919 if (CHECKBOUNDARY(location, 3)) {
920 if (shadow[1]==old_shadowval)
921 shadow[1] = new_shadowval;
923 if (shadow[2]==old_shadowval)
924 shadow[2] = new_shadowval;
926 if (shadow[3]==old_shadowval)
927 shadow[3] = new_shadowval;
933 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 1));
935 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 2));
937 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 3));
940 void raceCheckRead16(thread_id_t thread, const void *location)
942 uint64_t old_shadowval, new_shadowval;
943 old_shadowval = new_shadowval = INVALIDSHADOWVAL;
947 uint64_t * shadow = raceCheckRead_firstIt(thread, location, &old_shadowval, &new_shadowval);
948 if (CHECKBOUNDARY(location, 1)) {
949 if (shadow[1]==old_shadowval) {
950 shadow[1] = new_shadowval;
954 raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 1));
957 void raceCheckRead8(thread_id_t thread, const void *location)
959 uint64_t old_shadowval, new_shadowval;
960 old_shadowval = new_shadowval = INVALIDSHADOWVAL;
964 raceCheckRead_firstIt(thread, location, &old_shadowval, &new_shadowval);
967 static inline uint64_t * raceCheckWrite_firstIt(thread_id_t thread, const void * location, uint64_t *old_val, uint64_t *new_val)
969 uint64_t *shadow = lookupAddressEntry(location);
970 uint64_t shadowval = *shadow;
971 ClockVector *currClock = get_execution()->get_cv(thread);
972 if (currClock == NULL)
975 struct DataRace * race = NULL;
977 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
978 race = fullRaceCheckWrite(thread, location, shadow, currClock);
983 int threadid = id_to_int(thread);
984 modelclock_t ourClock = currClock->getClock(thread);
986 /* Thread ID is too large or clock is too large. */
987 if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) {
988 expandRecord(shadow);
989 race = fullRaceCheckWrite(thread, location, shadow, currClock);
994 /* Check for datarace against last read. */
995 modelclock_t readClock = READVECTOR(shadowval);
996 thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
998 if (clock_may_race(currClock, thread, readClock, readThread)) {
999 /* We have a datarace */
1000 race = reportDataRace(readThread, readClock, false, get_execution()->get_parent_action(thread), true, location);
1006 /* Check for datarace against last write. */
1007 modelclock_t writeClock = WRITEVECTOR(shadowval);
1008 thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
1010 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
1011 /* We have a datarace */
1012 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), true, location);
1018 *shadow = ENCODEOP(0, 0, threadid, ourClock);
1020 *old_val = shadowval;
1026 #ifdef REPORT_DATA_RACES
1027 race->numframes=backtrace(race->backtrace, sizeof(race->backtrace)/sizeof(void*));
1028 if (raceset->add(race))
1030 else model_free(race);
1039 static inline void raceCheckWrite_otherIt(thread_id_t thread, const void * location) {
1040 uint64_t *shadow = lookupAddressEntry(location);
1042 uint64_t shadowval = *shadow;
1044 ClockVector *currClock = get_execution()->get_cv(thread);
1045 if (currClock == NULL)
1048 struct DataRace * race = NULL;
1049 /* Do full record */
1050 if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
1051 race = fullRaceCheckWrite(thread, location, shadow, currClock);
1056 int threadid = id_to_int(thread);
1057 modelclock_t ourClock = currClock->getClock(thread);
1059 /* Thread ID is too large or clock is too large. */
1060 if (threadid > MAXTHREADID || ourClock > MAXWRITEVECTOR) {
1061 expandRecord(shadow);
1062 race = fullRaceCheckWrite(thread, location, shadow, currClock);
1067 /* Check for datarace against last read. */
1068 modelclock_t readClock = READVECTOR(shadowval);
1069 thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
1071 if (clock_may_race(currClock, thread, readClock, readThread)) {
1072 /* We have a datarace */
1073 race = reportDataRace(readThread, readClock, false, get_execution()->get_parent_action(thread), true, location);
1079 /* Check for datarace against last write. */
1080 modelclock_t writeClock = WRITEVECTOR(shadowval);
1081 thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
1083 if (clock_may_race(currClock, thread, writeClock, writeThread)) {
1084 /* We have a datarace */
1085 race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), true, location);
1091 *shadow = ENCODEOP(0, 0, threadid, ourClock);
1096 #ifdef REPORT_DATA_RACES
1097 race->numframes=backtrace(race->backtrace, sizeof(race->backtrace)/sizeof(void*));
1098 if (raceset->add(race))
1100 else model_free(race);
1107 void raceCheckWrite64(thread_id_t thread, const void *location)
1109 uint64_t old_shadowval, new_shadowval;
1110 old_shadowval = new_shadowval = INVALIDSHADOWVAL;
1114 uint64_t * shadow = raceCheckWrite_firstIt(thread, location, &old_shadowval, &new_shadowval);
1115 if (CHECKBOUNDARY(location, 7)) {
1116 if (shadow[1]==old_shadowval)
1117 shadow[1] = new_shadowval;
1119 if (shadow[2]==old_shadowval)
1120 shadow[2] = new_shadowval;
1122 if (shadow[3]==old_shadowval)
1123 shadow[3] = new_shadowval;
1125 if (shadow[4]==old_shadowval)
1126 shadow[4] = new_shadowval;
1128 if (shadow[5]==old_shadowval)
1129 shadow[5] = new_shadowval;
1131 if (shadow[6]==old_shadowval)
1132 shadow[6] = new_shadowval;
1134 if (shadow[7]==old_shadowval)
1135 shadow[7] = new_shadowval;
1141 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 1));
1143 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 2));
1145 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 3));
1147 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 4));
1149 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 5));
1151 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 6));
1153 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 7));
1156 void raceCheckWrite32(thread_id_t thread, const void *location)
1158 uint64_t old_shadowval, new_shadowval;
1159 old_shadowval = new_shadowval = INVALIDSHADOWVAL;
1163 uint64_t * shadow = raceCheckWrite_firstIt(thread, location, &old_shadowval, &new_shadowval);
1164 if (CHECKBOUNDARY(location, 3)) {
1165 if (shadow[1]==old_shadowval)
1166 shadow[1] = new_shadowval;
1168 if (shadow[2]==old_shadowval)
1169 shadow[2] = new_shadowval;
1171 if (shadow[3]==old_shadowval)
1172 shadow[3] = new_shadowval;
1178 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 1));
1180 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 2));
1182 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 3));
1185 void raceCheckWrite16(thread_id_t thread, const void *location)
1187 uint64_t old_shadowval, new_shadowval;
1188 old_shadowval = new_shadowval = INVALIDSHADOWVAL;
1193 uint64_t * shadow = raceCheckWrite_firstIt(thread, location, &old_shadowval, &new_shadowval);
1194 if (CHECKBOUNDARY(location, 1)) {
1195 if (shadow[1]==old_shadowval) {
1196 shadow[1] = new_shadowval;
1200 raceCheckWrite_otherIt(thread, (const void *)(((uintptr_t)location) + 1));
1203 void raceCheckWrite8(thread_id_t thread, const void *location)
1205 uint64_t old_shadowval, new_shadowval;
1206 old_shadowval = new_shadowval = INVALIDSHADOWVAL;
1210 raceCheckWrite_firstIt(thread, location, &old_shadowval, &new_shadowval);
1213 void print_normal_accesses()
1215 model_print("store 8 count: %u\n", store8_count);
1216 model_print("store 16 count: %u\n", store16_count);
1217 model_print("store 32 count: %u\n", store32_count);
1218 model_print("store 64 count: %u\n", store64_count);
1220 model_print("load 8 count: %u\n", load8_count);
1221 model_print("load 16 count: %u\n", load16_count);
1222 model_print("load 32 count: %u\n", load32_count);
1223 model_print("load 64 count: %u\n", load64_count);