Decidability of Liveness on the TSO Memory Model

07/21/2021
by   Chao Wang, et al.
0

An important property of concurrent objects is whether they support progress -a special case of liveness-guarantees, which ensure the termination of individual method calls under system fairness assumptions. Liveness properties have been proposed for concurrent objects. Typical liveness properties includelock-freedom,wait-freedom,deadlock-freedom,starvation-freedom and obstruction-freedom. It is known that the five liveness properties above are decidable on the Sequential Consistency (SC) memory model for a bounded number of processes. However, the problem of decidability of liveness for finite state concurrent programs running on relaxed memory models remains open. In this paper we address this problem for the Total Store Order (TSO) memory model,as found in the x86 architecture. We prove that lock-freedom, wait-freedom,deadlock-freedom and starvation-freedom are undecidable on TSO for a bounded number of processes, while obstruction-freedom is decidable.

READ FULL TEXT VIEW PDF
POST COMMENT

Comments

There are no comments yet.

Authors

page 1

page 2

page 3

page 4

05/13/2018

Fast and Scalable Group Mutual Exclusion

The group mutual exclusion (GME) problem is a generalization of the clas...
01/05/2021

An Ownership Policy and Deadlock Detector for Promises

Task-parallel programs often enjoy deadlock freedom under certain restri...
05/14/2021

Linearizability: a Typo

Linearizability is the de facto consistency condition for concurrent obj...
08/29/2018

Memory Consistency Models using Constraints

Memory consistency models (MCMs) are at the heart of concurrent programm...
08/05/2021

Crystalline: Fast and Memory Efficient Wait-Free Reclamation

Historically, memory management based on lock-free reference counting wa...
09/15/2021

Dala: A Simple Capability-Based Dynamic Language Design For Data Race-Freedom

Dynamic languages like Erlang, Clojure, JavaScript, and E adopted data-r...
This week in AI

Get the week's most popular data science and artificial intelligence research sent straight to your inbox every Saturday.

1 Introduction

A concurrent object provides a set of methods for client programs to access the object. Given the complexity of writing efficient concurrent code, it is recommended to use mature libraries of concurrent objects such as java.util.concurrent for Java and std::thread for C++11. The verification of these concurrent libraries is obviously important but intrinsically hard, since they are highly optimized to avoid blocking – thus exploiting more parallelism – by using optimistic concurrency in combination with atomic instructions like compare-and-set.

Various liveness properties (progress conditons) have been proposed for concurrent objects. Lock-freedom, wait-freedom, deadlock-freedom, starvation-freedom and obstruction-freedom [9, 13] are five typical liveness properties. A liveness property describes conditions under which method calls are guaranteed to successfully complete in an execution. Intuitively, clients of a wait-free library can expect each method call to return in finite number of steps. Clients using a lock-free library can expect that at any time, at least one library method call will return after a sufficient number of steps, while it is possible for methods on other processes to never return. Deadlock-freedom and starvation-freedom require each fair execution to satisfy lock-freedom and wait-freedom, respectively. Clients using an obstruction-free library can expect each method call to return in a finite number of steps when executed in isolation.

It is often that programmers assume that all accesses to the shared memory are performed instantaneously and atomically, which is guaranteed only by the sequential consistency (SC) memory model [11]. However, modern multiprocessors (e.g., x86 [7], ARM [14] ), and programming languages (e.g., C/C++ [3], Java [15]) do not implement the SC memory model. Instead they provide relaxed memory models, which allow subtle behaviors due to hardware and compiler optimizations. For instance, in a multiprocessor system implementing the Total Store Order (TSO) memory model [2], each processor is equipped with a FIFO store buffer. In this paper we follow the TSO memory model of [2] (similarly to [17, 4, 5]). Although in every realistic multiprocessor system implementing the TSO memory model, the buffer is of bounded size, to describe the semantics of any TSO implementing system it is necessary to consider unbounded size FIFO store buffers associated with each process, as in the semantics of [2]. Otherwise, TSO implementations with larger store buffer will not be captured by this theoretical TSO memory model. Any write action performed by a processor is put into its local store buffer first and can then be flushed into the main memory at any time. Some libraries are optimized for relaxed memory models. For example, some work-stealing queue implementations [12, 16] are specifically written to perform well on TSO.

