Verification for Concurrent Programs

Slides:



Advertisements
Similar presentations
Greta YorshEran YahavMartin Vechev IBM Research. { ……………… …… …………………. ……………………. ………………………… } T1() Challenge: Correct and Efficient Synchronization { ……………………………
Advertisements

The complexity of predicting atomicity violations Azadeh Farzan Univ of Toronto P. Madhusudan Univ of Illinois at Urbana Champaign.
1 Chao Wang, Yu Yang*, Aarti Gupta, and Ganesh Gopalakrishnan* NEC Laboratories America, Princeton, NJ * University of Utah, Salt Lake City, UT Dynamic.
A Program Transformation For Faster Goal-Directed Search Akash Lal, Shaz Qadeer Microsoft Research.
An Case for an Interleaving Constrained Shared-Memory Multi-Processor Jie Yu and Satish Narayanasamy University of Michigan.
Architecture-aware Analysis of Concurrent Software Rajeev Alur University of Pennsylvania Amir Pnueli Memorial Symposium New York University, May 2010.
Abstraction and Modular Reasoning for the Verification of Software Corina Pasareanu NASA Ames Research Center.
Reduction, abstraction, and atomicity: How much can we prove about concurrent programs using them? Serdar Tasiran Koç University Istanbul, Turkey Tayfun.
A Randomized Dynamic Program Analysis for Detecting Real Deadlocks Koushik Sen CS 265.
Ch. 7 Process Synchronization (1/2) I Background F Producer - Consumer process :  Compiler, Assembler, Loader, · · · · · · F Bounded buffer.
Operating System Concepts and Techniques Lecture 12 Interprocess communication-1 M. Naghibzadeh Reference M. Naghibzadeh, Operating System Concepts and.
Annoucements  Next labs 9 and 10 are paired for everyone. So don’t miss the lab.  There is a review session for the quiz on Monday, November 4, at 8:00.
Reducing Context-bounded Concurrent Reachability to Sequential Reachability Gennaro Parlato University of Illinois at Urbana-Champaign Salvatore La Torre.
Iterative Context Bounding for Systematic Testing of Multithreaded Programs Madan Musuvathi Shaz Qadeer Microsoft Research.
Tom Ball, Sebastian Burckhardt, Madan Musuvathi, Shaz Qadeer Microsoft Research.
Verification for Concurrency Part 2: Incomplete techniques and bug finding.
On Sequentializing Concurrent Programs Ahmed Bouajjani LIAFA, University of Paris 7, France LIAFA, University of Paris 7, France Michael Emmi LIAFA, University.
Transaction Processing Lecture ACID 2 phase commit.
Cormac Flanagan UC Santa Cruz Velodrome: A Sound and Complete Dynamic Atomicity Checker for Multithreaded Programs Jaeheon Yi UC Santa Cruz Stephen Freund.
Verifying Concurrent Programs by Memory Unwinding Ermenegildo Tomasco University of Southampton, UK Omar Inverso University of Southampton, UK Bernd Fischer.
Learning From Mistakes—A Comprehensive Study on Real World Concurrency Bug Characteristics Shan Lu, Soyeon Park, Eunsoo Seo and Yuanyuan Zhou Appeared.
272: Software Engineering Fall 2012 Instructor: Tevfik Bultan Lecture 4: SMT-based Bounded Model Checking of Concurrent Software.
Thread-modular Abstraction Refinement Thomas A. Henzinger, et al. CAV 2003 Seonggun Kim KAIST CS750b.
Concurrency Recitation – 2/24 Nisarg Raval Slides by Prof. Landon Cox.
CUTE: A Concolic Unit Testing Engine for C Technical Report Koushik SenDarko MarinovGul Agha University of Illinois Urbana-Champaign.
Chapter 25 Formal Methods Formal methods Specify program using math Develop program using math Prove program matches specification using.
Use of Coverity & Valgrind in Geant4 Gabriele Cosmo.
Games Development 2 Concurrent Programming CO3301 Week 9.
Motivation  Parallel programming is difficult  Culprit: Non-determinism Interleaving of parallel threads But required to harness parallelism  Sequential.
CS527 Topics in Software Engineering (Software Testing and Analysis) Darko Marinov August 30, 2011.
CSV 889: Concurrent Software Verification Subodh Sharma Indian Institute of Technology Delhi State merging, Concolic Execution.
CS533 – Spring Jeanie M. Schwenk Experiences and Processes and Monitors with Mesa What is Mesa? “Mesa is a strongly typed, block structured programming.
Compositionality Entails Sequentializability Pranav Garg, P. Madhusudan University of Illinois at Urbana-Champaign.
Bounded Model Checking of Multi-Threaded C Programs via Lazy Sequentialization Omar Inverso University of Southampton, UK Ermenegildo Tomasco University.
Specifying Multithreaded Java semantics for Program Verification Abhik Roychoudhury National University of Singapore (Joint work with Tulika Mitra)
CS 153 Design of Operating Systems Winter 2016 Lecture 7: Synchronization.
Soyeon Park, Shan Lu, Yuanyuan Zhou UIUC Reading Group by Theo.
1 Critical Section Problem CIS 450 Winter 2003 Professor Jinhua Guo.
Testing Concurrent Programs Sri Teja Basava Arpit Sud CSCI 5535: Fundamentals of Programming Languages University of Colorado at Boulder Spring 2010.
Where Testing Fails …. Problem Areas Stack Overflow Race Conditions Deadlock Timing Reentrancy.
Synchronization Questions answered in this lecture: Why is synchronization necessary? What are race conditions, critical sections, and atomic operations?
1 Active Random Testing of Parallel Programs Koushik Sen University of California, Berkeley.
On Sequentializing Concurrent Programs
Healing Data Races On-The-Fly
Software Testing.
Why Events Are A Bad Idea (for high-concurrency servers)
Processes and Threads Processes and their scheduling
Sequentializing Parameterized Programs
runtime verification Brief Overview Grigore Rosu
Specifying Multithreaded Java semantics for Program Verification
Presented by Mahadevan Vasudevan + Microsoft , *UC-Berkeley
Verification of Concurrent Programs
Threads and Memory Models Hal Perkins Autumn 2011
Software Testing (Lecture 11-a)
References [1] LEAP:The Lightweight Deterministic Multi-processor Replay of Concurrent Java Programs [2] CLAP:Recording Local Executions to Reproduce.
Objective of This Course
Chapter 26 Concurrency and Thread
Over-Approximating Boolean Programs with Unbounded Thread Creation
All You Ever Wanted to Know About Dynamic Taint Analysis & Forward Symbolic Execution (but might have been afraid to ask) Edward J. Schwartz, Thanassis.
Threads and Memory Models Hal Perkins Autumn 2009
Lazy Sequentialization Unbounded Concurrent Programs
Design and Implementation Issues for Atomicity
Why Threads Are A Bad Idea (for most purposes)
CSE 153 Design of Operating Systems Winter 19
CUTE: A Concolic Unit Testing Engine for C
Foundations and Definitions
Why Threads Are A Bad Idea (for most purposes)
Why Threads Are A Bad Idea (for most purposes)
CSE 332: Concurrency and Locks
Pointer analysis John Rollinson & Kaiyuan Li
Presentation transcript:

Verification for Concurrent Programs Part 3: Incomplete techniques and bug finding

Context bounding and Sequentialization

Context bounding Folk knowledge: Most concurrency bugs are shallow in terms of required context-switches Most bugs require very few context-switches Most concurrency bugs are atomicity violations or order violations For an empirical study, see Shan Lu et al. 2006…2008 Why not check concurrent programs only up to a few context switches? Much more efficient

CHESS: Systematic exploration Culmination of techniques proposed by Qadeer et al in 2004 Correctness primarily given by assertions in the code Can also use monitors Can detect data-races, deadlocks, etc Main idea: Use a scheduler that explores traces of the program deterministically, prioritizing traces having few context-switches

CHESS: Controlling scheduler Non-determinism source: Input Scheduling Timing and library Input non-determinism controlled by specifying fixed inputs Scheduling non-determinism controlled by writing deterministic scheduler Library non-determinism: model library code

State-space explosion Thread1: x = 1 … y = k Threadn: x = 1 … y = k Exploring k steps in each of the n threads Number of executions is O(nnk) Exploring k steps in each thread, but only c context-switches Number of executions is O((n2k)c.n!) Not exponential in k … Additionally, scheduler can use polynomial amount of space Remember c spots for context switches Permutations of the n+c atomic blocks

Scheduling: Picking pre-emption points void Deposit100() { ChessSchedule(); EnterCriticalSection(&cs); balance += 100; LeaveCriticalSection(&cs); } void Withdraw100() { int t; ChessSchedule(); EnterCriticalSection(&cs); t = balance; LeaveCriticalSection(&cs); balance = t -100; } Heuristics: More pre-emption points in critical code, etc Coverage guarantee: When 2 context-switches are explored, every remaining bug requires at least 3 context-switches

CHESS: Summary Build a deterministic scheduler Advantages: Complications: Fairness and Live locks, weak memory models Advantages: Runs real code on real systems Only scheduler has been replaced Disadvantages: Is mostly program agnostic Exhaustive testing

Sequentialization CHESS approach: Concurrent program + bound on context switches  explore all interleavings General sequentialization approach: Concurrent program + bound on context switches  Sequential program Then, verify sequential program using your favourite verification technique Many flavours of context-bounded analysis: PDS based (Qadeer et al.) Transformation based sequentialization: Eager, Lazy (Lal et al.) BMC based (Parlato et al.)

Sequentialization: Basic idea What is hard about sequentialization? Have to remember local variables across phases (though they don’t change) If exploring T1  T2  T1, have to remember locals of T1 across phase of T2 Lal-Reps 2008: Instead, do a source to source transformation Copy each statement and global variable c times Now, we can explore T1  T1  T2 instead of T1  T2  T1 Only one threads local variables relevant at each stage

Sequentialization: Basic idea Replace each global variable X by X[tid][0..K] X[tid][i] represents the value of the global variable X the ith time thread tid is scheduled if (phase = 0) X[tid][0] := X[tid][0] + 1 else if (phase = 1) X[tid][1] := X[tid][1] + 1 … else if (phase = K) X[tid][K] = X[tid][K] + 1 if (phase < K && *) phase++; if phase == K + 1 phase = 1 Thread[tid+1]() X := X + 1

Sequentialization: Basic idea A program (T1||T2) is rewritten into Seq(T1); Seq(T2); check() Roughly, Execute each thread sequentially But, at random points, guess new values for global variables In the end, check the guessed new values are consistent for phase = 0 to K if (phase > 0) assume (X[0][phase] == X[N][phase – 1] for tid = 1 to N assume (X[tid][phase] == X[tid-1][phase])

Each green arrow is one part of the check! Sequentialization Each green arrow is one part of the check! Thread 0: Thread 1: … X[0][0] := X[0][0] + 1 … X[1][0] := X[1][0] + 1 … X[0][1] := X[0][1] + 1 … X[1][1] := X[1][1] + 1 … X[0][2] := X[0][2] + 1 … X[1][2] := X[1][2] + 1

Sequentialization The original Lal/Reps technique uses summarization for verification of the sequential program Compute summaries for the relation of initial and final values of global variables Extremely powerful idea Advantage: Reduces the need to reason about locals of different threads No need to reason explicitly about interleavings Interleavings encoded into data (variables) Scales linearly with number of threads

Sequentialization and BMC Currently, the best tools in the concurrency verification competitions use “sequentialization + BMC” The previous sequentialization technique is better suited for analysis techniques, not model checking No additional advantage using additional globals and then checking for consistency Instead, just explicitly use non-determinism

BMC for concurrency First, rewrite threads by unrolling loops and inlining function calls No loops No function calls Forward only control flow Write a driver “main” function to schedule the threads one by one

Naïve sequentialization for BMC threadi(): switch(pci) { case 0: goto 0; case 1: goto 1; … } 0: CS(0); stmt0; 1: CS(1); stmt1; M: CS(M); stmtm; CS(j) := if(*) { pci = j; return Main driver: pc0 = 0, … , pcn = 0 main() { for (r = 0; r < K, r++) for (i = 0; i < n; i++) threadi(); } The resume mechanism jumps into “right” spot in the thread There is a potential CS before each statement What’s the problem? Lots of jumps in the control flow Bad for SMT encoding

Better sequentialization for BMC threadi(): 0: CS(0); stmt0; 1: CS(1); stmt1; … M: CS(M); stmtm; CS(j) := if(j < pci || j >= nextCS) { goto j+1; } Main driver: pc0 = 0, … , pcn = 0 main() { for (r = 0; r < K, r++) for (i = 0; i < n; i++) nextCS = * assume (nextCS >= pci) threadi(); pci = nextCS } Avoid the multiple control flow breaking jumps Restricted non-determinism to one spot

Context bounding and Sequentialization: Summary Host of related techniques Can be adapted for analysis, model checking, testing, etc Different techniques need different kinds of tuning Basic idea: Most bugs require few context switches to turn up Can leverage standard sequential program analysis techniques

Odds and Ends Things we didn’t cover

Specification-free correctness In many cases we don’t want to write assertions Just want concurrent program to do the same thing as a sequential program is doing Standard correctness conditions Linearizability [Herlihy/Wing 91] Serializability [Papadimitrou and others 70s] Conc. Exec Method 0 Method 2 Method 1 Method 3 Method 0 Method 3 Method 1 Seq. Exec Method 2

Testing for concurrency Root cause of bugs Ordering violations Atomicity violations Data races Coverage metrics and coverage guided search Define use pairs [Tasirin et al] Find ordering violations based on define use orderings HaPSet [ Wang et al] Find interesting interleavings by trying to cover all “immediate histories” of events Cute/JCute [Sen et al] Concolic testing: Accumulate constraints along test run to guide future test runs

(Symbolic) Predictive Analysis Analyze variations of the given concurrent trace Run a test and record information Build a predictive model by relaxing scheduling constraints Analyze predictive model for alternate inter-leavings Can flag false bugs Symbolic predictive analysis From a trace, build precise predictive model (as SMT formula) No false bugs

This is the End Brief overview of concurrent verification techniques Lecture 1: Race detection Lecture 2: Full proof techniques Lecture 3: Bug finding What did we learn? Full verification is hard, not many techniques for weak- memory architectures Use light-weight and incomplete techniques to detect shallow bugs Code using a strict concurrency discipline is more likely to be correct, easier to verify