-- 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.