To address the problem of decidability of liveness properties, we remark that concurrent systems with a bounded number of processes on SC can be expressed as finite state labelled transition systems (LTS). Lock-freedom, wait-freedom and obstruction-freedom can be expressed as LTL formulas, as shown in [18]. We show that deadlock-freedom and starvation-freedom can be expressed as CTL formulas. Given that LTL and CTL model checking is decidable [6], it is known that lock-freedom, wait-freedom, deadlock-freedom, starvation-freedom and obstruction-freedom are decidable in this case. However, their decidability problem on TSO memory model for a bounded number of processes remains open.

In this paper, we study the decision problem of liveness properties on TSO. Our work covers the five typical liveness properties of [9], which are commonly used in practice. Our main findings are:

  • Lock-freedom, wait-freedom, deadlock-freedom and starvation-freedom are undecidable on TSO, which reveals that the verification of liveness properties on TSO is intrinsically harder when compared to their verification on SC.

  • Obstruction-freedom is decidable on TSO.

To the best of our knowledge, ours are the first decidability and undecidability results for liveness properties on relaxed memory models. Let us now present a sketch of the techniques used in the paper to justify our findings.

Undecidability Proof. Abdulla et al. [1] reduce the cyclic post correspondence problem (CPCP) [19], a known undecidable problem, into checking whether a specific lossy channel machine has an infinite execution that visits a specific state infinitely often. Our undecidability proof of lock-freedom and wait-freedom is obtained by reducing the checking of the lossy channel machine problem into checking lock-freedom and wait-freedom for a specific library, based on a close connection of concurrent programs on TSO and lossy channel machines [2, 20].

We generate a library template that can be instantiated as a specific library for each instance of CPCP. The collaboration between methods simulates lossy channel machine transitions. Each execution of the lossy channel machine contains (at most) two phases. Each accepting infinite execution of the lossy channel machine loops infinitely in the second phase. Thus, we make each method of the library to work differently depending on the phase. Our library has the following features: if an infinite library execution simulates an accepting infinite execution of the lossy channel machine, then it violates lock-freedom, and thus, it also violates wait-freedom; if an infinite library execution does not simulate an accepting infinite execution of the lossy channel machine, then it satisfies wait-freedom, and thus, it also satisfies lock-freedom. This is because any execution that satisfies wait-freedom also satisfies lock-freedom. Therefore, we reduce checking whether the lossy channel machine has an accepting infinite execution, or more precisely CPCP, into checking lock-freedom and wait-freedom of the library.

Perhaps surprisingly, the same library can be used to show the undecidability of deadlock-freedom (resp., starvation-freedom), which requires that each infinite fair execution satisfies lock-freedom (resp., wait-freedom). This is because whenever a library execution simulates an accepting infinite execution of the lossy channel machine, we require library methods to collaborate and work alternatingly, and thus, such library execution must be fair and violates deadlock-freedom, and thus, violates starvation-freedom. Therefore, checking the existence of accepting infinite executions of the lossy channel machines is reduced into checking violations of deadlock-freedom and starvation-freedom.

Decidability Proof. We introduce a notion called blocking pair, coupling a process control state and a memory valuation, and capturing a time point from which we can generate an infinite execution on the SC memory model, for which eventually one process runs in isolation and does not perform any return. We reduce checking obstruction-freedom into the state reachability problem, a known decidable problem [2], for configurations that “contain a blocking pair” and have an empty buffer for each process. There are two difficulties here: firstly, the TSO concurrent systems of [2] do not use libraries; and secondly, the state reachability problem requires the buffer of each process to be empty for the destination configuration, while such configuration may not exist in a obstruction-freedom violation.

The first difficulty is addressed by making each process repeatedly call an arbitrary method with an arbitrary arguments for an arbitrarily number of times, while transforming each call and return action into internal actions. To solve the second difficulty, we show that each obstruction-freedom violation has a prefix reaching a configuration that “contains a blocking pair”. By discarding specific actions of the prefix execution and forcing some flush actions to happen, we obtain another prefix execution reaching a configuration that both “contains a blocking pair” and has an empty buffer for each process.

Related work. There are several works on the decidability of verification on TSO. Atig et al. [2] prove that the state reachability problem is decidable on TSO while the repeated state reachability problem is undecidable on TSO. Bouajjani et al. [4] prove that robustness is decidable on TSO. Our previous work [20] proves that TSO-to-TSO linearizability [5], a correctness condition of concurrent libraries on TSO, is undecidable on TSO. Our previous work [21] proves that a bounded version of TSO-to-SC linearizability [8] is decidable on TSO. None of these works address the decidability of concurrent library liveness on TSO.

