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 CONDITION ← NIL;
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.