-- File: VMStorageMgr.mesa
-- Last edited by
-- HGM: 13-Nov-84 2:58:23, Fix Warnings from poolPages
-- Gobbel: 30-Sep-81 13:11:50
-- M. Johnson: 11-Jan-82 14:15:32
-- Hankins: 25-Jul-84 12:20:04 Klamath update (space rework)
DIRECTORY
Environment USING [PageNumber],
File USING [nullFile],
Heap USING [CreateMDS, DeleteMDS],
Space USING [
Allocate, Deallocate, Interval, LongPointerFromPage, MapAt, MDS, PageCount,
PageFromLongPointer, PageOffset, Pointer, UnmapAt, wordsPerPage],
VMStorage USING [];
VMStorageMgr: MONITOR
IMPORTS Heap, Space --VMSpecial--
EXPORTS VMStorage =
BEGIN
-- Types and Related Constants --
BitIndex: TYPE = CARDINAL [0..4096);
-- (restriction of current implementation)
AllocArray: TYPE = PACKED ARRAY [0..poolPages) OF BOOLEAN;
Page: TYPE = ARRAY [0..Space.wordsPerPage) OF WORD;
-- Constants and Global Variables --
inUse: BOOLEAN = TRUE;
free: BOOLEAN = FALSE;
poolPages: CARDINAL = 50;
freePageCount: Space.PageCount ← poolPages;
allocMap: AllocArray ← ALL[free];
rover: BitIndex ← 0;
longTermSize: Space.PageCount = 2;
shortTermSize: Space.PageCount = 2;
poolSpace: Space.Interval;
storagePool: POINTER TO ARRAY [0..poolPages) OF Page;
-- Miscellaneous Declarations --
AllocMapBug: ERROR = CODE;
NoMemory: ERROR = CODE;
PageAlreadyFree: ERROR = CODE;
-- Procedures and Variables Exported to VMStorage --
-- Node-Level Allocator --
longTerm, shortTerm: PUBLIC MDSZone;
-- Page-Level Allocator --
AllocatePage: PUBLIC ENTRY PROCEDURE RETURNS [POINTER] =
-- allocates a single page of main memory, returning its address.
BEGIN
Inc: PROCEDURE [bit: BitIndex] RETURNS [BitIndex] = INLINE {
RETURN[(bit + 1) MOD poolPages]};
IF freePageCount = 0 THEN ERROR NoMemory;
FOR i: BitIndex ← Inc[rover], Inc[i] UNTIL i = rover DO
IF allocMap[i] = free THEN {allocMap[i] ← inUse; rover ← i; EXIT};
REPEAT FINISHED => ERROR AllocMapBug;
ENDLOOP;
freePageCount ← freePageCount - 1;
RETURN[@storagePool[rover]];
END;
FreePage: PUBLIC ENTRY PROCEDURE [p: POINTER] =
-- releases the single page beginning at 'p'.
BEGIN
bit: BitIndex = LOOPHOLE[p - storagePool];
IF allocMap[bit] # inUse THEN ERROR PageAlreadyFree;
allocMap[bit] ← free;
freePageCount ← freePageCount + 1;
END;
InitializeStorage: PUBLIC PROCEDURE =
-- initializes the main memory allocator.
BEGIN InitializePageLevel[]; InitializeNodeLevel[]; END;
FinalizeStorage: PUBLIC PROCEDURE =
-- finalizes the main memory allocator.
BEGIN FinalizeNodeLevel[]; FinalizePageLevel[]; END;
-- Internal Procedures --
-- Node-Level Allocator --
InitializeNodeLevel: PROCEDURE =
BEGIN
longTerm ← Heap.CreateMDS[initial: longTermSize];
shortTerm ← Heap.CreateMDS[initial: shortTermSize];
END;
FinalizeNodeLevel: PROCEDURE =
BEGIN Heap.DeleteMDS[longTerm]; Heap.DeleteMDS[shortTerm]; END;
-- Page-Level Allocator --
InitializePageLevel: PROCEDURE =
BEGIN
firstPage: Environment.PageNumber;
poolSpace ← Space.Allocate[count: poolPages, within: Space.MDS[]];
storagePool ← Space.Pointer[poolSpace.pointer];
firstPage ← Space.PageFromLongPointer[poolSpace.pointer];
FOR p: Space.PageOffset IN [0..poolPages) DO
[] ← Space.MapAt[
at: [pointer: Space.LongPointerFromPage[firstPage + p], count: 1],
window: [file: File.nullFile, base: 0, count: 1], class: data];
ENDLOOP;
END;
FinalizePageLevel: PROCEDURE =
BEGIN
firstPage: Environment.PageNumber ← Space.PageFromLongPointer[
poolSpace.pointer];
FOR p: Space.PageOffset IN [0..poolPages) DO
[] ← Space.UnmapAt[pointer: Space.LongPointerFromPage[firstPage + p]];
ENDLOOP;
Space.Deallocate[poolSpace];
END;
END.