Tải bản đầy đủ (.pdf) (518 trang)

Static analysis 23rd international symposium, SAS 2016

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (20.44 MB, 518 trang )

LNCS 9837

ARCoSS

Xavier Rival (Ed.)

Static Analysis
23rd International Symposium, SAS 2016
Edinburgh, UK, September 8–10, 2016
Proceedings

123


Lecture Notes in Computer Science

9837

Commenced Publication in 1973
Founding and Former Series Editors:
Gerhard Goos, Juris Hartmanis, and Jan van Leeuwen

Editorial Board
David Hutchison, UK
Josef Kittler, UK
Friedemann Mattern, Switzerland
Moni Naor, Israel
Bernhard Steffen, Germany
Doug Tygar, USA

Takeo Kanade, USA


Jon M. Kleinberg, USA
John C. Mitchell, USA
C. Pandu Rangan, India
Demetri Terzopoulos, USA
Gerhard Weikum, Germany

Advanced Research in Computing and Software Science
Subline of Lecture Notes in Computer Science
Subline Series Editors
Giorgio Ausiello, University of Rome ‘La Sapienza’, Italy
Vladimiro Sassone, University of Southampton, UK

Subline Advisory Board
Susanne Albers, TU Munich, Germany
Benjamin C. Pierce, University of Pennsylvania, USA
Bernhard Steffen, University of Dortmund, Germany
Deng Xiaotie, City University of Hong Kong
Jeannette M. Wing, Microsoft Research, Redmond, WA, USA


More information about this series at />

Xavier Rival (Ed.)

Static Analysis
23rd International Symposium, SAS 2016
Edinburgh, UK, September 8–10, 2016
Proceedings

123



Editor
Xavier Rival
Ecole Normale Supérieure
Paris
France

ISSN 0302-9743
ISSN 1611-3349 (electronic)
Lecture Notes in Computer Science
ISBN 978-3-662-53412-0
ISBN 978-3-662-53413-7 (eBook)
DOI 10.1007/978-3-662-53413-7
Library of Congress Control Number: 2016950412
LNCS Sublibrary: SL2 – Programming and Software Engineering
© Springer-Verlag GmbH Germany 2016
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication
does not imply, even in the absence of a specific statement, that such names are exempt from the relevant
protective laws and regulations and therefore free for general use.
The publisher, the authors and the editors are safe to assume that the advice and information in this book are
believed to be true and accurate at the date of publication. Neither the publisher nor the authors or the editors
give a warranty, express or implied, with respect to the material contained herein or for any errors or
omissions that may have been made.
Printed on acid-free paper

This Springer imprint is published by Springer Nature
The registered company is Springer-Verlag GmbH Berlin Heidelberg


Preface

Static Analysis is increasingly recognized as a fundamental tool for program verification, bug detection, compiler optimization, program understanding, and software
maintenance. The series of Static Analysis Symposia has served as the primary venue
for the presentation of theoretical, practical, and applicational advances in the area.
Previous symposia were held in Saint-Malo, Munich, Seattle, Deauville, Venice,
Perpignan, Los Angeles, Valencia, Kongens Lyngby, Seoul, London, Verona, San
Diego, Madrid, Paris, Santa Barbara, Pisa, Aachen, Glasgow, and Namur. This volume
contains the papers presented at SAS 2016, the 23rd International Static Analysis
Symposium. The conference was held on September 8–10, 2016 in Edinburgh, UK.
The conference received 55 submissions, each of which was reviewed by at least
three Program Committee members. The Program Committee decided to accept 21
papers, which appear in this volume. As in previous years, authors of SAS submissions
were able to submit a virtual machine image with artifacts or evaluations presented in
the paper. In accordance with this, 19 submissions came with an artifact. Artifacts were
used as an additional source of information during the evaluation of the submissions.
The Program Committee also invited four leading researchers to present invited
talks: Jade Alglave (Microsoft Research UK), Thomas A. Henzinger (IST Austria,
Klosterneuburg, Austria), Fausto Spoto (University of Verona, Italy), and Martin
Vechev (ETH Zurich, Switzerland). We deeply thank them for accepting the
invitations.
SAS 2016 was collocated with the Symposium on Logic-Based Program Synthesis
and Transformation (LOPSTR 2016) and the Symposium on Principles and Practice of
Declarative Programming (PPDP 2016) and it featured five associated workshops: the
Workshop on Static Analysis and Systems Biology (SASB 2016) and the Workshop on
Tools for Automatic Program Analysis (TAPAS 2016) were held before SAS, on the

7th of September; the Numerical and Symbolic Abstract Domains Workshop (NSAD
2016), the Workshop on Static Analysis of Concurrent Software, and REPS AT SIXTY
were held after SAS, on the 11th of September.
The work of the Program Committee and the editorial process were greatly facilitated by the EasyChair conference management system. We are grateful to Springer for
publishing these proceedings, as they have done for all SAS meetings since 1993.
Many people contributed to the success of SAS 2015. We would first like to thank
the members of the Program Committee, who worked hard at carefully reviewing
papers, holding extensive discussions during the on-line Program Committee meeting,
and making final selections of accepted papers and invited speakers. We would also
like to thank the additional referees enlisted by Program Committee members. We
thank the Steering Committee members for their advice. A special acknowledgment


