Atomizer: AD ynamic Atomicity Checker For Multithreaded Programs by DI0rR5B

VIEWS: 6 PAGES: 44

									Atomizer:
A Dynamic Atomicity Checker
For Multithreaded Programs


Cormac Flanagan             Stephen Freund
University of California,   Williams College
Santa Cruz
Race-Free Bank Account

class Account {
  private int balance = 0;

    public read() {          public void deposit(int n) {
      int r;                   int r = read();
      synchronized(this) {     other threads can update balance
        r = balance;           synchronized(this) {
      }                          balance = r + n;
      return r;                }
    }                        }

}

 Race-freedom is not sufficient

                                                          2
Fixed Bank Account

class Account {
  private int balance = 0;

    public read() {          public void deposit(int n) {
      int r;                   synchronized(this) {
      synchronized(this) {       int r = balance;
        r = balance;             balance = r + n;
      }                        }
      return r;              }
    }

}




                                                     3
Optimized Bank Account

class Account {
  private int balance = 0;

    public read() {          public void deposit(int n) {
      return balance;          synchronized(this) {
    }                            int r = balance;
                                 balance = r + n;
                               }
                             }


}

 Race-freedom is not necessary

                                                     4
Race-Freedom

 Race-freedom is neither necessary nor
  sufficient to ensure the absence of errors
  due to unexpected interactions between
  threads

 Is there a more fundamental semantic
  correctness property?




                                               5
Sequential Program Execution


  deposit()   precond.
                          void deposit() {

                              ..


                              ..


              postcond.   }




                                             6
Multithreaded Program Execution



                        void deposit() {

                            ..


                            ..


                        }




                                           7
Multithreaded Program Execution



                        void deposit() {

                            ..


                            ..


                        }




                                           8
Multithreaded Program Execution

                   Atomicity

                    – maximal non-interference
                      property

                    – enables sequential reasoning

                    – matches existing methodology




                                               9
Definition of Atomicity
 Serial execution of deposit
        x             y           acq(this)       r=bal       bal=r+n       rel(this)          z
                                                                                                 
 Non-serial executions of deposit
      acq(this)           x       r=bal             y         bal=r+n          z            rel(this)
         
  public void          
                    deposit(int n) {                                                                
      synchronized(this) {
      acq(this)   x        y       r=bal                      bal=r+n         z             rel(this)
               r
         int  = bal;                                                                              
         bal = r + n;
      }
 deposit is atomic if for every non-serial
   }
  execution, there is a serial execution with the
  same overall behavior (same final state)
                                                                                               10
Atomizer: Dynamic Analysis

 Lockset algorithm
  – from Eraser [Savage et al. 97]
  – identifies race conditions


 Reduction [Lipton 75]
  – proof technique for verifying atomicity,
    using information about race conditions




                                               11
Atomizer: Dynamic Analysis

 Lockset algorithm
  – from Eraser [Savage et al. 97]
  – identifies race conditions


 Reduction [Lipton 75]
  – proof technique for verifying atomicity,
    using information about race conditions




                                               12
Atomizer: Dynamic Analysis

 Lockset algorithm
  – from Eraser [Savage et al. 97]
  – identifies race conditions


 Reduction [Lipton 75]
  – proof technique for verifying atomicity,
    using information about race conditions




                                               13
     Reduction [Lipton 75]
     acq(this)    X        j=bal        Y        bal=j+n        Z        rel(this)
S0           S1       S2           S3       S4             S5       S6               S7




                                                                               14
     Reduction [Lipton 75]
     acq(this)    X         j=bal            Y           bal=j+n           Z             rel(this)
S0           S1       S2            S3              S4             S5               S6                S7




        X         Y        acq(this)        j=bal        bal=j+n        rel(this)            Z
S0           T1       T2               T3           S4             S5               T6                S7




                                                                                                 15
Commuting Actions

           b         c
      0        1       3




                              16
Right Mover

              b                    c
      0               1                3




      0          c
                        2         b
                                         3



                      b is right mover




                                              17
Right Mover

           ACQ(l,t)           c
      0              1              3




      0       c
                      2   ACQ(l,t)
                                      3




                                           18
Left Mover

             b                   c
      0             1                3




      0         c
                      2         b
                                       3



                     c is left mover




                                            19
Left Mover

             b             REL(l,t)
      0              1              3




      0   REL(l,t)
                      2       b
                                      3




                                           20
Both Mover

                      b                 MEM(m,a,t)
            0                     1                3




             0   MEM(m,a,t)
                                   2       b
                                                     3


  m is always protected by the
 lockset L and at least one lock
   in L is held by t during the
              access


                                                          21
Non Mover

                     b                 MEM(m,a,t)
           0                     1                3



                                  X
            0   MEM(m,a,t)
                                  2       b
                                                    3


  m is always protected by the
