@Override public void classInitialized(ClassInitializedEvent e) { final ShadowThread currentThread = e.getThread(); final CV cv = this.ts_get_cv(currentThread); Util.log("Class Init for " + e + " -- " + cv); classInitTime.get(e.getRRClass()).max(cv); this.incEpochAndCV(currentThread, e); super.classInitialized(e); }
@Override public void preWait(WaitEvent we) { FastTrackLockData lockData = get(we.getLock()); this.incEpochAndCV(we.getThread(), we); synchronized (lockData) { lockData.cv.max(ts_get_cv(we.getThread())); } super.preWait(we); }
@Override public void acquire(final AcquireEvent ae) { final ShadowThread td = ae.getThread(); final ShadowLock shadowLock = ae.getLock(); final FastTrackLockData fhbLockData = get(shadowLock); this.maxEpochAndCV(td, fhbLockData.cv, ae); super.acquire(ae); }
@Override public void postJoin(final JoinEvent je) { final ShadowThread td = je.getThread(); final ShadowThread joining = je.getJoiningThread(); if (joining.getTid() != -1) { this.incEpochAndCV(joining, je); this.maxEpochAndCV(td, ts_get_cv(joining), je); } super.postJoin(je); }
@Override public void release(final ReleaseEvent re) { final ShadowThread td = re.getThread(); final ShadowLock shadowLock = re.getLock(); final FastTrackLockData fhbLockData = get(shadowLock); CV cv = ts_get_cv(td); fhbLockData.cv.max(cv); this.incEpochAndCV(td, re); super.release(re); }
@Override public void create(NewThreadEvent e) { ShadowThread currentThread = e.getThread(); CV cv = ts_get_cv(currentThread); if (cv == null) { cv = new CV(INIT_CV_SIZE); ts_set_cv(currentThread, cv); cv.set(currentThread.getTid(), Epoch.make(currentThread.getTid(), 0)); this.incEpochAndCV(currentThread, null); } super.create(e); }
@Override public void preStart(final StartEvent se) { final ShadowThread td = se.getThread(); final ShadowThread forked = se.getNewThread(); final CV curCV = ts_get_cv(td); CV forkedCV = ts_get_cv(forked); this.maxAndIncEpochAndCV(forked, curCV, se); this.incEpochAndCV(td, se); super.preStart(se); }
@Override public void volatileAccess(final VolatileAccessEvent fae) { final ShadowVar orig = fae.getOriginalShadow(); final ShadowThread td = fae.getThread(); FastTrackVolatileData vd = get((fae).getShadowVolatile()); final CV cv = ts_get_cv(td); if (fae.isWrite()) { vd.cv.max(cv); this.incEpochAndCV(td, fae); } else { cv.max(vd.cv); } super.volatileAccess(fae); }
@Override public void postWait(WaitEvent we) { FastTrackLockData lockData = get(we.getLock()); this.maxEpochAndCV(we.getThread(), lockData.cv, we); super.postWait(we); }
@Override public void preNotify(NotifyEvent we) { super.preNotify(we); }
@Override public void access(final AccessEvent fae) { final ShadowVar var = fae.getOriginalShadow(); final ShadowThread td = fae.getThread(); if (var instanceof FastTrackGuardState) { // load the error guard state set by the fast path if it exists. final FastTrackGuardState isItAnError = ts_get_preStateOnError(td); final FastTrackGuardState x = (isItAnError != null) ? isItAnError : (FastTrackGuardState) var; ts_set_preStateOnError(td, null); final int tdEpoch = ts_get_epoch(td); final CV tdCV = ts_get_cv(td); Object target = fae.getTarget(); if (target == null) { CV initTime = classInitTime.get(((FieldAccessEvent) fae).getInfo().getField().getOwner()); tdCV.max(initTime); } if (!fae.isWrite()) { // READ retry: do { final long orig = x.getWREpochs(); final int lastReadEpoch = EpochPair.read(orig); if (lastReadEpoch == tdEpoch) { break; // commit : same epoch } final int tid = td.getTid(); final int lastWriteEpoch = EpochPair.write(orig); if (lastReadEpoch == Epoch.READ_SHARED) { if (x.get(tid) != tdEpoch) { // (*) racy access -> should be fine. synchronized (x) { if (orig != x.getWREpochs()) { Yikes.yikes("concurrent mod"); continue retry; } x.set(tid, tdEpoch); } } } else { final int lastReader = Epoch.tid(lastReadEpoch); if (lastReader == tid) { if (!x.cas(orig, lastWriteEpoch, tdEpoch)) { Yikes.yikes("concurrent mod"); continue retry; } // commit: read-exclusive fast case } else if (lastReadEpoch <= tdCV.get(lastReader)) { if (!x.cas(orig, lastWriteEpoch, tdEpoch)) { Yikes.yikes("concurrent mod"); continue retry; } // commit: read-exclusive slow case } else { synchronized (x) { x.makeCV(INIT_CV_SIZE); // do first, in case we need it at (*) if (!x.cas(orig, lastWriteEpoch, Epoch.READ_SHARED)) { Yikes.yikes("concurrent mod"); continue retry; } // commit: read share x.set(lastReader, lastReadEpoch); x.set(td.getTid(), tdEpoch); } } } final int lastWriter = Epoch.tid(lastWriteEpoch); if (lastWriter != tid && lastWriteEpoch > tdCV.get(lastWriter)) { error(fae, 4, "write-by-thread-", lastWriter, "read-by-thread-", tid); } } while (false); // awesome... } else { // WRITE retry: do { final long orig = x.getWREpochs(); final int lastWriteEpoch = EpochPair.write(orig); if (lastWriteEpoch == tdEpoch) { break; // commit: same epoch } final int tid = td.getTid(); final int lastReadEpoch = EpochPair.read(orig); if (lastReadEpoch == tdEpoch) { if (!x.cas(orig, tdEpoch, tdEpoch)) { Yikes.yikes("concurrent mod"); continue retry; } // commit: write exclusive fast case } else if (lastReadEpoch != Epoch.READ_SHARED) { if (!x.cas(orig, tdEpoch, tdEpoch)) { Yikes.yikes("concurrent mod"); continue retry; } // commit: write exclusive slow case final int lastReader = Epoch.tid(lastReadEpoch); if (lastReader != tid && lastReadEpoch > tdCV.get(lastReader)) { error(fae, 2, "read-by-thread-", lastReader, "write-by-thread-", tid); } } else { synchronized (x) { if (!x.cas(orig, tdEpoch, tdEpoch)) { Yikes.yikes("concurrent mod"); continue retry; } // commit write shared if (x.anyGt(tdCV)) { int errorCount = 0; for (int prevReader = x.nextGt(tdCV, 0); prevReader > -1; prevReader = x.nextGt(tdCV, prevReader + 1)) { if (prevReader != tid) { errorCount++; error(fae, 3, "read-by-thread-", prevReader, "write-by-thread-", tid); } } if (errorCount == 0) { Assert.fail("Bad error count"); } } } } final int lastWriter = Epoch.tid(lastWriteEpoch); if (lastWriter != tid && lastWriteEpoch > tdCV.get(lastWriter)) { error(fae, 1, "write-by-thread-", lastWriter, "write-by-thread-", tid); } } while (false); } } else { super.access(fae); } }
@Override public void stop(ShadowThread td) { super.stop(td); }