summaryrefslogtreecommitdiff
path: root/src/thread_create.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/thread_create.asm')
-rw-r--r--src/thread_create.asm52
1 files changed, 32 insertions, 20 deletions
diff --git a/src/thread_create.asm b/src/thread_create.asm
index 9a6fe78..8dc8813 100644
--- a/src/thread_create.asm
+++ b/src/thread_create.asm
@@ -72,12 +72,16 @@ linen_thread_create:
; Callee-save registers
push rbx
+ ; It's handy to have a register that's 0 for a while
+ xor ecx, ecx
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Check validity of arguments ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Return EINVAL if any argument is NULL
- mov eax, -22 ; (EINVAL = -22)
+ ; Return EINVAL (-22) if any argument is NULL
+ lea eax, [rcx - 22] ; mov eax, -22
+
test rdi, rdi
jz create_return ; Nowhere to store the thread handle
test rsi, rsi
@@ -91,9 +95,9 @@ linen_thread_create:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Save these registers: we'll clobber them for the mmap call
- mov rbx, rdi
- push rdx
- push rsi
+ push rdx ; argument
+ push rsi ; function
+ push rdi ; thread handle destination
; The mmap system call does many things, in this case allocate memory.
; See: man 2 mmap
@@ -103,25 +107,26 @@ linen_thread_create:
; mmap: rsi = length: size of buffer to allocate
mov esi, (STACK_SIZE + GUARD_PAGE)
; mmap: rdx = prot: mprotect-style access permissions
- mov edx, (PROT_WRITE | PROT_READ)
+ lea edx, [rcx + 3] ; mov edx, (PROT_READ | PROT_WRITE)
; mmap: r10 = flags: configuration flags for mapping:
; - MAP_ANONYMOUS: there is no file backing this buffer
; - MAP_PRIVATE: only this process can see thread's stack
; - MAP_STACK: no-op; inform kernel that this is a stack
- mov r10, (MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK)
+ mov r10d, (MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK)
; mmap: r8 = fd: ignored for MAP_ANONYMOUS, recommended -1
- mov r8, -1
+ lea r8, [rcx - 1] ; mov r8, -1
; mmap: r9 = offset: should be 0 when MAP_ANONYMOUS is used
xor r9, r9
; mmap: rax = system call ID
- mov eax, SYS_MMAP
- ; mmap: rax = mmap(rdi, rsi, rdx, r10, r8, 9)
+ lea eax, [rcx + SYS_MMAP] ; mov eax, SYS_MMAP
+ ; mmap: rax = mmap(rdi, rsi, rdx, r10, (r8), (r9))
syscall
; Pop these now before we start branching. Those registers
; won't be used by the next system calls, so they're safe.
- pop r8 ; function
- pop r9 ; argument
+ pop rbx ; thread handle destination
+ pop r8 ; function
+ pop r9 ; argument
; Check result of mmap: negative means failure,
; otherwise rax is the address of the new mapping.
@@ -145,12 +150,13 @@ linen_thread_create:
; mprotect: rdx = prot: access permissions; zero for none
xor edx, edx
; mprotect: rax = system call ID
- mov eax, SYS_MPROTECT
+ xor eax, eax
+ mov al, SYS_MPROTECT
; mprotect: rax = mprotect(rdi, rsi, rdx)
syscall
; Check result of mprotect: nonzero means failure
- test rax, rax
+ test eax, eax
jnz create_return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -162,7 +168,7 @@ linen_thread_create:
; once in the parent (0 if success) and once in the child (the TID).
; See: man 2 clone
- ; clone: rsi = stack
+ ; clone: rsi = stack: pointer for child's initial rsp
; Currently rdi points to the lowest byte of the stack area.
; Again, stacks grow downward, so we calculate the address of
; the top qword to use as the child thread's starting point.
@@ -194,14 +200,14 @@ linen_thread_create:
; clone: r8 = tls: ignored unless CLONE_SETTLS is used
; clone: rax = system call ID
- mov eax, SYS_CLONE
+ mov al, SYS_CLONE
; clone: rax = clone(rdi, rsi, (rdx), r10, (r8));
syscall
; Ideally, both parent and new-born child are executing this code now.
; Check result of clone:
- test rax, rax
+ test eax, eax
js create_return ; Negative means failure
jnz create_success ; Positive means we're in the parent thread
; Zero means we're in the child thread
@@ -220,10 +226,16 @@ linen_thread_create:
; Once done, leave function's return value lying around
push rax
- ; Exit the thread with return value 0
+ ; Exit the thread with status 0 using the exit system call.
+ ; See: man 2 exit
+
+ ; exit: rdi = status to report
xor edi, edi
- mov rax, SYS_EXIT
- syscall ; (never returns)
+ ; exit: rax = system call ID
+ xor eax, eax
+ mov al, SYS_EXIT
+ ; exit: call never returns
+ syscall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Clean up in parent thread ;;;;