delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1992/09/27/20:42:15

From: gkochanski AT attmail DOT com
Date: 27 Sep 92 23:52:06 GMT
To: djgpp AT sun DOT soe DOT clarkson DOT edu
Message-Version: 2
>To: internet!sun.soe.clarkson.edu!djgpp
Original-Date: Sun Sep 27 23:52:06 GMT 1992
Original-From: attmail!gkochanski (Greg Kochanski )
Mts-Message-Id: <gkochanski2712352060>
Ua-Content-Id: <gkochanski2712352060>
Email-Version: 2
Subject: Task Package Fixes
Ua-Message-Id: <gkochanski2712352060>
Original-To: attmail!internet!sun.soe.clarkson.edu!djgpp

Despite significant efforts, I was not able to get the contributed
task library (.../contrib/tasks) to do anything but wedge itself,
even on its own test program.
To console myself, I upgraded the supplied (and functional)
task package in .../samples/grtask to allow the creation of
semaphores and mailboxes (not included here).  I also added a few

comments to make it a bit more intelligible, and reduced the time to
task switch (by eliminating a setjmp/longjmp pair in case the task
doesn't need to change when Yield() is called.  I also added the
possibility of a single high-priority task that gets called once
between every two other tasks.
Also, I added the capability of killing a task from another,
and caused all descendants of a task to die when the parent dies.
This makes it a *lot* easier to clean things up when a program is
finished.  There were also a few other minor cleanups, such as
changing the default stacksize from 1024 (very small) to 9999 bytes.

##################task.h differences ####################
*** /djgpp2/samples/grtask/task.h	Wed Mar 20 16:56:38 1991
--- task.h	Thu Sep 10 17:23:48 1992
***************
*** 6,9
  typedef int (TaskProc)(int, void*);
  
  class Task {
    public:

--- 6,10 -----
  typedef int (TaskProc)(int, void*);
  
+ 
  class Task {
    public:
***************
*** 31,35
  public:
    
!   Task(TaskProc proc=0, int val=0, void* ptr=0, int stacksize=1024); // use default proc in main() to setup initial task
    ~Task();
    

--- 32,41 -----
  public:
    
!   Task(TaskProc proc=0, int val=0, void* ptr=0, int stacksize=9999,
!   			int priviliged=0);
!   				// use default proc in main() to setup initial task
!   				/* Val and ptr are passed into TaskProc when it begins */
! 				/* to execute.   If proviliged is nonzero, the task will */
! 				/* be executed once for every call to Yield(). */
    ~Task();
    
***************
*** 38,41
    friend int Wait(Task* child=0);
    friend void Return(int rv=0);
    friend void Yield();
  };

--- 44,48 -----
    friend int Wait(Task* child=0);
    friend void Return(int rv=0);
+   	/* All child tasks are killed when a task returns. */
    friend void Yield();
    friend void Block(Task **my_task_ptr);
***************
*** 39,42
    friend void Return(int rv=0);
    friend void Yield();
  };
  

--- 46,59 -----
    	/* All child tasks are killed when a task returns. */
    friend void Yield();
+   friend void Block(Task **my_task_ptr);
+   			/* This task won't execute until unblock() is called. */
+ 			/* My_task_ptr points to a place to put an identifier for */
+ 			/* this task; you'll need it to unblock.  Usually used as */
+ 			/* Task *p; Block(&p); ....... Unblock(p); */
+ 			/* Execution doesn't make it out of Block() until Unblock() */
+ 			/* is called (from another task). */
+   friend void Unblock(Task *blocked_task);
+   friend void Kill(Task *victim_task, int rv=0);
+ 			/* Equivalent to having the victim task call Return(rv) */
  };
  
***************
*** 40,45
    friend void Yield();
  };
- 
- extern Task *thisTask;
  
  #endif

--- 57,60 -----
  			/* Equivalent to having the victim task call Return(rv) */
  };
  
  #endif




##################task.cc differences ####################
*** /djgpp2/samples/grtask/task.cc	Wed Mar 20 16:56:38 1991
--- task.cc	Fri Sep 11 19:07:26 1992
***************
*** 3,6
  #include <pc.h>
  
  #include "Task.h"
  

--- 3,10 -----
  #include <pc.h>
  
+ typedef int BOOL;
+ #define FALSE	0
+ #define TRUE	1
+ 
  #include "Task.h"
  
***************
*** 7,12
  #define dprintf if(0)printf
  
! Task *thisTask=0;
! 
  static Task *task_list=0;
  

--- 11,16 -----
  #define dprintf if(0)printf
  
! static Task *thisTask=0;
! static Task *priviligedTask=0;
  static Task *task_list=0;
  
***************
*** 24,28
        case Task::Dead: rs="Dead"; break;
      }
!     dprintf("  0x%08x p=0x%08x s=%s\n", t, t->parent, rs);
    }
  }

