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