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