Our approach for simulating executions of lossy channel machines with libraries is partly inspired by Atig et al. [2]. However, Atig et al. do not consider libraries, and their concurrent programs do not have call or return actions. Our library needs to ensure that, in each infinite library execution simulating an infinite execution of the lossy channel machine, methods are “fixed to process”, in other words, the same method must run on the same process. The TSO concurrent systems of [2] do not need to “fix methods to processes” since they record the control states and transitions of each process. Both Atig et al. and our work store the lossy channel content in the store buffer. However, when simulating one lossy channel machine transition, methods of Atig et al. only require to do one read or write action, while methods of our paper require to read the whole channel content. It appears that we can not “fix methods to processes” with methods in the style of [2], unless we use specific command to directly obtain the process identifier.

Our previous work [20] considers safety properties of libraries. Both [20] and this paper use the collaboration of two methods to simulate one lossy channel machine transition. Our idea for simulating lossy channel machine transitions with libraries extends that of [20], since each library constructed using the latter contains executions violating liveness, which makes such libraries not suitable for their reduction to liveness. The library of [20] contains a method that never returns and thus, do not need to consider “fixing methods to processes”.

Our previous work [21] verifies bounded TSO-to-SC linearizability by reducing it into another known decidable reachability problem, the control state reachability problem of lossy channel machines. That work focuses on dealing with call and return actions across multiple processes, while our verification approach for obstruction-freedom considers call and return action as internal actions.

2 Concurrent Systems

2.1 Notations

In general, a finite sequence on an alphabet is denoted , where is the concatenation symbol and for each . Let and denote the length and the -th element of , respectively, i.e., and for . Let denote the string . Let denote the projection of on the alphabet . Given a function , let be the function that is the same as everywhere, except for , where it has the value . Let denote an item, of which the value is irrelevant, and the empty word.

A labelled transition system (LTS) is a tuple , where is a set of states, is an alphabet of transition labels, is a transition relation and is the initial state. A finite path of is a finite sequence of transitions with , and a finite trace of is a finite sequence , with if there exists a finite path of . An infinite path of is an infinite sequence of transitions , and correspondingly an infinite trace of is an infinite sequence if there exists an infinite path of .

2.2 Concurrent Objects and The Most General Client

Concurrent objects are implemented as well-encapsulated libraries. The most general client of a concurrent object is a program that interacts with the object, and is designed to exhibit all the possible behaviors of the object. A simple instance of the most general client is a client that repeatedly makes non-deterministic method calls with non-deterministic arguments. Libraries may contain private memory locations for their own uses. For simplicity, and without loss of generality, we assume that methods have only one argument and one return value (when they return).

Given a finite set of memory locations, a finite set of method names and a finite data domain , the set PCom of primitive commands is defined by the following grammar:

where and . Here represents an internal command. To use the commands as labels in an LTS we assume that they encode the expected values that they return (an oracle of sorts). Hence, for instance the read command encodes the value read . In general cas (compare-and-set) commands execute a read and a conditional write (or no write at all) in a single atomic step. In our case a successful cas is represented with the command , and it is enabled when the initial value of is , upon which the command updates it with value , while a failed cas command, represented with the command does not update the state, and can only happen when the value of is not .

A library is a tuple = , where , and are a finite memory location set, a finite method name set and a finite data domain of , respectively. is the union of disjoint finite sets of program positions of each method . Each program position represents the current program counter value and local register value of a process and can be considered as a state. is the union of disjoint transition relations of each method . Let be the set of primitive commands (except call and return commands) upon , and . Then, for each , . For each and , contains an initial program position , which represents that library begins to execute method with argument , and a final program position which represents that method has finished its execution and then a return action with return value can occur. There are neither incoming transitions to nor outgoing transitions from in .

The most general client is defined as a tuple , where is a finite method name set, is a finite data domain, is the state set, and is a transition relation. State represents that currently no method of library is running, and represents that some method of library is running.

2.3 TSO Operational Semantics

A concurrent system consists of processes, each of which runs the most general client = , and all the most general clients interact with a same library = . In this paper we follow the TSO memory model of [2] (similarly to [17, 4, 5]), where each processor is equipped with a FIFO store buffer. As explained in the introduction, in this TSO memory model, each process is associated with an unbounded FIFO store buffer. Fence commands are used to ensure order between commands before fence and commands after fence. The TSO memory model of [2] does not include fence commands, since fence commands can be simulated with cas commands.

