openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

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