示例#1
0
 static void ts_set_preStateOnError(ShadowThread ts, FastTrackGuardState v) {
   Assert.panic("Bad");
 }
示例#2
0
  private void error(
      final AccessEvent ae,
      final int errorCase,
      final String prevOp,
      final int prevTid,
      final String curOp,
      final int curTid) {

    try {
      if (ae instanceof FieldAccessEvent) {
        FieldAccessEvent fae = (FieldAccessEvent) ae;
        final FieldInfo fd = fae.getInfo().getField();
        final ShadowThread currentThread = fae.getThread();
        final Object target = fae.getTarget();

        fieldErrors.error(
            currentThread,
            fd,
            "Guard State",
            fae.getOriginalShadow(),
            "Current Thread",
            toString(currentThread),
            "Class",
            target == null ? fd.getOwner() : target.getClass(),
            "Field",
            Util.objectToIdentityString(target) + "." + fd,
            "Prev Op",
            prevOp + prevTid,
            "Cur Op",
            curOp + curTid,
            "Case",
            "#" + errorCase,
            "Stack",
            ShadowThread.stackDumpForErrorMessage(currentThread));
        if (!fieldErrors.stillLooking(fd)) {
          advance(ae);
          return;
        }
      } else {
        ArrayAccessEvent aae = (ArrayAccessEvent) ae;
        final ShadowThread currentThread = aae.getThread();
        final Object target = aae.getTarget();

        arrayErrors.error(
            currentThread,
            aae.getInfo(),
            "Alloc Site",
            ArrayAllocSiteTracker.allocSites.get(aae.getTarget()),
            "Guard State",
            aae.getOriginalShadow(),
            "Current Thread",
            toString(currentThread),
            "Array",
            Util.objectToIdentityString(target) + "[" + aae.getIndex() + "]",
            "Prev Op",
            prevOp + prevTid + ("name = " + ShadowThread.get(prevTid).getThread().getName()),
            "Cur Op",
            curOp + curTid + ("name = " + ShadowThread.get(curTid).getThread().getName()),
            "Case",
            "#" + errorCase,
            "Stack",
            ShadowThread.stackDumpForErrorMessage(currentThread));

        aae.getArrayState().specialize();

        if (!arrayErrors.stillLooking(aae.getInfo())) {
          advance(aae);
          return;
        }
      }
    } catch (Throwable e) {
      Assert.panic(e);
    }
  }
示例#3
0
 /** *** */
 static FastTrackGuardState ts_get_preStateOnError(ShadowThread ts) {
   Assert.panic("Bad");
   return null;
 }
示例#4
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);
    }
  }
示例#5
0
 static void ts_set_cv(ShadowThread ts, CV cv) {
   Assert.panic("Bad");
 }
示例#6
0
 static CV ts_get_cv(ShadowThread ts) {
   Assert.panic("Bad");
   return null;
 }
示例#7
0
 static void ts_set_epoch(ShadowThread ts, int v) {
   Assert.panic("Bad");
 }
示例#8
0
 static int ts_get_epoch(ShadowThread ts) {
   Assert.panic("Bad");
   return -1;
 }