The operational semantics of a concurrent system (with library and processes) on TSO is defined as an LTS = , with Conf, , and InitConf described below.

Configuration of Conf are tuples , where represents the control state of each process, is the valuation of memory locations, and is the content of each process’s store buffer. The initial configuration is . Here maps each process id to , is a valuation for memory locations in , and initializes each process with an empty buffer.

We denote with the set of actions defined by the following grammar:

where , and . The transition relation is the least relation satisfying the transition rules shown in Figure 1 for each . The rules are explained below:

  • Tau rule: A transition only influences the control state of one process.

  • Read rule: A function is used to search for the latest value of in the buffer or the main memory, i.e.,

    where is the set of items of in buffer. A action returns the latest value of in the buffer if present, or returns the value in memory if the buffer contains no stores on .

  • Write rule: An action puts an item into the tail of its store buffer.

  • and rules: A cas action atomically executes a read and a conditional write (or no write at all) if and only if the process’s store buffer is empty.

  • Flush rule: An flush action is carried out by the memory model to flush the item at the head of the process’s store buffer to memory at any time.

  • Call and Return rules: After a call action, the current process transits to . When the current process transits to it can launch a return action and move to of the most general client.

Figure 1: Transition Relation

3 Liveness

We use to denote all infinite traces of the concurrent system . Given an execution , we say a call action matches a return action with , if the two actions are by the same process, and there are no call or return actions by the same process in-between. Here we assume that methods do not call other methods. Let denote the set of pending call actions of , in other words, call actions of with no matching return action in .

We define the following predicates borrowed from [13]. Since we do not consider aborts, and we do not consider termination markers, we slightly modify the predicates definition of [13] by consider only infinite executions. Given an infinite execution :

  • : This predicate holds when every method call in eventually returns. Formally, for each index and action , if , there exists , such that matches .

  • : This predicate holds when there is always some method return action happens in the future if the system executes for a sufficient number of steps. Formally, for each index and action , if holds, then there exists , such that is a return action.

  • : This predicate holds if is an infinite trace with pending call actions, and at least one of the processes with a pending call action is scheduled infinitely many times. Formally, if and , then there exists , such that . Here represents the projection of into the actions of the process of .

  • : This predicate describing fair interleavings requires that if is an infinite execution, then each process is scheduled infinitely many times. Formally, if , then for each process in , . Here represents the projection of into actions of process .

  • : This predicate requires that if is an infinite execution, eventually only one process is scheduled. Formally, if , then there exists index and process , such that for each , is an action of process .

With these predicates, we can present the formal notions of lock-freedom, wait-freedom, deadlock-freedom, starvation-freedom and obstruction-freedom of [13].

Definition 1

Given an execution :

  • satisfies lock-freedom whenever: ,

  • satisfies wait-freedom whenever: ,

  • satisfies deadlock-freedom whenever: ,

  • satisfies starvation-freedom whenever: ,

  • satisfies obstruction-freedom whenever:

For library , we parameterize the definitions above over processes, and we define their satisfaction requiring that each execution of satisfies the corresponding liveness property.

Petrank et al. [18] demonstrate how to formalize lock-freedom, wait-freedom and obstruction-freedom as LTL formulas. It remains to show that deadlock-freedom and starvation-freedom for processes can be formalized as CTL formulas. Let , and be the standard modalities in CTL. Let be a predicate identifying return actions, be a predicate identifying actions of process , and the predicate identifying process ’s return actions. We define to describe fair executions of processes. Then, deadlock-freedom can be defined as the CTL formula , and starvation-freedom can be defined as the CTL formula .

As explained in Section 5.2, concurrent system with processes on SC can be expressed as finite state LTS, and LTL and CTL model checking is decidable [6], we can obtain that the above five liveness properties are decidable for SC.

4 Undecidability of Four Liveness Properties

In this section we propose our undecidability proof of lock-freedom, wait-freedom, deadlock-freedom and starvation-freedom on TSO.

4.1 Perfect/Lossy Channel Machines

A channel machine [1, 2] is a finite control machine equipped with channels of unbounded size. It can perform send and receive operations on its channels. A lossy channel machine is a channel machine where arbitrarily many items in its channels may be lost non-deterministically at any time and without any notification.

