//
// Copyright (C) 2013 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.vm;
import gov.nasa.jpf.Config;
import gov.nasa.jpf.util.Predicate;
import gov.nasa.jpf.vm.choice.MultiProcessThreadChoice;
import gov.nasa.jpf.vm.choice.ThreadChoiceFromSet;
/**
* @author Nastaran Shafiei <nastaran.shafiei@gmail.com>
*
* This scheduler factory is used for distributed application
*/
public class DistributedSchedulerFactory extends DefaultSchedulerFactory {
public DistributedSchedulerFactory (Config config, VM vm, SystemState ss) {
super(config, vm, ss);
}
Predicate<ThreadInfo> getRunnableAppPredicate (final ThreadInfo ti){
return new Predicate<ThreadInfo>(){
public boolean isTrue (ThreadInfo t){
return (t.appCtx == ti.appCtx && t.isTimeoutRunnable());
}
};
}
Predicate<ThreadInfo> getLiveUserAppThreads (final ThreadInfo ti){
return new Predicate<ThreadInfo>(){
public boolean isTrue (ThreadInfo t){
return (t.appCtx == ti.appCtx && t.isAlive() && !t.isSystemThread());
}
};
}
Predicate<ThreadInfo> getRunnableSystemAppThreads (final ThreadInfo ti){
return new Predicate<ThreadInfo>(){
public boolean isTrue (ThreadInfo t){
return (t.appCtx == ti.appCtx && t.isSystemThread() && t.isTimeoutRunnable());
}
};
}
/**************************************** our choice acquisition methods ***/
/**
* get list of all runnable threads in the same process as ti
*/
protected ThreadInfo[] getRunnables(ThreadInfo ti) {
return filter(vm.getThreadList().getAllMatching(getRunnableAppPredicate(ti)));
}
/**
* return a list of runnable choices, or null if there is only one,
* in the same process as ti
*/
protected ThreadInfo[] getRunnablesIfChoices(ThreadInfo ti) {
ThreadInfo[] choices = vm.getThreadList().getAllMatching(getRunnableAppPredicate(ti));
int n = choices.length;
if ((n > 1) || (n == 1 && breakSingleChoice)){
return filter(choices);
} else {
return null;
}
}
protected ThreadInfo[] getRunnablesWith (ThreadInfo ti) {
return filter(vm.getThreadList().getAllMatchingWith(ti, getRunnableAppPredicate(ti)));
}
protected ThreadInfo[] getRunnablesWithout (ThreadInfo ti) {
return filter(vm.getThreadList().getAllMatchingWithout(ti, getRunnableAppPredicate(ti)));
}
/************************************ the public interface towards the insns ***/
@Override
public ChoiceGenerator<ThreadInfo> createThreadTerminateCG (ThreadInfo terminateThread) {
// terminateThread is already TERMINATED at this point
ThreadList tl = vm.getThreadList();
if (tl.hasAnyMatching(vm.getAlivePredicate())) {
int liveUserCount = tl.getMatchingCount(getLiveUserAppThreads(terminateThread));
int runnableSystemCount = tl.getMatchingCount(getRunnableSystemAppThreads(terminateThread));
if(liveUserCount==0 && runnableSystemCount==0) {
return new MultiProcessThreadChoice( THREAD_TERMINATE, super.getRunnablesWithout(terminateThread), true);
} else {
return new ThreadChoiceFromSet( THREAD_TERMINATE, getRunnablesWithout(terminateThread), true);
}
} else {
return null;
}
}
/**
* after the FinalizerThread processes the finalizeQueue, a global scheduling point is created
*/
@Override
public ChoiceGenerator<ThreadInfo> createPostFinalizeCG (ThreadInfo finalizerThread) {
return new MultiProcessThreadChoice( POST_FINALIZE, super.getRunnables(finalizerThread), true);
}
}