-- File: ImageCache.Mesa by Bruce on July 8, 1980 8:41 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY AllocDefs USING [AddSwapStrategy, CantSwap, SwappingProcedure, SwapStrategy], AltoDefs USING [LogPageSize, PageNumber, PageSize], AltoFileDefs USING [eofDA, fillinDA, vDA], BFSDefs USING [ActOnPages, GetNextDA], DiskDefs USING [DiskRequest], ImageFileInfoDefs USING [], ImageFormat USING [FirstImageDataPage, ImageHeader, MapItem], InlineDefs USING [BITAND, BITSHIFT, COPY], SegmentDefs USING [ DeleteFileSegment, FileHandle, FileSegmentAddress, FileSegmentHandle, GetFileSegmentDA, LockFile, NewFileSegment, Read, SetFileSegmentDA, SwapIn, Unlock], Storage USING [Pages, FreePages]; ImageCache: PROGRAM IMPORTS AllocDefs, BFSDefs, InlineDefs, Storage, SegmentDefs EXPORTS ImageFileInfoDefs SHARES SegmentDefs = BEGIN -- User's core image management CoreSegmentObject: TYPE = RECORD [ segment: SegmentDefs.FileSegmentHandle, address: POINTER, lastused: CARDINAL, page: AltoDefs.PageNumber]; CoreSegment: TYPE = POINTER TO CoreSegmentObject; maxsegments: CARDINAL = 8; -- number of pages to keep in core CS: ARRAY [0..maxsegments) OF CoreSegmentObject; CurrentUseValue: CARDINAL; CoreFile: SegmentDefs.FileHandle; DAs: ARRAY [-1..256] OF AltoFileDefs.vDA; CacheSwap: AllocDefs.SwapStrategy _ AllocDefs.SwapStrategy[ link:, proc: AllocDefs.CantSwap]; PageMap: PACKED ARRAY [0..256) OF [0..256); InvalidPage: PUBLIC SIGNAL [page: AltoDefs.PageNumber] = CODE; InitImageCache: PROCEDURE [file: SegmentDefs.FileHandle] = BEGIN i: CARDINAL; CurrentUseValue _ 0; FOR i IN [0..maxsegments) DO CS[i].segment _ NIL ENDLOOP; CoreFile _ file; SegmentDefs.LockFile[CoreFile]; AllocDefs.AddSwapStrategy[@CacheSwap]; END; FlushCoreCache: PUBLIC AllocDefs.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.segment # NIL THEN BEGIN Unlock[cs.segment]; DeleteFileSegment[cs.segment]; cs.segment _ NIL; did _ TRUE; END; ENDLOOP; CurrentUseValue _ 0; RETURN[did] END; NewCoreSegment: PROCEDURE [p: AltoDefs.PageNumber, cs: CoreSegment] = BEGIN OPEN SegmentDefs; seg: FileSegmentHandle; seg _ NewFileSegment[CoreFile, PageMap[p], 1, Read]; SetFileSegmentDA[seg, DAs[p]]; SwapIn[seg]; DAs[p] _ GetFileSegmentDA[seg]; cs.segment _ seg; cs.address _ FileSegmentAddress[seg]; cs.page _ p; END; GetCS: PROCEDURE [p: AltoDefs.PageNumber] RETURNS [sp: CoreSegment] = BEGIN minUseVal: CARDINAL _ CurrentUseValue; minUseIndex: CARDINAL _ 0; i: CARDINAL; BEGIN FOR i IN [0..maxsegments) DO sp _ @CS[i]; IF sp.segment = NIL THEN GO TO newseg; IF sp.page = p 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; sp _ @CS[minUseIndex]; SegmentDefs.Unlock[sp.segment]; SegmentDefs.DeleteFileSegment[sp.segment]; sp.segment _ NIL; GO TO newseg; END ENDLOOP; EXITS newseg => BEGIN cso: CoreSegmentObject; NewCoreSegment[p, @cso]; FOR i IN [0..maxsegments) DO sp _ @CS[i]; IF sp.segment = NIL THEN BEGIN sp^ _ cso; EXIT END; REPEAT FINISHED => ERROR ENDLOOP; END; END; sp.lastused _ CurrentUseValue _ CurrentUseValue + 1; CacheSwap.proc _ FlushCoreCache; RETURN[sp]; END; READ: PUBLIC PROCEDURE [a: UNSPECIFIED] RETURNS [UNSPECIFIED] = BEGIN OPEN AltoDefs, InlineDefs; memory: POINTER = a; fp: PageNumber = SELECT BITSHIFT[ a, -LogPageSize] FROM IN [2..253] => BITSHIFT[a, -LogPageSize], 1 => 254, 0 => 255, ENDCASE => 0; IF fp = 0 THEN RETURN[memory^]; IF PageMap[fp] = 0 THEN SIGNAL InvalidPage[fp]; RETURN[(GetCS[fp].address + BITAND[a, PageSize - 1])^]; END; CopyRead: PUBLIC PROCEDURE [from, to: POINTER, nwords: CARDINAL] = BEGIN i: CARDINAL; FOR i IN [0..nwords) DO (to + i)^ _ READ[from + i]; ENDLOOP; RETURN END; InvalidImageFile: PUBLIC SIGNAL = CODE; -- initialization InitializeImageCache: PUBLIC PROCEDURE [seg: SegmentDefs.FileSegmentHandle] = BEGIN OPEN AltoFileDefs, DiskDefs, SegmentDefs; image: POINTER TO ImageFormat.ImageHeader; map: POINTER TO normal ImageFormat.MapItem; i, mapIndex: CARDINAL _ 0; page, count, imagePage: CARDINAL; p: POINTER; ImageDAs: ARRAY [-1..256] OF AltoFileDefs.vDA; diskrequest: DiskRequest; SwapIn[seg]; image _ FileSegmentAddress[seg]; IF image.prefix.type = checkfile THEN SIGNAL InvalidImageFile; diskrequest _ DiskRequest[ ca: Storage.Pages[1], fixedCA: TRUE, da: @ImageDAs[0], fp: @seg.file.fp, firstPage: 0, lastPage: 255, action: ReadD, lastAction: ReadD, signalCheckError: FALSE, option: update[BFSDefs.GetNextDA]]; p _ LOOPHOLE[@ImageDAs[0] - 1]; p^ _ fillinDA; InlineDefs.COPY[from: p, to: p + 1, nwords: 257]; ImageDAs[0] _ seg.file.fp.leaderDA; [] _ BFSDefs.ActOnPages[LOOPHOLE[@diskrequest]]; Storage.FreePages[diskrequest.ca]; map _ LOOPHOLE[@image.map[0]]; imagePage _ ImageFormat.FirstImageDataPage; FOR i IN [0..256) DO DAs[i] _ AltoFileDefs.eofDA; PageMap[i] _ 0; ENDLOOP; WHILE (map + mapIndex)^ # ImageFormat.MapItem[0, 0, normal[]] DO page _ (map + mapIndex)^.page; count _ (map + mapIndex)^.count; FOR i IN [0..count) DO DAs[page + i] _ ImageDAs[imagePage + i]; PageMap[page + i] _ imagePage + i; ENDLOOP; imagePage _ imagePage + count; mapIndex _ mapIndex + 1; ENDLOOP; Unlock[seg]; InitImageCache[seg.file]; END; END...