1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-01-31 13:52:00 +00:00
Files
PDP-10.stacken/files/stacken-tape-backup/dskb:10_7/mon/clock1.mac
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

3669 lines
129 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE CLOCK1 - CLOCK, CONTEXT SWITCHING, AND JOB STARTUP AND STOP ROUTINES - V1465
SUBTTL APRINT TH/CHW/RCC/PFC/JE/DAL/EVS/JBS 21-JUNE-88
SEARCH F,S,DEVPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1973,1988>
XP VCLOCK1,1465
; 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 APR,AP.NXE## ;NON-EXISTENT MEMORY
CONSZ APR,AP.MPE## ; OR MEMORY PARITY ERROR?
JRST APRPAR ;YES--GO PROCESS IT
>
SKIPN .CPTIM## ;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 APRSU3 ;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)*TICSEC GOES IN
MOVEM T1,.CPOK## ; THE POLICY CPU'S OK WORD
MOVEI T1,.C0CDB## ;FIRST CPU'S CDB
APRSU1: AOSN .CPOK##-.CPCDB##(T1) ;COUNT EVERYONE ELSE'S KEEP ALIVE
PUSHJ P,BRKLOK## ;CPU IS DOWN, BREAK ANY INTERLOCKS IT MAY OWN
APRSU2: HLRZ T1,.CPCDB##-.CPCDB##(T1) ;NEXT CDB
JUMPN T1,APRSU1 ;LOOP IF MORE
>
AOS TIME## ;INCREMENT TIME OF DAY FOR SYSTEM
AOS T1,SYSUPT## ; AND SYSTEM UPTIME
PUSH P,T2 ;SAVE SECOND PART OF RESULT
MULI T1,^D1000 ;CONVERT TO MILLISECONDS
DIV T1,TICSEC## ; OF UPTIME
POP P,T2 ;RESTORE TRASHED AC
MOVEM T1,SYSUTM## ;SAVE AWAY
JRST APRSU4
APRSU3: MOVN T1,TICSEC## ;-TICS/SECOND
MOVEM T1,.CPOK## ;NUMBER OF COUNTS UNTIL WE ARE DEAD
APRSU4: AOS .CPUPT## ;INCREMENT THIS CPU'S UPTIME
AOSN .CPTMF## ;SET FLAG THAT APR CLOCK HAS TICKED
AOS .CPTMF## ;I SAID SET IT (KAF BEFORE WRAPAROUND ANYWAY)
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
>
SETZM .CPTIM## ;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
IFN FTKL10,<
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
RDERA .CPAER## ;SAVE THE ERA ON KL10
PUSHJ P,REDSBC## ;READ AND CLEAR MEMORY CONTROLLERS
MOVEI T4,UE.PEF ;ASSUME PARITY ERROR
CONSZ APR,AP.NXE## ;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?
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,TICSEC## ;TICKS PER SECOND
IMULI T1,5 ;MAKE THAT FIVE SECONDS
ADD T1,.CPLCI## ;PLUS TIME OF LAST CHANNEL INTERRUPT
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
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,DATIME## ;PRINT DATE/TIME
PUSHJ P,PCRLF## ;APPEND A CRLF
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
; JRST APPKLE ;GO EXAMINE THE ERA FOR FURTHER INFO
;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
;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,AP.NOT## ;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: MOVEM 17,.CPA17## ;SAVE AC 17
MOVEI 17,.CPA00## ;FIRST ADR. OF PARITY SWEEP SAVE AC AREA
BLT 17,.CPA17##-1 ;SAVE ALL ACS IN CDB BLOCK
MOVE 17,.CPA17## ;RESTORE AC 17
HLLZ S,.CPMPS## ;REQUEST CPU SWEEP
TRO S,(T4) ;FLAG WHETHER NXM OR PARITY SWEEP
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,17 ;...
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
>; END IFN FTKL10
;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:
IFN FTKL10,<
TRNE T4,UE.PEF!UE.NXM;IS THIS A NXM/PARITY ERROR?
JRST APPUPE ;YES, FLAG JOB AS SUCH
>; END IFN FTKL10
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 FTKL10,<
TRNN T4,UE.PEF!UE.NXM ;IS THIS A PARITY/NXM ERROR?
JRST APRUT6 ;NO--PROCEED
>; END IFN FTKL10
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
IFN FTKL10,<
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
>; END IFN FTKL10
;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
IFN FTKL10,<
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)
>; END IFN FTKL10
;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 FTKL10,<
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,AP.NOT## ;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,<
SKIPN T1,MOFLPG## ;SETTING MEMORY OFF-LINE OR CHANGING POLICY CPU?
JRST SAVPC2 ;NO, PROCEDE
HRRZS T1 ;GET CPU NUMBER IF CHANGING POLICY
SKIPL MOFLPG## ;CHANGING POLICY OR SETTING MEMORY OFF-LINE?
MOVE T1,BOOTCP## ;SETTING MEMORY OFF-LINE
CAME T1,.CPCPN## ;ARE WE THE ONE THAT WANTS TO KEEP RUNNING?
JRST CP1MFL## ;NO, GO STICK OUR HEAD IN THE SAND
>
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,-1-MXSECN ;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 #
SKIPN .CPTMF## ;DID CLOCK TICK?
JRST NOTACL ;NOT APR CLOCK
SIGNAL C$APRC ;YES, SIGNAL APR CLOCK
JFCL ;NO TICK OR NOT ENABLED
NOTACL: PUSHJ P,TIMEX ;READ THE TIME (NEEDED FOR OVERHEAD CALCULATION)
MOVE P1,T1 ;SAVE IT FOR POSSIBLE ACCOUNTING
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
>;END IFN FTEMRT
JUMPE J,CIP2
LDB T3,JBYLTM## ;GET JOB'S TIME LIMIT
SOSL .CPQNT## ;QUANTUM TIME MAY HAVE EXPIRED?
JUMPE T3,INCTM4 ;NO LIMIT, CONTINUE
PUSHJ P,CPUTP1 ;UPDATE CPU USAGE (SETUP P2 WITH INCREMENTAL TIME)
LDB T3,JBYLTM## ;GET JOB'S TIME LIMIT AGAIN
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
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,DOINT1## ;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
>
;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
JFCL ;ALLOW FOR BRAIN DAMAGED ROUTINES
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:
IFN FTMP,<
PUSHJ P,DSKTIC## ;PROCESS DISK QUEUED I/O
PUSHJ P,TAPTIC## ;PROCESS TAPE QUEUED I/O
IFN FTKL10,<PUSHJ P,KNITIC##> ;PROCESS KLNI QUEUED I/O
>; END IFN FTMP
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
PUSHJ P,SETSJ0## ;SET SP.SJx SO JOB IN .CPJOB DOESN'T BECOME
;RUNNABLE BEFORE WE GET TO SAVUAC AND FRIENDS
;SHOULD THIS TRIP THRU NXTJOB UNLOCK THE
;SCHEDULER TO WANDER THRU THE SWAPPER (CKJB6)
>
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 [CAME J,.CPJOB## ;IF NEW JOB NOT THE OLD JOB,
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
PUSHJ P,SETSJ0## ;MAKE SURE JOB IN .CPJOB DOESN'T RUN
;ELSEWHERE IF NXTJOB UNLOCKS THE SCHEDULER
;TO SERVICE THE SWAPPER(SCHED1-CKJB6)
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,REDOMP ;WAS HIGH SEGMENT MOVED BY LOCK UUO?
PUSHJ P,SETRL1## ;AND MAKE PAGE MAP REFLECT THE MOVE.
JUMPE J,CIP7 ;ALWAYS DO CPUTIM IF NULL JOB (KEEP NULL TIME RIGHT)
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
MOVE T1,.CPJOB## ;CALL IT SAME AS 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
;HERE TO CHARGE OLD JOB FOR RESOURCE USAGE (CPU TIME, KCS, ETC.)
CIP7: EXCH U,J ;CPUTIM NEEDS OLD JOB NUMBER IN J
PUSHJ P,CPUTP1 ;DO ACCOUNTING FOR OLD JOB
EXCH U,J ;NEW JOB NUMBER BACK TO J
CAMN U,.CPJOB## ;SAME AS LAST JOB?
JUMPE J,CIPXIT ;DONE IF JUST TRYING TO KEEP NULL TIME CORRECT
LDB T1,PDYQNT## ;QUANTUM RUN TIME LEFT
MOVEM T1,.CPQNT## ;MUST CALL CPUTIM WHEN EXPIRES
;RESTORE SOFTWARE STATE OF NEW JOB,THEN HARDWARE STATE
NULJOB:: ;TRANSFER HERE FROM SYSINI WITH J=0 AND .CPJOB=0
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
MOVSI T2,-CDBPGS## ;SET UP AOBJN
MOVEM T1,.USCDB(T2) ;SALT AWAY MAPPING
ADD T1,[XWD 1,0] ;BUMP SPT INDEX
AOBJN T2,.-2 ;LOOP FOR ALL PAGES
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 FTDECNET,<
IFN FTXMON,<PUSHJ P,DCNJIF##> ;CALL DECNET
IFE FTXMON,<DNCALL DCNJIF##> ;CALL DECNET
> ;END IFN FTDECNET
IFN FTSCA,<
PUSHJ P,SC.TIC## ;DO SCS ONCE PER TICK PROCESSING
PUSHJ P,PPDTIC## ;DITTO FOR THE KLIPA
>; END IFN FTSCA
SKPCPU (0) ;ON THE BOOT CPU?
JRST CIPXT1 ;NO
;ADD CALLS TO ONCE A TIC ROUTINES THAT HAVE TO BE RUN ON THE BOOT CPU HERE
SKIPE CLPTOP## ;NEED TO ALLOCATE PAGES AT CLOCK LEVEL?
PUSHJ P,CRECLP## ;YES, GO WORK ON IT
IFN FTSCA,<
PUSHJ P,SCSCLK## ;DO ONCE PER TIC SCS PROCESSING
>; END IFN FTSCA
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?
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
MOVE T1,JBTSTS##(J) ;JOB HAVE NON-BLOCKING TTY I/O PENDING?
TRNE T1,JS.NTO ;?
JRST CIP9 ;YES, CONTINUE
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 JOB HAS NON-BLOCKING TTY I/O PENDING AND WE WOULD HAVE GONE TO USER MODE
CIP9: DMOVE T2,.CPPC## ;GET PC USER NEEDS TO BE RESTARTED AT
DMOVEM T2,.JDAT+JOBPDL##+1 ;SET UP
MOVE T2,[IC.UOU+USRXNX##]
PUTPC T2,.CPPC##
MOVE P,[MJOBPD##+2,,.JDAT+JOBPDL##+2] ;SET UP EXEC STACK POINTER
XJEN .CPPC## ;..
;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
IFN FTENET,<PUSHJ P,KNIRMV##> ;TELL KLNI WE ARE GOING AWAY
IFN FTSCA,< PUSHJ P,PPDRMV##> ;TELL KLIPA WE ARE GOING AWAY
MOVE T1,.CPRUN## ;RUNNABILITY BITS
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##] ;NOW 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
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
;SUBROUTINE TO CHECK IF THE CLOCK QUEUE HAS ROOM FOR MORE ENTRIES.
;CALL:
; PUSHJ P,SKPCLQ
; <RETURN HERE IF QUEUE FULL>
; <RETURN HERE IF ROOM IN QUEUE>
;NOTE: OBVIOUSLY YOU MUST HAVE THE APPROPRIATE INTERLOCK WHEN
;CALLING THIS ROUTINE IF YOU EXPECT THE ANSWER TO REMAIN VALID.
SKPCLQ::PUSH P,T1 ;SAVE AN AC
HRRZ T1,CIPWT## ;GET POINTER INTO QUEUE
CAIL T1,CIPWTE## ;PAST END?
JRST TPOPJ## ;YES, NON-SKIP RETURN
JRST TPOPJ1## ;NO, SKIP 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.
;SUBROUTIME CPUTIM TO DO 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.
;CLOBBERS (RETURNS) P1, P2
CPUTP1: SKIPA T1,P1 ;GET VALUE PREVIOUSLY READ
CPUTIM: PUSHJ P,TIMEX ;GET TIME IN T1
IFE FTEMRT,<
SKIPN P1,T1 ;TEST FOR 0 (& SAVE TIME IN P1)
POPJ P, ;NO TIME RETURN
>;END IFE FTEMRT
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
;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
POPJ P, ;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
>
POPJ P, ;NOW GO SCHEDULE
;INCREMENT JOB'S RUNTIME
INCTIM: SKIPE JBTADR##(J)
PUSHJ P,FNDPDB## ;GET ADDRESS OF PDB
POPJ P, ;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
POPJ P, ;NOT PAST JIFFY SO DON'T INCREMENT TOTALS
;NOW P1 / NUMBER JIFFIES BY WHICH JOB'S RUN TIME
;HAS INCREASED SINCE THE LAST TIME IT WAS STOPPED. (NORMALLY THE
;INCREASE IN JIFFIES WILL BE 0 OR 1, BUT IT MIGHT POSSIBLY BE MORE.)
;NOTE: JOB 0 TIME IS NULL JOB TIME FOR ALL PROCESSORS IN A
;MULTIPROCESSOR SYSTEM.
ADDM P1,.PDRTM##(W) ;INCREMENTAL RUN TIME
ADDM P1,.PDTTM##(W) ;TOTAL RUN TIME
HRRZ T2,JBTPDB##+0 ;GET NULL JOBS PDB
ADDM P1,.PDTTM##(T2) ;ACCUMULATE SOLD 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
MOVEM T2,.CPQNT## ;SO WE DON'T GET CALLED SO OFTEN
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
POPJ P, ;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
POPJ P, ;ACCOUNTING DONE
;SUBROUTINE TO UPDATE CPU TIME FOR THE JOB WHOSE JOB NUMBER IS IN J
;CALL:
; MOVEI J,JOB NUMBER TO UPDATE CPU TIME FOR
; PUSHJ P,UDCPUT ;UPDATE CPU TIME
; ALWAYS RETURNS HERE
UDCPUT::PUSHJ P,SAVE2## ;CPUTIM CLOBBERS P1, P2
PUSHJ P,SAVJW## ;CPUTIM MAY CHANGE W
CAMN J,.CPJOB## ;ALWAYS UPDATE FOR CURRENT JOB WHICH IS ALREADY
PJRST CPUTIM ; ADDRESSABLE
IFN FTMP,<
PUSHJ P,ANYRUN## ;CURRENTLY RUNNING ON SOME OTHER CPU?
CAIA ;YES, MUST UPDATE CPU TIME NOW
>;END IFN FTMP
POPJ P, ;SINGLE CPU SYSTEM OR NOT RUNNING ANYWHERE,
; CPU TIMES ARE CURRENT
IFN FTMP,<
PUSHJ P,UUOLVL## ;CALLED AT UUO LEVEL?
PJRST UDCPT1 ;NO, DON'T NEED HACKERY TO CALL SVEUB
HRRZ T1,.CPNPD## ;YES, POINT TO BASE OF THIS CPU'S NULL PDL
MOVEM P,(T1) ;SAVE UUO LEVEL STACK POINTER
MOVE P,.CPNPD## ;USE THIS CPU'S NULL PUSH DOWN LIST SO
; CAN CHANGE THE UBR. THIS DEPENDS ON NOT
; RESCHEDULING IN EXEC MODE
PUSHJ P,UDCPT1 ;UPDATE CPU TIME
HRRZ T1,.CPNPD## ;ADDRESS OF UUO LEVEL STACK POINTER
MOVE P,(T1) ;RESTORE UUO LEVEL STACK POINTER
POPJ P, ;AND RETURN
UDCPT1: PUSHJ P,SVEUB## ;SO CAN WRITE THE METERS BACK TO THIS JOB'S MAP
PJRST CPUTIM ;UPDATE CPU TIME AND RETURN
> ;END IFN FTMP
;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##
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
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,<
PUSHJ P,DCNSEC## ;CALL DECNET
>
PUSHJ P,TAPSEC## ;CALL TAPSER
IFN FTKL10,<
PUSHJ P,D78SEC## ;CHECK DAS78'S
>;END OF IFN FTKL10
PUSHJ P,DSKSEC## ;CHECK FOR HUNG DISK DDBS
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.
> ;END IFN FTMP
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
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 FTKL10,<
PUSHJ P,MOSMIN## ;CLEAR MOS ERROR TIMER
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
IFN FTKS10,<
PUSHJ P,KSMIN## ;DO ONCE/MINUTE KS MEMORY CHECKS
>; END IFN FTKS10
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 FTKL10,<
PUSHJ P,D78MIN## ;CHECK DAS78'S
>;END OF IFN FTKL10
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
JUMPL T1,NOKSYS ;JUMP IF NO KSYS PENDING
PUSHJ P,PSIKSY## ;TELL EVERYONE
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##
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::PUSH P,T2 ;SAVE NEW SLEEP TIME FOR LATER
HLRZ T4,T2 ;COPY POST ROUTINE ADDRESS
CLKLOK ;INTERLOCK QUEUE
PUSHJ P,CLKFND
JRST [CLKNLK ;UNLOCK CLOCK
JRST TPOPJ##] ;RETURN
POP P,T3 ;RESTORE SLEEP TIME
HRRM T3,(T2) ; ..
MOVSI T3,(1B4) ; ..
ANDCAM T3,1(T2) ; ..
SETOM CLKNEW## ; ..
CLKNLK
CAIE T4,CTXWKJ## ;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
;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,TICSEC## ;TICKS PER SECOND
HRLI T2,CLKCMD ;ROUTINE TO CALL
SYSPIF
IDPB T2,CLOCK
IDPB T1,CLOCK
SETOM CLKNEW## ;NEW ENTRY IN QUEUE
PJRST ONPOPJ## ;RESTORE PI AND RETURN
;HERE TO FIND A CLOCK REQUEST FOR A JOB. RETURNS WITH T2 POINTING
;AT THE INTERLOCK. MUST BE CALLED WITH THE CLOCK INTERLOCK
;ON ENTRY T1 CONTAINS JCH FOR THE JOB LOOKED FOR AND T4 THE POST ADDRESS
;ON SUCCESS EXIT, T2 POINTS TO THE 1ST WORD OF THE APPROPRIATE REQUEST
CLKFND: SYSPIF ;MAKE SURE GET THE RIGHT PARITY OF ENTRY
HRRZ T2,CLOCK ;GET RH OF CLOCK QUEUE POINTER
SYSPIN
CLKFD1: CAIG T2,CIPWTM## ;AT TOP OF QUEUE?
POPJ P, ;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,CLKFD2 ;NO. LOOK AT NEXT ONE.
HRRZ T3,(T2) ;GET DATA ITEM
CAIN T3,0(T1) ;NOW. DOES THAT EQUAL DESIRED JOB NO?
SOJA T2,CPOPJ1## ;POINT TO FIRST WORD
SOS T2 ;ENTRIES ARE TWO WORDS LONG
CLKFD2: SOJA T2,CLKFD1
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:: 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
MOVSI T1,JNA+JACCT ;CLEAR JOB NUMBER ASSIGNED AND LOGGED IN BITS
ANDCAM T1,JBTSTS##(J)
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::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
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
>
HRRZS JBTCCC##(J) ;CLEAR CONTROL-C COUNT
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,DOINT1## ;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
SKIPN .CPISF## ;RUNNING SCHEDULER AT UUO LEVEL?
CONSZ PI,PI.IPA ;NOT LOGGED IN - KILL JOB IF NOT ON CHAN 7
JRST STOP1C ;AT CHANNEL 7
JRST JOBKL## ;CLEAR JNA
;ROUTINE TO STOP ANY JOB FROM BEING SCHEDULED
;CALL:
; MOVE J, JOB NUMBER
; PUSHJ P, STOP1
; EXIT ;RETURN HERE IMMEDIATELY, IF CALLED FROM HIGHER
;PRIORITY PI CHANNEL THAN CLK(LOWEST), OTHERWISE WHEN JOB IS RUNABLE
;CALLED FROM COMMAND DECODER WHEN <CONTROL>C TYPED IN BY USER
;OR ON ANY ERROR MESSAGE(SEE PREVIOUS PAGE)
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
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?
JRST STOP1H ;NO
PUSHJ P,TICAVL## ;ANY CHARACTERS TO BE INPUT?
TDZA T2,[IOW,,IOACT] ;PRESERVE ONLY I/O BITS
JRST STOP1M ;SET STATUS TO "TI"
ANDCAM T2,DEVIOS(F) ;PREVENT TI HANGS
STOP1H: TDZA T2,T2 ;NO, ZERO STATUS
STOP1M: 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
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,LGONAM## ;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 DECREASE # OF USERS WHO DON'T WANT THIS JOB TO ^C OUT
;AND CHECK VALUE
DECCCC::PUSH P,T1 ;SAVE AC
MOVSI T1,1
ADDB T1,JBTCCC##(J) ;INCREMENT
JUMPL T1,TPOPJ## ;IF STILL NEGATIVE, OK
TLNE T1,-1 ;OR IF ZERO, OK
STOPCD DECCC1,DEBUG,CCW, ;++CONTROL-C COUNT WRONG
JRST TPOPJ## ;RETURN
DECCC1: HRRZS JBTCCC##(J) ;FIX COUNT
JRST TPOPJ## ;RETURN
;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::SKIPGE JBTCCC##(J) ;SOMEONE WANT HIM STUCK?
AOSA (P) ;YES, NEVER LET HIM GO
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: 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,FLMCOM ;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,MXSECN
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,-1-MXSECN
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:: CAIG J,JOBMAX## ;TOO HIGH?
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
/
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
PUSHJ P,SETSTX ;WAIT
CLKLOK ;HERE ON RETURN, KILL ANY DANGLING CLOCK REQS
MOVE T1,.CPJCH## ;JCH
MOVEI T4,CTXWKJ## ;ROUTINE ADDRESS
PUSHJ P,CLKFND ;IS THERE ONE?
JRST SETHB4 ;NO, JUST RETURN (AOS'D EARLIER)
SYSPIF ;LOCK OUT CHANGES
MOVE T1,@CLOCK ;MOVE LAST ENTRY TO THIS SLOT
MOVEM T1,1(T2)
SOS CLOCK
MOVE T1,@CLOCK
MOVEM T1,(T2)
SOS CLOCK ;DECREMENT
SYSPIN
SETHB4: CLKNLK ;UNLOCK CLOCK QUEUE
POPJ P,
;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
UERRPT::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: DMOVEM 16,.JDAT+JOBD16## ;SAVE AC16 AND 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
; CAMN 17,USRTAB##-MQ(16) ;ALREADY OWN RESOURCE?
; STOPCD .,STOP,AOWNSR, ;++ALREADY OWN SHARABLE RESOURCE
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
REPEAT 0,<
SKIPE DINITF## ;ONCE ONLY?
JRST SRFRE0 ;YES
PUSH P,T2 ;SAVE AN AC
MOVE T2,USRTAB##(T1) ;GET RESOURCE OWNER
CAME T2,.CPJOB## ;GIVING UP THE RESOURCE I OWN?
STOPCD .,STOP,DOWNSR, ;++DON'T OWN SHARABLE RESOURCE
POP P,T2 ;RESTORE T2
SRFRE0:
> ;END REPEAT 0
HRLZS USRTAB##(T1) ;XWD LAST USER, 0 (NO CURRENT USER)
SOSL REQTAB##(T1) ;DECREMENT REQUEST COUNT. ANY JOBS WAITING?
SETOM AVALTB##(T1) ;YES, FLAG AS AVAILABLE 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?
HRROS SCDRTF## ;SEMI-PREEMPTIVE RESCHEDULE
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
TDNE T1,.PDDFL##(W) ;HAVE WE COUNTED DOWN YET?
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
LDB T1,PJOBN## ;GET JOB # AGAIN
SYSPIF ;TURN OFF PI'S
SKIPN SCDRTF## ;ANY REAL TIME RESCHEDULE TO DO?
MOVNM T1,SCDRTF## ;SET AS HPQ JOB FORCING RESCHEDULE
SETOM .CPCKF## ;DOING A CH7 INTERRUPT
SYSPIN (CLKBIT##+PI.IIO)
>;END IFN FTHPQ
SETID1: LDB T1,PJOBN## ;GET JOB NUMBER
PUSHJ P,PSIIOD## ;CALL PSISER TO CHECK FOR TRAPS
IFE FTMPXSER,<
TLZN S,IOW ;IN I/O WAIT?
>
IFN FTMPXSER,<
TLZE S,IOW ;IN I/O WAIT?
JRST SETID2 ;YES
PUSHJ P,MPXIOD## ;MAYBE - ASK MPXSER
>
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 FTMPXSER,<
PUSH P,T1 ;NEED A SPARE AC
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIN T1,.TYMPX ;AN MPX CHANNEL?
PJRST MPXWAI## ;YES, SPECIAL MPXSER CODE THEN
POP P,T1 ;NO, NORMAL DEVICE HANDLING
WAIT1M::
> ;END IFN FTMPXSER
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
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