-- MMStart.Mesa Edited by Sandman on May 23, 1979 11:52 AM
-- Edited by Forrest on October 8, 1980 2:42 PM
DIRECTORY
AltoDefs USING [PageNumber],
BcplOps USING [BcplJSR],
ControlDefs USING [FrameHandle, GlobalFrameHandle, NullFrame, StateVector],
FrameOps USING [GetReturnFrame, MyLocalFrame],
ImageDefs USING [UserCleanupProc],
InlineDefs USING [BITSHIFT, BITOR],
MMInit,
MMSDEntries,
ProcessDefs USING [
DefaultPriority, Detach, DisableInterrupts, DisableTimeout, DIW,
EnableInterrupts, GetPriority, Priority, SetPriority, SetTimeout,
TimeoutLevel],
ProcessOps,
PSBDefs,
SDDefs USING [
sAllocTrap, sBLTE, sBLTEC, sBYTBLTE, sBYTBLTEC, sBreak, sControlFault,
sCopy, SD, sError, sErrorList, sFork, sJoin, sLongDiv, sLongDivMod,
sLongMod, sLongMul, sProcessTrap, sRestart, sGoingAway, sReturnError,
sReturnErrorList, sSignal, sSignalList, sSignedDiv, sStackError,
sStart, sStringInit, sSwapTrap, sUnbound, sULongDiv, sULongDivMod,
sULongMod, sUnnamedError, sUnNew],
SegmentDefs USING [DeleteDataSegment],
SystemDefs USING [FreePages],
SwapperOps,
WartDefs;
MMStart: PROGRAM [h: POINTER TO WartDefs.Header] RETURNS [PROGRAM]
IMPORTS BcplOps, FrameOps, ImageDefs, InlineDefs, MMInit,
MMSDEntries, ProcessDefs, ProcessOps, SegmentDefs, SystemDefs, SwapperOps
EXPORTS MMInit =
BEGIN OPEN MMInit, SDDefs;
InitSD: PUBLIC PROCEDURE =
BEGIN OPEN SDDefs, MMSDEntries;
sd: POINTER TO ARRAY [0..0) OF UNSPECIFIED ← SD;
sd[sSignalList] ← SignalList;
sd[sSignal] ← Signal;
sd[sErrorList] ← ErrorList;
sd[sError] ← Error;
sd[sReturnErrorList] ← ReturnErrorList;
sd[sReturnError] ← ReturnError;
sd[sUnnamedError] ← UnnamedError;
sd[sStackError] ← StackErrorTrap;
sd[sControlFault] ← ControlFaultTrap;
sd[sStart] ← Start;
sd[sRestart] ← Restart;
sd[sBLTE] ← BlockEqual;
sd[sBYTBLTE] ← ByteBlockEqual;
sd[sBLTEC] ← BlockEqualCode;
sd[sBYTBLTEC] ← ByteBlockEqualCode;
sd[sStringInit] ← StringInit;
sd[sSignedDiv] ← SignDivide;
sd[sLongDivMod] ← DDivMod;
sd[sLongMod] ← DMod;
sd[sLongDiv] ← DDiv;
sd[sLongMul] ← DMultiply;
sd[sULongDivMod] ← DUnsignedDivMod;
sd[sULongMod] ← DUnsignedMod;
sd[sULongDiv] ← DUnsignedDiv;
sd[sAllocTrap] ← AllocTrap[AllocTrap[ControlDefs.NullFrame]];
sd[sSwapTrap] ← CodeTrap;
sd[sUnbound] ← UnboundProcedureTrap;
sd[sCopy] ← Copy;
sd[sUnNew] ← UnNew;
sd[sGoingAway] ← ImageDefs.UserCleanupProc;
END;
Memory: PUBLIC PROCEDURE [ff, lf: AltoDefs.PageNumber] =
BEGIN
MMInit.lfvmp ← lf; MMInit.ffvmp ← ff;
FOR i: CARDINAL IN [ff..lf] DO MMInit.pageMap[i] ← free ENDLOOP;
END;
Interrupt: PROCEDURE =
BEGIN OPEN ProcessDefs;
save: Priority = GetPriority[];
START MMInterrupt;
SetTimeout[@wakeup, 1];
SetPriority[6];
Detach[FORK CheckInterrupt];
SetPriority[save];
RETURN
END;
InitializeProcesses: PROCEDURE =
BEGIN OPEN SDDefs, ProcessDefs, ProcessOps, PSBDefs;
sd: POINTER TO ARRAY [0..0) OF UNSPECIFIED ← SD;
PSBBase: CARDINAL = 0;
firstPSB: ProcessHandle ← FirstProcess↑;
lastPSB: ProcessHandle ← LastProcess↑;
psb: ProcessHandle;
DisableTimeout[@dead];
DisableTimeout[@frameReady];
DisableTimeout[@frameTaken];
DisableTimeout[@rebirth];
CurrentState↑ ← FirstStateVector↑ +
DefaultPriority*SIZE[ControlDefs.StateVector];
-- locate and initialize PSBs
sd[sProcessTrap] ← ProcessTrap;
sd[sFork] ← Fork;
sd[sJoin] ← Join;
-- fabricate PSB for self
lastPSB↑ ← PSB[
link: lastPSB,
cleanup: Clean,
timeout: 0,
enterFailed: FALSE,
detached: FALSE,
fill: 0B,
state: alive,
timeoutAllowed:,
abortPending: FALSE,
timeoutPending: FALSE,
waitingOnCV: FALSE,
priority: DefaultPriority,
frame: FrameOps.MyLocalFrame[]];
CurrentPSB↑ ← ReadyList↑ ← lastPSB;
-- set up free PSB pool ("rebirth" condition)
FOR psb ← firstPSB, psb+SIZE[PSB]
UNTIL psb = lastPSB DO
psb↑ ← PSB[
link: psb-SIZE[PSB],
cleanup: Clean,
timeout: 0,
enterFailed: FALSE,
detached: FALSE,
fill: 0B,
state: dead,
timeoutAllowed:,
abortPending: FALSE,
timeoutPending: FALSE,
waitingOnCV: TRUE,
priority: DefaultPriority,
frame: ControlDefs.NullFrame];
ENDLOOP;
LOOPHOLE[rebirth, Condition].queue ←
(firstPSB.link ← lastPSB-SIZE[PSB])-PSBBase;
-- CV↑ already set up by Nova code
ActiveWord↑ ← 77777B;
RETURN
END;
InitializeTimeouts: PROCEDURE =
BEGIN OPEN InlineDefs, ProcessDefs;
TimeoutMask: WORD = BITSHIFT[1,TimeoutLevel];
DisableInterrupts[];
-- Nova code has set up IntVec[TimeoutLevel]
DIW↑ ← BITOR[DIW↑, TimeoutMask];
EnableInterrupts[];
RETURN
END;
ProcessWartList: PROCEDURE RETURNS [PROGRAM] =
BEGIN OPEN WartDefs;
segBase: TableBase = h.tablebase + h.segOffset;
linkBase: TableBase = h.tablebase + h.linkOffset;
ProcessOps.WriteWDC[0]; -- interrupts on
FOR seg: SegIndex ← LOOPHOLE[SIZE[Header]],
seg + SIZE[SegEntry] UNTIL seg = h.segLength
DO
s: SegHandle = @segBase[seg];
IF s.in THEN s.handle ← SwapperOps.BootDataSegment[s.vmPage, s.pages]
ENDLOOP;
FOR link: LinkIndex ← FIRST[LinkIndex],
link + SIZE[LinkEntry] UNTIL link = h.linkLength
DO
frame: ControlDefs.GlobalFrameHandle = linkBase[link].frame;
s: SegHandle = @segBase[linkBase[link].codeseg];
IF s.handle=NIL THEN ERROR;
frame.code.handle ← LOOPHOLE[s.vmPage*256];
ENDLOOP;
InitializeProcesses[];
InitializeTimeouts[];
Interrupt[];
SegmentDefs.DeleteDataSegment[segBase[h.loadState].handle];
SegmentDefs.DeleteDataSegment[segBase[h.initLoadState].handle];
IF segBase[h.bcd].in THEN
SegmentDefs.DeleteDataSegment[segBase[h.bcd].handle];
SystemDefs.FreePages[h];
START MMDebug[LOOPHOLE[h.user]];
FrameOps.GetReturnFrame[].returnlink ← LOOPHOLE[MMSDEntries.Restart];
SDDefs.SD[sBreak] ← MMSDEntries.Break;
RETURN[LOOPHOLE[MMDebug]];
END;
WartBreak: PROCEDURE =
BEGIN OPEN BcplOps, ControlDefs;
s: StateVector;
f: FrameHandle;
break: RECORD[a,b: WORD];
s ← STATE;
break ← [77400B, 1400B];
f ← FrameOps.GetReturnFrame[];
s.dest ← f;
f.pc ← [IF f.pc < 0 THEN -f.pc ELSE (1-f.pc)];
s.instbyte ← BcplJSR[JSR, @break, 0];
RETURN WITH s;
END;
SDDefs.SD[sBreak] ← WartBreak;
InitSD[];
START MMTraps;
START MMMemory;
START MMSignals;
START MMProcess;
Memory[h.ffvmp, h.lfvmp];
RETURN[ProcessWartList[]];
END......