home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_08_11
/
8n11066a
< prev
next >
Wrap
Text File
|
1990-07-27
|
4KB
|
162 lines
// npx.cpp - Non-Preemptive eXecutive
// Copyright 1990 by Cnapse
// Written by: M. de Champlain
#include <stdio.h>
#include <stdlib.h>
#include "npx.hpp"
Task *running;
// ---- base class StateQ -------------------
class StateQ {
friend class ReadyQ;
Task *header;
taskState state;
public:
StateQ(int nTasks, taskState st);
void Insert(Task *thisTask);
void Transfer(Task *thisTask);
~StateQ( );
};
inline StateQ::StateQ(int nTasks, taskState st)
{
header = List_Allocate(nTasks, sizeof(Task));
state = st;
}
inline void StateQ::Insert(Task *thisTask)
{
thisTask->state = state;
List_InsertTail(thisTask, header);
}
inline void StateQ::Transfer(Task *thisTask)
{
thisTask->state = state;
List_Remove(thisTask);
List_InsertTail(thisTask, header);
}
inline StateQ::~StateQ()
{
List_Free( header );
}
// ---- derived class ReadyQ -------------------
class ReadyQ : StateQ {
public:
ReadyQ() : StateQ(0, READY) {}
void GetNextRunning(void);
};
inline void ReadyQ::GetNextRunning(void)
{
(running = List_RemoveHead(header))->state = RUNNING;
}
StateQ *terminatedQ, *suspendedQ;
ReadyQ *readyQ;
Task *Task::Start(void)
{
if (stackBase = new word[stackSizeInBytes/2])
{
/* establish new task's SP */
sp = (reg)((word)stackBase + stackSizeInBytes);
*--sp = (word) taskStartingAddress;
--sp; /* push bp */
parent = running;
self = this;
readyQ->Insert(this);
return self;
}
else
return 0;
}
Task *Task::Self(void)
{
return self;
}
Task *Task::Parent(void)
{
return parent;
}
void Task::Schedule(void)
{
readyQ->GetNextRunning(); // assume at least one task is READY
}
extern void ContextSwitch(void);
extern void RunNext(void);
reg *addrRunningTcbSp;
void Task::ReSchedule(void)
{
// save the address of the runningTcb's stack ptr for ContextSwitch.
addrRunningTcbSp = &running->sp;
// put the running task in the READY queue
readyQ->Insert(running);
Schedule();
ContextSwitch();
}
void Task::Terminate(Task *id)
{
if ( id->state != TERMINATED )
{
delete id->stackBase;
terminatedQ->Transfer(id);
delete id;
if ( id == running )
{
Schedule();
RunNext();
// should never back here
}
}
}
void Task::Suspend(Task *id)
{
if ( id->state != SUSPENDED )
{
suspendedQ->Transfer(id);
if ( id == running )
{
// save address of the runningTcb's stack ptr for ContextSwitch.
addrRunningTcbSp = &running->sp;
Schedule();
ContextSwitch();
// will come back here after a Resume
}
}
}
void Task::Resume(Task *id)
{
if ( id->state == SUSPENDED )
readyQ->Transfer(id);
}
extern void StartUpUserTasks(void);
main(void)
{
printf("Non-Preemptive eXecutive, Copyright 1990 by Cnapse\n\n");
terminatedQ = new StateQ(10, TERMINATED );
suspendedQ = new StateQ( 0, SUSPENDED );
readyQ = new ReadyQ();
// Make StartUpUserTasks RUNNING
(new Task(StartUpUserTasks, 1024))->Start();
readyQ->GetNextRunning();
RunNext();
}