VI

Preface

goes to James Cheney for leading the local organization of the conference and to the
University of Edinburgh for hosting the Conference. Finally, we would like to thank
our sponsors: Facebook, Fondation de l’ENS, and Springer.
July 2016

Xavier Rival


Organization

Program Committee
Bor-Yuh Evan Chang
Patrick Cousot

Vijay D’Silva
Javier Esparza
Jérôme Feret
Pierre Ganty
Roberto Giacobazzi
Atsushi Igarashi
Andy King
Francesco Logozzo
Roman Manevich
Matthieu Martel
Jan Midtgaard
Ana Milanova
Mayur Naik
Francesco Ranzato
Xavier Rival
Sukyoung Ryu
Francesca Scozzari
Caterina Urban
Bow-Yaw Wang
Kwangkeun Yi

University of Colorado Boulder, USA
New York University, USA
Google Inc., USA
Technical University of Munich, Germany
Inria/CNRS/Ecole Normale Supérieure, France
IMDEA Software Institute, Spain
University of Verona, Italy
Kyoto University, Japan
University of Kent, UK

Facebook, USA
Ben-Gurion University of the Negev, Israel
Université de Perpignan Via Domitia, France
Technical University of Denmark, Denmark
Rensselaer Polytechnic Institute, USA
Georgia Institute of Technology, USA
University of Padua, Italy
Inria/CNRS/Ecole Normale Supérieure, France
KAIST, South Korea
Università di Chieti-Pescara, Italy
ETH Zürich, Switzerland
Academia Sinica, Taiwan
Seoul National University, South Korea

Additional Reviewers
Adje, Assale
Amato, Gianluca
Brutschy, Lucas
Chapoutot, Alexandre
Chawdhary, Aziem
Chen, Yu-Fang
Cho, Sungkeun
Dogadov, Boris
Garoche, Pierre-Loic
Haller, Leopold
Heo, Kihong

Hur, Chung-Kil
Jourdan, Jacques-Henri
Kang, Jeehoon

Kong, Soonho
Lee, Woosuk
Meier, Shawn
Meyer, Roland
Miné, Antoine
Mover, Sergio
Oh, Hakjoo
Seed, Tom

Seidl, Helmut
Seladji, Yassamine
Si, Xujie
Singh, Gagandeep
Stein, Benno
Suwimonteerabuth,
Dejvuth
Tsai, Ming-Hsien
Walukiewicz, Igor
Werey, Alexis
Zhang, Xin


Contents

Invited Papers
Simulation and Invariance for Weak Consistency . . . . . . . . . . . . . . . . . . . .
Jade Alglave

3


Quantitative Monitor Automata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Krishnendu Chatterjee, Thomas A. Henzinger, and Jan Otop

23

The Julia Static Analyzer for Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Fausto Spoto

39

Full Papers
Automated Verification of Linearization Policies . . . . . . . . . . . . . . . . . . . . .
Parosh Aziz Abdulla, Bengt Jonsson, and Cong Quy Trinh

61

Structure-Sensitive Points-To Analysis for C and C++ . . . . . . . . . . . . . . . . .
George Balatsouras and Yannis Smaragdakis

84

Bounded Abstract Interpretation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Maria Christakis and Valentin Wüstholz

105

Completeness in Approximate Transduction . . . . . . . . . . . . . . . . . . . . . . . .
Mila Dalla Preda, Roberto Giacobazzi, and Isabella Mastroeni

126


Relational Verification Through Horn Clause Transformation . . . . . . . . . . . .
Emanuele De Angelis, Fabio Fioravanti, Alberto Pettorossi,
and Maurizio Proietti

147

Securing a Compiler Transformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Chaoqiang Deng and Kedar S. Namjoshi

170

Exploiting Sparsity in Difference-Bound Matrices . . . . . . . . . . . . . . . . . . . .
Graeme Gange, Jorge A. Navas, Peter Schachte, Harald Søndergaard,
and Peter J. Stuckey

189

Flow- and Context-Sensitive Points-To Analysis Using Generalized
Points-To Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Pritam M. Gharat, Uday P. Khedker, and Alan Mycroft

212

Learning a Variable-Clustering Strategy for Octagon from Labeled
Data Generated by a Static Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Kihong Heo, Hakjoo Oh, and Hongseok Yang

237



X

Contents

Static Analysis by Abstract Interpretation of the Functional Correctness
of Matrix Manipulating Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Matthieu Journault and Antoine Miné

257

Generalized Homogeneous Polynomials for Efficient Template-Based
Nonlinear Invariant Synthesis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Kensuke Kojima, Minoru Kinoshita, and Kohei Suenaga

278

On the Linear Ranking Problem for Simple Floating-Point Loops . . . . . . . . .
Fonenantsoa Maurica, Frédéric Mesnard, and Étienne Payet
Alive-FP: Automated Verification of Floating Point Based Peephole
Optimizations in LLVM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
David Menendez, Santosh Nagarakatte, and Aarti Gupta

300

317

A Parametric Abstract Domain for Lattice-Valued Regular Expressions . . . . .
Jan Midtgaard, Flemming Nielson, and Hanne Riis Nielson


