home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <pc.h>
-
- typedef int BOOL;
- #define FALSE 0
- #define TRUE 1
-
- #include "Task.h"
-
- #define dprintf if(0)printf
-
- static Task *thisTask=0;
- static Task *priviligedTask=0;
- static Task *task_list=0;
-
- void TaskList()
- {
- Task *t;
- for (t=task_list; t; t=t->next)
- {
- char *rs="Unknown";
- switch (t->run_state)
- {
- case Task::Running: rs="Running"; break;
- case Task::Blocked: rs="Blocked"; break;
- case Task::Waiting: rs="Waiting"; break;
- case Task::Dead: rs="Dead"; break;
- }
- dprintf(" 0x%08x p=0x%08x s=%s%c\n", t, t->parent, rs,
- t==thisTask?'*':' ');
- }
- }
-
- static int fall_off_end()
- {
- int rv;
- asm("movl %%eax,%0" : "=g" (rv) );
- Return(rv);
- return 0;
- }
-
- Task::Task(TaskProc proc, int val, void* ptr, int stacksize, int priviliged)
- {
- prev = 0;
- next = task_list;
- if (task_list)
- task_list->prev = this;
- task_list = this;
- parent = thisTask;
- run_state = Running;
- setjmp(state);
- stack = 0;
- if (proc) {
- stack_len = stacksize;
- stack = new unsigned[stacksize];
- unsigned *sp = stack+stacksize;
- *--sp = (unsigned) ptr;
- *--sp = (unsigned) val;
- *--sp = (unsigned) fall_off_end;
- state->esp = (unsigned)(stack+stacksize-3);
- state->eip = (unsigned long) proc;
- }
- if (thisTask == 0)
- thisTask = this;
- if(priviliged)
- priviligedTask = this;
- dprintf("Task::Task -> 0x%x\n", this);
- }
-
- Task::~Task()
- {
- dprintf("Task::~Task <= 0x%x\n", this);
- if (task_list == this)
- task_list = next;
- if (prev)
- prev->next = next;
- if (next)
- next->prev = prev;
- if (parent)
- parent->run_state = Running;
- if (stack)
- delete stack;
- if (this == thisTask)
- Yield();
- TaskList();
- }
-
- int Task::ReturnValue()
- {
- return ret_val;
- }
-
- int Wait(Task* child)
- {
- int rv;
- int waiting = 1;
- if (child)
- dprintf("Task::Wait for 0x%x\n", child);
- else
- dprintf("Task::Wait\n");
- while (waiting) {
- waiting = 0;
- if(child && child->run_state==Task::Dead) {
- rv = child->ret_val;
- delete child;
- return rv;
- }
-
- Task *t, *tn;
- for (t=task_list; t; t=tn) {
- tn = t->next;
- if (t->parent == thisTask) {
- if (t->run_state == Task::Dead) {
- dprintf("Dead child 0x%x\n", t);
- delete t;
- }
- else {
- dprintf("Running child 0x%x\n", t);
- waiting = 1;
- }
- }
- }
- if (waiting) {
- dprintf("parent waiting...\n");
- thisTask->run_state = Task::Waiting;
- Yield();
- }
- }
- return 0;
- }
-
- void Yield()
- {
- dprintf("Task::Yield 0x%x -> ", thisTask);
- if(priviligedTask && thisTask!=priviligedTask &&
- priviligedTask->run_state==Task::Running) {
- if (setjmp(thisTask->state))
- return;
- thisTask = priviligedTask;
- dprintf("0x%x P(0x%x)\n", thisTask, thisTask->state->eip);
- longjmp(thisTask->state, 1);
- }
-
- Task *p = thisTask;
- do {
- p = (p->next ? p->next : task_list);
- } while(p!=thisTask && p->run_state!=Task::Running);
-
- if(p->run_state != Task::Running) {
- fprintf(stderr, "Wedged.\n");
- TaskList();
- abort();
- }
- else if(p != thisTask) {
- if (setjmp(thisTask->state))
- return;
- thisTask = p;
- dprintf("0x%x (0x%x)\n", thisTask, thisTask->state->eip);
- longjmp(thisTask->state, 1);
- }
- }
-
- void Unblock(Task *blocked_task)
- {
- if(blocked_task->run_state == Task::Blocked)
- blocked_task->run_state = Task::Running;
- }
-
- void Block(Task **p)
- {
- thisTask->run_state = Task::Blocked;
- *p = thisTask;
- Yield();
- }
-
- void Kill(Task *victim, int rv)
- {
- Task *t;
- BOOL found = FALSE;
-
- dprintf("Task::Kill(%d) <- 0x%x\n", rv, victim);
- for (t=task_list; t; t=t->next)
- if(t == victim) {
- found = TRUE;
- if(victim->run_state != Task::Dead) {
- victim->ret_val = rv;
- victim->run_state = Task::Dead;
- if (victim->parent)
- victim->parent->run_state = Task::Running;
- }
- }
-
- if(!found) {
- fprintf(stderr, "Task::Kill - victim not found.\n");
- abort();
- }
-
- for (t=task_list; t; t=t->next) /* Kill all children of a victim. */
- if(t->parent == victim)
- Kill(t, rv);
-
- if(victim == thisTask)
- Yield();
- }
-
- void Return(int rv)
- {
- Kill(thisTask, rv);
- }
-