<> <> 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 = { <> schedulingLevels: PACKED ARRAY Process.Priority OF BOOLEAN _ [FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE]; schedulingInterval: CONDITION _ [timeout: Process.MsecToTicks[defaultInterval]]; pSchedulingInterval _ @schedulingInterval; <> 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[]; <> 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.