338

Cell Morphing: From Array Programs to Array-Free Horn Clauses . . . . . . . .
David Monniaux and Laure Gonnord

361

Loopy: Programmable and Formally Verified Loop Transformations . . . . . . .
Kedar S. Namjoshi and Nimit Singhania

383

Abstract Interpretation of Supermodular Games. . . . . . . . . . . . . . . . . . . . . .
Francesco Ranzato

403

Validating Numerical Semidefinite Programming Solvers
for Polynomial Invariants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Pierre Roux, Yuen-Lam Voronin, and Sriram Sankaranarayanan
Enforcing Termination of Interprocedural Analysis . . . . . . . . . . . . . . . . . . .
Stefan Schulze Frielinghaus, Helmut Seidl, and Ralf Vogler

424
447

From Array Domains to Abstract Interpretation Under Store-Buffer-Based
Memory Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Thibault Suzanne and Antoine Miné


469

Making k-Object-Sensitive Pointer Analysis More Precise
with Still k-Limiting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tian Tan, Yue Li, and Jingling Xue

489

Author Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

511


Invited Papers


Simulation and Invariance for Weak Consistency
Jade Alglave1,2(B)
1

Microsoft Research Cambridge, Cambridge, UK

2
University College London, London, UK

Abstract. We aim at developing correct algorithms for a wide variety of
weak consistency models M0 , . . . , Mn . Given an algorithm A and a consistency model M ∈ {M0 , . . . , Mn }, at quite a high-level examining the
correctness of the algorithm A under M amounts to asking, for example,
“can these executions happen?”, or “are these the only possible executions?”. Since a few years, Luc Maranget and myself have been designing
and developing the herd7 simulation tool: given a litmus test, i.e. a small

piece of code and a consistency model, i.e. a set of constraints defining
the valid executions of a program, the herd7 tool outputs all the possible executions of the litmus test under the consistency model. In recent
works with Patrick Cousot, we have developed an invariance method for
proving the correctness of algorithms under weak consistency models. In
this paper I would like to give a general overview of these works.

1

Introduction

Weak consistency models (WCMs) are now a fixture of computing systems: for
example Intel x86 or ARM processors, Nvidia graphics cards, programming languages such as C++ or OpenCL, or distributed systems such as Amazon AWS
or Microsoft’s Azure. In this context, the execution of a concurrent program no
longer is an interleaving of the instructions involved on the different processes
that constitute the program, unlike what is prescribed by Lamport’s Sequential
Consistency (SC) [Lam79a].
On the contrary, semantics of programs need to take into account possible reordering of instructions on one process, or propagation delays between
processes, for example due to hardware features such as store buffers and caches.
Different consistency semantics styles can be used to describe WCMs. Operational models define abstract machines in which executions of programs are
sequences of transitions made to or from formal objects modelling e.g. hardware
features such as store buffers and caches. Axiomatic models abstract away from
such concrete features and describe executions as relations over events modelling
e.g. read or write memory accesses, and synchronisation.
Different program semantics styles can be used to describe program executions (operational, denotational, axiomatic, etc.). The approach taken by the
herd7 tool, formalised later with Patrick Cousot, is as follows. Computations
are described as individual traces of processes on the one hand, and anarchic
c Springer-Verlag GmbH Germany 2016
X. Rival (Ed.): SAS 2016, LNCS 9837, pp. 3–22, 2016.
DOI: 10.1007/978-3-662-53413-7 1



4

J. Alglave

(unrestrained) communications between processes. Specific WCMs are taken into
account by placing restrictions on communications only.
We aim at developing correct algorithms for a wide variety of weak consistency models M0 , . . . , Mn . Given an algorithm A and a consistency model
M ∈ {M0 , . . . , Mn }, at quite a high-level examining the correctness of the algorithm A under M amounts to asking, for example, “can these executions happen?”, or “are these the only possible executions?”.
1.1

Simulation, or Building All the Possible Executions

A first way to try to address this question is by simply building all the possible
executions of A under M and examining to what extent the subset of executions
under scrutiny (the ones which possibility we question above) is included in the
set of all possible executions.
Since a few years, Luc Maranget and myself have been designing and developing the herd7 simulation tool: given a litmus test, i.e. a small piece of code
and a consistency model, i.e. a set of constraints defining the valid executions of
a program, the herd7 tool outputs all the possible executions of the litmus test
under the consistency model.
1.2

Invariance, or Building Invariant Specifications of Executions

Another way to try to address this question is to build invariant specifications
of the algorithm; in other words to state properties that all executions satisfy,
at all execution points. Then one needs to check that these specifications indeed
are invariant. Once this is done one can assess whether the executions under
scrutiny satisfy the specification, in which case they can well happen.

In recent works with Patrick Cousot, we have developed such a method for
proving the correctness of algorithms under weak consistency models.
1.3

Overview

In this paper I would like to give a general overview of these works. In both cases
– we get given
1. an algorithm A, and
2. a consistency model M .
– we need to build
1. a description of the semantics of each thread, and
2. a description of the communications between threads.
– we need to invent a specification of how the program should behave.
As an illustration, we will use the classical mutual exclusion algorithm of
Peterson [Pet81]. Our algorithms will be written in our Litmus Instruction Set
Architecture (lisa) language. Our consistency models will be written in our cat
language.


