4.2 State Filters
4.2.4 The SuperStepP OR Filter
leads froms0to sinAG, we have thatqdoes not exhibit a local cycle, and so it will not be cut by Algorithm 5. Ifqis not cut by Algorithm 3, then a staten, that corresponds tou0being extended withq, is explored. Ifq is cut by Algorithm 3, then we can constructq0 partial order equivalent to qsuch thatq0 also leads tos(see Theorem 6).
is partial order equivalent to q, and there exists an i,0 ≤i≤n, such that the following properties hold:
• u0 a01
−→u1 a02
−→... a
0
−→i ui is a path fromAS andui is a super node inAS;
• for any thread t, if bt1bt2...btk is the sequence of those actions taken by t from the sequence a0i+1...a0n, then for all l, 0 < l ≤k, the path ui
bt1
−→... b
t
−→l uti+l does not end in a super node from AS (uti+l∈/ VSN).
Proof. We prove the lemma by induction on the depth ofu, which is the same as the length ofq. For n = 1, q = we have q0 = and i = 0. The two properties are trivially satisfied since u0∈VSN.
Forn= 1,q=a1we haveq0=a1. Becauseu0is a super step end, anda1is enabled inu0, there exists a super step starting fromu0 that containsa1. We have two cases:
a)u1is a super node, and in this casei= 1. The two properties hold sinceu0 a1
−→a1is a path from AS ending in a super node, and the suffixai...an is empty.
b) u1 is not a super node, and in this case i = 0. The first property trivially holds sinceu0 is a super node, and the second property holds becauseu1is not a super node.
We have proved the base case, and now we proceed to the induction step.
Let q =a1...an−1an. From the induction step we know there exists a path a01...a0n−1 and an i such that the two properties hold fora1...an−1.
Let qt be the sequence of actions taken by thread(an) starting from ui. From the induction hypothesis we know thatqtdoesn’t pass through a super node in AS. Again, we have two cases:
a) The sequence qtan leads to a super node inAS (the case depicted in Figure 4.2a). From the induction hypothesis we know that for any threadp6=t,qp doesn’t pass through a super node, and so we must have that qtan is independent with all the actions in qp. If this were not true, then considering Definition 25, either qt or qp would have to pass through a super node, thus violating the induction hypothesis.
Because for any threadp6=twe have thatqtan is independent withqp, we can reorderq to get a partial order equivalent sequence q0 with q0 =a01...a0iqtan...a00n such thatatan starts from ui and ends in a super node uj. We now have thata01...a0iqtan is a path from AS. We also know from the induction hypothesis that for any two threadst1 andt2,qt1 is independent withqt2 (otherwise one of them would have to pass through a super node starting fromui). If started fromuj, anyqppasses through a super node, we can reorder the suffix such that the part ofqp that forms the super step appears right afteruj. We repeat this process until the two properties hold.
b) The sequence qtan does not lead to a super node in AS (the case depicted in Figure 4.2b).
q0 =a01...a0i−1an andi satisfy the two properties. Using the same argument as in case a) we have
(a) a new super node is reached (b) no super node is reached
Figure 4.2: Extending a path with an actionan
that for any two threads t1 and t2, qt1 and qt2 are independent starting from ui. an has to be independent with all the actions from other threads, since otherwise it would imply that eitherqtan
or anotherqp passes through a super node.
Theorem 9. Let AR be the graph of representations corresponding to AG, and let AS be a super step reduced graph of AR. Assuming thatAG is acyclic, if a state sinAG, having a representation uinAR, violates a safety property then there exists a state representation u0 inAS that corresponds to a state s0 in AG such that s0 violates the same safety property.
Proof. By applying Lemma 14 we can construct a sequence of actionsq=a1...ai...an that starting from u0 leads to usuch that a1...ai is a path in AS starting from u0 and none of the actions aj, i < j≤nis the end of a super step.
If ucorresponds to a deadlock state then all the threads are disabled in u. Any action from a thread t, that leads to a state in whicht is disabled has to be the last action of a super step (we can’t continue the super step). Souis reached by the last action of a super step, souhas to be a super node, and in this caseu0 =u.
Ifucorresponds to an assertion violation or a global invariant violation then none of the actions aj, i < j ≤ n can change the value of the assertion or the value of the global invariant because otherwiseaj would conflict with all the other actions and so it would have to be the end of a super step. So the same assertion violation or global invariant violation is present inuireached by taking the sequence of actionsa1..ai fromu0. So in this case we haveu=u0i.
TheSuperStepP ORfilter tags to each state representationuthe super stepSuperStep(u). This means thatlast_action(u) is part ofSuperStep(u) as either an intermediate action or as the last
Algorithm 6SuperStepP OR(Successors)
1: ss_end=true
2: N extRep={n0 ∈Successors|last_thread(n0) =last_thread(n)}
3: if n6=u0∧N extRep6=∅ then
4: ss=SuperStep(n)
5: sn=SuperN ode(ss)
6: next=choose(N extRep)
7: if IndepLast(ss, sn)∧IndepInter(next, sn)∧
¬Enables(last_action(n), Successors\N extRep)then
8: ss_end=f alse
9: Intermediate(ss) =Intermediate(ss)∪ {Last(ss)}
10: Last(ss) =last_action(next)
11: SuperStep(next) =ss
12: Successors=N extRep
13: end if
14: end if
15: if ss_endthen
16: sn=newSuperN ode
17: SuperSteps(sn) =∅
18: for alln0∈Successorsdo
19: ss=newSuperStep
20: SuperN ode(ss) =sn
21: Intermediate(ss) =∅
22: Last(ss) =last_action(n0)
23: SuperSteps(sn) =SuperSteps(sn)∪ {ss}
24: SuperStep(n0) =ss
25: end for
26: end if
27: return Successors action.
With each super step sswe associate its set of intermediate actions Intermediate(ss), its last actionLast(ss), and the parent super nodeSuperN ode(ss).
A super node is represented by the set of outgoing super nodes, and when it is created, it marks the fact that the current state representationnis inVSN.
The main idea of theSuperStepP ORfilter is to create new super steps for each outgoing action from a super nodeu. Initially these new super steps contain only the corresponding action that was enabled inu. Each super step is repeatedly extended as long as it can be extended. When the super step cannot be extended any longer, a new super node is created at the end of the super step, and the same process is applied to the new super node.
IndepLast(ss, sn), in line 7 of the filter, tests if the last action from the super stepss is inde- pendent with all the last actions from other sibling super steps taken from the super nodesn.
IndepInter(next, sn), in line 7 of the filter, tests if last_action(next)is independent with all the intermediate actions from super steps taken from the super nodesn, except the super step that corresponds tolast_thread(next).
Enables(last_action(n), Successors\N extRep)determines if the last taken action enabled ac- tions from threads that were not previously enabled.
Theorem 10. Algorithm 2 with F ilters holding only Algorithm 6 terminates and traverses AS, a super step reduced graph ofAR.
Proof. The filter does not contain any loops so it has to terminate. The variable Successors is modified only on line 12 where it becomes a subset of the initial value forSuccessors. Algorithm 2 is a restricted graph exploration, and becauseAG is acyclic, it calls theSuperStepP ORfilter only a finite number of times. So Algorithm 2 terminates.
For u0, Algorithm 6 creates a new super node. The guard of the if statement in line 3 is false whenn=u0 and this ensures that the variabless_endistruein line 15. So forn=u0, lines 16 to 25 of the algorithm are executed. These lines create a new super node that corresponds tou0 and also create new super steps for each enabled action inu0.
Figure 4.3: The super step partial order reduction
Figure 4.3 presents the data structures used by the SuperStepP OR filter, and what are their connections to each other.
The current state representationnis part of a super stepss=SuperStep(n)taken by a thread i=last_thread(n)from the parent super node sn=SuperN ode(ss).
The algorithm maintains the following invariantJ1: for any threadt6=last_thread(n),Intermediate(ss) is independent with Intermediate(sst), and alsoLast(ss) is independent withIntermediate(sst),
wheresstis the super node taken from snby threadt.
The algorithm also maintains the invariant J2 none of the actions in Intermediate(ss)enable actions from other threads that were previously disabled.
Together, these two invariants ensure that the conditions presented in the super step definition (Definition 25) are not violated during the exploration.
The SuperStepP OR filter tries to extend ss =SuperStep(n) by adding the next action from last_thread(n)to the super step. First, line 3, ensures thatnis notu0so there exists a last action.
Second, line 3, also ensures that there exists a next action from the same thread (N extRep 6=∅, there exists a successors state representation reached by taking an action from the same thread).
IndepLast(ss, sn)andIndepInter(next, sn), if true, ensure that the invariantJ1 is maintained by extending the super step with the actionlast_action(next).
¬Enables(last_action(n), Successors\N extRep), if true, ensures that the invariantJ2is main- tained by extending the super step with the actionlast_action(next).
If the super step can be extended, then we can remove fromSuccessors(line 12) all the successor state representations that are not reached by taking an action from the current thread.
If it is determined that the super step cannot be extended (ss_end=true), then to maintain the invariantsJ1 and J2,nhas to be the end of the super step ssand become a super node. This is exactly what happens in lines 16-25: a new super node corresponding to n is created, and also new outgoing super steps are created for all the actions that are enabled inn(for all the successors state representations).
The conditions presented in Definition 25 are not violated during the algorithm execution meaning that the algorithm exploresAS, a super step reduced graph ofAR.
Theorem 11. If a state sin AG violates a safety property, then Algorithm 2 with F iltersholding only Algorithm 6 terminates and explores a state s0 from AG, with s0 violating the same safety property as s.
Proof. We apply Theorem 10 and we get that Algorithm 2 terminates and explores AS, a super step reduced graph ofAR.
We apply Theorem 9 and we get that any safety violation that would be exposed by exploring AR is also exposed by just exploringAS.
Chapter 5
SCALE - Design and Implementation
SCALE is divided into three major components. First, aStatic Analysis And Code Instrumentation component finds, by analyzing the source code, the global statements and modifies the code around them to allow an external scheduler to control the way threads are interleaved. Second, aSchedul- ing component, explores the application’s state space by trying many different thread schedulings.
During exploration, when stepped, a thread atomically executes the code between two consecutive global statements. SCALE checks if every visited state satisfies the specified properties. If a viola- tion is found, then a trace of how to get to the error state is generated. Finally, a thirdSimulation component replays error traces allowing the bugs to be reproduced and analyzed at a later time.
SCALE’s static analysis and code instrumentation is written in OCaml, has about 300 lines of code, and was developed as a CIL [20] code transformation. The other components were developed in C and have around 11000 lines of code, most of which is for the scheduling component. SCALE was tested on x86, 32 bit and 64 bit, Linux platforms, and it should be easily ported to any platform that has: a C compiler, an OCaml compiler, the pthread library, and a mechanism for turning off Address Space Layout Randomization[8, 1, 3].
5.1 Static Analysis and Code Instrumentation
The purpose of SCALE’s static analysis and code instrumentation is to modify the verified program such that an external Scheduler process can control how the program’s threads are interleaved.
Using CIL’s[20] points-to analysis and then a CIL transformation, we identify and replace the global statements described in section 3 with wrapped versions. Besides having the same functionality the original ones, the wrapped versions of the global statements, also implement the instrumented executable’s side of the Scheduling Protocol that will be presented in Section 5.2. If finer control is needed, the wrappers can also be inserted manually. There are wrappers for each kind of global statement: creating a new thread, locking and unlocking a mutex, reading and writing to a variable, etc. The wrappers are grouped together in a wrapper library so they can be easily reused. The
whole process is presented in Figure 5.1. At the end, we get aninstrumented executable that uses theScheduling Protocol to communicate with aScheduler.
Figure 5.1: SCALE’s static analysis and code instrumentation process