diff options
author | Prefetch | 2023-07-24 19:21:30 +0200 |
---|---|---|
committer | Prefetch | 2023-07-24 19:21:30 +0200 |
commit | 94e3e3652f9f04810126ee754fa9a788289e2897 (patch) | |
tree | af5aac9f176039e97f1ebc46b497b5fd192a4fa2 /src/thread_finish.asm | |
parent | a211da8cfe9b0565881537cc81b09ae55c722111 (diff) |
Diffstat (limited to 'src/thread_finish.asm')
-rw-r--r-- | src/thread_finish.asm | 30 |
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) |