LarkControlServer.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Stewart, December 22, 1983 1:45 pm
Swinehart, April 6, 1987 9:52:47 am PDT
DIRECTORY
BasicTime USING [Now, Update],
IO,
LarkControl,
LarkPrograms USING [ProcedureEnclosing, STObject],
Pup USING [nullSocket],
PupName USING [ NameLookup],
Process USING [MsecToTicks, SetTimeout],
Rope USING [Cat, ROPE],
TeleLoad USING [AddressToName, EventProc, EventRecordObject, StopHimProbing, SwabEvent];
LarkControlServer: CEDAR MONITOR
IMPORTS BasicTime, IO, LarkControl, LarkPrograms, Process, PupName, 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 ← PupName.NameLookup["ME", Pup.nullSocket].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 => {
cant find the offending lark!
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;
Lark boot reasons
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], , d.wDir];
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;
out.NewLine[];
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.LarkDBSet[lark: lark, setMode: TRUE, setProgram: TRUE];
LarkControl.PaintMode[lark];
IF lark.larkMode # 'O THEN RETURN;
Don't try again for three minutes if it fails this time.
lark.h.log.PutF["%g: Automatic load at %t\n", IO.rope[lark.addressRope], 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.addressRope]];
};
}.
May 6, 1983 7:04 pm, LCS, created from LarkCommImpl.mesa
December 22, 1983 1:45 pm, LCS, Cedar 5
Swinehart, May 15, 1986 5:12:18 pm PDT
Cedar 6.1
changes to: DIRECTORY, IMPORTS, NoteEvents