DREADLOCKS : Efficient Deadlock Detection Maurice Herlihy Joint work with Eric Koskinen
Spin-Locks • Good for short pauses • Multiprocessors • Can be made cache-friendly TRANSACT 08 2
Deadlock TRANSACT 08 3
Waits-For Graph waiting owned TRANSACT 08 4
Deadlock waiting owned TRANSACT 08 5
Dealing with Deadlock • Avoidance – Not practical if demands not known in advance • Detection – Existing algs require complex probing and poking TRANSACT 08 6
Can Use Timeouts • Abort if you don’t get lock in time • Plus – Easy to implement • Minus – How do you choose timeout? – Is choice robust? • Different platforms/apps? TRANSACT 08 7
Dreadlocks • Fast, incremental deadlock detection • Low overhead • Cache-friendly • Algorithm … TRANSACT 08 8
Digest TRANSACT 08 9
Digest TRANSACT 08 10
Digest Uh-oh! TRANSACT 08 11
Algorithm • Each thread publishes digest – Initially contains only itself – Always contains itself • Spins on lock owner’s digest – Propagates changes (union with own) – Aborts if finds itself in owner’s digest TRANSACT 08 12
T&T&Set Spin Lock publ i c voi d publ i c voi d l ock( ) { l ock( ) { whi l e whi l e ( t r ue t r ue) { ) { whi l e whi l e ( ( owner = st at e. get ( ) ) ! = ( ( owner = st at e. get ( ) ) ! = nul l nul l ) { ) { i f i f ( owner . cont ai ns( m ( owner . cont ai ns( m e) ) { e) ) { t hr ow new t hr ow new Abor t edExcept i on( ) ; Abor t edExcept i on( ) ; } } el se i f el se i f ( owner . changed( ) ) { ( owner . changed( ) ) { m m yDi gest . set Uni on( owner , m yDi gest . set Uni on( owner , m e) ; e) ; } } i f i f ( st at e. com ( st at e. com par eAndSet ( nul l , m par eAndSet ( nul l , m yDi gest ) ) { yDi gest ) ) { m m yDi gest . set Si ngl e( m yDi gest . set Si ngl e( m e) ; e) ; r et ur n r et ur n; } } } (1) TRANSACT 08 13
T&T&Set Spin Lock publ i c voi d l ock( ) { publ i c voi d l ock( ) { whi l e ( t r ue) { whi l e ( t r ue) { whi l e whi l e ( ( owner = st at e. get ( ) ) ! = ( ( owner = st at e. get ( ) ) ! = nul l nul l ) { ) { i f ( owner . cont ai ns( m i f ( owner . cont ai ns( m e) ) { e) ) { t hr ow new Abor t edExcept i on( ) ; t hr ow new Abor t edExcept i on( ) ; } el se i f ( owner . changed( ) ) { } el se i f ( owner . changed( ) ) { m m yDi gest . set Uni on( owner , m yDi gest . set Uni on( owner , m e) ; e) ; } } i f ( st at e. com i f ( st at e. com par eAndSet ( nul l , m par eAndSet ( nul l , m yDi gest ) ) { yDi gest ) ) { m m yDi gest . set Si ngl e( m yDi gest . set Si ngl e( m e) ; e) ; r et ur n; r et ur n; } Busy lock points to owner digest } } (1) TRANSACT 08 14
T&T&Set Spin Lock publ i c voi d l ock( ) { publ i c voi d l ock( ) { whi l e ( t r ue) { whi l e ( t r ue) { whi l e ( ( owner = st at e. get ( ) ) ! = nul l ) { whi l e ( ( owner = st at e. get ( ) ) ! = nul l ) { i f i f ( owner . cont ai ns( m ( owner . cont ai ns( m e) ) { e) ) { t hr ow new Abor t edExcept i on( ) ; t hr ow new Abor t edExcept i on( ) ; } el se i f ( owner . changed( ) ) { } el se i f ( owner . changed( ) ) { m m yDi gest . set Uni on( owner , m yDi gest . set Uni on( owner , m e) ; e) ; } } i f ( st at e. com i f ( st at e. com par eAndSet ( nul l , m par eAndSet ( nul l , m yDi gest ) ) { yDi gest ) ) { m m yDi gest . set Si ngl e( m yDi gest . set Si ngl e( m e) ; e) ; r et ur n; r et ur n; Abort if I’m in owner’s } digest } } (1) TRANSACT 08 15
T&T&Set Spin Lock publ i c voi d l ock( ) { publ i c voi d l ock( ) { whi l e ( t r ue) { whi l e ( t r ue) { whi l e ( ( owner = st at e. get ( ) ) ! = nul l ) { whi l e ( ( owner = st at e. get ( ) ) ! = nul l ) { i f ( owner . cont ai ns( m i f ( owner . cont ai ns( m e) ) { e) ) { t hr ow new Abor t edExcept i on( ) ; t hr ow new Abor t edExcept i on( ) ; } } el se i f el se i f ( owner . changed( ) ) { ( owner . changed( ) ) { m m yDi gest . set Uni on( owner , m yDi gest . set Uni on( owner , m e) ; e) ; } } i f ( st at e. com i f ( st at e. com par eAndSet ( nul l , m par eAndSet ( nul l , m yDi gest ) ) { yDi gest ) ) { m m yDi gest . set Si ngl e( m yDi gest . set Si ngl e( m e) ; e) ; r et ur n; r et ur n; Back-propagate changes from } owner’s digest } } (1) TRANSACT 08 16
T&T&Set Spin Lock Clear own digest publ i c voi d l ock( ) { publ i c voi d l ock( ) { whi l e ( t r ue) { whi l e ( t r ue) { when lock acquired whi l e ( ( owner = st at e. get ( ) ) ! = nul l ) { whi l e ( ( owner = st at e. get ( ) ) ! = nul l ) { i f ( owner . cont ai ns( m i f ( owner . cont ai ns( m e) ) { e) ) { t hr ow new Abor t edExcept i on( ) ; t hr ow new Abor t edExcept i on( ) ; } el se i f ( owner . changed( ) ) { } el se i f ( owner . changed( ) ) { m m yDi gest . set Uni on( owner , m yDi gest . set Uni on( owner , m e) ; e) ; } } i f i f ( st at e. com ( st at e. com par eAndSet ( nul l , m par eAndSet ( nul l , m yDi gest ) ) { yDi gest ) ) { m m yDi gest . set Si ngl e( m yDi gest . set Si ngl e( m e) ; e) ; r et ur n r et ur n; } } } (1) TRANSACT 08 17
Concurrency • Digest methods don’t have to be atomic – False positives OK if rare – False negatives OK if transient • Means we can use multi-word bitmaps TRANSACT 08 18
Bit Maps • 32 (or 64) bit array • Good for small sets • Exact membership tests • Manipulated by shifting & masking TRANSACT 08 19
Bloom Filter h 1 h 2 TRANSACT 08 20
Testing Membership Yes, maybe… member h 1 h 2 TRANSACT 08 21
No False Negatives No member h 1 h 2 TRANSACT 08 22
False Positivies Yes, maybe member h 1 h 2 TRANSACT 08 23
Experiments • Dreadlock TTAS lock • Used for Abstract Locking in Boosting • Implemented TTAS lock in C • Built upon Boosting / TL2 • Synthetic benchmark: boosted array TRANSACT 08 24
TRANSACT 08 25
TRANSACT 08 26
Throughput Small # Threads TRANSACT 08 27
Throughput Large # Threads TRANSACT 08 28
No Deadlock No Cry • Can use locks with reckless abandon • Dreadlocks will detect deadlocks • So far – Slightly higher overhead TRANSACT 08 29
Recommend
More recommend