Proof of Correctness of Lock-free Twol Algorithm

Một phần của tài liệu High performance sequential and lock free parallel access priority queue structures (Trang 197 - 205)

 ‘’“”•‘–” —ility [Herlihy and Wing 1990] is a correctness condition for concurrent objects that exploits the semantics of an abstract data type (ADT) such as a priority queue. Formally, a concurrent implementation is considered linearizable if every operation by concurrent processes appears to take effect instantaneously at some point between its invocation and its response, implying that the meaning of operations can be given by pre- and post-conditions [Herlihy and Wing 1990]. This particular instant is defined as the linearization (or linearizability) point.

For every linearizable concurrent execution, there should also exist an equal sequential execution which adheres to the pre- and post-conditions of the sequential semantics of the ADT. This means that the correctness of an ADT is essentially the mapping of a concurrent history to form an equivalent valid sequential history. Thus a correct concurrent object must satisfy this condition for all histories of concurrency. But for a complex ADT structure, it is highly difficult to get histories for all cases. However, the mapping of concurrent histories has been shown to be always possible (i.e. the concurrent object is correct) if every operation that modifies the shared object has a linearization point [Sundell and Tsigas 2005].

Thus to prove that a concurrent implementation is linearizable, the following methodology, which has been devised by Sundell and Tsigas [2005], can be employed:

• Define precise sequential semantics

• Define abstract state and its interpretation – show that each state is atomically updated

• Define linearizability points – show that operations take effect atomically at these points with respect to sequential semantics

The lock-free Twol structure is first proved to be linearizable and then followed by the proof that it is ˜ ™ck-free. Some definitions are first stated to help in presenting and explaining the proof better. We first define the syntax which will be used in presenting the semantics, followed by defining the sequential semantics of our priority queue operations.

š ›œœžœŸN B.1: The syntax is S1 : O1, S2, where S1 is the conditional state before the operation O1, and S2 is the resulting state after performing the corresponding operation.

DEFINITION B.2: Qt is denoted as the abstract internal state of the Twol priority queue at the time t. Qt is viewed as a set of pairs of 〈p v, 〉 where p is the priority (or key) and has a corresponding value v. 1Q t is denoted as the abstract internal state of Twol’s first-tier structure T1 and 2Q t represents the state of second- tier T2, where Qt =Q1tQ2t. The operations that can be carried out on the priority queue are Insert (I) and DeleteMin (DM). The time just before the atomic execution of the operation is defined as t1 and the time just after the atomic execution is defined as t2. We denote Prev and Next as contiguous priority elements within a linked list in a bucket.

(Insert into T1)

{ }

  )

{ }

1 1

1 1

2 1 1 1

2 ,

: ,

, 1t 1t ,

p T cur Prev p Next I p v true

Q Q p v

≤ ≤ <

〈 〉 =

= ∪ 〈 〉

(1)

(Insert into T2)

{ }

  )

{ }

1

1 1

2 1 1 1

2

: ,

, 2t 2t ,

p T cur I p v true

Q Q p v

>

〈 〉 =

= ∪ 〈 〉

(2)

(DeleteMin)

{ }

¡ ¢

{ }

1 1 1

1 1

2 1 1 1

, min ,

: ,

, \ ,

£

£ £

¤ ¥ ¤ ¥ ¦

§¨ ¤ ¥

¦ ¦ ¤ ¥

〈 〉 = 〈 〉 ∈

= 〈 〉

= 〈 〉

(3)

(DeleteMin)

{ }

¡ ¢

1

:

£

¦

§¨

= ∅

= ⊥ (4)

â êêA B.1: ô ơư definition of the abstract internal state for our Twol implementation is consistent with all concurrent operations examining the state of the priority queue.

PROOF: Each bucket in T1 and T2 is made up of a linked list in which the linked list has a head node pointer. And since the head and the next pointers are changed only using the MCAS operation, we are sure that all processes see the same state of the Twol priority queue. Therefore all changes of the abstract state will appear to be atomic. □

