-- File: XDMemCache.Mesa -- Last edited by -- Bruce; August 27, 1980 1:41 PM -- Sandman; July 21, 1980 10:39 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 [], Inline USING [COPY, HighHalf, LongDivMod, LongMult, LongNumber], MachineDefs USING [eofDA, fillinDA, PageSize, 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]; XDMemCache: PROGRAM IMPORTS BFSDefs, DebugOps, Inline, 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 Inline, 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 PROCEDURE = BEGIN OPEN SegmentDefs; i: CARDINAL _ 0; cs: CoreSegment; FOR i IN [0..maxsegments) DO cs_@CS[i]; IF cs.inuse THEN FlushCS[cs]; ENDLOOP; CurrentUseValue_0; 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] _ Inline.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] _ Inline.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 Inline; 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 = BEGIN OPEN DiskDefs, SegmentDefs; fh: FileHandle _ data.debuggeeFH; 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; Inline.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...