Simulation and Invariance for Weak Consistency

2

5

Semantics

In this section we examine, on a store buffering litmus test, the following points:
1. write the litmus test in the Litmus Instruction Set Architecture (lisa) language of the herd7 tool; this includes:

– writing a small piece of concurrent code;
– writing a question about which executions can happen;
2. build all the possible executions of the litmus test;
3. write several consistency models in the cat language;
4. examine to what extent the executions we have asked about can happen under
a certain model.
2.1

Writing a Litmus Test in lisa

We give the code of a store buffering litmus test in lisa in Fig. 1. The test
uses two shared variables F1 and F2. This snippet is at the heart of Peterson’s
algorithm, which we will examine later; essentially F1 and F2 are flags which
each thread uses to indicate that they would like to enter their critical sections.
LISA SB
{F1=0; F2=0}
P0
| P1
;
w[] F1 1 | w[] F2 1 ;
r[] r1 F2 | r[] r3 F1 ;
exists (0:r1=0 /\ 1:r3=0)

Fig. 1. A store buffering litmus test (sb)

Let’s read the lisa code; our litmus test is composed of:
– a prelude at line 0:, between curly brackets, which initialises the variables F1
and F2 to 0;
– two processes P0 and P1, each depicted as a column; let’s detail the first
process, on the left-hand side: at line 1:, we write 1 to the variable F1—the

lisa syntax for writes is “w[] x e” where x is a variable and e an expression
over registers, whose value is written to x. At line 5: we read the value of
shared variable F2 and place it into register R1, which is private to the first
thread.
– a question about the final state of registers R1 and R2; here we ask: “is it
possible that R1 and R2 both contain the value 0?”.
This outcome is possible on machines that feature store buffers for example.
Indeed the two writes—the write of F1 on P0 and the write of F2 on P1—can be
made to the respective private store buffers of P0 and P1. Then the two reads
can be made from memory, i.e. the read of F2 on P0 reads the initial value 0, and
idem for the read of F1 on P1. Finally, the two writes are flushed to memory.


6

2.2

J. Alglave

Build All the Possible Executions of a Litmus Test

We now show all the possible executions of the sb litmus test, in Fig. 2.

Fig. 2. All possible executions of the store buffering litmus test of Fig. 1

At the top left-hand corner, we see an execution where the read of F1 on P1
takes its value from the write of F1 by P0, hence reads the value 1. We depict
by with a read-from arrow (rf), between the write and the read of F1.
In the same execution, we see that the read of F2 on P0 takes its value
from the inital state. We depict this by a read-from. Here we have omitted the

initialisation events to F1 and F2, hence the rf arrow has a little stub at its
source, instead of a write event.
At the top right-hand corner, we see an execution where the read of F1 takes
its value from the initial state, whilst the read of F2 takes its value from the
write of F2 by P1.
At the bottom left-hand corner, we see an execution where both reads take
their values from the updates: the read of F1 reads 1 as written by P0, idem for
the read of F2.
Finally at the bottom right-hand corner, we see an execution where both
reads take their values from the inital state. This is the execution that leads to
both registers holding the value 0 in the end, as asked by the question at the
bottom of the sb litmus test in Fig. 1.
Now, let’s take a closer look at that last execution. We reproduce it in Fig. 3,
with some additional information.

Fig. 3. The execution of sb leading to the final state in question


Simulation and Invariance for Weak Consistency

7

In Fig. 3, we have added coherence arrows. Coherence relates writes to the
same variable. By convention, the initialisation write of a given variable is
ordered in coherence before any update of that variable. Thus the write of F1
by P0 appears in coherence after the initialisation write of F1, idem for F2.
Now, observe that the execution in Fig. 3 exhibits a cycle: 1: w[] F1 true
— po −→ 5: r[] R1 F2 — rf^-1 −→ 0: w[] F2 false — co −→ 21: w[] F2 true
— po −→ 25: r[] R3 F1 — rf^-1 −→ 0: w[] F1 false — co −→ 1: w[] F1 true.


This is the sequence that the consistency model needs to forbid to ensure that
this final state is never reached.
2.3

Write Consistency Models in cat

Now we can examine these questions through the prism of various consistency
models. Before detailing how we write models, we give a glimpse of the cat
language. In this paper we will focus on:
– Sequential Consistency [Lam79a] (SC), where executions of a program are
interleavings of the instructions appearing on the threads of the program, and
– Total Store Order [SPA94,OSS09] (TSO), which allows store buffering scenarios as seen in Fig. 1, and is the model of Sparc TSO and x86 machines.
However we note that the cat language has been used to define a variety
of models, such as IBM Power [AMT4b], ARM [AMT4b], Nvidia [ABD+15],
HSA [ACM15b], C++ [BDW16], OpenCL [BDW16].
The cat language (see [ACM15b]) is a domain specific language to describe
consistency models succinctly by constraining an abstraction of program executions into a candidate execution e, po, rf, IW providing
– events e, giving a semantics to instructions; for example a lisa write w[] x
v yields a write event of variable x with value v. Events can be (for brevity
this is not an exhaustive list):
• writes, gathered in the set W, unless they come from the prelude of the
program in which case they are gathered in the set of initial writes IW;
• reads, gathered in the set R;
• fences, gathered in the set F.
– the program order po, relating accesses written in program order in the original
lisa program;
– the read-from rf describing a communication between a write and a read.
The language provides additional basic built-in semantics bricks:
– the relation loc relating events accessing the same variable;
– the relation ext relating events from different processes;

