-- Copyright (C) 1981, 1982, 1984, 1985 by Xerox Corporation. All rights reserved. -- VMStorageMgr.mesa, HGM, 17-Sep-85 2:27:30 -- This module is just barely used, HGM, 16-Sep-85 22:20:19 -- 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], Space USING [ Allocate, Deallocate, Interval, LongPointerFromPage, MapAt, PageCount, PageFromLongPointer, PageOffset, UnmapAt, virtualMemory, wordsPerPage], VMPrivate USING [maxPageIndex, PageIndex], VMStorage USING []; VMStorageMgr: MONITOR IMPORTS Space EXPORTS VMStorage = BEGIN -- Types and Related Constants -- PageIndex: TYPE = VMPrivate.PageIndex; AllocArray: TYPE = PACKED ARRAY PageIndex OF BOOLEAN; Page: TYPE = ARRAY [0..Space.wordsPerPage) OF WORD; -- Constants and Global Variables -- inUse: BOOLEAN = TRUE; free: BOOLEAN = FALSE; freePageCount: Space.PageCount ← VMPrivate.maxPageIndex; allocMap: AllocArray ← ALL[free]; rover: PageIndex ← 0; poolSpace: Space.Interval; storagePool: LONG POINTER TO ARRAY PageIndex OF Page; -- Miscellaneous Declarations -- AllocMapBug: ERROR = CODE; NoMemory: ERROR = CODE; PageAlreadyFree: ERROR = CODE; UserConfused: ERROR = CODE; -- Page-Level Allocator -- AllocatePage: PUBLIC ENTRY PROCEDURE RETURNS [LONG POINTER, VMPrivate.PageIndex] = -- allocates a single page of main memory, returning its address. BEGIN Inc: PROCEDURE [bit: PageIndex] RETURNS [PageIndex] = INLINE { RETURN[(bit + 1) MOD VMPrivate.maxPageIndex]}; IF freePageCount = 0 THEN ERROR NoMemory; FOR i: PageIndex ← 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], rover]; END; FreePage: PUBLIC ENTRY PROCEDURE [p: LONG POINTER, bit: VMPrivate.PageIndex] = BEGIN IF p # @storagePool[rover] THEN ERROR UserConfused; IF allocMap[bit] # inUse THEN ERROR PageAlreadyFree; allocMap[bit] ← free; freePageCount ← freePageCount + 1; END; InitializeStorage: PUBLIC PROCEDURE RETURNS [LONG POINTER] = -- initializes the main memory allocator. BEGIN InitializePageLevel[]; RETURN[poolSpace.pointer] END; FinalizeStorage: PUBLIC PROCEDURE = -- finalizes the main memory allocator. BEGIN FinalizePageLevel[]; END; -- Internal Procedures -- -- Page-Level Allocator -- InitializePageLevel: PROCEDURE = BEGIN firstPage: Environment.PageNumber; poolSpace ← Space.Allocate[count: VMPrivate.maxPageIndex, within: Space.virtualMemory]; storagePool ← poolSpace.pointer; firstPage ← Space.PageFromLongPointer[poolSpace.pointer]; FOR p: Space.PageOffset IN [0..VMPrivate.maxPageIndex) 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..VMPrivate.maxPageIndex) DO [] ← Space.UnmapAt[pointer: Space.LongPointerFromPage[firstPage + p]]; ENDLOOP; Space.Deallocate[poolSpace]; END; END.