package soot.jimple.toolkits.thread; import soot.*; import soot.jimple.*; import java.util.*; /** AbstractRuntimeThread written by Richard L. Halpert 2007-03-04 * Acts as a container for the thread information collected by * UnsynchronizedMhpAnalysis. A set of threads started from the same location * will be represented by one AbstractRuntimeThread, with runsMany set to true. */ public class AbstractRuntimeThread { // Where thread is started/joined Stmt startStmt; SootMethod startStmtMethod; Stmt joinStmt; // What methods are in the thread List<Object> methods; List<Object> runMethods; // meant to be a subset of methods // What kind of parallelism boolean runsMany; boolean runsOnce; boolean runsOneAtATime; // How we determined the parallelism boolean startStmtHasMultipleReachingObjects; boolean startStmtMayBeRunMultipleTimes; // boolean hasJoinStmt; // just check if joinStmt is null or not boolean startMethodIsReentrant; boolean startMethodMayHappenInParallel; // Just for kicks boolean isMainThread; public AbstractRuntimeThread() { startStmt = null; startStmtMethod = null; methods = new ArrayList<Object>(); runMethods = new ArrayList<Object>(); // What kind of parallelism - this is set unsafely, so analysis MUST set it correctly runsMany = false; runsOnce = false; runsOneAtATime = false; // How we determined the parallelism - this is set unsafely, so analysis MUST set it correctly startStmtHasMultipleReachingObjects = false; startStmtMayBeRunMultipleTimes = false; startMethodIsReentrant = false; startMethodMayHappenInParallel = false; // Just for kicks isMainThread = false; } public void setStartStmt(Stmt startStmt) { this.startStmt = startStmt; } public void setJoinStmt(Stmt joinStmt) { this.joinStmt = joinStmt; } public void setStartStmtMethod(SootMethod startStmtMethod) { this.startStmtMethod = startStmtMethod; } public SootMethod getStartStmtMethod() { return startStmtMethod; } public boolean containsMethod(Object method) { return methods.contains(method); } public void addMethod(Object method) { methods.add(method); } public void addRunMethod(Object method) { runMethods.add(method); } public List<Object> getRunMethods() { return runMethods; } public int methodCount() { return methods.size(); } public Object getMethod(int methodNum) { return methods.get(methodNum); } public void setStartStmtHasMultipleReachingObjects() { startStmtHasMultipleReachingObjects = true; } public void setStartStmtMayBeRunMultipleTimes() { startStmtMayBeRunMultipleTimes = true; } public void setStartMethodIsReentrant() { startMethodIsReentrant = true; } // Does this ever happen? Should run a test to see if this situation would // already be caught by StartStmtMayBeRunMultipleTimes public void setStartMethodMayHappenInParallel() { startMethodMayHappenInParallel = true; } public void setRunsMany() { runsMany = true; runsOnce = false; runsOneAtATime = false; } public void setRunsOnce() { runsMany = false; runsOnce = true; runsOneAtATime = false; } public void setRunsOneAtATime() { runsMany = false; runsOnce = false; runsOneAtATime = true; } public void setIsMainThread() { isMainThread = true; } public String toString() { String ret = (isMainThread ? "Main Thread" : "User Thread") + " (" + (runsMany ? "Multi, " : (runsOnce ? "Single, " : (runsOneAtATime ? "At-Once,": "ERROR"))); if(startStmtHasMultipleReachingObjects) { ret = ret + "MRO,"; // Multiple Reaching Objects if(startMethodIsReentrant) ret = ret + "SMR"; // Start Method is Reentrant else if(startMethodMayHappenInParallel) ret = ret + "MSP"; // May be Started in Parallel else if(startStmtMayBeRunMultipleTimes) ret = ret + "RMT"; // Run Multiple Times else ret = ret + "ROT"; // Run One Time } else { if(isMainThread) ret = ret + "---,---"; // no start stmt... else ret = ret + "SRO,---"; // Single Reaching Object } ret = ret + "): "; if(!isMainThread) ret = ret + "Started in " + startStmtMethod + " by " + startStmt + "\n"; else ret = ret + "\n"; if(joinStmt != null) ret = ret + " " + "Joined in " + startStmtMethod + " by " + joinStmt + "\n"; ret = ret + methods.toString(); return ret; } }