-- ExecStorage.mesa
-- Edited by Levin, September 9, 1980 5:17 PM
-- Edited by Brotz, December 24, 1981 2:44 PM
DIRECTORY
AltoDefs USING [PageSize],
FSPDefs USING [AddToNewZone, BlockSize, DestroyZone, FreeNode, MakeNewZone,
MakeNode, NodeHeader, NodeSize, NoRoomInZone, PruneZone, ZoneHeader,
ZoneOverhead, ZonePointer, ZoneTooSmall],
LaurelExecImpDefs USING [],
Mopcodes USING [zBLT],
SegmentDefs USING [DataSegmentAddress, DataSegmentHandle, DefaultMDSBase,
HardDown, MakeDataSegment, VMtoDataSegment],
Storage USING [],
SystemDefs USING [Even, FreePages, Quad, SegmentSize];
ExecStorage: PROGRAM
IMPORTS FSPDefs, SegmentDefs, realSystemDefs: SystemDefs
EXPORTS SystemDefs, Storage, LaurelExecImpDefs =
BEGIN
SegmentListRec: TYPE = RECORD [next: SegmentList, base: POINTER];
SegmentList: TYPE = POINTER TO SegmentListRec;
segmentList: SegmentList ← NIL;
UsedNodeSize: FSPDefs.BlockSize = SIZE[inuse FSPDefs.NodeHeader];
FreeNodeSize: FSPDefs.BlockSize = SIZE[free FSPDefs.NodeHeader];
ZoneHeaderSize: FSPDefs.BlockSize = SIZE[FSPDefs.ZoneHeader];
execHeap: FSPDefs.ZonePointer ← NIL;
useCount: CARDINAL ← 0;
LargeNode: CARDINAL = 150;
-- Interface for Laurel Executive
clientWords: PUBLIC CARDINAL;
StartExecStorage: PUBLIC PROCEDURE =
BEGIN
useCount ← useCount + 1;
END; -- of StartExecStorage --
FinishExecStorage: PUBLIC PROCEDURE =
BEGIN
IF useCount = 0 THEN ERROR;
useCount ← useCount - 1;
IF useCount > 0 THEN RETURN;
UNTIL segmentList = NIL DO
FreePages[segmentList.base];
ENDLOOP;
IF execHeap # NIL THEN {FSPDefs.DestroyZone[execHeap]; execHeap ← NIL};
END; -- of FinishExecStorage --
-- SystemDefs (Storage) Interface for Laurel Client BCDs
AllocatePages, AllocateResidentPages, Pages: PUBLIC PROCEDURE [npages: CARDINAL]
RETURNS [base: POINTER] =
BEGIN
OPEN SegmentDefs;
seg: DataSegmentHandle ← MakeDataSegment[DefaultMDSBase, npages, HardDown];
seg.type ← 89;
base ← DataSegmentAddress[seg];
AddSegmentToList[base];
END; -- of AllocatePages, AllocateResidentPages, Pages --
AllocateSegment, AllocateResidentSegment, Words: PUBLIC
PROCEDURE [nwords: CARDINAL] RETURNS [base: POINTER] =
BEGIN
RETURN[AllocatePages[PgsForWords[nwords]]];
END; -- of AllocateSegment, AllocateResidentSegment, Words --
FreePages, FreeSegment, FreeWords: PUBLIC PROCEDURE [base: POINTER] =
BEGIN
RemoveSegmentFromList[base];
realSystemDefs.FreePages[base];
END; -- of FreePages, FreeSegment, FreeWords --
AddSegmentToList: PRIVATE PROCEDURE [base: POINTER] =
BEGIN
sl: SegmentList ← AllocateHeapNode[SIZE[SegmentListRec]];
sl↑ ← SegmentListRec[next: segmentList, base: base];
segmentList ← sl;
END; -- of AddSegmentToList --
RemoveSegmentFromList: PRIVATE PROCEDURE [base: POINTER] =
BEGIN
sl: SegmentList ← segmentList;
slPrev: SegmentList ← NIL;
UNTIL sl = NIL DO
IF base = sl.base THEN
{IF slPrev = NIL THEN segmentList ← sl.next ELSE slPrev.next ← sl.next; RETURN};
slPrev ← sl;
sl ← sl.next;
ENDLOOP;
END; -- of RemoveSegmentFromList --
SegmentSize: PUBLIC PROCEDURE [base: POINTER] RETURNS [nwords: CARDINAL] =
BEGIN
RETURN[realSystemDefs.SegmentSize[base]];
END; -- of SegmentSize --
HeapZone: PUBLIC PROCEDURE RETURNS [FSPDefs.ZonePointer] =
BEGIN
IF execHeap = NIL THEN InitHeap[];
RETURN[execHeap];
END; -- of HeapZone --
PruneHeap, Prune: PUBLIC PROCEDURE RETURNS [BOOLEAN] =
BEGIN
RETURN[execHeap # NIL AND FSPDefs.PruneZone[execHeap]];
END; -- of PruneHeap, Prune --
Even: PUBLIC PROCEDURE [u: UNSPECIFIED] RETURNS [UNSPECIFIED] =
BEGIN
RETURN[realSystemDefs.Even[u]];
END; -- of Even --
Quad: PUBLIC PROCEDURE [u: UNSPECIFIED] RETURNS [UNSPECIFIED] =
BEGIN
RETURN[realSystemDefs.Quad[u]];
END; -- of Quad --
Node, AllocateHeapNode: PUBLIC PROC [nwords: CARDINAL] RETURNS [p: POINTER] =
BEGIN OPEN FSPDefs;
IF execHeap = NIL THEN InitHeap[];
IF INTEGER[nwords] < 0 THEN ERROR ZoneTooSmall[execHeap];
IF nwords + UsedNodeSize > LargeNode THEN
BEGIN
p ← Pages[PgsForWords[nwords + UsedNodeSize]];
p↑ ← NodeHeader[length: nwords + UsedNodeSize, extension: inuse[]];
clientWords ← clientWords + FSPDefs.NodeSize[p + 1];
RETURN[p + 1]
END;
p ← MakeNode[execHeap, nwords ! NoRoomInZone =>
{Expand[PgsForWords[nwords + ZoneOverhead + UsedNodeSize]]; RESUME}];
clientWords ← clientWords + FSPDefs.NodeSize[p];
END; -- of Node, AllocateHeapNode --
Expand: PUBLIC PROCEDURE [pages: CARDINAL] =
BEGIN
FSPDefs.AddToNewZone[z: execHeap, base: GetMorePages[pages],
length: pages*AltoDefs.PageSize, deallocate: realSystemDefs.FreePages];
END; -- of Expand --
GetMorePages: PROCEDURE [pages: CARDINAL] RETURNS [POINTER] =
BEGIN OPEN SegmentDefs;
seg: DataSegmentHandle ← MakeDataSegment[DefaultMDSBase, pages, HardDown];
seg.type ← 89;
RETURN[DataSegmentAddress[seg]];
END; -- of GetMorePages --
Free, FreeHeapNode: PUBLIC PROCEDURE [p: POINTER] =
BEGIN OPEN SegmentDefs, FSPDefs;
pp: POINTER;
IF p = NIL THEN RETURN;
clientWords ← clientWords - FSPDefs.NodeSize[p];
IF LOOPHOLE[(pp ← p - 1), POINTER TO inuse NodeHeader].length > LargeNode
AND DataSegmentAddress[VMtoDataSegment[pp]] = pp THEN
{FreePages[pp]; RETURN};
FreeNode[execHeap, p];
END; -- of Free, FreeHeapNode --
String, AllocateHeapString: PUBLIC PROC [nchars: CARDINAL] RETURNS [s: STRING] =
BEGIN
s ← AllocateHeapNode[WdsForString[nchars]];
s↑ ← StringBody[length: 0, maxlength: nchars, text:];
RETURN[s]
END; -- of String, AllocateHeapString --
PgsForWords: PRIVATE PROC [nwords: CARDINAL] RETURNS [CARDINAL] = INLINE
{RETURN[(nwords + AltoDefs.PageSize - 1) / AltoDefs.PageSize]};
WdsForString: PRIVATE PROC [nchars: CARDINAL] RETURNS [CARDINAL] = INLINE
{RETURN[2 + (nchars + 1) / 2]};
FreeString, FreeHeapString: PUBLIC PROCEDURE [s: STRING] = LOOPHOLE[Free];
CopyString: PUBLIC PROCEDURE [s: STRING, longer: CARDINAL ← 0] RETURNS [STRING] =
BEGIN
ns: STRING;
IF s = NIL THEN RETURN[IF longer = 0 THEN NIL ELSE String[longer]];
ns ← AllocateHeapString[s.length + longer];
CPY[from: @s.text, to: @ns.text, nwords: (s.length + 1)/2];
ns.length ← s.length;
RETURN[ns];
END; -- of CopyString --
ExpandString: PUBLIC PROCEDURE [s: POINTER TO STRING, longer: CARDINAL ← 0] =
BEGIN
ns: STRING;
IF s↑ = NIL THEN {IF longer # 0 THEN s↑ ← String[longer]; RETURN};
ns ← AllocateHeapString[s.maxlength + longer];
CPY[from: @s.text, to: @ns.text, nwords: (s.length + 1)/2];
ns.length ← s.length;
FreeHeapString[s↑];
s↑ ← ns;
END; -- of ExpandString --
CPY: PRIVATE PROCEDURE [from: POINTER, nwords: CARDINAL, to: POINTER] =
MACHINE CODE {Mopcodes.zBLT};
InitHeap: PUBLIC PROCEDURE =
BEGIN
IF useCount = 0 THEN ERROR;
execHeap ← FSPDefs.MakeNewZone
[GetMorePages[2], 2*AltoDefs.PageSize, realSystemDefs.FreePages];
END; -- of InitHeap --
END. -- of ExecStorage --