-- RTProcessImpl.Mesa
-- last edited September 9, 1982 9:34 am by Paul Rovner


DIRECTORY
CPSwapDefs USING[ProcessState],
PSB USING[PsbIndex, PsbNull, PDA, PsbHandle],
RTOS USING[RTProcessStarted, GetCurrent],
RTProcess USING[GetPSBIPageFaults],
RTProcessPrivate USING[ProcessObject, MapRecord, InvalidateFaultingCedarProcess],
SafeStorage USING[NewZone];

RTProcessImpl: MONITOR -- protects MapPSBIToHandle
IMPORTS RTOS, RTProcess, RTProcessPrivate, SafeStorage
EXPORTS RTProcess, RTProcessPrivate

= BEGIN OPEN RTProcess, RTProcessPrivate;

-- types
Handle: TYPE = REF Object;
Object: PUBLIC TYPE = RTProcessPrivate.ProcessObject;

-- variables
processZone: ZONE = SafeStorage.NewZone[quantized];
MapPSBIToHandle: PUBLIC REF MapRecord;

-- SIGNALs
InvalidProcess: PUBLIC ERROR[h: Handle] = CODE;

-- PROCs

Current: PUBLIC PROC RETURNS[Handle] = {RETURN[MapPSBIToHandle[RTOS.GetCurrent[]]]};

PSBIToHandle: PUBLIC PROC[psbi: PSB.PsbIndex] RETURNS[Handle] =
{RETURN[MapPSBIToHandle[psbi]]};

HandleToPSBI: PUBLIC PROC[h: Handle] RETURNS[PSB.PsbIndex] =
{IF NOT Valid[h] THEN ERROR InvalidProcess[h];
RETURN[h.psbi]};

EnumerateCedarProcesses: PUBLIC PROC[p: PROC[Handle]
RETURNS[stop: BOOLEAN]]
RETURNS[stopped: BOOLEAN] =
{FOR h: Handle ← FirstHandle[], NextHandle[h] UNTIL h = NIL
DO IF Valid[h] AND p[h] THEN RETURN[TRUE]
ENDLOOP;
RETURN[FALSE]};

FirstHandle: ENTRY PROC RETURNS[Handle] =
{ENABLE UNWIND => NULL;
FOR psbi: PSB.PsbIndex IN PSB.PsbIndex
DO handle: Handle = MapPSBIToHandle[psbi];
IF DoValid[handle] THEN RETURN[handle];
ENDLOOP;
RETURN[NIL]};

NextHandle: ENTRY PROC[h: Handle] RETURNS[Handle] =
{ENABLE UNWIND => NULL;
FOR psbi: PSB.PsbIndex IN [h.psbi+1..LAST[PSB.PsbIndex]]
DO handle: Handle = MapPSBIToHandle[psbi];
IF DoValid[handle] THEN RETURN[handle];
ENDLOOP;
RETURN[NIL]};

PageFaults: PUBLIC PROC[h: Handle] RETURNS[LONG INTEGER] =
{RETURN[RTProcess.GetPSBIPageFaults[HandleToPSBI[h ! InvalidProcess => GOTO forgetIt]]];
EXITS forgetIt => RETURN[0]};

-- escape hatch
SetAttachment: PUBLIC ENTRY PROC[h: Handle, attachment: REF ANY] =
{ENABLE UNWIND => NULL;
IF NOT Valid[h] THEN ERROR InvalidProcess[h];
h.attachment ← attachment};

GetAttachment: PUBLIC ENTRY PROC[h: Handle] RETURNS[REF ANY] =
{ENABLE UNWIND => NULL;
IF NOT Valid[h] THEN ERROR InvalidProcess[h];
RETURN[h.attachment]};

Valid: PUBLIC PROC[h: Handle] RETURNS[BOOLEAN] =
{RETURN[DoValid[h]]};

DoValid: PROC[h: Handle] RETURNS[BOOLEAN] =
INLINE
{RETURN[h # NIL AND h.valid AND h.psbi # PSB.PsbNull AND IsAlive[h.psbi]]};

IsAlive: PUBLIC PROC[psbi: PSB.PsbIndex] RETURNS[BOOLEAN] =
{RETURN[ProcState[ProcessOperations.IndexToHandle[psbi]].state = alive]};

ProcState: PROC[psbh: PSB.PsbHandle] RETURNS [CPSwapDefs.ProcessState] =
INLINE
{RETURN[LOOPHOLE[PSB.PDA[psbh].flags.available, CPSwapDefs.ProcessState]]};

NewCedarProcessRegistered: PUBLIC ENTRY PROC[psbi: PSB.PsbIndex] =
{ENABLE UNWIND => NULL;
handle: Handle = MapPSBIToHandle[psbi];
IF DoValid[handle] THEN ERROR;
handle.valid ← TRUE};

InvalidateCedarProcess: PUBLIC PROC[psbi: PSB.PsbIndex] =
{h: Handle;
RTProcessPrivate.InvalidateFaultingCedarProcess[psbi];
h ← MapPSBIToHandle[psbi];
h.valid ← FALSE};


-- START HERE

MapPSBIToHandle ← NEW[RTProcessPrivate.MapRecord[LAST[PSB.PsbIndex]+1]];
FOR psbi: PSB.PsbIndex IN PSB.PsbIndex
DO MapPSBIToHandle[psbi] ← processZone.NEW[Object ← [psbi: psbi]]; ENDLOOP;

-- register the RTProcess package with RTProcessPrivateImpl
RTOS.RTProcessStarted[];

END.