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