Google
 

Trailing-Edge - PDP-10 Archives - BB-4170G-SM - sources/sched.mac
There are 52 other files named sched.mac in the archive. Click here to see a list.
;<3A.MONITOR>SCHED.MAC.10,  9-Aug-78 20:36:02, Edit by DBELL
;TCO 1905.  PREVENT ZERO POINTER IN TLEINT FROM CAUSING RESBAD, ILLUUO BUGCHKS
 ;<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
;<3A.MONITOR>SCHED.MAC.8, 12-Jun-78 10:07:17, EDIT BY MILLER
;TCO 1894. MAKE SURE CTY OUTPUT IS STARTED AT SWHLT3
;<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
;<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
;<3A.MONITOR>SCHED.MAC.1,  3-Apr-78 13:30:59, EDIT BY MILLER
;REMOVE 2 MS DELAY IN SCHPRF
;<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.
;<3.SM10-RELEASE-3>SCHED.MAC.5, 16-Jan-78 11:34:24, EDIT BY MILLER
;CHANGES TO SUPPORT PAGE LOCKING
;<3.SM10-RELEASE-3>SCHED.MAC.4, 11-Jan-78 09:39:35, EDIT BY MILLER
;FIX JTENQ NOT TO TURN ON IFIW IN QUEUE POINTER.
;<3.SM10-RELEASE-3>SCHED.MAC.3, 10-Jan-78 11:23:18, EDIT BY MILLER
;FIX LOSING PCU IN PIRCOF
;<ENGEL>SCHED.MAC.3, 13-Dec-77 16:59:23, EDIT BY ENGEL
;TCO #1888  PASS PSIBIP TO JSBSTF - CLEAR ONLY CURRENT LEVEL ENTRIES
;<3-MONITOR>SCHED.MAC.551, 11-Nov-77 17:56:28, EDIT BY MURPHY
;ADD FRTON, FRTOFF - ROUTINES FOR CONTROLLING FORK RUN TIME ACCOUNTING
;<3-MONITOR>SCHED.MAC.550, 11-Nov-77 16:58:13, EDIT BY MURPHY
;FIX HANG CAUSED BY BALSET HYSTERESIS
;<3-MONITOR>SCHED.MAC.549,  9-Nov-77 09:57:40, EDIT BY KIRSCHEN
;MORE COPYRIGHT UPDATING...
;<3-MONITOR>SCHED.MAC.548,  8-Nov-77 20:37:54, EDIT BY MILLER
;CHECK PNSKDC WHEN PSI IS REQUESTED AND AT JSYS ENTRY
;<3-MONITOR>SCHED.MAC.547, 31-Oct-77 16:23:09, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.546, 20-Oct-77 13:08:35, EDIT BY MILLER
;FIX BAD INDEX AT UCLOC1
;<3-MONITOR>SCHED.MAC.545, 17-Oct-77 13:45:15, EDIT BY MILLER
;CODE AT SCHPRF MUST CALL GETMST TO GET CURRENT TIME
;<3-MONITOR>SCHED.MAC.544, 12-Oct-77 20:42:23, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.543, 12-Oct-77 14:12:08, EDIT BY KIRSCHEN
;UPDATE COPYRIGHT FOR RELEASE 3
;<3-MONITOR>SCHED.MAC.542, 11-Oct-77 23:44:32, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.541, 10-Oct-77 13:35:17, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.540,  7-Oct-77 17:58:46, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.539,  6-Oct-77 00:02:03, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.538,  5-Oct-77 13:57:48, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.537,  4-Oct-77 20:47:19, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.536,  3-Oct-77 17:35:50, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.535,  2-Oct-77 15:08:33, EDIT BY MILLER
;MAKE IT IN UPPER CASE THIS TIME
;<3-MONITOR>SCHED.MAC.534,  2-Oct-77 14:59:39, EDIT BY MILLER
;use msec1b when need pc format of section #
;<3-MONITOR>SCHED.MAC.533, 30-Sep-77 15:05:00, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.532, 29-Sep-77 15:22:40, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.531, 23-Sep-77 16:28:38, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.530, 23-Sep-77 09:26:12, EDIT BY MILLER
;MORE WORK ON NETWKF
;<3-MONITOR>SCHED.MAC.528, 23-Sep-77 08:21:00, EDIT BY MILLER
;ADD NETWKF ROUTINE FOR NSPSRV
;<3-MONITOR>SCHED.MAC.527, 21-Sep-77 14:03:13, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.526, 20-Sep-77 18:12:19, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.525, 15-Sep-77 22:35:03, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.524, 15-Sep-77 17:35:00, EDIT BY MURPHY
;BETTER HANDLING OF PCS REGISTER
;<3-MONITOR>SCHED.MAC.523, 14-Sep-77 15:00:23, Edit by MCLEAN
;COMMENT OUT SJOBD PER PMH SUGGESTION
;<MURPHY.MON>SCHED.MAC.2, 12-Sep-77 23:41:52, EDIT BY MURPHY
;EVENT DRIVEN BALSET ENTRY, TRYLDF, ETC.
;<3-MONITOR>SCHED.MAC.522, 12-Sep-77 22:25:29, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.521,  1-Sep-77 23:31:37, EDIT BY MURPHY
;TINKER NEWST
;<3-MONITOR>SCHED.MAC.520,  1-Sep-77 17:53:29, EDIT BY MURPHY
;UPDTCK USAGE
;<3-MONITOR>SCHED.MAC.519, 26-Aug-77 09:30:12, EDIT BY MILLER
;EXECUTE PWRFLE WHEN POWER FAIL DETECTED
;<3-MONITOR>SCHED.MAC.518, 25-Aug-77 13:15:56, EDIT BY MILLER
;<3-MONITOR>SCHED.MAC.518, 25-Aug-77 13:03:12, EDIT BY MILLER
;MAKE IMCLL0 ACCEPT JSYS OR ADDRESS ARGS
;<3-MONITOR>SCHED.MAC.517, 24-Aug-77 17:45:37, EDIT BY MILLER
;MAKE IMCALL TRANSFER TO ANY SECTION
;<3-MONITOR>SCHED.MAC.516, 15-Aug-77 16:30:28, EDIT BY MILLER
;INIT DECNET QUOTA COUNT AT JOB INIT
;<3-MONITOR>SCHED.MAC.515, 15-Aug-77 12:43:59, EDIT BY MILLER
;INCREASE MINNR TO ALLOW FOR STACK PAGE TO SWAP IN
;<3-MONITOR>SCHED.MAC.514, 15-Aug-77 12:34:54, EDIT BY MILLER
;MAKE CHKWT USE SAVEAC SO PI STACK DOESN'T OVERFLOW
;<3-MONITOR>SCHED.MAC.513,  9-Aug-77 08:47:19, EDIT BY MILLER
;ASSIGN AN SPTN TO PSB STACK PAGE AND LOCK IT DOWN WHEN PROCESS IN BALSET
;<3-MONITOR>SCHED.MAC.512,  6-Aug-77 14:35:23, Edit by LCAMPBELL
;<3-MONITOR>SCHED.MAC.511,  3-Aug-77 11:49:04, Edit by LCAMPBELL
;<3-MONITOR>SCHED.MAC.510,  3-Aug-77 11:45:25, Edit by LCAMPBELL
;MORE TCO 1838 - ADDR BREAK
;<3-MONITOR>SCHED.MAC.509, 30-Jul-77 01:46:47, EDIT BY CROSSLAND
;REMOVE SPECIAL CHECKS FOR NVTS
;<3-MONITOR>SCHED.MAC.508, 29-Jul-77 14:50:11, Edit by LCAMPBELL.ADBRK
;TCO 1838 - ADDRESS BREAK
;<3-MONITOR>SCHED.MAC.507, 29-Jul-77 00:02:31, EDIT BY CROSSLAND
;FIX UP MIS MERGE BY REMOVING CODE TO DELETE 2ND PSB PAGE FROM HLTJB1
;<3-MONITOR>SCHED.MAC.506, 28-Jul-77 21:12:26, EDIT BY CLEMENTS
; Repair JTENQ - storing PC flags in wrong flag word
;<3-MONITOR>SCHED.MAC.505, 28-Jul-77 17:36:04, EDIT BY CLEMENTS
; replace two instructions accidentally dropped in previous edit
;<3-MONITOR>SCHED.MAC.504, 28-Jul-77 02:40:13, EDIT BY CLEMENTS
; SCTTY ADDS, FIXES
;<3-MONITOR>SCHED.MAC.503, 26-Jul-77 18:49:37, EDIT BY CLEMENTS
; MODEL B CODE FIX FOR UUO-TRAPPING
;<3-MONITOR>SCHED.MAC.502, 26-Jul-77 15:54:32, EDIT BY MILLER
;DEFER DELETING PSB STACK PAGE UNTIL PROCESS IS IN SCHED CONTEXT
;<3-MONITOR>SCHED.MAC.501, 25-Jul-77 12:28:18, EDIT BY HURLEY
;MAKE THE DEFAULT SETTING OF FACTSW ALLOW USER SETTING OF DIR PARAMS
;<3-MONITOR>SCHED.MAC.500, 25-Jul-77 00:51:59, EDIT BY CROSSLAND
;<3-NSW-MONITOR>SCHED.MAC.2, 24-Jul-77 15:44:12, EDIT BY CLEMENTS.CALVIN
; Added JSYS trap code
;<3-NSW-MONITOR>SCHED.MAC.1, 23-Jul-77 14:05:04, EDIT BY CLEMENTS.CALVIN
; Changes for new TIMER code & JSYS trap initilization code
;<3-MONITOR>SCHED.MAC.497, 15-Jul-77 10:41:16, EDIT BY HALL
;ADD CKMMOD
;<3-MONITOR>SCHED.MAC.496,  4-Jul-77 18:16:38, EDIT BY CROSSLAND
;FIX UP DEASIGNING OF NVT'S AT HLTJB
;<3-MONITOR>SCHED.MAC.495, 23-Jun-77 13:30:22, Edit by MCLEAN
;ADD PSBMSZ
;<3-MONITOR>SCHED.MAC.494, 22-Jun-77 13:15:07, EDIT BY HALL
;TCO 1740 - CHANGE JOBSRT TO CALL TTABRT
;<1MURPHY>SCHED.MAC.1, 17-Jun-77 16:47:35, EDIT BY MURPHY
;TCO #1826 - FIX NBQ UPDATE (ALSO ELIMINATE RJQNT)
;<2-MONITOR>SCHED.MAC.450, 11-Jun-77 14:50:21, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.491, 10-Jun-77 11:10:34, EDIT BY MURPHY
;PERFORMANCE ENHANCEMENTS
;<3-MONITOR>SCHED.MAC.489,  5-May-77 16:04:56, EDIT BY MILLER
;TCO 1272 AGAIN. FIX SUPUB0
;<3-MONITOR>SCHED.MAC.488, 28-Apr-77 15:31:21, EDIT BY MILLER
;FORCE IN UPDL PAGES WHEN GOING NOSKED
;<3-MONITOR>SCHED.MAC.487, 14-Apr-77 16:45:42, EDIT BY HALL
;TCO 1740 - MADE HLTJB CALL LCKDVL BEFORE CALLING TTYDAS
;<3-MONITOR>SCHED.MAC.486,  5-Apr-77 16:39:19, EDIT BY MILLER
;TCO 1769. MAKE PSIPG 2 PAGES
;<3-MONITOR>SCHED.MAC.485,  5-Apr-77 02:43:24, Edit by MCLEAN
;ADD MONPC AND MONFL TO SAVCT
;<3-MONITOR>SCHED.MAC.484,  1-Apr-77 11:30:25, Edit by MCLEAN
;FIX ITRSIM IT WAS LOOSING IMCALL FLAG
;<3-MONITOR>SCHED.MAC.483, 23-Mar-77 16:13:08, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.482, 22-Mar-77 11:29:23, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.481, 22-Mar-77 02:14:08, Edit by MCLEAN
;REMOVE USELESS REFERENCE TO SKCLKF
;<3-MONITOR>SCHED.MAC.480, 11-Mar-77 15:41:17, EDIT BY HALL
;TCO 1740 - FIX TTPSRQ TO CHECK FOR -1 CONTROLLING JOB NUMBER
;<3-MONITOR>SCHED.MAC.479,  9-Mar-77 16:05:10, EDIT BY HALL
;TCO 1740 - MADE HLTJB WAIT WHEN TTYDAS RETURNS FAILURE
;<3-MONITOR>SCHED.MAC.478,  5-Mar-77 15:34:14, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.477,  5-Mar-77 15:28:11, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.476, 28-Feb-77 11:31:51, EDIT BY HURLEY
;ADD TEST IN SCHEDULER TO NOT SCHEDULE A JOB OUT OF UTREP (UTEST)
;<3-MONITOR>SCHED.MAC.475, 28-Feb-77 04:48:45, EDIT BY CROSSLAND
;TCO 1743 CRJOB
;<3-MONITOR>SCHED.MAC.474, 25-Feb-77 17:12:18, EDIT BY MILLER
;<3-MONITOR>SCHED.MAC.473, 23-Feb-77 20:23:55, EDIT BY HALL
;TCO 1740 - CHANGED REFERENCES TO TTY DATA TO CALLS TO TTYSRV
;<3-MONITOR>SCHED.MAC.472, 23-Feb-77 17:46:08, EDIT BY MURPHY
;DEFINE NBWT
;<3-MONITOR>SCHED.MAC.470, 21-Feb-77 17:59:24, EDIT BY MURPHY
;TCO #1739 - NEW STATISTICS
;<2-MONITOR>SCHED.MAC.445, 15-Feb-77 18:29:57, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.468, 15-Feb-77 17:37:35, EDIT BY HURLEY
;<2-MONITOR>SCHED.MAC.443, 15-Feb-77 12:27:56, EDIT BY MURPHY
;TCO #1734 - FIX NEGATIVE INCREMENT TO QSUM
;<3-MONITOR>SCHED.MAC.466,  5-Feb-77 14:26:30, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.465, 27-Jan-77 13:38:23, EDIT BY MURPHY
;<2-MONITOR>SCHED.MAC.440, 27-Jan-77 13:23:48, EDIT BY MURPHY
;<2-MONITOR>SCHED.MAC.439, 25-Jan-77 17:54:11, EDIT BY MURPHY
;<3-MONITOR>SCHED.MAC.466, 25-Jan-77 17:13:31, EDIT BY MURPHY
;<2-MONITOR>SCHED.MAC.437, 20-Jan-77 15:53:13, EDIT BY MURPHY
;TCO #1479 - BUG FIXES
;<3-MONITOR>SCHED.MAC.463, 19-Jan-77 19:39:32, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.462, 19-Jan-77 02:26:27, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.461, 16-Jan-77 15:02:41, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.460, 16-Jan-77 14:17:22, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.459, 13-Jan-77 15:43:30, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.458, 11-Jan-77 16:29:52, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.457,  3-Jan-77 14:46:34, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.456, 30-Dec-76 16:56:59, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.455, 30-Dec-76 15:11:22, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.454, 30-Dec-76 01:20:19, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.453, 30-Dec-76 00:19:30, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.452, 29-Dec-76 23:13:39, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.451, 29-Dec-76 12:58:41, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.450, 27-Dec-76 17:36:51, EDIT BY HURLEY
;<3-MONITOR>SCHED.MAC.449, 18-Dec-76 04:09:11, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.447, 18-DEC-76 03:52:09, EDIT BY MCLEAN
;<3-MONITOR>SCHED.MAC.446,  7-Dec-76 15:47:17, EDIT BY MILLER
;TCO 1678. IMPROVE CHECK FOR PISTK ROOM AT PSISM.
;<3-MONITOR>SCHED.MAC.445,  3-Dec-76 22:58:20, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.444,  3-Dec-76 00:41:52, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.443, 30-Nov-76 01:17:00, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.442, 28-Nov-76 17:39:58, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.441, 28-Nov-76 15:34:06, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.440, 28-Nov-76 13:07:15, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.439, 27-Nov-76 03:12:38, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.438, 26-Nov-76 20:24:31, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.437, 26-Nov-76 20:23:16, Edit by MCLEAN
;<3-MONITOR>SCHED.MAC.436, 26-Nov-76 20:17:01, Edit by MCLEAN
;TCO 1669 EXTENDED ADDRESSING
;<2-MONITOR>SCHED.MAC.434, 16-Nov-76 13:17:07, EDIT BY MURPHY
;TCO #1663 - RESET SCKATM AT SCDW
;<2-MONITOR>SCHED.MAC.433, 15-Nov-76 00:08:22, EDIT BY BOSACK
;ADD FEATURE TO FORCE RELEASE OF ALL UNLOCKED MEMORY
;<2-MONITOR>SCHED.MAC.432, 12-Nov-76 16:22:02, EDIT BY BOSACK
;MOVE RPLQ DATABASE TO STG
;<2-MONITOR>SCHED.MAC.431,  8-Nov-76 14:45:06, EDIT BY MILLER
;CHANGE MOVE TO LOAD IN FKSET1
;<2-MONITOR>SCHED.MAC.430, 29-Oct-76 15:37:03, EDIT BY MILLER
;TCO 1636. TURN OFF PSICOB BIT IN PIRCOF.
;<2-MONITOR>SCHED.MAC.429, 23-Oct-76 16:40:21, EDIT BY HALL
;DELETED STOKF
;<2-MONITOR>SCHED.MAC.428, 12-Oct-76 18:18:46, EDIT BY HURLEY
;MAKE RDISMS DO AN OKINT AS WELL AS A NOSKED
;<2-MONITOR>SCHED.MAC.427, 12-Oct-76 16:06:00, EDIT BY HURLEY
;MAKE THE NOINTS AND OKINTS AT NOSKD0 BE IN THE CORRECT ORDER
;<2-MONITOR>SCHED.MAC.427, 11-Oct-76 14:59:05, Edit by MACK
;TCO 1586 - ADD REDEFINED SCHEDULING CONTROL MACRO ROUTINES
;<2-MONITOR>SCHED.MAC.425,  4-Oct-76 14:29:43, EDIT BY HURLEY
;TCO 1566 - MAKE SMRETN DO A MOVE P,MPP BEFORE THE AOS (P)
;<2-MONITOR>SCHED.MAC.424, 28-Sep-76 11:42:53, EDIT BY MILLER
;TCO 1549. CHECK FOR WAITING PROCESS AT PIRCOF
;<2-MONITOR>SCHED.MAC.423, 21-Sep-76 19:00:35, EDIT BY MURPHY
;TCO #1533 - CHECK IMCFLG AT ITRSIM AND CHKERT
;<P3-MONITOR>SCHED.MAC.16,  9-Sep-76 11:35:50, EDIT BY MURPHY
;TCO #1518 - UNDEFINED JSYSES CAUSE ITRAP
;<2-MONITOR>SCHED.MAC.421, 25-Aug-76 16:12:20, EDIT BY MURPHY
;<2-MONITOR>SCHED.MAC.420, 20-Aug-76 18:40:40, EDIT BY MURPHY
;<P3-MONITOR>SCHED.MAC.14, 20-Aug-76 18:32:58, EDIT BY MURPHY
;<2-MONITOR>SCHED.MAC.418, 16-Aug-76 12:33:48, EDIT BY MURPHY
;<2-MONITOR>SCHED.MAC.417, 13-Aug-76 17:47:15, EDIT BY MURPHY
;<2-MONITOR>SCHED.MAC.416, 12-Aug-76 17:48:30, EDIT BY MURPHY
;TCO #1490 - HANDLE OVERFLOW OF MTIME WORD
;<2-MONITOR>SCHED.MAC.415, 12-Aug-76 17:35:18, EDIT BY MURPHY
;TCO #1479
;<2-MONITOR>SCHED.MAC.413, 12-Aug-76 17:23:34, EDIT BY MURPHY
;<2-MONITOR>SCHED.MAC.412, 11-Aug-76 13:51:18, Edit by HESS
;ADD ROUTINE ITRSIM
;<2-MONITOR>SCHED.MAC.411,  5-Aug-76 12:12:56, EDIT BY MURPHY
;TCO #1479 - BALANCE SET PARTITIONING
;<2-MONITOR>SCHED.MAC.409,  3-Aug-76 14:55:38, Edit by HESS
;TCO 1478 - ADD QUOTA CHL TO PANIC CHL MASK
;<2-MONITOR>SCHED.MAC.408, 28-Jul-76 16:50:25, EDIT BY MURPHY
;TCO #1479 - HI/LO LOAD AVERAGES; MOVED SOME STORAGE TO STG
;<1B-MONITOR>SCHED.MAC.405, 15-JUN-76 15:12:24, EDIT BY MILLER
;TCO 1421. SWEEP CACHE AS PART OF POWER FAIL
;<1B-MONITOR>SCHED.MAC.404, 14-JUN-76 14:23:09, EDIT BY JMCCARTHY
;TCO 1412 - REPLACE JOB'S WITH JFOV'S
;<2-MONITOR>SCHED.MAC.2,  9-JUN-76 09:26:48, EDIT BY MILLER
;<1MILLER>SCHED.MAC.1,  2-JUN-76 11:17:02, EDIT BY MILLER
;<1B-MONITOR>SCHED.MAC.3,  3-MAY-76 11:28:47, EDIT BY MILLER
;<1B-MONITOR>SCHED.MAC.2, 30-APR-76 10:12:49, EDIT BY MILLER
;TCO 1272. MOVE CALL TO FKTMI TO SUPUNB
;<1B-MONITOR>SCHED.MAC.1, 22-APR-76 13:30:21, EDIT BY MILLER
;TCO 1255. CREATE PSIPGA ON FORK CREATE
;<1A-MONITOR>SCHED.MAC.402,  9-APR-76 14:04:41, EDIT BY MILLER
;TCO 1199 AGAIN. FIX BAD EDIT
;<1MONITOR>SCHED.MAC.401, 25-MAR-76 10:39:51, Edit by MACK
;TCO #1220 - UNDO TCO #1197
;<1MONITOR>SCHED.MAC.400, 22-MAR-76 11:22:08, Edit by MACK
;TCO #1199 - FORK-STRUCTURE SEARCH FIXED TO PREVENT MONITOR PDL OVERFLOW
; AT PSIT1D+2: 
;<1MONITOR>SCHED.MAC.399, 19-MAR-76 16:02:29, Edit by MACK
;TCO #1197 - EFFECTIVE ADDR CALCULATION FOR SIMULATED ERCAL FIXED
;<1MONITOR>SCHED.MAC.398, 17-MAR-76 16:01:24, Edit by MACK
;TCO #1189 - ERCAL PUSHJ SIMULATION FIXED SO USER PC UPDATED PROPERLY
;<1MONITOR>SCHED.MAC.397, 16-MAR-76 16:00:29, Edit by MACK
;TCO #1185 - PDL OVERFLOW CHECK AT ITRRET:
;<1MONITOR>SCHED.MAC.396,  1-MAR-76 11:38:52, EDIT BY MURPHY
;TCO #1097 - INCREASE MON VAS
;<2MONITOR>SCHED.MAC.395,  2-FEB-76 11:20:28, EDIT BY KIRSCHEN
;MCO 48 - ADD FLAG RTSKED: REAL-TIME SERVICE REQUIRED
;<2MONITOR>SCHED.MAC.394, 30-JAN-76 12:45:55, EDIT BY HURLEY
;MCO 44 - UNMAP DIRECTORIES BEFORE KILLING A FORK
;<2MONITOR>SCHED.MAC.393, 19-JAN-76 12:27:20, EDIT BY MURPHY
;<2MONITOR>SCHED.MAC.392, 16-JAN-76 12:54:35, EDIT BY MURPHY
;MCO #7 - FIX BAD FKCSIZ AT LOADBS
;<2MONITOR>SCHED.MAC.391,  9-JAN-76 11:01:37, EDIT BY HURLEY

;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 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>
;LOWER CORE LOCATIONS FOR LITES DISPLAY


SHLTW==:30			;SCHEDULER HALT REQUEST WORD
SCTLW==:20			;SCHEDULER CONTROL WORD
;SJOBD==:21			;JOB DISPLAY
;SLITES==:22			;USUAL LITES
;SPRIJD==:23			;PRIORITY JOB DISPLAY

NSCDRQ==20			;SIZE OF SCHEDULER REQUEST QUEUE

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

;QUANTUM GUARANTEED TO PROCESS LOADED IN BALSET BEFORE IT BECOMES
;ELIGIBLE FOR SWAPOUT.

BSQPP::	^D50*NTMS		;TIME PER PAGE OF WORKING SET
BSQMAX::^D2000*NTMS		;MAX QUANTUM REGARDLESS OF SIZE

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

MINWSS::^D8

;ASSUMED TYPICAL SIZES FOR INTERACTIVE AND COMPUTATIONAL FORKS

NHQR::	^D16			;INTERACTIVE = 8K
NLQR::	^D64			;COMPUTATIONAL = 32K

;BASIC PERIODS

SKDSCY:	^D20		;SHORT CYCLE
SKDLCY:	^D100		;LONG CYCLE
AJBLCY:	^D1000			;AJBALS CYCLE
SKDBQT:	^D200*NTMS		;BALSET RUN QUANTUM

