A separation logic for refining concurrent objects
Fine-grained concurrent data structures are crucial for gaining performance from multiprocessing, but their design is a subtle art. Recent literature has made large strides in verifying these data structures, using either atomicity refinement or separation logic with rely-guarantee reasoning. In this paper we show how the ownership discipline of separation logic can be used to enable atomicity refinement, and we develop a new rely-guarantee method that is localized to the definition of a data structure. We present the first semantics of separation logic that is sensitive to atomicity, and show how to control this sensitivity through ownership. The result is a logic that enables compositional reasoning about atomicity and interference, even for programs that use fine-grained synchronization and dynamic memory allocation.
- Conference Article
31
- 10.1145/1926385.1926415
- Jan 26, 2011
Fine-grained concurrent data structures are crucial for gaining performance from multiprocessing, but their design is a subtle art. Recent literature has made large strides in verifying these data structures, using either atomicity refinement or separation logic with rely-guarantee reasoning. In this paper we show how the ownership discipline of separation logic can be used to enable atomicity refinement, and we develop a new rely-guarantee method that is localized to the definition of a data structure. We present the first semantics of separation logic that is sensitive to atomicity, and show how to control this sensitivity through ownership. The result is a logic that enables compositional reasoning about atomicity and interference, even for programs that use fine-grained synchronization and dynamic memory allocation.
- Dissertation
- 10.26686/wgtn.17060108
- Jan 1, 2017
<p>This thesis explores two kinds of program logics that have become important for modern program verification - separation logic, for reasoning about programs that use pointers to build mutable data structures, and rely guarantee reasoning, for reasoning about shared variable concurrent programs. We look more closely into the motivations for merging these two kinds of logics into a single formalism that exploits the benefits of both approaches - local, modular, and explicit reasoning about interference between threads in a shared memory concurrent program. We discuss in detail two such formalisms - RGSep and Local Rely Guarantee (LRG), in particular we analyse how each formalism models program state and treats the distinction between global state (shared by all threads) and local state (private to a given thread) and how each logic models actions performed by threads on shared state, and look into the proof rules specifically for reasoning about atomic blocks of code. We present full examples of proofs in each logic and discuss their differences. This thesis also illustrates how a weakest precondition semantics for separation logic can be used to carry out calculational proofs. We also note how in essence these proofs are data abstraction proofs showing that a data structure implements some abstract data type, and relate this idea to a classic data abstraction technique by Hoare. Finally, as part of the thesis we also present a survey of tools that are currently available for doing manual or semi-automated proofs as well as program analyses with separation logic and rely guarantee.</p>
- Dissertation
- 10.26686/wgtn.17060108.v1
- Jan 1, 2017
<p>This thesis explores two kinds of program logics that have become important for modern program verification - separation logic, for reasoning about programs that use pointers to build mutable data structures, and rely guarantee reasoning, for reasoning about shared variable concurrent programs. We look more closely into the motivations for merging these two kinds of logics into a single formalism that exploits the benefits of both approaches - local, modular, and explicit reasoning about interference between threads in a shared memory concurrent program. We discuss in detail two such formalisms - RGSep and Local Rely Guarantee (LRG), in particular we analyse how each formalism models program state and treats the distinction between global state (shared by all threads) and local state (private to a given thread) and how each logic models actions performed by threads on shared state, and look into the proof rules specifically for reasoning about atomic blocks of code. We present full examples of proofs in each logic and discuss their differences. This thesis also illustrates how a weakest precondition semantics for separation logic can be used to carry out calculational proofs. We also note how in essence these proofs are data abstraction proofs showing that a data structure implements some abstract data type, and relate this idea to a classic data abstraction technique by Hoare. Finally, as part of the thesis we also present a survey of tools that are currently available for doing manual or semi-automated proofs as well as program analyses with separation logic and rely guarantee.</p>
- Conference Article
27
- 10.1109/.9
- Jul 20, 2009
The capabilities of modern FPGAs permit the mapping of increasingly complex applications into reconfigurable hardware. High-level synthesis (HLS) promises a significant shortening of the FPGA design cycle by raising the abstraction level of the design entry to high-level languages such as C/C++. Applications using dynamic, pointer-based data structures and dynamic memory allocation, however, remain difficult to implement well, yet such constructs are widely used in software. Automated optimizations that aim to leverage the increased memory bandwidth of FPGAs by distributing the application data over separate banks of on-chip memory are often ineffective in the presence of dynamic data structures, due to the lack of an automated analysis of pointer-based memory accesses. In this work, we take a step towards closing this gap. We present a static analysis for pointer-manipulating programs which automatically splits heap-allocated data structures into disjoint, independent regions. The analysis leverages recent advances in separation logic, a theoretical framework for reasoning about heap-allocated data which has been successfully applied in recent software verification tools. Our algorithm focuses on dynamic data structures accessed in loops and is accompanied by automated source-to-source transformations which enable automatic loop parallelization and memory partitioning by off-the-shelf HLS tools. We demonstrate the successful loop parallelization and memory partitioning by our tool flow using three real-life applications which build, traverse, update and dispose dynamically allocated data structures. Our case studies, comparing the automatically parallelized to the non-parallelized HLS implementations, show an average latency reduction by a factor of 2.5 across our benchmarks.
- Conference Article
14
- 10.1109/fccm.2014.11
- May 1, 2014
The capabilities of modern FPGAs permit the mapping of increasingly complex applications into reconfigurable hardware. High-level synthesis (HLS) promises a significant shortening of the FPGA design cycle by raising the abstraction level of the design entry to high-level languages such as C/C++. Applications using dynamic, pointer-based data structures and dynamic memory allocation, however, remain difficult to implement well, yet such constructs are widely used in software. Automated optimizations that aim to leverage the increased memory bandwidth of FPGAs by distributing the application data over separate banks of on-chip memory are often ineffective in the presence of dynamic data structures, due to the lack of an automated analysis of pointer-based memory accesses. In this work, we take a step towards closing this gap. We present a static analysis for pointer-manipulating programs which automatically splits heap-allocated data structures into disjoint, independent regions. The analysis leverages recent advances in separation logic, a theoretical framework for reasoning about heap-allocated data which has been successfully applied in recent software verification tools. Our algorithm focuses on dynamic data structures accessed in loops and is accompanied by automated source-to-source transformations which enable automatic loop parallelization and memory partitioning by off-the-shelf HLS tools. We demonstrate the successful loop parallelization and memory partitioning by our tool flow using three real-life applications which build, traverse, update and dispose dynamically allocated data structures. Our case studies, comparing the automatically parallelized to the non-parallelized HLS implementations, show an average latency reduction by a factor of 2.5 across our benchmarks.
- Conference Article
6
- 10.1145/2576779.2576781
- Mar 1, 2014
OpenCL is becoming a popular choice for the parallel programming of both multi-core CPUs and GPGPUs. One of the features missing in OpenCL, yet commonly required in irregular parallel applications, is dynamic memory allocation. In this paper, we propose KMA, a first dynamic memory allocator for OpenCL. KMA's design is based on a thorough analysis of a set of 11 algorithms, which shows that dynamic memory allocation is a necessary commodity, typically used for implementing complex data structures (arrays, lists, trees) that need constant restructuring at runtime. Taking into account both the survey findings and the status-quo of OpenCL, we design KMA as a two-layer memory manager that makes smart use of the patterns we identified in our application analysis: its basic functionality provides generic malloc() and free() APIs, while the higher layer provides support for building and efficiently managing dynamic data structures. Our experiments measure the performance and usability of KMA, using both microbenchmarks and a real-life case-study. Results show that when dynamic allocation is mandatory, KMA is a competitive allocator. We conclude that embedding dynamic memory allocation in OpenCL is feasible, but it is a complex, delicate task due to the massive parallelism of the platform and the portability issues between different OpenCL implementations.
- Research Article
3
- 10.1016/j.apal.2021.103063
- Nov 19, 2021
- Annals of Pure and Applied Logic
Separation logic and logics with team semantics
- Book Chapter
9
- 10.1007/978-3-319-94205-6_30
- Jan 1, 2018
Separation logic has become a stock formalism for reasoning about programs with dynamic memory allocation. We introduce a variant of separation logic that supports lists and trees as well as inductive constraints on the data stored in these structures. We prove that this logic has the small model property, meaning that for each satisfiable formula there is a small domain in which the formula is satisfiable. As a consequence, the satisfiability and entailment problems for our fragment are in NP and coNP, respectively. Leveraging this result, we describe a polynomial SMT encoding that allows us to decide satisfiability and entailment for our separation logic.
- Conference Article
12
- 10.1109/iscis.2008.4717922
- Oct 1, 2008
Dynamic memory (DM) allocation is one of the most crucial components of modern software engineering. It offers a greatest flexibility to the software systemspsila design; nevertheless, developers of real-time systems often avoid using dynamic memory allocation due to its problems like unbounded or long bounded response time and memory fragmentation. However, the modern complex applications like multimedia streaming and network applications made the dynamic memory allocation mandatory for applicationspsila design. The major challenges of memory allocator are minimizing fragmentation, providing a good response time, and maintaining a good locality among the memory blocks. This paper introduces a new smart dynamic memory allocator particularly for embedded systems that have limited memory and processing power. It aimed at addressing the major challenges of dynamic memory allocator. The smart allocator predicts the short-lived objects and allocates those objects on one side of the heap memory and remaining objects on other side of the heap memory for effective utilization of memory footprint. The allocator is implemented with enhanced multilevel segregated mechanism using lookup tables and hierarchical bitmaps that ensure very good response time and reliable timing performance. The proposed algorithm has shown excellent experimental results, with respect to both response time and memory footprint usage, as compared to the well known algorithms. In addition, this paper presents a memory intensive synthetic (MIS) work load, which can model the allocation behavior of most of the real applications.
- Single Book
17
- 10.47715/jpc.b.978-93-91303-50-1
- Apr 30, 2023
The book "Data Structures Using C" provides a comprehensive guide to the fundamental concepts of data structures and algorithms using the C programming language. The book is designed to serve as a practical guide for students, professionals, and researchers who want to learn data structures and algorithms using C language. The book covers various data structures such as arrays, linked lists, stacks, queues, trees, graphs, and hashing, and their implementation using the C language. It also covers various sorting and searching algorithms such as bubble sort, quicksort, merge sort, binary search, and linear search. The book provides numerous examples and exercises to help readers practice and implement the concepts learned. The book also includes real-world examples of data structures and algorithms used in computer science and engineering. In addition, the book covers advanced topics such as dynamic memory allocation, recursion, and file handling using C language. The book also covers advanced data structures such as AVL trees, Red-Black trees, and B-trees. The book is written in a simple and easy-to-understand language with a focus on practical implementation. It aims to help readers develop a solid foundation in data structures and algorithms and apply them to solve real-world problems. Keywords: Data Structures, C Programming Language, Algorithms, Arrays, Linked Lists, Stacks, Queues, Trees, Graphs, Hashing, Sorting Algorithms, Searching Algorithms, Dynamic Memory Allocation, Recursion, File Handling, AVL Trees, Red-Black Trees, B-Trees.
- Research Article
2
- 10.1145/3591275
- Jun 6, 2023
- Proceedings of the ACM on Programming Languages
Concurrent separation logic has been responsible for major advances in the formal verification of fine-grained concurrent algorithms and data structures such as locks, barriers, queues, and reference counters. The key ingredient of the verification of a fine-grained program is an invariant, which relates the physical data representation (on the heap) to a logical representation (in mathematics) and to the state of the threads (using a form of ghost state). An invariant is typically represented as a disjunction of logical states, but this disjunctive nature makes invariants a difficult target for automated verification. Current approaches roughly suffer from two problems. They use backtracking to introduce disjunctions in an uninformed manner, which can lead to unprovable goals if an appropriate case analysis has not been made before choosing the disjunct. Moreover, they eliminate disjunctions too eagerly, which can cause poor efficiency. While disjunctions are no problem for automated provers based on classical (i.e., non-separating) logic, the challenges with disjunctions are prominent in the study of proof automation for intuitionistic logic. We take inspiration from that area—specifically, based on ideas from connection calculus , we design a simple multi-succedent calculus for separation logic with disjunctions featuring a novel concept of a connection . While our calculus is not complete, it has the advantage that it can be extended with features of the state-of-the-art concurrent separation logic Iris (such as modalities, higher-order quantification, ghost state, and invariants), and can be implemented effectively in the Coq proof assistant with little need for backtracking. We evaluate the practicality on 24 challenging benchmarks, 14 of which we can verify fully automatically.
- Research Article
2
- 10.37391/ijeer.100254
- Jun 30, 2022
- International Journal of Electrical and Electronics Research
Due to an increased scalability, flexibility, and reduced cost complexity, the dynamic memory allocation models are highly preferred for the real-time embedded systems. For this purpose, the different types of dynamic models have been developed in the conventional works, which are highly focused on allocating the memory blocks with increased searching capability. However, it faced some of the problems and issues related to the factors of complex operations, high time consumption, memory overhead, and reduced speed of processing. Thus, this research work objects to design an advanced and intelligent dynamic memory allocation mechanism for the real-time embedded systems. Here, a Classy Memory Management System (CyM2S) is developed by using an Isolated Dynamic Two-Level Memory Allocation (ID2LMA) algorithm for efficiently allocating the memory blocks with simple searching. The CyM2S helps to reduce the fragmentation rate and time consumption by optimally allocating the memory blocks. In this model, the small buffer has been maintained for surplus pointers, and the allocated blocks comprise the metadata and payload data. During evaluation, the performance of the proposed CyM2S- ID2LMA technique is validated and compared by using the measures of memory allocation time, release time, execution, and processing speed.
- Research Article
6
- 10.1145/3282517.3282528
- Dec 28, 2018
- ACM SIGSOFT Software Engineering Notes
Software systems are often shipped and deployed with both known and unknown bugs. On-the-fly program repairs, which handle runtime errors and allow programs to continue successfully, can help software reliability, e.g., by dealing with inconsistent or corrupted data without interrupting the runni program. We report on our work-in-progress that repairs dat structure using separation logic. Our technique, inspired by existing works on specification-based repair, takes as input specification written in a separation logic formula and a concrete data structure that fails that specification, and performs on-thefly repair to make the data conforms with the specification. The use of separation logic allows us to compactly and precisely represent desired properties of data structures and use existing analyses in separation logic to detect and repair bugs in complex data structures. We have developed a prototype, called STARFIX, to repair invalid Java data structures violating given specifications in separation logic. Preliminary results show that tool can efficiently detect and repair inconsistent data structures including lists and trees.
- Research Article
31
- 10.1145/3158125
- Dec 27, 2017
- Proceedings of the ACM on Programming Languages
Concurrent separation logics have helped to significantly simplify correctness proofs for concurrent data structures. However, a recurring problem in such proofs is that data structure abstractions that work well in the sequential setting are much harder to reason about in a concurrent setting due to complex sharing and overlays. To solve this problem, we propose a novel approach to abstracting regions in the heap by encoding the data structure invariant into a local condition on each individual node. This condition may depend on a quantity associated with the node that is computed as a fixpoint over the entire heap graph. We refer to this quantity as a flow . Flows can encode both structural properties of the heap (e.g. the reachable nodes from the root form a tree) as well as data invariants (e.g. sortedness). We then introduce the notion of a flow interface , which expresses the relies and guarantees that a heap region imposes on its context to maintain the local flow invariant with respect to the global heap. Our main technical result is that this notion leads to a new semantic model of separation logic. In this model, flow interfaces provide a general abstraction mechanism for describing complex data structures. This abstraction mechanism admits proof rules that generalize over a wide variety of data structures. To demonstrate the versatility of our approach, we show how to extend the logic RGSep with flow interfaces. We have used this new logic to prove linearizability and memory safety of nontrivial concurrent data structures. In particular, we obtain parametric linearizability proofs for concurrent dictionary algorithms that abstract from the details of the underlying data structure representation. These proofs cannot be easily expressed using the abstraction mechanisms provided by existing separation logics.
- Book Chapter
6
- 10.1007/11424505_34
- Jan 1, 2005
The needs for run-time data storage in modern wired and wireless network applications are increasing. Additionally, the nature of these applications is very dynamic, resulting in heavy reliance to dynamic memory allocation. The most significant problem in dynamic memory allocation is fragmentation, which can cause the system to run out of memory and crash, if it is left unchecked. The available dynamic memory allocation solutions are provided by the real time Operating Systems used in embedded or general-purpose systems. These state-of-the-art dynamic memory allocators are designed to satisfy the run-time memory requests of a wide range of applications. Contrary to most applications, network applications need to allocate too many different memory sizes (e.g. hundreds different sizes for packets) and have an extremely dynamic allocation and de-allocation behavior (e.g. unpredictable web-browsing activity). Therefore, the performance and the de-fragmentation efficiency of these allocators is limited. In this paper, we analyze all the important issues of fragmentation and the ways to reduce it in network applications, while keeping the performance of the dynamic memory allocator unaffected or even improving it. We propose highly customized dynamic memory allocators, which can be configured for specific network needs. We assess the effectiveness of the proposed approach in two representative real-life case studies of wired and wireless network applications. Finally, we show very significant reduction in memory fragmentation and increase in performance compared to state-of-the-art dynamic memory allocators utilized by real-time Operating Systems.KeywordsMemory SizeNetwork ApplicationMemory BlockReal Time Operating SystemInternal FragmentationThese keywords were added by machine and not by the authors. This process is experimental and the keywords may be updated as the learning algorithm improves.