lockset L and none of the locks
   in L is held by t during the
              access


                                                         22
Performing Reduction Dynamically

 R: right-mover                 B: both-mover
    – lock acquire                   – race-free field access
 L: left-mover                  N: non-mover
    – lock release                   – access to "racy" fields
           acq(lock)   j=bal   bal=j+n    rel(lock)

             R          B        B             L
 Reducible methods: (R|B)* [N] (L|B)*
         R|B                             L|B
 start                   L|N                       R|N
atomic       InRight             InLeft                  Error
 block
                                                                 23
     Reduction [Lipton 75]
     acq(this)    X        j=bal        Y        bal=j+n        Z        rel(this)
S0           S1       S2           S3       S4             S5       S6               S7




     green thread holds lock
      red thread does not hold lock
      operation y does not access balance
       (assuming balance protected by lock)
      operations commute
                                                                              24
     Reduction [Lipton 75]
     acq(this)    X        j=bal          Y           bal=j+n        Z        rel(this)
S0           S1       S2            S3           S4             S5       S6               S7


     acq(this)    X         Y            j=bal        bal=j+n        Z        rel(this)
S0           S1       S2            T3           S4             S5       S6               S7




                                   green thread holds lock after acquire
                                    operation x does not modify lock
                                    operations commute
                                                                                   25
     Reduction [Lipton 75]
     acq(this)       X             j=bal         Y           bal=j+n        Z        rel(this)
S0           S1               S2           S3           S4             S5       S6               S7


     acq(this)       X              Y           j=bal        bal=j+n        Z        rel(this)
S0           S1               S2           T3           S4             S5       S6               S7


        X         acq(this)         Y           j=bal        bal=j+n        Z        rel(this)
S0           T1               S2           T3           S4             S5       S6               S7




                                                                                          26
     Reduction [Lipton 75]
     acq(this)       X             j=bal         Y           bal=j+n        Z        rel(this)
S0           S1               S2           S3           S4             S5       S6               S7


     acq(this)       X              Y           j=bal        bal=j+n        Z        rel(this)
S0           S1               S2           T3           S4             S5       S6               S7


        X         acq(this)         Y           j=bal        bal=j+n        Z        rel(this)
S0           T1               S2           T3           S4             S5       S6               S7


        X            Y         acq(this)        j=bal        bal=j+n        Z        rel(this)
S0           T1               T2           T3           S4             S5       S6               S7




                                                                                          27
     Reduction [Lipton 75]
     acq(this)       X             j=bal         Y           bal=j+n           Z             rel(this)
S0           S1               S2           S3           S4             S5               S6               S7


     acq(this)       X              Y           j=bal        bal=j+n           Z             rel(this)
S0           S1               S2           T3           S4             S5               S6               S7


        X         acq(this)         Y           j=bal        bal=j+n           Z             rel(this)
S0           T1               S2           T3           S4             S5               S6               S7


        X            Y         acq(this)        j=bal        bal=j+n           Z             rel(this)
S0           T1               T2           T3           S4             S5               S6               S7


        X            Y         acq(this)        j=bal        bal=j+n        rel(this)           Z
S0           T1               T2           T3           S4             S5               T6               S7
                                                                                                    28
Atomizer Goal

class Account {
  private int balance = 0;

    atomic public read() {   atomic void deposit(int n) {
      int r;                   synchronized(this) {
      synchronized(this) {       int r = balance;
        r = balance;             balance = r + n;
      }                        }
      return r;              }
    }

}

        Add two more event types: BEGIN and END


                                                    29
                     Atomizer Algorithm
                                              ACQ(l,t)
     REL(l,t)

                                                                Wrong
                      t.State = InLeft



                                                         MEM(m,a,t)
            MEM(m,a,t)                                   and m is
            and m is                          END        unprotected
            unprotected


REL(l,t)

                          t.State = InRight                t.State =
                                               BEGIN     OutsideAtomic


       ACQ(l,t)

                                                                         30
Atomizer Review

 Instrumented code calls Atomizer runtime
  – on field accesses, sync ops, etc
 Lockset algorithm identifies races
  – used to classify ops as movers or non-movers
 Atomizer checks reducibility of atomic blocks
  – warns about atomicity violations




                                                   31
Evaluation

 12 benchmarks
  – scientific computing, web server, std libraries, ...
  – 200,000+ lines of code

 Heuristics for atomicity
  – all synchronized blocks are atomic
  – all public methods are atomic, except main and run


 Slowdown:       1.5x - 40x

                                                     32
                             Base       Atomizer
 Benchmark   Lines
                           Time (s)     Slowdown
