ConceptioArchivearXiv CS
arXiv CSopen access

Generalized Compare-and-Swap and Space-Efficient Universal Constructions for the Infinite-Arrival Model

2026 · arxiv_cs
arXiv CS · Papers · License: Open Access · 2026
Open Source ↗Direct PDF ↓
clouddistributed-computingparallel-computing
distributed computing, parallel computing, cloud

Generalized Compare-and-Swap and Space-Efficient Universal Constructions for the Infinite-Arrival Model

arXiv:2605.19237v1 [cs.DC] 19 May 2026

Vassos Hadzilacos

Myles Thiessen

Sam Toueg

Abstract We introduce GCAS, a natural generalization of the well-known compare-and-swap (CAS) object. Intuitively, GCAS just replaces the fixed equality test of CAS with a parametrized comparator chosen from {<, =, >}. To showcase the utility of GCAS, we present two space-efficient wait-free universal constructions for systems where the number of participating processes is unknown and may be infinite (the infinite-arrival model). The first has space-complexity linear in the number of processes that have participated so far, while the second has space-complexity linear in the point contention but assumes bounded concurrency. To the best of our knowledge, these are the first wait-free universal constructions that achieve this space complexity in the infinite-arrival model. To achieve space complexity linear in the point contention, our second universal construction uses a novel memory recycling scheme that works in the infinite-arrival model with bounded concurrency. The ideas behind this recycling scheme could be of more general use.

GCAS(C, val1 , val2 ) current := O if current C val1 then O := val2 return True return False

CAS(val1 , val2 ) current := O if current = val1 then O := val2 return True return False

Figure 1: CAS and GCAS operations.

1

Introduction

We propose a natural generalization of compare-and-swap (CAS), a fundamental object in shared memory systems, and show how it enables space-efficient, wait-free universal constructions in systems where the number of participating processes is unknown and may be infinite (this is the infinite-arrival model introduced by Merrit and Taubenfeld [18]). This model encourages the design of adaptive algorithms whose performance depends on the number of processes that actually participate rather than the maximum number that could participate. We now describe our results. A CAS object O supports a CAS(val1 , val2 ) operation which compares the current value of O to val1 and, if equal, replaces it with val2 ; see Figure 1 on the left. The object also supports standard read and write operations. We introduce generalized compare-and-swap (GCAS ), a simple generalization of CAS that replaces the fixed equality test of CAS with a comparator C ∈ {<, =, >} supplied as a parameter. A GCAS object O supports a GCAS(C, val1 , val2 ) operation which compares the current value v of O to val1 using C and, if v C val1 , replaces it with val2 ; see Figure 1 on the right. Like CAS objects, GCAS objects also support standard read and write operations. It is worth noting that GCAS should be implementable in hardware with minimal overhead compared to CAS (because testing for inequality is not much harder than testing for equality).1 To showcase the utility of GCAS, we present two space-efficient wait-free universal constructions for the infinite-arrival model. The space complexity of our first universal construction at any time t is linear in the number of processes that have participated by time t. To the best of our knowledge, this is the first universal construction to achieve this space complexity in the infinite-arrival model. A drawback of our first construction is that once a process reserves memory, that memory remains allocated forever, even if the process later leaves the system. Ideally, the space complexity at time t would be linear in the number of operations that are concurrent at time t, i.e., the point contention at time t. Our second universal construction achieves this space complexity, but under the assumption of an unknown upper bound on the maximum point contention (this is the infinitearrival model with bounded concurrency [2, 18]). To the best of our knowledge, this is the first universal construction to attain this space complexity in this model. We achieve this space complexity via a novel memory recycling scheme. Common approaches to memory recycling include reference counting (e.g., [3, 9, 14, 21, 22, 24]) and hazard pointers or related techniques (e.g., [13, 19, 20]), but, to the best of our knowledge, none of the existing schemes can be used to achieve our goals: some are non-blocking but not wait-free (e.g., [9, 14, 21, 22, 24]), others do not work in the infinite-arrival model (e.g., [3, 7, 13, 19, 20]). Our memory recycling 1 In this paper we restrict the comparator C of GCAS to be an equality or inequality test. We do so for two reasons: (a) these tests suffice for our universal constructions, and (b) this restriction minimizes the potential hardware overhead in implementing GCAS relative to CAS. More generally, C could be any other binary comparator such as ≤ or ≥, or even any function that takes two values and returns True or False.

1

scheme uses reference counters, with a key twist: each reference counter is decomposed into two counters, namely an acquisitions and a revocations counter, each stored at different locations; these are coalesced back into a single reference counter when its value is needed for recycling. Our universal constructions leverage GCAS to achieve wait-freedom with a simple helping mechanism that prioritizes operations based on their timestamps. Roughly speaking, to execute an operation o, a process p obtains a timestamp t, and then it competes with other processes to have o selected as the next operation to execute. To do so, p tries to “announce” o by applying a GCAS(>, (t, o), (t, o)) operation on a GCAS “announcement” object A: if the timestamp t of o is smaller than the timestamp t′ of the operation o′ currently in A, this GCAS operation will replace (t′ , o′ ) with (t, o) in A (because o has higher priority).2 Eventually, the operation with the smallest timestamp will “stick” in A and will be executed. Once this operation is executed, however, it must be removed from A even if it has a higher priority than any current and future operations. So, if p notices that the timestamped operation (t′ , o′ ) that is currently in A has been executed, p tries to replace it with its own operation (t, o) by applying a GCAS(=, (t′ , o′ ), (t, o)) operation on A. In summary, this paper makes the following four contributions: • A natural generalization of the well-known compare-and-swap (CAS) object that replaces the fixed equality test with a parametrized comparator chosen from {<, =, >}. • The first wait-free universal construction for the infinite-arrival model whose space complexity at time t is linear in the number of processes that have participated by time t. • The first wait-free universal construction for the infinite-arrival model with bounded concurrency whose space complexity at time t is linear in the point contention at time t. • A novel memory recycling scheme for the infinite-arrival model with bounded concurrency. The ideas behind this recycling scheme could be of more general use. It is worthwhile noting that our first universal construction guarantees more than wait-freedom: the step complexity of each operation is linear in the point contention. Roadmap. In Section 2 we sketch our model. In Section 3 we present a simple universal construction for the infinite-arrival model. In Section 4 we describe our more space-efficient universal construction for the infinite-arrival model with bounded concurrency. In Section 5 we discuss related work. We conclude the paper with some remarks and open problems in Section 6.

2

Model Sketch

We consider shared-memory systems where asynchronous processes may fail by crashing. In contrast to most work on shared-memory systems, which assumes a system with n processes (the n-arrival model), our system may have an infinite number of processes (the infinite-arrival model).

2.1

Objects, Implementations, and Runs

Each object has a type that specifies how the object behaves when it is accessed sequentially. We assume that the type T of object O is given in the form of a (possibly nondeterministic) statetransition function applyT : if s is a state of O and o is an operation that can be applied to O, applyT (o, s) returns a pair of the form (s′ , r), where s′ is a possible new state of O and r is the corresponding response returned by o when o is applied to O in state s. An implementation of a target object O from a set of base objects is a collection of procedures that specify how any process in the system can perform any operation of O by applying operations to the base objects. We only consider implementations that are linearizable [15] and wait-free [12]. A universal construction from a set of base objects is an algorithm that takes the state-transition 2

Throughout this paper we compare tuples in lexicographic order. In practice, this comparison can be achieved by reserving a field for each component of the tuple, concatenating these fields, and comparing the resulting bit strings.

2

function applyT of an arbitrary type T as input, and outputs an implementation of an object of type T from these base objects. A run of an implementation of an object O is a sequence of steps, where each step is an invocation of an operation on O, an atomic operation on a base object, or a response from an operation on O. Each step in a run R has an associated “time” which is the sequence number of that step within R, i.e., the time of the t-th step in R is t. Furthermore, we say that a process p has participated at time t in a run R if p has taken a step in R before or at time t.

2.2

Concurrency

The point contention at time t in a run R is the number of operations that are pending at time t. More precisely: Definition 1 (Point Contention). The point contention at time t in a run R is the number of operations that, by time t, have been invoked but have not responded. Definition 2 (Bounded Concurrency). A system has bounded concurrency if for every run R of the system there is a bound bR ∈ N such that the point contention at every time t in R is at most bR . We stress that in a system with bounded concurrency, processes do not know the bound on the point contention (so they cannot use it); this is because the bound bR may be different in each run R. Recall that our first universal construction works in the infinite-arrival model. This model does not assume any bound on concurrency, i.e., there may be runs where the concurrency grows without bound (this is called the infinite-arrival model with unbounded concurrency in [2, 18]). Our second universal construction (which is more space efficient than our first) works in the infinite-arrival model with bounded concurrency.

2.3

Memory Manager

To support space efficiency, shared memory systems are often augmented with a memory manager that dynamically allocates and frees cells as instructed by processes. For our purposes, a “cell” consists of a constant number of objects; i.e., it is a structure. The memory manager maintains the set of currently unallocated cells. When a process p needs a new set of base objects, it asks the memory manager to allocate a new cell comprised of these objects. The memory manager picks a cell C that is not currently allocated, and returns a pointer to C to p. When a process determines that a cell C is no longer needed by any process, it asks the memory manager to free it for future reuse; the cell is no longer allocated. We say that a base object is allocated by the memory manager if it resides in a cell that is currently allocated by the memory manager. We stress that if a process performs an operation on an object in a cell C that has been freed and not yet reallocated, the operation may return an incorrect value or may not return at all. This is because after the memory manager regains ownership of C it may use C arbitrarily—for example, it may assign C to another application that accesses it in ways outside the control of our implementation. In particular, this application could modify the contents of C or change its formatting. In systems with a memory manager, the base objects used by an implementation fall into two categories: statically allocated objects, which exist and are known to all processes at the start of a run, and dynamically allocated objects, which are currently allocated by the memory manager. So we define the space complexity of an implementation as follows: Definition 3 (Space Complexity). The space complexity of an implementation at time t of a run is the number of statically allocated base objects plus the number of base objects dynamically allocated by the memory manager at time t in that run.

3

Statically allocated shared objects: C : A F&I object, initially 1. A : A GCAS object with three fields: time : the timestamp t of the operation o in the field below, initially 0. operation : the operation o to execute, initially Noop. pointer : a pointer ptr to the cell of the process that invoked o, initially a pointer ptrNoop to a dummy cell. S : A CAS object with four fields: time : the timestamp t of the operation o that resulted in the current object state s, initially 0. state : the current object state s, initially the initial state of type T . response : the response r of the operation o that resulted in the current object state s, initially ⊥. pointer : a pointer ptr to the cell of the process that invoked o, initially ptrNoop . Dynamically allocated shared objects: Each cell contains a single CAS object with two fields: time : the timestamp t of the last operation o invoked by the owner of this cell. response : the response r of the operation o or Null. Local persistent variable per process: ptr : a pointer to the cell of this process, initially Null. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

procedure DoOp(o) // to perform an operation o on the target object if ptr = Null then ptr := AllocateCell() // get a pointer to a cell from the memory manager t := F&I(C) // get a timestamp t for o (∗ptr) := (t, Null) // initialize o’s response to Null while (∗ptr) = (t, Null) do // while o is not done (i.e., its response is Null) (t∗ , s∗ , r∗ , ptr∗ ) := S // read the state of the target object CAS((∗ptr∗ ), (t∗ , Null), (t∗ , r∗ )) // copy the last operation’s response into its cell GCAS(>, A, (t, o, ptr), (t, o, ptr)) // if o has higher priority, announce it (t′ , o′ , ptr′ ) := A // read the currently announced operation o′ to help (t̂, r̂) := (∗ptr′ ) // read the response of o′ from its cell ′ ′ if (t̂, r̂) = (t , Null) then // if o is not done (i.e., its response is Null) (s′ , r′ ) := applyT (o′ , s∗ ) // apply o′ to the target object state CAS(S, (t∗ , s∗ , r∗ , ptr∗ ), (t′ , s′ , r′ , ptr′ )) // try to linearize o′ by changing S ′ else // if o is done (i.e., its response is not Null) GCAS(=, A, (t′ , o′ , ptr′ ), (t, o, ptr)) // and o′ is still in A, try to announce o return (∗ptr).response // return the response of o (found in o’s cell)

Algorithm 1: A simple & space-efficient wait-free universal construction.

3

A Simple & Space-Efficient Universal Construction

We now describe a simple wait-free universal construction for the infinite-arrival model. Its space complexity at any time is linear in the number of processes that have participated by that time. This universal construction, shown in Algorithm 1, uses GCAS, CAS, and fetch-and-increment (F&I) objects to implement an object O of an arbitrary type T .3 In this construction, we leverage GCAS to implement the priority-based helping scheme outlined in Section 1. When a process p invokes its first operation, it obtains from the memory manager a pointer to a cell consisting of a single CAS object, and assigns that pointer to a local variable ptr (line 2). Thereafter, across all operations invoked by p, ptr points to this cell. This cell is used to store the response of each operation issued by p; since it is dedicated to p, we will call it p’s cell. In general it stores a pair (t, r), where t is the timestamp of an operation o on O that p has invoked and r will eventually contain the response of o (initially it is Null, indicating that o is not done yet). 3

Since GCAS is a generalization of CAS, we can replace all CAS objects with GCAS objects. But, to highlight where the additional functionality of GCAS is used, we opted to use CAS rather than GCAS whenever CAS is sufficient.

4

In addition to the cells that store the response of operations, this universal construction uses three statically allocated base objects: • C (for “clock”): A F&I object used to timestamp operations. • A (for “announce”): A GCAS object that processes use to announce the operations they wish to apply to O. It contains information about the oldest (highest priority) operation announced that has not yet been applied, namely a tuple (t, o, ptr), where o is an operation, t is its timestamp, and ptr is a pointer to the cell of the process that invoked o. • S (for “state”): A CAS object that stores information about the state of the target object O. More precisely, it stores a tuple (t, s, r, ptr), where t is the timestamp of the last operation o applied to O, s is the state of O after the application of o, r is the response of o, and ptr is a pointer to the cell of the process that invoked o. To perform an operation o, a process p first gets a timestamp t for o from the clock object C (line 3). Then, p sets its response cell, which is pointed to by ptr, to (t, Null) (line 4). Operation o may be completed by p itself or by a “helper”. While o is not done, i.e., while the response cell of p still contains (t, Null) (line 5): 1. p reads the tuple (t∗ , s∗ , r∗ , ptr∗ ) currently in S (line 6). 2. p ensures that the response of the last operation applied to O is copied into the response cell of the process that invoked it, i.e., p ensures that (t∗ , r∗ ) is written in the cell pointed to by ptr∗ , by applying a CAS operation on it (line 7). 3. p then tries to announce its own operation o by applying a GCAS(>, . . .) operation on A to write (t, o, ptr) in it. This GCAS will succeed if t is less than the timestamp of the operation presently in A, i.e., if o has higher priority (line 8). 4. Irrespective of whether this GCAS operation on A was successful (i.e., whether p succeeded in writing (t, o, ptr) in A), p now helps to execute whatever operation is currently in A. To do so, p first reads from A the tuple (t′ , o′ , ptr′ ) describing the operation to help (line 9), and then it reads the response of o′ (in the cell pointed to by ptr′ ) to see whether o′ is already done (line 10). (a) If o′ is not done, p applies o′ to the state s∗ of the target object O that it read in step (1), to get the new state s′ of O and the response r′ of o′ . It then attempts to linearize o′ by trying to replace the tuple it read from S in step (1) with (t′ , s′ , r′ , ptr′ ) (lines 11-13). (b) If o′ is done, p tries to remove o′ from A by replacing it with its own operation o. To do so, p applies a GCAS(=, . . .) operation on A to replace (t′ , o′ , ptr′ ) with (t, o, ptr) (line 15). When p finds that o is done, it returns the response of o, which is stored in the response cell of p (line 16). Theorem 4. Algorithm 1 is a wait-free universal construction for the infinite-arrival model. Its space complexity at time t is linear in the number of processes that have participated by time t. In fact, this universal construction guarantees more than wait-freedom: we prove that the step complexity of each operation is linear in the point contention (at the time the invoking process gets a timestamp for this operation). More precisely: Theorem 5. Suppose a process p invokes an operation o and executes line 3 within o. Let c be the point contention at this time. Then, the number of steps that p takes within o is at most linear in c.

4

A More Space-Efficient Universal Construction

The space complexity of our first universal construction at time t is linear in the number of processes that have participated by t. We now describe a universal construction whose space complexity at t is linear only in the point contention at t (Definition 1). It uses the same types of

5

base objects as our first universal construction, except it also uses fetch-and-add (F&A) in addition to fetch-and-increment (F&I). Both constructions work in the infinite-arrival model, but the second one requires the additional assumption of bounded concurrency (Definition 2). We first outline the main challenges in achieving this space complexity and how our universal construction solves them, and then present its pseudocode.

4.1

Some Challenges and Their Solutions

In our first universal construction, the first time a process participates, it gets a new response cell from the memory manager and never frees it. In other words, this construction never recycles these cells. To improve the space complexity, our second universal construction recycles cells, i.e., it frees previously allocated cells. Cell recycling. One difficulty with recycling is that before a process p frees a cell C, it must be sure that no process will ever try to access an object O within C until C is allocated again. This is because if this were to happen, O could misbehave: it could return a wrong value, or even not return at all. A naive way to recycle cells with our first universal construction is as follows. When a process p invokes an operation o, it allocates a new cell C to store the response of o. Then, after p finds the response of o in C (on line 16), it immediately frees C (because p no longer needs it). The problem with this approach is that another process q can now access C, even though C is unallocated. This occurs when q reads a pointer to C from the announce object A on line 9 (before C has been freed), goes to sleep, wakes up after C has been freed, and then accesses C on line 10. A common approach to enable the freeing of no-longer-needed cells is by using reference counters (e.g., [3, 9, 14, 21, 22, 24]). Intuitively, a reference counter for a cell C stores the number of processes that currently have the right to access C. A process acquires the right to access C by incrementing the reference counter for C; and when it no longer needs to access C, the process decrements the reference counter for C. A process that finds a cell’s reference counter to be 0 can free that cell. But where do we put the reference counter for a cell C? If we put it in C itself, then to acquire the right to access C (by incrementing its reference counter) a process would have to access C (where its reference counter is stored) — a chicken-and-egg situation. To solve this, we could try to put C’s reference counter outside of C. But doing this raises another problem: when we recycle C, we now must also recycle its reference counter; so we need a mechanism to recycle the reference counters themselves — a different kind of chicken-and-egg situation! Our second universal construction solves this problem by (a) threading the cells of the operations that are pending in a linked list, and (b) splitting the reference counter of each cell into two parts, each in a different location, as we now explain. Reference counter splitting. At any time t, the reference counter for a response cell C in the list is equal to the number of processes that have acquired the right to access C minus the number of processes that have relinquished that right by time t. We store the reference counter for C implicitly by maintaining two separate counters: the acquisitions counter for C, stored in the predecessor of C in the list; and the revocations counter for C, stored in C itself. Note that the acquisitions counter for C and the pointer to C, both of which reside in the predecessor of C, must be updated together atomically. So we store both of them in a CAS object called next (in the predecessor of C). The revocations counter for C is stored in a F&A object, called revocations, in C itself. List traversal. To access any cell C in the list, a process p must first acquire the right to do so, i.e., it must increment the acquisitions counter for C. Since this counter is located in the predecessor of C, p must traverse the list to find (and acquire the right to access) the predecessor of C. This traversal proceeds as follows. Having obtained the right to access a cell Ci in the list, p

6

first obtains the right to access the next cell Ci+1 by incrementing the acquisitions counter for Ci+1 , which resides in Ci (p does so by performing a successful CAS operation on the next object of Ci because it contains the acquisitions counter for Ci+1 ). After p has acquired the right to access Ci+1 , it no longer needs access to Ci , so it relinquishes its right to access Ci . It does so by incrementing Ci ’s revocations counter, by performing a F&A operation on the revocations object of Ci . We note that the starting point of this traversal, i.e., the head of the list H = C0 , is a statically allocated cell that is never freed (so all processes always have the right to access H). Cell removal. When an operation completes, its corresponding response cell is removed from the list. To remove a cell C from the list, a process p must move the acquisitions counter for the successor C + of C, stored in C, to the predecessor C − of C. But the removal of C and the move of the acquisitions counter for C + (from C to C − ) must be done atomically to avoid the following bad scenario. Before p removes C from the list, it reads the acquisitions counter for C + from C, say its value is a. Then, another process acquires the right to access C + by incrementing the acquisitions counter for C + stored in C; at this time, the number of acquisitions for C + is a + 1. Now p removes C from the list and writes a into C − . But the acquisitions counter for C + , now stored in C − , is incorrect: its value is a, but the true number of acquisitions for C + is a + 1! To solve this problem, p removes C from the list as follows: (1) it first freezes the acquisitions counter for C + , (2) it then reads the acquisitions counter for C + , say its value is a, and (3) it finally removes C from the list and writes a into C − ; this last step is done atomically by doing a CAS operation on the next object of C − . Process p does step (1) by setting a sealed flag in the next object of C (which contains the acquisitions counter for C + ). Once this flag is set, the content of next cannot change (the content of the next object of C is now sealed ). Cell freeing. When a cell C is removed from the list it cannot necessarily be freed yet. This is because some process may still have the right to access C. To determine when C can be freed, we need to determine whether the reference counter for C is zero. This is done as follows. When a process p removes C from the list, it computes the reference counter for C by: (1) reading the value a of the acquisitions counter for C, which is stored in the predecessor of C, and (2) subtracting a from the revocations counter for C, which is stored in C, using a F&A operation on the revocations object of C. Note that this subtraction changes the semantics of the revocations object of C: it used to be the revocations counter for C, it is now the negation of the reference counter for C. This trick allows processes to relinquish their right to access C in a uniform way by incrementing the revocations object of C (irrespective of its current semantics). We prove that the process that causes the reference counter for C to become zero is the last process that had the right to access C, so it can safely free C. Wait-freedom. To achieve wait-freedom, we use a modified version of the priority-based helping mechanism of Algorithm 1. But this is no longer sufficient here, because processes that are trying to use the list (e.g., traverse the list, add a cell, remove a cell, or change the content of a cell) may be prevented from doing so by other processes that are concurrently using the list. So we also need a mechanism to ensure that accessing the list is wait-free. We now briefly elaborate on these two mechanisms. To apply an operation o on the target object O, a process p first obtains from the memory manager a cell C to store the response of o. Then p performs the following three “low-level” operations, possibly with the help of other processes, in that order: 1. AddCell: append C to the end of the list; 2. Apply&CopyResponse: apply o to O and then copy the response to C; and 3. RemoveCell: remove C from the list. A process performs these three operations using a modified version of the priority-based helping mechanism of Algorithm 1. As before, process p first obtains a timestamp for the operation that 7

it wants to do from a F&I object C, it tries to announce it by applying a GCAS(>, . . .) operation on the announce object A, and then tries to perform the operation oA stored in A. Recall that in Algorithm 1, p tries to perform oA as follows: (a) it first reads the state s of O from the state object S, (b) it then applies oA to s (using the state-transition function applyT of the type T of O) to get the next state s′ of O and the corresponding response r′ , and (c) it finally tries to write (s′ , r′ ) into the state object S by doing a CAS operation on that object. Note that, if this CAS is successful, step (3) does two things simultaneously: it linearizes oA and changes the state of O accordingly. In contrast, our second universal construction separates these two things, as follows. When p tries to perform the operation oA stored in A, it simply tries to write oA into a CAS object L. We ensure that once an operation is written into L, it is not removed until it has taken effect. Thus, operations are linearized in the order they are written into L (which is why this object is called L). We now explain how processes perform the operations written into L. Recall that in Algorithm 1, before doing its own operation, a process p copies the response of the last operation that was linearized (into the appropriate cell). In contrast, in our second universal construction, before doing its own operation, a process p performs the last operation that was linearized. To do so, p reads the operation oL that is currently in L, and then: 1. If oL is an AddCell operation to add a cell C, p traverses the list to append C to the end of the list. 2. If oL is an Apply&CopyResponse operation to apply an operation o to the target object O, p first applies o to O by performing steps (a), (b) and (c) above to the state object S. Then p traverses the list to find the appropriate cell and copies the response of o into it. 3. If oL is a RemoveCell operation to remove a cell C, p traverses the list to find and remove C from the list. The priority-based helping mechanism described above, however, is not sufficient for performing the operation oL that is currently in L in a wait-free manner: as we see above, to perform oL , a process p must traverse the list of cells, but this traversal could be impeded by concurrent processes that are also traversing the list. To see this, recall that to reach the successor C + of a cell C in the list, p must acquire the right to access C + (by incrementing the acquisitions counter for C + , which resides in C). But to do so p must “win” a CAS operation on the next object of C which contains the acquisitions counter for C + . This is problematic because p may keep losing its CAS operations on the next object of C, so p may get stuck at cell C while trying to traverse the list. To avoid this, in our universal construction, p periodically checks whether the operation oL that it is trying to perform is still in L (recall that p is traversing the list to perform oL ). If p sees that oL is no longer in L, it can be certain that oL has already taken effect (because oL cannot be removed from L until it has taken effect), and so p bails out. This bail-out mechanism to achieve wait-freedom, however, works only under the assumption of bounded concurrency. This is because, with unbounded concurrency, a process attempting to traverse the list may repeatedly lose its CAS operations on a next object because there may be an unbounded stream of newly arriving processes, each of which wins a CAS operation on that next object and then immediately crashes before changing L. Different incarnations of a cell. Recycling cells may also raise the following problem. A process p reads a next object that contains a pointer to a cell C, but goes to sleep before acquiring the right to access C (i.e., before incrementing the acquisitions counter for C, which also resides in this next object). Then C gets recycled and reallocated; this is a new “incarnation” of C, and its content has changed. Finally, p wakes up and acquires the right to access (the new incarnation of) C, thinking that it has acquired the right to access the older incarnation of C — this is clearly problematic. A simple solution to this problem is for processes to tag each pointer returned by the 8

memory manager with a unique identifier (which they can obtain by performing a F&I operation): this creates “unique pointers” that are used in place of “raw” pointers everywhere (except for when a process needs a “raw” pointer to access a cell). As it turns out, creating these unique pointers is not necessary: we show that the above scenario (and other problematic ones involving different incarnations of a cell) cannot occur in our universal construction. Space complexity. We show that at any time t, our universal construction uses a number of cells that is linear in the point contention ct at time t. Intuitively, this follows from the following properties: • At any time, a process holds the right to access at most a small constant number α of cells. This is ensured by relinquishing access to each cell as soon as it is no longer needed (for example, during list traversal, a process successively acquires and relinquishes cells as it traverses through the list). • When a process relinquishes the right to access a cell, it decrements the cell’s (implicit or explicit) reference counter. If the resulting value indicates that no process currently holds the right to access the cell, it frees the cell and returns it to the memory manager. • Before completing an operation on the target object, a process relinquishes the right to access every cell it acquired the right to access during that operation. The above properties ensure that the universal construction uses about α · ct cells (so about 3α · ct base objects) at any time t.

4.2

Pseudocode Description

The pseudocode of this universal construction is given in Algorithm 2. This algorithm uses the following statically allocated base objects: H (for “head”), C (for “clock”), A (for “announce”), L (for “linearize”), and S (for “state”). This algorithm also uses a list of dynamically allocated cells (H is the head of this list). Each cell consists of three base objects: response, revocations, and next. The purpose of all the base objects was described in the previous section, and their type and content is given at the top of Algorithm 2. Note that next is a CAS object with four fields: view, sealed, acquisitions, and ptr. We already described the purpose of sealed, acquisitions, and ptr in the previous section. The view field is a monotonically increasing counter that prevents ABA problems.4 • DoHighLevelOp(hlo) is invoked by any process p that wants to perform an operation hlo on the target object (to differentiate hlo from the three low-level operations that our universal construction does to perform hlo, we call hlo a “high-level” operation). In line 2 p gets a pointer ptr to a new cell from the memory manager. Process p then performs the operation hlo on the target object by ensuring the following three low-level operations are performed in order: (1) add the cell pointed to by ptr to the list of cells, (2) apply hlo to the target object and copy its response into the cell pointed to by ptr, and (3) remove this cell from the list. This is done by invoking the DoLowLevelOp procedure with a first parameter of AddCell, ⟨Apply&CopyResponse, hlo⟩, and RemoveCell on lines 3, 4, and 6, respectively. After p has finished these procedures, hlo is done. Hence, p no longer needs the cell pointed to by ptr (which was used to store the response of hlo), so it relinquishes its right to access it (line 7). Recall that the cell pointed to by ptr is not necessarily recyclable yet because other processes may still have the right to access it. Finally, p returns the response of hlo (line 8) that it read from the cell pointed to by ptr on line 5. • DoLowLevelOp(llo, ptr) performs the low-level operation llo and ensures the response of this operation is stored in the cell pointed to by ptr. The high-level flow of this procedure is similar to Algorithm 1. Process p first gets a unique timestamp t (line 10) and forms the pair (t, llo); we 4

This field can be avoided by making next an LL/SC object rather than a CAS object.

9

Statically allocated shared objects: H : A cell that serves as the head of a list of cells.

Dynamically allocated shared objects: The response of each high-level operation is stored in a cell; a cell consists of the following objects

C : A F&I object, initially 1. A : A GCAS object with two fields: ullo : a unique low-level operation to linearize, initially (0, Noop). ptr : a pointer to a cell in which to store the response of ullo, initially Null. L : A CAS object with two fields: ullo : the last unique low-level operation that was linearized, initially (0, Noop). ptr : a pointer to a cell in which to store the response of ullo, initially Null.

next : A CAS object with four fields: view : the number of times next has changed in this incarnation of this cell, initially 0. sealed : True if this cell is in the process of being removed otherwise False, initially False. acquisitions : the number of times the cell pointed to by ptr was acquired, initially 0. ptr : a pointer to a cell, initially Null.

S : A CAS object with three fields: ullo : the unique Apply&CopyResponse operation that resulted in the current object state, initially (0, Noop). state : the current object state, initially the initial state of type T . resp : the response of ullo, initially ⊥. 1 2 3 4 5 6 7 8

procedure DoHighLevelOp(hlo) ptr := AllocateCell() DoLowLevelOp(AddCell, ptr) DoLowLevelOp(⟨Apply&CopyResponse, hlo⟩, ptr) (−, resp) := (∗ptr).response DoLowLevelOp(RemoveCell, ptr) Relinquish(ptr) return resp

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

procedure DoLowLevelOp(llo, ptr) t := F&I(C) ullo := (t, llo) (∗ptr).response := (ullo, Null) while (∗ptr).response = (ullo, Null) do (ulloL , ptrL ) := L if ulloL = (∗, AddCell) then DoAddCell(ulloL , ptrL ) else if ulloL = (∗, RemoveCell) then DoRemoveCell(ulloL , ptrL ) else if ulloL = (∗, ⟨Apply&CopyResponse, ∗⟩) then DoApply&CopyResponse(ulloL , ptrL ) GCAS(>, A, (ullo, ptr), (ullo, ptr)) (ulloA , ptrA ) := A status := IsDone(ulloL , ulloA , ptrA ) if status = NotDone then CAS(L, (ulloL , ptrL ), (ulloA , ptrA )) else if status = Done then GCAS(=, A, (ulloA , ptrA ), (ullo, ptr))

28 29 30 31 32 33 34 35 36

procedure DoAddCell(ulloL , ptrL ) curr ptr := &H while curr ptr ̸= ptrL do (status, next ptr) := AcquireNext(ulloL , curr ptr) if status = L-Changed then break else if status = NotFound then (view, −, −, −) := (∗curr ptr).next if L.ullo ̸= ulloL then break CAS((∗curr ptr).next, (view, False, 0, Null), (view + 1, False, 1, ptrL )) break else if status = Found then Relinquish(curr ptr) curr ptr := next ptr Relinquish(curr ptr) SetResponse(ulloL , ptrL , Done)

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

procedure DoRemoveCell(ulloL , ptrL ) SetResponse(ulloL , ptrL , Done) (prev ptr, curr ptr) := (Null, &H) while curr ptr ̸= ptrL do (status, next ptr) := AcquireNext(ulloL , curr ptr) if status = L-Changed ∨ status = NotFound then goto line 63 else if status = Found then Relinquish(prev ptr) (prev ptr, curr ptr) := (curr ptr, next ptr) while (∗ptrL ).next.sealed = False do (view, sealed, a, next ptr) := (∗ptr L ).next CAS((∗ptr L ).next, (view, sealed, a, next ptr), (view + 1, True, a, next ptr)) (−, −, a, next ptr) := (∗ptr L ).next repeat (view′ , −, a′ , next ptr ′ ) := (∗prev ptr).next if L.ullo ̸= ulloL ∨ next ptr ′ = next ptr then goto line 63 until CAS((∗prev ptr).next, (view′ , False, a′ , ptrL ), ′ (view + 1, False, a, next ptr)) F&A((∗ptr L ).revocations, −a′ ) Relinquish(prev ptr) Relinquish(curr ptr)

type cell: response : A CAS object with two fields: ullo : the last unique low-level operation invoked by the owner of this cell, initially (0, Noop). resp : the response of applying this low-level operation or Null, initially Null. revocations : A F&A object that stores the number of times this cell was revoked, initially 0.

65 66 67 68 69 70 71 72 73

procedure DoApply&CopyResponse(ulloL , ptrL ) (ulloS , sS , r S ) := S if L.ullo ̸= ulloL then return if ulloS ̸= ulloL then (−, ⟨Apply&CopyResponse, hloL ⟩) := ulloL (s, r) := apply T (hloL , sS ) CAS(S, (ulloS , sS , r S ), (ulloL , s, r)) r S := S.resp SetResponse(ulloL , ptrL , r S )

74 75 76 77 78

procedure SetResponse(ulloL , ptrL , response) status := Acquire(ulloL , ptrL ) if status = Found then CAS((∗ptrL ).response, (ulloL , Null), (ulloL , response)) Relinquish(ptrL )

79 80 81 82 83 84 85 86 87 88 89 90 91

procedure IsDone(ulloL , ulloA , ptrA ) status := Acquire(ulloL , ptrA ) if status = L-Changed then return L-Changed response := Done if ulloA = (∗, AddCell) ∧ status = NotFound then response := NotDone else if ulloA = (∗, RemoveCell) ∧ status = Found then response := NotDone else if ulloA = (∗, ⟨Apply&CopyResponse, ∗⟩) then if (∗ptrA ).response = (ulloA , Null) then response := NotDone if status = Found then Relinquish(ptrA ) return response

92 93 94 95 96 97 98 99 100 101

procedure Acquire(ulloL , target ptr) curr ptr := &H while curr ptr ̸= target ptr do (status, next ptr) := AcquireNext(ulloL , curr ptr) Relinquish(curr ptr) if status = L-Changed ∨ status = NotFound then return status else if status = Found then curr ptr := next ptr return Found

102 103 104 105 106 107 108 109 110

procedure AcquireNext(ulloL , curr ptr) repeat (view, −, a, next ptr) := (∗curr ptr).next if L.ullo ̸= ulloL then return (L-Changed, ∗) if next ptr = Null then return (NotFound, ∗) until CAS((∗curr ptr).next, (view, False, a, next ptr), (view + 1, False, a + 1, next ptr)) return (Found, next ptr)

111 112 113 114

procedure Relinquish(curr ptr) if curr ptr = Null ∨ curr ptr = &H then return x := F&A((∗curr ptr).revocations, 1) if x + 1 = 0 then FreeCell(curr ptr)

Algorithm 2: A more space-efficient wait-free universal construction. 10

call the pair (t, llo) a unique low-level operation and denote it ullo (line 11). The timestamp t is the priority of llo. Process p then sets the response of ullo in the cell pointed to by ptr to Null (line 12), and enters the loop on line 13. p exits this loop once the response of ullo is not Null (indicating ullo has taken effect). In each iteration of this loop: (1) p reads the value (ulloL , ptrL ) currently stored in L, and then invokes the DoAddCell, DoRemoveCell, or DoApply&CopyResponse procedure, depending on the kind of operation ulloL is, to ensure ulloL takes effect and its corresponding response is written into the cell pointed to by ptrL (lines 15-20); (2) p tries to announce its own operation and pointer (ullo, ptr) by performing a GCAS(>, . . .) operation on A (line 21); (3) regardless of the outcome of this GCAS operation, p reads the low-level operation ulloA currently stored in A (line 22), and then it invokes the IsDone procedure to try to determine whether this operation has already taken effect (line 23). If IsDone returns NotDone, then ulloA has not yet taken effect and p tries to store (ulloA , ptrA ) into L by performing a CAS operation on L (line 25). If IsDone returns Done, then ulloA has taken effect, and in this case p tries to remove (ulloA , ptrA ) from A by replacing it with (ullo, ptr) by performing GCAS(=, . . .) operation on A (line 27). Finally, if IsDone returns L-Changed, then p could not determine whether ulloA has taken effect or not; in this case, p does nothing: it just proceeds to the next iteration of the loop. • DoAddCell(ulloL , ptrL ) traverses the list of cells to find the last cell in the list, appends the cell C pointed to by ptrL after it, and sets its response to Done. To traverse the list, p maintains a current pointer curr ptr that points to some cell in the list (curr ptr is initially a pointer to the head of the list &H). While curr ptr does not point to C (i.e., curr ptr ̸= ptrL ), p tries to acquire the right to access the cell after the cell pointed to by curr ptr by invoking the AcquireNext procedure (line 31). If the AcquireNext procedure returns Found (line 38), then p continues the traversal: p relinquishes its right to curr ptr (line 39), updates curr ptr to the next pointer (line 40), and continues to the next iteration of the while loop. If the AcquireNext procedure returns NotFound (line 33), curr ptr points to the last cell Clast in the list. Therefore, p did not find C in the list, and p tries to add C after Clast . To do so, p performs a CAS operation on Clast to set its next pointer to ptrL (line 36). We prove that, regardless of whether this CAS succeeds or not, C is added to the list at the time of this CAS. So, in all cases, p exits the while loop after performing this CAS. Note that the CAS that adds C to the list sets the acquisitions counter for C to be 1 to signify that the process that allocated C has the right to access C (this process will relinquish its right to access C at the end of its operation on line 7). After p exits the while loop, p first relinquishes its right to access the cell pointed to by curr ptr (line 41). Then, p invokes the SetResponse procedure to write Done into the response object of C; this informs the process that allocated C that C has been added to the list (line 42). • SetResponse(ulloL , ptrL , response) tries to set the response of ulloL in the cell C pointed to by ptrL to response. To do so, p tries to acquire the right to access C by invoking the Acquire procedure on line 75; if it is successful, then p tries to write response into the response object of C by performing a CAS operation on this object (line 77). We prove that by the time p exits this procedure, the response object of C was set to response (this is true even if p was unsuccessful in acquiring the right to access C or p failed the CAS on line 75). Note that, before exiting this procedure, if p was successful in acquiring the right to access C, then p relinquishes its right to access C on line 78. • AcquireNext(ulloL , curr ptr) assumes that the process p invoking it has the right to access the cell C pointed to by curr ptr, and it returns one of the following: (Found, next ptr), meaning p has acquired the right to access the next cell in the list (i.e., the one pointed to by next ptr); (NotFound, ∗), meaning there is no cell after the one pointed to by curr ptr in the list (so C is the last cell of the list); and (L-Changed, ∗), meaning the operation stored in L is no longer ulloL 11

(which implies that ulloL has already taken effect, so there is no needed to acquire the right to access the cell after C). To acquire the right to access the next cell C + in the list, p enters a repeat-until loop (line 103) in which it repeatedly tries to increment the acquisitions counter for C + , which is stored in C. To do so, p first reads the next object of C to learn the current number of acquisitions a of C + and the pointer next ptr to C + (line 104). Then, p performs a CAS operation on the next object of C to set the acquisitions counter for C + to a+1 (line 109). If this CAS operation succeeds, p has acquired the right to access C + . There are three ways that p can exit this repeat-until loop: (1) the CAS operation on line 109 succeeds, in which case p returns (Found, next ptr); (2) p finds that C is the last cell in the list, so C + does not exist, in which case p returns (NotFound, ∗); or (3) p finds that L no longer stores ulloL , in which case p returns (L-Changed, ∗).5 • Acquire(ulloL , target ptr) traverses the list of cells to find the cell pointed to by target ptr and acquires the right to access it. This procedure returns one of the following: Found, meaning p has acquired the right to access the cell pointed to by target ptr; NotFound, meaning the cell pointed to by target ptr is not in the list; and L-Changed, meaning the operation stored in L is no longer ulloL . To determine whether the cell pointed to by target ptr is in the list, p searches for this cell by traversing the list, starting from the head H of the list. To do so, p maintains a pointer curr ptr to the current cell C that it has reached in its traversal. Process p initializes curr ptr to &H, and then it enters the while loop on line 94 which continues until curr ptr = target ptr, i.e., until p finds the cell pointed to by target ptr; at this point p has acquired the right to access it. In each iteration of this loop, p invokes the AcquireNext procedure to try to acquire the right to access the successor C + of the cell C pointed to by curr ptr. Then, irrespective of the result, it relinquishes the right to access C. If p fails in acquiring the right to access C + , then p returns L-Changed or NotFound (depending on the reason why it failed). Otherwise, (i.e., if p succeeds in acquiring the right to C + ) p sets curr ptr to the pointer of C + . If C + is the cell pointed to by target ptr, then p will exit the loop and return Found. • IsDone(ulloL , ulloA , ptrA ) checks whether ulloA has taken effect. This procedure returns one of the following: NotDone, meaning ulloA has not taken effect; Done, meaning ulloA has taken effect; and L-Changed, meaning the operation stored in L is no longer ulloL . Observe that this procedure cannot simply check if ulloA has already taken effect by just reading the response object of the cell CA pointed to by ptrA . This is because p cannot access any cell (including CA ) before acquiring the right to access it, i.e., incrementing the acquisitions counter for CA (which is located in the predecessor of CA in the list). So, p first tries to acquire the right to access CA by executing the Acquire procedure on line 80; let status be its response. If status = L-Changed, then IsDone returns L-Changed. Otherwise, status equals NotFound or Found. At this point, p can determine whether ulloA has taken effect or not as follows: ulloA has not taken effect if and only if ulloA is an AddCell operation and status = NotFound (which means that the Acquire procedure did not find CA in the list); ulloA is a RemoveCell operation and status = Found (which means that the Acquire procedure found CA in the list); or ulloA is an Apply&CopyResponse operation, and the response in CA is still (ulloA , Null). If p determines that ulloA has not taken effect, the IsDone procedure returns NotDone, and otherwise returns Done. Before returning, however, p relinquishes its right to access CA if the Acquire procedure found CA in the list, i.e., if status = Found. • Relinquish(curr ptr) assumes that the process p invoking it has the right to access the cell C pointed to by curr ptr, and it is used by p to relinquish its rights to access C. To do so, p increments the revocations object of C by doing a fetch-and-increment operation on it. Let c be 5

This is the “bail out” mechanism described in Section 4.1. Recall that this is needed because p could be stuck trying to acquire C + because its CAS operations fail forever.

12

the value of this object immediately after this fetch-and-increment operation. As we explained in Section 4.1, when c > 0, c is the value of the revocations counter for C; otherwise, |c| is the value of the reference counter for C. We prove that if c = 0, this relinquish by p is the last relinquish for C, and so p can safely free C.6 • DoApply&CopyResponse(ulloL , ptrL ) is used by a process p to: (1) apply the high-level operation hloL stored in ulloL (where ulloL = (∗, ⟨Apply&CopyResponse, hloL ⟩)) to the target object state stored in S, and (2) copy its response into the cell C pointed to by ptrL . To do so, p first reads the content (ulloS , sS , rS ) of S (line 66). Recall that ulloS = (∗, ⟨Apply&CopyResponse, hloS ⟩) where hloS is the last high-level operation to the target object that has taken effect, sS is the current state of the target object, and rS is the response of hloS . Then, p checks if ulloL is still stored in L (line 67); if L has changed, then hloL has already been applied to the target object and the response of hloL has already been copied into C, so p exits the procedure. Otherwise, ulloL is still stored in L. In this case, we prove that hloL has been applied to the target object if and only if ulloS = ulloL . So p now checks whether ulloS ̸= ulloL (line 68), and if so p tries to apply hloL to the target object. To do so, p determines the new state s and response r by applying hloL to sS using the state-transition function applyT of the type T of the target object (line 70), and tries to write (ulloL , s, r) into S using a CAS operation (line 71). We prove that regardless of whether this CAS is successful or not, hloL has been applied to the target object. What remains to be done is to copy the response from S into C. To do so, p first reads the current response from S (line 72) (p must re-read the response from S because of non-determinism: the response that p got from applyT may be different from the response that the process that succeeded in writing the response into S received). Then p invokes the SetResponse procedure to copy this response into the cell C pointed at by ptrL . • DoRemoveCell(ulloL , ptrL ) is used by a process p to remove the cell C pointed to by ptrL from the list if p finds C in the list. Process p does this in four stages: (1) p traverses the list of cells to find C and its predecessor C − (lines 45-52); (2) if p finds C, p seals the acquisitions counter stored in C to prevent any process from acquiring the right to access the successor C + of C (lines 53-55); (3) then it removes C from the list by setting the successor of C − to C + (lines 56-61); and (4) finally p consolidates the acquisitions and revocations counter for C into the reference counter for C (line 62). To do stage (1), p traverses the list of cells by maintaining a current pointer curr ptr and a pointer to its predecessor prev ptr, which are initially &H and Null, respectively. While curr ptr does not point to C (i.e., curr ptr ̸= ptrL ), p tries to acquire the right to access the cell after the cell pointed to by curr ptr by invoking the AcquireNext procedure (line 47). If the AcquireNext procedure returns Found (line 50), then p continues the traversal: p relinquishes its right to prev ptr (line 51), updates (prev ptr, curr ptr) to curr ptr and the next pointer, respectively (line 52), and continues to the next iteration of the while loop. If the AcquireNext procedure returns L-Changed or NotFound (line 48), then p skips stages (2), (3), and (4): C has already been removed from the list. To do stage (2), while the next object of C is not sealed, p repeatedly performs a CAS operation on the next object of C to try to set its sealed flag from False to True (line 55). We prove that, even though these CAS operations can keep failing, the next object of C is eventually sealed, and so p eventually exits this loop. To do stage (3), p repeatedly performs a CAS operation on the next object of C − on line 61 to try to: (a) copy the acquisitions counter for C + (which is in C) into C − ; and (b) set the successor of C − to C + . There are two ways p can exit this loop. First, if p finds that C has already been 6

In the pseudocode, c = x + 1 because fetch-and-increment fetches the value of the object before incrementing it.

13

removed from the list (either because the successor of C − is C + or the operation ulloL to remove C from the list is no longer stored in L), then p immediately exits this loop. Second, if p performs a successful CAS operation on line 61, then p is the process that removes C from the list. To do stage (4), p must now compute the reference counter for C from the acquisitions and revocations counters for C (which are located in C − and C, respectively), and store it in C. To do so, p decrements the revocations counter for C by the value of the acquisitions counter that p previously read from C − (on line 58). Let v be the value of the revocations object of C after this decrement. Note that (a) |v| now represents the reference counter for C; and (b) v < 0 (because p still has the right to access C). At this point (just after line 62), C has been removed from the list (and its reference counter was computed). The natural thing to do now would be to set the response object of C to Done (by invoking SetResponse(ulloL , ptrL , Done) between line 62 and 63), but this does not work. To see why, consider the following scenario. A process p allocates a cell C and completes the AddCell and Apply&CopyResponse operations and begins the RemoveCell operation for C. Process p writes (RemoveCell, &C) into the announce object A, and then goes to sleep. A process q now reads (RemoveCell, &C) from A and writes (RemoveCell, &C) into L. Then, q reads (RemoveCell, &C) from L and invokes the DoRemoveCell procedure to try to remove C from the list. Process q then successfully removes C from the list, but crashes before setting C’s response to Done. A process r then invokes an operation on the target object, and begins the AddCell operation for the cell it allocated. Process r then reads (RemoveCell, &C) from L and invokes the DoRemoveCell procedure to try to remove C from the list. During this procedure, when r invokes the SetResponse procedure between line 62 and 63, r sees that C has already been removed from the list (because q removed it earlier). Since C is no longer in the list, the SetResponse procedure cannot acquire the right to access C. Thus, it does not set C’s response to Done (to inform p that C has been removed). So, r exits the DoRemoveCell procedure without settings C’s response to Done.7 Since no process other than p can acquire the right to access C, no process other than p can set the response object of C to Done. Afterward, r writes AddCell into A, then into L, and crashes. At this point, p wakes up and cannot determine that (RemoveCell, &C) was written into L. This is because (1) (RemoveCell, &C) is no longer in L and (2) p cannot determine whether C has been removed from the list by traversing it to see if C is still there (since new processes may arrive and traverse the list concurrently, impeding p’s traversal). So, p will not set the response object of C to Done. Thus, this object remains Null forever, and so p will loop forever in the loop on line 13. So instead of invoking SetResponse(ulloL , ptrL , Done) between line 62 and 63, to set the response object of C to Done, we do so in the first line of the DoRemoveCell procedure. In other words, we tell the process that wants to remove C from the list that C has been removed from the list before we actually remove C from the list! Although this does not look right, we prove that it does not affect the universal construction’s correctness or asymptotic space complexity. Roughly speaking, this is because the operation to remove C, namely ulloL , is in L, and so no other operation can now occur unless this removal is done first. Theorem 6. Algorithm 2 is a wait-free universal construction for the infinite-arrival model with bounded concurrency. Its space complexity at time t is linear in the point contention at t.

5

Related Work Most object implementations in shared-memory systems do not work in the infinite-arrival 7

Notice that this argument does not depend on how r tries to set C’s response to Done: once C has been removed from the list, no newly arrived process can acquire the right to access C in order to set its response to Done.

14

model: they assume a system with n processes, where n is known to the processes (this is the n-arrival model [2]). Object implementations for these systems typically use this known n in their code, and they use some number of base objects that depends on this n. These base objects are statically allocated in every run, even those in which fewer than n processes actually participate. This is clearly undesirable. To avoid this, researchers have designed algorithms for systems where the number of processes is bounded but unknown (this is called the finite-arrival model [2]), e.g., algorithms in [2, 16, 19]. But such algorithms may not work in the infinite-arrival model, i.e., if an infinite number of processes may participate in a run. For example, as Aguilera pointed out in [2], the simple naming algorithm in [2, Figure 4] is not wait-free in these runs. Researchers have also designed algorithms for the infinite-arrival model (e.g., [1, 2, 4–6, 10, 17, 18, 23]). Existing algorithms for this model are typically not space-efficient, and some use infinitely many objects in every run (e.g., [1, 2, 4, 10, 18]). In particular, the universal construction of [4] uses infinitely many base objects in every run because it relies on the collect algorithm of [10], and the universal construction of [23] uses space linear in the number of operations applied so far. Observe that this can be much higher than the number of processes that have participated so far, because each participating process can apply arbitrarily many operations. So, the space complexity of [23] can be much higher (and never less) than the space complexity of our first universal construction. Other work has focused on designing space-efficient algorithms for the infinite-arrival model. For example, the LL/SC implementation from CAS in [17] uses a number of base objects linear in the number of processes that have participated so far. The universal constructions of [5, 6] were also developed for the infinite-arrival model and aim to achieve space efficiency. However, the constructions of [5, 6] rely on an external garbage collection mechanism that automatically frees any object that “becomes inaccessible by any process in the system” [6], even though no such mechanism is provided. Determining when an object becomes inaccessible and can be safely reclaimed is itself a difficult problem [7]. Indeed, to the best of our knowledge, there is no known automatic wait-free garbage collection mechanism for the infinitearrival model. In contrast, our universal constructions do not assume any garbage collection mechanism. In particular, in our second algorithm, processes explicitly manage the recycling of objects. It is worth noting that the algorithms given [5, 6] are analyzed under a space complexity measure that accounts only for the space used at quiescent times, i.e., only at times when no operations are executing. But this measure provides no bounds on the space used in runs without quiescent times, i.e., runs in which at every moment at least one operation is executing. We note that the infinite-arrival model and its variants, including versions with bounded and unbounded concurrency, were introduced by Merritt and Taubenfeld in their seminal paper [18]. The GCAS object and our first universal construction originally appeared in [11]. This universal construction was inspired by the 2-nonblocking universal construction of [8]; in particular, as in our construction, processes compete on a single announce object.

6

Conclusion

We introduced GCAS, a simple and natural generalization of CAS, and showed how it can be used to obtain two space-efficient, wait-free universal constructions in the infinite-arrival model. The first has space-complexity linear in the number of processes that have participated so far, the second has space-complexity linear in the point contention but assumes bounded concurrency. A natural question is whether such universal constructions can be achieved using CAS instead of GCAS. Equivalently, can GCAS be implemented in a space-efficient manner using CAS in the infinite-arrival model? If the answer is yes, then plugging such an implementation into our algorithms would imme15

diately yield space-efficient, wait-free universal constructions based on CAS. If the answer is no, this would demonstrate that GCAS is strictly more powerful than CAS for at least one purpose: obtaining space-efficient, wait-free universal constructions in the infinite-arrival model. We conclude with a final open question: can one achieve the space complexity of our second universal construction in the infinite-arrival model without assuming bounded concurrency?

References [1]

Yehuda Afek, Eli Gafni, and Adam Morrison. “Common2 extended to stacks and unbounded concurrency”. In: Proceedings of the twenty-fifth annual ACM symposium on Principles of distributed computing. 2006, pp. 218–227.

[2]

Marcos K Aguilera. “A pleasant stroll through the land of infinitely many creatures”. In: ACM Sigact News 35.2 (2004), pp. 36–59.

[3]

Daniel Anderson, Guy E Blelloch, and Yuanhao Wei. “Concurrent deferred reference counting with constant-time overhead”. In: Proceedings of the 42nd ACM SIGPLAN International Conference on Programming Language Design and Implementation. 2021, pp. 526–541.

[4]

James Aspnes, Gauri Shah, and Jatin Shah. “Wait-free consensus with infinite arrivals”. In: Proceedings of the thiry-fourth annual ACM symposium on Theory of computing. 2002, pp. 524–533.

[5]

Denis Bédin et al. “Wait-free Algorithms: the Burden of the Past”. In: (2024). url: https: //doi.org/10.21203/rs.3.rs-4125819/v1.

[6]

Denis Bédin et al. “Wait-Free CAS-Based Algorithms: The Burden of the Past”. In: 35th International Symposium on Distributed Computing (DISC 2021). Schloss-Dagstuhl-Leibniz Zentrum für Informatik. 2021.

[7]

Trevor Alexander Brown. “Reclaiming memory for lock-free data structures: There has to be a better way”. In: Proceedings of the 2015 ACM Symposium on Principles of Distributed Computing. 2015, pp. 261–270.

[8]

David YC Chan et al. “Differentiated nonblocking: a new progress condition and a matching queue algorithm”. In: arXiv preprint arXiv:2103.11926 (2021).

[9]

David L Detlefs et al. “Lock-free reference counting”. In: Proceedings of the twentieth annual ACM symposium on Principles of distributed computing. 2001, pp. 190–199.

[10]

Eli Gafni, Michael Merritt, and Gadi Taubenfeld. “The concurrency hierarchy, and algorithms for unbounded concurrency”. In: Proceedings of the twentieth annual ACM symposium on Principles of distributed computing. 2001, pp. 161–169.

[11]

Vassos Hadzilacos, Myles Thiessen, and Sam Toueg. “Generalized Compare and Swap”. In: arXiv preprint arXiv:2410.19102 (2024).

[12]

Maurice Herlihy. “Wait-free synchronization”. In: ACM Transactions on Programming Languages and Systems (TOPLAS) 13.1 (1991), pp. 124–149.

[13]

Maurice Herlihy, Victor Luchangco, and Mark Moir. “The repeat offender problem: A mechanism for supporting dynamic-sized, lock-free data structures”. In: International Symposium on Distributed Computing. Springer. 2002, pp. 339–353.

[14]

Maurice Herlihy et al. “Nonblocking memory management support for dynamic-sized data structures”. In: ACM Transactions on Computer Systems (TOCS) 23.2 (2005), pp. 146–196.

16

[15]

Maurice P Herlihy and Jeannette M Wing. “Linearizability: A correctness condition for concurrent objects”. In: ACM Transactions on Programming Languages and Systems (TOPLAS) 12.3 (1990), pp. 463–492.

[16]

Prasad Jayanti and Srdjan Petrovic. “Efficiently implementing a large number of LL/SC objects”. In: International Conference On Principles Of Distributed Systems. Springer. 2005, pp. 17–31.

[17]

Prasad Jayanti and Srdjan Petrovic. “Efficiently implementing LL/SC objects shared by an unknown number of processes”. In: International Workshop on Distributed Computing. Springer. 2005, pp. 45–56.

[18]

Michael Merritt and Gadi Taubenfeld. “Computing with infinitely many processes”. In: Information and Computation 233 (2013), pp. 12–31.

[19]

Maged M Michael. “Hazard pointers: Safe memory reclamation for lock-free objects”. In: IEEE Transactions on Parallel and Distributed Systems 15.6 (2004), pp. 491–504.

[20]

Maged M Michael. “Safe memory reclamation for dynamic lock-free objects using atomic reads and writes”. In: Proceedings of the twenty-first annual symposium on Principles of distributed computing. 2002, pp. 21–30.

[21]

Ruslan Nikolaev and Binoy Ravindran. “Hyaline: fast and transparent lock-free memory reclamation”. In: Proceedings of the 2019 ACM Symposium on Principles of Distributed Computing. 2019, pp. 419–421.

[22]

Ruslan Nikolaev and Binoy Ravindran. “Snapshot-free, transparent, and robust memory reclamation for lock-free data structures”. In: Proceedings of the 42nd ACM SIGPLAN International Conference on Programming Language Design and Implementation. 2021, pp. 987– 1002.

[23]

Matthieu Perrin, Achour Mostefaoui, and Grégoire Bonin. “Extending the wait-free hierarchy to multi-threaded systems”. In: Proceedings of the 39th Symposium on Principles of Distributed Computing. 2020, pp. 21–30.

[24]

John D Valois. “Lock-free linked lists using compare-and-swap”. In: Proceedings of the fourteenth annual ACM symposium on Principles of distributed computing. 1995, pp. 214–222.

17

Appendix Contents A Model

19

B Proof of Algorithm 1 B.1 Basic Facts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.2 Step Complexity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.3 Linearizability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20 21 25 33

C Proof of Algorithm 2 36 C.1 Basic Facts About B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 C.1.1 Assumptions, definitions, and observations . . . . . . . . . . . . . . . . . . . . 37 C.1.2 A-events, L-events, S-attempts, and list-attempts . . . . . . . . . . . . . . . . 41 C.1.3 Response-reset events and response-set attempts . . . . . . . . . . . . . . . . 54 C.1.4 List-acquire-next attempts, acquire-copy events, and revocation events . . . . 60 C.1.5 The DoLowLevelOp procedure . . . . . . . . . . . . . . . . . . . . . . . . . . 64 C.1.6 Properties of List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 C.1.7 Miscellaneous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 C.2 The L-Invariants Hold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 C.2.1 The sequence of L-events determines the shape of the list . . . . . . . . . . . 77 C.2.2 Each successful S-attempt is immediately after its corresponding L-event . . 86 C.2.3 The AcquireNext procedure has the intended effect . . . . . . . . . . . . . . . 89 C.2.4 The Acquire procedure has the intended effect . . . . . . . . . . . . . . . . . 89 C.2.5 The DoAddCell procedure has the intended effect . . . . . . . . . . . . . . . . 92 C.2.6 The DoRemoveCell procedure has the intended effect . . . . . . . . . . . . . 98 C.2.7 The DoApply&CopyResponse procedure has the intended effect . . . . . . . . 104 C.2.8 The IsDone procedure has the intended effect . . . . . . . . . . . . . . . . . . 108 C.2.9 The L-invariants hold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 C.3 B is Linearizable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 C.3.1 Linearization points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 C.3.2 The linearization respects the real-time order of operations . . . . . . . . . . 128 C.3.3 The linearization respects the specification of the target object type . . . . . 129 C.3.4 The linearization is equivalent to the completed history . . . . . . . . . . . . 130 C.4 B is Wait-free . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 C.4.1 Processes cannot get stuck in the loops on lines 30, 46, and 94. . . . . . . . . 135 C.4.2 Processes cannot get stuck in the loops on lines 53, 57, and 103. . . . . . . . 148 C.4.3 Processes cannot get stuck in the loop on line 13 . . . . . . . . . . . . . . . . 161 C.5 B Correctly Manages Cells and is Space-Efficient . . . . . . . . . . . . . . . . . . . . 164 C.5.1 At most one FreeCell operation per pointer . . . . . . . . . . . . . . . . . . . 165 C.5.2 Tracking acquisitions and revocations per operation execution . . . . . . . . . 167 C.5.3 Acquire-copy events copy the total number of acquisitions . . . . . . . . . . . 175 C.5.4 B correctly manages cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 C.5.5 B is space-efficient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 C.6 A is Linearizable, Wait-free, and Space-Efficient . . . . . . . . . . . . . . . . . . . . . 199 C.6.1 A correctness-preserving mapping from implementation histories of A to B . 202 C.6.2 The mapping produces implementation histories of B . . . . . . . . . . . . . . 206 C.6.3 The mapping is correctness-preserving . . . . . . . . . . . . . . . . . . . . . . 242

18

A

Model

In this section, we elaborate on the model given in Section 2 as needed for our proofs. We consider an infinite arrival distributed system where possibly infinitely many asynchronous processes that may fail by crashing communicate via shared objects such as generalized-compare-and-swap and fetch-and-add. In such systems, shared objects can be used to implement other shared objects such that the implemented objects are linearizable and wait-free. An implementation A of a target object O from a set of base objects B is a collection of procedures that specify how any process in the system can perform any operation of O by applying operations to the base objects in B. A configuration of implementation A is a complete description of the state of the computation at some point in time during a run of the implementation. Formally, it is a function that assigns a state to each process and a state to each shared object in B used by the implementation. The state of a process consists of the values of its local variables and its program counter. In our case the base objects used by the implementation include the objects contained in cells that can be allocated by the memory manager, even those that are not currently allocated. The initial configuration C0 of the implementation A assigns to each process its initial state and to each object the initial state specified by the implementation. Each process executes steps. Formally, a step is a triple (C, p, C ′ ), where p is a process, C, C ′ are configurations of the implementation, and C ′ is obtained from C by executing the instruction indicated by p’s program counter in C. The instructions executed by p are of the following types: • Invocation of an operation on the target object O. • Response of an operation on the target object O. • Computation involving only local variables of p and at most one atomic access to a base object. Accordingly we call the step (C, p, C ′ ) involving the execution of such an instruction an invocation, response, or implementation step. An implementation history I of A is a (finite or infinite) sequence of steps (C0 , p1 , C1 ), (C1 , p2 , C2 ), (C2 , p3 , C3 ), . . . . That is, I describes a possible sequence of steps taken by processes during a run of A, starting from its initial configuration. For brevity, we write this implementation history as C0 , p1 , C1 , p2 , C2 , p3 , C3 , . . . , but it is important to keep in mind that technically an implementation history is a sequence of steps. We note that, in the special case where I is an implementation history of A consisting of zero steps, I = C0 where C0 is the initial configuration of A. We require that, for every process p, the subsequence of implementation history I consisting of the steps of p is composed of the repetition, zero or more times, of the following pattern: (a) the invocation step for an operation o of the target object O, (b) a sequence of implementation steps, and (c) the response step for o. where the last repetition may be a prefix of this pattern. The sequence of implementation steps in (b) is precisely as specified by the implementation A for how p is to perform operation o. An operation execution opx of process p in I consists of an invocation step of p and all the subsequent steps of p in I up to and including the next response step of p, if such a step exists. If opx ends with a response step, we say that opx is complete in I and its invocation and

19

response steps are matching; otherwise, we say that opx is incomplete in I. Accordingly, the point contention in I is the number of pending operations in I.8 An object history H of O is a sequence of invocation and response steps, such that for each process p, the subsequence of H involving only the steps of p, denoted H|p , consists of an alternating sequence of invocation and response steps, starting with an invocation step. An operation execution opx of process p in H is either a pair consisting of an invocation step of p and the next response step of p, if such a step exists; or the last invocation step of p in H, if that step is not followed by a response step of p. In the first case, we say that opx is complete in H and the two steps of opx are matching; in the second case, opx is incomplete in H. An object history H is complete if all operation executions in H are complete. A completion of H is an object history H′ formed by removing the invocation step of, or adding a response step to, each incomplete operation execution in H; thus H′ is complete. Two object histories H1 and H2 are equivalent if for all processes p, H1 |p = H2 |p . An object history H induces an irreflexive partial order <H on operation executions: opx1 <H opx2 if opx1 ’s response step occurs before opx2 ’s invocation step in H. An object history S is sequential if S starts with an invocation step and each invocation step is immediately followed by its matching response step. Each object has a type that specifies how the object behaves when it is accessed sequentially. Formally, an object of type T is specified by a tuple (OP, RES, Q, δ, s0 ), where OP is a set of operations, RES is a set of responses, Q is a set of states, δ ⊆ Q × OP × Q × RES is a state transition relation, and s0 ∈ Q is the initial state of T . A tuple (s, o, s′ , r) in δ means that if type T is in state s when operation o ∈ OP is invoked, then T can change its state to s′ and return the response r. Note that δ is a relation as opposed to a function to capture non-determinism. A sequential object history S is legal with respect to T if the operation responses in S could be those received when applying these operations sequentially, in the order dictated by S, on an object of type T . That is, S = invocation(opx1 , o1 ), response(opx1 , r1 ), . . . is legal with respect to T if there are s1 , s2 , . . . in Q such that (si−1 , oi , si , ri ) ∈ δ for all i ≥ 1, where s0 is the initial state of T . An implementation A of an object O of type T should be linearizable with respect to T : even when O is accessed concurrently by processes that use A, every operation on O must appear to take effect instantaneously, at some point during its execution interval, according to type T . More precisely, an object history H of O is linearizable with respect to T if there is a completion H′ of H that is equivalent to some sequential object history S that is legal with respect to T and <H′ ⊆<S . An implementation history I of A is linearizable with respect to T if the object history H obtained by removing all implementation steps from I is linearizable with respect to T . Finally, implementation A is linearizable with respect T if every implementation history I of A is linearizable with respect to type T . An implementation A of an object is wait-free if, in any implementation history of A, a process cannot invoke an operation and then take infinitely many steps without completing it.

B

Proof of Algorithm 1

The goal of this section is to prove the step complexity of Algorithm 1 and that it is linearizable. Throughout the proof of both algorithms, we use the notion of “time” as a surrogate for the position of a step in any implementation history I. Specifically, if I = (C0 , p1 , C1 ), (C1 , p2 , C2 ), . . ., then time t in I is the tth step in I, i.e., (Ct−1 , pt , Ct ). When we talk about the value of an object or local variable at time t, we are referring to the value of this object or local variable in Ct . Furthermore, when we talk about the operation that occurred at time t (if any), we are referring to the operation that pt performed (Ct−1 , pt , Ct ). So, when thinking about time t, we are always referring either to 8

Note that this is the same as Definition 1 except the time is fixed to be “the end” of the implementation history.

20

the action performed by pt or the state of Ct , and never Ct−1 . In the few cases when we need to talk about the state of Ct−1 , we opt instead to talk about the state at time t − 1.

B.1

Basic Facts

Before we prove the step complexity of Algorithm 1 and that it is linearizable, we begin with some definitions and basic facts. Throughout the proof of Algorithm 1, we use the term “operation” to refer to an operation execution. For convenience, we would like the notion of a cell of a process to be well-defined in every implementation history of Algorithm 1 we consider in this proof. To do so, we make the following assumption, which we note is without loss of generality for our purposes. Assumption B.1.1. Every process that participates in any implementation history of Algorithm 1 takes at least two steps. This is assumed without loss of generality for our purposes because of the following. Consider any implementation history I of Algorithm 1 in which some number of processes take a single step. Let I − be the subsequence of I where all steps by these processes are removed. Since these processes just perform an invocation step and nothing else, it follows that I − is an implementation history of Algorithm 1. Observe that any linearization of I − is a linearization of I. This is because any completion of the object history of I − (which is created by removing all of the implementation steps from I − ) is a completion of the object history of I (because all operations invoked by processes that take a single step are not complete in I, so we remove them in the completed object history). Furthermore, an upper-bound on the step complexity of any operation in I − is also an upper bound on the step complexity of any operation in I because the only operation in I not in I − are ones which take a single step. Finally, the space complexity of I − and I is the same because all processes that take a single step in I do not perform any AllocateCell operations. For convenience, we treat Noop as an operation that occurred in Algorithm 1. So, when we consider any operation o, this is either (1) Noop or (2) an operation execution. Consider any implementation history I of Algorithm 1. All claims are with respect to I. Assumption B.1.2. Null is a value that differs from all possible responses to all operations of type T and Noop is a value that differs from all operations of T . Definition B.1.3. The invocation and response steps for an operation o are line 1 and line 16, respectively. Definition B.1.4. We call a CAS / GCAS operation successful if its response is true and unsuccessful otherwise. Definition B.1.5. For an operation o ̸= Noop: p(o) denotes the process that invoked o; t(o) is equal to the response of the F&I operation executed by p(o) on line 3 within o or ∞ if p(o) has never executed line 3 within o; and we use Cp(o) to refer both to the response p(o) received on its first execution of line 2 and the cell it points to (this is well-defined by Assumption B.1.1.). We sometimes say that Cp(o) is the cell of p(o). For the special case of Noop, p(Noop) is undefined, t(Noop) = 0, and Cp(Noop) equals ptrNoop which is a pointer to a dummy cell initialized to (0, ⊥). Definition B.1.6 (Complete at T ). An operation o is complete at time T if p(o) executed line 16 at some time T ′ ≤ T within o. Definition B.1.7 (Done at T ). An operation o is done at time T if Cp(o) = (t(o), r) and r ̸= Null at some time T ′ ≤ T .

21

We start with two observations about operations in general. An immediate consequence of Definition B.1.7 is Observation B.1.8. If operation o is done at time T then for all times T ′ ≥ T o is done at T ′ . Since timestamp assignment is done using a fetch-and-increment object (line 3) that is initially 1, each operation is assigned a unique timestamp greater than or equal to 1. Hence Observation B.1.9. For all operations o and o′ , if t(o) ̸= ∞ and t(o′ ) ̸= ∞ then o ̸= o′ if and only if t(o) ̸= t(o′ ). The following three observations concern A and S. Since A is initially (t(Noop), Noop, CNoop ) and the new values passed on line 8 and line 15 are always of the form (t(o), o, Cp(o) ), we have: Observation B.1.10. For all times T there exists an operation o such that A equals (t(o), o, Cp(o) ) at T . In this case, we also say that “(t(o), o, Cp(o) ) is stored in A” or, for brevity, “o is stored in A” at time T . Furthermore, we say “an execution of line 8 or line 15 is for operation o” to mean that it is of the form GCAS(−, A, (t(o), o, Cp(o) ), (t(o), o, Cp(o) )). Since t(o) is unique to o, and processes only write timestamps into A they received on line 3, we have: Observation B.1.11. Every execution of line 8 or line 15 for operation o is by p(o) within o. Like with Observation B.1.10, S is initially (t(Noop), s0 , ⊥, CNoop ). Since every new time and cell pointer written into S on line 13 is supplied from reading A, they are always t(o) and Cp(o) by Observation B.1.10. Moreover, the response field is equal to the response from applyT which is always not Null by Assumption B.1.2. Hence: Observation B.1.12. For all times T there exists an operation o such that S equals (t(o), −, r, Cp(o) ) at T for some response r ̸= Null. In this case, we also say that “(t(o), −, r, Cp(o) ) is stored in S” or, for brevity, “o is stored in S” at time T . Furthermore, we say “an execution of line 13 is for operation o” to mean that it is of the form CAS(S, −, (t(o), −, r, Cp(o) )). The following two observations concern each process p’s cell Cp . By Observation B.1.12: Observation B.1.13. Each execution of line 7 is of the form CAS(Cp(o) , (t(o), Null), (t(o), r)) for some operation o and response r ̸= Null. Henceforth we abbreviate this as “line 7 is executed for o”. Since the contents of Cp only change on line 4 and line 7 we have the following: Observation B.1.14. For all processes p the following hold: • Cp .time only changes by p executing line 4. • Every execution of line 4 by p sets Cp .time to a unique value. • Cp .time is monotonically increasing. The following observation concerns CNoop . Since Noop is a value that differs from all operations of T by Assumption B.1.2, DoOp(Noop) is never invoked. Thus, the contents of CNoop can only change on line 7, but since CNoop is initialized to (0, ⊥), all executions of line 7 for Noop will not change CNoop . Hence: Observation B.1.15. CNoop = (0, ⊥) at all times. 22

We now prove some basic facts about Algorithm 1. Lemma B.1.16. Every CAS operation on S on line 13 is for an operation o ̸= Noop. Proof. Suppose, for contradiction, that some CAS on S on line 13 is for Noop and let p be the process that executed this CAS. Thus, p read (0, Noop, CNoop ) from A on line 9 and found the condition on line 11 to be true. Therefore, CNoop = (0, Null) ̸= (0, ⊥) at some time. However, by Observation B.1.15, CNoop = (0, ⊥) at all times, a contradiction. Lemma B.1.16 Lemma B.1.17. Suppose Cp = (t, r) and r ̸= Null at time T . For all times T ′ ≥ T if Cp .time = t at T ′ then Cp .response = r at T ′ . Proof. Suppose that Cp = (t, r) at time T where r ̸= Null, and Cp .time = t at time T ′ ≥ T . Hence, since by Observation B.1.14 Cp .time is monotonically increasing, we have that Cp .time equals t throughout [T, T ′ ]. Thus, since by Observation B.1.14 Cp .time only changes by p executing line 4, and every execution of line 4 by p sets Cp .time to a unique value, it follows that line 4 has not been executed by p throughout [T, T ′ ]. So, throughout [T, T ′ ] the contents of Cp can only be changed by executions of line 7. However, since line 7 only changes Cp .response if it equals Null, and Cp .response = r which is not Null at T , all executions of line 7 throughout [T, T ′ ] are unsuccessful. Therefore, Cp .response = r throughout [T, T ′ ] as wanted. Lemma B.1.17 Lemma B.1.18. Suppose process p executes line 9 at time T , operation o is stored in A at T , o is done at T , and p executes line 11 after T . Let the time of p’s next execution of line 11 after T be T ′ . Then, p finds the condition on line 11 to be false at T ′ . Proof. Since o is done at T , by Definition B.1.7, Cp(o) = (t(o), r) such that r ̸= Null at some time T1 ≤ T . Furthermore, since p executes line 9 at time T , and operation o is stored in A at T , by Observation B.1.10, p reads (t(o), o, Cp(o) ) from A on line 9 at T . Hence, since p executes line 11 after T , we have that p reads some value (t̂, r̂) from Cp(o) on its next execution of line 10 after T ; say at time T2 > T , so T2 ≥ T1 (because T1 ≤ T ). Thus, on p’s execution of line 11 at T ′ , we have that p checks whether (t̂, r̂) = (t(o), Null). If t̂ = t(o), then since Cp(o) = (t(o), r) such that r ̸= Null at T1 ≤ T2 , by Lemma B.1.17, r̂ = r ̸= Null, so p finds the condition on line 11 to be false at T ′ . Otherwise, t̂ ̸= t(o), so p finds the condition on line 11 to be false at T ′ . Lemma B.1.18 Lemma B.1.19. If operation o is complete at time T , then o is done at some time T ′ < T . Proof. If operation o is complete at time T , then by Definition B.1.6 p(o) executed line 16 at some time T1 ≤ T within o. Hence, p(o) found the condition on line 5 to be false at some time T2 < T1 within o. Thus, since by Observation B.1.14 line 4 is the only step that changes Cp(o) .time, we have that Cp(o) .time = t(o) at T2 . So, at T2 , Cp(o) = (t(o), r) for some r ̸= Null. Therefore, by Definition B.1.7 o is done at T2 , which is before T as wanted. Lemma B.1.19 Proposition B.1.20. If Cp(o) = (t(o), −) at time T and Cp(o) = (t, −) for some t ̸= t(o) at time T ′ > T then operation o is done at some time T ∗ < T ′ . Proof. Since by Observation B.1.14 Cp(o) .time is monotonically increasing, t ̸= t(o), and T ′ > T , we have that t(o) < t. Hence, since by Observation B.1.14 line 4 is the only step that changes Cp(o) .time, we have that at some time T1 ≤ T ′ , p(o) executed line 4 within some operation o′ where t = t(o′ ). Thus, since t(o) < t, we have that t(o) < t(o′ ), and so o′ ̸= o. So, since t(o) < t(o′ ), and p(o) invoked both o and o′ , by the monotonicity of the responses on line 3, p(o) completed o at some time T2 < T1 . Therefore, by Lemma B.1.19 o is done at some time T ∗ < T2 < T ′ . Proposition B.1.20 23

Lemma B.1.21. If a process executes line 7 for operation o at time T then o is done at T . Proof. Suppose a process p executes line 7 for o at some time T . If o = Noop then by Observation B.1.15 CNoop = (0, ⊥) at T . Hence by Definition B.1.7, o is done at T . Now suppose o ̸= Noop. By Observation B.1.13 p’s execution of line 7 at time T was of the form CAS(Cp(o) , (t(o), Null), (t(o), r)) for some r ̸= Null. If p’s CAS is successful, then Cp(o) = (t(o), r) at time T , and so by Definition B.1.7 o is done at T . If p’s CAS is unsuccessful, then Cp(o) = (t′ , r′ ) at time T such that t′ ̸= t(o) or r′ ̸= Null. If t′ = t(o), then r′ ̸= Null, so by Definition B.1.7 o is done at T . Now suppose t′ ̸= t(o). Hence, since p executed line 7 for o, we have that o was stored in S at the time T1 < T when p executed line 6 the same iteration of the loop. Thus, since o ̸= Noop, it follows that some process q executed a successful CAS operation on line 13 for o at some time T2 < T1 . So, q read (t(o), o, Cp(o) ) from A on its last execution of line 9 before T2 , and found the condition on line 11 to be true on its last execution of line 11 before T2 ; say at time T3 < T2 . Hence, Cp(o) = (t(o), Null) at the time of q’s last execution of line 10 before T3 ; say at time T4 < T3 . Since Cp(o) = (t(o), Null) at T4 and Cp(o) = (t′ , r′ ) where t′ ̸= t(o) at T > T4 (because T4 < T3 < T2 < T1 < T ), by Proposition B.1.20, o is done at some time T5 < T . Therefore, by Observation B.1.8, o is done at T as wanted. Lemma B.1.21 Lemma B.1.22. Suppose S stores operations o and o′ at times T and T ′ > T , respectively. If o ̸= o′ then o is done at T ′ . Proof. Since S stores o at T and o′ ̸= o at T ′ > T , it follows that some process executed a successful CAS operation on line 13 between T and T ′ . Let T1 be the first such time, and let p be the process that executed it. Hence, since o is stored in S at T , it follows that o is stored in S at the step before T1 . Thus, since the CAS at T1 is successful, it follows that p read (t(o), −, −, Cp(o) ) from S on its last execution of line 6 before T1 , and so p executed line 7 for o on its last execution of line 7 before T1 ; say at time T2 . Hence, by Lemma B.1.21, o is done at T2 . Therefore, since T2 < T1 < T ′ , by Observation B.1.8 o is done at T ′ as wanted. Lemma B.1.22 Lemma B.1.23. If an operation o is done at time T then Cp(o) ̸= (t(o), Null) from T onwards. Proof. Since o is done at T , by Definition B.1.7, Cp(o) = (t(o), r) such that r ̸= Null at some time T ∗ ≤ T . Hence, since by Observation B.1.14 Cp(o) .time is monotonically increasing, we have that Cp(o) .time equals some timestamp t ≥ t(o) at any time T ′ ≥ T ∗ . If t = t(o), then since Cp(o) = (t(o), r) such that r ̸= Null at T ∗ ≤ T ′ by Lemma B.1.17 Cp(o) = (t(o), r) at T ′ . Otherwise, Cp(o) = (t, −) and t > t(o) at T ′ . Hence, Cp(o) ̸= (t(o), Null) at T ′ and therefore from T onwards as wanted. Lemma B.1.23 Proposition B.1.24. Suppose that: • At time Ti13 , process pi executes a successful CAS operation on S on line 13 for operation o. • At time Tj13 > Ti13 , process pj executes a CAS operation on S on line 13 also for operation o. Then the last reading of S by pj on line 6 before Tj13 occurs at some time Tj6 < Ti13 . Proof. Suppose, for contradiction, pj ’s last execution of line 6 before Tj13 occurs at time Tj6 > Ti13 . Let Tj7 < Tj9 < Tj10 < Tj11 be the times between Tj6 and Tj13 when pj executed lines 7, 9, 10, and 11, respectively. Since pj executed a CAS operation on S on line 13 for operation o at Tj13 , it read (t(o), o, Cp(o) ) on line 9 at Tj9 . Hence, pj read from Cp(o) on line 10 at Tj10 . Since pj executed line 13 at Tj13 , it found the condition of line 11 to be true at Tj11 . Thus, Cp(o) = (t(o), Null) at Tj10 . We claim that o is done at either Tj6 or Tj7 , which is before Tj10 . There are two cases.

24

Case 1. o is stored in S at Tj6 . Hence, pj ’s CAS operation on line 7 at Tj7 is for o. Thus, by Lemma B.1.21, o is done at Tj7 . Case 2. o′ ̸= o is stored in S at Tj6 . By assumption the CAS on S on line 13 by pi at Ti13 was for operation o and is successful, so S stores o at Ti13 . Since o′ ̸= o is stored in S at time Tj6 > Ti13 , by Lemma B.1.22 o is done at Tj6 . We now finish the proof. Since o is done before Tj10 , by Lemma B.1.23, Cp(o) ̸= (t(o), Null) at Tj10 . However, as established above, Cp(o) = (t(o), Null) at Tj10 , a contradiction. Proposition B.1.24 Lemma B.1.25. Every successful CAS operation on S on line 13 is for a different operation. Proof. Suppose, for contradiction, that processes pi and pj both execute successful CAS operations on S on line 13 for the same operation o at distinct times Ti13 and Tj13 , respectively. Without loss of generality, assume Tj13 is the minimum time when there are two successful CAS operations on S on line 13 for the same operation. Hence, Ti13 < Tj13 . Let Tj6 be the time of pj ’s last execution of line 6 before Tj13 . Hence, by Proposition B.1.24, Tj6 < Ti13 . Let o1 be the operation stored in S at Tj6 . We claim that o1 ̸= o. Suppose, for contradiction, that o1 = o. Since pi and pj perform CAS operations on S on line 13 for o, by Lemma B.1.16, o ̸= Noop. Hence, since o1 = o, we have that o1 ̸= Noop. Thus, since o1 is stored in S at Tj6 , it follows that there is a successful CAS operation on S on line 13 for o1 (and hence o) before Tj6 . Therefore, since Tj6 < Ti13 < Tj13 , it follows that at time Ti13 there are two successful CAS operations on S on line 13 for o. However, Tj13 is the minimum time when there are two successful CAS operations on S on line 13 for the same operation, a contradiction. We now finish the proof of Lemma B.1.25. Since the CAS operation on S on line 13 at Ti13 is for o and is successful, we have that S stores o at Ti13 . Hence, since o1 is stored in S at Tj6 < Ti13 < Tj13 , and pj ’s CAS operation on S on line 13 at Tj13 is successful, it follows that S stores o1 at the step before Tj13 . Thus, since as we proved above o1 ̸= o, it follows that there is a successful CAS operation on S on line 13 for o1 between Ti13 and Tj13 . So, by Lemma B.1.16, o1 ̸= Noop. Hence, since o1 is stored in S at Tj6 , it follows that there is a successful CAS operation on S on line 13 for o1 before Tj6 . Therefore, since Tj6 < Ti13 < Tj13 , we have that there are two successful CAS operations on S on line 13 for o before Tj13 . However, Tj13 is the minimum time when there are two successful CAS operations on S on line 13 for the same operation, a contradiction. Lemma B.1.25

B.2

Step Complexity

In this section, we prove that the maximum number of steps a process takes to perform an operation o is adaptive to the point contention at the time it gets a timestamp for o. More precisely: Theorem. Suppose a process p invokes an operation o and executes line 3 within o. Let c be the point contention at this time. Then, the number of steps that p takes within o is at most linear in c. Since if p doesn’t execute line 3 within o, it only takes two steps within o (p executes line 1 and 2 within o), and the point contention at any time is an integer, this theorem implies wait-freedom. We now describe the high-level strategy for proving this theorem. Since p takes a constant number of steps before and after the loop on line 5 within o, and p takes a constant number of steps each iteration of the loop on line 5 within o, it suffices to prove that p performs at most linear in c number of iterations of the loop on line 5 within o. Before we explain how we do this, we note that the reason p continues to iterate in the loop is that it is either unable to announce 25

o into A or it gets “dislodged” from A by operations with higher priority (i.e., those with smaller timestamps). So, to bound the number of iterations of the loop, we have to argue that eventually these high-priority operations are no longer in A, and they eventually stop dislodging o from A. We also note that there are at most c of these operations: those that have a timestamp no larger than t(o) and are pending at the time p executes line 3 within o; denote them by S(o). To bound the number of iterations of the loop, we prove that every small constant number of iterations of the loop by p within o, which we call a period (as defined formally later), p can identify an operation o′ in S(o). The strategy is then that if p performs too many periods, it can identify more operations in S(o) than what are actually in S(o), yielding a bound on the number of iterations. For example, if S(o) has five elements, and we were guaranteed that in every period p could identify a unique operation in S(o), then p performs at most 5 periods because if it were to perform more, we could identify 6 elements in S(o), contradicting the fact that S(o) has five elements. The challenge with making this strategy work is that this identification may be redundant: p performs many periods, but it always identifies the same operation in S(o). To avoid this, we require that p identifies an operation o′ ∈ S(o) in any period with the following properties: (1) o′ is done during the period; (2) o′ is stored in A during the period; and (3) o′ is dislodged from A during the period after it was stored in A and after it is done. As a black box, these three properties let us prove that p can identify the same operation in at most three periods. This is because if p identifies the same operation o′ in four different periods, then it would imply that p(o′ ) announced o′ in A three times after o′ was done, but by the order in which operations happen in the loop, p(o′ ) will check whether o′ is done before announcing o′ for the third time, at which time it will see o′ is done, and stop trying to announce o′ , contradicting the fact it announces o′ for a third time. Since p identifies a new operation in S(o) at least every fourth period, we can conclude that p performs at 3S(o) periods within o. This is because if p were to perform any more, it would imply S(o) has more elements than it does. So, since S(o) has at most c elements, we have p performs at most 3c periods within o, and so p performs at most linear in c number of iterations within o. The majority of the work is in proving that p can identify an operation in each period with the above properties. We prove this by considering various “paths” that p can take during the period (e.g., in the first iteration of the loop, did p execute line 13 or line 15 and was the CAS operation successful or not) and identifying the desired operation in each case. We now begin the proof. We start by formalizing the concept of a period. Definition B.2.1. We call an iteration I of the loop on line 5 by some process p terminal if p finds the condition on line 5 to be false during I. Furthermore, we call I complete if either (a) I is terminal or (b) p executes line 13 or line 15 during I. Definition B.2.2. For each operation o, we call five consecutive complete and not terminal iterations of the loop on line 5 by p(o) within o a period of o. We call a period P of o a non-initial period when the first iteration of P is not the first iteration of the loop on line 5 by p(o) within o. We call periods P1 and P2 of o distinct when P1 and P2 are comprised of distinct iterations. We now define the set of high-priority operations that can compete with o. Definition B.2.3. Let S(o) be the set of operations that are pending at the time p(o) executes line 3 within operation o, assuming it does, such that ∀o′ ∈ S(o) t(o′ ) ≤ t(o), and ∅ otherwise. We now define the properties of the operation we want to identify within each period. Definition B.2.4. For a period P of o we say that P is useful when the following are true. 1. There is an operation o′ ∈ S(o) that is done at some time T1 during P . 26

2. o′ is stored in A at some time T2 during P . 3. Some operation o∗ ̸= o′ is stored in A at some time T3 during P such that T3 > max(T1 , T2 ). The bulk of the work is to prove that every non-initial period is useful. The next two lemmas motivate why we consider non-initial periods instead of periods. Roughly speaking, by discarding the first iteration of the loop within an operation o, we don’t need to worry about the case where a high-priority operation that is not in S(o) blocks p(o) from announcing o. This is because the first iteration ensures that p(o) gets them out of A if they are there at all, and because they are not in S(o), they are guaranteed not to be announced again (as is implied by the next claim). Proposition B.2.5. Consider any operation o where p(o) executes line 3 within o. For every operation o′ with t(o′ ) ≤ t(o) if o′ is not pending at the time p(o) executes line 3 within o, then o′ is complete at the time p(o) executes line 3 within o. Proof. Suppose, for contradiction, there is an operation o′ with t(o′ ) ≤ t(o) such that o′ is not pending and not complete at the time p(o) executes line 3 within o. Hence, o′ was not invoked at the time p(o) executes line 3 within o. Since p(o) executes line 3 within o, by Definition B.1.5, t(o) ̸= ∞. Hence, since t(o′ ) ≤ t(o), we have that t(o′ ) ̸= ∞. Thus, by Definition B.1.5, p(o′ ) executes line 3 within o′ . So, since o′ was not invoked at the time p(o) executes line 3 within o, we have that p(o′ ) executes line 3 within o′ after p(o) executes line 3 within o. Therefore, by line 3, t(o) < t(o′ ). However, by assumption t(o′ ) ≤ t(o), a contradiction. Proposition B.2.5 Lemma B.2.6. Consider any iteration I of the loop on line 5 by p(o) within operation o other than the first iteration. Some operation in S(o) is stored in A at the time p(o) executes line 8 in I. Proof. Suppose, for contradiction, no operation in S(o) is stored in A at the time p(o) executes line 8 in I; say time T 8 . By Observation B.1.10, some operation o′ is stored in A at time T 8 , i.e., A = (t(o′ ), o′ , Cp(o′ ) ) at T 8 . Since p(o) executes line 8 in I at time T 8 , we have that it is for o, so the GCAS executed at time T 8 is of the form GCAS(>, A, (t(o), o, Cp(o) ), (t(o), o, Cp(o) )). Hence, since A = (t(o′ ), o′ , Cp(o′ ) ) at T 8 , we have that (t(o′ ), o′ , Cp(o′ ) ) ≤ (t(o), o, Cp(o) ), and so t(o′ ) ≤ t(o). Thus, if o′ is pending at the time p(o) executes line 3 within o, by Definition B.2.3, o′ ∈ S(o), and so some operation in S(o) is stored in A at time T 8 , contradicting our initial assumption. So, o′ is not pending at the time p(o) executes line 3 within o. Hence, since t(o′ ) ≤ t(o), by Proposition B.2.5, o′ is complete at the time p(o) executes line 3 within o. Since I is any iteration of the loop on line 5 by p(o) within o other than the first iteration, we have that p(o) completed an iteration I − of the loop on line 5 within o before it began I. Hence, since o′ is complete at the time p(o) executes line 3 within o, it follows that o′ is complete before p(o) began I − . Suppose o∗ is the operation stored in A at the time p(o) executed line 9 in I − ; say at time T 9 , so T 9 < T 8 . There are two cases. Case 1. o∗ ̸= o′ . Hence, since o∗ is the operation stored in A at T 9 , o′ is stored in A at T 8 , and T 9 < T 8 , by Observation B.1.11, it follows that p(o′ ) executed line 8 or line 15 for o′ within o′ after T 9 ; say at time T . Thus, since o′ completed before p(o) began I − , and T 9 is a time after p(o) began I − , by transitivity, o′ completed before T . Therefore, since p(o′ ) took the step at T within o′ , we have that p(o′ ) took a step within o′ after o′ completed, which is impossible. Case 2. o∗ = o′ . Hence, since o∗ is the operation stored in A at T 9 , we have that o′ is the operation stored in A at T 9 . Since o′ is complete before p(o) began I − , by Lemma B.1.19, o′ is done before p(o) began I − . Hence, since p(o) executed line 9 at time T 9 in I − , by Observation B.1.8, o′ is done at T 9 . 27

Thus, since p(o) executed line 9 at T 9 , o′ is the operation stored in A at T 9 , o′ is done at T 9 , and p(o) completes I − , by Lemma B.1.18, p(o) finds the condition on line 11 to be false during I − . So, p(o) executes line 15 during I − . Hence, since o′ is the operation stored in A at T 9 , and p(o) executed line 9 in I − at T 9 within o, we have that p(o)’s execution of line 15 during I − is of the form GCAS(=, A, (t(o′ ), o′ , Cp(o′ ) ), (t(o), o, Cp(o) )). Thus, since o′ is complete at the time p(o) executes line 3 within o, it follows that o′ ̸= o, and so regardless of whether p(o)’s execution of line 15 during I − is successful, it follows that o′ is not stored in A at the time of it. Thus, o′ is not stored in A sometime during I − . So, since o′ is stored in A at T 8 , and T 8 is the time of a step after I − , by Observation B.1.11, it follows that p(o′ ) executed line 8 or line 15 for o′ within o′ sometime after I − began. Therefore, since o′ completed before p(o) began I − , we have that p(o′ ) took a step within o′ after o′ completed, which is impossible. Lemma B.2.6 Lemma B.2.7. Consider any iteration I of the loop on line 5 by p(o) within operation o other than the first iteration. If at any time after p(o) executes line 8 in I the operation o′ stored in A has the property that t(o′ ) ≤ t(o), then o′ ∈ S(o). Proof. Suppose, for contradiction, o′ ∈ / S(o). Since t(o′ ) ≤ t(o), if o′ is pending at the time p(o) executes line 3 within o, then by Definition B.2.3 o′ ∈ S(o), contradicting o′ ∈ / S(o). Hence, it ′ must be that o is not pending at the time p(o) executes line 3 within o. Thus, since t(o′ ) ≤ t(o), by Proposition B.2.5, o′ is complete at the time p(o) executes line 3 within o. Let T 8 be the time that p(o) executes line 8 in I. Hence, since o′ is complete at the time p(o) executes line 3 within o, and p(o) executes line 3 within o before T 8 , by transitivity, o′ is complete before T 8 . Furthermore, since I is any iteration of the loop on line 5 by p(o) within o other than the first iteration, by Lemma B.2.6, some operation o∗ ∈ S(o) is stored in A at T 8 . Thus, since o′ ∈ / S(o) is stored in A at some time after T 8 , it follows that there is an execution of line 8 or line 15 for o′ after T 8 . So, since o′ is complete before T 8 , by transitivity, there is an execution of line 8 or line 15 for o′ after o′ is complete. Therefore, by Observation B.1.11, there is an execution of line 8 or line 15 by p(o′ ) within o′ after o′ is complete, which is impossible, a contradiction. Lemma B.2.7 The goal of the next few claims is to prove that every non-initial period is useful. The plan is to consider various “paths” that p(o) can take during the period. Proposition B.2.8. Consider any non-initial period P of some operation o. If an operation o′ ∈ / S(o) is stored in A at some time T during P such that T is after the first time p(o) executed line 8 during P , then P is useful. Proof. Let T 8 be the first time p(o) executed line 8 during P . Denote the iteration of the loop on line 5 that p(o) performed this execution of line 8 in as I. Since P is a non-initial period, and I is an iteration of P , by Definition B.2.2, I is not the first iteration of the loop on line 5 by p(o) within o. Hence, by Lemma B.2.6, some operation o∗ ∈ S(o) is stored in A at T 8 . Thus, since o′ ∈ / S(o) is stored in A at T , and T 8 < T , we have that there is a non-empty finite sequence of GCAS operation on A during (T 8 , T ], each of which is an execution of either line 8 or line 15. Let e1 , . . . en denote the sequence of GCAS operations on A during (T 8 , T ]. We claim that at least one of e1 , . . . en is a successful execution of line 15. Suppose, for contradiction, none of e1 , . . . en is a successful execution of line 15. Hence, since e1 , . . . en are executions of either line 8 or line 15, we have that each successful execution is on line 8. Thus, since o∗ ∈ S(o) is stored in A at T 8 , by Definition B.2.3, t(o∗ ) ≤ t(o), and so since e1 , . . . en is the sequence of GCAS operations on A during (T 8 , T ], each successful execution in e1 , . . . en is for line 8, and o′ ∈ / S(o) is stored in A at T , it follows that t(o′ ) ≤ t(o). Therefore, since o′ is an operation stored in A after T 8 , by Lemma B.2.7, o′ ∈ S(o). However, o′ ∈ / S(o), a contradiction. 28

We now finish the proof of Proposition B.2.8. Since at least one of e1 , . . . en is a successful execution of line 15, we have that there is a first ei in e1 , . . . en that is a successful execution of line 15. Hence, since e1 , . . . ei−1 are executions of either line 8 or line 15, we have that each successful execution is on line 8. Let ô be the operation stored in A at the step before ei . Since o∗ ∈ S(o) is stored in A at T 8 , by Definition B.2.3, t(o∗ ) ≤ t(o), and so since e1 , . . . ei−1 is the sequence of GCAS operations on A between T 8 and the step before ei , each successful execution in e1 , . . . ei−1 is for line 8, and ô is stored in A at at the step before ei , it follows that t(ô) ≤ t(o). Hence, since ô is an operation stored in A after T 8 , by Lemma B.2.7, ô ∈ S(o). Let q be the process that executed ei . Since ei is a successful execution of line 15, and ô is the operation stored in A at the step before ei , by Observation B.1.10, it follows that ei is of the form GCAS(=, A, (t(ô), ô, Cp(ô) ), −). Hence, q found the condition on line 11 to be false on its last execution of it before ei , and so by line 10, q saw Cp(ô) ̸= (t(ô), Null) before executing ei . Thus, by Definition B.1.7, ô is done at before ei , and so by Observation B.1.8, ô is done at ei . Lastly, since ô ∈ S(o) is stored in A at the step before ei , e1 , . . . en is the sequence of GCAS operations on A during (T 8 , T ], and o′ ∈ / S(o) is stored in A at ′ T , we have that o ̸= ô is stored in A at T . Therefore, since (1) ô ∈ S(o) is done at ei which is in P , (2) ô is stored in A at the step before ei which is in P , and (3) o′ ̸= ô is stored in A at T which is in P and after ei , by Definition B.2.4, P is useful as wanted. Proposition B.2.8 Proposition B.2.9. Consider any non-initial period P of some operation o. If p(o) executes line 15 during one of the first four iterations of P , then P is useful. Proof. Consider any execution of line 15 by p(o) during any iteration I of P such that I is one of the first four iterations of P . By Proposition B.2.8, it suffices to consider the case where the operation o′ stored in A at the time p(o) executes line 9 during I is in S(o); say T 9 . Since o′ is stored in A at T 9 , by Observation B.1.10, p(o) read (t(o′ ), o′ , Cp(o′ ) ) from A on line 9 at T 9 . Hence, since p(o) executed line 15 during I, we have that p(o) found the condition on line 11 to be false during I, and so p(o) saw Cp(o′ ) ̸= (t(o′ ), Null) on line 10 during I. Thus, by Definition B.1.7, o′ is done at some time during I and before p(o) executed line 15 during I. There are two cases. Case 1. o ̸= o′ . Hence, p(o) tries to write (t(o), o, Cp(o) ) ̸= (t(o′ ), o′ , Cp(o′ ) ) into A on line 15 during I. If p(o) is successful, then an operation o ̸= o′ is stored in A at the time p(o) executed line 15 during I. Otherwise, if p(o) is unsuccessful, since p(o) read (t(o′ ), o′ , Cp(o′ ) ) from A on line 9 during I, we have that A ̸= (t(o′ ), o′ , Cp(o′ ) ) at the time p(o) executed line 15 during I. Hence, in all cases, some operation o∗ ̸= o′ is stored in A at the time p(o) executed line 15 during I. Therefore, since (1) o′ ∈ S(o) is done at some time during I (and thus P ) before p(o) executed line 15 during I, (2) o′ is stored in A at at the time p(o) executes line 9 during I which is in P , and (3) some operation o∗ ̸= o′ is stored in A at the time p(o) executed line 15 during I (and thus P ) which is after the time identified in (1) and (2), by Definition B.2.4, P is useful as wanted. Case 2. o = o′ . Since I is one of the first four iterations of P , by Definition B.2.2, there is a complete and not terminal iteration I + of the loop on line 5 after I by p(o) within o. Hence, since o′ is done at some time during I and before p(o) executed line 15 during I, and o = o′ , by Observation B.1.8, o is done at the time p(o) executes line 5 during I + . Thus, by Lemma B.1.23, Cp(o) ̸= (t(o), Null) at this time, and so p(o) finds the condition on line 5 to be false during I + . Therefore, by Definition B.2.1, I + is terminal. However, I + is not terminal, a contradiction, so this case is impossible. Proposition B.2.9 Proposition B.2.10. Consider any non-initial period P of some operation o. If p(o) executes line 13 and the response is true in any of the first three iterations of P , then P is useful. 29

Proof. Consider any execution of line 13 whose response is true during any iteration I of P such that I is one of the first three iterations of P . By Proposition B.2.8, it suffices to consider the case where the operation o′ stored in A at the time p(o) executes line 9 during I is in S(o); say T 9 . Since o′ is stored in A at T 9 , by Observation B.1.10, p(o) read (t(o′ ), o′ , Cp(o′ ) ) from A on line 9 at T 9 . Hence, since p(o) executed line 13 during I, it is of the form CAS(S, −, (t(o′ ), −, −, Cp(o′ ) )), so by Observation B.1.12, it is for o′ . Thus, since the response of this CAS operation is true, we have that o′ is stored in S during I; say at time T . Since I is one of the first three iterations of P , by Definition B.2.2, there is a complete and not terminal iterations of the loop on line 5 by p(o) within o after I. Let I + be the next one after I. Since I + is complete and not terminal, p(o) executes line 6 (resp. line 7) during I + ; say at time T 6 (resp. T 7 ). Hence, since I completes before I + begins, and T is a time during I, we have that T < T 6 < T 7 . Let o∗ be the operation stored in S at T 6 . If o′ ̸= o∗ , then since o′ is stored in S at T , o∗ is stored in S at T 6 , and T < T 6 , by Lemma B.1.22, o′ is done at T 6 , and so since T 6 < T 7 , by Observation B.1.8, o′ is done at T 7 . If o′ = o∗ , then since o∗ is stored in S at T 6 , we have that p(o) executes line 7 for o′ at T 7 , and so by Lemma B.1.21, o′ is done at T 7 . Therefore, in all cases, o′ is done at T 7 . There are two cases. Case 1. o′ is not stored in A at the time p(o) executes line 9 during I + . Therefore, since (1) o′ ∈ S(o) is done at T 7 during I + (and thus P ), (2) o′ is stored in A at T 9 during I (and thus P ), and (3) o′ is not stored in A at the time p(o) executes line 9 during I + which is after the times in (1) and (2), by Definition B.2.4, P is useful as wanted. Case 2. o′ is stored in A at the time p(o) executes line 9 during I + . Hence, p(o) read (t(o′ ), o′ , Cp(o′ ) ) from A at this time. Thus, since o′ is done at T 7 , by Observation B.1.8, o′ is done at the time p(o) executes line 10 during I + . So, by Lemma B.1.23 Cp(o′ ) ̸= (t(o′ ), Null) at this time. Hence, p(o) finds the condition on line 11 to be false during I + , and so p(o) executes line 15 during I + . Thus, since I is one of the first three iterations of P , and I + is the iteration after I in P , we have that I + is one of the first four iterations of P . Therefore, since p(o) executes line 15 during I + , by Proposition B.2.9, P is useful as wanted. Proposition B.2.10 Proposition B.2.11. Consider any non-initial period P of some operation o. If p(o) executes line 13 and the response is false in the second and third iteration of P , then P is useful. Proof. Denote the first three iterations of P as I1 , I2 , and I3 . Let T26 (resp. T36 ) be the time that p(o) executed line 6 during I2 (resp. I3 ) and let T213 (resp. T313 ) be the time that p(o) executed line 13 during I2 (resp. I3 ). Since p(o) executed line 13 during I2 (resp. I3 ) and received a response of false, it follows that the value of S changed between T26 and T213 (resp. T36 and T313 ). Hence, there is a successful execution of the CAS operation on line 13 between T26 and T213 (resp. T36 and T313 ). Let e2 (resp. e3 ) be a successful execution of the CAS operation on line 13 between T26 and T213 (resp. T36 and T313 ). Hence, since T26 and T213 (resp. T36 and T313 ) are during I2 (resp. I3 ), and I2 is completed before I3 begins, we have the following ordering: T26 < e2 < T213 < T36 < e3 < T313 . Let q be the process that executed e3 and let Tq6 be the time of q’s last execution of line 6 before e3 . We claim that Tq6 is after e2 . Suppose, for contradiction, Tq6 is before e2 . Let o3 be the operation stored in S at the step before e3 . Hence, since e3 is successful, it follows that q read (t(o3 ), −, −, Cp(o3 )) ) from S on line 6 at Tq6 . Thus, by Observation B.1.12, o3 is stored in S at Tq6 . Since Tq6 is before e2 , e2 is before e3 , and o3 is the operation stored in S at the step before e3 , we have that there is a successful CAS operation on S on line 13 for o3 strictly between Tq6 and e3 . 30

Hence, by Lemma B.1.16, o3 ̸= Noop. Thus, since o3 is stored in S at Tq6 , we have that there is a successful CAS operation on S on line 13 for o3 before Tq6 . Therefore, there are two successful CAS operation on S on line 13 for o3 . However, by Lemma B.1.25, every CAS operation on S on line 13 is for a different operation, a contradiction. We now finish the proof of Proposition B.2.11. Since Tq6 is after e2 , we have that q’s last execution of line 9 before e3 is between e2 and e3 ; say at time Tq9 . Let T18 be the time p(o) executed line 8 during I1 . Hence, since I1 completed before I2 began, and T26 is during I2 , by transitivity, T18 < T26 . Thus, since T26 < e2 , e2 < Tq9 < e3 , and e3 < T313 , by transitivity, T18 < Tq9 < T313 . So, since T18 is a time during I1 , T313 is a time during I3 , and both I1 and I3 are during P , we have that Tq9 is a time during P . Let o′ be the operation stored in A at Tq9 . There are two cases. Case 1. o′ ∈ / S(o). Since o′ ∈ / S(o) is stored in A at time Tq9 , which by above is during P , and Tq9 is after the first time p(o) executed line 8 during P (namely T18 ), by Proposition B.2.8, P is useful as wanted. Case 2. o′ ∈ S(o). The argument is essentially the same as Proposition B.2.10. Since o′ is the operation stored in A at Tq9 , by Observation B.1.10, q read (t(o′ ), o′ , Cp(o′ ) ) from A on line 9 at Tq9 . Hence, since Tq9 is the time of q’s last execution of line 9 before e3 , we have that e3 is of the form CAS(S, −, (t(o′ ), −, −, Cp(o′ ) )), so by Observation B.1.12, it is for o′ . Thus, since the response of this CAS operation is true, we have that o′ is stored in S at e3 . So, since T36 < e3 < T313 , and T36 and T313 are during I3 , we have that o′ is stored in S during I3 ; say at time T . Since I3 is the third iteration of P , by Definition B.2.2, there is a complete and not terminal iteration of the loop on line 5 by p(o) within o after I3 . Let I + be the next one after I3 . Since I + is complete and not terminal, p(o) executes line 6 (resp. line 7) during I + ; say at time T 6 (resp. T 7 ). Hence, since I3 completes before I + begins, and T is a time during I3 , we have that T < T 6 < T 7 . Let o∗ be the operation stored in S at T 6 . If o′ ̸= o∗ , then since o′ is stored in S at T , o∗ is stored in S at T 6 , and T < T 6 , by Lemma B.1.22, o′ is done at T 6 , and so since T 6 < T 7 , by Observation B.1.8, o′ is done at T 7 . If o′ = o∗ , then since o∗ is stored in S at T 6 , we have that p(o) executes line 7 for o′ at T 7 , and so by Lemma B.1.21, o′ is done at T 7 . Therefore, in all cases, o′ is done at T 7 . There are two cases. Case 2.1. o′ is not stored in A at the time p(o) executes line 9 during I + . Hence, since T18 < Tq9 < T313 , T313 is during I3 , and I3 completed before I + began, by transitivity, the time p(o) executes line 9 during I + is after Tq9 . Therefore, since (1) o′ ∈ S(o) is done at T 7 during I + (and thus P ), (2) o′ is stored in A at Tq9 which by the above is during P , and (3) o′ is not stored in A at the time p(o) executes line 9 during I + which is after the times in (1) and (2), by Definition B.2.4, P is useful as wanted. Case 2.2. o′ is stored in A at the time p(o) executes line 9 during I + . Hence, p(o) read (t(o′ ), o′ , Cp(o′ ) ) from A at this time. Thus, since o′ is done at T 7 , by Observation B.1.8, o′ is done at the time p(o) executes line 10 during I + . So, by Lemma B.1.23 Cp(o′ ) ̸= (t(o′ ), Null) at this time. Hence, p(o) finds the condition on line 11 to be false during I + , and so p(o) executes line 15 during I + . Thus, since I3 is the third iteration of P , and I + is the iteration after I3 in P , we have that I + is one of the first four iterations of P . Therefore, since p(o) executes line 15 during I + , by Proposition B.2.9, P is useful as wanted. Proposition B.2.11 Lemma B.2.12. Every non-initial period is useful.

31

Proof. Consider any non-initial period P of an operation o. If either: (1) p(o) executes line 15 during any of the first three iterations of P ; (2) p(o) executes line 13 and the response is true in any of the first three iterations of P ; or (3) p(o) executes line 13 and the response is false in each of the first three iterations of P , then by Propositions B.2.9, B.2.10, and B.2.11, respectively, P is useful. So, it suffices to assume P does not satisfy case (1), (2), or (3). We show that this is impossible, completing the proof. By Definition B.2.2 P is five consecutive complete and not terminal iterations of the loop on line 5 by p(o) within o; denote the first three of them by I1 , I2 , and I3 . Since these iterations are complete and not terminal, by Definition B.2.1, p(o) executes either line 13 or line 15 in each of them. However, since P does not satisfy case (1), we have that p(o) executed line 13 during I1 , I2 , and I3 . Hence, since P does not satisfy case (2), we have that when p(o) executes line 13 and receives a response of false in I1 , I2 , and I3 . Therefore, P satisfies case (3). However, P does not satisfy case (3), a contradiction. Lemma B.2.12 We now bound the number of distinct non-initial periods per operation. We start by proving that after four distinct non-initial periods, we have identified at least two operations. Proposition B.2.13. Consider four distinct non-initial periods P1 , P2 , P3 , and P4 of an operation. By Lemma B.2.12, they are useful, so by Definition B.2.4, there is an operation o1 , o2 , o3 , and o4 that is done at some time in P1 , P2 , P3 , and P4 , respectively. Then, |{o1 , o2 , o3 , o4 }| ≥ 2. Proof. Suppose, for contradiction, |{o1 , o2 , o3 , o4 }| < 2. Hence, o1 = o2 = o3 = o4 ; denote this operation by o. Without loss of generality, suppose P1 , P2 , P3 , P4 is the order in which they occur. Since P1 is useful, by Definition B.2.4, o is done at some time D during P1 . Furthermore, since P1 , P2 , P3 , and P4 are useful, by Definition B.2.4, there is a time T2A , T3A , and T4A during P2 , P3 , and P4 , respectively, where o is stored in A, and there is a time T1X , T2X , and T3X during P1 , P2 , and P3 , respectively, where o is not stored in A such that T1X > D, T2X > T2A , and T3X > T3A . Hence, since P1 , P2 , P3 , P4 are distinct, and this is the order in which they occur, it follows that D < T1X < T2A < T2X < T3A < T3X < T4A . A , it follows that Thus, for each i ∈ [1..3], since o is not stored in A at TiX and o is stored in A at Ti+1 A there is an execution of line 8 or line 15 for operation o; denote this execution between TiX and Ti+1 as ei . So, by Observation B.1.11, ei is performed by p(o) within o. Since e1 , e2 , and e3 are each an execution of line 8 or line 15 by p(o) within o, it follows that p(o) executes line 5 within o some time strictly between e1 and e3 ; say at time T . Thus, since T is after e1 , e1 is after T1X , and T1X is after D, by transitivity, T is after D. So, since o is done at D, by Lemma B.1.23, Cp(o) ̸= (t(o), Null) at T . Since T is the time of an execution of line 5 by p(o) within o, it follows that p(o) checks whether Cp(o) = (t(o), Null) on line 5 at time T . Therefore, since Cp(o) ̸= (t(o), Null) at time T , we have that p(o) finds the condition on line 5 to be false at time T , and so p(o) does not execute line 8 or line 15 from T onwards within o. However, since T is strictly before e3 , and e3 is an execution of line 8 or line 15 by p(o) within o, we have that p(o) executes line 8 or line 15 from T onwards within o, a contradiction. Proposition B.2.13

Lemma B.2.14. Every operation o has at most 3|S(o)| distinct non-initial periods. Proof. Suppose, for contradiction, some operation o has more than 3|S(o)| distinct non-initial periods. Hence, there are at least 3|S(o)| + 1 distinct non-initial periods of o. Denote them as P1 , P2 , . . . , P3|S(o)|+1 . For each i ∈ [1..3|S(o)| + 1], by Lemma B.2.12, Pi is useful, so by Definition B.2.4, some operation oi ∈ S(o) is done at some time during Pi . For each n ∈ [0..|S(o)|] let P(n) be the predicate: |On | ≥ n + 1 where On = {o1 , . . . o3n+1 }. We prove P(n) by induction on n. 32

Base Case. n = 0. Hence, On = {o1 } and n + 1 = 1. Therefore, since |{o1 }| ≥ 1, we have that P(0) holds. Inductive Case. ∀n ∈ [0..|S(o)|) P(n) =⇒ P(n + 1). Suppose for some n ∈ [0..|S(o)|) P(n) holds. This is the inductive hypothesis. Suppose, for contradiction, P(n+1) does not hold, so |On+1 | < n+2. Since P(n) holds, we have that |On | ≥ n+1. Hence, since On ⊆ On+1 , we have that |On+1 | ≥ n + 1, and so n + 1 ≤ |On+1 | < n + 2. Thus, |On+1 | = n + 1. So, since |On | ≥ n + 1 and On ⊆ On+1 , it follows that On = On+1 . Therefore, since On ̸= ∅, and On+1 = On ∪ {o3n+2 , o3n+3 , o3n+4 }, we have that o′ = o3n+2 = o3n+3 = o3n+4 for some o′ ∈ On . However, by Proposition B.2.13, |{o′ , o3n+2 , o3n+3 , o3n+4 }| ≥ 2, a contradiction. We now finish the proof of Lemma B.2.14. Since for each i ∈ [1..3|S(o)| + 1] oi ∈ S(o), we have that O|S(o)| ⊆ S(o). Furthermore, since P(|S(o)|) holds, we have that |O|S(o)| | ≥ |S(o)| + 1. Therefore, since O|S(o)| ⊆ S(o), we have that |S(o)| ≥ |S(o)|+1, which is impossible. Lemma B.2.14 We now have all we need to prove the main result of this section. Theorem B.2.15 (Theorem 5 restated). Suppose a process p invokes an operation o and executes line 3 within o. Let c be the point contention at this time. Then, the number of steps that p takes within o is at most linear in c. Proof. By Definition B.1.5, p = p(o). Furthermore, by Definition B.2.3 |S(o)| is at most the number of pending operations at the time p(o) executes line 3 within o, so |S(o)| ≤ c. Hence, since by Lemma B.2.14, o has at most 3|S(o)| distinct non-initial periods, it follows that o has at most 3|c| distinct non-initial periods. Thus, by Definition B.2.2, o has at most 3|c| distinct periods after the first iteration of the loop on line 5 by p(o) within o. So, by Definition B.2.2, p(o) completes at most 15|c| non-terminal iterations of the loop on line 5 within o after the first iteration of the loop on line 5 by p(o) within o. Hence, by Definition B.2.1, p(o) completes at most 15|c| + 2 iterations of the loop on line 5 within o (the 2 accounts for the first iteration and the terminal iteration). Therefore, since p(o) takes a constant number of steps before entering (resp. after exiting) the loop on line 5 within o, and p(o) takes a constant number of steps during each iteration of the loop on line 5 within o, it follows that p(o) takes at most linear in c steps within o as wanted. Theorem B.2.15

B.3

Linearizability

In this section, we prove that Algorithm 1 is linearizable with respect to type T . Theorem B.3.1. Algorithm 1 is linearizable with respect to type T . Proof. Consider any implementation history I of Algorithm 1. Let H be the object history obtained by removing all implementation steps from I. We must prove that H is linearizable with respect to T ; that is, we must prove that there is a completion H′ of H that is equivalent to some sequential history S such that S is legal with respect to T and <H′ ⊆<S . Let (t1 , s1 , r1 , −), (t2 , s2 , r2 , −), (t3 , s3 , r3 , −), . . . be the sequence of values written into S in I. These values were written by the sequence of successful CAS executions on S on line 13 in I. Observe that there is a unique operation oi on O that has timestamp ti (see Observation B.1.9). So the sequence Ops = o1 , o2 , o3 , . . . 33

is the sequence of operations stored in S during I (see Observation B.1.12). Using Ops, we define the completion H′ of H as follows. Consider any incomplete operation o in H. If o is in Ops and the first index it appears at is i, then a response step for o is appended at the end of H′ with response ri . Otherwise, o’s invocation step is removed in H′ . Also using Ops, we define a sequential history S as the sequence invocation(o1 ), response(o1 , r1 ), invocation(o2 ), response(o2 , r2 ), . . . where invocation(oi ) is the invocation step of operation oi (line 1) and response(oi , ri ) is the response step of oi which returned the response ri (line 16). The remainder of this proof will go as follows. • First we define the linearization point ℓ(oi ) of oi to be the time when the successful CAS on line 13 wrote (ti , si , ri , −) in S. Since each oi appears exactly once in Ops, ℓ(oi ) is well-defined, and the operations in Ops appear in increasing order of their linearization points. • We will prove that (a) every complete operation in H is in Ops and (b) the linearization point ℓ(oi ) of every operation oi in Ops (whether complete in I or not) is after oi ’s invocation step in I and before oi ’s response step I if it exists. These two facts together imply that <H′ ⊆<S . • We will then prove that for every oi in Ops, (si , ri ) = applyT (oi , si−1 ). This implies that S is legal with respect to T . • We will then prove that if oi is a complete operation in I then its response is ri in I. • Finally, we will prove that H′ is equivalent to S. For every operation o in Ops, define ℓ(o) to be the time of the successful CAS on S on line 13 for o in I. This is well defined by Lemma B.1.25. Claim B.3.1.1. (a) Every complete operation in I is in Ops. (b) The linearization point ℓ(o) of every operation o in Ops (whether complete in I or not) is after o’s invocation step in I and before o’s response step in I if it exists. Proof. For part (a) consider any complete operation o in I and let p = p(o). Therefore, p found the response r to o in Cp .response (see lines 5 and 16). Thus some process q previously executed a successful CAS on Cp on line 7 that wrote (t(o), r) in Cp . Hence, q previously read (t(o), −, r, Cp ) in S on line 6, say at time Tq6 . Thus a successful CAS on S on line 13 and wrote that value before Tq6 . Therefore, the complete operation o is one of the operations in Ops, say oi , which completes the proof of part (a). Furthermore, oi ’s linearization point ℓ(oi ) occurred before Tq6 , and so before o’s response step, which is needed for part (b). To complete the proof of part (b) consider any operation o in I, whether complete or not. The linearization point ℓ(o) of o is the time when some process p executes a successful CAS on S on line 13 and writes (t(o), −, −, −) in S. For this to happen p must have previously read (t(o), −, −) in A on line 9, which means that p(o) executed a successful GCAS on A on either line 8 or line 15 within o. Therefore, the linearization point ℓ(o) occurs after o’s invocation step, which completes the proof of part (b). Claim B.3.1.1 Claim B.3.1.2. <H′ ⊆<S . Proof. Consider any two operations o and o′ in H′ such that o <H′ o′ . Thus, o’s response step in H′ is before o′ ’s invocation step in H′ . Hence, by the construction of H′ : o is complete in H, o <H o′ , and o′ is in Ops. Since H is the result of removing all implementation steps in I, this implies that o is complete in I and that o’s response step in I is before o′ ’s invocation step in I. Since o is complete in I, Claim B.3.1.1 (a) asserts that o is in Ops. Thus by Claim B.3.1.1 (b), ℓ(o) is before o’s response step in I (it exists since o is complete in I). Likewise, since o′ is in Ops, 34

Claim B.3.1.1 (b) states that ℓ(o′ ) is after o′ ’s invocation step in I. Thus, ℓ(o) is before ℓ(o′ ) in I and therefore o is before o′ in Ops. Hence, by the construction of S, o’s response step is before o′ ’s invocation step in S. Therefore, o <S o′ as wanted. Claim B.3.1.2 Claim B.3.1.3. For every oi in Ops, (si , ri ) = applyT (oi , si−1 ), where s0 is the initial state of type T. Proof. By definition, si and ri are the values written in S.state and S.response, respectively, by the ith successful CAS on S on line 13 in I. Let q be the process that performed this CAS. Therefore, by line 12, (si , ri ) = applyT (o′ , s∗ ), where o′ is the operation in A.operation when q last read A on line 9 and s∗ is the state in S.state when q last read S on line 6. So the timestamp t′ in A.time when q read A on line 9 is the timestamp ti that q wrote into S.time in the i-th successful CAS on S on line 13; therefore t′ = ti , and o′ = oi . Furthermore, s∗ is the value in S.state when q executed the i-th successful CAS on S on line 13: otherwise, that CAS would not be successful. Therefore, s∗ is the value written in S.state by the (i − 1)-th successful CAS on S on line 13, or the initial state s0 of O, if i = 1, so s∗ = si−1 . Thus (si , ri ) = applyT (oi , si−1 ), as wanted. Claim B.3.1.3 By the definition of applyT Claim B.3.1.3 immediately implies: Corollary B.3.1.4. For every oi in Ops, (si−1 , oi , si , ri ) ∈ δ, where δ is the state-transition relation of type T , and s0 is the initial state of type T , so S is legal with respect to T . Claim B.3.1.5. For every oi in Ops, if oi is complete in I then its response is ri in I. Proof. Suppose that oi ’s response is r in I. Let p = p(oi ). Since oi is complete and (by definition) t(oi ) = ti , p found Cp = (ti , r) on line 5, for some r ̸= Null, and returned r on line 16. Therefore, some process q wrote (ti , r) in Cp by a successful CAS on line 7. This means that q read (ti , s, r, Cp ) from S on line 6, for some state s. This, in turn, implies that some process q ′ wrote (ti , s, r, Cp ) into S via a successful CAS on line 13. By Lemma B.1.25 there is only one successful CAS on S on line 13 in I for oi . So, s = si and r = ri . Therefore, oi returns ri in I. Claim B.3.1.5 Claim B.3.1.6. H′ is equivalent to S. Proof. We must prove that H′ |p = S|p for each process p. By the definition of H′ , S, and Claims B.1.25 and B.3.1.1 (a), there is a one-to-one mapping between steps of H′ |p and those of S|p . Furthermore, by definition the operations of these operation executions are the same in H′ |p and those of S|p , and by Claim B.3.1.5 it follows that their responses are the same. Since operations for each process p appear sequentially in I from which H′ is derived, H′ |p is a sequential history. Thus <H′ |p is a total order over all operations in H′ |p . Likewise, since S|p is a sequential history, <S|p is a total order over all operations in S|p . Since (1) there is a one-to-one mapping between steps of H′ |p and those of S|p for each process p, (2) <H′ |p is a total order over all operations in H′ |p , (3) <S|p is a total order over all operations in S|p , and (4) <H′ |p ⊆<S|p by Claim B.3.1.2, H′ |p = S|p . Claim B.3.1.6 By Claim B.3.1.6 H′ is equivalent to S, by Corollary B.3.1.4 S is legal with respect to T , and by Claim B.3.1.2 <H′ ⊆<S . Therefore, H is linearizable with respect to T . Theorem B.3.1 Theorem B.3.2 (Theorem 4 restated). Algorithm 1 is a wait-free universal construction for the infinite-arrival model. Its space complexity at time t is linear in the number of processes that have participated by time t. Proof. By Theorem B.2.15 and Theorem B.3.1, Algorithm 1 is a wait-free universal construction for the infinite-arrival model. The space complexity immediately follows from the observation that every process performs at most one AllocateCell operation. Theorem B.3.2 35

Let C be an infinite set of pointers to unique cells. State: Allocated : A set of pointers to cells, initially ∅. AllocateCell() ptr := pick a pointer from C \ Allocated Allocated := Allocated ∪ {ptr} return ptr

FreeCell(ptr) Allocated := Allocated \ {ptr} return Done

Algorithm 3: Memory manager operations. State: Allocated : A set of pointers, initially ∅. FreeCell(ptr) return Done

AllocateCell() ptr := pick a pointer from C \ Allocated Allocated := Allocated ∪ {ptr} return ptr

Algorithm 4: Lazy memory manager operations.

C

Proof of Algorithm 2

In this section, we prove that Algorithm 2 is linearizable, wait-free, and has space complexity linear in the point contention. The high-level strategy is to prove that Algorithm 2 satisfies these properties assuming that the memory manager does not reuse freed cells (we call this version algorithm B). We then show that violation of any of these properties by Algorithm 2 when the memory manager can reuse freed cells (we call this version algorithm A) would imply the violation of that property of B, contradicting the first result. This is done by establishing a “correctnesspreserving mapping” from implementation histories of A to B. A high-level description of this mapping is given at the start of Appendix C.6. Also, for convenience, we treat the memory manager as a base object, and define A and B below. Definition C.0.1 (A). Algorithm A is Algorithm 2 using the memory manager given in Algorithm 3. For a step (C, p, C ′ ), there are two details not specified in the pseudocode: 1. If during this step p performs an AllocateCell operation on the memory manager whose response is ptr, then the state assigned to each object of the cell pointed to by ptr in C ′ is the initial state specified in Algorithm 2. 2. If during this step p performs an operation o on an object of a cell whose pointer is not in the state assigned to the memory manager in C, then the response of o is arbitrary. Definition C.0.2 (B). Algorithm B is Algorithm 2 using the “lazy” memory manager given in Algorithm 4.9 In contrast to algorithm A, AllocateCell operations do not change the state of objects of a cell, and every operation on an object of a cell respects the semantics of its type. Roadmap. Appendix C.1 proves some basic facts about B, and states some key-invariants that we prove in Appendix C.2. We then prove that B is linearizable, wait-free, and has space complexity linear in the point contention in Appendices C.3, C.4, and C.5, respectively. Lastly, we prove that A has all these properties in Appendix C.6. We note that Appendices C.2-C.6 are logically independent, but all they all depend on the definitions and basic facts given in Appendix C.1. 9

This memory manager is lazy in the sense that FreeCell operations do nothing.

36

Conventions. We use the symbol ∗ to mean any value, and − is used in the code to mean that that field is not needed. A prefix I ′ of an implementation history I during [t1 , t2 ] means that if I = (C0 , p1 , C1 ), (C1 , p2 , C2 ), . . ., then I ′ = (C0 , p1 , C1 ), . . . , (Ci−1 , pi , Ci ) for some i ∈ [t1 , t2 ]. We will often talk about an operation that occurs during some step s, e.g., a CAS operation on some base object, and denote it by o, and then later refer to some step s that happened before (resp. after) o, and use the notation s < o (resp. o < s) to mean that the step number of s is smaller (resp. larger) than the step number of o in the implementation history I they both occur in. Throughout the entire proof, every number we refer to is an integer. Lastly, to help keep track of the important statements, the headwords (i.e., Claim, Lemma, Proposition, Theorem) in this appendix are used as follows. Theorems are only for major properties of an algorithm (i.e., linearizability, and there are only four theorems for B and one for A), lemmas are properties referenced outside of the subsubsection they are stated in, propositions are properties not referenced outside of the subsubsection they are stated in, and claims are properties stated and used inside a proof.

C.1

Basic Facts About B

In this section prove some basic facts about B. Throughout this section, I B refers to an arbitrary implementation history of B, i.e., all statements that refer to I B begin with “for every implementation history I B of B”, which is omitted for brevity. C.1.1

Assumptions, definitions, and observations

We first state all assumptions used throughout the proof. Assumption C.1.1. The system has bounded concurrency (see Definition 2). Assumption C.1.2. Null ∈ / C and &H ∈ / C ∪ {Null}. Assumption C.1.3. Null differs from all possible responses to all operations of T . Definition C.1.4. The invocation and response steps for an operation execution are lines 1 and 8, respectively. The purpose of the long definition that follows is to provide hopefully meaningful and evocative terminology (rather than referring to line numbers) for the steps that affect the states of the base objects. This makes the statements of the claims that follow more natural and their proofs easier to follow. Definition C.1.5. We define the following terminology for steps in I B . • An execution of a GCAS (resp. CAS) operation is successful if it returns True and unsuccessful if it returns False. • Consider a successful execution of the GCAS operation in line 21 or a successful execution of the CAS operation in line 27. (These lines are the only places in the algorithm that modify the contents of A, see Observation C.1.6.) Such an operation writes into A a value of the form ((t, llo), ptr). We refer to these operations as A-events for timestamp t or A-events for ptr. Specifically, – If llo = AddCell, we say that this is an A-add event for timestamp t or an A-add event for ptr. – If llo = ⟨Apply&CopyResponse, ∗⟩, we say that this is an A-apply event for timestamp t or an A-apply event for ptr. – If llo = RemoveCell, we say that this is an A-remove event for timestamp t or an A-remove event for ptr.

37

(As we will see in Proposition C.1.13 t > 0, in Lemma C.1.14 ptr ∈ C, and in Lemma C.1.15 every A-event is either an A-add, A-apply, or A-remove event.) • Consider a successful execution of the CAS operation in line 25. (This line is the only place in the algorithm that modifies the contents of L, see Observation C.1.6.) Such an operation writes into L a value of the form ((t, llo), ptr). We refer to these operations as L-events for timestamp t or L-events for ptr. Specifically, – If llo = AddCell, we say that this is an L-add event for timestamp t or an L-add event for ptr. – If llo = ⟨Apply&CopyResponse, ∗⟩, we say that this is an L-apply event for timestamp t or an L-apply event for ptr. – If llo = RemoveCell, we say that this is an L-remove event for timestamp t or an L-remove event for ptr. (As we will see in Lemma C.1.26 t > 0, in Lemma C.1.28 ptr ∈ C, and in Lemma C.1.29 every L-event is either an L-add, L-apply, or L-remove event.) • Consider an (unsuccessful or successful) execution of the CAS operation in line 71. Observe that this CAS operation occurs during an invocation of the DoApply&CopyResponse procedure with parameters ((t, ∗), ∗). This CAS operation attempts to write into S a value of the form ((t, ∗), ∗, ∗). We refer to these operations as S-attempts for t. (We use the word “attempt” as opposed to “event”, to highlight the fact that, in contrast to A- and L-events, which refer to successful CAS operations, S-attempts are not necessarily successful. As we will see in Lemma C.1.45 t > 0.) • Consider an (unsuccessful or successful) execution of the CAS operation in line 36. Observe that this CAS operation occurs during an invocation of the DoAddCell procedure with parameters (∗, ptr). This CAS operation attempts to append to the list the cell pointed to by ptr by changing the next field of the cell pointed to by some pointer curr ptr to (∗, ∗, ∗, ptr). We call the execution of such a CAS operation a list-add attempt for ptr after cur ptr. (As we will see in Lemma C.1.46 ptr ∈ C and in Lemma C.1.49 curr ptr ∈ C ∪ {&H}.) • Consider an (unsuccessful or successful) execution of the CAS operation in line 55. Observe that this CAS operation occurs during an invocation of the DoRemoveCell procedure with parameters (∗, ptr). This CAS operation attempts to seal the cell pointed to by ptr by changing the next.sealed field of the cell pointed to by ptr from False to True. We call the execution of such a CAS operation a list-seal attempt for ptr. (As we will see in Lemma C.1.46 ptr ∈ C.) • Consider an (unsuccessful or successful) execution of the CAS operation in line 61. Observe that this CAS operation occurs during an invocation of the DoRemoveCell procedure with parameters (∗, ptr). This CAS operation attempts to remove from the list the cell pointed to by ptr by changing the next field of the cell pointed to by prev ptr to (∗, ∗, ∗, next ptr). We call the execution of such a CAS operation a list-remove attempt for ptr between prev ptr and next ptr. (As we will see in Lemma C.1.46 ptr ∈ C and in Lemma C.1.53 prev ptr ∈ C ∪ {&H} and next ptr ∈ C ∪ {Null}.) • Consider an execution of the write operation in line 12 for some ptr. Observe that this write operation occurs during an invocation of the DoLowLevelOp procedure with parameters (llo, ptr). This write operation sets the value of (∗ptr).response = ((∗, llo), Null). We refer to these operations as response-reset events for ptr. Specifically, – If llo = AddCell, we say that this is an add-response-reset event for ptr. – If llo = ⟨Apply&CopyResponse, ∗⟩, we say that this is an apply-response-reset event for ptr. – If llo = RemoveCell, we say that this is a remove-response-reset event for ptr. 38

(We will see in Lemma C.1.62 ptr ∈ C and every response-reset event is either an addresponse-reset, apply-response-reset, or remove-response-reset event.) • Consider an execution of the CAS operation in line 77 for some ptr. Observe that this CAS operation occurs during an invocation of the SetResponse procedure with parameters ((∗, llo), ptr, response). This CAS operation attempts to set the value of (∗ptr).response = ((∗, llo), response). We refer to these operations as response-set attempts for ptr to response. Specifically, – If llo = AddCell, we say that this is an add-response-set attempt for ptr to response. – If llo = ⟨Apply&CopyResponse, ∗⟩, we say that this is an apply-response-set attempt for ptr to response. – If llo = RemoveCell, we say that this is a remove-response-set attempt for ptr to response. (We will see in Lemma C.1.75 ptr ∈ C and every response-set attempt is either an addresponse-set, apply-response-set, or remove-response-set attempt.) • Consider an (unsuccessful or successful) execution of the CAS operation in line 109. Observe that this CAS operation occurs during an invocation of the AcquireNext procedure with parameters (∗, ptr). This CAS operation attempts to acquire the cell after the cell pointed to by ptr by changing the next field of the cell pointed to by ptr from (∗, ∗, a, next ptr) to (∗, ∗, a + 1, next ptr). We call the execution of such a CAS operation a list-acquirenext attempt for next ptr after ptr.(As we will see in Lemma C.1.90 next ptr ∈ C and ptr ∈ C ∪ {&H}) • Consider an execution of the F&A operation in line 62. Observe that this F&A operation occurs during an invocation of the DoRemoveCell procedure with parameters (∗, ptr). This F&A operation copies the final number of acquires for ptr into the cell that ptr points to after ptr was removed from the list. We call the execution of such a F&A operation an acquire-copy event for ptr. (As we will see in Lemma C.1.96 ptr ∈ C) • Consider an execution of the F&A operation in line 113. Observe that this F&A operation occurs during an invocation of the Relinquish procedure with parameters (∗, ptr). This F&A operation increments the number of revocations of ptr followed by freeing ptr if it is no longer in use. We call the execution of such a F&A operation a revocation event for ptr. (As we will see in Lemma C.1.97 ptr ∈ C) The benefit of this terminology is that it captures with evocative words (rather than line numbers) the steps that change the values of the base objects. We summarize this in the following observation. In this observation, we use the terminology “set” to mean a step that sets the state of an object or one of its fields, and “change” to mean that a step can actually change the object or one of its fields. This distinction is important because some steps set the state of an object but do not change some of its fields. Observation C.1.6. The following are true for steps in I B : • The only steps that set the value of A are A-events. • The only steps that set the value of L are L-events. • The only steps that set the value of S are successful S-attempts. • For every ptr ∈ C ∪ {&H} the only steps that set the value of (∗ptr).response are responsereset events for ptr and successful response-set attempts for ptr. • For every ptr ∈ C ∪ {&H} the only steps that set the value of (∗ptr).revocations are acquirecopy events for ptr and revocation events for ptr.

39

• For every ptr ∈ C ∪ {&H} the only steps that set the value of (∗ptr).next are successful listadd attempts after ptr, successful list-seal attempts for ptr, successful list-remove attempts between ptr and some pointer, and successful list-acquire-next attempts after ptr. • For every ptr ∈ C ∪ {&H} the only steps that change the value of (∗ptr).next.acquisitions are successful list-add attempts after ptr, successful list-remove attempts between ptr and some pointer, and successful list-acquire-next-attempts after ptr. • For every ptr ∈ C ∪ {&H} the only step that change the value of (∗ptr).next.sealed are successful list-sealed attempts for ptr. • For every ptr ∈ C ∪{&H} the only steps that change the value of (∗ptr).next.ptr are successful list-add attempts after ptr and successful list-remove attempts between ptr and some pointer. In addition to the above terminology, a central concept throughout the proof is the “shape” of the list. As we will see, the shape of the list at some time is determined by the sequence of L-events up to and including that time. We formalize below what the “shape” of the list should be. Definition C.1.7. Consider any finite implementation history I of B. • Let e1 , e2 , . . . , en be the (possibly empty) subsequence of I consisting of the L-add events for some pointer for which there are no subsequent L-remove events for that pointer in I. Let ei be an L-add event for pointer ptri . We let List(I) = &H, ptr1 , ptr2 , . . . , ptrn , Null. • We say that the list of cells conforms to ptr0 , ptr1 , . . . , ptrn , ptrn+1 in I if, at the end of I, for all i ∈ [0..n], (∗ptri ).next.ptr = ptri+1 (assuming ptri ∈ C ∪ {&H}). As we will see in Lemma C.2.6, List(I) is essentially the “shape” of the list at the end of I, or more precisely, the list of cells conforms to List(I) in I. We note that we use the word “essentially” here to disregard the fact that there is some lag between the moment an L-add (resp. L-remove) event for ptr occurs and the time ptr is added (resp. removed) from the list. See Lemma C.2.6 for a precise description of the conditions when this lag does and does not occur. The high-level strategy for proving this fact, and many useful and natural facts about the algorithm, are stated and proved conditionally on the invariants holding. The reason for this is that these statements are needed to prove the invariants themselves. This is not circular because we prove the invariants by induction: we consider any implementation history I of n + 1 steps and assume that the invariants hold for the prefix I ′ of it up to and including the nth step and show that the invariants hold for I. In our proof that the invariants hold for I, we invoke the conditional facts for I ′ , whose assumptions hold because the invariants hold for I ′ by the inductive hypothesis. Definition C.1.8. We define the following four invariants. Invariant P (I B ): For each ptr, there is at most one L-add event for ptr, at most one L-apply event for ptr, and at most one L-remove event for ptr in I B . Invariant Q(I B ): All of the following are true: 1. Every list-add attempt for some ptr after some curr ptr in I B is preceded by a unique L-add event for ptr; furthermore, if I is the prefix of I B up to but excluding that L-add event, curr ptr is the second last pointer in List(I) — i.e., the one preceding Null. 2. Every list-remove attempt for some ptr between some prev ptr and some next ptr in I B is preceded by a unique L-remove event for ptr; furthermore, if I is the prefix of I B up to but excluding that L-remove event, ptr is in List(I) exactly once and prev ptr and next ptr are the pointers preceding and succeeding ptr in List(I). Invariant R(I B ): All of the following are true for any two successive L-events e and e′ in I B : 1. If e is an L-add event for ptr, then the interval between e and e′ contains one successful list-add attempt for ptr and no other successful list-add or list-remove attempt for any pointer. 40

2. If e is an L-apply event, then the interval between e and e′ contains no successful list-add or list-remove attempts for any pointer. 3. If e is an L-remove event for ptr, the interval between e and e′ contains one successful listremove attempt for ptr and no other successful list-remove or list-add attempt for any pointer. Invariant O(I B ): All of the following are true for any two successive L-events e and e′ in I B : • If e is an L-add or L-remove event, then the interval between e and e′ contains no successful S-attempts. • If e is an L-apply event for a timestamp t, then between e and e′ there is one successful S-attempt for t and no other successful S-attempts for any timestamp. We now record some basic observations that are useful throughout the proof. Observation C.1.9. For every prefix I of I B if P (I B ), Q(I B ), R(I B ), or O(I B ) holds, then P (I), Q(I), R(I), or O(I) holds, respectively. Because of this observation, for brevity, when we are satisfying the conditions of a lemma regarding some prefix I of I B , we will satisfy the condition of the lemma that X(I) holds, where X is one of the invariants, by stating that X(I B ) holds. Observation C.1.10. For every ptr ∈ C ∪ {&H}, (∗ptr).next.view is monotonically increasing and is greater than or equal to 0. Observation C.1.11. Every timestamp returned on line 10 is unique and is an integer larger than 0. Observation C.1.12. Consider any response-set attempt a during an invocation I of the SetResponse procedure. The following are true. 1. a is an add-response-set attempt if and only if I was invoked during an invocation of the DoAddCell procedure. 2. a is a remove-response-set attempt if and only if I was invoked during an invocation of the DoRemoveCell procedure. 3. a is an apply-response-set attempt if and only if I was invoked during an invocation of the DoApply&CopyResponse procedure. C.1.2

A-events, L-events, S-attempts, and list-attempts

We start with some facts about A-events. Proposition C.1.13. Every A-event in I B is for a timestamp larger than 0. Proof. Consider any A-event e for some timestamp t executed by some process p. Hence, by Definition C.1.5, e set A to ((t, ∗), ∗), so by Definition C.1.5 t is the response p received on line 10 during the invocation of the DoLowLevelOp procedure that p executed e during. Therefore, by Observation C.1.11 t > 0, and so e is for a timestamp larger than 0 as wanted. Proposition C.1.13 Lemma C.1.14. Every A-event in I B is for some pointer in C. Proof. Consider any A-event e for some ptr executed by some process p. Hence, by Definition C.1.5, p executed e during some invocation I of the DoLowLevelOp procedure with a second parameter of ptr. Thus, since this procedure is only invoked on lines 3, 4, and 6, p performed an AllocateCell whose response is ptr before invoking I. Therefore, by Algorithm 4, ptr ∈ C. Lemma C.1.14 Lemma C.1.15. Every A-event in I B is either an A-add, A-apply, or A-remove event. 41

Proof. Let p be a process that executed an A-event e which sets A.ullo = (∗, llo). By Definition C.1.5, e is an execution of line 21 or line 27 and so p executed e during some invocation I of the DoLowLevelOp procedure. Hence, since e set A.ullo = (∗, llo), it follows that the first parameter of I is llo. Thus, since the DoLowLevelOp procedure is only invoked on lines 3, 4, and 6, we have that llo is either AddCell, ⟨Apply&CopyResponse, ∗⟩, or RemoveCell. Therefore, by Definition C.1.5, e is either an A-add, A-apply, or A-remove event as wanted. Lemma C.1.15 Proposition C.1.16. If the left field of A.ullo is the same at times T and T ′ in I B , then the value of A is the same at T and T ′ . Proof. Suppose, for contradiction, that the left field of A.ullo is the same at T and T ′ and the value of A is different at T and T ′ . Suppose A = ((t, llo), ptr) at T and suppose A = ((t, llo′ ), ptr′ ) at T ′ such that (llo, ptr) ̸= (llo′ , ptr′ ). Without loss of generality, suppose T < T ′ . Hence, the value of A was set to ((t, llo′ ), ptr′ ). Thus, by Observation C.1.6, an A-event e′ set A.ullo to ((t, llo′ ), ptr′ ). So, by Proposition C.1.13 t ̸= 0. Hence, since A is initially ((0, Noop), Null), the value of A at T is not the initial value, and so A was set to ((t, llo), ptr). Thus, by Observation C.1.6, an A-event e set A.ullo to ((t, llo), ptr). Let p (resp. p′ ) be the process that executed e (resp. e′ ). Since e and e′ both set A.ullo = (t, ∗), both p and p′ received t on line 10 during some invocation I (resp. I ′ ) of the DoLowLevelOp procedure. Hence, since by Observation C.1.11 every response on line 10 is unique, we have that p = p′ and I = I ′ . Since p (resp. p′ ) set A to ((t, llo), ptr) (resp. ((t, llo′ ), ptr′ )), we have that the parameters of I (resp. I ′ ) are (llo, ptr) (resp. (llo′ , ptr′ )). Therefore, since I = I ′ , we have that (llo, ptr) = (llo′ , ptr′ ). However, (llo, ptr) ̸= (llo′ , ptr′ ), a contradiction. Proposition C.1.16 Lemma C.1.17. Let e1 and e2 be two executions of either line 21 or 27 that try to set A = ((t, ∗), ∗) in I B . Then, e1 and e2 are executed by the same process p during the same invocation I of the DoLowLevelOp procedure such that p received t as a response on line 10 during I. Proof. Suppose e1 and e2 are performed by processes p1 and p2 during invocations I1 and I2 of the DoLowLevelOp procedure, respectively. Since p1 and p2 both try to set A = ((t, ∗), ∗) during I1 and I2 , we have that p1 and p2 both received t as a response on line 10 during I1 and I2 , respectively. Therefore, since by Observation C.1.11 the responses on line 10 are unique, we have that p1 = p2 = p, I1 = I2 = I, and p received t as a response on line 10 during I as wanted. Lemma C.1.17 Lemma C.1.17 implies the following. Corollary C.1.18. Let e1 and e2 be two executions of either line 21 or 27 that try to set A = v in I B . Then, e1 and e2 are executed by the same process during the same invocation of the DoLowLevelOp procedure. Proposition C.1.19. Consider any A-events e1 and e2 for ptr in I B . Let I1 and I2 be the invocations of the DoLowLevelOp procedure that e1 and e2 were executed in, respectively. Then, I1 and I2 were invoked by the same processes and invoked during the same invocation of the DoHighLevelOp procedure. Proof. Let p1 and p2 be the processes that executed e1 and e2 , respectively. Hence, since e1 and e2 are A-events for ptr during I1 and I2 , respectively, by Definition C.1.5, the second parameter of I1 and I2 is ptr. Thus, p1 and p2 received ptr as response on line 2. Therefore, since by Algorithm 4 the responses on line 2 are unique in B, we have that p1 = p2 and I1 and I2 were invoked during the same invocation of the DoHighLevelOp procedure. Proposition C.1.19 42

Lemma C.1.20. Consider any A-remove event e for ptr in I B . Then, there are no A-apply events for ptr from e onwards in I B . Proof. Suppose, for contradiction, there is an A-remove event e for ptr in I B and there is an A-apply event e′ for ptr after e in I B . Hence, by Proposition C.1.19, the same process p executed e and e′ and did so during the same invocation I of the DoHighLevelOp procedure. By Definition C.1.5, p executed e during an invocation of the DoLowLevelOp procedure invoked on line 6 during I, and p executed e′ during an invocation of the DoLowLevelOp procedure invoked on line 4 during I. Therefore, e′ < e. However, by assumption e < e′ , a contradiction. Lemma C.1.20 Lemma C.1.21. Consider any A-remove event e for ptr in I B . Then, there are no A-add events for ptr from e onwards in I B . Proof. By essentially the same argument as Lemma C.1.20, which is provided below for completeness. Suppose, for contradiction, there is an A-remove event e for ptr in I B and there is an A-add event e′ for ptr after e in I B . Hence, by Proposition C.1.19, the same process p executed e and e′ and did so during the same invocation I of the DoHighLevelOp procedure. By Definition C.1.5, p executed e during an invocation of the DoLowLevelOp procedure invoked on line 6 during I, and p executed e′ during an invocation of the DoLowLevelOp procedure invoked on line 3 during I. Therefore, e′ < e. However, by assumption e < e′ , a contradiction. Lemma C.1.21 Proposition C.1.22. Consider any A-X events e1 and e2 for ptr where X ∈ {add, apply, remove} in I B . Then, e1 and e2 set A to the same value. Proof. Suppose e1 set A = v1 and e2 set A = v2 . Since e1 and e2 are A-X events for ptr, by Definition C.1.5, v1 = ((t1 , llo), ptr) and v2 = ((t2 , llo), ptr). Let p1 and p2 be the processes that executed e1 and e2 , respectively, and let I1 and I2 be the invocation of the DoLowLevelOp procedure that p1 and p2 executed e1 and p2 during, respectively. Since e1 set A = ((t1 , llo), ptr) and e2 set A = ((t2 , llo), ptr), we have that the parameters of I1 and I2 are (llo, ptr) and (llo, ptr), respectively, and p1 and p2 received t1 and t2 as a response on line 10 during I1 and I2 , respectively. Hence, since by Proposition C.1.19 p1 = p2 and I1 and I2 were invoked during the same invocation I of the DoHighLevelOp procedure, and the DoLowLevelOp procedure is only invoked with the same first parameter on a single line during I, we have that I1 = I2 . Thus, since p1 and p2 received t1 and t2 as a response on line 10 during I1 and I2 , respectively, we have that t1 = t2 . Therefore, it follows that v1 = v2 as wanted. Proposition C.1.22 We now prove some facts about L-events. Lemma C.1.23. Consider an L-event e which set L to v in I B . Then, there is an A-event which set A to v before e. We call the last A-event which set A to v before e, e’s corresponding A-event. Proof. Consider any L-event e which set L to some value v. Let p be the process that executed e. Since e set L to v, p read v from A on its last execution of line 22 before e; say at time T 22 . To prove that there is an A-event which sets A to v before e, it suffices to prove that v does not equal the initial value of A. Suppose, for contradiction, v is the initial value of A, i.e., v = ((0, Noop), Null). Since p executed e after reading v from A at T 22 , p found the condition line 24 to be true between T 22 and e; say at time T 24 . Hence, status = NotDone at T 24 . Let I be p’s invocation of the IsDone procedure on line 23 between T 22 and T 24 . Hence, the response of I is NotDone. Thus, p found the condition on line 84, line 86, or line 89 to be true during I. Therefore, since p read ((0, Noop), Null) from A at T 22 , the parameters of I are (∗, (0, Noop), Null), and so Noop equals either AddCell, RemoveCell, or ⟨Apply&CopyResponse, ∗⟩, a contradiction. Lemma C.1.23 43

By Definition C.1.5, this implies the following. Corollary C.1.24. Consider any L-event e in I B and its corresponding A-event e′ . • e is an L-add event if and only if e′ is an A-add event. • e is an L-apply event if and only if e′ is an A-apply event. • e is an L-remove event if and only if e′ is an A-remove event. • e is for timestamp t if and only if e′ is for timestamp t. • e is for ptr if and only if e′ is for ptr. Using this corollary, we can now port basic facts about A-events to L-events. Lemma C.1.25. Consider any A-X event eA for some ptr, and an L-X event eL for ptr where X ∈ {add, apply, remove} in I B . Suppose eA set A = vA and eL set L = vL . Then, vA = vL . Proof. Since eL set L = vL , by Lemma C.1.23, there is an A-event e that sets A = vL . Furthermore, since eL is an L-X event for ptr, by Corollary C.1.24, e is an A-X event for ptr. Therefore, since eA and e are A-X events for ptr, eA set A = vA , and e set A = vL , by Proposition C.1.22, vA = vL as wanted. Lemma C.1.25 Lemma C.1.26. Every L-event in I B is for a timestamp larger than 0. Proof. Consider any L-event e for some timestamp t. Let e′ be e’s corresponding A-event (see Lemma C.1.23). By Corollary C.1.24, e′ is for timestamp t. Therefore, by Proposition C.1.13, t is larger than 0 as wanted. Lemma C.1.26 This implies the following. Corollary C.1.27. Every L-event in I B sets L.ullo ̸= (0, Noop). Lemma C.1.28. Every L-event in I B is for some pointer in C. Proof. Consider any L-event e for some ptr. Let e′ be e’s corresponding A-event (see Lemma C.1.23). Therefore, by Corollary C.1.24, e′ is for ptr, so by Lemma C.1.14, ptr ∈ C. Lemma C.1.28 Lemma C.1.29. Every L-event in I B is either an L-add, L-apply, or L-remove event. Proof. Consider any L-event e. Let e′ be e’s corresponding A-event defined by Lemma C.1.23. Therefore, by Lemma C.1.15 e′ is either an A-add, A-apply, or A-remove event, and so by Corollary C.1.24 e is either an L-add, L-apply, or L-remove event. Lemma C.1.29 We now show that invariant P implies the uniqueness of L-events in I B in different senses. Lemma C.1.30. If P (I B ) holds, then every L-event in I B sets L to a unique value. Proof. Suppose, for contradiction, P (I B ) holds and there are two L-events in I B , say e1 and e2 , that set L to the same value ((∗, llo), ptr). Hence, by Definition C.1.5, e1 and e2 are L-events for ptr, so by Lemma C.1.28 ptr ∈ C. Furthermore, by Lemma C.1.29, llo is either AddCell, ⟨Apply&CopyResponse, ∗⟩, or RemoveCell. Thus, by Definition C.1.5: if llo = AddCell, then e1 and e2 are both L-add events for ptr; if llo = ⟨Apply&CopyResponse, ∗⟩, then e1 and e2 are both L-apply events for ptr; and if llo = RemoveCell, then e1 and e2 are both L-remove events for ptr. Therefore, for some ptr ∈ C, in I B there is either two L-add events for ptr, two L-apply events for ptr, or two L-remove events for ptr. However, since ptr ∈ C, by P (I B ), in I B there is at most one L-add event for ptr, at most one L-apply event for ptr, and at most one L-remove event for ptr, a contradiction. Lemma C.1.30 44

Proposition C.1.31. If the left field of L.ullo is the same at times T and T ′ in I B , then the value of L is the same at T and T ′ . Proof. Suppose, for contradiction, that the left field of L.ullo is the same at T and T ′ and the value of L is different at T and T ′ . Suppose L = ((t, llo), ptr) at T and suppose L = ((t, llo′ ), ptr′ ) at T ′ such that (llo, ptr) ̸= (llo′ , ptr′ ). Without loss of generality, suppose T < T ′ . Hence, the value of L was set to ((t, llo′ ), ptr′ ) sometime during (T, T ′ ]. Thus, by Observation C.1.6, an L-event e′ set L to ((t, llo′ ), ptr′ ). So, by Lemma C.1.23, A = ((t, llo′ ), ptr′ ) at some time TA′ . Furthermore, by Lemma C.1.26, t ̸= 0. Hence, since L is initially ((0, Noop), Null), the value of L at T is not the initial value, and so L was set to ((t, llo), ptr). Thus, by Observation C.1.6, an L-event set L to ((t, llo), ptr). So, by Lemma C.1.23, A = ((t, llo), ptr) at some time TA . Therefore, since A = ((t, llo), ptr) at TA and A = ((t, llo′ ), ptr′ ) at TA′ , by Proposition C.1.16, (llo, ptr) = (llo′ , ptr′ ). However, (llo, ptr) ̸= (llo′ , ptr′ ), a contradiction. Proposition C.1.31 Lemma C.1.32. If P (I B ) holds, then every L-event in I B sets L.ullo to a unique value. Proof. Suppose, for contradiction, P (I B ) holds and there are two L-events e1 and e2 in I B that set the value of L.ullo to the same value. Since e1 and e2 are in I B and by assumption P (I B ) holds, by Lemma C.1.30, e1 and e2 set L to different values. Therefore, since e1 and e2 set L.ullo to the same value, it follows that e1 and e2 set L.ptr to different values. However, since L.ullo is the same at e1 and e2 , by Proposition C.1.31, L.ptr is the same at e1 and e2 , so e1 and e2 set L.ptr to the same value, a contradiction. Lemma C.1.32 Lemma C.1.33. If P (I B ) holds, then every L-event in I B is for a unique timestamp. Proof. Suppose, for contradiction, P (I B ) holds and there are two L-events e1 and e2 in I B for the same timestamp t. Let ((t, llo1 ), ptr1 ) and ((t, llo2 ), ptr2 ) be the values that e1 and e2 write into L, respectively. Since e1 and e2 set L.ullo to (t, llo1 ) and (t, llo2 ), respectively, by Proposition C.1.31, llo1 = llo2 . Therefore, e1 and e2 set L.ullo to the same value. However, since P (I B ) holds, by Lemma C.1.32, every L-event in I B sets L.ullo to a unique value, a contradiction. Lemma C.1.33 We now define the concept of a corresponding L-event for invocations of the DoAddCell, DoRemoveCell, and DoApply&CopyResponse procedures. Proposition C.1.34. Let I be any invocation of the DoAddCell procedure in I B with parameters (ulloL , ptrL ). There is an L-add event for ptrL before I was invoked that set L = (ulloL , ptrL ). Proof. Let p be the process that invoked I. Hence, p read (ulloL , ptrL ) from L on line 14 before invoking I, and so by the condition on line 15 ulloL = (∗, AddCell). Thus, ulloL ̸= (0, Noop), and so since L is initially ((0, Noop), Null), we have that L was set to (ulloL , ptrL ) before I was invoked. So, by Observation C.1.6, there is an L-event e for ptrL that set L = (ulloL , ptrL ) before I was invoked. Therefore, since ulloL = (∗, AddCell), by Definition C.1.5, e is an L-add event for ptrL as wanted. Proposition C.1.34 Proposition C.1.35. Let I be any invocation of the DoRemoveCell procedure in I B with parameters (ulloL , ptrL ). There is an L-remove event for ptrL before I was invoked that set L = (ulloL , ptrL ). Proof. By essentially the same argument as Proposition C.1.34, which is provided below for completeness. Let p be the process that invoked I. Hence, p read (ulloL , ptrL ) from L on line 14 before invoking I, and so by the condition on line 17 ulloL = (∗, RemoveCell). Thus, ulloL ̸= (0, Noop), 45

and so since L is initially ((0, Noop), Null), we have that L was set to (ulloL , ptrL ) before I was invoked. So, by Observation C.1.6, there is an L-event e for ptrL that set L = (ulloL , ptrL ) before I was invoked. Therefore, since ulloL = (∗, RemoveCell), by Definition C.1.5, e is an L-remove event for ptrL as wanted. Proposition C.1.35 Proposition C.1.36. Let I be any invocation of the DoApply&CopyResponse procedure in I B with parameters (ulloL , ptrL ). There is an L-apply event for ptrL before I was invoked that set L = (ulloL , ptrL ). Proof. By essentially the same argument as Proposition C.1.34, which is provided below for completeness. Let p be the process that invoked I. Hence, p read (ulloL , ptrL ) from L on line 14 before invoking I, and so by the condition on line 19 ulloL = (∗, ⟨Apply&CopyResponse, ∗⟩). Thus, ulloL ̸= (0, Noop), and so since L is initially ((0, Noop), Null), we have that L was set to (ulloL , ptrL ) before I was invoked. So, by Observation C.1.6, there is an L-event e for ptrL that set L = (ulloL , ptrL ) before I was invoked. Therefore, since ulloL = (∗, ⟨Apply&CopyResponse, ∗⟩), by Definition C.1.5, e is an L-apply event for ptrL as wanted. Proposition C.1.36 By Lemmas C.1.34, C.1.35, and C.1.36 we have the following. Corollary C.1.37. Let I be any invocation of the DoAddCell, DoApply&CopyResponse, or DoRemoveCell procedure in I B with parameters (ulloL , ptrL ). The following are true. • There is an L-event e for ptrL before I was invoked that set L = (ulloL , ptrL ). • I is an invocation of DoAddCell if and only if e is an L-add event. • I is an invocation of DoRemoveCell if and only if e is an L-remove event. • I is an invocation of DoApply&CopyResponse if and only if e is an L-apply event. We call e the corresponding L-event of I. For convenience, we sometimes call e the corresponding L-event of a step during I performed by the process that invoked I. We now prove that L-events appear in the expected order for a given pointer. Lemma C.1.38. Every L-apply event for ptr in I B is preceded by an L-add event for ptr. Proof. Consider any L-apply event e for ptr in I B . Hence, by Lemma C.1.28, ptr ∈ C. Let p be the process that executed e. We prove two intermediate claims. Claim C.1.38.1. Some process q found the condition on line 13 to be false at some time Tq13 < e during some invocation of the DoLowLevelOp procedure with parameters (AddCell, ptr). Proof. Since e is an L-apply event for ptr, by Corollary C.1.24, there is an A-apply event e′ for ptr before e; say by process q. Thus, by Definition C.1.5, q executed e′ during an invocation I of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr). Let I hlo be the invocation of the DoHighLevelOp procedure that q invoked I during. So, q invoked I on line 4 during I hlo . Hence, before q invoked I, q invoked and exited the DoLowLevelOp procedure on line 3 during I hlo ; let I ′ denote this invocation. Thus, since I has parameters (∗, ptr), it follows that I ′ has parameters (AddCell, ptr). Since q exited I ′ , we have that q found the condition on line 13 to be false during I ′ ; say at time Tq13 . Therefore, since q executed the step at Tq13 during I ′ , q exited I ′ before invoking I, q executed e′ during I, and e′ < e, by transitivity, Tq13 < e. Claim C.1.38.1 Claim C.1.38.2. Let Tq12 be the time of q’s last execution of line 12 before Tq13 . Then, there is a successful add-response-set attempt for ptr during (Tq12 , Tq13 ).

46

Proof. Since q executed the step at Tq13 during some invocation Iq of the DoLowLevelOp procedure with parameters (AddCell, ptr) and q’s step at Tq12 is its last execution of line 12 before Tq13 , we have that q’s step at Tq12 is during Iq . Hence, since Iq ’s parameters are (AddCell, ptr) and Tq12 is during Iq , we have that q set the value of (∗ptr).response = ((∗, AddCell), Null) at Tq12 . Since q found the condition on line 13 to be false during Iq at Tq13 , we have that (∗ptr).response ̸= ((∗, AddCell), Null) at Tq13 . Hence, since (∗ptr).response = ((∗, AddCell), Null) at Tq12 , and Tq12 < Tq13 , the value of (∗ptr).response changed during (Tq12 , Tq13 ). Thus, by Observation C.1.6, a response-reset event for ptr or a successful response-set attempt for ptr changed (∗ptr).response during (Tq12 , Tq13 ). Let a be the first step that changed (∗ptr).response during (Tq12 , Tq13 ). Case 1. a is a response-reset event for ptr. Hence, by Definition C.1.5, a set (∗ptr).response = (∗, Null) on line 12. Thus, some process r executed a during an invocation Ir of the DoLowLevelOp procedure with parameters (∗, ptr). Hence, r received ptr as a response on line 2 during the invocation Irhlo of the DoHighLevelOp procedure in which r invoked Ir during. Let Iqhlo be the invocation of the DoHighLevelOp procedure in which q invoked Iq during. Since the second parameter of Iq is ptr, it follows that q received ptr as a response on line 2 during Iqhlo . Thus, since by Algorithm 4 the response of every AllocateCell operation is unique, we have that q = r and Iqhlo = Irhlo . Therefore, since a is an execution of line 12 and is during (Tq12 , Tq13 ), q executed line 12 during the loop on line 13 during Iq . However, q must exit the loop on line 13 to execute line 12, a contradiction, so this case is impossible. Case 2. a is a successful response-set attempt for ptr. Hence, by Definition C.1.5, a is an execution of line 77. Thus, since by definition a is the first step that changed (∗ptr).response during (Tq12 , Tq13 ), and as established above (∗ptr).response = ((∗, AddCell), Null) at Tq12 , it follows that the first parameter of a is ((∗, AddCell), Null) (if it was anything else a would not be successful). Hence, by Definition C.1.5, a is an add-responseset attempt for ptr. Therefore, since a is successful and is during (Tq12 , Tq13 ), we have that a is a successful add-response-set attempt for ptr during (Tq12 , Tq13 ) as required. Claim C.1.38.2 We now return to the proof of Lemma C.1.38. Let a be the successful add-response-set attempt for ptr during (Tq12 , Tq13 ) identified by Claim C.1.38.2 and let r be the process that executed a. Since by Claim C.1.38.1 Tq13 < e, by transitivity, a < e. Furthermore, since a is an add-response-set attempt for ptr, by Definition C.1.5, a was executed during an invocation I of the SetResponse procedure with parameters ((∗, AddCell), ptr, ∗). Hence, by Observation C.1.12, I was invoked during an invocation I ′ of the DoAddCell procedure. Thus, since I has parameters ((∗, AddCell), ptr, ∗), it follows that I ′ has parameters ((∗, AddCell), ptr). So, by Corollary C.1.37, there is an L-add e′ for ptr before I ′ was invoked. Hence, since I was invoked during I ′ , a was executed during I, and a < e, by transitivity, e′ < e. Therefore, there is an L-add event for ptr before e. Lemma C.1.38 Lemma C.1.39. Every L-remove event for ptr in I B is preceded by an L-apply event for ptr. Proof. By essentially the same argument as Lemma C.1.38, which we provide below for completeness. Consider any L-remove event e for ptr in I B . Hence, by Lemma C.1.28, ptr ∈ C. Let p be the process that executed e. We prove two intermediate claims. Claim C.1.39.1. Some process q found the condition on line 13 to be false at some time Tq13 < e during some invocation of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr).

47

Proof. Since e is an L-remove event for ptr, by Corollary C.1.24, there is an A-remove event e′ for ptr before e; say by process q. Thus, by Definition C.1.5, q executed e′ during an invocation I of the DoLowLevelOp procedure with parameters (RemoveCell, ptr). Let I hlo be the invocation of the DoHighLevelOp procedure that q invoked I during. So, q invoked I on line 6 during I hlo . Hence, before q invoked I, q invoked and exited the DoLowLevelOp procedure on line 4 during I hlo ; let I ′ denote this invocation. Thus, since I has parameters (∗, ptr), it follows that I ′ has parameters (⟨Apply&CopyResponse, ∗⟩, ptr). Since q exited I ′ , we have that q found the condition on line 13 to be false during I ′ ; say at time Tq13 . Therefore, since q executed the step at Tq13 during I ′ , q exited I ′ before invoking I, q executed e′ during I, and e′ < e, by transitivity, Tq13 < e. Claim C.1.39.1 Claim C.1.39.2. Let Tq12 be the time of q’s last execution of line 12 before Tq13 . Then, there is a successful apply-response-set attempt for ptr during (Tq12 , Tq13 ). Proof. Since q executed the step at Tq13 during some invocation Iq of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr) and q’s step at Tq12 is its last execution of line 12 before Tq13 , we have that q’s step at Tq12 is during Iq . Hence, since Iq ’s parameters are (⟨Apply&CopyResponse, ∗⟩, ptr) and Tq12 is during Iq , we have that q set the value of (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at Tq12 . Since q found the condition on line 13 to be false at Tq13 , we have that (∗ptr).response ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at Tq13 . Hence, since (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at Tq12 , and Tq12 < Tq13 , the value of (∗ptr).response changed during (Tq12 , Tq13 ). Thus, by Observation C.1.6, a response-reset event for ptr or a successful response-set attempt for ptr changed (∗ptr).response during (Tq12 , Tq13 ). Let a be the first step that changed (∗ptr).response during (Tq12 , Tq13 ). Case 1. a is a response-reset event for ptr. Hence, by Definition C.1.5, a set (∗ptr).response = (∗, Null) on line 12. Thus, some process r executed a during an invocation Ir of the DoLowLevelOp procedure with parameters (∗, ptr). Hence, r received ptr as a response on line 2 during the invocation Irhlo of the DoHighLevelOp procedure in which r invoked Ir during. Let Iqhlo be the invocation of the DoHighLevelOp procedure in which q invoked Iq during. Since the second parameter of Iq is ptr, it follows that q received ptr as a response on line 2 during Iqhlo . Thus, since by Algorithm 4 the response of every AllocateCell operation is unique, we have that q = r and Iqhlo = Irhlo . Therefore, since a is an execution of line 12 and is during (Tq12 , Tq13 ), q executed line 12 during the loop on line 13 during Iq . However, q must exit the loop on line 13 to execute line 12, a contradiction, so this case is impossible. Case 2. a is a successful response-set attempt for ptr. Hence, by Definition C.1.5, a is an execution of line 77. Thus, since by definition a is the first step that changed (∗ptr).response during (Tq12 , Tq13 ), and as established above (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at Tq12 , it follows that the first parameter of the CAS operation a performs is ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) (if it was anything else a would not be successful). Hence, by Definition C.1.5, a is an apply-response-set attempt for ptr. Therefore, since a is successful and is during (Tq12 , Tq13 ), we have that a is a successful apply-response-set attempt for ptr during (Tq12 , Tq13 ) as required. Claim C.1.39.2 We now return to the proof of Lemma C.1.39. Let a be the successful apply-response-set attempt for ptr during (Tq12 , Tq13 ) identified by Claim C.1.39.2 and let r be the process that executed a. Since by Claim C.1.39.1 Tq13 < e, by transitivity, a < e. Furthermore, since a is an apply-response-set attempt for ptr, by Definition C.1.5, a was executed during an invocation I of the SetResponse procedure with parameters ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr, ∗). Hence, by Observation C.1.12, 48

I was invoked during an invocation I ′ of the DoApply&CopyResponse procedure. Thus, since I has parameters (∗, ptr, ∗), it follows that I ′ has parameters (∗, ptr). So, since I ′ is an invocation of the DoApply&CopyResponse procedure, by Corollary C.1.37, there is an L-apply event e′ for ptr before I ′ was invoked. Hence, since I was invoked during I ′ , a was executed during I, and a < e, by transitivity, e′ < e. Therefore, there is an L-apply event for ptr before e. Lemma C.1.39 Lemma C.1.38 and Lemma C.1.39 imply the following. Corollary C.1.40. Every L-remove event for ptr in I B is preceded by an L-add event for ptr. We now prove two properties about successive L-events. Lemma C.1.41. For every two successive L-events e and e′ in I B , the process that executed e′ read the value that e set L to on its last execution of line 14 before e′ . Proof. Suppose, for contradiction, the process p that executed e′ read a different value v ′ on its last execution of line 14 before e′ such that v ′ ̸= v where e set L to v. Since p read v ′ from L on its last execution of line 14 before e′ and e′ is a successful CAS operation on line 25, the value of L at the step before e′ is v ′ . Hence, since e < e′ , and e set L to v ̸= v ′ , the value stored in L changed during (e, e′ ). Therefore, by Observation C.1.6, there is an L-event during (e, e′ ). However, this contradicts the fact that e and e′ are successive L-events. Lemma C.1.41 B be any implementation history of B such that I B is a prefix of I B . Lemma C.1.42. Let I+ + ′ B such that e is in I B . Lastly, let p be the Furthermore, let e and e be any successive L-events in I+ process that executed e′ . If P (I B ) holds, then p’s last execution of line 14 before e′ is after e.

Proof. Suppose, for contradiction, T 14 < e where T 14 is the time of p’s last execution of line 14 before e′ . Let v be the value e sets L to. Hence, by Corollary C.1.27, v is not the initial value of L. Since e and e′ are successive L-events, by Lemma C.1.41, p read v on line 14 at T 14 . Hence, since v is not the initial value of L and T 14 < e, we have that some step before T 14 set L to v. Thus, by Observation C.1.6, some L-event e∗ before T 14 set L to v. Hence, since T 14 < e, by transitivity, e∗ < e, and so e∗ ̸= e. Furthermore, since e is in I B and e∗ < e, we have that e∗ is in I B . Therefore, e and e∗ are two L-events in I B that set L to v. However, since by assumption P (I B ) holds, by Lemma C.1.30, every L-event in I B sets L to a unique value, a contradiction. Lemma C.1.42 We now prove some facts about S-attempts. Lemma C.1.43. Consider an S-attempt a which attempts to set S.ullo to some value v in I B during some invocation I of the DoApply&CopyResponse procedure. Then, a’s corresponding L-event is an L-apply event which set L.ullo to v before I was invoked. Proof. Since a tries to set S.ullo to v, by Definition C.1.5, the process that executed a did so during an invocation of the DoApply&CopyResponse procedure with a first parameter of v. Therefore, by Corollary C.1.37, the claim follows. Lemma C.1.43 By Definition C.1.5, this implies the following. Corollary C.1.44. Consider a S-attempt a in I B and let e be its corresponding L-event. Then, a is for timestamp t if and only if e is for timestamp t. Lemma C.1.45. Every S-attempt in I B is for a timestamp larger than 0.

49

Proof. Consider any S-attempt a for some timestamp t. Let e be a’s corresponding L-event. By Corollary C.1.44 e is for timestamp t. Hence, by Lemma C.1.26 t > 0 as wanted. Lemma C.1.45 We now prove some facts about list-attempts. Lemma C.1.46. Every list-add, list-seal, and list-remove attempt in I B is for some pointer in C. Proof. Consider any list-add attempt a for some ptr. Hence, by Definition C.1.5, a occurred during an invocation of the DoAddCell procedure with parameters (∗, ptr). Thus, by Corollary C.1.37, there is an L-add event for ptr in I B . Therefore, by Lemma C.1.28, ptr ∈ C. Now, consider any list-seal or list-remove attempt a for some ptr. Hence, by Definition C.1.5, a occurred during an invocation of the DoRemoveCell procedure with parameters (∗, ptr). Thus, by Corollary C.1.37, there is an L-remove event for ptr in I B . Therefore, by Lemma C.1.28, ptr ∈ C. Lemma C.1.46 The next few statements show that pointer fields and variables contain legitimate pointer values. Lemma C.1.47. For every ptr ∈ C ∪ {&H}, if (∗ptr).next.ptr = next ptr at any time in I B , then next ptr ∈ C ∪ {Null}. Proof. Suppose, for contradiction, there exists a ptr ∈ C ∪ {&H} such that at some time T in I B (∗ptr).next.ptr = next ptr for some next ptr ∈ / C ∪ {Null}. Without loss of generality, suppose T is the first time the lemma is violated for any pointer in C ∪ {&H}. Since (∗ptr).next.ptr is initially Null, (∗ptr).next.ptr = next ptr ̸= Null at T , and T is the first time the lemma is violated in I B , it follows that the step at T sets the value of (∗ptr).next.ptr to next ptr. Hence, by Observation C.1.6, the step at T is either a successful list-add attempt for next ptr after ptr or a successful list-remove attempt between ptr and next ptr. We consider each case separately. Case 1. The step at T is a successful list-add attempt for next ptr after ptr. / C ∪ {Null}. Therefore, by Lemma C.1.46, next ptr ∈ C, contradicting next ptr ∈ Case 2. The step at T is a successful list-remove attempt between ptr and next ptr. Suppose this step is for ptr′ . Hence, by Lemma C.1.46, ptr′ ∈ C. Let p be the process that performed the step at T . Hence, p read next ptr from (∗ptr′ ).next.ptr on its last execution of line 56 before T . Therefore, since ptr′ ∈ C and p read next ptr from (∗ptr′ ).next.ptr before T , by the minimality of T , next ptr ∈ C ∪ {Null}. However, next ptr ∈ / C ∪ {Null}, a contradiction. Lemma C.1.47 Lemma C.1.48. Let I be any invocation of the DoAddCell procedure in I B by some process p and let T 29 be the time p executed line 29 during I (assuming p does). At all times at or after T 29 and before I returns, the value of the local variable curr ptr in I is in C ∪ {&H}. Proof. Suppose, for contradiction, there is a time T at or after T 29 and before I returns (if it ever does) such that the value of the local variable curr ptr in I is ptr ∈ / C ∪ {&H}. Without loss of generality, suppose T is the first such time. Since p executed line 29 at T 29 during I, the value of / C ∪ {&H} at T ≥ T 29 , it follows curr ptr is &H at T 29 . Hence, since the value of curr ptr is ptr ∈ that the value of curr ptr was set to ptr at T . Thus, since the value of curr ptr only changes on line 40 after T 29 during I, we have that p set curr ptr to ptr by executing line 40 at T . So, the value of the local variable next ptr in I is ptr at T . Therefore, the response of the invocation I ′ of the AcquireNext procedure on line 31 during the same iteration of the while loop on line 30 as T is (Found, ptr). Let T 31 be the time p invoked I ′ , and let ptr′ be the second parameter of I ′ . Hence, the value of curr ptr is ptr′ at T 31 . Thus, since p invoked I ′ at T 31 strictly before T , by the minimality of T , ptr′ ∈ C ∪ {&H}. Since the second parameter of I ′ is ptr′ , and the response of 50

I ′ is (Found, ptr), it follows that p read ptr from (∗ptr′ ).next.ptr on the last execution of line 104 during I ′ ; say at time T 104 . Hence, since ptr′ ∈ C ∪ {&H}, by Lemma C.1.47, ptr ∈ C ∪ {Null}. Therefore, since ptr ∈ / C ∪ {&H}, we have that ptr = Null. However, since p exited I ′ with response (Found, ptr), we have that p found the clause on line 107 to be false on its last execution of line 107 during I ′ , and since p read ptr from (∗ptr′ ).next.ptr on its last execution of line 104 during I ′ , this implies that ptr ̸= Null, a contradiction. Lemma C.1.48 Lemma C.1.49. Every list-add attempt in I B is after some pointer in C ∪ {&H}. Proof. Consider any list-add attempt a for any pointer after some pointer ptr by some process p. Let I be the invocation of the DoAddCell procedure that p executed a during. Hence, p executed line 29 before a during I. Furthermore, since a is a list-add attempt after ptr, the value of the local variable curr ptr in I is ptr at a. Therefore, by Lemma C.1.48 ptr ∈ C ∪ {&H}, and so a is after some pointer in C ∪ {&H} as wanted. Lemma C.1.49 Below, we bound the domain of values that a list-remove attempt can be between. Lemma C.1.50. Let I be any invocation of the DoRemoveCell procedure in I B by some process p and let T 45 be the time p executed line 45 during I (assuming p does). At all times at or after T 45 and before I returns, the value of the local variable curr ptr in I is in C ∪ {&H}. Proof. By essentially the same argument as Lemma C.1.48, which we provide below for completeness. Suppose, for contradiction, there is a time T at or after T 45 and before I returns (if it ever does) such that the value of the local variable curr ptr in I is ptr ∈ / C ∪ {&H}. Without loss of generality, suppose T is the first such time. Since p executed line 45 at T 45 during I, the value of curr ptr is &H at T 45 . Hence, since the value of curr ptr is ptr ∈ / C ∪ {&H} at T ≥ T 45 , it follows that the value of curr ptr was set to ptr at T . Thus, since the value of curr ptr only changes on line 52 after T 45 during I, we have that p set curr ptr to ptr by executing line 52 at T . So, the value of the local variable next ptr in I is ptr at T . Therefore, the response of the invocation I ′ of the AcquireNext procedure on line 47 during the same iteration of the while loop on line 46 as T is (Found, ptr). Let T 47 be the time p invoked I ′ , and let ptr′ be the second parameter of I ′ . Hence, the value of curr ptr is ptr′ at T 47 . Thus, since p invoked I ′ at T 47 strictly before T , by the minimality of T , ptr′ ∈ C ∪ {&H}. Since the second parameter of I ′ is ptr′ , and the response of I ′ is (Found, ptr), it follows that p read ptr from (∗ptr′ ).next.ptr on the last execution of line 104 during I ′ ; say at time T 104 . Hence, since ptr′ ∈ C ∪ {&H}, by Lemma C.1.47, ptr ∈ C ∪ {Null}. Therefore, since ptr ∈ / C ∪ {&H}, we have that ptr = Null. However, since p exited I ′ with response (Found, ptr), we have that p found the clause on line 107 to be false on its last execution of line 107 during I ′ , and since p read ptr from (∗ptr′ ).next.ptr on its last execution of line 104 during I ′ , this implies that ptr ̸= Null, a contradiction. Lemma C.1.50 Lemma C.1.51. Let I be any invocation of the DoRemoveCell procedure in I B by some process p and let T 52 be the first time p executed line 52 during I (assuming p does). At all times at or after T 52 and before I returns, the value of the local variable prev ptr in I is in C ∪ {&H}. Proof. Suppose I is an invocation of the DoRemoveCell procedure by some process p and T 52 is the first time p executed line 52 during I. Hence, p executed line 45 before T 52 ; say at time T 45 < T 52 . Thus, by Lemma C.1.50 at all times at or after T 45 and before I returns, the value of the local variable curr ptr in I is in C ∪ {&H}. Therefore, since every time p sets the value of prev ptr at or after T 52 during I it is to the value of curr ptr (see line 52) the claim follows. Lemma C.1.51 This implies the following. 51

Corollary C.1.52. Let I be any invocation of the DoRemoveCell procedure in I B by some process p and let T 45 be the time p executed line 45 during I (assuming p does). At all times at or after T 45 and before I returns, the value of the local variable prev ptr in I is in C ∪ {&H, Null}. Lemma C.1.53. Every list-remove attempt in I B is between some pointer in C ∪ {&H} and some pointer in C ∪ {Null}. Proof. Consider any list-remove attempt a for some ptr between some prev ptr and some next ptr. Hence, by Lemma C.1.46, ptr ∈ C, so by Assumption C.1.2 ptr ̸= &H. Furthermore, by Definition C.1.5, some process p executed a during some invocation I of the DoRemoveCell procedure with parameters (∗, ptr). Since the value of the local variable curr ptr is initially &H in I, and ptr ̸= &H, we have that p found the condition on line 46 to be true at least once in I. Hence, since p executes line 61 in I (because p executed a during I), we have that p executes line 52 at least once in I; say at time T 52 . Thus, by Lemma C.1.51, the value of the local variable prev ptr in I is in C ∪ {&H} at all times from T 52 until I returns (if ever). Therefore, since a is a list-remove attempt between prev ptr and next ptr, and p executed a during I, we have that prev ptr is the value of the local variable prev ptr at a during I, and since a is after T 52 , we have that prev ptr ∈ C ∪ {&H} as wanted. Furthermore, since a is a list-remove attempt for ptr between prev ptr and next ptr, we have that p read next ptr from (∗ptr).next.ptr on its last execution of line 56 before executing a in I, and so since ptr ̸= &H, by Lemma C.1.47, next ptr ∈ C ∪ {Null}. Lemma C.1.53 We now prove that invariants P and Q imply some useful facts about list-add and list-remove attempts. Lemma C.1.54. Let a1 and a2 be two list-add attempts for some ptr in I B . If Q(I B ) holds, then a1 and a2 are after the same curr ptr. Proof. Suppose a1 (resp. a2 ) is after curr ptr1 (resp. curr ptr2 ). Hence, since a1 (resp. a2 ) is a list-add attempts for ptr, by Q(I B ), there is a unique L-add event e for ptr before a1 (resp. a2 ), thus e is the same for a1 and a2 , and if I is the prefix of I B up to but excluding e, curr ptr1 (resp. curr ptr2 ) is the second last pointer in List(I). Therefore, curr ptr1 = curr ptr2 . Lemma C.1.54 Lemma C.1.55. Let a be a list-add attempt for some ptr after some curr ptr in I B . If P (I B ) and Q(I B ) hold, then curr ptr ̸= ptr. Proof. Suppose, for contradiction, curr ptr = ptr. Since a is a list-add attempt for ptr, by Lemma C.1.46 ptr ∈ C. Furthermore, by Q(I B ), there is a unique L-add event e for ptr before a, and if I is the prefix of I B up to but excluding e, then curr ptr is the second last pointer in List(I). Hence, since curr ptr = ptr, we have that ptr is the second last pointer in List(I). Thus, since ptr ∈ C, by Assumption C.1.2 ptr ̸= &H, and so by the definition of List(I) (see Definition C.1.7), there is an L-add event e′ for ptr in I. Hence, since e is an L-add event for ptr, and I is the prefix of I B up to but excluding e, it follows that e ̸= e′ . Therefore, since both e and e′ are L-add events for ptr in I B , there are two L-add events for ptr in I B . However, since ptr ∈ C, by P (I B ), there is at most one L-add event for ptr in I B , a contradiction. Lemma C.1.55 Lemma C.1.56. Let a1 and a2 be two list-remove attempts for some ptr in I B . If Q(I B ) holds, then a1 and a2 are between the same prev ptr and next ptr. Proof. Suppose a1 (resp. a2 ) is between prev ptr1 (resp. prev ptr2 ) and next ptr1 (resp. next ptr2 ). Hence, since a1 (resp. a2 ) is a list-remove attempts for ptr, by Q(I B ), there is a unique L-remove event e for ptr before a1 (resp. a2 ), thus e is the same for a1 and a2 , and if I is the prefix of 52

I B up to but excluding e, ptr is in List(I) exactly once, and prev ptr1 (resp. prev ptr2 ) and next ptr1 (resp. next ptr2 ) are the pointers preceding and succeeding ptr in List(I). Therefore prev ptr1 = prev ptr2 and next ptr1 = next ptr2 as wanted. Lemma C.1.56 Lemma C.1.57. Let a be a list-remove attempt for some ptr between some prev ptr and some next ptr in I B . If P (I B ) and Q(I B ) hold, then prev ptr, ptr, and next ptr are distinct. Proof. Suppose, for contradiction, either prev ptr = ptr, ptr = next ptr, or prev ptr = next ptr. Since a is a list-remove attempt for ptr between prev ptr and next ptr, by Lemma C.1.46 ptr ∈ C and by Lemma C.1.53 prev ptr ∈ C ∪ {&H} and next ptr ∈ C ∪ {Null}. Hence, since a is in I B , by Q(I B ), there is a unique L-remove event e for ptr before a, and if I is the prefix of I B up to but excluding e, then ptr ∈ List(I) exactly once and prev ptr and next ptr are the pointers preceding and succeeding ptr in List(I). We prove that some ptr∗ ∈ C occurs twice in List(I). There are two cases. Case 1. prev ptr = ptr or ptr = next ptr. Hence, since prev ptr is the pointer preceding ptr in List(I), and next ptr is the pointer succeeding ptr in List(I), we have that ptr occurs twice in List(I) and is in C. Case 2. prev ptr = next ptr. Since prev ptr ∈ C ∪ {&H}, next ptr ∈ C ∪ {Null}, and by Assumption C.1.2 &H ̸= Null, we have that prev ptr ∈ C. Hence, since prev ptr is the pointer preceding ptr in List(I), and next ptr is the pointer succeeding ptr in List(I), we have that prev ptr occurs twice in List(I) and is in C. We now finish the proof of Lemma C.1.57. Since ptr∗ ∈ C, by Assumption C.1.2, ptr∗ ̸= &H and ptr∗ ̸= Null. Thus, since ptr∗ occurs twice in List(I), by the definition of List(I) (see Definition C.1.7), there are two L-add events for ptr∗ in I. Therefore, since I is a prefix of I B , there are two L-add events for ptr∗ in I B . However, since ptr∗ ∈ C, by P (I B ), there is at most one L-add event for ptr∗ in I B , a contradiction. Lemma C.1.57 Lastly, we prove some facts relating list-add and list-remove attempts with list-seal attempts. Lemma C.1.58. Consider any list-remove attempt aremove for ptr in I B . Let p be the process that executed aremove and let T 56 be the time of p’s last execution of line 56 before aremove . There is a successful list-seal attempt for ptr before T 56 in I B . Proof. By Lemma C.1.46, ptr ∈ C. Let I be the invocation of the DoRemoveCell procedure that p executed aremove during. Since aremove is a list-remove attempt for ptr during I, by Definition C.1.5, the second parameter of I is ptr. Furthermore, since p executed aremove during I, p found the condition on line 53 to be false before T 56 during I. Hence, since the second parameter of I is ptr, we have that (∗ptr).next.sealed ̸= False at some time T before T 56 . Thus, since ptr ∈ C, we have that (∗ptr).next.sealed is initially False, and so (∗ptr).next.sealed was changed before T . Hence, by Observation C.1.6, there is a successful list-seal attempt for ptr before T . Therefore, since T < T 56 , there is a successful list-seal attempt for ptr before T 56 in I B . Lemma C.1.58 Lemma C.1.59. Consider any successful list-seal attempt aseal for ptr in I B . By Lemma C.1.46, curr ptr ∈ C. Then, from aseal onwards in I B (∗curr ptr).next.sealed = True. Proof. By Definition C.1.5, aseal sets (∗curr ptr).next.sealed = True. Hence, since curr ptr ∈ C, by Observation C.1.6, the only steps that change the value of (∗curr ptr).next.sealed are successful list-sealed attempts for curr ptr, and since every successful list-sealed attempt for curr ptr sets (∗curr ptr).next.sealed = True, the claim follows. Lemma C.1.59 53

Lemma C.1.60. Consider any successful list-add attempt aadd after curr ptr in I B . There are no successful list-seal attempts for curr ptr before aadd in I B . Proof. Suppose, for contradiction, there is a successful list-seal attempt aseal for curr ptr before aadd in I B . By Lemma C.1.59, from aseal onwards in I B (∗curr ptr).next.sealed = True. Therefore, since aseal < aadd , we have that (∗curr ptr).next.sealed = True at aadd . However, since aadd is a successful list-add attempt after curr ptr, it follows that (∗curr ptr).next.sealed = False at aadd , a contradiction. Lemma C.1.60 Lemma C.1.61. Consider any successful list-remove attempt aremove between curr ptr and some pointer in I B . There are no successful list-seal attempts for curr ptr before aremove in I B . Proof. Suppose, for contradiction, there is a successful list-seal attempt aseal for curr ptr before aremove in I B . By Lemma C.1.59, from aseal onwards in I B (∗curr ptr).next.sealed = True. Therefore, since aseal < aremove , we have that (∗curr ptr).next.sealed = True at aremove . However, since aremove is a successful list-remove attempt between curr ptr and some pointer, it follows that (∗curr ptr).next.sealed = False at aremove , a contradiction. Lemma C.1.60 C.1.3

Response-reset events and response-set attempts

We now prove some facts about response-reset events. Lemma C.1.62. Every response-reset event in I B is for some pointer in C and is either an addresponse-reset, apply-response-reset, or remove-response-reset event. Proof. Consider any response-reset event e for some ptr by some process p. By Definition C.1.5, e is an execution of line 12 during some invocation I of the DoLowLevelOp procedure with a second parameter of ptr. Thus, since this procedure is only invoked on lines 3, 4, and 6, p performed an AllocateCell whose response is ptr before invoking I. Therefore, by Algorithm 4, ptr ∈ C. Now suppose e sets the value of (∗ptr).response = (ullo, Null). By line 11, ullo = (∗, llo) where llo is the first parameter of I. Hence, e set (∗ptr).response = ((∗, llo), Null). Since DoLowLevelOp is only invoked on lines 3, 4, and 6, llo is either AddCell, ⟨Apply&CopyResponse, ∗⟩, or RemoveCell. Therefore, by Definition C.1.5, e is either an add-response-reset, apply-responsereset, or remove-response-reset event as wanted. Lemma C.1.62 Proposition C.1.63. There is at most one add-response-reset event for ptr in I B . Proof. Suppose, for contradiction, there is more than one add-response-reset event for some ptr. Let e1 and e2 be two add-response-reset events for ptr and let p1 (resp. p2 ) be the process that executed e1 (resp. e2 ). Hence, by Definition C.1.5, p1 and p2 executed e1 and e2 in an invocation of the DoLowLevelOp procedure with parameters (AddCell, ptr). Let I1 (resp I2 ) be the invocation the DoLowLevelOp procedure that p1 (resp. p2 ) executed e1 (resp. e2 ) during. Furthermore, let I1hlo (resp. I2hlo ) be the invocation of the DoHighLevelOp procedure that p1 (resp. p2 ) invoked I1 (resp. I2 ) during. Since the the second parameter of I1 and I2 is ptr, it follows that p1 and p2 both performed an AllocateCell operation on line 2 whose response is ptr during I1hlo and I2hlo , and since by Algorithm 4 the response of every AllocateCell operation is unique, we have that p1 = p2 and I1hlo = I2hlo . Hence, since the first parameter of I1 and I2 is AddCell, I1 and I2 are invoked by the same process, and I1 and I2 are both invoked during the same invocation of the DoHighLevelOp procedure, it follows that I1 = I2 . Thus, e1 and e2 are performed during the same invocation of the DoLowLevelOp procedure. Therefore, since there is at most one response-reset event per invocation of the DoLowLevelOp procedure (because line 12 is executed at most once), we have that e1 = e2 . However, e1 ̸= e2 , a contradiction. Proposition C.1.63 54

Proposition C.1.64. There is at most one apply-response-reset event for ptr in I B . Proof. By essentially the same argument as Proposition C.1.63, which we provide below for completeness. Suppose, for contradiction, there is more than one apply-response-reset event for some ptr. Let e1 and e2 be two apply-response-reset events for ptr and let p1 (resp. p2 ) be the process that executed e1 (resp. e2 ). Hence, by Definition C.1.5, p1 and p2 executed e1 and e2 in an invocation of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr). Let I1 (resp I2 ) be the invocation the DoLowLevelOp procedure that p1 (resp. p2 ) executed e1 (resp. e2 ) during. Furthermore, let I1hlo (resp. I2hlo ) be the invocation of the DoHighLevelOp procedure that p1 (resp. p2 ) invoked I1 (resp. I2 ) during. Since the the second parameter of I1 and I2 is ptr, it follows that p1 and p2 both performed an AllocateCell operation on line 2 whose response is ptr during I1hlo and I2hlo , and since by Algorithm 4 the response of every AllocateCell operation is unique, we have that p1 = p2 and I1hlo = I2hlo . Hence, since the first parameter of I1 and I2 is ⟨Apply&CopyResponse, ∗⟩, I1 and I2 are invoked by the same process, and I1 and I2 are both invoked during the same invocation of the DoHighLevelOp procedure, it follows that I1 = I2 . Thus, e1 and e2 are performed during the same invocation of the DoLowLevelOp procedure. Therefore, since there is at most one response-reset event per invocation of the DoLowLevelOp procedure (because line 12 is executed at most once), we have that e1 = e2 . However, e1 ̸= e2 , a contradiction. Proposition C.1.64 Proposition C.1.65. There is at most one remove-response-reset event for ptr in I B . Proof. By essentially the same argument as Proposition C.1.63, which we provide below for completeness. Suppose, for contradiction, there is more than one remove-response-reset event for some ptr. Let e1 and e2 be two remove-response-reset events for ptr and let p1 (resp. p2 ) be the process that executed e1 (resp. e2 ). Hence, by Definition C.1.5, p1 and p2 executed e1 and e2 in an invocation of the DoLowLevelOp procedure with parameters (RemoveCell, ptr). Let I1 (resp I2 ) be the invocation the DoLowLevelOp procedure that p1 (resp. p2 ) executed e1 (resp. e2 ) during. Furthermore, let I1hlo (resp. I2hlo ) be the invocation of the DoHighLevelOp procedure that p1 (resp. p2 ) invoked I1 (resp. I2 ) during. Since the the second parameter of I1 and I2 is ptr, it follows that p1 and p2 both performed an AllocateCell operation on line 2 whose response is ptr during I1hlo and I2hlo , and since by Algorithm 4 the response of every AllocateCell operation is unique, we have that p1 = p2 and I1hlo = I2hlo . Hence, since the first parameter of I1 and I2 is RemoveCell, I1 and I2 are invoked by the same process, and I1 and I2 are both invoked during the same invocation of the DoHighLevelOp procedure, it follows that I1 = I2 . Thus, e1 and e2 are performed during the same invocation of the DoLowLevelOp procedure. Therefore, since there is at most one response-reset event per invocation of the DoLowLevelOp procedure (because line 12 is executed at most once), we have that e1 = e2 . However, e1 ̸= e2 , a contradiction. Proposition C.1.65 By Propositions C.1.63, C.1.64, and C.1.65 we have the following. Corollary C.1.66. There is at most one add-response-reset, apply-response-reset, and removeresponse-reset event for ptr in I B . Proposition C.1.67. Let e be an L-add event for ptr in I B that set L.ullo = ullo. There is exactly one add-response-reset event for ptr before e, and it set (∗ptr).response = (ullo, Null). Proof. By Corollary C.1.66, there is at most one add-response-reset event for ptr before e, so it suffices to prove that there is at least one before e. Since e is an L-add event for ptr that set L.ullo = ullo, by Definition C.1.5, ullo = (∗, AddCell) and e set L to (ullo, ptr). Hence, by 55

Lemma C.1.23, there is an A-event e′ which set A to (ullo, ptr) before e. Thus, by Definition C.1.5, e′ is an execution of either line 21 or 27, and so the process that executed e′ set (∗ptr).response = (ullo, Null) on line 12 before e′ (and thus e by transitivity). Therefore, since ullo = (∗, AddCell), by Definition C.1.5, this is an add-response-reset event for ptr before e as wanted. Proposition C.1.67 Proposition C.1.68. Let e be an L-apply event for ptr in I B that set L.ullo = ullo. There is exactly one apply-response-reset event for ptr before e, and it set (∗ptr).response = (ullo, Null). Proof. By essentially the same argument as Proposition C.1.67, which we provide below for completeness. By Corollary C.1.66, there is at most one apply-response-reset event for ptr before e, so it suffices to prove that there is at least one before e. Since e is an L-apply event for ptr that set L.ullo = ullo, by Definition C.1.5, ullo = (∗, ⟨Apply&CopyResponse, ∗⟩) and e set L to (ullo, ptr). Hence, by Lemma C.1.23, there is an A-event e′ which set A to (ullo, ptr) before e. Thus, by Definition C.1.5, e′ is an execution of either line 21 or 27, and so the process that executed e′ set (∗ptr).response = (ullo, Null) on line 12 before e′ (and thus e by transitivity). Therefore, since ullo = (∗, ⟨Apply&CopyResponse, ∗⟩), by Definition C.1.5, this is an apply-response-reset event for ptr before e as wanted. Proposition C.1.68 Proposition C.1.69. Let e be an L-remove event for ptr in I B that set L.ullo = ullo. There is exactly one remove-response-reset event for ptr before e, and it set (∗ptr).response = (ullo, Null). Proof. By essentially the same argument as Proposition C.1.67, which we provide below for completeness. By Corollary C.1.66, there is at most one remove-response-reset event for ptr before e, so it suffices to prove that there is at least one before e. Since e is an L-remove event for ptr that set L.ullo = ullo, by Definition C.1.5, ullo = (∗, RemoveCell) and e set L to (ullo, ptr). Hence, by Lemma C.1.23, there is an A-event e′ which set A to (ullo, ptr) before e. Thus, by Definition C.1.5, e′ is an execution of either line 21 or 27, and so the process that executed e′ set (∗ptr).response = (ullo, Null) on line 12 before e′ (and thus e by transitivity). Therefore, since ullo = (∗, RemoveCell), by Definition C.1.5, this is a remove-response-reset event for ptr before e as wanted. Proposition C.1.69 By Propositions C.1.67, C.1.68, and C.1.69 we have the following. Corollary C.1.70. Let e be an L-X event for ptr in I B where X ∈ {add, apply, remove} that set L.ullo = ullo. There is exactly one X-response-reset event for ptr before e, and it set (∗ptr).response = (ullo, Null). We now prove some facts about response-set attempts. Lemma C.1.71. Let I be any invocation of the SetResponse procedure in I B with parameters (ullo, ptr, ∗). Then, there is an L-event e before I was invoked that set L = (ullo, ptr). Proof. Since some process p invoked I on either line 42, 44, or 73, we have that p invoked I during an invocation I ′ of either the DoAddCell, DoRemoveCell, or DoApply&CopyResponse procedure. Hence, since the parameters of I are (ullo, ptr, ∗), it follows that the parameters of I ′ are (ullo, ptr). Thus, by Corollary C.1.37, there is an L-event e before I ′ was invoked that set L to (ullo, ptr). Therefore, since I ′ was invoked before I, the claim follows. Lemma C.1.71 Proposition C.1.72. Every response-set attempt in I B is for some pointer in C.

56

Proof. Consider any response-set attempt a for ptr in I B . Hence, by Definition C.1.5, a was executed during some invocation I of the SetResponse procedure with parameters (∗, ptr, ∗). Thus, by Lemma C.1.71, there is an L-event for ptr. Therefore, by Lemma C.1.28, ptr ∈ C as wanted. Proposition C.1.72

Lemma C.1.73. Consider any response-set attempt a for ptr, so by Proposition C.1.72 ptr ∈ C, which tries to set (∗ptr).response.ullo to some value v in I B . Then, there is an L-event which set L to (v, ptr) before a. We call the last L-event which set L to (v, ptr) before a, a’s corresponding L-event. Proof. Consider any response-set attempt a for ptr by some process p which attempts to set the value of (∗ptr).response.ullo to v. Hence, by Definition C.1.5, p executed a during some invocation of the SetResponse procedure with parameters (v, ptr, ∗). Thus, by Lemma C.1.71, there is an L-event before this invocation was invoked that set L = (v, ptr). Lemma C.1.73 By Definition C.1.5, this implies the following. Corollary C.1.74. Consider a response-set attempt a for ptr in I B and let e be its corresponding L-event. The following are true. • e is for ptr. • a is an add-response-set attempt if and only if e is an L-add event. • a is an apply-response-set attempt if and only if e is an L-apply event. • a is an remove-response-set attempt if and only if e is an L-remove event. Lemma C.1.75. Every response-set attempt in I B is for some pointer in C and is either an addresponse-set, apply-response-set, or remove-response-set attempt. Proof. Consider any response-set attempt a for ptr in I B and let e be its corresponding L-event (see Lemma C.1.73). Hence, by Corollary C.1.74, e is for ptr, and so by Lemma C.1.28 ptr ∈ C. Furthermore, since by Lemma C.1.29 e is either an L-add, L-apply, or L-remove event, by Corollary C.1.74, a is either an add-response-set, apply-response-set, or remove-response-set attempt. Lemma C.1.75 Lemma C.1.76. If there is a X-response-set attempt for ptr in I B where X ∈ {add, apply, remove}, then there is a X-response-reset event for ptr beforehand. Proof. Consider any X-response-set attempt a for ptr in I B . Hence, by Corollary C.1.74, there is an L-X event e for ptr before a. Thus, by Corollary C.1.70, there is an X-response-reset event for ptr before e. Therefore, since e is before a, the claim follows. Lemma C.1.76 Lemma C.1.77. Every response-set attempt in I B is to a response other than Null. Proof. Consider any response-set attempt a to response r by some process p. Hence, by Definition C.1.5, p executed a during some invocation I of the SetResponse procedure with parameters (∗, ∗, r). Since p invoked I on either line 42, 44, or 73, we have that r is Done or the value of S.resp. Hence, since S.resp is initially ⊥ and is only set to the right field of the response of applyT , we have that r is either Done, ⊥, or some response to an operation of type T . Therefore, by Assumption C.1.3, r ̸= Null as wanted. Lemma C.1.77 Proposition C.1.78. There is at most one successful add-response-set attempt for ptr in I B .

57

Proof. Suppose, for contradiction, there is more than one successful add-response-set attempt for ptr. Hence, by Lemma C.1.75, ptr ∈ C. Let a1 and a2 be two successful add-response-set attempts for ptr. Without loss of generality, suppose a1 < a2 . Hence, since ptr ∈ C, by Lemma C.1.77, a1 sets (∗ptr).response ̸= (∗, Null). Furthermore, since a2 is a successful add-response-set attempt, by Definition C.1.5, (∗ptr).response = (ullo, Null) at the step before a2 where ullo = (∗, AddCell). Hence, since a1 < a2 , we have that (∗ptr).response was set to (ullo, Null) between a1 and a2 . Thus, by Observation C.1.6, either a response-reset event or a successful response-set attempt for ptr set (∗ptr).response = (ullo, Null) between a1 and a2 . However, since by Lemma C.1.77 every successful response-set attempt for ptr sets the value of (∗ptr).response ̸= (∗, Null), we have that there is a response-reset event e2 for ptr between a1 and a2 that set (∗ptr).response = (ullo, Null). Hence, since ullo = (∗, AddCell), by Definition C.1.5, e2 is an add-response-reset event for ptr. Since a1 is an add-response-set attempt for ptr, by Lemma C.1.76, there is an add-response-reset event e1 for ptr before a1 . Therefore, since e1 is before a1 , and e2 is between a1 and a2 , it follows that there are two add-response-reset events for ptr in I B . However, by Corollary C.1.66, there is at most one add-response-reset event for ptr in I B , a contradiction. Proposition C.1.78 Proposition C.1.79. There is at most one successful apply-response-set attempt for ptr in I B . Proof. By essentially the same argument as Proposition C.1.78, which we provide below for completeness. Suppose, for contradiction, there is more than one successful apply-response-set attempt for ptr. Hence, by Lemma C.1.75, ptr ∈ C. Let a1 and a2 be two successful apply-responseset attempts for ptr. Without loss of generality, suppose a1 < a2 . Hence, since ptr ∈ C, by Lemma C.1.77, a1 sets (∗ptr).response ̸= (∗, Null). Furthermore, since a2 is a successful applyresponse-set attempt, by Definition C.1.5, (∗ptr).response = (ullo, Null) at the step before a2 where ullo = (∗, ⟨Apply&CopyResponse, ∗⟩). Hence, since a1 < a2 , we have that (∗ptr).response was set to (ullo, Null) between a1 and a2 . Thus, by Observation C.1.6, either a response-reset event or a successful response-set attempt for ptr set (∗ptr).response = (ullo, Null) between a1 and a2 . However, since by Lemma C.1.77 every successful response-set attempt for ptr sets the value of (∗ptr).response ̸= (∗, Null), we have that there is a response-reset event e2 for ptr between a1 and a2 that set (∗ptr).response = (ullo, Null). Hence, since ullo = (∗, ⟨Apply&CopyResponse, ∗⟩), by Definition C.1.5, e2 is an apply-response-reset event for ptr. Since a1 is an apply-responseset attempt for ptr, by Lemma C.1.76, there is an apply-response-reset event e1 for ptr before a1 . Therefore, since e1 is before a1 , and e2 is between a1 and a2 , it follows that there are two apply-response-reset events for ptr in I B . However, by Corollary C.1.66, there is at most one apply-response-reset event for ptr in I B , a contradiction. Proposition C.1.79 Proposition C.1.80. There is at most one successful remove-response-set attempt for ptr in I B . Proof. By essentially the same argument as Proposition C.1.78, which we provide below for completeness. Suppose, for contradiction, there is more than one successful remove-response-set attempt for ptr. Hence, by Lemma C.1.75, ptr ∈ C. Let a1 and a2 be two successful remove-responseset attempts for ptr. Without loss of generality, suppose a1 < a2 . Hence, since ptr ∈ C, by Lemma C.1.77, a1 sets (∗ptr).response ̸= (∗, Null). Furthermore, since a2 is a successful removeresponse-set attempt, by Definition C.1.5, (∗ptr).response = (ullo, Null) at the step before a2 where ullo = (∗, RemoveCell). Hence, since a1 < a2 , we have that (∗ptr).response was set to (ullo, Null) between a1 and a2 . Thus, by Observation C.1.6, either a response-reset event or a successful response-set attempt for ptr set (∗ptr).response = (ullo, Null) between a1 and a2 . However, since by Lemma C.1.77 every successful response-set attempt for ptr sets the value of (∗ptr).response ̸= (∗, Null), we have that there is a response-reset event e2 for ptr between a1 58

and a2 that set (∗ptr).response = (ullo, Null). Hence, since ullo = (∗, RemoveCell), by Definition C.1.5, e2 is a remove-response-reset event for ptr. Since a1 is a remove-response-set attempt for ptr, by Lemma C.1.76, there is a remove-response-reset event e1 for ptr before a1 . Therefore, since e1 is before a1 , and e2 is between a1 and a2 , it follows that there are two remove-response-reset events for ptr in I B . However, by Corollary C.1.66, there is at most one remove-response-reset event for ptr in I B , a contradiction. Proposition C.1.80 By Propositions C.1.78, C.1.79, and C.1.80 we have the following. Corollary C.1.81. There is at most one successful add-response-set, apply-response-set, and remove-response-set attempt for ptr in I B . Lemma C.1.82. For every ptr ∈ C, if there is a successful add-response-set attempt a for ptr during I B , then from a onwards (∗ptr).response ̸= ((∗, AddCell), Null). Proof. Suppose, for contradiction, there is a successful add-response-set attempt a for ptr during I B and (∗ptr).response = ((∗, AddCell), Null) at or after a. Let a be a successful add-responseset attempt to r. By Lemma C.1.77, r ̸= Null. Hence, since a is a successful add-responseset attempt for ptr to r, we have that (∗ptr).response ̸= ((∗, AddCell), Null) at a. Thus, since (∗ptr).response = ((∗, AddCell), Null) at or after a, we have (∗ptr).response was set to ((∗, AddCell), Null) after a. Hence, by Observation C.1.6, either an add-response-reset event for ptr or a successful add-response-set attempt for ptr set (∗ptr).response to ((∗, AddCell), Null) after a. Since by Lemma C.1.77, every add-response-set attempt does not set the response to Null, it cannot be a successful add-response-set attempt that set the value of (∗ptr).response to ((∗, AddCell), Null) after a. Hence, there is an add-response-reset event for ptr after a. Thus, since a is a successful add-response-set attempt for ptr, by Lemma C.1.76, there is an add-responsereset event for ptr before a. Therefore, since there is an add-response-reset event for ptr after a, there are two add-response-reset events for ptr in I B . However, by Corollary C.1.66, there is at most one add-response-reset event for ptr, a contradiction. Lemma C.1.82 Lemma C.1.83. For every ptr ∈ C, if there is a successful apply-response-set attempt a for ptr during I B , then from a onwards (∗ptr).response ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), Null). Proof. By essentially the same argument as Lemma C.1.82, which we provide below for completeness. Suppose, for contradiction, there is a successful apply-response-set attempt a for ptr during I B and (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at or after a. Let a be a successful apply-response-set attempt to r. By Lemma C.1.77, r ̸= Null, and so (∗ptr).response ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at a. Thus, since by assumption (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at or after a, we have (∗ptr).response was set to the value ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) after a. Hence, by Observation C.1.6, either an applyresponse-reset event for ptr or a successful apply-response-set attempt for ptr set (∗ptr).response to ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) after a. Since by Lemma C.1.77, every apply-responseset attempt does not set the response to Null, it cannot be a successful apply-response-set attempt that set the value of (∗ptr).response to ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) after a. Hence, there is an apply-response-reset event for ptr after a. Thus, since a is a successful apply-response-set attempt for ptr, by Lemma C.1.76, there is an apply-response-reset event for ptr before a. Therefore, since there is an apply-response-reset event for ptr after a, there are two apply-response-reset events for ptr in I B . However, by Corollary C.1.66, there is at most one apply-response-reset event for ptr, a contradiction. Lemma C.1.83

59

Lemma C.1.84. For every ptr ∈ C, if there is a successful remove-response-set attempt a for ptr during I B , then from a onwards (∗ptr).response ̸= ((∗, RemoveCell), Null). Proof. By essentially the same argument as Lemma C.1.82, which we provide below for completeness. Suppose, for contradiction, there is a successful remove-response-set attempt a for ptr during I B and (∗ptr).response = ((∗, RemoveCell), Null) at or after a. Let a be a successful removeresponse-set attempt to r. By Lemma C.1.77, r ̸= Null. Hence, since a is a successful removeresponse-set attempt for ptr to r, we have that (∗ptr).response ̸= ((∗, RemoveCell), Null) at a. Thus, since (∗ptr).response = ((∗, RemoveCell), Null) at or after a, we have (∗ptr).response was set to ((∗, RemoveCell), Null) after a. Hence, by Observation C.1.6, either a removeresponse-reset event for ptr or a successful remove-response-set attempt for ptr set (∗ptr).response to ((∗, RemoveCell), Null) after a. Since by Lemma C.1.77, every remove-response-set attempt does not set the response to Null, it cannot be a successful remove-response-set attempt that set the value of (∗ptr).response to ((∗, AddCell), Null) after a. Hence, there is a remove-responsereset event for ptr after a. Thus, since a is a successful remove-response-set attempt for ptr, by Lemma C.1.76, there is a remove-response-reset event for ptr before a. Therefore, since there is a remove-response-reset event for ptr after a, there are two remove-response-reset events for ptr in I B . However, by Corollary C.1.66, there is at most one remove-response-reset event for ptr, a contradiction. Lemma C.1.84 C.1.4

List-acquire-next attempts, acquire-copy events, and revocation events

We now prove some facts about list-acquire-next attempts. Lemma C.1.85. Consider any successful list-acquire-next attempt aacquire after curr ptr in I B . There are no successful list-seal attempts for curr ptr before aacquire in I B . Proof. Suppose, for contradiction, there is a successful list-seal attempt aseal for curr ptr before aacquire in I B . By Lemma C.1.59, from aseal onwards in I B (∗curr ptr).next.sealed = True. Therefore, since aseal < aacquire , we have that (∗curr ptr).next.sealed = True at aacquire . However, since aacquire is a successful list-acquire-next attempt after curr ptr, it follows that (∗curr ptr).next.sealed = False at aacquire , a contradiction. Lemma C.1.85 Lemma C.1.86. Consider any successful list-acquire-next attempt aacquire after curr ptr in I B . There are no successful list-remove attempts for curr ptr before aacquire in I B . Proof. Suppose, for contradiction, there is a successful list-remove attempt aremove for curr ptr before aacquire in I B . Let p be the process that executed aremove and let T 56 be the time of p’s last execution of line 56 before aremove . Hence, by Lemma C.1.58, there is a successful list-seal attempt for curr ptr before T 56 in I B . Therefore, since T 56 < aremove and aremove < aacquire , by transitivity, there is a successful list-seal attempt for curr ptr before aacquire in I B . However, by Lemma C.1.85, there are no successful list-seal attempts for curr ptr before aacquire in I B , a contradiction. Lemma C.1.86 Lemma C.1.87. Consider any successful list-acquire-next attempt aacquire after curr ptr in I B . If R(I B ) holds, and there is an L-remove event for curr ptr before aacquire in I B , then it is the last L-event before aacquire in I B . Proof. Suppose, for contradiction, there is an L-remove event e for curr ptr before aacquire in I B and e is not the last L-event before aacquire in I B . Hence, there is an L-event after e but before aacquire in I B . Let e′ be the next L-event after e in I B , so e′ < aacquire . Hence, e and e′ are 60

successive L-events in I B . Thus, since e is an L-remove event for curr ptr and R(I B ) holds, we have that there is a successful list-remove attempt for curr ptr before e′ in I B . Therefore, since e′ < aacquire , we have that there is a successful list-remove attempt for curr ptr before aacquire in I B . However, by Lemma C.1.86, there are no successful list-remove attempts for curr ptr before aacquire in I B , a contradiction. Lemma C.1.87 Proposition C.1.88. Let I be any invocation of the Acquire procedure in I B by some process p and let T 93 be the time p executed line 93 during I (assuming p does). At all times at or after T 93 and before I returns, the value of the local variable curr ptr in I is in C ∪ {&H}. Proof. By essentially the same argument as Lemma C.1.48, which we provide below for completeness. Suppose, for contradiction, there is a time T at or after T 93 and before I returns (if it ever does) such that the value of the local variable curr ptr in I is ptr ∈ / C ∪ {&H}. Without loss of generality, suppose T is the first such time. Since p executed line 93 at T 93 during I, the value of curr ptr is &H at T 93 . Hence, since the value of curr ptr is ptr ∈ / C ∪ {&H} at T ≥ T 93 , it follows that the value of curr ptr was set to ptr at T . Thus, since the value of curr ptr only changes on line 100 after T 93 during I, we have that p set curr ptr to ptr by executing line 100 at T . So, the value of the local variable next ptr in I is ptr at T . Therefore, the response of the invocation I ′ of the AcquireNext procedure on line 95 during the same iteration of the while loop on line 94 as T is (Found, ptr). Let T 95 be the time p invoked I ′ , and let ptr′ be the second parameter of I ′ . Hence, the value of curr ptr is ptr′ at T 95 . Thus, since p invoked I ′ at T 95 strictly before T , by the minimality of T , ptr′ ∈ C ∪ {&H}. Since the second parameter of I ′ is ptr′ , and the response of I ′ is (Found, ptr), it follows that p read ptr from (∗ptr′ ).next.ptr on the last execution of line 104 during I ′ ; say at time T 104 . Hence, since ptr′ ∈ C ∪ {&H}, by Lemma C.1.47, ptr ∈ C ∪ {Null}. Therefore, since ptr ∈ / C ∪ {&H}, we have that ptr = Null. However, since p exited I ′ with response (Found, ptr), we have that p found the clause on line 107 to be false on its last execution of line 107 during I ′ , and since p read ptr from (∗ptr′ ).next.ptr on its last execution of line 104 during I ′ , this implies that ptr ̸= Null, a contradiction. Proposition C.1.88 Since the AcquireNext procedure is invoked only on lines 31, 47, and 95, Propositions C.1.48, C.1.50, and C.1.88 imply the following. Corollary C.1.89. Consider any invocation of the AcquireNext procedure in I B and let curr ptr be its second parameter. Then, curr ptr ∈ C ∪ {&H}. Lemma C.1.90. Consider any list-acquire-next attempt for next ptr after curr ptr in I B . Then, next ptr ∈ C and curr ptr ∈ C ∪ {&H}. Proof. Consider any list-acquire-next attempt a for next ptr after curr ptr by some process p. By Definition C.1.5, p performed a during some invocation I of the AcquireNext procedure with parameters (∗, curr ptr). Hence, by Corollary C.1.89, curr ptr ∈ C ∪ {&H}. Thus, since a is for next ptr, we have that p read next ptr from (∗curr ptr).next.ptr on p’s last execution of line 104 during I; say at time T 104 . Hence, since curr ptr ∈ C ∪ {&H}, by Lemma C.1.47, next ptr ∈ C ∪ {Null}. If next ptr ∈ C, then we are done, so suppose next ptr = Null. Since a is a list-acquire-next attempt for next ptr, we have that p found the condition on line 105 to be false between T 104 and a. Hence, next ptr ̸= Null, contradicting the fact that next ptr = Null, so this case impossible. Therefore, next ptr ∈ C as wanted. Lemma C.1.90 Lemma C.1.91. Consider any invocation of the AcquireNext procedure in I B whose response is (Found, next ptr). Then, next ptr ∈ C. 61

Proof. Consider any invocation I of the AcquireNext procedure whose response is (Found, next ptr) by some process p. Hence, p exited I on line 110, and so p performed a successful list-acquire-next attempt for next ptr on line 109. Therefore, by Lemma C.1.90, next ptr ∈ C. Lemma C.1.91 Lemma C.1.92. Consider any invocation I of the Acquire procedure in I B . The second parameter of I is in C ∪ {Null}. Proof. Observe that I is invoked on either line 75 or line 80. Hence, the second parameter of I was read from either L.ptr or A.ptr. Since L.ptr (resp. A.ptr) is initially Null, by Observation C.1.6 only L-events (resp. A-events) change the value of L.ptr (resp. A.ptr), and by Lemma C.1.28 (resp. Lemma C.1.14) every L-event (resp. A-event) is for a pointer from C, the lemma follows. Lemma C.1.92

Since &H ∈ / C ∪ {Null} (Assumption C.1.2), the second parameter of I is not &H, which implies the following. Corollary C.1.93. Consider any invocation I of the Acquire procedure that exits in I B . The process that invoked I executed line 105 at least once during I. Lemma C.1.94. Consider any list-acquire-next attempt aacquire for ptr after curr ptr in I B . There is either a successful list-add attempt for ptr after curr ptr or a successful list-remove attempt between curr ptr and ptr before aacquire in I B . Proof. Let p be the process that executed aacquire . Since aacquire is a list-acquire-next attempt for ptr after curr ptr, by Lemma C.1.90, ptr ∈ C and curr ptr ∈ C ∪ {&H}. Furthermore, p read ptr from (∗curr ptr).next.ptr on its last execution of line 104 before aacquire ; say at time T 104 . Hence, since ptr ∈ C, by Assumption C.1.2, ptr ̸= Null. Thus, since curr ptr ∈ C ∪ {&H}, we have that (∗curr ptr).next.ptr is initially Null, and so since p read ptr from (∗curr ptr).next.ptr at T 104 , it follows that (∗curr ptr).next.ptr was set to ptr before T 104 . Therefore, since curr ptr ∈ C ∪ {&H}, by Observation C.1.6, there is either a successful list-add attempt for ptr after curr ptr or a successful list-remove attempt between curr ptr and ptr before T 104 (and thus aacquire ). Lemma C.1.94 We now prove some facts about acquire-copy events. Lemma C.1.95. Consider any acquire-copy event e for ptr in I B . Let p be the process that executed e and let I be the invocation of the DoRemoveCell procedure that e was executed during. Then, p performed a successful list-remove attempt for ptr before e during I. Proof. Since e is an acquire-copy event for ptr during I, by Definition C.1.5, the second parameter of I is ptr. Furthermore, it follows that p executed a successful CAS on line 61 before e during I. Let a denote this successful CAS on line 47 before e during I. Therefore, since the second parameter of I is ptr, by Definition C.1.5, a a successful list-remove attempt for ptr. Lemma C.1.95 Lemma C.1.96. Every acquire-copy event in I B is for a pointer in C. Proof. By Lemma C.1.95, the process that performs any acquire-copy event for some ptr previously performs a successful list-remove attempt for ptr. Thus, by Lemma C.1.46, ptr ∈ C. Lemma C.1.96 We now prove some facts about revocation events. Lemma C.1.97. Every revocation event in I B is for a pointer in C.

62

Proof. Consider any revocation event e for some ptr in I B . Hence, by Definition C.1.5, e was performed by some process p during an invocation I of the Relinquish procedure with parameters ptr. Thus, since e is an execution of line 113, we have that p found the condition on line 112 to be false during I, so ptr ̸= Null and ptr ̸= &H. Observe that I could be invoked on line 7, 39, 41, 51, 63, 64, 78, 90, 96. We consider each case. Case 1. I was invoked on line 7. Hence, since I’s parameter is ptr, p received ptr as a response to an AllocateCell operation on line 2. Therefore, by Algorithm 4, ptr ∈ C. Case 2. I was invoked on line 39 or 41. Hence, since I’s parameter is ptr, we have that ptr is the value of p’s local variable curr ptr during an invocation of the DoAddCell procedure. Thus, by Lemma C.1.48, ptr ∈ C ∪ {&H}. Therefore, since ptr ̸= &H, we have that ptr ∈ C as wanted. Case 3. I was invoked on line 51 or 63. Hence, since I’s parameter is ptr, we have that ptr is the value of p’s local variable prev ptr during an invocation of the DoRemoveCell procedure. Thus, by Corollary C.1.52, ptr ∈ C ∪ {&H}. Therefore, since ptr ̸= Null and ptr ̸= &H, we have that ptr ∈ C as wanted. Case 4. I was invoked on line 64. Hence, since I’s parameter is ptr, we have that ptr is the value of p’s local variable curr ptr during an invocation of the DoRemoveCell procedure. Thus, by Lemma C.1.50, ptr ∈ C∪{&H}. Therefore, since ptr ̸= &H, we have that ptr ∈ C as wanted. Case 5. I was invoked on line 78. Hence, since I’s parameter is ptr, we have that ptr is the second parameter of some invocation of the SetResponse procedure. Thus, by Lemma C.1.71, there is an L-event for ptr in I B , and so by Lemma C.1.28 ptr ∈ C as wanted. Case 6. I was invoked on line 90. Hence, since I’s parameter is ptr, we have that p read ptr from A.ptr. Since A.ptr is initially Null, and ptr ̸= Null, we have that A.ptr was set to ptr. Hence, by Observation C.1.6, some A-event eA set A.ptr = ptr, and so by Definition C.1.5, eA is an A-event for ptr. Therefore, by Lemma C.1.14, ptr ∈ C as wanted. Case 7. I was invoked on line 96. Hence, since I’s parameter is ptr, we have that ptr is the value of p’s local variable curr ptr during an invocation of the Acquire procedure. Thus, by Proposition C.1.88, ptr ∈ C ∪ {&H}. Therefore, since ptr ̸= &H, we have that ptr ∈ C as wanted. Lemma C.1.97 Since every FreeCell(ptr) operation is preceded by a revocation event for ptr, Lemma C.1.97 implies the following. Corollary C.1.98. The input of every FreeCell in I B is in C. We are now ready to prove that every line of B that tries to perform an operation on an object of a cell actually does. In other words, in B, no step de-references a value that isn’t in C ∪ {&H}.

63

Lemma C.1.99. Every execution of line 5, 12, 13, 34, 36, 53, 54, 55, 56, 58, 61, 62, 77, 88, 104, 109, and 113 in I B performs an operation on an object of a cell whose pointer is in C ∪ {&H}. Proof. The claim is trivial for lines 5, 12, and 13. For line 34 the claim follows from Lemma C.1.48. For line 36 the claim follows from Lemma C.1.49. For lines 53, 54, 55, and 56 the claim follows from Corollary C.1.37. For lines 58 and 61, let I be the invocation of the DoRemoveCell procedure that either is executed in, and let ptrL be the second parameter of I. Hence, by Corollary C.1.37, ptrL ∈ C, and so by Assumption C.1.2, ptrL ̸= &H. Thus, the process that invoked I found the condition on line 46 to be false its first time in I, and so it executed line 52 at least once during I (since it executed line 58 or 61 in I). So, the claim follows from Lemma C.1.51. For line 62 the claim follows from Lemma C.1.96. For line 77 the claim follows from Lemma C.1.75. For line 88, observe that (ulloA , ptrA ) was read from A, which is initially ((0, Noop), Null), and since ulloA = (∗, ⟨Apply&CopyResponse, ∗⟩) by the condition on line 87, we have that A was set to (ulloA , ptrA ), and so by Observation C.1.6, some A-event set A to (ulloA , ptrA ), and thus by Lemma C.1.14, ptrA ∈ C. For lines 104 and 109 the claim follows from Corollary C.1.89. Finally, for line 113, the claim follows from Lemma C.1.97. Lemma C.1.99 C.1.5

The DoLowLevelOp procedure

We now prove that if an invocation of the DoLowLevelOp procedure exits, then the low-level operation it was trying to do is “done” in the sense described below. Lemma C.1.100. Consider any invocation I of the DoLowLevelOp procedure with a second parameter of ptr that never exits in I B . Let T 12 be the time line 12 is executed during I. Then, from T 12 onwards in I B there are no response-reset events for ptr. Proof. Suppose, for contradiction, there is a response-reset event e for ptr after T 12 . Let p be the process that invoked I and let q be the process that executed e. Let I ′ be the invocation of the DoLowLevelOp procedure that q executed e during. Since e is a response-reset event for ptr, the second parameter of I ′ is ptr. Since the second parameter of I (resp. I ′ ) is ptr, it follows that p (resp. q) received ptr as a response on line 2. Hence, since by Algorithm 4 every response on line 2 is unique, we have that p = q. Therefore, since e is after T 12 , p never exits I after T 12 , and p executes line 12 at T 12 , p executes line 12 twice during I. However, there is at most one execution of line 12 per invocation of the DoLowLevelOp procedure, a contradiction. Lemma C.1.100 Proposition C.1.101. Consider any invocation I of the DoLowLevelOp procedure with a second parameter of ptr that exits at some time Te in I B . Let T 12 be the time line 12 is executed during I. Then, between T 12 and Te , there are no response-reset events for ptr. Proof. Let I be the prefix of I B up to but excluding the last step of I, so I never exits in I. By plugging in I for I B in Lemma C.1.100 the claim follows. Proposition C.1.101 Lemma C.1.102. Consider any invocation I of the DoLowLevelOp procedure with parameters (AddCell, ptr) that exits at some time Te in I B . Let T 12 be the time line 12 is executed during I. Then, between T 12 and Te , there is a successful add-response-set attempt for ptr. Proof. Let p be the process that executed I. Hence, p received ptr as a response on line 2, and so by Algorithm 4 ptr ∈ C. Since p exited I, we have that p finds the condition on line 13 to be false at some time during I; say at time T 13 . Hence, since p set (∗ptr).response = (ullo, Null) at T 12 during I, and then later found line 13 to be false at T 13 during I, we have that between T 12 and T 13 , the value of (∗ptr).response changed. Thus, since ptr ∈ C, by Observation C.1.6, 64

there is either a response-reset event for ptr or a successful response-set attempt for ptr between T 12 and T 13 . Hence, since T 13 is during I and I exits at Te , by transitivity, T 13 < Te , and so there is either a response-reset event for ptr or a successful response-set attempt for ptr between T 12 and Te . However, since by Proposition C.1.101 there are no response-reset events for ptr between T 12 and Te , we have that there is a successful response-set attempt for ptr between T 12 and Te . Let a be the first successful response-set attempt for ptr between T 12 and Te . Hence, since (∗ptr).response = (ullo, Null) at T 12 , and a is a successful execution of line 77, we have that a is of the form CAS((∗ptr).response, (ullo, Null), ∗). Since (∗ptr).response = (ullo, Null) at T 12 during I and I’s first parameter is AddCell, we have that ullo = (∗, AddCell). Hence, a is of the form CAS((∗ptr).response, ((∗, AddCell), Null), ∗), and so by Definition C.1.5, a is a successful add-response-set attempt for ptr. Therefore, since a is between T 12 and Te , we have there is a successful add-response-set attempt for ptr between T 12 and Te as wanted. Lemma C.1.102 Lemma C.1.103. Consider any invocation I of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr) that exits at some time Te in I B . Let T 12 be the time line 12 is executed during I. Then, between T 12 and Te , there is a successful apply-response-set attempt for ptr. Proof. By essentially the same argument as Lemma C.1.102, which we provide below for completeness. Let p be the process that executed I. Hence, p received ptr as a response on line 2, and so by Algorithm 4 ptr ∈ C. Since p exited I, we have that p finds the condition on line 13 to be false at some time during I; say at time T 13 . Hence, since p set (∗ptr).response = (ullo, Null) at T 12 during I, and then later found line 13 to be false at T 13 during I, we have that between T 12 and T 13 , the value of (∗ptr).response changed. Thus, since ptr ∈ C, by Observation C.1.6, there is either a response-reset event for ptr or a successful response-set attempt for ptr between T 12 and T 13 . Hence, since T 13 is during I and I exits at Te , by transitivity, T 13 < Te , and so there is either a responsereset event for ptr or a successful response-set attempt for ptr between T 12 and Te . However, since by Proposition C.1.101 there are no response-reset events for ptr between T 12 and Te , we have that there is a successful response-set attempt for ptr between T 12 and Te . Let a be the first successful response-set attempt for ptr between T 12 and Te . Hence, since (∗ptr).response = (ullo, Null) at T 12 , and a is a successful execution of line 77, we have that a is of the form CAS((∗ptr).response, (ullo, Null), ∗). Since (∗ptr).response = (ullo, Null) at T 12 during I and I’s first parameter is ⟨Apply&CopyResponse, ∗⟩, we have that ullo = (∗, ⟨Apply&CopyResponse, ∗⟩). Hence, a is of the form CAS((∗ptr).response, ((∗, ⟨Apply&CopyResponse, ∗⟩), Null), ∗), and so by Definition C.1.5, a is a successful apply-response-set attempt for ptr. Therefore, since a is between T 12 and Te , we have there is a successful apply-response-set attempt for ptr between T 12 and Te as wanted. Lemma C.1.103 Lemma C.1.104. Consider any invocation I of the DoLowLevelOp procedure with parameters (RemoveCell, ptr) that exits at some time Te in I B . Let T 12 be the time line 12 is executed during I. Then, between T 12 and Te , there is a successful remove-response-set attempt for ptr. Proof. By essentially the same argument as Lemma C.1.102, which we provide below for completeness. Let p be the process that executed I. Hence, p received ptr as a response on line 2, and so by Algorithm 4 ptr ∈ C. Since p exited I, we have that p finds the condition on line 13 to be false at some time during I; say at time T 13 . Hence, since p set (∗ptr).response = (ullo, Null) at T 12 during I, and then later found line 13 to be false at T 13 during I, we have that between T 12 and T 13 , the value of (∗ptr).response changed. Thus, since ptr ∈ C, by Observation C.1.6, there is either a response-reset event for ptr or a successful response-set attempt for ptr between 65

T 12 and T 13 . Hence, since T 13 is during I and I exits at Te , by transitivity, T 13 < Te , and so there is either a response-reset event for ptr or a successful response-set attempt for ptr between T 12 and Te . However, since by Proposition C.1.101 there are no response-reset events for ptr between T 12 and Te , we have that there is a successful response-set attempt for ptr between T 12 and Te . Let a be the first successful response-set attempt for ptr between T 12 and Te . Hence, since (∗ptr).response = (ullo, Null) at T 12 , and a is a successful execution of line 77, we have that a is of the form CAS((∗ptr).response, (ullo, Null), ∗). Since (∗ptr).response = (ullo, Null) at T 12 during I and I’s first parameter is RemoveCell, we have that ullo = (∗, RemoveCell). Hence, a is of the form CAS((∗ptr).response, ((∗, RemoveCell), Null), ∗), and so by Definition C.1.5, a is a successful remove-response-set attempt for ptr. Therefore, since a is between T 12 and Te , we have there is a successful remove-response-set attempt for ptr between T 12 and Te as wanted. Lemma C.1.104 Lemma C.1.105. Consider any invocation I of the DoLowLevelOp procedure with parameters (AddCell, ptr) that is invoked at time Tb and exits at some time Te in I B . If P (I B ) holds, then there is an L-add event for ptr between Tb and Te . Proof. Let p be the process that invoked I. We first prove that there is an L-add event for ptr before Te . Let T 12 be the time line 12 is executed during I. By Lemma C.1.102, there is a successful add-response-set attempt for ptr between T 12 and Te . Let a be this successful add-response-set attempt. Hence, by Corollary C.1.74, there is an L-add event e for ptr before a (and thus Te since a < Te ). Thus, by P (I B ), e is the only L-add event for ptr in I B . We now prove that e is after Tb , which completes the proof. Suppose, for contradiction, e < Tb . Since e is an L-add event for ptr, by Definition C.1.5, e set L to a value of the form ((∗, AddCell), ptr). Hence, by Lemma C.1.23, there is an A-event e′ before e which set A to the same value. Thus, by Definition C.1.5, e′ is an A-add event for ptr. Let q be the process that executed e′ . Since e′ is an A-add event for ptr, we have that q executed e′ during an invocation I ′ of the DoLowLevelOp procedure with parameters of the form (AddCell, ptr). Hence, since e′ is before e, and by assumption e < Tb , we have that I ′ was invoked before I was invoked, and so I ′ ̸= I. Therefore, since I and I ′ are both invocations of the DoLowLevelOp procedure with parameters of the form (AddCell, ptr), we have that there are two invocations of the DoLowLevelOp procedure with parameters of the form (AddCell, ptr) in I B . However, since the response on line 2 is unique, there is at most one invocation of the DoLowLevelOp procedure with these parameters in I B , a contradiction. Lemma C.1.105 Lemma C.1.106. Consider any invocation I of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr) that is invoked at time Tb and exits at some time Te in I B . If P (I B ) holds, then there is an L-apply event for ptr between Tb and Te . Proof. By essentially the same argument as Lemma C.1.105, which we provide below for completeness. Let p be the process that invoked I. We first prove that there is an L-apply event for ptr before Te . Let T 12 be the time line 12 is executed during I. By Lemma C.1.103, there is a successful apply-response-set attempt for ptr between T 12 and Te . Let a be this successful apply-response-set attempt. Hence, by Corollary C.1.74, there is an L-apply event e for ptr before a (and thus Te since a < Te ). Thus, by P (I B ), e is the only L-apply event for ptr in I B . We now prove that e is after Tb , which completes the proof. Suppose, for contradiction, e < Tb . Since e is an L-apply event for ptr, by Definition C.1.5, e set L to ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr). Hence, by Lemma C.1.23, there is an A-event e′ before e which set A to the same value. Thus, by Definition C.1.5, e′ is an A-apply event for ptr. Let q be the process that executed e′ . Since e′ is an A-apply event for ptr, we have that q executed e′ during an invocation I ′ of the DoLowLevelOp 66

procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr). Hence, since e′ is before e, and by assumption e < Tb , we have that I ′ was invoked before I was invoked, and so I ′ ̸= I. Therefore, since I and I ′ are both invocations of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr), we have that there are two invocations of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr) in I B . However, since the response on line 2 is unique, there is at most one invocation of the DoLowLevelOp procedure with these parameters in I B , a contradiction. Lemma C.1.106 Lemma C.1.107. Consider any invocation I of the DoLowLevelOp procedure with parameters (RemoveCell, ptr) that is invoked at time Tb and exits at some time Te in I B . If P (I B ) holds, then there is an L-remove event for ptr between Tb and Te . Proof. By essentially the same argument as Lemma C.1.105, which we provide below for completeness. Let p be the process that invoked I. We first prove that there is an L-remove event for ptr before Te . Let T 12 be the time line 12 is executed during I. By Lemma C.1.104, there is a successful remove-response-set attempt for ptr between T 12 and Te . Let a be this successful removeresponse-set attempt. Hence, by Corollary C.1.74, there is an L-remove event e for ptr before a (and thus Te since a < Te ). Thus, by P (I B ), e is the only L-remove event for ptr in I B . We now prove that e is after Tb , which completes the proof. Suppose, for contradiction, e < Tb . Since e is an L-remove event for ptr, by Definition C.1.5, e set L to ((∗, RemoveCell), ptr). Hence, by Lemma C.1.23, there is an A-event e′ before e which set A to the same value. Thus, by Definition C.1.5, e′ is an A-remove event for ptr. Let q be the process that executed e′ . Since e′ is an A-remove event for ptr, we have that q executed e′ during an invocation I ′ of the DoLowLevelOp procedure with parameters of the form (RemoveCell, ptr). Hence, since e′ is before e, and by assumption e < Tb , we have that I ′ was invoked before I was invoked, and so I ′ ̸= I. Therefore, since I and I ′ are both invocations of the DoLowLevelOp procedure with parameters of the form (RemoveCell, ptr), we have that there are two invocations of the DoLowLevelOp procedure with parameters of the form (RemoveCell, ptr) in I B . However, since the response on line 2 is unique, there is at most one invocation of the DoLowLevelOp procedure with these parameters in I B , a contradiction. Lemma C.1.107 Lemma C.1.108. Consider any invocation I of the DoLowLevelOp procedure with parameters of the form (⟨Apply&CopyResponse, ∗⟩, ptr) that is invoked at time Tb and exits at some time Te in I B . Suppose P (I B ) holds. Let t be the response on line 10 during I and let e be the L-apply event for ptr between Tb and Te identified by Lemma C.1.106. Then, e is for timestamp t. Proof. Suppose, for contradiction e is for a timestamp t′ ̸= t. Hence, since e is an L-apply event for ptr, by Definition C.1.5, e set L to ((t′ , ⟨Apply&CopyResponse, ∗⟩), ptr). Thus, by Lemma C.1.23, there is an A-event e′ which set A to ((t′ , ⟨Apply&CopyResponse, ∗⟩), ptr). Hence, e′ is invoked during an invocation I ′ of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptr) whose response on line 10 is t′ . Thus, since I is an invocation of the DoLowLevelOp procedure with (⟨Apply&CopyResponse, ∗⟩, ptr) whose response on line 10 is t, and t′ ̸= t, we have that I ̸= I ′ . Therefore, there are two invocations of the DoLowLevelOp procedure with parameters of the form (⟨Apply&CopyResponse, ∗⟩, ptr) in I B . However, since the response on line 2 is unique, there is at most one invocation of the DoLowLevelOp procedure with parameters of the form (⟨Apply&CopyResponse, ∗⟩, ptr) in I B , a contradiction. Lemma C.1.108 Another consequence of the fact that once a DoLowLevelOp procedure exits there is a successful response-set attempt is that if there is an unsuccessful response-set attempt, then there must be a successful one beforehand. 67

Lemma C.1.109. Consider any unsuccessful add-response-set attempt for ptr in I B . Then there is a successful add-response-set attempt for ptr beforehand. Proof. Consider any unsuccessful add-response-set attempt a for ptr in I B . Hence, by Lemma C.1.75 ptr ∈ C. Suppose a tried to set (∗ptr).response.ullo = ullo. Then, by Lemma C.1.73, there is an L-event e before a which set L = (ullo, ptr), and so e is an L-add event for ptr. Since a tries to set (∗ptr).response.ullo = ullo, and is unsuccessful, we have that (∗ptr).response ̸= (ullo, Null) at the step before a. Since e is an L-add event for ptr that set L.ullo = ullo, by Corollary C.1.70, there is exactly one add-response-reset event er for ptr before e that set (∗ptr).response = (ullo, Null). Hence, since e < a, and (∗ptr).response ̸= (ullo, Null) at the step before a, we have that the value of (∗ptr).response changed during (er , a). Let ec be the first step during (er , a) that changed the value of (∗ptr).response. Thus, since ptr ∈ C, by Observation C.1.6, ec is either a response-reset event for ptr or a successful response-set attempt for ptr. We consider each case separately. Case 1. ec is a response-reset event for ptr. Hence, by Definition C.1.5, ec set (∗ptr).response = (∗, Null) on line 12. Let pr (resp. pc ) be the process that executed er (resp. ec ). Since er is an add-response-reset event for ptr and ec is a response-reset event for ptr, pr (resp. pc ) performed er (resp. ec ) during an invocation Ir (resp. Ic ) of the DoLowLevelOp procedure whose second parameter is ptr. Let Irhlo (resp. Ichlo ) be the invocation of the DoHighLevelOp procedure that pr (resp. pc ) invoked Ir (resp. Ic ) during. Since the second parameter of Ir (resp. Ic ) is ptr, it follows that pr (resp. pc ) received ptr as a response on line 2 during Irhlo (resp. Ichlo ). Hence, since by Algorithm 4 every AllocateCell operation returns a unique response, we have that pr = pc and Irhlo = Ichlo . Let p∗ be this process. Since er (resp. ec ) is an execution of line 12 during Ir (resp. Ic ), and there is at most one execution of line 12 per invocation of the DoLowLevelOp procedure, we have that Ir ̸= Ic . Hence, since er < ec , and p∗ invoked both Ir and Ic , it follows that Ir exited before Ic was invoked. Since p∗ executed er during Ir , and er is an add-response-reset event for ptr, it follows that the parameters are Ir are (AddCell, ptr). Hence, by Lemma C.1.102, there is a successful add-response-set attempt for ptr before Ir exits. Therefore, since Ir exits before Ic is invoked, p∗ executes ec during Ic , and ec < a, by transitivity, there is a successful add-response-set attempt for ptr before a. Case 2. ec is a successful response-set attempt for ptr. Since er set (∗ptr).response = (ullo, Null), and the first time it changes after er is ec , it follows that (∗ptr).response = (ullo, Null) throughout [er , ec ). Hence, since ec is a successful response-set attempt for ptr, by Definition C.1.5, ec is a CAS operation on line 77. Thus, since ec is successful and (∗ptr).response = (ullo, Null) throughout [er , ec ), the first parameter of ec is (ullo, Null). Hence, since ullo = (∗, AddCell) (because e set L.ullo = ullo and e is an L-add event), by Definition C.1.5, ec is a successful add-response-set attempt for ptr. Therefore, since ec < a, there is a successful add-response-set attempt for ptr before a. Lemma C.1.109 Lemma C.1.110. Consider any unsuccessful apply-response-set attempt for ptr in I B . Then there is a successful apply-response-set attempt for ptr beforehand. Proof. By essentially the same argument as Lemma C.1.109, which we provide below for completeness. Consider any unsuccessful apply-response-set attempt a for ptr in I B . Hence, by Lemma C.1.75 ptr ∈ C. Suppose a tried to set (∗ptr).response.ullo = ullo. Then, by Lemma C.1.73, there is an L-event e before a which set L = (ullo, ptr), and so e is an L-apply event for ptr. Since a tries to set (∗ptr).response.ullo = ullo, and is unsuccessful, we have that (∗ptr).response ̸= (ullo, Null) at the step before a. Since e is an L-apply event for ptr that set L.ullo = ullo, 68

by Corollary C.1.70, there is exactly one apply-response-reset event er for ptr before e that set (∗ptr).response = (ullo, Null). Hence, since e < a, and (∗ptr).response ̸= (ullo, Null) at the step before a, we have that the value of (∗ptr).response changed during (er , a). Let ec be the first step during (er , a) that changed the value of (∗ptr).response. Thus, since ptr ∈ C, by Observation C.1.6, ec is either a response-reset event for ptr or a successful response-set attempt for ptr. We consider each case separately. Case 1. ec is a response-reset event for ptr. Hence, by Definition C.1.5, ec set (∗ptr).response = (∗, Null) on line 12. Let pr (resp. pc ) be the process that executed er (resp. ec ). Since er is an apply-response-reset event for ptr and ec is a response-reset event for ptr, pr (resp. pc ) performed er (resp. ec ) during an invocation Ir (resp. Ic ) of the DoLowLevelOp procedure whose second parameter is ptr. Let Irhlo (resp. Ichlo ) be the invocation of the DoHighLevelOp procedure that pr (resp. pc ) invoked Ir (resp. Ic ) during. Since the second parameter of Ir (resp. Ic ) is ptr, it follows that pr (resp. pc ) received ptr as a response on line 2 during Irhlo (resp. Ichlo ). Hence, since by Algorithm 4 every AllocateCell operation returns a unique response, we have that pr = pc and Irhlo = Ichlo . Let p∗ be this process. Since er (resp. ec ) is an execution of line 12 during Ir (resp. Ic ), and there is at most one execution of line 12 per invocation of the DoLowLevelOp procedure, we have that Ir ̸= Ic . Hence, since er < ec , and p∗ invoked both Ir and Ic , it follows that Ir exited before Ic was invoked. Since p∗ executed er during Ir , and er is an apply-response-reset event for ptr, it follows that the parameters are Ir are (⟨Apply&CopyResponse, ∗⟩, ptr). Hence, by Lemma C.1.103, there is a successful applyresponse-set attempt for ptr before Ir exits. Therefore, since Ir exits before Ic is invoked, p∗ executes ec during Ic , and ec < a, by transitivity, there is a successful apply-response-set attempt for ptr before a. Case 2. ec is a successful response-set attempt for ptr. Since er set (∗ptr).response = (ullo, Null), and the first time it changes after er is ec , it follows that (∗ptr).response = (ullo, Null) throughout [er , ec ). Hence, since ec is a successful response-set attempt for ptr, by Definition C.1.5, ec is a CAS operation on line 77. Thus, since ec is successful and (∗ptr).response = (ullo, Null) throughout [er , ec ), the first parameter of ec is (ullo, Null). Hence, since ullo = (∗, ⟨Apply&CopyResponse, ∗⟩) (because e set L.ullo = ullo and e is an Lapply event), by Definition C.1.5, ec is a successful apply-response-set attempt for ptr. Therefore, since ec < a, there is a successful apply-response-set attempt for ptr before a. Lemma C.1.110 Lemma C.1.111. Consider any unsuccessful remove-response-set attempt for ptr in I B . Then there is a successful remove-response-set attempt for ptr beforehand. Proof. By essentially the same argument as Lemma C.1.109, which we provide below for completeness. Consider any unsuccessful remove-response-set attempt a for ptr in I B . Hence, by Lemma C.1.75 ptr ∈ C. Suppose a tried to set (∗ptr).response.ullo = ullo. Then, by Lemma C.1.73, there is an L-event e before a which set L = (ullo, ptr), and so e is an L-remove event for ptr. Since a tries to set (∗ptr).response.ullo = ullo, and is unsuccessful, we have that (∗ptr).response ̸= (ullo, Null) at the step before a. Since e is an L-remove event for ptr that set L.ullo = ullo, by Corollary C.1.70, there is exactly one remove-response-reset event er for ptr before e that set (∗ptr).response = (ullo, Null). Hence, since e < a, and (∗ptr).response ̸= (ullo, Null) at the step before a, we have that the value of (∗ptr).response changed during (er , a). Let ec be the first step during (er , a) that changed the value of (∗ptr).response. Thus, since ptr ∈ C, by Observation C.1.6, ec is either a response-reset event for ptr or a successful response-set attempt for ptr. We consider each case separately. 69

Case 1. ec is a response-reset event for ptr. Hence, by Definition C.1.5, ec set (∗ptr).response = (∗, Null) on line 12. Let pr (resp. pc ) be the process that executed er (resp. ec ). Since er is an remove-response-reset event for ptr and ec is a response-reset event for ptr, pr (resp. pc ) performed er (resp. ec ) during an invocation Ir (resp. Ic ) of the DoLowLevelOp procedure whose second parameter is ptr. Let Irhlo (resp. Ichlo ) be the invocation of the DoHighLevelOp procedure that pr (resp. pc ) invoked Ir (resp. Ic ) during. Since the second parameter of Ir (resp. Ic ) is ptr, it follows that pr (resp. pc ) received ptr as a response on line 2 during Irhlo (resp. Ichlo ). Hence, since by Algorithm 4 every AllocateCell operation returns a unique response, we have that pr = pc and Irhlo = Ichlo . Let p∗ be this process. Since er (resp. ec ) is an execution of line 12 during Ir (resp. Ic ), and there is at most one execution of line 12 per invocation of the DoLowLevelOp procedure, we have that Ir ̸= Ic . Hence, since er < ec , and p∗ invoked both Ir and Ic , it follows that Ir exited before Ic was invoked. Since p∗ executed er during Ir , and er is an remove-response-reset event for ptr, it follows that the parameters are Ir are (RemoveCell, ptr). Hence, by Lemma C.1.104, there is a successful remove-response-set attempt for ptr before Ir exits. Therefore, since Ir exits before Ic is invoked, p∗ executes ec during Ic , and ec < a, by transitivity, there is a successful remove-response-set attempt for ptr before a. Case 2. ec is a successful response-set attempt for ptr. Since er set (∗ptr).response = (ullo, Null), and the first time it changes after er is ec , it follows that (∗ptr).response = (ullo, Null) throughout [er , ec ). Hence, since ec is a successful response-set attempt for ptr, by Definition C.1.5, ec is a CAS operation on line 77. Thus, since ec is successful and (∗ptr).response = (ullo, Null) throughout [er , ec ), the first parameter of ec is (ullo, Null). Hence, since ullo = (∗, RemoveCell) (because e set L.ullo = ullo and e is an L-remove event), by Definition C.1.5, ec is a successful remove-response-set attempt for ptr. Therefore, since ec < a, there is a successful remove-response-set attempt for ptr before a. Lemma C.1.111 Lastly, we prove a basic property of the IsDone procedure. Lemma C.1.112. Consider any process p and any iteration I of the loop on line 13 such that during I p exits some invocation I ′ of the Acquire procedure on line 80 with response status during I B . Let T 14 be the time p executes line 14 during I and let T 105 be the last time p executes line 105 during I ′ . Recall that T 105 is well-defined by Corollary C.1.93. If P (I B ) holds and status ̸= L-Changed, then there are no L-events throughout [T 14 , T 105 ] during I B . Proof. Suppose p read ulloL from L.ullo on line 14 during I at time T 14 . Hence, since I ′ is invoked during I, we have that the first parameter of I ′ is ulloL . We first prove that L.ullo = ulloL at T 105 (*). Since, by assumption, the response of I ′ is not L-Changed, we have that the response of every invocation of the AcquireNext procedure during I ′ is also not L-Changed (otherwise I ′ ’s response would be L-Changed). Hence, p finds the condition on line 105 to be false on every execution of line 105 during I ′ . Thus, since the first parameter of I ′ is ulloL , the first parameter of every invocation of the AcquireNext procedure during I ′ is also ulloL , and so at the time of every execution of line 105 during I ′ p finds L.ullo = ulloL . Therefore, L.ullo = ulloL at T 105 . We now finish the proof of Lemma C.1.112. Suppose, for contradiction, there is an L-event during [T 14 , T 105 ]. Let e be the last L-event in [T 14 , T 105 ]. Hence, since by (*) L.ullo = ulloL at T 105 , we have that e set L.ullo = ulloL , and so by Corollary C.1.27, ulloL ̸= (0, Noop). Thus, since p read ulloL from L.ullo at T 14 , and L.ullo is initially (0, Noop), we have that L.ullo was set to ulloL before T 14 . So, by Observation C.1.6, there is an L-event e′ before T 14 that set L.ullo = ulloL . Since e′ is before T 14 and e is during [T 14 , T 105 ], we have that e′ < e, and so e′ ̸= e. Therefore, there 70

are two L-events that set L.ullo = ulloL in I B . However, since P (I B ) holds, by Lemma C.1.32, every L-event in I B sets the value of L.ullo to a unique value, a contradiction. Lemma C.1.112 C.1.6

Properties of List

We now prove some facts about List (see Definition C.1.7). Lemma C.1.113. Let I be a finite implementation history of B and let List(I) = ptr0 , . . . , ptrn+1 for some integer n ≥ 0. Then, ptr0 = &H, for every i ∈ [1..n] ptri ∈ C, and ptrn+1 = Null. Proof. Since List(I) = ptr0 , . . . , ptrn+1 , by Definition C.1.7, ptr0 = &H, ptrn+1 = Null, and for every i ∈ [1..n], there is an L-add event for ptri in I, so by Lemma C.1.28 ptri ∈ C. Lemma C.1.113 Lemma C.1.114. Let I be a finite implementation history of B and let List(I) = ptr0 , . . . , ptrn+1 for some integer n ≥ 0. If P (I) holds, then for every i, j ∈ [0..n + 1], if i ̸= j, then ptri ̸= ptrj . Proof. Suppose, for contradiction, for some i, j ∈ [0..n + 1] i ̸= j and ptri = ptrj . Case 1. i = 0 or j = 0. Hence, since by assumption i ̸= j, either i or j is not zero. Without loss of generality, suppose i = 0 and j ̸= 0. Hence, by Definition C.1.7, ptri = &H. Thus, since by assumption ptri = ptrj , we have that ptrj = &H. Since j ̸= 0, j ∈ [1..n + 1]. Hence, by Lemma C.1.113, ptrj ∈ C ∪ {Null}. Therefore, by Assumption C.1.2, ptrj ̸= &H. However, ptrj = &H, a contradiction. Case 2. i ̸= 0 and j ̸= 0. Hence, since i, j ∈ [0..n + 1] and by assumption i ̸= j, either i, j ∈ (0..n + 1) or one of i and j is in (0..n + 1) and the other equals n + 1. We consider each case separately. Case 2.1. i ∈ (0..n + 1) and j ∈ (0..n + 1). Hence, i, j ∈ [1..n], and since List(I) = ptr0 , . . . , ptrn+1 , by Definition C.1.7, there is an L-add event for ptri in I, an L-add event for ptrj in I, and so by Lemma C.1.28 ptri , ptrj ∈ C. Therefore, since by assumption ptri = ptrj , there are two L-add events in I for the same pointer in C. However, by P (I), there is at most one L-add event in I for every pointer in C, a contradiction. Case 2.2. One of i and j is in (0..n + 1) and the other equals n + 1. Without loss of generality suppose i ∈ (0..n + 1) and j = n + 1. Hence, i ∈ [1..n], and since List(I) = ptr0 , . . . , ptrn+1 , by Definition C.1.7, there is an L-add event for ptri in I, and so by Lemma C.1.28 ptri ∈ C. Thus, by Assumption C.1.2, ptri ̸= Null. Therefore, since by assumption ptri = ptrj , ptrj ̸= Null. However, since j = n + 1, by Lemma C.1.113, ptrj = Null, a contradiction. Lemma C.1.114 Lemma C.1.115. Consider any finite implementation histories I1 and I2 of B such that I1 is a prefix of I2 . Suppose some curr ptr ∈ C ∪ {&H} is in List(I1 ) and it appears immediately before some ptr ∈ C in List(I1 ). If P (I2 ) holds, and both curr ptr and ptr are in List(I2 ), then curr ptr appears immediately before ptr in List(I2 ). Proof. Suppose curr ptr and ptr are in List(I2 ). There are two cases. Case 1. curr ptr = &H. Since ptr ∈ C, by Assumption C.1.2, ptr ̸= &H and ptr ̸= Null. Hence, since curr ptr = &H and it appears immediately before ptr in List(I1 ), by Definition C.1.7, there is an L-add event e1 for 71

ptr in I1 such that for every L-event e before e1 in I1 , if e is an L-add event for ptr′ , then there is an L-remove event for ptr′ after e in I1 . Furthermore, since ptr is in List(I2 ), by Definition C.1.7, there is an L-add event e2 for ptr in I2 such that there is no L-remove event for ptr after e2 in I2 . Since e1 is in I1 and I1 is a prefix of I2 , we have that e1 is in I2 . Hence, by P (I2 ), there is at most one L-add event for ptr in I2 , and so e1 = e2 . Thus, since for every L-event e before e1 in I1 , if e is an L-add event for ptr′ , then there is an L-remove event for ptr′ after e in I1 , and I1 is a prefix of I2 , we have that for every L-event e before e2 in I2 , if e is an L-add event for ptr′ , then there is an L-remove event for ptr′ after e in I2 . Hence, e2 is the first L-add event for a pointer without a subsequent L-remove event for that pointer in I2 . Therefore, since e2 is an L-add event for ptr, by Definition C.1.7, the first two elements of List(I2 ) are &H and ptr, and so curr ptr appears immediately before ptr in List(I2 ) as required. Case 2. curr ptr ∈ C. Since curr ptr ∈ C and ptr ∈ C, by Assumption C.1.2, ptr ̸= &H, curr ptr ̸= &H, ptr ̸= Null, and curr ptr ̸= Null. Hence, since curr ptr appears immediately before ptr in List(I1 ), by Definition C.1.7, there is an L-add event e1 for curr ptr in I1 and an L-add event e′1 for ptr in I1 such that e1 < e′1 and for every L-event e between e1 and e′1 in I1 , if e is an L-add event for ptr′ , then there is an L-remove event for ptr′ after e in I1 . Furthermore, since curr ptr and ptr are in List(I2 ), by Definition C.1.7, there is an L-add event e2 for curr ptr in I2 and an L-add event e′2 for ptr in I2 such that: (1) e2 < e′2 ; (2) there is no L-remove event for curr ptr after e2 in I2 ; and (3) there is no L-remove event for ptr after e′2 in I2 . Since e1 and e′1 are in I1 and I1 is a prefix of I2 , we have that e1 and e′1 are in I2 . Hence, by P (I2 ), there is at most one L-add event for curr ptr (resp. ptr) in I2 , and so e1 = e2 (resp. e′1 = e′2 ). Thus, since for every L-event e between e1 and e′1 in I1 , if e is an L-add event for ptr′ , then there is an L-remove event for ptr′ after e in I1 , and I1 is a prefix of I2 , we have that for every L-event e between e2 and e′2 in I2 , if e is an L-add event for ptr′ , then there is an L-remove event for ptr′ after e in I2 . Hence, e2 and e′2 are successive L-add events for a pointer without a subsequent L-remove event for that pointer in I2 . Therefore, since e2 (resp. e′2 ) is an L-add event for curr ptr (resp. ptr), by Definition C.1.7, curr ptr and ptr are successive elements of List(I2 ), and so curr ptr appears immediately before ptr in List(I2 ) as required. Lemma C.1.115 Lemma C.1.116. Suppose P (I B ) holds. For every finite prefix I of I B if ptr ∈ List(I), then there are no L-remove events for ptr in I and there are no list-remove attempts for ptr in I. Proof. Suppose ptr ∈ List(I). We first prove that there are no L-remove events for ptr in I. Suppose, for contradiction, there is an L-remove event eremove for ptr in I. Hence, by Lemma C.1.28, ptr ∈ C, and so by Assumption C.1.2, ptr ̸= &H and ptr ̸= Null. Thus, since ptr ∈ List(I), by Definition C.1.7, there is an eadd event for ptr in I such that from eadd onwards in I there are no L-remove events for ptr. Hence, since eremove is an L-remove event for ptr in I, we have that eremove ≤ eadd . Thus, by Corollary C.1.40, there is a L-add event e for ptr before eremove in I. Hence, since eremove ≤ eadd , by transitivity, e < eadd , and so e ̸= eadd . Therefore, there are two L-add events for ptr in I. However, by P (I B ), there is at most one L-add event for ptr in I, a contradiction. We now prove there are no list-remove attempts for ptr in I. Suppose, for contradiction, there is a list-remove attempt a for ptr in I. Hence, by Corollary C.1.37 there is a L-remove event e for ptr before a. Therefore, since a is in I, we have that e is in I, and so there is an L-remove event for ptr in I. However, there are no L-remove events for ptr in I, a contradiction. Lemma C.1.116

72

Lemma C.1.117. Consider any L-add event e for ptr in I B and let Ieexclude be the prefix of I B up to but excluding e. If P (I B ) holds, then, ptr ∈ / List(Ieexclude ). Proof. Suppose, for contradiction, ptr ∈ List(Ieexclude ). Since e is a L-event for ptr, we have that by Lemma C.1.28, ptr ∈ C, so by Assumption C.1.2, ptr ̸= &H and ptr ̸= Null. Hence, since ptr ∈ List(Ieexclude ), by Definition C.1.5, there is an L-add event e′ for ptr in Ieexclude . Thus, since Ieexclude is the prefix of I B up to but excluding e, we have that e′ is before e in I B , and so e′ ̸= e. Therefore, since e and e′ are L-add events for ptr in I B , there are two L-add events for ptr in I B . However, by P (I B ), there is at most one L-add event for ptr in I B , a contradiction. Lemma C.1.117 Lemma C.1.118. Consider any L-remove event e for ptr in I B and let Ieexclude be the prefix of I B up to but excluding e. If P (I B ) holds, then ptr ∈ List(Ieexclude ). Proof. Suppose, for contradiction, ptr ∈ / List(Ieexclude ). Hence, since ptr ∈ / List(Ieexclude ), by Definition C.1.7, either there is an L-add event for ptr with a subsequent L-remove event for ptr in Ieexclude or there is no L-add event for ptr in Ieexclude . Thus, since Ieexclude is the prefix of I B up to but excluding e, either there is an L-add event for ptr with a subsequent L-remove event for ptr before e in I B or there is no L-add event for ptr before e in I B . Case 1. There is an L-add event for ptr with a subsequent L-remove event for ptr before e in I B . Hence, since e is an L-remove event for ptr, there are two L-remove events for ptr in I B . However, by P (I B ), there is at most one L-remove event for ptr in I B , a contradiction. Case 2. There is no L-add event for ptr before e in I B . However, since e is an L-remove event for ptr in I B , by Corollary C.1.40, there is an L-add for ptr before e in I B , a contradiction. Lemma C.1.118 Lemma C.1.119. Consider any L-remove event e for ptr in I B and let Ieexclude be the prefix of I B up to but excluding e. Let List(Ieexclude ) = ptr0 , . . . , ptrn+1 for some integer n ≥ 0. If P (I B ) holds, then there is exactly one i ∈ [1..n] such that ptri = ptr. Proof. We first prove i exists. Since e is an L-event for ptr, by Lemma C.1.28, ptr ∈ C, and so by Assumption C.1.2 ptr ̸= &H and ptr ̸= Null. Furthermore, by Lemma C.1.113, ptr0 = &H, and ptrn+1 = Null. Hence, since P (I B ) holds, byLemma C.1.118 ptr ∈ List(Ieexclude ), and so since List(Ieexclude ) = &H, ptr1 , . . . , ptrn , Null, there is at least one i ∈ [1..n] such that ptri = ptr. We now prove that i is unique. Suppose, for contradiction, there exists i, j ∈ [1..n] such that i ̸= j and ptri = ptrj = ptr. However, since Ieexclude is a prefix of I, List(Ieexclude ) = ptr0 , . . . , ptrn+1 , by b b assumption P (I) holds, and i ̸= j, by Lemma C.1.114 ptri ̸= ptrj , a contradiction. Lemma C.1.119 C.1.7

Miscellaneous

We finish the basic facts section with some miscellaneous properties. Lemma C.1.120. Consider any list-remove attempt aremove for ptr in I B . If R(I B ) holds, then there is a successful list-add attempt for ptr before aremove ’s corresponding L-event in I B . Proof. Since aremove is a list-remove attempt for ptr, by Corollary C.1.37, there is a L-remove event eremove for ptr before aremove in I B . Hence, by Corollary C.1.40, there is a L-add event eadd for ptr before eremove in I B . Thus, there is an L-event after eadd in I B . Let e be the next L-event after eadd in I B , so e ≤ eremove . Since eadd is an L-add event for ptr, and eadd and e are successive L-events in I B , by R(I B ), there is a successful list-add attempt aadd for ptr before e. Therefore, since aadd < e and e ≤ eremove , by transitivity, aadd < eremove , and so there is a successful list-add attempt for ptr before aremove ’s corresponding L-event in I B as wanted. Lemma C.1.120 73

Proposition C.1.121. For every ptr ∈ C ∪ {&H}, if (∗ptr).next.ptr ̸= Null at time T in I B , and (∗ptr).next.ptr = Null at time T ′ > T in I B , then there is a successful list-remove attempt between ptr and Null during (T, T ′ ]. Proof. Since (∗ptr).next.ptr does not equal Null at T and equals Null at T ′ where T ′ > T , it follows that (∗ptr).next.ptr was set to Null during (T, T ′ ]. Hence, by Observation C.1.6, there is either a successful list-add attempt for Null after ptr or a successful list-remove attempt between ptr and Null during (T, T ′ ]. Therefore, since by Lemma C.1.46 every list-add attempt is for a pointer in C, and by Assumption C.1.2 every pointer in C is not Null, the former is impossible, so the latter is the only possibility as wanted. Proposition C.1.121 Lemma C.1.122. Consider two successful list-add attempts after curr ptr in I B denoted by a1 and a2 such that a1 < a2 . Then there is a successful list-remove attempt between curr ptr and Null between a1 and a2 in I B . Proof. Suppose a1 is for ptr, so by Lemma C.1.46 ptr ∈ C. Since a1 is after curr ptr, by Lemma C.1.49, curr ptr ∈ C ∪ {&H}. Hence, since a1 is for ptr (∗curr ptr).next.ptr = ptr at a1 . Thus, since ptr ∈ C, by Assumption C.1.2, ptr ̸= Null, and so (∗curr ptr).next ̸= Null at a1 . Let s be the step before a2 in I B . Hence, a1 ≤ s (since a1 < a2 ). Furthermore, since a2 is a successful list-add attempt after curr ptr, by Definition C.1.5, (∗curr ptr).next.ptr = Null at s. Thus, since (∗curr ptr).next ̸= Null at a1 , we have that a1 ̸= s, and thus a1 < s (since a1 ≤ s). So, since curr ptr ∈ C ∪ {&H}, (∗curr ptr).next ̸= Null at a1 , (∗curr ptr).next.ptr = Null at s, and a1 < s, by Proposition C.1.121, there is a successful list-remove attempt between curr ptr and Null during (a1 , s]. Therefore, since s < a2 , the claim follows. Lemma C.1.122 Lemma C.1.123. Suppose there is a last L-event in I B ; say elast . Consider any process p and iteration I of the loop on line 13 by p during I B such that p’s execution of line 14 during I is after elast . Then, p does not find the condition on line 81 to be true during I. Proof. Suppose, for contradiction, p finds the condition on line 81 to be true during I. Suppose elast set L = (ullo, ptr). Hence, since by assumption elast is the last L-event in I B , by Observation C.1.6, L = (ullo, ptr) from elast onwards in I B . Thus, since p’s execution of line 14 during I is after elast , p reads (ullo, ptr) from L on line 14 during I. Hence, the first parameter of the Acquire procedure on line 80 during I is ullo. Let I ′ denote this invocation of the Acquire procedure. Since p finds the condition on line 81 to be true during I, we have that the response of I ′ is L-Changed. Hence, p found the condition on line 105 to be true during an invocation I ∗ of the AcquireNext procedure invoked during I ′ ; say at time T 105 . Since I ∗ is invoked during I ′ and I ′ ’s first parameter is ullo, we have that I ∗ ’s first parameter is ullo. Furthermore, since p’s execution of line 14 during I is after elast , I ′ was invoked on line 80 during I, I ∗ was invoked during I ′ , and T 105 is during I ∗ , by transitivity, elast < T 105 . Therefore, since I ∗ ’s first parameter is ullo, and p finds the condition on line 105 to be true during I ∗ at T 105 which is after elast , we have that L.ullo ̸= ullo after elast . However, L = (ullo, ptr) from elast onwards in I B , a contradiction. Lemma C.1.123 Lemma C.1.124. For every ptr ∈ C ∪ {&H}, if (∗ptr).next = (∗, ∗, acq, Null) at any time in I B , then acq = 0. Proof. Suppose, for contradiction, there exists a ptr ∈ C ∪ {&H} such that at some time T in I B (∗ptr).next = (∗, ∗, acq, Null) for some acq ̸= 0. Without loss of generality, suppose T is the first time the lemma is violated for any pointer in C ∪ {&H}. Since (∗ptr).next.acquisitions is initially 0, (∗ptr).next.acquisitions = acq ̸= 0 at T , and T is the first such time in I B , it follows that the 74

step at T sets the value of (∗ptr).next to (∗, ∗, acq, Null) at T . Hence, by Observation C.1.6, the step at T is either a successful list-add attempt after ptr, a successful list-seal attempt for ptr, a successful list-remove attempt between ptr and Null, or a successful list-acquire-next attempt after ptr. Denote by a this attempt at T and so a set (∗ptr).next to (∗, ∗, acq, Null) (*). Case 1. a is a successful list-add attempt after ptr. Hence, by Lemma C.1.46, a is for some ptr′ ∈ C. Thus, since a is successful, by Definition C.1.5 a set (∗ptr).next.ptr = ptr′ . Therefore, since ptr′ ∈ C, by Assumption C.1.2, ptr′ ̸= Null, and so a set (∗ptr).next.ptr ̸= Null. However, by (*) a set (∗ptr).next.ptr = Null, a contradiction. Case 2. a is a successful list-remove attempt between ptr and Null Let p be the process that executed a and suppose a is for some ptr′ . Hence, by Lemma C.1.46, ptr′ ∈ C. Since a is a successful list-remove attempt for ptr′ between ptr and Null and a set (∗ptr).next to (∗, ∗, acq, Null), p read (∗, ∗, acq, Null) from (∗ptr′ ).next on its last execution of line 56 before a. Therefore, for some ptr′ ∈ C, (∗ptr′ ).next = (∗, ∗, acq, Null) at some time before T , and so by the minimality of T , acq = 0. However, by assumption acq ̸= 0, a contradiction. Case 3. a is a successful list-seal attempt for ptr. Let p be the process that executed a. Since a is a successful list-seal attempt for ptr and a set (∗ptr).next to (∗, ∗, acq, Null), we have that p read (∗, ∗, acq, Null) from (∗ptr′ ).next on its last execution of line 54 before a. Therefore, (∗ptr).next = (∗, ∗, acq, Null) at some time before T , and so by the minimality of T , acq = 0. However, by assumption acq ̸= 0, a contradiction. Case 4. a is a successful list-acquire-next attempt after ptr. Let p be the process that executed a. Since a set (∗ptr).next to (∗, ∗, acq, Null), we have that p read (∗, ∗, ∗, Null) from (∗ptr).next on its last execution of line 104 before a. Therefore, p found the condition on line 107 to be true between this time and a. However, since p executed a, it must have found the condition on line 107 to be false between this time and a, a contradiction. Lemma C.1.124 Lemma C.1.125. For every ptr ∈ C ∪ {&H}, (∗ptr).next.acquisitions ≥ 0 at all times in I B . Proof. Suppose, for contradiction, there is a ptr ∈ C ∪{&H} such that (∗ptr).next.acquisitions < 0 at some time T in I B . Without loss of generality, suppose T is the first time in I B the lemma is violated, i.e., for every ptr ∈ C ∪ {&H}, (∗ptr).next.acquisitions ≥ 0 at all times before T in I B . Since ptr ∈ C ∪ {&H} (∗ptr).next.acquisitions is initially 0. Hence, the step at time T set (∗ptr).next.acquisitions < 0. Thus, by Observation C.1.6, the step at T is either a successful list-add attempt after ptr, a successful list-remove attempt between ptr and some pointer, or a successful list-acquire-next attempt after ptr. In the first and last case, by line 36 and line 109, the value of (∗ptr).next.acquisitions is one larger at time T than T −1, so (∗ptr).next.acquisitions < 0 at T − 1, a contradiction to the minimality of T . Now consider the second case. Let the step at T be a successful list-remove attempt for ptrL , so by Lemma C.1.46 ptrL ∈ C. By line 61, the step at T set (∗ptr).next.acquisitions = a where (∗ptrL ).next.acquisitions = a at some time before T . Therefore, since ptrL ∈ C, by the minimality of T , a ≥ 0. However, since (∗ptr).next.acquisitions < 0 at T , and (∗ptr).next.acquisitions = a at T , we have that a < 0, a contradiction. Lemma C.1.125 Lemma C.1.126. Every FreeCell(ptr) operation in I B is preceded by a successful list-remove attempt for ptr.

75

Proof. Consider any FreeCell(ptr) operation o in I B by some process p, so by Corollary C.1.98 ptr ∈ C. Since p performed o, it did so on line 114, and thus p performed a revocation event for ptr whose response is −1 before o. Hence, since ptr ∈ C (a) by Observation C.1.6 the only steps that change the value of (∗ptr).revocations are acquire-copy events for ptr and revocation events for ptr, (b) each revocation event for ptr increases the value of (∗ptr).revocations by 1, and (c) (∗ptr).revocations is initially 0, we have that there is an acquire-copy event for ptr before o. Therefore, by Lemma C.1.95, there is a successful list-remove attempt for ptr before o as wanted. Lemma C.1.126 Since by Corollary C.1.37 every list-remove attempt for ptr is preceded by an L-remove event for ptr, Lemma C.1.126 implies the following. Corollary C.1.127. Every FreeCell(ptr) operation in I B is preceded by an L-remove event for ptr. Lemma C.1.128. Suppose Q(I B ) holds. For every ptr ∈ C ∪ {&H}, if (∗ptr).next.ptr = next ptr at some time T in I B where next ptr ∈ C, then there is an L-event for ptr before T in I B . Proof. Since ptr ∈ C ∪{&H}, we have that (∗ptr).next.ptr is initially Null, and since next ptr ∈ C, by Assumption C.1.2, next ptr ̸= &H and next ptr ̸= Null, and so (∗ptr).next.ptr was set to next ptr before T in I B . Thus, by Observation C.1.6, there is either a successful list-add attempt for next ptr after ptr or a successful list-remove attempt between ptr and next ptr before T in I B . Let a denote this successful list attempt. If a is a successful list-add attempt for ptr, by Corollary C.1.37, there is an L-event for ptr before a. Furthermore, if a is a successful list-remove attempt between ptr and next ptr, by Q(I B ), ptr ∈ List(I) where I is a prefix of I B before a. Hence, since ptr ̸= Null and ptr ̸= &H, by Definition C.1.7, there is an L-event for ptr in I. Therefore, in all cases, there is an L-event for ptr before a (and thus T ) in I B . Lemma C.1.128

C.2

The L-Invariants Hold

The high-level strategy for proving many facts about B is to do so under the assumption that the L-invariants hold. We already saw some basic examples of this in the last section. The main goal of this section is to prove that the L-invariants hold for every implementation history of B. The high-level strategy for doing so is as follows. First, we will prove that List(I) is essentially the “shape” of the list at the end of I where I is a finite implementation history of B. Then, using this fact, we prove that the DoAddCell, DoApply&CopyResponse, and DoRemoveCell procedures have the intended effect: if a process exits any of these procedures, then the task it wanted to complete has been completed (but not necessarily by itself). For example, if a process exits the DoAddCell procedure with parameters (∗, ptr), then by the time this procedure exits, ptr has been added to the list, i.e., there is a successful list-add attempt for ptr. We then use these facts to prove that the IsDone procedure has the intended effect in the sense that its response informs the invoking process whether the inputted low-level operation has been written into L. For example, if a process invokes the IsDone procedure with parameters (∗, (∗, AddCell), ptr) and receives response NotDone, then it knows that there has yet to be an L-add event for ptr and conversely if it receives response Done, then it knows that there is an L-add event for ptr (note that the exact time when these are true is delicate). Finally, these facts let us prove inductively that the L-inva3riants hold for any implementation history of B. Throughout this section, I B refers to an arbitrary implementation history of B, i.e., all statements that refer to I B begin with “for every implementation history I B of B” which is omitted for brevity.

76

C.2.1

The sequence of L-events determines the shape of the list

We start by proving that the List(I) is essentially the “shape” of the list at the end of I. Given P (I), Q(I), and R(I) hold, this is mostly a matter of capturing the “lag” between the time of an L-event and the time it “takes effect” (i.e., the relevant cell is added to or removed from the list), and carefully applying these invariants along with the definition of List(I). The one difficulty is dealing with the period after the last L-event in I because invariant R only tells us how the list changes between successive L-events. So, the first step is to “extend” R beyond the last L-event elast in I to state that there is either (1) at most one successful list-add attempt for ptr and no other successful list-add or list-remove attempts for any pointer (if elast is an L-add event for ptr), (2) zero successful list-add or list-remove attempts for any pointer (if elast is an L-apply event), or (3) at most one successful list-remove attempt for ptr and no other successful list-add or list-remove attempts for any pointer (if elast is an L-remove event for ptr). We accomplish this goal via the next four lemmas. We start by showing that the success of a list-add / list-remove attempt implies the non-existence of an L-event between its corresponding L-event and it. As we will see shortly, this is the key fact that lets us “extend” R beyond the last L-event within I. Proposition C.2.1. Consider a list-add or list-remove attempt a in I B and let eb be its corresponding L-event (see Corollary C.1.37). Suppose there is an L-event after eb in I B and that P (I B ), Q(I B ), and R(I B ) hold. Let ea be the next L-event after eb in I B . If ea < a, then a is unsuccessful. Proof. Suppose, for contradiction, ea < a, and a is successful. Let p be the process that executed a. If a is a list-add attempt, suppose it is for some ptr after some curr ptr and otherwise, suppose it is for ptr between curr ptr and some next ptr. Hence, by Lemmas C.1.46, C.1.49, and C.1.53, ptr ∈ C, curr ptr ∈ C ∪ {&H}, and next ptr ∈ C ∪ {Null}. Claim C.2.1.1. If a is a list-add attempt, then T is the time of p’s last execution of line 34 before a; otherwise, T is the time of p’s last execution of line 58 before a. Then, T ∈ (eb , ea ). Proof. Let I be the invocation of the DoAddCell or DoRemoveCell procedure that p executed a during. Hence, T is the time of a step that p performed during I, and by Corollary C.1.37 eb is before p invoked I. Therefore, eb < T . So, what remains is to prove that T < ea . Suppose, for contradiction, ea ≤ T . If a is a list-add attempt, then T ′ is the time of p’s execution of line 35 between T and a; otherwise, T ′ is the time of p’s execution of line 59 between T and a. Hence, T < T ′ . Since eb < ea , ea ≤ T , and T < T ′ , by transitivity, eb < ea < T ′ . Furthermore, since p executed a, it follows that the condition on line 35 or 59 is false at T ′ . Hence, L.ullo = ulloL at T ′ where ulloL is the first parameter of I. Thus, since eb is a’s corresponding L-event, and p executed a during I, by Corollary C.1.37, eb set L.ullo = ulloL . Furthermore, since eb < T ′ , by Observation C.1.6, the last L-event before T ′ set L.ullo = ulloL , and since eb < ea < T ′ there is an L-event during (eb , T ′ ) that set L.ullo = ulloL . Therefore, since eb set L.ullo = ulloL , we have that two L-events in I B set L.ullo to the same value. However, since P (I B ) holds, by Lemma C.1.32, every L-event in I B sets L.ullo to a unique value, contradiction. Claim C.2.1.1 Claim C.2.1.2. During (T, a), there is either a successful list-add attempt after curr ptr or there is a successful list-remove attempt between curr ptr and some pointer. Proof. There are two cases. Case 1. a is a list-add attempt for ptr after curr ptr.

77

Let I be the invocation of the DoAddCell procedure that p executed a during. Since a is a listadd attempt for ptr, by Definition C.1.5, the second parameter of I is ptr. Hence, since eb is a’s corresponding L-event, by Corollary C.1.37, eb is an L-add event for ptr. Since by assumption eb and ea are in I B and ea is defined as the next L-event after eb in I B , eb and ea are successive L-events in I B . Therefore, since eb is an L-add event for ptr, by R(I B ), there is one successful list-add attempt for ptr during (eb , ea ); say a′ . Since a′ < ea and ea < a, by transitivity, a′ < a. Furthermore, since a and a′ are both list-add attempts for ptr in I B , a is after curr ptr, and Q(I B ) holds, by Lemma C.1.54, a′ is after curr ptr. There are two cases. Case 1.1. T < a′ . Hence, since a′ < a, we have that a′ ∈ (T, a). Therefore, since a′ is a successful list-add attempt after curr ptr, the claim follows. Case 1.2. a′ < T . Hence, since by definition T < a, by transitivity, a′ < a. Since a′ and a are two successful list-add attempts after curr ptr in I B such that a′ < a, by Lemma C.1.122, there is a successful list-remove attempt a∗ between curr ptr and Null between a′ and a in I B . There are two more cases. Case 1.2.1. T < a∗ . Hence, since a∗ < a, we have that a∗ ∈ (T, a). Therefore, since a∗ is a successful list-remove attempt between curr ptr and some pointer, the claim follows. Case 1.2.2. a∗ < T . Hence, since a′ < a∗ , we have that a∗ ∈ (a′ , T ). Thus, since eb < a′ and by Claim C.2.1.1 T < ea , by transitivity, a∗ ∈ (eb , ea ). Therefore, there is a successful list-remove attempt during (eb , ea ). However, since eb and ea are successive L-events in I B and eb is an L-add event, by R(I B ), there are no successful list-remove attempts during (eb , ea ), a contradiction, so this case is impossible. Case 2. a is a list-remove attempt for ptr between curr ptr and next ptr. Let I be the invocation of the DoRemoveCell procedure that p executed a during. Since a is a list-remove attempt for ptr, by Definition C.1.5, the second parameter of I is ptr. Hence, since eb is a’s corresponding L-event, by Corollary C.1.37, eb is an L-remove event for ptr. Since by assumption eb and ea are in I B and ea is defined as the next L-event after eb in I B , eb and ea are successive L-events in I B . Therefore, since eb is an L-remove event for ptr, by R(I B ), there is one successful list-remove attempt for ptr during (eb , ea ); say a′ . Since a′ < ea and ea < a, by transitivity, a′ < a. Furthermore, since a and a′ are both list-remove attempts for ptr in I B , a is between curr ptr and next ptr, and Q(I B ) holds, by Lemma C.1.56, a′ is between curr ptr and next ptr. There are two cases. Case 2.1. T < a′ . Hence, since a′ < a, we have that a′ ∈ (T, a). Therefore, since a′ is a successful list-remove attempt between curr ptr and some pointer, the claim follows. Case 2.2. a′ < T . Since eb and ea are successive L-events in I B and eb is an L-remove event for ptr, by R(I B ), there are no successful list-add or list-remove attempts during (eb , ea ) other than a′ . Hence, since a′ is a listremove attempt for ptr between curr ptr and next ptr, by Observation C.1.6, (∗curr ptr).next.ptr is set exactly once during (eb , ea ) (at a′ ), so (∗curr ptr).next.ptr is unchanged during (a′ , ea ). We now deduce the values that p read from ptr at the time of p’s last execution of line 56 before a, say T 56 , and from curr ptr at T . First ptr at T 56 . Since a is a list-remove attempt for ptr 78

between curr ptr and next ptr, we have that p read next ptr from (∗ptr).next.ptr on line 56 at T 56 . Now curr ptr at T . Since a′ is a successful list-remove attempt between curr ptr and next ptr, we have that (∗curr ptr).next.ptr = next ptr at a′ . Hence, since (∗curr ptr).next.ptr is unchanged during (a′ , ea ), we have that (∗curr ptr).next.ptr = next ptr throughout (a′ , ea ). Furthermore, since a′ < T and by Claim C.2.1.1 T < ea , we have that T ∈ (a′ , ea ). Hence, (∗curr ptr).next.ptr = next ptr at T . Therefore, since p executes a, a is a list-remove attempt for ptr between curr ptr and next ptr, and T is the time of p’s last execution of line 58 before a, we have that p read next ptr from (∗curr ptr).next.ptr at T . We now complete the proof of Case 2.2. Since T is the time of p’s last execution of line 58 before a, we have that p performed the following steps back-to-back: (1) line 58 at T ; (2) line 59 at some time T 59 ; and (3) line 61 at a. Therefore, since p read next ptr from (∗ptr).next.ptr at T 56 , and p read next ptr from (∗curr ptr).next.ptr at T , it follows that p found the second clause of line 59 to be true at T 59 . However, since p executed a after executing line 59 at T 59 , p found the second clause of line 59 to be false at T 59 , a contradiction, so this case is impossible. Claim C.2.1.2 We now return to the proof of Proposition C.2.1. Let a′ be the attempt identified in Claim C.2.1.2. By Definition C.1.5, a′ is of the form CAS((∗curr ptr).next, (v, ∗, ∗, ∗), (v + 1, ∗, ∗, ∗)) for some v. Thus, since a′ is successful, (∗curr ptr).next.view equals v at the step before a′ , and v + 1 at a′ . Hence, since curr ptr ∈ C ∪ {&H}, by Observation C.1.10, (∗curr ptr).next.view is monotonically increasing, and since a′ ∈ (T, a), it follows that (1) (∗curr ptr).next.view ≤ v at T , and (2) (∗curr ptr).next.view > v at the step before a. Since a is either a successful list-add attempt after curr ptr or a is a successful list-remove attempt between curr ptr and some pointer, by Definition C.1.5 a is of the form CAS((∗curr ptr).next, (v ′ , ∗, ∗, ∗), (v ′ + 1, ∗, ∗, ∗)) for some v ′ . Hence, by the definition of T , p read (∗curr ptr).next.view = v ′ at T . Thus, by (1), v ′ ≤ v. Therefore, since a is successful, (∗curr ptr).next.view = v ′ at the step before a, and since v ′ ≤ v, (∗curr ptr).next.view ≤ v at the step before a. However, this contradicts (2). Proposition C.2.1 This implies the following. Corollary C.2.2. Consider a successful list-add or list-remove attempt a in I B and let eb be its corresponding L-event (see Corollary C.1.37). If P (I B ), Q(I B ), and R(I B ) hold, then there are no L-events during (eb , a) in I B . Equivalently, eb is the last L-event before a in I B . We now “extend” R beyond the last L-event. We do so based on the type of the last L-event. Lemma C.2.3. Suppose I B has a last L-event denoted by e, and P (I B ), Q(I B ), and R(I B ) hold. If e is an L-add event for ptr, then from e onwards in I B , there is at most one successful list-add attempt for ptr and no other successful list-add or list-remove attempts for any pointer. Proof. Suppose, for contradiction, e is an L-add event for ptr, and at or after e in I B there is either at least two successful list-add attempts for ptr, one or more successful list-add attempts for a pointer other than ptr, or one or more successful list-remove attempts. We consider each case separately. Note that since e is an L-add event for ptr, by Lemma C.1.28, ptr ∈ C. Case 1. There are at least two successful list-add attempts for ptr at or after e in I B . Let a1 and a2 be the first two successful list-add attempts for ptr at or after e in I B such that a1 < a2 . Since a1 and a2 are in I B and Q(I B ) holds, by Lemma C.1.54, a1 and a2 are after the same curr ptr. Hence, a1 and a2 are two successful list-add attempts after curr ptr in I B such that a1 < a2 , so by Lemma C.1.122, there is a successful list-remove attempt between curr ptr and Null between a1 and a2 in I B . Therefore, since a1 is at or after e in I B , there is a successful list-remove attempt at or after e in I B , so this case reduces to the third case. 79

Case 2. There is a successful list-add attempt a for ptr′ ̸= ptr at or after e in I B . Hence, by Definition C.1.5, a was executed during an invocation of the DoAddCell procedure whose parameters are (∗, ptr′ ), and so by Corollary C.1.37, a’s corresponding event eb is an L-event for ptr′ . Thus, since e is for ptr and ptr′ ̸= ptr, we have that eb ̸= e. Therefore, since e is the last L-event in I B , we have that eb < e, and since e < a (because e ≤ a and e ̸= a since e is an L-event and a is a list-add attempt), we have that e ∈ (eb , a). However, since P (I B ), Q(I B ), and R(I B ) hold, and a is a successful list-add attempt in I B whose corresponding L-event is eb , by Corollary C.2.2, there are no L-events during (eb , a) in I B , a contradiction. Case 3. There is a successful list-remove attempt a at or after e in I B . By Definition C.1.5, a was executed during some invocation of the DoRemoveCell procedure, and so by Corollary C.1.37, a’s corresponding event eb is an L-remove event. Thus, since e is an L-add event, we have that eb ̸= e. Therefore, since e is the last L-event in I B , we have that eb < e, and since e < a (because e ≤ a and e ̸= a since e is an L-event and a is a list-remove attempt), we have that e ∈ (eb , a). However, since P (I B ), Q(I B ), and R(I B ) hold, and a is a successful list-remove attempt in I B whose corresponding L-event is eb , by Corollary C.2.2, there are no L-events during (eb , a) in I B , a contradiction. Lemma C.2.3 Lemma C.2.4. Suppose I B has a last L-event denoted as e, and P (I B ), Q(I B ), and R(I B ) hold. If e is an L-apply event, then from e onwards in I B there are no successful list-add or list-remove attempts. Proof. Let a be any list-add or list-remove attempts at or after e in I B . Hence, by Definition C.1.5, a was executed during some invocation of the DoAddCell or DoRemoveCell procedure. Thus, by Corollary C.1.37, a’s corresponding event eb is either an L-add or L-remove event. So, since e is an L-apply event, it follows that eb ̸= e. Therefore, since e is the last L-event in I B , we have that eb < e, and since e < a (because e ≤ a and e ̸= a since e is an L-event and a is a list-add or list-remove attempt), we have that e ∈ (eb , a). However, since P (I B ), Q(I B ), and R(I B ) hold, and a is a successful list-add or list-remove attempt in I B whose corresponding L-event is eb , by Corollary C.2.2, there are no L-events during (eb , a) in I B , a contradiction. Lemma C.2.4 Lemma C.2.5. Suppose I B has a last L-event denoted as e, and P (I B ), Q(I B ), and R(I B ) hold. If e is an L-remove event for ptr, then from e onwards in I B there is at most one successful list-remove attempt for ptr and no other successful list-remove or list-add attempt for any pointer. Proof. Suppose, for contradiction, e is an L-remove event for ptr, and at or after e in I B there is either at least two successful list-remove attempts for ptr, one or more successful list-remove attempts for a pointer other than ptr, or one or more successful list-add attempts. We consider each case separately. Note that since e is an L-remove event for ptr, by Lemma C.1.28, ptr ∈ C. Case 1. There are at least two successful list-remove attempts for ptr at or after e in I B . Let a1 and a2 be the first two successful list-remove attempts for ptr at or after e in I B such that a1 < a2 . Since a1 and a2 are in I B and Q(I B ) holds, by Lemma C.1.56, a1 and a2 are successful listremove attempts for ptr between the same prev ptr and next ptr, and by Lemma C.1.53 prev ptr ∈ C ∪ {&H}. Furthermore, since P (I B ) and Q(I B ) hold, by Lemma C.1.57, next ptr ̸= ptr. Since a1 and a2 are both successful list-remove attempts for ptr between prev ptr and next ptr, and prev ptr ∈ C ∪ {&H}, by Definition C.1.5, (∗prev ptr).next.ptr = ptr at the step before both a1 and a2 and (∗prev ptr).next.ptr = next ptr at a1 and a2 . Hence, since next ptr ̸= ptr and a1 < a2 , the value of (∗prev ptr).next.ptr was set to ptr during (a1 , a2 ). Thus, by Observation C.1.6, there 80

is either a successful list-add attempt for ptr after prev ptr or a successful list-remove attempt for some ptr′ between prev ptr and ptr during (a1 , a2 ). Since a1 is at or after e in I B , by transitivity, there is either a successful list-add attempt for ptr or a successful list-remove attempt for ptr′ at or after e in I B . If the former, then this case reduces to the third. If the latter, then by the minimality of a2 ptr′ ̸= ptr, so this case reduces to the second. Case 2. There is a successful list-remove attempt a for ptr′ ̸= ptr at or after e in I B . Hence, by Definition C.1.5, a was executed during an invocation of the DoRemoveCell procedure whose parameters are (∗, ptr′ ), and so by Corollary C.1.37, a’s corresponding event eb is an L-event for ptr′ . Thus, since e is for ptr and ptr′ ̸= ptr, we have that eb ̸= e. Therefore, since e is the last L-event in I B , we have that eb < e, and since e < a (because e ≤ a and e ̸= a since e is an L-event and a is a list-remove attempt), we have that e ∈ (eb , a). However, since P (I B ), Q(I B ), and R(I B ) hold, and a is a successful list-remove attempt in I B whose corresponding L-event is eb , by Corollary C.2.2, there are no L-events during (eb , a) in I B , a contradiction. Case 3. There is a successful list-add attempt a at or after e in I B . By Definition C.1.5, a was executed during some invocation of the DoAddCell procedure, and so by Corollary C.1.37, a’s corresponding event eb is an L-add event. Thus, since e is an L-remove event, we have that eb ̸= e. Therefore, since e is the last L-event in I B , we have that eb < e, and since e < a (because e ≤ a and e ̸= a since e is an L-event and a is a list-add attempt), we have that e ∈ (eb , a). However, since P (I B ), Q(I B ), and R(I B ) hold, and a is a successful list-add attempt in I B whose corresponding L-event is eb , by Corollary C.2.2, there are no L-events during (eb , a) in I B , a contradiction. Lemma C.2.5 We are now ready to prove that List(I) is essentially the “shape” of the list at the end of I. Lemma C.2.6. For every finite implementation history I of B, if P (I), Q(I), and R(I) hold, then the list of cells conforms to either one of two sequences in I: 1. if I has at least one L-event, the last L-event in I denoted by e is a L-add or L-remove event, and from e onwards in I there are no successful list-add or list-remove attempts, then the list of cells conforms to List(Ieexclude ) in I where Ieexclude is the prefix of I up to but excluding e; 2. otherwise, the list of cells conforms to List(I) in I. Proof. Let P(n) be the predicate: for every implementation history I of B of n steps, if P (I), Q(I), and R(I) hold, then the list of cells conforms to either one of two sequences in I as described in the statement of the lemma. We prove P(n) by induction on n. Base Case. P(0). Let I0 be an implementation history of B of zero steps. Hence, there are zero L-events in I0 . Thus, we must prove that the list of cells conforms to List(I) in I0 . Since there are zero L-events in I0 , by Definition C.1.7 List(I) = &H, Null, and so we must prove that H.next.ptr = Null at the end of I0 . Since the end of I0 is the initial configuration, this follows from the initialization of H. Inductive Case. ∀n P(n) =⇒ P(n + 1). Suppose for some n ≥ 0 P(n) holds. To prove that P(n + 1) holds, consider any implementation history In+1 of B of n + 1 steps, and suppose that P (In+1 ), Q(In+1 ), and R(In+1 ) hold. Let s be the last step in In+1 , and let In be the prefix of In+1 up to and including the nth step, so s is the only step in In+1 not in In . There are two cases.

81

Case 1. s is not a successful list-add or list-remove attempt. We start with a claim. Claim C.2.6.1. If the list of cells conforms to ptr0 , . . . , ptrm+1 in In , then the list of cells conforms to ptr0 , . . . , ptrm+1 in In+1 . Proof. Since by assumption the list of cells conforms to ptr0 , . . . , ptrm+1 in In , by Definition C.1.7, at the end of In , for all i ∈ [0..m], (∗ptri ).next.ptr = ptri+1 and ptri ∈ C ∪ {&H}. Hence, since s is the only step in In+1 not in In , s is not a successful list-add or list-remove attempt, and by Observation C.1.6 for all i ∈ [0..m] (∗ptri ).next.ptr only changes as the result of a successful list-add or list-remove attempt, at the end of In+1 , for all i ∈ [0..m], (∗ptri ).next.ptr = ptri+1 . Therefore, by Definition C.1.7, the list of cells conforms to ptr0 , . . . , ptrm+1 in In+1 as wanted. Claim C.2.6.1 We now return to the proof of Case 1. Since In is an implementation history of B of n steps, and by assumption P(n) holds, there are two cases. Case 1.1. In has at least one L-event, the last L-event in In denoted by e is a L-add or L-remove event, from e onwards in In there are no successful list-add or list-remove attempts, and the list of cells conforms to List(Ieexclude ) in In where Ieexclude is the prefix of In up to but excluding e. We start with two claims. Claim C.2.6.2. e is the last L-event in In+1 . Proof. Since In is a prefix of In+1 and e is in In , we have that e is in In+1 , and so In+1 has at least one L-event. Now suppose, for contradiction, that e is not the last L-event in In+1 . Hence, since e is in In+1 , and s is the only step in In+1 not in In , it follows that s is an L-event, and so e and s are successive L-events in In+1 . Thus, since by Case 1.1 e is either an L-add or L-remove event, by R(In+1 ), there is either a successful list-add attempt or a successful list-remove attempt between e and s. Therefore, since In is a prefix of In+1 up to s, we have that from e onwards in In there is either a successful list-add or a successful list-remove attempt. However, by Case 1.1 from e onwards in In there are no successful list-add or list-remove attempts, a contradiction. Claim C.2.6.2 Claim C.2.6.3. If the list of cells conforms to List(Ieexclude ) in In+1 , then P(n + 1) holds. Proof. This follows from three facts. (1) By Claim C.2.6.2 In+1 has at least one L-event. (2) Since by Case 1.1 e is a L-add or L-remove event, and by Claim C.2.6.2 e is the last L-event of In+1 , the last L-event in In+1 is an L-add or L-remove event. (3) Since by Case 1.1 from e onwards in In there are no successful list-add or list-remove attempts, by Case 1 s is not a successful list-add or list-remove attempt, and s is the only step in In+1 not in In , it follows that from e onwards in In+1 there are no successful list-add or list-remove attempts. Therefore, P(n + 1) requires that the list of cells conforms to List(Ieexclude ) in In+1 as wanted. Claim C.2.6.3 We now finish the proof of Case 1.1. Since by Case 1.1 the list of cells conforms to List(Ieexclude ) in In , by Claim C.2.6.1, the list of cells conforms to List(Ieexclude ) in In+1 . Therefore, by Claim C.2.6.3, P(n + 1) holds as wanted. Case 1.2. Either (1) In as zero L-events; (2) the last L-event in In is not an L-add or L-remove event; or (3) from the last L-event in In onwards in In , there is a successful list-add or list-remove attempt. In any case, the list of cells conforms to List(In ) in In . The core of the proof of Case 1.2 is the following claim. Claim C.2.6.4. If the list of cells conforms to List(In ) in In+1 , then P(n + 1) holds.

82

Proof. Since s is either not an L-event or it is an L-event, and by Lemma C.1.29, if s is an L-event then it is either an L-add, L-apply, or L-remove event, it follows that there are three cases. Case A. s is not an L-event. We first reduce the task of proving P(n + 1) to proving that the list of cells conforms to List(In+1 ) in In+1 .10 First, suppose (1) is true. Since In has zero L-events and s is the only step in In+1 not in In , there are zero L-events in In+1 . Thus, P(n + 1) requires that the list of cells conforms to List(In+1 ) in In+1 . Now suppose (2) is true. Since s is the only step in In+1 not in In and s is not an L-event, the last L-event is the same in In and In+1 , and since the last L-event in In is not an L-add or L-remove event, the last L-event in In+1 is not an L-add or L-remove event. Thus, P(n + 1) requires that the list of cells conforms to List(In+1 ) in In+1 . Finally, suppose (3) is true. By the same argument above, the last L-event is the same in In and In+1 , and since from the last L-event in In onwards in In there is a successful list-add or list-remove attempt, it follows that from the last L-event in In+1 onwards in In+1 there is a successful list-add or list-remove attempt. Thus, P(n + 1) requires that the list of cells conforms to List(In+1 ) in In+1 . Therefore, in all cases, P(n + 1) requires that the list of cells conforms to List(In+1 ) in In+1 . Since s is the only step in In+1 not in In and s is not an L-event, by Definition C.1.7, List(In ) = List(In+1 ), so if the list of cells conforms to List(In ) in In+1 , then P(n + 1) holds as wanted. Case B. s is an L-add or L-remove event. Hence, In+1 has at least one L-event, the last L-event in In+1 , s, is an L-add or L-remove event, and from s onwards in In+1 there are no successful list-add or list-remove attempts, so P(n + 1) requires that the list of cells conforms to List(Isexclude ) in In+1 where Isexclude is the prefix of In+1 up to but excluding s. Since s is the only step in In+1 not in In , we have that Isexclude = In , and so if the list of cells conforms to List(In ) in In+1 , then P(n + 1) holds as wanted. Case C. s is an L-apply event. Hence, the last L-event in In+1 , s, is not an L-add or L-remove event, so P(n + 1) requires that the list of cells conforms to List(In+1 ) in In+1 . Since s is an L-apply event, by Definition C.1.7, List(Isexclude ) = List(In+1 ) where Isexclude is the prefix of In+1 up to but excluding s, so P(n + 1) requires that the list of cells conforms to List(Isexclude ) in In+1 . Since s is the only step in In+1 not in In , we have that Isexclude = In , and so if the list of cells conforms to List(In ) in In+1 , then P(n + 1) holds as wanted. Claim C.2.6.4 We now finish the proof of Case 1.2. Since by Case 1.2 the list of cells conforms to List(In ) in In , by Claim C.2.6.1, the list of cells conforms to List(In ) in In+1 . Therefore, by Claim C.2.6.4, P(n + 1) holds as wanted. Case 2. s is a successful list-add or list-remove attempt. We start with a few claims. Claim C.2.6.5. Let e be the corresponding L-event of s. Then, e is the last L-event in In+1 . Proof. Since s is a successful list-add or list-remove attempt in In+1 , and by assumption P (In+1 ), Q(In+1 ), R(In+1 ) hold, by Corollary C.2.2, e is the last L-event before s in In+1 . Therefore, since s is the last step in In+1 and is not an L-event, the claim follows. Claim C.2.6.5 Claim C.2.6.6. If the list of cells conforms to List(In+1 ) in In+1 , then P(n + 1) holds. Proof. Since s is the last step of In+1 , s is a successful list-add or list-remove attempt, and by Claim C.2.6.5 e is a last L-event in In+1 , from e onwards in In+1 there is a successful list-add or list-remove attempt. Therefore, the claim follows from the definition of P(n + 1). Claim C.2.6.6 10

Notice that here we are referring to List(In+1 ) whereas the claim refers to List(In ).

83

Claim C.2.6.7. The following properties hold regarding In . 1. In has at least one L-event. 2. e is the last L-event in In and it is an L-add or L-remove event. 3. From e onwards in In there are no successful list-add or list-remove attempts. 4. The list of cells conforms to List(Ieexclude ) in In where Ieexclude is the prefix of In up to but excluding e. Proof. First 1. Since e is the corresponding L-event of s, by Corollary C.1.37, e < s. Hence, since s is the only step in In+1 not in In , we have that e is in In . Therefore, In has at least one L-event. Now 2. Since by 1 e is in In , by Claim C.2.6.5 e is the last L-event in In+1 , and In is a prefix of In+1 , we have that e is the last L-event in In . Furthermore, since e is the corresponding L-event of s and s is a successful list-add or list-remove attempt, by Corollary C.1.37, e is either an L-add or L-remove event. Now 3. Since by Claim C.2.6.5 e is the last L-event in In+1 , the last step of In+1 is a successful list-add or list-remove attempt, and P (In+1 ), Q(In+1 ), and R(In+1 ) hold, by Lemmas C.2.3 and C.2.5, s is the only successful list-add or list-remove attempt from e onwards in In+1 . Therefore, since s is the only step in In+1 not in In , it follows that from e onwards in In there are no successful list-add or list-remove attempts. Lastly 4. Since P(n) holds and In is a finite implementation history of B of n steps, by 1, 2, and 3, the list of cells conforms to List(Ieexclude ) in In as wanted. Claim C.2.6.7 We now return to the proof of Case 2. By Claim C.2.6.6, it suffices to prove that the list of cells conforms to List(In+1 ) in In+1 . Let List(Ieexclude ) = ptr0 , . . . , ptrm + 1 for some m. Since P (In+1 ) holds, by Lemma C.1.113, ptr0 = &H, for every i ∈ [1..m] ptri ∈ C, and ptrm+1 = Null. Also, note that since Ieexclude is the prefix of In up to but excluding e, and In is a prefix of In+1 , we have that Ieexclude is also the prefix of In+1 up to but excluding e. Case 2.1. s is a list-add attempt for some ptr after some curr ptr. Hence, by Lemma C.1.46 ptr ∈ C and by Lemma C.1.49 curr ptr ∈ C ∪ {&H}. Thus, since s is a list-add attempt for ptr, by Definition C.1.5, s was executed during an invocation of the DoAddCell procedure whose second parameter was ptr, so by Corollary C.1.37, its corresponding L-event is before s and is an L-add event for ptr. So, since by Claim C.2.6.5 e is the corresponding L-event of s, we have that e is an L-add event for ptr. Therefore, since e < s, by Q(In+1 ), e is the unique L-add event that precedes s, and since Ieexclude is the prefix of In+1 up to but excluding e, curr ptr is the second last pointer in List(Ieexclude ). Since List(Ieexclude ) = ptr0 , . . . , ptrm + 1, we have that curr ptr = ptrm , so s is a successful list-add attempt for ptr after ptrm . Furthermore, since by Claim C.2.6.5 e is the last L-event in In+1 , and Ieexclude is the prefix of In+1 up to but excluding e, we have that e is the only L-event in In+1 not in Ieexclude , and e is after all L-events in Ieexclude . Hence, since e is an L-add event for ptr, and List(Ieexclude ) = &H, ptr1 , . . . , ptrm , Null, by Definition C.1.7, List(In+1 ) = &H, ptr1 , . . . , ptrm , ptr, Null. Therefore, to prove that the list of cells conforms to List(In+1 ) in In+1 , by Definition C.1.7, we must prove that the following properties hold at the end of In+1 : (1) for all i ∈ [0..m) (∗ptri ).next.ptr = ptri+1 ; (2) (∗ptrm ).next.ptr = ptr; and (3) (∗ptr).next.ptr = Null. The following claims prove these properties, completing Case 2.1. Claim C.2.6.8. For all i ∈ [0..m), (∗ptri ).next.ptr = ptri+1 at the end of In+1 . Proof. Since by Claim C.2.6.7 the list of cells conforms to List(Ieexclude ) in In , and List(Ieexclude ) = ptr0 , . . . , ptrm+1 , by Definition C.1.7, at the end of In , for all i ∈ [0..m), (∗ptri ).next.ptr = ptri+1 . Hence, since s is the only step in In+1 not in In , it suffices to show that s does not change the value of 84

(∗ptri ).next.ptr for all i ∈ [0..m). This follows from three facts: (1) s is a successful list-add attempt for ptr after ptrm ; (2) since for all i ∈ [0..m) ptri ∈ C ∪{&H}, by Observation C.1.6, (∗ptri ).next.ptr only changes as the result of a successful list-add attempt after ptri or list-remove attempt between ptri and some pointer; and (3) since Ieexclude is a prefix of In+1 , List(Ieexclude ) = ptr0 , . . . , ptrm+1 , P (In+1 ) holds, and for all i ∈ [0..m) i ̸= m, by Lemma C.1.114, ptri ̸= ptrm . Claim C.2.6.8 Claim C.2.6.9. (∗ptrm ).next.ptr = ptr at the end of In+1 . Proof. s is a successful list-add attempt for ptr after ptrm .

Claim C.2.6.9

Claim C.2.6.10. (∗ptr).next.ptr = Null at the end of In+1 . Proof. Suppose, for contradiction, (∗ptr).next.ptr ̸= Null at the end of In+1 . Hence, since ptr ∈ C, (∗ptr).next.ptr is initialized to Null, and so it was changed in In+1 . Thus, by Observation C.1.6, there is a successful list-add attempt after ptr or a successful list-remove attempt between ptr and some pointer in In+1 . Let a be this successful list attempt. Hence, by Q(In+1 ), ptr ∈ List(Ieexclude ) ′ where e′ is the unique L-event preceding a in In+1 for the same pointer as a, and Ieexclude is the ′ prefix of In+1 up to but excluding e′ . Thus, since by Claim C.2.6.5 e is the last L-event in In+1 , we have that e′ ≤ e. Furthermore, since ptr ∈ C, by Assumption C.1.2, ptr ̸= &H and ptr ̸= Null, . ), by Definition C.1.7, there is a L-add event for ptr in Ieexclude and so since ptr ∈ List(Ieexclude ′ ′ exclude is the prefix of In+1 up to but excluding e′ , there is a L-add event for ptr Hence, since Ie′ before e′ in In+1 . Thus, since e′ ≤ e, there is a L-add event for ptr before e in In+1 . Therefore, since e is an L-add for ptr, it follows that there are two L-add events for ptr in In+1 . However, by P (In+1 ), there is at most one L-add event for ptr in In+1 , a contradiction. Claim C.2.6.10 Case 2.2. s is a list-remove attempt for some ptr between some prev ptr and some next ptr. Hence, by Lemma C.1.46 ptr ∈ C and by Lemma C.1.53 prev ptr ∈ C ∪ {&H} and next ptr ∈ C ∪ {Null}. Thus, since s is a list-remove attempt for ptr, by Definition C.1.5, s was executed during an invocation of the DoRemoveCell procedure whose second parameter was ptr, so by Corollary C.1.37, its corresponding L-event is before s and is an L-remove event for ptr. So, since by Claim C.2.6.5 e is the corresponding L-event of s, we have that e is an L-remove event for ptr. Therefore, since e < s, by Q(In+1 ), e is the unique L-remove event that precedes s, and since Ieexclude is the prefix of In+1 up to but excluding e, ptr is in List(Ieexclude ) exactly once and prev ptr and next ptr are the pointers preceding and succeeding ptr in List(Ieexclude ). Since ptr ∈ C, by Assumption C.1.2 ptr ̸= &H and ptr ̸= Null, and so since List(Ieexclude ) = &H, ptr1 , . . . , ptrm , Null, we have that ptr = ptri for a unique i ∈ [1..m], prev ptr = ptri−1 , and next ptr = ptri+1 , so s is a successful listremove attempt for ptri between ptri−1 and ptri+1 . Furthermore, since by Claim C.2.6.5 e is the last L-event in In+1 , and Ieexclude is the prefix of In+1 up to but excluding e, we have that e is the only L-event in In+1 not in Ieexclude , and e is after all L-events in Ieexclude . Hence, since e is an L-remove event for ptr, ptr = ptri for a unique i ∈ [1..m], and List(Ieexclude ) = &H, ptr1 , . . . , ptrm , Null, by Definition C.1.7, List(In+1 ) = &H, ptr1 , . . . , ptri−1 , ptri+1 , . . . , ptrm , Null. Therefore, to prove that the list of cells conforms to List(In+1 ) in In+1 , by Definition C.1.7, we must prove that the following hold at the end of In+1 : (1) for all j ∈ [0..i − 1) ∪ [i + 1..m], (∗ptrj ).next.ptr = ptrj+1 ; and (2) (∗ptri−1 ).next.ptr = ptri+1 . The following claims prove this, completing Case 2.2. Claim C.2.6.11. For all j ∈ [0..i − 1) ∪ [i + 1..m], (∗ptrj ).next.ptr = ptrj+1 at the end of In+1 . Proof. Since by Claim C.2.6.7 the list of cells conforms to List(Ieexclude ) in In , and List(Ieexclude ) = ptr0 , . . . , ptrm+1 , by Definition C.1.7, for all j ∈ [0..i−1)∪[i+1..m] (∗ptrj ).next.ptr = ptrj+1 at the end of In . Hence, since s is the only step in In+1 not in In , it suffices to show that s does not change (∗ptrj ).next.ptr for all j ∈ [0..i − 1) ∪ [i + 1..m]. This follows from three facts: (1) s is a successful 85

list-remove attempt for ptri between ptri−1 and ptri+1 ; (2) since for all j ∈ [0..i − 1) ∪ [i + 1..m] ptrj ∈ C ∪ {&H}, by Observation C.1.6, (∗ptrj ).next.ptr only changes as the result of a successful list-add for some pointer after ptrj or list-remove attempt for some pointer between ptrj and some pointer; and (3) since Ieexclude is a prefix of In+1 , List(Ieexclude ) = ptr0 , . . . , ptrm+1 , P (In+1 ) holds, and for all j ∈ [0..i − 1) ∪ [i + 1..m] j ̸= i − 1, by Lemma C.1.114, ptrj ̸= ptri−1 . Claim C.2.6.11 Claim C.2.6.12. (∗ptri−1 ).next.ptr = ptri+1 at the end of In+1 . Proof. s is a successful list-remove attempt between ptri−1 and ptri+1 .

Claim C.2.6.12 Lemma C.2.6

C.2.2

Each successful S-attempt is immediately after its corresponding L-event

In the last section, we proved, roughly speaking, that successful list-attempts are immediately after their corresponding L-event. We now prove analogous facts for S-attempts. These facts are useful because they let us prove the invariant O, and subsequently define the linearization points for B. Lemma C.2.7. Consider an S-attempt a in I B and let eb be its corresponding L-event (see Corollary C.1.37). Suppose there is a L-event after eb in I B and that P (I B ) and O(I B ) holds. Let ea be the next L-event after eb in I B . If ea < a, then a is unsuccessful. Proof. Suppose, for contradiction, ea < a and a is successful. Without loss of generality, suppose a is the first such S-attempt in I B . More precisely, for every S-attempt a′ before a in I B , if e′b is a′ ’s corresponding L-event, e′a is the next L-event after e′b in I B , and e′a < a′ , then a′ is unsuccessful. Let p be the process that executed a, and let T 66 be the last time p executed line 66 before a. Hence, by Definition C.1.5, p executed T 66 and a during the same invocation I of the DoApply&CopyResponse procedure. Let the first parameter of I be ulloL . Hence, since eb is a’s corresponding L-event, by Corollary C.1.37, eb set L.ullo = ulloL , eb is an L-apply event, and eb is before I was invoked. Thus, by O(I B ), there is exactly one successful S-attempt between eb and ea ; say a′ . We now prove two simple facts about T 66 and a′ . Claim C.2.7.1. T 66 ∈ (eb , ea ). Proof. Since eb is before I was invoked and T 66 is during I, we have that eb < T 66 , so it suffices to prove that T 66 < ea . Suppose, for contradiction, that ea < T 66 . Let T 67 be the time of p’s execution of line 67 between T 66 and a. Since eb < ea , ea < T 66 , and T 66 < T 67 , by transitivity, eb < ea < T 67 . Furthermore, since p executed a, we have that p found the condition on line 67 to be false at T 67 . Hence, since the first parameter of I is ulloL , we have that L.ullo = ulloL at T 67 . Thus, since eb set L.ullo = ulloL , the value of L.ullo is the same at eb and T 67 . So, since eb < ea < T 67 , it follows that that L.ullo was set to ulloL during (eb , T 67 ), and thus by Observation C.1.6, there is an L-event during (eb , T 67 ) that set L.ullo = ulloL . Therefore, since eb set L.ullo = ulloL , there are two L-events in I B that set L.ullo = ulloL . However, since P (I B ) holds, by Lemma C.1.32, every L-event in I B sets L.ullo to a unique value, a contradiction. Claim C.2.7.1 Claim C.2.7.2. S.ullo = ulloL at a′ . Proof. Suppose q executed a′ . Hence, by Definition C.1.5, q executed a′ during some invocation I ′ of the DoApply&CopyResponse procedure. By O(I B ), eb and a′ are for the same timestamp; say t. Hence, by Definition C.1.5, the first parameter of I ′ is some ullo = (t, ∗). Thus, by Corollary C.1.37, there is an L-event e′b that set L.ullo = ullo, and so by Definition C.1.5, e′b is for timestamp t. So, since eb is for timestamp t, and P (I B ) holds, by Lemma C.1.33, eb = e′b . Hence, since e′b set L.ullo = ullo and eb set L.ullo = ulloL , we have that ullo = ulloL . Thus, the first parameter of I ′ is ulloL . Therefore, since a′ is successful, we have that S.ullo = ulloL at a′ as wanted. Claim C.2.7.2 86

We now identify a successful S-attempt that contradicts the minimality of a. Claim C.2.7.3. The corresponding L-event of a successful S-attempt during (a′ , a) is before eb . Proof. There are two cases. Case 1. T 66 < a′ . Since by Claim C.2.7.1 T 66 ∈ (eb , ea ), and a′ ∈ (eb , ea ), by transitivity, eb < T 66 < a′ < ea . Suppose p read ullo from S.ullo at T 66 . Since p executed T 66 and a during I, we have that p found the condition on line 68 to be true during I. Hence, since I’s first parameter is ulloL , we have that ullo ̸= ulloL . Furthermore, since p executed a during I, p read ullo from S.ullo at T 66 , and by assumption a is successful, we have that S.ullo = ullo at the step before a. Hence, since a′ < a (because a′ < ea and ea < a), by Claim C.2.7.2 S.ullo = ulloL at a′ , and ullo ̸= ulloL , we have that some step set the value of S.ullo = ullo during (a′ , a). Thus, by Observation C.1.6, some successful S-attempt a∗ set the value of S.ullo = ullo during (a′ , a). So, by Lemma C.1.45, a∗ is for a timestamp larger than 0, and so ullo ̸= (0, ∗). Thus, since p read ullo from S.ullo at T 66 and the initial value of S.ullo = (0, Noop), we have that S.ullo was set to ullo before T 66 . Therefore, by Observation C.1.6, some successful S-attempt â set S.ullo = ullo before T 66 . Let q be the process that executed a∗ , and let e∗b be a∗ ’s corresponding L-event. Since a∗ set S.ullo = ullo, by Corollary C.1.37, e∗b set L.ullo = ullo. Thus, since eb set L.ullo = ulloL and ullo ̸= ulloL , we have that e′b ̸= eb . We now prove that e∗b ≤ eb . Let r be the process that executed â, and let eˆb be â’s corresponding L-event. Since â set S.ullo = ullo, by Lemma C.1.43, eˆb set L.ullo = ullo. Hence, since e∗b and eˆb are two L-events in I B that set L.ullo = ullo and P (I B ) holds, by Lemma C.1.32, e∗b = eˆb . Since by Claim C.2.7.1 T 66 ∈ (eb , ea ), and eb and ea are successive L-events, eb is the last L-event before T 66 . Furthermore, since eˆb < â and â < T 66 , by transitivity, eˆb < T 66 , and since e∗b = eˆb , we have that e∗b < T 66 . Therefore, since eb is the last L-event before T 66 , and e∗b is an L-event before T 66 , we have that e∗b ≤ eb as wanted. Since e∗b ̸= eb and e∗b ≤ eb , we have that e∗b < eb . Therefore, there is a successful S-attempt during (a′ , a) (namely a∗ ) whose corresponding L-event (namely e∗b ) is before eb as wanted. Case 2. a′ < T 66 . Since by Claim C.2.7.1 T 66 ∈ (eb , ea ) and a′ ∈ (eb , ea ), by transitivity, eb < a′ < T 66 < ea . Hence, since a′ is the only successful S-attempt during (eb , ea ), and by Claim C.2.7.2 S.ullo = ulloL at a′ , we have that S.ullo = ulloL throughout (a′ , ea ). Thus, since T 66 ∈ (a′ , ea ), we have that p read ulloL from S.ullo on line 66 at T 66 . Hence, since I’s first parameter is ulloL , we have that p finds the condition on line 68 to be false during I. Therefore, p does not execute line 71 during I. However, p executes a during I, a contradiction, so this case is impossible. Claim C.2.7.3 We now finish the proof of Lemma C.2.7. Let a∗ be the successful S-attempt identified by Claim C.2.7.3 and let e∗b be its corresponding L-event. Hence, a∗ is during (a′ , a) and e∗b < eb . Since e∗b < eb , it follows that there is an L-event after e∗b . Let e∗a be the next L-event after e∗b . Hence, since e∗b < eb , we have that e∗a ≤ eb . Thus, since eb < a′ (because a′ ∈ (eb , ea )) and a′ < a∗ (because a∗ ∈ (a′ , a)), by transitivity, e∗a < a∗ . Therefore, since a∗ < a, we have shown that a∗ is a successful S-attempt before a such that the next L-event after a∗ ’s corresponding L-event is before a∗ . However, by the minimality of a, a∗ must be unsuccessful, a contradiction. Lemma C.2.7 This implies the following. Corollary C.2.8. Consider a successful S-attempt a in I B and let eb be its corresponding L-event (see Corollary C.1.37). If P (I B ) and O(I B ) hold, then there are no L-events during (eb , a) in I B . 87

We now “extend” O beyond the last L-event. We do so based on the type of the last L-event. Lemma C.2.9. Suppose I B has a last L-event denoted as e and P (I B ) and O(I B ) hold. If e is an L-apply event for a timestamp t, then from e onwards in I B there is at most one successful S-attempt for t and no other successful S-attempts for any timestamp. Proof. Suppose, for contradiction, e is a L-apply event for timestamp t, so by Lemma C.1.26 t ̸= 0, and at or after e in I B there is either at least two successful S-attempts for t, or one or more successful S-attempts for a timestamp other than t. We consider each case separately. Case 1. There are at least two successful S-attempts for t at or after e in I B . Let a1 and a2 be the first two successful S-attempts for t at or after e in I B . Without loss of generality, suppose a1 < a2 . Let p1 (resp. p2 ) be the process that executed a1 (resp. a2 ). Furthermore, let e1 (resp. e2 ) be a1 ’s (resp. a2 ’s) corresponding L-event (see Corollary C.1.37). Since a1 and a2 are for timestamp t, by Corollary C.1.44, e1 and e2 are for timestamp t. Since e, e1 , and e2 are all L-events in I B for timestamp t, and P (I B ) holds, by Lemma C.1.33, e = e1 = e2 , so by Lemma C.1.43 a1 and a2 set S.ullo to the same value; say ulloL . So, by Lemma C.1.43, e set L.ullo = ulloL . Let I1 and I2 be the invocations of the DoApply&CopyResponse procedure that a1 and a2 are executed during, respectively, so the first parameter of I1 and I2 is ulloL . Since p2 executed a2 during I2 , p2 found the condition on line 68 to be true during I2 . Hence, p2 read S.ullo = ullo on line 66 during I2 , say at time T 66 , such that ullo ̸= ulloL . We now prove that there is a successful S-attempt that set S.ullo = ullo between a1 and a2 (*). There are two cases. Case 1.1. T 66 < a1 . Hence, since a1 < a2 , by transitivity, T 66 < a1 < a2 . Thus, since S.ullo = ullo at T 66 , S.ullo = ulloL at a1 , ullo ̸= ulloL , and a2 is successful, we have that S.ullo was set to ullo between a1 and a2 . Hence, by Observation C.1.6, (*) follows. Case 1.2. a1 < T 66 . Hence, since T 66 < a2 , by transitivity, a1 < T 66 < a2 . Since a1 set S.ullo = ulloL , S.ullo = ullo at T 66 , and ullo ̸= ulloL , we have that S.ullo was set to ullo between a1 and T 66 . Hence, by Observation C.1.6, there is a successful S-attempt that set S.ullo = ullo between a1 and T 66 . Therefore, since T 66 < a2 , (*) follows. We now finish the proof of Case 1. Let a′ be the successful S-attempt that set S.ullo = ullo between a1 and a2 identified by (*). Let e′ be a′ ’s corresponding L-event, so by Lemma C.1.43, e′ set L.ullo = ullo. Hence, since e set L.ullo = ulloL , and ullo ̸= ulloL , we have that e ̸= e′ . Thus, since e and e′ are two different L-events in I B , e is for timestamp t, and P (I B ) holds, by Lemma C.1.33, e′ is for a timestamp t′ ̸= t. Hence, since e′ is a′ ’s corresponding L-event, and e′ is for timestamp t′ , by Corollary C.1.44, a′ is for timestamp t′ . Thus, there is a successful S-attempt for a timestamp other than t between a1 and a2 . So, since a1 is at or after e in I B , we have that there is a successful S-attempt for a timestamp other than t at or after e in I B . Therefore, this case reduces to the next one. Case 2. There is a successful S-attempt a for a timestamp other than t at or after e in I B . We will apply Lemma C.2.7. Suppose eb is a’s corresponding L-event and suppose a is for timestamp t′ ̸= t. Hence, by Corollary C.1.44, eb is for timestamp t′ . Thus, since t′ ̸= t and e is for timestamp t, we have that eb ̸= e. So, since eb < a, a is in I B , and e is the last L-event in I B , we have that 88

eb < e. Hence, there is a next L-event after eb in I B ; say ea . Thus, ea ≤ e, and since e < a, by transitivity, ea < a. Therefore, since P (I B ) and O(I B ) hold, by Lemma C.2.7, a is unsuccessful. However, a was assumed to be successful, a contradiction. Lemma C.2.9 Lemma C.2.10. Suppose I B has a last L-event denoted as e and P (I B ) and O(I B ) hold. If e is an L-add or L-remove event, then from e onwards in I B there are no successful S-attempts. Proof. Suppose, for contradiction, e is a L-add or L-remove event and at or after e in I B there is a successful S-attempt a. We will apply Lemma C.2.7. Suppose eb is a’s corresponding L-event, so by Corollary C.1.37, eb is an L-apply event. Hence, since e is an L-add or L-remove event, it follows that eb ̸= e. Thus, since eb < a, a is in I B , and e is the last L-event in I B , we have that eb < e. Hence, there is a next L-event after eb in I B ; say ea . Thus, ea ≤ e, and since e < a, by transitivity, ea < a. Therefore, since P (I B ) and O(I B ) hold, by Lemma C.2.7, a is unsuccessful. However, a was assumed to be successful, a contradiction. Lemma C.2.10 C.2.3

The AcquireNext procedure has the intended effect

We are now ready to prove that various procedures have the intended effect: once they exit, what they were trying to do is done. Lemma C.2.11. Suppose some process p exited some invocation I of the AcquireNext procedure with parameters (ulloL , curr ptr) in I B . By Corollary C.1.89, curr ptr ∈ C ∪ {&H}. Let T 104 (resp. T 105 ) be the last time p executed line 104 (resp. line 105) during I. If L.ullo = ulloL at T 105 , then 1. if (∗curr ptr).next.ptr = Null at T 104 , then I’s response is (NotFound, ∗); otherwise 2. I’s response is (Found, next ptr) where (∗curr ptr).next.ptr = next ptr at T 104 . Proof. Since L.ullo = ulloL at T 105 , it follows that p finds the condition on line 105 to be false at T 105 . Hence, since p exits I, p executes line 107 after T 105 during I. Let T 107 be the time of p’s next execution of line 107 after T 105 . By definition T 104 < T 105 < T 107 , and T 104 , T 105 , and T 107 occur within the last iteration I ′ of the loop on line 103 during I. There are two cases. Case 1. (∗curr ptr).next.ptr = Null at T 104 . Hence, p finds the condition on line 107 to be true at T 107 . Therefore, since p exits I, p exits on line 108 with response (NotFound, ∗) as required. Case 2. (∗curr ptr).next.ptr ̸= Null at T 104 . Let (∗curr ptr).next.ptr = next ptr at T 104 . Hence, next ptr ̸= Null. Thus, p finds the condition on line 107 to be false at T 107 . Since (1) T 104 , T 105 , and T 107 are within I ′ , (2) I ′ is the last iteration of the loop on line 103 during I, (3) p exits I, (4) p finds the condition on line 105 to be false at T 105 , and (5) p finds the condition on line 107 to be false at T 107 , we have that p finds the condition on line 109 to be true during I ′ . Therefore, since p exits I, we have that p exits I on line 110 with the response (Found, next ptr) as required. Lemma C.2.11 C.2.4

The Acquire procedure has the intended effect

Lemma C.2.12. Suppose some process p exited some invocation I of the Acquire procedure in I B with parameters (ulloL , target ptr) for some target ptr ∈ C and returns response status. Let Tb be the time p invoked I, and let T 105 be the last time p executes line 105 during I. Recall that T 105 is well-defined by Corollary C.1.93. If P (I B ) holds and for some finite prefix I of I B the following two conditions hold for every prefix I ′ of I B during [Tb , T 105 ]: 89

• L.ullo = ulloL at the end of I ′ ; and • the list of cells conforms to List(I) in I ′ then 1. if target ptr ∈ List(I), then status = Found; and 2. if target ptr ̸∈ List(I), then status = NotFound. Proof. We start by showing that our first assumption implies the following claim. As we will see, this claim is useful for satisfying the conditions of Lemma C.2.11 and our second assumption. Claim C.2.12.1. Consider any invocation I ∗ of the AcquireNext procedure on line 95 during I. Note that since I exits I ∗ exits. Let TI104 (resp. TI105 ∗ ∗ ) be the last time p executes line 104 (resp. ∗ line 105) during I (these are well-defined since I ∗ exits). Then, the following are true: • L.ullo = ulloL at TI105 ∗ ; and • TI104 ∈ [Tb , T 105 ]. ∗ Proof. First 1. Since by the first assumption of Lemma C.2.12 L.ullo = ulloL at the end of I ′ for every prefix I ′ of I in [Tb , T 105 ], we have that L.ullo = ulloL throughout [Tb , T 105 ]. Since I was invoked at Tb , I ∗ was invoked during I, TI105 is the last time p executes line 105 during I ∗ , and T 105 ∗ is the last time p executes line 105 during I, by transitivity, TI105 ∈ [Tb , T 105 ]. Hence, since L.ullo = ∗ 105 105 ulloL throughout [Tb , T ], we have that L.ullo = ulloL at TI ∗ . Now 2. Since I was invoked at Tb , I ∗ was invoked during I, and TI104 is the time of a step during I ∗ , by transitivity, Tb < TI104 ∗ ∗ . 104 105 105 Hence, since TI ∗ < TI ∗ and TI ∗ ∈ [Tb , T 105 ], by transitivity, TI104 ∈ [Tb , T 105 ]. ∗ Claim C.2.12.1 We now prove that I “traverses” List(I). By Definition C.1.7, List(I) = ptr0 , . . . , ptrn+1 for some n. Hence, by Lemma C.1.113, ptr0 = &H, for every i ∈ [1..n] ptri ∈ C, and ptrn+1 = Null. Claim C.2.12.2. Consider any iteration of the loop on line 94 during I, denoted by I ′ , such that the local variable curr ptr = ptri for some i ∈ [0..n) at the start of I ′ .11 If ptri ̸= target ptr, then p executes line 100 at some time T 100 during I ′ and curr ptr = ptri+1 at T 100 . Proof. Since curr ptr = ptri at the start of I ′ , and ptri ̸= target ptr, we have that p finds the condition on line 94 to be true at the start of I ′ . Hence, since p exits I, p begins and exits the AcquireNext procedure on line 95 during I ′ . Denote this invocation by I ∗ . We first prove that I ∗ ’s response is (Found, ptri+1 ) by satisfying the conditions of Lemma C.2.11. Since the first parameter of I is ulloL and curr ptr = ptri at the start of I ′ , the parameters of I ∗ are (ulloL , ptri ). Let TI104 and TI105 by defined as in Claim C.2.12.1, and so L.ullo = ulloL ∗ ∗ 105 104 105 at TI ∗ , and TI ∗ ∈ [Tb , T ]. Hence, there is a prefix of I during [Tb , T 105 ] up to and includ′ ing TI104 ∗ ; say I . Thus, by the second assumption of Lemma C.2.12, the list of cells conforms to ′ List(I) in I . So, since List(I) = ptr0 , . . . , ptrn+1 , and i ∈ [0..n], by Definition C.1.7, at the end of I ′ (∗ptri ).next.ptr = ptri+1 . Thus, since ptri+1 ∈ C (because i + 1 ∈ [1..n]), by Assumption C.1.2 ptri+1 ̸= Null, and so (∗ptri ).next.ptr = ptri+1 ̸= Null at the end of I ′ . Therefore, we have established the following: (1) I ∗ has parameters (ulloL , ptri ); (2) L.ullo = ulloL at TI105 ∗ ; 104 ′ and (3) (∗ptri ).next.ptr = ptri+1 ̸= Null at TI ∗ (this is equivalent to the end of I ), and so by Lemma C.2.11, I ∗ ’s response is (Found, ptri+1 ) as wanted. We now finish the proof of Claim C.2.12.2. Since I ∗ ’s response is (Found, ptri+1 ), and p exits I, we have that p finds the condition on line 99 to be true during I ′ , and so p executes line 100 during I ′ ; say at time T 100 . Therefore, curr ptr = ptri+1 at T 100 as wanted. Claim C.2.12.2 11

The start of an iteration I of a loop on line X refers to the time line X was executed during I.

90

Claim C.2.12.3. Suppose for some i ∈ [1..n] for every j ∈ [0..i − 1] ptrj ̸= target ptr. Then, for every j ∈ [1..i + 1], (1) p executes line 94 j times during I and (2) at the time p executes line 94 for the jth time during I the local variable curr ptr = ptrj−1 . Proof. By induction on j. Base Case. j = 1. In this case, (1) holds immediately since p must execute line 94 at least once during I as p exits I. Let T194 be the time of p’s first execution of line 94 during I. For (2), since curr ptr at T194 is the value it was initialized to on line 93 during I, we have that curr ptr = &H at T194 . Therefore, since ptr0 = &H, we have that curr ptr = ptr0 at T194 as wanted. Inductive Case. For every j ∈ [1..i], if (1) and (2) hold for j, then (1) and (2) hold for j + 1. Suppose for any j ∈ [1..i] (1) p executes line 94 j times during I and (2) at the time p executes line 94 for the jth time during I curr ptr = ptrj−1 . This is the inductive hypothesis. Let Ij be the jth iteration of the loop on line 94 during I, which is well-defined by (1) of the inductive hypothesis. Furthermore, let Tj94 be the time of p’s jth execution of line 94 during I which is the start of Ij . Since by (2) of the inductive hypothesis curr ptr = ptrj−1 at Tj94 where j − 1 ∈ [0..n) (since j ∈ [1..i] and i ∈ [1..n]), and by assumption ptrj−1 ̸= target ptr (since j − 1 ∈ [0..i − 1]), by Claim C.2.12.2, p executes line 100 at some time Tj100 during Ij and curr ptr = ptrj at Tj100 . Hence, since p exits I, it follows that p executes line 94 one more time during I, so p executes line 94 j + 1 times during I. Since curr ptr = ptrj at Tj100 , and the value of curr ptr does not change between Tj100 and the time of p’s j + 1th execution of line 94 during I, it follows that at the time p executes line 94 for the j + 1th time during I curr ptr = ptrj . Therefore, (1) and (2) hold for j + 1 as wanted. Claim C.2.12.3 We now complete the proof of Lemma C.2.12. There are two cases. Case 1. target ptr ∈ List(I). Since target ptr ∈ C, by Assumption C.1.2, target ptr ̸= &H and target ptr ̸= Null. Hence, since target ptr ∈ List(I), List(I) = ptr0 , . . . , ptrn+1 , ptr0 = &H, and ptrn+1 = Null, we have that target ptr = ptri for some i ∈ [1..n]. Since I is a finite prefix of I B , List(I) = ptr0 , . . . , ptrn+1 , and P (I B ) holds, by Lemma C.1.114, for every j ∈ [0..n + 1] if j ̸= i, then ptrj ̸= ptri , so ptrj ̸= target ptr. Hence, for every j ∈ [0..i − 1] ptrj ̸= target ptr. Thus, by Claim C.2.12.3, p executes line 94 i + 1 times during I and at the time p executes line 94 for the i + 1th time during I curr ptr = ptri . Since target ptr = ptri , this implies that p finds the condition on line 94 to be false during I. Therefore, p executes line 101 during I, and so status = Found as wanted. Case 2. target ptr ∈ / List(I). Hence, for every j ∈ [1..n] ptrj ̸= target ptr. Thus, by Claim C.2.12.3, p executes line 94 n + 1 times during I and at the time p executes line 94 for the n + 1th time during I curr ptr = ptrn . Let In+1 be the n + 1th iteration of the loop on line 94 during I. Since p exits I, p invokes and exits the AcquireNext procedure during In+1 . Denote this invocation by I ∗ . We first prove that I ∗ ’s response is (NotFound, ∗) by satisfying the conditions of Lemma C.2.11. Since the first parameter of I is ulloL and curr ptr = ptrn at the start of In+1 , the parameters of I ∗ are (ulloL , ptrn ). Let TI104 and TI105 by defined as in Claim C.2.12.1, and so L.ullo = ulloL at TI105 ∗ ∗ ∗ , 104 105 and TI ∗ ∈ [Tb , T ]. Hence, there is a prefix of I during [Tb , T 105 ] up to and including TI104 ; say ∗ I ′ . Thus, by the second assumption of Lemma C.2.12, the list of cells conforms to List(I) in I ′ . So, 91

since List(I) = ptr0 , . . . , ptrn+1 , by Definition C.1.7, at the end of I ′ (∗ptrn ).next.ptr = ptrn+1 . Hence, since ptrn+1 = Null, we have that (∗ptrn ).next.ptr = Null at the end of I ′ . Therefore, we have established the following: (1) I ∗ has parameters (ulloL , ptrn ); (2) L.ullo = ulloL at TI105 ∗ ; ′ ), by Lemma C.2.11, and (3) (∗ptrn ).next.ptr = Null at TI104 (this is equivalent to the end of I ∗ I ∗ ’s response is (NotFound, ∗) as wanted. We now finish the proof of Case 2. Since I ∗ ’s response is (NotFound, ∗), and p exits I, we have that p finds the condition on line 97 to be true during In+1 , and so p executes line 98 during In+1 . Therefore, given the response of I ∗ , it follows that status = NotFound as wanted. Lemma C.2.12 C.2.5

The DoAddCell procedure has the intended effect

In this section, we prove that the DoAddCell procedure with parameters (∗, ptrL ) has the intended effect: (1) once it exits there is a successful list-add attempt for ptrL ; and (2) once it exits there is a successful add-response-set attempt for ptrL . Lemma C.2.13. Consider any invocation of the DoAddCell procedure with a second parameter of ptrL which exits the loop on line 30 at some time T exit during I B . If P (I B ), Q(I B ), and R(I B ) hold, then there is a successful list-add attempt for ptrL before T exit . Proof. Suppose, for contradiction, there is an invocation I of the DoAddCell procedure with parameters (ulloL , ptrL ) which exits the loop on line 30 at some time T exit during I B such that there is not a successful list-add attempt for ptrL before T exit in I B . Let p be the process that invoked I. Since I has parameters (ulloL , ptrL ), by Corollary C.1.37, there is an L-add event e for ptrL before I was invoked that set L to (ulloL , ptrL ). Hence, by Lemma C.1.28 ptrL ∈ C. Furthermore, since e is before I was invoked and T exit is after I was invoked, by transitivity, e < T exit , thus all steps during the loop line 30 during I are during (e, T exit ]. There are two cases. Suppose during (e, T exit ] there is at least one L-event in I B . Let ea be the next L-event after e in I B . Hence, since e and ea are successive L-events in I B , and e is an L-add event for ptrL , by R(I B ), there is a successful list-add attempt for ptrL during (e, ea ). Therefore, since ea < T exit , by transitivity, there is a successful list-add attempt for ptrL before T exit . However, by our initial assumption of Lemma C.2.13, there are no successful list-add attempts for ptrL before T exit , a contradiction. Now suppose during (e, T exit ] there are no L-events. Hence, e is the last L-event in I where I is any prefix of I B during (e, T exit ]. Thus, since e set L.ullo = ulloL , by Observation C.1.6, L.ullo = ulloL throughout (e, T exit ] (*). We first show (e, T exit ] is desolate in two other senses. Claim C.2.13.1. There are no successful list-add or list-remove attempts during (e, T exit ]. Proof. Let I be the prefix of I B up to and including T exit , so by (*) e is the last L-event in I. Hence, since P (I B ), Q(I B ), and R(I B ) hold, and the last L-event in I, e, is an L-add event for ptrL , by Lemma C.2.3, from e onwards in I there is at most one successful list-add attempt for ptrL and no other successful list-add or list-remove attempts for any other pointer. So, since I is the prefix of I B up to and including T exit , during (e, T exit ] there is at most one successful list-add attempt for ptrL and no other successful list-add or list-remove attempts for any other pointer. If during (e, T exit ] there is a successful list-add attempt for ptrL , there would be a successful list-add attempt for ptrL before T exit , contradicting our initial assumption of Lemma C.2.13. Therefore, there are no successful list-add or list-remove attempts during (e, T exit ] as wanted. Claim C.2.13.1 Claim C.2.13.2. For every prefix I of I B during (e, T exit ], the list of cells conforms to List(Ieexclude ) in I where Ieexclude is the prefix of I B up to but excluding e.

92

Proof. For the first part, consider any prefix I of I B during (e, T exit ]. Hence, by (*) e is the last L-event in I, and so the last L-event in I is an L-add event. Furthermore, since by Claim C.2.13.1 there are no successful list-add or list-remove attempts during (e, T exit ], we have that from e onwards in I there are no successful list-add or list-remove attempts. Thus, since I is finite and by assumption P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(Ie ) in I where Ie is the prefix of I up to but excluding e. Therefore, since I is a prefix of I B after e, Ie = Ieexclude , and so the list of cells conforms to List(Ieexclude ) in I as wanted. Claim C.2.13.2 We now prove that I “traverses” List(Ieexclude ). The following three claims will be reminiscent of the proof of Lemma C.2.12. Let List(Ieexclude ) = ptr0 , . . . , ptrn+1 for some n ≥ 0. Hence, by Lemma C.1.113, ptr0 = &H, for every i ∈ [1..n] ptri ∈ C, and ptrn+1 = Null. Furthermore, since P (I B ) holds, by Lemma C.1.117, ptrL ∈ / List(Ieexclude ), so for every i ∈ [0..n + 1] ptri ̸= ptrL (**). Claim C.2.13.3. Consider any invocation I ∗ of the AcquireNext procedure on line 31 during I. Since I exits the loop on line 30 I ∗ exits. Let TI104 (resp. TI105 ∗ ∗ ) be the last time p executes line 104 ∗ ∗ (resp. line 105) during I (these are well-defined since I exits). Then, the following are true: • L.ullo = ulloL at TI105 ∗ ; and exit 104 ]. • TI ∗ ∈ (e, T Proof. First 1. Since I ∗ began and exited during the loop on line 30 in I, all steps during the loop on line 30 during I are during (e, T exit ], and by (*) L.ullo = ulloL throughout (e, T exit ], we have that L.ullo = ulloL throughout I ∗ . Hence, since TI105 is the time of a step during I ∗ , we have that ∗ 105 L.ullo = ulloL at TI ∗ . Now 2. Since all steps during the loop on line 30 during I are during ∈ (e, T exit ]. is the time of a step during I ∗ , we have that TI104 (e, T exit ], and TI104 ∗ ∗ Claim C.2.13.3 Claim C.2.13.4. Consider any iteration of the loop on line 30 during I, denoted by I ′ , such that the local variable curr ptr = ptri for some i ∈ [0..n) at the start of I ′ . Then, p executes line 40 at time T 40 during I ′ and the local variable curr ptr = ptri+1 at T 40 . Proof. Since by (**) for every i ∈ [0..n + 1] ptri ̸= ptrL , and by assumption curr ptr = ptri at the start of I ′ for some i ∈ [0..n), it follows that p finds the condition on line 30 to be true at the start of I ′ . Hence, since p exits the loop on line 30 during I, p begins and exits the AcquireNext procedure on line 31 during I ′ . Denote this invocation by I ∗ . We first prove that I ∗ ’s response is (Found, ptri+1 ) by satisfying the conditions of Lemma C.2.11. Since the first parameter of I is ulloL and curr ptr = ptri at the start of I ′ , the parameters of I ∗ are (ulloL , ptri ). Let TI104 and TI105 by defined as in Claim C.2.13.3, and so L.ullo = ulloL ∗ ∗ 105 104 exit at TI ∗ , and TI ∗ ∈ (e, T ]. Hence, there is a prefix of I B during (e, T exit ] up to and inexclude ) in I. cluding TI104 ∗ ; say I. Thus, by Claim C.2.13.2 the list of cells conforms to List(Ie exclude So, since List(Ie ) = ptr0 , . . . , ptrn+1 , and i ∈ [0..n], by Definition C.1.7, at the end of I (∗ptri ).next.ptr = ptri+1 . Thus, since ptri+1 ∈ C (because i + 1 ∈ [1..n]), by Assumption C.1.2 ptri+1 ̸= Null, and so (∗ptri ).next.ptr = ptri+1 ̸= Null at the end of I. Therefore, we have established the following: (1) I ∗ has parameters (ulloL , ptri ); (2) L.ullo = ulloL at TI105 ∗ ; and (3) 104 (∗ptri ).next.ptr = ptri+1 ̸= Null at TI ∗ (equivalently, the end of I), and so by Lemma C.2.11, I ∗ ’s response is (Found, ptri+1 ). We now finish the proof of Claim C.2.13.4. Since p exits the loop on line 30 during I and I ∗ ’s response is (Found, ptri+1 ), we have that p finds the condition on line 38 to be true, so p executes line 40 during I ′ ; say at time T 40 . Therefore, curr ptr = ptri+1 at T 40 as wanted. Claim C.2.13.4 Claim C.2.13.5. For every i ∈ [1..n + 1], (1) p executes line 30 i times during I and (2) at the time p executes line 30 for the ith time during I the local variable curr ptr = ptri−1 . 93

Proof. By induction on i. Base Case. i = 1. In this case, (1) holds immediately since p must execute line 30 at least once during I as p exits the loop on line 30 during I. Let T130 be the time of p’s first execution of line 30 during I. For (2), since curr ptr at T130 is the value it was initialized to on line 29 during I, we have that curr ptr = &H at T130 . Therefore, since ptr0 = &H, we have that curr ptr = ptr0 at T130 . Inductive Case. For every i ∈ [1..n], if (1) and (2) hold for i, then (1) and (2) hold for i + 1. Suppose for any i ∈ [1..n] (1) p executes line 30 i times during I and (2) at the time p executes line 30 for the ith time during I curr ptr = ptri−1 . This is the inductive hypothesis. Let Ii be the ith iteration of the loop on line 30 during I, which is well-defined by (1) of the inductive hypothesis. Furthermore, let Ti30 be the time of p’s ith execution of line 30 during I which is the start of Ii . Since by (2) of the inductive hypothesis curr ptr = ptri−1 at Ti30 where i − 1 ∈ [0..n), by Claim C.2.13.4, p executes line 40 at some time Ti40 during Ii and curr ptr = ptri at Ti40 . Hence, since p exits the loop on line 30 during I, it follows that p executes line 30 one more time during I, so p executes line 30 i + 1 times during I. Since curr ptr = ptri at Ti40 , and the value of curr ptr does not change between Ti40 and the time of p’s i + 1th execution of line 30 during I, it follows that at the time p executes line 30 for the i + 1th time during I curr ptr = ptri . Therefore, (1) and (2) hold for i + 1 as wanted. Claim C.2.13.5 Now that we have established p “traverses” to the end of List(Ieexclude ) during I, we are ready to prove that p performs a list-add attempt for ptrL during I. Claim C.2.13.6. p performs a list-add attempt for ptrL during I. Proof. By Claim C.2.13.5, p executes line 30 n + 1 times during I and at the time p executes line 30 for the n + 1th time during I curr ptr = ptrn . Let In+1 be the n + 1th iteration of the loop on line 30 during I. Since by (**) for every i ∈ [0..n + 1] ptri ̸= ptrL , and curr ptr = ptrn at the start of In+1 , it follows that p finds the condition on line 30 to be true at the start of In+1 . Hence, since p exits the loop on line 30 during I, p invokes and exits the AcquireNext procedure during In+1 . Denote this execution of the AcquireNext procedure by I ∗ . We prove that the response of I ∗ is (NotFound, ∗) by satisfying the conditions of Lemma C.2.11. Since the first parameter of I is ulloL and curr ptr = ptrn at the start of In+1 , the parameters of I ∗ are (ulloL , ptrn ). Let TI104 and TI105 by defined as in Claim C.2.13.3, and so L.ullo = ulloL ∗ ∗ 105 104 exit at TI ∗ , and TI ∗ ∈ (e, T ]. Hence, there is a prefix of I B during (e, T exit ] up to and including exclude ) in I. So, since TI104 ∗ ; say I. Thus, by Claim C.2.13.2 the list of cells conforms to List(Ie exclude List(Ie ) = ptr0 , . . . , ptrn+1 , by Definition C.1.7, at the end of I (∗ptrn ).next.ptr = ptrn+1 . Thus, since ptrn+1 = Null, we have that (∗ptrn ).next.ptr = Null at the end of I. Therefore, we have established the following: (1) I ∗ has parameters (ulloL , ptrn ); (2) L.ullo = ulloL at TI105 ∗ ; and (3) (∗ptrn ).next.ptr = Null at TI104 (equivalently, the end of I), and so by Lemma C.2.11, I ∗ ’s ∗ response is (NotFound, ∗) as wanted. We now finish the proof of Claim C.2.13.6. Since p exits the loop on line 30 during I and I ∗ ’s response is (NotFound, ∗), we have that p finds the condition on line 33 to be true during In+1 . Let T 35 be the time p executes line 35 during In+1 . Since all steps during the loop on line 30 during I are during (e, T exit ], it follows that T 35 ∈ (e, T exit ]. Hence, since by (*) L.ullo = ulloL throughout (e, T exit ], we have that L.ullo = ulloL at T 35 . Thus, p finds the condition on line 35 to be false at T 35 , and so p executes line 36 during In+1 . Therefore, since the second parameter of I is ptrL , by Definition C.1.5, p performs a list-add attempt for ptrL during I as wanted. Claim C.2.13.6 94

Suppose this list-add attempt is after some curr ptr, so by Lemma C.1.49 curr ptr ∈ C ∪{&H}. The remainder of the proof is dedicated to showing that this list-add attempt is successful. Claim C.2.13.7. (∗curr ptr).next = (∗, False, 0, Null) throughout (e, T exit ]. Proof. Since e is an L-add event for ptrL in I B , by P (I B ), e is the only L-add event for ptrL in I B . Since p performs a list-add attempt a for ptrL after curr ptr during (e, T exit ], by Q(I B ), e is the unique L-add event for ptrL preceding a and curr ptr is the second last pointer in List(Ieexclude ), i.e., the one preceding Null (so curr ptr ∈ List(Ieexclude )). Thus, since by Claim C.2.13.2 at every prefix I of I B during (e, T exit ], the list of cells conforms to List(Ieexclude ) in I, by Definition C.1.7, at the end of I (∗curr ptr).next.ptr = Null. Hence, since I is an arbitrary prefix of I B during (e, T exit ] and both e and T exit are in I B , we have that (∗curr ptr).next = ∗, ∗, ∗, Null) throughout (e, T exit ]. Therefore, since curr ptr ∈ C ∪ {&H}, by Lemma C.1.124, (∗curr ptr).next = (∗, ∗, 0, Null) throughout (e, T exit ]. So, it suffices to prove (∗curr ptr).next.sealed = False throughout (e, T exit ]. Suppose, for contradiction,(∗curr ptr).next.sealed ̸= False sometime during (e, T exit ]. Hence, since curr ptr ∈ C ∪ {&H}, (∗curr ptr).next.sealed is initialized to False, and so the value of (∗curr ptr).next.sealed changed before T exit . Thus, by Observation C.1.6, there is a successful list-sealed attempt for curr ptr before T exit and so by Lemma C.1.46 curr ptr ∈ C. Let s be this successful list-seal attempt, and let q be the process that executed s. Since s is for curr ptr, by Definition C.1.5, q executed s during an invocation of the DoRemoveCell procedure with a second parameter of curr ptr. Hence, by Corollary C.1.37, there is an L-remove event e1 for curr ptr before q invoked this procedure, and so since q executed s during this procedure, we have that e1 < s. Thus, since s < T exit , by transitivity, e1 < T exit . Therefore, since e1 is an L-remove event for curr ptr, by Corollary C.1.40, there is an L-add event e2 for curr ptr before e1 in I B . We now prove that there is an L-add for curr ptr other than e2 in I B . Since as we established above, curr ptr ∈ C, by Assumption C.1.2, curr ptr ̸= &H and curr ptr ̸= Null. Thus, since curr ptr ∈ List(Ieexclude ), by Definition C.1.7, there is an L-add event e3 for curr ptr in Ieexclude such that from e3 onwards in Ieexclude there are no L-remove events for curr ptr. Since Ieexclude is the prefix of I B up to but excluding e, e is an L-add event, and by (*) there are no L-events during (e, T exit ], it follows that during [e3 , T exit ] there are no L-remove events for curr ptr. Thus, since e1 is a L-remove event for curr ptr before T exit , we have that e1 < e3 . Hence, since e2 < e1 , it follows that e2 < e3 , and so e2 ̸= e3 . Therefore, since e2 and e3 are both L-add events for curr ptr in I B , there are two L-add events for curr ptr in I B . However, by P (I B ), there is at most one L-add event for curr ptr in I B , a contradiction. Claim C.2.13.7 Claim C.2.13.8. (∗curr ptr).next is unchanged throughout (e, T exit ]. Proof. Suppose, for contradiction, (∗curr ptr).next changes during (e, T exit ]. Hence, by Observation C.1.6, during (e, T exit ] there is either a successful list-add attempt after curr ptr, a successful list-seal attempt for curr ptr, a successful list-remove attempt between curr ptr and some pointer, or a successful list-acquire-next attempt after curr ptr. Since by Claim C.2.13.1 there are no successful list-add or list-remove attempts during (e, T exit ], there is either a successful list-seal attempt for curr ptr or a successful list-acquire-next attempt after curr ptr. Case 1. There is a successful list-seal attempt for curr ptr during (e, T exit ]. Hence, by Definition C.1.5, (∗curr ptr).next.sealed = True sometime during (e, T exit ]. However, by Claim C.2.13.7, (∗curr ptr).next.sealed = False at all times during (e, T exit ], a contradiction. Case 2. There is a successful list-acquire-next attempt after curr ptr during (e, T exit ]. 95

Let a be this successful attempt and let (∗curr ptr).next.acquisitions = acq at the step before a. Since curr ptr ∈ C ∪{&H}, by Lemma C.1.125, acq ≥ 0. Since a is successful, by Definition C.1.5, a sets (∗curr ptr).next.acquisitions = acq+1. Hence, (∗curr ptr).next.acquisitions > 0 at a. Therefore, (∗curr ptr).next.acquisitions > 0 some time during (e, T exit ]. However, by Claim C.2.13.7, (∗curr ptr).next.acquisitions = 0 at all times during (e, T exit ], a contradiction. Claim C.2.13.8 We now return to the proof of Lemma C.2.13. By Claim C.2.13.6 p performs a list-add attempt a for ptrL . As defined afterwards, a is after curr ptr. Since all steps during the loop on line 30 during I are during (e, T exit ], we have that a ∈ (e, T exit ], and since a is neither e or the last step in the loop, we have that the step before a is in (e, T exit ]. Hence, by Claim C.2.13.7 (∗curr ptr).next = (∗, False, 0, Null) at the step before a. Furthermore, since by Claim C.2.13.1 there are no successful list-add or list-remove attempts during (e, T exit ], we have that a is unsuccessful. Hence, (∗curr ptr).next ̸= (v, False, 0, Null) at the step before a where (∗curr ptr).next.view = v at p’s last execution of line 34 before a; say at time T 34 . Since T 34 is during the loop on line 30 during I and all steps during the loop on line 30 during I are during (e, T exit ], we have that T 34 ∈ (e, T exit ]. Hence, since a ∈ (e, T exit ] and T 34 < a, by transitivity, [T 34 , a] ⊆ (e, T exit ]. Thus, by Claim C.2.13.8, (∗curr ptr).next.view is unchanged throughout [T 34 , a]. So, since (∗curr ptr).next.view = v at T 34 , we have that (∗curr ptr).next.view = v at the step before a. Therefore, since (∗curr ptr).next = (∗, False, 0, Null) at the step before a, we have that (∗curr ptr).next = (v, False, 0, Null) at the step before a. However, as we established above, (∗curr ptr).next ̸= (v, False, 0, Null) at at the step before a, a contradiction. Lemma C.2.13 Lemma C.2.14. Consider any invocation of the DoAddCell procedure with a second parameter of ptrL which ends at some time T exit during I B . If P (I B ), Q(I B ), and R(I B ) hold, then there is a successful add-response-set attempt for ptrL before T exit . Proof. Consider any invocation I of the DoAddCell procedure with parameters (ulloL , ptrL ) which ends at some time T exit during I B . Let p be the process that invoked I. Since I has parameters (ulloL , ptrL ), by Corollary C.1.37, there is an L-add event e for ptrL before I was invoked that set L to (ulloL , ptrL ). Hence, by Lemma C.1.28, ptrL ∈ C. The proof strategy is to identify an add-response-set attempt for ptrL before T exit . If this is successful, we are done, but if it is unsuccessful, then by Lemma C.1.109, there is a successful add-response-set attempt for ptrL beforehand, in which case we are also done. Claim C.2.14.1. Consider any invocation I ′ of the SetResponse procedure invoked on line 42 with parameters (ulloL , ptrL , Done). Then, there is a successful list-add attempt a for ptrL such that a is before I ′ was invoked and a is before e. Proof. We first prove that there is a successful list-add attempt for ptrL before I ′ was invoked. Let q be the process that invoked I ′ . Since q invoked I ′ on line 42, we have that q invoked I ′ during some invocation I ∗ of the DoAddCell procedure, and since the parameter of I ′ are (ulloL , ptrL , Done), it follows that the parameters of I ∗ are (ulloL , ptrL ). Furthermore, since q invoked I ′ on line 42 during I ∗ , we have that q exited the loop on line 30 at some time T during I ∗ . Therefore, since P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.13, there is a successful list-add attempt a for ptrL before T which is before I ′ was invoked as wanted. We now prove that e < a. Suppose, for contradiction, a ≤ e. Hence, since a is a successful list-add attempt for ptrL , by Corollary C.1.37, there is a L-add event e′ for ptrL before a. Thus, since e′ < a and a ≤ e, by transitivity e′ < e, so e′ ̸= e. Therefore, there are two L-add events for ptrL in I B . However, by P (I B ), there is at most one L-add event for ptrL in I B , a contradiction. Claim C.2.14.1 96

Claim C.2.14.2. The SetResponse procedure was invoked with parameters (ulloL , ptrL , Done) at some time Tb′ and ends at some time Te′ during I B such that: (1) [Tb′ , Te′ ] ⊆ (e, T exit ]; (2) e is the last L-event in I where I is any prefix of I B during [Tb′ , Te′ ]; (3) L.ullo = ulloL at the end of I where I is as in (2); and (4) the list of cells conforms to List(I) in I where I is as in (2). Proof. There are two cases. Case 1. During (e, T exit ] there are no L-events. Since p exited I, we have that p invoked the SetResponse procedure on line 42 during I. Denote this invocation by I ′ . We prove that I ′ is the desired invocation. Since I’s parameters are (ulloL , ptrL ), and I ′ is invoked during I, we have that I ′ ’s parameters are (ulloL , ptrL , Done). Let Tb′ and Te′ be the times that p invokes and exits I ′ , respectively. We first prove (1). Since e is before I was invoked, and I ′ was invoked during I, by transitivity, e < Tb′ . Furthermore, since I ′ exits before I does, by transitivity, Te′ < T exit . Together these imply [Tb′ , Te′ ] ⊆ (e, T exit ]. We now prove (2). Consider any prefix I of I B during [Tb′ , Te′ ]. Since [Tb′ , Te′ ] ⊆ (e, T exit ], and by assumption there are no L-events during (e, T exit ], we have that e is the last L-event in I. We now prove (3). Since by assumption of Case 1 there are no L-events during (e, T exit ], and e set L.ullo = ulloL , by Observation C.1.6, L.ullo = ulloL throughout (e, T exit ]. Hence, since [Tb′ , Te′ ] ⊆ (e, T exit ], we have that L.ullo = ulloL throughout [Tb′ , Te′ ]. This implies (3). We now prove (4). By Claim C.2.14.1, there is a successful list-add attempt a for ptrL before Tb′ and e < a. Thus, a is in I. So, since e is the last L-event in I, and e < a, we have that from the last L-event in I onwards, there is a successful list-add attempt. Therefore, since I is finite, and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I) in I. Case 2. During (e, T exit ] there is at least one L-event. We identify an earlier invocation than the one during I. Let e′ be the next L-event after e in I B , so e′ ∈ (e, T exit ]. Let q be the process that executed e′ . Hence, there are no L-events during (e, e′ ). Let Tq14 be the time of q’s last execution of line 14 before e′ . Since e and e′ are successive L-events and Tq14 is the time of q’s last execution of line 14 before e′ , by Lemma C.1.41, q read the value that e set L to on line 14 at Tq14 , and since P (I B ) holds, by Lemma C.1.42, e < Tq14 . Hence, since e set L to (ulloL , ptrL ), we have that q read (ulloL , ptrL ) from L on line 14 at Tq14 . Thus, since ulloL = (∗, AddCell) (because e set L.ullo = ulloL and e is an L-add event), we have that between Tq14 and e′ , q invoked and exited the DoAddCell procedure on line 16 with parameters (ulloL , ptrL ). Denote this invocation by I ∗ and the time q exited it by T∗exit , so T∗exit < e′ . Since q exited I ∗ , we have that q invoked the SetResponse procedure on line 42 during I ∗ . Denote this invocation by I ′ . We claim that I ′ is the desired invocation. Since I ∗ ’s parameters are (ulloL , ptrL ), and I ′ is invoked during I ∗ , we have that I ′ ’s parameters are (ulloL , ptrL , Done). Let Tb′ and Te′ be the times q invokes and exits I ′ , respectively. We first prove (1) Since e < Tq14 , Tq14 is before I ∗ was invoked, and I ′ was invoked during I ∗ , by transitivity, e < Tb′ . Furthermore, since Te′ < T∗exit (because I ′ exits during I ∗ ), T∗exit < e′ , by transitivity, Te′ < e′ . Together these imply [Tb′ , Te′ ] ⊆ (e, e′ ), and since e′ ≤ T exit , by transitivity, [Tb′ , Te′ ] ⊆ (e, T exit ]. We now prove (2). Consider any prefix I of I B during [Tb′ , Te′ ]. Since [Tb′ , Te′ ] ⊆ (e, e′ ), and there are no L-events during (e, e′ ), we have that e is the last L-event in I. We now prove (3). Since there are no L-events during (e, e′ ) and e set L.ullo = ulloL , by Observation C.1.6, L.ullo = ulloL throughout (e, e′ ). Hence, since [Tb′ , Te′ ] ⊆ (e, e′ ), we have that L.ullo = ulloL throughout [Tb′ , Te′ ]. This implies (3). We now prove (4). By Claim C.2.14.1, there is a successful list-add attempt a for ptrL before Tb′ and e < a. Thus, a is in I. So, since e is the last L-event in I, and e < a, we have that from the last L-event in I onwards, there is a successful list-add attempt. Therefore, since I is finite, and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I) in I. Claim C.2.14.2 97

Claim C.2.14.3. There is an add-response-set attempt for ptrL before T exit . Proof. Let I ′ be the invocation of the SetResponse procedure identified in Claim C.2.14.2 and let q be the process that executed I ′ . Furthermore, let Tb′ and Te′ be the times during I B that q begins and exits I ′ , respectively. Since q exits I ′ , q began and exited the Acquire procedure on line 75 during I ′ . Denote this invocation of the Acquire procedure by I ∗ . Since the parameters of I ′ are (ulloL , ptrL , Done), we have that the parameters of I ∗ are (ulloL , ptrL ). We now satisfy the conditions of Lemma C.2.12. As established above, ptrL ∈ C. Let Tb be the time q invoked I ∗ and let T 105 be the last time q executes line 105 during I ∗ . Recall that T 105 is well-defined by Corollary C.1.93. By assumption P (I B ) holds. Let Ieinclude be the prefix of I B up to and including e. We plug in Ieinclude for I in Lemma C.2.12. Consider any prefix I ∗ of I B during [Tb , T 105 ]. We first satisfy condition 1. Since by definition all steps during [Tb , T 105 ] are during I ∗ , and all steps during I ∗ are during I ′ , we have that [Tb , T 105 ] ⊆ [Tb′ , Te′ ]. Hence, since by (3) of Claim C.2.14.2, L.ullo = ulloL at the end of I ′ for any prefix I ′ of I B during [Tb′ , Te′ ], we have that L.ullo = ulloL at the end of I ∗ . We now satisfy condition 2. Since by (4) of Claim C.2.14.2 the list of cells conforms to List(I ′ ) in I ′ for any prefix I ′ of I B during [Tb′ , Te′ ], and [Tb , T 105 ] ⊆ [Tb′ , Te′ ], we have that that the list of cells conforms to List(I ∗ ) in I ∗ . We now prove that List(Ieinclude ) = List(I ∗ ). Since Ieinclude is the prefix of I B up to and including e, and e is an L-event, it follows that e is the last L-event in Ieinclude . Furthermore, since by (2) of Claim C.2.14.2 e is the last L-event in I ′ for any prefix I ′ of I B during [Tb′ , Te′ ], and [Tb , T 105 ] ⊆ [Tb′ , Te′ ], we have that e is the last L-event in I ∗ . Together, these imply that the sequence of L-events is the same in Ieinclude and I ∗ , and so by Definition C.1.7, List(Ieinclude ) = List(I ∗ ). Therefore, since the list of cells conforms to List(I ∗ ) in I ∗ , we have that the list of cells conforms to List(Ieinclude ) in I ∗ as wanted. So, by Lemma C.2.12 if ptrL ∈ List(Ieinclude ) then the response of I ∗ is Found. We now finish the proof of Claim C.2.14.3. Since e is an L-add event for ptrL , and e is the last L-event in Ieinclude , we have that there are no L-remove events after e for ptrL in Ieinclude . Hence, by Definition C.1.7, ptrL ∈ List(Ieinclude ), so the response of I ∗ is Found. Thus, since q exits I ′ , we have that q finds the condition on line 76 to be true during I ′ . So, q executes line 77 during I ′ . Since I ∗ ’s parameters are (ulloL , ptrL , Done) and ulloL = (∗, AddCell) (because e set L.ullo = ulloL and e is an L-add event), by Definition C.1.5, this execution is an add-response-set attempt for ptrL during I ′ (and thus [Tb′ , Te′ ]). Therefore, since by (1) of Claim C.2.14.2 [Tb′ , Te′ ] ⊆ (e, T exit ], we have that there is an add-response-set attempt for ptrL before T exit as wanted. Claim C.2.14.3 We now return to the proof of Lemma C.2.14. Let a be the add-response-set attempt for ptrL identified by Claim C.2.14.3. Since a is an add-response-set attempt for ptrL before T exit , if a is successful, we have satisfied the claim. If a is unsuccessful, then by Lemma C.1.109, there is a successful add-response-set attempt for ptrL before a (and thus before T exit ). Therefore, in either case, there is a successful add-response-set attempt for ptrL before T exit as wanted. Lemma C.2.14 C.2.6

The DoRemoveCell procedure has the intended effect

In this section, we prove that the DoRemoveCell procedure with parameters (∗, ptrL ) has the intended effect: (1) once it exits there is a successful list-remove attempt for ptrL ; and (2) once it exits there is a successful remove-response-set attempt for ptrL . Lemma C.2.15. Consider any invocation I of the DoRemoveCell procedure with a second parameter of ptrL which ends at some time T exit during I B . If P (I B ), Q(I B ), and R(I B ) hold, then there is a successful list-remove attempt for ptrL before T exit in I B . Proof. Suppose, for contradiction, there is an invocation I of the DoRemoveCell procedure with parameters (ulloL , ptrL ) which ends at some time T exit during I B such that there is not a successful 98

list-remove attempt for ptrL before T exit in I B . Let p be the process that invoked I. Since I has parameters (ulloL , ptrL ), by Corollary C.1.37, there is an L-remove event e for ptrL before I was invoked that set L to (ulloL , ptrL ). Hence, by Lemma C.1.28 ptrL ∈ C. Furthermore, since e is before I was invoked and T exit is after I was invoked, by transitivity, e < T exit , thus all steps during the loop line 46 during I are during (e, T exit ]. There are two cases. Suppose during (e, T exit ] there is at least one L-event in I B . Let ea be the next L-event after e in I B . Hence, since e and ea are successive L-events in I B , and e is an L-remove event for ptrL , by R(I B ), there is a successful list-remove attempt for ptrL during (e, ea ). Therefore, since ea < T exit , there is a successful listremove attempt for ptrL before T exit . However, by our initial assumption of Lemma C.2.15, there are no successful list-remove attempts for ptrL before T exit , a contradiction. Now suppose during (e, T exit ] there are no L-events in I. Hence, e is the last L-event in I where I is any prefix of I B during (e, T exit ]. Thus, since e set L.ullo = ulloL , by Observation C.1.6, L.ullo = ulloL throughout (e, T exit ] (*). We first show (e, T exit ] is desolate in two other senses. Claim C.2.15.1. There are no successful list-add or list-remove attempts during (e, T exit ]. Proof. Let I be the prefix of I B up to and including T exit , so by (*) e is the last L-event in I. Hence, since P (I B ), Q(I B ), and R(I B ) hold, and the last L-event in I, e, is an L-remove event for ptrL , by Lemma C.2.5, from e onwards in I there is at most one successful list-remove attempt for ptrL and no other successful list-add or list-remove attempts for any other pointer. Hence, since I is the prefix of I B up to and including T exit , during (e, T exit ] there is at most one successful list-remove attempt for ptrL and no other successful list-add or list-remove attempts for any other pointer. If during (e, T exit ] there is a successful list-remove attempt for ptrL , there would be a successful list-remove attempt for ptrL before T exit , contradicting our initial assumption of Lemma C.2.15. Therefore, there are no successful list-add or list-remove attempts during (e, T exit ]. Claim C.2.15.1 Claim C.2.15.2. At every prefix I of I B during (e, T exit ], the list of cells conforms to List(Ieexclude ) in I where Ieexclude is the prefix of I B up to but excluding e. Proof. For the first part, consider any prefix I of I B during (e, T exit ]. Hence, by (*) e is the last L-event in I, and so the last L-event in I is an L-remove event. Furthermore, since by Claim C.2.15.1 there are no successful list-add or list-remove attempts during (e, T exit ], we have that from e onwards in I there are no successful list-add or list-remove attempts. Thus, since I is finite and by assumption P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(Ie ) in I where Ie is the prefix of I up to but excluding e. Therefore, since I is a prefix of I B after e, Ie = Ieexclude , and so the list of cells conforms to List(Ieexclude ) in I. Claim C.2.15.2 We now prove that I “traverses” List(Ieexclude ). The following few claims will be reminiscent of the proof of Lemma C.2.12. Let List(Ieexclude ) = ptr0 , . . . , ptrn+1 for some integer n ≥ 0. Hence, by Lemma C.1.113, ptr0 = &H, for every i ∈ [1..n] ptri ∈ C, and ptrn+1 = Null. Furthermore, since e is an L-remove event for ptrL , and P (I B ) holds, by Lemma C.1.119, there is exactly one i ∈ [1..n] such that ptri = ptrL . Claim C.2.15.3. Consider any invocation I ∗ of the AcquireNext procedure on line 47 during I. Since I exits I ∗ exits. Let TI104 (resp. TI105 ∗ ∗ ) be the last time p executes line 104 (resp. line 105) ∗ ∗ during I (these are well-defined since I exits). Then, the following are true: 1. L.ullo = ulloL at TI105 ∗ ; and 104 exit ]. 2. TI ∗ ∈ (e, T

99

Proof. First 1. Since I ∗ began and exited during the loop on line 46 in I, all steps during the loop on line 46 during I are during (e, T exit ], and by (*) L.ullo = ulloL throughout (e, T exit ], we have that L.ullo = ulloL throughout I ∗ . Hence, since TI105 is the time of a step during I ∗ , we have that ∗ 105 L.ullo = ulloL at TI ∗ . Now 2. Since all steps during the loop on line 46 during I are during (e, T exit ], and TI104 is the time of a step during I ∗ , we have that TI104 ∈ (e, T exit ]. ∗ ∗ Claim C.2.15.3 Claim C.2.15.4. Consider any iteration of the loop on line 46 during I, denoted by I ′ , such that the local variable curr ptr = ptrj for some j ∈ [0..i) at the start of I ′ . Then, p executes line 52 at time T 52 during I ′ and the local variable curr ptr = ptrj+1 at T 52 . Proof. Since ptrL = ptri for a unique i ∈ [1..n], we have that every j ∈ [0..i) ptrj ̸= ptrL . Hence, since by assumption curr ptr = ptrj at the start of I ′ for some j ∈ [0..i), it follows that p finds the condition on line 46 to be true at the start of I ′ . Thus, since p exits I, p begins and exits the AcquireNext procedure on line 47 during I ′ . Denote this invocation by I ∗ . We first prove that I ∗ ’s response is (Found, ptrj+1 ) by satisfying the conditions of Lemma C.2.11. Since the first parameter of I is ulloL and curr ptr = ptrj at the start of I ′ , the parameters of by defined as in Claim C.2.15.3, and so L.ullo = ulloL and TI105 I ∗ are (ulloL , ptrj ). Let TI104 ∗ ∗ exit 104 105 ]. Hence, there is a prefix of I B during (e, T exit ] up to and inat TI ∗ , and TI ∗ ∈ (e, T 104 cluding TI ∗ ; say I. Thus, by Claim C.2.15.2 the list of cells conforms to List(Ieexclude ) in I. So, since List(Ieexclude ) = ptr0 , . . . , ptrn+1 , and j ∈ [0..n], by Definition C.1.7, at the end of I (∗ptrj ).next.ptr = ptrj+1 . Thus, since ptrj+1 ∈ C (because j + 1 ∈ [1..n]), by Assumption C.1.2 ptrj+1 ̸= Null, and so (∗ptrj ).next.ptr = ptrj+1 ̸= Null at the end of I. Therefore, we have established the following: (1) I ∗ has parameters (ulloL , ptrj ); (2) L.ullo = ulloL at TI105 ∗ ; and (3) 104 (∗ptrj ).next.ptr = ptrj+1 ̸= Null at TI ∗ (equivalently, the end of I), and so by Lemma C.2.11, I ∗ ’s response is (Found, ptrj+1 ). We now finish the proof of Claim C.2.15.4. Since p exits I and I ∗ ’s response is (Found, ptrj+1 ), we have that p finds the condition on line 50 to be true and so p executes line 52 during I ′ ; say at time T 52 . Therefore, curr ptr = ptrj+1 at T 52 as wanted. Claim C.2.15.4 Claim C.2.15.5. For every j ∈ [1..i + 1], (1) p executes line 46 j times during I, and (2) at the time p executes line 46 for the jth time during I the local variable curr ptr = ptrj−1 . Proof. By induction on j. Base Case. j = 1. In this case, (1) holds immediately since p must execute line 46 at least once during I as p exits I. Let T146 be the time of p’s first execution of line 46 during I. For (2), since curr ptr at T146 is the value it was initialized to on line 45 during I, we have that curr ptr = &H at T146 . Therefore, since ptr0 = &H, we have that curr ptr = ptr0 at T146 . Inductive Case. For every j ∈ [1..i], if (1) and (2) hold for j, then (1) and (2) hold for j + 1. Suppose for any j ∈ [1..i] (1) p executes line 46 j times during I and (2) at the time p executes line 46 for the jth time during I, curr ptr = ptrj−1 . This is the inductive hypothesis. Let Ij be the jth iteration of the loop on line 46 during I, which is well-defined by (1) of the inductive hypothesis. Furthermore, let Tj46 be the time of p’s jth execution of line 46 during I which is the start of Ij . Since by (2) of the inductive hypothesis curr ptr = ptrj−1 at Tj46 where j −1 ∈ [0..i), by Claim C.2.15.4, p executes line 52 at some time Tj52 during Ij and curr ptr = ptrj at Tj52 . Hence, since p exits I, it follows that p executes line 46 one more time during I, so p executes line 46 j + 1 times during I. Since curr ptr = ptrj at Tj52 , and the value of curr ptr does not change between 100

Tj52 and the time of p’s j + 1th execution of line 46 during I, it follows that at the time p executes line 46 for the j + 1th time during I curr ptr = ptrj . Therefore, (1) and (2) hold for j + 1 as wanted. Claim C.2.15.5 Since ptrL = ptri , this implies that p will exit the first loop on line 46 during I. Claim C.2.15.6. At the time p executes line 46 for the i + 1th time during I, which is well-defined by Claim C.2.15.5, p finds the condition on line 46 to be false. Proof. By Claim C.2.15.5 curr ptr = ptri at the time p executes line 46 for the i + 1th time, say T , and ptri = ptrL , so curr ptr = ptrL at T . Therefore, since the second parameter of I is ptrL , we have that p finds the condition on line 46 to be false at T . Claim C.2.15.6 The remainder of the proof will proceed as follows. Since p exits the loop on line 46 during I, we know that p will enter the loop on line 57 during I. Hence, since p exits I, it follows that p will find the condition on either line 59 or line 61 to be true. If the latter, then given I’s parameters, we are done, so the task is to prove that the former is impossible. We first prove that the value of the local variable prev ptr = ptri−1 during the loop on line 57 in I, and then we prove this. Claim C.2.15.7. At the time p executes line 46 for the i + 1th time during I, which is well-defined by Claim C.2.15.5, the local variable prev ptr = ptri−1 . Proof. Since i ∈ [1..n], by Claim C.2.15.5, (1) p executes line 46 i & i + 1 times during I and (2) at the time p executes line 46 for the ith time during I curr ptr = ptri−1 . Let Ii be the ith iteration of the loop on line 46 during I. Since p executes line 46 i & i+1 times during I and the first parameter of the response from the AcquireNext procedure is either Found, NotFound, or L-Changed, it follows that status = Found during Ii . Hence, p found the condition on line 50 to be true during Ii , and so p executed line 52 during Ii ; say at time Ti52 . Thus, since at the time p executes line 46 during Ii curr ptr = ptri−1 , we have that p set prev ptr = ptri−1 at Ti52 . Therefore, since the value of prev ptr does not change between Ti52 and the time of p’s i + 1th execution of line 46 during I, at the time p executes line 46 for the i + 1th time during I prev ptr = ptri−1 . Claim C.2.15.7 Claim C.2.15.8. p never finds the left clause of line 59 to be true during I. Proof. Suppose, for contradiction, p finds the left clause of line 59 to be true sometime during I. Hence, L.ullo doesn’t equal the first parameter of I sometime during I. Since the first parameter of I is ulloL , we have that L.ullo ̸= ulloL sometime during I. Therefore, since all steps during I are during (e, T exit ], we have that L.ullo ̸= ulloL sometime during (e, T exit ]. However, by (*) L.ullo = ulloL throughout (e, T exit ], a contradiction. Claim C.2.15.8 Claim C.2.15.9. p never finds the condition on line 59 to be true during I. 46 be the time of p’s i + 1th execution of line 46 during I. This time is well-defined Proof. Let Ti+1 46 prev ptr = ptr by Claim C.2.15.5. By Claim C.2.15.7, at Ti+1 i−1 . Hence, since by Claim C.2.15.6 46 p finds the condition on line 46 to be false at Ti+1 and prev ptr only changes on lines 45 and 52 46 onwards in I, prev ptr = ptr during I, from Ti+1 i−1 . Since p exits the loop on line 46 via the condition on line 46 during I, and p exits I, p enters and exits the loop on line 53 during I, followed by entering the loop on line 57 during I. Therefore, p executes line 59 at least once during I. We now prove that p finds the right clause to be false on its first execution of line 59 during I. Since p executes line 59 at least once during I, we have that p executes line 56 during I, and executes line 58 at least once during I. Let T 56 be the time of p’s execution of line 56 during I

101

and let T 58 be the times of p’s first executions of line 58 during I. Since the second parameter of I is ptrL , p reads from ptrL at T 56 . Thus, since ptri = ptrL , we have that p reads from 46 onwards in I, we have that p reads ptri at T 56 . Furthermore, since prev ptr = ptri−1 from Ti+1 58 56 58 from ptri−1 at T . Since T and T are during I and all steps during I are during (e, T exit ], we have that T 56 and T 58 are during (e, T exit ]. Hence, there is a prefix of I B during (e, T exit ] up to and including T 56 (resp. T 58 ); say I 56 (resp. I 58 ). Thus, by Claim C.2.15.2 the list of cells conforms to List(Ieexclude ) in I 56 and I 58 . So, since List(Ieexclude ) = ptr0 , . . . , ptrn+1 , and i, i − 1 ∈ [0..n], by Definition C.1.7, at the end of I 56 (∗ptri ).next.ptr = ptri+1 , and at the end of I 58 (∗ptri−1 ).next.ptr = ptri . Hence, by the definition of I 56 and I 58 , we have that p read ptri+1 from (∗ptri ).next.ptr at T 56 , and p read ptri from (∗ptri−1 ).next.ptr at T 58 . Thus, since Ieexclude is a finite prefix of I B , List(Ieexclude ) = ptr0 , . . . , ptrn+1 , P (I B ) holds, i, i + 1 ∈ [0..n + 1], and i + 1 ̸= i, by Lemma C.1.114, ptri+1 ̸= ptri . Therefore, p finds the right clause to be false on its first execution of line 59 during I. We now finish the proof of Claim C.2.15.9. Suppose, for contradiction, that p finds the condition on line 59 to be true sometime during I; say at time T 59 . Hence, since by Claim C.2.15.8 p finds the left clause to be false at T 59 , we have that p finds the right clause to be true at T 59 . Thus, since 46 onwards in I, we have p read ptri+1 from (∗ptri ).next.ptr at T 56 , and prev ptr = ptri−1 from Ti+1 that p read ptri+1 from (∗ptri−1 ).next.ptr on line 58 at some time T during I. Since p read ptri from (∗ptri−1 ).next.ptr on line 58 at time T 58 and ptri+1 ̸= ptri , we have that between T 58 and T (or vice versa), the value of (∗ptri−1 ).next.ptr changed. Hence, since T 58 and T both occurred during I, and all steps during I are during (e, T exit ], we have that (∗ptri−1 ).next.ptr changed during (e, T exit ]. Therefore, since ptri−1 ∈ C (because i − 1 ∈ [0..n)), by Observation C.1.6, there is a successful list-add or list-remove attempt during (e, T exit ]. However, by Claim C.2.15.1, there are no successful list-add or list-remove attempts during (e, T exit ], a contradiction. Claim C.2.15.9 We now return to the proof of Lemma C.2.15. Since by Claim C.2.15.6, p exits the loop on line 46 during I by the finding the condition on line 46 to be false, and p exits I, it follows that p either finds the condition on line 59 or line 61 to be true during I. By Claim C.2.15.9, p never finds the condition on line 59 to be true during I, so p finds the condition on line 61 to be true during I. Therefore, since all steps during I are during (e, T exit ], by Definition C.1.5, p executes a successful list-remove attempt during (e, T exit ]. However, by Claim C.2.15.1, there are no successful list-remove attempts during (e, T exit ], a contradiction. Lemma C.2.15 Lemma C.2.16. Consider any invocation of the DoRemoveCell procedure with a second parameter of ptrL which ends at some time T exit during I B . If P (I B ), Q(I B ), and R(I B ), hold then there is a successful remove-response-set attempt for ptrL before T exit . Proof. Consider any invocation I of the DoRemoveCell procedure with parameters (ulloL , ptrL ) which ends at some time T exit during I B . Let p be the process that invoked I. Since I has parameters (ulloL , ptrL ), by Corollary C.1.37, there is an L-remove event e for ptrL before I was invoked that set L to (ulloL , ptrL ). Hence, by Lemma C.1.28, ptrL ∈ C. The proof strategy is to identify a remove-response-set attempt for ptrL before T exit . If this is successful, we are done, but if it is unsuccessful, then by Lemma C.1.111, there is a successful remove-response-set attempt for ptrL beforehand, in which case we are also done. Claim C.2.16.1. There is a successful list-remove attempt a for ptrL during (e, T exit ] in I B such that during (e, a) there are no L-events and successful list-add and list-remove attempts. Proof. Since I is an invocation of the DoRemoveCell procedure with parameters (ulloL , ptrL ) which ends at time T exit in I B and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.15 there is a successful 102

list-remove attempt a for ptrL before T exit in I B . Hence, by Corollary C.1.37, a’s corresponding L-event is an L-remove event e′ for ptrL before a in I B . Thus, since e and e′ are both L-remove events for ptrL , by P (I B ), e = e′ . So, e is a’s corresponding L-event and e < a. Since a is a successful list-remove attempt in I B , and P (I B ), Q(I B ), and R(I B ) hold, by Corollary C.2.2, there are no L-events during (e, a). We now prove that there are no successful list-add and list-remove attempts during (e, a). Let include Ia be the prefix of I B up to and including a. Since e < a, we have that e is in Iainclude , and since there are no L-events during (e, a), we have that e is the last L-event in Iainclude . Hence, since P (I B ), Q(I B ), and R(I B ) hold, and the last L-event in Iainclude , e, is an L-remove event for ptrL , by Lemma C.2.5, from e onwards in Iainclude there is at most one successful list-remove attempt for ptrL and no other successful list-remove or list-add attempt for any pointer. Therefore, there are no successful list-add and list-remove attempts during (e, a). Claim C.2.16.1 Claim C.2.16.2. The SetResponse procedure was invoked with parameters (ulloL , ptrL , Done) at some time Tb′ and ends at some time Te′ during I B such that: (1) [Tb′ , Te′ ] ⊆ (e, T exit ]; (2) L.ullo = ulloL at the end of I where I is any prefix of I B during [Tb′ , Te′ ]; and (3) the list of cells conforms to List(Ieexclude ) in I where Ieexclude is the prefix of I B up to but excluding e. Proof. By Claim C.2.16.1 there is a successful list-remove attempt a for ptrL during (e, T exit ] in I B such that during (e, a) there are no L-events and successful list-add and list-remove attempts. Let q be the process that executed a. Since a is a list-remove attempt for ptrL , we have that q executed a during some invocation I ∗ of the DoRemoveCell procedure with parameters (ullo∗L , ptrL ). Hence, by Corollary C.1.37, there is an L-remove event e∗ for ptrL before I ∗ was invoked that set L = (ullo∗L , ptrL ). Thus, since e and e∗ are both L-remove events for ptrL in I B , by P (I B ), e = e∗ , and so ulloL = ullo∗L . So, the parameters of I ∗ are (ulloL , ptrL ). Since q executed a during I ∗ , we have that q invoked the SetResponse procedure on line 44 during I ∗ . Denote this invocation by I ′ . We prove that I ′ is the desired invocation. Since the parameters of I ∗ are (ulloL , ptrL ), and I ′ was invoked during I ∗ , we have that the parameters of I ′ are (ulloL , ptrL , Done). Let Tb′ and Te′ be the times that q invokes and exits I ′ , respectively. We first prove (1). Since e is before I ∗ was invoked (because e = e∗ ), and I ′ is invoked during I ∗ , by transitivity, e < Tb′ . Hence, since Te′ < a (because they are both executed during I ∗ ), by transitivity, [Tb′ , Te′ ] ⊆ (e, a), and since a ≤ T exit , by transitivity, [Tb′ , Te′ ] ⊆ (e, T exit ]. We now prove (2). Since there are no L-events during (e, a), and e set L.ullo = ulloL , by Observation C.1.6, L.ullo = ulloL throughout (e, a). Hence, since [Tb′ , Te′ ] ⊆ (e, a), we have that L.ullo = ulloL throughout [Tb′ , Te′ ]. This implies (2). We now prove (3). Consider any prefix I of I B during [Tb′ , Te′ ]. Since there are no L-events during (e, a), and [Tb′ , Te′ ] ⊆ (e, a), it follows that e is the last L-event in I. Hence, since e is an L-remove event, we have that the last L-event in I is an L-remove event. Since there are no successful list-add and list-remove attempts during (e, a), and [Tb′ , Te′ ] ⊆ (e, a), we have that there are no successful list-add or list-remove attempts during [Tb′ , Te′ ]. Thus, since I is a prefix of I B during [Tb′ , Te′ ], we have that from e onwards in I there are no successful list-add or list-remove attempts. So, since I is finite, and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(Ie ) in I where Ie is the prefix of I up to but excluding e. Therefore, since I is a prefix of I B after e, Ie = Ieexclude , and so the list of cells conforms to List(Ieexclude ) in I as wanted. Claim C.2.16.2 Claim C.2.16.3. There is a remove-response-set attempt for ptrL before T exit . Proof. Let I ′ be the invocation of the SetResponse procedure identified in Claim C.2.16.2 and let q be the process that executed I ′ . Furthermore, let Tb′ and Te′ be the times during I B that q begins and exits I ′ , respectively. Since q exits I ′ , q began and exited the Acquire procedure on line 75 103

during I ′ . Denote this invocation of the Acquire procedure by I ∗ . Since the parameters of I ′ are (ulloL , ptrL , Done), we have that the parameters of I ∗ are (ulloL , ptrL ). We now satisfy the conditions of Lemma C.2.12. By above, ptrL ∈ C. Let Tb be the time q invoked I ∗ and let T 105 be the last time q executes line 105 during I ∗ . Recall that T 105 is well-defined by Corollary C.1.93. By assumption P (I B ) holds. We plug in Ieexclude for I in Lemma C.2.12. Consider any prefix I ∗ of I B during [Tb , T 105 ]. We first satisfy condition 1. Since by definition all steps during [Tb , T 105 ] are during I ∗ , and all steps during I ∗ are during I ′ , we have that [Tb , T 105 ] ⊆ [Tb′ , Te′ ]. Hence, since by (2) of Claim C.2.16.2, L.ullo = ulloL at the end of I ′ for any prefix I ′ of I B during [Tb′ , Te′ ], we have that L.ullo = ulloL at the end of I ∗ . We now satisfy condition 2. Since by (3) of Claim C.2.16.2 the list of cells conforms to List(I ′ ) in I ′ for any prefix I ′ of I B during [Tb′ , Te′ ], and [Tb , T 105 ] ⊆ [Tb′ , Te′ ], we have that that the list of cells conforms to List(Ieexclude ) in I ∗ . Therefore, by Lemma C.2.12 if ptrL ∈ List(Ieexclude ) then the response of I ∗ is Found (*). We now prove that ptrL ∈ List(Ieexclude ). Suppose, for contradiction, ptrL ∈ / List(Ieexclude ). B Since e is an L-remove event for ptrL in I , by Corollary C.1.40, there is an L-add event eadd for ptrL before e in I B . Hence, since Ieexclude is a prefix of I up to but excluding e, and eadd < e, we have that eadd is in Ieexclude . Thus, since ptrL ∈ / List(Ieexclude ) and eadd is an L-add event for ptrL exclude in Ie , by Definition C.1.7, there is an L-remove event eremove for ptrL after eadd in Ieexclude . Hence, since Ieexclude is a prefix of I B up to but excluding e, we have that eremove < e. Therefore, eremove ̸= e, and so there are two L-remove events for ptrL in I B . However, by P (I B ), there is at most one L-remove event for ptrL in I B , a contradiction. We now finish the proof of Claim C.2.16.3. Since ptrL ∈ List(Ieexclude ), by (*) the response of I ∗ is Found. Thus, since q exits I ′ , we have that q finds the condition on line 76 to be true during I ′ . So, q executes line 77 during I ′ . Since I ∗ ’s parameters are (ulloL , ptrL , Done) and ulloL = (∗, RemoveCell) (because e set L.ullo = ulloL and e is an L-remove event), by Definition C.1.5, this execution is a remove-response-set attempt for ptrL during I ′ (and thus [Tb′ , Te′ ]). Therefore, since by (1) of Claim C.2.16.2 [Tb′ , Te′ ] ⊆ (e, T exit ], we have that there is an remove-response-set attempt for ptrL before T exit as wanted. Claim C.2.16.3 We now return to the proof of Lemma C.2.16. Let a be the remove-response-set attempt for ptrL identified by Claim C.2.16.3. Since a is a remove-response-set attempt for ptrL before T exit , if a is successful, we have satisfied the claim. If a is unsuccessful, then by Lemma C.1.111, there is a successful remove-response-set attempt for ptrL before a (and thus before T exit ). Therefore, in either case, there is a successful remove-response-set attempt for ptrL before T exit . Lemma C.2.16 C.2.7

The DoApply&CopyResponse procedure has the intended effect

In this section, we prove that the DoApply&CopyResponse procedure with parameters ((t, ∗), ptrL ) has the intended effect: (1) once it exits there is a successful S-attempt for timestamp t; and (2) once it exits there is a successful apply-response-set attempt for ptrL . Lemma C.2.17. Consider any invocation of the DoApply&CopyResponse procedure with a first parameter of ulloL = (t, ∗) which ends at some time T exit during I B . If P (I B ) and O(I B ) hold, then there is a successful S-attempt for timestamp t before T exit . Proof. Suppose, for contradiction, there is an invocation I of the DoApply&CopyResponse procedure with a first parameter of ulloL = (t, ∗) which ends at some time T exit during I B such that there is not a successful S-attempt for timestamp t before T exit in I B . Let p be the process that invoked I. Since I has a first parameter of ulloL , by Corollary C.1.37, there is an L-apply event e before I was invoked that set L.ullo = ulloL . Hence, by Definition C.1.5, e is for timestamp t. Furthermore, since e is before I was invoked and T exit is after I was invoked, by transitivity, 104

e < T exit , thus all steps during I are during (e, T exit ]. There are two cases. Suppose during (e, T exit ] there is at least one L-event in I B . Let ea be the next L-event after e in I B . Hence, since e and ea are successive L-events in I B , and e is an L-apply event for timestamp t, by O(I B ), there is a successful S-attempt for timestamp t during (e, ea ). Therefore, since ea < T exit , there is a successful S-attempt for timestamp t before T exit . However, by our initial assumption of Lemma C.2.17, there are no successful S-attempts for timestamp t before T exit in I B , a contradiction. Now suppose during (e, T exit ] there are no L-events in I B . Hence, e is the last L-event in I where I is any prefix of I B during (e, T exit ]. Thus, since e set L.ullo = ulloL , by Observation C.1.6, L.ullo = ulloL throughout (e, T exit ] (*). Claim C.2.17.1. There are no successful S-attempts for timestamp t during (e, T exit ]. Proof. Let I be the prefix of I B up to and including T exit , so by (*) e is the last L-event in I. Hence, since P (I B ) and O(I B ) hold, and the last L-event in I, e, is an L-apply event for timestamp t, by Lemma C.2.9, from e onwards in I there is at most one successful S-attempt for t and no other successful S-attempts for any timestamp. So, since I is the prefix of I B up to and including T exit , during (e, T exit ] there is at most one successful S-attempt for t and no other successful S-attempts for any timestamp. If during (e, T exit ] there is a successful S-attempt for timestamp t, there would be a successful S-attempt for timestamp t before T exit , contradicting the initial assumption of Lemma C.2.17. Therefore, there are no successful S-attempts for timestamp t during (e, T exit as wanted. Claim C.2.17.1 Let (ullo, s, r) be the value p read from S on line 66 during I; say at time T 66 . Claim C.2.17.2. ullo ̸= ulloL . Proof. Suppose, for contradiction, ullo = ulloL . Since e set L.ullo = ulloL , by Lemma C.1.26, ulloL ̸= (0, ∗). Furthermore, since p read ullo from S.ullo at T 66 , we have that S.ullo = ulloL at T 66 . Hence, since ulloL ̸= (0, ∗) and the value of S.ullo is initially (0, Noop), we have that some step set S.ullo = ulloL before T 66 . Thus, by Observation C.1.6, there is a successful S-attempt a that set S.ullo = ulloL before T 66 . So, since T 66 is the time of a step during I, and I exits at time T exit , we have that T 66 ≤ T exit , and thus a < T exit . Let ea be a’s corresponding L-event, so ea < a. Hence, since a set S.ullo = ulloL , by Lemma C.1.43, ea set L.ullo = ulloL . Thus, since e set L.ullo = ulloL , e and ea are both in I B , and P (I B ) holds, by Lemma C.1.32, e = ea . So, since ea < a, we have that e < a, and since a < T exit , we have that a ∈ (e, T exit ]. Therefore, there is a successful S-attempt during (e, T exit ] (namely a). However, by Claim C.2.17.1, there are no successful S-attempts during (e, T exit ], a contradiction. Claim C.2.17.2 We now finish the proof of Lemma C.2.17. Since ulloL is the first parameter of I, by (*) L.ullo = ulloL throughout (e, T exit ], and all steps during I are during (e, T exit ], we have that p finds the condition on line 67 to be false during I. Hence, since p exits I, p executes line 68 during I. Since p read (ullo, s, r) from S on line 66 during I, ulloL is the first parameter of I, and by Claim C.2.17.2 ullo ̸= ulloL , we have that p finds the condition on line 68 to be true during I. Hence, since p exits I, p executes line 71 during I. Since by Claim C.2.17.1 there are no successful S-attempts during (e, T exit ], and all steps during I are during (e, T exit ], we have that the value of S is the same throughout I. Hence, since p read (ullo, s, r) from S on line 66 during I, we have that p’s CAS operation on line 71 during I is successful. Thus, by Definition C.1.5, p performs a successful S-attempt during I. Therefore, since I exits at T exit , there is a successful S-attempt before T exit in I B , contradicting the initial assumption of Lemma C.2.17. Lemma C.2.17

105

Lemma C.2.18. Consider any invocation of the DoApply&CopyResponse procedure with a second parameter of ptrL which ends at some time T exit during I B . If P (I B ), Q(I B ), and R(I B ) hold, then there is a successful apply-response-set attempt for ptrL before T exit . Proof. Consider any invocation I of the DoApply&CopyResponse procedure which ends at some time T exit during I B . Let (ulloL , ptrL ) be the parameters of I and suppose p is the process that invoked I. Hence, by Corollary C.1.37, there is an L-apply event e for ptrL before I was invoked that set L to (ulloL , ptrL ). Thus, by Lemma C.1.28 ptrL ∈ C. The proof strategy is to identify an apply-response-set attempt for ptrL before T exit . If this is successful, we are done, but if it is unsuccessful, then by Lemma C.1.110, there is a successful apply-response-set attempt for ptrL beforehand, in which case we are also done. Claim C.2.18.1. The DoApply&CopyResponse procedure was invoked with parameters (ulloL , ptrL ) at some time Tb′ and ends at some time Te′ during I B such that: (1) [Tb′ , Te′ ] ⊆ (e, T exit ]; (2) e is the last L-event in I where I is any prefix of I B during [Tb′ , Te′ ]; (3) L.ullo = ulloL at the end of I where I is as in (2); and (4) the list of cells conforms to List(I) in I where I is as in (2). Proof. There are two cases. Case 1. During (e, T exit ] there are no L-events. We prove I is the desired invocation. By definition I’s parameters are (ulloL , ptrL ). Let Tb be the time I was invoked. We first prove (1). Since e < Tb , we have that [Tb , T exit ] ⊆ (e, T exit ]. We now prove (2). Consider any prefix I of I B during [Tb , T exit ]. Since [Tb , T exit ] ⊆ (e, T exit ], and by assumption there are no L-events during (e, T exit ], we have that e is the last L-event in I. We now prove (3). Since by assumption of Case 1 there are no L-events during (e, T exit ], and e set L.ullo = ulloL , by Observation C.1.6, L.ullo = ulloL throughout (e, T exit ]. Hence, since [Tb , T exit ] ⊆ (e, T exit ], L.ullo = ulloL throughout [Tb , T exit ]. This implies (3). We now prove (4). Since e is the last L-event in I, and e is an L-apply event, we have that the last L-event in I is not an L-add or L-remove event. Hence, since I is a finite and by assumption P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I) in I. Case 2. During (e, T exit ] there is at least one L-event. We identify an earlier invocation than I. Let e′ be the next L-event after e in I B , so e′ ∈ (e, T exit ]. Let q be the process that executed e′ . Hence, there are no L-events during (e, e′ ). Let Tq14 be the time of q’s last execution of line 14 before e′ . Since e and e′ are successive L-events and Tq14 is the time of q’s last execution of line 14 before e′ , by Lemma C.1.41, q read the value that e set L to on line 14 at Tq14 , and since P (I B ) holds, by Lemma C.1.42, e < Tq14 . Hence, since e set L to (ulloL , ptrL ), we have that q read (ulloL , ptrL ) from L on line 14 at Tq14 . Thus, since ulloL = (∗, ⟨Apply&CopyResponse, ∗⟩) (because e set L.ullo = ulloL and e is an L-apply event), we have that between Tq14 and e′ , q invoked and exited the DoApply&CopyResponse procedure on line 20 with parameters (ulloL , ptrL ). Denote this invocation by I ′ and the time q began and exited it by Tb′ and Te′ , respectively. We claim that I ′ is the desired invocation. We already established I ′ has the desired parameters, so first we prove (1). Since e < Tq14 , Tq14 < Tb′ , Tb′ < Te′ , and Te′ < e′ , by transitivity, [Tb′ , Te′ ] ⊆ (e, e′ ), and since e′ ≤ T exit , we have that [Tb′ , Te′ ] ⊆ (e, T exit ]. We now prove (2). Consider any prefix I of I B during [Tb′ , Te′ ]. Since [Tb′ , Te′ ] ⊆ (e, e′ ], and there are no L-events during (e, e′ ), we have that e is the last L-event in I. We now prove (3). Since there are no L-events during (e, e′ ), and e set L.ullo = ulloL , by Observation C.1.6, L.ullo = ulloL throughout (e, e′ ). Hence, since [Tb′ , Te′ ] ⊆ (e, e′ ), L.ullo = ulloL throughout [Tb′ , Te′ ]. This implies (3). We now prove (4). Since e is the last L-event in I, and e is an L-apply event, we have that the last L-event in 106

I is not an L-add or L-remove event. Hence, since I is a finite and by assumption P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I) in I. Claim C.2.18.1 Claim C.2.18.2. There is an apply-response-set attempt for ptrL before T exit . Proof. Let I ′ be the invocation of the DoApply&CopyResponse procedure in Claim C.2.18.1 and let q be the process that executed I ′ . Furthermore, let Tb′ and Te′ be the times during I B that q begins and exits I ′ , respectively. Since q exits I ′ , it follows that q began and exited the SetResponse procedure invoked on line 73 during I ′ ; denote this invocation by Ir . Hence, q began and exited the Acquire procedure on line 75 during Ir . Denote this invocation of the Acquire procedure by I ∗ . Since the parameters of I ′ are (ulloL , ptrL ), we have that the parameters of I ∗ are (ulloL , ptrL ). We now satisfy the conditions of Lemma C.2.12. As established above, ptrL ∈ C. Let Tb be the time q invoked I ∗ and let T 105 be the last time q executes line 105 during I ∗ . Recall that T 105 is well-defined by Corollary C.1.93. By assumption P (I B ) holds. Let Ieinclude be the prefix of I B up to and including e. We plug in Ieinclude for I in Lemma C.2.12. Consider any prefix I ∗ of I B during [Tb , T 105 ]. We first satisfy condition 1. Since by definition all steps during [Tb , T 105 ] are during I ∗ , and all steps during I ∗ are during I ′ , we have that [Tb , T 105 ] ⊆ [Tb′ , Te′ ]. Hence, since by (3) of Claim C.2.18.1, L.ullo = ulloL at the end of I ′ for any prefix I ′ of I B during [Tb′ , Te′ ], we have that L.ullo = ulloL at the end of I ∗ . We now satisfy condition 2. Since by (4) of Claim C.2.18.1 the list of cells conforms to List(I ′ ) in I ′ for any prefix I ′ of I B during [Tb′ , Te′ ], and [Tb , T 105 ] ⊆ [Tb′ , Te′ ], we have that that the list of cells conforms to List(I ∗ ) in I ∗ . We now prove that List(Ieinclude ) = List(I ∗ ). Since Ieinclude is the prefix of I B up to and including e, and e is an L-event, it follows that e is the last L-event in Ieinclude . Furthermore, since by (2) of Claim C.2.18.1 e is the last L-event in I ′ for any prefix I ′ of I B during [Tb′ , Te′ ], and [Tb , T 105 ] ⊆ [Tb′ , Te′ ], we have that e is the last L-event in I ∗ . Together, these imply that the sequence of L-events is the same in Ieinclude and I ∗ , and so by Definition C.1.7, List(Ieinclude ) = List(I ∗ ). Therefore, since the list of cells conforms to List(I ∗ ) in I ∗ , we have that the list of cells conforms to List(Ieinclude ) in I ∗ as wanted. So, by Lemma C.2.12 if ptrL ∈ List(Ieinclude ) then the response of I ∗ is Found (*). / List(Ieinclude ). We now prove that ptrL ∈ List(Ieinclude ). Suppose, for contradiction, ptrL ∈ B Since e is an L-apply event for ptrL in I , by Lemma C.1.38, there is an L-add event eadd for ptrL before e in I B . Hence, since Ieinclude is the prefix of I B up to and including e, and eadd < e, we have that eadd is in Ieinclude . Thus, since ptrL ∈ / List(Ieinclude ) and eadd is an L-add event for ptrL include in Ie , by Definition C.1.7, there is an L-remove event eremove for ptrL after eadd in Ieinclude . Hence, eremove is an L-remove event for ptrL in I B , and so by Lemma C.1.39, there is an L-apply event e′ for ptrL before eremove in I B . Since eremove is in Ieinclude , and Ieinclude is the prefix of I B up to and including e, we have that eremove ≤ e. Hence, since e′ < eremove , by transitivity, e′ < e, and so e′ ̸= e. Therefore, there are two L-apply events for ptrL in I B . However, by P (I B ), there is at most one L-apply event for ptrL in I B , a contradiction. We now finish the proof of Claim C.2.18.2. Since ptrL ∈ List(Ieinclude ), by (*), the response of I ∗ is Found. Thus, since q exits Ir , we have that q finds the condition on line 76 to be true during Ir . So, q executes line 77 during Ir . Since I ∗ ’s parameters are (ulloL , ptrL ) and ulloL = (∗, ⟨Apply&CopyResponse, ∗⟩) (because e set L.ullo = ulloL and e is an L-apply event), by Definition C.1.5, this execution is an apply-response-set attempt for ptrL during Ir (and thus [Tb′ , Te′ ] because Ir was invoked during I ′ ). Therefore, since by (1) of Claim C.2.18.1 [Tb′ , Te′ ] ⊆ (e, T exit ], we have that there is an apply-response-set attempt for ptrL before T exit as wanted. Claim C.2.18.2 We now return to the proof of Lemma C.2.18. Let a be the apply-response-set attempt for ptrL identified by Claim C.2.18.2. Since a is an apply-response-set attempt for ptrL before T exit , if a is successful, we have satisfied the claim. If a is unsuccessful, then by Lemma C.1.110, there is a 107

successful apply-response-set attempt for ptrL before a (and thus before T exit ). Therefore, in either case, there is a successful apply-response-set attempt for ptrL before T exit . Lemma C.2.18 C.2.8

The IsDone procedure has the intended effect

Now that we have proven that the DoAddCell, DoRemoveCell, and DoApply&CopyResponse procedures have the intended effect, we are ready to prove that the IsDone procedure has the intended effect: if a process p invokes IsDone(∗, ulloA , ∗) on line 23, where ulloA is the unique low-level operation it read in A on line 22, and this invocation returns Done (resp. NotDone) then ulloA is written (resp. not written) in L. The exact timing of this L-event (or its absence) is delicate, as we will see shortly. We start by characterizing the behavior of the Acquire procedure during an invocation of the IsDone procedure. Lemma C.2.19. Consider any process p and suppose during an iteration I of the loop on line 13 p does the following during I B : (1) p reads (∗, ptr) from A on line 22 for some ptr ∈ C; and (2) p exits the Acquire procedure on line 80 with response status. Let I be the prefix of I B up to and including the time p executed line 14 during I. If P (I B ), Q(I B ), and R(I B ) hold, and status ̸= L-Changed, then the following are true: 1. if ptr ∈ List(I), then status = Found; and 2. if ptr ∈ / List(I), then status = NotFound. Proof. Suppose p read ulloL from L.ullo on line 14 during I; say at time T 14 . Let I ′ be the invocation of the Acquire procedure on line 80 during I. We satisfy the conditions of Lemma C.2.12 for I ′ . Since p read ulloL from L.ullo on line 14 during I and p read (∗, ptr) from A on line 22 during I, we have that the parameters of I ′ are (ulloL , ptr). Since p exits I ′ , and by Corollary C.1.93 p executes line 105 at least once during I ′ , we have that p executes line 105 for a final time during I ′ . Let Tb be the time p invoked I ′ and let T 105 be the last time p executes line 105 during I ′ . Hence, since T 14 is the time p executed line 14 during I, by transitivity, T 14 < Tb . Furthermore, since Tb is the time p invoked I ′ , and T 105 is the last time p executes line 105 during I ′ , we have that Tb < T 105 , and so T 14 < Tb < T 105 . Now consider any prefix I ∗ of I B in [Tb , T 105 ]. Claim C.2.19.1. L.ullo = ulloL at the end of I ∗ . Proof. Suppose, for contradiction, L.ullo ̸= ulloL at the end of I ∗ . Hence, since I ∗ is any prefix of I B in [Tb , T 105 ], we have that L.ullo ̸= ulloL at some time T ∈ [Tb , T 105 ]. Since p read ulloL from L.ullo at T 14 , L.ullo ̸= ulloL at T , and T 14 < Tb ≤ T , we have that between T 14 and T , the value of L.ullo changed. Thus, by Observation C.1.6, there is an L-event between T 14 and T . Therefore, since T ≤ T 105 , we have that there is an L-event between T 14 and T 105 . However, by Lemma C.1.112, there are no L-events between T 14 and T 105 , a contradiction. Claim C.2.19.1 Claim C.2.19.2. The list of cells conforms to List(I) in I ∗ . Proof. There are two cases, the first of which is trivial. Suppose I ∗ has zero L-events. Then, since I ∗ is a finite prefix of I B , and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I ∗ ) in I ∗ as wanted. Now suppose I ∗ has at least one L-event. Let elast be the last L-event in I ∗ . Since T 14 < Tb < T 105 , and by Lemma C.1.112 there are no L-events throughout [T 14 , T 105 ], it follows that elast < T 14 . Thus, since I is the prefix of I B up to and including T 14 , we have that elast is the last L-event in I. So, by Observation C.1.6, L is unchanged from elast onwards in I. Hence, since elast < T 14 and p read ulloL from L.ullo on line 14 at T 14 , we have that elast set L.ullo = ulloL . Suppose elast set L = (ulloL , ptrL ). So, by Definition C.1.5, elast is an L-event for ptrL , and so 108

by Lemma C.1.28 ptrL ∈ C. Hence, by Lemma C.1.29 elast is either an L-add event for ptrL , an L-apply event for ptrL , or an L-remove event for ptrL . We consider each case separately and prove that the list of cells conforms to List(I ∗ ) in I ∗ . We then prove that List(I ∗ ) = List(I) afterwards. Case 1. elast is an L-add event for ptrL . Hence, since elast set L = (ulloL , ptrL ), by Definition C.1.5, ulloL = (∗, AddCell). Thus, since p read (ulloL , ptrL ) from L on line 14 at T 14 , and p invokes I ′ during I, we have that p found the condition on line 15 to be true during I, and so p invoked and exited the DoAddCell procedure on line 16 with a second parameter of ptrL which ends at some time Te < Tb during I. Hence, since P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.13, there is a successful list-add attempt a for ptrL before Te . Let eb be a’s corresponding L-event (see Corollary C.1.37), so eb < a and eb is an L-add event for ptrL . Hence, since elast is an L-add event for ptrL , by P (I B ), eb = elast , and so elast < a. Since a < Te and Te < Tb , by transitivity, a < Tb , and so a is in I ∗ . Thus, since by definition elast is the last L-event in I ∗ and elast < a, we have that from elast onwards in I ∗ there is a successful list-add attempt. Hence, since I ∗ is finite, and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I ∗ ) in I ∗ as wanted. Case 2. elast is an L-apply event for ptrL . Since by definition elast is the last L-event in I ∗ , and elast is an L-apply event, we have that the last L-event in I ∗ is not an L-add or L-remove event. Hence, since I ∗ is finite, and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I ∗ ) in I ∗ . Case 3. elast is an L-remove event for ptrL . The proof is the same as Case 1 by replacing the adds with the appropriate removes (i.e., list-add with list-remove and AddCell with RemoveCell) and Lemma C.2.13 with Lemma C.2.15. We now prove that List(I ∗ ) = List(I) which completes the proof. Since elast is the last L-event in I ∗ and I, and I ∗ and I are both prefixes of I B , we have that the sequence of L-events is the same in I ∗ and I. Therefore, by Definition C.1.7, List(I) = List(I ∗ ). Claim C.2.19.2 We now finish the proof of Lemma C.2.19. We have established: (1) I ′ is an invocation of the Acquire procedure in I B with parameters (ulloL , ptr) for some ptr ∈ C and exits with response status; (2) Tb is the time p invoked I ′ and T 105 is the last time p executes line 105 during I ′ ; (3) P (I B ) holds; and (4) I is a finite prefix of I B such that for every prefix I ∗ of I B during [Tb , T 105 ] 1. by Claim C.2.19.1 L.ullo = ulloL at the end of I ∗ and 2. by Claim C.2.19.2 the list of cells conforms to List(I) in I ∗ , and so by Lemma C.2.12, if ptr ∈ List(I), then status = Found, and if ptr ∈ / List(I), then status = NotFound as wanted. Lemma C.2.19 We now prove that the IsDone procedure has the intended effect for each type of low-level operation that can be provided as input (excluding the initial value of A). Lemma C.2.20. Consider any process p and any iteration I of the loop on line 13 by p in I B . Let I be the prefix of I B up to and including the time p executed line 14 during I. If P (I B ), Q(I B ), and R(I B ) hold, and p read ((∗, AddCell), ptr) from A on line 22 during I, then: 1. If p received NotDone on line 23 during I, then there is no L-add event for ptr in I; and 2. If p received Done on line 23 during I, then there is a L-add event for ptr in I. Proof. Since p read ((∗, AddCell), ptr) from A during I, and A is initially ((0, Noop), (0, Null)), we have that A was set to ((∗, AddCell), ptr), and so by Observation C.1.6 some A-event a

109

set A = ((∗, AddCell), ptr). Hence, by Definition C.1.5, this is an A-add event for ptr, so by Lemma C.1.14, ptr ∈ C. We now prove 1. Suppose p received NotDone on line 23 during I. Since p exited the IsDone procedure during I, we have that p exited the Acquire procedure on line 80 during it. Denote this invocation by I ′ , and its response by status. Since p received NotDone as a response on line 23 during I, it follows that p found the condition on line 81 to be false during I, and so status ̸= L-Changed. Hence, since P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.19, if status ̸= Found, then ptr ∈ / List(I). Therefore, since status ̸= L-Changed and status is either Found, NotFound, or L-Changed, this is equivalent to: if status = NotFound, then ptr ∈ / List(I) (*). We now prove that status = NotFound. Since p read ((∗, AddCell), ptr) from A on line 22 during I, we have that p found the conditions on line 85 and line 87 to be false during I. Furthermore, since p received NotDone as a response on line 23 during I, we have that between the time response was initialized to Done on line 82 during I and the time p exited the IsDone procedure during I, the value of response changed. Together, these imply that p found the condition on line 83 to be true during I. Therefore, status = NotFound as wanted. We now finish the proof of 1. Since status = NotFound, by (*), ptr ∈ / List(I). Hence, since ptr ∈ C, by Assumption C.1.2 ptr ̸= &H and ptr ̸= Null, and so by Definition C.1.7, either there is not a L-add event for ptr in I or there is an L-add event for ptr followed by an L-remove event for ptr in I. If the former, the claim is satisfied, so it suffices to consider the latter. We prove that the latter is impossible. Let e be the L-remove event for ptr in I. Hence, by Corollary C.1.24, there is an A-remove event e′ for ptr before e in I, and so by Definition C.1.5, A = ((∗, RemoveCell), ptr) at e′ . Thus, since p read ((∗, AddCell), ptr) from A on line 22 during I, and this step is not in I by definition, we have that between e′ and this step, A was set to ((∗, AddCell), ptr). Therefore, by Observation C.1.6 and Definition C.1.5, there is an A-add event for ptr after e′ in I B . However, since e′ is an A-remove event for ptr in I B , by Lemma C.1.21, there are no A-add events for ptr from e′ onwards in I B , a contradiction, and so the latter case is impossible. We now prove 2. Suppose p received Done on line 23 during I. Since p exited the IsDone procedure during I, we have that p exited the Acquire procedure on line 80 during it. Denote this invocation by I ′ , and its response by status. Since p received Done as a response on line 23 during I, p found the condition on line 81 to be false during I, and so status ̸= L-Changed. Therefore, since P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.19, if status ̸= NotFound, then ptr ∈ List(I) (*). We now prove that status ̸= NotFound. Since p received Done as a response on line 23 during I, we have that between the time response was initialized to Done on line 82 during I and the time p exited the IsDone procedure during I, the value of response was not changed. Hence, p found the condition on line 83 to be false during I. Thus, since p read ((∗, AddCell), ptr) from A on line 22 during I, this implies that p found the right condition on line 83 to be false during I. Therefore, status ̸= NotFound. We now finish the proof of 2. Since status ̸= NotFound, by (*), ptr ∈ List(I). Therefore, since ptr ∈ C, by Assumption C.1.2 ptr ̸= &H and ptr ̸= Null, and so by Definition C.1.7, there is a L-add event for ptr in I as wanted. Lemma C.2.20 We now prove the same for apply low-level operations with one important difference: in the second case, we cannot conclude that there is an L-apply event for ptr in I, but only in I B . Roughly speaking, this is because there is some lag between when the Acquire completes on line 80 and when the response of ptr is checked on line 88. As we will see, the second case is only needed during the proof of wait-freedom, and in the single location it is needed, identifying a single L-apply event (or L-add and L-remove event in the other two cases) for ptr in I B is sufficient. Lemma C.2.21. Consider any process p and any iteration I of the loop on line 13 by p in I B . Let I be the prefix of I B up to and including the time p executed line 14 during I. If P (I B ), Q(I B ), 110

and R(I B ) hold, and during I p read ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from A on line 22, then: 1. If p received NotDone on line 23 during I, then there is no L-apply event for ptr in I; and 2. If p received Done on line 23 during I, then there is a L-apply event for ptr in I B . Proof. Since p read ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from A during I, and A is initially ((0, Noop), (0, Null)), we have that A was set to ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr), and so by Observation C.1.6 some A-event a set A = ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr). Hence, by Definition C.1.5, this is an A-apply event for ptr, so by Lemma C.1.14, ptr ∈ C. We now prove 1. Suppose, for contradiction, p received NotDone on line 23 during I and there is a L-apply event e for ptr in I. Claim C.2.21.1. Let T 22 be the time p executed line 22 during I. Then, from T 22 onwards in I B (∗ptr).response ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), Null). Proof. We first identify an invocation I ∗ of the DoApply&CopyResponse procedure with a second parameter of ptr that exits at time T∗exit < T 22 . There are two cases. Case 1. e is the last L-event in I. Hence, since I is the prefix of I B up to and including the time p executed line 14 during I, say T 14 , we have that p read ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from L at T 14 . Thus, p finds the condition on line 19 to be true during I, and so p begins and exits the DoApply&CopyResponse procedure on line 20 with a second parameter of ptr during I. Denote this invocation of the DoApply&CopyResponse procedure by I ∗ and let T∗exit be the time I ∗ exits. Hence, T∗exit < T 22 . Case 2. e is not the last L-event in I. Let ea be the next L-event after e in I and let q be the process that executed ea . Since ea is the next L-event after e, by Lemma C.1.41, q read the value that e set L to on its last execution of line 14 before ea ; say at time Tq14 . Hence, since e is an L-apply event for ptr, by Definition C.1.5, e set L to ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr). Thus, since q read the value that e set L to on line 14 at Tq14 , we have that q read ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from L at Tq14 . Hence, q finds the condition on line 19 to be true between Tq14 and ea , and so q begins and exits the DoApply&CopyResponse procedure on line 20 with a second parameter of ptr between Tq14 and ea . Denote this invocation of the DoApply&CopyResponse procedure by I ∗ and let T∗exit be the time I ∗ exits. Hence, T∗exit < ea , and since ea is in I, we have that T∗exit is in I, so T∗exit < T 22 . We now return to the proof of Claim C.2.21.1. As we just established, I ∗ is an invocation of the DoApply&CopyResponse procedure with a second parameter of ptr that exits at time T∗exit , and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.18, there is a successful apply-response-set attempt a for ptr before T∗exit . Hence, by Lemma C.1.83, from a onwards in I B (∗ptr).response ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), Null). Therefore, since a < T∗exit and T∗exit < T 22 , from T 22 onwards in I B (∗ptr).response ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), Null). Claim C.2.21.1 We now finish the proof of 1. Since p exited the IsDone procedure during I, we have that p exited the Acquire procedure on line 80 during it. Denote this invocation by I ′ , and its response by status. Since p received Done as a response on line 23 during I, p found the condition on line 81 to be false during I. Hence, since p read ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from A on line 22 during I, we have that p found the conditions on line 83 and line 85 to be false during I. Thus, since p received NotDone as a response on line 23 during I, we have that p found the condition on line 88 to be true during I; say at time T 88 . So, (∗ptr).response = 111

((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at T 88 . Furthermore, since T 22 is the time p executed line 22 during I, and T 88 is the time p executed line 88 during I, we have that T 22 < T 88 . Therefore, (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) after T 22 in I B . However, this contradicts Claim C.2.21.1. We now prove 2. Suppose, for contradiction, p received Done on line 23 during I and there is not a L-apply event for ptr in I B . Claim C.2.21.2. There is a successful apply-response-set attempt for ptr in I B . Proof. Since p exited the IsDone procedure during I, we have that p exited the Acquire procedure on line 80 during it. Denote this invocation by I ′ , and its response by status. Since p received Done as a response on line 23 during I, p found the condition on line 81 to be false during I. Hence, since p read ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from A on line 22 during I, we have that p found the conditions on line 83 and line 85 to be false during I. Thus, since p received Done as a response on line 23 during I, we have that p found the condition on line 88 to be false during I; say at time T 88 . Hence, (∗ptr).response ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at T 88 . Since p read ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from A on line 22 during I, and A is initially ((∗, Noop), (∗, Null)), we have that A was set to ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) before p’s execution of line 22 during I. Hence, by Observation C.1.6, there is an A-event eapply that sets A to this value before p’s execution of line 22 during I. Thus, it follows that the process q that executed eapply did so during an invocation Iq of the DoLowLevelOp with parameters (⟨Apply&CopyResponse, ∗⟩, ptr). There are two cases. Case 1. q exits Iq . Hence, since Iq ’s parameters are (⟨Apply&CopyResponse, ∗⟩, ptr), by Lemma C.1.103, there is a successful apply-response-set attempt for ptr in I B . Case 2. q does not exit Iq . Since q executed eapply during Iq and by Definition C.1.5 eapply is an execution of either line 21 or line 27, we have that q executed line 12 during Iq before eapply ; say at time Tq12 , so Tq12 < eapply . Hence, since Iq ’s parameters are (⟨Apply&CopyResponse, ∗⟩, ptr), it follows that q sets (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at Tq12 . Since eapply is before p’s execution of line 22 during I, and T 88 is the time of p’s execution of line 88 during I, we have that eapply < T 88 . Hence, since Tq12 < eapply , by transitivity, Tq12 < T 88 . Thus, since (∗ptr).response equals ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) at Tq12 and does not at T 88 , we have that between Tq12 and T 88 the value of (∗ptr).response changed. Hence, since ptr ∈ C, by Observation C.1.6, there is either a response-reset event for ptr or a successful response-set attempt for ptr between Tq12 and T 88 . Let e∗ be the first such step between Tq12 and T 88 . Hence, throughout [Tq12 , e∗ ) (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null). Since Iq ’s parameters are (∗, ptr), by Case 2 q does not exit Iq , and Tq12 is the time q executes line 12 during Iq , by Lemma C.1.100, there are no response-reset events for ptr after Tq12 , and so e∗ is a successful response-set attempt for ptr. Therefore, since throughout [Tq12 , e∗ ) (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) and by Definition C.1.5 e∗ is a successful CAS on line 77, we have that the second parameter of e∗ is ((∗, ⟨Apply&CopyResponse, ∗⟩), Null), and so by Definition C.1.5 e∗ is a successful apply-response-set attempt for ptr as wanted. Claim C.2.21.2 We now finish the proof of 2. Since by Claim C.2.21.2 there is a successful apply-response-set attempt a for ptr, by Corollary C.1.74, there is a L-apply event for ptr in I B . However, by our initial assumption, there are no L-apply events for ptr, a contradiction. Lemma C.2.21 112

We now prove the same for remove low-level operations Lemma C.2.22. Consider any process p and any iteration I of the loop on line 13 by p in I B . Let I be the prefix of I B up to and including the time p executed line 14 during I. If P (I B ), Q(I B ), and R(I B ) hold, and during I p read ((∗, RemoveCell), ptr) from A on line 22 then: 1. If p received NotDone on line 23 during I, then there is no L-remove event for ptr in I; and 2. If p received Done on line 23 during I, then there is a L-remove event for ptr in I. Proof. Since p read ((∗, RemoveCell), ptr) from A on line 22 during I, and the value of A is initially ((∗, Noop), (∗, Null)), we have that A was set to ((∗, RemoveCell), ptr). Hence, by Observation C.1.6, there is an A-event eremove that sets A = ((∗, RemoveCell), ptr) before p read it on line 22 during I. Thus, by Definition C.1.5, eremove is an A-remove event for ptr, so by Lemma C.1.14, ptr ∈ C. We now prove 1. Suppose, for contradiction, p received NotDone on line 23 during I, and there is an L-remove event e for ptr in I. Since p exited the IsDone procedure during I, we have that p exited the Acquire procedure on line 80 during it. Denote this invocation by I ′ , and its response by status. Since p received NotDone as a response on line 23 during I, p found the condition on line 81 to be false during I, and so status ̸= L-Changed. Hence, since P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.19, if status ̸= NotFound, then ptr ∈ List(I). Therefore, since status ̸= L-Changed and status is either Found, NotFound, or L-Changed, this is equivalent to: if status = Found, then ptr ∈ List(I) (*). We now prove that status = Found. Since p read ((∗, RemoveCell), ptr) from A on line 22 during I, we have that p found the conditions on line 83 and line 87 to be false during I. Furthermore, since p received NotDone as a response on line 23 during I, we have that between the time response was initialized to Done on line 82 during I and the time p exited the IsDone procedure during I, the value of response changed. Together, these imply that p found the condition on line 85 to be true during I. Therefore, status = Found as wanted. We now finish the proof of 1. Since status = Found, by (*), ptr ∈ List(I). Hence, since ptr ∈ C, by Assumption C.1.2, ptr ̸= &H and ptr ̸= Null, so by Definition C.1.7, there is an L-add event e′ for ptr in I without a subsequent L-remove event for ptr in I. Thus, e < e′ . Therefore, since e is an L-remove event for ptr, by Corollary C.1.40, there is an L-add event for ptr before e, and so there are two L-add events for ptr in I B . However, by P (I B ), there is at most one L-add event for ptr in I B , a contradiction. We now prove 2. Suppose, for contradiction, p received Done on line 23 during I and there is not a L-remove event for ptr in I. Since p exited the IsDone procedure during I, we have that p exited the Acquire procedure on line 80 during I. Denote this invocation by I ′ , and its response by status. Since p received Done as a response on line 23 during I, p found the condition on line 81 to be false during I, and so status ̸= L-Changed. Let T 14 be the time p executes line 14 during I and let T 105 be the last time p executes line 105 during I ′ (this is well-defined by Corollary C.1.93). Hence, since status ̸= L-Changed and P (I B ) holds, by Lemma C.1.112, there are no L-events throughout [T 14 , T 105 ]. Furthermore, since P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.19, if ptr ∈ List(I), then status = Found (*). Claim C.2.22.1. status = NotFound. Proof. Since p received Done as a response on line 23 during I, we have that between the time response was initialized to Done on line 82 during I and the time p exited the IsDone procedure during I, the value of response was not changed. Hence, p found the condition on line 85 to be false during I. Thus, since p read ((∗, RemoveCell), ptr) from A on line 22 during I, this implies that status ̸= Found on line 85 during I. Hence, since status ̸= L-Changed, the response of I ′ is not 113

L-Changed and not Found. Therefore, since the response of I ′ is either Found, L-Changed, or NotFound, we have that status = NotFound as wanted. Claim C.2.22.1 Claim C.2.22.2. ptr ∈ List(I). Proof. Suppose, for contradiction, ptr ∈ / List(I). Since eremove is before p executed line 22 during I, I ′ is invoked on line 80 during I, and T 105 is the last time p executes line 105 during I ′ , by transitivity, eremove < T 105 . Furthermore, the process q that executed eremove did so during an invocation I1 of the DoLowLevelOp with parameters (RemoveCell, ptr). Since the first parameter of I1 is RemoveCell, q invoked I1 on line 6 during some invocation I ∗ of the DoHighLevelOp procedure. Hence, during I ∗ , q began and exited an invocation I2 the DoLowLevelOp procedure on line 3. Since I1 ’s parameters are (RemoveCell, ptr), and I1 and I2 are in during the same invocation I ∗ of the DoHighLevelOp procedure, we have that I2 ’s parameters are (AddCell, ptr). Hence, since P (I B ) holds, by Lemma C.1.105, there is an L-add event eadd for ptr in I B before q exited I2 . Since eadd is before q exited I2 , q exited I2 before q invoked I1 , q executed eremove during I1 , and eremove < T 105 , by transitivity, we have that eadd < T 105 . Thus, since eadd is an L-event, and by (*) there are no L-events throughout [T 14 , T 105 ], we have that eadd < T 14 . Hence, since I is the prefix of I B up to and including T 14 , we have that eadd is in I. Therefore, since by assumption ptr ∈ / List(I), by Definition C.1.5, there is an L-remove event for ptr in I. However, our initial assumption was that there is not an L-remove event for ptr in I, a contradiction. Claim C.2.22.2 We now finish the proof of 2. Since by Claim C.2.22.2 ptr ∈ List(I), by (*), status = Found. However, by Claim C.2.22.1, status = NotFound, a contradiction. Lemma C.2.22 C.2.9

The L-invariants hold

The goal of this subsection is to prove the following lemma. Lemma. P (I B ), Q(I B ), R(I B ), and O(I B ) hold. We first prove this claim for any finite implementation history of B; the infinite case is then trivial, since if one of the invariants doesn’t hold for an infinite I B , we can identify a finite prefix of I B in which this invariant also doesn’t hold. For the entirety of this section, we fix a finite implementation history I of B and consider a one-step continuation s of I, denoted by I ◦ s. Inductive Case for P Proposition C.2.23. If P (I), Q(I), and R(I) hold, then P (I ◦ s) holds. Proof. Suppose, for contradiction, P (I ◦ s) does not hold. Since P (I) holds, if s is anything other than an L-event, P (I ◦ s) holds by definition, so s must be an L-event; say for some ptr which by Lemma C.1.28 is in C. Since P (I) holds and P (I ◦ s) does not, there is some L-event in I, denoted by s′ , which is of the same form as s. Specifically, since by Lemma C.1.29 s is either an L-add, L-apply, or L-remove event for ptr, then the following are true. If s is an L-add event for ptr, then s′ is an L-add event for ptr, if s is an L-apply event for ptr, then s′ is an L-apply event for ptr, and if s is an L-remove event for ptr, then s′ is an L-remove event for ptr. Let e be the last L-event before s (e exists because s′ does), so e is in I and s′ ≤ e. Furthermore, let T 14 be the last time p executed line 14 before s, so T 14 is in I. Since e and s are successive L-events in I ◦ s, e is in I, and P (I) holds, by Lemma C.1.42, e < T 14 . Let I be the iteration of the loop on line 13 that p executed line 14 at T 14 during. Furthermore, let I 14 be the prefix of I up to and including T 14 (this is well-defined because T 14 is in I). Hence, since s′ ≤ e and e < T 14 , we have that s′ is in I 14 . Since p executed line 14 at T 14 during I, and T 14 is the last time p executed line 14 before 114

s, we have that p executed s during I. Hence, p received NotDone on line 23 during I, and so since this is before s, we have that p received NotDone on line 23 during I in I. Since s is either an L-add, L-apply, or L-remove event for ptr, we have that p read either ((∗, AddCell), ptr), ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr), or ((∗, RemoveCell), ptr) from A on line 22 during I, when s is an L-add, L-apply, or L-remove event for ptr, respectively. Therefore, since I 14 is the prefix of I up to and including T 14 , and P (I), Q(I), and R(I) hold, by 1. of Lemma C.2.20, Lemma C.2.21, and Lemma C.2.22, we have that there is not an L-add, L-apply, or L-remove event for ptr in I 14 , when s is an L-add, L-apply, or L-remove event for ptr, respectively.12 However, s′ is in I 14 and is an L-add, L-apply, or L-remove event for ptr, when s is an L-add, L-apply, or L-remove event for ptr, respectively, a contradiction. Proposition C.2.23 Inductive Case for Q Proposition C.2.24. If P (I), Q(I), and R(I) hold, then 1. of Q(I ◦ s) holds. Proof. Since Q(I) holds, if s is anything other than a list-add attempt, 1. of Q(I ◦ s) holds by definition, so it suffices to assume that s is a list-add attempt for some ptr. Hence, by Lemma C.1.46, ptr ∈ C. Furthermore, by Definition C.1.5, p executed s during some invocation I of the DoAddCell procedure with parameters (ulloL , ptr). Hence, by Corollary C.1.37, there is an L-add event e for ptr before I was invoked that set L to (ulloL , ptr). Thus, e < s, so e is in I, and by P (I), e is the only L-add event for ptr in I. Therefore, s is preceded by a unique L-add event for ptr (namely e). Thus, what remains is to prove that if Ieexclude is the prefix of I ◦ s up to but excluding e, then s is after the second last pointer in List(Ieexclude ). We start by establishing some basic facts for the proof. Since e is before p invoked I, we have that all steps during I are after e. Furthermore, since p executed s during I, and s is a list-add attempt, p executed line 35 before s during I; say at time T 35 . Hence, since a process can only execute line 35 once during a single invocation of the DoAddCell procedure, T 35 is the only time during I that p executes line 35. Furthermore, since T 35 < s, it follows that the step at T 35 is during I. Lastly, since e is before p invoked I and the step at T 35 is executed during I, we have that e < T 35 , so (e, T 35 ] is during I. We now prove that during (e, T 35 ] there are no L-events and the “shape” of the list is in one of two states. Claim C.2.24.1. There are no L-events during (e, T 35 ]. Proof. Suppose, for contradiction, there is an L-event e′ during (e, T 35 ]. Since e < e′ , we have that e ̸= e′ . Furthermore, since e′ < T 35 and T 35 < s, by transitivity, e′ < s. Hence, since s is the step after I in I ◦ s, we have that e′ is in I. Therefore, since L.ullo = ulloL at e, e′ is an L-event other than e in I, and by assumption P (I) holds, by Lemma C.1.32, L.ullo ̸= ulloL at e′ . We now prove that L.ullo ̸= ulloL at T 35 (*). Suppose, for contradiction, the value of L.ullo = ulloL at T 35 . Hence, since L.ullo ̸= ulloL at e′ , L.ullo = ulloL at T 35 , and e′ < T 35 , we have that some step set L.ullo = ulloL during (e′ , T 35 ). Thus, by Observation C.1.6, some L-event e∗ set L.ullo = ulloL during (e′ , T 35 ). Hence, since e∗ < T 35 and T 35 < s, by transitivity, e∗ < s, so e∗ is in I. Furthermore, since e < e′ and e′ < e∗ , by transitivity, e < e∗ , and so e ̸= e∗ . Therefore, since both e and e∗ are in I, and L.ullo = ulloL at both e and e∗ , there are two L-events in I (namely e and e∗ ) which set L.ullo to the same value. However, since P (I) holds, by Lemma C.1.32 every L-event in I sets L.ullo to a different value, a contradiction. We now finish the proof of Claim C.2.24.1. Since p executes s during I, it follows that p finds the condition on line 35 to be false at T 35 . Therefore, since the parameters of I are (ulloL , ptr), it follows that L.ullo = ulloL at T 35 . However, by (*), L.ullo ̸= ulloL at T 35 , a contradiction. Claim C.2.24.1 12

Observe that I 14 is plugged in for “I”, and I is plugged in for “I B ” when applying these lemmas.

115

Claim C.2.24.2. Consider any prefix I ′ of I during (e, T 35 ]. The list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in I ′ where Ieexclude is the prefix of I up to but excluding e and Ieinclude is the prefix of I up to and including e. Proof. Since I ′ is finite, and by assumption P (I), Q(I), and R(I) hold, by Lemma C.2.6, the list of cells conforms to either List(Ie′ ) or List(I ′ ) in I ′ where Ie′ is the prefix of I ′ up to but excluding e. Since I ′ is a prefix of I, e is in I ′ , and by definition Ieexclude is the prefix of I up to be excluding e, it follows that Ie′ = Ieexclude . Furthermore, since I ′ is a prefix of I during (e, T 35 ] and by Claim C.2.24.1 there are no L-events during (e, T 35 ], we have that the sequence of L-events in I ′ is exactly the sequence of L-events in I up to and including e, so by Definition C.1.7, List(I ′ ) = List(Ieinclude ). Therefore, the list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in I ′ as wanted. Claim C.2.24.2 We now prove that I “traverses” the list. Let List(Ieexclude ) = ptr0 , . . . , ptrn+1 for some n ≥ 0. Hence, by Lemma C.1.113, ptr0 = &H, for every i ∈ [1..n] ptri ∈ C, and ptrn+1 = Null. Furthermore, since Ieinclude is a single step more than Ieexclude and this single step is e, which is an L-add event for ptr, by the expansion of List(Ieexclude ) along with Definition C.1.7, it follows that List(Ieinclude ) = ptr0 , . . . , ptrn , ptr, ptrn+1 . Since P (I) holds, by Lemma C.1.117, ptr ∈ / List(Ieexclude ), and so since List(Ieexclude ) = ptr0 , . . . , ptrn+1 , for every i ∈ [0..n+1] ptr ̸= ptri (*). Claim C.2.24.3. Consider any invocation I ∗ of the AcquireNext procedure on line 31 during I. I ∗ exits since s is executed during I. Let TI104 (resp. TI105 ∗ ∗ ) be the last time p executes line 104 ∗ ∗ (resp. line 105) during I (these are well-defined since I exits). Then, the following are true: 1. L.ullo = ulloL at TI105 ∗ ; and 35 ]. 2. TI104 ∈ (e, T ∗ Proof. Since I ∗ began and exited during I, and all steps during I are after e, we have that all steps during I ∗ are after e. Furthermore, since T 35 is the only time p executes line 35 during I, it follows that I ∗ exited before T 35 , and so all steps during I ∗ are during (e, T 35 ]. Now 1. Since e set L.ullo = ulloL and by Claim C.2.24.1 there are no L-events during (e, T 35 ], we have that L.ullo = ulloL throughout (e, T 35 ]. Hence, since all steps during I ∗ are during (e, T 35 ], we have is the time of a step during I ∗ , we have that L.ullo = ulloL throughout I ∗ . Therefore, since TI105 ∗ 105 that L.ullo = ulloL at TI ∗ . Now 2. Since all steps during I ∗ are during (e, T 35 ], and TI104 is the ∗ ∗ 104 35 time of a step during I , we have that TI ∗ ∈ (e, T ]. Claim C.2.24.3 Claim C.2.24.4. Consider any iteration of the loop on line 30 during I, denoted by I ′ , such that the local variable curr ptr = ptri for some i ∈ [0..n) at the start of I ′ . Then, p executes line 40 at time T 40 during I ′ and the local variable curr ptr = ptri+1 at T 40 . Proof. Since by (*) for every i ∈ [0..n + 1] ptr ̸= ptri , and by assumption curr ptr = ptri at the start of I ′ for some i ∈ [0..n), it follows that p finds the condition on line 30 to be true at the start of I ′ . Hence, since p executes s during I, p begins and exits the AcquireNext procedure on line 31 during I ′ . Denote this invocation by I ∗ . We first prove that I ∗ ’s response is (Found, ptri+1 ) by satisfying the conditions of Lemma C.2.11. Since the first parameter of I is ulloL and curr ptr = ptri at the start of I ′ , the parameters of I ∗ are (ulloL , ptri ). Let TI104 and TI105 by defined as in Claim C.2.24.3, and so L.ullo = ulloL at TI105 ∗ ∗ ∗ , 104 35 35 104 and TI ∗ ∈ (e, T ]. Hence, there is a prefix of I during (e, T ] up to and including TI ∗ ; say I ′ . Thus, by Claim C.2.24.2 the list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in I ′ . So, since List(Ieexclude ) = ptr0 , . . . , ptrn+1 , List(Ieinclude ) = ptr0 , . . . , ptrn , ptr, ptrn+1 and i ∈ [0..n), 116

by Definition C.1.7, at the end of I ′ (∗ptri ).next.ptr = ptri+1 . Hence, since ptri+1 ∈ C (because i + 1 ∈ [1..n]), by Assumption C.1.2 ptri+1 ̸= Null, and so (∗ptri ).next.ptr = ptri+1 ̸= Null at T 104 . Therefore, we have established the following: (1) I ∗ has parameters (ulloL , ptri ); (2) 104 (equivalently, the end of L.ullo = ulloL at TI105 ∗ ; and (3) (∗ptri ).next.ptr = ptri+1 ̸= Null at TI ∗ I ′ ), and so by Lemma C.2.11, I ∗ ’s response is (Found, ptri+1 ) as wanted. We now finish the proof of Claim C.2.24.4. Since p executes s during I and I ∗ ’s response is (Found, ptri+1 ), we have that p finds the condition on line 38 to be true and so p executes line 40 during I ′ ; say at time T 40 . Therefore, curr ptr = ptri+1 at T 40 as wanted. Claim C.2.24.4 Claim C.2.24.5. For every i ∈ [1..n + 1], (1) p executes line 30 i times during I and (2) at the time p executes line 30 for the ith time during I, the local variable curr ptr = ptri−1 . Proof. By induction on i. Base Case. i = 1. In this case, (1) holds immediately since p must execute line 30 at least once during I as p executes s during I. Let T130 be the time of p’s first execution of line 30 during I. For (2), since curr ptr at T130 is the value it was initialized to on line 29 during I, we have that curr ptr = &H at T130 . Therefore, since ptr0 = &H, we have that curr ptr = ptr0 at T130 . Inductive Case. For every i ∈ [1..n], if (1) and (2) hold for i, then (1) and (2) hold for i + 1. Suppose for any i ∈ [1..n] (1) p executes line 30 i times during I and (2) at the time p executes line 30 for the ith time during I, curr ptr = ptri−1 . This is the inductive hypothesis. Let Ii be the ith iteration of the loop on line 30 during I, which is well-defined by (1) of the inductive hypothesis. Furthermore, let Ti30 be the time of p’s ith execution of line 30 during I which is the start of Ii . Since by (2) of the inductive hypothesis curr ptr = ptri−1 at Ti30 where i − 1 ∈ [0..n), by Claim C.2.24.4, p executes line 40 at some time Ti40 during Ii and curr ptr = ptri at Ti40 . Hence, since p executes s during I, it follows that p executes line 30 one more time during I, so p executes line 30 i + 1 times during I. Since curr ptr = ptri at Ti40 , and the value of curr ptr does not change between Ti40 and the time of p’s i + 1th execution of line 30 during I, it follows that at the time p executes line 30 for the i + 1th time during I curr ptr = ptri . Therefore, (1) and (2) hold for i + 1 as wanted. Claim C.2.24.5 What remains is to deal with the possibility that the “shape” of the list changes during I. Claim C.2.24.6. In the n + 1th iteration of the loop on line 30 during I, which is well-defined by Claim C.2.24.5, either p finds the condition on line 33 to be true, or p executes line 30 n + 2 times during I, and at the time p executes line 30 for the n + 2th time during I, the local variable curr ptr = ptr. Proof. By Claim C.2.24.5, at the time p executes line 30 for the n + 1th time during I, curr ptr = ptrn . Let In+1 be the n + 1th iteration of the loop on line 30 during I. Since by (*) for every i ∈ [0..n + 1] ptr ̸= ptri , and curr ptr = ptrn at the start of In+1 , it follows that p finds the condition on line 30 to be true at the start of In+1 . Thus, since p executes s during I, p invokes and exits the AcquireNext procedure during In+1 . Denote this execution by I ∗ . We first prove that I ∗ ’s response is either (NotFound, ∗) or (Found, ptr) by satisfying the conditions of Lemma C.2.11. Since the first parameter of I is ulloL and curr ptr = ptrn at the start of In+1 , the parameters of I ∗ are (ulloL , ptrn ). Let TI104 and TI105 by defined as in ∗ ∗ 105 104 35 Claim C.2.24.3, and so L.ullo = ulloL at TI ∗ , and TI ∗ ∈ (e, T ]. Hence, there is a prefix of I ′ during (e, T 35 ] up to and including TI104 ∗ ; say I . Thus, by Claim C.2.24.2, the list of cells conforms 117

to either List(Ieexclude ) or List(Ieinclude ) in I ′ . So, since List(Ieexclude ) = ptr0 , . . . , ptrn+1 , and List(Ieinclude ) = ptr0 , . . . , ptrn , ptr, ptrn+1 , by Definition C.1.7, at the end of I ′ (∗ptrn ).next.ptr equals either ptrn+1 or ptr. Thus, since ptr ∈ C, by Assumption C.1.2, ptr ̸= Null, and so since ptrn+1 = Null, it follows that (∗ptrn ).next.ptr equals either Null or ptr ̸= Null at the end of I ′ . Therefore, we have established the following: (1) I ∗ has parameters (ulloL , ptrn ); (2) L.ullo = ulloL 104 (equivalently, the end of at TI105 ∗ ; and (3) (∗ptrn ).next.ptr is either Null or ptr ̸= Null at TI ∗ I ′ ), and so by Lemma C.2.11, I ∗ ’s response is either (NotFound, ∗) or (Found, ptr) as wanted. We now finish the proof of Claim C.2.24.6. Suppose I ∗ ’s response is (NotFound, ∗). Hence, since p executes s during I, it follows that p finds the condition on line 33 to be true during In+1 . Now suppose I ∗ ’s response is (Found, ptr). Hence, since p executes s during I, it follows that p finds the condition on line 38 to be true during In+1 , and so p executes line 40 during In+1 ; say at time T 40 . Thus, curr ptr = ptr at T 40 . Therefore, p executes line 30 n + 2 times during I, and at the time p executes line 30 for the n + 2th time during I, curr ptr = ptr. Claim C.2.24.6 We now return to the proof of Proposition C.2.24. By Claim C.2.24.6, there are two cases. Case 1. During the n + 1th iteration of the loop on line 30 during I, p finds the condition on line 33 to be true. Let In+1 be the the n + 1th iteration of the loop on line 30 during I. We first prove that p executes s during In+1 . Since p executes s during I, and p finds the condition on line 33 to be true during In+1 , it follows that p either executes the break on line 35 or line 36 during In+1 . If the former, p would break out of the loop on line 30 during I before executing s, which is impossible (because p executes s during I), so p executes line 36 during In+1 . Therefore, since p executes line 36 at most once during I, p executes s during I, and p executes line 36 during In+1 , we have that p executes s during In+1 as wanted. We now finish the proof. Since by Claim C.2.24.5 the local variable curr ptr = ptrn at the start of In+1 , and p executes s during In+1 , we have that s is a CAS operation on (∗ptrn ).next. Thus, since s is a list-add attempt for ptr, by Definition C.1.5, s is a list-add attempt for ptr after ptrn . Hence, since List(Ieexclude ) = ptr0 , . . . , ptrn+1 , we have that ptrn is the second last pointer in List(Ieexclude ). Therefore, s is after the second last pointer in List(Ieexclude ) as wanted. Case 2. p executes line 30 n + 2 times during I, and at the time p executes line 30 for the n + 2th time during I, the local variable curr ptr = ptr. Hence, since the second parameter of I is ptr, it follows that p finds the condition on line 30 to be false on its n + 2th execution of line 30 during I. Therefore, p does not execute line 36 during I (otherwise, p would break out of the loop on line 30 during I on line 37 and not line 30). However, p executes s during I, a contradiction, so this case is impossible. Proposition C.2.24 Proposition C.2.25. If P (I), Q(I), and R(I) hold, then 2. of Q(I ◦ s) holds. Proof. Since Q(I) holds, if s is anything other than a list-remove attempt, 2. of Q(I ◦ s) holds by definition, so it suffices to assume that s is a list-remove attempt for some ptr. Hence, by Lemma C.1.46, ptr ∈ C. Furthermore, by Definition C.1.5, p executed s during some invocation I of the DoRemoveCell procedure with parameters (ulloL , ptr). Hence, by Corollary C.1.37, there is an L-remove event e for ptr before I was invoked that set L to (ulloL , ptr). Thus, e < s, so e is in I, and by P (I), e is the only L-remove event for ptr in I. Therefore, s is preceded by a unique L-remove event for ptr (namely e). Thus, what remains is to prove that if Ieexclude is the prefix of I ◦ s up to but excluding e, then ptr is in List(Ieexclude ) exactly once, and s is between pointers 118

preceding and succeeding ptr in List(Ieexclude ). We start by establishing some basic facts for the proof. Since e is before p invoked I, we have that all steps during I are after e. Furthermore, since p executed s during I, and s is a list-remove attempt, p executed line 59 during I. Hence, it executed line 59 for a last time during I before s; say at time T 59 . Since T 59 < s, it follows that the step at T 59 is during I. Lastly, since e is before p invoked I and the step at T 59 is executed during I, we have that e < T 59 , so (e, T 59 ] is during I. We now prove that during (e, T 59 ] there are no L-events and the “shape” of the list is in one of two states. Claim C.2.25.1. There are no L-events during (e, T 59 ]. Proof. Suppose, for contradiction, there is an L-event e′ during (e, T 59 ]. Since e < e′ , we have that e ̸= e′ . Furthermore, since e′ < T 59 and T 59 < s, by transitivity, e′ < s. Hence, since s is the step after I in I ◦ s, we have that e′ is in I. Therefore, since L.ullo = ulloL at e, e′ is an L-event other than e in I, and by assumption P (I) holds, by Lemma C.1.32, L.ullo ̸= ulloL at e′ . We now prove that L.ullo ̸= ulloL at T 59 (*). Suppose, for contradiction, the value of L.ullo = ulloL at T 59 . Hence, since L.ullo ̸= ulloL at e′ , L.ullo = ulloL at T 59 , and e′ < T 59 , we have that some step set L.ullo = ulloL during (e′ , T 59 ). Thus, by Observation C.1.6, some L-event e∗ set L.ullo = ulloL during (e′ , T 59 ). Hence, since e∗ < T 59 and by definition T 59 < s, by transitivity, e∗ < s, so e∗ is in I. Furthermore, since e < e′ and e′ < e∗ , by transitivity, e < e∗ , and so e ̸= e∗ . Therefore, since both e and e∗ are in I, and L.ullo = ulloL at both e and e∗ , there are two L-events in I (namely e and e∗ ) which set L.ullo to the same value. However, since P (I) holds, by Lemma C.1.32 every L-event in I sets L.ullo to a different value, a contradiction. We now finish the proof of Claim C.2.25.1. Since p executes s during I, p finds the condition on line 59 to be false at T 59 . Therefore, since the parameters of I are (ulloL , ptr), it follows that L.ullo = ulloL at T 59 . However, by (*), L.ullo ̸= ulloL at T 59 , a contradiction. Claim C.2.25.1 Claim C.2.25.2. Consider any prefix I ′ of I during (e, T 59 ]. The list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in I ′ where Ieexclude is the prefix of I up to but excluding e and Ieinclude is the prefix of I up to and including e. Proof. Since I ′ is finite, and by assumption P (I), Q(I), and R(I) hold, by Lemma C.2.6, the list of cells conforms to either List(Ie′ ) or List(I ′ ) in I ′ where Ie′ is the prefix of I ′ up to but excluding e. Since I ′ is a prefix of I, e is in I ′ , and by definition Ieexclude is the prefix of I up to be excluding e, it follows that Ie′ = Ieexclude . Furthermore, since I ′ is a prefix of I during (e, T 59 ] and by Claim C.2.25.1 there are no L-events during (e, T 59 ], we have that the sequence of L-events in I ′ is exactly the sequence of L-events in I up to and including e, so by Definition C.1.7, List(I ′ ) = List(Ieinclude ). Therefore, the list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in I ′ as wanted. Claim C.2.25.2 We now prove that I “traverses” the list. Let List(Ieexclude ) = ptr0 , . . . , ptrn+1 for some integer n ≥ 0. Hence, by Lemma C.1.113, ptr0 = &H, for every i ∈ [1..n] ptri ∈ C, and ptrn+1 = Null. Furthermore, since e is an L-remove event for ptr, and P (I) holds, by Lemma C.1.119, there is exactly one i ∈ [1..n] such that ptri = ptr. Hence, since Ieinclude is a single step more than Ieexclude and this single step is e, which is a L-remove event for ptr, by Definition C.1.7, it follows that List(Ieinclude ) = ptr0 , . . . , ptri−1 , ptri+1 , . . . , ptrn+1 . Claim C.2.25.3. Consider any invocation I ∗ of the AcquireNext procedure on line 47 during I. (resp. TI105 I ∗ exits since s is executed during I. Let TI104 ∗ ∗ ) be the last time p executes line 104 ∗ (resp. line 105) during I (these are well-defined since I ∗ exits). Then, the following are true: 1. L.ullo = ulloL at TI105 ∗ ; and 119

2. TI104 ∈ (e, T 59 ]. ∗ Proof. Since I ∗ began and exited during I, and all steps during I are after e, we have that all steps during I ∗ are after e. Furthermore, since T 59 is the last time p executes line 59 during I, it follows that I ∗ exited before T 59 , and so all steps during I ∗ are during (e, T 59 ]. Now 1. Since e set L.ullo = ulloL and by Claim C.2.25.1 there are no L-events during (e, T 59 ], we have that L.ullo = ulloL throughout (e, T 59 ]. Hence, since all steps during I ∗ are during (e, T 59 ], we have that L.ullo = ulloL throughout I ∗ . Therefore, since TI105 is the time of a step during I ∗ , we have ∗ 105 that L.ullo = ulloL at TI ∗ . Now 2. Since all steps during I ∗ are during (e, T 59 ], and TI104 is the ∗ ∗ 104 59 time of a step during I , we have that TI ∗ ∈ (e, T ]. Claim C.2.25.3 Claim C.2.25.4. Consider any iteration of the loop on line 46 during I, denoted by I ′ , such that the local variable curr ptr = ptrj for some j ∈ [0..n) \ {i − 1, i} at the start of I ′ . Then, p executes line 52 at time T 52 during I ′ and the local variable curr ptr = ptrj+1 at T 52 .13 Proof. Since ptr = ptri for a unique i ∈ [1..n], we have that every j ∈ [0..n] \ {i} ptr ̸= ptrj . Hence, since by assumption curr ptr = ptrj at the start of I ′ for some j ∈ [0..n) \ {i − 1, i} and the second parameter of I is ptr, it follows that ptr ̸= ptrj , so p finds the condition on line 46 to be true at the start of I ′ . Thus, since p executes s during I, p begins and exits the AcquireNext procedure on line 47 during I ′ . Denote this invocation by I ∗ . We first prove that I ∗ ’s response is (Found, ptrj+1 ) by satisfying the conditions of Lemma C.2.11. Since the first parameter of I is ulloL and curr ptr = ptrj at the start of I ′ , we have that the parameters of I ∗ are (ulloL , ptrj ). Let TI104 and TI105 by defined as in Claim C.2.25.3, and so L.ullo = ulloL ∗ ∗ 105 104 59 at TI ∗ , and TI ∗ ∈ (e, T ]. Hence, there is a prefix of I during (e, T 59 ] up to and including TI104 ∗ ; say I ′ . Thus, by Claim C.2.25.2 the list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in I ′ . So, since List(Ieexclude ) = ptr0 , . . . , ptrn+1 , List(Ieinclude ) = ptr0 , . . . , ptri−1 , ptri+1 , . . . , ptrn+1 , and j ∈ [0..n)\{i−1, i}, by Definition C.1.7, at the end of I ′ (∗ptrj ).next.ptr = ptrj+1 . Hence, since ptrj+1 ∈ C (because j + 1 ∈ [1..n]), by Assumption C.1.2 ptrj+1 ̸= Null, and so (∗ptrj ).next.ptr = ptrj+1 ̸= Null at T 104 . Therefore, we have established the following: (1) I ∗ has parameters 104 (equiv(ulloL , ptrj ); (2) L.ullo = ulloL at TI105 ∗ ; and (3) (∗ptrj ).next.ptr = ptrj+1 ̸= Null at TI ∗ ′ ∗ alently, the end of I ), and so by Lemma C.2.11, I ’s response is (Found, ptrj+1 ). We now finish the proof of Claim C.2.25.4. Since p executes s during I and I ∗ ’s response is (Found, ptrj+1 ), it follows that p finds the condition on line 50 to be true and so p executes line 52 during I ′ say at time T 52 . Therefore, curr ptr = ptrj+1 at T 52 as wanted. Claim C.2.25.4 Claim C.2.25.5. For every j ∈ [1..i] (1) p executes line 46 j times during I, (2) at the time p executes line 46 for the jth time during I, the local variable curr ptr is ptrj−1 . Proof. By induction on j. Base Case. j = 1. In this case, (1) holds immediately since p must execute line 46 at least once during I as p executes s during I. Let T146 be the time of p’s first execution of line 46 during I. For (2), since curr ptr at T146 is the value it was initialized to on line 45 during I, we have that curr ptr = &H at T146 . Therefore, since ptr0 = &H, we have that curr ptr = ptr0 at T146 . 13 We exclude i because if curr ptr = ptri on line 46 then p will find the condition to be false because the second parameter of I is ptr which is equal to ptri . We exclude i − 1 because p will set curr ptr either to ptri or ptri+1 at T 52 depending on whether ptr has been removed from the list or not (see Claim C.2.25.6).

120

Inductive Case. For every j ∈ [1..i), if (1) and (2) hold for j, then (1) and (2) hold for j + 1. Suppose for any j ∈ [1..i) (1) p executes line 46 j times during I and (2) at the time p executes line 46 for the jth time during I, curr ptr = ptrj−1 . This is the inductive hypothesis. Let Ij be the jth iteration of the loop on line 46 during I, which is well-defined by (1) of the inductive hypothesis. Furthermore, let Tj46 be the time of p’s jth execution of line 46 during I which is the start of Ij . Since by (2) of the inductive hypothesis curr ptr = ptrj−1 at Tj46 where j − 1 ∈ [0..i − 1), by Claim C.2.25.4, p executes line 52 at some time Tj52 during Ij and curr ptr = ptrj at Tj52 . Hence, since p executes s during I, it follows that p executes line 46 one more time during I, and so p executes line 46 j + 1 times during I. Since curr ptr = ptrj at Tj52 , and the value of curr ptr does not change between Tj52 and the time of p’s j + 1th execution of line 46 during I, it follows that at the time p executes line 46 for the j + 1th time during I curr ptr = ptrj . Therefore, (1) and (2) hold for j + 1 as wanted. Claim C.2.25.5 What remains is to deal with the possibility that the “shape” of the list changes during I. Claim C.2.25.6. p executes line 46 i + 1 times during I and at the time p executes line 46 for the i + 1th time during I, the local variable curr ptr is either ptr or ptri+1 . Furthermore, if curr ptr = ptri+1 , then i < n. Proof. By Claim C.2.25.5, p executes line 46 i times and at the time p executes line 46 for the ith time during I, curr ptr = ptri−1 . Let Ii be the ith iteration of the loop on line 46 during I. Since Ieexclude is a prefix of I, List(Ieexclude ) = ptr0 , . . . , ptrn+1 , by assumption P (I) holds, and i ∈ [1..n], by Lemma C.1.114 for every j ∈ [0..n + 1], if i ̸= j, then ptri ̸= ptrj . Hence, since ptri = ptr, for every j ∈ [0..n + 1], if i ̸= j, then ptr ̸= ptrj . Thus, since i − 1 ̸= i, we have that ptr ̸= ptri−1 . Hence, since curr ptr = ptri−1 at the start of Ii and the second parameter of I is ptr, we have that curr ptr ̸= ptr at the start of I ′ . Hence, p finds the condition on line 46 to be true at the start of Ii . Thus, since p executes s during I, p invokes and exits the AcquireNext procedure on line 47 during Ii . Denote this execution of the AcquireNext procedure by I ∗ . We first prove that I ∗ ’s response is either (NotFound, ∗), (Found, ptr), or (Found, ptri+1 ) by satisfying the conditions of Lemma C.2.11. Moreover, if I ∗ ’s response is (Found, ptri+1 ), then i < n. Since the first parameter of I is ulloL and curr ptr is ptri−1 at the start of Ii , the parameters of I ∗ are (ulloL , ptri−1 ). Let TI104 and TI105 by defined as in Claim C.2.25.3, and so L.ullo = ulloL at ∗ ∗ 105 104 59 TI ∗ , and TI ∗ ∈ (e, T ]. Hence, there is a prefix of I during (e, T 59 ] up to and including TI104 ∗ ; say ′ exclude include I . Thus, by Claim C.2.25.2 the list of cells conforms to either List(Ie ) or List(Ie ) in I ′ . exclude include So, since List(Ie ) = ptr0 , . . . , ptrn+1 , and List(Ie ) = ptr0 , . . . , ptri−1 , ptri+1 , . . . , ptrn+1 , by Definition C.1.7, at the end of I ′ (∗ptri−1 ).next.ptr equals either ptri or ptri+1 . Therefore, we have established the following: (1) I ∗ has parameters (ulloL , ptri−1 ); (2) L.ullo = ulloL at TI105 ∗ ; and (3) (∗ptri−1 ).next.ptr is either ptri or ptri+1 at TI104 (equivalently, the end of I ′ ), and so by ∗ Lemma C.2.11, I ∗ ’s response is either (NotFound, ∗), (Found, ptri ) (equivalently (Found, ptr) since ptr = ptri ), or (Found, ptri+1 ) as wanted. We now prove the “moreover” part. Suppose, for contradiction, I ∗ ’s response is (Found, ptri+1 ) and i ≥ n. Hence, by Lemma C.2.11, (∗ptri−1 ).next.ptr = ptri+1 ̸= Null at the end of I ′ . Furthermore, since i ∈ [1..n], we have that i + 1 = n + 1. Therefore, ptrn+1 ̸= Null. However, ptrn+1 = Null, a contradiction. We now finish the proof of Claim C.2.25.6. If I ∗ ’s response is (NotFound, ∗), then since p executes s during I, it follows that p finds the condition on line 48 to be true during Ii , so p executes line 49 during Ii . Therefore, p does not execute line 61 during I. However, by assumption p executes s during I, so this case is impossible. Now suppose I ∗ ’s response is either (Found, ptr) or (Found, ptri+1 ). Since p executes s during I, and I ∗ ’s response is either (Found, ptr) or 121

(Found, ptri+1 ), we have that p finds the condition on line 50 to be true and so p executes line 52 during Ii ; say at time T 52 . Hence, curr ptr is set to either ptr or ptri+1 at T 52 . Therefore, since p executes s during I, it follows that p executes line 46 i + 1 times during I, and at the time p executes line 46 for the i + 1th time during I, the value of curr ptr is either ptr or ptri+1 . For the furthermore part, if the value of curr ptr is ptri+1 , then I ∗ ’s response is (Found, ptri+1 ), so by the “moreover” part above, i < n as required. Claim C.2.25.6 Claim C.2.25.7. At the time p executes line 46 for the i + 1th time during I, which is well-defined by Claim C.2.25.6, the local variable prev ptr = ptri−1 . Proof. By Claims C.2.25.5 and C.2.25.6, respectively, p executes line 46 i & i + 1 times during I. Furthermore, by Claim C.2.25.5, at the time p executes line 46 for the ith time during I, curr ptr = ptri−1 . Let Ii be the ith iteration of the loop on line 46 during I. Since p executes line 46 i & i+1 times during I and the first parameter of the response of every invocation of the AcquireNext procedure is either Found, NotFound, or L-Changed, the local variable status = Found during Ii . Hence, p found the condition on line 50 to be true during Ii , and so p executed line 52 during Ii ; say at time Ti52 . Thus, since at the time p executes line 46 for the ith time during I curr ptr = ptri−1 , we have that p set prev ptr = ptri−1 at time Ti52 . Therefore, since the value of prev ptr does not change between Ti52 and the time of p’s i + 1th execution of line 46 during I, at the time p executes line 46 for the i + 1th time, prev ptr = ptri−1 as wanted. Claim C.2.25.7 Claim C.2.25.8. (∗ptri ).next.ptr = ptri+1 throughout (e, T 59 ]. Proof. We first prove that (∗ptri ).next.ptr = ptri+1 at e. Recall that Ieinclude is the prefix of I up to and including e. Hence, e is the last step in Ieinclude , and since e is an L-event, we have e is the last L-event in Ieinclude . Thus, from e onwards in Ieinclude , there are no successful list-add or list-remove attempts. So, since Ieinclude is finite, by assumption P (I), Q(I), and R(I) hold, Ieinclude has a last L-event (namely e), the last L-event in Ieinclude is a L-remove event, and from e onwards in Ieinclude , there are no successful list-add or list-remove attempts, by Lemma C.2.6, the list of cells conforms to List(I ′ ) in Ieinclude where I ′ is the prefix of Ieinclude up to but excluding e. Since Ieinclude is a prefix of I, e is in Ieinclude , and by definition Ieexclude is the prefix of I up to be excluding e, it follows that I ′ = Ieexclude . Hence, the list of cells conforms to List(Ieexclude ) in Ieinclude . Therefore, since List(Ieexclude ) = ptr0 , . . . , ptrn+1 , and i ∈ [1..n], by Definition C.1.7, at e (equivalently, the end of Ieinclude ) (∗ptri ).next.ptr = ptri+1 as wanted. So, it suffices to prove that (∗ptri ).next.ptr is unchanged throughout (e, T 59 ]. Suppose, for contradiction, (∗ptri ).next.ptr changes during (e, T 59 ]. Hence, by Observation C.1.6, there is either a successful list-add attempt after ptri or there is a successful list-remove attempt between ptri and some pointer during (e, T 59 ]. Since e is an L-remove event, and by Claim C.2.25.1 there are no L-events during (e, T 59 ], it follows that e is the last L-event in the prefix I 59 of I up to and including T 59 . Hence, since e is an L-remove event for ptr, and P (I), Q(I), and R(I) hold, by Lemma C.2.5, there is at most one successful list-remove attempt for ptr and no other successful list-add or list-remove attempts for any pointer from e onwards in I 59 , or equivalently, during (e, T 59 ]. Thus, since a is during (e, T 59 ], we have that a is a successful list-remove attempt for ptr between ptri and some pointer. So, since ptr = ptri , we have that a is a list-remove attempt for ptri between ptri and some pointer. Since a is before T 59 , and T 59 is in I, we have that a is in I. Hence, there is a list-remove attempt (namely a) for ptri between ptri and some pointer in I. Therefore, since by assumption P (I) and Q(I) hold, by Lemma C.1.57, ptri ̸= ptri . However, ptri = ptri , a contradiction. Claim C.2.25.8

122

Claim C.2.25.9. If the local variable curr ptr = ptri+1 at the time p executes line 46 for the i + 1th time during I, then for every j ∈ [i + 1..n], (1) p executes line 46 j times during I, (2) at the time p executes line 46 for the jth time during I, the local variable curr ptr = ptrj . Proof. By induction on j. Base Case. j = i + 1. In this case, (1) holds by Claim C.2.25.6 and (2) holds by assumption. Inductive Case. For every j ∈ [i + 1..n), if (1) and (2) hold for j, then (1) and (2) hold for j + 1. Suppose for any j ∈ [i + 1..n) (1) p executes line 46 j times during I and (2) at the time p executes line 46 for the jth time during I, curr ptr = ptrj . This is the inductive hypothesis. Let Ij be the jth iteration of the loop on line 46 during I, which is well-defined by (1) of the inductive hypothesis. Furthermore, let Tj46 be the time of p’s jth execution of line 46 during I which is the start of Ij . Since by (2) of the inductive hypothesis curr ptr = ptrj at Tj46 where j ∈ [i + 1..n), by Claim C.2.25.4, p executes line 52 at some time Tj52 during Ij and curr ptr = ptrj+1 at Tj52 . Hence, since p executes s during I, it follows that p executes line 46 one more time during I, and so p executes line 46 j + 1 times during I. Since curr ptr = ptrj+1 at Tj52 , and the value of curr ptr does not change between Tj52 and the time of p’s j + 1th execution of line 46 during I, it follows that at the time p executes line 46 for the j + 1th time during I curr ptr = ptrj+1 . Therefore, (1) and (2) hold for j + 1 as wanted. Claim C.2.25.9 46 be the time p executes line 46 for We now return to the proof of Proposition C.2.25. Let Ti+1 the i + 1th time during I. By Claim C.2.25.6, there are two cases. 46 . Case 1. The local variable curr ptr = ptr at Ti+1

Hence, since the second parameter of I is ptr, p finds the condition on line 46 to be false at 46 . Thus, since by Claim C.2.25.7 prev ptr = ptr 46 Ti+1 i−1 at Ti+1 , and prev ptr only changes on 46 lines 45 and 52, we have that prev ptr = ptri−1 from Ti+1 onwards in I. Hence, every CAS operation on line 61 during I is on (∗ptri−1 ).next. Thus, since s is an execution of line 61 during I, we have that s is a CAS operation on (∗ptri−1 ).next. Let T 56 be the time p executed line 56 during I (this is well-defined since p executed s during I). Hence, T 56 < T 59 . Furthermore, since all steps during I are after e, we have that e < T 56 , and so T 56 ∈ (e, T 59 ]. Hence, by Claim C.2.25.8, (∗ptri ).next.ptr = ptri+1 at T 56 . Thus, since the second parameter of I is ptr, and ptr = ptri , we have that p read ptri+1 from (∗ptri ).next.ptr at T 56 . So, since s is a CAS operation on (∗ptri−1 ).next, we have that s attempts to change the next field of ptri−1 to (∗, ∗, ∗, ptri+1 ). Hence, by Definition C.1.5, s is a list-remove attempt between ptri−1 and ptri+1 . Since s is a list-remove attempt for ptr and ptr = ptri , we have that s is a list-remove attempt for ptri between ptri−1 and ptri+1 . Hence, since i is unique, i is in [1..n], and List(Ieexclude ) = ptr0 , . . . , ptrn+1 , we have that ptri appears in List(Ieexclude ) exactly once and ptri−1 and ptri+1 are the pointers preceding and succeeding ptri in List(Ieexclude ). Therefore, we have established the following: s is a list-remove attempt for ptri between ptri−1 and ptri+1 , s is preceded by a unique L-remove event for ptr (namely e), Ieexclude is the prefix of I up to but excluding this L-remove event, ptri appears in List(Ieexclude ) exactly once, and ptri−1 and ptri+1 are the pointers preceding and succeeding ptri in List(Ieexclude ), and so 2. of Q(I ◦ s) holds as wanted. 46 . Case 2. The local variable curr ptr = ptri+1 at Ti+1

Hence, by Claim C.2.25.6 i < n. Furthermore, by Claim C.2.25.9 p executes line 46 n times during I, and at the time p executes line 46 for the nth time during I curr ptr = ptrn . Let In be 123

the nth iteration of the loop on line 46 during I. Since Ieexclude is a prefix of I, List(Ieexclude ) = ptr0 , . . . , ptrn+1 , by assumption P (I) holds, and i ∈ [1..n], by Lemma C.1.114 for every j ∈ [0..n+1], if i ̸= j, then ptri ̸= ptrj . Hence, since ptri = ptr, for every j ∈ [0..n + 1], if i ̸= j, then ptr ̸= ptrj . Thus, since i < n, we have that i ̸= n, so ptr ̸= ptrn . Hence, since curr ptr = ptrn at the start of In and the second parameter of I is ptr, we have that p finds the condition on line 46 to be true at the start of In . Thus, since p executes s during I, p invokes and exits the AcquireNext procedure during In . Denote this execution of the AcquireNext procedure by I ∗ . We first prove that the response of I ∗ is (NotFound, ∗) by satisfying the conditions of Lemma C.2.11. Since the first parameter of I is ulloL and curr ptr = ptrn at the start of In , the parameters of I ∗ are (ulloL , ptrn ). Let TI104 and TI105 by defined as in Claim C.2.25.3, and so L.ullo = ulloL at TI105 ∗ ∗ ∗ , and 104 59 ′ TI ∗ ∈ (e, T ]. Hence, there is a prefix of I during (e, T 59 ] up to and including TI104 ∗ ; say I . Thus, by Claim C.2.25.2 the list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in I ′ . So, since List(Ieexclude ) = ptr0 , . . . , ptrn+1 , List(Ieinclude ) = ptr0 , . . . , ptri−1 , ptri+1 , . . . , ptrn+1 , and i < n, by Definition C.1.7, at the end of I ′ (∗ptrn ).next.ptr = ptrn+1 . Hence, since ptrn+1 = Null, we have that (∗ptrn ).next.ptr = Null at the end of I ′ . Therefore, we have established the following: since (1) I ∗ has parameters (ulloL , ptrn ); (2) L.ullo = ulloL at TI105 ∗ ; and (3) (∗ptrn ).next.ptr = Null 104 ∗ at TI ∗ , and so by Lemma C.2.11, I ’s response is (NotFound, ∗) as wanted. We now finish the proof of Case 2. Since p executes s during I and I ∗ ’s response is (NotFound, ∗), p finds the condition on line 48 to be true during In and so p executes line 49 during In . Therefore, p does not execute line 61 during I. However, p executes s during I, which is an execution of line 61, a contradiction, so this case is impossible. Proposition C.2.25 Inductive Case for R Proposition C.2.26. If P (I), Q(I), and R(I) hold, then 1. of R(I ◦ s) holds. Proof. Since by assumption R(I) holds, it suffices to consider the case where I has at least one L-event, the last L-event in I is an L-add event for ptr, and s is an L-event, with the goal of proving that between e and s there is one successful list-add attempt for ptr and no other successful list-add or list-remove attempts for any pointer. Let e be the last L-event in I, so e is an L-add event for ptr. Hence, by P (I), e is the only L-add event for ptr in I. Furthermore, e and s are successive L-events in I ◦ s. Thus, by Lemma C.1.41 p read the value v that e set L to on its last execution of line 14 before s; say at time T 14 . Hence, since e is an L-add event for ptr, by Definition C.1.5, v = ((∗, AddCell), ptr). Thus, between T 14 and s, p finds the condition on line 15 to be true, and so p invokes and exits the DoAddCell procedure with a second parameter of ptr between T 14 and s. Denote this invocation of the DoAddCell procedure by I. Since I exits before s, and s is the step after I in I ◦ s, we have that I exits at some time Te during I. Hence, since P (I), Q(I), and R(I) hold, by Lemma C.2.13, there is a successful list-add attempt a for ptr before Te in I. Thus, since Te is in I, it is before s, and so a < s. Furthermore, since a is a successful list-add attempt for ptr, by Definition C.1.5, it was executed during a DoAddCell procedure with a second parameter of ptr, so by Corollary C.1.37, there is a L-add event for ptr before a, which must be e since it is the only L-add event for ptr in I. Therefore, since e < a and a < s, we have that there is a successful list-add attempt for ptr between e and s. What remains is to show that there are no other successful list-add or list-remove attempts between e and s. Since (1) I has at least one L-event, (2) I has a last L-event (namely e), (3) P (I), Q(I), and R(I) hold and (4) e is an L-add event for ptr, by Lemma C.2.3 from e onwards in I, there is at most one successful list-add attempt for ptr and no other successful list-add or list-remove attempts for any pointer. Proposition C.2.26 Proposition C.2.27. If P (I), Q(I), and R(I) hold, then 2. of R(I ◦ s) holds. 124

Proof. Since R(I) holds, it suffices to consider the case where I has at least one L-event, the last L-event in I is an L-apply event, and s is an L-event. Let e be the last L-event in I and consider any list-add or list-remove attempt a during (e, s) in I. Since (1) I has at least one L-event, (2) I has a last L-event (namely e), (3) P (I), Q(I), and R(I) hold, and (4) e is an L-apply event, by Lemma C.2.4, from e onwards in I there are no successful list-add or list-remove attempts. Therefore, a is unsuccessful as wanted. Proposition C.2.27 Proposition C.2.28. If P (I), Q(I), and R(I) hold, then 3. of R(I ◦ s) holds. Proof. Since by assumption R(I) holds, it suffices to consider the case where I has at least one L-event, the last L-event in I is an L-remove event for ptr, and s is an L-event, with the goal of proving that between e and s there is one successful list-remove attempt for ptr and no other successful list-add or list-remove attempts for any pointer. Let e be the last L-event in I, and so e is an L-remove event for ptr. Hence, by P (I), e is the only L-remove event for ptr in I. Furthermore, e and s are successive L-events in I ◦ s. Thus, by Lemma C.1.41 p read the value v that e set L to on its last execution of line 14 before s; say at time T 14 . Hence, since e is an L-remove event for ptr, by Definition C.1.5, v is of the form ((∗, RemoveCell), ptr). Thus, between T 14 and s, p finds the condition on line 17 to be true, and so p invokes and exits the DoRemoveCell procedure with a second parameter of ptr between T 14 and s. Denote this invocation of the DoRemoveCell procedure by I. Since I exits before s, and s is the step after I in I ◦ s, we have that I exits at some time Te during I. Hence, since by assumption P (I), Q(I), and R(I) hold, by Lemma C.2.15, there is a successful list-remove attempt a for ptr before Te in I. Thus, since Te is in I it is before s, and so a < s. Furthermore, since a is a successful list-remove attempt for ptr, by Definition C.1.5, it was executed during a DoRemoveCell procedure with a second parameter of ptr, so by Corollary C.1.37, there is a L-remove event for ptr before a, which must be e since it is the only L-remove event for ptr in I. Therefore, since e < a and a < s, there is a successful list-remove attempt for ptr between e and s. What remains is to show that there are no other successful list-add or list-remove attempts between e and s. Since (1) I has at least one L-event, (2) I has a last L-event (namely e), (3) by assumption P (I), Q(I), and R(I) hold and (4) e is an L-remove event for ptr, by Lemma C.2.5 from e onwards in I, there is at most one successful list-remove attempt for ptr and no other successful list-add or list-remove attempts for any pointer. Proposition C.2.28 Inductive Case for O Proposition C.2.29. If P (I) and O(I) hold, then O(I ◦ s) holds. Proof. Since by assumption O(I) holds, it suffices to consider the case where I has at least one L-event, and s is an L-event. Let e be the last L-event in I. By Lemma C.1.29 e is either an L-add, L-remove, or L-apply event. Suppose e is an L-add or L-remove event. Hence, (1) I has a last L-event (namely e), (2) by assumption P (I) and O(I) hold, and (3) e is an L-add or Lremove event, and so by Lemma C.2.10, from e onwards in I there are no successful S-attempts as wanted. Now suppose e is an L-apply event for some timestamp t. Hence, since P (I) holds, by Lemma C.1.33, e is the only L-apply event for timestamp t in I. Let p be the process that executed s. Since e and s are successive L-events in I ◦ s, by Lemma C.1.41, p read the value that e set L to on its last execution of line 14 before s; say at time T 14 . Hence, since e is an L-apply event for timestamp t, by Definition C.1.5, p read a value of the form (t, ⟨Apply&CopyResponse, ∗⟩) from L.ullo at T 14 . Thus, p finds the condition on line 19 to be true between T 14 and s, and therefore p invokes and exits the DoApply&CopyResponse procedure on line 20 with a first parameter of (t, ∗) between T 14 and s. Denote this invocation by I. Since I exits before s, and s is the step after I in I ◦ s, we have that I exits at some time Te during I. Hence, since by assumption P (I) and O(I) 125

hold, by Lemma C.2.17, there is a successful S-attempt a for timestamp t before Te in I. Thus, since Te is in I it is before s, and so a < s. Furthermore, since a is a successful S-attempt for timestamp t, by Corollary C.1.44, there is a L-apply event for timestamp t before a, which must be e since it is the only L-apply event for timestamp t in I. Therefore, since e < a and a < s, there is a successful S-attempt for timestamp t between e and s. What remains is to show that there are no other successful S-attempts between e and s. Since (1) I has a last L-event (namely e), (2) by assumption P (I) and O(I) hold, and (3) e is an L-apply event for timestamp t, by Lemma C.2.9, from e onwards in I, there is at most one successful S-attempt for t and no other successful S-attempts for any timestamp. Proposition C.2.29 The Finale Lemma C.2.30. P (I B ), Q(I B ), R(I B ), and O(I B ) hold. Proof. Let P(n) be the predicate: for every implementation history In of B comprised of n steps, P (In ), Q(In ), R(In ), and O(In ) hold. We prove P(n) by induction on n. Base Case. P(0). Since I0 contains zero steps, and P (I0 ), Q(I0 ), R(I0 ), and O(I0 ), assert properties about certain steps in I0 , they are vacuously true. Inductive Case. ∀n P(n) =⇒ P(n + 1). Suppose for some n ≥ 0 P(n) holds and consider any implementation history In+1 of B comprised of n+1 steps. Let In be the prefix of In+1 up to but excluding its last step, so In is an implementation history of B comprised of n steps. Hence, since P(n) holds, we have that P (In ), Q(In ), R(In ), and O(In ) hold. Thus, by Proposition C.2.23 P (In+1 ) holds. Furthermore, by Propositions C.2.24 and C.2.25 Q(In+1 ) holds. Moreover, by Propositions C.2.26, C.2.27, and C.2.28 R(In+1 ) holds. Finally, by Proposition C.2.29, O(In+1 ) holds. Therefore, if I B is finite, then P (I B ), Q(I B ), R(I B ), and O(I B ) hold. What remains is the case where I B is infinite. Observe that, if P (I B ), Q(I B ), R(I B ), or O(I B ) did not hold, then there is a finite prefix I of I B where P (I), Q(I), R(I) or O(I) does not hold, a contradiction to what we just proved. Therefore, the lemma follows. Lemma C.2.30

C.3

B is Linearizable

In this section, we prove that B is linearizable. Consider any implementation history I B of B, let H be the object history obtained by removing all implementation steps from I B , and let V = ((t1 , ⟨Apply&CopyResponse, o1 ⟩), s1 , r1 ), ((t2 , ⟨Apply&CopyResponse, o2 ⟩), s2 , r2 ), . . . be the sequence of values written into the state object S on line 71 during I B . To define our completion of H′ , we map entries of V to operation executions in I B as follows. Lemma C.3.1. For every index i of V , there is a unique operation execution opxi in I B that received ti as a response on line 10 during an invocation of the DoLowLevelOp procedure invoked on line 4. Furthermore, opxi was invoked before ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ) was first written into S on line 71 during I B .

126

Proof. Since ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ) is in V , some process p set the value of S to it on line 71 during I B for the first time; say T 71 . Hence, p did so during an invocation of the DoApply&CopyResponse procedure with a first parameter of (ti , ⟨Apply&CopyResponse, oi ⟩). Thus, by Corollary C.1.37, some L-event set L.ullo = (ti , ⟨Apply&CopyResponse, oi ⟩) before T 71 . So, by Lemma C.1.23, some A-event e′ set A.ullo = (ti , ⟨Apply&CopyResponse, oi ⟩) before T 71 . Let q be the process that executed e′ . Since e′ set A.ullo = (ti , ⟨Apply&CopyResponse, oi ⟩), q received ti as a response on line 10. Therefore, there is an operation execution that received ti as a response on line 10 and so by definition, opxi exists in I B , and this operation execution is unique since responses on line 10 are unique (see Observation C.1.11). Furthermore, since q received ti on line 10 before e′ , and e′ < T 71 , by transitivity, opxi received ti as a response on line 10 before T 71 . Therefore, since q invoked opxi before it received ti as a response on line 10, and p set S to ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ) at T 71 , we have that opxi was invoked before ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ) was written into S on line 71 as wanted. Lemma C.3.1 Let Opx = opx1 , opx2 , . . . be the corresponding sequence of operation executions to values in V . Note that, as of now, there may be duplicate values in V (and hence Opx). Our first order of business in this section will be to prove that this is not the case. We define the completion H′ of H as follows. Consider any incomplete operation execution opx in H. If opx appears in Opx and the first index in which it appears is i, then the response step for opx is appended at the end of H′ with response ri . Otherwise, opx’s invocation step is removed from H′ . We define a sequential object history S using Opx as follows: invocation(opx1 , o1 ), response(opx1 , r1 ), invocation(opx2 , o2 ), response(opx2 , r2 ), . . . where invocation(opxi , oi ) is the invocation step for opxi and response(opxi , ri ) is the response step for opxi which returned the response ri . The remainder of this section proves that <H′ ⊆<S , S is legal with respect to type T , and H′ is equivalent to S. The plan for doing so is as follows. • First, we prove that the values in V are pairwise distinct, implying that so are the operation executions in Opx. • We then define the linearization point ℓ(opx) for opx in Opx to be the time of the ith successful CAS operation on line 71 during I B where i is the unique index opx appears at in Opx. • We then prove (a) every complete operation execution in I B is in Opx and (b) the linearization point ℓ(opx) of every opx in Opx (whether complete in I B or not) is between opx’s invocation and response step in I B (if it exists). These two facts imply that <H′ ⊆<S . • We then prove that for every index i of V , (si , ri ) = applyT (oi , si−1 ). This implies that S is legal with respect to T . • Finally, we prove that if opx is a complete operation execution in I B then its invocation step is for oi and its response is ri in I B . This implies that H′ is equivalent to S. C.3.1

Linearization points

Lemma C.3.2. Every successful S-attempt in I B is for a unique timestamp. Proof. Suppose, for contradiction, there are two successful S-attempts in I B for the same timestamp t. Let a1 and a2 be these two attempts and let e1 and e2 be their corresponding L-events, respectively. Since a1 (resp. a2 ) is for timestamp t, by Corollary C.1.44, e1 (resp. e2 ) is for timestamp t. Hence, since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.33, e1 = e2 = e. Thus, by Corollary C.1.37, e is an L-apply event. There are two cases. 127

Case 1. e is the last L-event in I B . Hence, since a1 and a2 are after e, from e onwards in I B , there are two successful S-attempts for t. However, since I B has a last L-event (namely e), by Lemma C.2.30 P (I B ) and O(I B ) holds, and e is an L-apply event for timestamp t, by Lemma C.2.9, from e onwards in I B there is at most one successful S-attempt for t, a contradiction. Case 2. e is not the last L-event in I B . Hence, there is next L-event after e in I B ; say e′ . Since a1 and a2 are successful S-attempts in I B , e is there corresponding L-event, and by Lemma C.2.30 P (I B ) and O(I B ) hold, by Corollary C.2.8, there are no L-events during (e, a1 ) and (e, a2 ) in I B . Hence, since e′ is the next L-event after e in I B , we have that a1 and a2 are before e′ . Therefore, between e and e′ , there are two successful S-attempts for timestamp t. However, since e and e′ are successive L-events in I B , by O(I B ), there is at most one successful S-attempt between e and e′ , a contradiction. Lemma C.3.2 Lemma C.3.3. Every operation execution opx in I B appears at most once in Opx. Proof. Suppose, for contradiction, there exists an operation execution opx in I B that appears twice in Opx; say at indices i and j, i.e., opxi = opxj = opx for i ̸= j. Hence, by Lemma C.3.1, opx received ti and tj as a response on line 10 during an invocation of the DoLowLevelOp procedure invoked on line 4 during I B . Thus, since line 10 is executed at most once during an invocation of the DoLowLevelOp procedure invoked on line 4 by the process that executed opx during opx, we have that ti = tj . Therefore, since i ̸= j, and the ith (resp. jth) value written into S on line 71 during I B is ((ti , ∗), ∗, ∗) (resp. ((tj , ∗), ∗, ∗)), by Definition C.1.5, we have that there are two successful S-attempts for the same timestamp in I B . However, this contradicts Lemma C.3.2. Lemma C.3.3 Definition C.3.4. Consider any opx in Opx in I B . By Lemma C.3.3, opx appears exactly once in Opx, say at index i. We define the linearization point of opx, denoted by ℓ(opx), to be the time of the ith successful CAS operation on line 71 during I B . C.3.2

The linearization respects the real-time order of operations

Lemma C.3.5. (a) Every complete operation execution opx in I B is in Opx. (b) The linearization point ℓ(opx) of every operation execution opx in Opx (whether complete in I B or not) is after opx’s invocation step in I B and before opx’s response step in I B if it exists. Proof. For part (a) let ptr be the response on line 2 during opx. Let I apply and I remove be the invocations on line 4 and line 6, respectively, during opx. Hence, I apply has parameters (⟨Apply&CopyResponse, ∗⟩, ptr) and I remove has parameters (RemoveCell, ptr). Since opx is complete, I apply begins and exits at times Tbapply and Teapply , respectively, and I remove begins and exits at times Tbremove and Teremove , respectively, such that Tbapply < Teapply < Tbremove < Teremove . Since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.106, there is an L-apply event eapply for ptr between Tbapply and Teapply , and by Lemma C.1.107, there is an L-remove event eremove for ptr between Tbremove and Teremove . Hence, since Tbapply < Teapply < Tbremove < Teremove , we have that eapply < eremove . Let t be the response on line 10 during I apply . Hence, by Lemma C.1.108, eapply is for timestamp t. Since eapply < eremove , we have that there is a next L-event after eapply in I B ; say e. Hence, since eapply and e are successive L-events, and eapply is an L-apply event for timestamp t, by O(I B ) (which holds by Lemma C.2.30), there is a successful S-attempt a for timestamp t during (eapply , e). Thus, by Definition C.1.5, a wrote a value of the form ((t, ∗), ∗, ∗) into S during I B , and so ((t, ∗), ∗, ∗) appears in V , say at index i, so t = ti . So, by Lemma C.3.1, there is a 128

unique operation execution opxi that received ti as a response on line 10 during an invocation of the DoLowLevelOp procedure invoked on line 4 during I B . Therefore, since opx received t as a response on line 10 during I apply which is an invocation of the DoLowLevelOp procedure invoked on line 4, we have that opx = opxi , and so opx is in Opx, which completes the proof of part (a). We now prove part (b) for opx. Since by Observation C.1.6 only successful S-attempts change the value of S in I B , and by Lemma C.3.2 every successful S-attempt in I B is for a unique timestamp, it follows that for every index i and j of V if i ̸= j, then ti ̸= tj . Hence, ((ti , ∗), ∗, ∗) is written into S in I B once, and by the ith successful CAS operation on line 71 during I B . Thus, since a wrote a value of the form ((t, ∗), ∗, ∗) into S during I B , and t = ti , we have that a is the ith successful CAS operation on line 71 during I B . So, since opx is in Opx and appears at index i, by Definition C.3.4, ℓ(opx) is the time of a. We now position a (and hence ℓ(opx)) between opx’s invocation and response steps. Since e is the next L-event after eapply in I B , and eapply < eremove , it follows that e ≤ eremove . Hence, since the invocation step of opx is before Tbapply , Tbapply < eapply , eapply < a, a < e, e ≤ eremove , eremove < Teremove , and the response step of opx is after Teremove , by transitivity, a (and hence ℓ(opx)) is between the invocation and response step of opx. Therefore, for every complete operation execution opx in I B , ℓ(opx) is is after opx’s invocation step in I B and before opx’s response step in I B . To complete the proof of part (b), consider any operation execution opx in Opx that is incomplete in I B . Hence, opx does not have a response step in I B , so it suffices to prove that ℓ(opx) is after opx’s invocation step in I B . Suppose opx = opxi . Hence, by Definition C.3.4, the step at time ℓ(opx) set S to ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ). Therefore, by Lemma C.3.1, opxi (and hence opx) was invoked before ℓ(opx), which completes the proof of part (b). Lemma C.3.5 Lemma C.3.6. <H′ ⊆<S Proof. Consider any two operation executions opx and opx′ in H′ such that opx <H′ opx′ . Thus opx’s response step in H′ is before opx′ ’s invocation step in H′ . Hence, by the construction of H′ : opx is complete in H, opx <H opx′ , and if opx′ is incomplete in H, then opx′ is in Opx. Since H is the result of removing all implementation steps in I B , this implies that opx is complete in I B and that opx’s response step in I B is before opx′ ’s invocation step in I B . Since opx is complete in I B , by Lemma C.3.5 (a), opx is in Opx. Thus, by Lemma C.3.5 (b), ℓ(opx) is before opx’s response step in I B (which exists since opx is complete in I B ). Likewise, if opx′ is complete in H, then opx′ is complete in I B , in which case by Lemma C.3.5 (a), opx′ is in Opx. Hence, since if opx′ is incomplete in H, then opx′ is in Opx, we have that in any case, opx′ is in Opx. Thus, by Lemma C.3.5 (b), ℓ(opx′ ) is after opx′ ’s invocation step in I B . Therefore, we have established the following: (1) ℓ(opx) is before opx’s response step; (2) opx’s response step is before opx′ ’s invocation step; and (3) opx′ ’s invocation step is before ℓ(opx′ ). So, by transitivity, ℓ(opx) < ℓ(opx′ ). Since opx and opx′ are both in Opx, we have that opx = opxi and opx′ = opxj for indices i and j in Opx. Hence, since ℓ(opx) < ℓ(opx′ ), by Definition C.3.4, i < j. Thus, opx appears before opx′ in Opx. Therefore, by the construction of S, opx’s response step is before opx′ ’s invocation step in S, which implies opx <S opx′ , completing the lemma. Lemma C.3.6 C.3.3

The linearization respects the specification of the target object type

We start by proving that oi comes from the proper domain. Lemma C.3.7. Let OP be the set of operations of type T . Then, oi ∈ OP . Proof. Consider the ith successful CAS operation on S on line 71 in I B and denote it by ai . Hence, ai was executed during some invocation of the DoApply&CopyResponse with a first parameter 129

of (ti , ⟨Apply&CopyResponse, oi ⟩). Thus, by Corollary C.1.37, there is an L-event that set L.ullo = (ti , ⟨Apply&CopyResponse, oi ⟩). So, by Lemma C.1.23, there is an A-event that set A.ullo = (ti , ⟨Apply&CopyResponse, oi ⟩). Hence, it was executed during some invocation of the DoLowLevelOp procedure with a first parameter of ⟨Apply&CopyResponse, oi ⟩. Thus, this DoLowLevelOp procedure was invoked on line 4, and so oi was the first parameter of some invocation of the DoHighLevelOp procedure. Therefore, oi ∈ OP as wanted. Lemma C.3.7 Lemma C.3.8. For every index i of Opx, (si , ri ) = applyT (oi , si−1 ), where s0 is the initial state of type T . Proof. By definition, si and ri are the values written in S.state and S.resp, respectively, by the ith successful CAS on S on line 71 in I B . Let ai denote this CAS, let p be the process that performed ai , and let I be the invocation of the DoApply&CopyResponse procedure that q performed ai during. Since ai is the ith CAS on S on line 71 in I B , we have that ai set S to ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ). Hence, we have that the first parameter of I is (ti , ⟨Apply&CopyResponse, oi ⟩). Thus, by line 70 and 69, (si , ri ) = applyT (oi , s), where s is the state in S.state that p read on line 66 during I. So, since ai is successful, it follows that S.state = s at the step before ai in I B . Hence, by Observation C.1.6, s is the value written in S.state by the (i − 1)-th successful CAS on S on line 71 during I B , or the initial value of S if i = 1 (which is s0 ), so s = si−1 . Therefore, (si , ri ) = applyT (oi , si−1 ), as wanted. Lemma C.3.8 Since by Lemma C.3.7 oi is a valid operation of type T , by a simple induction, Lemma C.3.8 implies that for every index i of Opx si ∈ Q where Q is the set of states of type T and ri ∈ RES where RES is the set of responses of type T . Therefore, oi , si , and ri are all valid operations, states, and responses of type T , respectively, so by Lemma C.3.8 and the definition of applyT : Corollary C.3.9. S is legal with respect to T . C.3.4

The linearization is equivalent to the completed history

Proposition C.3.10. Every operation execution opx in H′ is in Opx. Proof. Since H′ is derived from H, and H is derived from I B , we have that opx is an operation execution in I B . There are two cases. Case 1. opx is complete in I B . Hence, by Lemma C.3.5 (a), opx is in Opx. Case 2. opx is incomplete in I B . Hence, opx is incomplete in H, and so by the definition of H′ , opx is in Opx.

Proposition C.3.10

Lemma C.3.11. Consider any operation execution opx in H′ whose invocation step is for operation o and let i be the unique index that opx appears in Opx, i.e., opx = opxi (i is well-defined by Proposition C.3.10 and Lemma C.3.3). Then, o = oi . Proof. Since opx is in H′ , by definition, it is in I B . Furthermore, since opx = opxi , by Lemma C.3.1, opx received ti as a response on line 10 during an invocation I of the DoLowLevelOp procedure invoked on line 4 during I B . Hence, since I is an invocation of the DoLowLevelOp procedure invoked on line 4 during opx and opx’s invocation step is for operation o, the first parameter of I is ⟨Apply&CopyResponse, o⟩. Furthermore, ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ) was written into S during I B . Hence, by Observation C.1.6, a successful S-attempt set S to 130

((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ) during I B . Thus, by Lemma C.1.43, an L-event set L.ullo = (ti , ⟨Apply&CopyResponse, oi ⟩). So, by Lemma C.1.23, an A-event e set A.ullo = (ti , ⟨Apply&CopyResponse, oi ⟩). Let p be the process that executed opx, and let q be the process that executed e. Since q executed e and e set A.ullo = (ti , ⟨Apply&CopyResponse, oi ⟩), we have that q received ti as a response on line 10. Hence, since p also received ti as a response on line 10, and by Observation C.1.11 the responses on line 10 are unique, it follows that p = q. Thus, p performed e, and since e set A.ullo = (ti , ⟨Apply&CopyResponse, oi ⟩), we have that p performed e during an invocation I ′ of the DoLowLevelOp procedure in which p received ti as a response on line 10 and whose first parameter is ⟨Apply&CopyResponse, oi ⟩. So, since p also received ti as a response on line 10 during I, and the responses on line 10 are unique, we have that I = I ′ . Therefore, since I’s first parameter is ⟨Apply&CopyResponse, o⟩, and I ′ ’s first parameter is ⟨Apply&CopyResponse, oi ⟩, we have that o = oi as wanted. Lemma C.3.11 Lemma C.3.12. Consider any operation execution opx in H′ whose response step is for response r in H′ and let i be the unique index that opx appears in Opx, i.e., opx = opxi (i is well-defined by Proposition C.3.10 and Lemma C.3.3). Then, r = ri . Proof. By definition of H′ and the fact that i is unique, the lemma trivially holds when opx is incomplete in H. Hence, it suffices to consider the case where opx is complete in H. Since H is derived from I B , opx is complete in I B . Hence, since opx is in Opx, by Lemma C.3.5 (b), ℓ(opx) is after opx’s invocation step and before opx’s response step in I B . Let p be the process that executed opx. Since opx is complete in I B p did the following during opx: p executed line 2 and got response ptr ∈ C, p invoked an invocation I apply of the DoLowLevelOp procedure on line 4 with parameters (⟨Apply&CopyResponse, ∗⟩, ptr) that began at time Tbapply and exited at some time Teapply during opx, and p invoked an invocation I remove of the DoLowLevelOp procedure on line 6 with parameters (RemoveCell, ptr) that began at time Tbremove and exited at some time Teremove during opx. Hence, Tbapply < Teapply < Tbremove < Teremove . Let T 12 be the time p executed line 12 during I apply . Then, by Lemma C.1.103, between T 12 and Teapply , there is a successful apply-response-set attempt aR for ptr. Since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.106, there is an L-apply event e for ptr between Tbapply and Teapply . Likewise, by Lemma C.1.107, there is an L-remove e′ event for ptr between Tbremove and Teremove . Hence, since Tbapply < Teapply < Tbremove < Teremove , we have that e < e′ . Let t be the response p received on line 10 during I apply , so by Lemma C.1.108 e is for timestamp t. Furthermore, since opx = opxi , by Lemma C.3.1, t = ti . Let aS be the successful S-attempt at ℓ(opx). Hence, since opx = opxi , by Definition C.3.4, aS is a successful S-attempt for timestamp ti , and since t = ti , we have that aS is a successful S-attempt for timestamp t. Claim C.3.12.1. aR is a successful apply-response-set attempt for ptr to ri . Proof. Let q be the process that executed aR and let I ′ be the invocation of the SetResponse procedure that q executed aR during. Since aR is a successful apply-response-set attempt for ptr, by Observation C.1.12, q invoked I ′ on line 73 during some invocation I ∗ of the DoApply&CopyResponse procedure. The remainder of the proof is split into two cases. Case 1. q found the condition on line 68 to be true during I ∗ . Hence, q executed line 72 during I ∗ ; say at time T 72 . Thus, since q executed aR during the SetResponse procedure on line 73 during I ∗ , we have that T 72 < aR . Since e < e′ , it follows that there is a next L-event after e in I B ; say ea . Hence, since e is an L-apply event for timestamp t, and by Lemma C.2.30 O(I B ) holds, we have that there is exactly one successful S-attempt between e

131

and ea in I B and it is for timestamp t. Therefore, since aS is a successful S-attempt for timestamp t, by Lemma C.3.2, aS is the single successful S-attempt between e and ea in I B . Let eS be aS ’s corresponding L-event (see Lemma C.1.43), so eS is before I ∗ was invoked. We prove that e = eS . Since aS is a successful S-attempt for timestamp t, by Corollary C.1.44, eS is an L-event for timestamp t. Hence, since P (I B ) holds, by Lemma C.1.33, eS is the only L-event for timestamp t in I B . Therefore, since e is an L-event for timestamp t, we have that e = eS as wanted. Hence, since eS is before I ∗ was invoked, we have that e is before I ∗ was invoked. We now prove that aS < T 72 . Suppose, for contradiction, that T 72 < aS . Let T 66 and T 71 be the times that q executed lines 66 and 71 during I ∗ , respectively. Since by definition T 66 < T 71 < T 72 , and by assumption T 72 < aS , by transitivity, T 66 < T 71 < T 72 < aS . Since e is before I ∗ is invoked, we have that e < T 66 , and so e < T 66 < T 71 < T 72 < aS . Furthermore, since aS < ea , by transitivity, e < T 66 < T 71 < T 72 < aS < ea . There are two cases. Case 1.1. q’s CAS operation at T 71 is successful. Hence, by Observation C.1.6, q’s step at T 71 is a successful S-attempt. Therefore, since e < T 66 < T 71 < T 72 < aS < ea , we have that there are two successful S-attempts between e and ea . However, aS is the only successful S-attempt between e and ea , a contradiction. Case 1.2. q’s CAS operation at T 71 is unsuccessful. Hence, the value of S changed between T 66 and T 71 . Thus, by Observation C.1.6, there is a successful S-attempt between T 66 and T 71 . Therefore, since e < T 66 < T 71 < T 72 < aS < ea , we have that there are two successful S-attempts between e and ea . However, aS is the only successful S-attempt between e and ea , a contradiction. We now prove that T 72 < ea . Let r be the process that executed ea . Since e and ea are successive L-events, by Lemma C.1.41, r read the value that e set L to on its last execution of line 14 before ea ; say time T 14 . Since e is an L-apply event for ptr, by Definition C.1.5, r read a value of the form ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from L at T 14 . Hence, since r executes ea , p finds the condition on line 20 to be true after T 14 , and so p invokes the DoApply&CopyResponse procedure with parameters (∗, ptr) after T 14 and exits it before ea . Denote this invocation of DoApply&CopyResponse procedure by I. Since I has parameters (∗, ptr) and exits before ea , and by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) holds, by Lemma C.2.18, there is a successful applyresponse-set attempt for ptr before ea . Hence, since aR is a successful apply-response-set attempt for ptr, and by Corollary C.1.81 there is at most one successful apply-response-set attempt for ptr in I B , it follows that aR < ea . Therefore, since T 72 < aR , by transitivity, T 72 < ea as wanted. We now finish the proof of Case 1. So far we have established that e < aS < T 72 < ea and aS is the only successful S-attempt between e and ea . Hence, since aS is at time ℓ(opx) and opx = opxi , by Definition C.3.4, aS set S to ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ), and so the value of S is ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ) throughout (aS , ea ). Thus, since T 72 ∈ (aS , ea ), we have that q read ri from S.resp on line 72 at T 72 . So, since q invoked I ′ on line 73 during I ∗ , we have that the third parameter of I ′ is ri . Therefore, since q executed aR during I ′ , by Definition C.1.5, aR is a successful apply-response-set attempt for ptr to ri as wanted. Case 2. q found the condition on line 68 to be false during I ∗ . Let (ullo, s, r) be the value q read from S on line 66 during I ∗ , say at time T 66 , and let ulloL be the first parameter of I ∗ . Hence, since q executed I ′ during I ∗ , we have that the first parameter of I ′ is ulloL . Thus, since q executed aR during I ′ , and aR is an apply-response-set attempt for ptr, we have that aR tries to set (∗ptr).response.ullo to ulloL . So, by Lemma C.1.73 and 132

Corollary C.1.74, an L-apply event eR set L = (ulloL , ptr) before aR . Since by Lemma C.2.30 P (I B ) holds, we have that eR is the only L-apply event for ptr in I B , and so since e is also an L-apply event for ptr in I B , it follows that e = eR . Hence, e set L = (ulloL , ptr) and e < aR . Thus, since e is for timestamp t, by Definition C.1.5, ulloL = (t, ∗). Since q found the condition on line 68 to be false during I ∗ , it follows that ullo = ulloL . Hence, since ulloL = (t, ∗), we have that ullo = (t, ∗). Since aS is for timestamp t, by Lemma C.1.45, t > 0. Hence, since q read (ullo, s, r) from S on line 66 at time T 66 , and ullo = (t, ∗), we have that some step set S = (ullo, s, r). Thus, by Observation C.1.6, some successful S-attempt set S = (ullo, s, r), and since ullo = (t, ∗), by Definition C.1.5, this S-attempt is for timestamp t. So, since by Lemma C.3.2 every successful S-attempt has a unique timestamp, and aS is for timestamp t, we have that aS set S = (ullo, s, r). Hence, since aS is the step at ℓ(opx), and opx = opxi , by Definition C.3.4, aS set S to ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ), and so ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ) = (ullo, s, r). Thus, q read ((ti , ⟨Apply&CopyResponse, oi ⟩), si , ri ) from S on line 66 at T 66 , and so since q found the condition on line 68 to be false during I ∗ , and q invoked I ′ during I ∗ , we have that the third parameter of I ′ is ri . Therefore, since q executed aR during I ′ , by Definition C.1.5, aR is a successful apply-response-set attempt for ptr to ri as wanted. Claim C.3.12.1 Let T 5 be the time p executes line 5 during opx (this is well-defined since opx is complete in H). Since aR is before Teapply , I apply exits at Teapply , and I apply is the invocation of the DoLowLevelOp procedure on line 4 during opx, we have that aR < T 5 . Claim C.3.12.2. The value of (∗ptr).response is unchanged throughout (aR , T 5 ]. Proof. Suppose, for contradiction, the value of (∗ptr).response changes during (aR , T 5 ]. Hence, by Observation C.1.6, there is a response-reset event for ptr or a successful response-set attempt for ptr during (aR , T 5 ]. We consider each case separately. Case 1. There is a successful response-set attempt a for ptr during (aR , T 5 ]. Hence, by Lemma C.1.77, (∗ptr).response.resp ̸= Null at aR . Hence, since by Definition C.1.5, a is a CAS operation on line 77 and a is successful, we have that (∗ptr).response.resp = Null at the step before a. Thus, (∗ptr).response.resp was set to Null between aR and a. Hence, by Observation C.1.6, either a response-reset event for ptr or a successful response-set attempt for ptr set (∗ptr).response.resp = Null between aR and a. Therefore, since by Lemma C.1.77, every successful response-set attempt for ptr sets (∗ptr).response.resp ̸= Null, we have that there is a response-reset event for ptr between aR and a. However, since a ≤ T 5 , there is a response-reset event for ptr during (aR , T 5 ] and so this case reduces to the next one. Case 2. There is a response-reset event e for ptr during (aR , T 5 ]. Let q be the process that executed e and let I ′ be the invocation of the DoLowLevelOp procedure that q executed e during. Since e is a response-reset event for ptr, by Definition C.1.5, the parameters of I ′ are (∗, ptr). Hence, q received ptr as a response on line 2. Thus, since by Algorithm 4 every response on line 2 is unique and p received ptr as a response on line 2, we have that p = q. Therefore, since e is between aR and T 5 , aR is between T 12 and Teapply , and p executes line 12 at T 12 , we have that p executes line 12 twice during [T 12 , T 5 ]. However, since p is inside I apply throughout [T 12 , Teapply ] and I apply was invoked on line 4 during opx, there is at most one execution of line 12 during [T 12 , T 5 ], a contradiction. Claim C.3.12.2 We now finish the proof of Lemma C.3.12. Since by Claim C.3.12.1 aR is a successful applyresponse-set attempt for ptr to ri , by Claim C.3.12.2 the value of (∗ptr).response is unchanged 133

during (aR , T 5 ], and aR < T 5 , we have that (∗ptr).response = (∗, ri ) at T 5 . Hence, since p received ptr as a response on line 2 during opx, and T 5 is the time p executes line 5 during opx, the value of the local variable resp on line 5 during opx is ri . Therefore, since the local variable resp on line 5 is unchanged for the remainder of opx, the response of opx on line 8 is ri as wanted. Lemma C.3.12 Lemma C.3.13. H′ is equivalent to S. Proof. We must prove that H′ |p = S|p for each process p. Since by Proposition C.3.10 every operation execution in H′ is in Opx, by Lemma C.3.3, every operation execution in H′ is in Opx exactly once. Furthermore, since every operation execution in Opx is an operation execution in I B , and thus H′ , we have that every operation execution in Opx is in H′ . Hence, since the sequence of operation executions in S is Opx, we have that every operation execution in H′ is in S exactly once, and every operation execution in S is in H′ exactly once. Now consider any operation execution opx in H′ . Suppose opx = opxi , and let invocation(opx, o) and response(opx, r) be its invocation and response steps in H′ , respectively. Hence, by Lemma C.3.11 o = oi and by Lemma C.3.12 r = ri , so invocation(opx, oi ) and response(opx, ri ) are the invocation and response steps of opx in H′ . Likewise, since opx = opxi , by the definition of S, invocation(opx, oi ) and response(opx, ri ) are opx’s invocation and response steps in S, respectively. Therefore, the invocation and response steps are the same for opx in H′ and S. Since operation executions for each process p appear sequentially in I B from which H′ is derived, H′ |p is a sequential object history. Thus <H′ |p is a total order over all operation executions in H′ |p . Likewise, since S|p is a sequential object object history, <S|p is a total order over all operation executions in S|p . Since (1) every operation execution in H′ is in S exactly once, and every operation execution in S is in H′ exactly once, (2) the invocation and response steps are the same for every operation execution opx in H′ and S, (3) <H′ |p is a total order over all operation executions in H′ |p , (4) <S|p is a total order over all operation executions in S|p , and (5) by Lemma C.3.6 <H′ |p ⊆<S|p , it follows that H′ |p = S|p as wanted. Lemma C.3.13 Theorem C.3.14. B is a linearizable with respect to T . Proof. Since H′ is a completion of H, by Lemma C.3.13 H′ is equivalent to S, by Corollary C.3.9 S is legal with respect to T , and by Lemma C.3.6 <H′ ⊆<S , we have that H is linearizable with respect to T . Hence, since H is the object history obtained by removing all implementation steps from I B , we have that I B is linearizable with respect to T . Therefore, since I B is any implementation history of B, we have that B is a linearizable with respect to T . Theorem C.3.14

C.4

B is Wait-free

In this section, we prove that B is wait-free. The proof is by contradiction, so we start by assuming that there is an implementation history I B of B with an operation execution that is “stuck”: Definition C.4.1. We call an operation execution opx in I B stuck when the process that executed opx takes infinitely many steps during opx without completing it. Let S be the set of operation executions in I B that are stuck. We note that this I B is fixed throughout the entire section, and it is assumed that S ̸= ∅. We first note the following properties of stuck operation executions. Observation C.4.2. For every operation execution opx ∈ S, the process that executed opx does the following during opx. (1) Takes infinitely many steps inside exactly one invocation of the DoLowLevelOp procedure. (2) Takes infinitely many steps inside exactly one instance of a loop. 134

We now define an operation execution opxmin ∈ S with the goal of showing that it is not stuck. In short, we show that opxmin is not stuck by showing that it cannot get stuck in each loop. Definition C.4.3. Consider any invocation I of the DoLowLevelOp procedure in I B . Let t(I) denote the response of line 10 during I or ∞ if line 10 was not executed during I. Definition C.4.4. For every opx ∈ S, let I(opx) denote the invocation of the DoLowLevelOp procedure identified by (1) of Observation C.4.2. Let opxmin be the operation in S such that every opx ∈ S, t(I(opxmin )) ≤ t(I(opx)). Throughout the remainder of the section, we define the following regarding opxmin . Let pmin be the process that executed opxmin . Since opxmin ∈ S, by Definition C.4.1, pmin takes infinitely many steps during opxmin in I B without completing it. Furthermore, by (2) of Observation C.4.2, pmin takes infinitely many steps inside exactly one instance of a loop Lmin during opxmin . C.4.1

Processes cannot get stuck in the loops on lines 30, 46, and 94.

This section shows that pmin cannot take infinitely many steps in the loops on lines 30, 46, and 94 during opxmin . If we suppose, for contradiction, that this is not the case, we have: Scenario C.4.5. Suppose Lmin is an instance of any loop except the loop on line 13. Let Imin denote the invocation of the DoAddCell, DoRemoveCell, Acquire, or AcquireNext procedure that Lmin was executed during. Furthermore, let ulloL be the first parameter of Imin . By tracing backwards, we have that pmin read (ulloL , ptrL ) from L on its last execution of line 14 before invoking Imin for 14 . some ptrL ; say at time Tmin The reason for this scenario being more general than stating that Lmin is an instance of a loop on lines 30, 46, and 94, is that most of the facts we prove will be useful when showing that pmin cannot take infinitely many steps in the loops on lines 53, 57, and 103 during opxmin . The high-level argument for why pmin cannot take infinitely many steps in the loops on lines 30, 46, and 94 during opxmin is the following. First, we prove that in Scenario C.4.5, there is a last 14 . L-event emin in I B , that emin set L = (ulloL , ptrL ) (the value pmin read), and that emin < Tmin This implies that the “shape” of the list is one of two finite lists from emin onwards (in particular, )). Second, we prove that in every iteration of Lmin , pmin ) or List(Ieinclude it is either List(Ieexclude min min “traverses” through a cell from one of these two finite lists (in particular, the response of every AcquireNext procedure is (Found, ptr) where ptr is in List(Ieexclude ) or List(Ieinclude )). Third, min min we prove that the pointers it traverses through are distinct (in particular, the response of every AcquireNext procedure is (Found, ptr) where ptr is different than any pointer previously returned from the AcquireNext procedure during Lmin ). The finale is then: since pmin takes infinitely many steps in Lmin , it received infinitely many responses from the AcquireNext procedure, and since they are all for different pointers in one of these two lists, we have that there are infinitely many pointers between these two lists, contradicting the fact that they are both finite. 14 onwards in I B . We start by proving that in Scenario C.4.5 L is fixed from Tmin Proposition C.4.6. In Scenario C.4.5, L.ullo = ulloL infinitely often in I B . Proof. Since Lmin is an instance of any loop except the loop on line 13, there are six cases. Case 1. Lmin is the loop on line 30. Since pmin takes infinitely many steps inside Lmin , we have that pmin invokes and exits the AcquireNext procedure on line 31 infinitely often. Hence, by the condition on line 32, the response of every invocation of the AcquireNext procedure on line 31 during Lmin returns a value other than 135

L-Changed. Thus, pmin finds the condition on line 105 to be false infinitely often. Therefore, since Lmin was executed during Imin , and the first parameter of Imin is ulloL , we have that the first parameter of every invocation of the AcquireNext procedure on line 31 during Lmin is also ulloL , and so L.ullo = ulloL infinitely often as wanted. Case 2. Lmin is the loop on line 46. Since pmin takes infinitely many steps inside Lmin , we have that pmin invokes and exits the AcquireNext procedure on line 47 infinitely often. Hence, by the condition on line 48, the response of every invocation of the AcquireNext procedure on line 47 during Lmin returns a value other than L-Changed. Thus, pmin finds the condition on line 105 to be false infinitely often. Therefore, since Lmin was executed during Imin , and the first parameter of Imin is ulloL , we have that the first parameter of every invocation of the AcquireNext procedure on line 47 during Lmin is also ulloL , and so L.ullo = ulloL infinitely often as wanted. Case 3. Lmin is the loop on line 53. Hence, Imin is an invocation of DoRemoveCell procedure with parameters (ulloL , ptrL ). Thus, by Corollary C.1.37 there is an L-remove e for ptrL that set L = (ulloL , ptrL ). So, by Lemma C.1.28, ptrL ∈ C. We claim that e is the last L-event in I B which completes the proof for this case. Suppose, for contradiction, there is an L-event after e in I B . Let e′ be the next L-event after e in I B , so e and e′ are successive L-events in I B . Hence, since by Lemma C.2.30 R(I B ) holds, and e is an L-remove event for ptrL , we have that there is a successful list-remove attempt for ptrL in I B . Thus, by Lemma C.1.58, there is a successful list-seal attempt for ptrL in I B ; say at time T . So, (∗ptrL ).next.sealed = True at T . Therefore, since ptrL ∈ C, by Observation C.1.6, only successful list-seal attempts change the value of (∗ptrL ).next.sealed, we have that from T onwards (∗ptrL ).next.sealed = True. However, since pmin takes infinitely many steps inside Lmin , we have that pmin finds the condition on line 53 to be false infinitely often, and since ptrL is the second parameter of Imin , it follows that (∗ptrL ).next.sealed = False infinitely often, a contradiction. Case 4. Lmin is the loop on line 57. Since pmin takes infinitely many steps inside Lmin , we have that pmin finds the condition on line 59 to be false infinitely often. Thus, since Lmin was executed during Imin , and the first parameter of Imin is ulloL , we have that L.ullo = ulloL infinitely often as wanted. Case 5. Lmin is the loop on line 94. Since pmin takes infinitely many steps inside Lmin , we have that pmin invokes and exits the AcquireNext procedure on line 95 infinitely often. Hence, by the condition on line 94, the response of every invocation of the AcquireNext procedure on line 95 during Lmin returns a value other than L-Changed. Thus, pmin finds the condition on line 105 to be false infinitely often. Therefore, since Lmin was executed during Imin , and the first parameter of Imin is ulloL , we have that the first parameter of every invocation of the AcquireNext procedure on line 95 during Lmin is also ulloL , and so L.ullo = ulloL infinitely often as wanted. Case 6. Lmin is the loop on line 103. Since pmin takes infinitely many steps inside Lmin , we have that pmin finds the condition on line 105 to be false infinitely often. Thus, since Lmin was executed during Imin , and the first parameter of Imin is ulloL , we have that L.ullo = ulloL infinitely often as wanted. Proposition C.4.6 14 onwards in I B . Proposition C.4.7. In Scenario C.4.5, L.ullo = ulloL from Tmin

136

14 in I B that L.ullo ̸= ullo . Hence, by Proof. Suppose, for contradiction, at some time T after Tmin L Proposition C.4.6, L.ullo = ulloL some time after T ; say T ′ . Thus, since L.ullo ̸= ulloL at T and L.ullo = ulloL at T ′ , we have that the value of L.ullo was set to ulloL between T and T ′ , and so by Observation C.1.6, some L-event e′ set L.ullo = ulloL between T and T ′ . So, by Corollary C.1.27, ulloL ̸= (0, Noop). Hence, since L.ullo = ulloL at T 14 , it follows that L.ullo was set to ulloL before T 14 , and so by Observation C.1.6, some L-event e set L.ullo = ulloL before T 14 . Thus, since e < T 14 , T 14 < T , and T < e′ , by transitivity, e < e′ , so e ̸= e′ . Therefore, two different L-events in I B set L.ullo to the same value (namely ulloL ). However, since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.32, every L-event in I B sets L.ullo to a unique value, a contradiction. Proposition C.4.7

Proposition C.4.8. In Scenario C.4.5, if ulloL = (0, Noop), then there are no L-event in I B . Proof. Suppose, for contradiction, ulloL = (0, Noop) and there is an L-event e in I B . Hence, by Corollary C.1.27, e sets L.ullo ̸= (0, Noop). Thus, since ulloL = (0, Noop), by Proposition C.4.7, 14 onwards in I B , and so e < T 14 . Since (1) L.ullo ̸= (0, Noop) L.ullo = (0, Noop) from Tmin min 14 , and (3) e < T 14 , we have that L.ullo was set to (0, Noop) at e, (2) L.ullo = (0, Noop) at Tmin min 14 . Therefore, by Observation C.1.6, an L-event set L.ullo = (0, Noop). However, between e and Tmin by Corollary C.1.27, every L-event sets L.ullo ̸= (0, Noop), a contradiction. Proposition C.4.8 Lemma C.4.9. In Scenario C.4.5, ulloL ̸= (0, Noop). Proof. There are two cases. Case 1. Lmin is the loop on line 30, 46, 53, or 57. Hence, Imin is an invocation of the DoAddCell or DoRemoveCell procedure. Thus, since ulloL is the first parameter of Imin , by the conditions on lines 15 and 17, we have that ulloL equals (∗, AddCell) or (∗, RemoveCell). Therefore, the claim follows. Case 2. Lmin is the loop on line 94 or 103. Suppose, for contradiction, ulloL = (0, Noop). We first define an invocation I of the AcquireNext procedure by pmin such that pmin finds the condition on line 107 to be false some time during I. If Lmin is the loop on line 94, then since pmin takes infinitely many steps in Lmin , we have that pmin invokes and exits the AcquireNext procedure on line 95 during Lmin infinitely often. Let I be any of these invocations. Since pmin invokes and exits the AcquireNext procedure on line 95 during Lmin infinitely often, we have that I’s response is of the form (Found, ∗) as otherwise, pmin would find the condition on line 97 to be true during Lmin implying pmin would exit Lmin . Hence, pmin finds the condition on line 107 to be false some time during I (otherwise it would return (NotFound, ∗)). If Lmin is the loop on line 103, then Imin is an invocation of the AcquireNext procedure. We let I = Imin . Since pmin takes infinitely many steps during Lmin in I, it immediately follows that pmin finds the condition on line 107 to be false some time during I (otherwise pmin would exit Lmin ). We now finish the proof for Case 2. Let curr ptr be the second parameter of I. Hence, by Corollary C.1.89, curr ptr ∈ C ∪ {&H}. Furthermore, since pmin finds the condition on line 107 to be false sometime during I, we have that (∗curr ptr).next.ptr ̸= Null sometime during I B . Hence, since curr ptr ∈ C ∪ {&H}, the value of (∗curr ptr).next.ptr is initially Null, and so it changed during I B . Thus, by Observation C.1.6, there is a successful list-add or list-remove attempt in I B . Therefore, by Corollary C.1.37, there is an L-event in I B . However, since ulloL = (0, Noop), by Proposition C.4.8, there are no L-events in I B , a contradiction. Lemma C.4.9 137

Lemma C.4.10. In Scenario C.4.5, there is an L-event emin in I B which set L = (ulloL , ptrL ) such 14 . that (1) emin is the only L-event in I B which set L = (ulloL , ptrL ) and (2) emin < Tmin 14 , and by Lemma C.4.9 ullo ̸= (0, Noop), we have Proof. Since p read L = (ulloL , ptrL ) at Tmin L 14 . Hence, by Observation C.1.6, some L-event e that L was set to (ulloL , ptrL ) before Tmin min set 14 . Thus, since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.30, e L = (ulloL , ptrL ) before Tmin min is the only L-event in I B that sets L = (ulloL , ptrL ). Lemma C.4.10

Lemma C.4.11. In Scenario C.4.5, emin is the last L-event in I B . Proof. Suppose, for contradiction, there is an L-event e after emin in I B . There are two cases. 14 . Case 1. e < Tmin 14 . Since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.32, e sets L.ullo Hence, emin < e < Tmin to a different value than emin . Hence, since by Lemma C.4.10 emin sets L.ullo = ulloL , we have 14 , we have that L.ullo was set to ullo that L.ullo ̸= ulloL at e. Thus, since L.ullo = ulloL at Tmin L 14 . So, by Observation C.1.6, some L-event e′ set L.ullo = ullo between e and between e and Tmin L 14 . Therefore, since e ′ ′ Tmin min < e and e < e , we have that emin ̸= e , and so there are two L-events B in I which set L.ullo = ulloL . However, since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.32, every L-event sets L.ullo to a unique value, a contradiction. 14 < e. Case 2. Tmin 14 , by transitivity, e 14 Hence, since by Lemma C.4.10 emin < Tmin min < Tmin < e. Since by Lemma C.2.30 B P (I ) holds, by Lemma C.1.32, e sets L.ullo to a different value than emin . Therefore, since by Lemma C.4.10 emin sets L.ullo = ulloL , we have that L.ullo ̸= ulloL at e. However, by Proposi14 onwards L.ullo = ullo , a contradiction. tion C.4.7, from Tmin Lemma C.4.11 L

Proposition C.4.12. In Scenario C.4.5, consider any finite prefix I of I B at or after emin . The list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in I where Ieexclude is the prefix of I B min min min include B up to but excluding emin and Iemin is the prefix of I up to and including emin . Proof. By Lemma C.4.11 emin is the last L-event in I B and since I is a prefix of I B at or after emin , we have that emin is the last L-event in I. Since emin is the last L-event in I, and by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to either List(Ieexclude ) min or List(I) in I. Furthermore, since I is a prefix of I B at or after emin , emin is the last L-event in is the prefix of I B up to and including emin , it follows that the sequence of L-events I, and Ieinclude min is identical in I and Ieinclude , so by Definition C.1.7 List(I) = List(Ieinclude ). Therefore, the list of min min include ) in I as wanted. cells conforms to either List(Ieexclude ) or List(I Proposition C.4.12 emin min This completes the first part of the high-level argument for why pmin cannot take infinitely many steps in the loops on lines 30, 46, and 94 during opxmin . We now prove that in every iteration of Lmin , pmin “traverses” through a cell from one of these two finite lists (in particular, the response of every AcquireNext procedure is (Found, ptr) where ptr is in List(Ieexclude ) or List(Ieinclude )). min min Lemma C.4.13. In Scenario C.4.5, if a process read (ulloL , ptrL ) from L at time T in I B , then emin < T . Proof. Since a process read (ulloL , ptrL ) from L at time T , L.ullo is initially (0, Noop), and by Lemma C.4.9 ulloL ̸= (0, Noop), we have that some step set L to (ulloL , ptrL ) before T . Hence, by Observation C.1.6, some L-event e set L = (ulloL , ptrL ) before T . Therefore, by Lemma C.4.10, e = emin , and so emin < T as wanted. Lemma C.4.13 138

There are three claims that allow us to conclude that in every iteration of Lmin , pmin “traverses” through a cell from either List(Ieexclude ) or List(Ieinclude ). The first of which is Proposition C.4.16. min min Roughly speaking, Proposition C.4.16 asserts that if pmin tries to acquire a pointer after some ptr in List(Ieexclude ), then ptr is in List(Ieinclude ). This is useful for the following reason. Suppose min min exclude ptr is in List(Iemin ) but at the moment pmin reads (∗ptr).next.ptr on line 104, the list of cells conforms to List(Ieinclude ). If ptr is not in List(Ieinclude ), then the fact that the list of cells conforms min min include to List(Iemin ) tells us nothing about the value that pmin read from (∗ptr).next.ptr on line 104. Proposition C.4.16 lets us avoid this problem entirely because the fact that ptr is in List(Ieexclude ) min tells us that ptr is in List(Ieinclude ), and since by Proposition C.4.12 the list of cells conforms to min include ), we always know that the value that p List(Ieexclude ) or List(I min read from (∗ptr).next.ptr e min min include ). We now prove Proposition C.4.16. on line 104 comes from List(Ieexclude ) or List(I emin min Proposition C.4.14. In Scenario C.4.5, consider any invocation I of the DoAddCell, DoRemoveCell, or Acquire procedure and denote the time that I was invoked in I B by Tb . Let I1 , I2 , . . . be the (possibly infinite) sequence of invocations of the AcquireNext procedure during I in the order they are invoked.14 If for every finite prefix I of I B at or after Tb the list of cells conforms to List(Ieinclude ) in I, the second parameter of Ii is in List(Ieinclude ) for every i (assuming Ii exists). min min Proof. By induction on i. Base Case. i = 1. Hence, the second parameter of I1 is &H By Definition C.1.7, &H is the first element of List(I) ) is &H. Therefore, for every finite implementation history I, so the first element of List(Ieinclude min include the second parameter of Ii is in List(Iemin ) as wanted. Inductive Case. For every i ≥ 1 if the second parameter of Ii is in List(Ieinclude ), then the second min include parameter of Ii+1 is in List(Iemin ) (assuming Ii+1 exists). Suppose for some i ≥ 1 that the second parameter of Ii is in List(Ieinclude ). This is the inductive min hypothesis. Since Ii+1 exists, it follows that the response of Ii is (Found, ptri+1 ), and the second parameter of Ii+1 is ptri+1 . Let ptri be the second parameter of Ii , so by the inductive hypothesis, ). Furthermore, by Corollary C.1.89, ptri ∈ C ∪ {&H}. Hence, by Assumpptri is in List(Ieinclude min ), tion C.1.2 ptri ̸= Null, and so since by Definition C.1.7 Null is the last element of List(Ieinclude min we have that ptri is not the last element of List(Ieinclude ). Since (Found, ptr ) is the response of i+1 min Ii , we have that (∗curr ptri ).next.ptr = ptri+1 at the time of the last execution of line 104 during Ii ; say at time T 104 . Since T 104 is during Ii and Ii is during I, we have that T 104 is during I, and so T 104 is after Tb . Hence, there is a prefix of I B at or after Tb and up to and including T 104 ; say I 104 . Thus, since (∗ptri ).next.ptr = ptri+1 at T 104 , we have that (∗ptri ).next.ptr = ptri+1 at the end of I 104 . Therefore, since by assumption the list of cells conforms to List(Ieinclude ) in I 104 , ptri min include include is in List(Iemin ), ptri is not the last element of List(Iemin ), and (∗ptri ).next.ptr = ptri+1 at the end of I 104 , by Definition C.1.7, ptri+1 is in List(Ieinclude ) as wanted. Proposition C.4.14 min Lemma C.4.15. In Scenario C.4.5, suppose emin is an L-remove event for ptrL . Consider any invocation I of the AcquireNext procedure in I B such that the process which invoked I read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I. Then, the second parameter of I is not ptrL . 14 More precisely, if p is the process that invoked I, then I1 , I2 , . . . is the (possibly infinite) sequence of invocations of the AcquireNext procedure by p during I in the order they are invoked.

139

Proof. Suppose, for contradiction, that there is an invocation I of the AcquireNext procedure such that the process p which invoked I read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I and the second parameter of I is ptrL . Since emin is an L-remove event for ptrL , by Lemma C.1.28, ptrL ∈ C. Furthermore, since by Lemma C.4.10 emin set L = (ulloL , ptrL ), by Definition C.1.5, (ulloL , ptrL ) is of the form ((∗, RemoveCell), ptrL ). Hence, since p read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I, we have that p invoked I either during an invocation of the DoRemoveCell procedure on line 18 or during an invocation of the Acquire procedure on line 80. In the first case, it follows that p invoked I either: (1) during an invocation of the Acquire procedure during an invocation of the SetResponse procedure on line 44; or (2) on line 47. Therefore, I is invoked either: (1) during an invocation of the Acquire procedure during an invocation of the SetResponse procedure on line 44; (2) on line 47; or (3) during an invocation of the Acquire procedure on line 80. We consider each separately. Case 1. I was invoked during an invocation Iparent of the Acquire procedure during an invocation of the SetResponse procedure on line 44. Hence, since p read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I, it follows that the parameters of Iparent are (ulloL , ptrL ). Furthermore, since ptrL is the second parameter of I, it follows that ptrL is either &H or (Found, ptrL ) is the response of an invocation I ′ of the AcquireNext procedure on line 95 during Iparent such that I ′ exited before I was invoked. However, since ptrL ∈ C, by Assumption C.1.2, ptrL ̸= &H, so the latter is the only possibility. Hence, p executed line 94 between when I ′ exited and when I was invoked. Let T 99 and T 94 denote the next time p execute lines 99 and 94 after exiting I ′ during Iparent . Since the response of I ′ is (Found, ptrL ), p finds the condition on line 99 to be true at T 99 and so p sets its local variable curr ptr to ptrL on line 100. Hence, since the parameters of Iparent are (ulloL , ptrL ), we have that p finds the condition on line 94 to be false at T 94 . Therefore, p exits the loop on line 94 during Iparent , and so I ′ is the last invocation of the AcquireNext procedure during Iparent . However, since I is an invocation of the AcquireNext procedure during Iparent and I ′ exited before I was invoked, we have that there is an invocation of the AcquireNext procedure after I ′ during Iparent , a contradiction. Case 2. I was invoked on line 47. Let Iparent be the invocation of the DoRemoveCell procedure that p invoked I ′ during. Since p read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I, we have that the parameters of Iparent are (ulloL , ptrL ). Furthermore, since ptrL is the second parameter of I, it follows that ptrL is either &H or (Found, ptrL ) is the response of an invocation I ′ of the AcquireNext procedure on line 47 during Iparent such that I ′ exited before I was invoked. However, since ptrL ∈ C, by Assumption C.1.2, ptrL ̸= &H, so the latter is the only possibility. Hence, p executed line 46 between when I ′ exited and when I was invoked. Let T 48 and T 46 denote the next time p executes lines 48 and 46 after exiting I ′ during Iparent . Since the response of I ′ is (Found, ptrL ), p finds the condition on line 50 to be true at T 50 and so p sets its local variable curr ptr to ptrL on line 52. Hence, since the parameters of Iparent are (ulloL , ptrL ), we have that p finds the condition on line 46 to be false at T 46 . Therefore, p exits the while loop on line 46 during Iparent , and so I ′ is the last invocation of the AcquireNext procedure during Iparent . However, since I is an invocation of the AcquireNext procedure during Iparent and I ′ exited before I was invoked, we have that there is an invocation of the AcquireNext procedure after I ′ during Iparent , a contradiction. Case 3. I was invoked during an invocation Iparent of the Acquire procedure on line 80. Let T 14 be the time of p’s last execution of line 14 before invoking I. Since p read (ulloL , ptrL ) from L at T 14 , and (ulloL , ptrL ) is of the form ((∗, RemoveCell), ptrL ), we have that between T 14 140

and the time p invoked Iparent , p invoked and exited the DoRemoveCell on line 18 with parameters (ulloL , ptrL ). Denote this invocation by I ′ . Since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.15, there is a successful list-remove attempt for ptrL before I ′ exits in I B . Thus, since I ′ exits before Iparent is invoked, there is a successful list-remove attempt a for ptrL before Iparent is invoked. We first prove that emin < a. Since a is a successful list-remove for ptrL , by Corollary C.1.37, there is an L-remove event e for ptrL before a. Hence, since by Lemma C.2.30 P (I B ) holds, we have that e is the only L-remove event for ptrL in I B . Therefore, since emin is an L-remove event for ptrL , we have that e = emin , and so emin < a as wanted. We now prove that for every prefix I of I B at or after a, the list of cells conforms to List(Ieinclude ) min in I. Since emin < a, we have that I is a prefix of I B at or after emin . Thus, since by Lemma C.4.11 emin is the last L-event in I B , it follows that emin is also the last L-event in I. Hence, since emin < a and a is a successful list-remove attempt, we have that there is a successful list-remove attempt after the last L-event in I. Thus, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I) in I. Since I is a prefix of I B at or after emin , emin is the last L-event in I, and Ieinclude is the prefix of I B up to and including emin , min it follows that the sequence of L-events is identical in I and Ieinclude . Thus, by Definition C.1.5 min include ) in I. List(I) = List(Ieinclude ). Therefore, the list of cells conforms to List(I emin min We now finish the proof of Case 3. Since a is before Iparent is invoked and for every prefix I of I B at or after a, the list of cells conforms to List(Ieinclude ) in I, we have that for every prefix I of min I B at or after the time Iparent is invoked, the list of cells conforms to List(Ieinclude ) in I. Hence, min include by Proposition C.4.14, the second parameter of I is in List(Iemin ). Therefore, since the second parameter of I is ptrL , we have that ptrL is in List(Ieinclude ). However, since emin is an L-remove min B up to and including e is the prefix of I event for ptrL and Ieinclude min , by Definition C.1.7, we have min include that ptrL is not in List(Iemin ), a contradiction. Lemma C.4.15 Proposition C.4.16. In Scenario C.4.5, consider any invocation I of the DoAddCell, DoRemoveCell, or Acquire procedure in I B such that the process which invoked I read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I. Let I1 , I2 , . . . be the (possibly infinite) sequence of invocations of the AcquireNext procedure during I in the order they are invoked, and let ptri denote the second parameter of Ii . If ptri is in List(Ieexclude ), ptri is in List(Ieinclude ) (assuming Ii min min exists). Proof. Suppose, for contradiction, that ptri is in List(Ieexclude ) and ptri is not in List(Ieinclude ). min min Hence, since by Lemma C.1.29 emin is either an L-add, L-apply, or L-remove event, and the sequence of L-events in Ieexclude and Ieinclude are the same except the former excludes emin and the min min latter includes it, by Definition C.1.7, the only way that this is possible is if emin is an L-remove event for ptri . Thus, since by Lemma C.4.10 emin is an L-event for ptrL , we have that ptri = ptrL , so emin is an L-remove event for ptrL . Therefore, since p read (ulloL , ptrL ) from L on its last execution of line 14 before invoking Ii , by Lemma C.4.15, the second parameter of Ii is not ptrL . However, the second parameter of Ii is ptri = ptrL , a contradiction. Proposition C.4.16 We now prove the other two claims that allow us to conclude that in every iteration of Lmin , pmin “traverses” through a cell from either List(Ieexclude ) or List(Ieinclude ). The first of which is min min Proposition C.4.17, which, roughly speaking, asserts that if pmin tries to acquire a pointer after some ptr not in List(Ieexclude ), then the list of cells does not conform to List(Ieexclude ) beforehand. The min min second is Lemma C.4.18, which, roughly speaking, asserts that if the list of cells does not conform to List(Ieexclude ), then the list of cells conforms to List(Ieinclude ) from then onwards. These two min min 141

facts together let us conclude that if ptr is not in List(Ieexclude ) then the list of cells conforms to min include List(Iemin ) at the time pmin tries to acquire the pointer after ptr. Proposition C.4.17. In Scenario C.4.5, consider any invocation I of the DoAddCell, DoRemoveCell, or Acquire procedure in I B such that the process which invoked I read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I. Let I1 , I2 , . . . be the (possibly infinite) sequence of invocations of the AcquireNext procedure during I in the order they are invoked, and let ptri denote the second parameter of Ii . If ptri is not in List(Ieexclude ), then there is a finite prefix I of min I B after emin and before Ii was invoked where the list of cells does not conform to List(Ieexclude ) min in I (assuming Ii exists). Proof. By induction on i. Base Case. i = 1. Suppose I1 exists. By definition, there are no invocations of the AcquireNext procedure during I before I1 . Hence, the second parameter of I1 is &H and so ptr1 = &H. By Definition C.1.7, &H is the first element of List(I) for every finite implementation history I. Hence, the first element of List(Ieexclude ) is &H, and so ptr1 is in List(Ieexclude ). Therefore, the claim is vacuously true. min min Inductive Case. For every i ≥ 1 if the claim holds for Ii , then the claim holds for Ii+1 (assuming Ii+1 exists). Suppose for some i ≥ 1 if ptri is not in List(Ieexclude ), then there is a prefix I of I B after emin min and before Ii was invoked where the list of cells does not conform to List(Ieexclude ) in I. This is min exclude the inductive hypothesis. Suppose, for contradiction, ptri+1 is not in List(Iemin ) and for every prefix I of I B after emin and before Ii+1 was invoked the list of cells conforms to List(Ieexclude ) min in I. Since Ii is the invocation of the AcquireNext procedure which proceeded Ii+1 during I, it follows that (Found, ptri+1 ) is the response of Ii . Let p be the process that invoked I and let Tp14 be the last time p executed line 14 before invoking I. Since p read (ulloL , ptrL ) from L at Tp14 , by Lemma C.4.13, emin < Tp14 . Since ptri is the second parameter of Ii , by Corollary C.1.89, ptri ∈ C ∪ {&H}, and so by Assumption C.1.2 ptri ̸= Null. Furthermore, since (Found, ptri+1 ) is the response of Ii , it follows that p read ptri+1 from (∗ptri ).next.ptr on p’s final execution of line 104 during Ii ; say at time Ti104 . Since emin < Tp14 , Tp14 is p’s last execution of line 14 before invoking I, Ii is invoked during I, and Ti104 is during Ii , by transitivity, emin < Ti104 . Hence, there is a prefix Ii of I B after emin that ends at time Ti104 . Thus, since (∗ptri ).next.ptr = ptri+1 at Ti104 , it follows that (∗ptri ).next.ptr = ptri+1 at the end of Ii . There are two cases. Case 1. ptri is in List(Ieexclude ). min 104 Since Ti is during Ii , and Ii exits before Ii+1 was invoked, by transitivity, Ti104 is before Ii+1 was invoked. Hence, since Ii is a prefix of I B after emin up to Ti104 , we have that Ii is a prefix of I B after emin and before Ii+1 . Thus, the list of cells conforms to List(Ieexclude ) in Ii . Therefore, min exclude since ptri ̸= Null, ptri is in List(Iemin ), and (∗ptri ).next.ptr = ptri+1 at the end of Ii , by Definition C.1.7, ptri+1 is in List(Ieexclude ). However, ptri+1 is not in List(Ieexclude ), a contradiction. min min Case 2. ptri is not in List(Ieexclude ). min Hence, by the inductive hypothesis, we have that there is a prefix I of I B after emin and before Ii was invoked where the list of cells does not conform to List(Ieexclude ) in I. Therefore, since Ii is before min Ii+1 , we have that there is a prefix I of I B after emin and before Ii+1 was invoked where the list of cells does not conform to List(Ieexclude ) in I. However, for every prefix I of I B after emin and before min Ii+1 was invoked the list of cells conforms to List(Ieexclude ) in I, a contradiction. Proposition C.4.17 min 142

Lemma C.4.18. In Scenario C.4.5, if there is a finite prefix I of I B at or after emin where the list of cells does not conform to List(Ieexclude ) in I, then for every finite prefix I ′ of I B such that I is min ′ a prefix of I we have that the list of cells conforms to List(Ieinclude ) in I ′ . min Proof. Suppose, that there is a prefix I of I B at or after emin where the list of cells does not conform to List(Ieexclude ) in I. Since by Lemma C.4.11 emin is the last L-event in I B and, I is a prefix of min B I at or after emin , we have that emin is the last L-event in I. We first prove that there is a successful list-add or list-remove attempt after emin in I (*). Suppose, for contradiction, there is not a successful list-add or list-remove attempt after emin in I. Hence, we have that (1) there is an L-event in I; (2) emin is the last L-event in I; and (3) from emin onwards in I there are no successful list-add or list-remove attempts. Therefore, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(Ieexclude ) in I. However, the list of cells does not conform to List(Ieexclude ) in I, a contradiction. min min Consider any prefix I ′ of I B such that I is a prefix of I ′ . Hence, I ′ is a prefix of I B at or after emin . Thus, since emin is the last L-event in I, we have that emin is the last L-event in I ′ . Since by (*) there is a successful list-add or list-remove attempt after emin in I, and I is a prefix of I ′ , there is a successful list-add or list-remove attempt after emin in I ′ . Hence, we have that (1) there is an L-event in I ′ ; (2) emin is the last L-event in I ′ ; and (3) there is a successful list-add or list-remove attempt after emin in I ′ . Thus, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I ′ ) in I ′ . So, since Ieinclude is the prefix of I B min up to and including emin , and emin is the last L-event in I ′ , it follows that the sequence of L-events is identical in I ′ and Ieinclude . Therefore, by Definition C.1.7, List(I ′ ) = List(Ieinclude ), and so the min min include ′ list of cells conforms to List(Iemin ) in I as wanted. Lemma C.4.18 We now complete the proof of every iteration of Lmin , pmin “traverses” through a cell from either List(Ieexclude ) or List(Ieinclude ). min min Lemma C.4.19. In Scenario C.4.5, consider any invocation I of the DoAddCell, DoRemoveCell, or Acquire procedure in I B such that the process which invoked I read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I. Let I1 , I2 , . . . be the (possibly infinite) sequence of invocations of the AcquireNext procedure during I in the order they are invoked, and let ptri ) (assuming Ii ) or List(Ieinclude denote the second parameter of Ii . ptri is in either List(Ieexclude min min exists). Proof. By induction on i. Base Case. i = 1. Suppose I1 exists. By definition, there are no invocations of the AcquireNext procedure during I before I1 . Hence, the second parameter of I1 is &H and so ptr1 = &H. By Definition C.1.7, &H is the first element of List(I) for every finite implementation history I. Hence, the first element of List(Ieexclude ) is &H, and so ptr1 is in List(Ieexclude ). Therefore, the claim follows. min min Inductive Case. For every i ≥ 1 if ptri is in either List(Ieexclude ) or List(Ieinclude ), then ptri+1 is min min exclude include in either List(Iemin ) or List(Iemin ) (assuming Ii+1 exists). Suppose for some i ≥ 1 that ptri is in either List(Ieexclude ) or List(Ieinclude ). This is the inductive min min hypothesis. Suppose Ii+1 exists. The setup is identical to Proposition C.4.17, which we repeat for completeness below. Since Ii is the invocation of the AcquireNext procedure which proceeded Ii+1 during I, it follows that (Found, ptri+1 ) is the response of Ii . Let p be the process that invoked I and let Tp14 be the last time p executed line 14 before invoking I. Since p read (ulloL , ptrL ) from L 143

at Tp14 , by Lemma C.4.13, emin < Tp14 . Since ptri is the second parameter of Ii , by Corollary C.1.89, ptri ∈ C ∪ {&H}, and so by Assumption C.1.2 ptri ̸= Null. Furthermore, since (Found, ptri+1 ) is the response of Ii , it follows that p read ptri+1 from (∗ptri ).next.ptr on p’s final execution of line 104 during Ii ; say at time Ti104 . Since emin < Tp14 , Tp14 is p’s last execution of line 14 before invoking I, Ii is invoked during I, and Ti104 is during Ii , by transitivity, emin < Ti104 . Hence, there is a prefix Ii of I B after emin that ends at time Ti104 . Thus, since (∗ptri ).next.ptr = ptri+1 at Ti104 , it follows that (∗ptri ).next.ptr = ptri+1 at the end of Ii . There are two cases. Case 1. ptri is in List(Ieexclude ). min B Since Ii is a prefix of I after emin , by Proposition C.4.12, the list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in Ii . Furthermore, since ptri is in List(Ieexclude ), by Proposimin min min include exclude include tion C.4.16, ptri is in List(Iemin ), and so ptri is in both List(Iemin ) and List(Iemin ). Hence, since ptri ̸= Null, and (∗ptri ).next.ptr = ptri at the end of Ii , by Definition C.1.7, ptri is in either List(Ieexclude ) or List(Ieinclude ). Therefore, the claim follows. min min Case 2. ptri is not in List(Ieexclude ). min Hence, by the inductive hypothesis, ptri is in List(Ieinclude ). Furthermore, by Proposition C.4.17, min there is a prefix I of I B after emin and before Ii was invoked where the list of cells does not conform to List(Ieexclude ) in I. Since the end of I is before Ii is invoked and the end of Ii is after Ii is invoked, min ) we have that I is a prefix of Ii . Hence, by Lemma C.4.18, the list of cells conforms to List(Ieinclude min in Ii . Thus, since ptri ̸= Null, ptri is in List(Ieinclude ), and (∗ptr ).next.ptr = ptr at the end of i i min Ii , by Definition C.1.7, ptri is in List(Ieinclude ). Therefore, the claim follows. Lemma C.4.19 min This completes the second part of the high-level argument for why pmin cannot take infinitely many steps in the loops on lines 30, 46, and 94 during opxmin . We now prove the third and final part: that the pointers pmin traverses through are distinct. Lemma C.4.20. In Scenario C.4.5, consider any invocation I of the DoAddCell, DoRemoveCell, or Acquire procedure in I B such that the process which invoked I read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I. Let I1 , I2 , . . . be the (possibly infinite) sequence of invocations of the AcquireNext procedure during I in the order they were invoked, and let ptri denote the second parameter of Ii . Then, for every i and j such that i ̸= j, ptri ̸= ptrj (assuming Ii and Ij exist). Proof. Suppose, for contradiction, there is Ii and Ij such that i ̸= j and ptri = ptrj . Without loss of generality suppose i < j and j is the first non-distinct pointer, i.e., for all k, l ∈ [1..j) if k ̸= l, then ptrk ̸= ptrl . Let p be the process that invoked I and let Tp14 be the last time p executed line 14 before invoking I. Since p read (ulloL , ptrL ) from L at Tp14 , by Lemma C.4.13, emin < Tp14 . Since 1 ≤ i and i < j, by transitivity 1 < j, and so 1 ≤ j − 1. Hence, Ij−1 is well-defined. Since ptrj−1 is the second parameter of Ij−1 , by Corollary C.1.89, ptrj−1 ∈ C ∪ {&H}, and so by Assumption C.1.2 ptrj−1 ̸= Null. Furthermore, since Ij−1 is the invocation of the AcquireNext procedure preceding Ij during I, we have that (Found, ptrj ) is the response of Ij−1 . Hence, since ptrj−1 is the second 104 , p read ptr from parameter of Ij−1 , on p’s last execution of line 104 during Ij−1 , say at time Tj−1 j (∗ptrj−1 ).next.ptr. Claim C.4.20.1. i > 1 and so Ii−1 is well-defined. Proof. Suppose, for contradiction, i = 1. Hence, I1 is the first invocation of the AcquireNext procedure during I, and so there are no invocations of the AcquireNext procedure before I1 during I. Thus, the second parameter of I1 is &H and so ptr1 = &H. Hence, since i = 1 and ptri = 144

104 , it follows that ptrj , we have that ptrj = &H. Thus, since (∗ptrj−1 ).next.ptr = ptrj at Tj−1 104 . Therefore, since by Corollary C.1.89 ptr (∗ptrj−1 ).next.ptr = &H at Tj−1 j−1 ∈ C ∪ {&H}, by Lemma C.1.47, &H ∈ C ∪ {Null}. However, by Assumption C.1.2 &H ∈ / C and &H ̸= Null, a contradiction. Therefore, Ii−1 is well-defined as wanted. Claim C.4.20.1

Since ptri−1 is the second parameter of Ii−1 , by Corollary C.1.89, ptri−1 ∈ C ∪ {&H}, and so by Assumption C.1.2 ptri−1 ̸= Null. Furthermore, since Ii−1 is the invocation of the AcquireNext procedure preceding Ii during I, we have that the response of Ii−1 is (Found, ptri ). Hence, since ptri−1 is the second parameter of Ii−1 , on p’s last execution of line 104 during Ii−1 , say at time 104 , p read ptr from (∗ptr 14 14 Ti−1 i i−1 ).next.ptr. Since emin < Tp , Tp is before p invoked I, Ii−1 (resp. 104 104 Ij−1 ) is invoked during I, and Ti−1 (resp. Tj−1 ) is during Ij−1 (resp. Ii−1 ), by transitivity, 104 (resp. e 104 we have that emin < Ti−1 min < Tj−1 ). Hence, there is a prefix Ii−1 (resp. Ij−1 ) of 104 (resp. T 104 ). Therefore, since p read ptr I B at or after emin and up to and including Ti−1 i j−1 104 (resp. T 104 ), we have that (resp. ptrj ) from (∗ptri−1 ).next.ptr (resp. (∗ptrj−1 ).next.ptr) at Ti−1 j−1 (∗ptri−1 ).next.ptr = ptri (resp. (∗ptrj−1 ).next.ptr = ptrj ) at the end of Ii−1 (resp. Ij−1 ) (*). We now perform a case reduction to simplify the finale. Claim C.4.20.2. One of the following three scenarios must occur. (1) ptri−1 and ptrj−1 are both in List(Ieexclude ) and the list of cells conforms to List(Ieexclude ) in min min both Ii−1 and Ij−1 , (2) ptri−1 and ptrj−1 are both in List(Ieinclude ) and the list of cells conforms to List(Ieinclude ) in min min both Ii−1 and Ij−1 , and ) ), the list of cells conforms to List(Ieexclude ), ptrj−1 is in List(Ieinclude (3) ptri−1 is in List(Ieexclude min min min include in Ii−1 , and the list of cells conforms to List(Iemin ) in Ij−1 . Proof. There are four cases. Case 1. ptri−1 and ptrj−1 are both in List(Ieexclude ). min Since Ii−1 (resp. Ij−1 ) is a prefix of I B at or after emin , by Proposition C.4.12, the list of cells conforms to either List(Ieexclude ) or List(Ieinclude ) in Ii−1 (resp. Ij−1 ). We consider each combination. min min Case 1.1. the list of cells conforms to List(Ieexclude ) in both Ii−1 and Ij−1 . min exclude Hence, since ptri−1 and ptrj−1 are both in List(Iemin ) (1) is satisfied. Case 1.2. the list of cells conforms to List(Ieinclude ) in both Ii−1 and Ij−1 . min exclude Since ptri−1 and ptrj−1 are both in List(Iemin ), by Proposition C.4.16, ptri−1 and ptrj−1 are both in List(Ieinclude ). Therefore, (2) is satisfied. min Case 1.3. the list of cells conforms to List(Ieexclude ) in Ii−1 and the list of cells conforms to min List(Ieinclude ) in I . j−1 min Since ptrj−1 is in List(Ieexclude ), by Proposition C.4.16, ptrj−1 is in List(Ieinclude ). Therefore, since min min exclude ptri−1 is in List(Iemin ), ptrj−1 is in List(Ieinclude ), the list of cells conforms to List(Ieexclude ) in min min include Ii−1 , and the list of cells conforms to List(Iemin ) in Ij−1 , (3) is satisfied. Case 1.4. the list of cells conforms to List(Ieinclude ) in Ii−1 and the list of cells conforms to min exclude List(Iemin ) in Ij−1 . It suffices to assume that the list of cells does not conform to List(Ieexclude ) in Ii−1 , as otherwise, min this case reduces to Case 1.1. Since i − 1 < j − 1, we have that Ii−1 exits before Ij−1 is invoked. 104 is during I 104 104 104 Hence, since Ti−1 i−1 and Tj−1 is during Ij−1 , we have that Ti−1 < Tj−1 . Thus, since Ii−1 104 , and I B 104 is the prefix of I B up to and including Ti−1 j−1 is the prefix of I up to and including Tj−1 , it 145

follows that Ii−1 is a prefix of Ij−1 . Thus, since the list of cells does not conform to List(Ieexclude ) min B in Ii−1 , and Ij−1 is the prefix of I such that Ii−1 is a prefix of Ij−1 , by Lemma C.4.18, the list of cells conforms to List(Ieinclude ) in Ij−1 . So, the list of cells conforms to List(Ieinclude ) in both min min Ii−1 and Ij−1 . Since ptri−1 and ptrj−1 are both in List(Ieexclude ), by Proposition C.4.16, ptri−1 min include and ptrj−1 are both in List(Iemin ). Therefore, (2) is satisfied. Case 2. ptri−1 is not in List(Ieexclude ) and ptrj−1 is in List(Ieexclude ). min min Hence, by Lemma C.4.19, ptri−1 is in List(Ieinclude ), and by Proposition C.4.16, ptrj−1 is in min include ). Furthermore, by Proposition C.4.17 List(Ieinclude ), so ptr and ptr are both in List(I i−1 j−1 emin min there is a prefix I of I B after emin and before Ii−1 was invoked such that the list of cells does not conform to List(Ieexclude ) in I. Since the end of I is before Ii−1 is invoked and the end of Ii−1 min (resp. Ij−1 ) is after Ii−1 was invoked (the end of Ii−1 is during Ii−1 and i − 1 < j − 1 implies Ij−1 is a prefix of Ii−1 ), we have that I is a prefix of Ii−1 (resp. Ij−1 ). Hence, by Lemma C.4.18, the list of cells conforms to List(Ieinclude ) in Ii−1 (resp. Ij−1 ). Therefore, (2) is satisfied. min Case 3. ptri−1 is in List(Ieexclude ) and ptrj−1 is not in List(Ieexclude ). min min ), and by Proposition C.4.16, ptri−1 is in Hence, by Lemma C.4.19, ptrj−1 is in List(Ieinclude min include List(Iemin ), so ptri−1 and ptrj−1 are both in List(Ieinclude ). Furthermore, by Proposition C.4.17 min there is a prefix I of I B after emin and before Ij−1 was invoked such that the list of cells does not conform to List(Ieexclude ) in I. Since the end of I is before Ij−1 is invoked and the end of min Ij−1 is after Ij−1 was invoked, we have that I is a prefix of Ij−1 . Hence, by Proposition C.4.12, ) in Ij−1 . Since Ii−1 is a prefix of I B at or after emin , the list of cells conforms to List(Ieinclude min ) in Ii−1 . ) or List(Ieinclude by Proposition C.4.12, the list of cells conforms to either List(Ieexclude min min exclude Suppose the list of cells conforms to List(Iemin ) in Ii−1 . Therefore, ptri−1 is in List(Ieexclude ), min exclude ) in I ptrj−1 is in List(Ieinclude ), the list of cells conforms to List(I , and the list of cells i−1 emin min conforms to List(Ieinclude ) in I , and so (3) is satisfied. Now suppose the list of cells conforms to j−1 min include ) in I List(Ieinclude ) in I . Hence, the list of cells conforms to List(I i−1 i−1 and Ij−1 . Therefore, emin min include since ptri−1 and ptrj−1 are both in List(Iemin ), (2) is satisfied. Case 4. ptri−1 and ptrj−1 are both not in List(Ieexclude ). min Hence, by Lemma C.4.19, ptri−1 and ptrj−1 are both in List(Ieinclude ), and by Proposition C.4.17 min there is a prefix I of I B at or after emin and before Ii−1 was invoked such that the list of cells does not conform to List(Ieexclude ) in I. Since the end of I is before Ii−1 is invoked and the end of Ii−1 min (resp. Ij−1 ) is after Ii−1 was invoked, we have that I is a prefix of Ii−1 (resp. Ij−1 ). Hence, by Proposition C.4.12, the list of cells conforms to List(Ieinclude ) in Ii−1 (resp. Ij−1 ). Therefore, (2) min is satisfied. Claim C.4.20.2 We now finish the proof of Lemma C.4.20. We first note that, since Ieexclude and Ieinclude are min min B exclude finite, and by Lemma C.2.30 P (I ) holds, by Lemma C.1.114, the values in List(Iemin ) and List(Ieinclude ) are unique. By Claim C.4.20.2, there are three cases. min Case 1. ptri−1 and ptrj−1 are both in List(Ieexclude ) and the list of cells conforms to List(Ieexclude ) min min in both Ii−1 and Ij−1 . Hence, since ptri−1 ̸= Null, ptrj−1 ̸= Null, (∗ptri−1 ).next.ptr = ptri at the end of Ii−1 , and (∗ptrj−1 ).next.ptr = ptrj at the end of Ij−1 , by Definition C.1.7, ptri and ptrj are the pointers after ptri−1 and ptrj−1 in List(Ieexclude ), respectively. Let ptri−1 and ptrj−1 be the kth and lth min exclude pointers in List(Iemin ), respectively. Hence, ptri and ptrj are the k + 1th and l + 1th pointers in List(Ieexclude ), respectively. min 146

We prove that k = l. Suppose, for contradiction, k ̸= l. Hence, k + 1 ̸= l + 1. Thus, since ptri and ptrj are the k + 1th and l + 1th pointers in List(Ieexclude ), we have that ptri ̸= ptrj . However, by min our initial assumption ptri = ptrj , a contradiction. Since ptri−1 and ptrj−1 are the kth and lth pointers in List(Ieexclude ), respectively, and k = l, we min have that ptri−1 = ptrj−1 . Therefore, since 1 < i < j, we have that i − 1 and j − 1 are in [1..j), i − 1 ̸= j − 1, and ptri−1 = ptrj−1 . However, this contradicts the minimality of j. Case 2. ptri−1 and ptrj−1 are both in List(Ieinclude ) and the list of cells conforms to List(Ieinclude ) min min in both Ii−1 and Ij−1 . Hence, since ptri−1 ̸= Null, ptrj−1 ̸= Null, (∗ptri−1 ).next.ptr = ptri at the end of Ii−1 , and (∗ptrj−1 ).next.ptr = ptrj at the end of Ij−1 , by Definition C.1.7, ptri and ptrj are the pointers after ptri−1 and ptrj−1 in List(Ieinclude ), respectively. Let ptri−1 and ptrj−1 be the kth and lth min include pointers in List(Iemin ), respectively. Hence, ptri and ptrj are the k + 1th and l + 1th pointers in List(Ieinclude ), respectively. min We prove that k = l. Suppose, for contradiction, k ̸= l. Hence, k + 1 ̸= l + 1. Thus, since ptri and ptrj are the k + 1th and l + 1th pointers in List(Ieinclude ), we have that ptri ̸= ptrj . However, by min our initial assumption ptri = ptrj , a contradiction. Since ptri−1 and ptrj−1 are the kth and lth pointers in List(Ieinclude ), respectively, and k = l, we min have that ptri−1 = ptrj−1 . Therefore, since 1 < i < j, we have that i − 1 and j − 1 are in [1..j), i − 1 ̸= j − 1, and ptri−1 = ptrj−1 . However, this contradicts the minimality of j. Case 3. ptri−1 is in List(Ieexclude ), ptrj−1 is in List(Ieinclude ), the list of cells conforms to min min exclude List(Iemin ) in Ii−1 , and the list of cells conforms to List(Ieinclude ) in Ij−1 . min Hence, since ptri−1 ̸= Null, ptrj−1 ̸= Null, (∗ptri−1 ).next.ptr = ptri at the end of Ii−1 , and (∗ptrj−1 ).next.ptr = ptrj at the end of Ij−1 , by Definition C.1.7, ptri is the pointer after ptri−1 in List(Ieexclude ), and ptrj is the pointer after ptrj−1 in List(Ieinclude ). Since ptri−1 and ptri are both min min exclude in List(Iemin ), by Proposition C.4.16, ptri−1 and ptri are both in List(Ieinclude ). min We first prove that ptri is the pointer after ptri−1 in List(Ieinclude ). Suppose, for contradiction, ptri min include is not the pointer after ptri−1 in List(Iemin ). Since ptri−1 ̸= Null and ptri−1 is in List(Ieinclude ), min by Definition C.1.7, there is a pointer after ptri−1 in List(Ieinclude ); say ptr. Since ptr is the pointer i min include ), and by definition I exclude after ptri−1 in List(Ieexclude ), ptr and ptr are both in List(I i−1 i e emin min min contains every L-event in Ieinclude with the exception of e , by Definition C.1.7, e is an Lmin min min add event for ptr. Hence, since ptr is after ptri−1 in List(Ieinclude ), by Definition C.1.7, ptr i−1 min is the third last element in List(Ieinclude ). Thus, since e is an L-add event for ptr, it follows min min that ptri−1 is the second last element in List(Ieexclude ). Therefore, since ptri is the pointer after min ptri−1 in List(Ieexclude ), by Definition C.1.7, ptr = Null. However, since by Corollary C.1.89 i min ptri ∈ C ∪ {&H}, by Assumption C.1.2, ptri ̸= Null, a contradiction. Let ptri−1 and ptrj−1 be the kth and lth pointers in List(Ieinclude ), respectively. Hence, since ptri min include and ptrj are the pointers after ptri−1 and ptrj−1 in List(Iemin ), respectively, we have that ptri and ptrj are the k + 1th and l + 1th pointers in List(Ieinclude ), respectively. min We prove that k = l. Suppose, for contradiction, k ̸= l. Hence, k + 1 ̸= l + 1. Thus, since ptri and ptrj are the k + 1th and l + 1th pointers in List(Ieinclude ), we have that ptri ̸= ptrj . However, by min our initial assumption ptri = ptrj , a contradiction. Since ptri−1 and ptrj−1 are the kth and lth pointers in List(Ieinclude ), respectively, and k = l, we min have that ptri−1 = ptrj−1 . Therefore, since 1 < i < j, we have that i − 1 and j − 1 are in [1..j), i − 1 ̸= j − 1, and ptri−1 = ptrj−1 . However, this contradicts the minimality of j. Lemma C.4.20 147

This completes the third part of the high-level argument for why pmin cannot take infinitely many steps in the loops on lines 30, 46, and 94 during opxmin . We are now ready to prove the main claim of this section. Lemma C.4.21. Lmin is not a loop on line 30, 46, or 94. Proof. Suppose, for contradiction, Lmin is a loop on either line 30, 46, or 94. Hence, Lmin is not a loop on line 13. Thus, this is Scenario C.4.5. Since Lmin is a loop on either line 30, 46, or 94, we have that Imin is an invocation of the DoAddCell, DoRemoveCell, or Acquire procedure. Since pmin takes infinitely many steps inside Lmin , we have that p invokes infinitely many invocations of the AcquireNext procedure during Imin . Let I1 , I2 , . . . denote these invocations of the AcquireNext procedure during Imin in the order they were invoked and let ptri denote the second parameter of Ii . Since Ieexclude and Ieinclude are finite, by Definition C.1.7, List(Ieexclude ) and List(Ieinclude ) min min min min exclude include are finite, and so the union of List(Iemin ) and List(Iemin ) is finite. Therefore, since pmin read (ulloL , ptrL ) from L on its last execution of line 14 before invoking Imin , by Lemma C.4.19, ptri is in either List(Ieexclude ) or List(Ieinclude ), and so {ptri | ∀i} is finite. However, by Lemma C.4.20, min min ptr1 , ptr2 , . . . are distinct so {ptri | ∀i} is infinite, a contradiction. Lemma C.4.21 C.4.2

Processes cannot get stuck in the loops on lines 53, 57, and 103.

This section shows that pmin cannot take infinitely many steps in the loops on lines 53, 57, and 103 during opxmin . The high-level argument for why is the following. First, we prove that the value of the next object of some cell changes infinitely often in I B . Second, we prove that the next object of each cell changes finitely many times in I B . The first property follows from the fact that each of these loops repeatedly performs a CAS operation on some pointer, and once a single one of these CAS operations is successful, pmin exits the loop, as we will soon show. The main technical difficulty is that some of these CAS operations (in particular, those on line 61 and line 109) have fixed values in their first parameter. So, to deduce that an unsuccessful CAS operation implies the value changed, we have to show these fixed values are actually the value of the object at the time pmin when it was read. We start with two basic facts and then prove this. Proposition C.4.22. In Scenario C.4.5, suppose Lmin is the loop on line 57. So, Imin is an invocation of the DoRemoveCell procedure. Let ptr be the value of the pmin ’s local variable prev ptr during Lmin . Then, there is an invocation of the AcquireNext procedure on line 47 during Imin whose second parameter is ptr. Proof. Since (ulloL , ptrL ) was read from L on pmin ’s last execution of line 14 before invoking Imin , we have that (ulloL , ptrL ) are the parameters of Imin . Hence, by Corollary C.1.37, there is an Lremove event for ptrL , and so by Lemma C.1.28 ptrL ∈ C. Thus, by Assumption C.1.2 ptrL ̸= &H, and so the first time pmin executes line 46 during Imin it finds the condition on line 46 to be true. Since Lmin is the loop on line 57 during Imin , we have that pmin exits the loop on line 46 during Imin by finding the condition on line 46 to be false. Thus, since the first time pmin executes line 46 during Imin it finds the condition on line 46 to be true, we have that pmin executes line 46 at least twice and at most finitely many times during Imin . Suppose pmin executes line 46 exactly n ≥ 2 times during Imin . Since pmin exits the loop on line 46 during Imin by finding the condition on line 46 to be false, and pmin executes line 46 exactly n times during Imin , we have that pmin finds the condition on line 46 to be false on pmin ’s nth execution of line 46 during Imin . Let prev ptri and curr ptri be the values of pmin ’s local variables prev ptr and curr ptr, respectively, at the time of pmin ’s ith execution of line 46 during Imin where i ∈ [1..n]. Since n ≥ 2, pmin executes line 46 n − 1 times during Imin , and between pmin ’s n − 1th and nth execution of line 46 during Imin , 148

pmin invokes the AcquireNext procedure on line 47. Denote this invocation by In−1 . Since In−1 is invoked just after pmin ’s n − 1th execution of line 46, its second parameter is curr ptrn−1 . Let status be the left field of In−1 ’s response. By the AcquireNext procedure status is either Found, L-Changed, or NotFound. Suppose status is L-Changed or NotFound. Hence, pmin would find the condition on line 48 to be true after exiting In−1 , and so pmin would execute the goto on line 49. Thus, pmin would not execute line 46 for an nth time during Imin , which is impossible, so status is Found. Hence, after exiting In−1 , pmin executes line 52. Since prev ptr and curr ptr are the same at this time as they were when pmin executes line 46 for the n − 1th time during Imin , we have that pmin sets prev ptr = curr ptrn−1 . Therefore, since prev ptr is unchanged from this time until pmin line 46 for the nth time during Imin , we have that prev ptrn = curr ptrn−1 . Since pmin finds the condition on line 46 to be false on pmin ’s nth execution of line 46 during Imin , we have that pmin ’s local variable prev ptr = curr ptrn−1 from the time pmin exits the loop on line 46 during Imin onwards in Imin . Hence, since ptr is the value of the local variable prev ptr in Lmin , we have that ptr = curr ptrn−1 . Therefore, since In−1 is an invocation of the AcquireNext procedure during Imin whose second parameter is curr ptrn−1 , the claim follows. Proposition C.4.22 Proposition C.4.23. In Scenario C.4.5, suppose Lmin is either the loop on line 53 (Case A), 57 (Case B), or 103 (Case C). Let ptr be the value of the local variable ptrL (Case A), prev ptr (Case B), or curr ptr (Case C) in Lmin . Then, ptr ∈ C ∪ {&H}. Proof. We consider each case separately. Case A. Hence, Imin is an invocation of the DoRemoveCell procedure, and the second parameter of Imin is ptr. Thus, by Corollary C.1.37, there is an L-event for ptr. Therefore, by Lemma C.1.28 ptr ∈ C. Case B. By Proposition C.4.22, the second parameter of an invocation of the AcquireNext procedure is ptr. Hence, by Corollary C.1.89, we have that ptr ∈ C ∪ {&H}. Case C. Since ptr is the the second parameter of an invocation of the AcquireNext procedure, by Corollary C.1.89, we have that ptr ∈ C ∪ {&H}. Proposition C.4.23 We now prove that pmin correctly fixes a value of False for the sealed field on line 61 and 109. Proposition C.4.24. In Scenario C.4.5, suppose Lmin is the loop on line 57 (Case A), or 103 (Case B). Let ptr be the value of the local variable prev ptr (Case A), or curr ptr (Case B) in Lmin . By Proposition C.4.23 ptr ∈ C ∪ {&H}. Then, (∗ptr).next.sealed = False throughout I B . Proof. The proof is done in two cases. First suppose that emin is an L-remove event for ptr. Hence, since by Lemma C.4.10 emin is an L-event for ptrL , we have that ptr = ptrL and emin is an Lremove event for ptrL . We define an invocation I of the AcquireNext procedure whose second parameter is ptr. In Case A, let I be the invocation of the AcquireNext procedure identified by Proposition C.4.22. In Case B, let Imin be the invocation. Hence, since ptr = ptrL , we have that the second parameter of I is ptrL . In Case A, I is invoked during Imin , and so since p read (ulloL , ptrL ) from L on its last execution of line 14 before invoking Imin , we have that p read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I. In Case B, this is immediate since I = Imin . Since emin is an L-remove event for ptrL , and I is an invocation of the AcquireNext procedure such that 149

p read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I, by Lemma C.4.15, the second parameter of I is not ptrL . However, the second parameter of I is ptrL , a contradiction. Now suppose that emin is not an L-remove event for ptr and suppose, for contradiction, that (∗ptr).next.sealed ̸= False at some time T during I B . This implies the following. Claim C.4.24.1. There is an L-remove event for ptr in I B . Proof. Since ptr ∈ C ∪ {&H}, (∗ptr).next.sealed is initially False. Thus, since by our initial assumption (∗ptr).next.sealed ̸= False at T , we have that (∗ptr).next.sealed changed in I B . Hence, by Observation C.1.6, there is a successful list-sealed attempt a for ptr in I B . Therefore, by Corollary C.1.37, there is an L-remove event for ptr in I B . Claim C.4.24.1 Claim C.4.24.2. ptr is in either List(Ieexclude ) or List(Ieinclude ). min min Proof. We first standardize the proof of both cases by defining an invocation Iparent of either the DoAddCell, DoRemoveCell, or Acquire procedure, and an invocation I of the AcquireNext procedure which occurs during Iparent and whose second parameter is ptr. In Case A, Imin is an invocation of the DoRemoveCell procedure. Let Iparent = Imin and let I be the invocation of the AcquireNext procedure during Imin identified by Proposition C.4.22. In Case B, Imin is an invocation of the AcquireNext procedure. Let Iparent be the invocation of the DoAddCell, DoRemoveCell, or Acquire procedure in which pmin invokes Imin during, and let I = Imin . 14 is the time of p Since Tmin min ’s last execution of line 14 before invoking Imin , it follows that 14 Tmin is also the time of pmin ’s last execution of line 14 before invoking Iparent . Thus, since pmin read 14 , we have that p (ulloL , ptrL ) from L at Tmin min read (ulloL , ptrL ) from L on its last execution of line 14 before invoking Iparent . Therefore, since ptr is the second parameter of I, by Lemma C.4.19, ) as wanted. ) or List(Ieinclude ptr is in either List(Ieexclude Claim C.4.24.2 min min We now finish the proof of Proposition C.4.24. By Claim C.4.24.2 ptr is in either List(Ieexclude ) min exclude ) and ptr ∈ include ). Let or List(Ieinclude ), so it suffices to prove that ptr ∈ / List(I / List(I emin emin min eremove be the L-remove event for ptr identified by Claim C.4.24.1. Since emin is not an L-remove event for ptr and eremove is an L-remove event for ptr, it follows that emin ̸= eremove . Hence, since by Lemma C.4.11 emin is the last L-event in I B , we have eremove ≤ emin , and since emin ̸= eremove , it follows that eremove < emin . Since eremove is an L-remove event for ptr in I B , by Corollary C.1.40, there is an L-add event eadd for ptr before eremove in I B , and since by Lemma C.2.30 P (I B ) holds, we have that eadd is the only L-add event for ptr in I B . Hence, since eadd < eremove and eremove < emin , by transitivity eadd < emin , and so eadd ̸= emin . Thus, since eadd is the only Ladd event for ptr in I B , we have that emin is not an L-add event for ptr. Since Ieexclude is the min B include B prefix of I up to but excluding emin , and Iemin is the prefix of I up to and including emin , it follows that the sequence of L-events in Ieexclude and Ieinclude are the same except the former min min excludes emin and the latter includes emin . Hence, since emin is not an L-add event for ptr, by Definition C.1.7, if ptr ∈ / List(Ieexclude ), then ptr ∈ / List(Ieinclude ). Therefore, what remains is to min min exclude prove that ptr ∈ / List(Iemin ). Suppose, for contradiction, that ptr ∈ List(Ieexclude ). Hence, by min exclude Definition C.1.5, we have that there is an L-add event e for ptr in Iemin such that there are no L-remove events for ptr from e onwards in Ieexclude . Since e is the only L-add event for ptr in add min B B I , and e is an L-add event for ptr in I , we have that eadd = e. Hence, there are no L-remove events for ptr from eadd onwards in Ieexclude . Therefore, since Ieexclude is the prefix of I B up to but min min excluding emin , there are no L-remove events for ptr between eadd and emin . However, since eremove is an L-remove event for ptr, eadd < eremove , and eremove < emin , we have that there is an L-remove event for ptr between eadd and emin , a contradiction. Proposition C.4.24

150

We now prove that pmin correctly fixes a value of ptrL for the ptr field on line 61. Proposition C.4.25. In Scenario C.4.5, suppose Lmin is the loop on line 57 so Imin is an invocation of the DoRemoveCell procedure. Let ptr be the value of the local variable of prev ptr in Lmin . Then, ptr ∈ C ∪ {&H} and from emin onwards in I B (∗ptr).next.ptr = ptrL . Proof. Since Lmin is the loop on line 57, we have that Imin is an invocation of the DoRemoveCell procedure. Hence, since pmin read (ulloL , ptrL ) from L on its last execution of line 14 before invoking Imin , we have that the parameters of Imin are (ulloL , ptrL ). Furthermore, by line 17, ulloL = (∗, RemoveCell). Therefore, since by Lemma C.4.10 emin set L = (ulloL , ptrL ), by Definition C.1.5, emin is an L-remove event for ptrL , so by Lemma C.1.28 ptrL ∈ C. Claim C.4.25.1. ptrL is in List(Ieexclude ) exactly once, and ptr is the pointer preceding ptrL in min exclude List(Iemin ). Furthermore, ptr ∈ C ∪ {&H}. Proof. Since pmin takes infinitely many steps in Lmin , we have that pmin executes line 61 infinitely often. Hence, since ptrL is the second parameter of Imin , and ptr is the value of the local variable of prev ptr in Lmin , by Definition C.1.5, pmin performs infinitely many list-remove attempts for ptrL between ptr and some pointer. Let a be the first list-remove attempt in Lmin . Since by Lemma C.2.30 Q(I B ) holds, we have that before a there is a unique L-remove event e for ptrL and if I is the prefix of I B up to but excluding e, ptrL is in List(I) exactly once, and ptr is the pointer preceding ptrL in List(I). Since by Lemma C.2.30 P (I B ) holds, we have that there is at most one L-remove event for ptrL in I B . Hence, since emin and e are both L-remove events for ptrL , we have that e = emin . Thus, since I is the prefix of I B up to but excluding e, we have that I is the prefix of . Therefore, since ptrL is in List(I) exactly once, I B up to but excluding emin , and so I = Ieexclude min ) exactly once, and ptr is the pointer preceding ptrL in List(I), we have that ptrL is in List(Ieexclude min exclude and ptr is the pointer preceding ptrL in List(Iemin ). Furthermore, since ptrL is in List(Ieexclude ) min exactly once, and ptr is the pointer preceding ptrL in List(Ieexclude ), it follows that ptr is not the min last pointer in List(Ieexclude ), and so by Definition C.1.7, ptr ∈ C ∪ {&H}. Claim C.4.25.1 min Claim C.4.25.2. There is a pointer next ptr succeeding ptrL in List(Ieexclude ). Furthermore, from min B emin onwards in I (∗ptrL ).next.ptr = next ptr. Proof. Since ptrL ∈ C, by Assumption C.1.2, ptrL ̸= Null. Hence, since by Claim C.4.25.1 ptrL is in List(Ieexclude ) exactly once, by Definition C.1.7, there is a pointer succeeding ptrL in min List(Ieexclude ); say next ptr. We now prove the furthermore part. Suppose, for contradiction, min (∗ptrL ).next.ptr ̸= next ptr at some time T ≥ emin in I B . We first prove that (∗ptrL ).next.ptr = next ptr at emin . Since by Lemma C.4.11 emin is the last L-event in I B , and by definition Ieinclude min is the prefix of I B up to and including emin , we have that emin is the last L-event in Ieinclude . min include there are Hence, since emin is the last step in Ieinclude , we have that from e onwards in I min emin min no successful list-add or list-remove attempts. Thus, since by Lemma C.2.30, P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(Ieexclude ) in Ieinclude . Hence, since min min exclude next ptr is the pointer after ptrL in List(Iemin ), and the the list of cells conforms to List(Ieexclude ) min include , (∗ptr ).next.ptr = next ptr. Therefore, since in Ieinclude , by Definition C.1.7, at the end of I L emin min emin is the last step in Ieinclude , we have that (∗ptrL ).next.ptr = next ptr at emin as wanted. Since min (∗ptrL ).next.ptr ̸= next ptr at some time T ≥ emin , this implies that T > emin . Hence, since (∗ptrL ).next.ptr = next ptr at emin , and (∗ptrL ).next.ptr ̸= next ptr at T > emin , we have that (∗ptrL ).next.ptr changed between emin and T . Thus, since ptrL ∈ C, by Observation C.1.6, there is a successful list-add attempt after ptrL or there is a successful list-remove attempt between ptrL and some pointer after emin in I B ; say a. Since by Lemma C.4.11 emin is the last L-event in I B , 151

emin is an L-remove event for ptrL , and by Lemma C.2.30, P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.5, from emin onwards in I B there is at most one successful list-remove attempt for ptrL and no other successful list-remove or list-add attempts for any pointer. Hence, since a is a successful list-attempt after emin , we have that a is a successful list-remove attempt for ptrL . Thus, since a is either a successful list-add attempt after ptrL or a successful list-remove attempt between ptrL and some pointer, we have that a is a successful list-remove attempt for ptrL between ptrL and some pointer. Therefore, since by Lemma C.2.30 P (I B ) and Q(I B ) hold, by Lemma C.1.57, ptrL ̸= ptrL . However, ptrL = ptrL , a contradiction. Claim C.4.25.2 Claim C.4.25.3. ptr ̸= ptrL ̸= next ptr, ptr is in List(Ieinclude ) exactly once, and next ptr is the min pointer succeeding ptr in List(Ieinclude ). min Proof. Since Ieexclude is finite, and by Lemma C.2.30 P (I B ) holds, by Lemma C.1.114, the pointers min exclude in List(Iemin ) are pairwise distinct. Hence, since by Claim C.4.25.1 ptrL is in List(Ieexclude ) min exactly once and ptr precedes ptrL in List(Ieexclude ), and by Claim C.4.25.2 next ptr succeeds min ptrL in List(Ieexclude ), we have that ptr = ̸ ptr L ̸= next ptr. Since emin is an L-remove event min ) that includes ) is a one step extension of List(Ieexclude for ptrL , and by definition List(Ieinclude min min exclude include emin , by Definition C.1.7, we have that List(Iemin ) and List(Iemin ) are identical with the exception that ptrL is in List(Ieexclude ) but not in List(Ieinclude ). Therefore, since ptr ̸= ptrL and min min exclude ptr is in List(Iemin ) exactly once, we have that ptr is in List(Ieinclude ) exactly once. Likewise, min include since next ptr ̸= ptrL , we have that next ptr is in List(Iemin ). Therefore, since List(Ieinclude ) and min exclude ) but not in List(I include ), List(Ieexclude ) are identical with the exception that ptr is in List(I L emin emin min ), next ptr is the pointer succeeding ptrL in ptr is the pointer preceding ptrL in List(Ieexclude min List(Ieexclude ), ptr is in List(Ieinclude ) exactly once, and next ptr is in List(Ieinclude ), we have that min min min next ptr is the pointer succeeding ptr in List(Ieinclude ) as wanted. Claim C.4.25.3 min Claim C.4.25.4. For every finite prefix I of I B at or after emin the list of cells conforms to List(Ieexclude ) in I. min Proof. Suppose, for contradiction, there is a prefix I of I B at or after emin such that the list of cells ) in I. Since pmin takes infinitely many steps in Lmin , we have that does not conform to List(Ieexclude min pmin executes line 58 infinitely often in Lmin . Hence, pmin executes line 58 in Lmin after the end of I. Let T 58 be the first time pmin executes line 58 in Lmin after the end of I, and let T 56 be the time of 14 , T 14 is pmin ’s execution of line 56 immediately preceding T 58 . Since by Lemma C.4.10, emin < Tmin min the time of pmin last execution of line 14 before Imin , and T 56 and T 58 are times of steps executing during Imin , we have that emin < T 56 < T 58 . We first show what value pmin read at T 56 . Since the parameters of Imin are (ulloL , ptrL ), and emin < T 56 , by Claim C.4.25.2, pmin read next ptr from (∗ptrL ).next.ptr on line 56 at T 56 . We now show what value pmin read at T 58 . Let I 58 be the prefix of I B up to and including T 58 . Since by definition T 58 is the first time pmin executes line 58 in Lmin after the end of I, we have that I is a prefix of I 58 . Hence, since the list of cells does not conform to List(Ieexclude ) in I, by Lemma C.4.18, the list of cells conforms to List(Ieinclude ) in min min 58 include I . Thus, since by Claim C.4.25.3 ptr is in List(Iemin ) and next ptr is the pointer succeeding ptr in List(Ieinclude ), by Definition C.1.7, (∗ptr).next.ptr = next ptr at the end of I 58 . Therefore, min since ptr is the value of the local variable of prev ptr in Lmin , we have that pmin read next ptr from (∗ptr).next.ptr on line 58 at T 58 . We now finish the proof. Since (∗ptrL ).next.ptr = next ptr at T 56 , and (∗ptr).next.ptr = next ptr at T 58 , we have that pmin finds the condition on line 59 to be true after T 58 . Therefore, pmin exits Lmin , and so pmin takes finitely many steps in Lmin . However, pmin takes infinitely many steps in Lmin , a contradiction. Claim C.4.25.4

152

We now finish the proof of Proposition C.4.25. Consider any prefix I of I B at or after emin . By Claim C.4.25.4, the list of cells conforms to List(Ieexclude ) in I. Since by Claim C.4.25.1 ptr min precedes ptrL in List(Ieexclude ) in I, by Definition C.1.7, (∗ptr).next.ptr = ptrL at the end of I. min Therefore, since I is any prefix of I B at or after emin , the claim follows. Proposition C.4.25 We are now ready to finish the first part of this subsection: that the value of the next object of some cell changes infinitely in I B . Proposition C.4.26. In Scenario C.4.5, suppose Lmin is either the loop on line 53 (Case A), 57 (Case B), or 103 (Case C). Let ptr be the value of the local variable ptrL (Case A), prev ptr (Case B), or curr ptr (Case C) in Lmin . Then, (∗ptr).next changes infinitely often during I B . Proof. We consider each case separately. Case A. Hence, Lmin is the loop on line 53. Since pmin takes infinitely many steps inside Lmin , we have that pmin executes infinitely many unsuccessful CAS operations on line 55 during Lmin . Hence, since the first parameter of each of these CAS operations is the value read from (∗ptr).next on the line before, we have that (∗ptr).next changes infinitely often as wanted. Case B. Hence, Lmin is the loop on line 57. Thus, Imin is an invocation of the DoRemoveCell procedure. Since pmin read (ulloL , ptrL ) from L on its last execution of line 14 before invoking Imin , we have that (ulloL , ptrL ) are the parameters of Imin . Furthermore, by Lemma C.4.13, pmin invoked Imin after emin . Since pmin takes infinitely many steps inside Lmin , we have that pmin executes infinitely many unsuccessful CAS operations on line 61 during Lmin . Consider any of these unsuccessful CAS operations and denote it by o. It suffices to prove that between pmin ’s last execution of line 58 before o and o, the value of (∗ptr).next changed. Let T 58 be time of pmin ’s last execution of line 58 before o. Since o is executed inside Lmin which is executed inside Imin , and the second parameter of Imin is ptrL , we have that the first parameter of o is of the form (view′ , False, a′ , ptrL ). Hence, by line 58, (∗ptr).next = (view′ , ∗, a′ , ∗) at T 58 . Furthermore, by Proposition C.4.24, (∗ptr).next.sealed = False at T 58 . Lastly, since emin is before pmin invoked Imin and T 58 is in Imin , by transitivity, emin < T 58 , and so by Proposition C.4.25, (∗ptr).next.ptr = ptrL at T 58 . Hence, (∗ptr).next = (view′ , False, a′ , ptrL ) at T 58 . Therefore, since the first parameter of o equals the value of (∗ptr).next at the time of pmin ’s last execution of line 58 before o, and o was unsuccessful, we have that the value of (∗ptr).next changed, as wanted. Case C. Hence, Lmin is the loop on line 103. Since pmin takes infinitely many steps inside Lmin , we have that pmin executes infinitely many unsuccessful CAS operations on line 109 during Lmin . Consider any of these unsuccessful CAS operations and denote it by o. It suffices to prove that between pmin ’s last execution of line 104 before o and o, the value of (∗ptr).next changed. Let (view, False, a, next ptr) be the first parameter of o. Hence, by line 104, (∗ptr).next = (view, ∗, a, next ptr) on pmin ’s last execution of line 104 before o. Furthermore, by Proposition C.4.24, (∗ptr).next.sealed = False throughout I B . Hence, (∗ptr).next = (view, False, a, next ptr) on pmin ’s last execution of line 104 before o. Therefore, since the first parameter of o equals the value of (∗ptr).next at the time of pmin ’s last execution of line 104 before o, and o was unsuccessful, we have that the value of (∗ptr).next changed, as wanted. Proposition C.4.26

153

This completes the first part of the high-level argument for why pmin cannot take infinitely many steps in the loops on lines 53, 57, and 103 during opxmin . We now prove the second part of this subsection: the next object of each cell changes finitely many times in I B . The high-level argument for why this is true is that: (1) each process performs a finite number of successful CAS operations on the next object of each cell; and (2) finitely many processes take steps in I B . The idea for proving (1) is that if a process performing infinitely many successful CAS operations on the next object of some cell, then it must perform an L-event after emin in I B , contradicting Lemma C.4.11. We start by proving two facts that relate A and L. Lemma C.4.27. Suppose there is an L-event e in I B that sets L = v. Then, there are finitely many executions of line 21 or line 27 in I B that try to set A = v. Proof. Suppose, for contradiction, there are infinitely many executions of line 21 or line 27 in I B that try to set A = v. Hence, by Corollary C.1.18, some process p performs infinitely many executions of line 21 or line 27 that try to set A = v during some invocation I of the DoLowLevelOp procedure. Since e is an L-event, by Definition C.1.5, e sets L = v = ((∗, llo), ptr). Hence, by Definition C.1.5, e is an L-event for ptr so by Lemma C.1.29 llo is either AddCell, ⟨Apply&CopyResponse, ∗⟩, or RemoveCell, and by Lemma C.1.28 ptr ∈ C. Since p performs infinitely many executions of line 21 or line 27 that try to set A = v during I and v = ((∗, llo), ptr), we have that (llo, ptr) are of the parameters of I. Furthermore, p executes line 13 and line 14 infinitely often during I, and so (∗ptr).response = ((∗, llo), Null) infinitely often during I B (*). There are three cases. We note that the proofs of each case are essentially the same, but they rely on different lemmas. Case 1. llo = AddCell. There are two cases. Case 1.1. L = ((∗, AddCell), ptr) from e onwards. Since p executes line 14 infinitely often during I, it follows that p executes line 14 at some time Tp14 after e, and so p reads ((∗, AddCell), ptr) from L at Tp14 . Hence, since p executes line 14 again after Tp14 , it follows that p invokes the DoAddCell procedure with a second parameter of ptr on line 16 immediately after Tp14 and p exits this invocation of the DoAddCell procedure; say at time Tp16 . Hence, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.14, there is a successful add-response-set attempt a for ptr before Tp16 . Therefore, since ptr ∈ C, by Lemma C.1.82, from a onwards (∗ptr).response ̸= ((∗, AddCell), Null). However, since by (*) (∗ptr).response = ((∗, llo), Null) infinitely often during I B and llo = AddCell, we have that (∗ptr).response = ((∗, AddCell), Null) some time after a, a contradiction. Case 1.2. L ̸= ((∗, AddCell), ptr) some time after e. Hence, since e sets L = ((∗, llo), ptr) and llo = AddCell, the value of L changed after e, and so by Observation C.1.6 there is an L-event after e. Let e′ be the next L-event after e and let q be the process that executed e′ . Hence, by Lemma C.1.41 q read the value that e set L to on its last execution of line 14 before e′ ; say at time Tq14 . Since e sets L = ((∗, AddCell), ptr), we have that q read ((∗, AddCell), ptr) from L at Tq14 . Hence, since q executes e′ after Tq14 , it follows that q invokes the DoAddCell procedure with parameters ptr on line 16 immediately after Tq14 and q exits this invocation of the DoAddCell procedure; say at time Tq16 . Thus, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.14, there is a successful add-response-set attempt a for ptr before Tq16 . Therefore, since ptr ∈ C, by Lemma C.1.82, from a onwards (∗ptr).response ̸= ((∗, AddCell), Null). However, since by (*) (∗ptr).response = ((∗, llo), Null) infinitely often during I B and llo = AddCell, we have that (∗ptr).response = ((∗, AddCell), Null) some time after a, a contradiction. 154

Case 2. llo = ⟨Apply&CopyResponse, ∗⟩. There are two cases. Case 2.1. L = ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from e onwards. Since p executes line 14 infinitely often during I, it follows that p executes line 14 at some time Tp14 after e, and so p reads ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from L at Tp14 . Hence, since p executes line 14 again after Tp14 , it follows that q invokes the DoApply&CopyResponse procedure with a second parameter of ptr on line 20 immediately after Tp14 and p exits this invocation of the DoApply&CopyResponse procedure; say at time Tp20 . Hence, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.18, there is a successful apply-response-set attempt a for ptr before Tp20 . Therefore, since ptr ∈ C, by Lemma C.1.83, from a onwards (∗ptr).response ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), Null). However, since by (*) (∗ptr).response = ((∗, llo), Null) infinitely often during I B and llo = ⟨Apply&CopyResponse, ∗⟩, we have that (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) some time after a, a contradiction. Case 2.2. L ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) some time after e. Hence, since e sets L = ((∗, llo), ptr) and llo = ⟨Apply&CopyResponse, ∗⟩, the value of L changed after e, and so by Observation C.1.6 there is an L-event after e. Let e′ be the next L-event after e and let q be the process that executed e′ . Hence, by Lemma C.1.41 q read the value that e set L to on its last execution of line 14 before e′ ; say at time Tq14 . Since e sets L = ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr), we have that q read ((∗, ⟨Apply&CopyResponse, ∗⟩), ptr) from L at Tq14 . Hence, since q executes e′ after Tq14 , q invokes the DoApply&CopyResponse procedure with a second parameter of ptr on line 20 immediately after Tq14 and q exits this invocation of the DoApply&CopyResponse procedure; say at time Tq20 . Thus, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.18, there is a successful apply-response-set attempt a for ptr before Tq20 . Therefore, since ptr ∈ C, by Lemma C.1.83, from a onwards (∗ptr).response ̸= ((∗, ⟨Apply&CopyResponse, ∗⟩), Null). However, since by (*) (∗ptr).response = ((∗, llo), Null) infinitely often during I B and llo = ⟨Apply&CopyResponse, ∗⟩, we have that (∗ptr).response = ((∗, ⟨Apply&CopyResponse, ∗⟩), Null) some time after a, a contradiction. Case 3. llo = RemoveCell. There are two cases. Case 3.1. L = ((∗, RemoveCell), ptr) from e onwards. Since p executes line 14 infinitely often during I, it follows that p executes line 14 at some time Tp14 after e, and so p reads ((∗, RemoveCell), ptr) from L at Tp14 . Hence, since p executes line 14 again after Tp14 , it follows that p invokes the DoRemoveCell procedure with a second parameter of ptr on line 18 immediately after Tp14 and p exits this invocation of the DoRemoveCell procedure; say at time Tp18 . Hence, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.16, there is a successful remove-response-set attempt a for ptr before Tp18 . Therefore, since ptr ∈ C, by Lemma C.1.84, from a onwards (∗ptr).response ̸= ((∗, RemoveCell), Null). However, since by (*) (∗ptr).response = ((∗, llo), Null) infinitely often during I B and llo = RemoveCell, we have that (∗ptr).response = ((∗, RemoveCell), Null) some time after a, a contradiction. Case 3.2. L ̸= ((∗, RemoveCell), ptr) some time after e. Hence, since e sets L = ((∗, llo), ptr) and llo = RemoveCell, the value of L changed after e, and so by Observation C.1.6 there is an L-event after e. Let e′ be the next L-event after e and let q be the process that executed e′ . Hence, by Lemma C.1.41 q read the value that e set L to on its last 155

execution of line 14 before e′ ; say at time Tq14 . Since e sets L = ((∗, RemoveCell), ptr), we have that q read ((∗, RemoveCell), ptr) from L at Tq14 . Hence, since q executes e′ after Tq14 , it follows that q invokes the DoRemoveCell procedure with a second parameter of ptr on line 18 immediately after Tq14 and q exits this invocation of the DoRemoveCell procedure; say at time Tq18 . Thus, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.16, there is a successful removeresponse-set attempt a for ptr before Tq18 . Therefore, since ptr ∈ C, by Lemma C.1.84, from a onwards (∗ptr).response ̸= ((∗, RemoveCell), Null). However, since by (*) (∗ptr).response = ((∗, llo), Null) infinitely often during I B and llo = RemoveCell, we have that (∗ptr).response = ((∗, RemoveCell), Null) some time after a, a contradiction. Lemma C.4.27 Lemma C.4.28. Consider any process p and iteration I of the loop on line 13 by p in I B . If p reads a value v from A on line 22 during I such that L ̸= v throughout I B , then p does not receive Done on line 23 during I. Proof. Suppose, for contradiction, p received Done on line 23 during I. Since A and L are both initially ((0, Noop), Null) and L ̸= v throughout I B , it follows that v ̸= ((0, Noop), Null). Hence, A was set to v at some time, so by Observation C.1.6, there is an A-event eA that set A = v. Suppose eA is an A-event for ptr. Hence, by Lemma C.1.15 eA is an A-add, A-apply, or A-remove event for ptr. We consider each case separately. We note that the proofs of each case are essentially the same, but they rely on different lemmas. Case 1. eA is an A-add event for ptr. Hence, by Definition C.1.5, v = ((∗, AddCell), ptr), and so p read ((∗, AddCell), ptr) from A on line 22 during I. Thus, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, and p received Done on line 23 during I, by Lemma C.2.20, there is an L-add event eL for ptr in I B . Therefore, since eA is an A-add event for ptr, eL is an an L-add event for ptr, and eA sets A = v, by Lemma C.1.25, eL sets L = v. However, by assumption L ̸= v throughout I B , a contradiction. Case 2. eA is an A-apply event for ptr. Hence, by Definition C.1.5, v = ((∗, ⟨DoApply&CopyResponse, ∗⟩), ptr), and so we have that p read ((∗, ⟨DoApply&CopyResponse, ∗⟩), ptr) from A on line 22 during I. Thus, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, and p received Done on line 23 during I, by Lemma C.2.21, there is an L-apply event eL for ptr in I B . Therefore, since eA is an A-apply event for ptr, eL is an an L-apply event for ptr, and eA sets A = v, by Lemma C.1.25, eL sets L = v. However, by assumption L ̸= v throughout I B , a contradiction. Case 3. eA is an A-remove event for ptr. Hence, by Definition C.1.5, v = ((∗, RemoveCell), ptr), and so p read ((∗, RemoveCell), ptr) from A on line 22 during I. Thus, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, and p received Done on line 23 during I, by Lemma C.2.22, there is an L-remove event eL for ptr in I B . Therefore, since eA is an A-remove event for ptr, eL is an an L-remove event for ptr, and eA sets A = v, by Lemma C.1.25, eL sets L = v. However, by assumption L ̸= v throughout I B , a contradiction. Lemma C.4.28 We now prove (1). Proposition C.4.29. In Scenario C.4.5, consider any process p and any pointer ptr ∈ C ∪ {&H}. Then, p performs a finite number of successful CAS operations on (∗ptr).next in I B .

156

Proof. Suppose, for contradiction, p performs an infinite number of successful CAS operations on (∗ptr).next in I B . Hence, p takes infinitely many steps in I B . Claim C.4.29.1. Consider any incarnation L of the loops on lines 30, 46, 53, 57, 94, and 103 by p during I B . Then, p takes finitely many steps during L. Proof. Suppose, for contradiction, p takes infinitely many steps during L. There are two cases. Case 1. L is the loop on line 53 (Case A), 57 (Case B), or 103 (Case C). There are two cases. Case 1.1. The value of ptrL (Case A), prev ptr (Case B), and curr ptr (Case C) in L is ptr. Hence, since p takes infinitely many steps during L, we have that p never performs a successful CAS operation on (∗ptr).next on line 55 (Case A), line 61 (Case B), and line 109 (Case C) during L. Thus, there is a time after which p never performs another another successful CAS operation on (∗ptr).next during I B . Therefore, p performs a finite number of successful CAS operations on (∗ptr).next in I B . However, by our initial assumption of Proposition C.4.29, p performs an infinite number of successful CAS operations on (∗ptr).next in I B , a contradiction. Case 1.2. The value of ptrL (Case A), prev ptr (Case B), and curr ptr (Case C) in L is not ptr. Hence, since these are the only values that p performs CAS operations on in L, and p takes infinitely many steps during L, there is a time after which p never performs another CAS operation on (∗ptr).next during I B . Therefore, p performs a finite number of successful CAS operations on (∗ptr).next in I B . However, by our initial assumption of Proposition C.4.29, p performs an infinite number of successful CAS operations on (∗ptr).next in I B , a contradiction. Case 2. L is the loop on line 30, 46, or 94. Let I be the invocation of the DoAddCell, DoRemoveCell, or Acquire procedure in which L is in. Since, as proven in Case 1, p exits every invocation of the AcquireNext procedure in I B , we have that p invokes infinitely many invocations of the AcquireNext procedure during I. Let I1 , I2 , . . . denote these invocations of the AcquireNext procedure during I in the order they were invoked. Claim C.4.29.1.1. p read (ulloL , ptrL ) from L on its last execution of line 14 before invoking I. Proof. Suppose, for contradiction, p read (ulloL ′ , ptrL ′ ) ̸= (ulloL , ptrL ) from L on its last execution of line 14 before invoking I; say at time Tp14 . Since by Lemma C.4.10 emin set L = (ulloL , ptrL ) and by Lemma C.4.11 emin is the last L-event in I B , we have that from emin onwards in I B L = (ulloL , ptrL ), and so given the value p read at Tp14 we have that Tp14 < emin . We claim that ulloL ′ ̸= ulloL (*). Suppose, for contradiction, that ulloL ′ = ulloL . Since by Lemma C.4.9 ulloL ̸= (0, Noop), we have that ulloL ′ ̸= (0, Noop). Hence, since p read (ulloL ′ , ptrL ′ ) from L at Tp14 , we have that L.ullo was set to ulloL ′ before Tp14 . Thus, by Observation C.1.6, some L-event e set L.ullo = ulloL ′ before Tp14 . So, since e < Tp14 and Tp14 < emin , by transitivity, e < emin , and so e ̸= emin . Therefore, since ulloL ′ = ulloL , we have that there are two L-events in I B which set L.ullo = ulloL (namely emin and e). However, since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.32 every L-event in I B sets L.ullo to a unique value, a contradiction. We now return to the proof of Claim C.4.29.1.1. Since p read (ulloL ′ , ptrL ′ ) from L on its last execution of line 14 before invoking I, the first parameter of I is ulloL ′ . Hence, since p invokes I1 , I2 , . . . during I, it follows that the first parameter of I1 , I2 , . . . is also ulloL ′ . Since p invokes 157

infinitely many invocations of the AcquireNext procedure during I, there exists some invocation Ii of the AcquireNext procedure during I which is invoked after emin . Hence, since from emin onwards in I B L = (ulloL , ptrL ), we have that L = (ulloL , ptrL ) throughout Ii . Since p eventually exits Ii , it executes line 105 during Ii at least once. Hence, since the first parameter of Ii is ulloL ′ , by (*) ulloL ′ ̸= ulloL , and L = (ulloL , ptrL ) throughout Ii , we have that p finds the condition on line 105 to be true during Ii . Thus, since p exits Ii , it exits on line 106, and returns (L-Changed, ∗). Therefore, the value of status during I is L-Changed, and so p only takes finitely many steps in L. However, by assumption, p takes infinitely many steps in L, a contradiction. Claim C.4.29.1.1 We now finish the proof of Case 2. Let ptri denote the second parameter of Ii . Since Ieexclude min exclude ) and List(I include ) are finite, and so the and Ieinclude are finite, by Definition C.1.7, List(I e e min min min union of List(Ieexclude ) and List(Ieinclude ) is finite. Therefore, since by Claim C.4.29.1.1 p read min min (ulloL , ptrL ) from L on its last execution of line 14 before invoking I, by Lemma C.4.19, ptri is in either List(Ieexclude ) or List(Ieinclude ), and so {ptri | ∀i} is finite. However, by Lemma C.4.20, min min ptr1 , ptr2 , . . . are distinct so {ptri | ∀i} is infinite, a contradiction. Claim C.4.29.1 Claim C.4.29.2. p executes line 14 infinitely often in I B . Furthermore, p reads (ulloL , ptrL ) from L on every execution of line 14 at or after emin . Proof. Since p takes infinitely many steps in I B , and by Claim C.4.29.1 p exits every incarnation of the loops on lines 30, 46, 53, 57, 94, and 103 during I B , we have that p exits every invocation of every procedure other than DoHighLevelOp and DoLowLevelOp in I B . Hence, since p takes infinitely many steps in I B and there are no loops in the DoHighLevelOp procedure, we have that p takes infinitely many steps inside the DoLowLevelOp procedure in I B . Thus, since there is only a single loop inside the DoLowLevelOp procedure, and p exits every invocation of every procedure invoked inside the DoLowLevelOp procedure, we have that p executes line 14 infinitely often in I B . Since by Lemma C.4.10 emin set L = (ulloL , ptrL ) and by Lemma C.4.11 emin is the last L-event in I B , we have that from emin onwards in I B L = (ulloL , ptrL ). Hence, p reads (ulloL , ptrL ) from L on every execution of line 14 at or after emin . Claim C.4.29.2 Claim C.4.29.3. There exists an iteration I of the loop on line 13 by p during I B such that p’s execution of line 14 during I is at or after emin and p executes line 25 during I. Proof. Suppose, for contradiction, every iteration I of the loop on line 13 by p during I B either (1) p’s execution of line 14 during I is before emin or (2) p does not execute line 25 during I. Claim C.4.29.3.1. There are infinitely many A-events in I B . Proof. Suppose, for contradiction, there are finitely many A-events in I B . Since by Lemma C.4.11 emin is in I B , by Lemma C.1.23, there is an A-event in I B , and so there is a last A-event in I B ; say elast . Hence, since by Observation C.1.6 only A-events change the value of A, from elast onwards the value of A does not change. Since by Claim C.4.29.2 p executes line 14 infinitely often in I B , p executes line 14 after elast and emin . Let I be any iteration of the loop on line 13 in which p executes line 14 after elast and emin . Hence, since by Lemma C.4.11 emin is the last L-event in I B , by Lemma C.1.123, p does not find the condition on line 81 to be true during I. Thus, since p takes infinitely many steps during I B , we have that p’s response on line 23 is either NotDone or Done, and so p either executes line 25 or line 27 during I. So, since I is an iteration of the loop on line 13 by p during I B and p’s execution of line 14 during I is after emin , by our initial assumption of Claim C.4.29.3, we have that p does not execute line 25 during I, and so p executes line 27 during I. Denote this execution of line 27 by eA . If eA is successful, then by Definition C.1.5, eA is an A-event. 158

Since I is chosen such that p’s execution of line 14 during I is after elast , we have that elast < eA , and so there is an A-event after elast . However, this is impossible since elast is by definition the last A-event in I B . Hence, eA is unsuccessful. Let Tp22 be the time of p’s last execution of line 22 before eA . Since the first parameter of eA is the value p read from A at Tp22 and eA is unsuccessful, we have that the value of A changed between Tp22 and eA . Thus, by Observation C.1.6, there is an A-event between Tp22 and eA . Since I is chosen such that p’s execution of line 14 during I is after elast , we have that elast < Tp22 , and so there is an A-event after elast . However, this is impossible since elast is by definition the last A-event in I B . Therefore, all cases are impossible, so there are infinitely many A-events in I B . Claim C.4.29.3.1 Claim C.4.29.3.2. There is a time T1 where for all times T ≥ T1 A = v at T for some value v such that L ̸= v throughout I B . Proof. By Lemma C.4.11 there are finitely many L-events in I B . Let l1 , l2 , . . . , ln denote these L-events and suppose li sets L = vi . Hence, by Lemma C.4.27, there are finitely many executions of line 21 or line 27 in I B that try to set A = vi , and so by Observation C.1.6, there are finitely many A-events in I B that set A = vi . Thus, since by Lemma C.4.11 emin is in I B , by Lemma C.1.23 there is an A-event in I B , and so there is a last A-event in I B that set A = vi for any i ∈ [1..n]; say elast . Since by Claim C.4.29.3.1 there are infinitely many A-events in I B , there is an A-event after elast ; say enext . Since enext is an A-event after elast , we have that enext sets A = v such that v ̸= vi for all i ∈ [1..n]. We claim that enext is the time T1 listed in the statement of Claim C.4.29.3.2. Suppose, for contradiction, at some time T ≥ enext A = v ′ at T for some value v ′ such that L = v ′ at sometime during I B . We first prove that v ′ ̸= ((0, Noop), Null). Suppose, for contradiction, v ′ = ((0, Noop), Null). Since enext is an A-event that set A = v, by Lemma C.1.15, v ̸= ((0, Noop), Null). Hence, v ̸= v ′ , and so since A = v at enext and A = v ′ at T ≥ enext , we have that A was set to v ′ . Therefore, by Observation C.1.6, an A-event set A = v ′ , and so by Lemma C.1.15, v ′ ̸= ((0, Noop), Null). However, v ′ = ((0, Noop), Null), a contradiction. Since L is initially ((0, Noop), Null), v ′ ̸= ((0, Noop), Null), and L = v ′ at sometime during I B , we have that L was set to v ′ during I B , and so by Observation C.1.6, an L-event e set L = v ′ during I B . Hence, since l1 , l2 , . . . , ln are the only L-events in I B , we have that e = li and v ′ = vi for some i ∈ [1..n]. Thus, since v ̸= vi for all i ∈ [1..n], we have that v ̸= v ′ . So, since A = v at enext and A = v ′ at T ≥ enext , we have that A was set to v ′ after enext . Hence, by Observation C.1.6, an A-event e′ after enext set A = v ′ . Therefore, since elast < enext and enext < e′ , by transitivity, elast < e′ , and so there is an A-event after elast that set A = v ′ = vi . However, elast is the last A-event in I B that set A = vi for any i ∈ [1..n], a contradiction. Claim C.4.29.3.2 We now finish the proof of Claim C.4.29.3. By Claim C.4.29.2, there is an iteration I of the loop on line 13 by p during I B such that p’s execution of line 14 during I is after max(emin , T1 ) and p reads (ulloL , ptrL ) from L on line 14 during I. Hence, since by Lemma C.4.11 emin is the last L-event in I B , by Lemma C.1.123, p does not find the condition on line 81 to be true during I. Thus, since p takes infinitely many steps during I B , we have that p receives NotDone or Done on line 23 during I. So, since I is an iteration of the loop on line 13 by p during I B and p’s execution of line 14 during I is after emin , by our initial assumption of Claim C.4.29.3, we have that p receives Done on line 23 during I (*). We now satisfy the condition of Lemma C.4.28. Suppose p read v from A on line 22 during I; say at time T 22 . Hence, since p’s execution of line 14 during I is after max(emin , T1 ), we have that T 22 ≥ T1 , and so by Claim C.4.29.3.2, L ̸= v throughout I B . Therefore, by Lemma C.4.28, p does does not receive Done on line 23 during I. However, by (*), p receives Done on line 23 during I, a contradiction. Claim C.4.29.3

159

We now finish the proof of Proposition C.4.29. Since by Claim C.4.29.3 there is an iteration I of the loop on line 13 by p during I B such that p’s execution of line 14 during I is at or after emin and p executes line 25 during I. There are two cases. Case 1. p’s execution of line 25 during I is successful. Hence, since p’s execution of line 14 during I is at or after emin , we have that p’s execution of line 25 during I is after emin . Therefore, by Definition C.1.5, there is an L-event after emin in I B . However, by Lemma C.4.11, emin is the last L-event in I B , a contradiction. Case 2. p’s execution of line 25 during I is unsuccessful. Hence, between p’s execution of line 14 and line 25 during I, the value of L changed. Thus, by Observation C.1.6, there is an L-event after p’s execution of line 14 during I. Therefore, since p’s execution of line 14 during I is at or after emin , we have that there is an L-event after emin in I B . However, by Lemma C.4.11, emin is the last L-event in I B , a contradiction. Proposition C.4.29 We now prove (2). Proposition C.4.30. In Scenario C.4.5, finitely many processes take steps in I B . Proof. Suppose, for contradiction, infinitely many processes take steps in I B . Since by Assumption C.1.1 I B has bounded concurrency15 , this implies infinitely many operations complete in I B . Let opx1 , opx2 , . . . denote this infinite sequence of complete operation executions and let ptri denote the response the process that executed opxi received on line 2 during opxi . We prove that there is an L-add event for ptri in I B . Since opxi completes and received ptri on line 2, we have that the process that executed opxi invokes and exits the DoLowLevelOp procedure on line 3 with parameters (AddCell, ptri ). Therefore, since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.105, there is an L-add event for ptri in I B . We now finish the proof. Since by Algorithm 4 the responses on line 2 are unique, we have that ptri ̸= ptrj for every i ̸= j. Hence, since there is an L-add event for ptri for every i in I B , we have that there are infinitely many L-events in I B . However, by Lemma C.4.11, there are finitely many L-events in I B , a contradiction. Proposition C.4.30 This completes the second part of the high-level argument for why pmin cannot take infinitely many steps in the loops on lines 53, 57, and 103 during opxmin . We are now ready to prove the main claim of this section. Lemma C.4.31. Lmin is not a loop on line 53, 57, or 103. Proof. Suppose, for contradiction, Lmin is a loop on line 53 (Case A), 57 (Case B), or 103 (Case C). Hence, Lmin is not a loop on line 13. Thus, this is Scenario C.4.5. Let ptr be the value of the local variable ptrL (Case A), prev ptr (Case B), or curr ptr (Case C) in Lmin . Since by Proposition C.4.23 ptr ∈ C ∪ {&H}, and by Proposition C.4.26, (∗ptr).next changes infinitely often during I B , by Observation C.1.6 and Definition C.1.5, we have that there are infinitely many successful CAS operations on (∗ptr).next in I B . However, since ptr ∈ C ∪ {&H}, by Proposition C.4.29 each process performs a finite number of successful CAS operations on (∗ptr).next in I B , and by Proposition C.4.30 only finitely many processes take steps in I B , we have that there are finitely many successful CAS operations on (∗ptr).next in I B , a contradiction. Lemma C.4.31 By Lemma C.4.21 and Lemma C.4.31 we have the following. Corollary C.4.32. Lmin is the loop on line 13. 15

This is the only place in the entire proof where we rely on this assumption.

160

C.4.3

Processes cannot get stuck in the loop on line 13

In this section, we show that pmin does not take infinitely many steps in Lmin . Let Imin denote the invocation of the DoLowLevelOp procedure that Lmin was executed during. Furthermore, let vmin = ((t(I(opxmin )), llomin ), ptrmin ) where (llomin , ptrmin ) are the parameters of Imin . Observation C.4.33. Every execution of line 21 or line 27 during Imin tries to set A = vmin . The high-level argument for why pmin does not take infinitely many steps in Lmin follows closely from the wait-freedom proof of Algorithm 1. Proposition C.4.34. L ̸= vmin throughout I B . Proof. Suppose, for contradiction, L = vmin at some time during I B . Hence, since L is initially ((0, Noop), Null), vmin = ((t(I(opxmin )), llomin ), ptrmin ), and llomin ̸= Noop, we have that L was set to vmin . Thus, by Observation C.1.6, there is an L-event e that set L = vmin . Since pmin takes infinitely many steps in Lmin , and by Corollary C.4.32 Lmin is the loop on line 13 during Imin , we have that pmin executes line 21 infinitely many times in Imin . Therefore, by Observation C.4.33, pmin performs infinitely many executions of line 21 that try to set A = vmin . However, since e is an L-event that set L = vmin in I B , by Lemma C.4.27, there are only finitely many executions of line 21 that try to set A = vmin , a contradiction. Proposition C.4.34 Proposition C.4.35. Suppose A = v from some time T onwards in I B . Then, there are finitely many L-events in I B . Proof. Suppose, for contradiction, there are infinitely many L-events in I B . Let l1 , l2 , . . . denote the infinitely many L-events in I B in the order they occur, and suppose li sets L = vi . Hence, by Lemma C.1.23, there is an A-event that set A = vi . Furthermore, since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.30, we have that vi ̸= vj for every i ̸= j. Hence, since there is an A-event that set A = vi , we have that there are infinitely many A-events that set A to different values in I B . Thus, for every time, there is a later A-event that sets A to a value that A has never been set to before. Therefore, since A = v at T , there is an A-event after T that sets A to a value other than v. However, by assumption, A = v from T onwards, a contradiction. Proposition C.4.35 Proposition C.4.36. Suppose A = v from some time T onwards in I B . Then, L = v at some time in I B . Proof. Suppose, for contradiction, from some time T onwards A = v and L ̸= v throughout I B . Hence, since L is initially ((0, Noop), Null), it follows that v ̸= ((0, Noop), Null). Thus, since A = v at T , and A is initially ((0, Noop), Null), it follows that A was set to v, and so by Observation C.1.6, there is an A-event e that set A = v. Suppose e is an A-event for ptr. Hence, by Definition C.1.5, v = (∗, ptr), and by Lemma C.1.14 ptr ∈ C. Since by assumption A = v from T onwards in I B , by Proposition C.4.35, there are finitely many L-events in I B . Hence, there is a last L-event in I B ; say elast . Claim C.4.36.1. Suppose pmin executes line 14 at some time after max(T, elast ) in I B . Then, in the same iteration of the loop on line 13, pmin executes line 25 and tries to set L = v. Proof. Suppose pmin executes line 14 at some time T 14 after max(T, elast ). Let I be the iteration of the loop on line 13 that pmin executes line 14 at T 14 . Since pmin takes infinitely many steps in Lmin , we have that pmin executes line 22 during I; say at time T 22 . Hence, max(T, elast ) < T 14 < T 22 . Since by assumption A = v from T onwards, and T < T 22 , we have that pmin read v from A at 161

T 22 . Hence, if pmin executes line 25 during I, we have that pmin tries to set L = v. Thus, it suffices to prove that pmin executes line 25 during I. Suppose, for contradiction, pmin does not execute line 25 during I. Since elast is the last Levent in I B , and pmin ’s execution of line 14 during I is after elast , by Lemma C.1.123, pmin does not find the condition on line 81 to be true during I. Thus, since pmin takes infinitely many steps in Lmin , we have that pmin receives NotDone or Done on line 23 during I. Therefore, since by assumption pmin does not execute line 25 during I, we have that pmin receives Done on line 23 during I. However, since pmin reads v from A on line 22 during I and L ̸= v throughout I B , by Lemma C.4.28, pmin does not receive Done on line 23 during I, a contradiction. Claim C.4.36.1 Claim C.4.36.2. There is a time T ′ after which all executions of line 25 try to set L = v. Proof. Suppose, for contradiction, that for all times there exists a later time where an execution of line 25 tries to set L to a value other than v. Thus, since every execution of line 25 tries to set L to a value read from A, we have that there are infinitely many executions of line 22 that read a value other than v from A. However, from T onwards A = v, a contradiction. Claim C.4.36.2 We now complete the proof of Proposition C.4.36. Since pmin takes infinitely many steps in Lmin and by Corollary C.4.32 Lmin is the loop on line 13, we have that pmin executes line 14 at some time after max(T, elast , T ′ ). Consider the first iteration of the loop on line 13 during Lmin that pmin executes line 14 after max(T, elast , T ′ ). Denote this loop iteration by I and let T 14 be the time pmin executed line 14 during I. By Claim C.4.36.1, pmin executes line 25 during I and tries to set L = v; say at time T 25 . If pmin ’s execution of line 25 at T 25 is successful, then L = v at T 25 . However, by assumption L ̸= v at all times in I B , so pmin ’s execution of line 25 at T 25 is unsuccessful. Thus, since the first parameter of pmin ’s execution of line 25 at T 25 is the value that pmin read from L on line 14 at T 14 , we have that between T 14 and T 25 the value of L changed, and so by Observation C.1.6, there is an L-event e′ after T 14 . Hence, since T 14 is after T ′ , by transitivity, T ′ < e. Therefore, since by Definition C.1.5 e′ is an execution of line 25, by Claim C.4.36.2, e′ set L = v. However, by assumption L ̸= v at all times in I B , a contradiction. Proposition C.4.36 Proposition C.4.37. Suppose some process p during some invocation I of the DoLowLevelOp procedure in I B received t < t(I(opxmin )) as a response on line 10 during I. Then, p takes finitely many steps in I. Proof. Suppose, for contradiction, p takes infinitely many steps in I. Let opx be the operation execution p is executing I during. Hence, since p takes infinitely many steps in I during opx, we have that p never executes line 8 during opx, and so p takes infinitely many steps during opx without completing it. Thus, by Definition C.4.1, opx is stuck, and so opx ∈ S. Since p takes infinitely many steps inside I during opx and I is an invocation of the DoLowLevelOp procedure, it follows that I is the invocation of the DoLowLevelOp procedure identified in (1) of Observation C.4.2. Hence, by Definition C.4.4, I(opx) = I. Thus, since p received t as a response on line 10 during I, by Definition C.4.3, t(I) = t, and since I(opx) = I, we have that t(I(opx)) = t. Therefore, since opx ∈ S, by Definition C.4.4, t(I(opxmin )) ≤ t(I(opx)), and so t(I(opxmin )) ≤ t. However, by definition t < t(I(opxmin )), a contradiction. Proposition C.4.37 Proposition C.4.38. A = vmin from some time T onwards in I B . Proof. Suppose, for contradiction, that for all times there exists a later time when A ̸= vmin . Claim C.4.38.1. There is a time T1 after which A ̸= ((t, ∗), ∗) for every t ∈ [0..t(I(opxmin ))).

162

Proof. Suppose, for contradiction, that for all times there is a later time when A = ((t, ∗), ∗) for some t ∈ [0..t(I(opxmin ))). There are two cases. Case 1. The value of A changes infinitely often. Since [0..t(I(opxmin ))) is finite, we have that A is set to ((t, ∗), ∗) for some t ∈ [0..t(I(opxmin ))) infinitely often. Hence, by Observation C.1.6, there are infinitely many A-events that set A to ((t, ∗), ∗). Thus, by Definition C.1.5, there are infinitely many executions of line 21 or line 27 that try to set A = ((t, ∗), ∗). Therefore, by Lemma C.1.17, all of these executions are by the same process p and inside the same invocation I of the DoLowLevelOp procedure where p received t as a response on line 10 during I. However, since t < t(I(opxmin )), by Proposition C.4.37, p takes finitely many steps in I, a contradiction. Case 2. The value in A changes finitely often. Since infinitely often A = ((t, ∗), ∗) for some t ∈ [0..t(I(opxmin ))), it follows that there exists a t ∈ [0..t(I(opxmin ))) such that A = ((t, ∗), ∗) from some time T onwards in I B . Hence, by Proposition C.4.35, there are finitely many L-events in I B ; say elast is the last L-event in I B . Since pmin takes infinitely many steps in Lmin , we have that pmin executes line 14 after max(T, elast ). Consider the first time pmin does so and let I be the iteration of the loop on line 13 that pmin does so in. Hence, since elast is the last L-event in I B , by Lemma C.1.123, pmin does not find the condition on line 81 to be true during I. Thus, since pmin takes infinitely many steps in Lmin , we have that pmin receives NotDone or Done on line 23 during I, and so pmin executes either line 25 or line 27 during I. We consider each case separately. Case 2.1. pmin executes line 25 during I. Let T 25 be the time of pmin ’s execution of line 25 during I. Since pmin executes line 14 after elast during I, we have that T 25 > elast . Thus, if pmin ’s execution of line 25 at T 25 is successful, by Definition C.1.5, there is an L-event after elast in I B . However, elast is the last L-event in I B so this is impossible. Hence, pmin ’s execution of line 25 at T 25 is unsuccessful. Suppose elast set L = (ullo, ptr). Hence, since elast is the last L-event in I B , by Observation C.1.6, L = (ullo, ptr) from elast onwards in I B . Thus, since pmin executes line 14 after elast during I, we have that pmin read (ullo, ptr) from L on line 14 during I. So, since pmin executes line 25 during I at T 25 , we have that its first parameter is (ullo, ptr). Therefore, since pmin ’s execution of line 25 at T 25 is unsuccessful, we have that L ̸= (ullo, ptr) at T 25 . However, since T 25 > elast and L = (ullo, ptr) from elast onwards in I B , we have that L = (ullo, ptr) at T 25 , a contradiction. Case 2.2. pmin executes line 27 during I. Let T 27 be the time of pmin ’s execution of line 27 during I. Since pmin executes line 14 during I after T , we have that pmin executes line 22 during I after T and T < T 27 . Hence, since A = v from T onwards in I B , we have that pmin read v from A on line 22 during I. Thus, the first parameter of pmin ’s execution of line 27 during I at T 27 is v. If this execution is unsuccessful, it follows that A ̸= v at T 27 , and since T < T 27 , we have that A ̸= v some time after T . However, A = v from T onwards in I B , and so this is impossible. Hence, pmin ’s execution of line 27 during I at T 27 is successful. Since this execution is during Imin , by Observation C.4.33, it sets A = vmin . Hence, A = vmin at T 27 , and since T < T 27 , we have that A = vmin some time after T . Therefore, since v = ((t, ∗), ∗) for some t < t(I(opxmin )), and vmin = ((t(I(opxmin )), ∗), ∗), we have that v ̸= vmin , and so A ̸= v some time after T . However, A = v from T onwards in I B , a contradiction. Claim C.4.38.1 Claim C.4.38.2. A = vmin at some time T2 ≥ T1 .

163

Proof. Since pmin takes infinitely many steps in Lmin , we have that pmin executes line 21 in Lmin at some time T2 ≥ T1 . Hence, since pmin ’s execution of line 21 at T2 is in Lmin , and Lmin is in Imin , by Observation C.4.33, pmin ’s execution of line 21 at T2 tries to set A = vmin . If this GCAS returns true, then A = vmin at T2 as wanted. Otherwise, this GCAS returns false, so A = v at T2 such that v ≤ vmin . However, since this GCAS is at T2 ≥ T1 , vmin = ((t(I(opxmin )), ∗), ∗), and the left component of A.ullo is always an integer greater than 0 (because it is initially zero, and is only set to the response of line 10), by Claim C.4.38.1, v ≥ vmin . Hence, v = ((t, ∗), ∗) for some t such that t ≤ t(I(opxmin )) and t ≥ t(I(opxmin )), and so t = t(I(opxmin )). Since A = v at T2 , it suffices to prove that v = vmin . Since t(I(opxmin )) is the response pmin received on line 10 during Imin , by the initialization of C, we have that t(I(opxmin )) > 0, and so t > 0. Thus, since A is initially ((0, Noop), Null) and A = v = ((t, ∗), ∗) at T2 , we have that A was set to v before T2 . Hence, by Observation C.1.6, some A-event set A = v before T2 , and so by Definition C.1.5 some execution e1 of line 21 or line 27 set A = v. Let e2 be pmin ’s execution of line 21 at T2 which tries to set A = vmin . Since v = ((t, ∗), ∗), vmin = ((t(I(opxmin )), ∗), ∗), and t = t(I(opxmin )), by Lemma C.1.17, we have that e1 and e2 are executed by the same process during the same invocation of the DoLowLevelOp procedure. Hence, since e2 is executed by pmin during Imin , we have that e1 is also executed by pmin during Imin . Thus, by Observation C.4.33, e1 sets A = vmin . Therefore, since by definition e1 sets A = v, we have that v = vmin as required. Claim C.4.38.2 We now complete the proof of Proposition C.4.38. Since by assumption for all times there exists a later time when A ̸= vmin , we have that there is a time T3 > T2 where A ̸= vmin at T3 . Without loss of generality, suppose this is the first time after T2 where A ̸= vmin . For A ̸= vmin at T3 , a process p performed a successful execution e of line 21 or line 27 during some invocation I of the DoLowLevelOp which set A = v for some v ̸= vmin at T3 . Since p executed e during I, we have that v = ((t, ∗), ∗) where t was the response p received on line 10 during I. Hence, t > 0. Thus, since T3 > T2 ≥ T1 , and A = ((t, ∗), ∗) at T3 , by Claim C.4.38.1, t ≥ t(I(opxmin )), and so v ≥ vmin . So, since T3 is the first time after T2 where A ̸= vmin , it follows that e could not have been on line 21. Hence, e was on line 27. Let I ′ be the iteration of the loop on line 13 that p executed e during. Since T3 is the first time after T2 where A ̸= vmin and e is a successful execution of line 27, we have that p read vmin from A on line 22 during I ′ ; say at time T 22 . Therefore, since e is an execution of line 27 during I ′ , we have that p received Done on line 23 during I ′ . However, since p read vmin from A on line 22 during I ′ and by Proposition C.4.34 L ̸= vmin throughout I B , by Lemma C.4.28, p does not received Done on line 23 during I ′ , a contradiction. Proposition C.4.38 Theorem C.4.39. B is wait-free. Proof. Suppose, for contradiction, B is not wait-free. Hence, there is an implementation history of B with an operation execution that is stuck. Let I B , the history defined at the beginning of Appendix C.4, be this history. Consider the value vmin . By Proposition C.4.38 A = vmin from some time T onwards in I B , and so by Proposition C.4.36, L = vmin at some time in I B . However, by Proposition C.4.34, L ̸= vmin throughout I B , a contradiction. Theorem C.4.39

C.5

B Correctly Manages Cells and is Space-Efficient

Throughout this section, I B refers to an arbitrary implementation history, i.e., all statements that refer to I B begin with “for every implementation history I B of B” which is omitted for brevity. The goal of this section is to prove the following two theorems. Theorem (B Correctly Manages Cells). For every ptr ∈ C the following are true.

164

1. There is at most one AllocateCell operation whose response is ptr, and at most one FreeCell(ptr) operation in I B . 2. If there is a FreeCell(ptr) operation in I B , then it is after an AllocateCell operation whose response is ptr. 3. Every operation on an object of the cell pointed to by ptr in I B is after an AllocateCell operation whose response is ptr, and is before any FreeCell(ptr) operation. Theorem (B is Space-Efficient). Suppose I B is finite. Let Allocate(I B ) be the set of pointers which have been allocated in I B , i.e., ptr ∈ Allocate(I B ) if and only if there is an AllocateCell operation in I B with response ptr. Likewise, let F ree(I B ) be the set of pointers which have been freed in I B , i.e., ptr ∈ F ree(I B ) if and only if there is a FreeCell(ptr) operation in I B . Then, |Allocate(I B ) \ F ree(I B )| ≤ 6c + 1 where c is the point contention in I B . C.5.1

At most one FreeCell operation per pointer

The main goal of this section is to prove the first two bullets of the B correctly manages cells theorem. We begin by proving some basic properties of successful list-add and list-remove attempts for a given pointer, which are used extensively throughout this section. Lemma C.5.1. There is at most one successful list-add attempt for ptr in I B . Proof. Suppose, for contradiction, there are at least two successful list-add attempts for ptr in I B ; say a1 and a2 such that a1 < a2 . Hence, there are two successful list-add attempts for ptr in I B . Let e1 and e2 be there corresponding L-events, so e1 < a1 . Hence, by Corollary C.1.37, e1 and e2 are both L-add events for ptr. Thus, since by Lemma C.2.30 P (I B ) holds, we have that e1 = e2 = e. Hence, since e1 < a1 and a1 < a2 , by transitivity, e < a1 < a2 . Furthermore, e is the corresponding L-event for a2 . Hence, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Corollary C.2.2, e is the last L-event before a2 in I B , and so e is the last L-event in Iainclude : the prefix of I B up to 2 and including a2 . Therefore, since e is an L-add event for ptr (because e1 = e2 = e), and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.3, there is at most one successful list-add attempt for ptr from e onwards in Iainclude . However, since e < a1 < a2 , there are two successful list-add attempts 2 for ptr from e onwards in Iainclude , a contradiction. Lemma C.5.1 2 The next lemma and its proof are the same as this one, except it’s for list-remove attempts. Lemma C.5.2. There is at most one successful list-remove attempt for ptr in I B . Proof. Suppose, for contradiction, there are at least two successful list-remove attempts for ptr in I B ; say a1 and a2 such that a1 < a2 . Hence, there are two successful list-remove attempts for ptr in I B . Let e1 and e2 be there corresponding L-events, so e1 < a1 . Hence, by Corollary C.1.37, e1 and e2 are both L-remove events for ptr. Thus, since by Lemma C.2.30 P (I B ) holds, we have that e1 = e2 = e. Hence, since e1 < a1 and a1 < a2 , by transitivity, e < a1 < a2 . Furthermore, e is the corresponding L-event for a2 . Hence, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Corollary C.2.2, e is the last L-event before a2 in I B , and so e is the last L-event in Iainclude : 2 the prefix of I B up to and including a2 . Therefore, since e is an L-remove event for ptr (because e1 = e2 = e), and P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.5, there is at most one successful list-remove attempt for ptr from e onwards in Iainclude . However, since e < a1 < a2 , there are two 2 successful list-remove attempts for ptr from e onwards in Iainclude , a contradiction. Lemma C.5.2 2 Lemma C.5.3. If there is a successful list-add attempt aadd for ptr in I B and a successful listremove attempt aremove for ptr in I B , then aadd is before aremove . 165

Proof. Since by Lemma C.2.30 R(I B ) holds, by Lemma C.1.120, there is a successful list-add attempt for ptr before aremove , which must be aadd by Lemma C.5.1. Lemma C.5.3 We now prove the first bullet of the B correctly manages cells theorem, i.e., for every ptr ∈ C, there is at most one FreeCell(ptr) operation in I B . The strategy for doing so is to prove that there is at most one revocation event for ptr whose response is −1 in I B . As we will see, this is a consequence of the following lemma. Lemma C.5.4. There is at most one acquire-copy event for ptr in I B . Proof. Suppose, for contradiction, there are two acquire-copy events for ptr in I B ; say e1 and e2 . Let p1 (resp. p2 ) be the process that executed e1 (resp. e2 ) and let I1 (resp. I2 ) be the invocation of the DoRemoveCell procedure that e1 (resp. e2 ) was executed during. Hence, since by Definition C.1.5 e1 and e2 are distinct executions of line 62 and line 62 is executed at most one per invocation of the DoRemoveCell procedure, we have that I1 ̸= I2 . By Lemma C.1.95, p1 (resp. p2 ) performed a successful list-remove attempt a1 (resp. a2 ) for ptr during I1 (resp. I2 ). Since a1 was executed during I1 , a2 was executed during I2 , and I1 ̸= I2 , we have that a1 ̸= a2 . Therefore, there are two successful list-remove attempts for ptr in I B . However, by Lemma C.5.2, there is at most one successful list-remove attempt for ptr in I B , a contradiction. Lemma C.5.4 Proposition C.5.5. There is at most one revocation event for ptr in I B whose response is −1. Proof. Suppose, for contradiction, there are at least two revocation events for ptr in I B whose responses are −1; say e1 and e2 such that e1 < e2 . Hence, by Lemma C.1.97 ptr ∈ C, and so (∗ptr).revocations is initially 0. Furthermore, by Observation C.1.6, the only steps that change the value of (∗ptr).revocations are acquire-copy events for ptr and revocation events for ptr. Hence, since (∗ptr).revocations is initially 0, each revocation event for ptr increases the value of (∗ptr).revocations by 1, and the response of e1 is −1, we have that there is an acquire-copy event e′1 for ptr before e1 . Since the response of e1 is −1 and e1 is a revocation event for ptr, we have that (∗ptr).revocations = 0 at e1 . Thus, since e1 < e2 , each revocation event for ptr increases the value of (∗ptr).revocations by 1, and the response of e2 is −1, we have that there is an acquire-copy event e′2 for ptr between e1 and e2 . Therefore, since e′1 < e1 and e1 < e′2 , we have that e′1 ̸= e′2 , and so there are two acquire-copy events for ptr in I B . However, by Lemma C.5.4, there is at most one acquire-copy event for ptr in I B , a contradiction. Proposition C.5.5 Lemma C.5.6. There is at most one FreeCell(ptr) operation in I B . Proof. Suppose, for contradiction, there are at least two FreeCell(ptr) operations in I B ; say at time T1 and T2 . Let p1 (resp. p2 ) be the process that executed the FreeCell operation at T1 (resp. T2 ) and let I1 (resp. I2 ) be the invocation of the Relinquish procedure that p1 (resp. p2 ) executed the step at T1 (resp. T2 ) during. Hence, since T1 ̸= T2 , and there is at most one execution of the FreeCell operation during an invocation of the Relinquish procedure, we have that I1 ̸= I2 . Furthermore, p1 (resp. p2 ) found the condition on line 114 during I1 (resp. I2 ) to be true. Let e1 (resp. e2 ) be the execution of line 113 during I1 (resp. I2 ). Since the FreeCell operation at T1 (resp. T2 ) has parameter ptr, it follows that e1 (resp. e2 ) is of the form F&A((∗ptr).revocations, 1), so by Definition C.1.5, e1 (resp. e2 ) is a revocation event for ptr. Hence, since p1 (resp. p2 ) found the condition on line 114 to be true at e1 (resp. e2 ), we have that the response of e1 (resp. e2 ) is −1. Since e1 is an execution of line 113 during I1 , e2 is an execution of line 113 during I2 , and I1 ̸= I2 , we have that e1 ̸= e2 . Therefore, there are two revocation events for ptr in I B whose response is −1. However, by Proposition C.5.5, there is at most one revocation event for ptr in I B whose response is −1, a contradiction. Lemma C.5.6 166

We now prove the second bullet of the B correctly manages cells theorem. Lemma C.5.7. If there is a FreeCell(ptr) operation in I B , then it is after an AllocateCell operation whose response is ptr. Proof. Consider a FreeCell(ptr) operation in I B at time T . Hence, by Corollary C.1.127, there is an L-remove event e for ptr before T . Thus, by Corollary C.1.24, there is an A-remove event e′ for ptr before e. So, by Definition C.1.5, this A-remove event was executed during some invocation of the DoLowLevelOp procedure with a second parameter of ptr. Hence, there is an AllocateCell operation whose response is ptr before e′ . Therefore, since e′ < e, and e < T , by transitivity, there is an AllocateCell operation whose response is ptr before T as wanted. Lemma C.5.7 C.5.2

Tracking acquisitions and revocations per operation execution

Over the next few sections, we prove the third bullet of the B correctly manages cells theorem and then prove that B is space-efficient. Both of these theorems require proving some properties about the number of acquisitions and revocations performed by the process that executed opx during some operation execution opx. These properties are informally stated below. • The number of successful list-acquire-next attempts for ptr is larger than the number of revocation events for ptr (Corollary C.5.16). • A process only performs an operation on an object of a cell when it has the right to use it (Lemma C.5.21). • The number of successful list-acquire-next attempts for ptr is equal to the number of revocation events for ptr at the time an operation execution completes (Corollary C.5.24). • Each process has the right to use at most three cells at all times (Lemma C.5.26). We note that the first two properties are used in the proof of the third bullet of the B correctly manages cells theorem, and all four properties are used in the proof of the B is space-efficient theorem. Formally, all four of these properties are stated with respect to R defined below. Definition C.5.8. For every operation execution opx in I B , we define R(I B , opx, ptr) as the number of successful list-acquire-next attempts for ptr minus the number of revocation events for ptr performed by the process that executed opx during opx in I B . Note that, since B is wait-free by Theorem C.4.39, we have that the process that executed opx performed a finite number of successful list-acquire-next attempts for ptr and revocation for ptr during opx (otherwise the process that executed opx would perform infinitely many steps during opx without completing it, implying B is not wait-free), so R(I B , opx, ptr) is always an integer. The main utility we get by proving bounds on R is that it implies bounds on the total difference between successful list-acquire-next attempts and revocation events in I B . We formalize this below. Definition C.5.9. Let A(I B , ptr) (resp. X(I B , ptr)) denote the number of successful list-acquirenext attempts (resp. revocation events) for ptr in I B . Note that unlike R, A and X may be infinite when I B is infinite, in which case they equal ∞. By Definition C.5.8 and Definition C.5.9, we have the following. Observation C.5.10. If I B is finite, then X

A(I B , ptr) − X(I B , ptr) =

opx is an operation execution in I B

167

R(I B , opx, ptr).

We now prove the four properties mentioned at the start of the section. We start with a few observations regarding the sequence of successful list-acquire-next attempts and revocation events performed during an invocation I of the Acquire, DoRemoveCell, and DoAddCell procedures. These observations are a consequence of the order in which the AcquireNext procedure and the Relinquish procedure are invoked during I. Furthermore, these sequences are necessarily finite by the fact that B is wait-free by Theorem C.4.39. Observation C.5.11. Consider any invocation I of the Acquire procedure by process p in I B . At any time T in I B , the sequence of successful list-acquire-next attempts and revocation events performed by p during I is some prefix of the following sequence, and is the entire sequence if p exited I by time T . First is a successful list-acquire-next attempt for ptr1 . Then, the following pattern occurs for i = 1, . . . , n where n ≥ 0: a successful list-acquire-next attempt for ptri+1 followed by a revocation event for ptri . Finally, if p exits I with response Found, then ptrn+1 is the second parameter of I, and otherwise, the last element of this sequence is a revocation event for ptrn+1 . Observation C.5.12. Consider any invocation I of the DoRemoveCell procedure by process p. At any time T in I B , the sequence of successful list-acquire-next attempts and revocation events performed by p during I, other than those performed during the SetResponse procedure on line 44, is some prefix of the following sequence, and is the entire sequence if p exited I by time T . First is a successful list-acquire-next attempt for ptr1 . Then, either (1) the next is a revocation event for ptr1 , and there are no other successful list-acquire-next attempts and revocation events performed by p during I, or (2) the next is a successful list-acquire-next attempt for ptr2 and the following pattern occurs for i = 1, . . . , n where n ≥ 0: a successful list-acquire-next attempt for ptri+2 followed by a revocation event for ptri ; finally, the last two elements of this sequence are a revocation event for ptrn+1 and a revocation event for ptrn+2 . Observation C.5.13. Consider any invocation I of the DoAddCell procedure by process p. At any time T in I B , the sequence of successful list-acquire-next attempts and revocation events performed by p during I, other than those performed during the SetResponse procedure on line 42, is some prefix of the following sequence, and is the entire sequence if p exited I by time T . First is a successful list-acquire-next attempt for ptr1 . Then, the following pattern occurs for i = 1, . . . , n where n ≥ 0: a successful list-acquire-next attempt for ptri+1 followed by a revocation event for ptri . Finally, the last element of this sequence is a revocation event for ptrn+1 . We now prove the first property of this section, which is, with the exception of the revocation event performed during the Relinquish procedure invoked on line 7, R is always non-negative. We first note an immediate consequence of Definition C.5.8. Observation C.5.14. For every operation execution opx in I B if the only step by the process that executed opx during opx in I B is the invocation step of opx, then R(I B , opx, ptr) = 0 for every ptr. Lemma C.5.15. Consider any operation execution opx in I B such that the process that executed opx has not executed line 7 during opx in I B . Then, R(I B , opx, ptr) ≥ 0 for every ptr. Proof. Let p be the process that executed opx. Suppose, for contradiction, R(I B , opx, ptr) < 0 for some ptr. Hence, by Definition C.5.8, p performed a revocation event for ptr during opx in I B , so there is an invocation step for opx in I B . Thus, by Observation C.5.14 R(I invoke , opx, ptr) = 0 where I invoke is the prefix of I B up to and including the invocation step of opx. So, since R(I B , opx, ptr) < 0, it follows that there is a finite prefix I of I B where R(I, opx, ptr) < 0 and for every proper prefix I ′ of I R(I ′ , opx, ptr) ≥ 0. Let I − be the prefix of I up to but excluding the last step of I. Hence, 168

R(I − , opx, ptr) ≥ 0, and since R(I, opx, ptr) < 0, we have that R(I − , opx, ptr) = 0. So, the last step of I is a revocation event for ptr by p during opx. Hence, by Definition C.1.5, the last step of I is an execution of line 113 during an invocation I of the Relinquish procedure by p. Thus, since I − is a prefix of I excluding the last step, we have that p invoked I during I − . Since p has not executed line 7 during opx in I B , and I is a prefix of I B , we have that p invoked I during an invocation I + of one of the following procedures: DoAddCell, DoRemoveCell, SetResponse, IsDone, or Acquire. Case 1. I + is an invocation of the DoAddCell, DoRemoveCell, or Acquire procedure. Hence, since the last step of I is a revocation event for ptr by p during I (and thus I + ), by Observations C.5.13, C.5.12, and C.5.11, the number of successful list-acquire-next attempts for ptr minus the number of revocation events for ptr by p during I + in I is non-negative. Therefore, since R(I, opx, ptr) < 0, it follows that R(I ′ , opx, ptr) < 0 for some proper prefix I ′ of I. However, for every proper prefix I ′ of I R(I ′ , opx, ptr) ≥ 0, a contradiction. Case 2. I + is an invocation of the SetResponse or IsDone procedure. Hence, since the last step of I is a revocation event for ptr by p during I, we have that p invoked I on either line 78 or line 90 depending on which procedure I + is. Thus, p invoked the Acquire procedure with a second parameter of ptr during I + before the end of I; denote this invocation by I acq . Furthermore, by the conditions on lines 76 and 90, we have that the response of I acq is Found. So, by Observation C.5.11, there is a successful list-acquire-next attempt a for ptr by p during I acq such that there is no revocation event for ptr after a by p during I acq . Therefore, since there are no revocation events by p during I + between the end of I acq and the last step of I, we have that from a onwards in I there are no revocation events for ptr by p. We now claim that R(Iainclude , opx, ptr) ≥ 1 where Iainclude is the prefix of I up to and including a. Suppose, for contradiction, R(Iainclude , opx, ptr) < 1. Hence, since Iainclude is a proper prefix of I, by the minimality of I, R(Iainclude , opx, ptr) ≥ 0, and so R(Iainclude , opx, ptr) = 0. Thus, since a is a successful list-acquire-next attempt for ptr by p during opx, we have that R(Iaexclude , opx, ptr) = −1 where Iaexclude is the prefix of I up to but excluding a. However, since Iaexclude is a proper prefix of I, by the minimality of I, R(Iaexclude , opx, ptr) ≥ 0, a contradiction. We now finish the proof of Case 2. Since from a onwards in I there are no revocation events for ptr by p and R(Iainclude , opx, ptr) ≥ 1, we have that R(I − , opx, ptr) ≥ 1. However, R(I − , opx, ptr) = 0, a contradiction. Lemma C.5.15 Lemma C.5.15 implies the first property, which is stated formally below. Corollary C.5.16. Consider any operation execution opx in I B . The following are true. 1. If the process that executed opx executed line 2 during opx with response ptropx , then for every ptr ̸= ptropx R(I B , opx, ptr) ≥ 0, and R(I B , opx, ptropx ) ≥ −1. 2. Otherwise, R(I B , opx, ptr) ≥ 0 for every ptr. We now prove the second property of this section, which is, roughly speaking, that the process that executed opx only performs an operation on an object of the cell when it has the right to use it. We start with a few observations regarding R at the beginning of every iteration of the loops on lines 30, 46, and 94. By a straightforward induction, each of these observations follows. Observation C.5.17. If the last step of I B is an execution of line 30 during some invocation I of the DoAddCell procedure during some operation execution opx, and the value ptr of the local variable curr ptr in I at the end of I B is in C, then R(I B , opx, ptr) ≥ 1. 169

Observation C.5.18. If the last step of I B is an execution of line 46 during some invocation I of the DoRemoveCell procedure during some operation execution opx, and the value ptr of the local variable curr ptr (resp. prev ptr) in I at the end of I B is in C, then R(I B , opx, ptr) ≥ 1. Observation C.5.19. If the last step of I B is an execution of line 94 during some invocation I of the Acquire procedure during some operation execution opx, and the value ptr of the local variable curr ptr in I at the end of I B is in C, then R(I B , opx, ptr) ≥ 1. Before proving the second property, we need one more fact about the special case of line 88. Proposition C.5.20. If a process p executes line 88 during I B , then p received response Found on line 80 during the same invocation of the IsDone procedure. Proof. Suppose, for contradiction, some process p executes line 88 during some invocation I of the IsDone procedure, and received a response other than Found on line 80 during I. Since p executes line 88 during I, by the condition on line 81, we have that p did not receive L-Changed on line 80 during I. Hence, since the Acquire procedure returns either Found, L-Changed, or NotFound, we have that p received NotFound on line 80 during I. Let ulloA (resp. ptrA ) be the second (resp. third) parameter of I. Hence, p read (ulloA , ptrA ) from A on line 22 during some iteration I 13 of the loop on line 13; say at time T 22 . Furthermore, since p executes line 88 during I, by the condition on line 87, ulloA = (∗, ⟨Apply&CopyResponse, ∗⟩). Thus, since A is initially ((0, Noop), Null), we have that A was set to (ulloA , ptrA ) before T 22 , and so by Observation C.1.6, some A-event set A = (ulloA , ptrA ) before T 22 . So, by Lemma C.1.14, ptrA ∈ C. Therefore, since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold and p received NotFound on line 80 during I (or equivalently on line 80 during I 13 ), by Lemma C.2.19, ptrA ∈ / List(I) where I is the prefix of I B up to and including the p’s execution of line 14 during I 13 . Let eA be the last A-event that set A = (ulloA , ptrA ) before T 22 . Since ulloA = (∗, ⟨Apply&CopyResponse, ∗⟩), by Definition C.1.5, eA is an A-apply event. Furthermore, since p read (ulloA , ptrA ) from A at T 22 , we have that eA is the last A-event before T 22 . By Definition C.1.5, eA was executed by some process q during an invocation of the DoLowLevelOp procedure with parameters (⟨Apply&CopyResponse, ∗⟩, ptrA ). Hence, before eA , q exited the DoLowLevelOp procedure with parameters (AddCell, ptrA ). Thus, since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.105, there is an L-add event eL for ptrA before q exited this invocation of the DoLowLevelOp procedure (and thus eA ). Therefore, since eA < T 22 , by transitivity, eL < T 22 . Let T 14 be the time p executes line 14 during I 13 and let T 105 be the last time p executes line 105 during the Acquire procedure on line 80 during I (since p exits the Acquire procedure on line 80 during I, by Corollary C.1.93, T 105 is well-defined), so T 22 ∈ [T 14 , T 105 ]. Hence, since P (I B ) holds and the Acquire procedure on line 80 during I (equivalently I 13 ) exits with response NotFound, by Lemma C.1.112, there are no L-events throughout [T 14 , T 105 ] during I B . Thus, since eL < T 22 and T 22 ∈ [T 14 , T 105 ], we have that eL < T 14 . Therefore, since I is the prefix of I B up to and including p’s execution of line 14 during I 13 , we have that eL is in I. Since eL is an L-add event for ptrA , eL is in I, and ptrA ∈ / List(I), by Definition C.1.7, there is an L-remove event e for ptrA in I. Hence, by Corollary C.1.24, there is an A-remove event e′ for ptrA before e. Since e is in I, and the time of the last step of I is T 14 , we have that e ≤ T 14 , and so since e′ < e, by transitivity, e′ < T 14 . Hence, since T 14 < T 22 , by transitivity, e′ < T 22 . Thus, since eA is the last A-event before T 22 , we have that e′ ≤ eA , and since eA is an A-apply event and e′ is an A-remove event, we have that e′ ̸= eA , and so e′ < eA . Therefore, there is an A-remove event for ptrA in I B such that after e′ there is an A-apply event for ptrA . However, by Lemma C.1.20, there are no A-apply events for ptrA from e′ onwards in I B , a contradiction. Proposition C.5.20 The second property is formally stated below. 170

Lemma C.5.21. If the last step of I B is an operation on an object of the cell pointed to by ptr ∈ C during some operation execution opx, then the following are true: 1. if the last step of I B is on line 5, 12, 13, or 113 during an invocation of the Relinquish procedure invoked on line 7, then R(I − , opx, ptr) ≥ 0; 2. otherwise, R(I − , opx, ptr) ≥ 1 where I − is the prefix of I B excluding the last step. Proof. Let p be the process that executed opx. Observe that the last step of I B is either on line 5, 12, 13, 34, 36, 53, 54, 55, 56, 58, 61, 62, 77, 88, 104, 109, and 113. The proof is by cases. Case 1. The last step of I B is either on line 5, 12, or 13. Hence, p executed line 2 during opx with response ptr, so we must show that R(I − , opx, ptr) ≥ 0. This follows from Lemma C.5.15. Case 2. The last step of I B is either on line 34 or 36. Hence, p performed the last step of I B during some invocation I of the DoAddCell procedure, and ptr is the value of the local variable curr ptr in I at the end of I B . Let I ′ be the prefix of I B up to and including p’s last execution of line 30. Hence, this execution is during I, and the value of the local variable curr ptr at the end of I ′ is ptr. Thus, since ptr ∈ C, by Observation C.5.17, R(I ′ , opx, curr ptr) ≥ 1. So, since there are no successful list-acquire-next attempts by p between the end of I ′ and I B , we have that R(I − , opx, ptr) ≥ 1 as wanted. Case 3. The last step of I B is either on line 53, 54, 55, 56, or 62. Let I ′ be the prefix of I B up to and including p’s last execution of line 46 before the last step of I. Since ptr ∈ C, by Observation C.5.18, if ptr is the value of curr ptr at the end of I ′ , then R(I ′ , opx, ptr) ≥ 1. Since this is the last execution of line 46 before the last step of I B , and the last step of I B is either on line 53, 54, 55, 56, or 62, we have that p found the condition on line 46 at the end of I ′ to be false and curr ptr = ptr at the end of I ′ . Hence, R(I ′ , opx, ptr) ≥ 1. So, since there are no successful list-acquire-next attempts by p between the end of I ′ and I B , we have that R(I − , opx, ptr) ≥ 1 as wanted. Case 4. The last step of I B is either on line 58 or 61. Let I ′ be the prefix of I B up to and including p’s last execution of line 46 before the last step of I. Since ptr ∈ C, by Observation C.5.18, if ptr is the value of prev ptr at the end of I ′ , then R(I ′ , opx, ptr) ≥ 1. Since this is the last execution of line 46 before the last step of I B , and the last step of I B is either on line 58 or 61, we have that p found the condition on line 46 at the end of I ′ to be false and prev ptr = ptr at the end of I ′ . Hence, R(I ′ , opx, ptr) ≥ 1. So, since there are no successful list-acquire-next attempts by p between the end of I ′ and I B , we have that R(I − , opx, ptr) ≥ 1 as wanted. Case 5. The last step of I B is on line 77. Let I be the invocation of the SetResponse procedure that p performed the last step of I B during. Since the last step of I is on line 77 and is an operation on an object of the cell pointed to by ptr, we have that the response of the Acquire procedure during I is Found and the second parameter of I is ptr. Hence, by Observation C.5.11, p performed a successful list-acquire-next attempt a for ptr such that p did not perform a revocation event for ptr after a during the Acquire procedure during I. Thus, by Lemma C.5.15, R(Ia , opx, ptr) ≥ 0 where Ia is the prefix of I B up to and including a, and since a is a successful list-acquire-next attempt for ptr, it follows that R(Ia , opx, ptr) ≥ 1 171

(otherwise R would be less than 0 at the step before a). Therefore, since p did not perform a revocation event for ptr after a during the Acquire procedure during I, and p does not perform any successful list-acquire-next attempts or revocation events during I, other than those performed during the Acquire procedure during I, we have that R(I − , opx, ptr) ≥ 1 as wanted. Case 6. The last step of I B is on line 88. Let I be the invocation of the IsDone procedure that p performed the last step of I B during. Since the last step of I B is on line 88 and is an operation on an object of the cell pointed to by ptr, by Proposition C.5.20, the response of the Acquire procedure during I is Found. Furthermore, the third parameter of I is ptr. Hence, by Observation C.5.11, p performed a successful list-acquire-next attempt a for ptr such that p did not perform a revocation event for ptr after a during the Acquire procedure during I. Since a is a successful list-acquire-next attempt for ptr, by Lemma C.5.15, R(Ia , opx, ptr) ≥ 1 where Ia is the prefix of I B up to and including a. Therefore, since p did not perform a revocation event for ptr after a during the Acquire procedure during I, and p does not perform any successful list-acquire-next attempts or revocation events during I, other than those performed during the Acquire procedure during I, we have that R(I − , opx, ptr) ≥ 1. Case 7. The last step of I B is either on line 104 or 109. Let I be the invocation of the AcquireNext procedure that p performed the last step of I during. Since the last step of I B is an operation on an object of the cell pointed to by ptr, we have that the second parameter of I is ptr. Hence, since I is invoked on either line 31, 47, or 95, we have that p executed line 30, 46, or 94, respectively, immediately before invoking I. Let I ′ be the prefix of I B up to and including p’s execution of this line. Hence, since the second parameter of I is ptr, by Observation C.5.17, C.5.18, and C.5.19, we have that R(I ′ , opx, ptr) ≥ 1. Therefore, since p does not perform any revocation events during I, we have that R(I − , opx, ptr) ≥ 1 as wanted. Case 8. The last step of I B is on line 113. Hence, since the last step of I B is an operation on an object of the cell pointed to by ptr, we have that the last step of I B is a revocation event for ptr by p during opx. Let I be the invocation of the Relinquish procedure that p performed the last step of I B during. First suppose that p did not invoke I on line 7, so we must prove that R(I − , opx, ptr) ≥ 1. Suppose, for contradiction, R(I − , opx, ptr) < 1. Since p did not invoke I on line 7, by Lemma C.5.15, R(I − , opx, ptr) ≥ 0. Hence, since R(I − , opx, ptr) < 1, we have that R(I − , opx, ptr) = 0. Therefore, since I − is the prefix of I B excluding the last step, and the last step of I B is a revocation event for ptr by p during opx, we have that R(I B , opx, ptr) = −1. However, since p has not invoked the Relinquish procedure on line 7 during opx in I B , by Lemma C.5.15, R(I B , opx, ptr) ≥ 0, a contradiction. Now suppose that p invoked I on line 7, so we must prove that R(I − , opx, ptr) ≥ 0. Suppose, for contradiction, R(I − , opx, ptr) < 0. By Corollary C.5.16 R(I − , opx, ptr) ≥ −1, so R(I − , opx, ptr) = −1. Therefore, since I − is the prefix of I B excluding the last step, and the last step of I B is a revocation event for ptr by p during opx, we have that R(I B , opx, ptr) = −2. However, by Corollary C.5.16 R(I B , opx, ptr) ≥ −1, a contradiction. Lemma C.5.21 We now prove the third property of this section, which is, roughly speaking, with the exception of the pointer allocated on line 2 during opx, R is 0 for every pointer once opx is complete. We start by proving that individual procedures “clean up” all the pointers that they allocated. Proposition C.5.22. Consider any operation execution opx in I B and any invocation I of the DoAddCell, DoRemoveCell, DoApply&CopyResponse, SetResponse, or IsDone procedure that the 172

process that executed opx exited during opx. Let I invoke (resp. I exit ) be the prefix of I B up to and including the first (resp. last) step of I. If R(I invoke , opx, ptr) = 0 for every ptr, then R(I exit , opx, ptr) = 0 for every ptr. Proof. Let p be the process that executed opx. We consider each case of I separately. Case 1. I is an invocation of the SetResponse or IsDone procedure. Since p exits I, we have that p exited the Acquire procedure on line 75 or line 80 during I with response status (depending on I). Denote this invocation of the Acquire procedure by I acq . If status ̸= Found, then by Observation C.5.11, the number of successful list-acquire-next attempts for ptr by p during I acq is equal to the number of revocation events for ptr by p for every ptr during I acq . Furthermore, since status ̸= Found, observe that p does not perform any successful list-acquire-next attempts or revocation events for any pointer during I, other than those performed during I acq . Therefore, since R(I invoke , opx, ptr) = 0 for every ptr, we have that for R(I exit , opx, ptr) = 0 for every ptr as wanted. Now suppose status = Found and let target ptr be the second parameter of I acq . By Observation C.5.11, for every ptr ̸= target ptr the number of successful list-acquire-next attempts for ptr by p during I acq is equal to the number of revocation events for ptr by p during I acq , and the number of successful list-acquire-next attempts for target ptr is one greater than the number of revocation events for target ptr by p during I acq . Since there is a successful list-acquire-next attempt for target ptr, by Lemma C.1.90, target ptr ∈ C. Hence, since status = Found, p does not perform any successful list-acquire-next attempts for any pointer during I, other than those performed during I acq , and p only performs a single revocation event for target ptr during I, other than those performed during I acq . Therefore, since R(I invoke , opx, ptr) = 0 for every ptr, we have that R(I exit , opx, ptr) = 0 for every ptr as wanted. Case 2. I is an invocation of the DoApply&CopyResponse procedure. Observe that p does not perform any successful list-acquire-next attempts or revocation events other than those performed during the SetResponse procedure on line 73 during I. Therefore, this case reduces to Case 1. Case 3. I is an invocation of the DoRemoveCell procedure. Since R(I invoke , opx, ptr) = 0 for every ptr, by Case 1, R(I, opx, ptr) = 0 for every ptr where I is the prefix of I B up to and including the last step by p of the SetResponse procedure on line 44 during I. Then, by Observation C.5.12, the number of successful list-acquire-next attempts for ptr by p during I is equal to the number of revocation events for ptr by p during I for every ptr. Therefore, R(I exit , opx, ptr) = 0 for every ptr as wanted. Case 4. I is an invocation of the DoAddCell procedure. Since R(I invoke , opx, ptr) = 0 for every ptr, and by Observation C.5.13 the number of successful list-acquire-next attempts for ptr by p during I is equal to the number of revocation events for ptr by p during I for every ptr, other than those performed during the SetResponse procedure on line 42 during I, we have that R(I, opx, ptr) = 0 for every ptr where I is the prefix of I B up to and including the first step by p of the SetResponse procedure on line 42 during I. Therefore, by Case 1, we have that R(I exit , opx, ptr) = 0 for every ptr as wanted. Proposition C.5.22 Since the DoLowLevelOp procedure only invokes the DoAddCell, DoApply&CopyResponse, DoRemoveCell, and IsDone procedures, Proposition C.5.22 implies the following corollary.

173

Corollary C.5.23. Consider any operation execution opx in I B and any invocation I of the DoLowLevelOp procedure that the process that executed opx exited during opx. Let I invoke (resp. I exit ) be the prefix of I B up to and including the first (resp. last) step of I. If R(I invoke , opx, ptr) = 0 for every ptr, then R(I exit , opx, ptr) = 0 for every ptr. Hence, since by Observation C.5.14 every operation execution opx starts with no successful listacquire-next attempts and no revocations events, after the third DoLowLevelOp procedure exits on line 6, there is a single revocation event for the pointer returned on line 2 during opx, and after opx completes there are no successful list-acquire-next attempts or revocation events during opx, it follows that Corollary C.5.23 implies the third property which is formally stated below. Corollary C.5.24. Consider any complete operation execution opx in I B . Hence, the process that executed opx executed line 2 during opx; say ptropx is its response. Then, R(I B , opx, ptr) = 0 for every ptr ̸= ptropx and R(I B , opx, ptropx ) = −1. We now prove the fourth and final property of this section, which is, roughly speaking, that the process that executed opx has “acquired” the right to use at most three cells at all times. Proposition C.5.25. Consider any operation execution opx in I B and any invocation I of the DoAddCell, DoRemoveCell, Acquire, and SetResponse procedure that the process that executed opx invoked during opx. Let I invoke be the prefix of I B up to and including the first step of I. Then, R(I invoke , opx, ptr) = 0 for every ptr. Proof. Let p be the process that executed opx. By Observation C.5.14 and Corollary C.5.23 we have the following. Consider any invocation I of the DoLowLevelOp procedure that p invoked during opx. Let I invoke be the prefix of I B up to and including the first step of I. Then, R(I invoke , opx, ptr) = 0 for every ptr. Hence, since the DoLowLevelOp procedure only invokes the DoAddCell, DoApply&CopyResponse, DoRemoveCell, and IsDone procedures, and the DoLowLevelOp does not perform any successful list-acquire-next attempts or revocation events except for those performed within these procedures, Proposition C.5.22 implies the following. Consider any invocation I of the DoAddCell, DoApply&CopyResponse, DoRemoveCell, and IsDone procedure that p invoked during opx. Let I invoke be the prefix of I B up to and including the first step of I. Then, R(I invoke , opx, ptr) = 0 for every ptr (*). So, what remains is to justify the claim for the Acquire and SetResponse procedures. Since the Acquire procedure is only invoked on lines 75 and 80, and we know that the claim holds at the start of every invocation of the IsDone procedure, it suffices to prove that the claim for the SetResponse procedure. Consider any invocation I of the SetResponse procedure by p during opx and let I invoke be the prefix of I B up to and including the first step of I. Observe that I was invoked on either line 42, 44, or 73. In the first case, let I ′ be the invocation of the DoAddCell procedure that I was invoked during. By (*) R(I ′ , opx, ptr) = 0 for every ptr where I ′ is the prefix of I B up to and including the first step of I ′ . Furthermore, since by Observation C.5.13 the number of successful list-acquire-next attempts and revocation events for every pointer is equal before invoking line 42 during I ′ , we have that R(I invoke , opx, ptr) = 0 for every ptr as wanted. In the second case, let I ′ be the invocation of the DoRemoveCell procedure that I was invoked during. By (*) R(I ′ , opx, ptr) = 0 for every ptr where I ′ is the prefix of I B up to and including the first step of I ′ . This immediately implies R(I invoke , opx, ptr) = 0 for every ptr because I invoke is a single step after I ′ . In the third and final case, let I ′ be the invocation of the DoApply&CopyResponse procedure that I was invoked during. By (*) R(I ′ , opx, ptr) = 0 for every ptr where I ′ is the prefix of I B up to and including the first step of I ′ . This immediately implies R(I invoke , opx, ptr) = 0 for every ptr because p does not perform any successful list-acquire-next attempts or revocation events during I ′ other than those during I. Proposition C.5.25 174

The fourth property is formalized below. Lemma C.5.26. For every operation execution opx in I B X R(I B , opx, ptr) ≤ 3. ptr

P Proof. Let p be the process that executed opx. Suppose, for contradiction, ptr R(I B , opx, ptr) > 3. Hence, by Definition C.5.8, p performed a successful list-acquire-next attempt for ptr during opx in I B , so there is an invocation step for opx in I B . Thus, by Observation C.5.14 R(I invoke , opx, ptr) = 0 where I invoke is the prefix of I B up to and including the invocation step of opx. So, since R(I B , opx, ptr) > 3, it follows that there is a finite prefix I of I B where R(I, opx, ptr) > 3 and for every proper prefix I ′ of I R(I ′ , opx, ptr) ≤ 3. Hence, the last step of I is a successful list-acquirenext attempt by p. Observe that p performed this step during an invocation of the AcquireNext procedure, which was performed during an invocation I of either the Acquire, DoRemoveCell, or DoAddCell procedure. By Proposition C.5.25, R(I invoke , opx, ptr) = 0 for every ptr where I invoke is the prefix of I B up to and including the first step of I. Therefore, since the P last step during I is during an invocation of the AcquireNext procedure invoked during I and ptr R(I, opx, ptr) > 3, we have that p performed more than three successful list-acquire-next attempts during I such that between then and the end of I, p did not perform revocation events for any of these pointers. However, since I is an invocation of either the Acquire, DoRemoveCell, or DoAddCell procedure, this is impossible by Observation C.5.11, C.5.12, and C.5.13, respectively, a contradiction. Lemma C.5.26 C.5.3

Acquire-copy events copy the total number of acquisitions

The main ingredient for proving the third bullet of the B correctly manages cells theorem, and the B is space-efficient theorem, is the following lemma. Lemma. For any acquire-copy event e for ptr in I B the following are true: 1. e = F&A((∗ptr).revocations, −(A(I B , ptr) + 1)); and 2. if I is the prefix of I B up to and including e then A(I, ptr) = A(I B , ptr). Since by Lemma C.5.4 there is at most one acquire-copy event for ptr, (1) of this lemma states that the process that performs an acquire-copy event e for ptr “knows” the total number of successful list-acquire-next attempts that will ever happen for ptr, and (2) states that all of these successful list-acquire-next attempts have already happened by the time of e. To get a sense of why this lemma is useful, we note that, roughly speaking, in conjunction with the facts proved in the last section, this lemma allows us to conclude: (1) for all times at and after a FreeCell(ptr) operation, no process has the right to access ptr; and (2) every pointer with an acquire-copy event gets freed by some time except at most some number linear in the point contention at that time. Since by Lemma C.5.21 processes only perform operations on an object of the cell pointed to by ptr if it has the right to access it, (1) implies that all operations on an object of the cell pointed to ptr are before any FreeCell(ptr) operation. This implies the third bullet of the B correctly manages cells theorem because the other requirement is proved by a simple tracing argument. Furthermore, (2) is used to complete the B is space-efficient theorem. As we will see, proving this lemma is almost entirely accomplished by proving that the acquisition counter of the cell pointed to by ptr is semantically correct, i.e., it is equal to the number of successful-list-acquire-next attempts for ptr plus one (Proposition C.5.45). Since the acquisition counter of the cell pointed to by ptr is stored in the cell preceding it in the list, we have to deal with the fact that the acquisition counter for ptr is only defined at some times (in particular, times when ptr is in the list). We deal with this issue by defining the notion of an active pointer at a particular time, and prove that if ptr is active at some time, then ptr is in the list at that time. 175

Definition C.5.27. We say ptr is active in I B if and only if there is a single successful list-add attempt for ptr in I B and no successful list-remove attempt for ptr in I B . Hence, by Lemma C.1.46, we have the following. Corollary C.5.28. If ptr is active in I B , then ptr ∈ C. We now prove that if ptr is active at some time, then ptr is in the list at that time. Lemma C.5.29. Suppose ptr is active in I B . Let a be the successful list-add attempt for ptr in I B which exists by Definition C.5.27. Then, there is an L-add event for ptr before a in I B . Proof. Let e be the corresponding L-event of a, so e < a. Hence, e is in I B . Furthermore, since a is a list-add attempt for ptr, by Corollary C.1.37, e is an L-add event for ptr. Lemma C.5.29 This implies the following. Corollary C.5.30. If I B is finite and ptr is active in I B , then there is a last L-event in I B . Proposition C.5.31. Suppose I B is finite and ptr is active in I B . Let elast be the last L-event in I B which is well-defined by Corollary C.5.30. If from elast onwards in I B there are no successful is where Ieexclude list-add or list-remove attempts, then there is an L-add event for ptr in Ieexclude last last B the prefix of I up to but excluding elast . Proof. Suppose, for contradiction, there are no L-add events for ptr in Ieexclude . Since ptr is active last B B in I , by Definition C.5.27, there is a successful list-add attempt a for ptr in I . By Lemma C.5.29, there is an L-add event eadd for ptr before a in I B . There are two cases. Case 1. eadd ̸= elast . Hence, since eadd is an L-event in I B and elast is the last L-event in I B , we have that eadd ≤ elast , and so eadd < elast . Thus, since Ieexclude is the the prefix of I B up to but excluding elast , we last exclude . However, by have that eadd is in Ielast . Therefore, there is an L-add event for ptr in Ieexclude last exclude assumption there are no L-add events for ptr in Ielast , a contradiction. Case 2. elast = eadd . Hence, since by assumption from elast onwards in I B there are no successful list-add or list-remove attempts, we have that from eadd onwards in I B there are no successful list-add or list-remove attempts. However, since eadd < a, a is in I B , and a is a successful list-add attempt, we have that from eadd onwards in I B there is a successful list-add attempt, a contradiction. Proposition C.5.31 Proposition C.5.32. Suppose I B is finite and ptr is active in I B . Let elast be the last L-event in I B which is well-defined by Corollary C.5.30. If from elast onwards in I B there are no successful list-add or list-remove attempts, then ptr is in List(Ieexclude ) exactly once where Ieexclude is the last last B prefix of I up to but excluding elast . Proof. It suffices to prove that ptr is in List(Ieexclude ) at least once because by Lemma C.2.30 last P (Ieexclude ) holds, and so by Lemma C.1.114 the elements of List(Ieexclude ) are pairwise distinct. last last exclude Suppose, for contradiction, ptr ∈ / List(Ielast ). Hence, since by Proposition C.5.31 there is an L-add event eadd for ptr in Ieexclude , by Definition C.1.7, there is a subsequent L-remove event last exclude eremove for ptr after eadd in Ielast . Since eremove is in Ieexclude and Ieexclude is a prefix of I B , we last last have that eremove is in I B . Furthermore, since Ieexclude is the prefix of I B up to but excluding last 176

elast , we have that there is a next L-event after eremove in I B ; say e. Therefore, since eremove is an L-remove event for ptr in I B and by Lemma C.2.30 R(I B ) holds, we have that there is a successful list-remove attempt for ptr in I B . However, since ptr is active in I B , by Definition C.5.27, there are no successful list-remove attempts for ptr in I B , a contradiction. Proposition C.5.32 Proposition C.5.33. Suppose I B is finite and ptr is active in I B . Let elast be the last L-event in I B which is well-defined by Corollary C.5.30. If elast is not an L-add nor an L-remove event or from elast onwards in I B there is a successful list-add or list-remove attempt, then ptr is in List(I B ) exactly once. Proof. It suffices to prove that ptr is in List(I B ) at least once because by Lemma C.2.30 P (I B ) holds, and so by Lemma C.1.114 the elements of List(I B ) are pairwise distinct. Suppose, for contradiction, ptr ∈ / List(I B ). Hence, since by Lemma C.5.29 there is an L-add event eadd for ptr in I B , by Definition C.1.7, there is a subsequent L-remove event eremove for ptr after eadd in I B . There are two cases. Case 1. eremove ̸= elast . Hence, since eremove is an L-event in I B and elast is the last L-event in I B , we have that eremove ≤ elast , and so eremove < elast . Thus, there is a next L-event after eremove in elast ; say e. Therefore, since eremove is an L-remove event for ptr in I B and by Lemma C.2.30 R(I B ) holds, we have that there is a successful list-remove attempt for ptr in I B . However, since ptr is active in I B , by Definition C.5.27, there are no successful list-remove attempts for ptr in I B , a contradiction. Case 2. eremove = elast . Hence, elast is an L-remove event, and so from elast onwards in I B there is a successful list-add or list-remove attempt. Thus, since eremove is the last L-event in I B , eremove is an L-remove event for ptr, and by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.5, from eremove onwards in I B there is at most one successful list-remove attempt for ptr and no other successful list-remove or list-add attempt for any pointer. Therefore, since from eremove onwards in I B there is a successful list-add or list-remove attempt, we have that from eremove onwards in I B there is a successful list-remove attempt for ptr. However, since ptr is active in I B , by Definition C.5.27, there are no successful list-remove attempts for ptr in I B , a contradiction. Proposition C.5.33 Proposition C.5.32 and Proposition C.5.33 cover the two possible cases of what the list may conform to (see Lemma C.2.6), so we have our desired conclusion: if ptr is active at some time, then ptr is in the list at that time. This allows us to identify the cell that stores the acquisition counter for the cell pointed to by ptr: the cell before the cell pointed to by ptr in the list. Definition C.5.34. Suppose I B is finite and ptr is active in I B . We define prev(I B , ptr) as follows. Let elast be the last L-event in I B which is well-defined by Corollary C.5.30 and let Ieexclude be the last prefix of I B up to but excluding elast . Then, • if elast is an L-add or L-remove event and from elast onwards in I B there are no successful list-add or list-remove attempts, then by Proposition C.5.32, ptr is in List(Ieexclude ) exactly last B exclude once, and we define prev(I , ptr) as the pointer immediately before ptr in List(Ielast ); and • otherwise, by Proposition C.5.33, ptr is in List(I B ) exactly once, and we define prev(I B , ptr) as the pointer immediately before ptr in List(I B ). prev(I B , ptr) is well-defined in both cases since ptr ̸= &H (because by Corollary C.5.28 ptr ∈ C and Assumption C.1.2) and by Definition C.1.7 &H is the first element of List(Ieexclude ) and List(I B ). last Before continuing, we record a simple fact about prev(I B , ptr). 177

Proposition C.5.35. If I B is finite and ptr is active in I B , then prev(I B , ptr) ∈ C ∪ {&H}. Proof. By Definition C.5.34 there is a prefix I of I B where ptr is in List(I) exactly once, and prev(I B , ptr) is immediately before ptr in List(I). Hence, prev(I B , ptr) is not the last element of List(I). Thus, by Definition C.1.7, prev(I B , ptr) is either &H or there is an L-add event for prev(I B , ptr) in I. If the latter, then by Lemma C.1.28, prev(I B , ptr) ∈ C. Therefore, prev(I B , ptr) ∈ C ∪ {&H} as wanted. Proposition C.5.35 Now that we have defined the cell that contains the acquisition counter for the cell pointed to by ptr, we need to prove that the acquisition counter of this cell is semantically correct, i.e., it is equal to the number of successful-list-acquire-next attempts for ptr plus one (Proposition C.5.45). To do so, we prove two facts: (1) every successful list-acquire-next attempt for ptr is after its previous cell (Proposition C.5.41); and (2) every successful list-acquire-next attempt after its previous cell is for ptr (Proposition C.5.42). These two facts together imply that during periods when the cell that contains the acquisition counter for the cell pointed to by ptr remains the same, the acquisition counter for ptr changes proportionally to the number of successful list-acquire-next attempts for ptr. In other words, in the special case where the cell that contains the acquisition counter for the cell pointed to by ptr is always the same, (1) and (2) imply that the acquisition counter for ptr is semantically correct. We start the proof of (1) and (2) by proving that ptr is active at the time of any successful list-acquire-next attempt for ptr, implying that our definition of the acquisition counter for the cell pointed to by ptr (Definition C.5.34) is well-defined. Proposition C.5.36. If the last step in I B is a successful list-acquire-next attempt after prev ptr such that prev ptr ̸= &H, then prev ptr is active in I B . Proof. Let aacquire be the last step in I B . By Definition C.5.27, we must prove that there is a single successful list-add attempt for ptr in I B and no successful list-remove attempts for ptr in I B . Since aacquire is a list-acquire-next attempt after prev ptr in I B , by Lemma C.1.90, prev ptr ∈ C ∪ {&H}, and since prev ptr ̸= &H we have that prev ptr ∈ C and so by Assumption C.1.2 prev ptr ̸= Null. Furthermore, by Lemma C.1.94, there is either a successful list-add attempt after prev ptr or a successful list-remove attempt between prev ptr and some pointer in I B . Let a be this successful list-add or list-remove attempt. Since by Lemma C.2.30 Q(I B ) holds, we have that there is an L-event e before a such that if Ieexclude is the prefix of I B up to but excluding e then prev ptr ∈ List(Ieexclude ). Hence, since prev ptr ̸= &H and prev ptr ̸= Null, by Definition C.1.7, there is an L-add event eadd for prev ptr in Ieexclude . Since eadd is in Ieexclude , we have that eadd < e, and so there is a next L-event after eadd in I B ; say e′ . Hence, since eadd is an L-add event for prev ptr in I B and by Lemma C.2.30 R(I B ) holds, we have that there is a successful list-add attempt aadd for prev ptr in I B . Therefore, by Lemma C.5.1, aadd is the only successful list-add attempt for prev ptr in I B as wanted. What remains is to prove that there are no successful list-remove attempts for ptr in I B . This follows from Lemma C.1.86 because aacquire is a successful list-acquire-next attempt after prev ptr and is the last step of I B . Proposition C.5.36 Lemma C.5.37. If the last step in I B is a successful list-acquire-next attempt for ptr, then ptr is active in I B . Proof. Let aacquire be the last step in I B and suppose aacquire is a successful list-acquire-next attempt for ptr after prev ptr. This setup yields the following three facts. First, by Lemma C.1.90, ptr ∈ C and prev ptr ∈ C ∪ {&H}. Second, (∗prev ptr).next.ptr = ptr at aacquire . Third, by Lemma C.1.94, there is a successful list-add or list-remove attempt before aacquire , and so by Corollary C.1.37, there is an L-event before aacquire . Hence, there is a last L-event before aacquire ; 178

say elast . Thus, since aacquire is the last step in I B , we have that elast is the last L-event in I B . Let Ieexclude be the prefix of I B up to but excluding elast . There are two cases. last Case 1. elast is an L-add or L-remove event and from elast onwards in I B there are no successful list-add or list-remove attempts. Hence, since I B is finite, by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, elast is the last L-event in I B , elast is an L-add or L-remove event, and from elast onwards in I B there are no successful list-add or list-remove attempts, by Lemma C.2.6, the list of cells conforms to List(Ieexclude ) in I B . last We now prove that prev ptr ∈ List(Ieexclude ). Since aacquire is a successful list-acquire-next attempt last after prev ptr, by Proposition C.5.36, prev ptr is active in I B . Therefore, since I B is finite, elast is the last L-event in I B , and from elast onwards in I B there are no successful list-add or list-remove attempts, by Proposition C.5.32, prev ptr ∈ List(Ieexclude ). last We now prove that ptr ∈ List(Ieexclude ). Since prev ptr ∈ C ∪ {&H}, by Assumption C.1.2, last prev ptr ̸= Null. Furthermore, since as established above (∗prev ptr).next.ptr = ptr at aacquire , and aacquire is the last step in I B , we have that (∗prev ptr).next.ptr = ptr at the end of I B . Since the list of cells conforms to List(Ieexclude ) in I B , prev ptr ∈ List(Ieexclude ), and prev ptr ̸= Null, last last exclude by Definition C.1.7, ptr ∈ List(Ielast ) as wanted. We now finish the proof of Case 1. We must prove that there is exactly one successful list-add attempt for ptr in I B and no successful list-remove attempts for ptr in I B . Since ptr ∈ C, by Assumption C.1.2, ptr ̸= &H and ptr ̸= Null. Hence, since ptr ∈ List(Ieexclude ), by Definition C.1.7, last exclude there is an L-add event eadd for ptr in Ielast . Hence, eadd < elast , and so there is a next L-event after eadd in I B ; say e. Thus, since eadd is an L-add event for ptr in I B and by Lemma C.2.30 R(I B ) holds, we have that there is a successful list-add attempt aadd for ptr in I B . Therefore, by Lemma C.5.1, aadd is the only successful list-add attempt for ptr in I B as wanted. What remains is to prove that there are no successful list-remove attempts for ptr in I B . Since by Lemma C.2.30 P (I B ) holds, and ptr ∈ List(Ieexclude ), by Lemma C.1.116, there are no list-remove attempts for ptr last exclude in Ielast . Therefore, since elast is not a list-remove attempt, and from elast onwards in I B there are no successful list-remove attempts, we have that there are no successful list-remove attempts for ptr in I B as wanted. Case 2. elast is not an L-add nor an L-remove event or from elast onwards in I B there is a successful list-add or list-remove attempt. Hence, since I B is finite, by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I B ) in I B . We now prove that prev ptr ∈ List(I B ). Since aacquire is a successful list-acquire-next attempt after prev ptr, by Proposition C.5.36, prev ptr is active in I B . Therefore, since I B is finite, elast is the last L-event in I B , elast is not an L-add nor an L-remove event or from elast onwards in I B there is a successful list-add or list-remove attempt, by Proposition C.5.33, prev ptr ∈ List(I B ). We now prove that ptr ∈ List(I B ). Since prev ptr ∈ C ∪ {&H}, by Assumption C.1.2, prev ptr ̸= Null. Furthermore, since as established above (∗prev ptr).next.ptr = ptr at aacquire , and aacquire is the last step in I B , we have that (∗prev ptr).next.ptr = ptr at the end of I B . Since the list of cells conforms to List(I B ) in I B , prev ptr ∈ List(I B ), and prev ptr ̸= Null, by Definition C.1.7, ptr ∈ List(I B ) as wanted. We now prove that there is a successful list-add attempt for ptr in I B . Since aacquire is a listacquire-next attempt for ptr, by Lemma C.1.94, there is either a successful list-add attempt for 179

ptr or there is a successful list-remove attempt between some pointer and ptr before aacquire . Let a be this successful list-add or list-remove attempt. Hence, if a is a list-add attempt for ptr, we are done, so suppose a is a successful list-remove attempt between some pointer and ptr. Thus, since by Lemma C.2.30 Q(I B ) holds, we have that there is an L-event e before a such that if Ieexclude is the prefix of I B up to but excluding e, then ptr ∈ List(Ieexclude ). Since ptr ∈ C, by Assumption C.1.2, ptr ̸= &H and ptr ̸= Null. Hence, since ptr ∈ List(Ieexclude ), by Definition C.1.7, there is an L-add event eadd for ptr in Ieexclude , so eadd < e. Thus, there is a next L-event after eadd in I B ; say e′ . Therefore, since eadd is an L-add event for ptr in I B and by Lemma C.2.30 R(I B ) holds, we have that there is a successful list-add attempt aadd for ptr in I B as wanted. We now finish the proof of Case 2. We must prove that there is exactly one successful list-add attempt for ptr in I B and no successful list-remove attempts for ptr in I B . Since there is a successful list-add attempt for ptr in I B , by Lemma C.5.1, there is exactly one successful list-add attempt for ptr in I B . What remains is to prove that there are no successful list-remove attempts for ptr in I B . This follows from Lemma C.1.116 since P (I B ) holds and ptr ∈ List(I B ). Lemma C.5.37 We are now ready to prove (1) and (2), i.e., (1) every successful list-acquire-next attempt for ptr is after its previous cell (Proposition C.5.41), and (2) every successful list-acquire-next attempt after its previous cell is for ptr (Proposition C.5.42). We start by recording a few useful facts. Proposition C.5.38. If the last step of I B is a successful list-add attempt for ptr after prev ptr, then prev ptr is immediately before ptr in List(I B ). Proof. Let a be the last step of I B . Hence, since by Lemma C.2.30 Q(I B ) holds, we have that a is preceded by a unique L-add event e for ptr and if Ieexclude is the prefix of I B up to but excluding e then prev ptr is the second last pointer in List(Ieexclude ). Since a is a list-add attempt for ptr, by Corollary C.1.37, there is an L-add event e′ for ptr before a. Hence, since e and e′ are both L-add events for ptr in I B and by Lemma C.2.30 P (I B ) holds, we have that e′ = e. Thus, e is a’s corresponding L-event, and so since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Corollary C.2.2, e is the last L-event in I B . So, since Ieexclude is the prefix of I B up to but excluding e, we have that the sequences of L-events in Ieexclude and I B are the same except Ieexclude excludes e and I B includes e. Therefore, since prev ptr is the second last pointer in List(Ieexclude ), and e is an L-add event for ptr, by Definition C.1.7, prev ptr is the third last pointer in List(I B ) and ptr is the second last pointer in List(I B ) as wanted. Proposition C.5.38 Proposition C.5.39. If the last step of I B is a successful list-remove attempt between prev ptr and next ptr, then prev ptr is immediately before next ptr in List(I B ). Proof. Let a be the last step of I B and suppose a is for ptr. Hence, since by Lemma C.2.30 Q(I B ) holds, we have that a is preceded by a unique L-remove event e for ptr in I B and if Ieexclude is the prefix of I B up to but excluding e then ptr is in List(Ieexclude ) exactly once and prev ptr and next ptr are the pointers preceding and succeeding ptr in List(Ieexclude ). Since a is a list-remove attempt for ptr, by, Corollary C.1.37, there is an L-remove event e′ for ptr before a. Hence, since e and e′ are both L-remove events for ptr in I B and by Lemma C.2.30 P (I B ) holds, we have that e′ = e. Thus, e is a’s corresponding L-event, and so since by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Corollary C.2.2, e is the last L-event in I B . So, since Ieexclude is the prefix of I B up to but excluding e, we have that the sequences of L-events in Ieexclude and I B are the same except Ieexclude excludes e and I B includes e. Therefore, since prev ptr and next ptr are the pointers preceding and succeeding ptr in List(Ieexclude ) and e is an L-remove event for ptr, by Definition C.1.7, prev ptr is the pointer preceding next ptr in List(I B ) as wanted. Proposition C.5.39 180

Proposition C.5.40. If the last step of I B is a successful list-add attempt for ptr after prev ptr or a successful list-remove attempt between prev ptr and ptr, then (1) the list of cells conforms to List(I B ) in I B and (2) prev ptr is immediately before ptr in List(I B ). Proof. Since the last step of I B is a successful list-add or list-remove attempt, by Corollary C.1.37, there is an L-event in I B , so there is a last L-event in I B ; say elast . Hence, since the last step of I B is a successful list-add or list-remove attempt, we have that from elast onwards in I B there is a successful list-add or list-remove attempt. Therefore, since I B is finite, and by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.6, the list of cells conforms to List(I B ) in I B satisfying (1). Furthermore, (2) follows from Proposition C.5.38 and Proposition C.5.39. Proposition C.5.40 We now prove (1). Proposition C.5.41. If the last step in I B is a successful list-acquire-next attempt for ptr, then it is after prev(I B , ptr). Proof. Let aacquire be the last step in I B , p be the process that executed aacquire , and suppose aacquire is for ptr after prev ptr. Hence, by Lemma C.1.90, ptr ∈ C and prev ptr ∈ C ∪ {&H}. Furthermore, by Lemma C.1.94, there is a successful list-add attempt for ptr after prev ptr or a successful list-remove attempt between prev ptr and ptr before aacquire in I B ; say a. Hence, by Proposition C.5.40, the list of cells conforms to List(Iainclude ) in Iainclude and prev ptr is immediately before ptr in List(Iainclude ) where Iainclude is the prefix of I B up to and including a (*). Since the last step in I B is a successful list-acquire-next attempt for ptr, by Lemma C.5.37, ptr is active in I B , and so by Corollary C.5.30, there is a last L-event in I B ; say elast . Case 1. elast < a. Hence, since a is a successful list-add or list-remove attempt, from elast onwards in I B there is a successful list-add or list-remove attempt. Thus, by Definition C.5.34, prev(I B , ptr) is immediately before ptr in List(I B ). Since elast < a, we have that elast is in Iainclude . Hence, since elast is the last L-event in I B and Iainclude is a prefix of I B , we have that the sequences of L-events are the same in Iainclude and I B . Thus, by Definition C.1.7, List(Iainclude ) = List(I B ). So, since by (*) prev ptr is immediately before ptr in List(Iainclude ), we have that prev ptr is immediately before ptr in List(I B ). Therefore, since prev(I B , ptr) is immediately before ptr in List(I B ), we have that prev(I B , ptr) = prev ptr as wanted. Case 2. a < elast . There are two cases. Case 2.1. elast is a L-remove event for prev ptr. Hence, by Lemma C.1.28, prev ptr ∈ C, so by Assumption C.1.2 prev ptr ̸= &H and Null. We first prove that from elast onwards in I B there are no successful list-add or list-remove attempts. Since elast is the last L-event in I B , elast is an L-remove event for prev ptr, and by Lemma C.2.30, P (I B ), Q(I B ), and R(I B ) hold, by Lemma C.2.5, from elast onwards in I B there is at most one successful list-remove attempt for prev ptr and no other successful list-remove or list-add attempt for any pointer. Furthermore, since aacquire is a successful list-acquire-next attempt after prev ptr in I B , by Lemma C.1.86, there are no successful list-remove attempts for prev ptr before aacquire in I B , and so since aacquire is the last step in I B , we have that there are no successful list-remove attempts for prev ptr in I B . These two facts together imply that from elast onwards in I B there are no successful list-add or list-remove attempts as wanted. 181

Since elast is an L-remove event and from elast onwards in I B there are no successful list-add or list-remove attempts, by Definition C.5.34, ptr is in List(Ieexclude ) exactly once and prev(I B , ptr) last exclude exclude is immediately before ptr in List(Ielast ) where Ielast is the prefix of I B up to but excluding elast . Since a < elast , we have that Iainclude is a prefix of Ieexclude . last exclude We now prove that prev ptr ∈ List(Ielast ). Suppose, for contradiction, prev ptr ∈ / List(Ieexclude ). last include Since by (*) prev ptr is in List(Ia ), and prev ptr ̸= &H and prev ptr ̸= Null, by Definition C.1.7, there is an L-add event eadd for prev ptr in Iainclude . Hence, since Iainclude is a prefix of Ieexclude , we have that eadd is in Ieexclude . Thus, since prev ptr ∈ / List(Ieexclude ), by Definition C.1.7, last last last exclude exclude there is an L-remove event eremove for prev ptr in Ielast . So, since Ielast is the prefix of I B up to but excluding elast , we have that eremove < elast , and thus eremove ̸= elast . Therefore, there are two L-remove events for prev ptr in I B (namely eremove and elast ). However, since by Lemma C.2.30 P (I B ) holds, there is at most one L-remove event for prev ptr in I B , a contradiction. We now finish the proof of Case 2.1. Since Iainclude is a prefix of Ieexclude , by (*) prev ptr ∈ C is last immediately before ptr ∈ C in List(Iainclude ), prev ptr is in List(Ieexclude ), ptr is in List(Ieexclude ), last last exclude and by Lemma C.2.30 P (Ielast ) holds, by Lemma C.1.115, prev ptr is immediately before ptr in List(Ieexclude ). Therefore, since ptr is in List(Ieexclude ) exactly once and prev(I B , ptr) is immediately last last exclude B before ptr in List(Ielast ), we have that prev(I , ptr) = prev ptr as wanted. Case 2.2. elast is not a L-remove event for prev ptr. By Definition C.5.34, either: (A) ptr is in List(Ieexclude ) exactly once and prev(I B , ptr) is immelast is the prefix of I B up to but excluding elast ; or ) where Ieexclude diately before ptr in List(Ieexclude last last B B (B) ptr is in List(I ) exactly once and prev(I , ptr) is immediately before ptr in List(I B ). Since a < elast , we have that Iainclude is a prefix of Ieexclude . last We first prove that there are no L-remove events for prev ptr in Ieexclude and I B . Since aacquire last B is the last step in I , aacquire is a successful list-acquire-next attempt after prev ptr, elast is the last L-event in I B , elast is not a L-remove event for prev ptr, and by Lemma C.2.30 R(I B ) holds, is a by Lemma C.1.87, there are no L-remove events for prev ptr in I B . Therefore, since Ieexclude last B as wanted. prefix of I B , we have that there are no L-remove events for prev ptr in Ieexclude and I last B ). If prev ptr = &H, this immediately We now prove that prev ptr is in List(Ieexclude ) and List(I last follows by Definition C.1.7, so since prev ptr ∈ C ∪ {&H}, it remains to consider the case where prev ptr ∈ C. Since prev ptr ∈ C, by Assumption C.1.2, prev ptr ̸= &H and prev ptr ̸= Null. Hence, since by (*) prev ptr is in List(Iainclude ), by Definition C.1.7, there is an L-add event eadd for prev ptr in Iainclude . Thus, since Iainclude is a prefix of Ieexclude and I B , we have that eadd is in last Ieexclude and I B . Therefore, since as we just proved there are no L-remove events for prev ptr in last exclude Ielast and I B , by Definition C.1.7, prev ptr is in List(Ieexclude ) and List(I B ) as wanted. last We now finish the proof of Case 2.2. First, consider (A). Hence, ptr is in List(Ieexclude ) exactly last B exclude include once and prev(I , ptr) is immediately before ptr in List(Ielast ). Since Ia is a prefix of include ), prev ptr is in Ieexclude , by (*) prev ptr ∈ C ∪ {&H} is immediately before ptr ∈ C in List(I a last exclude ), and by Lemma C.2.30 P (I exclude ) holds, by Lemma C.1.115, List(Ieexclude ), ptr is in List(I elast elast last B , ptr) = prev ptr as wanted. prev ptr is immediately before ptr in List(Ieexclude ). Therefore, prev(I last B Now consider (B). Hence, ptr is in List(I ) exactly once, and prev(I B , ptr) is immediately before ptr in List(I B ). Since Iainclude is a prefix of I B , by (*) prev ptr ∈ C ∪ {&H} is immediately before ptr ∈ C in List(Iainclude ), prev ptr is in I B , ptr is in I B , and by Lemma C.2.30 P (I B ) holds, by Lemma C.1.115, prev ptr is immediately before ptr in List(I B ). Therefore, prev(I B , ptr) = prev ptr as wanted. Proposition C.5.41 We now prove (2). 182

Proposition C.5.42. Suppose I B is finite and ptr is active in I B . If the last step in I B is a successful list-acquire-next attempt after prev(I B , ptr), then it is for ptr. Proof. Let aacquire be the last step of I B and suppose it is for ptr′ after prev(I B , ptr). Hence, by Lemma C.5.37, ptr′ is active in I B , and so by Proposition C.5.41, aacquire is a successful list-acquirenext attempt for ptr′ after prev(I B , ptr′ ), implying prev(I B , ptr) = prev(I B , ptr′ ). Let elast be the last L-event in I B which is well-defined by Corollary C.5.30 and let Ieexclude be the prefix of I B up last to but excluding elast . We must prove that ptr = ptr′ . There are two cases. Case 1. elast is an L-add or L-remove event and from elast onwards in I B there are no successful list-add or list-remove attempts. Hence, since ptr (resp. ptr′ ) is active in I B , by Definition C.5.34, ptr (resp. ptr′ ) is in List(Ieexclude ) last exactly once, and prev(I B , ptr) (resp. prev(I B , ptr′ )) is immediately before ptr (resp. ptr′ ) in List(Ieexclude ). Therefore, since prev(I B , ptr) = prev(I B , ptr′ ), we have that ptr = ptr′ . last Case 2. elast is not an L-add nor an L-remove event or from elast onwards in I B there is a successful list-add or list-remove attempt. Hence, since ptr (resp. ptr′ ) is active in I B , by Definition C.5.34, ptr (resp. ptr′ ) is in List(I B ) exactly once, and prev(I B , ptr) (resp. prev(I B , ptr′ )) is immediately before ptr (resp. ptr′ ) in List(I B ). Therefore, since prev(I B , ptr) = prev(I B , ptr′ ), we have that ptr = ptr′ . Proposition C.5.42 As we mentioned before, in the special case where the cell that contains the acquisition counter for the cell pointed to by ptr is always the same, Proposition C.5.41 and Proposition C.5.42 imply that the acquisition counter for ptr is semantically correct, i.e., it is equal to the number of successful list-acquire-next attempts for ptr plus one (Proposition C.5.45). So, what remains is to deal with the case where the cell that contains the acquisition counter for the cell pointed to by ptr changes. The challenge is ensuring that the acquisition counter for ptr is correctly copied when the cell it is stored in changes. Ultimately, this concern is addressed by the sealing mechanism, but to leverage this, we must first show that when the cell that stores the acquisition counter for ptr changes, it is a particular list-remove attempt that does so (Proposition C.5.44). Proposition C.5.43. Suppose ptr is active in I B . By Definition C.5.27, there is a single successful list-add attempt aadd for ptr in I B . For every prefix I of I B if aadd is in I, then ptr is active in I. Proof. Suppose, for contradiction, there is a prefix I of I B where aadd is in I and ptr is not active in I. Hence, since aadd is a successful list-add attempt for ptr, by Lemma C.5.1, aadd is the only successful list-add attempt for ptr in I. Thus, since ptr is not active in I, by Definition C.5.27, there is a successful list-remove attempt aremove for ptr in I. Therefore, since I is a prefix of I B , we have that aremove is in I B , and so there is a successful list-remove attempt for ptr in I B . However, since ptr is active in I B , by Definition C.5.27, there are no successful list-remove attempts for ptr in I B , a contradiction. Proposition C.5.43 Proposition C.5.44. Suppose ptr is active in I B . By Definition C.5.27, there is a single successful list-add attempt aadd for ptr in I B . Consider any proper prefix I of I B such that aadd is in I and let s be the step after I in I B . By Proposition C.5.43, ptr is active in both I and I ◦ s, and so prev(I, ptr) and prev(I ◦ s, ptr) are well-defined. If prev(I, ptr) ̸= prev(I ◦ s, ptr), then s is a successful list-remove attempt for prev(I, ptr) between prev(I ◦ s, ptr) and ptr. Proof. Suppose prev(I, ptr) ̸= prev(I ◦ s, ptr). Since ptr is active in I (resp. I ◦ s), by Corollary C.5.30, there is a last L-event in I (resp. I ◦ s); say eIlast (resp. eI◦s last ). There are two cases. 183

Case 1. eIlast ̸= eI◦s last . Hence, since I ◦ s is a one step continuation of I, we have that s = eI◦s last . We first prove that ptr is in List(I) exactly once, and prev(I ◦ s, ptr) is immediately before ptr in I◦s List(I). Since eI◦s last is an L-event, by Lemma C.1.29, elast is either an L-add, L-apply, or L-remove event. There are two cases. Case 1.1. eI◦s last is an L-add or L-remove event. I◦s Hence, since s = eI◦s last , we have that from elast onwards in I ◦s there are no successful list-add or listremove attempts, and so by Definition C.5.34, ptr is in List(I ∗ ) exactly once, and prev(I ◦ s, ptr) is immediately before ptr in List(I ∗ ) where I ∗ is the prefix of I ◦ s up to but excluding eI◦s last . Thus, I◦s ∗ since s = elast , we have that I = I. Therefore, ptr is in List(I) exactly once, prev(I ◦ s, ptr) is immediately before ptr in List(I) as wanted. Case 1.2. eI◦s last is an L-apply event. Hence, by Definition C.5.34, ptr is in List(I ◦ s) exactly once, and prev(I ◦ s, ptr) is immediately I◦s before ptr in List(I ◦ s). Since s = eI◦s last and elast is an L-apply event, by Definition C.1.7, List(I) = List(I ◦ s). Therefore, ptr is in List(I) exactly once, prev(I ◦ s, ptr) is immediately before ptr in List(I) as wanted. We now prove that prev(I, ptr) is immediately before ptr in List(I). Since eIlast is an L-event, by Lemma C.1.29, eIlast is either an L-add, L-apply, or L-remove event. If eIlast is an L-apply event, by Definition C.5.34, the claim follows. Otherwise, eIlast is an L-add or L-remove event. We prove that from eIlast onwards in I there is a successful list-add or list-remove attempt. Since eIlast is in I, we ′ ◦s I , we have that eIlast ≤ eI◦s have that eIlast is in I ◦ s. Hence, since s = eIlast last , and since elast is in I, it ′ I I ◦s I follows that elast < elast . Thus, there is a next L-event after elast in I ◦ s; say e. So, since eIlast is an L-add or L-remove event in I ◦ s, and by Lemma C.2.30 R(I ◦ s) holds, we have that between eIlast and e in I ◦ s, there is either a successful list-add or list-remove attempt, say a, so eIlast < a < e. Since e is in I ◦ s, we have that e ≤ s, so by transitivity, a < s. Hence, since a is in I ◦ s, we have that a is in I. Therefore, since eIlast < a and a is either a successful list-add or list-remove attempt, we have that from eIlast onwards in I there is a successful list-add or list-remove attempt. Since eIlast is an L-add or L-remove event, and from eIlast onwards in I there is a successful list-add or list-remove attempt, by Definition C.5.34, the claim follows. We now finish the proof of Case 1. So far we have proved that ptr is in List(I) exactly once, prev(I ◦ s, ptr) is immediately before ptr in List(I), and prev(I, ptr) is immediately before ptr in List(I). Together, these facts imply prev(I, ptr) = prev(I ◦s, ptr). However, our initial assumption is that prev(I, ptr) ̸= prev(I ◦ s, ptr), so this case is impossible. Case 2. eIlast = eI◦s last . Hence, the last L-event in I and I ◦ s is the same, and so for brevity we drop the superscript and denote it as elast . Furthermore, s is not an L-event. Hence, the sequence of L-events in I and I ◦ s are the same, so by Definition C.1.7 List(I) = List(I ◦ s). There are two cases. Case 2.1. elast is not an L-add nor an L-remove event, or from elast onwards in I there is a successful list-add or list-remove attempt. Hence, elast is not an L-add nor an L-remove event, or from elast onwards in I ◦ s there is a successful list-add or list-remove attempt, so by Definition C.5.34, ptr is in List(I ◦ s) exactly once, prev(I ◦ s, ptr) is immediately before ptr in List(I ◦ s), and prev(I, ptr) is immediately before ptr in List(I). Thus, since List(I) = List(I ◦ s), we have that ptr is in List(I) exactly 184

once, prev(I ◦ s, ptr) is immediately before ptr in List(I), and prev(I, ptr) is immediately before ptr in List(I). Together, these facts imply prev(I, ptr) = prev(I ◦ s, ptr). However, our initial assumption is that prev(I, ptr) ̸= prev(I ◦ s, ptr), so this case is impossible. Case 2.2. elast is an L-add or L-remove event, and from elast onwards in I there are no successful list-add or list-remove attempts. Hence, by Definition C.5.34, ptr is in List(Ieexclude ) exactly once and prev(I, ptr) is immediately last exclude is the prefix of I up to but excluding e before ptr in List(Ieexclude ) where I last . Since elast is elast last exclude in I ◦ s, we have that Ielast is the prefix of I ◦ s up to but excluding elast . There are two cases. Case 2.2.1. s is not a successful list-add nor list-remove attempt. Hence, since from elast onwards in I there are no successful list-add or list-remove attempts, we have that from elast onwards in I ◦ s there are no successful list-add or list-remove attempts. Thus, by Definition C.5.34, prev(I ◦ s, ptr) is immediately before ptr in List(Ieexclude ). Therefore, since last ptr is in List(Ieexclude ) exactly once and prev(I, ptr) is immediately before ptr in List(Ieexclude ), last last we have that prev(I, ptr) = prev(I ◦ s, ptr). However, our initial assumption is that prev(I, ptr) ̸= prev(I ◦ s, ptr), so this case is impossible. Case 2.2.2. s is a successful list-add or list-remove attempt. Hence, by Definition C.5.34, ptr is in List(I ◦ s) exactly once and prev(I ◦ s, ptr) is immediately before ptr in List(I◦s). Since s is a successful list-add or list-remove attempt, and by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Corollary C.2.2, s’ corresponding L-event e, is the last L-event before s in I B . Hence, since I ◦ s is the prefix of I B up to and including s, we have that e is the last L-event in I ◦ s. Therefore, since elast is the last L-event in I ◦ s, we have that e = elast , and so elast is s’ corresponding L-event. There are three cases. Case 2.2.2.1. s is a successful list-add attempt for any pointer. Hence, since elast is s’ corresponding L-event, by Corollary C.1.37, elast is an L-add event. Since elast is the last L-event in I ◦ s and Ieexclude is the prefix of I ◦ s up to but excluding elast , we last have that the sequences of L-events is the same in Ieexclude and I ◦ s except elast is not in Ieexclude last last and elast is in I ◦ s. Thus, since elast is an L-add event, by Definition C.1.7, every element in List(Ieexclude ) is in List(I ◦ s). So, since by the beginning of Case 2.2 prev(I, ptr) ∈ List(Ieexclude ), last last we have that prev(I, ptr) ∈ List(I ◦ s). Since Ieexclude is a prefix of I ◦ s, by Proposition C.5.35 last prev(I, ptr) ∈ C ∪ {&H}, by Corollary C.5.28 ptr ∈ C, by the beginning of Case 2.2 prev(I, ptr) is immediately before ptr in List(Ieexclude ), prev(I, ptr) ∈ List(I ◦ s), by the beginning of Case last 2.2.2 ptr ∈ List(I ◦ s), and by Lemma C.2.30 P (I ◦ s) holds, by Lemma C.1.115, prev(I, ptr) is immediately before ptr in List(I ◦ s). Therefore, since by the beginning of Case 2.2.2 ptr is in List(I ◦ s) exactly once and prev(I ◦ s, ptr) is immediately before ptr in List(I ◦ s), we have that prev(I, ptr) = prev(I ◦ s, ptr). However, our initial assumption is that prev(I, ptr) ̸= prev(I ◦ s, ptr), so this case is impossible. Case 2.2.2.2. s is a successful list-remove attempt for a pointer other than prev(I, ptr). Hence, since elast is s’ corresponding L-event, by Corollary C.1.37, elast is an L-remove event for v ̸= prev(I, ptr). Since elast is the last L-event in I ◦ s and Ieexclude is the prefix of I ◦ s up to but last excluding elast , we have that the sequences of L-events is the same in Ieexclude and I ◦ s except elast last exclude is not in Ielast and elast is in I ◦ s. Thus, since elast is an L-remove event for v ̸= prev(I, ptr), and by the beginning of Case 2.2 prev(I, ptr) ∈ List(Ieexclude ), by Definition C.1.7, prev(I, ptr) ∈ last List(I ◦ s). Since Ieexclude is a prefix of I ◦ s, by Proposition C.5.35 prev(I, ptr) ∈ C ∪ {&H}, by last Corollary C.5.28 ptr ∈ C, by the beginning of Case 2.2 prev(I, ptr) is immediately before ptr in List(Ieexclude ), prev(I, ptr) ∈ List(I ◦ s), by the beginning of Case 2.2.2 ptr ∈ List(I ◦ s), and last by Lemma C.2.30 P (I ◦ s) holds, by Lemma C.1.115, prev(I, ptr) is immediately before ptr in 185

List(I ◦ s). Therefore, since by the beginning of Case 2.2.2 ptr is in List(I ◦ s) exactly once and prev(I ◦ s, ptr) is immediately before ptr in List(I ◦ s), we have that prev(I, ptr) = prev(I ◦ s, ptr). However, our initial assumption is that prev(I, ptr) ̸= prev(I ◦ s, ptr), so this case is impossible. Case 2.2.2.3. s is a successful list-remove attempt for prev(I, ptr). Let s be a successful list-remove attempt for prev(I, ptr) between prev ptr and next ptr. We will prove that next ptr = ptr and prev ptr = prev(I ◦ s, ptr). Since s is a successful list-remove attempt for prev(I, ptr) between prev ptr and next ptr in I ◦ s and by Lemma C.2.30 Q(I ◦ s) holds, there is an L-remove event e for prev(I, ptr) before s in I ◦ s such that if Ieexclude is the prefix of I ◦ s up to but excluding e, then prev(I, ptr) is in List(Ieexclude ) exactly once and prev ptr and next ptr are the pointers preceding and succeeding prev(I, ptr) in List(Ieexclude ), respectively. Since s is a successful list-remove attempt for prev(I, ptr) and elast is s’ corresponding L-event, by Corollary C.1.37, elast is an L-remove event for prev(I, ptr). Hence, since by Lemma C.2.30 P (I ◦ s) holds, and e and elast are both L-remove events for prev(I, ptr) in I ◦ s, we have that e = elast . Thus, Ieexclude = Ieexclude , and so prev(I, ptr) is in List(Ieexclude ) exactly once and prev ptr last last and next ptr are the pointers preceding and succeeding prev(I, ptr) in List(Ieexclude ), respectively. last So, since by the beginning of Case 2.2 prev(I, ptr) is immediately before ptr in List(Ieexclude ), last we have that next ptr = ptr. What remains is to prove that prev ptr = prev(I ◦ s, ptr). Since prev(I, ptr) is in List(Ieexclude ) exactly once, prev ptr and next ptr are the pointers preceding and last succeeding prev(I, ptr) in List(Ieexclude ), respectively, and next ptr = ptr, by Definition C.1.7, last exclude List(Ielast ) = &H, . . . , prev ptr, prev(I, ptr), ptr, . . . , Null where the dots represent zero or more pointers. Hence, since elast is the last L-event in I ◦ s and Ieexclude is the prefix of I ◦ s last up to but excluding elast , we have that the sequences of L-events is the same in Ieexclude and I ◦ s last exclude and elast is in I ◦ s, and so since elast is an L-remove event for except elast is not in Ielast prev(I, ptr), by Definition C.1.7, List(I ◦ s) = &H, . . . , prev ptr, ptr, . . . , Null. Thus, prev ptr is immediately before ptr in List(I ◦ s). Therefore, since by the beginning of Case 2.2.2 ptr is in List(I ◦ s) exactly once and prev(I ◦ s, ptr) is immediately before ptr in List(I ◦ s), we have that prev ptr = prev(I ◦ s, ptr) as wanted. Proposition C.5.44 We are now ready to prove that the acquisition counter for ptr is semantically correct. Proposition C.5.45. Suppose I B is finite and ptr is active in I B . Then, at the end of I B (∗prev(I B , ptr)).next.acquisitions = A(I B , ptr) + 1. Proof. Since ptr is active in I B , by Definition C.5.27, there is a single successful list-add attempt aadd for ptr in I B . To prove this claim, it suffices to prove the following statement. Consider any prefix I of I B where aadd is in I. By Proposition C.5.43, ptr is active in I so prev(I, ptr) is well-defined. Then, at the end of I, (∗prev(I, ptr)).next.acquisitions = A(I, ptr) + 1. We prove this statement by induction on the step number in I B starting from aadd to the end of I B . Base Case. I is the prefix of I B up to and including aadd . We claim that there are no successful list-acquire-next attempts for ptr before aadd in I B . Suppose, for contradiction, there is a list-acquire-next attempt aacquire for ptr before aadd . Let I ∗ be the prefix of I B up to and including aacquire . Hence, by Lemma C.5.37, ptr is active in I ∗ . Thus, by Definition C.5.27, there is a successful list-add attempt a for ptr in I ∗ , so a < aacquire . Therefore, since aacquire < aadd , by transitivity a < aadd , and so there are two successful list-add attempts for ptr in I B . However, by Lemma C.5.1, there is at most one successful list-add attempt for ptr in I B , a contradiction. Since there are no successful list-acquire-next attempts for ptr before aadd in 186

I B , and aadd is the last step in I, we have that there are no successful list-acquire-next attempts for ptr in I. Therefore, by Definition C.5.9, A(I, ptr) = 0, and so we must prove that at the end of I, (∗prev(I, ptr)).next.acquisitions = 1. Since ptr is active in I, by Corollary C.5.30, there is a last L-event in I; say elast . Hence, since I is the prefix of I B up to and including aadd , we have that from elast onwards in I there is a successful list-add attempt (namely aadd ). Thus, since ptr is active in I, by Definition C.5.34, ptr is in List(I) exactly once and prev(I, ptr) is the pointer preceding ptr in List(I). Therefore, since aadd is the last step of I, aadd is a successful list-add attempt for ptr after some prev ptr, by Proposition C.5.40, prev ptr is immediately before ptr in List(I), and so prev(I, ptr) = prev ptr. Hence, aadd is a successful list-add attempt for ptr after prev(I, ptr). Thus, by line 36, (∗prev(I, ptr)).next.acquisitions = 1 at aadd . Therefore, since aadd is the last step in I, we have that (∗prev(I, ptr)).next.acquisitions = 1 at the end of I as required. Inductive Case. If the claim holds for some proper prefix I of I B then it holds for I ◦ s where s is the step after I in I B (s is well-defined since I is a proper prefix of I B ). Suppose for some proper prefix I of I B that (∗prev(I, ptr)).next.acquisitions = A(I, ptr)+1 at the end of I. This is the inductive hypothesis. We will prove that (∗prev(I◦s, ptr)).next.acquisitions = A(I ◦ s, ptr) + 1 at the end of I ◦ s where s is the step after I in I B . Since ptr is active in I and I ◦ s, by Proposition C.5.35, prev(I, ptr) and prev(I ◦ s, ptr) are in C ∪ {&H}. There are two cases. Case 1. prev(I, ptr) = prev(I ◦ s, ptr). There are two more cases. Case 1.1. s is a successful list-acquire-next attempt for ptr. Hence, by Definition C.5.9, A(I ◦ s, ptr) = A(I, ptr) + 1. Furthermore, by Proposition C.5.41, s is a successful list-acquire-next attempt for ptr after prev(I ◦ s, ptr). Hence, by Definition C.1.5, s is an execution of the form CAS((∗prev(I ◦ s, ptr)).next, (∗, ∗, a, ptr), (∗, ∗, a + 1, ptr)). Thus, since s is successful we have that (1) (∗prev(I ◦ s, ptr)).next.acquisitions = a at the step before s (the end of I) and (2) (∗prev(I ◦ s, ptr)).next.acquisitions = a + 1 at s (the end of I ◦ s). Since prev(I, ptr) = prev(I ◦ s, ptr), by (1), we have that (∗prev(I, ptr)).next.acquisitions = a at the end of I. Hence, since by the inductive hypothesis (∗prev(I, ptr)).next.acquisitions = A(I, ptr) + 1 at the end of I, we have that a = A(I, ptr) + 1. Thus, by (2), we have that (∗prev(I ◦ s, ptr)).next.acquisitions = A(I, ptr) + 2 at the end of I ◦ s. Therefore, since A(I ◦ s, ptr) = A(I, ptr) + 1, we have that (∗prev(I ◦ s, ptr)).next.acquisitions = A(I ◦ s, ptr) + 1 at the end of I ◦ s as required. Case 1.2. s is not a successful list-acquire-next attempt for ptr. Hence, by Definition C.5.9, A(I, ptr) = A(I ◦ s, ptr). Furthermore, since ptr is active in I ◦ s, by Proposition C.5.42, s is not a successful list-acquire-next attempt after prev(I ◦ s, ptr). We now prove that s is not a successful list-add attempt after prev(I ◦s, ptr) and s is not a successful list-remove attempt between prev(I ◦ s, ptr) and some pointer. Suppose, for contradiction, that s is a successful list-add attempt for next ptr after prev(I ◦ s, ptr) or a successful list-remove attempt between prev(I ◦ s, ptr) and next ptr. Hence, by Proposition C.5.40, prev(I ◦ s, ptr) is immediately before next ptr in List(I ◦s). Furthermore, the last step in I ◦s is a successful list-add or list-remove attempt, and so since ptr is active in I ◦ s, by Definition C.5.34, prev(I ◦ s, ptr) is immediately before ptr in List(I ◦ s). Hence, ptr = next ptr. Therefore, s is either a successful list-add attempt for ptr after prev(I ◦ s, ptr) or a successful list-remove attempt between prev(I ◦ s, ptr) and ptr. In the former case, since aadd is in I, and aadd is a successful list-add attempt for ptr, this implies there are two successful list-add attempts for ptr, a contradiction to Lemma C.5.1. In the latter

187

case, since s is a successful list-remove attempt for ptr, by Definition C.5.27, ptr is not active in I ◦ s, a contradiction to the fact that ptr is active in I ◦ s. We now finish the proof of Case 1.2. Since prev(I ◦ s, ptr) ∈ C ∪ {&H}, s is not a successful list-add attempt after prev(I ◦ s, ptr), s is not a successful list-remove attempt between prev(I ◦ s, ptr) and some pointer, and s is not a successful list-acquire-next attempt after prev(I ◦ s, ptr), by Observation C.1.6, (∗prev(I ◦ s, ptr)).next.acquisitions is the same at the end of I and at the end of I ◦ s. Thus, since prev(I, ptr) = prev(I ◦ s, ptr), (∗prev(I, ptr)).next.acquisitions at the end of I is equal to (∗prev(I ◦ s, ptr)).next.acquisitions at the end of I ◦ s. Hence, since by the inductive hypothesis, (∗prev(I, ptr)).next.acquisitions = A(I, ptr) + 1 at the end of I, we have that (∗prev(I ◦ s, ptr)).next.acquisitions = A(I, ptr) + 1 at the end of I ◦ s. Therefore, since A(I, ptr) = A(I ◦ s, ptr), we have that (∗prev(I ◦ s, ptr)).next.acquisitions = A(I ◦ s, ptr) + 1 at the end of I ◦ s as required. Case 2. prev(I, ptr) ̸= prev(I ◦ s, ptr). Hence, by Proposition C.5.44, s is a successful list-remove attempt for prev(I, ptr) between prev(I ◦ s, ptr) and ptr. Thus, by Definition C.5.9, A(I, ptr) = A(I ◦ s, ptr). Let p be the process that executed s and let T 56 be the time of p’s last execution of line 56 before s. Hence, by Lemma C.1.58, there is a successful list-seal attempt aseal for prev(I, ptr) before T 56 in I B . We now prove that there are no successful list-add attempts after prev(I, ptr), successful list-remove attempts between prev(I, ptr) and some pointer, and successful list-acquire-next attempts after prev(I, ptr) from T 56 onwards in I B , implying from T 56 onwards in I B (∗prev(I, ptr)).next.acquisitions is unchanged. We first prove that there are no successful list-add attempts after prev(I, ptr) from T 56 onwards in I B . Suppose, for contradiction, there is a successful list-add attempt aadd after prev(I, ptr) at or after T 56 in I B . Therefore, by Lemma C.1.60, there are no successful list-seal attempts for prev(I, ptr) before aadd in I B . However, since aseal < T 56 , and T 56 ≤ aadd , by transitivity, aseal < aadd , so there is a successful list-seal attempt for prev(I, ptr) before aadd in I B , a contradiction. We now prove that there are no successful list-remove attempts between prev(I, ptr) and some pointer from T 56 onwards in I B . Suppose, for contradiction, there is a successful list-remove attempt aremove between prev(I, ptr) and some pointer at or after T 56 in I B . Therefore, by Lemma C.1.61, there are no successful list-seal attempts for prev(I, ptr) before aadd in I B . However, since aseal < T 56 , and T 56 ≤ aremove , by transitivity, aseal < aremove , so there is a successful list-seal attempt for prev(I, ptr) before aremove in I B , a contradiction. We now prove that there are no successful list-acquire-next attempts after prev(I, ptr) from T 56 onwards in I B . Suppose, for contradiction, there is a successful list-acquire-next attempt aacquire after prev(I, ptr) at or after T 56 in I B . Therefore, by Lemma C.1.85, there are no successful list-seal attempts for prev(I, ptr) before aacquire in I B . However, since aseal < T 56 , and T 56 ≤ aacquire , by transitivity, aseal < aacquire , so there is a successful list-seal attempt for prev(I, ptr) before aacquire in I B , a contradiction. We now finish the proof of Case 2. Since prev(I, ptr) ∈ C ∪ {&H}, and there are no successful list-add attempts after prev(I, ptr), successful list-remove attempts between prev(I, ptr) and some pointer, and successful list-acquire-next attempts after prev(I, ptr) from T 56 onwards in I B , by Observation C.1.6, from T 56 onwards in I B (∗prev(I, ptr)).next.acquisitions is unchanged. Let (∗prev(I, ptr)).next.acquisitions = a at T 56 , so (∗prev(I, ptr)).next.acquisitions = a from T 56 onwards in I B . Hence, since by the inductive hypothesis (∗prev(I, ptr)).next.acquisitions = A(I, ptr) + 1 at the end of I, and T 56 is in I (because T 56 < s), we have that a = A(I, ptr) + 1. Since T 56 is the time of p’s last execution of line 56 before s, (∗prev(I, ptr)).next.acquisitions = a at T 56 , and s is a successful list-remove attempt for prev(I, ptr) between prev(I ◦ s, ptr) and ptr, we have that p read a from (∗prev(I, ptr)).next.acquisitions at T 56 and set (∗prev(I ◦ 188

s, ptr)).next.acquisitions = a at s (equivalently, the end of I ◦ s). Hence, since a = A(I, ptr) + 1, we have that (∗prev(I ◦ s, ptr)).next.acquisitions = A(I, ptr) + 1 at the end of I ◦ s. Therefore, since A(I, ptr) = A(I ◦ s, ptr), we have that (∗prev(I ◦ s, ptr)).next.acquisitions = A(I ◦ s, ptr) + 1 at the end of I ◦ s as required. Proposition C.5.45 We are now ready to prove the main claim of this section. Lemma C.5.46. For any acquire-copy event e for ptr in I B the following are true: 1. e = F&A((∗ptr).revocations, −(A(I B , ptr) + 1)); and 2. if I is the prefix of I B up to and including e then A(I, ptr) = A(I B , ptr). Proof. Let p be the process that executed e and let I be the invocation of the DoRemoveCell procedure that e was executed during. Hence, by Lemma C.1.96 ptr ∈ C and by Definition C.1.5 the second parameter of I is ptr. Furthermore, by Lemma C.1.95, p performed a successful listremove attempt aremove for ptr before e during I. Since e is for ptr, by Definition C.1.5, e is of the form F&A((∗ptr).revocations, ∗), and so the remainder of the proof is dedicated to showing that the second parameter of e is −(A(I B , ptr) + 1) (2 is proved along the way). We start with some definitions and basic facts. Let T 58 be the time of p’s last execution of line 58 before aremove , so the step at time T 58 is during I. Hence, since aremove is successful, we have that T 58 is the last time p executes line 58 during I. Since aremove is a successful list-remove attempt for ptr in I B , by Lemma C.5.2, aremove is the only successful list-remove attempt for ptr in I B . Furthermore, by Corollary C.1.37, aremove ’s corresponding L-event eremove , is an L-remove event for ptr before p invoked I, and so eremove < T 58 . Hence, since by Lemma C.2.30 R(I B ) holds, by Lemma C.1.120, there is a successful list-add attempt aadd for ptr before eremove in I B . Thus, by Lemma C.5.1, aadd is the only successful list-add attempt for ptr in I B . Finally, since eremove is aremove ’s corresponding L-event, and by Lemma C.2.30 P (I B ), Q(I B ), and R(I B ) hold, by Corollary C.2.2, eremove is the last L-event before aremove in I B . Hence, eremove is the last L-event in Iaexclude where Iaexclude is the prefix of I B up to but excluding aremove . remove remove Claim C.5.46.1. ptr is active in Iaexclude . remove Proof. Since aadd < eremove and eremove < aremove , by transitivity, aadd < aremove , and so aadd is in Iaexclude . Hence, since aadd is the only successful list-add attempt for ptr in I B and Iaexclude is the remove remove prefix of I B , it follows there is a single successful list-add attempt for ptr in Iaexclude . Furthermore, remove since aremove is not in Iaexclude , aremove is the only successful list-remove attempt for ptr in I B , and remove Iaexclude is the prefix of I B , we have that there are no successful list-remove attempts for ptr in remove exclude Iaremove . Therefore, by Definition C.5.27, ptr is active in Iaexclude as wanted. Claim C.5.46.1 remove Claim C.5.46.2. From eremove onwards in Iaexclude there are no successful list-add or list-remove remove attempts. Proof. Since eremove is the last L-event in Iaexclude , by Lemma C.2.30 P (Iaexclude ), Q(Iaexclude ), and remove remove remove exclude R(Iaremove ) hold, and eremove is an L-remove event for ptr, by Lemma C.2.5, from eremove onwards in Iaexclude there is at most one successful list-remove attempt for ptr and no other successful remove list-remove or list-add attempt for any pointer. Therefore, since aremove is the only successful listremove attempt for ptr in I B and aremove is not in Iaexclude , we have that from eremove onwards in remove exclude Iaremove there are no successful list-add or list-remove attempt as wanted. Claim C.5.46.2 Claim C.5.46.3. aremove is a successful list-remove attempt for ptr between prev(Iaexclude , ptr) remove and some pointer. 189

Proof. Recall that aremove is a successful list-remove attempt for ptr. Let aremove be a successful list-remove attempt for ptr between prev ptr and some pointer. We must prove that prev ptr = prev(ptr, Iaexclude ). Since Iaexclude is finite, by Claim C.5.46.1 ptr is active in Iaexclude , eremove is remove remove remove exclude the last L-event in Iaremove , eremove is an L-remove event, and by Claim C.5.46.2 from eremove onwards in Iaexclude there are no successful list-add or list-remove events, by Definition C.5.34, ptr remove is in List(Ieexclude ) exactly once and prev(Iaexclude , ptr) is immediately before ptr in List(Ieexclude ) remove remove remove exclude exclude exclude where Ieremove is the prefix of Iaremove up to but excluding eremove . Note that since Iaremove is a prefix of I B , Ieexclude is also the prefix of I B up to but excluding eremove . Since aremove is a remove list-remove attempt for ptr between prev ptr and some pointer in I B and by Lemma C.2.30 Q(I B ) holds, we have that before aremove in I B there is a L-remove event e for ptr such that if Ieexclude is the prefix of I B up to but excluding e, then ptr is in List(Ieexclude ) exactly once and prev ptr is the pointer preceding ptr in List(Ieexclude ). Since e and eremove are both L-remove events for ptr in I B , and by Lemma C.2.30 P (I B ) holds, we have that e = eremove . Hence, Ieexclude is the prefix of I B up to but excluding eremove , and so Ieexclude = Ieexclude . Thus, since prev ptr is the pointer remove exclude preceding ptr in List(Ie ), we have that prev ptr is the pointer preceding ptr in List(Ieexclude ). remove exclude , ptr) is immediately before Therefore, since ptr is in List(Ieexclude ) exactly once and prev(I aremove remove , ptr) as wanted. ptr in List(Ieexclude ), we have that prev ptr = prev(Iaexclude Claim C.5.46.3 remove remove Claim C.5.46.4. For every prefix I of Iaexclude if T 58 is in I, then ptr is active in I and prev(I, ptr) = remove exclude prev(Iaremove , ptr). , by Proof. We first prove that ptr is active in I. Since by Claim C.5.46.1 ptr is active in Iaexclude remove Definition C.5.27, there is a single successful list-add attempt a for ptr in Iaexclude . Since a is the add remove B exclude B only successful list-add attempt for ptr in I and Iaremove is a prefix of I , we have that a = aadd . Hence, since aadd < eremove and eremove < T 58 , by transitivity, aadd < T 58 , and so aadd is in I. Therefore, by Proposition C.5.43, ptr is active in I as wanted. So, prev(I, ptr) is well-defined. , ptr). Since eremove < T 58 , we have that We now prove that prev(I, ptr) = prev(Iaexclude remove exclude eremove is in I. Hence, since I is a prefix of Iaremove and eremove is the last L-event in Iaexclude , remove we have that eremove is the last L-event in I. Furthermore, since by Claim C.5.46.2 from eremove onwards in Iaexclude there are no successful list-add or list-remove events, we have that from eremove remove onwards in I there are no successful list-add or list-remove events. Since I is finite, ptr is active in I, eremove is the last L-event in I, eremove is an L-remove event, and from eremove onwards in I there are no successful list-add or list-remove events, by Definition C.5.34, ptr is in List(I ′ ) exactly once and prev(I, ptr) is immediately before ptr in List(I ′ ) where I ′ is the prefix of I up to but excluding eremove . Note that since I is a prefix of Iaexclude , I ′ is also the prefix of remove Iaexclude up to but excluding eremove . Since Iaexclude is finite, ptr is active in Iaexclude , eremove is remove remove remove exclude the last L-event in Iaremove , eremove is an L-remove event, and from eremove onwards in Iaexclude remove there are no successful list-add or list-remove attempts, by Definition C.5.34, ptr is in List(I ∗ ) exactly once and prev(Iaexclude , ptr) is immediately before ptr in List(I ∗ ) where I ∗ is the prefix of remove exclude Iaremove up to but excluding eremove . Hence, since I ′ is the prefix of Iaexclude up to but excluding remove eremove , we have that I ′ = I ∗ . Thus, since prev(Iaexclude , ptr) is immediately before ptr in List(I ∗ ), remove we have that prev(Iaexclude , ptr) is immediately before ptr in List(I ′ ). Therefore, since ptr is remove ′ in List(I ) exactly once and prev(I, ptr) is immediately before ptr in List(I ′ ), we have that prev(I, ptr) = prev(Iaexclude , ptr) as wanted. Claim C.5.46.4 remove Claim C.5.46.5. There are no successful list-acquire-next attempts for ptr after T 58 in I B . Proof. Suppose, for contradiction, there is a successful list-acquire-next attempt aacquire for ptr after T 58 in I B . There are two cases. 190

Case 1. aremove < aacquire . Let I be the prefix of I B up to and including aacquire . Hence, since aacquire is a successful listacquire-next attempt for ptr, by Lemma C.5.37, ptr is active in I. Thus, by Definition C.5.27, there are no successful list-remove attempts for ptr in I. Therefore, since I is the prefix of I B up to and including aacquire , we have that there are no successful list-remove attempts for ptr before aacquire in I B . However, since aremove < aacquire , we have that there is a successful list-remove attempt for ptr before aacquire in I B , a contradiction. Case 2. aacquire < aremove . Hence, since T 58 < aacquire , we have that T 58 < aacquire < aremove . Thus, there is a prefix I of Iaexclude up to and including aacquire such that T 58 is in I. So, by Claim C.5.46.4, remove prev(I, ptr) = prev(Iaexclude , ptr). Hence, since the last step of I, aacquire , is a successful listremove acquire-next attempt for ptr, by Proposition C.5.41, aacquire is a successful list-acquire-next attempt for ptr after prev(I, ptr). Thus, since prev(I, ptr) = prev(Iaexclude , ptr), we have that aacquire is remove exclude a successful list-acquire-next attempt for ptr after prev(Iaremove , ptr). Since Iaexclude is finite, and remove exclude , ptr) ∈ C ∪ {&H}. by Claim C.5.46.1 ptr is active in Iaexclude , by Proposition C.5.35, prev(I aremove remove Hence, by Definition C.1.5, aacquire is of the form CAS((∗prev(Iaexclude , ptr)).next, (v, ∗, ∗, ∗), (v + remove , ptr)).next.view = v 1, ∗, ∗, ∗)) for some view v. Thus, since aacquire is successful, (∗prev(Iaexclude remove at the step before aacquire , and (∗prev(Iaexclude , ptr)).next.view = v + 1 at aacquire . So, since remove exclude , ptr)).next.view is monotonprev(Iaexclude , ptr) ∈ C ∪{&H}, by Observation C.1.10, (∗prev(I aremove remove ically increasing, and T 58 < aacquire < aremove , it follows that (1) (∗prev(Iaexclude , ptr)).next.view ≤ remove v at T 58 , and (2) (∗prev(Iaexclude , ptr)).next.view > v at the step before a remove . Since by remove exclude Claim C.5.46.3 aremove is a list-remove attempt for ptr between prev(Iaremove , ptr) and some , ptr)).next, (v ′ , ∗, ∗, ∗), (v ′ + pointer, by Definition C.1.5 aremove is of the form CAS((∗prev(Iaexclude remove ′ 58 1, ∗, ∗, ∗)) for some view v . Hence, since T is the time of p’s last execution of line 58 before aremove , we have that p saw that (∗prev(Iaexclude , ptr)).next.view = v ′ at T 58 . Thus, since by remove exclude 58 (1) (∗prev(Iaremove , ptr)).next.view ≤ v at T , we have that v ′ ≤ v. Therefore, since aremove is successful, we have that (∗prev(Iaexclude , ptr)).next.view = v ′ at the step before aremove , and since remove ′ exclude v ≤ v, we have that (∗prev(Iaremove , ptr)).next.view ≤ v at the step before aremove . However, by (2) (∗prev(Iaexclude , ptr)).next.view > v at the step before aremove , a contradiction. Claim C.5.46.5 remove We now finish the proof of Lemma C.5.46. Let I 58 be the prefix of I B up to and including T 58 . Hence, since by Claim C.5.46.5 there are no successful list-acquire-next attempts for ptr after T 58 in I B , by Definition C.5.9, A(I 58 , ptr) = A(I B , ptr). Furthermore, since T 58 is in I 58 and T 58 < aremove , we have that I 58 is also the prefix of Iaexclude up to and including T 58 . Thus, by remove Claim C.5.46.4, ptr is active in I 58 and prev(I 58 , ptr) = prev(Iaexclude , ptr). Since I 58 is finite, and remove 58 58 ptr is active in I , by Proposition C.5.45, (∗prev(I , ptr)).next.acquisitions = A(I 58 , ptr) + 1 at the end of I 58 . Hence, since prev(I 58 , ptr) = prev(Iaexclude , ptr), and A(I 58 , ptr) = A(I B , ptr), we remove exclude B have that (∗prev(Iaremove ), ptr).next.acquisitions = A(I , ptr) + 1 at the end of I 58 (equivalently, T 58 ). Thus, since T 58 is the time of p’s last execution of line 58 before aremove , and by Claim C.5.46.3 aremove is a successful list-remove attempt for ptr between prev(Iaexclude , ptr) and some pointer, we remove B , ptr) + 1 on line 58 at T 58 . have that p saw that (∗prev(Iaexclude , ptr)).next.acquisitions = A(I remove Hence, since T 58 is the last time p executes line 58 before aremove during I, and p executes e on line 62 immediately after aremove on line 61 during I, it follows that the second parameter of e is −(A(I B , ptr) + 1). Therefore, e = F&A((∗ptr).revocations, −(A(I B , ptr) + 1)) as wanted. We now prove 2. Let I be the prefix of I B up to and including e. Since T 58 < aremove and aremove < e, by transitivity, T 58 < e, and so I 58 is a prefix of I. Therefore, since A(I 58 , ptr) = A(I B , ptr), by Definition C.5.9, A(I, ptr) = A(I B , ptr) as wanted. Lemma C.5.46 191

C.5.4

B correctly manages cells

In this section, we finish the proof of the B correctly manages cells theorem. Recall that all that remains is to prove the third bullet, i.e., every operation on an object of the cell pointed to by ptr in I B is after an AllocateCell operation whose response is ptr, and is before any FreeCell(ptr) operation. We start by proving the first half. Proposition C.5.47. For every ptr ∈ C and operation o on and object of the cell pointed to by ptr in I B , there is an AllocateCell operation whose response is ptr before o in I B . Proof. Consider any operation o on ptr in I B . Let opx be the operation execution that o was performed during. Since there are no operations on any pointer before line 2 in opx, we have that the process that executed opx performed an AllocateCell operation oA on line 2 before o during opx in I B . Let p be the process that executed opx. There are two cases. Case 1. oA ’s response is ptr. Hence, since oA is before o in I B , there is an AllocateCell operation whose response is ptr before o in I B as wanted. Case 2. oA ’s response is not ptr. Let I be the prefix of I B up to and including o. Since oA ’s response is not ptr, we have that o is not on line 5, 12, 13, or 113 during an invocation of the Relinquish procedure invoked on line 7. Hence, since the last step of I is p performing an operation on an object of the cell pointed to by ptr ∈ C, by Lemma C.5.21, R(I − , opx, ptr) ≥ 1 where I − is the prefix of I excluding the last step. Thus, by Definition C.5.8, p performed a successful list-acquire-next attempt aacquire for ptr before o in I B . Let I ′ be the prefix of I B up to and including aacquire . Since the last step of I ′ , aacquire , is a successful list-acquire-next attempt for ptr, by Lemma C.5.37, ptr is active in I ′ , and so by Definition C.5.27, there is a successful list-add attempt for ptr in I ′ . Hence, by Corollary C.1.37, there is an L-add event for ptr in I ′ . Thus, since I ′ is the prefix of I B up to and including aacquire , and aacquire is before o, we have that there is an L-add event for ptr before o in I B . So, by Corollary C.1.24, there is an A-add event eadd for ptr before o. Let q be the process that executed eadd . Hence, by Definition C.1.5, q executed eadd during an invocation I of the DoLowLevelOp with parameters (AddCell, ptr). Thus, q invoked I on line 3 during an invocation I ′ of the DoHighLevelOp procedure, and so p executed line 2 with response ptr during I ′ . Therefore, since p’s execution of line 2 during I ′ is before p invoked I, p executed eadd during I, and eadd is before o, by transitivity, there is an AllocateCell operation whose response is ptr before o in I B as wanted. Proposition C.5.47 Now all that remains is to prove the second half of the third bullet of the B correctly manages cells theorem. Recall from the last section that our strategy for doing so is to prove that for all times at and after a FreeCell(ptr) operation, no process has the right to access ptr (Lemma C.5.49). Proposition C.5.48. If I B is finite, then A(I B , ptr) − X(I B , ptr) ≥ −1. Proof. Consider any ptr. Since by Algorithm 4 the responses on line 2 are unique, by Corollary C.5.16, there is at most one operation execution in I B , say opxptr , such that R(I B , opxptr , ptr) ≥ −1, and every other operation execution opx in I B has R(I B , opx, ptr) ≥ 0. Therefore, X R(I B , opx, ptr) ≥ −1 opx is an operation execution in I B

and so by Observation C.5.10 A(I B , ptr) − X(I B , ptr) ≥ −1 as wanted. 192

Proposition C.5.48

Lemma C.5.49. Consider any ptr ∈ C, any FreeCell(ptr) operation oF in I B , and finite prefix I of I B such that oF is in I. By Lemma C.5.7, there is an AllocateCell operation oA whose response is ptr before oF in I B which is unique by Algorithm 4, so oA is in I. Let opxptr be the operation execution that oA was performed during, so opxptr was invoked in I. Then, R(I, opxptr , ptr) = −1 and R(I, opx, ptr) = 0 for every operation execution opx ̸= opxptr in I. Proof. Let p be the process that executed oF and let I be the invocation of the Relinquish procedure that p executed oF during. Hence, p found the condition on line 114 to be true during I. Let erevocation be the execution of line 113 during I. Hence, since oF has parameters ptr, erevocation is of the form F&A((∗ptr).revocations, 1), so by Definition C.1.5, erevocation is a revocation event for ptr. Furthermore, since p found the condition on line 114 to be true during I, we have that the response of erevocation is −1. Since ptr ∈ C, by definition, (∗ptr).revocations is initially 0. Furthermore, by Observation C.1.6, the only steps that change the value of (∗ptr).revocations are acquire-copy events for ptr and revocation events for ptr. Hence, since (∗ptr).revocations is initially 0, each revocation event for ptr increases the value of (∗ptr).revocations by 1, and the response of erevocation is −1, we have that there is an acquire-copy event eacquire−copy for ptr before erevocation in I B . Thus, by Lemma C.5.4, eacquire−copy is the only acquire-copy event for ptr in I B . Furthermore, by Lemma C.5.46, eacquire−copy is F&A((∗ptr).revocations, −(A(I B , ptr) + 1)). Since the response of erevocation is −1, we have that the (∗ptr).revocations = 0 at erevocation . Hence, since (∗ptr).revocations is initially 0, by Observation C.1.6 the only steps that change the value of (∗ptr).revocations are acquire-copy events for ptr and revocation events for ptr, eacquire−copy is the only acquire-copy event for ptr in I B , eacquire−copy is F&A((∗ptr).revocations, −(A(I B , ptr) + 1)), each revocation event for ptr increases the value of (∗ptr).revocations by 1, and eacquire−copy < erevocation , we have that there are exactly A(I B , ptr) + 1 revocation events for ptr before or at erevocation in I B . Let Ieinclude be the prefix of I B up to and including erevocation . Hence, by revocation Definition C.5.9, X(Ieinclude , ptr) = A(I B , ptr) + 1. Thus, since Ieinclude is finite, by Proposirevocation revocation include include B tion C.5.48, A(Ierevocation , ptr) − X(Ieinclude , ptr) ≥ −1, and so A(I erevocation , ptr) ≥ A(I , ptr). revocation Hence, since Ieinclude is a prefix of I B , by Definition C.5.9, A(Ieinclude , ptr) ≤ A(I B , ptr). revocation revocation include B Therefore, A(Ierevocation , ptr) = A(I , ptr). We now prove that there are no successful list-acquire-next attempts or revocation events for ptr after erevocation in I B . Since A(Ieinclude , ptr) = A(I B , ptr) and Ieinclude is the prefix of revocation revocation B I up to and including erevocation , by Definition C.5.9, there are no more successful list-acquirenext attempts for ptr after erevocation in I B . Now suppose, for contradiction, there is a revocation event for ptr after erevocation in I B . Let e be the first revocation event for ptr after erevocation in I B and let Ieinclude be the prefix of I B up to and including e. Since e is the first revocation event for ptr after erevocation and Ieinclude is the prefix of I B up to and including erevocation , revocation include include by Definition C.5.9, X(Ie , ptr) = X(Ierevocation , ptr) + 1. Hence, since X(Ieinclude , ptr) = revocation B A(I , ptr) + 1, we have that X(Ieinclude , ptr) = A(I B , ptr) + 2. Since there are no successful list-acquire-next attempts for ptr after erevocation in I B , by Definition C.5.9, A(Ieinclude , ptr) = A(Ieinclude , ptr), and so since A(Ieinclude , ptr) = A(I B , ptr), we have that A(Ieinclude , ptr) = revocation revocation A(I B , ptr). Therefore, A(Ieinclude , ptr) − X(Ieinclude , ptr) = −2. However, since Ieinclude is finite, by Proposition C.5.48, A(Ieinclude , ptr) − X(Ieinclude , ptr) ≥ −1, a contradiction. Since Ieinclude is the prefix of I B up to and including erevocation , erevocation < oF , and I is a revocation finite prefix of I B such that oF is in I, we have that Ieinclude is a prefix of I. Hence, since there revocation are no successful list-acquire-next attempts or revocation events for ptr after erevocation in I B , by Definition C.5.9, A(Ieinclude , ptr) = A(I, ptr) and X(Ieinclude , ptr) = X(I, ptr). Thus, since revocation revocation include B B , ptr) + 1, we have that A(I, ptr) = A(Ierevocation , ptr) = A(I , ptr) and X(Ieinclude , ptr) = A(I revocation A(I B , ptr) and X(I, ptr) = A(I B , ptr) + 1, and so A(I, ptr) − X(I, ptr) = −1. Thus, since I is 193

finite, by Observation C.5.10 X

R(I, opx, ptr) = −1.

opx is an operation execution in I

Since opxptr executed oA during opxptr in I and oA ’s response is ptr, by Corollary C.5.16, we have that R(opxptr , ptr, I) ≥ −1. Furthermore, since by Algorithm 4 there is at most one AllocateCell operation with response ptr in I B , we have that opxptr is the only operation execution in I that receive ptr as a response on line 2. Hence, for every operation execution opx ̸= opxptr in I if the process that executed opx executed line 2 during opx in I, then P its response is not ptr. Thus, by Corollary C.5.16, R(I, opx, ptr) ≥ 0. Therefore, since (1) R(I, opx, ptr) = −1, (2) opxptr is an operation execution in I (3) R(I, opxptr , ptr) ≥ −1, and (4) for every operation execution opx ̸= opxptr in I R(I, opx, ptr) ≥ 0, we have that R(I, opxptr , ptr) = −1 and R(I, opx, ptr) = 0 for every operation execution opx ̸= opxptr in I as wanted. Lemma C.5.49 Proposition C.5.50. For every ptr ∈ C and operation o on an object of the cell pointed to by ptr in I B , there are no FreeCell(ptr) operations before o in I B . Proof. Suppose, for contradiction, there is an operation o on an object of the cell pointed to by ptr in I B and there is a FreeCell(ptr) operation oF before o in I B . Let opx be the operation execution that o was performed during, and let Ioexclude be the prefix of I B up to but excluding o. Hence, since oF is before o, we have that oF is in Ioexclude . There are two cases. Case 1. The process that executed opx executed line 2 during opx in Ioexclude with response ptr. Let oA be this AllocateCell operation. Since oA ’s response is ptr, by Algorithm 4, oA is the only AllocateCell operation in I B whose response is ptr. Therefore, since Ioexclude is a finite prefix of I B such that oF is in Ioexclude , by Lemma C.5.49, R(Ioexclude , opx, ptr) = −1. However, since Ioexclude is a finite prefix of I B such that the step after Ioexclude in I B is the process that executed opx performing an operation on an object of the cell pointed to by ptr ∈ C during opx, by Lemma C.5.21, R(Ioexclude , opx, ptr) ≥ 0, a contradiction. Case 2. Otherwise. Hence, o was not executed on line 5, 12, 13, or 113 during an invocation of the Relinquish procedure invoked on line 7. Therefore, since Ioexclude is a finite prefix of I B such that the step after Ioexclude in I B is the process that executed opx performing an operation on an object of the cell pointed to by ptr ∈ C during opx, by Lemma C.5.21, R(Ioexclude , opx, ptr) ≥ 1. However, since Ioexclude is a finite prefix of I B such that oF is in Ioexclude , by Lemma C.5.49, R(Ioexclude , opx, ptr) ≤ 0, a contradiction. Proposition C.5.50 Theorem C.5.51. For every ptr ∈ C the following are true. 1. There is at most one AllocateCell operation whose response is ptr, and at most one FreeCell(ptr) operation in I B . 2. If there is a FreeCell(ptr) operation in I B , then it is after an AllocateCell operation whose response is ptr. 3. Every operation on an object of the cell pointed to by ptr in I B is after an AllocateCell operation whose response is ptr, and is before any FreeCell(ptr) operation. Proof. Algorithm 4 and Lemma C.5.6 imply 1, Lemma C.5.7 implies 2, and Propositions C.5.47 and C.5.50 imply 3. Theorem C.5.51

194

C.5.5

B is space-efficient

This section proves the B is space-efficient theorem (Theorem C.5.53). Proposition C.5.52. For every operation execution opx in I B define the set Acquired(I B , opx) as ptr ∈ Acquired(I B , opx) if and only if R(I B , opx, ptr) > 0. Then, |Acquire(I B , opx)| ≤ 3. Proof. There are two cases. Case 1. The process that executed opx has not executed line 7 during opx in I B . Hence, by Lemma C.5.15, R(I B , opx, ptr) ≥ 0 for every ptr. Therefore, since by Lemma C.5.26 P B B ptr R(I , opx, ptr) ≤ 3, we have that |Acquire(I , opx)| ≤ 3 as wanted. Case 2. The process that executed opx has executed line 7 during opx in I B . Let I be the prefix of I B up to but excluding the time that the process that executed opx executed line 7 during opx in I B . Hence, the process that executed opx has not executed line 7 during opx in P I. Thus, by Lemma C.5.15, R(I, opx, ptr) ≥ 0 for every ptr. So, since by Lemma C.5.26 B ptr R(I, opx, ptr) ≤ 3, we have that |Acquire(I, opx)| ≤ 3. Observe that, after I in I , the process that executed opx performs zero successful list-acquire-next attempts and at most one revocation event during opx. Hence, Acquire(I B , opx) ⊆ Acquire(I, opx). Therefore, since |Acquire(I, opx)| ≤ 3, we have that |Acquire(I B , opx)| ≤ 3 as wanted. Proposition C.5.52 Theorem C.5.53. Suppose I B is finite. Let Allocate(I B ) be the set of pointers which have been allocated in I B , i.e., ptr ∈ Allocate(I B ) if and only if there is an AllocateCell operation in I B with response ptr. Likewise, let F ree(I B ) be the set of pointers which have been freed in I B , i.e., ptr ∈ F ree(I B ) if and only if there is a FreeCell(ptr) operation in I B . Then, |Allocate(I B ) \ F ree(I B )| ≤ 6c + 1 where c is the point contention in I B . Proof. We note that since by Algorithm 4 the response of every AllocateCell operation is in C, Allocate(I B ) ⊆ C. Furthermore, since I B is finite, we have that Allocate(I B ) is finite. Let P ending(I B ) be defined as follows. ptr ∈ P ending(I B ) if and only if there is a pending operation execution opx in I B such that the process that executed opx executed line 2 during opx in I B and received response ptr. Since by definition there are c pending operation executions in I B , we have that |P ending(I B )| ≤ c. Furthermore, since by Algorithm 4 every response to an AllocateCell operation is in C, we have that P ending(I B ) ⊆ C. P ending(I B ) is useful for the following reason. Claim C.5.53.1. For every ptr ∈ Allocate(I B )\P ending(I B ) there is a unique operation execution opxptr in I B such that the process that executed opxptr executed line 2 during opxptr in I B and received response ptr. Furthermore, opxptr is complete in I B . Proof. Consider any ptr ∈ Allocate(I B ) \ P ending(I B ). Since ptr ∈ Allocate(I B ), we have that there is an operation execution opxptr in I B such that the process that executed opxptr executed line 2 during opxptr in I B and received response ptr. Hence, by Algorithm 4, this execution of line 2 is the only AllocateCell operation whose response is ptr in I B , and so opxptr is unique. Since ptr ∈ / P ending(I B ), by the definition of P ending(I B ), for every pending operation execution opx B in I , the process that executed opx received a response other than ptr on line 2 during opx in I B . Hence, opxptr is not a pending operation execution in I B . Therefore, since opxptr is an operation execution in I B , we have that opxptr is complete in I B as wanted. Claim C.5.53.1

195

We now define another useful set of pointers, Acquired(I B ), as ptr ∈ Acquired(I B ) if and only if there is a pending operation execution opx in I B with R(I B , opx, ptr) > 0. Hence, [ Acquire(I B , opx) Acquired(I B ) = opx is a pending operation execution in I B

where Acquire(I B , opx) is defined in Proposition C.5.52. Thus, since there are c pending operation executions in I B and by Proposition C.5.52 |Acquire(I B , opx)| ≤ 3, we have that |Acquired(I B )| ≤ 3c. Since |P ending(I)| ≤ c and |Acquired(I)| ≤ 3c, we have that |P ending(I)∪Acquired(I)| ≤ 4c. For brevity, let E1 = P ending(I) ∪ Acquired(I) where “E” stands for exceptions, so |E1 | ≤ 4c. Claim C.5.53.2. For every ptr ∈ Allocate(I B ) \ E1 there is one L-remove event ptr in I B . Proof. Consider any ptr ∈ Allocate(I B ) \ E1 . Hence, ptr ∈ Allocate(I B ) \ P ending(I B ), so by Claim C.5.53.1, there is a unique operation execution opxptr in I B such that the process that executed opxptr executed line 2 during opxptr in I B and received response ptr, and opxptr is complete in I B . Thus, the process that executed opxptr , say p, invoked and exited the DoLowLevelOp procedure on line 6 during opxptr in I B . Let I denote the invocation of this procedure. Since p received ptr as a response on line 2 during opxptr we have that the parameters of I are (RemoveCell, ptr). Hence, since by Lemma C.2.30 P (I B ) holds, by Lemma C.1.107, there is a L-remove event for ptr in I B . Therefore, by P (I B ), this is the only L-remove event for ptr in I B as wanted. Claim C.5.53.2 Claim C.5.53.3. For every set S with |S| ≤ 4c + 1 if |Allocate(I B ) \ S| ≤ 2c, then |Allocate(I B ) \ F ree(I B )| ≤ 6c + 1. Proof. If |Allocate(I B ) \ S| ≤ 2c, then since |S| ≤ 4c + 1, we have that |Allocate(I B )| ≤ 6c + 1, and so |Allocate(I B ) \ F ree(I B )| ≤ 6c + 1 as required. Claim C.5.53.3 For every ptr ∈ Allocate(I B )\E1 let L(ptr) be the unique L-remove event for ptr in I B identified by Claim C.5.53.2. Since |P ending(I B )∪Acquired(I B )| ≤ 4c, by Claim C.5.53.3, the theorem holds if |Allocate(I B ) \ E1 | = 0, so it suffices to assume that Allocate(I B ) \ E1 ̸= ∅. Hence, there is at least one element in Allocate(I B ) \ E1 . Thus, since Allocate(I B ) is finite, we have that there is a last L-remove event for some pointer in Allocate(I B ) \ E1 in I B . Let ptrlast ∈ Allocate(I B ) \ E1 be this pointer, i.e., and for every ptr ∈ Allocate(I B ) \ E1 L(ptr) ≤ L(ptrlast ). Note that since |E1 | ≤ 4c, we have that |E1 ∪ {ptrlast }| ≤ 4c + 1. As with E1 , we define E2 = E1 ∪ {ptrlast } or equivalently E2 = P ending(I B ) ∪ Acquired(I B ) ∪ {ptrlast }, so |E2 | ≤ 4c + 1. Claim C.5.53.4. For every ptr ∈ Allocate(I B ) \ E2 there is a successful list-remove attempt for ptr in I B . Proof. Consider any ptr ∈ Allocate(I B ) \ E2 . Since ptr ̸= ptrlast , we have that L(ptr) ̸= L(ptrlast ). Hence, since for every ptr ∈ Allocate(I B )\E1 L(ptr) ≤ L(ptrlast ), we have that L(ptr) < L(ptrlast ). Thus, there is a next L-event after L(ptr) in I B ; say e. Therefore, since by Lemma C.2.30 R(I B ) holds, we have that there is a successful list-remove attempt for ptr in I B as wanted. Claim C.5.53.4 Since Allocate(I B ) is finite, we have that |Allocate(I B ) \ E2 | = n for some non-negative integer n. Since |E2 | ≤ 4c + 1, by Claim C.5.53.3, the theorem holds if |Allocate(I B ) \ E2 | ≤ 2c and so we way assume that n > 2c. Hence, since c ≥ 0, we have that n is a positive integer. Claim C.5.53.5. There is an acquire-copy event for every ptr ∈ Allocate(I B ) \ E2 except at most c in I B . Let Coalesced(I B ) be the maximal subset of Allocate(I B ) \ E2 such that every pointer in Coalesced(I B ) has an acquire-copy event for it in I B , so |Coalesced(I B )| ≥ n − c. 196

Proof. Suppose, for contradiction, for some set {ptr1 , . . . , ptrc+1 } ⊆ Allocate(I B ) \ E2 of size c + 1 there is not an acquire-copy event for every ptri in I B . Consider an 1 ≤ i ≤ c+1. By Claim C.5.53.4, there is a successful list-remove attempt ai for ptri in I B . Let pi be the process that executed this successful list-remove attempt. Hence, since ai is a list-remove attempt for ptri , by Definition C.1.5, pi executed ai during an invocation Ii of the DoRemoveCell procedure with a second parameter of ptri . Thus, since ai is a successful list-remove attempt for ptri , it follows that pi will execute line 62 during Ii on its next step. So, if pi executes this step, then since Ii ’s second parameter is ptri , by Definition C.1.5, it would be an acquire-copy event for ptri . Hence, since by assumption there is not an acquire-copy event for ptri in I B , we have that pi does not execute this step during I B . Thus, pi does not exit Ii in I B , and so if opxi is the operation execution pi executed ai during, then opxi is pending in I B . Since there is at most one successful list-remove attempt per invocation of the DoRemoveCell procedure, we have that for every 1 ≤ i, j ≤ c + 1 if i ̸= j, then ai and aj are executed during different invocations of the DoRemoveCell procedure. Hence, since ai is executed during Ii and aj is executed during Ij , we have that Ii ̸= Ij . Thus, since each process is executing at most one invocation of the DoRemoveCell procedure at a time and for every 1 ≤ i ≤ c + 1 pi does not exit Ii in I B , it follows that for every 1 ≤ i, j ≤ c + 1 if i ̸= j, then pi ̸= pj . So, since opxi is the operation execution pi executed ai during, we have that for every 1 ≤ i, j ≤ c + 1 if i ̸= j, then opxi ̸= opxj . Therefore, since for every 1 ≤ i ≤ c + 1 opxi is pending in I B , we have that there are c + 1 pending operation executions in I B . However, by the definition of c, there are c pending operation executions in I B , a contradiction. Claim C.5.53.5 Claim C.5.53.6. For every ptr ∈ Coalesced(I B ) there is a revocation event for ptr with response −1 in I B . Proof. Since ptr ∈ Coalesced(I B ), by Claim C.5.53.5, ptr ∈ Allocate(I B ) \ E2 . Hence, since E2 = P ending(I B ) ∪ Acquired(I B ) ∪ {ptrlast }, we have that ptr ∈ Allocate(I B ) \ P ending(I B ). Thus, by Claim C.5.53.1, there is a unique operation execution opxptr in I B such that the process that executed opxptr executed line 2 during opxptr in I B and received response ptr, and opxptr is complete in I B . Furthermore, since ptr ∈ Coalesced(I B ), by Claim C.5.53.5, there is an acquire-copy event e for ptr in I B . Hence, by Lemma C.5.46, e is F&A((∗ptr).revocations, −(A(I B , ptr) + 1)) and if Ieinclude is the prefix of I B up to and including e, then A(Ieinclude , ptr) = A(I B , ptr). Let Ieexclude be the prefix of I B up to but excluding e. Hence, since the last step of Ieinclude is not a successful list-acquire-next attempt, by Definition C.5.9, A(Ieexclude , ptr) = A(Ieinclude , ptr) and so A(Ieexclude , ptr) = A(I B , ptr). We claim that A(I B , ptr) − X(I B , ptr) = −1. For every operation execution opx in I B opx is either complete or pending in I B . We first consider complete operation executions in I B . Since opxptr is complete in I B and the process that executed opxptr executed line 2 during opxptr and received response ptr, by Corollary C.5.24, R(I B , opxptr , ptr) = −1. Now consider any complete operation execution opx in I B other than opxptr . Since opxptr is the only operation execution in I B such that the process that executed opxptr received ptr on line 2 during opxptr in I B , we have that the process that executed opx received a different response on line 2 during opx, and so by Corollary C.5.24, R(I B , opx, ptr) = 0. Now consider any pending operation execution opx in I B . Hence, since opxptr is complete in I B , we have that opx ̸= opxptr . Since ptr ∈ / Acquired(I B ), by the definition of Acquire(I B ), we have that R(I B , opx, ptr) ≤ 0. Furthermore, since opxptr is the only operation execution in I B such that the process that executed opxptr received ptr on line 2 during opxptr in I B , we have that if the process that executed opx executed line 2 during opx, then it received a response other than ptr, and so by Corollary C.5.16, R(I B , opx, ptr) ≥ 0. Together, these imply that R(I B , opx, ptr) = 0. Hence, since (1) R(I B , opxptr , ptr) = −1, (2) for every complete

197

operation execution opx in I B other than opxptr R(I B , opx, ptr) = 0, and (3) for every pending operation execution opx in I B R(I B , opx, ptr) = 0, we have that X R(I B , opx, ptr) = −1. opx is an operation execution in I B

Therefore, since I B is finite, by Observation C.5.10, A(I B , ptr) − X(I B , ptr) = −1. Since A(I B , ptr) − X(I B , ptr) = −1, we have that X(I B , ptr) = A(I B , ptr) + 1. Let erevocation be the A(ptr, I B ) + 1th revocation event for ptr in I B , so by Definition C.5.9 erevocation is the last revocation event for ptr in I B . We claim that e < erevocation . Suppose, for contradiction, erevocation ≤ e. Hence, since erevocation is the last revocation event for ptr in I B , we have that there are no revocation events for ptr after e in I B . Let q be the process that performed e and suppose q did so during an operation execution opx. Hence, since the step after Ieexclude in I B is q performing an acquire-copy event for ptr ∈ C (because ptr ∈ Allocate(I B )), by Lemma C.5.21, R(Ieexclude , opx, ptr) ≥ 1. Since opx is an operation execution in I B , as proved above, R(I B , opx, ptr) is 0 or −1, and so R(I B , opx, ptr) < 1. Thus, since R(Ieexclude , opx, ptr) ≥ 1, and R(I B , opx, ptr) < 1, by Definition C.5.9, there is revocation event for ptr in I B that is not in Ieexclude . Therefore, since Ieexclude is the prefix of I B up to but excluding e, we have that there is a revocation event for ptr after e in I B . However, there are no revocation events for ptr after e in I B , a contradiction. We now finish the proof of Claim C.5.53.6. Since ptr ∈ C, by Observation C.1.6, only acquirecopy events for ptr and revocation events for ptr change (∗ptr).revocations. Furthermore, since e is an acquire-copy event for ptr in I B , by Lemma C.5.4, e is the only acquire-copy event for ptr in I B . Hence, since erevocation is the last revocation event for ptr in I B , and e < erevocation , we have that erevocation is the last operation on (∗ptr).revocations in I B . Since ptr ∈ C, we have that (∗ptr).revocations is initially 0. Hence, since there are exactly A(I B , ptr) + 1 revocation events for ptr in I B (because X(I B , ptr) = A(I B , ptr) + 1), each revocation event for ptr increases (∗ptr).revocations by 1, e decreases (∗ptr).revocations by A(I B , ptr) + 1, and e is the only acquirecopy event for ptr in I B , it follows that (∗ptr).revocations = 0 at the end of I B . Thus, since erevocation is the last operation on (∗ptr).revocations in I B , we have that (∗ptr).revocations = 0 at erevocation . Therefore, since erevocation is a revocation event for ptr, by Definition C.1.5, erevocation is F&A((∗ptr).revocations, 1), and so erevocation ’s response is −1 as wanted. Claim C.5.53.6 Recall that by Claim C.5.53.5, Coalesced(I B ) ⊆ Allocate(I B )\E2 and |Coalesced(I B )| ≥ n−c. Since Allocate(I B ) is finite, we have that |Coalesced(I B )| = m for some non-negative integer, so m ≥ n − c. Since n > 2c, we have that m > c, and since c is a non-negative integer, we have that m > 0. Hence, since m is a non-negative integer, m is a positive integer. Claim C.5.53.7. There is a FreeCell(ptr) operation for every ptr ∈ Coalesced(I B ) except at most c in I B . Let F reed(I B ) be the maximal subset of Coalesced(I B ) such that every pointer ptr ∈ F reed(I B ) has a FreeCell(ptr) operation in I B , so |F reed(I B )| ≥ m − c. Proof. Suppose, for contradiction, for some set {ptr1 , . . . , ptrc+1 } ⊆ Coalesced(I B ) of size c + 1 there is no FreeCell(ptri ) operation in I B . Consider an integer 1 ≤ i ≤ c + 1. By Claim C.5.53.6, there is a revocation event ei for ptri with response −1 in I B by process pi . Hence, since ei is a revocation event for ptri , by Definition C.1.5, pi executed ei during an invocation Ii of the Relinquish procedure with parameter ptri . Thus, since ei is a revocation event for ptri whose response is −1, pi will execute line 114 during Ii on its next step. So, if pi executes this step, then since Ii ’s second parameter is ptri , it would be a FreeCell(ptri ) operation. Hence, since by assumption there is not a FreeCell(ptri ) operation in I B , we have that pi does not execute this step 198

during I B . Thus, pi does not exit Ii in I B , and so if opxi is the operation execution pi executed ei during, then opxi is pending in I B . Since there is at most one revocation event per invocation of the Relinquish procedure, we have that for every 1 ≤ i, j ≤ c + 1 if i ̸= j, then ei and ej are executed during different invocations of the Relinquish procedure. Hence, since ei is executed during Ii and ej is executed during Ij , we have that Ii ̸= Ij . Thus, since each process is executing at most one invocation of the Relinquish procedure at a time and for every 1 ≤ i ≤ c + 1 pi does not exit Ii in I B , it follows that for every 1 ≤ i, j ≤ c + 1 if i ̸= j, then pi ̸= pj . So, since opxi is the operation execution pi executed ei during, we have that for every 1 ≤ i, j ≤ c + 1 if i ̸= j, then opxi ̸= opxj . Therefore, since for every 1 ≤ i ≤ c + 1 opxi is pending in I B , we have that there are c + 1 pending operation executions in I B . However, by the definition of c, there are c pending operation executions in I B , a contradiction. Claim C.5.53.7 We now finish the proof of Theorem C.5.53. By Claim C.5.53.7 F reed(I B ) ⊆ Coalesced(I B ) with |F reed(I B )| ≥ m − c such that for every ptr ∈ F reed(I B ) there is a FreeCell(ptr) operation in I B . Hence, by the definition of F ree(I B ), we have that F reed(I B ) ⊆ F ree(I B ). Furthermore, since m ≥ n−c, we have that |F reed(I B )| ≥ n−2c. Hence, since |Allocate(I B )\E2 | = n and |E2 | ≤ 4c+1, we have that |Allocate(I B )| ≤ n + 4c + 1, and so |Allocate(I B )| − |F reed(I B )| ≤ 6c + 1. Since F reed(I B ) ⊆ Coalesced(I B ), and by Claim C.5.53.5 Coalesced(I B ) ⊆ Allocate(I B ), by transitivity, F reed(I B ) ⊆ Allocate(I B ). Hence, since Allocate(I B ) is finite, we have that |Allocate(I B ) \ F reed(I B )| = |Allocate(I B )| − |F reed(I B )|. Thus, since |Allocate(I B )| − |F reed(I B )| ≤ 6c + 1 we have that |Allocate(I B ) \ F reed(I B )| ≤ 6c + 1. Therefore, since F reed(I B ) ⊆ F ree(I B ), we have that |Allocate(I B ) \ F ree(I B )| ≤ 6c + 1 as wanted. Theorem C.5.53

C.6

A is Linearizable, Wait-free, and Space-Efficient

In this section, we show that B being linearizable, wait-free, and having space complexity linear in the point contention implies A has these properties as well. Recall from Definition C.0.1 and Definition C.0.2 that the difference between B and A is the following: (1) B allocates a pointer at most once (in contrast to A which can reallocate a pointer arbitrarily many times); (2) all operations on any object of any cell in C respects the semantics of its type (in contrast to A where the response of an operation on an object of a cell which is not allocated is arbitrary); and (3) an AllocateCell operation whose response is ptr does not change the state assigned to the objects of the cell pointed to by ptr (in contrast to A where an AllocateCell operation whose response is ptr sets the state of each object of the cell pointed to by ptr to its initial state). The strategy for resolving these differences is by mapping each implementation history I A of A to an implementation history I B of B such that: (A) the object histories obtained by removing all implementation steps from of I A and I B , respectively, are the same; (B) the program counter of each process is the same in the ith configuration of I A and I B ; (C) the number of allocated cells is the same in the ith configuration of I A and I B . (A) is the property that lets us prove that A is linearizable because it allows us to reuse the linearization function of B. (B) is the property that lets us prove that A is wait-free because any supposed operation execution in A that takes in infinitely many steps without completing would be an operation execution in B that takes infinitely many steps without completing, contradicting the fact that B is wait-free. (C) is the property that lets us prove that the space complexity of A is linear in the point contention, because at any supposed time t where the number of allocated cells is larger than 6c + 1, where c is the point contention at t, is a time in B where the number of allocated cells is larger than 6c + 1, contradicting the space bound of B. We now sketch how we will build the implementation history I B from I A , and why it resolves differences (1)-(3). The main difficulty in building I B is dealing with (1). To see this, consider algorithm A′ which is the same as A except it uses the memory manager given in Algorithm 4 instead 199

of Algorithm 3, so A′ and B are the same except for differences (2) and (3). Mapping implementation histories of A′ to B is trivial: every implementation history of A′ is an implementation history of B. To see why, we provide a proof sketch for resolving (2) and (3) between A′ and B. Consider any implementation history I of A, and suppose that the prefix of I up to and including the nth step, denoted by In , is an implementation history of B. We sketch why the prefix of I up to and including the n + 1th step is an implementation history of B by resolving (2) and (3). For (2), it suffices to suppose that the n + 1th step in I executes an operation on an object of a cell in C which is not allocated; let pn+1 be the process that executed this step. Since In is an implementation history of B, we have that a one step continuation of In by pn+1 would yield an implementation history of B where a process executes an operation on an object of a cell in C which is not allocated, contradicting 3 of Theorem C.5.51. For (3), it suffices to suppose that the n+1th step in I executes an AllocateCell operation with response ptr, and the state of one of the objects of the cell pointed to by ptr in the n + 1th configuration in I differs from a one-step continuation by the same process in B from In . Since A′ sets the state of each object of the cell pointed to by ptr to its initial state in the n + 1th configuration in I, this implies that some step in In executed an operation on this object. Hence, since In is an implementation history of B, by 3 of Theorem C.5.51, there is an AllocateCell operation whose response is ptr in In . Therefore, there are two AllocateCell operations in I with the same response, which is impossible by Algorithm 4. To deal with difference (1) between A and B, we need to consistently “rename” the response of each AllocateCell operation in I A when building I B so that the response of each AllocateCell operation in I B is unique. Our approach for doing so is simple: use the step number as a source of uniqueness to pick a pointer from C. More precisely, we define an injective function M from N to C (such a function exists because C is infinite), and define the response of an AllocateCell operation during the nth step of I B as M(n). The injectivity of M yields the desired uniqueness of responses to AllocateCell operations in I B . Our task now is two-fold: (I) how do we make sure these changes in the responses to AllocateCell operations reflect in the subsequent configurations in I B ; and (II) how do we assign states to objects of cells. To see why (I) and (II) are delicate, we give some examples. For (I), if a process p receives M(n) as a response to an AllocateCell operation during the nth step of I B it must be that the local variable ptr at each step inside the same invocation of the DoHighLevelOp procedure is also M(n). For (II), in I A it could be the case that every AllocateCell operation returns the same response (this could happen when only a single process takes steps in I A ), but in I B we use infinitely many cells, so after a given step in I A , how do we decide what state to assign each of these cells in I B ? We solve (I) by “tracking” the dissemination of a response from an AllocateCell operation. More precisely, we watermark the jth value of each object or local variable O in the ith configuration of I A (for our purposes, a value is the smallest unit in the state of an object or a local variable), if it is in C as follows. If the ith step of I A does not change the jth value of O, then the ith watermark of the jth value of O is the same as the i − 1th watermark of the jth value of O. If the ith step of I A changes the jth value of O to a value originating from the kth value of some object or local variable O′ , then the ith watermark of the jth value of O is the watermark of the i − 1th watermark of the kth value of O′ . Lastly, if the ith step of I A is an AllocateCell operation, then the ith watermark of the jth value of O is i. This watermarking strategy lets us map states of objects and local variables in the ith configuration of I A to the ith configuration of I B by swapping every value with its watermarked counterpart. More precisely, the jth value of any object or local variable O in the ith configuration of I B is swapped to the output of M on the ith watermark of the jth value of O if it is well-defined, and is the same as the value in I A otherwise. To solve (II), each statically allocated base object or local variable is assigned to its mapped version of the state as described above. This suffices because the objects and local variables are not 200

“renamed”. The case of objects of cells is more delicate because an object O of a cell pointed to ptr may map to many different objects in I B . For example, the response of multiple AllocateCell operations may be ptr in I A , and since each AllocateCell operation is unique in I B , the object O corresponds to multiple different objects in I B . To deal with this ambiguity, we map the current state of O, using the mapping above, to the “latest” version of O in I B , and all other versions of O use the mapping above on the configuration when they were the latest version. More precisely, let W be the set of step numbers up to and including the ith step of I A which perform AllocateCell operations. For every ptr ∈ C \ M[W ]16 , the ith configuration of I A assigns every object of the cell pointed to by ptr to its initial state. Now consider any w ∈ W . Let ptr be the response of the AllocateCell operation performed during the wth step of I A . If for all w < j ≤ i the jth step of I A does not perform an AllocateCell operation whose response is ptr, then the ith configuration of I B assigns state Si ((∗ptr).f ) (the mapped version of (∗ptr).f ) to (∗M(w)).f for every f equal to response, revocations, or next. Otherwise, let j be the minimum w < j ≤ i such that the jth step of I A performs an AllocateCell cell operation whose response is ptr. Then, the ith configuration of I B assigns state Sj−1 ((∗ptr).f ) to (∗M(w)).f . Roadmap. We start by introducing some notation and a basic fact about A. We then define the mapping sketched above from the implementation histories of A to those of B and prove some basic facts about it. We then prove that this mapping actually yields implementation histories of B; this is the majority of the work in this section. Finally, we prove that A is linearizable, wait-free, and has space complexity linear in the point contention using this mapping. Definition C.6.1. We define the set CO of objects of cells as O ∈ CO if and only if for some ptr ∈ C ∪ {&H} O equals either (∗ptr).response, (∗ptr).revocations, or (∗ptr).next. The set of base objects of A are {C, A, L, S} ∪ CO and the memory manager given in Algorithm 3. The set of base objects of B are {C, A, L, S} ∪ CO and the memory manager given in Algorithm 4. Lemma C.6.2. Consider any implementation history I A of A. If two configurations of I A assign states of the form ((t, ∗), ∗) to A, then they assign the same state to A. Proof. Suppose, for contradiction, the ith and jth configurations of I A assign states of the form ((t, ∗), ∗) to A, but they assign different states to A. Let CiA (resp. CjA ) be the ith (resp. jth) configuration of I A . Furthermore, let si (resp. sj ) be the states they assign to A. By assumption, si and sj are of the form ((t, ∗), ∗) but si ̸= sj . Hence, i ̸= j. Without loss of generality, assume i < j. Hence, since si ̸= sj , we have that some process pj set the state of A to sj on the kj th step of I A where kj ∈ (i, j]. Thus, since the state of A is only changed on line 21 or 27, pj executed line 21 or 27 on the kj th step of I A with a third parameter of sj ; say during some invocation Ij of the DoLowLevelOp procedure. Since sj is of the form ((t, ∗), ∗), we have that pj set the state of A = ((t, ∗), ∗) on the kj th step of I A . Therefore, pj received t as a response to its execution of line 10 during Ij . Since the state of C is initially 1, by the definition of F&I, all responses on line 10 are bigger than 0, and so t ̸= 0. Hence, since the state of A is initially ((0, Noop), Null), and si is of the form ((t, ∗), ∗), we have that some process pi set the state of A to si on the ki th step of I A where ki ∈ [1..i]. Thus, since the state of A is only changed on line 21 or 27, pi executed line 21 or 27 on the ki th step of I A with a third parameter of si ; say during some invocation Ii of the DoLowLevelOp procedure. Since si is of the form ((t, ∗), ∗), we have that pi set the state of A = ((t, ∗), ∗) on the ki th step of I A . Therefore, pi received t as a response to its execution of line 10 during Ii . Since pi and pj both received t as a response to an execution of line 10, by the definition of F&I, we have that pi = pj . Furthermore, since pi (resp. pj ) performed this executions 16

This is the function image of a subset, i.e., for a function f : X → Y and S ⊆ X f [S] = {f (s) | s ∈ S}.

201

of line 10 during Ii (resp. Ij ), we have that Ii = Ij . Let pi = pj = p, and let Ii = Ij = I. Hence, p performed the ki th and kj th step during I. Let (llo, ptr) be the parameters of I. Since p received t as a response on line 10 during I, it follows that every execution of line 21 and 27 during I has a third parameter of ((t, llo), ptr). Therefore, since p executed the ki th and kj th step during I, and the third parameter of the ki th (resp. kj th) step is si (resp. sj ), we have that si = sj . However, si ̸= sj , a contradiction. Lemma C.6.2 C.6.1

A correctness-preserving mapping from implementation histories of A to B

In this section, we define our mapping of implementation histories of A to B and prove some basic facts about it. We start by defining what a value is. For our purposes, a value is the smallest unit in the state of an object or a local variable, as defined below. Observation C.6.3. In both algorithms A and B, the state of every local variable or base object other than the memory manager is a finite sequence of values. For example, • The state of C is a single value n, so the sequence is n. • The state of A and L is of the form ((t, llo), ptr) so the sequences is t, llo, ptr. • The state of S is of the form ((t, llo), s, r) so the sequence is t, llo, s, r. • The state of a cell’s response object is of the form ((t, llo), r) so the sequence is t, llo, r. • The state of a cell’s revocations object is a single value n, so the sequence is n. • The state of a cell’s next object is of the form (v, s, a, ptr) so the sequence is v, s, a, ptr. In all the cases above, when llo = ⟨Apply&CopyResponse, hlo⟩, llo in the above sequence is replaced with Apply&CopyResponse, hlo. Furthermore, in the same fashion as the cases above, the input and output to each operation performed on a local variable or base object is a finite sequence of values. We now define the watermarking scheme we described at the beginning of the section. We note that the phrase “process p set the value (or some index) of some local variable or base object O during some step s” means that p performs a write or CAS operation on O during s. Definition C.6.4 (Watermarks). Consider any implementation history I A = C0A , p1 , C1A , . . . of A. For every CiA , local variable or base object O other than the memory manager of A, and jth index of the state assigned to O in CiA , we define a watermarking function Wi (O, j) as follows. Let v1 , v2 , . . . be the state assigned to O in CiA (see Observation C.6.3). Suppose i > 0, if O is a base object (not a local variable), then O ∈ {A, L} ∪ {(∗ptr).next | ptr ∈ C ∪ {&H}}, and vj ∈ C. 1. If pi does not set the jth index of O during the ith step of I A , then Wi (O, j) = Wi−1 (O, j).17 2. If O is a local variable of pi other than its program counter, then: (a) If O is the local variable ptr of pi on line 2, and pi sets the jth index of O to vj during the ith step of I A because pi performs an AllocateCell operation whose response is vj , then Wi (O, j) = i. (b) If pi sets the jth index of O to vj during the ith step of I A because pi performs a read operation during the ith step of I A on a base object O′ whose kth index of its response A , then W (O, j) = W ′ is vj which is also the kth index of its state in Ci−1 i i−1 (O , k). A (c) If pi sets the jth index of O to vj during the ith step of I because the kth index of one A is v , then W (O, j) = W ′ of pi ’s local variables O′ in Ci−1 j i i−1 (O , k). 3. If O is a base object, and pi sets the jth index of O to vj during the ith step of I A because A is v , then W (O, j) = W ′ the kth index of one of pi ’s local variables O′ in Ci−1 j i i−1 (O , k). In all other cases Wi (O, j) = ⊥. So, by definition, Wi (O, j) ∈ N ∪ {⊥}. 17

A Note that this is not equivalent to saying that the jth index of O is the same in Ci−1 and CiA .

202

For convenience, it is useful to “rename” pointers in A to “fresh” pointers in B, i.e., pointers that were not used in the implementation history of A that we are mapping to B. To define these fresh pointers, we define the set of pointers used in an implementation I A of A below. Definition C.6.5. Consider any implementation history I A of A. Let C(I A ) be defined as ptr ∈ C(I A ) if and only if ptr ∈ C and there is a configuration CiA of I A where CiA assigns state s to a local variable or base object and ptr is an element of s (because s is a sequence Observation C.6.3). We define a set of fresh pointers that is large enough. Note that this set trivially exists when C is uncountable, and it can be shown that it exists even when C is countable by reasoning about the gaps between AllocateCell operations in any implementation history of A. Observation C.6.6. For every implementation history I A of A there exists a subset C 0 (I A ) ⊆ C such that (a) C 0 (I A ) and C(I A ) are disjoint, and (b) C 0 (I A ) is countably infinite. We are now ready to define how we map states of objects and local variables in A to B. Definition C.6.7 (Swapping Function). Consider any implementation history I A = C0A , p1 , C1A , . . . of A. For every CiA , local variable or base object O other than the memory manager of A, and jth index of the state assigned to O in CiA , we define a swapping function Si (O, j) as follows. Let s = v1 , v2 , . . . be the state assigned to O in CiA . ( M(Wi (O, j)) if Wi (O, j) ̸= ⊥ Si (O, j) = vj otherwise where M is an injective function from N to C 0 (I A ). This function exists because C 0 (I A ) is countably infinite (see Observation C.6.6). For convenience, the notation Si (O) means the sequence Si (O, 1), Si (O, 2), . . . for each index of s (see Observation C.6.3). Observe that M is defined only after we fix an implementation history I A of A (because its co-domain is C 0 (I A )), so M is dependent on I A . Throughout the proof, it will always be clear from context which I A we are referring to when using M, so we drop any reference to it. We now define the mapping from A to B. Definition C.6.8 (A to B Mapping). Let I A = C0A , p1 , C1A , . . . be any implementation history of A. We define I = C0 , p1 , C1 , . . . as follows. Consider any configuration CiA in I A . For every local variable or base object O other than the memory manager in A such that O ∈ / CO or O is in H, Ci assigns state Si (O) to O. Ci assigns states to objects of cells as follows. Let W be the set of step numbers up to and including the ith step of I A which perform AllocateCell operations. For every ptr ∈ C \ M[W ], Ci assigns every object of the cell pointed to by ptr to its initial state (as defined in Algorithm 2). Consider any w ∈ W . Let ptr be the response of the AllocateCell operation performed during the wth step of I A . If for all w < j ≤ i the jth step of I A does not perform an AllocateCell operation whose response is ptr, then Ci assigns state Si ((∗ptr).f ) to (∗M(w)).f for every f equal to response, revocations, or next. Otherwise, let j be the minimum w < j ≤ i such that the jth step of I A performs an AllocateCell cell operation whose response is ptr. Then, Ci assigns state Sj−1 ((∗ptr).f ) to (∗M(w)).f . Finally, Ci assigns state M[W ] to the memory manager. We now prove some basic facts about this mapping. Lemma C.6.9. Let I A = C0A , p1 , C1A , . . . be any implementation history of A and let I be the sequence C0 , p1 , C1 , . . . defined in Definition C.6.8. For every i, the program counter of each process is the same in CiA and Ci . 203

Proof. Suppose, for contradiction, the program counter pc of some process p is different in CiA and Ci . Hence, since pc stores a single value, by Definition C.6.8, Si (pc, 1) ̸= pc, and so by Definition C.6.7, Wi (pc, 1) ̸= ⊥. However, since pc is a program counter, by Definition C.6.4, Wi (pc, 1) = ⊥, a contradiction. Lemma C.6.9 Lemma C.6.10. Let I A = C0A , p1 , C1A , . . . be any implementation history of A and let I = C0 , p1 , C1 , . . . be the sequence defined in Definition C.6.8. Suppose the ith step of I A performs an AllocateCell operation and Ii−1 = C0 , p1 , C1 , . . . Ci−1 is an implementation history of B. Let IiB = C0 , p1 , C1 , . . . Ci−1 , pi , CiB be a one step continuation of Ii−1 by pi . If the state of the memory manager is the same in Ci and CiB , then the ith step of IiB performs an AllocateCell operation whose response is M(i). Proof. Suppose the ith step of I A performs an AllocateCell operation. Let Ai−1 (resp. Ai ) be the state of the memory manager in Ci−1 (resp. Ci ) and let W be the set of step numbers up to and including the ith step of I A which perform AllocateCell operations. Since the ith step of I A is an AllocateCell operation, we have that i ∈ W . Hence, by Definition C.6.8, Ai−1 = M[W \ {i}] and Ai = M[W ]. Thus, either Ai \ Ai−1 = ∅ or Ai \ Ai−1 = {M(i)}. We now prove that Ai \ Ai−1 ̸= ∅, which implies that Ai \ Ai−1 = {M(i)}. Suppose, for contradiction, Ai \ Ai−1 = ∅. Since Ai = M[W ] and Ai−1 = M[W \ {i}], we have that Ai \ Ai−1 = M[W ] \ M[W \ {i}], and so M[W ] \ M[W \ {i}] = ∅. Furthermore, since i ∈ W , we have that M(i) ∈ M[W ]. Hence, since M[W ] \ M[W \ {i}] = ∅, we have that M(i) ∈ M[W \ {i}]. Thus, for some j ∈ W \ {i}, we have that M(i) = M(j). Therefore, since j ∈ W \ {i}, we have that i ̸= j and M(i) = M(j). However, M is injective, so i ̸= j implies M(i) ̸= M(j), a contradiction. We now finish the proof of Lemma C.6.10. Since pi takes the ith step of I A and IiB , and by A and C Lemma C.6.9 the program counter of pi is the same in Ci−1 i−1 , we have that the ith step B B of Ii performs an AllocateCell operation. Hence, since Ii is an implementation history of B, by Algorithm 4, the response of the AllocateCell operation performed during the ith step of IiB is the pointer in the state of the memory manager in CiB which is not in the state of the memory manager in Ci−1 . Therefore, since by assumption the state of the memory manager is the same in Ci and CiB , and Ai is the state of the memory manager in Ci , we have that Ai is the state of the memory manager in CiB , and since Ai−1 is the state of the memory manager in Ci−1 , and Ai \ Ai−1 = {M(i)}, we have that the ith step of IiB performs an AllocateCell operation whose response is M(i) as wanted. Lemma C.6.10 Lemma C.6.11. Let I A = C0A , p1 , C1A , . . . be any implementation history of A and let I = C0 , p1 , C1 , . . . be the sequence defined in Definition C.6.8. Suppose the ith step of I A performs a FreeCell(ptr) operation and suppose Ii−1 = C0 , p1 , C1 , . . . Ci−1 is an implementation history of B. Let IiB = C0 , p1 , C1 , . . . Ci−1 , pi , CiB be a one step continuation of Ii−1 by pi . Furthermore, let A assigns state ptr to O be the local variable curr ptr of pi in the Relinquish procedure. Then, Ci−1 B O and the ith step of Ii performs a FreeCell(Si−1 (O)) operation. Proof. Since the ith step of I A performs a FreeCell(ptr) operation, we know that pi performed A . Hence, the value of O determines the this operation because it saw O to be assigned ptr in Ci−1 A input to pi ’s FreeCell operation in the ith step of I . Thus, since by Lemma C.6.9 the program A and C B counter of pi is the same in Ci−1 i−1 , we have that ith step of Ii performs a FreeCell(v) A , by Definition C.6.8, operation where v is the value of O in Ci−1 . Since O is assigned to ptr in Ci−1 B O is assigned to Si−1 (O) in Ci−1 . Therefore, since ith step of Ii performs a FreeCell(v) operation where v is the value of O in Ci−1 , we have that the ith step of IiB performs a FreeCell(Si−1 (O)) operation as wanted. Lemma C.6.11 204

Lemma C.6.12. Consider any implementation history I A = C0A , p1 , C1A , . . . of A. For every configuration CiA of I A , local variable or base object O other than the memory manager of A, and jth index of the state assigned to O in CiA , if Wi (O, j) = k ̸= ⊥, then k ≤ i and pk performed an AllocateCell operation during the kth step of I A with response vj where vj is the value of the jth index of the state assigned to O in CiA . Proof. By induction on i. Base Case. i = 0. Hence, by Definition C.6.4, W0 (O, j) = ⊥ for every local variable or base object O other than the memory manager of A and jth index of the state of O, so the claim vacuously holds. A . Inductive Case. for every i, if the claim holds for CiA , then the claim holds for Ci+1 A , local Suppose for some i, the claim holds for CiA . This is the inductive hypothesis. Consider Ci+1 variable or base object O other than the memory manager of A, and jth index of the state assigned A . Suppose W to O in Ci+1 i+1 (O, j) = k ̸= ⊥, we will prove that k ≤ i + 1 and pk performed an AllocateCell operation during the kth step of I A with response vj where vj is the value of the jth A . Hence, by Definition C.6.4, k = i+1 (2.a) or k = W (O ′ , l) index of the state assigned to O in Ci+1 i for some local variable or base object O′ other than the memory manager of A and the lth index of the state assigned to O′ in CiA (1, 2.b, 2.c, and 3). We consider each case separately.

Case 1. k = i + 1. Hence, k ≤ i+1 and by Definition C.6.4, during the i+1th step of I A pi+1 performs an AllocateCell operation whose response is vj . Therefore, since k = i+1, we have that pk performed an AllocateCell operation during the kth step of I A with response vj as wanted. Case 2. k = Wi (O′ , l) for some local variable or base object O′ other than the memory manager of A and the lth index of the state assigned to O′ in CiA . A because the lth index of O ′ in C A is Hence, by Definition C.6.4, the jth index of O is vj in Ci+1 i ′ vj . Since Wi (O , l) = k ̸= ⊥, by the inductive hypothesis, k ≤ i and pk performed an AllocateCell operation during the kth step of I A with response vl where vl is the value of the lth index of the state assigned to O′ in CiA . Hence, since the lth index of O′ in CiA is vj , we have that pk performed an AllocateCell operation during the kth step of I A with response vj as wanted. Lemma C.6.12 Lemma C.6.13. Consider any implementation history I A of A, configuration CiA of I A , local variable or base object O (resp. O′ ) other than the memory manager of A, and value vj (resp. vk′ ) in the jth (resp. kth) index of the state assigned to O (resp. O′ ) in CiA . Suppose if vj ∈ C (resp. vk′ ∈ C), then vj ∈ C(I A ) (resp. vk′ ∈ C(I A )). If vj ̸= vk′ , then Si (O, j) ̸= Si (O′ , k). Proof. There are four cases. Case 1. Si (O, j) = vj and Si (O′ , k) = vk′ . Hence, since vj ̸= vk′ , we have that Si (O, j) ̸= Si (O′ , k). Case 2. Si (O, j) = vj and Si (O′ , k) ̸= vk′ . Hence, by Definition C.6.7 Si (O′ , k) ∈ C 0 (I A ), and so by Observation C.6.6 Si (O′ , k) ∈ C. If vj ∈ / C, then vj ̸= Si (O′ , k), and so Si (O, j) ̸= Si (O′ , k). Otherwise, if vj ∈ C, then by assumption vj ∈ C(I A ). Hence, since by Observation C.6.6 C 0 (I A ) and C(I A ) are disjoint, Si (O′ , k) ∈ C 0 (I A ), and vj ∈ C(I A ), we have that vj ̸= Si (O′ , k), and so Si (O, j) ̸= Si (O′ , k). 205

Case 3. Si (O, j) ̸= vj and Si (O′ , k) = vk′ . The proof is symmetrical to Case 2 and is included below for completeness. Since Si (O, j) ̸= vj and Si (O′ , k) = vk′ , by Definition C.6.7, Si (O, j) ∈ C 0 (I A ), and so by Observation C.6.6 Si (O, j) ∈ C. If vk′ ∈ / C, then vk′ ̸= Si (O, j), and so Si (O, j) ̸= Si (O′ , k). Otherwise, if vk′ ∈ C, then by assumption ′ vk ∈ C(I A ). Hence, since by Observation C.6.6 C 0 (I A ) and C(I A ) are disjoint, Si (O, j) ∈ C 0 (I A ), and vk′ ∈ C(I A ), we have that vk′ ̸= Si (O, j), and so Si (O, j) ̸= Si (O′ , k) as wanted. Case 4. Si (O, j) ̸= vj and Si (O′ , k) ̸= vk′ . Hence, by Definition C.6.7, Si (O, j) = M(Wi (O, j)) and Si (O′ , k) = M(Wi (O′ , k)), and so by Observation C.6.6 Si (O, j) ∈ C and Si (O′ , k) ∈ C. Furthermore, Wi (O, j) = w ̸= ⊥ and Wi (O′ , k) = w′ ̸= ⊥. Thus, by Lemma C.6.12, the wth (resp. w′ th) step of I A is an AllocateCell operation whose response is vj (resp. vk′ ). Since vj ̸= vk′ , this implies that w ̸= w′ . Hence, Wi (O, j) ̸= Wi (O′ , k), and so since M is injective, we have that M(Wi (O, j)) ̸= M(Wi (O′ , k)). Therefore, Si (O, j) ̸= Si (O′ , k) as wanted. Lemma C.6.13 C.6.2

The mapping produces implementation histories of B

In this section, we prove that the mapping is an implementation of B. We start with an observation about how a step decides what object to perform a step on, and then prove this claim. Observation C.6.14. In any implementation history I A = C0A , p1 , C1A , . . . of A if pi performs an operation on a base object O ∈ CO during the ith step of I A , then by Definition C.6.1 O = (∗ptr).f for some ptr ∈ C ∪ {&H} where f is either response, revocations, or next, because one of pi ’s local A . We call O the source of O. variables Os was assigned state ptr in Ci−1 s Lemma C.6.15. For every implementation history I A = C0A , p1 , C1A , . . . of algorithm A, I = C0 , p1 , C1 , . . . as defined in Definition C.6.8 is an implementation history of B. Proof. The claim follows by proving the following predicate. Let P(n) be the predicate: for every implementation history InA = C0A , p1 , C1A , . . . , CnA of A, In = C0 , p1 , C1 , . . . , Cn as defined in Definition C.6.8 is an implementation history of B. We prove P(n) by induction on n. Base Case. P(0). Consider any local variable or base object O other than the memory manager such that O ∈ / CO . Hence, by Definition C.6.8, C0 assigns state S0 (O) to O. Since by Definition C.6.4 the output of W0 for every input is ⊥, by Definition C.6.7, S0 (O) is the state assigned to O in C0A . We now consider objects of cells and the memory manager. Since no steps have been performed in C0A , we have that no AllocateCell operations have been performed in C0A , and so the W defined in Definition C.6.8 is empty. Hence, M[W ] is empty, implying (1) for every ptr ∈ C C0 assigns every object of the cell pointed to by ptr to its initial state; and (2) C0 assigns the empty state to the memory manager. Thus, C0 assigns the same state to (1) every object of every cell; and (2) the memory manager as C0A . Therefore, since C0 assigns the same state to every local variable and every statically allocated object, we have that C0A = C0 , and so since the initial configurations of A and B are the same, we have that C0 is an implementation history of B as wanted. Inductive Case. ∀n P(n) =⇒ P(n + 1). Suppose for some n P(n) holds. This is the inductive hypothesis. Consider any implementation A A history In+1 = C0A , p1 , C1A , . . . , Cn+1 of A and let In+1 = C0 , p1 , C1 , . . . , Cn+1 be the sequence defined in Definition C.6.8. Let In be the prefix of In+1 up to and including the nth step, i.e., 206

In = C0 , p1 , C1 , . . . , Cn . By the inductive hypothesis, we have that In is an implementation history of B. We must prove that Cn+1 is reachable after a single step of pn+1 after In . We start by B identifying a reachable configuration Cn+1 after a single step of pn+1 after In which we will prove is equal to Cn+1 . Claim C.6.15.1. Since In is an implementation history of B, a single step of pn+1 after In leads to a set of possible configurations denoted by C = {c1 , c2 , . . .}. If pn+1 performs an AllocateCell operation after In , then some cj ∈ C assigns An ∪ {M(n + 1)} to the memory manager where An is the state of the memory manager in Cn . Proof. Suppose, for contradiction, pn+1 performs an AllocateCell operation after In and every c ∈ C does not assign An ∪ {M(n + 1)} to the memory manager. By Algorithm 4, the state of the memory manager after an AllocateCell operation starting from Cn can be any set An+1 so long as An+1 \An = {x} for x ∈ C. Hence, since by assumption every c ∈ C does not assign An ∪{M(n+1)} to the memory manager, we have either (An ∪ {M(n + 1)}) \ An = ∅ or M(n + 1) ∈ / C. Since the 0 A co-domain of M is C (I ), which by Observation C.6.6 is a subset of C, the latter is impossible, so (An ∪ {M(n + 1)}) \ An = ∅. Hence, M(n + 1) ∈ An , so by Definition C.6.8, for some i ≤ n M(i) = M(n + 1). Therefore, i ̸= n + 1 and M(i) = M(n + 1). However, since M is injective, i ̸= n + 1 implies M(i) ̸= M(n + 1), a contradiction. Claim C.6.15.1 B reachable by a single step of pn+1 after In . Since each line of We now define a configuration Cn+1 code except line 1 and 70 are deterministic18 , every base object other than the memory manager is deterministic, and for every v the FreeCell(v) operation on the lazy memory manager is deterministic, we have that if pn+1 does not execute line 1 nor 70 nor perform an AllocateCell operation after In , then there is only a single reachable configuration C by a single step of pn+1 after In . We now consider these three exceptions. Since by Lemma C.6.9 the program counter of pn+1 is the same in A , then p CnA and Cn , if pn+1 executes line ℓ during the n + 1th step of In+1 n+1 executes line ℓ after A In . If pn+1 executes line 1 during the n + 1th step of In+1 , then C is the configuration where pn+1 performs an invocation step for the same operation after In . Otherwise, if pn+1 executes line 70 A , then C is the configuration where p ′ during the n+1th step of In+1 n+1 sets its local variables s and ′ A r to the same values as in Cn+1 . Note that this is a possible configuration because: (1) by tracing backward hlo is an operation of type T ; and (2) by a simple induction s is a state of type T . Lastly, A , then p if pn+1 performs an AllocateCell operation during the n + 1th step of In+1 n+1 performs an AllocateCell operation after In , so by Claim C.6.15.1, there is a reachable configuration C by a single step of pn+1 after In that assigns An ∪ {M(n + 1)} to the memory manager. In all cases, we B let Cn+1 = C (where the C chosen is dependent on the case). B B B . Since I is an We must prove that Cn+1 = Cn+1 . Let In+1 = C0 , p1 , C1 , . . . , Cn , pn+1 , Cn+1 n B implementation history of B and Cn+1 is reachable by a single step of pn+1 after In , we have that B In+1 is an implementation history of B. We start by proving that every line of code executed during A In+1 that intends to perform an operation on an object of a cell actually does.

Claim C.6.15.2. Every execution of line 5, 12, 13, 34, 36, 53, 54, 55, 56, 58, 61, 62, 77, 88, 104, A 109, and 113 in In+1 performs an operation on an object of a cell in C ∪ {&H}. 18

Line 1 is non-deterministic because, given a configuration C of B where a process p’s program counter is one in C, a one step continuation from C by p leads to a different configuration depending on the operation p invokes (these configurations are different because p assigns its local variable hlo in the DoHighLevelOp procedure to the operation it invokes). Conversely, line 70 is non-deterministic when the implemented object type T is non-deterministic.

207

A Proof. Suppose, for contradiction, that an execution of one of these lines in In+1 does not perform an operation on an object of a cell in C ∪ {&H}; say the ith step. Hence, since pi takes the ith step A B , and by Lemma C.6.9 the program counter of p is the same in C A and C in In+1 and In+1 i i−1 , i−1 B it follows that there is an execution of one of the lines listed in the claim in In+1 that does not B perform an operation on an object of a cell in C ∪ {&H}. However, since In+1 is an implementation history of B, this contradicts Lemma C.1.99. Claim C.6.15.2 B We now prove that the state of the memory manager is the same in Cn+1 and Cn+1 . This is useful because it allows us to satisfy the conditions of Lemma C.6.10, enabling us to prove that if the ith A performs an AllocateCell operation, then the ith step of I B step of In+1 n+1 performs an AllocateCell operation whose response is M(i) (see Claim C.6.15.4). B Claim C.6.15.3. The state of the memory manager is the same in Cn+1 and Cn+1 .

Proof. There are two cases. A . Case 1. pn+1 does not perform an AllocateCell operation during the n + 1th step of In+1 Hence, by Definition C.6.8, the state of the memory manager is the same in Cn and Cn+1 . Furthermore, since by Lemma C.6.9 the program counter of pn+1 is the same in CnA and Cn , and pn+1 B , we have that p takes the n+1th step of In+1 n+1 does not perform an AllocateCell operation during B B . the n + 1th step of In+1 . Hence, the state of the memory manager is the same in Cn and Cn+1 Therefore, since the state of the memory manager is the same in Cn and Cn+1 , we have that the B state of the memory manager is the same in Cn+1 and Cn+1 as wanted. A . Case 2. pn+1 performs an AllocateCell operation during the n + 1th step of In+1 Hence, since by Lemma C.6.9 the program counter of pn+1 is the same in CnA and Cn , and pn+1 takes B , we have that p the n + 1th step of In+1 n+1 perform an AllocateCell operation during the n + 1th B B , we have that C B step of In+1 . Thus, by the definition of Cn+1 n+1 assigns state An ∪ {M(n + 1)} to the memory manager where Cn assigns state An to the memory manager. By Definition C.6.8, Cn (resp. Cn+1 ) assigns state M[Wn ] (resp. M[Wn+1 ]) where Wn (resp. Wn+1 ) is the set of step A which perform AllocateCell numbers up to and including the nth (resp. n + 1th) step of In+1 operations, so An = M[Wn ]. Hence, since pn+1 performs an AllocateCell operation during the A , we have that n + 1 ∈ n + 1th step of In+1 / Wn and n + 1 ∈ Wn+1 , and so it follows that Wn+1 = Wn ∪ {n + 1}. Thus, M[Wn+1 ] = M[Wn ∪ {n + 1}] which simplifies to M[Wn ] ∪ {M(n + 1)}. So, since An = M[Wn ], we have that M[Wn+1 ] = An ∪ {M(n + 1)}. Therefore, Cn+1 assigns state An ∪ {M(n + 1)} to the memory manager, and so the state of the memory manager is the same in B Cn+1 and Cn+1 . Claim C.6.15.3 A Claim C.6.15.4. If the ith step of In+1 performs an AllocateCell operation, then the ith step of B In+1 performs an AllocateCell operation whose response is M(i).

Proof. First, suppose that i ≤ n. Hence, by the inductive hypothesis, Ii−1 = C0 , p1 , C1 , . . . , Ci−1 is an implementation history of B, Ii = C0 , p1 , C1 , . . . , Ci−1 , pi , Ci is a one step continuation of Ii−1 by pi , and the state of the memory manager is by definition the same in Ci and Ci , and so B ) performs an AllocateCell operation whose by Lemma C.6.10, the ith step of Ii (and thus In+1 response is M(i). Now suppose i = n + 1. By the inductive hypothesis In = C0 , p1 , C1 , . . . , Cn is an B B implementation history of B, and by definition In+1 = C0 , p1 , C1 , . . . , Ci , pn+1 , Cn+1 is a one step continuation of In by pn+1 . Therefore, since by Claim C.6.15.3 the state of the memory manager B , the claim follows by Lemma C.6.10. is the same in Cn+1 and Cn+1 Claim C.6.15.4 208

B . We first prove a simple claim We now prove a similar claim for FreeCell operations in In+1 B A ). This is one asserting that the response of every AllocateCell operation in In+1 is not in C(In+1 place where we make use of the fact that we “rename” pointers in A to “fresh” pointers in B. B A ). Claim C.6.15.5. The response of every AllocateCell operation in In+1 is not in C(In+1 B ; say it is performed during the ith step. Proof. Consider any AllocateCell operation during In+1 A and C Hence, since by Lemma C.6.9 the program counter of pi is the same in Ci−1 i−1 and pi A B performs the ith step of In+1 and In+1 , we have that pi performed an AllocateCell operation A . Thus, by Claim C.6.15.4, the ith step of I B during the ith step of In+1 n+1 performs an AllocateCell A ). Therefore, since by operation whose response is M(i), and so by Definition C.6.7 it is in C 0 (In+1 A ) are disjoint, we have that the response of every AllocateCell Observation C.6.6 C(I A ) and C 0 (In+1 B A operation in In+1 is not in C(In+1 ) as wanted. Claim C.6.15.5 A Claim C.6.15.6. Consider any ptr ∈ C. If the ith step of In+1 performs a FreeCell(ptr) operation and Wi−1 (O, 1) = w where O is the local variable curr ptr of pi in the Relinquish procedure, then B w ̸= ⊥ and the ith step of In+1 performs a FreeCell(M(w)) operation. A Proof. Consider any ptr ∈ C and suppose the ith step of In+1 performs a FreeCell(ptr) operation and Wi−1 (O, 1) = w where O is the local variable curr ptr of pi in the Relinquish procedure. Hence, A assigns state ptr to O and the ith step of I B by Lemma C.6.11, Ci−1 n+1 performs a FreeCell(Si−1 (O)) operation.

We first prove that Wi−1 (O, 1) ̸= ⊥. Suppose, for contradiction, Wi−1 (O, 1) = ⊥. Hence, since A assigns ptr to O, by Definition C.6.7, S B Ci−1 i−1 (O) = ptr. Thus, since the ith step of In+1 B performs a FreeCell(Si−1 (O)) operation, the ith step of In+1 is a FreeCell(ptr) operation. Since A A Ci−1 assigns ptr to O, by Definition C.6.5, ptr ∈ C(In+1 ). Hence, by Claim C.6.15.5 the response B B of every AllocateCell operation in In+1 is not ptr. Therefore, in In+1 there is a FreeCell(ptr) such B that there is no AllocateCell operation whose response is ptr before it. However, since In+1 is an implementation history of B and ptr ∈ C, by 2 of Theorem C.5.51, every FreeCell(ptr) operation in B In+1 is after an AllocateCell operation whose response is ptr, a contradiction. B We now prove that the ith step of In+1 performs a FreeCell(M(w)) operation. Since Wi−1 (O, 1) = w ̸= ⊥, by Definition C.6.7, Si−1 (O, 1) = M(w). Hence, since the state of O is a single value, B Si−1 (O) = M(w). Therefore, since the ith step of In+1 performs a FreeCell(Si−1 (O)) operation, B we have that the ith step of In+1 performs a FreeCell(M(w)) operation as wanted. Claim C.6.15.6 A We now show that between any two AllocateCell and FreeCell operations for ptr in In+1 there is B a FreeCell operation for a “matching” pointer in In+1 . A Claim C.6.15.7. Consider any ptr ∈ C. If the ith step of In+1 performs an AllocateCell operation A whose response is ptr and the jth step of In+1 performs a FreeCell(ptr) operation where j ∈ (i..n+1], A then the kth step of In+1 performs a FreeCell(ptr) operation where k ∈ (i..j], and Wk−1 (Ok , 1) = i where Ok is the local variable curr ptr of pk in the Relinquish procedure.

Proof. By induction on i. Base Case. i = 1. Since every AllocateCell operation is performed on line 2, we have that there is at least one step A before any AllocateCell operation, and so the first step of In+1 cannot perform an AllocateCell operation. Therefore, the claim for i = 1 is vacuously true. 209

Inductive Case. ∀i ∈ [1..n] if the claim holds for all j ∈ [1..i], then the claim holds for i + 1. Suppose for some i ∈ [1..n] and every j ∈ [1..i] that the claim holds for j. This is the inductive hypothesis. We must prove that the claim holds for i+1. Suppose, for contradiction, that the i+1th A step of In+1 performs an AllocateCell operation whose response is ptr, for some i + 1 < j ≤ n + 1 A the jth step of In+1 performs a FreeCell(ptr) operation, and for all i + 1 < k ≤ j the kth step of A In+1 does not perform a FreeCell(ptr) operation or Wk−1 (Ok , 1) ̸= i + 1. Without loss of generality, A suppose j is the smallest such step number, i.e., for every i + 1 < j ′ < j if the j ′ th step of In+1 ′ ′ ′ A performs a FreeCell(ptr) operation, then for some i + 1 < k ≤ j the k th step of In+1 performs a FreeCell(ptr) operation, and Wk′ −1 (Ok′ , 1) = i + 1 (*). A performs a FreeCell(ptr) operation, by Claim C.6.15.6, W Since pj in the jth step of In+1 j−1 (Oj , 1) = B w ̸= ⊥ and the jth step of In+1 performs a FreeCell(M(w)) operation. Hence, by Lemma C.6.12, A w < j and the wth step of In+1 performed an AllocateCell operation with response v1 where v1 A . Thus, since O is the local variis the value of the 1st index of the state assigned to Oj in Cj−1 j A able curr ptr of pj in the Relinquish procedure, and the jth step of In+1 performs a FreeCell(ptr) A assigns state ptr to O , and so the wth step of I A operation, we have that Cj−1 j n+1 performed an AllocateCell operation with response ptr. There are two cases. Case 1. i + 1 < w. A perform an AllocateCell operation whose response Hence, since both the i+1th and wth step of In+1 A is ptr, by Algorithm 3, for some i + 1 < j ′ < w the j ′ th step of In+1 performs a FreeCell(ptr) ′ A operation. Since w < j, this implies that for some i + 1 < j < j the j ′ th step of In+1 performs a ′ ′ FreeCell(ptr) operation. Therefore, by (*), for some i + 1 < k ≤ j (or equivalently i + 1 < k ′ ≤ j A since j ′ < j) the k ′ th step of In+1 performs a FreeCell(ptr) operation, and Wk′ −1 (Ok′ , 1) = i + 1. A However, by our initial assumption, for all i + 1 < k ≤ j the kth step of In+1 does not perform a FreeCell(ptr) operation or Wk−1 (Ok , 1) ̸= i + 1, a contradiction. Case 2. w ≤ i + 1. A We first prove that the claim holds for w. Since, by assumption, the jth step of In+1 performs A a FreeCell(ptr) operation, and for all i + 1 < k ≤ j the kth step of In+1 does not perform a FreeCell(ptr) operation or Wk−1 (Ok , 1) ̸= i + 1, we have that Wj−1 (Oj , 1) ̸= i + 1. Hence, since Wj−1 (Oj , 1) = w, we have that w ̸= i + 1. Thus, since w ≤ i + 1, we have that w < i + 1, and so w ≤ i. Therefore, since 1 ≤ w, by the inductive hypothesis, the claim holds for w. We now prove that, roughly speaking, there is another FreeCell operation whose watermark is A the same as j’s. Since both the wth and i + 1th step of In+1 perform an AllocateCell operation ′ A whose response is ptr, by Algorithm 3, for some w < j < i + 1 the j ′ th step of In+1 performs a FreeCell(ptr) operation. Hence, since i + 1 ≤ n + 1, by transitivity, we have that w < j ′ < n + 1. A Thus, since the wth step of In+1 perform an AllocateCell operation whose response is ptr, the j ′ th A step of In+1 performs a FreeCell(ptr) operation, and the claim holds for w, we have that for some A w < k ≤ j ′ the kth step of In+1 performs a FreeCell(ptr) operation, and Wk−1 (Ok , 1) = w. A performs a FreeCell(ptr) operation and We now finish the proof of Case 2. Since the kth step of In+1 B Wk−1 (Ok , 1) = w, by Claim C.6.15.6, the kth step of In+1 performs a FreeCell(M(w)) operation. Furthermore, since k ≤ j ′ , j ′ < i + 1, and i + 1 < j, by transitivity, k < j, and so k ̸= j. Therefore, B since both the kth and jth step of In+1 perform a FreeCell(M(w)) operation, we have that there are B . However, since I B two FreeCell(M(w)) operations during In+1 n+1 is an implementation history of B, and by Definition C.6.7 M(w) ∈ C, by 1 of Theorem C.5.51, there is at most one FreeCell(M(w)) B , a contradiction. operation in In+1 Claim C.6.15.7 A We now prove that the n + 1th step of In+1 cannot perform an operation on an object of a cell which is unallocated. We will do this over the next few claims.

210

A Claim C.6.15.8. If the n + 1th step of In+1 performs an operation on a base object O other than B the memory manager, then the n + 1th step of In+1 performs an operation on O∗ defined as follows. ∗ Let O be O if O ∈ / CO and otherwise O is the object f of some cell where f is either response, revocations, or next, and O∗ = (∗Sn (Os )).f where Os is the source of O (see Observation C.6.14).

Proof. There are two cases. Case 1. O ∈ / CO . Hence, since O is not the memory manager, by Definition C.6.1, O ∈ {C, A, L, S}. Thus, pn+1 A performed an operation O during the n + 1th step of In+1 because of the line of code it executed (as opposed to because of the state of its local variables). Therefore, since by Lemma C.6.9 the B , program counter of pn+1 is the same in CnA and Cn , and pn+1 performs the n + 1th step of In+1 B we have that the n + 1th step of In+1 performs an operation on O as wanted. Case 2. O ∈ CO . Hence, by Definition C.6.1, for some ptr ∈ C ∪ {&H} O equals (∗ptr).f where f is defined in the claim. Observe that the line of code pn+1 executed determines f , but a local variable determines ptr. Since Os is the source of O, by Observation C.6.14, pn+1 performed an operation on O = (∗ptr).f during the n + 1th step of I A because Os was assigned to state ptr in CnA . Thus, since by Lemma C.6.9 the program counter of pn+1 is the same in CnA and Cn and pn+1 performs the B , p ′ ′ n + 1th step of In+1 n+1 performs an operation on (∗ptr ).f where ptr is the state assigned to Os A in Cn . Since Os = ptr in Cn , by Definition C.6.8, Os = Sn (Os ) in Cn . Therefore, pn+1 performs B an operation on (∗Sn (Os )).f during the n + 1th step of In+1 as wanted. Claim C.6.15.8 A Claim C.6.15.9. If the n + 1th step of In+1 performs an operation on a base object O ∈ CO , O is not in H, and Wn (Os , 1) = w where Os is the source of O (see Observation C.6.14), then (a) A w ̸= ⊥ (b) the wth step of In+1 performs an AllocateCell operation whose response is ptr where O is an object of the cell pointed to by ptr and (c) Sn (Os ) = M(w). A performs an operation Proof. We first prove (a). Suppose, for contradiction, the n+1th step of In+1 on a base object O ∈ CO , O is not in H, and Wn (Os , 1) = ⊥. Hence, by Definition C.6.1, O = (∗ptr).f where ptr ∈ C and f is either response, revocations, or next. Since Os is the source of O, by Observation C.6.14, CnA assigned state ptr to Os , and so by Definition C.6.5, ptr ∈ C(I A ). B Furthermore, by Claim C.6.15.8, the n + 1th step of In+1 performs an operation on (∗Sn (Os )).f . A Since Cn assigned state ptr to Os and Wn (Os , 1) = ⊥, by Sn (Os ) = ptr. Hence, since the n + 1th B B step of In+1 performs an operation on (∗Sn (Os )).f , we have that the n + 1th step of In+1 performs A an operation on (∗ptr).f . Therefore, since ptr ∈ C(I ), by Claim C.6.15.5, the response of every B B AllocateCell operation in In+1 is not ptr, and so in In+1 the n + 1th step performs an operation on an object of the cell pointed to by ptr and there are no AllocateCell operations whose response B . However, since I B is ptr in In+1 n+1 is an implementation history of B and ptr ∈ C, by 3. of Theorem C.5.51, every operation on an object of the cell pointed to by ptr is after an AllocateCell operation whose response is ptr, a contradiction. A We now prove (b) and (c). Since Wn (Os , 1) = w ̸= ⊥, by Lemma C.6.12, the wth step of In+1 A performs an AllocateCell operation during the wth step of In+1 with response v1 where v1 is the A A value of the 1st index of the state assigned to Os in Cn . Thus, since the n + 1th step of In+1 performs an operation on O, O is an object of the cell pointed to by ptr, and Os is the source of A O, by Observation C.6.14, CnA assigns state ptr to Os , and so the wth step of In+1 performs an A AllocateCell operation with response ptr. Furthermore, since Cn assigns a single value (namely ptr) to Os , and Wn (Os , 1) = w ̸= ⊥, by Definition C.6.7, Sn (Os ) = M(w). Claim C.6.15.9

211

A performs an operation on an object of the cell pointed Claim C.6.15.10. If the n+1th step of In+1 to by ptr ∈ C, then ptr is in the state of the memory manager in CnA . A Proof. Suppose, for contradiction, the n + 1th step of In+1 performs an operation on an object O of the cell pointed to by ptr ∈ C, and ptr is not in the state of the memory manager in CnA . Hence, O = (∗ptr).f where f is either response, revocations, or next, and so, by Definition C.6.1, O ∈ CO . A Let Os be the source of O. Hence, since the n + 1th step of In+1 performs an operation on the B cell pointed to by ptr ∈ C, by Claim C.6.15.8, the n + 1th step of In+1 performs an operation on A (∗Sn (Os )).f . Furthermore, by Claim C.6.15.9, Wn (Os , 1) = w ̸= ⊥, the wth step of In+1 performs an AllocateCell operation whose response is ptr, and Sn (Os ) = M(w). Therefore, the n + 1th step B of In+1 performs an operation on (∗M(w)).f . B . Since the wth step of I A We now identify a FreeCell(M(w)) operation in In+1 n+1 performs an A AllocateCell operation whose response is ptr, by Definition C.6.5 ptr ∈ C(In+1 ). Hence, since by assumption ptr is not in the state of the memory manager in CnA , by Algorithm 3, for some A w < j ≤ n the jth step of In+1 performs a FreeCell(ptr) operation. Thus, by Claim C.6.15.7, for A performs a FreeCell(ptr) operation and W some w < k ≤ j the kth step of In+1 k−1 (Ok , 1) = w where Oj is the local variable curr ptr of pk in the Relinquish procedure. Therefore, by Claim C.6.15.6, B the kth step of In+1 performs a FreeCell(M(w)) operation.

We now finish the proof Claim C.6.15.10. Therefore, since k < n + 1, there is an operation on an B object of the cell pointed to by M(w) during the n+1th step of In+1 which is after a FreeCell(M(w)) B B operation during the kth step of In+1 . However, since In+1 is an implementation history of B and M(w) ∈ C, by 3. of Theorem C.5.51, every operation on an object the cell pointed to by M(w) is before any FreeCell(M(w)) operation, a contradiction. Claim C.6.15.10 A The next claim should be thought of as: if the n + 1th step of In+1 performs an operation on an object of the cell, then when mapped to B, it is the latest version of that cell. A Claim C.6.15.11. Suppose the n + 1th step of In+1 performs an operation on a base object O ∈ CO and O is not in H. By Claim C.6.15.9, Wn (Os , 1) = w ̸= ⊥ where Os is the source of O A does not perform an AllocateCell operation (see Observation C.6.14). Then, the ith step of In+1 whose response is ptr, where i ∈ (w..n + 1] and ptr is the pointer to the cell that O is an object of.

Proof. Suppose, for contradiction, O ∈ CO , O is not in H, Wn (Os , 1) = w, and for some i ∈ A (w..n + 1] the ith step of In+1 performs an AllocateCell operation whose response is ptr. Hence, A by Claim C.6.15.9, the wth step of In+1 performs an AllocateCell operation whose response is A ptr. Since the wth and ith step of In+1 perform an AllocateCell operation with response ptr, and A w < i, by Algorithm 3, for some w < j < i the jth step of In+1 performs a FreeCell(ptr) operation. A Hence, by Claim C.6.15.7, for some w < k ≤ j the kth step of In+1 performs a FreeCell(ptr) operation, and Wk−1 (Ok , 1) = w where Ok is the local variable curr ptr of pk in the Relinquish procedure. Since k ≤ j, j < i, and i ≤ n + 1, by transitivity, k < n + 1. Furthermore, since the A kth step of In+1 performs a FreeCell(ptr) operation and Wk−1 (Ok , 1) = w, by Claim C.6.15.6, the B A kth step of In+1 performs a FreeCell(M(w)) operation. Since the n + 1th step of In+1 performs an operation on O ∈ CO and O is an object of the cell pointed to by ptr, by Claim C.6.15.8, the B n + 1th step of In+1 performs an operation on an object of the cell pointed to by Sn (Os ). Hence, B since Wn (Os , 1) = w, by Claim C.6.15.9, Sn (Os ) = M(w), and so the n + 1th step of In+1 performs B an operation on the cell pointed to by M(w). Therefore, since k < n + 1, in In+1 , there is an operation on an object of the cell pointed to by M(w) after a FreeCell(M(w)) operation. However, 212

B since In+1 is an implementation history of B and M(w) ∈ C, by 3 of Theorem C.5.51, every operation on an object of the cell pointed to by M(w) is before any FreeCell(M(w)) operation, a contradiction. Claim C.6.15.11

We now have all the facts we need to do the majority of the work to prove Lemma C.6.15. The A rest of the proof will go as follows. First, we will prove that if the n + 1th step of In+1 performs an operation on a base object O other than the memory manager, then the state of the “corresponding” B object in Cn+1 is the same as Cn+1 . We will then prove that the state of every local variable other B than the program counters is the same in Cn+1 and Cn+1 . Then, we will prove that the state of B every program counter is the same in Cn+1 and Cn+1 . A performs an operation oA Claim C.6.15.12. Suppose the n+1th step of In+1 n+1 on some base object A . Let O ∗ be O if O ∈ O other than the memory manager with response rn+1 / CO and otherwise O is the object f of some cell where f is either response, revocations, or next, and O∗ = (∗Sn (Os )).f B where Os is the source of O. Then, the n + 1th step of In+1 performs an operation on O∗ with B ∗ response rn+1 and Cn+1 assigns state Sn+1 (O) to O where rn+1 is defined as follows. If oA n+1 is a A read operation, then rn+1 = Sn (O); Otherwise, rn+1 = rn+1 . A Proof. Suppose the n + 1th step of In+1 performs an operation oA n+1 on some base object O other A . Hence, by Claim C.6.15.8, the n + 1th step of I B than the memory manager with response rn+1 n+1 performs an operation on+1 on O∗ ; say with response rn+1 . Since O is a base object other than the memory manager, O is either a F&A, CAS, or GCAS object, so O is deterministic. Let δ be A A the state transition function of O. Furthermore, let sA n (resp. sn+1 ) be the state that Cn (resp. A A A Cn+1 ) assigns to O. Hence, since the n + 1th step of In+1 performs an operation on+1 on O with A , if O ∈ A A A response rn+1 / CO , then we have that δ(sA n , on+1 ) = (sn+1 , rn+1 ). Otherwise, if O ∈ CO , then by Definition C.6.1, O is an object of some cell, say the one pointed to by ptr ∈ C, and so by Claim C.6.15.10, ptr is in the memory manager in CnA . Thus, by Definition C.0.1, we have that A A A A A A A δ(sA n , on+1 ) = (sn+1 , rn+1 ). Therefore, in all cases, δ(sn , on+1 ) = (sn+1 , rn+1 ).

We first prove that Cn assigns Sn (O) to O∗ (*). If O ∈ / CO or O is in H, then O∗ = O, and so by Definition C.6.8 Cn assigns Sn (O) to O. If O ∈ CO and O is not in H, then by Definition C.6.1, O = (∗ptr).f for some ptr ∈ C and f which is either response, revocations, or next. Let Wn (Os , 1) = w. A Hence, by Claim C.6.15.9, the wth step of In+1 performs an AllocateCell operation whose response is ptr, and Sn (Os ) = M(w). Furthermore, by Claim C.6.15.11 for all w < i ≤ n + 1 the ith step of A does not perform an AllocateCell operation whose response is ptr. Hence, by Definition C.6.8, In+1 Cn assigns state Sn ((∗ptr).f ) to (∗M(w)).f . Thus, since Sn (Os ) = M(w), we have that Cn assigns state Sn ((∗ptr).f ) to (∗Sn (Os )).f . Therefore, since O = (∗ptr).f , and O∗ = (∗Sn (Os )).f , we have that Cn assigns state Sn (O) to O∗ as wanted. The remainder of the proof is by cases depending on the type of oA n+1 . Case 1. oA n+1 is a read operation. A . Furthermore, since by Lemma C.6.9 the program Hence, the state of O is the same in CnA and Cn+1 A B , we have that counter of pn+1 is the same in Cn and Cn , and pn+1 takes the n + 1th step of In+1 on+1 is a read operation. Thus, since on+1 is an operation on O∗ , and by (*) Cn assigns Sn (O) to B O∗ , we have that rn+1 = Sn (O) and Cn+1 assigns state Sn (O) to O∗ . What remains is to show that A . Hence, since the Sn+1 (O) = Sn (O). Let vj be the value of the jth index of the state of O in Cn+1 A , it follows that v is the value of the jth index of the state state of O is the same in CnA and Cn+1 j A of O in Cn . Furthermore, since n is a non-negative integer, n + 1 > 0, so n ≥ 0. There are two cases. 213

Case 1.1. if O is a base object, then O ∈ {A, L} ∪ {(∗ptr).next | ptr ∈ C ∪ {&H}}, and vj ∈ C. Since oA n+1 is a read operation, we have that pn+1 does not set any index of O during the n + 1th A , and so by 1 of Definition C.6.4, W step of In+1 n+1 (O, j) = Wn (O, j). Hence, since the state of O A , by Definition C.6.7, S is the same in CnA and Cn+1 n+1 (O, j) = Sn (O, j). Case 1.2. otherwise. Hence, by Definition C.6.4, Wn+1 (O, j) = ⊥. We now show that Wn (O, j) = ⊥. Recall that n ≥ 0. If n = 0, then by Definition C.6.4, Wn (O, j) = ⊥, as wanted, so suppose n > 0. Hence, by assumption if O is a base object, then O ∈ / {A, L}∪{(∗ptr).next | ptr ∈ C ∪{&H}}, or vj ∈ / C. Thus, A since vj is the value of the jth index of the state of O in Cn , in either case, by Definition C.6.4, Wn (O, j) = ⊥. Therefore, since in all cases Wn+1 (O, j) = Wn (O, j), and the state of O is the same A , by Definition C.6.7, S in CnA and Cn+1 n+1 (O, j) = Sn (O, j). We now finish the proof of Case 1. Since Sn+1 (O, j) = Sn (O, j) for every index j of O, by B Definition C.6.7, Sn+1 (O) = Sn (O). Therefore, since Cn+1 assigns state Sn (O) to O∗ , we have that B ∗ Cn+1 assigns state Sn+1 (O) to O as wanted. Case 2. oA n+1 is a write operation. Observe that only line 12 executes a write operation. Hence, pn+1 executes line 12 during the n+1th A . Thus, oA step of In+1 n+1 is a write operation for a value v1 , v2 , Null where v1 , v2 is the state of pn+1 ’s local variable ullo in CnA . So, sA n+1 = v1 , v2 , Null. Since pn+1 performs a write operation A , and p A on O during the n + 1th step of In+1 n+1 executes line 12 during the n + 1th step of In+1 , it follows that O = (∗ptr).response, and so O ∈ / {A, L} ∪ {(∗ptr).next | ptr ∈ C ∪ {&H}}. Hence, by Definition C.6.4, Wn+1 (O, 1) = ⊥ and Wn (O, 2) = ⊥. Furthermore, since pn+1 sets the third index of O to Null and by Assumption C.1.2 Null ∈ / C, by Definition C.6.4, Wn+1 (O, 3) = ⊥. Thus, by Definition C.6.7, Sn+1 (O) = v1 , v2 , Null. Now observe that the values of pn+1 ’s local variable ullo on line 12 does not originate from an AllocateCell operation on line 2 (because t originates from line 10 and llo is a fixed input on either line 3, 4, or 6). Hence, by Definition C.6.4, Wn (ullo, 1) = Wn (ullo, 2) = ⊥. Thus, by Definition C.6.7, Sn (ullo, 1) = v1 , and Sn (ullo, 1) = v2 . Therefore, since Sn+1 (O) = v1 , v2 , Null, we have that Sn+1 (O) = Sn (ullo, 1), Sn (ullo, 2), Null. Since oA n+1 is a write operation for a value v1 , v2 , Null where v1 , v2 is the state of the local variable ullo in CnA , by Lemma C.6.9 the program counter of pn+1 is the same in CnA and Cn , and pn+1 B , we have that o ′ ′ takes the n + 1th step of In+1 n+1 is a write operation for a value v1 , v2 , Null where v1′ , v2′ is the state of the local variable ullo in Cn . Hence, since by Definition C.6.8, Cn assigns state Sn (ullo) to ullo, we have that Sn (ullo) = v1′ , v2′ . Thus, on+1 is a write operation for a value Sn (ullo, 1), Sn (ullo, 2), Null. Therefore, since Sn+1 (O) = Sn (ullo, 1), Sn (ullo, 2), Null and on+1 is B an operation on O∗ , we have that Cn+1 assigns state Sn+1 (O) to O∗ . Furthermore, since oA n+1 and on+1 are both write operations, their responses are both Done. Case 3. oA n+1 is a F&A operation. Observe that only line 10, 62, and 113 execute F&A operations. Hence, O is C or (∗ptr).revocations for some ptr ∈ C ∪ {&H}. Thus, by Definition C.6.4, Wn+1 (O, 1) = Wn (O, 1) = ⊥. So, by A A Definition C.6.7, Sn (O) = sA n and Sn+1 (O) = sn + a where a is the input of on+1 (in the case where A A A oA n+1 is an F&I operation, a = 1). Furthermore, the response of on+1 , i.e., rn+1 , is sn . In the single case where pn+1 read a from one of its local variables, say pr, on line 62 it can be seen that a did not originate from the response of an AllocateCell operation, and so by Definition C.6.4 Wn (pr, 1) = ⊥, and so by Definition C.6.7 Sn (pr) = a. Since oA n+1 is a F&A operation, by Lemma C.6.9 the B , we program counter of pn+1 is the same in CnA and Cn , and pn+1 takes the n + 1th step of In+1 have that on+1 is a F&A operation. Let a′ be the input to on+1 . Hence, a′ is either one, or a value pn+1 read from pr. Since by Definition C.6.8 Cn assigns state Sn (pr) to pr, and Sn (pr) = a, we 214

have that a′ = a. Hence, the input to on+1 is a. Thus, since by (*) Cn assigns Sn (O) to O∗ , we B have that the response of on+1 is Sn (O), and Cn+1 assigns state Sn (O) + a to O∗ . Therefore, since A A B Sn (O) = sn and Sn+1 (O) = sn + a, we have that Cn+1 assigns state Sn+1 (O) to O∗ and rn+1 = sA n. A Case 4. on+1 is a CAS operation. Hence, since by Lemma C.6.9 the program counter of pn+1 is the same in CnA and Cn , and pn+1 B , we have that o takes the n + 1th step of In+1 n+1 is a CAS operation. Observe that only line 25, 27, 36, 55, 61, 71, 77, and 109 execute CAS operations. Let oldA n+1 (resp. oldn+1 ) be the first A parameter of oA (resp. o ). Furthermore, let new (resp. new n+1 n+1 ) be the second parameter n+1 n+1 A . There of oA (resp. o ). Let ℓ be the line of code p executed during the n + 1th step of In+1 n+1 n+1 n+1 are two cases. A = False. Case 4.1. ri+1 A A A A A A A Hence, since δ(sA n , on+1 ) = (sn+1 , rn+1 ), we have that oldn+1 ̸= sn and sn+1 = sn (i.e., the state of A ). Thus, p O is the same in CnA and Cn+1 n+1 does not set any index of O during the n + 1th step A of In+1 . We first prove that Sn+1 (O) = Sn (O). Let vj be the value of the jth index of the state of O in A . Hence, since the state of O is the same in C A and C A , it follows that v is the value of Cn+1 j n n+1 the jth index of the state of O in CnA . Furthermore, since n is a non-negative integer, n + 1 > 0, so n ≥ 0. There are two cases. Case 4.1.1. if O is a base object, then O ∈ {A, L} ∪ {(∗ptr).next | ptr ∈ C ∪ {&H}}, and vj ∈ C. A , by 1 of DefiniHence, since pn+1 does not set any index of O during the n + 1th step of In+1 A , tion C.6.4, Wn+1 (O, j) = Wn (O, j). Therefore, since the state of O is the same in CnA and Cn+1 by Definition C.6.7, Sn+1 (O, j) = Sn (O, j). Case 4.1.2. otherwise. Hence, by Definition C.6.4, Wn+1 (O, j) = ⊥. We now show that Wn (O, j) = ⊥. Recall that n ≥ 0. If n = 0, then by Definition C.6.4, Wn (O, j) = ⊥, as wanted, so suppose n > 0. Hence, by assumption if O is a base object, then O ∈ / {A, L}∪{(∗ptr).next | ptr ∈ C ∪{&H}}, or vj ∈ / C. Thus, A since vj is the value of the jth index of the state of O in Cn , in either case, by Definition C.6.4, Wn (O, j) = ⊥. Therefore, since in all cases Wn+1 (O, j) = Wn (O, j), and the state of O is the same A , by Definition C.6.7, S in CnA and Cn+1 n+1 (O, j) = Sn (O, j). Since Sn+1 (O, j) = Sn (O, j) for every index j of O, by Definition C.6.7, Sn+1 (O) = Sn (O). This completes the proof that Sn+1 (O) = Sn (O). A A We now prove that oldn+1 ̸= Sn (O). Since oldA n+1 ̸= sn , we have that some index of oldn+1 and A A A sn differ; let this be the ith index. Let oi (resp. oi ) be the value of the ith index of oldn+1 (resp. A oldn+1 ). Observe that oA i is either (a) a value dictated by ℓ or (b) pn+1 read oi from the jth A A index of one of its local variable, say pr, in Cn . Hence, if (a), then oi = oi and, if (b), then by A A A Definition C.6.8 oi = Sn (pr, j). Let sA i be the value of the ith index of sn , so oi ̸= si . Hence, by A A A Definition C.6.5, if si ∈ C, then si ∈ C(In+1 ). We consider cases (a) and (b) separately. Case (a). A / C. Furthermore, o = oA . Hence, since oA i i is a static value determined by ℓ, it follows that oi ∈ i A A A A Thus, since oi ̸= si , we have that oi ̸= si , and since oi ∈ / C, we have that oi ∈ / C. Let A Wn (O, i) = w. If w = ⊥, then by Definition C.6.7 Sn (O, i) = sA i , and so since oi ̸= si , we have that oi ̸= Sn (O, i). If w ̸= ⊥, then Definition C.6.7 Sn (O, i) = M(w) ∈ C, and so since oi ∈ / C, we have that oi ̸= Sn (O, i). Therefore, oldn+1 ̸= Sn (O) as wanted. Case (b). A Hence, oi = Sn (pr, j) and oA i is the value of the jth index of pr in Cn . Thus, by Definition C.6.5, if A A A A A oi ∈ C, then oi ∈ C(In+1 ). So, since oi ̸= si , by Lemma C.6.13, Sn (pr, j) ̸= Sn (O, i). Therefore, since oi = Sn (pr, j), we have that oi ̸= Sn (O, i), and so oldn+1 ̸= Sn (O) as wanted. 215

This completes the proof that oldn+1 ̸= Sn (O). We now finish the proof of Case 4.1. Since by (*) Cn assigns Sn (O) to O∗ , on+1 is an operation B on O∗ , and oldn+1 ̸= Sn (O), we have that on+1 is unsuccessful, so rn+1 = False and Cn+1 assigns ∗ B state Sn (O) to O . Therefore, since Sn+1 (O) = Sn (O), we have that Cn+1 assigns state Sn+1 (O) A to O∗ , and rn+1 = rn+1 as wanted. A Case 4.2. rn+1 = True. A A A A A A A Hence, since δ(sA n , on+1 ) = (sn+1 , rn+1 ), we have that oldn+1 = sn and sn+1 = newn+1 . We first prove that oldn+1 = Sn (O). There are seven cases. Case 4.2.1 ℓ is 71. A Hence, O = S. Thus, oldA n+1 = sn is t, llo, s, r where one of pn+1 ’s local variables, say ullo, is A assigned to t, llo in Cn and two other local variables, say prs and prr , are assigned to s and r in CnA , respectively. Since S ∈ / {A, L} ∪ {(∗ptr).next | ptr ∈ C ∪ {&H}}, by Definition C.6.4, every index of its state is not watermarked. Hence, since sA n = t, llo, s, r, and O = S, by Definition C.6.7, Sn (O) = t, llo, s, r. Furthermore, since the contents of ullo, prs , and prr , originated from S, by Definition C.6.4, every index of their state is not watermarked. Hence, by Definition C.6.7, Sn (ullo) = t, llo, Sn (prs ) = s, and Sn (prr ) = r. Thus, by Definition C.6.8 Cn assigns state t, llo to ullo, s to prs , and r to prr . Therefore, oldn+1 = t, llo, s, r which is equal to Sn (O) as wanted. Case 4.2.2 ℓ is 77. A Hence, O = (∗ptr).response for some ptr ∈ C ∪ {&H}. Thus, oldA n+1 = sn is t, llo, Null, where A one of pn+1 ’s local variables, say ullo, is assigned to t, llo in Cn . Observe that the content of L.ullo never originates from the response of an AllocateCell operation, so by Definition C.6.4, every index of its state is not watermarked. Hence, since the contents of ullo originated from L.ullo, by Definition C.6.4, every index of their state is not watermarked. Thus, by Definition C.6.7, Sn (ullo) = t, llo. Therefore, oldn+1 = t, llo, Null. Since O = (∗ptr).response for some ptr ∈ C ∪ {&H}, we have that O ∈ / {A, L} ∪ {(∗ptr).next | ptr ∈ C ∪ {&H}}, and so by Definition C.6.4, every index of its state is not watermarked. Thus, since sA n = t, llo, Null, by Definition C.6.7, Sn (O) = t, llo, Null. Therefore, since oldn+1 = t, llo, Null, we have that oldn+1 = Sn (O). Case 4.2.3 ℓ is 36. A Hence, O = (∗curr ptr).next for some curr ptr ∈ C ∪ {&H}. Thus, it follows that oldA n+1 = sn is view, False, 0, Null, where one of pn+1 ’s local variables, say prview , is assigned to view in CnA . Observe that the contents of the first three indices of the state of (∗curr ptr).next do not originate from the response of an AllocateCell operation, so by Definition C.6.4, the first three indices of (∗curr ptr).next are not watermarked. Hence, since sA n = view, False, 0, Null, by Definition C.6.7, Sn (O) = view, False, 0, Sn (O, 4). Furthermore, since the contents of prview originated from (∗curr ptr).next.view, by Definition C.6.4, every index of their state is not watermarked. Thus, by Definition C.6.7, Sn (prview ) = view. Therefore, oldn+1 = view, False, 0, Null. Since the fourth index of sA / C, by Definition C.6.4, Wn (O, 4) = ⊥. n is Null, and by Assumption C.1.2 Null ∈ Hence, by Definition C.6.7, Sn (O, 4) = Null. Therefore, since Sn (O) = view, False, 0, Sn (O, 4), we have that Sn (O) = view, False, 0, Null, and so oldn+1 = Sn (O) as wanted. Case 4.2.4 ℓ is 55. Hence, O = (∗ptr).next for some ptr ∈ C ∪ {&H}, so by Definition C.6.1, O ∈ CO . Thus, it folA lows that oldA n+1 = sn is view, sealed, acquisitions, next ptr, where one of pn+1 ’s local variables, say prview , is assigned to view in CnA , another, say prsealed , is assigned sealed in CnA , another, say pracquisitions , is assigned acquisitions in CnA , and another, say prnext ptr , is assigned next ptr in CnA . Observe that the contents of the first three indices of the state of (∗ptr).next do not originate from the response of an AllocateCell operation, so by Definition C.6.4, the first three indices of (∗ptr).next are not watermarked. Hence, since sA n = view, sealed, acquisitions, next ptr, 216

by Definition C.6.7, Sn (O) = view, sealed, acquisitions, Sn (O, 4). Furthermore, since the contents of prview , prsealed , and pracquisitions originated from the first three indices of (∗ptr).next, respectively, by Definition C.6.4, every index of their state is not watermarked. Thus, by Definition C.6.7, Sn (prview ) = view, Sn (prsealed ) = sealed, and Sn (pracquisitions ) = acquisitions. Therefore, oldn+1 = view, sealed, acquisitions, Sn (prnext ptr ). Since by (*) Cn assigns Sn (O) to O∗ , what remains is to prove that Sn (prnext ptr ) = Sn (O, 4). Since O ∈ CO , it follows that O∗ = (∗Sn (Os )).next. Hence, if O is in H, then O∗ = H.next, and otherwise, by Claim C.6.15.9, Wn (Os , 1) = w ̸= ⊥ and Sn (Os ) = M(w), so O∗ = (∗M(w)).next. Thus, since O∗ = (∗Sn (Os )).next, and O∗ is either H.next or (∗M(w)).next, we have that Sn (Os ) ∈ C ∪ {&H}. Since pn+1 performs a CAS operation on O∗ during the n + 1th step of B , and old In+1 n+1 = view, sealed, acquisitions, Sn (prnext ptr ), we have that pn+1 read the value view, sealed, acquisitions, Sn (prnext ptr ) from O∗ on its last execution of line 54 before the n + 1th B ; say during the ith step of I B . Hence, (∗S (O )).next.view = view in C step of In+1 n s i−1 . Furn+1 thermore, since by (*) Cn assigns Sn (O) to O∗ , and Sn (O) = view, sealed, acquisitions, Sn (O, 4), we have that (∗Sn (Os )).next.view = view in Cn . Therefore, (∗Sn (Os )).next.view is the same in Ci−1 and Cn . B We prove that for every i < j < n + 1 the jth step of In+1 does not set the value of O∗ . Suppose, B for contradiction, for some i < j < n + 1 the jth step of In+1 sets the value of O∗ . Since the B ∗ ∗ jth step of In+1 sets the value of O , and O = (∗Sn (Os )).next, by Observation C.1.6, the jth step either performs a successful list-add attempt after Sn (Os ), a successful list-seal attempt for Sn (Os ), a successful list-remove attempt between Sn (Os ) and some pointer, or a successful listacquire-next attempt after Sn (Os ). Hence, by Definition C.1.5, the jth step performs a successful CAS operation of the form CAS((∗Sn (Os )).next, (v, ∗, ∗, ∗), (v + 1, ∗, ∗, ∗)) for some view v. Thus, (∗Sn (Os )).next.view = v in Cj−1 and (∗Sn (Os )).next.view = v+1 in Cj . Therefore, since Sn (Os ) ∈ C ∪ {&H} by Observation C.1.10 (∗Sn (Os )).next.view is monotonically increasing, and i < j < n + 1, it follows that (1) (∗Sn (Os )).next.view ≤ v in Ci−1 , and (2) (∗Sn (Os )).next.view > v in Cn , and so (∗Sn (Os )).next.view is different in Ci−1 and Cn . However, as we established above, (∗Sn (Os )).next.view is the same in Ci−1 and Cn , a contradiction. B , and for We now finish the proof of Case 4.2.4. Since pn+1 reads O∗ during the ith step of In+1 B ∗ every i < j < n + 1 the jth step of In+1 does not set the value of O , we have that the state of O∗ is the same in Ci−1 and Cn . Therefore, since pn+1 read view, sealed, acquisitions, Sn (prnext ptr ) B , and C assigns state S (O) = view, sealed, acquisitions, S (O, 4) to during the ith step of In+1 n n n O∗ , we have that Sn (prnext ptr ) = Sn (O, 4) as wanted. Case 4.2.5 ℓ is 109. The proof is essentially the same as Case 4.2.4. Since ℓ is 109, we have that O = (∗ptr).next for some A ptr ∈ C ∪ {&H}, so by Definition C.6.1, O ∈ CO . Thus, it follows that oldA n+1 = sn is the sequence view, False, acquisitions, next ptr, where one of pn+1 ’s local variables, say prview , is assigned to view in CnA , another, say pracquisitions , is assigned to acquisitions in CnA , and another, say prnext ptr , is assigned to next ptr in CnA . Observe that the first three indices of the state of (∗ptr).next do not originate from the response of an AllocateCell operation, so by Definition C.6.4, the first three indices of (∗ptr).next are not watermarked. Hence, since sA n = view, False, acquisitions, next ptr, by Definition C.6.7, Sn (O) = view, False, acquisitions, Sn (O, 4). Furthermore, since the contents of prview and pracquisitions originated from the first and third index of (∗ptr).next, respectively, by Definition C.6.4, their state is not watermarked. Thus, by Definition C.6.7, Sn (prview ) = view and Sn (pracquisitions ) = acquisitions. Therefore, oldn+1 = view, False, acquisitions, Sn (prnext ptr ). Since by (*) Cn assigns Sn (O) to O∗ , what remains is to prove that Sn (prnext ptr ) = Sn (O, 4). Since O ∈ CO , it follows that O∗ = (∗Sn (Os )).next. Hence, if O is in H, then O∗ = H.next, and oth-

217

erwise, by Claim C.6.15.9, Wn (Os , 1) = w ̸= ⊥ and Sn (Os ) = M(w), so O∗ = (∗M(w)).next. Thus, since O∗ = (∗Sn (Os )).next, and O∗ is either H.next or (∗M(w)).next, we have that Sn (Os ) ∈ C ∪ {&H}. Since pn+1 performs a CAS operation on O∗ during the n + 1th step of B , and old In+1 n+1 = view, False, acquisitions, Sn (prnext ptr ), we have that pn+1 read the value view, −, acquisitions, Sn (prnext ptr ) from O∗ on its last execution of line 104 before the n + 1th step B ; say during the ith step of I B . Hence, (∗S (O )).next.view = view in C of In+1 n s i−1 . Furthermore, n+1 ∗ since by (*) Cn assigns Sn (O) to O , and Sn (O) = view, False, acquisitions, Sn (O, 4), we have that (∗Sn (Os )).next.view = view in Cn . Therefore, (∗Sn (Os )).next.view is the same in Ci−1 and Cn . B We prove that for every i < j < n + 1 the jth step of In+1 does not set the value of O∗ . Suppose, B for contradiction, for some i < j < n + 1 the jth step of In+1 sets the value of O∗ . Since the B jth step of In+1 sets the value of O∗ , and O∗ = (∗Sn (Os )).next, by Observation C.1.6, the jth step either performs a successful list-add attempt after Sn (Os ), a successful list-seal attempt for Sn (Os ), a successful list-remove attempt between Sn (Os ) and some pointer, or a successful listacquire-next attempt after Sn (Os ). Hence, by Definition C.1.5, the jth step performs a successful CAS operation of the form CAS((∗Sn (Os )).next, (v, ∗, ∗, ∗), (v + 1, ∗, ∗, ∗)) for some view v. Thus, (∗Sn (Os )).next.view = v in Cj−1 and (∗Sn (Os )).next.view = v+1 in Cj . Therefore, since Sn (Os ) ∈ C∪{&H} by Observation C.1.10 (∗Sn (Os )).next.view is monotonically increasing, and i < j < n+1, it follows that (1) (∗Sn (Os )).next.view ≤ v in Ci−1 , and (2) (∗Sn (Os )).next.view > v in Cn , and so (∗Sn (Os )).next.view is different in Ci−1 and Cn . However, (∗Sn (Os )).next.view is the same in Ci−1 and Cn , a contradiction. B , and for We now finish the proof of Case 4.2.5. Since pn+1 reads O∗ during the ith step of In+1 B every i < j < n + 1 the jth step of In+1 does not set the value of O∗ , we have that the state of O∗ is the same in Ci−1 and Cn . Hence, since pn+1 read view, −, acquisitions, Sn (prnext ptr ) during the B , and C assigns state S (O) = view, False, acquisitions, S (O, 4) to O ∗ , we have ith step of In+1 n n n that Sn (prnext ptr ) = Sn (O, 4) as wanted. Case 4.2.6 ℓ is 61. Hence, O = (∗ptr).next for some ptr ∈ C ∪ {&H}, so by Definition C.6.1, O ∈ CO . Thus, it A ′ follows that oldA n+1 = sn is view, False, acquisitions, ptr , where one of pn+1 ’s local variables, say A prview , is assigned to view in Cn , another, say pracquisitions , is assigned acquisitions in CnA , and another, say prptr′ , is assigned ptr′ in CnA . Observe that the contents of the first three indices of the state of (∗ptr).next do not originate from the response of an AllocateCell operation, so by Definition C.6.4, the first three indices of (∗ptr).next are not watermarked. Hence, since sA n = ′ view, False, acquisitions, ptr , by Definition C.6.7, Sn (O) = view, False, acquisitions, Sn (O, 4). Furthermore, since the contents of prview and pracquisitions originated from the first and third index of (∗ptr).next, respectively, by Definition C.6.4, every index of their state is not watermarked. Thus, by Definition C.6.7, Sn (prview ) = view and Sn (pracquisitions ) = acquisitions. Therefore, oldn+1 = view, False, acquisitions, Sn (prptr′ ). Since by (*) Cn assigns Sn (O) to O∗ , what remains is to prove that Sn (prptr′ ) = Sn (O, 4). We start by proving that the state of O∗ is the same at the last time pn+1 read it and Cn . The argument is essentially the same as Case 4.2.5. Since O ∈ CO , it follows that O∗ = (∗Sn (Os )).next. Hence, if O is in H, then O∗ = H.next, and otherwise, by Claim C.6.15.9, Wn (Os , 1) = w ̸= ⊥ and Sn (Os ) = M(w), so O∗ = (∗M(w)).next. Thus, since O∗ = (∗Sn (Os )).next, and O∗ is either H.next or (∗M(w)).next, we have that Sn (Os ) ∈ C ∪ {&H}. Since pn+1 performs a CAS operation B , and old on O∗ during the n + 1th step of In+1 n+1 = view, False, acquisitions, Sn (prptr′ ), we have B ; that pn+1 read the value view, −, acquisitions, − from O∗ on its last execution of line 58 in In+1 B . Hence, (∗S (O )).next.view = view in C say during the ith step of In+1 n s i−1 . Furthermore, since

218

by (*) Cn assigns Sn (O) to O∗ , and Sn (O) = view, False, acquisitions, Sn (O, 4), we have that (∗Sn (Os )).next.view = view in Cn . Therefore, (∗Sn (Os )).next.view is the same in Ci−1 and Cn . B We prove that for every i < j < n + 1 the jth step of In+1 does not set the value of O∗ . Suppose, B for contradiction, for some i < j < n + 1 the jth step of In+1 sets the value of O∗ . Since the B jth step of In+1 sets the value of O∗ , and O∗ = (∗Sn (Os )).next, by Observation C.1.6, the jth step either performs a successful list-add attempt after Sn (Os ), a successful list-seal attempt for Sn (Os ), a successful list-remove attempt between Sn (Os ) and some pointer, or a successful listacquire-next attempt after Sn (Os ). Hence, by Definition C.1.5, the jth step performs a successful CAS operation of the form CAS((∗Sn (Os )).next, (v, ∗, ∗, ∗), (v + 1, ∗, ∗, ∗)) for some view v. Thus, (∗Sn (Os )).next.view = v in Cj−1 and (∗Sn (Os )).next.view = v+1 in Cj . Therefore, since Sn (Os ) ∈ C ∪ {&H} by Observation C.1.10 (∗Sn (Os )).next.view is monotonically increasing, and i < j < n + 1, it follows that (1) (∗Sn (Os )).next.view ≤ v in Ci−1 , and (2) (∗Sn (Os )).next.view > v in Cn , and so (∗Sn (Os )).next.view is different in Ci−1 and Cn . However, as established above (∗Sn (Os )).next.view is the same in Ci−1 and Cn , a contradiction. This implies that O∗ is in the same state in Ci−1 and Cn as wanted. The difference between this case and the last two is that pn+1 ’s fourth value in oldn+1 was not read from O∗ during the ith B step of In+1 but was read much earlier from L. We now prove that the value pn+1 read from (∗Sn (Os )).next.ptr during the ith step is the fourth value in oldn+1 , i.e., Sn (prptr′ ). B , we have that p Since pn+1 performs a CAS operation on O∗ during the n + 1th step of In+1 n+1 found the condition on line 59 to be false between the ith and n + 1th step; say the jth step. Hence, L.ullo = ulloL in Cj where (ulloL , ptrL ) are the parameters of the invocation I of the DoRemoveCell procedure that pn+1 executed the n + 1th step during. Thus, by Corollary C.1.37, there is an LB . So, by Lemma C.1.28, ptr ∈ C. remove e that set L = (ulloL , ptrL ) before I was invoked in In+1 L B Since the n + 1th step of In+1 performs a CAS operation on O∗ = (∗Sn (Os )).next on line 61, and this is during I whose second parameter is ptrL , by Definition C.1.5, the n + 1th step of B In+1 is a list-remove attempt for ptrL between Sn (Os ) and some pointer next ptr. Hence, since B , and oldn+1 is the first parameter of the CAS operation performed during the n + 1th step of In+1 oldn+1 = view, False, acquisitions, Sn (prptr′ ), it follows that Sn (prptr′ ) = ptrL . B . Suppose, for contradiction, We now prove that e is the last L-event before the jth step in In+1 B there is an L-event after e and before the jth step in In+1 . Let elast be the last L-event before B , so e < e the jth step in In+1 last . Hence, since L.ullo = ulloL in Cj , we have that elast set L.ullo = ulloL . Therefore, since e < elast , and e set L.ullo = ulloL , we have that two L-events B B in In+1 set L.ullo to the same value. However, since In+1 is an implementation history of B, by B B Lemma C.2.30, P (In+1 ) holds, and so by Lemma C.1.32, every L-event in In+1 sets L.ullo to a unique value, a contradiction. We now prove that there are no successful list-add or list-remove attempts between e and the B . Suppose, for contradiction, there is a successful list-add or list-remove attempt ith step of In+1 B . The plan is to show that this implies p between e and the ith step of In+1 n+1 must have found the condition on line 59 to be true at step j, contradicting the fact that it found the condition B , so k < i. Hence, p to be false. Let k be the step of pn+1 ’s last execution of line 56 in In+1 n+1 executed the kth step during I, and so since e occurred before I was invoked, it follows that e < k. Thus, since k < i, and i < j, by transitivity, k < j, and so since e is the last L-event before the B , we have that e is the last L-event before the kth step in I B . Let I be the jth step in In+1 k n+1 B prefix of In+1 up to and including the kth step, so e is the last L-event in Ik . Hence, since Ik is an implementation history of B, by Lemma C.2.30, P (Ik ), Q(Ik ), and R(Ik ) hold, and so since e is an L-remove event for ptrL , by Lemma C.2.5, from e onwards in Ik there is at most one successful list-remove attempt for ptrL and no other successful list-add or list-remove attempt for any pointer. First, suppose from e onwards in Ik there are no successful list-remove attempts for ptrL . Hence, 219

from e onwards in Ik there are no successful list-add or list-remove attempts, so since ptrL ∈ C, by Observation C.1.6, (∗ptrL ).next.ptr is unchanged from e onwards in Ik . Now suppose from e onwards in Ik there is a successful list-remove attempt for ptrL . Hence, from e onwards in Ik there is exactly one list-remove attempt for ptrL , say a, and no other successful list-add or list-remove attempt for any pointer. Let a be between some pointer prev ptr and some pointer. Hence, since a is for ptrL , and P (Ik ) and Q(Ik ) hold, by Lemma C.1.57, prev ptr ̸= ptrL . Thus, since ptrL ∈ C, by Observation C.1.6, (∗ptrL ).next.ptr is unchanged from e onwards in Ik . Therefore, in all cases, (∗ptrL ).next.ptr is unchanged from e onwards in Ik (A). B Let Ieinclude be the prefix of In+1 up to and including e. Hence, e is the last step (and thus Linclude event) in Ie , so there is no successful list-add or list-remove attempts from e onwards Ieinclude . B ), Q(I B ), and R(I B ) hold, Thus, since e is an L-remove event and by Lemma C.2.30, P (In+1 n+1 n+1 by Lemma C.2.6, the list of cells conforms to List(Ieexclude ) in Ieinclude where Ieinclude be the prefix B of In+1 up to but excluding e (B). B Let Ii be the prefix of In+1 up to and including the ith step. Since i < j, and e is the last L-event B before the jth step in In+1 , we have that e is the last L-event in Ii . Hence, since by assumption B , we have there is a successful list-add or list-remove attempt between e and the ith step of In+1 that from e onwards in Ii there is a successful list-add or list-remove attempt. Thus, since Ii is a finite implementation history of B, by Lemma C.2.30, P (Ii ), Q(Ii ), and R(Ii ) hold, and so by Lemma C.2.6, the list of cells conforms to List(Ii ) in Ii (C). B ) holds, and so since the B is an implementation history of B, by Lemma C.2.30, Q(In+1 Since In+1 B n + 1th step of In+1 performs a list-remove attempt for ptrL between Sn (Os ) and next ptr, it is B preceded by a unique L-remove event for ptrL such that if I is the prefix of In+1 up to but excluding that L-event, then ptrL appears in List(I) exactly once and Sn (Os ) and next ptr are the pointers B , it preceding and succeeding ptrL in List(I). Thus, since e is an L-remove event for ptrL in In+1 follows that I = Ieexclude , so ptrL appears in List(Ieexclude ) exactly once, and Sn (Os ) and next ptr are the pointers preceding and succeeding ptrL in List(Ieexclude ) (D). B , it follows that I exclude is the prefix of I up to but excluding e. Since e is before the ith step of In+1 i e So, since e is the last L-event in Ii , we have that the sequence of L-events in Ieexclude and Ii are the same except the former excludes e and the latter includes e. Hence, since e is an L-remove event for ptrL , ptrL appears in List(Ieexclude ) exactly once, and Sn (Os ) and next ptr are the pointers preceding and succeeding ptrL in List(Ieexclude ), by Definition C.1.7, Sn (Os ) appears immediately before next ptr in List(Ii ) (E). We now put everything together. Since by (B) the the list of cells conforms to List(Ieexclude ) in Ieinclude , and by (D) ptrL appears in List(Ieexclude ) exactly once and next ptr is the pointer succeeding ptrL in List(Ieexclude ), by Definition C.1.7, (∗ptrL ).next.ptr = next ptr at e. Hence, since by (A) (∗ptrL ).next.ptr is unchanged from e onwards in Ik , we have that (∗ptrL ).next.ptr = next ptr in Ck . Thus, since pn+1 performs a list-remove attempt for ptrL during the n + 1th step B , and k is p B of In+1 n+1 ’s last execution of line 56 in In+1 , we have that pn+1 read next ptr from B (∗ptrL ).next.ptr during the kth step of In+1 . Since by (C) the list of cells conforms to List(Ii ) in Ii , and by (E) Sn (Os ) appears immediately before next ptr in List(Ii ), by Definition C.1.7, (∗Sn (Os )).next.ptr = next ptr in Ci . Hence, since pn+1 performs a list-remove attempt between B , and i is p B Sn (Os ) and next ptr during the n+1th step of In+1 n+1 ’s last execution of line 58 in In+1 , B . Therefore, we have that pn+1 read next ptr from (∗Sn (Os )).next.ptr during the ith step of In+1 B since k (resp. i) is pn+1 ’s last execution of line 56 (resp. line 58) in In+1 , and they both read next ptr from the ptr field of a next object of a cell during these steps, we have that pn+1 finds B , so p the condition on line 59 to be true on its last execution of it in In+1 n+1 finds the condition B on line 59 to be true during the jth step of In+1 . However, pn+1 finds the condition on line 59 to B , a contradiction. be false during the jth step of In+1 220

B We now finish the proof of Case 4.2.6. Let Ii be the prefix of In+1 up to and including the ith B step. Since i < j, and e is the last L-event before the jth step in In+1 , we have that e is the last L-event in Ii . Furthermore, since there are no successful list-add or list-remove attempts between B , we have that from e onwards in I there are no successful list-add e and the ith step of In+1 i or list-remove attempts. Hence, since P (Ii ), Q(Ii ), and R(Ii ) hold, by Lemma C.2.6, the list of B cells conforms to List(Ieexclude ) in Ii where Ieexclude is the prefix of In+1 up to but excluding e. B B Since Q(In+1 ) holds, and the n + 1th step of In+1 performs a list-remove attempt for ptrL between Sn (Os ) and next ptr, it is preceded by a unique L-remove event for ptrL such that if I is the B prefix of In+1 up to but excluding that L-event, then ptrL appears in List(I) exactly once and Sn (Os ) and next ptr are the pointers preceding and succeeding ptrL in List(I). Thus, since e is an L-remove event for ptrL , it follows that I = Ieexclude , so ptrL appears in List(Ieexclude ) exactly once, and Sn (Os ) and next ptr are the pointers preceding and succeeding ptrL in List(Ieexclude ). Since the list of cells conforms to List(Ieexclude ) in Ii , and Sn (Os ) appears immediately before ptrL in List(Ieexclude ), by Definition C.1.7, (∗Sn (Os )).next.ptr = ptrL in Ci . Hence, since pn+1 performs B , and i is p a list-remove attempt between Sn (Os ) and next ptr during the n + 1th step of In+1 n+1 ’s B last execution of line 58 in In+1 , we have that pn+1 read ptrL from (∗Sn (Os )).next.ptr during the B . So, since O ∗ = (∗S (O )).next, the fourth value of O ∗ in C ith step of In+1 n s i−1 is ptrL . Hence, ∗ since as proved above O is in the same state in Ci−1 and Cn , we have that the fourth value of O∗ in Cn is ptrL . Thus, since by (*) Cn assigns Sn (O) to O∗ , we have that Sn (O, 4) = ptrL . Therefore, since Sn (prptr′ ) = ptrL , we have that Sn (prptr′ ) = Sn (O, 4) as wanted. Case 4.2.7 ℓ is either 25 or 27. A Hence, O is either L or A. Thus, oldA n+1 = sn = t, llo, ptr, where one of pn+1 ’s local variables, A say ullo, is assigned to t, llo in Cn , and another, say pr, is assigned to ptr in CnA . Observe that, the contents of ullo did not originate from the response of an AllocateCell operation, and so by Definition C.6.4, Wn (ullo, 1) = Wn (ullo, 2) = ⊥. Hence, by Definition C.6.7, Sn (ullo) = t, llo. Thus, by Definition C.6.8 Cn assigns state t, llo to ullo, so oldn+1 = t, llo, Sn (pr). Likewise, observe that the contents of A.ullo (resp. L.ullo) do not originate from the response of an AllocateCell operation, and so by Definition C.6.4, Wn (A, 1) = Wn (A, 2) = ⊥ (resp. Wn (L, 1) = Wn (L, 2) = ⊥). Hence, by Definition C.6.7, Sn (O) = t, llo, Sn (O, 3). There are two cases. Case A. Wn (pr, 1) = ⊥ and Wn (O, 3) = ⊥. Hence, since pr is assigned to ptr in CnA and the third index of O is ptr, by Definition C.6.7, Sn (pr) = ptr and Sn (O, 3) = ptr, and so Sn (pr) = Sn (O, 3). Therefore, since oldn+1 = t, llo, Sn (pr) and Sn (O) = t, llo, Sn (O, 3), we have that oldn+1 = Sn (O), as wanted. Case B. Wn (pr, 1) or Sn (O, 3) is not ⊥. Hence, since pr and the third index of O is assigned to ptr in CnA , by Definition C.6.4, we have that ptr ∈ C, so by Assumption C.1.2, ptr ̸= Null. Thus, since pr is a value read from the third index of O, and the third index of O is initially Null, we have that some process set the A . Since, as we can see, all values written into the third index of third index of O to ptr in In+1 O originate from the response of an AllocateCell operation, both Wn (pr, 1) and Wn (O, 3) are not ⊥. Let Wn (pr, 1) = w ̸= ⊥ and Wn (O, 3) = w′ ̸= ⊥. Hence, by Definition C.6.7, Sn (pr) = M(w) and Sn (O, 3) = M(w′ ). Thus, oldn+1 = t, llo, M(w) and Sn (O) = t, llo, M(w′ ). Therefore, if M(w) = M(w′ ), oldn+1 = Sn (O), so it suffices to consider the case where M(w) ̸= M(w′ ). We show that M(w) ̸= M(w′ ) leads to a contradiction, so this case is impossible. Since oldn+1 = B ; say during t, llo, M(w), we have that pn+1 read t, llo, M(w) from O before the n + 1th step of In+1 B . Hence, since the third index of O is initially Null and by Assumption C.1.2 the ith step of In+1 M(w) ̸= Null, we have that some process set O to t, llo, M(w) before the ith step; say during B . Since S (O) = t, llo, M(w ′ ), by Definition C.6.8, C assigns t, llo, M(w ′ ) to the jth step of In+1 n n

221

B , and M(w) ̸= M(w ′ ), we have that O. Hence, since pn+1 read M(w) during the ith step of In+1 B O was set to t, llo, M(w′ ) during the kth step of In+1 where i < k < n + 1. Thus, since j < i, by transitivity, j < k, so j ̸= k. There are two cases. Case B.1. O = L. B Therefore, the jth (resp. kth) step of In+1 perform distinct L-events that set L.ullo to the same B value (namely, t, llo). However, since In+1 is an implementation history of B, by Lemma C.2.30, B ) holds, so by Lemma C.1.32, every L-event in I B P (In+1 n+1 sets L.ullo to a distinct value, a contradiction, so Case B.1. is impossible. Case B.2. O = A. B B Since the jth (resp. kth) step of In+1 set A to t, llo, M(w) (resp. t, llo, M(w′ )), and In+1 is an ′ implementation history of B, by Proposition C.1.16, M(w) = M(w ). However, M(w) ̸= M(w′ ), a contradiction, so Case B.2 is impossible. This completes the proof that oldn+1 = Sn (O). We now return to the proof of Case 4.2. Since by (*) Cn assigns Sn (O) to O∗ , on+1 is an operation B on O∗ , and oldn+1 = Sn (O), we have that on+1 is successful, so rn+1 = True and Cn+1 assigns ∗ A A A A A state newn+1 to O . Recall that sn+1 = newn+1 , so Cn+1 assigns state newn+1 to O. Let newn+1 = ′ ′ v1 , v2 , . . . and newn+1 = v1 , v2 , . . .. Observe that vi is either (a) a value dictated by ℓ or (b) pn+1 read vi from the ji th index of its local variable pri in CnA . We consider each case separately. Case (a). Hence, 3 of Definition C.6.4 is not satisfied so Wn+1 (O, i) = ⊥, and so by Definition C.6.7 B , it Sn+1 (O, i) = vi . Furthermore, since pn+1 executes line ℓ during the n + 1th step of In+1 follows that vi′ = vi . Therefore Sn+1 (O, i) = vi′ . Case (b). B , by Definition C.6.8, v ′ = S (pr , j ). Hence, since pn+1 executes line ℓ during the n+1th step of In+1 n i i i Furthermore, 3 of Definition C.6.4 is satisfied so Wn+1 (O, i) = Wn (pri , ji ) or Wn+1 (O, i) = ⊥. First A suppose that Wn+1 (O, i) = Wn (pri , ji ). Hence, since the ith index of O is vi in Cn+1 and the ji th A index of pri is vi in Cn , by Definition C.6.7 Sn+1 (O, i) = Sn (pr, ji ). Therefore, since vi′ = Sn (pri , ji ), we have that Sn+1 (O, i) = vi′ . Now suppose that Wn+1 (O, i) = ⊥. Hence, since 3 of Definition C.6.4 is satisfied, it follows that vi ∈ / C. Thus, since the ji th index of pri is vi in CnA , by Definition C.6.4, Wn (pr, ji ) = ⊥. So, since Wn+1 (O, i) = ⊥ (resp. Wn (pr, ji ) = ⊥) and the value of the ith A (resp. CnA ) is vi , by Definition C.6.7, we have that (resp. ji th) index of O (resp. pr) in Cn+1 Sn+1 (O, i) = Sn (pr, ji ) = vi . Therefore, since vi′ = Sn (pri , ji ), we have that Sn+1 (O, i) = vi′ . We now finish the proof of Case 4.2. Since Sn+1 (O, i) = vi′ for each index i of the state of O in A , we have that v ′ , v ′ , . . . = S B Cn+1 n+1 (O, 1), Sn+1 (O, 2), . . ., so newn+1 = Sn+1 (O). Therefore, Cn+1 1 2 ∗ A assigns Sn+1 (O) to O and rn+1 = rn+1 as wanted.

Case 5. oA n+1 is GCAS operation. Hence, since by Lemma C.6.9 the program counter of pn+1 is the same in CnA and Cn , and pn+1 B , we have that o A takes the n + 1th step of In+1 n+1 is a GCAS operation. If the comparator of on+1 A is =, on+1 is simply a CAS operation, which we covered in Case 4. Hence, since A only performs GCAS(=) and GCAS(>) operations, it suffices to consider the case where the comparator of oA n+1 is >. Observe that the only GCAS(>) operation is on line 21. Hence, O = A. Furthermore, A the second and third parameter of oA n+1 (resp. on+1 ) are the same. Let valn+1 (resp. valn+1 ) A A A A be the second and third parameter of on+1 (resp. on+1 ). Hence, valn+1 = tA n+1 , llon+1 , ptrn+1 A A A where one of pn+1 ’s local variables, say ullo, is assigned to tn+1 , llon+1 in Cn , and another, say A pr, is assigned to ptrn+1 in CnA . Observe that the contents of ullo do not originate from the response of an AllocateCell operation, so by Definition C.6.4, Wn (ullo, 1) = Wn (ullo, 2) = ⊥. A Hence, by Definition C.6.7 Sn (ullo) = tA n+1 , llon+1 . Furthermore, observe that the contents of pr 222

A originated from the response of an AllocateCell operation, so by Algorithm 3 ptrn+1 ∈ C, and by Definition C.6.4, Wn (pr, 1) = w ̸= ⊥. Hence, by Definition C.6.7, Sn (pr, 1) = M(w). Therefore, A by Definition C.6.8, valn+1 = tA n+1 , llon+1 , M(w). A A A A Since CnA assigns state sA n to O, and O = A, we have that sn = tn , llon , ptrn . Observe that the contents of A.ullo do not originate from the response of an AllocateCell operation, and so by Definition C.6.4, Wn (A, 1) = Wn (A, 2) = ⊥. Hence, since O = A, by Definition C.6.7, Sn (O) = A tA n , llon , Sn (O, 3). There are two cases. A Case 5.1. rn+1 = False. A A A A A Hence, since δ(sA n , on+1 ) = (sn+1 , rn+1 ), and on+1 is a GCAS(>) operation, we have that sn ≤ A A A A A valn+1 and sn+1 = sn (i.e., the state of O is the same in Cn and Cn+1 ). Thus, pn+1 did not set A . any index of O during the n + 1th step of In+1 We first prove that Sn+1 (O) = Sn (O). Let vj be the value of the jth index of the state of O in A . Hence, since the state of O is the same in C A and C A , it follows that v is the value of Cn+1 j n n+1 the jth index of the state of O in CnA . Furthermore, since n is a non-negative integer, n + 1 > 0, so n ≥ 0. There are two cases. Case 5.1.1. vj ∈ C. A , by 1 Hence, since O = A, and pn+1 does not set any index of O during the n + 1th step of In+1 of Definition C.6.4, Wn+1 (O, j) = Wn (O, j). Therefore, since the state of O is the same in CnA and A , by Definition C.6.7, S Cn+1 n+1 (O, j) = Sn (O, j). Case 5.1.2. vj ∈ / C. Hence, by Definition C.6.4, Wn+1 (O, j) = ⊥. We now show that Wn (O, j) = ⊥. Recall that n ≥ 0. If n = 0, then by Definition C.6.4, Wn (O, j) = ⊥, as wanted, so suppose n > 0. Hence, since by assumption vj ∈ / C, and vj is the value of the jth index of the state of O in CnA , by Definition C.6.4, Wn (O, j) = ⊥. Therefore, since in all cases Wn+1 (O, j) = Wn (O, j), and the state of O is the same A , by Definition C.6.7, S in CnA and Cn+1 n+1 (O, j) = Sn (O, j). Since Sn+1 (O, j) = Sn (O, j) for every index j of O, by Definition C.6.7, Sn+1 (O) = Sn (O). This completes the proof that Sn+1 (O) = Sn (O). A A A A A A A We now finish the proof of Case 5.1. Since sA n = tn , llon , ptrn , valn+1 = tn+1 , llon+1 , ptrn+1 , and A A A A A A sn ≤ valn+1 , we have that tn ≤ tn+1 . Hence, since Sn (O) = tn , llon , Sn (O, 3), and valn+1 = A tA n+1 , llon+1 , M(w), we have that Sn (O) ≤ valn+1 . Thus, on+1 is unsuccessful. So, rn+1 = False B and Cn+1 assigns the same state to O∗ as Cn . Therefore, since by (*) Cn assigns state Sn (O) to ∗ B A . O , and Sn+1 (O) = Sn (O), we have that Cn+1 assigns state Sn+1 (O) to O∗ and rn+1 = rn+1 A Case 5.2. rn+1 = True. A A A A A Hence, since δ(sA n , on+1 ) = (sn+1 , rn+1 ), and on+1 is a GCAS(>) operation, we have that sn > A A A A A A A valn+1 and sA n+1 = valn+1 . Hence, since valn+1 = tn+1 , llon+1 , ptrn+1 , we have that sn+1 = A A A A A tn+1 , llon+1 , ptrn+1 . Thus, since pn+1 set the first and second index of O to tn+1 and llon+1 during A A A the n + 1th step of In+1 because the first and second index of ullo are tA n+1 and llon+1 in Cn , respectively, by 3 of Definition C.6.4, Wn+1 (O, 1) = Wn (ullo, 1) and Wn+1 (O, 2) = Wn (ullo, 2), or Wn+1 (O, 1) = Wn+1 (O, 2) = ⊥. So, since Wn (ullo, 1) = Wn (ullo, 2) = ⊥, in either case, by DefiniA A tion C.6.7, Sn+1 (O, 1) = tA n+1 and Sn+1 (O, 2) = llon+1 . Similarly, since ptrn+1 ∈ C and pn+1 set the A A third index of O to ptrn+1 during the n+1th step of In+1 because the first index of pr is assigned to A ptrn+1 in CnA , by 3 of Definition C.6.4, Wn+1 (O, 3) = Wn (pr, 1). Hence, since Wn (pr, 1) = w ̸= ⊥, A by Definition C.6.7, Sn+1 (O, 3) = M(w). Therefore, Sn+1 (O) = tA n+1 , llon+1 , M(w), and so ∗ valn+1 = Sn+1 (O). We now prove that on+1 sets O to valn+1 . A A A A A We first prove that tA n > tn+1 . Suppose, for contradiction, that tn ≤ tn+1 . If tn < tn+1 , then A A A A A A A A since sn = tn , llon , ptrn and valn+1 = tn+1 , llon+1 , M(w), we have that sn < valn+1 . However, A A A as established above, sA n > valn+1 , a contradiction, so tn ≥ tn+1 . Thus, since by assumption

223

A A A A A A A A A A A tA n ≤ tn+1 , we have that tn = tn+1 . Hence, since sn = tn , llon , ptrn and sn+1 = tn+1 , llon+1 , ptrn+1 , A A A A A by Lemma C.6.2, sA n+1 = sn . Therefore, since sn+1 = valn+1 , we have that sn = valn+1 . However, A A sn > valn+1 , a contradiction. A A A We now finish the proof of Case 5.2. Since tA n > tn+1 , Sn (O) = tn , llon , Sn (O, 3), and valn+1 = A tA n+1 , llon+1 , M(w), we have that Sn (O) > valn+1 . Hence, on+1 is successful. Thus, rn+1 = True B B and Cn+1 assigns state valn+1 to O∗ . Therefore, since valn+1 = Sn+1 (O), we have that Cn+1 assigns ∗ A state Sn+1 (O) to O and rn+1 = rn+1 as wanted. Claim C.6.15.12 A . Then, Claim C.6.15.13. Consider any local variable pr other than the program counters in Cn+1 B Cn+1 assigns state Sn+1 (pr) to pr. A A A Proof. Let sA n (resp. sn+1 ) be the state assigned to pr in Cn (resp. Cn+1 ) and let sn (resp. sn+1 ) B be the state assigned to pr in Cn (resp. Cn+1 ). Consider any index i of sA n+1 . We will prove that the ith index of sn+1 is Sn+1 (pr, i). There are two cases. A Case 1. the line of code ℓ executed by pn+1 during the n + 1th step of In+1 does not set the ith index of pr. A Hence, the ith index of sA n and sn+1 are the same. Furthermore, since by Lemma C.6.9, the program B , we have counter of pn+1 is the same in CnA and Cn , and pn+1 performs the n + 1th step of In+1 B that pn+1 executes ℓ during the n + 1th step of In+1 , and so the ith index of pr is the same in B . So, the ith index of s and s Cn and Cn+1 n n+1 are the same. Hence, since by Definition C.6.8 the ith index of sn is Sn (pr, i), we have that the ith index of sn+1 is Sn (pr, i). Since pn+1 does A , we have that 1 of Definition C.6.4 is not set the ith index of pr during the n + 1th step of In+1 satisfied, so Wn (pr, i) = Wn+1 (pr, i) if the ith index of pr in CnA is in C and Wn+1 = ⊥ if the ith index of pr in CnA is not in C. Hence, in the latter case, by Definition C.6.4, Wn = ⊥, and so in A , by all cases Wn (pr, i) = Wn+1 (pr, i). Thus, since the ith index of pr is the same in CnA and Cn+1 Definition C.6.7, Sn (pr, i) = Sn+1 (pr, i). Therefore, since the ith index of sn+1 is Sn (pr, i), we have that the ith index of sn+1 is Sn+1 (pr, i) as wanted. A Case 2. the line of code ℓ executed by pn+1 during the n + 1th step of In+1 sets the ith index of pr. We first deal with the special case of ℓ = 1. In this case, pr is the local variable hlo of pn+1 and i = 1. Notice that pr is set “externally” because pn+1 performs an invocation step during the A . Hence, the contents of pr did not originate from the response of AllocateCell n + 1th step of In+1 operation, and so by Definition C.6.4, Wn+1 (pr, 1) = ⊥. Thus, by Definition C.6.7, Sn+1 (pr) is A . Recall from the definition of C B the value of pr in Cn+1 n+1 that if pn+1 executes line 1 during the A B n + 1th step of In+1 , then Cn+1 is choosen such that pn+1 performs the same invocation step during B . Hence, the value of pr is the same in C A B the n + 1th step of In+1 n+1 and Cn+1 . Therefore, since i = 1, we have that the ith index of sn+1 is Sn+1 (pr, i) as wanted. Now suppose that ℓ = 70. Hence, pr is either s′ or r′ , so sA n+1 is a single value and i = 1. Thus, B B based on how we defined Cn+1 , we have that Cn+1 assigns state sA n+1 to pr. Since in this case pr does not satisfy the conditions of 2 of Definition C.6.4, we have that Wn+1 (pr, 1) = ⊥. Hence, since A A B Cn+1 assigns sA n+1 to pr, by Definition C.6.7 Sn+1 (pr, 1) = sn+1 . Therefore, since Cn+1 assigns A B state sn+1 to pr, we have that Cn+1 assigns state Sn+1 (pr, 1) to pr as wanted. Now suppose ℓ is neither 1 nor 70. Observe that the ith index of sA n+1 is either (a) the jth index of one of pn+1 ’s local variables pr′ in CnA or (b) the jth index of the response pn+1 received from an A . In Case (b), by Claim C.6.15.2, it follows operation o it performed during the n + 1th step of In+1 that o is an operation on a base object. We consider each case separately.

224

Case (a). Hence, since by Lemma C.6.9, the program counter of pn+1 is the same in CnA and Cn , and pn+1 B , the ith index of pr in C B ′ performs the n + 1th step of In+1 n+1 is the jth index of pr in Cn . Thus, ′ the ith index of sn+1 is the jth index of pr in Cn . Let s be the state assigned to pr′ in CnA . We first prove that Sn+1 (pr, i) = Sn (pr′ , j). Let vj be the value of the jth index of s. Hence, since ′ A A the ith index of sA n+1 is the jth index of pr in Cn , we have that the ith index of sn+1 is vj . Since ′ A A sA n+1 (resp. s) is the state assigned to pr (resp. pr ) in Cn+1 (resp. Cn ), and the ith (resp. jth) A index of sn+1 (resp. s) is vj , we have that if vj ∈ / C, then by Definition C.6.4 Wn+1 (pr, i) = ⊥ (resp. Wn (pr′ , j) = ⊥). Otherwise, since pr is a local variable of pn+1 other than its program A counter, and pn+1 sets the ith index of pr to vj during the n + 1th step of In+1 because the jth ′ A ′ index of pr is vj in Cn , by 2.3 of Definition C.6.4, Wn+1 (pr, i) = Wn (pr , j). So, in all cases, Wn+1 (pr, i) = Wn (pr′ , j). Therefore, since the ith (resp. jth) index of sA n+1 (resp. s) is vj , by ′ Definition C.6.7, Sn+1 (pr, i) = Sn (pr , j) as wanted. We now finish the proof of Case (a). Since by Definition C.6.8 the jth index of pr′ is Sn (pr′ , j) in Cn , and the ith index of sn+1 is the jth index of pr′ in Cn , we have that the ith index of sn+1 is Sn (pr′ , j). Therefore, since Sn+1 (pr, i) = Sn (pr′ , j), the ith index of sn+1 is Sn+1 (pr, i) as wanted. Case (b). A Hence, pn+1 performed an operation oA n+1 on a base object O with response rn+1 during the n + 1th A A step of In+1 and the ith index of sA n+1 is the jth index of rn+1 . Hence, since by Lemma C.6.9, the A B , program counter of pn+1 is the same in Cn and Cn , and pn+1 performs the n + 1th step of In+1 B we have that the ith index of pr in Cn+1 is the jth index of the response rn+1 pn+1 received during B . There are three cases. the n + 1th step of In+1 Case (b).1. O is the memory manager. Hence, oA n+1 is either an AllocateCell or FreeCell operation. However, since the only line of code that performs a FreeCell operation is line 114, and its response is not stored in any local variable, we have that oA n+1 is an AllocateCell operation whose response is v1 . Hence, since the only line of code that performs an AllocateCell operation is line 2, we have that pn+1 executed line 2 during A . Thus, pr is the local variable ptr of p the n + 1th step of In+1 n+1 on line 2 and i = 1. Since A on+1 is an AllocateCell operation whose response is v1 , we have that pn+1 sets the 1st index of pr A . Hence, sA to v1 during the n + 1th step of In+1 n+1 = v1 . Furthermore, by 2.1 of Definition C.6.4, Wn+1 (pr, 1) = n + 1, and so by Definition C.6.7, Sn+1 (pr, 1) = M(n + 1). Since the n + 1th step A B of In+1 performs an AllocateCell operation, by Claim C.6.15.4, the n + 1th step of In+1 performs an AllocateCell operation whose response is M(n + 1). Hence, since pr is the local variable ptr of pn+1 on line 2, we have that sn+1 = M(n + 1). Thus, since Sn+1 (pr, 1) = M(n + 1), we have that sn+1 = Sn+1 (pr, 1). Therefore, since i = 1, the ith index of sn+1 is Sn+1 (pr, i) as wanted. Case (b).2. O is not the memory manager and oA n+1 is a read operation. We first prove that the ith index of sA is the jth index of the state s assigned to O in CnA . If n+1 A A O∈ / CO , then rn+1 = s. Otherwise, if O ∈ CO , then by Claim C.6.15.10, rn+1 = s. So, in all cases, A A A rn+1 = s. Therefore, since the ith index of sn+1 is the jth index of rn+1 , we have that the ith index of sA n+1 is the jth index of s as wanted. We now prove that Sn+1 (pr, i) = Sn (O, j). Let vj be the jth index of s, so the ith index of sA n+1 A A ), and the is vj . Since sA (resp. s) is the state assigned to pr (resp. O) in C (resp. C n n+1 n+1 ith (resp. jth) index of sA / C, then by Definition C.6.4 n+1 (resp. s) is vj , we have that if vj ∈ Wn+1 (pr, i) = ⊥ (resp. Wn (O, j) = ⊥). Otherwise, since pr is a local variable of pn+1 other than A its program counter, and pn+1 sets the ith index of pr to vj during the n + 1th step of In+1 because pn+1 performs a read operation on O whose jth index of its response is vj which, as we just proved, is also the jth index of its state in CnA , by 2.2 of Definition C.6.4, Wn+1 (pr, i) = Wn (O, j). So, in 225

all cases, Wn+1 (pr, i) = Wn (O, j). Therefore, since the ith (resp. jth) index of sA n+1 (resp. s) is vj , by Definition C.6.7, Sn+1 (pr, i) = Sn (O, j) as wanted. We now finish the proof of Case (b).2. Since oA n+1 is a read operation on O, by Claim C.6.15.12, rn+1 = Sn (O). Hence, since the ith index of sn+1 is the jth index of rn+1 , we have that the ith index of sn+1 is the jth index of Sn (O), or equivalently Sn (O, j). Therefore, since Sn+1 (pr, i) = Sn (O, j), we have the ith index of sn+1 is Sn+1 (pr, i) as wanted. Case (b).3. O is not the memory manager and oA n+1 is not a read operation. A . Since the ith index of We first prove that Sn+1 (pr, i) = vj where vj is the jth index of rn+1 A A sA n+1 is the jth index of rn+1 , we have that the ith index of sn+1 is vj . Furthermore, since pr is a local variable of pn+1 other than its program counter, and pi+1 performs a non-read operation oA n+1 A , none of the conditions of Definition C.6.4 are satisfied, so on O during the n + 1th step of In+1 Wn+1 (pr, i) = ⊥. Therefore, since the ith index of sA n+1 is vj , by Definition C.6.7, Sn+1 (pr, i) = vj . We now finish the proof of Case (b).3. Since oA n+1 is not a read operation, by Claim C.6.15.12, A rn+1 = rn+1 . Hence, since the ith index of sn+1 is the jth index of rn+1 , we have that the the ith A , or equivalently v . Therefore, since S index of sn+1 is the jth index of rn+1 j n+1 (pr, i) = vj , we have the ith index of sn+1 is Sn+1 (pr, i) as wanted. We now finish the proof of Claim C.6.15.13. Since the ith index of sn+1 is Sn+1 (pr, i), by DefiniB tion C.6.7, sn+1 = Sn+1 (pr). Therefore, Cn+1 assigns Sn+1 (pr) to pr as wanted. Claim C.6.15.13 B We now prove that the program counters are the same in Cn+1 and Cn+1 . We start by dealing with the difficult cases in which a process compares two pointers and updates its program counter based on the comparison’s outcome.

Claim C.6.15.14. If pn+1 executes line ℓ where ℓ is either 30, 46, or 94 during the n + 1th step A of In+1 and finds the condition on line ℓ to be false, then pn+1 executes line ℓ during the n + 1th B step of In+1 and finds the condition on line ℓ to be false. Proof. Since by Lemma C.6.9 the program counter of pn+1 is the same in CnA and Cn , and pn+1 B , we have that p B takes the n + 1th step of In+1 n+1 executes line ℓ during the n + 1th step of In+1 . A Furthermore, since pn+1 finds the condition on line ℓ to be false during the n + 1th step of In+1 , it follows that pn+1 finds curr ptr = ptrL in CnA on line 30 or line 46, and curr ptr = target ptr in CnA on line 94. For uniformity, we let ptr be ptrL or target ptr depending on ℓ. Hence, curr ptr = ptr in CnA . Observe that the state of ptr and curr ptr is a single value. For ptr, this is because it is the last value of L or A, and for curr ptr, this is because it is either &H, or it is the last value of the next object of some cell. Hence, by Definition C.6.7, Sn (ptr) = Sn (ptr, 1) and Sn (curr ptr) = Sn (curr ptr, 1). There are four cases. Case 1. Wn (ptr, 1) = ⊥ and Wn (curr ptr, 1) = ⊥. Hence, by Definition C.6.7, Sn (ptr, 1) (resp. Sn (curr ptr, 1)) is the same as the first value of ptr (resp. curr ptr) in CnA . Thus, since Sn (ptr) = Sn (ptr, 1) (resp. Sn (curr ptr) = Sn (curr ptr, 1)), we have that Sn (ptr) (resp. Sn (curr ptr)) is the same as the value of ptr (resp. curr ptr) in CnA . So, by Definition C.6.8, the value of ptr (resp. curr ptr) is the same in CnA and Cn . Therefore, since curr ptr = ptr in CnA , we have that curr ptr = ptr in Cn , and so pn+1 finds the condition on B line ℓ to be false during the n + 1th step of In+1 as wanted. Case 2. Wn (ptr, 1) ̸= ⊥ and Wn (curr ptr, 1) = ⊥. Hence, since Sn (ptr) = Sn (ptr, 1), by Definition C.6.4, the value of ptr in CnA is in C. Thus, since curr ptr = ptr in CnA , we have that the value of curr ptr in CnA is in C; say v. So, by Definition C.6.5, 226

A ). Furthermore, since S (curr ptr) = S (curr ptr, 1) and W (curr ptr, 1) = ⊥, by v ∈ C(In+1 n n n Definition C.6.8, the value of curr ptr in Cn is v. Since v ∈ C, by Assumption C.1.2, v ̸= &H, and B , so since curr ptr is initialized to &H on either line 29, line 45, or line 93 depending on ℓ in In+1 B we have that pn+1 set curr ptr to v on either line 40, line 52, or line 100 depending on ℓ in In+1 . B . Let I B be the prefix of I B Thus, pn+1 performed a list-acquire-next attempt a for v in In+1 a n+1 up B to and including a. Hence, by Lemma C.5.37, v is active in Ia , and so by Lemma C.5.29, there is an B ). Thus, by Corollary C.1.24, there is an A-event e′ for v before L-event e for v in IaB (and thus In+1 B e in In+1 . Hence, the process p that executed e′ did so during an invocation of the DoLowLevelOp procedure with a second parameter of v. Thus, p performed an AllocateCell operation on line 2 B . Therefore, since v ∈ C(I A ), there is an AllocateCell operation in whose response is v in In+1 n+1 B A ). However, by Claim C.6.15.5, the response of every AllocateCell In+1 whose response is in C(In+1 B A ), so Case 2 is impossible. operation in In+1 is not in C(In+1

Case 3. Wn (ptr, 1) = ⊥ and Wn (curr ptr, 1) ̸= ⊥. Hence, since Sn (curr ptr) = Sn (curr ptr, 1), the value of curr ptr in CnA is in C. Thus, since curr ptr = ptr in CnA , we have that the value of ptr in CnA is in C; say v. So, by Definition C.6.5, A ). Furthermore, since S (ptr) = S (ptr, 1) and W (ptr, 1) = ⊥, by Definition C.6.8, the v ∈ C(In+1 n n n value of ptr is v in Cn . First consider the case where ℓ is either 30, 46, or 94 during an invocation of the Acquire procedure invoked on line 75. In these cases, pn+1 read v from L.ptr. Since v ∈ C, by Assumption C.1.2, v ̸= Null. Hence, since L.ptr is initially Null, we have that L.ptr was set to v. B . Therefore, by Corollary C.1.24, there Thus, by Definition C.1.5, there is an L-event for v in In+1 B is an A-event for v in In+1 . Now consider the case where ℓ is 94 during an invocation of the Acquire procedure invoked on line 80. In this case, pn+1 read v from A.ptr. Since v ̸= Null, and A.ptr is initially Null, we have that A.ptr was set to v. Thus, by Definition C.1.5, there is an A-event for v B . Therefore, in all cases, there is an A-event for v in I B . Let p be the process that executed in In+1 n+1 this A-event for v. Hence, p did so during an invocation of the DoLowLevelOp procedure with a second parameter of v. Thus, p performed an AllocateCell operation on line 2 whose response is A ), we have that there is an AllocateCell operation in I B v. Therefore, since v ∈ C(In+1 n+1 whose A response is in C(In+1 ). However, by Claim C.6.15.5, the response of every AllocateCell operation B A ), so Case 3 is impossible. in In+1 is not in C(In+1 Case 4. Wn (ptr, 1) ̸= ⊥ and Wn (curr ptr, 1) ̸= ⊥. Let Wn (ptr, 1) = w ̸= ⊥ and Wn (curr ptr, 1) = w′ ̸= ⊥. Hence, by Definition C.6.7, Sn (ptr, 1) = M(w) and Sn (curr ptr, 1) = M(w′ ). Therefore, since Sn (ptr) = Sn (ptr, 1) and Sn (curr ptr) = Sn (curr ptr, 1), we have that Sn (ptr) = M(w) and Sn (curr ptr) = M(w′ ). So, by Definition C.6.8, ptr (resp. curr ptr) is assigned to M(w) (resp. M(w′ )) in Cn . Hence, since pn+1 checks whether A curr ptr ̸= ptr during the n + 1th step of In+1 and pn+1 executes line ℓ during the n + 1th step of B In+1 , we have that pn+1 checks whether curr ptr ̸= ptr (and thus whether M(w) ̸= M(w′ )) during B . Thus, if w = w ′ , then M(w) = M(w ′ ), so it follows that p the n + 1th step of In+1 n+1 finds the B condition on line ℓ to be false during the n + 1th step of In+1 . Therefore, it suffices to consider the case where w ̸= w′ . Since Wn (ptr, 1) = w ̸= ⊥ (resp. Wn (curr ptr, 1) = w′ ̸= ⊥), by Lemma C.6.12, the wth (resp. A w′ th) step of In+1 performs an AllocateCell operation whose response is the value of ptr (resp. A curr ptr) in Cn . Hence, since curr ptr = ptr in CnA , we have that this is the same value, say A v, and so the wth and w′ th step of In+1 perform an AllocateCell operation whose response is B v. Furthermore, by Claim C.6.15.4, the wth (resp. w′ th) step of In+1 performs an AllocateCell ′ ′ operation whose response is M(w) (resp. M(w )). Since w ̸= w , there are two cases. Case 4.1. w′ < w.

227

A Hence, since the w′ th and wth step of In+1 perform an AllocateCell operation whose response is ′ A v, by Algorithm 3, v ∈ C and for some w < j < w the jth step of In+1 performs a FreeCell(v) ′ A operation. Thus, by Claim C.6.15.7, for some w < k ≤ j the kth step of In+1 performs a ′ FreeCell(v), and Wk−1 (Ok , 1) = w where Ok is the local variable curr ptr of pk in the Relinquish B procedure. So, by Claim C.6.15.6, the kth step of In+1 performs a FreeCell(M(w′ )) operation. Hence, by Lemma C.1.126, there is a successful list-remove attempt armv for M(w′ ) before the kth B . Therefore, since k ≤ j and j < w, by transitivity, a step of In+1 rmv < w (*). B Since ℓ is either 30, 46, or 94, pn+1 performs the n + 1th step of In+1 in the context of an invocation I of either a DoAddCell, DoRemoveCell, or Acquire procedure. Hence, since pn+1 checks whether B , and ptr is assigned to M(w) in C , we have that curr ptr ̸= ptr during the n + 1th step of In+1 n pn+1 read M(w) from either L.ptr or A.ptr before invoking I. We now prove that I was invoked B after the wth step of In+1 (**). We start by proving that there is an A-event for M(w) before pn+1 invoked I. Since M(w) ∈ C, by Assumption C.1.2, M(w) ̸= Null. First suppose pn+1 read M(w) from L.ptr before invoking I. Hence, since L.ptr is initially Null, and M(w) ̸= Null, we have that L.ptr was set to M(w) before I was invoked. Thus, by Definition C.1.5, there is an L-event for M(w) before T 14 . Therefore, by Corollary C.1.24, there is an A-event for M(w) before I was invoked as wanted. Now suppose that pn+1 read M(w) from A.ptr before invoking I. Hence, since A.ptr is initially Null, and M(w) ̸= Null, we have that A.ptr was set to M(w) before I was invoked. Therefore, by Definition C.1.5, there is an A-event for M(w) before I was invoked as wanted. Let e be this A-event for M(w) before pn+1 invoked I. By Definition C.1.5, the process q that executed e did so during an invocation of the DoLowLevelOp procedure whose second parameter is M(w). Hence, q performed an AllocateCell operation whose response is M(w) before executing e. Since by Algorithm 4 only a single AllocateCell operation has response M(w), B performs an AllocateCell operation has response M(w), we have that and the wth step of In+1 B . w < e. Hence, since pn+1 invoked I after e, we have that pn+1 invoked I after the wth step of In+1 ′ ′ We now finish the proof of Case 4.1. Since M(w ) ∈ C, by Assumption C.1.2, M(w ) ̸= &H. Hence, since pn+1 initializes curr ptr to &H on line 29, 45, or 93 depending on ℓ during I, and finds that curr ptr = M(w′ ) on line 30, line 46, or line 94 depending on ℓ during I, we have that pn+1 set curr ptr = M(w′ ) on either line 40, line 52, or line 100 depending on ℓ during I. Hence, pn+1 received response (Found, M(w′ )) from an invocation of the AcquireNext procedure during B I. Thus, pn+1 performed a successful list-acquire-next attempt aacq for M(w′ ) during I. Let Iacq B B is a successful list-acquirebe the prefix of In+1 up to and including aacq . Since the last step of Iacq ′ ′ B next attempt for M(w ), by Lemma C.5.37, M(w ) is active in Iacq . Hence, by Definition C.5.27, B , or equivalently, before a B there are no successful list-remove attempts for M(w′ ) in Iacq acq in In+1 . Therefore, since pn+1 executed aacq during I, and by (**) pn+1 invoked I after the wth step of B , we have that w < a ′ In+1 acq , so there are no successful list-remove attempts for M(w ) before the B wth step of In+1 . However, by (*) armv < w, so there is a successful list-remove attempt for M(w′ ) B , a contradiction, so Case 4.1 is impossible. before the wth step of In+1 Case 4.2. w < w′ . A Hence, since the wth and w′ th step of In+1 perform an AllocateCell operation whose response is A v, by Algorithm 3, v ∈ C and for some w < j < w′ the jth step of In+1 performs a FreeCell(v) A performs a FreeCell(v), operation. Thus, by Claim C.6.15.7, for some w < k ≤ j the kth step of In+1 and Wk−1 (Ok , 1) = w where Ok is the local variable curr ptr of pk in the Relinquish procedure. B Therefore, by Claim C.6.15.6, the kth step of In+1 performs a FreeCell(M(w)) operation. Since ℓ B is either 30, 46, or 94, pn+1 performs the n + 1 step of In+1 in the context of an invocation I of either a DoAddCell, DoRemoveCell, or Acquire procedure. Let v ′ be the value pn+1 read from L on its last execution of line 14 before invoking I; say at time T 14 . There are two cases.

228

Case 4.2.1. v ′ is the initial value of L, i.e., v ′ = ((0, Noop), Null). Hence, pn+1 does not find the condition on line 15, line 17, or line 19 to be true on its next execution of these lines after T 14 , and so I is not an invocation of either DoAddCell or DoRemoveCell, or the Acquire procedure on line 75. Thus, I must be an invocation of the Acquire procedure on line 80, and so ℓ = 94. Since pn+1 read v ′ from L on its last execution of line 14 before invoking I, we have that the first parameter of I is (0, Noop). Furthermore, by Definition C.6.7 M(w′ ) ∈ C, so by Assumption C.1.2, M(w′ ) ̸= &H and M(w′ ) ̸= Null. Hence, since pn+1 initializes curr ptr to &H on line 93 during I and finds that curr ptr = M(w′ ) on line 94 during I, we have that pn+1 set curr ptr = M(w′ ) on line 100 during I. Thus, pn+1 received response (Found, M(w′ )) from an invocation I ′ of the AcquireNext procedure during I. Let prev ptr be the second parameter of I ′ , so by Corollary C.1.89, prev ptr ∈ C ∪ {&H}. Since the first parameter of I is (0, Noop) and pn+1 invoked I ′ during I, we have that the first parameter of I ′ is (0, Noop). Hence, the parameters of I ′ are exactly ((0, Noop), prev ptr). Since the response of I ′ is (Found, M(w′ )), we have that (a) pn+1 read (∗prev ptr).next = (∗, ∗, ∗, M(w′ )) on line 104; say at time T 104 and (b) pn+1 found that L.ullo = (0, Noop) on its next execution of line 105 during I ′ ; say at time T 105 . Hence, since prev ptr ∈ C ∪ {&H}, (∗prev ptr).next is initially (∗, ∗, ∗, Null), and so since M(w′ ) ̸= Null and (∗prev ptr).next = (∗, ∗, ∗, M(w′ )) at T 104 , we have that (∗prev ptr).next was set to (∗, ∗, ∗, M(w′ )) before T 104 . Thus, by Observation C.1.6, there is either a successful listadd or list-remove attempt before T 104 , and so by Corollary C.1.37, there is a successful L-event before T 104 . Therefore, since T 104 < T 105 , we have that is an L-event before T 105 . However, since L.ullo = (0, Noop) at T 105 and by Corollary C.1.27 every L-event sets L.ullo ̸= (0, Noop), we have that there are no L-events before T 105 , a contradiction, so Case 4.2.1 is impossible. Case 4.2.2. v ′ is not the initial value of L, i.e., v ′ ̸= ((0, Noop), Null). Hence, L was set to v ′ before T 14 , and so by Definition C.1.5, some L-event e < T 14 set L = v ′ . B . Claim: There are no A-events for M(w′ ) before e in In+1 ′ B We first prove that every A-event for M(w ) is after the w′ th step of In+1 (*) . Suppose, for ′ ′ ′ B . Let p be contradiction, there is an A-event e for M(w ) before or at the w th step of In+1 ′ ′ the process that executed e . Hence, by Definition C.1.5, p executed e during an invocation of the DoLowLevelOp procedure with a second parameter of M(w′ ). Thus, before invoking this procedure, and thus before executing e′ , p performed an AllocateCell operation whose response is B M(w′ ). Therefore, since the w′ th step of In+1 performs an AllocateCell operation whose response ′ B whose response is M(w′ ). is M(w ), we have that there are two AllocateCell operations in In+1 However, by Algorithm 4, the response of every AllocateCell is unique, a contradiction. The rest of the proof of Claim is done in two cases. Case A. ℓ is either 30, 46, or 94 during an invocation of the Acquire procedure invoked on line 75. Hence, since v ′ is the value pn+1 read from L on line 14 at T 14 and ptr is assigned to M(w) in Cn , B it follows that v ′ = (∗, M(w)), and so by Definition C.1.5, e is an L-event for M(w). Since In+1 B is an implementation history of B, by Lemma C.2.30, P (In+1 ) holds. Hence, since M(w) ∈ C, by B ), there are at-most three L-events for M(w) in I B . P (In+1 n+1 B . Recall that the We now prove that there are three L-events for M(w) before the kth step of In+1 B kth step of In+1 performs a FreeCell(M(w)) operation. Hence, by Corollary C.1.127, there is an LB . Thus, by Lemma C.1.39 and Corollary C.1.40, remove event for M(w) before the kth step of In+1 B . there is an L-apply event for M(w) and an L-add event for M(w) before the kth step of In+1 B We now return to the proof of Case A. Since e is an L-event for M(w) in In+1 , there are three B , and there are at-most three L-events for M(w) in L-events for M(w) before the kth step of In+1 B B . Hence, since k < w ′ , we have that e is before In+1 , we have that e is before the kth step of In+1 B . Therefore, since by (*) every A-event for M(w ′ ) is after the w ′ th step of the w′ th step of In+1

229

B , we have that there are no A-events for M(w ′ ) before e in I B In+1 n+1 as wanted Case B. ℓ is 94 during an invocation of the Acquire procedure invoked on line 80. B We first prove that every A-event for M(w) is before the kth step of In+1 (**). Suppose, for B contradiction, there is an A-event for M(w) after the kth step of In+1 ; say during the ith step B . Let p be the process that performed this A-event, suppose p did so during an operation of In+1 B execution opx, and let IiB be the prefix of In+1 up to and including the ith step, so opx was invoked B B , by Definition C.1.5, it in Ii . Since p performed an A-event for M(w) during the ith step of In+1 ′ did so during some invocation I of the DoLowLevelOp procedure whose second parameter is M(w). Hence, p performed an AllocateCell operation whose response is M(w) during opx. Furthermore, p did not execute line 7 during opx in IiB . Thus, by Lemma C.5.15, R(IiB , opx, M(w)) ≥ 0. To reach B the contradiction, recall that the kth step of In+1 performs a FreeCell(M(w)) operation. Hence, since k < i, we have that the kth step is included in IiB , and so there is a FreeCell(M(w)) operation during IiB . Thus, since p performed an AllocateCell operation whose response is M(w) during opx, by Lemma C.5.49, R(IiB , opx, M(w)) = −1. However, R(IiB , opx, M(w)) ≥ 0, a contradiction. We now finish the proof of Case B. Since ℓ is 94 during an invocation of the Acquire procedure invoked on line 80, and ptr is assigned to M(w) in Cn , we have that pn+1 read M(w) from A.ptr B ; say at time T 22 . Thus, T 14 < T 22 , on its last execution of line 22 before the n + 1th step of In+1 and since e < T 14 , by transitivity, e < T 22 . Suppose, for contradiction, that there is an A-event B . Hence, since e′ < e and e < T 22 , by transitivity, e′ < T 22 . Since e′ for M(w′ ) before e in In+1 w ̸= w′ , and by Definition C.6.7 M is injective, we have that M(w) ̸= M(w′ ). Furthermore, since e′ is an A-event for M(w′ ), by Definition C.1.5, A.ptr = M(w′ ) at e′ . Hence, since pn+1 read M(w) from A.ptr at T 22 , M(w) ̸= M(w′ ), and e′ < T 22 , we have that A.ptr was set to M(w) after e′ . Thus, by Observation C.1.6, there is an A-event e∗ for M(w) after e′ . Therefore, since B , and e′ is an A-event for M(w ′ ), by by (*) every A-event for M(w′ ) is after the w′ th step of In+1 transitivity, w′ < e′ , and so since e′ < e∗ , by transitivity, w′ < e∗ . However, since by (**) every B , we have that e∗ < k, and so since k ≤ j and A-event for M(w) is before the kth step of In+1 ′ ∗ ′ j < w , by transitivity, we have that e < w , a contradiction. This completes the proof of Claim. We now complete the proof of Case 4.2.2. The plan is to show that there is an A-event for M(w′ ) B , contradicting Claim. Since p ′ before e in In+1 n+1 read v from L on its last execution of line 14 before invoking I, we have that the first parameter of I is ulloL where v ′ = (ulloL , ∗). Furthermore, by Definition C.6.7 M(w′ ) ∈ C, so by Assumption C.1.2, M(w′ ) ̸= &H and M(w′ ) ̸= Null. Hence, since pn+1 initializes curr ptr to &H on line 29, 45, or 93 depending on ℓ during I and finds that curr ptr = M(w′ ) on line 30, line 46, or line 94 depending on ℓ during I, we have that pn+1 set curr ptr = M(w′ ) on either line 40, line 52, or line 100 depending on ℓ during I. Thus, pn+1 received response (Found, M(w′ )) from an invocation I ′ of the AcquireNext procedure during I. Let prev ptr be the second parameter of I ′ , so by Corollary C.1.89, prev ptr ∈ C ∪ {&H}. Since the first parameter of I is ulloL and pn+1 invoked I ′ during I, we have that the first parameter of I ′ is ulloL . Hence, the parameters of I ′ are exactly (ulloL , prev ptr). Since the response of I ′ is (Found, M(w′ )), we have that (a) pn+1 read (∗prev ptr).next = (∗, ∗, ∗, M(w′ )) on line 104 during I ′ ; say at time T 104 and (b) pn+1 found that L.ullo = ulloL on its next execution of line 105 during I ′ ; say at time T 105 . Hence, since prev ptr ∈ C ∪ {&H}, (∗prev ptr).next is initially (∗, ∗, ∗, Null), and so since M(w′ ) ̸= Null and (∗prev ptr).next = (∗, ∗, ∗, M(w′ )) at T 104 , we have that (∗prev ptr).next was set to (∗, ∗, ∗, M(w′ )) before T 104 . Thus, by Observation C.1.6, there is either a successful list-add attempt for M(w′ ) or a successful list-remove attempt between prev ptr and M(w′ ) before T 104 . Let a denote this successful list attempt, so a < T 104 . If a is a successful list-add attempt for M(w′ ), by Corollary C.1.37, there is an L-event for M(w′ ) before a. B Furthermore, if a is a successful list-remove attempt between prev ptr and M(w′ ), then since In+1 B ′ is an implementation history of B, by Lemma C.2.30, Q(In+1 ) holds, and so v ∈ List(I ) where I ′

230

B is a prefix of In+1 before a. Hence, since M(w′ ) ̸= Null and M(w′ ) ̸= &H, by Definition C.1.7, there is an L-event for M(w′ ) in I ′ . Therefore, in all cases, there is an L-event for M(w′ ) before a in B . Since v ′ = (ullo , ∗) and e set L = v ′ , we have that e set L.ullo = ullo . Furthermore, since In+1 L L B B ) holds. Hence, since e < T 105 In+1 is an implementation history of B, by Lemma C.2.30, P (In+1 and L.ullo = ulloL at T 105 , by Lemma C.1.32, we have that e is the last L-event before T 105 in B . Thus, since there is an L-event for M(w ′ ) before a in I B , a < T 104 , and T 104 < T 105 , we In+1 n+1 B . Therefore, by Corollary C.1.24, have that there is an L-event for M(w′ ) before or at e in In+1 B . However, by Claim, there are no A-events for there is an A-event for M(w′ ) before e in In+1 ′ B M(w ) before e in In+1 , a contradiction, so Case 4.2.2 is impossible. Claim C.6.15.14 A Claim C.6.15.15. If pn+1 executes line 59 during the n + 1th step of In+1 and finds the condition B on line 59 to be true, then pn+1 executes line 59 during the n + 1th step of In+1 and finds the condition on line 59 to be true.

Proof. Since by Lemma C.6.9 the program counter of pn+1 is the same in CnA and Cn , and pn+1 B , we have that p B takes the n + 1th step of In+1 n+1 executes line 59 during the n + 1th step of In+1 . A , then so does p First observe that, if pn+1 finds the first clause of line 59 to be true in In+1 n+1 in B In+1 . This is because L.ullo is not watermarked, and so by Definition C.6.8, the value of L.ullo is the same in CnA and Cn . Hence, it suffices to consider the case where pn+1 finds the first clause A , i.e., p ′ A to be false and the second clause to be true in In+1 n+1 finds next ptr = next ptr in Cn . Thus, since the value of L.ullo is the same in CnA and Cn , we have that pn+1 finds the first clause B , and we must prove that the second clause is true. to be false in In+1

We start with a few basic facts. Since next ptr′ and next ptr are a single value, by Definition C.6.7, Sn (next ptr′ ) = Sn (next ptr′ , 1) and Sn (next ptr) = Sn (next ptr, 1). Furthermore, since pn+1 B , it did so during an invocation I of the DoRemoveCell execute line 59 during the n+1th step of In+1 procedure with parameters (ulloL , ptrL ). Hence, by Corollary C.1.37, there is an L-remove event e for ptrL before pn+1 invoked I that set L = (ulloL , ptrL ). Thus, by Lemma C.1.28 ptrL ∈ C, and so by Assumption C.1.2, ptrL ̸= &H. So, since ptrL is the second parameter of I, and the local variable curr ptr is initially &H (see line 45), we have that pn+1 finds the condition on line 46 to true on its first execution of line 46 during I. Furthermore, since pn+1 executes line 59 during I, we have that pn+1 finds the condition on line 46 to be false during I. These facts together imply pn+1 executes line 52 at least once during I; let T be the first time pn+1 does so. Hence, by Lemmas C.1.50 and C.1.51, from T onwards in I curr ptr ∈ C ∪ {&H} and prev ptr ∈ C ∪ {&H}. There are four cases. Case 1. Wn (next ptr, 1) = ⊥ and Wn (next ptr′ , 1) = ⊥. Hence, by Definition C.6.7, Sn (next ptr, 1) (resp. Sn (next ptr′ , 1)) is the same as the first value of next ptr (resp. next ptr′ ) in CnA . Thus, since Sn (next ptr) = Sn (next ptr, 1) (resp. Sn (next ptr′ ) = Sn (next ptr′ , 1)), we have that Sn (next ptr) (resp. Sn (next ptr′ )) is the same as the value of next ptr (resp. next ptr′ ) in CnA . So, by Definition C.6.8, the value of next ptr (resp. next ptr′ ) is the same in CnA and Cn . Therefore, since next ptr = next ptr′ in CnA , we have that next ptr = B . next ptr′ in Cn , and so pn+1 finds the condition on line 59 to be true during the n + 1th step of In+1 Case 2. Wn (next ptr, 1) ̸= ⊥ and Wn (next ptr′ , 1) = ⊥. Hence, since Sn (next ptr) = Sn (next ptr, 1), by Definition C.6.4, the value of next ptr in CnA is in C. Thus, since next ptr = next ptr′ in CnA , we have that the value of next ptr′ in CnA is in C; A ). Furthermore, since S (next ptr ′ ) = S (next ptr ′ , 1) say v. So, by Definition C.6.5, v ∈ C(In+1 n n and Wn (next ptr′ , 1) = ⊥, by Definition C.6.8, the value of next ptr′ is v in Cn . We now show 231

B that there is an AllocateCell operation in In+1 whose response is v. Since Cn assigns state v to ′ next ptr , we have that pn+1 saw (∗prev ptr).next = (∗, ∗, ∗, v) on its last execution of line 58 B B ) holds, during I. Hence, since In+1 is an implementation history of B, by Lemma C.2.30 Q(In+1 and so since prev ptr ∈ C ∪ {&H} and v ∈ C, by Lemma C.1.128, there is an L-event e for v in B . Thus, by Corollary C.1.24, there is an A-event e′ for v before e. So, by Definition C.1.5, In+1 the process p that executed e′ did so during an invocation of the DoLowLevelOp procedure with a second parameter of v. Thus, p performed an AllocateCell operation on line 2 whose response A ), there is an AllocateCell operation in I B is v. Therefore, since v ∈ C(In+1 n+1 whose response is in A B C(In+1 ). However, by Claim C.6.15.5, the response of every AllocateCell operation in In+1 is not A in C(In+1 ), a contradiction, so Case 2 is impossible.

Case 3. Wn (next ptr, 1) = ⊥ and Wn (next ptr′ , 1) ̸= ⊥. The proof is essentially the same as Case 2. Since Wn (next ptr′ , 1) ̸= ⊥, and Sn (next ptr′ ) = Sn (next ptr′ , 1), the value of next ptr′ in CnA is in C. Thus, since next ptr = next ptr′ in CnA , A ). we have that the value of next ptr in CnA is in C; say v. So, by Definition C.6.5, v ∈ C(In+1 Furthermore, since Sn (next ptr) = Sn (next ptr, 1) and Wn (next ptr, 1) = ⊥, by Definition C.6.8, B the value of next ptr is v in Cn . We now show that there is an AllocateCell operation in In+1 whose response is v. Since Cn assigns state v to next ptr, we have that pn+1 saw (∗ptrL ).next = (∗, ∗, ∗, v) B is an implementation history of B, by on its last execution of line 56 during I. Hence, since In+1 B Lemma C.2.30 Q(In+1 ) holds, and so since ptrL ∈ C and v ∈ C, by Lemma C.1.128, there is an B . Thus, by Corollary C.1.24, there is an A-event e′ for v before e. So, by L-event e for v in In+1 Definition C.1.5, the process p that executed e′ did so during an invocation of the DoLowLevelOp procedure with a second parameter of v. Thus, p performed an AllocateCell operation on line 2 A ), there is an AllocateCell operation in I B whose response is v. Therefore, since v ∈ C(In+1 n+1 whose A response is in C(In+1 ). However, by Claim C.6.15.5, the response of every AllocateCell operation B A ), a contradiction, so Case 3 is impossible. in In+1 is not in C(In+1 Case 4. Wn (next ptr, 1) ̸= ⊥ and Wn (next ptr′ , 1) ̸= ⊥. Let Wn (next ptr, 1) = w and Wn (next ptr′ , 1) = w′ . Hence, by Definition C.6.7, Sn (next ptr, 1) = M(w) and Sn (next ptr′ , 1) = M(w′ ). Therefore, since by above Sn (next ptr) = Sn (next ptr, 1) and Sn (next ptr′ ) = Sn (next ptr′ , 1), we have that Sn (next ptr) = M(w) and Sn (next ptr′ ) = M(w′ ). So, by Definition C.6.8, next ptr (resp. next ptr′ ) is assigned to M(w) (resp. M(w′ )) in B , we Cn . Hence, since pn+1 checks whether next ptr = next ptr′ during the n + 1th step of In+1 ′ B have that pn+1 checks whether M(w) = M(w ) during the n + 1th step of In+1 . Case 4.1. w = w′ . Hence, M(w) = M(w′ ). Therefore, since pn+1 checks whether M(w) = M(w′ ) during the n + 1th B , p B step of In+1 n+1 finds the condition on line 59 to be true during the n + 1th step of In+1 . Case 4.2. w ̸= w′ . Hence, since M is injective, we have that M(w) ̸= M(w′ ). Thus, pn+1 finds the second clause of B . Therefore, since p line 59 to be false during the n + 1th step of In+1 n+1 finds the first clause of B line 59 to be false during the n+1th step of In+1 , we have that pn+1 finds the condition on line 59 to B , and so p be false during the n+1th step of In+1 n+1 is poised to execute line 61 during its next step. B B Let In+2 be the one step of continuation of In+1 by pn+1 , so pn+1 executes line 61 during the last B B B step of In+2 . Since In+1 is an implementation history of B, we have that In+2 is an implementation history of B. Furthermore, since M(w) is the value of next ptr in Cn , it follows that pn+1 executes B line 61 during the last step of In+2 of the form CAS((∗prev ptr).next, (∗, ∗, ∗, ptrL ), (∗, ∗, ∗, M(w))). B Thus, by Definition C.1.5, the last step of In+2 is a list-remove attempt for ptrL between prev ptr B and M(w). Let a denote this list-remove attempt. Since In+2 is an implementation history of B, B B B B ), a is preceded by a by Lemma C.2.30, P (In+2 ), Q(In+2 ), and R(In+2 ) hold. Hence, by Q(In+2 232

B unique L-remove event for ptrL , and if I ′ is the prefix of In+2 up to but excluding that L-remove ′ event, ptrL is in List(I ) exactly once and prev ptr and M(w) are the pointers preceding and B succeeding ptrL in List(I ′ ). Therefore, since e is an L-remove event for ptrL in In+1 (as defined ′ B at the start of the proof), it follows that I is the prefix of In+2 up to but excluding e. B We now prove that there are no L-events after e in In+2 (*). Since pn+1 finds the first clause of B line 59 to be false during the n + 1th step of In+2 , and the first parameter of I is ulloL , we have B . Hence, since e is an L-event that set L.ullo = ullo during I B that L.ullo = ulloL in Cn+1 L n+2 and B B . P (In+2 ) holds, by Lemma C.1.32, there are no L-events after e in In+2 B We now prove that ptrL = M(w′ ) (**). Let I 58 be the prefix of In+2 up to and including pn+1 ’s B ′ ′ last execution of line 58 in In+2 . Since next ptr is assigned to M(w ) in Cn , and pn+1 executes B , we have that (∗prev ptr).next = line 59 and line 61 during the n + 1th and n + 2th step of In+2 (∗, ∗, ∗, M(w′ )) at the end of I 58 . Furthermore, notice that e is in I 58 . Hence, since by (*) B , we have that e is the last L-event in I 58 . Thus, since there are no L-events after e in In+2 B B B P (In+2 ), Q(In+2 ), and R(In+2 ) hold, by Lemma C.2.6, the list of cells conforms to either List(I ′ ) or List(I 58 ) in I 58 . In the first case, since ptrL is in List(I ′ ) exactly once and prev ptr is the pointer preceding ptrL in List(I ′ ), by Definition C.1.7, (∗prev ptr).next = (∗, ∗, ∗, ptrL ) at the end of I 58 . Hence, since (∗prev ptr).next = (∗, ∗, ∗, M(w′ )) at the end of I 58 , we have that ptrL = M(w′ ) as wanted. In the second case, since (a) the sequence of L-events in List(I ′ ) and List(I 58 ) are the same with the exception that e is not in List(I ′ ) and e is in List(I 58 ), (b) e is an L-remove event for ptrL , and (c) ptrL is in List(I ′ ) exactly once and prev ptr and M(w) are the pointers preceding and following ptrL in List(I ′ ), by Definition C.1.7, we have that prev ptr is preceding M(w) in List(I 58 ). Hence, since the list of cells conforms to List(I 58 ) in I 58 , by Definition C.1.7, (∗prev ptr).next = (∗, ∗, ∗, M(w)) at the end of I 58 . Therefore, since (∗prev ptr).next = (∗, ∗, ∗, M(w′ )) at the end of I 58 , we have that M(w) = M(w′ ). However, M(w) ̸= M(w′ ), a contradiction, so the second case is impossible. We now return the proof of Case 4.2. Since e is an L-remove event for ptrL , and by (**) ptrL = M(w′ ), we have that e is an L-remove event for M(w′ ). Furthermore, since Wn (next ptr, 1) = A w ̸= ⊥ (resp. Wn (next ptr′ , 1) = w′ ̸= ⊥), by Lemma C.6.12, the wth (resp. w′ th) step of In+1 ′ performs an AllocateCell operation whose response is the value of next ptr (resp. next ptr ) in CnA . Hence, since next ptr = next ptr′ in CnA , we have that this is the same value, say v, and so the A wth and w′ th step of In+1 perform an AllocateCell operation whose response is v. Furthermore, B by Claim C.6.15.4, the wth (resp. w′ th) step of In+1 performs an AllocateCell operation whose ′ response is M(w) (resp. M(w )). There are two cases.

Case 4.2.1. w < w′ . A Hence, since the wth and w′ th step of In+1 perform an AllocateCell operation whose response is A v, by Algorithm 3, v ∈ C and for some w < j < w′ the jth step of In+1 performs a FreeCell(v) A performs a FreeCell(v), operation. Thus, by Claim C.6.15.7, for some w < k ≤ j the kth step of In+1 and Wk−1 (Ok , 1) = w where Ok is the local variable curr ptr of pk in the Relinquish procedure. B Therefore, by Claim C.6.15.6, the kth step of In+1 performs a FreeCell(M(w)) operation, so by B . Corollary C.1.127, there is an L-remove event for M(w) before the kth step of In+1 ′ ′ We now prove that w < e. Since e is an L-event for M(w ), by Corollary C.1.24, there is an AB . Hence, by Definition C.1.5, some process executed this A-event event for M(w′ ) before e in In+2 during some invocation of the DoLowLevelOp with a second parameter M(w′ ), and so it performed B an AllocateCell operation with response M(w′ ) before e. Therefore, since the w′ th step of In+2 ′ performs an AllocateCell operation with response M(w ), and by Algorithm 4 the response of each AllocateCell operation is unique, we have that w′ < e. We now finish the proof of Case 4.2.1. Since M(w) ∈ C and M(w) ∈ List(I ′ ), by Definition C.1.7,

233

B there are no L-remove events for M(w) in I ′ . Therefore, since I ′ is the prefix of In+2 up to but B excluding e, we have that there are no L-remove events for M(w) before e in In+2 . However, as B , and so since k ≤ j, proved above, there is an L-remove event for M(w) before the kth step of In+1 ′ ′ j < w , and as proved above w < e, by transitivity, we have that there is an L-remove event for B , a contradiction, so Case 4.2.1 is impossible. M(w) before e in In+2 Case 4.2.2. w′ < w. A Hence, since the w′ th and wth step of In+1 perform an AllocateCell operation whose response is A v, by Algorithm 3, v ∈ C and for some w′ < j < w the jth step of In+1 performs a FreeCell(v) ′ A operation. Thus, by Claim C.6.15.7, for some w < k ≤ j the kth step of In+1 performs a ′ FreeCell(v), and Wk−1 (Ok , 1) = w where Ok is the local variable curr ptr of pk in the Relinquish B procedure. So, by Claim C.6.15.6, the kth step of In+1 performs a FreeCell(M(w′ )) operation, B . and thus by Corollary C.1.127, there is an L-remove event for M(w′ ) before the kth step of In+1 ′ B Therefore, since e is an L-remove event for M(w ), by P (In+2 ), e is the only L-remove event for B , and so e < k. M(w′ ) in In+2 B . Since next ptr is assigned to M(w) in We now prove that there is an L-event for M(w) in In+2 B , we have Cn , and pn+1 executes line 59 and line 61 during the n + 1th and n + 2th step of In+2 B . that pn+1 read (∗, ∗, ∗, M(w)) from ptrL at the time of pn+1 ’s last execution of line 56 during In+2 B B Hence, since In+2 is an implementation history of B, by Lemma C.2.30 Q(In+2 ) holds, and so since B . ptrL ∈ C and M(w) ∈ C, by Lemma C.1.128, there is an L-event for M(w) in In+2 ′ We now finish the proof of Case 4.2.2. Let e be the L-event for M(w) we just identified. Since e′ is B . Hence, by an L-event for M(w), by Corollary C.1.24, there is an A-event for M(w) before e′ in In+2 Definition C.1.5, some process executed this A-event during some invocation of the DoLowLevelOp with a second parameter M(w), and so it performed an AllocateCell operation with response M(w) B performs an AllocateCell operation with response M(w), before e′ . Thus, since the wth step of In+2 and by Algorithm 4 the response of each AllocateCell operation is unique, we have that w < e′ . B B , we have that e′ ≤ e. Since by (*) e is the last L-event in In+2 and e′ is an L-event in In+2 Therefore, since w < e′ and as proved above e < k, by transitivity, w < k. However, since k ≤ j and j < w, by transitivity, k < w, a contradiction, so Case 4.2.2 is impossible. Claim C.6.15.15 A . Then, C B Claim C.6.15.16. Let pr be a program counter in Cn+1 n+1 assigns Sn+1 (pr) to pr. A Proof. Suppose pr is the program counter for process p. Let sA n (resp. sn+1 ) be the state assigned A A B ). to pr in Cn (resp. Cn+1 ) and let sn (resp. sn+1 ) be the state assigned to pr in Cn (resp. Cn+1 We prove that sA n+1 = sn+1 . There are two cases. A Case 1. sA n = sn+1 . A , and so p ̸= p Hence, p did not take the n + 1th step of In+1 n+1 . Thus, since pn+1 takes the n + 1th B B , and so s = s step of In+1 , we have that p also does not take the n + 1th step of In+1 n n+1 . Since A by Lemma C.6.9, the program counter of p is the same in Cn and Cn , we have that sA n = sn . A A Therefore, since sA = s and s = s , we have that s = s . n n+1 n+1 n n+1 n+1 A Case 2. sA n ̸= sn+1 . A , and so p = p Hence, p takes the n + 1th step of In+1 n+1 . Thus, since pn+1 takes the n + 1th step B B , and so s ̸= s of In+1 , we have that p also takes the n + 1th step of In+1 n n+1 . Suppose p executes A the line of code ℓ during the n + 1th step of In+1 . Since by Lemma C.6.9, the program counter of p is the same in CnA and Cn , we have that p executes the line of code ℓ during the n + 1th step of B , so sA = s . Observe that sA In+1 n n n+1 is either (a) solely determined based on ℓ (i.e., it increases by one, or deterministically jumps to a new line number because ℓ invokes a procedure, is a goto statement, or is a response step) or (b) depends on the the response p received from an operation

234

A on a base object it performed during the i + 1th step of In+1 and/or the state of p’s local variables A in Cn (i.e., ℓ is an if, while, or until statement). We consider each case separately.

Case (a). B , we have that s A Hence, since p executes the line of code ℓ during the n+1th step of In+1 n+1 = sn+1 . Case (b). Hence, ℓ is an execution of either an if, while, or until statement. We consider each line. Case (b).1. ℓ is either 83, 85, or 87. Hence, pn+1 is comparing a unique low-level operation read from A with a static value and possibly comparing the response of an invocation of the Acquire procedure with a static value. By tracing backwards, we can see that the values of these local variables do not originate from the response of an AllocateCell operation, and so by Definition C.6.4, they are not watermarked. Thus, by Definition C.6.8, their state is the same in CnA and Cn . Therefore, pn+1 finds the condition on line A ℓ to be true during the n + 1th step of In+1 if and only if pn+1 finds the condition on line ℓ to be B true during the n + 1th step of In+1 , so sn+1 = sA n+1 as wanted. Case (b).2. ℓ is either 15, 17, 19, 35, 67, 68, or 105. Hence, pn+1 compares a unique low-level operation read from L with either a static value, the current unique low-level operation in L, or a unique low-level operation read from S. Since any unique low-level operation written into S was read from L, and any unique low-level operation written into L was read from A, we have that any possible values pn+1 compares do not originate from the response of an AllocateCell operation, and so by Definition C.6.4, they are not watermarked. Thus, by Definition C.6.8, their state is the same in CnA and Cn . Therefore, pn+1 finds the condition on A line ℓ to be true during the n + 1th step of In+1 if and only if pn+1 finds the condition on line ℓ to B be true during the n + 1th step of In+1 , so sn+1 = sA n+1 as wanted. Case (b).3. ℓ is either 13 or 88. Hence, by Claim C.6.15.2, pn+1 reads the current value of the response object O of some cell and compares it to a unique low-level operation and Null. Thus, by Claim C.6.15.12, pn+1 reads Sn (O) B . Since O ̸= (∗ptr).next for any ptr ∈ C ∪ {&H}, and by tracing backward, we can see in In+1 that any possible value pn+1 compares the state of O to do not originate from the response of an AllocateCell operation, by Definition C.6.4, they are not watermarked. Hence, by Definition C.6.7, Sn (O) is the state assigned to O in CnA , and by Definition C.6.8, the relevant local variables of pn+1 are the same in CnA and Cn . Therefore, pn+1 finds the condition on line ℓ to be true during the A n + 1th step of In+1 if and only if pn+1 finds the condition on line ℓ to be true during the n + 1th B step of In+1 , so sn+1 = sA n+1 as wanted. Case (b).4. ℓ is either 24, 26, 32, 33, 38, 48, 50, 76, 81, 90, 97, or 99. Hence, pn+1 compares the response of an invocation of the Acquire procedure with a static value. Since these values do not originate from the response of an AllocateCell operation, by Definition C.6.4, they are not watermarked. Thus, by Definition C.6.8, their state is the same in CnA and A Cn . Therefore, pn+1 finds the condition on line ℓ to be true during the n + 1th step of In+1 if and B only if pn+1 finds the condition on line ℓ to be true during the n + 1th step of In+1 , so sn+1 = sA n+1 as wanted. Case (b).5. ℓ is 53. Hence, by Claim C.6.15.2, pn+1 compares the response of O = (∗ptr).next.sealed to False for B . Since some ptr ∈ C ∪ {&H}. Thus, by Claim C.6.15.12, pn+1 receives response Sn (O, 3) in In+1 the sealed field of (∗ptr).next is initially False and is only set to True, by Definition C.6.4, it is not watermarked, so Sn (O, 3) is the same as the value of (∗ptr).next.sealed in CnA . Therefore, A pn+1 finds the condition on line ℓ to be true during the n + 1th step of In+1 if and only if pn+1 B , so s A finds the condition on line ℓ to be true during the n + 1th step of In+1 n+1 = sn+1 as wanted. 235

Case (b).6. ℓ is either 61 or 109. Hence, by Claim C.6.15.2, pn+1 compares the response of a CAS operation to True. Since by B , we have that Claim C.6.15.12, pn+1 receives the same response during the n + 1th step of In+1 A pn+1 finds the condition on line ℓ to be true during the n + 1th step of In+1 if and only if pn+1 B , so s A finds the condition on line ℓ to be true during the n + 1th step of In+1 n+1 = sn+1 as wanted. Case (b).7. ℓ is 114. Hence, by Claim C.6.15.2, pn+1 compares the response of a F&A operation to -1. Since by B , we have that Claim C.6.15.12, pn+1 receives the same response during the n + 1th step of In+1 A pn+1 finds the condition on line ℓ to be true during the n + 1th step of In+1 if and only if pn+1 B finds the condition on line ℓ to be true during the n + 1th step of In+1 , so sn+1 = sA n+1 as wanted. Case (b).8. ℓ is either 107 or 112. Hence, pn+1 compares a pointer with Null or &H. Let pr be this local variable and suppose CnA assigns state v to pr. If pn+1 finds this comparison to be true, then v is either Null or &H. Hence, by Definition C.6.4, Wn (pr, 1) = ⊥, and so by Definition C.6.7, Sn (pr) = v. Thus, by Definition C.6.8, Cn assigns state v to pr, and so the state of pr is the same in CnA and Cn . B . On the Therefore, pn+1 finds the condition on line ℓ to be true during the n + 1th step of In+1 other hand, if pn+1 finds the comparison on line ℓ to be false, then v is not Null nor &H. Note that by Definition C.6.7 Sn (pr) is either v or M(w) for some w. If Sn (pr) = v, then by Definition C.6.8, Cn assigns state v to pr, and so the state of pr is the same in CnA and Cn . Hence, since v is not Null nor &H, it follows that pn+1 finds the condition on line ℓ to be false during the n + 1th B . If S (pr) = M(w), then by Definition C.6.8, C assigns state M(w) to pr. Hence, step of In+1 n n since M(w) ∈ C, by Assumption C.1.2, M(w) ̸= &H and M(w) ̸= Null. Thus, pn+1 finds the B . Therefore p condition on line ℓ to be false during the n + 1th step of In+1 n+1 finds the condition A on line ℓ to be true during the n + 1th step of In+1 if and only if pn+1 finds the condition on line ℓ A B , so s to be true during the n + 1th step of In+1 n+1 = sn+1 as wanted. Case (b).9. ℓ is either 30, 46, or 94. Claim C.6.15.14 covers the case where pn+1 finds the condition on ℓ to be false during the n + 1th A . So, suppose p A step of In+1 n+1 finds the condition on ℓ to be true during the n + 1th step of In+1 . In this case, ℓ compares the value of two local variables, say pr1 and pr2 . Observe that, in all cases, the state of pr1 and pr2 is a single value, so by Definition C.6.7, Sn (pr1 ) = Sn (pr1 , 1) and Sn (pr2 ) = Sn (pr2 , 1). Let v1 (resp. v2 ) be the state of pr1 (resp. pr2 ) in CnA . Hence, since pn+1 finds A , we have that v ̸= v . Furthermore, the condition on ℓ to be true during the n + 1th step of In+1 1 2 A since v1 (resp. v2 ) is the state of a local variable in Cn , by Definition C.6.5, if v1 ∈ C (resp. A ) (resp. v ∈ C(I A )). Hence, by Lemma C.6.13, S (pr , 1) ̸= S (pr , 1). v2 ∈ C), then v1 ∈ C(In+1 2 n 1 n 2 n+1 Thus, since Sn (pr1 ) = Sn (pr1 , 1) and Sn (pr2 ) = Sn (pr2 , 1), we have that Sn (pr1 ) ̸= Sn (pr2 ). So, by Definition C.6.8, the state of pr1 and pr2 differ in Cn , implying pn+1 finds the condition on ℓ B . Therefore p to be true during the n + 1th step of In+1 n+1 finds the condition on line ℓ to be true A during the n + 1th step of In+1 if and only if pn+1 finds the condition on line ℓ to be true during B , so s A the n + 1th step of In+1 n+1 = sn+1 as wanted. Case (b).10. ℓ is 59. Claim C.6.15.15 covers the case where pn+1 finds the condition on ℓ to be true during the n + 1th A . So, suppose p A step of In+1 n+1 finds the condition on ℓ to be false during the n+1th step of In+1 . In this case, ℓ compares a unique low-level operation read from L with the unique low-level operation currently in L and the value of two local variables, say pr1 and pr2 . The former is covered by Case (b).3, so it suffices to consider the case where pn+1 finds the condition on ℓ to be false during the A , because the values of pr and pr differ in C A . The argument is the same as n + 1th step of In+1 1 2 n the previous case, which is provided below for completeness. Observe that, in all cases, the state of 236

pr1 and pr2 is a single value, so by Definition C.6.7, Sn (pr1 ) = Sn (pr1 , 1) and Sn (pr2 ) = Sn (pr2 , 1). Let v1 (resp. v2 ) be the state of pr1 (resp. pr2 ) in CnA . Hence, v1 ̸= v2 . Furthermore, since v1 (resp. v2 ) is the state of a local variable in CnA , by Definition C.6.5, if v1 ∈ C (resp. v2 ∈ C), A ) (resp. v ∈ C(I A )). Hence, by Lemma C.6.13, S (pr , 1) ̸= S (pr , 1). Thus, then v1 ∈ C(In+1 2 n 1 n 2 n+1 since Sn (pr1 ) = Sn (pr1 , 1) and Sn (pr2 ) = Sn (pr2 , 1), we have that Sn (pr1 ) ̸= Sn (pr2 ). So, by Definition C.6.8, the state of pr1 and pr2 differ in Cn , implying pn+1 finds the condition on ℓ to B . Therefore p be false during the n + 1th step of In+1 n+1 finds the condition on line ℓ to be true A during the n + 1th step of In+1 if and only if pn+1 finds the condition on line ℓ to be true during B , so s A the n + 1th step of In+1 n+1 = sn+1 as wanted. We now finish the proof of Claim C.6.15.16. Since pr is a program counter, by Definition C.6.4, A Wn+1 (pr, 1) = ⊥. Hence, since sA n+1 is the state assigned to pr in Cn+1 , by Definition C.6.7, A Sn+1 (pr) = Sn+1 (pr, 1) = sA n+1 . Thus, since sn+1 = sn+1 , we have that sn+1 = Sn+1 (pr). Therefore, B B since Cn+1 assigns state sn+1 to pr, we have that Cn+1 assigns state Sn+1 (pr) to pr. Claim C.6.15.16 B We now finish the inductive case of Lemma C.6.15. Recall we must prove that Cn+1 = Cn+1 . B Since by Claim C.6.15.13 and Claim C.6.15.16, Cn+1 assigns Sn+1 (pr) to pr where pr is any local B and Cn+1 assign every local variable to the same variable. Therefore, by Definition C.6.8, Cn+1 B state. What remains is to prove that Cn+1 and Cn+1 assign every base object to the same state. There are three cases. A Case 1. The n + 1th step of In+1 does not perform an operation on a base object. A , and p Hence, the state of every base object is the same in CnA and Cn+1 n+1 does not set any index of A any base object O during the n + 1th step of In+1 , so by Definition C.6.4, Wn+1 (O, i) = Wn (O, i). A , by Definition C.6.7, S Therefore, since the state of O is the same in CnA and Cn+1 n+1 (O, i) = Sn (O, i), and so Sn+1 (O) = Sn (O) for any base object O other than the memory manager (*). Claim: The state of every base object is the same in Cn and Cn+1 . Consider any base object O other than the memory manager. Case A. O ∈ / CO or O is in H. Hence, by Definition C.6.8, Cn (resp. Cn+1 ) assigns state Sn (O) (resp. Sn+1 (O)) to O. Therefore, since by (*) Sn+1 (O) = Sn (O), we have that Cn and Cn+1 assigns the same state to O. Case B. O ∈ CO and O is not in H. Hence, by Definition C.6.1, O = (∗ptr).f for some ptr ∈ C and f which is either response, revocations, or next. Let Wn (resp. Wn+1 ) be the set of step numbers up to and including A the nth (resp. n + 1th) step of In+1 which perform AllocateCell operations. Since the n + 1th step A A of In+1 does not perform an operation on a base object, we have that the n + 1th step of In+1 does not perform an AllocateCell operation, and so Wn = Wn+1 = W . Case B.1. ptr ∈ / M[W ]. Hence, by Definition C.6.8, Cn and Cn+1 assign O to its initial state. Case B.2. ptr ∈ M[W ]. Hence, M(w) = ptr for some w ∈ W . Thus, since O = (∗ptr).f , we have that O = (∗M(w)).f . A . Let ptr′ be the response of the AllocateCell operation performed during the wth step of In+1 A Case B.2.1. For all w < j ≤ n the jth step of In+1 does not perform an AllocateCell operation ′ whose response is ptr . A Since the n + 1th step of In+1 does not perform an AllocateCell operation, we have that for all A does not perform an AllocateCell operation whose response is ptr ′ . w < j ≤ n+1 the jth step of In+1 Hence, by Definition C.6.8, Cn (resp. Cn+1 ) assigns state Sn ((∗ptr′ ).f ) (resp. Sn+1 ((∗ptr′ ).f )) to

237

(∗M(w)).f . Thus, since by Algorithm 3 ptr′ ∈ C, (∗ptr′ ).f is a base object other than the memory manager, and so by (*) Sn+1 ((∗ptr′ ).f ) = Sn ((∗ptr′ ).f ). So, Cn and Cn+1 assign the same state to (∗M(w)).f . Therefore, since O = (∗M(w)).f , Cn and Cn+1 assign the same state to O. A Case B.2.2. For some w < j ≤ n the jth step of In+1 performs an AllocateCell operation whose ′ response is ptr . A Let j be the minimum w < j ≤ n such that the jth step of In+1 performs an AllocateCell cell ′ operation whose response is ptr . Hence, j is also the minimum w < j ≤ n+1 such that the jth step A of In+1 performs an AllocateCell cell operation whose response is ptr′ . Thus, by Definition C.6.8, Cn and Cn+1 assigns state Sj−1 ((∗ptr′ ).f ) to (∗M(w)).f . Therefore, since O = (∗M(w)).f , we have that Cn and Cn+1 assign the same state to O. This completes the proof of Case B. Finally, consider the memory manager. By Definition C.6.8, Cn (resp. Cn+1 ) assigns state M[Wn ] (resp. M[Wn+1 ]) to the memory manager, and since Wn = Wn+1 , we have that M[Wn ] = M[Wn+1 ], and so Cn and Cn+1 assign the same state to the memory manager. This completes the proof of Claim. A We now finish the proof of Case 1. Since the n + 1th step of In+1 does not perform an operation on a base object, and by Lemma C.6.9 the program counter of every process is the same in CnA and B Cn , we have that the n + 1th step of In+1 does not perform an operation on a base object. Hence, B . Therefore, since by Claim the state of the state of every base object is the same in Cn and Cn+1 every base object is the same in Cn and Cn+1 , we have that the state of every base object is the B same in Cn+1 and Cn+1 as wanted. A Case 2. The n + 1th step of In+1 performs an operation on the memory manager. The main challenge to be dealt with in this case compared to the last case is that in A, AllocateCell operations set the state of each object of the cell they return to their initial state while in B AllocateCell operations do not change the state of the objects of the cell they return. Claim 1: For every base object O in A such that O is not the memory manager, and O ∈ / CO or O is in H, Sn+1 (O) = Sn (O). A Since the n + 1th step of In+1 performs an operation on the memory manager, the state of O is A A . A the same in Cn and Cn+1 , and pn+1 does not set any index of O during the n + 1th step of In+1 Thus, for any index i of the state of O, by Definition C.6.4, Wn+1 (O, i) = Wn (O, i). Therefore, A , by Definition C.6.7, S since the state of O is the same in CnA and Cn+1 n+1 (O, i) = Sn (O, i), and so Sn+1 (O) = Sn (O) as wanted. A Claim 2: If the n + 1th step of In+1 does not perform an AllocateCell operation whose response is ptr, then for every base object O of the cell pointed to by ptr Sn+1 (O) = Sn (O). A performs an Consider any base object O of the cell pointed to by ptr. Since the n + 1th step of In+1 A operation on the memory manager and the n + 1th step of In+1 does not perform an AllocateCell A , and p operation whose response is ptr, the state of O is the same in CnA and Cn+1 n+1 does not A set any index of O during the n + 1th step of In+1 . Thus, for any index i of the state of O, by Definition C.6.4, Wn+1 (O, i) = Wn (O, i). Therefore, since the state of O is the same in CnA and A , by Definition C.6.7, S Cn+1 n+1 (O, i) = Sn (O, i), and so Sn+1 (O) = Sn (O) as wanted. Claim 3: The state of every base object other than the memory manager is the same in Cn and Cn+1 . Consider any base object O other than the memory manager. Case A. O ∈ / CO or O is in H. Hence, by Definition C.6.8, Cn (resp. Cn+1 ) assigns state Sn (O) (resp. Sn+1 (O)) to O. Therefore, since by Claim 1 Sn+1 (O) = Sn (O), Cn and Cn+1 assigns the same state to O.

238

Case B. O ∈ CO and O is not in H. Hence, by Definition C.6.1, O = (∗ptr).f for some ptr ∈ C and f which is either response, revocations, or next. Let Wn (resp. Wn+1 ) be the set of step numbers up to and including A the nth (resp. n + 1th) step of In+1 which perform AllocateCell operations. Since the n + 1th step A of In+1 performs an operation on the memory manager, we have that Wn+1 = Wn ∪ {n + 1}. There are two cases. Case B.1. ptr ∈ / M[Wn ]. Hence, by Definition C.6.8, Cn assign O to its initial state. There are two more cases. Case B.1.1. ptr ∈ / M[Wn+1 ]. Hence, by Definition C.6.8, Cn+1 assign O to its initial state, which is the same as Cn . Case B.1.2. ptr ∈ M[Wn+1 ]. Hence, since ptr ∈ / M[Wn ], we have that ptr = M(w) for some w ∈ Wn+1 \ Wn . Thus, since Wn+1 = Wn ∪ {n + 1}, we have that w = n + 1, so ptr = M(n + 1). Therefore, since O = (∗ptr).f , we have that O = (∗M(n + 1)).f . Let ptr′ be the response of the AllocateCell performed during A . Hence, the set of steps satisfying n + 1 < j ≤ n + 1 is empty, so by the n + 1th step of In+1 Definition C.6.8, Cn+1 assigns state Sn+1 ((∗ptr′ ).f ) to ((∗M(n + 1)).f ). Since the n + 1th step A A of In+1 performs an AllocateCell operation with response ptr′ , by Definition C.0.1, Cn+1 assigns ′ (∗ptr ).f to its initial state. Hence, since every value of every index of the initial state of (∗ptr′ ).f is not in C, by Definition C.6.4, Wn+1 ((∗ptr′ ).f, i) = ⊥ for any index i of the state of (∗ptr′ ).f . Thus, by Definition C.6.7, Sn+1 ((∗ptr′ ).f ) is the initial state of (∗ptr′ ).f . So, since Cn+1 assigns state Sn+1 ((∗ptr′ ).f ) to ((∗M(n + 1)).f ), we have that Cn+1 assigns (∗M(n + 1)).f to its initial state. Therefore, since O = (∗M(n + 1)).f , we have that Cn+1 assign O to its initial state, which is the same as Cn as wanted. Case B.2. ptr ∈ M[Wn ]. Hence, M(w) = ptr for some w ∈ Wn , so since O = (∗ptr).f , we have that O = (∗M(w)).f . Thus, since Wn+1 = Wn ∪ {n + 1}, we have that w ∈ Wn+1 , and so ptr ∈ M[Wn+1 ]. Let ptr′ be the A . There are two cases. response of the AllocateCell operation performed during the wth step of In+1 A does not perform an AllocateCell operation Case B.2.1. For all w < j ≤ n the jth step of In+1 ′ whose response is ptr . Hence, by Definition C.6.8, Cn assigns state Sn ((∗ptr′ ).f ) to (∗M(w)).f . Thus, since O = (∗M(w)).f , we have that Cn assigns state Sn ((∗ptr′ ).f ) to O. There are two more cases. A Case B.2.1.1. For all w < j ≤ n + 1 the jth step of In+1 does not perform an AllocateCell ′ operation whose response is ptr . Hence, by Claim 2, Sn+1 ((∗ptr′ ).f ) = Sn ((∗ptr′ ).f ). Furthermore, by Definition C.6.8, Cn+1 assigns state Sn+1 ((∗ptr′ ).f ) to (∗M(w)).f . Thus, since Sn+1 ((∗ptr′ ).f ) = Sn ((∗ptr′ ).f ), we have that Cn+1 assigns state Sn ((∗ptr′ ).f ) to (∗M(w)).f . Therefore, since O = (∗M(w)).f , we have that Cn+1 assigns state Sn ((∗ptr′ ).f ) to O which is the same as Cn as wanted. A Case B.2.1.2. For some w < j ≤ n + 1 the jth step of In+1 performs an AllocateCell operation ′ whose response is ptr . A Hence, since for all w < j ≤ n the jth step of In+1 does not perform an AllocateCell operation ′ A whose response is ptr , we have that the n + 1th step of In+1 performs an AllocateCell operation ′ whose response is ptr . Thus, j = n + 1 is the minimum w < j ≤ n + 1 such that the jth step A of In+1 performs an AllocateCell operation whose response is ptr′ . Therefore, by Definition C.6.8, Cn+1 assigns state Sn ((∗ptr′ ).f ) to (∗M(w)).f = O, which is the same as Cn . A Case B.2.2. For some w < j ≤ n the jth step of In+1 performs an AllocateCell operation whose response is ptr′ . 239

A Let j be the minimum w < j ≤ n such that the jth step of In+1 performs an AllocateCell cell ′ operation whose response is ptr . Hence, j is also the minimum w < j ≤ n+1 such that the jth step A of In+1 performs an AllocateCell cell operation whose response is ptr′ . Thus, by Definition C.6.8, Cn and Cn+1 assigns state Sj−1 ((∗ptr′ ).f ) to (∗M(w)).f . Therefore, since O = (∗M(w)).f , we have that Cn and Cn+1 assign the same state to O as wanted. This completes the proof of Claim 3. A We now finish the proof of Case 2. Since the n + 1th step of In+1 performs an operation on the memory manager, and by Lemma C.6.9 the program counter of every process is the same in CnA B and Cn , we have that the n + 1th step of In+1 performs an operation on the memory manager. B . Hence, the state of every base object other than the memory manager is the same in Cn and Cn+1 Thus, since by Claim 3 the state of every base object other than the memory manager is the same in Cn and Cn+1 , we have that the state of every base object other than the memory manager is B the same in Cn+1 and Cn+1 . Therefore, since by Claim C.6.15.3 the state of the memory manager B B is the same in Cn+1 and Cn+1 , we have that the state of every base object is the same in Cn+1 and Cn+1 as wanted. A performs an operation on a base object O other than the memory Case 3. The n+1th step of In+1 manager. A , and p Hence, the state of every base object except O is the same in CnA and Cn+1 n+1 does not set A any index of any base object except O during the n + 1th step of In+1 . Thus, for any base object O′ other than O and the memory manager and index i of the state of O′ , by Definition C.6.4, Wn+1 (O′ , i) = Wn (O′ , i). Therefore, since the state of every base object except O is the same in A , by Definition C.6.7, S ′ ′ ′ ′ CnA and Cn+1 n+1 (O , i) = Sn (O , i), and so Sn+1 (O ) = Sn (O ) (*). ∗ Claim: The state of every base object except O is the same in Cn and Cn+1 where O∗ is defined as: O if O ∈ / CO and otherwise O is the object f of some cell where f is either response, revocations, or next, and O∗ = (∗Sn (Os )).f where Os is the source of O (see Observation C.6.14). Consider any base object O′ other than O∗ and the memory manager. Case A. O′ ∈ / CO or O′ is in H. We first prove that O′ ̸= O. If O ∈ / CO or O is in H, then O∗ = O, and so since O′ ̸= O∗ , we have ′ that O ̸= O. Otherwise, if O ∈ CO and O is not in H, then since O′ ∈ / CO or O′ is in H, we have ′ ′ that O ̸= O. Therefore, in all cases, O ̸= O as wanted. We now finish the proof of Case A. Since O′ ∈ / CO or O′ is in H, by Definition C.6.8, Cn (resp. Cn+1 ) assigns state Sn (O′ ) (resp. Sn+1 (O′ )) to O′ . Hence, since O′ is a base object other than O and the memory manager, by (*), Sn+1 (O′ ) = Sn (O′ ). Therefore, Cn and Cn+1 assigns the same state to O′ as wanted. Case B. O′ ∈ CO and O′ is not in H. Hence, by Definition C.6.1, O′ = (∗ptr′ ).f ′ for some ptr′ ∈ C and f ′ which is either response, revocations, or next. Let Wn (resp. Wn+1 ) be the set of step numbers up to and including the A nth (resp. n + 1th) step of In+1 which perform AllocateCell operations. Since the n + 1th step of A In+1 performs an operation on a base object other than the memory manager, the n + 1th step of A In+1 does not perform an AllocateCell operation. Hence, Wn = Wn+1 = W . There are two cases. Case B.1. ptr′ ∈ / M[W ]. Hence, by Definition C.6.8, Cn and Cn+1 assign O′ to its initial state. Case B.2. ptr′ ∈ M[W ]. Hence, for some w′ ∈ W M(w′ ) = ptr′ . Thus, since O′ = (∗ptr′ ).f ′ , we have that O′ = (∗M(w′ )).f ′ . A , so Let ptr be the response of the AllocateCell operation performed during the w′ th step of In+1 by Algorithm 3 ptr ∈ C. There are two more cases.

240

A Case B.2.1. For all w′ < j ≤ n the jth step of In+1 does not perform an AllocateCell operation whose response is ptr. A Since the n + 1th step of In+1 does not perform an AllocateCell operation, we have that for all ′ A w < j ≤ n + 1 the jth step of In+1 does not perform an AllocateCell operation whose response is ptr. Hence, by Definition C.6.8, Cn (resp. Cn+1 ) assigns state Sn ((∗ptr).f ′ ) (resp. Sn+1 ((∗ptr).f ′ )) to (∗M(w′ )).f ′ . We now prove that O ̸= (∗ptr).f ′ . Suppose, for contradiction, O = (∗ptr).f ′ . Hence, since ptr ∈ C, by Definition C.6.1, O ∈ CO . Thus, by the definition of O∗ , we have that O∗ = (∗Sn (Os )).f ′ . Let A performs an Wn (Os , 1) = w. Since O = (∗ptr).f ′ where ptr ∈ C, by Claim C.6.15.9, wth step of In+1 AllocateCell operation whose response is ptr and Sn (Os ) = M(w). Hence, since O∗ = (∗Sn (Os )).f ′ , we have that O∗ = (∗M(w)).f ′ . Furthermore, by Claim C.6.15.11, for all w < i ≤ n + 1 the ith A step of In+1 does not perform an AllocateCell operation whose response is ptr where O is an object A of the cell pointed to by ptr. Since both the w′ th and wth step of In+1 perform an AllocateCell ′ A operation whose response is ptr, for all w < j ≤ n + 1 the jth step of In+1 does not perform an A AllocateCell operation whose response is ptr, and for all w < i ≤ n + 1 the ith step of In+1 does ′ not perform an AllocateCell operation whose response is ptr, it follows that w = w. Therefore, since O′ = (∗M(w′ )).f ′ , we have that O′ = (∗M(w)).f ′ , and so O′ = O∗ . However, O′ was chosen to be different from O∗ , a contradiction. We now finish the proof of Case B.2.1. Recall Cn (resp. Cn+1 ) assigns state Sn ((∗ptr).f ′ ) (resp. Sn+1 ((∗ptr).f ′ )) to (∗M(w′ )).f ′ . Hence, since ptr ∈ C and O ̸= (∗ptr).f ′ , we have that (∗ptr).f ′ is a base object other than O and the memory manager, and so by (*) Sn+1 ((∗ptr).f ′ ) = Sn ((∗ptr).f ′ ). Thus, Cn and Cn+1 assign the same state to (∗M(w′ )).f ′ . Therefore, since O′ = (∗M(w′ )).f ′ , we have that Cn and Cn+1 assign the same state to O′ as wanted. A Case B.2.2. For some w′ < j ≤ n the jth step of In+1 performs an AllocateCell operation whose ′ response is ptr . A Let j be the minimum w′ < j ≤ n such that the jth step of In+1 performs an AllocateCell cell ′ ′ operation whose response is ptr . Hence, j is also the minimum w < j ≤ n+1 such that the jth step A of In+1 performs an AllocateCell cell operation whose response is ptr. Thus, by Definition C.6.8, Cn and Cn+1 assigns state Sj−1 ((∗ptr).f ) to (∗M(w′ )).f ′ . Therefore, since O′ = (∗M(w′ )).f ′ , we have that Cn and Cn+1 assign the same state to O′ . This completes the proof of Case B. Finally, consider the memory manager. By Definition C.6.8, Cn (resp. Cn+1 ) assigns state M[Wn ] (resp. M[Wn+1 ]) to the memory manager, and since Wn = Wn+1 , we have that M[Wn ] = M[Wn+1 ], and so Cn and Cn+1 assign the same state to the memory manager. Therefore, the state of every base object except O∗ is the same in Cn and Cn+1 . This completes the proof of Claim. A We now finish the proof of Case 3. Since the n + 1th step of In+1 performs an operation on a base B object O other than the memory manager, by Claim C.6.15.8, the n + 1th step of In+1 performs ∗ ∗ B . an operation on O . Hence, the state of every base object except O is the same in Cn and Cn+1 Thus, since by Claim the state of every base object except O∗ is the same in Cn and Cn+1 , we B have that the state of every base object except O∗ is the same in Cn+1 and Cn+1 . What remains is B ∗ B to show that Cn+1 and Cn+1 assign the same state to O . By Claim C.6.15.12 Cn+1 assigns state ∗ Sn+1 (O) to O . First, suppose O ∈ / CO or O is in H. Hence, by Definition C.6.8, Cn+1 assigns state Sn+1 (O) to O. Thus, since O ∈ / CO or O is in H, we have that O∗ = O, so Cn+1 assigns state B Sn+1 (O) to O∗ . Therefore, Cn+1 and Cn+1 assign the same state to O∗ as wanted. Now suppose O ∈ CO and O is not in H. Hence, by Definition C.6.1, O = (∗ptr).f where f is either response, A revocations, or next. Let Wn (Os , 1) = w. By Claim C.6.15.9 the wth step of In+1 performs an

241

AllocateCell operation whose response is ptr and Sn (Os ) = M(w). Hence, since O = (∗ptr).f , by the definition of O∗ , O∗ = (∗Sn (Os )).f , and so O∗ = (∗M(w)).f . Furthermore, by Claim C.6.15.11 A does not perform an AllocateCell operation whose response for all w < i ≤ n+1 the ith step of In+1 A is ptr. Hence, since the wth step of In+1 performs an AllocateCell operation whose response is ptr, by Definition C.6.8, Cn+1 assigns state Sn+1 ((∗ptr).f ) to (∗M(w)).f . Thus, since O = (∗ptr).f B and O∗ = (∗M(w)).f , we have that Cn+1 assigns state Sn+1 (O) to O∗ . Therefore, Cn+1 and Cn+1 ∗ assign the same state to O as wanted. This completes the proof of the inductive case, and therefore the lemma. C.6.3

Lemma C.6.15

The mapping is correctness-preserving

In this section, we show that A is linearizable, wait-free, and has space complexity linear in the point contention by using the mapping from A to B and the fact that B has these properties. Proposition C.6.16. A is linearizable with respect to T . Proof. Consider any implementation history I A = C0A , p1 , C1A , . . . of A. By Lemma C.6.15, I = C0 , p1 , C1 , . . . as defined in Definition C.6.8 is an implementation history of B. Let HA (resp. H) be the object history of I A (resp. I). We claim that HA = H. Since by Lemma C.6.9, the program counter of each process is the same in the ith configuration of I A and I, we have that the subsequence of invocation and response steps (ignoring the operation or response they are for) in I A and I are the same, so all that remains is to show that each invocation (resp. response) step is for the same operation (resp. response) in I A and I. Consider any invocation step of I A ; say the ith step, and for some operation o. Let pi be the process that performed the ith step of I A . Hence, some local variable pr of pi is assigned the state of o in CiA . Thus, since the value of pr in CiA did not originate from the response of an AllocateCell response operation, by Definition C.6.4, Wi (pr, 1) = ⊥, and so by Definition C.6.7 Si (pr) = o. So, by Definition C.6.8, Ci assigns state o to pr. Therefore, since by definition pi performs the ith step of I and by Lemma C.6.9 the program A and C counter of pi is the same in Ci−1 i−1 , we have that the ith step of I is also an invocation step for o. Now consider any response step of I A ; say the ith step and for some response r. Let pi be the process that performed the ith step of I A . Hence, some local variable pr of pi is assigned A . Thus, since the value of pr in C A did not originate from the response of the state of r in Ci−1 i an AllocateCell response operation, by Definition C.6.4, Wi (pr, 1) = ⊥, and so by Definition C.6.7 Si (pr) = r. So, by Definition C.6.8, Ci assigns state r to pr. Therefore, since by definition pi A performs the ith step of I and by Lemma C.6.9 the program counter of pi is the same in Ci−1 and Ci−1 , we have that the ith step of I is also a response step for r. This completes the proof of that HA = H. Since H is the object history of I, and I is an implementation history of B, by Theorem C.3.14, H is linearizable with respect to T . Hence, since HA = H, we have that HA is linearizable with respect to T . Thus, since HA is the object history of I A , we have that I A is linearizable with respect to T . Therefore, every implementation history of A is linearizable with respect to T , and so A is linearizable with respect to T as wanted. Proposition C.6.16 Proposition C.6.17. A is wait-free. Proof. Suppose, for contradiction, A is not wait-free. Hence, there is an implementation history I A = C0A , p1 , C1A , . . . of A such that there is an operation execution opx in I A of A where the process that executed opx takes infinitely many steps during opx without completing it. Let p be the process that executed opx and let s1 , s2 , . . . be the infinite sequence of step numbers where si denotes the step number of the ith step p performed during opx in I A . Let I = C0 , p1 , C1 , . . . be 242

the implementation history defined in Definition C.6.8 from I A , and so by Lemma C.6.15, I is an implementation history of B. Since by definition the process that performs each step of I A and I A and C is the same, and by Lemma C.6.9 the program counter of p is the same in Ci−1 i−1 for the A ith step of I , we have that if p executes the line of code ℓi during the si th step of I A , then p executes the line of code ℓi during the si th step of I. Hence, since s1 is the first step p performs during opx in I A , we have that ℓ1 = 1, and so p performs an invocation step during the s1 th step of I. Furthermore, since by assumption p never completes opx in I A , we have that ℓi ̸= 8 for every i, and so p never performs a revocation step from the s1 th step onwards in I. Hence, since p performs a step of I at step numbers s1 , s2 , . . ., p performs an invocation step at s1 , and p never performs a revocation step from the s1 th step onwards in I, we have that p takes infinitely many steps during a single operation execution in I without completing it. Therefore, since I is an implementation history of B, by the definition of wait-freedom, B is not wait-free. However, by Theorem C.4.39, B is wait-free, a contradiction. Proposition C.6.17 Proposition C.6.18. For every implementation history I A of A, the space complexity at any time t in I A is linear in the point contention at t. Proof. Since by Definition 3 the space complexity at any time t in I A is the number of statically allocated base objects plus the number of dynamically allocated base objects at time t in I A , and A uses 7 statically allocated base objects (i.e., C, A, L, S, and the three objects in H), it suffices to prove that the number of dynamically allocated base objects at time t in I A is linear in the point contention at t. Furthermore, since each cell in A is comprised of three base objects, it suffices to prove that the number of allocated cells at time t in I A is linear in the point contention at t. We prove the following stronger claim. For every implementation history I A of A, the number of allocated cells at any time t in I A is at most 6c + 1 where c is the point contention at t in I A . In the same terminology used in Theorem C.5.53, this is equivalent to the following statement. For every finite implementation history I A of A, the number of allocated cells at the end of I A is at most 6c + 1 where c is the point contention in I A . Suppose, for contradiction, there is a finite implementation history I A = C0A , p1 , C1A , . . . , CnA of A such that the number of allocated cells at the end of I A (i.e., in CnA ) is larger than 6c + 1. Let M be the state of the memory manager in CnA , so |M | > 6c+1. Furthermore, let I = C0 , p1 , C1 , . . . , Cn be the implementation history defined in Definition C.6.8 from I A , and so by Lemma C.6.15, I is an implementation history of B. Consider the ith step of I A . Since the same process pi takes the A and C ith step of I A and I, and by Lemma C.6.9 the program counter of pi is the same in Ci−1 i−1 , A we have that if the ith step of I is an invocation step, then the ith step of I is an invocation step, and if the ith step of I A is an revocation step, then the ith step of I is an revocation step. Therefore, the subsequence of invocation and response steps (ignoring the operation or response they are for) in I A and I are the same, so the point contention in I is also c (A). Since |M | > 6c + 1, we have that there is a set {ptr1 , ptr2 , . . . , ptr6c+2 } of 6c + 2 pointers in M . Hence, for every i ∈ [1..6c + 2], by Algorithm 3, for some si ≤ n the si th step of I A performs an AllocateCell operation whose response is ptri such that for all si ≤ j ≤ n the jth step of I A does not perform a FreeCell(ptri ) operation (B). Hence, by Algorithm 3, ptri ∈ C. Furthermore, by Lemma C.6.10, the si th step of I performs an AllocateCell operation whose response is M(si ) ∈ C 0 (I A ) (C). Lastly, since |{ptr1 , ptr2 , . . . , ptr6c+2 }| = 6c + 2 and the si th step of I A performs an AllocateCell operation whose response is ptri , we have that |{s1 , s2 , . . . , s6c+2 }| = 6c+2. Therefore, since M is injective, we have that |{M(s1 ), M(s2 ), . . . , M(s6c+2 )}| = 6c + 2 (D). We claim that every step of I does not perform a FreeCell(M(si )) operation (E). Suppose, for contradiction, the jth step of I where j ≤ n does.

243

Case 1. j ≤ si . Since I is an implementation history of B, M(si ) ∈ C, and by assumption the jth step of step of I performs a FreeCell(M(si )) operation, by 2 of Theorem C.5.51, there is an AllocateCell operation whose response is M(si ) before the jth step of I. Therefore, since by (C) the si th step of I is an AllocateCell operation whose response is M(si ), and j ≤ si , we have that there are two AllocateCell operations whose response is M(si ) during I. However, by Algorithm 4, there is at most one AllocateCell operation whose response is M(si ) in I, a contradiction. Case 2. si < j. Hence, since j ≤ n, we have that si < j ≤ n. Since the jth step of I performs a FreeCell(M(si )) operation, we have that Cj−1 assigns state M(si ) to pj ’s local variable curr ptr in the Relinquish procedure; denote this local variable by pr. Hence, by Definition C.6.8, Sj−1 (pr) = M(si ). Thus, since the state assigned to curr ptr is a single value, Sj−1 (pr) = Sj−1 (pr, 1), and so by DefiniA tion C.6.7, Cj−1 either assigns state M(si ) to pr or Wj−1 (pr, 1) = si . If the former, then by Definition C.6.5, M(si ) ∈ C(I A ). However, M(si ) ∈ C 0 (I A ), and by Observation C.6.6 C(I A ) and C 0 (I A ) are disjoint, so this case is impossible. Hence, Wj−1 (pr, 1) = si . Thus, by Lemma C.6.12, the si th step of I A performs an AllocateCell operation with response v1 where v1 is the value of A . So, since by (B) the s th step of I A performs an the 1st index of the state assigned to pr in Cj−1 i A assigns state ptr to AllocateCell operation whose response is ptri , we have that v1 = ptri , so Cj−1 i pr. Since the jth step of I performs a FreeCell operation, the same process pj takes the jth step A and C of I A and I, and by Lemma C.6.9 the program counter of pj is the same in Cj−1 j−1 , we A A have that the jth step of I performs a FreeCell operation. Therefore, since Cj−1 assigns state ptri to pr and pr is pj ’s local variable curr ptr in the Relinquish procedure, we have that the jth step of I A performs a FreeCell(ptri ) operation. However, by (B), for all si ≤ j ≤ n the jth step of I A does not perform a FreeCell(ptri ), a contradiction. We now finish the proof of Proposition C.6.18. Let Allocate(I) be the set of pointers which have been allocated in I, i.e., ptr ∈ Allocate(I) if and only if there is an AllocateCell operation in I whose response is ptr. Likewise, let F ree(I) be the set of pointers which have been freed in I, i.e., ptr ∈ F ree(I) if and only if there is an FreeCell(ptr) operation in I. Consider any i ∈ [1..6c + 2]. Since by (C) the si th step of I is an AllocateCell operation whose response is M(si ), we have that M(si ) ∈ Allocate(I). Hence, since by (E) every step of I does not perform a FreeCell(M(si )) operation, we have that M(si ) ∈ Allocate(I) \ F ree(I). Thus, for every i ∈ [1..6c + 2] M(si ) ∈ Allocate(I) \ F ree(I). Therefore, by (D) |Allocate(I) \ F ree(I)| ≥ 6c + 2 > 6c + 1. However, since I is a finite implementation history of B, and by (A) the point contention in I is c, by Theorem C.5.53, |Allocate(I) \ F ree(I)| ≤ 6c + 1, a contradiction. Proposition C.6.18 This completes the main result of Appendix C. Theorem C.6.19 (Theorem 6 restated). Algorithm 2 is a wait-free universal construction for the infinite-arrival model with bounded concurrency. Its space complexity at time t is linear in the point contention at t. Proof. By Propositions C.6.16, C.6.17, and C.6.18.

244

Theorem C.6.19

Record · ID 204759 · SHA-256 94285182c5a6f09b
Retrieved via Conceptio — every document is proof-bundled with source, license, and retrieval metadata.