<> <> <> <> DIRECTORY BcdOps USING [MTHandle], CPSwapDefs USING [SwapInfo], Environment USING [Byte, wordsPerPage], MB USING [Alloc, AllocFault, BHandle, EnumerateNoTrapModules, Handle, WartFrame], MBOut USING [Char, CR, Decimal, Line, Number, Text], MBStorage USING [PagesForWords], MBVM USING [ AllocData, AllocMDSData, Base, CopyRead, CopyWrite, DataSeg, LongCopyWrite, LongPointerFromSeg, LongWrite, MDS, PointerFromSeg, Read, Write], PrincOps USING [ AV, ControlLink, FrameCodeBase, FrameSizeIndex, FrameVec, GFTIndex, GlobalFrame, GlobalFrameHandle, LargeReturnSlot, MainBodyIndex, SpecialReturnSlot], PrincOpsRuntime USING [GFT, GFTItem], PSB USING [PDABase, Priority, ProcessDataArea, ProcessStateBlock], RuntimeInternal USING [MakeFsi], SDDefs USING [SD, sGFTLength], StartList USING [StateVectorCounts], Time USING [Packed]; MBMain: PROGRAM IMPORTS MB, MBOut, MBStorage, MBVM, RuntimeInternal EXPORTS MB = BEGIN OPEN PrincOps; BYTE: TYPE = Environment.Byte; AVPage: CARDINAL = LOOPHOLE[PrincOps.AV, CARDINAL]/Environment.wordsPerPage; GFTPage: CARDINAL = LOOPHOLE[PrincOpsRuntime.GFT, CARDINAL]/Environment.wordsPerPage; data: MB.Handle _ NIL; values: LONG POINTER TO Values _ NIL; Values: TYPE = RECORD [ frameWeights: PACKED ARRAY FrameSizeIndex OF BYTE _ ALL[LAST[BYTE]], fsiChain: PACKED ARRAY FrameSizeIndex OF BYTE _ ALL[LAST[BYTE]]]; DefaultValues: Values = [ frameWeights: [9,13,9,8,7,6,4,2,2,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0], fsiChain: [1,2,3,4,5,6,7,8,9,10,11,0,13,14,15,16,17,18,0,0,0,0,0,0,0,0,0,0,0,0]]; heapFrames, extraFrames: FrameCounts _ NIL; FrameCounts: TYPE = LONG POINTER TO FrameCountTable; FrameCountTable: TYPE = ARRAY FrameSizeIndex OF CARDINAL; InitMain: PUBLIC PROC [h: MB.Handle] = { data _ h; values _ data.zone.NEW[Values _ []]; heapFrames _ data.zone.NEW[FrameCountTable _ ALL[0]]; extraFrames _ data.zone.NEW[FrameCountTable _ ALL[0]]; FOR i: PSB.Priority IN PSB.Priority DO h.stateVectorCounts[i] _ LAST[CARDINAL]; ENDLOOP; h.nProcesses _ LAST[CARDINAL]; h.framePages _ LAST[CARDINAL]; h.pdaPages _ LAST[CARDINAL]; h.svSize _ LAST[CARDINAL]; h.gftLength _ LAST[CARDINAL]; h.mdsBase _ LAST[CARDINAL]; h.codeBase _ LAST[CARDINAL]; }; FinishMain: PUBLIC PROC = { IF values # NIL THEN data.zone.FREE[@values]; IF heapFrames # NIL THEN data.zone.FREE[@heapFrames]; IF extraFrames # NIL THEN data.zone.FREE[@extraFrames]; data _ NIL; }; <> InitMemory: PUBLIC PROC = { AssignDefaults[]; IF ~data.germ THEN {ReserveSelectedPages[]; InitPDA[]}; InitializeMDS[]; AllocateLocalFrames[]; }; AssignDefaults: PROC = { i: CARDINAL; FOR i IN PSB.Priority DO IF data.stateVectorCounts[i] = LAST[CARDINAL] THEN data.stateVectorCounts[i] _ SimpleDefaults.stateVectorCounts[i]; ENDLOOP; FOR i IN FrameSizeIndex DO IF values.frameWeights[i] = LAST[BYTE] THEN values.frameWeights[i] _ DefaultValues.frameWeights[i]; IF values.fsiChain[i] = LAST[BYTE] THEN values.fsiChain[i] _ DefaultValues.fsiChain[i]; ENDLOOP; IF data.gftLength = LAST[CARDINAL] THEN data.gftLength _ SimpleDefaults.gftLength; IF data.mdsBase = LAST[CARDINAL] THEN data.mdsBase _ SimpleDefaults.mdsBase; IF data.codeBase = LAST[CARDINAL] THEN data.codeBase _ SimpleDefaults.codeBase; IF data.pdaPages = LAST[CARDINAL] THEN data.pdaPages _ SimpleDefaults.pdaPages; IF data.nProcesses = LAST[CARDINAL] THEN data.nProcesses _ SimpleDefaults.nProcesses; IF data.framePages = LAST[CARDINAL] THEN data.framePages _ SimpleDefaults.framePages; }; ReserveSelectedPages: PROC = { seg: MBVM.DataSeg; seg _ MBVM.AllocData[base: 1, pages: 1]; SetReservedSegBits[seg]; seg _ MBVM.AllocData[base: 376B, pages: 1]; SetReservedSegBits[seg]; seg _ MBVM.AllocData[base: 377B, pages: 1]; SetReservedSegBits[seg]; }; SetReservedSegBits: PROC [s: MBVM.DataSeg] = { s.info _ [FALSE, resident]; s.bootLoaded _ TRUE; }; InitPDA: PROC = { seg: MBVM.DataSeg; pda: PSB.PDABase; i: CARDINAL; words: CARDINAL _ 0; FOR i IN PSB.Priority DO words _ words + data.stateVectorCounts[i]*data.svSize; ENDLOOP; data.pdaPages _ MAX[ MBStorage.PagesForWords[ data.nProcesses*(SIZE[PSB.ProcessStateBlock]+1) + words + SIZE[PSB.ProcessDataArea]], data.pdaPages ]; seg _ MBVM.AllocData[base: 256, pages: data.pdaPages, dir: up]; SetReservedSegBits[seg]; pda _ MBVM.LongPointerFromSeg[seg]; FOR i IN [0..data.pdaPages*Environment.wordsPerPage) DO MBVM.LongWrite[pda+i, 0]; ENDLOOP; <> MBVM.LongCopyWrite[ from: @data.buildTime, to: @LOOPHOLE[@pda.available, LONG POINTER TO CPSwapDefs.SwapInfo].availableB, nwords: SIZE[Time.Packed] ]; }; InitializeMDS: PROC = { gftPages: CARDINAL; seg: MBVM.DataSeg; p: POINTER; <> p _ PrincOps.AV; SetReservedSegBits[seg _ MBVM.AllocMDSData[base: AVPage, pages: 1]]; FOR i: CARDINAL IN [0..Environment.wordsPerPage) DO MBVM.Write[p+i, 0] ENDLOOP; InitAV[p]; <> gftPages _ MBStorage.PagesForWords[data.gftLength*SIZE[PrincOpsRuntime.GFTItem]]; SetReservedSegBits[seg _ MBVM.AllocMDSData[base: GFTPage, pages: gftPages]]; p _ PrincOpsRuntime.GFT; FOR i: CARDINAL IN [0..gftPages*SIZE[PrincOpsRuntime.GFTItem]) DO MBVM.Write[p+i, 0]; ENDLOOP; MBVM.Write[@SDDefs.SD[SDDefs.sGFTLength], data.gftLength]; }; InitAV: PROC [av: POINTER] = { FOR i: FrameSizeIndex IN FrameSizeIndex DO IF values.fsiChain[i] <= i THEN MBVM.Write[av+i, 1] ELSE MBVM.Write[av+i, 4*values.fsiChain[i]+2]; ENDLOOP; MBVM.Write[av+LargeReturnSlot, 1]; MBVM.Write[av+SpecialReturnSlot, 1]; }; TurnOffStartTrap: PUBLIC PROC = { DoIt: PROC [bh: MB.BHandle, mth: BcdOps.MTHandle] RETURNS [BOOL] = { f: PrincOps.GlobalFrameHandle = bh.mt[mth.gfi].frame; fcb: PrincOps.FrameCodeBase; MBVM.CopyRead[from: @f.code, to: @fcb, nwords: SIZE[PrincOps.FrameCodeBase]]; fcb.out _ FALSE; MBVM.CopyWrite[from: @fcb, to: @f.code, nwords: SIZE[PrincOps.FrameCodeBase]]; RETURN[FALSE] }; MB.EnumerateNoTrapModules[DoIt]; }; StartControlLink: PUBLIC PROC RETURNS [proc: PrincOps.ControlLink] = { g: PrincOps.GlobalFrameHandle = MB.WartFrame[]; gf: PrincOps.GlobalFrame; <> MBVM.CopyRead[from: g, to: @gf, nwords: SIZE[PrincOps.GlobalFrame]]; proc _ [procedure[gfi: gf.gfi, ep: MainBodyIndex, tag: TRUE]]; gf.started _ TRUE; MBVM.CopyWrite[from: @gf, to: g, nwords: SIZE[PrincOps.GlobalFrame]]; }; <> SimpleValues: TYPE = RECORD [ mdsBase, codeBase: MBVM.Base, nProcesses: CARDINAL, framePages: CARDINAL, pdaPages: CARDINAL, gftLength: CARDINAL, svSize: CARDINAL, stateVectorCounts: StartList.StateVectorCounts ]; SimpleDefaults: SimpleValues = [ mdsBase: 512, codeBase: 768, nProcesses: 50, framePages: 10, pdaPages: 1, gftLength: 512, svSize: 20B, stateVectorCounts: [1,1,3,1,1,3,1,1] ]; GetFrameWeight: PUBLIC PROC [index: FrameSizeIndex] RETURNS [weight: CARDINAL] = { RETURN[values.frameWeights[index]]}; SetFrameWeight: PUBLIC PROC [index: FrameSizeIndex, weight: CARDINAL] = { values.frameWeights[index] _ weight}; GetFsiChain: PUBLIC PROC [index: FrameSizeIndex] RETURNS [fsiNext: FrameSizeIndex] = { RETURN[values.fsiChain[index]]}; SetFsiChain: PUBLIC PROC [index: FrameSizeIndex, fsiNext: FrameSizeIndex] = { values.fsiChain[index] _ fsiNext}; AllocateFrames: PUBLIC PROC [size: CARDINAL, single, resident: BOOL] RETURNS [frames: POINTER, inFrameHeap: BOOL] = { pages: CARDINAL; seg: MBVM.DataSeg; IF single THEN RETURN[MB.Alloc[RuntimeInternal.MakeFsi[size] ! MB.AllocFault => CONTINUE], TRUE]; pages _ MBStorage.PagesForWords[size]; seg _ MBVM.AllocData[base: MBVM.MDS, pages: pages, dir: up]; frames _ MBVM.PointerFromSeg[seg]; seg.info.readOnly _ FALSE; IF resident THEN { seg.bootLoaded _ TRUE; seg.info.state _ resident; DivideAllocationArea[frames+size, pages*Environment.wordsPerPage - size, extraFrames]; }; RETURN[frames, FALSE] }; AllocateLocalFrames: PUBLIC PROC = { pages: CARDINAL; seg: MBVM.DataSeg; localHeapSize: CARDINAL _ 0; FOR i: CARDINAL IN FrameSizeIndex DO localHeapSize _ localHeapSize + values.frameWeights[i]*(FrameVec[i]+1); ENDLOOP; pages _ MAX[MBStorage.PagesForWords[localHeapSize], data.framePages]; seg _ MBVM.AllocData[base: MBVM.MDS, pages: pages, dir: up]; seg.bootLoaded _ TRUE; seg.info _ [FALSE, resident]; DivideAllocationArea[MBVM.PointerFromSeg[seg], pages*Environment.wordsPerPage, heapFrames]; }; DivideAllocationArea: PROC [base: POINTER, size: CARDINAL, counts: FrameCounts] = { p: POINTER _ base+4; -- allow initial dead space i, s, c, sum, z: CARDINAL; fw: ARRAY FrameSizeIndex OF CARDINAL; IF size < FrameVec[0]+4 THEN RETURN; FOR i IN [0..LENGTH[fw]) DO fw[i] _ values.frameWeights[i] ENDLOOP; size _ size-4; sum _ 0; FOR i IN [0..LENGTH[fw]) DO sum _ sum + FrameVec[i]*fw[i] ENDLOOP; c _ MAX[size/sum, 1]; WHILE size > FrameVec[0] DO FOR i IN [0..LENGTH[FrameVec]) DO s _ FrameVec[i]; IF s MOD 4 = 3 THEN s _ s + 1; FOR j: CARDINAL IN[1..fw[i]*c] DO z _ LOOPHOLE[p, CARDINAL] MOD 256; IF size < s THEN EXIT; IF z = 0 THEN {p _ p + 4; size _ size - 4} ELSE IF z = 252 THEN {p _ p + 8; size _ size - 8}; <> IF size < s THEN EXIT; MBVM.Write[p-1, i]; -- hidden link word MBVM.Write[p, MBVM.Read[PrincOps.AV+i]]; MBVM.Write[PrincOps.AV+i, p]; counts[i] _ counts[i] + 1; p_p+s; size_size-s; ENDLOOP; ENDLOOP; FOR i IN [0..LENGTH[fw]-1) DO fw[i] _ MAX[fw[i]/3, 1] ENDLOOP; c _ 1; ENDLOOP; }; ReportFrameAllocation: PUBLIC PROC = { OPEN MBOut; CR[]; Line["LOCAL FRAMES ALLOCATED (total (=heap+serendipity)):"L]; CR[]; FOR i: PrincOps.FrameSizeIndex IN PrincOps.FrameSizeIndex DO Number[i, [10, FALSE, FALSE, 4]]; Text[": "L]; IF extraFrames[i] = 0 THEN Decimal[heapFrames[i]] ELSE { Decimal[heapFrames[i]+extraFrames[i]]; Text[" (="L]; Decimal[heapFrames[i]]; Char['+]; Decimal[extraFrames[i]]; Char[')]}; CR[]; ENDLOOP; }; END.