home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progc / djsrc106.arj / TASK.CC < prev    next >
C/C++ Source or Header  |  1991-03-20  |  3KB  |  164 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <pc.h>
  4.  
  5. #include "Task.h"
  6.  
  7. #define dprintf if(0)printf
  8.  
  9. Task *thisTask=0;
  10.  
  11. static Task *task_list=0;
  12.  
  13. void TaskList()
  14. {
  15.   Task *t;
  16.   for (t=task_list; t; t=t->next)
  17.   {
  18.     char *rs="Unknown";
  19.     switch (t->run_state)
  20.     {
  21.       case Task::Running: rs="Running"; break;
  22.       case Task::Blocked: rs="Blocked"; break;
  23.       case Task::Waiting: rs="Waiting"; break;
  24.       case Task::Dead: rs="Dead"; break;
  25.     }
  26.     dprintf("  0x%08x p=0x%08x s=%s\n", t, t->parent, rs);
  27.   }
  28. }
  29.  
  30. static int fall_off_end()
  31. {
  32.   int rv;
  33.   asm("movl %%eax,%0" : "=g" (rv) );
  34.   Return(rv);
  35.   return 0;
  36. }
  37.  
  38. Task::Task(TaskProc proc, int val, void* ptr, int stacksize)
  39. {
  40.   prev = 0;
  41.   next = task_list;
  42.   if (task_list)
  43.     task_list->prev = this;
  44.   task_list = this;
  45.   parent = thisTask;
  46.   run_state = Running;
  47.   memset(state, 0, sizeof(state));
  48.   stack = 0;
  49.   if (proc)
  50.   {
  51.     stack_len = stacksize;
  52.     stack = new unsigned[stacksize];
  53.     unsigned *sp = stack+stacksize;
  54.     *--sp = (unsigned) ptr;
  55.     *--sp = (unsigned) val;
  56.     *--sp = (unsigned) fall_off_end;
  57.     state->esp = (unsigned)(stack+stacksize-3);
  58.     state->eip = (unsigned long) proc;
  59.   }
  60.   if (thisTask == 0)
  61.     thisTask = this;
  62.   dprintf("Task::Task -> 0x%x\n", this);
  63. }
  64.  
  65. Task::~Task()
  66. {
  67.   dprintf("Task::~Task <= 0x%x\n", this);
  68.   if (task_list == this)
  69.     task_list = next;
  70.   if (prev)
  71.     prev->next = next;
  72.   if (next)
  73.     next->prev = prev;
  74.   if (parent)
  75.     parent->run_state = Running;
  76.   if (stack)
  77.     delete stack;
  78.   if (this == thisTask)
  79.     Yield();
  80.   TaskList();
  81. }
  82.  
  83. int Task::ReturnValue()
  84. {
  85.   return ret_val;
  86. }
  87.  
  88. int Wait(Task* child)
  89. {
  90.   int rv;
  91.   int waiting = 1;
  92.   if (child)
  93.     dprintf("Task::Wait for 0x%x\n", child);
  94.   else
  95.     dprintf("Task::Wait\n");
  96.   while (waiting)
  97.   {
  98.     waiting = 0;
  99.     if (child)
  100.     {
  101.       if (child->run_state == Task::Dead)
  102.       {
  103.         rv = child->ret_val;
  104.         delete child;
  105.         return rv;
  106.       }
  107.     }
  108.  
  109.     Task *t, *tn;
  110.     for (t=task_list; t; t=tn)
  111.     {
  112.       tn = t->next;
  113.       if (t->parent == thisTask)
  114.       {
  115.         if (t->run_state == Task::Dead)
  116.         {
  117.           dprintf("Dead child 0x%x\n", t);
  118.           delete t;
  119.         }
  120.         else
  121.         {
  122.           dprintf("Running child 0x%x\n", t);
  123.           waiting = 1;
  124.         }
  125.       }
  126.     }
  127.     if (waiting)
  128.     {
  129.       dprintf("parent waiting...\n");
  130.       thisTask->run_state = Task::Waiting;
  131.       Yield();
  132.     }
  133.   }
  134. }
  135.  
  136. void Return(int rv)
  137. {
  138.   dprintf("Task::Return(%d) <- 0x%x\n", rv, thisTask);
  139.   thisTask->ret_val = rv;
  140.   thisTask->run_state = Task::Dead;
  141.   if (thisTask->parent)
  142.     thisTask->parent->run_state = Task::Running;
  143.   Yield();
  144. }
  145.  
  146. void Yield()
  147. {
  148.   dprintf("Task::Yield 0x%x -> ", thisTask);
  149.   fflush(stdout);
  150.   if (setjmp(thisTask->state))
  151.     return;
  152.   while (1)
  153.   {
  154.     if (thisTask->next)
  155.       thisTask = thisTask->next;
  156.     else
  157.       thisTask = task_list;
  158.     if (thisTask->run_state == Task::Running)
  159.       break;
  160.   }
  161.   dprintf("0x%x (0x%x)\n", thisTask, thisTask->state->eip);
  162.   longjmp(thisTask->state,1);
  163. }
  164.