summaryrefslogtreecommitdiff
path: root/src/thread_finish.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/thread_finish.asm')
-rw-r--r--src/thread_finish.asm30
1 files changed, 19 insertions, 11 deletions
diff --git a/src/thread_finish.asm b/src/thread_finish.asm
index 860b0a4..c453d40 100644
--- a/src/thread_finish.asm
+++ b/src/thread_finish.asm
@@ -43,12 +43,15 @@ section .text
; Returns zero on success, or a standard error code.
global linen_thread_finish
linen_thread_finish:
+ ; It's handy to have a register that's 0 for a while
+ xor ecx, ecx
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Check validity of arguments ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Return EINVAL if rdi is NULL or otherwise invalid
- mov eax, -22 ; (EINVAL = -22)
+ ; Return EINVAL (-22) if rdi is NULL or otherwise invalid
+ lea eax, [rcx - 22] ; mov eax, -22
test rdi, rdi
jz finish_return ; rdi is NULL
@@ -57,8 +60,7 @@ linen_thread_finish:
; if that assumption is wrong we'll get a segmentation fault.
; But we don't yet trust that [rdi] is a valid thread handle!
; To verify this we check the canary value stored at [rdi + 4].
- mov ecx, [rdi + 4]
- cmp ecx, 0xDEADBEEF
+ cmp dword [rdi + 4], 0xDEADBEEF ; Oh CISC...
jnz finish_return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -86,9 +88,9 @@ linen_thread_finish:
; futex: rdi = uaddr: address of the dword to watch
; futex: rsi = futex_op: which futex operation we want:
- ; - FUTEX_WAIT: block until the value at [rdi] changes
+ ; - FUTEX_WAIT = 0: block until the value at [rdi] changes
; - FUTEX_PRIVATE_FLAG: FIXME waits forever, I don't understand why
- mov esi, FUTEX_WAIT
+ xor esi, esi ; mov esi, FUTEX_WAIT
; futex: rdx = val: the expected value at [rdi] before it changes
mov edx, eax
; futex: r10 = timeout: in case we had a deadline (we don't)
@@ -96,17 +98,18 @@ linen_thread_finish:
; futex: r8 = uaddr2: ignored when FUTEX_WAIT is used
; futex: r9 = val3: ignored when FUTEX_WAIT 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
; Sometimes the thread exits after the "lock cmpxchg" instruction
; but before the futex call. In that case, futex returns EAGAIN.
- cmp rax, -11 ; (EAGAIN = -11)
+ cmp eax, -11 ; (EAGAIN = -11)
je finish_retry
; Any other nonzero return value means failure
- test rax, rax
+ test eax, eax
jnz finish_return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -117,6 +120,11 @@ linen_thread_finish:
; The thread left its function return value on the stack, read it
mov rdx, [rdi - 8]
+ ; Remove the canary value so the thread handle becomes invalid. We're about
+ ; to deallocate this memory anyway, so it's optional, but maybe the address
+ ; becomes valid again later in the program's life, who knows? Play it safe.
+ mov [rdi + 4], eax ; eax = 0 for all paths
+
; The munmap system call destroys mappings created by mmap.
; In this case that means deallocating the stack buffer.
; See: man 2 munmap
@@ -127,12 +135,12 @@ linen_thread_finish:
; munmap: rsi = length: size of region starting from rdi
mov esi, (STACK_SIZE + GUARD_PAGE)
; munmap: rax = system call ID
- mov eax, SYS_MUNMAP
+ mov al, SYS_MUNMAP
; munmap: rax = munmap(rdi, rsi)
syscall
; Check result of munmap: nonzero means failure
- test rax, rax
+ test eax, eax
jnz finish_return
; Check if caller gave a location (r8) to save the return value (rdx)