diff options
Diffstat (limited to 'core/thread/start_thread.c')
-rw-r--r-- | core/thread/start_thread.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/core/thread/start_thread.c b/core/thread/start_thread.c new file mode 100644 index 0000000..2e4320a --- /dev/null +++ b/core/thread/start_thread.c @@ -0,0 +1,69 @@ +#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; +} |