1 / 54

On Sequentializing Concurrent Programs (Bounded Model Checking)

This study focuses on utilizing BMC approach for sequentializing concurrent C programs to enable efficient reachability analysis, bug finding, and shared memory handling in a structured manner. Various BMC tools, like BLITZ, CBMC, and ESBMC, are explored for tackling the reachability problem, assertion failures, and concurrency issues in concurrent programs. The sequentialization process involves code-to-code translation, Bounded Program Solver, and Sequentialization tool development to target BMC analyses for scalability and simplicity.

villatoro
Download Presentation

On Sequentializing Concurrent Programs (Bounded Model Checking)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. On SequentializingConcurrent Programs (Bounded Model Checking) GennaroParlato University of Southampton, UK UPMARC 7th Summer School on Multicore Computing, June 8-10, 2015

  2. Concurrent Programs - Reachability Problem 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 SHARED MEMORY … T1 TN T2 THREADS

  3. BMC approach – Sequential Programs Efficient tools for C • BLITZ [ Cho, D'Silva, Song – ASE’13 ] • CBMC [ Clarke, Kroening, Lerda – TACAS’04 ] • LLBMC [ Falke, Merz, Sinz – ASE’13 ] • ESBMC [ Cordeiro, Fischer, Marques-Silva – ASE’09 ] SAT/SMT FORMULA BOUNDED PROGRAM SOLVER PROGRAM inlining unrolling SSA form

  4. BMC approach - Concurrent C Programs SAT/SMT FORMULA BOUNDED PROGRAM SOLVER CONC PROGRAM 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 ]

  5. Sequentialization CONC PROGRAM SAT/SMT FORMULA BOUNDED PROGRAM SOLVER SEQUENTIALIZATION (code-to-code translation) BMC SEQ TOOL SEQ PROGRAM • 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]

  6. Sequentialization CONC PROGRAM SAT/SMT FORMULA BOUNDED PROGRAM SOLVER SEQUENTIALIZATION (code-to-code translation) BMC SEQ TOOL SEQ PROGRAM • BMC-based tools (Implementations of variants of Lal/Reps schema) • Corral (microsoft research) [ Lal, Qadeer, Lahiri – CAV’12, FSE’14 ] • Rek[ Chaki, Gurfinkel, Strichman – FMCAD’11 ] • STORM[ Lahiri,Qadeer,Rakamaric CAV’09 ]

  7. Sequentialization CONC PROGRAM SAT/SMT FORMULA BOUNDED PROGRAM SOLVER SEQUENTIALIZATION (code-to-code translation) BMC SEQ TOOL SEQ PROGRAM • We have designed • new sequentializations targeting BMC • scalable analyses + surprisingly simple • Lazy-CSeq • Memory Unwinding

  8. Lazy-CSeq: Schema Overview (new sequentialization for BMC) [ Inverso–Tomasco–Fischer–La Torre–Parlato, CAV’14 ]

  9. Lazy-CSeq Approach CONC PROGRAM BOUNDED PROGRAM SEQUENTIALIZATION (code-to-code translation) BMC SEQUENTIAL TOOL SEQ PROGRAM

  10. Bounded Concurrent Programs main() T0 … T1 TN-1 TN • no loops • no function calls • Control flow only forward • one procedure for each thread

  11. Round Robin Schedule round 1 round 2 round 3 main() T0 … T1 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 ]

  12. Schema Overview … bounded concurrent program main() T0 TN T1 Sequentialization (code-to-code translation) … translates translates translates “equivalent” Sequential program with non determinism … F0 FN main() F1 Sequentialized functions Driver

  13. Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION • a global pc for each thread • thread locals  thread global main driver pc0=0; ... pcN=0; local0; ... localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); }

  14. Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION • for each round • for each thread Ti • simulate Ti main driver pc0=0; ... pcN=0; local0; ... localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); }

  15. Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; ... case M: goto M; } 1: CS(0); stmt0; 2: CS(1); stmt1; 3: CS(2);stmt2; .. . E XE . .. M: CS(M);stmtM; main driver pc0=0; ... pcN=0; local0; ... localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); }

  16. Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() switch(pci) { case 0: goto 0; case 1: goto 1; case 2: goto 2; ... case M: goto M; } 1:CS(0);stmt0; 2: CS(1);stmt1; 3: CS(2);stmt2; .. . E XE . .. M: CS(M);stmtM; main driver context-switch resume mechanism pc0=0; ... pcN=0; local0; ... localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); } ... ...

  17. Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; ... case M: goto M; } 1: CS(1);stmt0; 2: CS(2);stmt1; 3: CS(3); stmt2; .. . E XE . . . M: CS(M);stmtM; main driver pc0=0; ... pcN=0; local0; ... localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); } ... ... ... Context-switch simulation: #define CS(j) if (*) { pci=j; return; }

  18. Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION Fi() switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; ... case M: goto M; } 1: CS(1);stmt0; 2: CS(2);stmt1; 3: CS(3); stmt2; .. . E XE . . . M: CS(M);stmtM; main driver pc0=0; ... pcN=0; local0; ... localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); } ... ... ...

  19. Naïve Lazy Sequentialization: CROSS PRODUCT SIMULATION switch(pck) { case 0: goto 0; case 1: goto 1; case 2: goto 2; ... case M: goto M; } 1: CS(0);stmt0; 2: CS(1);stmt1; 3: CS(2); stmt2; .. . E XE . . . M: CS(M);stmtM; main driver Formula encoding: goto statement to formula add a guard for each crossing control-flow edge = O(M2) guards pc0=0; pc1=0; ... pcN=0; local0; local1; ... localk; main() { for (r=0; r<R; r++) for(k=0; k<N; k++) // simulate Tk Fk(); } ... ... ...

  20. 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; } 1: CS(0);stmt0; 2: CS(1);stmt1; 3: CS(2); stmt2; .. . E XE . . . M: CS(M);stmtM; main driver pc0=0; ... pcN=0; local0; ... localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); } ... ... ...

  21. 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; } 1: CS(0);stmt0; 2: CS(1);stmt1; 3: CS(2); stmt2; .. . E XE . . . M: CS(M);stmtM; main driver pc0=0; ... pcN=0; local0; ... localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); } ... ... ...

  22. 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; } 1: CS(0);stmt0; 2: CS(1);stmt1; 3: CS(2); stmt2; .. . E XE . . . M: CS(M);stmtM; main driver pc0=0; ... pcN=0; local0; ... localk; main() { for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) Fi(); } ...

  23. 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; } 1: CS(1);stmt0; 2: CS(2);stmt1; 3: CS(3); stmt2; .. . E XE . . . M: CS(M);stmtM; main driver pc0=0; ... pcN=0; local0; ... localk; nextCS; main() for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) nextCS = nondet; assume(nextCS>=pci) Fi(); pci = nextCS; ... #define CS(j) NEW if (j<pci || j>=nextCS) goto j+1;

  24. 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; } 1: CS(1);stmt0; 2: CS(2);stmt1; 3: CS(3); stmt2; .. . E XE . . . M: CS(M);stmtM; main driver pc0=0; ... pcN=0; local0; ... localk; nextCS; main() for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) nextCS = nondet; assume(nextCS>=pci) Fi(); pci = nextCS; #define CS(j) NEW if (j<pci || j>=nextCS) goto j+1;

  25. 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; } 1: CS(0);stmt0; 2: CS(1);stmt1; 3: CS(2); stmt2; .. . E XE . . . M: CS(M);stmtM; main driver pc0=0; ... pcN=0; local0; ... localk; nextCS; main() for (r=0; r<K; r++) for (i=0; i<N; i++) // simulate Ti if (activei) nextCS = nondet; assume(nextCS>=pci) Fi(); pci = nextCS; ... #define CS(j) NEW if (j<pci || j>=nextCS) goto j+1;

  26. CSeq-Lazy Sequentialization:CROSS PRODUCT SIMULATION resuming + context-switch 1: CS(1); stmt1; 2: CS(2); stmt2; 3: CS(3); stmt3; EXECUTE M: CS(M); stmtM; skip ... pci nextCS skip ... #define CS(j)NEW if (j<pci || j>=nextCS) goto j+1;

  27. Individual Threads Sequentialization 1: CS(1); stmt1; 2: CS(2); stmt2; 3: CS(3); stmt3; EXECUTE M: CS(M); stmtM; Formula encoding: goto statement to formula add a guard for each crossing control-flow edge = O(M) guards ... ...

  28. Individual Threads Sequentialization 1: CS(1); stmt1; 2: CS(2); stmt2; 3: CS(3); stmt3; EXECUTE M: CS(M); stmtM; ... • inject light-weight, non-invasive control code • no non-determinism • no assignments • no return ... #define CS(j) if (j<pci || j>=next_CS) goto pc+1;

  29. Experiments

  30. Evaluation: bug-huntingSVCOMP’14, Concurrency (UNSAFE instances)

  31. Evaluation: bug-huntingSVCOMP’14, Concurrency (UNSAFE instances)

  32. Remarks Lazy-CSeq is 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 • Lazy does not require an implementation of a memory model and handling of error checks (as opposed to LR sequentialization) Lazy-CSeq won 2gold medals in the Concurrency category of the last two editions of the software verification competition SV-COMP • all verification tasks solved • 30x faster than the best tool with native concurrency handling

  33. Sequentialization based on Memory Unwinding [ Tomasco–Inverso–Fischer–La Torre–Parlato, TACAS’15 ]

  34. Interleaving semantics T1 T2 T3 run wx wy rx wy rx ry wx wx rx ry wy rx

  35. From interleavings to memory unwinding T1 T2 T3 run wx wy rx wy rx ry wx wx rx ry wy rx accesses to sharedmemory wx wy rx wy rx ry wx rx ry wy rx MEMORY UNWINDING wx wy writes wx wy wy wx wy wy wx wy ⇒ Memory unwinding models thread interaction history by data

  36. Memory unwindings as thread interfaces • bounding parameter: # of shared write operations • most concurrency bugs exposed by few interactions [Lu, Park, Seo, Zhou – ASPLOS 2008] TASK 2 TASK 1 MEMORY UNWINDING T1 T2 T1 Assume-guarantee reasoning style decomposition of verification

  37. Assume-guarantee reasoning TASK 2 MEMORY UNWINDING TASK 1 T1 T2 Task 1: Task 2: Thread T1 assumes: MU writes of other threads guarantees: its own MU writes Thread T2 assumes: MU writes of other threads guarantees: its own MU writes 

  38. Simulating a thread against an MU Global variable write – check against current MU entry void write(uint t, uint v, intval) { mc[t] = th_nxt_wr[t][mc[t]]; assume(var[mc[t]] == v); assume(val[mc[t]] == val); } void write(uint t, uint v, intval) { mc[t] = th_nxt_wr[t][mc[t]]; } y=1 …. a=x+5 ..... x=1 …. mc mc pc pc x=2 y=1 y=1 z=2 x=3 y=8 x=1

  39. Simulating a thread against an MU Local statement (no global variables) – update pc, keep mc y=1 …. a=x+5 ..... x=1 …. mc pc pc x=2 y=1 y=1 z=2 x=3 y=8 x=1

  40. Simulating a thread against an MU Global variable read – “pick write position in range” non-deterministic assignment int read(uint t, uint v) { if (thr_terminated()) return 0; if (var_fst_wr[v]==0) return 0; uintr_from = *; assume((r_from <= last_wr_pos) &&(r_from< th_nxt_wr[t][mc[t]])); assume(var[r_from] == v); if (r_from< mc[t]) assume(var_nxt_wr[r_from] > mc[t]); else { if (r_from < var_fst_wr[v]) return 0; mc[t] = r_from; }; return value[r_from]; } y=1 …. a=x+5 ..... x=1 …. mc pc x=2 y=1 y=1 z=2 x=3 y=8 x=1

  41. Simulating a thread against an MU Global variable read – “pick write position in range” Check in unwinding... ...before next write of thread... int read(uint t, uint v) { if (thr_terminated()) return 0; if (var_fst_wr[v]==0) return 0; uintr_from= *; assume((r_from <= last_wr_pos) &&(r_from< th_nxt_wr[t][mc[t]])); assume(var[r_from] == v); if (r_from< mc[t]) assume(var_nxt_wr[r_from] > mc[t]); else { if (r_from < var_fst_wr[v]) return 0; mc[t] = r_from; }; return value[r_from]; } y=1 …. a=x+5 ..... x=1 …. mc pc x=2 y=1 y=1 z=2 x=3 y=8 x=1

  42. Simulating a thread against an MU Global variable read – “pick write position in range” ...before next write of thread... int read(uint t, uint v) { if (thr_terminated()) return 0; if (var_fst_wr[v]==0) return 0; uintr_from= *; assume((r_from <= last_wr_pos) && (r_from< th_nxt_wr[t][mc[t]])); assume(var[r_from] == v); if (r_from< mc[t]) assume(var_nxt_wr[nxt_mc] > mc[t]); else { if (r_from< var_fst_wr[v]) return 0; mc[t] = r_from; }; return value[r_from]; } y=1 …. a=x+5 ..... x=1 …. mc pc x=2 y=1 y=1 z=2 x=3 y=8 ...right variable... x=1

  43. Simulating a thread against an MU Global variable read – “pick write position in range” int read(uint t, uint v) { if (thr_terminated()) return 0; if (var_fst_wr[v]==0) return 0; uintr_from= *; assume((r_from <= last_wr_pos) &&(r_from< th_nxt_wr[t][mc[t]])); assume(var[r_from] == v); if (r_from< mc[t]) assume(var_nxt_wr[r_from] > mc[t]); else { if (r_from < var_fst_wr[v]) return 0; mc[t] = r_from; }; return value[r_from]; } y=1 …. a=x+5 ..... x=1 …. mc pc x=2 y=1 y=1 z=2 x=3 y=8 ...right variable... x=1 ...next write of variable in future...

  44. Simulating a thread against an MU Global variable read – “pick write position in range” int read(uint t, uint v) { if (thr_terminated()) return 0; if (var_fst_wr[v]==0) return 0; uintr_from = *; assume((r_from <= last_wr_pos) &&(r_from< th_nxt_wr[t][mc[t]])); assume(var[r_from] == v); if (r_from< mc[t]) assume(var_nxt_wr[r_from] > mc[t]); else { if (r_from < var_fst_wr[v]) return 0; mc[t] = r_from; }; return value[r_from]; } y=1 …. a=x+5 ..... x=1 …. mc mc pc pc x=2 y=1 y=1 z=2 x=3 y=8 x=1 ...before next write of variable... ...else update mc. Return value.

  45. Simulating a thread against an MU Handling errors – “flag that an error occurs” y=1 …. a=x+5 ..... x=1 …. assert(b); pc x=2 y=1 y=1 z=2 x=3 y=8 x=1 translates to if (! b) _error = 1; (computation might not be feasible)

  46. Our apporach: sequentialization by MU … Concurrent program T0 TN T1 Sequentialization (code-to-code translation) … translates translates translates MEMORY UNWINDING Sequential program … F0 FN main() F1 Simulation functions

  47. Main Sequential Program Thread creation main void main(void){ memory_init(W); ct := mem_thread_create(); F0(); thread_terminate(ct); all_thread_simulated(); assert(_error == 0) } instantiate memory unwinding register main thread simulation starts from main thread all writes of the thread are executed all writes of the MU are executed error check

  48. CSeq framework + Evaluation

  49. CSeq framework • is a framework that simplifies code-to-code translations • for C programs + Pthread • comprises several code-to-code translation modules • supports several sequential analysis back-end tools • Internal modules • unrolling • function inlining • counter-example • … testing Klee sequential non-deterministic C program concurrent C program • bounded • model-checking • BLITZ • CBMC • ESBMC • LLBM sequential analysis tool code-to-code translation P P' • abstraction • CPA-checker • Frama-C • SATABS • Sequentialisations • Memory-Unwinding • Lazy-CSeq • LR-CSeq • … http://users.ecs.soton.ac.uk/gp4/cseq/

  50. Evaluation[ SV–COMP 2014 2015 ] • SV-COMP software verification competition @ TACAS • Concurrency category benchmarks: 1003 files • Lazy-CSeq won 2 GOLD medals (2014, 2015) • MU-CSeq won 2 SILVER medals (2014, 2015)

More Related