DIRECTORY Basics USING [BYTE], BcdDefs USING [MTHandle], BootStartList USING [StateVectorCounts], IO USING [card, PutF, rope, STREAM], MB USING [Alloc, AllocFault, BHandle, EnumerateNoTrapModules, Handle, WartFrame], MBVM USING [ AllocData, AllocMDSData, Base, CopyRead, CopyWrite, DataSeg, LongPointerFromSeg, LongWrite, MDS, PointerFromSeg, Read, Write], PrincOps USING [ AllocationVectorSize, AV, ControlLink, Frame, FrameCodeBase, FrameSizeIndex, FrameVec, GFT, GFTIndex, GFTItem, GlobalFrame, GlobalFrameHandle, LargeReturnSlot, MainBodyIndex, PDABase, Priority, ProcessDataArea, ProcessStateBlock, SD, sGFTLength, SpecialReturnSlot, wordsPerPage], PrincOpsUtils USING [PagesForWords, WordsForPages], RuntimeInternal USING [MakeFsi]; MBMain: PROGRAM IMPORTS IO, MB, MBVM, PrincOpsUtils, RuntimeInternal EXPORTS MB = BEGIN OPEN PrincOps; BYTE: TYPE = Basics.BYTE; AVPage: CARDINAL = LOOPHOLE[AV, CARDINAL]/wordsPerPage; GFTPage: CARDINAL = LOOPHOLE[GFT, CARDINAL]/wordsPerPage; data: MB.Handle _ NIL; values: REF 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 = REF FrameCountTable; FrameCountTable: TYPE = ARRAY FrameSizeIndex OF CARDINAL; InitMain: PUBLIC PROC [h: MB.Handle] = { data _ h; values _ NEW[Values _ []]; heapFrames _ NEW[FrameCountTable _ ALL[0]]; extraFrames _ NEW[FrameCountTable _ ALL[0]]; FOR i: Priority IN 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 = { values _ NIL; heapFrames _ NIL; extraFrames _ NIL; data _ NIL; }; InitMemory: PUBLIC PROC = { AssignDefaults[]; IF ~data.germ THEN {ReserveSelectedPages[]; InitPDA[]}; InitializeMDS[]; AllocateLocalFrames[]; }; AssignDefaults: PROC = { i: CARDINAL; FOR i IN 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: PDABase; i: CARDINAL; words: CARDINAL _ 0; FOR i IN Priority DO words _ words + data.stateVectorCounts[i]*data.svSize; ENDLOOP; data.pdaPages _ MAX[ PrincOpsUtils.PagesForWords[ data.nProcesses*(SIZE[ProcessStateBlock]+1) + words + SIZE[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*wordsPerPage) DO MBVM.LongWrite[pda+i, 0]; ENDLOOP; }; InitializeMDS: PROC = { gftPages: CARDINAL; seg: MBVM.DataSeg; p: POINTER; p _ AV; SetReservedSegBits[seg _ MBVM.AllocMDSData[base: AVPage, pages: 1]]; FOR i: CARDINAL IN [0..wordsPerPage) DO MBVM.Write[p+i, 0] ENDLOOP; InitAV[p]; gftPages _ PrincOpsUtils.PagesForWords[data.gftLength*SIZE[GFTItem]]; SetReservedSegBits[seg _ MBVM.AllocMDSData[base: GFTPage, pages: gftPages]]; p _ GFT; FOR i: CARDINAL IN [0..gftPages*SIZE[GFTItem]) DO MBVM.Write[p+i, 0]; ENDLOOP; MBVM.Write[@SD[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: BcdDefs.MTHandle] RETURNS [BOOL] = { f: GlobalFrameHandle = bh.mt[mth.gfi].frame; fcb: FrameCodeBase; MBVM.CopyRead[from: @f.code, to: @fcb, nwords: SIZE[FrameCodeBase]]; fcb.out _ FALSE; MBVM.CopyWrite[from: @fcb, to: @f.code, nwords: SIZE[FrameCodeBase]]; RETURN[FALSE] }; MB.EnumerateNoTrapModules[DoIt]; }; StartControlLink: PUBLIC PROC RETURNS [proc: ControlLink] = { g: GlobalFrameHandle = MB.WartFrame[]; gf: GlobalFrame; MBVM.CopyRead[from: g, to: @gf, nwords: SIZE[GlobalFrame]]; proc _ [procedure[gfi: gf.gfi, ep: MainBodyIndex, tag: TRUE]]; gf.started _ TRUE; MBVM.CopyWrite[from: @gf, to: g, nwords: SIZE[GlobalFrame]]; }; SimpleValues: TYPE = RECORD [ mdsBase, codeBase: MBVM.Base, nProcesses: CARDINAL, framePages: CARDINAL, pdaPages: CARDINAL, gftLength: CARDINAL, svSize: CARDINAL, stateVectorCounts: BootStartList.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 _ PrincOpsUtils.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; }; RETURN[frames, FALSE] }; FrameHeapPiece: TYPE = POINTER TO FrameHeapPieceHeader; FrameHeapPieceHeader: TYPE = MACHINE DEPENDENT RECORD [ next(0): FrameHeapPiece, wordsAllocated(1): CARDINAL, -- actually [0..VM.WordsForPages[shortPointerSpan]] wordsInUse(2): CARDINAL, -- assert: wordsInUse MOD 4 = 3 fsiFrame(3): ARRAY [0..0) OF --WORD-- FsiFrame]; -- must be at 3 MOD 4 boundary. FsiFrame: TYPE = MACHINE DEPENDENT RECORD [ fsi(0): AnyFrameSizeIndex, -- must be at 3 MOD 4 boundary. frame(1): local Frame]; AnyFrameSizeIndex: TYPE = CARDINAL [0..AllocationVectorSize); MarkerType: TYPE = MACHINE DEPENDENT {frame(0), deadSpace(1)}; FrameMarker: TYPE = MACHINE DEPENDENT RECORD [ marker(0): SELECT markerType(0:0..0): MarkerType FROM frame => [fsi(0:1..15): FrameSizeIndex], deadSpace => [count(0:1..15): NAT], -- count does NOT include FrameMarker ENDCASE]; AllocateLocalFrames: PROC = { pieceHeader: --VMInternal.--FrameHeapPieceHeader _ NULL; pieceInVM: --VMInternal.--FrameHeapPiece; piecePages: CARDINAL; localHeapSize: CARDINAL _ 0; seg: MBVM.DataSeg; FOR i: CARDINAL IN FrameSizeIndex DO localHeapSize _ localHeapSize + values.frameWeights[i]*(FrameVec[i]+1); ENDLOOP; piecePages _ MAX[PrincOpsUtils.PagesForWords[localHeapSize], data.framePages]; pieceHeader.next _ NIL; pieceHeader.wordsAllocated _ PrincOpsUtils.WordsForPages[piecePages]; seg _ MBVM.AllocData[base: MBVM.MDS, pages: piecePages, dir: up]; seg.bootLoaded _ TRUE; seg.info _ [FALSE, resident]; pieceInVM _ MBVM.PointerFromSeg[seg]; pieceHeader.wordsInUse _ DivideAllocationArea[pieceInVM, pieceHeader.wordsAllocated, heapFrames]; MBVM.CopyWrite[from: @pieceHeader, to: pieceInVM, nwords: SIZE[FrameHeapPieceHeader]]; }; DivideAllocationArea: PROC [base: POINTER, size: CARDINAL, counts: FrameCounts] RETURNS [wordsUsed: CARDINAL _ 0] = { p: POINTER _ base; origin: POINTER; sum: CARDINAL _ 0; ct: CARDINAL; fw: ARRAY FrameSizeIndex OF CARDINAL; AdjustSize: PROC [words: CARDINAL, markDead: BOOL _ TRUE] = { IF markDead THEN MBVM.Write[p, --VMSideDoor.--FrameMarker[deadSpace[words-1]]]; p _ p + words; size _ size - words; }; EnsureQuadWordAlignment: PROC [markDead: BOOL] = { pm4: CARDINAL = LOOPHOLE[p, CARDINAL] MOD 4; IF pm4 ~= 0 THEN AdjustSize[4 - pm4, markDead]; }; Ensure3Mod4Alignment: PROC [markDead: BOOL] = { pm4: CARDINAL = LOOPHOLE[p, CARDINAL] MOD 4; IF pm4 ~= 3 THEN AdjustSize[3 - pm4, markDead]; }; IF size < 4 THEN RETURN; EnsureQuadWordAlignment[markDead: FALSE]; IF size < 4 THEN RETURN; origin _ p; Ensure3Mod4Alignment[markDead: FALSE]; -- allow space for FramePieceHeader FOR i: FrameSizeIndex IN [0..fw.LENGTH) DO sum _ sum + FrameVec[i]*(fw[i] _ values.frameWeights[i]); ENDLOOP; ct _ MAX[size/sum, 1]; WHILE size > FrameVec[0] DO FOR fsi: FrameSizeIndex IN [0..FrameVec.LENGTH) DO frSize: CARDINAL = FrameVec[fsi] + SIZE[FrameMarker]; THROUGH [1..fw[fsi]*ct] UNTIL size < frSize DO AddFrameToAV: PROC = { MBVM.Write[p, FrameMarker[frame[fsi]]]; MBVM.Write[p + SIZE[FrameMarker], MBVM.Read[@AV[fsi]]]; MBVM.Write[@AV[fsi], p + SIZE[FrameMarker]]; }; EnsureLegalForDandelion: PROC = { OPEN PrincOps; offsetInPage: CARDINAL = LOOPHOLE[p, CARDINAL] MOD wordsPerPage; IF offsetInPage = wordsPerPage-SIZE[FrameMarker] THEN AdjustSize[4] ELSE IF offsetInPage = wordsPerPage-SIZE[FrameMarker]-SIZE[local Frame] THEN AdjustSize[8]; }; Ensure3Mod4Alignment[markDead: TRUE]; IF size < frSize THEN EXIT; EnsureLegalForDandelion[]; IF size < frSize THEN EXIT; AddFrameToAV[]; counts[fsi] _ counts[fsi] + 1; p _ p + frSize; size _ size - frSize; ENDLOOP; ENDLOOP; FOR i: FrameSizeIndex IN [0..fw.LENGTH-1) DO fw[i] _ MAX[fw[i]/3, 1]; ENDLOOP; ct _ 1; ENDLOOP; RETURN [p - origin] }; ReportFrameAllocation: PUBLIC PROC = { loadmap: IO.STREAM = data.loadmap; serendipity: BOOL _ FALSE; FOR i: FrameSizeIndex IN FrameSizeIndex DO IF extraFrames[i] ~= 0 THEN {serendipity _ TRUE; EXIT}; ENDLOOP; loadmap.PutF[ "\NLOCAL FRAMES ALLOCATED%g:\N\N", IO.rope[IF serendipity THEN " (total=(heap+serendipity))" ELSE NIL]]; FOR i: FrameSizeIndex IN FrameSizeIndex DO IF extraFrames[i] = 0 THEN loadmap.PutF["%4d: %d\N", IO.card[i], IO.card[heapFrames[i]]] ELSE loadmap.PutF["%4d: %d (=%d+%d)\N", IO.card[i], IO.card[heapFrames[i]+extraFrames[i]], IO.card[heapFrames[i]], IO.card[extraFrames[i]] ]; ENDLOOP; }; END. ¾MBMain.mesa Edited by Sandman on 6-Aug-81 15:41:24 Edited by Lewis on 17-Sep-81 13:31:13 Edited by Levin on September 30, 1983 4:08 pm Memory initialization av and sd gft Note that the following manipulates only the overhead words. Frame Allocation Someday, we may wish to do the following: [] _ DivideAllocationArea[frames+size, pages*wordsPerPage - size, extraFrames]; The following declarations are shared with VMInternal and VMSideDoor. When VM stabilizes, they should be referenced from there. VMInternal: VMSideDoor: OPEN VMSideDoor; Make sure that the fsi word, overhead, and local 0 are all in the same page. Assert: 'p' MOD 4 = 3 and 'frSize' words are available, beginning at 'p'. ʽ˜Jšœ ™ Jšœ&™&Jšœ%™%Jšœ-™-J˜šÏk ˜ Jšœœœ˜Jšœœ ˜Jšœœ˜(Jšœœœ˜$JšœœI˜Qšœœ˜ Jšœ\œ˜~—šœ œ˜Jšœœ?œŒœ/˜——Jšœœ ˜3Jšœœ ˜ J˜—šœ˜Jšœœœœ!˜5Jšœœ˜ J˜—Jš˜J˜Jšœ ˜J˜Jšœœ œ˜J˜Jš œœœœœ˜7Jš œ œœœœ˜9J˜Jšœœ œ˜J˜Jšœœ œ˜šœœœ˜Jšœœœœœœœœ˜DJšœ œœœœœœœ˜A—˜J˜MJ˜QJ˜—Jšœ'œ˜+Jšœ œœ˜(Jš œœœœœ˜9J˜šÏnœœœœ ˜(J˜ Jšœ œ˜Jšœ œœ˜+Jšœœœ˜,šœ œ ˜Jšœœœ˜(Jšœ˜—Jšœœœ˜Jšœœœ˜Jšœ œœ˜Jšœ œœ˜Jšœœœ˜Jšœ œœ˜Jšœ œœ˜Jšœ˜J˜—šž œœœ˜Jšœ œ˜Jšœ œ˜Jšœœ˜Jšœ˜ Jšœ˜J˜J˜—Jšœ™J˜šž œœœ˜J˜Jšœ œ%˜7J˜J˜J˜J˜—šžœœ˜Jšœœ˜ šœœ ˜šœœœ˜2J˜@—Jšœ˜—šœœ˜šœœœœ˜,J˜7—šœœœœ˜(J˜/—Jšœ˜—šœœœœ˜(J˜*—šœœœœ˜&J˜&—šœœœœ˜'J˜(—šœœœœ˜'J˜(—šœœœœ˜)J˜,—šœœœœ˜)J˜,—˜J˜——šžœœ˜Jšœœ ˜Jšœœ˜(J˜Jšœœ!˜+J˜Jšœœ!˜+J˜J˜J˜—šžœœœ ˜.Jšœ œ ˜Jšœ˜Jšœ˜J˜—šžœœ˜Jšœœ ˜Jšœ ˜ Jšœœ˜ Jšœœ˜šœœ œ˜J˜6Jšœ˜—šœœ˜˜Jšœœ!œ˜MJ˜ J˜——Jšœœ5˜?J˜Jšœœ˜#šœœ!œ˜,Jšœ˜Jšœ˜—šœ˜J˜——šž œœ˜Jšœ œ˜Jšœœ ˜Jšœœ˜ Jšœ ™ Jšœœ˜Jšœœ'˜DJš œœœœœœ˜CJ˜ Jšœ™Jšœ6œ ˜EJšœœ/˜LJšœœ˜š œœœœ ˜1Jšœ˜Jšœ˜—Jšœœ˜,Jšœ˜J˜—šžœœœ˜šœœ˜*Jšœœœ˜3Jšœœ%˜.Jšœ˜—Jšœ˜"Jšœ ˜$Jšœ˜J˜—šžœœœ˜!š žœœœ!œœ˜EJ˜,J˜Jšœ+œ˜DJšœ œ˜Jšœ,œ˜EJšœœ˜ Jšœ˜—Jšœ˜ Jšœ˜J˜—šžœœœœ˜=Jšœœ ˜&J˜Jšœ<™Jšœ œ˜Jšœ%œ˜š œ œœ œœ˜.šœ œ ˜5J˜(JšœœŸ%˜JJšœ˜ ——J˜šžœœ˜Jšœ Ÿœœ˜8Jšœ Ÿœ˜)Jšœ œ˜Jšœœ˜Jšœœ ˜šœœœ˜$J˜GJšœ˜—Jšœ œ>˜NJšœœ˜JšœE˜EJšœœœœ˜AJšœœ˜Jšœ œ ˜Jšœ œ˜%šœ˜JšœH˜H—Jšœ6œ˜VJšœ˜J˜—šžœœœœ˜OJšœ œ ˜%Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜ Jšœœœœ˜%š ž œœ œ œœ˜=Jšœ œœ Ÿœ!˜OJšœ˜Jšœ˜J˜—šžœœ œ˜2Jš œœœœœ˜,Jšœ œ˜/Jšœ˜—šžœœ œ˜/Jš œœœœœ˜,Jšœ œ˜/Jšœ˜—Jšœ œœ˜Jšœ"œ˜)Jšœ œœ˜J˜ JšœœŸ#˜Kšœœœ˜*Jšœ9˜9Jšœ˜—Jšœœ˜šœ˜šœœœ˜2Jšœœœ˜5šœœ ˜.šž œœ˜Jšœ™Jšœ#˜'Jšœ œœœ˜7Jšœœ œ˜,J˜—šžœœ˜!JšœL™LJšœ ˜Jš œœœœœ˜@Jšœœœ˜CJš œœœœœ˜[J˜—Jšœœ˜%Jšœœœ˜J˜Jšœœœ˜JšœJ™JJ˜J˜J˜J˜Jšœ˜—Jšœ˜—Jš œœœœ œœ˜NJ˜Jš˜—Jšœ ˜šœ˜J˜——šžœœœ˜&Jšœ œœ˜"Jšœ œœ˜šœœ˜*Jšœœœœ˜7Jšœ˜—šœ ˜ Jšœ"˜"Jš œœ œœœ˜E—šœœ˜*Jšœœœ œ˜Yš˜šœ#˜#Jšœ œ$˜2Jšœœ˜/Jšœ˜——Jš˜—šœ˜J˜——Jšœ˜J˜J˜—…—+¢>