home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / toy_os / part03 / processes.cc < prev    next >
C/C++ Source or Header  |  1994-09-05  |  4KB  |  180 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               UNT Virtual Machine
  6.  *
  7.  *               Process handling and scheduling
  8.  *
  9.  * The present file implements primitive operations on separate PCBs
  10.  * as well on their collection, PCB table. Advanced process scheduling,
  11.  * etc. is the concern of the CPUManager.
  12.  *
  13.  ************************************************************************
  14.  */
  15.  
  16. #include "processes.h"
  17. #pragma implementation
  18.  
  19. #include "myenv.h"
  20.  
  21. /*
  22.  *------------------------------------------------------------------------
  23.  *            Constructing the PCB
  24.  */
  25.  
  26. PCB::PCB(void)
  27. {
  28.   parent = lchild = rchild = NIL_pid;
  29.   status = Dead;
  30. }
  31.  
  32. /*
  33.  *------------------------------------------------------------------------
  34.  *            Elementary PCB operations
  35.  */
  36.  
  37. void PCB::dump(void)
  38. {
  39.   message("\n---> Process %d", id);
  40.   message(",  Status %s", 
  41.       status == Wait_for_kids ? "Waiting for kids to terminate" :
  42.       status == Wait_on_sema  ? "Waiting on semaphore" :
  43.       status == Dead  ? "Dead" :
  44.       status == Doing_io  ? "Doing I/O" :
  45.       status == Shall_die  ? "Shall die" :
  46.       "OK");
  47.   message(", \t PC = %06o",pc);
  48.   message("\n\t\tParent: "); 
  49.   parent == NIL_pid ? message("None") : message("%d",parent);
  50.   message(", Children: "); 
  51.   if( lchild == NIL_pid && rchild == NIL_pid )
  52.     message("None");
  53.   else
  54.   {
  55.     if( lchild != NIL_pid ) 
  56.       message("%d ",lchild);
  57.     if( rchild != NIL_pid ) 
  58.       message("%d ",rchild);
  59.   }
  60.   message("\n");
  61.   MMContext::dump();
  62. }
  63.  
  64.                 // Fork this PCB from dad's
  65. void PCB::fork_from_dad(PCB& dad_pcb)
  66. {
  67.   status = Ok;
  68.   parent = dad_pcb.id;
  69.   lchild = rchild = NIL_pid;
  70.   copy_context(dad_pcb);
  71.   if( dad_pcb.lchild == NIL_pid )
  72.     dad_pcb.lchild = (*this).id;
  73.   else
  74.     dad_pcb.rchild = (*this).id;
  75. }
  76.  
  77.                 // PCB for a brand-new process
  78. void PCB::brand_new(void)
  79. {
  80.   status = Ok;
  81. }
  82.  
  83.                 // Save the full hardware context
  84. void PCB::save_context(const CentralProcessingUnit& cpu_hardware)
  85. {
  86.   copy_context((const Context&)cpu_hardware);
  87.   MMContext::save_MMU((const MemoryManagementUnit&)cpu_hardware);
  88. }
  89.  
  90.                 // Load the context into the hardware
  91. void PCB::load_context(CentralProcessingUnit& cpu_hardware)
  92. {
  93.   cpu_hardware.copy_context((Context&)*this);
  94.   MMContext::load_MMU((MemoryManagementUnit&)cpu_hardware);
  95. }
  96.  
  97. /*
  98.  *------------------------------------------------------------------------
  99.  *            Constructing the process table
  100.  */
  101.  
  102. ProcessTable::ProcessTable(const int _nslots)
  103.     : nslots(_nslots)
  104. {
  105.   assure(nslots > 4,"No of slots in a process table must be at least 5");
  106.   pcbs = new PCB[nslots];
  107.   resume_scan_pid = NIL_pid;
  108.  
  109.   register PID i;
  110.   for(i=1; i<=nslots; i++)
  111.   {
  112.     PCB& pcb = (*this)[i];
  113.     pcb.id = i;
  114.     pcb.key = 0;
  115.     freePCBs.append(pcb);
  116.   }
  117. }
  118.  
  119. /*
  120.  *------------------------------------------------------------------------
  121.  *             Elementary ProcessTable operations
  122.  */
  123.  
  124.                 // Get a PCB given its index
  125. PCB& ProcessTable::operator [] (const PID id)
  126. {
  127.   assure(id != NIL_pid,"NIL index");
  128.   if( id > nslots )
  129.     _error("FATAL: PCB index %d is too big",id);
  130.   return pcbs[id-1];
  131. }
  132.  
  133.                 // Dump info about all processes in the system
  134. void ProcessTable::dump(void)
  135. {
  136.   message("\n\t\t=============== System Processes ================\n");
  137.   register PID i;
  138.   for(i=1; i<=nslots; i++)
  139.   {
  140.     PCB& pcb = (*this)[i];
  141.     if( pcb.status != PCB::Dead )
  142.       pcb.dump();
  143.   }
  144. }
  145.  
  146.                 // Get PID of a new process to create
  147.                 // Return NIL_pid if no free PCB is available
  148. PID ProcessTable::new_pid(void)
  149. {
  150.   if( freePCBs.is_empty() )
  151.     return NIL_pid;
  152.   return freePCBs.get_from_head()->id;
  153. }
  154.  
  155.  
  156.                 // Dispose of the PCB
  157. void ProcessTable::dispose(const PID pid)
  158. {
  159.   PCB& pcb = (*this)[pid];
  160.   assert( pid == pcb.id );
  161.   pcb.status = PCB::Dead;
  162.   freePCBs.append(pcb);
  163. }
  164.  
  165.                 // Find nex pcb according to the criterion
  166. PID ProcessTable::next_pcb(const SEARCH_CRIT crit)
  167. {
  168.   if( resume_scan_pid == NIL_pid || resume_scan_pid > nslots )
  169.     return NIL_pid;            // Scan is over or wasn't started
  170.   for(;resume_scan_pid <= nslots; resume_scan_pid++)
  171.   {
  172.     const PCB& pcb = (*this)[resume_scan_pid];
  173.     if( pcb.status == PCB::Dead )
  174.       continue;
  175.     if( (pcb.status == PCB::Ok) == (crit == Ready) )
  176.       return resume_scan_pid++;
  177.   }
  178.   return NIL_pid;
  179. }  
  180.