– operators over relations, such as intersection &, union |, inverse of a relation
^-1, closure +, cartesian product *, set difference \.
The cat user can define new relations using let, and declare constraints over
relations, such as irreflexivity or acyclicity constraints, using the eponymous
keywords irreflexive r and acyclic r (i.e. irreflexive r+).


8

J. Alglave

Preliminary definitions. In all the models shown below we use the following
two definitions:
– we define the relation co as relating initial writes (viz., the writes from the
prelude) to the writes in the program that access the same variable. In cat
speak, the set of initial writes is written IW, the set of writes in the program
is W, the relation between accesses to the same variable is loc (for location)
and the intersection is &;
– we define a shorthand fr (for from-read ) for the sequence of relations rf^-1
and co that appears twice in the cycle in Fig. 3. We refine this relation further,
to the relation fre, which is fr restricted to accesses that belong to different
processes—in cat speak this is denoted by the relation ext (for external).
When M is SC. In cat speak, SC is modelled as in Fig. 4 (see e.g. [Alg10]
for an equivalence proof). The first two lines define co and fr as above. The
last line states that there cannot be a cycle in the union (depicted by |) of the
program order po, the read-from rf, the coherence co and the from-read fr.
let co = (IW*W) & loc
let fr = (rf^-1;co)
acyclic po | rf | co | fr as sc


Fig. 4. SC in cat

When M is TSO. In cat speak, TSO is modelled as given in Fig. 5 (see e.g.
[Alg10] for an equivalence proof). The first two lines define co and fr as above.
Then we define a new relation po-loc, as the restriction of the program
order po to accesses relative the same variable (see the intersection with the
relation loc). Next up we require the acyclicity of the union of po-loc with all
the communication relations: read-from rf, coherence co and from-read fr. We
call this acyclicity check scpv, which stands for “SC per variable”. This check
is required to ensure that all the values read and written by accesses to a same
variable are reachable on SC. Less formally, this enforces coherence properties,
e.g. that a read of a variable cannot read from a write of the same variable
appearing later on the same thread.
We then define the relation ppo (for preserved program order ) as the program
order po relieved from (see the setminus operator \) the write-read pairs (W*R).
Then we define the relation rfe (for external read-from) as the restriction of the
read-from rf to accesses that belong to different threads (denoted by the relation
ext). Finally we require the acyclicity of the union of the preserved program
order, the external read-from, the coherence and the from-read relations. We
call this acyclicity check tso, as it is the main distinguishing feature of the TSO
model (the SC per variable check appearing in most other models that we have
studied, e.g. IBM Power).


Simulation and Invariance for Weak Consistency

9

let co = (IW*W) & loc
let fr = (rf^-1;co)

let po-loc = po & loc
acyclic po-loc | rf | co | fr as scpv
let ppo = po \ (W*R)
let rfe = rf & ext
acyclic ppo | rfe | co | fr as tso

Fig. 5. TSO in cat

2.4

Answer Our Question About the Final State

Recall the question that we have asked about the final state: “is it possible that
R1 and R2 both contain the value false?”. Recall that the consistency model
needs to forbid the cycle given in Fig. 3 to ensure that this final state is never
reached. In other words, a consistency model will forbid this execution if it
ensures that the sequence po; fre; po; fre is irreflexive, i.e. communications
between the two processes of sb should not be such that taking a step in program
order po, then a step of fre, landing on the other process, then a step of po,
then a step of fre again, goes back to the starting point. Overall this leads to
the cat specification given in Fig. 15 (Fig. 6):
let co = (IW*W) & loc
let fre = (rf^-1;co) & ext
irreflexive po; fre; po; fre as sb-forbid

Fig. 6. A possible specification of sb

When M is SC. Now, note that the sequence s forbidden by sb’s specification
is also a cycle in the union of relations which the SC model of Fig. 4 requires
to be acyclic, hence a contradiction: an execution containing s is also forbidden

when M is SC.
When M is TSO. An execution forbidden by our specification of sb (see
Fig. 15) will not be forbidden by the TSO model given in Fig. 5. This is because
any execution forbidden by our specification of sb involves a pair write-read in
program order (see the two po edges in the sequence s for example). Moreover,
the write-read pairs are explicitly removed from the tso acyclicity check given
on the last line of the TSO model of Fig. 5, thus will not contribute to executions
forbidden by the model.
Adding fences. lisa fences can be added to have a correct implementation of
sb. The fence semantics must be defined by a cat specification (F is the set of
fence events) and the specification of sb must be strengthened as given in Fig. 7.


10

J. Alglave
let fhw = (po & (_ * F)); po
let fre = (rf^-1;co) & ext
irreflexive fhw ; fre ; fhw ; fre as sb-forbid

Fig. 7. A stronger specification of sb

