-- IntVM.mesa -- Derived from IntVM -- Last changed by MN, 3-Aug-81 17:24:04 -- Virtual memory is mapped onto a file, using the Pilot Space machinery. -- The size of the file is fixed at the time the VM is started. -- VM address 0 maps onto the first word of page 2 (counting from 0) of the -- file, because page 0 is reserved for the leader page, and page 1 is used -- by the VM package for restart information. A simple marching allocator -- is provided, but it is logically separate from the VM package itself -- (i.e. the first command can be GetWordVM[...]). DIRECTORY IntVMDefs USING [VMBase, VMAddr], DCSFileTypes USING [tLeaderPage], Directory USING [CreateFile, Error, Lookup], File USING [Capability, Error, GetAttributes, GetSize, nullCapability, PageCount, read, write], Inline USING [LowHalf], Space USING [Create, CreateUniformSwapUnits, Delete, Handle, LongPointer, Map, nullHandle, Unmap, virtualMemory, wordsPerPage], Transaction USING [Begin, Commit, Handle, nullHandle]; IntVM: PROGRAM IMPORTS Directory, File, Inline, Space, Transaction EXPORTS IntVMDefs = { OPEN IntVMDefs; --*** GLOBALS *** vmpages: CARDINAL; -- number of pages available in VM maxWords: LONG CARDINAL; -- maximum number of words in VM minFileSize: File.PageCount = 12; -- don't allow VM file smaller than this maxFileSize: File.PageCount = 4002; -- don't allow VM file larger than this -- Paging file vmfile: File.Capability ← File.nullCapability; vmspace: Space.Handle ← Space.nullHandle; vmtrans: Transaction.Handle ← Transaction.nullHandle; vmbase: PUBLIC VMBase ← NIL; vmPassword: CARDINAL = 48249; -- a more-or-less random number -- Allocation info AllocInfo: TYPE = MACHINE DEPENDENT RECORD[ password: CARDINAL, words: LONG CARDINAL, offset: CARDINAL]; alloc: LONG POINTER TO AllocInfo ← NIL; --*** PROCEDURES *** OpenVMFile: PROC[name: STRING, nPages: CARDINAL] RETURNS[file: File.Capability, pages: CARDINAL, old: BOOLEAN] = { ENABLE { File.Error => GOTO Punt; Directory.Error => GOTO Punt; }; old ← TRUE; file ← Directory.Lookup[fileName: name, permissions: File.read+File.write !Directory.Error => SELECT type FROM fileNotFound => { old ← FALSE; CONTINUE }; ENDCASE]; IF old THEN { size: File.PageCount ← File.GetSize[file]; IF size IN[minFileSize..maxFileSize] THEN pages ← Inline.LowHalf[size]-2 ELSE GOTO Punt; IF File.GetAttributes[file].type#DCSFileTypes.tLeaderPage THEN GOTO Punt; } ELSE file ← Directory.CreateFile[fileName: name, fileType: DCSFileTypes.tLeaderPage, size: (pages ← nPages)+2]; RETURN[file,pages,old]; EXITS Punt => ERROR VMFileProblem }; InitVM: PUBLIC PROCEDURE RETURNS [BOOLEAN] = { filename: STRING ← "IntScratch$"; nPages: CARDINAL ← 4000; restarted: BOOLEAN; -- Restart VM to page from file filename, not to exceed nPages pages [vmfile,vmpages,restarted] ← OpenVMFile[filename,nPages]; vmspace ← Space.Create[size: vmpages+1, parent: Space.virtualMemory]; Space.CreateUniformSwapUnits[size: 1, parent: vmspace]; vmtrans ← Transaction.Begin[]; Space.Map[space: vmspace, window: [file: vmfile, base: 1], transaction: vmtrans]; alloc ← Space.LongPointer[vmspace]; -- first data page holds allocation info vmbase ← alloc + Space.wordsPerPage; maxWords ← LONG[vmpages]*Space.wordsPerPage; -- IF restarted THEN { -- IF alloc.password#vmPassword THEN ERROR VMFileProblem; -- IF alloc.words > maxWords THEN ERROR VMFull; -- } -- ELSE { alloc.password ← vmPassword; alloc.words ← 0; alloc.offset ← 0; -- }; RETURN[TRUE]; }; FinishVM: PUBLIC PROCEDURE RETURNS [BOOLEAN] = { -- Write up page buffers and deallocate them vmbase ← NIL; alloc ← NIL; Space.Unmap[vmspace]; Transaction.Commit[vmtrans]; vmtrans ← Transaction.nullHandle; Space.Delete[vmspace]; vmspace ← Space.nullHandle; RETURN[TRUE]; }; AllocateBlock: PUBLIC PROCEDURE [size: CARDINAL] RETURNS [VMAddr] = { -- Increment allocation pointer by length words -- Generates VMFull: location: VMAddr; IF alloc.offset > 0 THEN { alloc.words ← alloc.words + 1; alloc.offset ← 0 }; location ← LOOPHOLE[alloc.words]; alloc.words ← alloc.words + size; IF alloc.words > maxWords THEN ERROR VMFull; RETURN[location]; }; VMBadPointer: PUBLIC ERROR = CODE; VMFull: PUBLIC ERROR = CODE; VMFileProblem: PUBLIC ERROR = CODE; }.