SlideShare a Scribd company logo
ABA Problem

Dr. C.V. Suresh Babu
Introduction
• Queues are everywhere in parallel applications
and operating systems
• Many researchers have proposed queues
–
–
–
–

Hwang and Briggs
Gottlieb
Massalin
Et al. etc…

• Queue performance can be critical to operating
system performance
– Scheduling Queues
– Free memory lists
– Many other critical kernel operations
Concurrent FIFO Queue algorithms
• Blocking algorithms risk performance
degradation
– A process can be delayed or halted at inopportune
moments
• Scheduling preemption
• Page faults
• Cache misses

– Slow processes can prevent faster ones from
completing indefinitely

• Non-Blocking algorithms must solve the ABA
problem
– During contention, some process will complete
within a given number of operations
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {
loop
value = SM
newVal = value +1
Stack Data = d
CAS(&SM, value, newVal)
break

Stack

SM
5

…
x

time

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {
loop

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X
CAS(&SM,value,newVal)

value = SM
newVal = value +1
Stack Data = d
CAS(&SM, value, newVal)
break

Stack

SM
4

…
x

time
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {
loop

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X
CAS(&SM,value,newVal)

value = SM

v2 = x

newVal = value +1
Stack Data = d
CAS(&SM, value, newVal)
break

Stack

SM
4

…
x

time
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {
loop

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X
CAS(&SM,value,newVal)

value = SM

v2 = x

newVal = value +1

Push(z)

Stack Data = d
CAS(&SM, value, newVal)
break

Stack

SM
4

…
x

time
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {
loop

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X
CAS(&SM,value,newVal)

value = SM

v2 = x

newVal = value +1
Stack Data = d

Push(z)

CAS(&SM, value, newVal)

value = 4

break

Stack

SM
4

…
x

time
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {
loop

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X
CAS(&SM,value,newVal)

value = SM

v2 = x

newVal = value +1
Stack Data = d

Push(z)

CAS(&SM, value, newVal)

value = 4

break

newVal=5

Stack

SM
4

…
x

time
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {
loop

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X
CAS(&SM,value,newVal)

value = SM

v2 = x

newVal = value +1
Stack Data = d

Push(z)

CAS(&SM, value, newVal)

value = 4

break

newVal=5

Stack

CAS(&SM,value,newVal)

SM
5

…
z

time
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X

loop

CAS(&SM,value,newVal)

value = SM

v2 = x

newVal = value +1
Stack Data = d

Push(z)

CAS(&SM, value, newVal)

value = 4

break

newVal=5

Stack

CAS(&SM,value,newVal)
CAS(&SM,value,newVal)

SM
5

…
z

time
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X

loop

CAS(&SM,value,newVal)

value = SM

v2 = x

newVal = value +1
Stack Data = d

Push(z)

CAS(&SM, value, newVal)

value = 4

break

newVal=5

Stack

CAS(&SM,value,newVal)
CAS(&SM,value,newVal)
v1=x

SM
4

…
z

time
ABA problem

Pop () {
loop
value = SM
newVal = value -1

THREAD1

THREAD2

data = Stack Data
CAS(&SM, value, newVal)

v1=Pop()
value = 5

Push (d) {

newVal = 4

data=X

return data

value = 5

newVal = 4

break

v2=Pop()

data=X

loop

CAS(&SM,value,newVal)

value = SM

v2 = x

newVal = value +1
Stack Data = d

Push(z)

CAS(&SM, value, newVal)

value = 4

break

newVal=5

Stack

CAS(&SM,value,newVal)
CAS(&SM,value,newVal)
v1=x

SM
4

…
z

CAS should fail but it succeeds
time

Thread1 has Thread2’s data
Solutions for ABA problem
Cache Kernel
• Add version # to data structures
• Increment # during every CAS instruction
LL/SC
• Fail if Cache Line has been written to
Solution for ABA problem

Pop () {
loop
value = SM

newVal = value -1

THREAD1

THREAD2

data = Stack Data
DCAS(&SM, value,

v1=Pop()
value = 5

return data
Push (d) {

newVal = 4

data=X

break

value = 5

newVal = 4

<ver++,newVal>)

v2=Pop()

data=X

loop

DCAS(&SM,value,ver,newVal)

value = SM

v2 = x

newVal = value +1
Stack Data = d

Push(z)

DCAS(&SM, value,

value = 4

<ver++,newVal>)

newVal=5

Stack

break

DCAS(&SM,value,ver,newVal)
DCAS(&SM,value,ver,newVal)
Will not incorrectly succeed

SM
5

…
z

(ver != ver+2)

time
Solution for ABA problem

Pop () {
loop
value = SM

newVal = value -1

THREAD1

THREAD2

data = Stack Data
DCAS(&SM, value,

v1=Pop()
value = 5

return data
Push (d) {

newVal = 4

data=Z

break

value = 5

newVal = 4

<ver++,newVal>)

v2=Pop()

data=X

loop

DCAS(&SM,value,ver,newVal)

value = SM

v2 = x

newVal = value +1
Stack Data = d

Push(z)

DCAS(&SM, value,

value = 4

<ver++,newVal>)

newVal=5

Stack

break

DCAS(&SM,value,ver,newVal)
DCAS(&SM,value,ver,newVal)
Will not incorrectly succeed

SM
4

(ver != ver+2)

…
time

V1 = Z
Correctness Properties
1.
2.
3.
4.
5.

The linked list is always connected
Nodes only inserted after the last node
Nodes only deleted from beginning
Head always points to the first node
Tail always points to a node in the list
Queue # 1
• Non-Blocking Concurrent Queue
– enqueue()
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
node–>next.ptr = NULL
loop
tail = Q–>Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

“enqueue(myQueue, D1)”
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

D1
[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

D1
[NULL]

[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

D1
[NULL]

tail

[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

D1
[NULL]

tail

next

[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

D1
[NULL]

tail

next

[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS( &tail.ptr–>next, next,
<node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

D1
[NULL]

tail

next

[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

D1

+1
[NULL]

tail

next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

D1

+1
[NULL]

tail

next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

enqueue(myQueue, D1)
enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
+1
if tail == Q–>Tail
if next.ptr == NULL
if CAS(&tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
endif
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
endif
endif
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

D1

+1
[NULL]
Concurrent enqueues
• Suppose two processes call enqueue() at
the same time
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS( &tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
Process 1
endif
Enqueue(myQueue, ABC)
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
ABC
endif
endif
[NULL]
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

tail

next

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

D1
[NULL]

Process 2
Enqueue(myQueue, XYZ)

XYZ
[NULL]

tail

next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS( &tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
Process 1
endif
Enqueue(myQueue, ABC)
else
CAS(&Q–>Tail, tail, <next.ptr,
tail.count+1>)
ABC
endif
endif
[NULL]
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

tail

next

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

D1

+1
XYZ
[NULL]

Process 2
Enqueue(myQueue, XYZ)

tail
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

enqueue(Q: pointer to queue t, value: data type)
node = new node()
node–>value = value
Head
node–>next.ptr = NULL
loop
tail = Q–>Tail
Tail
next = tail.ptr–>next
if tail == Q–>Tail
if next.ptr == NULL
if CAS( &tail.ptr–>next,
next, <node, next.count+1>)
myQueue
break
Process 1
endif
Enqueue(myQueue, ABC)
else
CAS( &Q–>Tail, tail,
<next.ptr, tail.count+1>)
ABC
endif
endif
[NULL]
endloop
CAS(&Q–>Tail, tail, <node, tail.count+1>)

tail

next

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

D1

+1
XYZ
[NULL]

Process 2
Enqueue(myQueue, XYZ)

tail
Queue #1 (cont.)
• Non-Blocking Concurrent Queue
– dequeue()
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

“dequeue(myQueue, pvalue)”

dequeue(Q: ptr to queue t, pvalue: ptr to data
type):bool
loop
Head
head = Q–>Head
tail = Q–>Tail
next = head–>next
if head == Q–>Head
Tail
if head.ptr == tail.ptr
if next.ptr == NULL
return FALSE
endif
myQueue
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head,
head, <next.ptr, head.count+1>)
break
endif
endif
endif
endloop
free(head.ptr)

D1
[NULL]
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

dequeue(myQueue, pvalue)

dequeue(Q: ptr to queue t, pvalue: ptr to data
type):bool
loop
Head
head = Q–>Head
tail = Q–>Tail
next = head–>next
if head == Q–>Head
Tail
if head.ptr == tail.ptr
if next.ptr == NULL
return FALSE
endif
myQueue
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head,
head, <next.ptr, head.count+1>)
break
endif
endif
endif
endloop
free(head.ptr)

D1
[NULL]

head

tail
next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

dequeue(myQueue, pvalue)

dequeue(Q: ptr to queue t, pvalue: ptr to data
type):bool
loop
Head
head = Q–>Head
tail = Q–>Tail
next = head–>next
if head == Q–>Head
Tail
if head.ptr == tail.ptr
if next.ptr == NULL
return FALSE
endif
myQueue
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head,
head, <next.ptr, head.count+1>)
break
endif
endif
endif
endloop
free(head.ptr)

D1
[NULL]

head

tail
next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

dequeue(myQueue, pvalue)

dequeue(Q: ptr to queue t, pvalue: ptr to data
type):bool
loop
Head
head = Q–>Head
tail = Q–>Tail
next = head–>next
if head == Q–>Head
Tail
if head.ptr == tail.ptr
if next.ptr == NULL
return FALSE
endif
myQueue
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head,
head, <next.ptr, head.count+1>)
break
endif
endif
endif
endloop
free(head.ptr)

D1
[NULL]

head

tail
next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

dequeue(myQueue, pvalue)

dequeue(Q: ptr to queue t, pvalue: ptr to data
type):bool
loop
Head
head = Q–>Head
tail = Q–>Tail
next = head–>next
if head == Q–>Head
Tail
if head.ptr == tail.ptr
if next.ptr == NULL
return FALSE
endif
myQueue
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head, head,
<next.ptr, head.count+1>)
break
endif
endif
endif
endloop
free(head.ptr)

D1
[NULL]

head

tail
next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

dequeue(myQueue, pvalue)

dequeue(Q: ptr to queue t, pvalue: ptr to data
type):bool
loop
Head
head = Q–>Head
+1
tail = Q–>Tail
next = head–>next
if head == Q–>Head
Tail
if head.ptr == tail.ptr
if next.ptr == NULL
return FALSE
endif
myQueue
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head, head,
<next.ptr, head.count+1>)
break
endif
endif
endif
endloop
free(head.ptr)

D1
[NULL]

head

tail
next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

dequeue(myQueue, pvalue)

dequeue(Q: ptr to queue t, pvalue: ptr to data
type):bool
loop
Head
head = Q–>Head
+1
tail = Q–>Tail
next = head–>next
if head == Q–>Head
Tail
if head.ptr == tail.ptr
if next.ptr == NULL
return FALSE
endif
myQueue
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head, head,
<next.ptr, head.count+1>)
break
endif
endif
endif
endloop
free(head.ptr)

D1
[NULL]

head

tail
next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

dequeue(myQueue, pvalue)

dequeue(Q: ptr to queue t, pvalue: ptr to data
type):bool
loop
Head
head = Q–>Head
+1
tail = Q–>Tail
next = head–>next
if head == Q–>Head
Tail
if head.ptr == tail.ptr
if next.ptr == NULL
return FALSE
endif
myQueue
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head, head,
<next.ptr, head.count+1>)
break
endif
endif
endif
endloop
free(head.ptr)

D1
[NULL]

head

tail
next
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node

dequeue(myQueue, pvalue)

dequeue(Q: ptr to queue t, pvalue: ptr to data
type):bool
loop
Head
head = Q–>Head
+1
tail = Q–>Tail
next = head–>next
if head == Q–>Head
Tail
if head.ptr == tail.ptr
if next.ptr == NULL
return FALSE
endif
myQueue
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head, head,
<next.ptr, head.count+1>)
break
endif
endif
endif
endloop
free(head.ptr)

D1
[NULL]
Concurrent dequeues
• Suppose two processes call dequeue() at
the same time
struct pointer_t {
node_t * ptr
uint count
}

struct node_t {
data_type value
pointer_t next
}

struct queue_t {
pointer_t Head
pointer_t Tail
}

dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool
loop
head = Q–>Head
Head
tail = Q–>Tail
next = head–>next
if head == Q–>Head
if head.ptr == tail.ptr
Tail
if next.ptr == NULL
return FALSE
endif
CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>)
else
# Read value before CAS, otherwise another
# dequeue might free the next node
*pvalue = next.ptr–>value
if CAS ( &Q–>Head,head, <next.ptr, head.count+1>)
break
endif
“dequeue(myQueue,
endif
endif
endloop
free(head.ptr)
return TRUE

D1
[NULL]

pvalue)”
Queue #2
• Two-lock Concurrent Queue
struct node_t {
data_type value
node_t * next
}

struct queue_t {
pointer_t Head
pointer_t Tail
lock_type H_lock
lock_type T_lock
}

initialize(Q: pointer to queue t)
node = new node()
node–>next.ptr = NULL
Q–>Head = Q–>Tail = node
Q–>H lock = Q–>T lock = FREE

dequeue(Q: pointer to queue t, pvalue: pointer to data type): boolean
lock(&Q–>H lock)
node = Q–>Head
new head = node–>next
if new head == NULL
enqueue(Q: pointer to queue t, value: data type)
unlock(&Q–>H lock)
node = new node()
return FALSE
node–>value = value
endif
node–>next.ptr = NULL
*pvalue = new head–>value
lock(&Q–>T lock)
Q–>Head = new head
Q–>Tail–>next = node
unlock(&Q–>H lock)
Q–>Tail = node
free(node)
unlock(&Q–>T lock)
return TRUE

• Algorithms have same general structure only different
data types
• No loops, ‘busy waiting’ instead
• Only dequeues access Head Lock
• Only enqueues access Tail Lock
Performance Parameters
• Net execution time for one million
enqueue/dequeue pairs
• 12-processor Silicon Graphics Challenge
multiprocessor
• Algorithms compiled with using highest
optimization level
• Including many hand optimizations
Dedicated multiprocessor

Multiprogrammed system with 3
processes per processor

Multiprogrammed system with 2
processes per processor
Conclusion
• NBS clear winner for multiprocessor
multiprogrammed systems
• Above 5 processors, use the new nonblocking queue
• If hardware only supports test-and-set use
two lock queue
• For two or less processors use a single
lock algorithm for queues

More Related Content

What's hot

Process synchronization
Process synchronizationProcess synchronization
Process synchronization
Syed Hassan Ali
 
Spiral model
Spiral modelSpiral model
Spiral model
Noraphyusin
 
Mail Server Project Report
Mail Server Project ReportMail Server Project Report
Mail Server Project Report
Kavita Sharma
 
Semaphore
SemaphoreSemaphore
Semaphore
Arafat Hossan
 
Debugging by induction
Debugging by inductionDebugging by induction
Debugging by induction
Waqar Ali
 
Al Qur’an as A Media of Journalism for Da’wah
Al Qur’an as A Media of Journalism for Da’wahAl Qur’an as A Media of Journalism for Da’wah
Al Qur’an as A Media of Journalism for Da’wah
iosrjce
 
Chat Application [Full Documentation]
Chat Application [Full Documentation]Chat Application [Full Documentation]
Chat Application [Full Documentation]
Rajon
 
Online Quiz System Project Report
Online Quiz System Project Report Online Quiz System Project Report
Online Quiz System Project Report
Kishan Maurya
 
Waterfall model ppt final
Waterfall model ppt  finalWaterfall model ppt  final
Waterfall model ppt final
shiva krishna
 
Chat server nitish nagar
Chat server nitish nagarChat server nitish nagar
Chat server nitish nagar
Nitish Nagar
 
Single Pass Assembler
Single Pass AssemblerSingle Pass Assembler
Single Pass Assembler
Satyamevjayte Haxor
 
Software Development Life Cycle
Software Development Life CycleSoftware Development Life Cycle
Facts finding techniques in Database
Facts finding techniques in Database Facts finding techniques in Database
Facts finding techniques in Database
Afrasiyab Haider
 
Review on Whatsapp's End to End encryption and Facebook integration
Review on Whatsapp's End to End encryption and Facebook integrationReview on Whatsapp's End to End encryption and Facebook integration
Review on Whatsapp's End to End encryption and Facebook integration
Govindarrajan NV
 
Disk Scheduling Algorithm in Operating System
Disk Scheduling Algorithm in Operating SystemDisk Scheduling Algorithm in Operating System
Disk Scheduling Algorithm in Operating System
Meghaj Mallick
 
Court Case Management System
Court Case Management SystemCourt Case Management System
Court Case Management System
Lahiru Manchanayake
 
Railway management system, database mini project
Railway management system, database mini projectRailway management system, database mini project
Railway management system, database mini project
shashank reddy
 
Operating system critical section
Operating system   critical sectionOperating system   critical section
Operating system critical section
Harshana Madusanka Jayamaha
 
Evolution of os
Evolution of osEvolution of os
Evolution of os
janani thirupathi
 
Process management in os
Process management in osProcess management in os
Process management in os
Miong Lazaro
 

What's hot (20)

Process synchronization
Process synchronizationProcess synchronization
Process synchronization
 
Spiral model
Spiral modelSpiral model
Spiral model
 
Mail Server Project Report
Mail Server Project ReportMail Server Project Report
Mail Server Project Report
 
Semaphore
SemaphoreSemaphore
Semaphore
 
Debugging by induction
Debugging by inductionDebugging by induction
Debugging by induction
 
Al Qur’an as A Media of Journalism for Da’wah
Al Qur’an as A Media of Journalism for Da’wahAl Qur’an as A Media of Journalism for Da’wah
Al Qur’an as A Media of Journalism for Da’wah
 
Chat Application [Full Documentation]
Chat Application [Full Documentation]Chat Application [Full Documentation]
Chat Application [Full Documentation]
 
Online Quiz System Project Report
Online Quiz System Project Report Online Quiz System Project Report
Online Quiz System Project Report
 
Waterfall model ppt final
Waterfall model ppt  finalWaterfall model ppt  final
Waterfall model ppt final
 
Chat server nitish nagar
Chat server nitish nagarChat server nitish nagar
Chat server nitish nagar
 
Single Pass Assembler
Single Pass AssemblerSingle Pass Assembler
Single Pass Assembler
 
Software Development Life Cycle
Software Development Life CycleSoftware Development Life Cycle
Software Development Life Cycle
 
Facts finding techniques in Database
Facts finding techniques in Database Facts finding techniques in Database
Facts finding techniques in Database
 
Review on Whatsapp's End to End encryption and Facebook integration
Review on Whatsapp's End to End encryption and Facebook integrationReview on Whatsapp's End to End encryption and Facebook integration
Review on Whatsapp's End to End encryption and Facebook integration
 
Disk Scheduling Algorithm in Operating System
Disk Scheduling Algorithm in Operating SystemDisk Scheduling Algorithm in Operating System
Disk Scheduling Algorithm in Operating System
 
Court Case Management System
Court Case Management SystemCourt Case Management System
Court Case Management System
 
Railway management system, database mini project
Railway management system, database mini projectRailway management system, database mini project
Railway management system, database mini project
 
Operating system critical section
Operating system   critical sectionOperating system   critical section
Operating system critical section
 
Evolution of os
Evolution of osEvolution of os
Evolution of os
 
Process management in os
Process management in osProcess management in os
Process management in os
 

Similar to ABA Problem

Rewriting Java In Scala
Rewriting Java In ScalaRewriting Java In Scala
Rewriting Java In Scala
Skills Matter
 
Queue Data Structure (w/ php egs)
Queue Data Structure (w/ php egs)Queue Data Structure (w/ php egs)
Queue Data Structure (w/ php egs)
Roman Rodomansky
 
A bit about Scala
A bit about ScalaA bit about Scala
A bit about Scala
Vladimir Parfinenko
 
Monadologie
MonadologieMonadologie
Monadologie
league
 
An Introduction to Higher Order Functions in Spark SQL with Herman van Hovell
An Introduction to Higher Order Functions in Spark SQL with Herman van HovellAn Introduction to Higher Order Functions in Spark SQL with Herman van Hovell
An Introduction to Higher Order Functions in Spark SQL with Herman van Hovell
Databricks
 
Michal Malohlava presents: Open Source H2O and Scala
Michal Malohlava presents: Open Source H2O and Scala Michal Malohlava presents: Open Source H2O and Scala
Michal Malohlava presents: Open Source H2O and Scala
Sri Ambati
 
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and SparkCrystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
Jivan Nepali
 
Spark workshop
Spark workshopSpark workshop
Spark workshop
Wojciech Pituła
 
Introduction to Machine Learning
Introduction to Machine LearningIntroduction to Machine Learning
Introduction to Machine Learning
Big_Data_Ukraine
 
Perl6 a whistle stop tour
Perl6 a whistle stop tourPerl6 a whistle stop tour
Perl6 a whistle stop tour
Simon Proctor
 
Perl6 a whistle stop tour
Perl6 a whistle stop tourPerl6 a whistle stop tour
Perl6 a whistle stop tour
Simon Proctor
 
flows.ppt
flows.pptflows.ppt
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
Tomasz Wrobel
 
Scala
ScalaScala
Data Structures and Algorithm AnalysisSpring 2020 Post Midterm E
Data Structures and Algorithm AnalysisSpring 2020 Post Midterm EData Structures and Algorithm AnalysisSpring 2020 Post Midterm E
Data Structures and Algorithm AnalysisSpring 2020 Post Midterm E
jeniihykdevara
 
Scala training workshop 02
Scala training workshop 02Scala training workshop 02
Scala training workshop 02
Nguyen Tuan
 
GeoGebra JavaScript CheatSheet
GeoGebra JavaScript CheatSheetGeoGebra JavaScript CheatSheet
GeoGebra JavaScript CheatSheet
Jose Perez
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
Raúl Raja Martínez
 
Java/Scala Lab: Slava Schmidt - Introduction to Reactive Streams
Java/Scala Lab: Slava Schmidt - Introduction to Reactive StreamsJava/Scala Lab: Slava Schmidt - Introduction to Reactive Streams
Java/Scala Lab: Slava Schmidt - Introduction to Reactive Streams
GeeksLab Odessa
 
Formal methods 5 - Pi calculus
Formal methods   5 - Pi calculusFormal methods   5 - Pi calculus
Formal methods 5 - Pi calculus
Vlad Patryshev
 

Similar to ABA Problem (20)

Rewriting Java In Scala
Rewriting Java In ScalaRewriting Java In Scala
Rewriting Java In Scala
 
Queue Data Structure (w/ php egs)
Queue Data Structure (w/ php egs)Queue Data Structure (w/ php egs)
Queue Data Structure (w/ php egs)
 
A bit about Scala
A bit about ScalaA bit about Scala
A bit about Scala
 
Monadologie
MonadologieMonadologie
Monadologie
 
An Introduction to Higher Order Functions in Spark SQL with Herman van Hovell
An Introduction to Higher Order Functions in Spark SQL with Herman van HovellAn Introduction to Higher Order Functions in Spark SQL with Herman van Hovell
An Introduction to Higher Order Functions in Spark SQL with Herman van Hovell
 
Michal Malohlava presents: Open Source H2O and Scala
Michal Malohlava presents: Open Source H2O and Scala Michal Malohlava presents: Open Source H2O and Scala
Michal Malohlava presents: Open Source H2O and Scala
 
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and SparkCrystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
 
Spark workshop
Spark workshopSpark workshop
Spark workshop
 
Introduction to Machine Learning
Introduction to Machine LearningIntroduction to Machine Learning
Introduction to Machine Learning
 
Perl6 a whistle stop tour
Perl6 a whistle stop tourPerl6 a whistle stop tour
Perl6 a whistle stop tour
 
Perl6 a whistle stop tour
Perl6 a whistle stop tourPerl6 a whistle stop tour
Perl6 a whistle stop tour
 
flows.ppt
flows.pptflows.ppt
flows.ppt
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
 
Scala
ScalaScala
Scala
 
Data Structures and Algorithm AnalysisSpring 2020 Post Midterm E
Data Structures and Algorithm AnalysisSpring 2020 Post Midterm EData Structures and Algorithm AnalysisSpring 2020 Post Midterm E
Data Structures and Algorithm AnalysisSpring 2020 Post Midterm E
 
Scala training workshop 02
Scala training workshop 02Scala training workshop 02
Scala training workshop 02
 
GeoGebra JavaScript CheatSheet
GeoGebra JavaScript CheatSheetGeoGebra JavaScript CheatSheet
GeoGebra JavaScript CheatSheet
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Java/Scala Lab: Slava Schmidt - Introduction to Reactive Streams
Java/Scala Lab: Slava Schmidt - Introduction to Reactive StreamsJava/Scala Lab: Slava Schmidt - Introduction to Reactive Streams
Java/Scala Lab: Slava Schmidt - Introduction to Reactive Streams
 
Formal methods 5 - Pi calculus
Formal methods   5 - Pi calculusFormal methods   5 - Pi calculus
Formal methods 5 - Pi calculus
 

More from Dr. C.V. Suresh Babu

Data analytics with R
Data analytics with RData analytics with R
Data analytics with R
Dr. C.V. Suresh Babu
 
Association rules
Association rulesAssociation rules
Association rules
Dr. C.V. Suresh Babu
 
Clustering
ClusteringClustering
Classification
ClassificationClassification
Classification
Dr. C.V. Suresh Babu
 
Blue property assumptions.
Blue property assumptions.Blue property assumptions.
Blue property assumptions.
Dr. C.V. Suresh Babu
 
Introduction to regression
Introduction to regressionIntroduction to regression
Introduction to regression
Dr. C.V. Suresh Babu
 
DART
DARTDART
Mycin
MycinMycin
Expert systems
Expert systemsExpert systems
Expert systems
Dr. C.V. Suresh Babu
 
Dempster shafer theory
Dempster shafer theoryDempster shafer theory
Dempster shafer theory
Dr. C.V. Suresh Babu
 
Bayes network
Bayes networkBayes network
Bayes network
Dr. C.V. Suresh Babu
 
Bayes' theorem
Bayes' theoremBayes' theorem
Bayes' theorem
Dr. C.V. Suresh Babu
 
Knowledge based agents
Knowledge based agentsKnowledge based agents
Knowledge based agents
Dr. C.V. Suresh Babu
 
Rule based system
Rule based systemRule based system
Rule based system
Dr. C.V. Suresh Babu
 
Formal Logic in AI
Formal Logic in AIFormal Logic in AI
Formal Logic in AI
Dr. C.V. Suresh Babu
 
Production based system
Production based systemProduction based system
Production based system
Dr. C.V. Suresh Babu
 
Game playing in AI
Game playing in AIGame playing in AI
Game playing in AI
Dr. C.V. Suresh Babu
 
Diagnosis test of diabetics and hypertension by AI
Diagnosis test of diabetics and hypertension by AIDiagnosis test of diabetics and hypertension by AI
Diagnosis test of diabetics and hypertension by AI
Dr. C.V. Suresh Babu
 
A study on “impact of artificial intelligence in covid19 diagnosis”
A study on “impact of artificial intelligence in covid19 diagnosis”A study on “impact of artificial intelligence in covid19 diagnosis”
A study on “impact of artificial intelligence in covid19 diagnosis”
Dr. C.V. Suresh Babu
 
A study on “impact of artificial intelligence in covid19 diagnosis”
A study on “impact of artificial intelligence in covid19 diagnosis”A study on “impact of artificial intelligence in covid19 diagnosis”
A study on “impact of artificial intelligence in covid19 diagnosis”
Dr. C.V. Suresh Babu
 

More from Dr. C.V. Suresh Babu (20)

Data analytics with R
Data analytics with RData analytics with R
Data analytics with R
 
Association rules
Association rulesAssociation rules
Association rules
 
Clustering
ClusteringClustering
Clustering
 
Classification
ClassificationClassification
Classification
 
Blue property assumptions.
Blue property assumptions.Blue property assumptions.
Blue property assumptions.
 
Introduction to regression
Introduction to regressionIntroduction to regression
Introduction to regression
 
DART
DARTDART
DART
 
Mycin
MycinMycin
Mycin
 
Expert systems
Expert systemsExpert systems
Expert systems
 
Dempster shafer theory
Dempster shafer theoryDempster shafer theory
Dempster shafer theory
 
Bayes network
Bayes networkBayes network
Bayes network
 
Bayes' theorem
Bayes' theoremBayes' theorem
Bayes' theorem
 
Knowledge based agents
Knowledge based agentsKnowledge based agents
Knowledge based agents
 
Rule based system
Rule based systemRule based system
Rule based system
 
Formal Logic in AI
Formal Logic in AIFormal Logic in AI
Formal Logic in AI
 
Production based system
Production based systemProduction based system
Production based system
 
Game playing in AI
Game playing in AIGame playing in AI
Game playing in AI
 
Diagnosis test of diabetics and hypertension by AI
Diagnosis test of diabetics and hypertension by AIDiagnosis test of diabetics and hypertension by AI
Diagnosis test of diabetics and hypertension by AI
 
A study on “impact of artificial intelligence in covid19 diagnosis”
A study on “impact of artificial intelligence in covid19 diagnosis”A study on “impact of artificial intelligence in covid19 diagnosis”
A study on “impact of artificial intelligence in covid19 diagnosis”
 
A study on “impact of artificial intelligence in covid19 diagnosis”
A study on “impact of artificial intelligence in covid19 diagnosis”A study on “impact of artificial intelligence in covid19 diagnosis”
A study on “impact of artificial intelligence in covid19 diagnosis”
 

Recently uploaded

C1 Rubenstein AP HuG xxxxxxxxxxxxxx.pptx
C1 Rubenstein AP HuG xxxxxxxxxxxxxx.pptxC1 Rubenstein AP HuG xxxxxxxxxxxxxx.pptx
C1 Rubenstein AP HuG xxxxxxxxxxxxxx.pptx
mulvey2
 
Leveraging Generative AI to Drive Nonprofit Innovation
Leveraging Generative AI to Drive Nonprofit InnovationLeveraging Generative AI to Drive Nonprofit Innovation
Leveraging Generative AI to Drive Nonprofit Innovation
TechSoup
 
math operations ued in python and all used
math operations ued in python and all usedmath operations ued in python and all used
math operations ued in python and all used
ssuser13ffe4
 
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdfREASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
giancarloi8888
 
How to Make a Field Mandatory in Odoo 17
How to Make a Field Mandatory in Odoo 17How to Make a Field Mandatory in Odoo 17
How to Make a Field Mandatory in Odoo 17
Celine George
 
BÀI TẬP BỔ TRỢ TIẾNG ANH LỚP 9 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2024-2025 - ...
BÀI TẬP BỔ TRỢ TIẾNG ANH LỚP 9 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2024-2025 - ...BÀI TẬP BỔ TRỢ TIẾNG ANH LỚP 9 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2024-2025 - ...
BÀI TẬP BỔ TRỢ TIẾNG ANH LỚP 9 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2024-2025 - ...
Nguyen Thanh Tu Collection
 
A Independência da América Espanhola LAPBOOK.pdf
A Independência da América Espanhola LAPBOOK.pdfA Independência da América Espanhola LAPBOOK.pdf
A Independência da América Espanhola LAPBOOK.pdf
Jean Carlos Nunes Paixão
 
The History of Stoke Newington Street Names
The History of Stoke Newington Street NamesThe History of Stoke Newington Street Names
The History of Stoke Newington Street Names
History of Stoke Newington
 
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
Nguyen Thanh Tu Collection
 
What is Digital Literacy? A guest blog from Andy McLaughlin, University of Ab...
What is Digital Literacy? A guest blog from Andy McLaughlin, University of Ab...What is Digital Literacy? A guest blog from Andy McLaughlin, University of Ab...
What is Digital Literacy? A guest blog from Andy McLaughlin, University of Ab...
GeorgeMilliken2
 
LAND USE LAND COVER AND NDVI OF MIRZAPUR DISTRICT, UP
LAND USE LAND COVER AND NDVI OF MIRZAPUR DISTRICT, UPLAND USE LAND COVER AND NDVI OF MIRZAPUR DISTRICT, UP
LAND USE LAND COVER AND NDVI OF MIRZAPUR DISTRICT, UP
RAHUL
 
Level 3 NCEA - NZ: A Nation In the Making 1872 - 1900 SML.ppt
Level 3 NCEA - NZ: A  Nation In the Making 1872 - 1900 SML.pptLevel 3 NCEA - NZ: A  Nation In the Making 1872 - 1900 SML.ppt
Level 3 NCEA - NZ: A Nation In the Making 1872 - 1900 SML.ppt
Henry Hollis
 
Standardized tool for Intelligence test.
Standardized tool for Intelligence test.Standardized tool for Intelligence test.
Standardized tool for Intelligence test.
deepaannamalai16
 
RHEOLOGY Physical pharmaceutics-II notes for B.pharm 4th sem students
RHEOLOGY Physical pharmaceutics-II notes for B.pharm 4th sem studentsRHEOLOGY Physical pharmaceutics-II notes for B.pharm 4th sem students
RHEOLOGY Physical pharmaceutics-II notes for B.pharm 4th sem students
Himanshu Rai
 
How to deliver Powerpoint Presentations.pptx
How to deliver Powerpoint  Presentations.pptxHow to deliver Powerpoint  Presentations.pptx
How to deliver Powerpoint Presentations.pptx
HajraNaeem15
 
Chapter wise All Notes of First year Basic Civil Engineering.pptx
Chapter wise All Notes of First year Basic Civil Engineering.pptxChapter wise All Notes of First year Basic Civil Engineering.pptx
Chapter wise All Notes of First year Basic Civil Engineering.pptx
Denish Jangid
 
writing about opinions about Australia the movie
writing about opinions about Australia the moviewriting about opinions about Australia the movie
writing about opinions about Australia the movie
Nicholas Montgomery
 
Pharmaceutics Pharmaceuticals best of brub
Pharmaceutics Pharmaceuticals best of brubPharmaceutics Pharmaceuticals best of brub
Pharmaceutics Pharmaceuticals best of brub
danielkiash986
 
Gender and Mental Health - Counselling and Family Therapy Applications and In...
Gender and Mental Health - Counselling and Family Therapy Applications and In...Gender and Mental Health - Counselling and Family Therapy Applications and In...
Gender and Mental Health - Counselling and Family Therapy Applications and In...
PsychoTech Services
 
Mule event processing models | MuleSoft Mysore Meetup #47
Mule event processing models | MuleSoft Mysore Meetup #47Mule event processing models | MuleSoft Mysore Meetup #47
Mule event processing models | MuleSoft Mysore Meetup #47
MysoreMuleSoftMeetup
 

Recently uploaded (20)

C1 Rubenstein AP HuG xxxxxxxxxxxxxx.pptx
C1 Rubenstein AP HuG xxxxxxxxxxxxxx.pptxC1 Rubenstein AP HuG xxxxxxxxxxxxxx.pptx
C1 Rubenstein AP HuG xxxxxxxxxxxxxx.pptx
 
Leveraging Generative AI to Drive Nonprofit Innovation
Leveraging Generative AI to Drive Nonprofit InnovationLeveraging Generative AI to Drive Nonprofit Innovation
Leveraging Generative AI to Drive Nonprofit Innovation
 
math operations ued in python and all used
math operations ued in python and all usedmath operations ued in python and all used
math operations ued in python and all used
 
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdfREASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
 
How to Make a Field Mandatory in Odoo 17
How to Make a Field Mandatory in Odoo 17How to Make a Field Mandatory in Odoo 17
How to Make a Field Mandatory in Odoo 17
 
BÀI TẬP BỔ TRỢ TIẾNG ANH LỚP 9 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2024-2025 - ...
BÀI TẬP BỔ TRỢ TIẾNG ANH LỚP 9 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2024-2025 - ...BÀI TẬP BỔ TRỢ TIẾNG ANH LỚP 9 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2024-2025 - ...
BÀI TẬP BỔ TRỢ TIẾNG ANH LỚP 9 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2024-2025 - ...
 
A Independência da América Espanhola LAPBOOK.pdf
A Independência da América Espanhola LAPBOOK.pdfA Independência da América Espanhola LAPBOOK.pdf
A Independência da América Espanhola LAPBOOK.pdf
 
The History of Stoke Newington Street Names
The History of Stoke Newington Street NamesThe History of Stoke Newington Street Names
The History of Stoke Newington Street Names
 
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
 
What is Digital Literacy? A guest blog from Andy McLaughlin, University of Ab...
What is Digital Literacy? A guest blog from Andy McLaughlin, University of Ab...What is Digital Literacy? A guest blog from Andy McLaughlin, University of Ab...
What is Digital Literacy? A guest blog from Andy McLaughlin, University of Ab...
 
LAND USE LAND COVER AND NDVI OF MIRZAPUR DISTRICT, UP
LAND USE LAND COVER AND NDVI OF MIRZAPUR DISTRICT, UPLAND USE LAND COVER AND NDVI OF MIRZAPUR DISTRICT, UP
LAND USE LAND COVER AND NDVI OF MIRZAPUR DISTRICT, UP
 
Level 3 NCEA - NZ: A Nation In the Making 1872 - 1900 SML.ppt
Level 3 NCEA - NZ: A  Nation In the Making 1872 - 1900 SML.pptLevel 3 NCEA - NZ: A  Nation In the Making 1872 - 1900 SML.ppt
Level 3 NCEA - NZ: A Nation In the Making 1872 - 1900 SML.ppt
 
Standardized tool for Intelligence test.
Standardized tool for Intelligence test.Standardized tool for Intelligence test.
Standardized tool for Intelligence test.
 
RHEOLOGY Physical pharmaceutics-II notes for B.pharm 4th sem students
RHEOLOGY Physical pharmaceutics-II notes for B.pharm 4th sem studentsRHEOLOGY Physical pharmaceutics-II notes for B.pharm 4th sem students
RHEOLOGY Physical pharmaceutics-II notes for B.pharm 4th sem students
 
How to deliver Powerpoint Presentations.pptx
How to deliver Powerpoint  Presentations.pptxHow to deliver Powerpoint  Presentations.pptx
How to deliver Powerpoint Presentations.pptx
 
Chapter wise All Notes of First year Basic Civil Engineering.pptx
Chapter wise All Notes of First year Basic Civil Engineering.pptxChapter wise All Notes of First year Basic Civil Engineering.pptx
Chapter wise All Notes of First year Basic Civil Engineering.pptx
 
writing about opinions about Australia the movie
writing about opinions about Australia the moviewriting about opinions about Australia the movie
writing about opinions about Australia the movie
 
Pharmaceutics Pharmaceuticals best of brub
Pharmaceutics Pharmaceuticals best of brubPharmaceutics Pharmaceuticals best of brub
Pharmaceutics Pharmaceuticals best of brub
 
Gender and Mental Health - Counselling and Family Therapy Applications and In...
Gender and Mental Health - Counselling and Family Therapy Applications and In...Gender and Mental Health - Counselling and Family Therapy Applications and In...
Gender and Mental Health - Counselling and Family Therapy Applications and In...
 
Mule event processing models | MuleSoft Mysore Meetup #47
Mule event processing models | MuleSoft Mysore Meetup #47Mule event processing models | MuleSoft Mysore Meetup #47
Mule event processing models | MuleSoft Mysore Meetup #47
 

ABA Problem

  • 1. ABA Problem Dr. C.V. Suresh Babu
  • 2. Introduction • Queues are everywhere in parallel applications and operating systems • Many researchers have proposed queues – – – – Hwang and Briggs Gottlieb Massalin Et al. etc… • Queue performance can be critical to operating system performance – Scheduling Queues – Free memory lists – Many other critical kernel operations
  • 3. Concurrent FIFO Queue algorithms • Blocking algorithms risk performance degradation – A process can be delayed or halted at inopportune moments • Scheduling preemption • Page faults • Cache misses – Slow processes can prevent faster ones from completing indefinitely • Non-Blocking algorithms must solve the ABA problem – During contention, some process will complete within a given number of operations
  • 4. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { loop value = SM newVal = value +1 Stack Data = d CAS(&SM, value, newVal) break Stack SM 5 … x time newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X
  • 5. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { loop newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X CAS(&SM,value,newVal) value = SM newVal = value +1 Stack Data = d CAS(&SM, value, newVal) break Stack SM 4 … x time
  • 6. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { loop newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X CAS(&SM,value,newVal) value = SM v2 = x newVal = value +1 Stack Data = d CAS(&SM, value, newVal) break Stack SM 4 … x time
  • 7. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { loop newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X CAS(&SM,value,newVal) value = SM v2 = x newVal = value +1 Push(z) Stack Data = d CAS(&SM, value, newVal) break Stack SM 4 … x time
  • 8. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { loop newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X CAS(&SM,value,newVal) value = SM v2 = x newVal = value +1 Stack Data = d Push(z) CAS(&SM, value, newVal) value = 4 break Stack SM 4 … x time
  • 9. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { loop newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X CAS(&SM,value,newVal) value = SM v2 = x newVal = value +1 Stack Data = d Push(z) CAS(&SM, value, newVal) value = 4 break newVal=5 Stack SM 4 … x time
  • 10. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { loop newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X CAS(&SM,value,newVal) value = SM v2 = x newVal = value +1 Stack Data = d Push(z) CAS(&SM, value, newVal) value = 4 break newVal=5 Stack CAS(&SM,value,newVal) SM 5 … z time
  • 11. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X loop CAS(&SM,value,newVal) value = SM v2 = x newVal = value +1 Stack Data = d Push(z) CAS(&SM, value, newVal) value = 4 break newVal=5 Stack CAS(&SM,value,newVal) CAS(&SM,value,newVal) SM 5 … z time
  • 12. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X loop CAS(&SM,value,newVal) value = SM v2 = x newVal = value +1 Stack Data = d Push(z) CAS(&SM, value, newVal) value = 4 break newVal=5 Stack CAS(&SM,value,newVal) CAS(&SM,value,newVal) v1=x SM 4 … z time
  • 13. ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data CAS(&SM, value, newVal) v1=Pop() value = 5 Push (d) { newVal = 4 data=X return data value = 5 newVal = 4 break v2=Pop() data=X loop CAS(&SM,value,newVal) value = SM v2 = x newVal = value +1 Stack Data = d Push(z) CAS(&SM, value, newVal) value = 4 break newVal=5 Stack CAS(&SM,value,newVal) CAS(&SM,value,newVal) v1=x SM 4 … z CAS should fail but it succeeds time Thread1 has Thread2’s data
  • 14. Solutions for ABA problem Cache Kernel • Add version # to data structures • Increment # during every CAS instruction LL/SC • Fail if Cache Line has been written to
  • 15. Solution for ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data DCAS(&SM, value, v1=Pop() value = 5 return data Push (d) { newVal = 4 data=X break value = 5 newVal = 4 <ver++,newVal>) v2=Pop() data=X loop DCAS(&SM,value,ver,newVal) value = SM v2 = x newVal = value +1 Stack Data = d Push(z) DCAS(&SM, value, value = 4 <ver++,newVal>) newVal=5 Stack break DCAS(&SM,value,ver,newVal) DCAS(&SM,value,ver,newVal) Will not incorrectly succeed SM 5 … z (ver != ver+2) time
  • 16. Solution for ABA problem Pop () { loop value = SM newVal = value -1 THREAD1 THREAD2 data = Stack Data DCAS(&SM, value, v1=Pop() value = 5 return data Push (d) { newVal = 4 data=Z break value = 5 newVal = 4 <ver++,newVal>) v2=Pop() data=X loop DCAS(&SM,value,ver,newVal) value = SM v2 = x newVal = value +1 Stack Data = d Push(z) DCAS(&SM, value, value = 4 <ver++,newVal>) newVal=5 Stack break DCAS(&SM,value,ver,newVal) DCAS(&SM,value,ver,newVal) Will not incorrectly succeed SM 4 (ver != ver+2) … time V1 = Z
  • 17. Correctness Properties 1. 2. 3. 4. 5. The linked list is always connected Nodes only inserted after the last node Nodes only deleted from beginning Head always points to the first node Tail always points to a node in the list
  • 18. Queue # 1 • Non-Blocking Concurrent Queue – enqueue()
  • 19. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value node–>next.ptr = NULL loop tail = Q–>Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node
  • 20. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node
  • 21. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node
  • 22. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node [NULL]
  • 23. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node [NULL]
  • 24. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node “enqueue(myQueue, D1)” enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) [NULL]
  • 25. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) [NULL]
  • 26. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) D1 [NULL]
  • 27. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) D1 [NULL] [NULL]
  • 28. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) D1 [NULL] tail [NULL]
  • 29. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) D1 [NULL] tail next [NULL]
  • 30. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) D1 [NULL] tail next [NULL]
  • 31. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS( &tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) D1 [NULL] tail next [NULL]
  • 32. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) D1 +1 [NULL] tail next
  • 33. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) D1 +1 [NULL] tail next
  • 34. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node enqueue(myQueue, D1) enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next +1 if tail == Q–>Tail if next.ptr == NULL if CAS(&tail.ptr–>next, next, <node, next.count+1>) myQueue break endif else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) endif endif endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) D1 +1 [NULL]
  • 35. Concurrent enqueues • Suppose two processes call enqueue() at the same time
  • 36. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS( &tail.ptr–>next, next, <node, next.count+1>) myQueue break Process 1 endif Enqueue(myQueue, ABC) else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) ABC endif endif [NULL] endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) tail next initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node D1 [NULL] Process 2 Enqueue(myQueue, XYZ) XYZ [NULL] tail next
  • 37. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS( &tail.ptr–>next, next, <node, next.count+1>) myQueue break Process 1 endif Enqueue(myQueue, ABC) else CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) ABC endif endif [NULL] endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) tail next initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node D1 +1 XYZ [NULL] Process 2 Enqueue(myQueue, XYZ) tail
  • 38. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } enqueue(Q: pointer to queue t, value: data type) node = new node() node–>value = value Head node–>next.ptr = NULL loop tail = Q–>Tail Tail next = tail.ptr–>next if tail == Q–>Tail if next.ptr == NULL if CAS( &tail.ptr–>next, next, <node, next.count+1>) myQueue break Process 1 endif Enqueue(myQueue, ABC) else CAS( &Q–>Tail, tail, <next.ptr, tail.count+1>) ABC endif endif [NULL] endloop CAS(&Q–>Tail, tail, <node, tail.count+1>) tail next initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node D1 +1 XYZ [NULL] Process 2 Enqueue(myQueue, XYZ) tail
  • 39. Queue #1 (cont.) • Non-Blocking Concurrent Queue – dequeue()
  • 40. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node “dequeue(myQueue, pvalue)” dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop Head head = Q–>Head tail = Q–>Tail next = head–>next if head == Q–>Head Tail if head.ptr == tail.ptr if next.ptr == NULL return FALSE endif myQueue CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head, head, <next.ptr, head.count+1>) break endif endif endif endloop free(head.ptr) D1 [NULL]
  • 41. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node dequeue(myQueue, pvalue) dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop Head head = Q–>Head tail = Q–>Tail next = head–>next if head == Q–>Head Tail if head.ptr == tail.ptr if next.ptr == NULL return FALSE endif myQueue CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head, head, <next.ptr, head.count+1>) break endif endif endif endloop free(head.ptr) D1 [NULL] head tail next
  • 42. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node dequeue(myQueue, pvalue) dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop Head head = Q–>Head tail = Q–>Tail next = head–>next if head == Q–>Head Tail if head.ptr == tail.ptr if next.ptr == NULL return FALSE endif myQueue CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head, head, <next.ptr, head.count+1>) break endif endif endif endloop free(head.ptr) D1 [NULL] head tail next
  • 43. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node dequeue(myQueue, pvalue) dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop Head head = Q–>Head tail = Q–>Tail next = head–>next if head == Q–>Head Tail if head.ptr == tail.ptr if next.ptr == NULL return FALSE endif myQueue CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head, head, <next.ptr, head.count+1>) break endif endif endif endloop free(head.ptr) D1 [NULL] head tail next
  • 44. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node dequeue(myQueue, pvalue) dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop Head head = Q–>Head tail = Q–>Tail next = head–>next if head == Q–>Head Tail if head.ptr == tail.ptr if next.ptr == NULL return FALSE endif myQueue CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head, head, <next.ptr, head.count+1>) break endif endif endif endloop free(head.ptr) D1 [NULL] head tail next
  • 45. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node dequeue(myQueue, pvalue) dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop Head head = Q–>Head +1 tail = Q–>Tail next = head–>next if head == Q–>Head Tail if head.ptr == tail.ptr if next.ptr == NULL return FALSE endif myQueue CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head, head, <next.ptr, head.count+1>) break endif endif endif endloop free(head.ptr) D1 [NULL] head tail next
  • 46. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node dequeue(myQueue, pvalue) dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop Head head = Q–>Head +1 tail = Q–>Tail next = head–>next if head == Q–>Head Tail if head.ptr == tail.ptr if next.ptr == NULL return FALSE endif myQueue CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head, head, <next.ptr, head.count+1>) break endif endif endif endloop free(head.ptr) D1 [NULL] head tail next
  • 47. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node dequeue(myQueue, pvalue) dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop Head head = Q–>Head +1 tail = Q–>Tail next = head–>next if head == Q–>Head Tail if head.ptr == tail.ptr if next.ptr == NULL return FALSE endif myQueue CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head, head, <next.ptr, head.count+1>) break endif endif endif endloop free(head.ptr) D1 [NULL] head tail next
  • 48. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node dequeue(myQueue, pvalue) dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop Head head = Q–>Head +1 tail = Q–>Tail next = head–>next if head == Q–>Head Tail if head.ptr == tail.ptr if next.ptr == NULL return FALSE endif myQueue CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head, head, <next.ptr, head.count+1>) break endif endif endif endloop free(head.ptr) D1 [NULL]
  • 49. Concurrent dequeues • Suppose two processes call dequeue() at the same time
  • 50. struct pointer_t { node_t * ptr uint count } struct node_t { data_type value pointer_t next } struct queue_t { pointer_t Head pointer_t Tail } dequeue(Q: ptr to queue t, pvalue: ptr to data type):bool loop head = Q–>Head Head tail = Q–>Tail next = head–>next if head == Q–>Head if head.ptr == tail.ptr Tail if next.ptr == NULL return FALSE endif CAS(&Q–>Tail, tail, <next.ptr, tail.count+1>) else # Read value before CAS, otherwise another # dequeue might free the next node *pvalue = next.ptr–>value if CAS ( &Q–>Head,head, <next.ptr, head.count+1>) break endif “dequeue(myQueue, endif endif endloop free(head.ptr) return TRUE D1 [NULL] pvalue)”
  • 51. Queue #2 • Two-lock Concurrent Queue
  • 52. struct node_t { data_type value node_t * next } struct queue_t { pointer_t Head pointer_t Tail lock_type H_lock lock_type T_lock } initialize(Q: pointer to queue t) node = new node() node–>next.ptr = NULL Q–>Head = Q–>Tail = node Q–>H lock = Q–>T lock = FREE dequeue(Q: pointer to queue t, pvalue: pointer to data type): boolean lock(&Q–>H lock) node = Q–>Head new head = node–>next if new head == NULL enqueue(Q: pointer to queue t, value: data type) unlock(&Q–>H lock) node = new node() return FALSE node–>value = value endif node–>next.ptr = NULL *pvalue = new head–>value lock(&Q–>T lock) Q–>Head = new head Q–>Tail–>next = node unlock(&Q–>H lock) Q–>Tail = node free(node) unlock(&Q–>T lock) return TRUE • Algorithms have same general structure only different data types • No loops, ‘busy waiting’ instead • Only dequeues access Head Lock • Only enqueues access Tail Lock
  • 53. Performance Parameters • Net execution time for one million enqueue/dequeue pairs • 12-processor Silicon Graphics Challenge multiprocessor • Algorithms compiled with using highest optimization level • Including many hand optimizations
  • 54. Dedicated multiprocessor Multiprogrammed system with 3 processes per processor Multiprogrammed system with 2 processes per processor
  • 55. Conclusion • NBS clear winner for multiprocessor multiprogrammed systems • Above 5 processors, use the new nonblocking queue • If hardware only supports test-and-set use two lock queue • For two or less processors use a single lock algorithm for queues