-- file VirtCom.mesa -- edited by Kierr, February 8, 1978 11:32 AM. -- edited by Schroeder, November 18, 1980 12:50 PM. -- edited by Brotz, November 19, 1980 3:08 PM. -- edited by Levin, November 19, 1980 10:15 AM. -- Provides procedures common to VirtTOC, VirtCM, and VirtSS that manage the primary -- memory buffers for TOC's, DM's, and CM's. This module is expected to be in primary -- memory whenever any of the other three are. DIRECTORY crD: FROM "CoreDefs", exD: FROM "ExceptionDefs", gsD: FROM "GlobalStorageDefs", Inline, intCommon: FROM "IntCommon", ovD: FROM "OverviewDefs", tfD: FROM "TempFileDefs", vmD: FROM "VirtualMgrDefs"; VirtCom: PROGRAM IMPORTS crD, exD, gsD, Inline, intC: intCommon, tfD, vmD EXPORTS vmD SHARES vmD = PUBLIC BEGIN OPEN vmD; GetMessageChar: PROCEDURE [vs: VirtualMessagePtr, index: ovD.CharIndex] RETURNS [CHARACTER] = -- Obtains the index'th character (starting at zero) from the virtual structure vs. BEGIN OPEN g: vs.get; page: PageNumber; byte: CARDINAL; IF NOT (index IN [g.first .. g.free)) THEN WITH msg:vs^ SELECT FROM DM => BEGIN IF index >= msg.textLength THEN exD.SysBug[]; [page, byte] _ Inline.DIVMOD[msg.firstByte + index, 512]; page _ page + msg.firstPage; [g.mtPtr,] _ GetMtPtr[@msg, page, active]; g.first _ IF index > byte THEN index - byte ELSE 0; g.floor _ IF g.first = 0 THEN byte - index ELSE 0; g.free _ MIN[index + 512 - byte, vs.textLength]; g.string _ LOOPHOLE[g.mtPtr.address - 2, STRING]; END; CM => BEGIN [page, byte] _ MapCharIndexToPageByte[@msg, index]; IF SetGetCacheForCMPage[old, @msg, page, index - byte] # ovD.ok THEN exD.SysBug[]; --Can't happen for "old". END; ENDCASE; RETURN[g.string[index + g.floor - g.first]]; END; -- of GetMessageChar -- VoidCharCache: PROCEDURE [c: POINTER TO CharCache] = BEGIN easyToSpotValue: ovD.CharIndex = 177777B; c.first _ c.free _ easyToSpotValue; -- first=free is what counts END; -- of VoidCharCache -- GetMtPtr: PROCEDURE [vop: VirtualObjectPtr, pn: PageNumber, pageState: GetMtPtrState] RETURNS [mtPtr: MemoryTableEntryPtr, npn: PageNumber] = -- Arranges for the designated page of the designated object to occupy a primary memory -- buffer page, and returns a pointer to the corresponding Mte. Also returned is the new -- number for the designated page, which in the case that vop points to a CM may be less -- than pn because a compaction of the CM buffer pool has occured. If pageState = new -- then buffer pool is NOT checked to see if the page is already there. If pageState = -- active then the corresponding page will be read in from the backing file if the page is -- not already in the buffer pool. BEGIN oneBeforeMtPtr: MemoryTableEntryPtr _ NIL; rpn: PageNumber; -- page removed by a compaction compacted: BOOLEAN; npn _ pn; -- guess that returned pn is to be the same as requested pn IF pageState # new THEN --see if page is already in the buffer pool FOR mtPtr _ vop.memoryHeader, mtPtr.next UNTIL mtPtr = NIL DO IF mtPtr.state # unused AND mtPtr.logicalPageNumber = pn THEN BEGIN --found page in the buffer pool IF oneBeforeMtPtr # NIL THEN BEGIN oneBeforeMtPtr.next _ mtPtr.next; mtPtr.next _ vop.memoryHeader; vop.memoryHeader _ mtPtr; END; RETURN; --page was already in the buffer pool END; oneBeforeMtPtr _ mtPtr; ENDLOOP; [compacted, rpn] _ MakeBufferPoolHeadUnused[vop]; mtPtr _ vop.memoryHeader; -- get a pointer to the unused Mte mtPtr.state _ clean; mtPtr.filePageNumber _ mtPtr.logicalPageNumber _ pn; -- guess that they are the same IF mtPtr.address = NIL THEN -- no buffer page yet for this entry mtPtr.address _ gsD.GetMemoryPages[1]; WITH vo: vop^ SELECT FROM -- if we have a CM page numbers may be wrong VMO => WITH msg: vo SELECT FROM CM => BEGIN IF compacted AND pn > rpn THEN mtPtr.logicalPageNumber _ npn _ pn-1; mtPtr.filePageNumber _ msg.charMap[npn].page; END; ENDCASE; ENDCASE; IF pageState = active THEN ReadPageFromFile[vop, mtPtr]; RETURN; END; -- of GetMtPtr -- MakeBufferPoolHeadUnused: PROCEDURE [vop: VirtualObjectPtr] RETURNS [compacted: BOOLEAN, rpn: PageNumber] = -- Finds or makes an unused mte and relinks it to head of lru list. Compacted is returned -- FALSE unless the vop designates a CM and finding an unused Mte has caused -- compaction in the CM's buffer pool. When compacted is returned TRUE, the rpn -- returns the number of the CM page removed by the compaction. BEGIN oneBeforeMtPtr: MemoryTableEntryPtr _ NIL; mtPtr: MemoryTableEntryPtr; compacted _ FALSE; FOR mtPtr _ vop.memoryHeader, mtPtr.next UNTIL mtPtr = NIL DO IF mtPtr.state = unused THEN BEGIN -- have found an unused Mte IF oneBeforeMtPtr # NIL THEN BEGIN -- relink to the head of the buffer pool oneBeforeMtPtr.next _ mtPtr.next; mtPtr.next _ vop.memoryHeader; vop.memoryHeader _ mtPtr; END; RETURN; END; oneBeforeMtPtr _ mtPtr; ENDLOOP; -- there was no unused Mte so we must make one WITH vo: vop^ SELECT FROM -- if we have a CM compaction may be possible VMO => WITH msg: vo SELECT FROM CM => [compacted, rpn] _ TryToCompactBufferPool[@msg]; ENDCASE; ENDCASE; IF NOT compacted THEN BEGIN -- take last buffer in the lru list IF oneBeforeMtPtr.state = dirty THEN WritePageToFile[vop, oneBeforeMtPtr]; oneBeforeMtPtr.state _ unused; END; -- now there is an unused Mte for sure so find it and relink it oneBeforeMtPtr _ NIL; FOR mtPtr _ vop.memoryHeader, mtPtr.next UNTIL mtPtr.state = unused DO oneBeforeMtPtr _ mtPtr; ENDLOOP; IF oneBeforeMtPtr # NIL THEN BEGIN -- relink to the head of the buffer pool oneBeforeMtPtr.next _ mtPtr.next; mtPtr.next _ vop.memoryHeader; vop.memoryHeader _ mtPtr; END; RETURN; END; -- of MakeBufferPoolHeadUnused. WritePageToFile: PROCEDURE [vop: VirtualObjectPtr, mtPtr: MemoryTableEntryPtr] = -- Writes the file page associated with the designated Mte. BEGIN IF vop.file = NIL THEN vop.file _ tfD.AllocateTempFile[]; BombIfIOError[crD.WritePages[mtPtr.address, 512, mtPtr.filePageNumber, vop.file]]; RETURN; END; -- of WritePageToFile -- ReadPageFromFile: PROCEDURE [vop: VirtualObjectPtr, mtPtr: MemoryTableEntryPtr] = -- Reads the file page associated with the designated Mte. BEGIN IF vop.file = NIL THEN exD.SysBug[]; BombIfIOError[crD.ReadPages[mtPtr.address, 512, mtPtr.filePageNumber, vop.file].erc]; RETURN; END; -- of ReadPageFromFile -- BombIfIOError: PROCEDURE [erc: ovD.ErrorCode] = -- Call SysBug if erc isn't "ok". BEGIN IF erc # ovD.ok THEN exD.SysBug [SELECT erc FROM ovD.diskFull => exD.diskFull, ovD.fileTooBig => exD.fileTooLong, ENDCASE => exD.ioError]; RETURN; END; -- of BombIfIOError -- END. -- of VirtComz20461(529)