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: 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, ;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, ;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, ;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,[B2!PM.PUB!PM.SPY!,>] 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, ;CALL DECNET IFE FTXMON, ;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, IFN FTKS10, ANDCAM T1,.USUPF ;DON'T CAUSE REFILLS IFN FTKL10, IFN FTKS10, 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, ;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, ;SAVE PROTOCAL IFN FTKS10, ;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, ;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 ;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 ;YES DO NOT LOOK AT MEMORY MOVE T1,.CPDBM## EXCTXU ;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 ;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 ;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 ; ; ;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 ;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 ;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 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 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 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 ;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, ; 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 , IFIDN , 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 , ;;STOP IFIDN , ;;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, ; PUSHJ P,SAVCTS ; ; ; ;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,) 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, ; MOVE J, ; 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, ; 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 ;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 ;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'\, IFNB \'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