exec.hh
//*************************************************************************
// MODULE : Exec - Definitions for Process Control Blocks and such. *
// AUTHOR : Ron Chernich *
// PURPOSE: Define all classes and strucures required by the Kernel for *
// process control and management. *
// HISTORY: *
// 21-APR-93 First version *
// 06-MAR-94 Semaphore class added and PCB struct moded as needed *
// 01-SEP-94 File System Interface added to PCB struct *
// 21-MAR-94 Quantum made a constructor parameter *
//*************************************************************************
#ifndef _RCOS_EXEC_
#include "rcos.hh"
#include "message.hh"
#include "app.hh"
#include "dbllist.hh"
#include "ttyld.hh"
#include "cpu-disp.hh"
////////////////
// Values for process status (PS) - some combinations are valid
//
#define PS_Created 0x0001 // created, not yet started
#define PS_Ready 0x0002 // could run at any time
#define PS_Blocked 0x0004 // waiting on event or resource
#define PS_Suspended 0x0008 // under user suspension
#define PS_Illegal 0x0010 // can't continue (bad p-code?)
#define PS_Halted 0x0020 // Normal termination
#define PS_Swapped 0x0040 // swapped out to backing store
#define PS_Zombie 0x0080 // terminated, but still present
#define PCD_QUANTUM 100 // milliseconds per time-slice
#define PCD_PREEMPT -100 // quantum value when pre-empted
#define MAX_DEV 4 // Most devices a process can "own"
#define NO_PROC 0xffff // flag PCB PID/DEV for not in use
/////////////////////
// Process Control Block - built when a process is created (forked off)
// contains all details of process context.
//
class FsIface;
//
typedef struct pcb {
char *pszName; // user name for process, if any
INT16 nPriority, // process priority
nQuantum; // max permissable ticks per scheduling
UINT16 uPid, // unique ID for process (PID)
uPidp, // parent PID of process
uIP, uSP, uBP, // Instruction, Stack and Base pointers
uStatus, // current status
uDevCnt; // count of devices open by process
PMSG pReply; // message associated with wake-up
UINT32 lStarted, // time process started/created (mS).
luTicks, // amount of processor time in user mode
leTicks, // time consumed in executive mode
lCode; // 32 bit instruction at IP for animator
LnDrv *pDev; // pointer line protocol driver
UINT16 arrDev[MAX_DEV]; // Devices needed before process can start
UINT16 uTos; // fetched values at top of stack
UINT16 uSemOpen, // Bit map of semaphore ID's opened by PID
uSemSet, // map of semaphores set by this process
uSemWait; // map of semaphores we are waiting on
DblList Share; // List of open shared memory block ID's
FsIface *pFile; // File sysem Interface package
} PCB, *PPCB;
//////////////////
// Priority queue used to store PIDs. May be instantiated as ordered
// (by Process Priority, Quantum, something), or simple FIFO.
//
class Pque : private DblList {
typedef struct qmbr { // structure used for double link list
INT16 nKey; // Key for ordering (normally priority)
UINT16 uPid; // index into array (which is the PID #)
} QMBR;
typedef QMBR *PQMBR; // g++ doesn't like it being defined as
// part of the previous typedef???
BOOL bOrdered; // FIFO or priority ordering
public:
Pque (BOOL = FALSE); // default is FIFO
~Pque (void); // kill off any left-overs
BOOL PqEmpty (void); // state of play
BOOL PqFind (UINT16); // is this PID in the queue?
void PqAdd (PCB&); // add/insert PID (perhaps in priority order)
UINT16 PqGet (void); // remove PID from queue (head if ordered)
UINT16 PqGet (UINT16); // remove specific PID from queue
void PqImage (UINT16*); // copy queue PID numbers to passed array
};
////////////
// Semaphores are used by running processes for Inter-Process Communication
// (IPC) synchronisation. They are identified by power of 2 integer values.
// Each PID holds bit maps for semaphores they have created, ones they have
// "set" and ones they are waiting (delayed) on. Since a semaphore must be
// identified to the PLL/2 compiler by an integer, and since PLL/2 ints are
// 16 bit, this limits us to a max of 16 samaphores..
//
#define MAX_SEM 16 // maps system semaphores onto a 16 bit integer
class Sem4 {
Pque uPid, // list of users (semaphore is free when empty)
uDelayed; // priority list of waiting users
UINT16 uCount, // current p/v count, set when created
uCreator; // PID# of process that first opened it
char *pst; // optional user supplied name
public:
Sem4 (void);
~Sem4 (void);
void SemOpen (PCB&, UINT16, char*);
BOOL operator == (char*); // match with semaphore name
BOOL SemWait (PCB&); // this user wants the batton
BOOL SemSignal (void); // release held semaphore
BOOL SemIsFree (void); // test for any current users
BOOL SemIsUser (PCB&); // test for specific user
BOOL SemAddUser (PCB&); // enroll new user
BOOL SemDelUser (PCB&); // remove all trace of user (may deallocate)
UINT16 SemGetDelayed (void);// get the head of the delayed task queue
UINT16 SemGetDelayed (UINT16); // get specific PID from delayed task Q
UINT16 SemGetCount (void) { return uCount; };
};
//////////////////////////
// Class encapsulates operations required to support shared memory, based
// on a FIFO list (and hides details of the double link list we don't need).
//
typedef struct sh_tag {
UINT16 nID; // ID allocated to this block
UINT16 nCnt; // Usage count, delete when zero
UINT16 nLen; // Allocated length of block
INT16 *pData; // data (16 bit PLL/2 integers)
Str *pstName; // Unique shared block name
} MSHARE, *PMS;
class QmMgr : private DblList {
public:
QmMgr (void);
~QmMgr (void);
BOOL QmExists (char*, PMS*); // check by name string
BOOL QmExists (UINT16, PMS*); // check by block ID
void QmIncCnt (UINT16); // increase usage count
void QmDecCnt (UINT16); // decrease count, kill off if zero
INT16 QmLength (UINT16); // return block length
BOOL QmAdd (char*, UINT16); // Create and append a new block
BOOL QmGet (UINT16, UINT16, INT16*); // read an int value
BOOL QmPut (UINT16, UINT16, INT16*); // write an int value
};
////////////////////////
// This class performs all process control operations. There will only
// be one of him which is a private member of the Kernel (only one of
// her, too). When instantiated by the kernel, the class receives a
// reference to the kernel (sort of like device drivers) which it may
// use to send/post messages.
//
class Exec {
Knl *pTx; // pointer to out master's post box
Pque PqIn; // input queue (initialized, not started)
Pque PqBlocked; // Procs waiting on an event
Pque PqSusReady; // Procs suspended while ready
Pque PqSusBlock; // Procs suspended while blocked
Pque PqReady; // Procs ready to roll (perhaps rock, too)
PCB arrPCB[MAX_PROC]; // array of PCB structures
MCB arrMCB[MAX_PROC]; // per process region table structures
Sem4 arrSem[MAX_SEM]; // array of available semaphores
QmMgr ShareMem; // shared memory manager
UINT16 nQuantum; // default quantum per process
UINT16 uProcCnt; // current number of processes in system
UINT16 uCurProc; // current (running) proc - if any
BOOL LoSked (UINT16); // Low Level scheduler (for I/P queue)
void Sked (void); // dispatch next ready process to CPU
UINT16 Fork (void); // create new process from current
BOOL Kill (UINT16); // remove process
BOOL Start (UINT16); // move it from input to ready
BOOL Resume (UINT16); // resume suspended process
BOOL Suspend (UINT16); // suspend this process
void RunCon (PCB&); // Run the Console process
void RunProc (PCB&, MCB&); // Run the current User process
void DeCode (UINT32, char*); // decode a p-code
void CreateCon (void); // Create the "console" process
void InitCon (void); // Pre-start code for console
void ParseCon (char*); // Parse and action operator commands
UINT16 IpcOpen (char*); // register as user of named semaphore
UINT16 IpcAlloc (char*, UINT16);// allocate next free for use & set count
INT16 IpcWait (UINT16, UINT16);// process wants to use this samaphore
void IpcSignal(UINT16,UINT16);// process finished with it for now
void IpcClose (UINT16,UINT16);// free and release (if no other users)
INT16 SmOpen (char*); // open existing shared mem by name
INT16 SmCreate (char*, UINT16);// create named/annon shared mem block
INT16 SmClose (UINT16, UINT16);// close usage of shared mem for process
INT16 SmLength (UINT16); // get length of shared mem block from ID
BOOL SmRead (UINT16,UINT16,INT16*); // get int data of block at offset
BOOL SmWrite (UINT16,UINT16,INT16*); // set int data of block at offset
public:
Exec (Knl*, UINT16); // Initialize Exec (and Console)
~Exec (void); // Complete close down procedure
void Block (void); // Block current process
BOOL Dispatch (void); // Ready Queue manager
void StartCon (void); // Startup process Zero (console)
void PostReply (UINT16, PMSG); // Add message to queue for process
void GetPcom (PMSG_ANIP); // Snapshot current PCB
void GetQcom (UINT16, PMSG_ANIQ); // Snapshot Queue contents
};
#define _RCOS_EXEC_
#endif
/////////////////////////////////// eof ////////////////////////////////////