Initialize:
PROC = {
This procedure is implicitly parameterized by the module parameters.
AlignUp:
PROC [unaligned, modulus:
UNSPECIFIED]
RETURNS [aligned:
UNSPECIFIED] =
INLINE {RETURN[ ((unaligned + modulus-1) / modulus) * modulus]};
AlignDown:
PROC [unaligned, modulus:
UNSPECIFIED]
RETURNS [aligned:
UNSPECIFIED] =
INLINE {RETURN[unaligned - unaligned MOD modulus]};
rAlloc: PDABase RELATIVE POINTER TO UNSPECIFIED ← LOOPHOLE[pdaWords]; -- allocation pointer.
Initialize monitored variables and SD
Process.DisableTimeout[@dead];
Process.DisableTimeout[@frameReady];
Process.DisableTimeout[@frameTaken];
Process.DisableTimeout[@rebirth];
SD[sProcessTrap] ← ProcessTrap;
SD[sFork] ← Fork;
SD[--sCedarFork-- 153B] ← Fork; -- temporary until Compiler is fixed
SD[sJoin] ← Join;
Allocate StateVector pool:
{
alignmentStateVector: CARDINAL = 4; -- (a D0 requirement)
sizeStateVector:
CARDINAL =
AlignUp[MAX[SIZE[StateVector], wordsPerSV], alignmentStateVector];
rState: StateVectorHandle ← AlignDown[rAlloc, alignmentStateVector];
FOR pri: Priority
IN Priority
DO
PDA.state[pri] ← NullStateVectorHandle;
FOR k:
CARDINAL
IN [0..svCounts[pri])
DO
IF LOOPHOLE[rState, CARDINAL] < sizeStateVector THEN ERROR;
rState ← rState - sizeStateVector;
PDA[rState].stk[0] ← PDA.state[pri]; -- chain onto list.
PDA.state[pri] ← rState;
ENDLOOP;
ENDLOOP;
rAlloc ← rState;
};
{
Find number of {PSB, timeout words} that will fit in space remaining, considering TimeoutVector alignment and unused TimeoutVector positions.
sizePSBTimeout: CARDINAL = SIZE[ProcessStateBlock] + SIZE[Ticks];
alignmentTimeoutVector: CARDINAL = 16; -- (PrincOps requirement)
rStartPsb: PDABase
RELATIVE
POINTER
TO
UNSPECIFIED =
LOOPHOLE[PrincOpsUtils.PsbIndexToHandle[StartPsb]];
totalPsbs: CARDINAL;
PDA.count ← 0;
FOR nUseful:
CARDINAL
DECREASING
IN [0..(rAlloc - rStartPsb)/sizePSBTimeout]
DO
totalPsbs ← StartPsb + nUseful;
PDA.timeout ← AlignDown[rAlloc - totalPsbs, alignmentTimeoutVector];
IF (
LOOPHOLE[
PDA.timeout,
CARDINAL] + StartPsb
-- (first used word of timeout vector)
- LOOPHOLE[rStartPsb, CARDINAL]) / SIZE[ProcessStateBlock] >= nUseful THEN
{PDA.count ← nUseful; EXIT}; -- that many Psbs fit in available space.
REPEAT
FINISHED => ERROR;
ENDLOOP;
IF PDA.count <= 1 THEN ERROR;
};
Initialize TimeoutVector: (Note: TimeoutVector unused portions overlay Psbs)
FOR psb: PsbIndex
IN [StartPsb..StartPsb+
PDA.count)
DO
PDA[PDA.timeout][psb] ← NoTimeout;
ENDLOOP;
Set up the executing context as a legitimate process (detached) in the first Psb:
PDA.block[StartPsb] ← ProcessStateBlock[
link: [failed: FALSE, priority: FIRST[Priority], next: StartPsb, vector: NULL],
flags: [
processState: [state: alive, detached: TRUE],
cleanup: PsbNull, waiting: FALSE, abort: FALSE],
context: NULL,
TEMP until microcode uses timeout vector:
mds: Inline.HighHalf[LONG[LOOPHOLE[1, POINTER]]] ];
mds: NoTimeout
];
Note: the following assumes that someone has previously set the return link of the topmost frame to NullFrame.
FOR root: FrameHandle ← PrincOpsUtils.MyLocalFrame[], root.returnlink.frame
DO
IF root.returnlink.frame = NullFrame
THEN
{root.returnlink ← LOOPHOLE[End, procedure ControlLink]; EXIT};
ENDLOOP;
PrincOpsUtils.WritePSB[PrincOpsUtils.PsbIndexToHandle[StartPsb]]; -- tell the processor.
Initialize the ready list
PDA.ready ← Queue[tail: StartPsb];
Put rest of PSBs into free pool: (chained off "rebirth" condition)
{
firstFree: PsbIndex ← StartPsb+1;
lastFree: PsbIndex ← StartPsb+PDA.count-1;
LOOPHOLE[rebirth, ConditionVariable].condition.tail ← PsbNull;
FOR psb: PsbIndex
IN [firstFree..lastFree]
DO
PDA.block[psb].link.next ← IF psb=firstFree THEN lastFree ELSE psb-1;
PDA.block[psb].flags.processState.state ← dead;
TEMP until microcode uses timeout vector:
PDA.block[psb].mds ← NoTimeout;
REPEAT
FINISHED => LOOPHOLE[rebirth, ConditionVariable].condition.tail ← firstFree;
ENDLOOP;
};
Initialize FaultVector:
FOR fi: FaultIndex
IN FaultIndex
DO
PDA.fault[fi] ← [
queue: [tail: PsbNull], condition: [tail: PsbNull, abortable: FALSE, wakeup: FALSE]];
ENDLOOP;
Initialize naked-notify allocator:
busyLevels ← LOOPHOLE[reservedNakedNotifyMask];
PrincOpsUtils.WriteWDC[0]; -- start interrupts.
Start the time slicer
Detach[FORK Schedule[]];
};