Example #1
0
 @Override
 public final ShadowVar makeShadowVar(final AccessEvent fae) {
   if (fae.getKind() == Kind.VOLATILE) {
     FastTrackVolatileData vd = get(((VolatileAccessEvent) fae).getShadowVolatile());
     ShadowThread currentThread = fae.getThread();
     vd.cv.max(ts_get_cv(currentThread));
     return super.makeShadowVar(fae);
   } else {
     return createHelper(fae);
   }
 }
Example #2
0
  @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);
    }
  }
Example #3
0
 protected FastTrackGuardState createHelper(AccessEvent e) {
   return new FastTrackGuardState(e.isWrite(), ts_get_epoch(e.getThread()));
 }