Google
 

Trailing-Edge - PDP-10 Archives - BB-K911B-SM - sources/sched.mac
There are 52 other files named sched.mac in the archive. Click here to see a list.
; UPD ID= 269, SNARK:<4.MONITOR>SCHED.MAC.330,  18-Feb-80 14:20:55 by MURPHY
;FIX POSSIBLE J0NRUN FROM STICKY PIBMP
; UPD ID= 257, SNARK:<4.MONITOR>SCHED.MAC.329,  11-Feb-80 16:09:08 by BLOUNT
; UPD ID= 256, SNARK:<4.MONITOR>SCHED.MAC.328,  10-Feb-80 22:16:34 by MURPHY
;FIX NEWST
;<4.MONITOR>SCHED.MAC.327,  3-Jan-80 08:10:27, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;<4.MONITOR>SCHED.MAC.326, 26-Nov-79 11:45:05, EDIT BY MURPHY
;AT HLTFK2 SET SCHED CONTEXT AFTER DELETE OF FORK
;<4.MONITOR>SCHED.MAC.325,  8-Nov-79 12:22:03, EDIT BY MURPHY
;FIX AC CLOBBERAGE ON ERJMP CERTAIN CASES
;<4.MONITOR>SCHED.MAC.324, 31-Oct-79 14:18:19, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.323, 30-Oct-79 12:31:00, EDIT BY MILLER
;CHARGE BALSET HOLD TIME FOR SWAP READS AS WELL AS FILE READS
;<4.MONITOR>SCHED.MAC.322, 29-Oct-79 11:22:00, EDIT BY MILLER
;CHANGE CODE AT MENT2 TO PRESERVE NOINT IN DIAG JSYS
;<4.MONITOR>SCHED.MAC.321, 25-Oct-79 14:06:02, EDIT BY MURPHY
;TTOLST FOR FASTER WAKEUP ON TTY OUTPUT
;<4.MONITOR>SCHED.MAC.318, 24-Oct-79 12:57:13, EDIT BY GRANT
;ADD 20 MS TASK FOR RCVOK TIMER
;<4.MONITOR>SCHED.MAC.317, 24-Oct-79 10:28:02, EDIT BY MURPHY
;APSKED, BSCRSK REVISIONS, SETPCV.
;<4.MONITOR>SCHED.MAC.315, 19-Oct-79 17:20:33, EDIT BY MURPHY
;BALSET HOLD TIME ADJUSTMENTS
;<4.MONITOR>SCHED.MAC.314, 18-Oct-79 12:46:01, EDIT BY MILLER
;REMOVE CODE AT SCHED0 THAT CHECKS CRSKED.
;<4.MONITOR>SCHED.MAC.313, 15-Oct-79 13:02:57, EDIT BY MILLER
;GIVE PSBUMP IN SPIRQ EVEN IF PROCESS IS BLOCKED
;<4.MONITOR>SCHED.MAC.312, 15-Oct-79 10:15:22, EDIT BY MILLER
;FIX COMPUTATION IN CHKSNP
;<4.MONITOR>SCHED.MAC.311, 12-Oct-79 17:29:14, EDIT BY MURPHY
;IGNORE SECTION NUMBER IN CHKSNP
;<4.MONITOR>SCHED.MAC.310, 28-Sep-79 12:41:37, EDIT BY MILLER
;ONE MORE TRY. APPLY SIR SECTION TO CHANNEL ROUTINE AS WELL
;<4.MONITOR>SCHED.MAC.309, 28-Sep-79 12:31:41, EDIT BY MILLER
;FIX CODE AROUND DEBRKS TO APPLY SECTION TO INTERRUPT PC
;<4.MONITOR>SCHED.MAC.308, 27-Sep-79 15:53:36, EDIT BY MILLER
;FIX CODE AT PSIS5 TO DISALLOW INTS FROM OTHER THAN PC SIR SECTION
;<4.MONITOR>SCHED.MAC.307, 21-Sep-79 13:38:43, EDIT BY MURPHY
;CSKED - ALLOW SCHED SUBTASKS TO RUN (BUGS IN FORK.MAC NOW FIXED)
;<4.MONITOR>SCHED.MAC.306, 20-Sep-79 11:52:46, EDIT BY MILLER
;MAKE SET JOB CLASS ALWAYS DO GTOKM
;<4.MONITOR>SCHED.MAC.305, 13-Sep-79 13:32:34, EDIT BY MILLER
;PARAMETERIZE MINIMUM CLASS SHARE AND ATTENDANT VALUES
;<4.MONITOR>SCHED.MAC.304, 13-Sep-79 12:48:11, EDIT BY MILLER
;FIX .SKED COMPUTATION TO USE FAD INSTEAD OF FADR
;<OSMAN.MON>SCHED.MAC.1, 10-Sep-79 16:04:00, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>SCHED.MAC.302,  7-Sep-79 10:10:57, EDIT BY MURPHY
;PUT CRSKED BACK, FIXES TO ERJMP STUFF
;<4.MONITOR>SCHED.MAC.301, 30-Aug-79 12:12:01, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.300, 29-Aug-79 15:10:03, EDIT BY MURPHY
;BETTER DETECTION OF ERJMP/ERCAL USAGE IN NESTED JSYSES
;<4.MONITOR>SCHED.MAC.299, 29-Aug-79 09:32:57, EDIT BY MILLER
;CHANGE PSII TO PRESERVE PENDING INTS IF FORK IS HALTED
;<4.MONITOR>SCHED.MAC.298, 28-Aug-79 15:49:43, EDIT BY MURPHY
;CSKED HANDLING - ALLOW SCHEDULER SUBTASKS TO RUN
;<4.MONITOR>SCHED.MAC.297, 27-Aug-79 13:57:48, EDIT BY MILLER
;CORRECT CODE AT CORF55
;<4.MONITOR>SCHED.MAC.296, 26-Aug-79 20:09:44, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.295, 26-Aug-79 20:02:21, EDIT BY MILLER
;USE SK%HT2 TO DETERMINE IF NO HOLD TIME FOR SKIPPED PROCESS
;<4.MONITOR>SCHED.MAC.293, 25-Aug-79 09:07:26, EDIT BY MILLER
;init mjrstf in skhwpt to be a bughlt
;<4.MONITOR>SCHED.MAC.292, 21-Aug-79 12:24:45, EDIT BY MILLER
;BE SURE PROCESS LOADED BECAUSE OF CRSKED OR PIBMP
; GETS NO HOLD TIME
;<4.MONITOR>SCHED.MAC.291, 20-Aug-79 13:34:50, EDIT BY MILLER
;CHANGE CODE @PSIS5 AND @DEBRK1 TO FORCE SECTION 0 ADDRESS IF OLD
; STYLE SIR DONE
;<4.MONITOR>SCHED.MAC.290, 19-Aug-79 18:06:26, EDIT BY GILBERT
;CHANGE FKIBSH TO FKIBH TO AVOID CONFLICT WITH FKIBS.
;<4.MONITOR>SCHED.MAC.289, 16-Aug-79 13:42:37, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.288, 16-Aug-79 13:20:25, EDIT BY DBELL
;TCO 4.2405 - INITIALIZE CRSKED ON ENTRY TO TOP-LEVEL JSYS
;<4.MONITOR>SCHED.MAC.287, 16-Aug-79 07:18:50, EDIT BY MILLER
;ONE MORE TIME
;<4.MONITOR>SCHED.MAC.286, 15-Aug-79 17:11:12, EDIT BY MILLER
;CORFC1 AGAIN. IF CLASS IN WINDFALL, INTQ PROCESSES GET SMALL BOOST
;<4.MONITOR>SCHED.MAC.285, 15-Aug-79 15:44:28, EDIT BY MILLER
;FIX CORFC1 TO NOT BOOST QUEUE 2 PROCESS IF ITS CLASS IS GETTING WINDFALL
;<4.MONITOR>SCHED.MAC.284, 14-Aug-79 10:09:19, EDIT BY MILLER
;DON'T HONOR SK%RQ1 IF PROCESS HAS SPECIAL PRIORITY
;<4.MONITOR>SCHED.MAC.283,  9-Aug-79 12:45:26, EDIT BY MILLER
;USE JOB LOAD AVGS
;<4.MONITOR>SCHED.MAC.282,  8-Aug-79 16:39:24, EDIT BY MILLER
;HANDLE .SAWA ARG TO "SET CLASS SHARE" FUNCTION OF SKED
;<4.MONITOR>SCHED.MAC.281, 30-Jul-79 09:30:24, EDIT BY MILLER
;DON'T MAKE CHECK FOR JOB 0 IN AJBALS
;<4.MONITOR>SCHED.MAC.280, 24-Jul-79 14:11:50, EDIT BY MILLER
;INIT QUANTT ACCORDING TO SCHEDULER SETTINGS
;<4.MONITOR>SCHED.MAC.279, 19-Jul-79 08:36:07, EDIT BY MILLER
;FIX CLDRJ TO DO LOAD AVG COMPUTATION BETTER
;<4.MONITOR>SCHED.MAC.278, 13-Jul-79 11:38:27, EDIT BY HALL
;CHANGES FOR USER MODE-EXTENDED ADDRESSING:
; DEBRK - FORCE PCS TO 1
; PSII - CHANGE INDEXED PREVIOUS CONTEXT REFERENCES TO INDIRECT
; TO ALLOW GLOBAL REFERENCING OF ALL SECTIONS INCLUDING 0
; (0 IN LH WOULD BE LOCAL IF INDEXED)
; CHANGE PSII FOR EXTENDED SIR STUFF
;<4.MONITOR>SCHED.MAC.277, 15-Jun-79 12:08:58, EDIT BY MURPHY
;REMOVE CALL TO WSMGR IN TRYLDF
;<4.MONITOR>SCHED.MAC.276, 23-May-79 13:59:12, EDIT BY HALL
;COMMENTS ONLY
;<4.MONITOR>SCHED.MAC.275,  2-May-79 14:41:45, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.274,  2-May-79 14:35:45, EDIT BY MILLER
;ALLOW LOADING OF JOB 0 FORK AT AJBAL6. ALSO, LIMIT BAL SET HOLD
; IF CLASS SCHEDULE TO NEWUTL CYCLE (AT SETIBS)
;<4.MONITOR>SCHED.MAC.273,  2-May-79 10:15:03, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.272,  1-May-79 16:53:16, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.271,  1-May-79 15:38:29, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.271,  1-May-79 14:31:24, EDIT BY MILLER
;FIX AJABLS NOT TO LOAD A PROCESS OF LOWER PRIORITY THAN ONE
; THAT WAS SKIPPED WHEN THE CLASS SCHEDULER IS ON
;<4.MONITOR>SCHED.MAC.270,  1-May-79 12:16:50, EDIT BY MILLER
;DON'T ASSIGN HOLD TIME TO PROCESS IF ANOTHER WAS SKIPPED
;<4.MONITOR>SCHED.MAC.269,  1-May-79 08:46:40, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.268, 30-Apr-79 17:54:01, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.267, 30-Apr-79 17:52:24, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.266, 30-Apr-79 13:03:24, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.265, 28-Apr-79 12:54:38, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.264, 26-Apr-79 16:46:55, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.263, 26-Apr-79 16:13:09, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.262, 26-Apr-79 13:40:12, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.261, 26-Apr-79 11:32:31, EDIT BY MILLER
;SAVE T4 ACROSS CALL TO REMWS AT AJBAL12
;<4.MONITOR>SCHED.MAC.260, 26-Apr-79 11:07:54, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.259, 26-Apr-79 10:58:44, EDIT BY MILLER
;FIX AJBALS TO LOAD OR KEEP IF PROCESS IS CSKED
;<4.MONITOR>SCHED.MAC.258, 25-Apr-79 16:55:46, EDIT BY MILLER
;MORE FIXES TO AJBALS AND TRYLDF TO ALLOW LOADING IF PIBMP IS ON
;<4.MONITOR>SCHED.MAC.257, 25-Apr-79 16:20:00, EDIT BY MILLER
;REMOVE .SKSSD FUNCTION OF SKED
;<4.MONITOR>SCHED.MAC.256, 25-Apr-79 11:51:12, EDIT BY MILLER
;CHANGE CORFCT TO COMPUTE PIBMP PRIORITY DIFFERENTLY
; CHNAGE AJBALS TO ALWAYS KEEP A PIBMP PROCESS EVEN IF AJHQOF IS SET
;<4.MONITOR>SCHED.MAC.255, 24-Apr-79 13:54:13, EDIT BY OSMAN
;FIX SETTING BATCH CLASS (CORRECT TEST FOR VALID CLASS, CORRECT ERROR CODE)
;<4.MONITOR>SCHED.MAC.254, 20-Apr-79 14:40:43, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.253, 17-Apr-79 10:40:24, EDIT BY MILLER
;ADD CHECK FOR INTERRUPTABILITY AT PSISV0
;<4.MONITOR>SCHED.MAC.252, 14-Apr-79 13:17:52, EDIT BY MILLER
;FIX UP CODE FOR JOB LOAD AVERGES
;<4.MONITOR>SCHED.MAC.251, 13-Apr-79 16:50:20, EDIT BY MURPHY
;ONE MORE TIME ON ILIST
;<4.MONITOR>SCHED.MAC.250, 13-Apr-79 11:30:48, EDIT BY BOSACK
;CLEAR FULLWORD AT LIST END IN ILIST
;<4.MONITOR>SCHED.MAC.249, 13-Apr-79 11:07:25, EDIT BY MILLER
;CHECK FOR HIGH Q EARLY IN NEWST AND AVOID EXECUTING NEDLESS INSTRUCTIONS
;<4.MONITOR>SCHED.MAC.248, 12-Apr-79 13:03:23, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.247, 12-Apr-79 11:08:31, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.246, 11-Apr-79 15:13:32, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.245, 11-Apr-79 14:48:21, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.244, 11-Apr-79 14:41:26, EDIT BY MILLER
;BE SURE BUMP PRIORITY IS REMOVED AT UNPIR
;<4.MONITOR>SCHED.MAC.243, 10-Apr-79 15:48:31, EDIT BY MILLER
;DO A "SOS NBSWP" WHEN PRELOAD TEST SUCCEEDS
;<4.MONITOR>SCHED.MAC.242, 10-Apr-79 13:24:34, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.241, 10-Apr-79 12:13:50, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.240, 10-Apr-79 11:43:14, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.239, 10-Apr-79 11:32:00, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.238, 10-Apr-79 10:20:25, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.237,  5-Apr-79 11:17:03, Edit by MCLEAN
;REMOVE FIRST ARG FROM GTOKM
;<4.MONITOR>SCHED.MAC.236,  4-Apr-79 09:08:38, EDIT BY MILLER
;CHANGE PIBMP PRIORITY COMPUTATON
;<4.MONITOR>SCHED.MAC.235,  3-Apr-79 14:29:08, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.234,  3-Apr-79 10:46:31, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.233,  3-Apr-79 10:44:23, EDIT BY MILLER
;FIX UP HANDLING OF MJBUSE. DON'T PRELOAD FORK IF DOING A PSI
;<4.MONITOR>SCHED.MAC.232,  1-Apr-79 14:37:54, EDIT BY MILLER
;MORE PSI FIXES
;<4.MONITOR>SCHED.MAC.231,  1-Apr-79 13:47:33, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.230,  1-Apr-79 13:30:25, EDIT BY MILLER
;FIX UP PRIORITY CALCULATIONS. USE PIBMP FOR PI BOOSTING
;<4.MONITOR>SCHED.MAC.229, 31-Mar-79 13:55:24, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.228, 31-Mar-79 13:49:32, EDIT BY MILLER
;MORE FIXES TO NEWUTL
;<4.MONITOR>SCHED.MAC.227, 31-Mar-79 13:15:39, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.226, 29-Mar-79 18:20:49, EDIT BY BOSACK
;FIX CORFCT SO THAT CRSKED IS HIGHER PRIORITY THAN QUEUE 0 OR 1
;<4.MONITOR>SCHED.MAC.225, 29-Mar-79 17:33:33, EDIT BY MILLER
;ADJUST CLASS PARAMETERS WHEN A JOB LOGS OUT
;<4.MONITOR>SCHED.MAC.224, 29-Mar-79 11:40:59, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.223, 29-Mar-79 11:23:50, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.222, 29-Mar-79 11:19:37, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.221, 29-Mar-79 10:35:38, EDIT BY MILLER
;FIX NEWUTL COMPUTATIONS
;<4.MONITOR>SCHED.MAC.220, 28-Mar-79 13:35:42, EDIT BY MILLER
;ZERO JOBIRT AT JOBSRT. REMOVE CALL TO ADJCLS @ NEWUTL
;<4.MONITOR>SCHED.MAC.219, 27-Mar-79 13:40:51, EDIT BY MILLER
;FIX SKDSJC TO ALLOW THIS JOB
;<4.MONITOR>SCHED.MAC.218, 26-Mar-79 13:17:52, EDIT BY MILLER
;ONE MORE TRY
;<4.MONITOR>SCHED.MAC.217, 26-Mar-79 12:35:13, EDIT BY MILLER
;CHANGE ARGS ON GTOKM FOR .GOCLS
;<4.MONITOR>SCHED.MAC.216, 23-Mar-79 10:29:53, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.215, 21-Mar-79 17:41:40, EDIT BY MILLER
;MAKE SURE JOBCLS IS CORRECT AT JOBSRT
;<4.MONITOR>SCHED.MAC.214, 20-Mar-79 18:26:37, EDIT BY MURPHY
;PERFORMANCE - RPLQ LOW LOGIC
;<4.MONITOR>SCHED.MAC.212, 13-Mar-79 17:10:02, EDIT BY HURLEY
;FIX GTOKM TO HAVE A LEADING 0 ARGUMENT
;<4.MONITOR>SCHED.MAC.211, 13-Mar-79 10:37:17, EDIT BY MILLER
;ALLOW 0 PERCENTAGE TO BE GIVEN TO A CLASS
;<4.MONITOR>SCHED.MAC.210, 11-Mar-79 12:54:43, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.MONITOR>SCHED.MAC.209,  9-Mar-79 16:38:59, EDIT BY MURPHY
;ELIMINATE SWAPOUT OF PSB, UPT WHEN FORK KILLED
;<4.MONITOR>SCHED.MAC.208,  9-Mar-79 13:53:30, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.207,  9-Mar-79 13:16:24, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.206,  9-Mar-79 11:58:13, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.205,  9-Mar-79 11:17:37, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.204,  8-Mar-79 15:57:31, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.203,  8-Mar-79 14:56:23, EDIT BY MILLER
;IMPROVE CHGCLS
;<4.MONITOR>SCHED.MAC.202,  8-Mar-79 11:24:53, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.201,  7-Mar-79 17:26:05, EDIT BY MILLER
;CHANGE CORFCT TO INCLUDE QUEUE 2 IN THE CLASS "INTERACTIVE" SET
;<4.MONITOR>SCHED.MAC.200,  7-Mar-79 12:50:25, EDIT BY MILLER
;DON'T HONOR SK%HQR IF USING CLASS SCHEDULER
;<4.MONITOR>SCHED.MAC.199,  6-Mar-79 10:58:13, EDIT BY OSMAN
;tco 4.2202 - SK%DRG, change u/s order in .SKRCV
;<4.MONITOR>SCHED.MAC.198,  5-Mar-79 20:05:10, EDIT BY MURPHY
;FIX PRELOAD BUG
;<4.MONITOR>SCHED.MAC.197,  4-Mar-79 13:46:14, EDIT BY MILLER
;MAKE SURE CLASS SURE IS>= .5%
;<4.MONITOR>SCHED.MAC.196,  2-Mar-79 17:48:52, EDIT BY MURPHY
;PREVENT CRSKED FORKS FROM LOCKING OUT HIGHQ FORKS
;<4.MONITOR>SCHED.MAC.195,  2-Mar-79 16:45:25, Edit by MCLEAN
;ADD NEW ERROR CODES FOR SKED%
;<4.MONITOR>SCHED.MAC.194,  1-Mar-79 15:19:01, EDIT BY BOSACK
;MAKE INTERACTIVE BIAS WITHIN CLASS SOMEWHAT STRONGER
;<4.MONITOR>SCHED.MAC.193,  1-Mar-79 13:39:34, EDIT BY OSMAN
;USE ARG BLOCK OFFSET SYMBOLS IN SKED% JSYS
;<4.MONITOR>SCHED.MAC.192,  1-Mar-79 10:47:36, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.191, 28-Feb-79 12:27:58, EDIT BY MILLER
;FIX CLDRJ
;<4.MONITOR>SCHED.MAC.190, 27-Feb-79 15:58:47, Edit by MCLEAN
;MAKE  .SKRCS RETURN LOAD AVERAGES ALSO
;<4.MONITOR>SCHED.MAC.189, 27-Feb-79 14:41:22, EDIT BY MILLER
;FIX CHGCLS TO RECOMPUTE CLASS GOLST COUNTS FOR OLD AND NEW CLASSES
;<4.MONITOR>SCHED.MAC.188, 19-Feb-79 23:22:17, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.187, 13-Feb-79 16:58:26, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.186,  4-Feb-79 23:05:58, EDIT BY MURPHY
;PERFORMANCE TUNING
;<4.UTILITIES>SCHED.MAC.1,  9-Jan-79 10:41:51, EDIT BY HALL
;FIX COUNT
;<4.MONITOR>SCHED.MAC.184,  8-Jan-79 13:46:28, EDIT BY MILLER
;ONCE AGAIN, FIX UP CLASS LOAD AVG COMPUTATION
;<4.MONITOR>SCHED.MAC.183,  8-Jan-79 06:58:56, EDIT BY GILBERT
;TCO 4.2155 - Implement hidden symbol tables:
;	Change PSECT bounds name.
;<4.MONITOR>SCHED.MAC.182,  7-Jan-79 23:55:21, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.178,  5-Jan-79 11:15:03, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.177,  4-Jan-79 15:38:23, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.176,  3-Jan-79 10:57:17, EDIT BY MILLER
;FIX CLASS LOAD AVG COMPUTATION
;<4.MONITOR>SCHED.MAC.175,  3-Jan-79 10:40:13, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.174,  3-Jan-79 10:31:48, EDIT BY MILLER
;<MURPHY.MON>SCHED.MAC.6,  4-Jan-79 14:46:11, EDIT BY MURPHY
;NEW HOLD LOGIC
;<4.MONITOR>SCHED.MAC.173,  2-Jan-79 17:24:18, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.172,  2-Jan-79 12:45:20, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.171,  2-Jan-79 10:24:57, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.170,  2-Jan-79 10:17:31, EDIT BY MILLER
;MAKE FIXED FOR CLASS SCHEDULER
;<4.MONITOR>SCHED.MAC.169, 29-Dec-78 12:29:50, EDIT BY MURPHY
;REVISE QUANTUM TIMES
;<4.MONITOR>SCHED.MAC.167, 29-Dec-78 11:17:53, EDIT BY MILLER
;COMPUTE ON-GOLST COUNT PER CLASS. NEEDED IN LOAD AVERAGE COMPUTATION
;<MURPHY.MON>SCHED.MAC.1, 27-Dec-78 15:25:55, EDIT BY MURPHY
;REMOVE PUFLD AND CORE NUMBERS
;ENSURE ADEQUATE STACK AT TRYLDF
;<4.MONITOR>SCHED.MAC.162, 21-Dec-78 14:38:42, EDIT BY MILLER
;DO SAME JUGGLE AT TLEINT
;<4.MONITOR>SCHED.MAC.161, 21-Dec-78 14:29:08, EDIT BY MILLER
;USE NORMAL PROCESS STACK AT PSIT1 WHEN PSIR4 IS CALLED
;<4.MONITOR>SCHED.MAC.160, 21-Dec-78 10:55:44, EDIT BY MILLER
;FIX UP REDIT ERROR. REORDR NO LONGER A SUBROUTINE
;<4.MONITOR>SCHED.MAC.159, 21-Dec-78 10:50:23, EDIT BY MILLER
;FIX REORDR
;<4.MONITOR>SCHED.MAC.158, 20-Dec-78 18:21:43, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.151, 19-Dec-78 10:23:09, EDIT BY MILLER
;REMOVE CODE THAT FORCES ERJMP TO SECTION OF CALL. UCODE 215 WORKS
;<4.MONITOR>SCHED.MAC.150, 14-Dec-78 17:23:46, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.143,  6-Dec-78 11:02:16, EDIT BY ENGEL
;MAKE PTY HUNGRY AFTER A ?FULL MESSAGE
;<4.MONITOR>SCHED.MAC.142,  5-Dec-78 14:04:50, EDIT BY MILLER
;SAVE LAST SETTING OF KNOB SO SKED JSYS ALWAYS REPPORTS ACCURATE VALUE
;<4.MONITOR>SCHED.MAC.141, 16-Nov-78 15:56:46, EDIT BY MILLER
;FIX CODE AT PSII THAT SETS NEW PC AND FLAGS
;<4.MONITOR>SCHED.MAC.140, 15-Nov-78 12:35:14, EDIT BY MILLER
;MAKE SURE PCS IS NOT LOST WHEN MENT0 IS INVOKED
;<4.MONITOR>SCHED.MAC.139, 15-Nov-78 12:22:30, EDIT BY MILLER
;MAKE SURE FFL CONTAINS PCS IN MENTU
;<4.MONITOR>SCHED.MAC.138,  3-Nov-78 17:22:49, EDIT BY MURPHY
;FIX ANCIENT ENTSKD BUG
;<4.MONITOR>SCHED.MAC.137,  2-Nov-78 11:05:12, EDIT BY MURPHY
;<MURPHY.MON>SCHED.MAC.23,  7-Dec-78 13:51:58, EDIT BY MURPHY
;NEW SWAP LOGIC
;<4.MONITOR>SCHED.MAC.136, 24-Oct-78 13:27:44, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.135, 23-Oct-78 15:21:29, EDIT BY MILLER
;ONE MORE CHANGE TO NEWST
;<4.MONITOR>SCHED.MAC.134, 23-Oct-78 13:43:13, EDIT BY MILLER
;FIX NEWST TO DO Q ADJUSTMENTS FOR CLASS SCHEDULER.
;<4.MONITOR>SCHED.MAC.133, 21-Oct-78 14:33:22, EDIT BY MILLER
;USE PSBUMP EVEN IF CLASS SCHEDULING ON
;<4.MONITOR>SCHED.MAC.132, 20-Oct-78 18:47:18, EDIT BY MILLER
;CHANGE CORFCT TO "ROUND-ROBIN" FORKS OF EQUAL PRIORITY
;<4.MONITOR>SCHED.MAC.131, 19-Oct-78 14:57:24, EDIT BY MILLER
;FIX SAVRT TO ALWAYS CALL GLREM AND GOCONC
;<4.MONITOR>SCHED.MAC.130,  9-Oct-78 09:09:34, EDIT BY MILLER
;PUT ERJMPS IN CODE TO REFERENCE USER PSI WORDS
;<4.MONITOR>SCHED.MAC.129,  1-Oct-78 22:16:47, EDIT BY DBELL
;TCO 4.2027 - SAVE TIME JOB STARTED IN SRTTIM
;<4.MONITOR>SCHED.MAC.128, 29-Sep-78 12:34:25, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.127, 29-Sep-78 10:11:21, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.126, 29-Sep-78 10:09:28, EDIT BY MILLER
;REMOVE VARIABLE PERIOD CODE FOR NOW
;<4.MONITOR>SCHED.MAC.125, 28-Sep-78 16:34:12, EDIT BY MILLER
;FIX NEWUTL SO PERIODS CAN BE VARIABLE
;<4.MONITOR>SCHED.MAC.124, 28-Sep-78 12:12:55, EDIT BY MILLER
;MAKE UTLEXP A VECTOR. ADD FIELD FOR NEWUTL SKIP COUNT
;<4.MONITOR>SCHED.MAC.123, 27-Sep-78 15:14:48, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.121, 27-Sep-78 11:28:39, EDIT BY MILLER
;FIX CORFCT TO DO COMPUTATION CORRECTLY
;<4.MONITOR>SCHED.MAC.120, 22-Sep-78 16:42:08, EDIT BY MILLER
;GET SCHEDULER'S STACK BEFORE GOING TO DISMSE AT PSIDF1
;<4.MONITOR>SCHED.MAC.119, 21-Sep-78 18:28:02, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.118, 20-Sep-78 11:28:20, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.117, 19-Sep-78 15:38:03, EDIT BY ENGEL
;MAKE THE "FULL" MESSAGE INTO "?FULL".
;<4.MONITOR>SCHED.MAC.116, 18-Sep-78 18:10:33, EDIT BY MILLER
;<MURPHY.MON>SCHED.MAC.5, 21-Sep-78 17:18:03, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.115, 18-Sep-78 12:18:15, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.114, 17-Sep-78 15:01:09, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.113, 17-Sep-78 14:13:18, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.112, 17-Sep-78 13:46:58, EDIT BY MILLER
;ADD FUNCTION TO READ CLASS PARAMETERS
;<4.MONITOR>SCHED.MAC.111, 16-Sep-78 15:34:42, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.110, 16-Sep-78 15:12:15, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.109, 16-Sep-78 15:05:34, EDIT BY MILLER
;ADD SKDLOG ROUTINE.
;<4.MONITOR>SCHED.MAC.108, 16-Sep-78 13:45:45, EDIT BY MILLER
;ADD MFRKWD DEF
;<4.MONITOR>SCHED.MAC.107, 16-Sep-78 13:17:46, EDIT BY MILLER
;ADD GTOKM TO "SET JOB CLASS" FUNCTION
;<4.MONITOR>SCHED.MAC.106, 16-Sep-78 12:58:08, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.105, 16-Sep-78 12:56:06, EDIT BY MILLER
;REWRITE SKED JSYS
;<4.MONITOR>SCHED.MAC.104, 15-Sep-78 12:09:36, EDIT BY MILLER
;FIX UP QUEUE TESTING IN AJBALS
;<4.MONITOR>SCHED.MAC.103, 15-Sep-78 11:00:16, EDIT BY MILLER
;ADD BATCH DREGS STUFF
;<4.MONITOR>SCHED.MAC.102, 14-Sep-78 17:24:25, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.99,  1-Sep-78 17:01:45, EDIT BY BOSACK
;<4.MONITOR>SCHED.MAC.98,  1-Sep-78 15:08:07, EDIT BY BOSACK
;CAUSE ERCAL TO NOT STORE FLAGS
;<4.MONITOR>SCHED.MAC.97,  1-Sep-78 13:45:24, EDIT BY BOSACK
;CAUSE ERJMP IN USER TO RETURN TO SECTION OF CALL
;<4.MONITOR>SCHED.MAC.96, 29-Aug-78 17:12:17, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.94, 27-Aug-78 13:05:29, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.93, 27-Aug-78 09:54:04, EDIT BY MILLER
;REMOVE TCDIV. ADD BATCH CLASS CODE
;<4.MONITOR>SCHED.MAC.92, 27-Aug-78 09:16:10, EDIT BY MILLER
;ADD BATCH CLASS WORD AND DEFAULT CLASS WORD
;<4.MONITOR>SCHED.MAC.91, 25-Aug-78 18:16:13, EDIT BY MURPHY
;REMOVE BALSET PARTITIONING, ADD DISASTER AVOIDANCE
;<MURPHY.MON>SCHED.MAC.3, 24-Aug-78 17:26:19, EDIT BY MURPHY
;GLOBAL PAGE AGING
;<4.MONITOR>SCHED.MAC.88, 25-Aug-78 08:25:36, EDIT BY MILLER
;MAKE CLASS COUNTS BE BASED ON LOGGED-IN JOBS
;<4.MONITOR>SCHED.MAC.87, 24-Aug-78 17:33:24, EDIT BY MILLER
;CLEAR CLASS COUNTS WHEN STARTING CLASS SCHEDULER
;<4.MONITOR>SCHED.MAC.86, 24-Aug-78 17:25:17, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.85, 24-Aug-78 12:57:58, EDIT BY MILLER
;FIX UP STARTING OF CLASS SCHEDULER
;<4.MONITOR>SCHED.MAC.84, 24-Aug-78 11:45:14, EDIT BY MILLER
;ADD SETCLS
;<4.MONITOR>SCHED.MAC.83, 23-Aug-78 08:22:30, EDIT BY MILLER
;CHANGE SAVRT NOT TO DEQUEUE AND REQUEUE PROCESS IF USING CLASS SCHEDULER
;<4.MONITOR>SCHED.MAC.82, 22-Aug-78 15:22:06, EDIT BY MILLER
;FIX UP CLASS DISTANCE COMPUTATION
;<4.MONITOR>SCHED.MAC.81, 21-Aug-78 08:43:42, EDIT BY MILLER
;FIX NEWST FOR CLASS SCHEDULING
;<4.MONITOR>SCHED.MAC.80, 18-Aug-78 13:44:47, EDIT BY HALL
;DO REORDR EACH TIME NEWUTL IS CALLED
;<4.MONITOR>SCHED.MAC.79, 15-Aug-78 16:59:28, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.78, 14-Aug-78 13:00:00, EDIT BY MILLER
;CLEAR CLSSUM AND CLSRJA WHEN CLASS SCHEDULER IS TURNED ON
;<4.MONITOR>SCHED.MAC.77, 14-Aug-78 12:17:55, EDIT BY MILLER
;ADD CLASS LOAD AVERAGE COMPUTATIONS. REWRITE DORJ1.
;<4.MONITOR>SCHED.MAC.76, 13-Aug-78 15:50:33, EDIT BY MILLER
;DON'T CALL PSBUMP IF DOING CLASS SCHEDULING
;<4.MONITOR>SCHED.MAC.75, 13-Aug-78 15:24:15, EDIT BY MILLER
;CLEAN UP CODE IN CLASS SCHEDULER.
;<4.MONITOR>SCHED.MAC.74, 13-Aug-78 12:30:32, EDIT BY MILLER
;FINISH REMOVING JOBQ
;<4.MONITOR>SCHED.MAC.73, 13-Aug-78 12:14:14, EDIT BY MILLER
;REMOVE JOBQ,CLSQ,CLSQI
;<4.MONITOR>SCHED.MAC.72, 12-Aug-78 13:38:31, EDIT BY MILLER
;DON'T INHIBIT LOAD OF FORK AT AJBCQS IF DOING CLASS SCHEDULING
;<4.MONITOR>SCHED.MAC.71, 12-Aug-78 12:52:38, EDIT BY MILLER
;DO CLSSHI UPDATES AT NEWUTL
;<4.MONITOR>SCHED.MAC.70, 12-Aug-78 10:53:52, EDIT BY MILLER
;REDO CLASS SCHEDULER. MAKE IT INDEPENDENT OF BALSET SCHEDULER
;<4.MONITOR>SCHED.MAC.69, 11-Aug-78 13:04:17, EDIT BY MILLER
;FIX GETJQ AND CORFCT
;<4.MONITOR>SCHED.MAC.68, 11-Aug-78 10:22:20, EDIT BY HALL
;FIX COUNT TO CALL ADJCLS IF COMPUTED COUNT IS DIFFERENT FROM OLD COUNT
;<4.MONITOR>SCHED.MAC.67, 11-Aug-78 08:15:22, EDIT BY MILLER
;fix typeo
;<4.MONITOR>SCHED.MAC.66, 11-Aug-78 08:05:39, EDIT BY MILLER
;FIX CLASS SCHEUDLER COMPUTATIONS
;<4.MONITOR>SCHED.MAC.65, 10-Aug-78 17:04:37, Edit by DBELL
;TCO 1905.  PREVENT ZERO POINTER IN TLEINT FROM CAUSING RESBAD, ILLUUO BUGCHKS
;<4.MONITOR>SCHED.MAC.64,  3-Aug-78 11:02:49, EDIT BY MILLER
;FIX TYPEOS
;<4.MONITOR>SCHED.MAC.63,  3-Aug-78 08:37:58, EDIT BY MILLER
;<4.MONITOR>SCHED.MAC.62,  3-Aug-78 08:36:21, EDIT BY MILLER
;CHANGE COMPUTATION OF CLASS POPULATION
;<4.MONITOR>SCHED.MAC.61, 30-Jul-78 10:28:22, EDIT BY MILLER
;CHECK IN LOGOUT CODE FOR JOB IN A CLASS
;<4.MONITOR>SCHED.MAC.60, 25-Jul-78 15:23:20, EDIT BY MILLER
;FIX SKJFC2 NOT TO CALL GCCOR SO MANY TIMES
;<4.MONITOR>SCHED.MAC.59, 25-Jul-78 13:32:07, Edit by PORCHER
;TCO 1953 - FIX CHKERT ROUTINE TO CHECK ONLY OP/AC FOR ERJMP/ERCAL
;<4.MONITOR>SCHED.MAC.58, 18-Jul-78 15:04:28, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.56, 17-Jul-78 11:04:25, EDIT BY MILLER
;REMOVE "SCALING" CODE AT ONBSQ
;<4.MONITOR>SCHED.MAC.55, 14-Jul-78 11:41:26, EDIT BY MILLER
;MORE CLASS FIXES
;<4.MONITOR>SCHED.MAC.54, 14-Jul-78 08:44:34, EDIT BY MILLER
;CHANGE VALUE OF SKDBQC FOR BETTER PRECISION
;<4.MONITOR>SCHED.MAC.53, 13-Jul-78 20:53:00, EDIT BY MILLER
;MORE CLASS SCHEDULING CODE
;<4.MONITOR>SCHED.MAC.52, 12-Jul-78 16:45:14, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.51, 12-Jul-78 16:34:06, EDIT BY MILLER
;FIX UP CHECK AT SAVRT9
;<4.MONITOR>SCHED.MAC.50, 11-Jul-78 12:58:07, EDIT BY MILLER
;CHECK FKMXQ AT ALL PLACES WHERE QUEUE CHANGES.
;<4.MONITOR>SCHED.MAC.49, 10-Jul-78 13:34:32, EDIT BY MILLER
;ADD MORE MAXCLS
;<4.MONITOR>SCHED.MAC.48, 10-Jul-78 13:29:52, EDIT BY MILLER
;TCO 1938. ADD CLASS SCHEDULER CODE
;<4.MONITOR>SCHED.MAC.45,  6-Jul-78 07:31:29, EDIT BY MILLER
;MORE FIXED FOR TCO 1929. FIX CODE AT PRISET
;<4.MONITOR>SCHED.MAC.43,  1-Jul-78 12:08:12, EDIT BY MILLER
;REMOVE ONBSQN
;<4.MONITOR>SCHED.MAC.42,  1-Jul-78 12:07:43, EDIT BY MILLER
;RESTORE USE OF SK%BQR AND SK%BQE
;<4.MONITOR>SCHED.MAC.41, 30-Jun-78 16:40:29, EDIT BY MURPHY
;TCO #1930 - CRITICAL SECTION FACILITY
;<4.MONITOR>SCHED.MAC.38, 30-Jun-78 14:21:31, EDIT BY MILLER
;FIX CODE IN SAVRT TO INSURE QUEUE IS CORRECT IF QUEUE #'S SET
;<4.MONITOR>SCHED.MAC.36, 30-Jun-78 13:40:13, EDIT BY MILLER
;INITIALIZE FKQMX IN ASSFK
;<4.MONITOR>SCHED.MAC.35, 30-Jun-78 13:35:20, EDIT BY MILLER
;MORE FIXES TO QUEUE NUMBERS
;<4.MONITOR>SCHED.MAC.34, 30-Jun-78 11:06:42, EDIT BY MILLER
;CHECK FKMXQ AT NEWST3
;<4.MONITOR>SCHED.MAC.27, 23-Jun-78 17:59:36, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.23, 20-Jun-78 13:13:55, EDIT BY MILLER
;FIX UP ALL XJRSTFS TO PRESERVE FLAGS. CHANGE MJRST1 TO USE JRST @
;<1BOSACK>SCHED.MAC.1001,  5-Jun-78 21:38:18, EDIT BY BOSACK
;<1BOSACK>SCHED.MAC.1000,  5-Jun-78 19:02:46, EDIT BY BOSACK
;<4.MONITOR>SCHED.MAC.21, 19-Jun-78 17:17:41, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.20, 19-Jun-78 13:50:46, Edit by MCLEAN
;ADD GOKFRE FOR GETOK JSYS TCO 1908
;<3A.MONITOR>SCHED.MAC.8, 12-Jun-78 10:07:17, EDIT BY MILLER
;TCO 1894. MAKE SURE CTY OUTPUT IS STARTED AT SWHLT3
;<4.MONITOR>SCHED.MAC.18,  8-Jun-78 09:12:45, EDIT BY MILLER
;FIX ITRSIM TO DO SPECIAL HANDLING OF MONITOR CALLS. (SEE NOTE)
;<3A.MONITOR>SCHED.MAC.7,  7-Jun-78 07:58:15, EDIT BY MILLER
;FIX DISMS JSYS
;<3A.MONITOR>SCHED.MAC.6,  7-Jun-78 07:56:41, EDIT BY MILLER
;ALLOW HDISMS OF ARBITRARY TIME
;<4.MONITOR>SCHED.MAC.16, 17-May-78 17:12:28, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.15, 16-May-78 16:49:29, EDIT BY MURPHY
;<4.MONITOR>SCHED.MAC.14, 16-May-78 14:32:36, EDIT BY MURPHY
;<MURPHY.MON>SCHED.MAC.8, 16-May-78 13:13:41, EDIT BY MURPHY
;TCO #1904 - WORKING SET SWAPPING
;<3A.MONITOR>SCHED.MAC.5, 24-Apr-78 17:20:54, EDIT BY MURPHY
;<3A.MONITOR>SCHED.MAC.4, 18-Apr-78 17:12:36, EDIT BY MURPHY
;<3A.MONITOR>SCHED.MAC.3, 13-Apr-78 15:09:47, EDIT BY MURPHY
;TCO #1901 - SCHEDULER CONTROLS FOR INTERACTIVE/COMPUTATIONAL BIAS
;<4.MONITOR>SCHED.MAC.10,  3-Apr-78 13:42:58, EDIT BY MILLER
;REMOVE 2 MS DELAY FROM SCHPRF
;<4.MONITOR>SCHED.MAC.9, 11-Mar-78 10:48:32, EDIT BY MILLER
;FIX UP REG USE IN RTG1
;<4.MONITOR>SCHED.MAC.8, 10-Mar-78 10:07:30, EDIT BY MILLER
;TCO 1889. CHECK JOBSKD AS WELL AS JOBBIT IN SAVRT
;<4.MONITOR>SCHED.MAC.7,  9-Mar-78 13:44:09, EDIT BY MILLER
;MAKE TERM INT FIELD IN FKINT BE 9 BITS. FREE UP 9 BITS FOR INTS
;<4.MONITOR>SCHED.MAC.6,  9-Mar-78 08:52:13, EDIT BY MILLER
;CLEAR "QUOTA EXCEEDED" BIT AT MRETN
;<4.MONITOR>SCHED.MAC.5, 21-Feb-78 14:59:24, Edit by HALL
;INITIALIZE JSAMX AT FKSET1
;<3.SM10-RELEASE-3>SCHED.MAC.6, 10-Feb-78 17:10:26, Edit by MCLEAN
;REMOVE LOW CORE DEFINITONS (SJOBD,SLITES AND SPRIJD) BECAUSE
;THEY ARE NEEDED SINCE THEY ARE NOT SAVED OR DESTROYED OVER
;RELOADS AND ALSO THEY ARE NOT CACHED.
;<4.MONITOR>SCHED.MAC.3,  1-Feb-78 11:11:39, EDIT BY MILLER
;ONE MORE FIX. CHECK FOR ERCAL AND ERJMP CORRECTLY
;<4.MONITOR>SCHED.MAC.2,  1-Feb-78 09:43:57, EDIT BY MILLER
;FIX ITRSIM TO ALLOW INDEXING/INDIRECTION ON ERJMP/ERCAL.
;<4.MONITOR>SCHED.MAC.1, 31-Jan-78 08:10:12, EDIT BY MILLER
;TCO 1880. REMOVE CALL TO SETOVF IN SKDJOB

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	SEARCH PROLOG
	TTITLE SCHED

; SCHEDULER - D. MURPHY

;SPECIAL AC DEFINITIONS USED HEREIN

DEFAC (FX,Q3)			;FORK INDEX

;LOCAL ITEMS IN STG.MAC

EXTN <N2CLKS,CLK2TM,LV8CHK,CLK2CL,SCHPF0>
EXTN <PAGDIF,ADJSWP,TSTFRP>

;CLASS SCHEDULER EXTERNALS

EXTN <CLSSHR,CLSCNT,JOBIRT,CLSUTL,CLSDST,CLSSUM,CLSRJA>
EXTN <MJBUSE,UTLTIM,UTLINT,OLDSLD,CLASSF>
EXTN <JOBDST,JOBCLS,JOBUTL,CLSSHI,MAXCLS,CLSCTL,CLSIRT,WA>

DEFSTR (CLGLC,CLSCNT,17,18)	;COUNT OF PROCESSES ON GOLST FOR THIS CLASS
;LOWER CORE LOCATIONS FOR LITES DISPLAY


SHLTW==:30			;SCHEDULER HALT REQUEST WORD
SCTLW==:20			;SCHEDULER CONTROL WORD

NSCDRQ==20			;SIZE OF SCHEDULER REQUEST QUEUE

MINNR==:4			;MIN SIZE OF RPLQ FOR LOADING FORK
TRMINT==^D19			;FORK TERMINATION CHANNEL

;ASSUMED WORKING SET SIZE (MINIMUM) FOR FORK WAKING UP AFTER LONG
;BLOCK.

MINWSS::^D10

;VALUES FOR DISASTER AVOIDANCE - USED ONLY IF SK%HQR = 1

;THESE ARE THE VALUES OF THE HQ LDAV AT WHICH AJNNLF WILL GO OFF AND ON
;RESPECTIVELY.  AJNNLF PREVENTS NEW LQ FORKS FROM COMING INTO THE BALSET
;WHEN ON.  THE TWO VALUES ARE SEPARATED SLIGHTLY TO PREVENT INSTABILITY.

HQLEV1::4.0			;'OFF' VALUE FOR AJNNLF
HQLEV2::6.0			;'ON' VALUE FOR AJNNLF

;THESE ARE THE VALUES OF THE HQ LDAV AT WHICH AJHQOF WILL GO OFF AND ON
;RESPECTIVELY.  AJHQOF FORCES LQ FORKS OUT OF THE BALSET.  AGAIN, TWO
;VALUES PREVENT INSTABILITY.

HQLEV3::6.0			;'OFF' VALUE FOR AJHQOF
HQLEV4::9.0			;'ON' VALUE FOR AJHQOF

;BASIC PERIODS

SKDSCY:	^D20			;SHORT CYCLE
SKDLCY:	^D100			;LONG CYCLE
AJBLCY:	^D1000			;AJBALS CYCLE
SKDBQT:	^D200*NTMS		;BALSET RUN QUANTUM
	MINQNT==^D10*NTMS	;MINMUM TIME BEFORE CHANGING ALARM
	SMLSTM==^D10		;ALARM CYCLE TO CATCH SMALL QUANTA
UTLTMI==^D1000			;TIME PERIOD
UTLINI==3			;# OF PERIODS IN A COMPUTE CYCLE
UTLEXP:	0.983471454		;e-(1/60)
	0.9672161		;e-(2/60)
	0.951229424		;e-(3/60)
	0.935506985		;e-(4/60)

	DEFSTR (SKPCT,JOBNAM,2,2) ;SKIP COUNT FOR NEWUTL
	MXSKPS==3		;MAX VALUE OF SKIP COUNT
;THE FOLLOWING MACROS AND COMPUTATIONS ARE NECESSARY DUE
;TO MACROS INABILITY TO PERFORM FLOATING POINT
;COMPUTATIONS.

	RADIX 10
MINSHR==5			;MIN % A SHARE MAY HAVE
MAXVAL==1000/MINSHR		;MAX BIAS FOR CLASS PRIORITY

;NOW SOME MACROS TO DO THE FP CONSTRUCTIONS

   DEFINE FLTMIN (A) <

	SHRMIN==0.00'A
   >

   DEFINE FLTMAX (A) <

	MXBIAS==A'.0>

;NOW PRODUCE THE VALUES

	FLTMIN (\MINSHR)	;FP REPRESENTATION OF MINSHR
	FLTMAX (\MAXVAL)	;FP REPRESENTATION OF MAXVAL

	RADIX 8			;RETURN TO DEFAULT RADIX
;STANDARD VALUES FOR SCHEDULER INTERACTIVE/COMPUTATIONAL FLAGS
; ON A SCALE OF 0 - 9

   REPEAT 0,<			;FOR REFERENCE ONLY - DEFINITIONS IN MONSYM
SK%CYT==:1B18			;CYCLE TIME
SK%IOC==:1B19			;IO QUANTUM CHARGE
SK%HT1==:1B20			;LIMIT HOLD TIME IF 1
SK%HT2==:1B21			;NO HOLD TIME AFTER SKIPPED FORK IF 1
SK%HQR==:1B22			;HIGH QUEUE FORKS HAVE ABSOLUTE PRIORITY UNDER LOAD
;23 NOT USED
;24 NOT USED
SK%RSQ==1B25			;QUICK RESCHEDULE ON WAKEUP EVENTS
SK%RQ1==:1B26			;REQUEUE TO QUEUE 1
SK%TTP==:1B27			;TTY PREFERENCE
SK%WCF==:1B28			;WAIT CREDIT PROPORTIONAL TO LOAD AV
   >

SKFLGV::BYTE (18) 0 (1) 1,0,1,1,1,1,1,1,1,1,1
	BYTE (18) 0 (1) 1,0,1,1,1,1,1,1,1,1,1
	BYTE (18) 0 (1) 1,0,1,1,1,1,1,1,1,1,1
	BYTE (18) 0 (1) 1,0,1,1,1,1,1,1,1,1,1
	BYTE (18) 0 (1) 1,0,1,0,1,1,1,1,1,1,1
	BYTE (18) 0 (1) 1,0,1,0,1,1,1,1,1,1,1
	BYTE (18) 0 (1) 1,0,1,0,1,1,1,1,1,1,1
	BYTE (18) 0 (1) 1,0,1,0,1,1,1,1,1,1,1
	BYTE (18) 0 (1) 1,0,1,0,1,0,1,1,1,1,0
	BYTE (18) 0 (1) 1,0,1,0,1,0,1,1,1,1,0 
SKFLDF:	BYTE (18) 0 (1) 1,0,1,0,0,0,1,0,1,1,0 ;NORMAL DEFAULT
	BYTE (18) 0 (1) 1,0,1,0,0,0,1,0,1,1,0
	BYTE (18) 0 (1) 1,0,1,0,0,0,1,0,0,1,0
	BYTE (18) 0 (1) 1,0,1,0,0,0,1,0,0,1,0
	BYTE (18) 0 (1) 1,0,1,0,0,0,1,0,0,1,0
	BYTE (18) 0 (1) 1,0,1,0,0,0,1,0,0,1,0
	BYTE (18) 0 (1) 0,0,0,0,0,0,1,0,0,0,0
	BYTE (18) 0 (1) 0,0,0,0,0,0,1,0,0,0,0
	BYTE (18) 0 (1) 0,0,0,0,0,0,1,0,0,0,0
	BYTE (18) 0 (1) 0,0,0,0,0,0,1,0,0,0,0
NSKFLV==:.-SKFLGV

;CLASS SCHEDULING STRUCTURE DEFS

DEFSTR (CLSBD,CLSCTL,0,1)		;BATCH JOBS TO DREGS QUEUE
DEFSTR (CLSDF,CLSCTL,9,9)		;DEFAULT CLASS
DEFSTR (CLSBT,CLSCTL,18,9)		;BATCH CLASS
DEFSTR (CLSAC,CLSCTL,19,1)		;IF ON, CLASS BY ACCOUNTS
DEFSTR (CLSKV,CLSCTL,25,6)	;CURRENT KNOB VALUE

	DREGS==<LOWQ>B29+LOWQ+1		;BATCH DREGS PRIORITY WORD
	LDAVCJ==0		;USE JOB LOAD AVERAGES
;SCHEDULER INITIALIZATION

SCDIN::	SETZM SYSIFG
	SETZM PWRDWN
	SETZM FACTSW		;INITIALIZE SYSTEM FLAGS WORD
	SETZM RSKCHK+2		;INSURE FLAGS WORD 0
	MOVE F,SKFLDF		;SET DEFAULT CONTROL FLAGS
	MOVEM F,SCHFLG
	move t1,[bug (scduuo)]
	movem t1,mjrstf		;init scheuler's uuo disptach to bughlt
	MOVEI T1,SKFLDF-SKFLGV+1 ;GET KNOB VALUE
	STOR T1,CLSKV		;SAVE IT
	SETOM WA		;INIT WINDFALL ALLOCATION
	MOVE T1,[WA,,WA+1]
	BLT T1,WA+MAXCLS-1	;INIT ALL TO -1
	MOVEI T1,UTLTMI*UTLINI	;DEFAULT INTERVAL FOR UTIL
	MOVEM T1,UTLINT		;SET UP INTERVAL
	MOVX T1,1B1		;GET A LARGE NUMBER
	MOVEM T1,UTLTIM		;WHEN TO COMPUTE UTILIZATION
	MOVE T1,[RSKCH1]	;SETUP JSR DISPATCH
	MOVEM T1,RSKCHK+3
	MOVE 1,[JRST SCDRQ0]
	MOVEM 1,SCDRQ+1		;DISPATCH FOR JSR-CALLED ROUTINE
	MOVEI T1,JTLST		; Set up JSYS trap queue
	MOVEM T1,JTLSTL
	MOVEI 1,SCDRQB
	MOVEM 1,SCDRQI
	MOVEM 1,SCDRQO
	MOVE T1,[1B0+FKPT]
	MOVEI 2,NFKS
	CALL ILIST		;INIT FREE FORK LIST
	HRRZM 1,FREFK
	MOVEI 1,JOBPT
	MOVEI 2,NJOBS
	CALL ILIST
	MOVEM 1,FREJOB		;INIT FREE JOB LIST
	SETOM JOBRT
	MOVE 1,[XWD JOBRT,JOBRT+1]
	BLT 1,JOBRT+NJOBS-1
	SETZM SCTLW
	SETZM SHLTW
	SETOM SCDRN1
	SETOM FORKX
	SETOM TADIDT
	SETOM SSKED
	MOVEM 1,INSKED
	MOVX 1,SF%FAC!SF%CRD	;INIT FACTSW TO FACT FILE ON
				;  AND ALLOW USERS TO CHANGE DIR PARAMETERS
	IORM 1,FACTSW
	MOVSI 1,(1B1)
	MOVEM 1,CHKTIM		;PREVENT JOB 0 ALARM UNTIL INITIALIZED

;GENERATE LQWBAS TABLE

	MOVEI T2,INTQ1		;FIRST QUEUE TO DO
SCDIN0:	FLTR T1,T2		;GET FLOAT OF QUEUE NUMBER
	FDVR T1,FLOWQ		;DO DIVIDE
	FSBRI T1,(1.0)		;DO -(1-Q/LOWQ)
	FDVRI T1,(10.0)		;COMPLETE COMPUTATION
	MOVNM T1,LQWBAS-INTQ1(T2) ;STASH IT
	ADDI T2,1		;NEXT Q
	CAIG T2,LOWQ		;ALL DONE?
	JRST SCDIN0		;NO. MORE THEN
	CALLRET QBIAS		;SET UP BAIS QUANTUM TABLE
ILIST::	ADDI 1,-1(2)
	HLLZM T1,0(T1)		;CLEAR END OF LIST
	SOJLE 2,ILIST1		;  SIZE OF BLOCK IN 2
	MOVEM 1,-1(1)
	SUBI 1,1
	SOJG 2,.-2
ILIST1:	RET
;CHANNEL 7 INTERRUPT
;CLOCK, POSSIBLE RESCHEDULING, OR START PROCESS FROM SCHEDULER

PISC7::	XWD PISC7R,.+1
	CLSB SCDCHN		;ISB MUST BE EXPLICITLY CLEARED ON KI
	SKIPE RSKCHK+1		;CALL FROM RESKED CHECK?
	JRST [	DMOVEM T1,PI7AC1 ;SAVE ACS
		DMOVE T1,RSKCHK	;MOVE FLAGS AND PC TO USUAL PLACE
		DMOVEM T1,PISC7R
		SETZM RSKCHK+1	;CLEAR INDICATOR
		DMOVE T1,PI7AC1	;RESTORE ACS
		JRST .+1]	;WILL RESKED NOW IF POSSIBLE
	SKIPN SKEDFC		;FORCED MEMORY CLEAR?
	SKIPG SCKATM		;ALARM CLOCK?
	AOS SKEDF3		;YES
	SKIPE SKEDF1		;INITIATED BY SCHEDULER?
	JRST SCDR		;YES, GO START PROCESS
	SKIPG INSKED		;IN SCHEDULER NOW, OR
	SKIPG SKEDF3		;NO SCHEDULING REQUESTS?
	XJEN PISC7R		;IGNORE INTERRUPT
	;SKIPN CRSKED		;CSKED PREVENTS RESCHEDULE
	SKIPE NSKED		;OK TO RESCHEDULE?
	JRST SCDW		;NO, GO SET TRAP
	SKIPGE UTLOCK		;ANY UNIT TESTING BEING DONE?
	SKIPE SNPCNT		;ANY SNOOP BREAK POINTS INSERTED?
	JRST CHKSNP		;YES, GO SEE IF PC IS INSIDE A BP
PISC7A:
	DATAO PAG,SETMON	;SET MON CONTEXT
	MOVEM 17,PAC+17		;YES, SAVE PROCESS AC'S
	MOVEI 17,PAC
	BLT 17,PAC+16
	DMOVE T1,PISC7R		;GET FLAGS AND PC
	TXNN T1,UMODF		;MONITOR PC?
	JRST [	HRRZ T3,T2	;YES, AT POINT OF RETURN TO USER?
		CAIN T3,GOUSR+1
		HRRI T2,GOUSR	;YES, RE-EXECUTE DATAO PAG WHEN RESUMED
		JRST .+1]
	DMOVEM T1,PFL
	MOVE 1,RSKEDN		;RESET NOSKED TRAP
	MOVEM 1,RSKED
	AOS INSKED
	JSP FX,KISSAV		;SAVE APR-DEPENDENT STUFF
	XJEN [0
	     MSEC1,,SCHED0]

;SET TRAP TO CAUSE INTERRUPT ON OKSKED

SCDW:	MOVEM 1,RSKED
	MOVEI T1,1
	SKIPG SCKATM		;ALARM HAS GONE OFF?
	MOVEM T1,SCKATM		;YES, RESET IT FOR 1 MS.
	MOVE 1,RSKEDT
	EXCH 1,RSKED
	XJEN PISC7R

RSKEDN:	JFCL			;NO-TRAP CONTENTS OF RSKED
RSKEDT:	XPCW RSKCHK		;TRAP CONTENTS OF RSKED

;HERE WHEN RESKED REQUEST WAITING AND PROGRAM DOES XCT RSKED

RSKCH1:	ISB SCDCHN		;ENTER VIA INTERRUPT
	JRST .			;WAIT FOR INTERRUPT TO HAPPEN
;CHECK IF PROCESS IS IN A SNOOP BREAK POINT
;  IF YES, THEN THE PROCESS CANNOT BE STOPPED IN CASE BP IS REMOVED

CHKSNP:	MOVEM T1,SNPSV1		;SAVE AN AC FOR TEST
	MOVE T1,PISC7R		;GET PC OF PROCESS BEING STOPPED
	TLNE T1,(UMODF)		;IN USER MODE?
	JRST CHKSN1		;YES, OK TO STOP HIM THEN
	HRRZ T1,PISC7R+1	;PICK UP PC
	CAIL T1,UTREP		;IN THE CRITICAL UTEST ROUTINE?
	CAILE T1,UTREPE		;...
	SKIPA			;NO
	JRST CHKSN0		;YES, DO NOT RESCHEDULE NOW
	CAIL T1,SNPBPP		;IN BREAK POINT PAGES?
	CAILE T1,SNPBPP+SNPBPS+SNPDPS-1
	JRST CHKSN1		;NOT IN BP PAGES, OK TO RESKED
CHKSN0:	MOVE T1,SNPSV1		;RESTORE AC
	JRST SCDW		;SET TRAPS AND CONTINUE PROCESS

CHKSN1:	MOVE T1,SNPSV1		;RESTORE AC
	JRST PISC7A		;SAVE CONTEXT, STOP PROCESS

;SETUP AND RESUME PROCESS

SCDR:
   REPEAT 0,<			;DON'T USE FINE CONTROLS NOW
	SKIPE CLASSF		;DOING CLASS SCHEDULING?
	JRST [	MOVE T1,BSQNT	;YES. GET CURRENT QUANTUM REMAINING
		CAILE T1,MINQNT	;NEED TO ADJUST ALARM?
		JRST .+1	;NO
		MOVEI T1,SMLSTM	;YES
		MOVEM T1,SCKATM	;STORE IT
		JRST .+1]
   >				;END OF REPEAT 0
	SETZM SKEDF1		;CLEAR LOCAL FLAG
	SETZM INSKED		;NO LONGER IN SCHEDULER
	SETOM SSKED
	JSP FX,KISLOD		;LOAD APR-DEPENDENT STUFF
	MOVE 1,PFL		;GET FLAGS
	TXNE 1,UMODF		;RETURNING TO USER OR MONITOR?
	SKIPA 1,SETUSR		;USER, GET USER CONTEXT WORD
	MOVE 1,SETMON		;GET MONITOR CONTEXT WORD
	MOVEM 1,SETPAG		;SAVE FOR USE BELOW
	MOVSI 17,PAC		;RESTORE PROCESS AC'S
	BLT 17,17
	DATAO PAG,SETPAG	;SET AC BLOCKS
	SKIPN NSKED		;RESUMING NOSKED PROCESS?
	SKIPE CRSKED		;OR CSKED PROCESS?
	SKIPA
	XJEN PFL		;RUN PROCESS
	AOS SKEDF3		;YES, REMEMBER SCHEDULING NEEDED
	MOVEM 1,RSKED		;SET DEFERRED SCHED TRAPS
	MOVE 1,RSKEDT
	EXCH 1,RSKED
	XJEN PFL		;RUN PROCESS
;VARIOUS WAYS OF ENTERING SCHEDULER

;JSYS HALTF - DISMISS FORK UNTIL INTERRUPT OR EXTERNALLY RESTARTED

.HALTF::MCENT
HALTF1::			;FORK TERM 
HALTX:	CALL GETSFX		;GET SUPERIOR FORK INDEX
	HRRI 1,HALTT
	MOVSI T2,FHV1		;SAY LOW PRIORITY WAIT
	HDISMS
	JRST MRETN		;IF CONTINUED

HALTT::	JRST 0(4)		;IDENTIFIABLE TEST FOR HALTED FORK

;SCHEDULING CONTROL MACROS
;NOSKED AND NOSKD1 EXECUTE A NOINT
;OKSKED AND OKSKD1 EXECUTE AN OKINT

;NOSKED - ENTERED VIA JSP CX,NOSKD0

NOSKD0::NOINT
	AOS NSKED
	JRST 0(CX)

;OKSKED - ENTERED VIA JSP CX,OKSKD0

OKSKD0::SOSG NSKED
	XCT RSKED
	OKINT
	JRST 0(CX)
;CRITICAL SECTION, BGN AND END
;INVOKED BY CSKED AND ECSKED MACROS

CRSKD0::NOINT			;IMPLIES NOINT ALSO
	AOS CRSKED
	JRST 0(CX)

ECSKD0::SOSG CRSKED		;NOW OUT OF ALL CRITICAL SECTIONS?
	XCT RSKED		;YES, CHECK FOR DEFERRED RESCHEDULE
	OKINT
	JRST 0(CX)

;NOSKD1 - ENTERED VIA JSP CX,NOSK11

NOSK11::SKIPE INSKED
	JRST 0(CX)
	NOINT
	AOS NSKED
	JRST 0(CX)

;OKSKD1 - ENTERED VIA JSP CX,OKSK11

OKSK11::SKIPE INSKED
	JRST 0(CX)
	SOSG NSKED
	XCT RSKED
	OKINT
	JRST 0(CX)
;DISMISS WITH HOLD TIME--KEEP IN BALSET FOR SPECIFIED TIME BECAUSE
;BLOCK EXPECTED TO BE SATISFIED IN THAT TIME.
; 1/ USUAL DISMISS TEST
; 2/ HOLD TIME IN MILLISECONDS
;NORMALLY INVOKED VIA HDISMS(HT) MACRO

EDMSH::	ENTSKD			;ENTER SCHED
	TXZ CX,EXFLBT		;MASK OFF FLAGS BITS IF SEC 0
	MOVEM CX,PPC		;SAVE PC
	MOVE CX,ENSKR		;FIND FLAGS
	MOVEM CX,PFL		;SET FLAGS
	JRST DISMSH		;JOIN REGULAR DISMISS BUT KEEP 2

;EXEC DISMISS - AC1 CONTAINS  XWD DATA,TEST ROUTINE ADR

EDMS0::	ENTSKD			;ENTER SCHEDULER
	TXZ CX,EXFLBT		;MASK OFF FLAGS INCASE SECTION 0
	MOVEM CX,PPC		;RETURN BECOMES PROCESS PC
	MOVE CX,ENSKR		;FIND FLAGS ON THIS CALL
	MOVEM CX,PFL		;SAVE FLAGS
DISMSE:	MOVE P,PI7P		;INIT SCHED STACK
	MOVEI 2,0		;SAY 0 HOLD TIME
	SKIPE CRSKED		;CRITICAL SECTION?
	MOVEI T2,^D200		;YES, STAY IN BALSET FOR A WHILE
DISMSH:	PUSH P,2		;SAVE HOLD TIME
	HRRZ T2,T1		;GET ADR OF ROUTINE
	SKIPN NSKED		;CHECK FOR BUGGY DISMISS
	CAILE T2,RSCODZ		;CHECK FOR A NON-RESIDENT TEST ROUTINE
	BUG(NSKDIS)
	MOVEM 1,FKSTAT(FX)	;PUT IN TEST WORD
FRIBP2::CALL SAVRT		;(WATCH BPT TAG)
	HRRZ 1,FKSTAT(FX)
	CAIE 1,HALTT		;FORK TERMINATING?
	CAIN 1,FORCTM
	CALL SUPUNB		;YES, UNBLOCK SUPERIOR IF NECESSARY
	SETZM JOBCK0		;INIT MEASURING INTERVAL
	POP P,2			;RECOVER HOLD TIME
	HLRZ T3,T2		;GET WAIT PRIORITY
	CAIN T3,0		;GIVEN?
	MOVEI T3,FHV3		;NO, DEFAULT TO MIDDLE VAL
	STOR T3,FKGOLN		;SAVE IT
	HRRZ T2,T2
	JUMPE 2,[CALL REMBSJ	;IF 0 HOLD TIME, REMOVE IMMEDIATELY
		CALL GLREM	;REMOVE FROM GOLST
		CALL WTCONC
		SETOB FX,FORKX
		JRST SCHED0]
	MOVE 1,TODCLK
	ANDI 1,377777
	ADDI 1,0(2)		;CONSTRUCT SPECIAL TEST FOR HOLD TIME
	MOVSI 1,0(1)
	HRRI 1,DISMT
	MOVEM 1,FKPGST(FX)
	JRST SCHP3
;RESCHEDULE ON PAGE WAIT

SCHEDP::TXZ CX,EXFLBT		;MASK OFF FLAGS INCASE SECTION 0
	XSFM SKDFL		;STORE FLAGS
	MOVEM CX,SKDPC		;STORE PC
	SKIPE INSKED
	BUG(SKDCL1)
	ENTSKD
SCHP1:	PUSH P,1
	CALL SAVRT
	POP P,1
	MOVEM 1,FKPGST(FX)
	DMOVE 1,SKDFL
	DMOVEM 1,PFL
	HRRZ T1,PPC
	SKIPE NSKED		;BLOCK WHILE NOSKED?
	CALL NBNSB		;YES, SAVE PC
SCHP3:	MOVE 1,TODCLK		;REMEMBER TIME WAIT STARTED
	MOVEM 1,FKNBW(FX)
	AOS NBWT		;COUNT WAITING BALSET PROCESS
	HRRZ T1,FKPGST(FX)
	CAIE T1,SWPINT		;SWAP WAIT?
	CAIN T1,SWPRT
	AOS NBSWP		;YES, COUNT
	MOVX T1,BSWTB
	CALL SCHP2
	JRST SCHED0

;RETAIN FORK IN BALSET, SET FLAGS, ETC.

SCHP2:	IORM T1,FKSWP(FX)
	SKIPE NSKED
	MOVEM FX,SSKED		;REMEMBER FORK NUMBER OF NOSKED FORK
	SETOB FX,FORKX
	RET
;DO OKSKED AND RESCHEDULE

SCHEDR::TXZ CX,EXFLBT		;CLEAR FLAGS INCASE SECTION 0
	XSFM SKDFL		;SET FLAGS
	MOVEM CX,SKDPC
	SKIPE INSKED
	BUG(SKDCL2)
	ENTSKD
	SOSGE NSKED
	BUG(ILOKSK)
	SOS INTDF		;FIX UP NOINT AS WELL
	JRST SCHP1
;COMMON SCHEDULER ENTER ROUTINE, SAVE AC'S
; ** INSKED MUST BE NON-0 BEFORE THIS CALL **

ENSKED::MOVEM 17,PAC+17		;SAVE PROCESS AC'S
	MOVEI 17,PAC
	BLT 17,PAC+16
	JSP FX,KISSAV		;SAVE APR-DEPENDENT STUFF
	MOVE FX,FORKX		;GET INDEX OF CURRENT FORK
	MOVE P,PI7P		;GET PDL POINTER
	CALL UPDTCK		;UPDATE TODCLK
	DMOVE T1,PAC+1		;RESTORE T1 AND T2
	XJRSTF ENSKR

;ROUTINE TO SAVE PC'S WHICH CAUSE NOSKED BLOCKS
;CALLED FROM PGRTRP ALSO
; T1/ PC TO SAVE

NBNSB::	HRLZ T4,NNSBE		;NEG NUMBER TABLE ENTRIES IN USE
	JUMPGE T4,NBNS2		;JUMP IF TABLE EMPTY
NBNS1:	HLRZ T2,NSBTAB(T4)
	CAMN T1,T2		;ALREADY HAVE THIS PC?
	JRST NBNS3		;YES, JUST COUNT IT
	AOBJN T4,NBNS1		;CHECK ALL ENTRIES
NBNS2:	CAIL T4,NNSBT		;TABLE FULL?
	RET			;YES, CAN'T ADD NEW ENTRY
	HRLZM T1,NSBTAB(T4)	;ADD NEW PC TO TABLE
	MOVNI T2,1(T4)		;INCREMENT USE COUNT
	MOVEM T2,NNSBE
NBNS3:	AOS NSBTAB(T4)	;COUNT OCCURRANCES
	RET

NNSBT==^D20			;SIZE OF PC TABLE
RS NSBTAB,NNSBT			; PC,,COUNT
RS NNSBE,1			;NUMBER OF ENTRIES IN USE
;INSTRUCTION TRAP - TRAP PC IN FPC, ASSUMED TO BE I +1

ITRAP1::MOVEM 1,LSTERR		;SAVE ERROR CODE GIVEN IN 1
ITRAP::	SKIPE INSKED
	BUG(SKDTRP)
	SKIPL FORKX		;NO FORK RUNNING, OR
	CONSZ PI,177B27		;PI IN PROGRESS?
	BUG(PIITRP)
	SKIPE NSKED		;CHECK FOR PROPER STATE
	BUG(NOSKTR)
	SETZM NSKED
	SETZM CRSKED
	SETOM TRAPC		;CLEAR FLAGS AND COUNTERS
	SKIPGE SLOWF		;NOW IN SLOW CODE?
	MCENTR			;NO, ENTER
	DMOVE 1,KIMUU1		;GET LAST USER MUUO
	DMOVEM 1,UMUUOW		;SAVE AS TRAPPED INSTRUCTION
	MOVE P,MPP		;GET LAST STACK FRAME
	MOVE Q2,-3(P)		;PREVIOUS CONTEXT INTDF
	MOVEM Q2,INTDF
ITRRT2:	MOVE P,MPP
	MOVE Q2,INTDF		;GET CURRENT CONTEXT INTDF
	DMOVE T1,-1(P)		;GET PREV CONTEXT FLAGS AND PC
	EXCH T1,T2		;(IN PROPER ORDER)
	TXNN T1,UMODF		;BACK TO USER?
	CAMN Q2,-3(P)		;OR INTDF UNCHANGED?
	SKIPA			;YES, OK
	BUG(NOINTR)
	CALL SETPCV		;SET PREVIOUS CONTEXT VARIABLES FOR ITRSIM
	CALL ITRSIM		;SEE IF ERJMP/ERCAL
	 JRST ITRRT1		;NO
	MOVEM T3,-1(P)		;SET PC TO E OF ERJMP/ERCAL
	JRST MRETN		;RETURN TO IT

ITRRT1:	TXNE T1,UMODF		;NOW TO TOP OF STACK?
	JRST ITR2		;YES, NO ERJMP SEEN
	XMOVEI T2,ITRRT2	;SET TO RETURN THROUGH MRETN
	MOVEM T2,-1(P)		; TO LOOP ABOVE
	JRST MRETN

ITR2:	SKIPN CRSKED
	SETZM INTDF		;SET TO 1 LEVEL NOINTERRUPT
	MOVE 1,CHNSON
	ANDCAM 1,PSIBW		;FLUSH PREVIOUS PANIC BREAKS
	MOVEI 1,^D15		;INITIATE CHANNEL 15 INTERRUPT
	CALL PSIRQ0
	CHKINT			;GET THE INTERRUPT "SEEN"
	OKINT			;INTERRUPT SHOULD TAKE HERE
	MOVE P,UPP		;RETURN TO USER IF CONTINUED
	ADD P,BHC+3
	JRST MRETN
;BLOCK UNTIL CONDITION SATISFIED
;BLOCK0 - STAYS IN BALSET,  BLOCK1 - LEAVES BALSET

BLOCK0::SUBI CX,2		;MAKE RETURN TO CALL-1
	TXZ CX,EXFLBT		;CLEAR FLAGS INCASE SECTION 0
	XSFM SKDFL		;STORE FLAGS
	MOVEM CX,SKDPC
	ENTSKD
	CALL BLOCKS
	JRST SCHP1

BLOCK1::ENTSKD
	CALL BLOCKS
	SUBI CX,2		;MAKE RETURN TO CALL-1
	TXZ CX,EXFLBT		;CLEAR FLAGS INCASE SECTION0
	MOVEM CX,PPC		;RETURN BECOMES PROCESS PC
	MOVE CX,ENSKR		;PICK UP CALLERS FLAGS
	MOVEM CX,PFL
	JRST DISMSE

BLOCKS:	MOVNI 1,^D100*NTMS
	ADDM T1,BSQNT		;CHARGE QUANTUM
	MOVE 1,TODCLK
	ANDI 1,377777
	ADDI 1,^D1000		;ADD 1000 MILLISECS
	MOVSI 1,0(1)
	HRRI 1,BLOCKW
	RET

;SHORT WAIT TEST.  RETURNS NUMBER OF MS LEFT TO WAIT

BLOCKM::JFCL			;SCHED TEST FOR .5 TO 64 SEC.
BLOCKW::MOVE 2,TODCLK		;SCHEDULER TEST, GET TIME
	ANDI 2,377777
	SUB 1,2			;DESIRED - NOW = WAIT LEFT
BLK2:	JUMPLE 1,1(4)		;NO WAIT TIME LEFT
	CAIGE 1,200000		;BIG DIFFERENCE?
	JRST 0(4)		;NO, KEEP WAITING
	SUBI 1,400000		;YES, COMPENSATE FOR WRAPAROUND
	JRST BLK2
;DISMISS UNTIL WORD .GE. 0

DISGE::	PUSH P,1
	HRLI 1,DISGET		;GIVEN MON ADDRESS IN 1
DISXE:	MOVS 1,1
	MDISMS
	POP P,1
	RET

DISGET::SKIPGE 0(1)
	JRST 0(4)
	JRST 1(4)

;DISMISS UNTIL WORD .L. 0

DISL::	PUSH P,1
	HRLI 1,DISLT
	JRST DISXE

DISLT::	SKIPL 0(1)
	JRST 0(4)
	JRST 1(4)

;DISMISS UNTIL WORD .G. 0

DISG::	PUSH P,1
	HRLI 1,DISGT
	JRST DISXE

DISGT::	SKIPG 0(1)
	JRST 0(4)
	JRST 1(4)
;DISMISS UNTIL WORD .LE. 0

DISLE::	PUSH P,1
	HRLI 1,DISLET
	JRST DISXE

DISLET::SKIPLE 0(1)
	JRST 0(4)
	JRST 1(4)

;DISMISS UNTIL WORD .E. 0

DISE::	PUSH P,1
	HRLI 1,DISET
	JRST DISXE

DISET::	SKIPE 0(1)
	JRST 0(4)
	JRST 1(4)

;DISMISS UNTIL WORD .N. 0

DISN::	PUSH P,1
	HRLI 1,DISNT
	JRST DISXE

DISNT::	SKIPN 0(1)
	JRST 0(4)
	JRST 1(4)
;DISMISS FOR SPECIFIED TIME JSYS

.DISMS::MCENT
	JUMPLE 1,MRETN
	CAIL 1,100000		;LONG OR SHORT TIME?
	JRST TDIS1		;LONG
	MOVE 2,TODCLK
	ANDI 2,377777
	ADDI 2,0(1)		;COMPUTE TIME TO RESTART
	CAIGE T1,^D200		;VERY SHORT WAIT?
	JRST [	MOVEI T1,BLOCKW	;YES, USE BLOCKW AND HDISMS
		HRL T1,T2
		HDISMS (200)	;HOLD FOR ENOUGH TIME
		JRST MRETN]
	CAIGE 1,^D2000		;USE BLOCKW FOR WAIT .L. 2000 MS
	SKIPE T1,[FHV4,,BLOCKW]	;SHORT WAIT, USE BLOCKW AND HIGHER PRIORITY
	MOVE T1,[FHV2,,BLOCKM]	;BLOCKM AND LOWER PRIORITY
	HLL T2,T1		;PASS BLOCK PRIORITY
	HRL T1,T2		;SETUP TIME
	HRRI T2,0		;NO HOLD TIME
TDIS2:	HDISMS			;DISMISS WITH SPECIFIED TEST
	JRST MRETN

TDIS1:	CALL SETBKT		;COMPUTE TEST DATA
	HRRI 1,BLOCKT
	MOVSI T2,FHV1		;VERY LOW PRIORITY
	JRST TDIS2		;GO COMPLETE DISMISSAL

;ROUTINE TO COMPUTE BLOCKT TEST DATA FROM GIVEN TIME IN MS
; 1/ TIME IN MS
;	CALL SETBKT
; RETURN +1: ALWAYS, 1/ TEST ARG FOR BLOCKT ,, 0

SETBKT::CAML 1,[400,,0]		;BELOW MAX TIME?
	MOVSI 1,400		;NO, SET TO MAX
	MOVE 2,TODCLK		;COMPUTE TIME AT WHICH WAKEUP DUE
	TLZ 2,777000		; IN FORM USED BY BLOCKT
	ADD 2,1
	LSH 2,-^D10		;ROUND TO 18-BIT VALUE
	MOVSI 1,0(2)
	RET

;SCHEDULER WAIT TEST FOR LONG WAIT
;RETURNS NUMBER OF MS LEFT TO WAIT

BLOCKT::LSH 1,^D10		;RESTORE WAKEUP TIME TO FULL SIZE
	MOVE 2,TODCLK		;GET TIME NOW
	TLZ 2,777000
	SUB 1,2			;DESIRED-NOW = TIME LEFT TO WAIT
BLKT1:	JUMPLE 1,1(4)		;WAKEUP IF NEGATIVE
	CAMG 1,[XWD 400,0]	;VERY LARGE DIFFERENCE?
	JRST 0(4)		;NO, KEEP WAITING
	SUB 1,[XWD 1000,0]	;COMPENSATE FOR WRAPAROUND
	JRST BLKT1		;CHECK AGAIN
;TEMPORARY JSYS'S FOR INTERJOB COMMUNICATION

;HIBERNATE - BLOCK UNTIL SIGNAL OR SPECIFIED ELAPSED TIME
; 1/ 0,,TIME		MAXIMUM BLOCK TIME IN SECONDS
;	THIBR
; RETURN +1: NEVER
; RETURN +2: SIGNAL RECEIVED OR TIME EXPIRED

.THIBR:: MCENT
	IMULI 1,^D1000		;CONVERT SECONDS TO MS
	CALL SETBKT		;COMPUTE TEST DATA FOR TIME
	HRRI 1,HIBERT		;CONSTRUCT TEST WORD
	MOVSI T2,FHV2		;LOWER PRIORITY BLOCK
	HDISMS
	MOVE 1,JOBNO		;DISMISS SATISFIED, CLEAR WAKE BIT
	MOVSI 2,(JWAKEF)
	ANDCAM 2,JOBNAM(1)
	SMRETN

;SCHEDULER TEST FOR HIBERNATING FORK

HIBERT::LOAD 2,FKJOBN		;GET JOB NUMBER FOR FORK
	MOVSI 3,(JWAKEF)
	TDNE 3,JOBNAM(2)	;SIGNAL RECEIVED?
	JRST 1(4)		;YES, WAKEUP
	JRST BLOCKT		;NO, GO TEST TIME

;WAKEUP - SEND SIGNAL TO JOB WHICH WILL BE SEEN BY THIBR
; 1/ 0,,JOB#		NUMBER OF JOB TO BE AWAKENED
;	TWAKE
; RETURN +1: BAD JOB NUMBER
; RETURN +2: SIGNAL SENT.  DESTINATION JOB WILL BE AWAKENED
;	IMMEDIATELY IF NOW IN THIBR OR AS SOON AS NEXT THIBR DONE

.TWAKE:: MCENT
	MOVEI 1,0(1)
	CAIGE 1,NJOBS		;JOB NUMBER WITHIN RANGE?
	SKIPGE JOBRT(1)		;AND JOB EXISTS?
TWAKER:	RETERR ATACX1		;NO
	HRRZ 2,JOBDIR(1)	;GET LOGIN DIRECTORY
	JUMPE 2,TWAKER		;ERROR IF JOB NOT LOGGED IN
	MOVSI 2,(JWAKEF)
	IORM 2,JOBNAM(1)	;SEND SIGNAL
	SMRETN
;SCHEDULER

;'NULL' JOB - WAITS WHEN NO FORKS RUNNABLE

SCDNUL:	CALL SKCLK		;SET ALARM CLOCK
	MOVE 3,[SOJG 2,3]	;SETUP WAIT LOOP IN AC'S
	MOVE 4,[JRST SCDNL2]
SCDNL0:	MOVEI 2,^D50		;COUNTDOWN BETWEEN FLAG CHECKS
	JRST 3

SCDNL2:	SKIPN PSKED		;CHANGES OF STATE?
	SKIPE QSKED
	JRST SCDNL1		;YES
	SKIPE SKEDF3		;SCHEDULING REQUESTS?
	JRST SCDNL1		;YES
	JRST SCDNL0		;NO

SCDNL1:	CALL RDSIVL		;GET LAST INSKED INTERVAL
	SKIPE NBSWP		;FORKS WAITING FOR SWAPPING?
	JRST [	ADDB 1,SKDSWP	;YES, CHARGE SWAP-WAIT TIME
		IDIVI 1,NTMS	;CONVERT TO 1 MS. UNITS
		MOVEM 1,SKDTM1	;UPDATE 1 MS VERSION OF SWAP-WAIT TIME
		JRST SCDNL3]	;GO SCHEDULE
	SKIPE NGOJOB		;ANY RUNNABLE FORKS?
	JRST [	ADDM T1,SKDFIL	;YES, ACCUMULATE OTHER BS WAITS
		JRST SCDNL3]
	ADDB 1,SKDIDL		;OTHERWISE CHARGE IDLE TIME
	IDIVI 1,NTMS		;CONVERT TO 1 MS UNITS
	MOVEM 1,SKDTM0		;UPDATE 1 MS VERSION OF IDLE TIME
SCDNL3:	CALL UPDTCK		;UPDATE TODCLK
	SKIPE QSKED		;FORK RECENTLY UNBLOCKED?
	CALL XCLKS		;YES, UPDATE EVERYTING
	JRST SCH0		;GO SCHEDULE

;READ LAST IN-SCHEDULER INTERVAL FOR STATISTICS
;RETURNS +1,
; T1/ TIME IN HP UNITS SINCE ROUTINE LAST CALLED
; SKDLST/ VALUE OF HP TIME NOW

RDSIVL:	JSP 4,MTIME		;READ HP CLOCK
	MOVE 2,SKDLST		;GET LAST PREVIOUS READING OF HP CLOCK
	MOVEM 1,SKDLST		;SET NEW LAST READING
	SUB 1,2			;COMPUTE TIME SPEND IN NULL JOB
	CAIGE T1,0		;OVERFLOW?
	ADD T1,BASOVV		;YES, ADD CORRECTION
	RET
SCHED0::CONSZ PI,177B27		;ANY PI IN PROGRESS?
	BUG(PISKED)
	MOVE P,PI7P		;SETUP LOCAL PDL
	CALL UPDTCK		;UPDATE TODCLK
SCH0:	XCT KEPALV		;DO KEEP ALIVE
	MOVE F,SCHFLG		;SETUP PERM FLAGS
	SKIPL FX,FORKX		;FORK NOW RUNNING?
	CALL UCLOCK		;YES. UPDATE CLOCKS
	CALL SCLDAV		;CHECK LOAD AVS AND LITES
	CALL SKCLK		;UPDATE CLOCKS
	CALL TCLKS		;TEST CLOCKS
	SETZM SKEDF3
	MOVE 4,SCDRQO
	CAME 4,SCDRQI		;ANY REQUESTS?
	CALL SCDRQ1		;YES
;	SKIPGE FORKX
;	CALL SETPSK		;SET PAGING TO SCHED CONTEXT
	CALL SWTST		;CHECK POKE AND SWITCH REQUESTS
	SKIPGE FX,FORKX		;JOB TO CONTINUE?
	CALL SKDJOB		;NO, GO SCHEDULE ONE
	JUMPL FX,SCDNUL		;RUN 'NULL' JOB IF NO FORK TO CONTINUE
	CALL RDSIVL		;READ LAST INTERVAL
	MOVEM 1,SKDLRT		;SAVE IT
	ADDB 1,SKDOVH		;ACCUMULATE SCHED OVERHEAD
	IDIVI 1,NTMS		;CONVERT TO MS.
	MOVEM 1,SKDTM2		;MAINTAIN MS VERSION OF OVH CLOCK
	MOVE T1,SKDLST		;UPDATE FKT0 IN CASE SCHED REENTERED
	MOVEM T1,FKT0
	SKIPGE 1,FKINT(FX)	;PSI REQUEST PENDING?
	JRST SCHED5		;YES, GO CHECK IT
SCHED4:	CALL UPDTCK		;UPDATE TODCLK
	CALL SKCLK		;SET ALARM CLOCK
	SETZM SKEDF3		;NOTE NO PENDING SCHEDULE REQUESTS
	AOS SKEDF1		;SET FLAG FOR CH7 ROUTINE
	ISB SCDCHN		;LET IT START PROCESS
	JRST .			;WAIT FOR PI TO START
SCHED5:	TLNN 1,(1B1)		;PSI NOW BEING DEFERRED?
	SKIPE NSKED		;OR NOSKED FORK?
	JRST SCHED4		;YES, CONTINUE CURRENT SEQUENCE
	MOVSI 1,(1B1)		;CLEAR WORD EXCEPT FOR PI IN PROG
	EXCH 1,FKINT(FX)
	MOVEM 1,PIMSK		;PASS REQUEST WORD TO SERVICE ROUTINE
	DMOVE T1,PFL		;SAVE PROCESS PC FOR PSI HANDLER
	DMOVEM T1,PIFL
	DMOVE T1,[PCU		;SET PPC TO START PSI HANDLER
		0,,PIRQ]
	DMOVEM T1,PFL
	JRST SCHED4		;GO START PROCESS
;UPDATE SCHED CLOCKS AND SET ALARM

SKCLK:	MOVE 1,TODCLK
	EXCH 1,OLDTCK
	SUB 1,OLDTCK		;INTERVAL (NEGATIVE) SINCE LAST UPDATE
	MOVSI 2,-NPCLKS+1	;SCAN CLOCKS EXCEPT BSQNT 
APCLK3:	ADDM 1,TIM1(2)		;COUNTDOWN CLOCK
	AOBJN 2,APCLK3
	SKIPG TIM1		;RESCHED DUE?
	AOS SKEDF3		;YES
	MOVE T3,SKDSCY		;INIT ALARM TO SHORT CYCLE TIME
	MOVEM 3,SCKATM		;SET ALARM TIME
	RET

;TEST PROCESS CLOCKS AND PERFORM ACTIONS ON TIMEOUT

TCLKS:	MOVSI P6,-NPCLKS	;SCAN PROCESS CLOCKS
	SKIPG BSQNT(P6)		;EXHAUSTED? (BSQNT IS FIRST IN TABLE)
	XCT PCLKT(P6)		;YES, SERVICE WHATEVER
	AOBJN P6,.-2
	SKIPE TSKED		;TTY OUTPUT EVENTS?
	CALL CHKTL		;YES, CHECK LIST
	SKIPE PSKED		;RECENT WAKEUP EVENT?
	CALL DISMSJ		;YES, FORCE RESCHEDULE
	RET

;PERFORM ALL PERIODIC ACTIONS

XCLKS:	CALL SKCLK
	MOVSI P6,-NPCLKS+1
	XCT BKGNDT(P6)
	AOBJN P6,.-1
	RET

;TABLE OF SERVICE CALLS FOR PROCESS CLOCKS

PCLKT:	CALL DISMSJ		;RUNNING JOB QUANTUM OVERFLOW
BKGNDT:	CALL SKDLV8		;EVERY TICK STUFF ('LEVEL 8')
	CALL CLK2		;SECOND LEVEL CLOCK
NPCLKS==.-PCLKT
;ACTIONS DONE 'FREQUENTLY' -- EVERY 20 MS

SKDLV8:	CALL RDSIVL		;READ LAST INTERVAL
	MOVEM T1,SKDTHS		;ACCUMULATE SCHED TIME
	CALL LV8CHK		;DO DEVICE-DEPENDENT THINGS
	CALL RCVCH7		;CHECK RCVOK TIMER
	CALL TTCH7		;TTY BIG BUFFER
	CALL REMFPB		;CHECK DELETED PAGE QUEUE
	CALL RDSIVL		;READ LAST INTERVAL
	ADDM T1,BGNDTM		;ACCUMULATE BACKGROUND OVERHEAD TIME
	MOVN T1,SKDTHS		;RESET SCHED OVERHEAD TIME
	ADDM T1,SKDLST
	CALL CLKCHK		;CHECK FORKS WAITING FOR CLOCK
	MOVE T1,SKDSCY		;SET CLOCK TO SHORT CYCLE TIME
	TXNN F,SK%CYT		;NORMAL CYCLE TIMES?
	ASH T1,2		;NO, USE TIMES 4
	MOVEM 1,TIM1
	RET

;SECOND PROCESS CLOCK, LESS PRECISE, UPDATES EVERY 100 MS

CLK2:	CALL DISMSJ		;DISMISS CURRENT FORK, FORCE SKDJOB
	MOVSI 1,(1B1)
	SKIPL SCDRN1		;RUNNING SPECIFIC JOB?
	MOVEM 1,CHKTIM		;YES, DISABLE JOB 0 CHECK
	MOVE 1,TODCLK
	CAML 1,CHKTIM		;JOB 0 OVERDUE?
	BUG(J0NRUN)
	CALL RDSIVL
	MOVEM T1,SKDTHS		;SAVE SCHED OVERHEAD TIME
	MOVE P5,SKDLCY
	TXNN F,SK%CYT		;NORMAL CYCLE TIMES?
	ASH P5,2		;NO, USE TIMES 4
	EXCH P5,TIM2		;SET NEW TIME, GET OLD
	SUB P5,TIM2		;COMPUTE ACTUAL TIME SINCE LAST UPDATE
	MOVSI P4,-N2CLKS	;SET TO SCAN SECOND LEVEL CLOCKS
CLK21:	ADDM P5,CLK2TM(P4)	;UPDATE CLOCK
	SKIPG CLK2TM(P4)	;COUNTED OUT?
	XCT CLK2CL(P4)		;YES, DO WHATEVER
	AOBJN P4,CLK21
	CALL RDSIVL		;READ LAST INTERVAL
	ADDM T1,BGNDTM		;ACCUMULATE BACKGROUND OVERHEAD TIME
	MOVN T1,SKDTHS		;RESET SCHED OVERHEAD TIME
	ADDM T1,SKDLST
	SETZM QSKED
	RET

PI7P::	IOWD NSKDP,SKDPDL
;CHECK LOAD AVS AND LITES

SCLDAV:	MOVE T2,TODCLK
	SUB T2,RJTTIM
	CAIGE T2,^D100		;TIME FOR UPDATE?
	RET			;NO
	MOVE T1,TODCLK		;YES, RESET START OF INTERVAL
	MOVEM T1,RJTTIM
	MOVE T1,NGOJOB		;UPDATE NGOJOB INTEGRAL
	IMUL T1,T2
	ADDM T1,RJTSUM
	MOVE T1,NBPROC
	IMUL T1,T2
	ADDM T1,BSTSUM		;UPDATE NBPROC INTEGRAL
	MOVE T1,NWSMEM
	IMUL T1,T2
	ADDM T1,NWSSUM		;UPDATE NWSMEM INTEGRAL
	MOVE T1,SUMNR		;INTEGRATE SUMNR
	IMUL T1,T2
	ADDM T1,SNRSUM
	MOVE T1,NRPLQ		;INTEGRATE NRPLQ
	IMUL T1,T2
	ADDM T1,RPQSUM
	MOVE T1,NHQFK		;UPDATE HIGH-QUEUE FORKS INTEGRAL
	IMUL T1,T2
	ADDM T1,HQFSUM
	MOVE T1,NLQFK		;UPDATE LOW-QUEUE FORKS INTEGRAL
	IMUL T1,T2
	ADDM T1,LQFSUM
	SKIPE CLASSF		;DOING CLASS SCHEDULING?
	CALL CLSAVG		;YES. INTEGRATE NRUN FOR THE CLASSES
	MOVE 2,TODCLK
	CAML 2,RJATIM		;TIME FOR RJAV UPDATE?
	CALL DORJAV		;YES
	MOVE T1,TODCLK		;GET NOW AGAIN
	CAML T1,UTLTIM		;TIME TO DO CLASS UTILIZATION UPDATES?
	CALL NEWUTL		;YES. DO IT NOW
	RET
;UPDATE RUNNABLE JOB AVERAGES

DORJAV:	MOVEI T1,^D1000		;SET TIME FOR NEXT UPDATE
	ADDM T1,RJATIM
	MOVE T1,RJTSUM		;DO TOTAL AVERAGES
	SUBM T1,RJAVS1
	EXCH T1,RJAVS1
	MOVEI T2,RJAV		;TABLE AT RJAV
	CALL DORJ1
	MOVE T1,HQFSUM		;DO HIGH-QUEUE AVERAGES
	SUBM T1,RJAVS2
	EXCH T1,RJAVS2
	MOVEI T2,HQLAV		;TABLE AT HQLAV
	CALL DORJ1
	MOVE T1,LQFSUM		;DO LOW-QUEUE AVERAGES
	SUBM T1,RJAVS3
	EXCH T1,RJAVS3
	MOVEI T2,LQLAV		;TABLE AT LQLAV
	CALL DORJ1
	SKIPE CLASSF		;DOING CLASS SCHEDULING?
	CALL CLDRJ		;YES. COMPUTE LOAD AVGS FOR THE CLASSES
	FIXR T1,RJAV		;GET INTEGER 1 MIN AVERAGE
	MOVEM T1,IRJAV
	RET
;RUN AVERAGE ROUTINES FOR THE CLASS SCHEDULER

;ROUTINE TO COMPUTE INTEGRALS FOR EACH OF THE CLASSES
;	T2/ TIME INTERVAL

CLSAVG:	MOVEI T3,MAXCLS-1	;SCAN ALL CLASSES
CLSAV0:	LOAD T1,CLGLC,(T3)	;GET GOLST POPULATION
	IMUL T1,T2		;COMPUTE N*dt
	ADDM T1,CLSSUM(T3)	;ACCUMULATE INTEGRAL
CLSAV1:	SOJGE T3,CLSAV0		;DO ALL CLASSES
	RET			;DONE

;ROUITNE TO COMPUTE RUN AVGS FOR THE CLASSES

CLDRJ:	ACVAR <Q1>		;GET A WORK REG
	MOVEI Q1,MAXCLS-1	;SCAN ALL CLASSES
	JFOV .+1		;CLEAR OVERFLOW FLAG
CLDRJ0:	FLTR T1,CLSSUM(Q1)	;GET INTEGRAL
	MOVE T2,CLSSHR(Q1)	;GET SHARE
	CAMGE T2,CLSUTL(Q1)	;GOT ANY WINDFALL?
	MOVE T2,CLSUTL(Q1)	;YES. USE UTIL THEN
	FDVR T1,T2		;SCALE
	JFOV [	FLTR T1,CLSSUM(Q1) ;IF OVERFLOW, USE SUM AS INTEGRAL
		JRST .+1]	;AND PROCEED
	SETZM CLSSUM(Q1)	;NO SUM NOW
	MOVEI T2,0(Q1)		;GET CLASS
	IMULI T2,NRJAVS		;FIND N-WORD CHUNK FOR THIS CLASS
	ADDI T2,CLSRJA		;THE AREA
	CALL DORJ2		;COMPUTE AVERAGES
CLDRJ1:	SOJGE Q1,CLDRJ0		;DO ALL CLASSES
	RET			;DONE
;COMPUTE ONE SET AVERAGES
; T1/ INTEGRAL OVER LAST ONE SECOND
; T2/ TABLE TO BE UPDATED

DORJ1:	FLTR T1,T1		;FLOAT INTEGRAL
DORJ2:	FDVRI T1,(1000.0)	;DIVIDE BY 1 SECOND
	JFOV .+1		;CLEAR OV FLAG
	MOVSI T3,-NRJAVS	;NUMBER ITEMS IN TABLE
	HRLI T2,T3+(IFIW)	;SETUP INDIRECT ADDRESS
SCHC1:	MOVE T4,@T2		;GET PRESENT SUM
	FSBR T4,T1		;COMPUTE SUM-TERM
	FMPR T4,EXPFF(T3)	;COMPUTE (SUM-TERM)*e(-T/C)
	JFOV [	SETZM T4	;IF UNDERFLOW, ASSUME ZERO
		JRST .+1]
	FADR T4,T1		;SUM=(SUM-TERM)e-(T/C)+TERM
	MOVEM T4,@T2		;NEW SUM
	AOBJN T3,SCHC1		;DO ALL TABLE
	RET

;TABLE OF EXP(-T/C) FOR T = 1 SEC.

EXPFF:	EXP 0.983471454		;C = 1 MIN
	EXP 0.996672216		;C = 5 MIN
	EXP 0.998889506		;C = 15 MIN

;TABLE OF 1-EXP(-T/C) FOR T = 1 SEC

   REPEAT 0,<			;DON'T NEED THIS NOW
EXPGF:	EXP 0.0165285462	;C = 1 MIN
	EXP 0.00332778395	;C = 5 MIN
	EXP 0.00111049406	;C = 15 MIN
   >				;END OF REPEAT 0
;TEST WORD DEPOSITED BY SWITCHES IN 20

SWTST:	SKIPE PWRDWN		;POWER DOWN?
	JRST SCHPRF		;YES
	SKIPE SHLTW		;HALT REQUEST?
	JRST SWCRSH		;YES
	SKIPN T1,SCTLW		;SWITCHES?
	RET			;NO, NOTHING TO DO
	SETZM SCTLW
	JFFO 1,.+1
	CAIGE 2,NSWTT
	XCT SWTT(2)
	TXNE T1,1B35		;ALTERNATE MANUAL PAUSE?
	JRST SWHLT		;YES
	TXNE T1,1B34		;RESET PROTOCOL?
	JRST SWRS11		;YES
SWTST1:	RET

SWTT:	JRST SWHLT		;HALT T.S.
	JRST SWTST1		;NOT USED
	JRST SWTST1		;NOT USED
	JRST SCWAIT		;INTERNALLY GENERATED - WAIT FOR DOWN
NSWTT==.-SWTT

SWHLT:	CALL DISMSJ		;DISMISS CURRENT FORK
	CALL SETPSK		;SET SCHED CONTEXT
	SKIPE DDTPRS		;DDT LOADED?
SWHLT4:	XCT CHKADR		;YES, GET BREAKPOINT
	JRST SCHED0		;RESUME SCHEDULER WHEN PROCEEDED

;POWER FAIL DETECTED

SCHPRF:	CALL DISMSJ		;FLUSH CURRENT FORK
	CALL SETPSK		;SET SCHED CONTEXT
	XCT PWRFLE		;DO ANY SPECIAL POWER FAIL CODE
	CALL CASHOF		;MAKE SURE MEMORY IS CORRECT
	JRST SCHPF0		;FINISH IN APRSRV

;RESET FE PROTOCOL

SWRS11:	PIOFF
	JSR BUGMON		;ENTER SECONDARY
	JSR BUGPRI		;ENTER PRIMARY, SHOULD BE IN SYNCH NOW
	PION
	JRST SCHED0		;CONTINUE
SWCRSH:	SETZM SHLTW
	MOVSI 1,(1B3)		;SETUP TO WAIT FOR DDMP COMPLETION
	MOVEM 1,SCTLW
	SETZM DDTIME		;POKE DDMP
	AOS JB0FLG		;DO JOB 0
	SETZ 1,
SWRUN2:	MOVEM 1,SCDRN1		;ALLOW ONLY THAT JOB TO RUN
	CALL DISMSJ		;DISMISS CURRENT FORK
	JRST SWTST1

SCWAIT:	SKIPN DDTIME		;DDMP FINISHED?
	JRST [	MOVSI 1,(1B3)	;REISSUE REQUEST
		MOVEM 1,SCTLW
		JRST SWTST1]
	CALL DISMSJ		;DISMISS CURRENT FORK IF ANY
	CALL SETPSK		;SET SCHED CONTEXT
	SKIPE IOIP		;WAIT FOR IO TO FINISH
	JRST .-1
	HRROI 1,[ASCIZ /**HALTED**
/]
	MOVE 2,CTYLNO
	CALL TTEMES		;ANNOUNCE HALT ON CTY
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST SWHLT5		;NOT ACTIVE. SHOULDN'T HAPPEN
	PUSH P,T2		;SAVE DYNAMIC DATA ADDRESS
SWHL33:	CALL TTCH7		;MAKE SURE CTY OUPTUT IN PROGRESS
	MOVE T2,0(P)		;GET DYNMAIC DATA ADDRESS
	CALL TTSOBE		;SEE IF OUTPUT BUFFER IS EMPTY
	 JRST .-1		;NOT YET. KEEP WAITING
	POP P,T2		;DON'T NEED THIS ANYMORE
SWHLT5:	SKIPN DDTPRS		;DDT PRESENT?
	JRST SWHLT2		;NO, HALT PROCESSOR
	SKIPN DBUGSW		;EXPECTING BREAKPOINTS?
	SKIPE DCHKSW
	JRST SWHLT4		;YES, GET ONE
SWHLT2:
	PIOFF			;STOP ALL INTERRUPTS
	JSR BUGMON		;AND ENTER SECONDARY PROTOCOL
	JRST 4,.+1		;STOP HERE
	JSR BUGPRI		;IF CONTINUES, RESTORE MACHINE
	PION			;ALL OF IT
	JRST SCHED0		;AND RESUME SCHEDULER
;SCHEDULER REQUEST PROCESSOR

;SCDRQ7 CALLED BY ROUTINES HAVING PDL POINTER IN P

SCDRQ7::PIOFF
	JSR SCDRQ
	PION
	RET

;SCDRQ CALLED BY JSR AFTER HAVING TURNED OFF PI SYSTEM

RS SCDRQ,2

SCDRQ0:	MOVEM 1,@SCDRQI
	AOS 1,SCDRQI
	CAIE 1,SCDRQB+NSCDRQ
	JRST SCDRQ2
	MOVEI 1,SCDRQB
	MOVEM 1,SCDRQI
SCDRQ2:	CAMN T1,SCDRQO		;OVERFLOW?
	BUG(SRQOVF)
	JRST @SCDRQ

;PROCESS SCHEDULER REQUESTS

SCDRQ1:	CAMN 4,SCDRQI
	RET
	MOVE 2,0(4)		;WORD CONTAINS DATA,,DISPATCH ADR
	HLRZ 1,2
	HRRZS T2		;GET ADDRESS ONLY
	CALL 0(2)
	AOS 4,SCDRQO
	CAIE 4,SCDRQB+NSCDRQ
	JRST SCDRQ1
	MOVEI 4,SCDRQB
	MOVEM 4,SCDRQO
	JRST SCDRQ1
;SCHEDULER REQUESTS

JOBSRT::HRRE T1,T1		;ARGUMENT MAY BE NEGATIVE IF CRJOB
	MOVEI 2,0(T1)
	CAMN 2,CTYLNO		;CTY?
	JRST JOBSR2		;YES, ALLOW IF AT ALL POSSIBLE
	MOVE 2,SPTC		;CURRENT SPT COUNT
	CAML 2,SPC1		;ABOVE LOGIN LIMIT?
	JRST JOBSR1		;YES, DON'T PERMIT LOGIN
	MOVE 2,DRMFRE
	CAMG 2,DRMIN0		;ENOUGH DRUM SPACE?
	JRST JOBSR1		;NO
JOBSR2:	SKIPE FREJOB		;ROOM FOR NEW JOB
	SKIPN FREFK		;AND NEW FORK?
	JRST JOBSR1		;NO
	MOVE 2,@FREJOB		;ASSIGN JOB NUMBER
	EXCH 2,FREJOB
	SUBI 2,JOBPT
	SETZM JOBIRT(T2)	;NO INCREMENTAL RUN TIME YET
	CAMLE T2,MJBUSE		;HIGHER JOB NUMBER?
	MOVEM T2,MJBUSE		;YES
	LOAD T3,CLSDF		;GET DEFAULT CLASS
	HRRM T3,JOBCLS(T2)	;INIT TO DEFAULT CLASS
	AOS CLSCNT(T3)		;COUNT THIS NEW JOB
	PUSH P,1		;START JOB (FROM TTY SRV)
	PUSH P,2		;SAVE JOB NUMBER
	CALL ASSFK		;GET A FORK
	POP P,2			;RECOVER JOB NUMBER
	STOR 2,FKJOBN		;LEAVE IT IN FORK
	CALL ASFSB		;ASSIGN JSB
	STOR 1,FKJSB
	POP P,1			;RECOVER TTY NUMBER
	HRLI 1,NEWJBF
	IORM 1,FKINT(FX)	;LEAVE TTY NUMBER FOR STARTUP ROUTINE
	CALLRET WTCONC		;PUT FORK ON WAIT LIST

;HERE WHEN CAN'T START THE JOB BECAUSE OF SOME SHORTAGE.  SEND
;'FULL' TO THE LINE

JOBSR1:	JUMPL T1,JOBSRC		;IF CREATE-JOB, GIVE FAIL CODE.
	MOVEI 2,0(T1)		;LINE NUMBER
	MOVE 1,[POINT 7,[ASCIZ /?FULL
/]]
	PUSH P,2		;SAVE
	CALL TTABRT		;CONDITION LINE FOR TTEMES
	CALL TTEMES		;GIVE USER BAD NEWS
	POP P,1			;GET LINE NUMBER
	CALL CHKPTY		;IS THIS A PTY
	 SKIPA			;NO - DONE
	CALL PTYFIN		;YES - MAKE IT HUNGRY
	RET

JOBSRC:	MOVEI T1,CRJBX6		;SYSTEM FULL ERROR CODE
	MOVEM T1,CRJANS		;ANSWER TO OTHER JOB
	RET
;ASSIGN FORK SLOT

ASSFK::	HRRZ FX,@FREFK
	EXCH FX,FREFK		;GET FORK, UPDATE LIST
	SUBI FX,FKPT
	SETZM FKQ2(FX)		;INIT FLAGS AND Q VALUES
	MOVEI 1,JSKP
	MOVEM 1,FKSTAT(FX)	;INIT STATUS
	MOVE 1,QUANTT+INTQ
	STOR 1,FKQTM		;ESTABLISH QUEUE
	MOVE 1,TODCLK
	MOVEM 1,FKTIME(FX)
	MOVEI 1,INTQ
	STOR 1,FKQN
	MOVSI 1,400000+NEWFKF
	MOVEM 1,FKINT(FX)	;LEAVE INTERRUPT REQUEST
	SETZM FKSWP(FX)
	SETZM FKPT(FX)
	SETZM FKINTB(FX)
	SETZM FKPGS(FX)		;CLEAR PT AND PSB WORD
	SETZM FKCNO(FX)
	SETZM FKJOB(FX)
	SETZM FKWSP(FX)
	MOVE 1,[XWD 100100,3]	;INIT AGE TO 100, W.S. TO 3
	MOVEM 1,FKNR(FX)
	CALL ASFSB		;ASSIGN PSB
	STOR 1,FKPSB
	CALL ASFSB		;ASSIGN UPT
	STOR 1,FKUPT
	CALL ASFSB		;GET ONE FOR THE STACK PAGE
	STOR T1,FSSPTN		;SAVE IT
	RET

;PROCESSOR INTERRUPTS REFERRED FROM APR PI SERVICE


MPEINT:	MOVEI 2,.ICDAE		;GIVES I/O ERROR INTERRUPT
	EXCH 1,2		;FORK NUMBER LEFT BY APR ROUTINE
	CALL PSIRQ
	RET
;BALANCE SET SCHEDULER
;CALLED TO SELECT JOB TO RUN

SKDJOB:	SKIPE SKEDFC		;FORCED CLEAR REQUESTED?
	JRST [	SKIPGE SSKED	;YES, A NOSKED FORK?
		JRST SKDJFC	;NO, OK TO DO
		JRST .+1]	;YES, CAN'T DO IT NOW
	CALL TSTBAL		;TEST AND ADJUST BALSET IF NECESSARY
	CALL WSMCHK		;DO PERIODIC WS MGT
	SETZM PSKED
	HRRZ FX,GOLST		;SCAN GOLST FOR FORK TO RUN
SKCB5:	JUMPE FX,BKGND1		;NO RUNNABLE FORK
	SUBI FX,FKPT		;GET FORK INDEX
	MOVE T1,FKSWP(FX)	;GET SWAP FLAGS
	JXE T1,FKWSL,SKCB2	;IF NOT LOADED, SKIP IT
	JXE T1,BSWTB,SKCB3	;JUMP IF RUNNABLE
	CALL SKDJ3		;NO, TEST IT
	 JRST SKCB2		;STILL NOT RUNNABLE
SKCB3:	SKIPL T1,SSKED		;HAVE A NOSKED FORK?
	CAIN FX,0(T1)		;YES, THIS ONE?
	JRST SKDJ2		;OK TO RUN THIS FORK
SKCB2:	HRRZ FX,FKPT(FX)	;CAN'T RUN THIS FORK, GET NEXT IN LIST
	JRST SKCB5
;HAVE RUNNABLE FORK - SET IT UP AND RUN IT

SKDJ2:	AOS NCSWCH		;COUNT CONTEXT SWITCHES
	MOVEM FX,FORKX
	CALL SETPPG		;SETUP PAGER FOR THIS PROCESS
	LOAD T3,FKQTM		;SETUP QUANTUM FOR THIS RUN
	MOVEM T3,BSQNT
	MOVEM T3,BSQNT0
	SETZM FKT1		;CLEAR INCREMENTAL TIME
	CALL XGCCHK		;CHECK FOR XGC NEEDED
	RET			;DONE

;FOUND NO FORK TO RUN

BKGND1:	CALL UPDTCK		;UPDATE TODCLK
	SKIPE NBPROC		;BALSET EMPTY?
	JRST [	CALL WTCHK	;NO, CHECK WAIT LIST ONLY
		JRST BKGND2]
	CALL XCLKS		;DO ALL PERIODIC ACTIONS
	CALL WTCHK		;CHECK WAITING FORKS
	SETZM QSKED
	CALL AJBALS		;CHECK BALSET
BKGND2:	SETO FX,		;NOTE NO FORK TO RUN
	RET

;HERE TO FORCE UNLOAD OF BALSET AND COLLECT ALL OF MEMORY THAT
;ISNT ACTUALLY LOCKED

SKDJFC:	MOVSI FX,-NFKS
SKJFC1:	OPSTR <SKIPE>,FKIBS	;IS THIS FORK IN THE BALANCE SET?
	CALL CLRIBS		;YES. REMOVE IT
	JE FKWSL,,SKJFC3	;JUMP IF WS NOT LOADED
	CALL REMWS		;REMOVE IT
SKJFC3:	AOBJN FX,SKJFC1

;HERE WHEN BALSET UNLOADED, FORCE GCCOR TO FREE MEMORY. GCCOR TAKES
;NOTE OF SKEDFC

SKJFC2:	CALL GCCOR		;GETS PRIVATE PAGES AND SPT PAGES
	SETZM SKEDFC		;CLEAR BLUNDERBUSS FLAG
	JRST SKDJOB		;AND TRY AGAIN.
;TEST WAITING BALSET FORK

SKDJ3:	HRRZ 2,FKPGST(FX)
	HLRZ 1,FKPGST(FX)	;SETUP TEST DATA
	JSP 4,0(2)		;CALL TEST ROUTINE
	 JRST SKDJW		;STILL WAITING
DISMT3:	CALL DISACC		;ACCOUNT FOR WAIT
	HRRZ 1,FKPGST(FX)
	CAIN T1,PRELWT		;PRELOAD WAIT?
	JRST [	SOS NBSWP	;YES. ONE LESS IN SWAP WAIT
		JRST SKDJS2]	;AND WAIT SOME MORE
	CAIE 1,SWPINT		;WAS BEING LOADED?
	RETSKP			;NO, RETURN RUNNABLE
	OPSTR <SKIPN>,PIBMP	;RETURNING TO NORMAL PROCESSING?
	SKIPN PRELDF		;PRELOADING DESIRED?
	JRST SKDJS1		;NO
SKDJS2:	MOVE T1,NRPLQ		;SAVE NUMBER PAGES NOW AVAIL
	ADD T1,IOIP
	PUSH P,T1
	CALL PRELD		;TRY TO PRELOAD
	 JRST [	SETONE BSWTB	;NOT COMPLETE, PUT FORK BACK INTO WAIT
		MOVEM T1,FKPGST(FX) ;WAIT TEST RETURNED BY PRELD
		AOS NBWT	;COUNT IT
		AOS NBSWP	; AS SWAP WAIT
		MOVE 1,TODCLK	;RESET TIME OF START OF WAIT
		MOVEM 1,FKNBW(FX)
		POP P,T1
		SUB T1,NRPLQ	;COMPUTE NUMBER PAGES USED FOR LOAD
		SUB T1,IOIP
		LOAD T2,FKNWCE	;GET PRELOAD RESERVE
		CAMGE T2,T1	;GREATER THAN NUMBER LOADED?
		MOVE T1,T2	;NO, LIMIT
		SUB T2,T1	;REDUCE RESERVE BY AMT LOADED
		STOR T2,FKNWCE
		MOVN T1,T1	;REDUCE TOTAL RESERVE
		ADDM T1,NRPMIN
		JRST SKDJW]
	POP P,T1		;FLUSH TEMP
SKDJS1:	CALL SOSNEB		;PROCESS FINISHED ENTERING BALSET
	RETSKP			;RETURN RUNNABLE

SKDJW:	RET			;RETURN NOSKIP, FORK STILL WAITING
;ACCOUNT FOR BALSET WAIT ON COMPLETION

DISACC:	SETZRO BSWTB		;CLEAR WAIT
	SOS NBWT		;NOW ONE LESS WAITING PROCESS
	MOVE 1,TODCLK		;COMPUTE LENGTH OF TIME WAITED
	SUB 1,FKNBW(FX)
	HRRZ 2,FKPGST(FX)	;WAIT TEST ADR
	ADDM 1,BSWT		;ACCUMULATE TOTAL WAIT
	CAIE 2,SWPINT		;SWAPIN?
	CAIN 2,SWPRT		;OR SWAP?
	JRST [	ADDM T1,DRMWT	;YES, CHARGE TO DRUM
		SOS NBSWP	;REDUCE COUNT OF SWAP WAITS
		CAIN T2,SWPRT	;SWAP-IN?
		CALL CHGHLS	;YES. DO CHARGING THEN
		JRST DISAC1]
	CAIN T2,DWRTST		;WRITE WAIT?
	JRST [	ADDM T1,DWRWT	;YES, CHARGE IT
		JRST DISMT5]
	CAIE 2,UDWDON		;UTILITY DSK? OR
	CAIN 2,DSKRT		;DSK?
	SKIPA			;YES
	JRST DISAC1		;NO, NO CHARGE TO QUANTUM
	ADDM 1,DSKWT		;CHARGE TO DSK
DISMT5:	TXNE F,SK%IOC		;QUANTUM CHARGE FOR IO?
	JRST DISAC1		;NO
	MOVEI T1,^D10*NTMS	;NOMINAL QUANTUM CHARGE
	LOAD 3,FKQTM		;CHARGE AGAINST REGULAR QUANTUM
	CAIG T3,0(T1)		;WILL RESULT BE POSITIVE?
	MOVEI T3,1(T1)		;NO. FORCE IT TO BE SO
	SUB 3,1
	STOR 3,FKQTM
	CALL CHGHLF		;CHARGE FOR FILE READ
DISAC1:	RET

;CHARGE HOLD TIME FOR FAULT

;ENTRY FOR SWAP READ

CHGHLS:	MOVEI T1,2		;ASSUME SMALL CHARGE
	SKIPE PRELDF		;PRELOADING WS?

;ENTRY FOR FILE READ AND FOR SWAP READ IF PRELDF IS ON

CHGHLF:	MOVEI T1,^D10		;LARGE CHARGE
	LOAD T3,FKBET		;GET HOLD TIME
	JUMPE T3,R		;IF NONE, DONE
	SUBI T3,0(T1)		;REDUCE BY QUANTUM CHARGE
	STOR T3,FKBET
	RET			;AND DONE
;UPDATE FOR PROCESS FINISHED ENTERING BALSET

SOSNEB:	LOAD T1,FKNWCE		;WS SIZE RESERVED DURING SWAPIN
	MOVN 1,1
	ADDM 1,NRPMIN		;REMOVE FROM CORE RESERVE
	SOS NEBAL
	RET

;CHECK FORK HAVING DONE EDISMS, BEING HELD IN BALSET

DISMT:	HRRZ 2,FKSTAT(FX)	;SEE IF EDISMS WAIT FINISHED
	HLRZ T1,FKSTAT(FX)
	JSP 4,0(2)
	 CAIA			;NO
	JRST FRIBP1		;YES
	HLRZ T1,FKPGST(FX)	;GET TIME PARAMETER FOR BLOCKW
	JSP 4,BLOCKW		;SEE IF GRACE PERIOD OVER
	 JRST DISMT1		;NO
	CALL DISACC		;YES, ACCOUNT FOR WAIT
	CALL DISMT2		;PUT FORK INTO NORMAL BLOCK STATE
	MOVEI FX,GOLST-FKPT	;REINIT LIST PTR
	JRST SKDJW		;RETURN

DISMT1:	SKIPGE 1,FKINT(FX)	;SEE IF INTERRUPT PENDING
	TLNE 1,(1B1)		;AND ACCEPTABLE
	JRST SKDJW		;NO
	MOVSI 1,PSIWTF		;YES, REMEMBER FORK WAS WAITING
	IORM 1,FKINT(FX)
FRIBP1::JRST DISMT3		;LET IT RUN

DISMT2:	PUSH P,FKNBW(FX)		;SAVE TIME THAT WAIT STARTED
	CALL REMBSJ		;REMOVE JOB FROM BAL SET
	CALL GLREM		;REMOVE FORK FROM GOLST
	POP P,FKPGST(FX)	;SAVE TOD OF DISMISS FOR NEWST
	CALL WTCON2		;PUT ON WAIT LIST
	RET
;CALL PERIODIC WS MGT ROUTINES

WSMPER==^D500			;LENGTH OF PERIOD

WSMCHK:	SETOM RWSOKF		;FLAG TO ALLOW REMWS IN WSMGR
	CALL TSTGCC		;SEE IF GCCOR NEEDED
	 SKIPA			;NO
	CALL DOGCC		;YES, DO IT AND ACCOUNT OVERHEAD
	MOVE T1,SUMNR
	ADD T1,NRPLQ
	ADD T1,IOIP
	CAMGE T1,MAXNR		;UNACCOUNTED PAGES?
	CALL DOGCC		;YES, COLLECT
	MOVE T1,NRPLQ
	ADD T1,IOIP
	CAIGE T1,^D32
	SETZ T1,
	SKIPE NRPLQ
	CAMG T1,NRPMIN		;LOW ON MEM?
	CALL WSMGR		;YES, FIX
	MOVE T1,TODCLK
	CAMGE T1,WSMTIM		;TIME FOR UPDATES?
	JRST WSMCK1		;NO
	ADDI T1,WSMPER		;YES, SETUP NEXT TIME
	MOVEM T1,WSMTIM
	CALL STEPFH		;UPDATE HISTORY VALUES
	CALL WSMGR		;CHECK FOR SWAP
WSMCK1:	SETZM RWSOKF		;RESET FLAG
	RET

;STEP FORK HISTORY VALUES - RUN PERIODICALLY

FHUNIT==1B<^L<FKHST>>		;UNIT VALUE IN HISTORY
STEPTC==^D8			;TIME CONSTANT, LARGER FOR SLOWER CHANGE

STEPFH:	MOVSI FX,-NFKS		;SCAN FORK TABLES
STEPH1:	SKIPGE FKPT(FX)		;FORK EXISTS?
	JRST STEPH2		;NO
	LOAD T3,FKHST
	IMULI T3,STEPTC-1	;COMPUTE H*(X-1)/X
	MOVE T1,FKSWP(FX)	;GET FLAGS
	TXZN T1,FKIBH		;WAS IN BALSET DURING INTERVAL?
	TXNE T1,FKIBS		;FORK NOW IN BALSET?
	ADD T3,[FHUNIT]		;YES, ADD UNIT VALUE
	HLLM T1,FKSWP(FX)	;UPDATE FLAGS
	IDIVI T3,STEPTC
	STOR T3,FKHST
STEPH2:	AOBJN FX,STEPH1
	RET
;GET FORK HISTORY VALUE
;VALUE USED TO RANK FORK WORKING SETS PRIORITY IN MEM
;GREATER NUMBER MEANS HIGHER PRIORITY
; FX/ FORK INDEX

;VALUES IN RESULT

FHMNSK==4000B17			;NOSKED, TOP PRIORITY
FHMRUN==2000B17			;RUNNABLE
FHMPQ==  400B17			;PRIORITY QUEUE
FHMBS==  200B17			;IN BALSET
FHMCSK== 100B17			;CRITICAL SECTION
FHMBIP==40B17			;PI BUMP
;FHMWTS==  70B17			;WAIT STATE CODE

GFHST:	MOVE T4,FKSWP(FX)	;GET SWAP FLAGS
	SETZ T1,		;START WITH 0
	OPSTR <SKIPE>,PIBMP	;FORK NEEDS BUMPING FOR PI?
	ADD T1,[FHMBIP]		;YES. GIVE IT HELP THEN
	TXNE T4,BSNSK		;NOSKED?
	ADD T1,[FHMNSK]		;YES, PRIORITY
	TXNE T4,BSCRSK		;CRITICAL SECTION?
	ADD T1,[FHMCSK]		;YES
	LOAD T2,FKQN
	CAIG T2,HIGHQ		;ON PRIORITY QUEUE?
	ADD T1,[FHMPQ]		;YES, BUMP
	TXNN T4,FKBLK		;FORK RUNNABLE?
	JRST GFHST1		;YES
	LOAD T2,FKGOLN		;NO, GET BLOCK WAIT PRIORITY
	;STOR T2,FHMWTS,T1	;INCLUDE IN HISTORY WORD
	OPSTR <ADD T1,>,FKHST	;USE HISTORY VALUE
	RET

GFHST1:	ADD T1,[FHMRUN]		;YES, MAKE IT BETTER THAN ALL BLOCKED FORKS
	TXNE T4,FKIBS		;IN BALSET?
	ADD T1,[FHMBS]		;YES, BASIC UNIT VALUE
	OPSTR <ADD T1,>,FKGOLN	;GOLST POSITION IS FINAL DETERMINANT
	RET
;WORKING SET MANAGER
;SELECT WORKING SETS TO SWAP INTO OR OUT OF MEMORY

WSMGR:	TRVAR <MAXWS,MAXWSF,MINWS,MINWSF,WSMSUP,WSMSNR>
	MOVEI T4,NFKS		;ASSIGN GOLST POSITION TO ALL FORKS ON GOLST
	HRRZ FX,GOLST
WSMGS1:	JUMPE FX,WSMG0		;JUMP IF END OF LIST
	MOVEI FX,-FKPT(FX)	;GET FORK INDEX
	STOR T4,FKGOLN		;STORE POSITION
	HRRZ FX,FKPT(FX)	;STEP LIST
	SOJA T4,WSMGS1		;STEP POSITION NUMBER

WSMG0:	MOVSI FX,-NFKS		;SCAN FORK TO SELECT WORST IN-MEMORY
	SETZM WSMSUP		; FORK AND BEST NOT-IN-MEM FORK
	SETZM WSMSNR		;INIT SUMNR COUNT
	MOVX T1,1B1
	MOVEM T1,MINWS
	MOVNM T1,MAXWS
	SETOM MINWSF
WSMG2:	MOVE T1,FKSWP(FX)	;GET SWAP FLAGS
	TXNE T1,FKWSL		;WS IN MEM?
	JRST [	LOAD T2,FKWSS	;YES, COMPUTE TOTAL 
		ADDM T2,WSMSNR
		LOAD T2,FKCSIZ
		ADDM T2,WSMSUP	;TOTAL USED PAGES
		CALL GFHST	;GET HISTORY VALUE
		CAML T1,MINWS	;HAVE NEW MINIMUM?
		JRST WSMG1	;NO
		MOVEM T1,MINWS	;YES, SAVE VALUE AND FX
		HRRZM FX,MINWSF
		JRST WSMG1]
	TXNN T1,FKIBS		;NOT IN MEM, WANTS TO BE?
	JRST WSMG1		;NO
	CALL GFHST		;WS NOT IN MEM, GET HISTORY VAL
	CAMG T1,MAXWS		;NEW MAX?
	JRST WSMG1		;NO
	MOVEM T1,MAXWS		;YES, SAVE VALS
	HRRZM FX,MAXWSF
WSMG1:	AOBJN FX,WSMG2
	; ..
	; ..
	MOVE T4,WSMSNR		;CHECK TOTAL
	PIOFF			;PREVENT CHANGE AT INT LEVEL
	MOVE T3,SUMNR
	ADD T4,BALSHC
	PION
	CAME T4,T3
	JRST [	MOVE T3,SUMNR
		BUG(SUMNR2,<<T3,D>,<T4,D>>)
		MOVEM T4,SUMNR
		JRST .+1]
	SKIPN RWSOKF		;REMWS OK HERE?
	JRST WSMG6		;NO, NO SWAPOUTS
WSMG8:	MOVE T1,NRPLQ
	ADD T1,IOIP		;CHECK AVAILABLE MEM
	SKIPE NRPLQ
	CAMG T1,NRPMIN		;LOW?
	JRST WSMG4		;YES, DO SOMETHING ABOUT IT
	SKIPGE FX,MINWSF	;HAVE FORK WHICH COULD GO OUT?
	JRST WSMG6		;NO
	JN FKIBS,,WSMG6		;JUMP IF IT BELONGS IN BALSET
	CAIGE T1,^D32		;DOESN'T, MEM GETTING LOW?
	JRST WSMG4		;YES, FLUSH IT
WSMG6:	SKIPGE MAXWS		;HAVE A FORK WAITING TO COME IN?
	JRST WSMG3		;NO
	MOVE FX,MAXWSF		;YES, GET ITS FX
	MOVE T1,MAXWS		;SEE IF BEST NOT-IN-MEM IS BETTER THAN
	SKIPL MINWSF		; WORST IN-MEM (OR NONE IN MEM)
	CAMLE T1,MINWS
	JRST WSMG5		;YES, LOAD
	LOAD T1,FKWSS		;ELSE, SEE IF FORK WOULD FIT WITH OTHERS
	ADD T1,SUMNR
	CAML T1,MAXNR		;FITS?
	JRST WSMG3		;NO, DO NOTHING
WSMG5:	CALL LOADWS		;LOAD FORK
	 JRST WSMG3		;COULDN'T
	JRST WSMG0		;RECHECK
WSMG4:	MOVE T2,SUMNR		;MEM DEFINITELY OVERLOADED?
	CAMGE T2,MAXNR
	JRST [	ADD T2,IOIP	;INCLUDE PAGES DUE
		CAML T2,MAXNR	;STILL UNDER LIMIT?
		JRST WSMG6	;NO, DO NOTHING
		CALL DOGCC	;COLLECT UNASSIGNED PAGES
		MOVE T2,SUMNR	;RECHECK LIMIT
		CAMGE T2,MAXNR
		JRST WSMG6	;UNDER, CONTINUE
		JRST .+1]	;OVER, REMOVE SOMETHING
	MOVE T1,NWSMEM
	CAIG T1,1		;MORE THAN ONE FORK IN MEM?
	JRST [	CALL DOGCC	;NO, CLEAR OUT SHARED PAGES
		JRST WSMG6]	;AND LEAVE FORK AS IS
	SKIPGE FX,MINWSF	;HAVE A FORK TO REMOVE?
	JRST WSMG3		;NO, DO NOTHING NOW
	MOVX T1,FKBLK
	TDNN T1,FKSWP(FX)	;FORK BLOCKED?
	AOS NREMR		;NO, COUNT SWAPOUT OF RUNNABLE FORK
	CALL REMWS
	SKIPN POSPGF		;POST PURGE DONE?
	CALL FKGC		;NO, REMOVE FORK PAGES
	JRST WSMG0		;RECHECK

WSMG3:	RET			;DONE

;DO GCCOR AND SWITCH OVERHEAD CHARGING

DOGCC:	CALL RDSIVL		;YES, SWITCH OVERHEAD CHARGING
	MOVEM T1,SKDTHS
	CALL GCCOR
	CALL RDSIVL		;READ LAST INTERVAL
	ADDM T1,GCCTIM		;ACCUMULATE GCCOR TIME
	MOVN T1,SKDTHS		;RESET SCHED OVERHEAD TIME
	ADDM T1,SKDLST
	RET
;ADJUST CONTENTS OF BALANCE SET
;SCAN DOWN GOLIST, REMOVING OR ADDING PROCESSES TO BALSET
; AS APPROPRIATE

AJBYPF==1B0			;LOCAL FLAG - PASSED A NON-BALSET FK
AJNNLF==1B1			;NO NEW LQ FORKS
AJHQOF==1B2			;HQ FORKS ONLY
AJLHTF==1B3			;USE LONG HOLD TIME

;LOCAL VARS - PAIRS MUST BE IN ORDER

RS AJBNHQ,1			;RUNNING NUMBER HQ FORKS
RS AJBNLQ,1			;RUNNING NUMBER LQ FORKS

RS AJBHQP,1			;RUNNING TOTAL HQ PAGES
RS AJBLQP,1			;RUNNING TOTAL LQ PAGES

RS NXTAJB,1			;TIME NEXT AJBALS DUE
RS AJBFLG,1			;PERMANENT FLAGS

BSPAD==^D20			;PAD FOR BALSET SUM
BSPADO==^D10			;POS OR NEG OFFSET FOR REMOVING OR LOADING

;TEST FOR AJBALS NECESSARY BEFORE SELECTING FORK TO RUN

TSTBAL:	MOVE T1,MAXNR
	CAMGE T1,SUMBNR		;MEM OVERCOMMITTED?
	JRST TSTBL1		;YES, ADJUST
	MOVE T1,TODCLK
	CAMGE T1,NXTAJB		;TIME FOR PERIODIC CHECK?
	RET			;NO, DO NOTHING
TSTBL1:	AOS NAJBAL		;COUNT FORCED CALLS
	CALLRET AJBALS		;DO IT
;ADJUST BALANCE SET

AJBALS:	TRVAR <AJLODN,AJBLFK,AJBBSC,PRIPST>
	;ACS Q1,Q2,FX,P1,P2 SHOULD BE SAVED HERE
	SKIPE PAGDIF		;NEW PAGES IN SYSTEM?
	CALL ADJSWP		;YES. ADJUST PAGING TO MATCH NEW STATE
	SETOM PRIPST		;NO SKIPPED PROCESS YET
	SETZM AJLODN		;NUMBER FORKS LOADED ON THIS CALL
	SETZM AJBNHQ		;INIT VARIABLES
	SETZM AJBNLQ
	SETZM AJBHQP
	SETZM AJBLQP
	SETOM AJBLFK
	HLL F,AJBFLG		;GET PERM FLAGS
	SKIPN CLASSF		;NON-CLASS SCHEDULER?
	TXNN F,SK%HQR		;HQ DISASTER AVOIDANCE?
	JRST AJBS1		;NO
	MOVE T1,HQLAV		;YES, GET CURRENT HQ LDAV
	CAMGE T1,HQLEV1		;BELOW TURN OFF POINT?
	TXZ F,AJNNLF		;YES
	CAML T1,HQLEV2		;ABOVE TURN ON POINT?
	TXO F,AJNNLF		;YES
	CAMGE T1,HQLEV3		;BELOW TURN OFF POINT?
	TXZ F,AJHQOF		;YES
	CAML T1,HQLEV4		;ABOVE TURN ON POINT?
	TXO F,AJHQOF		;YES
AJBS1:	MOVE T1,MAXNR		;SET LIMIT FOR HOLDING FORKS
	SUBI T1,100
	MOVEM T1,MAXHNR		;HOLD LIMIT
	SETZM BSKED
	SETZ Q1,			;INIT NBP COUNT
	MOVE 4,BALSHC		;INIT SUMNR COUNT
	ADDI T4,BSPAD		;INCLUDE PAD
	MOVEM T4,AJBBSC		;SAVE BASE
	MOVEI Q2,BSLST		;SCAN LIST OF RECENT BALSET ENTRIES
AJBS2:	HRRZ Q2,0(Q2)		;GET NEXT
	JUMPE Q2,AJBAL4		;JUMP IF END OF LIST
	MOVEI FX,-FKBSPW(Q2)
	SETZRO FKBSHF		;ASSUME NOT HOLDING
	LOAD T1,FKBET		;GET HOLD EXPIRATION TIME
	LOAD T2,FKJOBN
	SUB T1,JOBRT(T2)	;COMPUTE TIME REMAINING
	TXNE T1,FKBETH		;NEGATIVE NUMBER? (CHECK HIGH-ORDER BIT)
	JRST [	SETZRO FKBET	;YES, SET TIME EXPIRED
		CALL REMBSL	;REMOVE FROM PROTECT LIST
		JRST AJBS2]
	LOAD T1,FKWSS
	ADD T1,T4
	SUBI T1,BSPAD
	CAMLE T1,MAXHNR		;ROOM TO HOLD FORK?
	JUMPG Q1,AJBS2		;NO (UNLESS FIRST FORK SEEN)
	SETONE FKBSHF		;SET HOLD FLAG
	CALL AJBUQS		;STILL HOLDING, COUNT PAGES
	ADDM T1,T4
	AOJA Q1,AJBS2
;SCAN GOLST CHECKING ALL FORKS, AND REMOVE, LOAD, OR
;LEAVE AS IS.

AJBAL4:	TXZ F,AJBYPF		;INIT FLAG
	MOVEI Q2,GOLST
AJBAL1:	HRRZ Q2,0(Q2)		;GET NEXT
AJBL10:	JUMPE Q2,AJBALX		;DONE IF REACHED END OF GOLST
	MOVEI FX,-FKPT(Q2)	;GET FORK INDEX
	LOAD P2,FKQN		;CHECK FORK QUEUE
	CAIGE P2,MAXQ		;HIGH QUEUES?
	TDZA P2,P2		;YES, USE 0 INDEX
	MOVEI P2,1		;NO, USE 1 INDEX
	JE FKIBS,,AJBAL5	;JUMP IF NOT IN BALSET
FRIBP0:	MOVE CX,FKSWP(FX)	;GET FLAGS
	TXNE CX,FKBSHF		;HELD?
	JRST AJBAL1		;YES. ALREADY ACCOUNTED
	TXNE CX,BSNSK!BSCRSK	;NOSKED OR CRSKED?
	JRST AJBL77		;YES. TRY TO KEEP IT THEN
	JN PIBMP,,AJBL77	;KEEP IF PI'ING
	SKIPLE CLASSF		;WITHHOLDING WINDFALL?
	JRST [	CALL CKAHED	;YES. IS THIS ONE AHEAD?
		 JRST .+1	;NO. PROCEED
		JRST AJBL9]	;YES, REMOVE FROM BALSET AND MEM
	TXNE F,AJHQOF		;HQ FORKS ONLY?
	JUMPN P2,AJBL9		;YES, FLUSH IF LQ
	JUMPE Q1,AJBAL7		;NO FURTHER CHECKS IF FIRST FORK SEEN
AJBL77:	LOAD 1,FKWSS
	ADD 1,4
	SUBI T1,BSPAD		;REDUCE BY PAD OFFSET
	CAMG Q1,MAXBP		;FORK STILL FITS IN BALSET?
	CAMLE 1,MAXNR
	JRST AJBL12		;NO
AJBAL7:	LOAD T1,FKWSS		;GET SIZE
	ADDM T1,4		;UPDATE SUM
	CALL AJBUQ0		;UPDATE QUEUE SUMS
	AOJA Q1,AJBAL1		;COUNT FORK

;HERE IF FORK NOW IN BALSET DOESN'T APPEAR TO FIT.

AJBL12:	HRRZ Q2,0(Q2)		;STEP LIST
	CALL CLRIBS		;NOTE NOT IN BALSET
	TXON F,AJBYPF		;NOTE PASSED A FORK NOT IN BALSET
	CALL SETPRP		;IF FIRST ONE, DO PRIORITY STUFF
	AOS NREMJ		;NOTE FORCED REMOVALS
	JRST AJBL10

;HERE TO REMOVE FORK FROM BALSET AND SWAPOUT IMMEDIATELY

AJBL9:	CALL CLRIBS
AJBAL2:	JE FKWSL,,AJBAL1	;JUMP IF WS NOT LOADED
	HRRZ Q2,0(Q2)		;STEP LIST
	PUSH P,T4		;SAVE SUMBNR COMPUTATION
	CALL REMWS		;SWAPOUT
	POP P,T4		;RESTORE LOCAL SUMBNR
	JRST AJBL10
;FORK NOT NOW IN BALSET

AJBAL5:	SKIPLE CLASSF		;WITHHOLDING WINDFALL?
	JRST [	CALL CKAHED	;YES. IS THIS FORK AHEAD?
		 JRST .+1	;NO. PROCEED
		JRST AJBAL2]
	SKIPL SPMLCK		;SOMEONE TRYING TO GET A PAGE?
	JRST [	CALL TSTFRP	;YES. IS THIS FORK HOARDING THE PAGE?
		 JRST AJBAL1	;YES. DON'T LOAD IT
		JRST .+1]	;NO. GO ON
	JUMPE Q1,AJBAL6		;NO FURTHER CHECKS IF FIRST FORK SEEN
	LOAD T1,FKWSS		;CHECK SIZE
	ADD T1,T4			;BALSET SUM WHICH WOULD INCLUDE THIS FORK
	ADDI T1,BSPADO		;INCREASE BY PAD OFFSET
	CAMGE Q1,MAXBP		;ROOM IN BALSET FOR ANOTHER FORK?
	CAMLE T1,MAXNR		;ROOM FOR THIS FORK'S PAGES?
	JRST AJBL11		;NO
	TXNE F,AJNNLF		;ALLOW NEW LQ FORKS?
	JUMPN P2,AJB666		;NO. IF LQ CHECK FOR SPECIAL LOADING
	SKIPE CLASSF		;CLASS SCHEDULING BEING USED?
	TXNN F,AJBYPF		;YES. BYPASSED ANYBODY?
	SKIPA			;NO
	JRST [	CALL CORFCT	;YES. GET PRIORITY OF THIS PROCESS
		CAMGE T1,PRIPST	;THIS ONE LOWER THAN ONE PASSED?
		JRST AJB667	;YES. CHECK FOR SPECIAL LOAD
		CALL SETIBS	;NO. LOAD IT THEN
		JRST AJBAL7]	;AND PROCEED
AJBAL6:	CALL SETIBS		;NOTE IN BALSET
	TXNE F,SK%HT2		;NO HOLD TIME IF SKIPPED PROCESS?
	TXNN F,AJBYPF		;YES, SKIPPED A PROCESS?
	JRST AJBAL7		;NO. ACCOUNT FOR IT
AJBL69:	SETZRO FKBET		;YES. NO HOLD TIME NOW
	CALL REMBSL		;REMOVE FROM PROTECTED LIST
	JRST AJBAL7		;AND PROCEED

AJBL11:	TXON F,AJBYPF		;NOTE PASSED A FORK NOT IN BALSET
	CALL SETPRP		;IF FIRST TIME, DO PRIROITY STUFF
	JRST AJBAL1
;FORK CANNOT BE LOADED ACCORDING TO NORMAL RULES. CHECK FOR SPECIAL
;LOADING CRITERIA

AJB666:	SKIPA T1,[AJBAL1]	;WHERE TO GO
AJB667:	MOVEI T1,AJBL11		;WHERE TO GO
	JN BSCRSK,,AJB668	;IF CRSKED, LOAD IT
	JN PIBMP,,AJB668	;OR IF PI ALSO
	JRST 0(T1)		;CAN'T LOAD IT, GIVE UP
AJB668:	CALL SETIBS		;PUT IN BALSET
	JRST AJBL69		;BUT NO HOLD TIME

;UPDATE RUNNING QUEUE SUMS

AJBUQS:	LOAD P2,FKQN		;SET QUEUE SET INDEX
	CAIGE P2,MAXQ
	TDZA P2,P2		;USE 0 FOR INTERACTIVE QUEUES
	MOVEI P2,1		;1 FOR COMPUTE QUEUE
AJBUQ0:	LOAD T1,FKWSS		;UPDATE FOR CURRENT FORK
	ADDM T1,AJBHQP(P2)	;COUNT PAGES
	AOS AJBNHQ(P2)		;COUNT FORKS
	RET

;ROUTINE OF AJBALS TO HANDLE FIRST INSTANCE OF A FORK THAT
;WON'T FIT

SETPRP:	SKIPN CLASSF		;CLASS SCHEDULING?
	RET			;NO. NOTHING TO DO HERE THEN
	CALL CORFCT		;YES. GET PRIROITY OF THIS PROCESS
	CAMLE T1,[1.0]		;ONE OF THE COMPUTING PROCESSES?
	JRST [	TXZ F,AJBYPF	;NO. IGNORE THE SKIP THEN
		RET]		;AND DONE
	MOVEM T1,PRIPST		;SAVE PRIORITY OF THIS PROCESS
	RET			;AND DONE

;EXIT FROM AJBALS

AJBALX:	SUB T4,AJBBSC		;REMOVE PAD AND ORIG BALSHC
	PIOFF			;PREVENT CHANGE AT INT LEVEL
	MOVE T3,SUMBNR
	ADD T4,BALSHC		;INCLUDE CURRENT BALSHC
	PION
	CAME T4,T3		;CHECK SUM
	JRST [	MOVE T3,SUMBNR
		BUG(SUMNR1,<<T3,D>,<T4,D>>)
		MOVEM T4,SUMBNR
		JRST .+1]
	MOVE T1,TODCLK		;SET TIME FOR NEXT PERIODIC CALL
	ADD T1,AJBLCY
	MOVEM T1,NXTAJB
	MOVEM F,AJBFLG		;SAVE NEW SETTINGS
	MOVE T1,AJLODN		;RETURN COUNT OF FORKS LOADED THIS CALL
	RET
;CHECK FOR POSSIBILITY OF LOADING FORK INTO BALSET

CHKTFK:	SAVEQ
	MOVEI Q2,GOLST
CHKTF1:	HRRZ Q2,0(Q2)		;GET NEXT FORK ON GOLST
	JUMPE Q2,R		;DONE WHEN LIST NULL
	MOVEI FX,-FKPT(Q2)	;GET FORK INDEX
	JN FKIBS,,CHKTF1		;JUMP IF FORK IN BALSET
	SKIPL SPMLCK		;IS SOME FORK TRYING TO GET A PAGE?
	JRST [	CALL TSTFRP	;YES. IS THIS FORK GUILTY OF HOLDING IT?
		 JRST CHKTF1	;YES. SKIP IT THEN
		JRST .+1]	;NO. PROCEED
	CALL TRYLDF		;SEE IF IT CAN BE LOADED
	 RET			;COULDN'T, TRY NO MORE
	JRST CHKTF1		;COULD, TRY AGAIN
;CHECK SPECIFIC FORK FOR LOADING INTO BALSET
;N.B. (THIS IS A MONUMENT). THIS CODE SHOULD NEVER BE
;CALLED TO LOAD A FORK OF LOWER PRIORITY THAN ONE NOT LOADED.
;THAT IS, IF A FORK HIGHER ON GOLST CAN NOT BE LOADED, THEN
;DON'T CALL TRYLDF TO LOAD THIS ONE. PRESENTLY, CHKTFK IS
;THE ONLY USER OF TRYLDF AND IT DOES THE RIGHT THING.
;WOE BE TO HE (OR HER) THAT VIOLATES THIS TRUST.

TRYLDF:	MOVE T2,AJBFLG		;GET AJBALS PERMANENT FLAGS
	JN BSCRSK,,TRYLD0	;IF CSKED, ALWAYS TRY
	JN PIBMP,,TRYLD0	;IF PI'ING, ALSO LOAD
	TXNE T2,AJNNLF		;LQ FORK ALLOWED?
	JRST [	LOAD T1,FKQN	;NO
		CAIL T1,MAXQ	;THIS FORK LQ?
		RET		;YES, DON'T LOAD
		JRST .+1]	;OK
	SKIPLE CLASSF		;CLASS SCHED?
	JRST [	CALL CKAHED	;WINDFALL?
		 JRST .+1	;NO. OK TO LOAD?
		JRST TRYLD2]	;NO, DON'T LOAD
TRYLD0:	LOAD T1,FKWSS		;GET WS SIZE
	ADDI T1,BSPAD		;INCREASE BY PAD AND OFFSET
	ADD T1,SUMBNR		;COMPUTE BALSET SIZE WITH FORK
	CAML T1,MAXNR		;FORK WS FITS?
	JRST TRYLD2		;NO, DON'T LOAD
	CALL SETIBS		;NOTE FORK IN BALSET
	MOVE T1,FKSWP(FX)
	TXNN T1,FKWSL		;WS NOW LOADED?
	SETZM WSMTIM		;NO, CHECK SOON
	RETSKP			;DONE

TRYLD2:	RET
;REMOVE FORK FROM BALSET WHEN BLOCKING

REMBSJ:	JE FKIBS,,R		;RETURN IF ALREADY OUT
	CALL CLRIBS
	LOAD T1,FKWSS
	LOAD T2,FKCSIZ
	ADDI T2,4
	CAMGE T2,T1		;WS SMALLER NOW?
	CALL [	MOVE T1,T2	;YES, REDUCE RESERVE
		CALLRET ADJWSS]
	HLRZ 2,FKJOB(FX)	;MAINTAIN SUBSYSTEM INFO...
	HRRZ 2,JOBNAM(2)
	HRRZ 1,FKNR(FX)
	ADDM 1,SSIZE(2)		;INTEGRATE WS SIZE
	AOS SNBLKS(2)		;AND COUNT NUMBER OF SAMPLES
	RET

;NOTE FORK IN/OUT OF BALSET, MAINTAIN COUNT
; FX/ FORK INDEX

SETIBS:	SETONE <FKIBS,FKIBH>
	SETZRO FKBSHF		;INIT HOLD FLAG
	JXE F,SK%HT1,SETIB2	;ALWAYS DO HOLD IF SK%HT1 0
	MOVE T1,NBSL		;NUMBER HOLDING FORKS
	CAIL T1,2		;ENOUGH NOW?
	JRST SETIB1		;YES, NO MORE
	JUMPE T1,SETIB2		;GIVE HOLD TIME IF NO OTHERS
	MOVE T1,SUMBNR
	ASH T1,1
	CAML T1,MAXNR		;IF 1 OTHER, GIVE HOLD TIME IF
	JRST SETIB1		; BALSET LESS THAN HALF FULL
SETIB2:	CALL APPBSL		;APPEND FORK TO BALSET LIST
	MOVEI T2,^D10000	;MAX HOLD TIME IF BIAS SCHEDULER
	SKIPE CLASSF		;IS IT?
	MOVEI T2,UTLINI*UTLTMI	;NO. SET TO NEWUTL CYCLE THEN
	LOAD T1,FKWSS		;COMPUTE HOLD TIME AS SIZE * 20 MS
	IMULI T1,^D20
	CAIGE T1,^D1000		;AT LEAST 1 SEC
	MOVEI T1,^D1000
	CAILE T1,0(T2)		;OVER MAX LIMIT?
	MOVEI T1,0(T2)		;YES. APPLY LIMIT THEN
	LOAD T2,FKJOBN
	ADD T1,JOBRT(T2)	;COMPUTE EXPIRATION TIME
	STOR T1,FKBET
SETIB1:	LOAD T1,FKWSS
	ADDM T1,SUMBNR		;UPDATE BALSET SUM
	AOS NBPROC
	RET

CLRIBS:	SETZRO <FKIBS,FKBET>
	CALL REMBSL		;REMOVE FORK FROM LIST
	LOAD T1,FKWSS
	MOVN T1,T1
	ADDM T1,SUMBNR		;UPDATE BALSET SUM
	SOS NBPROC
	RET
;APPEND FORK TO BALSET LIST

APPBSL:	SAVEAC <Q1,Q2>
	MOVEI Q1,BSLST
APPBS1:	HRRZ Q2,0(Q1)		;GET NEXT, SAVE PREV PTR
	JUMPN Q2,[MOVE Q1,Q2	;STEP AGAIN IF NOT END OF LIST
		JRST APPBS1]
	MOVEI Q2,FKBSPW(FX)	;END OF LIST, MAKE PTR TO NEW FORK
	HRRM Q2,0(Q1)		;APPEND
	HLLZS FKBSPW(FX)	;MARK NEW END
	AOS NBSL		;MAINTAIN COUNT
	RET

;REMOVE FORK FROM BALSET LIST

REMBSL:	MOVEI T1,BSLST
CLRIB1:	HRRZ T2,0(T1)		;GET NEXT, SAVE PREV
	JUMPE T2,R		;NOT ON LIST, IGNORE
	CAIE T2,FKBSPW(FX)	;DESIRED ONE?
	JRST [	MOVE T1,T2	;NO, STEP
		JRST CLRIB1]
	HRRZ T2,0(T2)		;SPLICE LIST
	HRRM T2,0(T1)
	SOS NBSL		;MAINTAIN COUNT
	RET

;CHANGE FKNR, UPDATE SUMNR IF NECESSARY
; T1/ NEW VALUE OF FKNR
; FX/ FORK INDEX

ADJWSS::JE FKWSL,,ADJWS1	;JUMP IF FORK WS NOT LOADED
	LOAD T2,FKWSS		;WS IN MEM, MUST UPDATE SUMNR
	SUBM T1,T2		;GET DIFFERENCE
	ADDM T2,SUMNR		;ADJUST SUMNR
ADJWS1:	STOR T1,FKWSS		;SET NEW VALUE
	RET
;REMOVE FORK WORKING SET FROM MEMORY
;REMWSN - REMOVE WORKING SET WITHOUT POSTPURGING

REMWS:	JE BSWTB,,REMWS1	;JUMP IF FORK NOT IN WAIT
	CALL DISACC		;TERMINATE WAIT
	HRRZ T1,FKPGST(FX)
	CAIN T1,DISMT		;HDISMS?
	JRST [	CALL DISMT2	;YES, CLEAN UP
		JRST REMWS1]
	CAIE T1,PRELWT		;ENTERING?
	CAIN T1,SWPINT
	CALL SOSNEB		;YES, CLEAN UP
REMWS1:	SKIPE POSPGF		;POSTPURGING?
	JRST [	JSP T4,SWPINT	;YES, PSB AND UPT IN CORE?
		 JRST .+1	;NO, DON'T DO IT
		CALL WSSWPO	;YES, DO IT
		JRST REMBS7]
REMWSN:	MOVSI 2,(-PLKV)
	MOVSI T4,-NFKSPP	;UNLOCK ALL SPECIAL PAGES
REMBS6:	XCT FKSPPT(T4)		;GET PAGE ID
	HRRZ T1,SPT(T1)		;GET CORE ADDRESS
	ADDM T2,CST1(T1)	;UNLOCK IT
	AOBJN T4,REMBS6
REMBS7:	LOAD T2,FKWSS		;GET CURRENT RESERVE
	MOVN 1,2
	ADDM 1,SUMNR		;REDUCE BALSET SIZE
	SETZRO FKWSL		;WORKING SET NOT LOADED NOW
	SOS NWSMEM
	RET

;TABLE OF SPECIAL FORK PAGES
;EXECUTED BY LOADBS, REMBSJ, WSSWPO

FKSPPT::HRRZ T1,FKPGS(FX)	;PSB
	HLRZ T1,FKPGS(FX)	;UPT
	LOAD T1,FKJSB		;JSB
	LOAD T1,FSSPTN		;SECOND PSB
NFKSPP==:.-FKSPPT
;LOAD WORKING SET INTO MEMORY

LOADWS:	MOVE T1,NRPLQ
	CAIG T1,NFKSPP		;ENOUGH PAGES TO START LOAD?
	RET			;NO
	SAVEAC <P2>
LDJB3::	AOS NWSMEM		;COUNT NUMBER OF PROCESSES
	SETONE <BSWTB,FKWSL>	;SET FLAGS, WS LOADED AND WAITING
	MOVEI 1,SWPINT
	MOVEM 1,FKPGST(FX)	;SET TEST TO WAIT FOR PSB AND PT
	HRRZ 1,FKNR(FX)		;GET WORKING SET SIZE
	HRRZ 2,FKWSP(FX)	;PAGES NOW ASSIGNED
	CAMGE 1,2		;REASONABLE VALUES?
	JRST FIXWSP		;NO
LDJB5:	ADDM 1,SUMNR		;UPDATE SUM OF NR
	SUB T1,T2		;REDUCE RESERVE BY PAGES ALREADY ASSIGNED
	SKIPN PRELDF		;PRELOADING?
	MOVEI T1,NFKSPP		;NO, USE SMALL CONSTANT
	STOR T1,FKNWCE		;SAVE PRELOAD RESERVE
	ADDM T1,NRPMIN		;ADDITIONAL RESERVE FOR ENTERING FORKS
	AOS NEBAL		;COUNT ENTERING PROCESSES
	MOVSI P2,-NFKSPP	;SWAPIN ALL SPECIAL PAGES
LDJB1:	XCT FKSPPT(P2)
	CALL SWPIN0
	AOBJN P2,LDJB1
	AOS NWSLOD		;COUNT WS LOADS
	AOS NBWT		;COUNT WAITING BALSET PROCESS
	AOS NBSWP		;COUNT IS AS SWAP WAIT
	MOVE T1,TODCLK		;SET START OF WAIT TIME
	MOVEM T1,FKNBW(FX)
	SKIPN INSKED		;CHECK COMPLETION UNLESS NOT INSKED
	SKIPN PRELDF		; AND PRELOADING
	SKIPL FORKX		;CAN'T DO IT IF FORK CONTEXT SETUP
	SKIPA
	CALL SKDJ3
	 NOP
	RETSKP
;HANDLE BAD FKCSIZ - RECOMPUTE COUNT AND REPORT VALUES

FIXWSP:	MOVE T4,MONCOR		;SETUP TO SCAN CST3
	SETZ T2,		; TO COUNT ASSIGNED PAGES
FIXWS1:	LOAD T1,CSTOFK,(T4)	;GET FORK ASSIGNMENT
	CAMN T1,FX		;THIS FORK?
	AOS T2			;YES, COUNT
	CAME T4,NHIPG		;SCANNED ALL PAGES
	AOJA T4,FIXWS1		;NO
	LOAD T1,FKWSS		;GET EXISTING VALUES
	LOAD T3,FKCSIZ
	BUG(FKWSP1,<<T1,D>,<T2,D>,<T3,D>>)
	STOR T2,FKCSIZ		;FIX COUNT
	CAMGE T1,T2		;NOW LOOKS OK?
	MOVE T1,T2		;NO, RESET FKWSS ALSO
	STOR T1,FKWSS
	JRST LDJB5		;NOW...
;UPDATE QUEUE NUMBER AND TIME USED VALUE

SAVRT:	CALL UCLOCK		;UPDATE CLOCKS
	SETZ T1,
	SKIPE NSKED		;NOSKED?
	TXO T1,BSNSK		;YES
	SKIPE CRSKED		;CSKED?
	TXO T1,BSCRSK		;YES
	XOR T1,FKSWP(FX)	;COMPARE WITH LAST SETTING
	TXNE T1,BSNSK+BSCRSK	;CHANGED?
	JRST [	ANDX T1,BSNSK+BSCRSK
		XORM T1,FKSWP(FX) ;YES, UPDATE VALUES
		CALL GLREM	;CHANGE FORK POSITION ON GOLST
		CALL GOCONC
		JRST .+1]
	MOVE T1,FKT1		;GET TIME USE SINCE SETRT
	SETZM FKT1
	LOAD T2,FKQN		;ACCUMULATE QUEUE DISTRIBUTION
	ADDM T1,QSUM(T2)	; STATISTICS
	MOVE T1,BSQNT		;GET REMAINING BALSET QUANTUM
	SUB T1,BSQNT0		;COMPUTE QUANTUM CHARGE THIS RUNNING
	OPSTRM <ADDB T1,>,FKQTM	;UPDATE FORK QUANTUM
	JUMPG T1,[LDB T3,[POINT 6,JOBBIT,35] ;NOT EXHAUSTED
		CAML T2,T3	;BUT CHECK FOR MAXQ
		JUMPN T3,.+1	;RECALC IF MAXQ SET AND EXCEEDED
		RET]		;ALL OK
	AOS BSKED		;EXHAUSTED, REQUEST ADJUST OF BALSET
;	SKIPN CLASSF		;CLASS SCHEDULING?
	CALL GLREM		;NO, REMOVE FROM GOLST WHILE CHANGING QUEUE
SAVR12:	LOAD T2,FKQN		;GET Q NUMBER
	SKIPN T4,JOBBIT		;SPECIAL PRIORITY?
	SKIPE T4,JOBSKD		;ANY JOB-WIDE SCHEDULING CAPS?
	JRST [	LDB 3,[POINT 7,T4,17] ;GET RUNTIME GUARANTEE
		SKIPN CLASSF	;IF CLASS SCHEDULING, NO CPU GUARANTEE
		JUMPN 3,RTG1	;DO SOMETHING ABOUT IT IF NON-0
		LDB 3,[POINT 6,T4,35] ;GET SPECIAL MAXQ
		JUMPE 3,.+1	;IF 0 THEN NOT THIS FACILITY
		LDB T1,[POINT 6,T4,29] ;GET HIGHEST Q
		CAIL T2,0(T1)	;TOO HIGH?
		CAIL T2,-1(T3)	;NO. TOO LOW?
		SKIPA T2,T1	;YES. GET NEW QUEUE NUMBER
		JRST .+1	;NO. PROCEED WITH NORMAL PATH
		JRST SAVRT9]
SAVRT8:	CAIGE 2,MAXQ		;NOW ON MAX Q?
	AOJA 2,SAVRT9		;NO, GO TO NEXT ONE
	MOVEI 2,MAXQ		;YES, ROUND-ROBIN IN IT
SAVRT9:	STOR 2,FKQN		;SET NEW QUEUE NUMBER
	MOVE 1,QUANTT(2)	;GET QUANTUM FOR THIS QUEUE
RTG2:	STOR 1,FKQTM		;SET NEW QUANTUM VALUE
	MOVE 3,TODCLK
	MOVEM 3,FKTIME(FX)	;SET TIME ON QUEUE
;	SKIPE CLASSF		;CLASS SCHEDULING?
;	RET			;YES. ALL DONE
	CALLRET GOCONC		;NO. PUT FORK BACK ON GOLST
;DISMISS JOB FOR RESCHEDULING

DISMSJ:	MOVE FX,FORKX
	JUMPL FX,R		;NO JOB
	CALL SAVRT		;UPDATE QUEUE AND QUANTUM
	SETZ 1,
	CALL SCHP2		;SET BALSET WORD
	RET

;ROUTINE USED BY LOADBS AND AJBALS TO CHECK IF A PROCESS SHOULD
;BE LOADED. IF A PRCESS IS "WAY AHEAD" OF ITS UTILIZATION,
;IT WILL NOT BE LOADED.
;	FX/ FORK INDEX
;RETURNS:	+1 NOT "WAY AHEAD"
;		+2 "WAY AHEAD"

CKAHED:	LOAD T1,FKQN		;GET QUEUE NUMBER OF PROCESS
	MOVE CX,FKSWP(FX)	;GET FLAGS ALSO
	TXNN CX,BSNSK!BSCRSK	;IF CRITICAL, DO IT
	CAIG T1,INTQ1		;INTERACTIVE OR SPECIAL?
	RET			;NO. LOAD IT TO ALLOW AN INTERACTION
	JN PIBMP,,R		;OR IF DOING PI, ALLOW IT
	CALL DIST		;GET PROCESS'S DISTANCE
	JUMPGE T1,R		;IF NOT AHEAD, LOAD IT
	RETSKP			;IS AHEAD. DON'T LOAD IT
;RUNTIME GUARANTEE CONTROL - COMPUTE RUNTIME/ELAPSED, COMPARE WITH
;DESIGNATED CPU FRACTION.  RAISE OR LOWER SCHEDULER PRIORITY AS
;NECESSARY.
;	T4/ PRIORTY WORD

;LOWQT - CONTROLS INTERVAL OVER WHICH TIME IN GUARANTEED

LOWQT==^D10000

RTG1:	LDB T3,[POINT 7,T4,17]	;GET CPU RUN-TIME GUARANTEE
	MOVE 1,JOBNO
	SKIPN JOBCK0		;GUARANTEE WORDS INIT'ED?
	JRST [	MOVE 4,TODCLK	;INITIALIZE TIME QUARANTEE WORDS
		MOVEM 4,JOBCK0
		MOVE 4,JOBRT(1)
		MOVEM 4,JOBCK1
		JRST RTG3]
SAVRT7:	JUMPE T3,SAVRT8		;NOT SPECIAL
	MOVE 4,JOBRT(1)		;COMPUTE RUNTIME DURING TEST INTERVAL
	SUB 4,JOBCK1
	MOVE 1,TODCLK		;COMPUTE REAL TIME OF TEST INTERVAL
	SUB 1,JOBCK0
	IMULI 4,^D100		;COMPUTE RUNTM*100%/PCT TO GET
	IDIV 4,T3		;EXPECTED REAL TIME
	SUB 4,1			;EXCESS OR DEFICIT OF REAL TIME
	CAIL 4,LOWQT/2		;ACCUMULATED REASONABLE EXCESS?
	JRST SAVRT5		;YES, REDUCE PRIORITY
RTG3:	IMUL T3,NBPROC		;GIVE BALSET QUANTUM PROPORTIONAL TO NBPROC
	IMUL T3,SKDBQT		;AND DESIRED PERCENTAGE
	IDIVI T3,^D100
	MOVEI T2,HIGHQ		;KEEP ON A HIGH Q TO GET EXCLUSIVE TIME
	JRST SAVRT9


;4 NOW CONTAINS TIME SUCH THAT AFTER THAT REAL-TIME INTERVAL,
;WITH NO RUNNING OF PROGRAM, ACTUAL PCT WILL EXACTLY EQUAL DESIRED PCT

SAVRT5:	CAIGE 4,LOWQT		;ACCUMULATED EXCESS .GE. LOW-Q QUANT?
	JRST [	CAIGE 2,MAXQ-1	;NO, STILL ON HIGHER QUEUES?
		JRST SAVRT8	;YES, FOLLOW NORMAL ALGORITHM
		MOVEI 2,MAXQ-1	;STAY ON SECOND LOWEST QUEUE
		JRST SAVRT9]
	CAIGE 4,2*LOWQT		;ACCUMULATED LARGE EXCESS?
	JRST SAVRT6		;NO
	SUBI 4,2*LOWQT		;YES, REMOVE EXCESS OVER 2*LOWQT
	MOVN 4,4
	ADDM 4,JOBCK0		;FROM CONSIDERATION
	MOVEI 4,2*LOWQT
SAVRT6:	MOVEI 2,MAXQ		;PUT ON LOWEST QUEUE
	STOR 2,FKQN		;SET QUEUE NUMBER
SAVR66:	MOVE 1,QUANTT		;GIVE ONLY SHORT QUANTUM SO WILL RECHECK SOON
	JRST RTG2
;UPDATE USER CLOCKS ON REQUEST (MUST BE NOSKED OR INSKED)

UCLOCK::MOVE T1,SKDLST		;TIME AT ENTRY TO SCHED
	SKIPN INSKED		;NOW INSKED?
	JRST [	PUSH P,T4	;NO, READ CLOCK
		JSP T4,MTIME
		POP P,T4
		JRST .+1]
	SKIPE FKTOFF		;CLOCK NOW OFF?
	JRST [	SUB T1,FKTOFF	;YES, COMPUTE TIME OFF
		ADDM T1,FKTLST	;ACCUMULATE AS LOST
		MOVE T1,FKTOFF	;USE TIME OFF AS END OF CHARGE INTERVAL
		JRST .+1]
	SUBM T1,FKT0		;COMPUTE INCREMENTAL RUNTIME
	EXCH T1,FKT0		;INIT NEW INTERVAL
	CAIGE T1,0		;OVERFLOW?
	ADD T1,BASOVV		;YES, CORRECT
	MOVN 2,1
	ADDM T2,BSQNT		;SUBTRACT TIME FROM QUANTUM
	ADD 1,RUNT2		;ACCUMULATE HIGH PRECISION TIME
	IDIVI 1,NTMS		;CONVERT TO MS
	MOVEM 2,RUNT2		;RETAIN HIGH PRECISION UNITS
	JUMPE 1,R		;RETURN IF NO CHANGE
	ADDM T1,FKT1		;ACCUMULATE RUNTIME SINCE SETRT
	MOVE 2,JOBNO
	ADDM 1,JOBRT(2)		;ACCOUNT FOR JOB
	ADDM 1,FKRT		;ACCOUNT FOR FORK
	ADDM T1,USRTIM		;ACCUMULATE TOTAL USER TIME
	ADDM T1,JOBIRT(T2)	;ACCUMULATE JOB RUN-TIME AS WELL
	HRRZ T3,JOBCLS(T2)	;GET CLASS OF THIS FORK
	ADDM T1,CLSIRT(T3)	;AND ACCUMULATE HERE ALSO
	JN JOBRTP,(2),UCLOC1	; Do runtime limit exceeded check if one set
UCLOC2:	HRRZ 2,JOBNAM(2)	;GET SUBSYSTEM INDEX
	ADDM 1,STIMES(2)	;ACCUMULATE SUBSYSTEM TIME
	RET

UCLOC1:	LOAD 3,JOBRTP,(2)	; Get blk ptr
	LOAD 3,TIMTIM,(3)	; Get limit
	JUMPE 3,UCLOC2		; Already done this stage?
	CAML 3,JOBRT(2)		; Exceeded yet?
	 JRST UCLOC2		; No, continue normally
	LOAD 3,JOBRTP,(2)	; Once again retrieve blk ptr
	SETZRO TIMTIM,(3)	; So we won't try to do it again
	PUSH P,1		; Save increment of time
	MOVSI 1,400000+PSITLE
	MOVE 2,FORKX
	HLRZ 2,FKJOB(2)		; First get job this fork belongs to
	HRRZ 2,JOBPT(2)		; then the top fork of the job
	IORM 1,FKINT(2)		; Turn on TLE
	CALL PSIR4		; Start up the fork
	POP P,1			; Recover time increment
	MOVE 2,JOBNO		; And job number
	JRST UCLOC2		; Done here, do the rest
;TURN FORK CPU TIME CLOCK OFF

FRTOFF::JSP T4,MTIME		;SAVE TIME AT WHICH CLOCK TURNED OFF
	MOVEM T1,FKTOFF
	RET

;TURN FORK CPU TIME CLOCK BACK ON
; RETURNS:
;  1/ CPU TIME THAT CLOCK WAS OFF IN HP UNITS

FRTON::	JSP T4,MTIME
	SUB T1,FKTOFF		;COMPUTE TIME OFF
	ADDM T1,FKTLST		;ACCUMULATE AS LOST TIME
	ADDM T1,FKT0		;ADJUST START OF PERIOD TO EXCLUDE LOST TIME
	SETZB T1,FKTOFF		;NOTE CLOCK NOW ON
	EXCH T1,FKTLST		;RETURN ACCUMULATED LOST TIME AND CLEAR
	RET

;GET CURRENT FORK RUNTIME

GETFRT::NOSKED
	;SKIPN T1,FKTOFF		;USE CLOCK OFF TIME IF PRESENT
	JSP T4,MTIME		;READ CLOCK
	SUB T1,FKT0		;COMPUTE TIME SINCE LAST UPDATE
	CAIGE T1,0		;OVERFLOW?
	ADD T1,BASOVV		;YES, CORRECT
	ADD T1,RUNT2		;ADD FRACTIONAL MS
	IDIVI T1,NTMS		;CONVERT TO MS
	ADD T1,FKRT		;ADD CURRENT TIME
	OKSKED
	RET

;GET CURRENT FORK RUNTIME IN HIGH PRECISION UNITS

GETHRT::NOSKED
	;SKIPN T1,FKTOFF	;USE CLOCK OFF TIME IF PRESENT
	JSP T4,MTIME		;READ CLOCK
	SUB T1,FKT0		;COMPUTE TIME SINCE LAST UPDATE
	CAIGE T1,0		;CHECK FOR OVERFLOW
	ADD T1,BASOVV
	ADD T1,RUNT2		;ADD FRACTIONAL MS ACCUMULATED RUNTIME
	MOVE T2,FKRT		;GET MS ACCUMULATED RUNTIME
	IMULI T2,NTMS		;CONVERT TO HP UNITS
	ADD T1,T2		;COMPUTE SUM OF ACCUMULATED AND RECENT RUNTIME
	OKSKED
	RET
;PUT FORK ON WAIT LIST

WTCONC::MOVE 1,TODCLK		;SAVE TIME FORK WAS PUT INTO WAITING
	MOVEM 1,FKPGST(FX)
WTCON2:	HRRZ 1,FKSTAT(FX)	;CHECK FOR SPECIAL WAITS
	CAIN 1,TCITST		;TTY INPUT?
	JRST [	MOVEI 2,TTILST	;YES
		JRST WTCON1]
	CAIE T1,TCOTST		;TTY OUTPUT WAITS?
	CAIN T1,TTOBET
	SKIPA
	CAIN T1,TTOAV
	JRST [	MOVEI T2,TTOLST	;YES
		JRST WTCON1]
	CAIE T1,HALTT		;ANY OF VARIOUS HALTS?
	CAIN T1,JRET
	JRST WTCON3
	CAIE T1,SUSWT
	CAIN 1,FRZWT		;FREEZE?
WTCON3:	JRST [	MOVEI T2,FHV1
		STOR T2,FKGOLN	;SET WAIT PRIORITY
		MOVEI 2,FRZLST
		JRST WTCON1]
	CAIE 1,TRMTS1
	CAIN 1,TRMTST		;INFERIOR FORK WAIT?
	JRST [	MOVEI 2,TRMLST
		JRST WTCON1]
	CAIE 1,BLOCKM
	CAIN 1,BLOCKW		;CLOCKS?
	SKIPA
	CAIN 1,BLOCKT
	JRST [	MOVEI 2,CLKLST
		SETZM ALARMT	;FORCE RECHECK OF CLOCKS TO INCLUDE THIS
		JRST WTCON1]
	CAIN 1,PIDWAT		;IPCF?
	JRST [	MOVEI 2,WT2LST	;YES, USE GENERAL PURPOSE LIST
		JRST WTCON1]
	MOVEI 2,WTLST		;ALL OTHER WAITS
WTCON1:	STOR 2,FKWTL		;REMEMBER WHICH LIST
	MOVEI 1,FKPT(FX)	;PUT FORK ON PROPER LIST
	EXCH 1,0(2)
	HRRM 1,FKPT(FX)
	SETONE FKBLK		;NOTE BLOCKED
	MOVE 2,FKSTAT(FX)	;NOW TRY TEST ONCE
	HLRZ 1,2
	HRRZ 4,2
	JSP 4,0(4)
	JRST [	SKIPGE 1,FKINT(FX) ;TEST FAILS, IS INTERRUPT REQUESTED?
		TLNE 1,(1B1)	;AND NOT ALREADY DEFERRING?
		JRST .+2	;NO
		MOVSI 1,PSIWTF	;YES, FLAG INTERRUPT FROM WAIT STATE
		IORM 1,FKINT(FX)
		JRST .+1]	;AND WAKEUP FORK
	CALL UNBLK1		;CONDITION ALREADY SATISFIED
	RET
;MOVE FORK FROM ONE WAIT LIST TO ANOTHER.  USED WHEN WAIT STATE
; CHANGES (E.G. FREEZE)
; FX/ FORK

RECONC::SAVEAC <Q2>
	JE FKBLK,,UNBLK3		;JUMP IF NOT BLOCKED
	LOAD 1,FKWTL		;GET POINTER TO SPECIFIC LIST
RECON1:	HRRZ Q2,0(1)		;SCAN FOR FORK
	JUMPE Q2,UBBAD		;COULDN'T FIND IT
	MOVEI 2,-FKPT(Q2)		;GET FOR INDEX
	CAIE 2,0(FX)		;DESIRED FORK
	JRST [	MOVEI 1,0(Q2)	;NO
		JRST RECON1]
	HRRZ 2,0(Q2)		;YES, REMOVE FROM CURRENT LIST
	HRRM 2,0(1)
	CALL WTCON2		;PUT ON NEW LIST
	JRST UNBLK3		;RETURN


; CHKWT - Check if fork in FX is on wait list

CHKWT::	JE FKBLK,,R		;JUMP AND RETURN IF NOT BLOCKED
	RETSKP			;SKIP IF BLOCKED

;CHKTOT - CALLED BY TTYSRV WHEN A TTY OUTPUT EVENT HAS OCCURED WHICH
;WILL LIKELY ALLOW A FORK TO WAKEUP

CHKTOT::AOS TSKED		;JUST FLAG FOR NEXT TCLKS
	RET
;UNBLOCK SPECIFIC FORK - MAY BE CALLED FROM OUTSIDE SCHEDULER
; 1/ FORK INDEX
;	CALL UNBLKF
; RETURN +1 ALWAYS

UNBLKF::SAVEAC <FX>
	MOVEM 1,FX		;SETUP ARG
	NOSKD1			;NOSKED WHILE DIDDLING LISTS
	JE FKBLK,,UNBF1		;JUMP IF NOT BLOCKED
UNBF2:	HRRZ 2,FKSTAT(FX)
	HLRZ 1,FKSTAT(FX)		;SETUP TEST CALL
	JSP 4,0(2)		;IS FORK REALLY UNBLOCKED?
	 JRST UNBF1		;NO, IGNORE CALL
	CALL UNBLK1		;DO THE WORK
UNBF1:	OKSKD1
	RET

;ROUTINE TO UNBLOCK SPECIFIC FORK
; FX/ FORK

UNBLK1::SAVEAC <Q2,F>
	MOVE F,SCHFLG		;SETUP PERMANENT FLAGS
	JE FKBLK,,UBBAD		;JUMP IF NOT BLOCKED
	LOAD 1,FKWTL		;YES, GET POINTER TO IT
UNBLK2:	HRRZ Q2,0(1)		;GET NEXT FORK ON LIST
	JUMPE Q2,UBBAD		;COULDN'T FIND IT
	MOVEI 2,-FKPT(Q2)		;GET INDEX FOR FORK
	CAIE 2,0(FX)		;REQUESTED ONE?
	JRST [	MOVEI 1,0(Q2)	;NO
		JRST UNBLK2]
	HRRZ 2,0(Q2)		;REMOVE FORK FROM LIST
	HRRM 2,0(1)
	CALL SCHEDJ		;ADJUST QUEUE AND PUT ON GOLST
UNBLK3:	RET

UBBAD:	BUG(UNBFNF)
	JRST UNBLK3
;WAKEUP SUPERIOR, E.G. ON FORK SUSPENSION
; T1/ TEST ADR - WAKEUP ONLY IF THIS TEST
;	CALL WAKSUP

WAKSUP:	SAVEAC <FX>
	MOVE T2,T1
	HRRZ T1,FORKN		;GET SUPERIOR
	JUMPE T1,R		;RETURN IF TOP FORK
	ADD T1,SUPERP
	LDB T1,T1
	HRRZ FX,SYSFK(T1)
	JE FKBLK,,R		;RETURN IF NOT BLOCKED
	HRRZ T1,FKSTAT(FX)
	CAME T1,T2		;SPECIFIED TEST?
	RET			;NO, DON'T WAKE
	CALLRET UNBLK1		;WAKE IT

;SPECIAL ROUTINE CALLED FROM NSPSRV TO UNBLOCK A PROCESS IF
;NECESSARY. ACCEPTS:
;		T1/ FORK INDEX
;		T2/ LOW ADDRESS FOR SCHEDULER TESTS
;		T3/ HIGH ADDRESS

;THIS ROUTINE CHECKS IF PROCESS IS ON WAIT LIST AND IS WAITING
;ON ONE OF THE SPECIFIED ROUTINES

NETWKF::MOVE T3,T2		;SET UP RANGE TEST
NETWK1::SAVEAC <FX>
	MOVE FX,T1		;GET FORK # INTO FX
	NOSKD1			;PREVENT STATE CHANGES
	JE FKBLK,,UNBF1		;JUMP IF NOT BLOCKED
	HRRZ T1,FKSTAT(FX)	;YES. GET WAIT ROUTINE
	CAML T1,T2		;WITHIN RANGE?
	CAMLE T1,T3		;STILL?
	JRST UNBF1		;NO. DON'T WAKE IT
	JRST UNBF2		;YES. WAKE IT
;CHECK CLOCK LIST.  WAKEUP ANY FORKS HAVING EXPIRED TIMES AND
; COMPUTE TIME FOR NEXT CHECK

CLKCHK:	SAVEQ
	MOVE 1,TODCLK
	CAMGE 1,ALARMT		;TIME FOR CHECK NOW?
	RET			;NO
	MOVSI 1,(1B1)		;YES, INIT TO FIND MIN VALUE
	MOVEM 1,ALARMT
	MOVEI 5,CLKLST
CLKCH1:	HRRZ Q2,0(Q1)		;GET NEXT FORK
	JUMPE Q2,R
	MOVEI FX,-FKPT(Q2)	;GET FORK INDEX
	HRRZ 2,FKSTAT(FX)
	HLRZ 1,FKSTAT(FX)
	JSP 4,0(2)		;CALL WAKEUP TEST
	 JRST [	ADD 1,TODCLK	;FAILS, RETURNS NUMBER OF MS REMAINING
		CAMGE 1,ALARMT	;THIS SOONER THAN SOONEST SO FAR?
		MOVEM 1,ALARMT	;YES
		MOVEI Q1,0(Q2)
		JRST CLKCH1]
	HRRZ 2,0(Q2)		;REMOVE FORK FROM LIST
	HRRM 2,0(Q1)
	CALL SCHEDJ		;WAKEUP THE FORK
	JRST CLKCH1
;CHECK SUPERIOR ON FORK TERMINATION
;SUPERIOR FORK INDEX LEFT IN LH OF DISMISS TEST WORD
;OR ENTER AT SUPUB0 WITH FORKX INDEX IN 1

SUPUNB:	STKVAR <SUPFX>
	MOVEM FX,SUPFX		;SAVE CURRENT
	HLRZ FX,FKSTAT(FX)	;GET SUPERIOR FORK INDEX
	JE FKBLK,,SUPUX		;JUMP IF SUPERIOR NOT BLOCKED
	LOAD 1,FKWTL		;SEE WHERE IT IS
	CAIE 1,TRMLST		;WAITING FOR TERMINATION?
	JRST SUPUX		;NO
	HRRZ 2,FKSTAT(FX)	;YES
	CAIN 2,TRMTS1		;WAITING FOR ANY FORK?
	JRST SUPU1		;YES, WAKE IT
	HLRZ 2,FKSTAT(FX)	;NO, SPECIFIC FORK.
	CAMN 2,SUPFX		;WAITING FOR THIS ONE?
SUPU1:	CALL UNBLK1		;YES, WAKE IT
SUPUX:	MOVE FX,SUPFX		;RESTORE SELF
	SKIPE PRIMRY		;IS THIS IN FORK INIT?
	CALL FKTMI		;NO. GENERATE INTERRUPT THEN
	RET

SUPUB0::MOVEI T1,TRMINT		;GET CHANNEL FOR FORK TERMINATION
	MOVE T2,FORKX		;TO SELF
	CALL PSIRQ		;GO REQUEST INTERRUPT
	CHKINT			;AND MAKE IT HAPPEN
	RET			;AND DONE

;WTCHK - TEST ALL NON-SPECIAL WAITING FORKS
;CHKTL - TEST TTY OUTPUT FORKS

WTCHK::	MOVEI T1,^D300		;SET TIME FOR NEXT CHECK
	MOVEM T1,WTTIM
	MOVEI Q2,WTLST		;HEAD OF WAITING LIST
	CALL SCHEDA
CHKTL:	MOVEI Q2,TTOLST		;TTY OUTPUT LIST
	SETZM TSKED
SCHEDA:	MOVEI Q1,0(Q2)		;KEEP POINTER TO LAST ONE IN Q1,
SCHEDB:	HRRZ Q2,0(Q1)		;POINTER TO CURRENT ONE IN Q2
	JUMPE Q2,R		;DONE
	MOVEI FX,-FKPT(Q2)	;FORK INDEX
	HRRZ 2,FKSTAT(FX)	;FKSTAT/  TEST VALUE,,ADR OF TEST ROUTINE
	HLRZ 1,FKSTAT(FX)
	JSP 4,0(2)		;CALL TEST ROUTINE
	JRST SCHEDA		;NO SKIP => STILL NOT RUNNABLE
	HRRZ 2,0(Q2)		;REMOVE FROM WAIT LIST
	HRRM 2,0(Q1)
	CALL SCHEDJ		;SETUP QUEUE AND GOLST
	JRST SCHEDB
;DO WAKEUP ON FORK - SET NEW STATUS AND PUT ON GOLST

SCHEDJ:	AOS TTYBKS		;NOW RUNNABLE, COUNT UNBLOCKS
	SETZRO FKBLK
	CALL APSKED		;SEE IF RESCHEDULE NEEDED
	CALL NEWST		;ESTABLISH NEW QUEUE STATUS
	CALL GOCONC		;PUT ON READY LIST
	CALLRET CHKTFK		;PUT FORK INTO BALSET IF POSSIBLE

;UPON RECEIPT OF WAKEUP EVENT FOR FORK, SEE IF RESCHEDULING SHOULD
;OCCUR TO RUN UNBLOCKED FORK RATHER THAN CURRENT FORK
; FX/ FORK INDEX
;	CALL APSKED
; RETURN +1 ALWAYS, ALL ACS PRESERVED

APSKED::SKIPL FORKX		;HAVE A CURRENT FORK?
	SKIPE INSKED		;ALREADY IN SCHEDULER?
	JRST APSK1		;NO OR YES - NO NEED TO INTERRUPT
	CAIL FX,NFKS
	JRST APSK1		;NOT A VALID FORK
	SAVEAC <T1,T2,FX>
	LOAD T1,FKQN		;GET QUEUE NUMBER OF NEW FORK
	MOVE FX,FORKX
	LOAD T2,FKQN		;GET QUEUE NUMBER OF CURRENT FORK
	CAML T1,T2		;NEW BETTER THAN CURRENT?
	RET			;NO, DO NOTHING
	MOVX T1,SK%RSQ		;SYSTEM MGR WANTS THIS?
	TDNN T1,SCHFLG
	JRST APSK1		;NO
	AOS SKEDF3		;YES, REQUEST RESCHED
	AOS PSKED
	;ISB SCDCHN		;RIGHT NOW
	RET

APSK1:	AOS PSKED		;FORCE DISMISS OF CURRENT FORK
	RET
;PUT FORK ON GO LIST.  LIST IS KEPT IN PRIORITY ORDER; SEARCH
; DOWN LIST UNTIL FORK OF LOWER PRIORITY IF FOUND.  PUT NEW FORK
; JUST AHEAD OF THAT ONE.

GOCONC:	SAVEAC <Q2>
	CALL ONGOL		;PUT ON GO LIST
	AOS NGOJOB		;KEEP COUNT OF READY JOBS
	LOAD T3,FKJOBN		;GET JOB #
   IFDEF LDAVCJ,<		;CDOE TO DO JOB LOAD AVERAGES
	SKIPN CLASSF		;CLASS SCHEDULER ON?
	JRST GOCNC1		;NO.
	MOVSI CX,1		;GET AN INCREMENTOR
	ADDB CX,JOBCLS(T3)	;ONE MORE ON GOLST
	TLNE CX,777776		;FIRST ONE ON?
	JRST GOCNC0		;NO.
   >				;END OF REPEAT 0
GOCNC1:	HRRZ T3,JOBCLS(T3)	;GET CLASS
	INCR CLGLC,(T3)		;ONE MORE ON GOLST
GOCNC0:	LOAD T3,FKQN		;UPDATE QUEUE COUNTS
	CAIGE T3,MAXQ
	AOSA NHQFK
	AOS NLQFK
GOC3:	RET

;ROUTINE TO DO THE WORK. 

ONGOL: STKVAR <SFX,SP1,SP2>
	MOVEM FX,SFX		;SAVE FORK INDEX
	CALL CORFCT		;COMPUTE PRIORITY
	MOVEM T1,SP1
	MOVEM T2,SP2		;SAVE PRIORITIES
	MOVEI T3,GOLST
GOC1:	HRRZ T4,0(T3)		;GET NEXT FORK ON LIST
	JUMPE T4,ONGOL0		;END OF LIST?
	MOVEI FX,-FKPT(T4)	;GET FORK INDEX (.. -FKPT(T4) )
	CALL CORFCT		;GET PRIORITY OF THIS FORK
	CAMG T1,SP1		;BETTER THAN CLASS TO BE ADDED?
	JRST GOC2		;NO. TEST FOR INSET HERE
ONGOL1:	MOVEI T3,0(T4)		;YES. KEEP SCANNING
	JRST GOC1

;FOUND BEGINNING OF CLASS STUFF. NOW FIND PROPER PLACE

GOC2:	CAMN T1,SP1		;SAME CLASS?
	CAMGE T2,SP2		;YES. BELONG HERE?
	JRST ONGOL0		;YES. DO IT
	JRST ONGOL1		;NO. KEEP GOING THEN
ONGOL0:	MOVE FX,SFX		;GET ORIGINAL INDEX
	MOVEI T1,FKPT(FX)	;PUT FORK INTO LIST
	HRRM T1,0(T3)		;LINK TO PREVIOUS
	HRRM T4,FKPT(FX)
	RET			;DONE
;REMOVE SELECTED FORK FROM GOLST

GLREM:	SAVEQ
	HRRZ Q1,FX		;GET FORK INDEX FOR COMPARING
	MOVEI 1,GOLST
GLREM1:	HRRZ Q2,0(1)
	JUMPE Q2,GLREM2
	MOVEI FX,-FKPT(Q2)	;GET FORK INDEX
	CAME FX,Q1		;DESIRED ONE?
	JRST [	MOVEI 1,0(Q2)	;NO
		JRST GLREM1]
	HRRZ Q2,FKPT(FX)		;YES, REMOVE FROM LIST
	HRRM Q2,0(1)
	SOS NGOJOB
	LOAD Q1,FKJOBN		;GET JOB NUMBER
   IFDEF LDAVCJ,<		;CODE TO DO JOB LOAD AVERAGES
	SKIPN CLASSF		;CLASS SCHEDULER ON?
	JRST GLREM3		;NO
	MOVSI CX,-1		;GET A DECREMNTOR
	ADDB CX,JOBCLS(Q1)	;DO IT
	TLNE CX,-1		;LAST ONE OFF?
	JRST GLREM0		;NO
   >				;END OF REPEAT 0
GLREM3:	HRRZ Q1,JOBCLS(Q1)	;GET CLASS NUMBER
	DECR CLGLC,(Q1)		;ONE LESS ON GOLST
GLREM0:	LOAD Q1,FKQN		;UPDATE QUEUE COUNTS
	CAIGE Q1,MAXQ
	SOSA NHQFK
	SOS NLQFK
	RET

GLREM2:	BUG(GLFNF)

JSKP::	JRST 1(4)
JRET::	JRST 0(4)
;COMPUTE PRIORITY NUMBER FOR FORK
; FX/ FORK INDEX
;	CALL CORFCT
; RETURNS +1, T1/ FIRST SORT KEY
; T2/ SECOND SORT KEY

CORFCT:	LOAD T2,FKQN		;GET QUEUE NUMBER
	SKIPE CLASSF		;CLASS SCHEDULING?
	JRST CORFC1		;YES
	MOVE T1,TODCLK		;NO, ORDER FORKS BY QUEUE NUMBER
	SUB T1,FKTIME(FX)	; AND THEN ELAPSED TIME ON QUEUE
	JUMPL T1,CORFC2		;RETURN NEG IF NOT DUE TO RUN YET
	ADD T1,TBASE(T2)	;ADD QUEUE OFFSET
CORFC2:	MOVE T2,FKSWP(FX)	;CHECK FLAGS
	TXNE T2,BSNSK		;NOSKED?
	ADD T1,NSKBAS		;YES, PRIORITY
	OPSTR <SKIPN>,PIBMP	;IF PI'ING, GIVE PRIORITY
	TXNE T2,BSCRSK		;CRITICAL SECTION?
	ADD T1,CSKBAS		;YES, SECOND PRIORITY
	MOVEI T2,0		;NO SECOND KEY HERE
	RET
;THE CLASS SCHEDULER IS ON. THE COMPUTED PRIORITY IS AS FOLLOWS:
;	T1/ CLASS DISTANCE+MODIFIER
;  OR	T1/ SPECIAL VALUE
;WHERE THE SPECIALS ARE:
;	6.0 IF NOSKED
;	4.0 IF Q 0
;	3.1 IF Q 1
;	3.0 IF PI BOOST
;	3.0 IF CRSKED AND NONE OF THE ABOVE

;HOWEVER, IF THE CLASS IS PRESENTLY USING WINDFALL, Q1 PROCESSES
;RECEIVE CSLDST+.05 AS THE PRIORITY

;MODIFIERS IF NON-SPECIAL
;	0.5 IF ON INTQ1 AND CLASS NOT USING WINDFALL
;	T2/ JOB DISTANCE + MODIFIER
;WHERE THESE MODIFERS ARE:
;	0.1(1-Q/LOWQ) 
;OR	T2/	Q NUMBER
;	IF PROCESS IS SPECIAL

CORFC1:	MOVE T1,FKSWP(FX)	;GET PRIORITY FLAGS
	TXNE T1,BSNSK		;NOSKED?
	JRST CORFC4		;YES
	JUMPE T2,[MOVX T1,<4.0>	;IF QUEUE 0, DO IT
		  RET]		;DONE
	CAIG T2,INTQ		;INTERACTIVE PROCESS?
	JRST CORFC5		;YES. GO HANDLE IT
	OPSTR <SKIPN>,PIBMP	;PI BOOST?
	TXNE T1,BSCRSK		;IS IT CRSKED?
	JRST [	MOVX T1,<3.0>	;YES. MAKE IT HIGHER THAN OTHER COMPUTERS
		RET]		;AND DONE
	CALL DIST		;GET DISTANCES
	LOAD CX,FKQN		;GET Q VALUE AGAIN
	FADR T2,LQWBAS-INTQ1(CX) ;ATTENUATE JOB DISTANCE
	JUMPL T1,R		;IF CLASS IN WINDFALL, NO BOOST
	CAIN CX,INTQ1		;SECOND INTERACTIVE QUEUE?
	FADRI T1,(EXP 0.5)	;YES. ATTENUATE CLASS DISTANCE SUCH
				; THAT A WELL-BEHAVED CLASS WILL
				; ACHIEVE PRIORITY ON THIS QUEUE
	RET			;AND DONE

;NEED SPECIAL PRIORITY

CORFC4:	MOVX T1,<6.0>		;FOR NOSKED
	RET			;AND DONE
;CORFCT CONTINUED.
;PROCESS IS ON QUEUE 1 AND CLASS SCHEDULER IS ON

CORFC5:	CALL DIST		;NO. GET DIST
	SKIPG CLASSF		;WITHHOLDING?
	SKIPL T1		;IN WINDFALL?
CORF55:	SKIPA T1,[EXP 3.1]	;NO. USE BIG BOOST
	JRST [	PUSH P,T2	;SAVE REG
		MOVE T2,FKSWP(FX) ;GET FLAGS
		OPSTR <SKIPN>,PIBMP
		TXNE T2,BSCRSK	;SPECIAL?
		SKIPA T1,[EXP 3.0]
		FADRI T1,(0.5)
		CALLRET PB2]	;RESTORE T2 AND RETURN
	RET			;AND DONE
;COMPUTE NEW UTILIZATION FOR ALL CLASSES.

;COMPUTATION PERFORMED IS:
;	U(I+1)=U(I)*e^-(T/C)+F(1-e^(T/C))
;WHERE:
;	U(I)=PREVIOUS UTILIZATION
;	U(I+1)= NEWLY COMPUTED UTILIZATION
;	T/C= 1/20 (TIME CONSTANT OF 60 SEC, COMPUTED EVERY 3 SEC)
;	F= FRACTIONAL UTILIZTION IN INTERVAL. COMPUTE AS:
;		CLSIRT/TIME    WHERE:
;	TIME= INCREMENTAL SOLD TIME+( INCREMENTAL SWAP-WAIT TIME<=SOLD)

NEWUTL:	ACVAR <W1,W2,W3>	;GET A WORK REG
	MOVE W2,USRTIM		;GET CURRENT USER TIME
	SUBM W2,OLDSLD		;COMPUTE TIME SOLD IN INTERVAL
	EXCH W2,OLDSLD		;START NEW INTERVAL
	FLTR W2,W2		;GET FLOAT OF INTERVAL
	JFOV .+1		;INIT OVERFLOW FLAG
	MOVEI W1,MAXCLS-1	;SET UP TO COMPUTE CLASS UTILS
NEWUT0:	SKIPN T3,CLSIRT(W1)	;ANY TIME IN THIS INTERVAL?
	JRST NEWUT1		;NO. PROCEED
	SETZM CLSIRT(W1)	;CLEAR COUNTER
	FLTR T3,T3		;FLOAT THE VALUE
	FDVR T3,W2		;COMPUTE FRACTIONAL USE
NEWUT1:	MOVE T1,CLSUTL(W1)	;GET CLASS UTIL
	FSBR T1,T3
	FMPR T1,UTLEXP+UTLINI-1	;DECAY IT
	JFOV [	SETZM T1	;YES. ASSUME UNDERFLOW THEN
		JRST .+1]
	FADR T1,T3		;NEW UTIL
	MOVEM T1,CLSUTL(W1)
	FSBR T1,CLSSHR(W1)	;COMPUTE LINEAR DISTANCE
	SKIPL T1		;WINDFALL?
	SKIPGE T3,WA(W1)	;YES. ANY WINDFALL ALLOCATION?
	MOVE T3,CLSSHR(W1)	;NO. USE NORMAL SHARE THEN
	FDVR T1,T3		;COMPUTE DISTANCE
	JFOV [	SKIPE T3	;ANY SHARE?
		TDZA T1,T1	;YES. ASSUME ON TARGET THEN
		FADRI T1,(MXBIAS) ;NO. MAKE SURE IS RUN LAST THEN
		JRST .+1]	;PROCEED
	MOVNM T1,CLSDST(W1)	;SAVE DISTANCE
	SOJGE W1,NEWUT0		;DO ALL CLASSES
	; ..
;NEWUTL CONTINUED...
;COMPUTE JOB UTILS AND DISTANCES

	MOVE W1,MJBUSE		;GET HIGHEST JOB IN USE
NEWU00:	SKIPGE JOBRT(W1)	;THIS JOB IN USE?
	JRST NEWU02		;NO. SKIP IT THEN
	SKIPN T3,JOBIRT(W1)	;THIS JOB HAVE SOME RUN-TIME?
	JRST NEWU01		;NO
	SETZM JOBIRT(W1)	;YES. CLEAR COUNTER
	FLTR T3,T3		;GET FLOAT OF TIME
	FDVR T3,W2		;GET FRACTION
NEWU01:	MOVE T1,JOBUTL(W1)	;GET CURRENT JOB UTILIZATON
	FSBR T1,T3
	FMPR T1,UTLEXP+UTLINI-1	;DECAY IT
	JFOV [	SETZM T1
		JRST .+1]
	FADR T1,T3		;NEW UTIL
	MOVEM T1,JOBUTL(W1)	;SAVE IT
	HRRZ T2,JOBCLS(W1)	;GET CLASS
	MOVE T3,CLSSHI(T2)	;GET JOB'S SHARE
	FSBR T3,T1		;COMPUTE LINEAR DIFFERENCE
	FDVR T3,CLSSHI(T2)	;COMPUTE "EXPONENTIAL DIFFERENCE
	JFOV [	SKIPE CLSSHI(T2) ;ANY SHARE?
		SETZM T3	;NO. ASSUME ON TARGET THEN
		JRST .+1]
	MOVEM T3,JOBDST(W1)	;SAVE JOB DISTANCE
NEWU02:	SOJGE W1,NEWU00		;DO ALL JOBS
	MOVE T1,TODCLK		;GET NOW
	ADD T1,UTLINT		;WHEN TO DO IT NEXT
	MOVEM T1,UTLTIM		;""

;REORDER GOLST

	MOVE W1,GOLST		;GET GOLST
	SETZM GOLST		;INIT IT TO EMPTY
REORDR:	JUMPE W1,R		;IF EMPTY NOW, ALL DONE
	MOVEI FX,-FKPT(W1)	;GET FORK INDEX
	HRRZ W1,FKPT(FX)	;GET NEXT ITEM
	CALL ONGOL		;INSERT IN NEW GOLST
	JRST REORDR		;AND PROCEED
;COMPUTE CURRENT DISTANCE FROM TARGET UTIL FOR PROCESS
;FX/	FORK HANDLE
;RETURNS:	T1/ DISTANCE FROM CLASS TARGET UTILIZATION (IN %)
;		T2/ DISTNCE FROM JOB TARGET UTIL (IN %)
;CLOBBERS ONLY T1 AND T2

DIST:	LOAD T2,FKJOBN		;GET JOB NUMBER
	HRRZ T1,JOBCLS(T2)	;GET JOB CLASS
	MOVE T1,CLSDST(T1)	;GET CLASS DISTANCE
	MOVE T2,JOBDST(T2)	;GET JOB DISTANCE
	RET			;DONE
;MORE CLASS SCHEDULING PARAMETERS.
;ROUTINES TO MAINTAIN SHARE COUNTS

;ADD A MEMBER TO A CLASS
;	T1/ CLASS

   REPEAT 0,<			;NOT BEING USED NOW
DECSHR:	SOSA CLSCNT(T1)		;ONE LESS ITEM
INCSHR:	AOS CLSCNT(T1)		;ONE MORE ITEM
	SKIPE CLASSF		;DOING CLASS SCHEDULING?
	CALL ADJCLS		;YES. ADJUST CLASS PARAMETERS
	RET			;ALL DONE THEN
   >				;END OF REPEAT 0

;ROUTINE TO START UP CLASS SCHEDULING

STRCLS:	SKIPE CLASSF		;NOW ON?
	RET			;YES. NO NEED THEN
	ACVAR <W1>
	SETOM CLASSF		;START IT UP
	MOVEI W1,NJOBS-1	;SCAN JOBS
STRCL0:	SETZM JOBIRT(W1)	;NO INCREMENTAL RUN-TIME YET
	SETZM JOBUTL(W1)	;NO UTIL
STRC00:	SOJGE W1,STRCL0		;DO ALL JOBS
	MOVE T1,USRTIM		;GET CURRENT "SOLD" TIME
	MOVEM T1,OLDSLD		;INIT INTERVAL
	MOVE T1,[JOBIRT,,JOBIRT+1]
	SETZM JOBIRT		;INIT JOB TIMES
	BLT T1,JOBIRT+NJOBS-1	;SET ALL TO 0
	MOVE T1,[CLSIRT,,CLSIRT+1]
	SETZM CLSIRT
	BLT T1,CLSIRT+MAXCLS-1	;INIT THESE TO 0 ALSO
	MOVE T1,[CLSSUM,,CLSSUM+1]
	SETZM CLSSUM
	BLT T1,CLSSUM+MAXCLS-1	;CLEAR INTEGRAL ACCUMUALTOR
	MOVE T1,[CLSRJA,,CLSRJA+1]
	SETZM CLSRJA		;SET UP TO CLEAR RUN AVG AS WELL
	BLT T1,CLSRJA+<MAXCLS*NRJAVS>-1 ;CLEAR IT
	SETZM CLSCNT		;CLEAR COUNTS AS WELL
	MOVE T1,[CLSCNT,,CLSCNT+1]
	BLT T1,CLSCNT+MAXCLS-1	;DO IT
	CALL COUNT		;GET CORRECT CLASS COUNTS
	CALLRET NEWUTL		;INIT UTILIZATION COMPUTER
;ROUTINES TO COMPUTE CLASS PARAMETERS

;FIRST. COMPUTE ALL CLSCNT VALUES BY SCANNING GOLST

COUNT:	SAVEAC <FX>		;SAVE REG
	MOVEI T4,NJOBS-1	;SCAN ALL JOBS
COUNT0:	SKIPGE JOBRT(T4)	;THIS JOB ACTIVE?
	JRST COUNT4		;NO
	HRRZS T2,JOBCLS(T4)	;YES. GET CLASS
	AOS CLSCNT(T2)		;INCREMENT COUNT
COUNT4:	SOJGE T4,COUNT0		;DO ALL JOBS
COUNT1:	MOVEI T1,MAXCLS-1
COUNT2:	SKIPE CLSCNT(T1)	;ANYBODY IN THIS CLASS?
	CALL ADJCLS		;YES. DO COMPUTING THEN
	SOJGE T1,COUNT2

;NOW COMPUTE ON GOLST COUNT

	HRRZ T1,GOLST		;GET TOP ENTRY OF GOLST
COUNT5:	JUMPE T1,R		;IF AT THE END, DONE
	MOVEI FX,-FKPT(T1)	;GET FORK INDEX
	LOAD T2,FKJOBN		;GET JOB NUMBER
   IFDEF LDAVCJ,<		;CODE TO DO JOB LOAD AVERAGES
	MOVSI CX,1		;AN INCREMENTOR
	ADDB CX,JOBCLS(T2)	;ONE MORE ON GOLST
	TLNE CX,777776		;FIRST ONE?
	JRST COUNT6		;NO
   >				;END OF REPEAT 0
	HRRZ T2,JOBCLS(T2)	;GET CLASS
	INCR CLGLC,(T2)		;INCREMENT COUNT
COUNT6:	HRRZ T1,FKPT(FX)	;GET NEXT FORK
	JRST COUNT5		;AND STEP

;ADJUST GOLST COUNTS WHEN A JOB CHANGES CLASSES
;	T1/ OLD CLASS
;	T2/ JOB #

CHGCNT:	SAVEAC <FX>		;SAVE A REG
	HRRZ T4,JOBCLS(T2)	;GET NEW CLASS
	SKIPN FX,GOLST		;ANYTHING ON GOLST?
	RET			;NO
CHGCN0:	SUBI FX,FKPT		;GET FORK #
	LOAD T3,FKJOBN		;GET JOB #
	CAIE T3,0(T2)		;SAME AS TARGET?
	JRST CHGCNX		;NO
	DECR CLGLC,(T1)		;YES. ONE LESS IN OLD CLASS
	INCR CLGLC,(T4)		;AND ONE MORE IN NEW CLASS
   IFDEF LDAVCJ,<RET>
CHGCNX:	HRRZ FX,FKPT(FX)	;GET NEXT ITEM
	JUMPN FX,CHGCN0		;DO IT
	RET			;ALL DONE
;ROUTINE TO CHANGE CLASS FOR A JOB.
;	T1/ NEW CLASS
;	T2/ JOB NUMBER
;MUST BE IN THE SCHEDULER

CHGCLS:	ASUBR <NCLASS,JOBNOM>
	CAMN T2,JOBNO		;THIS JOB?
	CALL [	SAVET		;YES
		CALLRET UCLOCK]	;UPDATE CLOCKS
	HRRZ T3,JOBCLS(T2)	;GET CURRENT CLASS VALUE
	SOS CLSCNT(T3)		;ONE LESS IN THIS CLASS
	AOS CLSCNT(T1)		;ONE MORE IN THIS CLASS
	HRRM T1,JOBCLS(T2)	;SET NEW CLASS
	SKIPN CLASSF		;DOING CLASS SCHEDULING?
	RET			;NO .DONE THEN
	MOVEM T3,NCLASS		;SAVE OLD CLASS IN NEW CLASS PLACE
	CALL ADJCLS		;ADJUST CLASS PARAMETERS
	MOVE T1,NCLASS		;GET BACK OLD CLASS
	CALL ADJCLS		;AND ADJUST THIS AS WELL
	MOVE T2,JOBNOM		;RECOVER JOB NUMBER
	CALLRET CHGCNT		;AND ADJUST GOLST COUNTS

;ROUTINE TO SET CLASS PARAMETERS
;	T1/ SHARE OF MACHINE TO GET
;	T2/ CLASS #

CRTSHR:	MOVEM T1,CLSSHR(T2)	;SET CLASSES SHARE
	MOVE T1,T2		;GET CLASS I.D.
	CALLRET ADJCLS		;GO ADJUST CLASS PARAMETERS

;ROUTINE TO ADSJUST CLSSHI AND CLSQ WHEN SOMETHING CHANGES
;	T1/ CLASS

ADJCLS:	SKIPN T2,CLSCNT(T1)	;ANY MEMBERS OF THIS CLASS?
	MOVEI T2,1		;NO. ASSUME ONE FOR CONVENIENCE
	HRRZS T2		;GET POPULATION COUNT ONLY
	FLTR T2,T2		;GET FLOAT OF POPULATION
	MOVE T3,CLSSHR(T1)	;GET CLASS'S SHARE
	FDVR T3,T2		;GET EACH MEMBER'S FAIR SHARE
	MOVEM T3,CLSSHI(T1)	;SAVE IT
	RET			;DONE

;ROUTINE USED BY CACCT AND LOGIN TO SET CLASS OF JOB.
;	T1/ CLASS TO SET

SETCLS::ASUBR <CLSNUM>		;SAVE INCOMING ARG
	SKIPL T1,CTRLTT		;ATTACHED?
	CALL CHKBCH		;SEE IF A BATCH JOB
	 JRST SETCL0		;NO. PROCEED
	JN CLSBD,,[SKIPE JOBSKD	;ALREADY PRIORITZED?
		JRST .+1	;YES. PROCEED THEN
		MOVE T1,JOBNO	;NO. GET JOB NUMBER
		MOVX T2,DREGS	;GET DREGS PRIORITY WORD
		SJPRI		;SET PRIORITY WORD
		ERJMP .+1	;IF FAILED, PROCEED ANYWAY
		JRST .+1]	;DONE
	LOAD T1,CLSBT		;GET BATCH CLASS
	SOSGE T1		;IF A BATCH CLASS, USE IT
SETCL0:	MOVE T1,CLSNUM		;GET CLASS
	JE CLSAC,,R		;IF NOT USING ACCOUNTS, RETURN NOW
	NOSKED			;OWN MACHINE
	SKIPL T1		;VALID CLASS?
	CAIL T1,MAXCLS		;""
	SETZM T1		;NO. USE ZERO THEN
	MOVE T2,JOBNO		;GET JOB NUMBER
	HRRZ T3,JOBCLS(T2)	;GET PRESENT CLASS
	CAIE T3,0(T1)		;CHANGING?
	CALL CHGCLS		;YES
	OKSKED			;ALL DONE
	RET			;""

;ROUTINE CALLED WHEN LOGIN WILL SUCCEED.

SKDLOG::OPSTR <SKIPN>,CLSAC	;CLASS BY ACCOUNT?
	SKIPN CLASSF		;NO. CLASS SCHEDULING OFF THEN?
	RET			;YES. NOTHING TO DO
	GTOKM (.GOCL0,,R) 	;IF FAILURE, USE DEFAULT
	RET			;AND DONE
;QUEUE PARAMETER TABLES

	RADIX 10

;QUANTA FOR EACH QUEUE (IN HIGH PRECISION UNITS)
;HEURISTIC: A JOB SHOULD GET AT LEAST A FULL LOWEST QUEUE QUANTUM 
;BEFORE FALLING TO LOW QUEUE AND THEREBY YEILDING TO ALL THE COMPUTE
;BOUND JOBS.  HENCE, THE SUM OF QUANTA FOR QUEUES 0 TO MAXQ-1
;SHOULD BE .GE. THE QUANTUM FOR MAXQ

NQUEUE==:7			;NUMBER OF QUEUES
RS QUANTT,NQUEUE		;DEFINE QUEUE TABLES
LQUANT==QUANTT+NQUEUE-2		;LOW QUEUE

;DEFINE PROTO TABLE FOR BIAS CONTROL
QUANTB:	300*NTMS
	200*NTMS		;NORMAL INTERACTIVE QUEUE
	400*NTMS		;SECOND INTERACTIVE QUEUE
	1000*NTMS
	2000*NTMS
	3000*NTMS
	10000*NTMS		;"DREGS" QUEUE

;DEFINE PROTO TABLE FOR CLASS SCHEDULER

QUANTC:	300*NTMS
	100*NTMS
	500*NTMS
	1000*NTMS
	2000*NTMS
	3000*NTMS
	10000*NTMS
INTQ==1
INTQ1==INTQ+1			;SECOND INTERACTIVE QUEUE
HIGHQ==0			;SPECIAL HI PRI QUEUE
LOWQ==:NQUEUE-1			;SPECIAL LOW-PRIORITY QUEUE
MAXQ==:LQUANT-QUANTT		;"NORMAL" LOW QUEUE

BQUANT:	100*NTMS		;QUANTUM GIVEN FOR PSI 'BUMP'

DEFINE GETFLQ(N)<
EXP N'.0
>
FLOWQ:	GETFLQ(\LOWQ)
MFRKWD==:<INTQ>B29+MAXQ		;SPECIAL PRIORITY WORD FOR MONITOR FORKS

	RADIX 8

RS QSUM,NQUEUE			;ACCUMULATED RUNTIMES OF QUEUES
RS LQWBAS,<LOWQ-INTQ>		;# OF WORDS IN TABLE

;NON-CLASS BIASES

NSKBAS:	1B4			;BASE FOR NOSKED FORK
CSKBAS:	<NQUEUE-LOWQ+1>B8	;BASE FOR CRSKED FORK, BETTER THAN LOW Q

TBASE:	XX==NQUEUE-1
	REPEAT NQUEUE,<
	<XX+1>B8-1
	XX==XX-1>
;ROUTINE TO INIT QUANTT TABLE

;FIRST, TO INIT TO BIAS CONTROL SETTINGS

QBIAS:	SKIPA T1,[QUANTB,,QUANTT]

;NOW FOR CLASS SCHEDULER

QCLASS:	MOVE T1,[QUANTC,,QUANTT]
	BLT T1,QUANTT+NQUEUE-1	;DO TABLE
	RET			;AND DONE
;HEURISTIC FOR ADJUSTING QUEUE LEVEL AFTER I/O WAIT

;THIS ROUTINE IS THE PRINCIPLE CONTROL OVER THE EXTENT TO WHICH
;'INTERACTIVE' OR 'COMPUTE-BOUND' JOBS ARE FAVORED.  IT GIVES
;PRIORITY 'CREDIT' TO A FORK AS A RESULT OF WAITING.  THE MORE
;CREDIT GIVEN FOR A CERTAIN LENGTH WAIT (OR THE SHORTER THE WAIT
;REQUIRED TO BECOME HIGH-Q), THE MORE THE SYSTEM WILL FAVOR
;INTERACTIVE FORKS, AND THE GREATER THE CHANCE THAT FREQUENT OR
;WELL-TIMED INTERACTIONS WILL GIVE A PROCESS AN EXCESSIVELY LARGE
;SHARE OF COMPUTE TIME.  IT HAS BEEN DEMONSTRATED HOWEVER, THAT
;A COMPLETELY 'FAIR' ALGORITHM HERE, I.E. ONE WHICH PREVENTS AN
;INTERACTIVE FORK FROM GETTING ANY GREATER SHARE OF THE MACHINE
;THAN A COMPUTE-BOUND FORK, IS HIGHLY UNSATISFACTORY TO INTERACTIVE
;USERS UNDER MEDIUM AND HEAVY LOADS (AND ALL USERS ARE INTERACTIVE
;SOMETIMES), AND RESULTS IN EXPONENTIALLY INCREASING LEVELS OF
;FRUSTRATION, CURSING AND BEATING OF TERMINALS, ETC.  THEREFORE
;THIS ROUTINE IS GENUINELY A HEURISTIC, MODIFIED AS A RESULT OF
;PRESSURES BROUGHT TO BEAR ON SYSTEM PROGRAMMERS.

;THE FOLLOWING DESCRIBES THE CURRENT PRACTICE:
; 1. TTY INPUT WAITS OF .GE. 1 SEC GIVE HIGH-Q.  GREATLY REDUCES
;    USER FRUSTRATION LEVEL.
; 2. WAITS BY FORKS ON QUEUE 0 RESULT IN NO CHANGE TO Q VALUE
; 3. FORKS ON QUEUES 1 TO MAXQ-1 WILL BE HIGH-Q IF WAITING TIME IS
;    LONGER THAN LAST RUNTIME AS IMPLIED BY Q LEVEL.
; 4. FORKS ON MAXQ WILL BE HIGH-Q IF WAITING TIME IS LONGER THAN
;    THE MAXQ QUANTUM, AND WILL BE MOVED UP TO MAXQ-1 IF WAITING
;    TIME IS LONGER THAN SOME 'MINIMAL' TIME (500 MS)

;'WAITING TIME' ABOVE MEANS ACTUAL ELAPSED WAITING TIME
;DIVIDED BY THE 1-MINUTE LOAD AVERAGE.  THIS KEEPS 'WELL-TIMED'
;INTERACTIONS FROM USING MORE THAN ABOUT 1/LDAV OF THE CPU.
;COMPUTE NEW Q VALUE

NEWST:	MOVE 1,TODCLK		;CALCULATE ACTUAL WAITING TIME
	SUB 1,FKPGST(FX)
	ADDM 1,FKTIME(FX)	;DON'T COUNT WAIT TIME
	CAIGE T1,^D100		;ABOVE MIN WAIT TIME?
	RET			;NO, NO CHANGE
	IMULI 1,NTMS		;CONVERT TO HIGH PRECISION UNITS
	TXNE F,SK%WCF		;CONSIDER LOAD AVG?
	JRST NEWST5		;NO
	MOVE 2,IRJAV		;AV NUMBER RUNNABLE FORKS
	SUBI T2,5		;IGNORE LOAD AV UNLESS .G. 5
	CAILE T2,1
	IDIVI 1,1(2)		;WAIT CREDIT INV PROP'L TO LOAD AV
NEWST5:	TXNE F,SK%TTP		;CONSIDER INTERACTIONS?
	CAMGE 1,[^D1000*NTMS]	;YES, ABOVE MIN WAIT TIME?
	JRST NEWST2		;NO FOLLOW REGULAR ALGORITHM
	HRRZ 2,FKSTAT(FX)
	CAIN 2,TCITST		;TTY INPUT?
	JRST [	HLRZ 2,FKSTAT(FX) ;YES
		CALL CKPHYT	;IS IT A PHYSICAL TERMINAL?
		 JRST NEWST2	;FOR PTY, FOLLOW NORMAL ALGORITHM
		JRST NEWST1]	;YES, BE MORE GENEROUS
NEWST2:	LOAD 2,FKQN		;CURRENT QUEUE
	LOAD T3,FKMXQ		;GET FORK'S MAX QUEUE
	CAIGE T2,0(T3)		;ON A VALID QUEUE?
	JRST [	MOVEI T1,0(T3)	;GET GET NEW QUEUE VALUE
		JRST NEWST3]	;AND GO ADJUST
	CAIG 2,INTQ1		;ONE OF THE HIGHEST?
	RET			;YES. NO CHANGE THEN
	SKIP CLASSF		;FALL THRU
	JRST NEWST9		;USE ALTERNATE ALGORITHM
	CAIL T2,MAXQ		;NOW ON LOW QUEUE?
	JRST [	CAMGE T1,QUANTT+MAXQ-1 ;YES, WAITED LENGTH OF PREV QUEUE?
		RET		;NO, NO CHANGE
		MOVEI T1,MAXQ-1	;YES, BUMP ONE QUEUE
		JRST NEWST3]	;APPEND TO QUEUE W FULL QUANT
	LOAD T3,FKQTM		;GET REMAINING QUANT
	ADD T3,T1		;CREDIT WAIT TIME
	CAMGE T3,QUANTT(T2)	;MORE THAN FULL?
	JRST [	STOR T3,FKQTM	;NO, JUST UPDATE
		RET]
	MOVE T1,T2		;YES, REQUEUE ON SAME QUEUE
	JRST NEWST3

NEWST9:	LOAD 3,FKQTM		;GET CURRENT REMAINING QUANTUM
	ADD 3,1			;GIVE CREDIT FOR WAIT
	CAMG 3,QUANTT(2)	;MORE THAN FULL QUANT FOR THIS QUEUE?
	JRST [	STOR 3,FKQTM	;NO, KEEP FORK ON SAME QUEUE
		RET]
	SUB 3,QUANTT(2)		;SUBTRACT QUANTUM FOR THIS QUEUE
	SOJG 2,[CAML 3,QUANTT(2) ;BUMP UP ONE QUEUE, FULL QUANT HERE?
		JRST .-1	;YES, KEEP GOING HIGHER
		CAIN T2,INTQ1	;GET TO SECOND INTERACTIVE QUEUE?
		AOS T2		;YES. BUMP IT THEN
		SKIPE CLASSF	;CLASS SCHEDULER?
		CAILE T2,INTQ	;YES. DID IT BECOME INTERACTIVE?
		SKIPA T1,T2	;NO. USE CURRENT VALUE
		MOVEI T1,INTQ1+1 ;YES. USE HIGHEST IT IS ENTITLED TO
		JRST NEWST3]
   REPEAT 0,<			;ALLOW PROMOTION IN THIS CASE
	SKIPE CLASSF		;CLASS SCHEDULER?
	JRST [	MOVEI T1,INTQ+1	;YES. CAN'T BE ON INTQ
		JRST NEWST3]	;AND PROCEED
   >				;END OF REPEAT 0
	; ..
	; ..
;ESTABLISH VALUES FOR NEW QUEUE

NEWST1:	HRRZ T1,FKWSP(FX)	;SET NR TO MAX (6, WSP)
	CAMGE T1,MINWSS		;ABOVE MIN WORKING SET SIZE?
	MOVE T1,MINWSS		;NO, SET TO IT
	LOAD T2,FKWSS		;GET CURRENT SIZE
	CAMLE T2,T1		;DON'T CHANGE IF CURRENT SIZE SMALLER
	CALL ADJWSS		;CHANGE FKRN FOR FORK
	MOVEI T1,INTQ		;INIT ON QUEUE 0
NEWST3:	LOAD T2,FKMXQ		;GET MAX Q IF ANY
	JUMPN T2,NEWST4		;IF SPECIAL, GO ON
	TXNN F,SK%RQ1		;USING INTERACTIVE QUEUE?
	CAILE T1,INTQ		;NO. IS IT ON THE INTERACTIVE Q?
	SKIPA			;ALL SET
	MOVEI T1,INTQ1+1	;PUT IT ON INTQ+1
NEWST4:	CAIGE T1,0(T2)		;WITHIN RANGE
	MOVEI T1,0(T2)		;NO. GET MAX QUEUE AS NEW QUEUE NUMBER
	MOVE 2,QUANTT(1)
	STOR 2,FKQTM		;SET NEW QUEUE VALUE
	STOR 1,FKQN		;SET NEW QUEUE NUMBER
	MOVE 2,TODCLK
	MOVEM 2,FKTIME(FX)
	RET
;BUMP PRIORITY OF FORK SO PSI WILL BE HANDLED PROMPTLY.  GIVE
;GIVE PRIORITY TO SEE IF PSI IS OF INTEREST.
; FX/ FORK INDEX
;	CALL PSBUMP
; RETURN +1 ALWAYS

PSBUMP:	CALL CHKBMP		;SEE IF NEED BUMP PRIORITY
	 RET			;NO. SO RETURN NOW
	JN FKBLK,,R		;IF NOW BLOCKED, DONE
	CALL GLREM		;REMOVE FROM GOLST
	CALLRET GOCONC		;AND REQUEUE WITH NEW PRIORITY

;ROUTINES USED BY SJPRI AND SPRIW TO CAUSE PSI FOR FKMXQ UPDATE

;INTERRUPT SPECIFIC PROCESS
;	T2/ SYSTEM FORK HANDLE

SETPRF::MOVE T1,[1B0+PSIPRI]
	IORM T1,FKINT(T2)	;SAY THIS FORK NEEDS INTERRUPTING
	CALLRET PSIR4		;AND COMPLETE TASK
;HALT JOB

HLTJB::	HRRE 6,CTRLTT
	JUMPL 6,HLTJB1		;IF JOB DETACHED
	CALL LCKDVL		;LOCK DEVICE LOCK, GO NOINT
	MOVE 2,6
	CALL TTYDAS		;DEASSIGN CTRLTT
	 JRST HLTJB3		;GO CHECK FOR ERROR OR DISMISS
	UNLOCK DEVLCK		;UNLOCK THE DEVICE LOCK
	OKINT			;DEVLCK WENT NOINT
HLTJB1:	MOVE 5,JOBNO
	SETOM CTRLTT		;CLEAR CONTROL TTY WORDS
	HRROS JOBPT(5)
	CALL UNMAPD		;UNMAP THE DIRECTORY AND RELEASE ITS OFN
	SETZM JOBM0+JSBPG	;CLEAR FAKE JSB MAPPING
	MOVE FX,FORKX		;THIS FORK.
	HRRZ 1,FKJOB(FX)	;GET JSB
	CALL WTSPT		;WAIT FOR IT TO BE UNSHARED
	SETZ 1,
	HRLZ 2,FKJOB(FX)	;GET SPTN OF JSB
	HRRI 2,JOBMAP-JSBPGA
	MOVEI 4,JSLST-JSBPG
	CALL MSETPT		;CLEAR ALL PAGES OF JOB MAP
	HRLZ 2,FKPGS(FX)
	HRRI 2,PPLOW
	SETZ 1,
	MOVEI 4,PPHI+1-PPLOW
	CALL MSETPT		;CLEAR ALL PAGES OF PROCESS MAP
	HRRZ 1,FKJOB(FX)	;JSB
	CALL WTSPT		;WAIT FOR IT TO BE UNSHARED
	CALL WTFPGS		;WAIT FOR PSB AND UPT TO BE IN NO MAPS
	ENTSKD			;ENTER SCHED
	MOVE T2,JOBNO		;RELEASE JOB NUMBER
	SETZM JOBDIR(T2)	;CLEAR DIRECTORY NUMBER
	SETOM JOBRT(T2)		;INDICATE JOB NUMBER NOT IN USE
	HRRZ T1,JOBCLS(T2)	;SAVE CLASS OF JOB
	ADDI T2,JOBPT
	EXCH T2,FREJOB		;PUT SLOT ON FREE LIST
	MOVEM T2,@FREJOB
	SOS CLSCNT(T1)		;ONE LESS JOB IN THIS CLASS
	CAMN T2,MJBUSE		;WAS THIS THE HIGHEST JOB IN USE?
	JRST [	SOS T2,MJBUSE	;YES. NO LONGER IN USE
		SKIPGE JOBRT(T2) ;PREVIOUS JOB IN USE?
		JRST .		;NO. DISCOUNT IT TOO
		JRST .+1]	;AND PROCEED
	SKIPE CLASSF		;DOING CLASS SCHEDULING?
	CALL ADJCLS		;NOW UPDATE CLASS VALUES
	JRST HLTFK2		;FLUSH THIS LAST FORK
;HLTJB CONTINUED..
;DEASSIGN OF JOB CONTROLLING FAILED

HLTJB3:	TXZN T1,1B0		;FAILED. NEED TO WAIT?
	BUG(TTDAS1)
	UNLOCK DEVLCK		;YES. UNLOCK THE DEVICE LOCK
	OKINT			;LCKDVL WENT NOINT
	HRL T1,CTRLTT		;T1/(LINE NUMBER,,ADDRESS OF ROUTINE)
	MDISMS			;WAIT UNTIL DEALLOCATION IS POSSIBLE
	JRST HLTJB		; AND TRY AGAIN
;FINISH DELETE OF FORK

HLTFK1::ENTSKD			;ENTER SCHEDULER
HLTFK2:	CALL REMBSJ		;REMOVE FORK FROM BAL SET
	CALL REMWSN		;REMOVE WS WO POSTPURGING
	CALL GLREM		;REMOVE FORK FROM GOLST
	HRRZ 1,FKJOB(FX)	;JSB
	CALL GETSHR		;GET SHARE COUNT
	MOVE 2,1		;SAVE IT
	HRRZ 1,FKJOB(FX)	;GET BACK JSB
	CAIE 2,1		;LAST USE OF JSB?
	JRST [	CALL DWNSHR	;NO. REDUCE SHARE COUNT
		JRST .+2]
	CALL DESPT		;YES, DELETE IT (LOGOUT CASE)
	HLRZ 1,FKPGS(FX)	;UPT
	CALL DESPT		;DELETE IT
	LOAD T1,FSSPTN		;GET STACK I.D.
	CALL DESPT		;RELEASE IT AS WELL
	HRRZ 1,FKPGS(FX)
	CALL DESPT		;DEASSIGN PSB
	SETOM FORKX
	MOVEI T1,FKPT(FX)
	EXCH T1,FREFK		;PUT FORK NUMBER ON FREE LIST
	TLO T1,400000
	MOVEM T1,@FREFK
	CALL FKGC		;CLEAN UP ALL PAGES OF FORK
	HRRZ 1,FKWSP(FX)	;MAKE SURE FORK CLEANED UP
	HRRZ 2,FKCNO(FX)
	CAIN 1,0
	CAIE 2,0
	BUG(FRKNDL)
	CALL SETPSK		;SET PAGING TO SCHED CONTEXT
	JRST SCHED0		;NOW THERE IS NOTHING LEFT OF JOB...
;WAIT FOR PSB AND UPT TO HAVE SHARE COUNT OF 1

WTFPGS::HRRZ 1,FKPGS(FX)	;PSB
	CALL WTSPT
	LOAD T1,FSSPTN		;GET STACK PAGE
	CALL WTSPT		;WAIT FOR THIS AS WELL
	HLRZ 1,FKPGS(FX)	;UPT
WTSPT::	PUSH P,4
WTSPT2:	MOVE 2,1		;SAVE 1 SINCE WTSPTT CLOBBERS IT
	JSP 4,WTSPTT		;TEST PAGE NOW
	JRST WTSPT1		;MUST WAIT
	POP P,4			;NOW OK
	RET

WTSPT1:	MOVSI 1,0(2)
	HRRI 1,WTSPTT
	MDISMS
	HLRZ 1,1
	JRST WTSPT2

WTSPTT::CALL GETSHR		;GET SHARE COUNT
	CAIE 1,1
	JRST 0(4)
	JRST 1(4)
;PRELIMINARY FORK INIT

FKSET:	MOVE 1,UPP		;GET USUAL MON STACK
	MOVEM 1,PIAC+P		;PUT IN AC17
	MOVE T1,[IOWD NPSIPG*PGSIZ,PSIPGA] ;SET UP STACK POINTER
	MOVEM 1,PSIPT		;PSI STORAGE STACK
	MOVEI 1,<UACB>B39-1	;SETUP AC BASE
	MOVEM 1,ACBAS
	CALL FKSETK		;SETUP HWPT STUFF
	MOVE 1,INTDF0		;INTERRUPT SWITCHES
	MOVEM 1,INTDFF
	MOVE 1,MJRST0
	MOVEM 1,MJRSTF
	MOVEI 1,PSISV1
	MOVEM 1,PIPC+2
	SETZM PIPC+1		;INSURE FLAGS 0
	SETZM NSKED
	SETZM CRSKED
	SETZM SNPPGS		;INITIALIZE SNOOP BREAK POINTS
	SETZM SNPLST		;  NONE TO START WITH
	SETOM PSISYS		;INIT PI SYSTEM OFF
	MOVE 1,RSKEDN
	MOVEM 1,RSKED
	MOVSI 1,<MOVEM 1,0>B53
	MOVEM 1,PATU40		;SETUP INSTRUCTION PART FOR COMPAT
	MOVEM 1,PATUPC		;ENTRY PROCEDURE
	MOVEM 1,DMSU40		;SET UP FOR DMS CALLS
	MOVEM 1,DMSUPC
	SETOM SLOWF
	SETOM INTDF
	SETOM TRAPC
	MOVE 1,NPMAX		;INIT LOCAL NPMAX TO SYSTEM NPMAX
	MOVEM 1,FNPMAX
	SETOM FKTAB
	MOVEI 1,FKTAB+1
	HRLI 1,-1(1)
	BLT 1,FKTAB+NLFKS/2-1
	SETZM JTTRW		; Clear JSYS trap word
	SETZRO JTFRK		; Clear trapped fork
	MOVEI T1,7777		; We haven't interrupted anyone yet
	STOR T1,JTMNI		; ...
	MOVEI T1,77		; And we don't want to be interrupted
	STOR T1,JTMCN
	MOVE T1,[IFIW!FKJTB]	; Put under top fork's environment
	MOVEM T1,JTBLK		;  until CFROK can update to FKJTB+forkn
	SETOM JTLCK		; Clear lock
	MOVE FX,FORKX
	CALL FKSETP		;SETUP PSB AND UPT POINTERS
	MOVEI T1,NPSIPG		;MUST CREATE ALL PI PAGES
	MOVEI T2,PSIPGA		;THE FIRST ONE
FKSET4:	SETZM 0(T2)		;CREATE THIS ONE
	ADDI T2,PGSIZ		;NEXT PAGE
	SOJG T1,FKSET4		;DO ALL OF THEM
	MOVE 6,PIMSK		;GET REQUEST BITS
	TLNE 6,NEWJBF		;NEW JOB TOO?
	JRST FKSET1		;YES
	HRRZ 1,FKJOB(FX)	;GET JSB
	CALL UPSHR		;BUMP SHARE COUNT
	MOVEI 1,FKSET2
FKSET3:	MOVEM 1,PIPC
	SETZM PIFL
	SETZM PIOLDS
	JRST PIRQR		;DEBREAK - RUN IN NORMAL MODE
;INIT NEW JOB

FKSET1:	HRREI T2,0(6)		;GET NUMBER OF CONTROLLING TTY, IF ANY
	LOAD 1,FKJOBN		;GET JOB NUMBER
	MOVEM 1,JOBNO
	MOVSM 2,JOBPT(1)	;TTY ASSIGNED TO JOB
FKSE01:	MOVE T3,FORKX
	HRRM T3,JOBPT(1)		;TOP FORK OF JOB
	PUSH P,T1		;SAVE JOB NUMBER
	MOVE T1,FORKX		;SET FORKX INTO THIS TTY'S PSI DESTINATION
	SKIPL T2		;IF THERE IS A TTY,
	CALL STTOPF		; PUT IN THE FORKX
	POP P,T1		;RESTORE JOB NUMBER
	SETZM JOBRT(1)		;JOB RUNTIME
	SETZRO JOBRTP,(1)	; No job runtime limit
	SETZRO TIMCNT,(1)	;  and no clocks in use yet
	HRRZ T2,JOBCLS(1)	;GET CLASS OF THIS JOB
	MOVE T1,T2		;GET CLASS
	SKIPE CLASSF		;IF DOING CLASS SCHEDULING, ADJUST
	CALL ADJCLS		;AND SET UP PARAMETERS
	CALL LGTAD		;GET CURRENT TIME
	MOVEM T1,SRTTIM		;REMEMBER TIME JOB STARTED (MAYBE -1)
	SETOM FKCTTY		;INIT JOB CTTY FOR ALL FORKS
	MOVE T1,[FKCTTY,,FKCTTY+1]
	BLT T1,<FKCTTY+<NUFKS-NUFKS/2>>
	MOVE T1,JOBNO
	HLRE T2,JOBPT(T1)	;CONTROLLING TTY, IF ANY, -1 IF NONE
	MOVEM T2,CTRLTT		;IN JSB
	LOAD T1,FKJSB		;GET JSB IDENT
	MOVE T2,SHRPTR		;CONSTRUCT JSB MAPPING
	STOR T1,SPTX,T2
	MOVEM T2,JOBM0+JSBPG
	SETZM @JTBLK		; No jsys traps for top fork
	MOVEI T1,DCOPNM		;DEFAULT MAX DECNET LINKS
	STOR T1,DCMAX		;TO THE JSB
	MOVEI T1,ATJBMX		;MAXIMUM HTN'S FOR A JOB
	STOR T1,JSAMX		;STORE IN JSB
	MOVEI 1,EXEC0
	JRST FKSET3

FKSET2:	XCTU [SETZM 0]		;CLEAR USER AC'S
	MOVEI CX,1
	XBLTUU [BLT CX,17]
	ENTSKD
	SETZM PPC		;SET PC 0
	MOVSI 1,(UMODF)
	MOVEM 1,PFL
	MOVEI 1,HALTT
	JRST DISMSE

INTDF0:	SOS INTDF		;NORMAL CONTENTS OF INTDFF
MJRST0:	XJRSTF FFL		;NORMAL CONTENTS OF MJRSTF
CHNSON::EXP 1B9+1B11+1B12+1B15+1B16+1B17+1B18+1B20 ;ALWAYS ON PSI CHANS
;PSEUDO-INTERRUPT SYSTEM

NEWFKF==:1B20			;INITIATE NEW FORK - PI FLAG
NEWJBF==:1B21			;INITIATE NEW JOB - PI FLAG
PSIIF==:1B22			;CHANNEL INTERRUPT REQUESTED IN FKINTB
PSIT1F==:1B23			;TERMINAL CODE INTERRUPT, PHASE 1
PSIT2F==:1B24			;TERMINAL CODE INTERRUPT, PHASE 2
SUSFKR==:1B25			;SUSPEND FORK REQUEST
PSIWTF==:1B26			;JOB WAS IN WAIT STATUS
PSILOB==:1B27			;LOGOUT JOB REQUEST
FRZB1==:1B28			;DIRECT FREEZE HAS BEEN DONE
FRZB2==:1B29			;INDIRECT FREEZE HAS BEEN DONE
FRZBB==:FRZB1+FRZB2		;BOTH BITS FOR EXTERNAL REFS
PSICOB==:1B30			;CARRIER OFF ACTION REQUEST
PSITLE==:1B31			;TIME LIMIT EXCEEDED INTERRUPT
PSIJTR==:1B32			; JSYS trap request
JTFRZB==:1B33			; JSYS trap freeze
ADRBKF==:1B34			;ADDRESS BREAK REQUEST
ABFRZB==:1B35			;ADDRESS BREAK FREEZE
FRZBAL==:ABFRZB+JTFRZB+FRZBB	; All types of freezes
DEFSTR (TRMCOD,,35,9)		; FIELD IN FKINT OR PIMSK FOR TERM
;DEFS IN RH OF WORD

PSIPRI==:1B18			;PRIORITY WORD SET.
UNUSED==MASKB(19,26)		;UNUSED FKINT BITS
				; INT CODE
;SCHEDULER CAUSES JOB TO BE STARTED HERE ON PI REQUEST
;SAVED PC IN PIPC
;PIMSK CONTAINS INTERRUPT REQUEST WORD

PIRQ:	MOVEM P,PIAC+17
	MOVEI P,PIAC		;SAVE USER AC'S
	BLT P,PIAC+16
	MOVE P,PIPDL		;SET UP LOCAL STACK
	MOVE P2,TRAPFL
	MOVE P3,KIMUFL
	MOVE P4,TRAPPC		;SAVE IMMEDIATELY VULNERABLE CELLS
	MOVE P5,KIMUPC
	MOVE P6,KIMUEF
	MOVE FX,PIMSK		;INTERRUPT REQUEST WORD
	MOVE Q2,FORKX
	SETZ 2,
	TLZE FX,PSIWTF		;WAS JOB IN WAIT STATUS?
	MOVE 2,FKSTAT(Q2)	;YES, GET OLD STATUS
	MOVEM 2,PIOLDS		;SAVE OLD STATUS, OR 0 IF WAS RUNNING
	TLZE FX,NEWFKF		;START NEW FORK?
	JRST FKSET		;YES
	TLZE FX,PSIT1F
	JRST PSIT1		;TERMINAL, PHASE 1
	TLZE FX,PSIT2F
	JRST PSIT2		;TERMINAL, PHASE 2
	TLZE FX,PSITLE		;TIME LIMIT EXCEEDED INTERRUPT?
	JRST TLEINT		;YES, GO INTERRUPT THE FORK
	TRZE FX,PSIPRI		;SET PRIORITY WORD?
	JRST PRISET		;YES. GO FIX UP DATA BASE
PSITR1:	TLNE FX,PSIIF+SUSFKR+PSILOB+PSICOB+PSIJTR+ADRBKF
	JRST PSII		;CHANNEL INTERRUPT SPEC. BY FKINTB
PIRQR:	CALL UNPIR		;LEAVE PI STATE
PSIDF1:	SKIPN 1,PIOLDS		;WAS RUNNING BEFORE PSI?
	JRST SCHED0		;YES
	CAIE 1,TRMTS1		;WAITING FOR ARBITRARY FORK TERM?
	JRST DISMSE		;NO, RETURN TO WAIT STATE
	SETZM PIOLDS		;CLEAR OLD STATE
	MOVEI 1,WFORKA		;GO BACK INTO JSYS TO DO TEST
	MOVEM 1,PPC		; AND MAKE THIS THE PC
	SETZM PFL		; SET FLAGS
	JRST SCHED0		;GO RESCHEDULE THIS PROCESS
;LEAVE PSI CONTEXT.  RETURN THROUGH SCHEDULER

UNPIRN:	TDZA T1,T1		;DON'T REQUEUE IF BUMPED
UNPIR:	MOVEI T1,1		;CONDITIONAL REQUEUE IF BUMPED
	AOS INSKED		;ENTER SCHEDULER
	POP P,CX		;GET LOCAL RETURN
	MOVE P,PI7P		;SETUP SCHED STACK
	PUSH P,CX		;PUT LOCAL RETURN ON IT
	PUSH P,T1		;SAVE ENTRY FLAG ON STACK
	MOVEM P2,TRAPFL
	MOVEM P3,KIMUFL
	MOVEM P4,TRAPPC		;RESTORE VULNERABLE CELLS
	MOVEM P5,KIMUPC
	MOVEM P6,KIMUEF
	MOVE 1,[XWD PIAC,PAC]
	BLT 1,PAC+17		;PUT AC'S BACK
	JSP FX,KISSAV		;SAVE APR-DEPENDENT STUFF
	MOVE 1,PIFL
	MOVEM 1,PFL
	MOVE 1,PIPC
	MOVEM 1,PPC
	MOVSI 1,200000
	MOVE FX,FORKX
	TDNN T1,FKINT(FX)
	BUG(UNPIRX)
	ANDCAM 1,FKINT(FX)
	JE PIBMP,,[POP P,0(P)	;CLEAN UP THE STACK
		   RET]		;AND DONE
	SETZRO PIBMP		;CLEAR BUMPING
	POP P,CX		;GET BACK ENTFLG
	SKIPE CX		;REQUEUEING WANTED?
	SKIPE PIOLDS		;YES. CONTINUE AS RUNNABLE?
	RET			;NO. DONE THEN
	SAVET			;YES. SAVE ALL REGS
	CALL GLREM		;REMOVE FROM GOLST
	CALLRET GOCONC		;AND DONE

PIPDL:	IOWD NPIPDL,PIPDB	;INTERRUPT ROUTINES LOCAL PDL

;REQUEST PSEUDO INTERRUPT

;IIC TO SELF - FOR MONITOR INTERNAL USE.  FASTER THAN IIC AND DOES
;NOT REQUIRE PROCESS TO BE ABLE TO SET FKLOCK.
; 1/ CHANNEL MASK
;	CALL IICSLF
; RETURN +1 ALWAYS

;PSIRQ0 - SAME AS IICSLF EXCEPT TAKES CHANNEL NUMBER IN 1 RATHER THAN MASK

PSIRQ0::MOVE 1,BITS(1)		;GET MASK FOR CHANNEL
IICSLF::TDNN 1,PSICHM		;SEE IF INTERRUPT WILL BE TAKEN
	TDNE 1,CHNSON
	JRST IICSL1		;YES
	TDNN 1,SUPCHN
	RET			;NO, DON'T SEND IT
IICSL1:	NOINT
	MOVE 2,FORKX
	CALL PSIRQB		;REQUEST THE INTERRUPT
	OKINT
	CHKINT			;GET IT PROCESSED IF POSSIBLE
	RET
;GENERAL PSI REQUEST HANDLER
; 1/ CHANNEL MASK FOR PSIRQB, CHANNEL NUMBER FOR PSIRQ
; 2/ FORK INDEX
;	CALL ...
; RETURN +1 ALWAYS

PSIRQ::	MOVE 1,BITS(1)
PSIRQB::HRRZS 2
	IORM 1,FKINTB(2)	;SET BIT IN INTERRUPT WAITING BUFFER
PSITQ:	MOVSI 1,400000+PSIIF	;REGULAR INTERRUPT FLAG
	IORM 1,FKINT(2)
	CAMN 2,FORKX		;FOR THIS FORK?
	RET			;YES
PSIR4::	NOSKD1
	PUSH P,FX
	MOVEI FX,0(2)
	MOVE 1,FKINT(FX)
	TLNE 1,(1B1)		;FORK NOW INTERRUPTABLE?
	JRST PSIR61		;NO
	JN FKBLK,,[MOVSI 1,PSIWTF	;YES, SET FLAG
		IORM 1,FKINT(FX)
		CALL UNBLK1	;WAKE UP THE FORK
		JRST .+1]	;PROCEED
	PUSH P,3
	CALL PSBUMP		;NO, GIVE FORK 'BUMP' TO GET PSI HANDLED
	POP P,3
PSIR61:	MOVEI 2,0(FX)
	POP P,FX
	OKSKD1
	RET
;TERMINAL INTERRUPT
;PHASE ONE - CALLED FROM TERM SERVICE ROUTINES
; 2/ LINE NO.,   3/ INTERRUPT CODE
;SEND TO TOP FORK TO FIND PROPER DESTINATION

TTPSRQ::PUSH P,T3		;SAVE INTERRUPT CODE
	CALL GTCJOB		;GET CONTROLLING JOB
TTPSRX:	 JRST [	POP P,T3	;NONE (SHOULDN'T HAPPEN)
		RET]
	CAIN T3,-1		;IS THERE A CONTROLLING JOB?
	JRST TTPSRX		;NO. SHOULDN'T HAPPEN
	HLRZ T4,JOBPT(T3)	;GET THE JOB'S CONTROLLING LINE
	CAIE T4,0(T2)		;IS IT THIS LINE?
	JRST TTPSR2		;NO, LOOK ELSEWHERE IN THAT JOB
	HRRZ 2,JOBPT(3)		;GET INDEX OF TOP FORK
TTPSR1:	MOVSI 1,1B18+PSIT1F	;PHASE ONE REQUEST
	IORM 1,FKINT(2)
	POP P,T3		;RESTORE INTERRUPT CODE
	STOR 3,TRMCOD,FKINT(2)	;INTERRUPT CODE
	JRST PSIR4		;SET NEW STATUS

TTPSR2:	CALL GTTOPF		;GET TOP FORK OF TTY'S CTTY GROUP
	 JRST TTPSRX		;THAT TTY ISN'T ACTIVE
	MOVEI T2,(T3)		;COPY THE FORKX
	CAIL T2,NFKS		;IS IT VALID? (ELSE -1 FOR NONE)
	JRST TTPSRX		;NO
	JRST TTPSR1		;YES, GO INTERRUPT THIS FORK

FKCTYP::POINT 18,FKCTTY,17	;POINTERS TO FKCTTY HALF-WORD TABLE
	POINT 18,FKCTTY,35
;ROUTINES TO HANDLE INTERRUPT CONDITIONS AS SPECIFIED BY BITS
;IN LEFT HALF OF FKINT

;TERMINAL INTERRUPT, PHASE ONE
;THIS CODE RUN IN TOP FORK ONLY

PSIT1:	LOAD Q2,TRMCOD,FX	;GET TERM INTERRUPT CODE
	MOVE Q2,BITS(Q2)
	HRRZ 1,FORKN		;START WITH TOP FORK
	IDIVI T1,2		;GET THE CTTY FOR THIS FORK
	ADD T1,FKCTYP(T2)
	LDB T4,T1		;TTY DEVICE DESIGNATOR
	HRRZ T1,FORKN		;RESTORE FORK NUMBER
	SETO Q1,
	TDNE Q2,FKPSIE(1)	;TERM CODE ON IN FORK?
	MOVEI Q1,0(1)		;YES, REMEMBER FORK
	CALL PSIT1A		;LOOK AT ALL INFERIORS
	JUMPL Q1,PSIT11		;NOT FOUND, SO TURN OFF CODE
	HRRZ 2,SYSFK(Q1)		;GET SYSTEM INDEX OF FORK TO GET INTERPT
	CAMN 2,FORKX		;THIS FORK?
	JRST PSIT2		;YES, GO DIRECTLY TO PHASE TWO
	NOSKED
	LOAD T1,TRMCOD,FX	;NO. GET TERM INTERRUPT CODE
	STOR T1,TRMCOD,FKINT(T2) ; AND SET UP INT FOR PROPER FORK
	MOVSI 1,PSIT2F+400000	;PHASE TWO REQUEST FLAG
	IORM 1,FKINT(2)
	CALL PSIR4
	OKSKED
	JRST PSITR1

PSIT11:	CAIN T4,-1		;SOURCE OF PSI = JOB CTTY?
	JRST PSIT12		;YES
	TRZN T4,1B18		;MAYBE, CONVERT TO LINE #
	JRST PSITR1		;DESIGNATOR, NOT TTY. RETURN.
	CAMN T4,CTRLTT		;CTTY OF JOB?
	JRST PSIT12		;YES
	CAIGE T4,NLINES		;VALID TTY NUMBER?
	CAIGE T4,0
	JRST PSITR1
	JRST PSIT13		;YES

PSIT12:	ANDCAM Q2,TTSPSI ;NOT FOUND, SO TURN OFF CODE
	SKIPGE T2,CTRLTT
	JRST PSITR1
PSIT13:	MOVE T1,Q2		;T1/ INTERRUPT BIT
	CALL CLRINT		;CLEAR THE INTERRUPT IN TERMINAL'S DATA
	JRST PSITR1
;SEARCH FORK STRUCTURE FOR FORK TO INTERRUPT
; T4/ DESIGNATOR OF SOURCE OF THIS PSI

PSIT1A::ADD 1,INFERP		;LOOK AT INFERIOR LIST
PSIT1B:	LDB 1,1			;GET NEXT IN LIST
	JUMPE 1,R		;RETURN AT END OF LIST
	PUSH P,T1		;SAVE THE FORKN
	IDIVI T1,2		;COMPUTE POINTER TO THAT FORK'S CTTY
	ADD T1,FKCTYP(T2)	; ..
	LDB T2,T1		;GET THE TTY DESIGNATOR
	POP P,T1		;RESTORE THE FORKN
	CAIE T2,0(T4)		;IS IT THE ONE THAT MADE THIS PSI?
	JRST PSIT1E		;NO, SO DON'T CONSIDER FORK.
	HRRZ 2,SYSFK(1)		;CHECK STATE OF FORK
	PUSH P,FX		;SAVE FX
	MOVEI FX,0(T2)		;SEE IF THIS FORK IS FROZEN OR HALTED
	CALL CHKWT		; ..
	 JRST [	POP P,FX	;IT'S NOT.
		JRST PSIT1D]
	POP P,FX		;YES, SEE WHICH
	HRRZ T3,FKSTAT(T2)	;GET ITS STATE
	CAIN T3,FRZWT		;FROZEN?
	JRST PSIT1G		;YUP
	CAIE T3,HALTT		;NO, HALTED OR FORCED TERM?
	CAIN T3,FORCTM		; ..
	JRST PSIT1C		;YES.
PSIT1D:	TDNE Q2,FKPSIE(1)	;FORK HAS CODE ENABLED?
	MOVEI Q1,0(1)		;YES, REMEMBER IT
PSIT1E:	HRLM T1,0(P)		;REMEMBER CURRENT FORK
	CALL PSIT1A		;CHECK ITS INFERIORS
	HLRZ T1,0(P)		;RECOVER CURRENT FORK
	XMOVEI T2,20		;RESTORE RETURN ADDRESS
	HLLM T2,0(P)
PSIT1C:	ADD T1,PARALP		;LOOK AT ITS PARALLELS
	JRST PSIT1B		;DO PARALLELS

PSIT1G:	MOVSI T3,JTFRZB		;FORK FROZEN. BY JSYS TRAP?
	TDNN T3,FKINT(T2)	; ..
	JRST PSIT1C		;NO. ORDINARY FREEZE
	MOVSI T3,FRZBB		;YES. ONLY TRAP, OR OTHERS TOO?
	TDNE T3,FKINT(T2)	; ..
	JRST PSIT1C		;OTHERS TOO. DON'T CONSIDER THIS FK
	JRST PSIT1D		;NO, JUST JSYS TRAP. IT MAY STILL
				; TAKE THE PSI, SO CONSIDER THIS FK.

;FORK STRUCTURE POINTERS

SUPERP::POINT 12,FKPTRS,11	;SUPERIOR
PARALP::POINT 12,FKPTRS,23	;PARALLEL
INFERP::POINT 12,FKPTRS,35

;TERMINAL INTERRUPT, PHASE TWO

PSIT2:	LOAD T1,TRMCOD,FX	;GET TERM INTERRUPT CODE
	CALL GETCHA
	LDB 2,2
	MOVE 1,BITS(2)		;AND SET BIT IN INT. WAITING WORD
	AND 1,PSICHM		;BUT ONLY FOR ENABLED CHANNELS
	IORM 1,PSIBW
	JRST PSII		;THEN GO PROCESS IT

;TIME LIMIT EXCEEDED INTERRUPT
;ROUTINE TO ISSUE TIME LIMIT EXCEEDED INTERRUPT
;  RUN BY TOP FORK OF JOB ONLY

TLEINT:	MOVE T1,JOBNO		; Get the job
	LOAD T2,JOBRTP,(T1)	; And then ptr to runtime limit blk
	JUMPE T2,PSITR1		; If none, then don't do this
	PUSH P,T2		; Save so we can release blk
	LOAD T1,TIMCHN,(T2)	; Channel for poke
	LOAD T2,TIMFRK,(T2)	; And fork to poke
	CALL PSIRQ
	POP P,T4		; Blk to be released
	CALL CLKKIL		; Release storage for clock
	MOVE T1,JOBNO
	SETZRO JOBRTP,(T1)	; And finally clear the ptr
	JRST PSITR1		;CONTINUE ON

;PRIORITY WORD WAS SET. COMPUTE NEW FKMXQ

PRISET:	PUSH P,FX		;SAVE INT BITS
	MOVE FX,FORKX		;GET FORK HANDLE
	SKIPN T1,JOBBIT		;GET LOCAL PRIORITY WORD
	MOVE T1,JOBSKD		;GET JOB PRIORITY WORD
	LDB T1,[POINT 6,T1,29]	;GET HIGH Q NUMBER FROM PRIORITY WORD
	STOR T1,FKMXQ		;NEW MAX Q FOR PROCESS
	POP P,FX
	JRST PSITR1		;PROCEED
;SUSPEND FORK REQUEST

PIRSFK:	MOVE 1,FX		;GET PIMSK
	MOVE FX,FORKX
	TLZ 1,400000+SUSFKR	;CLEAR THIS REQUEST
	IORM 1,FKINT(FX)	;KEEP OTHER REQUESTS
	DMOVE 1,PIFL
	CALL PITEST		;NOW INTERRUPTABLE?
	JRST PIRSF1		;NO
	MOVEI 3,SUSWT		;SUSPENDED FORK TEST
PIRSK1:	MOVE 2,FORKX
	MOVSI 1,SUSFKR
	ANDCAM 1,FKINT(2)
	CALL UNPIRN		;LEAVE INTERRUPT STATE
	IORM 1,FKINT(FX)	;KEEP INTERRUPT STARTING BIT
	MOVEI 1,0(3)		;SUSWT OR FRZWT
	HRL 1,PIOLDS		;WITH OLD STATUS
	PUSH P,T1
	MOVEI T1,SUSFKT
	CALL WAKSUP		;WAKEUP SUPERIOR IF WAITING FOR SUSP
	POP P,T1
	JRST DISMSE		;DISMISS

PIRSF1:	MOVE FX,FORKX
       NOSKED			;
	HRRZ T1,FKSTAT(FX)	;
	CAIN T1,JTQWT		; IN JSYS TRAP QUEUE WAIT?
	JRST PIRSF2		; YES, ALLOW SUSPENSION
       OKSKED			;
	MOVSI 1,SUSFKR		;TURN REQUEST BIT BACK ON
	IORM 1,FKINT(FX)
	JRST PSIDFR		;AND SET DEFERRED INTERRUPTS

PIRSF2:	MOVEI T1,FKJTQ(FX)	; FORK IN JSYS TRAP QUEUE WAIT
	CALL JTDEQ		; REMOVE IT FROM QUEUE
	MOVEI T1,JTRLCK		; SET RESUME ADDR. TO LOCK ROUTINE
	SETZM PIOLDS		;
	SETZM PIFL
	MOVEM T1,PIPC		;
       OKSKED			;
	MOVEI T3,SUSWT		;
	JRST PIRSK1		;

SUSWT::	JRST 0(4)		;SCHEDULER TEST FOR SUSPENDED FORK

;CARRIER OFF ACTION REQUEST

PIRCOF:	DMOVE 1,PIFL
	CALL TFTEST		;INTERRUPT OK NOW?
	 JRST [	MOVE FX,FORKX	;NO, SETUP DEFER
		MOVSI 1,PSICOB	;KEEP REQUEST
		IORM 1,FKINT(FX)
		JRST PSIDFR]	;GO SET DEFER
	MOVSI T1,PSIWTF		;SEE IF PROCESS WAS WAITING
	TDNE T1,PIMSK		;WAS IT?
	SOS PIPC		;YES. MAKE IT GO BACK INTO WAIT THEN
	MOVSI T1,PSICOB		;GET THE BIT FOR THIS CONDITION
	MOVE FX,FORKX		;GET THIS FORK'S ID
	ANDCAM T1,FKINT(FX)	;CLEAR THIS CONDITION (NECESSARY
				; IF THIS WAS DEFERRED).
	MOVEI 1,JOBCOF		;SET TO DEBREAK TO ACTION PROCEDURE
	JRST PIRLG1

;LOGOUT REQUEST

PIRLGO:	DMOVE 1,PIFL
	CALL TFTEST		;OK TO INTERRUPT?
	JRST [	MOVE FX,FORKX	;NO, REMEMBER REQUEST
		MOVSI 1,PSILOB
		IORM 1,FKINT(FX)
		JRST PSIDFR]
	MOVEI 1,FLOGO
PIRLG1:	SETZM PIOLDS		;MAKE FORK RUNNABLE
	EXCH 1,PIPC
	MOVE T2,PIFL		;GET CURRENT FLAGS. PRESERVE THEM ALSO
	SKIPGE SLOWF
	JRST [	MOVEM 1,FPC	;IN USER MODE, SIMULATE JSYS
		MOVEM 2,FFL
		JRST PIRQR]
	MOVE 2,PIAC+17		;IN MON MODE, SIMULATE PUSHJ
	PUSH 2,1
	MOVEM 2,PIAC+17
	JRST PIRQR

;SPECIAL TEST USED BEFORE INTERRUPT TOP FORK FOR LOGOUT OR CARRIER OFF

TFTEST:	CALL PITEST		;INTERRUPTABLE NORMALLY?
	 RET			;NO, NOT HERE EITHER
	MOVX 2,LOGIOB
	TDNE 2,JOBBIT		;LOGGING IN OR OUT?
	RET			;YES, NO INTERRUPT
	RETSKP			;NO, INTERRUPT OK

; JSYS TRAP REQUEST

PIRJTP:	DMOVE T1,PIFL		; Pick up flags
	CALL PITEST		; FORK INTERRUPTABLE?
	JRST PIRJT1		; NO, DEFER IT
	MOVSI T1,PSIJTR		;
	MOVE FX,FORKX		; IN CASE THIS PSI WAS DEFERRED
	ANDCAM T1,FKINT(FX)	; CLEAR IT FROM FKINT
	LOAD T1,JTMCN		; GET PSI CHANNEL FOR TRAP
	MOVE T1,BITS(T1)	;
	IORM T1,PSIBW		; SET BIT IN INT WAITING WORD
	SETZ FX,		;
	JRST PSII		; GO PROCESS THE TRAP

PIRJT1:	MOVE FX,FORKX		; DEFER THE JSYS TRAP PSI
	MOVSI T1,PSIJTR		;
	IORM T1,FKINT(FX)	;
	JRST PSIDFR		;

;ADDRESS BREAK REQUEST - FREEZE FORK AND INTERRUPT SUPERIOR

PIRABK:	MOVE T1,FX		;GET REQUEST BITS
	MOVE FX,FORKX		; AND FORK INDEX
	TLZ T1,400000+ADRBKF	;CLEAR BITS FOR THIS REQUEST
	IORM T1,FKINT(FX)	;SAVE OTHERS
	DMOVE T1,PIFL		;GET INTERRUPTED PC DOUBLEWORD
	CALL PITEST		;INTERRUPTABLE?
	 JRST PIRBK1		;NO
	MOVSI T1,FRZB1+ABFRZB	;YES, INDICATE FREEZE DUE TO ADDR BRK
	IORM T1,FKINT(FX)	; ..
	MOVSI T1,ADRBKF		;CLEAR ORIGINAL REQUEST BIT
	ANDCAM T1,FKINT(FX)	; ..
	CALL FKTMI		;INTERRUPT SUPERIOR FORK
	CALL UNPIRN		;LEAVE PSI CONTEXT
	SETZM PIOLDS		;SET OLD STATE TO RUNNING
	MOVEI T1,FRZWT		;WAIT LIST ON WHICH WE WISH TO LIVE
	JRST DISMSE		;DISMISS

PIRBK1:	MOVSI T1,ADRBKF		;RE-LIGHT REQUEST BIT
	IORM T1,FKINT(FX)	; ..
	JRST PSIDFR		;AND DEFER THE INTERRUPT
;PROCESS INTERRUPT(S) FOR THIS FORK AS SPECIFIED BY FKINTB
;THIS CODE *CAN* CAUSE PAGE FAULTS WHEN REFERENCING THE USER
;CHANNEL AND LEVEL TABLES.

PSII:	MOVE 1,MJRST0		;NORMALIZE ALL DEFER TRAPS
	MOVEM 1,MJRSTF
	MOVE 1,INTDF0
	MOVEM 1,INTDFF

;DETERMINE REASON FOR THE INTERRUPT AND GO PROCESS IT.

	TLNE FX,SUSFKR		;FORK SUSPENSION REQUEST?
	JRST PIRSFK		;YES
	TLNE FX,PSILOB		;LOGOUT REQUEST?
	JRST PIRLGO
	TLNE FX,PSICOB		;CARRIER OFF REQUEST?
	JRST PIRCOF		;YES
	TLNE FX,PSIJTR		; JSYS trap requested?
	 JRST PIRJTP		; Yes
	TLNE FX,ADRBKF		;ADDRESS BREAK REQUEST?
	JRST PIRABK		;YES, HANDLE

;HERE BECAUSE BIT PSIIF IS SET IN FKINT, INDICATING A CHANNEL
;INTERRUPT. FKINTB HAS BIT SET FOR EACH CHANNEL THAT NEEDS TO
;INTERRUPT.

	MOVE 2,FORKX
	MOVEI 1,0
	EXCH 1,FKINTB(2)	;RESET FKINTB TO 0
	IORM 1,PSIBW		;INCLUDE IN PROCESS WAITING BREAKS
	MOVE 1,PSICHM		;USERS ENABLED CHANNELS
	IOR 1,CHNSON		;WITH ALWAYS ON CHANNELS
	IOR 1,SUPCHN		;WITH SUPERIOR RESERVED CHANNELS
	SKIPE 3,PIOLDS		;WAS FORK WAITING?
	JRST [	SKIPN FORKN	;AND NOT TOP FORK?
		JRST .+1	;NO
		MOVEI 3,0(3)	;YES, HALT OR FORCED TERM?
		CAIE 3,HALTT
		CAIN 3,FORCTM
		JRST PIRQR	;YES. IGNORE REQUEST UNTIL LATER
		JRST .+1]
	ANDB 1,PSIBW		;FLUSH DISABLED CHANS
	JUMPE 1,PIRQR		;RETURN IF NO BREAKS WAITING
	DMOVE 1,PIFL		;PROCESS PC
	;..
	;..
	CALL PITEST		;CAN PROCESS BE INTERRUPTED NOW?
	 JRST PSIDFR		;NO, GO SETUP DEFERRED INTERRUPT
	MOVE 1,PSIBW
	TDNE 1,MONCHN		;MONITOR RESERVED CHANNEL?
	JRST PSIMB		;YES
	TDNN T1,CHNSON		;PANIC CHANNEL?
	JRST PSIN5		;NO
	DMOVE T1,PIFL		;YES, CHECK FOR ERJMP/ERCAL
	TXNN T1,UMODF		;USER PC NOW?
	JRST [	DMOVE T1,UPDL	;NO, GET IT
		EXCH T1,T2	;(IN PROPER ORDER)
		JRST .+1]
	CALL SETPCV		;SET PREVIOUS CONTEXT FOR ITRSIM
	CALL ITRSIM		;CHECK AND INTERPRET ER INSTRUCTION
	 JRST PSIN6		;NONE THERE, CONTINUE WITH INTERRUPT
	MOVEM T3,PIPC		;FOUND, SET PC TO E OF INSTRUCTION
	MOVEM T1,PIFL		;AND FLAGS TO USER FLAGS
	MOVE T3,CHNSON		;CLEAR INTERRUPT REQUEST
	ANDCAM T3,PSIBW
	JRST PIRQR		;RETURN TO USER

PSIN6:	MOVE T1,PSIBW
PSIN5:	AND 1,SUPCHN		;LOOK AT SUPERIOR RESERVED CHANS
	JUMPN 1,PSIN3		;TERMINATE IF ANY
	MOVE 1,PSIBW
	AND 1,CHNSON		;LOOK AT SPECIAL CHANNELS
	SKIPE PSISYS		;IF THIS PROCESS NOT TAKING PSI'S,
	JUMPN 1,PSIN3		;TERMINATE IT IF ANY SPECIALS
	ANDCM 1,PSICHM		;AND'ING WITH USER'S 'OFF' CHANNELS
	JUMPN 1,PSIN3		;TERMINATE CAUSE CHANNEL NOT ACTIVE
	SKIPE PSISYS		;PSI SYSTEM ON?
	JRST PIRQR		;NO
	SKIPN PSLEVT		;THIS PROCESS TAKING INTERRUPTS?
	JRST PSIN1		;NO, GO TRANSMIT THE PSI
	XJRSTF [PCU+MSEC1
		MSEC1,,.+1]	;SET PCS SO EXT REFS WORK
	MOVE 1,PSIBW		;FIND HIGHEST PRIORITY INTERRUPT
	MOVEI 2,0		;NOW WAITING
	MOVSI 3,1

;PSIBW (AND AC 1) HAS A BIT SET FOR EACH CHANNEL TO GIVE AN INTERRUPT.
;FIND THE LEFTMOST BIT THAT IS SET. THIS CODE ASSUMES NON-ZERO AC1.

PSIS1:	JUMPL 1,PSIS2		;THIS CHANNEL HAS WAITING BREAK?
PSIS4:	LSH 1,1			;NO, SHIFT TO NEXT CHANNEL
	ADDI 2,1		;COUNT CHANNEL NUMBER
	JUMPN 1,PSIS1		;KEEP LOOKING IF ANY BITS LEFT
	JRST PSIS10		;NO MORE. GO FINISH
;HERE WHEN NEED TO INTERRUPT FOR A CHANNEL. DETERMINE THE CORRESPONDING
;LEVEL. IF LEVEL IS .LE. PREVIOUS LOW, SAVE IT AND CHANNEL NUMBER.
;(LOW LEVEL NUMBER IS HIGH PRIORITY)

;T2/ CHANNEL NUMBER
;T3/ PREVIOUS LOW LEVEL NUMBER

PSIS2:	MOVE 4,PSCHNT		;GET ADR OF USER'S CHANNEL TABLE
	ADDI 4,0(2)		;COMPUTE ADR OF USER'S CHANNEL WORD
	UMOVE T4,@T4		;GET LEVEL NUMBER FOR THIS CHANNEL
	ERJMP PSIN1
	JN PSXSIR,,[	LOAD T4,SILEV,T4 ;GET LEVEL NUMBER
			JRST PSIS3]
	HLRZS T4		;GET LEVEL NUMBER
PSIS3:	CAILE 4,NPILEV		;LEGAL LEVEL?
	SETZ 4,			;NO, TREAT AS 0
	CAIG 3,0(4)		;OLD LEVEL GREATER THAN CURRENT?
	JRST PSIS4		;NO
	MOVEI 3,0(4)		;YES, REMEMBER NEW LEVEL
	MOVEI Q1,0(2)		;AND CHANNEL NUMBER
	JRST PSIS4		;RESUME SCAN

;HERE WHEN ALL BITS HAVE BEEN LOOKED AT.
;T3/ LEVEL OF HIGHEST PRIORITY INTERRUPT FOUND
;Q1/ CORRESPONDING CHANNEL NUMBER

PSIS10:	JUMPE 3,PSID1		;NO LEVEL ASSIGNED? GO XMIT INTERRUPT
	MOVE 1,BITS(3)
	CAMG 1,PSIBIP		;OK TO BREAK ON THIS LEVEL?
	JRST [	MOVE 2,PSIBW	;NO, .GE. PRIORITY LEVEL IN PROGRESS
		TDNN 2,CHNSON	;BREAKS ON PANIC CHNS WAITING?
		JRST PIRQR	;NO, HOLD WAITING BREAKS
		MOVE 1,2
		JRST PSIN3]	;YES, MUST TERMINATE
	IORM 1,PSIBIP		;YES, REMEMBER  BREAK THIS LEVEL
	MOVE 1,PSCHNT		;GET ADR OF USER'S CHANNEL TABLE
	ADDI 1,0(Q1)		;COMPUTE ADR OF USER'S CHANNEL WORD
	UMOVE T4,@1		;GET LEVEL + ADDR OF USER'S INT ROUTINE
	ERJMP PSIN1		;IF FAILED, TERMINATE
	JN PSXSIR,,[	ANDX T4,SIADR	;IF EXTENDED, GET ROUTINE ADDRESS
			JRST PSIS9]
	HLL T4,PSCHNT		;APPLY SECTION USED IN SIR JSYS
PSIS9:	MOVE 1,PIFL		;SAVE FLAGS, GET FLAGS WHEN INTERRUPTED
	EXCH 4,PIPC		;GET PC WHEN INTERRUPTED
	TLNN 1,(UMODF)		;WAS IN USER MODE?
	JRST PSISM		;NO, MUST SAVE MONITOR CONTEXT
	HLLZM T1,PIFL		;PRESERVE USERS FLAGS
	;..
;HERE WHEN MONITOR CONTEXT HAS BEEN SAVED (IF NECESSARY). READY TO
;STORE PC INTO USER'S LEVTAB. PIFL AND PIPC ARE SET UP FOR GOING TO
;USER'S INTERRUPT ROUTINE.

;	T1/ FLAGS TO GO INTO LEVTAB
;	T4/ PC TO GO INTO LEVTAB
;	Q1/ CHANNEL NUMBER

	;..
PSIS5:	SETZM PIOLDS
	MOVE 2,PSLEVT		;GET ADR OF USER'S LEVEL TABLE
	ADDI 2,-1(3)		;COMPUTE ADR OF USER'S LEVEL WORD
	UMOVE 2,@2		;GET ADR OF PC WORD FOR THIS LEVEL
	ERJMP PSIN1		;IF FAILED, TERMINATE
	JN PSXSIR,,[	UMOVEM T1,@T2 ;SAVE FLAGS WORD
			ERJMP PSIN1 ;QUIT IF FAILED
			AOS T2
			UMOVEM T4,@T2 ;SAVE PC WORD
			ERJMP PSIN1 ;QUIT IF FAILED
			JRST PSID3]
	HRR T1,T4		;COMBINE PC
	XOR T4,PSLEVT		;SEE IF SECTIONS ARE THE SAME
	TLNE T4,-1		;ARE THEY?
	JRST PSIN1		;NO. ERROR THEN
	HLL T2,PSLEVT		;FORCE CORRECT SECTION
	UMOVEM 1,@2		;STORE BREAK PC IN USER'S MEMORY
	ERJMP PSIN1		;IF FAILED, TERMINATE
PSID3:	MOVE 1,BITS(Q1)		;CLEAR WAITING BREAK BIT FOR THIS CHANNEL
	ANDCAM 1,PSIBW
	JRST PIRQR		;TO USER


;MONITOR ROUTINE IS SHORTSTOPPING INTERRUPTS - SIMULATE  JSYS MONBK

PSIMB:	HRRZ 1,MONBK		;ROUTINE ADDRESS
	EXCH 1,PIPC		;GET OLD PC
	MOVE 3,PIFL		;GET FLAGS
	SETZM PIFL		;SET MONITOR
	SETZM PIOLDS
	HLRZ 2,MONBK		;RET LOC
	MOVEM 3,0(2)		;STORE FLAGS FOR RETURN
	MOVEM 1,1(2)		;STORE RETURN
	JRST PIRQR
;HERE WHEN INTERRUPTED OUT OF MONITOR CONTEXT. SAVE ALL RELEVANT
;INFO BEFORE GIVING THE INTERRUPT.

;THIS CODE SAVES ONTO A SPECIAL PSI STACK. IT USES AC FX AS ITS STACK
;POINTER. THE DEBRK JSYS USERS THIS INFORMATION TO CONTINUE THE INTERRUPTED
;JSYS

;T1/ FLAGS AT TIME OF INTERRUPT (FROM PIFL)
;T4/ PC AT TIME OF INTERRUPT (FROM PIPC)

PSISM:	HLRZ 2,BITS(3)		;NO, REMEMBER MONITOR INTERRUPT
	IORM 2,PSIBIP		;IN RH OF BIP WORD
	MOVE FX,PSIPT		;STORAGE STACK POINTER
	MOVE P1,FX		;SAVE POINTER
	PUSH FX,1
	PUSH FX,4		;SAVED PC AND FLAGS

;SAVE A SET OF IMPORTANT CELLS. SAVCT CONTAINS A LIST OF THEM.

	MOVSI Q2,-NSAVC		;SAVE VULNERABLE CELLS
	PUSH FX,@SAVCT(Q2)
	AOBJN Q2,.-1

;SAVE THE UPDL STACK

	MOVSI Q2,UPDL		;STORE ENTIRE MONITOR STACK
	HRRI Q2,1(FX)
	ADD FX,[XWD NUPDL,NUPDL]
	JUMPGE FX,PIOVFW	;IF POSITIVE NO ROOM
	BLT Q2,0(FX)

;STORE THE CURRENT CONTEXT AC'S AT THE TIME OF THE INTERRUPT

	MOVSI 1,PIAC		;STORE CURRENT MONITOR AC'S
	HRRI 1,1(FX)		;NOW LIVING IN PIAC
	ADD FX,[XWD 20,20]
	JUMPGE FX,PIOVFW	;IF POSISTVE NO ROOM
	BLT 1,0(FX)

;SAVE ALL AC BLOCKS (THOSE IN ACBAS BLOCKS AND PREVIOUS
;CONTEXT AC'S)

	HRRZ 1,ACBAS		;STORE ALL AC BLOCKS IN USE
	SUBI 1,<UACB>B39-1	;COMPUTE NUMBER BLOCKS IN USE
	JUMPLE 1,PSISM1		;JUMP IF NONE
	MOVEI T2,1(FX)		;SAVE PREVIOUS CONTEXT ACS
	ADD FX,[20,,20]
	JUMPGE FX,PIOVFW	;IF POSITIVE NO ROOM
	XBLTUM [BLT T2,0(FX)]
	MOVSI T2,UACB		;PUT USER ACS BACK INTO AC BLOCK
	XBLTMU [BLT T2,17]
	MOVSI 2,UACB		;SETUP TO BLT ENTIRE AC STACK
	HRRI 2,1(FX)		; .. TO PSI STACK ..
	LSH 1,4			;COMPUTE NUMBER WORDS IN USE
	HRLI 1,0(1)		;NUMBER OF WORDS BOTH HALFS
	ADD FX,1
	JUMPGE FX,PIOVFW	;IF POSITIVE NO ROOM
	BLT 2,0(FX)
PSISM1:	PUSH FX,1		;SAVE COUNT FOR DEBRK
	PUSH FX,ACBAS		;AND CURRENT ACBAS
	MOVE 1,UPP		;RESET MON STACK
	MOVEM 1,PIAC+P
;GET RH FLAGS ONLY. DON'T WANT TO STORE OP CODE INTO LEVTAB
	HLLZ 1,UPDL+1		;USER FLAGS AT MONITOR CALL
	MOVEM T1,PIFL		;PRESERVE USERS FLAGS
	MOVE T4,UPDL		;GET PC AT JSYS ENTRY
	PUSH FX,P1		;PSI STACK BEFORE ALL THIS PUSHING
	PUSH FX,1		;SAVE FLAGS AT JSYS ENTRY
	PUSH FX,T4		;SAVE PC AT JSYS ENTRY
	MOVEM FX,PSIPT		;SAVE CURRENT STACK POINTER
	TLZ 1,(UMODF)		;SO HE CAN TELL IT WAS MON INTERRUPT
	SETOM SLOWF
	JRST PSIS5		;FINISH INTERRUPT START

PIOVFW:	BUG(PSISTK)
;XMIT INTERRUPT TO SUPERIOR FORK

PSIT:	HRRZ 2,FORKN
	ADD 2,SUPERP		;GET SUPERIOR
	LDB 2,2
	HRRZ 2,SYSFK(2)		;SYSTEM FORK INDEX
	CALLRET PSIRQ		;REQUEST INTERRUPT

;THIS FORK WON'T TAKE INTERRUPT, DISMISS IT AND RECORD WHY

PSID1:	MOVEI 2,0(Q1)		;CHANNEL WITH NO LEVEL ASSIGNED
	JRST PSIN2

PSIN1:	MOVE 1,PSIBW		;INTERRUPTS OFF OR NO LEVCHN
PSIN3:	JFFO 1,.+1		;CALCULATE CHANNEL NUMBER
PSIN2:	MOVEM 2,FORCTC		;SAVE CHANNEL NUMBER FOR STATUS
	MOVE 1,BITS(2)		;JUST ONE CHANNEL AT A TIME
	ANDCAM 1,PSIBW		;RESET WAITING BIT
PSIN4:	MOVE 1,CAPENB
	TLNE 1,(1B17)		;SUPERIOR WANTS FROZEN STEAD HALT?
	JRST [	CALL FKTMI	;YES. GO INTERRUPT IT THEN
		MOVEI 3,FRZWT	;AND GET PROPER STATUS
		JRST PIRSK1]	;AND GO DO THE FREEZE
	CALL GETSFX		;GET SUPERIOR FORK INDEX
	MOVE Q2,1		;SAVE IT
	CALL UNPIRN		;LEAVE PI STATE, MOVE AC'S ETC.
	MOVE P,PI7P
	MOVE 1,Q2		;RECOVER SUPERIOR FORK INDEX
	HRRI 1,FORCTM
	JRST DISMSE		;THIS ONE IS BEING DISMISSED
;GET SUPERIOR FORK INDEX FOR HALT OR FORCED TERMINATION

GETSFX:	HRRZ 1,FORKN
	ADD 1,SUPERP		;MAKE POINTER TO SUPERIOR
	LDB 1,1
	HRLZ 1,SYSFK(1)		;PUT INDEX IN LH FOR DISMISS TEST WORD
	RET

FORCTM::JRST 0(4)		;SCHEDULER TEST FOR FORCED TERM FORK

;INTERRUPT SUPERIOR FORK ON TERMINATION

FKTMI:	HRRZ 1,FORKN
	SKIPN 1
	SKIPA 1,[^D35]		;TERMINATING TOP FORK, GIVE CH 35
	MOVEI 1,TRMINT		;19 IS FORK TERMINATED
	CALL PSIT		;TRANSMIT IT
	RET

;CONSTRUCT BYTE PTR TO CHANNEL NUMBER FOR TERM CODE
; 1/ TERMINAL CODE
;	CALL GETCHA
; RETURN +1: ALWAYS, 2/ BYTE PTR TO CHANNEL NUMBER

GETCHA::MOVEI 2,0(1)
	IDIVI 2,6
	ADDI 2,PSICHA
	HLL 2,CH6TAB(3)
	RET
;DEFERRED INTERRUPT LOGIC
;SET TRAPS TO RECHECK INTERRUPTS WHEN STATE CHANGES
;HERE WHEN PROCESS IS NOINT AND CAN'T TAKE AN INTERRUPT. SET UP INTDFF
;AND MJRSTF TO HANDLE THIS LATER

PSIDFR:	MOVE 1,MJRST1
	MOVEM 1,MJRSTF
	MOVE 1,INTDF1
	MOVEM 1,INTDFF
	CALL UNPIRN		;LEAVE BREAK STARTING STATE
	IORM 1,FKINT(FX)	;BUT LEAVE PENDING BIT
	CALL CHKBMP		;SEE IF NEED PI BUMPING AGAIN
	 NOP
	JRST PSIDF1		;RESUME

MJRST1:	JRST @[PSISV0]		;TRY FOR INTERRUPT NOW, IN SECTION 0
INTDF1:	XPCW PIFL		;CONTENTS OF INTDFF WHEN TRAP SET
				;PIPC+1 CONTAINS JRST PSISV1

;HERE WHEN PROCESS DID AN OKINT AND THERE WAS AN INTERRUPT PENDING FOR
;THE PROCESS. DON'T LET IT TAKE IF PROCESS IS STILL NOINT.

PSISV1:
	DATAO PAG,SETMON	;SET MON AC BLOCK CURRENT
	SOSL INTDF
	XJRSTF PIFL		;IF STILL NOINT, PROCEED
	JRST @[PSISV2]		;GO ON, IN SECTION 0 PLEASE

;HERE WHEN PROCESS WENT TO MRETN (TO RETURN FROM A JSYS OR UUO),
;AN INTERRUPT WAS PENDING, AND THE PROCESS HAS BEEN NOINT UNTIL NOW.
;IF JSYS WAS NESTED (I.E., PROCESS IS NOT RETURNING TO USER) AND
;PROCESS IS STILL NOINT, DON'T LET THE INTERRUPT TAKE.

PSISV0:
	DATAO PAG,SETMON	;SET MON AC BLOCK CURRENT
	DMOVEM 1,PIFL		;SAVE AC1
	DMOVE 1,FFL		;FFL NOW CONTAINS USER'SPC
	TXNN T1,UMODF		;A USER-MODE PC?
	JRST [	SKIPGE INTDF	;NO. NOW INTERRUPTABLE?
		JRST .+1	;YES. PROCEED
		DMOVE T1,PIFL	;NO. RECOVER AC CONTENTS
		XJRSTF FFL]	;AND RETURN FROM MUUO
	EXCH 1,PIFL
	EXCH 2,PIPC
PSISV2:	MOVEM P,PIAC+17		;SAVE USER'S AC17
	MOVEI P,PIAC		;AND AC'S 0-16
	BLT P,PIAC+16
	MOVE P,PIPDL		;RESTORE INTERRUPT STARTING STATE
	MOVE P2,TRAPFL
	MOVE P3,KIMUFL
	MOVE P4,TRAPPC		;SAVE VULNERABLE CELLS
	MOVE P5,KIMUPC
	MOVE P6,KIMUEF
	SETZM PIOLDS
PSISV3:	MOVE 2,FORKX
	MOVE FX,FKINT(2)
	JRST PSII		;ENTER MAIN SEQUENCE
;TEST FOR IMMEDIATE OR DEFERRED INTERRUPT
;SKIP => IMMEDIATE
;NOSKIP => DEFERRED
;CALLED WITH TEST USER PC IN AC1,AC2

PITEST::TLNE 1,(UMODF)		;USER MODE?
	JRST [	SKIPE NSKED	;ARE WE NOSKED?
		SKIPN PNSKDC	;YES. SHOULD WE BE BECAUSE OF RESOURCES?
		RETSKP		;NO. SAY CAN INTERRUPT THEN
		RET]		;YES. DEFER THE INT
	SKIPL SLOWF		;NO, SLOW CODE?
	SKIPL INTDF		;YES, INTERRUPTABLE
	RET			;NO, DEFER
	SKIPN CRSKED
	SKIPE NSKED		;IN CASE NOSKED W/O NOINT
	BUG(PSINSK)
	JRST RSKP		;IMMEDIATE

;TEST FOR PI BUMPING NEEDED
;	T2/ OUTSTANDING INTERRUPT BITS
;	FX/ FORK INDEX

CHKBMP:	MOVSI CX,200000
	TDNE CX,FKINT(FX)	;DEFERRING?
	RET			;YES, NO BUMP
	MOVSI CX,SUSFKR!PSILOB!PSIT1F!PSIT2F ;ANY INTERRUPT BITS ON?
	TDNN CX,FKINT(FX)	;?
	RET			;NO. NO BOOST THEN
	SETONE PIBMP		;YES. BUMP IT
	RETSKP			;AND INFORM CALLER OF SAME
;DEBREAK

.DEBRK::MCENT
	SKIPN PSIBIP		;ANY BREAKS IN PROGRESS?
	ITERR DBRKX1		;NO, ERROR
	DMOVE T3,[PCU+MSEC1
		MSEC1,,DEBRK1]	;GET NEW PC
	XJRSTF T3		;DO IT
DEBRK1:	MOVE 2,FORKX
	MOVSI 1,200000
	IORM 1,FKINT(2)		;SET INTERRUPT STARTING BIT
	SETZM PIOLDS
	MOVE 2,PSIBIP		;BREAKS NOW IN PROGRESS
	JFFO 2,.+1		;FIND HIGHEST ONE
	MOVE 1,PSLEVT		;COMPUTE ADDRESS OF RETURN PC
	ADDI 1,-1(3)
	UMOVE 1,@1
	JN PSXSIR,,[	XCTU [DMOVE Q1,@T1]
			JRST DEBRK2]
	HRRZS 1			;IF OLD STYLE, FORCE SECTION 0 ADDRESS
	UMOVE Q1,@1		;GET RETURN PC FROM USER MEMORY
	HRRZ Q2,Q1		;SAVE THE PC HERE
	HLLZS Q1		;SAVE ONLY FLAGS HERE
	HLL Q2,PSLEVT		;APPLY SECTION THAT WAS LOST WHEN STORED
DEBRK2:	MOVS 2,BITS(3)
	TDNE 2,PSIBIP		;WAS THIS MONITOR INTERRUPT?
	JRST DEBRK6		;YES, GO UNWIND

;HERE TO RETURN CONTROL TO THE USER PROGRAM.
;Q1/ FLAGS FROM LEVTAB
;Q2/ PC FROM LEVTAB
;SEND USER TO THIS LOCATION PRESERVING CERTAIN FLAGS IF THEY WERE
;ON AT ENTRY TO DEBRK

DEBRK3:	HLLZ T2,0(P)		;GET FLAGS FROM JSYS ENTRY
	MOVE P,PIPDL		;ESTABLISH PI STACK
	XOR Q1,T2		;KEEP PRIVILEGED BITS FROM THIS CALL
	TXZ Q1,UMODF+UIOF+PC%AFI+37B17
	XOR Q1,T2
	MOVEM Q1,PIFL		;SET THIS AS FLAGS FOR PROCEEDING
	MOVEM Q2,PIPC		;SET TO DEBREAK AT THAT ADDRESS
	SETOM SLOWF		;NORMALIZE FLAGS FOR RETURN TO USER
	SETOM INTDF
	MOVE 1,UPP
	MOVEM 1,PIAC+P
DEBRK4:	MOVE 1,BITS(3)
	ANDCAM 1,PSIBIP		;CLEAR BIP THIS LEVEL
	JRST PSISV3		;GO CHECK FOR OTHER INTERRUPTS AND RETURN
;HERE BECAUSE INTERRUPT OCCURRED OUT OF MONITOR CONTEXT. PSISM SAVED
;CONTEXT ON PSI STACK. IF PC IN LEVTAB HAS BEEN CHANGED, DON'T CONTINUE
;IN MONITOR. IF UMODF IS ON, USER MUST HAVE SET IT, BECAUSE PSISM
;CLEARED IT BEFORE PUTTING IT IN LEVTAB. PSI STACK CONTAINS FLAGS AND
;PC AT TOP OF UPDL WHEN INTERRUPT OCCURRED. THESE WERE PUT INTO LEVTAB
;BY PSISM.

;Q1/ FLAGS FROM USER'S LEVTAB
;Q2/ PC FROM USER'S LEVTAB

DEBRK6:	ANDCAM 2,PSIBIP		;CLEAR MON BREAK FLAG FOR THIS LEVEL
	MOVE FX,PSIPT
	POP FX,T4		;PC AT TOP OF UPDL WHEN INTERRUPT 
	POP FX,T2		;FLAGS AT TOP OF UPDL WHEN INTERRUPTED
	POP FX,PSIPT		;TOP OF THIS BLOCK OF PSI STORAGE
	TLOE Q1,(UMODF)		;IF IT WAS DIDDLED AT ALL,
	JRST DEBRK5
;NOT NEEDED IF DEBRK3 DOES HLLZ
;	HLLZS T2		;CLEAR RH FLAGS
	CAMN Q1,T2		;DO FLAGS MATCH?
	CAME Q2,T4		;YES. PC MATCH?

;HERE WHEN PC HAS BEEN CHANGED. DON'T PROCEED IN THE MONITOR ROUTINE
;THAT WAS INTERRUPTED. RELEASE ANY RESOURCES THAT THE PROCESS OWNS, AND
;GO SEND THE PROCESS TO THE ADDRESS IN LEVTAB.

DEBRK5:	JRST [	MOVE T1,FORKX	;NO. GET FORK HANDLE
		HLLZ T2,PSIBIP	;TELL THEM WHAT INTERRUPT LEVEL WE'RE AT
		TDZ T2,BITS(T3)	;POINT TO LEVEL WE'RE GOING TO
		PUSH P,T2	;SAVE FOR CALL TO GOKFRE
		CALL JSBSTF	;GO PROCESS DEALLOCATION STACK
		MOVE T1,FORKX	;GET FORK HANDLE
		POP P,T2	;GET CORRECT LEVEL
		CALL GOKFRE	;FREE GETOK ENTRIES
		JRST DEBRK3]	;DON'T RESUME MON ROUTINE

;HERE WHEN INTERRUPT OCCURRED FROM MONITOR CONTEXT, AND WE ARE
;RESUMING THE MONITOR ROUTINE. RESTORE CONTEXT AS SAVED BY PSISM
;ON SPECIAL PSI STACK

	MOVE P,PIPDL		;ESTABLISH PI PDL
	POP FX,ACBAS
	POP FX,4		;GET NUMBER OF WORDS FOR AC BLOCKS
	;..

;RESTORE AC STACKS

	;..
	JUMPLE 4,PDBK1		;JUMP IF NO AC STACK TO RESTORE
	SUB FX,4
	MOVEI Q1,UACB
	HRLI Q1,1(FX)
	ADDI 4,0(Q1)
	HRRZS T4
	BLT Q1,-1(4)		;RESTORE AC BLOCKS
	MOVEI Q1,UACB		;PUT USER ACS BACK ONTO STACK
	XBLTUM [BLT Q1,UACB+17]
	SUB FX,[20,,20]		;RESTORE PREVIOUS CONTEXT AC'S
	MOVSI 2,1(FX)
	XBLTMU [BLT 2,17]

;RESTORE AC'S FOR MONITOR

PDBK1:	SUB FX,[XWD 20,20]
	MOVEI 2,PIAC
	HRLI 2,1(FX)
	BLT 2,PIAC+17		;RESTORE MONITOR AC'S

;RESTORE UPDL STACK

	SUB FX,[XWD NUPDL,NUPDL]
	MOVEI 2,UPDL
	HRLI 2,1(FX)
	BLT 2,UPDL+NUPDL-1	;RESTORE STACK

;RESTORE SPECIAL CELLS

	MOVEI 2,NSAVC-1		;RESTORE VULNERABLE CELLS
	POP FX,@SAVCT(2)
	SOJGE 2,.-1
	POP FX,2		;GET PC AT TIME OF INTERRUPT
	MOVEM 2,PIPC		;SAVE PC (PROCESS WILL GO THERE)
	POP FX,2		;GET FLAGS AT TIME OF INTERRUPT
	MOVEM 2,PIFL		;SAVE FLAGS
	SETZM SLOWF
	SETOM INTDF		;BE OKINT
	JRST DEBRK4		;NOW DEBRK

;TABLE OF VULNERABLE CELLS

SAVCT:	MPP
	FFL
	FPC
	MONFL
	MONPC
	PIOLDS
	P2
	P3
	P4
	P5
	P6
NSAVC==.-SAVCT
; Jsys Traps support code (TRAPSI, JTLOCK, JTULCK, etc)..


;TRAP AND PSI ROUTINE EXECUTED WHEN A FORK EXECUTES A TRAPPED JSYS
;CALLED AS FIRST CODE EXECUTED BY THE TRAPPED JSYS (WITH IT'S CONTEXT
;BUT TOTALLY INVISIBLE TO IT)

;P1/	ADDRESS OF FORK'S JTB + P2
;P2/	OFFSET FOR THIS JSYS NUMBER 
;P3/	BIT MASK FOR THIS JSYS NUMBER

;P4/	MONITOR'S FORKN
;P5/	TRAP HANDLED FLAG
;P6/	OFFSET TO MONITOR'S PSB

TRAPSI::NOINT			;DON'T INTERRUPT THIS CODE
	SUBI P1,(P2)		;GET BACK ADDRESS OF JTB WITHOUT OFFSET
	SKIPA P5,[0]		;TRAP HANDLED IF NON-ZERO

TRPSI2:	MOVE P1,FKJTB(P4)	;pointer to monitor's JTB
	JUMPE P1,TRPSI6		;if he's not monitored were done
	LOAD P4,JTIMP,(P1)	;forkn of monitor's monitor
	ADDI P1,(P2)		;add in offset to bit table
	TDNN P3,JTBIM(P1)	;HANDLED BY THIS MONTIOR?
	JRST TRPSI2		;no, keep looking up the chain of monitors

	SETO P5,		;YES, INDICATE TRAP HANDLED
	MOVEI T1,0(P4)
	CALL SETLF1		;MAP PSB OF THE MONITOR
	MOVE P6,T1		;SAVE POINTER TO MONITOR'S PSB
TRPSI4:	LOAD T2,JTMCN,(T1)
	CAIN T2,77		;IS CHANNEL SPECIFIED?
	JRST TRPSI2		;NO, DON'T PSI, SEARCH FOR ANOTHER MONITOR
	CALL JTLOCK		;YES, SYNCH WITH OTHER TRAPPING FORKS
	JRST TRPSI4		;FORK SUSPENDED AND RESUMED
	 			;WHILE QUEUED, RETRY LOCKING
	JSP CX,FRZPSI		;FREEZE SELF AND PSI MONITOR


;RESUMED HERE AFTER TRAP HANDLED IF MONITOR DOES NOT CHANGE PC
;WHEN CONTROL RETURNS TO TRPSI5 ACS P1-5 MUST BE THE SAME AS TRPSI3

TRPSI5::JRST TRPSI2		;LOOK FOR MORE MONITORS (OF MONITORS)

;RETURN TO THE NORMAL JSYS CODE

TRPSI6:	SKIPL P5		;HAS TRAP BEEN HANDLED AT ALL?
	 BUG(TRPSIE)
	LDB T1,[POINT 9,KIMUU1,26] ; Pick up opcode of trapped guy
	CAIE T1,<JSYS>B62	; Was a JSYS?
	 JRST TRPSI7		; No, a UUO
	LOAD T1,JTJNO
	MOVE CX,JSTAB(T1)	;GET NORMAL DISPATCH
	HLLZM CX,FFL		; Restore normal flags
	TXZ CX,EXFLBT
	MOVEM CX,FPC		; And dispatch
	XCTU [DMOVE T1,1]	;RESTORE STANDARD 4 ARGS
	XCTU [DMOVE T3,3]
	SETZM INTDF		;RESTORE STATE TO ENTRY AT TRAPSI
	OKINT			;TURN PSIS BACK ON
	XCT MJRSTF		;DO NORMAL DISP FOR THIS JSYS

TRPSI7:	SETOM SLOWF		; Untangle ourselves
	MOVE P,MPP		; in a state like this
	POP P,FFL		; Reset flags
	POP P,FPC		; And caller
	MOVE P,UPP		; Reset the stack...
	SETZM INTDF
	OKINT
	JRST U10501		; Return to handle the UUO
;FREEZE AND PSI ROUTINE - FORK INITIATES JSYS TRAP PSI OF
;MONITOR AND THEN FREEZES ITSELF
;P4/ JOB INDEX OF FORK TO PSI
;P6/ OFFSET TO FORKS PSB


FRZPSI:	MOVS T4,KIMUU1		; Pick LH of instruction
	HRR T4,KIMUU1+1		; And then RH
	MOVEM T4,JTTRW(P6)	; Set last trapped instruction
	HRRZ T4,FORKN
	STOR T4,JTFRK,(P6)	; Trapped fork index
	STOR P4,JTMNI		;SAVE FORK WE TRAPPED TO FOR UTFRK

	ENTSKD			;SAVE ACS ETC.
	TXZ CX,EXFLBT
	MOVEM CX,PPC		; Save return for DISMSE
	MOVE CX,ENSKR		;GET THE RIGHT FLAGS
	HLLZM CX,PFL		;FOR RESUME AFTER DISMSE

	LOAD T2,JTMNI
	HRRZ T2,SYSFK(T2)	;GET FORKX OF MONITOR FORK
	MOVSI T1,400000+PSIJTR
	IORM T1,FKINT(T2)	;PSI MONITORING FORK
	CALL PSIR4		;MAKE SCHEDULER SEE IT

	MOVSI T1,200000+JTFRZB	;DO "JSYS TRAP" FREEZE OF SELF
	IORM T1,FKINT(FX)	;FX=FORKX SET BY ENSKED
	SETZM PIOLDS		;"OLD STATE" = RUNNING
	MOVEI T1,FRZWT
	JRST DISMSE		;DISMS
;JSYS TRAP LOCK AND UNLOCK ROUTINES
;WHEN A FORK TRIES JTLOCK AND SOME OTHER FORK HAS THE
;LOCK, THE FORK ADDS ITSELF TO A QUEUE (FKJTQ) AND BECOMES BLOCKED.
;WHEN THE LOCK IS CLEARED (BY A MONITORING FORK) THE QUEUE IS
;SCANNED FOR THE FIRST FORK (IF ANY) WAITING ON THE LOCK.  THAT
;FORK IS REMOVED FROM THE QUEUE AND ALLOWED TO RUN.

;LOCK ROUTINE
;ON ENTRY TO JTLOCK:
;P4/ JOB FORK INDEX (OF FORK TO FIELD TRAP)
;P6/ PTR TO ITS PSB
;RET + 1 IF SUSPENDED AND RESUMED WHILE QUEUED
;RET + 2 WITH LOCK SET

JTLOCK:	NOSKED
	AOSE JTLCK(P6)		;TRY TO SEIZE THE LOCK
	JRST JTLOC2		;SOMEONE ELSE HAS IT
	OKSKED 			;GOT IT
JTLOC1:	AOS 0(P)		;RET + 2
 	RET

JTLOC2:	JSP CX,JTENQ		;PUT SELF ON JSYS TRAP QUEUE
	JRST JTLOC1		;RETURNS HERE WITH LOCK SEIZED

;IF FORK IS RESUMED AT JTRLCK, IT RETURNS + 1 TO TRAPSI ROUTINE
;FORCING ANOTHER CALL TO JTLOCK AFTER A CHECK TO SEE IF THE TRAP IS
;STILL TO GO TO THE SAME FORK.


JTRLCK:	RET

				;ROUTINE TO PLACE FORK ON QUEUE
JTENQ:	HRL T1,SYSFK(P4)	;1=FORK WAITING ON
	HLLZM CX,PFL
	TXZ CX,EXFLBT
	MOVEM CX,PPC		;SAVE RETURN PC NOW
	ENTSKD			;ENTER SCHEDULER
	SOSE NSKED		;MATCHED NOSKED IN JTLOCK
	BUG(JTENQE)
	MOVEI T2,FKJTQ(FX)	;FX=FORKX, SET BY ENSKED
	HRRM T2,@JTLSTL		;ADD THIS FORK TO END OF QUEUE
	EXCH T2,JTLSTL		;SET NEW END OF QUEUE PTR
	MOVSM T2,FKJTQ(FX)	;SET BACK PTR TO OLD QUEUE END
	HRRI T1,JTQWT
	JRST DISMSE		;DISMS


;JSYS TRAP QUEUE WAIT TEST

JTQWT:	MOVE T1,FKINT(FX)	;DID A SUSPEND REQUEST OCCUR
	TLNN T1,SUSFKR		;BEFORE BLOCKING?
	JRST 0(4)		;NO.
	MOVSI T1,400000+PSIWTF	;YES, REINITIATE SUSPEND
	IORM T1,FKINT(FX)	;REQUEST PSI
	MOVSI T1,200000
	ANDCAM T1,FKINT(FX)	;ALLOW PSI'S
	PUSH P,3
	CALL PSBUMP		;NO, GIVE FORK SOME PRIORITY
	POP P,3
	JRST 1(4)


;UNLOCK ROUTINE
;USES BUT DOES NOT SAVE ACS 1,2,3,4

JTULCK::HRRZ T2,FORKX
       NOSKED
	MOVE T1,JTLST		;SCAN QUEUE LOOKING FOR FORK
	 			;WAITING ON EXECUIING FORK
JTULC1:	JUMPE T1,JTULC3		;NONE FOUND
	MOVEI T4,0(T1)
	SUBI T4,FKJTQ		;4=FORK INDEX OF QUEUED FORK
	HLRZ T3,FKSTAT(T4)
	CAMN T3,T2		;THIS FORK WAITING ON EX FORK?
	JRST JTULC2		;YES, REMOVE IT FROM QUEUE
	HRRZ T1,0(T1)		;NO, TRY NEXT FORK
	JRST JTULC1

JTULC2:	CALL JTDEQ		;REMOVE FORK FROM QUEUE
	PUSH P,FX		;UNBLOCK FORK
	MOVE FX,T4
	CALL UNBLK1
	POP P,FX
	CAIA
JTULC3:	SETOM JTLCK		;NO FORKS ON QUEUE, CLEAR LOCK
       OKSKED
	RET

;REMOVE FORK WHOSE FKJTQ ENTRY IS PT'D TO BY 1 FROM JSYS TRAP QUEUE
;USES BUT DOES NOT SAVE ACS 2,3

JTDEQ:	NOSKED
	HRRZ T3,(T1)		;3=PTR TO NEXT ITEM ON QUEUE
	HLRZ T2,(T1)		;2=PTR TO PREV ITEM
	HRRM T3,(T2)
	JUMPE T3,JTDEQ1		;REMOVING LAST ITEM?
	HRLM T2,(T3)		;NO
	CAIA
JTDEQ1:	MOVEM T2,JTLSTL
       OKSKED
	RET
ILUUO::	MCENTR
	ITERR ILINS1		;ILLEGAL UUO

;ALL UNDEFINED JSYS'S

UJSYS0::MCENT
UJSYS::	ITERR ILINS2		;UNDEFINED JSYS

UU1050::SKIPE P1,@JTBLK		; JSYS traps?
	 JRST [ SETZ P2,	; Word 0
		MOVSI P3,(1B0)	; Check for JSYS 0 (UUO trapping)
		TDNN P3,JTBAL(P1)
		 JRST .+1	; Not trapping UUOs
		MOVE CX,[PCU+MSEC1B+TRAPSI] ; We are, go JSYS trap route
		JRST MENTU1]	; Join JSYS code
U10501::MOVE 1,KIMUU1+1		;LOGICAL 40
	HRL 1,KIMUU1
	SKIPG PATADR		;GOT PAT NOW?
	JRST GETPAT		;NO, GO GET IT
	XCTU PATU40		;CONTAINS MOVEM 1,MONUUO
	MOVE 1,FPC
	HLL 1,FFL		;SET FLAGS
	XCTU PATUPC		;CONTAINS MOVEM 1,MONUPC
	MOVE 1,PATADR		;ENTRY VECTOR
	HRRZM 1,FPC
	JRST GOUSR		;TRANSFER TO USER

;HERE ON DMS JSYS

DMSENT::MOVE 1,KIMUEF		;LOGICAL 40
	HRL 1,KIMUFL		;SET FLAGS
	SKIPG DMSADR		;GOT DMS NOW?
	JRST GETDMS		;NO, GO GET IT
	XCTU DMSU40		;CONTAINS MOVEM 1,MONUUO
	MOVE 1,FPC
	HLL 1,FFL
	XCTU DMSUPC		;CONTAINS MOVEM 1,MONUPC
	MOVE 1,DMSADR		;ENTRY VECTOR
	HRRZM 1,FPC
	JRST GOUSR		;TRANSFER TO USER
;SLOW MONITOR CALL SETUP ROUTINE
; INVOKED VIA  JSP CX,MENT0

MENTM::	LOAD CX,EXPCBT,JSTAB(CX)	;GET ROUTINE ADDRESS WITHOUT PCU FLAG
MENT0::	SETOM SLOWF
	EXCH T1,MONFL		;SAVE T1
	EXCH T2,MONPC		;SAVE T2
	XSFM T1			;GET PCS INTO T1
	HLL T1,CX		;GET FLAGS
	MOVE T2,CX
	TXZ T2,EXFLBT		;MASK OFF FLAGS
	EXCH T2,KIMUPC
	MOVE CX,T1		;RESTORE CX TO FLAGS ONLY
	EXCH T1,MONFL		;SAVE FLAGS
	EXCH T2,MONPC		;AND FLAGS AND RESTORE T1,T2
	EXCH CX,FFL		;GET RETURN PC
	MOVEM CX,MONFL
	TLNE CX,(UMODF)		;FROM USER?
	JRST MENT1		;YES
   IFN DEBUG,<
	AOSGE INTDF		;CHECK STATE OF INTDF
	BUG(IDFOD1)
	SOS INTDF
	PUSH P,INTDF		;SAVE VARIABLES
	PUSH P,MPP
	PUSH P,MONPC
	PUSH P,CX		;SAVE RETURN
	MOVEM P,MPP		;SAVE CURRENT STACK POINTER
	AOS CX,ACBAS		;SETUP NEXT AC STACK BLOCK
	CAIL CX,<EUACB>B39	;USED ALL BLOCKS?
	BUG(NOACB)
	LSH CX,4		;MAKE INTO ADDRESS
	HRRZ P,CX		;SAVE COPY
	XBLTUM [BLT CX,17(P)]	;PUSH PREV AC BLOCK ONTO STACK
	SETZ CX,
	XBLTMU [BLT CX,CX-1]	;MOVE CURR TO PREV
	MOVE P,MPP		;RESTORE P
	SETZM SLOWF
	XCT MJRSTF		;RESUME MONITOR ROUTINE

MENT1:	EXCH CX,FFL	;YES
	TLO CX,(PCU)	;MAKE SURE PCU IS ON LOCALLY
	EXCH CX,FFL
	XSFM T1			;GET CURRENT FLAGS
	TXO T1,PCU		;MAKE USER PREVIOUS CONTEXT
	MOVE T2,[MSEC1,,MENT11]	;WHERE TO PROCEED
	XJRSTF T1		;DO IT
MENT11:	MOVE P,UPP		;TOP OF MON STACK
	PUSH P,MONPC		;SAVE RETURN FOR PSI
	PUSH P,CX
	PUSH P,MONPC
	PUSH P,CX		;SAVE RETURN FOR OTHER USES
	JRST MENT2		;JOIN NORMAL USER ENTRY
;ENTRY TO TOP-LEVEL JSYS (I.E. FROM USER)

MENTU::	SKIPE P1,@JTBLK		; Any JSYSes monitored for this fork?
	 JRST [	JUMPE CX,[ MCENTR	; Special case JSYS 0 (UUO trapping)
			JRST UJSYS]
		MOVE CX,JSTAB(CX)	;GET ROUTINE ADDRESS AND PCU FLAG
		LOAD P2,JTJNO	; Yes, get JSYS number
		IDIVI P2,^D36	; Get word offset into bit table
		MOVE P3,BITS(P3) ; And bit mask
		ADDI P1,0(P2)	; Form address within bit table
		TDNE P3,JTBAL(P1) ; Trapped?
		 HRRI CX,TRAPSI	; Yes, go trapped route
		JRST MENTU1]
	MOVE CX,JSTAB(CX)	;GET ROUTINE ADDRESS AND PCU FLAG
MENTU1:	MOVE P,UPP		;SET UP STACK
	PUSH P,KIMUPC
	PUSH P,KIMUFL		;RETURN FOR PSI
	PUSH P,KIMUPC
	PUSH P,KIMUFL
	XSFM FFL		;STORE PCS INTO FFL
	HLLM CX,FFL		;SET FLAGS
	TXZ CX,EXFLBT		;CLEAR FLAGS
	MOVEM CX,FPC
MENT2:	MOVEM P,MPP		;SET STACK FENCE
	XCTU [DMOVE T1,T1]	;GET STANDARD 4 ARGS
	XCTU [DMOVE T3,T3]
	MOVEI CX,<UACB>B39-1	;INIT AC STACK
	MOVEM CX,ACBAS
	SKIPE NSKED		;IS THIS PROCESS NOSKED?
	CALL [	SKIPN PNSKDC	;YES, SHOULD IT BE?
		RET		;NO. ALLOW INTS THEN
		RETSKP]		;YES
	SETOM INTDF		;INIT INTDF
	SETZM CRSKED		;INIT CRITICAL REGION FLAG
	SETZM SLOWF		;INIT SLOWF
	XCT MJRSTF		;RESUME MONITOR ROUTINE
IMCFLG==1B14			;INTERNAL MONITOR CALL FLAG (X FIELD OF PC)

;RETURN FROM SLOW MONITOR CALL

MRETNE::UMOVEM 1,1		;RETURN ERROR CODE IN AC1
EMRET0::MOVEM 1,LSTERR		;SAVE ERROR CODE IN STANDARD PLACE
EMRET1::MOVE P,MPP		;RESTORE STACK PTR
	DMOVE T1,-1(P)		;GET RETURN PC
	EXCH T1,T2		;IN PROPER ORDER
	CALL ITRSIM		;ERJMP/ERCAL PRESENT?
	 JRST MRETN		;NO, NORMAL RETURN
	MOVEM T3,-1(P)		;YES, SETUP RETURN
	JRST MRETN

;SKMRTN IS STANDARD SKIP RETURN FROM JSYS

SKMRTN::MOVE P,MPP		;SET UP THE STACK POINTER
	AOS -1(P)		;THEN INCREMENT THE RETURN ADDRESS
MRETN::	SETOM SLOWF		;RESET FLAG
   IFN DEBUG,<
	AOSGE INTDF		;CHECK STATE OF INTDF
	BUG(IDFOD2)>
	MOVE P,MPP		;GO BACK TO LAST STACK FENCE
	POP P,CX		;RETURN PC
	TXZ CX,QUOTAB		;FLUSH "QUOTA" BIT
	TLNN CX,(UMODF)		;RETURN TO USER?
	JRST MRETN1		;NO
	MOVEM CX,FFL		;SET UP FLAGS
	POP P,FPC		;RESTORE PC

;ALL TRANSFERS TO USER MODE COME HERE.  THE SCHEDULER RECOGNIZES
;THE PC AT GOUSR+1 AS A SINGULARITY (USER AC BLOCK BUT MONITOR PC)
;AND CORRECTS FOR IT.

GOUSR::
	DATAO PAG,SETUSR	;SETUP USER AC BLOCK AS CURRENT
	XCT MJRSTF

MRETN1:	POP P,FPC		;RESTORE PC
	MOVEM CX,FFL		;STORE FLAGS
	TXZE CX,IMCFLG		;INTERNAL CALL FLAG?
	JRST IMCLL1		;YES, DIFFERENT RETURN SEQUENCE
	SETZ CX,		;MOVE PREV AC TO CURRENT
	XBLTUM [BLT CX,CX-1]
	HRLZ CX,ACBAS		;POP AC STACK
	LSH CX,4
	XBLTMU [BLT CX,17]
	SOS CX,ACBAS		;DECREMENT ACBAS PTR
	CAIGE CX,<UACB>B39-1
	BUG(OPOPAC)
MRETN2:	POP P,MPP		;RESTORE VARIABLES
	POP P,INTDF
	SETZM SLOWF
	XCT MJRSTF
;CKMMOD - CHECK FOR MONITOR MODE

	CALL CKMMOD

;RETURNS +1: CALLER CAME FROM USER CONTEXT
;	 +2: CALLER CAME FROM MONITOR CONTEXT

;CLOBBERS NO AC'S

;THIS ROUTINE IS CALLED BY A JSYS (TTMSG, FOR EXAMPLE), WHEN IT
;REQUIRES THE CALLER TO BE PRIVILEGED EXCEPT WHEN THE CALLER IS IN
;MONITOR CONTEXT.  THIS ALLOWS A NON-PRIVILEGED JSYS LIKE DTACH
;TO DO A PRIVILEGED FUNCTION LIKE TTMSG

CKMMOD::ACVAR <W1>		;GET A WORK AC
	MOVE W1,MPP		;GET STACK POINTER ON ENTRY TO THE JSYS
	MOVE W1,0(W1)		;GET THE FLAGS WORD FROM THE STACK
	TLNE W1,(UMODF)		;IS IT USER MODE?
	RET			;YES. TAKE NONSKIP RETURN
	RETSKP			;NO. TAKE SKIP RETURN
;INTERNAL MONITOR CALL LOGIC
;	JSP CX,IMCLL0
;	 ADDRESS
;THIS EFFECTS A CALL TO 'ADDRESS' (PRESUMABLY A JSYS ENTRY POINT)
;JUST AS THOUGH A JSYS HAD BEEN DONE BUT WITHOUT CHANGING THE
;PREVIOUS CONTEXT.  THUS PREVIOUS CONTEXT REFERENCES IN THE CALLEE
;WILL NOT REFERENCE THE CURRENT CONTEXT OF THE CALLER BUT RATHER
;THE PREVIOUS CONTEXT OF THE CALLER.  USED WHERE ARGUMENTS
;(E.G. BLOCK POINTERS, STRINGS) MUST BE PASSED TO LOWER LEVEL
;ROUTINES.  NOTE THAT ALL ACS ARE AUTOMATICALLY SAVED AND RESTORED,
;THE THE AC CONTEXT IS NOT CHANGED, SO ARGUMENTS MUST GENERALLY
;BE SETUP IN THE PREVIOUS CONTEXT ACS.

IMCLL0::SETOM SLOWF		;HERE VIA JSP CX,IMCLL0, INHIBIT PSI
	XSFM FFL		;SAVE FLAGS
	TXZ CX,EXFLBT		;MASK OFF FLAGS FROM JSP
	MOVEM CX,FPC		;SAVE RETURN
	ADD P,[CX,,CX]		;ALLOCATE STACK SPACE FOR ACS
	MOVEI CX,-CX+1(P)	;MOVE ACS TO STACK
	BLT CX,0(P)
	PUSH P,INTDF		;ESTABLISH USUAL STACK CONTEXT
	PUSH P,MPP
	AOS FPC			;BUMP RETURN PAST CALL ADDRESS WORD
	PUSH P,FPC
	MOVE CX,FFL		;PICK UP FLAGS
	TXO CX,IMCFLG		;FLAG INTERNAL CALL
	PUSH P,CX		;STACK RETURN
	MOVE CX,FPC		;RESTORE PC
	MOVE CX,-1(CX)		;GET CALL ADDRESS
	TXC CX,<JSYS>		;SEE IF A JSYS
	TXCN CX,<JSYS>		;IS IT?
	JRST [	TLNE CX,<-<JSYS+1>>B53 ;MAYBE. STILL?
		JRST .+1	;NO
		HRRZS CX	;YES. GET INDEX
		LDB CX,[POINT ^D23,JSTAB(CX),35] ;GET DISPATCH ADDRESS
		JRST .+1]	;AND PROCEED
	MOVEM CX,FPC		;SET UP TRANSFER TO PROPER SECTION,,OFFSET
	MOVEM P,MPP		;SAVE STACK FENCE
	XCTU [DMOVE T1,T1]	;GET STANDARD 4 ARGS
	XCTU [DMOVE T3,T3]
	SETZM SLOWF		;ENABLE PSI
	XCT MJRSTF		;JUMP TO CALL ADDRESS

;HERE WHEN INTERNAL CALL FLAG DETECTED IN RETURN PC

IMCLL1:	POP P,MPP		;RESTORE CONTEXT VARIABLES
	POP P,INTDF
	MOVSI CX,-CX+1(P)	;RESTORE ACS
	BLT CX,CX-1
	SUB P,[CX,,CX]		;DEALLOCATE STACK SPACE
	XCTU [DMOVE T1,T1]	;SETUP RETURN VALUES
	XCTU [DMOVE T3,T3]
	SETZM SLOWF		;ENABLE PSI
	XCT MJRSTF		;RETURN
;CHECK FOR PRESENCE OF SPECIAL INSTRUCTIONS FOLLOWING JSYS WHICH
;FAILED.

;COMMON ROUTINE TO CHECK FOR ERJMP/ERCAL AND DO
;CORRECT SIMULATION.
; T1,T2/ FLAGS AND PC
;
; RETURNS +1 IF NONE FOUND OR PDL OV ON ERCAL
; RETURNS +2 WITH RETURN ADDRS IN C(T3)
;NOTE: ALL REFERENCES TO PREVIOUS CONTEXT SHOULD BE PROTECTED WITH
;ERJMPS IN CASE USER HAS BAD PROTECTIONS, NONX SECTIONS, ETC.

ITRSIM::TXNN T1,UMODF		;CALL FROM MONITOR?
	SKIPA T3,0(T2)		;YES, FETCH FROM CURRENT CONTEXT
	UMOVE T3,0(T2)		;NO, FETCH FROM PREVIOUS CONTEXT
	 ERJMP R		;RETURN IF REF FAILS
	LDB T4,[POINT 13,T3,12]	;GET OPCODE AND AC
	CAIN T4,<ERJMP>B58	;AN ERJMP?
	JRST ITRSX		;YES
	CAIE T4,<ERCAL>B58	;AN ERCAL?
	RET			;NO
	HRRI T2,1(T2)		;YES, GET INCREMENTED PC
	UMOVE T4,P		;LOOK AT STACK PTR
	TXNE T2,VSECNO		;PC IN SECTION 0?
	JUMPGE T4,[MOVEI T4,1	;NO, DIFFERENT RULES
		XCTU [ADDB T4,P] ;BUMP PTR, NO OV CHECK
		JRST ITRSY]	;GO FINISH UP JUMP
	MOVE T4,[1,,1]
	XCTU [ADDB T4,P]	;BUMP PTR
	TLNN T4,377777		;PDL OVERFLOW?
	CALL [SAVET		;YES
	      MOVE T1,BITS+.ICPOV ;CHANNEL 9 INTERRUPT  
	      CALL IICSLF
	      RET]
	TXNN T2,VSECNO		;IF NOT EXT ADR,
	HLL T2,T1		;INCLUDE FLAGS WITH PC
ITRSY:	UMOVEM T2,0(T4)		;STORE PC FROM JSYS
	 ERJMP R		;GIVE UP IF PROBLEMS
ITRSX:	TLZ T3,777740		;GET RID OF INSTRUCTION PART
	TXO T3,<XMOVEI T3,0>	;FORM INST FETCH
	XCTUU T3		;GET PREV CONTEXT ADDRESS
	 ERJMP R		;GIVE UP IF E CALC FAILS
	RETSKP			;GIVE GOOD RETURN

;SET PREVIOUS CONTEXT VARIABLES
;CALLED WHEN CHANGING CONTEXT IN SOME UNUSUAL WAY, E.G. POPPING UPDL
; T1/ FLAGS
; T2/ PC
;	CALL SETPCV
;  RETURN +1 ALWAYS, ARGS PRESERVED

SETPCV:	XSFM T3			;GET CURRENT FLAGS
	TXZ T3,PCU		;CLEAR VARIABLES
	TXNE T1,UMODF		;PREVIOUS CONTEXT WAS USER?
	TXO T3,PCU		;YES
	LOAD T4,VSECNO,T2	;GET PREVIOUS PC SECTION
	STOR T4,EXPCS,T3
	POP P,T4		;GET LOCAL RETURN
	ANDX T4,EXPCBT		;BUT ONLY THE GOOD BITS
	XJRSTF T3		;RETURN AND SET PREV CONTEXT VARIABLES
;ROUTINE TO CHECK IF THERE IS AN ERJMP OR AN ERCAL AFTER A JSYS
;ACCEPTS IN T1/ RETURN FLAGS
;		T2/ RETURN PC
;	CALL CHKERT
;RETURNS +1:	NO ERJMP OR ERCAL
;	 +2:	THERE IS AN ERJMP OR AN ERCAL

CHKERT::TXNE T1,IMCFLG		;INTERNAL CALL?
	SKIPA T1,0(T2)		;YES, FETCH FROM CURRENT CONTEXT
	UMOVE T1,0(T2)		;NO, FETCH FROM PREVIOUS CONTEXT
	LDB T1,[POINT 13,T1,12]	;GET OP AND AC FIELDS
	CAIE T1,<ERJMP>B58	;IS IT AN ERJMP?
	CAIN T1,<ERCAL>B58	; OR AN ERCAL?
	RETSKP			;YES
	RET			;NO

UPP::	IOWD NUPDL,UPDL		;MONITOR BASE STACK POINTER
UPP1:	XWD -NUPDL+3,UPDL-1+3	;STK PTR AT ENTRY TO TOP LEVEL JSYS
;JSYS TO DO SCHEDULER CONTROLS

;JSYS TO READ/SET SCHEDULER PARAMETERS.

	SWAPCD			;START UP IS SWAPPABLE
.SKED::	MCENT			;GET INTO MONITOR
	SKIPLE T1		;VALIDATE FUNCTION
	CAILE T1,MAXFUN		;VALID FUNCTION
	ITERR (ARGX02)		;INVALID
	SKIPL FNCTBL-1(T1)	;PRIVILEGED FUNCTION?
	JRST SKED1		;NO
	MOVX T4,SC%WHL!SC%OPR	;MUST BE PRIVILEGED
	TDNN T4,CAPENB		;IS IT?
	ITERR (CAPX1)		;NO. BOMB THEN
SKED1:	HRRZ T1,FNCTBL-1(T1)	;GET DISPATCH
	JRST 0(T1)		;DO FUNCTION

FNCTBL:	SKDRNB			;READ KNOB
	IFIW!SKDSNB		;SET KNOB
	SKDRCS			;READ CLASS SHARES
	IFIW!SKDSCS		;SET CLASS SHARE
	IFIW!SKDSCL		;START CLASS SCHEDULING
	SKDSJC			;SET JOB CLASS
	SKDRTJ			;READ THIS JOB'S UTILIZATION AND SHARE
	SKDRCB			;READ CLASS SETTING FOR BATCH JOBS
	IFIW!SKDSCB		;SET BATCH CLASS
	IFIW!SKDRDQ		;RUN BATCH JOBS ON DREGS QUEUE
	IFIW![ITERR (ARGX02)]	;UNUSED SLOT
	SKDRCP			;READ CLASS PARAMETERS
MAXFUN==.-FNCTBL
;ACTION ROUTINES FOR EACH FUNCTION

;READ MICRO-CONTROL KNOB

SKDRNB:	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	CAIG T3,1		;ROOM TO STORE VALUE?
	ITERR (ARGX04)		;NO. ERROR THEN
	LOAD T1,CLSKV		;GET KNOB VALUE
	UMOVEM T1,.SAKNB(T2)		;RETURN TO USER
	MRETNG			;AND DONE

;SET MICRO-CONTROL VALUE

SKDSNB:	UMOVE T3,.SACNT(T2)		;GET COUNT
	CAIG T3,1		;HAVE VALUE TO SET?
	ITERR (ARGX04)		;NO.
	UMOVE T2,.SAKNB(T2)		;YES. GET IT
	SKIPLE T2
	CAILE T2,NSKFLV		;VALID SETTING?
	ITERR (ARGX30)		;INVALID KNOB
	STOR T2,CLSKV		;STORE KNOB VALUE
	MOVE T2,SKFLGV-1(T2)	;GET NEW FLAGS
	MOVEM T2,SCHFLG		;NEW FLAGS
	MRETNG			;AND DONE

;READ CLASS SHARE

SKDRCS:	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	CAIG T3,2		;ROOM FOR DATA?
	ITERR (ARGX04)		;NO
	SUBI T3,2		;REMOVE HEADER
	MOVNS T3
	HRLZS T3		;GET VALUE TO LH
	HRRI T3,2(T2)		;START OF DATA
	UMOVE P1,1(T2)		;GET CLASS I.D.
	SKIPL P1		;GOOD CLASS?
	CAIL P1,MAXCLS		;STILL?
	ITERR (ARGX25)		;NO
	MOVE T4,CLSSHR(P1)	;GET CLASS' SHARE
	UMOVEM T4,0(T3)		;RETURN TO CALLER
	AOBJP T3,SKDONE		;WANT MORE?
	MOVE T4,CLSUTL(P1)	;YES. GET UTILIZATION
	UMOVEM T4,0(T3)		;RETURN TO CALLER
	AOBJP T3,SKDONE		;WANT MORE?
	IMULI P1,3		;LOAD AVERAGES *3
	MOVE T4,CLSRJA(P1)	;GET FIRST AVERAGE
	UMOVEM T4,0(T3)		;STORE IT
	AOBJP T3,SKDONE		;WANT MORE?
	MOVE T4,CLSRJA+1(P1)	;GET SECOND AVERAGE
	UMOVEM T4,0(T3)		;STORE IT
	AOBJP T3,SKDONE		;LAST ONE TOO?
	MOVE T4,CLSRJA+2(P1)	;GET THIRD AVERAGE
	UMOVEM T4,0(T3)		;STORE THIRD AVERAGE
	JRST SKDON0		;AND DONE

;READ THIS JOB'S UTILIZATION AND SHARE

SKDRTJ:	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	CAIG T3,2		;ROOM FOR ANY DATA?
	ITERR (ARGX04)		;NO
	SUBI T3,2		;YES. GET NUMBER OF WORDS WANTED
	MOVNS T3		;MAKE IT NEG
	HRLZS T3		;GET IT IN THE LH
	HRRI T3,.SAJCL(T2)		;FORM AOBJP POINTER
	UMOVE T1,1(T2)		;GET JOB NUMBER
	CAMN T1,[-1]		;THIS JOB?
	MOVE T1,JOBNO		;YES. GET THE JOB NUMBER THEN
	SKIPL T1		;VALID JOB NUMBER?
	CAIL T1,NJOBS		;STILL?
	ITERR (ARGX08)		;NO
	SKIPGE JOBRT(T1)	;LOGGED IN?
	ITERR (ARGX15)		;NO
	HRRZ P1,JOBCLS(T1)	;GET CLASS OF JOB
	UMOVEM P1,0(T3)		;RETURN CLASS NUMBER
	AOBJP T3,SKDONE		;WANT MORE?
	MOVE T4,CLSSHI(P1)	;YES. GET JOB'S SHARE
	UMOVEM T4,0(T3)		;AND RETURN TO USER
	AOBJP T3,SKDONE		;WANT MORE?
	MOVE T4,JOBUTL(T1)	;YES. GET UTILIZATION
	UMOVEM T4,0(T3)		;AND RETURN IT TO THE USER
	AOBJP T3,SKDONE		;WANT MORE?
	MOVE T4,CLSSHR(P1)	;YES. GET CLASS SHARE
	UMOVEM T4,0(T3)		;AND RETURN TO USER
	AOBJP T3,SKDONE		;WANT MORE?
	MOVE T4,CLSUTL(P1)	;YES. GET CLASS UTILIZATION
	UMOVEM T4,0(T3)		;AND RETURN TO USER
SKDON0:	ADD T3,BHC+1		;ACCOUNT FOR LAST ONE
SKDONE:	HLRES T3		;GET REMAINING COUNT
	XCTU [HRRZ T4,0(T2)]	;GET ORIGINAL COUNT
	ADD T3,T4		;COMPUTE WORDS PROCESSED
	XCTU [HRLM T3,0(T2)]	;AND RETURN THIS AS WELL
	MRETNG			;AND DONE

;SET CLASS SHARE FOR CLASS N

	RESCD			;MUST BE RESIDENT TO AVOID PAGE FAULTS
SKDSCS:	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	CAIG T3,.SACLS+1	;ENOUGH ARGS GIVEN?
	ITERR (ARGX04)
	SETOM P2		;ASSUME WA SETTING IN ON
	CAILE T3,.SAWA		;SPECIFIED SWITCH SETTING?
	UMOVE P2,.SAWA(T2)	;YES. GET IT
	SKIPE P2		;ON?
	SETOM P2		;YES. SWITCH IT THEN
	XCTU [DMOVE T1,.SACLS(T2)]	;GET ARGS
	SKIPL T1
	CAILE T1,MAXCLS-1	;VALID CLASS?
	ITERR (ARGX25)
	NOSKED			;OWN MACHINE FOR A WHILE
	PUSH P,CLSSHR(T1)	;SAVE OLD CLASS VALUE
	MOVEM T2,CLSSHR(T1)	;SET NEW CLASS
	SETZM P1		;GET ACCUMULATOR
	MOVEI T3,MAXCLS-1
SKDSC1:	FAD P1,CLSSHR(T3)	;GET TOTAL SHARES ALLOCATED
	SOJGE T3,SKDSC1
	POP P,CLSSHR(T1)	;PUT BACK OLD VALUE
	JUMPE T2,SKDS11		;ALLOW 0 ALWAYS
	CAML T2,[SHRMIN]	;AT LEAST THE MINIMUM?
	CAMLE P1,[1.0]		;VALID NUMBER?
	ITERR (ARGX29,<OKSKED>)	;NO
SKDS11:	MOVEM P2,WA(T1)		;SET WA VECTOR VALUE
	EXCH T1,T2		;ORDER ARGS
	CALL CRTSHR		;MAKE SHARE
	OKSKED			;RESTORE MACHINE
	MRETNG			;AND DONE

;SET CLASS FOR JOB

SKDSJC:	OPSTR <SKIPN>,CLSAC	;DOING CLASS BY ACCOUNT?
	SKIPN CLASSF		;NO. ACCOUNTING OFF?
	ITERR (SKDX1)		;YES. CAN'T DO THIS THEN
	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	CAIGE T3,3		;ENOUGH ROOM?
	ITERR (ARGX04)		;NO
	XCTU [DMOVE T1,.SAJOB(T2)]	;GET DATA
	CAME T1,[-1]		;THIS JOB?
	CAMN T1,JOBNO		;NO. OR THIS WAY?
	SKIPA T1,JOBNO		;YES. DO IT
	JRST [	MOVX T3,SC%WHL!SC%OPR ;NO. MUST BE PRIVILEGED
		TDNN T3,CAPENB	;IS IT?
		ITERR (CAPX1)	;NO. ERROR THEN
		JRST SKDSJ0]	;YES. PROCEED
SKDSJ0:	SKIPL T1
	CAIL T1,NJOBS		;VALID JOB
	ITERR (ARGX08)		;NO
	SKIPGE JOBRT(T1)	;LOGGED IN?
	ITERR (ARGX15)		;NO
;	MOVX T3,SC%WHL		;SEE IF THIS JOB IS WHEELED
;	TDNE T3,CAPENB		;IS IT?
;	JRST SKDSJ1		;YES. SKIP GETOK THEN
	GTOKM (.GOCLS,<T1,T2>)	;VERIFY REQUEST. ITRAP IF DENIED
SKDSJ1:	EXCH T1,T2		;ARRANGE ARGS PROPERLY
	NOSKED
	CALL CHGCLS		;DO CHANGE
	OKSKED
	MRETNG			;AND DONE

;START UP THE CLASS SCHEDULER

SKDSCL:	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	CAIG T3,1		;ENOUGH WORDS?
	ITERR (ARGX04)		;NO
	NOSKED
	UMOVE P1,.SACTL(T2)		;GET CONTROL WORD
	TXNE P1,SK%STP		;STOP?
	JRST [	SETZM CLASSF	;YES
		MOVX T1,1B1	;GET A BIG NUMBER
		MOVEM T1,UTLTIM	;AND TURN OFF UTIL COMPUTATION
		CALL QBIAS	;SET UP QUANTS PROPERLY
		JRST SKDSC0]	;DONE
	SKIPE CLASSF		;NO. IS IT NOW ON?
	ITERR (ARGX31,<OKSKED>)	;YES. CAN'T DO IT THEN
	CALL QCLASS		;SET UP CLASS QUANTS
	CALL STRCLS		;START UP CLASS SCHEDULER
	MOVEI T1,0
	TXNE P1,SK%ACT		;WANT CLASS BY ACCOUNTS?
	MOVEI T1,1		;YES.
	STOR T1,CLSAC		;STORE VALUE
	MOVEI T1,1
	TXNE P1,SK%WDF		;WITHHOLD WINDFALL?
	MOVEM T1,CLASSF		;YES. STATE THIS THEN
SKDSC0:	OKSKED			;RESTORE MACHINE
	MRETNG			;AND DONE
;FUNCTIONS TO SET/READ DEFAULT INFORMATION

;READ CLASS SETTING FOR BATCH JOBS

	SWAPCD			;BACK TO SWAPPABLE CODE
SKDRCB:	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	CAIG T3,1		;ROOM TO STORE VALUE?
	ITERR (ARGX04)		;NO. CAN'T DO IT THEN
	LOAD T1,CLSBT		;GET BATCH CLASS
	SUBI T1,1		;ONE LESS
	UMOVEM T1,.SABCL(T2)		;RETURN GOOD DATA
	MRETNG			;AND DONE

;SET BATCH CLASS

SKDSCB:	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	CAIG T3,1		;HAVE AN ARG?
	ITERR (ARGX04)		;NO
	UMOVE T1,.SABCL(T2)		;GET SETTING
	AOSL T1			;VALID?
	CAILE T1,MAXCLS+1	;STILL?
	ITERR (ARGX25)		;NO
	STOR T1,CLSBT		;SAVE IT
	MRETNG			;AND DONE

;RUN ALL BATCH JOBS ON DREGS QUEUE

SKDRDQ:	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	SKIPE T2		;HAVE A COUNT?
	CAIG T3,1		;BIG ENOUGH?
	TROA T1,1		;NO. SET IT THEN
	UMOVE T1,.SADRG(T2)		;YES. GET IT
	SKIPE T1		;SET OR CLEAR?
	MOVEI T1,1		;SET
	STOR T1,CLSBD		;DO IT
	MRETNG			;AND DONE

;READ CLASS PARAMETERS

SKDRCP:	XCTU [HRRZ T3,.SACNT(T2)]	;GET COUNT
	CAIG T3,1		;ROOM FOR DATA?
	ITERR (ARGX04)		;NO
	SKIPN CLASSF		;CLASS SCHEDULER ON?
	JRST [	MOVX T1,SK%STP	;NO. SAY STOPPED
		JRST SKDRC0]	;AND FINISH UP
	SETZM T1		;INIT VALUE
	OPSTR <SKIPE>,CLSAC	;DOING ACCOUNTS?
	TXO T1,SK%ACT		;YES
	SKIPL CLASSF		;WINDFALL WITHHELD?
	TXO T1,SK%WDF		;YES.
SKDRC0:	LOAD T3,CLSBD		;SEE IF BATCH ON DREGS
	STOR T3,SK%DRG,T1	;0 IF SO, 1 IF NOT
	UMOVEM T1,.SACTL(T2)		;RETURN DATA
	MRETNG			;AND DONE
	TNXEND
	END