22.11.2014 Views

Formal Verification of Lock-Free Algorithms

Formal Verification of Lock-Free Algorithms

Formal Verification of Lock-Free Algorithms

SHOW MORE
SHOW LESS

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.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!