3

Specifications

In this section we will examine, on Peterson’s algorithm, the following points:
1. write the algorithm in the Litmus Instruction Set Architecture (lisa) language of the herd7 tool [AM15]. Along the way, we use lisa’s special fence
instructions, which allow to indicate between which program points (perhaps
sets of program points) synchronisation is needed for correctness.

2. state an invariant specification Sinv of the algorithm;
3. state an invariant communication specification Scom of the algorithm.
3.1

Writing the Algorithm in lisa

We give the code of Peterson’s algorithm in lisa in Fig. 8. The algorithm uses
three shared variables F1, F2 and T:
– two shared flags, F1 for the first process P0 (resp. F2 for the second process
P1), indicating that the process P0 (resp. P1) wants to enter its critical section,
and
– a turn T to grant priority to the other process: when T is set to 1 (resp. 2),
the priority is given to P0 (resp. P1).
Let’s look at the process P0: P0 busy-waits before entering its critical section
(see the do instruction at line 3:) until (see the while clause at line 6:) the
process P1 does not want to enter its critical section (viz., when F2=false, which
in turn means ¬R1=true thanks to the read at line 4:) or if P1 has given priority
to P0 by setting turn T to 1, which in turn means that R2=1 thanks to the read
at line 5:.
LISA code. Let’s read it together; our algorithm is composed of:
– a prelude at line 0:, between curly brackets, which initialises the variables F1
and F2 to false and the variable T to 0;
– two processes, each depicted as a column; let’s detail the first process, on the
left-hand side: at line 1: we write true to the variable F1—the lisa syntax for
writes is “w[] x e” where x is a variable and e an expression over registers,
whose value is written to x. At line 2 we write 2 to T. At line 3: we see a
do instruction which ensures that we iterate the instructions at lines 4 and 5
until the condition expressed at line 6 (viz., R1 ∧ R2 = 1) is false. At line 4:
we read the variable F2 and write its value into register R1, and at line 5: we
read the variable T and write its value into register R2. At line 7: we have a

skip instruction, simply to signify the critical section, and at line 8: we write
false to F1.


Simulation and Invariance for Weak Consistency

11

0:{ w F1 false; w F2 false; w T 0; }
P0:
P1:
10:w[] F2 true;
1:w[] F1 true
11:w[] T 1;
2:w[] T 2
12:do {j}
3:do {i}
4:
r[] R1 F2 {
F2i4 }
13:
r[] R3 F1; {
F1j13 }
i
5:
r[] R2 T {
T5 }
14:
r[] R4 T; {
Tj14 }

6:while R1 ∧ R2 = 1 {iend } 15:while R3 ∧ R4 = 2; {jend }
16:skip (* CS2 *)
7:skip (* CS1 *)
17:w[] F2 false;
8:w[] F1 false
18:
9:

Fig. 8. Peterson algorithm in LISA

Annotations. We have placed a few annotations in our lisa code, to be used
later in invariants and proofs:
– iteration counters: each do loop, at line 3: and at line 12:, is decorated with
an iteration counter, e.g. i for the first process and j for the second process.
We also decorate the line of each until clause (i.e. lines 6: and 15:) with a
symbolic name (iend and jend ) to represent the iteration counter when exiting
the loop.
– pythia variables: each read, at lines 4 and 5 for the first process, and lines
13 and 14 for the second process, is decorated with a pythia variable. More
precisely a read : r[] R x at line :, reading the variable x and placing its
result into register R, is decorated with the pythia variable { xn }, where is
the line of the read in the program, x is the variable that the read is reading,
and n is an instance of the iteration counter.
Our invariants use pythia variables as opposed to simply the shared variables
because WCMs are such that there is no notion of instantaneous value of the
shared variables that the invariants could refer to. Instead, we use pythia variables, which give us a unique way to denote the values read during computation.
3.2

Stating an Invariant Specification Sinv


Figure 9 gives an invariant specification of our implementation of Peterson: the
specification states that both processes cannot be simultaneously in their critical
sections.
3.3

Stating a Communication Specification Scom

The next step in our specification process consists in stating an invariant communication specification Scom , expressing which inter-process communications
are allowed for the algorithm A. We take the reader through this process using
again Peterson’s algorithm as an illustration.


12

J. Alglave
1: {true}
...
7: {¬at{16}}
...
9: {true}

10: {true}
...
16: {¬at{7}}
...
18: {true}

Fig. 9. Invariant specification Sinv for Peterson’s algorithm

Peterson can go wrong under WCMs. Under certain WCMs, such as x86TSO or any weaker model, Peterson’s algorithm is incorrect (i.e. does not satisfy

the specification Sinv given above in Fig. 9, that both processes cannot be simultaneously in their critical section).
To see this, consider Fig. 10. The red arrows are an informal representation
of a communication scenario where:
– on the first process (see the left-hand side), the read at line 4: reads the value
that F2 was initialised with at line 0:, so that R1 contains false. The read at
line 5: reads from the update of T by the right-hand side process, so that R2
contains the value 1.
– on the second process, the read at line 13: reads from the initial value of F1,
so that R3 contains false; the read at line 14: reads from the left-hand side
process, so that R4 contains 2.

0:{ w F1 false; w F2 false; w T 0; }
P1:
P0:
10:w[] F2 true;
1:w[] F1 true
rf
2:w[] T 2
11:w[] T 1;
12:do {j}
3:do {i}
F2i4 }
13:
r[] R3 F1; {
F1j13 }
4:
r[] R1 F2 {
Ti5 }
14:
r[] R4 T; {

Tj14 }
5:
r[] R2 T {
6:while R1 ∧ R2 = 1 {iend } 15:while R3 ∧ R4 = 2; {jend }
7:skip (* CS1 *)
16:skip (* CS2 *)
8:w[] F1 false
17:w[] F2 false;
18:
9:
Fig. 10. Incorrect execution of Peterson algorithm with WCM

In this situation (which is impossible under SC), both loop exit conditions
can be true so that both processes can be simultaneously in their critical section,
thus invalidating the specification Sinv .
Communication specification Scom . Let us express the communication scenario depicted in red in Fig. 10 as an invariant. We write the pythia triple


Simulation and Invariance for Weak Consistency

13

pythia , xθ , v to mean that the read : r[] R x { xθ }, or more precisely
its pythia variable xθ , takes its value v from evaluating the expression e of the
write : w[] x e, and the local invariant at implies that e = v.
We give a communication specification for Peterson’s algorithm in Fig. 11.
Scom

¬[∃i, j . pythia 0, F2i4 , false ∧ pythia 11, Ti5 , 1 ∧
pythia 0, F1j13 , false ∧ pythia 2, Tj14 , 2 ]


Fig. 11. A communication specification for Peterson’s algorithm

In words, our communication specification Scom states that the scenario in
Fig. 10 is impossible, which in turn ensures that both processes cannot be simultaneously in their critical section. Therefore, there cannot be two iteration counters i and j such that:
– the read at line 4: and ith iteration (corresponding to the pythia variable
F2i4 ) takes its value, false, from the initialisation of the variable F2 (which
has been made in the prelude at line 0:);
– the read at line 5: and ith iteration (corresponding to the pythia variable Ti5 )
takes its value, 1, from the write at line 11;
– the read at line 13 and j th iteration (corresponding to the pythia variable
F1j13 ) takes its value, false, from the initialisation of the variable F1 (which
has been made in the prelude at line 0:);
– the read at line 14 and j th iteration (corresponding to the pythia variable Tj14 )
takes its value, 2, from the write at line 2.
3.4

And Now to the Proofs!

Our method is articulated as follows—we detail each of these points in turn
below, and show a graphical representation in Fig. 12:
1. Design and specifications:
– write the algorithm A, including synchronisation markers if needed
– state an invariant specification Sinv (see Sect. 3.2)
– state a communication specification Scom (see Sect. 3.3);
2. Proofs:
– prove the correctness of the algorithm A w.r.t. the invariant specification
Sinv , under the communication specification Scom (see Sect. 4);
– prove that the consistency model M guarantees the communication specification Scom that we postulated for the correctness of A (see Sect. 5).
Recall Fig. 12; given an algorithm A (e.g. Peterson’s algorithm as given in

Fig. 8) and a WCM M , we first need to invent:


14

J. Alglave

Fig. 12. Our method

1. an invariant specification Sinv , e.g. the one in Fig. 9 for Peterson’s algorithm;
2. a communication specification Scom , e.g. Fig. 11 for Peterson’s algorithm.
With these two specifications at hand, we can now start proving away; our
method is articulated as follows:
1. Conditional invariance proof Scom ⇒ Sinv : we need to prove that if the communications occur like prescribed by Scom , then the processes satisfy the invariant
Sinv ;
2. Inclusion proof M =⇒ Scom : we need to validate the hypotheses made in the
communication specification Scom , viz., we need to ensure that the WCM M
guarantees them.
We now detail each proof in turn.

4

Conditional Invariance Proof Scom ⇒ Sinv

Given an algorithm A, and the specifications Sinv and Scom , we need to prove that
each process of the algorithm satisfies a given invariant Sinv under the hypothesis
Scom ; to do so we:
1. invent a stronger invariant Sind , which is inductive;
2. prove that Sind is indeed inductive, i.e. satisfies verification conditions implying that if it is true, it stays true after one step of computation or one step
of communication that satisfies Scom ; effectively we prove Scom ⇒ Sind .

3. prove that Sind is indeed stronger than Sinv (i.e. Sind =⇒ Sinv );


Simulation and Invariance for Weak Consistency

15

Thus we have:
– Scom ⇒ Sind , saying that Sind is invariant for the algorithm under communication hypothesis Scom ;
– Sind =⇒ Sinv , saying that the inductive invariant Sind is stronger than the
invariant Sinv .
This allows us to conclude that Scom ⇒ Sinv , which was our goal. We now
illustrate the correctness proof process on Peterson.
4.1

Invent a Stronger Invariant Sind , which is inductive

An inductive invariant Sind , stronger than Sinv is given in Fig. 13. More precisely,
Fig. 13 gives local invariants (depicted in blue in curly brackets) for each program
point of each process, as in the Owicki-Gries and Lamport proof methods [OG76,
Lam77]. Our invariants can depend on registers (both the ones local to the
process under scrutiny, and from other processes), pythia variables and, as in
Lamport’s method [Lam77], on the program counter of the other processes (thus
avoiding auxiliary variables [OG76]). The invariants cannot depend on shared
variables.
0: { w F1 false; w F2 false; w T 0; }
{F1=false ∧ F2=false ∧ T=0} }
1:{R1=0 ∧ R2=0}
w[] F1 true


