adding a test case
[IRC.git] / Robust / TransSim / FlexScheduler.java
index d1d9ef02881d9f4dec2dd1d595f0b6a4661c71bd..1ce1d2d081a0c81d53dab6f8a96a8dfa97906fb4 100644 (file)
@@ -14,7 +14,7 @@ public class FlexScheduler extends Thread {
     this.abortRatio=abortRatio;
     this.checkdepth=checkdepth;
   }
-  
+
   public void run() {
     dosim();
   }
@@ -51,6 +51,9 @@ public class FlexScheduler extends Thread {
     }
   }
 
+  int lowid=0;
+  int countlow=0;
+
   Plot p;
   Series serCommit;
   Series serStart;
@@ -79,16 +82,56 @@ public class FlexScheduler extends Thread {
   public static final int POLITE=9;
   public static final int ERUPTION=10;
   public static final int THREAD=11;
+  public static final int ATTACKTIME=12;
+  public static final int ATTACKTHREAD=13;
+
+  public static String getName(int policy) {
+    switch (policy) {
+    case LAZY:
+      return new String("LAZY");
+    case COMMIT:
+      return new String("COMMIT");
+    case ATTACK:
+      return new String("ATTACK");
+    case SUICIDE:
+      return new String("TIMID");
+    case TIMESTAMP:
+      return new String("TIMESTAMP");
+    case LOCK:
+      return new String("LOCK");
+    case LOCKCOMMIT:
+      return new String("LOCKCOMMIT");
+    case RANDOM:
+      return new String("RANDOM");
+    case KARMA:
+      return new String("KARMA");
+    case POLITE:
+      return new String("POLITE");
+    case ERUPTION:
+      return new String("ERUPTION");
+    case THREAD:
+      return new String("THREAD");
+    case ATTACKTIME:
+      return new String("ATTACKTIME");
+    case ATTACKTHREAD:
+      return new String("ATTACKTHREAD");
+    }
+    return null;
+  }
 
   PriorityQueue eq;
   int policy;
   boolean[] aborted;
   long shorttesttime;
+  long earliesttime=-1;
   long starttime=-1;
   Hashtable rdobjmap;
   Hashtable wrobjmap;
   int abortcount;
   int commitcount;
+  long backoffcycles;
+  long stallcycles;
+  long abortedcycles;
   Event[] currentevents;
   Random r;
   int[] backoff;
@@ -100,7 +143,7 @@ public class FlexScheduler extends Thread {
   boolean[] blocked;
 
   public boolean isEager() {
-    return policy==ATTACK||policy==SUICIDE||policy==TIMESTAMP||policy==RANDOM||policy==KARMA||policy==POLITE||policy==ERUPTION||policy==THREAD;
+    return policy==ATTACK||policy==SUICIDE||policy==TIMESTAMP||policy==RANDOM||policy==KARMA||policy==POLITE||policy==ERUPTION||policy==THREAD||policy==ATTACKTIME||policy==ATTACKTHREAD;
   }
 
   public boolean countObjects() {
@@ -119,12 +162,46 @@ public class FlexScheduler extends Thread {
     return commitcount;
   }
 
+  public long getEarliestTime() {
+    return earliesttime-starttime;
+  }
+
   public long getTime() {
     return shorttesttime-starttime;
   }
 
+  public long getStallTime() {
+    return stallcycles;
+  }
+
+  public long getBackoffTime() {
+    return backoffcycles;
+  }
+
+  public long getAbortedTime() {
+    return abortedcycles;
+  }
+
+  //Computes wasted time
+  public void timewasted(int currthread, long currtime) {
+    Event e=currentevents[currthread];
+    Transaction trans=e.getTransaction();
+    int eIndex=e.getEvent();
+    long eTime=e.getTime();
+    long timeleft=eTime-currtime;
+    if (e.isStalled()) {
+      stallcycles-=timeleft; //this time is no longer stalled...back it out
+      timeleft=0;//if the event is stalled, we already waited this time...
+    }
+    long totaltime=trans.getTime(eIndex);
+    totaltime-=timeleft;//subtract off time to the next event
+    abortedcycles+=totaltime;
+  }
+
   //Aborts another thread...
-  public void reschedule(int currthread, long time) {
+  public void reschedule(int currthread, long currtime, long backofftime) {
+    long time=currtime+backofftime;
+    backoffcycles+=backofftime;
     currentevents[currthread].makeInvalid();
     if (threadinfo[currthread].isStalled()) {
       //remove from waiter list
@@ -143,12 +220,13 @@ public class FlexScheduler extends Thread {
   }
 
   //Aborts another thread...
-  public void stall(Event ev, long time) {
-    ev.setTime(time);
+  public void stall(Event ev, long time, long delay) {
+    stallcycles+=delay;
+    ev.setTime(time+delay);
+    ev.setStall();
     eq.add(ev);
   }
 
-
   private void releaseObjects(Transaction trans, int currthread, long time) {
     //remove all events
     for(int i=0;i<trans.numEvents();i++) {
@@ -241,6 +319,16 @@ public class FlexScheduler extends Thread {
     //ready to commit this one
     long currtime=ev.getTime();
     releaseObjects(trans, ev.getThread(), currtime);
+
+    if (ev.getThread()==lowid) {
+      countlow++;
+      if (countlow==4) {
+       countlow=0;
+       lowid++;
+       if (lowid==e.numThreads())
+         lowid=0;
+      }
+    }
     
     //See if we have been flagged as aborted for the lazy case
     boolean abort=aborted[ev.getThread()];
@@ -255,6 +343,7 @@ public class FlexScheduler extends Thread {
       }
       //Reset our backoff counter
       threadinfo[ev.getThread()].priority=0;
+      threadinfo[ev.getThread()].aborted=false;
       backoff[ev.getThread()]=BACKOFFSTART;
       retrycount[ev.getThread()]=0;
       transferred[ev.getThread()]=0;
@@ -304,7 +393,8 @@ public class FlexScheduler extends Thread {
                serAbort.addPoint(currtime, threadid);
            } else if (policy==COMMIT||policy==LOCKCOMMIT) {
              //abort it immediately
-             reschedule(threadid, currtime);
+             timewasted(threadid, currtime);
+             reschedule(threadid, currtime, 0);
              abortcount++;
            }
          }
@@ -312,6 +402,7 @@ public class FlexScheduler extends Thread {
       }
     } else {
       abortcount++;
+      timewasted(ev.getThread(), currtime);
     }
     
     //add next transaction event...could be us if we aborted
@@ -327,6 +418,9 @@ public class FlexScheduler extends Thread {
       Event nev=new Event(currtime+nexttrans.getTime(0), nexttrans, 0, ev.getThread(), nexttransnum);
       currentevents[ev.getThread()]=nev;
       eq.add(nev);
+    } else {
+      if (earliesttime==-1)
+       earliesttime=currtime;
     }
   }
 
@@ -345,6 +439,14 @@ public class FlexScheduler extends Thread {
       return conflictset;
   }
 
+
+  int normalize(int tid) {
+    int newtid=tid-lowid;
+    if (newtid<0)
+      newtid+=e.numThreads();
+    return newtid;
+  }
+
   public Set wrConflictSet(int thread, ObjIndex obj) {
     HashSet conflictset=new HashSet();
     if (rdobjmap.containsKey(obj)) {
@@ -368,8 +470,6 @@ public class FlexScheduler extends Thread {
   //Takes as parameter -- current transaction read event ev, conflicting
   //set of threads, and the current time
   //Returning false causes current transaction not continue to be scheduled
-  long stalltime=0;
-  long aborttime=0;
 
 
   public boolean handleConflicts(Event ev, Set threadstokill, long time) {
@@ -381,13 +481,14 @@ public class FlexScheduler extends Thread {
        int dback=backoff[thread]*2;
        if (dback>0)
          backoff[thread]=dback;
-       stall(ev, time+r.nextInt(backoff[thread]));
+       stall(ev, timer.nextInt(backoff[thread]));
        return false;
       } else {
        //abort other transactions
        for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
          Integer thread=(Integer)thit.next();
-         reschedule(thread, time);
+         timewasted(thread, time);
+         reschedule(thread, time, 0);
          abortcount++;
        }
        return true;
@@ -404,8 +505,7 @@ public class FlexScheduler extends Thread {
        threadinfo[ev.getThread()].priority--;
        retrycount[ev.getThread()]++;
        int rtime=r.nextInt(3000);
-       stall(ev, time+rtime);
-       stalltime+=rtime;
+       stall(ev, time, rtime);
        return false;
       } else {
        //we win
@@ -415,8 +515,8 @@ public class FlexScheduler extends Thread {
          if (dback>0)
            backoff[thread]=dback;
          int atime=r.nextInt(backoff[thread]);
-         reschedule(thread, time+atime);
-         aborttime+=atime;
+         timewasted(thread, time);
+         reschedule(thread, time, atime);
          abortcount++;
        }
        return true;
@@ -434,8 +534,7 @@ public class FlexScheduler extends Thread {
        threadinfo[ev.getThread()].priority--;
        //stall for a little while
        int rtime=r.nextInt(3000);
-       stall(ev, time+rtime);
-       stalltime+=rtime;
+       stall(ev, time, rtime);
        int ourpriority=threadinfo[ev.getThread()].priority;
        ourpriority-=transferred[ev.getThread()];
        for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
@@ -454,8 +553,8 @@ public class FlexScheduler extends Thread {
          if (dback>0)
            backoff[thread]=dback;
          int atime=r.nextInt(backoff[thread]);
-         reschedule(thread, time+atime);
-         aborttime+=atime;
+         timewasted(thread, time);
+         reschedule(thread, time, atime);
          abortcount++;
        }
        return true;
@@ -466,7 +565,8 @@ public class FlexScheduler extends Thread {
        retrycount[ev.getThread()]=0;
        for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
          Integer thread=(Integer)thit.next();
-         reschedule(thread, time);
+         timewasted(thread, time);
+         reschedule(thread, time, 0);
          abortcount++;
        }
        return true;
@@ -475,13 +575,14 @@ public class FlexScheduler extends Thread {
        int stalltime=(1<<(retry-1))*12;
        if (stalltime<0)
          stalltime=1<<30;
-       stall(ev, time+r.nextInt(stalltime));
+       stall(ev, timer.nextInt(stalltime));
        return false;
       }
     } else if (policy==ATTACK) {
       for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
        Integer thread=(Integer)thit.next();
-       reschedule(thread, time+r.nextInt(backoff[thread.intValue()]));
+       timewasted(thread, time);
+       reschedule(thread, time, r.nextInt(backoff[thread.intValue()]));
        int dback=backoff[thread.intValue()]*2;
        if (dback>0)
          backoff[thread.intValue()]=dback;
@@ -489,7 +590,8 @@ public class FlexScheduler extends Thread {
       }
       return true;
     } else if (policy==SUICIDE) {
-      reschedule(ev.getThread(), time+r.nextInt(backoff[ev.getThread()]));
+      timewasted(ev.getThread(), time);
+      reschedule(ev.getThread(), time, r.nextInt(backoff[ev.getThread()]));
       int dback=backoff[ev.getThread()]*2;
       if (dback>0)
        backoff[ev.getThread()]=dback;
@@ -508,71 +610,143 @@ public class FlexScheduler extends Thread {
       }
       if (opponenttime>ev.getTransaction().getTime(ev.getEvent())) {
        //kill ourself
-       reschedule(ev.getThread(), time+r.nextInt(backoff[ev.getThread()]));
+       timewasted(ev.getThread(), time);
+       reschedule(ev.getThread(), time, 0);
        abortcount++;
        return false;
       } else {
        //kill the opponents
        for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
          Integer thread=(Integer)thit.next();
-         reschedule(thread, time+r.nextInt(backoff[thread.intValue()]));
+         timewasted(thread, time);
+         reschedule(thread, time, 0);
          abortcount++;
        }
        return true;    
       }
-    } else if (policy==TIMESTAMP) {
-      long opponenttime=0;
+    } else if (policy==THREAD) {
+      long tid=1000;
 
       for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
        Integer thread=(Integer)thit.next();
        Event other=currentevents[thread.intValue()];
        int eventnum=other.getEvent();
-       long otime=other.getTransaction().getTime(other.getEvent());
-       if (otime>opponenttime)
-         opponenttime=otime;
+       long otid=normalize(thread.intValue());
+       if (tid>otid)
+         tid=otid;
       }
-      if (opponenttime>ev.getTransaction().getTime(ev.getEvent())) {
+      if (normalize(ev.getThread())>tid) {
        //kill ourself
-       reschedule(ev.getThread(), time+r.nextInt(backoff[ev.getThread()]));
+       timewasted(ev.getThread(), time);
+       reschedule(ev.getThread(), time, 0);
        abortcount++;
        return false;
       } else {
        //kill the opponents
        for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
          Integer thread=(Integer)thit.next();
-         reschedule(thread, time+r.nextInt(backoff[thread.intValue()]));
+         timewasted(thread, time);
+         reschedule(thread, time, 0);
          abortcount++;
        }
        return true;    
       }
-    } else if (policy==THREAD) {
-      long tid=1000;
-
+    } else if (policy==ATTACKTIME) {
+      boolean timebased=false;
+      int tev=ev.getThread();
+      timebased|=threadinfo[tev].aborted;
       for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
        Integer thread=(Integer)thit.next();
-       Event other=currentevents[thread.intValue()];
-       int eventnum=other.getEvent();
-       long otid=thread.intValue();
-       if (tid>otid)
-         tid=otid;
+       timebased|=threadinfo[thread.intValue()].aborted;
       }
-      if (ev.getThread()>tid) {
-       //kill ourself
-       reschedule(ev.getThread(), time+r.nextInt(backoff[ev.getThread()]));
-       abortcount++;
-       return false;
+      if (timebased) {
+       long opponenttime=0;
+       
+       for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
+         Integer thread=(Integer)thit.next();
+         Event other=currentevents[thread.intValue()];
+         int eventnum=other.getEvent();
+         long otime=other.getTransaction().getTime(other.getEvent());
+         if (otime>opponenttime)
+           opponenttime=otime;
+       }
+       if (opponenttime>ev.getTransaction().getTime(ev.getEvent())) {
+         //kill ourself
+         timewasted(ev.getThread(), time);
+         reschedule(ev.getThread(), time, 0);
+         threadinfo[ev.getThread()].aborted=true;
+         abortcount++;
+         return false;
+       } else {
+         //kill the opponents
+         for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
+           Integer thread=(Integer)thit.next();
+           timewasted(thread, time);
+           reschedule(thread, time, 0);
+           threadinfo[thread.intValue()].aborted=true;
+           abortcount++;
+         }
+         return true;  
+       }
       } else {
-       //kill the opponents
        for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
          Integer thread=(Integer)thit.next();
-         reschedule(thread, time+r.nextInt(backoff[thread.intValue()]));
+         timewasted(thread, time);
+         reschedule(thread, time, 0);
+         threadinfo[thread.intValue()].aborted=true;
          abortcount++;
        }
-       return true;    
+       return true;
+      }
+    } else if (policy==ATTACKTHREAD) {
+      boolean threadbased=false;
+      int tev=ev.getThread();
+      threadbased|=threadinfo[tev].aborted;
+      for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
+       Integer thread=(Integer)thit.next();
+       threadbased|=threadinfo[thread.intValue()].aborted;
+      }
+      if (threadbased) {
+       long opponentthr=1000;
+       
+       for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
+         Integer thread=(Integer)thit.next();
+         Event other=currentevents[thread.intValue()];
+         int eventnum=other.getEvent();
+         long othr=thread.intValue();
+         if (othr<opponentthr)
+           opponentthr=othr;
+       }
+       if (opponentthr<tev) {
+         //kill ourself
+         timewasted(ev.getThread(), time);
+         reschedule(ev.getThread(), time, 0);
+         threadinfo[ev.getThread()].aborted=true;
+         abortcount++;
+         return false;
+       } else {
+         //kill the opponents
+         for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
+           Integer thread=(Integer)thit.next();
+           timewasted(thread, time);
+           reschedule(thread, time, 0);
+           threadinfo[thread.intValue()].aborted=true;
+           abortcount++;
+         }
+         return true;  
+       }
+      } else {
+       for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
+         Integer thread=(Integer)thit.next();
+         timewasted(thread, time);
+         reschedule(thread, time, 0);
+         threadinfo[thread.intValue()].aborted=true;
+         abortcount++;
+       }
+       return true;
       }
     }
 
-
     //Not eager
     return true;
   }
@@ -705,6 +879,15 @@ public class FlexScheduler extends Thread {
     Transaction t;
     int threadid;
     int transnum;
+    boolean stalled;
+
+    public boolean isStalled() {
+      return stalled;
+    }
+
+    public void setStall() {
+      stalled=true;
+    }
 
     public void makeInvalid() {
       valid=false;