-- 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......