0% found this document useful (0 votes)
32 views14 pages

Real Lock Implementation

This document discusses different implementations of locks for concurrent programming, including user-level locks on ARM architecture and locks using the Plan 9 C library. It describes how test-and-set (TAS) locks work on ARM and how they can implement locks slowly or quickly using sleep. It also discusses ticket locks as an alternative that uses fetch-and-add instead of write to avoid cache coherence issues. New ARM synchronization primitives like LDREX and STREX that can be used to implement TAS are also covered.

Uploaded by

Khoi Tran
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views14 pages

Real Lock Implementation

This document discusses different implementations of locks for concurrent programming, including user-level locks on ARM architecture and locks using the Plan 9 C library. It describes how test-and-set (TAS) locks work on ARM and how they can implement locks slowly or quickly using sleep. It also discusses ticket locks as an alternative that uses fetch-and-add instead of write to avoid cache coherence issues. New ARM synchronization primitives like LDREX and STREX that can be used to implement TAS are also covered.

Uploaded by

Khoi Tran
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

CS361: Concurrent

Programming
Real Lock Implementations

Locking Example

User-level lock implementation


ARM architecture
Plan 9 C library

ARM Locks

TEXT

_tas(SB), 1, $-4
MOVW
R0,R1
MOVW
$1,R0
SWPW
R0,(R1)
RET

ARM Locks
void
lock(Lock *lk)
{
int i;
/* once fast */
if(!_tas(&lk->val))
return;
/* a thousand times pretty fast */
for(i=0; i<1000; i++){
if(!_tas(&lk->val))
return;
sleep(0);
}
3

ARM Locks

/* now nice and slow */


for(i=0; i<1000; i++){
if(!_tas(&lk->val))
return;
sleep(100);
}
/* take your time */
while(_tas(&lk->val))
sleep(1000);
}

Multi-Core Effects

Each core has cache


Writes to memory invalidate cache
What is the effect of repeated TAS operations?
What about with non-per-core caches?

Ticket Locks

Like waiting for service at a bakery:


1. When wanting service take a ticket.
2. Wait until the now serving sign matches our ticket.
Repeated operation is read, not write
Needs atomic fetch-and-add operation

Ticket Lock Algorithm

p1:
p2:
p3:
p4:
p5:

integer ticket 1, serving 1


p
loop forever
non-critical section
mytick fetch-and-add(ticket, 1)
await mytick = serving
critical section
serving mytick + 1

fetch-and-add

Present in some architectures


Can be constructed from other primitives
How can fetch-and-add be implemented using test-and-set?

New ARM Synchronization Primitives

LDREX: Load exclusive


STREX: Store exclusive
Can be used to build TAS or any fetch-and-x

Load Exclusive

LDREX

(R0), R1

Loads R1 with the contents of memory location whose


address is in R0
Marks the memory location for exclusive access

10

Store Exclusive

STREX

R1, (R0), R2

If access is marked exclusive, R1 is stored to the memory


location whose address is in R0, and R2 0
Else R2 1

11

TAS with LDREX and STREX

TEXT _tas(SB), $-4


MOVW
R0,R5
DMB
MOVW
$1,R2
tas1:
LDREX
(R5),R0
CMP.S
$0, R0
BNE
lockbusy
STREX
R2,(R5),R4
CMP.S
$0, R4
BNE
tas1
DMB
RET
lockbusy:
CLREX
RET

/* _tas(ulong *) */

/* new value of (R0) */

/* old value non-zero (lock taken)? */


/* we lose */

/* strex failed? try again */

12

Queue Locks

If the lock is available, enter the critical section


Otherwise add to the tail of the queue and sleep
After critical section, wake up process on head of queue

13

You might also like