Rev 6811 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6811 | clevermous | 1 | ; Threads management. |
2 | |||
3 | ; int create_thread(int (*proc)(void *param), void *param, int stack_size) |
||
4 | ; Creates a thread that executes the given function proc(param). |
||
5 | ; Returns -1 on error, TID otherwise. |
||
6 | ; If proc(param) returns, the returned value is passed to exit_thread(). |
||
7 | ; If stack_size is zero, uses the value from PE header of the executable. |
||
8 | proc create_thread stdcall uses ebx, thread_proc, param, stack_size |
||
9 | ; 1. Determine stack size. |
||
10 | ; Align stack_size up to page boundary; |
||
11 | mov ecx, [stack_size] |
||
12 | add ecx, 0xFFF |
||
13 | and ecx, not 0xFFF |
||
14 | jnz .stack_size_ok |
||
15 | ; if this results in zero, read the value from the header of main module. |
||
16 | mov eax, [modules_list + MODULE.next] |
||
17 | mov eax, [eax + MODULE.base] |
||
18 | mov ecx, [eax+STRIPPED_PE_HEADER.SizeOfStackReserve] |
||
19 | cmp byte [eax], 'M' |
||
20 | jnz .stack_size_ok |
||
21 | mov ecx, [eax+3Ch] |
||
22 | mov ecx, [eax+ecx+IMAGE_NT_HEADERS.OptionalHeader.SizeOfStackReserve] |
||
23 | .stack_size_ok: |
||
24 | mov [stack_size], ecx |
||
25 | ; 2. Allocate the stack. |
||
26 | mov eax, 68 |
||
27 | mov ebx, 12 |
||
28 | call FS_SYSCALL_PTR |
||
29 | test eax, eax |
||
30 | jz .fail |
||
31 | ; 3. Copy parameters to the stack. |
||
32 | lea edx, [eax+ecx-16] |
||
33 | mov [edx], ecx |
||
34 | mov ebx, FS_SYSCALL_PTR |
||
35 | mov [edx+4], ebx |
||
36 | mov ebx, [thread_proc] |
||
37 | mov [edx+8], ebx |
||
38 | mov ebx, [param] |
||
39 | mov [edx+12], ebx |
||
40 | ; 4. Call the kernel to create the thread. |
||
41 | mov eax, 51 |
||
42 | mov ebx, 1 |
||
43 | mov ecx, internal_thread_start |
||
44 | call FS_SYSCALL_PTR |
||
45 | cmp eax, -1 |
||
46 | jz .fail_free |
||
47 | ret |
||
48 | .fail_free: |
||
49 | mov eax, 68 |
||
50 | mov ebx, 13 |
||
51 | lea ecx, [edx+12] |
||
52 | sub ecx, [stack_size] |
||
53 | call FS_SYSCALL_PTR |
||
54 | xor eax, eax |
||
55 | .fail: |
||
56 | dec eax |
||
57 | ret |
||
58 | endp |
||
59 | |||
60 | ; void exit_thread(int exit_code) |
||
61 | ; Terminates the current thread. |
||
62 | ; exit_code is reserved; currently ignored |
||
63 | proc exit_thread stdcall, exit_code |
||
6812 | clevermous | 64 | ; Use int 0x40 instead of call FS_SYSCALL_PTR, because we are freeing the stack. |
65 | mov eax, 68 |
||
66 | mov ebx, 13 |
||
67 | mov ecx, FS_STACK_MIN |
||
68 | int 0x40 |
||
6811 | clevermous | 69 | or eax, -1 |
6812 | clevermous | 70 | int 0x40 |
6811 | clevermous | 71 | endp |
72 | |||
73 | ; Real entry point of threads created by create_thread. |
||
74 | ; Provides user-space initialization of the thread, |
||
75 | ; calls user-provided thread routine, |
||
76 | ; passes the returned value to exit_thread. |
||
77 | proc internal_thread_start |
||
78 | pop eax ; stack_size |
||
79 | lea ecx, [esp+12] |
||
80 | mov FS_STACK_MAX, ecx |
||
81 | sub ecx, eax |
||
82 | mov FS_STACK_MIN, ecx |
||
83 | pop FS_SYSCALL_PTR ; from caller's FS_SYSCALL_PTR |
||
84 | pop eax ; thread_proc |
||
85 | call eax ; param is still on the stack |
||
86 | push eax ; exit_code |
||
87 | push 0 ; no return address |
||
88 | jmp exit_thread |
||
89 | endp |