-
Notifications
You must be signed in to change notification settings - Fork 0
/
threads32.c
51 lines (46 loc) · 1.29 KB
/
threads32.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include "threads.h"
#include <stdlib.h> /* abort */
#include <string.h> /* memset */
void thread_switch(struct thread_context *to, struct thread_context *from);
__asm__(
"\n .globl thread_switch"
"\nthread_switch:"
"\n movl 0x04(%esp), %ecx" /* to */
"\n movl 0x08(%esp), %eax" /* from */
"\n movl %ebp, 0x00(%eax)" /* regs into 'from' */
"\n movl %ebx, 0x04(%eax)"
"\n movl %esi, 0x08(%eax)"
"\n movl %edi, 0x0C(%eax)"
"\n movl %esp, 0x10(%eax)"
"\n"
"\n movl 0x00(%ecx), %ebp" /* regs from 'to' */
"\n movl 0x04(%ecx), %ebx"
"\n movl 0x08(%ecx), %esi"
"\n movl 0x0C(%ecx), %edi"
"\n movl 0x10(%ecx), %esp"
"\n retl"
);
static void push(uint32_t *esp, uint32_t val)
{
*esp -= 4;
*(uint32_t*)*esp = (uint32_t)val;
}
static void start_thread(void (*func)(void *arg), void *arg)
{
func(arg);
abort();
}
void thread_new(
struct thread_context *new,
struct thread_context *from,
void *stack_top,
void (*func)(void *), void *arg)
{
memset(new, 0, sizeof *new);
new->esp = (uint32_t)stack_top;
push(&new->esp, (uint32_t)arg);
push(&new->esp, (uint32_t)func);
push(&new->esp, (uint32_t)NULL); /* ret-addr: We should never jump here */
push(&new->esp, (uint32_t)&start_thread); /* Jump-to */
thread_switch(new, from);
}