-- VMMgr>ProjectionImpl.mesa (last edited by Levin on August 3, 1982 4:05 pm) -- The routines in this module are only called from within the SpaceImpl monitor. Thus, the database accessed by this module need not be protected by a local monitor because it is already protected by the SpaceImpl monitor. DIRECTORY CachedRegion USING [Apply, Desc, Insert, State, Outcome], CachedSpace USING [Level], Projection USING [], STLeaf USING [alive, ProjectionState], STree USING [Delete, Desc, Get, Insert, Key, PDesc, Update], VM USING [PageNumber, PageCount], VMMPrograms USING []; ProjectionImpl: PROGRAM [countVM: VM.PageCount] -- (not a monitor) IMPORTS CachedRegion, STree EXPORTS Projection, VMMPrograms = BEGIN Bug: ERROR[type: BugType] = CODE; -- not to be caught by client. BugType: TYPE = {funnyLevel, funnyOutcome, mergeAtZero}; DeleteSwapUnits: PUBLIC PROCEDURE [pageMember: VM.PageNumber] = BEGIN projDesc: projection STree.Desc; [] ← STree.Get[LOOPHOLE[LONG[@projDesc], STree.PDesc], [projection[pageMember]] ]; IF projDesc.hasSwapUnits THEN { projDesc.hasSwapUnits ← FALSE; STree.Update[LOOPHOLE[LONG[@projDesc], STree.PDesc]] }; END; ForceOut: PUBLIC PROCEDURE [pageMember: VM.PageNumber] = BEGIN desc: CachedRegion.Desc; outcome: CachedRegion.Outcome = CachedRegion.Apply[pageMember, [ifMissing: report, ifCheckedOut: wait, afterForking: , vp: get[andResetDDirty: TRUE, pDescResult: @desc]]].outcome; WITH outcome SELECT FROM ok => IF desc.dDirty THEN BEGIN OPEN desc; projDesc: projection STree.Desc ← [projection[ -- transform a CachedRegion.Desc into an projection STLeaf.Desc: page: interval.page, level: level, state: IF state IN STLeaf.ProjectionState THEN state ELSE --state IN CachedRegion.Alive-- STLeaf.alive, -- (in a projection desc, we only know that the region is some flavor of alive.) levelMapped: levelMapped, writeProtected: writeProtected, hasSwapUnits: hasSwapUnits, needsLogging: needsLogging]]; STree.Update[LOOPHOLE[LONG[@projDesc], STree.PDesc]] END; regionDMissing => NULL; ENDCASE => ERROR Bug[funnyOutcome]; END; Get: PUBLIC PROCEDURE [pageMember: VM.PageNumber] RETURNS [desc: CachedRegion.Desc] = BEGIN projDesc: projection STree.Desc; keyNext: STree.Key; descVictim: CachedRegion.Desc; outcome: CachedRegion.Outcome = CachedRegion.Apply[pageMember, [ifMissing: report, ifCheckedOut: wait, afterForking: , vp: get[andResetDDirty: FALSE, pDescResult: @desc]]].outcome; WITH outcome SELECT FROM ok => NULL; -- descriptor is in the cache, just return .it regionDMissing => -- Otherwise, fetch descriptor from hierarchy and cache it.. BEGIN keyNext ← STree.Get[LOOPHOLE[LONG[@projDesc], STree.PDesc], [projection[pageMember]]]; BEGIN OPEN projDesc; desc ← [ -- transform an projection STLeaf.Desc into a CachedRegion.Desc: interval: [page, keyNext.pageP-page], level: level, dPinned: FALSE, dTemperature: , -- don't care dDirty: FALSE, state: state, -- i.e. outAlive. levelMapped: levelMapped, beingFlushed: FALSE, writeProtected: writeProtected, hasSwapUnits: hasSwapUnits, needsLogging: needsLogging]; END; descVictim ← CachedRegion.Insert[desc]; IF descVictim.dDirty THEN BEGIN OPEN descVictim; projDesc ← [projection[ -- transform a CachedRegion.Desc into an projection STLeaf.Desc: page: interval.page, level: level, state: IF state IN STLeaf.ProjectionState THEN state ELSE --state IN CachedRegion.Alive-- STLeaf.alive, -- (in a projection desc, we only know that the region is some flavor of alive.) levelMapped: levelMapped, writeProtected: writeProtected, hasSwapUnits: hasSwapUnits, needsLogging: needsLogging]]; STree.Update[LOOPHOLE[LONG[@projDesc], STree.PDesc]] END END; ENDCASE => ERROR Bug[funnyOutcome]; END; Merge: PUBLIC PROCEDURE [pageNext: VM.PageNumber] = BEGIN projDesc: projection STree.Desc; IF pageNext=0 THEN ERROR Bug[mergeAtZero]; -- Unconditionally "resurrect" a dead region: conservative approach to avoid propagating deadness [] ← STree.Get[LOOPHOLE[LONG[@projDesc], STree.PDesc], [projection[pageNext-1]]]; IF projDesc.state=outDead THEN { projDesc.state ← outAlive; STree.Update[LOOPHOLE[LONG[@projDesc], STree.PDesc]] }; -- Do the merge: (depends on the fact that the size of a projection STree.Desc is implicit) STree.Delete[[projection[pageNext]]]; END; Split: PUBLIC PROCEDURE [pageNext: VM.PageNumber] = BEGIN projDesc: projection STree.Desc; IF pageNext~=countVM THEN BEGIN -- Depends on the fact that the size of a projection STree.Desc is implicit [] ← STree.Get[LOOPHOLE[LONG[@projDesc], STree.PDesc], [projection[pageNext]]]; IF projDesc.page~=pageNext THEN { projDesc.page ← pageNext; STree.Insert[LOOPHOLE[LONG[@projDesc], STree.PDesc]] }; END; END; Touch: PUBLIC PROCEDURE [pageMember: VM.PageNumber] = { [] ← Get[pageMember] }; TranslateLevel: PUBLIC PROCEDURE [pageMember: VM.PageNumber, delta: INTEGER] = BEGIN projDesc: projection STree.Desc; [] ← STree.Get[LOOPHOLE[LONG[@projDesc], STree.PDesc], [projection[pageMember]]]; IF ~(projDesc.level+delta IN CachedSpace.Level) THEN ERROR Bug[funnyLevel]; projDesc.level ← projDesc.level+delta; STree.Update[LOOPHOLE[LONG[@projDesc], STree.PDesc]] END; END. LOG May 24, 1978 10:13 AM McJones Created file. June 23, 1978 10:57 AM McJones Split didn't check for pageNext=countVM. August 2, 1978 9:27 AM McJones Updated to new CachedRegion interface. August 4, 1978 2:19 PM McJones Added beingRemapped. August 29, 1978 7:32 PM McJones Cleared dDirty before calling CachedRegion.Insert. August 21, 1979 4:33 PM Knutsen Made compatible with new CachedRegion.Desc. September 28, 1979 3:57 PM Knutsen Made compatible with new CachedRegion.Desc. February 25, 1980 6:01 PM Knutsen Added DeleteSwapUnits. Named the ERRORs. June 16, 1980 4:57 PM Gobbel Made compatible with new CachedRegion.Desc. July 30, 1980 2:52 PM Knutsen Made compatible with new CachedRegion.Desc. September 16, 1980 9:48 AM Knutsen DeleteSwapUnits failed if no existing swap units. August 3, 1982 4:05 pm Levin Correct all occurrences of ~IN.