DIRECTORY Collector USING [backgroundCollectorProcess], PrincOps USING [ NullStateVectorHandle, PDA, PDABase, Priority, PsbHandle, StateVectorHandle], PrincOpsUtils USING [DisableInterrupts, EnableInterrupts, PsbIndexToHandle, Requeue], Process USING [Detach, MsecToTicks, Pause, priorityClient3, SetPriority], SafeStorage USING [IsCollectorActive, WaitForCollectorStart]; CollectorWatchdogImpl: PROGRAM IMPORTS Collector, PrincOpsUtils, Process, SafeStorage EXPORTS Collector = BEGIN PDA: PrincOps.PDABase = PrincOps.PDA; latency: PUBLIC CARDINAL _ 2000; -- milliseconds timesBumped: INT _ 0; enabled: BOOL _ TRUE; ResetPriority: PROC [psb: PrincOps.PsbHandle, new: PrincOps.Priority] RETURNS [success: BOOL _ TRUE] = { old: PrincOps.Priority; PrincOpsUtils.DisableInterrupts[]; old _ PDA[psb].link.priority; IF old # new THEN { self: PrincOps.PsbHandle = PrincOpsUtils.PsbIndexToHandle[ PDA[PrincOpsUtils.PsbIndexToHandle[PDA.ready.tail]].link.next]; npsb: PrincOps.PsbHandle _ PrincOpsUtils.PsbIndexToHandle[PDA[self].link.next]; IF PDA[psb].link.vector THEN { nsv: PrincOps.StateVectorHandle _ PDA.state[new]; IF nsv = PrincOps.NullStateVectorHandle THEN GO TO fail; PDA.state[new] _ LOOPHOLE[PDA[nsv].stk[0]]; PDA[nsv].stk[0] _ LOOPHOLE[PDA.state[old]]; PDA.state[old] _ nsv; }; PDA[psb].link.priority _ new; DO IF npsb = self THEN EXIT; IF npsb = psb THEN { PrincOpsUtils.Requeue[@PDA.ready, @PDA.ready, psb]; EXIT; }; npsb _ PrincOpsUtils.PsbIndexToHandle[PDA[npsb].link.next]; ENDLOOP; EXITS fail => {success _ FALSE}; }; PrincOpsUtils.EnableInterrupts[]; }; BailOutCollector: PROC = { psb: PrincOps.PsbHandle _ PrincOpsUtils.PsbIndexToHandle[LOOPHOLE[Collector.backgroundCollectorProcess]]; lag: INT _ 0; Process.SetPriority[Process.priorityClient3]; WHILE enabled DO active: BOOL; count: INT; [incarnation: lag] _ SafeStorage.WaitForCollectorStart[]; Process.Pause[Process.MsecToTicks[latency]]; [active, count] _ SafeStorage.IsCollectorActive[]; IF NOT active OR count # lag THEN LOOP; {priority: PrincOps.Priority = PDA[psb].link.priority; IF priority < Process.priorityClient3 THEN THROUGH [0..100) DO IF ResetPriority[psb, priority + 1] THEN { timesBumped _ timesBumped + 1; EXIT; }; Process.Pause[Process.MsecToTicks[100]]; [active, count] _ SafeStorage.IsCollectorActive[]; IF NOT active OR count # lag THEN EXIT; ENDLOOP; }; ENDLOOP; }; Process.Detach[FORK BailOutCollector[]]; END. ΔCollectorWatchdogImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Russ Atkinson, February 1, 1985 1:14:18 pm PST This routine sets the priority of the specified process. We need to preserve the number of state vectors at various priorities. The easiest way to do this is to transfer a state vector from the new priority list to the old priority list, which allows the current state vector to remain with the process. If there is no available state vector at that priority, then we lose. Remove the new state vector from its priority chain Give the new state vector to the old priority chain. At this point we can alter the priority and assume success. If the process that is getting its priority changed is on the ready queue we must remove it from the queue and put it back, thereby changing its position in the queue. If it was not on the ready queue, we hope that changing its priority did not upset someone who was depending on priorities being sorted within other kinds of queues. We will see what we will see! If the collector is not active OR is a different collection, then wait until it is At this point the collector is running and it has been running more than the required latency for being bumped. So bump the priority and try again. We could not change the priority because there were no state vectors at the target priority level, so we wait a brief while for either success or for something else to change about the collection. ΚΩ˜codešœ™Kšœ Οmœ1™