diff src/main/gov/nasa/jpf/vm/AllRunnablesSyncPolicy.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children 87e9c7544a06
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/gov/nasa/jpf/vm/AllRunnablesSyncPolicy.java	Fri Jan 23 10:14:01 2015 -0800
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2014, United States Government, as represented by the
+ * Administrator of the National Aeronautics and Space Administration.
+ * All rights reserved.
+ *
+ * The Java Pathfinder core (jpf-core) platform is licensed under the
+ * Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ * 
+ *        http://www.apache.org/licenses/LICENSE-2.0. 
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package gov.nasa.jpf.vm;
+
+import gov.nasa.jpf.Config;
+import gov.nasa.jpf.vm.choice.ThreadChoiceFromSet;
+
+/**
+ * a Scheduler implementation base class that allows filtering of runnable threads and
+ * implements SyncPolicy without backtracking or empty transitions, i.e. choice sets that
+ * include all runnable threads
+ */
+public class AllRunnablesSyncPolicy implements SyncPolicy {
+
+  protected VM vm;
+  protected boolean breakSingleChoice;
+  protected boolean breakLockRelease;
+  protected boolean breakNotify;
+  protected boolean breakSleep;
+  protected boolean breakYield;
+  protected boolean breakPriority;
+  
+  public AllRunnablesSyncPolicy (Config config){
+    breakSingleChoice = config.getBoolean("cg.break_single_choice", false);    
+    breakLockRelease = config.getBoolean("cg.break_lock_release", true);
+    breakNotify = config.getBoolean("cg.break_notify", true);
+    breakSleep = config.getBoolean("cg.break_sleep", true);
+    breakYield = config.getBoolean("cg.break_yield", true);
+    breakPriority = config.getBoolean("cg.break_priority", true);
+  }
+  
+  
+  //--- internal methods
+
+  /**
+   * this is the main policy method that can be overridden by subclasses, e.g. by filtering
+   * out the highest priority runnables, or by ordering according to priority
+   * 
+   * Default behavior is to first try to find runnables within the provided ApplicationContext,
+   * and fall back to any runnable if there are none in this context
+   * 
+   * this includes threads that are in operations that can timeout
+   */
+  protected ThreadInfo[] getTimeoutRunnables (ApplicationContext appCtx){
+    ThreadList tlist = vm.getThreadList();
+    
+    if (tlist.hasProcessTimeoutRunnables(appCtx)){
+      return tlist.getProcessTimeoutRunnables(appCtx);
+    } else {
+      return tlist.getTimeoutRunnables();
+    }
+  }
+
+    
+  protected ChoiceGenerator<ThreadInfo> getRunnableCG (String id, ThreadInfo tiCurrent){
+    ThreadInfo[] choices = getTimeoutRunnables(tiCurrent.getApplicationContext());
+    
+    if (choices.length == 0){
+      return null;
+    }
+    
+    if ((choices.length == 1) && (choices[0] == tiCurrent) && !tiCurrent.isTimeoutWaiting()){ // no context switch
+      if (!breakSingleChoice){
+        return null;
+      }
+    }
+    
+    return new ThreadChoiceFromSet( id, choices, true);
+  }
+  
+  protected boolean setNextChoiceGenerator (ChoiceGenerator<ThreadInfo> cg){
+    if (cg != null){
+      return vm.getSystemState().setNextChoiceGenerator(cg); // listeners could still remove CGs
+    } else {
+      return false;
+    }
+  }
+  
+  /**
+   * set a runnable CG that is optional if we are in a atomic section 
+   */
+  protected boolean setNonBlockingCG (String id, ThreadInfo tiCurrent){
+    if (!tiCurrent.isFirstStepInsn() || tiCurrent.isEmptyTransitionEnabled()) {
+      if (vm.getSystemState().isAtomic()) {
+        return false;
+      } else {
+        return setNextChoiceGenerator(getRunnableCG(id, tiCurrent));
+      }
+      
+    } else {
+      return false;  // no empty transitions
+    }
+  }
+  
+  protected static ChoiceGenerator<ThreadInfo> blockedWithoutChoice = 
+          new ThreadChoiceFromSet("BLOCKED_NO_CHOICE", new ThreadInfo[0], true);
+  
+  /**
+   * set a runnable CG that would break a atomic section because it requires
+   * a context switch
+   */
+  protected boolean setBlockingCG (String id, ThreadInfo tiCurrent){
+    if (!tiCurrent.isFirstStepInsn() || tiCurrent.isEmptyTransitionEnabled()) {
+      if (vm.getSystemState().isAtomic()) {
+        vm.getSystemState().setBlockedInAtomicSection();
+      }
+      
+      ChoiceGenerator<ThreadInfo> cg = getRunnableCG(id, tiCurrent);
+      if (cg == null){ // make sure we don't mask a deadlock
+        if (vm.getThreadList().hasLiveThreads()){
+          cg = blockedWithoutChoice;
+        }
+      }
+      
+      return setNextChoiceGenerator(cg);
+      
+    } else {
+      return false;  // no empty transitions
+    }
+  }
+    
+  /**
+   * set a runnable CG that only breaks a atomic section if the blocking thread
+   * is the currently executing one
+   */
+  protected boolean setMaybeBlockingCG (String id, ThreadInfo tiCurrent, ThreadInfo tiBlock){
+    if (tiCurrent == tiBlock){
+      return setBlockingCG( id, tiCurrent);
+    } else {
+      return setNonBlockingCG( id, tiCurrent);
+    }
+  }
+  
+  
+  //--- SyncPolicy interface
+  
+  //--- initialization
+  @Override
+  public void initializeSyncPolicy (VM vm, ApplicationContext appCtx){
+    this.vm  = vm;
+  }
+  
+  @Override
+  public void initializeThreadSync (ThreadInfo tiCurrent, ThreadInfo tiNew){
+  }
+    
+  //--- locks
+  @Override
+  public boolean setsBlockedThreadCG (ThreadInfo ti, ElementInfo ei){
+    return setBlockingCG( BLOCK, ti);
+  }
+  
+  @Override
+  public boolean setsLockAcquisitionCG (ThreadInfo ti, ElementInfo ei){
+    return setNonBlockingCG( LOCK, ti);
+  }
+  
+  @Override
+  public boolean setsLockReleaseCG (ThreadInfo ti, ElementInfo ei, boolean didUnblock){
+    if (breakLockRelease){
+      if (didUnblock){
+        return setNonBlockingCG( RELEASE, ti);
+      }
+    }
+    
+    return false;
+  }
+  
+  //--- thread termination
+  @Override
+  public boolean setsTerminationCG (ThreadInfo ti){
+    return setBlockingCG( TERMINATE, ti);
+  }
+  
+  //--- java.lang.Object APIs
+  @Override
+  public boolean setsWaitCG (ThreadInfo ti, long timeout){
+    return setBlockingCG( WAIT, ti);
+  }
+  
+  @Override
+  public boolean setsNotifyCG (ThreadInfo ti, boolean didNotify){
+    if (breakNotify){
+      if (didNotify){
+        return setNonBlockingCG( NOTIFY, ti);
+      }
+    }
+    
+    return false;
+  }
+  
+  @Override
+  public boolean setsNotifyAllCG (ThreadInfo ti, boolean didNotify){
+    if (breakNotify){
+      if (didNotify){
+        return setNonBlockingCG( NOTIFYALL, ti);
+      }
+    }
+    
+    return false;
+  }
+  
+    
+  //--- the java.lang.Thread APIs
+  @Override
+  public boolean setsStartCG (ThreadInfo tiCurrent, ThreadInfo tiStarted){
+    return setNonBlockingCG( START, tiCurrent);
+  }
+  
+  @Override
+  public boolean setsYieldCG (ThreadInfo ti){
+    if (breakYield){
+      return setNonBlockingCG( YIELD, ti);
+    } else {
+      return false;
+    }
+  }
+  
+  @Override
+  public boolean setsPriorityCG (ThreadInfo ti){
+    if (breakPriority){
+      return setNonBlockingCG( PRIORITY, ti);    
+    } else {
+      return false;
+    }
+  }
+  
+  @Override
+  public boolean setsSleepCG (ThreadInfo ti, long millis, int nanos){
+    if (breakSleep){
+      return setNonBlockingCG( SLEEP, ti);
+    } else {
+      return false;
+    }
+  }
+  
+  @Override
+  public boolean setsSuspendCG (ThreadInfo tiCurrent, ThreadInfo tiSuspended){
+    return setMaybeBlockingCG( SUSPEND, tiCurrent, tiSuspended);      
+  }
+  
+  @Override
+  public boolean setsResumeCG (ThreadInfo tiCurrent, ThreadInfo tiResumed){
+    return setNonBlockingCG( RESUME, tiCurrent);
+  }
+  
+  @Override
+  public boolean setsJoinCG (ThreadInfo tiCurrent, ThreadInfo tiJoin, long timeout){
+    return setBlockingCG( JOIN, tiCurrent);      
+  }
+  
+  @Override
+  public boolean setsStopCG (ThreadInfo tiCurrent, ThreadInfo tiStopped){
+    return setMaybeBlockingCG( STOP, tiCurrent, tiStopped);
+  }
+  
+  @Override
+  public boolean setsInterruptCG (ThreadInfo tiCurrent, ThreadInfo tiInterrupted){
+    if (tiInterrupted.isWaiting()){
+      return setNonBlockingCG( INTERRUPT, tiCurrent);
+    } else {
+      return false;
+    }
+  }
+  
+  
+  //--- sun.misc.Unsafe
+  @Override
+  public boolean setsParkCG (ThreadInfo ti, boolean isAbsTime, long timeout){
+    return setBlockingCG( PARK, ti);
+  }
+  
+  @Override
+  public boolean setsUnparkCG (ThreadInfo tiCurrent, ThreadInfo tiUnparked){
+    // if the unparked thread is not blocked there is no point
+    if (tiUnparked.isBlocked()){
+      return setNonBlockingCG( UNPARK, tiCurrent);
+    } else {
+      return false;
+    }
+  }
+
+  
+  //--- system scheduling events
+  
+  /**
+   * this one has to be guaranteed to set a CG
+   */
+  @Override
+  public void setRootCG (){
+    ThreadInfo[] runnables = vm.getThreadList().getTimeoutRunnables();
+    ChoiceGenerator<ThreadInfo> cg = new ThreadChoiceFromSet( ROOT, runnables, true);
+    vm.getSystemState().setMandatoryNextChoiceGenerator( cg, "no ROOT choice generator");
+  }
+  
+  
+  //--- gov.nasa.jpf.vm.Verify
+  @Override
+  public boolean setsBeginAtomicCG (ThreadInfo ti){
+    return setNonBlockingCG( BEGIN_ATOMIC, ti);
+  }
+  
+  @Override
+  public boolean setsEndAtomicCG (ThreadInfo ti){
+    return setNonBlockingCG( END_ATOMIC, ti);
+  }
+  
+  //--- ThreadInfo reschedule request
+  @Override
+  public boolean setsRescheduleCG (ThreadInfo ti, String reason){
+    return setNonBlockingCG( reason, ti);
+  }
+  
+  //--- FinalizerThread
+  @Override
+  public boolean setsPostFinalizeCG (ThreadInfo tiFinalizer){
+    // the finalizer is already waiting at this point, i.e. it's not runnable anymore
+    return setBlockingCG( POST_FINALIZE, tiFinalizer);
+  }
+  
+
+}