Lock-Free Concurrent Data Structures Danny Hendler Ben-Gurion - - PowerPoint PPT Presentation

lock free concurrent data structures
SMART_READER_LITE
LIVE PREVIEW

Lock-Free Concurrent Data Structures Danny Hendler Ben-Gurion - - PowerPoint PPT Presentation

Lock-Free Concurrent Data Structures Danny Hendler Ben-Gurion University 1 Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 Key synchronization alternatives 1. Lock-based synchronizaGon 2. Nonblocking algorithms 3. TransacGonal


slide-1
SLIDE 1

Lock-Free Concurrent Data Structures

Danny Hendler

Ben-Gurion University

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 1

slide-2
SLIDE 2

Key synchronization alternatives

  • 1. Lock-based synchronizaGon
  • 2. Nonblocking algorithms
  • 3. TransacGonal memory

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

slide-3
SLIDE 3

Coarse-grained locks

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Pros

q Easy to program

Cons

q SequenGal

slide-4
SLIDE 4

Fine-grained locks

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Pros

q PotenGally scalable

Cons

q Not robust against failures q SuscepGble to:

  • Deadlocks
  • Priority inversion
  • Convoying

q Locks do not compose

slide-5
SLIDE 5

Nonblocking synchronization

Wait-freedom

Every thread is guaranteed to complete its operaGon aPer performing a sufficient number of steps.

Lock-freedom

Some thread is guaranteed to complete its operaGon aPer a sufficient number of steps by threads is taken.

ObstrucGon-freedom

A thread is guaranteed to complete its operaGon aPer performing a sufficient number of steps when running solo.

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 5

slide-6
SLIDE 6

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Lock-free algorithms

q Ensure global progress q Avoid lock-based programming weaknesses q OPen require strong synchronizaGon operaGons

  • Compare-and-swap (CAS)
  • Fetch-and-add
  • Swap

q OPen difficult to devise and prove correct

6

slide-7
SLIDE 7

Talk Outline

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

n Preliminaries n A simple lock-free stack algorithm

  • Linearizability

n Michael & Sco] queue algorithm n The Harris-Michael linked list algorithm n EliminaGon-based stack n Discussion & conclusions

7

slide-8
SLIDE 8

Treiber/IBM’s stack algorithm

q Stack represented as linked list q Top pointer manipulated by compare-and-swap (CAS) operaGons Top

val next val next

val next atomically

t read from var if (var = expected) { var new return success } else return failure;

Compare&swap(var,expected,new)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 8

slide-9
SLIDE 9

Treiber/IBM: Push

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Top

val next val next

val next val next

CAS

9

slide-10
SLIDE 10

Treiber/IBM: Push

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Push(int v, Stack S) 1. n := new NODE ;create node for new stack item 2. n.val := v ;write item value 3. do forever ;repeat until success 4. node top := S.top 5. n.next := top ;next points to current top (LIFO order) 6. if compare&swap(S, top, n) ; try to add new item 7. return ; return if succeeded 8. end do

10

slide-11
SLIDE 11

Top

val next val next

val next

CAS

Treiber/IBM: Pop

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 11

slide-12
SLIDE 12

Treiber/IBM: Pop

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Pop(Stack S) 1. do forever 2. top := S.top 3. if top = null 4. return empty 5. if compare&swap(S, top, top.next) 6. return-val=top.val 7. free top? 8. return return-val 9. end do

Why is the algorithm lock-free?

12

slide-13
SLIDE 13

Is the algorithm “correct”?

What does it mean for a concurrent algorithm to be correct?

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 13

slide-14
SLIDE 14

Correctness of sequential counter

  • fetch&increment, applied to a counter with value v,

returns v and increments the counter’s value to (v+1).

  • Values returned by consecuGve operaGons:

0, 1, 2, … How should we define the correctness of a shared counter?

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 14

slide-15
SLIDE 15

time q.enq(x) q.enq(y) q.deq(x) q.deq(y) fetch&inc fetch&inc fetch&inc fetch&inc time

There is only a partial order between operations!

Invocation Response

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Correctness of concurrent counter?

15

slide-16
SLIDE 16

Correctness of concurrent counter?

time q.enq(x) q.enq(y) q.deq(x) q.deq(y) fetch&inc fetch&inc fetch&inc fetch&inc time

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

1 3 4

16

slide-17
SLIDE 17

Correctness of concurrent counter?

time q.enq(x) q.enq(y) q.deq(x) q.deq(y) fetch&inc fetch&inc fetch&inc fetch&inc time

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

1 3 2

17

slide-18
SLIDE 18

Correctness of concurrent counter?

time q.enq(x) q.enq(y) q.deq(x) q.deq(y) fetch&inc fetch&inc fetch&inc fetch&inc time

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

2 1 3

18

slide-19
SLIDE 19

Correctness of concurrent counter?

time q.enq(x) q.enq(y) q.deq(x) q.deq(y) fetch&inc fetch&inc fetch&inc fetch&inc time

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

2 1 3

19

slide-20
SLIDE 20

Linearizability definition

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Linearizability An execuGon is linearizable if there exists a permutaGon of the operaGons on each object o, π, such that:

  • π is a sequenGal history of o
  • π preserves the parGal order of the execuGon.

20

slide-21
SLIDE 21

Linearizability: more examples

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

time q.enq(x) q.enq(y) q.deq(x) q.deq(y) q.enq(x) q.enq(y) q.deq(x) q.deq(y) time

21

slide-22
SLIDE 22

Linearizability: more examples

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

time q.enq(x) q.enq(y) q.deq(y) q.enq(x) q.enq(y)

22

slide-23
SLIDE 23

Linearizability: more examples

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

time q.enq(x) q.deq(x) q.enq(x) q.deq(x) time

23

slide-24
SLIDE 24

Linearizability: more examples

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

time q.enq(x) q.enq(y) q.deq(y) q.deq(x) time q.enq(x) q.enq(y) q.deq(y) q.deq(x) q.enq(x) q.enq(y) q.deq(y) q.deq(x)

24

slide-25
SLIDE 25

Back to Trieber’s stack algorithm Push linearization points

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Push(int v, Stack S) 1. n := new NODE ;create node for new stack item 2. n.val := v ;write item value 3. do forever ;repeat until success 4. node top := S.top 5. n.next := top ;next points to current (LIFO order) 6. if compare&swap(S, top, n) ; try to add new item 7. return ; return if succeeded 8. end do

Upon success

25

slide-26
SLIDE 26

Back to Trieber’s stack algorithm Pop linearization points

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Upon success

Pop(Stack S) 1. do forever 2. top := S.top 3. if top = null 4. return empty 5. if compare&swap(S, top, top.next) 6. return-val=top.val 7. return return-val 8. end do

When empty

26

slide-27
SLIDE 27

Talk Outline

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

n Preliminaries n A simple lock-free stack algorithm

  • Linearizability

n Michael & Sco] queue algorithm n The Harris-Michael linked list algorithm n EliminaGon-based stack n Discussion & conclusions

27

slide-28
SLIDE 28
  • Companion slides for
  • The Art of MulGprocessor Programming
  • by Maurice Herlihy & Nir Shavit

The art of multiprocessor programming

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 28

slide-29
SLIDE 29

Queue interface

q Pool of items q First-in-first-out q Methods