;STANDARD VALUES FOR SCHEDULER INTERACTIVE/COMPUTATIONAL FLAGS
; ON A SCALE OF 0 - 19

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 ;NORMAL DEFAULT
SKFLDF:	BYTE (18) 0 (1) 1,0,1,0,1,0,1,0,1,1,0
	BYTE (18) 0 (1) 1,0,1,0,1,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,1,0,0,1,0,0,0,0
	BYTE (18) 0 (1) 0,0,0,1,0,0,1,0,0,0,0
	BYTE (18) 0 (1) 0,0,0,1,0,0,1,0,0,0,0
	BYTE (18) 0 (1) 0,0,0,1,0,0,1,0,0,0,0
NSKFLV==:.-SKFLGV
;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,[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
	MOVEI 1,FKPT
	MOVEI 2,NFKS
	CALL ILIST		;INIT FREE FORK LIST
	MOVEM 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
	MOVX 1,PUFLD		;BITS IN PROCESS USE REG
	MOVEM 1,FRECB
	SETZM FBALS
	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
	MOVE T1,[BALLST,,BALLST]
	MOVEM T1,BALLST		;INIT BALSET RUN LIST
	HRRZM T1,BALLS0		;AND HIGH QUEUE TAIL PTR
	RET
;SET BALANCE SET PARTITIONING LIMITS
;CONSIDER ONE LOW QUEUE FORK AND ONE HIGH QUEUE FORK AS A UNIT, SEE
;HOW MANY SUCH UNITS CAN FIT IN CORE.  IF LESS THAN ONE OR
;GREATER THAN 3, DIVIDE CORE IN HALF.

AJBPAR::MOVEI T3,3		;SEE IF 3 UNITS WILL FIT
AJBP1:	MOVE T1,NHQR		;SIZE OF ONE UNIT
	ADD T1,NLQR
	IMULI T1,0(T3)		;SIZE OF THIS N UNITS
	CAMLE T1,MAXNR		;WILL THIS NUMBER FIT?
	SOJG T3,AJBP1		;NO, TRY ONE LESS
	MOVE T2,NLQR		;HAVE NUMBER, COMPUTE LOW QUEUE SIZE
	IMULI T2,0(T3)
	MOVE T1,MAXNR		;ALSO COMPUTE ONE-HALF CORE
	ASH T1,-1
	CAMGE T1,T2		;SELECT MAX
	MOVE T1,T2
	MOVEM T1,MAXLQR		;THAT IS MAX LOW QUEUE RESERVE
	SUB T1,MAXNR		;COMPUTE (MAXNR-MAXLQR)
	MOVNM T1,MAXHQR		;THAT IS MAX HIGH QUEUE RESERVE
	RET

ILIST::	ADDI 1,-1(2)
	SETZM 0(1)		;INIT FREE LIST, BLOCK ADR IN AC1,
	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
	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
	MOVE 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?
	CAIL T1,SNPBPP+SNPBPS+SNPDPS
	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:	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?
	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
	MDISMS
	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)

;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:	MOVEI 2,0		;SAY 0 HOLD TIME
DISMSH:	PUSH P,2		;SAVE HOLD TIME
	HRRZ T2,T1		;GET ADR OF ROUTINE
	SKIPN NSKED		;CHECK FOR BUGGY DISMISS
	CAIL T2,SWPMA		;CHECK FOR A NON-RESIDENT TEST ROUTINE
	BUG(HLT,NSKDIS,<DISMISS WHILE NOSKED OR WITH NON-RES TEST ADDRESS>)
	MOVEM 1,FKSTAT(FX)	;PUT IN TEST WORD
	CALL SAVRT
	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
;	CAMLE 2,MAXBSH		;IMPOSE LIMIT
;	MOVE 2,MAXBSH
	JUMPE 2,[CALL REMBSJ	;IF 0 HOLD TIME, REMOVE IMMEDIATELY
		HRRZ 1,FKCNO(FX)
		MOVE 1,BITS(1)
		IORM 1,PUBCL	;NOTE PROC REMOVED FROM BALSET
		CALL GLREM	;REMOVE FROM GOLST
		CALL WTCONC
		CALL CHKTFK	;CHECK BALSET
		SETOB FX,FORKX
		JRST SCHED0]
	LOAD P1,FKLOC		;GET BALSET INDEX
	SETZM NBQ(P1)		;ALLOW REMOVAL IF NECESSARY
	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

MAXBSH:	^D100			;MAX BALSET HOLD TIME
;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(HLT,SKDCL1,<CALL TO SCHEDULER WHEN ALREADY IN SCHEDULER>)
	ENTSKD
SCHP1:	PUSH P,1
	CALL SAVRT
	POP P,1
	MOVEM 1,FKPGST(FX)
	DMOVE 1,SKDFL
	DMOVEM 1,PFL
SCHP3:	MOVSI 1,(BSWTB)
	CALL SCHP2
	MOVE 1,TODCLK		;REMEMBER TIME WAIT STARTED
	MOVEM 1,NBW(P1)
	AOS NBWT		;COUNT WAITING BALSET PROCESS
	JRST SCHED0

;RETAIN FORK IN BALSET, SET FLAGS, ETC.

SCHP2:	SKIPE NSKED
	MOVEM FX,SSKED		;REMEMBER FORK NUMBER OF NOSKED FORK
	LOAD P1,FKLOC		;BALSET INDEX
	SKIPE NSKED		;NON-RESCHEDULABLE?
	TLO 1,(BSNSK)		;YES
	HLLM 1,BALSET(P1)	;WAITING FLAG
	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(HLT,SKDCL2,<CALL TO SCHEDULER WHEN ALREADY IN SCHEDULER>)
	ENTSKD
	SOSGE NSKED
	BUG(HLT,ILOKSK,<OKSKED WHEN NOT NOSKED>)
	SOS INTDF		;FIX UP NOINT AS WELL
	JRST SCHP1
;COMMON SCHEDULER ENTER ROUTINE, SAVE AC'S AND SET INSKED FLAG

ENSKED::AOS INSKED		;PREVENT ACTION BY CH7 BREAK
	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
	MOVE 1,PAC+1		;AC1 SOMETIMES ARG TO DISMISS ROUTINE
	XJRSTF ENSKR
;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(HLT,SKDTRP,<INSTRUCTION TRAP WHILE IN SCHEDULER>)
	SKIPL FORKX		;NO FORK RUNNING, OR
	CONSZ PI,177B27		;PI IN PROGRESS?
	BUG(HLT,PIITRP,<INSTRUCTION TRAP WHILE PI IN PROGRESS OR IN SCHEDULER>)
	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		;STACK PTR ON ENTERING THIS CONTEXT
	CALL ITRRET		;CHECK FOR ERROR TEST INSTRUCTION
	MOVE 2,0(P)		;RETURN PC
	TLNN 2,(UMODF)		;PREVIOUS CONTEXT INTERRUPTABLE?
	SKIPGE -3(P)		;I.E. USER MODE, OR INTDF .L. 0
	JRST ITR2		;YES, OK
	BUG(CHK,NOINTR,<ITRAP AND PREVIOUS CONTEXT WAS NOINT>)
ITR2:	SKIPE NSKED		;CHECK FOR PROPER STATE
	BUG(CHK,NOSKTR,<ITRAP FROM NOSKED CONTEXT>)
	SETZM NSKED
	SETOM TRAPC		;CLEAR FLAGS AND COUNTERS
	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
	CAMGE T1,MAXBSH		;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,^D500		;USE BLOCKW FOR WAIT .L. 500 MS
	SKIPA 1,[BLOCKW]
	MOVEI 1,BLOCKM		;BLOCKM OTHERWISE
	HRLI 1,0(2)
TDIS2:	MDISMS			;DISMISS WITH SPECIFIED TEST
	JRST MRETN

TDIS1:	CALL SETBKT		;COMPUTE TEST DATA
	HRRI 1,BLOCKT
	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
	MDISMS
	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:	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
	SKIPE NBPROC		;BALSET NON-EMPTY?
	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
	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
SCHED0::SETZ 0,			;FOR PEOPLE WATCHING LIGHTS
	CONSZ PI,177B27		;ANY PI IN PROGRESS?
	BUG(HLT,PISKED,<ENTERED SCHEDULER WITH PI IN PROGRESS>)
	MOVE P,PI7P		;SETUP LOCAL PDL
	CALL UPDTCK		;UPDATE TODCLK
SCH0:	XCT KEPALV		;DO KEEP ALIVE
	MOVE F,SCHFLG		;SETUP PERM FLAGS
	SKIPL FORKX		;FORK SETUP?
	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
	SKIPE PWRDWN		;POWER FAIL DETECTED?
	JRST SCHPRF		;YES
	SKIPN SHLTW
	SKIPE 1,SCTLW		;REQUEST FROM SWITCHES?
	CALL SWTST		;YES
	SKIPGE FX,FORKX		;JOB TO CONTINUE?
	CALL SKDJOB		;NO, GO SCHEDULE ONE
	JUMPL FX,SCDNUL		;RUN 'NULL' JOB IF NO FORK TO CONTINUE
	JSP 4,MTIME		;READ HIGH RESOLUTION CLOCK
	MOVEM T1,FKT0		;UPDATE IN CASE SCHED REENTERED
	MOVE 2,SKDLST		;GET LAST READING OF HP CLOCK
	MOVEM 1,SKDLST		;SET NEW LAST READING
	SUB 1,2			;TIME SPENT THIS PASS
	CAIGE T1,0		;OVERFLOW?
	ADD T1,BASOVV		;YES, ADD CORRECTION
	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
	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
	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 C1STAT		;DO STATISTICS
	CALL LV8CHK		;DO DEVICE-DEPENDENT THINGS
	CALL TTCH7		;TTY BIG BUFFER
	CALL REMFPB		;CHECK DELETED PAGE QUEUE
	CALL CLKCHK		;CHECK FORKS WAITING FOR CLOCK
	SKIPE PSKED		;RESCHEDULE REQUEST?
	CALL DISMSJ		;YES, FLUSH CURRENT FORK
	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(HLT,J0NRUN,<JOB 0 NOT RUN FOR TOO LONG, PROBABLE SWAPPING HANGUP>)
	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
	SETZM QSKED
	RET

PI7P::	IOWD NSKDP,SKDPDL

;STATISTICS - INTEGRALS COMPUTED FREQUENTLY

C1STAT:	MOVE T1,TODCLK		;COMPUTE ACTUAL TIME SINCE LAST UPDATE
	SUBM T1,TIM0
	EXCH T1,TIM0
	MOVE T2,SUMNR		;INTEGRATE SUMNR
	IMUL T2,T1
	ADDM T2,SNRSUM
	MOVE T2,NRPLQ		;INTEGRATE NRPLQ
	IMUL T2,T1
	ADDM T2,RPQSUM
	RET
;CHECK LOAD AVS AND LITES

SCLDAV:	MOVE 2,TODCLK
	SUBM 2,RJTTIM		;REAL TIME SINCE LAST UPDATE TO RJTSUM
	EXCH 2,RJTTIM
	MOVE T1,NGOJOB		;UPDATE NGOJOB INTEGRAL
	IMUL T1,T2
	ADDM T1,RJTSUM
	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
	MOVE 2,TODCLK
	CAML 2,RJATIM		;TIME FOR RJAV UPDATE?
	CALL DORJAV		;YES
	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
	FIXR T1,RJAV		;GET INTEGER 1 MIN AVERAGE
	MOVEM T1,IRJAV
	RET
;COMPUTE ONE SET AVERAGES
; T1/ INTEGRAL OVER LAST ONE SECOND
; T2/ TABLE TO BE UPDATED

DORJ1:	FLTR T1,T1		;FLOAT INTEGRAL
	FDVRI T1,(1000.0)	;DIVIDE BY 1 SECOND
	JOV .+1			;CLEAR OV FLAG
	MOVSI T3,-NRJAVS	;NUMBER ITEMS IN TABLE
	HRLI T2,T3+(IFIW)	;SETUP INDIRECT ADDRESS
SCHC1:	MOVE T4,EXPFF(T3)	;SUM = SUM*EXP(-T/C)
	FMPRM T4,@T2
	JOV [	SETZM @T2	;SET TO 0 IF UNDERFLOW
		JRST .+1]
	MOVE T4,T1		;SUM = TERM*(1-EXP(-T/C)) + SUM
	FMPR T4,EXPGF(T3)
	FADRM T4,@T2
	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

EXPGF:	EXP 0.0165285462	;C = 1 MIN
	EXP 0.00332778395	;C = 5 MIN
	EXP 0.00111049406	;C = 15 MIN
