// SwatFailSysB.bcpl -- exception handlers of all sorts // companion file is SwatFailSysA.asm // Copyright Xerox Corporation 1979, 1982 // Last modified March 29, 1982 1:36 AM by Boggs // FailSys is a package for handling errors in an orderly way, // like LISP's errorset. // Typical use: // SetFailPt(restore) // ... // ... critical section ... // ... // UnSetFailPt() // ... // restore: ... restore invariant ...; FAIL() get "Swat.decl" get "AltoDefs.d" external [ // outgoing procedures InitFailSys; InitInternalTraps TrapHandler; SysErr SetFailPt; UnSetFailPt Fail; ReportFail; ReportBug CheckInterruptSystem; Enable; Disable // incoming procedures from swat ReadFromKeys; AllocatorWarning ParityError; SwatTrap; SwatInterrupt PrintError; PutTemplate; Ws; DisplayState OsFinish; CallSwat; InLd; OutLd // incoming procedures from OS Allocate; CreateDiskStream; Usc CallersFrame; GotoLabel; ReturnTo EnableInterrupts; DisableInterrupts; StartIO // outgoing statics failAC2 //incoming statics sysZone; lvUserFinishProc; lvSysErr; lvAbortFlag; dsp; debugFlag ] manifest [ swatTrapNo = 37b lenFailPtStack = 16 swatInterruptLevel = 8 //must agree with SysInternals.d ] static [ failPtStack // stack of fail points currFailPt // current fail point failAC2 // stack to use when failing argVec // see SysErr TeleInLd; TeleOutLd shouldBeActive // what should be in activeInterrupts ] //---------------------------------------------------------------------------- let InitFailSys() be //---------------------------------------------------------------------------- [ //TeleSwat.asm redefines InLd and OutLd. The old definitions for disk world // swapping are pointed at by OS top statics. We need these, of course! let topStatics = @176777b TeleOutLd = OutLd; OutLd = topStatics!35b TeleInLd = InLd; InLd = topStatics!36b // Init fail point mechanism failPtStack = Allocate(sysZone, lenFailPtStack) currFailPt = -2 ] //---------------------------------------------------------------------------- and SetFailPt(label) be //---------------------------------------------------------------------------- [ currFailPt = currFailPt +2 if currFailPt ge lenFailPtStack then [ Ws("FailPtStack overflow -- Inform Swat service man.*n") return ] failAC2 = CallersFrame() failPtStack!currFailPt = failAC2 failPtStack!(currFailPt+1) = label ] //---------------------------------------------------------------------------- and UnSetFailPt() be //---------------------------------------------------------------------------- [ if currFailPt ls 0 then [ Ws("FailPtStack underflow -- Inform Swat service man.*n") currFailPt = 2 ] currFailPt = currFailPt -2 failAC2 = failPtStack!currFailPt ] //---------------------------------------------------------------------------- and Fail() be //---------------------------------------------------------------------------- [ // May come here with interrupts off. So turn them back on. StartIO(3) //smash off the ethernet Enable() if currFailPt ls 0 then [ Ws("Fail called but FailPtStack empty -- Inform Swat service man*n") return ] ReadFromKeys() UnSetFailPt() GotoLabel(failPtStack!(currFailPt+2), failPtStack!(currFailPt+3)) ] //---------------------------------------------------------------------------- and ReportFail(str) be [ PutTemplate(dsp, "$S*N", str); Fail() ] //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- and ReportBug(str) be //---------------------------------------------------------------------------- [ PutTemplate(dsp, "$S -- Inform Swat service man*n", str); Fail() ] //---------------------------------------------------------------------------- and InitInternalTraps() be //---------------------------------------------------------------------------- // This code ambushes all the ways Swat could escape to itself or the O.S. // It must be called before entering SwatMain, but after installing Swat. [ @lvAbortFlag = @lvAbortFlag +1 @lvSysErr = SysErr OsFinish = FinishTrap shouldBeActive = @activeInterrupts test debugFlag ifso [ let topStatics = @176777b topStatics!35b = TeleOutLd topStatics!36b = TeleInLd ] ifnot [ interruptVector!swatInterruptLevel = SwatInterrupt //keyboard // When you say to the Exec "Resume Swat", it reaches into swat, picks // up what would be in trapVector!swatTrapNo, and assumes that that // points to the swat communication table, where it proceeds to refresh // the FPs for Swat and swatee. Swat wants to catch traps and make // them go to 'SwatTrap' in SwatFailSysA, but it must not disturb the // trap vector pointer. So smash the first two words of the scm // (which aren't vital when Swat is in memory) with code to go off // to SwatTrap. let scm = trapVector!swatTrapNo scm!0 = 2401B //jmp @.+1 scm!1 = SwatTrap ] ] //---------------------------------------------------------------------------- and FinishTrap() be ReportBug("Unexpected finish") //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- and TrapHandler() be //---------------------------------------------------------------------------- // catch swat traps (jumps to low core, parity errors, etc.) [ let tloc = @trapPC-1 test tloc!0 eq 77401B ifso // A parity error occured [ @displayListHead = tloc!6 let f(x) = @x ParityError(tloc, f) for i = 1 to 400 do for j = 1 to 400 loop // let him read it @activeInterrupts = shouldBeActive Enable() ] ifnot [ PutTemplate(dsp, "Internal Trap at location $UO*N", tloc) DisplayState() ] Fail() ] //---------------------------------------------------------------------------- and SysErr(arg1, errNo, arg2, arg3, arg4, arg5; numargs na) be //---------------------------------------------------------------------------- [ test errNo eq 1205 //not enough space for disk stream ifso //Bleahhhh [ AllocatorWarning() ReturnTo(CreateDiskStream+5) //skip store of numargs ] ifnot [ let t = arg1; arg1 = errNo; errNo = t argVec = lv arg1 PrintError(dsp, "Sys.errors", SysErrFetch) ReportBug("Internal Swat Trap") ] ] //---------------------------------------------------------------------------- and SysErrFetch(arg) = Usc(arg, 10) ls 0? argVec!arg, @arg //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- and CheckInterruptSystem(resetit) be //---------------------------------------------------------------------------- [ if @activeInterrupts eq shouldBeActive return Ws("Swat's interrupt is system screwed up!*N") if resetit then [ Disable() @activeInterrupts = shouldBeActive Enable() ] ] //---------------------------------------------------------------------------- and Enable() be //---------------------------------------------------------------------------- [ let temp = @activeInterrupts @activeInterrupts = 0 EnableInterrupts() @wakeupsWaiting = 0 @activeInterrupts = temp ] //---------------------------------------------------------------------------- and Disable() be DisableInterrupts() //----------------------------------------------------------------------------