Let be the finite set of channel names and be a finite alphabet of channel contents. The content of a channel is a finite sequence over . A channel operation is either a send operation sending the value over channel , a receive operation receiving over , or a silent operation . We associate with each channel operation a relation over words as follows: Given , we have , and . A channel operation over a finite channel name set is a mapping that associates, with each channel of , a channel operation. Let be the set of channel operations over . The relation of channel operations is extended to channel operations over as follows: given a channel operation op over and two functions , we have , if holds for each .

A channel machine is formally defined as a tuple , where (1) is a finite set of states, (2) is a finite set of channel names, (3) is a finite alphabet for channel contents, (4) is a finite set of transition labels, and (5) is a finite set of transitions. When CM is considered as a perfect channel machine, its semantics is defined as an LTS . A configuration of Conf is a pair where and . initConf is the initial configuration and all its channels are empty. The transition relation is defined as follows: given and , , if there exists , such that and . When CM is considered as a lossy channel machine, its semantics is defined as another LTS , with transition relation defined as follows: , if there exists , such that (1) for each , is a sub-word of , (2) and (3) for each , is a sub-word of . Here a sequence is a sub-word of another sequence , if there exists , such that for each .

4.2 The Lossy Channel Machine for CPCP of Abdulla et al. [1]

Given two sequences and , let denote that there exists sequences and , such that and . Given two finite sequences and , where each and is a finite sequence over a finite alphabet, a solution of and is a nonempty sequence of indices , such that . The cyclic post correspondence problem (CPCP) [19], known to be undecidable, requires to answer given and , whether there exists one such solution.

Given two finite sequences and of finite sequences, Abdulla et al. [1] generate the lossy channel machine shown in Figure2. Moreover, they prove that CPCP has a solution for and , if and only if has an infinite execution that visits state infinite times. We point the readers to [1] for an explanation on how solves CPCP.

Figure 2: The lossy channel machine .

contains two channels and . We use to represent inserting the contents of into one by one, and use to represent receiving the content of from one by one. We use to represent first do and then do . Each execution of can be divided into (at most) two phases. The first phase, called the guess phase, is a self-loop of state , and is used to guess a solution of CPCP. The second phase, called the check phase, goes from to and then repeatedly “checks the content of and ”.

Based on we generate the lossy channel machine which uses only one channel and works in a similar way. To simulate one transition of , stores the content of followed by the content of (as well as new delimiter symbols) in its channel. Then it scans each symbol in its channel, modifies it (if necessary) and puts it back into its buffer, until the contents of and have all been dealt with.

We could depict similarly to Figure 2, and each transition of is now a “extended version transition” as we discussed above. Therefore, there are “’s versions” of , and , and when no confusion is possible we also call them , and , respectively. Note that if some new delimiter symbols are lost during transition, then such paths can not complete the simulation of one transition of , and thus, do not influence the proof of the following lemma. Based on above discussion, we reduce CPCP of and into an infinite execution problem of the lossy channel machine , as stated by the following lemma.

Lemma 1

There is a CPCP solution for sequences and of finite sequences, if and only if there is an infinite execution of that visits infinitely often.

4.3 Libraries for Four Liveness Properties

In this subsection, we propose our library that is generated from and simulates the executions of . This library contains two methods and . Similarly to [2, 20], we use the collaboration of two methods to simulate a lossy channel. Our library requires that each method be fixed to a single process when simulating infinite execution of . Methods of our library work differently when simulating lossy channel machine transitions of different phases.

Let us now explain in detail the construction of . uses the following memory locations: , , , , phase, failSimu and firstM1. phase stores the phase of , and its initial value is guess. failSimu is a flag indicating the failure of the simulation of , and its initial value is false. firstM1 is used to indicate the first execution of , and its initial value is true.

The pseudo-code of and are shown in Algorithms 1 and 2, respectively. and are two new symbols not contained in . For brevity, we use the following notations. We use to represent the sequence of commands writing followed by into . We use to represent the sequence of commands writing into . is a delimiter that ensures one update of a memory location will not be read twice. We use to represent the sequence of commands reading followed by from for some and then assigning to . Moreover, if the values read do not correspond with followed by we set failSimu to true and then let the current method return. This will terminate the simulation procedure. Similarly, reads a transition rule followed by from , and assign the rule to . We use to represent repeatedly using to read an update of and using to write it to , until reading from and writing to . Given a transition rule , let and be the value received and sent by , respectively. The symbols and in the pseudo-code of represent the corresponding state of .