;TEST WORD DEPOSITED BY SWITCHES IN 20

SWTST:	SETZM SCTLW
	SKIPE SHLTW		;HALT REQUEST?
	JRST SWCRSH		;YES
	JFFO 1,.+1
	CAIGE 2,NSWTT
	XCT SWTT(2)
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
	SKIPN DDTPRS		;DDT LOADED?
	JRST SWHLT3		;NO
SWHLT4:	XCT CHKADR		;YES, GET BREAKPOINT
	JRST SCHED0		;RESUME SCHEDULER WHEN PROCEEDED

;POWER FAIL DETECTED

SCHPRF:	CALL DISMSJ		;FLUSH CURRENT FORK
	XCT PWRFLE		;DO ANY SPECIAL POWER FAIL CODE
	CALL CASHOF		;MAKE SURE MEMORY IS CORRECT
	JRST SCHPF0		;FINISH IN APRSRV
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
SWHLT3:	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(CHK,SRQOVF,<SCDRQ-SCHED REQUEST QUEUE OVERFLOW>)
	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
	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
/]]
	CALL TTABRT		;CONDITION LINE FOR TTEMES
	CALL TTEMES		;GIVE USER BAD NEWS
	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
	MOVEI 1,JSKP
	MOVEM 1,FKSTAT(FX)	;INIT STATUS
	MOVE 1,QUANTT
	STOR 1,FKQTM		;ESTABLISH QUEUE
	MOVE 1,TODCLK
	MOVEM 1,FKTIME(FX)
	MOVEI 1,0
	STOR 1,FKQN
	MOVSI 1,400000+NEWFKF
	MOVEM 1,FKINT(FX)	;LEAVE INTERRUPT REQUEST
	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:
;	SETZM SJOBD		;CLEAR JOB-NOW-RUNNING DISPLAY
SKDJ0:	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 GCCOR		;COLLECT CORE PAGES
SKDJ1:	SETZM PSKED
	HRRZ P1,BALLST		;GET LIST OF BALSET FORKS
SKCB2:	CAIN P1,BALLST		;END OF LIST?
	JRST BKGND1		;YES, NO RUNNABLE FORK
	SUBI P1,BSPT		;COMPUTE BALSET INDEX
	LOAD FX,BSFK		;GET FORK INDEX
	SKIPL BALSET(P1)	;RUNNABLE?
	JRST SKCB3		;YES
	CALL SKDJ3		;NO, TEST IT
	 JRST SKCB4		;STILL NOT RUNNABLE, STEP TO NEXT
SKCB3:	SKIPL T1,SSKED		;HAVE A NOSKED FORK?
	CAIN FX,0(T1)		;YES, IS THIS IT?
	JRST SKDJ2		;OK TO RUN THIS FORK
SKCB4:	HRRZ P1,BSPT(P1)	;GET NEXT FORK ON BALSET QUEUE
	JRST SKCB2
;HAVE RUNNABLE FORK - SET IT UP AND RUN IT

SKDJ2:	HRRZM FX,FORKX
	CALL SETPPG		;SETUP PAGER FOR THIS PROCESS
	HRRZS BALSET(P1)	;CLEAR ANY FLAGS
	LOAD T3,BSQTM		;SETUP QUANTUM FOR THIS RUN
	MOVEM T3,BSQNT
	SETZM FKT1		;CLEAR INCREMENTAL TIME
;	LOAD 1,FKQN		;QUEUE LEVEL OF FORK
;	HLRZ 2,FKJOB(FX)	;JOB NUMBER OF FORK
;	IOR 1,BITS(2)		;BIT POSITION DESIGNATES JOB NUMBER
;	MOVEM 1,SJOBD		;FORK NUMBER AND STATUS FOR LIGHTS
	CALLRET SETOVF		;IN APRSRV

;TEST FOR AJBALS NECESSARY BEFORE SELECTING FORK TO RUN

TSTBAL:	MOVE T1,SUMNR
	CAMLE T1,MAXNR		;BALSET OVERLOADED?
	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

;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
;ROUTINES TO MANIPULATE BALSET QUEUE

;REMOVE FORK FROM QUEUE
; P1/ BALSET INDEX

OFFBSQ:	HRRZ T1,BSPT(P1)	;GET FWD PTR
	HLRZ T2,BSPT(P1)	;GET BACK PTR
	HRLM T2,0(T1)		;MAKE NEXT POINT TO PREVIOUS
	HRRM T1,0(T2)		;MAKE PREVIOUS POINT TO NEXT
	MOVEI T1,BSPT(P1)	;MAKE PTR TO THIS
	CAMN T1,BALLS0		;WAS TAIL OF HIGH QUEUE?
	MOVEM T2,BALLS0		;YES, RESET TAIL TO PREVIOUS
	RET

;APPEND FORK TO QUEUE
; P1/ BALSET INDEX

ONBSQ:	HLRZ T2,BALLST		;GET END PTR
ONBSQ2:	MOVEI T1,BSPT(P1)	;CONSTRUCT PROPER POINTER
	HRRZ T3,0(T2)		;GET NEXT PTR
	HRRM T1,0(T2)		;MAKE PREVIOUS POINT TO THIS
	MOVEM T3,0(T1)		;STORE NEW PTR PAIR
	HRLM T2,0(T1)
	HRLM T1,0(T3)		;STORE NEW END PTR
ONBSQ1:	MOVE T3,SKDBQT		;GIVE FULL QUANT
	STOR T3,BSQTM
	RET

;APPEND FORK TO BALSET HIGH QUEUE
; P1/ BALSET INDEX

ONBSQ0:	MOVE T2,BALLS0		;GET HIGH QUEUE TAIL PTR
	CALL ONBSQ2		;INSERT FORK AT THAT POINT
	MOVEM T1,BALLS0		;UPDATE TAIL PTR
	RET

;PUT FORK AT TOP OF BALSET QUEUE

ONTBSQ:	MOVEI T2,BALLST		;PTR TO TOP
	JRST ONBSQ2		;GO INSERT AFTER THAT
;HERE TO FORCE UNLOAD OF BALSET AND COLLECT ALL OF MEMORY THAT
;ISNT ACTUALLY LOCKED

SKDJFC:	MOVE Q2,GOLST		;SETUP TO SCAN GOLST
SKJFC1:	JUMPE Q2,SKJFC2		;DONE?
	MOVEI FX,-FKPT(Q2)	;GET FORK INDEX
	HRRZ Q2,(Q2)		;DO CDR NOW, REMBS MAY REMOVE THIS FORK
	LOAD T1,FKLOC		;IS THIS FORK IN BALSET?
	CAIGE T1,NBP		; ???
	CALL REMBS		;YES - REMOVE FORK FROM BALSET
	JRST SKJFC1		;LOOP FOR ALL

;HERE WHEN BALSET UNLOADED, FORCE GCCOR TO FREE MEMORY

SKJFC2:	CALL GCCOR0		;GETS PRIVATE PAGES AND SPT PAGES
	CALL GCCOR0		;GETS MOST PAGE TABLES
	CALL GCCOR0		;SHOULD HAVE FREED ALL UNLOCKED MEMORY
	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:	TXZ FX,BSWTB		;CLEAR WAIT FLAG
	MOVEM FX,BALSET(P1)
	SOS NBWT		;NOW ONE LESS WAITING PROCESS
	MOVE 1,TODCLK		;COMPUTE LENGTH OF TIME WAITED
	SUB 1,NBW(P1)
	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
		JRST DISMT4]
	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 DISMT4		;NO, NO CHARGE TO QUANTUM
	ADDM 1,DSKWT		;CHARGE TO DSK
DISMT5:	TXNE F,SK%IOC		;QUANTUM CHARGE FOR IO?
	JRST DISMT4		;NO
	CAIL 1,5		;CHARGE MIN(5,ACTUAL)
	MOVEI 1,5
	IMULI 1,NTMS		;CONVERT TO HP UNITS
	ADDM 1,NBQ(P1)		;CHARGE AGAINST BALSET QUANTUM
	LOAD 3,FKQTM		;CHARGE AGAINST REGULAR QUANTUM
	SUB 3,1
	STOR 3,FKQTM
	LOAD T3,BSQTM		;AND BALSET QUANTUM
	SUB T3,T1
	STOR T3,BSQTM
DISMT4:	HRRZ 1,FKPGST(FX)
	CAIE 1,SWPINT		;WAS BEING LOADED?
	RETSKP			;NO, RETURN RUNNABLE
	SKIPN PRELDF		;YES, PRELOADING DESIRED?
	JRST SKDJS1		;NO
	HLRZ 1,FKWSP(FX)	;YES, ENOUGH CORE TO PRELOAD?
	CAMLE 1,NRPLQ
	JRST [	SKIPG IOIP	;NO, FREE PAGES ON THE WAY?
		JRST .+1	;NO, LOAD AS MUCH AS POSSIBLE NOW
		TXO FX,BSWTB	;YES, PUT FORK BACK INTO WAIT
		MOVEM FX,BALSET(P1)
		AOS NBWT	;COUNT IT
		MOVE 1,TODCLK	;RESET TIME OF START OF WAIT
		MOVEM 1,NBW(P1)
		AOS CGFLG	;SAY WE NEED CORE
		JRST SKDJW]
	CALL PRELD		;PRELOAD WS
SKDJS1:	CALL SOSNEB		;PROCESS FINISHED ENTERING BALSET
	RETSKP			;RETURN RUNNABLE

SKDJW:	RET			;RETURN NOSKIP, FORK STILL WAITING
;UPDATE FOR PROCESS FINISHED ENTERING BALSET

SOSNEB:	HLRZ 1,FKWSP(FX)	;PRELOAD SIZE AS DETERMINED BY LDJOB
	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 DISMT3		;YES
	HLRZ T1,FKPGST(FX)	;GET TIME PARAMETER FOR BLOCKW
	JSP 4,BLOCKW		;SEE IF GRACE PERIOD OVER
	 JRST DISMT1		;NO
	CALL DISMT2		;YES, REMOVE FORK FROM BALSET
	JRST SCHED0		;RESET STACK AND RESTART SCHED SELECTION

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)
	JRST DISMT3		;LET IT RUN

;REMOVE HOLDING FORK FROM BALSET AND PUT IT ON WTLIST
; 10/ BALSET INDEX
; FX/ FORK INDEX

DISMT2:	PUSH P,NBW(P1)		;SAVE TIME THAT WAIT STARTED
	MOVE 1,TODCLK		;FINISH REMOVAL FROM BALSET
	SUB 1,NBW(P1)		;ACCOUNT WAITING TIME
	ADDM 1,BSWT
	CALL REMBSJ		;REMOVE JOB FROM BAL SET
	HRRZ 1,FKCNO(FX)	;CORE NUMBER
	MOVE 1,BITS(1)		;PROCESS USE BIT
	IORM 1,PUBCL		;CLEAR BIT AT NEXT GC
	CALL GLREM		;REMOVE FORK FROM GOLST
	POP P,FKPGST(FX)	;SAVE TOD OF DISMISS FOR NEWST
	CALL WTCON2		;PUT ON WAIT LIST
	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

;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 MAXHQP,1			;CURRENT MAX HQ PAGES
RS MAXLQP,1			;CURRENT MAX LQ PAGES

RS MAXHQR,1			;MAX HQ RESERVE
RS MAXLQR,1			;MAX LQ RESERVE

RS NXTAJB,1			;TIME NEXT AJBALS DUE

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

AJBALS:	TRVAR <BSHC1,AJLODN,AJBLFK>
	;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
	SETZM AJLODN		;NUMBER FORKS LOADED ON THIS CALL
	SETZM AJBNHQ		;INIT VARIABLES
	SETZM AJBNLQ
	SETZM AJBHQP
	SETZM AJBLQP
	SETOM AJBLFK
	FIXR T1,HQLAV		;COMPUTE CURRENT PARTITION,
	IMUL T1,NHQR		;CONSTANT TIMES 1 MIN HQ LOAD AV
	CAMLE T1,MAXHQR		;ABOVE LIMIT?
	MOVE T1,MAXHQR		;YES
	TXNE F,SK%HQR		;USE HQ RESERVE?
	MOVEI T1,0		;NO
	SUB T1,MAXNR		;COMPUTE MAXNR MINUS HQ RESERVE
	MOVNM T1,MAXLQP		;THAT IS LQ LIMIT
	MOVE T1,NLQFK		;GET CURRENT NUMBER COMPUTE FORKS
	IMUL T1,NLQR		;CONSTANT PER FORK
	CAMLE T1,MAXLQR		;ABOVE LIMIT?
	MOVE T1,MAXLQR		;YES
	TXNN F,SK%LQR		;USE LQ RESERVE?
	MOVEI T1,0		;NO
	SUB T1,MAXNR		;COMPUTE MAXNR MINUS LQ RESERVE
	MOVNM T1,MAXHQP		;THAT IS HQ LIMIT
	SETZM BSKED
	SETZ Q1,			;INIT NBP COUNT
	MOVE 4,BALSHC		;INIT SUMNR COUNT
	MOVEM T4,BSHC1		;SAVE, BALSHC MAY CHANGE AT INT LEVEL
	ADDI T4,BSPAD		;INCLUDE PAD
	MOVX 3,BSHLD
	SKIPL FX,SSKED		;NOSKED FORK?
	JRST [	LOAD 1,FKWSS	;YES, IS FIRST PRIORITY
		ADDM 1,4	;CHARGE SIZE
		CALL AJBUQS	;UPDATE QUEUE SUMS
		AOJA Q1,.+1]
	MOVE FX,GOLST		;SETUP TO SCAN BALSET FOR HOLDING FORKS
	MOVE Q2,NBPROC
	JUMPE Q2,AJBAL4
