home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <pc.h>
-
- #include "Task.h"
-
- #define dprintf if(0)printf
-
- Task *thisTask=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\n", t, t->parent, rs);
- }
- }
-
- 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)
- {
- prev = 0;
- next = task_list;
- if (task_list)
- task_list->prev = this;
- task_list = this;
- parent = thisTask;
- run_state = Running;
- memset(state, 0, sizeof(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;
- 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)
- {
- if (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();
- }
- }
- }
-
- void Return(int rv)
- {
- dprintf("Task::Return(%d) <- 0x%x\n", rv, thisTask);
- thisTask->ret_val = rv;
- thisTask->run_state = Task::Dead;
- if (thisTask->parent)
- thisTask->parent->run_state = Task::Running;
- Yield();
- }
-
- void Yield()
- {
- dprintf("Task::Yield 0x%x -> ", thisTask);
- fflush(stdout);
- if (setjmp(thisTask->state))
- return;
- while (1)
- {
- if (thisTask->next)
- thisTask = thisTask->next;
- else
- thisTask = task_list;
- if (thisTask->run_state == Task::Running)
- break;
- }
- dprintf("0x%x (0x%x)\n", thisTask, thisTask->state->eip);
- longjmp(thisTask->state,1);
- }
-