use of soot.jimple.spark.sets.HashPointsToSet in project soot by Sable.
the class DeadlockDetector method detectLocksetDeadlock.
public MutableEdgeLabelledDirectedGraph<Integer, CriticalSection> detectLocksetDeadlock(Map<Value, Integer> lockToLockNum, List<PointsToSetInternal> lockPTSets) {
HashMutableEdgeLabelledDirectedGraph<Integer, CriticalSection> permanentOrder = new HashMutableEdgeLabelledDirectedGraph<Integer, CriticalSection>();
MutableEdgeLabelledDirectedGraph<Integer, CriticalSection> lockOrder;
boolean foundDeadlock;
int iteration = 0;
do {
iteration++;
logger.debug("[DeadlockDetector] Deadlock Iteration #" + iteration);
foundDeadlock = false;
// start each iteration with a fresh copy of the permanent orders
lockOrder = permanentOrder.clone();
// Assemble the partial ordering of locks
Iterator<CriticalSection> deadlockIt1 = criticalSections.iterator();
while (deadlockIt1.hasNext() && !foundDeadlock) {
CriticalSection tn1 = deadlockIt1.next();
// skip if unlocked
if (tn1.group == null) {
continue;
}
// add a node for each lock in this lockset
for (EquivalentValue lockEqVal : tn1.lockset) {
Value lock = lockEqVal.getValue();
if (!lockOrder.containsNode(lockToLockNum.get(lock))) {
lockOrder.addNode(lockToLockNum.get(lock));
}
}
// Get list of tn1's target methods
if (tn1.transitiveTargets == null) {
tn1.transitiveTargets = new HashSet<MethodOrMethodContext>();
for (Unit tn1Invoke : tn1.invokes) {
Iterator<MethodOrMethodContext> targetIt = tt.iterator(tn1Invoke);
while (targetIt.hasNext()) {
tn1.transitiveTargets.add(targetIt.next());
}
}
}
// compare to each other tn
Iterator<CriticalSection> deadlockIt2 = criticalSections.iterator();
while (deadlockIt2.hasNext() && !foundDeadlock) {
CriticalSection tn2 = deadlockIt2.next();
// skip if unlocked
if (tn2.group == null) {
continue;
}
// add a node for each lock in this lockset
for (EquivalentValue lockEqVal : tn2.lockset) {
Value lock = lockEqVal.getValue();
if (!lockOrder.containsNode(lockToLockNum.get(lock))) {
lockOrder.addNode(lockToLockNum.get(lock));
}
}
if (tn1.transitiveTargets.contains(tn2.method) && !foundDeadlock) {
// This implies the partial ordering (locks in tn1) before (locks in tn2)
if (// optionPrintDebug)
true) {
logger.debug("[DeadlockDetector] locks in " + (tn1.name) + " before locks in " + (tn2.name) + ": " + "outer: " + tn1.name + " inner: " + tn2.name);
}
// Check if tn2locks before tn1locks is in our lock order
for (EquivalentValue lock2EqVal : tn2.lockset) {
Value lock2 = lock2EqVal.getValue();
Integer lock2Num = lockToLockNum.get(lock2);
List<Integer> afterTn2 = new ArrayList<Integer>();
// filter here!
afterTn2.addAll(lockOrder.getSuccsOf(lock2Num));
ListIterator<Integer> lit = afterTn2.listIterator();
while (lit.hasNext()) {
// node the edges go to
Integer to = lit.next();
List<CriticalSection> labels = lockOrder.getLabelsForEdges(lock2Num, to);
boolean keep = false;
if (// this shouldn't really happen... is something wrong with the edge-labelled graph?
labels != null) {
for (CriticalSection labelTn : labels) {
// Check if labelTn and tn1 share a static lock
boolean tnsShareAStaticLock = false;
for (EquivalentValue tn1LockEqVal : tn1.lockset) {
Integer tn1LockNum = lockToLockNum.get(tn1LockEqVal.getValue());
if (tn1LockNum < 0) {
// this is a static lock... see if some lock in labelTn has the same #
for (EquivalentValue labelTnLockEqVal : labelTn.lockset) {
if (Objects.equals(lockToLockNum.get(labelTnLockEqVal.getValue()), tn1LockNum)) {
tnsShareAStaticLock = true;
}
}
}
}
if (// !hasStaticLockInCommon(tn1, labelTn))
!tnsShareAStaticLock) {
keep = true;
break;
}
}
}
if (!keep) {
lit.remove();
}
}
/*
for (int i = 0; i < afterTn2.size(); i++) {
List<Integer> succs = lockOrder.getSuccsOf(afterTn2.get(i)); // but not here
for (Integer o : succs) {
if (!afterTn2.contains(o)) {
afterTn2.add(o);
}
}
}
*/
for (EquivalentValue lock1EqVal : tn1.lockset) {
Value lock1 = lock1EqVal.getValue();
Integer lock1Num = lockToLockNum.get(lock1);
if ((!Objects.equals(lock1Num, lock2Num) || lock1Num > 0) && afterTn2.contains(lock1Num)) {
if (!optionRepairDeadlock) {
logger.debug("[DeadlockDetector] DEADLOCK HAS BEEN DETECTED: not correcting");
foundDeadlock = true;
} else {
logger.debug("[DeadlockDetector] DEADLOCK HAS BEEN DETECTED while inspecting " + lock1Num + " (" + lock1 + ") and " + lock2Num + " (" + lock2 + ") ");
// Create a deadlock avoidance edge
DeadlockAvoidanceEdge dae = new DeadlockAvoidanceEdge(tn1.method.getDeclaringClass());
EquivalentValue daeEqVal = new EquivalentValue(dae);
// Register it as a static lock
// negative indicates a static lock
Integer daeNum = -lockPTSets.size();
permanentOrder.addNode(daeNum);
lockToLockNum.put(dae, daeNum);
PointsToSetInternal dummyLockPT = new HashPointsToSet(lock1.getType(), (PAG) Scene.v().getPointsToAnalysis());
lockPTSets.add(dummyLockPT);
// Add it to the locksets of tn1 and whoever says l2 before l1
for (EquivalentValue lockEqVal : tn1.lockset) {
Integer lockNum = lockToLockNum.get(lockEqVal.getValue());
if (!permanentOrder.containsNode(lockNum)) {
permanentOrder.addNode(lockNum);
}
permanentOrder.addEdge(daeNum, lockNum, tn1);
}
tn1.lockset.add(daeEqVal);
List<CriticalSection> forwardLabels = lockOrder.getLabelsForEdges(lock1Num, lock2Num);
if (forwardLabels != null) {
for (CriticalSection tn : forwardLabels) {
if (!tn.lockset.contains(daeEqVal)) {
for (EquivalentValue lockEqVal : tn.lockset) {
Integer lockNum = lockToLockNum.get(lockEqVal.getValue());
if (!permanentOrder.containsNode(lockNum)) {
permanentOrder.addNode(lockNum);
}
permanentOrder.addEdge(daeNum, lockNum, tn);
}
tn.lockset.add(daeEqVal);
}
}
}
List<CriticalSection> backwardLabels = lockOrder.getLabelsForEdges(lock2Num, lock1Num);
if (backwardLabels != null) {
for (CriticalSection tn : backwardLabels) {
if (!tn.lockset.contains(daeEqVal)) {
for (EquivalentValue lockEqVal : tn.lockset) {
Integer lockNum = lockToLockNum.get(lockEqVal.getValue());
if (!permanentOrder.containsNode(lockNum)) {
permanentOrder.addNode(lockNum);
}
permanentOrder.addEdge(daeNum, lockNum, tn);
}
tn.lockset.add(daeEqVal);
logger.debug("[DeadlockDetector] Adding deadlock avoidance edge between " + (tn1.name) + " and " + (tn.name));
}
}
logger.debug("[DeadlockDetector] Restarting deadlock detection");
}
foundDeadlock = true;
break;
}
}
if (!Objects.equals(lock1Num, lock2Num)) {
lockOrder.addEdge(lock1Num, lock2Num, tn1);
}
}
if (foundDeadlock) {
break;
}
}
}
}
}
} while (foundDeadlock && optionRepairDeadlock);
return lockOrder;
}
Aggregations