elevator             500         11.2                -
hedc            29,900            6.4                -
tsp                  700          1.9          21.8
sor             17,700            1.3              1.5
moldyn           1,300           90.6              1.5
montecarlo       3,600            6.4              2.7
raytracer        1,900            4.8          41.8
mtrt            11,300            2.8          38.8
jigsaw          90,100            3.0              4.7
specJBB         30,500           26.2          12.1
webl            22,300           60.3                -
lib-java        75,305           96.5                -



                                                         33
Extensions

 Redundant lock operations are both-movers
  – re-entrant acquire/release
  – operations on thread-local locks
  – operations on lock A, if lock B always acquired
    before A


 Write-protected data




                                                      34
Write-Protected Data
class Account {
    int bal;
    /*# atomic */ int read() { return bal; }
    /*# atomic */ void deposit(int n) {
 R    synchronized (this) {
 B      int j = bal;
N       bal = j + n;
 L    }
    }
}




                                               35
Extensions Reduce Number of Warnings
80


70
                                                                       lib-java
60                                                                     webl
                                                                       jbb
50                                                                     jigsaw
                                                                       elevator
                                                                       hedc
40
                                                                       tsp
                                                                       sor
30
                                                                       moldyn
                                                                       montecarlo
20                                                                     raytracer
                                                                       mtrt
10


 0
 Basic   reentrant   thread-local   thread-    protected     write-
           locks         locks      local(2)     locks     protected
                                      locks                  data

Total                                                      Total
 341                                                        97
                                                                           36
Evaluation
 Warnings: 97 (down from 341)
 Real errors (conservative): 7
 False alarms due to:
  – simplistic heuristics for atomicity
    • programmer should specify atomicity
  – false races
  – methods irreducible yet still "atomic"
    • eg caching, lazy initialization


 No warnings reported in more than 90% of
  exercised methods
                                             37
java.lang.StringBuffer

/**
  ... used by the compiler to implement the binary
  string concatenation operator ...

  String buffers are safe for use by multiple
   threads. The methods are synchronized so that
   all the operations on any particular instance
   behave as if they occur in some serial order
   that is consistent with the order of the method
   calls made by each of the individual threads
   involved.
*/
/*# atomic */ public class StringBuffer { ... }

                                                     38
    java.lang.StringBuffer
public class StringBuffer {
  private int count;
  public synchronized int length() { return count; }
  public synchronized void getChars(...) { ... }
  /*# atomic */
  public synchronized void append(StringBuffer sb){
                                   sb.length() acquires lock on sb,
        int len = sb.length();
                                   gets length, and releases lock
        ...
        ...
                                 other threads can change sb
        ...
        sb.getChars(...,len,...);
        ...                     use of stale len may yield
    }                               StringIndexOutOfBoundsException
}                                   inside getChars(...)
                                                                 39
    java.lang.StringBuffer
public class StringBuffer {
  private int count;
  public synchronized int length() { return count; }
  public synchronized void getChars(...) { ... }
  /*# atomic */
  public synchronized void append(StringBuffer sb){
                                    StringBuffer.append is not atomic:
                                      Start:
        int len = sb.length();          at StringBuffer.append(StringBuffe
        ...                             at Thread1.run(Example.java:17)
        ...
                                      Commit: Lock Release
        ...                             at StringBuffer.length(StringBuffe
        sb.getChars(...,len,...);       at StringBuffer.append(StringBuffe
                                        at Thread1.run(Example.java:17)
        ...
    }                                 Error: Lock Acquire
                                        at StringBuffer.getChars(StringBuf
}                                       at StringBuffer.append(StringBuffe
                                        at Thread1.run(Example.java:17)
                                                                  40
  Related Work
 Reduction
    – [Lipton 75, Lamport-Schneider 89, ...]
    – type systems [Flanagan-Qadeer 03],
      model checking [Stoller-Cohen 03, Flanagan-Qadeer 03],
      procedure summaries [Qadeer et al 04]
 Other atomicity checkers
    –   [Wang-Stoller 03], Bogor model checker [Hatcliff et al 03]
 Race detection / prevention
    – dynamic [Savage et al 97, O'Callahan-Choi 01, von Praun-Gross 01]
    – Warlock [Sterling 93], SPMD [Aiken-Gay 98]
    – type systems [Abadi-Flanagan 99, Flanagan-Freund 00, Boyapati-Rinard 01]
    – Guava [Bacon et al 01]
 View consistency [Artho-Biere-Havelund 03, von Praun-Gross 03]



                                                                                 41
Multithreaded Program Execution


           run()
                     atomic

   a()             b()


         d()




                                  42
Multithreaded Program Execution


           run()
                     atomic

   a()             b()


         d()




                                  43
Conclusions And Future Directions
 Atomicity
  – maximal non-interference property
  – enables sequential reasoning
  – matches practice
 Atomizer extends race detection techniques
  – catches "higher-level" concurrency errors
  – some benign races do not break atomicity

 Atomicity for distributed systems?


                                                44

								
To top