-- RTSpongeImpl.Mesa

-- ******* NOTE COMPILE THIS /-c *********

-- last edited December 6, 1982 12:51 pm by Paul Rovner

DIRECTORY
Process USING[Detach, Priority, SetPriority, GetPriority],
ProcessInternal USING[DisableInterrupts],
ProcessOperations USING[EnableAndRequeue, ReadPSB, HandleToIndex],
PSB USING[PDA, PsbIndex],
RTOS USING[UnregisterCedarProcess],
RTSponge USING[spongePriority],
Runtime USING[GlobalFrame],
SpecialSpace USING[MakeCodeResident, MakeCodeSwappable, MakeGlobalFrameResident--, MakeGlobalFrameSwappable--];

RTSpongeImpl: MONITOR LOCKS Lock -- allows the Sponge to WAIT
IMPORTS Process, ProcessInternal, ProcessOperations, RTOS, Runtime, SpecialSpace
EXPORTS RTSponge
= BEGIN

Lock: PUBLIC MONITORLOCK;
SpongeNeeded: PUBLIC CONDITION;
SpongeRunning: PUBLIC CONDITION;
SpongeFinished: PUBLIC CONDITION;
SpongeEnabled: PUBLIC CONDITION;

useCount: PUBLIC CARDINAL ← 0;
spongeRunning: PUBLIC BOOLEANFALSE;
spongeDisabled: PUBLIC BOOLEANFALSE;

normalPriority: Process.Priority = Process.GetPriority[];

sponge: PROCESS;
thisModule: PROGRAM = Runtime.GlobalFrame[Sponge];

-- This guy is fired up as a detached process by the start code
Sponge: PROC =
{ RTOS.UnregisterCedarProcess[GetCurrent[]];
DO
SpongeInner[];
Yield[]; -- never let a process with a lower priority than this one run
ENDLOOP};

GetCurrent: PROC RETURNS[PSB.PsbIndex] =
INLINE
{RETURN[ProcessOperations.HandleToIndex[ProcessOperations.ReadPSB[]]]};

SpongeInner: ENTRY PROC = INLINE
{WHILE useCount = 0
DO IF spongeRunning
THEN {Process.SetPriority[normalPriority];
-- SpecialSpace.MakeGlobalFrameSwappable[RTSpongeImpl];
  SpecialSpace.MakeCodeSwappable[thisModule];
  spongeRunning ← FALSE};
WAIT SpongeNeeded
ENDLOOP;
IF NOT spongeRunning
THEN {SpecialSpace.MakeCodeResident[thisModule];
SpecialSpace.MakeGlobalFrameResident[RTSpongeImpl];
Process.SetPriority[RTSponge.spongePriority];
spongeRunning ← TRUE;
NOTIFY SpongeRunning}};

Yield: PROC = INLINE
{ ProcessInternal.DisableInterrupts[]; -- (to cancel subsequent enable)
ProcessOperations.EnableAndRequeue[@PSB.PDA.ready,
@PSB.PDA.ready,
ProcessOperations.ReadPSB[]]};



-- START HERE

Process.Detach[sponge ← FORK Sponge];

END.