Bounded Model Checking of MultiThreaded C Programs via
Bounded Model Checking of Multi-Threaded C Programs via Lazy Sequentialization Omar Inverso Ermenegildo Tomasco Bernd Fischer Salvatore La Torre University of Southampton, UK Gennaro Parlato University of Southampton, UK Stellenbosch University, South Africa Università di Salerno, Italy
Concurrent Programs - Reachability Problem SHARED MEMORY … T 1 TN T 2 concurrent C programs • • POSIX threads SC memory model reachability • • • assertion failure out-of-bound array division-by-zero, … bounded model checking (BMC) • bug-finding, not complete analysis THREADS
BMC approach - Sequential C Programs PROGRAM BOUNDED PROGRAM SAT/SMT FORMULA SOLVER inlining unrolling SSA form tools • • BLITZ CBMC LLBMC ESBMC [ Cho, D'Silva, Song – ASE’ 13 ] [ Clarke, Kroening, Lerda – TACAS’ 04 ] [ Falke, Merz, Sinz – ASE’ 13 ] [ Cordeiro, Fischer, Marques-Silva – ASE’ 09 ]
BMC approach - Concurrent C Programs CONC PROGRAM BOUNDED PROGRAM SAT/SMT FORMULA concurrency handling direct SAT/SMT approach • • • encode each thread as in the sequential case add a conjunct for shared memory operations all possible interleavings in the bounded program φthreads ∧ φconcurrency papers: • • [ Sinha, Wang – POPL’ 11 ] [ Alglave, Kroening, Tautschnig – CAV’ 13 ] SOLVER
(code-to-code translation) SEQUENTIALIZATION Sequentialization CONC PROGRAM BOUNDED PROGRAM SEQ TOOL SAT/SMT FORMULA SOLVER pros • reuse robust sequential analysis tools • fast prototyping of concurrency handling • delegating all sequential reasoning to an existing target analysis tool • easier to implement than full-fledged tools
(code-to-code translation) SEQUENTIALIZATION Sequentialization CONC PROGRAM BOUNDED PROGRAM SEQ TOOL SAT/SMT FORMULA SOLVER papers • proposal [ Qadeer, Wu – PLDI’ 04 ] • eager, bounded context-switch, finite # threads [ Lal, Reps – CAV’ 08 ] • lazy, finite # threads, parameterized [La Torre, Madhusudan, Parlato – CAV’ 09, CAV’ 10] • thread creation [Bouajjani, Emmi, Parlato – SAS’ 11] [Emmi, Qadeer, Rakamaric – POPL’ 11] • Lal/Reps for real-time systems [Chaki, Gurfinkel, Strichman – FMCAD’ 11] • message-passing programs [Bouajjani, Emmi -- TACAS’ 12]
(code-to-code translation) SEQUENTIALIZATION Sequentialization CONC PROGRAM BOUNDED PROGRAM SEQ TOOL tools • • SAT/SMT FORMULA SOLVER (Implementations of variants of Lal/Reps schema) Corral CSeq Rek STORM [ Lal, Qadeer, Lahiri – CAV’ 12 ] [ Fischer, Inverso, Parlato – ASE’ 13 ] [ Chaki, Gurfinkel, Strichman – FMCAD’ 11 ] [ Lahiri, Qadeer, Rakamaric CAV’ 09 ] BMC based
(code-to-code translation) SEQUENTIALIZATION Sequentialization CONC PROGRAM BOUNDED PROGRAM SEQ TOOL SAT/SMT FORMULA SOLVER what we propose new sequentialization targeting BMC efficient + surprisingly simple
Lazy-CSeq: Schema Overview (new sequentialization for BMC)
(code-to-code translation) SEQUENTIALIZATION Lazy-CSeq Approach CONC PROGRAM BOUNDED PROGRAM SEQ PROGRAM BMC SEQUENTIAL TOOL
Bounded Concurrent Programs main() T 0 • • T 1 … no loops no function calls Control flow only forward one procedure for each thread TN-1 TN
Round Robin Schedule round 1 round 2 round 3 T 0 T 1 … main() TN-1 TN round k Lazy-Cseq sequentialization: • captures all bounded Round-Robin computations for a given bound • error manifest themselves within very few rounds [ Musuvathi, Qadeer – PLDI’ 07 ]
Schema Overview T 1 TN translates … main() T 0 … bounded concurrent program Sequentialization (code-to-code translation) … F 0 F 1 Sequentialized functions sequential program FN main() Driver
Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION main driver pc 0=0; . . . pc. N=0; local 0; . . . localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) } Fi(); • a global pc for each thread • thread locals thread global
Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION main driver pc 0=0; . . . pc. N=0; local 0; . . . localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) } Fi(); for each round for each thread Ti simulate Ti
Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() main driver pc 0=0; . . . pc. N=0; local 0; . . . localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) } Fi(); switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; } 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M;
Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION main driver. . . pc 0=0; . . . pc. N=0; local 0; . . . localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) . . . } Fi(); switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; } 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; context-switch resume mechanism Fi()
Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() main driver . . . pc 0=0; . . . pc. N=0; local 0; . . . localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; Context-switch simulation: #define CS(j) if (*) { pci=j; return; } . . . } Fi(); switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; }
Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() main driver . . . pc 0=0; . . . pc. N=0; local 0; . . . localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; . . . } Fi(); switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; }
Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION main driver. . . pc 0=0; pc 1=0; . . . pc. N=0; local 1; . . . localk; Formula encoding: main() { for (r=0; r<R; r++) goto statement to formula for (k=0; k<N; k++) // simulate Tk = O(M 2) guards 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; . . . } . . . add a guard for each crossing control Fk(); -flow edge switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; }
CSeq-Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() main driver 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; . . . main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); } . . . pc 0=0; . . . pc. N=0; local 0; . . . localk; switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; }
CSeq-Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() main driver 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; . . . main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); } . . . pc 0=0; . . . pc. N=0; local 0; . . . localk; switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; }
CSeq-Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() main driver pc 0=0; . . . pc. N=0; local 0; . . . localk; 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; . . . main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); } switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; }
CSeq-Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; } main driver 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; #define CS(j) NEW if (j<pci || j>=next. CS) goto j+1; . . . pc 0=0; . . . pc. N=0; local 0; . . . localk; next. CS; main() for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) next. CS = nondet; assume(next. CS>=pci) Fi(); pci = next. CS;
CSeq-Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; } main driver pc 0=0; . . . pc. N=0; local 0; . . . localk; next. CS; main() for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) next. CS = nondet; assume(next. CS>=pci) Fi(); pci = next. CS; 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; #define CS(j) NEW if (j<pci || j>=next. CS) goto j+1;
CSeq-Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; . . . case M: goto M; } main driver . . . pc 0=0; . . . pc. N=0; local 0; . . . localk; next. CS; main() for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) next. CS = nondet; assume(next. CS>=pci) Fi(); pci = next. CS; #define CS(j) 1: CS(0); stmt 0; 2: CS(1); stmt 1; 3: CS(2); stmt 2; . . . E XE. . . M: CS(M); stmt. M; NEW if (j<pci || j>=next. CS) goto j+1;
CSeq-Lazy Sequentialization: CROSS PRODUCT SIMULATION . . . skip resuming + context-switch 1: CS(1); stmt 1; 2: CS(2); stmt 2; 3: CS(3); stmt 3; pci EXECUTE next. CS . . . skip M: CS(M); stmt. M; #define CS(j) NEW if (j<pci || j>=next. CS) goto j+1;
Individual Threads Sequentialization . . . Formula encoding: EXECUTE = O(M) guards . . . goto statement to formula add a guard for each crossing control -flow edge 1: CS(1); stmt 1; 2: CS(2); stmt 2; 3: CS(3); stmt 3; M: CS(M); stmt. M;
Individual Threads Sequentialization . . . inject light-weight, invasive control code 1: CS(1); stmt 1; 2: CS(2); stmt 2; 3: CS(3); stmt 3; non- EXECUTE . . . • no non-determinism • no assignments • o return M: CS(M); stmt. M; #define CS(j) if (j<pci || j>=next_CS) goto pc+1;
Tool / Empirical Evaluation
Tool: CSeq rounds unwind backend sequential non-deterministic C program concurrent C program sequential BMC CSeq P P' true/false CBMC, ESBMC, LLBMC [ Fischer, Inverso, Parlato -- ASE’ 13 ]
Evaluation: bug-hunting SVCOMP’ 14, Concurrency (UNSAFE instances) 27_Boop_simple_vf 28_buggy_simple_. . . 32_pthread 5_vs 40_barrier_vf 49_bigshot_p 50_bigshot_s 53_fib_bench 55_fib_bench_longer 57_fib_bench_longest 61_lazy 01 63_qrcu 65_queue 67_read_write_lock 69_reorder_2 70_reorder_5 72_sigma 73_singleton 75_stack 77_stateful 01 82_twostage_3 0. 4 TO 0. 3 624. 7 0. 8 TO 0. 6 n/a 0. 3 1. 7 0. 5 4. 0 1. 8 31. 1 3. 2 150. 9 75. 2 TO 0. 5 398. 6 0. 7 TO 20. 9 TO 0. 4 TO 0. 7 TO 219. 1 TO 1. 6 TO 0. 8 TO 0. 7 TO 4. 9 TO Threader CSeq Corral R 2 0. 3 0. 8 0. 4 1 0. 2 0. 3 2 0. 4 0. 3 0. 2 1 0. 2 0. 3 0. 6 5 36. 6 1. 0 15. 2 2. 1 6 155. 5 1. 5 402. 1 3. 1 11 TO 214. 0 TO TO 1 0. 3 0. 2 0. 4 2 1. 4 0. 8 0. 7 safe 2 1. 6 8. 8 1. 1 TO 2 0. 5 0. 3 0. 4 safe 1 0. 3 0. 6 n/a 1. 3 1 0. 4 0. 9 n/a 3. 3 1 1. 4 7. 8 n/a 73. 0 3 0. 7 0. 5 safe 1 0. 2 0. 3 1. 0 1 0. 2 0. 3 0. 5 1 0. 3 0. 8 n/a 8. 0 ESBMC LLBMC Concurrent Tools ESBMC U 2 2 2 4 1 1 5 6 11 1 1 2 4 16 1 2 CBMC BLITZ Lazy-CSeq CBMC 1. 9 1. 0 117. 6 0. 8 0. 2 0. 3 2. 2 n/a TO 0. 8 n/a 0. 7 n/a n/a n/a 5. 8 6. 3 6. 9 14. 4 7. 2 10. 4 TO n/a 54. 3 1. 3 0. 7 7. 1 5. 8 safe TO n/a 128. 7 n/a 1. 8 2. 6 38. 4 1. 3 n/a 2. 4 1. 9 n/a 3. 5 n/a n/a n/a 2. 1 151. 9 2. 0 0. 7 0. 9 3. 6 n/a TO
Evaluation: bug-hunting SVCOMP’ 14, Concurrency (UNSAFE instances) 27_Boop_simple_vf 28_buggy_simple_. . . 32_pthread 5_vs 40_barrier_vf 49_bigshot_p 50_bigshot_s 53_fib_bench 55_fib_bench_longer 57_fib_bench_longest 61_lazy 01 63_qrcu 65_queue 67_read_write_lock 69_reorder_2 70_reorder_5 72_sigma 73_singleton 75_stack 77_stateful 01 82_twostage_3 0. 4 TO 0. 3 624. 7 0. 8 TO 0. 6 n/a 0. 3 1. 7 0. 5 4. 0 1. 8 31. 1 3. 2 150. 9 75. 2 TO 0. 5 398. 6 0. 7 TO 20. 9 TO 0. 4 TO 0. 7 TO 219. 1 TO 1. 6 TO 0. 8 TO 0. 7 TO 4. 9 TO Threader CSeq Corral R 2 0. 3 0. 8 0. 4 1 0. 2 0. 3 2 0. 4 0. 3 0. 2 1 0. 2 0. 3 0. 6 5 36. 6 1. 0 15. 2 2. 1 6 155. 5 1. 5 402. 1 3. 1 11 TO 214. 0 TO TO 1 0. 3 0. 2 0. 4 2 1. 4 0. 8 0. 7 safe 2 1. 6 8. 8 1. 1 TO 2 0. 5 0. 3 0. 4 safe 1 0. 3 0. 6 n/a 1. 3 1 0. 4 0. 9 n/a 3. 3 1 1. 4 7. 8 n/a 73. 0 3 0. 7 0. 5 safe 1 0. 2 0. 3 1. 0 1 0. 2 0. 3 0. 5 1 0. 3 0. 8 n/a 8. 0 ESBMC LLBMC Concurrent Tools ESBMC U 2 2 2 4 1 1 5 6 11 1 1 2 4 16 1 2 CBMC BLITZ Lazy-CSeq CBMC 1. 9 1. 0 117. 6 0. 8 0. 2 0. 3 2. 2 n/a TO 0. 8 n/a 0. 7 n/a n/a n/a 5. 8 6. 3 6. 9 14. 4 7. 2 10. 4 TO n/a 54. 3 1. 3 0. 7 7. 1 5. 8 safe TO n/a 128. 7 n/a 1. 8 2. 6 38. 4 1. 3 n/a 2. 4 1. 9 n/a 3. 5 n/a n/a n/a 2. 1 151. 9 2. 0 0. 7 0. 9 3. 6 n/a TO
Conclusions
Conclusions / Future Work We have presented a new sequentialization targeted to BMC backends • • lazy based on bounded round-robin computations efficient for bug-hunting simple to implement (CSeq framework) Eager vs Lazy • • no empirical evidence that lazy is faster (maybe faster because of good handing of CFG) Lazy does not require an implementation of memory model and handling of error checks Lazy-CSeq won the gold medal in the Concurrency category of SVCOMP’ 14 • • all verification tasks solved 30 x faster than the best tool with native concurrency handling Future Work • • integration with partial order reduction Weak Memory Models (WMM) Message Passing Interface (MPI) sequentializations targeting other analysis technologies: • • • abstract interpretation cegar-based testing
Thank You users. ecs. soton. ac. uk/gp 4/cseq
Evaluation: state space coverage Lazy-CSeq + CBMC vs CBMC (SAFE instances) How far is it possible to push the unwind bound with the two different methods and still finish the analysis within the given time and space requirements (10 GB, 750 s)? • CBMC starts failing >60% files when increasing unwind bound • bounding the rounds allows deeper exploration of loops • alternative coverage of the state space
Evaluation: formula size Lazy-CSeq + CBMC vs CBMC (SAFE instances) What is the VC size for sequentialized files compared to native concurrency handling? • • 5 x. . 15 x less variables 5 x. . 25 x less clauses
- Slides: 38