1 / 47

Type Inference Against Races

Type Inference Against Races. Cormac Flanagan UC Santa Cruz. Stephen N. Freund Williams College. Software Validation & Verification. Standard approach: Testing test coverage problem Multithreaded software increasing widespread (Java, C#, GUIs, servers) testing inadequate due to

Download Presentation

Type Inference Against Races

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. Type Inference Against Races Cormac Flanagan UC Santa Cruz Stephen N. Freund Williams College SAS’04: Type Inference Against Races

  2. Software Validation & Verification • Standard approach: Testing • test coverage problem • Multithreaded software • increasing widespread (Java, C#, GUIs, servers) • testing inadequate due to • test coverage • scheduling coverage • An important application for static analysis! SAS’04: Type Inference Against Races

  3. Errors in Multithreaded Software class Ref { int i; void add(Ref r) { i = i + r.i; } } SAS’04: Type Inference Against Races

  4. Errors in Multithreaded Software class Ref { int i; void add(Ref r) { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); x.add(y); x.add(y); assert x.i == 6; SAS’04: Type Inference Against Races

  5. Errors in Multithreaded Software class Ref { int i; void add(Ref r) { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { x.add(y); // two calls happen x.add(y); // in parallel } assert x.i == 6; A race condition occurs if • two threads access a shared variable at the same time • at least one of those accesses is a write SAS’04: Type Inference Against Races

  6. Lock-Based Synchronization class Ref { int i; // guarded by this void add(Ref r) { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6; • Field guarded by a lock • Lock acquired before accessing field • Ensures race freedom SAS’04: Type Inference Against Races

  7. Verifying Race Freedom • Race freedom a key correctness property • Rccjava [Flanagan-Freund, PLDI’99] • race condition checker for Java • verifies race freedom using a static analysis • analysis expressed as a type system • type annotations to specify locking discipline • guarded_by, requires, ... SAS’04: Type Inference Against Races

  8. Verifying Race Freedom with Types class Ref { int i; void add(Ref r) { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6; SAS’04: Type Inference Against Races

  9. Verifying Race Freedom with Types class Ref { int i guarded_by this; void add(Ref r) requires this, r { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6;  check: this  { this, r } SAS’04: Type Inference Against Races

  10. Verifying Race Freedom with Types class Ref { int i guarded_by this; void add(Ref r) requires this, r { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6;  check: this  { this, r } check: this[this:=r] = r  { this, r }  replace this by r SAS’04: Type Inference Against Races

  11. Verifying Race Freedom with Types class Ref { int i guarded_by this; void add(Ref r) requires this, r { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6;  check: this  { this, r } check: this[this:=r] = r  { this, r }  replace formals this,r by actuals x,y  check: {this,r}[this:=x,r:=y]  { x, y } SAS’04: Type Inference Against Races

  12. Verifying Race Freedom with Types class Ref { int i guarded_by this; void add(Ref r) requires this, r { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6;  check: this  { this, r } check: this[this:=r] = r  { this, r }  replace formals this,r by actuals x,y  check: {this,r}[this:=x,r:=y]  { x, y } check: {this,r}[this:=x,r:=y]  { x, y }  Soundness Theorem: Well-typed programs are race-free SAS’04: Type Inference Against Races

  13. Basic Type Inference class Ref { int i; void add(Ref r) { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6; SAS’04: Type Inference Against Races

  14. Basic Type Inference static final Object m =new Object(); class Ref { int i; void add(Ref r) { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6; Iterative GFP algorithm: • [Flanagan-Freund, PASTE’01] • Start with maximum set of annotations SAS’04: Type Inference Against Races

  15. Basic Type Inference static final Object m =new Object(); class Ref { int i guarded_by this, m; void add(Ref r) { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6; Iterative GFP algorithm: • [Flanagan-Freund, PASTE’01] • Start with maximum set of annotations SAS’04: Type Inference Against Races

  16. Basic Type Inference static final Object m =new Object(); class Ref { int i guarded_by this, m; void add(Ref r) requires this, r, m { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6; Iterative GFP algorithm: • [Flanagan-Freund, PASTE’01] • Start with maximum set of annotations SAS’04: Type Inference Against Races

  17. Basic Type Inference static final Object m =new Object(); class Ref { int i guarded_by this, m; void add(Ref r) requires this, r, m { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6; Iterative GFP algorithm: • [Flanagan-Freund, PASTE’01] • Start with maximum set of annotations • Iteratively remove all incorrect annotations X X SAS’04: Type Inference Against Races

  18. Basic Type Inference static final Object m =new Object(); class Ref { int i guarded_by this, m; void add(Ref r) requires this, r, m { i = i + r.i; } } Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (x,y) { x.add(y); } synchronized (x,y) { x.add(y); } } assert x.i == 6; Iterative GFP algorithm: • [Flanagan-Freund, PASTE’01] • Start with maximum set of annotations • Iteratively remove all incorrect annotations • Check each field still has a protecting lock Sound, complete, fast But type system too basic X X SAS’04: Type Inference Against Races

  19. Harder Example: External Locking class Ref { int i; void add(Ref r) { i = i + r.i; } } Object m = new Object(); Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (m) { x.add(y); } synchronized (m) { x.add(y); } } assert x.i == 6; • Field i of x and y protected by external lock m • Not typable with basic type system • m not in scope at i • Requires more expressive type system with ghost parameters SAS’04: Type Inference Against Races

  20. Ghost Parameters on Classes class Ref { int i; void add(Ref r) { i = i + r.i; } } Object m = new Object(); Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (m) { x.add(y); } synchronized (m) { x.add(y); } } assert x.i == 6; SAS’04: Type Inference Against Races

  21. Ghost Parameters on Classes class Ref<ghost g> { int i; void add(Ref r) { i = i + r.i; } } Object m = new Object(); Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (m) { x.add(y); } synchronized (m) { x.add(y); } } assert x.i == 6; • Ref parameterized by external ghost lock g SAS’04: Type Inference Against Races

  22. Ghost Parameters on Classes class Ref<ghost g> { int i guarded_by g; void add(Ref r) { i = i + r.i; } } Object m = new Object(); Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (m) { x.add(y); } synchronized (m) { x.add(y); } } assert x.i == 6; • Ref parameterized by external ghost lock g • Field i guarded by g SAS’04: Type Inference Against Races

  23. Ghost Parameters on Classes class Ref<ghost g> { int i guarded_by g; void add(Ref r) requires g { i = i + r.i; } } Object m = new Object(); Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (m) { x.add(y); } synchronized (m) { x.add(y); } } assert x.i == 6; • Ref parameterized by external ghost lock g • Field i guarded by g • g held when add called SAS’04: Type Inference Against Races

  24. Ghost Parameters on Classes class Ref<ghost g> { int i guarded_by g; void add(Ref<g> r) requires g { i = i + r.i; } } Object m = new Object(); Ref x = new Ref(0); Ref y = new Ref(3); parallel { synchronized (m) { x.add(y); } synchronized (m) { x.add(y); } } assert x.i == 6; • Ref parameterized by external ghost lock g • Field i guarded by g • g held when add called • Argument r also parameterized by g SAS’04: Type Inference Against Races

  25. Ghost Parameters on Classes class Ref<ghost g> { int i guarded_by g; void add(Ref<g> r) requires g { i = i + r.i; } } Object m = new Object(); Ref<m> x = new Ref<m>(0); Ref<m> y = new Ref<m>(3); parallel { synchronized (m) { x.add(y); } synchronized (m) { x.add(y); } } assert x.i == 6; • Ref parameterized by external ghost lock g • Field i guarded by g • g held when add called • Argument r also parameterized by g • x and y parameterized by lock m SAS’04: Type Inference Against Races

  26. Type Checking Ghost Parameters class Ref<ghost g> { int i guarded_by g; void add(Ref<g> r) requires g { i = i + r.i; } } Object m = new Object(); Ref<m> x = new Ref<m>(0); Ref<m> y = new Ref<m>(3); parallel { synchronized (m) { x.add(y); } synchronized (m) { x.add(y); } } assert x.i == 6;  check: {g} [this:=x,r:=y, g:=m]  {m} SAS’04: Type Inference Against Races

  27. Type Inference with Ghosts • HARD • iterative GFP algorithm does not work • check may fail because of two annotations • which should we remove? • requires backtracking search • NP-complete! • Our approach • reduce type inference to SAT • use fast, modern SAT solver (Chaff) SAS’04: Type Inference Against Races

  28. Reducing Type Inference to SAT class Ref { int i; void add(Ref r) { i = i + r.i; } } SAS’04: Type Inference Against Races

  29. Reducing Type Inference to SAT class Ref<ghost g1,g2,...,gn> { int i; void add(Ref r) { i = i + r.i; } } SAS’04: Type Inference Against Races

  30. Reducing Type Inference to SAT class Ref<ghost g> { int i; void add(Ref r) { i = i + r.i; } } • Add ghost parameters <ghost g>to each class declaration SAS’04: Type Inference Against Races

  31. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref r) { i = i + r.i; } } • Add ghost parameters <ghost g>to each class declaration • Add guarded_by i to each field declaration • type inference resolves i to some lock SAS’04: Type Inference Against Races

  32. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref<2> r) { i = i + r.i; } } • Add ghost parameters <ghost g>to each class declaration • Add guarded_by i to each field declaration • type inference resolves i to some lock • Add <2> to each class reference SAS’04: Type Inference Against Races

  33. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref<2> r) requires  { i = i + r.i; } } • Add ghost parameters <ghost g>to each class declaration • Add guarded_by i to each field declaration • type inference resolves i to some lock • Add <2> to each class reference • Add requires ito each method • type inference resolves i to some set of locks SAS’04: Type Inference Against Races

  34. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref<2> r) requires  { i = i + r.i; } } Constraints: 1  { this, g } 2  { this, g }  { this, g, r } 1  1[this := r, g:=2] SAS’04: Type Inference Against Races

  35. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref<2> r) requires  { i = i + r.i; } } Constraints: 1  { this, g } 2  { this, g }  { this, g, r } 1  1[this := r, g:=2] Encoding: 1 = (b1 ? this : g ) 2 = (b2 ? this : g )  = { b3 ? this, b4 ? g, b5 ? r } Use boolean variables b1,...,b5 to encode choices for 1, 2,  SAS’04: Type Inference Against Races

  36. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref<2> r) requires  { i = i + r.i; } } Constraints: 1  { this, g } 2  { this, g }  { this, g, r } 1  1[this := r, g:=2] Encoding: 1 = (b1 ? this : g ) 2 = (b2 ? this : g )  = { b3 ? this, b4 ? g, b5 ? r } Use boolean variables b1,...,b5 to encode choices for 1, 2,  1[this := r, g:=2]   SAS’04: Type Inference Against Races

  37. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref<2> r) requires  { i = i + r.i; } } Constraints: 1  { this, g } 2  { this, g }  { this, g, r } 1  1[this := r, g:=2] Encoding: 1 = (b1 ? this : g ) 2 = (b2 ? this : g )  = { b3 ? this, b4 ? g, b5 ? r } Use boolean variables b1,...,b5 to encode choices for 1, 2,  1[this := r, g:=2]   (b1 ? this : g ) [this := r, g:=2]   SAS’04: Type Inference Against Races

  38. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref<2> r) requires  { i = i + r.i; } } Constraints: 1  { this, g } 2  { this, g }  { this, g, r } 1  1[this := r, g:=2] Encoding: 1 = (b1 ? this : g ) 2 = (b2 ? this : g )  = { b3 ? this, b4 ? g, b5 ? r } Use boolean variables b1,...,b5 to encode choices for 1, 2,  1[this := r, g:=2]   (b1 ? this : g ) [this := r, g:=2]   (b1 ? r : 2)   SAS’04: Type Inference Against Races

  39. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref<2> r) requires  { i = i + r.i; } } Constraints: 1  { this, g } 2  { this, g }  { this, g, r } 1  1[this := r, g:=2] Encoding: 1 = (b1 ? this : g ) 2 = (b2 ? this : g )  = { b3 ? this, b4 ? g, b5 ? r } Use boolean variables b1,...,b5 to encode choices for 1, 2,  1[this := r, g:=2]   (b1 ? this : g ) [this := r, g:=2]   (b1 ? r : 2)   (b1 ? r : (b2 ? this : g )) { b3 ? this, b4 ? g, b5 ? r } SAS’04: Type Inference Against Races

  40. Reducing Type Inference to SAT class Ref<ghost g> { int i guarded_by 1; void add(Ref<2> r) requires  { i = i + r.i; } } Constraints: 1  { this, g } 2  { this, g }  { this, g, r } 1  1[this := r, g:=2] Encoding: 1 = (b1 ? this : g ) 2 = (b2 ? this : g )  = { b3 ? this, b4 ? g, b5 ? r } Use boolean variables b1,...,b5 to encode choices for 1, 2,  Clauses: (b1  b5) (b1  b2  b3) (b1  b2  b4) 1[this := r, g:=2]   (b1 ? this : g ) [this := r, g:=2]   (b1 ? r : 2)   (b1 ? r : (b2 ? this : g )) { b3 ? this, b4 ? g, b5 ? r } SAS’04: Type Inference Against Races

  41. Overview of Type Inference Add Unknowns: class Ref<ghost g> { int i guarded_by 1 ; ... Constraints: 1  { this, g } ... SAT problem: (b1  b5) ... b1,... encodes choice for 1,... Unannotated Program: class Ref { int i; ... Chaff SAT solver Error: potential race on field i unsatisfiable satisfiable Annotated Program: class Ref<ghost g> { int i guarded_by g; ... Constraint Solution: 1 = g ... SAT soln: b1=false ... SAS’04: Type Inference Against Races

  42. Improving Precision • Synchronization not necessary if • only a single thread exists • object never escapes its creating thread • object has not yet escaped its creating thread • read-shared field • read-only after it escapes its creating thread • code is unreachable • Fields guarded_by expressions, not just vars • must be a constant expression • bound on size SAS’04: Type Inference Against Races

  43. Implementation • Full Java programming language • inheritance, subtyping, interfaces • inner classes, static fields and methods • Separate SAT problem for each field decl • to identify fields with potential race conditions • Generate MAX-SAT optimization problem • minimize number+complexity of error messages • Supports extra manual annotations • /*# no_warn */, /*# single_threaded */ • more ghost parameters, extra lock expressions, ... SAS’04: Type Inference Against Races

  44. Experimental Results SAS’04: Type Inference Against Races

  45. Summary • Type inference for rccjava is NP-complete • due to ghost parameters • requires backtracking search • Reduce type inference to SAT • adequately fast up to 30,000 LOC • precise: 92-100% of fields verified race free SAS’04: Type Inference Against Races

  46. Future Work • Atomicity • a key semantic correctness property for multithreaded code • a method is atomic if concurrent threads do not interfere with its behavior • sequential reasoning is OK for atomic methods • Developing type-based analysis for atomicity • leverages information about race conditions • early result: 85% of methods in jbb are atomic! SAS’04: Type Inference Against Races

  47. Type Inference Against Races Cormac Flanagan UC Santa Cruz Stephen N. Freund Williams College SAS’04: Type Inference Against Races

More Related