home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume44
/
toy_os
/
part03
/
processes.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-05
|
4KB
|
180 lines
// This may look like C code, but it is really -*- C++ -*-
/*
************************************************************************
*
* UNT Virtual Machine
*
* Process handling and scheduling
*
* The present file implements primitive operations on separate PCBs
* as well on their collection, PCB table. Advanced process scheduling,
* etc. is the concern of the CPUManager.
*
************************************************************************
*/
#include "processes.h"
#pragma implementation
#include "myenv.h"
/*
*------------------------------------------------------------------------
* Constructing the PCB
*/
PCB::PCB(void)
{
parent = lchild = rchild = NIL_pid;
status = Dead;
}
/*
*------------------------------------------------------------------------
* Elementary PCB operations
*/
void PCB::dump(void)
{
message("\n---> Process %d", id);
message(", Status %s",
status == Wait_for_kids ? "Waiting for kids to terminate" :
status == Wait_on_sema ? "Waiting on semaphore" :
status == Dead ? "Dead" :
status == Doing_io ? "Doing I/O" :
status == Shall_die ? "Shall die" :
"OK");
message(", \t PC = %06o",pc);
message("\n\t\tParent: ");
parent == NIL_pid ? message("None") : message("%d",parent);
message(", Children: ");
if( lchild == NIL_pid && rchild == NIL_pid )
message("None");
else
{
if( lchild != NIL_pid )
message("%d ",lchild);
if( rchild != NIL_pid )
message("%d ",rchild);
}
message("\n");
MMContext::dump();
}
// Fork this PCB from dad's
void PCB::fork_from_dad(PCB& dad_pcb)
{
status = Ok;
parent = dad_pcb.id;
lchild = rchild = NIL_pid;
copy_context(dad_pcb);
if( dad_pcb.lchild == NIL_pid )
dad_pcb.lchild = (*this).id;
else
dad_pcb.rchild = (*this).id;
}
// PCB for a brand-new process
void PCB::brand_new(void)
{
status = Ok;
}
// Save the full hardware context
void PCB::save_context(const CentralProcessingUnit& cpu_hardware)
{
copy_context((const Context&)cpu_hardware);
MMContext::save_MMU((const MemoryManagementUnit&)cpu_hardware);
}
// Load the context into the hardware
void PCB::load_context(CentralProcessingUnit& cpu_hardware)
{
cpu_hardware.copy_context((Context&)*this);
MMContext::load_MMU((MemoryManagementUnit&)cpu_hardware);
}
/*
*------------------------------------------------------------------------
* Constructing the process table
*/
ProcessTable::ProcessTable(const int _nslots)
: nslots(_nslots)
{
assure(nslots > 4,"No of slots in a process table must be at least 5");
pcbs = new PCB[nslots];
resume_scan_pid = NIL_pid;
register PID i;
for(i=1; i<=nslots; i++)
{
PCB& pcb = (*this)[i];
pcb.id = i;
pcb.key = 0;
freePCBs.append(pcb);
}
}
/*
*------------------------------------------------------------------------
* Elementary ProcessTable operations
*/
// Get a PCB given its index
PCB& ProcessTable::operator [] (const PID id)
{
assure(id != NIL_pid,"NIL index");
if( id > nslots )
_error("FATAL: PCB index %d is too big",id);
return pcbs[id-1];
}
// Dump info about all processes in the system
void ProcessTable::dump(void)
{
message("\n\t\t=============== System Processes ================\n");
register PID i;
for(i=1; i<=nslots; i++)
{
PCB& pcb = (*this)[i];
if( pcb.status != PCB::Dead )
pcb.dump();
}
}
// Get PID of a new process to create
// Return NIL_pid if no free PCB is available
PID ProcessTable::new_pid(void)
{
if( freePCBs.is_empty() )
return NIL_pid;
return freePCBs.get_from_head()->id;
}
// Dispose of the PCB
void ProcessTable::dispose(const PID pid)
{
PCB& pcb = (*this)[pid];
assert( pid == pcb.id );
pcb.status = PCB::Dead;
freePCBs.append(pcb);
}
// Find nex pcb according to the criterion
PID ProcessTable::next_pcb(const SEARCH_CRIT crit)
{
if( resume_scan_pid == NIL_pid || resume_scan_pid > nslots )
return NIL_pid; // Scan is over or wasn't started
for(;resume_scan_pid <= nslots; resume_scan_pid++)
{
const PCB& pcb = (*this)[resume_scan_pid];
if( pcb.status == PCB::Dead )
continue;
if( (pcb.status == PCB::Ok) == (crit == Ready) )
return resume_scan_pid++;
}
return NIL_pid;
}