-- RealMemoryImplDLion.mesa
-- Last edited by Luniewski, March 27, 1981 11:15 AM
DIRECTORY
DeviceCleanup USING [Await, Item, Reason],
DLionInputOutput USING [firstReservedPage, numberVirtualPages,
ReservedMemoryUse],
Environment USING [bitsPerWord, PageCount, PageNumber, wordsPerPage],
HeadStartChain USING [Start],
Inline USING [LongCOPY],
PageMap USING [Assoc, Flags, flagsClean, flagsVacant, GetF, RealPageNumber,
SetF, Value, valueVacant],
PrincOps USING [BytePC, ControlLink, EPRange, PrefixHandle],
PrincOpsRuntime USING [GFT],
RealMemory USING [],
Runtime USING [GlobalFrame],
RuntimeInternal USING [Codebase],
Space USING [Create, Delete, GetAttributes, GetHandle, Handle, LongPointer,
LongPointerFromPage, PageFromLongPointer, virtualMemory, VMPageNumber],
SpecialSpace USING [DonateDedicatedRealMemory];
RealMemoryImplDLion: MONITOR
IMPORTS DeviceCleanup, Inline, PageMap,
RemainingHeads: HeadStartChain, Runtime, RuntimeInternal, Space,
SpecialSpace
EXPORTS DLionInputOutput, HeadStartChain, RealMemory
SHARES PageMap =
BEGIN
maxDLionRealPages: CARDINAL = 768*4; -- "Fat" Dandelions can have up to 768K words
allocMap: PUBLIC DESCRIPTOR FOR ARRAY OF WORD ← DESCRIPTOR[allocMapArray];
allocMapArray:
ARRAY [0..
(maxDLionRealPages + Environment.bitsPerWord - 1)
/Environment.bitsPerWord) OF WORD;
-- initial state not important
currentReservedMemoryUse: DLionInputOutput.ReservedMemoryUse ← notBusy;
firstGermRealPage: PageMap.RealPageNumber ← maxDLionRealPages;
-- gets set to proper value by initialization code
lastLFPage: PageMap.RealPageNumber = 205;
-- 64 words per line * 808 lines + 4 pages of cursor bitmap
lastAvailReservedPage: PageMap.RealPageNumber;
ReservedMemoryHandle: PROCEDURE = {};
firstTime: BOOLEAN ← TRUE;
MoveToDisplayMemory: PUBLIC PROCEDURE
[proc: PROCEDURE] =
BEGIN OPEN PageMap;
-- Note on variable names:
-- page count names are prefixed with 'n
-- real page numbers are prefixed with 'r
-- virtual page numbers are prefixed with 'v
hSource: Space.Handle = Space.GetHandle[PageFromProc[LOOPHOLE[proc]]];
vSource: Environment.PageNumber = Space.VMPageNumber[hSource];
nSource: Environment.PageCount = Space.GetAttributes[hSource].size;
pSource: LONG POINTER = Space.LongPointerFromPage[vSource];
nBuffer: Environment.PageCount =
MIN[nSource, lastAvailReservedPage-lastLFPage];
hBuffer: Space.Handle;
pBuffer: LONG POINTER;
vBuffer: Environment.PageNumber;
rDest: RealPageNumber = (lastAvailReservedPage - nBuffer) + 1;
IF nBuffer = 0 THEN RETURN;
hBuffer ← Space.Create[nBuffer, Space.virtualMemory];
pBuffer ← Space.LongPointer[hBuffer];
vBuffer ← Space.PageFromLongPointer[pBuffer];
AssocBlock[
vPage: vBuffer, rPage: rDest, flags: flagsClean, count: nBuffer];
-- put display memory under buffer
Inline.LongCOPY[from: pSource, to: pBuffer,
nwords: nBuffer*Environment.wordsPerPage];
-- copy data to be moved into buffer (and into display rm)
FOR i: CARDINAL IN [0..nBuffer) DO -- swap mapping of source and buffer
tValue: Value;
[] ← SetF[vBuffer+i, valueVacant];
tValue ← GetF[vSource+i];
Assoc[page: vSource+i, value: [logSingleError: FALSE,
flags: tValue.flags, realPage: rDest+i]];
Assoc[vBuffer+i, [FALSE, flagsClean, tValue.realPage]];
ENDLOOP;
SpecialSpace.DonateDedicatedRealMemory[vBuffer, nBuffer];
-- free original rm
lastAvailReservedPage ← lastAvailReservedPage - nBuffer;
Space.Delete[hBuffer];
IF firstTime THEN
{firstTime ← FALSE; MoveToDisplayMemory[ReservedMemoryHandle]};
END;
AssocBlock: PROCEDURE
[vPage: Environment.PageNumber,
rPage: PageMap.RealPageNumber,
count: Environment.PageCount, flags: PageMap.Flags] =
BEGIN
FOR i: Environment.PageNumber IN [0..count) DO
PageMap.Assoc[vPage+i, [FALSE, flags, rPage+i]] ENDLOOP;
END;
PageFromProc: PROCEDURE [proc: procedure PrincOps.ControlLink]
RETURNS [code: Environment.PageNumber] =
-- Returns VM page number of procedure's code.
-- TEMP until function exported by RuntimeInternal (.Code[])!
BEGIN
codeBase: LONG PrincOps.PrefixHandle;
startPC: PrincOps.BytePC;
evi: CARDINAL;
codeBase ← RuntimeInternal.Codebase[Runtime.GlobalFrame[proc]];
evi ← PrincOpsRuntime.GFT[proc.gfi].epbias*PrincOps.EPRange + proc.ep;
startPC ← codeBase.entry[evi].initialpc;
RETURN[Space.PageFromLongPointer[codeBase + startPC]];
END;
DonateReservedMemory: PUBLIC PROCEDURE
[pagesToKeep: Environment.PageCount] =
BEGIN
firstRealPageFreed: PageMap.RealPageNumber =
DLionInputOutput.firstReservedPage + pagesToKeep;
space: Space.Handle;
vp: Environment.PageNumber;
space ← Space.Create[
size: (lastAvailReservedPage - firstRealPageFreed) + 1,
parent: Space.virtualMemory];
vp ← Space.VMPageNumber[space];
FOR p: PageMap.RealPageNumber
IN [firstRealPageFreed..lastAvailReservedPage]
DO PageMap.Assoc[vp, [FALSE, PageMap.flagsClean, p]]; vp ← vp + 1 ENDLOOP;
SpecialSpace.DonateDedicatedRealMemory[
Space.VMPageNumber[space], firstGermRealPage - firstRealPageFreed];
Space.Delete[space];
END;
InitializeCleanup: PROCEDURE =
BEGIN
item: DeviceCleanup.Item;
DO
reason: DeviceCleanup.Reason = DeviceCleanup.Await[@item];
IF reason#disconnect THEN LOOP;
FOR p: Environment.PageNumber
IN [0..DLionInputOutput.numberVirtualPages) DO
value: PageMap.Value = PageMap.GetF[p];
IF value.flags = PageMap.flagsVacant THEN LOOP;
IF value.realPage NOT IN
[DLionInputOutput.firstReservedPage..firstGermRealPage)
THEN LOOP;
PageMap.Assoc[p, PageMap.valueVacant];
ENDLOOP;
ENDLOOP;
END;
MemoryConfigurationError: ERROR = CODE;
SetReservedMemoryUse: PUBLIC PROC [
use: DLionInputOutput.ReservedMemoryUse,
pagesNeeded: Environment.PageCount] =
BEGIN
availableReservedMemory: Environment.PageCount =
(lastAvailReservedPage-DLionInputOutput.firstReservedPage) + 1;
IF (SELECT use FROM
notBusy => FALSE,
Raven =>
currentReservedMemoryUse=Display
OR pagesNeeded > availableReservedMemory,
Display =>
currentReservedMemoryUse=Raven
OR lastAvailReservedPage<lastLFPage,
ENDCASE => TRUE) THEN ERROR MemoryConfigurationError;
currentReservedMemoryUse ← use
END;
Start: PUBLIC PROCEDURE =
-- Initialize cleanup proc
{InitializeCleanup[]; RemainingHeads.Start[]};
-- This procedure is called before Mesa runtime is initialized, so we must
-- leave the cleanup proc initialization to be done in Start, above
Initialize: PUBLIC PROCEDURE =
BEGIN
-- scan virtual memory looking for lowest page mapped - we then use this
-- page as the top of the area to use for "resident cool" code
FOR i: CARDINAL IN [0..DLionInputOutput.numberVirtualPages) DO
tValue: PageMap.Value = PageMap.GetF[i];
IF tValue.flags#PageMap.flagsVacant THEN
firstGermRealPage ← MIN[tValue.realPage, firstGermRealPage];
ENDLOOP;
lastAvailReservedPage ← firstGermRealPage - 1;
END;
END...
LOG
Time: January 15, 1981 3:13 PM By: Gobbel
Created file
Time: March 16, 1981 11:08 AM By: Luniewski
maxDLionRealPages = 768*4 for "Fat" Dandelions
Time: March 27, 1981 11:14 AM By: Luniewski
Only swap nBuffer pages worth of mapping in MoveToDisplayMemory