-- 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 --z20461(529)\f1