VMImpl.mesa
Copyright Ó 1988, 1990, 1991 by Xerox Corporation. All rights reserved.
Carl Hauser, October 19, 1988 11:38:40 am PDT
Spreitze, May 2, 1990 10:31 am PDT
Willie-s, July 30, 1991 5:52 pm PDT
Chauser, July 23, 1992 5:51 pm PDT
Michael Plass, August 31, 1992 11:55 am PDT
DIRECTORY
Basics USING [bytesPerWord, logBytesPerWord, BITAND, BITLSHIFT, BITRSHIFT],
VM USING [BytesForPages, FalseBool, Interval, logBytesPerPage, LogPageCount, logUnitsPerPage, NullInterval, nullInterval, PageCount, PageNumber, PageNumberForAddress, VMPartition, ZeroPageCount, ZeroPageNumber];
Size Parameterization
bytesPerPage:
PUBLIC
NAT = GetPageSize[];
logBytesPerPage: PUBLIC NAT = Log2[bytesPerPage];
wordsPerPage:
PUBLIC
NAT = bytesPerPage/Basics.bytesPerWord;
logWordsPerPage: PUBLIC NAT = logBytesPerPage - Basics.logBytesPerWord;
the unitsPerPage is needed for address calculations - be careful if unitsPerPage#bytesPerPage
unitsPerPage:
PUBLIC
NAT = bytesPerPage;
logUnitsPerPage: PUBLIC NAT = Log2[unitsPerPage];
Errors
AddressFault: PUBLIC ERROR [address: POINTER] ~ CODE;
WriteProtectFault: PUBLIC ERROR [address: POINTER] ~ CODE;
CantAllocate: PUBLIC ERROR [bestInterval: Interval] ~ CODE;
Public Procedures
AllocatedInterval:
TYPE ~
RECORD [
address: POINTER, -- Prevents collection of VM chunk.
interval: Interval
];
allocList: LIST OF AllocatedInterval ¬ NIL;
Allocate:
PUBLIC PROC [count: PageCount,
partition: VMPartition ¬ normalVM, subRange: NullInterval ¬ [0, 0],
start: ZeroPageNumber ¬ 0, alignment: LogPageCount ¬ 0, in64K: FalseBool ¬
FALSE]
RETURNS [interval: Interval] ~ {
byteCount: WORD ¬ LOOPHOLE[BytesForPages[count+1]];
align: WORD ¬ Power2[alignment+logWordsPerPage];
addr: POINTER ¬ NIL;
addr ¬ AlignedAlloc[--align,-- byteCount];
IF addr = NIL THEN ERROR CantAllocate[nullInterval];
interval.page ¬ PageNumberForAddress[LOOPHOLE[LOOPHOLE[addr, CARD]+(unitsPerPage-1)]];
interval.count ¬ count;
NoteInterval[addr, interval];
};
SimpleAllocate:
PUBLIC PROC [count: PageCount]
RETURNS [interval: Interval] ~ {
interval ¬ Allocate[count];
};
NoteInterval:
ENTRY
PROC [addr:
POINTER, interval: Interval] ~ {
allocList ¬ CONS[[addr, interval], allocList];
};
Free:
PUBLIC
ENTRY UNSAFE PROC [interval: Interval] ~ {
This implementation can only free an entire previously allocated interval.
MJS May 2, 1990: removed test on result 'cause valloc𡤏ree returns void.
MFP August 31, 1992: Added monitor; added test on full interval; fixed a bug in updating allocList.
lag: LIST OF AllocatedInterval ← NIL;
FOR l:
LIST
OF AllocatedInterval ← allocList, l.rest
WHILE l#
NIL
DO
IF l.first.interval = interval
THEN {
FreePreviouslyAllocatedBlock[l.first.address];
l.first.address ¬ NIL;
IF lag = NIL THEN allocList ¬ l.rest ELSE lag.rest ¬ l.rest;
RETURN
};
lag ¬ l;
ENDLOOP;
};
Touch:
PUBLIC PROC [interval: Interval] ~ {
should touch every page in the interval, but needn't
};