--- 28,33 -----
        case Task::Dead: rs="Dead"; break;
      }
!     dprintf("  0x%08x p=0x%08x s=%s%c\n", t, t->parent, rs,
! 					t==thisTask?'*':' ');
    }
  }
***************
*** 36,40
  }
  
! Task::Task(TaskProc proc, int val, void* ptr, int stacksize)
  {
    prev = 0;

--- 41,45 -----
  }
  
! Task::Task(TaskProc proc, int val, void* ptr, int stacksize, int priviliged)
  {
    prev = 0;
***************
*** 47,52
    memset(state, 0, sizeof(state));
    stack = 0;
!   if (proc)
!   {
      stack_len = stacksize;
      stack = new unsigned[stacksize];

--- 52,56 -----
    memset(state, 0, sizeof(state));
    stack = 0;
!   if (proc) {
      stack_len = stacksize;
      stack = new unsigned[stacksize];
***************
*** 57,61
      state->esp = (unsigned)(stack+stacksize-3);
      state->eip = (unsigned long) proc;
!   }
    if (thisTask == 0)
      thisTask = this;

--- 61,65 -----
      state->esp = (unsigned)(stack+stacksize-3);
      state->eip = (unsigned long) proc;
!     }
    if (thisTask == 0)
      thisTask = this;
***************
*** 60,63
    if (thisTask == 0)
      thisTask = this;
    dprintf("Task::Task -> 0x%x\n", this);
  }

--- 64,69 -----
    if (thisTask == 0)
      thisTask = this;
+   if(priviliged)
+   	priviligedTask = this;
    dprintf("Task::Task -> 0x%x\n", this);
  }
***************
*** 94,99
    else
      dprintf("Task::Wait\n");
!   while (waiting)
!   {
      waiting = 0;
      if (child)

--- 100,104 -----
    else
      dprintf("Task::Wait\n");
!   while (waiting) {
      waiting = 0;
        if(child && child->run_state==Task::Dead) {
***************
*** 97,104
    {
      waiting = 0;
!     if (child)
!     {
!       if (child->run_state == Task::Dead)
!       {
          rv = child->ret_val;
          delete child;

--- 102,106 -----
    while (waiting) {
      waiting = 0;
!       if(child && child->run_state==Task::Dead) {
          rv = child->ret_val;
          delete child;
***************
*** 104,109
          delete child;
          return rv;
!       }
!     }
  
      Task *t, *tn;

--- 106,110 -----
          delete child;
          return rv;
!     	}
  
      Task *t, *tn;
***************
*** 108,113
  
      Task *t, *tn;
!     for (t=task_list; t; t=tn)
!     {
        tn = t->next;
        if (t->parent == thisTask)

--- 109,113 -----
  
      Task *t, *tn;
!     for (t=task_list; t; t=tn) {
        tn = t->next;
        if (t->parent == thisTask) {
***************
*** 111,118
      {
        tn = t->next;
!       if (t->parent == thisTask)
!       {
!         if (t->run_state == Task::Dead)
!         {
            dprintf("Dead child 0x%x\n", t);
            delete t;

--- 111,116 -----
      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;
***************
*** 117,123
            dprintf("Dead child 0x%x\n", t);
            delete t;
!         }
!         else
!         {
            dprintf("Running child 0x%x\n", t);
            waiting = 1;

--- 115,120 -----
            dprintf("Dead child 0x%x\n", t);
            delete t;
!           }
!         else {
            dprintf("Running child 0x%x\n", t);
            waiting = 1;
***************
*** 125,130
        }
      }
!     if (waiting)
!     {
        dprintf("parent waiting...\n");
        thisTask->run_state = Task::Waiting;

--- 122,126 -----
        }
      }
!     if (waiting) {
        dprintf("parent waiting...\n");
        thisTask->run_state = Task::Waiting;
***************
*** 132,135
      }
    }
  }
  

--- 128,132 -----
      }
    }
+  return 0;
  }
  
***************
*** 134,138
  }
  
! void Return(int rv)
  {
    dprintf("Task::Return(%d) <- 0x%x\n", rv, thisTask);

--- 131,135 -----
  }
  
! void Yield()
  {
   dprintf("Task::Yield 0x%x -> ", thisTask);
***************
*** 136,145
  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();
  }
  

--- 133,163 -----
  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);
!   	}
  }
  
***************
*** 144,148
  }
  
! void Yield()
  {
    dprintf("Task::Yield 0x%x -> ", thisTask);

--- 162,166 -----
  }
  
! void Unblock(Task *blocked_task)
  {
   if(blocked_task->run_state == Task::Blocked)
***************
*** 146,163
  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);
  }

--- 164,210 -----
  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);
  }


--Greg Kochanski   attmail!gkochanski

- Raw text -


  webmaster     delorie software   privacy  
  Copyright 2019   by DJ Delorie     Updated Jul 2019