Last active
June 2, 2021 23:40
-
-
Save michaeljclark/483df86b8ad1c5453098cdce8801c8b0 to your computer and use it in GitHub Desktop.
Queued ticket lock description in English and some RISC-V assembly for a possible implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
# Ticket Lock | |
# | |
# Ticket locks are fair spinlocks that order acccess on a first-in, | |
# first-out basis. The lock is composed of a head counter and a tail | |
# counter. The head counter indicates the ticket number of the current | |
# lock owner. The tail counter indicates the last issued ticket number. | |
# To acquire the lock, the acquiring thread atomically increments the | |
# tail counter to assign itself a ticket number. It then waits until | |
# its assigned ticket number is seen in the head counter. If the lock | |
# is not contended, then head will equal the ticket number just assigned. | |
# To release the lock, the lock owner atomically increments head counter | |
# thereby allowing access to the thread holding the next ticket number. | |
# | |
# Initializtion - the lock is initialized unlocked, so that the | |
# next tail increment returns a ticket that will acquires the lock. | |
# | |
# tail | head | |
# -------|------- | |
# 0x0000 | 0x0001 | |
# | |
# Lock - the tail is incremented, and the thread waits unti the tail | |
# is equal to the head before returning control, which is the typical | |
# case if the lock is uncontended. | |
# | |
# tail | head | |
# -------|------- | |
# 0x0001 | 0x0001 | |
# | |
# Unlock - the head is incremented, so that it will now equal the value | |
# of the ticket of the next waiter, if any. | |
# | |
# tail | head | |
# -------|------- | |
# 0x0001 | 0x0002 | |
# | |
# Waiters - the number of waiters can be calculated by subtracting | |
# head (current ticket) from the tail plus one (next ticket) | |
# | |
# num_waiters = tail + 1 - head | |
# | |
spin_lock: | |
lui a2,0x10 | |
amoadd.w a5,a5,(a0) | |
srliw a4,a5,0x10 | |
2: slliw a5,a5,0x10 | |
srliw a5,a5,0x10 | |
bne a5,a4,3f | |
ret | |
3: lw a5,0(a0) | |
fence r,rw | |
j 2b | |
spin_trylock: | |
lui a5,0x10 | |
lr.w.aq a4,(a0) | |
addw a5,a5,a4 | |
slliw a3,a5,0x10 | |
srliw a3,a3,0x10 | |
srliw a4,a5,0x10 | |
beq a3,a4,2f | |
1: li a0,0 | |
ret | |
2: sc.w.rl a4,a5,(a0) | |
bnez a4,1b | |
fence r,rw | |
li a0,1 | |
ret | |
spin_unlock: | |
fence rw,w | |
1: lr.w.aq a4,(a0) | |
srliw a5,a4,0x10 | |
addiw a4,a4,1 | |
slliw a4,a4,0x10 | |
srliw a4,a4,0x10 | |
slliw a5,a5,0x10 | |
or a5,a5,a4 | |
sc.w.rl a4,a5,(a0) | |
bnez a5,1b | |
ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment