-- IntervalTimerHeadDorado.mesa
-- Last Edited by: Taft, March 31, 1983 9:12 am
-- Last Edited by: Stewart, January 1, 1984 6:24 pm

DIRECTORY
Basics USING [LowHalf],
DeviceCleanup USING [Await, Item, Reason],
DoradoInputOutput USING [SetIntervalTimer],
IntervalTimerFace,
Loader USING [ MakeProcedureResident, MakeGlobalFrameResident ],
PrincOpsUtils USING [AllocateNakedCondition, LongNotify],
ProcessorFace USING [GetClockPulses];

IntervalTimerHeadDorado: MONITOR
IMPORTS Basics, DeviceCleanup, DoradoInputOutput, Loader, PrincOpsUtils, ProcessorFace
EXPORTS IntervalTimerFace =
BEGIN OPEN IntervalTimerFace;

csb: LONG POINTER TO IntervalTimerCSB = LOOPHOLE[LONG[177422B]];
IntervalTimerCSB: TYPE = RECORD [
wakeups: WORD];

nakedCondition: LONG POINTER TO CONDITION;

expirationTime: ClockPulses;

SetExpirationTime: PUBLIC PROCEDURE [time: ClockPulses] =
BEGIN
expirationTime ← time;
DoradoInputOutput.SetIntervalTimer[Basics.LowHalf[expirationTime]];
IF LOOPHOLE[ProcessorFace.GetClockPulses[] - expirationTime, INT] >= 0 THEN
PrincOpsUtils.LongNotify[nakedCondition];
END;

Wait: PUBLIC ENTRY PROCEDURE =
BEGIN
DO
WAIT nakedCondition;
IF LOOPHOLE[ProcessorFace.GetClockPulses[] - expirationTime, INT] >= 0 THEN EXIT;
SetExpirationTime[expirationTime];
ENDLOOP;
END;

exists: PUBLIC BOOLEAN ← TRUE;

InitializeCleanup: PROCEDURE =
BEGIN
item: DeviceCleanup.Item;
reason: DeviceCleanup.Reason;
savedCSB: IntervalTimerCSB;
DO
reason ← DeviceCleanup.Await[@item];
SELECT reason FROM
 turnOff, kill =>
  BEGIN
  savedCSB ← csb^;
  csb.wakeups ← 0;
  END;
 turnOn =>
  BEGIN
  csb^ ← savedCSB;
  SetExpirationTime[expirationTime];
  END;
 ENDCASE
ENDLOOP
END;

Start: PROCEDURE =
BEGIN
[cv: nakedCondition, mask: csb.wakeups] ← PrincOpsUtils.AllocateNakedCondition[];
Loader.MakeProcedureResident[InitializeCleanup];
Loader.MakeGlobalFrameResident[InitializeCleanup];
InitializeCleanup[];
-- RemainingHeads.Start[];
END;

Start[];
END.
January 1, 1984 6:24 pm, Stewart, added Loader procedures on advice of Taft