Trailing-Edge
-
PDP-10 Archives
-
BB-X140B-BB_1986
-
10,7/703mon/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 - V1417
SUBTTL APRINT TH/CHW/RCC/PFC/JE/DAL/EVS/JBS 21 JAN 86
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.
;
.CPYRT<1973,1986>
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
XP VCLOCK1,1417
; 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
$LOW
DAMESS::ASCIZ /-Jan-/
CLOCK:: POINT 36,CIPWTM##,35 ;BYTE POINTER TO CLOCK REQ QUEUE
$HIGH
;FORMAT OF THE CLOCK QUEUE IS
;WORD 0: ADDRESS TO DISPATCH TO WHEN COUNT GOES TO ZERO,,COUNT
;WORD 1: <CPU THAT CLOCK REQUEST SHOULD BE PROCESSED ON>B2,,DATA
; WHERE DATA IS A HALF WORD PRESENTED TO THE ROUTINE
; DISPATCHED TO WHEN COUNT GOES TO ZERO
;SUBROUTINE TO SERVICE COMMON APR INTERRUPTS (PARITY, NXM, AND CLOCK)
;CALL: PUSHJ P,APRSUB
; ALWAYS RETURN HERE
;
;FATAL AND CPU DEPENDENT ERRORS ARE FILTERED OUT BEFORE CALLING APRSUB
APRSUB::
IFN FTKL10,<
CONSO @.CPNXM## ;NON-EXISTENT MEMORY
CONSZ @.CPMPE## ; OR MEMORY PARITY ERROR?
JRST APRPAR ;YES--GO PROCESS IT
>
XCT .CPHCT## ;IS THIS AN APR CLOCK TICK?
JRST APRERR ;NO--GO CHECK OTHER APR CONDITIONS
SOS .CPHTM## ;YES--DECREMENT HNGTIM FOR THIS CPU
PUSH P,T1 ;SAVE AN AC
IFN FTMP,<
SKIPL INTDIE## ;ANY CPU PROCESSING A STOPCD?
PUSHJ P,CHKDIE## ;YES, WAIT FOR IT TO FINISH
SKIPE .CPNBI## ;ANYBODY BREAK MY INTERLOCKS?
STOPCD .,CPU,CIB, ;++CPU INTERLOCKS BROKEN
SKPCPU (0) ;IS THIS THE POLICY CPU? (CPU0)
JRST APRSU1 ;NO--DO NOT DO TIME ACCOUNTING FOR SYSTEM AS WHOLE
MOVE T1,NCPRUN## ;GET THE NUMBER OF RUNNING CPUS
MOVE T1,COKTAB##-1(T1) ; -(RUNNING CPUS-1)*JIFSEC GOES IN
MOVEM T1,.CPOK## ; THE POLICY CPU'S OK WORD
MOVEI T1,.C0CDB## ;FIRST CPU'S CDB
APRSU0: AOSN .CPOK##-.CPCDB##(T1) ;COUNT EVERYONE ELSE'S KEEP ALIVE
PUSHJ P,BRKLOK## ;CPU IS DOWN, BREAK ANY INTERLOCKS IT MAY OWN
HLRZ T1,.CPCDB##-.CPCDB##(T1) ;NEXT CDB
JUMPN T1,APRSU0 ;LOOP IF MORE
>
AOS TIME## ;INCREMENT TIME OF DAY FOR SYSTEM
AOS SYSUPT## ; AND SYSTEM UPTIME
JRST APRSU2
APRSU1: MOVN T1,TICSEC## ;-TICS/SECOND
MOVEM T1,.CPOK## ;NUMBER OF COUNTS UNTIL WE ARE DEAD
APRSU2: AOS .CPUPT## ;INCREMENT THIS CPU'S UPTIME
SETOM .CPTMF## ;SET FLAG THAT APR CLOCK HAS TICKED
SETOM .CPCKF## ;SET FLAG FOR CLK FORCED SCHEDULER INTERRUPT
CONO PI,XI.RQC## ;REQUEST INTERRUPT ON CLK (SCHEDULER) CHANNEL
IFN FTKL10&FTRSP,<
AOSN .CPBPF## ;WHEN BACKGROUND PERF ANAL COUNT HITS 0
PUSHJ P,BPAUPD## ;UPDATE PERFORMANCE ANALYSIS COUNTS
>
IFN FTMP,<
AOSN @.CPOK1## ;CHECK IF BOOT PROCESSOR IS ALIVE
PUSHJ P,BECOM0## ;BOOT CPU DIED, ASSUME ITS ROLE
>
XCT .CPCCF## ;CLEAR CLOCK FLAG
MOVEI T1,XP.CLK ;USER ENABLED FOR CLOCK INT BIT
TDNN T1,.CPCN1## ;IS HE ENABLED?
JRST TPOPJ## ;NO--DISMISS INTERRUPT
POP P,T1 ;RESTORE T1
PUSHJ P,SAVT## ;AND THEN SAVE ALL T REGS
PUSHJ P,APRPTS ;GET THE REAL PC
TLNN T1,(XC.USR) ;IS PC FROM USER MODE ?
POPJ P, ;NO--DISMISS INTERRUPT
MOVEM T3,.CPPIP## ;YES--SAVE POINTER TO INTERRUPT PC
MOVEI T4,XP.CLK ;CLOCK BIT
IORM T4,.JDAT+.JBCNI## ;STORE STATUS FOR USER
PUSHJ P,SAVJW## ;SAVE J (W COMES ALONG FOR THE RIDE)
MOVE J,.CPJOB## ;SET UP J WITH CURRENTLY RUNNING JOB
JRST APRUTP ;GO TRAP TO HIM
;HERE TO HANDLE MEMORY PARITY OR NXM INTERRUPT
APRPAR: PUSHJ P,SAVT## ;SAVE T REGS
PUSHJ P,SAVJW## ;SAVE J (W COMES ALONG FOR THE RIDE)
PUSHJ P,CPUSTS## ;READ CPU STATUS
PUSHJ P,DVCSTS## ;AND DEVICE STATUS
CONI APR,.CPPEF## ;SAVE THE APR STATUS
CONI PI,.CPPPI## ;SAVE THE PI STATE
IFN FTKL10,<
RDERA .CPAER## ;SAVE THE ERA ON KL10
PUSHJ P,REDSBC## ;READ AND CLEAR MEMORY CONTROLLERS
>
MOVEI T4,UE.PEF ;ASSUME PARITY ERROR
CONSZ @.CPNXM## ;IS THIS A NXM INTERRUPT?
MOVEI T4,UE.NXM ;YES--NXM (AND TAKES PRECEDENCE OVER PARITY)
CONO APR,@.CPIEF## ;NOW CLEAR THE APR
PUSHJ P,APRPTS ;GET REAL PC
DMOVEM T1,.CPAPC## ;SAVE IN CDB
DMOVEM T1,.CPMDP## ; AND HERE FOR ERROR REPORTING
IOR T1,T2 ;PHONEY IT UP FOR ERROR REPORTING
MOVEM T1,.CPMPP## ;FOR DAEMON
MOVEM T3,.CPPIP## ;SAVE POINTER TO INTERRUPT PC
TRNN T4,UE.PEF ;IS THIS A PARITY INTERRUPT?
JRST APRPA1 ;NO--JUST GO ON
SKIPE .CPCHE## ;CHANNEL ERROR REPORT IN PROGRESS?
POPJ P, ;YES--JUST IGNORE IT THEN, IT'S EXPECTED
APRPA1: SKIPE .CPPSP## ;IS A PI 7 MEMORY SCAN IN PROGRESS?
IFN FTKL10,<
POPJ P, ;YES--IGNORE THIS INTERRUPT, TRAP WILL HANDLE
MOVSI T1,(EA.CHN) ;NO--CHANNEL REFERENCE BIT IN ERA
TDNN T1,.CPAER## ;IS FAILURE FROM A CHANNEL DOING SOMETHING?
JRST APRPA2 ;NO--GO PRINT INTERRUPT MESSAGE
MOVE T1,.CPLCI## ;YES--GET TIME OF LAST CHANNEL INTERRUPT
ADDI T1,5*JIFSEC## ;ADD FIVE SECONDS
MOVE T2,TIME## ;GET JIFFY CLOCK
CAMLE T1,T2 ;HAS IT BEEN FIVE SECONDS SINCE LAST?
POPJ P, ;NO--DON'T FLOOD CTY ON RETRIES TO SAME PLACES
MOVEM T2,.CPLCI## ;YES--UPDATE "LAST" CHAN INT TIME
APRPA2: PUSHJ P,SVPPC## ;SWITCH TO SECONDARY PROTOCOL
MOVEI T1,.ERKLP ;GET CODE FOR DAEMON
>;END IFN FTKL10
HRL T1,.CPSLF## ;GET ADDRESS OF OUR CPU DATA BLOCK
PUSHJ P,DAEEIM ;POKE DAEMON TO LOG THIS
PUSHJ P,RCDSTD## ;ALSO LOG CPU AND DEVICE STATUS BLOCKS
MOVE J,.CPJOB## ;SET UP J WITH CURRENTLY RUNNING JOB
DIELOK ;GRAB THE DIE INTERLOCK
PUSH P,.CPTOA## ;SAVE TYPEOUT ROUTINE ADDRESS
MOVEI T3,CTYWAT## ;REPLACE WITH ONE THAT DOESN'T
MOVEM T3,.CPTOA## ; USE PI SYSTEM
MOVEI T1,SDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,CONMES## ;PRINT START DELIMITER
MOVE T2,.CPLOG## ;GET THIS CPU'S NAME
PUSHJ P,PRNAME## ;PRINT IT
TRNN T4,UE.NXM ;SELECT PROPER MESSAGE
SKIPA T1,[[ASCIZ / parity error interrupt/]]
MOVEI T1,[ASCIZ / non-existent memory interrupt/]
PUSHJ P,CONMES## ;PRINT IT
DMOVE T1,.CPAPC## ;GET THE INTERRUPT PC
PUSHJ P,DPCP## ;PRINT IT
MOVEI T1,[ASCIZ/ on /]
PUSHJ P,CONMES## ;PRINT "ON"
PUSHJ P,DAYTIM## ;FINISH LINE WITH DATE/TIME
MOVEI T1,[ASCIZ /CONI APR, = /]
PUSHJ P,CONMES## ;PRINT "CONI APR, ="
MOVE T1,.CPPEF## ;GET THE CONI APR DATA
PUSHJ P,HWDPNT## ; AND PRINT IT
PUSHJ P,CRLF## ;END WITH CRLF
MOVEI T1,[ASCIZ /CONI PI, = /]
PUSHJ P,CONMES## ;PRINT "CONI PI, ="
MOVE T1,.CPPPI## ;GET THE CONI PI DATA
PUSHJ P,HWDPNT## ; AND PRINT IT
PUSHJ P,CRLF## ;END WITH CRLF
IFN FTKL10,<
; JRST APPKLE ;GO EXAMINE THE ERA FOR FURTHER INFO
>
IFN FTKL10,<
;HERE TO EXAMINE THE ERA FOR FURTHER DECISIONS
APPKLE: MOVEI T1,[ASCIZ /ERA = /]
PUSHJ P,CONMES## ;PRINT "ERA ="
MOVE T1,.CPAER## ;GET THE ERA DATA
PUSHJ P,HWDPNT## ; AND PRINT IT
PUSHJ P,CRLF## ;END WITH CRLF
MOVEI T1,[ASCIZ /Error invoked by a /]
PUSHJ P,CONMES## ;PRINT DIAGNOSIS PREAMBLE
MOVE T3,.CPAER## ;GET THE ERA CONTENTS
TLNN T3,(EA.SWP) ;WAS A CACHE SWEEP THE CULPRIT?
JRST APPKL1 ;NO--PRESS ON
MOVEI T1,[ASCIZ /cache write-back forced by a sweep instruction.
/]
JRST APPKL3 ;YES--GO PRINT REASON AND DISMISS
APPKL1: TLNN T3,(EA.CHN) ;WAS A CHANNEL INVOLVED?
JRST APPKL4 ;NO--MUST BE CPU
TLNN T3,(EA.WRT) ;YES--IS IT A WRITE OPERATION?
JRST APPKL2 ;NO--CONTINUE
TLNN T3,(EA.SRC) ;YES--GET PROPER MESSAGE
SKIPA T1,[[ASCIZ /channel status word write.
/]]
MOVEI T1,[ASCIZ /channel data word write.
/]
JRST APPKL3 ;GO PRINT MESSAGE AND DISMISS
APPKL2: TLNN T3,(EA.SRC) ;GET PROPER MESSAGE
SKIPA T1,[[ASCIZ /channel read from memory.
/]]
MOVEI T1,[ASCIZ /channel read from cache.
/]
APPKL3: PUSHJ P,PRTSBD ;PRINT SBUS DIAG INFO AND END MESSAGE
POP P,.CPTOA## ;RESTORE TYPEOUT ADDRESS
DIENLK ;GIVE BACK THE DIE LOCK
POPJ P, ;NOW JUST DISMISS INTERRUPT
APPKL4: TLNN T3,(EA.WRT) ;IS IT A WRITE OF SOME SORT?
JRST APPKL6 ;NO--CONTINUE
TLNN T3,(EA.SRC) ;YES--GET PROPER MESSAGE
SKIPA T1,[[ASCIZ /CPU write to memory (not cache).
/]]
MOVEI T1,[ASCIZ /cache write-back forced by a CPU write.
/]
JRST APPKL7 ;GO PRINT MESSAGE
APPKL6: TLNN T3,(EA.SRC) ;GET PROPER MESSAGE
SKIPA T1,[[ASCIZ /CPU read or page refill from memory.
/]]
MOVEI T1,[ASCIZ /page refill from cache.
/]
APPKL7: TRNE T4,UE.NXM ;IS THIS A NXM?
JRST APPK10 ;YES--WANT TO CONTINUE AT INTERRUPT LEVEL
TLNE T3,(EA.DAT!EA.SRC!EA.WRT) ;NO--PARITY, IS THIS A READ FROM MEMORY?
JRST APPKL3 ;NO--THEN JUST PRINT MESSAGES AND DISMISS
HLLZ T2,.CPMPS## ;GET CPU REQUESTS SCAN BITS
TRO T2,(T4) ;SCAN FOR PARITY ERRORS
IORM T2,.CPAEF## ;SET BITS TO FORCE SCAN AT NEXT CLK RESCHEDULE
LDB T2,[POINT 5,.USPFW,5] ;PF CODE
CAIL T2,PF.ARP ;HAS A PF TRAP OCCURED?
JRST APPKL3 ;YES, LET TRAP ROUTINE HANDLE IT
MOVEI T2,JS.MPE ;STOP THE CURRENT JOB
IORM T2,JBTSTS##(J) ; TO PREVENT A POSSIBLE LOOP
PUSHJ P,PRTSBD ;FINISH MESSAGE AND PRINT SBUS DIAGS
POP P,.CPTOA## ;RESTORE TYPE OUT ADDRESS
JRST APRUTZ ;STOP USER AND SCAN
APPK10: PUSHJ P,PRTSBD ;PRINT SBUS DIAG INFO AND END MESSAGE
DMOVE T1,.CPAPC## ;GET INTERRUPT PC
TLNN T1,(XC.USR) ;PC IN USER MODE?
JRST APPMON ;NO--GO DO MONITOR CHECKS
POP P,.CPTOA## ;YES--RESTORE TYPEOUT ADDRESS
JRST APPUSR ;GO DO USER CHECKS
>;END IFN FTKL10
;HERE ON EXEC PARITY IN NO SPECIAL PLACE - CHECK FOR SAME AS LAST INTERRUPT
; ANNOUNCE OUR INTENTION TO SWEEP SINCE IT TAKES A LONG TIME SO THE OPR WON'T
; GET EXCITED
APPMON: PUSHJ P,APASWP ;ANNOUNCE INTENTION TO DO A SWEEP, DO IT
; AT INTERRUPT LEVEL SO IT WILL BE GUARANTEED
; TO COME OUT QUICKLY SO THE OPR DOESN'T GET EXCITED
MOVE T1,.CPAPC##+1 ;AND THE NXM PC
SKIPN .CPISF## ;IF IN THE SCHEDULER, OR
CAMN T1,.CPLPP## ; 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
CONSZ PI,@.CPNAP## ;ARE ANY PI'S (BELOW APR) IN PROGRESS?
JRST APPSWP ;YES--SWEEP AT APR PI LEVEL
POP P,.CPTOA## ;NO--RESTORE TYPEOUT ADDRESS
JRST APPUPE ;GO REQUEST PI 7 SWEEP OF CORE AND
; 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 OR NXM
APPSWP: MOVEI T1,.CPA00## ;FIRST ADR. OF PARITY SWEEP SAVE AC AREA
BLT T1,.CPA17## ;SAVE ALL ACS IN CDB BLOCK
HLLZ S,.CPMPS## ;REQUEST CPU SWEEP
TRO S,(T4) ;FLAG WHETHER NXM OR PARITY SWEEP
;GIVING UP THE LOCK RESULTS IN CIBS SO MUST CHECK IN TRAP ROUTINE
; DIENLK ;GIVE UP THE LOCK (TRAP ROUTINE GETS IT)
PUSHJ P,ANNSWP ;ANNOUNCE SWEEP
PUSHJ P,PARSWP## ;CALL MEMORY SCAN ROUTINE
TLZ S,(CP.PSX) ;CLEAR REQUEST TO SWEEP BIT
IORM S,.CPAEF## ;SET PRINT ONLY REQUEST
SKIPGE .CPMPC## ;ANY SERIOUS ERRORS?
PJRST PARHLT## ;YES--PRINT MESSAGE AND HALT CPU
MOVSI 17,.CPA00## ;RESTORE ALL ACS FROM CPU DATA BLOCK
BLT 17,16 ;...
MOVE 17,.CPA17## ;...
POP P,.CPTOA## ;RESTORE TYPEOUT ADDRESS
; TLZ T4,UE.NXM ;DON'T GIVE UP THE INTERLOCK AGAIN
JRST APRSTU ;GO RESCHEDULE
;HERE ON PARITY ERROR WHEN PC REALLY IN USER MODE - T1 HAS REAL PC
APPUSR: MOVE T3,.CPCN1## ;USER ENABLED APR AND PI TRAPS
TRNN T3,(T4) ;ENABLED FOR NXM OR PARITY ERROR?
JRST APPUPE ;NO--STOP JOB AND REQUEST MEMORY SCAN
MOVE T3,JBTSTS##(J) ;YES, JOB STATUS WORD
TLNE T3,JACCT ;IS JOB PRIVILEGED?
JRST APPPET ;YES, ALLOW PARITY ERROR TRAP
MOVE T3,JBTPPN##(J) ;JOB PROJECT-PROGRAMMER NO.
CAME T3,FFAPPN## ;IS IT THE OPERATOR PROJ-PROG
CAMN T3,UMDPPN## ; OR THE USER MODE DIAGNOSTIC PPN?
JRST APPPET ;YES--ALLOW THE TRAP
JRST APPUPE ;NO--STOP JOB AND REQUEST MEMORY SCAN
;HERE TO TRAP TO PRIVILEGED, ENABLED USER - (J SET TO JOB NO, T1 TO REAL PC)
APPPET: IORM T4,.JDAT+.JBCNI## ;STORE PARITY/NXM FLAG FOR USER
TRNN T4,UE.PEF ;A PARITY ERROR?
AOSA .CPUEN## ;NO, NXM BUMP COUNT OF USER ENABLED NXM'S
AOS .CPUEP## ;INCREMENT COUNT OF USER ENABLED PAR ERRORS
; ON THIS CPU
; TO LOOK AT IN HIS INTERRUPT ROUTINE
;JRST APRUTP ;HANDLE TRAPS TO USER
;HERE TO SET UP THE TRAP TO THE USER
;HERE WITH T1=ERROR PC, T4=APRENB BITS
APRUTP: HRR T1,T2 ;ADDRESS TO T1 (SINCE USER, MUST BE IN SECTION 0)
MOVEM T1,.JDAT+.JBTPC## ;STORE ERROR PC
HRRZ T3,.JDAT+.JBAPR## ;GET USER TRAP ADDRESS
CAIN T3,(T1) ;IS INT FROM 1ST INSTR. IN HIS TRAP CODE?
JRST APRUT2 ;YES, GO STOP USER IF SAME INT PC
; AS LAST, SET PC = 0 SO PI 7 CAN INT.
HRRI T3,1(T3) ;INCREMENT TRAP ADR BY 1
CAIE T3,(T1) ;SAME AS PC STORED BY INT?
JRST APRUT3 ;NO--GO TRAP TO USER
APRUT2: TRNE T4,UE.PEF!UE.NXM;IS THIS A NXM/PARITY ERROR?
JRST APPUPE ;YES, FLAG JOB AS SUCH
MOVEI T3,XP.LTH ;NO, SET STUCK IN LOOP BIT
IORM T3,.CPAEF##
DMOVE T3,@.CPPIP## ;FLAGS AND PC
DMOVEM T3,.CPAPC## ;AND SAVE FOR THE ERROR MESSAGE
JRST APRUTW ;STOP JOB
;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.)
APRUT3: HRR T1,.JDAT+JOBENB## ;GET SAVED SOFTWARE ENABLE FLAGS
TRNE T1,XP.DDU ;DOES USER WANT TRAPS DISABLED WHENEVER ONE OCCURS?
JRST APRUT4 ;NO, GO DISABLE CLOCK ONLY
;HERE TO DISABLE ALL USER ENABLED INTERRUPTS
HLLZS .JDAT+JOBENB## ;CLEAR SOFTWARE FLAGS SO THAT USER MUST DO
; ANOTHER APRENB UUO IN ORDER TO ENABLE TRAPS
SETZM .CPCN1## ;ALSO CLEAR IN CDB
HRRI T1,@.CPEEB## ;RESET APR CONSO MASK
HRRM T1,.CPCON## ; TO STANDARD SETTINGS
APRUT4: TRZN T1,XP.CCF ;ALWAYS DISABLE CLOCK INTERRUPT
JRST APRUT5 ;BECAUSE USER CANNOT CONTROL ITS
HRRM T1,.JDAT+JOBENB## ; COMING AND COULD INTERRUPT HIS OWN
ANDM T1,.CPCN1## ; INTERRUPT PROCESSOR WITHOUT MEANING TO.
APRUT5:
IFN FTKL10,<
TLO T1,(XC.PUB) ;FORCE HARDWARE TO TEST FOR PORTAL
>
HRR T1,.JDAT+.JBAPR## ;GET USER TRAP ADDRESS
PUSHJ P,APRUTS ;STORE PC TO DISMISS TO
IFN FTMP,<
TRNN T4,UE.PEF!UE.NXM ;IS THIS A PARITY/NXM ERROR?
JRST APRUT6 ;NO--PROCEED
DIENLK ;GIVE BACK THE DIE LOCK
APRUT6:>
POPJ P, ;DISMISS INTERRUPT
APRLOP: JRST APRLOP ;WAIT HERE FOR THE INTERRUPT
APRUTW: SKIPA T1,[IC.UOU+APRLOP];DON'T GO TO THE TRAP ROUTINE
APRUTZ: MOVSI T1,(XC.USR) ;DISMISS TO USER PC 0
PUSHJ P,APRUTS ;STORE PC TO DISMISS TO
JRST APRSTU ;GO STOP THE JOB
;HERE WITH T1=PC TO DISMISS TO
APRUTS: HRRZ T2,T1 ;SECTION 0
TRZ T1,-1 ;NO FLAGS
DMOVEM T1,@.CPPIP ;STORE IT
POPJ P,
;ANNOUNCE THAT A SWEEP HAS BEEN REQUESTED BY THIS CPU
APASWP: PUSH P,S ;PRCHCP WANTS S SETUP
HLLZ S,.CPMPS## ;CPU
TRO S,(T4) ;INDICATE NXM
PUSHJ P,ANNSWP ;OUTPUT THE MESSAGE
POP P,S ;RESTORE S
POPJ P, ;RETURN
;SUBROUTINE TO WARN THE OPR THAT A MEMORY SWEEP IS GOING TO HAPPEN
ANNSWP::MOVEI T1,SDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,CONMES## ;PRINT START DELIMITER
TRNE S,UE.PEF ;PARITY ERROR?
SKIPA T1,[[ASCIZ /Memory parity scan initiated by /]]
MOVEI T1,[ASCIZ /Non-existent memory scan initiated by /]
PUSHJ P,CONMES## ;ANNOUNCE SWEEP
PJRST PRCHCP## ;FINISH SWEEP MESSAGE
;SUBROUTINE TO TYPE SBUS DIAG INFO
IFN FTKL10,<
PRTSBD: PUSHJ P,CONMES## ;PRINT REASON MESSAGE
MOVEI T1,[ASCIZ /SBUS DIAGS:
CNTRLR FNC 0 FNC 1
/]
PUSHJ P,CONMES## ;PRINT SBDIAG HEADER
PUSHJ P,TYPSBD## ;PRINT THE SBDIAG INFO
MOVEI T1,EDELIM## ;GET ADDRESS OF TEXT
PJRST CONMES## ;PRINT END DELIMITER
>
;HERE ON USER PARITY/NXM ERROR
;FLAG CURRENT USER THIS CPU AS HAVING ERROR AND HAVE TO BE STOPPED
APPUPE: DMOVE T1,.CPAPC## ;GET THE INTERRUPT PC
CAMN T2,.CPLPP## ;IS IT THE SAME AS LAST PC?
JRST APRUTZ ;YES, CLEAR PC TO 0, SO CAN DISMISS TO PI7
; MUST BE MEM PAR/NXM ON INSTR. FETCH
;HERE TO REQUEST PI 7 MEMORY SCAN
HLLZ T3,.CPMPS## ;GET SWEEP REQUESTED BY CPU N (THIS CPU) BITS
TRO T3,(T4) ;SET PARITY OR NXM FLAG
IORM T3,.CPAEF## ;SET FLAG FOR PI 7 TO SWEEP MEMORY
DMOVE T1,.CPAPC## ;GET THE ERROR PC
MOVEM T2,.CPLPP## ;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)
;HERE TO STOP THE CURRENT JOB
APRSTU: SETOM .CPCKF## ;SET FLAG FOR SCHEDULER INTERRUPT (PI 7)
SETOM .CPSCF## ;FORCE RESCHEDULE EVEN IF ERROR IN MONITOR
IFN FTMP,<
TRNN T4,UE.PEF!UE.NXM ;IS THIS A PARITY/NXM ERROR?
JRST APRST1 ;NO--PROCEED
DIENLK ;YES, GIVE BACK THE DIE LOCK
APRST1:>
CONO PI,XI.RQC## ;REQUEST PI 7 INTERRUPT
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
; KL10 - NXM AND PARITY ERROR - REAL PC EXEC OR USER MODE
; CALLED ON EVERY MEMORY PARITY INTERRUPT
;CALL:
; PUSHJ P,APRPTS
; RETURN HERE, C(T1)=REAL ERROR FLAGS
; C(T2)=REAL ERROR PC
; C(T3)=POINTER TO LOCATION OF SAVED USER MODE PC
APRPTS: MOVE T1,@.CPCHL## ;GET INTERRUPT PC
TLNE T1,(XC.USR) ;INTERRUPT PC IN USER MODE?
JRST APRPT1 ;YES, EASY TO SET UP
IFN FTKL10,<
DMOVE T1,@.CPCHL## ;GET THE PC
CAIL T2,SEILM## ;IN TRAP ROUTINE?
CAILE T2,SEIL1## ; ...
JRST APRPT0 ;NO, LOOK ELSEWHERE
DMOVE T1,.USPFP ;YES, GET THE DOUBLE WORD PC
TDZ T1,[7777,,-1] ;FOR GETTAB
MOVE T3,.CPCHL## ;WHERE TO STORE THE PC IF NECESSARY
POPJ P,
APRPT0:>
CONI PI,T1 ;GET PI'S CURRENTLY IN PROGRESS
ANDI T1,@.CPNAP## ;EXCEPT APR CHANNEL
JFFO T1,.+2 ;DETERMINE CHANNEL NUMBER
JRST APRPT1 ;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,.CPEPT## ;0 OR 100 FOR TRAP OFF SET
HLRZ T1,(T2) ;GET INSTRUCTION FROM PI LOCATION
ANDI T1,777740 ;GET RID OF NOISE BITS
CAIE T1,(XPCW)
AOS T2 ;MUST BE BLKI(O), GO TO 41+2N
HRRZ T3,(T2) ;GET CH'N
DMOVE T1,@.CPCHL ;T2=STORED PC
MOVE T1,3(T3) ;PC TO XPCW TO
CAME T1,T2 ;IS STORED PC FIRST ONE IN ROUTINE?
APRPT1: MOVE T3,.CPCHL## ;NO, POINT TO SAVED APR INTERRUPT PC
DMOVE T1,(T3) ;RETURN PC
POPJ P,
;HERE ON APR INTERRUPTS OTHER THAN THE CLOCK
APRERR:
IFN FTKS10,<
CONSO APR,SP.FEI ;FRONT END?
JRST NOTFE ;NO, GO CHECK ERROR FLAGS
SETOM .CPFEF## ;YES, SET SOFTWARE FLAG FOR SCNSER
WRPI REQCTY## ;AND CAUSE AN INTERRUPT FOR CTY
WRAPR SP.CSF!SP.FEI ;CLEAR THE FRONT END FLAG
POPJ P, ;AND DISMISS SO "CTY" INTERRUPT WILL HAPPEN
NOTFE:>
EXCH T1,@.CPCHL## ;GET INTERRUPT PC
AOS .CPEDI## ;COUNT NO OF EXEC DON'T-CARE INTERRUPTS (AOV,FOV)
; HAPPENS ONLY IF USER IS ENABLED WHEN MONITOR
; CAUSES CONDITION
HRLM T1,.CPEDI## ;STORE OFFENDING PC SO WE CAN FIX CODE -
; SINCE THIS SLOWS DOWN SYSTEM
EXCH T1,@.CPCHL## ;RESTORE INTERRUPT PC
POPJ P, ;DISMISS INTERRUPT
;HERE ON CHANNEL 7 CLOCK INTERRUPT
CLKINT::CONO PI,II.CCI## ;CLEAR SOFTWARE REQUESTED INTERRUPT
DMOVEM 17,.CPS17##
DMOVE 17,@.CPCKL##
CAIE 0,EACAPC## ;DOING EFFECTIVE ADDRESS CALCULATION?
CAMN 0,[MCSEC1+EACAPC##] ;PERHAPS IN SECTION ONE?
JRST [MOVE 17,.CPJOB## ;GET CURRENT JOB ON THIS CPU
MOVE 17,JBTSTS##(17) ;AND THE ASSOCIATED JOB STATUS WORD
TLNE 17,CNTRLC ;WAS CONTROL-C TYPED?
HRRI 0,EACACC## ;YES--ALTER THE PC TO LET THE USER OUT
MOVE 17,@.CPCKL## ;GET PC FLAGS BACK
DMOVEM 17,@.CPCKL## ;UPDATE POSSIBLY CHANGED PC DOUBLE WORD
JRSTF @SAVPC] ;AND RESCHEDULE OUT OF EXEC MODE
TLNN 17,(XC.USR) ;PC IN USER MODE?
SKIPE .CPSCF## ;NO, IS THIS A FORCED RESCHEDULING INTERRUPT?
JRSTF @SAVPC ;YES--IT IS OK TO RESCHEDULE NOW
DMOVE 17,.CPS17##
XJEN @.CPCKL##
SAVPC: XWD XC.UOU##,.+1 ;JRSTF @ HERE TO RESCHEDULE
DMOVEM 17,.CPPC##
TLNE 17,(XC.USR) ;PC IN USER MODE?
JRST [DMOVE 17,.CPS17## ;RESTORE USER AC 17
EXECAC ;SWITCH TO EXEC AC BLOCK
JRST CLKSPD] ;CONTEXT SWITCH WILL SAVE USER ACS
DMOVE 17,.CPS17##
EXECAC ;EXEC MODE DOESN'T NECESSARILY MEAN EXEC AC'S
MOVEM 17,.CPS17## ;SAVE AC 17
SKIPN 17,.CPADR## ;CURRENT JOB DATA AREA, IS THERE ONE?
MOVE 17,.CPNJD## ;NO, MUST BE NULL JOB OR CORE 0
MOVEM 16,JOBD16##(17) ;SAVE AC 16 IN DUMP AC PART OF JOB DATA AREA
MOVEI 16,JOBDAC##(17) ;SOURCE=0,DESTINATION=DUMP AC 0
BLT 16,JOBD15##(17) ;SAVE ACS 0-15 JUST BELOW AC 16
MOVE T1,.CPS17## ;NOW SAVE 17 IN JOB DATA AREA
MOVEM T1,JOBD17##(17) ;ALONG WITH OTHER ACS
CLKSPD::
IFN FTXMON,<
JRST @[0,,.+1]
>
MOVE P,.CPNPD## ;SET UP PUSH DOWN LIST IN NULL JOB DATA
; AREA IN LOWER CORE
IFN FTMP,<
SKPCPU (1) ;CHECK FOR BOOT CPU
JRST SAVPC2 ;DON'T WANT EVERYBODY TO STICK THEIR HEADS IN THE SAND
SKIPE MOFLPG## ;IF SETTING MONITOR MEMORY OFF-LINE
JRST CP1MFL## ; FORCE ALL OTHER CPUS TO JUMP INTO THE ACS
>
SAVPC2::SETOM .CPISF## ;FLAG THAT WE'RE IN THE SCHEDULER
MOVE S,.CPAEF## ;COMMUNICATION FLAG BETWEEN HIGHER PI LEVELS AND CLK
JUMPE S,RSCHED ;ANY APR ERRORS? NO--RESCHEDULE
PUSHJ P,APRILM## ;YES--GO PROCESS IMMEDIATELY
JRST RSCHED ;NOW RESCHEDULE
;HERE AT UUO LEVEL WHEN CURRENT JOB RETURNS TO USER MODE FROM UUO 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
USCHD1::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
USCHED::XSFM .CPPC## ;FLAGS DON'T REALLY MATTER BUT EXEC MODE DOES
POP P,.CPPC##+1 ;SAVE PC IN PROTECTED PART OF SYSTEM DATA
MOVEM F,.JDAT+JOBDAC##+F ;SAVE F
; ; SINCE CAN START UP ON EITHER CPU
USCHE1::MOVEM J,.JDAT+JOBDAC##+J ;SAVE CURRENT JOB NUMBER
; NEEDED ON CALL FROM USER UUO EXIT
MOVEM P,.JDAT+JOBDPD## ;SAVE P
JRST WSCHD2 ;GO SETUP LONGER PDL AND RESCHEDULE
;ROUTINE TO ALLOW INTERRUPTION OF LONG UUO'S
SCDCHK::SKIPN SCDRTF## ;FORCED RESCHEDULE PENDING?
SKIPE .CPTMF## ;OR CLOCK TICKED?
PJRST WSCHED ;YES, PROCESS COMMNAND, SCAN JOBS
POPJ P, ;NO, CONTINUE THE UUO A WHILE
;HERE AT UUO LEVEL WHEN JOB GOES INTO IO WAIT OR SHARABLE DEVICE WAIT
;CALL: PUSHJ P,WSCHED
; RETURN HERE WHEN RUNABLE AGAIN
WSCHED::MOVEM 17,.JDAT+JOBD17## ;SAVE AC17 IN DUMP ACS (P4 IN NEW ACS)
WSCHD1::XSFM .CPPC## ;FLAGS DON'T REALLY MATTER BUT EXEC MODE DOES
POP P,.CPPC##+1 ;SAVE PC IN PROTECTED PART OF SYSTEM DATA
MOVEI 17,.JDAT+JOBDAC## ;SAVE ACS 0-16 IN DUMP ACS
BLT 17,.JDAT+JOBD16## ;IN CURRENT JOB DATA AREA
WSCHD2: HRRZS P ;RIGHT HALF FOR COMPARE
CAMGE P,SYSSIZ## ;UUO LEVEL PDL?
STOPCD .+1,JOB,WTP, ;++WRONG TYPE OF PDL
WSCHD3::MOVE P,.CPNPD## ;NULL JOB PD LIST (ELSE GET PDL OVF)
;USED TO CALL SCHEDULER AND COMMAND DECODER
;FALL INTO RSCHED AND RESCHEDULE
RSCHED::SETOM .CPISF## ;FLAG IN THE SCHEDULAR
MOVSI T1,777740 ;CLEAR FLAGS STORED BY PUSH/POP
ANDCAM T1,.CPPC##+1
IFN FTXMON,<
JRST @[0,,.+1] ;FOR THE TIME BEING, ALWAYS RUN THE SCHEDULER IN SECTION0
>
MOVE J,.CPJOB## ;GET CURRENT JOB #
IFN FTPI,<
SKIPN .CPTMF## ;DID CLOCK TICK?
JRST CPUTIM ;NOT APR CLOCK
SIGNAL C$APRC ;YES, SIGNAL APR CLOCK
JFCL ;NO TICK OR NOT ENABLED
>;END FTPI
;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.
CPUTIM: PUSHJ P,TIMEX ;GET TIME IN T1
IFE FTEMRT,<
SKIPN P1,T1 ;TEST FOR 0 (& SAVE TIME IN P1)
JRST CIP1
>;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 INCJOB ;YES, MUST INCREMENT USER TIME EVEN
; THOUGH REAL TIME WAS NOT A TICK
>;END IFN FTEMRT
;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: JUMPN J,INCTIM ;LAST JOB. WAS IT NULL JOB?
SKIPN .CPPLT## ; YES..WAS IT LOST TIME?
JRST INCNUL ; NOT LOST, JUST IDLE.
MOVE T1,P1 ; LOST, INCREMENT TOTAL
ADD T1,.CPLS2## ;ADD PREV EXCESS
IDIVI T1,RTUPS## ;CONVERT TO JIFFY + EXCESS
ADDM T1,.CPLST## ;INCREMENT JIFFY TOTAL
MOVEM T2,.CPLS2## ;REMEMBER EXCESS
SETZM .CPPLT## ;CLEAR LOST TIME FLAG
IFN FTKL10&FTMP,<
SKIPN .CPCLF## ;LOST TIME BECAUSE OF CACHE ON DUAL CPUS?
JRST INCNUL ;NO
MOVE T1,P1
ADD T1,.CPCL2## ;DO USUAL STUFF
IDIVI T1,RTUPS##
ADDM T1,.CPCLT## ;MORE LOST TIME
MOVEM T2,.CPCL2## ;SAVE REMAINDER
SETZM .CPCLF## ;CLEAR FLAG
>;END FTKL10&FTMP
INCNUL: MOVE T1,P1 ;INCREMENT IDLE TIME
ADD T1,.CPNL2## ;ADD PREV EXCESS
IDIVI T1,RTUPS## ;CONVERT TO JIFFY + EXCESS
ADDM T1,.CPNUL## ;INCREMENT JIFFY TOTAL
MOVEM T2,.CPNL2## ;REMEMBER EXCESS
INCJOB: JUMPN J,INCTIM ;DO ALL THE WORK IF A REAL USER
IFN FTEMRT,<
PUSHJ P,CHKPMJ## ;WORRY ABOUT PERF METER RUNNING
JRST CIP2 ;NO, GO SCHEDULE
PUSHJ P,GETMBT## ;GET MBOX COUNTERS
DADD T1,.CPMM0## ;GET NEW TOTAL
DMOVEM T1,.CPMM0## ;WISH WE HAD DADDM
PUSHJ P,CLREMB## ;RESET VALUES
>
JRST CIP2 ;NOW GO SCHEDULE
;INCREMENT JOB'S RUNTIME
INCTIM: SKIPN JBTADR##(J)
JRST CIP2
PUSHJ P,FNDPDB## ;GET ADDRESS OF PDB
JRST CIP0 ;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
.ADD T2,.PDEB2##(W) ;ADD IN EXCESS FROM LAST TIME
TLZE T2,(1B0) ;OVERFLOW?
AOS T1 ;YES
DIV T1,.CPEBJ## ;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## ;GET NEW TOTAL
DMOVEM T3,.CPMM0## ;STORE
INCTAA: PUSHJ P,CLREMB## ;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## ;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 ;YES, REPLACE HIGH PRECISION RUNTIME WITH EBOX/MBOX TIME
>;END IFN FTEMRT
SKIPN P2,P1 ;SINCE NOT USING EBOX/MBOX, SETUP P2 OLD STYLE
JRST CIP1 ;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
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
PUSHJ P,VMSIZE## ;JOB VIRTUAL SIZE
ADDI T2,(T1)
LSH T2,P2KLSH## ;CONVERT TO K
IMUL T2,P1 ;VIRTUAL KCS
ADDM T2,.PDVKC##(W) ;ACCUMULATE
IFN FTNSCHED,<
ADDM P1,RTCTOT## ;UPDATE TOTAL TIME GIVEN OUT SINCE WE SET
; CLASS QUOTAS
>;END IFN FTNSCHED
.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## ;EXIT IF THIS JOB NOT FROM SUBQUEUES
JRST CIP0 ;GIVE ACCOUNTING DONE RETURN
;HERE IF SCHEDULER IS TRYING TO SATISFY QUOTAS FOR ONE OR MORE CLASSES.
; INCREMENT TOTAL RUNTIME, AND PER CLASS RUNTIME.
; THIS JOB'S CLASS.
ADDM P1,TOTRTC## ;INCREMENT TOTAL RUNTIME FOR ALL CLASSES
;MINUS TIME THEY GOT WHEN ALL QUOTAS WERE
;EXHAUSTED (WHEN RRFLAG = 0)
LDB T2,JBYCLS## ;GET THIS JOB'S CLASS NUMBER
ADDM P1,CLSRTM##(T2) ;AND RUNTIME FOR THIS CLASS SINCE STARTUP
>;END IFN FTNSCHED
;HERE IF CURRENT JOB HAS NO PDB (KJOB UUO)
CIP0: JUMPE J,CIP2
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
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
SKIPA ;USER DOESN'T WANT TRAP
JRST INCT1A ;TRAP THE JOB
>
MOVEI T4,.ERTLX ;TIME LIMIT EXCEEDED ERROR
PUSHJ P,CHKINT## ;NO, HE WANT THIS INTERCEPT
JRST INCTM1 ;NO, GIVE ERROR MSG
GETPC T2,.CPPC## ;PC AT INTERRUPT
TLNE T2,(XC.USR) ;JOBPD1 IS OK IF DURING A UUO
PUTPC T2,.JDAT+JOBPD1## ;SAVE FOR DOINT
HLL T1,.CPPC## ;FLAGS AT INTERRUPT
TLNE T1,(XC.USR) ;USER MODE?
PUTPC T1,.CPPC## ;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,MTIMLM ;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: SKIPE JBTADR##(J) ;NOTHING TO DO IF NO CORE IN CORE
SKIPL T3,JBTSTS##(J) ;JOB RUNNABLE?
JRST INCTM6 ;NO, DON'T TEST
TLNN T3,NSHF!NSWP ;LOCKED?
PUSHJ P,FNDPDB## ;GET THE JOB'S PDB
JRST INCTM6 ;DON'T TEST IF NOT THERE
SKIPE .PDTMC##(W) ;COUNTER ZERO?
SOSLE .PDTMC##(W) ;NO, DECREMENT COUNTER
JRST INCTM6 ;NO COUNT SETUP OR COUNT HASN'T GONE TO ZERO
DMOVE T1,.CPPC## ;GET THE JOB'S PC
TLNN T1,(XC.USR) ;PC IN USER MODE?
JRST INCTM5 ;NO, TRY AGAIN IN A TIC
HRRZ T3,.JDAT+.JBPFH## ;START OF PFH
HLRZ T4,.JDAT+.JBPFH## ;END OF PFH
CAIG T3,(T2) ;PC IN PFH?
CAIGE T4,(T2) ; ..
SKIPA T3,[EXP IC.UOU+TIMFLT##] ;NO, PC TO CATCH TIME FAULT AT UUO EXIT
JRST INCTM5 ;YES, POSTPONE TIME FAULT ONE TICK
DMOVEM T1,.USPFP ;STORE OLD PC FOR TIMFLT
PUTPC T3,.CPPC## ;MAKE CONTEXT SWITCH GO TO TIMFLT
JRST INCTM6
INCTM5: MOVEI T1,1 ;WAIT ONE TICK FOR VIRTUAL TIME TRAP
MOVEM T1,.PDTMC##(W) ;STORE NEW VALUE IN COUNTER OR USER'S PC
INCTM6:
;HERE AFTER ALL TIME CHARGING TO CURRENT USER HAS BEEN DONE
CIP1: DMOVE T1,.CPPC##
MOVE J,.CPJOB## ;&JOB #
SKIPN JBTADR##(J) ;ADDRESS OF JOBDAT
JRST CIP2 ;NONE
DMOVEM T1,USRPC##
DMOVE T3,.JDAT+JOBPD1## ;ADDRESS OF UUO
SUBI T4,1
TLNE T3,(XC.USR) ;IN USER MODE?
MOVEM T4,JBTPC##(J) ;YES--STORE FOR CONTROL-T
TLNE T1,(XC.USR) ;ARE WE IN USER MODE?
MOVEM T2,JBTPC##(J) ;YES--STORE PC
CIP2:
IFN FTKL10&FTMP,<
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
SKIPN .CPTMF## ;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.
;DO SYSTEM TIME ACCOUNTING
SETOM .CPCHT## ;REMEMBER CLOCK TICKED
MOVE T1,TIME## ;REMEMBER THIS TIME FOR
EXCH T1,.CPTML## ; NEXT TIME & COMPUTE
SUB T1,.CPTML## ; DIFFERENCE (TIMINT)
MOVNS T1
SKIPGE T1 ;IN CASE WENT THRU MIDNIGHT
ADD T1,MIDNIT##
ADDM T1,.CPTNT##
IFN FTMP,<
SKPCPU (0) ;POLICY CPU?
JRST CIP3 ;NO, DON'T UPDATE TIME OR DO COMMANDS
>
;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##
MOVSI T1,(DF.RQC) ;DID SOME CPU REQUEST THAT WE
TDNE T1,DEBUGF## ; CALL CRSCPY ON THE NEXT TICK?
PUSHJ P,[ANDCAM T1,DEBUGF## ;IF SO, CLEAR THE REQUEST
JRST CRSCPY##] ;AND CAUSE CRASH COPY PROGRAM TO START
IFN FTKS10&FTNET,<
MOVSI T1,(DF.RQK) ;DID SOME ONE WANT KDPLDR TO RUN
TDNE T1,DEBUGF## ; ON THIS CLOCK TICK?
PUSHJ P,[ANDCAM T1,DEBUGF## ;IF SO, CLEAR THE REQUEST
JRST KDPLDR##] ;AND CALL KDPLDR
>
IFN FTKL10,<
MOVSI T1,(DF.RQN) ;DID SOME ONE WANT KNILDR TO RUN
TDNE T1,DEBUGF## ; ON THIS CLOCK TICK?
PUSHJ P,[ANDCAM T1,DEBUGF## ;IF SO, CLEAR THE REQUEST
JRST KNILDR##] ;AND CALL KNILDR
>
;PROCESS ANY COMMANDS TYPED
SKIPE .CPJOB## ;NULL JOB?
SKIPE .CPADR## ;NO, JOB HAVE CORE?
SKIPN COMCNT## ;YES, ANYTHING TYPED
JRST CIP3 ;NO, DON'T DO COMMAND PROCESSING
PUSHJ P,COMMAND## ;YES, GO PROCESS
;PROCESS TIMING REQUESTS STORED IN QUEUE
CIP3: MOVE T1,.CPCPN## ;OUR CPU NUMBER
SKIPGE T2,.CPTNT## ;TICKS GONE BY SINCE LAST TIME
SETZB T2,.CPTNT##
SETZ T3, ;FOR BOOT CPU CHECK
IFN FTMP,<SKPCPU (1)> ;DO WE MAINTAIN "SYSTEM" QUEUE AS WELL
EXCH T3,CLKNEW## ;YES, GET/CLEAR NEW REQUEST FLAG
CAMGE T2,CLKMIN##(T1) ;TIME TO PROCESS YET
JUMPE T3,CIP5 ;NO, DO ONCE A TICK STUFF UNLESS SOMETHING NEW
HLLOS CLKMIN##(T1) ;COMPUTE NEW MINIMUM TIME
CLKLOK ;KEEP OTHER CPU'S FROM PROCESSING THE QUEUE
SYSPIF ;AND NEW REQUESTS FROM COMMING IN
HRRZ U,CLOCK ;GET END OF LIST
SYSPIN ;OK TO PUT NOW, WE KNOW THE END OF THE LIST
CAIL U,CIPWTE## ;MAKE SURE IT DIDN'T GO OVER END
STOPCD .,STOP,CQO, ;CLOCK QUEUE OVERFLOWED AT SOME TIME.
CIP4: CAIN U,CIPWTM## ;END YET?
JRST CIP4C ;YES
IFN FTMP,<
SKIPL (U) ;CPU SPECIFIC REQUEST
SKIPA T1,BOOTCP## ;NO, ONLY BOOT CPU PROCESSES THE "SYSTEM" QUEUE
LDB T1,[POINT 3,(U),3] ;YES, GET CPU THAT IS TO DO THE WORK
CAME T1,.CPCPN## ;IS IT ME
SOJA U,CIP4B ;NO, LOOK AT NEXT ENTRY
>
IFE FTMP,<SETZ T1,> ;USE "CPU0" ON SINGLE SYSTEMS
MOVSI T3,(1B4) ;GET SCANNED REQUEST BIT
HRRZ T2,-1(U) ;DECREMENT TIME REQUEST
TDNN T3,(U) ;IS THIS A NEW REQUEST
SOSA T2 ;YES, DECREMENT BY ONLY ONE TICK
SUB T2,.CPTNT## ;SEEN BEFORE, REDUCE BY TIME GONE BY
JUMPLE T2,CIP4A ;REMOVE IF REQUEST HAS TIMED OUT
HRRM T2,-1(U) ;NOT EXPIRED, STORE NEW WAIT TIME
IORM T3,(U) ;AND MARK REQUEST AS SCANNED
CAMGE T2,CLKMIN##(T1) ;FIND NEW MINIMUM TIME
MOVEM T2,CLKMIN##(T1) ;THIS IS IT SO FAR
SOJA U,CIP4B ;CONTINUE SCAN
CIP4A: HRRZ T1,(U) ;GET DATA ITEM TO BE RETURNED
MOVS T2,-1(U) ;AND DISPATCH ADDRESS
SYSPIF ;MOVE LAST ITEM IN LIST TO THIS
MOVE T3,@CLOCK
SOS CLOCK
MOVEM T3,(U)
MOVE T3,@CLOCK
SOS CLOCK
MOVEM T3,-1(U)
SYSPIN ;DONE RE-ARRANGING THE QUEUE
PUSH P,U ;SAVE ONLY VALUABLE AC
PUSHJ P,(T2) ;AND DISPATCH TO TIMING REQUEST ROUTINE
POP P,U ;GET CURRENT ENTRY POINTER BACK
SUBI U,1 ;ADJUST POINTER
CIP4B: SOJA U,CIP4 ;GO BACK FOR MORE REQUESTS
CIP4C: CLKNLK ;OPEN THE FLOOD GATES
SETZM .CPTNT## ;START NEW TIMER
CIP5: SKIPG .CPHTM## ;SECOND COUNTER GONE TO ZERO (OR LESS)?
PUSHJ P,SECOND ;YES, GO DO ONCE-A-SECOND JOBS
CIP6: CPLOCK (SCD) ;LOCK SCHEDULER TO AVOID RACES
CIP601: PUSHJ P,NXTJOB## ;CALL SCHEDULER, SET J TO NEXT JOB # TO RUN
IFN FTMP,<
SKIPE .CPADR## ;WAS LAST JOB NULL JOB, OR
CAMN J,.CPJOB## ;IS THIS JOB SAME AS LAST JOB
CPUNLK (SCD) ;YES, CAN UNLOCK NOW
CIP60: SKPCPU (0) ;BOOT
JRST CIP6A ;NO, ONLY THE BOOT CPU DOES 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
; THEREFORE, IT IS A JFCL. IF IT IS DESIRED
; THE PATCH IS SIMPLE.
>;END REPEAT 0
CIP6A: CONO PI,PI.OFF
SETZM .CPCKF## ;CLEAR CLK INTERRUPT FLAG
; SET ON ALL FORCED CLK INTERRUPTS
CONO PI,PI.ON+II.CCI## ;ENABLE INTRPS, CLEAR SOFTWARE INTRP
SETOM .CPPTF## ;RESET PAGE TABLE PARITY COUNT
; DO IT HERE RATHER THAT APR LEVEL TO AVOID A LOOP
IFN FTHPQ!FTNSCHED,<
SKIPL T2,SCDRTF## ;NEED TO FORCE SCHEDULAR CYCLE?
JRST CIP70 ;NO
MOVNS T2 ;MAKE JOB NUMBER
TRNN T2,-1 ;JOB 0= ONLY IF IDLE
JRST [JUMPN J,CIP70 ;THIS IS A RARE CASE
IFN FTMP,<
SKIPN .CPADR## ;UNLOCK SCHEDULAR (SINCE J=0, WAS LAST JOB NUL OR DESTROYED?)
JRST CIP6 ;YES
>
JRST CIP601] ;NO, DON'T GET INTERLOCK AGAIN
> ;END FTHPQ!FTNSCHED
IFN FTHPQ,<
HLRZ T1,JBTRTD##(J) ;CURRENT JOB
HLRZ T2,JBTRTD##(T2) ;JOB IN SCDRTF
ANDI T1,HPUMSK## ;THIS SHOULD BE FASTER THAN LDB?
ANDI T2,HPUMSK##
CAMGE T1,T2 ;CURRENT JOB OR REQUESTED JOB HIGHER?
IFN FTMP,<
JRST [PUSHJ P,CLRSJ0## ;CLEAR CP.SJ0 ON JOB JUST SELECTED
SKIPE .CPADR ;IF LAST JOB NULL OR DESTROYED OR SAME,
CAMN J,.CPJOB ;UNLOCK SCHEDULAR ALREADY?
JRST CIP6 ;YES
JRST CIP601 ];
>
IFE FTMP,<
JRST CIP601
>
> ;END IFN FTHPQ
CIP70:
SETZM .CPTMF## ;CLEAR TIMED (1 JIFFY) INTERRUPT FLAG.
SETZM .CPSCF## ;CLEAR FORCED SCHEDULING FLAG
IFN FTHPQ!FTNSCHED,<
SETZM .CPHQU## ;CLEAR FLAG SAYING CURRENT JOB DID A HPQ UUO
>
MOVE U,.CPJOB## ;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)
TLNE T1,SEGMB ;WAS HIGH SEGMENT MOVED BY LOCK UUO?
PUSHJ P,SETRL1## ;AND MAKE PAGE MAP REFLECT THE MOVE.
JRST CIPXIT]
SKIPE U ;NO, SAVE PREVIOUS JOB NO. FOR PERFORMANCE
MOVEM U,.CPLJR## ;MONITORING WITH A DISPLAY
;DIFFERENT JOB, SAVE SOFTWARE STATE(HARDWARE ALREADY SAVED)
AOS .CPTJC## ;COUNT NO. OF CONTEXT SWITCHES TO DIFF. JOB
; (INCLUDE NULL JOB)
CAMN U,.USJOB ;DON'T SAVE IF NOT MAPPED TO RIGHT USER
;(SWITCHING AWAY FROM DESTROYED CONTEXT)
PUSHJ P,SAVUAC ;SAVE THE USER'S ACS (AC BLOCK 1) IN THE SHADOW AREA
MOVEM J,.CPJOB## ;STORE NEW CURRENT JOB NUMBER
PUSHJ P,CTXJCJ## ;GET JCH
MOVEI T1,0 ;CALL IT THE NULL JOB
MOVEM T1,.CPJCH## ;SAVE
IFN FTKL10&FTMP,<
SKIPE J ;NO I/O FROM NULL JOB
PUSHJ P,SETCSJ## ;SET FOR CURRENT JOB FOR I/O
>
SKIPN .CPADR## ;NULL JOB OR CORE 0 ON OLD JOB?
JRST CIP7 ;YES, DO NOT SAVE SOFTWARE STATE
DMOVE T1,.CPPC## ;GET PC
DMOVEM T1,USRPC## ;SAVE IT
MOVE T1,USRDDT## ;CONTEXT SWITCH JOBDDT SO THAT IT REMAINS
MOVEM T1,.JDAT+JOBDDT## ;PROTECTED BUT USER CAN LOOK AT IT
IFN FTKL10&FTMP,<
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
PUSHJ P,CTXSWP## ;NOW DO A SWEEP IF OLD JOB IS ON THE
; SLAVE NOW AND NEEDS A MASTER UUO
; DONE.
>;END IFN FTKL10&FTMP
CPUNLK (SCD) ;UNLOCK SCHEDULER AFTER SAVING JOB'S STATE
;RESTORE SOFTWARE STATE OF NEW JOB,THEN HARDWARE STATE
NULJOB:: ;TRANSFER HERE FROM SYSINI WITH J=0 AND .CPJOB=0
CIP7:
NULADR::PUSHJ P,SETRL1## ;GO SETUP HARDWARE AND SOFTWARE RELOCATION
; INFORMATION FOR NEW CURRENT USER
PUSHJ P,RESUAC ;RESTORE THE USER'S ACS (AC BLOCK 1)
; FROM THE SHADOW AREA
JUMPE J,CIPXIT ;IS NEW JOB THE NULL JOB?
SKIPN JBTADR##(J) ;DOES JOB HAVE CORE ASSIGNED?
STOPCD .,STOP,NCA, ;++NO CORE ASSIGNED
DMOVE T1,USRPC## ;NEW USER'S PC
DMOVEM T1,.CPPC## ;SAVE IT IN THE CDB
MOVE T1,.JDAT+JOBDDT## ;CONTEXT SWITCH JOBDDT SO THAT
MOVEM T1,USRDDT## ;IT REMAINS PROTECTED BUT USER CAN LOOK AT IT
IFN FTMP&FTPEEKSPY,<
MOVSI T1,(UP.CSP) ;SPY PAGES BIT
TDNE T1,.USBTS ;MIGHT THIS USER BE SPYING?
SKIPN .USCDB ;AND SPYING ON THE CDB?
JRST CIPXIT ;NO, DON'T UPDATE .USCDB
MOVE T1,[<PM.ICD>B2!PM.PUB!PM.SPY!<XWD <.CPCDB##/PAGSIZ##>,<SPTLOW##-SPTTAB##>>]
ADD T1,.CPCPN## ;BUILD INDIRECT POINTER TO .CPCDB
CAMN T1,.USCDB ;HAS IT CHANGED?
JRST CIPXIT ;NO, DON'T BOTHER ME
MOVE T2,T1 ;YES, COPY PAGE POINTER
ADD T2,[XWD 1,0] ;ACCOUNT FOR TWO-PAGE CDBS
DMOVEM T1,.USCDB ;STORE NEW MAPPING
PUSHJ P,STEUB## ;DO THE WRUBR AGAIN
;FALL THROUGH TO CIPXIT
> ;END OF IFN FTMP&FTPEEKSPY
;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: SKIPN .CPCHT## ;CLOCK TIC?
JRST CIPX0A ;NO
SETZM .CPCHT## ;CLEAR FLAG
PUSH P,U
MOVE U,.CPUPT## ;CURRENT UPTIME
STOPAT::TRNN U,M.STOF## ;CORRECT TIC TO START TERMINAL OUTPUT?
PUSHJ P,@.CPSTO## ;START OUTPUT FOR ANY LINES WAITING
IFN FTMP,<
PUSHJ P,DSKTIC## ;DO DISK-CPU QUEING
PUSHJ P,TAPTIC## ;SAME FOR TAPE
IFN FTKL10,<
PUSHJ P,KNITIC## ;SAME FOR KLNI
>; END IFN FTKL10
>; END IFN FTMP
IFN FTDECNET,<
IFN FTXMON,<
PUSHJ P,DCNJIF## ;CALL DECNET
>
IFE FTXMON,<
DNCALL DCNJIF##
>
>
IFN FTSCA,<
PUSHJ P,SC.TIC## ;DO SCS ONCE PER TICK PROCESSING
PUSHJ P,PPDTIC## ;DITTO FOR THE KLIPA
PUSHJ P,SCSCLK## ;DITTO FOR SCS. UUO
>; END IFN FTSCA
SKPCPU (0) ;ON THE BOOT CPU?
JRST CIPXT1 ;NO
SKIPE CLPTOP## ;NEED TO ALLOCATE PAGES AT CLOCK LEVEL?
PUSHJ P,CRECLP## ;YES, GO WORK ON IT
CIPXT1: POP P,U ;RESTORE LAST JOB RUN
MOVE J,.CPJOB## ;AND CURRENT JOB
CIPX0A: 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## ;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## ; & CDB NULL TIME
MOVE T1,T3
CIPXI1: ADD T1,.CPOH2## ;CONVERT TO JIFFYS
IDIVI T1,RTUPS##
ADDM T1,.CPOHT## ;ADD INTEGRAL JIFFYS
MOVEM T2,.CPOH2##
JUMPE J,CIPXI2 ;NULL JOB?
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## ;SKIP IF JOB IS IN USER MODE
JRST CIPPSI ;DO NOT TRAP IF EXEC MODE
XCT PINOJN## ;SKIP IF CANNOT GRANT PSI INTERRUPTS
PUSHJ P,PSIGEN## ;CAN, SEE IF THERE ARE ANY PENDING
CIPPSI::>
MOVEI T1,UTRP ;TRAP PENDING BIT
MOVSI T2,USRMOD ;USER MODE
TDNE T2,.CPPC## ;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,.JDAT+JOBFDV## ;GET OLD (IRP) PC
MOVE M,.JDAT+JOBINT## ;SETUP M FOR PUTWRD
JUMPE M,CIPXI4 ;UTRP MAY GET SET BY PSISER. IGNORE (.JBINT)=0
MOVEI M,2(M) ; TO STORE PC IN THIRD WORD OF INT BLOCK
PUSHJ P,PUTWRD## ;STORE THE INTERRUPT PC
JFCL ;IGNORE ERROR
CIPXI4: SETZM .CPISF## ;FLAG NO LONGER IN SCHEDULAR
CIP8A: MOVE T1,.CPPC## ;GET THE PC FOR THE CURRENT JOB
TLNN T1,(XC.USR) ;IS IT IN USER MODE
JRST [MOVSI 17,.JDAT+JOBDAC## ;NO, RESTORE EXEC MODE ACS
BLT 17,17 ;FROM THE DUMP AREA
XJEN .CPPC##] ;RETURN TO INTERRUPTED EXEC
IFN FTKL10,<MOVSI T1,(LG.LUB)>
IFN FTKS10,<MOVSI T1,(SG.LUB)>
ANDCAM T1,.USUPF ;DON'T CAUSE REFILLS
IFN FTKL10,<MOVSI T1,(LG.LAB+LG.LPC+1B8+1B11)>
IFN FTKS10,<MOVSI T1,(SG.LAB+1B8+1B11)>
IORM T1,.USUPF ;USERACS + LOAD PCS
DATAO PAG,.USUPF ;RESET USER AC BLOCK #'S
XJEN .CPPC## ;RETURN TO THE USER PROGRAM
;HERE WHEN ABOUT TO RUN THE NULL JOB
CIPXI2: SETZM .CPISF## ;FLAG NO LONGER IN SCHEDULAR
MOVE T1,.CPRUN## ;RUNNABILITY BITS
TLNN T1,(CR.SPD) ;SUSPEND THIS CPU?
JRST CIPXI3 ;NO
IFN FTNET,<
PUSHJ P,FEKCPS## ;TELL FRONT ENDS WE ARE GOING AWAY
>
TLNN T1,(CR.TSS) ;SHOULD THIS CPU SNAP SHOT THE SYSTEM?
JRST CIPXI3 ;NO, JUST SUPPEND
PUSHJ P,CSDMP## ;MAKE SURE EVERYTHING IS IN CORE BEFORE DUMPING
CONO PI,PI.OFF ;MONBTS WANTS THE PI SYSTEM OFF
PUSHJ P,[IFN FTKL10,<PUSHJ P,SVPPC##> ;SAVE PROTOCAL
IFN FTKS10, <PUSHJ P,DISKAL##> ;DISABLE KEEP ALIVE
PUSHJ P,SLPDMP## ;TAKE A SYSTEM SNAP SHOT
CAIA
JRST [MOVEI T1,[ASCIZ /[SYSTEM suspended]
/]
PUSHJ P,CTYTYP##
PJRST RMVCPU##] ;SUCCEEDED, STICK OUR HEAD IN THE SAND
IFN FTKS10, <PUSHJ P,ENAKAL##> ;ENABLE KEEP ALIVE
CONO PI,PI.ON ;FAILED
MOVSI T1,(CR.SPD)
ANDCAB T1,.CPRUN## ;GIVE USER THE ERROR RETURN
POPJ P,]
CIPXI3: TLNE T1,(CR.RMV!CR.SPD) ;REMOVED OR SUSPENDED CPU?
PUSHJ P,RMVCPU## ;YES, DO IT NOW THAT ONLY NULL JOB LEFT
JUMPN U,NULJB ;NULL JOB--WAS PREVIOUS JOB NULL?
;NO--GO SET IT UP
SKIPN .CPNJE## ;HAS AN ERROR OCCURRED WHILE NULL JOB
; WAS RUNNING? IF YES, RESTORE ACS
; ILL UUO LOSED ACS
JRST CIP8A ;GO RESUME THE NULL JOB
; 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
NULJB: SETZM .CPNJE##
; 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
EXCTXU <BLT T1,6> ;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## ;IS TRPSET ENABLED
EXCTXU <MOVEM T1,3> ;YES DO NOT LOOK AT MEMORY
>
MOVE T1,.CPDBM##
EXCTXU <MOVEM T1,7> ;SETUP USER AC TO POINT TO PROPER CDB
USERAC
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
TDNE 7,DOORBL## ;AC3 - CHECK IF DOORBELL WAS RUNG
WAKINS::WAKE ;AC4 - WAKE UP MONITOR
AOJINS: AOJA 1 ;AC5 - COUNT UP LOC 0
0 ;CLEAR AC6
;ROUTINE TO SAVE THE USER'S ACS IN AC BLOCK 1 IN THE SHADOW AC
; AREA IN THE JOB DATA AREA ON A CONTEXT SWITCH
;CALLING SEQUENCE:
; SETUP THE USER BASE REGISTER TO POINT TO THE CURRENT JOB'S UPMP
; PUSHJ P,SAVUAC
; ALWAYS RETURN HERE
SAVUAC: PUSH P,J ;SAVE CURRENT JOB NUMBER
MOVE J,U ;J 2 JOB NUMBER OF THE LAST JOB RUN
PUSHJ P,SETUPR ;SETUP T2 TO POINT TO SHADOW AREA
JRST JPOPJ## ;NO CORE IN CORE
MOVEI T1,(T2) ;SOURCE = USER AC 0,
; DESTINATION = AC 0 IN SHADOW AREA
EXCTUX <BLT T1,17(T2)>
;SAVE USER ACS 0-17
JRST JPOPJ## ;RETURN
;ROUTINE TO RESTORE THE USER'S ACS TO AC BLOCK 1 FROM THE SHADOW AC
; AREA IN THE JOB DATA AREA ON A CONTEXT SWITCH
;CALLING SEQUENCE:
; SETUP THE USER BASE REGISTER TO POINT TO CURRENT JOB'S UPMP
; PUSHJ P,RESUAC
; ALWAYS RETURN HERE
RESUAC: PUSHJ P,SETUPR ;SETUP T2 TO POINT TO SHADOW AREA
POPJ P, ;NO CORE IN CORE
MOVSI T1,(T2) ;SOURCE = AC 0 IN THE SHADOW AREA,
; DESTINATION = USER AC 0
EXCTXU <BLT T1,17> ;RESTORE USER ACS 0-17
POPJ P, ;RETURN
;SUBROUTINE TO SETUP T2 TO POINT TO SHADOW AC AREA FOR THE CURRENT JOB
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER OF CURRENT JOB
; PUSHJ P,SETUPR
; RETURN HERE IF NOT THE NULL JOB BUT HAS NO CORE (CORE 0,KJOB)
; RETURN HERE - T2 POINTS TO THE CURRENT JOBS SHADOW ACS
SETUPR: MOVEI T1,JS.ASA ;DON'T SAVE ACS IF THE SHADOW AREA ISN'T FREE
TDNE T1,JBTSTS##(J) ;IS IT?
POPJ P, ;NO
SKIPN T2,JBTADR##(J) ;SETUP T2 - DOES THE JOB HAVE CORE IN CORE?
JUMPN J,CPOPJ## ;NO, IF J IS NON-ZERO (I.E., NOT THE NULL
; JOB) GIVE NON-SKIP RETURN (JOB HAS NO ACS)
JUMPN T2,CPOPJ1## ;IS IT THE NULL JOB?
MOVE T2,.CPNJD## ;YES, RETURN ADDRESS OF NULL JOBS SHADOW AREA
ADDI T2,JOBDAC## ; ..
JRST CPOPJ1## ;GIVE SKIP (THERE IS A PLACE TO STORE ACS) RETURN
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
MOVEI P1,1 ;FIRST ENTRY IN JBTADR
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## ;SWAP WITH LAST VALUE
SUB T1,.CPXTM## ; 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
SECOND: PUSHJ P,DTASEC##
MOVE T1,TICSEC## ;RESTORE THE SECOND-COUNTER
ADDM T1,.CPHTM## ;TO FULL SECOND
;COUNT GOES TO -1 SO SCHED1 CAN TELL WHEN
;EXACTLY ONE MINUTE HAS GONE BY
IFN FTMP,<
SKPCPU (0) ;ON CPU0?
JRST SECON1 ;NO
>
AOSGE COMCNT## ;BUMP FOR SAFETY
SETZM COMCNT## ;DON'T LET COMCNT GO NEGATIVE
AOS T1,LOCSEC## ;BUMP SECOND
CAIL T1,^D60 ;NEW MINUTE?
PUSHJ P,MINUTE ;YES
PUSHJ P,XTCSEC## ;CHECK XTCDDB'S
MOVEI T1,FRCQUE## ;FORCE COMMAND LDB/TTY OUTPUT HEADER
PUSHJ P,TOTAKE## ;ANY OUTPUT THERE
JRST SECON1 ;NO, PRESS ON
SE1XCT <SKIPGE LDBDCH##(U)> ;IS THE LINE IDLE
SECON0: PUSHJ P,XMTCHR## ;YES, GET SOME OUTPUT
JRST SECON1 ;ALL DONE
MOVSI T1,(DF.WFL) ;"WATCH FRCLIN"
TDNN T1,DEBUGF## ;WANT TO SEE WHATS GOING ON
JRST SECON0 ;NO,THROW IT ON THE FLOOR
PUSH P,U ;SAVE THE LDB ADDRESS
HRRZ U,BOOTCT## ;CTY LINE NUMBER
MOVE U,LINTAB##(U) ;CTY LDB
PUSHJ P,CCTYO## ;OUTPUT IT
POP P,U ;RESTORE FRCLIN
JRST SECON0 ;AND GET SOME MORE
;MOVE THIS LABEL UP AS MORE ONCE A SECOND CODE CAN BE
; EXECUTED ON ALL CPUS
SECON1: SOSG .CPSEC## ;TIME TO DO ONE-A-MINUTE STUFF ON THIS CPU?
PUSHJ P,CPUMIN ;YES
MOVE T1,.CPUPT##
CAMGE T1,.CPIUT##
POPJ P,
ADD T1,TICSEC##
MOVEM T1,.CPIUT##
IFN FTNET!FTDN60,<
PUSHJ P,DLXSEC## ;CHECK DL-10, DTE-20 OR KMC/DUP
>
IFN FTKL10,<
PUSHJ P,DTESEC## ;CALL 1/SECOND 10/11 PROTOCOL ROUTINE
>;END IFN FTKL10
IFN FTKS10,<
PUSHJ P,KSSEC## ;DO ONCE/SECOND FOR KS10
>;IFN FTKS10
IFN FTSCA,<
PUSHJ P,SC.SEC## ;CALL ONCE/SECOND SCA PROTOCOL ROUTINE
PUSHJ P,PPDSEC## ;CALL ONCE/SECOND CI PORT DRIVER ROUTINE
>; END IFN FTSCA
PUSHJ P,SCNSEC## ;AND HANDLE TELETYPE PROBLEMS
IFE FTXMON,<
PUSHJ P,DNMAP##
>
IFN FTENET,<
PUSHJ P,ETHSEC## ;CALL ONCE/SECOND ETHERNET SERVICE
IFN FTKL10,<
PUSHJ P,KNISEC## ;CALL ONCE/SECOND KLNI DEVICE SERVICE
>; END IFN FTKL10
>; END IFN FTENET
IFN FTDECNET&FTXMON,<
PUSHJ P,DCNSEC## ;CALL DECNET
>
IFE FTXMON,<
IFN FTDECNET,<
PUSHJ P,DCNSEC##
>
PUSHJ P,RGMAP##
>
PUSHJ P,TAPSEC## ;CALL TAPSER
IFN FTDAS78,<
PUSHJ P,D78SEC## ;CHECK DAS78'S
>;END OF IFN FTDAS78
PUSHJ P,DSKSEC## ;CHECK FOR HUNG DISK DDBS
IFN FTDAS78!FTDN60!FTNET,<
MOVEI J,FEKFST## ;GET ADDRESS OF FIRST FEK (0 IF NONE)
CAIA ;SKIP INTO THE SCAN LOOP
SECND1: HRRZ J,FEKBLK(J) ;STEP TO THE NEXT FEK
JUMPE J,SECND2 ;EXIT LOOP IF WE'VE DONE ALL THE FEKS.
IFN FTMP,< ;FOR SMP, SEE IF OWNING CPU DIED.
MOVSI T1,FK.CPD ;FLAG SET AT APR-CLOCK LEVEL WHEN CPU DIES.
TDNE T1,FEKBLK(J) ;SEE IF THIS FEK'S CPU DIED ON HIM.
PUSHJ P,[MOVEI T1,FI.DWN ;IF CPU DOWN, GET "FEK DOWN" CODE,
PJRST FEKINT##] ; AND TELL NETSER THE FEK HAS GONE
HLRE T1,FEKUNI(J) ;GET NUMBER OF CPU THAT THIS FEK IS ON.
SKIPGE T1 ; A CPU NUMBER OF "-1" MEANS
MOVE T1,BOOTCP## ; "THE POLICY CPU"
CAME T1,.CPCPN## ;IF WE AREN'T ON THE RIGHT CPU FOR THIS FEK
JRST SECND1 ; GO DO THE NEXT FEK. HIS CPU WILL CALL HIM.
>
MOVEI T1,FF.SEC ;GET THE "ONCE/SEC" FUNCTION CODE.
XCT FEKDSP(J) ;CALL THE FEK
JRST SECND1 ;GO DO THE REST OF THE FEKS
SECND2: PUSHJ P,NETSEC## ;POKE NETSER
> ;END OF IFN FTDAS78!FTDN60!FTNET
IFN FTKS10,<
PUSHJ P,KDPSEC## ;GO CHECK THE KMC-11
PUSHJ P,DMRSEC## ;GO WORRY ABOUT DMR11s
>
PJRST DEVCHK## ;GO CHECK FOR HUNG DEVICES
;SUBROUTINE CALLED ONCE A MINUTE ON ALL CPU'S.
CPUMIN: MOVEI T1,^D60 ;REFRESH ONCE-A-MINUTE
MOVEM T1,.CPSEC## ; COUNTER FOR THIS CPU
PUSHJ P,TAPMIN## ;PRINT TAPE CONTROLLER MESSAGES
REPEAT 0,< ;CAN'T REALLY RETURN CHUNKS OUT FROM UNDER DAEMON
;SINCE WE MADE AN ENTRY IN THE QUEUE
IFN FTKL10,<
SOSN .CPETM## ;TIME TO GIVE UP KL ERROR CHUNKS YET?
PUSHJ P,KLEREL## ;YES, GIVE THEM BACK
>
>;END OF REPEAT 0
IFN FTMOS,<
PUSHJ P,MOSMIN## ;CLEAR MOS ERROR TIMER
>
IFN FTKL10,<
SOSLE .CPDTT## ;TIME TO UPDATE -20F'S IDEA OF DATE/TIME?
POPJ P, ;NOT YET
MOVEI T1,^D15 ;DO IT AGAIN IN 15 MINUTES
MOVEM T1,.CPDTT## ;JUST TO KEEP TOO MUCH SKEW FROM DEVELOPING
MOVSI T1,F20SDT## ;BIT TO REQUEST DTESER (UMM, TTDINT) TO
IORM T1,.CP20F## ;SEND THE DATE/TIME ABOUT NOW
>;FTKL10
POPJ P, ;RETURN
;SUBROUTINE CALLED AT CLOCK LEVEL ONCE A MINUTE
MINUTE: PUSHJ P,SAVE2## ;SAVE P1,P2 FOR AVG JOB SIZE, # DAEMON
;HUNG JOBS, MCU CALCULATION
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
IFN FTDAS78,<
PUSHJ P,D78MIN## ;CHECK DAS78'S
>;END OF IFN FTDAS78
IFN FTENET,<
IFN FTKL10,<
PUSHJ P,LLMMIN## ;CHECK LLMOP
> ;END IFN FTKL10
> ;END IFN FTENET
SOSLE OMSMIN## ;NEED TO PRINT OPR MESSAGE YET?
JRST MINUT0 ;NO
MOVE T1,OMSINI## ;RESET COUNTER TO
MOVEM T1,OMSMIN## ;INITIAL VALUE
MOVE U,OPRLDB## ;GET LDB ADDRESS OF OPR
PUSHJ P,BIGBEN## ;PRINT CURRENT DATE/TIME
MOVE U,BOOTCT## ;GET LINE NUMBER OF THE CTY
MOVE U,LINTAB##(U) ;GET LDB ADDRESS
CAME U,OPRLDB## ;SAME AS OPR?
PUSHJ P,BIGBEN## ;NO, PRINT THERE ALSO
MINUT0: PUSHJ P,D76MIN## ;PRINT OUT PDP-11 MESSAGES
SKIPLE J,HIGHJB## ;CHECK ALL JOBS
PUSHJ P,DECHJB ;MAKE SURE HIGHJB IS HONEST
PUSHJ P,FJCONT ;FORCE A JCONT ON ALL WAITING JOBS
PUSHJ P,ENQMIN## ;LOOK FOR STALE LOCK BLOCKS
MINUT1:
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
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
SKIPE P1 ;HOW MANY JOBS WAITING FOR DAEMON?
PUSHJ P,DPMOPR## ;ONE OR MORE, TELL OPR JOB #S.
IFN FTMP,<
PUSHJ P,CP1CHK## ;CHECK IF DUAL PROCESSOR IS STILL RUNNING
>
PUSHJ P,CHKUNI## ;CHECK ALL DISK UNITS
SKIPN T1,SYSKTM## ;IS A SHUTDOWN PENDING
JRST NOKSYS ;NO SHUTDOWN PENDING
SOSE T1,SYSKTM## ;YES. COUNT DOWN TO ZERO
SKIPA T1,SYSKTM## ;NOT FIRST KSYS TIME
SETOM SYSKTM## ;FLAG FOR PRIVILEDEGED CUSP
IFN FTPI,<
JUMPL T1,NOKSYS ;JUMP IF NO KSYS PENDING
PUSHJ P,PSIKSY## ;TELL EVERYONE
> ;END FTPI
NOKSYS: AOS ARFLAG## ;COUNT UP AUTO RELOAD COUNTER
POPJ P,0 ;RETURN
;ROUTINE TO FORCE A JCONT COMMAND ON ALL THE JOBS THAT ARE WAITING
FJCONT::PUSHJ P,SAVJW## ;SAVE J, W COMES ALONG FOR A RIDE
PUSH P,F ;SAVE F
MOVE J,HIGHJB## ;HIGHEST JOB
FJCNT1: MOVE T1,JBTSTS##(J) ;STATUS
TLNN T1,JERR ;IF JOB CAN CONTINUE,
TRNN T1,JDCON ;AND IS WAITING FOR A DEVICE,
JRST FJCNT2
PUSHJ P,DETJCK## ;DETACHED JOB?
JRST FJCNT8 ;YES
MOVE T1,J ;PUT JOB NUMBER IN T1
PUSHJ P,FCONRQ## ;AND TRY FORCED CONTINUE
JFCL
JRST FJCNT2 ;LOOK ON
FJCNT8: MOVEI T1,JDCON ;YES, CAN'T FORCE A COMMAND
ANDCAM T1,JBTSTS##(J) ;CLEAR OW BIT
PUSHJ P,SETRUN ;TRY TO CONTINUE THE JOB
FJCNT2: SOJG J,FJCNT1 ;TEST ALL JOBS
PJRST FPOPJ##
;SUBROUTINE CALLED ONCE AN HOUR
HOUR: SETZM LOCMIN## ;SET MINUTE TO 0
AOS LOCHOR## ;BUMP HOUR
CHKMNT::MOVE T1,LOCHOR## ;MIDNIGHT?
CAIGE T1,^D24
POPJ P, ;NO, ALL DONE
SUBI T1,^D24 ;YES, BACK UP A DAY
MOVEM T1,LOCHOR##
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
PUSHJ P,THSDA ;RECOMPUTE THSDAT
PUSHJ P,SUDATE ;RECOMPUTE 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
JRST CHKMNT ;AGAIN
;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
SKIPL LOCSEC## ;IF TIME INVALID DON'T DECREMENT DATE
ADD T3,T1 ;ADD DATE AND TIME
SUB T3,GMTDIF## ;CONVERT TO GMT
MOVEM T3,DATE##
SETZM DATREM## ;CLEAR LEFT OVER REMAINDER
POPJ P,
;SUBROUTINE TO RECOMPUTE NUMBER OF MINUTES TO NEXT OPR
; MESSAGE
OMSTIM::MOVE T1,LOCMIN## ;GET CURRENT MINUTE
IDIV T1,OMSINI## ;DIVIDE BY PERIOD, T3=# MINUTES
MOVE T1,OMSINI## ;IN CURRENT PERIOD
SUBI T1,(T2) ;COMPUTE TIME TO END OF PERIOD
MOVEM T1,OMSMIN## ;STORE
POPJ P, ;RETURN
;CLKCHG IS A ROUTINE TO SEARCH THE CLOCK QUEUE FOR AN ENTRY FOR A
;PARTICULAR JOB AND TO CHANGE THE REMAINING CLOCK REQUEST TIME.
; MOVE T1,JOBNUM ;T1 = JOB TO SEARCH FOR
; MOVE T2,[POST ADDR,,NEW INTERVAL] ;T2 = WHERE TO GO WHEN EXPIRES,,TIME IN JIFFIES
; PUSHJ P,CLKCHG ;CHANGE CLOCK REQUEST TIME
; RETURN HERE IF AN ENTRY WAS NOT FOUND (T1=NEW SLEEP TIME)
; RETURNS HERE, CLOCK REQUEST TIME UPDATED.
;CLKCHG USES T2, T3 WITHOUT RESTORING THEM
CLKCHG::CLKLOK ;INTERLOCK QUEUE
PUSH P,T2 ;SAVE NEW SLEEP TIME FOR LATER
HLRZ T4,T2 ;COPY POST ROUTINE ADDRESS
IFN FTMP,<
SYSPIF ;SINCE TWO WORDS/ENTRY IN QUEUE
>
HRRZ T2,CLOCK ;GET RH OF CLOCK QUEUE POINTER
IFN FTMP,<
SYSPIN
>
CLKCH1: CAIG T2,CIPWTM## ;AT TOP OF QUEUE?
JRST [CLKNLK
JRST TPOPJ##];YES, JOB NOT IN QUEUE
HLRZ T3,-1(T2) ;GET TIME-OUT ADDRESS
CAIE T3,(T4) ;POST ADDRESS THE SAME AS NEW ENTRY
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) ; ..
MOVSI T3,(1B4) ; ..
ANDCAM T3,(T2) ; ..
SETOM CLKNEW## ; ..
CLKNLK
CAIE T4,WAKEJ ;IS THIS A SLEEP/HIBER REQUEST
JRST CPOPJ1## ;NO, DONT DIDDLE IN-CORE PROTECT TIMES
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
;HERE ON CLOCK REQUEST TO ALLOW MORE INITIA'S TO RUN
CLKCMD::MOVEI T2,20 ;ALLOW MORE INITIA'S TO RUN
ADDM T2,COMCNT## ;BUMP COUNT OF COMMANDS
SUBI T1,20 ;DECREMENT ORIGINAL (SYSINI) COUNT
JUMPLE T1,CPOPJ## ;DONE IF EXHAUSTED
MOVE T2,[CLKCMD,,JIFSEC##] ;COME BACK IN A SECOND
SYSPIF
IDPB T2,CLOCK
IDPB T1,CLOCK
SETOM CLKNEW## ;NEW ENTRY IN QUEUE
PJRST ONPOPJ## ;RESTORE PI AND RETURN
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
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
>
SETZM JBTRCT##(J) ;CLEAR NO. OF DISK BLOCKS READ BY JOB
SETZM JBTWCT##(J) ;CLEAR NO. OF DISK BLOCKS WRITTEN BY JOB
IFN FTSPL,< SETZM JBTSPL##(J) ;CLEAR SPOOLING BITS
>
MOVSI T1,JXPN
TDNN T1,JBTSTS##(J)
JRST CLRJBL
LDB T1,IMGOUT##
SKIPN T1
DPB T1,IMGIN##
CLRJBL:
PUSHJ P,FIXXPN## ;IF JOB WAS EXPANDING, DEC. XJOB
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) ;IS HE IN PQ2?
TLO T2,(JS.PQ2) ;YES, SET THE BIT
MOVEM T2,JBTSCD##(J) ;SAVE INITIAL VALUE
>
IFN FTKL10&FTMP,<
PUSHJ P,CLCSN## ;CLEAR OUT JBTST3 ENTRY, IF IT EXISTS
>;END IFN FTKL10&FTMP
IFN FTHPQ!FTRTTRP,< XCT CLRRTD## ;CLEAR HPQ POSITION
>
SETZM JBTPPN##(J) ;CLEAR PROJECT-PROGRAMMER NUMBER
SETZM JBTJLT##(J) ;CLEAR JOB'S LOGIN TIME
SETZM JBTCLM##(J) ;CLEAR OUT CORE LIMIT
SETZM JBTLIM##(J) ;AND TIME LIMIT
SETZM JBTPRV##(J) ;CLEAR PRIVILEGES
IFN FTRSP,< SETZM JBTRSP##(J) ;CLEAR RESPONSE TIME MEASURE
SETZM JBTRQT##(J) ;CLEAR RUN-QUEUES TIME
>
IFN FTMP,< PUSHJ P,SETJSP## ;SET UP JBTSPS WORD WITH INITIAL CAN RUN BITS
>
POPJ P,
;SUBROUTINE TO STOP CURRENT JOB, NOT SET ERROR BIT
; PUT TTY IN COMMAND MODE, START TTY0, CALL SCHEDULER
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
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 <CRLF><PERIOD>
;CALL: MOVEI T1,ADR. OF MESSAGE
; PUSHJ P,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>
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,CHKPOP ;WANT TO AUTO-POP?
JRST HOLD2 ;NO, WE'RE REALLY GOING TO STOP THE JOB
SKIPN JBTADR##(J) ;IF NO JOB DATA AREA,
JRST HOLD2 ;GIVE UP
PUSHJ P,SVEUB## ;MAKE SURE IT'S ADDRESSABLE
PUSHJ P,CRLF## ;PRINT A CRLF
PUSHJ P,TTYSTR## ;START TTY IN USER MODE
PJRST STOP1C ;STOP JOB
HOLD2: PUSHJ P,PRRSP1## ;NO, 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
ESTOP:: JUMPE J,CPOPJ## ;IS THIS ERROR IN JOB 0?
ESTOP1::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
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,FFAPPN##
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,.CPJOB## ;DAEMON NOW RUNNING?
POPJ P, ;NO (CHAN 7). AVOID DISASTER
PJRST QKUSXT## ;GO DO QUICKY USER EXIT
ESTOP2:
MOVE T1,[JACCT,,JS.RUU+JS.ASA] ;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.)
MOVSI T1,(JS.IGS) ;CLEAR "IN GETSEG" BIT
ANDCAM T1,JBTST2##(J)
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
CONSZ PI,PI.IPA ;NOT LOGGED IN - KILL JOB IF NOT ON CHAN 7
JRST STOP1C ;AT CHANNEL 7
SETZM .CPISF## ;NO LONGER IN SCHEDULAR
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)
STOP1::
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
MOVE U,DDBLDB##(T1) ;ADDRESS OF LDB
JUMPE U,STOP1J ;DETACHED (AND TYPED CTRL/C?)
SE1XCT <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
SKIPN T1,TTYTAB##(J) ;GET TTY DDB
JRST STOP1H ;NO DDB?
SKIPL T2,DEVIOS(T1) ;GET I/O STATUS
TLNN T2,IOW ;IN INPUT WAIT?
STOP1H: TDZA T2,T2 ;NO, ZERO STATUS
GETPCS T1,.JDAT+JOBPD1## ;YES, GET UUO PC
GETPCS T1,USRPC## ;NO, GET CURRENT
MOVSI T2,(1B0) ;YES, SET STATUS BIT
PUSH P,T1 ;SAVE PC ACROSS SIGNAL
SIGNAL C$CTLC ;SIGNAL CONTROL-C INTERRUPT
JRST STOP1F ;USER DOESN'T WANT THE INTERRUPT
POP P,T1 ;GET NEW PC
PUSHJ P,SETPIT ;GET JOB STARTED
JFCL ;IGNORE NOT ENABLED RETURN
JRST STOP1D ;GO FINISH UP
STOP1F: POP P,T1 ;CLEAN STACK
> ;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
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 FTMP,<
PUSHJ P,CLRCCB## ;CLEAR SECONDARY PROCESSOR ^C-BIT
>
POPJ P, ;AND RETURN
;HERE TO UNCONDITIONALLY STOP THE JOB
STOP1C::SKIPE T2,JBTPPN##(J) ;IF PPN IS ZERO OR
CAMN T2,HLPPPN## ; [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
SYSPIF ;DONE AT INTERUPT LEVEL HIGHER THAN DT LEVEL
TDNN T1,JBTSTS##(J) ;NO, IS RUN BIT OFF IN JOB STATUS WORD
JRST [SYSPIN ;YES
JRST STOP1A]
TLO T1,CNTRLC ;TURN OFF. "USER TYPED ^C WHILE STILL IN EXEC MODE"
ANDCAM T1,JBTSTS##(J)
SYSPIN
MOVSI T1,(UP.DST) ;DON'T SEARCH TO TERMINAL?(HNGSTP)
SKIPE JBTADR##(J) ;NO UPBTS IF NO CORE
TDNN T1,.USBTS ;IF ON, LEAVE TERMINAL AT USER LEVEL
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
PUSHJ P,FNDPDB## ;FIND PDB
JRST STOP1E ;NO PDB
SKIPN .PDPGM##(W) ;GET CUSP TO RUN
JRST STOP1E ;NONE
MOVEI T1,TTFCXI## ;FORCE AN .R INITIA 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
CAIE T1,DAQ## ;IS IT DA?
JRST STP1E1 ;NO
HLRZ T1,JBTDAU##(J) ;YES. GET WHICH ONE
JUMPE T1,STOP1A ;STRANGE
UUOLOK ;
HLRZ T2,UNIAJB##(T1) ;GET WAIT COUNT
SOSL T2 ;DECREMENT IT
HRLM T2,UNIAJB##(T1) ;STORE IT BACK
UUONLK ;UNLOCK IT
JRST STOP1A ;AND PROCEED
STP1E1: CAIE T1,AUQ## ;IS IT AUQ?
JRST STP1E2 ;NO. NORMAL
HRRZ T1,JBTDAU##(J) ;YES. WHICH ONE
JUMPE T1,STOP1A ;STRANGE
UUOLOK ;LOCK IT
SOSGE UFBWAT##(T1) ;DECREMENT WAITERS
SETZM UFBWAT##(T1) ;PRECAUTION?
UUONLK ;UNLOCK IT
JRST STOP1A ;PROCEED
STP1E2: 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:
PUSHJ P,DIACLR## ;CRANK UP DSK IO IF STOPPED WITH DIAG.
PUSHJ P,TPFREE## ;CHECK FOR MTA'S
IFN FTMP,<
PUSHJ P,CLRCCB## ;CLEAR CONTROL C BIT
>
IFN FTRSP,<
SETZM JBTRSP##(J) ;CLEAR TIME USER STARTED TO WAIT FOR RESPONSE
; SO COUNT NEW RESPONSE
>
MOVSI T1,(UP.GET+UP.MPF+UP.IYB+UP.DST) ;CLEAR GET IN PROGRESS FLAG
SKIPE JBTADR##(J) ;DON'T DO ANDCAM IF NO MAP
ANDCAM T1,.USBTS
STOP1B: PUSHJ P,CHKPOP ;WANT TO AUTO-POP?
JRST STOP1K ;NO, DON'T DO IT
ANDCAM T1,JBTST2##(J) ;YES, CLEAR BIT FOR NEXT TIME
PUSHJ P,FNDPDS## ;FIND THE PDB
PUSHJ P,INTLVL## ;AT INTERRUPT LEVEL?
JRST STOP1I ;NO
JSP T2,MONJOB ;RUN AT UUO LEVEL
MOVEI T2,ESTOP ;PUT ESTOP ON THE STACK
JSP T1,MONSTR ;SET UP ACS
STOP1I: PUSHJ P,CTXPOP## ;DO AUTO-RESTORE
STOP1K: CAME J,.CPJOB## ;NO, IS THIS JOB CURRENT USER
JRST REQUE ;NO, SET REQUE JOB FLAG
SKIPN JBTADR##(J) ;JOB HAVE CORE?
JRST STOP1L ;NO, CAN HAPPEN IF CURRENT CONTEXT HAS BEEN DESTROYED
SKIPL T1,JBTSTS##(J) ;RUN FLAG OFF?
TLNN T1,JERR ;YES, IF JOB ERROR FLAG ON
JRST STOP2 ;NO, (IRP LEVEL ONLY) DON'T SET .CPSCF 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
STOP1L: SETOM .CPSCF## ;YES, FORCE RESCHEDULING EVEN IF JOB IN EXEC MODE
; JRST STOP2 ;CAUSE CLK INTERRUPT
;ROUTINE TO CAUSE CLK ROUTINE TO RESCHEDULE
;CALLED AT ANY LEVEL
;CALL: PUSHJ P,STOP2
; RETURN IMMEDIATELY EXCEPT IF AT UUO LEVEL
; IF AT UUO LEVEL, RETURN WHEN JOB IS RUNABLE AGAIN
STOP2:: CONO PI,PI.OFF ;PREVENT CLOCK INTERRUPT DURING STOP2 CODE
SETOM .CPCKF## ;SET FLAG TO INDICATE CLK INTERRUPT
; EVEN THOUGH CLK INTERRUPT IS NOT A TIME INTERRUPT
CONO PI,PI.ON+PI.IIO+CLKBIT## ;TURN PI BACK ON AND REQUEST INTERRUPT TO
; CLK PI CHANNEL(LOWEST PRIORITY CHANNEL)
CONSZ PI,II.IPA ;AT INTERRUPT LEVEL?
POPJ P, ;YES, RETURN IMMEDIATELY
PUSH P,T1 ;NO, AT UUO LEVEL
STOP3: CONI PI,T1 ; MAKE SURE CLOCK LEVEL PROCESSING
TLNE T1,CLKBIT## ; HAPPENS BEFORE DOING ANYTHING ELSE
JRST STOP3 ; SINCE MAY NOT HAVE ANY CORE
JRST TPOPJ## ;RETURN
;HERE TO CHECK WHETHER JOB SHOULD DO AN AUTO-POP RATHER THAN EXIT
;
;CALL: J/ JOB TO CHECK
;
;RETURN 1: NO, DO THE EXIT
;RETURN 2: YES, AUTO-POP
; T1/ JS.SAC
CHKPOP: MOVEI T1,JDCON ;OW STATE BIT
TDNE T1,JBTSTS##(J) ;TEST FOR HNGSTP
POPJ P, ;YES, ALLOW THE CONTEXT TO RECOVER
MOVSI T1,(JS.SAC) ;NO, GET AUTO-POP BIT
TDNE T1,JBTST2##(J) ;IF LIT,
AOS (P) ;FLAG FOR SELF-DESTRUCTION
POPJ P, ;RETURN STATUS TO CALLER
;HERE (FROM COMCON) TO PREFORM THE ACTUAL ^D BREAKPOINT TRAP.
;
;JOB IS IN SAFE STATE (I.E., SIMCHK SAYS OK)
;
;***GETPC***PUTPC*** EXTENDED ADDRESSING MAY GET IMPACTED HERE
CDBRK:: XMOVEI T4,USRPC## ;ASSUME RANDOM JOB PC
CAMN J,.CPJOB## ;IS THIS JOB CURRENTY SCHEDULED?
XMOVEI T4,.CPPC## ;YES, THEN THE PC IS ACTUALLY STORED HERE
DMOVE T1,@T4 ;GET THE JOB'S CURRENT PC
TLNE T1,USRMOD ;IS THE JOB IN USER MODE?
JRST CDBRK2 ;YES, TRIVIAL CASE
XMOVEI T4,.JDAT+JOBPD1## ;NO, EXEC MODE, MUST BE UUO (SIMCHK)
HRRZ T3,T2
DMOVE T1,@T4 ;NOW GET THE REAL USER PC
CAIE T3,UUODON## ;UUO COMPLETION?
JRST CDBRK5 ;NO, THIS GETS MORE COMPLICATED!
HRRZ T4,.JDAT+JOBDAC##+P ;GET SAVED P
MOVEI T4,-1(T4)
DMOVE T1,@T4 ;GET PC
;HERE WITH T1 CONTAINING THE USER PC A LA THE "JSR @.JBBPT", AND T4
;CONTAINING THE MONITOR ADDRESS FROM WHENCE THE USER PC CAME.
CDBRK2: TLNN T1,USRMOD ;JUST MAKING SURE
STOPCD .,JOB,BPE, ;++ BREAKPOINT PC EXEC MODE
PUSHJ P,INDDT ;IS USER PC FROM WITHIN DDT?
POPJ P, ;YES, FORGET IT!
PUSH P,T1 ;SAVE DOUBLE-WORD PC FLAGS WORD
TLNE T2,-1 ;IS USER PC FROM SECTION 0?
SKIPA T1,T2 ;NO, GLOBAL PC (SECTION,,PC)
HRR T1,T2 ;YES, LOCAL PC (FLAGS,,PC)
MOVEM T1,.JDAT+JOBOPC## ;STORE THE PC AS IF ^C, DDT
HRR M,.JDAT+JOBBPT##;POINT M TO THE BREAKPOINT TRAP ROUTINE
PUSHJ P,PUTWRD## ;STORE THE USER PC A LA "JSR @.JBBPT"
STOPCD .,JOB,BPF, ;++ BREAKPOINT PUTWRD FAILED
POP P,T1 ;RESTORE CURRENT USER PC FLAGS
MOVE T2,.JDAT+JOBBPT## ;ADDRESS OF BREAKPOINT TRAP ROUTINE
HRRI T2,1(T2) ;CONCOCT NEW USER PC A LA "JSR @.JBBPT"
DMOVEM T1,@T4 ;AND SET THE NEW USER PC
IFN FTKL10&FTMP,<
PUSHJ P,SETCSJ## ;THIS JOB IS NOW CACHE-DEPENDENT ON THIS CPU
> ;END IFN FTKL10&FTMP
JRST CPOPJ1## ;SUCCESSFUL RETURN
;THE USER PROGRAM IS IN A UUO WHICH SIMCHK SAYS CAN BE ABORTED. BACK OUT
;OF THE UUO, BACKUP THE USER PC, AND CONTINUE AS THOUGH THE UUO HADN'T
;BEEN EXECUTED. "$P" WILL RE-EXECUTE THE UUO.
CDBRK5: MOVSI T3,(JS.HIB) ;THE STUPID HIBER BIT
TDNE T3,JBTST2##(J) ;WAS IT A HIBER UUO?
HRRI T2,-1(T2) ;ACCOUNT FOR HIBER'S STUPID AOS
HRRI T2,-1(T2) ;BACKUP USER PC TO POINT TO THE UUO
XMOVEI T4,USRPC## ;ASSUME NON-SCHEDULED JOB
CAMN J,.CPJOB## ;CURRENTLY-SCHEDULED JOB?
XMOVEI T4,.CPPC## ;YES (???HUH??? CAN THIS HAPPEN???)
PUSHJ P,CDBRK2 ;SIMULATE THE "JSR" FOR THE "JSR @.JBBPT"
POPJ P, ;PC FROM WITHIN DDT? FLICK IT IN
LDB T3,PJBSTS## ;GET JOB WAIT CODE (IF ANY)
CAIL T3,MINQ## ;SHARABLE RESOURCE WAIT?
CAILE T3,MAXQ## ;AND DOES STATE ALSO HAVE A Q?
JRST CDBRK6 ;NO
SOSL RQTBMQ(T3) ;YES, REDUCE IT
JRST CDBRK6 ;NO
SOSGE AVTBMQ(T3) ;YES, REDUCE COUNT
SETZM AVTBMQ(T3) ;CLEAR AVAILABLE FLAG IF NO ONE ELSE WAITING
CDBRK6: MOVEI T3,RNQ## ;THE RUN QUEUE
DPB T3,PJBSTS## ;POOF! THE JOB IS NOW RUNNABLE!
TLO M,TTYRNU## ;TELL COMCON TO RUN TTYUSR ON RETURN
; THIS WILL DO MANY AND WONDROUS THINGS
; PUT TTY IN USER MODE (BREAK FROM TTCALL)
; SET NEW QUANTUM RUN TIME
; REQUE THE JOB, ETC.
JRST CPOPJ1## ;SUCCESS RETURN TO COMCON
;SUBROUTINE TO SEE IF USER PC IS IN DDT.
;CALL IS:
;
; D/MOVE T1,<PC>
; PUSHJ P,INDDT
; PC IS IN DDT
; PC IS NOT IN DDT
;
;WHERE PC IS ONE-WORD PC IF KI-STYLE PAGING, TWO-WORD PC IF KL-STYLE
;PAGING (ASSUMES STUCK IN SECTION 0).
;
;USES T3.
INDDT:: PUSHJ P,SAVE2## ;NEED A COUPLA SCRATCH ACS HERE
HRRZ T3,T2
HRRZ P1,.JDAT+JOBDDT## ;GET START ADDRESS OF DDT
HLRZ P2,.JDAT+JOBDDT## ;GET END ADDRESS OF DDT(PLUS 1)
CAML T3,P1 ;USER PC IN DDT?
CAML T3,P2 ; . . .
JRST CPOPJ1## ;NO
JUMPN P1,CPOPJ## ;YES
JRST CPOPJ1## ;NO
;SUBROUTINE TO SET UP AN INTERCEPT
;CALL WITH T4=INTERCEPT BIT
;EXIT NON-SKIP IF NOT ENABLED
;SKIP-RETURN IF ENABLED, SET TO TRAP ON UUO EXIT
; (OR START AT TRAP LOC IF IN USER MODE).
SETINT::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
SETPIT: PUSH P,T1 ;SAVE PC
GETPC T2,USRPC## ;YES--GET CURRENT PC
TLNE T2,USRMOD ;SEE IF EXEC MODE
JRST SETPIU ;NO--DO USER MODE
SETOM T1 ;SET DOINT FLAG
PUSHJ P,SETUTP ;YES--SET IF NEEDED TO TRAP UUO
JRST SETPIU ;NO--GO START JOB
POP P,T2 ;THROW AWAY PC
JRST CPOPJ1## ;ALL DONE UNTIL UUO EXIT
;HERE WHEN UUO NOT IN PROGRESS
SETPIU: PUTPC T2,USRPC## ;SETUP JOBPC FOR USTART
PUSHJ P,CLRTI## ;GET DDB OUT OF TI WAIT
POP P,T2 ;GET START PC
PUSH P,.JDAT+JOBOPC## ;SAVE OPC FOR USER
IFN FTXMON,<
HRRZS T2 ;AVOID ILLEGAL SECTION PAGE FAULTS
>
PUSHJ P,USTART ;START IN USER MODE
MOVE T1,.JDAT+JOBOPC## ;GET OLD PC
POP P,.JDAT+JOBOPC## ;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
;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)
SIMCHK::SKIPL T1,JBTSTS##(J) ;JOB STATUS. IS RUN BIT OFF?
POPJ P, ;YES, STOP JOB BUT DO NOT PRINT WATCH STATUS
TLNE T1,JERR ;IS ERROR BIT ON?
TRNE T1,JS.RUU ;AND NOT IN RUN/GET CODE?
CAIA ;NO TO ONE OF ABOVE, SO SKIP ON
POPJ P, ;JERR AND NOT IN RUN/GET, SO STOP JOB NOW
TLNN T1,SWP ;IS JOB IN CORE?
SKIPN JBTADR##(J) ;YES, DOES JOB HAVE CORE IN CORE?
JRST STOPC ;NO. ASSUME PC IN EXEC MODE
DMOVE T1,USRPC## ;YES, GET PC
CAMN J,.CPJOB## ;IS THIS JOB THE CURRENT JOB?
DMOVE T1,.CPPC## ;YES, GET PC AND FLAGS FOR CURRENT JOB
TLNE T1,USRMOD ;JOB PC IN USER MODE?
POPJ P, ;YES, JOB CAN BE STOPPED
HRRZ T1,T2 ;PC
CAIN T1,UUODON## ;AT THE END OF A UUO?
POPJ P, ;YES, STOP JOB RETURN
STOPC:
STOPD: 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
TDNE T2,DELAYN ;NO, IS JOB IN A STATE(IN EXEC) WHICH
; CAN BE STOPPED IMMEDIATELY
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
LDB T1,PJBSTS## ;GET STATE CODE
CAIE T1,EWQ## ;EVENT WAIT QUEUE?
POPJ P, ;NO, GO STOP JOB
LDB T2,JBYEWT## ;GET REASON CODE
MOVE T1,EWCCMK ;GET MASK OF BITS TO SEE IF DELAY OR STOP
LSH T1,-1(T2) ;SHIFT BIT TO BIT 0 POSITION
PJUMPL T1,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
POPJ P, ;STOP JOB
;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
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
;DEFINE A BIT FOR EACH EVENT WAIT CODE
; WHICH INDICATES WHETHER TO DELAY OR STOP THE JOB.
; 1 = DELAY (DJ), 0 = STOP (SJ)
DEFINE X(SYM,CODE),<
SYM==SYM ;;FORCE INTO SYMBOL TABLE
IFIDN <CODE><SJ>,<QQ==0> ;;STOP
IFIDN <CODE><DJ>,<QQ=1> ;;DELAY
YY==ZZ*QQ ;;SET THIS TO 1 OR 0
XX==XX!YY ;;ACCUMULATE VALUES IN XX
ZZ==ZZ_<-1> ;MOVE MASK BIT RIGHT ONE PLACE
>;END DEFINE X
QQ==0 ;MAKE SURE INTERMEDIATE VALUE IS 0
XX==0 ;START FINAL VALUE AT 0
ZZ==1B0 ;START WITH BIT 0 AND SHIFT RIGHT
EWCODE ;GENERATE BIT MASK IN XX
EWCCMK: EXP XX ;EVENT WAIT CODE BIT MASK WITH
; BIT ON IF JOB IS TO BE DELAYED,
; OR OFF IF IT IS TO BE STOPPED
; BITS GO FROM LEFT TO RIGHT
; IE, EV CODE 1 IS BO, 2 IS B1.
;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
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 CHKUT1 ;NO, CHECK FOR EVENT WAIT
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
CHKUT1: CAIE T3,EWQ## ;EVENT WAIT?
JRST CPOPJ1## ;NO--DELAY
PUSH P,T1 ;SAVE T1
LDB T1,JBYEWT## ;GET STATE SUB-CODE
MOVE T3,EWCCMK ;GET MASK BITS
LSH T3,-1(T1) ;POSITION TO SIGN BIT
JUMPL T3,TPOPJ1## ;BIT SET--DELAY TRAP
JRST TPOPJ## ;BIT CLEAR--OKAY TO TRAP NOW
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,.JDAT+JOBFDV## ;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
DLYCOM::MOVSI T1,CMWB ;SET COMMAND WAIT BIT
TDNE T1,JBTSTS##(J) ;IS JOB ALREDY IN COMMAND WAIT?
POPJ P, ;YES,JUST EXIT
IORM T1,JBTSTS##(J) ;IN JOB STATUS WORD
PJRST REQUE
;ROUTINE TO PUT JOB IN NO CORE QUEUE
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
; JSP T2,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
; 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"
SAVCTD::TLNE P4,SWP!SHF ;JOB IN CORE?
JRST DLYCM ;NO, WAIT UNTIL IT COMES IN
SAVCTX::SKIPGE JBTSTS##(J) ;JOB RUNNING OR RUNNABLE?
JRST SAVCT3 ;YES, FLUNK OUT NOW
SKIPN JBTADR##(J) ;DOES THIS JOB HAVE CORE?
S0PSHJ GETCIC## ;NO, ASSIGN A MINIMAL AMOUNT
PUSHJ P,FNDPDS## ;ADDRESS OF THE PDB
PUSHJ P,SAVCTS ;GO DO THE REAL WORK
JRST DLYCM## ;CORE NOT AVAILABLE YET, CAN'T SAVE CONTEXT
JRST ABORTC## ;WORKED
;RETURN HERE AT UUO LEVEL
;RETURN HERE AT UUO LEVEL
MOVE J,.CPJOB## ;CURRENT JOB'S JOB NUMBER
HRRZ W,JBTPDB##(J) ;ADDRESS OF THE PDB
HRRZ T1,.PDSCX##(W) ;ADDRESS OF THE SAVED CONTEXT
MOVE T2,.SCPPC(T1) ;THE JOB'S PC WHEN STOPPED
MOVE T3,.SCJST(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,.JDAT+JOBDPD## ;NO, USE THE CURRENT STACK POINTER IF THERE IS ONE
MOVE P,[MJOBPD##,,.JDAT+JOBPDL##] ;YES OR NO EXEC STACK POINTER,
; SO SETUP THE STACK TO POINT AT THE
; JOB'S JOB DATA AREA
PUSHJ P,TTYFNU## ;FIND OUR TTY
JUMPE U,ESTOP3 ;IF NOT ATTACHED, GIVE UP AND STOP THE JOB
HRRZ T1,.PDSCX##(W) ;RESTORE THE ADDRESS OF THE CONTEXT BLOCK
MOVEM U,.CPCML## ;SEE STOPCM IN SCNSER
MOVE S,.SCCIT(T1) ;SETUP ITEM TO BE RETURNED
TLO M,400000 ;INDICATE THIS IS A COMMAND
PUSHJ P,@.SCCPC(T1) ;CALL THE CALLER TO SAVCTX AS A SUBROUTINE
JFCL ;ALLOW A SKIP RETURN AS A CONVENIENCE
PUSHJ P,TTYFUW## ;FIND OUR TTY, U := ZERO IF DETACHED
PUSHJ P,FNDPDS## ;ADDRESS OF THE PDB
PUSHJ P,RESCTS ;RESTORE CONTEXT
PUSH P,T1 ;SAVE PC
PUSH P,T2 ;SECOND HALF
PUSH P,T3 ;SAVE JBTSTS
JUMPE U,SAVCT4 ;DON'T TYPE IF DETACHED
PUSHJ P,PRDOTM## ;OUTPUT A PERIOD
PUSHJ P,TTYSTC## ;START TTY,LEAVE AT MONITOR LEVEL
SAVCT4: POP P,T1 ;RESTORE PREVIOUS JBTSTS
;JUMPE U,ESTOP3 ;IF WE'RE DETACHED, JUST STOP THE JOB
TLNE T1,JERR ;WAS THE JOB IN A CONTINUABLE STATE?
JRST [HRRZS .JDAT+JOBPD1## ;NO, STOP THE JOB AND DON'T ALLOW CONTINUE
PJRST ESTOP]
PUSHJ P,ESTOP3 ;YES, ITS STILL CONTINUABLE
POP P,T2 ;PC
POP P,T1 ;FLAGS
DMOVEM T1,.CPPC## ;STORE FOR SCHEDULER
PJRST USCHE1 ;SAVE SOME ACS AND RESCHEDULE
SAVCT3: MOVEI T1,RUNERR## ;"PLEASE TYPE ^C FIRST"
PJRST ERRMES## ;PRINT THAT AND RETURN TO COMCON
;HERE TO DO THE REAL CLOCK LEVEL WORK. SWAPPER AND SAVCTX USE THIS
;(SWAPPER FOR MAPBAK). CALL IS:
;
; MOVEI T2,<TOP LEVEL PC TO RETURN TO AT UUO LEVEL>
; PUSHJ P,SAVCTS
; <CAN'T GET CORE>
; <SET UP TO RUN AT .+1 AT UUO LEVEL>
; <HERE AT UUO LEVEL>
;OTHER ITEMS (I.E. S) AS SET UP FOR SAVCTX
SAVCTS::PUSH P,T2 ;SAVE HIS CALLER'S PC
HRRZ T1,.PDSCX##(W) ;ALREADY BEEN HERE ONCE?
JUMPE T1,SAVCT1 ;JUMP IF NO
MOVE T2,.SCDAC+P(T1) ;SAVED PUSH DOWN LIST POINTER
MOVEM T2,.JDAT+JOBDPD## ;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 T2POPJ## ;CAN'T DO ANYTHING NOW
MOVE T2,JBTSTS##(J) ;THE JOB'S CURRENT STATUS
MOVEM T2,.SCJST(T1) ;SAVE THAT
DMOVE T2,USRPC## ;THE JOB'S CURRENT PC
DMOVEM T2,.SCPPC(T1) ;SAVE THAT TOO
MOVSI T2,.JDAT+JOBDAC## ;MAKE A BLT POINTER TO THE JOB'S
HRRI T2,.SCDAC(T1) ; USER AND EXEC ACS
BLT T2,.SCDAC+17(T1) ;SAVE THE JOB'S ACS
SAVCT2: MOVEM S,.SCCIT(T1) ;STORE ITEM TO BE RETURNED TO THE CALLER
POP P,.SCCPC(T1) ;STORE THE CALLER'S PC
HRRM T1,.PDSCX##(W) ;REMEMBER THE ADDRESS OF THE BLOCK CONTAINING
; THE JOB'S CONTEXT
MOVEM M,.SCCCF(T1) ;SAVE FLAGS FOR PRDOTM (EXAMINE COMMAND)
TLO M,NOFLM##!LHRUNF## ;TTYRNU+NOMESS+NOCRLF+NOPER+NOFLM
TLZ M,NOINCK## ;MAKE SURE JNA GETS TURNED ON SO JOB
; CORE IMAGE, ETC. WILL GO AWAY IF NOT LOGGED IN
AOS T2,(P) ;RETURN ADDRESS
AOJA T2,MSTART ;SET UP FOR UUO LEVEL AND RETURN
;HERE TO RESTORE THINGS SET UP BY SAVCTS
;RETURN WITH T1, T2 CONTAINING SAVED PC AND T3 CONTAINING SAVED JBTSTS
RESCTS::HRRZ T2,.PDSCX##(W) ;ADDRESS OF THE JOB'S SAVED CONTEXT
PUSH P,.SCPPC(T2) ;THE SUSPENDED JOB'S FLAGS
PUSH P,.SCPPC+1(T2) ;THE SUSPENDED JOB'S PC
MOVSI T1,.SCDAC(T2) ;FORM A BLT POINTER
HRRI T1,.JDAT+JOBDAC## ; TO THE JOB'S SAVED ACS
BLT T1,.JDAT+JOBD17## ;RESTORE THE JOB'S SAVED ACS
PUSH P,.SCJST(T2) ;JOB'S PREVIOUS JBTSTS
MOVE M,.SCCCF(T2) ;ORIGINAL M (FOR FLAGS)
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,T3 ;RESTORE PREVIOUS JBTSTS
JRST TTPOPJ## ;PUT PC IN T1,T2 AND RETURN
;SUBROUTINE TO ZERO F, F IN THE DUMP AC'S, AND F IN THE JOB'S
;SAVED CONTEXT, IF ANY
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER
; MOVEI F,DDB ADDRESS
; PUSHJ P,DMPFZR
DMPFZR::PUSHJ P,SAVJW## ;PRESERVE J
MOVE J,.USJOB ;SET UP TO FIND PDB OF RIGHT JOB
PUSH P,T1 ;SAVE T1
PUSHJ P,FNDPDS## ;FIND JOB'S PDB
HRRZ T1,.PDSCX##(W) ;ADDR OF SAVED CONTEXT
JUMPE T1,DMPFZ1 ;JUMP IF NONE
PUSH P,T2 ;SAVE T2
HRRZ T2,.SCDAC+F(T1) ;GET RH OF F IN SAVED CONTEXT
CAIN T2,(F) ;SAME AS ONE WE ARE RETURNING?
SETZM .SCDAC+F(T1) ;YES, ZERO F IN SAVED CONTEXT
POP P,T2 ;RESTORE T2
DMPFZ1: SETZB F,.JDAT+JOBDAC##+F ;ZERO F & DUMP AC F
PJRST TPOPJ## ;RESTORE T1 & RETURN
;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
MONJOB::
IFN FTMP,<
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.; 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,W,M, AND J SETUP
MONSTR::SKIPN J,.CPJOB## ;CURRENT JOB NUMBER
STOPCD .,STOP,NDS, ;++NULL-JOB DID SAVGET
MOVSI P,MJOBPD## ;MINUS LENGTH OF SYSTEM PD LIST
HRRI P,.JDAT+JOBPDL## ;FIRST LOC.-1 OF PD LIST
PUSHJ P,FNDPDB## ;ADDRESS OF PDB FOR THIS JOB
JFCL
IFN FTMP,<
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
MOVE T2,[IOW,,IOACT] ;JOB IS NOT IN TIOW WHEN RUNNING THE MONITOR JOB
SKIPE T3,TTYTAB##(J) ;SO IF THE JOB HAS A TTY, CLEAR IOW
ANDCAM T2,DEVIOS(T3) ;SINCE A CALL TO STTIOD WILL ZAP WAIT STATE CODES
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
; PUSHJ P,USTART(PC TO USER MODE),MSTART(PC TO MONITOR MODE)
; RETURN HERE IMMEDIATELY
USTART::GETPC T1,USRPC## ;GET OLD PC
TLNE T1,USRMOD ;IS IT IN USER MODE TOO?
JRST USTRT1 ;YES, DUMP ACS AND PC FLAGS ARE ALREADY HIS
GETPC T1,.JDAT+JOBPD1## ;GET LAST PC + 1
HRRI T1,-2(T1) ;ASSUME HE DID A HIBER
PUSH P,T2
MOVSI T2,(JS.HIB) ;WAS HE HIBERNATING?
TDNN T2,JBTST2##(J)
HRRI T1,1(T1) ;NO, DON'T DECREMENT TWICE
POP P,T2
USTRT1: MOVEM T1,.JDAT+JOBOPC## ;STORE OLD PC FOR USER TO LOOK AT
IFN FTMP,<
PUSHJ P,DPXST## ;MAKE JOB RUNNABLE ON SLAVE NOW
>
MOVE T1,USRPC##
TLNN T1,USRMOD
MOVE T1,.JDAT+JOBPD1##
TLO T1,(XC.USR+IFN FTKL10,<XC.PUB>)
TLZ T1,37
JRST MSTRT1 ;DON'T CLEAR JSP WORD
MSTART::
IFN FTXMON,<
MOVSI T1,MXSECN
ANDCAM T1,.USUPF ;ALWAYS START MONITOR JOB WITH PCS=0
>
MOVSI T1,(IC.UOU)
TLZ T2,777740
IFN FTMP,<
PUSHJ P,CLRJSP## ;INITIALIZE JBTSPS ENTRY
>
MSTRT1: CAMN J,.CPJOB## ;IS IT THE CURRENTLY RUNNING JOB?
DMOVEM T1,.CPPC##
DMOVEM T1,USRPC##
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.DPM] ;CLEAR TYPED ^C FLAG
; CLEAR MEM PAP ERR, 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
SETRUN::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
CAIL T1,MINQ## ;SHARABLE RESOURCE STATE CODE?
CAILE T1,MAXQ## ;DOES JOB STATUS CODE HAVE A QUEUE?
JRST SETR1 ;NO
CAIE T1,AUQ## ;HAVE AU?
CAIN T1,DAQ## ;OR DA?
STOPCD .,STOP,CCR, ;CAN'T CONTINUE WITH RESOURCE
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&FTMP,<
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
HRRZ T2,JBTPDB##(J)
SKIPN T2
STOPCD .,JOB,CFP, ;++CAN'T FIND PDB
.DPB T1,PDYQT2## ;SET QUANTUM RUN TIME
REQUE:: SKIPN J ;TRYING TO REQUEUE THE NULL JOB?
STOPCD CPOPJ##,DEBUG,RJ0, ;++REQUEUE JOB 0
MOVSI T1,JRQ ;MARK JOB TO BE REQUEUED WITH JRQ BIT
SYSPIF ;GUARD AGAINST COUNTING QJOB UP TWICE
TDNE T1,JBTSTS##(J) ;INCREMENT COUNT ONLY ONCE FOR EACH JOB
JRST ONPOPJ## ;JOB IS ALREADY MARKED FOR REQUEING
IORM T1,JBTSTS##(J) ;SET REQUE BIT FOR SCHEDULER
CAMN J,JBTJRQ## ;ABOUT TO CAUSE SCHEDULER LOOP?
STOPCD ONPOPJ##,DEBUG,RSJ, ;++REQUEUE SAME JOB
MOVE T1,JBTJRQ##
HRRZM J,JBTJRQ##
MOVEM T1,JBTJRQ##(J)
SYSPIN ;TURN ON
PJRST NJBTST ;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
SYSPIF ;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
SYSPIN ;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
HRRZ J,T1 ;JOB # TO J
MOVEI T1,RNQ## ;RUN QUEUE
SYSPIF ;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)
SYSPIN
PJRST JPOPJ## ;EXIT
;SUBROUTINE TO SET TIME USER STARTED TO WAIT FOR RESPONSE
; IF NOT ALREADY CALLED WHEN A COMMAND IS DELAYED
IFN FTRSP,<
SETRSP::MOVE T1,SYSUPT## ;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,.CPAOR## ;BASE ADR FOR 3 WORD TTY OUTPUT UUO RSP
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,.CPAIR## ;BASE ADR. FOR 3 WORD TTY INPUT UUO RSP
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 J,JOB NUMBER
; MOVEI T1,.CPA??## ;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::MOVE J,.CPJOB## ;CURRENT JOB ON CPU0
RSPRC2::PUSHJ P,RSPREC ;RECORD THIS RESPONSE
MOVEI T1,.CPAXR## ;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,SYSUPT## ;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.
SYSPIF ;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
SYSPIN ;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
MTIMLM: PUSHJ P,TTYERP## ;LIMIT JUST WENT TO 0 - FIND TTY DDB
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
MOVE T3,JBTLIM##(J) ;GET BATCH LIMIT WORD
TLNN T3,(JB.LBT) ;A BATCH JOB?
JRST HOLD0 ;NO--STOP JOB, DON'T ALLOW CONTINUE
PUSHJ P,CTLJBD## ;FIND THE CONTROLLING JOB
SE1XCT <LDB T2,LDPMJN##> ;GET LINES MIC MASTER JOB NUMBER
CAME T1,T2 ;IF CONTROLLING JOB NUMBER MATCHES MIC
; MASTER JOB NUMBER, THEN THIS IS A MIC
; COJOB AND WE DON'T WANT TO ZAP MIC
; MIC STATUS. (COJOBS DON'T CARE ABOUT TIME
; LIMIT EXCEEDED.
SE1XCT <SETZM LDBMIC##(U)> ;PREVENT MIC FROM MESSING WITH A REAL
; "BATCON" BATCH JOB
JRST HOLD0 ;STOP JOB, DONT SET JERR
; (SO "CONT" WILL WORK)
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
;ROUTINE TO PUT A JOB TO SLEEP AND WAKE UP AGAIN LATER
;CALLED AFTER CLOCK QUEUE REQUEST PUT IN BY UUO ROUTINE
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 IF ALREADY THE WAIT STATE CODE SET UP (HIBER)
SETHBR::MOVEI T1,CLKR
IORM T1,JBTSTS##(J) ;SAY WE SET THE REQUEST
JRST SETSTX
;HERE AT CLOCK LEVEL WHEN CLOCK REQUEST TIMES OUT FOR SLEEP
;JOB NO. IN AC T1
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
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
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 LOG AN ERROR BUT NOT BLOCK THE JOB
;CALL: MOVE J,JOB NUMBER
; MOVEI T1,CODE FOR THIS ERROR
; HRLI T1,CDB OR DDB ADDRESS
; PUSHJ P,DAEDSJ##
; ALWAYS RETURN
DAEDSJ::PUSH P,J ;SAVE J
DPB J,[POINT 9,T1,26] ;STORE IN CODE WORD
PUSHJ P,DAEEIM ;LOG IT BUT DON'T STOP JOB
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,PI.OFF ;NEED TO TURN OF PI'S TO STOP TWO I
IFN FTMP,<
SKIPGE DAELOK ;DON'T TRY IF CAN'T POSSIBLY GET IT
AOSE DAELOK ;GET CPU INTERLOCK
JRST .-2 ;WAIT UNTIL AVAILABLE
>
MOVE T2,ERPSIZ## ;GET SIZE OF ERPTBK ENTRY
ADDB T2,ESVIDX## ;GET INDEX FOR NEXT ERROR TO SAVE
CAIL T2,ERPTMX## ;HAVE WE EXCEEDED MAX
SETZB T2,ESVIDX## ;YES, JUST RESET ESVIDX
IFN FTMP,<
SETOM DAELOK
>
CONO PI,PI.ON
SKIPE ERPTBK##(T2) ;HAVE WE OVERLAPPED
JRST MNYERR ;YES, DAEMON ISN'T KEEPING UP, LOSE THIS ERROR
TRNE J,-1 ;DON'T STORE JOB NUMBER IF ZERO
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)
MOVS T1,.CPCPN## ;GET CPU NUMBER OF THIS CPU
TRO T1,777 ;SET TO WHAT LOOKS LIKE A JUNK
MOVEM T1,ERPTBK##+2(T2) ; CODE TO OLD VERSIONS OF DAEMON FOR COMPATABILITY
SETZM ERPTBK##+3(T2) ;ZERO FINAL WORD
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
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
;ROUTINE TO FIND DAEMON, START RUNNING
;RETURNS POPJ IF CANT FIND, CPOPJ1 IF OK, T1 = DAEMON JOB #
STDAEM::MOVEI T1,1 ;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
TLNE T2,JACCT
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: CAMG T1,HIGHJB## ;LOOP FOR MORE JOBS
AOJA T1,STDAE1
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
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?
CAIA ;START USER IF RUNNABLE
POPJ P, ;RETURN
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.
;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
PUSHJ P,SAVE1## ;SAVE PI
CAIL T2,ERPTMX## ;OFF END OF TABLE?
SETZ T2, ;YES, RESET POINTERS
HRR M,T1
HLRZ P1,T1 ;GET LENGTH
CAIGE P1,2 ;LESS THAN 2?
MOVEI P1,2 ;YES, OLD DAEMON
CAMLE P1,ERPSIZ## ;LARGER THAN ENTRY SIZE?
MOVE P1,ERPSIZ## ;YES, MAKE IT ENTRY SIZE
MOVNI P1,-1(P1) ;GET -VE COUNT FOR AOBJP POINTER
HRLZS P1 ;MAKE AOBJP POINTER TO ARGS .GT. 2
ERPTLP: SKIPE T1,ERPTBK##(T2) ;IS THIS ENTRY 0?
JRST GOTONE ;NO, RETURN IT
ADD T2,ERPSIZ##
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##
HRR P1,T2 ;POINT TO ENTRY WITH P1
ERPLP1: AOBJP P1,ERPLPE ;DONE IF COUNT RAN OUT
MOVE T1,ERPTBK##+1(P1) ;GET NEXT ENTRY
PUSHJ P,PUTWD1## ;GIVE IT TO DAEMON
JRST ERPLP1 ;LOOP FOR NEXT
ERPLPE: ADD T2,ERPSIZ##
MOVEM T2,EPKIDX## ; AND SAVE FOR WHERE TO LOOK NEXT
JRST CPOPJ1## ;AND SKIP
;SUBROUTINE TO CALL DAEMON FOR DEBUG OR JOB STOPCD
;DOES NOT TRY TO STOP ANY JOB
DAEEST::MOVEI T1,41 ;LENGTH OF STOPCODE ENTRY
PUSHJ P,ALCSEB## ;GET A SYSTEM ERROR BLOCK
POPJ P, ;COULDN'T? DON'T LOG IT
MOVEI T2,.ERMSE ;GET CODE FOR DAEMON
DPB T2,[POINT 9,.EBTYP(T1),8] ;STUFF IT IN ENTRY
MOVE T3,.CPJOB## ;GET RUNNING JOB NUMBER
MOVSI T2,CONFIG## ;BUILD BLT POINTER
HRRI T2,.EBHDR(T1) ;TO COPY SYSTEM NAME
BLT T2,.EBHDR+6(T1) ;(R0-R6) AND DATE
XMOVEI T2,.EBHDR+6(T1) ;POINT TO NEXT PLACE FOR ITEMS
PUSH T2,.CPASN## ;(R7) CPU SERIAL NUMBER
PUSH T2,MONVER## ;(R10) MONITOR VERSION NUMBER
PUSH T2,%SYSCD## ;(R11) STOPCODE NAME
PUSH T2,T3 ;(R12) JOB NUMBER
PUSH T2,@TTYTAB##(T3) ;(R13) TTY NAME
PUSH T2,JBTPRG##(T3) ;(R14) PROGRAM NAME
PUSH T2,JBTPPN##(T3) ;(R15) PPN
PUSH T2,%SYNJS## ;(R16) NUMBER OF JOB STOPCODES
PUSH T2,%SYNDS## ;(R17) NUMBER OF DEBUG STOPCODES
HRLZ T2,.CPACA##
HRRI T2,.EBHDR+20(T1) ;SET UP TO COPY ACs WHICH WERE ACTIVE
BLT T2,.EBHDR+37(T1) ;(R20-R37) AT TIME OF STOPCODE
MOVE T2,.CPCPI## ;GET PI STATUS
MOVEM T2,.EBHDR+40(T1) ;(R40) AND SAVE IT
JRST QUESEB## ;QUEUE THE ERROR BLOCK AND KICK DAEMON
;SUBROUTINE TO CALL DAEMON FOR ANY ERROR TO BE REPORTED
;DURING STOPCD PROCESSING.
;ARGS SAME AS DAEEIM.
DAEDIE::
IFN FTMP,<
MOVEI T2,^D100 ;MAX COUNT TO WAIT FOR INTERLOCK
SKIPGE DAELOK ;DON'T TRY IF CAN'T POSSIBLY GET IT
AOSE DAELOK ;GET INTERLOCK
SOJG T2,.-2 ;FAILED, LOOP BUT NOT TOO LONG
>;END IFN FTMP
MOVE T2,ERPSIZ## ;GET SIEZ OF ENTRY
ADDB T2,ESVIDX## ;GET INDEX FOR NEXT ERROR TO SAVE
CAIL T2,ERPTMX## ;HAVE WE EXCEEDED MAX
SETZB T2,ESVIDX## ;YES, JUST RESET ESVIDX
IFN FTMP,<
SETOM DAELOK ;RELEASE INTERLOCK
>
SKIPE ERPTBK##(T2) ;HAVE WE OVERLAPPED
JRST MNYERR ;YES, DAEMON ISN'T KEEPING UP, LOSE THIS ERROR
DPB J,[POINT 9,T1,26] ;PUT IN JOB NUMBER
MOVEM T1,ERPTBK##(T2) ;SAVE T1 FOR ERRPT. UUO
MOVE T1,U
HRL T1,F
MOVEM T1,ERPTBK##+1(T2)
MOVS T1,.CPCPN## ;GET CPU NUMBER OF THIS CPU
TRO T1,777 ;JUNK CODE FOR COMPATABABILITY WITH OLD DAEMON'S
MOVEM T1,ERPTBK##+2(T2) ;STORE IN BLOCK
SETZM ERPTBK##+3(T2) ;CLEAR LAST WORD
POPJ P,
IFN FTMP,<
$LOW
DAELOK: -1 ;INTERLOCK TO PREVENT MORE THAN ONE
;CPU IN A MULTIPROCESSOR SYSTEM FROM
;GETTING TO DAEDIE AT THE SAME TIME.
;THE SYSPIF INTERLOCK IS NOT USED HERE
;BECAUSE WAITING FOR THE INTERLOCK MAY
;HAVE CAUSED THE CRASH.
$HIGH
>
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
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
DEFINE X(A,B,C)<
MQ==MQ+1>
MQ==0
QUEUES
DEFINE X(A)<
A'WAIT:: PUSHJ P,SRWAIT
>
DVWAIT: RWAITS
SRWAIT: MOVEM 16,.JDAT+JOBD16## ;SAVE AC16 (SINCE IT IS A PRESERVED AC)
MOVEM 17,.JDAT+JOBD17## ;ALSO AC17
POP P,16 ;GET ENTRY ADDRESS
MOVEI 16,-DVWAIT+MQ-1(16) ;COMPUTE WAIT-STATE QUEUE CODE
MOVE 17,.CPJOB## ;PICK UP JOB NUMBER
CPLOCK (SCD)
AOSG REQTAB##-MQ(16) ;IS THE RESOURCE AVAILABLE?
JRST SRAVAL ;YES, GO USE IT
SETSTT: MOVE 17,.CPJOB## ;JOB NUMBER OF RESOURCE REQUESTER
DPB 16,PJBS3 ;STORE QUEUE CODE IN JOB STATUS
SETSTX:
MOVE 16,.JDAT+JOBD16## ;RESTORE AC16
IFN FTMP,<
PUSHJ P,SCDOWN## ;OWN?
CPUNLK (SCD)
> ;END IFN FTMP
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: CPUNLK (SCD)
IFN FTMP,<
SETZM AVALTB-MQ(16) ;MMAVAL COULD BE -1 IF ONE
; CPU WAS IN GETMM WHILE
; ANOTHER CPU IS IN SRFREE
>
MOVE 17,.CPJOB## ;JOB NUMBER OF RESOURCE OWNER
CAIE 16,CBQ## ;ALWAYS GIVE THE JOB THE CB RESOURCE
SKIPE DINITF ;IF ONCE
JRST SRAVL0 ; ONLY
PUSH P,T3 ;PRESERVE T3
MOVE T3,JBTSTS##(17) ;JOB STATUS
TLNN T3,JXPN ;EXPANDING?
CAMN 17,FORCEF## ;OR BEING FORCED OUT?
JRST SRAVL2 ;YES, CHECK FUTHER
SRAVL1: POP P,T3 ;RESTORE T3
SRAVL0: MOVEM 17,USRTAB##-MQ(16);REMEMBER IT SO RESOURCE CAN BE GIVEN
; UP IN THE EVENT OF A CATASTROPIC ERROR
MOVE 17,.JDAT+JOBD17## ;RESTORE AC17
MOVE 16,.JDAT+JOBD16## ;AND AC16
POPJ P, ;RETURN TO THE CALLER WITH THE
; REQUESTED RESOURCE
SRAVL2: PUSH P,J ;PRESERVE J
MOVE J,17 ;JOB NUMBER FOR FLDSR
PUSHJ P,FLSDR## ;HAVE DISK RESOURCE?
JRST SRAVL3 ;NO, DON'T GIVE HIM ANOTHER
POP P,J ;RESTORE J AND LET HIM
JRST SRAVL1 ; CONTINUE UNTIL HE HAS NONE
SRAVL3: POP P,J
POP P,T3 ;RESTORE AC'S
SETOM AVALTB-MQ(16) ;SET AVAL BUT DON'T
JRST SETSTT ; GIVE UP RESOURCE
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
DEFINE X(A,B,C)<
A'FREE:: PUSHJ P,SRFREE
>
DVFREE::RWAITS
SRFREE: EXCH T1,(P) ;GET ENTRY ADDRESS AND SAVE T1
SUBI T1,DVFREE+1 ;CALCULATE WAIT STATE INDEX
HRLZS USRTAB##(T1) ;XWD LAST USER, 0 (NO CURRENT USER)
SOSL REQTAB##(T1) ;DECREMENT REQUEST COUNT. ANY JOBS WAITING?
SETOM AVALTB##(T1) ;YES, FLAG IT AS AVAILABE SO THIS SCHEDULER WILL
; GIVE THE RESOURCE TO A WAITER
SKIPE DINITF## ;NO UNWINDING DURING ONCE-ONLY
JRST TPOPJ##
PUSH P,J ;SAVE J
HLRZ J,USRTAB##(T1) ;GET OWNER OF RESOURCE
SRFRCX::
SRFRAU:: ;
SRFRDA:: ;
SRFRIP::
SRFRDT::
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
MOVSI T1,-AVLNUM## ;# OF QUEUES
SRFRE1: PUSHJ P,@TSTSRT(T1) ;JOB OWN RESOURCE OF THIS TYPE?
AOBJN T1,SRFRE1 ;NO
JUMPL T1,SRFRE4 ;JOB OWNS SOMETHING
;HERE IF JOB OWNS NO OTHER RESOURCES - FLAG FOR FORCED RESCHEDULE
SYSPIF ;NO PI'S
SKIPN SCDRTF## ;FORCED RESCHEDULE IN PROGRESS?
SETOM SCDRTF## ;NO PUT ONE IN
SYSPIN ;ALLOW PI'S
MOVEI T1,JS.OOO ;CLEAR OUT OF ORDER BIT
ANDCAM T1,JBTST2##(J)
SETZM UNWIND## ;ALLOW ANOTHER UNWIND CYCLE
SRFRE4: 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
POP P,J ;RESTORE J
; GET BACK HERE.
POP P,T1 ;RESTORE T1
PJRST RTEVM## ;AND GIVE UP EVM IF ANY
;TABLE USED BY THE ABOVE
DEFINE X(A,B,C,D,E,F)<
IFB \'F'\,<IFIW TSTSR>
IFNB \'F'\,<IFIW 'F'##>
>
TSTSRT: RWAITS
;DEFAULT TEST ROUTINE:
TSTSR: CAMN J,USRTAB##(T1)
AOS (P) ;OWN RESOURCE OF THIS TYPE
POPJ P,
;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
PUSHJ P,FNDPDS## ;GET ADDRESS OF PDB
MOVSI T1,(PD.LGN) ;GET THE COUNT BIT
TDNN T1,.PDDFL##(W) ;HAVE WE COUNTED YET?
POPJ P, ;YES, ALL DONE
ANDCAM T1,.PDDFL##(W) ;NO, SO CLEAR IT AND
AOS LOGNUM## ;INCREMENT LOGNUM
POPJ P, ;RETURN
;SUBROUTINE TO CLEAR JLOG AND DECREMENT LOGNUM
;CALL WITH:
; MOVE J,JOB#
; PUSHJ P,CLRLOG
;USES T1,T2
CLRLOG::
MOVSI T2,(JB.LBT) ;IS THIS A BATCH JOB?
TDNE T2,JBTLIM##(J) ;--
SOS BATNUM## ;DECREMENT BATNUM
PUSHJ P,FNDPDS## ;GET ADDRESS OF PDB
MOVSI T1,(PD.LGN) ;GET THE COUNT BIT
TDNN T1,.PDDFL##(W) ;HAVE WE COUNTED DOWN YET?
TRNA ;NO, SO SKIP
JRST CLRJLG ;YES, JUST CHECK JLOG NOW
IORM T1,.PDDFL##(W) ;FLAG THAT WE HAVE COUNTED
SOS LOGNUM## ;DECREMENT LOGNUM
CLRJLG:: ;HERE JUST TO CLEAR JLOG
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
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
PJBS2: POINT JWSIZ,JBTSTS##(T1),JWPOS ;BYTE POINTER TO JOB STATUS
; WORD QUEUE CODE
STPIOD::MOVEI T2,PSQ## ;REQUE TO PAGING I/O WAIT SATISFIED
JRST STIDZA
STTIOD::LDB T1,PJOBN## ;JOB NUMBER
IFN FTRSP,<
MOVE T2,SYSUPT## ;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
CAMGE T2,FRSHPQ## ;FORCE SCHEDULER CYCLE.
JRST STTID2 ;NO, NOT HPQ OR HPQ TOO LOW
PUSH P,T3 ;SAVE T3
MOVSI T3,SWP ;GET BIT TO TEST FOR
SYSPIF ;TURN OFF PI'S
TDNN T3,JBTSTS##(T1) ;HPQ JOB SWAPPED OUT, COMMING OUT OF
;TI WAIT?
JRST STTID1 ;NOT SWAPPED OUT, TURN ON PIS AND CONTINUE
SKIPG T3,SCDRTF## ;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,SCDRTF## ;YES, USE OUR JOB NUMBER
SETOM .CPCKF## ;FLAG THAT WE'RE DOING CH7 INTERRUPT
SYSPIN (CLKBIT##+PI.IIO) ;CAUSE INTERRUPT TO HAPPEN
POP P,T3
JRST STTID2 ;CONTINUE
STTID1: SYSPIN ;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
JRST SETID1
SETIOD::MOVEI T2,WSQ## ;REQUE TO WAIT SATISFIED Q
JRST SETID0
STDIOD::MOVEI T2,DSQ## ;SET DISK IO WAIT STATISFIED QUEUE
SETID0:
IFN FTHPQ,<
LDB T1,PJOBN## ;GET JOB NUMBER OF DDB IN F
LDB T1,HPQPT1## ;GET HIS HPQ NUMBER
CAMGE T1,FRSHPQ## ;FORCE SCHEDULER CYCLE NOW
JRST SETID1 ;NO,NOT HPQ OR HPQ TO LOW
SYSPIF ;TURN OFF PI'S
SKIPN SCDRTF## ;ANY REAL TIME RESCHEDULE TO DO?
SETOM SCDRTF## ;NO, FLAG UUOCON AND SCHED1 THAT THERE IS
;AN HPQ JOB TO SCHEDULE
SETOM .CPCKF## ;DOING A CH7 INTERRUPT
SYSPIN (CLKBIT##+PI.IIO)
>;END IFN FTHPQ
SETID1: LDB T1,PJOBN## ;GET JOB NUMBER
IFN FTPI,<
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: MOVEM S,DEVIOS(F) ;MAKE SURE IOS IS IN MEMORY BEFORE MAKING JOB RUNNABLE
STIDZA: CAIN T2,TSQ## ;TIOW SATISFIED?
JRST STID2B ;YES, REQUEUE
MOVEI T2,RNQ## ;MAKE JOB RUNNABLE
DPB T2,PJBS2
JRST NJBTST ;SEE IF WE SHOULD FORCE REQUE
STID2B: DPB T2,PJBS2 ;IN JOB STATUS WORD
PUSH P,J ;SAVE J
MOVE J,T1 ;GET JOB NUMBER
PUSHJ P,REQUE ;REQUE THIS JOB
POP P,J ;RESTORE J
NJBTST::SKIPN .CPJOB## ;IS NULL JOB RUNNING?
PJRST STOP2 ;YES, CAUSE RESCHEDULE
IFN FTMP,<
MOVE T1,.CPSCS## ;RUN THE SCHEDULER
IORM T1,DOORBL## ;DONG!
>
POPJ P, ;NO LET OTHER JOB RUN TILL SCHEDULER IS TRAPPPED TO
SETID3:
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## ;OK TO 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.
WAIT1::
IFN FTMSGSER,<
PUSH P,T1 ;NEED A SPARE AC
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIN T1,<.TYMPX/.TYEST> ;AN MPX CHANNEL?
PJRST MPXWAI## ;YES, SPECIAL MSGSER CODE THEN
POP P,T1 ;NO, NORMAL DEVICE HANDLING
WAIT1M::> ;END IFN FTMSGSER
MOVE S,DEVIOS(F) ;GET I/O STATUS WORD
TRNN S,IOACT ;IS DEVICE ACTIVE? (IOACT=1?)
JRST WAIT2 ;RETURN
PUSHJ P,WSYNC ;WAIT
JRST WAIT1
IFN FTMP,<
WAIT2: PUSH P,T1 ;SAVE A TEMP
HRRZ T1,DEVCPU(F) ;GET ADDR OF INTERLOCK WORD
SKIPL (T1) ;WAIT UNTIL CPU DOING IO
JRST .-1 ; LEAVES INTERRUPT LEVEL
JRST TPOPJ## ;RESTORE AC AND RETURN
>
IFE FTMP,<
WAIT2==CPOPJ##
>
;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
WSYNC:: PUSHJ P,SAVE3## ;SAVE P1-P3
TRNN F,777700 ;IS RH(F) LESS THAN 100?
STOPCD CPOPJ##,JOB,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 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,.CPJOB## ;CURRENT JOB NO.
MOVEI P2,IOACT ;DEVICE ACTIVE BIT
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
PION ;TURN PI ON
HRRM F,JBTDDB##(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
HLLZS JBTDDB##(P3)
JRST WSYNC2
WSYNC1: PION
WSYNC2: ANDCAB S,DEVIOS(F) ;CLEAR DEVICE IO-WAIT BIT
POPJ P, ;HALT HERE IF F LESS THAN 100
$LIT
CLKEND: END