QDTS.mesa
last edited by Levin, November 23, 1982 2:52 pm
DIRECTORY
Inline USING [BITAND],
Process USING [Detach, Milliseconds, MsecToTicks, Priority, SetPriority, Ticks],
ProcessInternal USING [DisableInterrupts, EnableInterrupts],
ProcessOperations USING [Requeue],
ProcessPriorities USING [priorityRealTime],
PSB USING [PDA, PsbHandle, PsbIndex, PsbLink, Queue],
SpecialSpace USING [MakeProcedureResident];
QDTS: MONITOR
IMPORTS Inline, Process, ProcessInternal, ProcessOperations, SpecialSpace =
BEGIN OPEN PSB;
defaultInterval: Process.Milliseconds = 100;
schedulerPriority: Process.Priority = ProcessPriorities.priorityRealTime;
pSchedulingInterval: LONG POINTER TO CONDITIONNIL;
psbNextMask: PsbLink =
[failed: FALSE, priority: 0, next: LAST[PsbIndex], reserved: 0, vector: FALSE];
queueTailMask: Queue = [reserved1: 0, tail: LAST[PsbIndex], reserved2: 0];
SetTimeSlice: PUBLIC ENTRY PROC [ticks: Process.Ticks] = {
IF pSchedulingInterval = NIL THEN RETURN;
pSchedulingInterval^.timeout ← ticks;
NOTIFY pSchedulingInterval^;
};
Schedule: ENTRY PROCEDURE = {
The following is intended to be altered only by the debugger.
schedulingLevels: PACKED ARRAY Process.Priority OF BOOLEAN
[FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE];
schedulingInterval: CONDITION ← [timeout: Process.MsecToTicks[defaultInterval]];
pSchedulingInterval ← @schedulingInterval;
Note: this procedure only touches resident structures and does not call any procedures. Therefore, in principle, it could run at schedulerPriority = priorityFrameFault.
Process.SetPriority[schedulerPriority];
DO
WAIT schedulingInterval;
FOR priority: Process.Priority DECREASING IN [FIRST[Process.Priority]..schedulerPriority) DO
IF schedulingLevels[priority] THEN {
psb: PsbHandle;
ProcessInternal.DisableInterrupts[];
Note that readyList can't be empty, since we are running!
psb ← PsbLinkToPsbHandle[PDA[QueueToPsbHandle[PDA.ready]].link];
DO
SELECT PDA[psb].link.priority FROM
= priority => {ProcessOperations.Requeue[@PDA.ready, @PDA.ready, psb]; EXIT};
< priority => EXIT;
ENDCASE => IF psb = QueueToPsbHandle[PDA.ready] THEN EXIT;
psb ← PsbLinkToPsbHandle[PDA[psb].link];
ENDLOOP;
ProcessInternal.EnableInterrupts[];
};
ENDLOOP;
ENDLOOP;
};
PsbLinkToPsbHandle: PROCEDURE [psbLink: PsbLink] RETURNS [PsbHandle] = INLINE
{RETURN[Inline.BITAND[psbLink, psbNextMask]]};
QueueToPsbHandle: PROCEDURE [queue: Queue] RETURNS [PsbHandle] = INLINE
{RETURN[Inline.BITAND[queue, queueTailMask]]};
-- Main body --
Initialize: ENTRY PROCEDURE = INLINE {
SpecialSpace.MakeProcedureResident[Schedule];
Process.Detach[FORK Schedule[]];
};
Initialize[];
END.