task.c (3216B)
1 /* Copyright 1998-1999, Brian J. Swetland. All rights reserved. 2 ** Distributed under the terms of the OpenBLT License 3 */ 4 5 #include "kernel.h" 6 #include "memory.h" 7 #include "task.h" 8 9 extern char *gdt; 10 extern int live_tasks; 11 12 void thread_bootstrap(void); 13 void kthread_bootstrap(void); 14 15 void task_wake(task_t *task, int status) 16 { 17 task->status = status; 18 rsrc_enqueue(run_queue, task); 19 } 20 21 int wait_on(resource_t *rsrc) 22 { 23 task_t *task = current; 24 task->status = 0; 25 rsrc_enqueue(rsrc, task); 26 swtch(); 27 return current->status; 28 } 29 30 void task_destroy(task_t *task) 31 { 32 team_t *team = task->rsrc.owner; 33 34 if(task == current) panic("cannot destroy the running task"); 35 36 TCLRMAGIC(task); 37 38 if(task->stack_area) { 39 area_destroy(team->aspace, task->stack_area->rsrc.id); 40 } 41 42 kfreepage(task->kstack); 43 rsrc_release(&task->rsrc); 44 kfree(task_t, task); 45 46 team->refcount--; 47 if(team->refcount == 0) team_destroy(team); 48 } 49 50 /* create a new task, complete with int stack */ 51 task_t *task_create(team_t *team, uint32 ip, uint32 sp, int kernel) 52 { 53 task_t *t = kmalloc(task_t); 54 uint32 *SP; 55 56 t->kstack = kgetpages(1); 57 t->cr3 = team->aspace->pdirphys; 58 59 t->esp = (uint32) ( ((char *) t->kstack) + 4092 ); 60 t->esp0 = t->esp; 61 t->scount = 0; 62 t->stack_area = NULL; 63 t->team = team; 64 65 t->node.data = t; 66 67 /* prep the kernel stack for first switch 68 ** SS 69 ** ESP 70 ** EFLAGS 71 ** CS 72 ** EIP -- thread_bootstrap will iret into the thread 73 ** 74 ** <thread_bootstrap> 75 ** EFLAGS 76 ** EBP (0) 77 ** ESI (0) 78 ** EDI (0) -- stuff for _context_switch to pop off / return to 79 ** EBX (0) 80 */ 81 82 SP = (uint32*) t->esp; 83 84 if(kernel) { 85 SP--; *SP = SEL_KDATA; 86 SP--; *SP = sp - 4*5; 87 SP--; *SP = 0x3202; 88 SP--; *SP = SEL_KCODE; 89 SP--; *SP = ip; 90 SP--; *SP = (uint32) thread_bootstrap; 91 } else { 92 SP--; *SP = SEL_UDATA | 3; 93 SP--; *SP = sp - 4*5; 94 SP--; *SP = 0x3202; 95 SP--; *SP = SEL_UCODE | 3; 96 SP--; *SP = ip; 97 SP--; *SP = (uint32) thread_bootstrap; 98 } 99 SP--; *SP = 0x3002; 100 SP--; *SP = 0; 101 SP--; *SP = 0; 102 SP--; *SP = 0; 103 SP--; *SP = 0; 104 105 t->esp = (uint32) SP; 106 107 // kprintf("thr:%x/%x:%d",sp,ip,(kernel ? SEL_KCODE : (SEL_UCODE | 3))); 108 109 t->irq = 0; 110 t->flags = tREADY; 111 t->waiting_on = NULL; 112 team->refcount++; 113 114 TSETMAGIC(t); 115 return t; 116 } 117 118 119 int thr_wait(int thr_id) 120 { 121 task_t *task = rsrc_find_task(thr_id); 122 123 if(task) { 124 wait_on((resource_t *)task); 125 return ERR_NONE; 126 } else { 127 return ERR_RESOURCE; 128 } 129 } 130 131 int thr_spawn(uint32 ip, uint32 sp, 132 uint32 area0, uint32 vaddr0, 133 uint32 area1, uint32 vaddr1, 134 const char *name) 135 { 136 aspace_t *aspace; 137 task_t *task; 138 team_t *team; 139 area_t *area; 140 int id; 141 void *addr; 142 143 team = team_create(); 144 aspace = team->aspace; 145 task = task_create(team, ip, sp, 0); 146 task->ustack = 0; 147 rsrc_bind(&task->rsrc, RSRC_TASK, team); 148 149 id = area_clone(aspace, area0, vaddr0, &addr, 0); 150 team->heap_id = id; 151 152 if(area = rsrc_find_area(id)) { 153 rsrc_set_owner(&area->rsrc, team); 154 } 155 156 id = area_clone(aspace, area1, vaddr1, &addr, 0); 157 if(area = rsrc_find_area(id)) rsrc_set_owner(&area->rsrc, team); 158 159 rsrc_set_name(&task->rsrc, name); 160 rsrc_set_name(&team->rsrc, name); 161 rsrc_enqueue(run_queue, task); 162 live_tasks++; 163 164 return task->rsrc.id; 165 } 166 167