home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / gnu / djgpp / samples / grtask / task.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-15  |  4.3 KB  |  211 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <pc.h>
  4.  
  5. typedef int BOOL;
  6. #define FALSE    0
  7. #define TRUE    1
  8.  
  9. #include "Task.h"
  10.  
  11. #define dprintf if(0)printf
  12.  
  13. static Task *thisTask=0;
  14. static Task *priviligedTask=0;
  15. static Task *task_list=0;
  16.  
  17. void TaskList()
  18. {
  19.   Task *t;
  20.   for (t=task_list; t; t=t->next)
  21.   {
  22.     char *rs="Unknown";
  23.     switch (t->run_state)
  24.     {
  25.       case Task::Running: rs="Running"; break;
  26.       case Task::Blocked: rs="Blocked"; break;
  27.       case Task::Waiting: rs="Waiting"; break;
  28.       case Task::Dead: rs="Dead"; break;
  29.     }
  30.     dprintf("  0x%08x p=0x%08x s=%s%c\n", t, t->parent, rs,
  31.                     t==thisTask?'*':' ');
  32.   }
  33. }
  34.  
  35. static int fall_off_end()
  36. {
  37.   int rv;
  38.   asm("movl %%eax,%0" : "=g" (rv) );
  39.   Return(rv);
  40.   return 0;
  41. }
  42.  
  43. Task::Task(TaskProc proc, int val, void* ptr, int stacksize, int priviliged)
  44. {
  45.   prev = 0;
  46.   next = task_list;
  47.   if (task_list)
  48.     task_list->prev = this;
  49.   task_list = this;
  50.   parent = thisTask;
  51.   run_state = Running;
  52.   setjmp(state);
  53.   stack = 0;
  54.   if (proc) {
  55.     stack_len = stacksize;
  56.     stack = new unsigned[stacksize];
  57.     unsigned *sp = stack+stacksize;
  58.     *--sp = (unsigned) ptr;
  59.     *--sp = (unsigned) val;
  60.     *--sp = (unsigned) fall_off_end;
  61.     state->esp = (unsigned)(stack+stacksize-3);
  62.     state->eip = (unsigned long) proc;
  63.     }
  64.   if (thisTask == 0)
  65.     thisTask = this;
  66.   if(priviliged)
  67.       priviligedTask = this;
  68.   dprintf("Task::Task -> 0x%x\n", this);
  69. }
  70.  
  71. Task::~Task()
  72. {
  73.   dprintf("Task::~Task <= 0x%x\n", this);
  74.   if (task_list == this)
  75.     task_list = next;
  76.   if (prev)
  77.     prev->next = next;
  78.   if (next)
  79.     next->prev = prev;
  80.   if (parent)
  81.     parent->run_state = Running;
  82.   if (stack)
  83.     delete stack;
  84.   if (this == thisTask)
  85.     Yield();
  86.   TaskList();
  87. }
  88.  
  89. int Task::ReturnValue()
  90. {
  91.   return ret_val;
  92. }
  93.  
  94. int Wait(Task* child)
  95. {
  96.   int rv;
  97.   int waiting = 1;
  98.   if (child)
  99.     dprintf("Task::Wait for 0x%x\n", child);
  100.   else
  101.     dprintf("Task::Wait\n");
  102.   while (waiting) {
  103.     waiting = 0;
  104.       if(child && child->run_state==Task::Dead) {
  105.         rv = child->ret_val;
  106.         delete child;
  107.         return rv;
  108.         }
  109.  
  110.     Task *t, *tn;
  111.     for (t=task_list; t; t=tn) {
  112.       tn = t->next;
  113.       if (t->parent == thisTask) {
  114.         if (t->run_state == Task::Dead) {
  115.           dprintf("Dead child 0x%x\n", t);
  116.           delete t;
  117.           }
  118.         else {
  119.           dprintf("Running child 0x%x\n", t);
  120.           waiting = 1;
  121.         }
  122.       }
  123.     }
  124.     if (waiting) {
  125.       dprintf("parent waiting...\n");
  126.       thisTask->run_state = Task::Waiting;
  127.       Yield();
  128.     }
  129.   }
  130.  return 0;
  131. }
  132.  
  133. void Yield()
  134. {
  135.  dprintf("Task::Yield 0x%x -> ", thisTask);
  136.  if(priviligedTask && thisTask!=priviligedTask &&
  137.                           priviligedTask->run_state==Task::Running)    {
  138.       if (setjmp(thisTask->state))
  139.         return;
  140.       thisTask = priviligedTask;
  141.     dprintf("0x%x P(0x%x)\n", thisTask, thisTask->state->eip);
  142.       longjmp(thisTask->state, 1);
  143.     }
  144.  
  145.  Task *p = thisTask;
  146.  do    {
  147.     p = (p->next ? p->next : task_list);
  148.       } while(p!=thisTask && p->run_state!=Task::Running);
  149.  
  150.  if(p->run_state != Task::Running)    {
  151.     fprintf(stderr, "Wedged.\n");
  152.     TaskList();
  153.     abort();
  154.       }
  155.  else if(p != thisTask)    {
  156.       if (setjmp(thisTask->state))
  157.         return;
  158.       thisTask = p;
  159.     dprintf("0x%x (0x%x)\n", thisTask, thisTask->state->eip);
  160.       longjmp(thisTask->state, 1);
  161.       }
  162. }
  163.  
  164. void Unblock(Task *blocked_task)
  165. {
  166.  if(blocked_task->run_state == Task::Blocked)
  167.      blocked_task->run_state = Task::Running;
  168. }
  169.  
  170. void Block(Task **p)
  171. {
  172.  thisTask->run_state = Task::Blocked;
  173.  *p = thisTask;
  174.  Yield();
  175. }
  176.  
  177. void Kill(Task *victim, int rv)
  178. {
  179.  Task *t;
  180.  BOOL found = FALSE;
  181.  
  182.  dprintf("Task::Kill(%d) <- 0x%x\n", rv, victim);
  183.  for (t=task_list; t; t=t->next)
  184.       if(t == victim)    {
  185.         found = TRUE;
  186.         if(victim->run_state != Task::Dead)    {
  187.               victim->ret_val = rv;
  188.               victim->run_state = Task::Dead;
  189.               if (victim->parent)
  190.                 victim->parent->run_state = Task::Running;
  191.             }
  192.         }
  193.  
  194.  if(!found)    {
  195.      fprintf(stderr, "Task::Kill - victim not found.\n");
  196.     abort();
  197.     }
  198.  
  199.   for (t=task_list; t; t=t->next)    /* Kill all children of a victim. */
  200.     if(t->parent == victim)
  201.         Kill(t, rv);
  202.  
  203.  if(victim == thisTask)
  204.      Yield();
  205. }
  206.  
  207. void Return(int rv)
  208. {
  209.  Kill(thisTask, rv);
  210. }
  211.