forked from KolibriOS/kolibrios
thread management for the system library
git-svn-id: svn://kolibrios.org@6811 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
6198f1e4c9
commit
9be5e01ff1
@ -44,6 +44,7 @@ include 'malloc.inc'
|
||||
include 'peloader.inc'
|
||||
include 'modules.inc'
|
||||
include 'cmdline.inc'
|
||||
include 'thread.inc'
|
||||
|
||||
proc syscall_int40
|
||||
int 0x40
|
||||
@ -302,6 +303,8 @@ export 'kolibri.dll' \
|
||||
, dlopen, 'dlopen' \
|
||||
, dlclose, 'dlclose' \
|
||||
, dlsym, 'dlsym' \
|
||||
, create_thread, 'create_thread' \
|
||||
, exit_thread, 'exit_thread' \
|
||||
|
||||
end data
|
||||
|
||||
|
84
programs/system/os/thread.inc
Normal file
84
programs/system/os/thread.inc
Normal file
@ -0,0 +1,84 @@
|
||||
; Threads management.
|
||||
|
||||
; int create_thread(int (*proc)(void *param), void *param, int stack_size)
|
||||
; Creates a thread that executes the given function proc(param).
|
||||
; Returns -1 on error, TID otherwise.
|
||||
; If proc(param) returns, the returned value is passed to exit_thread().
|
||||
; If stack_size is zero, uses the value from PE header of the executable.
|
||||
proc create_thread stdcall uses ebx, thread_proc, param, stack_size
|
||||
; 1. Determine stack size.
|
||||
; Align stack_size up to page boundary;
|
||||
mov ecx, [stack_size]
|
||||
add ecx, 0xFFF
|
||||
and ecx, not 0xFFF
|
||||
jnz .stack_size_ok
|
||||
; if this results in zero, read the value from the header of main module.
|
||||
mov eax, [modules_list + MODULE.next]
|
||||
mov eax, [eax + MODULE.base]
|
||||
mov ecx, [eax+STRIPPED_PE_HEADER.SizeOfStackReserve]
|
||||
cmp byte [eax], 'M'
|
||||
jnz .stack_size_ok
|
||||
mov ecx, [eax+3Ch]
|
||||
mov ecx, [eax+ecx+IMAGE_NT_HEADERS.OptionalHeader.SizeOfStackReserve]
|
||||
.stack_size_ok:
|
||||
mov [stack_size], ecx
|
||||
; 2. Allocate the stack.
|
||||
mov eax, 68
|
||||
mov ebx, 12
|
||||
call FS_SYSCALL_PTR
|
||||
test eax, eax
|
||||
jz .fail
|
||||
; 3. Copy parameters to the stack.
|
||||
lea edx, [eax+ecx-16]
|
||||
mov [edx], ecx
|
||||
mov ebx, FS_SYSCALL_PTR
|
||||
mov [edx+4], ebx
|
||||
mov ebx, [thread_proc]
|
||||
mov [edx+8], ebx
|
||||
mov ebx, [param]
|
||||
mov [edx+12], ebx
|
||||
; 4. Call the kernel to create the thread.
|
||||
mov eax, 51
|
||||
mov ebx, 1
|
||||
mov ecx, internal_thread_start
|
||||
call FS_SYSCALL_PTR
|
||||
cmp eax, -1
|
||||
jz .fail_free
|
||||
ret
|
||||
.fail_free:
|
||||
mov eax, 68
|
||||
mov ebx, 13
|
||||
lea ecx, [edx+12]
|
||||
sub ecx, [stack_size]
|
||||
call FS_SYSCALL_PTR
|
||||
xor eax, eax
|
||||
.fail:
|
||||
dec eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; void exit_thread(int exit_code)
|
||||
; Terminates the current thread.
|
||||
; exit_code is reserved; currently ignored
|
||||
proc exit_thread stdcall, exit_code
|
||||
or eax, -1
|
||||
call FS_SYSCALL_PTR
|
||||
endp
|
||||
|
||||
; Real entry point of threads created by create_thread.
|
||||
; Provides user-space initialization of the thread,
|
||||
; calls user-provided thread routine,
|
||||
; passes the returned value to exit_thread.
|
||||
proc internal_thread_start
|
||||
pop eax ; stack_size
|
||||
lea ecx, [esp+12]
|
||||
mov FS_STACK_MAX, ecx
|
||||
sub ecx, eax
|
||||
mov FS_STACK_MIN, ecx
|
||||
pop FS_SYSCALL_PTR ; from caller's FS_SYSCALL_PTR
|
||||
pop eax ; thread_proc
|
||||
call eax ; param is still on the stack
|
||||
push eax ; exit_code
|
||||
push 0 ; no return address
|
||||
jmp exit_thread
|
||||
endp
|
Loading…
Reference in New Issue
Block a user