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