-- File: VMPrivate.mesa
-- Last edited by Wobber: 2-Nov-82 12:02:41
-- Last edited by Levin: 12-Jul-82 14:57:02
DIRECTORY
Environment USING [maxPagesInMDS],
FileDefs USING [FileHandle, FSInstance, Operations, PageNumber],
VMDefs USING [
CacheIndex, FileHandle, FileSystemType, OpenOptions, Page, PageAddress,
PageByteIndex, PageNumber, Position, Problem];
VMPrivate: DEFINITIONS =
BEGIN
-- Types and Related Constants --
FileSystem: TYPE = POINTER TO FSInstance;
FSInstance: TYPE = RECORD [
ops: FileDefs.Operations, instance: FileDefs.FSInstance];
ObjectType: TYPE = {page, file};
Object: TYPE = RECORD [
body: SELECT tag: ObjectType FROM
file => [
seal: VMFileSeal,
useCount: CacheIndex,
link: FileHandle,
fh: FileDefs.FileHandle,
fs: FileSystem,
cachePages: CacheIndex,
options: VMDefs.OpenOptions,
altoFile: BOOLEAN,
openCount: [0..37B]], -- pick a convenient size based on size of other fields
page => [
state: PageState,
age: LRUInfo,
dirty: BOOLEAN,
recordNextVda: BOOLEAN,
errorStatus: VMDefs.Problem,
buffer: MDSPageNumber,
pageStable: CONDITION,
file: FileHandle,
beingTaken: BOOLEAN,
page: FileDefs.PageNumber,
hashLink: CacheIndex,
useCount: [0..377B] -- pick a convenient size based on size of other fields
],
ENDCASE];
FileObject: TYPE = file Object;
PageObject: TYPE = page Object;
ObjectHandle: TYPE = POINTER TO Object;
FileHandle: TYPE = POINTER TO FileObject;
PageHandle: TYPE = POINTER TO PageObject;
-- File Operations --
fsOps: ARRAY VMDefs.FileSystemType OF FileDefs.Operations;
Writable: PROCEDURE [file: FileHandle] RETURNS [BOOLEAN] = INLINE {
RETURN[file.options ~= oldReadOnly]};
-- Cache Management --
-- Types and Related Constants --
CacheIndex: TYPE = VMDefs.CacheIndex;
nilCacheIndex: CacheIndex = 255;
HandleTable: TYPE = RECORD [SEQUENCE nHandles: CacheIndex OF PageHandle];
LRUInfo: TYPE = {old, new};
PageByteCount: TYPE =
[FIRST[VMDefs.PageByteIndex] + 1..LAST[VMDefs.PageByteIndex] + 1];
-- Procedures and Signals --
InitializeVMCache: PROCEDURE [min, max: CacheIndex];
-- establishes initial invariant for VMCache.
FinalizeVMCache: PROCEDURE;
-- cleans up VMCache.
InitializeVMCacheMgr: PROCEDURE [
h: POINTER TO HandleTable, min, max: CacheIndex];
-- establishes initial invariant for VMCacheMon.
FinalizeVMCacheMgr: PROCEDURE;
-- cleans up VMCacheMon.
AcquireCache: PROCEDURE;
-- waits for the cache to become stable, marks it unstable, and returns.
ReleaseCache: PROCEDURE;
-- resets the cache to a stable state (and awakens anyone waiting for it).
AllocateCacheIndex: PROCEDURE RETURNS [CacheIndex];
-- allocates a slot in the cache and returns its CacheIndex. This index will
-- correspond to an allocated page object with page.state = unstable,
-- page.useCount = 0, page.buffer ~= nilMDSPage, and page.pageStable initialized,
-- but whose remaining fields are undefined.
IndexToHandle: PROCEDURE [index: CacheIndex] RETURNS [PageHandle];
-- maps a CacheIndex to the PageHandle for the corresponding object.
LookupInHashTable: PROCEDURE [addr: VMDefs.PageAddress]
RETURNS [index: CacheIndex];
-- looks up the given address to discover whether there exists a corresponding
-- page already in the cache. If so, its CacheIndex is returned, if not,
-- nilCacheIndex is returned.
EnterInHashTable: PROCEDURE [page: PageHandle];
-- enters the given page into the hash table.
EnterInPageTable: PROCEDURE [page: MDSPageNumber, index: CacheIndex];
-- establishes a correspondance between the (MDS) 'page' and slot 'index' in
-- the cache.
RemovePageFromTables: PROCEDURE [page: PageHandle];
-- eliminates 'page' from the mapping tables, and disassociates it from its file.
EnumerateCachePagesInFile: PROCEDURE [
file: VMDefs.FileHandle,
proc: PROCEDURE [page: PageHandle] RETURNS [found, unmap: BOOLEAN]]
RETURNS [BOOLEAN];
-- enumerates all cache slots containing pages belonging to 'file'. If 'proc'
-- returns 'unmap' = TRUE, RemovePageFromTables will be called (providing that
-- there are no other users of the page. If 'found' = TRUE, the enumeration
-- terminates. Note: This procedure supplies its own cache mutual exclusion.
-- Page Management --
-- Types and Related Constants --
MDSPageNumber: TYPE = [0..Environment.maxPagesInMDS);
nilMDSPage: MDSPageNumber = 0;
PageState: TYPE = {stable, unstable};
PageByte: TYPE = MACHINE DEPENDENT RECORD [p: MDSPageNumber, b: [0..255]];
WaitReason: TYPE = {reading, writing};
-- Procedures and Signals --
InitializeVMPageMgr: PROCEDURE;
-- establishes initial invariant for VMPageMon.
FinalizeVMPageMgr: PROCEDURE;
-- cleans up VMPageMon.
AcquirePage: PROCEDURE [page: PageHandle];
-- waits for 'page' to become stable, marks it unstable, and returns.
ReleasePage: PROCEDURE [page: PageHandle];
-- resets 'page' to a stable state (and awakens anyone waiting for it).
WaitUntilStable: PROCEDURE [page: PageHandle, why: WaitReason]
RETURNS [PageState];
-- waits for the argument page to become stable, potentially reporting transmission
-- errors. If the return value is 'stable', 'page' is stable and the previous
-- transfer completed successfully. If the return value is 'unstable', 'page' is
-- unstable (i.e., an implicit AcquirePage has been done) and the previous transfer
-- was never started (i.e., the DiskIODefs.CompletionStatus was 'neverStarted'). If
-- the previous transfer had a permanent transmission error, either
-- VMDefs.CantReadBackingStore (if why = reading) or VMDefs.CantWriteBackingStore
-- (if why = writing) is raised.
ValidatePageAddress: PROCEDURE [page: PageHandle]
RETURNS [extending: BOOLEAN, newLength: VMDefs.Position];
-- ensures that page.addr is reasonable for page.file.
-- I/O Management --
InitializeVMIO: PROCEDURE;
-- initializes the I/O handling routines.
FinalizeVMIO: PROCEDURE;
-- finalizes the I/O handling routines.
WritePageToFS: PROCEDURE [page: PageHandle, wait: BOOLEAN];
-- initiates a write to the file system of 'page'. page.state is assumed to be
-- unstable and remains so while the transfer is underway. If 'wait' is TRUE,
-- WritePageToFS will wait until the write operation completes before returning,
-- at which time the page will be placed in the 'stable' state. If 'wait' if FALSE,
-- WritePageToFS returns immediately after initiating the operation. The page is
-- marked clean (i.e., page.dirty becomes FALSE) when the write completes
-- successfully.
-- File Manipulation --
-- Types and Related Constants --
VMFileSeal: TYPE = [0..77B];
openSeal: VMFileSeal = 51B;
underwaySeal: VMFileSeal = 35B;
closedSeal: VMFileSeal = 26B;
-- Procedures and Signals --
InitializeVMFile: PROCEDURE [maxCachePages: CacheIndex];
-- establishes initial invariant for VMFile.
FinalizeVMFile: PROCEDURE;
-- cleans up VMFile.
ValidateFile: PROCEDURE [file: VMDefs.FileHandle] = INLINE
-- ensures that 'file' is a plausible file handle.
{IF LOOPHOLE[file, FileHandle].seal ~= openSeal THEN ERROR InvalidFile};
ValidatePageNumber: PROCEDURE [page: VMDefs.PageNumber] = INLINE
-- ensures that 'page' is a plausible page number.
{IF CARDINAL[page] > 77777B THEN ERROR InvalidPageNumber};
InvalidFile: ERROR;
-- raised by ValidateFile.
InvalidPageNumber: ERROR;
-- raised by ValidatePageNumber
-- Miscellaneous Procedures and Signals --
AddressToHandle: PROCEDURE [address: VMDefs.Page] RETURNS [PageHandle];
-- maps an (MDS) address to the PageHandle for the corresponding object.
HandleToAddress: PROCEDURE [page: PageHandle] RETURNS [VMDefs.Page];
-- maps a PageHandle to the (MDS) address of its corresponding buffer.
AddressToMDSPage: PROCEDURE [address: POINTER] RETURNS [MDSPageNumber] = INLINE
-- maps an (MDS) address to the corresponding MDSPageNumber.
{RETURN[LOOPHOLE[address, PageByte].p]};
MDSPageToAddress: PROCEDURE [p: MDSPageNumber] RETURNS [POINTER] = INLINE
-- maps a MDSPageNumber to the corresponding (MDS) address.
{RETURN[LOOPHOLE[PageByte[p: p, b: 0]]]};
loggingEnabled: BOOLEAN;
-- indicates whether statistics logging is enabled.
clobberCatcherEnabled: BOOLEAN;
-- indicates whether hardware write-protect is to be used to detect clobbers.
WriteEnable: PROCEDURE [page: MDSPageNumber];
-- clears write-protection on the indicated page.
WriteProtect: PROCEDURE [page: MDSPageNumber];
-- sets write-protection on the indicated page.
END.