Automatic Atomicity Verification for Clients of Concurrent Data Structures

Automatic Atomicity Verification for Clients of Concurrent Data Structures

Automatic Atomicity Verification for Clients of Concurrent Data Structures Mohsen Lesani, Todd Millstein, and Jens Palsberg University of California, Los Angeles flesani, todd, [email protected] Abstract. Mainstream programming languages offer libraries of concur- rent data structures. Each method call on a concurrent data structure appears to take effect atomically. However, clients of such data struc- tures often require stronger guarantees. For instance, a histogram class that is implemented using a concurrent map may require a method to atomically increment a histogram bar, but its implementation requires multiple calls to the map and hence is not atomic by default. Indeed, prior work has shown that atomicity errors in clients of concurrent data structures occur frequently in production code. We present an automatic and modular verification technique for clients of concurrent data structures. We define a novel sufficient condition for atomicity of clients called condensability. We present a tool called Snowflake that generates proof obligations for condensability of Java client methods and discharges them using an off-the-shelf SMT solver. We applied Snowflake to an existing suite of client methods from sev- eral open-source applications. It successfully verified 76.9% of the atomic methods without any change and verified the rest of them with small code refactoring and/or annotations. 1 Introduction Many modern programming languages provide libraries of concurrent data struc- tures (e.g., the java.util.concurrent package and Intel Threading Building Blocks library) that are widely used. A concurrent data structure is an object that satisfies the well-known correctness criterion called linearizability [19]. At a high level, this property ensures that the operations of the data structure can be invoked concurrently from multiple threads while still appearing to ex- ecute atomically and behaving according to the sequential specification of the data structure. The linearizability guarantee relieves the programmer from com- plex reasoning about possible interference among data-structure methods and removes the need to add explicit synchronization. While the linearizability guarantee is very useful, it only pertains to an indi- vidual operation on the data structure. In practice, clients of a concurrent data structure may require stronger guarantees. For example, consider the AtomicMap class in Figure 1, which is a subset of Java's ConcurrentHashMap class and pro- vides atomic methods for getting, putting and removing elements, as well as 1 class AtomicMap<K, V> {// data structure 2 V get (K k) {/*..*/} 3 void put(K k, V v) {/*..*/} 4 V remove(K k) {/*..*/} 5 V putIfAbsent(K k, V v) {/*..*/} 6 boolean replace(K k, V ov, V nv) {/*..*/} 7 } 1 class AtomicHistogram<K> {// client 2 private AtomicMap<K, Integer> m; 3 4 V get (K k) { 5 return m.get(k); 6 } 7 8 Integer inc(K key) { 9 while(true){ 10 Integer i = m.get(key); 11 if (i == null){ 12 Integer r = m.putIfAbsent(key, 1); ~ 13 if (r == null) 14 return 1; 15 } else{ 16 Integer ni = i + 1; 17 boolean b = m.replace(key, i, ni); ~ 18 if (b) 19 return ni; 20 }}}} Fig. 1. The classes AtomicMap and AtomicHistogram conditional versions of put: putIfAbsent only performs the put if the given key is currently unmapped, and replace only performs the put if the given key is currently mapped to a given value. As Figure 1 shows, a programmer may use the AtomicMap class to implement the client AtomicHistogram class, which sup- ports the method inc to increment one bar of the histogram. The figure shows a correct implementation of atomic increment [30], which is subtle and error prone. For example, a naive implementation of this client method, which simply gets the current value and puts back an incremented value, is not atomic and can easily violate the sequential specification in the presence of multiple threads. In this paper, we present an automatic and modular technique for verification of the atomicity of clients of concurrent data structures, such as our histogram class. Prior work on automatic atomicity verification leverages Lipton's notion of moverness [23]. Moverness can be applied to verify conflict-serializability of transactions [4] and atomicity of both data-structure and client methods [14, 15, 35]. The main idea is to prove that individual operations in a method M can commute with operations from other threads, in such a way that M's operations can be always \moved" to be contiguous in any execution. Moverness has been successfully applied to automatically check atomicity of concurrent code that uses locks for synchronization [14, 15] and was later extended to sup- port non-blocking synchronization by paired load-link (LL) and store-conditional (SC) instructions [35]. Unfortunately, the ABA problem [27] makes moverness too strong a requirement to prove atomicity of non-blocking algorithms that employ compare-and-swap (CAS) [35]. Similarly, as we will show in the next section, the ABA problem makes the moverness requirement too strong to prove the atomicity of the increment method in Figure 1. Instead, we define and check a novel sufficient condition for atomicity called condensability. Our approach handles client classes that use a single concurrent data structure in their implementation. Consider a client method M that uses an atomic object o. Intuitively, a call to M in a concurrent execution e is con- densable if there is a method call m on o in M's execution such that (a) either m does not modify the state of o or it is the only method call in M's execution that does so; and (b) the sequential execution of the entire method M at the place of m in e results in the same final state of o as m and the same return value as the original execution of M. A client object is condensable if every execution of every method of it is condensable. The notion of condensability is similar in spirit to the idea of moverness, but instead of moving individual oper- ations in a method, condensability allows relocating the entire method at once. Condensability targets a common class of clients that access a single concurrent data structure and provides a modular verification technique for atomicity of this class of clients. Specifically, condensability can be separately checked for each method, so changes to one method do not affect the condensability of other methods. In Section 3, we formalize condensability and prove that condensability implies atomicity. We demonstrate the applicability of condensability with an automatic check- ing tool for Java called Snowflake. The tool takes as input a client class C along with a sequential specification for each of the methods in the concurrent data structure that C employs. As we will show later, such specifications are typically quite simple and are obtainable from documentation of the data structures. For each method in C, Snowflake generates a set of proof obligations that are suffi- cient for condensability and provides them to the Z3 SMT solver [8]. If the proof obligations are discharged, the method is verified to be atomic. We applied Snowflake to a suite of open-source benchmarks that was used to evaluate prior work by others [30]. Snowflake succeeds in verifying atomicity of 76.9% of the atomic methods and rejecting all non-atomic methods in the benchmark suite. In addition, Snowflake can verify the remaining 23.1% of the atomic methods after some manual code refactoring. Related work. Shacham et al. [30] provide a tool called Colt for finding atomicity bugs in client methods of concurrent data structures by heuristically executing such code with interference from other threads. They reported many bugs in a variety of real-world applications. Tools like Colt identify actual exe- cutions with atomicity bugs and as such have no false positives, but they cannot prove the absence of such errors. In later work, Shacham and colleagues have explored conditions on client methods that allow for exhaustive testing for interference, thereby support- ing atomicity verification. Shacham [29] shows that a data-independent client method, whose control flow does not depend on the specific data values used, need only be tested using a bounded number of data values in order to cover all possible atomicity violations. Zomer et al. [37] show that an encapsulated client method, whose only shared state is the underlying data structure, need only be tested using two threads and one occurrence of the client method. They also provide a condition called composition closure on the underlying data structure that allows each client method to be tested separately for interference. Our work requires client methods to be encapsulated and to support additional restrictions but does not restrict the data structure itself; indeed maps are not composition closed. Our restrictions allow us to verify atomicity via a few simple and modular condensability conditions on each method. Work on atomicity refinement provides sound rules for extending the scope of atomic blocks [12, 20]. Some refinement rules, such as Jonsson's absorption rule [20], are similar in spirit to our requirements for condensability. However, the refinement rules must be applied step by step in order to eventually produce a single atomic block, while condensability directly compares an interleaved ex- ecution to a sequential version. Others have ensured atomicity for clients of linearizable data structures by automatically inserting additional synchronization [5, 16, 18]. Such approaches provide strong atomicity guarantees by construction but incur synchronization overheads that our approach avoids. In addition to prior work on atomicity, condensability is closely related to the notion of linearization points in linearizability proofs, which are points where each method can be seen to atomically satisfy its sequential specification. Lin- earizability is a strong property that combines atomicity with functional cor- rectness.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    18 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us