Input: an arbitrary argument
1 while true do
2       If failSimu, then return;
3       if firstM1 then
4             guess a transition rule that starts from ;
5             ;
6             ;
7            
8      else
9             ;
10             let and ;
11             ;
12             if , then ;
13             guess a transition rule starts from the destination state of ;
14             ;
15             while true do
16                   ;
17                   if , then break;
18                   ;
19                  
20            ;
21            
22      if and the destination state of is , then set phase to check;
23       ;
24       if , then return;
25      
Algorithm 1
Input: an arbitrary argument
1 while true do
2       if failSimu, then return;
3       ;
4       ;
5       if , then return;
6      
Algorithm 2
Figure 3: One execution of .

Figure 3 illustrates a possible execution of . and work differently in the different phases. In the guess phase, and return after simulating one lossy channel machine transition, while in the check phase, and keep working until the simulation procedure fails.

Assume that (resp., ) runs on process (resp., process ). To simulate one lossy channel machine transition with channel content , we first store in process ’s store buffer as buffered items of , where is the transition rule of this transition, and and are additional symbols indicating the start and end of channel content of , respectively. Then, the procedure for simulating one lossy channel machine transition is as follows:

  • reads the transition rule and channel content of by reading all the updates of . After reading , non-deterministically chooses a transition rule of the lossy channel machine. Such rule should begin from the destination state of .

  • There are four points for information update and transfer between and : (1) According to transition rule , modifies and writes all the updates of into , (2) then reads all the updates of and writes all the updates into , (3) then reads all the updates of and writes all the updates into , and (4) finally, reads all the updates of and writes all the updates into . To read all the updates of a memory location, we need to repeatedly read until read , which indicates the end of channel content.

    Since there is no item in the buffer at the beginning of the simulation procedure, to simulate the first lossy channel machine transition directly writes to and does not need to read updates from , where is a transition rule from . This is the reason for using firstM1.

  • is also responsible for modifying the phase (stored in the memory location phase). If the last lossy channel machine transition simulated belongs to the guess phase and the destination state of is , changes the memory location phase to check.

The reason why we need to update and transfer information between and is to deal with the case when an update of is not captured. Let us first consider a simple but infeasible solution: reads updates from (until reading ), and modifies and writes all the updates into ; while repeatedly reads an update of and writes it into , until reading . This solution can not deal with the case when updates of for is not seen by , and will make and fall into infinite loop that violates liveness. This may happen in simulating each lossy channel machine transition, and thus, introduces “false negatives” to four liveness properties. To deal with this case, we need to break the infinite loop and avoid directly writing the updates of back into . Instead, in our update and transfer points, we exhaust the updates of , which are written to , and later written to instead of . Therefore, there is no infinite loop even if updates of for are lost.

Assume that we can successfully simulate one transition of with one running on process and one running on process . Then the most general client on process (resp., on process ) can call and . Perhaps surprisingly, the only possible way to simulate the second transition of is to let and to continue to run on processes and , respectively. Let us explain why other choices fail to simulate the second transition: (1) If both processes run method , then they both require reading updates of . Since there is no buffered item for , and none of them write to , both fail the simulation. (2) If both processes run , we arrive at a similar situation. (3) If and run on processes and , respectively. requires reading the updates on , and the only possible buffered items are in process ’s buffer. According to the TSO memory model, always reads the same value for and thus fails to do . Thus, fails the simulation. Therefore, we essentially “fix methods to processes” without adding specific commands for checking process id.

4.4 Undecidability of Four Liveness Properties

The following theorem states that lock-freedom, wait-freedom, deadlock-freedom and starvation-freedom are all undecidable on TSO for a bounded number of processes. Perhaps surprisingly, we prove this theorem with the same library .

Theorem 4.1

The problems of checking lock-freedom, wait-freedom, deadlock-freedom and starvation-freedom of a given library for a bounded number of processes are undecidable on TSO.

Proof

(Sketch) For each infinite execution of , assume that it simulates an execution of , or it intends to do so. There are three possible cases for shown as follows:

  • Case : The simulation fails because some readOne does not read the intended value.

  • Case : The simulation procedure succeeds, and infinitely loops in the guess phase.

  • Case : The simulation procedure succeeds, and infinitely loops in the check phase and visits infinitely many times.

