Formal Verification of Lock-Free Algorithms
Formal Verification of Lock-Free Algorithms
Formal Verification of Lock-Free Algorithms
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
2009 Ninth International Conference on Application <strong>of</strong> Concurrency to System Design<br />
<strong>Formal</strong><strong>Verification</strong><strong>of</strong> <strong>Lock</strong>-<strong>Free</strong><strong>Algorithms</strong><br />
(Invited Paper)<br />
Gerhard Schellhorn, Simon Bäumler<br />
Institute for S<strong>of</strong>tware and Systems Engineering<br />
University <strong>of</strong> Augsburg<br />
Germany<br />
{schellhorn, baeumler}@informatik.uni-augsburg.de<br />
Abstract<br />
The current trend towards multi-core processors has renewed<br />
the interest in the development and correctness <strong>of</strong><br />
concurrent algorithms.<br />
Most <strong>of</strong> these algorithms rely on locks to protect critical<br />
sections from unwanted interference. Recently a new class<br />
<strong>of</strong> nonblocking algorithms has been developed which do<br />
not rely on critical sections, but on atomic compare-and-set<br />
instructions. Such lock-free algorithms are less vulnerable<br />
to the typical problems <strong>of</strong> concurrent algorithms: deadlocks,<br />
livelocks and priority inversion. On the other hand, the lack<br />
<strong>of</strong> a uniform principle to rule out interference results in<br />
increased complexity. This makes it harder to understand<br />
these algorithms and to verify their correctness.<br />
The paper gives a simple example to demonstrate the<br />
central correctness criteria <strong>of</strong> linearizability (a safety property)<br />
and lock-freeness (a liveness property) for lock-free<br />
algorithms. It then sketches our approach to the modular<br />
verification <strong>of</strong> lock-free algorithms which uses relyguaranteereasoningandapowerfultemporallogictoderive<br />
refinement pro<strong>of</strong> obligations that can be verified with the<br />
interactive theorem prover KIV. Finally an overview over<br />
related work and techniques that are relevant to automate<br />
pro<strong>of</strong>s is given.<br />
1. Introduction<br />
As multi-core processor architectures have become standard,<br />
the study <strong>of</strong> concurrent algorithms is a current and<br />
important research topic. Among these, lock-free algorithms<br />
are a recently developed class <strong>of</strong> algorithms for concurrent<br />
access to data structures. They typically do not use locks and<br />
mutualexclusiveaccess,butinsteadrelyonatomiccompareand-swap-operations.<br />
Such operations are now implemented<br />
byallcommonprocessortypes,languagesupportisprovided<br />
e.g.byJavaandC#.AsimpleexampleisshowninSection2.<br />
<strong>Lock</strong>-free algorithms use an optimistic approach to cope<br />
with interference: all processes may attempt to read or<br />
modify a data structure at the same time. In case <strong>of</strong> conflicts,<br />
only one process will succeed while the others have to<br />
retry. If conflicts are rare, this avoids the bottleneck <strong>of</strong><br />
locks, which a priori restricts access to only one process.<br />
<strong>Lock</strong>-free algorithms also have the advantage <strong>of</strong> being less<br />
vulnerabletocommonproblemssuchasdeadlocks,livelocks<br />
and priority inversion. They have been used in operating<br />
system kernels [1], [2], [3], and also in computer games<br />
which need to exploit the performance gain <strong>of</strong> several<br />
processors [4].<br />
On the other hand these algorithms are more complex,<br />
since they do not use the universal principle <strong>of</strong> mutual<br />
exclusion. This makes it harder to assure their correctness<br />
by intuitive arguments. Therefore, a number <strong>of</strong> researchers<br />
have started to develop formal verification techniques that<br />
guarantee their correctness.<br />
Correctness <strong>of</strong> lock-free algorithms is typically based on<br />
verifying linearizability (for safety) as defined by Herlihy<br />
and Wing [5] and lock-freedom (for liveness), which are<br />
described in Section 3.<br />
Usually, reasoning over a concurrent system is hard and<br />
tedious work as all possible interleavings have to be considered.<br />
To have compositional pro<strong>of</strong>s the rely-guarantee<br />
paradigm is used, which reduces pro<strong>of</strong> <strong>of</strong> properties for<br />
a full system to properties <strong>of</strong> the components. Section 4<br />
gives an introduction, and describes our current approach.<br />
which used a compositionality theorem for refinement, to<br />
break down the linearizability condition to rely-guarantee<br />
pro<strong>of</strong> obligations for single processes. The approach is fully<br />
mechanized,usingtheexpressivetemporallogic[6],[7]built<br />
into the interactive theorem prover KIV [8]. KIV has been<br />
used to verify the compositionality theorem, as well as to<br />
verify the pro<strong>of</strong> obligations that result from the lock-free<br />
stack algorithm <strong>of</strong> Section 2, see [9].<br />
Finally, Section 5 gives an overview over related work.<br />
2. An example algorithm<br />
This section describes the lock-free stack implementation<br />
<strong>of</strong> Treiber [10], which is a standard example for lockfree<br />
algorithms. The example is used to illustrate the CAS<br />
instruction and the basic ideas <strong>of</strong> lock-free algorithms.<br />
For representation <strong>of</strong> the stack in the store, a linked list<br />
in the heap is used. Figure 1 shows an example <strong>of</strong> such<br />
a representation. Each node <strong>of</strong> the stack contains a .val<br />
1550-4808/09 $25.00 © 2009 IEEE<br />
DOI 10.1109/ACSD.2009.10<br />
13<br />
Authorized licensed use limited to: Technische Universitat Kaiserslautern. Downloaded on January 18, 2010 at 11:43 from IEEE Xplore. Restrictions apply.
Top<br />
a b c<br />
null<br />
Figure 1. Example <strong>of</strong> a Stack representation<br />
CAS(Old,New,G : Pointer){<br />
if G = Old<br />
then {G := New; return TRUE; }<br />
else return FALSE;<br />
}<br />
Figure 2. The atomic CAS operation<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
9<br />
10<br />
CPOP(Top : Pointer ) {<br />
repeat<br />
OTop := Top ;<br />
if OTop = null then<br />
return empty;<br />
ONxt := OTop .nxt ;<br />
Res := OTop .val ;<br />
until CAS(OTop , ONxt , Top );<br />
return Res<br />
}<br />
Figure 4. The pop operation<br />
field for the data value and a .nxt pointer to refer to the<br />
succeeding node. The end <strong>of</strong> the stack is marked with the<br />
null pointer. The entry point <strong>of</strong> the stack, i.e. the top cell,<br />
is referenced by the global variable Top.<br />
The push and pop operations consist <strong>of</strong> two phases. First,<br />
the needed data is prepared without changing the main<br />
data structure, e.g. storage is allocated or data are read. In<br />
a second phase, it is attempted to change the stack data<br />
structure in a single atomic step. If this atomic step fails<br />
(e.g. because the data structure has changed), the main data<br />
structure is not changed and the algorithm repeats phase<br />
one. To change the stack atomically, a compare-and-swap<br />
(CAS) command is used. Pseudocode for this operation is<br />
given in Figure 2. The CAS command compares a local<br />
pointer Old with a global pointer G, where Old is typically<br />
a value <strong>of</strong> G, that was read earlier by the process. If both<br />
pointers are identical, G is set to a new value New and<br />
the CAS command succeeds. If the values are different, G<br />
is left unchanged and the CAS command fails. All usual<br />
multi-core processors support atomic CAS instructions (e.g.<br />
CMPXCHG on x86 processors) or equivalent instructions.<br />
The push algorithm is depicted in Figure 3. Parameters <strong>of</strong><br />
CPUSH are the value input value V, which should be placed<br />
on top <strong>of</strong> the stack, and a reference to the Top pointer.<br />
Since each invocation <strong>of</strong> CPUSH runs in parallel with calls<br />
to CPUSH or CPOP from other processes, Top may change<br />
at any time while the algorithm is executed.<br />
Variables UNew and UTop are local pointer variables.<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
CPUSH(V : Data, Top : Pointer){<br />
UNew := new(Node);<br />
UNew .val := V;<br />
repeat {<br />
UTop := Top ;<br />
UNew .nxt := UTop ;<br />
} until CAS(UTop , UNew , Top )<br />
}<br />
Figure 3. The push operation<br />
The algorithm starts by allocating a new cell on the heap<br />
and writing the input value V into the newly allocated node<br />
(line 2 and 3). After that the algorithm loops, as long as the<br />
insertion <strong>of</strong> the new cell in the stack fails (line 4 to 7). Inside<br />
the loop the pointer <strong>of</strong> the current top cell is copied to the<br />
local variable UTop and the .nxt-pointer <strong>of</strong> the previously<br />
allocated cell is set to the current top cell (line 5 and 6).<br />
Finally, the algorithms attempts to add the new data value<br />
to the top <strong>of</strong> the stack data structure by a CAS operation<br />
(line 7). If the current Top is still the same as it was in line<br />
5, the previously allocated cell UNew contains the correct<br />
.nxt -pointer and Top can be set to UNew . If the top <strong>of</strong><br />
stack was changed by another push or pop process in the<br />
meantime, the CAS operation fails and the loop is reiterated.<br />
The pop algorithm, shown in Figure 4, is very similar.<br />
The only difference is that it has to be checked, whether the<br />
stack is empty or not (line 4). In case <strong>of</strong> an empty stack, a<br />
special value empty is returned.<br />
3. Linearizability and <strong>Lock</strong>-<strong>Free</strong>dom<br />
The usual correctness criteria for lock-free algorithms are<br />
linearizability for safety and lock-freedom for liveness.<br />
Linearizability was defined by Herlihy & Wing [5]. It<br />
is based on the visible inputs and outputs <strong>of</strong> processes.<br />
<strong>Formal</strong>ly a history is defined as a list <strong>of</strong> invoke and return<br />
events. An invoke event inv(p,op,in) is added to the history,<br />
when process p invokes operation op with input in. Similarly<br />
a return event ret(p,op,out) is added when process p returns<br />
with output out from operation op. In our example a possible<br />
history created by two processes p and q is<br />
H = [inv(p,push,3), inv(q,push,4), ret(p,push,−),<br />
ret(q,push,−), inv(q,pop,−), ret(q,pop,4)]<br />
where the − indicates no input/output. A history is linearizable<br />
if it can be reordered to a sequential history, where each<br />
invoke is directly followed by the corresponding return. The<br />
reordering must respect the order that was present in the<br />
original history: an operation whose invoke happened after<br />
the return <strong>of</strong> another operation, must end up in the same<br />
14<br />
Authorized licensed use limited to: Technische Universitat Kaiserslautern. Downloaded on January 18, 2010 at 11:43 from IEEE Xplore. Restrictions apply.
order in the sequential history. For the history H above two<br />
linearizations are possible.<br />
[inv(q,push,4), ret(q,push,−), inv(p,push,3),<br />
ret(p,push,−), inv(q,pop,−), ret(q,pop,4)].<br />
and<br />
[inv(p,push,3), ret(p,push,−), inv(q,push,4),<br />
ret(q,push,−), inv(q,pop,−), ret(q,pop,4)]<br />
The first history is not compatible with the semantics <strong>of</strong><br />
a stack (if 3 was pushed last, then the pop should return<br />
3, not 4), but the second is. Therefore H is linearizable. A<br />
concurrent implementation <strong>of</strong> a data type is linearizable, if<br />
every history it creates is linearizable.<br />
The definition given is difficult to use for verification.<br />
Therefore all work we are aware <strong>of</strong> has used the following<br />
simpler requirement: in between the invoke and return <strong>of</strong><br />
every operation a linearization point must exist, such that<br />
the operation can be thought <strong>of</strong> as executing atomically at<br />
that point. In simple examples, the linearization point can be<br />
identified as a specific line <strong>of</strong> the source code: for the push<br />
operation the CAS instruction is the linearization point.<br />
That the original definition is difficult to use has already<br />
been noted in the original work [5], and an alternative<br />
definition based on so-called possibilities is given that is<br />
closer to the simple requirement. In [11] we have formalized<br />
the original definition as well as possibilities, and have<br />
formally proved that they are equivalent.<br />
Linearizability can be viewed as a correctness criterion<br />
for refinement. In the example <strong>of</strong> the previous section,<br />
stack operations are refined by programs working on pointer<br />
structures. In [12] and [11] we have shown, that it is possible<br />
to view linearizability as an instance <strong>of</strong> non-atomic data<br />
refinement. [12] is based on encoding the control structure<br />
<strong>of</strong> the operations in CSP. Single steps <strong>of</strong> the algorithm are<br />
defined as Z operations. [11] replaces the CSP control structure<br />
with program counters, which allowed to mechanize the<br />
pro<strong>of</strong>swithKIV.Interleavingisrealizedbyusingpromotion.<br />
To verify linearizability [11] and [13] give modular pro<strong>of</strong><br />
obligations, that reduce the problem to two processes by<br />
exploiting their symmetry. The stack algorithm is used as a<br />
running example. The resulting pro<strong>of</strong> obligations can be verified<br />
using predicate logic alone. They resemble the Owicki-<br />
Gries technique [14] for proving program correctness.<br />
Linearizability guarantees that operations will return correct<br />
results, but not their termination. Indeed, termination<br />
<strong>of</strong> a single push algorithm (and therefore liveness <strong>of</strong> the<br />
process) cannot be guaranteed, since it is possible that each<br />
loopiterationisinterceptedbyanotherpushorpopoperation<br />
that modifies the stack and causes the CAS operation to fail.<br />
The algorithm does not satisfy the Wait-<strong>Free</strong>dom criterion,<br />
that requires that each operation must finish within a finite<br />
number <strong>of</strong> (his own) steps. This is a disadvantage compared<br />
to algorithms using locks which usually satisfy waitfreedom.<br />
Instead lock-free algorithms satisfy the weaker<br />
criterion <strong>of</strong> <strong>Lock</strong>-<strong>Free</strong>dom which only requires, that when<br />
several operations are currently running, at least one <strong>of</strong><br />
them will terminate. This implies that as soon as no new<br />
operations are started any more, all running operations will<br />
eventually terminate. For the stack example the criterion is<br />
satisfied: if a push or pop operation must retry due to a failed<br />
CAS, this was caused by another push or pop operation, that<br />
successfully modified the stack and therefore terminated.<br />
4. Current Work<br />
Acommon technique toavoid pro<strong>of</strong>s thathave toconsider<br />
theconcurrentsystemasawholeiscompositionalreasoning,<br />
which was first formulated in [15] by Dijkstra. The idea <strong>of</strong><br />
this technique is to split the system into several subcomponents.<br />
Then, the overall property is proved by combining<br />
properties <strong>of</strong> the subcomponents.<br />
A common compositional pro<strong>of</strong> technique is the relyguarantee<br />
paradigm, which was introduced by Jones [16]<br />
and by Misra and Chandy [17] (under the name assumptioncommitment).<br />
The basic idea <strong>of</strong> this paradigm is, that<br />
each component can make specific assumptions about its<br />
environment in order to guarantee a specific behavior.<br />
Usually a rely-guarantee technique provides a theorem,<br />
that specifies in a number <strong>of</strong> pro<strong>of</strong> obligations how the<br />
various assumptions and guarantees have to be connected<br />
in order to show the property for the overall system. Ideally,<br />
these pro<strong>of</strong> obligations consider only single subcomponents<br />
and are <strong>of</strong> feasible size. Most rely-guarantee techniques use<br />
either a semantic framework or temporal logics. Examples<br />
can be found e.g. in [18], [19], [20].<br />
Our own approach uses an expressive temporal logic [7],<br />
[6] that is a variant <strong>of</strong> interval temporal logic (ITL, [21]).<br />
ITL extends linear temporal logic (LTL) by considering<br />
infinite as well as finite runs (called intervals). Therefore<br />
termination is expressible. The semantics <strong>of</strong> a formula is a<br />
set <strong>of</strong> intervals, which makes the formula valid. Sequential<br />
as well as parallel programs are just specific formulas, since<br />
their semantics is also a set <strong>of</strong> intervals (the set <strong>of</strong> possible<br />
runs). This makes it possible to mix programs and formulas<br />
freely: components can be abstracted to their properties.<br />
KIV supports deduction for interleaved programs (used to<br />
model the stack example), as well as asynchronous parallel<br />
programs and statecharts [22], [23].<br />
Since programs are explicit formulas, there is no need to<br />
encode algorithms such as the push and pop algorithm into<br />
transition systems, as most other approaches (e.g. TLA [24])<br />
do. Instead our deduction approach extends the well-known<br />
principle <strong>of</strong> symbolic execution and induction [25] to parallel<br />
programs.<br />
Using this approach we have mechanized a compositionality<br />
theorem for linearizability as a special case <strong>of</strong> trace<br />
refinement. We also verified the resulting pro<strong>of</strong> obligations<br />
for the stack example [26],[9] from Section 2. In a master’s<br />
thesisone<strong>of</strong>ourstudents[27]hasmechanizedlinearizability<br />
15<br />
Authorized licensed use limited to: Technische Universitat Kaiserslautern. Downloaded on January 18, 2010 at 11:43 from IEEE Xplore. Restrictions apply.
<strong>of</strong> the slightly optimized version [28] <strong>of</strong> Michael and Scott’s<br />
queue [1] implementation. This work also proves lockfreedom<br />
<strong>of</strong> the queue.<br />
5. Related Work<br />
Our approach is based on an expressive temporal logic,<br />
which is built into the theorem prover. In this sense it is similar<br />
to the formalization <strong>of</strong> TLA [24] in Isabelle [29] and to<br />
the STEP prover [30] or to + CAL [31]. All these approaches<br />
require to encode programs to a normal form <strong>of</strong> transition<br />
systems for deduction. Although this is not a drawback for<br />
automated pro<strong>of</strong>s using model checking, we found it very<br />
unintuitive to reason about program counters in interactive<br />
verification. Therefore we avoid such an encoding.<br />
An alternative to using temporal logic and rely-guarantee<br />
reasoning directly, is to use an encoding into higher-order<br />
logic (e.g. [32], [33] or [34]). This has the advantage that<br />
soundness <strong>of</strong> the logic can be reduced to the soundness<br />
<strong>of</strong> higher-order logic, but it requires to encode a lot <strong>of</strong><br />
the semantics (we are not aware <strong>of</strong> encodings that support<br />
a full abstract programming language with local variables,<br />
recursion, blocking, and interleaving as KIV does).<br />
<strong>Verification</strong> <strong>of</strong> lock-free algorithms is currently an active<br />
research topic. Various algorithms have been proved to be<br />
linearizable, e.g. algorithms working on a global queue [28],<br />
[35], a lazy caching algorithm [36] or a concurrent garbage<br />
collection [37].<br />
The algorithm considered here was taken from Colvin and<br />
Groves [28], [38], who have given a correctness pro<strong>of</strong> using<br />
IO automata and the theorem prover PVS. We have only<br />
studied the core algorithm, their work discusses extending<br />
the algorithm with elimination arrays, and adds modification<br />
counts to avoid the ABA problem. In contrast to this formal<br />
pro<strong>of</strong> our pro<strong>of</strong> is not monolithic, and does not require to<br />
encode programs as automata using program counters.<br />
Recent work by the same authors [39], [40] discusses<br />
incremental development <strong>of</strong> the algorithm using refinement<br />
calculus and programs very similar to ours. The resulting<br />
steps are rather intuitive for explaining the ideas and possible<br />
variations, but have not been mechanized. Again this<br />
work also discusses various extensions and variations <strong>of</strong> the<br />
algorithm. Colvin and Dongol [41] have also developed an<br />
mechanized approach to verify lock-freeness.<br />
In [42], Vafeiadis et. al. describe a rely-guarantee approach<br />
for linearizability, that is applied informally on an<br />
implementation <strong>of</strong> sets using fine-grained locking. [43],<br />
[44], [45] mechanizes verification <strong>of</strong> the resulting pro<strong>of</strong><br />
obligations (correctness <strong>of</strong> the pro<strong>of</strong> obligations is argued<br />
on the semantic level). [46] considers lock-freedom. In<br />
contrast to our approach, the approach mixes the abstract<br />
and concrete layer, by calling the abstract operation at the<br />
linearization point within the concrete code. We have not<br />
used this idea, since it is incompatible with the idea <strong>of</strong><br />
developing concrete programs incrementally from abstract<br />
specifications. Nevertheless the technique allows to use a<br />
standard rely-guarantee theorem for a single program. The<br />
approach is fully automatic on a number <strong>of</strong> examples. It uses<br />
an impressive range <strong>of</strong> specialized automation techniques:<br />
separation logic [47] is used to reason over pointer structures,<br />
the distinction between local (i.e. modifiable only by<br />
one process) and global references is encoded as boxed and<br />
unboxed formulas. A variant <strong>of</strong> the abstraction and invariant<br />
generation technique proposed by [48] is used to deal with<br />
loops.<br />
Fully automatic approaches based on static analysis are<br />
given by Amit et. al. in [49] and by Berdine et. al. in [50].<br />
They also specialize on reasoning over pointer structures.<br />
6. Conclusion<br />
Our work aims to define a generic, modular approach<br />
that allows mechanized, interactive verification <strong>of</strong> lockfree<br />
and other concurrent algorithms. The approach uses<br />
an expressive temporal logic to formalize compositionality<br />
theorems for rely-guarantee reasoning and refinement. The<br />
approach has been applied to simple examples like the one<br />
shown in this paper.<br />
Current work is to use the approach on more complex<br />
examples and to integrate specialized deduction techniques<br />
that help to automate pro<strong>of</strong>s into our generic framework.<br />
References<br />
[1] M. M. Michael and M. L. Scott, “Nonblocking algorithms<br />
and preemption-safe locking on multiprogrammed shared —<br />
memory multiprocessors,” Journal <strong>of</strong> Parallel and Distributed<br />
Computing, vol. 51, no. 1, pp. 1–26, 1998.<br />
[2] M. M. Michael, “High performance dynamic lock-free hash<br />
tables and list-based sets,” in SPAA 2002. ACM, 2002, pp.<br />
73–82.<br />
[3] M. M. Michael, “Practical lock-free and wait-free ll/sc/vl<br />
implementations using 64-bit cas,” in DISC 04, vol. 3274.<br />
Springer LNCS, 2004.<br />
[4] T. Leonard, “Dragged kicking and screaming:<br />
Source multicore,” Talk at the Game Developers<br />
Conference, San Francisco, March 2007. [Online].<br />
Available: www.valves<strong>of</strong>tware.com/publications/2007/<br />
GDC2007 SourceMulticore.pdf<br />
[5] M. Herlihy and J. M. Wing, “Linearizability: A correctness<br />
condition for concurrent objects,” ACM Transactions on Programming<br />
Languages and Systems, vol. 12, no. 3, pp. 463–<br />
492, 1990.<br />
[6] M. Balser, “Verifying concurrent system with symbolic execution<br />
– temporal reasoning is symbolic execution with a<br />
little induction,” Ph.D. dissertation, University <strong>of</strong> Augsburg,<br />
Augsburg, Germany, 2005.<br />
16<br />
Authorized licensed use limited to: Technische Universitat Kaiserslautern. Downloaded on January 18, 2010 at 11:43 from IEEE Xplore. Restrictions apply.
[7] M. Balser, S. Bäumler, W. Reif, and G. Schellhorn, “Interactive<br />
verification <strong>of</strong> concurrent systems using symbolic<br />
execution,” in Proceedings <strong>of</strong> 7th International Workshop <strong>of</strong><br />
Implementation <strong>of</strong> Logics (IWIL 08), 2008.<br />
[8] W.Reif,G.Schellhorn,K.Stenzel,andM.Balser,“Structured<br />
specifications and interactive pro<strong>of</strong>s with KIV,” in Automated<br />
Deduction—A Basis for Applications, W. Bibel and<br />
P. Schmitt, Eds. Dordrecht: Kluwer Academic Publishers,<br />
1998, vol. II: Systems and Implementation Techniques, ch. 1:<br />
Interactive Theorem Proving, pp. 13 – 39.<br />
[9] S. Bäumler, G. Schellhorn, M. Balser, and W. Reif, “Proving<br />
linearizability with temporal logic,” <strong>Formal</strong> Aspects <strong>of</strong> Computing<br />
(FAC), 2009, submitted.<br />
[10] R. K. Treiber, “System programming: Coping with parallelism,”<br />
IBM Almaden Research Center, Tech. Rep. RJ 5118,<br />
1986.<br />
[11] J. Derrick, G. Schellhorn, and H. Wehrheim, “Mechanising<br />
a correctness pro<strong>of</strong> for a lock-free concurrent stack,” in<br />
Prooceedings <strong>of</strong> FMOODS 2008, Oslo, ser. LNCS, vol. 5051,<br />
2008, pp. 78–95.<br />
[12] J. Derrick, G. Schellhorn, and H. Wehrheim, “Proving linearizabilty<br />
via non-atomic refinement,” in Proceedings <strong>of</strong> the<br />
International Conference on integrated formal methods (iFM)<br />
2007, ser. LNCS, J. G. J. Davies, Ed., vol. 4591. Springer,<br />
2007, pp. 195–214.<br />
[13] J. Derrick, G. Schellhorn, and H. Wehrheim, “Mechanically<br />
verified pro<strong>of</strong> obligations for linearizability,” ACM transactions<br />
on Programming Languages and Systems, 2009, (submitted).<br />
[14] S. S. Owicki and D. Gries, “An Axiomatic Pro<strong>of</strong> Technique<br />
for Parallel Programs I,” Acta Inf., vol. 6, pp. 319–340, 1976.<br />
[15] E.W.Dijkstra,“Solution<strong>of</strong>aprobleminconcurrentprogramming<br />
control,” Commun. ACM, vol. 8, no. 9, p. 569, 1965.<br />
[16] C. B. Jones, “Tentative steps toward a development method<br />
for interfering programs,” ACM Trans. Program. Lang. Syst.,<br />
vol. 5, no. 4, pp. 596–619, 1983.<br />
[17] J. Misra and K. Chandi, “Pro<strong>of</strong>s <strong>of</strong> networks <strong>of</strong> processes,”<br />
IEEE Transactions <strong>of</strong> S<strong>of</strong>tware Engineering, 1981.<br />
[18] W.-P. de Roever et al., Concurrency <strong>Verification</strong>: Introduction<br />
to Compositional and Noncompositional Methods. Cambridge<br />
University Press, 2001.<br />
[19] M. Abadi and L. Lamport, “Conjoining specifications,” ACM<br />
Transactions on Programming Languages and Systems, 1995.<br />
[20] A. Cau and P. Collette, “Parallel composition <strong>of</strong> assumptioncommitment<br />
specifications: A unifying approach for shared<br />
variable and distributed message passing concurrency,” Acta<br />
Informatica, vol. 33, no. 2, pp. 153–176, 1996.<br />
[21] B. Moszkowski, Executing Temporal Logic Programs.<br />
Cambridge: Cambridge University Press, 1986. [Online].<br />
Available: citeseer.ist.psu.edu/moszkowski86executing.html<br />
[22] S. Bäumler, M. Balser, A. Knapp, W. Reif, and A. Thums,<br />
“Interactive verification <strong>of</strong> uml state machines,” in <strong>Formal</strong><br />
Methods and S<strong>of</strong>tware Engineering, ser. LNCS, no. 3308.<br />
Springer, 2004.<br />
[23] A. Thums, F. Ortmeier, W.Reif, and G. Schellhorn, “Interactive<br />
verification <strong>of</strong> statecharts,” in Integration <strong>of</strong> S<strong>of</strong>tware<br />
Specification Techniques for Applications in Engineering,<br />
H. Ehrig, Ed. Springer LNCS 3147, 2004, pp. 355 – 373.<br />
[24] L. Lamport, “The temporal logic <strong>of</strong> actions,” ACM Transactions<br />
on Programming Languages and Systems, vol. 16, no. 3,<br />
pp. 872–923, May 1994.<br />
[25] R. M. Burstall, “Program proving as hand simulation with<br />
a little induction,” Information processing 74, pp. 309–312,<br />
1974.<br />
[26] S. Bäumler, G. Schellhorn, M. Balser, and<br />
W. Reif, “Proving linearizability with temporal<br />
logic,” Universität Augsburg, Technical Report<br />
2008-19, 2008, uRL: http://www.informatik.uniaugsburg.de/lehrstuehle/swt/se/publications/.<br />
[27] B. T<strong>of</strong>an, “Correctness Analysis Of <strong>Lock</strong>-<strong>Free</strong> <strong>Algorithms</strong><br />
For Multi-Core Architectures,” Diplomarbeit, Universität<br />
Augsburg, 2009.<br />
[28] S. Doherty, L. Groves, V. Luchangco, and M. Moir, “<strong>Formal</strong><br />
verification <strong>of</strong> a practical lock-free queue algorithm,” in<br />
FORTE 2004, ser. LNCS, vol. 3235, 2004, pp. 97–114.<br />
[29] S. Merz, “Mechanizing TLA in Isabelle,” in Workshop on<br />
<strong>Verification</strong> in New Orientations, R. Rodošek, Ed. Maribor:<br />
Univ. <strong>of</strong> Maribor, Jul. 1995, pp. 54–74.<br />
[30] N. S. Bjørner, A. Browne, M. A. C. On, B. Finkbeiner,<br />
H. B. Sipma, and T. Uribe, “Verifying temporal properties<br />
<strong>of</strong> reactive systems: A step tutorial,” in <strong>Formal</strong> Methods in<br />
System Design, 1999, p. 2000.<br />
[31] L. Lamport, “The +cal algorithm language,” Micros<strong>of</strong>t,<br />
Tech. Rep., 2006. [Online]. Available:<br />
http://research.micros<strong>of</strong>t.com/users/lamport/pubs/pubs.html<br />
[32] S. Owre, S. Rajan, J. M. Rushby, N. Shankar, and M. Srivas,<br />
“PVS: Combining specification, pro<strong>of</strong> checking, and model<br />
checking,” in Computer Aided <strong>Verification</strong> (CAV), R. Alur and<br />
T. A. Henzinger, Eds. Springer LNCS 1102, 1996.<br />
[33] S. Kalvala, “A formulation <strong>of</strong> TLA in isabelle,”<br />
http://www.research.digital.com/SRC/personal/lamport/<br />
tla/tla.html, June 1995.<br />
[34] L. Nieto, “The rely-guarantee method in isabelle /hol,” in European<br />
Symposium on Programming (ESOP’03), ser. LNCS,<br />
P. Degano, Ed., vol. 2618. Springer, 2003, pp. 348–362.<br />
[35] J.-R. Abrial and D. Cansell, “<strong>Formal</strong> Construction <strong>of</strong> a Nonblocking<br />
Concurrent Queue Algorithm (a Case Study in<br />
Atomicity),” Journal <strong>of</strong> Universal Computer Science, vol. 11,<br />
no. 5, pp. 744–770, 2005.<br />
[36] W. H. Hesselink, “Refinement verification <strong>of</strong> the lazy caching<br />
algorithm,” Acta Inf., vol. 43, no. 3, pp. 195–222, 2006.<br />
17<br />
Authorized licensed use limited to: Technische Universitat Kaiserslautern. Downloaded on January 18, 2010 at 11:43 from IEEE Xplore. Restrictions apply.
[37] H. Gao, J.F. Groote, and W. H. Hesselink,“<strong>Lock</strong>-free parallel<br />
and concurrent garbage collection by mark&sweep,” Sci.<br />
Comput. Program., vol. 64, no. 3, pp. 341–374, 2007.<br />
[38] R. Colvin, S. Doherty, and L. Groves, “Verifying concurrent<br />
data structures by simulation,” ENTCS, vol. 137, pp. 93–110,<br />
2005.<br />
[39] L. Groves and R. Colvin, “Derivation <strong>of</strong> a scalable lock-free<br />
stack algorithm,” Electron. Notes Theor. Comput. Sci., vol.<br />
187, pp. 55–74, 2007.<br />
[40] L. Groves and R. Colvin, “Trace-based derivation <strong>of</strong> a scalable<br />
lock-free stack algorithm,” <strong>Formal</strong> Aspects <strong>of</strong> Computing<br />
(FAC), vol. 21, no. 1–2, pp. 187–223, 2009.<br />
[41] R. Colvin and B. Dongol, “A general technique for proving<br />
lock-freedom,” Sci. Comput. Program., vol. 74, no. 3, pp.<br />
143–165, 2009.<br />
[42] V. Vafeiadis, M. Herlihy, T. Hoare, and M. Shapiro, “Proving<br />
correctness <strong>of</strong> highly-concurrent linearisable objects,” in<br />
PPoPP ’06: Proceedings <strong>of</strong> the eleventh ACM SIGPLAN symposium<br />
on Principles and practice <strong>of</strong> parallel programming.<br />
New York, NY, USA: ACM, 2006, pp. 129–136.<br />
[43] C. Calcagno, M. J. Parkinson, and V. Vafeiadis, “Modular<br />
safety checking for fine-grained concurrency,” in SAS, ser.<br />
Lecture Notes in Computer Science, H. R. Nielson and<br />
G. Filé, Eds., vol. 4634. Springer, 2007, pp. 233–248.<br />
[44] V. Vafeiadis and M. J. Parkinson, “A marriage <strong>of</strong><br />
rely/guarantee and separation logic,” in CONCUR, ser. Lecture<br />
Notes in Computer Science, L. Caires and V. T. Vasconcelos,<br />
Eds., vol. 4703. Springer, 2007, pp. 256–271.<br />
[45] V. Vafeiadis, “Shape-value abstraction for verifying linearizability,”<br />
in Proceedings VMCAI 2009, ser. LNCS, vol. 5403.<br />
Springer, 2009.<br />
[46] A. Gotsman, B. Cook, M. Parkinson, and V. Vafeiadis, “Proving<br />
that nonblocking algorithms don’t block,” in Principles <strong>of</strong><br />
Programming Languages. ACM, 2009, pp. 16–28.<br />
[47] J. C. Reynolds, “Separation logic: A logic for shared mutable<br />
data structures,” in LICS ’02: Proceedings <strong>of</strong> the 17th Annual<br />
IEEE Symposium on Logic in Computer Science. Washington,<br />
DC, USA: IEEE Computer Society, 2002, pp. 55–74.<br />
[48] D. Distefano, P. O’Hearn, and H. Yang, “A local shape<br />
analysis based on separation logic,” in TACAS, vol. 3920.<br />
Springer, 2006, pp. 287–302.<br />
[49] D. Amit, N. Rinetzky, T. W. Reps, M. Sagiv, and E. Yahav,<br />
“Comparison under abstraction for verifying linearizability,”<br />
in CAV, ser. Lecture Notes in Computer Science, W. Damm<br />
and H. Hermanns, Eds., vol. 4590. Springer, 2007, pp. 477–<br />
490.<br />
[50] J. Berdine, T. Lev-Ami, R. Manevich, G. Ramalingam, and<br />
M. Sagiv, “Thread quantification for concurrent shape analysis,”<br />
in CAV’08: 20th International Conference on Computer<br />
Aided <strong>Verification</strong>. Springer, 2008.<br />
18<br />
Authorized licensed use limited to: Technische Universitat Kaiserslautern. Downloaded on January 18, 2010 at 11:43 from IEEE Xplore. Restrictions apply.