MODULE CPROC= !Create a process block, stack, & everything else a process is known to need !Also contains routines to clean up after process termination BEGIN ! !Table of Contents ! FORWARD ROUTINE CPROC, !Create a process SAYDIE, !Say we're dead REMINF, !Remove a deceased inferior CHECKF; !Validate a pseudoprocess handle ! !Library & Require files ! REQUIRE 'INTR.REQ'; ! !Version info ! THIS_IS [CPROC] VERSION[2] EDIT[3] DATE[10,OCT,79] ![3] Validate process handles ! !Literals ! LITERAL PTAB_LEN=20; LITERAL JBREL=%O'44'; ! !Externals ! EXTERNAL ROUTINE CREATEPROC, !Set up stack FREEFB, !RELEASE and free storage for a file block & decendants TSICLF, !Clear pending clock requests for fork FREE, !Release storage ALLOC; EXTERNAL RUN: REF PROCESS_BLOCK, !Current process block FREEOK, !First word of dynamic memory CMDPBL: PROCESS_BLOCK; !Top level process block ! !Global data ! GLOBAL PTAB: VECTOR[PTAB_LEN]; ! ! Macros ! MACRO PREFIX='IPH' %; ! !Routines ! GLOBAL ROUTINE CPROC(RTN,ARGLST,STKL)= !Create process !Arguments: !RTN: Top level routine to execute !ARGLST: List of arguments (# of args following,arg,arg,arg...) !STKL: # of words of stack to allocate BEGIN LOCAL PB: REF PROCESS_BLOCK; LOCAL T; MAP ARGLST: REF VECTOR; PB=ALLOC((T=.STKL+P_LEN+.ARGLST[0]+1)); !Allocate space for process block and stack ! and argument list PB[P$FREE]=.T; !Remember how much space to free later T=.PB+P_LEN+.STKL; !Get origin of argument list storage place INCR I FROM 0 TO .ARGLST[0] DO (.T+.I)=.ARGLST[.I]; !Copy argument list PB[P$STKL]=.STKL; PB[P$STK]=.PB+P_LEN; !Store origin of stack PB[P$SUPERIOR]=.RUN; !We are the superior to this process IF .RUN[P$INFERIORS] EQL 0 THEN RUN[P$INFERIORS]=.PB !Start of linked list ELSE BEGIN LOCAL T: REF PROCESS_BLOCK; T=.RUN[P$INFERIORS]; DO BEGIN IF .T[P$LINK] EQL 0 THEN BEGIN T[P$LINK]=.PB; !Put at end of linked list EXITLOOP END; T=.T[P$LINK] END WHILE 1 END; PB[P$WAIT]=0; !Not waiting for anything yet !Put this process in the process table IF (INCR I FROM 0 TO PTAB_LEN-1 DO (IF .PTAB[.I] EQL 0 THEN (PTAB[.I]=.PB;EXITLOOP -1;))) EQL 0 THEN CRASH('No free processes'); CREATEPROC(.PB[P$STK],.STKL,SAYDIE,.RTN,.T); !Set up the stack NOINTS(( BEGIN LOCAL T: REF PROCESS_BLOCK; MAP RUN: REF PROCESS_BLOCK; T=.RUN; !Start at this process DO BEGIN IF .T[P$NEXT] EQL 0 THEN BEGIN T[P$NEXT]=.PB; EXITLOOP; END; T=.T[P$NEXT]; END WHILE 1; END; ));!NOINTS .PB !Return address of process block END; !CPROC GLOBAL ROUTINE SAYDIE= !Tell our superior of our demise BEGIN EXTERNAL ROUTINE QUIT, !Signal superior that we gave up the ghost STOP; !HALTF, MONRT., ... EXTERNAL RUN: REF PROCESS_BLOCK; IF .RUN[P$SUPERIOR] EQL 0 THEN STOP(); !Return to the monitor QUIT(SS$_NORMAL); !Say we finished END; GLOBAL ROUTINE REMINF(AFORK)= !Remove a process from all linked-lists and tables !AFORK: address of process block (process must be an immediate inferior) BEGIN MAP AFORK: REF PROCESS_BLOCK; EXTERNAL RUN: REF PROCESS_BLOCK; LOCAL T: REF PROCESS_BLOCK; LOCAL IB: REF INT_BLOCK; LABEL FIND_PROCESS; !Remove from process table INCR I FROM 0 TO PTAB_LEN-1 DO IF .PTAB[.I] EQL .AFORK THEN (PTAB[.I]=0; EXITLOOP); !Free up any pending temporary interrupt blocks IF (IB=.AFORK[P$INTERRUPTS]) NEQ 0 THEN BEGIN LOCAL TIB: REF INT_BLOCK; DO BEGIN TIB=.IB[INT$NEXT]; !Save addr of next one IF .IB[INT$TEMP] THEN FREE(.IB,INT_LEN) END WHILE (IB=.TIB) NEQ 0; END; TSICLF(.AFORK); !Clear any pending clock requests IF .RUN[P$INFERIORS] EQL .AFORK THEN RUN[P$INFERIORS]=.AFORK[P$LINK] !Close the linked list ELSE FIND_PROCESS: BEGIN IF (T=.RUN[P$INFERIORS]) EQL 0 THEN CRASH('REMINF--no inferior'); DO BEGIN !Chase the pointers to find the process IF .T[P$LINK] EQL .AFORK THEN BEGIN T[P$LINK]=.AFORK[P$LINK]; LEAVE FIND_PROCESS END; END WHILE (T=.T[P$LINK]) NEQ 0; CRASH('REMINF--not an inferior') END; IF (T=.AFORK[P$NDB]) NEQ 0 THEN FREEFB(.T); !Free his NDB FREE(.AFORK,.AFORK[P$FREE]); !Give back the storage END; !REMINF GLOBAL ROUTINE CHECKF(PH)= !Verify a process handle !Return: WIN if OK, 0 if not BEGIN MAP PH: REF PROCESS_BLOCK; SELECT .PH OF SET [CMDPBL]: RETURN WIN; !This is the top level [0]: RETURN 0; !This is nothing [.FREEOK TO .JBREL]: INCR I FROM 0 TO PTAB_LEN-1 DO IF .PH EQL .PTAB[.I] THEN RETURN WIN; TES; INFO('Ignoring Invalid process handle'); 0 END; !CHECKF END ELUDOM