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 } 70