summaryrefslogtreecommitdiff
path: root/src/lock_release.asm
diff options
context:
space:
mode:
authorPrefetch2023-07-24 19:21:30 +0200
committerPrefetch2023-07-24 19:21:30 +0200
commit94e3e3652f9f04810126ee754fa9a788289e2897 (patch)
treeaf5aac9f176039e97f1ebc46b497b5fd192a4fa2 /src/lock_release.asm
parenta211da8cfe9b0565881537cc81b09ae55c722111 (diff)
Reduce total code size by 53 bytes (big deal, right?)HEADmaster
Diffstat (limited to 'src/lock_release.asm')
-rw-r--r--src/lock_release.asm32
1 files changed, 18 insertions, 14 deletions
diff --git a/src/lock_release.asm b/src/lock_release.asm
index f86caa2..2892cc3 100644
--- a/src/lock_release.asm
+++ b/src/lock_release.asm
@@ -43,12 +43,15 @@ section .text
; Returns zero on success, or a standard error code.
global linen_lock_release
linen_lock_release:
+ ; It's handy to have a register that's 0 during most of this function
+ xor esi, esi
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Check validity of argument ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Return EINVAL if rdi is NULL or invalid
- mov eax, -22 ; (EINVAL = -22)
+ ; Return EINVAL (-22) if rdi is NULL or invalid
+ lea eax, [rsi - 22] ; mov eax, -22
test rdi, rdi
jz release_return ; rdi is NULL
@@ -57,8 +60,7 @@ linen_lock_release:
; if that assumption is wrong we'll get a segmentation fault.
; But we don't yet trust that [rdi] is a valid lock handle!
; To verify this we check the canary value stored at [rdi + 8].
- mov ecx, [rdi + 8]
- cmp ecx, 0xCAFEBABE
+ cmp dword [rdi + 8], 0xCAFEBABE ; Oh CISC...
jnz release_return
; Lock owners are identified by their TID; let's find ours.
@@ -66,17 +68,19 @@ linen_lock_release:
; See: man 2 gettid
; gettid: rax = system call ID
- mov eax, SYS_GETTID
+ xor eax, eax
+ mov al, SYS_GETTID
; gettid: rax = gettid()
syscall
; Save a copy of our TID (no need for an error check)
mov edx, eax
- ; Return EPERM if this lock currently doesn't belong to us
- mov eax, -1 ; (EPERM = -1)
+ ; Return EPERM (-1) if this lock currently doesn't belong to us
+ or eax, -1 ; mov eax, -1
- ; Read the futex dword at [rdi] and keep its lowest 30 bits
+ ; Read the futex dword at [rdi] and keep its lowest 30 bits.
+ ; No need to use atomics, since we currently own this lock.
mov ecx, [rdi]
and ecx, FUTEX_TID_MASK
; Those bits contain the owner's TID; it should be our TID
@@ -96,9 +100,8 @@ linen_lock_release:
mov eax, edx
; Atomically try to set the dword at [rdi] to 0 if it was equal to our TID.
- ; if ([rdi] == eax]) { [rdi] = 0; goto release_success; } else { eax = [rdi]; }
- xor ecx, ecx
- lock cmpxchg [rdi], ecx
+ ; if ([rdi] == eax) { [rdi] = 0; goto release_success; } else { eax = [rdi]; }
+ lock cmpxchg [rdi], esi ; esi = 0
je release_success
; We failed because [rdi] wasn't equal to our TID. In theory,
@@ -111,18 +114,19 @@ linen_lock_release:
; futex: rsi = futex_op: which futex operation we want:
; - FUTEX_UNLOCK_PI: wake up one thread sleeping via FUTEX_LOCK_PI
; - FUTEX_PRIVATE_FLAG: this lock isn't shared with another process
- mov esi, (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG) ; futex: futex_op
+ mov sil, (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
; futex: rdx = val: ignored when FUTEX_UNLOCK_PI is used
; futex: r10 = timeout: ignored when FUTEX_UNLOCK_PI is used
; futex: r8 = uaddr2: ignored when FUTEX_UNLOCK_PI is used
; futex: r9 = val3: ignored when FUTEX_UNLOCK_PI is used
; futex: rax = system call ID
- mov eax, SYS_FUTEX
+ xor eax, eax
+ mov al, SYS_FUTEX
; futex: rax = futex(rdi, rsi, (rdx), (r10), (r8), (r9))
syscall
; Check result of futex: nonzero means failure
- test rax, rax
+ test eax, eax
jnz release_return
release_success: