Verifying Concurrent Programs by Controlling Alias Interference
Total Page:16
File Type:pdf, Size:1020Kb
c Copyright 2014 Colin S. Gordon Verifying Concurrent Programs by Controlling Alias Interference Colin S. Gordon A dissertation submitted in partial fulfillment of the requirements for the degree of Doctor of Philosophy University of Washington 2014 Reading Committee: Michael D. Ernst, Chair Dan Grossman, Chair Matthew Parkinson, Microsoft Research, Cambridge, UK Program Authorized to Offer Degree: UW Computer Science and Engineering University of Washington Abstract Verifying Concurrent Programs by Controlling Alias Interference Colin S. Gordon Co-Chairs of the Supervisory Committee: Professor Michael D. Ernst Computer Science and Engineering Associate Professor Dan Grossman Computer Science and Engineering This dissertation proposes a family of techniques for static verification of sequential and concurrent imperative programs by leveraging fine-grained characterizations of mutation. The key idea is that by attaching to each reference in a program (1) a restriction on mu- tations permitted using that reference, and (2) a characterization of possible interference through other aliases, a type system can reason about what properties are preserved by all mutations in a program. This thesis develops four variations on this idea: (1) We adapt reference immutability to support data-race-free concurrent programming. (2) We generalize reference immutability to rely-guarantee references, allowing two-state invariants to express usage restrictions be- tween read-only and arbitrary mutation. (3) We extend rely-guarantee references to prove invariants and functional correctness of lock-free concurrent data structures. (4) We evalu- ate rely-guarantee references' utility for existing Haskell programs. Together these variations show that reasoning about aliasing and reasoning about con- current (imperative) programs are the same fundamental challenge, and that by taking the right foundational approach to reasoning about sequential programs, the gap to reasoning about concurrent programs is significantly reduced. TABLE OF CONTENTS Page List of Figures . iv Chapter 1: Introduction . .1 1.1 Modular Verification: Simple, Pure, and Imperative . .2 1.2 Protocols for Shared Mutable State . .5 1.3 The Granularity of Modularity . .7 1.4 Explanation of Thesis . .8 1.5 Published Content . 10 Chapter 2: General Related Work . 12 2.1 Global Reasoning . 15 2.2 Separation and Isolation . 16 2.3 Isolation with Serialized Sharing . 24 2.4 Read-sharing . 27 2.5 Interference Summaries . 32 2.6 Implementing Verification Systems . 43 2.7 Relating Sequential and Concurrent Correctness . 44 2.8 Dependent Type Theory . 45 Chapter 3: Uniqueness and Reference Immutability for Safe Parallelism . 49 3.1 Reference Immutability, Uniqueness, and Parallelism . 51 3.2 Types for Reference Immutability and Parallelism . 58 3.3 Type Soundness . 66 3.4 Polymorphism . 84 3.5 Evaluation . 95 3.6 Related Work . 106 3.7 Conclusions . 112 i Chapter 4: Rely-Guarantee References . 113 4.1 Introduction . 113 4.2 Rely-Guarantee References . 116 4.3 Examples . 119 4.4 A Type System for Rely-Guarantee References . 128 4.5 Implementation . 142 4.6 Future Work: Extensions and Adaptations . 149 4.7 Related Work . 150 4.8 Conclusion . 154 Chapter 5: Concurrent Refinement Types and Functional Correctness via Rely- Guarantee References . 162 5.1 Correctness for Lock-Free Datastructures . 164 5.2 Suitability of RGrefs for Concurrent Programming . 166 5.3 RGrefs for Concurrency . 168 5.4 Refinement from Rely-Guarantee Reasoning . 196 5.5 Implementation . 203 5.6 Related Work . 204 5.7 Conclusions . 208 Chapter 6: Rely-Guarantee References for Existing Code . 210 6.1 Background: State and Refinement Types in Haskell . 212 6.2 Embedding Rely-Guarantee References in Liquid Haskell . 217 6.3 Defining Liquid RGrefs.............................. 222 6.4 Using Liquid RGrefs ............................... 228 6.5 Related Work . 239 6.6 Fruitful Directions for Further Investigation . 240 6.7 Conclusions . 241 Chapter 7: Directions for Future Work . 243 7.1 Direct Extensions to RGrefs........................... 243 7.2 Richer Specification Languages . 248 7.3 Gradual Verification . 249 Chapter 8: Conclusion . 251 Bibliography . 253 ii Appendix A: Background Reading . 278 A.1 Dependent Types . 278 A.2 Program Logics: Hoare Logic, Separation Logic, and Beyond . 279 iii LIST OF FIGURES Figure Number Page 2.1 Selected proof rules for sequential and concurrent separation logic, variable side conditions elided. 18 3.1 External uniqueness with immutable out-references. 52 3.2 Qualifier conversion/subtyping lattice. 53 3.3 Core language syntax. 60 3.4 Subtyping rules . 61 3.5 Core typing rules. 61 3.6 Program typing . 62 3.7 Recovery rules . 63 3.8 Type rules for safe parallelism. IsoOrImm is defined in Figure 3.7 . 64 3.9 Typing derivation for adding a node to an isolated doubly-linked list. 66 3.10 Definition of Well-Regioned . 69 3.11 Denoting types and type environments. 72 3.12 The thread interference relation R0........................ 74 3.13 Weak type environment denotation, for framed-out environments. The differ- ences from Figure 3.11 are the permissions required by readable and writable references, and the way π bounds the state's permissions. 78 3.14 Method call extensions to the language and program logic. 80 3.15 The proof tree for validity of method summaries when the summary is not for an isolated receiver. Environment reordering steps are not shown explic- itly. Parentheticals on the right hand side indicate the method by which the assertion on the same line was proved from the previous assertion and/or statement when it is not an obvious derivation like framing. 85 3.16 Grammar extensions for the polymorphic system. 86 3.17 Auxiliary judgements and metafunctions for the polymorphic system. 87 3.18 Generics typing rules. All structural, recovery, and parallelism rules remain as in Figures 3.5, 3.7, and 3.8, extended with ∆ in conclusions and appropriate hypotheses. 90 iv 3.19 Well formed polymorphic programs. In T-Method*, the bound on the method permission p is present if and only if p is a permission variable. ............................................ 91 3.20 Denoting types and type environments in the polymorphic system, differences from Figure 3.11. The main change is to the subclass clause of the writable and isolated cases, which require the runtime type's field types to exactly match the supertype's. 93 3.21 A simplified collection with a polymorphic enumerator. 100 3.22 Extension methods to add regular and parallel map to a linked list. 102 4.1 RGref code for a prepend-only linked list. 123 4.2 Combining reference immutability permissions, from [105]. Using a p refer- ence to read a q T field produces a (p B q) T ................... 126 4.3 Syntax, omitting booleans (b : bool), unary natural numbers (n : nat), unit, pairs, propositional True and False, and standard recursors. The expression/- type division is presentational; the language is a single syntactic category of PTS-style [14] pseudoterms. 130 4.4 Typing. For standard recursors for naturals, booleans, pairs, and identity types [129], as well as well-formed contexts, and (pure) expression/type con- version (Γ ` τ τ), see (Figure 4.6). 155 4.5 Typing, continued. 156 4.6 Selected auxiliary judgments . 157 4.7 Auxilliary functions . 158 4.8 The simplest term we can imagine that observes the multiple-dereference reduction . 158 4.9 Values, typing of runtime values, and main operational semantics for RGref. 159 4.10 Structural / context operational semantics for RGref.............. 160 4.11 Dynamic state typing. 161 5.1 A positive monotonically increasing counter using RGrefs, in our Coq DSL. The rgref monad for imperative code is indexed by input and output envi- ronments ∆ of substructural values, not used in this example. 171 5.2 Atomic increment for a monotonically increasing counter. This code uses a standard read-modify-CAS loop. Until the increment succeeds, it reads the counter's value, then tries to compare-and-swap the old value with the incremented result. RGFix is a fixpoint combinator, and rgret returns a value.171 5.3 A Treiber Stack [251] using RGrefs, omitting proofs. The relation local imm (not shown) constrains the immediate referent to immutable; any is the always-true predicate. 172 v 5.4 A lock-free union find implementation [7] using RGrefs, omitting interactive proofs. a<|i|> accesses the ith entry of array a. The type Fin.t n is (isomorphic to) a natural number less than n, making it a safe index into the array. u conjoins predicates. 174 5.5 Core typing rules for concurrency-safe RGrefs. See also Figure 5.7 for meta- function definitions. 178 5.6 Primitive to introduce new refinements based on observed values. 179 5.7 Metafunctions for side conditions used in Figure 5.5. 179 5.8 Views state space. \Hats" (e.g., Mc) indicate explicit annotations of RGref.