– enq(x) adds x at the end of the queue – deq returns the item at the head of the queue or an empty indicaGon

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 29

slide-30
SLIDE 30

Queue: concurrency

enq enq(x) (x) y=deq() y=deq() enq() and deq() work at different ends of the object tail head

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 30

slide-31
SLIDE 31

Michael & Scott queue Sentinel

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Sentinel

head tail

31

slide-32
SLIDE 32

Michael & Scott queue Enq

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

head tail

Enq( )

32

slide-33
SLIDE 33

Michael & Scott queue Enq

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

head tail

33

slide-34
SLIDE 34

Michael & Scott queue Enq: first CAS

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

head tail

CAS

34

slide-35
SLIDE 35

Michael & Scott queue Enq: second CAS

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

head tail

Enqueued Node CAS

35

slide-36
SLIDE 36

Michael & Scott queue Enq

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

q Two CAS operaGons (not atomic) q Tail references either:

  • Actual last node
  • One-before-last node (needs to be fixed!)

If tail has non-null next reference, CAS tail to tail.next

36

slide-37
SLIDE 37

AtomicReference Atomically update reference

  • At

Atomi micR cRefere rence ce class

– Java.util.concurrent.atomic package Public Public object get();

  • bject get();

Public Public boolean boolean compareAndSet compareAndSet (T expected, T new); (T expected, T new);

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 37

slide-38
SLIDE 38

AtomicReference Atomically update reference

  • At

Atomi micR cRefere rence ce class

– Java.util.concurrent.atomic package Public Public object get();

  • bject get();

Public Public boolean boolean compareAndSet compareAndSet (T expected, T new); (T expected, T new); Returns current reference

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 38

slide-39
SLIDE 39

AtomicReference Atomically update reference

  • At

Atomi micR cRefere rence ce class

– Java.util.concurrent.atomic package Apply CAS: if expected value, change to new Public object get(); Public object get(); Public Public boolean boolean compareAndSet compareAndSet (T expected, T new); (T expected, T new);

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 39

slide-40
SLIDE 40

Michael & Scott queue Deq

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

head tail

Read value

40

slide-41
SLIDE 41

Michael & Scott queue Deq

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

head tail

CAS Make first Node new sentinel

41

slide-42
SLIDE 42

Michael & Scott queue Queue node

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public class public class Node { Node { public public T value; T value; public public AtomicReference AtomicReference<Node> next; <Node> next; public public Node(T value) { Node(T value) { this.value this.value=value; =value; next=new next=new AtomicReference AtomicReference<Node>(null); <Node>(null); } } } }

42

slide-43
SLIDE 43

public class Node { public class Node { public public T value; T value; public public AtomicReference AtomicReference<Node> next; <Node> next; public Node(T value) { public Node(T value) { this.value this.value=value; =value; next=new next=new AtomicReference AtomicReference<Node>(null); <Node>(null); } } } }

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Value stored by node

Michael & Scott queue Queue node

43

slide-44
SLIDE 44

public class Node { public class Node { public T value; public T value; public public AtomicReference AtomicReference<Node> next; <Node> next; public Node(T value) { public Node(T value) { this.value this.value=value; =value; next=new next=new AtomicReference AtomicReference<Node>(null); <Node>(null); } } } }

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Reference to next queue node

Michael & Scott queue Queue node

44

slide-45
SLIDE 45

public class Node { public class Node { public T value; public T value; public public AtomicReference AtomicReference<Node> next; <Node> next; public public Node(T value) { Node(T value) { this.value this.value=value; =value; next=new next=new AtomicReference AtomicReference<Node>(null); <Node>(null); } } } }

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

New node created with null ‘next’

Michael & Scott queue Queue node

45

slide-46
SLIDE 46