w[] F2 true;
11:
{R3=0 ∧ R4=0}

2:{R1=0 ∧ R2=0}

w[] T 1;

w[] T 2
3:{R1=0 ∧ R2=0}

12:
{R3=0 ∧ R4=0}
do {j}

do {i}
4:{(i=0 ∧ R1=0 ∧ R2=0) ∨
i−1
∧ R2=T5
)}
(i>0 ∧ R1=F2i−1
4
F2i4 }
r[] R1 F2 {
5:{R1=F2i4 ∧ (i=0 ∧ R2=0) ∨
(i>0 ∧ R2=Ti−1
)}
5
r[] R2 T {


6:{R1=F2i4

10:
{R3=0 ∧ R4=0}



R2=Ti5 }

Ti5 }

while R1 ∧ R2=1 {iend }
i

i

i

i

i

i

13:
{(j=0 ∧ R3=0 ∧ R4=0) ∨
j−1
j−1
(j>0 ∧ R3=F113
∧ R4=T14 )}

j
r[] R3 F1 {
F113 };
j

14:
{R3=F113 ∧ (j=0 ∧ R4=0) ∨
j−1
(j>0 ∧ R4=T14 )}
j
T14 }
j
R4=T14 )}

r[] R4 T; {

j
15:
{R3=F113



while R3 ∧ R4=2 {jend } ;
j

j

j

j


j

j

7:{¬F24end ∧ T5end =1}
skip (* CS1 *)

end ∧ T end =2}
16:
{¬F113
14
skip (* CS2 *)

8:{¬F24end ∧ T5end =1}
w[] F1 false

end ∧ T end =2}
17:
{¬F113
14
w[] F2 false;

9:{¬F24end ∧ T5end =1}

end ∧ T end =2}
18:
{¬F113
14


Fig. 13. Invariants of Peterson algorithm

Let us read the local invariants for the first process of Peterson:
– line 0: simply reflects the initialisations made in the prelude, thus we have
F1=false ∧ F2=false ∧ T=0;


16

J. Alglave

– at line 1: lisa assumes that all registers local to P1 (viz., R1 and R2) are
initialised to 0, thus we have R1=0 ∧ R2=0—we separate the initialisation of
shared variables (e.g. F1, F2 and T), factored out in the prelude, and the
initialisation of local registers, which is made at the top of each concerned
process;
– at line 2:, we have just passed a write of F1, which leaves the invariant
unchanged, thus we still have R1=0 ∧ R2=0;
– similarly at line 3:, we just passed a write of T, which leaves the invariant
unchanged, thus we still have R1=0 ∧ R2=0;
– at line 4:, we are about to enter, or have entered, a loop, whose iterations are
indexed by i as indicated by the annotation after the do instruction; the loop
invariant states that:
• either we have not entered the loop yet (i=0), in which case the registers
are unchanged, viz., R1=0 ∧ R2=0, or
• we have entered the loop (i>0), in which case the registers contain updated
values, more precisely updated pythia variables: for example R1=F24i−1 indicates that in the i − 1 iteration of the loop, there has been, at line 4:, a
read of the variable F2, resulting in the pythia variable F24i−1 being placed
into register R1;
– at line 5: we have just passed a read of the variable F2, yielding the pythia

variable F2i4 : this leads to the updated local invariant R1=F2i4 ∧ ((i=0 ∧ R2=0)
∨ (i>0 ∧ R2=T 5i−1 ));
– at line 6: we have just passed a read of the variable T, yielding the pythia
variable Ti5 : this leads to the updated local invariant R1=F2i4 ∧ R2=Ti5 ;
– at line 7:, we have just exited the loop—as symbolised by the annotation
iend —thus we have met the exit condition, viz., ¬R1 ∨ R2=1; this is reflected in
the invariant ¬ F2i4end ∧ Ti5end =1, as we know from the invariant at line 6: that
R1=F2i4 and R2=Ti5 ;
– at line 8:, we just passed a skip, which leaves the invariant unchanged;
– at line 9:, we just passed a write, which leaves the invariant unchanged.
4.2

Prove that Sind Is Indeed Inductive

Sind is inductive under the hypothesis Scom ; we prove this in several steps:
– Initialisation proof: we must prove that the invariant at the entry of each
process (e.g. R1=0 ∧ R2=0 for P0) is true when all processes are at their entry,
all registers hold the value 0, and there is no pythia variable;
– Sequential proof: we must prove that the invariants are true when executing
a process sequentially. This is simple since:
• a read r[] R x
xi updates the value of register R to the adequate pythia
variable xi ,
• a write is handled like a skip, i.e. has no effect on the invariant, and
• loops are handled classically:
* the loop invariant at line 4: must be true upon the first loop entry (i.e.
R1=0 ∧ R2=0 when i=0), and



×