AJBAL2:	SUBI FX,FKPT		;GET FORK INDEX
	LOAD P1,FKLOC
	CAIL P1,NBP		;FORK IN  BALSET
	JRST [	HRRZ FX,FKPT(FX) ;NO
		JRST AJBAL2]
	CAMN FX,SSKED
	JRST AJBAL3		;BYPASS NOSKED FORK
	ANDCAM 3,BALSET(P1)	;CLEAR HOLD FLAG
	SKIPL NBQ(P1)		;USED BALSET QUANTUM?
	JRST AJBAL3		;YES, NO SPECIAL CONSIDERATION
	LOAD 1,FKWSS		;NO, KEEP FORK
	ADDM T1,T4		;COMPUTE SUM
	CAMLE T4,MAXNR		;FORK FITS?
	CALL AJBSHK		;NO, TRY TO SHRINK IT
	MOVEM FX,AJBLFK		;REMEMBER LAST FORK
	ADDI Q1,1		;COUNT BALSET PROCESSES
	CALL AJBUQS		;UPDATE QUEUE SUMS
	IORM 3,BALSET(P1)	;FLAG HOLDING
AJBAL3:	HRRZ FX,FKPT(FX)	;GET NEXT FORK
	SOJG Q2,AJBAL2		;COUNT BALSET FORKS SEEN
	; ..
;HAVE NOW NOTED FORKS WHICH MUST STAY IN BALSET BY REASON OF
;BEING NOSKED OR RECENTLY LOADED INTO BALSET.  NOW RESCAN GOLIST
;CHECKING ALL FORKS NOT ALREADY DECIDED UPON, AND REMOVE, LOAD,
;OR LEAVE ALONE AS APPROPRIATE.

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
	CAIE P2,MAXQ		;HIGH QUEUES?
	TDZA P2,P2		;YES, USE 0 INDEX
	MOVEI P2,1		;NO, USE 1 INDEX
	LOAD 1,FKLOC		;SEE WHERE FORK IS
	CAIL 1,NBP		;IN BALSET?
	JRST AJBAL5		;NO
	MOVE 1,BALSET(1)
	TXNE 1,BSNSK+BSHLD	;NOSKED OR HOLDING?
	JRST [	CAMLE T4,MAXNR	;YES, HOLDING FORKS OVER LIMIT?
		CALL AJBSHK	;YES, TRY TO SHRINK THIS FORK
		JRST AJBAL1]	;CONTINUE
AJBAL8:	JUMPE Q1,AJBAL7		;NO FURTHER CHECKS IF FIRST FORK SEEN
	;CALL AJBCQS		;IS FORK BEYOND LIMIT OF PARTITON?
	;JUMPE T1,AJBAL9		;FLUSH IT IF SO
	LOAD 1,FKWSS
	ADD 1,4
	SUBI T1,BSPADO		;REDUCE BY PAD OFFSET
	CAMG Q1,MAXBP		;FORK STILL FITS IN BALSET?
	CAMLE 1,MAXNR
	JRST AJBAL9		;NO
AJBAL7:	LOAD T1,FKWSS		;GET SIZE
	ADDM T1,4		;UPDATE SUM
	CALL AJBUQ0		;UPDATE QUEUE SUMS
	AOJA Q1,AJBAL1		;COUNT FORK

AJBAL9:	LOAD T1,FKWSS		;GET WORKING SET SIZE
	LOAD T2,FKCSIZ		;AND CURRENT SIZE
	ADDI T2,2		;PLUS SMALL ALLOWANCE
	CAMG T1,T2		;RESERVE MUCH GREATER THAN CURRENT SIZE?
	JRST AJBL12		;NO, REMOVE FORK
	SUB T2,T1		;YES, REDUCE RESERVE
	ADDM T2,FKNR(FX)
	ADDM T2,SUMNR
	JRST AJBAL8		;NOW MAYBE FORK WILL FIT

AJBL12:	HRRZ Q2,0(Q2)		;STEP NOW IN CASE REMBS DIDDLES GOLST
	PUSH P,T4		;PRESERVE TEMP
	CALL REMBS		;REMOVE FORK
	POP P,T4
	TXO F,AJBYPF		;NOTE PASSED A FORK NOT IN BALSET
	JRST AJBL10
;FORK NOT NOW IN BALSET

AJBAL5:	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
	CALL AJBCQS		;CHECK FORK AGAINST QUEUE SUMS
	JUMPE T1,AJBL11		;CAN'T LOAD IT
	;SKIPE NEBAL		;ALREADY A FORK ENTERING BALSET?
	;JRST AJBL11		;YES, DON'T START ANOTHER ONE
AJBAL6:	CALL [	SAVEAC <T4>	;SAVE TEMP
		CALLRET LOADBS]	;LOAD FORK
	 JRST AJBL11		;COULDN'T LOAD, RPLQ INSUFFICIENT
	AOS AJLODN		;COUNT FORKS LOADED
	LOAD P1,FKLOC		;GET BALSET INDEX
	TXNE F,AJBYPF		;PREVIOUS FORK NOT LOADED?
	SETZM NBQ(P1)		;YES, GIVE NO HOLD QUANTUM
	LOAD 1,FKWSS		;GET SIZE (MAY HAVE CHANGED IN LOADBS)
	ADDM 1,4		;UPDATE BALSET SUM
	CALL AJBUQ0		;UPDATE QUEUE SUMS
	AOJA Q1,AJBAL1		;COUNT BALSET FORK

AJBL11:	TXO F,AJBYPF		;NOTE PASSED A FORK NOT IN BALSET
	JRST AJBAL1

;UPDATE RUNNING QUEUE SUMS

AJBUQS:	LOAD P2,FKQN		;SET QUEUE SET INDEX
	CAIE 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

;TRY TO SHRINK FORK SO BALSET MAX NOT EXCEEDED

AJBSHK:	LOAD T1,FKWSS		;GET CURRENT SIZE
	LOAD T2,FKCSIZ		;GET ACTUAL SIZE
	SUBM T1,T2		;COMPUTE DIFFERENCE
	MOVE T1,T4		;GET BALSET SIZE
	SUB T1,MAXNR		;COMPUTE OVERAGE
	CAMLE T1,T2		;GET MINIMUM
	MOVE T1,T2
	MOVN T1,T1		;REDUCE FORK SIZE BY MIN
	ADDM T1,FKNR(FX)
	ADDM T1,SUMNR		;ADJUST OTHER VARIABLES ACCORDINGLY
	ADDM T1,T4
	RET
;CHECK FOR FORK WITHIN LIMITS FOR QUEUE

AJBCQS:	LOAD T1,FKWSS		;GET SIZE OF FORK
	ADD T1,AJBHQP(P2)	;COMPUTE TOTAL FOR GROUP
	SKIPE AJBNHQ(P2)	;FIRST FORK?
	CAMGE T1,MAXHQP(P2)	;OR WITHIN LIMIT?
	JRST RTRUE		;YES, OK
	JRST RFALSE		;NO, DON'T LOAD

AJBALX:	SUBI T4,BSPADO		;REDUCE BY PAD OFFSET
	CAMLE T4,MAXNR		;HOLDING FORKS STILL OVER MAX?
	JRST [	CAILE Q1,1	;MORE THAN ONE FORK IN BALSET?
		SKIPGE FX,AJBLFK	;YES, REMOVE LAST ONE
		JRST .+1		;WASN'T ONE
		LOAD T1,FKWSS
		SUB T4,T1	;ADJUST BALSET TOTAL
		PUSH P,T4	;SAVE TEMP
		CALL REMBS
		POP P,T4
		JRST .+1]
	SUB T4,BSHC1		;ADJUST IN CASE BALSHC CHANGED
	PIOFF
	ADD T4,BALSHC
	MOVE T3,SUMNR		;USE CONSISTENT BALSHC AND SUMNR
	PION
	CAIN T4,BSPAD-BSPADO(T3) ;BALSET SUM AGREES? (ADJUSTING FOR PAD)
	JRST AJBALY		;YES, DONE
	BUG(CHK,SUMNR1,<AJBALS-SUMNR INCORRECT>)
	MOVEM 4,SUMNR		;FIX SUMNR
AJBALY:	MOVE T1,TODCLK		;SET TIME FOR NEXT PERIODIC CALL
	ADD T1,AJBLCY
	MOVEM T1,NXTAJB
	MOVE T1,AJLODN		;RETURN COUNT OF FORKS LOADED THIS CALL
	RET

;REMOVE SELECTED FORK FROM BALSET IF POSSIBLE

REMBS:	LOAD P1,FKLOC
	MOVE 1,BALSET(P1)
	AOS NREMJ		;COUNT FORCED REMOVALS
	JXE T1,BSWTB,REMS1	;JUMP IF FORK NOT IN BALSET WAIT
	SOS NBWT		;COUNT ONE LESS WAITING FORK IN BALSET
	HRRZ 1,FKPGST(FX)	;GET WAIT TEST ROUTINE ADR
	CAIN 1,DISMT		;HOLD DISMISS?
	JRST [	CALLRET DISMT2]	;YES, REMOVE AND PUT ON WTLST
	CAIN 1,SWPINT		;FORK WAS ENTERING BALSET?
	CALL SOSNEB		;YES, UNDO ENTERING STUFF
REMS1:	CALLRET REMBSF		;REMOVE FORK

;MAINTAIN INTEGRAL NBPROC DT

BSMEAS:	MOVE 1,TODCLK
	SUBM 1,BSCTIM		;DT - TIME SINCE LAST UPDATE
	EXCH 1,BSCTIM
	IMUL 1,NBPROC		;NBPROC * DT
	ADDM 1,BSTSUM
	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
	LOAD Q1,FKLOC		;GET CURRENT LOCATION
	CAIGE Q1,NBP		;IN BALSET?
	JRST CHKTF1		;YES, SKIP IT
	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

TRYLDF:	SKIPG T2,NBPROC		;BALSET NOW EMPTY?
	JRST TRYLD1		;YES, LOAD FORK
	LOAD T1,FKWSS		;GET WS SIZE
	ADDI T1,BSPAD+BSPADO	;INCREASE BY PAD AND OFFSET
	ADD T1,SUMNR		;COMPUTE BALSET SIZE WITH FORK
	CAMGE T2,MAXBP		;BALSET SIZE WITHIN LIMITS?
	CAML T1,MAXNR
	RET			;NO, DON'T LOAD
TRYLD1:	CALL LOADBS		;YES, LOAD
	 RET			;COULDN'T
	RETSKP			;DONE
;REMOVE FORK FROM BALANCE SET

REMBSJ:	SETO 3,			;FLAG VOLUNTARY REMOVAL FOR POSTPG
	AOSA BSKED		;FLAG VOLUNTARY REMOVAL FOR AJBALS
REMBSF:	SETZ 3,			;FLAG FORCED REMOVAL FOR POSTPG
	SAVEAC <P1>
	LOAD P1,FKLOC		;GET BALSET INDEX
	LOAD T2,FKWSS		;GET CURRENT RESERVE
	MOVN 1,2
	ADDM 1,SUMNR		;REDUCE BALSET SIZE
	JUMPE T3,REMBS5		;NO CHANGE TO WSS IF FORCED DISMISS
	LOAD T4,FKCSIZ		;GET CURRENT SIZE
	ADDI T4,4		;COMPUTE NEW WS ESTIMATE
	CAMGE T4,T2		;LARGER THAN CURRENT WS ESTIMATE?
	STOR T4,FKWSS		;NO, USE NEW ONE
