Atomizer A Dynamic Atomicity Checker For Multithreaded Programs

  • Slides: 44
Download presentation
Atomizer: A Dynamic Atomicity Checker For Multithreaded Programs Cormac Flanagan University of California, Santa

Atomizer: A Dynamic Atomicity Checker For Multithreaded Programs Cormac Flanagan University of California, Santa Cruz Stephen Freund Williams College

Race-Free Bank Account class Account { private int balance = 0; public read() {

Race-Free Bank Account class Account { private int balance = 0; public read() { int r; synchronized(this) { r = balance; } return r; } public void deposit(int n) { int r = read(); other threads can update balance synchronized(this) { balance = r + n; } } } Race-freedom is not sufficient 2

Fixed Bank Account class Account { private int balance = 0; public read() {

Fixed Bank Account class Account { private int balance = 0; public read() { int r; synchronized(this) { r = balance; } return r; } public void deposit(int n) { synchronized(this) { int r = balance; balance = r + n; } } } 3

Optimized Bank Account class Account { private int balance = 0; public read() {

Optimized Bank Account class Account { private int balance = 0; public read() { return balance; } public void deposit(int n) { 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

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

Sequential Program Execution deposit() precond. void deposit() {. . postcond. } 6

Multithreaded Program Execution void deposit() {. . } 7

Multithreaded Program Execution void deposit() {. . } 7

Multithreaded Program Execution void deposit() {. . } 8

Multithreaded Program Execution void deposit() {. . } 8

Multithreaded Program Execution Atomicity – maximal non-interference property – enables sequential reasoning – matches

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

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) public void x r=bal y bal=r+n z deposit(int n) { synchronized(this) { acq(this) x y r=bal bal=r+n z r = bal; int bal = r + n; } deposit is atomic if for every non-serial } rel(this) 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

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

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

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] S 0 acq(this) S 1 X S 2 j=bal S 3

Reduction [Lipton 75] S 0 acq(this) S 1 X S 2 j=bal S 3 Y S 4 bal=j+n S 5 Z S 6 rel(this) 14 S 7

Reduction [Lipton 75] S 0 acq(this) X X Y S 1 T 1 j=bal

Reduction [Lipton 75] S 0 acq(this) X X Y S 1 T 1 j=bal S 2 S 3 acq(this) T 2 T 3 Y j=bal S 4 bal=j+n S 5 Z rel(this) S 6 rel(this) T 6 Z S 7 15

Commuting Actions 0 b 1 c 3 16

Commuting Actions 0 b 1 c 3 16

Right Mover 0 0 b 1 c 2 c b 3 3 b is

Right Mover 0 0 b 1 c 2 c b 3 3 b is right mover 17

Right Mover 0 0 ACQ(l, t) c 1 2 c ACQ(l, t) 3 3

Right Mover 0 0 ACQ(l, t) c 1 2 c ACQ(l, t) 3 3 18

Left Mover 0 0 b 1 c 2 c b 3 3 c is

Left Mover 0 0 b 1 c 2 c b 3 3 c is left mover 19

Left Mover 0 0 b REL(l, t) 1 2 REL(l, t) b 3 3

Left Mover 0 0 b REL(l, t) 1 2 REL(l, t) b 3 3 20

Both Mover 0 0 b MEM(m, a, t) 1 2 MEM(m, a, t) b

Both Mover 0 0 b MEM(m, a, t) 1 2 MEM(m, a, t) b 3 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 0 b 1 MEM(m, a, t) 3 X 0 MEM(m, a, t)

Non Mover 0 b 1 MEM(m, a, t) 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 L: left-mover N: non-mover – lock acquire

Performing Reduction Dynamically R: right-mover B: both-mover L: left-mover N: non-mover – lock acquire – race-free field access – lock release acq(lock) R – access to "racy" fields j=bal bal=j+n rel(lock) B B L Reducible methods: (R|B)* [N] (L|B)* R|B start atomic block In. Right L|N L|B In. Left R|N Error 23

Reduction [Lipton 75] S 0 acq(this) S 1 X S 2 j=bal S 3

Reduction [Lipton 75] S 0 acq(this) S 1 X S 2 j=bal S 3 Y S 4 bal=j+n S 5 Z S 6 rel(this) green thread holds lock red thread does not hold lock operation y does not access balance (assuming balance protected by lock) operations commute 24 S 7

Reduction [Lipton 75] S 0 acq(this) X S 1 S 2 j=bal Y S

Reduction [Lipton 75] S 0 acq(this) X S 1 S 2 j=bal Y S 3 T 3 Y j=bal S 4 bal=j+n S 5 Z Z S 6 rel(this) S 7 green thread holds lock after acquire operation x does not modify lock operations commute 25

Reduction [Lipton 75] S 0 S 0 acq(this) X X acq(this) S 1 T

Reduction [Lipton 75] S 0 S 0 acq(this) X X acq(this) S 1 T 1 S 2 S 2 j=bal Y Y S 3 T 3 Y j=bal S 4 S 4 bal=j+n S 5 S 5 Z Z Z S 6 S 6 rel(this) 26 S 7 S 7

Reduction [Lipton 75] S 0 S 0 acq(this) X X acq(this) S 1 X

Reduction [Lipton 75] S 0 S 0 acq(this) X X acq(this) S 1 X T 1 Y S 2 S 2 j=bal Y Y acq(this) T 2 S 3 T 3 T 3 Y j=bal S 4 S 4 bal=j+n S 5 S 5 Z Z S 6 S 6 rel(this) 27 S 7 S 7

Reduction [Lipton 75] S 0 S 0 S 0 acq(this) X X acq(this) S

Reduction [Lipton 75] S 0 S 0 S 0 acq(this) X X acq(this) S 1 X X T 1 T 1 Y Y S 2 S 2 j=bal Y Y acq(this) T 2 S 3 T 3 T 3 Y j=bal S 4 S 4 S 4 bal=j+n bal=j+n S 5 S 5 S 5 Z Z rel(this) S 6 S 6 T 6 rel(this) Z S 7 S 7 S 7 28

Atomizer Goal class Account { private int balance = 0; atomic public read() {

Atomizer Goal class Account { private int balance = 0; atomic public read() { int r; synchronized(this) { r = balance; } return r; } atomic void deposit(int n) { synchronized(this) { int r = balance; balance = r + n; } } } Add two more event types: BEGIN and END 29

Atomizer Algorithm ACQ(l, t) REL(l, t) Wrong t. State = In. Left MEM(m, a,

Atomizer Algorithm ACQ(l, t) REL(l, t) Wrong t. State = In. Left MEM(m, a, t) and m is unprotected END MEM(m, a, t) and m is unprotected REL(l, t) t. State = In. Right BEGIN t. State = Outside. Atomic ACQ(l, t) 30

Atomizer Review Instrumented code calls Atomizer runtime – on field accesses, sync ops, etc

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, . . . –

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. 5 x - 40 x 32

Benchmark elevator Base Time (s) Lines Atomizer Slowdown 500 11. 2 - 29, 900

Benchmark elevator Base Time (s) Lines Atomizer Slowdown 500 11. 2 - 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 spec. JBB 30, 500 26. 2 12. 1 webl 22, 300 60. 3 - lib-java 75, 305 96. 5 - hedc 33

Extensions Redundant lock operations are both-movers – re-entrant acquire/release – operations on thread-local locks

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

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

Extensions Reduce Number of Warnings Total 341 Total 97 36

Extensions Reduce Number of Warnings Total 341 Total 97 36

Evaluation Warnings: 97 (down from 341) Real errors (conservative): 7 False alarms due to:

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. String. Buffer /**. . . used by the compiler to implement the

java. lang. String. Buffer /**. . . 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 String. Buffer {. . . } 38

java. lang. String. Buffer public class String. Buffer { private int count; public synchronized

java. lang. String. Buffer public class String. Buffer { private int count; public synchronized int length() { return count; } public synchronized void get. Chars(. . . ) {. . . } /*# atomic */ public synchronized void append(String. Buffer sb){ } } sb. length() acquires lock on sb, int len = sb. length(); gets length, and releases lock. . . other threads can change sb. . . sb. get. Chars(. . . , len, . . . ); . . . use of stale len may yield String. Index. Out. Of. Bounds. Exception inside get. Chars(. . . ) 39

java. lang. String. Buffer public class String. Buffer { private int count; public synchronized

java. lang. String. Buffer public class String. Buffer { private int count; public synchronized int length() { return count; } public synchronized void get. Chars(. . . ) {. . . } /*# atomic */ public synchronized void append(String. Buffer sb){ int len = sb. length(); . . sb. get. Chars(. . . , len, . . . ); . . . } } String. Buffer. append is not atomic: Start: at String. Buffer. append(String. Buff at Thread 1. run(Example. java: 17) Commit: Lock Release at String. Buffer. length(String. Buff at String. Buffer. append(String. Buff at Thread 1. run(Example. java: 17) Error: Lock Acquire at String. Buffer. get. Chars(String. Bu at String. Buffer. append(String. Buff at Thread 1. run(Example. java: 17) 40

Related Work Reduction – [Lipton 75, Lamport-Schneider 89, . . . ] – type

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() 42

Multithreaded Program Execution run() atomic a() b() d() 43

Multithreaded Program Execution run() atomic a() b() d() 43

Conclusions And Future Directions Atomicity – maximal non-interference property – enables sequential reasoning –

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