Home | History | Annotate | Download | only in thread
      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