LEMMA B.2: During a transfer of priority elements from T2 to T1 occur, Insert and DeleteMin cannot successfully occur, i.e. inserting and deleting of elements cannot take place.

PROOF: Before a transfer begins, the next pointers in all the buckets of both T1 and T2 are ensured marked. Only then the transfer operation starts to move the priority elements from T2 to T1. Since the next pointers are changed atomically, we are sure that all the processes executing the Insert and DeleteMin operations will see the same state, i.e. that the next pointers are marked and denote that a transfer is occurring. Therefore those processes will suspend their intended operation (i.e.

Insert or DeleteMin) and attempt to help in the transfer until all the elements are transferred from T2 to T1. When the transfer is complete, all the next pointers will

be unmarked and those processes will continue to execute their intended operation.

®¯¯A B.3:° ± Insert operation where p v, 〉 is successfully inserted into T1, i.e. I²〈p v, 〉 =) true, takes effect atomically at one statement.

PROOF: The linearization point (LP) for an Insert into T1 which succeeds ( I²〈p v, 〉 =) true) is when the MCAS sub-operation in line IT17 (in InsertT1) succeeds, and the Insert operation will finally return true. The pre-condition directly before the passing of the LP must have been pT cur2 . Otherwise, it would have been inserted into T2. SearchT1 function determines that p is to be inserted between Prev and Next, and they are guaranteed to be consistent (from the point SearchT1 has decided till just before IT17) else MCAS would have failed. The state of the priority queue directly after passing the LP will be Q1t2 =Q1t1 ∪{〈p v1, 1〉}, i.e.

{ }

2 1 1, 1

t t

Q =Q ∪ 〈p v〉 . □

LEMMA B.4:An Insert operation where p v, 〉 is successfully inserted into T2, i.e. I²〈p v, 〉 =) true, takes effect atomically at one statement.

PROOF: The LP for an Insert into T2 which succeeds (I²〈p v, 〉 =) true) is

when the MCAS sub-operation in line I19 or I24 or I28 or I32 succeeds, and the Insert operation operation will finally return true. The reason for having these four possibilities is because Twol’s algorithm needs to have updated T2min and T2max, which denote the minimum and maximum priority found in T2 respectively. The pre-condition directly before the passing of the LP must have been p1>T cur2 (see I14). The state of the priority queue directly after passing the LP will be

{ }

2 1 1 1

2t 2t ,

Q =Q ∪ 〈p v〉 , i.e. Qt2 =Qt1 ∪{〈p v1, 1〉}. □

³´´A B.5: ả DeleteMin operation which succeeds, i.e. DMã )= 〈p v1, 1〉 where p v1, 1〉 = 〈min ,p v〉 ∈Qt1, takes effect atomically at one statement.

PROOF: The LP for a DeleteMin operation which succeeds (DMã )= 〈p v1, 1〉) is when the MCAS sub-operation in line FD11 (in FinalDelete) succeeds. The pre-condition directly before the passing of the LP must have been

1, 1 min , t1

p v p v Q

〈 〉 = 〈 〉 ∈ since the element to be deleted is the first element from the head of the most current bucket. The state of the priority queue after passing the LP will be Qt2 =Qt1 \{〈p v1, 1〉}. □

LEMMA B.6:A DeleteMin operation which fails, i.e. DMã )= ⊥, takes effect atomically at one statement.

PROOF: The LP for a DeleteMin operation which fails (DMã )= ⊥), is

when the MCAS sub-operation in line TI24 (in TransferInit) succeeds. The pre- condition directly before the passing of the LP must have been Qt1 = ∅. This is because the success of MCAS means that all the buckets in T1 are invalidated, and all the heads in T2 points to the Tail node, i.e. Q1t1= ∅,Q2t1 = ∅. □

LEMMA B.7: One operation in our Twol implementation will always progress regardless of the actions by the other concurrent operations.

