Search in sources :

Example 1 with HashPointsToSet

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;
}
Also used : EquivalentValue(soot.EquivalentValue) PointsToSetInternal(soot.jimple.spark.sets.PointsToSetInternal) ArrayList(java.util.ArrayList) Unit(soot.Unit) EquivalentValue(soot.EquivalentValue) Value(soot.Value) HashPointsToSet(soot.jimple.spark.sets.HashPointsToSet) HashMutableEdgeLabelledDirectedGraph(soot.toolkits.graph.HashMutableEdgeLabelledDirectedGraph) MethodOrMethodContext(soot.MethodOrMethodContext)

Aggregations

ArrayList (java.util.ArrayList)1 EquivalentValue (soot.EquivalentValue)1 MethodOrMethodContext (soot.MethodOrMethodContext)1 Unit (soot.Unit)1 Value (soot.Value)1 HashPointsToSet (soot.jimple.spark.sets.HashPointsToSet)1 PointsToSetInternal (soot.jimple.spark.sets.PointsToSetInternal)1 HashMutableEdgeLabelledDirectedGraph (soot.toolkits.graph.HashMutableEdgeLabelledDirectedGraph)1