| #include <string.h> |
| #include <stdlib.h> |
| #include <com32.h> |
| #include "core.h" |
| #include "thread.h" |
| |
| #define REAL_MODE_STACK_SIZE 4096 |
| #define MIN_STACK_SIZE 16384 |
| #define THREAD_ALIGN 64 /* Thread alignment */ |
| |
| extern void __start_thread(void); |
| |
| struct thread *start_thread(const char *name, size_t stack_size, int prio, |
| void (*start_func)(void *), void *func_arg) |
| { |
| irq_state_t irq; |
| struct thread *curr, *t; |
| char *stack, *rmstack; |
| const size_t thread_mask = THREAD_ALIGN - 1; |
| struct thread_stack *sp; |
| |
| if (stack_size < MIN_STACK_SIZE) |
| stack_size = MIN_STACK_SIZE; |
| |
| stack_size = (stack_size + thread_mask) & ~thread_mask; |
| stack = malloc(stack_size + sizeof(struct thread)); |
| if (!stack) |
| return NULL; |
| rmstack = lmalloc(REAL_MODE_STACK_SIZE); |
| if (!rmstack) { |
| free(stack); |
| return NULL; |
| } |
| |
| t = (struct thread *)stack; |
| memset(t, 0, sizeof *t); |
| t->stack = stack; |
| t->rmstack = rmstack; |
| stack += sizeof(struct thread); |
| |
| /* sp allocated from the end of the stack */ |
| sp = (struct thread_stack *)(stack + stack_size) - 1; |
| t->esp = sp; |
| |
| sp->errno = 0; |
| sp->rmss = SEG(rmstack); |
| sp->rmsp = REAL_MODE_STACK_SIZE; |
| sp->esi = (size_t)start_func; |
| sp->edi = (size_t)func_arg; |
| sp->ebx = irq_state(); /* Inherit the IRQ state from the spawner */ |
| sp->eip = __start_thread; |
| t->prio = prio; |
| t->name = name; |
| |
| irq = irq_save(); |
| curr = current(); |
| |
| t->thread_magic = THREAD_MAGIC; |
| |
| t->list.prev = &curr->list; |
| t->list.next = curr->list.next; |
| curr->list.next = &t->list; |
| t->list.next->prev = &t->list; |
| |
| __schedule(); |
| |
| irq_restore(irq); |
| return t; |
| } |