1 | #include <string.h> |
---|
2 | #include <stdlib.h> |
---|
3 | #include <com32.h> |
---|
4 | #include "core.h" |
---|
5 | #include "thread.h" |
---|
6 | |
---|
7 | #define REAL_MODE_STACK_SIZE 4096 |
---|
8 | #define MIN_STACK_SIZE 16384 |
---|
9 | #define THREAD_ALIGN 64 /* Thread alignment */ |
---|
10 | |
---|
11 | extern void __start_thread(void); |
---|
12 | |
---|
13 | struct thread *start_thread(const char *name, size_t stack_size, int prio, |
---|
14 | void (*start_func)(void *), void *func_arg) |
---|
15 | { |
---|
16 | irq_state_t irq; |
---|
17 | struct thread *curr, *t; |
---|
18 | char *stack, *rmstack; |
---|
19 | const size_t thread_mask = THREAD_ALIGN - 1; |
---|
20 | struct thread_stack *sp; |
---|
21 | |
---|
22 | if (stack_size < MIN_STACK_SIZE) |
---|
23 | stack_size = MIN_STACK_SIZE; |
---|
24 | |
---|
25 | stack_size = (stack_size + thread_mask) & ~thread_mask; |
---|
26 | stack = malloc(stack_size + sizeof(struct thread)); |
---|
27 | if (!stack) |
---|
28 | return NULL; |
---|
29 | rmstack = lmalloc(REAL_MODE_STACK_SIZE); |
---|
30 | if (!rmstack) { |
---|
31 | free(stack); |
---|
32 | return NULL; |
---|
33 | } |
---|
34 | |
---|
35 | t = (struct thread *)stack; |
---|
36 | memset(t, 0, sizeof *t); |
---|
37 | t->stack = stack; |
---|
38 | t->rmstack = rmstack; |
---|
39 | stack += sizeof(struct thread); |
---|
40 | |
---|
41 | /* sp allocated from the end of the stack */ |
---|
42 | sp = (struct thread_stack *)(stack + stack_size) - 1; |
---|
43 | t->esp = sp; |
---|
44 | |
---|
45 | sp->errno = 0; |
---|
46 | sp->rmss = SEG(rmstack); |
---|
47 | sp->rmsp = REAL_MODE_STACK_SIZE; |
---|
48 | sp->esi = (size_t)start_func; |
---|
49 | sp->edi = (size_t)func_arg; |
---|
50 | sp->ebx = irq_state(); /* Inherit the IRQ state from the spawner */ |
---|
51 | sp->eip = __start_thread; |
---|
52 | t->prio = prio; |
---|
53 | t->name = name; |
---|
54 | |
---|
55 | irq = irq_save(); |
---|
56 | curr = current(); |
---|
57 | |
---|
58 | t->thread_magic = THREAD_MAGIC; |
---|
59 | |
---|
60 | t->list.prev = &curr->list; |
---|
61 | t->list.next = curr->list.next; |
---|
62 | curr->list.next = &t->list; |
---|
63 | t->list.next->prev = &t->list; |
---|
64 | |
---|
65 | __schedule(); |
---|
66 | |
---|
67 | irq_restore(irq); |
---|
68 | return t; |
---|
69 | } |
---|