DIRECTORY BasicTime USING [Now, Update], IO, LarkControl, LarkPrograms USING [ProcedureEnclosing, STObject], PupDefs USING [UniqueLocalPupAddress], PupTypes USING [fillInPupAddress], Process USING [MsecToTicks, SetTimeout], Rope USING [Cat, ROPE], TeleLoad USING [AddressToName, EventProc, EventRecordObject, StopHimProbing, SwabEvent]; LarkControlServer: CEDAR MONITOR IMPORTS BasicTime, IO, LarkControl, LarkPrograms, Process, PupDefs, Rope, TeleLoad EXPORTS LarkControl = { NoteEvents: PUBLIC TeleLoad.EventProc = TRUSTED { d: LarkControl.Data _ NARROW[clientData]; lark: LarkControl.LarkData _ NIL; index: LarkControl.LarkIndex _ LOOPHOLE[who.host]; IF who.net = 0 THEN who.net _ PupDefs.UniqueLocalPupAddress[PupTypes.fillInPupAddress].net; FOR ll: LIST OF REF ANY _ LarkControl.GetInstanceList[], ll.rest WHILE ll # NIL DO d _ NARROW[ll.first]; IF d.net = who.net THEN EXIT; REPEAT FINISHED => RETURN; ENDLOOP; IF d.larks[index].address.net = who.net AND d.larks[index].address.host = who.host THEN lark _ d.larks[index] ELSE FOR i: LarkControl.LarkIndex IN LarkControl.LarkIndex DO IF d.larks[i].address.net = who.net AND d.larks[i].address.host = who.host THEN { index _ i; lark _ d.larks[i]; EXIT; }; REPEAT FINISHED => { d.out.PutF["Event received from (unknown) %g\n", IO.rope[TeleLoad.AddressToName[who].nameRope]]; RETURN; }; ENDLOOP; IF d.mainSwitch # off THEN TeleLoad.StopHimProbing[h: lark.h, setPointers: TRUE]; cb _ TeleLoad.SwabEvent[cb]; lark.event _ cb; lark.newEvent _ TRUE; d.eventLark _ index; d.anyEvent _ TRUE; LarkControl.NotifyWatcher[]; }; printAllEvents: BOOL _ FALSE; cDivideError: CARDINAL = 0; cTRACE: CARDINAL = 1; cNMI: CARDINAL = 2; cBreakpoint: CARDINAL = 3; cOverflow: CARDINAL = 4; cCallSwat: CARDINAL = 5; cWDTBoot: CARDINAL = 0FFF8H; cMainRet: CARDINAL = 0FFF9H; cTeleBoot: CARDINAL = 0FFFAH; cSSFAIL: CARDINAL = 0FFFBH; cMONRET: CARDINAL = 0FFFCH; cRUNERR: CARDINAL = 0FFFDH; cEXTINT: CARDINAL = 0FFFEH; cPwrOnBoot: CARDINAL = 0FFFFH; BootReason: PUBLIC PROC [reason: CARDINAL, BX: CARDINAL _ 0] RETURNS [Rope.ROPE] = { r: Rope.ROPE; r _ SELECT reason FROM cDivideError => "DivideError", cTRACE => "Single Step", cNMI => "NMI", cBreakpoint => "Breakpoint", cOverflow => "Overflow", cCallSwat => IF BX = 0 THEN "CallSwat" ELSE Rope.Cat["CallSwat(", BootReason[BX, 0], ")"], cWDTBoot => "Watchdog Timer boot", cMainRet => "Main program returned", cTeleBoot => "Teleboot", cSSFAIL => "Single Step failure", cMONRET => "Monitor returned", cRUNERR => "Execution into monitor space", cEXTINT => "External Interrupt", cPwrOnBoot => "Power On Boot", LarkControl.cRUNNING => "Running", LarkControl.cDown => "Down" ENDCASE => IO.PutFR["%04x", IO.card[reason]]; RETURN[r]; }; watchProcess: PROCESS; watcherActive: BOOL _ FALSE; watchWait: CONDITION; watcherUseCount: INT _ 0; NotifyWatcher: PUBLIC ENTRY PROC = { NOTIFY watchWait; }; StartWatcher: PUBLIC ENTRY PROC = TRUSTED { watcherUseCount _ watcherUseCount + 1; IF watcherUseCount > 1 THEN RETURN; IF watcherActive THEN RETURN; watcherActive _ TRUE; Process.SetTimeout[@watchWait, Process.MsecToTicks[1000]]; watchProcess _ FORK WatchProcess[]; }; StopWatcher: PUBLIC PROC = TRUSTED { giveUp: BOOL _ FALSE; GetLock: ENTRY PROC = TRUSTED { watcherUseCount _ MAX[0, watcherUseCount - 1]; IF watcherUseCount > 0 THEN giveUp _ TRUE; IF NOT watcherActive THEN giveUp _ TRUE; watcherActive _ FALSE; }; GetLock[]; IF NOT giveUp THEN JOIN watchProcess; }; WatchProcess: PROC = { d: LarkControl.Data; DO FOR ll: LIST OF REF ANY _ LarkControl.GetInstanceList[], ll.rest WHILE ll # NIL DO d _ NARROW[ll.first]; IF d.anyEvent THEN CheckLark[d, d.larks[d.eventLark], TRUE]; ENDLOOP; FOR ll: LIST OF REF ANY _ LarkControl.GetInstanceList[], ll.rest WHILE ll # NIL DO d _ NARROW[ll.first]; FOR i: LarkControl.LarkIndex IN LarkControl.LarkIndex DO CheckLark[d, d.larks[i], TRUE]; ENDLOOP; d.anyEvent _ FALSE; ENDLOOP; WaitLocked[]; IF NOT watcherActive THEN EXIT; ENDLOOP; }; WaitLocked: ENTRY PROC = { WAIT watchWait; }; CheckLark: ENTRY PROC [d: LarkControl.Data, lark: LarkControl.LarkData, display: BOOL _ TRUE] = { reason: Rope.ROPE _ NIL; event: TeleLoad.EventRecordObject _ lark.event; maybeTakeAction: BOOL _ TRUE; out: IO.STREAM _ lark.h.log; IF lark.newEvent THEN { lark.newEvent _ FALSE; IF lark.expectEvent THEN { lark.expectEvent _ FALSE; IF (event.reason = lark.expectedEventType OR (event.reason = cCallSwat AND event.regs.Regs[BX] = lark.expectedEventType)) AND NOT printAllEvents THEN RETURN; }; reason _ BootReason[event.reason, event.regs.Regs[BX]]; SELECT event.reason FROM cDivideError => NULL; cTRACE => lark.state _ event.regs; cNMI => lark.state _ event.regs; cBreakpoint => { here: LarkPrograms.STObject; known: BOOL _ FALSE; event.regs.Regs[IP] _ event.regs.Regs[IP] - 1; here _ LarkPrograms.ProcedureEnclosing[lark.program, event.regs.Regs[IP]]; FOR l: LIST OF LarkControl.Breakpoint _ lark.breakList, l.rest WHILE l # NIL DO IF event.regs.Regs[IP] = l.first.address THEN { known _ TRUE; EXIT; }; ENDLOOP; IF NOT known THEN out.PutRope["Unknown "]; out.PutF["Break at %04x, (%g", IO.card[event.regs.Regs[IP]], IO.rope[here.id]]; IF here.addr = event.regs.Regs[IP] THEN out.PutRope[")\n"] ELSE out.PutF[" + %x)\n", IO.card[event.regs.Regs[IP] - here.addr]]; lark.state _ event.regs; }; cOverflow => NULL; cCallSwat => NULL; cWDTBoot => NULL; cMainRet => NULL; cTeleBoot => NULL; cSSFAIL => NULL; cMONRET => NULL; cRUNERR => NULL; cEXTINT => NULL; cPwrOnBoot => NULL; LarkControl.cDown => maybeTakeAction _ FALSE; LarkControl.cRUNNING => maybeTakeAction _ FALSE; ENDCASE => NULL; IF display THEN LarkControl.DisplayEvent[lark: lark, event: event, out: out, reasonRope: reason, preRope: "Event from"]; IF maybeTakeAction THEN ConsiderActionFurther[lark: lark, event: event]; }; }; ConsiderActionFurther: PUBLIC PROC [lark: LarkControl.LarkData, event: TeleLoad.EventRecordObject] = { IF lark.world.mainSwitch # auto THEN RETURN; IF lark.eval # NIL THEN RETURN; IF lark.larkMode = 'd THEN RETURN; IF event.reason = LarkControl.cRUNNING THEN RETURN; IF event.reason = LarkControl.cDown THEN RETURN; LarkControl.LarkGVSet[lark: lark, setMode: TRUE, setProgram: TRUE]; LarkControl.PaintMode[lark]; IF lark.larkMode # 'O THEN RETURN; lark.h.log.PutF["%g: Automatic load at %t\n", IO.rope[lark.rName], IO.time[BasicTime.Now[]]]; lark.lastBootTimeValid _ TRUE; lark.lastBoot _ BasicTime.Update[base: BasicTime.Now[], period: -1]; IF lark.slaveProgram # NIL THEN LarkControl.LoadProgram[lark: lark, go: FALSE, main: FALSE]; IF lark.program # NIL THEN LarkControl.LoadProgram[lark: lark, go: TRUE, main: TRUE] ELSE lark.h.log.PutF["%g: program not found\n", IO.rope[lark.rName]]; }; }. May 6, 1983 7:04 pm, LCS, created from LarkCommImpl.mesa December 22, 1983 1:45 pm, LCS, Cedar 5 ¸LarkControlServer.mesa Stewart, December 22, 1983 1:45 pm cant find the offending lark! Lark boot reasons out.NewLine[]; Don't try again for three minutes if it fails this time. Ê H˜Jšœ™Jšœ"™"J˜šÏk ˜ Jšœ œ˜Jšœ˜J˜ Jšœ œ ˜2Jšœœ˜&Jšœ œ˜"Jšœœ˜(Jšœœœ˜Jšœ œJ˜XJ˜—Jšœœ˜ Jšœ œ=˜RJšœ˜J˜J˜šœ œœ˜1Jšœœ ˜)Jšœœ˜!Jšœœ ˜2Jšœ œ1œ˜[šœœœœœ*œœ˜RJšœœ ˜Jšœœœ˜Jš˜Jšœœ˜Jšœ˜—Jšœ&œ(œ˜mšœœœ˜=šœ"œ$œ˜QJ˜ J˜Jšœ˜J˜—Jš˜šœ˜ J™Jšœ1œ-˜`Jšœ˜J˜—Jšœ˜—Jšœœ1œ˜QJ˜Jšœ˜Jšœœ˜J˜Jšœ œ˜Jšœ˜J˜—J˜Jšœœœ˜J˜™Jšœœ˜Jšœœ˜Jšœœ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜—J˜šÏn œœœ œœœœœ˜TJšœœ˜ šœœ˜J˜J˜J˜J˜J˜Jš œ œœœ œ"œ ˜ZJ˜"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˜—J˜šž œœœœ˜$Jšœœœ˜šžœœœœ˜Jšœœ˜.Jšœœ œ˜*Jšœœœ œ˜)Jšœœ˜J˜—J˜ Jšœœœœ˜%J˜—J˜šž œœ˜Jšœ˜š˜šœœœœœ*œœ˜RJšœœ ˜Jšœ œ$œ˜