In case , since failSimu is set to true, each method returns immediately. Therefore, satisfies wait-freedom and thus, satisfies lock-freedom. can be either fair or unfair. In case , since each method returns after finite number of steps in the guess phase, satisfies wait-freedom and thus, satisfies lock-freedom. In case , since and do not return in the check phase, violates lock-freedom and thus, violates wait-freedom. Since and coordinate when simulating each transition of , in case and , must be fair.

Therefore, we reduce the problem of checking whether has an execution that visits infinitely often into the problem of checking whether has an infinite execution of case (which is fair and violates both wait-freedom and lock-freedom). By Lemma 1, we can see that the problems of checking lock-freedom, wait-freedom, deadlock-freedom and starvation-freedom of a given library for bounded number of processes are undecidable.

We remark here that [10] considers imposing liveness condition on store buffers, and requires buffered items to be eventually flushed. Our undecidability results on liveness properties on TSO still hold when imposing such liveness condition on store buffers, since in case of the proof of Theorem 4.1, each item put into buffer will eventually be flushed.

5 Checking Obstruction-Freedom

5.1 The Basic TSO Concurrent Systems

Atig et al. [2] considers the following concurrent systems on TSO: Each process runs a finite control state program that can do internal, read, write and cas actions, and different processes communicate via shared memory. We use basic TSO concurrent systems to denote such concurrent systems.

Formally, let be the set containing the (internal) action, the read actions, the write actions and the cas actions over memory locations with data domain and of process . A basic TSO concurrent system is a tuple , where each is a tuple , such that is a finite control state set and is the transition relation. They define an operational semantics similar to the one presented in Section 2. Each configuration is also a tuple , where stores control state of each process, is a memory valuation and stores buffer content of each process. We refer the reader to [2] for a detailed description of the operational semantics on TSO which is unsurprising, and hence omitted here.

Given a basic TSO concurrent system , two functions and that store control states of each process and two memory valuations and , the state reachability problem requires to determine whether there is a path from to in the operational semantics, where initializes each process with an empty buffer. Atig et al. [2] prove that the state reachability problem is decidable.

5.2 Verification of Obstruction-Freedom

The definition of obstruction-freedom requires checking infinite executions, while the state reachability problem considers finite executions reaching specific configurations. To bridge this gap, we propose a notion called blocking pairs, which is defined on concurrent systems on the SC memory model and captures potential obstruction-freedom violations. Let be the operational semantics of a concurrent system that runs on the SC memory model and contains processes. The configurations of coincide with the configurations of that preserve the buffer empty for each process. When performing a write action does not put the item into the buffer, but directly updates the memory instead. does not have flush actions, while other actions are unchanged from . Since we use finite program positions, finite memory locations, a finite data domain, finite method names and a finite number of processes, and since we essentially do not use buffers, we observe that is a finite state LTS.

Let us now propose the notion of blocking pairs. Given a state (recall that is the set of program positions of library, and are the states of the most general client) and a memory valuation , is a blocking pair, if in there exists a configuration , such that the state of process 1 of is (), and there exists an infinite execution from and such execution does not have a return action. This property can be expressed by the CTL formula , where is the usual modality of CTL, is a predicate that checks if the transition label is a return action, and returns true for any transition label. The following lemma reduces checking obstruction-freedom into the state reachability problem.

Lemma 2

Given a library , there exists an infinite execution of that violates obstruction-freedom on TSO, if and only if there exists an finite execution of and a process , such that leads to a configuration , where is a blocking pair.

Proof

(Sketch) To prove the if direction, consider the infinite executions which first act as , and then always run process and disallowing other processes to do actions. The behaviors after of these executions behave as the executions of from the configuration , where is a function that maps process to . According to the definition of blocking pairs, there exists one such execution that violates obstruction-freedom.

The only if direction is proved as follows: There exists , and process , such that , and contains only actions of process . Given process , let be the last write action of process in that has not been flushed. Let be obtained from by removing the last non-flush action of process after for some process . can not influence other process since it can not influence memory. Since the only possible actions of process after is flush, the subsequent actions of process is not influenced. Therefore, is an execution of . By repeatedly apply above approach we obtain from , such that violates obstruction-freedom, and for each process , all write of process has been flushed in . Since process runs as on SC in and read actions first try to read from buffer, we can see that