Trailing-Edge
-
PDP-10 Archives
-
AP-D543V_SB
-
clock1.mac
There are 14 other files named clock1.mac in the archive. Click here to see a list.
TITLE CLOCK1 - CLOCK, CONTEXT SWITCHING, AND JOB STARTUP AND STOP ROUTINES - V131047
SUBTTL APRINT TH/CHW/RCC/PFC/JE/DAL/EVS 24 OCT 78
SEARCH F,S
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VCLOCK1,131047
; PUT VERSION NUMBER IN GLOB LISTING AND LOADER STORAGE MAP
ENTRY CLOCK1 ;ALWAYS LOAD CLOCK1 IF LIBRARY SEARCH
CLOCK1:
;THIS SERVICE ROUTINE RUNS ON A HIGH PRIORITY CHANNEL
;AND REQUESTS INTERRUPTS ON LOWER CLK CHANNEL
;FOR SCHEDULING JOBS AND ERROR HANDLING THAT THE USER
;IS NOT ENABLED TO HANDLE HIMSELF
EXTERNAL .C0NJD,.C0ADR,.C0AEF,.C0APC,.C0JOB,.C0PC,.C0SCF,.C0UPT
EXTERNAL .C0S17,.C0CDB,.C0NPD
EXTERNAL .CPDUI
EXTERNAL .CPABC,.CPABA,.CPADR,.CPAEF,.CPAPC,.CPCHL,.CPCKF
EXTERNAL .CPCN1,.CPCON,.CPDTO,.CPJOB,.CPLJR
EXTERNAL .CPLST,.CPLUC,.CPNAP,.CPNJD,.CPNJE
EXTERNAL .CPNXJ,.CPPLT,.CPREL,.CPRUA,.CPSCF,.CPTMF,.CPTOS,.CPUPT
EXTERNAL .CPEEB,.CPEME,.CPIEF,.CPILM
EXTERNAL .CPUEH
EXTERNAL TIME,XI.RQC
EXTERNAL JOBTPC,JOBCNI,JOBAPR,JOBD15
EXTERNAL JBTNAM,JOBINT,CPOPJ1
EXTERNAL APRILM,COMMAN,CONMES,DEVCHK,DEVSRC
EXTERNAL CRSHWD,CRASHX
INTERNAL FTCHECK,FTMONP,FTMEMPAR,FTLOGIN
IFN FTCHECK+FTMONP,<
EXTERNAL DATA,DAMESS,UUO0,CLOCK
INTERNAL UUO1
>
IFE FTCHECK+FTMONP,<
INTERN CLOCK,DAMESS
EXTERN CIPWTM
$LOW
DAMESS: ASCIZ /-Jan-/
CLOCK: POINT 36,CIPWTM,35 ;BYTE POINTER TO CLOCK REQ QUEUE
$HIGH
>
;SUBROUTINE TO SERVICE APR INTERRUPTS (AND MEM PARITY)
;THIS IS CPU INDEPENDENT - CALLED FROM COMMON
;FOR SPEED, NO ACS SAVED EXCEPT P,P4
;CALL: MOVEI P4,ADR OF CPU DATA BLCK
; PUSJP,APRSU
; ALWAYS RETURN HERE
;THE CODE IS ORGANIZED SO THAT:
; 1. CLOCK INTERRUPTS ARE FASTEST
; 2. TRAPS TO USERS ARE NEXT FASTEST
; 3. MORE SERIOUS ERRORS ARE LAST
;THE ORDER OF RECOGNIZING INTERRUPTS IS MUCH DIFFERENT:
; 1. FIRST MEM PARITY IS CHECKED FOR - SINCE POTENTIALLY CATASTROPHIC
; AND ANY OTHER ERRORS COULD ERRONEOUSLY COME UP AT THE SAME TIME.
; 2. THEN CLOCK
; 3. FINALLY ALL OTHER INTERRUPTS
;FATAL AND CPU DEPENDENT ERRORS ARE FILTERED OUT BEFORE CALLING APRSUB
; THESE INCLUDE POWER FAIL AND (IO PAGE FAIL - KI10) AND ADDRESS BREAK
INTERN FTMEMPAR,FTRTTRP
INTERN APRSUB,APRER9,APRCK0
APRSUB:
IFN FTMEMPAR,< ;MEM PARITY (HALT IN COMMON IF NOT FEATURE)
IFN FTMEMNXM,<
CONSO @.CPNXM##(P4) ;NON-EXISTENT MEMORY? (AP.NXM OR IP.NXP)
>
XCT .CPMPE##(P4) ;MEMORY PARITY? (CONSZ PI, ON KA-10)
; (CONSZ APR, ON KI-10)
JRST APRPAR ;YES, GO HANDLE
>
IFN FTRTTRP,< ;REAL TIME RTTRP UUO?
SKIPE .CPRTT##(P4) ;ANY REAL TIME INTERRUPTS IN PROGRESS?
PJRST APRCHK## ;YES, GO SERVICE IT PROPERLY
>
;HERE TO CHECK FOR AND SERVICE CLOCK
APRCK0: XCT .CPHCT##(P4) ;NO, HAVE CLOCK INTERRUPT
JRST APRER ;NO, GO CHECK ERROR FLAGS
IFN FTMS,< ;DUAL CPUS
SKPCPU (0); ;YES, IS THIS CPU1?
JRST APRCK1 ;YES, DO NOT DO TIME ACCOUNTING FOR SYSTEM AS WHOLE
>
AOS TIME ;NO, INCREMENT TIME OF DAY FOR SYSTEM
SOS HNGTIM## ;DECREMENT HNGTIM FOR SYSTEM
IFN FTKL10,<
SETOM .CPPTF##(P4) ;INITIALIZE PAGE TABLE PARITY FLAG ONCE/CLOCK TICK
>
APRCK1: AOS .CPUPT(P4) ;UPTIME IS LOADED AS ZERO,AND IS NEVER CLEARED
SETOM .CPTMF(P4) ;FLAG THAT APR CLOCK HAS TICKED
SETOM .CPCKF(P4) ;SET FLAG FOR CLK FORCED INTERRUPT
IFN FTMS,< EXTERNAL .CPOK,.CPOK1
SETOM .CPOK(P4) ;TELL OTHER PROCESSOR THAT ALL IS OK
SOS .CPOK(P4) ;MAKE COUNT -2 IN CASE OF LOST TIME FROM PI'S ABOVE APR
AOS @.CPOK1(P4) ;CHECK IF OTHER PROCESSOR IS ALIVE
> ;END OF FTMS CONDITIONAL
CONO PI,XI.RQC ;REQUEST INTERRUPT ON CLK CHANNEL
XCT .CPIUE##(P4) ;IS USER ENABLED FOR ANY FLAGS(INCLUDING CLOCK)
CAIA
; RH .CPCN1 ALSO MODIFIED EACH TIME A USER RUNS
JRST APRERC ;YES, GO PROCESS TRAP
XCT .CPCCF##(P4) ;NO, CLEAR ONLY THE CLOCK FLAG
; (IN CASE OTHERS ALSO ON)
POPJ P, ;DISMISS INTERRUPT - IF OTHERS ON TOO (RARE)
; THEY WILL INTERRUPT IMMEDIATELY AGAIN
;HERE ON CLOCK FLAG AND IT OR SOME OTHER FLAG IS ON WHICH USERS WANTS
APRERC: EXCH T1,@.CPCHL(P4) ;SAVE T1, GET PC
TLNE T1,(XC.USR) ;IS PC FROM USER MODE ?
JRST APRE1A ;YES, GO GET STATUS
XCT .CPCCF##(P4) ;NO, NOW CLEAR CLOCK FLAG
JRST APRER0 ;GO CHECK IN CASE ALSO A SERIOUS ERROR
;HERE ON USER ENABLED TRAP AND PC IS IN USER MODE
APRE1A: EXCH R,.CPADR##(P4) ;GET STATUS--PICK UP EXEC VIRT. ADR OF JOB DATA AREA
XCT .CPUEH(P4) ;STORE STATUS IN JOB DATA AREA (JOBCNI)
XCT .CPCCF##(P4) ;CLEAR CLOCK FLAG
JRST APRER4 ;GO TRAP TO HIM
COMMENT $
HERE FOR MEMORY PARITY ERROR ANALYSIS
THE FIRST RULE OF THE MEMORY PARITY CHECKER IS NEVER
PROCEED IF THERE IS ANY CHANCE OF THE MONITOR MAKING AN
ERROR USING INFORMATION WHICH IS IN ERROR.
THE SECOND RULE IS TO KEEP THE SYSTEM RUNNING IF ONLY ONE
OR MORE USER JOBS ARE AFFECTED.
FINALLY THE OPERATOR AND THE AFFECTED USERS ARE ALWAYS
INFORMED OF PARITY ERRORS. THE OPERATOR IS GIVEN ENOUGH
INFO ON CTY OR OPR TO RECONFIGURE THE MEMORIES. FIELD SERVICE
CAN OBTAIN ENOUGH INFORMATION BY CONSULTING ERROR LOG
FILE WRITTEN BY DAEMON. IF SYSTEM HALTS DURING
PARITY CHECK, CTY PRINTS MESSAGE INSTEAD OF OPR. DAEMON WILL
FIND PARITY INFO IN CRASHED MONITOR (CRASH.SAV) WHEN SYSTEM IS
RELOADED, PROVIDED OPERATOR FOLLOWS CRASH PROCEDURE.
THE ANALYSIS IS AS FOLLOWS:
IF PAR ERROR PC FROM USER MODE
IF USER ENABLED FOR PAR TRAP AND PRIVILEGED, DISMISS TO HIM
IF PC SAME AS LAST PARITY PC, SET PC TO 0 ( SO PI 7 CAN GET IN)
REQUEST INTERRUPT ON PI 7 TO SWEEP ALL OF CORE
ELSE (ERROR PC FROM EXEC MODE)
IF ADR OF INSTR. IS MONITOR SWEEP LOOP (.CPMPI IN CPU DEPENDENT SUBS)
DISMISS INTERRUPT WITH PC+1 TO MAKE IT SKIP
IF ADR OF INST. IS IN CHANNEL MEM PARITY STATISTICS ROUTINE
DISMISS INTERRUPT - NOT SERIOUS
IF ADR OF INST. IS MONITOR USER-AREA BLT (BLTINS IN CORE1)
SET FLAG FOR ERROR IN JOB (JS.PEF)
IF BAD WORD IS IN JOB DATA AREA, SET BIT (JS.JDP) TO CLEAR JOBDAT AT PI 7
IF ANY PIS IN PROGRESS OR PC SAME AS LAST PARITY PC
SWEEP CORE AT APR PI LEVEL
IF ERRORS IN MONITOR, PRINT CTY+HALT
ELSE REMEMBER THIS PC AS LAST PC
END
DISMISS INTERRUPT
$
;HERE TO DO MEMORY PARITY ANALYSIS
IFN FTMEMPAR,< ;MEMORY PARITY ANALYSIS?
APRPAR::
IFN FTMEMNXM,<
PUSHJ P,SAVE1## ;SAVE P1
MOVEI P1,UE.PEF ;ASSUME PARITY ERROR
XCT .CPMPE##(P4) ;IS IT A PARITY ERROR?
JRST APRPA1 ;YES
IFN FTKA10!FTKI10,<
CONO APR,@.CPNXM##(P4) ;NO, NXM CLEAR NXM FLAG
TRCA P1,UE.PEF+UE.NXM;INDICATE NXM
>;END IFN FTKA10!FTKI10
IFN FTKL10,<
TRC P1,UE.PEF!UE.NXM
>
>
APRPA1:
IFN FTKA10!FTKI10,<
CONO PI,XI.CPE ;CLEAR PARITY ERROR (KA10 + KI10)
>
EXCH T1,@.CPCHL##(P4);SAVE T1, GET INTERRUPT PC
PUSH P,T1 ;SAVE INTERRUPT PC
PUSH P,T2 ;SAVE T2
EXCH R,.CPADR##(P4) ;SAVE R, SETUP ADR OF JOB DATA AREA
IFN FTKL10,<
RDERA T1 ;GET SPECIFIC INFO ON THE FAILURE
TLNE T1,(EA.CHN) ;IS IT FROM A CHANNEL REFERENCE?
JRST APREX1 ;YES, LET CHANNEL ROUTINE HANDLE
MOVE T1,-1(P) ;GET STORED PC
>
PUSHJ P,APRPTS ;GET REAL PC (IN CASE LOWER PRIORITY INT JSR SNUCK IN KI10)
TLNE T1,(XC.USR) ;IS REAL PC IN USER MODE?
JRST APPUSR ;YES, NOT A SERIOUS ERROR
;HERE IF REAL PC IS IN EXEC MODE (THIS MAYBE A SERIOUS ERROR)
TLZ T1,-1 ;CLEAR LH PC FLAGS
CAME T1,.CPMPI##(P4) ;IS INT. FROM PI 7 PARITY SWEEP LOOP?
JRST APPCPE ;NO, GO CHECK OTHER SPECIAL MONITOR ADRS
;HERE WHEN PC IS FROM PI 7 MEM PARITY SWEEP LOOP
AOS @T2 ;ADD 1 TO REAL PC SO INSTR. IN MEM SWEEP
; LOOP WILL SKIP
AOS @T2 ;ADD ANOTHER (SO GET OVER SOJG - ONKJ)
JRST APREX1 ;POP T2 T1, R AND DISMISS INT.
; LOOP WILL SKIP, DISMISS INTERRUPT
;HERE TO CHECK IF PARITY ERROR IN CHANNEL ERROR RECORDING ROUTINE (CHNMPE)
APPCPE:
IFN FTKL10,<
SKIPN .CPTSD##(P4) ;DID THE TRAP ROUTINE SAVE THE DATA?
JRST APPCP1 ;NO-CAPTURE IT NOW
MOVE T1,.CPAPI##(P4) ;GET THE APR PIA
TRO T1,LP.CSF!LP.PAR!LP.SBE ;SAY CLEAR THE FLAGS
CONO APR,(T1)
MOVE T1,.CPPPC##(P4) ;YES-THIS INTERRUPT IS FROM A "HARD"
;TRAP FAILURE,DATA HAS BEEN SAVED AT TIME OF THE TRAP
;WE ARE HERE TO GET PC AT TIME OF TRAP AND HANDLE INTERRUPT
;AS IF TRAP NEVER HAPPENED, IE. CHECK FOR USER TRAP ENABLED,
;SWEEP CORE AND KILL THE USER, ETC.
JRST APPUSR ;AND HANDLE AS A USER ERROR
APPCP1: RDERA .CPAER##(P4) ;SAVE ERA FOR ERROR REPORT
CONI APR,.CPPEF##(P4) ;SAVE APR FLAGS
PUSH P,T3 ;SAVE T3
PUSH P,T4 ;SAVE T4
MOVE T3,[100000,,0] ;GET FUNCTION FOR SBDIAG IN T3
SBDIAG T3 ;DO IT
DMOVEM T3,.CPPSB##(P4) ;SAVE SBDIAG FUNCTION 1
MOVE T3,[100000,,1] ;GET FUNCTION
SBDIAG T3 ;READ SBUS
DMOVEM T3,.CPPSB##+2(P4) ;SAVE SBDIAG FUNCTION 2
MOVSI T3,110000 ;SETUP TO CLEAR THE ERRORS IN THE DMA-20
SWPUA ;SINCE WE KNOW WE HAVE AN ERROR EITHER IN
;CACHE OR CORE, WE SWEEP THE CACHE NOW,
;WITH THE APR,ERA,AND DMA STILL FROZEN, TO
;AVOID RECURSIVE FAILURES AS MUCH AS POSSIBLE
CONSZ APR,LP.CSB ;WAIT FOR THE SWEEP TO FINISH
JRST .-1 ;FAILURES WHICH MIGHT OCCUR HERE WILL
;ALL BE DETECTED DURING THE CORE MEMORY SWEEP
;WHICH WILL FOLLOW.
TRNN P1,UE.PEF ;PARITY?
JRST APPCP2 ;YES
PUSH P,T1 ;SAVE T1 FOR A MINUTE
MOVE T1,.CPAPI##(P4) ;GET THE APR PIA
TRO T1,LP.CSF!LP.PAR!LP.SBE ;SAY CLEAR THE FLAGS
CONO APR,(T1)
POP P,T1 ;GET T1 BACK
SKIPA ;GO ON
APPCP2:: CONO APR,@.CPNXM##(P4) ;CLEAR NXM FLAG
SBDIAG T3 ;NOW CLEAR THE DMA WITH THE FUNCTION WE SET UP ABOVE
POP P,T4 ;RESTORE T4
POP P,T3 ;RESTORE T3
>;END FTKL10
CAIL T1,CHNIN1## ;BELOW FIRST BLT IN CHNMPE ROUTINE
CAILE T1,CHNIN2## ;NO, ABOVE LAST BLT IN CHNMPE ROUTINE
SKIPA ;YES, NOT IN CHNMPE ROUTINE - CHECK OTHER ADRS
JRST APREX1 ;NO, JUST DISMISS INT. THIS IS NOT SERIOUS
; CHANNEL ROUTINE CAN REQUEST SWEEP
;HERE TO CHECK IF EXEC MODE PC IS FROM BLT OF USER CORE
IFN FTLOCK,< ;LOCK UUO FEATURE
CAIN T1,LOKINS## ;EXEC PC = ADR OF BLT OF USER CORE ON LOCK UUO?
JRST APPBLT ;YES, SEE IF IN JOB DATA AREA
>
CAIE T1,BLTINS## ;NO, EXEC PC = ADR OF BLT OF USER CORE?
JRST APPSAM ;NO, SEE IF SAME PC OR PI'S IN PROGRESS
;HERE ON PARITY ERROR DURING BLT OF USER CORE
XP BLTAC,P1 ;AC USED IN BLT INSTR. - GET MUL DEF
; GLOBAL IF DO NOT AGREE WITH CORE1 MODULE
APPBLT: MOVE T2,.CPLSB##(P4) ;JOB OR HIGH SEG NO BEING BLTED
HLRZ T1,BLTAC ;GET SOURCE MOVE SO FAR FROM BLT AC POINTER
SUB T1,JBTADR(T2) ;SUBTRACT ORIGIN OF SOURCE
TLZ T1,-1 ;CLEAR OUT GARBAGE (-PROTECTION)
MOVEI T2,JS.MPE!JS.APE ;JOB HAS A MEM PARITY STATUS BIT AND APR ERROR
;USED ON PI 7 TO PRINT MESSAGE FOR JOB
IFN FTMEMNXM,<
TRNE P1,UE.NXM ;WAS IT REALLY NXM?
TRC T2,JS.MPE+JS.NXM;YES, INDICATE NXM INSTEAD
>
CAIG T1,JOBPFI##+3 ;IS BAD WORD IN PROTECTED PART OF JOB DATA AREA?
; (BLT POINTER STOPS 1(KA10)3(KI10) BEYOND ERROR)
TRO T2,JS.JDP ;YES, FLAG JOB DATA AREA PARITY ERROR
; SO JOB DATA AREA WILL BE CLEARED AT PI 7
; SINCE MONITOR ADDRESSES ARE NO LONGER VALID
IFN FTMEMNXM,<
TRNN P1,UE.PEF ;PARITY ERROR?
TRZ T2,JS.JDP ;NO, DON'T ATTEMPT TO CLEAR JOBDAT SINCE IT
; MAY BE IN NON-EXISTENT MEMORY
>
HRRZ T1,.CPLSB##(P4) ;JOB OR HIGH SEG NO. OF SEG BEING BLTED
IFN FT2REL,<
CAIG T1,JOBMAX## ;IS THIS A HIGH SEG BEING BLTED?
>
IORM T2,JBTSTS##(T1) ;NO, SET JOB ERROR BITS
JRST APPRSC ;GO REQUEST PI 7 SWEEP OF CORE (OK FOR
; PI 7 TO BE IN PROGRESS - CORE COMMAND)
; (NO INTERVENING PIS BETTER BE IN PROGRESS
; ELSE CAN NEVER DISMISS TO PI 7)
;DO NOT FLAG CURRENT JOB, SINCE MAY NOT
; BE THE JOB BEING SHUFFLED
;HERE ON EXEC PARITY IN NO SPECIAL PLACE - CHECK FOR SAME AS LAST INTERRUPT
APPSAM: MOVE T1,-1(P) ;GET ALL OF STORED PC INCLUDING FLAGS
CAMN T1,.CPLPP##(P4) ;SAME PC AS LAST ON REQUEST TO PI 7?
JRST APPSWP ;YES, HAVE TO SWEEP AT APR PI THEN
; (PARITY ERROR AT UUO LEVEL IN MONITOR ON INSTR. FETCH
; OR INSTR OR INDIRECT AT PI LEVEL)
;HERE IF EXEC MODE PC IS NOT IN ANY OF THE SPECIAL PLACES IN MONITOR OR SAME PC
CONSO PI,@.CPNAP##(P4) ;ARE ANY PI'S (BELOW APR) IN PROGRESS?
JRST APPRS1 ;NO, GO REQUEST PI 7 SWEEP OF CORE
; FLAG CURRENT USER TO BE STOPPED SINCE DOING HIS UUO
;HERE IF IT IS NECESSARY TO SWEEP CORE AT APR LEVEL TO FIND BAD ADRS.
; FOR FEAR OF DISMISSING AND THE MONITOR PROCEDING WITH DATA
; THAT IS POSSIBLY IN ERROR DUE TO THE BAD PARITY
APPSWP: MOVE T1,-1(P) ;GET STORED PC
PUSHJ P,APRPTS ;GET REAL PC
MOVEM T1,.CPAPC##(P4) ;STORE SO SWEEP ROUTINE WILL KNOW
; WHERE PC IS IN CASE NO PARITY FOUND
; ON SWEEP - SERIOUS IF EXEC MODE
MOVEI T1,.CPA00##(P4) ;FIRST ADR. OF PARITY SWEEP SAVE AC AREA
BLT T1,.CPA17##(P4) ;SAVE ALL ACS IN CDB BLOCK
HLLZ S,.CPMPS##(P4) ;REQUEST CPU SWEEP, SO JOBS WILL BE FLAGGED
; TO STOP
IFN FTMEMNXM,<
TRO S,(P1) ;FLAG WHETHER NXM OR PARITY SWEEP
>
IFN FTKL10,<
PUSHJ P,SVPPC## ;SAVE PROTOCOL, ENTER SECONDARY
>
PUSHJ P,PARSW1## ;CALL USUAL PI 7 ROUTINE TO SWEEP CORE
;(DO NOT PRINT ANY INFO)
TLZ S,(CP.PSX) ;CLEAR REQUEST TO SWEEP - SINCE ALREADY
; SWEPT AT APR PI
IORM S,.CPAEF##(P4) ;STORE PRINT REQUEST FOR PRINT ROUTINE
; SO IT WILL NOT THINK CHAN FOUND ERROR
PUSHJ P,PARCTY## ;IF ANY SERIOUS ERRORS OR NONE, PRINT ON CTY+HALT
; RETURN IF NOT SERIOUS OR OPER PUSHES CONTINUE
; NOT RECOMMENDED SINCE MONITOR WILL
; PROBABLY HAVE BAD DATA
MOVSI 17,.CPA00##(P4) ;RESTORE ALL ACS FROM CDB BLOCK
BLT 17,17 ;
HLLZ T1,.CPAEF##(P4) ;SWEEP AND PRINT REQUEST BITS FOR THIS CPU
JRST APPRS2 ;GO REQEUST PI 7 TO PRINT (NO SWEEP)
; DO NOT FLAG CURRENT USER WITH ERROR
;HERE ON PARITY ERROR WHEN PC REALLY IN USER MODE - T1 HAS REAL PC, R=JOBDAT
APPUSR: EXCH J,.CPJOB##(P4) ;SAVE AC J - GET CURRENT JOB NO.
MOVE T2,.CPCN1##(P4) ;USER ENABLED APR AND PI TRAPS
IFE FTMEMNXM,<
TRNN T2,UE.PEF ;IS HE ENABLED TO TRAP ON THESE?
>
IFN FTMEMNXM,<
TRNN T2,(P1) ;ENABLED FOR NXM OR PARITY ERROR?
>
JRST APPRS0 ;NO, REQUEST PI 7 SWEEP OF CORE
MOVE T2,JBTSTS##(J) ;YES, JOB STATUS WORD
TLNE T2,JACCT ;IS JOB PRIVILEGED?
JRST APPPET ;YES, ALLOW PARITY ERROR TRAP
MOVE T2,JBTPPN##(J) ;JOB PROJECT-PROGRAMMER NO.
CAME T2,FSFPPN## ;IS IT THE OPERATOR PROJ-PROG?
JRST APPRS0 ;NO, DON'T ALLOW TRAP, GO REQUEST SWEEP
;HERE TO TRAP TO PRIVILEGED, ENABLED USER - (J SET TO JOB NO, T1 TO REAL PC, R=JOBDAT)
APPPET: EXCH J,.CPJOB##(P4) ;RESTORE J, JOB NUMBER
IFE FTMEMNXM,<
MOVEI T2,UE.PEF ;JOBENB UUO PARITY DONE FLAG
MOVEM T2,JOBCNI##(R) ;STORE PSEUDO PROCESSOR FLAGS FOR USER OR ERRCON
>
IFN FTMEMNXM,<
MOVEM P1,JOBCNI##(R) ;STORE PSEUDO-PROCESSOR FLAG FOR USER OR ERRCON
TRNN P1,UE.PEF ;A PARITY ERROR?
AOSA .CPUEN##(P4) ;NO, NXM BUMP COUNT OF USER ENABLED NXM'S
>
AOS .CPUEP##(P4) ;INCREMENT COUNT OF USER ENABLED PAR ERRORS
; ON THIS CPU
; TO LOOK AT IN HIS INTERRUPT ROUTINE
MOVE T1,-1(P) ;GET STORED PC (SO CAN COMPUTE POINTER WHERE
; REAL PC IS STORED (T2 IN APRPTS)
JRST APRE4A ;HANDLE TRAPS TO USER (T1 HAS STOPPED PC FOR APRPTS)
> ;END FTMEMPAR
;HERE IF APR INTERRUPT, BUT NOT CLOCK
APRER: EXCH T1,@.CPCHL(P4) ;SAVE T1, GET TRAP PC
TLNN T1,(XC.USR) ;INTERRUPT PC IN USER MODE?
APRER0: CONSZ APR,@.CPILM(P4) ;WAS ERROR ILM, IF SO MUST BE FROM USER
; EVEN IF PC IN EXEC MODE - SEE APRPTS
JRST APRER3 ;ERROR WAS USER GENERATED
CONSZ APR,@.CPEME(P4) ;DOES EXEC CARE ABOUT ERROR?
JRST APRER9 ;YES, GO HANDLE IT
AOS .CPEDI##(P4) ;COUNT NO OF EXEC DON'T-CARE INTERRUPTS (AOV,FOV)
; HAPPENS ONLY IF USER IS ENABLED WHEN MONITOR
; CAUSES CONDITION
HRLM T1,.CPEDI##(P4) ;STORE OFFENDING PC SO WE CAN FIX CODE -
; SINCE THIS SLOWS DOWN SYSTEM
JRST APRER1 ;NO, CLEAR PC FLAGS, RESTORE T1, CLEAR APR AND DISMISS
;HERE IF ERROR GENERATED BY USER
APRER3: XCT .CPIUE##(P4) ;USER ENABLED FOR THIS ERROR?
JRST APRER6 ;NO, STOP USER AND PRINT ERROR MESSAGE
;HERE TO TRAP TO USER - NOT CLOCK OR MEM PARITY
EXCH R,.CPADR(P4) ;SAVE AC R, GET CURRENT JOB ADDR. ON THIS CPU
XCT .CPUEH(P4) ;CONI APR TO JOB DATA AREA (JOBCNI)
; INCLUDE THE CLOCK FLAG
;HERE TO TRAP TO USER ON CLOCK - R SET TO EVA OF USER JOB DATA AREA
APRER4: PUSH P,T1 ;SAVE T1 AND T2
PUSH P,T2
;HERE TO TRAP TO USER ON MEM PARITY, R SET TO EXEC VIRT ADR OF JOB DATA AREA,
; T1 TO STORED PC
APRE4A: PUSHJ P,APRPTS ;GET POINTER TO REAL USER MODE PC
MOVEM T1,JOBTPC(R) ;STORE ERROR PC
HRR T1,JOBAPR##(R) ;GET USER TRAP ADDRESS
CAMN T1,JOBTPC##(R) ;IS INT FROM FIRST INSTR IN HIS TRAP
; ROUTINE?
JRST APRRS3 ;YES, GO STOP USER IF SAME INT PC
; AS LAST, SET PC = 0 SO PI 7 CAN INT.
HRRI T1,1(T1) ;INCREMENT TRAP ADR BY 1
CAMN T1,JOBTPC##(R) ;SAME AS PC STORED BY INT?
JRST APRRS3 ;YES, STOP JOB-INT FROM USER INT
; ROUTINE-MEM PAR ALWAYS INCREMENTS PC
; SO COULD BE IN A LOOP
;HERE IF NO POSSIBILITY OF A SYSTEM LOOP CAUSED BY FIRST INSTR.
; IN USER TRAP ROUTINE GIVING AN INT. ON INSTR. FETCH (BEFORE PI7 CAN INT.)
APRE4C: HRR T1,JOBENB(R) ;GET SAVED SOFTWARE ENABLE FLAGS
TRNE T1,XP.DDU ;DOES USER WANT TRAPS DISABLED WHENEVER ONE OCCURS?
JRST APRE4B ;NO, GO DISABLE CLOCK ONLY
;HERE TO DISABLE ALL USER ENABLED INTERRUPTS
HLLZS JOBENB(R) ;CLEAR SOFTWARE FLAGS SO THAT USER MUST DO
; ANOTHER APRENB UUO IN ORDER TO ENABLE TRAPS
SETZM .CPCN1(P4) ;ALSO CLEAR USER APR CONSO FLAGS
HRRI T1,@.CPEEB(P4) ;AND SET MONITOR TO CHECK ONLY
HRRM T1,.CPCON(P4) ;PD OVF,ILM,NXM, AND CLOCK AND ADDRESS BREAK
HRR T1,.CPDUI(P4) ;GET APR CONO MASK
HRRZM T1,.CPLUC(P4) ;STORE FOR INTERRUPT LEVEL USE
CONO APR,(T1) ;DISABLE FOV, AROVF IN CASE ON
; SO USER MUST REENABLE WITH APRENB UUO
APRE4B: TRZN T1,XP.CCF ;ALWAYS DISABLE CLOCK INTERRUPT
JRST APRER5 ;BECAUSE USER CANNOT CONTROL ITS
HRRM T1,JOBENB(R) ;COMING AND COULD INTERRUPT HIS OWN
ANDM T1,.CPCN1(P4) ;INTERRUPT PROCESSOR WITHOUT MEANING TO.
APRER5: HRR T1,JOBAPR(R) ;GET USER TRAP ADDRESS
MOVEM T1,@T2 ;SET UP USER TRAP FROM DISMISS
; (IF ILM - COULD POINT TO LOWER PI JSR PC)
APREX1: EXCH R,.CPADR(P4) ;RESTORE JOB ADDRESS AND AC R
POP P,T2 ;RESTORE T1
POP P,T1 ;RESTORE T2
JRST APRER1 ;GO CLEAR PC FLAGS AND DISMISS APR INTERRUPT
;HERE WHEN USER TRAP ROUTINE HAS LOOP (PC=FIRST OR SECOND ADR)
; MEM PARITY OR OTHER USER ENABLED TRAP.
APRRS3:
MOVE T1,JOBCNI##(R) ;APR CONI BITS ALREADY STORED FOR USER
TRNN T1,UE.PEF+IFN FTMEMNXM,<UE.NXM> ;IS THIS A MEM PARITY ERROR?
JRST APRE6A ;NO, JUST STOP JOB
IFN FTMEMPAR,< ;MEMORY PARITY ANALYSIS?
;HERE ON USER PARITY ERROR - T1 = REAL PC
;FLAG CURRENT USER THIS CPU AS HAVING ERROR AND HAVE TO BE STOPPED
APPRS1: EXCH J,.CPJOB##(P4) ;GET CURRENT JOB NO, SAVE J
APPRS0: MOVEI T2,JS.MPE!JS.APE ;JOB MEM PAR ERROR AND APR ERROR
IFN FTMEMNXM,<
TRNN P1,UE.PEF ;A PARITY ERROR?
TRC T2,JS.MPE+JS.NXM;NO, INDICATE NXM
>
IORM T2,JBTSTS(J) ;FLAG JOB TO GET PARITY MESSAGE
EXCH J,.CPJOB##(P4) ;RESTORE J, SAVE JOB NO.
MOVE T1,-1(P) ;STORED PC
PUSHJ P,APRPTS ;GET REAL PC = T1, ADR OF PC = T2
CAMN T1,.CPLPP##(P4) ;IS REAL PC SAME AS LAST PC?
JRST APRE6A ;YES, CLEAR PC TO 0, SO CAN DISMISS TO PI7
; MUST BE MEM PAR ON INSTR. FETCH
;HERE TO REQUEST SWEEP OF CORE AT PI 7 TO FIND ALL BAD PARITY WORDS
; R=JOB DATA AREA PROPER JOB ERROR BIT ALREADY SET (IN CASE PAR NOT IN CURRENT JOB)
APPRSC: HLLZ T1,.CPMPS##(P4) ;GET SWEEP REQUESTED BY CPU N (THIS CPU) BITS
; (CP.PXX+CP.RSX)
IFE FTMEMNXM,<
TRO T1,UE.PEF ;PSEUDO PARITY ERROR FLAG FOR APR CONI
>
IFN FTMEMNXM,<
TRO T1,(P1) ;SET PUEUDO PARITY OR NXM FLAG
>
APPRS2: IORM T1,.CPAEF##(P4) ;SET FLAG FOR PI 7 TO SEE PAR ERROR
; AND CALL PARITY SWEEP ROUTINE
MOVEM T1,.JBCNI##(R) ;STORE ERROR FLAGS IN JOB DATA AREA
; (IN CASE THIS IS CPU1 - CAN'T PRINT UNTIL ON CPU0)
MOVE T1,-1(P) ;GET STORED PC
PUSHJ P,APRPTS ;GET REAL PC AGAIN (MAYBE DIFF ON KI10)
SKIPE .CPTSD##(P4) ;WAS THIS INTERRUPT CAUSED BY A HARD TRAP
;FAILURE ON A KL10?
MOVE T1,.CPPPC##(P4) ;YES, GET THE REAL INTERRUPT PC
SETZM .CPTSD##(P4) ;CLEAR THE INTERLOCK FLAG
MOVEM T1,.CPMPP##(P4) ;STORE MEM PAR PC FOR PI7
MOVEM T1,.CPLPP##(P4) ;REMEMBER THIS PC AS LAST PC
; CLEARED WHEN PI7 SWEEP FINISHED
; USED TO DETECT WHEN PI7 IS NOT GETTING INTERRUPT
; WHEN APR DISMISSES (PAR ON INSTR. FETCH)
JRST APRE6B ;STORE ERROR PC AND REQUEST PI 7
; DO NOT CLEAR PC SINCE CHECK WILL BE
; MADE ON NEXT INTERRUPT FOR EXEC OR USER
; DISMISS LOOP - SEE .CPLPP
> ;END FTMEMPAR
;HERE IF CURRENT JOB IS TO BE STOPPED
APRER6: EXCH R,.CPADR(P4) ;GET JOB ADDRESS SAVE R
PUSH P,T1 ;SAVE T1 (CONTAINS PC WORD)
PUSH P,T2 ;SAVE T2
PUSHJ P,APRPTS ;GET POINTER TO USER MODE PC
XCT .CPUEH##(P4) ;SET UP FLAG TO CLOCK LEVEL (CONI APR,JOBCNI)
; NOTE: DO NOT STORE IN .CPAEF, SINCE MAYBE CPU1.
; SINCE JS.APE IS SET, ERROR WILL BE CAUGHT JUST
; BEFORE RUNNING THE USER
;HERE TO STOP USER ELSE HE IS IN A SYSTEM LOOP (FIRST INSTR. IN HIS
; INTERRUPT ROUTINE CAUSES INTERRUPT BEFORE PI7 CAN GET IN)
APRE6A: MOVSI T1,(XC.USR) ;DISMISS TO USER 0
EXCH T1,@T2 ;WHENEVER PC REACHES CLOCK LEVEL (MAYBE -1(P))
APRE6B: MOVEM T1,.CPAPC(P4) ;STORE PC FOR ERROR REPORTING
MOVEM T1,JOBTPC(R) ;STORE ERROR PC FOR USER TO LOOK AT
MOVEI T2,JS.APE ;GET ERROR BIT
EXCH J,.CPJOB(P4) ;GET JOB NO. OF JOB ON THIS CPU
IORM T2,JBTSTS(J) ;SET ERROR BIT IN STATUS WORD
IFN FTMS,< ;DUAL PROCESSOR?
PUSHJ P,CP1APE## ;MAKE SURE JOB CAN RUN ON CPU0 SO
; ERROR MESSAGE WILL PRINT
>
EXCH J,.CPJOB(P4) ;RESTORE J
EXCH R,.CPADR(P4) ;RESTORE R
APREX3: POP P,T2 ;RESTORE T2
POP P,T1 ;RESTORE T1 (PC WORD - MAY HAVE CHANGED)
JRST APRER8 ;REQUEST CLK INT, CLEAR FLAGS AND DISMISS
;EXIT - APR ERROR IN EXEC MODE - MAY BE SERIOUS
APRER9: XCT .CPEEH##(P4) ;STORE APR STATUS FOR PI 7 PROCESSING
; BY CPU0 OR CPU1
MOVEM T1,.CPAPC##(P4) ;STORE ERROR PC FOR PI 7 TO FIND
IFN FTHALT,<
CONSZ PI,@.CPNAP##(P4) ;ANY PIS IN PROGRESS (NOT APR)
STOPCD .+1,STOP,POP, ;++PI ON PROGRESS
> ;CONTINUE WILL TRY THOUGH
;DO NOT CLEAR PC TO IMPROVE CHANCES
; OF GETTING TO PI 7 LEVEL. ONLY CASE
; CLEARING PC WOULD HELP IS NXM ON INSTR. FETCH
;(EXEC MODE MEMORY OFF-LINE OR WILD TRANSFER)
; IN THIS CASE SYSTEM WILL LOOP ON CONTINUE
;EXIT - REQUEST PI 7 INTERRUPT AND RESCHEDULE (STOP) CURRENT USER
APRER8: SETOM .CPCKF##(P4) ;SET FLAG FOR CLK (PI 7) INTERRUPT
SETOM .CPSCF##(P4) ;FORCE RESCHEDULING EVEN IF ERROR
; IS IN MONITOR
CONO PI,XI.RQC ;REQUEST CLK (PI 7) INTERRUPT
;EXIT - CLEAR PC FLAGS SO INTERRUPT CAN BE DISMISSED
APRER1: TLZ T1,(XC.OVF+XC.FOV+XC.FUF+XC.NDV) ;CLEAR PC FLAGS
; OVF, FOV, FLOAT UNDERFLOW, NO DIVIDE
APRER2: EXCH T1,@.CPCHL##(P4) ;RESTORE T1, SAVE (NEW) DISMISS PC
CONO APR,@.CPIEF##(P4) ;CLEAR ALL FLAGS EXCEPT CLOCK, PAR
;(PAR ALREADY CLEARED, MIGHT GET ONE IN
; THIS ROUTINE, CLOCK MIGHT LOSE TIME).
POPJ P, ;RETURN AND DISMISS
;SUBROUTINE TO SET UP POINTERS TO REAL PC FOR APR ON THIS CPU
; REAL PC CAN DIFFER FROM STORED PC BY APR JSR IF AN INTERMEDIATE
; LEVEL PI SNEAKS IN ITS JSR
; KA10 - ONLY ILM - THEREFORE REAL PC BETTER BE USER MODE
; KI10 - NXM AND PARITY ERROR - REAL PC EXEC OR USER MODE
; CALLED ON EVERY MEMORY PARITY INTERRUPT
;CALL: PUSH P,T1 ;PC WORD
; PUSH P,T2 ;
; PUSHJ P,APRPTS
; RETURN HERE, C(T1)=REAL ERROR PC
; C(T2)=POINTER TO LOCATION OF SAVED USER MODE PC
; WARNING T2 MAY BE POINTER TO THIS STACK -1(P) AFTER POPJ.
INTERN APRPTS
APRPTS: TLNE T1,(XC.USR) ;INTERRUPT PC IN USER MODE?
JRST APRPT1 ;YES, EASY TO SET UP
CONI PI,T1 ;GET PI'S CURRENTLY IN PROGRESS
ANDI T1,@.CPNAP(P4) ;EXCEPT APRCHANNEL
JFFO T1,.+2 ;DETERMINE CHANNEL NUMBER
JRST APRPT0 ;IF NO PIS IN PROGRESS, THEN STORED PC
; IS REAL PC - RETURN IT
LSH T2,1 ;COMPUTE ADDRESS OF JSR
SUBI T2,2*^D20-40 ;FOR THIS CHANNEL
ADD T2,.CPTOS(P4) ;0 OR 100 FOR TRAP OFF SET
HLRZ T1,(T2) ;GET INSTRUCTION FROM PI LOCATION
ANDI T1,777000 ;JUST GET OPCODE
CAIE T1,(JSR) ;IS THIS A JSR?
AOS T2 ;MUST BE BLKI(O), GO TO 41+ZN
MOVE T2,(T2) ;GET "JSR CH'N"
PUSH P,(T2) ;SAVE POSSIBLE REAL PC FOR RET IN T1
HRRZ T1,-3(P) ;GET STORED APR PC
CAIN T1,1(T2) ;IS APR STORED PC ONE AFTER CH'N?
JRST TPOPJ## ;YES, THEN JSR HAD JUST SNUCK IN - RET REAL PC IN T2
POP P,T2 ;NO, LIKELY ON MEMPAR (ALWAYS WHEN FROM SWEEP AT PI7
;HERE IF PC STORED BY APR JSR IS REAL PC WHICH CAUSED APR INTERRUPT
APRPT0: MOVE T1,-2(P) ;RETURN STORED PC AS REAL PC
APRPT1: HRLOI T2,P ;POINT TO SAVED APRCHL PC ON PUSH DOWN STACK
POPJ P, ;RETURN (NOW REAL PC IS AT -1(P)).
;HERE FROM KASER OR KISER WITH THE ACS SAVED IF APPROPRIATE
; I.E., ALWAYS ON A KA10, ONLY IF THE PC IS IN EXEC MODE ON THE KI10
CHKAPE::
IFN FTPI,<
SETZM CK0CHL## ;SO PSISER WON'T FIND THE NULL JOBS PC
>
IFN FTVM,<
SETOM .C0ISF## ;FLAG IN THE SCHEDULAR
>
IFN FTMS,< EXTERNAL SVMES,SVTYPE
SKIPE SVMES ;DOES THE SLAVE NEED A MESSAGE TYPED OUT
PUSHJ P,SVTYPE ;YES, GO TYPE IT OUT
>
MOVEI P4,.C0CDB ;GET CDB OFFSET FOR THIS PROCESSOR
MOVE S,.CPAEF(P4) ;COMMUNICATION FLAG BETWEEN HIGHER PI LEVELS AND CLK
JUMPE S,RSCHED ;ANY APR OR PARITY ERRORS?
PUSHJ P,APRILM ;YES, GO PROCESS ERROR,APRILM WILL CLEAR .CPAEF
; FLAG IMMEDIATELY
JRST RSCHED ;NOT PDL OV - RESCHEDULE
PUSHJ P,CPUTIM ;CHARGE THE CURRENT USER FOR HIS ACCUMULATED
; CPU TIME INCLUDING THE PDL OVERFLOW
; PROCESSING TIME
JRST CIP6A ;IGNORE 0 CHARGES;CONTINUE SAME JOB
LDB T3,JBYLTM## ;ELSE, GET JOB'S TIME LIMIT
JUMPE T3,CIP6A ;NO LIMIT, CONTINUE SAME JOB
SUB T3,P1 ;REDUCE REMAINING TIME
SKIPG T3 ;IS THERE ANY TIME LEFT?
MOVEI T3,1 ;NO, AMKE NEXT JOB ACC'T'NG FAIL
DPB T3,JBYLTM## ;REPLACE TIME LIMIT WITH NEW
JRST CIP6A ;GO CONTINUE WITH SAME JOB
TSTRS: AOS (P) ;TEST R AND SKIP
TESTR: SKIPE R ;R NON-ZERO? (20-37 WIPED IF NOT)
POPJ P, ;YES, RETURN
STOPCD .+1,DEBUG,NCJ, ;++NO CORE FOR JOB
MOVE R,.C0ADR## ;ATTEMPT RECOVERY
POPJ P,
;HERE AT UUO LEVEL WHEN CURRENT JOB RETURNS TO USER MODE
;FROM A UUO CALL AND EITHER:
; 1. CURRENT JOB TYPED CONTROL C WHILE IN EXEC MODE
; 2. CLOCK FLAG WENT OFF WHILE CURRENT JOB WAS
; IN EXEC MODE
;CALL: MOVE J,CURRENT JOB NUMBER
; PUSHJ P,USCHD1 ;FROM UUOCON(UUO HANDLER RETURN TO USER)
; RETURN HERE WHEN RUNABLE
INTERN USCHD1
USCHD1:
IFN FTMEMPAR,<
TRNN T1,JS.MPE ;MEM PAR AT UUO LEVEL ?
JRST USCHD2 ;NO, GO CHECK FOR ^C.
PUSHJ P,STOP1C ;YES, STOPJOB
JRST USCHED ;STOPPED
USCHD2:
>
TLNE T1,CNTRLC ;^C TYPED WHILE IN MONITOR ?
PUSHJ P,STOP1 ;YES, STOPJOB.
;HERE AT UUO LEVEL FROM MONRET UUO
;SAME CALL AS USCHD1, EXCEPT T1 NOT SETUP
INTERNAL USCHED
EXTERNAL JOBDPG,JOBDPD
USCHED: POP P,.C0PC## ;SAVE PC IN PROTECTED PART OF SYSTEM DATA
PUSHJ P,TESTR ;MAKE SURE R IS SETUP
MOVEM J,JOBDAC##+J(R) ;SAVE CURRENT JOB NUMBER
; NEEDED ON CALL FROM USER UUO EXIT
; SINCE CAN START UP ON EITHER CPU
MOVEM R,JOBDPG(R) ;SAVE R IN DUMP AC AREA
MOVEM P,JOBDPD(R) ;SAVE P
JRST WSCHD2 ;GO SETUP LONGER PDL AND RESCHEDULE
;HERE AT UUO LEVEL WHEN JOB GOES INTO IO WAIT OR SHARABLE DEVICE WAIT
;CALL: PUSHJ P,WSCHED
; RETURN HERE WHEN RUNABLE AGAIN
;ROUTINE TO ALLOW INTERRUPTION OF LONG UUOS
SCDCHK::SKIPN .C0RTF## ;FORCED SCHED
SKIPE .C0CKF## ;OR CLOCK TICK
PJRST WSCHED ;YES, GO SCHED
POPJ P, ;NO, RETURN
EXTERNAL JOBDAC,JOBD16
WSCHED::
MOVEM 17,JOBD17##(R) ;SAVE AC17 IN DUMP ACS (P4 IN NEW ACS)
PUSHJ P,TSTRS ;MAKE SURE R IS SETUP
WSCHD1::PUSHJ P,TESTR ;MAKE SURE R IS SETUP
POP P,.C0PC## ;SAVE PC IN PROTECTED PART OF SYSTEM DATA
MOVEI 17,JOBDAC(R) ;SAVE ACS 0-16 IN DUMP ACS
BLT 17,JOBD16(R) ;IN CURRENT JOB DATA AREA
WSCHD2: MOVE P,.C0NPD## ;NULL JOB PD LIST
;USED TO CALL SCHEDULER AND COMMAND DECODER
; OTHERWISE GET PD OUF
;FALL INTO RSCHED AND RESCHEDULE
MOVEI P4,.C0CDB ; WITH P4 SET UP WITH CDB FOR CPU 0
;SLAVE PROCESSOR ENTERS HERE WITH P4 SET UP TO CPU DATA BLOCK
INTERN FTKCT,RSCHED
EXTERNAL COMCNT,HNGTIM
EXTERNAL PMONTB
RSCHED:
IFN FTVM!FTMS,<
SETOM .CPISF##(P4) ;FLAG IN THE SCHEDULAR
>
IFN FTPI,<
MOVE J,.CPJOB(P4) ;GET CURRENT JOB #
SKIPN .CPTMF(P4) ;DID CLOCK TICK?
JRST NTAPRC ;NOT APR CLOCK
MOVE T2,DATE## ;UNIVERSAL DATE/TIME
SIGNAL C$APRC ;SIGNAL APR CLOCK
EXCTXU <MOVEM T2,IBKISW##(M)> ;STORE FOR USER
>;END FTPI
NTAPRC: PUSHJ P,CPUTIM ;CHARGE USER WITH CPU TIME USED
JRST CIP1 ;DID NOT USE FULL JIFFY
JRST CIP0 ;USED OVER A JIFFY
;TIME ACCOUNTING
;THE VARIOUS TIME TOTALS ACCUMULATED FOR JOBS ARE BASED ON
;UNITS OF JIFFIES (1/60 OR 1/50 SECOND ACCORDING TO LOCAL
;POWER LINE FREQUENCY.) IN ORDER TO USE THE GREATER PRECISION
;OF THE DK10 REAL TIME CLOCK IN A MANNER COMPATABLE WITH
;EXISTING PROGRAMS THAT USE THESE TOTALS, SEPARATE TOTALS OF 10^-5 JIFFIES
;PAST LAST WHOLE JIFFY ARE MAINTAINED. WHEN ONE OF THESE
;TOTALS EXCEEDS A JIFFY WE DECREMENT IT AND INCREMENT
;THE CORRESPONDING JIFFY COUNT.
EXTERN TIME,MIDNIT,THSDAT,TSETBI
CPUTIM: PUSHJ P,TIMEX ;GET TIME IN T1
IFE FTEMRT,<
SKIPN P1,T1 ;TEST FOR 0 (& SAVE TIME IN P1)
POPJ P,
>;END IFE FTEMRT
IFN FTEMRT,<
MOVSI T2,(ST.EMO) ;EXCLUDE MONITOR OVERHEAD?
TDNE T2,STATES## ;SKIP IF NO
PUSHJ P,ACCMOF## ;ITS TO BE EXCLUDED, TURN ACCOUNTING METER OFF
SKIPN P1,T1 ;SKIP IF ANY REAL TIME TO CHARGE
JRST INCTIM ;YES, MUST INCREMENT USER TIME EVEN
; THOUGH REAL TIME WAS NOT A TICK
>;END IFN FTEMRT
CPUTM1:
IFN FTTIME,<
;P1 IS NOW SET UP WITH THE LENGTH OF TIME FOR WHICH THE
;LAST USER RAN, IN JIFFIES *10^-5. ABOVE CODE SHOULD NOT
;BE MADE CONDITIONAL BECAUSE THIS NUMBER MAY BE
;USED FOR SEVERAL DIFFERENT PURPOSES.
IFN FTRSP,<
SKIPN SWPNUF## ;SWAPPER NULL FLAG UP?
JRST INCLST ;NO, CONTINUE
MOVE T1,P1 ;YES, COMPUTE NULL TIME VALUE
ADD T1,SWPNU2##
IDIVI T1,RTUPS##
ADDM T1,SWPNUL##
MOVEM T2,SWPNU2##
SETZM SWPNUF## ;CLEAR FLAG
SKIPN SWPPLT## ;LOST TIME UP THIS TICK?
JRST INCLST ;NO, CONTINUE
MOVE T1,P1 ;YES, GET TIME IN T1
ADD T1,SWPLS2## ;ADD LAST REMAINDER
IDIVI T1,RTUPS## ;CONVERT TO JIFFIES PLUS REMAINDER
ADDM T1,SWPLOS## ;ADD TO SWAPPER LOST TIME
MOVEM T2,SWPLS2## ;REMEMBER NEW REMAINDER
SETZM SWPPLT## ;CLEAR LOST TIME FLAG
>;END IFN FTRSP
INCLST: SKIPE J,.CPJOB(P4) ;LAST JOB..WAS IT NULL JOB?
JRST INCTIM ; NO, CONTINUE
SKIPN .CPPLT##(P4) ; YES..WAS IT LOST TIME?
JRST INCNUL ; NOT LOST, JUST IDLE.
MOVE T1,P1 ; LOST, INCREMENT TOTAL
ADD T1,.CPLS2##(P4) ;ADD PREV EXCESS
IDIVI T1,RTUPS## ;CONVERT TO JIFFY + EXCESS
ADDM T1,.CPLST(P4) ;INCREMENT JIFFY TOTAL
MOVEM T2,.CPLS2(P4) ;REMEMBER EXCESS
IFN FTKL10&FTMS,<
SKIPN .CPCLF##(P4) ;LOST TIME BECAUSE OF CACHE ON DUAL CPUS?
JRST INCNUL ;NO
MOVE T1,P1
ADD T1,.CPCL2##(P4) ;DO USUAL STUFF
IDIVI T1,RTUPS##
ADDM T1,.CPCLT##(P4) ;MORE LOST TIME
MOVEM T2,.CPCL2##(P4) ;SAVE REMAINDER
SETZM .CPCLF##(P4) ;CLEAR FLAG
>;END FTKL10&FTMS
INCNUL: MOVE T1,P1 ;INCREMENT IDLE TIME
ADD T1,.CPNL2##(P4) ;ADD PREV EXCESS
IDIVI T1,RTUPS ;CONVERT TO JIFFY + EXCESS
ADDM T1,.CPNUL##(P4) ;INCREMENT JIFFY TOTAL
MOVEM T2,.CPNL2(P4) ;REMEMBER EXCESS
;INCREMENT JOB'S RUNTIME
INCTIM: PUSHJ P,FNDPDB## ;GET ADDRESS OF PDB
JRST CPOPJ1## ;NO PDB (KJOB UUO)
.ADD P1,.PDTT2(W) ;ADD JOB'S EXCESS BEYOND JIFFY
IDIVI P1,RTUPS ;CONVERT TO JIFFY + EXCESS
.MOVEM P2,.PDTT2##(W) ;REMEMBER EXCESS
IFN FTEMRT,<
PUSHJ P,GETEBT## ;GET EBOX TIME FROM EBOX CYCLE COUNTER
; HIGH ORDER IN T1, LOW IN T2
PUSHJ P,CLREBT## ;CLEAR OUT COUNT SO NEXT TIME WE READ
; FOR THIS JOB WE WILL GET INCREMENTAL
; EBOX COUNTS. THIS IS NECESSARY
; SINCE JOBS DON'T ALWAYS HAVE UPT'S
.ADD T2,.PDEB2##(W) ;ADD IN EXCESS FROM LAST TIME
TLZE T2,(1B0) ;OVERFLOW?
AOS T1 ;YES
DIV T1,.CPEBJ##(P4) ;DIVIDE BY EBOX COUNTS PER JIFFY
.ADDM T1,.PDEBT##(W) ;ADD TO TOTAL EBOX TIME FOR JOB
.MOVEM T2,.PDEB2##(W) ;SAVE LEFTOVERS FOR NEXT TIME
MOVE P2,T1 ;SAVE EBOX COUNTS IN P2
PUSHJ P,GETMBT## ;GET MBOX COUNTS IN T1,T2
PUSHJ P,[PUSH P,T1 ;SAVE T1
PUSHJ P,CHKPMJ## ;CHECK JOB ENABLE CONDITION
JRST TPOPJ##
JRST TPOPJ1##]
JRST INCTAA ;PERF METER NOT RUNNING FOR LAST JOB, DON'T UPDATE
DMOVE T3,T1 ;GET COPY OF MBOX REFS
DADD T3,.CPMM0##(P4) ;GET NEW TOTAL
DMOVEM T3,.CPMM0##(P4) ;STORE
INCTAA: PUSHJ P,CLRMBT## ;CLEAR OUT COUNT SO NEXT TIME WILL BE
; INCREMENTAL. HAVE TO DO ALL THIS
; CLEARING NOW, OR ELSE USERS WON'T
; BE CHARGED OVERHEAD IF THAT IS DESIRED.
.ADD T2,.PDMB2##(W) ;ADD IN EXCESS FROM LAST TIME
TLZE T2,(1B0) ;OVERFLOW?
AOS T1 ;YES, INCREMENT HIGH ORDER WORD
DIV T1,.CPMBJ##(P4) ;CONVERT TO JIFFIES
.ADDM T1,.PDMBT##(W) ;REMEMBER HOW MUCH IN .PDMBT
.MOVEM T2,.PDMB2##(W) ;AND SAVE REMAINDER
ADD P2,T1 ;GET TOTAL RUNTIME IN P2
MOVE T1,CNFST2## ;GET STATES WORD
TRNE T1,ST%EMR ;EBOX/MBOX RUNTIME?
MOVE P1,P2 ;REPLACE HIGH PRECISION RUNTIME WITH EBOX/MBOX TIME
>;END IFN FTEMRT
SKIPN P2,P1 ;SINCE NOT USING EBOX/MBOX, SETUP P2 OLD STYLE
POPJ P, ;NOT PAST JIFFY SO DON'T INCREMENT TOTALS
;NOW P1 / NUMBER JIFFIES BY WHICH JOB'S RUN TIME
;HAS INCREASED SINCE THE LAST TIME IT WAS STOPPED. (NORMALLY THE
;INCREASE IN JIFFIES WILL BE 0 OR 1, BUT IT MIGHT POSSIBLY BE MORE.)
;NOTE: JOB 0 TIME IS NULL JOB TIME FOR ALL PROCESSORS IN A
;MULTIPROCESSOR SYSTEM.
.ADDM P1,.PDRTM##(W) ;INCREMENTAL RUN TIME
.ADDM P1,.PDTTM##(W) ;TOTAL RUN TIME
IFN FTKCT,< ;KILO CORE TICKS?
PUSHJ P,JOBSIZ## ;GET SIZE OF JOB (LOW + HIGH SEG) INTO T2
IMUL T2,P1 ;MULTIPLY BY INCREASE IN JIFFY RUN TIME
.ADDM T2,.PDKCT##(W) ;ADD TO KILO-CORE-TICKS
IFN FTVM&FTACCT,<
PUSHJ P,VMSIZE## ;JOB VIRTUAL SIZE
ADDI T2,UPMPSZ##(T1)
LSH T2,P2KLSH## ;CONVERT TO K
IMUL T2,P1 ;VIRTUAL KCS
ADDM T2,.PDVKC##(W) ;ACCUMULATE
>
> ;END FTKCT CONDITIONAL
IFN FTNSCHED,<
ADDM P1,RTCTOT## ;UPDATE TOTAL TIME GIVEN OUT SINCE WE SET
; CLASS QUOTAS
>;END IFN FTNSCHED
JUMPE J,CPOPJ1## ;IF JOB ZERO, RETURN
.LDB T2,PDYQNT## ;GET IN QUE TIME
SUB T2,P1 ;SUBTRACT JIFFIES CHARGED FOR BY CLOCK
JUMPGE T2,.+2 ;GONE NEGATIVE?
SETZ T2, ;YES. PUT IN A ZERO
.DPB T2,PDYQNT## ;STORE NEW VALUE FOR SCHED1
IFN FTPSCD,<
LDB T2,PJBST2## ;GET PHYSICAL QUEUE
CAIN T2,PQ1##
ADDM P1,RNTPQ1## ;CHARGE PQ1
CAIN T2,PQ2##
ADDM P1,RNTPQ2## ;CHARGE PQ2
CAILE T2,PQ2## ;HPQ?
ADDM P1,RNTHPQ## ;CHARGE HPQS
>
IFN FTNSCHED,<
SKIPN .CPSQF##(P4) ;EXIT IF THIS JOB NOT FROM SUBQUEUES
JRST CPOPJ1## ;GIVE ACCOUNTING DONE RETURN
;HERE IF SCHEDULER IS TRYING TO SATISFY QUOTAS FOR ONE OR MORE CLASSES.
; INCREMENT TOTAL RUNTIME AND PER CLASS RUNTIME.
ADDM P1,TOTRTC## ;INCREMENT TOTAL RUNTIME FOR ALL CLASSES
;DOES NOT INCLUDE TIME GAINED IN PQ1, HPQ, ETC.
LDB T2,JBYCLS## ;GET THIS JOB'S CLASS NUMBER
ADDM P1,CLSRTM##(T2) ;INCR. RUNTIME FOR THIS CLASS SINCE STARTUP
>;END IFN FTNSCHED
JRST CPOPJ1## ;EXIT
;HERE IF CURRENT JOB HAS NO PDB (KJOB UUO)
CIP0: MOVE R,JBTADR(J) ;ADR OF JOB
JUMPE J,CIP2
IFN FTTLIM,<
LDB T3,JBYLTM## ;GET JOB'S TIME LIMIT
JUMPE T3,INCTM4 ;NO LIMIT, CONTINUE
SUB T3,P2 ;REDUCE REMAINING TIME BY RUN TIME
JUMPG T3,INCTM3 ;REACH LIMIT?
;HERE WHEN TIME LIMIT EXCEEDED
CIPTLE: MOVSI T3,JACCT ; YES
TDNE T3,JBTSTS(J) ;PRIVILEGED PROGRAM?
JRST INCTM2 ; YES, LET IT GO
PUSHJ P,SIMCHK ;CAN JOB BE STOPPED?
SKIPA T3,JBTLIM(J) ;YES, GET BATCH-JOB BIT
JRST INCTM2 ;NO, TRY LATER (IN MIDDLE OF MONITOR)
TLNE T3,(JB.LBT) ;SKIP IF NOT BATCH JOB
JRST INCTM1 ;ELSE BOMB HIM OUT
IFN FTPI,<
SIGNAL C$TLE ;SIGNAL TIME LIMIT UP
JRST INCT1A ;TRAP TO THE USER
>
MOVEI T4,.ERTLX ;TIME LIMIT EXCEEDED ERROR
PUSHJ P,CHKINT## ;NO, HE WANT THIS INTERCEPT
JRST INCTM1 ;NO, GIVE ERROR MSG
MOVE T2,.CPPC(P4) ;PC AT INTERRUPT
TLNE T2,(XC.USR) ;JOBPD1 IS OK IF DURING A UUO
MOVEM T2,JOBPD1(R) ;SAVE FOR DOINT
HLL T1,.CPPC##(P4) ;FLAGS AT INTERRUPT
TLNE T1,(XC.USR) ;USER MODE?
HRRM T1,.CPPC##(P4) ;YES, NEW START LOC GOES INTO PC WORD
PUSHJ P,DOINT## ;TELL USER PC, SET EXIT LOC
SKIPA ;SKIP THE ERROR MESSAGE
INCTM1: PUSHJ P,@.CPTLE##(P4) ;TYPE LIMIT EXCEEDED MESG
INCT1A: TDZA T3,T3 ;NEW LIMIT WILL BE 0 (I.E. NO LIMIT)
INCTM2: MOVEI T3,1 ;MINIMUM LIMIT
INCTM3: DPB T3,JBYLTM ;REPLACE LIMIT
INCTM4:
IFN FTVM,<
JUMPE R,INCTM6 ;NOTHING TO DO IF NO CORE IN CORE
SKIPL JBTSTS##(J) ;JOB RUNNABLE?
JRST INCTM6 ;NO, DON'T TEST
SKIPE .UPMP+.UPTMC ;COUNTER ZERO?
SOSLE .UPMP+.UPTMC ;NO, DECREMENT COUNTER
JRST INCTM6 ;NO COUNT SETUP OR COUNT HASN'T GONE TO ZERO
MOVE T1,.CPPC##(P4) ;GET THE JOB'S PC
TLNN T1,(XC.USR) ;PC IN USER MODE?
JRST INCTM5 ;NO, TRY AGAIN IN A TIC
HRRZ T2,.JBPFH##(R) ;START OF PFH
HLRZ T3,.JBPFH##(R) ;END OF PFH
CAIG T2,(T1) ;PC IN PFH?
CAIGE T3,(T1) ; ..
SKIPA T2,[EXP IC.UOU+TIMFLT##] ;NO, PC TO CATCH TIME FAULT AT UUO EXIT
JRST INCTM5 ;YES, POSTPONE TIME FAULT ONE TICK
MOVEM T1,.UPMP+.UPTMC ;STORE OLD PC FOR TIMFLT AND
; PSISER
MOVEM T2,.CPPC##(P4) ;MAKE CONTEXT SWITCH GO TO TIMFLT
JRST INCTM6
INCTM5: MOVEI T1,1 ;WAIT ONE TICK FOR VIRTUAL TIME TRAP
MOVEM T1,.UPMP+.UPTMC ;STORE NEW VALUE IN COUNTER OR USER'S PC
INCTM6:> ;END FTVM
> ;END FTTLIM CONDITIONAL
> ;END FTTIME CONDITIONAL
;HERE AFTER ALL TIME CHARGING TO CURRENT USER HAS BEEN DONE
CIP1:
MOVE T1,.CPPC##(P4) ;PICK UP PC
MOVE J,.CPJOB##(P4) ;&JOB #
SKIPN T2,JBTADR##(J) ;ADDRESS OF JOBDAT
JRST CIP2 ;NONE
MOVEM T1,JOBPC##(T2) ;STORE PC FOR ALL TO SEE
IFN FTWATCH,<
MOVE T2,JOBPD1##(T2) ;ADDRESS OF UUO
SUBI T2,1
TLNE T2,(XC.USR) ;IN USER MODE?
HRRM T2,JBTPC##(J) ;YES--STORE FOR CONTROL-T
TLNE T1,(XC.USR) ;ARE WE IN USER MODE?
HRRM T1,JBTPC##(J) ;YES--STORE PC
>;END FTWATCH
CIP2: SKIPN .CPTMF(P4) ;HAS THE JIFFY CLOCK TICKED SINCE
; WE WERE HERE LAST?
JRST CIP6 ; NO, JUST RESCHEDULE
;NOTE: ALL PROCESSING DRIVEN BY TIME INTERVALS EXCEPT
;THE ABOVE RUN TIME ACCOUNTING IS DRIVEN BY THE JIFFY (POWER LINE)
;CLOCK. THE FLAG .CPTMF IS SET AT APR INTERRUPT LEVEL WHEN THE JIFFY
;CLOCK INTERRUPTS. NONE OF THE FUNCTIONS CONTROLLED BY .CPTMF ARE
;CRITICALLY TIME DEPENDENT, IN THAT MISSING OR DELAYING THE PROCESSING
;OF ONE TICK WOULD BE A SERIOUS PROBLEM.
IFN FTMS,< ;MASTER/SLAVE?
SKPCPU (0) ;MASTER?
JRST CIP6 ;NO, SLAVE DOES NOT UPDATE TIME
>
IFN FTMETR,<
SKIPGE T2,MP4## ;METER CLOCK TICKS
PUSHJ P,@MPDPRA##(T2) ;YES, CALL POINT ROUTINE
>
;DO SYSTEM TIME ACCOUNTING
MOVE T1,TIME## ;REMEMBER THIS TIME FOR
EXCH T1,TIMLST## ; NEXT TIME & COMPUTE
SUB T1,TIMLST ; DIFFERENCE (TIMINT)
MOVNS T1
SKIPGE T1 ;IN CASE WENT THRU MIDNIGHT
ADD T1,MIDNIT##
MOVEM T1,TIMINT##
;UPDATE SMITHSONIAN DATE-TIME
;T1 = # OF TICKS TO ADD
HRLZ T2,T1 ;T2 = T1*1000000
SETZM T1
ADD T2,DATREM## ; + REMAINDER FROM LAST TIME
DIV T1,MIDNIT##
MOVEM T2,DATREM## ;REMEMBER REMAINDER
HRRZ T2,DATE## ;RH=FRACT. OF DAY
ADD T2,T1
TLNE T2,-1 ;DON'T BUMP DAY (RH)
MOVEI T2,-1 ; LET 'HOUR' DO IT
HRRM T2,DATE##
;PROCESS TIMING REQUESTS STORED IN QUEUE
HRRZ U,CLOCK ;GET END OF LIST
CIP4: CAIN U,CIPWTM ;END YET?
JRST CIP5 ;YES
HRRZ T2,-1(U) ;DECREMENT TIME REQUEST
SUB T2,TIMINT##
HRRM T2,-1(U)
SKIPLE T2 ;TIME EXPIRED?
SOJA U,CIP4A ;NO, CONTINUE SCAN
MOVE T1,(U)
MOVE T2,-1(U)
CONO PI,PIOFF ;YES, MOVE LAST ITEM IN LIST TO THIS
MOVE T3,@CLOCK
SOS CLOCK
MOVEM T3,(U)
MOVE T3,@CLOCK
MOVEM T3,-1(U)
SOS CLOCK
CONO PI,PION
MOVSS T2 ;SETUP DISPATCH ADDRESS
PUSH P,U ;SAVE ONLY VALUABLE AC
PUSHJ P,(T2) ;AND DISPATCH TO TIMING REQUEST ROUTINE
POP P,U
SUBI U,1
CIP4A: SOJA U,CIP4 ;GO BACK FOR MORE REQUESTS
CIP5: SKIPG HNGTIM ;SECOND COUNTER GONE TO ZERO (OR LESS)?
PUSHJ P,SECOND ;YES, GO DO ONCE-A-SECOND JOBS
IFN FTKI10!FTKL10,<
SKIPE T1,.C0JOB## ;CALL COMMAND DECODER IF NULL JOB IS RUNNING
SKIPE JBTADR##(T1) ;DON'T CALL COMMAND DECODER
; IF CURRENT JOB LOGGED OUT SINCE
; ITS CORE MAY BE REASSIGNED BEFORE
; ITS REALLY STOPPED
>
PUSHJ P,TTYCMD## ;PROCESS ANY COMMAND
MOVEI P4,.C0CDB ;RESTORE P4 AFTER CALL TO COMCON
CIP6:
IFN FTKL10&FTMS,<
PUSHJ P,CSREQS## ;SERVICE POSSIBLE CACHE SWEEP REQUEST
; BY ANOTHER CPU. DO IT BEFORE
; GETTING INTERLOCK INCASE IT MIGHT
; HELP OTHER CPU
>;END IFN FTKL10&FTMS
CPLOCK (SCD) ;LOCK SCHEDULER TO AVOID RACES
PUSHJ P,@.CPNXJ(P4) ;CALL SCHEDULER, SET J TO NEXT JOB # TO RUN
IFN FTMS,<
CAME J,.CPJOB(P4) ;IS THIS JOB SAME AS LAST JOB
SKIPN .CPADR(P4) ;OR WAS LAST JOB THE NULL JOB
CPUNLK (SCD) ;YES, CAN UNLOCK NOW
SKIPE T1,.CPJOB(P4) ;WAS LAST JOB THE NULL JOB
CAMN T1,J ;NO, IS THIS SAME AS LAST JOB
JRST CIP60 ;YES, DON'T RING DRBELL
HLRZ T2,JBTSTS(T1) ;DO A QUICK RUNABILITY CHECK ON LAST JOB
TRZ T2,RUNMSK+CMWB ;CLEAR UNWANTED BITS
CAIN T2,RUNABL ;IS IT RUNABLE STILL
SETOM @.CPRDB##(P4) ;YES, RING OTHER CPU'S DOORBELL
CIP60:
SKPCPU (0) ;MASTER?
JRST CIP6A ;NO SLAVE DOES NOT DO MOVIE
>
; TIME TO BE SKIPE SYSSNP
SKIPE SYSSNP## ;IF A PROGRAM WANT TO COLLECT
; MONITOR DATA IT SHOULD POKE.
; 27[SYSSNP] TO THE ABSOLUTE
; LOCATION OF A ROUTINE TO CALL
JSR @SYSSNP## ;CALL THE ROUTINE
REPEAT 0,< ;LEAVE OUT IN DISTRIBUTED VERSION
PATCHK::JFCL CKJBAD ;IF THIS INSTRUCTION IS A PUSHJ P,CKJBAD
; IT WILL:
; 1. CHECK CORTAL MATCHES THE BIT MAP
; 2. CHECK JBTADR AGAINST CORTAL
; 3. EAT UP MASSIVE CPU TIME
; THEREFOR, IT IS A JFCL. IF IT IS DESIRED
; THE PATCH IS SIMPLE.
>;END REPEAT 0
CIP6A:
IFN FTKI10!FTKL10,<
CONO PI,PI.OFF ;NO INTERRUPTS
>
SETZM .CPCKF(P4) ;CLEAR CLK INTERRUPT FLAG
; SET ON ALL FORCED CLK INTERRUPTS
IFN FTKI10!FTKL10,<
CONO PI,PI.ON!II.CCI## ;CLEAR SOFTWARE INTERRUPT
>
SETZM .CPTMF(P4) ;CLEAR TIMED (1 JIFFY) INTERRUPT FLAG.
SETZM .CPSCF(P4) ;CLEAR FORCED SCHEDULING FLAG
SETZM .CPRTF##(P4) ;CLEAR REAL TIME RESCHEDULE FLAG
IFN FTHPQ!FTNSCHED,<
SETZM .CPHQU##(P4) ;CLEAR FLAG SAYING CURRENT JOB DID A HPQ UUO
>
IFN <FTKI10!FTKL10>&FTSET,<
CONI APR,.CPAPR##(P4) ;READ MI PROG DIS SETTING
>
MOVE U,.CPJOB(P4) ;T1 = LAST JOB RUN
CAMN J,U ;IS NEXT JOB SAME AS LAST ONE?
;IF SEGMENT WAS MOVED, GO REMAP IT
JRST [MOVE T1,JBTSGN##(J)
TLZN T1,SEGMB ;WAS HIGH SEGMENT MOVED BY LOCK UUO?
JRST CIPXIT ;NO, REMAP IS NOT NECESSARY.
MOVEM T1,JBTSGN##(J) ;YES, CLEAR SEGMENT MOVED BIT.
PUSHJ P,SETRL1## ;AND MAKE PAGE MAP REFLECT THE MOVE.
JRST CIPXIT]
SKIPE U ;NO, SAVE PREVIOUS JOB NO. FOR PERFORMANCE
MOVEM U,.CPLJR(P4) ;MONITORING WITH A DISPLAY
IFN FTMETR,< ;METER NEW JOB #
SKIPL T2,MP2## ;POINT #2, IS IT ENABLED?
JRST CIP6A1 ;NO
HRRZ T1,U ;POINT VAL.=LAST JOB TO RUN
CAME T1,MPDPAR##(T2) ;POINT PARAMETER SELECTS JOB NUMBER
SKIPGE MPDPAR(T2) ;OR ALL JOBS IF -1
JRST CIP6A0 ;JOB NR OK, DO THE POINT
JRST CIP6A1 ;WRONG JOB NO POINT
CIP6A0: PUSHJ P,FPDBT1## ;FIND PDB VIA T1
JRST CIP6A1 ;NO PDB
HRR T1,.PDTTM##(T1) ;PICK UP ITS CPU TIME
HRL T1,U ;RESTORE JOB#
PUSHJ P,@MPDPRA##(T2)
CIP6A1:
> ;IFN FTMETR
;DIFFERENT JOB, SAVE SOFTWARE STATE(HARDWARE ALREADY SAVED)
EXTERNAL JOBPRT,JOBJDA
AOS .CPTJC##(P4) ;COUNT NO. OF CONTEXT SWITCHES TO DIFF. JOB
; (INCLUDE NULL JOB)
IFN FTKI10!FTKL10,< ;IF KI10,
PUSHJ P,SAVUAC## ;SAVE THE USER'S ACS (AC BLOCK 1) IN THE SHADOW AREA
>
MOVEM J,.CPJOB(P4) ;STORE NEW CURRENT JOB NUMBER
SKIPN R,.CPADR(P4) ;NULL JOB OR CORE 0 ON OLD JOB?
JRST CIP7 ;YES, DO NO SAVE SOFTWARE STATE
IFE FTVM,<
MOVEI T1,JOBPRT(R) ;DEST.=FIRST LOC PROTECTED FROM USER
HRLI T1,.CPPRT##(P4) ;SOUR.=SYSTEM DATA STORAGE FOR CURRETN JOB
SKIPL T2,.CPHCU##(P4) ;MOVE NO. OF OLD USER IO CHAN. IN USE
CAILE T2,17 ;MUST BE 17 OR LESS(IO MIGHT
; CLOBBER IF ADDRESS CHECKING MISSES)
MOVEI T2,0 ;MOVE ONLY CHN 0 IF NEG, OR GR 17
; SAVGET SETS LH NEGATIVE DURING IO AS A FLAG
; SINCE IT DOES IO INTO AND OUT OF
; CHANNEL LOCATIONS (JOBJDA+1...JOBJDA+17).
ADD R,T2 ;RELOCATE TO USER AREA
BLT T1,JOBJDA(R) ;MOVE TO USER JOB DATA AREA
; STOP WITH USER CHANNEL 0-1+C(USRHCU)
> ;END IFE FTVM
IFN FTVM,<
MOVE T1,.CPPC##(P4) ;GET PC
MOVEM T1,JOBPC##(R) ;SAVE IT
MOVE T1,USRDDT## ;CONTEXT SWITCH JOBDDT SO THAT IT REMAINS
MOVEM T1,JOBDDT##(R) ;PROTECTED BUT USER CAN LOOK AT IT
> ;END IFN FTVM
IFN FTKL10&FTMS,<
MOVE T1,J ;SAVE NEW JOB NUMBER
SETZ J, ;SWITCH TO NULL JOB'S UPMP FOR A SEC
PUSHJ P,STEUB## ;BEFORE SETCSN IS CALLED SO THAT
; ACCT METER STUFF IN UPMP IS STORED
; BACK NOW
MOVE J,T1 ;RESTORE
PUSHJ P,CTXSWP## ;SWEEP CACHE ON DUAL KL SO SLAVE CAN RUN THE JOB.
; SLAVE NOW AND NEEDS A MASTER UUO
; DONE.
PUSHJ P,SETCSN## ;HERE WE ARE GUARANTEED TO HAVE DIFFERENT
; NON-NULL JOB WITH CORE, SO CALL SETCSN.
; ANY CACHE SWEEP ON THIS CPU AFTER THIS
; CALL WILL MAKE THE OLD JOB
; RUNNABLE ON ANOTHER CPU
>;END IFN FTKL10&FTMS
CPUNLK (SCD) ;UNLOCK SCHEDULER AFTER SAVING JOB'S STATE
;RESTORE SOFTWARE STATE OF NEW JOB,THEN HARDWARE STATE
INTERNAL NULJOB,NULADR
EXTERNAL JBTDAT,JOBPRT
EXTERNAL JOBHCU,JOBENB
NULJOB: ;TRANSFER HERE FROM SYSINI WITH J=0 AND .CPJOB(P4)=0
CIP7:
NULADR:
PUSHJ P,SETRL1## ;GO SETUP HARDWARE AND SOFTWARE RELOCATION
; INFORMATION FOR NEW CURRENT USER
IFN FTKI10!FTKL10,< ;IF KI10,
PUSHJ P,RESUAC## ;RESTORE THE USER'S ACS (AC BLOCK 1)
; FROM THE SHADOW AREA
>
JUMPE J,CIPXIT ;IS NEW JOB THE NULL JOB?
IFN FTHALT,<
SKIPN R ;DOES JOB HAVE CORE ASSIGNED?
STOPCD .,STOP,NCA, ;++NO CORE ASSIGNED
>
IFE FTVM,<
MOVEI T1,.CPPRT##(P4) ;NO, DEST.=PROTECTED AREA IN MONITOR
HRLI T1,JOBPRT(R) ;SOURCE=FIRST PROTECTED LOC. IN JB DATA AREA
SKIPL T2,JOBHCU(R) ;MOVE NO. OF USER IO CHAN. IN USE
CAILE T2,17 ;MUST BE 17 OR LESS(IO MIGHT CLOBBER
; IF ADRRESS CHECKING MISSES
MOVEI T2,0 ;MOVEJUST CHAN 0 IF NEG. OR GREATER THAN 17
; SAVEGET SETS NEG.DURING IO
ADDI T2,(P4) ;RELOCATE PROPERTY INTO CDB
BLT T1,.CPJDA##(T2) ;AND MOVE INTO MONITOR
> ;END IFE FTVM
IFN FTVM,<
MOVE T1,JOBPC##(R) ;NEW USER'S PC
MOVEM T1,.CPPC##(P4) ;SAVE IT IN THE CDB
MOVE T1,JOBDDT##(R) ;CONTEXT SWITCH JOBDDT SO THAT
MOVEM T1,USRDDT## ;IT REMAINS PROTECTED BUT USER CAN LOOK AT IT
> ;END IFN FTVM
;RESTORE HARDWARE STATE OF NEW JOB
;CONTROL ALWAYS FLOWS THROUGH HERE (EVEN IF NULL JOB)
; ON EACH CONTEXT SWITCH SO THAT MONITOR OVERHEAD
; TIME MAY BE ACCUMULATED.
CIPXIT:
PUSHJ P,TIMEX ;GET OVERHEAD INTERVAL
MOVE T3,STATES## ;GET STATES
IFN FTEMRT,<
TLNN T3,(ST.EMO) ;AND EXCLUDE MONITOR OVERHEAD?
JRST CIPX1A ;NO
PUSHJ P,ACCMON## ;YES, SO WE TURNED METER OFF BEFORE. TURN ON AGAIN.
SKIPN .CPAPS##(P4) ;SCDPMR HAS BEEN CALLED IF ACC METER
;AND PERF METER ARE IN SYNC
>;END IFN FTEMRT
IFN FTKL10,<
CIPX1A: PUSHJ P,SCDPMR## ;TURN PERF METER ON/OFF DEPENDING
; ON JOB CONDITION
>
TLNE T3,(ST.EMO) ;EXCLUDE MONITOR OVERHEAD FROM USER RUNTIME?
JRST CIPXI1 ;YES
MOVE T3,T1
MOVE T1,J
PUSHJ P,FPDBT1##
JRST CIPXI0
ADDM T3,.PDTT2##(T1) ;YES - ADD TO LAST JOB'S TIME
CIPXI0: SKIPN J
ADDM T3,.CPNL2##(P4) ; & CDB NULL TIME
MOVE T1,T3
CIPXI1: ADD T1,.CPOH2##(P4) ;CONVERT TO JIFFYS
IDIVI T1,RTUPS##
ADDM T1,.CPOHT##(P4) ;ADD INTEGRAL JIFFYS
MOVEM T2,.CPOH2(P4)
JUMPE J,CIPXI2 ;NULL JOB?
MOVE R,.CPADR(P4) ;NO-GET JOB DATA AREA
MOVE T2,JBTSTS##(J) ;GET THE JOB STATUS WORD
TRNE T2,JS.NTO ;IS HE DOING NON-BLOCKING TTY OUTPUT?
PUSHJ P,TTMORE## ;YES--DO SOME MORE OUTPUT
IFN FTPI,<
MOVSI T2,USRMOD ;USER MOD BIT IN PC WORD
TDNN T2,.CPPC##(P4) ;SKIP IF JOB IS IN USER MODE
JRST CIPPSI ;DO NOT TRAP IF EXEC MODE
XCT NOPISK## ;SKIP IF NO PI'S ARE TO BE GRANTED. THIS
; IS EITHER BECAUSE THE JOB DID NOT DO
; A PIINI., THE SYSTEM IS TURNED OFF, OR
; PSISER IS NOT LOADED.
XCT @JBTPIA##(J) ;EXECUTE THE TRAP INSTRUCTION
CIPPSI::>
IFN FTCCIN!FTDAEM!FTOPRERR,<
MOVEI T1,UTRP ;TRAP PENDING BIT
MOVSI T2,USRMOD ;USER MODE
TDNE T2,.CPPC##(P4) ;CURRENT JOB IN USER MODE?
TDNN T1,JBTSTS(J) ; AND DOES IT HAVE A TRAP PENDING?
JRST CIPXI4 ;NO, GO START THE USER
ANDCAM T1,JBTSTS(J) ;TURN OFF TRAP PENDING
MOVE T1,JOBFDV(R) ;GET OLD (IRP) PC
MOVE M,JOBINT(R) ;SETUP M FOR PUTWRD
MOVEI M,2(M) ; TO STORE PC IN THIRD WORD OF INT BLOCK
PUSHJ P,PUTWRD## ;STORE THE INTERRUPT PC
JFCL ;IGNORE ERROR
>
CIPXI4:
IFN FTVM!FTMS,<
SETZM .CPISF##(P4) ;FLAG NO LONGER IN SCHEDULAR
>
JRST @.CPRUA(P4) ; & DISMISS
; (IMPURE--MASTER GOES TO CIP8A
CIPXI2: IFN FTVM!FTMS,<
SETZM .CPISF##(P4) ;FLAG NO LONGER IN SCHEDULAR
>
JUMPN U,NULJB ;NULL JOB--WAS PREVIOUS JOB NULL?
;NO--GO SET IT UP
MOVE R,.CPNJD(P4) ;YES--SET UP NULL JOB DATA AREA
SKIPN .CPNJE(P4) ;HAS AN ERROR OCCURRED WHILE NULL JOB
; WAS RUNNING? IF YES, RESTORE ACS
; ILL UUO LOSED ACS
JRST @.CPRUA(P4) ;DISMISS ROUTINE IS IMPURE
; MASTER GOES TO CIP8A
;IF NULL JOB ERROR FALL THRU TO NULJB
;THE NULL JOB
;RUNS IN USER MODE WITH PC=1 AND COUNTS IN AC 0
EXTERNAL TIME,THSDAT,MIDNIT
NULJB:
SETZM .CPNJE(P4)
; CLEAR FLAG SAYING ERROR IN NULL JOB
; LOC JOBDAT (LOCATION OF NULL JOB DATA AREA) TO 0
; AS A FLAG (ONLY DUMP ACS USED IN NULL JOB DATA AREA)
; IF ANY ERRORS (APRERR NON-ZERO) OCCURRED
; WHILE CLK IN PROGRESS
; CATCH THEM NEXT CLK INTERRUPT
MOVSI T1,NULCOD
PXCTXU <BLT T1,5>,<PX.MEM> ;CLEAR AC 0 USED FOR USUAL MONITORING OF
; NULL TIME INTERVAL, INSTR. TO AC 1
IFN FTTRPSET,<
MOVE T1,AOJINS ;GET AOJA 1
SKIPE .CPSTS##(P4) ;IS TRPSET ENABLED
EXCTXU <MOVEM T1,3> ;YES DO NOT LOOK AT MEMORY
>
EXCTXU <MOVEM P4,P4> ;SETUP USER AC TO POINT TO PROPER CDB
IFN FTKL10,<
USERAC
>;END IFN FTKL10
JEN @NULJPC## ;DISMISS IF INTERUPT IN PROGRESS
XP NULCNT,^D50 ;# OF SOJG'S IN NULL JOB BEFORE
;CHECKING DOORBELL
NULCOD: 0 ;CLEAR AC0
SOJG 6,1 ;AC1 - DON'T CAUSE EXCESSIVE MEMORY INTERFERENCE
MOVEI 6,NULCNT ;AC2 - START OF NULJOB
SKIPE 400000+.CPDBL##(P4) ;AC3 - CHECK IF DOORBELL WAS RUNG
WAKINS::WAKE ;AC4 - WAKE UP MONITOR
AOJINS: AOJA 1 ;AC5 - COUNT UP LOC 0
;CPU0 COMES HERE TO START THE USER (CIP8A IS IN .C0RUA)
INTERN CIP8A
EXTERNAL CURJOB
CIP8A: HRRM J,CURJOB ;PUT JOB NUMBER IN LOW CORE FOR OPERATOR (CPU0)
JUMPE J,CIP8B## ;GO IF NULL JOB
MOVEI T1,JS.APE ;DOES THIS JOB HAVE AN APR ERROR
TDNN T1,JBTSTS(J) ; PENDING FROM CPU1 OR INTERRUPT LEVEL ON CPU0?
JRST CIP8B## ;NO, RESTORE ACS AND START THE JOB RUNNING
IFN FTMS&FTTLIM,< EXTERNAL CSPTLE
PUSHJ P,CSPTLE ;GO CHECK IF TIME LIMIT WAS EXCEEDED ON SLAVE
JRST CIPTLE ;YES, JS.APE CLEARED, GO INTERCEPT OR PRINT MESSAGE
>
MOVE T1,JOBCNI(R) ;NO, GET APR ERROR CONI
IFN FTMEMPAR,< ;MEMORY PARITY OPTION?
TLZ T1,(CP.PS1!CP.PS2!CP.PS3!CP.PS4!CP.PS5) ;CLEAR REQUEST TO SWEEP
;FOR ALL CPUS EXCEPT CPU0, SO CPU0 WILL NOT
; SWEEP FOR ERROR ANOTHER CPU HAS ALREADY SWEPT FOR
>
MOVEM T1,.C0AEF ;STORE ERROR BITS FOR ERRCON
MOVE T1,JOBTPC(R) ;GET PC OF ERROR
MOVEM T1,.C0APC ;STORE IT FOR ERRCON PRINTING
MOVE P,.C0NPD## ;SETUP PUSH DOWN LIST POINTER
JRST CHKAPE ;GO HANDLE APR ERROR
REPEAT 0,<
;SUBROUTINE TO INSURE THAT CORTAL, CORTAB, AND JBTADR ALL MATCH
; EACH OTHER. THIS TEST MAKES DEBUGGING MUCH EASIER BUT USES MORE
; CPU TIME THAN IT IS WORTH AND SO IT SHOULD BE REPEAT 0'ED IN A
; PRODUCTION MONITOR. TO CUT OUT OVERHEAD (BUT NOT SAVE
; ANY CORE YOU CAN PATCH "PATCHK" TO A JFCL.
;ALL AC'S ARE SAVED
;CALL WITH:
; PUSHJ P,CHJBAD
; RETURN HERE OR HALT
CKJBAD: PUSHJ P,CHKTAL## ;FIRST MAKE SURE THAT CORTAB IS
; NOT MESSED UP.
PUSHJ P,SAVE4## ;SAVE P1 THRU P4
IFN FTPDBS,< ;IS THE PDB'S LIVE IN USER CORE CHECK THEM
MOVNI P1,JOBN## ;START WITH PDB'S
> ;END FTPDBS
IFE FTPDBS,< ;IF THE PDB'S ARE IN MONITOR CORE START WITH JOB 1
MOVEI P1,1 ;FIRST ENTRY IN JBTADR
> ;END FTPDBS
SETZ P2,0 ;START WITH 0 WORDS IN USE
CHKADL: HLRZ P3,JBTADR(P1) ;GET SIZE OF SEGMENT
PUSHJ P,CNTCHK ;SEE IF WE SHOULD COUNT IT
ADDI P2,1(P3) ;ADD IN NUMBER OF WORDS
CAIE P1,JBTMAX## ;GONE THROUGH WHOLE TABLE (DO NOT TRUST
; HIGHJB)
AOJA P1,CHKADL ;NO--LOOP OVER ALL SEGMENTS
MOVE P3,MAXMAX## ;GET THE SIZE OF CORE IN WORDS
SUB P3,P2 ;FREE CORE IN WORDS.
LSH P3,W2PLSH## ;CONVERT TO PAGES
CAME P3,CORTAL## ;DO THEY MATCH?
STOPCD .,STOP,JNE, ;++JBTADR NOT EQUAL TO CORTAL
POPJ P, ;YES--RETURN ALL IS WELL
;SUBROUTINE TO DECIDE IF NUMBER IN P3 SHOULD BE ADDED TO P2 TO ACCOUNT
; FOR A SEGMENT WHOSE NUMBER IS IN P1. CALLED ONLY FROM ABOVE.
; CLOBBERS P4.
;ONLY CALL IS ABOVE
CNTCHK: JUMPE P3,CPOPJ1 ;DO NOT ACCOUNT FOR ZERO LENGTH SEGMENTS
; BECAUSE ADDING THE 1 FOR ROUNDING WILL
; MESS US UP.
CAIG P1,JOBMAX## ;IS THIS A HISEG?
POPJ P, ;NO--JUST ADD IT INTO TOTAL
HRRZ P4,JBTSTS(P1) ;PICK UP INCORE COUNT
JUMPE P4,CPOPJ1 ;IDLE SEGMENT-DO NOT COUNT IT
POPJ P, ;ACTIVE SEGMENT. ADD IT INTO TOTAL
>;END REPEAT 0
;SUBROUTINE RETURNS INCREMENTAL TIME (SINCE LAST CALL)
;
; PUSHJ P,TIMEX ;GET INTERVAL (GETIME-UNITS*JIFFYS/SEC)
; ADD T1,EXCESS ;ADD LAST REMAINDER (FRAC.OF JIFFY)
; IDIVI T1,RTUPS## ;DIVIDE TO GET INTEGRAL JIFFYS
; ADDM T1,TIME ;ADD JIFFYS TO ACCUMULATED TIME
; MOVEM T2,EXCESS ;REMEMBER FRACTION FOR NEXT TIME
TIMEX: PUSHJ P,GETIME## ;GET CURRENT TIME IN GETIME-UNITS
EXCH T1,.CPXTM##(P4) ;SWAP WITH LAST VALUE
SUB T1,.CPXTM(P4) ; COMPUTE DIFFERENCE
MOVNS T1 ; & LEAVE IN T1
SKIPGE T1 ;IF NEGATIVE INCREMENT
ADD T1,RTCMAX## ; WE MUST HAVE GONE THROUGH MIDNIGHT
IMUL T1,TICSEC## ;CONVERT TO GETIME-UNITS*JIFFIES/SEC SO THAT
POPJ P, ; IDIV RTUPS WILL GIVE JIFFY QUOTIENT AND
; PARTIAL-JIFFY REMAINDER.
;SUBROUTINE CALLED AT CLOCK LEVEL ONCE A SECOND
EXTERNAL HNGTIM,TICSEC,DEVCHK,SCNSEC,HNGMIN
SECOND: PUSHJ P,SAVE2## ;SAVE P1,P2 FOR AVG JOB SIZE, # DAEMON
;HUNG JOBS, MCU CALCULATION
AOS T1,LOCSEC## ;BUMP SECOND
CAIL T1,^D60 ;NEW MINUTE?
PUSHJ P,MINUTE ;YES
MOVE T1,TICSEC ;RESTORE THE SECOND-COUNTER
ADDM T1,HNGTIM ;TO FULL SECOND
;COUNT GOES TO -1 SO SCHED1 CAN TELL WHEN
;EXACTLY ONE MINUTE HAS GONE BY
PUSHJ P,DEVCHK ;GO CHECK FOR HUNG DEVICES
IFN FTNET,<
PUSHJ P,NET2ND## ;CALL NETSER ONCE A SECOND
>
IFN FTNET!FTCAFE!FTDAS78,<
PUSHJ P,DLXSEC## ;CHECK DL-10
>
PUSHJ P,TAPSEC## ;CALL TAPSER
IFN FTDAS78,<
PUSHJ P,D78SEC## ;CHECK DAS78'S
>;END OF IFN FTDAS78
PUSHJ P,XTCSEC## ;CHECK XTCDDB'S
PUSHJ P,DTASEC## ;CALL DTASER
IFN FTKA10!FTKI10,<
CONO TTY,SCNCHN## ;MAKE SURE CTY HAS A PIA
>
IFN FTKL10,<
PUSHJ P,DTESEC## ;CALL 1/SECOND 10/11 PROTOCOL ROUTINE
>;END IFN FTKL10
PJRST SCNSEC ;AND HANDLE TELETYPE PROBLEMS
;SUBROUTINE CALLED AT CLOCK LEVEL ONCE A MINUTE
MINUTE: SETZB P1,LOCSEC## ;CLEAR SECONDS AND NO. OF DAEMON ERROR JOBS
SETZ P2, ;CLEAR AVERAGE JOB SIZE COUNTER
AOS T1,LOCMIN## ;BUMP MINUTE
CAIL T1,^D60 ;NEW HOUR?
PUSHJ P,HOUR ;YES
PUSHJ P,D76MIN## ;PRINT OUT PDP-11 MESSAGES
PUSHJ P,TAPMIN## ;PRINT TAPE CONTROLLER MESSAGES
IFN FTDAS78,<
PUSHJ P,D78MIN## ;CHECK DAS78'S
>;END OF IFN FTDAS78
SKIPLE J,HIGHJB## ;CHECK ALL JOBS
PUSHJ P,DECHJB ;MAKE SURE HIGHJB IS HONEST
MINUT1:
IFN FTJCON,< ;DEVICE PROBLEM FEATURE?
MOVE T1,JBTSTS(J) ;STATUS
TLNN T1,JERR ;IF JOB CAN CONTINUE,
TRNN T1,JDCON ;AND IS WAITING FOR A DEVICE,
JRST MINUT2
MOVE T1,J ;PUT JOB NUMBER IN T1
PUSHJ P,FCONRQ## ;AND TRY FORCED CONTINUE
JFCL
MINUT2:
> ;END DEVICE PROBLEM FEATURE
IFN FTDAEM,< ;DAEMON FEATURE?
PUSHJ P,DPMJOB## ;IS THIS JOB STILL WAITING FOR DAEMON SINCE LAST MINUTE?
ADDI P1,1 ;YES, KEEP COUNT SO TELL OPERATOR
MOVEI T2,JS.DPM ;DAEMON PROBLEM MESSAGE NEEDED NEXT MIN.
MOVE T3,JBTSTS##(J) ;JOB STATUS WORD
LDB T1,PJBSTS## ;JOB WAIT STATE CODE
CAIE T1,JDCQ ;JOB TYPED DCORE COMMAND?
TRNE T3,JS.DEM ;NO, WAITING FOR DAEMON (ERROR LOGGING OR DAEMON UUO)
IORM T2,JBTSTS##(J) ;YES, SET JOB TO GET MESSAGE NEXT MIN
; IF STILL WAITING
> ;END DAEMON FEATURE
IFE FTDAEM,<MOVE T3,JBTSTS(J)>
TLNN T3,JNA ;REAL JOB?
JRST MINUT3 ;NO
PUSHJ P,JOBSIZ## ;YES, GET ITS TOTAL SIZE
LSH T2,K2PLSH## ;CONVERT TO PAGES (JOBSIZ IS IN K)
ADD P2,T2 ;ACCUMULATE IN P2
MINUT3: SOJG J,MINUT1 ;TEST ALL JOBS
MOVE T1,P2 ;GET P2 IN T1 SO WE DON'T SMASH P3
IDIV T1,LOGNUM## ;GET AVERAGE JOB SIZE
MOVEM T1,AVJSIZ## ;SAVE IT FOR MCU CALCULATION
IFN FTDAEM,< ;DAEMON FEATURE?
SKIPE P1 ;HOW MANY JOBS WAITING FOR DAEMON?
PUSHJ P,DPMOPR## ;ONE OR MORE, TELL OPR JOB #S.
>
IFN FTMS,< EXTERNAL CP1CHK
PUSHJ P,CP1CHK ;CHECK IF DUAL PROCESSOR IS STILL RUNNING
>
IFN FTDISK&FTDBAD,<
EXTERN CHKUNI
PUSHJ P,CHKUNI ;CHECK ALL DISK UNITS
>
IFN FT5UUO,<
SKIPE T1,SYSKTM## ;IS A SHUTDOWN PENDING
SOSE T1,SYSKTM ;YES. COUNT DOWN TO ZERO
SKIPA T1,SYSKTM## ;NOT FIRST KSYS TIME
SETOB T1,SYSKTM## ;FLAG FOR PRIVILEDEGED CUSP
IFN FTPI,<
JUMPE T1,NOKSYS ;JUMP IF NO KSYS PENDING
CAIGE T1,^D10 ;LONG TIME TILL KSYS?
PUSHJ P,PSIKSY## ;NO--TELL EVERYONE
NOKSYS: > ;END FTPI
> ;END CONDITIONAL ON FT5UUO
AOS ARFLAG## ;COUNT UP AUTO RELOAD COUNTER
IFN FTKL10,<
SOSN KLETIM## ;TIME TO GIVE UP KL ERROR CHUNKS YET?
PUSHJ P,KLEREL## ;YES, GIVE THEM BACK
>;END IFN FTKL10
POPJ P,0 ;RETURN
;SUBROUTINE CALLED ONCE AN HOUR
HOUR: SETZM LOCMIN## ;SET MINUTE TO 0
AOS T1,LOCHOR## ;BUMP HOUR
CHKMNT::CAIGE T1,^D24 ;MIDNIGHT?
POPJ P, ;NO
SETZM LOCHOR ;YES-RESET HOUR
MOVE T1,LOCMON## ;SET T1=DAYS/MONTH
SOS T1
LDB T2,PMONTB##
SOJN T1,HOUR2 ;JUMP IF NOT FEB.
MOVEI T3,3 ;LEAP YEAR?
TDNN T3,LOCYER##
AOS T2 ;YES-29 DAYS
HOUR2: CAML T2,LOCDAY## ;NEW MONTH?
JRST HOUR4 ;NO
SETZM LOCDAY## ;YES-RESET DAY (AOS'D BELOW)
AOS T1,LOCMON## ;BUMP MONTH
CAIG T1,^D12
JRST HOUR4
AOS LOCYER## ;!!!HAPPY NEW YEAR!!!
MOVEI T1,1
MOVEM T1,LOCMON
HOUR4: AOS LOCDAY## ;BUMP DAY
HLRZ T1,DATE## ;AND UNIV. DATE
AOS T1
HRLZM T1,DATE
; DO OTHER MIDNIGHT THINGS
MOVN T1,MIDNIT## ;RESET TIME
ADDM T1,TIME##
SKIPGE TIME ;DONT LET IT GO NEGATIVE
SETZM TIME
PUSHJ P,RTCDAY## ;DK10 THINGS ARE IN COMMON
; HOUR5 (DELETED)
;FALL INTO THSDA1
;SUBROUTINE TO COMPUTE & STORE THSDAT
THSDA:: MOVE T1,LOCYER
SUBI T1,^D1964
IMULI T1,^D12
ADD T1,LOCMON
IMULI T1,^D31
ADD T1,LOCDAY
SUBI T1,^D32
MOVEM T1,THSDAT##
POPJ P,
;SUBROUTINE TO COMPUTE & STORE 'DATE' (UNIVERSAL DATE-TIME)
;MAKE UNIVERSAL DATE-TIME WORD
SUDATE::
MOVE T1,LOCMON## ;GET MONTH
MOVE T3,LOCYER## ;CALCULATE LEAP DAYS
IMULI T3,^D12
ADDI T3,^D45(T1)
IDIVI T3,^D48
SOJA T1,SUDAT3
SUDAT2: LDB T2,PMONTB##
ADDI T3,1(T2)
SUDAT3: SOJGE T1,SUDAT2
ADD T3,LOCDAY##
MOVE T1,LOCYER## ;GET YEAR
IMULI T1,^D365 ;ADD YEARS
ADD T3,T1
SUB T3,[^D678957] ;SUBTRACT NOV. 17 1858
MOVE T1,LOCHOR## ;GET HOUR
IMULI T1,^D60 ;MAKE MINUTES
ADD T1,LOCMIN## ;ADD MINUTES
IMULI T1,^D60 ;MAKE SECONDS
ADD T1,LOCSEC## ;ADD SECONDS
HRLZS T1 ;CONVERT TO FRACT. OF DAY
IDIVI T1,^D24*^D3600
HRLZS T3 ;DAYS TO LH
ADD T3,T1 ;ADD DATE AND TIME
SUB T3,GMTDIF## ;CONVERT TO GMT
MOVEM T3,DATE##
POPJ P,
;CLKCHG IS A ROUTINE TO SEARCH THE CLOCK QUEUE FOR AN ENTRY FOR A
;PARTICULAR JOB AND TO CHANGE THE REMAINING CLOCK REQUEST TIME.
;THE CALLING SEQUENCE IS AS FOLLOWS:
; MOVE T1,JOBNUM ;T1 = JOB TO SEARCH FOR
; MOVE T2,NEW SLEEP TIME ;T2 = NEW SLEEP TIME IN JIFFIES
; PUSHJ P,CLKCHG ;CHANGE CLOCK REQUEST TIME
; RETURN HERE IF AN ENTRY WAS NOT FOUND (T1=NEW SLEEP TIME)
;CLKCHG USES T2, T3 WITHOUT RESTORING THEM
; RETURNS HERE, CLOCK REQUEST TIME UPDATED.
EXTERNAL TPOPJ
INTERNAL CLKCHG
CLKCHG: PUSH P,T2 ;SAVE NEW SLEEP TIME FOR LATER
HRRZ T2,CLOCK ;GET RH OF CLOCK QUEUE POINTER
CLKCH1: CAIN T2,CIPWTM1 ;AT TOP OF QUEUE?
JRST TPOPJ ;YES, JOB NOT IN QUEUE
HLRZ T3,-1(T2) ;GET TIME-OUT ADDRESS
CAIE T3,WAKEJ ;IS THIS JOB SLEEPING?
SOJA T2,CLKCH2 ;NO. LOOK AT NEXT ONE.
HRRZ T3,(T2) ;GET DATA ITEM
CAIE T3,0(T1) ;NOW. DOES THAT EQUAL DESIRED JOB NO?
SOJA T2,CLKCH2 ;NO. GO LOOK FOR NEXT JOB.
POP P,T3 ;YES, GET THE NEW REQUEST TIME
HRRM T3,-1(T2) ; ..
IFN FTSWAP,<
MOVSI T2,SWP
TDNE T2,JBTSTS##(T1) ;IS JOB SWAPPED?
JRST CPOPJ1## ;YES, DON'T CHANGE IN-CORE PROTECT TIME
PUSHJ P,FPDBT1## ;FIND PDB VIA T1
JRST CPOPJ1## ;NO PDB, DO NOT WORRY ABOUT
; INCORE PROTECT TIME
.LDB T2,PDYIP2## ;GET ICPT
CAIGE T2,(T3) ; SLEEPING LONGER THAN ICPT?
PUSHJ P,CLRIP1## ;YES. CLEAR ICPT
>
JRST CPOPJ1## ;RETURN
CLKCH2: SOJA T2,CLKCH1
SUBTTL RUNCSS - RUN CONTROL(STARTING AND STOPPING OF JOBS)
;RUN CONTROL IS A COLLECTION OF ROUTINES WHICH
;SET AND CLEAR BITS IN THE JOB STATUS WORDS OF
;ALL JOBS SO THAT THE SCHEDULER WILL START AND STOP
;THEM ACCORDINGLY
;COMMON ERROR STOPPING ROUTINES
;CALLED AT ANY LEVEL(UUO,CLK, OR INTERRUPT)
;CALL: MOVE J,JOB CAUSING ERROR OR BEING STOPPED
; MOVE F,ADRRESS OF THAT JOB TTY DEVICE DATA BLOCK
; MOVE U,BYTE POINTER TO LAST CHAR. ALREADY MOVED
; ;TO TTY OUTPUT BUFFER
; PUSHJ P,KSTOP,PHOLD,HOLD,OR ESTOP
; NEVER RETURN IF CALLED AT UUO LEVEL
;ROUTINE TO STOP JOB AFTER KJOB COMMAND
;CALLED AT UUO LEVEL IF JOB HAD CORE,CLK LEVEL IF NOT
INTERNAL KSTOP,FTPRV,FT2REL,FTCNO,FTHALT,FTHIBW,FTHPQ,FTSPL,FTTLIM,FTUNAM,CLRJBT,DECHJB
EXTERNAL HIGHJB,TTYTAB
KSTOP:
MOVSI T1,JNA+JACCT ;CLEAR JOB NUMBER ASSIGNED AND LOGGED IN BITS
ANDCAM T1,JBTSTS(J)
PUSHJ P,CLRLOG ;CLEAR JLOG, COUNT DOWN LOGNUM & BATNUM
PUSHJ P,CLRJBT ;GO CLEAR ALL THE JOB TABLES
PUSHJ P,KILPDB## ;DEALLOCATE PDB
HLLZS TTYTAB(J) ;CLEAR TTY DDB LINK
PUSHJ P,DECHJB ;DECREMENT HIGHJB IF NOT REQUEUED
JRST ESTOP ;GO SET ERROR BIT
DECHJB:
; IF THIS IS THE LARGEST JOB IN USE,FIND NEXT
; HIGHEST AND SET HIGHJB
CAMGE J,HIGHJB ;IS THIS THE BIGGEST JOB NUMBER ASSIGNED?
POPJ P,0 ;NO, LEAVE HOLE
MOVSI T2,JNA+CMWB+JRQ ;YES, LOOK FOR LAST JOB WITH
;JOB NUMBER ASSIGNED BIT OR COMMAND WAIT BIT
HRRZ T1,J ;SCAN DOWNWARD
TDNN T2,JBTSTS(T1) ;ARE BITS SET FOR THIS JOB?
SOJG T1,.-1 ;NO,KEEP LOOKING,FINISHED(TRUE IF THIS THE ONLY JOB
MOVEM T1,HIGHJB ;YES,STORE NEW HIGHEST JOB NUMBER ASSIGNED
POPJ P,0 ;AND RETURN
;ROUTINE TO CLEAR ALL INTERESTING JOB TABLES AND PROCESS DATA BLOCK (PDB)
;COULD BE CALLED ANYTIME, BUT IS CALLED ONLY
; FROM NEWJOB (COMCON) AT JOB INITIALIZATION
; AND FROM KSTOP (CLOCK1) AT JOB TERMINATION
CLRJBT:
IFN FTPI,<
PUSHJ P,CLRPSI## ;CLEAR SOFTWARE INTERRUPT SYSTEM
>
IFN FTDISK,<IFN FTDSTT,<EXTERN JBTRCT,JBTWCT
SETZM JBTRCT(J) ;CLEAR NO. OF DISK BLOCKS READ BY JOB
SETZM JBTWCT(J) ;CLEAR NO. OF DISK BLOCKS WRITTEN BY JOB
>>
IFN FTSPL,<EXTERN JBTSPL
SETZM JBTSPL(J) ;CLEAR SPOOLING BITS
>
PUSHJ P,FIXXPN##
MOVEI T1,JS.SFL
ANDCAM T1,JBTSTS(J)
MOVEI T1,JS.MSK ;MASK FOR ACTUAL QUE
ANDM T1,JBTST2##(J) ;CLEAR ALL OTHER BITS IN JBTST2
IFN FTNSCHED,<
SETZ T2, ;CLEAR OUT FINAL RESULT
MOVE T1,DEFCLS## ;GET DEFAULT CLASS
DPB T1,[POINT 5,T2,17] ;PUT INTO T2
SKIPGE JBTSCD##(J) ;IN PQ2 STILL(WON'T STAY LONG)
TLO T2,(JS.PQ2) ;YES. REMEMBER
MOVEM T2,JBTSCD##(J) ;SAVE INITIAL VALUE
>
IFN FTKL10&FTMS,<
PUSHJ P,CLCSN## ;CLEAR OUT JBTST3 ENTRY, IF IT EXISTS
>;END IFN FTKL10&FTMS
IFN FTHPQ!FTRTTRP!FTHIBWAK,<EXTERNAL CLRRTD
XCT CLRRTD ;CLEAR HPQ POSITION
>
IFN FTLOGIN,<EXTERN JBTPPN
SETZM JBTPPN(J) ;CLEAR PROJECT-PROGRAMMER NUMBER
SETZM JBTJLT##(J) ;CLEAR JOB'S LOGIN TIME
>
IFN FTTLIM,<
SETZM JBTLIM##(J) ;NO LIMIT ON TIME OR CORE
>
IFN FTPRV,<EXTERN JBTPRV
SETZM JBTPRV(J) ;CLEAR PRIVILEGES
>
IFN FTRSP,<EXTERN JBTRSP
SETZM JBTRSP(J) ;CLEAR RESPONSE TIME MEASURE
SETZM JBTRQT##(J) ;CLEAR RUN-QUEUES TIME
>
IFN FTMS,< EXTERNAL SETJSP
PUSHJ P,SETJSP ;SET UP JBTSPS WORD WITH INITIAL CAN RUN BITS
>
IFE FTPDBS,< ;IF WE HAVE PDB'S IN MONITOR CORE
IFN FTTRACK,<
PJRST SETPDB## ;INITIALIZE PDB (SINCE SAME TYPE OF INFO AS
; JOB TABLES) AND RETURN
>
IFE FTTRACK,<
POPJ P,
>
> ;END FTPDBS
IFN FTPDBS,<
POPJ P,
> ;END FTPDBS
;SUBROUTINE TO STOP CURRENT JOB, NOT SET ERROR BIT
; PUT TTY IN COMMAND MODE, START TTY0, CALL SCHEDULER
INTERN HOLDW
HOLDW: PUSHJ P,HOLD0 ;PRINT CRLF, START TTY, TURN OFF RUN BIT
PJRST WSCHED ;NOW CALL SCHEDULER
;SUBROUTINE TO STOP JOB, BUT NOT SET ERROR BIT, PUT TTY IN COMMAND MODE
;AND START TTY
INTERN HOLD0
HOLD0: PUSHJ P,PRRSP1 ;PRINT CRLF, [XXX], CRLF, CRLF, DOT
PUSHJ P,TTYSTC ;START TTY AND LEAVE IN MONITOR MODE
PJRST ESTOP3 ;STOP JOB BUT DO NOT SET ERROR BIT
;SO JOB CAN CONTINUE
;ROUTINE TO STOP JOB, SET ERROR BIT AND PRINT MESSAGE
;THEN ADD ^C<CRLF><CRLF><PERIOD>
;CALL: MOVEI T1,ADR. OF MESSAGE
; PUSHJ P,PHOLD
INTERN PHOLD
PHOLD: PUSHJ P,CONMES ;MOVE MESSAGE TO TTY OUTPUT BUFFER
; FALL INTO HOLD
;ROUTINE TO STOP JOB, SET ERROR BIT,
;AND ADD "^C<CRLF><CRLF><PERIOD>
EXTERNAL TTYSTC,PRRSP1
HOLD:: JUMPE F,HOLD1 ;JUMP IF NO TTY DDB
LDB T1,PJOBN## ;THERE IS A DDB, GET THE OWNER'S JOB NUMBER
CAMN T1,J ;STOPPING THE JOB THAT OWN'S THE DDB?
JRST HOLD1 ;YES, GO DO USUAL THINGS
PUSHJ P,CRLF## ;ADD <CRLF> TO THE MESSAGE
PUSHJ P,TTYSTR## ;START THE TTY
JRST ESTOP ;STOP THE JOB
HOLD1: PUSHJ P,PRRSP1 ;PRINT CRLF, [XXX], CRLF, CRLF, DOT
PUSHJ P,TTYSTC ;MAKE SURE TTY STAYS IN MONITOR MODE
; AND START TTY TYPING OUT MESSAGE
; FALL INTO ESTOP
;ROUTINE TO STOP USER AND FLAG AS ERROR STOP
INTERNAL ESTOP,ESTOP1
EXTERNAL JBTSTS,TTYSRC,TTYDET
EXTERNAL CPOPJ
ESTOP: JUMPE J,CPOPJ ;IS THIS ERROR IN JOB 0?
ESTOP1:
IFN FTKI10!FTKL10,<
SKIPE JBTADR(J) ;DON'T MAKE JOB DATA AREA ADDRESSABLE IF THERE
; ISN'T ONE
PUSHJ P,SVEUB## ;MAKE SURE JOB DATA AREA IS ADDRESSABLE
>
IFN FTDAEM,<
MOVE T1,JBTNAM(J) ;IS THIS THE SYSTEM DAEMON
MOVE T2,JBTSTS(J) ; IDENTIFIED BY NAME
CAMN T1,[SIXBIT /DAEMON/]
TLNN T2,JACCT ; AND COPY BIT
JRST ESTOP2 ;NO--NOT DAEMON, STOP JOB
MOVE T1,JBTPPN##(J)
CAME T1,FSFPPN##
JRST ESTOP2
PUSHJ P,TTYSRC ;IS JOB DETACHED?
SKIPA ;YES--LEAVE IT ALONE
PUSHJ P,PTYDET## ;NO--DETACH IT.
MOVEI T4,0 ;NO SPECIAL BIT
PUSHJ P,CHKINT## ;SETUP INTERCEPT
JRST ESTOP2 ;NO--STOP JOB
PUSHJ P,DOINT## ;PREPARE INTERCEPT
SETO T1,
PUSHJ P,PUTWR1##
STOPCD .+1,JOB,IBI, ;++INTERCEPT BLOCK ILLEGAL
CAME J,.C0JOB## ;DAEMON NOW RUNNING?
POPJ P, ;NO (CHAN 7). AVOID DISASTER
PJRST QKUSXT## ;GO DO QUICKY USER EXIT
ESTOP2:>
MOVSI T1,JACCT ;CLEAR PRIVS IF ERROR STOPPING
ANDCAM T1,JBTSTS##(J)
MOVSI T1,JERR ;SET ERROR BIT IN JOB STATUS WORD
IORM T1,JBTSTS(J) ;SO JOB CAN NOT CONTINUE(CONT COM.)
ESTOP3::MOVE T1,JBTSTS(J)
TLNN T1,JLOG ;IF THIS GUY IS NOT LOGGED IN
TLNN T1,JNA ; AND HAS JNA SET -- KILL HIM
JRST STOP1C ;JLOG SET OR JNA CLEAR
CONSO PI,PI.IPA ;NOT LOGGED IN - KILL JOB IF NOT ON CHAN 7
JRST JOBKL## ;CLEAR JNA
;ROUTINE TO STOP ANY JOB FROM BEING SCHEDULED
;CALL:
; MOVE J, JOB NUMBER
; PUSHJ P, STOP1
; EXIT ;RETURN HERE IMMEDIATELY, IF CALLED FROM HIGHER
;PRIORITY PI CHANNEL THAN CLK(LOWEST), OTHERWISE WHEN JOB IS RUNABLE
;CALLED FROM COMMAND DECODER WHEN <CONTROL>C TYPED IN BY USER
;OR ON ANY ERROR MESSAGE(SEE PREVIOUS PAGE)
INTERNAL STOP1,STOP1C
EXTERNAL JBTSTS,PJBSTS,RQTBMQ,AVTBMQ,MINQ,MAXQ
STOP1C:
IFN FTGALAXY,<
SKIPE T2,JBTPPN##(J) ;IF PPN IS ZERO OR
CAMN T2,HELPPP## ; [2,5] DO NOT TRY
JRST STOPP ; TO LOG BACK IN
MOVE T2,JBTNAM##(J) ;GET PROGRAM NAME
CAMN T2,[SIXBIT/LOGOUT/] ;IS IT LOGOUT?
PUSHJ P,SETLOG ;LOG JOB BACK IN
>
STOPP: MOVSI T1,RUN
CONO PI,PIOFF ;DONE AT INTERUPT LEVEL HIGHER THAN DT LEVEL
TDNN T1,JBTSTS(J) ;NO, IS RUN BIT OFF IN JOB STATUS WORD
JRST STOP1A ;YES
TLO T1,CNTRLC ;TURN OFF. "USER TYPED ^C WHILE STILL IN EXEC MODE"
TRO T1,JS.RUU+JS.ASA ;TURN OFF RUN COMMAND BIT
ANDCAM T1,JBTSTS(J)
CONO PI,PION
IFN FTKI10!FTKL10,<
MOVSI T1,(JS.IGS) ;CLEAR "IN GETSEG" BIT
ANDCAM T1,JBTST2##(J)
>
PUSHJ P,TTYSRC## ;FIND CONTROLLING TTY
JRST STOP1E ;NONE--SKIP ON
JUMPE U,STOP1E ;IF NO LDB FORGET FIXING UP TTY.
PUSHJ P,CNCMOD## ;SET TTY TO MONITOR LEVEL
IFN FTSET,<
PUSHJ P,FNDPDB## ;FIND PDB
JRST STOP1E ;NO PDB
SKIPN .PDPGM##(W) ;GET CUSP TO RUN
JRST STOP1E ;NONE
MOVEI T1,TTFCXU## ;FORCE AN .R DUMP WHICH
MOVEI T2,JS.RPC ; WILL TURN INTO AN
TDNE T2,JBTST2##(J) ; .R C(.PDPGM). DO THIS
PUSHJ P,TTFORC## ; ONLY IF JS.RPC=1
>
STOP1E: LDB T1,PJBSTS ;GET JOB WAIT QUEUE CODE(IF ANY)
CAIL T1,MINQ ;SHARABLE RESOURCE STATE?
CAILE T1,MAXQ ;AND DOES STATE ALSO HAVE A Q?
JRST STOP1A ;NO
SOSL RQTBMQ(T1) ;YES. REDUCE IT.
JRST STOP1A ;NO
SOSGE AVTBMQ(T1) ;YES REDUCE COUNT
SETZM AVTBMQ(T1) ;CLEAR AVAL FLAG IF NO ONE WAITING
STOP1A: CONO PI, PION ;MAKE SURE PI ON
IFN FTDHIA,<
PUSHJ P,DIACLR## ;CRANK UP DSK IO IF JOB HAD
; IT STOPPED WITH DIAG.
>
PUSHJ P,TPFREE## ;CHECK FOR MTA'S
IFN FTMS,< EXTERNAL CLRCCB
PUSHJ P,CLRCCB ;CLEAR CONTROL C BIT
>
IFN FTRSP,<EXTERN JBTRSP
SETZM JBTRSP(J) ;CLEAR TIME USER STARTED TO WAIT FOR RESPONSE
; SO COUNT NEW RESPONSE
>
IFN FTVM,<
MOVSI T1,(UP.GET) ;CLEAR GET IN PROGRESS FLAG
ANDCAM T1,.UPMP+.UPBTS
>
STOP1B: CAME J,.C0JOB ;NO, IS THIS JOB CURRENT USER
IFE FTSWAP,<
POPJ P, ;NO
>
IFN FTSWAP,<
JRST REQUE ;NO, SET REQUE JOB FLAG
>
SKIPL T1,JBTSTS(J) ;RUN FLAG OFF?
TLNN T1,JERR ;YES, IF JOB ERROR FLAG ON
JRST STOP2## ;NO, (IRP LEVEL ONLY) DO NOT SET .C0SCF IN CASE CURRENT USER
; IS IN EXEC MODE, CALLING SCHEDULER, COMMAND DECODER
; AND P HAS BEEN CHANGED TO NULPDL SO NO LONGER
; STATE OF USER JOB. CHANNEL 7 WOULD SAVE P AGAIN
SETOM .C0SCF ;YES, FORCE RESCHEDULING EVEN IF JOB IN EXEC MODE
JRST STOP2## ;CAUSE CLK INTERRUPT
STOP1:
IFN FTCCIN,<
MOVSI T1,JACCT ;EVEN IF JACCT JOB IS
TDNE T1,JBTSTS##(J) ; ON A PTY LET THE
JRST STOP1J ; INTERCEPT HAPPEN
HRRZ T1,TTYTAB##(J) ;ADDRESS OF TTY DDB
JUMPE T1,STOP1J ;JUMP IF NO DDB
HRRZ U,DDBLDB##(T1) ;ADDRESS OF LDB
JUMPE U,STOP1J ;DETACHED (AND TYPED CNTRL-C?)
HRLZ T1,LDBDCH##(U) ;GET DEVICE BITS
JUMPL T1,STOP1G ;DO NOT INTERCEPT FOR PTY'S
STOP1J: SKIPL JBTSTS(J) ;RUN BIT ON?
JRST STOP1C ;NO, DON'T DO INTERCEPTING ^C'S
IFN FTPI,< ;IF WE WANT PSISER
PUSHJ P,SAVE1##
MOVE P1,M
SIGNAL C$CTLC ;SIGNAL CONTROL-C INTERRUPT
JRST STOP1F ;INTERRUPT NOW PENDING
MOVE M,P1
> ;END FTPI
MOVEI T4,.ERICC ;FLAG FOR CONTROL-C
PUSHJ P,SETINT ;SET UP INTERRUPT IF HE WANTS TO
JRST STOP1G ;NOT ENABLED
JRST STOP1D ;GO FINISH UP
IFN FTPI,<
STOP1F: SKIPN T1,TTYTAB##(J) ;GET TTY DDB
JRST STOP1H ;NO DDB?
SKIPL T1,DEVIOS(T1) ;GET I/O STATUS
TLNN T1,IOW ;IN INPUT WAIT?
STOP1H: TDZA T1,T1 ;NO--ZERO AC
MOVSI T1,(1B0) ;YES--SET STATUS BIT
EXCTUU <MOVEM T1,IBKISW##(M)>
MOVE M,P1 ;RESTORE FLAGS
PUSHJ P,CLRTI## ;GET DDB OUT OF TI WAIT
JRST STOP1D ;GO FINISH UP
>; END FTPI
>;END FTCCIN
STOP1G: SKIPGE T1,JBTSTS##(J) ;NO INTERRUPT BLOCK, SEE IF RUN AND JACCT
TLNN T1,JACCT ; SET FOR JOB
JRST STOP1C ;NO--GO STOP JOB
STOP1D: TLO M,NOCRLP## ;SET FOR NO CRLF OR PER
SKIPGE T1,JBTSTS(J) ;IF RUNNABLE
TLO M,TTYRNM## ;SET TO USER LEVEL
MOVSI T1,CNTRLC ;CLEAR DELAYED
ANDCAM T1,JBTSTS(J) ; .HALT HANDLING
IFN FTMS,<
PUSHJ P,CLRCCB ;CLEAR SECONDARY PROCESSOR ^C-BIT
>
POPJ P, ;AND RETURN
IFN FTCCIN!FTDAEM!FTOPRERR,<
INTERN SETINT
;SUBROUTINE TO SET UP AN INTERCEPT
;CALL WITH T4=INTERCEPT BIT
;EXIT NON-SKIP IN NOT ENABLED
;SKIP-RETURN IF ENABLED, SET TO TRAP ON UUO EXIT
; (OR START AT TRAP LOC IF IN USER MODE).
SETINT:
IFN FTKI10!FTKL10,<
PUSHJ P,SVEUB## ;MAKE SURE JOB DATA AREA IS ADDRESSABLE
>
PUSHJ P,CHKINT## ; SEE IF ENABLED
POPJ P, ;NO
MOVEI T2,UTRP
TDNE T2,JBTSTS##(J) ;ALREADY BEEN THRU HERE
JRST CPOPJ1## ;YES, DON'T DO IT AGAIN
PUSH P,T1 ;SAVE PC
MOVE T2,JOBPC(R) ;YES--GET CURRENT PC
CAMN J,.C0JOB ;CURRENT USER?
MOVE T2,USRPC## ;YES--GET PC FROM PROTECTED PLACE
TLNE T2,USRMOD ;SEE IF EXEC MODE
JRST STOP1U ;NO--DO USER MODE
SETOM T1 ;SET DOINT FLAG
PUSHJ P,SETUTP ;YES--SET IF NEEDED TO TRAP UUO
JRST STOP1U ;NO--GO START JOB
POP P,T2 ;THROW AWAY PC
JRST CPOPJ1 ;ALL DONE UNTIL UUO EXIT
;HERE WHEN UUO NOT IN PROGRESS
STOP1U: MOVEM T2,JOBPC(R) ;SETUP JOBPC FOR USTART
PUSHJ P,CLRTI## ;GET DDB OUT OF TI WAIT
POP P,T2 ;GET START PC
PUSH P,JOBOPC(R) ;SAVE OPC FOR USER
PUSHJ P,USTART ;START IN USER MODE
MOVE T1,JOBOPC(R) ;GET OLD PC
POP P,JOBOPC(R) ;RESTORE OPC
PJRST STUTRP ;DONT DO INTERRUPT UNTIL JOB IS RUNNABLE
; ELSE IRP CONDITION COULD OCCUR AGAIN AND STOP
; THE JOB SINCE JOBINT+2 NON-ZERO
> ;IFN FTCCIN!FTDAEM!FTOPRER
;ROUTINE TO CHECK IF OK TO STOP JOB IN MONITOR (OR WAIT TILL UUO EXIT)
;CALLED ON CONTROL C AND ANY ERROR WHICH PUTS JOB IN DAEMON ERROR PAUSE
;CALL: MOVE J,JOB NUMBER
; PUSHJ P,SIMCHK
; OK TO STOP JOB NOW RETURN
; WAIT TILL EXIT FROM MONITOR VIA UUO (BECAUSE JOB MAY HAVE A RESOURCE)
INTERN SIMCHK
SIMCHK: LDB T1,PJBSTS ;GET JOB STATUS CODE
MOVEI T2,1 ;BIT POS. IN DELAYN FOR STATE CODE 0
LSH T2,(T1) ;MOVE LEFT ACCORDING TO STATE CODE
SKIPL T1,JBTSTS(J) ;JOB STATUS. IS RUN BIT OFF?
POPJ P, ;YES, STOP JOB BUT DO NOT PRINT WATCH STATUS
TLNE T1,JERR ;NO, IS ERROR BIT ON?
POPJ P, ;YES. STOP JOB EVEN IF IN EXEC MODE
TLNE T1,SWP ;IS JOB IN CORE?
JRST STOPC ;NO. ASSUME PC IN EXEC MODE
MOVE R,JBTADR(J) ;RELOCATION FOR JOB (LOW SEG)
; (SIMCHK CALLED ON INT LEVEL ON DEVICE ERRORS)
JUMPE R,CPOPJ ;YES, DOES JOB HAVE CORE IN CORE?
PUSHJ P,SCPCDB## ;SET UP P4
MOVE T1,JOBPC##(R) ;YES, GET PC
CAMN J,.CPJOB##(P4) ;IS THIS JOB THE CURRENT JOB?
MOVE T1,.CPPC##(P4) ;YES, GET PC AND FLAGS FOR CURRENT JOB
TLNE T1,USRMOD ;JOB PC IN USER MODE?
POPJ P, ;YES, JOB CAN BE STOPPED
TLZ T1,-1 ;CLEAR PC FLAGS
CAIE T1,UUODON## ;AT THE END OF A UUO?
STOPC: TDNN T2,DELAYN ;NO, IS JOB IN A STATE(IN EXEC) WHICH
; CAN BE STOPPED IMMEDIATELY
POPJ P, ;YES, STOP JOB RETURN
PJRST CPSCHK## ;EXEC MODE PC AND NO DELAY, DOES JOB HAVE A
; RUNNABLE CPU SPECIFICATION? RETURN CPOPJ IF NO,
; CPOPJ1 TO CATCH JOB AT UUO EXIT
;DEFINE A BIT FOR EACH STATE CODE
; WHICH IS 1(DJ) MEANS DELAY JOB(IF PC IN EXEC MODE) WHEN CONTROL C TYPED
; IF 0(SJ), OK TO STOP JOB(IN EXEC MODE)
DEFINE X(A,B,C)
< IFIDN <C><DJ>,<QQ==1>
IFIDN <C><SJ>,<QQ==0>
YY==ZZ*QQ ;;SET THIS STATE CODE BIT TO 0 OR 1
XX==XX!YY ;;ACCUMULATE VALUES IN XX
ZZ==ZZ*2 ;;MOVE MASK BIT LEFT ONE PLACE
>
QQ==0 ;MAKE SURE INTERMEDIATE VALUE IS 0
XX==0 ;START FINAL VALUE AT 0
ZZ==1 ;START OFF BIT FOR STATE 0
QUEUES
RWAITS
CODES
INTERN DELAYN
DELAYN: EXP XX ;GENERATE THE DELAY WORD BIT 35=STATE 0,
; BIT 34=STATE 1, ETC.
; BIT 35-I=1 IF STATE I MUST BE DELAYED ON CONTROL C
;SETUTP -- ROUTINE TO SET UUO TRAP
;CALL: MOVE T1,NEW ADDR (-1 = JOBINT)
; PUSHJ P,SETUTP
;NON-SKIP IF START IMMEDIATELY
;SKIP IF DELAY TO END OF UUO
INTERN SETUTP
CHKUTP::LDB T3,PJBSTS ;GET WAIT CODE
CAIE T3,NAPQ## ;SEE IF NAPPING OR
CAIN T3,SLPQ ;SLEEPING
POPJ P, ;YES--START IMMEDIATELY
CAIE T3,TIOWQ ;SEE IF TTY WAIT (IN OR OUT)
JRST CPOPJ1## ;NO--DELAY
MOVE T3,TTYTAB##(J) ;GET TTY DDB
MOVE T3,DEVIOS(T3) ;GET STATUS
TLNE T3,IOW ;SEE IF IN IOWAIT
TLNN T3,TTYOUW## ;YES--SEE IF OUTPUT WAIT
POPJ P, ;NO--STARTUP IMMEDIATELY
JRST CPOPJ1## ;YES--DELAY
SETUTP: PUSHJ P,CHKUTP ;SEE IF WE CAN TRAP NOW
POPJ P, ;YES--DO IT NOW
;HERE IF TRAP MUST BE DELAYED UNTIL UUO EXIT
STUTRP: MOVEM T1,JOBFDV##(R) ;NO--SAVE START IN JOBDAT
MOVEI T3,UTRP ;SET FLAG FOR UUO EXIT
IORM T3,JBTSTS(J) ; THAT JOB DOESN'T DO NORMAL THING
JRST CPOPJ1 ;SKIP
;ROUTINE TO REQUE JOB WHICH HAS HAD A COMMAND TYPED
;WHICH NEEDS CORE AND THE CORE IMAGE IS ON THE DISK.
;OR IS IN CORE AND HAS ACTIVE DEVICES.
;CALLED FROM COMMAND DECODER
;CALL: MOVE J,JOB NO.
; PUSHJ P,DLYCOM
INTERNAL DLYCOM
DLYCOM: MOVSI T1,CMWB ;SET COMMAND WAIT BIT
IFN FTSWAP,<
TDNE T1,JBTSTS(J) ;IS JOB ALREDY IN COMMAND WAIT?
POPJ P, ;YES,JUST EXIT
>
IORM T1,JBTSTS(J) ;IN JOB STATUS WORD
INTERNAL FTSWAP
IFN FTSWAP,<
PJRST REQUE
>
IFE FTSWAP,<
POPJ P,
>
;ROUTINE TO PUT JOB IN NO CORE QUEUE
INTERNAL FTSWAP
IFN FTSWAP,<INTERNAL NOCORQ
EXTERNAL NULQ
NOCORQ: MOVEI T1,NULQ ;NO JOB NO. OR NO CORE QUEUE
DPB T1,PJBSTS
JRST REQUE
>
;SUBROUTINE TO SAVE AND RESTORE THE CONTEXT OF A JOB SO THAT THE
; JOB CAN BE CONTINUED AFTER RUNNING THE MONITOR JOB
;CALLING SEQUENCE:
; MOVE S,ITEM TO BE RETURNED
; MOVE J,JOB NUMBER
; PUSHJ P,SAVCTX
;RETURN HERE AT UUO LEVEL WITH THE FOLLOWING ACS CONTAINING THE
; FOLLOWING ITEMS
; P CONTAINS A POINTER TO THE STACK
; S CONTAINS THE ITEM TO BE RETURNED
; R CONTAINS THE PROTECTION,,RELOCATION OF THE JOB
; J CONTAINS THE JOB NUMBER
;UPON A POPJ FROM THE CALLING ROUTINE, THE JOB'S CONTEXT IS RESTORED
;N.B. THE STACK MUST BE SUCH THAT A "JRST DLYCM" WILL WORK
;IF THE JOB IS RUNNING (RUNNABLE), THE USER WILL GET THE MESSAGE
;"PLEASE TYPE ^C FIRST"
SAVCTX::SKIPGE JBTSTS##(J) ;JOB RUNNING OR RUNNABLE?
JRST SAVCT3 ;YES, FLUNK OUT NOW
PUSHJ P,FNDPDS## ;ADDRESS OF THE PDB
HRRZ T1,.PDSCX##(W) ;ALREADY BEEN HERE ONCE?
JUMPE T1,SAVCT1 ;JUMP IF NO
MOVE T2,4+P(T1) ;SAVED PUSH DOWN LIST POINTER
MOVEM T2,JOBDPD##(R) ;STORE IT FOR REUSE
JRST SAVCT2 ; AND PROCEED
SAVCT1: MOVEI T2,NWSCTX ;NUMBER OF WORDS REQUIRED TO SAVE THE JOB'S CONTEXT
PUSHJ P,GETWDS## ;GET THAT MUCH FREE CORE
JRST [POP P,(P) ;NOT AVAILABLE, POP OFF CALLERS PC
JRST DLYCM##] ;WAIT A TICK AND TRY AGAIN
MOVE T2,JBTSTS##(J) ;THE JOB'S CURRENT STATUS
MOVEM T2,2(T1) ;SAVE THAT
MOVE T2,JOBPC##(R) ;THE JOB'S CURRENT PC
MOVEM T2,3(T1) ;SAVE THAT TOO
MOVSI T2,JOBDAC##(R) ;MAKE A BLT POINTER TO THE JOB'S
HRRI T2,4(T1) ; USER AND EXEC ACS
BLT T2,17+4(T1) ;SAVE THE JOB'S ACS
SAVCT2: MOVEM S,(T1) ;STORE ITEM TO BE RETURNED TO THE CALLER
POP P,1(T1) ;STORE THE CALLER'S PC
MOVE T2,TTCMCH## ;SAVE TIMESHARED LOCS FOR COMCON
MOVEM T2,24(T1)
MOVE T2,TTCMCA##
MOVEM T2,25(T1)
HRRM T1,.PDSCX##(W) ;REMEMBER THE ADDRESS OF THE BLOCK CONTAINING
; THE JOB'S CONTEXT
TLO M,RUNFLG## ;TTYRNU+NOMESS+NOCRLF+NOPER
PJSP T2,MSTART ;START THE MONITOR JOB
;RETURN HERE AT UUO LEVEL
MOVE J,.C0JOB## ;CURRENT JOB'S JOB NUMBER
MOVE R,JBTADR##(J) ; AND ITS ADDRESS
HRRZ W,JBTPDB##(J) ;ADDRESS OF THE PDB
HRRZ T1,.PDSCX##(W) ;ADDRESS OF THE SAVED CONTEXT
MOVE T2,3(T1) ;THE JOB'S PC WHEN STOPPED
MOVE T3,2(T1) ;JBTSTS
TLNE T3,JERR ;JOB NOT CONTINUABLE?
JRST .+3 ;YES, USE UUO LEVEL STACK ALWAYS
TLNN T2,(XC.USR) ;WAS THE JOB IN USER MODE?
SKIPN P,JOBDPD##(R) ;NO, USE THE CURRENT STACK POINTER IF THERE IS ONE
JRST [MOVSI P,MJOBPD## ;YES OR NO EXEC STACK POINTER,
HRRI P,JOBPDL##(R) ; SO SETUP THE STACK TO POINT AT THE
JRST .+1] ; JOB'S JOB DATA AREA
PUSHJ P,TTYFUW## ;FIND THE JOB'S TTY (WAIT IF NECESSARY
; BEFORE RESTORING TTCMCH AND TTCMCA)
HRRZ T1,.PDSCX##(W) ;RESTORE THE ADDRESS OF THE CONTEXT BLOCK
HRRZM U,CMDLIN## ;SEE STOPCM IN SCNSER
MOVE T2,24(T1) ;RESTORE TIMESHARED LOCS FOR COMCON
MOVEM T2,TTCMCH## ;SAVE TIMESHARED LOCS FOR COMCON
MOVE T2,25(T1)
MOVEM T2,TTCMCA##
MOVE S,(T1) ;SETUP ITEM TO BE RETURNED
TLO M,400000 ;INDICATE THIS IS A COMMAND
PUSHJ P,@1(T1) ;CALL THE CALLER TO SAVCTX AS A SUBROUTINE
JFCL ;ALLOW A SKIP RETURN AS A CONVENIENCE
PUSHJ P,TTYFUW## ;FIND THE JOB'S TTY AND RESTORE J
PUSHJ P,FNDPDS## ;ADDRESS OF THE PDB
HRRZ T2,.PDSCX##(W) ;ADDRESS OF THE JOB'S SAVED CONTEXT
PUSH P,3(T2) ;THE SUPPENDED JOB'S PC
MOVSI T1,4(T2) ;FORM A BLT POINTER
HRRI T1,JOBDAC##(R) ; TO THE JOB'S SAVED ACS
BLT T1,JOBD17##(R) ;RESTORE THE JOB'S SAVED ACS
PUSH P,2(T2) ;JOB'S PREVIOUS JBTSTS
MOVEI T1,NWSCTX ;NUMBER OF WORDS TO RETURN TO FREE CORE
PUSHJ P,GIVWDS## ;RETURN MONITOR FREE CORE
HLLZS .PDSCX##(W) ;INDICATE NO SAVED CONTEXT
POP P,T1 ;RESTORE PREVIOUS JBTSTS
TLNE T1,JERR ;WAS THE JOB IN A CONTINUABLE STATE?
JRST [HRRZS JOBPD1##(R) ;NO, STOP THE JOB AND DON'T ALLOW CONTINUE
PJRST HOLD]
PUSHJ P,HOLD0 ;YES, ITS STILL CONTINUABLE
PJRST USCHED
SAVCT3: MOVEI T1,RUNERR## ;"PLEASE TYPE ^C FIRST"
POP P,(P) ;POP OFF CALLER'S PC
PJRST ERRMES## ;PRINT THAT AND RETURN TO COMCON
;ROUTINE TO SETUP MONITOR JOB TO RUN LATER AT UUO LEVEL
;CALLED BY COMMANDS WHICH MAY OR MAY NOT NEED TO
;RUN MONITOR JOB DEPENDING ON WHETHER JOB HAS CORE(KJOB,IJOB)
;TTY WILL REMAIN IN MONITOR MODE
;JOB MUST HAVE CORE ASSIGNED
;CALL: MOVE J, JOB NUMBER
; MOVEI T2,ADDR. OF MONITOR JOB TO BE RUN
; PUSHJ P,MONJOB
;WHEN SCHEDULED TO RUN, MONITOR JOB MUST SET UP ITS OWN ACS
INTERNAL MONJOB
MONJOB:
IFN FTMS,< EXTERNAL CLRJSP
PUSHJ P,CLRJSP ;RESET JBTSPS WORD FOR THIS JOB
;THIS INSURES THAT THE MONITOR JOB RUNS ON MASTER
>
PUSHJ P,MSTART ;START WITH PC IN MONITOR
JRST SETRUN ;SET TTY TO START JOB WHEN COMMAND RESPONSE
; IS FINISHED AND KEEP TTY IN MONITOR MODE
;ROUTINE TO SETUP ACS FOR MONITOR JOB STARTING AT UUO LEVEL
;SETS UP J, WITH JOB NO.; R WITH RELOCATION, AND P
;WITH PUSH DOWN LIST ADR. IN JOB DATA AREA
;USED BY KJOB,CORE 0,SAVE,GET,RUN,R,REASSIGN AND FINISH COMMANDS
;CALL: MOVEI T2,MONITOR JOB STOP ADDRESS
; JSP T1,MONSTR
; RETURN WITH ACS P,R,W,M, AND J SETUP
INTERNAL MONSTR
EXTERNAL JBTADR,MJOBPD,JOBPDL,JBTDAT
MONSTR: SKIPN J,.C0JOB ;CURRENT JOB NUMBER
STOPCD .,STOP,NDS, ;++NULL-JOB DID SAVGET
MOVE R,JBTDAT(J) ;ADR. OF JOB DATA AREA
MOVSI P,MJOBPD ;MINUS LENGTH OF SYSTEM PD LIST
HRRI P,JOBPDL(R) ;FIRST LOC.-1 OF PD LIST
PUSHJ P,FNDPDB## ;ADDRESS OF PDB FOR THIS JOB
JFCL
IFN FTMS,< EXTERNAL CLRJSP
PUSHJ P,CLRJSP ;CLEAR JBTSPS WORD FOR THIS JOB
>
TLZ T2,-1 ;CLEAR STRAY PC BITS
PUSH P,T2 ;SAVE STOP ADRRESS
MOVSI M,FLMCOM## ;SET FLAG FOR COMMAND AT UUO LEVEL
JRST (T1) ;RETURN AND DO MONITOR JOB
; WITH TTY DDB,OUTPUT BYTE POINTER, AND JOB NO.
;ROUTINE TO SET JOB STATE TO BE SCHEDULED TO RUN
;WITH SPECIFIED STARTING ADDRESS INCLUDING PC FLAGS
;CALLED ONLY WHEN JOB IN CORE AND AFTER JOB HAS BEEN
;SAFELY STOPPED IN ONE OF 3 STATES:
;1) PC IN USER MODE
;2) JOB IN A WAIT FOR SHARABLE DEVICE, OR IO WAIT
;3) JOB JUST ABOUT TO RETURN TO USER MODE FROM A UUO CALL
;CALL: MOVE T2,STARTING PC
; MOVE J, JOB NUMBER
; MOVE R,ADR. OF JOB DATA AREA WHICH MUST BE IN CORE
; PUSHJ P,USTART(PC TO USER MODE),MSTART(PC TO MONITOR MODE)
; RETURN HERE IMMEDIATELY
INTERNAL MSTART,USTART,RSTART
EXTERNAL JOBPC,JOBDAC,JOBD17,JOBOPC,JOBPD1
USTART:
MOVE T1,JOBPC(R) ;GET OLD PC
TLNE T1,USRMOD ;IS IT IN USER MODE TOO?
JRST USTRT1 ;YES, DUMP ACS AND PC FLAGS ARE ALREADY HIS
IFN FTKA10,<
MOVEI T1,JOBDAC(R) ;NO, MOVE USERS(UUO) ACS TO DUMP ACS
HRL T1,R ;SOURCE=REL. 0,DEST.=JOBDAC IN JOB DATA AREA
BLT T1,JOBD17(R) ;MOVE ALL ACS
>
MOVE T1,JOBPD1(R) ;GET LAST PC + 1
HRRI T1,-2(T1) ;DECREMENT TWICE IN CASE THIS IS HIBER
PUSH P,T2
MOVSI T2,(JS.HIB) ;HIBER UUO?
TDNN T2,JBTST2##(J)
HRRI T1,1(T1) ;NO. DECREMENT ONLY ONCE
POP P,T2
; (RH=0 ON HALT 0 OR FIRST START)
USTRT1:
MOVEM T1,JOBOPC(R) ;STORE OLD PC FOR USER TO LOOK AT
HLL T2,T1 ;PRESERVE USER APR FLAGS
TLO T2,USRMOD ;MAKE SURE NEW PC IN USER MODE
IFN FTKI10!FTKL10,<
TLO T2,(XC.PUB) ;INSURE PUBLIC IS SET
>
TLZ T2,37 ;MAKE SURE NO INDIRECT BITS OR INDEX FIELD
IFN FTMS,< EXTERNAL DPXST
PUSHJ P,DPXST ;MAKE JOB RUNNABLE ON SLAVE NOW
>
JRST MSTRT1 ;DON'T CLEAR JSP WORD
MSTART:
IFN FTKI10!FTKL10,<
TLO T2,(IC.UOU) ; INSURE USER IOT IS ON
>
IFN FTMS,< EXTERNAL CLRJSP
PUSHJ P,CLRJSP ;INITIALIZE JBTSPS ENTRY
>
MSTRT1: CAMN J,.C0JOB ;IS IT THE CURRENTLY RUNNING JOB?
MOVEM T2,.C0PC ;YES - SAVE NEW PC IN USRPC IN CASE WE'RE AT
; CLOCK LEVEL AND HAVE EXITED FROM CURRENT JOB.
; THIS WILL AVOID THE PROBLEM OF GOING BACK TO JOB.
; THE LOCATION AFTER THE "CALLI 12" BECAUSE
; SOFTWARE AND HARDWARE STATUS OF JOB ARE NEVER CHANGED.
MOVEM T2,JOBPC(R) ;STORE NEW PC
MOVE T1,[XWD WTMASK+JERR,UTRP] ;CLEAR TRAP TO USER AT UUO EXIT,
; WAIT STATE CODE AND ERROR IN JOB BIT
ANDCAM T1,JBTSTS(J) ;IN JOB STATUS WORD
;ROUTINE TO CLEAR FLAGS SO A JOB CAN CONTINUE IN MIDDLE OF MONITOR
; (CALLED ON REENTER AND DDT COMMANDS).
RSTART: MOVE T1,[XWD CNTRLC,JS.MPE+JS.JDP+JS.APE+JS.DPM] ;CLEAR TYPED ^C FLAG
; CLEAR MEM PAP ERR, MEM PAR IN JOB DATA AREA,
; APR ERROR, DAEMON PROBLEM MESSAGE
ANDCAM T1,JBTSTS(J) ;IN JOB STATUS WORD
MOVSI T1,(JS.HIB) ;CLEAR HIBER BIT
ANDCAM T1,JBTST2##(J)
POPJ P, ;RETURN
;ROUTINE TO SET JOB STATUS RUN BIT(RUN)
;CALLED BY SCANNER SERVICE WHEN TTY MONITOR COMMAND
;RESPONSE FINISHES. THIS ACTION IS ENABLED BY CALLING
;TTYUSR, OR TTYURC IN SCNSER
;CALL: MOVE J,JOB NUMBER
; PUSHJ P,SETRUN
INTERNAL SETRUN,SETR2
EXTERNAL JBTSTS,PJBSTS,RQTBMQ,AVTBMQ
EXTERNAL MINQ,MAXQ
SETRUN: IFN FTDAEM,<
MOVEI T1,JDC ;SEE IF WAITING
TDNE T1,JBTSTS(J) ; FOR DAEMON
POPJ P, ;YES--DO NOT REQUEUE
>
LDB T1,PJBSTS ;GET JOB STATUS WAIT QUEUE CODE
IFN FTSWAP,<
CAIL T1,MINQ ;SHARABLE RESOURCE STATE CODE?
>
CAILE T1,MAXQ ;DOES JOB STATUS CODE HAVE A QUEUE?
JRST SETR1 ;NO
AOSLE RQTBMQ(T1) ;ADD TO REQUEST COUNT
JRST SETR1 ;OTHERS WAITING?
AOSG AVTBMQ(T1) ;MAKE AVAILABLE
SETOM AVTBMQ(T1) ;FLAG AS JUST AVAILABLE, BECAUSE
; NO JOB WAS USING DEVICE. SCHEDULER
; WILL SCAN THIS QUEUE
SETR1: CAIE T1,EWQ ;IF IN EVENT WAIT
JRST SETR1A
MOVEI T1,RNQ## ;THEN SET TO RUN STATE
DPB T1,PJBSTS
SETR1A: IFN FTRSP,<
PUSHJ P,SETRSP ;SET TIME USER BEGAN TO WAIT FOR RESPONSE
>
IFN FTKL10&FTMS,<
PUSHJ P,SETCSJ## ;CAN'T RUN ON CPU1 UNTIL A SWEEP IS DONE
>
MOVSI T1,RUN ;SET RUN BIT IN JOB STATUS WORD
IORM T1,JBTSTS(J)
;HERE FROM WAKE UUO IN UUOCON
SETR2: MOVE T1,QADTAB## ;SET QUANTUM TIME TO RUN QUEUE QUANTUM
PUSH P,W
IFE FTPDBS,< ;IF WE KNOW PDB IS IN CORE
SKIPN T2,JBTPDB##(J) ;GET PDB ADR
STOPCD .,JOB,CFP, ;++CAN'T FIND PDB
.DPB T1,PDYQT2## ;SET QUANTUM RUN TIME
> ;END FTPDBS
IFN FTPDBS,< ;IF PDB MAY BE ON THE DISK
PUSHJ P,SETQNT## ;CALL SUBROUTINE TO SET UP .PDQNT
> ;END FTPDBS
POP P,W
INTERNAL FTSWAP
IFE FTSWAP,<
JRST NJBTST ;GO SEE IF NULL JOB IS RUNNING
>
IFN FTSWAP,<
INTERNAL REQUE
EXTERNAL JBTSTS
REQUE: SKIPN J ;TRYING TO REQUEUE THE NULL JOB?
STOPCD CPOPJ,DEBUG,PJ0, ;++REQUEUE JOB 0
IFN FTMS,<
SKPCPU (0) ;CPU 0?
STOPCD .,STOP,RC1, ;CAN'T CALL REQUE FROM SECOND CPU
>
MOVSI T1,JRQ ;MARK JOB TO BE REQUEUED WITH JRQ BIT
CONO PI,PIOFF ;GUARD AGAINST COUNTING QJOB UP TWICE
TDNE T1,JBTSTS(J) ;INCREMENT COUNT ONLY ONCE FOR EACH JOB
JRST REQUE1 ;JOB IS ALREADY MARKED FOR REQUEING
IORM T1,JBTSTS(J) ;SET REQUE BIT FOR SCHEDULER
MOVE T1,JBTJRQ## ;ADD TO FRONT OF LINKED LIST
HRRZM J,JBTJRQ## ;NEW FIRST
MOVEM T1,JBTJRQ##(J) ;OLD FIRST NOW SECOND
REQUE1: PJRST ONPOPJ## ;TURN ON
;PI AND RETURN
>
;SUBROUTINE TO PUT JOB IN EVENT WAIT
;CALL: MOVE T1,<REASON>
; MOVE J,<JOB NUMBER>
; PUSHJ P,ESLEEP
; RETURN HERE WHEN SOME EVENT HAPPENS
;ENTER AT FSLEEP IF THE EVENT WHICH IS BEING WAITED FOR IS LIKELY
; TO OCCUR SOON (WITHIN MILLISECONDS) AND THE JOB SHOULD NOT
; BECOME MORE SWAPPABLE AS A RESULT OF GOING INTO EVENT WAIT
ESLEEP::PUSH P,W ;SAVE W
PUSHJ P,ZERIPT## ;FIND PDB, MARK JOB AS SWAPPABLE
PUSHJ P,FSLEEP ;WAIT FOR THE EVENT
JRST WPOPJ## ;RESTORE W AND RETURN
FSLEEP::PUSHJ P,SAVE1## ;SAVE P1
MOVEI T2,EWAKEB ;WAKUP BIT
MOVEI P1,EWQ## ;Q TO PUT JOB INTO
CONO PI,PIOFF## ;SOLVES ALL RACES
TDNN T2,JBTST2##(J) ;LOOK IN STATUS WORD
JRST ESLP1 ;PUT HIM TO SLEEP
ANDCAM T2,JBTST2##(J) ;ELSE CLEAR BIT
PJRST ONPOPJ## ; TURN ON PI
; AND RETURN
;HERE TO PUT JOB TO SLEEP
ESLP1: DPB P1,PJBSTS## ;SET WAIT STATE
DPB T1,JBYEWT## ;SET REASON CODE
CONO PI,PION## ;RESTORE PI SYSTEM
PJRST WSCHED ;RESCHEDULE
;SUBROUTINE TO WAKE UP JOB IN EW
;CALL: MOVE T1,<JOB NUMBER>
; PUSHJ P,EWAKE
; RETURN HERE
;CLOBBERS T1,T2
EWAKE:: PUSH P,J ;SAVE J
MOVE J,T1 ;JOB # TO J
MOVEI T1,RNQ## ;RUN QUEUE
CONO PI,PIOFF## ;INTERLOCK
LDB T2,PJBSTS## ;GET STATE CODE
CAIE T2,EWQ## ;WAITING?
JRST NOTEW ;NO - REMEMBER THEN
IFN FTPSCD,<
AOS %EWCNT## ;COUNT EW SATISFIED
>
PUSH P,W ;SAVE W
PUSHJ P,WAKOKE## ;WAKE UP JOB
JFCL ;IN CASE OF NON-SKIP
POP P,W ;RESTORE W
PJRST JPOPJ## ;RESTORE J AND RETURN
NOTEW: MOVEI T2,EWAKEB ;SET BIT FOR LATER
IORM T2,JBTST2##(J)
CONO PI,PION##
PJRST JPOPJ## ;EXIT
;SUBROUTINE TO SET TIME USER STARTED TO WAIT FOR RESPONSE
; IF NOT ALREADY CALLED WHEN A COMMAND IS DELAYED
IFN FTRSP,<EXTERN JBTRSP
INTERN SETRSP
SETRSP: MOVE T1,.C0UPT ;TIME SYSTEM HAS BEEN UP IN JIFFIES
SKIPE T2,JBTRSP(J) ;HAS USER STOPPED WAITING?
; (DELAYED COMMAND)
TLNE T2,(JR.RXX) ;NO, HAVE ANY RESPONSES BEEN STORED?
; (NEXT CALL ON DELAYED COMMAND WILL NOT
; STORE, SO INCLUDE DELAY IN RESPONSE TIME)
MOVEM T1,JBTRSP(J) ;YES, STORE TIME USER BEGAN TO WAIT FOR RESPONSE
; SEE SYSRSP, NUMRSP. SCHEDULER ACCUMULATES AVERAGE
; RESPONSE
POPJ P,
>
;ROUTINE TO RECORD RESPONSE SATISFIED BY TTY OUTPUT UUO EXECUTION
;
;CALL: PUSHJ P,RSPTOR
; RETURN
IFN FTRSP,<
RSPTOR::MOVEI T1,.C0AOR## ;BASE ADR FOR 3 WORD TTY OUTPUT UUO RSP
; ON CPU0
MOVSI T2,(JR.ROR) ;RECORD TTY OUT UUO RSP FOR THIS JOB
PJRST RSPRC1 ;GO RECORD UNLESS ALREADY
;ROUTINE TO RECORD RESPONSE SATISFIED BY TTY INPUT UUO EXECUTION
;CALL: PUSHJ P,RSPTIR
; RETURN
RSPTIR::MOVEI T1,.C0AIR## ;BASE ADR. FOR 3 WORD TTY INPUT UUO RSP
; ON CPU0
MOVSI T2,(JR.RIR) ;RECORD TTY INPUT UUO RSP FOR THIS JOB
;FALL INTO RSPRC1
;ROUTINES TO RECORD RESPONSE DATA FOR VARIOUS TYPES OF RESPONSES
;CALL: MOVE P4,CPU DAT BLOCK
; MOVE J,JOB NUMBER
; MOVEI T1,.CPA??##(P4) ;BASE ADR OF 3 WORD BLOCK IN CDB
; MOVSI T2,(RS.R??) ;BIT - ALREADY RECORDED THIS RESPONSE
; TDNN T2,JBTRSP(J) ;OPTIONAL TEST TO SEE IF RECORDED
; PUSHJ P,RSPRC2 OR RSPREC
; RETURN
RSPRC1::MOVEI P4,.C0CDB## ;SETUP CPU0 CDB POINTER
MOVE J,.C0JOB## ;CURRENT JOB ON CPU0
RSPRC2::PUSHJ P,RSPREC ;RECORD THIS RESPONSE
MOVEI T1,.CPAXR##(P4) ;ADDR FOR ANY OF TTY OUT, TTY IN, OR REQUE
; RESPONSE TERMINATIONS
MOVSI T2,(JR.RXR) ;RECORDED ANY OF TTYOUT, TTYIN, OR REQUE
;UNTIL FIRST CPU RESPONSE ONLY
RSPREC::TDNE T2,JBTRSP##(J) ;RECORDED IT YET?
POPJ P, ;YES, RETURN
IORB T2,JBTRSP##(J) ;GET UP TIME STARTED TO WAIT FOR RESPONSE
TLZ T2,(JR.RXX) ;CLEAR OUT ALL RESPONSE BITS
MOVNS T2 ;NEGATIVE
ADD T2,.C0UPT ;UP TIME NOW - START=RESPONSE TIME
ADDM T2,RSPAXR##(T1) ;ACCUM SUM OF RSP OF THIS TYPE FOR THIS CPU
MUL T2,T2 ;T2,T3=SQUARE OF RESPONSE
; (FOR STANDARD PEVIATION)
TLO T3,400000 ;FORCE SIGN NEG OF LOW ORDER WORD
; SO DIFFERENT FROM ACCUM SO NEVER OVF. INT.
CONO PI,PIOFF ;ALLOW ONLY ONE UPDATE AT A TIME
ADD T3,RSPLXR##(T1) ;ADD LOW ORDER SQUARE
TLZN T3,400000 ;DID AN OVERFLOW OCCUR?
ADDI T2,1 ;YES, PROPAGATE CARRY TO HIGH ORDER WORD
MOVEM T3,RSPLXR##(T1) ;NOW STORE LOW ORDER WITH SIGN ALWAYS 0
CONO PI,PION ;ALLOW INT AGAIN
ADDM T2,RSPHXR##(T1) ;ACCUM. HIGH ORDER SQUARE
AOS RSPNXR##(T1) ;COUNT NO. OF RESPONSES OF THIS TYPE
POPJ P,
>
;END RESPONSE
IFN FTTLIM,< INTERNAL MTIMLM,TLEMES
MTIMLM: PUSHJ P,TTYERP## ;LIMIT JUST WENT TO 0 - FIND TTY DDB
IFN FTOPRERR,<
JRST MTIML1 ;TIME LIMIT EXCEEDED FOR DETACHED JOB
>
PUSHJ P,INLMES## ; AND THE MESSAGE:
TLEMES: ASCIZ /?
?Time limit exceeded
/
IFN FTPI,<
PUSHJ P,PSIERR## ;IF INTERCEPTING TLE,
POPJ P, ; GO TO THE USER
POPJ P,
>
PUSHJ P,TSETBI ;CLEAR TYPE AHEAD
JRST HOLD0 ;STOP JOB, DONT SET JERR
; (SO "CONT" WILL WORK)
IFN FTOPRERR,<
MTIML1: PUSHJ P,ERINDJ## ;SET UP TO GIVE MESSAGE TO OPR
MOVEI T1,TLEMES ;
PUSHJ P,CONMES## ; AND GO GIVE IT
JRST ESTOP3 ; AND THEN STOP THE USER
> ;END FTOPRERR
> ;END FTTLIM
;ROUTINE TO PUT A JOB TO SLEEP AND WAKE UP AGAIN LATER
;CALLED AFTER CLOCK QUEUE REQUEST PUT IN BY UUO ROUTINE
INTERNAL FTSLEEP
IFN FTSLEEP,<
INTERNAL SETSLP
EXTERNAL JBTSTS,SLPQ
SETSLP:
MOVEI 16,SLPQ ;SLEEP STATE CODE
JRST SETNP1 ;SET STATUS AND RESCHEDULE
;HERE FROM UUOCON TO PUT A JOB INTO NAP STATE. THIS MERELY
; HAS THE EFFECT OF MAKING ITS WAIT STATE CODE NON-ZERO WHILE
; LEAVING IT IN THE RUN QUEUE. IF A JOB SLEEPS OR HIBERNATES
; FOR LESS THAN ONE SECOND, IT IS PUT INTO NAP STATE RATHER THAN
; SLEEP, SO THAT IT WILL NOT GET BACK INTO PQ1 WHEN IT WAKES UP.
SETNAP::MOVEI 16,NAPQ## ;PUT INTO NAP STATE
SETNP1: MOVEI T1,CLKR ;FLAG THAT A CLOCK REQUEST HAS BEEN PUT IN
IORM T1,JBTSTS##(J)
JRST SETSTT ;SET STATUS AND RESCHEDULE
;HERE AT CLOCK LEVEL WHEN CLOCK REQUEST TIMES OUT FOR SLEEP
;JOB NO. IN AC T1
INTERNAL WAKEJ
EXTERNAL PJBSTS,SLPQ
WAKEJ: MOVEI T2,RNQ## ;RUN QUEUE CODE
MOVE J,T1 ;JOB NO.
MOVEI T1,CLKR ;CLEAR CLOCK REQUEST BIT FOR THIS JOB
ANDCAM T1,JBTSTS(J) ;SO IT CAN PUT ANOTHER ONE IN
MOVSI T1,(JS.HIB) ;CLEAR THE SLEEP BIT TOO!
ANDCAM T1,JBTST2##(J)
LDB T1,PJBSTS ;GET QUEUE CODE
CAIE T1,NAPQ## ;IS JOB NAPPING?
JRST WAKE1 ;NO.
DPB T2,PJBSTS## ;YES, MAKE HIM RUNNABLE AGAIN
POPJ P, ;RETURN
WAKE1: CAIE T1,SLPQ ;IS JOB STILL SLEEPING?
POPJ P, ;NO. RETURN TO CLOCK ROUTINE
IFN FTPSCD,<
AOS REQSS## ;COUNT A SLEEP SATISFIED
>
DPB T2,PJBSTS ;YES, STORE RUN QUEUE CODE
; (CONTROL C, START CAN GET JOB OUT OF SLEEP)
JRST SETR2
>
;ROUTINE TO WAKE UP DAEMON AND STOP USER WITH DEVICE ERROR
; UNTIL DAEMON HAS A CHANCE TO ENTER ERROR IN LOG FILE.
;CAN BE CALLED AT ANY LEVEL:
;CALL: MOVE F,DEVICE DATA BLOCK ADR.
; MOVEI T1,CODE FOR THIS ERROR
; HRL T1,CDB OR DDB ADDR
; PUSHJ P,DAEERR OR DAESJE
; ALWAYS RETURN J PRESERVED, T1, T2 USED
IFN FTEL,< ;ERROR LOGGING?
INTERN DAEERR,DAESJE,DAEEIM,DAERPT
EXTERN JOB,PJOBN,SYSERR
DAEERR: PUSH P,J ;SAVE J(FILIO USES J FOR CONTROLLER DATA BLOCK)
LDB J,PJOBN ;GET JOB NUMBER FORM DEVICE DATA BLOCK
MOVE T2,DEVSTA(F) ;WHERE DISABLE ERROR LOGGING BUT IS
TRNE T2,DEPDEL ;ERROR LOGGING DISABLED FOR THIS DEVICE
; BY USER ON OPEN UUO (USER MODE DIAG)
AOSA DELCNT## ;YES, JUST KEEP COUNT AND RETURN
; DO NOT STOP USER OR WAKE DAEMON
PUSHJ P,DAESJE ;STOP JOB AS SPECIFIED BY J
JRST JPOPJ## ;RESTORE J AND RETURN
;ROUTINE TO WAKE DAEMON AND, STOP SPECIFIED JOB
;CALL: MOVE J,JOBNUMBER
; MOVEI T1,CODE FOR THIS ERROR
; HRL T1,CDB OR DDB ADDR
; PUSHJ P,DAESJE
; ALWAYS RETURN
DAEEIM: MOVEI J,0 ;ERROR IN MONITOR, BLAME JOB 0
DAESJE: AOS SYSERR ;INCREMENT NO OF SYSTEM ERRORS FOR DAEMON
DAERPT: CONO PI,PIOFF## ;NEED TO TURN OF PI'S TO STOP TWO I
; HITTING END OF TABLE AT SAME TIME
AOS ESVIDX##
AOS T2,ESVIDX## ;GET INDEX FOR NEXT ERROR TO SAVE
CAIL T2,ERPTMX## ;HAVE WE EXCEEDED MAX
SETZB T2,ESVIDX## ;YES, JUST RESET ESVIDX
CONO PI,PION## ;TURN THE PI'S BACK ON
SKIPE ERPTBK##(T2) ;HAVE WE OVERLAPPED
JRST MNYERR ;YES, DAEMON ISN'T KEEPING UP, LOSE THIS ERROR
DPB J,[POINT 9,T1,26]
MOVEM T1,ERPTBK##(T2) ;SAVE T1 FOR ERRPT. UUO
MOVE T1,U
HRL T1,F
MOVEM T1,ERPTBK##+1(T2)
PUSHJ P,STDAEM ; SO DAEMON WILL KNOW AN ERROR HAPPENED
;WAKE UP DAEMON - RETURN T1=DAEMON JOB #
POPJ P, ;DAEMON NOT RUNNING
JUMPE J,CPOPJ ;IF ERROR IN MONITOR DON'T TRY TO STOP A JOB
MOVEI T2,JS.DEP ;STOP USER WHO HAD ERROR
PUSHJ P,FLSDR## ;JOB HAVE DISK RESOURCE?
CAMN J,T1 ;NO. IS IT DAEMON?
POPJ P, ;YES, DONT STOP HIM
IORM T2,JBTSTS(J) ;NO, STOP HIM, DAEMON WILL CONTINUE
IFN FTKI10!FTKL10,<
PUSHJ P,SVEUB## ;SINCE CAN BE AT INTERRUPT LEVEL, MAKE THE
; JOB DATA AREA ADDRESSABLE
>
PUSHJ P,SIMCHK ;CAN JOB BE STOPPED NOW (OR MUST IT
; WAIT TILL UUO EXIT)?
PJRST STOP1B ;YES, STOP HIM NOW
POPJ P, ;NO, LET UUO RETURN STOP JOB
MNYERR: AOS ERRLAP## ;COUNT TIMES WE'VE OVERFLOWED BLOCK
POPJ P, ;AND JUST RETURN
> ;END FTEL
IFE FTEL,<
DAEERR::DAEEIM::DAESJE:: POPJ P,
>
IFN FTDAEM,< ;DAEMON FEATURE?
INTERN STDAEM
;ROUTINE TO FIND DAEMON, START RUNNING
;RETURNS POPJ IF CANT FIND, CPOPJ1 IF OK, T1 = DAEMON JOB #
STDAEM: MOVE T1,HIGHJB ;SCAN ALL JOBS
STDAE1: MOVE T2,JBTNAM(T1) ;PROGRAM NAME
CAME T2,[SIXBIT/DAEMON/] ;IS THIS DAEMON?
JRST STDAE2 ;NO
MOVE T2,JBTSTS(T1) ;JOB STATUS WORD
IFN FTLOGI,<
TLNE T2,JACCT
> ;IS THIS DAEMON PRIVELEGED?
TLNN T2,RUN ;YES, IS IT RUNNING
JRST STDAE2 ;NO, KEEP LOOKING
LDB T2,PJBS2
CAIN T2,TIOWQ
JRST STDAE2
PUSH P,T1 ;WAKJOB DESTROYS THE DAEMON JOB NUMBER
PUSHJ P,WAKJOB## ;WAKE UP DAEMON
PJRST TPOPJ1## ;AND OK RETURN (DAEMON STARTED)
STDAE2: SOJG T1,STDAE1 ;LOOP FOR MORE JOBS
POPJ P, ;COULD NOT FIND DAEMON, 'ERROR RETURN'
;ROUTINE TO START A JOB WHEN DAEMON IS DONE
;CALL: MOVE J,JOB NO. OF USER TO START
; PUSHJ P,DAEDON
; ALWAYS RETURN HERE
;CALLED FROM DAEFIN UUO
INTERN DAEDON
DAEDON: MOVEI T1,JDC!JS.DPM ;DAEMON BIT FOR REQUEING AND DAEMON PROBLEM
; MESSAGE BIT (ONCE-A-MIN)
ANDCAM T1,JBTSTS(J) ;CLEAR IT IN JOB STATUS WORD
MOVEI T1,JS.DEP ;DAEMON ERROR PAUSE BIT
LDB T2,PJBSTS ;USER WAIT STATE CODE
TDNN T1,JBTSTS(J) ;WAS USER IN ERROR PAUSE?
CAIN T2,JDCQ## ;NO, WAS USER IN DAEMON QUEUE?
JRST DAEFN3 ;YES, START USER UP IF STILL RUNNABLE
PUSHJ P,TTYSRC## ;NO, MUST HAVE BEEN DUMP COMMAND, FIND TTY
MOVEI U,0 ;NONE FOUND
TRNE U,-1 ;FIND A LINE?
PUSHJ P,TTYSTC ;YES, SET BACK TO COMMAND LEVEL
POPJ P, ;RETURN
;HERE ON UUO CALL TO DAEMON OR DAEMON ERROR PAUSE
DAEFN3: ANDCAM T1,JBTSTS(J) ;CLEAR DAEMON ERROR PAUSE BIT
IFN FTPSCD,<
AOS REQJSD## ;COUNT DAEMON RESPONSE
>
MOVEI T1,RNQ## ;SET WAIT STATE CODE BACK TO RUN
CAIN T2,JDCQ## ;DON'T REQUEUE IF NOT IN DAE QUEUE
DPB T1,PJBSTS ;IN JOB STATUS WORD
PJRST REQUE ;REQUE USER SO WILL RUN IF HE
; HASN'T TYPED CONTROL C.
> ;END FTDAEM
IFN FTDAEM,<
;ERRPT. UUO
;USED BY DAEMON TO OBTAIN NEXT DEVICE/CONDITION
;WITH AN ERROR THAT MUST BE LOGGED
;NON SKIP RETURN IF NO OTHER ERRORS OR NO PRIVS
;RETURNS CODE,,DDB ADDRESS IN AC ON SKIP RETURN
ERRPT.::PUSHJ P,PRVJ## ;IS THIS GUY PRIVILEGED?
SKIPA T2,EPKIDX## ;GET NEXT WORD TO LOOK AT IN TABLE
POPJ P, ;NO, GIVE ERROR RETURN
CAIL T2,ERPTMX## ;OFF END OF TABLE?
SETZ T2, ;YES, RESET POINTERS
HRR M,T1
ERPTLP: SKIPE T1,ERPTBK##(T2) ;IS THIS ENTRY 0?
JRST GOTONE ;NO, RETURN IT
ADDI T2,2
CAMN T2,EPKIDX## ;LOOKED AT ALL ENTRIES?
POPJ P, ;YES, NONE FOUND
CAIL T2,ERPTMX## ;OFF END OF TABLE
SETZ T2, ;YES, RESET TO BEGINNIG OF TABLE
CAMN T2,EPKIDX## ;LOOKED AT ALL ENTRIES?
POPJ P, ;YES, NOTHING FOUND
JRST ERPTLP ;LOOP BACK FOR NEXT ENTRY
GOTONE: SETZM ERPTBK##(T2) ;ZERO THIS ENTRY
PUSHJ P,PUTWDU##
MOVE T1,ERPTBK##+1(T2)
PUSHJ P,PUTWD1##
ADDI T2,2
MOVEM T2,EPKIDX## ; AND SAVE FOR WHERE TO LOOK NEXT
JRST CPOPJ1 ;AND SKIP
> ;END FTDAEM
IFE FTDAEM,<
ERRPT.==:CPOPJ##
>
IFN FTDAEM,< ;DAEMON FEATURE?
;SUBROUTINE TO CALL DAEMON FOR DEBUG OR JOB STOPCD
;DOES NOT TRY TO STOP ANY JOB
DAEEST::MOVEI T1,.ERMSE ;GET CODE FOR DAEMON
HRLI T1,.C0CAC## ;PUT INTERSTING ADDR IN T1 FOR DAEMON
AOS ESVIDX##
AOS T2,ESVIDX## ;GET INDEX FOR NEXT ERROR TO SAVE
CAIL T2,ERPTMX## ;HAVE WE EXCEEDED MAX
SETZB T2,ESVIDX## ;YES, JUST RESET ESVIDX
SKIPE ERPTBK##(T2) ;HAVE WE OVERLAPPED
JRST MNYERR ;YES, DAEMON ISN'T KEEPING UP, LOSE THIS ERROR
MOVEM T1,ERPTBK##(T2) ;SAVE T1 FOR ERRPT. UUO
MOVE T1,U
HRL T1,F
MOVEM T1,ERPTBK##+1(T2)
PUSHJ P,STDAEM ; SO DAEMON WILL KNOW AN ERROR HAPPENED
JFCL
POPJ P,
> ;END FTDAEM
REPEAT 0,<
;THIS SUBROUTINE USED ONLY IF PDP-6 DECTAPES
;ROUTINE TO GET DATA CONTROL AND ANOTHER SHARABLE DEVICE
;JOB NEVER GETS ONE DEVICE AND WAITS FOR SECOND, SINCE TYPING
;CONTROL C WOULD NEVER FINISH WITH FIRST DEVICE
;CALL PUSHJ P,GETDCXX
; AOSE XXREQ ;REQUEST COUNT FOR OTHER DEVICE
; RETURN WHEN BOTH AVAILABLE
INTERNAL GETDCDT,GETDCMT
EXTERNAL DCREQ,REQTAB,AVALTB,DCAVAL,CPOPJ1
GETDCDT:GETDCMT:
XCT @(P) ;INCREASE SHARABLE DEVICE REQ. COUNT
GETWT: PUSHJ P,DVWAT1 ;NOT AVAIL., GO WAIT FOR IT
AOSN DCREQ ;IS DATA CONTROL AVAILABLE?
JRST CPOPJ1 ;YES, RETURN BOTH AVAILABLE
MOVE P1,@(P) ;DATA CONTROL NOT AVAILABLE
SUBI P1,REQTAB
SOSL REQTAB(P1) ;REDUCE REQ. COUNT FOR OTHER
; SHARABLE DEVICE.
SETOM AVALTB(P1) ;SET AVAILABLE IF OTHER JOBS WAITING
JFCL DCREQ ;ARGUMENT FOR DCWAIT
PUSHJ P,DCWAIT ;WAIT FOR DATA CONTROL FREE
MOVE P1,@(P) ;INCREMENT REQ. COUNT
AOSN @P1 ;NOW IS SHARABLE DEVICE FREE?
JRST CPOPJ1 ;YES
SOSL DCREQ ;NO, REDUCE DATA CONTROL REQUEST
SETOM DCAVAL ;SET AVAIL., SOME OTHER JOB WAITING FOR IT
JRST GETWT ;TRY AGAIN
> ;END REPEAT 0
;ROUTINE TO WAIT FOR A SHARABLE RESOURCE
;CALLED AT UUO LEVEL ONLY
; PUSHJ P,XXWAIT
; RETURN WHEN RESOURCE AVAILABLE
;INITIALLY THE REQUEST COUNT IS -N, WHERE N IS THE
;NUMBER OF JOBS WHICH CAN USE THE SHARABLE RESOURCE AT THE SAME TIME
;A REQUEST COUNT OF 0 MEANS THE MAXIMUM NO. OF JOBS ARE
;USING THE RESOURCE, A POSITIVE NUMBER IS THE
;NUMBER OF JOBS WAITING IN THE SHARABLE RESOURCE WAIT QUEUE
;MUMERIC ACS 16 AND 17 ARE PRESERVED SINCE THE NEW AC CONVENTION DEPENDS
;ON THEM BEING SAVED. NUMERIC ACS ARE USED RATHER THAN SYMBOLIC SO THAT
;THE PROPER ACS WILL BE SAVED IN THE DUMP ACS EVEN IF THE SYMBOLIC AC
;VALUES ARE CHANGED
EXTERNAL JOBD16,JOBD17,REQTAB
DEFINE X(A,B,C)<
MQ==MQ+1>
MQ==0
QUEUES
DEFINE X(A,B,C)<
A'WAIT: PUSHJ P,SRWAIT
INTERNAL A'WAIT
>
DVWAIT: RWAITS
SRWAIT:
MOVEM 16,JOBD16(R) ;SAVE AC16 (SINCE IT IS A PRESERVED AC)
MOVEM 17,JOBD17(R) ;ALSO AC17
POP P,16 ;GET ENTRY ADDRESS
SUBI 16,DVWAIT-MQ+1 ;COMPUTE WAIT-STATE QUEUE CODE
MOVE 17,.C0JOB ;PICK UP JOB NUMBER
AOSG REQTAB-MQ(16) ;IS THE RESOURCE AVAILABLE?
JRST SRAVAL ;YES, GO USE IT
IFN FTMS,<
AOS RESOUR## ;NUMBER OF RESOURCES WAITERS
>
SETSTT: MOVE 17,.C0JOB ;JOB NUMBER OF RESOURCE REQUESTER
DPB 16,PJBS3 ;STORE QUEUE CODE IN JOB STATUS
MOVE 16,JOBD16(R) ;RESTORE AC16
PJRST RMEVM## ;REMEMBER EVM IF ANY AND
; RESCHEDULE AND RETURN TO CALLER
; WHEN SHARABLE DEVICE BECOMES AVAILABLE
; SEE CLOCK AND CLKCSS
;HERE WHEN THE REQUESTED SHARABLE RESOURCE WAS AVAILABLE
SRAVAL: MOVE 17,.C0JOB ;JOB NUMBER OF RESOURCE OWNER
IFN FTDISK,<
SKIPE DINITF ;DON'T CHECK JOB IN ONCE-ONLY
JRST SRAVL0 ;IF IN ONCE-ONLY
PUSH P,T3 ;SAVE T3
MOVE T3,JBTSTS##(17) ;GET JOB STATUS
TLNN T3,JXPN ;EXPANDING? (PROBABLY BY SOMEONE ELSE
;SHARING THE JOBS HIGHSEG)
CAMN 17,FORCEF## ;IS THIS JOB SELECTED TO BE SWAPPED?
JRST SRAVL2 ;YES. MUST CHECK FURTHER
SRAVL1: POP P,T3 ;RESTORE T3 AND GRANT RESOURCE
>
SRAVL0: MOVEM 17,USRTAB-MQ(16);REMEMBER WHO HAS RESOURCE SO IT CAN BE GIVEN
; UP IN THE EVENT OF A CATASTROPIC ERROR
MOVE 17,JOBD17(R) ;RESTORE AC17
MOVE 16,JOBD16(R) ;AND AC16
POPJ P, ;RETURN TO THE CALLER WITH THE
; REQUESTED RESOURCE
IFN FTDISK,<
SRAVL2: PUSH P,J ;SAVE J
MOVE J,17 ;GET JOB NUMBER
PUSHJ P,FLSDR## ;DOES JOB HAVE RESOURCE ALREADY?
JRST SRAVL3 ;NO. DON'T GRANT ONE (TRYING TO STOP JOB)
POP P,J ;RESTORE J AND GRANT ADDITIONAL RESOURCES
JRST SRAVL1 ;SO JOB CAN (EVENTUALLY) GIVE THEM UP
SRAVL3: POP P,J ;RESTORE J
POP P,T3 ;AND T3
SETOM AVALTB-MQ(16) ;SET AVAL BUT DON'T GIVE UP RESOURCE
JRST SETSTT ;AND MAKE HIM WAIT FOR SCHED.
>
PJBS1: POINT JWSIZ,JBTSTS(P3),JWPOS ;BYTE POINTER TO JOB STATUS
; WORD WAIT QUEUE CODE
PJBS3: POINT JWSIZ,JBTSTS(17),JWPOS
;SUBROUTINE TO RETURN A SHARABLE RESOURCE AND FLAG IT
; AS AVAILABLE IF ANY JOBS ARE WAITING FOR IT. IF
; JOBS ARE WAITING, THE SCHEDULAR WILL GIVE THE RESOURCE
; TO THE HIGHEST PRIORITY JOB.
;CALL: PUSHJ P,XXFREE
; RETURN HERE - ALL ACS PRESERVED
EXTERNAL REQTAB,AVALTB,USRTAB
INTERNAL DVFREE
DEFINE X(A,B,C)<
A'FREE: PUSHJ P,SRFREE
INTERNAL A'FREE
>
DVFREE: RWAITS
SRFREE: EXCH T1,(P) ;GET ENTRY ADDRESS AND SAVE T1
SUBI T1,DVFREE+1 ;CALCULATE WAIT STATE INDEX
HRRZS T1 ;CLEAR ANY PC BITS
SOSL REQTAB(T1) ;DECREMENT REQUEST COUNT. ANY JOBS WAITING?
SETOM AVALTB(T1) ;YES, FLAG IT AS AVAILABE SO THS SCHEDULAR WILL
; GIVE THE RESOURCE TO A WAITER
HRLZS USRTAB(T1) ;XWD LAST USER, 0 (NO CURRENT USER)
IFN FTDISK,<
SKIPE DINITF## ;NO UNWINDING DURING ONCE-ONLY
JRST TPOPJ##
>
PUSH P,J ;SAVE J
HLRZ J,USRTAB(T1) ;GET OWNER OF RESOURCE
IFN FTDISK,<
CAIN T1,MQWAIT-DVWAIT ;IF MQ RESOURCE
LDB J,PJOBN ; GET J FOR DDB (USRTAB ISN'T RIGHT)
>
MOVEI T1,JS.OOO ;WAS HE RUN OUT OF ORDER?
TDNN T1,JBTST2##(J) ;...
JRST SRFRE5 ;NO. DON'T FIDDLE
PUSH P,T3 ;SAVE T3
PUSH P,P1 ;AND P1
SETZB T1,P1 ;SET UP FOR NXTJBB, AND SCAN
SRFRE1: CAMN J,USRTAB(T1) ;DOES JOB OWN ANY OTHER RESOURCES?
JRST SRFRE4 ;YES
CAIGE T1,AVLNUM##
AOJA T1,SRFRE1
SRFRE2: PUSHJ P,NXTJBB## ;DOES IT OWN A MON-BUF?
JRST SRFRE3 ;NO
CAME T3,J
JRST SRFRE2
JRST SRFRE4 ;YES
;HERE IF JOB OWNS NO OTHER RESOURCES - FLAG FOR FORCED RESCHEDULE
SRFRE3: CONO PI,PI.OFF ;NO PI'S
SKIPN .C0RTF## ;FORCED RESCHEDULE IN PROGRESS?
SETOM .C0RTF ;NO PUT ONE IN
CONO PI,PI.ON ;ALLOW PI'S
MOVEI T1,JS.OOO ;CLEAR OUT OF ORDER BIT
ANDCAM T1,JBTST2##(J)
SRFRE4: POP P,P1 ;RESTORE ACS
POP P,T3
SRFRE5: MOVEI T1,JS.DEP!JDC ;JOB GAVE BACK RESOURCE
TDNE T1,JBTSTS##(J) ;WAS HE WAITING TO GO INTO DAEMON 0?
PUSHJ P,REQUE ;YES-SEE THAT HE GETS THERE NOW
; IF HE HAS MORE RESOURCES AT THE MOMENT,
; THE SCHEDULER WILL DEFER THE REQUEUE AGAIN AND EVENTUALLY
; GET BACK HERE.
POP P,J ;RESTORE J
IFN FTKA10,<
JRST TPOPJ ;RESTORE T1 AND RETURN
>
IFN FTKI10!FTKL10,<
POP P,T1 ;RESTORE T1
PJRST RTEVM## ;AND GIVE UP EVM IF ANY
>
;SUBROUTINE TO SET JLOG AND COUNT UP LOGNUM
;CALL WITH:
; MOVE J,JOB#
; PUSHJ P,SETLOG
;USES T1,T2
SETLOG::MOVSI T1,JLOG ;THE BIT OF INTEREST
TDNE T1,JBTSTS##(J) ;IS IT SET?
POPJ P, ;YES--ALL DONE
IORM T1,JBTSTS##(J) ;NO--SET IT
MOVEI T1,1 ;INDICATE SETTING
PJRST CLRLG1 ;FIX LOGNUM & BATNUM
;SUBROUTINE TO CLEAR JLOG AND DECREMENT LOGNUM
;CALL WITH:
; MOVE J,JOB#
; PUSHJ P,CLRLOG
;USES T1,T2
CLRLOG::MOVSI T1,JLOG ;THE BIT OF INTEREST
TDNN T1,JBTSTS##(J) ;IS IT SET?
POPJ P, ;NO--ALL DONE
ANDCAM T1,JBTSTS##(J) ;YES--CLEAR IT
SETOM T1
;HERE FROM SETLOG
CLRLG1: ADDM T1,LOGNUM## ;DECREMENT LOGNUM
IFN FTTLIM,<
MOVSI T2,(JB.LBT) ;IS THIS A BATCH JOB?
TDNE T2,JBTLIM##(J) ;--
ADDM T1,BATNUM## ;YES--ADJUST LOGNUM
>
POPJ P, ;RETURN
;ROUTINE TO SET JOB TO RUN AFTER IT HAS BEEN STOPPED
;BECAUSE IT HAD TO WAIT FOR IO TO COMPLETE FOR SOME DEVICE
;EACH SERVICE ROUTINE AT INTERRUPT LEVEL
;CHECK EACH TIME IT FINISHED A TASK(BUFFERFUL)
;TO SEE IF THE JOB USING THE DEVICE HAS
;PREVIOUSLY CAUGHT UP WITH DEVICE AND HAS BEEN STOPPED
;CALL: MOVE F,ADR. OF DEVICE DATA BLOCK
; MOVE S,DEVIOS(F) ;GET DEVICE IO STATUS WORD FROM DDB
; PUSHJ P,SETIOD ;YES, GO FLAG JOB TO START UP AGAIN
; RETURN
;SETS THE JOB QUEUE WAIT CODE TO WSQ IN JOB STATUS WORD.
;THE SCHEDULER THEN SEES THAT THIS JOB HAS ITS
;IO WAIT SATISFIED AND IS WAITING TO BE RUN AGAIN
INTERNAL SETIOD,STTIOD
EXTERNAL WSQ,TSQ,JOB,PJOBN
IFN FTDISK,<EXTERN DSQ
INTERN STDIOD>
PJBS2: POINT JWSIZ,JBTSTS(T1),JWPOS ;BYTE POINTER TO JOB STATUS
; WORD QUEUE CODE
IFN FTVM,<
STPIOD::MOVEI T2,PSQ## ;REQUE TO PAGING I/O WAIT SATISFIED
JRST SETID2
>
STTIOD:
IFN FTRSP!FTHPQ,<
LDB T1,PJOBN ;JOB NUMBER
>
IFN FTRSP,<
MOVE T2,.C0UPT ;TIME SYSTEM HAS BEEN UP IN JIFFIES
TLNN S,IO ;IS USER DOING INPUT?
MOVEM T2,JBTRSP##(T1) ;YES, STORE TIME USER BEGAN TO WAIT FOR RESPONSE
>
IFN FTHPQ,<
LDB T2,HPQPT1## ;GET HPQ NUMBER OF JOB IN T1
JUMPE T2,STTID2 ;IF ZERO, NOTHING TO WORRY ABOUT
PUSH P,T3 ;SAVE T3
MOVSI T3,SWP ;GET BIT TO TEST FOR
CONO PI,PIOFF## ;TURN OFF PI'S
TDNN T3,JBTSTS##(T1) ;HPQ JOB SWAPPED OUT, COMING OUT OF TI WAIT?
JRST STTID1 ;NOT SWAPPED OUT, TURN ON PIS AND CONTINUE
SKIPG T3,.C0RTF## ;ANY REALTIME RESCHEDULE BEING DONE?
JRST STTID0 ;NO, FLAG THAT THERES AN HPQ JOB ON DSK
LDB T3,HPQPN3## ;YES, GET OTHER JOB'S HPQ NUMBER
CAMG T2,T3 ;IS HE GREATER THAN OURS?
JRST STTID1 ;YES, DON'T DO ANYTHING.
STTID0: MOVEM T1,.C0RTF## ;YES, USE OUR JOB NUMBER
SETOM .C0CKF## ;FLAG THAT WE'RE DOING CH7 INTERRUPT
CONO PI,PICLK## ;CAUSE INTERRUPT TO HAPPEN
POP P,T3
JRST STTID2 ;CONTINUE
STTID1: CONO PI,PION## ;TURN PI'S BACK ON
POP P,T3 ;RESTORE T3
STTID2:>;END OF IFN FTHPQ
MOVEI T2,TSQ ;SET TTY IO WAIT SATISFIED QUEUE CODE
IFE FTSWAP,<
AOS TSAVAL##
>
JRST SETID1
SETIOD: MOVEI T2,WSQ ;REQUE TO WAIT SATISFIED Q
IFE FTSWAP,<
AOS WSAVAL## ;INCR. NO. OF JOBS WITH IO WAIT
; SATISFIED. NON-ZERO WSAVAL WILL
; CAUSE SCHED. TO SCAN FOR IO
; SATISFIED JOB.
>
IFN FTDISK,<
JRST SETID0
STDIOD: MOVEI T2,DSQ ;SET DISK IO WAIT STATISFIED QUEUE
IFE FTSWAP,<
AOS DSAVAL##
>
> ;END CONDITIONAL ON FTDISK
SETID0:
IFN FTHPQ,<
LDB T1,PJOBN## ;GET JOB NUMBER OF DDB IN F
LDB T1,HPQPT1## ;GET HIS HPQ NUMBER
JUMPE T1,SETID1 ;HE'S NOT IN AN HPQ
CONO PI,PIOFF## ;TURN OFF PI'S
SKIPN .C0RTF## ;ANY REAL TIME RESCHEDULE TO DO?
SETOM .C0RTF## ;NO, FLAG UUOCON AND SCHED1 THAT THERE IS
;AN HPQ JOB TO SCHEDULE
SETOM .C0CKF## ;DOING A CH7 INTERRUPT
CONO PI,PICLK##
>;END IFN FTHPQ
SETID1: LDB T1,PJOBN ;GET JOB NUMBER
IFN FTPI,<
TLNN S,IOSTBL ;IS OFF-LINE, CATCH IT AT UUO LEVEL
PUSHJ P,PSIIOD## ;CALL PSISER TO CHECK FOR TRAPS
>
IFE FTMSGSER,<
TLZN S,IOW ;IN I/O WAIT?
>
IFN FTMSGSER,<
TLZE S,IOW ;IN I/O WAIT?
JRST SETID2 ;YES
PUSHJ P,MPXIOD## ;MAYBE - ASK MSGSER
>
JRST SETID3 ;NO, SEE IF HIBERNATING ON I/O ACTIVITY
SETID2: CAIN T2,TSQ## ;GOING TO TTY SATISFIED?
JRST STID2B ;YES. MUST REQUEUE
IFN FTMS,<
IFN FTVM,<
CAIN T2,PSQ## ;GOING TO PAGING SATISFIED?
JRST STID2A ;NO. JUST CLEAR STATE CODE
>
PUSHJ P,MSIPUC## ;DS OR WS . MUST INCREMENT .C1PUC
>
STID2A: MOVEI T2,RNQ## ;SET STATE TO RNQ
DPB T2,PJBS2 ;SO JOB CAN RUN
JRST NJBTST ;AND SEE IF WE SHOULD FORCE RESCHED
STID2B: DPB T2,PJBS2 ;IN JOB STATUS WORD
INTERNAL FTSWAP
IFN FTSWAP,<
PUSH P,J ;SAVE J
MOVE J,T1 ;GET JOB NUMBER
PUSHJ P,REQUE ;REQUE THIS JOB
POP P,J ;RESTORE J
>
NJBTST::SKIPE .C0JOB ;IS NULL JOB RUNNING?
POPJ P, ;NO LET OTHER JOB RUN TILL SCHEDULER IS TRAPPPED TO
PJRST STOP2## ;YES, CAUSE RESCHEDULE
SETID3:
IFN FTHIBWAK,<
MOVSI T2,IOACE## ;JOB ENABLED FOR WAKEUP ON I/O ACTIVITY?
TDNN T2,JBTRTD##(T1)
POPJ P, ;NO, RETURN
TLNN S,IOSTBL ;IF OFFLINE, NO IO ACTIVITY OCCURS
PJRST WAKJOB## ;YES, WAKE THE JOB
>
POPJ P, ;NO, RETURN
;ROUTINE TO WAIT TILL DEVICE CATCHES UP WITH USER AND BECOMES INACTIVE
;CALLING SEQUENCE
; PUSHJ P, WAIT1
; EXIT ALWAYS RETURNS HERE
;IF THE DEVICE IS INACTIVE (IOACT=0), RETURNS TO EXIT. OTHERWISE, SETS
;IOW:=1 AND ENTERS WAIT UNLESS IOACT BECOMES ZERO BEFORE THE
;JUMP IS MADE, IN WHICH CASE IT SETS IOW:=0 AND RETURNS TO EXIT.
;ON LEAVING THE WAIT STATE, RETURNS TO EXIT.
;THIS ROUTINE PREVENTS THE STATE IOACT=0 AND IOW=1 FROM OCCURING
;CALLING SEQUENCE
; PUSHJ P, WSYNC
; EXIT ALWAYS RETURNS HERE
;SETS IOW:=1 AND ENTERS WAIT ROUTINE. RETURNS TO EXIT WHEN IOACT=0.
INTERNAL WAIT1
WAIT1: MOVE S,DEVIOS(F)
TRNN S, IOACT ;IS DEVICE ACTIVE? (IOACT=1?)
POPJ P, ;RETURN
PUSHJ P,WSYNC ;WAIT
JRST WAIT1
;WSYNC IS CALLED TO WAIT UNTIL SETIOD IS CALLED BY INTERRUPT SERVICE ROUTINE
;IE UNTIL CURRENT BUFFER ACTIVITY IS COMPLETED
;CALLED ONLY FROM UUO LEVEL
;CALL: MOVE F,ADR. OF DEVICE DATA BLOCK
; PUSHJ P,WSYNC
; RETURN IMMEDIATELY IF DEVICE IS INACTIVE
; RETURN WHEN DEVICE FINISHES NEXT BUFFER IF IT IS ACTIVE
INTERNAL WSYNC
EXTERNAL IOWQ,TIOWQ,PION,PIOFF
IFN FTDISK,<EXTERN DIOWQ>
WSYNC: PUSHJ P,SAVE3## ;SAVE P1-P3
IFN FTHALT,<
TRNN F,777700 ;IS RHDEVDAT LESS THAN 100?
STOPCD CPOPJ,DEBUG,NDP, ;++NOT DDB POINTER
>
MOVSI S,IOW ;SETUP DEVICE IO WAIT BIT
MOVEI P1,IOWQ ;IO WAIT STATE CODE
MOVE P3,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNE P3,DVTTY ;IS THIS DEVICE A TTY?
MOVEI P1,TIOWQ ;YES, SET TTY WAIT STATE CODE
IFN FTDISK,<
IFN FTSPL,<
SKIPL DEVSPL(F) ;ITS ALWAYS A DSK IF SPOOLED
>
TLNE P3,DVDSK ;IS THIS DEVICE A DISK?
MOVEI P1,DIOWQ ;YES, SET DISK WAIT STATE CODE
>
MOVE P3,.C0JOB ;CURRENT JOB NO.
MOVEI P2,IOACT ;DEVICE ACTIVE BIT
CONO PI, PIOFF ;TURN PI OFF
TDNN P2,DEVIOS(F) ;IS THE DEVICE ACTIVE?
JRST WSYNC1 ;NO
IORM S,DEVIOS(F) ;YES, SET DEVICE IO-WAIT BIT
; AND SETUP S FOR RETURN WHEN WAIT SATISFIED
DPB P1,PJBS1 ;SET JOB WAIT STATE CODE
; IN JOB STATUS WORD
CONO PI, PION ;TURN PI ON
IFN FTWATCH,<HRLM F,JBTPC##(P3)>
PUSHJ P,WSCHED ;CALL SCHEDULER TO FIND ANOTHER JOB TO RUN
; RETURN WHEN NEXT BUFFERFUL IS FINISHED
; WITH ACS 0-14 OCTAL RESTORED
; RETURN WHEN IO-WAIT FINISHED
IFN FTWATCH,<HRRZS JBTPC(P3)>
WSYNC1: CONO PI, PION
ANDCAB S, DEVIOS(F) ;CLEAR DEVICE IO-WAIT BIT
WSYNC2: POPJ P, ;HALT HERE IF F LESS THAN 100
$LIT
CLKEND: END