REMBS5:	MOVE 1,3		;PASS FLAG TO POSTPG
	CALL POSTPG		;CHECK WS WORDS, ETC.
	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
	CALL OFFBSQ		;REMOVE FROM BALSET QUEUE
	MOVSI 2,(-PLKV)
	HRRZ 1,FKPGS(FX)
	HRRZ 1,SPT(1)
	ADDM 2,CST1(1)		;UNLOCK PSB
	LOAD T1,FKJSB		;UNLOCK JSB
	HRRZ T1,SPT(T1)
	ADDM T2,CST1(T1)
	HLRZ 1,FKPGS(FX)
	HRRZ 1,SPT(1)
	ADDM 2,CST1(1)		;UNLOCK PT
	LOAD T1,FSSPTN		;GET STACK PAGE I.D.
	HRRZ T1,SPT(T1)
	ADDM T2,CST1(T1)	;UNLOCK THE PAGE
	MOVEI 1,GOLST
	STOR 1,FKLOC		;SET FORK LOCATION TO GOLST
	HRRZ 1,FKCNO(FX)	;CORE NUMBER ASSIGNED?
	JUMPE 1,REMBS4
	HRRZ 2,FKWSP(FX)	;AND NO PAGES IN USE?
	JUMPN 2,REMBS4
	MOVE 1,BITS(1)		;DEASSIGN CORE NUMBER
	IORM 1,FRECB
	HLLZS FKCNO(FX)
REMBS4:	SETOM REMFGS		;NOTE FORK REMOVAL FOR GCCOR, ETC.
	SETOM BALSET(P1)	;SET PROCESS WORD TO EMPTY
	LOAD T2,FKQN		;GET FORK QUEUE LEVEL
	CAIE T2,MAXQ		;LOW Q?
	SOSA BSHQN		;NO, COUNT IN HIGH Q TOTAL
	SOS BSLQN
	CALL BSMEAS		;UPDATE MEASUREMENTS
	SOSG NBPROC		;BALSET NOW EMPTY?
	CALL REMBSB		;YES, CHECK SUMNR
	MOVE 1,FBALS
	CAIN 1,1(P1)		;RELEASED LAST WORD?
	JRST REMBS3		;YES, GO ADJUST LIMITS OF TABLE
REMBS2:	RET
;REMBSJ...

REMBS3:	SETO 1,
REMBS1:	SOS 2,FBALS		;ADJUST END OF TABLE POINTER
	JUMPE 2,REMBS2		;DONE IF TABLE NOW EMPTY
	CAME 1,BALSET-1(2)	;LAST ENTRY EMPTY?
	JRST REMBS2		;NO
	JRST REMBS1		;YES, KEEP CHECKING

REMBSB:	PIOFF			;ENSURE CONSISTENT BALSHC AND SUMNR
	MOVE 1,BALSHC
	CAME 1,SUMNR		;SUMNR CORRECT?
	BUG(CHK,SUMNR2,<SUMNR INCORRECT>)
	MOVEM 1,SUMNR
	PION
	RET
;MOVE FORK INTO BALANCE SET

LOADBS:	SAVEAC <P1>
	SKIPL SPMLCK		;SOMEONE TRYING TO GET A PAGE?
	JRST [	CALL TSTFRP	;YES. SEE IF THIS FORK IS GUILTY
		 JRST LDJB66	;IT IS. DON'T LOAD IT
		JRST .+1]	;NO. LOAD IT
LDJB6:	MOVE 3,NRPLQ
	CAIGE 3,MINNR		;ENOUGH FOR REQUIRED PAGES?
LDJB66:	JRST [	AOS BSKED	;NO, REQUEST ANOTHER BALSET SCAN SOON
		RET]		;RETURN WITHOUT LOADING FORK
	SETZ P1,		;SETUP TO FIND FREE BALSET SLOT
	SETO 1,
LDJB2:	CAML P1,FBALS		;END OF TABLE?
	JRST [	CAIL P1,NBP	;ROOM IN BALSET TABLE?
		JRST [	AOS BSKED ;NO, REQUEST ANOTHER SCAN
			RET]
		AOS FBALS
		JRST LDJB4]	;YES, USE NEXT SLOT
	CAME 1,BALSET(P1)	;DELETED ENTRY?
	AOJA P1,LDJB2		;NO, KEEP LOOKING
LDJB4:	HRRZ 2,FKCNO(FX)
	JUMPN 2,LDJB3		;CHECK FOR CORE NUMBER ASSIGNED
	MOVE 2,FRECB		;ASSIGN ONE
	JFFO 2,.+2
	MOVX T3,<POS(PUFLD)>	;NONE LEFT, USE LAST ONE AGAIN
	MOVE 2,BITS(3)
	ANDCAM 2,FRECB
	HRRM 3,FKCNO(FX)
LDJB3:	HRRZ T2,FKCNO(FX)	;GET CORE NUMBER
	MOVE T2,BITS(T2)	;EQUIVALENT BIT
	ANDCAM T2,PUBCL		;CLEAR 'REMOVED' BIT
	MOVEM FX,BALSET(P1)	;YES, STORE FORK INDEX IN SLOT
	STOR P1,FKLOC		;FKLOC IS NOW BALSET SLOT
	CALL BSMEAS
	AOS NBPROC		;COUNT NUMBER OF PROCESSES
	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
	SUBI 1,0(2)
	HRLM 1,FKWSP(FX)	;AMOUNT OF REPLACABLE PAGES TO BE HELD
	ADDM 1,NRPMIN		;ON REPLACABLE QUEUE
	AOS NEBAL		;COUNT ENTERING PROCESSES
   REPEAT 0,<
	LOAD 1,FKWSS		;GET WS SIZE
	IMUL 1,BSQPP		;GIVE QUANTUM PER PAGE
	CAMLE 1,BSQMAX		;BUT ONLY UP TO MAX
	MOVE 1,BSQMAX
   >
   REPEAT 1,<
	LDB T1,[POINTR F,SK%HTF] ;GET HOLD TIME CONTROL
	MOVE T1,[^D20000*NTMS	;SELECT VALUE
		^D5000*NTMS
		^D1000*NTMS
		0](T1)
   >
	MOVNM 1,NBQ(P1)		;QUANT GUARANTEED BEFORE FORCED OUT
	LOAD T1,FKQN		;GET QUEUE NUMBER
	TXNE F,SK%BQE		;HIGH BALSET QUEUE FOR ENTERING FORKS?
	CAIL T1,MAXQ		;ON HIGH QUEUES?
	JRST [	CALL ONBSQ	;NO, APPEND TO BALSET QUEUE
		JRST LDJB7]
	CALL ONBSQ0		;YES, APPEND TO BALSET HIGH QUEUE
LDJB7:
	; ..
;MOVE FORK INTO BALSET ...

	LOAD T1,FKJSB		;GET JSB INTO CORE
	CALL SWPIN0
	HRRZ 1,FKPGS(FX)	;GET PSB INTO CORE
	CALL SWPIN0
	HLRZ 1,FKPGS(FX)
	CALL SWPIN0
	LOAD T1,FSSPTN		;GET STACK PAGE I.D.
	CALL SWPIN0		;SWAP IT IN AS WELL
	MOVEI 1,SWPINT
	MOVEM 1,FKPGST(FX)	;SET TEST TO WAIT FOR PSB AND PT
	MOVX T1,BSWTB
	HLLM 1,BALSET(P1)
	AOS BSWT		;COUNT WAITING BALSET PROCESS
	MOVE 1,TODCLK
	MOVEM 1,NBW(P1)		;TIME THAT WAIT STARTED
	LOAD T2,FKQN		;GET FORK QUEUE LEVEL
	CAIE T2,MAXQ		;LOW Q?
	AOSA BSHQN		;NO, COUNT IN HIGH Q TOTAL
	AOS BSLQN
	RETSKP

;HANDLE BAD FKCSIZ - THIS IS NEEDED BECAUSE OF A BUG SOMEWHERE WHICH
;OCCASIONALLY CAUSES FKCSIZ TO DISAGREE WITH THE ACTUAL NUMBER OF
;PAGES ASSIGNED.  THIS PREVENTS THE SCHEDULING HANG WHICH WOULD
;OTHERWISE RESULT.

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(CHK,FKWSP1,<LOADBS-UNREASONABLE FKWSP>,<T1,T2,T3>)
	STOR T2,FKCSIZ		;FIX COUNT
	CAMGE T1,T2		;NOW LOOKS OK?
	MOVE T1,T2		;NO, RESET FKWSS ALSO
	STOR T1,FKWSS
	JRST LDJB5		;NOW...
;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

;UPDATE QUEUE NUMBER AND TIME USED VALUE

SAVRT:	CALL UCLOCK		;UPDATE CLOCKS
	MOVE T1,FKT1		;GET TIME USE SINCE SETRT
	SETZM FKT1
	LOAD P1,FKLOC		;UPDATE BALSET HOLD QUANTUM
	LOAD T2,FKQN		;ACCUMULATE QUEUE DISTRIBUTION
	ADDM T1,QSUM(T2)	; STATISTICS
	ADDM 1,USRTIM		;ACCUMULATE TOTAL USER TIME
	IMULI T1,NTMS		;CONVERT TO HP UNITS
	ADDM T1,NBQ(P1)		;CHARGE BALSET HOLD TIME
	MOVE T1,BSQNT		;GET REMAINING BALSET QUANTUM
	LOAD T2,BSQTM		;GET BALSET QUANT AT LAST SETRT
	SUBM T1,T2		;COMPUTE DIFFERENCE
	OPSTRM <ADDM T2,>,FKQTM	;UPDATE REGULAR QUANTUM
	STOR T1,BSQTM		;SAVE BALSET QUANTUM
	JUMPG T1,SAVRT1		;JUMP IF QUANTUM NOT EXHAUSTED
	CALL OFFBSQ		;BALSET QUANTUM EXHAUSTED, REMOVE FROM QUEUE
	LOAD T1,FKQN		;GET SCHED QUEUE NUMBER
	TXNE F,SK%BQR		;USING HIGH BALSET QUEUE?
	CAIL T1,MAXQ		;FORK ON INTERACTIVE QUEUES?
	JRST [	CALL ONBSQ	;USE REGULAR BALSET QUEUE
		JRST SAVRT1]
	CALL ONBSQ0		;USE BALSET HIGH QUEUE
