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 -