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 April 5, 1983 3:16 pm
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;
};
Memory initialization
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;
fill in build time (used by Runtime.GetBuildTime)
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;
av and sd
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];
gft
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;
Note that the following manipulates only the overhead words.
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]];
};
Frame Allocation
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};
add to alloc vector
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.