SAVRT1:	LOAD T1,FKQTM		;GET REAMINING QUANTUM
	JUMPG T1,R		;DONE IF NOT EXHAUSTED
	AOS BSKED		;EXHAUSTED, REQUEST ADJUST OF BALSET
	CALL GLREM		;REMOVE FROM GOLST WHILE CHANGING QUEUE
	LOAD T2,FKQN		;GET CURRENT QUEUE NUMBER
	SKIPE JOBBIT		;SPECIAL PRIORITY?
	JRST [	LDB 3,[POINT 7,JOBBIT,17] ;GET RUNTIME GUARANTEE
		JUMPN 3,RTG1	;DO SOMETHING ABOUT IT IF NON-0
		LDB 3,[POINT 6,JOBBIT,35] ;GET SPECIAL MAXQ
		JUMPE 3,.+1	;IF 0 THEN NOT THIS FACILITY
		CAIGE 2,-1(3)	;REACHED SPECIAL MAXQ?
		JRST .+1	;NO
		LDB 2,[POINT 6,JOBBIT,29] ;YES, GET NEW Q
;		MOVEM FX,SPRIJD	;NOTE FORK USING PRIORITY
		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
	CALL GOCONC		;PUT FORK BACK ON GOLST
	RET
;RUNTIME GUARANTEE CONTROL - COMPUTE RUNTIME/ELAPSED, COMPARE WITH
;DESIGNATED CPU FRACTION.  RAISE OR LOWER SCHEDULER PRIORITY AS
;NECESSARY.

;LOWQT - CONTROLS INTERVAL OVER WHICH TIME IN GUARANTEED

LOWQT==^D10000

RTG1:	MOVE 1,JOBNO
	SKIPN JOBCK0		;GUARANTEE WORDS INIT'ED?
	JRST [	MOVE 3,TODCLK	;INITIALIZE TIME QUARANTEE WORDS
		MOVEM 3,JOBCK0
		MOVE 3,JOBRT(1)
		MOVEM 3,JOBCK1
		JRST RTG3]
SAVRT7:	LDB 3,[POINT 7,JOBBIT,17] ;GET GUARANTEE PERCENTAGE
	JUMPE 3,SAVRT8		;NOT SPECIAL
;	HRLM 1,SPRIJD		;SAVE JOB NUMBER FOR LIGHTS WATCHERS
	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,3		;EXPECTED REAL TIME
	SUB 4,1			;EXCESS OR DEFICIT OF REAL TIME
;	HRRM 4,SPRIJD		;FOR LIGHT WATCHERS
	CAIL 4,LOWQT/2		;ACCUMULATED REASONABLE EXCESS?
	JRST SAVRT5		;YES, REDUCE PRIORITY
RTG3:	LDB T3,[POINT 7,JOBBIT,17] ;GET PERCENTAGE
	IMUL T3,NBPROC		;GIVE BALSET QUANTUM PROPORTIONAL TO NBPROC
	IMUL T3,SKDBQT		;AND DESIRED PERCENTAGE
	IDIVI T3,^D100
	STOR T3,BSQTM
	MOVEI 2,0		;KEEP ON QUEUE 0 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
	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
	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
	ADDB 1,PGTIM		;CORE MGT CLOCK
	CAIGE 1,AGTICK		;TIME TO TICK AGE CLOCK?
	RET			;NO
	SETZM PGTIM		;YES, RESET CLOCK
	MOVE 2,FORKX
	LDB 1,[POINT 9,FKNR(2),17] ;CURRENT AGE
	ADDI 1,1		;TICK
	TRNE 1,777000		;OVERFLOW 9 BIT FIELD?
	SUBI 1,1000-100		;YES, WRAPAROUND
	DPB 1,[POINT 9,FKNR(2),17] ;SET NEW AGE
	CALL LDAGER		;LOAD NEW AGE INTO PAGER
	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]
	CAIN 1,FRZWT		;FREEZE?
	JRST [	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?
	JRST .+2
	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,FKLOC		;REMEMBER WHICH LIST
	MOVEI 1,FKPT(FX)	;PUT FORK ON PROPER LIST
	EXCH 1,0(2)
	HRRM 1,FKPT(FX)
	MOVEI 1,WTLST
	HRLM 1,FKPT(FX)
	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>
	HLRZ 1,FKPT(FX)
	CAIE 1,WTLST		;ON SOME WAITLIST?
	JRST UNBLK3		;NO
	LOAD 1,FKLOC		;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::	SAVEAC <T1>		;PRESERVE ALL WORK REGS
	HLRZ T1,FKPT(FX)	; Is fork on some kind of wait list?
	CAIN T1,WTLST		; ...
	  RETSKP
	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
	HLRZ 1,FKPT(FX)
	CAIE 1,WTLST		;ON SOME WAITLIST?
	JRST UNBF1		;NO, IGNORE CALL
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
	HLRZ 1,FKPT(FX)
	CAIE 1,WTLST		;ON SOME WAITLIST?
	JRST UBBAD		;NO
	LOAD 1,FKLOC		;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(CHK,UNBFNF,<UNBLK1 - FORK NOT FOUND>)
	JRST UNBLK3
;WAKEUP SUPERIOR, E.G. ON FORK SUSPENSION
;	CALL WAKSUP

WAKSUP:	SAVEAC <FX>
	HRRZ T1,FORKN		;GET SUPERIOR
	JUMPE T1,R		;RETURN IF TOP FORK
	ADD T1,SUPERP
	LDB T1,T1
	HRRZ FX,SYSFK(T1)
	HLRZ T1,FKPT(FX)
	CAIN T2,WTLST		;WAITING?
	CALL UNBLK1		;YES, WAKE IT
	RET

;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
	HLRZ T1,FKPT(FX)	;GET CURRENT FORK QUEUE
	CAIE T1,WTLST		;ON THE WAIT LIST?
	JRST UNBF1		;NO. ALL DONE THEN
	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:	SAVEAC <FX>
	HLRZ FX,FKSTAT(FX)	;GET SUPERIOR FORK INDEX
SUPUB1:	LOAD 1,FKLOC		;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,0(P)		;WAITING FOR THIS ONE?
SUPU1:	CALL UNBLK1		;YES, WAKE IT
SUPUX:	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

;TEST ALL NON-SPECIAL WAITING FORKS

WTCHK::	MOVEI Q2,WTLST		;HEAD OF WAITING LIST
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,[MOVEI T1,^D300	;DONE, RESET CLOCK
		MOVEM T1,WTTIM
		RET]
	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
	FSKED			;NOTE FORK NOW UNBLOCKED
	CALL NEWST		;ESTABLISH NEW QUEUE STATUS
	CALL GOCONC		;PUT ON READY LIST
	MOVEI 1,GOLST
	STOR 1,FKLOC
	CALL TRYLDF		;PUT FORK INTO BALSET IF POSSIBLE
	 NOP
	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>
	MOVEI 2,GOLST
	MOVSM 2,FKPT(FX)	;NOTE WHERE FORK IS
	CALL CORFCT		;COMPUTE IS PRIORITY VALUE
	PUSH P,FX
	PUSH P,1		;REMEMBER IT
	MOVEI 3,GOLST
GOC1:	HRRZ Q2,0(3)		;GET NEXT FORK ON LIST
	JUMPE Q2,GOC2		;END OF LIST?
	MOVEI FX,-FKPT(Q2)	;GET FORK INDEX (.. -FKPT(Q2) )
	CALL CORFCT		;GET PRIORITY OF THIS FORK
	CAML 1,0(P)		;BETTER THAN FORK TO BE ADDED?
	JRST GOC2		;NO, INSERT FORK HERE
	MOVEI 3,0(Q2)		;YES, KEEP SCANNING
	JRST GOC1

GOC2:	POP P,1
	POP P,FX
	MOVEI 1,FKPT(FX)	;PUT FORK INTO LIST
	HRRM 1,0(3)
	HRRM Q2,FKPT(FX)
	AOS NGOJOB		;KEEP COUNT OF READY JOBS
	LOAD T3,FKQN		;UPDATE QUEUE COUNTS
	CAIE T3,MAXQ
	AOSA NHQFK
	AOS NLQFK
	LOAD Q2,FKLOC
	CAIL Q2,NBP		;FORK IN BALSET?
	JRST GOC3		;NO
	CAIE T3,MAXQ		;YES, UPDATE BALSET QUEUE COUNTS
	AOSA BSHQN
	AOS BSLQN
GOC3:	RET
;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,FKQN		;UPDATE QUEUE COUNTS
	CAIE Q1,MAXQ
	SOSA NHQFK
	SOS NLQFK
	LOAD Q2,FKLOC
	CAIL Q2,NBP		;FORK IN BALSET?
	JRST GLREM3		;NO
	CAIE Q1,MAXQ		;YES, UPDATE BALSET QUEUE COUNTS
	SOSA BSHQN
	SOS BSLQN
GLREM3:	SETZM FKPT(FX)
	RET

GLREM2:	BUG(HLT,GLFNF,<GLREM - FORK NOT FOUND>)

JSKP::	JRST 1(4)
JRET::	JRST 0(4)

;COMPUTE PRIORITY NUMBER FOR FORK

CORFCT:	MOVE 1,FKTIME(FX)	;TIME ON CURRENT QUEUE
	SUB 1,TODCLK		;NEGATIVE OF INTERVAL ON CURRENT QUEUE
	JUMPG 1,[MOVSI 1,(1B5)	;NOT YET TIME TO RUN, RETURN VERY LOW
		RET]		;PRIORITY NUMBER
	LOAD 2,FKQN
	ADD 1,TBASE(2)		;ADD BASE FOR THE QUEUE
	RET
;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

QUANTT:	300*NTMS
	2000*NTMS
	2000*NTMS
LQUANT:	4000*NTMS
NQUEUE==:.-QUANTT		;NUMBER OF QUEUES
MAXQ==:NQUEUE-1			;NUMBER OF MAXIMUM QUEUE

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

	RADIX 8

RS QSUM,NQUEUE			;ACCUMULATED RUNTIMES OF QUEUES

;<QUEUE NUMBER>B8+77...77

TBASE:	XX==0
   REPEAT NQUEUE,<
	<XX+1>B8-1
	XX=XX+1>
;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
	IMULI 1,NTMS		;CONVERT TO HIGH PRECISION UNITS
	TXNE F,SK%WCF		;USE LOAD AV PROPORTIONALITY?
	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		;GIVE TTY PREFERENCE?
	CAMGE 1,[^D1000*NTMS]	;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
	JUMPE 2,R		;NO CHANGE IF HIGHEST
	CAIGE 2,MAXQ		;LOW Q?
	JRST NEWST4		;NO, DO Q'S 1 TO MAXQ-1 ALGORITHM
	CAML 1,LQUANT		;LOW Q - WAITED FULL QUANTUM?
	JRST NEWST1		;YES, CAN BE HI-Q
	CAMGE 1,[^D500*NTMS]	;.GE. MINIMAL WAIT?
	RET			;NO
	MOVEI 1,MAXQ-1		;YES, REQUE ON MAXQ-1
	JRST NEWST3

NEWST4:	LOAD 3,FKQTM		;GET CURRENT REMAINING QUANTUM
	ADD 3,1			;GIVE CREDIT FOR WAIT
	CAMGE 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
		MOVEI 1,0(2)	;NO, USE THIS QUEUE
		JRST NEWST3]
NEWST1:	HRRZ 2,FKWSP(FX)	;SET NR TO MAX (6, WSP)
	CAMGE 2,MINWSS		;ABOVE MIN WORKING SET SIZE?
	MOVE 2,MINWSS		;NO, SET TO IT
	SKIPG PRELDF		;DON'T CHANGE WSS IF PRELOADING
	HRRM 2,FKNR(FX)
	SETZ 1,			;INIT ON QUEUE 0
NEWST3:	TXNN F,SK%RQ1		;USING QUEUE 0?
	JUMPE T1,[AOJA T1,.+1]	;NO, CHANGE 0 TO 1
	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
;QUANTUM ONLY ABOUT LONG ENOUGH TO DO PSI OR FREEZE.
; FX/ FORK INDEX
;	CALL PSBUMP
; RETURN +1 ALWAYS

PSBUMP:	LOAD T1,FKQN		;GET CURRENT QUEUE
	CAIE T1,MAXQ		;LOW Q?
	RET			;NO, DO NOTHING
	ACVAR <Q1>
	HLRZ Q1,FKPT(FX)
	CAIN Q1,GOLST		;NOW ON GOLST?
	CALL GLREM		;REMOVE FORK FROM RUN QUEUE
	DECR FKQN		;MOVE FORK TO ONE HIGHER QUEUE
	MOVE T1,BQUANT		;GIVE SPECIAL SHORT 'BUMP' QUANTUM
	STOR T1,FKQTM
	MOVE T1,TODCLK
	MOVEM T1,FKTIME(FX)	;INIT QUEUE TIME
	CAIN Q1,GOLST		;NOW ON GOLIST?
	CALL GOCONC		;PUT BACK ON AT CORRECT PLACE
	RET
;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
	SETZM PSBM0+UPTPG		;FLUSH UPT PTR
	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 1,JOBNO		;RELEASE JOB NUMBER
	SETZM JOBDIR(1)		;CLEAR DIRECTORY NUMBER
	SETOM JOBRT(1)		;INDICATE JOB NUMBER NOT IN USE
	ADDI 1,JOBPT
	EXCH 1,FREJOB		;PUT SLOT ON FREE LIST
	MOVEM 1,@FREJOB
	JRST HLTFK2		;FLUSH THIS LAST FORK


HLTJB3:	TXZN T1,1B0		;FAILED. NEED TO WAIT?
	BUG(HLT,TTDAS1,<HLTJB: UNABLE TO DEASSIGN CONTROLLING TERMINAL>)
	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 GLREM		;REMOVE FORK FROM GOLST
	MOVEI 1,(1B0)
	HRLM 1,FKPT(FX)		;NOTE FORK NOT IN BALSET
	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(CHK,FRKNDL,<FORK NOT PROPERLY DELETED>)
	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,ICAPT
	MOVEM 1,CAPT
	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 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
	SETZM JOBNAM(1)		;INIT JOBNAM AND FLAGS WORD
	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 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

;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
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, REPLACE ON WAIT LIST
	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

UNPIR:	AOS INSKED		;ENTER SCHEDULER
	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(CHK,UNPIRX,<UNPIR-NO PSI IN PROGRESS>)
	ANDCAM 1,FKINT(FX)
	RET

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
	HLRZ 1,FKPT(FX)		;YES, GET STATUS OF FORK
	CAIN 1,WTLST		;NOW WAITING?
	JRST [	MOVSI 1,PSIWTF	;YES, SET FLAG
		IORM 1,FKINT(FX)
		LOAD 1,FKLOC
		CALL UNBLK1	;WAKE UP THE FORK
		JRST PSIR61]
	PUSH P,3
	CALL PSBUMP		;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
	HRRM 3,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:	MOVE Q2,BITS(FX)
	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
	HRRM FX,FKINT(2)	;NO, SETUP TO INTERRUPT 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 PSIT2		;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:	MOVEI 1,0(FX)
	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, can'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
;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 UNPIR		;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
	CALL WAKSUP		;WAKEUP SUPERIOR
	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 UNPIR		;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:
	XJRSTF [PCU		;SET PREV CONTEXT USER
		MSEC1,,.+1]
	MOVE 1,MJRST0		;NORMALIZE ALL DEFER TRAPS
	MOVEM 1,MJRSTF
	MOVE 1,INTDF0
	MOVEM 1,INTDFF
	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
	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
		SETZ 1,		;YES, FLUSH BREAKS
		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
	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 LEVCHN		;THIS PROCESS TAKING INTERRUPTS?
	JRST PSIN1		;NO, GO TRANSMIT THE PSI
	MOVE 1,PSIBW		;FIND HIGHEST PRIORITY INTERRUPT
	MOVEI 2,0		;NOW WAITING
	MOVSI 3,1
	; ..
	; ..
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

;AC3 NOW CONTAINS LEVEL OF HIGHEST PRIORITY INTERRUPT FOUND
;Q1 CONTAINS CORRESPONDING CHANNEL NUMBER

	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
	HRRZ 1,LEVCHN		;GET ADR OF USER'S CHANNEL TABLE
	ADDI 1,0(Q1)		;COMPUTE ADR OF USER'S CHANNEL WORD
	UMOVE 1,0(1)		;GET ADR OF USER'S INT ROUTINE
	HRRZ T4,T1		;GET PC
	EXCH 1,PIFL		;SET TO START THERE, GET OLD FLAGS
	EXCH 4,PIPC		;GET PC
	TLNN 1,(UMODF)		;WAS IN USER MODE?
	JRST PSISM		;NO, MUST SAVE MONITOR CONTEXT
	HLLZM T1,PIFL		;PRESERVE USERS FLAGS
PSIS5:	SETZM PIOLDS
	HLRZ 2,LEVCHN		;GET ADR OF USER'S LEVEL TABLE
	ADDI 2,-1(3)		;COMPUTE ADR OF USER'S LEVEL WORD
	UMOVE 2,0(2)		;GET ADR OF PC WORD FOR THIS LEVEL
	HRR 1,T4		;COMBINE PC
	UMOVEM 1,0(2)		;STORE BREAK PC IN USER'S MEMORY
PSID3:	MOVE 1,BITS(Q1)		;CLEAR WAITING BREAK BIT FOR THIS CHANNEL
	ANDCAM 1,PSIBW
	JRST PIRQR		;TO USER

PSIS2:	HRRZ 4,LEVCHN		;GET ADR OF USER'S CHANNEL TABLE
	ADDI 4,0(2)		;COMPUTE ADR OF USER'S CHANNEL WORD
	XCTU [HLRZ 4,0(4)]	;GET LEVEL NUMBER FOR THIS CHANNEL
	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

;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
;SPECIAL ROUTINE TO SAVE STATE OF INTERRUPTED MONITOR
;ROUTINE

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
	MOVSI Q2,-NSAVC		;SAVE VULNERABLE CELLS
	PUSH FX,@SAVCT(Q2)
	AOBJN Q2,.-1
	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)
	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)
	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
	MOVE 1,UPDL+1		;USER PC AT MONITOR CALL
	MOVEM T1,PIFL		;PRESERVE USERS FLAGS
	MOVE T4,UPDL		;GET PC
	PUSH FX,P1		;PSI STACK BEFORE ALL THIS PUSHING
	PUSH FX,1
	PUSH FX,T4
	MOVEM FX,PSIPT
	TLZ 1,(UMODF)		;SO HE CAN TELL IT WAS MON INTERRUPT
	SETOM SLOWF
	JRST PSIS5		;FINISH INTERRUPT START

PIOVFW:	BUG(HLT,PSISTK,<PSI STORAGE STACK OVERFLOW>)
;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 UNPIR		;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

PSIDFR:	MOVE 1,MJRST1
	MOVEM 1,MJRSTF
	MOVE 1,INTDF1
	MOVEM 1,INTDFF
	CALL UNPIR		;LEAVE BREAK STARTING STATE
	IORM 1,FKINT(FX)	;BUT LEAVE PENDING BIT
	JRST PSIDF1		;RESUME

MJRST1:	XJRSTF [0
	       PSISV0]
INTDF1:	XPCW PIFL		;CONTENTS OF INTDFF WHEN TRAP SET
				;PIPC+1 CONTAINS JRST PSISV1

PSISV1:
	DATAO PAG,SETMON	;SET MON AC BLOCK CURRENT
	SOS INTDF
	XJRSTF [0
		PSISV2]

PSISV0:
	DATAO PAG,SETMON	;SET MON AC BLOCK CURRENT
	DMOVEM 1,PIFL		;SAVE AC1
	DMOVE 1,FFL		;FFL NOW CONTAINS USER'SPC
	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
	SKIPE NSKED		;IN CASE NOSKED W/O NOINT
	BUG(CHK,PSINSK,<PSI FROM NOSKED CONTEXT>)
	JRST RSKP		;IMMEDIATE
;DEBREAK

.DEBRK::MCENT
	SKIPN PSIBIP		;ANY BREAKS IN PROGRESS?
	ITERR DBRKX1		;NO, ERROR
	MOVE 2,FORKX
	MOVSI 1,200000
	IORM 1,FKINT(2)		;SET INTERRUPT STARTING BIT
	SETZM PIOLDS
PSIDBK:	MOVE 2,PSIBIP		;BREAKS NOW IN PROGRESS
	JFFO 2,.+1		;FIND HIGHEST ONE
	HLRZ 1,LEVCHN		;COMPUTE ADDRESS OF RETURN PC
	ADDI 1,-1(3)
	UMOVE 1,0(1)
	UMOVE 1,0(1)		;GET RETURN PC FROM USER MEMORY
	MOVS 2,BITS(3)
	TDNE 2,PSIBIP		;WAS THIS MONITOR INTERRUPT?
	JRST PSIS7		;YES, GO UNWIND
PSIS8:	MOVE T2,0(P)		;GET RETURN PC
	HRR T2,-1(P)
	MOVE P,PIPDL		;ESTABLISH PI STACK
	XOR T1,T2		;KEEP PRIVILEGED BITS FROM THIS CALL
	TXZ T1,UMODF+UIOF+PC%AFI+37B17
	XOR T1,T2
	HLLZM 1,PIFL
	HRRZM 1,PIPC		;SET TO DEBREAK AT THAT ADDRESS
	SETOM SLOWF		;NORMALIZE FLAGS FOR RETURN TO USER
	SETOM INTDF
	MOVE 1,UPP
	MOVEM 1,PIAC+P
PSIS6:	MOVE 1,BITS(3)
	ANDCAM 1,PSIBIP		;CLEAR BIP THIS LEVEL
	JRST PSISV3		;GO CHECK FOR OTHER INTERRUPTS AND RETURN
PSIS7:	ANDCAM 2,PSIBIP		;CLEAR MON BREAK FLAG FOR THIS LEVEL
	MOVE FX,PSIPT
	POP FX,T4		;PC GIVEN TO USER
	POP FX,T2
	HLL T4,T2		;MAKE ONE WORD PC
	POP FX,PSIPT		;TOP OF THIS BLOCK OF PSI STORAGE
	TLON 1,(UMODF)		;IF IT WAS DIDDLED AT ALL,
	CAME 1,4
	JRST [	PUSH P,T1	;SAVE REGISTER
		MOVE T1,FORKX	;GET FORK HANDLE
		PUSH P,T2	;SAVE 2
		HLLZ T2,PSIBIP	;TELL THEM WHAT INTERRUPT LEVEL WE'RE AT
		TDZ T2,BITS(T3)	;POINT TO LEVEL WE'RE GOING TO
		CALL JSBSTF	;GO PROCESS DEALLOCATION STACK
		POP P,T2	;RESTORE REGISTER
		POP P,T1	;RESTORE REGISTER
		JRST PSIS8]	;DON'T RESUME MON ROUTINE
	MOVE P,PIPDL		;ESTABLISH PI PDL
	POP FX,ACBAS
	POP FX,4
	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]
PDBK1:	SUB FX,[XWD 20,20]
	MOVEI 2,PIAC
	HRLI 2,1(FX)
	BLT 2,PIAC+17		;RESTORE MONITOR AC'S
	SUB FX,[XWD NUPDL,NUPDL]
	MOVEI 2,UPDL
	HRLI 2,1(FX)
	BLT 2,UPDL+NUPDL-1	;RESTORE STACK
	MOVEI 2,NSAVC-1		;RESTORE VULNERABLE CELLS
	POP FX,@SAVCT(2)
	SOJGE 2,.-1
	POP FX,2		;GET PC
	MOVEM 2,PIPC		;SAVE PC
	POP FX,2
	MOVEM 2,PIFL		;AND FLAGS
	SETZM SLOWF
	SETOM INTDF
	JRST PSIS6		;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(CHK,TRPSIE,<NO MONITOR FOR TRAPPED FORK>)
	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(HLT,JTENQE,<JTENQ WITH BAD NSKED>)
	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		;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
	HLLZ 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(CHK,IDFOD1,<AT MENTR - INTDF OVERLY DECREMENTED>)
	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(HLT,NOACB,<MENTR - NO MORE AC BLOCKS>)
	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
	XJRSTF [PCU
		MSEC1,,.+1]
	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
	HLLZM 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 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
	CALL ITRRET		;CHECK FOR ERROR TEST INSTRUCTION
	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(CHK,IDFOD2,<AT MRETN - INTDF OVERLY DECREMENTED>)>
	MOVE P,MPP		;GO BACK TO LAST STACK FENCE
	POP P,CX		;RETURN PC
	TLNN CX,(UMODF)		;RETURN TO USER?
	JRST MRETN1		;NO
	MOVEM CX,FFL		;SET UP FLAGS
	POP P,FPC		;RESTORE PC
	MOVE P,UPP		;RESET STACK

;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(HLT,OPOPAC,<MRETN - TRIED TO OVER-POP AC STACK>)
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.  PERFORM SPECIFIED ACTION IF FOUND, RETURN OTHERWISE.

;	CALL ITRRET
; RETURN +1 IF NO SPECIAL INSTRUCTION FOUND, RETURN TO USER OTHERWISE

ITRRET:	MOVE T2,-2(P)		;GET CONTEXT RETURN PC
	MOVE T1,-1(P)		;GET FLAGS ALSO
	CALL ITRSIM		;CALL SUBR TO DO WORK
	 RET			;NO ERJMP/ERCAL
	HRRM T3,-2(P)		;SET RETURN ADDRS
	JRST MRETN		;RETURN TO USER

;COMMON ROUTINE TO CHECK FOR ERJMP/ERCAL AND DO
;CORRECT SIMULATION.
; T2/ ADDRESS OF ERJMP/ERCAL
;
; RETURNS +1 IF NONE FOUND OR PDL OV ON ERCAL
; RETURNS +2 WITH RETURN ADDRS IN C(T3)

ITRSIM::TXNE T1,IMCFLG		;INTERNAL CALL?
	SKIPA T3,0(T2)		;YES, FETCH FROM CURRENT CONTEXT
	UMOVE T3,0(T2)		;NO, FETCH FROM PREVIOUS CONTEXT
	HLLZ T4,T3		;LOOK AT INSTRUCTION ONLY
	CAMN T4,[ERJMP]		;SPECIAL?
	JRST ITRSX		;YES
	CAME T4,[ERCAL]
	RET			;NO
	MOVE T4,BHC+1		;SIMULATE PUSHJ - BUMP STACK PNTR
	XCTU [ADDB T4,P]
	TLNN T4,-1		;PDL OVERFLOW?
	CALL [SAVET		;YES
	      MOVE T1,BITS+.ICPOV ;CHANNEL 9 INTERRUPT  
	      CALL IICSLF
	      RET]
	HLLZS T1		;REMOVE JUNK FROM RIGHT HALF TO FORM 1 WORD
				;WARNING THIS DOES NOT WORK FOR
				;SECTIONS GT 10 BECAUSE OF IMCALL FLAG
				;AND IT WILL HAVE TO BE CHANGED WHEN
				;EXTENDED ADDRESSING IS ADDED FOR USER MODE
	IOR T2,T1		;FORM 1 WORD PC
	UMOVEM T2,0(T4)		;STORE PC FROM JSYS
	XCTU [AOS 0(T4)]	;MAKE PC POINT TO LOC AFTER ERCAL
ITRSX:	RETSKP			;GIVE GOOD RETURN
;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
	HLLZ T1,T1		;LOOK AT INSTRUCTION ONLY
	CAME T1,[ERJMP]		;ERJMP?
	CAMN T1,[ERCAL]		;OR 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

	TNXEND
	END