Michael & Scott queue Enq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public public boolean boolean enq enq(T value) { (T value) { Node Node node=new Node(value); node=new Node(value); while while ( (true true) { ) { Node last = Node last = tail.get tail.get(); (); Node next = Node next = last.next.get last.next.get(); (); if if (last == (last == tail.get tail.get()) { ()) { if if (next == (next == null null) { ) { if if ( (last.next.compareAndSet last.next.compareAndSet(null null,node ,node) { ) { tail.compareAndSet tail.compareAndSet(last,node last,node); ); return; return; } } } } else else { { tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } } } } } } }

46

slide-47
SLIDE 47

Michael & Scott queue Enq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public public boolean boolean enq enq(T value) { (T value) { Node Node node=new Node(value); node=new Node(value); while (true) { while (true) { Node last = Node last = tail.get tail.get(); (); Node next = Node next = last.next.get last.next.get(); (); if (last == if (last == tail.get tail.get()) { ()) { if (next == null) { if (next == null) { if ( if (last.next.compareAndSet last.next.compareAndSet(null,node null,node) { ) { tail.compareAndSet tail.compareAndSet(last,node last,node); ); return; return; } } } else { } else { tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } } } } } } }

Create new node

47

slide-48
SLIDE 48

public public boolean boolean enq enq(T value) { (T value) { Node node=new Node(value); Node node=new Node(value); while (true) { while (true) { Node last = Node last = tail.get tail.get(); (); Node next = Node next = last.next.get last.next.get(); (); if (last == if (last == tail.get tail.get()) { ()) { if (next == null) { if (next == null) { if ( if (last.next.compareAndSet last.next.compareAndSet(null,node null,node) { ) { tail.compareAndSet tail.compareAndSet(last,node last,node); ); return; return; } } } else { } else { tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } } } } } } }

Michael & Scott queue Enq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Repeat until successful

48

slide-49
SLIDE 49

public public boolean boolean enq enq(T value) { (T value) { Node node=new Node(value); Node node=new Node(value); while (true) { while (true) { Node last = Node last = tail.get tail.get(); (); Node next = Node next = last.next.get last.next.get(); (); if (last == if (last == tail.get tail.get()) { ()) { if (next == null) { if (next == null) { if ( if (last.next.compareAndSet last.next.compareAndSet(null,node null,node) { ) { tail.compareAndSet tail.compareAndSet(last,node last,node); ); return; return; } } } else { } else { tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } } } } } } }

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Read tail and its next reference

Michael & Scott queue Enq pseudo-code

49

slide-50
SLIDE 50

public public boolean boolean enq enq(T value) { (T value) { Node node=new Node(value); Node node=new Node(value); while (true) { while (true) { Node last = Node last = tail.get tail.get(); (); Node next = Node next = last.next.get last.next.get(); (); if (last == if (last == tail.get tail.get()) { ()) { if (next == null) { if (next == null) { if ( if (last.next.compareAndSet last.next.compareAndSet(null,node null,node) { ) { tail.compareAndSet tail.compareAndSet(last,node last,node); ); return; return; } } } else { } else { tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } } } } } } }

Michael & Scott queue Enq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

If no need to fix tail, CAS last.next

50

slide-51
SLIDE 51

public public boolean boolean enq enq(T value) { (T value) { Node node=new Node(value); Node node=new Node(value); while (true) { while (true) { Node last = Node last = tail.get tail.get(); (); Node next = Node next = last.next.get last.next.get(); (); if (last == if (last == tail.get tail.get()) { ()) { if (next == null) { if (next == null) { if ( if (last.next.compareAndSet last.next.compareAndSet(null,node null,node) { ) { tail.compareAndSet tail.compareAndSet(last,node last,node); ); return; return; } } } else { } else { tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } } } } } } }

Michael & Scott queue Enq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

If successful, try to fix tail

51

slide-52
SLIDE 52

public public boolean boolean enq enq(T value) { (T value) { Node node=new Node(value); Node node=new Node(value); while (true) { while (true) { Node last = Node last = tail.get tail.get(); (); Node next = Node next = last.next.get last.next.get(); (); if (last == if (last == tail.get tail.get()) { ()) { if (next == null) { if (next == null) { if ( if (last.next.compareAndSet last.next.compareAndSet(null,node null,node) { ) { tail.compareAndSet tail.compareAndSet(last,node last,node); ); return; return; } } } else { } else { tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } } } } } } }

Michael & Scott queue Enq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Try to fix tail

52

slide-53
SLIDE 53

Michael & Scott queue Deq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public T public T deq deq() throws () throws EmptyException EmptyException{ { while while ( (true true) { ) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if if (first == last) { (first == last) { if if (next == (next == null null) { ) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } else else { { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

53

slide-54
SLIDE 54

public T public T deq deq() throws () throws EmptyException EmptyException{ { while (true) { while (true) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if (first == last) { if (first == last) { if (next == null) { if (next == null) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } else { } else { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

Michael & Scott queue Deq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Return value or throw EmptyException

54

slide-55
SLIDE 55

public T public T deq deq() throws () throws EmptyException EmptyException{ { while while ( (true true) { ) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if (first == last) { if (first == last) { if (next == null) { if (next == null) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } else { } else { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

Michael & Scott queue Deq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Repeat until completed

55

slide-56
SLIDE 56

public T public T deq deq() throws () throws EmptyException EmptyException{ { while (true) { while (true) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if if (first == last) { (first == last) { if (next == null) { if (next == null) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } else { } else { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

Michael & Scott queue Deq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

If head and tail are same node…

56

slide-57
SLIDE 57

public T public T deq deq() throws () throws EmptyException EmptyException{ { while (true) { while (true) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if (first == last) { if (first == last) { if if (next == (next == null null) { ) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } else { } else { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

Michael & Scott queue Deq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

If queue contains only sentinel, it is empty

57

slide-58
SLIDE 58

public T public T deq deq() throws () throws EmptyException EmptyException{ { while (true) { while (true) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if (first == last) { if (first == last) { if (next == null) { if (next == null) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } else { } else { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

Michael & Scott queue Deq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Otherwise, tail should be fixed

58

slide-59
SLIDE 59

public T public T deq deq() throws () throws EmptyException EmptyException{ { while (true) { while (true) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if (first == last) { if (first == last) { if (next == null) { if (next == null) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } else else { { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

Michael & Scott queue Deq pseudo-code

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Try to dequeue from first node

59

slide-60
SLIDE 60

Michael & Scott queue Enq linearization points

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public public boolean boolean enq enq(T value) { (T value) { Node Node node=new Node(value); node=new Node(value); while while ( (true true) { ) { Node last = Node last = tail.get tail.get(); (); Node next = Node next = last.next.get last.next.get(); (); if if (last == (last == tail.get tail.get()) { ()) { if if (next == (next == null null) { ) { if if ( (last.next.compareAndSet last.next.compareAndSet(null null,node ,node) { ) { tail.compareAndSet tail.compareAndSet(last,node last,node); ); return; return; } } } } else else { { tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } } } } } } }

60

slide-61
SLIDE 61

Michael & Scott queue Enq linearization points

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public public boolean boolean enq enq(T value) { (T value) { Node Node node=new Node(value); node=new Node(value); while while ( (true true) { ) { Node last = Node last = tail.get tail.get(); (); Node next = Node next = last.next.get last.next.get(); (); if if (last == (last == tail.get tail.get()) { ()) { if if (next == (next == null null) { ) { if if ( (last.next.compareAndSet last.next.compareAndSet(null null,node ,node) { ) { tail.compareAndSet tail.compareAndSet(last,node last,node); ); return; return; } } } } else else { { tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } } } } } } }

Upon success

61

slide-62
SLIDE 62

Michael & Scott queue Deq linearization points

public T public T deq deq() throws () throws EmptyException EmptyException{ { while while ( (true true) { ) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if if (first == last) { (first == last) { if if (next == (next == null null) { ) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } else else { { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 62

slide-63
SLIDE 63

Michael & Scott queue Deq linearization points

public T public T deq deq() throws () throws EmptyException EmptyException{ { while while ( (true true) { ) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if if (first == last) { (first == last) { if if (next == (next == null null) { ) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } else else { { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

Upon success

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 63

slide-64
SLIDE 64

Michael & Scott queue Deq linearization points

public T public T deq deq() throws () throws EmptyException EmptyException{ { while while ( (true true) { ) { Node first = Node first = head.get head.get(); (); Node last = Node last = tail.get tail.get(); (); Node next = Node next = first.next.get first.next.get(); (); if if (first == last) { (first == last) { if if (next == (next == null null) { ) { throw new throw new EmptyException EmptyException(); (); } } tail.compareAndSet tail.compareAndSet(last,next last,next); ); } } else else { { T value = T value = next.value next.value; ; if ( if (head.compareAndSet head.compareAndSet(first,next first,next)) )) return value; return value; } } } } } } } }

When empty

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 64

slide-65
SLIDE 65

Talk Outline

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

n Preliminaries n A simple lock-free stack algorithm

  • Linearizability

n Michael & Sco] queue algorithm n The Harris-Michael linked list algorithm n EliminaGon-based stack n Discussion & conclusions

65

slide-66
SLIDE 66

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Set interface

q Unordered collecGon of items q No duplicates q Methods

– add(x) put x in set – remove(x) take x out of set – contains(x) tests if x in set

66

slide-67
SLIDE 67

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

List-based sets

public interface Set<T> { public interface Set<T> { public public boolean boolean add(T x); add(T x); public public boolean boolean remove(T x); remove(T x); public public boolean boolean contains(T x); contains(T x); } }

Add item to set

67

slide-68
SLIDE 68

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

List-based sets

public interface Set<T> { public interface Set<T> { public public boolean boolean add(T x); add(T x); public public boolean boolean remove(T x); remove(T x); public public boolean boolean contains(Tt x); contains(Tt x); } }

Remove item from set

68

slide-69
SLIDE 69

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

List-based sets

public interface Set<T> { public interface Set<T> { public public boolean boolean add(T x); add(T x); public public boolean boolean remove(T x); remove(T x); public public boolean boolean contains(T x); contains(T x); } }

Is item in set?

69

slide-70
SLIDE 70

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

List Node

public class public class Node { Node { public public T item; T item; public public int int key; key; public public Node next; Node next; } }

70

slide-71
SLIDE 71

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

List Node

public class Node { public class Node { public public T item; T item; public int key; public int key; public Node next; public Node next; } }

item of interest

71

slide-72
SLIDE 72

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

List Node

public class Node { public class Node { public T item; public T item; public public int int key; key; public Node next; public Node next; } }

Usually hash code

72

slide-73
SLIDE 73

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

List Node

public class Node { public class Node { public T item; public T item; public int key; public int key; public public Node next; Node next; } }

Reference to next node

73

slide-74
SLIDE 74

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set

a b c

Sorted with Sentinel nodes (min & max possible keys)

+∞

74

slide-75
SLIDE 75

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 75

slide-76
SLIDE 76

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

remove(c) remove(c)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 76

slide-77
SLIDE 77

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

remove(c) remove(c)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 77

slide-78
SLIDE 78

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

remove(c) remove(c)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 78

slide-79
SLIDE 79

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

remove(c) remove(c)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 79

slide-80
SLIDE 80

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

remove(c) remove(c)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 80

slide-81
SLIDE 81

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

remove(c) remove(c)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 81

slide-82
SLIDE 82

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

remove(c) remove(c)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 82

slide-83
SLIDE 83

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

remove(c) remove(c)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 83

slide-84
SLIDE 84

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required

q Scan list from leP to right, apply operaGon `at the right place’ q Not so simple…

a b c d

remove(c) remove(c)

SUCCESS SUCCESS

X

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 84

slide-85
SLIDE 85

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Use compare-and-swap (CAS)!

a b c d

remove(c) remove(c)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 85

slide-86
SLIDE 86

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Use compare-and-swap (CAS)!

a b c d

remove(c) remove(c)

CAS

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 86

slide-87
SLIDE 87

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Use compare-and-swap (CAS)!

a b c d

remove(c) remove(c)

CAS CAS

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 87

slide-88
SLIDE 88

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

a b c d

88

slide-89
SLIDE 89

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

a b c d

remove(c) remove(b)

89

slide-90
SLIDE 90

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

a b c d

remove(c) remove(b)

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

90

slide-91
SLIDE 91

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

a b c d

remove(c) remove(b)

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

91

slide-92
SLIDE 92

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

a b c d

remove(c) remove(b)

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

92

slide-93
SLIDE 93

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

a b c d

remove(c) remove(b)

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

93

slide-94
SLIDE 94

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

a b c d

remove(c) remove(b)

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

94

slide-95
SLIDE 95

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

a b c d

remove(c) remove(b)

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

95

slide-96
SLIDE 96

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

a b c d

remove(c) remove(b)

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

96

slide-97
SLIDE 97

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

a c d

remove(c) remove(b)

The List-Based Set Why synchronization is required (2)

q Apply operaGon `at the right place’ using CAS q Not so simple…

X

97

slide-98
SLIDE 98

The List-Based Set Logical remove, then physical remove

q Scan list from leP to right q Apply modificaGons using CAS q Separate removal to two steps

– Logical removal: mark node to be deleted – Physical removal: change predecessor's next reference

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 98

slide-99
SLIDE 99

The List-Based Set Logical remove, then physical remove

a a b c d

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 99

slide-100
SLIDE 100

The List-Based Set Logical remove, then physical remove

c a a b d Present in list

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 100

slide-101
SLIDE 101

The List-Based Set Logical remove, then physical remove

c a a b d Logically deleted

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 101

slide-102
SLIDE 102

a a b c d Physically deleted

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Logical remove, then physical remove

102

slide-103
SLIDE 103

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Logical remove, then physical remove

a a b c d

remove(c) remove(b)

103

slide-104
SLIDE 104

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Logical remove, then physical remove

a a b c d

remove(c) remove(b)

104

slide-105
SLIDE 105

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Logical remove, then physical remove

a a b c d

remove(c) remove(b)

105

slide-106
SLIDE 106

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Logical remove, then physical remove

a a b c d

remove(c) remove(b)

106

slide-107
SLIDE 107

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Logical remove, then physical remove

a a b c d

remove(c) remove(b)

107

slide-108
SLIDE 108

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Logical remove, then physical remove

a a c d

remove(c) remove(b)

108

slide-109
SLIDE 109

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Logical remove, then physical remove

SGll not enough!

109

slide-110
SLIDE 110

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

The List-Based Set Logical remove, then physical remove

a 0 a b c e 1 c

Logical Removal = Set Mark Bit

d Problem: d not added to list… Must Prevent manipulation of removed node’s pointer

Node added Before Physical Removal CAS

SGll not enough!

110

slide-111
SLIDE 111

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

AtomicMarkableRereference Combine bit and pointer (Harris)

a 0 a b c e 1 c

Logical Removal = Set Mark Bit Physical Removal CAS

d Mark-Bit and Pointer are CASed together (AtomicMarkableReference)

Fail CAS: Node not added after logical Removal

111

slide-112
SLIDE 112

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

AtomicMarkableRereference Marking a node

  • At

Atomi micMa cMarka rkableRefere rence ce class

– Java.util.concurrent.atomic package address F mark bit Reference

112

slide-113
SLIDE 113

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

AtomicMarkableReference Extracting reference & mark

Public Public Object get( Object get(boolean boolean[] marked); [] marked); Returns reference Returns mark at array index 0!

113

slide-114
SLIDE 114

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

AtomicMarkableReference Extracting reference only

public public object

  • bject getReference();

getReference(); Value of reference

114

slide-115
SLIDE 115

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public public boolean boolean isMarked(); isMarked(); Value of mark

AtomicMarkableReference Extracting mark only

115

slide-116
SLIDE 116

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

AtomicMarkableReference Changing state

Public Public boolean boolean compareAndSet( compareAndSet( Object expectedRef, Object expectedRef, Object updateRef, Object updateRef, boolean expectedMark, boolean expectedMark, boolean updateMark); boolean updateMark);

116

slide-117
SLIDE 117

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

AtomicMarkableReference Changing state

Public Public boolean boolean compareAndSet( compareAndSet( Object expectedRef, Object expectedRef, Object updateRef, Object updateRef, boolean expectedMark, boolean expectedMark, boolean updateMark); boolean updateMark); If this is the current reference … And this is the current mark …

117

slide-118
SLIDE 118

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

AtomicMarkableReference Changing state

Public Public boolean boolean compareAndSet( compareAndSet( Object expectedRef, Object expectedRef, Object updateRef, Object updateRef, boolean expectedMark, boolean expectedMark, boolean updateMark); boolean updateMark); …then change to this new reference … … and this new mark

118

slide-119
SLIDE 119

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

q Scan list from leP to right q Apply modificaGons using CAS q Separate removal to two steps

– Logical removal: mark node to be deleted

  • Once done, next reference cannot be changed

– Physical removal: change predecessor's next reference

q When finding a logically-deleted node, finish the job

The List-Based Set Key ideas

119

slide-120
SLIDE 120

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove pseudo-code

public public boolean boolean remove(T item) { remove(T item) { Boolean Boolean snip; snip; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if if ( (curr.key curr.key != key) { != key) { return return false false; ; } } else else { { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet(succ succ, , succ succ, , false false true true); ); if if (!snip) (!snip) continue continue; ; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, , false false, , false false); ); return return true true; ; }}} }}}

120

slide-121
SLIDE 121

public public boolean boolean remove(T item) { remove(T item) { Boolean snip; Boolean snip; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if ( if (curr.key curr.key != key) { != key) { return false; return false; } else { } else { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet ( (succ succ, , succ succ, false, , false, true); true); if (!snip) continue; if (!snip) continue; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, false, false); , false, false); return true; return true; }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove pseudo-code

Keep trying

121

slide-122
SLIDE 122

public public boolean boolean remove(T item) { remove(T item) { Boolean snip; Boolean snip; while (true) { while (true) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if ( if (curr.key curr.key != key) { != key) { return false; return false; } else { } else { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet ( (succ succ, , succ succ, false, , false, true); true); if (!snip) continue; if (!snip) continue; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, false, false); , false, false); return true; return true; }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove pseudo-code

Find neighbors

122

slide-123
SLIDE 123

public public boolean boolean remove(T item) { remove(T item) { Boolean snip; Boolean snip; while (true) { while (true) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if if ( (curr.key curr.key != key) { != key) { return return false false; ; } } else else { { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet(succ succ, , succ succ, false, , false, true); true); if (!snip) continue; if (!snip) continue; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, false, false); , false, false); return true; return true; }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove pseudo-code

She’s not there …

123

slide-124
SLIDE 124

public public boolean boolean remove(T item) { remove(T item) { Boolean snip; Boolean snip; while (true) { while (true) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if ( if (curr.key curr.key != key) { != key) { return false; return false; } else { } else { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet(succ succ, , succ succ, , false false, , true true); ); if (!snip) continue; if (!snip) continue; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, false, false); , false, false); return true; return true; }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove pseudo-code

Try to mark node as deleted

124

slide-125
SLIDE 125

public public boolean boolean remove(T item) { remove(T item) { Boolean snip; Boolean snip; while (true) { while (true) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if ( if (curr.key curr.key != key) { != key) { return false; return false; } else { } else { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet(succ succ, , succ succ, false, , false, true); true); if if (!snip) (!snip) continue continue; ; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, false, false); , false, false); return true; return true; }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove pseudo-code

If it doesn’t work, just retry, if it does, job essentially done

125

slide-126
SLIDE 126

public public boolean boolean remove(T item) { remove(T item) { Boolean snip; Boolean snip; while (true) { while (true) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if ( if (curr.key curr.key != key) { != key) { return false; return false; } else { } else { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet(succ succ, , succ succ, false, , false, true); true); if (!snip) continue; if (!snip) continue; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, , false false, , false false); ); return return true true; ; }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove pseudo-code

Try to advance reference (if we don’t succeed, someone else did or will).

a

126

slide-127
SLIDE 127

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove linearization points

public public boolean boolean remove(T item) { remove(T item) { Boolean Boolean snip; snip; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if if ( (curr.key curr.key != key) { != key) { return return false false; ; } } else else { { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet(succ succ, , succ succ, , false false true true); ); if if (!snip) (!snip) continue continue; ; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, , false false, , false false); ); return return true true; ; }}} }}}

127

slide-128
SLIDE 128

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove linearization points

public public boolean boolean remove(T item) { remove(T item) { Boolean Boolean snip; snip; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if if ( (curr.key curr.key != key) { != key) { return return false false; ; } } else else { { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet(succ succ, , succ succ, , false false true true); ); if if (!snip) (!snip) continue continue; ; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, , false false, , false false); ); return return true true; ; }}} }}}

Upon success

128

slide-129
SLIDE 129

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Remove linearization points

public public boolean boolean remove(T item) { remove(T item) { Boolean Boolean snip; snip; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if if ( (curr.key curr.key != key) { != key) { return return false false; ; } } else else { { Node Node succ succ = = curr.next.getReference curr.next.getReference(); (); snip = snip = curr.next.compareAndSet curr.next.compareAndSet(succ succ, , succ succ, , false false true true); ); if if (!snip) (!snip) continue continue; ; pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, , false false, , false false); ); return return true true; ; }}} }}}

When returning false

129

slide-130
SLIDE 130

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Add pseudo-code

public public boolean boolean add(T item) { add(T item) { boolean boolean splice; splice; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if if ( (curr.key curr.key == key) { == key) { return return false false; ; } } else else { { Node Node node node = = new new Node(item); Node(item); node.next node.next = = new new AtomicMarkableRef AtomicMarkableRef(curr curr, , false false); ); if if ( (pred.next.compareAndSet pred.next.compareAndSet(curr curr, node, , node, false false, , false false)) { )) {return true return true;} ;} }}} }}}

130

slide-131
SLIDE 131

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Add pseudo-code

public public boolean boolean add(T item) { add(T item) { boolean boolean splice; splice; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if ( if (curr.key curr.key == key) { == key) { return false; return false; } else { } else { Node Node node node = new Node(item); = new Node(item); node.next node.next = new = new AtomicMarkableRef AtomicMarkableRef(curr curr, false); , false); if ( if (pred.next.compareAndSet pred.next.compareAndSet(curr curr, node, false, , node, false, false)) {return true;} false)) {return true;} }}} }}}

Keep trying

131

slide-132
SLIDE 132

Add pseudo-code

public public boolean boolean add(T item) { add(T item) { boolean boolean splice; splice; while (true) { while (true) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if ( if (curr.key curr.key == key) { == key) { return false; return false; } else { } else { Node Node node node = new Node(item); = new Node(item); node.next node.next = new = new AtomicMarkableRef AtomicMarkableRef(curr curr, false); , false); if ( if (pred.next.compareAndSet pred.next.compareAndSet(curr curr, node, false, , node, false, false)) {return true;} false)) {return true;} }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find neighbors

132

slide-133
SLIDE 133

public boolean add(T item) { public boolean add(T item) { boolean splice; boolean splice; while (true) { while (true) { Window window = find(head, key); Window window = find(head, key); Node pred = window.pred, curr = window.curr; Node pred = window.pred, curr = window.curr; if if (curr.key == key) { (curr.key == key) { return return false false; ; } else { } else { Node node = new Node(item); Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, if (pred.next.compareAndSet(curr, node, false, false)) {return true;} false)) {return true;} }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Add pseudo-code

Item already there.

133

slide-134
SLIDE 134

public public boolean boolean add(T item) { add(T item) { boolean boolean splice; splice; while (true) { while (true) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if ( if (curr.key curr.key == key) { == key) { return false; return false; } else { } else { Node Node node node = = new new Node(item); Node(item); node.next node.next = = new new AtomicMarkableRef AtomicMarkableRef(curr curr, , false false); ); if ( if (pred.next.compareAndSet pred.next.compareAndSet(curr curr, node, false, , node, false, false)) {return true;} false)) {return true;} }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Add pseudo-code

create new node

134

slide-135
SLIDE 135

public boolean add(T item) { public boolean add(T item) { boolean splice; boolean splice; while (true) { while (true) { Window window = find(head, key); Window window = find(head, key); Node pred = window.pred, curr = window.curr; Node pred = window.pred, curr = window.curr; if (curr.key == key) { if (curr.key == key) { return false; return false; } else { } else { Node node = new Node(item); Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); node.next = new AtomicMarkableRef(curr, false); if if (pred.next.compareAndSet(curr, node, (pred.next.compareAndSet(curr, node, false false, , false false)) { )) {return true return true;} ;} }}} }}}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Add pseudo-code

Install new node, else retry loop

135

slide-136
SLIDE 136

Add linearization points

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public public boolean boolean add(T item) { add(T item) { boolean boolean splice; splice; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if if ( (curr.key curr.key == key) { == key) { return return false false; ; } } else else { { Node Node node node = = new new Node(item); Node(item); node.next node.next = = new new AtomicMarkableRef AtomicMarkableRef(curr curr, , false false); ); if if ( (pred.next.compareAndSet pred.next.compareAndSet(curr curr, node, , node, false false, , false false)) { )) {return true return true;} ;} }}} }}}

136

slide-137
SLIDE 137

Add linearization points

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public public boolean boolean add(T item) { add(T item) { boolean boolean splice; splice; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if if ( (curr.key curr.key == key) { == key) { return return false false; ; } } else else { { Node Node node node = = new new Node(item); Node(item); node.next node.next = = new new AtomicMarkableRef AtomicMarkableRef(curr curr, , false false); ); if if ( (pred.next.compareAndSet pred.next.compareAndSet(curr curr, node, , node, false false, , false false)) { )) {return true return true;} ;} }}} }}}

Upon success

137

slide-138
SLIDE 138

Add linearization points

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

public public boolean boolean add(T item) { add(T item) { boolean boolean splice; splice; while while ( (true true) { ) { Window Window window window = find(head, key); = find(head, key); Node Node pred pred = = window.pred window.pred, , curr curr = = window.curr window.curr; ; if if ( (curr.key curr.key == key) { == key) { return return false false; ; } } else else { { Node Node node node = = new new Node(item); Node(item); node.next node.next = = new new AtomicMarkableRef AtomicMarkableRef(curr curr, , false false); ); if if ( (pred.next.compareAndSet pred.next.compareAndSet(curr curr, node, , node, false false, , false false)) { )) {return true return true;} ;} }}} }}}

When returning false

138

slide-139
SLIDE 139

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Contains pseudo-code

public public boolean boolean contains(T item) { contains(T item) { boolean boolean marked; marked; int int key = key = item.hashCode item.hashCode(); (); Node Node curr curr = = this this.head .head; ; while while ( (curr.key curr.key < key) < key) curr curr = = curr.next curr.next; ; Node Node succ succ = = curr.next.get curr.next.get(marked); (marked); return return ( (curr.key curr.key == key == key && && !marked[0]) !marked[0]) } }

139

slide-140
SLIDE 140

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Contains pseudo-code

public public boolean boolean contains(T item) { contains(T item) { boolean boolean marked; marked; int int key = key = item.hashCode item.hashCode(); (); Node Node curr curr = = this this.head .head; ; while ( while (curr.key curr.key < key) < key) curr curr = = curr.next curr.next; ; Node Node succ succ = = curr.next.get curr.next.get(marked); (marked); return ( return (curr.key curr.key == key && !marked[0]) == key && !marked[0]) } }

Start at the head

140

slide-141
SLIDE 141

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Contains pseudo-code

public public boolean boolean contains(T item) { contains(T item) { boolean boolean marked; marked; int int key = key = item.hashCode item.hashCode(); (); Node Node curr curr = = this.head this.head; ; while while ( (curr.key curr.key < key) < key) curr curr = = curr.next curr.next; ; Node Node succ succ = = curr.next.get curr.next.get(marked); (marked); return ( return (curr.key curr.key == key && !marked[0]) == key && !marked[0]) } }

Search key range

141

slide-142
SLIDE 142

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Contains pseudo-code

public public boolean boolean contains(T item) { contains(T item) { boolean boolean marked; marked; int int key = key = item.hashCode item.hashCode(); (); Node Node curr curr = = this.head this.head; ; while ( while (curr.key curr.key < key) < key) curr curr = = curr.next curr.next; ; Node Node succ succ = = curr.next.get curr.next.get(marked); (marked); return ( return (curr.key curr.key == key && !marked[0]) == key && !marked[0]) } }

Traverse

142

slide-143
SLIDE 143

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Contains pseudo-code

public public boolean boolean contains(T item) { contains(T item) { boolean boolean marked; marked; int int key = key = item.hashCode item.hashCode(); (); Node Node curr curr = = this.head this.head; ; while ( while (curr.key curr.key < key) < key) curr curr = = curr.next curr.next; ; Node Node succ succ = = curr.next.get curr.next.get(marked); (marked); return return ( (curr.key curr.key == key == key && && !marked[0]) !marked[0]) } }

Return true if value found in a non-marked node

143

slide-144
SLIDE 144

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Contains linearization point

public public boolean boolean contains(T item) { contains(T item) { boolean boolean marked; marked; int int key = key = item.hashCode item.hashCode(); (); Node Node curr curr = = this this.head .head; ; while while ( (curr.key curr.key < key) < key) curr curr = = curr.next curr.next; ; Node Node succ succ = = curr.next.get curr.next.get(marked); (marked); return return ( (curr.key curr.key == key == key && && !marked[0]) !marked[0]) } }

144

slide-145
SLIDE 145

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Contains linearization point

public public boolean boolean contains(T item) { contains(T item) { boolean boolean marked; marked; int int key = key = item.hashCode item.hashCode(); (); Node Node curr curr = = this this.head .head; ; while while ( (curr.key curr.key < key) < key) curr curr = = curr.next curr.next; ; Node Node succ succ = = curr.next.get curr.next.get(marked); (marked); return return ( (curr.key curr.key == key == key && && !marked[0]) !marked[0]) } }

When returning true

145

slide-146
SLIDE 146

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Contains linearization point

public public boolean boolean contains(T item) { contains(T item) { boolean boolean marked; marked; int int key = key = item.hashCode item.hashCode(); (); Node Node curr curr = = this this.head .head; ; while while ( (curr.key curr.key < key) < key) curr curr = = curr.next curr.next; ; Node Node succ succ = = curr.next.get curr.next.get(marked); (marked); return return ( (curr.key curr.key == key == key && && !marked[0]) !marked[0]) } }

Linearization more complicated when returning false

146

slide-147
SLIDE 147

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

public public Window find(Node head, Window find(Node head, int int key) { key) { Node Node pred pred = null, = null, curr curr = null, = null, succ succ = null; = null; boolean boolean[] [] marked = { marked = {false false}; }; boolean boolean snip; snip; retry: retry: while while ( (true true) { ) { pred pred = head; = head; curr curr = = pred.next.getReference pred.next.getReference(); (); while while ( (true true) { ) { succ succ = = curr.next.get curr.next.get(marked); (marked); while while (marked[0]) { (marked[0]) { … … } }

if ( if (curr.key curr.key >= key) >= key) return new Window( return new Window(pred pred, , curr curr); ); pred pred = = curr curr; ; curr curr = = succ succ; ; } }

}} }}

147

slide-148
SLIDE 148

public public Window find(Node head, Window find(Node head, int int key) { key) { Node Node pred pred = null, = null, curr curr = null, = null, succ succ = null; = null; boolean boolean[] [] marked = { marked = {false false}; }; boolean boolean snip; snip; retry: while (true) { retry: while (true) { pred pred = head; = head; curr curr = = pred.next.getReference pred.next.getReference(); (); while (true) { while (true) { succ succ = = curr.next.get curr.next.get(marked); (marked); while (marked[0]) { while (marked[0]) { … … } }

if ( if (curr.key curr.key >= key) >= key) return new Window( return new Window(pred pred, , curr curr); ); pred pred = = curr curr; ; curr curr = = succ succ; ; } }

}} }}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

Start search for key at the head

148

slide-149
SLIDE 149

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

public Window find(Node head, int key) { public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; boolean[] marked = {false}; boolean snip; retry: retry: while while ( (true true) { ) { pred = head; pred = head; curr = pred.next.getReference(); curr = pred.next.getReference(); while (true) { while (true) { succ = curr.next.get(marked); succ = curr.next.get(marked); while (marked[0]) { while (marked[0]) { … … } }

if (curr.key >= key) if (curr.key >= key) return new Window(pred, curr); return new Window(pred, curr); pred = curr; pred = curr; curr = succ; curr = succ; } }

}} }}

If list changes while traversed, start over. Lock-Free because we start over only if someone else makes progress

149

slide-150
SLIDE 150

public Window find(Node head, public Window find(Node head, int int key) { key) { Node Node pred pred = null, = null, curr curr = null, = null, succ succ = null; = null; boolean boolean[] marked = {false}; [] marked = {false}; boolean boolean snip; snip; retry: while (true) { retry: while (true) { pred pred = head; = head; curr curr = = pred.next.getReference pred.next.getReference(); (); while (true) { while (true) { succ succ = = curr.next.get curr.next.get(marked); (marked); while (marked[0]) { while (marked[0]) { … … } }

if ( if (curr.key curr.key >= key) >= key) return new Window( return new Window(pred pred, , curr curr); ); pred pred = = curr curr; ; curr curr = = succ succ; ; } }

}} }}

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

Start looking from head

150

slide-151
SLIDE 151

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

public Window find(Node head, public Window find(Node head, int int key) { key) { Node Node pred pred = null, = null, curr curr = null, = null, succ succ = null; = null; boolean boolean[] marked = {false}; [] marked = {false}; boolean boolean snip; snip; retry: while (true) { retry: while (true) { pred pred = head; = head; curr curr = = pred.next.getReference pred.next.getReference(); (); while while ( (true true) { ) { succ succ = = curr.next.get curr.next.get(marked); (marked); while while (marked[0]) { (marked[0]) { … … } }

if if ( (curr.key curr.key >= key) >= key) return return new Window( new Window(pred pred, , curr curr); ); pred pred = = curr curr; ; curr curr = = succ succ; ; } }

}} }}

Move down the list

151

slide-152
SLIDE 152

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

public Window find(Node head, public Window find(Node head, int int key) { key) { Node Node pred pred = null, = null, curr curr = null, = null, succ succ = null; = null; boolean boolean[] marked = {false}; [] marked = {false}; boolean boolean snip; snip; retry: while (true) { retry: while (true) { pred pred = head; = head; curr curr = = pred.next.getReference pred.next.getReference(); (); while (true) { while (true) { succ succ = = curr.next.get curr.next.get(marked); (marked); while (marked[0]) { while (marked[0]) { … … } }

if ( if (curr.key curr.key >= key) >= key) return new Window( return new Window(pred pred, , curr curr); ); pred pred = = curr curr; ; curr curr = = succ succ; ; } }

}} }}

Get ref to successor and current deleted bit

152

slide-153
SLIDE 153

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

public Window find(Node head, int key) { public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; boolean[] marked = {false}; boolean snip; retry: while (true) { retry: while (true) { pred = head; pred = head; curr = pred.next.getReference(); curr = pred.next.getReference(); while (true) { while (true) { succ = curr.next.get(marked); succ = curr.next.get(marked); while while (marked[0]) { (marked[0]) { … … } }

if (curr.key >= key) if (curr.key >= key) return new Window(pred, curr); return new Window(pred, curr); pred = curr; pred = curr; curr = succ; curr = succ; } }

}} }}

Try to remove deleted nodes in path…code details soon

153

slide-154
SLIDE 154

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

public Window find(Node head, public Window find(Node head, int int key) { key) { Node Node pred pred = null, = null, curr curr = null, = null, succ succ = null; = null; boolean boolean[] marked = {false}; [] marked = {false}; boolean boolean snip; snip; retry: while (true) { retry: while (true) { pred pred = head; = head; curr curr = = pred.next.getReference pred.next.getReference(); (); while (true) { while (true) { succ succ = = curr.next.get curr.next.get(marked); (marked); while (marked[0]) { while (marked[0]) { … … } }

if if ( (curr.key curr.key >= key) >= key) return return new Window( new Window(pred pred, , curr curr); ); pred pred = = curr curr; ; curr curr = = succ succ; ; } }

}} }}

If curr key that is greater or equal, return pred and curr

154

slide-155
SLIDE 155

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

public Window find(Node head, int key) { public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; boolean[] marked = {false}; boolean snip; retry: while (true) { retry: while (true) { pred = head; pred = head; curr = pred.next.getReference(); curr = pred.next.getReference(); while (true) { while (true) { succ = curr.next.get(marked); succ = curr.next.get(marked); while (marked[0]) { while (marked[0]) { … … } }

if (curr.key >= key) if (curr.key >= key) return new Window(pred, curr); return new Window(pred, curr); pred = curr; pred = curr; curr = succ; curr = succ; } }

}} }}

Otherwise advance window and loop again

155

slide-156
SLIDE 156

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

retry: retry: while while ( (true true) { ) { … … while while (marked[0]) { (marked[0]) { snip = snip = pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, , false false, , false false); ); if if (!snip) (!snip) continue continue retry; retry; curr curr = = succ succ; ; succ succ = = curr.next.get curr.next.get(marked); (marked); } } … …

156

slide-157
SLIDE 157

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

retry: while (true) { retry: while (true) { … … while while (marked[0]) { (marked[0]) { snip = snip = pred.next.compareAndSet pred.next.compareAndSet(curr curr, , succ succ, false, false); , false, false); if (!snip) continue retry; if (!snip) continue retry; curr curr = = succ succ; ; succ succ = = curr.next.get curr.next.get(marked); (marked); } } … …

If current node is marked

157

slide-158
SLIDE 158

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

retry: while (true) { retry: while (true) { … … while (marked[0]) { while (marked[0]) { snip = pred.next.compareAndSet(curr, snip = pred.next.compareAndSet(curr, succ, succ, false false, , false false); ); if (!snip) continue retry; if (!snip) continue retry; curr = succ; curr = succ; succ = curr.next.get(marked); succ = curr.next.get(marked); } } … …

Try to snip out node

158

slide-159
SLIDE 159

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

retry: while (true) { retry: while (true) { … … while (marked[0]) { while (marked[0]) { snip = pred.next.compareAndSet(curr, snip = pred.next.compareAndSet(curr, succ, false, false); succ, false, false); if if (!snip) (!snip) continue continue retry; retry; curr = succ; curr = succ; succ = curr.next.get(marked); succ = curr.next.get(marked); } } … …

if predecessor’s next field changed, retry whole traversal

159

slide-160
SLIDE 160

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find pseudo-code

retry: while (true) { retry: while (true) { … … while (marked[0]) { while (marked[0]) { snip = pred.next.compareAndSet(curr, snip = pred.next.compareAndSet(curr, succ, false, false); succ, false, false); if (!snip) continue retry; if (!snip) continue retry; curr = succ; curr = succ; succ = curr.next.get(marked); succ = curr.next.get(marked); } } … …

Otherwise move on to check if next node deleted

160

slide-161
SLIDE 161

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find linearization points

public public Window find(Node head, Window find(Node head, int int key) { key) { Node Node pred pred = null, = null, curr curr = null, = null, succ succ = null; = null; boolean boolean[] [] marked = { marked = {false false}; }; boolean boolean snip; snip; retry: retry: while while ( (true true) { ) { pred pred = head; = head; curr curr = = pred.next.getReference pred.next.getReference(); (); while while ( (true true) { ) { succ succ = = curr.next.get curr.next.get(marked); (marked); while while (marked[0]) { (marked[0]) { … … } }

if ( if (curr.key curr.key >= key) >= key) return new Window( return new Window(pred pred, , curr curr); ); pred pred = = curr curr; ; curr curr = = succ succ; ; } }

}} }}

161

slide-162
SLIDE 162

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Find linearization points

public public Window find(Node head, Window find(Node head, int int key) { key) { Node Node pred pred = null, = null, curr curr = null, = null, succ succ = null; = null; boolean boolean[] [] marked = { marked = {false false}; }; boolean boolean snip; snip; retry: retry: while while ( (true true) { ) { pred pred = head; = head; curr curr = = pred.next.getReference pred.next.getReference(); (); while while ( (true true) { ) { succ succ = = curr.next.get curr.next.get(marked); (marked); while while (marked[0]) { (marked[0]) { … … } }

if ( if (curr.key curr.key >= key) >= key) return new Window( return new Window(pred pred, , curr curr); ); pred pred = = curr curr; ; curr curr = = succ succ; ; } }

}} }}

Last read of non-marked node

162

slide-163
SLIDE 163

Talk Outline

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

n Preliminaries n A simple lock-free stack algorithm

  • Linearizability

n Michael & Sco] queue algorithm n The Harris-Michael linked list algorithm n EliminaGon-based stack n Discussion & conclusions

163

slide-164
SLIDE 164

IBM/Treiber algorithm's disadvantage

Top

val next val next

val next

Is this inherent?

Has a sequenGal bo]leneck

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 164

slide-165
SLIDE 165

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Key idea:

pairs of push/pop operaGons may collide and eliminate each other without accessing a central stack.

Top

val next val next

val next

Central stack collision array

An elimination-backoff stack (Hendler, Shavit & Yerushalmi, 2004)

165

slide-166
SLIDE 166

An elimination-backoff stack Collision scenarios

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Collision array

push pop push push Top

val next val next

val next

Central stack

pop push

166

slide-167
SLIDE 167

An elimination-backoff stack Elimination challenges

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Collision array

push pop push push Top

val next val next

val next

Central stack

pop push

q Prevent eliminaGon chains: e.g., A collides with B, which collides with C… q Prevent race condiGons: e.g., A collides with B, which is already gone…

167

slide-168
SLIDE 168

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Each stack operation is represented by a ThreadInfo structure struct ThreadInfo { id ;the identifier of the thread performing the operation

  • p ;a PUSH/POP opcode

cell ;a cell structure spin ; duration to spin } Struct cell { ;a representation of stack item as in Treiber pnext ;pointer to the next cell pdata ;stack item}

Location array

p1 p2 p3 pn

Thread Info Thread Info

p4

collision array

p1 p7

Data structures

168

slide-169
SLIDE 169

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Pseudo-code: main loop

void EStack(ThreadInfo *p) 1. Do forever 2. stack: if (TryPerformStackOp(p)==TRUE) return ;Aapply op to central stack 3. location[mypid]=p ;announce arrival 4. pos=GetPosition(p) ;get a random position at the collision array 5. him=collision[pos] ;read current value of that position 6. while (!compare&swap(&collision[pos],him,mypid);try to write own ID 7. him=collision[pos] ;continue till success 8. if (him != empty) ;if read an ID of another thread 9. q=location[him] ;read a pointer to the other thread’s info 10. if (q!=NULL && q->id=him && q->op != p->op) ;if may collide 11. if (compare&swap(&location[mypid],p,NULL) ; prevent unwanted collisions 12. if (TryCollision(p,q)==true) ;if collided successfully 13. return ;return code is already at ThreadInfo structure 14. else goto stack ;try to apply operation to central stack 15. else FinishCollision(p), return ;extract information and finish 16. delay (p->spin) ;Wait for other thread to collide with me 17. if (!compare&swap(&location[mypid],p,NULL) ;if someone collided with me 18. FinishCollision(p), return;Extract information and finish

169

slide-170
SLIDE 170

Pseudo-code: TryCollision,FinishCollision

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

void TryCollision(ThreadInfo* p, ThreadInfo *q) 1. if (p->op==PUSH) 2. if (compare&swap(&location[him],q,p)) ;give my record to other thread 3. return TRUE 4. else 5. return FALSE 6. else 7. if (compare&swap(&location[him],q,NULL)) 8. p->cell=q->cell ;get pointer to PUSH operation’s cell 9. return TRUE 10. else 11. return FALSE void FinishCollision(ThreadInfo* p) 1. if (p->op==POP) 2. p->pcell=location[mypid]->pcell 3. location[mypid]=NULL

170

slide-171
SLIDE 171

Linearization points

If operaGon completed on central stack, same as Treiber Otherwise:

void TryCollision(ThreadInfo* p, ThreadInfo *q) 1. if (p->op==PUSH) 2. if (compare&swap(&location[him],q,p)) ;give my record to other thread 3. return TRUE 4. else 5. return FALSE 6. else 7. if (compare&swap(&location[him],q,NULL)) 8. p->cell=q->cell ;get pointer to PUSH operation’s cell 9. return TRUE 10. else 11. return FALSE

Upon success Upon success

Colliding operations-pair linearized together – push before pop.

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 171

slide-172
SLIDE 172

Adaptive elimination backoff

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

q Handle load by backoff in space and Gme

  • E.g., exponenGal backoff

q Decisions made locally, per thread q Array-width/waiGng-period decreased when:

  • Many `no-show’ unsuccessful collision a]empts

q Array-width/waiGng-period increased when:

  • Many `high-contenGon’ unsuccessful collision a]empts

Collision array

Thread A Thread B

172

slide-173
SLIDE 173

n Preliminaries n A simple lock-free stack algorithm

  • Linearizability

n Michael & Sco] queue algorithm n The Harris-Michael linked list algorithm n EliminaGon-based stack n Discussion & conclusions

Talk Outline

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 173

slide-174
SLIDE 174

The notion of helping

q Lock-free algorithms may be made wait-free using the noGon of helping q Used for wait-free data-structures and universal construcGons q Formal definiGons a]empted only recently

  • Used for proving complexity & impossibility results

Censor-Hillel, Petrank and Timnat, PODC, 2015 Attiya, Castañeda and Hendler , OPODIS, 2015

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 174

slide-175
SLIDE 175

Informal notions of `helping’ (1)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 175

slide-176
SLIDE 176

Informal notions of `helping’ (2)

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 176

slide-177
SLIDE 177

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Conclusions

q Lock-free algorithms may be oPen wait-free in pracGce q Require strong synchronizaGon operaGons q OPen difficult to devise q Guarantee global progress in the face of thread failures

177

slide-178
SLIDE 178

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

slide-179
SLIDE 179

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

Exercise formulation The swap and fetch-and-inc operations

atomically

t read from c c c + 1 return t

fetch-and-inc(c)

atomically

t read from var var new return t

swap(var,new)

179

slide-180
SLIDE 180

Exercise formulation A lock-free queue algorithm

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 180

slide-181
SLIDE 181

Exercise formulation The questions

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017

a. Describe a detailed execuGon showing that the algorithm is not linearizable.

  • b. Present a small change to the algorithm to make it linearizable

(and sGll lock-free).

181

slide-182
SLIDE 182

Danny Hendler, SPTCC summer school, Saint-Petersburg, 2017 182