rely guarantee reasoning for asynchronous programs
play

Rely/Guarantee Reasoning for Asynchronous Programs Ivan Gavran 1 , - PowerPoint PPT Presentation

Rely/Guarantee Reasoning for Asynchronous Programs Ivan Gavran 1 , Filip Niksic 1 , Aditya Kanade 2 , Rupak Majumdar 1 , Viktor Vafeiadis 1 1 Max Planck Institute for Software Systems (MPI-SWS), Germany 2 Indian Institute of Science, Bangalore,


  1. Rely/Guarantee Reasoning for Asynchronous Programs Ivan Gavran 1 , Filip Niksic 1 , Aditya Kanade 2 , Rupak Majumdar 1 , Viktor Vafeiadis 1 1 Max Planck Institute for Software Systems (MPI-SWS), Germany 2 Indian Institute of Science, Bangalore, India

  2. Asynchronous programming is widespread • Web apps : AJAX, jQuery, XMLHttpRequest • Smartphone apps : AsyncTask, dispatch_async • Server-side : node.js, java.nio • Systems : kqueue, epoll, Libevent • Other : async/await in Scala

  3. Common feature: Posting tasks for later execution A pending tasks

  4. Common feature: Posting tasks for later execution A pending tasks B C

  5. Common feature: Posting tasks for later execution A B C pending tasks

  6. Common feature: Posting tasks for later execution A B C Tasks may be executed when pending tasks • triggered by external events (mouse click, response ready, socket ready, …) • dispatched by a scheduler

  7. Drawback: Obscured control-flow A B C

  8. Drawback: Obscured control-flow A C B Multiple pending tasks may be executed in any order .

  9. Drawback: Obscured control-flow A C B precondition P B

  10. Drawback: Obscured control-flow A C B precondition P B postcondition Q A Q A ⇒ P B

  11. Drawback: Obscured control-flow A C B precondition P B postcondition Q A Q A ⇒ P B C might invalidate P B

  12. Adapting rely/guarantee reasoning [Jones83] A C B precondition P B postcondition Q A Q A ⇒ P B

  13. Adapting rely/guarantee reasoning [Jones83] A C B precondition P B postcondition Q A Q A ⇒ P B rely R B : “preserve P B ”

  14. Adapting rely/guarantee reasoning [Jones83] A C B precondition P B postcondition Q A Q A ⇒ P B rely R B : “preserve P B ” guarantee G C G C ⇒ R B

  15. Soundness of rely/guarantee reasoning Given a program with specification in terms of predicates P, Q, R, G, if the predicates satisfy “natural rely/guarantee • conditions” each task meets its rely/guarantee specification • then the program is correct.

  16. Rely/guarantee reasoning is modular Sufficient to verify each task in isolation , using a verifier for sequential software.

  17. Contributions We have: • Identified the “natural rely/guarantee conditions” • Proved soundness of rely/guarantee reasoning • Demonstrated the approach on two C programs that use Libevent (done using Frama-C)

  18. The rest of the talk: Rely/guarantee… … by example … in theory … in practice

  19. The rest of the talk: Rely/guarantee… … by example … in theory … in practice

  20. Modeling asynchronous tasks Extend an imperative language with asynchronous procedures , together with constructs: post f(v 1 , …, v k ) delete f(v 1 , …, v k ) Maintain a set of pending procedure instances . Execute instances atomically in a non-deterministic order .

  21. Example: ROT13 server async main() { int socket = prepare_socket(); post accept(socket); } async accept( int socket) { struct client *c = malloc(…); client_setup(c); c->fd = accept_connection(socket); post read(c); post accept(socket); } async read( struct client *c) { … } async write( struct client *c) { … }

  22. Example: ROT13 server async read( struct client *c) { async write( struct client *c) { if (…) { // c->fd is ready if (…) { // c->fd is ready receive_chunk(c); send_chunk(c); post write(c); if (more_to_send(c)) post read(c); post write(c); } } else { // connection is closed else { // connection is closed delete write(c); delete read(c); free(c); free(c); } } } }

  23. Example: ROT13 server //@ requires valid(c); //@ requires valid(c); async read( struct client *c) { async write( struct client *c) { if (…) { // c->fd is ready if (…) { // c->fd is ready receive_chunk(c); send_chunk(c); post write(c); if (more_to_send(c)) post read(c); post write(c); } } else { // connection is closed else { // connection is closed delete write(c); delete read(c); free(c); free(c); } } } }

  24. Introducing predicate posted f For each asynchronous procedure f(x 1 ,…,x k ) , we introduce a predicate posted f (x 1 , …, x k ) True iff f has been posted with arguments x 1 , …, x k during the execution of the current asynchronous procedure .

  25. Example: ROT13 server /*@ requires valid(c); /*@ requires valid(c); @ ensures ∀ c 1 ; @ ensures ∀ c 1 ; @ posted_read(c 1 ) ⇒ valid(c 1 ); @ posted_write(c 1 ) ⇒ valid(c 1 ); @ ensures ∀ c 1 ; @*/ @ posted_write(c 1 ) ⇒ valid(c 1 ); async write( struct client *c) { if (…) { // c->fd is ready @*/ send_chunk(c); async read( struct client *c) { if (more_to_send(c)) if (…) { // c->fd is ready post write(c); receive_chunk(c); } post write(c); else { // connection is closed post read(c); delete read(c); } free(c); else { // connection is closed } delete write(c); } free(c); } }

  26. Preserving the precondition read(c) write(c) P write ( c ) ≡ valid( c ) P write ( c ) ≡ valid( c ) parent child

  27. Preserving the precondition read(c 1 ) write(c 1 ) read(c) accept(socket) write(c) P write ( c ) ≡ valid( c ) P write ( c ) ≡ valid( c ) parent concurrent siblings child

  28. Preserving the precondition read(c 1 ) write(c 1 ) read(c) accept(socket) write(c) G read ⇒ R write guarantee P write rely on P write G write ⇒ R write is preserved being preserved G accept ⇒ R write parent concurrent siblings child

  29. Introducing predicate pending f For each asynchronous procedure f(x 1 ,…,x k ) , we introduce a predicate pending f (x 1 , …, x k ) True iff f with arguments x 1 , …, x k is pending , i.e. is in the set of pending procedure instances.

  30. write ’s rely predicate R write R write ≡ ∀ c. (pending’ write (c) ∧ pending write (c) ∧ valid’(c)) ⇒ valid(c) (prime means at the beginning of execution)

  31. write ’s global invariant With write ’s parents ensuring: ∀ c. posted write (c) ⇒ valid(c) and write ’s concurrent siblings ensuring: ∀ c. (pending’ write (c) ∧ pending write (c) ∧ valid’(c)) ⇒ valid(c) rely/guarantee ensures a global invariant : ∀ c. pending write (c) ⇒ valid(c)

  32. Final specification of write /*@ requires Precondition: @ valid(c); @ ensures Parent_child_condition: @ ∀ c 1 ; posted_write(c 1 ) ⇒ valid(c 1 ); @ ensures Guarantee: @ ( ∀ c 1 ; (pending_read’(c 1 ) ∧ pending_read(c 1 ) @ ∧ valid’(c 1 )) ⇒ valid(c 1 )) @ ∧ ( ∀ c 1 ; (pending_write’(c 1 ) ∧ pending_write(c 1 ) @ ∧ valid’(c 1 )) ⇒ valid(c 1 )); @*/ async write( struct client *c) { … }

  33. Final specification of write /*@ requires Precondition: @ valid(c); @ ensures Parent_child_condition: @ ∀ c 1 ; posted_write(c 1 ) ⇒ valid(c 1 ); @ ensures Guarantee: @ ( ∀ c 1 ; (pending_read’(c 1 ) ∧ pending_read(c 1 ) } R read @ ∧ valid’(c 1 )) ⇒ valid(c 1 )) @ ∧ ( ∀ c 1 ; (pending_write’(c 1 ) ∧ pending_write(c 1 ) } R write @ ∧ valid’(c 1 )) ⇒ valid(c 1 )); @*/ async write( struct client *c) { … }

  34. Final specification of write /*@ requires Precondition: @ valid(c); @ ensures Parent_child_condition: @ ∀ c 1 ; posted_write(c 1 ) ⇒ valid(c 1 ); @ ensures Guarantee: @ ( ∀ c 1 ; (pending_read’(c 1 ) ∧ pending_read(c 1 ) } R read @ ∧ valid’(c 1 )) ⇒ valid(c 1 )) @ ∧ ( ∀ c 1 ; (pending_write’(c 1 ) ∧ pending_write(c 1 ) } R write @ ∧ valid’(c 1 )) ⇒ valid(c 1 )); @*/ async write( struct client *c) { … } write can now be verified in isolation using a standard verification tool (in our case Frama-C)

  35. The rest of the talk: Rely/guarantee… … by example … in theory … in practice

  36. Rely/guarantee decomposition For each asynchronous procedure f we require: • P f — precondition predicate • R f — rely predicate • G f — guarantee predicate • Q f — postcondition predicate First-order formulas; may include predicates posted g and pending g (in negative positions)

  37. Rely/guarantee conditions Given a rely/guarantee decomposition, for each asynchronous procedure f : (1) Q f ⇒ G f (2) Q g ⇒ (posted f ⇒ P f ), for each g ∈ parents( f ) (3) R f ⇒ ((pending’ f ∧ pending f ∧ P’ f ) ⇒ P f ) (4) G g ⇒ R f , for each g ∈ siblings( f )

  38. Soundness of rely/guarantee reasoning Theorem. Given an asynchronous program with a rely/guarantee decomposition, if • the decomposition satisfies the rely/guarantee conditions • each procedure meets its specification (P and Q) then the program is correct.

  39. Key lemma Lemma. For each asynchronous procedure f , at every schedule point we have pending f ⇒ P f

  40. The rest of the talk: Rely/guarantee… … by example … in theory … in practice

  41. Generic rely/guarantee predicates Given preconditions P f , the weakest predicates that satisfy the rely/guarantee conditions: • R f ≡ (pending’ f ∧ pending f ∧ P’ f ) ⇒ P f • G f ≡ ⋀ R g g ∈ siblings( f ) • Q f ≡ G f ∧ ⋀ posted g ⇒ P g g ∈ children( f )

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend