+ }
+
+ modelclock_t readClock = READVECTOR(shadowval);
+ thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
+
+ if (clock_may_race(currClock, thread, readClock, readThread)) {
+ /* We don't subsume this read... Have to expand record. */
+ expandRecord(shadow);
+ struct RaceRecord *record = (struct RaceRecord *) (*shadow);
+ record->thread[1] = thread;
+ record->readClock[1] = ourClock;
+ record->numReads++;
+
+ goto Exit;
+ }
+
+ *shadow = ENCODEOP(threadid, ourClock, id_to_int(writeThread), writeClock) | (shadowval & ATOMICMASK);
+ }
+Exit:
+ if (race) {
+#ifdef REPORT_DATA_RACES
+ race->numframes=backtrace(race->backtrace, sizeof(race->backtrace)/sizeof(void*));
+ if (raceset->add(race))
+ assert_race(race);
+ else model_free(race);
+#else
+ model_free(race);
+#endif
+ }
+}
+
+void raceCheckRead64(thread_id_t thread, const void *location)
+{
+ int old_flag = GET_MODEL_FLAG;
+ ENTER_MODEL_FLAG;
+
+ uint64_t old_shadowval, new_shadowval;
+ old_shadowval = new_shadowval = INVALIDSHADOWVAL;
+#ifdef COLLECT_STAT
+ load64_count++;
+#endif
+ uint64_t * shadow = raceCheckRead_firstIt(thread, location, &old_shadowval, &new_shadowval);
+ if (CHECKBOUNDARY(location, 7)) {
+ if (shadow[1]==old_shadowval)
+ shadow[1] = new_shadowval;
+ else goto L1;
+ if (shadow[2]==old_shadowval)
+ shadow[2] = new_shadowval;
+ else goto L2;
+ if (shadow[3]==old_shadowval)
+ shadow[3] = new_shadowval;
+ else goto L3;
+ if (shadow[4]==old_shadowval)
+ shadow[4] = new_shadowval;
+ else goto L4;
+ if (shadow[5]==old_shadowval)
+ shadow[5] = new_shadowval;
+ else goto L5;
+ if (shadow[6]==old_shadowval)
+ shadow[6] = new_shadowval;
+ else goto L6;
+ if (shadow[7]==old_shadowval)
+ shadow[7] = new_shadowval;
+ else goto L7;
+ RESTORE_MODEL_FLAG(old_flag);
+ return;
+ }
+
+L1:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 1));
+L2:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 2));
+L3:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 3));
+L4:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 4));
+L5:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 5));
+L6:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 6));
+L7:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 7));
+ RESTORE_MODEL_FLAG(old_flag);
+}
+
+void raceCheckRead32(thread_id_t thread, const void *location)
+{
+ int old_flag = GET_MODEL_FLAG;
+ ENTER_MODEL_FLAG;
+
+ uint64_t old_shadowval, new_shadowval;
+ old_shadowval = new_shadowval = INVALIDSHADOWVAL;
+#ifdef COLLECT_STAT
+ load32_count++;
+#endif
+ uint64_t * shadow = raceCheckRead_firstIt(thread, location, &old_shadowval, &new_shadowval);
+ if (CHECKBOUNDARY(location, 3)) {
+ if (shadow[1]==old_shadowval)
+ shadow[1] = new_shadowval;
+ else goto L1;
+ if (shadow[2]==old_shadowval)
+ shadow[2] = new_shadowval;
+ else goto L2;
+ if (shadow[3]==old_shadowval)
+ shadow[3] = new_shadowval;
+ else goto L3;
+ RESTORE_MODEL_FLAG(old_flag);
+ return;
+ }
+
+L1:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 1));
+L2:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 2));
+L3:
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 3));
+ RESTORE_MODEL_FLAG(old_flag);
+}
+
+void raceCheckRead16(thread_id_t thread, const void *location)
+{
+ int old_flag = GET_MODEL_FLAG;
+ ENTER_MODEL_FLAG;
+
+ uint64_t old_shadowval, new_shadowval;
+ old_shadowval = new_shadowval = INVALIDSHADOWVAL;
+#ifdef COLLECT_STAT
+ load16_count++;
+#endif
+ uint64_t * shadow = raceCheckRead_firstIt(thread, location, &old_shadowval, &new_shadowval);
+ if (CHECKBOUNDARY(location, 1)) {
+ if (shadow[1]==old_shadowval) {
+ shadow[1] = new_shadowval;
+ RESTORE_MODEL_FLAG(old_flag);
+ return;
+ }
+ }
+ raceCheckRead_otherIt(thread, (const void *)(((uintptr_t)location) + 1));
+ RESTORE_MODEL_FLAG(old_flag);
+}
+
+void raceCheckRead8(thread_id_t thread, const void *location)
+{
+ int old_flag = GET_MODEL_FLAG;
+ ENTER_MODEL_FLAG;
+
+#ifdef COLLECT_STAT
+ load8_count++;
+#endif
+ raceCheckRead_otherIt(thread, location);
+ RESTORE_MODEL_FLAG(old_flag);
+}
+
+static inline uint64_t * raceCheckWrite_firstIt(thread_id_t thread, const void * location, uint64_t *old_val, uint64_t *new_val)
+{
+ uint64_t *shadow = lookupAddressEntry(location);
+ uint64_t shadowval = *shadow;
+ ClockVector *currClock = get_execution()->get_cv(thread);
+ if (currClock == NULL)
+ return shadow;
+
+ struct DataRace * race = NULL;
+ /* Do full record */
+ if (shadowval != 0 && !ISSHORTRECORD(shadowval)) {
+ race = fullRaceCheckWrite(thread, location, shadow, currClock);
+ goto Exit;
+ }
+
+ {
+ 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);
+ race = fullRaceCheckWrite(thread, location, shadow, currClock);
+ goto Exit;
+ }
+
+ {
+ /* Check for datarace against last read. */
+ modelclock_t readClock = READVECTOR(shadowval);
+ thread_id_t readThread = int_to_id(RDTHREADID(shadowval));
+
+ if (clock_may_race(currClock, thread, readClock, readThread)) {
+ /* We have a datarace */
+ race = reportDataRace(readThread, readClock, false, get_execution()->get_parent_action(thread), true, location);
+ goto ShadowExit;
+ }
+ }
+
+ {
+ /* Check for datarace against last write. */
+ modelclock_t writeClock = WRITEVECTOR(shadowval);
+ thread_id_t writeThread = int_to_id(WRTHREADID(shadowval));
+
+ if (clock_may_race(currClock, thread, writeClock, writeThread)) {
+ /* We have a datarace */
+ race = reportDataRace(writeThread, writeClock, true, get_execution()->get_parent_action(thread), true, location);
+ goto ShadowExit;
+ }