1. Technical Field
The present invention relates to symbolic predictive analysis of computer programs and more particularly to methods and systems for predicting concurrency and atomicity violations in concurrent programs.
2. Description of the Related Art
Predictive analysis aims at detecting concurrency errors by observing execution traces of a concurrent program which may be non-erroneous. Due to the inherent nondeterminism in scheduling concurrent processes/threads, executing a program with the same test input may lead to different program behaviors. This poses a significant challenge in testing concurrent programs—even if a test input may cause a failure, the erroneous interleaving manifesting the failure may not be executed during testing. Furthermore, merely executing the same test multiple times does not always increase the interleaving coverage. In predictive analysis, a concrete execution trace is given, together with a correctness property in the form of assertions embedded in the trace. The given execution trace need not violate the property; but there may exist an alternative trace, i.e., a feasible permutation of events of the given trace, that violates the property. The goal of predictive analysis is detecting such erroneous traces by statically analyzing the given execution trace without re-executing the program.
Prior art predictive analysis algorithms can be classified into two categories based on the quality of reported bugs. The first category consists of methods that do not miss real errors but may report bogus errors. Historically, algorithms that are based on lockset analysis fall into the first category. They strive to cover all possible interleavings that are feasible permutations of events of the given trace, but at the same time may introduce some interleavings that can never appear in the actual program execution. The second category consists of methods that do not report bogus errors but may miss some real errors. Algorithms that are based on happens-before causality often fall into the second category. They provide the feasibility guarantee—that all the reported erroneous interleavings are actual program executions—but they do not cover all interleavings.
Accordingly, techniques are wherein presented which meet the feasibility guarantee, and which outperform prior-art algorithms. According to the present principles, a method for symbolic predictive analysis for finding assertion violations in concurrent programs is shown that includes deriving a concurrent trace program (CTP) for a program under test, generating a logic formula based on a concurrent static single assignment (CSSA) representation of the CTP, wherein the formula includes at least one assertion property, and determining the satisfiability of the formula with a processor, wherein a determination of formula satisfiability indicates an assertion violation.
A further embodiment of the present principles includes a method for symbolic predictive analysis for finding assertion violations in concurrent programs that includes deriving a CTP for a program under test, generating a logic formula based on a CSSA representation of the CTP, wherein the formula includes at least one atomicity violation, and determining the satisfiability of the formula with a processor, wherein a determination of formula satisfiability indicates an atomicity violation.
A further embodiment of the present principles includes a system for symbolic predictive analysis for finding concurrency violations in concurrent programs that includes a CTP module that derives a CTP for a program under test, a CSSA module that generates a logic formula based on a CS SA representation of the CTP, wherein the formula includes a condition for a concurrency violation, and a satisfiability module that determines the satisfiability of the formula with a processor, wherein a determination of formula satisfiability indicates a concurrency violation.
These and other features and advantages will become apparent from the following detailed description of illustrative embodiments thereof, which is to be read in connection with the accompanying drawings.
The disclosure will provide details in the following description of preferred embodiments with reference to the following figures wherein:
a depicts an execution trace.
b depicts an erroneous prefix related to the execution trace of
The present principles are directed to predictive analysis algorithms with a feasibility guarantee. A given execution trace is regarded as a total order on the events appearing in the trace. Based on happens-before reasoning, one can derive a causal model—a partial order of events—which admits not only the given trace but also many alternative permutations. However, two problems need to be solved in testing for concurrency violations. First, checking all of the feasible interleavings allowed by a causal model for property violations is a bottleneck. Despite the long quest for ever more accurate causal models, little has been done to improve the underlying checking algorithms. Second, these causal models often do not assume that source code is available, and therefore rely on observing only the concrete events during execution. In a concrete event, only the values read from or written to shared memory locations are available, whereas the actual program code that produces the event is not known. Consequently, often unnecessarily strong happens-before causality was imposed to achieve the desired feasibility guarantee.
Similar problems exist in testing for atomicity violations. Atomicity, or serializability, is a semantic correctness condition for concurrent programs. Intuitively, a thread interleaving is serializable if it is equivalent to another thread interleaving which executes the user-intended transactional block without other threads interleaved in between. Much attention has recently been focused on three-access atomicity violations, which involves one shared variable and three consecutive accesses to it. If two accesses in a local thread, which are inside a user-intended transactional block, are interleaved in between by an access in another thread, this interleaving may be unserializable if the remote access has data conflicts with the two local accesses. In practice, unserializable interleavings often indicate the presence of subtle concurrency bugs in the program.
Predictive methods for detecting atomicity violations either suffer from imprecision as a result of conservative modeling (or no modeling at all) of the program data flow (consequently producing many false negatives), or suffer from a very limited coverage of interleavings due to trace-based under-approximations. Because of such approximations, the reported atomicity violations may not exist in the actual program. As with the concurrency violation techniques described above, methods using happens—before causality for atomicity violations often miss many real violations.
The present principles include a symbolic predictive analysis technique to address these problems. It can be assumed that the source code is available for instrumentation to obtain symbolic events at runtime (instrumentation is a process for modifying program source code in order to modify its behavior during execution). Considering these symbolic events allows the present principles to achieve the goal of covering more interleavings. This also facilitates a constraint-based modeling where various concurrency primitives or semantics (locks, semaphores, happens-before, sequential consistency, etc.) are handled easily and uniformly.
A concurrent trace program is introduced below as a predictive model to capture feasible interleavings that can be predicted from a given execution trace. A technique for concurrent static single assignment (CSSA) based representation is introduced for symbolic reasoning with a satisfiability modulo theory (SMT) solver. The symbolic search automatically captures property- or goal-directed pruning through conflict analysis and learning features in modern SMT solvers. A method to symbolically constrain the number of context switches in an interleaving is also disclosed and further improves the scalability of the symbolic algorithm.
Using these principles, techniques are given for improved detection of assertion violations and atomicity violations. The present principles advantageously allow for the detection of many more violations, while still reporting only valid violations. The following description outlines particular examples of the present principles. The description is not intended to be limiting, and alterations made to the following embodiments that fall within the scope and spirit of the claims are also considered.
Concurrent Trace Programs
None of the sound causal models in the prior art can predict this error. “Sound,” as used herein, means that the predictive technique does not generate false alarms. For example, if happens-before causality is used to define the feasible trace permutations of ρ, the execution order of all read-after-write event pairs in ρ, which are over the same shared variable, is respected. This means that event t8 must always be executed before t10 and event t7 must always be executed before t11. These happens—before constraints are sufficient but often not necessary to ensure that the admitted traces are feasible. As a result, many other feasible interleavings are left out.
There have been various causal models proposed that have been aimed at lifting some of the happens-before constraints without jeopardizing the feasibility guarantee. However, when applied to the example in
In contrast, the present principles model the execution trace as s sequence of symbolic events by considering the actual program statements that produce ρ and capturing abstract values generated during runtime. In
The techniques described below for concurrency and atomicity violations share a common framework. The semantics of an execution trace is defined using a state transition system. Let
be the set of all program variables and Val be a set of values of variables in V. Referring now to
where s, s′ are states and t is an event in thread Ti, 1≦i≦k, if and only if the following conditions hold:
t=i,(assume(c),asgn)
, s[c] is true, and for each assignment lval:=exp in asgn, s′[lval]=s[exp] holds; states s and s′ agree on all other variables; and
t=i, assert(c)
and s[c] is true. When s[c] is false, an attempt to execute event t raises an error.
Let ρ=t1 . . . tn be an execution trace of program P. If is a feasible execution if there exists a state sequence s0, . . . , sn such that, s0 is the initial state of program P and for all i=1, . . . , n, there exists a transition
An execution trace ρ is a total order on the symbolic events. From ρ one may derive a partial order called the concurrent trace program (CTP). The concurrent trace program of ρ is a partially ordered set CTPρ=(T,⊂) such that,
T={t|tερ} is the set of events, and
⊂ is a partial order such that, for any ti, tj,εT, ti⊂tj if and only if tid(ti)=tid(tj) and i<j (in ρ, event ti appears before tj).
Intuitively, CTPρ orders events from the same thread by their execution order in ρ; events from different threads are not explicitly ordered with each other. Keeping events symbolic and allowing events from different threads remain unordered with each other is a significant advantage of the present principles over prior art techniques.
The feasibility of admitted traces is guaranteed through the notion of feasible linearizations of CTPρ. A linearization of this partial order is an alternative interleaving of events in ρ; due to the sequential consistency execution semantics of concurrent programs, some linearizations may not appear in the actual program execution. (Recall that synchronization primitives are modeled using auxiliary shared variables in atomic guarded assignment events.) Let ρ′=t′1 . . . t′n be a linearization of CTPρ. ρ′ is a feasible linearization if and only if there exist states s0, . . . , sn such that, s0 is the initial state of the program and for all i=1, . . . , n, transitions
exists.
Given the execution trace ρ, one may derive the model CTPρ and symbolically check all its feasible linearizations for property violations. For this, one may create a formula ΦCTP
This encoding is based on transforming the trace program into a concurrent static single assignment (CSSA) form. The CSSA form has the property that each variable is defined exactly once. Here a definition of variable vεV is an event that modifies v, and a use of v is an event where it appears in an expression. In this case, an event defines v if and only if v appears in the left-hand-side of an assignment; an event uses v if and only if v appears in a condition (an assume or the assert) or the right-hand-size of an assignment.
Unlike in classic sequential SSA form, one need not add φ-functions to model the confluence of multiple if-else branches, because in a concurrent trace program each thread has a single control path. The branching decisions have already been made during the program execution.
One may differentiate shared variables in SV from thread-local variables in LVi where 1≦i≦k. Each use of variables v εLVi corresponds to a unique definition, a preceding event in the same thread Ti that defines v. For shared variables, however, each use of variable vεSV may map to multiple definitions due to thread interleaving. A π-function is added to model the confluence of these possible definitions. A π-function, introduced for a shared variable v immediately before its use, has the form π(v1, . . . , vk), where each vi, 1≦i≦k, is either the most recent definition of v in another concurrent thread. These π-functions represent memory consistency constraints.
Therefore, the construction of CSSA includes the following steps: 1. Create unique names for local/shared variables in their definitions; 2. For each use of a local variable vεLVi, 1≦i≦k, replace v with the most recent (unique) definition v′; 3. For each use of a shared variable vεSV, create a unique name v′ and add the definition v′←π(v1, . . . , vk). Then replace v with the new definition v′. Let v′←π(v1, . . . , vk) be defined in event t and each parameter vi, 1≦i≦k be defined in event ti. The π-function may return any of the k parameters as the result depending on the write-read consistency in a particular interleaving. Intuitively, (v′=vi) in an interleaving if and only if vi is the most recent definition before event t. More formally, (v′=vi), where 1≦i≦k, holds if and only if the following condition holds,
event ti, which defines vi, is executed before event t; and
any event tj that defines vj, 1≦i≦k and j≠i, is executed either before the definition in ti or after the use in t.
As an example,
CSSA-Based Satisfiability (SAT) Formula
A quantifier-free first-order logic formula ΦCTP is generated based on the notion of feasible linearizations of CTP and the π-function semantics. The construction is straight forward and follows their definitions. The entire formula ΦCTP consists of the following four subformulas:
ΦCTP:=ΦPOΦVD
ΦPI
PRP,
where ΦPO encodes the program order, ΦVD encodes the variable definitions, and ΦPI, encodes the π-functions, and ΦPRP encodes the property. Formula ΦCTP is satisfiable if and only if there exists a feasible linearization of the CTP that violates the given property.
The following notations are helpful to present the encoding algorithm:
First Event tfirst: add a dummy event tfirst, to be the first event executed in the CTP. That is, ∀tεCTP and t≠tfirst event t must be executed after tfirst;
Last event tlast: add a dummy event tlast, to be the last executed event in the CTP. That is, ∀tεCTP and t≠tlast, event t must be executed after tlast;
First Event tfirsti of Thread Ti: for each iεTid, this is the first event of the thread;
Last event tlasti of Thread Ti: for each iεTid, this is the last event of the thread;
Thread-local preceding event: for each event t, define its thread-local preceding event t′ as follows; tid(t′)=tid(t) and t″εCTP such that t″≠t′, t″=t, and tid(t″)=tid(t), either t″⊂t′ or t⊂t″.
HB-constraint: one may use HB(t,t′), to denote that event t is executed before t′. The actual constraint comprising HB(t,t′) is given in below.
For each event tεCTPρ, the path condition g(t) is defined such that t is executed if and only if g(t) is true. The path conditions are computed as follows:
1. If t=tfirst, or t=tfirsti where iεTid, let g(t):=true.
2. Otherwise, t has a thread-local preceding event t′.
Intuitively, ΦPO captures the event order within each thread. It does impose any inter-thread constraint. Let ΦPO:=true initially. For each event tεCTPρ,
1. if t=tfirst, do nothing;
2. if t=firsti where iεTid, let ΦPO:=ΦPOHB(tfirst,tfirsti);
3. if t=tlasti, let ΦPO:=ΦPOΛ∀iεTidHB(tlasti,tlast);
4. Otherwise, t has a thread-local preceding event t′; let ΦPO:=ΦPOHB(t′,t).
Formula ΦVD is the conjunction of all variable definitions. Let ΦVD:=true initially. For each event tεCTPρ,
Each π-function defines a new variable v′, and ΦPI is a conjunction of all these variable definitions. Let ΦPI:=true initially. For each v′←π(v1, . . . vk) defined in event t, where v′ is used also assume that each vi, where 1≦i≦k is defined in event ti. Let
Intuitively, the π-function evaluates to vi if and only if it chooses the i-th definition in the π-set such that other definitions vj, j≠i, are either before ti or after this use of vi in t.
Let tεCTP be the event with action assert(c), which specifies the correctness property. The property ΦPRP is defined as:
ΦPRP:=(g(t)→c)
Intuitively, the assertion condition c must hold if t is executed. Recall that ΦPRP is negated in ΦCTP
Referring now to g12
(π8=1). In the figure, t0, t14 are the dummy entry and exit events. The subformula in ΦPI for the π-function t11 is defined as follows:
(true)
HB(t11,t3)
HB(t11,t7)
π7 = x1
(g3
HB(t3,t11))
true
HB(t11,t7)
π7 = x2
(g7
HB(t7,t11))
true
true
Note that some of the HB-constraints evaluate to true statically—such simplification is frequent and is performed in our implementation to reduce the size of the final formula.
Symbolic Context Bounding
Traditionally, a context switch is defined as the computing process of storing and restoring the CPU state (context) when executing a concurrent program, such that multiple processes or threads can share a single CPU resource. Concurrency bugs in practice can often be exposed in interleavings with a surprisingly small number of context switches (say 3 or 4).
Referring again to the example of
ρ′=(t1t2 . . . t8)(t9t10 . . . t13)
ρ″=(t9t10 . . . t13)(t1t2 . . . t8).
In both cases, the context switch happens when one thread completes its execution. However, none of the two traces is erroneous and ρ″ is not even a feasible permutation. When the context bound is increased to 2, the number of admitted interleavings remains small but now the following trace is admitted:
ρ′″=(t1t2t3)(t9t10t11t12)(t4 . . . t8).
The trace has two context switches and exposes the error in t12 (where y=0).
HB(t,t′) is defined above as O(t)<O(t′). However, such a strictly-less-than constraint is sufficient, but not necessary, to ensure the correctness of the encoding. To facilitate the implementation of context hounding, the definition of the HB(t,t′) constraint is modified as follows:
1. HB(t,t′):=O(t)≦O(t′) if one of the following condition holds:
2. HB(t,t′):=O(t)≦O(t′) otherwise.
Note that first, if two events t and t′ are from the same thread, the execution time O(t) need not be strictly less than O(t′) to enforce HB(t,t′). This is because the CSSA form, through the renaming of definitions and uses of thread-local variables, already guarantees the flow-sensitivity within each thread. That is, implicitly, a definition always happens before the subsequent uses. Therefore, when tid(t)=tid(t′), one may relax the definition of HB(t,t′) by using less than or equal to.
Second, if events t and t′ are from two different threads (and t≠tfirst and t≠tlast) according to the above encoding rules, the constraint HB(t,t′) must be introduced by the subformula ΦPI encoding π-functions. In such a case, HB(t,t′) means that there is at least one context switch between the execution of t and t′. Therefore, when tid(t)≠tid(t′), the present principles force event t to happen strictly before event t′ in time.
Let k be the maximal number of context switches allowed in an interleaving. In practice, k is empirically set to a small integer. Given the formula ΦCTP
ΦCTP(O(tlast)−O(tfirst)≦k)
The additional constraint states that tlast the unique exit event, may be executed no more than k steps later than tfirst the unique entry event.
The execution times of the events in a feasible trace always form a non-decreasing sequence. Furthermore, the execution time is forced to increase whenever a context switch happens, i.e., as a result of HB(t,t′) when tid(t)≠tid(t′). In the above context-bound constraint, such increases of execution time are limited to less than or equal to k times.
It can be shown that, if CB(ρ′)≦k and ρ′ violates a correctness property, then ΦCTP
In the context bounded analysis, one can empirically choose a bound CB and check the satisfiability of formula ΦCTP
ΦCTP(O(tlast)−O(tfirst)=k).
In both cases, if the formula is satisfiable, an error has been found. Otherwise, the SMT solver used to decide the formula will return a subset of the given formula as a proof of unsatisfiability. More formally, the proof of unsatisfiability of a formula f, which is unsatisfiable, is a subformula funsat of f such that funsat itself is also unsatisfiable. The addition of context-bounding renders the present techniques efficient enough to be used for on-line bug detection. The above formulation of context bounding relates specifically to the framework of symbolic predictive analysis, and is not represented in the prior art.
Atomicity Violations
The above techniques may also be applied to finding atomicity violations in concurrent programs. The resulting technique is more accurate than prior-art methods, while not producing false positives. Given an execution trace on which transactional blocks are explicitly marked, one can check all alternative interleavings of the symbolic events of that trace for three-access atomicity violations. The symbolic events are constructed from both the concrete trace and the program source code. The present principles may be applied as follows:
1. Run a test of the concurrent program to obtain an execution trace.
2. Run a sound but over-approximate algorithm to detect all potential atomicity violations. If no violation is found, return.
3. Build the precise predictive model, and for each potential violation, check whether it is feasible.
Step 3 above may be formulated as a satisfiability problem by constructing a formula which is satisfiable if and only if there exists a feasible and yet unserializable interleaving of events of the given trace. The formula is in a quantifier-free, first-order logic and is decided by a Satisfiability Modulo Theory (SMT) solver. The symbolic, predictive model and the subsequent analysis using an SMT solver differ substantially from techniques described in the prior art. The model tracks the actual data flow and models all synchronization primitives precisely. The greater capability of covering interleavings is due to the use of concrete trace as well as the program source code. Furthermore, using symbolic techniques rather than explicit enumeration makes the analysis less sensitive to the large number of interleavings.
An execution trace ρ is serializable if and only if it is equivalent to a feasible linearization ρ′ of CTPρ which executes the intended transaction without other threads interleaved in between. Two traces are equivalent if and only if one can transform one into another by repeatedly swapping adjacent independent events. Here two events are independent if and only if swapping their execution order always leads to the same program state.
Three-access atomicity violation is a special case of serializability violations, involving an event sequence tc . . . tr . . . tc′, such that:
1. tc and tc′, are in a transactional block of one thread, and tr is in another thread;
2. tc and tr have data conflict; and tr and tc′ have data conflict.
In practice these atomicity violations account for a large number of concurrency errors. Depending on whether each event is a read or write, there are eight combinations of the triplet tc, tr, tc′. While R-R-R, R-R-W, and W-R-R are serializable, the remaining five indicate atomicity violations.
Given the CTPρ and a transactional block trans=ti . . . tj, where ti . . . tj are events from the same thread in ρ, one can use the set PAV to denote all these potential atomicity violations. Conceptually, the set PAV can be computed by scanning the trace ρ once, and for each remote event trεCTPρ finding the two local events tc, tc′εtrans such that tc,tr,tc′
forms a non-serializable pattern.
Deciding whether an event sequence tc . . . tr . . . tc′ exists in the actual program execution is difficult. However, over-approximate algorithms can be used to prune away event triplets in PAV that are definitely infeasible. One method reduces the problem of checking (the existence of) tc . . . tr . . . tc′ to simultaneous reachability under nested locking. That is, does there exist an event tc″ such that (1) tc″ is within the same thread and is located between tc and tc′, and (2) tc″, tr are simultaneously reachable. Simultaneous reachability under nested locking can be checked by a compositional analysis based on locksets and acquisition histories. However, this analysis is over-approximate in that it ignores the data flow and synchronization primitives other than nested locks.
Sometimes, two events with data conflict may still be independent to each other, although they are conflict-dependent. A data conflict occurs when two events access the same variable and at least one of them is a write. The conflict-independence between two events is defined as: (1) executing one does not enable/disable another; and (2) they do not have data conflict. These conditions are necessary but insufficient for two events to be truly independent. Consider event t1: x=5 and event t2: x=5, for example. They have a data conflict but arc semantically independent. An independence relation may be more precisely defined, wherein two events t1,t2 are guarded independent with respect to a condition cG I and only if cG implies that the following properties:
then t2 is enabled in s if and only if t2 is enabled in s′: and
The guard cG is computed by statically traversing the CTP or program structure. For each event tεCTPρ let VRD(t) be the set of variables read by t, and VWR(t) be the set of variables, written by t. The potential conflict set between events t1 and t2 is defined as:
C
t
,t
t
=V
RD(t1)∩VWR(t2)∪VRD(t2)∩VWR(t1)∪VWR(t1)∩VWR(t2).
For programs with pointers (* p) and arrays (a[i]), the guarded independence relation RG is computed as follows:
1. when Ct t1, t2,true
to RG;
2. when Ct t1,t2,i≠j
to RG;
3. when Ct t1,t2,pi≠pj
to RG;
4. when Ct
This set of rules can be readily extended to handle a richer set of language constructs. Note that among these patterns, the syntactic conditions based on data conflict is able to catch the first pattern only. In symbolic search based on SMT/SAT solvers, the guarded independence relation is compactly encoded as constraints in the problem formulation, as described below.
Given the CTPρ and a set PAV of event triplets as potential atomicity violations, one can precisely check whether a potential violation exists in any feasible linearization of CTPρ. For this, a formula Φ is generated which is satisfiable if and only if there exists a feasible linearization of CTPρ that exposes the violation. Let Φ=ΦCTPΦAV, where ΦCTP
ΦVD
ΦPI
ΦAV.
Given a set PAV of potential violations, one may build formula ΦAV as follows;
1. Initialize ΦAV:=false;
2. For each event triplet tc,tr,tc′
εPAV, let
ΦAV:=ΦAV(HB(tc,tr)
HB(tr,tc′))
Recall that for two events t and t′, the constraint HB(t, t′) denotes that t must be executed before t′. Consider a model introducing for each event tεCTP a fresh integer variable O(t) that denotes its position in the linearization (execution time). A satisfiable assignment to ΦCTP
Recall that HB(t, t′) is defined as follows:
HB(t,t′):=O(t)<O(t′).
In SMT, HB(t, t′) corresponds to a constraint in special type of Integer Difference Logic (IDL), i.e. O(t)<O(t′) or simply O(t)−O(t′)≦−1. It is special in that the integer constant c in (x−y≦c), where x and y are integer variables, is always −1. Deciding this fragment of IDL is easier because consistency can be checked by a cycle detection algorithm in the constraint graph, which is O(|V|+|E|) where |V| and |E| are the number of nodes and edges, respectively, rather than by a negative-cycle detection algorithm, which has the best-known complexity of O(|V|×|E|).
Referring now to
For synchronization primitives such as locks, there are even more opportunities to further simplify the SAT formula. For example, if π1←π(l1, . . . , ln) denotes the value read from a lock variable l during lock acquire, then it is evident that that π1=0 must hold, since the lock need to be available for it to be acquired. This means that for parameters that are not 0, the constraint π1=li, where 1≦i≦n, evaluates to false. Due to the mutex lock semantics, for all 1≦i≦n, li=0 if and only if li is defined by a lock release.
The encoding of Φ=ΦCTPΦAV closely follows the definitions of CTP, feasible linearizations, and the semantics of it π-functions. The formula Φ is satisfiable if and only if there exists a feasible linearization of the CTP that violates the given atomicity property.
Let n be the number of events in CTPρ, let nπ be the number of shared variable uses, let lπ be the maximal number of parameters in any π-function, and let ltrans be the number of shared variable accesses in trans. One may also assume that each event in ρ accesses at most one shared variable. The size of (ΦPOΦVD
ΦPI
ΦAV) is O(n+n+nπ×lπ2+nπ×ltrans). Note that shared variable accesses in a concurrent program are often kept few and far in between, especially when compared to computations within threads, to minimize the synchronization overhead. This means that lπ, nπ, and ltrans are typically much smaller than n, which significantly reduces the formula size. In contrast, conventional bounded model checking (BMC) algorithms, if they were to be applied to a CTP, would need to unroll the transition relation of the CTP up to n times in order to cover all linearizations; at each step, the transition relation needed to encode all events of the CTP needs to be duplicated, leading to the formula size 0(n2). The BMC formula size cannot be easily reduced even if lπ, nπ, and ltrans are significantly smaller than n.
Sometimes, the existence of an atomicity violation leads the execution to take a branch that is not in the CTPρ. Consider the example in
t2: (π1=x1)g1
HB(t1,t2)
(HB(t5,t1)
HB(t2,t5))
(π1=x3)
g5
HB(t5,t2)
(HB(t1,t5)
HB(t2,t1))
t6: (π2=x1)g1
HB(t1,t6)
HB(t4,t1)
HB(t6,t4))
HB(t5, t1)
HB(t6, t5))
(π1=x2)
g4
HB(t4,t6)
HB(t1,t4)
HB(t6,t1))
HB(t5,t4)
HB(t6,t5))
(π2=x3)
g5
HB(t5,t6)
(HB(t1,t5)
HB(t6,t1))
(HB(t4,t5)
HB(t6,t4))
In trace t1t5t2 . . . , g4=false, HB(t4,t1)=HB(t6,t4)=false, and
HB(t4,t5)=HB(t6,t4)=false.
Such an execution trace ρ′ is not a feasible linearization of CTPρ, although it has exposed a real atomicity violation. The symbolic encoding of formula Φ is now extended to capture this type of erroneous trace prefix (as opposed to the entire erroneous trace). The symbolic encoding is extended as follows. Let event triplet {tc,tr,tc′} be the potential violation. Modify the construction of ΦPI (for the π-function in event t) as follows:
That is, if the atomicity violation bas already happened, as indicated by the current event, t (which uses this π-function) happens after tc′, then do not enforce any read-after-write consistency. The rest of the encoding algorithm remains the same.
The above technique generates an SMT formula such that the violation of an atomicity property exists if and only if the SMT formula is satisfiable. The algorithm does not report bogus errors (i.e., false positives) and, at the same time, achieves a better interleaving coverage than the previously existing explicit-state methods for predictive analysis.
Referring now in detail to the figures in which like numerals represent the same or similar elements and initially to
Embodiments may include a computer program product accessible from a computer-usable or computer-readable medium providing program code for use by or in connection with a computer or any instruction execution system. A computer-usable or computer readable medium may include any apparatus that stores, communicates, propagates, or transports the program for use by or in connection with the instruction execution system, apparatus, or device. The medium can be magnetic, optical, electronic, electromagnetic, infrared, or semiconductor system (or apparatus or device) or a propagation medium. The medium may include a computer-readable medium such as a semiconductor or solid state memory, magnetic tape, a removable computer diskette, a random access memory (RAM), a read-only memory (ROM), a rigid magnetic disk and an optical disk, etc.
Referring again to
In order to build a CSSA encoding for the CTP, first the program order ΦPO is encoded at block 706. Second, the variable definitions are encoded as ΦVD at block 708. Next the π-function is encoded as ΦPI at block 710. Finally the assertion property ΦPRP is encoded at block 712. These formulas are incorporated into a formula for the CTP ΦCTP at block 714. Determining whether there exists a feasible linearization that violates the assertion property is then a simple matter of determining the satisfiability of ΦCTP at block 716.
As an optional step, a context bound may be introduced at block 715, before determining the satisfiability of the formula. This context bound limits the number of context switches allowed in an interleaving. Given that many concurrency bugs may be exposed in interleavings with only a small number of context switches, the introduction of a context bound may lead to a significant increase in efficiency with only a modest decrease in accuracy.
Referring now to
Block 812 encodes the atomicity violations, as described above. By joining the formula for atomicity violations with the above encodings, a formula based on CSSA encoding that represents atomicity violations in the program is constructed at block 814. Finally, by determining the satisfiability of the formula at block 816, one may determine whether the program includes feasible linearizations that violate the atomicity property.
Referring now to
Embodiments according to the present principles are able to find bugs in a program under test more efficiently and more accurately than prior art systems, while still not over-predicting such violations. The present principles thereby allow for on-line violation detection and represent a significant advance over the prior art.
Having described preferred embodiments of a system and method (which are intended to be illustrative and not limiting), it is noted that modifications and variations can be made by persons skilled in the art in light of the above teachings. It is therefore to be understood that changes may be made in the particular embodiments disclosed which are within the scope and spirit of the invention as outlined by the appended claims. Having thus described aspects of the invention, with the details and particularity required by the patent laws, what is claimed and desired protected by Letters Patent is set forth in the appended claims.
This application claims priority to provisional application Ser. Nos. 61/174,128 filed on Apr. 30, 2009 and 61/247,281 filed on Sep. 30, 2009, both incorporated herein by reference.
Number | Date | Country | |
---|---|---|---|
61174128 | Apr 2009 | US | |
61247281 | Sep 2009 | US |