-- Swapper>SwapperControl.mesa (last edited by Levin on September 15, 1982 8:50 pm)
DIRECTORY
CachedRegion USING [age, Apply, Outcome, pagefault, pageTop],
CachedRegionInternal USING [FindUnreferenced],
Environment USING [PageCount, PageNumber],
MStore USING [AwaitBelowThreshold, SetThreshold],
PageFault USING [AwaitPageFault],
Process USING [DisableAborts, GetPriority, Priority, SetPriority, SetTimeout],
ProcessPriorities USING [priorityPageFaultHigh],
Runtime USING [CallDebugger],
StoragePrograms USING [],
SwapperException USING [Report],
SwapperPrograms USING [
CachedRegionImplB, CachedSpaceImpl, PageFaultImpl, InitializeSwapBuffer,
SwapperExceptionImpl, SwapTaskImpl];
SwapperControl: MONITOR --just so we can use a CONDITION as a mechanism for yielding control--
IMPORTS
CachedRegion, CachedRegionInternal, MStore, PageFault, Process, Runtime,
SwapperException, SwapperPrograms
EXPORTS StoragePrograms =
BEGIN
InitializeSwapper: PUBLIC PROCEDURE [pMapLogDesc: LONG POINTER TO UNSPECIFIED] =
BEGIN
throwAway: PROCESS;
priorityPrev: Process.Priority;
-- CachedRegionImplA is started by PilotControl (see StoragePrograms).
-- MStoreImpl is started by PilotControl (see StoragePrograms).
-- SimpleSpaceImpl is started by PilotControl (see StoragePrograms).
-- ResidentMemoryImpl is started by PilotControl (see StoragePrograms).
-- ResidentHeapImpl is started by PilotControl (see StoragePrograms).
START SwapperPrograms.CachedSpaceImpl[];
START SwapperPrograms.CachedRegionImplB[pMapLogDesc];
SwapperPrograms.InitializeSwapBuffer[]; -- (CachedSpaceImpl must be started first.)
START SwapperPrograms.PageFaultImpl[];
START SwapperPrograms.SwapTaskImpl[];
START SwapperPrograms.SwapperExceptionImpl[];
Process.DisableAborts[@aShortTime];
Process.SetTimeout[condition: @aShortTime, ticks: 1];
priorityPrev ← Process.GetPriority[];
Process.SetPriority[ProcessPriorities.priorityPageFaultHigh];
throwAway ← FORK PageFaultProcess[]; -- (no profit in detaching.)
Process.SetPriority[priorityPrev];
-- (ReplacementProcess is forked by PilotControl.)
END;
PageFaultProcess: PROCEDURE =
BEGIN
page: Environment.PageNumber;
outcome: CachedRegion.Outcome;
DO
page ← PageFault.AwaitPageFault[]; -- wait for a page fault.
-- Start region coming in. Faulting process will be restarted by PageTransferProcess
-- when it is in.
outcome ← CachedRegion.Apply[page, CachedRegion.pagefault].outcome;
WITH outcome SELECT FROM
ok => NULL;
regionDMissing, spaceDMissing, error =>
-- I can't do it, pass the buck to the VM Helper.
SwapperException.Report[page, CachedRegion.pagefault, outcome];
ENDCASE => ERROR;
ENDLOOP;
END;
aShortTime: CONDITION; -- used to yield control to VM Helper, and to yield control if everyone is being referenced.
ReplacementProcess: PUBLIC ENTRY PROCEDURE [threshold: Environment.PageCount] =
BEGIN
deadlockPasses: CARDINAL = 1000; -- meant to be about 60 sec of trying.
swapUnitsAgedInCycle: CARDINAL; -- just for instrumentation.
page, pageNext: Environment.PageNumber;
newCycle, allReferenced: BOOLEAN;
outcome: CachedRegion.Outcome;
passes: CARDINAL ← 0;
MStore.SetThreshold[threshold];
DO --make a pass through memory..
FOR page ← FIRST[Environment.PageNumber], pageNext WHILE page<CachedRegion.pageTop DO
IF (newCycle ← MStore.AwaitBelowThreshold[].newCycle) THEN -- wait until memory gets short
{passes ← 0; swapUnitsAgedInCycle ← 0};
[allReferenced, page] ← CachedRegionInternal.FindUnreferenced[newCycle, page];
IF allReferenced THEN WAIT aShortTime;
[outcome, pageNext] ← CachedRegion.Apply[page, CachedRegion.age]; -- swaps out region if not referenced; else marks it not referenced.
swapUnitsAgedInCycle ← SUCC[swapUnitsAgedInCycle];
SELECT outcome.kind FROM
ok => NULL;
spaceDMissing => {
SwapperException.Report[page, CachedRegion.age, outcome];
IF passes >= 2 THEN WAIT aShortTime;
}; -- if we're having trouble, allow VM Helper a chance to make progress.
ENDCASE => ERROR;
ENDLOOP;
IF (passes ← SUCC[passes]) >= deadlockPasses THEN
Runtime.CallDebugger["No regions to swap out!"];
ENDLOOP; --end of one pass through memory.
END;
END.
LOG
(For earlier log entries, see Pilot 3.0 archive version.)
January 31, 1980 1:03 PM Knutsen/McJones Add Region Cache parameters/switch to InitializeSwapper starting interface.
February 21, 1980 6:53 PM Knutsen Implement Region Cache parameters. Don't START MStoreImpl (now started by PilotControl).
March 20, 1980 12:50 PM Knutsen Made ReplacementProcess detect deadlocks.
April 15, 1980 12:05 PM Knutsen Various components started early by PilotControl.
December 1, 1980 12:55 PM Knutsen Only use Process.mumble during initialization. Yield to VMHelper if having trouble. Use FindUnreferenced.
January 19, 1981 4:14 PM Knutsen Set process priorities.
September 15, 1982 8:50 pm Levin PageFault.Await => PageFault.AwaitPageFault.