-- File: DebugCache.Mesa -- Last edited by -- Bruce; July 2, 1980 4:30 PM -- Sandman; November 9, 1979 9:03 AM -- Johnsson; July 11, 1980 11:11 AM DIRECTORY BFSDefs USING [ActOnPages, GetNextDA], DebugOps USING [Lengthen, LongREAD, ShortREAD], DebugUsefulDefs USING [], DiskDefs USING [DiskRequest], Drum USING [], Init USING [], InlineDefs USING [COPY, HighHalf, LongDivMod, LongMult, LongNumber], MachineDefs USING [eofDA, fillinDA, PageSize, SwappingProcedure, vDA], Mopcodes USING [zPOP, zR0, zRBL, zW0, zWBL], SegmentDefs USING [BankIndex, DefaultBase, DeleteFileSegment, FileHandle, FileSegmentAddress, FileSegmentHandle, HardUp, LockFile, MakeSwappedIn, NewFileSegment, Read, SetFileSegmentDA, Unlock], State USING [GetGS, GSHandle], Storage USING [Free, FreePages, Node, Pages], SwapperOps USING [RegionTable, SystemTable]; DebugCache: PROGRAM IMPORTS BFSDefs, DebugOps, InlineDefs, State, Storage, SegmentDefs EXPORTS DebugOps, DebugUsefulDefs, Drum, Init SHARES DiskDefs, SegmentDefs = BEGIN OPEN MachineDefs; InvalidAddress: PUBLIC ERROR [address: LONG POINTER] = CODE; -- Cache of user memory pages CoreSegmentObject: TYPE = RECORD [ address: POINTER, lastused: CARDINAL, mempage: CARDINAL, inuse: BOOLEAN, dirty: BOOLEAN, segment: SegmentDefs.FileSegmentHandle]; CoreSegment: TYPE = POINTER TO CoreSegmentObject; maxsegments: CARDINAL = 4; -- number of pages to keep in core CS: ARRAY [0..maxsegments) OF CoreSegmentObject; CurrentUseValue: CARDINAL; data: State.GSHandle ← State.GetGS[]; CoreFile: SegmentDefs.FileHandle; DaListItem: TYPE = RECORD [ link: POINTER TO DaListItem, base: vDA, count: CARDINAL]; DAs: POINTER TO DaListItem ← NIL; DiskAddresses: PROCEDURE [page: CARDINAL] RETURNS [vDA] = BEGIN curBase: CARDINAL ← 0; FOR p: POINTER TO DaListItem ← DAs, p.link UNTIL p = NIL DO IF page < curBase + p.count THEN RETURN[[p.base+(page-curBase)]]; curBase ← curBase + p.count; ENDLOOP; RETURN[eofDA] END; InitCoreCache: PROCEDURE [file: SegmentDefs.FileHandle] = BEGIN i: CARDINAL; CurrentUseValue ← 0; FOR i IN [0..maxsegments) DO CS[i].inuse ← FALSE ENDLOOP; CoreFile ← file; SegmentDefs.LockFile[CoreFile]; END; Lengthen: PUBLIC PROCEDURE [p: POINTER] RETURNS [LONG POINTER] = BEGIN OPEN InlineDefs, MachineDefs; mds: LONG CARDINAL = LongMult[data.mds, PageSize]; lp: LongNumber ← [num[lowbits: LOOPHOLE[p, CARDINAL], highbits: 0]]; RETURN[IF p = NIL THEN NIL ELSE LOOPHOLE[lp.lc+mds]] END; FlushCoreCache: PUBLIC MachineDefs.SwappingProcedure = BEGIN OPEN SegmentDefs; did: BOOLEAN ← FALSE; i: CARDINAL ← 0; cs: CoreSegment; -- CacheSwap.proc ← AllocDefs.CantSwap; FOR i IN [0..maxsegments) DO cs←@CS[i]; IF cs.inuse THEN BEGIN FlushCS[cs]; did ← TRUE; END; ENDLOOP; CurrentUseValue←0; RETURN[did] END; FlushCS: PROCEDURE [cs: CoreSegment] = BEGIN OPEN SegmentDefs, cs; IF dirty THEN segment.write ← TRUE; Unlock[segment]; DeleteFileSegment[segment]; inuse ← FALSE; END; NewSwateeSegment: PROCEDURE [mempage: CARDINAL, cs: CoreSegment] = BEGIN OPEN SegmentDefs; filepage: CARDINAL = SELECT mempage FROM IN[2..253] => mempage, 1 => 254, ENDCASE => 255; seg: FileSegmentHandle = NewFileSegment[CoreFile, filepage, 1, Read]; SetFileSegmentDA[seg, DiskAddresses[filepage]]; MakeSwappedIn[seg, DefaultBase, HardUp]; cs↑ ← [ address: FileSegmentAddress[seg], inuse: TRUE, dirty: FALSE, lastused:, mempage: mempage, segment: seg]; RETURN END; GetCS: PROCEDURE [mempage: CARDINAL] RETURNS [sp: CoreSegment] = BEGIN minUseVal: CARDINAL ← CurrentUseValue; minUseIndex: CARDINAL ← 0; i: CARDINAL; BEGIN FOR i IN [0..maxsegments) DO sp ← @CS[i]; IF ~sp.inuse THEN GO TO newseg; IF sp.mempage = mempage THEN EXIT; IF sp.lastused < minUseVal THEN BEGIN minUseVal←sp.lastused; minUseIndex←i END; REPEAT FINISHED => BEGIN FOR i IN [0..maxsegments) DO CS[i].lastused ← CS[i].lastused - minUseVal; ENDLOOP; CurrentUseValue ← CurrentUseValue - minUseVal; FlushCS[sp ← @CS[minUseIndex]]; GO TO newseg; END ENDLOOP; EXITS newseg => BEGIN cso: CoreSegmentObject; IF mempage IN [0..253] THEN NewSwateeSegment[mempage, @cso] ELSE ERROR; FOR i IN [0..maxsegments) DO sp ← @CS[i]; IF ~sp.inuse THEN BEGIN sp↑ ← cso; EXIT END; REPEAT FINISHED => ERROR ENDLOOP; END; END; sp.lastused ← CurrentUseValue ← CurrentUseValue+1; -- CacheSwap.proc ← FlushCoreCache; RETURN[sp]; END; LongREAD: PUBLIC PROCEDURE [loc: LONG POINTER] RETURNS [val: UNSPECIFIED] = BEGIN OPEN Mopcodes; ReadMEMORY: PROCEDURE [LONG POINTER] RETURNS [UNSPECIFIED] = MACHINE CODE BEGIN zPOP; zR0 END; mempage, offset: CARDINAL; [mempage, offset] ← InlineDefs.LongDivMod[LOOPHOLE[loc],PageSize]; SELECT mempage FROM > 255 => RETURN[ReadVM[loc]]; > 253 => RETURN[ReadMEMORY[loc]]; ENDCASE => RETURN [(GetCS[mempage].address + offset)↑]; END; LongWRITE: PUBLIC PROCEDURE [loc: LONG POINTER, val: UNSPECIFIED] = BEGIN WriteMEMORY: PROCEDURE [UNSPECIFIED, LONG POINTER] = MACHINE CODE BEGIN Mopcodes.zPOP; Mopcodes.zW0 END; mempage, offset: CARDINAL; [mempage, offset] ← InlineDefs.LongDivMod[LOOPHOLE[loc],PageSize]; SELECT mempage FROM > 255 => WriteVM[loc,val]; > 253 => WriteMEMORY[val, loc]; ENDCASE => BEGIN s: CoreSegment ← GetCS[mempage]; (s.address + offset)↑ ← val; s.dirty ← TRUE; END; RETURN END; LongCopyREAD: PUBLIC PROCEDURE [ from: LONG POINTER, nwords: CARDINAL, to: LONG POINTER] = BEGIN i: CARDINAL; FOR i IN [0..nwords) DO (to+i)↑ ← LongREAD[from+i]; ENDLOOP; RETURN END; LongCopyWRITE: PUBLIC PROCEDURE [ from: LONG POINTER, nwords: CARDINAL, to: LONG POINTER] = BEGIN i: CARDINAL; FOR i IN [0..nwords) DO LongWRITE[to+i, (from+i)↑]; ENDLOOP; RETURN END; CheckPointer: PROCEDURE [p: LONG POINTER] = BEGIN OPEN InlineDefs; table: POINTER TO SwapperOps.SystemTable = data.ESV.tables; regions: POINTER TO SwapperOps.RegionTable ← DebugOps.ShortREAD[@table.regions]; index: CARDINAL ← HighHalf[p]; IF index > LAST[SegmentDefs.BankIndex] OR DebugOps.ShortREAD[@regions[LOOPHOLE[index]]] = NIL THEN ERROR InvalidAddress[p]; END; ReadVM: PROCEDURE [p: LONG POINTER] RETURNS [UNSPECIFIED] = BEGIN RBL: PROC [LONG POINTER] RETURNS [UNSPECIFIED] = MACHINE CODE BEGIN Mopcodes.zRBL, 0 END; CheckPointer[p]; RETURN[RBL[p]]; END; WriteVM: PROCEDURE [p: LONG POINTER, v: UNSPECIFIED] = BEGIN OPEN Mopcodes; WBL: PROC [UNSPECIFIED, LONG POINTER] = MACHINE CODE BEGIN zWBL, 0 END; CheckPointer[p]; WBL[v, p] END; -- initialization Files: PUBLIC PROCEDURE [fh: SegmentDefs.FileHandle] = BEGIN OPEN DiskDefs, SegmentDefs; run: POINTER TO DaListItem ← Storage.Node[SIZE[DaListItem]]; runStart: INTEGER; i: INTEGER ← 0; p: POINTER TO ARRAY [-1..256] OF vDA ← Storage.Node[258]; diskrequest: DiskRequest ← [ ca: Storage.Pages[1], fixedCA: TRUE, da: @p[0], fp: @fh.fp, firstPage: 0, lastPage: 255, action: ReadD, lastAction: ReadD, signalCheckError: FALSE, option: update[BFSDefs.GetNextDA]]; p[-1] ← fillinDA; InlineDefs.COPY[from: @p[-1], to: @p[0], nwords: 257]; p[0] ← fh.fp.leaderDA; [] ← BFSDefs.ActOnPages[LOOPHOLE[@diskrequest]]; Storage.FreePages[diskrequest.ca]; DAs ← run; run.link ← NIL; -- cross jump run.base ← p[runStart ← i]; DO WHILE i <= 255 AND p[i+1] = p[i]+1 DO i ← i + 1 ENDLOOP; run.count ← i - runStart + 1; IF i > 255 THEN EXIT; i ← i + 1; run.link ← Storage.Node[SIZE[DaListItem]]; run ← run.link; run.link ← NIL; run.base ← p[runStart ← i]; ENDLOOP; Storage.Free[p]; InitCoreCache[fh]; END; END...