PROOF: There are several potential recurrent loops in our implementation which can delay the termination of the operations, thus possibly preventing the operations in the implementation from progressing. However, we shall demonstrate that these recurrent loops occur only if some other operations have occurred (i.e.

there is still progression in the system). The invocations of these loops are found in:

FinalDelete (FD6, FD13)

• FD6 occurs only if some other operation has already deleted element D. Thus it tries again to delete from subsequent elements. But once the bucket is empty or invalid, this operation terminates.

• The failure of MCAS (FD13) is only possible if some other operations have progressed by changing the next or value pointers.

TransferInit (TI26, TI41)

• TI26 occurs only if some other operations have inserted some new elements between the time taken to execute (TI13 – TI23), thus resulting in a failed MCAS (TI24).

• TI41 occurs only if either some other operations have inserted some new elements into the T2 buckets or a TransferInit has already occurred causing the MCAS operation to fail.

TransferNodes (TN16, TN26, TN33, TN44)

• TN16 occurs due to the operation’s semantics to transfer only T2 buckets which are not empty.

• TN26 occurs only if some other processes are helping to transfer into the same T1 bucket; the áạev and Next returned by SearchT1 has changed, which means that some other processes executing this particular operation have progressed.

• TN33 happens when not all the T2 buckets have been transferred which obeys the operation’s semantics.

• TN44 occurs only if some T2 buckets have yet to finish transferring the elements. Therefore it is required to start over and try again to help in the transfer starting from that bucket.

DeleteMin (D5, D7, D9, D11, D13, D17, D19, D20, D26)

• D5, D7 and D17 occur only if other processes have progressed by transferring elements from T2 to T1.

• D9 and D13 retry the operation because they have just finished helping in the transfer of elements.

• D11 occurs upon the completion of TransferInit operation.

• D19 occurs because another process has just incremented T1index.

• D20 occurs because just before T1index is incremented by this process, another operation has progressed by inserting a new element into the current bucket.

• D26 obeys the operation semantics by attempting again to delete an element.

InsertT1 (IT9, IT10, IT12, IT18)

• IT9 tries again to find the most current bucket as the previously determined bucket has been invalidated by another operation.

• IT10 occurs only if the bucket (where the element is to be inserted) has been invalidated by another operation.

• IT12 occurs only if SearchT1 returns false. This can occur if either the current bucket has changed (T1index has been incremented) or a transfer has already occurred.

• The failure of MCAS sub-operation (IT18) means that the ºằev and Next elements differ from the ones obtained by SearchT1. It implies that some other operations have already progressed by inserting at least one element between Prev and Next or that Prev has already been deleted. So this operation does a retry only if at least one other process has progressed.

Insert (I6, I8, I11 – I13, I34, I38, I41)

• I6, I8, I11 and I12 occur only if some other process has progressed by changing the head pointer in the T2 bucket, i.e. transferring of elements have been completed.

• I13 does a TransferNodes operation to help other processes to complete the transfer and thus Insert should restart since the T2cur must have changed after a transfer.

• I34 occurs when MCAS sub-operation has failed and this is possible only if some other process has inserted at least one new element into T2. Either that or a transfer has already been initiated.

• I38 is to check if T1index = T1end which means that T1 is now empty and a transfer is about to occur or has already been initiated.

• I41 attempts to insert the new element into the next valid bucket because another operation has already incremented T1index. □

ẳẵ ắ¿ẵ À B.1: ÁÂÃ algorithm implements a linearizable and lock-free priority queue.

PROOF: We have shown that the operations take effect atomically at the linearization points (Lemmas B.3, B.4, B.5, B.6) which respect the sequential semantics given in Definition B.2. And with Lemma B.7, proves that our Twol priority queue implementation is linearizable and lock-free. □

Một phần của tài liệu High performance sequential and lock free parallel access priority queue structures (Trang 197 - 205)

Tải bản đầy đủ (PDF)

(205 trang)