1 / 20

Practical Lock/Unlock Pairing for Concurrent Programs

Practical Lock/Unlock Pairing for Concurrent Programs. Hyoun Kyu Cho 1 , Yin Wang 2 , Hongwei Liao 1 , Terence Kelly 2 , St é phane Lafortune 1 , Scott Mahlke 1. 1 University of Michigan 2 Hewlett-Packard Labs. Parallel Programming.

rusti
Download Presentation

Practical Lock/Unlock Pairing for Concurrent Programs

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. Practical Lock/Unlock Pairing for Concurrent Programs HyounKyu Cho1, Yin Wang2, Hongwei Liao1, Terence Kelly2, Stéphane Lafortune1, Scott Mahlke1 1University of Michigan 2Hewlett-Packard Labs 1

  2. Parallel Programming • Industry wide move to multicores forces parallel programming • Inherently difficult • Concurrency bugs • Non-determinism Intel 4 Core Nehalem AMD 4 Core Shanghai Sun Niagara 2 IBM Cell 2

  3. Tools for Parallel Programs • Concurrency bug detection tools • To statically infer concurrency • ex) RacerX[Engler`03] • Automated bug fix tools • To avoid deadlocks • ex) AFix[Jin`11], Gadara[Wang`08] • Optimizing compilers • Accurate synchronization information can enable more aggressive optimizations 3

  4. Examples 1 : intwork_on_tree(…) 2 : { 3 : Node *ptr1, *ptr2; 4 : … 5 : lock( ptr->mutex ); 6 : while( ptr != NULL ) { 7 : … 8 : ptr2 = iterate_next( ptr1 ); 9 : ptr1 = ptr1; 10: } 11: unlock( ptr->mutex ); 12: } 13: Node* iterate_next(Node *current) 14: { 15: Node *next = find(current); 16: … 17: lock(next->mutex); 18: unlock(current->mutex); 19: … 20: return next; 21: } public class Counter { … public void increment() { synchronized (this) { ++count; } } … } 4

  5. Unpaired Locks and Unlocks • Challenges • Infeasible paths 5

  6. Unpaired Locks Due To Infeasible Paths • Example if (x) void foo(x, A) { if (x) lock(A); … if (x) unlock(A); } true lock(A); false … if(x) true unlock(A); false Feasible Infeasible 6

  7. Unpaired Locks and Unlocks • Challenges • Infeasible paths • Spanning function boundaries • Pointers • Impacts • False positives • Need programmers’ annotation • Conservative, less efficient 7

  8. Practical Lock/Unlock Pairing • For a lock, give a set of pairing unlocks and check if the mutex would be released by them for all feasible paths • Path-sensitive analysis using a SAT solver • Use heuristics based on likely assumptions • Instrument code for dynamic checking 8

  9. Static Analysis Mapping Lock to Set of Corresponding Unlocks Path Condition Calculation Checking Lock/Unlock Pairing 9

  10. Lock/Unlock Pairing Example 01: intfoo(struct Task *job) { 02: … 03: if(job->hasMutex) 04: lock(job->mutex); //(1) 05: if(job->isSpecial) { 06: // Do some special work 07: if(job->hasMutex) 08: unlock(job->mutex); //(2) 09: return result; 10: } 11: // Do normal work 12: if(job->hasMutex) 13: unlock(job->mutex); //(3) 14: return result; 15: } 1. Map set of corresponding unlocks (1) → { (2), (3) } 10

  11. Lock/Unlock Pairing Example 01: intfoo(struct Task *job) { 02: … 03: if(job->hasMutex) 04: lock(job->mutex); //(1) 05: if(job->isSpecial) { 06: // Do some special work 07: if(job->hasMutex) 08: unlock(job->mutex); //(2) 09: return result; 10: } 11: // Do normal work 12: if(job->hasMutex) 13: unlock(job->mutex); //(3) 14: return result; 15: } 2. Calculate Boolean expressions (1): (2): (3): (1): (2): (3): 11

  12. Path Condition Calculation • Recursively calculate path conditions that decide execution of each lock and unlock • Join Point • Disjunction (OR) • Consecutive conditions in a path • Conjunction (AND) src x=true x=false child1 child2 dest • Assign same Boolean variable to Branch conditions that should have same value 12

  13. Lock/Unlock Pairing Example Examine pairing (1) is paired up with { (2), (3) }. If (1) is executed, (2) or (3) is executed. 01: intfoo(struct Task *job) { 02: … 03: if(job->hasMutex) 04: lock(job->mutex); //(1) 05: if(job->isSpecial) { 06: // Do some special work 07: if(job->hasMutex) 08: unlock(job->mutex); //(2) 09: return result; 10: } 11: // Do normal work 12: if(job->hasMutex) 13: unlock(job->mutex); //(3) 14: return result; 15: } 13

  14. CFG Pruning 1 1 2 3 3,5,6 5 6 4 7 7 8 9 9 10 2,4,8,10,11 11 14

  15. Inter-procedural Analysis • Observations • Corresponding unlocks share lowest common ancestor (LCA) in the callgraph • Depths from locks and unlocks to LCA relatively small • Proximity-based Callgraph Partitioning • Extend pairing analysis with context 15

  16. Dynamic Checking • Checking Lock-to-Unlocks Mapping • Keeps a map structure from mutex to acquired LOCK_ID • When released, check if UNLOCK_ID is in corresponding unlock set of LOCK_ID • Checking Semiflow Property • Keeps a map structure from function to mutex • When function returns, check if holding a mutex that should not be held 16

  17. Experimental Setup • Implemented pairing in LLVM compiler infrastructure • Benchmarks • Apache 2.2.11 web server • MySQL 5.0.91 database server • OpenLDAP 2.4.19 lightweight directory access protocol server • pbzip2 1.1.4 • pfscan 1.0 • aget 0.4 • On an Intel Core 2 Quad Q8300 @2.50GHz w/ 8GB MEM 17

  18. Effectiveness of Static Analysis 18

  19. Runtime Overhead 19

  20. Conclusion • Practical Lock/Unlock Pairing • Combines static analysis and dynamic checking • Infeasible path analysis using path conditions • Makes likely assumptions and check at runtime • Overall, pairs up 98.2% of all locks including 7.1% of them paired speculatively • Negligible runtime overhead of 3.4% at most 20

More Related