Trailing-Edge
-
PDP-10 Archives
-
dec-10-omona-u-mc9
-
cp1ser.mac
There are 2 other files named cp1ser.mac in the archive. Click here to see a list.
TITLE CP1SER - SECOND PROCESSOR CONTROL V141
SUBTTL M. CHURCH - LNS/MIT P. HURLEY - DEC 08 MAR 77
SEARCH F,S
IFN FTKL10,<
SEARCH DTEPRM ;IF KL10, SEARCH DTE SYMBOLS
>
$RELOC
$HIGH
;***COPYRIGHT 1973,1974,1975,1976,1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.***
XP VCP1SR,141 ;VERSION NUMBER FOR LOADER STORAGE MAP
CP1SER: ENTRY CP1SER ;LOAD IF SPECIFIED BY COMMON
EXTERNAL JOBMAX,SYSDSP,.CPUFC,UFC0,TWOREG
EXTERNAL COMERR,JBTPRV,STOTAC,.C0CDB,.CPCDB,.CPPHY,.CPRUN
EXTERNAL CPOPJ,INLMES,NXMMES,OPRLDB,PDLMES
EXTERNAL TTYFNU
EXTERNAL CONMES,CPOPJ1
;LOW PRIORITY CLOCK ROUTINE FOR SECOND PROCESSOR
INTERNAL CK1INT
EXTERNAL .C1CKF,.C1S17,CK1CHL,.C1SCF,.C1ADR,.C1NJD,.C1NPD,.CPAEF,NU1DAT,RSCHED
EXTERNAL JOBD16,JOBD15,JOBDAC,JBTSPS,JBTSTS
EXTERNAL JOBD17
EXTERNAL JBTDAT
CK1INT: SKIPN .C1CKF ;CK1 INTERRUPT REQUEST?
JRST CK1INT ;NO, CHECK OTHER DEVICES
IFN FTKI10!FTKL10,<
CONO PI,II.CCI## ;KI10, CLEAR SOFTWARE REQUESTED INTERRUPT
>
IFN FTKL10,<
DATAI PAG,SVPG17 ;SAVE CURRENT AC STATUS
EXECAC ;SWITCH TO EXEC AC BLOCK
>
MOVEM 17,.C1S17 ;SAVE AC 17
JSR CT1CLK ;CK FOR CTY CHAR.
MOVE 17,CK1CHL ;IS CURRENT JOB IN USER MODE?
TLNN 17,(XC.USR) ;PC IN USER MODE?
SKIPE .C1SCF ;NO, IS THIS A FORSCED RESCHEDULING INTERRUPT?
JRSTF @[XWD XC.UOU##,SAVPC1] ;YES, IT IS OK TO RESCHEDULE NOW
MOVE 17,.C1S17 ;NO, LEAVE TIMEF SET AND DISMISS INT.
IFN FTKL10,<
DATAO PAG,SVPG17 ;RESTORE AC SET
>
JEN @CK1CHL ;DISMISS
SAVPC1: MOVEM 17,.C1PC ;SAVE PC IN PROTECTED PART OF SYSTEM DATA
; STORAGE FOR CURRENT JOB
IFN FTKI10!FTKL10,<
TLNE 17,(XC.USR) ;PC IN USER MODE?
JRST CK1SPD ;PC IN USER MODE, DON'T NEED TO SAVE ACS
; SINCE IT WILL BE DONE AT CONTEXT SWITCH
>
SKIPN 17,.C1ADR ;CURRENT JOB DATA AREA, IS THERE ONE?
MOVE 17,.C1NJD ;NO, MUST BE NULL JOB OR CORE 0
; RUNS AT UUO LEVEL,REQUESTS CK1 INT. TO STOP
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,.C1S17 ;NOW SAVE 17 IN JOB DATA AREA
MOVEM T1,JOBD17(17) ;ALONG WITH OTHER ACS
CK1SPD::MOVE P,.C1NPD ;SET UP PUSH DOWN LIST IN NULL JOB DATA
; AREA IN LOWER CORE
MOVEI P4,.C1CDB ;GET CDB OFFSET FOR THIS PROCESSOR
MOVE S,.C1AEF## ;IT THIS AN ERROR INTERRUPT?
JUMPE S,RSCHED ;NON-ZERO IF YES
PUSHJ P,AP1ERR ;YES, GO PROCESS ERROR,APRILM WILL CLEAR .CPAEF
; FLAG IMMEDIATELY
JRST RSCHED ;NOT PDL OV - RESCHEDULE
;CALL SCHEDULER TO GET NEXT JOB FOR SLAVE
;SCHEDULER IS PURE EXCEPT FOR ENTRY AND DISMISSING
;SCHEDULER WILL RETURN HERE TO START THE NEXT JOB ON THE SLAVE
INTERNAL SCIP8A
EXTERNAL CURJOB
SCIP8A: HRLM J,CURJOB ;DISPLAY JOB NUMBER IN LOW CORE
IFN FTKI10!FTKL10,<
MOVE T1,.C1PC ;GET THE PC
TLNE T1,(XC.USR) ;IS THE PC IN USER MODE?
IFN FTKI10,<
JEN @.C1PC ;PC IN USER MODE, USER ACS ARE ALREADY SETUP
>
IFN FTKL10,<
JRST [USERAC ;SETUP USER AC BLOCK
JEN @.C1PC] ;GO TO THE USERS
>
>
MOVSI 17,JOBDAC(R) ;RESTORE DUMP ACS FROM REL.20 IN JOBDATA
BLT 17,17
JEN @.C1PC ;DISMISS
IFN FTKL10,<
$LOW
SVPG17: 0 ;SAVE CONTENTS OF PAG HERE
$HIGH
>
;HERE ON UUO FROM USER ON SECOND PROCESSOR.
;USER AC17 SAVED IN LOC USRSAV+OFFSET
EXTERNAL MJOBPD,JOBPDL,JOBAC
EXTERNAL SPTRAP,.C1SAV,JOBDAC,UUOSP0,MPUUO
EXTERNAL .C0SCN,.C1CDB,.C1PC,.C1JOB,.C1LJU,.C1PUC,.C1QUE,.C1SCN
INTERNAL UUOUSP
UUOUSP: PUSH P,UUOSP0 ;SAVE RETURN ON PD LIST
MOVE M,SPTRAP ;GET CONTENTS OF 140 INTO AC M
IFN FTKA10,<
MOVEI P4,.C1CDB## ;POINT TO CPU1'S CDB
>
LDB T1,[POINT 9,M,8];GET THE UUO OP CODE
ROT T1,-1 ;DIVIDE BY 2, SAVE REMAINDER IN BIT 0
MOVE T2,CHKTAB##-20(T1)
UUOUS1: SKIPL T1 ;ODD OR EVEN OPCODE?
MOVSS T2 ;EVEN, SWAP HALVES
TRNN T2,UU.CP1 ;CAN THIS UUO BE EXECUTED ON CPU1?
JRST UUOUS2 ;CAN'T BE EXECUTED ON CPU1
ROT T1,1 ;RESTORE ORIGIONAL OPCODE
CAIE T1,<CALLI>B62 ;THIS DEPENDS ON CALLI 47 BEING
; EXECUTABLE ON CPU1
JRST SMUUO2 ;CAN BE BUT NOT A CALLI
HRRE T1,M ;CALLI NUMBER (NEGATIVE IF CUSTOMER DEFINED)
TRNN T1,400000 ;POSITIVE CALLI NUMBER?
TRZA T1,UPHNLY ;YES, CLEAR PHYSICAL ONLY BIT
TRO T1,UPHNLY ;NEGATIVE, MAKE SURE TRUE NEGATIVE INDEX
CAML T1,MCCLEN## ;LESS THAN THE MAXIMUM CUSTOMER DEFINED CALLI?
CAIL T1,UCILEN## ;OR GREATER THAN THE MAXIMUM DIGITAL DEFINED CALLI
JRST USPRET## ;YES, POPJ NOP
ROT T1,-1 ;DIVIDE BY 2 AGAIN
MOVE T2,CHKTBC##(T1) ;GET CALLI CHECK BITS
JRST UUOUS1 ;SEE IF THE CALLI CAN BE EXECUTED ON CPU1
;HERE TO RESCHEDULE JOB ON MP (MASTER PROCESSOR) WHEN CANNOT DO UUO ON SP
UUOUS2: MOVEM P,JOBDAC+P(R) ;SAVE P
MOVEM R,JOBDAC+R(R) ;SAVE PROG
MOVEM M,JOBDAC+M(R) ;ALL NECESSARY AC'S HAVE BEEN SAVED
MOVE T1,[XWD XC.UOU##,SMUUO1] ;GET START ADR ON MASTER
;HERE TO RESCHEDULE JOB ON THE MASTER WHEN A UUO CANNOT COMPLETE ON SP
UUOUS3: MOVE J,.C1JOB ;CURRENT CPU1 JOB NUMBER
HRL J,.C1QUE ;SAVE THE QUE CODE FOR THIS JOB ALSO
MOVEM J,.C1LJU ;SAVE LAST JOB WHICH DID A UUO
AOS .C1PUC ;MARK THAT A UUO MUST BE DONE BY MASTER
UUOUS4: MOVSI T2,(SP.NR1) ;MAKE UNRUNNABLE ON SLAVE
IORM T2,JBTSPS(J) ;BY LIGHTING UNRUNNABLE(SLAVE) BIT
UUOUS5: MOVEM T1,.C1PC## ;STORE THE PC
JRST CK1SPD ;THEN GO RESCHEDULE
;HERE AFTER RESCHEDULED ON MASTER CPU
SMUUO1: MOVE T1,(P) ;PC STORED BY UUO TRAP (ON CPU1)
MOVEM T1,UUO0## ;STORE AS IF UUO TRAP HAPPENED ON CPU0
; (ONLY NEEDED IN CASE ANY CALL TO UUOERR)
MOVEM M,MPTRAP##
MOVEI P4,.C0CDB##
SMUUO2: MOVE J,.CPJOB##(P4) ;UUOERR CALLS GIVRES, WHICH NEEDS J
MOVEI F,0 ;ALSO F DOES NOT POINT TO ADDB
TLNE M,740000 ;TO MONITOR UUO (40-77)?
JRST MPUUO ;YES, GO DO UUO
JRST UUOERR## ;NO, PRINT ERROR (CHECK OCCURS BEFORE
; STUFF IS PUT ON PD LIST WHICH OBSCURES LAST POPJS
;SUBROUTINE TO INSURE JOB IS ON CPU0
;CALLING SEQUENCE:
; PUSHJ P,ONCP0S
;RETURNS CPOPJ IF ALREADY ON CPU0, CPOPJ1 IF
; RESCHEDULING WAS REQUIRED TO GET THERE
ONCP0S::SKPCPU (1) ;ALREADY ON CPU0?
POPJ P, ;YES, NON-SKIP RETURN
AOS (P) ;SKIP RETURN
;FALL INTO ONCPU0
;SUBROUTINE TO INSURE THAT A JOB IS ON CPU0
;CALLING SEQUENCE:
; PUSHJ P,ONCPU0
;ALWAYS RETURNS CPOPS ON CPU0
ONCPU0::SKPCPU (1) ;ALREADY ON CPU0?
POPJ P, ;YES, JUST RETURN
PUSH P,UUOSP0## ;ON CPU1, SAVE CPU1 MUUO
MOVEM 17,JOBD17##(R) ;SAVE AC17
MOVEI 17,JOBDAC##(R) ;SAVE ACS 0-16
BLT 17,JOBD16##(R) ; IN THE JOB DATA AREA
JSP T1,UUOUS3 ;CAUSE THE JOB TO BE RESCHEDULED ONTO CPU0
;RETURN HERE ON CPU0
POP P,UUO0 ;RESTORE MUUO PC WHERE CPU0 EXPECTS IT
POPJ P, ;RETURN TO THE CALLER ON CPU0
;CODE CALLED FROM USRXIT TO SEE IF MUST RESCHEDULE
EXTERNAL USCHED,JBTSPS,.C0JOB
INTERNAL UXITMP
UXITMP: MOVEI T1,SP.CR0 ;TEST IF USER CAN RUN ON MASTER
TDNE T1,JBTSPS(J)
AOS (P) ;YES HE CAN, SKIP RETURN
POPJ P, ;AND RETURN
;HERE TO EXIT FROM A UUO WHICH WAS EXECUTED ON CPU1
USPXIT::MOVE J,.C1JOB## ;CURRENT CPU1 JOB NUMBER
MOVE T2,[XWD STOPIO!CNTRLC,JS.DEP!JS.MPE]
TDNN T2,JBTSTS##(J) ;SHOULD THE JOB BE STOPPED? (USER TYPED
; CONTROL C DURING THE UUO, MEMORY PARITY
; ERROR IN UUO ARGUMENT LIST, DAEMON ERROR
; PAUSE, OR TRYING TO STOP I/O)
SKIPE .C1TMF## ;CLOCK TICK DURING UUO PROCESSING?
SKIPA T1,[XWD XC.UOU##,UUODON##]
JRST USRRET## ;CONTINUE WITH CURRENT USER
MOVEM R,JOBDAC##+R(R) ;SAVE PROTECTION,,RELOCATION
MOVEM J,JOBDAC##+J(R) ;SAVE CURRENT JOB NUMBER
MOVEM P,JOBDAC##+P(R) ;SAVE PUSH DOWN LIST POINTER
TDNN T2,JBTSTS##(J) ;MUST THE JOB BE RUN ONLY ON CPU0?
JRST UUOUS4 ;YES, MAKE IT UNRUNNABLE ON CPU1
JRST UUOUS5 ;NO, CLOCK JUST TICKED (CALL SCHEDULAR)
; LEAVING THIS JOB RUNNABLE ON CPU1
;MTSUUO MAKES A JOB DOING A UUO STAY ON THE MASTER CPU FOR THE
; DURATION OF THE UUO. SP.NR1 GETS CLEARED AT USRXIT.
INTERNAL MSTUUO
MSTUUO: MOVE J,.C0JOB ;GET JOB NUMBER ON CPU0
;SUBROUTINE TO MAKE SURE JOB CAN GET SCHED ON CPU0 FOR APR ERROR MESSAGE
; NEEDED IN CASE JOB IS SET TO RUN ON CPU1 ONLY
CP1APE::MOVSI T2,(SP.NR1) ;PREPARE TO SET NO RUN SLAVE BIT
IORM T2,JBTSPS(J) ;SET BIT
POPJ P, ;AND RETURN
;ROUTINE TO CHECK IF JOB CAN RUN ON EITHER OR BOTH CPUS
;CALL: MOVE J,JOB NUMBER
; PUSHJ P,SAVE4 ;P4 SAVED
; PUSHJ P,CHKCPU
; JOB IS SET TO RUN ONLY CPU1 - P4=CPU1CB
; JOB WAS SET TO RUN ON ALL CPUS OR JUST CPU0 - NOW SET TO CPU0 ONLY
; P4=CPU0CB
;CALLED BY TRPSET AND RTTRP
CHKCPU::MOVEI P4,.C1CDB## ;ASSUME JOB IS ON CPU1
MOVE T1,JBTSPS##(J) ;JOB CAN RUN BITS IN SECOND CPU STATUS
TRNN T1,SP.CR0 ;CAN JOB RUN ON CPU0
POPJ P, ;NO, RETURN ON CPU1 ONLY
MOVEI P4,.C0CDB## ;YES, RETURN CPU0 CDB ADR
MOVEI T1,SP.CR1 ;CLEAR CAN RUN ON CPU1
ANDCAM T1,JBTSPS(J) ;SO WILL ONLY RUN ON CPU0
JRST CPOPJ1 ;RETURN ON CPU0 ONLY
;SUBROUTINE TO CHECK IF TRPSET UUO IS ALLOWED ON DUAL SYSTEM
;CALL: MOVE J,JOB NUMBER
; PUSHJ P,CPUTRP
; CANNOT - ON CPU1 ONLY AND NOT LOCKED IN CORE
; OK - WAS ON BOTH CPUS OR JUST CPU0 - NOW ON CPU0 ONLY
IFN FTTRPSET,< ;TRPSET UUO FEATURE?
CPUTRP::PUSHJ P,CHKCPU ;IF JOB IS ON BOTH CPUS FORCE TO CPU0
IFN FTLOCK,< ;LOCK UUO FEATURE?
PUSHJ P,LOKCHK## ;JOB IS ONLY ON CPU1 - IS IT LOCKED IN CORE?
>
IFE FTLOCK,< ;LOCK UUO FEATURE?
POPJ P, ;JOB IS ONLY ON CPU1 - CANNOT BE LOCKED
>
JRST CPOPJ1## ;OK RETURN, JOB WAS ON CPU0 OR BOTH - NOW ONLY ON CPU0
; OR IS ON CPU1 ONLY AND LOCKED IN CORE
IFN FTLOCK,<
POPJ P, ;ERROR RETURN JOB IS ON CPU1 ONLY AND ISN'T LOCKED IN CORE
>
> ;END FTTRPSET FEATURE
;HERE FROM COMCON TO TEST IF JOB ON SLAVE, BEFORE DOING CONTROL C
INTERNAL SPSTOP
SPSTOP: PUSHJ P,LOKSCD ;TURN ON INTERLOCK
MOVSI T2,(SP.CC1) ;SET THE CONTROL C BIT SO SLAVE CANNOT RUN JOB
IORM T2,JBTSPS(J) ;AVOID SLAVE PICKING JOB UP BEFORE IT IS STOPPED
MOVSI T2,(SP.CJ1) ;TEST IF JOB IS CURRENT JOB ON SLAVE PROCESSOR
TDNN T2,JBTSPS(J)
AOS (P) ;NO, SKIP RETURN AND DONT DELAY COMMAND
JRST ULKSCD ;TURN OFF INTERLOCK
;HERE FROM COMCON, RUN UUO, AND TO CLEAR SP.NR1 AT END OF A UUO
INTERNAL DPXST
DPXST: MOVSI T1,(SP.NR1) ;CLEAR THE UNRUNNABLE BIT FOR SLAVE
ANDCAM T1,JBTSPS(J) ;JOB CAN NOW RUN ON SLAVE
POPJ P,
;HERE TO CLEAR MULTIPROCESSOR STATUS BITS
INTERNAL CLRJSP
CLRJSP: PUSH P,T1 ;SAVE A WORKING AC
MOVSI T1,(SP.NR1) ;MAKE JOB UNRUNNABLE ON SLAVE
IORM T1,JBTSPS(J)
HRLOI T1,(SP.NR1+SP.CJ0+SP.CJ1) ;CLEAR LEFT HALF OF ALL BUT TWO RUN BITS
ANDM T1,JBTSPS(J)
JRST TPOPJ## ;RESTORE T1 AND RETURN
;ROUTINE TO SET INITIAL CONDITIONS FOR CPU RUNNABILITY
;CALLED FROM CLOCK1 - CLRJBT
INTERN SETJSP
SETJSP: MOVEI T1,<SP.CR0+SP.CR1>B29+SP.CR0+SP.CR1 ;MAKE JOB RUNNABLE ON ALL CPU'S
MOVEM T1,JBTSPS(J)
POPJ P, ;AND RETURN
;ROUTINE TO CLEAR CONTROL C TYPED BIT
;CALLED FROM CLOCK1-WHEN JOB CAN BE STOPPED
INTERN CLRCCB
CLRCCB: MOVSI T1,(SP.CC1) ;THIS ROUTINE IS CALLED TO CLEAR SP.CC1 BIT
ANDCAM T1,JBTSPS(J) ;CONTROL C TYPED, SO DON'T RUN ON CPU1.
POPJ P, ;AND RETURN
;HERE FROM ANYDEV TO MAKE IT LOOK LIKE JOB HAS ACTIVE DEVICES
;IF JOB IS CURRENTLY BEING RUN ON THE SLAVE PROCESSOR
INTERNAL ANYRUN
ANYRUN: PUSHJ P,LOKSCD ;TURN ON INTERLOCK
IFN FTTRPSET,<
CAMN J,.C1STS ;ALSO LOOK LIKE ACTIVE DEV IF STOPTS ON SLAVE
JRST ULKSCD ;YES, GO ULKSCD AND POPJ RETURN
>
PUSH P,T2 ;SAVE AN AC
IFN FT2REL,< EXTERNAL JBTSGN
MOVE T2,.C1JOB ;GET SLAVE PROCESSOR JOB NUMBER
HRRZ T2,JBTSGN(T2) ;GET HIGH SEGMENT NUMBER FOR THAT JOB
CAIN T2,(J) ;IS THIS A HIGH SEGMENT RUNNING ON SLAVE?
JRST ANYRN1 ;YES, GIVE NO SHUFFLE RETURN
CAILE J,JOBMAX ;IS THIS A HIGH SEGMENT?
JRST ANYRN0 ;YES, DONT CHECK JBTSPS TABLE
>
MOVSI T2,(SP.CJ1)
TDNN T2,JBTSPS(J) ;TEST IF RUNNING ON SLAVE
ANYRN0: AOS -1(P) ;NOT RUNNING, GIVE SKIP RETURN
ANYRN1: POP P,T2 ;RESTORE WORKING AC
JRST ULKSCD ;GO ULKSCD AND POPJ RETURN
;HERE ON MASTER FROM CLOCK1 ONCE A MINUTE TO CHECK IF CPU1 IS RUNNING
;IF CPU1 IS NOT RUNNING, TYPE OUT APPROPRIATE MESSAGES TO OPERATOR
INTERNAL CP1CHK
CP1CHK: PUSHJ P,CPRMIN ;CHECK TO SEE IF ALL JOBS HAVE RUNNABLE SPECIFICATIONS
SKIPG .C1OK ;IS DUAL PROCESSOR OK?
POPJ P, ;YES, JUST RETURN
MOVEI T1,.C1CDB ;NO, FIND OUT IF CPU1 IS RUNNABLE
SKIPGE .CPRUN(T1) ;IS CPU1 RUNNABLE?
POPJ P, ;NO, NO MESSAGE
HRRZ U,OPRLDB ;YES, GET OPR TTY DDB
MOVEI T1,[ASCIZ/%
%Problem on CPU1
/]
JRST CONMES ;GO TYPE OUT MESSAGE
;THIS ROUTINE IS CALLED AT THE BEGINNING OF SCHED (NXTJOB)
;TO PUT SCAN TABLE ADDRESS INTO AC DAT. THE MASTER PROCESSOR
;IS MADE TO SCAN PQ1,PQ2,PQ3 WHILE THE SLAVE PROCESSOR IS MADE
;TO SCAN PQ3,PQ2,PQ1. IN ADDITION, THIS ROUTINE IS USED
;TO DETERMINE WHETHER TO DO REGULAR SCHEDULING AT THIS TIME
;OR TO RUN EITHER (1) A JOB WHICH HAS STOPPED TIME SHARING
;OR (2) A JOB WHICH WAS RUNNING ON THE SLAVE PROCESSOR THAT
;MUST DO A UUO (PROBABLY FOR I/O)
INTERNAL MSCHED,SSCHED
EXTERNAL SCHEDJ,.C0PUC,.C1PUC
MSCHED:
IFN FTTRPSET,<
SKIPE J,.C0STS## ;DID ANYONE STOP TIME SHARING?
JRST MRNBL1 ;YES, SEE IF HE IS RUNNABLE
>
SKIPE J,.C1PUC ;SLAVE PROCESSOR FLAG ON?
JRST MRNBL2 ;YES, GO SEE IF SLAVE JOB TO RUN
EXTERNAL SSCAN ;SSCAN DEFINED IN SCHED
MSCALL: SETZM .CPUFC(P4) ;CLEAR UUO FAIRNESS COUNT
PUSHJ P,SCHEDJ ;DISPATCH TO SCHED CODE
MSEL: MOVSI T1,(SP.CJ0) ;PICK UP RUN BIT FOR MASTER PROCESSOR
MOVE F,.C0JOB ;GET LAST JOB NUMBER
ANDCAM T1,JBTSPS(F) ;TURN OFF RUNBIT FOR OLD JOB
IORM T1,JBTSPS(J) ;TURN ON RUNBIT FOR NEW JOB
POPJ P, ;AND RETURN
;TEST IF JOB WHICH STOPPED T/S IS RUNNABLE
MRNBL1: MOVE T1,NRNMSK ;GET NON RUNNABLE MASK
TDNN T1,JBTSTS(J) ;IS JOB WAITING TO SHUFFLE,SWAP,EXPAND,LOCK,OR REQUE
PUSHJ P,MPRUN ;SECOND STATUS WORD BITS OK?
JRST MSNULL ;JOB UNRUNNABLE, GO RUN NULL JOB
JRST MSEL ;JOB RUNNABLE, GO TO IT
;TEST IF JOB WHICH NEEDS UUO IS RUNNABLE, AND CLEAR FLAG
EXTERNAL .C0QUE,QSCAN,SSCAN
MRNBL2: AOS T1,.CPUFC(P4) ;COUNT UP UUO FAIRNESS COUNT
CAILE T1,UFC0 ;IS IT GREATER THAN THE MAXIMUM?
JRST MSCALL ;YES, GO DO A NORMAL SCHEDULE
SKIPN J,.C1LJU ;WHAT WAS THE LAST JOB TO DO A UUO
JRST MRNBL3 ;THERE WASN'T1 ONE
SETZM .C1LJU ;ZERO FLAG SO WE DONT TRY TO USE IT TWICE
HLLZ T2,J ;GET THIS JOB'S QUEUE CODE
HRRZS J ;GUARANTEE THAT J IS ONLY JOB NUMBER
LDB T1,PJBSTS## ;T1=JOBS QUEUE CODE
JUMPN T1,MRNBL3 ;JUMP IF THE JOB IS NOT RUNNABLE NOW
; CAN HAPPEN IF MASTER RAN THE JOB BEFORE
; SLAVE SETUP .C1LJU
SKIPGE T1,JBTSTS(J) ;IS THIS JOB RUNNABLE
TLNE T1,SWP+SHF+JXPN+JRQ
JRST MRNBL3 ;NO, JOB IS NOT RUNNABLE
IFN FTKL10,<
PUSHJ P,CHKCSH ;IS JOB RUNNABLE W.R.T. CACHE?
; (ALWAYS IS SINCE CPU1 DOES SWEEP
; IF IT SEES JOB DID MASTER UUO,
; THIS CALL IS FOR SAFETY)
JRST .+2 ;SUCCESS RETURN, OK
JRST MRNBL3 ;SORRY, LOOK FOR OTHER UUO DOERS
>;END IFN FTKL10
IFN FTLOCK,<
TRNN T1,LOK> ;OR IS JOB TRYING TO LOCK?
PUSHJ P,MPRUN ;TEST SECOND STATUS WORD BITS
MRNBL3: SKIPA U,.C1SCN ;NOT RUNNABLE, CALL SCHEDULER WITH U SET UP
JRST MRNBL4 ;IS RUNNABLE, RUN IT NOW
JSP T1,QSCAN ;GO SCAN RUN QUEUES
JRST MRNBL5 ;NO RUNNABLE JOBS NOW (COULD HAPPEN IF SWAPPER DECIDES
; TO SWAP OUT JOB AFTER IT HAS DONE UUO ON CPU1
MOVE F,JBTSPS(J) ;GET STATUS BITS
TLNN F,(SP.NR1) ;DID THIS JOB DO A UUO (NOT RUNABLE ON CPU1)
JRST (T2) ;NO, CONTINUE SCANING
MOVE F,NRNMSK ;GET OTHER STATUS BITS
TDNN F,JBTSTS(J) ;JOB RUNNABLE?
PUSHJ P,MPRUN ;YES, MAYBE
JRST (T2) ;NO, CONTINUE SCANNING
IFN FTKL10,<
PUSHJ P,CHKCSH ;IS JOB RUNNABLE W.R.T. CACHE?
; (ALWAYS IS, SEE COMMENT AT PUSHJ
; TO CHKCSH ABOVE)
JRST MRNBL4 ;OK, HE WINS
JRST (T2) ;NOT OK, LOOK FOR NEXT JOB
>;END IFN FTKL10
MRNBL4: SOS .C1PUC ;YES, COUNT DOWN NUMBER OF UUO'S TO BE DONE
HLREM T2,.C0QUE ;SAVE THE QUEUE NUMBER FOR CPU0
JRST MSEL ;AND GO RUN IT
;SELECT NULL JOB BECAUSE JOB WHICH STOPPED TIME SHARING CANNOT RUN
MSNULL: SETZ J,
JRST MSEL
;HERE WHEN COULD NOT FIND A JOB WHICH HAD JUST DONE A CPU1 UUO AND IS STILL RUNABLE
MRNBL5: SOS .C1PUC ;COUNT DOWN UUO COUNTER TO AVOID OVERHEAD SCANNING
JRST MSCALL ;GO LOOK FOR ANY RUNNABLE JOB
;CALLED BY SLAVE PROCESSOR
SSCHED:
IFN FTTRPSET,<
SKIPE J,.C1STS## ;T/S STOPPED (TRPSET UUO)?
JRST SRNBL1 ;YES, SEE IF JOB IS RUNNABLE
>
SKIPE J,.C0PUC ;FLAG FROM MASTER PROCESSOR ON?
SETZM .C0PUC ;CLEAR MASTER PROCESSOR'S FLAG WORD
PUSHJ P,SCHEDJ ;DISPATCH TO SCHED CODE
SSEL: MOVSI T1,(SP.CJ1) ;GET SLAVE RUN BIT
MOVE F,.C1JOB ;GET LAST JOB NUMBER
ANDCAM T1,JBTSPS(F) ;CLEAR RUNBIT FOR LAST JOB
IORM T1,JBTSPS(J) ;SET RUNBIT FOR NEW JOB
POPJ P, ;AND RETURN
;TEST IF JOB WHICH STOPPED T/S IS RUNNABLE
SRNBL1: MOVE T1,NRNMSK ;GET NON RUNNABLE MASK
TDNN T1,JBTSTS(J)
PUSHJ P,SPRUN ;TEST JBTSPS BITS
MOVEI J,0 ;JOB UNRUNNABLE, RUN NULL JOB
JRST SSEL ;JOB RUNNABLE, GO RUN IT
IFN FTLOCK,<
NRNMSK: XWD SWP+SHF+JXPN+JRQ+WTMASK,LOK
>
IFE FTLOCK,<
NRNMSK: XWD SWP+SHF+JXPN+JRQ+WTMASK,0
>
;ROUTINE TO DETERMINE IF JOB IS RUNNABLE WITH RESPECT TO JBTSPS BITS
;CALLED FROM SCHED WHEN SCHED IS ENTERED BY EITHER PROCESSOR
INTERNAL DXRUN
DXRUN: SKPCPU (1) ;TEST WHICH PROCESSOR
JRST MPRUN ;WAS MASTER PROCESSOR
;WAS SLAVE, FALL INTO SPRUN
;ROUTINE CALLED WHEN SLAVE IS RUNNING SCHED, TO SEE
;IF JBTSPS BITS PERMIT JOB TO RUN ON SLAVE.
;SKIP RETURN IF JOB IS RUNNABLE.
SPRUN: SKIPGE .CPRUN##(P4) ;IS CPU RUNNABLE?
POPJ P, ;NO, TAKE CAN NOT RUN RETURN
MOVE F,JBTSPS(J) ;GET DUPLEX STATUS
TLNE F,(SP.NR0) ;DOES THIS JOB HAVE A UUO TO BE DONE ON SLAVE
JRST SPRUN1 ;YES, GO DO IT
TRNN F,SP.CR1 ;JOB OK TO RUN ON SLAVE
POPJ P, ;NO, TAKE NON-SKIP RETURN
SPRUN1: TLNE F,(SP.NR1+SP.CJ0+SP.CC1) ;RUNNING ON MASTER OR UNRUNNABLE ON SLAVE?
POPJ P, ;YES, GIVE CANNOT RUN THIS JOB RETURN
MOVEI F,JS.APE ;CHECK APR ERROR BIT
TDNE F,JBTSTS(J) ;IF SET DON'T RUN JOB
POPJ P, ;JOB HAD AN ERROR, LET CPU0 TYPE MESSAGE
MOVEM J,.CPPLT##(P4) ;NO, FLAG POTENTIALLY LOST IF CAN'T RUN HIM
; BECAUSE OF MONITOR BIND
CAMN J,SW0JOB## ;WANT TO SWAP THIS JOB?
POPJ P, ;YES, DONT RUN IT THEN
SKIPG F,JBTSGN(J) ;GET HIGH SEG NO., SPY OR NONE?
JRST CPOPJ1 ;NO HIGH SEG OR SPY HI SEG - GIVE CAN RUN RETURN
MOVE F,JBTSTS(F) ;YES, HIGH SEG STATUS WORD (OR JOB 0'S)
TLNN F,SWP!SHF!JXPN ;IS HIGH SEG BEING SHUFFLED, SWAPPED, OR EXPANDED?
; BY THE MASTER
AOS (P) ;NO, GIVE CAN RUN THIS JOB RETURN
POPJ P, ;YES, GIVE CAN NOT RUN THIS JOB RETURN
;ROUTINE CALLED WHEN MASTER IS RUNNING SCHED, TO SEE IF JOB IS RUNNABLE
;ON MASTER. SKIP RETURN IF IS. NOTE AC ASSIGNMENTS SENSITIVE.
MPRUN: MOVE F,JBTSPS(J) ;GET STATUS WORD
TLNE F,(SP.NR1) ;DOES JOB HAVE UUO TO BE DONE
JRST MPRUN1 ;YES
SKIPL .CPRUN##(P4) ;SKIP IF CUP0 NOT RUNNABLE
TRNN F,SP.CR0 ;CAN JOB RUN ON MASTER
POPJ P, ;NO, TAKE NON-SKIP RETURN
MPRUN1: TLNN F,(SP.NR0+SP.CJ1) ;NOT RUNNABLE OR SLAVE CURRENT JOB?
AOS (P) ;OK TO RUN, TAKE SKIP RETURN
POPJ P, ;RETURN
;ROUTINE TO FORCE MASTER TO DO FAST SCHEDULING
;OF JOBS WAITING FOR UUO'S TO BE DONE
INTERNAL MSRQT,MSIPUC
MSRQT: JUMPE U,CPOPJ## ;IF JOB IS COMING OUT OF WS, TS, OR DS
CAIG U,DSQ## ;NOTE THAT WE NOW HAVE A RUNNABLE
MSIPUC: AOS .C1PUC ; JOB WHICH THE MASTER MUST HANDLE
POPJ P, ; RETURN
IFN <FTKI10!FTKL10>&FTSET,<
;SUBROUTINE TO CHECK IF A JOB IS RUNNABLE ON CPU0 AND IF
; CPU0 IS RUNNING
; EXITS CPOPJ1 IF SO, CPOPJ IF NOT RUNNABLE ON CPU0 OR CPU0 NOT RUNNING
;PRESERVES ALL ACS EXCEPT T3
CP0RC:: MOVEI T3,SP.CR0 ;CAN RUN ON CPU0 BIT
TDNE T3,JBTSPS##(J) ;CAN THE JOB RUN ON CPU0?
SKIPGE .C0RUN## ;AND IS CPU0 RUNNING?
POPJ P, ;CAN'T RUN ON CPU0 OR CPU0 NOT RUNNING
JRST CPOPJ1## ;RETURN
IFN FTKI10,<
;SUBROUTINE TO SEE MI PROG DIS MUST BE OFF ON CPU1 FOR
; THIS JOB TO USE ADDRESS BREAK
;ENTER WITH T4=IP.MID
;EXIT POPJ IF ADDRESS BREAK NOT AVAILABLE, CPOPJ1 IF OK
;PRESERVES T1,T2
CP1AC:: MOVEI T3,SP.CR1 ;CAN RUN ON CPU1 BIT
TDNE T3,JBTSPS##(J) ;CAN THE JOB RUN ON CPU1?
SKIPGE .C1RUN## ;AND IS CPU1 RUNNING?
JRST CPOPJ1## ;NO, ADDRESS BREAK IS OK
TDNN T4,.C1APR## ;IS MI PROG DIS SET?
AOS (P) ;NO, OK
POPJ P, ;RETURN
>;END IFN FTKI10
>
;SUBROUTINE TO SEE IF JOB # IN J IS ON SOME OTHER CPU
;CALL WITH:
; MOVEI J,JOB-TO-TEST
; PUSHJ P,OTHCPU
; RETURN HERE IF ON OTHER CPU
; RETURN HERE IF NOT ON OTHER CPU
;
OTHCPU::MOVSI T2,(SP.CJ1) ;ASSUME ON CPU0
SKPCPU (0) ;ON CPU0?
MOVSI T2,(SP.CJ0) ;ON CPU1, SEE IF THIS IS CPU0 JOB
TDNN T2,JBTSPS##(J) ;SEE IF JOB IN J IS ON THE OTHER CPU
AOS (P) ;NOT--SKIP RETURN
POPJ P,
IFN <FTKI10!FTKL10>&FTLOCK,<
;SUBROUTINE TO COPY A PORTION OF THE USER'S MAP INTO
; CPU1'S MAP.
;CALLING SEQUENCE:
; MOVE T1,EXEC VIRTUAL PAGE NUMBER
; MOVE T2,NUMBER OF PAGES
; MOVE T3,USER VIRTUAL ADDRESS
; PUSHJ P,MAPUEC
; ALWAYS RETURN HERE
MAPUEC::ADDI T1,.E12OF## ;OFFSET TO MAKE MAPUEI COPY USER'S MAP TO CPU1'S MAP
PJRST MAPUEI## ;COPY USER'S MAP TO CPU1'S MAP
>
IFN FTLOCK&FTVM,<
;SUBROUTINE TO MAP THE UPMP OF A JOB BEING LOCKED INTO
; CPU1'S MAP
;CALLING SEQUENCE:
; MOVE T2,BYTE POINTER TO CPU0'S MAP
; MOVE T3,CONTENTS OF UPMP MAP SLOT
; PUSHJ P,MAPUC
; ALWAYS RETURN HERE
;PRESERVES T1
MAPUC:: ADDI T2,.E1OFS## ;ADD OFFSET FROM CPU0'S TO CPU1'S MAP
DPB T3,T2 ;MAP THE UPMP THERE
POPJ P, ; AND RETURN
>
IFN FT2SEGMON&FTMOFFL,<
;SUBROUTINE TO INSURE THAT CPU1 IS IN ITS ACS BEFORE CHANGING
; THE EXEC MAP. RETURNS POPJ OF NOT, CPOPJ1 IF SO
CP1STP::SKIPL .C1OK ;CPU1 RUNNING?
JRST CPOPJ1## ;NO, OK TO CHANGE THE EXEC MAP
MOVE T1,.E1IL## ;"140",SETOMED IF CPU1 STUCK IT HEAD IN THE SAND
AOJE T1,CPOPJ1## ;IF MINUS ONE, CPU1 IS QUIENTLY RELAXING
POPJ P, ;CPU1 IS BUSY, WAIT AWHILE
>
;ROUTINES TO HANDLE VARIOUS CPU1 ERROR CONDITIONS ON CPU1
; ONLY GET HERE ON SERIOUS EXEC MODE ERRORS OR MEM PARITY
INTERN SVTYPE,SVMES
AP1ERR: JUMPGE S,AP1ER0 ;APR ERROR
PUSHJ P,PARSWP## ;NO, MEM PARITY - SWEEP CORE ON CPU1
; FLAG JOBS WITH BAD PARITY
; DO NOT PRINT SINCE THIS IS CPU1
SETZM .C1AEF## ;CLEAR CPU1 APR ERROR FLAG
PJSP T1,SPTOPR ;FLAG CPU0 TO PRINT MESSAGE ON NEXT
; CLOCK TICK TO OPR. CPU1 LOOP UNTIL
; CPU0 STARTS MESSAGE
ASCIZ /Mem par err/ ;THE MESSAGE
;NOTE: CPU1 HAS REQUESTED CPU0 TO PRINT RANGE ON OPR
; AND USER'S CONSOLES. BOTH OF THESE MESSAGES ARE IN ADDITION TO THIS ONE ABOVE
;HERE ON ANY APR ERROR ON CPU1
AP1ER0: SETZM .CPAEF(P4) ;CLEAR SLAVE ERROR FLAG
TRNN S,AP.NXM ;IS THIS A NXM ERROR FOR EXEC
JRST AP1EPD ;NO, CHECK IF IT IS A PDL OV ERROR
MOVEI T1,NXMMES ;PREPARE TO TYPE OUT "NXM ERROR"
AP1TYP: PUSHJ P,SPTYPE ;GO TYPE OUT MESSAGE POINTED TO BY T1
STOPCD CPOPJ,DEBUG,C1N, ;++CPU 1 NXM
AP1EPD: TRNN S,AP.POV ;IS THIS A PDL OV ERROR
JRST AP1EHD ;AWK! THIS IS A HARDWARE ERROR PERHAPS
MOVEI T1,PDLMES ;TYPE OUT PDL OV MESSAGE
JRST AP1TYP
AP1EHD: MOVEI T1,[ASCIZ/Unexplicable APR error/]
JRST AP1TYP ;TYPE THIS ERROR MESSAGE AND HALT
IFN FTKL10,<
SUBTTL MULTIPROCESSING KL10 CACHE CONTROL
;ROUTINE FOR SCHEDULER TO CHECK THE STATE OF THE CACHE FOR A JOB
; SKIP RETURN MEANS OK, NON-SKIP MEANS JOB IS NOT RUNNABLE ON THIS
; CPU BECAUSE OF CACHE. CALL IS:
;
; MOVE P4,<CPU DATA BLOCK ADDR>
; MOVE J,<JOB NUMBER>
; PUSHJ P,SCDCSH
; <JOB NOT RUNNABLE W.R.T. CACHE>
; <JOB RUNNALBE W.R.T. CACHE>
; IF ERROR RETURN WAS GIVEN, .CPCLN IS INCREMENTED (# TIMES SCHEDULER
; COULD NOT RUN A JOB BECAUSE OF CACHE) AND .CPCLF IS SET TO THE JOB'S
; NUMBER (POTENTIALLY LOST TIME BECAUSE OF CACHE)
SCDCSH::PUSHJ P,CHKCSH ;CHECK STATE OF CACHE
JRST CPOPJ1## ;OK, RETURN
AOS .CPCLN##(P4) ;NOT OK, SCHEDULER HAS TO IGNORE AGAIN
MOVEM J,.CPCLF##(P4) ;IN CASE NOTHING ELSE IS RUNNABLE
POPJ P, ;RETURN AND SAY RUN SOMEONE ELSE
;ROUTINE TO CHECK THE STATE OF CACHE FOR A JOB, CALLED BY SWAPPER
; JUST BEFORE IT IS TO SWAP OUT A JOB OR SEGMENT.
; SKIP RETURN MEANS OK, NON-SKIP MEANS JOB IS NOT SWAPPABLE W.R.T. CACHE.
; CALL IS:
;
; MOVE J,<SEGMENT NUMBER>
; MOVE P4,<CPU DATA BLOCK ADDR>
; PUSHJ P,SWPCSH
; <JOB CANNOT BE SWAPPED BECAUSE OF CACHE>
; <OK TO SWAP JOB>
;
; IF ERROR RETURN IS GIVEN, .CPCSD IS INCREMENTED, WHICH IS THE
; NUMBER OF TIMES THE SWAPPER WAS DELAYED FROM SWAPPING A JOB OUT
; BECAUSE OF THE CACHE.
SWPCSH::CAILE J,JOBMAX## ;IS THIS A LOWSEG?
POPJ P,
SWPCS1: PUSHJ P,CHKCSH ;DO THE REAL WORK
JRST CPOPJ1## ;EVERY THING IS BEAUTIFUL
; (IN ITS OWN WAY)
AOS .CPCSD##(P4) ;INCREMENT SWAPPER CACHE DELAY COUNT
POPJ P, ;BECAUSE SWAPPER HAS BAD NEWS COMING
;SUBROUTINE TO INSURE CPU1'S CACHE HAS BEEN SWEPT IF NECESSARY
; CALL IS:
;
; MOVE J,<JOB NUMBER>
; PUSHJ P,CKCP1C
; <OK TO PROCEED>
; <NEED TO DELAY>
CKCP1C::PUSH P,P4 ;SAVE P4
MOVEI P4,.C1CDB## ;ASK ABOUT CPU1
PUSHJ P,CHKCSH ;CHECK STATE OF CPU1'S CACHE W.R.T. THIS JOB
CAIA ;OK
AOS -1(P) ;NEED TO WAIT FOR A SWEEP
POP P,P4 ;RESTORE P4
POPJ P, ;AND RETURN
;ROUTINE TO CHECK THE STATE OF THE CACHE FOR A JOB
; CALLED ONLY BY SCDCSH, SWPCSH
; CALL:
; MOVE P4,<CPU DATA BLOCK ADDRESS>
; MOVE J,<JOB NUMBER>
; PUSHJ P,CHKCSH
; <SUCCESSFUL RETURN> ;JOB IS RUNNABLE, SWAPPABLE W.R.T. CACHE
; <ERROR RETURN> ;CACHE MUST BE SWEPT ON ANOTHER CPU FOR THIS JOB
;
; SMASHES T3
CHKCSH: HRRZ T3,JBTST3##(J) ;GET CDB ADDR OF LAST CPU JOB RAN ON
JUMPE T3,CPOPJ ;ZERO MEANS SOMEONE SPECIFICALLY GAVE
; THE OK NOT TO SWEEP CACHE
CAIN T3,(P4) ;WAS LAST CPU SAME AS THIS ONE?
POPJ P, ;YES, ALL IS OK
MOVE T4,.CPCSN##(T3) ;NO, MUST CHECK CURRENT SWEEP NUMBER ON OLD CPU AGAINST
CAMLE T4,JBTCSN##(J) ; SWEEP NUMBER ON OLD CPU WHEN JOB LEFT IT
POPJ P, ;CURRENT SERIAL NUMBER IS LARGER, OLD CPU
; HAS SWEPT SO JOB IS RUNNABLE, SWAPPABLE
;JOB CANNOT BE RUN OR SWAPPED, SO PUT IN A REQUEST TO THE OLD CPU
; TO SWEEP ITS CACHE.
MOVEM T4,.CPCSR##(T3) ;.CPCSN CAN NEVER BE LESS THAN JBTCSN, SO
; NOW WE KNOW THAT .CPCSN## AND JBTCSN ARE EQUAL.
; OTHER CPU WILL SWEEP IF REQUEST IS EQUAL
; OR GREATER IN VALUE THAN CURRENT SWEEP NUMBER
; ON THAT CPU
JRST CPOPJ1 ;INDICATE THAT JOB CANNOT BE DEALT
; WITH NOW.
;ROUTINE TO CLEAR JOB'S CACHE SWEEP SERIAL NUMBER DATA, INDICATING
; THAT NO SWEEP NEED BE DONE BEFORE THE JOB SWITCHES CPUS
; CALLED FROM KLSER, COMCON WHEN JOB THROWS AWAY OLD CORE IMAGE.
; CALL:
; MOVE J,<JOB NUMBER>
; PUSHJ P,CLCSN
; <ONLY RETURN>
;
; RESPECTS ALL ACS
CLCSN:: PUSH P,T1 ;SAVE T1
SETZ T1,
HRRM T1,JBTST3##(J) ;JUST CLEAR OUT CDB ADDRESS, MAKING
; JBTCSN ENTRY INVALID
JRST TPOPJ## ;RESTORE T1 AND RETURN
;ROUTINE TO SET UP JBTST3 AND JBTCSN WITH CDB ADDRESS AND CURRENT
; SWEEP SERIAL NUMBER USING CDB IN P4.
; CALL:
; MOVE U,<JOB NUMBER>
; MOVE P4,<CDB ADDRESS>
; PUSHJ P,SETCSN
; <ONLY RETURN>
;
;CALLED BY CLOCK1 AFTER COMPLETION OF CONTEXT SWITCHING FROM OLD JOB.
; NOT CALLED FOR CONTEXT SWITCH FROM NULL JOB
; MUST BE CALLED INSIDE CPU INTERLOCK
; ANY CACHE SWEEP DONE ON A CPU AFTER THIS ROUTINE IS CALLED ON
; THAT CPU WILL CAUSE JOB THAT THIS ROUTINE WAS CALLED FOR TO BE
; RUNNABLE W.R.T. CACHE ON ANOTHER CPU
SETCSN::HRRM P4,JBTST3##(U) ;SETUP CDB ADDRESS
MOVE T1,.CPCSN##(P4) ;GET CACHE SWEEP SERIAL #
MOVEM T1,JBTCSN##(U) ;SAVE FOR LATER USE BY SCHED1
POPJ P, ;RETURN
;ROUTINE TO SERVICE CACHE SWEEP REQUEST. CALLED BY
; CLOCK1 BEFORE SCHEDULER IS CALLED SO THAT
; SWEEP REQUESTS CAN BE SERVICED BY ANOTHER CPU BEFORE IT
; ENTERS THE SCHEDULER.
; IF A SWEEP IS DONE, .CPCRN IS INCREMENTED
CSREQS::MOVE T1,.CPCSR##(P4) ;GET REQUEST NUMBER
CAMGE T1,.CPCSN##(P4) ;IS IT LESS THAN CURRENT SWEEP NUMBER?
POPJ P, ;NO REQUESTED CACHE SWEEP THIS TICK
AOS .CPCRN##(P4) ;NO, EQUAL(HAPPENS) OR GREATER (NEVER HAPPENS)
; INCREMENT COUNT OF SWEEPS DONE BY REQUEST
PJRST CSDMP## ;SWEEP AND RETURN
; MEANS A REQUEST IS IN.
;ROUTINE TO ANTICIPATE THE NEED FOR A CACHE SWEEP FOR ANOTHER CPU
; CALLED IN CLOCK1 AFTER OLD JOB'S CONTEXT IS SAVED (IF APPLICABLE)
; AND AFTER SETCSN IS CALLED SO THAT IF A CACHE SWEEP IS DONE IT
; WILL MAKE THE JOB IN QUESTION RUNNABLE ON ANOTHER CPU.
; NOTE THAT IT IS CALLED INSIDE INTERLOCK SO THAT MASTER CPU
; WILL NEVER HAVE TO REQUEST A CACHE SWEEP FOR A JOB THAT DID A
; MASTER UUO ON SLAVE BY GETTING TO SCHEDULER BEFORE CSHUUO IS
; CALLED BY SLAVE.
; A SWEEP IS DONE IF LAST JOB RUN WAS ON
; SLAVE CPU AND DID A UUO WHICH MUST BE EXECUTED ON MASTER. HOPEFULLY,
; THIS SAVES CPU0 FROM WAITING FOR CPU1 TO RUN NULL JOB (COULD BE A WHILE)
; OR SERVICING SWEEP REQUEST (COULD TAKE SEVERAL TICKS, SINCE ITS DONE AT
; PI 7
;
;CALL WITH NEW JOB IN J, OLD JOB IN U.
CSHUUO::SKPCPU (1) ;IF ON MASTER,
POPJ P, ;DON'T DO ANY MORE
MOVE T1,JBTSPS##(U) ;GET MS STATUS WORD OF OLD JOB
TLNE T1,(SP.NR1) ;HAS HE DONE A UUO FOR MASTER?
PJRST CSDMP## ;YES, DO A SWEEP
POPJ P, ;NO, DO NOTHING
;SUBROUTINE TO CALL SETCSN WHEN THE JOB NUMBER
; IS IN J AND THE CONTENTS OF P4 IS UNKNOWN
SETCSJ::PUSHJ P,SCPCDB## ;SETUP P4 FOR THIS CPU
PUSH P,U ;SAVE U
MOVE U,J ;ARGUMENT FOR SETCSN
PUSHJ P,SETCSN ;MAKE JOB UNRUNNABLE ON THE OTHER
; CPU UNTIL A SWEEP IS DONE
PJRST UPOPJ## ;RESTORE U AND RETURN
;SUBROUTINE TO CAUSE HIGH SEGMENT PART OF ALL MAPS TO GET CHANGED WHEN UWP CHANGES
;CALLING SEQUENCE:
; MOVEI T1,PREVIOUS STATE OF UWP (0 IF OFF, 1 IF ON)
; PUSHJ P,CLRCSH
;ALWAYS RETURN HERE (CACHE BITS CLEARED OR SET AS APPROPRIATE)
CLRCSH::MOVE J,.C0JOB## ;CURRENT JOB
SKIPLE J,JBTSGN##(J) ;JOB HAVE A HIGH SEGMENT?
TLNN J,SHRSEG ; AND IS IT SHARABLE?
POPJ P, ;NO, NOTHING TO DO
TLNN J,UWPOFF ;IS THE HIGH SEGMENT WRITE PROTECTED?
JRST CLRCS2 ;YES, SEE IF ANY OTHER JOB HAS IT WRITE ENABLED
JUMPE T1,CPOPJ## ;NOTHING TO DO IF NOTHING CHANGED
MOVEI T1,SETNCH ;SUBROUTINE TO SET NO CACHE BITS
PUSHJ P,HGHAPP## ;TURN ON NOCSH!REDOMP FOR ALL JOBS SHARING THIS SEGMENT
CLRCS1: MOVE J,.C0JOB## ;CURRENT JOB
HRRZ J,JBTSGN##(J) ;JOB'S HIGH SEGMENT NUMBER
MOVE T2,.C1JOB## ;CPU1'S CURRENT JOB
SKIPLE T1,JBTSGN##(T2) ;HIGH SEGMENT JOB ON CPU1 IS USING
CAIE J,(T1) ;SAME AS THE HIGH SEGMENT WHICH WAS JUST W.E.'ED?
POPJ P, ;NO, EVERYTHING IS OK
MOVSI T1,REDOMP ;HAS THE MAP BEEN REDONE FOR THE CPU1 JOB?
TDNN T1,JBTSGN##(T2) ; ...
POPJ P, ;YES, ALL IS WELL
MOVEI T1,1 ;NO, SLEEP A TIC
MOVE J,.C0JOB## ;OUR JOB NUMBER
PUSHJ P,SLEEP## ;WAIT A WHILE
JRST CLRCS1 ;AND TRY AGAIN
CLRCS2: JUMPN T1,CPOPJ## ;RETURN IF NOT CHANGING THE STATE OF UWP
MOVEI T1,CHKUWP ;SUBROUTINE TO CHECK IF ANY OTHER JOB HAS UWPOFF
SETZ T2, ;INITIALIZE FLAG SAYING NO JOBS FOUND
PUSHJ P,HGHAPP## ;ANY OTHER JOB HAVE UWP OFF FOR THIS SEGMENT?
JUMPL T2,CPOPJ## ;EXIT IF SOME JOB HAS UWP OFF
MOVEI T1,CLRNCH ;CLEAR NOCSH FOR ALL JOBS SHARING THIS SEGMENT
PJRST HGHAPP## ;CAUSE MAPS TO BE REDONE WITH CACHE ON
SETNCH: MOVSI T1,NOCSH!REDOMP ;DON'T CACHE THE HIGH SEG, CAUSE MAP TO BE REDONE
IORM T1,JBTSGN##(J)
POPJ P,
CHKUWP: MOVSI T1,UWPOFF ;IS USER WRITE PROTECT OFF?
TDNE T1,JBTSGN##(J)
SETO T2, ;YES, FLAG IT
POPJ P,
CLRNCH: MOVSI T1,NOCSH ;DON'T CACHE IT
ANDCAM T1,JBTSGN##(J) ;CLEAR NO CACHE BIT
MOVSI T1,REDOMP ;REDO THE MAP BIT
IORM T1,JBTSGN##(J) ;CAUSE MAP TO BE REDONE WITH CACHE BITS ON
POPJ P,
;SUBROUTINE TO CHECK TO SEE IF A JOB IS ATTACHING TO A SHARABLE
; WRITABLE HIGH SEGMENT
CHKSWS::MOVE J,.C0JOB## ;CURRENT JOB
SKIPLE J,JBTSGN##(J) ;JOB HAVE A REAL HIGH SEGMENT?
TLNN J,SHRSEG ; AND IS IT SHARABLE?
POPJ P, ;NO, NOTHING TO DO
MOVEI T1,CHKUWP ;ROUTINE TO LOOK FOR UWPOFF
SETZ T2, ;ASSUME IT ISN'T
PUSHJ P,HGHAPP## ;SET IF ANY JOB HAS UWPOFF FOR THIS SEGMENT
MOVE J,.C0JOB## ;JOB NUMBER
MOVSI T1,NOCSH!REDOMP ;FORCE MAP TO BE REDONE UNCACHED
SKIPE T2 ;SKIP IF NOT WRITABLE
IORM T1,JBTSGN##(J) ;UNCACHE HIGH SEGMENT IN THIS JOB'S MAP
POPJ P, ;AND RETURN
>;END IFN FTKL10
CP1SBP::MOVSI T1,(DF.RDC!DF.RJE) ;SET DEBUGF SO THAT
IORM T1,DEBUGF## ;ALL STOPCD'S CRASH
JRST CP1TY2 ;SETUP TO RETURN INTO
;DIE CODE FOR CPU1'S STOPCD
CP1TYP::CONI PI,.C0CPI## ;SAVE STATE OF CPU0
CONO PI,1177 ;..
MOVEM 17,.C0CAC##+17 ;..
MOVEI 17,.C0CAC## ;..
BLT 17,.C0CAC##+16 ;..
CP1TY2: MOVE P,.C1CAC##+P ;SETUP P AS CPU1'S P
MOVE F,.C1CAC##+F ;AND F AS CPU1'S F
MOVEI P4,.C1CDB## ;POINT TO CPU1 CDB
SETOM CP1HLT ;MARK CPU1 DIE IN PROGRESS
IFN FTKI10,<
DATAI PAG,CP0EUB ;SAVE CPU0
MOVE T1,CP1EUB
TLO T1,(PG.LUB)
DATAO PAG,T1 ; AND PRETEND WE ARE CPU1
>
IFN FTKL10,<
DATAI PAG,CP0UPT ; SAVE CPU0 UPT
MOVE T1,CP1UPT
TDC T1,[LG.LAB!LG.LPC!LG.IAM]
DATAO PAG,T1 ;AND PRETEND TO BE CPU1
>
JRST DIETYP## ;TYPE CPU1 STOPCD INFO
;HERE IF CPU1 DOES A STOPCD
CP1DIE::CONI APR,AP1STS ;SAVE STATE OF
CONI PI,.C1CPI## ; THE HARDWARE
CONO PI,PIOFF ;NO PIS
IFN FTKI10,<
DATAI PAG,CP1EUB ; AT TIME OF CRASH
>
IFN FTKL10,<
CONI PAG,CP1EPT ;SAVE EPT AND
DATAI PAG,CP1UPT ; UPT STATUS
>;END IFN FTKL10
MOVEM 17,.C1CAC##+17 ;SAVE THE AC'S
MOVEI 17,.C1CAC## ;..
BLT 17,.C1CAC##+16 ;..
MOVE T1,SPTRAP## ;GET LAST MUUO
MOVEM T1,.C1TRP## ;SAVE IN CPU DATA BLOCK
AOS CP1HLT ;TELL CPU0 WE DIED
CP1DI1: SKIPE CRSHWD## ;RELOADING?
JRST CP1DI2 ;YES, GO HIDE IN AC'S
SKIPE CP1HLT ;CPU0 DONE YET?
JRST CP1DI1 ;NO, WAIT
MOVEI T1,177 ;POINT TO ALL PI CHANNELS
AND T1,.C1CPI## ;RESTORE ONLY THOSE THAT WERE ON
IORI T1,PI.TNP ;SET BIT TO TURN THEM ON
MOVEM T1,.C1CPI## ;SAVE FOR LATER
MOVSI 17,.C1CAC## ;RESTORE THE AC'S
BLT 17,17
CONO PI,@.C1CPI## ;TURN PI SYSTEM BACK ON
POPJ P, ;CONTINUE
;CONSOLE TELETYPE (CTY1)
IFN FTCTY1,<
CT1==120 ;DEVICE CODE
;--------THIS CODE EXECUTED BY CPU1----------
; INTERRUPT ROUTINE
IFN FTKA10!FTKI10,<
CT1INT::CONSO CT1,50
JRST .-1
CONSO CT1,40 ;WHAT?
JRST CT1OUT ;OUTPUT DONE
DATAI CT1,CT1REC ;INPUT - GET CHARACTER
JRST CT1XIT
CT1OUT: CONO CT1,200+CT1CHN## ;CLEAR INTERRUPT
JEN @CT1CHL
CT1XIT: SETOM ST1IRP ;SET 'INTERRUPT' FLAG
JEN @CT1CHL##
>;END IFN FTKA10!FTKI10
IFN FTKL10,<
$LOW
CT1INT::0
CONO DTE0,CL11PT ;CLEAR INTERRUPT
SKIPN DT1MTI## ;INPUT READY?
JEN @CT1INT ;NO, LET CT1CLK LOOK AT DT1MTD
EXCH 17,DT1F11## ;YES, GET CHARACTER
MOVEM 17,CT1REC ;LET CPU0 KNOW WHAT IT IS
MOVE 17,DT1F11## ;RESTORE 17
SETOM ST1IRP ;LET CPU0 TAKE BALL
SETZM DT1MTI## ;ALLOW ANOTHER CHARACTER
JEN @CT1INT ;RETURN
$HIGH
>;END IFN FTKL10
$LOW
CT1REC::0 ;REC'D CHAR STORED HERE
CT1XMT::0 ;NON-0 WHEN XMT-DONE SEEN
ST1IRP::0 ;NON-0 TO GENERATE ST1 IRP. ON CPU0
$HIGH
; INITILIZATION
IFN FTKL10,<
$HIGH
LIT
$LOW
>
CT1INI: SETZM CT1REC
SETOM CT1XMT
SETOM ST1IRP
SETZM CT1TYP
IFN FTKA10!FTKI10,<
CONO CT1,1200+CT1CHN##
POPJ P,
>;END IFN FTKA10!FTKI10
IFN FTKL10,<
MOVE T1,[DT1DBG##,,DT1DBG+1] ;CLEAR OUT DTE SOFTWARE AREA
SETZM DT1DBG##
BLT T1,DT1DND##
MOVE T1,[JSR CT1INT] ;SETUP EPT LOCATION
MOVEM T1,DT1II## ;WITH INTERRUPT JSR FOR DTE
MOVE T1,[DT1EPW##,,DT1EPW+1]
SETZM DT1EPW## ;CLEAR OUT DTE HARDWARE AREA
BLT T1,DT1DRW##
CONO DTE0,CL11PT+PILDEN+CT1CHN## ;SETUP DTE PI LEVEL
MOVEI T1,DT.ESP ;ENTER SECONDARY PROTOCOL
MOVEM T1,DT1CMD##
CONO DTE0,TO11DB ;DO COMMAND
MOVSI T1,10 ;WAIT, BUT NOT TOO LONG
SKIPN DT1FLG##
SOJG T1,.-1
POPJ P,
LIT ;FORCE LITERALS TO BE IN LOWSEG
$HIGH
>;END IFN FTKL10
; CALLED AT CLOCK LEVEL TO TYPE OUT WAITING CHARACTER
$LOW
IFN FTKA10!FTKI10,<
CT1CLK: 0
CONSZ CT1,20
JRST @CT1CLK
SETZM 17 ;CHARACTER TO TYPE?
EXCH 17,CT1TYP
JUMPE 17,@CT1CLK
DATAO CT1,17 ;YES - TYPE IT
SETOM CT1XMT
SETOM ST1IRP
JRST @CT1CLK
>;END IFN FTKA10!FTKI10
IFN FTKL10,<
CT1CLK: 0
SKIPN DT1MTD## ;OUTPUT NOT BUSY?
JRST @CT1CLK ;OUTPUT STILL BUSY, TRY NEXT TIME
SETZM 17
EXCH 17,CT1TYP ;GET CHARACTER, IF ANY
JUMPE 17,@CT1CLK ;NONE
SETZM DT1MTD## ;CLEAR DONE
ANDI 17,377 ;JUST CHARACTER
MOVEI 17,DT.MTO(17) ;OUTPUT IT
MOVEM 17,DT1CMD##
CONO DTE0,TO11DB ;RING 11 DOORBELL
SETOM CT1XMT ;TELL 10 WE HAVE CHAR
SETOM ST1IRP
JRST @CT1CLK ;AND RETURN
>;END IFN FTKL10
$HIGH
;--------THIS CODE EXECUTED ON CPU0--------
;ST1IRP IS CHECKED AT APR LEVEL AND IF NON-0
; A PI REQUEST IS MADE FOR ST1INT WHO INTERFACES WITH SCNSER
ST1INT::SKIPN ST1IRP ;SOFTWARE INTERRUPT?
JRST .-1
IFN FTKI10!FTKL10,<
CONO PI,CLRST1##
>
SETZM ST1IRP ;YES - CLEAR FLAG
JSR ST1SAV## ;SAV AC'S
MOVEI U,CT1LIN## ;LOAD LINE NUMBER
SETZM T3
EXCH T3,CT1REC ;WAS IT RECEIVE?
JUMPE T3,ST1XMT ;NO
PUSHJ P,RECINT## ;YES - GIVE IT TO SCNSER
SKIPE CT1XMT ;IF XMT WAITING - CATCH IT NEXT TICK
SETOM ST1IRP
POPJ P,
ST1XMT: EXCH T3,CT1XMT ;WAS IT XMIT - DONE?
PJUMPN T3,XMTINT## ;YES - TELL SCNSER
POPJ P, ;NO - IGNORE IT
; HERE FROM SCNSER TO TYPE A CHARACTER
CT1TYO::TLO T3,400000 ;SO NULLS WON'T BE OVERLOOKED
MOVEM T3,CT1TYP ;CUP1 APR CLOCK WILL SEE
POPJ P, ; THIS AND TYPE IT
$LOW
CT1TYP: 0 ;CHARACTER TO TYPE OUT.
$HIGH
> ;IFN FTCTY1
IFE FTCTY1,< ;IF NO CTY1
CT1INI==CPOPJ##
CT1CLK==CPOPJ##
> ;IFE FTCTY1
;ROUTINES TO TYPE OUT ERROR MESSAGES
;CALLED BY CLOCK1 TO TYPE OUT TIME LIMIT EXCEEDED MESSAGE
IFN FTTLIM,< INTERN STIMLM
STIMLM: MOVEI T1,JS.APE ;THIS IS AN ERROR FOR MASTER TO TYPE OUT
TDNE T1,JBTSTS##(J) ;IS THERE ALREADY A "REAL" APR ERROR TO BE PROCESSED?
POPJ P, ;YES, FORGET ABOUT TIME LIMIT EXCEEDED
IORM T1,JBTSTS(J) ;SET ERROR BIT
MOVSI T1,(SP.TLE+SP.NR1)
IORM T1,JBTSPS(J) ;SET ERROR BITS ON FOR CIP8A TO SEE
POPJ P, ;AND RETURN (JOB WILL NOW BE RESCHEDULED)
>
;ROUTINE TO CAUSE THE MASTER TO TYPE OUT A MESSAGE
;CALL: MOVEI T1,MESSAGE ;GET ADR OF MESSAGE TO TYPE IN T1
; HRLI T1,JOB NO., 0 ASSUMES OPR WHERE TO TYPE MESSAGE
; PUSHJ P,SPTYPE ;RETURN WHEN MESSAGE HAS BEEN TYPED
INTERN SPTYPE
SPTOPR::HRLI T1,0 ;FORCE MESSAGE ON OPR TTY
SPTYPE: MOVEM T1,SVMES ;STORE ADDR OF ERROR MESSAGE FOR MASTER
SPTP1: SKIPN SVMES ;HAS FLAG BEEN CLEARED YET BY MASTER
POPJ P, ;YES, MESSAGE MUST HAVE GONE OUT
ROT T1,^D72 ;NOP SO NOT TO SLOW DOWN MEMORY
JRST SPTP1 ;GO SEE IF MESSAGE FINISHED YET
;ROUTINE CALLED BY THE MASTER TO TYPE OUT MESSAGES FROM SLAVE
SVTYPE: HRRZ U,OPRLDB ;FIND THE OPR TTY
HLRZ J,SVMES ;GET SLAVE JOB NUMBER IF ANY
SKIPE J ;IS THERE A JOB NUMBER
PUSHJ P,TTYFNU ;YES, FIND ITS LDB FOR ITS TTY
PUSHJ P,INLMES ;TYPE OUT FOLLOWING MESSAGE
ASCIZ /?
?Error ON CPU1
?/
HRRZ T1,SVMES ;GET ADDRESS OF MESSAGE TO GO OUT
PUSHJ P,CONMES ;TYPE IT OUT (T1 CONTAINS POINTER TO MESSAGE)
SETZM SVMES ;CLEAR FLAG TO SIGNAL END OF TYPE OUT
PJRST CRLF## ;RETURN AND PRINT CRLF
;ROUTINE TO CHECK FOR APR ERRORS DETECTED ON CPU1
; JUST BEFORE CPU0 IS ABOUT TO RUN JOB (CONTEXT HAS BEEN SWITCHED)
;CALL: MOVEI T1,JS.APE
; MOVE J,JOB NUMBER
; MOVE R,JOB DATA AREA EXEC VIRTUAL ADDRESS
; PUSHJ P,CSPTLE
; EXCEEDED TIME LIMIT ON CPU1 - JS.APE CLEARED IN JPTSTS
; MUST BE ANOTHER APR ERROR - JS.APE NOT CLEARED (ERRCON MUST ANYWAY)
; ERROR FLAGS SET (.C0AEF) SO ERRCON WILL BE CALLED INSTEAD OF RUNNING USER
IFN FTTLIM,<
CSPTLE::MOVSI T2,(SP.TLE) ;TIME LIMIT EXCEEDED ON CPU1
TDNN T2,JBTSPS##(J) ;IS LIMIT EXCEEDED FOR THIS JOB?
JRST CPOPJ1## ;NO, SOME OTHER APR ERROR
ANDCAM T2,JBTSPS##(J) ;CLEAR TIME LIMIT EXCEEDED
ANDCAM T1,JBTSTS##(J) ;YES, CLEAR APR ERROR BIT
POPJ P, ;AND DO TIME LIMIT MESSAGE OR INTERCEPT
; NOW THAT JOB IS ON CPU0
> ;END COND ON FTTLIM
$LIT
;SLAVE PROCESSOR INITIALIZATION. JRST HERE FROM 400 STARTUP.
INTERNAL SPRINI
EXTERNAL AP1RST,UUOSP0,UUOSP2,CTYTYP
EXTERNAL .C1SCD,.C1NPD,NULJB1
$LOW ;THIS CODE MUST BE IN THE LOW SEGMENT SINCE
; THE HIGH SEGMENT ISN'T ADDRESSABLE UNTIL
;CPU1'S MAP IS SETUP FROM CPU0'S MAP
SPRINI: CONO PI,CLRPIS## ;CLEAR PI AND PARITY ERROR FLAG
CONO APR,AP1RST ;RESET EVERYTHING AND ENABLE CLOCK
IFN FTKL10,<
EXECAC ;MAKE SURE AC BLOCKS ARE OK
>
MOVE P,.C1NPD ;SET UP PUSH DOWN POINTER
IFN FTKI10,<
CONI PAG,T1 ;READ SERIAL NUMBER
LSH T1,-^D26 ;RIGHT ADJUST
MOVEM T1,.C1ASN## ;STORE
>
IFN FTKL10,<
APRID T1 ;READ SERIAL NUMBER
ANDI T1,7777 ;MASK OUT U CODE
MOVEM T1,.C1ASN## ;STORE
PUSHJ P,CT1INI ;IF KL10, INITIALIZE CTY NOW SO THIS WILL
; COME OUT
>;END IFN FTKL10
MOVEI T1,[ASCIZ/
[CPU1]
/]
PUSHJ P,CTYTYP ;TELL OPERATOR THAT THIS IS THE SECOND CPU
SETZM .E1IL##
MOVE 14,[XWD ACLOOP,2] ;LOAD AC'S WITH WAIT LOOP
BLT 14,14 ;CPU1 WILL WAIT UNTIL CPU0 IS GOING
MOVE 13,[JRST SPRIN1] ;SET UP RETURN INSTRUCTION
JRST 2 ;ENTER LOOP
;INITIALIZE PD LIST
SPRIN1: MOVE P,.C1NPD ;SET UP PUSH DOWN POINTER
IFN FTKI10!FTKL10,<
PUSH P,.E1PM## ;SAVE FIRST SLOT IN CPU1'S MAP TEMPORARRLY
IFN FT2SEGMON,<
PUSHJ P,MAPINI
>
IFN FTKL10,<
MOVEI T1,LG.CSL!LG.CSW
IORM T1,.C1EBR
>
MOVEI T1,.C1DBL## ;ADDRESS OF CPU1'S DOORBELL
LSH T1,W2PLSH## ;CONVERT TO PAGE NUMBER
TRO T1,PM.ACC+PM.PUB;ACCESS ALLOWED AND PUBLIC (NULL JOB RUNS
; IN PUBLIC USER MODE)
MOVEI T2,400000+.C1DBL##
ROT T2,W2PLSH##-1 ;MAP SLOT IN THE NULL JOBS MAP WHICH
; WILL MAP CPU1'S DOORBELL FOR CPU1'S NULL JOB
MOVEI T3,NLUPMP##(T2) ;ADDRESS OF THE NULL JOB'S UPMP+DOORBELL OFFSET
HRLI T3,222200 ;ASSUME LEFT HALF WORD MAPS DOORBELL
SKIPGE T2 ;IS IT AN ODD PAGE?
HRLI T3,002200 ;NO, RIGHT HALF WORD MAPS THE DOORBELL
DPB T1,T3 ;MAP THE DOORBELL FOR CPU1'S NULL JOB
JRSTF @[EXP IC.UOU+SPRIN4] ;TURN ON USER IOT SO EXECUTE PAGED
; CORRECTLY AND PROCEED WITH INITIALIZATION
>
IFN FTKA10,<
SPRIN2: PUSH P,SPTRAP+1 ;SAVE 141
PUSH P,SPTRAP+2 ;AND 142
MOVE T1,[JSR ENDTST]
MOVEM T1,SPTRAP+1 ;SET UP FOR UUO TRAP
MOVEM T1,SPTRAP+2 ;AND FOR CHANNEL 1 INTERRUPT
CONO APR,633551 ;TURN APR ON TO CHANNEL 1
CONO PI,12300 ;ALLOW INTERRUPTS ONE 1
DATAO APR,[XWD 376776,400] ;SET UP KT10A
JRST 1,.+1 ;GO TO USER MODE
MOVE T1,400100 ;TRY A MEMORY REFERENCE
SPRIN3: MOVEI 17,400000 ;BLT SHADOW ACS TO THEIR SELF
BLT 17,400017 ; TO CLEAR POSSIBLE PARITY ERRORS
SETZ T2, ;ZERO AN AC
SETOM 400000+T2 ;SET SHADOW AC TO SEE IF AC GETS CLOBBERED
CALL ;GO BACK TO MONITOR MODE
ENDTST: 0 ;JSR IS DONE HERE FROM CALL UUO
POP P,SPTRAP+2 ;RESTORE 142
POP P,SPTRAP+1 ;AND 141
CONSZ APR,@.C1ILM## ;WAS THERE AN ILM. (NO TWO REGISTERS?)
PUSHJ P,NKT10A ;ONLY ONE REGISTER EXISTS
CONO APR,@.C1ILM## ;CLEAR ILM
>
SPRIN4: CONO PI,10000 ;AND CLEAR PI SYSTEM
IFN FTKI10!FTKL10,<
POP P,.E1PM## ;RESTORE CONTENTS OF CPU1 EXEC MAP SLOT 0
>
IFN FTKA10,<
JUMPE T2,SPRIN5 ;IF FAST ACS ARE ON CONTINUE
MOVEI T1,[ASCIZ/CPU1 fast acs are off - set FM ENB/]
MOVEM T1,SVMES ;TYPE THIS OUT ON MASTER
PUSHJ P,CTYTYP ;AND ON THE SLAVE TTY
; SPLIT CYCLE ON, 2 CPUS CONFLICT
; ON MEMORY REFERENCES
STOPCD SYSDSP,HALT,SCO, ;++SPLIT CYCLE ON
NKT10A: SKIPN TWOREG ;DOES MASTER HAVE TWO REGISTERS
POPJ P, ;NO, RETURN
STOPCD .,HALT,KN1, ;++KT10A NOT ON CPU1
>
;HERE TO SET UP TO RUN NULL JOB, & SETUP PI
SPRIN5: HRRZS .C1MPC## ;CLEAR SERIOUS MEMORY PARITY HALT FLAG
; HALT AFTER PRINTING ON CPU0 CTY
MOVEI J,JOBMAX## ;MAX JOB NO.
MOVSI T1,(SP.CJ1) ;JOB RUNNING ON CPU1 BIT
SPRLP1: ANDCAM T1,JBTSPS##(J) ;CLEAR FOR ALL JOB IN SYSTEM
; (IN CASE THIS IS A 450 RESTART ON CPU1)
SOJGE J,SPRLP1 ;MORE?
MOVEI P4,.C1CDB## ;SETUP P4
IFN FTKL10,<
MOVE T1,.CPEBS##(P4) ;GET EBOX TICKS/SECOND
IDIV T1,TICSEC## ;AND NOW GET EBOX COUNTS/JIFFY
IMULI T1,.EBCPT ;MULTIPLY BY EBOX COUNTS/TICK
MOVEM T1,.CPEBJ##(P4) ;STORE IN CDB VARIABLE
MOVE T1,.CPMBS##(P4) ;GET MBOX TICKS/SECOND
IDIV T1,TICSEC## ;GET MBOX COUNTS/JIFFY
IMULI T1,.MBCPT ;MULTIPLY BY MBOX COUNTS/TICK
MOVEM T1,.CPMBJ##(P4) ;SAVE
IFN FTEMRT,<
PUSHJ P,ACCMON## ;START UP ACCOUNTING METERS
PUSHJ P,CLREBT## ;CLEAR OUT E AND MBOX ACCOUNTING METERS
>;END IFN FTEMRT
>;END IFN FTKL10
PUSHJ P,SETIME## ;TO INITILIZE 'GGTIME' CLOCK (IN SYSINI)
IFN FTKL10,<
CONI MTR,T1 ;PRESERVE TIME BASE INFO
CONO MTR,AP1CHN##(T1) ;SETUP INTERVAL TIMER PI
MOVE T1,[JSR TM1INT##] ;GET TIMER INTERRUPT INST.
MOVEM T1,.E1TII## ;MOVE INTO EPT TRAP LOC
MOVEI T1,^D1666 ;ASSUME 60HZ
MOVE T2,STATES##
TLNE T2,(ST.CYC) ;IS OUR ASSUMPTION CORRECT?
MOVEI T1,^D2000 ;NO, 2000 IS INTERVAL
CONO TIM,TO.CTD!TO.CIT!TO.SIT(T1) ;START TIMER GOING
>
IFN FTKA10!FTKI10,<
PUSHJ P,CT1INI ;INIT CTY1 CODE
>
CONO APR,AP1NUL##
CONO PI,52377 ;TURN ON ALL PI, ENABLE MEMORY PARITY
IFN FTKL10,<
SETOM DT1MTD## ;SET DONE INITIALLY SO CT1CLK WILL TYPE
; CHARACTERS
>
JRST NULJB1 ;GO START NULL JOB
;SUBROUTINE TO INITIALISE CP11'S MAP FROM CPU0'S MAP
IFN FT2SEGMON,<
MAPINI: PUSH P,.E1MP##+.MSKPC
MOVE T1,[.EPPM##,,.E1PM##]
BLT T1,.E1PM##+177
IFN FTKL10,<
MOVE T1,[.EPLM##,,.E1LM##]
BLT T1,.E1LM##+157
>
POP P,.E1MP##+.MSKPC
CLRPGT (1)
POPJ P,
>
SUBTTL DUAL CPU INITIALIZATION
;ROUTINE TO CHECK IF BOTH PROCESSORS ARE IN SYSINI TOGETHER
;NOTE: THIS ROUTINE CANNOT USE A PD LIST SINCE BOTH CPUS CAN GET HERE
; IF OFFSET SWITCHES SET THE SAME WAY
;CALL: JSP T1,TWOCHK
; RETURN HERE IF ALL IS OK
INTERN TWOMAS,ONCCHK,TWOCHK
EXTERN .C0OK,CTYTYP
TWOCHK: MOVEI T3,^D34000 ;SET UP FOR 10 CLOCK TIC LOOP
SETZM .C0OK ;INITIALIZE MASTER OK WORD
SETZB T2,ONCCHK ;ZERO COUNTER AC AND WORD
SYS2MC: AOS T2 ;COUNT THE AC
AOS ONCCHK ;AND THEN THE MEMORY LOCATION
SOJG T3,SYS2MC ;LOOP FOR THE SPECIFIED TIME
CAMN T2,ONCCHK ;ARE THE AC AND MEMORY WORD THE SAME
SKIPGE .C0OK ;AND THE MASTER OK WORD STILL ZERO
JRST TWOMAS ;NO, GO TYPE OUT A MESSAGE
JRST (T1) ;OK, RETURN
TWOMAS: MOVEI T1,[ASCIZ/
?Change the CPU1 MA TRP OFFSET switch in bay 1
/]
MOVEM T1,SVMES ;TYPE OUT MESSAGE ON MASTER
MOVEI P,T1 ;SET UP PUSH DOWN LIST IN AC'S
; SINCE BOTH CPUS COULD GET HERE
PUSHJ P,CTYTYP ;AND TYPE OUT MESSAGE
STOPCD SYSDSP,HALT,TOW, ;++TRAP OFFSET WRONG
ONCCHK: 0 ;MEMORY LOCATION COUNTER WORD
LIT
$HIGH ;BACK TO THE HIGH SEGMENT
;ROUTINE TO SAVE AC'S ANDLOOP IN THE AC'S WAITING FOR MASTER
;TO BE RELOADED. HERE AT APR PI WHEN MASTER STOPPED, OR 30 NON-ZERO
INTERN CP1CRS
EXTERNAL SYSDSP,.C0OK,.C1OK
XP DEDTIM,^D10000 ;TIME OUT TO GUARANTEE MASTER IS DEAD
CP1CRS: CONI APR,AP1STS ;SAVE APR STATUS FOR DUMP
CONI PI,.C1CPI## ;SAVE PI STATUS FOR DUMP
CONO PI,PI.OFF ;TURN OFF ALL INTERRUPTS DURING MASTER CRASH
IFN FTKI10,<
DATAI PAG,CP1EUB
>
IFN FTKL10,<
CONI PAG,CP1EPT ;SAVE EPT STATUS
DATAI PAG,CP1UPT ;AND UPT STATUS
EXECAC
;SWITCH TO EXEC ACS SO A PDP IS IN P,
; AND SO WE DON'T SMASH USER ACS
>
MOVEM 17,.C1CAC##+17 ;SAVE AC 17
IFN FT2SEGMON&FTMOFFL,<
SKIPE MOFLPG## ;SETTING MEMORY OFF
JRST CP1DI0 ;YES, JUST RELAX UNTIL ITS DONE
>
MPD1: AOSN 17,.C0OK ;START COUNTING UP MPOK
JRST MPDR ;MASTER IS GOING AGAIN (MPOK WAS -1)
CAIG 17,DEDTIM ;MASTER REALLY SICK NOW?
JRST MPD1 ;NOT YET
CP1DI0: MOVEI 17,.C1CAC## ;SAVE ALL AC'S
BLT 17,.C1CAC##+16
IFN FTKL10,<
PUSHJ P,CSDMP## ;MAKE SURE ITS ALL IN CORE FOR THE DUMP
>
CP1DI2:
IFN FTKL10,<
PUSHJ P,CSDMP## ;MAKE SURE ITS ALL IN CORE FOR THE DUMP
>
MOVE 17,[XWD ACLOOP,2] ;SET UP AC LOOP
BLT 17,17
MOVE .E1IL## ;SAVE 140
MOVEM SAV140 ;IN CASE WE CAN CONTINUE AGAIN
SETOM .E1IL## ;ZERO 140 (MASTER WILL SETOM 140 IF RESTARTED)
JRST 2 ;START LOOP IN AC'S
$LOW
MPD2:
IFN FT2SEGMON&FTMOFFL,<
MOVE P,.C1CAC##+P
PUSHJ P,MAPINI
>
MOVE SAV140 ;MASTER RECOVERED
MOVEM .E1IL## ;RESTORE 140
MOVSI 17,.C1CAC## ;AND THE AC'S
BLT 17,17
JRST MPDR1 ;AND RETURN TO CLOCK ROUTINE
MPDR: MOVE 17,.C1CAC##+17 ;RESTORE AC 17
MPDR1:
IFN FTKI10,<
DATAO PAG,CP1EUB ;RESTORE OLD UBR,EBR
>
IFN FTKL10,<
DATAO PAG,CP1UPT ;RESTORE OLD AC BLOCK, UPT
>;END IFN FTKL10
CONO PI,PI.ON ;RESTORE INTERRUPTS AGAIN
JRST AP1BCK## ;GO CONTINUE AGAIN WITH APR INTERRUPT FOR CPU1
ACLOOP: MOVEI 1,20 ;2 INITIALIZE ITERATION COUNT
MOVE 0,.C1OK ;3 GET CURRENT .C1OK
CAMN 0,.C1OK ;4 SEE IF .C1OK HAS CHANGED
JRST 4 ;5 NO, WAIT UNTIL IT DOES CHANGE
AOS 0 ;6 COUNT OLD .C1OK BY ONE
CAME 0,.C1OK ;7 DID .C1OK INCREASE BE EXACTLY ONE
JRST 2 ;10 NO, START OVER AGAIN
SOJG 1,4 ;11 WAIT FOR 20 COUNTS TO BE SURE
AOSE .E1IL## ;12 WAS 140 SET TO -1 BY MASTER
JRST SYSDSP ;13 YES, GO RESTART SLAVE
JRST MPD2 ;14 NO, JUST CONTINUE
INTERNAL SAV140
SAV140: 0 ;LOCATION OF 140 DURING A SLAVE CRASH
AP1STS::0 ;APR STATUS ON CRASH
IFN FTKI10,<
CP1EUB::0 ;EXEC USER BASE REG
CP0EUB::0 ;SAVE CPU0 BASE REG WHILE DOING STOPCD AS CPU1
>
IFN FTKL10,<
CP1EPT: 0 ;EXEC BASE REGISTER
CP1UPT: 0 ;USER BASE REGISTER
CP0UPT::0 ; AND USER BASE REG WHILE MASQUERADING
>
CP1HLT::0 ;SET TO -1 ON A CPU1 STOPCD
$HIGH
;INTERLOCK ROUTINES - LOKSCD, ULKSCD
;CALLED BY PUSHJ TO ENTER CODE WHICH MUST RUN TO COMPLETION
;ON THE CURRENT PROCESSOR BEFORE IT (OR ANY INTERLOCKED
;SECTIONS) IS ENTERED BY THE OTHER PROCESSOR.
;
; PUSHJ P,LOKSCD
; ...INTERLOCKED CODE...
; PUSHJ P,ULKSCD
;
;THERE IN FACT CAN EXIST SEVERAL LEVELS OF INTERLOCK, OF WHICH
;ONLY THE LOWEST LEVEL IS REAL, REST ARE VIRTUAL. NECESSARY
;BECAUSE OF THE EXISTENCE OF ROUTINES WHICH MUST THEMSELVES
;BE INTERLOCKED BUT WHICH ARE CALLED BOTH BY INTERLOCKED CODE
;AND UN-INTERLOCKED CODE. (EXAMPLE: QQXFER)
;THE LOCATIONS .C0SCD,.C1SCD SHOULD BE INITIALIZED TO -1
;AT SYSTEM STARTUP TIME.
INTERNAL LOKSCD,ULKSCD
EXTERNAL .C0SCD,.C1SCD,PION,PIOFF ;LOCS DEFINED IN COMMON
;HERE TO TURN ON INTERLOCK
LOKSCD: SKPCPU (0) ;TEST TRAP OFFSET BIT TO SEE WHICH PROCESSOR CALLED US
JRST LOCKS ;SLAVE PROCESSOR
;MASTER PROCESSOR LOKSCD ROUTINE
LOCKM: AOS .C0SCD ;REQUEST INTERLOCK
LOCKML: SKIPGE .C1SCD ;DOES THE SLAVE HAVE IT?
POPJ P, ;NO, RETURN
AOS .C0LLC## ;YES, COUNT NO. OF TIMES IN LOOP
IFN FTKL10,<
PUSHJ P,LOCKCR ;SWEEP CACHE IF NEEDED
>
JRST LOCKML ;WAIT FOR SLAVE
;SLAVE PROCESSOR LOKSCD ROUTINE
LOCKS: CONO PI,PIOFF ;THIS MAKES SLAVE INTERRUPT CALLS LEGAL
AOS .C1SCD ;REQUEST INTERRLOCK
SKIPGE .C0SCD ;DID WE GET IT?
JRST LOCKS2 ;YES
SOSL .C1SCD ;TAKE AWAY REQUEST
JRST LOCKS1 ;SLAVE ALREADY HAS INTERLOCK, ALL IS OK
CONO PI,PION ;WAIT FOR INTERLOCK TO BE FREE
LOCKSL: SKIPGE .C0SCD ;DOES MASTER HAVE IT?
JRST LOCKS ;NO, TRY AGAIN
AOS .C1LLC## ;YES, COUNT NO. OF TIMES IN LOOP
IFN FTKL10,<
PUSHJ P,LOCKCR ;SWEEP CACHE IF NEEDED
>
JRST LOCKSL ;WAIT FOR MASTER
LOCKS1: AOS .C1SCD ;COUNT LEVEL UP AGAIN
LOCKS2: CONO PI,PION ;TRUN ON PI AGAIN
POPJ P, ;AND RETURN
;HERE TO TURN OFF INTERLOCK
ULKSCD: SKPCPU (0) ;WHICH PROCESSOR?
JRST UNLOKS ;SLAVE
;MASTER PROCESSOR ULKSCD ROUTINE
UNLOKM: SKIPGE .C0SCD ;TEST INTERLOCK LEVEL
STOPCD CPOPJ,DEBUG,MAU, ;++MASTER ALREADY UNLOCKED
SOS .C0SCD ;DECREMENT LEVEL
UNLKM1: POPJ P, ;AND RETURN
;SLAVE PROCESSOR ULKSCD ROUTINE
UNLOKS: SKIPGE .C1SCD ;TEST LEVEL
STOPCD CPOPJ,DEBUG,SAU, ;++SLAVE ALREADY UNLOCKED
SOS .C1SCD ;DECREMENT LEVEL
UNLKS1: POPJ P, ;AND RETURN
IFN FTKL10,<
;SUBROUTINE TO CHECK FOR CACHE SWEEP REQUEST WHILE
; WAITING FOR THE SCHEDULAR INTERLOCK
LOCKCR: PUSHJ P,SCPCDB## ;SAVE AND SETUP P4
PUSH P,T1 ;SAVE T1
PUSHJ P,CSREQS ;SWEEP CACHE IF REQUESTED
PJRST TPOPJ## ;RESTORE T1 AND RETURN
>
;CODE TO IMPLEMENT THE SETUUO'S NUMBER 14 (.STCPU)
;AND 15 (.STRUN)
INTERN SETCRN
SETCRN: MOVEI T4,.C0CDB ;ADDRESS OF FIRST CDB
TRZ T2,777700 ;GET ONLY BITS OF INTEREST
SETCR1: MOVE T3,.CPRUN(T4) ;GET RUN BIT FOR CPU
TRNE T2,1 ;CHECK BIT FOR CPU RUNNABILITY
TLZA T3,400000 ;CLEAR SIGN BIT TO ALLOW CPU TO RUN
TLO T3,400000 ;SET SIGNBIT TO TURN CPU OFF
MOVEM T3,.CPRUN(T4) ;PUT BACK IN CDB
HLRZ T4,.CPCDB(T4) ;GET ADDRESS OF NEXT CDB
PJUMPE T4,CPOPJ1 ;NO ERROR RETURNS
LSH T2,-1 ;MOVE NEXT BIT TO 35
JRST SETCR1 ;AND CHECK OUT THIS ONE
.ERNAR==0 ;NONE ARE RUNNING ERROR CODE
.ERDHP==1 ;DOESN'T HAVE PRIVILEGES ERROR
;ROUTINE TO HANDLE SETUUO #14 (.STCPU) USER SET
;CPU SPECIFICATION
INTERN SETCPU
SETCPU: MOVSI T3,JP.CCC ;CAN CHANGE CPU SPECIFICATION BIT
TDNE T3,JBTPRV(J) ;USER PRIVILEGED TO CHANGE?
JRST SETCP1 ;YES, PROCEED
PUSHJ P,PRVJ## ;NO, IS HE [1,2] OR IS JACCT SET?
JRST SETCP1 ;YES, OK TO PROCEED
MOVEI T1,.ERDHP ;NO, GIVE ERROR RETURN
PJRST STOTAC ;WITH DOESN'T HAVE PRIVILEGE CODE
SETCP1: MOVE T1,T2 ;HOLD BITS IN T1
MOVEI T4,.C0CDB ;GET ADDRESS OF CPU0 CDB
TRZ T2,777700 ;EXTRACT THE BITS WE WANT
SETCP2: TRNE T2,1 ;DO WE CARE ABOUT THIS CPU?
SKIPGE .CPRUN(T4) ;YES, IS IT RUNNING?
JRST SETCP3 ;NO, CHECK NEXT
DPB T1,[POINT 6,JBTSPS(J),35] ;YES, WE ARE SATISFIED.
JRST CPOPJ1 ;AND SKIP RETURN
SETCP3: HLRZ T4,.CPCDB(T4) ;GET ADDRESS OF NEXT CDB
JUMPE T4,SETCP4 ;IF NO MORE, ERROR
LSH T2,-1 ;MOVE NEXT BIT INTO POSITION
JRST SETCP2
SETCP4: MOVEI T1,.ERNAR ;GET NONE ARE RUNNING CODE
PJRST STOTAC ;GIVE TO USER AND CPOPJ
INTERNAL CPUCMD
CPUCMD: PUSHJ P,SAVE1## ;SAVE P1
MOVSI P1,JP.CCC ;GET CAN CHANGE CPU SPECIFICATION BIT
PUSHJ P,SETLGL## ;IS THIS THE OPR OR A [1,2] JOB,
TDNE P1,JBTPRV(J) ; OR DOES THE JOB HAVE PRIVILEGES?
JRST CPUCM1 ;YES, PROCEED
PJSP T1,ERRMES## ;NO, ERROR MESSAGE
ASCIZ /No privileges to SET CPU
/
CPUCM1: PUSHJ P,CTEXT## ;GET NEXT ARGUMENT
MOVE P1,T2 ;SAVE IN P1
PUSHJ P,CPUFND ;SEE IF IT IS CPXN
JRST CPUCM2 ;NO, GET REST OF COMMAND
IORM T3,JBTSPS(J) ;WAS SET CPU CPXN, BITS IN T3
JRST CPUCM5 ;AND RETURN
CPUCM2: PUSHJ P,CTEXT## ;GET NEXT ARGUMENT
JUMPE T2,CPUCM4 ;NO MORE, MUST BE SET CPU ALL
PUSHJ P,CPUFND ;FIND CPU AND SET MASK BITS
PJRST COMERR ;NOT FOUND, ERROR
CAME P1,[SIXBIT /NO/] ;WAS THIRD ARGUMENT "NO"?
JRST CPUCM3 ;NO, CHECK OTHERS
ANDCAM T3,JBTSPS(J) ;YES, CHANGE SPECIFICATION
JRST CPUCM5 ;AND RETURN
CPUCM3: CAME P1,[SIXBIT /ONLY/] ;WAS THIRD ARGUMENT ONLY?
PJRST COMERR ;NO, ERROR
DPB T3,[POINT 12,JBTSPS(J),35] ;CHANGE SPECIFICATION
JRST CPUCM5 ;AND RETURN.
CPUCM4: CAME P1,[SIXBIT/ALL/];ARGUMENT #3 MUST BE "ALL"
PJRST COMERR ;WASN'T, ERROR
MOVEI T3,7777 ;GET BITS FOR ALL POSSIBLE CPU'S
DPB T3,[POINT 12,JBTSPS(J),35] ;CHANGE SPECIFICATION
CPUCM5: PUSHJ P,CPRONE ;CHECK TO SEE IF NEW SPECIFICATION IS VALID
PJRST CPOPJ1 ;AND RETURN
;SUBROUTINE TO DETERMINE IF CPU DESIGNATOR IN SET CPU COMMAND
;IS LOGICAL OR PHYSICAL CPU NAME. IF PHYSICAL, MAKE SURE IT EXISTS AND
;SET UP BIT MASK FOR JBTSPS. CALLED WITH SIXBIT ARGUMENT IN T2, BIT MASK
;RETURNED IN AC T3. T4 RESPECTED.
CPUFND: HLLZ T1,T2 ;GET LEFT MOST 3 CHARACTERS
CAMN T1,[SIXBIT /CPU/] ;IS ARGUMENT LOGICAL NAME?
JRST CPUFN2 ;YES, DOESN'T MATTER IF IT EXISTS
MOVEI T3,.C0CDB ;GET ADDRESS OF FIRST CDB
CPUFN1: CAMN T2,.CPPHY(T3) ;THIS CPU?
JRST CPUFN2 ;YES, OK TO PROCEED
HLRZ T3,.CPCDB(T3) ;GET ADDRESS OF NEXT CDB
JUMPE T3,CPOPJ ;NON-SKIP RETURN IF NON EXISTANT
JRST CPUFN1 ;GO LOOK AT NEXT
CPUFN2: HRRZ T1,T2 ;CPU NAME OK, MAKE A BIT MASK
LSH T1,-14 ;GET SIXBIT NUMBER RIGHT JUSTIFIED
SUBI T1,20 ;REDUCE TO BINARY
CAIG T1,5 ;LEGAL CPU NUMBER?
SKIPGE T1 ;
POPJ P, ;ERROR RETURN IF NON EXISTANT
MOVEI T3,101 ;MASK FOR CPU0
CPUFN3: SOJL T1,CPOPJ1 ;EXIT WHEN MASK IN RIGHT POSITION
LSH T3,1 ;NOT THIS CPU, SHIFT LEFT
JRST CPUFN3 ;AND PROCEED
;SUBROUTINE CALLED BY SIMCHK IN CLOCK1 TO SEE IF JOB WITH EXEC
;MODE PC HAS A RUNNABLE CPU SPECIFICATION. RETURN CPOPJ IF NONE, CPOPJ1 IF RUNNABLE
INTERNAL CPSCHK
CPSCHK: PUSHJ P,CPRBIT ;SET UP MASK OF RUNNING CPU'S
TDNN T2,JBTSPS(J) ;SKIP IF JOB HAS A RUNNABLE CPU
POPJ P, ;NO RUNNABLE CPU'S, STOP JOB
MOVE T2,JBTSPS(J) ;PICK UP SECOND PROCESSOR STATUS
TLNE T2,(SP.CC1) ;SKIP IF CONTROL C NOT ON CPU1
TLNE T2,(SP.NR1) ;WAS ON CPU1, SKIP IF NOT IN MIDDLE OF UUO
JRST CPOPJ1 ;IS RUNNABLE, CATCH AT UUO EXIT
TRNN T2,SP.CR0 ;SINCE CAN'T RUN ON CPU1, SKIP IF RUNNABLE ONCPU0
POPJ P, ;IS NOT RUNNABLE, STOP JOB.
JRST CPOPJ1 ;JOB IS RUNNABLE, DEFER STOPPING.
;SUBROUTINE TO BUILD A BIT MASK FOR TESTING JBTSPS ENTRIES. AN
;APPROPRIATE BIT IS SET FOR EACH RUNNING CPU. RETURNS MASK IN T2.
CPRBIT: MOVEI T4,.C0CDB ;GET ADDRESS OF FIRST CDB
MOVEI T3,1 ;GET BIT INDICATING CPU0 IS RUNNING
SETZ T2, ;CLEAR T2
CPRBT1: SKIPL .CPRUN(T4) ;SKIP IF CPU NOT RUNNING
ADD T2,T3 ;SET BIT IN MASK
HLRZ T4,.CPCDB(T4) ;GET ADDRESS OF NEXT CDB
JUMPE T4,CPOPJ ;EXIT IF THROUGH
LSH T3,1 ;MOVE BIT TO NEXT POSITION
JRST CPRBT1 ;AND LOOK AT NEXT CPU
;SUBROUTINE TO CHECK IF A JOB IS RUNNABLE ON ANY PROCESSOR CALLED
;WITH MASK OF RUNNING PROCESSORS IN AC T2 AND JOB NUMBER TO CHECK IN J.
CPRCHK: TDNE T2,JBTSPS(J) ;SKIP IF NO RUNNABLE CPU FOR THIS JOB
POPJ P, ;OK, RETURN
MOVE U,TTYTAB##(J) ;GET TTY DDB
HRRZ U,DDBLDB##(U) ;LDB ADDRESS
PJSP T1,CONMES## ;PRINT MESSAGE TO USER AND CPOPJ
ASCIZ /%No Running CPU's in specification
/
CPRONE: PUSHJ P,CPRBIT ;SET UP MASK OF RUNNING CPU'S
PJRST CPRCHK ;CHECK TO SEE IF WE HAVE ONE RUNNING
CPRMIN: PUSHJ P,CPRBIT ;GET MASK FOR TESTING JBTSPS
SKIPLE J,HIGHJB## ;GET HIGHEST USED JOB NUMBER
; -1 IF NO JOBS HAVE LOGGED IN YET
PUSHJ P,CPRCHK ;CHECK TO SEE IF RUNNABLE ON SOME CPU
SOJG J,.-1 ;NEXT?
POPJ P, ;NO, EXIT
;SUBROUTINE TO RETURN CPU SPECIFICATION TO THAT SET
;BY LAST "SET CPU" COMMAND. CALLED FROM "RESET" IN UUOCON
INTERN CRESET
;SUB TO MAKE JOB RUNABLE ON ALL CPUS
;CLEARING BITS IN LH OF JBTSPS(CALLED FROM COMCON ON KJOB SO LOGOUT CAN RUN
; NO MATER WHAT CPU SPECIFICATION USER MAY HAVE CHANGED TO)
ALLJSP::SKIPA T1,ALCPUS ;MAKE JOB RUNABLE ON ALL CPUS
; SKIP INTO CRESET
CRESET: LDB T1,[POINT 6,JBTSPS(J),29] ;GET LAST COMMAND SET SPECIFICATION
DPB T1,[POINT 6,JBTSPS(J),35] ;OVERRIDE LAST SETUUO
ALCPUS: POPJ P,<SP.CR0+SP.CR1>B29+SP.CR0+SP.CR1 ;CAN RUN ON CPU0 AND 1
REPEAT 0,< ;IF "SBLOK (SCD)" IS EVER USED, REMOVE THIS CONDITIONAL
;ROUTINE TO LOKSCD, DISPATCH, ULKSCD, AND RETURN.
;CALLED FROM ANY ROUTINE WHICH IS CALLED BY A PUSHJ
;AND EXPECTS TO RETURN WITH POPJ OR AOS (P), POPJ.
INTERNAL SBSCD
SBSCD: PUSHJ P,LOKSCD ;TURN ON INTERLOCK
PUSHJ P,@(P) ;DISPATCH TO ROUTINE
SKIPA
AOS -1(P) ;PROVIDE FOR SKIP RETURN
POP P,XXXX ;FIX PUSHDOWN TO RETURN TO ORIGINAL CALLER
JRST ULKSCD ;TURN OFF INTERLOCK AND RETURN WITH POPJ
XXXX: 0 ;(LOC TO HOLD JUNK)
>
INTERN SVMES
$LOW
CP1ERR: 0 ;LOCATION FOR WAITING FOR A PARITY ERROR TO BE HANDLED
SVMES: 0 ;XWD JOB#,ADR OF MESSAGE FOR MASTER TO TYPE
$HIGH
$LIT ;GENERATE LITERALS SO CAN CHECK ASCII OCTAL
CL2END: END