-- 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; }.