Google
 

Trailing-Edge - PDP-10 Archives - BB-4170G-SM - sources/pagem.mac
There are 55 other files named pagem.mac in the archive. Click here to see a list.
;<3A.MONITOR>PAGEM.MAC.696, 28-Aug-78 15:09:16, EDIT BY MURPHY
;FIX POTENTIAL UNLOCK OF BAD PTR AT SETIOP+4
;<3A.MONITOR>PAGEM.MAC.695, 16-Aug-78 13:15:54, EDIT BY MURPHY
;<3A.MONITOR>PAGEM.MAC.694, 15-Aug-78 11:36:10, EDIT BY MILLER
; LOAD AGE AT TRPSPM
;<3A.MONITOR>PAGEM.MAC.693, 13-Aug-78 11:54:07, EDIT BY MILLER
;FIXES FOR SPMQ LOGIC.
;<3A.MONITOR>PAGEM.MAC.692,  9-Aug-78 13:48:41, EDIT BY MILLER
;ADD ADDITIONAL DATA TO UBANXM BUGHLT
;<3A.MONITOR>PAGEM.MAC.691,  9-Aug-78 07:51:23, EDIT BY MILLER
;FIX CODE AT FRCSP3 TO BE NOSKED
;<3A.MONITOR>PAGEM.MAC.690,  3-Aug-78 08:19:23, Edit by ENGEL
;ADD "ADD A,BALSHC" TO NICCKS+1 AND NIC3B+3
;<3A.MONITOR>PAGEM.MAC.689, 12-Jul-78 17:37:51, EDIT BY MILLER
;CHECK FOR IMMEDIATE POINTER IN ULDPAG
;<3A.MONITOR>PAGEM.MAC.688, 27-Jun-78 12:23:40, EDIT BY MURPHY
;<1BOSACK>PAGEM.MAC.1001,  5-Jun-78 21:37:56, EDIT BY BOSACK
;<1BOSACK>PAGEM.MAC.1000,  5-Jun-78 19:23:50, EDIT BY BOSACK
;<3A.MONITOR>PAGEM.MAC.686, 13-Jun-78 08:22:51, EDIT BY MILLER
;CHANGE CODE AT NGP1 TO CHECK FOR NOINT MONITOR CORRECTLY
;<3A.MONITOR>PAGEM.MAC.685,  1-Jun-78 13:54:52, EDIT BY MILLER
;DEFINE CLRMPE AS EXTERNAL
;<3A.MONITOR>PAGEM.MAC.684,  1-Jun-78 12:46:12, EDIT BY MILLER
;ADD CALL MEMSTR AFTER ALL MEMORY IS FOUND
;<3A.MONITOR>PAGEM.MAC.683,  1-Jun-78 11:44:20, EDIT BY MILLER
;MAKE SURE PGRINI CLEARS PARITY ERROR
;<3A.MONITOR>PAGEM.MAC.682, 31-May-78 14:33:22, EDIT BY BOSACK
;ALLOW OFN2XB TO BE SET IN SPTH (TEMP)
;<3A.MONITOR>PAGEM.MAC.681, 30-May-78 08:12:28, EDIT BY MILLER
;FIX FRCRMP SO NRPLQ IS MAINTAINED PROPERLY
;<3A.MONITOR>PAGEM.MAC.680, 26-May-78 16:12:02, EDIT BY MILLER
;FIX CODE AT NPG THAT CHECKS NOINT. BE SURE PC IS IN MONITOR
;<3A.MONITOR>PAGEM.MAC.679, 14-May-78 14:27:43, EDIT BY MILLER
;FIX AT RELP4. CLEAR MAPPING AT APPROPRIATE TIME
;<3A.MONITOR>PAGEM.MAC.678,  4-May-78 12:04:09, EDIT BY MILLER
;DON'T BE NOSKED WHILE GETTING IN XB IN ASGOFN
;<3A.MONITOR>PAGEM.MAC.677, 19-Apr-78 16:57:36, EDIT BY MILLER
;CLEAR PAGER IN MSPACS
;<3A.MONITOR>PAGEM.MAC.676,  7-Apr-78 21:39:50, Edit by BORCHEK
;DO NOT DO SETUP IF ANBSEC=0
;<3A.MONITOR>PAGEM.MAC.675,  5-Apr-78 12:24:09, EDIT BY MILLER
;FIX TYPEO IN SETPST
;<3A.MONITOR>PAGEM.MAC.674,  4-Apr-78 13:25:46, EDIT BY MILLER
;MAKE SETPST RETURN PREVIOUS STATE. ADD LODPPS TO DECLARE SPECIAL
;PREVIOUS STATE
;<3A.MONITOR>PAGEM.MAC.673, 23-Mar-78 08:19:27, EDIT BY MILLER
;CHANGE NAME OF ASLOFN TO ASGOFL
;<3A.MONITOR>PAGEM.MAC.672, 23-Mar-78 08:12:46, EDIT BY MILLER
;MERGE ASLOFN INTO ASGOFN. MAKE CODE AS "SMART" AS POSSIBLE
;<3A.MONITOR>PAGEM.MAC.671, 16-Mar-78 09:28:34, EDIT BY MILLER
;WHEN ALL OFN'S EXHAUSTED, TRY FREEING "UNSHARED" ONES
;<3A.MONITOR>PAGEM.MAC.670,  3-Mar-78 15:29:11, EDIT BY MILLER
;SCAN OFN AT RELMI1 IF SHARE COUNT IS ZERO
;<3A.MONITOR>PAGEM.MAC.669,  3-Mar-78 12:20:52, Edit by MCLEAN
;<3.SM10-RELEASE-3>PAGEM.MAC.3, 27-Feb-78 17:44:42, Edit by MCLEAN
;<3.SM10-RELEASE-3>PAGEM.MAC.2, 23-Feb-78 15:36:47, Edit by MCLEAN
;FIX PAGEFAIL CODE 20 ERRORS
;<3A.MONITOR>PAGEM.MAC.667,  3-Mar-78 12:12:35, EDIT BY MILLER
;REMOVE "STRUCTURE" CHECKING IN QCHK. MOVED TO DSKASN
;<3A.MONITOR>PAGEM.MAC.666,  3-Mar-78 11:26:54, EDIT BY MILLER
;ONLY CHECK SYSSPC IN QCHK IF STRUCTURE IS PS
;<3A.MONITOR>PAGEM.MAC.665, 28-Feb-78 15:24:56, EDIT BY MILLER
;RELEASE ALOC ENTRY IN INVOFN
;<3A.MONITOR>PAGEM.MAC.664, 17-Feb-78 09:29:04, EDIT BY MILLER
;PASS PC FLAGS TO ITRSIM AT ILRFU
;<3A.MONITOR>PAGEM.MAC.663, 11-Feb-78 10:03:28, EDIT BY MILLER
;NOW SPELL IT RIGHT
;<3A.MONITOR>PAGEM.MAC.662, 11-Feb-78 09:49:02, EDIT BY MILLER
;MAKE SURE FLAGS AND PC ARE CORRECT ON RETRY FROM "HARD" PAGE FAIL
;<3A.MONITOR>PAGEM.MAC.661, 24-Jan-78 15:17:33, EDIT BY MILLER
;FIX NPG TO ALLOW USER CREATES IN ANY SECTION
;<3A.MONITOR>PAGEM.MAC.660, 24-Jan-78 12:46:51, EDIT BY MILLER
;FIX FPTA AND GETTPD TO GET USER SECTION POINTER FROM UPT
;<3A.MONITOR>PAGEM.MAC.659, 23-Jan-78 20:26:50, EDIT BY MILLER
;FIX TYPEO IN ULDPAG. CHANGE SWPOUT TO SWPOT0 IN FRCSPM
;<3A.MONITOR>PAGEM.MAC.658, 23-Jan-78 13:55:43, EDIT BY MILLER
;MORE ULDPAG FIXES
;<3A.MONITOR>PAGEM.MAC.657, 23-Jan-78 13:50:02, EDIT BY MILLER
;MAKE ULDPAG WAIT FOR SWAP TO COMPLETE
;<3A.MONITOR>PAGEM.MAC.656, 23-Jan-78 11:31:43, EDIT BY MILLER
;BUG FIXES FOR PAGE LOCKING
;<3A.MONITOR>PAGEM.MAC.655, 20-Jan-78 09:53:23, EDIT BY MILLER
;FIX FRCRMP TO DO ADDRESSING CORRECTLY
;<3.SM10-RELEASE-3>PAGEM.MAC.654, 19-Jan-78 16:33:55, EDIT BY MILLER
;<3.SM10-RELEASE-3>PAGEM.MAC.653, 19-Jan-78 16:14:28, EDIT BY MILLER
;WAIT FOR SWAP TO FINISH IN ULDPAG
;<3.SM10-RELEASE-3>PAGEM.MAC.652, 18-Jan-78 16:37:44, EDIT BY MILLER
;FIX OFFSPQ TO SET BACKUP ADDRESS TO UAAB
;<3.SM10-RELEASE-3>PAGEM.MAC.651, 18-Jan-78 16:07:46, EDIT BY MILLER
;FIX FRCSPM TO CORRECTLY PRESERVE PRESENT STATE
;<3.SM10-RELEASE-3>PAGEM.MAC.650, 18-Jan-78 13:08:23, EDIT BY MILLER
;CHANGE NAME OF ROUTINE TO RMPCHK
;<3.SM10-RELEASE-3>PAGEM.MAC.649, 18-Jan-78 13:03:17, EDIT BY MILLER
;CHANGE FRCRMP TO CALL ROUTINE IN APRSRV FOR PAGE CHECK
;<3.SM10-RELEASE-3>PAGEM.MAC.648, 17-Jan-78 15:28:40, EDIT BY MILLER
;MORE CHANGES TO LET LODPPG GRAP RES MONITOR PAGE
;<3.SM10-RELEASE-3>PAGEM.MAC.647, 17-Jan-78 14:30:32, EDIT BY MILLER
;FIX MAPPHP TO CHECK FOR RESMON CORRECTLY
;<3.SM10-RELEASE-3>PAGEM.MAC.646, 17-Jan-78 14:11:41, EDIT BY MILLER
;ALLOW LODPPG TO GET RES MONITOR PAGES. FIX UP ROUTINES TO RETURN PAGE
;<3.SM10-RELEASE-3>PAGEM.MAC.645, 17-Jan-78 12:46:34, EDIT BY MILLER
;ALLOW LODPPG TO LOAD INTO "ON-LINE" RESIDENT MONITOR PAGE
;<3.SM10-RELEASE-3>PAGEM.MAC.644, 16-Jan-78 11:32:24, EDIT BY MILLER
;ADD CHANGES FOR LOCKING PAGES NEEDED FOR MEMORY SUPPORT
;<3.SM10-RELEASE-3>PAGEM.MAC.642, 30-Dec-77 13:48:08, EDIT BY MILLER
;FIX UP FRCRMP. DON'T CHECK FOR SPECIAL PAGES
;<3.SM10-RELEASE-3>PAGEM.MAC.641, 30-Dec-77 13:43:40, EDIT BY MILLER
;UNDO ALL OF SWAP OUT CHECKS. ADD CODE TO LOCK RESIDENT MONITOR
;<3.SM10-RELEASE-3>PAGEM.MAC.640, 28-Dec-77 13:13:50, EDIT BY MILLER
;MORE CHANGES FOR TRANSITION PAGES. MAKE A SUBROUTINE OUT OF CHECKER
;<3.SM10-RELEASE-3>PAGEM.MAC.639, 28-Dec-77 12:06:56, EDIT BY MILLER
;FIX SWPOUT TO CHECK FOR TRANSITION TO SPQ
;<3.SM10-RELEASE-3>PAGEM.MAC.638, 28-Dec-77 11:56:08, EDIT BY MILLER
;FIX CODE AT SWPDON TO CHECK FOR PAGE IN TRANSITION TO SPQ
;<3.SM10-RELEASE-3>PAGEM.MAC.637, 12-Dec-77 12:30:52, EDIT BY MILLER
;FIX FPTA TO RETURN A ZERO FOR NON-EX SECTION POINTER
;<3.SM10-RELEASE-3>PAGEM.MAC.636, 11-Dec-77 19:31:59, Edit by MCLEAN
;<3.SM10-RELEASE-3>PAGEM.MAC.635, 11-Dec-77 19:31:17, Edit by MCLEAN
;FIX SEEADR FOR RM03 SUPPORT
;<3.SM10-RELEASE-3>PAGEM.MAC.634, 10-Dec-77 19:03:05, EDIT BY HELLIWELL
;LOCK PAGE FROM SPMQ DOWN AT SWPIQ1, UNLOCK AT LODPP1
;<3.SM10-RELEASE-3>PAGEM.MAC.633, 10-Dec-77 02:07:55, EDIT BY HELLIWELL
;FIX BUG IN PAGE ACCOUNTING AT SWPIQ1
;<3.SM10-RELEASE-3>PAGEM.MAC.632, 10-Dec-77 00:58:57, EDIT BY HELLIWELL
;FIX NON-EX PAGE CREATION IN SWPPAG
;<3.SM10-RELEASE-3>PAGEM.MAC.631,  9-Dec-77 23:09:42, EDIT BY HELLIWELL
;FIX PAGE ACCOUNTING FOR PAGES GOING ON/OFF SPMQ
;<3.SM10-RELEASE-3>PAGEM.MAC.6, 17-Nov-77 14:56:58, EDIT BY MURPHY
;<3.SM10-RELEASE-3>PAGEM.MAC.5, 14-Nov-77 13:10:12, EDIT BY MURPHY
;LOGIC TO INCLUDE/EXCLUDE PAGE TRAP TIME FROM RUNTIME
;<3-MONITOR>PAGEM.MAC.630, 11-Nov-77 17:19:08, EDIT BY MURPHY
;<3.SM10-RELEASE-3>PAGEM.MAC.3,  2-Nov-77 01:51:10, Edit by LCAMPBELL
;<3-MONITOR>PAGEM.MAC.625,  1-Nov-77 10:25:28, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.624, 31-Oct-77 23:54:59, Edit by LCAMPBELL
;<3-MONITOR>PAGEM.MAC.623, 31-Oct-77 22:36:39, Edit by LCAMPBELL
;MAKE ADBRK WITH ONLY AB%RD ON TRAP ONLY ON READS
;<3-MONITOR>PAGEM.MAC.622, 31-Oct-77 16:44:57, EDIT BY MURPHY
;<3.SM10-RELEASE-3>PAGEM.MAC.1, 27-Oct-77 22:55:07, EDIT BY MILLER
;FIX INVOFN TO RESCAN ENTIRE XB IF HAD TO BLOCK IN SKPNWR
;<3-MONITOR>PAGEM.MAC.621, 12-Oct-77 14:03:10, EDIT BY KIRSCHEN
;UPDATE COPYRIGHT FOR RELEASE 3
;<3-MONITOR>PAGEM.MAC.620, 11-Oct-77 23:46:11, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.619, 10-Oct-77 13:39:56, EDIT BY MURPHY
;INCREMENTAL GCCOR
;<3-MONITOR>PAGEM.MAC.618,  6-Oct-77 00:03:44, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.617,  5-Oct-77 08:44:43, EDIT BY MILLER
;CHANGE TEST FOR PC SECTION AT PGRT3 TO BE SLIGHTLY MORE EFFICIENT
;<3-MONITOR>PAGEM.MAC.616,  4-Oct-77 20:54:44, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.615,  4-Oct-77 12:30:23, EDIT BY MILLER
;ALLOW PAGE FAULT PC TO BE IN SECTION 0 OR IN SECTION MSEC1 AT PGRT3
;<3-MONITOR>PAGEM.MAC.614,  4-Oct-77 11:26:31, EDIT BY MILLER
;INIT OFN SHARE COUNT TO 1 AT ASOF6 IN CASE GARBAGE LEFT BEHIND
;<3-MONITOR>PAGEM.MAC.613,  4-Oct-77 10:11:02, EDIT BY MILLER
;SET UP FPTABL IN PGRINI SO SECTIONS CAN BE SHUFFLED
;<3-MONITOR>PAGEM.MAC.612,  3-Oct-77 17:32:39, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.608,  2-Oct-77 13:57:05, EDIT BY MILLER
;FIXES TO ALLOW MONITOR TO RUN ALL INSECTION 0
;<3-MONITOR>PAGEM.MAC.607, 30-Sep-77 22:40:09, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.606, 30-Sep-77 16:35:52, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.604, 23-Sep-77 16:32:54, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.603, 21-Sep-77 13:13:32, Edit by MCLEAN
;CHANGE MONCLR TO MONCLA IN UNLBTB
;<3-MONITOR>PAGEM.MAC.602, 19-Sep-77 06:01:01, EDIT BY BOSACK
;<3-MONITOR>PAGEM.MAC.601, 18-Sep-77 16:52:48, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.600, 17-Sep-77 22:49:37, EDIT BY HELLIWELL
;ADD HOOKS FOR LOCK JSYS (USED BY VB10 SERVICE)
;<3-MONITOR>PAGEM.MAC.599, 15-Sep-77 17:18:17, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.598, 12-Sep-77 23:08:40, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.597, 12-Sep-77 22:19:44, EDIT BY MURPHY
;TCO #1856 - ONRQ/OFRQ LOGIC
;<3-MONITOR>PAGEM.MAC.596, 12-Sep-77 15:15:41, EDIT BY CROSSLAND
;FIX TO MLKPGM TO SET AGE TO PSASN INSTEAD OF CONTENTS OF PSASN
;<3-MONITOR>PAGEM.MAC.595,  8-Sep-77 15:45:47, EDIT BY HELLIWELL
;CHANGES FOR REL 3 VB10 SUPPORT ALL UNDER RVCF COND.
;<3-MONITOR>PAGEM.MAC.591,  2-Sep-77 14:30:34, EDIT BY MILLER
;FIX PIPTRP CODE
;<3-MONITOR>PAGEM.MAC.590,  1-Sep-77 17:54:59, EDIT BY BOSACK
;<3-MONITOR>PAGEM.MAC.589,  1-Sep-77 17:48:08, EDIT BY BOSACK
;MAKE PI PAGE FAIL ANALYZE AR/ARX PARITY ERRORS CORRECTLY
;<3BOSACK>PAGEM.MAC.590, 23-Aug-77 01:22:04, EDIT BY BOSACK
;INITIALIZE FREECORE TO NUMBER OF INITCODE PAGES
;<3-MONITOR>PAGEM.MAC.587, 17-Aug-77 09:42:47, EDIT BY MILLER
;FIX DASALC TO CHECK FOR ALLOC INFO BEFORE TOUCHING OFNLEN
;<3-MONITOR>PAGEM.MAC.586, 12-Aug-77 17:34:09, Edit by LCAMPBELL
;MORE ADDRESS BREAK
;<3-MONITOR>PAGEM.MAC.585, 12-Aug-77 10:09:06, EDIT BY HALL
;ADD ADJALC - ADJUST DIRECTORY'S ALLOCATION ENTRY FOR CRDIR
;<3-MONITOR>PAGEM.MAC.584,  9-Aug-77 14:43:02, EDIT BY MILLER
;<3-MONITOR>PAGEM.MAC.583,  9-Aug-77 14:06:08, EDIT BY MILLER
;REMOVE BUGCHK FOR USER MODE EXTENDED ADDRESSING REFERENCE
;<3-MONITOR>PAGEM.MAC.582,  9-Aug-77 08:46:08, EDIT BY MILLER
;MAKE PSB STACK PAGE HAVE AN SPTN AND LOCK IT DOWN IN SCHEDULER
;<MILLER.1MILLER>PAGEM.MAC.1,  8-Aug-77 16:59:20, EDIT BY MILLER
;<3-MONITOR>PAGEM.MAC.581,  8-Aug-77 10:48:33, EDIT BY MILLER
;ALLOW FPTA TO RETURN A ZERO FOR NON-EX SECTION. CHECK BY ALL CALLERS
;<3-MONITOR>PAGEM.MAC.580,  4-Aug-77 18:00:59, EDIT BY MILLER
;PUT IN HACK IN MRMAP TO CHECK FOR FPTA RETURNING A ZERO
;<3-MONITOR>PAGEM.MAC.579, 29-Jul-77 14:57:27, Edit by LCAMPBELL.ADBRK
;TCO 1838 - ADDRESS BREAK
;<3-MONITOR>PAGEM.MAC.578, 28-Jul-77 10:09:07, EDIT BY MILLER
;FIX PGRTH TO USE FLAGS FROM PFAID
;<3-MONITOR>PAGEM.MAC.577, 27-Jul-77 01:09:07, EDIT BY CROSSLAND
;ADD OMITED INSTRUCTION IN MULKSP
;<3-MONITOR>PAGEM.MAC.576, 26-Jul-77 15:58:01, EDIT BY MILLER
;<3-MONITOR>PAGEM.MAC.575, 26-Jul-77 15:49:51, EDIT BY MILLER
;ADD DESSTK ROUTINE FOR USE BY SCHEDULER
;<3-MONITOR>PAGEM.MAC.574, 26-Jul-77 15:07:04, EDIT BY MILLER
;FIX FAILURES OF SETP7A TO WORK WITH EXTENDED ADDRESSING
;<3-MONITOR>PAGEM.MAC.573, 24-Jul-77 16:34:48, EDIT BY CROSSLAND
;<3-MONITOR>PAGEM.MAC.572, 24-Jul-77 00:06:58, EDIT BY CROSSLAND
;ADD MULKSP TO UNLOCK PAGES IN SECTIONS OTHER THAN 0 AT INTERRUPT LEVEL
;MOVE ARPANET BUFFERS TO ANOTHER SECTION
;<3-MONITOR>PAGEM.MAC.571, 19-Jul-77 13:54:18, EDIT BY MILLER
;TCO 1843. INHIBIT XGC IF IN A NESTED FAULT
;<3-MONITOR>PAGEM.MAC.570, 13-Jul-77 17:53:00, EDIT BY MILLER
;FIX CODE AT RELP4 (AGAIN) TO MAKE SHARER CHECK FASTER
;<3-MONITOR>PAGEM.MAC.569, 11-Jul-77 14:12:05, EDIT BY MILLER
;FIX RELP4 CODE TO UPDATE OFN RACE FREE
;<3-MONITOR>PAGEM.MAC.568, 29-Jun-77 21:01:35, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.567, 29-Jun-77 08:16:57, EDIT BY MILLER
;DON'T SCAN OFN AT RELP4 UNLESS "DUD" IS SET
;<3-MONITOR>PAGEM.MAC.566, 28-Jun-77 17:03:40, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.565, 27-Jun-77 14:52:16, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.564, 27-Jun-77 14:33:30, Edit by MCLEAN
;MOVE BITTABLE TO NON/ZERO SECTION
;<3-MONITOR>PAGEM.MAC.562, 26-Jun-77 12:38:07, EDIT BY MILLER
;FIX ILRFU TO STORE ERJMP PC IN CORRECT PC WORD
;<3-MONITOR>PAGEM.MAC.561, 23-Jun-77 15:16:19, Edit by HESS
;FIX FAIL RETURN FROM SETP7A AT SETP7E TO UNLOCK CST
;<3-MONITOR>PAGEM.MAC.560, 21-Jun-77 20:05:07, EDIT BY CROSSLAND
;FIX INDEX AT MVPT SO LEFT HALF IS ZERO
;<3-MONITOR>PAGEM.MAC.559, 17-Jun-77 18:21:23, EDIT BY CROSSLAND
;FIX UP BAD INDEXES
;<3-MONITOR>PAGEM.MAC.558, 16-Jun-77 12:56:26, EDIT BY MILLER
;<3-MONITOR>PAGEM.MAC.557, 16-Jun-77 12:07:45, EDIT BY MILLER
;CLEAR PAGER IN UNLBTB
;<3-MONITOR>PAGEM.MAC.556,  9-Jun-77 23:03:46, EDIT BY MURPHY
;PERFORMANCE ENHANCEMENTS
;REMOVE AN "RVCF" CONDITIONAL
;<2-PERF>PAGEM.MAC.7, 31-May-77 16:09:58, EDIT BY MURPHY
;<2-PERF>PAGEM.MAC.4, 27-May-77 15:49:58, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.555,  3-Jun-77 17:13:42, EDIT BY MILLER
;MAKE RELP4 CALL UPDOFN IF OFN SHARE COUNT IS ZERO
;<3-MONITOR>PAGEM.MAC.554,  3-Jun-77 13:56:47, EDIT BY MILLER
;LET INDIRECT POINTERS TO OFN'S ALWAYS WORK
;<3-MONITOR>PAGEM.MAC.553,  2-Jun-77 11:44:28, Edit by MCLEAN
;FIX NICMG1 FOR USER REF TO PAGE IN NON 0 SECTION
;<3-MONITOR>PAGEM.MAC.552,  1-Jun-77 23:50:09, Edit by MCLEAN
;ADD LABEL PGRI2A FOR PARITY ERROR CHECK
;<3-MONITOR>PAGEM.MAC.551, 27-May-77 16:54:42, EDIT BY HURLEY
;FIX TO MAKE PAGEM RUN ON MODEL B MACHINE
;<3-MONITOR>PAGEM.MAC.550,  5-May-77 22:10:24, Edit by MCLEAN
;ADD MSEC1 TO MSECTB INSTEAD OF +1
;<3-MONITOR>PAGEM.MAC.549,  2-May-77 10:11:41, EDIT BY MILLER
;TCO 1787. FIX MRPT
;<3-MONITOR>PAGEM.MAC.548, 29-Apr-77 15:51:37, EDIT BY BOSACK
;TCO 1786 - DONT LEAVE PRIVATE WCPY PAGE LOCKED
;<3-MONITOR>PAGEM.MAC.547, 28-Apr-77 16:59:56, EDIT BY BOSACK
;TCO 1785 - FIX BUGHLT NOTOFN BY CALLING UPDOF0 WITH JUST OFN
;<3-MONITOR>PAGEM.MAC.546, 28-Apr-77 14:40:29, EDIT BY MILLER
;MAKE MLKCP DO NOSKD1 AND OKSKD1
;<3-MONITOR>PAGEM.MAC.545, 13-Apr-77 16:08:55, EDIT BY MILLER
;TCO 1780. KEEP LONG FILE PT'S AROUND AS LONG AS POSSIBLE
;<3-MONITOR>PAGEM.MAC.544, 11-Apr-77 13:44:49, EDIT BY MURPHY
;TCO #1776 - FLUSH CALL TO RPCST AT MOVDS1
;<3-MONITOR>PAGEM.MAC.543,  7-Apr-77 14:39:18, Edit by MCLEAN
;FIX ILRD TO GET FLAGS AND PC CORRECT
;<3-MONITOR>PAGEM.MAC.542,  6-Apr-77 08:36:55, EDIT BY MILLER
;MORE FIXES TO PGRTRP
;<3-MONITOR>PAGEM.MAC.541,  6-Apr-77 02:37:57, Edit by MCLEAN
;ADD EXADF1 SO SM10 CAN USE EXTENDED ADDRESSING FORMAT PAGEFAIL
;<3-MONITOR>PAGEM.MAC.540,  5-Apr-77 16:31:32, EDIT BY MILLER
;MAKE PGRTRP RUN NOINT FROM THE TOP
;<3-MONITOR>PAGEM.MAC.539, 27-Mar-77 00:46:22, Edit by MCLEAN
;ADD MVAGER
;<3-MONITOR>PAGEM.MAC.538, 26-Mar-77 19:08:14, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.537, 20-Mar-77 15:36:13, Edit by MCLEAN
;FIX SECG37 BUGCHECK AT SETIO1-2
;<3-MONITOR>PAGEM.MAC.536, 11-Mar-77 11:25:43, EDIT BY MILLER
;TCO 1755. PRESERVE PT MAPPING ON LONG FILE UNMAP
;<3-MONITOR>PAGEM.MAC.535,  9-Feb-77 16:15:35, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.534,  3-Feb-77 16:23:33, EDIT BY MURPHY
;<3-MONITOR>PAGEM.MAC.533,  3-Feb-77 12:26:26, Edit by HESS
;TCO 1726 - FIX TO EOF ON SIMULTANEOUS UPDATE PROBLEM
;<3-MONITOR>PAGEM.MAC.532,  3-Feb-77 11:24:30, EDIT BY MURPHY
;TCO #1729 - ALLOW MLKPG USE BY RES STG ALLOCATOR WHILE INSKED
;<3-MONITOR>PAGEM.MAC.531,  1-Feb-77 13:44:58, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.530, 29-Jan-77 17:38:11, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.529, 23-Jan-77 23:29:48, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.528, 23-Jan-77 23:25:53, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.527, 23-Jan-77 22:56:52, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.526, 19-Jan-77 19:31:47, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.525, 16-Jan-77 00:06:53, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.524, 15-Jan-77 22:19:24, EDIT BY HELLIWELL
;REMOVE ADJUSTMENT TO TOTRC FOR VB10C, PAGES ARE INCLUDED IN BALSHC
;<3-MONITOR>PAGEM.MAC.523, 15-Jan-77 17:52:02, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.522,  8-Jan-77 00:33:25, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.521,  6-Jan-77 15:01:30, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.520,  4-Jan-77 13:05:41, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.519,  4-Jan-77 12:58:27, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.518, 30-Dec-76 12:43:35, EDIT BY MILLER
;FIX TYPEO AT PREPG1
;<3-MONITOR>PAGEM.MAC.517, 29-Dec-76 22:19:01, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.516, 28-Dec-76 21:47:59, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.515, 27-Dec-76 17:35:21, EDIT BY HURLEY
;<3-MONITOR>PAGEM.MAC.514, 27-Dec-76 10:49:24, EDIT BY MILLER
;MAKE SURE XB NOT BEING WRITTEN AT RELOFN
;<2-MONITOR>PAGEM.MAC.489, 22-Dec-76 17:07:56, EDIT BY BOSACK
;TCO 1688 - RECREATE LOGIC TO MARK HARD ERRORS IN XB/FDBS
;<3-MONITOR>PAGEM.MAC.512, 22-Dec-76 14:08:47, Edit by HESS
;FIX SETP7A CALLS TO UNLOCK PAGE ON FAILURE ONLY IF PAGE LOCKED
;<3-MONITOR>PAGEM.MAC.511, 20-Dec-76 13:12:15, EDIT BY MILLER
;LOCK XB DURING RELOFN SO IT WON'T GET WRITTEN
;<3-MONITOR>PAGEM.MAC.510, 20-Dec-76 09:47:26, EDIT BY MILLER
;ADD UNLBTB ROUTINE
;<3-MONITOR>PAGEM.MAC.509, 19-Dec-76 00:05:35, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.508, 18-Dec-76 23:45:33, Edit by MCLEAN
;<2-MONITOR>PAGEM.MAC.485, 18-Dec-76 18:56:54, EDIT BY HELLIWELL
;MAYBE I GOT IT RIGHT THIS TIME
;<3-MONITOR>PAGEM.MAC.506, 18-Dec-76 17:08:11, EDIT BY HELLIWELL
;MOVE SETRVC CALL
;<3-MONITOR>PAGEM.MAC.505, 18-Dec-76 04:04:41, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.503, 17-Dec-76 00:48:40, Edit by MCLEAN
;<1MCLEAN>PAGEM.MAC.2, 16-Dec-76 16:22:53, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.503, 17-Dec-76 00:48:40, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.502, 16-Dec-76 00:31:58, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.501, 13-Dec-76 17:03:40, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.500,  9-Dec-76 13:13:39, EDIT BY MILLER
;LOCK STRLOK IN DDMP
;<3-MONITOR>PAGEM.MAC.499,  9-Dec-76 11:51:08, EDIT BY MILLER
;<3-MONITOR>PAGEM.MAC.498,  9-Dec-76 10:24:42, EDIT BY MILLER
;MOVE NOSKED IN RELOFN
;<3-MONITOR>PAGEM.MAC.497,  9-Dec-76 10:19:10, EDIT BY MILLER
;<3-MONITOR>PAGEM.MAC.496,  9-Dec-76 03:41:28, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.495,  8-Dec-76 16:57:24, EDIT BY MILLER
;<3-MONITOR>PAGEM.MAC.494,  8-Dec-76 16:53:48, EDIT BY MILLER
;FIX BUG IN MRKOFN

;<3-MONITOR>PAGEM.MAC.493,  7-Dec-76 10:43:41, Edit by HESS
;DO DISK SPACE CHECKING/ACCOUNTING AT SETP7
;<3-MONITOR>PAGEM.MAC.492,  3-Dec-76 00:48:37, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.491,  2-Dec-76 03:31:40, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.490,  1-Dec-76 21:23:57, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.489,  1-Dec-76 17:09:11, Edit by MCLEAN
;<2-MONITOR>PAGEM.MAC.475,  1-Dec-76 10:50:00, EDIT BY HELLIWELL
;UPDATE FREE CORE PAGES AT SETRVC
;<3-MONITOR>PAGEM.MAC.487, 30-Nov-76 16:10:16, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.486, 30-Nov-76 15:35:43, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.485, 30-Nov-76 01:32:22, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.484, 28-Nov-76 23:09:04, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.483, 28-Nov-76 13:01:16, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.482, 27-Nov-76 17:37:55, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.481, 27-Nov-76 03:11:29, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.480, 26-Nov-76 22:26:47, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.479, 26-Nov-76 22:24:01, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.478, 26-Nov-76 22:19:20, Edit by MCLEAN
;<3-MONITOR>PAGEM.MAC.477, 26-Nov-76 21:46:38, Edit by MCLEAN
;TCO 1669 EXTENDED ADDRESSING
;<2-MONITOR>PAGEM.MAC.474, 23-Nov-76 17:00:23, EDIT BY MILLER
;RECHECK OFN SLOT IF INVOFN HAD TO WAIT FOR WRITE TO COMPLETE
;<2-MONITOR>PAGEM.MAC.473, 23-Nov-76 09:30:44, EDIT BY MILLER
;AT RELP4, CALL RELOFN INSTEAD OF CLROFN
;<2-MONITOR>PAGEM.MAC.472, 15-Nov-76 02:35:20, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.471, 15-Nov-76 02:31:26, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.470, 15-Nov-76 02:07:51, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.469, 15-Nov-76 00:20:30, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.468, 14-Nov-76 23:20:06, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.467, 14-Nov-76 22:45:41, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.466, 14-Nov-76 18:26:46, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.465, 14-Nov-76 18:10:24, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.464, 14-Nov-76 16:55:20, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.463, 14-Nov-76 16:21:28, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.462, 14-Nov-76 14:00:06, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.461, 13-Nov-76 18:33:38, EDIT BY BOSACK
;<2BOSACK>PAGEM.MAC.4, 13-Nov-76 16:37:23, EDIT BY BOSACK
;<2BOSACK>PAGEM.MAC.3, 13-Nov-76 14:00:17, EDIT BY BOSACK
;<2BOSACK>PAGEM.MAC.2, 13-Nov-76 11:35:00, EDIT BY BOSACK
;<2BOSACK>PAGEM.MAC.1, 12-Nov-76 21:36:11, EDIT BY BOSACK
;ADD SPMQ LOGIC, REWORK RPLQ LOGIC
;<2-MONITOR>PAGEM.MAC.459, 12-Nov-76 10:52:45, Edit by HESS
;ADD ERROR CODES TO PAGER TRAPS AND STORE IN LSTERR
;<2-MONITOR>PAGEM.MAC.458, 12-Nov-76 10:21:43, EDIT BY MILLER
;MAKE INVOFN CALL SKPNWR BEFORE REMFP1 TO INSURE STORAGE WILL BE RELEASED
;<2-MONITOR>PAGEM.MAC.457, 11-Nov-76 15:31:32, EDIT BY MILLER
;CHANGE MRKOFN TO PRESERVE LOOP CONTROL OVER CALL TO LCKOFN
;<2-MONITOR>PAGEM.MAC.456,  8-Nov-76 14:03:25, EDIT BY MILLER
;MAKE TRP0 RESTART TRAP IF AGE IS NOT SPECIAL
;<2-MONITOR>PAGEM.MAC.455,  8-Nov-76 10:40:29, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.454,  8-Nov-76 10:29:08, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.453,  8-Nov-76 10:14:02, EDIT BY MILLER
;CLEAR OFN IN RELMPG IF SHARE COUNT GOES TO ZERO
;<2-MONITOR>PAGEM.MAC.452,  5-Nov-76 17:15:49, EDIT BY MILLER
;FIX UP STACK
;<2-MONITOR>PAGEM.MAC.451,  5-Nov-76 09:17:39, EDIT BY MILLER
;PUT IN BUGCHK IF SWPOUT FINDS AN OFN WITH A ZERO SHARE COUNT
;<2-MONITOR>PAGEM.MAC.450,  3-Nov-76 19:38:36, EDIT BY MILLER
;MAKE MRKOFN SKIP  DISMOUNTED OFN'S
;<2-MONITOR>PAGEM.MAC.449,  3-Nov-76 18:29:08, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.448,  3-Nov-76 18:25:59, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.447,  3-Nov-76 18:21:34, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.446,  3-Nov-76 17:43:28, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.445,  3-Nov-76 12:44:17, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.444,  3-Nov-76 12:39:30, EDIT BY MILLER
;FIX INVOFN TO PROPERLY SCAN DISMOUNTED XB
;<2-MONITOR>PAGEM.MAC.443,  1-Nov-76 15:15:52, EDIT BY HELLIWELL
;DON'T CACHE PAGES USED BY RVCF
;<2-MONITOR>PAGEM.MAC.442, 26-Oct-76 15:07:15, EDIT BY MURPHY
;TCO #1629 - NOSKED AT MLKCP
;<2-MONITOR>PAGEM.MAC.441, 22-Oct-76 15:54:05, EDIT BY MILLER
;FIX MRPACS TO CHECK OFN ON EACH INDIRECT POINTER
;<2-MONITOR>PAGEM.MAC.440, 21-Oct-76 18:51:09, EDIT BY HURLEY
;FIX SWPOG3 BUG
;<2-MONITOR>PAGEM.MAC.439, 20-Oct-76 09:50:21, EDIT BY MILLER
;FIX SWAP OUT OF XB TO ALWAYS DO SWAP
;<2-MONITOR>PAGEM.MAC.438, 20-Oct-76 09:36:20, EDIT BY MILLER
;FIX SWPOUT TO PUT PAGE ON DISK WHEN SWAPPING SPACE LOW IF POSSIBLE
;<2-MONITOR>PAGEM.MAC.437, 19-Oct-76 18:49:06, EDIT BY MILLER
;FIX SWPOUT TO SWAP EVEN IF DRUM SPACE IS LOW
;<2-MONITOR>PAGEM.MAC.436, 16-Oct-76 09:56:42, EDIT BY MILLER
;REMOVE DDMP EDITS
;<2-MONITOR>PAGEM.MAC.435, 14-Oct-76 18:16:18, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.434, 14-Oct-76 16:24:38, EDIT BY MILLER
;MAKE DDMP CALL CHKBT FOR PS
;<2-MONITOR>PAGEM.MAC.433, 13-Oct-76 16:07:45, EDIT BY MILLER
;CHECK FOR OFN SHARE COUNT UNDERFLOW IN DWNSHR
;<2-MONITOR>PAGEM.MAC.432, 12-Oct-76 20:37:27, EDIT BY MILLER
;FIX RANGE CHECK CHECK FOR BIT TABLE IN FPTA
;<2-MONITOR>PAGEM.MAC.431, 12-Oct-76 18:26:46, EDIT BY MURPHY
;MORE FIXING OF NOINT, NOSKED IN PGRTRP
;<2-MONITOR>PAGEM.MAC.430, 11-Oct-76 15:05:44, Edit by MACK
;TCO 1586 - REPLACED DIAGNOSTIC AT PRT3: WITH NORMAL NOSKED
;PGU3: DOES OKSKED AND NOT OKINT AS WELL
;<2-MONITOR>PAGEM.MAC.429,  4-Oct-76 14:10:00, EDIT BY HURLEY
;<2-MONITOR>PAGEM.MAC.428,  1-Oct-76 12:04:33, EDIT BY MURPHY
;TCO #1556 - DON'T COUNT NEW PAGES IN DSKRD
;<2-MONITOR>PAGEM.MAC.427, 28-Sep-76 17:01:32, EDIT BY MILLER
;ONLY NEED TO CHECK FOR INDIRECT LOOPS IN MRPACS
;<2-MONITOR>PAGEM.MAC.426, 28-Sep-76 13:45:17, EDIT BY MILLER
;CLEAN UP CST0 CLEAN UP
;<2-MONITOR>PAGEM.MAC.425, 28-Sep-76 13:39:57, EDIT BY MILLER
;TCO 1550. HANDLE INDIRECT LOOPS CORRECTLY.
;<2-MONITOR>PAGEM.MAC.424, 22-Sep-76 16:16:08, EDIT BY BOSACK
;TCO 1536 - CST0 DATABASE CLEANUP
;<2-MONITOR>PAGEM.MAC.423, 13-Aug-76 18:18:20, Edit by HESS
;REMOVE  ASFOFN AND ASLOFN , MOVE THEM TO DISC
;<2-MONITOR>PAGEM.MAC.422, 12-Aug-76 14:11:03, EDIT BY MURPHY
;TCO #1482
;<2-MONITOR>PAGEM.MAC.421, 12-Aug-76 13:58:30, EDIT BY MURPHY
;TCO #1491 - INIT PCU FLAG IN PGRTRP CODE
;<2-MONITOR>PAGEM.MAC.420, 11-Aug-76 14:36:23, Edit by HESS
;CHECK FOR ERJMP/ERCAL BEFORE POSTING INTERUPT AT ILRF
;<2-MONITOR>PAGEM.MAC.419,  9-Aug-76 16:17:15, EDIT BY MURPHY
;<2-MONITOR>PAGEM.MAC.418,  5-Aug-76 21:52:44, Edit by HESS
;<2-MONITOR>PAGEM.MAC.417,  5-Aug-76 12:30:45, EDIT BY MURPHY
;TCO #1482 - ADJUST FKWSS AT NICMG
;<2-MONITOR>PAGEM.MAC.416,  5-Aug-76 12:13:44, EDIT BY MURPHY
;TCO #1479 - BALANCE SET PARTITIONING
;<2-MONITOR>PAGEM.MAC.414,  4-Aug-76 13:08:07, Edit by HESS
;<HESS>PAGEM.MAC.11,  3-Aug-76 14:59:21, Edit by HESS
;TCO 1478 - QUOTA CHECKING
;<2-MONITOR>PAGEM.MAC.412, 28-Jul-76 13:49:24, EDIT BY MILLER
;MAKE PMAP TO DISK SWAP OUT TO DISK
;<1MILLER>PAGEM.MAC.1, 26-Jul-76 15:20:06, EDIT BY MILLER
;MAKE RELMI1 MOVE PAGE TO THE DISK IF POSSIBLE
;<2-MONITOR>PAGEM.MAC.410, 21-Jul-76 17:28:00, EDIT BY MILLER
;FIX UPDPGS WHEN XB HAS IMMEDIATE POINTER TO DRUM
;<2-MONITOR>PAGEM.MAC.409, 21-Jul-76 14:13:09, EDIT BY MILLER
;ADD MRKOFN ROUTINE
;<2-MONITOR>PAGEM.MAC.408, 21-Jul-76 13:13:06, EDIT BY MILLER
;FIX MOVDSK TO USE RPCST
;<2-MONITOR>PAGEM.MAC.407, 21-Jul-76 11:11:51, EDIT BY MILLER
;FIX INVOFN . FIX RELMPG TO RELEASE OFN IF DISMOUNTED
;<2-MONITOR>PAGEM.MAC.406, 20-Jul-76 21:52:44, EDIT BY MILLER
;ADD CAUTION COMMENT TO MOVDSK
;<2-MONITOR>PAGEM.MAC.405, 20-Jul-76 21:25:07, EDIT BY MILLER
;FIX RELOFN TO CALL MOVDSK WITH OFN IN LH OF 4
;<1MILLER>PAGEM.MAC.6, 20-Jul-76 20:08:23, EDIT BY MILLER
;FIX MOVDSK TO PROPERLY DELETE IN CORE PAGES
;<1MILLER>PAGEM.MAC.5, 20-Jul-76 15:43:20, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.4, 20-Jul-76 13:27:24, EDIT BY MILLER
;ADD TEST FOR FILDUD IN ASOFN AND SET IN SPTH IF REQUESTED
;<1MILLER>PAGEM.MAC.3, 19-Jul-76 16:25:41, EDIT BY HALL
;FIX ASOFN TO WORK IF OFN IS LOCKED
;<1MILLER>PAGEM.MAC.2, 19-Jul-76 12:38:00, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.1, 19-Jul-76 12:23:14, EDIT BY MILLER
;FIX SWAPPING 
;<1MILLER>PAGEM.MAC.5, 13-Jul-76 20:45:08, EDIT BY MILLER
;REMOVE ARCHAIC COMMENT LINE
;<1MILLER>PAGEM.MAC.4,  7-Jul-76 17:44:49, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.3,  7-Jul-76 12:03:23, EDIT BY MILLER
;MORE CHANGES TO REDUCE STACK USAGE IN PAGE FAULT CODE
;<1MILLER>PAGEM.MAC.2,  7-Jul-76 11:26:55, EDIT BY MILLER
;CHANGE XGC TO SAVE AND RESTORE Q1 AND Q2
;<1MILLER>PAGEM.MAC.1,  7-Jul-76 10:18:02, EDIT BY MILLER
;CHANGE PGRTRP CODE SO IT USES 2 FEWER WORDS OF STACK PER FAULT.
;<2-MONITOR>PAGEM.MAC.400,  6-Jul-76 19:16:55, EDIT BY HURLEY
;UNDO TCO 1460 AFTER MUCH THOUGHT
;<2-MONITOR>PAGEM.MAC.399,  6-Jul-76 15:46:47, EDIT BY MILLER
;MAKE CHKDMO INTERNAL
;<2-MONITOR>PAGEM.MAC.398,  6-Jul-76 14:36:49, EDIT BY MILLER
;ADD CALL TO CHKDMO AT MSCANP
;<2-MONITOR>PAGEM.MAC.397,  6-Jul-76 11:36:50, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.17,  5-Jul-76 10:36:56, EDIT BY MILLER
;ADD CHKDMO CHECKING TO VARIOUS ROUTINES
;<1MILLER>PAGEM.MAC.16,  1-Jul-76 16:51:07, EDIT BY MILLER
;FIX VERPT AND PTVER FOR 0,,OFN .
;<1MILLER>PAGEM.MAC.15,  1-Jul-76 11:50:52, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.14,  1-Jul-76 11:47:11, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.13,  1-Jul-76 10:49:01, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.12,  1-Jul-76 10:20:42, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.11,  1-Jul-76 09:19:33, EDIT BY MILLER
;FIX SETMPG,MSETMP,SETPT,MSETPT AND FRIENDS TO HANDLE DISMOUNTED OFNS
;<1MILLER>PAGEM.MAC.10, 30-Jun-76 18:49:30, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.9, 30-Jun-76 18:21:12, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.8, 30-Jun-76 12:16:38, EDIT BY MILLER
;MORE FIXES TO INVOFN
;<1MILLER>PAGEM.MAC.7, 30-Jun-76 12:02:12, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.6, 30-Jun-76 11:57:26, EDIT BY MILLER
;FIX DELETE OF LOCAL STORAGE IN INVOFN
;<1MILLER>PAGEM.MAC.5, 30-Jun-76 11:48:37, EDIT BY MILLER
;MAKE INVOFN SWAPPABLE
;<1MILLER>PAGEM.MAC.4, 30-Jun-76 11:14:34, EDIT BY MILLER
;CHECK FOR DISMOUNTED OFN IN GETTPD PAGE FAULT RESOLUTION
;<1MILLER>PAGEM.MAC.3, 30-Jun-76 10:49:09, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.2, 30-Jun-76 10:32:42, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.1, 30-Jun-76 09:51:39, EDIT BY MILLER
;ADD INVOFN ROUTINE TO MARK OFN AS DISMOUNTED
;<2-MONITOR>PAGEM.MAC.394, 29-Jun-76 12:53:37, EDIT BY MILLER
;FIX PRELOADING TO IGNORE INDIRECT POINTERS
;<2-MONITOR>PAGEM.MAC.35, 21-Jun-76 15:02:22, EDIT BY MILLER
;FIX UPSHR AND FRIENDS
;<1B-MONITOR>PAGEM.MAC.390, 19-MAY-76 17:34:13, EDIT BY MILLER
;TCO 1302. FIX PREPG.
;<1B-MONITOR>PAGEM.MAC.391, 28-APR-76 17:44:58, EDIT BY MILLER
;TCO 1268. UNLOCK PAGE AT SETP7X
;<1B-MONITOR>PAGEM.MAC.390, 27-APR-76 11:59:39, EDIT BY MILLER
;TCO 1262. ALLOW PAGE CREATES IF NOINT
;<1B-MONITOR>PAGEM.MAC.389, 13-APR-76 19:00:16, EDIT BY BOSACK
;<2-MONITOR>PAGEM.MAC.33, 18-Jun-76 15:04:33, EDIT BY MILLER
;USE BTBORA IN PGRINI
;<1MILLER>PAGEM.MAC.8,  4-JUN-76 16:21:21, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.7,  3-JUN-76 19:42:09, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.6,  2-JUN-76 15:29:47, EDIT BY MILLER
;EXPAND STRUCTURE NUMBER TO 6 BITS
;<1MILLER>PAGEM.MAC.5,  2-JUN-76 11:18:11, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.4,  2-JUN-76 11:09:33, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.3,  2-JUN-76 11:04:20, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.2,  1-JUN-76 14:00:19, EDIT BY MILLER
;<1MILLER>PAGEM.MAC.1,  1-JUN-76 13:33:56, EDIT BY MILLER
;ADD SPTO TABLE
;<2-MONITOR>PAGEM.MAC.31, 30-MAY-76 16:27:35, EDIT BY HALL
;MOVED FROM HALL
;<HALL>PAGEM.MAC.3, 30-MAY-76 09:40:30, EDIT BY MILLER
;FIX MRPACS NOT TO CREATE PT FOR UNMAPPED BITTABLE
;<HALL>PAGEM.MAC.2, 28-MAY-76 16:48:04, EDIT BY MILLER
;<HALL>PAGEM.MAC.1, 28-MAY-76 11:51:16, EDIT BY HALL
;<1MILLER>PAGEM.MAC.1, 28-MAY-76 09:54:45, EDIT BY MILLER
;IMPROVE BIT TABLE HANDLING
;<2-MONITOR>PAGEM.MAC.30, 19-MAY-76 17:34:39, EDIT BY MILLER
;TCO 1302. FIX PREPG
;<2-MONITOR>PAGEM.MAC.29, 11-MAY-76 18:30:20, EDIT BY MILLER
;ADD CHECK FOR VALID STRUCTURE NUMBER IN ASOFN
;<2-MONITOR>PAGEM.MAC.28, 28-APR-76 17:46:13, EDIT BY MILLER
;TCO 1268. UNLOCK PAGE AT SETP7X
;<2-MONITOR>PAGEM.MAC.27, 27-APR-76 12:00:45, EDIT BY MILLER
;TCO 1262. ALLOW PAGE CREATE IF NOINT
;<2-MONITOR>PAGEM.MAC.26, 20-APR-76 18:58:49, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.25, 20-APR-76 15:28:28, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.24, 20-APR-76 14:36:48, EDIT BY MILLER
;ADD SWPIN1 FOR DSKAL1 TO CALL
;<2-MONITOR>PAGEM.MAC.23, 20-APR-76 13:22:31, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.22, 20-APR-76 13:00:41, EDIT BY MILLER
;REPLACE SKIPG NTRACK WITH SKIPG NSSUN
;<2-MONITOR>PAGEM.MAC.21, 20-APR-76 11:46:01, EDIT BY MILLER
;ADD CALL TO GSTRPG AT NIC64 TO GET ALLOCATION OF STRUCTURE
;<2-MONITOR>PAGEM.MAC.20, 20-APR-76 10:37:16, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.19, 19-APR-76 17:43:35, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.18, 19-APR-76 17:38:00, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.17, 19-APR-76 16:08:07, EDIT BY HALL
;<2-MONITOR>PAGEM.MAC.16, 19-APR-76 15:56:04, EDIT BY HALL
;<2-MONITOR>PAGEM.MAC.15, 18-APR-76 18:20:03, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.14, 18-APR-76 13:35:04, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.13, 16-APR-76 09:53:40, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.12, 15-APR-76 19:42:25, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.11, 15-APR-76 16:35:41, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.10, 15-APR-76 13:44:09, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.9, 15-APR-76 12:53:00, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.8, 15-APR-76 09:30:59, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.7, 14-APR-76 20:20:19, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.6, 14-APR-76 16:31:06, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.5, 14-APR-76 11:53:13, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.4, 14-APR-76 10:29:16, EDIT BY MILLER
;<2-MONITOR>PAGEM.MAC.3, 12-APR-76 13:07:00, EDIT BY HALL
;<2-MONITOR>PAGEM.MAC.2,  5-APR-76 20:10:40, EDIT BY HALL
;<2-MONITOR>PAGEM.MAC.1,  5-APR-76 19:27:45, EDIT BY MILLER
;ADDED MMAPWP AND MMAPWE
;<1MONITOR>PAGEM.MAC.388, 29-MAR-76 15:18:25, EDIT BY MURPHY
;TCO #1222 - DETECT TOO MUCH CORE
;<1MONITOR>PAGEM.MAC.387,  5-MAR-76 12:43:00, EDIT BY MURPHY
;<1MONITOR>PAGEM.MAC.386,  1-MAR-76 11:45:38, EDIT BY MURPHY
;MORE #1097
;<1MONITOR>PAGEM.MAC.385,  1-MAR-76 10:18:04, EDIT BY KIRSCHEN
;TCO # 1130 - PRESERVE Q AC'S AT FPTAQ
;<1MONITOR>PAGEM.MAC.384, 26-FEB-76 17:27:12, EDIT BY MURPHY
;<2MONITOR>PAGEM.MAC.383, 26-FEB-76 10:53:19, EDIT BY MURPHY
;<2MONITOR>PAGEM.MAC.382, 16-FEB-76 16:28:18, EDIT BY MURPHY
;TCO #1097 - INCREASE FREE MONITOR VAS
;<2MONITOR>PAGEM.MAC.380, 10-FEB-76 11:14:15, EDIT BY MURPHY
;<2MONITOR>PAGEM.MAC.379,  6-FEB-76 18:06:27, EDIT BY MURPHY
;TCO #1064 - FIX MRPACS
;<2MONITOR>PAGEM.MAC.378, 19-JAN-76 12:22:24, EDIT BY MURPHY
;<2MONITOR>PAGEM.MAC.377,  9-JAN-76 15:36:30, EDIT BY MURPHY
;<2MONITOR>PAGEM.MAC.373, 19-DEC-75 16:39:58, EDIT BY MURPHY
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1977 BY DIGITAL EQUIPMENT CORPORATION

	SEARCH PROLOG
	TTITLE PAGEM

EXTN <SPCRES,MEMSTR,CLRMPE>
DEFAC (FX,Q3)			;FORK INDEX

;STORAGE

RS BTSTRT,1			;START OF BITTABLE
RS BTEND,1			;END OF BITTABLE
RS PAGDIF,1			;COUNT OF NEW PAGES IN THE SYSTEM
RS SWPCOR,1			;FIRST PAGE USED FOR SWAPPING
RS NHIPG,1			;HIGEST PAGE USED BY SWAPPER
RS SPTC,1			;COUNT OF SPT (EXCLUDING OFN) ENTRIES IN SPT
RS NOF,1			;COUNT OF ENTRIES IN OFN PART OF SPT
RS FRESPT,1			;FREE SPT LIST
RS MAXSPL,1			;MAX NUMBER OF PROBES TO SPTH
RS MMSPTN,1			;OFN OF MONITOR MAP
RS LOKPGS,1			;COUNT OF LOCKED PAGES, VIA MLKPG
RS LOKSUM,1			;NET NUMBER OF LOCKS, MLKPG-MULKPG
RS GNPBAS,1			;AMOUNT BY WHICH NPMAX REDUCED
RS DDTIME,1			;TIME NEXT DDMP DUE
RS IOIP,1			;SWAP WRITES IN PROGRESS
RS DRMIN0,1			;DRUM SPACE LEVEL FOR DDMP ACTION
RS DRMLV0,1			;DRUM SPACE LEVEL FOR NO NEW PRIV PAGES
RS PRELRQ,1			;PRELOADING SWAPIN IF NON-0
RS DELPGQ,1			;QUEUE OF DELETED PAGES
RS DWRCFL,1			;FLAG - FORK WAITING FOR WRITE COMPLETION
RS JOBBAS,1			;JOB BASE (SPT INDEX)
RS PSBBAS,1			;FORK BASE (SPT INDEX)
RS BTBBAS,1			;BIT TABLE BASE
RS NBADCP,1			;NUMBER CORE PAGES DECLARED BAD
RS BSHC1,1			;GCCOR - NEW BALSHC
RS GCCLPG,1			;GCCOR - LAST PAGE COLLECTED

;VARIABLES FOR SWPOM (SWPOMI, SWPOML, SWPOMG)

RS SWPLST,1			;LIST OF PAGES FOR SWAP
RS SWPLSI,1			;IN PTR TO SWAP LIST
RS SWPRC0,1			;COUNT OF PAGES ON LIST
RS SWPDAD,1			;NEXT SEQUENTIAL SWAP ADDRESS TO USE

SPC0::	EXP <SSPT-NOFN-400>*5/6	;SPT LEVEL FOR USING INDIRECT PTRS
SPC1::	EXP SSPT-NOFN-100	;SPT LEVEL FOR NO NEW JOBS
SPC2::	EXP SSPT-NOFN-10	;SPT LEVEL FOR NO NEW FORKS

;INDEX BLOCK DEFINTIONS

XBBAT==1B0			;BAT BIT
XBBWRD==4			;WORD FOR XBBAT

;CANONICAL POINTERS

IMMPTR::FLD(IMMCOD,PTRCOD)+PTWR+PTCACH
SHRPTR::FLD(SHRCOD,PTRCOD)+PTWR+PTCACH
INDPTR::FLD(INDCOD,PTRCOD)+PTWR+PTCACH

	MAXIND==1000		;MAXIMUM INDIRECT POINTERS ALLOWED
				; BEFORE MONITOR GIVES UP

;BOUNDARY TO ARTIFICIALLY LIMIT CORE

NLOWPG:: 0			;PAGES BELOW HERE CONSIDERED NXM

;ADMINISTRATIVE LIMIT OF PROGRAM (FORK) SIZE.  ACTUAL LIMIT MAY BE LOWER
;IF INSUFFICIENT CORE.  SYSTEM ADMINISTRATOR MAY ADJUST THIS PARAMETER
;TO LIMIT SIZE OF LARGE JOBS THEREBY ALLOWING MORE IN CORE.

PGMMAX:: MAXFKS			;FORK SIZE LIMIT SPECIFIED IN PARAMS

IPTIM::	IPTIMF			;FLAG FOR PAGE TRAP TIME FROM PARAMS

GCMIN0==^D64			;MIN PAGES FOR GCCOR TO COLLECT

NRPMX:	MINNR+2			;RPLQ MIN, SHOULD BE .G. MINNR

;BOUNDARIES SET BY POSTLD

MONCOR::0			;NUMBER PAGES OF RES MON
SWPCP0::0			;FIRST PAGE OF REAL CORE FOR SWAPPING
;INITIALIZATION, SPT, CST, ETC.
;ASSUMES PAGING ALREADY TURNED ON

PGRINI::ACVAR <Q1>
	SETZM SPTC
	SETZM NOF
	SETZM MAXSPL
	MOVE 1,[DST,,DST+1]	;INIT DST TO -1
	SETOM -1(1)
	BLT 1,DST+NDST-1
	MOVEI 1,SPT+NOFN
	MOVEI 2,SSPT-NOFN
	CALL ILIST		;MAKE LIST OF FREE SPT ENTRIES
	MOVEM 1,FRESPT
	SETZM SPTH
	MOVE 1,[XWD SPTH,SPTH+1]
	BLT 1,SPTH+NOFN-1	;ZERO OUT SPTH
	CALL ASSPT		;ASSIGN SPT SLOT FOR JOB BASE REG
	MOVEM T1,JOBBAS
	CALL UPSHR		;INIT SHARE COUNT
	CALL ASSPT		;ASSIGN SPT SLOT FOR FORK BASE REG
	MOVEM T1,PSBBAS
	CALL UPSHR		;INIT SHARE COUNT
	CALL ASSPT		;GET ANOTHER ONE
	MOVEM T1,BTBBAS		;MAKE THIS THE BIT TABLE BASE
	MOVX T2,UAAB		;SET UP ACCESS TO NULL
	MOVEM T2,SPT(T1)	;TO THE SPT
	CALL UPSHR		;INIT SHARE COUNT
	SETZM SPTH(T1)		;SET NO CORRESPONDENCE
	MOVE T1,[MMAP,,MMAP+1]	;CLEAR MONITOR MAP
	SETZM MMAP
	BLT T1,MMAP+PGSIZ-1
	MOVSI T1,-MAXSEC	;SET UP TO INIT FPTA TARNSFER TABLE
	MOVE T2,[IFIW!ILLFPT]	;ASSUME ALL ARE ILLEGAL
PGR00:	MOVEM T2,FPTABL(T1)	;INIT THIS ENTRY
	AOBJN T1,PGR00		;DO ALL OF THE TABLE
	CALL ASSPT		;ASSIGN SPT SLOT FOR MMAP
	MOVE T2,SHRPTR		;CONSTRUCT SHARE PTR TO MMAP
	STOR T1,SPTX,T2
	MOVEM T2,MSECTB		;SETUP POINTER FOR MON SECTION 0
	MOVE T3,[IFIW!FPTA0]	;ROUTINE FOR MONITOR SECTION
	MOVEM T3,FPTABL		;SET UP SECTION 0
	SKIPN [MSEC1]		;DOING EXTENDED ADDRESSING?
	JRST PGRI10		;NO. SKIP EPT SET UP THEN
	MOVEM T2,MSECTB+MSEC1	;SET UP POINTER FOR MON SEC1 ALSO
	MOVEM T3,FPTABL+MSEC1	;INIT FOR OTHER CODE SECTION
	MOVE T3,INDPTR		;GET INDIRECT POINTER
	MOVE T2,PSBBAS		;GET BASE POINTER
	STOR T2,SPTX,T3		;STORE SPT POINTER
	MOVEI T2,DRMAP		;FIND INDEX
	STOR T2,IPPGN,T3
	MOVEM T3,MSECTB+DRSECN
	MOVE T4,[IFIW!FPTA6]	;DISPATCH FOR DIRECTORY
	MOVEM T4,FPTABL+DRSECN	;SET IT UP
	MOVEI T2,IDXMAP		;SET UP POINTER TO IDXTAB
	STOR T2,IPPGN,T3
	MOVEM T3,MSECTB+IDXSEC	;SET IDX SECTION
	MOVE T4,[IFIW!FPTA7]	;IDX ADDRESS
	MOVEM T4,FPTABL+IDXSEC	;TO THE TABLE
	MOVE T4,[IFIW!FPTA8]	;BIT TABLE HANDLER
	MOVEM T4,FPTABL+BTSEC	;TO THE TABLE
	MOVE T4,[IFIW!FPTAAN]	;APRPANET BUFFER HANDLER
	SKIPE [ANBSEC]		;NO SPECIAL SECTION FOR NET
	 MOVEM T4,FPTABL+ANBSEC	;TO THE TABLE
PGRI10:	MOVEI 2,MMAP/PGSIZ	;GET ADDRESS FIELD
	MOVEM 2,SPT(1)
	CALL UPSHR		;SET SHARE COUNT
	MOVEM 1,MMSPTN
	MOVSI 2,0(1)
	SETZ 1,			;START WITH CORE PAGE 0
PGRI1:	MOVX T4,PSASM		;INIT CST'S
	MOVEM T4,CST0(T1)
	MOVX T4,UAAB		;SET BACKUP ADR TO UNASSIGNED
	MOVEM T4,CST1(T1)
	MOVEM T2,CST2(T1)
	MOVX T4,<FLD OFNUL,CSTOFK>
	MOVEM T4,CST3(T1)	;MAKE PAGE UNASSIGNED
	MOVE T4,IMMPTR
	STOR 1,STGADR,4		;MAKE MAPPED MON EQUIV TO PHYS CORE
	MOVEM 4,MMAP(2)
	ADDI 1,1
	CAMGE 1,SWPCOR		;FILL TO END OF RES MON
	AOJA 2,PGRI1
	MOVEI T2,MMAP/PGSIZ	;CORE PAGE OF MMAP
	OPSTRM <ADDM T1,>,PLKCNT,(T2) ;NOTE CORE PTRS IN MMAP
	; ..
;SET UP LOCATIONS FOR BIT TABLE

	CALL INITBT		;SETUP INITIAL BTB SIZES
	SKIPE EXADDR		;IF EXTENDED ADDRESSING MAP NOT IN MMAP
	JRST PGRIBT
	MOVE T1,INDPTR		;GET INDIRECT POINTER FOR MAP
	MOVE T2,BTBBAS		;THE SPTN FOR THE BITTABLE
	STOR T2,SPTX,T1		;FORM REST OF POINTER WORD
PGRI77:	MOVEM T1,MMAP(T4)	;STORE NEXT POINTER
	ADD T1,[<FLD 1,IPPGN>]	;NEXT PAGE
	AOBJN T4,PGRI77		;DO ALL OF ADDRESS SPACE

;SETUP JOB COMMON STORAGE (JSBPG TO JSBLST INCLUSIVE) TO INDIRECT JOBBAS

PGRIBT:	MOVE T4,[XWD JSBPG-JSLST,JSBPG]
	MOVE T1,INDPTR		;CONSTRUCT INDIRECT PTR
	MOVE T2,JOBBAS
	STOR T2,SPTX,T1
	MOVEI T2,JOBMAP-JSBPGA
	STOR T2,IPPGN,T1
PGRI3:	MOVEM T1,MMAP(T4)	;STORE IN MON MAP
	AOS T2			;BUMP POINTER
	STOR T2,IPPGN,T1
	AOBJN T4,PGRI3		;DO ALL JOB AREA

;SETUP PSB (PSSPS TO PSB1) INDIRECT PSBBAS

	MOVE T4,[XWD PSSPS-PSB1-1,PSSPS]
	MOVE T2,PSBBAS		;CONSTRUCT INDIRECT PTR
	STOR T2,SPTX,T1
	MOVEI T2,PSBMAP-PSBPGA
	STOR T2,IPPGN,T1
PGRI5:	MOVEM T1,MMAP(T4)	;STORE IN MON MAP
	AOS T2			;BUMP POINTER
	STOR T2,IPPGN,T1
	AOBJN T4,PGRI5		;DO ALL PROCESS AREA
	MOVE T1,SHRPTR		;SETUP SHARE POINTER TO PSB AND JSB
	MOVE T2,PSBBAS		; VIA SPECIAL BASE ADDRESS WORDS
	STOR T2,SPTX,T1
	MOVEM T1,MMAP+PSBPG
	MOVE T2,JOBBAS
	STOR T2,SPTX,T1
	MOVEM T1,MMAP+JSBPG

;SET UP ARPANET BUFFER SECTION PAGE MAP 

	SKIPE [ANBSEC]		;NO SPECIAL SECTION FOR NET
	SKIPG [NHOSTS]		;IS IT AN ARPA SYSTEM
	JRST PGRI8		;NO  SKIP SET UP
	CALL ASSPT		;GET AN SPT SLOT
	MOVE T2,SHRPTR		;SET UP SHARE PONITER FOR PAGE MAP
	STOR T1,SPTX,T2	
	MOVEM T2,MSECTB+ANBSEC	;SET UP POINTER FOR ARPANET BUFFER SEC.
	MOVEI T2,NTBFIX/PGSIZ	;GET PAGE NUMBER OF MAP PAGE
	MOVEM T2,SPT(T1)	;SET UP SPT POINTER
	CALL UPSHR		;SET SHARE COUNT

PGRI8:	CALL SETPSK		;SET TO SCHED CONTEXT
	CALL PGRON		;TURN ON PAGING
	; ..
;FIND ALL EXISTENT PHYSICAL CORE AND CONSTRUCT RPLQ

	MOVE T1,SWPCOR	
	SUB T1,MONCOR		;INIT TOTRC TO COUNT OF
	MOVEM T1,TOTRC		;CONDITIONALLY SWAPPABLE PAGES

	SETZM GNPBAS		;INIT OVERHEAD PAGES
	SETZM NSPMQ		;INITIALIZE SPMQ
	MOVSI T1,SPMQ		;SET TAIL POINTER
	MOVEM T1,SPMQ		; ...
	SETOM SPMLCK		;SPMQ USER INTERLOCK
	SETOM SPMONR		;FORK OWNING SPMLCK
	SETZM NRPLQ
	CONO APR,APFCLR+APNXM+APRCHN	 ;CLEAR NXM
	MOVE Q1,SWPCOR
	MOVE 2,[XWD RPLQ,RPLQ]
	MOVEM 2,RPLQ		;REPLACEMENT QUEUE EMPTY
PGRI2:	MOVX T2,PSASM		;SET LEGAL AGE FOR TEST REFERENCE
	MOVEM T2,CST0(Q1)
	SETZM CST1(Q1)		;CLEAR CST ENTRIES
	SETZM CST2(Q1)
	SETZM CST3(Q1)
	MOVE T1,Q1		;GET PHYS PAGE NUMBER
	CALL MAPRCA		;MAP IT
PGRI2A::MOVE T2,0(T1)		;TRY TO REFERENCE IT
	CONSZ APR,APNXM		;NXM?
	JRST PGRI6		;YES
	MOVE T2,1(T1)		;TRY 3 OTHER WORDS IN CASE INTERLEAVED
	MOVE T2,2(T1)
	MOVE T2,3(T1)
PGRI6::	CAML Q1,NLOWPG		;EXCLUDE PAGES BELOW BOUNDARY
	CONSZ APR,APNXM		;NXM?
	JRST [	CONO APR,APFCLR+APNXM+APRCHN	 ;YES, CLEAR FLAG
		MOVX T2,<FLD(PSDEL,CSTAGE)+FLD(PSTOFL,CSTPST)>
		MOVEM T2,CST0(Q1)	;CALL IT DELETED
		MOVE T1,Q1		;AND PLACE ON SPMQ
		CALL ONSPMQ		;LIKE ONRQ, RETURNS
		PIOFF			;PION
		JRST PGRI4]
	SETZM CST0(Q1)		;NO, PAGE EXISTS
	MOVEM Q1,NHIPG		;REMEMBER HIGHEST PAGE FOUND
	MOVE T1,Q1
	CLRMPE			;CLEAR ANY PARITY ERROR FROM SCAN
	CALL ONRQ		;PUT PAGE ON REPLACABLE QUEUE
	PIOFF
	AOS TOTRC		;COUNT PAGES OF CORE FOUND
PGRI4:	CAIGE Q1,MAXCOR-1	;CHECK ALL POSSIBLE CORE
	AOJA Q1,PGRI2
	CALL MEMSTR		;SET UP MEM CONTROLLERS IF APPROPRIATE
	; ..
;SETUP VARIOUS CONSTANTS FOR CORE MGT

	CALL MEMMGT		;SET UP PAGING PARAMETERS
	CALL AJBPAR		;COMPUTE BALSET PARTITIONING
	MOVEI 1,100
	CALL LDAGER		;LOAD AGE REGISTER
	MOVE Q1,MONCOR		;LOCK POSSIBLY SWAPPABLE PAGES
PGRI7:	MOVE T1,Q1
	CALL MLKCP
	AOS Q1
	CAMGE Q1,SWPCOR		;PAGES FROM MONCOR TO SWPCOR
	JRST PGRI7
PGRRST::CALL PGRON
	CALL PGRCLD
	RET
;ROUTINES TO COMPUTE PAGE MANAGEMENT PARAMETERS

MEMMGT:	MOVE T1,TOTRC		;TOTAL REAL MEM FOUND
	SUB T1,NRPMX
	MOVEM T1,MAXNR		;MAX VALUE OF SUMNR
	SUBI T1,10
	SKIPE T2,PGMMAX		;CUSTOMER-SPECIFIED LIMIT?
	JRST [	CAMLE T2,T1	;YES, BELOW CORE LIMIT?
		MOVE T2,T1	;NO, MUST USE CORE LIMIT
		MOVEM T2,NPMAX	;USE FOR BOTH REGULAR AND SMALL LIMIT
		MOVEM T2,SNPMAX
		JRST PGRI9]
	MOVEM T1,NPMAX
	CAIL T1,140		;REASONABLY LARGE SYSTEM?
	SUBI T1,40		;YES, SET SNPMAX 16K SMALLER
	MOVEM T1,SNPMAX		;SMALL NPMAX
PGRI9:	MOVE T1,NRPMX		;INIT NRPMIN
	MOVEM T1,NRPMIN
	MOVE T1,TOTRC
	LSH T1,-3
	CAIL T1,NBP
	MOVEI T1,NBP-1
	MOVEM T1,MAXBP
	RET			;DONE

;SET SWAP SPACE PARAMETERS - CALLED FROM DRMINI AFTER DRUM SPACE KNOWN
;ALSO CALLED WHEN NEW PAGES APPAEAR IN SYSTEM
; A/ NUMBER PAGES AVAILABLE FOR SWAPPING

SETSSP::MOVE B,TOTRC		;PREVENT NEW PRIVATE PAGES
	MOVEM B,DRMLV0		;WHEN FREE DRUM EQUALS TOTAL CORE
	IMULI B,2		;DOUBLE THAT LEVEL
	MOVEM B,DRMIN0		;TO CAUSE DDMP ACTIVITY
	RET
;INIT NEW FORK

FKSETP::MOVE T2,SHRPTR		;CONSTRUCT SHARE PTR
	LOAD T1,FKUPT		;GET UPT IDENT
	STOR T1,SPTX,T2		;CONSTRUCT SHARE PTR
	MOVEM T2,PSBM0+UPTPG	;MAP UPT
	MOVEM T2,USECTB		;SET AS USER SECTION 0 ALSO
	LOAD T1,FKPSB
	STOR T1,SPTX,T2		;BUILD SHARE PTR TO PSB
	MOVEM T2,PSBM0+PSBPG	;SET IT IN MON MAP
	LOAD T1,FSSPTN		;GET STACK PAGE I.D.
	STOR T1,SPTX,T2		;MAKE A SHARE POINTER TO IT
	MOVEM T2,PSBM0+PSB1	;POINT TO THE STACK PAGE FROM THE UPT
	RET

;ROUTINE TO CHECK IF A PAGE CAN BE USED (DOESNT NXM)
;T1/ PHYSICAL PAGE
;	CALL CHKPAG
;RETURNS+1(FAILURE):
;	PAGE NOT USEABLE
;RETURNS+2(SUCCESS):
;	PAGE APPEARS OK

CHKPAG:	PIOFF		;PREVENT ANY INTERRUPTS
	PUSH P,CST0(T1)		;SAVE PRESENT STATE
	PUSH P,T1		;SAVE PAGE NUMBER AS WELL
	MOVX T2,PSASM		;ALLOW REFERENCE
	IORM T2,CST0(T1)	; ...
	CALL MAPRCA		;MAP PAGE
	POP P,T2		;RESTORE PAGE NUMBER
	SKIP 0(T1)		;REFERENCE FIRST WORD
	CONSZ APR,APNXM		;NXM?
	JRST CHKPG1		;YES - LOSE QUICKLY
	SKIP 1(T1)		;NO - TRY NEXT 3 WORDS
	SKIP 2(T1)		;IN CASE INTERLEAVE
	SKIP 3(T1)		;DEFECTIVE
	CONSZ APR,APNXM		;STILL NO NXM?
	JRST CHKPG1		;NXM - NOT SUITABLE
	POP P,CST0(T2)		;RESTORE ORIGINAL STATE
	CALL UNMRCA		;CLEAR TEMP MAPPING
	PION
	RETSKP			;SUCCESS RETURN

CHKPG1:	CONO APR,APFCLR+APNXM+APRCHN	;RESET NXM FLAG
	POP P,CST0(T2)		;RESTORE ORIGINAL STATE
	CALL UNMRCA		;RELEASE TEMP MAPPING
	PION
	RET			;FAILURE
;ROUTINES FOR SAVING AND RESTORING SWAPPABLE MONITOR MAP
;AROUND RESTARTS

;SAVE SWAP MON MAP

SAVSMM::MOVEI Q1,SWPMPG-1
	SUB Q1,SWCEND		;COMPUTE NUMBER PAGES IN SWAP MON
	HRLZ Q1,Q1		;SETUP AOBJN PTR
SAVSM1:	MOVE T1,MMAP+SWPMPG(Q1)	;GET CURRENT MAP PTR
	TXNN T1,NCORTM		;IN CORE?
	JRST [	HRRZS T1	;MASK OFF HIGH BITS
		MOVE T1,CST1(T1)	;YES, GET DRUM ADDRESS
		JRST .+1]
	MOVEM T1,TMPSMM(Q1)	;SAVE DRUM ADDRESS
	AOBJN Q1,SAVSM1
	RET

;RESTORE SWAP MON MAP FROM TEMP AREA IN LOW CORE

RESSMM::MOVEI Q1,SWPMPG-1	;COMPUTE NUMBER PAGES IN SWAP MON
	SUB Q1,SWCEND
	HRLZ Q1,Q1
RESSM1:	LOAD T1,STGADR,TMPSMM(Q1) ;GET DRUM ADR FOR THIS PAGE
	CALL DRMASA		;ASSIGN IT
	 BUG(HLT,RSMFAI,<RESSMM-FAILED TO ASSIGN SWAP MON PAGE>)
	LOAD T1,STGADR,TMPSMM(Q1)
	IOR T1,IMMPTR		;MAKE NEW PTR
	MOVEM T1,MMAP+SWPMPG(Q1) ;SETUP MON MAP
	AOBJN Q1,RESSM1
	RET
;RESTART SWAPPER - REINITIATE IO OPERATIONS IN PROGRESS AT TIME OF CRASH

SWPRST::SETZM IOIP
	MOVE 6,MONCOR		;SCAN CST AND CHECK STATE OF PAGES
SWPRS1:	LOAD 1,CSTAGE,(6)	;GET STATE CODE
	CAIN 1,PSRIP		;READ IN PROGRESS?
	JRST SWPRSR		;YES, GO RESTART IT
	CAIN 1,PSWIP		;WRITE?
	JRST SWPRSW		;YES
	CAIL 1,PSASN		;PAGE ASSIGNED TO PROCESS?
	JRST [	MOVE 2,CST3(6)	;YES, SEE IF BEING WRITTEN
		TLNE 2,(DWRBIT)
		JRST SWPRSW	;WAS BEING WRITTEN, RESTART WRITE
		JRST .+1]	;NOT BEING WRITTEN
SWPRS2:	CAMGE 6,NHIPG		;LOOKED AT ALL PAGES?
	AOJA 6,SWPRS1		;NO
	RET

SWPRSW:	MOVSI 1,(DWRBIT)	;WRITE OPERATION
	AOSA IOIP		;COUNT WRITES IN PROGRESS
SWPRSR:	SETZ 1,			;READ OPERATION
	HRRI 1,0(6)
	MOVE 2,CST1(6)		;BACKUP ADDRESS
	TLNE 2,(DSKAB)		;DISK?
	JRST SWPRS3		;YES
	TLNN 2,(DRMAB)		;DRUM?
	BUG(HLT,ILCST1,<ILLEGAL ADDRESS IN CST1 ENTRY, CAN'T RESTART>)
	CALL DRMIO
	JRST SWPRS2

SWPRS3:	CALL DSKIO
	JRST SWPRS2
;PERIODIC ROUTINE TO TRICKLE PAGES TO DISK

DDMPLF==1B0			;LOCAL FLAG IN F, DRUM SP LOW IF 1

DDMP::	AOSE STRLOK		;STRUCTURE BEING DISMOUNTED?
	RET			;YES. FAIL
	SETZ F,			;CLEAR FLAGS
	MOVE 1,DRMFRE
	SKIPE DDTIME		;SYSTEM SHUTDOWN?
	CAMGE 1,DRMIN0		;OR INSUFFICIENT DRUM SPACE?
	TLO F,(DDMPLF)		;YES, TAKE SPECIAL ACTION
	MOVSI P1,-NOFN		;SETUP TO SCAN ALL OFN'S
	AOBJN P1,.+1		;0 NOT USED
DDMP9:	NOSKED
	SKIPN SPTH(P1)		;OFN IN USE?
	JRST DDMP2		;NO
	SETCM 1,SPTH(P1)	;GET THAW AND WRITE BITS
	TXNN 1,FILWB+THAWB	;BOTH 1? (I.E. THAW MODE)
	JRST DDMP3		;YES, UPDATE
	TXNN F,DDMPLF		;DRUM FULL?
	JRST DDMP2		;NO, BYPASS OFN
DDMP3:	MOVX 2,OFNDMO!OFNDUD	;CHECK IF THIS OFN IS DISMOUNTED
				; OR DDMP BEING SUPPRESSED
	TDNE 2,SPTH(P1)		;IS IT?
	JRST DDMP2		;YES. SKIP IT
	MOVX 2,SPTLKB		;TRY TO LOCK OFN
	TDNE 2,SPTH(P1)
	JRST DDMP2		;ALREADY LOCKED, SKIP IT THIS TIME
	IORM 2,SPTH(P1)		;SET LOCK
	OKSKED			;WILL UPDATE OFN, NOW SAFELY LOCKED
	LOAD A,STRX,(P1)	;GET STRUCTURE NUMBER
	CALL UPDBTB		;UPDATE BIT TABLE
	HRLZ 1,P1		;CONSTRUCT IDENT OF FIRST PAGE
	MOVEI 2,PGSIZ		;DO ALL PAGES
	TXNN F,DDMPLF		;DOING DRUM LOW ACTIONS?
	CALL UPDPGS		;NO, REGULAR UPDATE PAGES
	TXNE F,DDMPLF
	CALL UPDPG0		;YES, FLUSH ALL PAGES TO DISK
	HRRZ 1,P1		;GET OFN
	CALL UPDOF0		;UPDATE THE INDEX BLOCK
	MOVX 1,SPTLKB
	ANDCAM 1,SPTH(P1)	;CLEAR LOCK
	JRST DDMP1		;DONE WITH THIS OFN

DDMP2:	OKSKED
DDMP1:	AOBJN P1,DDMP9		;SCAN ALL OFN'S
	SETOM STRLOK		;RELEASE LOCK
	RETSKP			;AND RETURN SUCCESSFULLY
;UPDATE OFN--GET INDEX BLOCK WRITTEN TO DISK
; 1/ OFN
;	CALL UPDOFN
; RETURN +1 ALWAYS, BIT TABLE AND INDEX BLOCK UPDATED

UPDOFN::STKVAR <OFN>
	MOVEM A,OFN
	HRRZ B,A		;GET OFN
	CALL CHKDMO		;SEE IF DISMOUNTED
	 RET			;IT IS. IGNORE REQUEST.
	HRRZ A,OFN		;GET OFN
	CALL LCKOFN		;LOCK OFN AGAINST CHANGES
	MOVX B,OFNWRB		;SEE IF OFN MODIFIED
	TDNN B,SPTH(A)
	JRST UPDOFX		;NOT MODIFIED, DO NOTHING
	LOAD A,STRX,(A)		;GET STRUCTURE NUMBER
	CALL UPDBTB		;UPDATE BIT TABLE
	HRRZ A,OFN		;GET OFN AGAIN
	CALL UPDOF0		;WRITE INDEX BLOCK
UPDOFX:	MOVE A,OFN
	CALL ULKOFN		;UNLOCK OFN
	RET
;SCAN INDEX BLOCK AND WRITE IMAGE TO DISK
;ASSUMES OFN LOCKED AGAINST CHANGES
; A/ OFN
;	CALL UPDOF0
; RETURN +1 ALWAYS
;AC USAGE:
; P1 - OFN
; P2 - AOBJN PTR FOR SCANNING PAGE TABLE
; P3, P4 - TEMPS
; P5 - CHECKSUM

UPDOF0:	SAVEP			;SAVE P1-P6
	CAILE A,0		;ENSURE LEGAL OFN
	CAIL A,NOFN
	BUG(HLT,NOTOFN,<UPDOF0-ARG NOT OFN>)
	MOVEM A,P1		;KEEP OFN AROUND
	LOAD A,STGADR,SPT(P1)	;GET CURRENT ADR OF XB
	TXNE A,DSKAB		;ON DISK?
	RET			;YES, NOTHING TO DO
	MOVX A,OFNWRB
	TDNN A,SPTH(P1)		;CHANGED SINCE LAST UPDATE?
	RET			;NO, NOTHING TO DO
	ANDCAM A,SPTH(P1)	;NOTE OFN NOW UPDATED
	MOVE A,P1
	MOVE B,[PTRW+FPG2A]
	CALL SETMPG		;MAP XB
	MOVEI A,0
	MOVEI B,FPG3A
	CALL SETMPG		;CLEAR A PAGE TO RECEIVE XB IMAGE
	SETZM FPG3A		;MAKE IT EXIST
	MOVEI P5,0		;INIT CHECKSUM
	JCRY0 .+1
	MOVSI P2,-PGSIZ		;SETUP TO SCAN XB
UOFN1:	SKIPE FPG2A(P2)	;ENTRY EXISTS?
	JRST UOFN2		;YES, GO TRACK DOWN DISK ADR
	ADDI P5,0(P2)		;USE XB INDEX FOR 0 WORD IN CHECKSUM
	JCRY0 [AOJA P5,.+1]	;WRAPAROUND CARRY
UOFN6:	AOBJN P2,UOFN1		;SCAN ALL XB
	MOVX A,OFNBAT		;SEE IF OFN HAS BAT BIT
	MOVX B,XBBAT		;IN CASE IT DOES
	TDNE A,SPTH(P1)		;IS IT SET?
	IORM B,XBBWRD+FPG3A	;YES. MARK XB
	; ..
;UPDOFN...
;HAVE FINISHED SCAN OF XB

	MOVEI A,P5		;POINT TO CHECKSUM
	MOVE B,[XBCKSM+FPG3A]	;PUT IT IN FIRST FOUR WORDS OF XB
	CALL STXBD		;STORE CHECKSUM IN XB
	MOVEI A,FPG3A		;GET IDENT FOR IMAGE PAGE
	CALL FPTA
	MOVEM A,P3		;SAVE IT
	CALL MLKPG		;LOCK IMAGE PAGE IN CORE FOR DSKIO
	MOVEM A,P4		;SAVE CORE PAGE NUMBER
	LOAD A,STGADR,SPTH(P1)	;GET DSK ADR OF XB
	MOVX B,DOP%WR+PGSIZ	;SAY WRITE ONE PAGE
	HRRZ C,P4		;SETUP PHYSICAL CORE ADR
	LSH C,PGSFT
	LOAD D,STRX,(P1)	;GET STRUCTURE NUMBER
	CALL UDSKIO		;WRITE TO DISK
	AOS DSKWR		;COUNT WRITES FOR STATISTICS
	EXCH A,P3		;SAVE ERROR BITS, GET CORE PAGE
	CALL MULKPG		;UNLOCK PAGE
	SKIPE P3		;ERROR ON WRITE?
	BUG(CHK,XBWERR,<UPDOFN-DSK WRITE ERROR ON XB>)
UOFNX:	MOVEI A,0
	MOVEI B,FPG2A
	MOVEI C,2
	CALL MSETMP		;UNMAP BOTH PAGES
	RET
;UPDOFN...
;FIND DISK ADDRESS FOR PAGE IN XB

UOFN2:	NOSKED
	MOVE A,FPG2A(P2)	;GET POINTER
	LOAD B,PTRCOD,A		;GET PTR TYPE
	CAIE B,SHRCOD		;SHARE?
	JRST [	LOAD A,STGADR,A	;NO, PRIVATE. GET ADR.
		JRST UOFN3]
	LOAD A,SPTX,A		;GET SPT INDEX
	LOAD A,STGADR,SPT(A)	;GET ADDRESS OF PAGE
UOFN3:	TXNE A,DSKAB		;HAVE DISK ADDRESS?
	JRST UOFN4		;YES, DONE
	TXNE A,DRMAB		;HAVE DRUM ADDRESS?
	JRST UOFN5		;YES
	TXNE A,NCORTM		;CORE ADDRESS?
	JRST [	SETZ A,		;NO, UNASSIGNED. USE 0
		JRST UOFN4]
	CAML A,MONCOR		;LEGAL PAGE NUMBER?
	CAMLE A,NHIPG
	JRST UOFBPP		;NO
	HRRZS A
	LOAD A,STGADR,CST1(A)	;GET NEXT LEVEL ADDRESS
	JRST UOFN3		;GO SEE WHAT IT IS

;HAVE DRUM ADDRESS

UOFN5:	MOVE B,A
	CALL GDSTX		;GET DST INDEX
	HRRZS B
	LOAD A,STGADR,DST(B)	;GET NEXT LEVEL ADDRESS FROM DST
	TXNN A,DSKAB		;IT MUST BE DISK
	JRST UOFBPP		;LOSSAGE
UOFN4:	OKSKED
	STOR A,STGADR,FPG3A(P2) ;PUT DSK ADR IN IMAGE PAGE
	SKIPN A			;PAGE EXISTS?
	HRRZ A,P2		;NO, USE XB INDEX FOR CHECKSUM
	JCRY0 .+1		;CLEAR CARRY FLAG
	ADD P5,A		;DO CHECKSUM
	JCRY0 [AOJA P5,.+1]	;WRAPAROUND CARRY
	JRST UOFN6		;CONTINUE SCAN

;CASES OF BAD POINTER

UOFBPP:	BUG(HLT,ILPPT1,<UPDOFN-BAD POINTER IN PAGE TABLE>)
	OKSKED
	JRST UOFNX		;RETURN WITHOUT WRITING XB
;LOAD/STORE DATA IN INDEX BLOCK.
;SINCE THE STORAGE ADDRESS IS ONLY 23 BITS, THE REMAINING PORTION
;OF EACH WORD CAN BE USED TO STORE USEFUL INFORMATION, E.G. A
;CHECKSUM OF THE INDEX BLOCK.  THESE ROUTINES PACK AND UNPACK
;THE DATA FROM THE XB USING B0-8 OF SUCCESSIVE WORDS.

; A/ ADDRESS OF WORD(S)
; B/ NUMBER OF XB WORDS,,XB ADDRESS + OFFSET
;	CALL STXBD/LDXBD
; RETURN +1 ALWAYS, DATA MOVED BETWEEN XB AND C(C(A))

;STORE DATA INTO INDEX BLOCK

STXBD:	HRLI A,(<POINT 9,0>)	;INIT PTR TO CALLERS DATA
STXBD1:	ILDB C,A		;GET BYTE FROM CALLER
	DPB C,[POINT 9,0(B),8]	;PUT IT IN XB
	AOBJN B,STXBD1		;INCREMENT THROUGH XB
	RET

;LOAD FROM XB

LDXBD:	HRLI A,(<POINT 9,0>)	;INIT PTR TO CALLERS STORAGE
LDXBD1:	LDB C,[POINT 9,0(B),8]	;GET BYTE FROM XB
	IDPB C,A		;PUT IT IN CALLERS STORAGE
	AOBJN B,LDXBD1		;SCAN THROUGH XB
	RET

;ITEMS IN INDEX BLOCK VECTOR

XBCKSM==<-4,,0>			;CHECKSUM--4 WORDS BEGINNING AT 0
;UPDATE FILE PAGES--CAUSE CHANGED PAGES TO BE WRITTEN TO DISK
; 1/ IDENT OF FIRST FILE PAGE, OFN,,PN
; 2/ NUMBER OF SEQUENTIAL PAGES TO UPDATE
;	CALL UPDPGS
; RETURN +1 ALWAYS, ALL WRITES COMPLETED

;AC USAGE:
; P1 - OFN
; P2 - AOBJN PTR FOR SCANNING PT
; P3 - FLAGS
; P4 - COPY OF INITIAL AOBJN PTR

;LOCAL FLAGS

UPGSF0==1B1			;0=WRITE PAGES, 1=WAIT FOR COMPLETION
UPGSLF==1B2			;1=DRUM SPACE LOW, FORCE PAGES TO DSK
UPGKPF==1B3			;0 = USE OFRQ, 1 = USE ONRQ ON SWPOUT

;ROUTINE SCANS PAGE TABLE TWICE.  FIRST TIME TO REQUEST WRITES ON
;ALL CHANGED PAGES, SECOND TIME TO WAIT FOR COMPLETION OF WRITES.
;THIS IS FASTER THAN WAITING FOR EACH WRITE TO COMPLETE AS IT
;IS REQUESTED.

UPDPGS::SAVEP			;SAVE P1-P6
	MOVX P3,UPGKPF		;KEEP PAGES
	JRST UPGS0

UPDPGR::SAVEP			;ENTRY TO REMOVE PAGES QUICKLY
	MOVX P3,0		;CLEAR FLAGS
	JRST UPGS0

;SPECIAL ENTRY FOR DDMP, SET FLAG TO FORCE PAGES TO DSK WHEN DRUM FULL

UPDPG0:	SAVEP
	MOVX P3,UPGSLF+UPGKPF	;SET FULL FLAG AND KEEP PAGES
UPGS0:	HLRZM A,P1		;SAVE OFN
	HRRM A,P2		;SETUP INITIAL PAGE NUMBER
	HRRZ A,A
	ADD A,B			;COMPUTE FINAL PAGE NUMBER
	CAILE A,PGSIZ		;BEYOND END OF PT?
	BUG(HLT,PTOVRN,<UPDPGS-COUNT TOO LARGE>)
	MOVN B,B
	HRLM B,P2		;CONSTRUCT AOBJN PTR TO SCAN PT
	MOVE B,P1		;GET PT
	CALL CHKDMO		;SEE IF IT IS A DISMOUNTED OFN
	 CALLRET DMOINT		;IT IS. GIVE AN ERROR
	MOVEM P2,P4		;SAVE COPY FOR SECOND PASS
	LOAD A,STGADR,SPT(P1)	;GET CURRENT ADR OF INDEX BLOCK
	TXNE A,DSKAB		;ON DISK?
	RET			;YES, NOTHING TO DO
	MOVE A,P1		;MAP PAGE TABLE
	MOVE B,[PTRW+FPG2A]
	CALL SETMPG
UPGS1:	SKIPE FPG2A(P2)	;PAGE EXISTS?
	JRST UPGS2		;YES, GO CHECK IT OUT
UPGS3:	AOBJN P2,UPGS1		;DO ALL PAGES
	MOVE P2,P4		;REINIT AOBJN PTR
	TXON P3,UPGSF0	;DONE PASS 2 YET?
	JRST UPGS1		;NO, GO DO IT
UPGSX:	MOVEI A,0
	MOVEI B,FPG2A
	CALL SETMPG		;RELEASE PT MAPPING
	RET
;UPDPGS...
;INVESTIGATE SPECIFIC PAGE

UPGS2:	NOSKED
UPGS7:	MOVE A,FPG2A(P2)	;GET POINTER
	LOAD B,PTRCOD,A		;GET PTR TYPE
	CAIN B,SHRCOD		;SHARE?
	JRST [	LOAD D,SPTX,A	;YES, GET SPT INDEX
		LOAD A,STGADR,SPT(D) ;GET PAGE ADR FROM SPT
		JRST UPGS9]	;GO PROCESS IT
	MOVE D,P2		;IS PRIVATE. FORM ID
	HRL D,P1		; AS OFN.PN
UPGS9:	TXNE A,DSKAB		;ON DISK?
	JRST UPGS4		;YES, NO UPDATE NEEDED
	TXNN A,DRMAB		;ON DRUM?
	JRST UPGS5		;NO
	TXNE P3,UPGSF0	;YES, PASS 2?
	JRST UPGS4		;YES, WRITE, IF ANY, MUST HAVE COMPLETED
	MOVE B,A		;GET DRUM ADDRESS TO B FOR GDSTX
	CALL GDSTX		;GET DST INDEX
	HRRZS B
	MOVE C,DST(B)		;GET DRUM INFO
	TXNN C,BWRBIT		;PAGE MODIFIED?
	JRST [	TXNN P3,UPGSLF ;NO, DRUM FULL?
		JRST UPGS4	;NO, BYPASS PAGE
		SETOM DST(B)	;DRUM FULL, SO PUT PAGE BACK ON DSK
		TLNE D,-1	;IN SPT OR XB?
		CALL [	HRRZ B,D
			STOR C,STGADR,FPG2A(B) ;IN XB
			RETSKP]	;DONE
		STOR C,STGADR,SPT(D) ;SPT
		CALL DASDRM	;ADJUST POINTER AND DEASSN DRM ADR
		JRST UPGS4]
	MOVE A,D		;MUST SWAPIN PAGE, GET SPT INDEX
UPGS6:	CALL SWPINW		;SWAPIN THE PAGE
	JRST UPGS7		;NOW SHOULD BE IN CORE
;PAGE NOT ON DISK OR DRUM

UPGS5:	TXNE A,NCORTM		;IN CORE?
	JRST UPGS4		;NO, UNASSIGNED. IGNORE.
	TXNE P3,UPGSF0	;PASS 2?
	JRST [	CALL SKPNWR	;YES, WRITE STILL IN PROGRESS?
		 JRST UPGS7	;YES, WAITED FOR COMPLETION
		JRST UPGS4]	;NO, COMPLETED
	MOVX B,CORMB
	HRRZ C,A
	TDNN B,CST0(C)		;PAGE IN CORE MODIFIED?
	TXNE P3,UPGSLF	;OR SWAPPING BECAUSE DRUM FULL?
	JRST UPGS8		;YES, SWAPOUT PAGE
	LOAD B,STGADR,CST1(C)	;NO, SEE IF MODIFIED ON DRUM
	TXNN B,DSKAB		;PAGE BACKUP ON DRUM?
	TXNN B,DRMAB
	JRST UPGS4		;NO, DON'T SWAPOUT
	CALL GDSTX		;YES, GET DRUM INFO
	HRRZS B
	MOVX C,BWRBIT
	TDNN C,DST(B)		;MODIFIED ON DRUM?
	JRST UPGS4		;NOT MODIFIED, NO UPDATE NEEDED
UPGS8:	CALL SKPNWR		;WRITE IN PROGRESS?
	 JRST UPGS7		;YES, RECHECK PAGE
	CALL AGESET		;ASSIGN PAGE
	MOVX B,-PLKV
	TDNE B,CST1(A)		;PAGE LOCKED?
	JRST UPGS4		;YES, LEAVE IT
	MOVX B,DSKSWB
	IORM B,CST3(A)		;REQUEST SWAP TO DISK
	JXN P3,UPGKPF,[CALL SWPOTK ;SWPOUT AND USE ONRQ
		JRST UPGS4]
	CALL SWPOT0		;WRITE PAGE
UPGS4:	OKSKED
	JRST UPGS3		;CONTINUE SCAN OF PT

;CASES OF BAD POINTER

UPGBPP:	BUG(HLT,ILPPT2,<UPDPGS-BAD POINTER IN PAGE TABLE>)
	OKSKED
	JRST UPGSX		;QUIT WITHOUT FURTHER ADO
;ASSIGN OFN
; AC1/ (STGADR) INDEX BLOCK FILE ADDRESS (DISK, DRUM OR CORE)
;          1 WRITE BIT (FILWB)
;          2 THAWED BIT (THAWB)
;	   3 NEW FILE BIT (FILNB)
; AC2/ STRUCTURE NUMBER
; AC3/ DIRECTORY NUMBER
; AC4/ REMAINING PAGES (DRLIQ - DRDCA)
;RETURN SKIP WITH OFN IN AC1 IF PROPER OPENING
;RETURN NO-SKIP IF ILLEGAL SHARED OPENING (ILLEGAL CONFIGURATION
;      OF THAWED AND WRITE BITS)
;FILWB AND THAWB PROVIDE FOR 4 MODES OF OPENING:
; 00 - OPEN FOR READ, OTHER READERS AND 1 OTHER WRITER ALLOWED
; 10 - OPEN FOR WRITE, OTHER READERS ALLOWED BUT NO OTHER WRITERS
; 11 - OPEN 'THAWED' - ARBITRARY OTHER READERS AND WRITERS ALLOWED
; 01 - OPEN 'RESTRICTED' - NO OTHER OPENS ALLOWED
;AC USAGE:
; Q1 - XB ADDRESS/CHECKSUM OF XB
; Q2 - OFN
; FX - STRUCTURE NUMBER
;ENTRY AT ASLOFN ASSIGNS OFN ONLY IF IT ALREADY EXISTS OR
;CURRENT OFN USAGE IS BELOW LONG FILE CUTOFF

ASGOFL::TLOA T2,-1		;REMEMBER ASLOFN ENTRY
ASGOFN::TLZ T2,-1		;REMEMBER ASGOFN ENTRY
	SAVEQ
	MOVEI FX,0(2)		;SAVE STRUCTURE NUMBER
	HRRZ Q2,T3		;COPY DIRECTORY NUMBER
ASGOF1:	CAIGE FX,STRN		;A VALID STRUCTURE NUMBER?
	SKIPN STRTAB(FX)	;YES. DOES THE STRUCTURE EXIST?
	BUG (HLT,STRBAD,<ASOFN-ILLEGAL STRUCTURE NUMBER>)
	TRVAR <PGASG,DNASG,SVX,ENTTYP>
	HLRZM T2,ENTTYP		;REMEMBER IF ASLOFN OR ASGOFN
	MOVEM T4,PGASG		;PAGE ALLOCTION
	MOVEM Q2,DNASG		;DIR NUMBER
ASOFC:	LOAD Q1,STGADR,1	;GET ADDRESS ONLY
	AND 1,[FILWB+THAWB+FILNB+OFNDUD+OFN2XB] ;GET BITS CALLER ALLOWED TO SPECIFY
	IOR 1,Q1		;CONSTRUCT COMPOSIT WORD FOR SPTH
	NOSKED
	TLNN 1,(DSKAB)		;DISK?
	JRST [	MOVEI 1,OPNX16	;NO, RETURN BAD
		JRST ASOFXB]
	MOVEM 1,SVX		;SAVE ADDRESS
ASGOF2:	CALL OFNSRC		;SEARCH SPTH FOR GIVEN DSK ADR
	 JRST ASOF4		;NOT FOUND, GO ADD TO TABLE
	HRRZ Q2,1		;FOUND, GET OFN
	MOVX 2,SPTLKB
	TDNE 2,SPTH(Q2)		;OFN LOCKED?
	JRST [	HRLZ 1,1	;YES, MUST WAIT
		CALL WTOFNL
		MOVE 1,SVX	;RECOVER ADDRESS
		JRST ASOFC]	;START OVER
	IORM 2,SPTH(Q2)		;LOCK IT
	NOINT			;NOINT FOR EACH SPT LOCK
	; ..
;SHARED OPEN, CHECK WRITE AND THAWED BITS FOR LEGAL COMBINATION

	MOVE 2,SVX		;RECOVER CLASS AND BITS
	MOVE 1,SPTH(Q2)		;GET EXISTING THAWB AND FILWB
	TLNE 1,(THAWB)		;FILE NOW OPEN THAWED OR RESTRICTED?
	JRST [	XOR 1,2		;YES, COMPARE EXISTING AND NEW MODES
		TLNN 1,(FILWB+THAWB) ;BOTH THE SAME?
		TLNN 2,(FILWB)	;AND NOT RESTRICTED?
		JRST ASOFB	;NO, REPORT BUSY
		JRST ASOF5]	;THIS OPEN OK
	TLNE 2,(THAWB)		;NEW OPEN CONSISTENT?
	JRST ASOFB		;NO, REPORT BUSY
	TLNN 2,(FILWB)		;NEW OPEN WANTS WRITE?
	JRST ASOF5		;NO, MUST BE OK
	TLOE 1,(FILWB)		;YES, FILE ALREADY HAS WRITER?
	JRST ASOFB		;YES, REPORT BUSY
	MOVEM 1,SPTH(Q2)	;NEW WRITE OPEN OK, UPDATE STATE
ASOF5:	MOVX 1,OFNDUD		;GET DDMP SUPPRESS BIT
	TDNE 1,2		;DID USER REQUEST DDMP SUPPRESS?
	IORM 1,SPTH(Q2)		;YES. SET IT THEN
	MOVEM Q2,SVX		;SAVE OFN FOR ALLOC CODE
	OPSTR <SKIPN>,ALOCX,(Q2) ;HAVE AN ALLOC ENTRY YET?
	CALL ASGALC		;NO. GO GET ONE FOR THIS OFN
	HRRZ 1,SVX		;RETURN OFN (SPT INDEX)
	CALL UPSHR		;INCREMENT SHARE COUNT
	CALL ULKOFN		;UNLOCK
	JRST ASOFXG		;RETURN GOOD

ASOFB:	HRRZ 1,Q2
	CALL ULKOFN		;UNLOCK OFN
	MOVEI 1,OPNX9		;ERROR NUMBER FOR FILE BUSY
	JRST ASOFXB

;EXITS FROM ASOFN

ASOFXB:	TDZA 2,2		;EXIT "BAD"
ASOFXG:	SETO 2,			;EXIT "GOOD"
	OKSKED
	JUMPE 2,R		;BAD = NOSKIP RETURN
	RETSKP			;GOOD = SKIP RETURN
;COULD NOT FIND MATCHING OFN. CREATE ONE.

ASOF4:	SKIPE ENTTYP		;ASLOFN ENTRY?
	JRST [	MOVE Q2,NOF	;YES. GET "OPEN FILE COUNT"
		CAIGE T3,NOFN-NROFN-1 ;CAN WE OPEN ANOTHER LONGY?
		JRST .+1	;YES. PROCEED
		SKIPG ENTTYP	;FIRST TIME?
		JRST [	MOVEI T1,MONX01 ;NO. BOMB
			JRST ASOFXB] ;GIVE UP
		CALL FREOFN	;YES. CLEAN UP OFNS AND TRY AGAIN
		 JFCL
		SETOM ENTTYP	;SAY DONE IT ONCE
		MOVE T1,SVX	;GET BACK ARG
		JRST ASGOF2]	;AND TRY AGAIN
	JUMPN 1,ASOF6		;JUMP IF HAVE DELETED ENTRY TO REUSE
	MOVE 1,MAXSPL		;MUST MAKE NEW ENTRY
	CAIL 1,NOFN-1		;ROOM?
	JRST [	CALL FREOFN	;TRY RELEASING ALL "UNSHARED" OFN
		 SKIPA		;NONE FOUND
		JRST [	MOVE T1,SVX ;GET BACK OFN
			JRST ASGOF2] ;AND TRY AGAIN
		MOVEI 1,OPNX10	;SAY 'NO ROOM'
		JRST ASOFXB]	;RETURN BAD
	AOS 1,MAXSPL		;GET NEXT FREE ENTRY
ASOF6:	HRRZ Q2,1
	MOVE 1,SVX		;RECOVER CLASS AND BITS
	TLZE 1,(FILNB)		;NEWLY ASSIGNED XB?
	TLO Q1,(DSKNB)		;YES, INDICATE IN DISK ADDRESS
	MOVEM 1,SPTH(Q2)
	MOVEM Q1,SPT(Q2)	;PUT ADDRESS IN SPT
	STOR FX,STRX,(Q2)	;PUT IN STRUCTURE NUMBER
	MOVEM Q2,SVX		;SAVE OFN INDEX
	CALL ASGALC		;GO GET AN ALLOC ENTRY FOR THIS OFN
	MOVE Q2,SVX		;GET BACK OFN
	AOS NOF			;COUNT OPEN FILES
	MOVEI 1,1		;SHARE COUNT WILL BE ONE
	STOR 1,OFNSHC,(Q2)	;STORE IT
	; ...
	HRRZ 3,Q2		;COPY OFN
	CALL SETXB1		;MAP XB
	HRRZ T1,Q2		;GET OFN AGAIN
	CALL LCKOFN		;LOCK THE OFN (SOULDN'T BE LOCKED YET
	OKSKED			;NOW ALLOW OTHERS TO  RUN
	SKIP CXBPGA		;GET XB IN MEMORY
	NOSKED			;TAKE OVER MACHINE AGAIN
	CALL ULKOFN		;AND UNLOCK THE OFN
	SKIP CXBPGA		;MUST BE SURE IT IS STILL IN MEMORY
	HRRZ 1,SPT(Q2)		;CORE ADDRESS
	MOVSI 2,(SWPERR)
	TDNE 2,CST3(1)		;DISK ERROR IN XB?
	JRST ASCHK3		;YES, DON'T OPEN
	TXNE Q1,DSKNB		;NEW XB?
	JRST [	MOVX 1,OFNWRB	;YES, NOTE CHANGE FOR NEXT UPDATE
		IORM 1,SPTH(Q2)
		JRST ASCHK4]	;NO CHECKSUM TO COMPUTE
	MOVE A,CXBPGA+XBBWRD	;SEE IF XB HAS A BAD ENTRY
	MOVX B,OFNBAT		;IN CASE IT DOES
	TXZE A,XBBAT		;IS IT SET?
	IORM B,SPTH(Q2)		;YES. REMEMBER THIS IN SPT
	MOVEM A,CXBPGA+XBBWRD	;STORE NEW XB WORD
	MOVEI A,Q1		;POINT TO Q1 TO STORE CHECKSUM
	MOVE B,[XBCKSM+CXBPGA]	;CHECKSUM IS IN FIRST 4 WDS OF XB
	CALL LDXBD		;GET CHECKSUM FROM XB
	SETCA Q1,		;COMPLEMENT IT, SHOULD THEN ADD TO 0
	JCRY0 .+1
	MOVSI 1,-PGSIZ		;SETUP TO SCAN XB
ASCHK1:	LOAD 2,STGADR,CXBPGA(1)	;GET ADDR FROM XB
	JUMPE 2,[ADDI Q1,0(1)	;USE XB INDEX IF WORD EMPTY FOR CHECKSUM
		JCRY0 [AOJA Q1,ASCHK2] ;WRAPAROUND CARRY
		JRST ASCHK2]
	ADD Q1,2		;DO CHECKSUM
	JCRY0 [AOJA Q1,.+1]	;WRAPAROUND CARRY
	IOR 2,IMMPTR		;CONSTRUCT IMMED PTR
ASCHK2:	MOVEM 2,CXBPGA(1)
	AOBJN 1,ASCHK1
	CAME Q1,[-1]		;CHECKSUM OK? (0 OR -0)
	JUMPN Q1,ASCHK3		;JUMP IF CHECKSUM BAD
ASCHK4:	CALL RELCXB		;OK, RELEASE XB
	HRRZ 1,Q2		;RETURN OFN IN 1
	JRST ASOFXG
;ASOFN...
;HANDLE BAD XB

ASCHK3:	CALL RELCXB		;FILE NO GOOD, RELEASE XB
	PUSH P,SPT(Q2)		;SAVE CORE ADR
	MOVE 1,Q2
	CALL DASOFN		;DEASSIGN OFN SLOT
	POP P,1			;RECOVER CORE ADR
	CALL DECOR
	HRRZS 1
	SETZM CST2(1)
	CALL OFRQ		;PUT ON TOP OF RPLQ SINCE PAGE IS USELESS
	MOVEI 1,OPNX16		;ERROR NUMBER FOR BAD XB
	JRST ASOFXB

;ERROR IN ALLOCATION TABLE

ASG6X:	BUG (HLT,OVFLOW,<ASOFN - ALLOCATION TABLE OVERFLOW>)

;ROUTINE TO FREE ALL "UNSHARED" OFNS. CALLED WHEN OFN'S
;RUN OUT
;MUST BE CALLED NOSKED
;RETURNS:	+1 NONE FOUND. OFN'S STILL EXHAUSTED
;		+2 AT LEAST ONE FOUND AND FREED

FREOFN:	ACVAR <Q1>		;GET A WORK REG
	HRLZ T1,MAXSPL		;GET HIGHEST OFN
	MOVN T1,T1		;MAKE AOBJN POINTER
	HRRI T1,1		;START AT FIRST OFN
	SETZM Q1		;NONE FOUND YET
FREOF1:	SKIPN SPTH(T1)		;THIS ONE IN USE?
	JRST FREOF3		;NO. GO ON
	PUSH P,T1		;SAVE AOBJN WORD
	CALL GETSHR		;SEE IF SHARED
	JUMPN T1,FREOF2		;IF SO, JUMP OFF
	HRRZ T1,0(P)		;NOT SHARED.
	CALL CLROFN		;COLLECT IT
	AOS Q1			;FOUND ONE
FREOF2:	POP P,T1		;RESTORE AOBJN POINTER
FREOF3:	AOBJN T1,FREOF1		;DO THEM ALL
	JUMPE Q1,R		;IF NONE FOUND. +1
	RETSKP			;IF SOME FOUND. +2
;CHECK OFN -- SEE IF FILE IN USE BUT DO NOT OPEN
; A/ DISK ADR OF XB (SAME AS ASOFN)
; B/ STRUCTURE NUMBER
;	CALL CHKOFN
; RETURN +1, FILE ALREADY OPEN
; RETURN +2, FILE NOT OPEN

CHKOFN::SAVEQ
	MOVE FX,B		;SAVE STRUCTURE NUMBER
	LOAD Q1,STGADR,1	;SETUP XB ADR
	CALL OFNSRC		;SEARCH FOR IT
	 RETSKP			;NOT FOUND
	RET			;FOUND

;LOCAL ROUTINE TO SEARCH SPTH FOR GIVEN XB ADR
; Q1/ DISK ADR
; FX/ STRUCTURE NUMBER
;	CALL OFNSRC
; RETURN +1, NOT FOUND; 1/ FIRST FREE ENTRY OR 0
; RETURN +2, FOUND; 1/ INDEX

OFNSRC:	HRLZ 1,MAXSPL		;GET COUNT OF ENTRIES IN USE
	MOVN 1,1		;SETUP AOBJN PTR
	HRRI 1,1		;START WITH ENTRY 1 OF SPT
	SETZ 3,			;INIT PLACE TO HOLD DELETED ENTRY IF FOUND
	JUMPGE 1,OFNSR3		;QUIT NOW IF TABLE EMPTY
OFNSR1:	MOVX 2,OFNDMO		;GET DISMOUNTED BIT
	TDNE 2,SPTH(1)		;IS THIS A DISMOUNTED OFN?
	JRST OFNSR2		;YES. DON'T CONSIDER IT
	LOAD 2,STGADR,SPTH(1)	;GET ADR
	JUMPE 2,[SKIPN 3	;ENTRY NOT IN USE, KEEP IT?
		HRRZ 3,1	;YES
		JRST OFNSR2]
	LOAD D,STRX,(1)		;GET THIS ENTRY'S STRUCTURE NUMBER
	CAIN D,0(FX)		;SAME AS REQUESTED?
	CAME B,Q1		;YES. IS DISK ADDRESS THE SAME?
	SKIPA			;NO. LOOK AT MORE
	RETSKP			;YES, DONE
OFNSR2:	AOBJN 1,OFNSR1		;SEARCH ALL EXTANT ENTRIES
OFNSR3:	MOVE 1,3		;NOT FOUND, RETURN FIRST FREE SEEN
	RET
;LOCAL ROUTINE TO DELETE OFN SLOT
; T1/ OFN
;	CALL DASOFN
; RETURN +1 ALWAYS, REDUCE END OF TABLE IF POSSIBLE

DASOFN:	SETZM SPTH(T1)		;FLUSH GIVEN ENTRY
	CALL DASALC		;CLEAR ALLOC DATA
	SETZRO OFNSHC,(T1)	;CLEAR SHARE COUNT IN THE OFN
	SOS NOF			;NOTE ONE LESS OPEN FILE
	CAME T1,MAXSPL		;THIS ENTRY LAST ONE IN TABLE?
	RET			;NO, DONE
DASOF2:	SOSE T2,MAXSPL		;YES, REDUCE LENGTH OF TABLE
	SKIPE SPTH(T2)		;NEW LAST ENTRY ALSO FREE?
	RET
	JRST DASOF2		;YES, REDUCE AGAIN

;ROUTINE TO CLEAR ALLOC DATA FROM OFN
;	T1/ OFN

DASALC:	LOAD T2,ALOCX,(T1)	;GET INDEX TO ALLOCATION INFO
	JUMPE T2,R		;IF NO TABLE, RETURN
	SETZM OFNLEN(T1)	;ZERO LENGTH INFO
	SETZRO ALOCX,(T1)	;ZERO IT
	DECR ODIRC,(T2)		;DECREMENT OFN COUNT
	JN ODIRC,(T2),R		;OK IF STILL OPEN OFN'S
	SETZRO ALCWD,(T2)	;CLEAR SLOT IF COUNT =0
	SETZRO PGLFT,(T2)	; ...
	RET			;AND DONE

;ROUTINE TO LOOK FOR AN APPROPRIATE ALLOC ENTRY

ASGALC:	MOVE Q2,DNASG		;GET DIRECTORY NUMBER
	CALL PGTCAL		;SEE IF CURRENT ENTRY
	 JRST ASOF6A		; NO - MAKE NEW ENTRY
	MOVE Q2,SVX		;RESTORE OFN INDEX
	JRST ASOF6B		;JUST INCREMENT COUNT

;HERE TO CREATE NEW DIRECTORY ALLOCATION ENTRY

ASOF6A:	MOVE Q2,SVX		;GET OFN
	MOVE T2,[-NOFN-1,,1]	;PREPARE AOBJN PNTR
	OPSTR <SKIPE>,ALCWD,(T2) ;LOOK FOR EMPTY SLOT
	AOBJN T2,.-1		;...
	JUMPGE T2,ASG6X		;ERROR IF NO ROOM
	MOVE T1,DNASG		;GET DIRECTORY NUMBER
	STOR T1,ADIRN,(T2)	;SAVE IN TABLE
	MOVE T1,PGASG		;PAGES LEFT IN QUOTA
	STOR T1,PGLFT,(T2)	;STORE
ASOF6B:	STOR T2,ALOCX,(Q2)	;TABLE INDEX TO SPT
	SETZM OFNLEN(Q2)	;CLEAR EOF INFO
	INCR ODIRC,(T2)		;INCREMENT OFN DIRECTORY COUNT
	RET			;ALL DONE.
;LOCK/UNLOCK OFN
;LOCKING OFN PREVENTS ANY CHANGE TO IT, E.G. ADDING OR DELETING PAGES

;LOCK OFN
; A/ OFN
;	CALL LCKOFN
; RETURN +1 ALWAYS, BLOCK AND WAIT IF ALREADY LOCKED

LCKOFN:
LCKOF1:	MOVX 2,SPTLKB
	NOSKED
	TDNE 2,SPTH(1)		;LOCK NOW CLEAR?
	JRST [	HRLZ 1,1	;SETUP SCHED TEST
		CALL WTOFNL	;OKSKED AND DISMISS
		HLRZ 1,1	;RECOVER OFN
		JRST LCKOF1]	;TRY AGAIN
	IORM 2,SPTH(1)		;SET LOCK
	NOINT			;NOINT FOR EACH SPT LOCK
	OKSKED
	RET

;ROUTINE TO DO OKSKED AND DISMISS FOR OFN LOCK
; A/ OFN,,0
;	CALL WTOFNL
; RETURN +1 ALWAYS

WTOFNL:	OKSKED
	HRRI A,OFNLKT
	MDISMS
	RET

;SCHED TEST FOR OFN UNLOCKED

OFNLKT:	MOVX 2,SPTLKB
	TDNE 2,SPTH(1)
	JRST 0(4)
	JRST 1(4)

;UNLOCK OFN
; A/ OFN
;	CALL ULKOFN
; RETURN +1 ALWAYS

ULKOFN:	MOVX 2,SPTLKB
	ANDCAM 2,SPTH(1)	;CLEAR LOCK
	OKINT
	RET
;LOCK/UNLOCK FOR CONVENIENCE WHERE PAGE ID IN A

;LOCK OFN

LCKOFI:	SAVET
	HLRZ A,A		;GET OFN
	CAIGE A,NOFN		;REALLY AN OFN?
	CALL LCKOFN		;YES, LOCK IT
	RET

;UNLOCK

ULKOFI:	SAVET
	HLRZ A,A		;GET OFN
	CAIGE A,NOFN		;REALLY AN OFN?
	CALL ULKOFN		;YES, UNLOCK IT
	RET
;RELEASE/DELETE OFN
; A/ OFN
;	CALL RELOFN/DELPT
; RETURN +1 ALWAYS, A/ PAGE COUNT IN XB IF FILE COMPLETELY CLOSED,
;		-1 IF FILE NOT COMPLETELY CLOSED.

DELOF==1B0			;LOCAL FLAG IN Q1 FOR DELETE/RELEASE

DELPT::	SAVEQ
	MOVX Q1,DELOF		;SAY DELETE
	JRST RELOF0

RELOFN::MOVX B,OFNWRB		;OFN NEEDS UPDATING?
	TDNE B,SPTH(A)
	CALL UPDOFN		;YES, DO IT
	SAVEQ
	MOVEI Q1,0		;SAY RELEASE
RELOF0:	TRVAR <OFNX,XBX>
	CALL LCKOFN		;LOCK THE OFN
	MOVE 2,1		;MOVE OFN
	CALL GETSHR		;GET OFN SHARE COUNT
	EXCH 1,2		;COUNT TO 2 AND OFN TO 1
	CAIE 2,1		;IS THIS FINAL CLOSE?
	JRST RELOF6		;NO
	NOSKED
	MOVX 2,OFNDMO		;CHECK IF DISMOUNTED
	TDNE 2,SPTH(1)		;IS IT?
	JRST [	CALL DASOFN	;YES. DEASSIGN THE OFN
		OKSKED		;ALLOW SCHEDULING AGAIN
		OKINT		;ALLOW INTS AGAIN
		RET]		;AND DONE
	MOVEI 3,0(1)
	CALL SETXB1		;MAP INDEX BLOCK
	MOVEM T1,OFNX		;SAVE THE OFN
RLOF00:	SKIP CXBPGA		;SWAP IN XB, IF NECESSARY
	LOAD T1,STGADR,SPT(T1)	;GET CORE PAGE
	CALL SKPNWR		;MAKE SURE NOT BEING WRITTEN
	 JRST [	MOVE T1,OFNX	;IT WAS. GET OFN AGAIN
		JRST RLOF00]	;AND TRY IT AGAIN
	MOVX T3,PLKV		;GET A UNIT OF LOCK COUNT
	ADDM T3,CST1(T1)	;LOCK XB FOR REST OF RELOFN
	MOVE T1,OFNX		;GET THE OFN
	CALL SCNOFN		;MOVE ALL OF THE PAGES TO DISK
	 JRST RELOF4		;BAD XB .DON'T RELEASE IT
	SKIPE Q2,T1		;FOUND SOME PAGES
	TXNN Q1,DELOF		;YES. WANT DELETE?
	JRST RELOF7		;NO. GO ON
	MOVEM Q2,XBX		;YES. SAVE COUNT OF PAGES
	MOVE 2,OFNX		;GET OFN
	LOAD 3,ALOCX,(2)	;GET INDEX
	OPSTRM <ADDM Q2,>,PGLFT,(3) ;UPDATE COUNT OF PAGES
	MOVE 2,SPTH(2)
	TXNN 2,OFNBAT		; A BAD OFN?
	JRST OFNDLN		;NO. DO A FAST DELETE THEN
	JRST DELBAD		;YES, GO DELETE BAD OFN
RELOF7:	MOVE 1,OFNX		;RECOVER OFN
	CALL DWNSHR		;DECREMENT SHARE COUNT
	MOVE 3,SPTH(1)		;SAVE FLAGS
	MOVEM 3,XBX		;SAVE FLAGS
	LOAD C,STRX,(1)		;GET STRUCTURE NUMBER
	MOVEM C,OFNX		;SAVE IT FOR LATER
	CALL DASOFN		;RELEASE SPT SLOT
	LOAD 1,STGADR,SPT(1)	;GET (CORE) ADDRESS OF XB
	MOVSI T2,(-PLKV)	;GET A NEGATIVE UNIT OF LOCK COUNT
	ADDM T2,CST1(T1)	;UNLOCK XB
	OKINT			;MATCH NOINT DONE BY LCKOFN
	CALL REMFP1		;FLUSH CORE AND DRUM ADDRESSES
	SKIPN 1
	BUG(HLT,NOADXB,<RELOFN-NO DSK ADR FOR XB>)
	MOVE 2,XBX		;RESTORE FLAGS
	MOVE C,OFNX		;GET STRUCTURE NUMBER
	TXNE Q1,DELOF		;DELETING FILE?
	CALL DEDSKC		;YES, DELETE DISK ADR OF XB
	MOVE 1,Q2		;RETURN PAGE COUNT
RELOF4:	CALL RELCXB		;RELEASE TEMP MAPPING
	OKSKED
	RET
;THIS ROUTINE IS GOTTEN TO WHEN THE CALLER WANTS TO DELETE THE
;OFN AND IT DOES NOT CONTAIN A BAT BLOCK.

OFNDLN:	MOVSI Q2,-PGSIZ		;SCAN WHOLE XB
OFNDL1:	SKIPN CXBPGA(Q2)	;AN ENTRY HERE?
	JRST OFNDL2		;NO
	LOAD 1,STGADR,CXBPGA(Q2) ;GET DISK ADDRESS
	MOVE B,OFNX		;GET OFN
	LOAD B,STRX,(B)		;GET STRUCTURE NUMBER
	CALL DEDSK		;RELEASE THE PAGE
	SETZM CXBPGA(Q2)	;CLEAN UP
OFNDL2:	AOBJN Q2,OFNDL1		;DO WHOLE XB
	JRST RELOF7		;NOW GO DO XB ITSELF

;RETURN WHEN FILE NOT CLOSED BECAUSE SHARE COUNT NOT 0

RELOF6:	CALL DWNSHR		;DECREMENT SHARE COUNT
	MOVE 2,SPTH(1)		;GET CURRENT BITS
	TXNN 2,OFNDMO		;DISMOUNTED?
	TLNE 2,(THAWB)		;OPEN IN RESTRICTED OR THAWED MODE?
	JRST RELOF1		;YES, NO UPDATE OF BITS NEEDED
	TLNE 1,(FILWB)		;NO, IS THIS THE WRITER?
	TLZ 2,(FILWB)		;YES, AFTER THIS CLOSE, FILE HAS NO WRITER
	MOVEM 2,SPTH(1)		;UPDATE BITS
RELOF1:	CALL ULKOFN		;UNLOCK OFN
	SETO 1,			;RETURN -1 FOR COUNT
	RET

RELBAD:	BUG(CHK,ILIBPT,<BAD POINTER TYPE IN INDEX BLOCK>)
	SETO 1,			;SAY FILE NOT CLOSED
	RET			;RETURN BAD

;CLEAR OFN FOUND WHEN SWAPPING OUT PAGE
; A/ OFN

CLROFN:	CALL DASOFN		;RELEASE OFN SLOT
	LOAD 1,STGADR,SPT(1)	;GET CORE ADR
	CALLRET REMFP1		;RELEASE STORAGE
;ROUTINE TO SCAN AN XB AND MOVE ALL OF ITS PAGES TO DISK.
;CALLED WITH T1/ THE OFN
;AND THE XB MAPPED INTO CXBPGA
; RETURNS +1 WITH T1/ COUNT OF PAGES

SCNOFN:	ACVAR <W1,W2,W3>	;GET SOME WORK REGS
	MOVE W3,T1		;SAVE THE OFN
	MOVSI W1,-PGSIZ		;SCAN XB
	SETZ W2,		;INIT COUNT OF IN-USE PAGES
SCNOF3:	MOVE 2,CXBPGA(W1)	;GET PTR
	JUMPE 2,SCNOF2		;JUMP IF EMPTY
	LOAD T1,PTRCOD,T2	;GET PTR TYPE
	CAIE T1,IMMCOD		;PRIVATE?
	JRST RELBAD		;NO, LOSSAGE
	TXNE 2,DSKAB		;ON DSK?
	JRST SCNOF5		;YES
	TXNE 2,NCORTM		;IN CORE?
	JRST [	TXNE 2,DRMAB ;NO, PRIVATE UNASSIGNED?
		JRST .+1	;NO. MUST MOVE IT TO DISK THEN
		SETZM CXBPGA(W1) ;FLUSH UNASSIGNED PTR
		JRST SCNOF2]
	MOVE 4,W1		;SET UP ARGUMENT FOR CALL
	HRL 4,W3		;PROVIDE THE OFN AS WELL
	CALL MOVDSK		;MOVE THE PAGE TO DISK
SCNOF4:	MOVE T1,CXBPGA(W1)	;GET PRESENT ADDRESS
	TXNE T1,NCORTM		;STILL IN CORE?
	JRST SCNOF3		;NO
	LOAD T1,STGADR,T1	;GET JUST PAGE NUMBER IN T1
	CALL SKPNWR		;WAIT FOR WRITE TO COMPLETE
	 JRST SCNOF4		;RECHECK
	LOAD T2,CSTAGE,(T1)	;CHECK STATUS
	CAIE T2,PSRPQ		;ON RPLQ?
	CALL OFRQ		;NO, PUT IT ON
	CALL RPCST		;FORCE DISK ADR BACK TO XB
	JRST SCNOF3		;LOOK AT PTR AGAIN, SHOULD BE DSK ADR

SCNOF5:	AOS W2			;COUNT THE PAGE
SCNOF2:	AOBJN W1,SCNOF3		;SCAN XB
	MOVE T1,W2		;RETURN COUNT OF PAGES FOUND
	RETSKP			;AND DONE
;HERE TO DELETE A FILE (OFN) WHICH HAS ONE OR MORE BAT PAGES IN IT

DELBAD:	OKSKED			;ALLOW SCHEDULING FOR A WHILE
	NOINT			;BUT PREVENT LOCAL INTERRUPTS
	MOVEI 1,FPG3A		;YES. LOCK DOWN A PAGE
	CALL MLKMA		;GET IT
	LSH 1,PGSFT		;MAKE IT A CORE ADDRESS
	MOVE P3,1		;AND SAVE IT
OFNFIN:	SETZ P5,		;NO ERROR HERE
	MOVSI P1,-PGSIZ		;SIZE OF XB
	SETO P2,		;NO DRIVE FOUND YET
	NOSKED			;PROTECT XB SCANNING
TOPOFN:	LOAD 1,STGADR,CXBPGA(P1) ;GET ENTRY
	JUMPE 1,NOPGH		; ANYTHING HERE?
	TXZ 1,DSKAB		;CLEAR DEVICE TYPE
	MOVE B,OFNX		;GET OFN
	LOAD D,STRX,(B)		;GET STRUCTURE NUMBER
	MOVE B,STRTAB(D)	;GET SDB INDEX
	IDIV A,SDBSIZ(B)	;COMPUTE UNIT NUMBER AND LOCAL ADDRESS
	MOVE P4,2		;SAVE DISK ADDRESS
	SKIPL P2		;HAVE A DRIVE YET?
	JRST HAVBAT		;YES. GO LOOK AT IT
	OKSKED			;ALLOW INTS FOR BAT BLOCK LOGIC
	MOVE P2,1		;ESTABLISH THIS DRIVE
	MOVE B,P3		;CORE ADDRESS
	MOVEI C,FPG3A		;VIRTUAL ADDRESS
	CALL RDBAT		;GO READ THE BAT BLOCKS
	 JRST BUMBAT		;NO THERE
	MOVE B,P4		;RESTORE LOCAL DISK ADDRESS
	NOSKED			;PROTECT THE SCANNING
	JRST YESBAT
;HAVE BAT BLOCKS IN FOR THIS UNIT. NOW GO DO COMPARE

HAVBAT:	CAIE A,0(P2)		;IS THIS THE PROPER UNIT?
	JRST NOPGH		;NO
YESBAT:	JUMPN P5,NOTBD1		;IS OK.
	MOVE A,B		;GET LOCAL ADDRESS
	MOVEI B,FPG3A		;WHERE THE BAT BLOCK IS
	MOVE C,OFNX		;GET OFN
	LOAD C,STRX,(C)		;GET STRUCTURE NUMBER
	MOVE C,STRTAB(C)	;GET SDB ENTRY
	MOVE C,STRUDB(C)	;GET A UDB ADDRESS FOR ONE OF THIS TYPE
	CALL SEEADR		;SEE IF THIS IS THERE
	 JRST NOTBD1		;NO
	JRST BADD		;YES.

NOTBD1:	LOAD 1,STGADR,CXBPGA(P1) ;GET DISK ADDRESS
	MOVE B,OFNX		;GET OFN
	LOAD B,STRX,(B)		;GET STRUCTURE NUMBER
	CALL DEDSK		;RELEASE PAGE
BADD:	SETZM CXBPGA(P1)	;CLEAR SLOT
	SOSG XBX		;ALL DONE?
	JRST ALLDNE		;YES.
NOPGH:	AOBJN P1,TOPOFN		;GO DO REST
	OKSKED			;ALLOW SCHEDULING
	JRST OFNFIN		;AND DONE

BUMBAT:	MOVEI P5,1		;SAY NO BAT BLOCKS HERE
	NOSKED			;PREVENT SCHEDULING
	JRST NOTBD1		;GO FREE THE PAGE

;FINISHED THE SCAN OF THE BAD INDEX BLOCK. NOW RELEASE WORK
;PAGE AND PROCEED TO FREE THE INDEX BLOCK ITSELF.

ALLDNE:	OKSKED			;ALLOW SCHEDULING
	MOVE A,P3		;GET PHYSICAL ADDRESS
	LSH A,-PGSFT		;MAKE IT A PAGE NUMBER
	CALL MULKCR		;AND RELEASE IT
	OKINT			;PAGE IS RELEASED, ALLOW INTERRUPTS AGAIN
	NOSKED			;PROTECT THE XB RELEASE
	JRST RELOF7
;ROUTINE TO MARK THAT AN OFN IS ON A DISMOUNTED STRUCTURE. 
;ACCEPTS:	A/ THE OFN
;MUST BE CALLED WITH THE OFN LOCKED AND THE PROCESS NOINT.
;THIS ROUTINE WILL RELEASE ALL LOCAL STORAGE ASSOCIATED WITH THE
;OFN AND WITH ANY SHARE POINTERS ASSOCIATED WITH THE OFN. IN
;ADDITION IT WILL MARK THE OFN AS INVALID SO THAT SUBSEQUENT PAGE
;FAULTS ON IT OR ANY OF ITS PAGES CAN BE CONVERTED INTO MEMORY
;TRAPS.

	SWAPCD			;CALLED FROM PROCESS CONTEXT

INVOFN:	SAVEP			;GET SOME WORK REGISTERS
	HRRZ P2,A		;SAVE OFN HERE

;NOW MAP OFN AND SCAN IT RELEASING ALL PRIVATE STORAGE

	MOVEI T3,0(P2)		;GET OFN IN T3
	CALL SETXB1		;MAP INDEX BLOCK
INVRTY:	MOVSI P1,-PGSIZ		;SCAN ENTIRE INDEX BLOCK
	SKIP CXBPGA		;FAULT IN PAGE BEFORE NOSKED
	NOSKED			;PROTECT THE XB
INOF2:	SKIPN T1,CXBPGA(P1)	;ANYTHING HERE?
	JRST INOF3		;NO. GO ON
	LOAD T2,PTRCOD,T1	;GET POINTER
	CAIN T2,IMMCOD		;IMMEDIATE?
	JRST [	LOAD T1,STGADR,T1 ;GET STORAGE ADDRESS
		CALL REMPGI	;GO ZAP THE PAGE
		 JRST INVRTY	;HAD TO BLOCK. GO CHECK IT AGAIN
		STOR T1,STGADR,CXBPGA(P1) ;PUT SOMETHING BACK
		JRST INOF3]	;AND PROCEED
	LOAD P3,SPTX,T1		;GET SPT INDEX
	LOAD T1,STGADR,SPT(P3)	;GET SPT ADDRESS
	CALL REMPGI		;GO ZAP THE PAGE
	 JRST INVRTY		;HAD TO BLOCK. GO TRY IT AGAIN
	STOR T1,STGADR,SPT(P3)	;PUT IN A NEW ADDRESS
INOF3:	AOBJN P1,INOF2		;DO ENTIRE INDEX BLOCK

;NOW RELEASE STORAGE ASSOCIATED WITH THE OFN

	LOAD A,STGADR,SPT(P2)	;GET CURRENT LOCATION
	CALL REMPGI		;RELEASE THE STORAGE
	 JRST INVRTY		;HAD TO BLOCK. TRY AGAIN
	STOR A,STGADR,SPT(P2)	;PUT IN HOME ADDRESS
	MOVX T2,OFNDMO		;GET DISMOUNTED BIT
	IORM T2,SPTH(P2)	;MARK THE OFN
	MOVE A,P2		;GET OFN IN 1
	CALL DASALC		;RELEASE ALOC ENTRY FOR THIS OFN
	OKSKED			;ALLOW SCHEDULING AGAIN
	CALLRET RELCXB		;RELEASE XB MAPPING

;ROUTINE TO RELEASE STORAGE FOR INVOFN. WAITS FOR ANY WRITES TO COMPLETE
;BEFORE CALLING REMFP1

REMPGI:	TXNE T1,DSKAB!DRMAB	;IS THIS A CORE PAGE?
	JRST REMPG2		;NO. GO RELEASE IT NOW
	PUSH P,T1		;YES. SAVE I.D.
REMPG1:	CALL SKPNWR		;WAIT FOR WRITE TO COMPLETE
	 JRST [	POP P,0(P)	;CLEAN UP STACK
		OKSKED		;ALLOW SCHEDULING FOR THE RETRY CODE
		RET]		;SAY WE BLOCKED.
	POP P,T1		;RESTORE I.D.
REMPG2:	CALL REMFP1		;GO RELEASE STORAGE
	RETSKP			;AND RETURN SUCCESSFULLY
;ROUTINE CALLED FROM JSYS CODE TO SCAN OFN'S AND MARK EACH ONE
;ON THE STRUCTURE IN QUESTION DISMOUNTED.
;ACCEPTS:	A/ STRUCTURE NUMBER
;RETURNS:	+1 ALWAYS. WITH ALL OFN'S MARKED AND ALL
;		   LOCAL STORAGE RELEASED

MRKOFN::ASUBR<STRMRK>		;SAVE STRUCTURE NUMBER
	STKVAR <LOOPER>		;SAVE LOOP COUNTER
	MOVSI A,-NOFN		;SEARCH ALL OFN'S
MRKOF3:	MOVEM A,LOOPER		;REMEMBER CURRENT LOOPER
MRKOF4:	NOSKED			;GAIN CONTROL OF THE SYSTEM
	SKIPN SPTH(A)		;THIS OFN IN USE?
	JRST [	OKSKED		;NO. SKIP IT
		JRST MRKOF1]	;""
	MOVX B,SPTLKB		;SEE IF LOCKED
	TDNE B,SPTH(A)		;IS IT?
	JRST [	HRLZS A		;GET OFN TO LH
		CALL WTOFNL	;WAIT FOR OFN TO UNLOCK
		MOVE A,LOOPER	;GET BACK INDEX
		JRST MRKOF4]	;GO RECHECK IT
	IORM B,SPTH(A)		;NO. LOCK IT
	NOINT			;PREVENT INTERRUPTION
	OKSKED			;AND ALLOW SCHEDULING AGAIN
	LOAD B,STRX,(A)		;GET ITS STRUCTURE NUMBER
	CAME B,STRMRK		;THE SAME AS THE ONE DSIMOUNTING?
	JRST MRKOF2		;NO. SKIP IT
	MOVX B,OFNDMO		;SEE IF DISMOUNTED
	TDNE B,SPTH(A)		;IS IT?
	JRST MRKOF2		;YES. SKIP IT
	CALL INVOFN		;MARK IT AND ITS SHARE POINTERS
	MOVE A,LOOPER		;RESTORE OFN
MRKOF2:	CALL ULKOFN		;FREE THIS OFN
	MOVE A,LOOPER		;GET BACK LOOP CONTROL
MRKOF1:	AOBJN A,MRKOF3		;DO ALL OF THEM
	RET			;DONE

	RESCD			;RETURN TO RESIDENT CODE
;ROUTINE TO SEARCH FOR THE QUOTA ALLOCATION ENTRY FOR
;A GIVEN DIRECTORY.
;CALL:
; Q2/ DIRECTORY NUMBER
; FX/ STRUCTURE NUMBER
;	CALL PGTCAL
; RETURN +1, DIRECTORY NOT OPENED
; RETURN +2, FOUND, T1/ CURRENT QUOTA, T2/ INDEX INTO ALCWD

PGTCAL:	HRLZ T3,MAXSPL		;GET CURRENT SPT LENGTH
	JUMPE T3,R		;RETURN IF EMPTY
	MOVNS T3		;MAKE AOBJN PNTR
	HRRI T3,1
GETC1:	LOAD T2,ALOCX,(T3)	;GET INDEX
	JUMPE T2,GETCN		;SKIP NULL ENTRIES
	LOAD T1,ADIRN,(T2)	;GET DIR #
	CAME T1,Q2		;WANT THIS ONE?
	JRST GETCN		;NO - TRY NEXT
	LOAD T1,STRX,(T3)	;GET STR #
	CAME T1,FX		;CORRECT STR?
	JRST GETCN		;NO - TRY SOME MORE
	LOAD T1,PGLFT,(T2)	;YES - GET QUOTA LEFT
	RETSKP			;GIVE GOOD RETURN

GETCN:	AOBJN T3,GETC1		;LOOP TILL DONE
	RET			;FAILED (NOT FOUND)

;GLOBAL ROUTINE FOR PGTCAL
; T1/ DIRECTORY NUMBER
; T2/ STRUCTURE NUMBER

GETCAL::SAVEQ			;SAVE Q1-Q3
	HRRZ Q2,T1		;COPY ARGS TO
	HRRZ FX,T2		;SET UP FOR PGTCAL
	CALLRET PGTCAL

;ADJALC - ADJUST ALLOCATION TABLE ENTRY FOR THIS DIRECTORY

;ACCEPTS:
;	T1/ DIRECTORY NUMBER
;	T2/ STRUCTURE NUMBER
;	T3/ AMOUNT TO ADD TO THE ALLOCATION FOR THIS DIRECTORY

;	CALL ADJALC

;RETURNS +1: ALWAYS

ADJALC::STKVAR <ADJADL>
	MOVEM T3,ADJADL		;SAVE CHANGE 
	NOSKED			;NOSKED WHILE FINDING AND CHANGING SLOT
	CALL GETCAL		;GET CURRENT AVAILABLE PAGE COUNT
	 JRST ADJAL1		;NO OPEN FILES IN THIS DIRECTORY
	ADD T1,ADJADL		;ADD THE INCREMENT
	STOR T1,PGLFT,(T2)	;STORE UPDATED VALUE IN ALLOCATION ENTRY
ADJAL1:	OKSKED			;ALLOW SCHEDULING AGAIN

	RET
;ASSIGN PAGE TABLE USING LOCAL VALUES. CALLED FROM DSKALC TO
;ASSIGN AN SPT FOR THE NASCENT BITTABLE.

ASSPTL::SAVEQ			;SAVE REGISTERS
	MOVE FX,FORKX		;USE LOCAL FORK INDEX

;ASSIGN PSB FOR NEW PROCESS
; FX/ FORK INDEX

ASSPT::	SKIPG 1,FRESPT		;ANY FREE CELLS?
	BUG(HLT,SPTFL1,<SPT COMPLETELY FULL>)
	HRRZ 1,0(1)
	EXCH 1,FRESPT
	SUBI 1,SPT
	AOS SPTC		;ASSIGN SPT SLOT
	MOVX 2,UAAB		;NO ACCESS
	MOVEM 2,SPT(1)		;SHARE COUNT OF 1, NO ADDRESS
	CALL UPSHR		;SET SHARE COUNT TO ONE
	HRRZM FX,SPTH(1)	;SPTH HOLD OWNER FORK INDEX
	RET

;DEASSIGN SPT AND RELEASE STORAGE

DESPT::	CALL DWNSHR		;DECREMENT SHARE COUNT
	PUSH P,1		;SAVE SPT INDEX
	CALL GETSHR		;GET CURRENT SHARE COUNT
	SKIPE 1			;IS IT NOW UNSHARED?
	BUG(HLT,SHRNO0,<DESPT-SHARE COUNT NON-ZERO>)
	POP P,1			;YES. RESTORE SPT
	LOAD 2,STGADR,SPT(1)	;GET STORAGE ADDRESS
	TXNN 2,NCORTM		;PAGE IN CORE?
	JRST [	MOVSI 3,(-PLKV)	;YES
		TDNE 3,CST1(2)	;LOCKED?
		JRST DESPX1
		JRST .+1]	;NO, OK
	PUSH P,1
	MOVE 1,2		;MOVE STORAGE ADDRESS
	CALL REMFP1		;RELEASE CORE AND/OR DRUM
	SKIPE 1			;BE SURE NOTHING LEFT TO DELETE
	BUG(HLT,PTDEL,<DESPT-PT NOT DELETED>)
	POP P,1
	MOVEI 1,SPT(1)		;CONSTRUCT PTR
	EXCH 1,FRESPT		;PUT ON FREE LIST
	EXCH 1,@FRESPT
	SOS SPTC
	RET

DESPX1:	BUG(HLT,PAGLCK,<DESPT-PAGE LOCKED>)

;ASSIGN FORK STORAGE BLOCK (JSB, PSB, UPT)

ASFSB::CALLRET ASSPT		;ASSIGN SPT SLOT ONLY
   REPEAT 0,<			;FOLLOWING NOT PRESENTLY USED
	ACVAR <Q1>
	CALL ASSPT		;ASSIGN SPT SLOT
	MOVEM T1,Q1		;SAVE IT
	CALL DRMASN		;ASSIGN SWAP STORAGE
	 BUG(HLT,DRMFL1,<ASFSB-UNEXPECTED DRUM FULL>)
	STOR T1,STGADR,SPT(Q1)	;PUT ADR IN SPT
	MOVEM T1,T2
	CALL GDSTX		;GET DST INDEX
	MOVX T1,UAAB		;SET DST
	MOVEM T1,DST(T2)
	MOVE T1,Q1		;RETURN SPT INDEX
	RET
   >				;END REPEAT 0

;SPECIAL ROUTINE USED BY SCHEDULER TO DELETE SECOND PSB PAGE.
;CALLED FROM HLTFK1.

   REPEAT 0,<
DESSTK::SKIPN T1,PSBMAP+PSBMSZ-1 ;SEE IF PAGE EXISTS
	RET			;NO. NOTHING TO DO THEN
	LOAD T1,STGADR,T1	;GET STORAGE ADDRESS ONLY
	SETZM PSBMAP+PSBMSZ-1	;ASSUME IT IS NOW CLEARED
	CALLRET REMFP1		;AND GET RID OF IT
   >				;END OF REPEAT 0
;READ MAP GIVEN VIRTUAL ADDRESS

MRMAP::	CALL FPTA		;GET PAGE TABLE ADDRESS
;**********
;TEMP FIX TO FPTA RETURNING A ZERO....
;************
	JUMPE T1,RDMQ5

;GENERAL MAP READ
;ENTER HAVING PTN.PN IN 1
; RETURN +1 IF PTN.PN
; RETURN +2 IF OFN.PN

MRPT::	SAVEQ
	HLRZ 2,1		;GET PTN
	CALL CHKDMO		;SEE IF A DISMOUNTED OFN
	 CALLRET DMOINT		;IT IS. GIVE ERROR AND RETURN
	CALL SETCPT
	HRRZ Q2,1
	MOVE 2,CPTPGA(Q2)	;GET MAP WORD
	JUMPE 2,RDMQ5		;EMPTY
	LOAD Q1,PTRCOD,2	;GET PTR TYPE
	CAIN Q1,IMMCOD		;PRIVATE?
	JRST MRM1		;YES
	CAIE Q1,SHRCOD		;SHARED OR INDIRECT?
	JRST [	LOAD 1,IPPGN,2	;INDIRECT, CONSTRUCT IDENT
		LOAD 2,SPTX,2
		HRL 1,2
		JRST MRM1]
	LOAD 2,SPTX,2		;GET SPT INDEX
	MOVE 1,SPTH(2)		;NO, GET OFN.PN
MRM1:	HLRZ 2,1
	CAIGE 2,NOFN		;OWNED BY OFN?
	AOS 0(P)		;YES, SKIP RETURN
	PUSH P,T1		;SAVE IDENT
	MOVE T1,CPTPGA(Q2)	;GET POINTER
	CALL GPAC		;TRANSLATE ACCESS BITS
	MOVE T2,T1		;RETURN ACCESS IN T2
	POP P,T1
	CALLRET RELCPT

RDMQ5:	SETZB 1,2		;RETURN 0
	CALLRET RELCPT
;FIND NON-0 PAGE IF ANY, AND RETURN ITS ACCESS DATA
; 1/ IDENT
; 2/ COUNT OF NUMBER OF PAGES TO SCAN
; RETURNS +1 WITH ACCESS DATA IN 1, UPDATED COUNT IN 2.  IF NO
;  NON-0 PAGE FOUND, 2 WILL CONTAIN 0.

MSCANP::PUSH P,B		;SAVE ARG
	HLRZ B,A		;GET SPTN
	CALL CHKDMO		;SEE IF DISMOUNTED
	 JRST [	POP P,B		;YES. IT IS
		CALLRET DMOINT]	;AND GIVE ERROR
	POP P,B			;GET BACK ARG
	HLRZ 3,1		;GET OFN
	CAIG 3,0		;LEGAL?
	BUG(HLT,ILOFN1,<MSCANP-ILLEG IDENT>)
	CALL SETXB1		;MAP INDEX BLOCK
	HRRZ T4,T1
MSCAN1:	SKIPE 3,CXBPGA(4)	;EMPTY?
	JRST MSCAN2		;NO
	ADDI T4,1		;YES, BUMP IDENT TO NEXT PAGE
	SOJG 2,MSCAN1		;COUNTDOWN MAX PAGES
	HRR T1,T4		;FIX IDENT
	CALLRET RELCXB		;COUNT DONE, ALL PAGES EMPTY

MSCAN2:	HRR T1,T4		;FIX IDENT
	PUSH P,2		;SAVE UPDATED COUNT
	CALL MRPACS		;GET ACCESS DATA
	POP P,2
	RET
;READ PAGE ACCESSIBILITY
; 1/ IDENT
; RETURNS +1 WITH ACCESS INFORMATION IN RPACS FORMAT IN 1

MRPACS::SAVEPQ
	SETZB Q2,P1		;NO PTR AND NO INDIRECT COUNT
	MOVX T4,PTWR+PTCPY 	;ACCESS BITS TO COMPUTE
MRP4:	HLRZ 2,1		;GET PT IDENTIFIER
	CALL CHKDMO		;SEE IF A DISMOUNTED OFN
	 JRST [	CALL DMOINT	;DELIVER ERROR
		JRST MRPCX]	;AND LEAVE
	HLRZ T3,T1		;GET PTN
	CAMN T3,BTBBAS		;IS THIS THE BIT TABLE IDENT?
	JRST [	MOVX T2,UAAB	;YES. SEE IF IT IS MAPPED
		TDNN T2,SPT(T3)	;IS IT?
		JRST .+1	;YES. PROCEED
		SETZ T1,	;NO. RETURN NONEX PAGE
		JRST MRPCX]	;AND DONE
	CAIG T3,0
	BUG(HLT,ILPTN1,<MRPACS-ILLEG PTN>)
	CALL SETXB1		;MAP PT
	HRRZS T1
	MOVE T3,CXBPGA(T1)	;GET PTR
	SKIPN Q2		;FIRST PTR?
	MOVEM T3,Q2		;YES, SAVE IT
	JUMPE T3,MRP2		;JUMP IF EMPTY
	TXC T3,PTCPY	;'AND' 0S FOR THIS BIT
	ANDM T3,T4		;COMPUTE COMPOSIT ACCESS
	LOAD Q1,PTRCOD,T3	;GET PTR TYPE
	CAIE Q1,INDCOD		;INDIRECT?
	JRST MRP2		;NO, DONE
	CAIL P1,MAXIND		;ALREADY SAW TOO MANY OF THESE?
	JRST [	SETZ T1,	;YES. SAY PAGE DOES NOT EXIST
		JRST MRPCX]	;AND RETURN NON-EX PAGE
	ADDI P1,1		;SAW ANOTHER INDIRECT POINTER
	LOAD T1,IPPGN,T3	;YES, CONSTRUCT IDENT
	LOAD T3,SPTX,T3
	HRL T1,T3
	JRST MRP4		;CONTINUE TRACE

;TRACED ALL PTRS,
; Q2/ FIRST PTR
; T4/ COMPOSIT ACCESS
; T3/ LAST PTR

MRP2:	JUMPE Q2,[SETZ T1,	;FIRST PTR NULL, RETURN 0
		JRST MRPCX]
	MOVE T1,T4
	TXC T1,PTCPY+PTRCOD	;NOT (AND (NOT ..))
	CALL GPAC		;TRANSLATE ACCESS TO USER BITS
	MOVEM T1,T4
	LOAD Q1,PTRCOD,Q2	;GET FIRST PTR TYPE
	CAIN Q1,INDCOD		;INDIRECT?
	TXO T4,PA%IND		;YES
	CAIN Q1,IMMCOD		;PRIVATE?
	TXO T4,PA%PRV		;YES
	MOVE T1,Q2
	CALL GPAC		;TRANSLATE ACCESS OF FIRST PTR
	HLRZ T1,T1		;RETURN IT IN RH
	HLL T1,T4		;RETURN COMPOSIT IN LH
	JUMPE T3,MRPCY		;CLEAR 'EXISTS' IF LAST PTR EMPTY
	LOAD Q1,PTRCOD,T3	;GET TYPE OF LAST PTR
	CAIE Q1,SHRCOD		;SHARED?
	JRST MRPCX		;NO
	LOAD T3,SPTX,T3		;YES, CHECK ADDRESS
	LOAD T3,STGADR,SPT(T3)
	TXNN T3,DSKAB+DRMAB	;UNASSIGNED?
	TXNN T3,UAAB
	JRST MRPCX		;NO, ELSE CLEAR EXISTS
MRPCY:	TXZ T1,PA%PEX		;CLEAR 'EXISTS'
MRPCX:	CALLRET RELCXB		;RELEASE TEMP MAPPING AND RETURN

;TRANSLATE POINTER ACCESS BITS TO USER ACCESS BITS
; T1/ POINTER
;	CALL GPAC
; RETURN +1 ALWAYS, T1/ USER ACCESS BITS

GPAC:	JUMPE T1,R		;NULL PTR YEILDS 0
	MOVE T2,T1
	MOVX T1,PA%RD+PA%EX+PA%PEX ;SAY POINTER EXISTS
	TXNE T2,PTWR		;WRITE?
	TXO T1,PA%WT		;YES
	TXNE T2,PTCPY		;COPY?
	TXO T1,PA%CPY		;YES
	RET

;TRANSLATE USER ACCESS BITS TO POINTER ACCESS BITS
; T2/ USER BITS
; T3/ POINTER TO BE SET
;	CALL SPAC
; RETURN +1, T3/ MODIFIED POINTER

SPAC:	TXZ T3,PTWR+PTCPY	;SET THESE BITS...
	TXNE T2,PA%WT		;WRITE?
	TXO T3,PTWR		;YES
	TXNE T2,PA%CPY		;COPY?
	TXO T3,PTCPY		;YES
	RET
;SET PAGE ACCESSIBILITY
; T1/ IDENT
; T2/ ACCESS

MSPACS::PUSH P,2
	CALL SETCPT		;MAP PT
	HRRZ T4,T1
	POP P,2
	SKIPN CPTPGA(T4)		;PAGE EXISTS?
	JRST MRSPX		;NO, IGNORE CALL
	HLRZ 3,1
	CAIGE 3,NOFN		;FILE?
	JRST MRSPX		;YES, DO NOTHING
	NOSKED
	MOVE 3,CPTPGA(T4)	;GET PTR
	CALL SPAC		;SET POINTER BITS PER USER REQUEST
	MOVEM 3,CPTPGA(T4)	;STORE MODIFIED PTR
	CALL MONCLA		;MAKE SURE PAGER NOTICES DIFFERENCES
	OKSKED
MRSPX:	CALLRET RELCPT

;MRPAC - JSYS FOR MONITOR DDT

.MRPAC::MCENT
	MOVE 2,0(P)		;RETURN PC
	TLNE 2,(UMODF)		;FROM MONITOR?
	ITERR(ILINS1)		;NO, ILLEGAL FROM USER
	TLNE 1,(1B0)		;USER?
	JRST [	CALL FPTA	;YES, GET PTN.PN
		JUMPE T1,MRPC1	;IF NO SECTION, DO NO-ACCESS
		JRST MRPC3]
	HRRZ 2,1
	CAIGE 2,PPRMA		;NON-RES MON?
	JRST [	LSH 2,-PGSFT	;NO, IS RESIDENT MAPPED MON
		MOVE 1,MMAP(2)	;GET PTR
		CALL GPAC	;TRANSLATE PTR TO ACCESS BITS
		TLO 1,(PA%PRV)	;NOTE PRIV PTR
		JRST MRPC2]	;RETURN CONTENTS OF MMAP
	CAIL 2,CXBPGA		;CHECK SPECIAL PAGES
	CAILE 2,CPYPGA		;SETPT, ETC. PAGES?
	CAIGE 2,PPRMA+NRSPG*1000 ;SWAPPER PAGES?
	JRST MRPC1		;YES, RETURN NO-ACCESS
	CALL FPTA
	JUMPE T1,MRPC1		;IF NO SECTION, RETURN NO-ACCESS
MRPC3:	CALL MRPACS
MRPC2:	UMOVEM 1,2		;RETURN RESULT IN 2 LIKE RPACS
	JRST MRETN

MRPC1:	MOVSI 1,(PA%PRV)		;NO-ACCESS
	JRST MRPC2
;SET PAGE IN MONITOR OR USER MAP (INTERNAL MONITOR CALL)
; AC1/ OFN,,PN   (OFN IS SPT POINTER, PN IS 0-777)
; AC2/ 18-35 VIRTUAL ADDRESS OF PAGE (NOT PAGE NUMBER)
;       0    1 => USER MAP, 0 => MONITOR MAP
;	1-17 - ACCESS

SETMPG::TRVAR <SID,ADR,ARG3,ARG4,DEST>
	DMOVEM T1,SID		;SAVE ARGS
	DMOVEM T3,ARG3
	CALL VERPT		;GO VERIFY NO DISMOUNTED OFN
	 RET			;USER REQUESTED BAD OFN. IGNORE IT
	HLLZ 3,2		;GET ACCESS
	MOVE 1,2
	CALL FPTA		;CONVERT ADDRESS TO PTN.PN
	JUMPE T1,SETMPX		;IF NO SECTION, ERROR
	MOVEM T1,DEST		;SAVE DEST I.D.
	CALL SETCPT		;SETUP PAGE TABLE
	CALL LCKOFI		;LOCK DEST IF OFN
	MOVE 2,SID		;GET SOURCE IDENT
	CALL RELMP5		;RELEASE OLD CONTENTS
	MOVE T1,DEST
	MOVE T2,SID		;RESTORE ARGS
	SKIPGE ADR		;CHANGING EXEC OR USER MAP?
	JRST [	CALL PGRCLD		;USER, CLEAR ALL
		JRST .+2]
	HLLZ T3,ADR		;GET ACCESS BITS
	CALL MONCLA		;EXEC, CLEAR EXEC SCRATCHPAD
	CALL SETPT0		;SET NEW CONTENTS
MSETM2:	CALL RELCXB		;RELEASE SOURCE PT
	CALL RELCPT		;RELEASE DESTINATION PT
	CALL ULKOFI		;UNLOCK DEST IF OFN
	DMOVE T1,SID		;RESTORE TEMPS
	DMOVE T3,ARG3
	RET

;MULTIPLE SET PAGE IN MAP - SAME AS ABOVE EXCEPT
; 3/ NUMBER OF SUCCESSIVE PAGES TO BE SET

MSETMP::TRVAR <SID,ADR,PCT,ARG4,DEST>
	DMOVEM T1,SID		;SAVE ARGS
	DMOVEM T3,PCT
	CALL VERPT		;GO VERIFY NOT USING DISMOUNTED OFN
	 RET			;CAN'T MAP DISMOUNTED OFN
	HLLZ 3,2		;ACCESS BITS
	MOVE 1,2
	CALL FPTA		;CONVERT DESTINATION TO PTN.PN
	JUMPE T1,SETMPX		;IF NO SECTION, ERROR
	MOVEM T1,DEST		;SAVE DEST I.D.
	CALL SETCPT		;MAP DESTINATION PT
	CALL LCKOFI		;LOCK DEST IF OFN
	MOVE 2,SID		;GET SOURCE PTN.PN
MSETM1:	CALL RELMP5		;RELEASE EXISTING CONTENTS OF DEST
	MOVE T2,SID
	MOVE T1,DEST		;RESTORE ARGS
	HLLZ T3,ADR		;GET ACCESS BITS
	CALL SETPT0		;SET NEW CONTENTS
	AOS T1,DEST		;NEXT DEST ADDRESS
	SKIPE 2			;SOURCE 0?
	AOS T2,SID		;NEXT SOURCE IF APPROPRIATE
	SOSLE PCT		;COUNT PAGES DONE
	JRST MSETM1
	SKIPGE ADR		;CHANGING EXEC OR USER MAP?
	JRST [	CALL PGRCLD		;USE, CLEAR ALL
		JRST .+2]
	CALL MONCLA		;EXEC, CLEAR EXEC ONLY
	JRST MSETM2
;LOCAL ROUTINE USED BY SETMPG AND MSETMP TO VERIFY THAT REQUESTOR
;IS NOT SELECTING A DISMOUNTED OFN.

VERPT:	JUMPE 1,RSKP		;IF DELETING, ALLOW IT
	SAVEAC <T2>		;DON'T CLOBBER ANY ARGS
	HLRZ 2,1		;GET OFN
	SKIPN 2			;WAS THIS AN OFN.PN?
	MOVEI 2,0(1)		;NO. IS 0,,OFN. SO GET THE OFN
	CALL CHKDMO		;SEE IF DISMOUNTED
	 CALLRET DMOINT		;YES. PROVIDE AN INTERRUPT
	RETSKP			;NO. ALLOW MAP

;LOCAL ROUTINE USED BY SETPT AND MSETPT TO VERIFY THAT REQUESTOR
;IS NOT SELECTING A DISMOUNTED OFN.

PTVER:	JUMPE 1,RSKP		;IF DELETING, ALLOW IT
	SAVEAC <T2>		;DON'T CLOBBER ANY ARGS
	STKVAR <AR2>		;SAVE DESTINATION HERE
	MOVEM 2,AR2		;SAVE DESTINATION
	HLRZ 2,1		;GET OFN OF SOURCE
	SKIPN 2			;WAS THIS OFN.PN?
	MOVEI 2,0(1)		;NO. IS 0,,OFN. SO GET THE OFN
	CALL CHKDMO		;SEE IF DISMOUNTED
	 CALLRET DMOINT		;YES. PROVIDE INTERRUPT
	HLRZ 2,AR2		;GET OFN OF DESTINATION
	CALL CHKDMO		;SEE IF IT IS DISMOUNTED
	 CALLRET DMOINT		;YES. GIVE INTERRUPT
	RETSKP			;NO. ALLOW MAP

;ROUTINE TO DELIVER A PSEUDO INTERRUPT TO PROCESS. THIS ROUTINE
;IS CALLED WHENEVER A PROCESS ATTEMPTS TO ILLEGALLY MAP A PAGE
;FROM A DISMOUNTED OFN.

DMOINT:	SAVET
	MOVEI A,PMAPX7		;PROVIDE CHARACTERISTIC CODE
	MOVEM A,LSTERR		; FOR PROCESS TO SEE
	MOVEI A,.ICIRD		;GENERATE ILLEGAL MEM READ
	CALL PSIRQ0		; TO THIS PROCESS
	CHKINT			;MAKE SURE PROCESS SEES IT ASAP
	RET			;AND DONE

;ATTEMPT TO MAP A NON-EXISTANT SECTION

SETMPX:	BUG (HLT,SECEX1,<SETMPG-ATTEMPT TO MAP NON-EX SECTION>)
;MAP PHYSICAL CORE PAGE
; T1/ DESTINATION IDENT
; T2/ PHYSICAL PAGE NUMBER
;	CALL MAPPHP
; RETURN +1: FAILURE, PAGE LOCKED OR OTHERWISE INACCESSIBLE
; RETURN +2: SUCCESS, PRIVATE POINTER SETUP

MAPPHP::ASUBR <ID,PGNO>
	CAMLE T2,NHIPG		;WITHIN KNOWN RANGE?
	BUG(HLT,XSCORE,<CST TO SMALL FOR PHYSICAL CORE PRESENT>)
	CALL SETCPT		;MAP DESTINATION PT
	CALL RELMP5		;CLEAR PREVIOUS CONTENTS
	CALL MONCLA		;CLEAR PAGE MEMORY
	NOSKED
	MOVE T1,PGNO
	CAMGE T1,MONCOR		;RES MONITOR PAGE?
	JRST [	CALL RESPCK	;CHECK RESMON PAGE
		 JRST .+1	;NOT PART OF RESMON
		MOVE T2,ID	;YES, DON'T CHANGE CST
		JRST MAPPH1]
	MOVX T2,-PLKV
	TDNE T2,CST1(T1)	;PAGE LOCKED?
	JRST MAPPHX		;YES, CAN'T GRAB IT
	CALL RPCST		;RELEASE PAGE FROM PRESENT USE
	CALL AGESET		;ASSIGN PAGE  HERE
	MOVX T2,UAAB		;SET UNASSIGNED BACKUP ADDRESS
	MOVEM T2,CST1(T1)
	MOVE T2,ID
	MOVEM T2,CST2(T1)	;SET OWNER ID
MAPPH1:	IOR T1,IMMPTR		;CONSTRUCT PRIVATE PTR
	HRRZS T2		;PREVENT PAGE FAULT
	MOVEM T1,CPTPGA(T2)	;PUT IN DEST MAP
	HLRZ T1,ID		;GET PT I.D.
	LOAD T1,STGADR,SPT(T1)	;GET MEMORY PAGE NUMBER
	MOVX T2,PLKV		;ONE UNIT OF LOCK COUNT
	ADDM T2,CST1(T1)	;ONE MORE PAGE IN MEMORY
	OKSKED
	CALL RELCPT		;RELEASE DEST MAP
	MOVE T2,PGNO		;RESTORE ARG
	RETSKP

MAPPHX:	OKSKED
	CALLRET RELCPT
;MAP PHYSICAL PAGE INTO MONITOR ADDRESS
; T1/ PHYSICAL CORE PAGE NUMBER
; T2/ MONITOR VIRTUAL ADDRESS
;	CALL MAPPHA
; SAME AS MAPPHP EXCEPT TAKES MONITOR VIRTUAL ADDRESS

MAPPHA::EXCH T1,T2
	CALL FPTA		;TRANSLATE ADDRESS TO IDENT
	JUMPE T1,SETMPX		;SECTION MUST EXIST
	CALLRET MAPPHP		;DO THE WORK

;ROUTINE TO SEE IF A PAGE LESS THAN MONCOR IS STILL PART
;OF MONITOR MAP.
;ACCEPTS:	T1/ PAGE NUMBER
;RETURNS:	+1 NOT PART OF MONITOR MAP
;		+2 PART OF MONITOR MAP

RESPCK:	HLRZ T2,CST2(T1)	;GET PRESENT OWNER
	CAME T2,MMSPTN		;OWNED BY MONITOR MAP?
	RET			;NO
	RETSKP			;YES
;MMAPWE AND MMAPWP- ROUTINES TO WRITE ENABLE OR WRITE PROTECT THE MONITOR'S MAP

;ACCEPTS:
;	T1/VIRTUAL ADDRESS OF FIRST PAGE AFFECTED
;	T2/COUNT OF NUMBER OF PAGES TO AFFECT

;CALL MMAPWE OR CALL MMAPWP

;RETURNS +1 ALWAYS

;THIS ROUTINE MODIFIES THE ACCESS FOR CONSECUTIVE PAGES IN THE MONITOR'S MAP.
;IT MODIFIES MMAP FOR PAGES BELOW THE JSB, JOBMAP FOR PAGES IN THE JSB, AND
;PSBMAP FOR PAGES IN THE PER PROCESS REGION.  IT ASSUMES THAT THE RANGE
;SPECIFIED DOES NOT EXTEND BEYOND THE STARTING REGION.  THAT IS, ALL PAGES
;ARE BETWEEN 0 AND 577, OR 600 AND 677, OR 700 AND 777.

MMAPWE::SKIPA T3,[IORM T4,0(T1)] ;T3/INSTRUCTION TO WRITE-ENABLE
MMAPWP::MOVE T3,[ANDCAM T4,0(T1)] ;T3/INSTRUCTION TO WRITE-PROTECT
	LOAD T1,VPGNO,T1	;GET PAGE NUMBER
	CAIL T1,PSSPS		;BELOW THE PSB?
	JRST [	ADDI T1,PSBMAP-PSSPS ;IN THE PSB.  POINT TO ENTRY IN PSBMAP FOR FIRST PAGE		
		JRST MM1]	;GO LOOP THROUGH PAGES
	CAIL T1,JSBPG		;BELOW THE JSB?
	JRST [	ADDI T1,JOBMAP-JSBPG ;IN THE JSB. POINT TO ENTRY IN JOBMAP FOR FIRST PAGE
		JRST MM1]	;GO LOOP THROUGH PAGES
	ADDI T1,MMAP		;IN MMAP. POINT TO ENTRY FOR THE FIRST PAGE

;T1 HAS THE ADDRESS OF THE FIRST WORD OF THE MAP.  LOOP THROUGH ENTRIES
;ACCORDING TO COUNT IN T2

MM1:	MOVX T4,PTWR		;T4/WRITE ACCESS
MM2:	SKIPE 0(T1)		;IGNORE NON-EXISTANT PAGE
	XCT T3			;WRITE ENABLE OR PROTECT ACCORDING TO EARLIER SETUP OF T3
	AOS T1			;POINT TO NEXT WORD
	SOJG T2,MM2		;AT THE END?
	CALLRET MONCLA		;YES. MAKE THE PAGER SEE THE CHANGES
;SET PAGE TABLE (FOR PROCESS OR FILE)
; AC1/ SOURCE IDENTIFIER
; AC2/ DESTINATION IDENTIFIER
; T3/ 0-17 ACCESS INFO

;IDENT IS OFN.PN (PAGE IN FILE), 0.OFN (INDEX BLOCK),
; PTN.PN (PAGE IN PROCESS), OR 0.PTN (PROCESS PT)

SETPT::	CALL PTVER		;VERIFY ARGS
	 RET			;CAN'T USED A DISMOUNTED OFN
	EXCH 1,2
	CALL RELMPG		;RELEASE EXISTING PAGE
	CALL SETPT0
	CALL RELCXB		;RELEASE SOURCE PT
	CALL RELCPT		;RELEASE DESTINATION PT
	CALL ULKOFI		;UNLOCK DEST IF OFN
	EXCH 1,2
	RET

;MULTIPLE SET PAGE TABLE - SAME AS SETPT, EXCEPT
; 4/ COUNT OF NUMBER OF SUCCESSIVE PAGES TO SET

MSETPT::ASUBR <SID,DID,ARG3,ARG4>
	CALL PTVER		;VERIFY ARGS
	 RET			;CAN'T USE A DISMOUNTED OFN
	MOVE 1,2
	CALL SETCPT		;SETUP DESTINATION MAP
	CALL LCKOFI		;LOCK DEST IF OFN
	MOVE 2,SID		;GET SOURCE PTR
MSETP1:	CALL RELMP5		;RELEASE OLD CONTENTS
	MOVE T2,SID
	MOVE T1,DID		;RESTORE ARGS
	MOVE T3,ARG3		;ACCESS BITS
	CALL SETPT0		;SET NEW CONTENTS
	AOS T1,DID			;NEXT DEST PAGE
	SKIPE 2
	AOS T2,SID		;NEXT SOURCE IF APPROPRIATE
	SOSLE ARG4		;MORE TO DO?
	JRST MSETP1		;DO IT
	CALL PGRCLD		;CLEAR PAGER SCRATCHPAD
	JRST MSETM2
;SET NEW CONTENTS OF PT

SETPT0:	JUMPE 2,R		;CHECK FOR NO NEW PAGE TO SET
	ASUBR <ARG1,ARG2,ARG3,ARG4>
	NOSKED
SETP5A:	CAMN 1,2		;DON'T ALLOW MAP TO SELF
	JRST SETPF1
	HLRZ 3,2		;GET OFN
	JUMPE 3,SETMXB		;OFN=0 MEANS SPTN IN RH
	TXNE 2,<<^-SPTM>B17+777000> ;LEGAL PTN AND PN?
	BUG(HLT,ILSRC,<ILLEGAL SOURCE IDENTIFIER GIVEN TO SETPT>)
	MOVE 3,ARG3		;GET FLAGS
	TXNE 3,PM%MVP		;MOVE OF PAGE REQUESTED?
	JRST [	CALL MVPT	;YES, DO IT
		 JRST SETPTE	;FAILED
		JRST SETPT2]
	HLRZ 4,1		;GET DESTINATION PTN
	CAIGE 4,NOFN		;FILE?
	JRST [	CALL MVPT	;YES, **SHOULD BE CHANGED TO SETPF1**
		 JRST SETPTE
		JRST SETPT2]
	HLRZ 4,2		;GET SOURCE PTN
	TXNN T3,PM%IND		;OR INDIRECT PTR REQUESTED?
	CAIL 4,NOFN		;PROCESS?
	JRST SETP5		;YES, GO SETUP INDIRECT POINTER
	HLRZ T3,T2		;GET SOURCE PTN
	CALL SETXB1		;MAP SOURCE XB
	OKSKED
	HRRZ T3,T2
	SKIP CXBPGA(T3)		;REFERENCE PAGE WHILE OKSKED
	NOSKED
	MOVE T3,CXBPGA(T3)	;GET WORD FROM XB
	JUMPE 3,SETP5		;JUMP IF PAGE NONEXISTENT
	LOAD 4,PTRCOD,3		;GET PTR TYPE
	CAIN 4,INDCOD		;INDIRECT?
	BUG(HLT,ILXBP,<SETPT-BAD POINTER IN XB>)
	CAIN 4,SHRCOD		;ALREADY SHARED?
	JRST SETMP3		;YES, GO USE SAME POINTER
	MOVE 4,SPTC		;YES
	CAMGE 4,SPC0		;ROOM IN SPT? (SPT .L. C FULL)
	JRST SETMP6		;YES, SETUP SHARE PTR
	JRST SETP5		;USE IND PTR

;ERROR RETURNS

SETPF1:	MOVEI 1,PMAPX2		;PMAP-ILLEGAL CASE
SETPTE:	MOVEM 1,LSTERR
	MOVEI 2,.ICILI		;ERROR CHANNEL
	CAIN 1,IOX11		;DISK FULL?
	MOVEI 2,.ICQTA		;YES - USE THIS CHL
	MOVE 1,2		;COPY CHL TO T1
SETPF2:	CALL PSIRQ0		;REQUEST PSI
	CHKINT			;GET IT SEEN
	JRST SETPT2
;HERE TO CONSTRUCT INDIRECT PTR TO SOURCE

SETP5:
   REPEAT 0,<
;SOMETHING POSSIBLY NEEDED HERE TO DETECT LOOPS OF INDIRECT PTRS.
;THIS CODE FORMERLY NEEDED TO ELIMINATE CHAINS OF INDIRECT PTRS
;BECAUSE OF BBN PAGER LIMITATION, ALSO WOULD DETECT SIMPLE LOOPS
;BUT NOT FIGURE 6'S, ETC.
	LOAD 4,PTRCOD,3		;GET TYPE CODE
	CAIN 4,INDCOD		;INDIRECT?
	JRST [	LOAD 4,SPTX,3	;YES, GET SPTN
		CAIGE 4,NOFN	;VIA INDEX BLOCK?
		JRST .+1	;YES, OK
		CALL RELCXB	;NO, TRACE DOWN
		LOAD 2,IPPGN,3	;CONSTRUCT ID OF PAGE POINTED
		HRLI 2,0(4)	; TO BY INDIRECT PTR
		JRST SETP5A]	;AND USE THAT AS SOURCE
   >				;END REPEAT 0
	HLRZ T3,T2		;GET SPTN
	MOVE T4,T1		;SAVE STORAGE ADDRESS
	MOVEI T1,0(T3)		;GET SPTN
	CALL GETSHR		;GET SHARE COUNT
	EXCH T1,T4		;RESTORE VALUES
	CAIL T4,MAXSC0		;TOO MUCH?
	JRST [	CAIGE T3,NOFN	;IS THIS AN OFN?
		JRST .+1	;YES. WE CAN LET IT GO THEN
		MOVEI T1,PMAPX6	;NO. SHARE COUNT TOO LARGE
		JRST SETPTE]
	MOVE 4,INDPTR		;CONSTRUCT IND PTR
	STOR 3,SPTX,4		;PUT SPTN IN PTR
	STOR 2,IPPGN,4		;PUT PN IN PTR
	MOVE 2,4
SETMP4:	LOAD 3,SPTX,2		;GET OFN OF INDEX BLOCK
SETMP5:	JUMPE T3,SETMP2		;JUMP IF NO SPT
	CALL SETSHR		;LOCAL CALL TO INCREMENT SHARE COUNT
SETMP2:	MOVE T3,T2		;INITIAL POINTER...
	MOVE T2,ARG3		;GET USER ACCESS BITS
	CALL SPAC		;SET POINTER ACCESS BITS FROM USER
	HRRZS T1
	SKIPE CPTPGA(T1)		;BE SURE PREVIOUS CONTENTS NULL
	BUG(HLT,PTNON0,<SETPT0 - PREVIOUS CONTENTS NON-0>)
	MOVEM T3,CPTPGA(1)	;PUT MAP WORD IN MAP
SETPT2:	OKSKED
	DMOVE T1,ARG1		;RESTORE ARGS
	DMOVE T3,ARG3
	RET

SETMXB:	CAIL 2,SSPT		;LEGAL NUMBER?
	BUG(HLT,ILSPTI,<ILLEGAL SPT INDEX GIVEN TO SETMXB>)
	HLRZ 3,1		;GET DESTINATION PTN
	CAIGE 3,NOFN		;FILE?
	BUG(HLT,ILDEST,<ILLEGAL DESTINATION IDENTIFIER TO SETMPG OR SETPT>)
	HRRZ 3,2
	MOVE 2,SHRPTR		;CONSTRUCT SHARE PTR TO INDEX BLOCK
	STOR 3,SPTX,2
	JRST SETMP5
;SETUP NEW SHARED PAGE

SETMP6:	SKIPG 4,FRESPT		;ASSIGN NEW SPT SLOT
	BUG(HLT,SPTFL2,<SPT COMPLETELY FULL>)
	HRRZ 4,0(4)		;GET CDR
	EXCH 4,FRESPT		;LIST OF FREE SLOTS
	SUBI 4,SPT		;MAKE RELATIVE
	AOS SPTC		;COUNT OF USED SPT ENTRIES
	TLNE 3,(NCORTM)		;IN CORE?
	JRST SETP2
	PUSH P,5
	PUSH P,6
	HRRZ 6,3
	CAME 2,CST2(6)		;CHECK OLD OWNERSHIP
	BUG(HLT,CST2I1,<PAGE TABLE CORE POINTER AND CST2 FAIL TO CORRESPOND>)
	MOVEM 4,CST2(6)		;RECORD NEW LOCATION OF CORE ADDRESS
	HLRZ 6,2		;YES, UPDATE LOCK COUNT FOR
	HRRZ 6,SPT(6)		;OWNING PT
	MOVSI 5,(-PLKV)		;REDUCE IT, BECAUSE IT WILL HAVE
	ADDM 5,CST1(6)		;ONE LESS CORE ADDRESS IN IT
	POP P,6
	POP P,5
SETP2:	ANDX 3,STGADM
	MOVEM 3,SPT(4)		;PUT IT IN SPT
	MOVEM 2,SPTH(4)		;PUT OFN.PN IN SPTH
	MOVE 3,SHRPTR		;MAKE SHARE PTR
	STOR 4,SPTX,3
	HRRZ T4,T2
	MOVEM 3,CXBPGA(T4)	;STORE IT IN XB
	HLRZ 3,2		;GET OFN
	CALL SETSHR		;LOCAL INCREMENT SHARE COUNT
SETMP3:	HRRZ T3,T2
	LOAD 3,SPTX,CXBPGA(T3)	;GET SPT INDEX
	CAME 2,SPTH(3)		;ALL OK?
	BUG(HLT,ILSPTH,<SETPT-SPTH INCONSISTENT WITH XB>)
	CALL SETSHR		;LOCAL INCREMENT SHARE COUNT
	HLRZ 3,2		;GET OFN
	HRRZS 2
	MOVE 2,CXBPGA(2)	;GET THE POINTER
	JRST SETMP5		;GO PUT IT IN PT

;LOCAL ROUNTINE TO INCREMENT SHARE COUNT OF SPT INDEX IN 3

SETSHR:	EXCH T1,T3		;SAVE CONTENTS OF 1. GET ARG
	CALL UPSHR		;INCREMENT SHARE COUNT
	EXCH T1,T3		;RESTORE REGS
	RET			;AND DONE
;MOVE PAGE.  PAGE IS REMOVED FROM SOURCE RATHER THAN BECOMING SHARED
; 1/ DESTINATION ID, PT MAPPED INTO CPTPG
; 2/ SOURCE ID, PT MAPPED INTO CXBPG
;	CALL MVPT
; RETURN +1, FAILURE, ERROR CODE IN A
; RETURN +2, SUCCESS.

MVPT:	HLRZ T3,T2		;GET SOURCE PTN
	CALL SETXB1		;MAP INDEX BLOCK
	OKSKED
	HRRZ T4,T2		;GET ADDRESS ONLY
	SKIP CXBPGA(T4)		;REFERENCE PAGE WHILE OKSKED
	NOSKED
	HLRZ 4,2		;GET SOURCE AND DEST PTN'S
	HLRZ 3,1
	CAIGE 3,NOFN		;DEST IS FILE?
	JRST [	CAIL 4,NOFN	;YES, SOURCE ALSO?
		JRST SETP7	;NO, DO FORK-TO-FILE CASE
		HRRZ T3,T2
		LOAD 3,PTRCOD,CXBPGA(3) ;FILE-TO-FILE CASE,
		CAIE 3,IMMCOD	;PAGE NOW PRIVATE?
		RETBAD(PMAPX3)	;NO, ERROR
		JRST MVPT1]
	CAIGE 4,NOFN		;DEST IS FORK, SOURCE ALSO?
	RETBAD(PMAPX4)		;NO, FILE-TO-FORK ILLEGAL
MVPT1:	HRRZ T3,T2
	MOVE 3,CXBPGA(3)	;GET PTR
	JUMPE 3,MVPT3		;NOP IF NULL
	LOAD 4,PTRCOD,3		;GET PTR TYPE
	CAIN 4,IMMCOD		;PRIVATE AND IN CORE?
	TLNE 3,(NCORTM)
	JRST MVPT2
	HRRZ 4,3		;GET ADDRESS ONLY
	CAME 2,CST2(4)		;YES, CHECK CST CONSISTENCY
	BUG(HLT,CST2I2,<MVPT-CST2 INCONSISTENT>)
	MOVEM 1,CST2(4)		;NOTE NEW LOCATION OF POINTER
	CALL MVLK		;MOVE THE PT LOCK COUNT
	PUSH P,1
	HRRZ 1,2
	MOVE 1,CXBPGA(1)	;GET CORE PAGE NUMBER
	CALL DECOR		;DEASSIGN PAGE FROM WS
	POP P,1
MVPT2:	SETZ 3,
	HRRZ 4,2
	EXCH 3,CXBPGA(4)	;REMOVE PTR FROM OLD LOCATION
	HLRZ T4,T1
	HRRZS T1
	CAIGE T4,NOFN		;DEST IS FILE?
	JRST [	ANDX T3,STGADM	;YES, EXTRACT STG ADR FROM PRIV PTR
		IOR T3,IMMPTR	;MAKE STANDARD POINTER
		MOVEM T3,CPTPGA(T1) ;PUT IN XB
		JRST MVPT3]
	MOVE T2,ARG3		;GET USER ACCESS BITS
	CALL SPAC		;SET THEM INTO POINTER
	MOVEM 3,CPTPGA(1)	;PUT IT IN NEW LOCATION
MVPT3:	RETSKP

;LOCAL ROUTINE TO MOVE PT LOCK COUNT WHEN MOVING CORE PTR

MVLK:	HLRZ 4,2		;SOURCE PTN
	HRRZ 4,SPT(4)
	MOVSI 3,(-PLKV)
	ADDM 3,CST1(4)		;REDUCE LOCK COUNT OF PT
	HLRZ 4,1
	HRRZ 4,SPT(4)
	MOVSI 3,(PLKV)
	ADDM 3,CST1(4)		;INCREASE LOCK COUNT OF XB
	RET
;DESTINATION IS FILE, SOURCE FORK

SETP7:	HRRZ T3,T2
	MOVE 3,CXBPGA(3)	;GET PTR
	JUMPE 3,SETP7K		;JUMP IF PAGE NON-EXISTENT
	LOAD 4,PTRCOD,3		;GET PTR TYPE
	CAIE 4,IMMCOD		;NOT PRIVATE?
	RETBAD(PMAPX3)		;YES, ERROR
	PUSH P,5
	HRRZ 5,3		;ELIMINATE LEFT HALF OF 3
	TLNE 3,(DSKAB)		;NOW ON DISK?
	JRST SETP71		;YES
	TLNE 3,(DRMAB)		;NOW ON DRUM?
	JRST SETP7D		;YES, GO ADJUST DRUM BACKUP ADR
	LOAD 4,STGADR,3		;IN CORE, GET PAGE NUMBER
	CAML 4,MONCOR		;NORMAL SWAPPING PAGE?
	CAMLE 4,NHIPG
	JRST [	POP P,5		;NO, CAN'T MAP INTO FILE
		RETBAD(PMAPX5)]
	PUSH P,1
	MOVEI 1,0(5)
	CALL AGESET		;FIX PAGE
	POP P,1
	MOVSI 4,(PLKV)		;IN CORE,
	ADDB 4,CST1(5)		;GET BACKUP ADR AND LOCK PAGE
	TLNE 4,(DSKAB)		;DISK?
	JRST SETP7C		;YES
	TLNE 4,(DRMAB)		;DRUM?
	JRST SETP7E		;YES
	MOVEI 4,CST1(5)		;NOT ASSIGNED, PUT BACKUP ADR IN CST1
	CALL SETP7A		;ASSIGN BACKUP ADR AND STORE IT
	 JRST [	HRRZ 5,T3	;FAILED. GET CORE ADDRESS
		MOVSI T1,(-PLKV)
		ADDM T1,CST1(5) ;UNLOCK PAGE
		POP P,5		;CLEAN UP THE STACK
		RETBAD (IOX11)]	;FAIL RETURN, NO ROOM
SETP7C:	PUSH P,3
	HRRZ 5,3
	MOVEM 1,CST2(5)		;IN CORE, ADJUST CST
	MOVSI 4,(-PLKV)
	ADDM 4,CST1(5)		;UNLOCK PAGE
	CALL MVLK		;MOVE PT LOCK COUNT
	POP P,3
SETP71:	HRRZ 5,2
	SETZM CXBPGA(5)		;PUT SOURCE PTR IN DEST MAP
	ANDX 3,STGADM		;EXTRACT STORAGE ADDRESS
	IOR 3,IMMPTR		;MAKE PRIVATE PTR
	PUSH P,1
	HRRZS 1
	MOVEM 3,CPTPGA(1)
SETP72:	MOVE 1,0(P)		;BE SURE WE HAVE IDENT
	HRRZ 3,1
	MOVE 3,CPTPGA(3)	;GET CURRENT ADR OF PAGE
	TLNE 3,(DSKAB)		;PAGE NOW ON DSK?
	JRST SETP73		;YES, DONE
	TLNE 3,(DRMAB)		;ON DRUM?
	JRST [	CALL SWPINW	;YES, GET IT IN CORE
		JRST SETP72]	;RECHECK ADDRESS
	HRRZS 1
	MOVE 1,CPTPGA(1)	;GET CURRENT ADDRESS OF PAGE
	CALL SKPNWR		;WRITE IN PROGRESS?
	 JRST SETP72		;YES, RECHECK ADDRESS
	MOVX 2,DSKSWB		;GET DISK BIT
	IORM 2,CST3(1)		;AND SET DISK BIT IN CST
	CALL SWPOT0		;SWAP PAGE TO DISK
SETP73:	POP P,1
	POP P,5
SETP7K:	HLRZ 3,1		;GET DEST OFN
	MOVX 4,OFNWRB		;NOTE CHANGE TO IT
	IORM 4,SPTH(3)
	RETSKP
SETP7D:	MOVE 4,3
SETP7E:	PUSH P,2
	PUSH P,3
	MOVE 2,4		;DRUM ADDRESS
	CALL GDSTX		;GET DST INDEX
	MOVEI 4,DST(2)		;WHERE TO STORE ADDRESS
	POP P,3
	POP P,2
	MOVE 5,0(4)		;PRESENT BACKUP
	TLNE 5,(DSKAB)		;DISK?
	JRST SETPE1
	CALL SETP7A		;NO, ASSIGN DISK ADDRESS AND STORE IT
	 JRST [	HRRZ 5,T3	;FAILED. GET CORE ADDRESS (IF ONE)
		MOVSI T1,(-PLKV)
		TLNN T3,(NCORTM) ;CORE PAGE?
		ADDM T1,CST1(5) ;UNLOCK PAGE
		POP P,5		;CLEAN UP THE STACK
		RETBAD (IOX11)]	;FAIL RETURN
SETPE1:	TLNN 3,(NCORTM)
	JRST SETP7C
	JRST SETP71

SETP7A:	HLRZ 5,1		;GET OFN OF DESTINATION FILE
	ADJSP P,4		;SAVE T1-T4
	DMOVEM T1,-3(P)
	DMOVEM T3,-1(P)
	MOVE T1,5		;OFN TO CHECK
	CALL QCHK		;SEE IF OK TO ASSIGN DISK PAGE
	 JRST SETP7B		;ERROR - BOMB OUT NOW
	MOVE T1,-3(P)		;GET DEST IDENT
	CALL FNDLDA		;GET LAST DISK ADR ASSIGNED FOR DSKASN
	LOAD T2,STRX,(5)	;GET STRUCTURE NUMBER
	CALL DSKASN		;ASSIGN DISK ADDRESS FOR PAGE
SETP7B:	 SETO T1,		;DISK FULL
	MOVE 5,T1		;SAVE ADDRS (OR FLAG)
	DMOVE T1,-3(P)		;RESTORE T1-T2
	JUMPL 5,SETP7Y		;SKIP IF ERROR
	HLRZ T3,T1		;GET OFN AGAIN
	LOAD T3,ALOCX,(T3)	;INDEX INTO QUOTA TABLE
	DECR PGLFT,(T3)		;ONE LESS PAGE LEFT
SETP7Y:	DMOVE T3,-1(P)		;RESTORE T3-T4
	ADJSP P,-4		;CLEAN OFF STACK
	JUMPL 5,R		;FAIL RETURN
	STOR 5,STGADR,0(T4)	;STORE ADDRESS PER ARG
	RETSKP
;PUT INDEX BLOCK IN FIXED PAGE (CXBPG) OF PP MAP FOR TEMP USE
; 3/ SPTN

SETXB1:	PUSH P,SHRPTR		;CONSTRUCT SHARE PTR
	STOR 3,SPTX,0(P)
	POP P,3
	CAMN 3,PSBM0+CXBPG	;ALREADY THERE?
	RET			;YES
	CALL RELCXB		;RELEASE CURRENT ONE
	NOINT			;NO INTERRUPTS WHILE XB MAPPED
	MOVEM 3,PSBM0+CXBPG	;PUT INTO CURRENT X BLOCK PAGE
	RET

;RELEASE INDEX BLOCK NOW IN FIXED PAGE

RELCXB:	SKIPN PSBM0+CXBPG
	RET			;NONE THERE NOW
	SETZM PSBM0+CXBPG		;CLEAR MAP
	PUSH P,1
	MOVEI 1,CXBPGA
	CALL MONCLR		;CLEAR MAP ENTRY
	POP P,1
	OKINT
	RET

;MAP CURRENT PAGE TABLE FOR TEMP USE
; 1/ SPTN,,PN			;PN IGNORED

SETCPT:	HLRZ 2,1		;GET PTN
	PUSH P,SHRPTR		;CONSTRUCT SHARE PTR
	STOR 2,SPTX,0(P)
	POP P,2
	CAMN 2,PSBM0+CPTPG	;ALREADY THERE?
	RET			;YES
	CALL RELCPT		;RELEASE CURRENT ONE
	NOINT
	MOVEM 2,PSBM0+CPTPG
	RET

;RELEASE CURRENT PT MAPPING

RELCPT:	SKIPN PSBM0+CPTPG		;ANYTHING THERE?
	RET			;NO
	SETZM PSBM0+CPTPG		;CLEAR MAP
	PUSH P,1
	MOVEI 1,CPTPGA
	CALL MONCLR		;CLEAR MAP ENTRY
	POP P,1
	OKINT
	RET
;RELEASE PAGE FROM MAP
; AC1/ OFN.PN OF PAGE

RELMPG:	SAVET			;SAVE TEMPS
	HLRZ T2,T1
	CALL CHKDMO		;STR DISMOUNTED?
	 RET			;YES, DO NOTHING
	CALL SETCPT
	CALL LCKOFI		;LOCK IF OFN
	CALL RELMP5
	CALL PGRCLD
	RET

;RELEASE ASSUMING PT ALREADY MAPPED AND THAT PAGER CLEAR WILL
;BE DONE FOLLOWING.

RELMP5:
RELMP6:	HRRZ T4,T1
	SKIPN CPTPGA(4)		;REF PAGE BEFORE GOING NOSKED
	RET			;ALREADY EMPTY
	NOSKED
	MOVE 2,CPTPGA(4)	;GET MAP WORD
	JUMPE 2,RELMPS		;EMPTY
	LOAD 3,PTRCOD,2		;GET PTR TYPE
	CAIN 3,IMMCOD		;PRIVATE?
	JRST RELP3		;YES
	CAIN T3,INDCOD		;INDIRECT?
	JRST RELMI1		;YES
	HLRZ T3,T1		;GET PTN
	CAIGE T3,NOFN		;OWNED BY FILE?
	JRST RELMP4		;CAN'T DELETE FILE PAGE STILL SHARED
	SETZM CPTPGA(T4)	;CLEAR MAP WORD
	MOVE T3,T2		;SAVE POINTER
	LOAD T2,SPTX,T2
	CAIGE 2,NOFN		;OFN?
	JRST RELP1		;YES
	HLRZ 3,SPTH(2)		;IS SHARE POINTER, GET OFN
	JUMPE 3,RELP1		;IF UNOWNED SPTN
	MOVEI 1,0(3)		;GET OFN
	CALL DWNSHR		;DECREMENT OFN SHARE COUNT
	MOVEI 1,0(2)		;GET PAGE ID
	CALL DWNSHR		;DECREMENT PAGE SHARE COUNT
	CALL GETSHR		;GET PAGE SHARE COUNT
	JUMPN 1,[LOAD 1,STGADR,SPT(2) ;NO. GET STORAGE ADDRESS
		TLNN 1,(NCORTM)	;PAGE NOW IN CORE?
		CALL DECOR	;YES, DEASSIGN IT
		JRST RELMPS]	;DONE
	LOAD 1,STGADR,SPT(2)	;GET STORAGE ADDRESS
	TLNE 1,(NCORTM)		;CORE?
	JRST RELMP2		;NO
	CALL AGESET		;IN CORE, SET AGE
	MOVSI 4,(PLKV)
	ADDM 4,CST1(1)		;AND LOCK WHILE ADJUSTING
	; ..
RELMP2:	PUSH P,1		;SAVE CORE NUMBER
	MOVEI 1,0(3)		;GET XB INDEX
	CALL DWNSHR		;DECREMENT SHARE COUNT
	POP P,1			;RESTORE CORE PAGE NUMBER
	CALL SETXB1		;MAP OWNING XB
	MOVE 4,SPTH(2)		;GET OWNING PTN.PN
	PUSH P,3		;SAVE OWNING OFN
	MOVE 3,2
	MOVEI 2,SPT(2)		;CONSTRUCT PTR
	EXCH 2,FRESPT		;RETURN SPT SLOT TO FREE LIST
	MOVEM 2,@FRESPT
	SOS SPTC
	POP P,2			;GET BACK OWNING OFN
	CALL CHKDMO		;SEE IF THIS OFN IS DISMOUNTED
	 JRST CHKRLO		;IT IS. SEE IF OFN NEEDS TO BE RELEASED
	ANDX 1,STGADM		;FLUSH ACCESS AND PTR BITS
	IOR 1,IMMPTR		;CONSTRUCT STANDARD XB PTR
	HRRZ 2,4
	MOVEM 1,CXBPGA(2)	;PUT PRIV PTR BACK INTO XB
	TLNE 1,(NCORTM)		;PAGE IN CORE?
	JRST RELP4		;NO
	HRRZS 1
	CAME 3,CST2(1)		;CONFIRM OLD OWNERSHIP
	BUG(HLT,CST2I3,<PAGE TABLE CORE POINTER AND CST2 FAIL TO CORRESPOND>)
	MOVEM 4,CST2(1)		;YES, CHANGE RECORD OF OWNING PT
	HLRZ 3,4		;PTN OF OWNING PT
	HRRZ 3,SPT(3)		;CORE ADDRESS OF IT
	MOVSI 2,(PLKV)
	ADDM 2,CST1(3)		;INCREMENT LOCK COUNT
	MOVSI 3,(-PLKV)
	ADDM 3,CST1(1)		;UNLOCK PAGE
	JRST RELP4

RELP1:	MOVEI 1,0(2)
	CALL DWNSHR		;DECREMENT SHARE COUNT
	JRST RELMPS

RELMP4:	MOVEI 1,PMAPX2		;ILLEG UNMAPPING
	MOVEM 1,LSTERR
	MOVEI 1,.ICDAE
	CALL PSIRQ0		;GENERATE ITRAP
	JRST RELMPS
;HERE TO RELEASE INDIRECT PTR

RELMI1:	SETZM CPTPGA(T4)	;CLEAR MAP
	MOVE T3,T2		;SAVE PTR
	LOAD T2,SPTX,T3		;GET PTN FROM PTR
	MOVE T1,T2
	CALL DWNSHR		;REDUCE SHARE COUNT OF PT
	CAIL 2,NOFN		;IS IT A PT
	JRST RELMPS		;YES. ALL DONE THEN
	CALL CHKDMO		;SEE IF A DISMOUNTED OFN
	 JRST CHKRLO		;IT IS. GO CHECK IT OUT
	MOVX 1,OFNDUD		;SEE IF NO UPDATE REQUESTED
	TDNE 1,SPTH(2)		;IS IT?
	JRST [	MOVE 1,2	;COPY OFN
		CALL GETSHR	;GET ITS SHARE COUNT
		JUMPE 1,.+1	;IF ZERO, SCAN IT ANYWAY
		JRST RELMPS]	;NON-ZERO. SKIP THE SCAN
	LOAD 4,IPPGN,3		;NO. GET PAGE NUMBER IN FILE
	HRLI 4,0(2)		;FORM ID FOR PAGE
	MOVE 3,2		;MOVE OFN
	CALL SETXB1		;MAP THE OFN
	JRST RELP4		;AND MOVE THE PAGE TO DISK

CHKRLO:	MOVEI 1,0(2)		;SEE IF NEED TO RELEASE OFN
	CALL GETSHR		;SEE WHAT ITS SHARE COUNT IS
	JUMPN 1,RELMPR		;CAN'T RELEASE IT YET. GO ON
	MOVEI 1,0(2)		;GET OFN IN 1
	CALL DASOFN		;FREE IT
	JRST RELMPR		;AND GO WRAP UP

;PAGE BECOMING UNSHARED, MUST MAKE IT BE ON DISK

RELP4:	HLRZ T1,T4		;GET THE OFN
	CALL UPSHR		;ARTIFICIALLY INCREMENT OFN
	PUSH P,T1		;SAVE OFN
	CALL MOVDSK		;MOVE IT TO DISK NOW
	MOVE T1,0(P)		;GET BACK OFN
	CALL GETSHR		;GET THE OFN SHARE COUNT
	SOJG T1,RLMPR2		;ARE WE THE ONLY SHARER?
	MOVE T1,0(P)		;YES. GET OFN AGAIN
	CALL DASALC		;CLEAR ALLOC ENTRY IN THE OFN
	PUSH P,PSBM0+CPTPG	;RESTORE PT MAPPING
	SETZM PSBM0+CPTPG	; AND CLEAR IT SO RELCPT DOESN'T
				; GET CONFUSED
	MOVX T3,OFNDUD		;CHECK IF DUD IS SET
	TDNN T3,SPTH(T1)	;IS IT?
	JRST RLMPR1		;NO. DON'T NEED TO SCAN THE OFN THEN
	CALL LCKOFN		;LOCK THE OFN AGAINST MODIFICATION
	CALL SCNOFN		;GET XB'S PAGES TO DISK
	 JFCL			;SHOULDN'T HAPPEN
	MOVE T1,-1(P)		;GET BACK OFN
	CALL ULKOFN		;UNLOCK THE OFN
RLMPR1:	MOVX T4,OFNWRB		;SEE IF MODIFIED
	TDNE T4,SPTH(T1)	;WAS IT?
	CALL UPDOFN		;YES. PUT OFN ON THE DISK ALSO
	POP P,PSBM0+CPTPG	;RESTORE PT MAPPING
RLMPR2:	POP P,T1		;GET OFN
	CALL DWNSHR		;RESTORE ORIGINAL SHARE COUNT
RELMPR:	CALL RELCXB		;RELEASE XB MAPPING
RELMPS:	OKSKED
	RET
;HERE IF PRIVATE PAGE -- PAGE WILL BE DELETED

RELP3:	TLNE 2,(NCORTM)		;IN CORE?
	JRST RELP32		;NO, CAN RELEASE ALL.
	MOVSI 3,(DWRBIT)	;YES, WRITE IN PROGRESS?
	HRRZ 4,2
	TDNN 3,CST3(4)
	JRST RELP32		;NO, NO PROBLEM
	AOS DWRCFL		;FLAG FORK WAITING FOR WRITE COMPLETION
	PUSH P,1
	MOVEI 1,DWRTST		;YES, MUST WAIT FOR COMPLETION
	HRLI 1,0(2)
	RDISMS
	POP P,1
	JRST RELMP6		;GO TRY AGAIN

RELP32:	PUSH P,1		;SAVE IDENT
	HRRZS 1
	MOVE 2,CPTPGA(1)	;GET POINTER
	SETZM CPTPGA(1)		;CLEAR MAP SLOT
	LOAD 1,STGADR,2		;GET ADDR ONLY
	TXNN 1,NCORTM		;IN CORE?
	CALL AGESET		;YES, ENSURE ACCESS
	TXNE 2,PTLOK		;LOCKED POINTER?
	CALL [	LOAD 1,STGADR,2
		CAMGE 1,MONCOR	;RESMON PAGE?
		JRST [	SAVEAC <T2>
			CALL RESPCK ;YES. SEE IF PART OF RESMON
			 RET	;NO. SKIP UNLOCK THEN
			CALLRET MULKCR] ;YES.
		CALLRET MULKCR]	;NO. UNLOCK IT
	LOAD 1,STGADR,2		;GET ADDR ONLY AGAIN
	CALL REMFP1		;DELETE CORE AND DRUM STORAGE
	JUMPE 1,[POP P,1	;DONE IF NOTHING LEFT
		JRST RELMPS]
	PUSH P,1		;HAVE DSK ADR LEFT TO DELETE, SAVE IT
	HLRZ 1,-1(P)		;GET OFN OF DEST
	MOVX 2,OFNWRB		;NOTE CHANGE TO XB
	IORM 2,SPTH(1)
	OKSKED
	NOINT			;STAY NOINT WHILE CPT RELEASED
	CALL RELCPT		;RELEASE CPT CAUSE UPDOF0 USES IT
	CALL UPDOF0		;UPDATE IT TO DSK
	POP P,1			;RECOVER DSK ADDRESS
	HLRZ 2,0(P)		;RECOVER OFN
	LOAD C,ALOCX,(2)	;GET ALLOCATION PNTR
	INCR PGLFT,(C)		;ADJUST PAGES LEFT UP
	LOAD C,STRX,(2)		;GET STRUCTURE NUMBER
	MOVE 2,SPTH(2)		;SEND DEDSK THE OFN BITS
	NOSKED			;MUST CALL IT NOSKED
	CALL DEDSKC		;DELETE IT
	POP P,1			;RECOVER IDENT
	CALL SETCPT		;MAP PT AGAIN
	OKINT			;UNDO NOINT ABOVE
	JRST RELMPS		;DONE
;ROUTINE TO MOVE A PAGE TO ITS HOME ON THE DISK AND DELETE ANY
;LOCAL STORAGE. CALLED FROM RELOFN AND RELMPG.
;ACCEPTS:	4/ OFN.PN  WITH THE OFN MAPPED INTO CXBPGA
;RETURNS:	+1 ALWAYS, WITH PAGE EITHER ON THE DISK OR
;		   A WRITE IN PROGRESS
;CLOBBERS ALL TEMP REGISTERS 

MOVDSK:	HRRZ 2,4
	MOVE 1,CXBPGA(2)	;GET CURRENT ADR OF PAGE
	JUMPE 1,R		;MAY BE EMPTY
	LOAD 2,PTRCOD,1
	CAIN 2,SHRCOD		;BECAME SHARED AGAIN?
	RET			;YES, NOTHING TO DO OR CAN BE DONE
	TXNN 1,NCORTM		;IN CORE?
	JRST MOVDS1		;YES. GO CHECK IT
	TXNE 1,DSKAB		;ON DISK?
	RET			;YES. ALL DONE
	TXNN 1,DRMAB		;ON DRUM?
	JRST [	HRRZ 2,4
		SETZM CXBPGA(2)	;NO, UNNASSIGNED. FLUSH IT
		RET]		;AND DONE
	MOVE 2,1		;PAGE ON DRUM, GET DRUM ADR
	CALL GDSTX		;GET DST INDEX
	MOVE 3,DST(2)		;CHECK DRUM STATUS WORD
	TLNE 3,(BWRBIT)		;HAS PAGE BEEN MODIFIED SINCE DISK?
	JRST [	MOVE 1,4	;YES, MUST WRITE IT BACK ON DISK
		PUSH P,4
		CALL SWPINW	;SO FIRST GET IT INTO CORE
		POP P,4
		JRST MOVDSK]	;NEXT SWPOUT WILL GO TO DISK
	SETOM DST(2)		;PAGE NOT MODIFIED, NO WRITING NEEDED
	HRRZ 2,4
	STOR 3,STGADR,CXBPGA(2)	;RELEASE DST SLOT, PUT DSK ADR BACK IN XB
	CALL DASDRM		;DEASSIGN DRUM ADDRESS
	RET			;PAGE NOW ON DISK

;HERE IF PAGE IN CORE

MOVDS1:	CALL SKPNWR		;WRITE IN PROGRESS?
	 JRST MOVDSK		;YES. RECHECK PAGE ID
	CALL AGESET		;MAKE PAGE IN USE
	MOVX 3,DSKSWB		;MAKE SURE IT GOES TO DISK
	IORM 3,CST3(1)		;BY REQUESTING THIS EXPLICITLY
	CALL SWPOT0		;SWAP IT OUT
	RET			;DONE
;ROUTINES TO ADJUST AND FETCH SPT SHARE COUNTS.
;ACCEPTS:	1/ SPT INDEX (EITHER PT OR OFN)
;RETURNS:	+1 ALWAYS

;INCREASE SHARE COUNT

UPSHR::	ACVAR <Q1,Q2>		;GET A WORK REGISTER
	HRRZ Q2,T1		;GET THE SPT INDEX
	CAIL Q2,NOFN		;AN OFN?
	JRST SHRSPT		;NO
	MOVX Q1,OFSHR		;YES. GET BIT FOR OFN
	ADDB Q1,SPTO(Q2)	;INCREMENT SHARE COUNT
	TLNN Q1,(-OFSHR)	;DID IT OVERFLOW?
	BUG (HLT,SHROFN,<UPSHR-OFN SHARE COUNT OVERFLOW>) ;YES
	RET			;NO. RETURN GOOD

SHRSPT:	MOVX Q1,USHR		;GET SHARE BIT FOR SPT
	ADDB Q1,SPT(Q2)		;INCREMENT IT
	TLNN Q1,(-USHR)		;DID IT OVERFLOW?
	BUG (HLT,SPTSHR,<UPSHR-SPT SHARE COUNT OVERFLOW>)
	RET			;DONE

;DECREMENT SHARE COUNT

DWNSHR::ACVAR <Q1,Q2>		;GET A WORK REGISTER
	HRRZ Q1,T1		;GET SPT INDEX
	CAIL Q1,NOFN		;AN OFN
	JRST [	DECR SPTSHC,(Q1) ;NO. DECREMENT SPT SHARE COUNT
		RET]		;AND DONE
	MOVSI Q2,(-OFSHR)	;GET DECREMENTER
	TDNN Q2,SPTO(Q1)	;FIRST CHECK FOR OVER DECREMENTING
	BUG (HLT,SHROFD,<DWNSHR-OFN SHARE COUNT UNDERFLOW>)
	ADDM Q2,SPTO(Q1)	;DO THE DECREMENT
	RET			;AND DONE

;GET CURRENT VALUE OF SHARE COUNT

GETSHR::ACVAR <Q1>		;GET A WORK REGISTER
	HRRZ Q1,T1		;GET SPT INDEX
	CAIL Q1,NOFN		;AN OFN?
	JRST [	LOAD T1,SPTSHC,(Q1) ;NO. GET SPT SHARE COUNT
		RET]		;AND DONE
	LOAD T1,OFNSHC,(Q1)	;YES. GET OFN SHARE COUNT
	RET			;AND DONE
;SKIP IF NO WRITE IN PROGRESS ON CORE PAGE.  OTHERWISE RESCHEDULE
;UNTIL WRITE IS COMPLETED.
; 1/ CORE PAGE NUMBER
;	CALL SKPNWR
; RETURN +1, PAGE WAS BEING WRITTEN, WRITE HAS COMPLETED.
; RETURN +2, PAGE WAS NOT BEING WRITTEN.
;UNLESS THE PAGE IS LOCKED, IT MAY CHANGE STATE ON A RESCHED.  HENCE
;THE +1 RETURNS MEANS THAT THE POINTER TO THE PAGE MUST BE RECHECKED.
;CLOBBERS NO AC'S

SKPNWR::HRRZS A
	SKIPL CST3(A)		;WRITE IN PROGRESS?
	RETSKP			;NO, SKIP
	AOS DWRCFL		;FLAG FORK WAITING FOR WRITE COMPLETION
	HRLZ A,A		;YES, SETUP SCHED TEST
	HRRI A,DWRTST
	RDISMS			;OKSKED AND DISMISS
	HLRZ A,A		;RESTORE PAGE NUMBER TO A
	NOSKED			;RESTORE NOSKED STATE
	RET			;RETURN NOSKIP

DWRTST::MOVSI 2,(DWRBIT)	;SCHED TEST FOR WRITE COMPLETED
	TDNE 2,CST3(1)
	JRST 0(4)
	JRST 1(4)

;ROUTINE CALLED PERIODICALLY TO FINISH DELETING PAGES LEFT BY
;REMFP1 BECAUSE OF A WRITE IN PROGRESS.
;	CALL REMFPB
; RETURN +1 ALWAYS, ALL PAGES DELETED FROM QUEUE

REMFPB::SKIPN DELPGQ		;ANY PAGES ON DELETED QUEUE?
	RET			;NO, DONE
	PIOFF			;YES, PREVENT INTERRUPTS WHILE REMOVING
	HRRZ 1,DELPGQ
	HRRZ 1,0(1)
	EXCH 1,DELPGQ		;REMOVE PAGE FROM QUEUE
	PION
	SUBI 1,CST3		;TRANSLATE TO CORE PAGE NUMBER
	CALL REMFB1		;FINISH UP DELETE
	SKIPE 1			;COMPLETELY DELETED?
	BUG(HLT,PGNDEL,<REMFPB-PAGE NOT COMPLETELY DELETED>)
	JRST REMFPB		;DO ALL PAGES
;REMOVE PAGE FROM SYSTEM (DELETE PERMANENT AND TEMPORARY ADDRESSES)
; 1/ STORAGE ADDRESS

REMFP1:	SAVEQ
REMFPA:	HRRZ Q1,1
	TLNE 1,(DSKAB)		;DISK?
	RET			;YES, LEAVE IT IN 1
	TLNE 1,(DRMAB)		;DRUM?
	JRST REMFD		;YES
	TLNE 1,(NCORTM)		;CORE?
	JRST REMFPR		;UNASSIGNED, DONE
	CAMG 1,NHIPG		;LEGAL PAGE?
	CAMGE 1,MONCOR
	JRST [	CALL RESPCK	;SEE IF PART OF RESMON
		 JRST .+1	;NO. ASSUME WE WANT TO GET RID OF IT
		JRST REMFPX]	;YES. LEAVE IT ALONE
	LOAD 2,CSTAGE,(Q1)	;GET PAGE STATE CODE
	CAIL 2,PSASN		;ASSIGNED TO PROCESS?
	CALL DECOR		;YES, DEASSIGN
	HLRZ 2,CST2(Q1)		;GET PTN OF OWNING PT
	JUMPE 2,REMFP2		;NONE, SPT
	HRRZ 3,SPT(2)		;GET ADR OF OWNING PT
	MOVSI 4,(-PLKV)
	ADDM 4,CST1(3)		;DECREMENT LOCK COUNT
REMFP2:	PIOFF
	SETZM CST2(Q1)		;FLUSH OWNER IDENT
	MOVE 3,CST3(Q1)		;GET WRITE BIT
	PION
	TXNE 3,DWRBIT		;PAGE BEING WRITTEN?
	JRST REMFPR		;YES, DELETE WILL BE COMPL'D AFTER WRITE
	SKIPA			;SKIP OVER SAVQ FOR ALTERNATE ENTRY
REMFB1:	SAVEQ			;SAVE REGISTERS
	HRRZ Q1,1
	MOVSI 4,(-PLKV)
	LOAD 3,CSTAGE,(Q1)	;GET STATE CODE
	CAIE 3,PSRPQ		;ON RPLQ?
	TDNE 4,CST1(Q1)		;OR LOCKED IN CORE?
	JRST REMF22		;YES, LEAVE AS IS
	CALL OFRQ		;PUT ON TOP OF RPLQ SINCE NOT TO BE REUSED
REMF22:	MOVSI 3,(-PLKV)
	AND 3,CST1(Q1)		;FLUSH BACKUP ADDRESS, LEAVE LK CNT
	EXCH 3,CST1(Q1)		;GET BACKUP ADDRESS
	MOVE 1,3
	JRST REMFPA

REMFD:	PUSH P,1
	CALL DASDRM		;DEASSIGN DRUM ADDRESS
	POP P,2
	CALL GDSTX
	MOVE 1,DST(2)		;GET BACKUP ADDRESS
	SETOM DST(2)		;MAKE DST SLOT EMPTY
	JRST REMFPA

REMFPX:				;NON-SWAPPING PAGE, E.G. FROM MAPPHP
REMFPR:	SETZ 1,			;RETURN 0 TO SAY ALL DELETED
	RET
;HANDLE BAD CORE PAGE--CALLED AS RESULT OF PARITY ERROR OR OTHER
;PROBLEM WITH PHYSICAL PAGE.
; T1/ CORE PAGE NUMBER
;	CALL BADCPG
; RETURN +1, CONTENTS NOT RECOVERABLE
; RETURN +2, CONTENTS RECOVERABLE.

;THE CONTENTS ARE RECOVERABLE IF THE PAGE IS UNMODIFIED, I.E. THE
;DATA CAN BE READ FROM DISK OR DRUM AGAIN.  IN THIS CASE, THE
;POINTERS ARE RESET AND THE NEXT PROCESS REFERENCE SHOULD CAUSE
;THE PAGE TO BE READ INTO A DIFFERENT PHYSICAL CORE PAGE.
;IF THE PAGE HAS BEEN MODIFIED OR IF IT IS LOCKED, IT IS LEFT
;MAPPED AND ANY PROCESSES WHICH REFERENCE THE BAD DATA SHOULD GET
;INTERRUPTS.  IN EITHER CASE, THE PAGE IS LOCKED SO THAT IT WILL
;NOT BE USED AGAIN.

BADCPG::CAMGE T1,MONCOR		;RESIDENT PAGE?
	BUG(HLT,RPGERR,<BADCPG-FATAL ERROR IN RESIDENT PAGE>)
	NOSKED
	MOVX T2,-PLKV
	MOVX T3,CORMB
	TDNN T2,CST1(T1)	;PAGE LOCKED?
	TDNE T3,CST0(T1)	;OR MODIFIED?
	JRST BADCP3		;YES
	MOVEI T2,PSTERR		;NO, SET PAGE TO ERROR STATUS
	STOR T2,CSTPST,(T1)	; ...
	CALL RPCST		;RESET POINTERS
	PIOFF			;INTERLOCK CALL
	CALL ONSPMQ		;PLACE ON SPMQ, RETURNS PION
	AOS NBADCP		;COUNT LOSSAGE
	OKSKED
	RETSKP

;HERE IF CANNOT RELEASE PAGE BECAUSE MODIFIED OR LOCKED

BADCP3:	MOVE T2,CST2(T1)	;GET OWNER IDENT, FIND OFN IF ANY...
	HLRZ T3,T2
	JUMPN T3,[CAIL T3,NOFN	;HAVE PTN, IS OFN?
		JRST BADCP2	;NO, FORK PAGE
		MOVE T2,T3	;YES
		JRST BADCP1]	;GO MARK OFN
	CAIL T2,NOFN		;IS PAGE AN XB?
	JRST [	HLRZ T2,SPTH(T2) ;NO, GET OWNING PT
		JUMPN T2,BADCP1	;GO MARK IT
		BUG(HLT,FRKPTE,<BADCPG-FATAL ERROR IN FORK PT PAGE>)]
BADCP1:	MOVX T3,OFNERR		;MARK ERROR IN OFN, REPORTED ON CLOSF
	IORM T3,SPTH(T2)
BADCP2:	MOVEI T2,PSTERR		;INDICATE ERROR IN PAGE
	STOR T2,CSTPST,(T1)	; ...
	AOS NBADCP
	OKSKED
	RET			;RETURN NOT RECOVERABLE
;CONSTRUCT PTN.PN FOR
;ADDRESS GIVEN IN 18-35 OF AC1
;BIT 0 OF AC1 SAYS USER (IF 1) OR MONITOR (IF 0) ADDRESS
;RETURN WITH PTN.PN IN AC1
;MAY RETURN WITH AC1 =0 IF SECTION DOES NOT EXIST

FPTA::	SAVEQ
	MOVE FX,FORKX
	MOVEM T1,Q1		;CONSTRUCT RESULT IN Q1
	LOAD T1,VPGNO,T1	;GET PAGE NUMBER
	LDB Q2,[POINT 5,T1,26]	;GET THE SECTION NUMBER FROM THE PAGE NUMBER
	ANDI T1,777		;GET THE PAGE NUMBER IN THE SECTION
	HRRM T1,Q1		;SAVE IT
	JUMPL Q1,[SKIPN T1,USECTB(Q2) ;YES. GET SECTION POINTER
		JRST RFALSE	;NON-EX SECTION
		ANDX T1,STGADM	;GET SPT INDEX ONLY
		JRST FPTAR]
	SKIPN MSECTB(Q2)	;IS THE SECTION POINTER PRESENT?
	JRST RFALSE		;NO. QUITE IRREGULAR! RETURN A ZERO
	CAIG Q2,MAXSEC		;IF GREATER THAN MAX SECTION SOMBODY HAS BAD SECTION
	JRST @FPTABL(Q2)	;GO TO PROPER PAGE ROUTINE
ILLFPT:	BUG(HLT,ILFPTE,<ILLFPT: ILLEGAL SECTION NUMBER REFERENCED>)

FPTA0:	CAIL T1,PSSPS		;WHICH PART OF MONITOR?
	JRST FPTA1		;PRIVATE PER PROCESS
	CAIL T1,JSBPG
	JRST FPTA2		;PRIVATE PER JOB
	CAML T1,BTSTRT		;WITHIN BIT TABLE
	CAMLE T1,BTEND		;STILL?
FPTA4:	SKIPA T1,MMSPTN		;NO. IN MONITOR MAP
	JRST FPTA3
FPTAR:	HRLM T1,Q1		;CONSTRUCT PAGE IDENT
	MOVE T1,Q1		;RETURN RESULT
	RET

FPTA1:	ADDI Q1,-PSSPS+PSBMAP-PSBPGA ;OFFSET INTO PSBMAP
	LOAD T1,FKPSB		;GET PSB IDENT
	JRST FPTAR

FPTA2:	ADDI Q1,-JSBPG+JOBMAP-JSBPGA ;FIRST JOB PAGE MAPPED BY JOBMAP+0
	LOAD T1,FKJSB		;GET JSB IDENT
	JRST FPTAR

FPTA3:	MOVE T1,BTBBAS		;GET SPTN FOR BIT TABLE
	MOVX Q2,UAAB		;GET NO ACCESS BIT
	TDNE Q2,SPT(T1)		;ACCESSIBLE?
	JRST FPTA4		;NO. RETURN MMAP DATA
	SUB Q1,BTSTRT		;GET PAGE NUMBER
	MOVE T1,SPTH(T1)	;YES. GET TRUE ID
	JRST FPTAR		;AND DONE

FPTA6:	HRRZ T1,DRMAP		;MAP DIRECTORY
FPTAS:	JUMPE T1,R		;IF NO SECTION POINTER, RETURN 0
	JRST FPTAR		;GO FORM CORRECT POINTER

FPTA7:	HRRZ T1,IDXMAP		;FIND IDXMAP
	JRST FPTAS		;GO FINISH UP

FPTA8:	HRRZ T1,MSECTB+BTSEC	;FIND BITMAP
	JRST FPTAS		;GO FINISH UP

FPTAAN:	HRRZ T1,MSECTB+ANBSEC	;FIND ARPANET BUFFER MAP
	JRST FPTAS		;GO FINISH UP
;SETUP IO PAGE -- LOCKED AND MAPPED VIA MON MAP
; 1/ IDENT OF SOURCE
; 2/ ACCESS,,MON ADR
;	CALL SETIOP
; RETURN +2, PAGE LOCKED AND MAPPED

SETIOP::ASUBR <SOURCE,BFRP>
	LOAD 2,VPGNO,2		;GET PAGE NUMBER
	HRRM 2,BFRP
	SKIPE 1,MMAP(2)		;PREVIOUS CONTENTS?
	JRST [	SETZM MMAP(2)	;YES, REMOVE
		TXNE T1,NCORTM	;CORE?
		JRST .+1	;NO, FORGET IT
		HRRZ 1,1	;GET CORE PAGE NUMBER
		MOVX T3,-PLKV
		TDNN T3,CST1(T1) ;LOCKED?
		JRST .+1	;NO, FORGET IT
		CALL MULKCR	;UNLOCK IT
		JRST .+1]
	SKIPN 1,SOURCE		;GET SOURCE ID
	JRST SETIO1		;NONE, JUST RESETTING PREVIOUS PAGE
	CALL MLKPG		;LOCK PAGE AND GET CORE PAGE NUMBER
	IOR 1,IMMPTR		;CONSTRUCT POINTER
	MOVE 2,BFRP		;GET ACCESS REQUEST
	TXNN 2,PA%WT		;WRITE WANTED?
	TXZ 1,PTWR		;NO, CLEAR IT
	MOVEM 1,MMAP(2)		;PUT PAGE IN MON MAP
	HRRZS T1		;MAKE ADDRESS FOR CST0(T1)
	MOVX T3,CORMB
	TXNE T2,PA%WT		;PAGE WRITABLE?
	IORM T3,CST0(T1)	;YES, ASSUME IT WILL BE WRITTEN
	CALL KICLKP		;PUT PAGE IN KI MAP
SETIO1:	RETSKP

;MARK MODIFIED PAGE - USED WHEN PAGE IS BEING MODIFIED BY OTHER
;THAN PROCESSOR REFERENCE, E.G. BY IO VIA CHANNEL.
; T1/ CORE PAGE NUMBER
;	CALL MRKMPG
; RETURN +1 ALWAYS, MODIFIED BIT SET FOR SPECIFIED PAGE

MRKMPG::CAML T1,MONCOR		;VALIDATE PAGE
	CAMLE T1,NHIPG
	BUG(HLT,ILPAGN,<MRKMPG-INVALID PAGE NUMBER>)
	SETONE CORMB,CST0(T1)	;MARK IT
	RET
;LOCK, UNLOCK PAGE ON REQUEST (FOR DTA IO, ETC.)
; 1/ ADDRESS (+1B0 IF USER)
;RETURN +1: 1/ CORE PAGE NUMBER

MLKMA::	TLNN 1,(1B0)		;LOCK PAGE GIVEN ADDRESS. USER?
	SKIPA 0(1)		;NO, MON. REF PAGE TO ENSURE EXISTS
	XCTU [SKIP 0(1)]
	CALL FPTA		;TRANSLATE ADDRESS TO OFN.PN
;	JUMPE T1,SETMPX		;CAN'T HAPPEN SINCE REFERENCE TO PAGE
				;SUCCEEDED

;LOCK PAGE GIVEN OFN.PN
; 1/ OFN,,PN

MLKPG::	SKIPE INSKED		;IN SCHED CONTEXT?
	JRST MLKPGM		;YES, SPECIAL HANDLING
	PUSH P,1
	CALL GETONT		;GET PTN.PN OR OWNING PT
	JUMPE T2,MLKPG2		;JUMPE IF PAGE DOES NOT EXIST
	TLNN 2,(NCORTM)		;PAGE NOW IN CORE?
	JRST MLKPG1		;YES.
MLKPG4:	CALL SWPINW		;INITIATE SWAP AND WAIT FOR COMPL.
	POP P,1
	OKSKED
	JRST MLKPG		;TRY AGAIN

MLKPG2:	TLNN T1,-1		;IN SPT?
	JRST [	MOVX T2,UAAB	;YES, SETUP ADDRESS
		STOR T2,STGADR,SPT(T1)
		JRST MLKPG4]
	CALL SETCPT		;IN A PAGE TABLE - MAP IT
	HRRZ T2,T1
	MOVE T3,IMMPTR		;CONSTRUCT PTR WITH UNASSIGNED ADR
	TXO T3,UAAB
	MOVEM T3,CPTPGA(T2)	;PUT IT IN PT
	CALL RELCPT
	JRST MLKPG4

;MLKPG IN SCHED CONTEXT - NONX PAGE IN MONMAP ONLY

MLKPGM:	HLRZ T2,T1		;GET PT IDENT
	HRRZ T3,T1		;GET PAGE NUMBER
	CAMN T2,MMSPTN		;IN MONMAP?
	SKIPE MMAP(T3)		;PAGE IS NON-EXISTENT?
	BUG(HLT,ILPLK1,<MLKPG-ILLEGAL ARGS>)
	MOVE T2,IMMPTR		;CONSTRUCT PTR WITH UNASSIGNED ADR
	TXO T2,UAAB
	MOVEM T2,MMAP(T3)	;PUT IN MON MAP
	CALL SWPIN		;ASSIGN CORE AND CLEAR IT
	HLRZ T1,T1		;GET CORE PAGE NUMBER ASSIGNED
	MOVEI T3,PSASN
	STOR T3,CSTAGE,(T1)	;SET STATE TO IN-USE
	MOVEI T3,OFNUL
	STOR T3,CSTOFK,(T1)	;SET OWNERSHIP TO UNASSIGNED
	SETZRO PUFLD,CST0(T1)	;CLEAR USE BITS
	JRST MLKCP		;LOCK AND ADJUST VARIABLES
;LOCK PAGE GIVEN CORE PAGE NUMBER
; T1/ PAGE NUMBER
;	CALL MLKCP
; RETURN +1 ALWAYS, T1 PRESERVED

;LOCK PAGE COMMON CODE

MLKCP::	NOSKD1
	SKIPA T2,T1
MLKPG1:	POP P,1
	HRRZ T2,T2
	CAMGE T2,MONCOR		;WITHIN RANGE?
	JRST MLKPG5
	MOVE 1,CST1(2)
	TLNE 1,(-PLKV)		;PAGE LOCKED NOW?
	JRST MLKPG3
	AOS LOKPGS		;NO, COUNT IT
	AOS BALSHC
	AOS GNPBAS
	AOS SUMNR
	TLO 2,(1B0)		;SET LOCAL FLAG FOR TEST BELOW
MLKPG3:	MOVSI 1,(PLKV)
	ADDM 1,CST1(2)		;INCREMENT LOCK COUNT
	AOS LOKSUM
	SKIPE INSKED		;IN SCHED CONTEXT?
	RET			;YES, DONE
	HRRZ T1,T2
	CALL AGESET		;SET AGE
	PUSH P,2
	LOAD 2,CSTOFK,(1)	;GET OWNING FORK
	CAIGE 2,NFKS		;ASSIGNED?
	CALL SOSWSP		;YES, DEASSIGN IT
	POP P,2
	MOVX 1,OFNUL		;STORE NULL VALUE FOR OWNER FORK
	STOR 1,CSTOFK,(2)
	CALL MONCLA
MLKPG5:	OKSKD1
	HRRZ 1,2		;RETURN PHYS PAGE NUMBER
	RET
;UNLOCK PAGE
; 1/ PAGE IDENT (OFN,,PN)
;	CALL MULKPG
; RETURN +1 ALWAYS, BUGHLT IF PAGE NOT PREVIOUSLY LOCKED

MULKPG::PUSH P,2
	CALL GETONT		;GET OWNING PT
	TLNE 2,(NCORTM)		;PAGE NOW IN CORE?
	BUG(HLT,ILULK1,<MULKPG - TRIED TO UNLOCK PAGE NOT LOCKED>)
	CALL MULK1
	POP P,2
	OKSKED
	RET

MULK1:	MOVSI 1,(-PLKV)
	HRRZS 2
	CAMGE T2,MONCOR		;WITHIN RANGE?
	RET			;NO, IGNORE
	TDNN 1,CST1(2)		;LOCK COUNT NON-ZERO?
	BUG(HLT,ILULK2,<TRIED TO UNLOCK PAGE NOT LOCKED>)
	ADDB 1,CST1(2)		;DECREMENT LOCK COUNT
	TLNE 1,(-PLKV)		;NOW UNLOCKED?
	JRST MULK2		;NO
	SOS LOKPGS
	CALL UPSWP		;ONE MORE SWAPPING PAGE
	SKIPE CST2(2)		;STILL EXISTS?
	JRST MULK2		;YES
	MOVEI 1,0(2)		;HAS BEEN DELETED, PUT ON RPLQ
	CALL OFRQ		;PUT ON TOP OF RPLQ FOR IMMEDIATE REUSE
MULK2:	SOS LOKSUM
	RET

;UNLOCK PAGE GIVEN MONITOR ADDRESS
;ASSUMED NOSKED OR INSKED

MULKMP::LOAD 1,VPGNO,1		;GET PAGE NUMBER
	CAIL T1,JSBPG		;MONITOR MAP ONLY
	BUG(HLT,ILULK3,<MULKMP - ILLEGAL MONITOR ADDRESS>)
	LOAD 1,STGADR,MMAP(1)	;GET CORE ADDRESS
	JRST MULKCR

;UNLOCK PAGE GIVEN CORE PAGE NUMBER IN 1
;MAY BE CALLED AT INTERRUPT LEVEL

MULKCR::CAML 1,MONCOR		;LEGAL?
	CAMLE 1,NHIPG
	BUG(HLT,ILULK4,<MULKCR - ILLEGAL CORE PAGE NUMBER>)
	PUSH P,2
	MOVEI 2,0(1)
	CALL MULK1
	POP P,2
	RET
;MULKSP - UNLOCK A PAGE IN NON-ZERO SECTION.  THIS ROUTINE  MAY BE
;CALLED AT ANY INTERRUPT LEVEL.

;ACCEPTS:  T1/  VIRTUAL ADDRESS

;RETURNS: +1  ALWAYS

MULKSP::PUSH P,T2		;SAVE T2
	CALL GETCPA		;GET REAL PAGE ADDRESS
	POP P,T2		;RESTORE T2
	HRRZS T1		;RETAIN JUST PAGE NUMBER
	CALLRET MULKCR		;GO UNLOCK THE PAGE

;ROUTINE TO ADJUST SWAPPING WHEN PAGES ARE LOCKED OR
;UNLOCKED

;FIRST. ROUTINE TO ADJUST PARAMETERS ON UNLOCK

UPSWP:	SOS BALSHC		;ONE LESS OVERHEAD PAGE
	SOS GNPBAS		;ONE LESS HERE TOO
	SOS SUMNR		;AND REMOVE LIEN FROM BALSET
	RET			;DONE

;ROUTINE TO ADJUST SWAPPING/SCHEDULING PARAMETERS
;CALLED BY SCHEDULER WHENEVER NEW PAGES APPEAR IN SYSTEM
;RECOMPUTES ALL VALUES BASED ON TOTRC (E.G. MAXNR, DRMLV0, ...)
;CALLED FROM SCHEULER PERIODICALLY

ADJSWP::PIOFF			;PROTECT ALL STRUCTURES
	CALL MEMMGT		;RECOMPUTE BASIC SWAPPING PARAMETERS
	CALL AJBPAR		;RECOMPUTE BALSET PARTITIONS
	SETZM PAGDIF		;NO NEW PAGES
	PION			;OKAY NOW
	CALLRET SETSSP		;AND RECOMPUTE "DRUM" USAGE
;GET CORE PAGE GIVEN ADDRESS OR IDENTIFIER
;CLOBBERS T2

GETCPA::CALL FPTA		;CONVERT ADDRESS TO IDENTIFIER
	JUMPE T1,GETCPX		;IF NOT EXISTANT, NOT IN CORE
GETCPP::SAVEQ
	HLRZ 2,1		;PT IDENT
	MOVE 2,SPT(2)		;ADR OF IT
	TLNE 2,(NCORTM)		;IN CORE?
GETCPX:	BUG(HLT,PAGNIC,<GETCPP-PAGE NOT IN CORE>)
	HRRZS 1
	HRRZS T2		;SAVE ONLY PAGE NUMBER
	CALL MOVRCA		;MOVE 1,PT(1)
	LOAD Q1,PTRCOD,1	;GET PTR TYPE
	CAIN Q1,IMMCOD		;PRIVATE?
	RET			;YES
	CAIE Q1,INDCOD		;INDIRECT?
	JRST [	LOAD 2,SPTX,1	;SHARED, GET SPT IDX
		MOVE 1,SPT(2)
		RET]
	LOAD Q1,SPTX,2		;GET PT NUMBER
	LOAD 1,IPPGN,2		;GET PAGE NUMBER
	HRL 1,Q1		;CONSTRUCT IDENT
	JRST GETCPP

;GET OWNING PAGE TABLE
;GIVEN PTN.PN, LOCATE PT CURRENTLY HAVING ADDRESS OF PAGE

GETONT:	SAVEQ
	CALL SETCPT		;MAP GIVEN PAGE TABLE
	NOSKED
	HRRZ 2,1
	MOVE 2,CPTPGA(2)	;GET PTR
	JUMPE T2,GETONX		;RETURN IF NONX PAGE
	LOAD Q1,PTRCOD,2	;GET PTR TYPE
	CAIN Q1,IMMCOD		;PRIVATE?
	JRST GETONX
	CAIE Q1,INDCOD		;INDIRECT?
	JRST GETON1		;NO, SHARE POINTER.
	OKSKED
	LOAD 1,IPPGN,2		;GET PAGE NUMBER
	LOAD 2,SPTX,2		;GET PT NUMBER
	HRL 1,2			;CONSTRUCT IDENT
	CALL RELCPT		;RELEASE CPT
	JRST GETONT		;TRY AGAIN

GETON1:	LOAD 1,SPTX,2		;FOR SHARE POINTER, RETURN SPTN
	MOVE 2,SPT(1)		;AND CURRENT ADDRESS
GETONX:	CALLRET RELCPT		;RELEASE CPT AND RETURN
;LODPPG - LOAD VIRTUAL PAGE INTO PHYSICAL LOCATION
;CALL WITH:
;T1/	PTN.PN
;T2/	BITS,,PHY. PAGE
;T3/	PREVIOUS STATE IF ENTERED AT LODPPS
;BITS ARE:
;LK%NCH		DON'T CACHE PAGE
;LK%PHY IF OFF, FREE CHOICE OF PAGE
;LK%AOL ALLOW LOCKING IN OFF-LINE MEMORY
;	CALL LODPPG
;	 ERROR RETURN, CAN'T LOAD PAGE, CODE IN 1
;	SUCCESS PAGE IS LOADED AND LOCKED
;SHOULD ALWAYS BE CALLED NOINT
;VIRTUAL PAGE MUST BE PRIVATE OR NON-EXISTANT
;POINTER WILL HAVE PTLOK SET WHICH WILL CAUSE IT TO BE UNLOCKED
;BY RELMPG.

LODPPG::TXO T3,1B0		;NO SPECIAL "PREVIOUS STATE"
LODPPS::ASUBR <LODSRC,LODDST,LODPST>
	TXNN T2,LK%PHY		;FREE CHOICE?
	JRST LODFRE		;YES. GO CHOOSE
LODPP3:	HRRZ T1,LODDST		;GET PHY PAGE
	LOAD T2,CSTPST,(T1)	;GET CURRENT PAGE STATE
	SKIPGE LODPST		;ALREADY HAVE A "PREVIOUS STATE"?
	MOVEM T2,LODPST		;NO. SAVE HERE
	LOAD T2,CSTAGE,(T1)	;GET AGE
	CAIN T2,PSSPQ		;ALREADY ON SPMQ?
	JRST [	MOVX T3,LK%AOL	;YES. SEE IF OFF-LINE LOCKING ALLOWED
		TDNE T3,LODDST	;IS IT?
		JRST LODPP1	;YES. PAGE WILL RETURN TO SPMQ
		RETBAD (LOCKX1)] ;NO. CAN'T DO IT THEN
	MOVEI T2,PSTOFL		;PLACE PAGE OFF LINE
	CALL SETPST		;PUT INTO SPMQ
	 RETBAD(LOCKX2)		;ERROR, CODE IN 1
LODPP1:	NOSKED			;OWN MACHINE FOR A WHILE
	HLRZ T3,LODSRC		;GET SOURCE PAGE
	CALL SETXB1		;MAP IT
	HRRZ T1,LODSRC		;GET PAGE NUMBER
	SKIPN T1,CXBPGA(T1)	;GET POINTER
	JRST LODPP0		;NON-EX. OKAY
	LOAD T2,PTRCOD,T1	;GET TYPE
	CAIE T2,IMMCOD		;PRIVATE?
LODBAD:	RETBAD (LOCKX1,<CALL RELCXB
			OKSKED>)
	ANDX T1,STGADM		;GET ADDRESS ONLY
	MOVX T2,-PLKV		;LOCK FIELD
	TXNN T1,NCORTM		;IN MEMORY?
	TDNN T2,CST1(T1)	;YES. LOCKED?
	SKIPA			;NO. OKAY TO REPLACE IT
	JRST LODBAD		;LOCKED. CAN'T DO IT. SORRY!
	; ..
LODPP0:	CALL RELCXB		;FREE INDEX BLOCK
	HRRZ T1,LODDST		;GET PHY PAGE NUMBER
	CALL OFFSPQ		;REMOVE FROM SPMQ
	MOVEI T2,PSASN		;GET A GOOD AGE
	STOR T2,CSTAGE,(T1)	;MAKE BLT WORK
	MOVE T1,LODSRC		;GET SOURCE ADDRESS
	MOVE T2,[PTRW+FPG2A]	;MAP PAGE
	CALL SETMPG		;DO IT
	SKIP FPG2A		;GET DATA
	PIOFF			;OWN MACHINE
	HRRZ T1,LODDST		;GET DEST PAGE
	CALL MAPRCA		;MAKE IT ADDRESSABLE
	MOVE T2,T1		;SAVE ADDRESS
	HRLI T1,FPG2A		;SOURCE DATA
	BLT T1,PGSIZ-1(T2)	;MOVE DATA
	CALL UNMRCA		;CLEAR MAPPING
	PION			;BREATH A LITTLE NOW
	MOVEI T2,FPG2A		;WHERE WE PUT DATA
	SETZM T1		;UNMAP
	CALL SETMPG		;FREE IT
	MOVE T1,LODSRC		;WHERE NEW DATA IS TO GO
	HRRZ T2,LODDST		;PHYSICAL PAGE NUMBER
	CALL MAPPHP		;MAKE THEM ONE AND THE SAME
	 JFCL			;CAN'T FAIL
	HRRZ T1,LODDST		;GET PHY PAGE
	MOVE T2,LODPST		;GET OLD STATE BACK
	STOR T2,CSTPST,(T1)	;WILL RETURN TO STATE WHEN RELEASED
	CALL MLKCP		;LOCK PAGE, SET AGE (REMOVE FROM FORK WS)
	OKSKED			;WE CAN REST NOW
	HLRZ T3,LODSRC		;GET PTN
	CALL SETXB1		;MAP IT
	HRRZ T1,LODSRC		;GET PN
	MOVX T2,PTLOK		;FLAG AS LOCKED POINTER
	IORM T2,CXBPGA(T1)	;IN PAGE TABLE
	JE LK%NCH,LODDST,LODPP2	;JUMP IF NO-CACHE NOT REQUESTED
	MOVX T2,PTCACH		;GET CACHE BIT
	ANDCAM T2,CXBPGA(T1)	;CLEAR IT
	HRRZ T1,LODDST		;GET PAGE #
	CALL CASHFP		;FLUSH FROM CACHE
LODPP2:	CALL RELCXB		;RELEASE PAGE TABLE
	RETSKP			;RETURN SUCCESS
;ULDPAG - UNLOAD PAGE IF LOCKED
;CALL WITH:
;T1/	PTN.PN
;	CALL ULDPAG
;	 ERROR, PAGE NOT LOCKED OR CAN'T BE SWAPPED, CODE IN 1
;	SUCCESS, PAGE SWAPPED OUT OF MEM.
;PAGE ALWAYS UNLOCKED IF WAS LOCKED AND CACHE BIT TURNED ON AGAIN

ULDPAG::STKVAR <ULDSRC,ULDDST>
	MOVEM T1,ULDSRC		;SAVE PTN.PN
	HLRZ T3,ULDSRC		;GET PTN
	CALL SETXB1		;MAP IT (RETURNS NOINT)
	HRRZ T2,ULDSRC		;USER PAGE
	MOVX T1,PTLOK		;LOCKED POINTER BIT
	NOSKED			;PROTECT THE PAGE POINTER
	LOAD T3,PTRCOD,CXBPGA(T2) ;GET POINTER TYPE
	CAIN T3,IMMCOD		;IMMEDIATE?
	TDNN T1,CXBPGA(T2)	;IS IT STILL LOCKED?
	JRST ULDPG1		;NO, JUST RETURN
	ANDCAM T1,CXBPGA(T2)	;CLEAR LOCKED POINTER BIT
	MOVX T1,PTCACH		;TURN CACHE BIT BACK ON (IF OFF)
	IORB T1,CXBPGA(T2)	;AND PICKUP POINTER
	ANDX T1,STGADM		;GET PHY ADDR ONLY
	MOVEM T1,ULDDST		;SAVE PAGE NUMBER
	CAML T1,MONCOR		;RES MON PAGE?
	CALL MULKCR		;NO, UNLOCK PAGE
	MOVE T1,ULDDST		;GET PAGE NUMBER AGAIN
ULDPG3:	MOVX T2,-PLKV		;SEE IF STILL LOCKED
	TDNN T2,CST1(T1)	;IS IT?
	CALL SWPOT0		;NO. SWAP IT OUT THEN
ULDPG2:	MOVE T1,ULDDST		;GET PAGE NUMBER AGAIN
	CALL SKPNWR		;WAIT FOR IT TO FINISH
	 JRST ULDPG2		;TRY AGAIN
	HRRZ T2,ULDSRC		;PAGE NUMBER AGAIN
	LOAD T1,STGADR,CXBPGA(T2) ;GET STORAGE ADDRESS NOW
	TXNE T1,NCORTM		;IM MEMORY?
	JRST ULDPG1		;NO. ALL DONE
	LOAD T2,CSTAGE,(T1)	;YES. GET ITS AGE THEN
	CAIN T2,PSRPQ		;ON RPLQ YET?
	JRST ULDPG1		;YES. DONE THEN
	MOVEM T1,ULDDST		;NO. SAVE MEM PAGE NUMBER
	JRST ULDPG3		;AND DO IT AGAIN
   REPEAT 0,<			;FOR NOW, WAIT FOR SWAP OUT
	MOVE T1,ULDSRC		;GET PTN.PN
	CALL SWPPAG		;SWAP PAGE OUT (CXBPG ALREADY HAS PTN)
	 RETBAD()		;RETURN ERROR (ALREADY RELEASED PTN)
	OKSKED			;RETURNED NOSKED
   >				;END OF REPEAT 0
ULDPG1:	OKSKED			;ALLOW SCHEDULING AGAIN
	CALL RELCXB		;RELEASE UPT (DOES OKINT)
	RETSKP

;HERE FROM LODPPG ON FREE CHOICE OF PAGE

LODFRE:	NOSKED			;PROTECT RPLQ
	CALL CHKRPQ		;WAIT FOR PAGES TO SHOW UP
	 JRST .-1		;WAIT SOME MORE
	HRRZ T1,RPLQ		;GET TOP PAGE
	SUBI T1,CST3		;COMPUTE PAGE NUMBER
	HRRM T1,LODDST		;MAKE IT THE TARGET PAGE
	OKSKED			;NO NEED FOR THIS NOW
	JRST LODPP3		;AND PROCEED
;SWPPAG - SWAP USER PAGE OUT AND WAIT UNTIL COMPLETE
;CALL WITH:
;T1/	PTN.PN
;	CALL SWPPAG
;	 ERROR, PAGE CAN'T BE SWAPPED, CODE IN 1
;	SUCCESS, PAGE IS NOW SWAPPED (RETURNS NOSKED)
;MUST BE CALLED NOINT
;PAGE MUST BE PRIVATE OR NOT EXIST.
;PAGE MUST NOT BE LOCKED

   REPEAT 0,<			;NOT PRESENTLY NEEDED
SWPPAG::STKVAR <SWPSRC,SWPTRY>
	MOVEM T1,SWPSRC
	MOVEI T2,10		;TRY THIS MANY TIMES
	MOVEM T2,SWPTRY
SWPPG1:	HLRZ T3,SWPSRC		;GET PTN
	CALL SETXB1		;MAP PAGE TABLE (GOES NOINT)
	SKIP CXBPGA		;SWAP IN IF NECESSARY
	NOSKED			;DON'T LET PAGE STATE CHANGE
	HRRZ T1,SWPSRC		;GET PAGE NUMBER
	SKIPN T1,CXBPGA(T1)	;GET POINTER
	JRST SWPPG4		;NON-EX
	CALL RELCXB		;RELEASE MAP (OKINT)
	LOAD T2,PTRCOD,T1	;GET POINTER CODE
	CAIE T2,IMMCOD		;PRIVATE?
	RETBAD(LOCKX1,OKSKED)	;NO, ILLEGAL
	TLNE T1,(NCORTM)	;IN CORE?
	RETSKP			;NO, SKIP RETURN NOSKED
	ANDX T1,STGADM		;GET ADDR ONLY
	MOVSI T2,(-PLKV)	;GET LOCK MASK
	TDNE T2,CST1(T1)	;IS PAGE LOCKED?
	RETBAD(LOCKX2,OKSKED)	;YES, ERROR
	CALL SKPNWR		;WAIT FOR ANY WRITES TO FINISH
	 JRST SWPPG2		;HAD TO WAIT, CHECK EVERYTHING AGAIN
	LOAD T2,CSTAGE,(T1)	;GET AGE
	CAIGE T2,PSASN		;ASSIGNED TO PROCESS?
	JRST SWPPG3		;NO, DEASSIGN
	CALL SWPOT0		;SWAP PAGE OUT
SWPPG2:	OKSKED
	JRST SWPPG1		;AND CHECK AGAIN

SWPPG3:	CALL RPCST		;DEASSIGN CST USAGE (SO WE CAN SWAP IN)
	RETSKP			;RETURN SUCCESS (NOW SWAPPED OUT) (NOSKED)

SWPPG4:	HRRZ B,SWPSRC		;GET VIRT PAGE #
	MOVE A,IMMPTR		;GET IMMEDIATE POINTER
	TXO A,UAAB		;SET UNASSIGNED ADDR BIT
	MOVEM A,CXBPGA(B)	;STORE IN PAGE TABLE
	CALL RELCXB		;RELEASE TEMP MAPPING
	RETSKP			;AND INDICATE SUCCESS
   >				;END OF REPEAT 0
;SETUP PAGER VARIABLES FOR NEW PROCESS
; FORKX/ FORK INDEX
;	CALL SETPPG
; RETURN +1 ALWAYS

SETPPG::MOVE FX,FORKX
	LOAD T1,FKPSB		;GET CORE ADR OF PSB
	MOVE T1,SPT(T1)
	TXNE T1,NCORTM
	BUG(HLT,PSBNIC,<SETPPG-PSB NOT IN CORE>)
	STOR T1,PAGUBA		;PUT IT IN DATAO WORD
	MOVE T2,PSBBAS
	STOR T1,STGADR,SPT(T2)	;PUT IT IN MMAP BASE
	LOAD T1,FKJSB		;GET CORE ADR OF JSB
	MOVE T1,SPT(T1)
	TXNE T1,NCORTM
	BUG(HLT,JSBNIC,<SETPPG-JSB NOT IN CORE>)
	MOVE T2,JOBBAS
	STOR T1,STGADR,SPT(T2)	;PUT IT IN MMAP BASE
	HRRZ T1,FKCNO(FX)	;GET PROCESS USE BIT NUMBER
	MOVE T2,BITS(T1)	;GET BIT
	LOAD T1,FKAGE		;GET CURRENT AGE
	STOR T1,AGEMSK,T2	;CONSTRUCT CST UPDATE WORD
	CALL MVAGER		;SET NEW AGE WORD
	RET
;PRELOAD PAGES ON REQUEST
; 1/ IDENT OF FIRST PAGE
; 2/ NUMBER OF SUCCESSIVE PAGES
;	CALL PREPG
; RETURN +1: NOT ALL PAGES DONE
; RETURN +2: ALL PAGES DONE, SWAPIN REQUESTED FOR ALL PAGES NOT IN CORE

PREPG::	PUSH P,2		;SAVE COUNT
	CALL SETCPT		;MAP PAGE TABLE
PREPG4:	MOVE 2,NRPLQ		;CHECK FOR SUFFICIENT FREE PAGES
	CAMG 2,NRPMX		;BELOW MIN?
	JRST [	CALL RELCPT	;YES, RELEASE PAGE TABLE
		POP P,2
		RET]		;RETURN FAIL
	NOSKED
	PUSH P,1		;SAVE IDENT
	HRRZ 2,1
	SKIPE 2,CPTPGA(2)	;GET PTR FROM MAP
	CALL PREPG1		;INITIATE SWAP
	POP P,1			;RECOVER IDENT
	OKSKED
	SOSLE 0(P)		;DONE ALL PAGES?
	AOJA 1,PREPG4		;NO, BUMP IDENT AND GO DO NEXT ONE
	POP P,2
	CALL RELCPT		;RELEASE PT
	RETSKP
;PRELOAD PAGES FOR FORK, FORKX IN 7

PRELD::	SAVEPQ
	SKIPN PRELDF		;PRELOADING IN OPERATION?
	JRST PREL2		;NO
	SETOM PRELRQ		;SET FLAG NOTING PRELOADING SWAPS
	HRRZ 11,FKNR(7)		;CURRENT WS SIZE
	SUBI 11,4		;LESS PSB, UPT, AND 2 RESERVE
	HRRZ 1,FKPGS(7)		;PSB
	CALL SFITPG		;MAP IT INTO FITPG
	HLRZ 1,FKPGS(7)		;PAGE TABLE
	CALL SPRLPG		;MAP INTO PRLPG
	MOVSI 10,-NWSPGS	;SETUP TO SCAN WS BIT WORDS
PREL1:	SKIPE 5,XWSPGS(10)	;ANY PAGES THIS WORD?
PREL6:	JFFO 5,PREL3		;YES
	AOBJN 10,PREL1
PREL2:	SETZM PRELRQ
	RET

PREL3:	ANDCM 5,BITS(6)		;REMOVE BIT FOR PAGE JUST FOUND
	PUSH P,5		;SAVE PARTIAL BIT WORD
	MOVEI 5,0(10)		;COMPUTE PAGE NUMBER IN UPT
	IMULI 5,^D36
	ADDI 6,0(5)
	SKIPN 2,PRLPGA(6)	;CHECK IF PAGE EXISTS
	JRST PREL4		;NONE
	HLLZ 1,FKPGS(7)		;CONSTRUCT IDENTIFIER FOR PRIVATE CASE
	HRRI 1,0(6)		;PTN.PN
	CALL PREPG1		;SWAP IN IF NOT ALREADY IN CORE
PREL4:	POP P,5			;RECOVER PARTIAL BIT WORD
	SOJG 11,PREL6		;KEEP GOING UNLESS WS EXHAUSTED
	JRST PREL2		;QUIT
;PRELOAD A PAGE - INITIATE SWAPIN IF PAGE NOT ALREADY IN CORE
;WILL BE A NOOP IF POINTER IS INDIRECT
; 1/ IDENT OF PAGE
; 2/ PTR
;	CALL PREPG1
; RETURN +1: ALWAYS

PREPG1:	LOAD 3,PTRCOD,2		;GET PTR TYPE
	CAIN 3,INDCOD		;AN INDIRECT POINTER?
	RET			;YES. RETURN IMMEDIATELY
	CAIN 3,SHRCOD		;SHARED?
	JRST [	LOAD 1,SPTX,2	;YES, GET SPT INDEX
		MOVE 2,1	;SPTN TO 2
		CALL CHKDMO	;SEE IF A DISMOUNTED OFN
		 RET		;IT IS . DON'T LOAD IT THEN
		LOAD 2,STGADR,SPT(1) ;AND ADDRESS FROM SPT
		JRST .+1]
	TLNE 2,(NCORTM)		;PAGE NOW IN CORE?
	JRST [	SKIPLE NRPLQ	;MAKE SURE THERE'S ROOM
		TLNN 2,(DSKAB+DRMAB) ;AND PAGE IS ASSIGNED
		JRST PREPG2
		CALL SWPIN	;NO, SWAP IT IN
		JRST PREPG2]
	HRRZ T2,T2		;FLUSH LH
	LOAD 1,CSTAGE,(2)	;PAGE IS IN CORE, SEE WHAT STATE
	CAIN 1,PSRPQ		;ON REPLACABLE?
	JRST PREL5		;YES
	CAIE 1,PSWIP		;BEING WRITTEN?
	JRST PREPG2		;NO, ANYTHING ELSE IS OK
	PIOFF			;INTERLOCK CHECK
	LOAD 3,CSTAGE,(2)	;GET CURRENT AGE
	MOVX 1,PSRDN		;SET NEW AGE
	STOR 1,CSTAGE,(2)	;TO READ COMPLETE
	CAIN 3,PSRPQ		;WAS ON RPLQ?
	JRST PREL5		;YES
	SOS IOIP		;NO, HAVE NOW DISABLED COMPLETION ACTION
	PION
PREPG2:	RET

PREL5:	CALL PRLDEQ		;DEQUEUE THE PAGE FROM RPLQ
	MOVX 1,PSRDN
	STOR 1,CSTAGE,(2)	;SET PAGE TO READ-COMPLETED
	STOR FX,CFXRD,(2)	;NOTE FORK
	JRST PREPG2

;ROUTINE USED BY PREPG1 AND FRCSPM TO DEQUEUE A PAGE FROM RPLQ
;	T2/ PAGE NUMBER

PRLDEQ:	SOS NRPLQ		;TAKE PAGE OFF REPLACABLE
	PIOFF
	MOVE 1,CST3(2)
	HRRZ 3,1
	HLLM 1,0(3)
	HLRZ 3,1
	HRRM 1,0(3)
	PION
	SETZRO <PUFLD,CORMB>,CST0(2)
	SETZM CST3(2)
	RET			;DONE. PAGE DEQUEUED
;CHECK WS BITS AS PROCESS LEAVES BALSET

POSTPG::SKIPG POSPGF		;POST PURGING ON?
	JUMPE 1,R		;NO, RETURN IF NO WS UPDATE NEEDED
	TRVAR <REMBFL>		;FLAG FOR WS UPDATE
	MOVEM 1,REMBFL
	SAVEQ
	CALL SWPOMI		;INIT SWAPOUT LIST
	HRRZ 1,FKPGS(7)
	CALL SFITPG		;MAP VIA FITPG
	HLRZ 1,FKPGS(7)		;PAGE TABLE
	CALL SPRLPG		;MAP VIA PRLPG
	MOVSI 6,-NWSPGS		;SCAN WS BIT WORDS
	SETZ 3,			;COUNTING BITS
REMB2:	SKIPE 4,XWSPGS(6)	;ANY BITS HERE?
REMB7:	JFFO 4,REMB5		;YES, FIND ONE
	AOBJN 6,REMB2
	ADDI 3,3		;PAGES IN WS PLUS 3 FOR MON OVHD
	CAIGE 3,6		;SET NR TO: MAX(6,SIZ,WSBITS+3)
	MOVEI 3,6
	HRRZ 2,FKWSP(7)		;SIZE
	CAIGE 3,0(2)
	MOVEI 3,0(2)
	LOAD 2,FKWSS		;CURRENT NR
	CAILE 3,0(2)		;ABOVE .G. CURRENT?
	MOVEI 3,0(2)		;YES, KEEP CURRENT
	HRRM 3,FKNR(7)		;SET NEW NR
	CALL SWPOMG		;DO IO FOR ALL PAGES FOUND
	RET

;SWAP OUT PURGED PAGE

GCSWP:	MOVE 2,CST1(1)
	TLNE 2,(-PLKV)		;DON'T SWAP PAGE IF LOCKED
	RET
	MOVSI 2,(DWRBIT)
	TDNE 2,CST3(1)		;DON'T SWAP PAGE IF NOW BEING WRITTEN
	RET
	LOAD 2,CSTAGE,(1)	;GET PAGE STATE CODE
	CAIGE 2,PSASN		;PAGE NOW ASSIGNED?
	JRST GCSW1		;NO, SWAP IT
	LOAD 2,CSTOFK,(1)	;GET OWNING FORK NUMBER
	PUSH P,1
	CAIGE 2,NFKS		;ASSIGNED?
	CALL SOSWSP		;YES, DEASSIGN IT
	POP P,1
GCSW1:	SKIPG SWRSAF		;REASSIGNING STORAGE?
	JRST [	CALLRET SWPOUT]	;NO, DO SINGLE-PAGE SWPOUT
	CALLRET SWPOML		;YES, BUILD SWAP LIST
;LOOK AT PAGE IN WS

REMB5:	ANDCM 4,BITS(5)		;REMOVE BIT FROM TEMP WORD
	MOVEI 1,0(6)		;COMPUTE PAGE NUMBER IN PT
	IMULI 1,^D36
	ADDI 1,0(5)
	SKIPN 1,PRLPGA(1)	;PAGE NOW EMPTY?
	JRST REMB6		;YES, FORGET IT
	LOAD 2,PTRCOD,1		;GET PTR TYPE
	CAIN 2,INDCOD		;INDIRECT?
	JRST REMB6		;YES, IGNORE
	CAIN 2,SHRCOD		;SHARED?
	JRST [	LOAD 1,SPTX,1	;YES, GET ADDRESS FROM SPT
		MOVE 1,SPT(1)
		JRST .+1]
	TLNE 1,(NCORTM)		;PAGE NOW IN CORE?
	JRST REMB6		;NO, FORGET IT
	HRRZ 2,1
	LOAD 2,CSTAGE,(2)	;GET PAGE STATE CODE
	CAIGE 2,PSASN		;PAGE IN USE?
	JRST [	CAIE 2,PSRDN	;NO, IS IT READ COMPLETED?
		JRST REMB6	;NO, FLUSH IT
		JRST .+1]	;YES, KEEP IT
	PUSH P,3
	PUSH P,4
	SKIPLE POSPGF		;POST PURGING REQUESTED?
	CALL GCSWP		;YES, SWAP OUT THE PAGE
	POP P,4
	POP P,3
	AOJA 3,REMB7		;COUNT PAGE AND CONTINUE

REMB6:	SKIPN REMBFL		;FORK WAS DISMISSED OR FORCED OUT?
	AOJA 3,REMB7		;FORCED OUT, DON'T FLUSH UNREF PGS
	MOVE 2,BITS(5)
	ANDCAM 2,XWSPGS(6)	;DISMISSED, FLUSH UNREF PAGES
	JRST REMB7
;DEASSIGN CORE

DECOR:	TLNE 1,(NCORTM)		;GIVEN MAP WORD, NOW IN CORE?
	RET			;NO, NOTHING TO DO
	PUSH P,2
	PUSH P,3
	CALL DASWSP		;DEASSIGN PAGE FROM FORK
	MOVSI 2,(-PLKV)
	HRRZ 3,1
	TDNE 2,CST1(3)		;PAGE WAS LOCKED?
	JRST [	AOS BALSHC	;YES, CHARGE TO OVERHEAD
		AOS SUMNR
		JRST .+1]
	POP P,3
	POP P,2
	RET

;REMOVE PAGE FROM CURRENT FORK ASSIGNMENT
; A/ CORE PAGE NUMBER
;	CALL DASWSP
; RETURN +1, PAGE DEASSIGNED IF PREVIOUSLY ASSIGNED.

DASWSP:	HRRZ 2,1
	LOAD 2,CSTAGE,(2)	;GET STATE CODE
	CAIGE 2,PSASN		;NOW ASSIGNED?
	RET			;NO
	HRRZ 2,1
	LOAD 2,CSTOFK,(2)	;GET PROCESS ASSIGNMENT
	CAIL 2,NFKS		;ASSIGNED?
	RET			;NO
	PUSH P,1
	CALL SOSWSP		;REDUCE N FOR THIS PROCESS
	HRRZ 1,0(P)
	MOVX 2,OFNUL		;MARK PAGE UNASSIGNED
	STOR 2,CSTOFK,(1)
	POP P,1
	RET

;DECREMENT WSP AND RELEASE CORE NUMBER IF WSP 0

SOSWSP:	SOS 1,FKWSP(2)
	TRNE 1,400000		;NEGATIVE?
	JRST [	BUG(CHK,WSPNEG,<SOSWSP-WSP NEGATIVE>)
		SETZB 1,FKWSP(2) ;FIXUP SOMEWHAT
		JRST .+1]
	TRNE 1,777777		;WSP NOW 0?
	RET			;NO
	PUSH P,FX
	MOVEI FX,0(2)
	LOAD 1,FKLOC
	POP P,FX
	CAIGE 1,NBP		;IN BALSET?
	RET
	HRRZ 1,FKCNO(2)
	JUMPE 1,R		;NO NUMBER (?)
	HLLZS FKCNO(2)
	MOVE 1,BITS(1)
	IORM 1,FRECB
	RET
;GARBAGE COLLECT CORE, REMOVE PAGES OF PROCESSES NOT IN BAL SET

;LOCAL AC USE:
; P1/ NUMBER OF PAGES NOW AVAILABLE (NRPLQ+IOIP+COLLECTED)
; P2/ MASK FOR CORE NUMBERS OF PROCESSES NOW IN BALSET
; P3/ TEMP
; P4/ CURRENT CORE PAGE NUMBER

GCCOR::	MOVE T1,NRPLQ
	ADD T1,IOIP		;NUMBER OF PAGES NOW OR SOON TO BE AVAILABLE
	;SUBI T1,GCMIN0/4	;LESS PAD
	CAMG T1,NRPMIN		;SUFFICIENT?
	SKIPG NSSUN		;FILESYS INITIALIZED?
	RET			;NO, DO NOTHING
	MOVE 1,NRPMX
	CAMLE 1,NRPLQ
	MOVE 1,NRPLQ		;INSPECT N PAGES
GCCORX:	SAVEP
	SKIPL SSKED		;NOSKED FORK?
	JRST [	SKIPN NRPLQ	;YES, DESPERATE?
		SKIPE IOIP
		RET		;NO, DO NOTHING
		JRST .+1]	;YES, GO AHEAD
	AOS NGCCOR		;COUNT OCCURRANCES
	JUMPE 1,GCPC2		;N MAY BE 0 ...
	HRRZ P3,RPLQ		;ON REPLACABLE QUEUE
GCPC1:	MOVEI 3,0(P3)
	SUBI 3,CST3		;GET PAGE NUMBER
	CALL DEPG		;UNDO POINTER AND FLUSH BACK PTR,
	SETZM CST2(3)		;THUS UNLOCKING OWNING PT
	HRRZ P3,0(P3)
	SOJG 1,GCPC1
GCPC2:	MOVEI T1,GCMIN0		;GET INITIAL TARGET RPLQ LEVEL
	ADD 1,NRPMIN		;INCLUDING RESERVES FOR FORKS ENTERING BS
	SKIPE SKEDFC		;FORCED CLEAR?
	MOVX T1,1B1		;YES, VERY LARGE NUMBER
	MOVEM 1,GCMINP
GCPC4:	SKIPA SKEDFC		;FORCED CLEAR? **** UNDER INVESTIGATION ***
	JRST [	CALL FGC	;NO, TRY FAST GC
		JUMPE P2,GCPC3	;JUMP IF NOTHING FOUND
		MOVE T1,NRPLQ	;SEE HOW MANY PAGES NOW AVAILABLE
		ADD T1,IOIP
		CAMG T1,GCMINP	;SUFFICIENT?
		JRST GCPC4	;NO, DO ANOTHER FORK
		RET]		;OK, DONE
GCPC3:	MOVE P1,NRPLQ
	ADD P1,IOIP		;WRITES NOW IN PROGRESS
	SETZB P2,P3		;FOR BITS OF BALSET PROCESSES
GCCOR3:	CAML P3,FBALS		;LOOKED AT ALL BALSET PROCESSES?
	JRST GCCOR2		;YES
	MOVE 1,BALSET(P3)
	TLNE 1,(BSNUL)		;VALID PROCESS NUMBER?
	AOJA P3,GCCOR3		;NO
	HRRZ 1,FKCNO(1)
	IOR P2,BITS(1)		;PROCESS IN BALSET
	AOJA P3,GCCOR3

;ENTRY TO GCCOR TO DEPG ALL RPLQ FIRST

GCCOR0::MOVE 1,NRPLQ
	JRST GCCORX
;FORK GC - COLLECT PAGES FOR SPECIFIED PROCESS
; FX/ FORK INDEX
;	CALL FKGC

FKGC::	SAVEAC <P1,P2>
	MOVEI P2,1		;SCAN ONLY THIS FORK
	MOVE T1,MONCOR		;SETUP AOBJN PTR
	SUB T1,NHIPG
	MOVSI P1,-1(T1)
	HRR P1,MONCOR
	CALL SWPOMI		;INIT SWAPOUT LIST
	JRST FGC1		;GO SCAN CORE

;'FAST' GC - COLLECT PAGES FOR ONE PROCESS

FGC:	SETZ P2,		;INIT COUNT OF PAGES COLLECTED
	MOVE T1,MONCOR		;SETUP AOBJN PTR
	SUB T1,NHIPG
	MOVSI P1,-1(T1)		;NEG COUNT
	HRR P1,MONCOR
	CALL SWPOMI		;INIT SWPOUT LIST
FGC5:	LOAD T1,CSTAGE,(P1)	;SCAN FOR FIRST COLLECTABLE PAGE
	CAIL T1,PSASN		;ASSIGNED?
	JRST FGC4		;YES, CHECK IT
FGC6:	AOBJN P1,FGC5		;DO NEXT PAGE
	RET			;FOUND NO COLLECTABLE PAGE

FGC4:	LOAD FX,CSTOFK,(P1)	;GET OWNING FORK
	CAIGE FX,NFKS		;ASSIGNED TO EXISTANT FORK?
	SKIPGE FKPT(FX)
	JRST FGC6		;NO
	LOAD T1,FKLOC
	CAIGE T1,NBP		;FORK ON WTLST?
	JRST FGC6		;NO, IN BALSET
	HLRZ T1,FKPT(FX)
	CAIE T1,WTLST
	JRST FGC6		;NO

;NOW SCAN REST OF CST FOR PAGES OWNED BY SAME FORK

FGC1:	LOAD T1,CSTOFK,(P1)
	CAMN T1,FX		;SAME FORK
	JRST FGC2		;YES, COLLECT IT
FGC3:	AOBJN P1,FGC1		;DO ALL PAGES
	CALL SWPOMG		;SWAPOUT LIST
	RET			;DONE OK

FGC2:	LOAD T1,CSTAGE,(P1)
	CAIGE T1,PSASN		;PAGE ASSIGNED?
	JRST FGC7		;NO
	MOVX T1,-PLKV
	MOVX T2,DWRBIT
	TDNN T1,CST1(P1)	;PAGE LOCKED?
	TDNE T2,CST3(P1)	;PAGE BEING WRITTEN?
	JRST [	HRRZ T1,P1	;YES, JUST DEASSIGN IT
		CALL DASWSP
		JRST FGC7]
	ADDI P2,1		;COUNT PAGES COLLECTED
	HRRZ T1,P1		;DEASSIGN PAGE
	CALL DASWSP
	HRRZ T1,P1
	MOVX T2,CORMB
	TDNE T2,CST0(P1)	;PAGE MODIFIED?
	SKIPG SWRSAF		;REASSIGN SWAP ADDRESSES?
	JRST [	CALL SWPOUT	;NO, SINGLE PAGE SWPOUT
		JRST FGC7]
	CALL SWPOML		;YES, YES - BUILD SWAP LIST
FGC7:	JUMPG P2,FGC3		;CONTINUE SAME FORK IF PAGES COLLECTED
	JRST FGC6		;LOOK FOR ANOTHER FORK IF PAGE NOT COLLECTABLE
GCCOR2:	ANDCAM P2,PUBCL		;FOR PROCESSES WHICH CAME BACK IN BALSET
	CALL SWPOMI		;INIT SWAPOUT LIST
	MOVE P4,MONCOR
	SUB P4,NHIPG		;COMPUTE MAX NUMBER PAGES TO CHECK
	MOVSI P4,-1(P4)
	SKIPN T1,GCCLPG		;START WHERE ENDED LAST TIME
	MOVE T1,MONCOR		;OR AT LOWEST PAGE
	HRR P4,T1		;SETUP AOBJN PTR
GCC2:	HRRZ T1,P4
	CAMLE T1,NHIPG		;REACHED END OF CORE?
	CALL GCECOR		;YES, VARIOUS FIXUPS AND WRAPAROUND
	LOAD 1,CSTAGE,(P4)	;CODE FIELD
	SKIPE SKEDFC		;FORCED CLEAR?
	JRST [	CAIE T1,PSRDN	;READ DONE?
		CAIL T1,PSASN	;NO. ASSIGNED THEN?
		JRST GCCS	;YES. COLLECT IT THEN
		JRST GCC1]	;NO. MUST LEAVE IT
	CAIGE 1,PSASN		;PAGE IN USE?
	JRST [	CAIN T1,PSSPQ	;NO, PAGE ON SPECIAL MEMORY QUEUE?
		AOS BSHC1	;YES, CHARGE TO SYSTEM
		CAIE T1,PSRDN	;READ COMPLETE?
		JRST GCC1	;NO, SKIP PAGE
		CAMGE P1,NRPMIN	;TIGHT FOR CORE?
		JRST GCCS	;YES, GRAB A PRELOADED PAGE
		LOAD FX,CFXRD,(P4) ;GET FX OF FORK WHICH INITIATED READ
		CAIGE FX,NFKS	;IF NOT A FORK,
		SKIPGE FKPT(FX)	;OR FORK DELETED?
		JRST GCCS	;FLUSH PAGE
		LOAD 2,FKLOC
		CAIL 2,NBP	;IF FORK NOT IN BALSET,
		JRST GCCS	;COLLECT PAGE
		JRST GCC1]	;LEAVE PAGE
	LOAD FX,CSTOFK,(P4)	;GET PROCESS ASSIGNMENT
	CAIGE FX,NFKS		;PAGE NOW ASSIGNED?
	SKIPGE FKPT(FX)		;AND FORK NOT DELETED?
	JRST GCCS		;NO, COLLECT IT
	MOVE 1,PUBCL		;PROCESS BITS TO BE CLEARED
	ANDCAB 1,CST0(P4)
	LOAD 3,FKLOC
	CAIGE 3,NBP		;OWNER IN BALSET?
	JRST GCC1		;YES, KEEP PAGE
	HLRZ 3,FKPT(FX)		;CURRENT LOCATON
	CAIE 3,WTLST		;ON WAIT LIST, OR
	TDNN 1,P2		;USERS IN BALSET?
	JRST GCCS		;NO, COLLECT
	CAMGE P1,NRPMIN		;TIGHT ON CORE?
	JRST GCCS		;YES, COLLECT SHARED PAGE
	AOS BSHC1		;NO, CHARGE PAGE TO SYSTEM
	JRST GCC1
GCCS:	HRRZ 1,P4
	CALL DASWSP		;DEASSIGN PAGE FROM FORK
	MOVE 2,CST1(P4)		;BACKUP ADDRESS
	TLNE 2,(-PLKV)		;PAGE LOCKED?
	JRST [	AOS BSHC1	;YES, LEAVE IT AND CHARGE TO SCHED
		JRST GCC1]
	MOVSI 2,(DWRBIT)
	TDNE 2,CST3(P4)		;PAGE BEING WRITTEN?
	JRST GCC1		;YES, LEAVE IT
	HRRZ T1,P4		;SWAPOUT
	MOVX 2,CORMB
	TDNE 2,CST0(1)		;PAGE WAS WRITTEN?
	SKIPG SWRSAF		;REASSIGNING SWAP STORAGE?
	JRST [	CALL SWPOUT	;NO, DO SINGLE-PAGE SWAPOUT
		JRST .+2]
	CALL SWPOML		;YES, PUT PAGE ON LIST
	ADDI P1,1		;COUNT PAGES COLLECTED
	CAMGE P1,GCMINP		;STOP IF COLLECTED ENOUGH
GCC1:	AOBJN P4,GCC2
	MOVEM P4,GCCLPG		;REMEMBER LAST PAGE DONE
	CALL SWPOMG		;DO ALL SWAPS QUEUED ABOVE
	SETZM CGFLG
	RET

GCECOR:	HRR P4,MONCOR		;RESET TO LOWEST PAGE
	MOVE T1,BSHC1		;GET NEW BALSHC VALUE
	PIOFF			;PROTECT AGAINST CHANGES AT PI LEVEL
	SUBM T1,BALSHC		;COMPUTE NEW-OLD
	EXCH T1,BALSHC		;SET NEW VALUE
	ADDM T1,SUMNR		;ADJUST SUMNR BY DIFFERENCE
	PION
	SETZM BSHC1		;RESET NEW SHARE COUNT
	RET
;MULTIPLE-PAGE SWAPOUT ROUTINES.  PROCEDURE:
; 1. CALL SWPOMI TO INIT LIST
; 2. CALL SWPOML FOR EACH PAGE TO BE SWAPPED
; 3. CALL SWPOMG TO BEGIN IO FOR ALL PAGES

;INIT SWAPOUT LIST
;	CALL SWPOMI
; RETURN +1: ALWAYS

SWPOMI:	SETZM SWPRC0		;INIT COUNT
	MOVEI 1,SWPLST		;INIT END PTR
	MOVEM 1,SWPLSI
	SETZM SWPLST		;INIT LIST PTR
	RET

;ADD PAGE TO SWAPOUT LIST IF POSSIBLE.  IF PAGE WOULD NOT BE SWAPPED
;TO DRUM THEN CALL REGULAR SWAPOUT.  OTHERWISE, DEASSIGN
;EXISTING DRUM ADDRESS AND PUT PAGE ON LIST.

SWPOML:	SKIPN 2,CST2(1)		;PTR BACKUP EXISTS?
	JRST SWPOM1		;NO, EXCEPTION CASE.
	HLRZ 3,2		;CHECK IF IN SPT
	JUMPN 3,[CAIGE 3,NOFN	;PAGE LIVES IN FILE XB?
		JRST SWPOM1	;YES, EXCEPTION CASE.
		JRST SWPOM2]	;NO, PAGE LIVES IN FORK PAGE TABLE
	MOVE T3,T1		;SAVE STORAGE ADDRESS
	MOVEI T1,0(T2)		;SPT INDEX
	CALL GETSHR		;GET SHARE COUNT
	EXCH T1,T3		;RESTORE REGS
	JUMPE 3,SWPOM1		;IF SHARE COUNT 0, THEN EXCEPTION CASE
SWPOM2:	MOVE 2,CST1(1)		;CHECK EXISTING BACKUP ADDRESS
	TLNN 2,(DSKAB)		;HAS DRUM ADDRESS NOW?
	TLNN 2,(DRMAB)
	JRST SWPOM1		;NO, EXCEPTION CASE
	CALL GDSTX		;GET DST INDEX FOR DRUM ADDRESS
	MOVE 3,DST(2)		;GET NEXT LEVEL BACKUP ADDRESS
	MOVX 4,CORMB
	TLZE 3,(BWRBIT)		;MODIFIED ON DRUM?
	IORM 4,CST0(1)		;YES, NOTE
	SETOM DST(2)		;FLUSH DST SLOT
	EXCH 3,CST1(1)		;REPLACE BACKUP ADDRESS FOR PAGE
	PUSH P,1
	MOVE 1,3		;GET DRUM ADDRESS
	CALL DASDRM		;DEASSIGN IT
	POP P,1
	MOVEI 2,CST3(1)		;PUT PAGE ON SWAPOUT LIST
	HLLZS 0(2)		;MARK END OF LIST WITH 0
	HRRM 2,@SWPLSI		;APPEND TO END OF LIST
	MOVEM 2,SWPLSI		;UPDATE END PTR
	AOS SWPRC0		;COUNT PAGES ON LIST
	RET

;EXCEPTION CASE - PAGE CANNOT BE WRITTEN ON DRUM OR HAS NO DRUM ADDRESS

SWPOM1:	CALLRET SWPOUT		;USE SINGLE-PAGE SWPOUT
;ASSIGN NEW DRUM STORAGE AND INITIATE I/O FOR ALL PAGES ON SWAPOUT LIST.

SWPOMG:	SKIPG SWPRC0		;ANY PAGES ON LIST?
	RET			;NO
	PUSH P,P1
	PUSH P,P2
SWPOG2:	HRRZ P1,SWPLST		;GET LIST OF PAGES TO DO
	MOVE 1,SWPRC0		;GET COUNT OF PAGES LEFT ON LIST
	CALL DRMAM		;TRY TO GET THAT MANY SEQUENTIAL PAGES
	MOVEM 2,SWPDAD		;REMEMBER FIRST ADDRESS OF GROUP
	CAMLE 1,SWPRC0		;GOT MORE THAN NEEDED?
	MOVE 1,SWPRC0		;YES
	MOVEM 1,P2		;REMEMBER COUNT OF CURRENT GROUP
	MOVN 1,1
	ADDM 1,SWPRC0		;REDUCE NUMBER LEFT BY THIS GROUP SIZE
SWPOG1:	JUMPE P1,SWPOG3		;JUMP IF END OF LIST
	MOVE 1,SWPDAD		;HAVE ANOTHER PAGE TO DO, GET NEXT DRUM
	CALL DRMASA		; ADDRESS IN SEQUENCE AND ASSIGN IT
	 BUG(HLT,ASGSW2,<SWPOMG-CAN'T ASSIGN RESERVED DRUM ADDRESS>)
	MOVEI 1,0(P1)		;GET PAGE NUMBER
	SUBI 1,CST3
	MOVE 2,SWPDAD		;GET NEW DRUM ADDRESS
	MOVE 4,CST1(1)		;GET PRESENT BACKUP ADR FOR PAGE
	MOVEM 2,CST1(1)		;SET DRUM ADR AS NEW BACKUP
	CALL GDSTX		;GET DST INDEX FOR DRUM ADDRESS
	MOVX 3,CORMB
	TDNE 3,CST0(1)		;PAGE WAS MODIFIED IN CORE?
	TLO 4,(BWRBIT)		;YES, MEANS MODIFIED RELATIVE TO DISK TOO
	MOVEM 4,DST(2)		;SAVE DISK ADR OF PAGE
	ANDCAM 3,CST0(1)	;CLEAR MODIFIED BIT IN CORE
	MOVEI 3,PSWIP		;GET WRITE-IN-PROGRESS CODE
	STOR 3,CSTAGE,(1)	;SET STATUS OF PAGE
	AOS IOIP		;NOTE 1 MORE WRITE IN PROGRESS
	AOS DRMWR		;NOTE 1 MORE DRUM WRITE
	MOVE 1,SWPDAD		;BUMP DRUM ADDRESS TO NEXT PAGE
	CALL DRMIAD
	MOVEM 1,SWPDAD
	SOJG P2,[HRRZ P1,0(P1)	;DO CDR IF HAVE MORE PAGES IN THIS GROUP
		JRST SWPOG1]	;GO DO NEXT ONE
SWPOG3:	HRRZ 1,0(P1)		;END OF GROUP, GET PTR TO NEXT GROUP
	HLLZS 0(P1)		;TIE OFF LIST
	EXCH 1,SWPLST		;SET NEXT LIST, GET CURRENT LIST
	SUBI 1,CST3		;MAKE PTR RELATIVE
	TXO 1,DWRBIT		;SAY WRITE
	CALL DRMIOM		;DO MULTI-PAGE WRITE
	SKIPLE SWPRC0		;DONE ALL OF GROUP, STILL PAGES ON LIST?
	JRST SWPOG2		;YES, DO ANOTHER GROUP
	POP P,P2
	POP P,P1
	RET
;SWAP OUT PAGE REQUESTED BY PROCESS
; A/ CORE PAGE NUMBER
;	CALL SWPOT0
; RETURN +1, SWAPOUT OF PAGE INITIATED.

SWPKPF==1B0			;LOCAL FLAG: 0 = USE OFRQ, 1 = USE ONRQ

SWPOTK:	SAVEAC <Q1>
	MOVX Q1,SWPKPF		;KEEP PAGE
	JRST SWPOT1

SWPOT0:	SAVEAC <Q1>
	MOVX Q1,0
SWPOT1:	TLNE 1,(NCORTM)		;IN CORE?
	JRST SWPTBD		;NO
	HRRZ 2,1
	CAML 2,MONCOR		;NO, LEGAL PAGE NUMBER?
	CAMLE 2,NHIPG
	JRST [	CALL RESPCK	;PART OF RESMON?
		 JRST .+1	;NO. SWAP IT OUT THEN
		JRST SWPTBD]	;YES. ERROR OF SOME SORT
	CALL AGESET		;BE SURE PAGE IS READY
	CALL DASWSP		;NOW DEASSIGN IT
	MOVE 2,CST1(1)
	TLNE 2,(-PLKV)		;CAN SWAP IT OUT?
	JRST SWPTBD		;NO, LOCKED
	MOVSI 2,(DWRBIT)
	TDNE 2,CST3(1)		;BEING WRITTEN?
	JRST SWPTBD		;YES
	CALLRET SWPOU0		;ALL OK, SWAPOUT THE PAGE

;HERE IF ANYTHING WRONG WITH PAGE

SWPTBD:	BUG(HLT,ILPAG1,<SWPOT0-INVALID PAGE>)
;INITIATE SWAPOUT OF SINGLE PAGE
; 1/ CORE PAGE NUMBER
;	CALL SWPOUT
; RETURN +1: ALWAYS, IO REQUESTED OR PAGE PUT ON REPLACABLE QUEUE

SWPOUT:	SAVEAC <Q1>
	MOVX Q1,0		;CLEAR FLAGS
SWPOU0:	SKIPN 2,CST2(1)		;GET BACKUP
	JRST BKUPN		;PAGE HAS NO BACKUP, FLUSH IT
	HLRZ 3,2		;CHECK PT OF SOURCE
	JUMPN 3,[CAIGE 3,NOFN	;PAGE LIVES IN FILE XB?
		JRST BKUPC	;YES. GO CHECK FOR DISK OR DRUM
		JRST BKUPS]	;NO, PAGE LIVES IN FORK PT, SEND TO DRUM
	MOVE T3,T1		;SAVE STORAGE ADDRESS
	MOVEI T1,0(T2)		;GET SPTN
	CALL GETSHR		;GET SHARE COUNT
	EXCH T1,T3		;RESTORE REG VALUES
	CAIGE 2,NOFN		;OFN?
	JRST SWPOF1		;YES
	JUMPE 3,BKUPD		;IF SHARE COUNT 0, SWAP TO DISK
BKUPC:	MOVE 2,CST3(1)
	TLNE 2,(DSKSWB)		;SWAP TO DISK REQUESTED BY DDMP?
	JRST BKUPD		;YES
BKUPS:	MOVE 2,CST1(1)		;CORE PAGE NUMBER IN 1, GET BACKUP ADR
	TLNN 2,(DSKAB)		;DISK OR UNASSIGNED?
	TLNN 2,(DRMAB)
	JRST SWPO4		;YES
BKUP0:	MOVE 3,CST0(1)		;HAVE DRUM ADDRESS
	TXNN 3,CORMB		;PAGE WRITTEN INTO?
	JRST BKUPN		;NO, PUT IT ON RPLQ
	CALL GDSTX
SWPO5:	MOVSI 3,(BWRBIT)	;SET BACKUP WRITTEN BIT
	IORM 3,DST(2)
SWPO2:	MOVX 3,CORMB
	ANDCAM 3,CST0(1)	;CLEAR WRITTEN BIT
	MOVEI 3,PSWIP
	STOR 3,CSTAGE,(1)	;SET CODE TO WRITE IN PROGRESS
	AOS IOIP		;NOTE WRITE IN PROGRESS
	HRLI 1,(DWRBIT)		;WRITE REQUEST BIT
	CALL DRMIO		;INITIATE DRUM WRITE
	AOS DRMWR		;COUNT DRUM WRITES FOR STATISTICS
	RET

;OFN - MUST ALWAYS SWAP TO DRUM

SWPOF1:	SKIPG 3			;SHARE COUNT OK?
	 JRST [	MOVE 1,2	;NO. OFN IS UNUSED
		CALLRET CLROFN]	;SO GET RID OF IT
	MOVE 2,CST1(1)		;YES, CHECK BACKUP ADDRESS
	TLNN 2,(DSKAB)		;DISK?
	JRST BKUP0		;NO, DRUM ADR ALREADY ASSIGNED
	SKIPGE DRUMP		;YES, MUST ENSURE SWAP OF XB TO DRUM
	RET			;CAN'T SWAP TO DRUM, LEAVE IN CORE
	JRST SWOFN		;GO ASN DRM ADR, EVEN IF DRM SPC LOW
;HERE IF NEED TO ASSIGN DRUM ADDRESS FOR PAGE GOING TO DRUM

SWPO4:	MOVSI 3,(SWPERR)
	TDNE 3,CST3(1)		;ERROR READING FROM DISK?
	JRST BKUPN		;YES, DON'T WRITE IT
	MOVE 3,DRMFRE
	CAMGE 3,DRMIN0		;YES. HAVE ROOM ON THE SWAPPING?
	JRST [	TXNN T2,DSKAB	;NO. HAVE A BACK UP DISK ADDRESS?
		JRST SWOFN	;NO. PUT IT ON THE SWAP SPACE ANYWAY
		HLRZ T3,CST2(T1) ;YES. GET HOME FOR THIS PAGE
		SKIPN T3	;DOES IT LIVE IN AN OFN?
		HRRZ T3,CST2(T1) ;NO. GET SPT INDEX THEN
		CAIL T3,NOFN	;IS THIS THE OFN?
		HLRZ T3,SPTH(T3) ;NO. GET IT FROM THE SHARE POINTER THEN
		JUMPE T3,SWOFN	;IF A FORK PT PAGE, PUT IT ON THE SWAP SPACE
		MOVE T3,SPTH(T3) ;GET OFN FLAGS
		TXNE T3,OFNDUD	;SUPPRESSING DISK UPDATE?
		JRST SWOFN	;YES. PUT IT ON SWAP SPACE
		JRST BKUPD]	;NO. PUT IT ON THE DISK THEN
SWOFN:	PUSH P,1
	CALL DRMASN		;ASSIGN DRUM ADDRESS
	BUG(HLT,DRMFUL,<DRUM COMPLETELY FULL>)
	MOVE 2,1
	POP P,1
	MOVE 4,CST1(1)		;GET PREVIOUS BACKUP ADDRESS
	MOVEM 2,CST1(1)		;SET DRUM AS NEW BACKUP ADDRESS
	CALL GDSTX
	MOVEM 4,DST(2)		;PREVIOUS BACKUP ADDRESS TO DST
SWPP1:	MOVE 3,CST0(1)
	TXNE 3,CORMB		;PAGE WRITTEN WHILE IN CORE?
	JRST SWPO5		;YES, SET BACKUP WRITTEN BIT ALSO
	JRST SWPO2		;NO
;SWAP PAGE TO DISK

BKUPD:
BKUPD1:	MOVE 2,CST1(1)		;GET BACKUP ADDRESS
	TLNN 2,(DSKAB+DRMAB)	;NONE?
	JRST BKUP7		;YES
	TLNE 2,(DSKAB)		;DISK?
	JRST BKUP3		;YES
	CALL GDSTX		;DRUM
	MOVE 3,DST(2)		;GET NEXT LEVEL BACKUP ADDRESS
	MOVX 4,CORMB
	TLZE 3,(BWRBIT)		;WRITTEN SINCE BACKUP?
	IORM 4,CST0(1)		;YES, SET CORE WRITTEN BIT
	SETOM DST(2)		;RELEASE DST SLOT
	EXCH 3,CST1(1)
	PUSH P,1
	MOVE 1,3
	CALL DASDRM		;DEASSIGN DRUM ADDRESS
	POP P,1
	JRST BKUPD1

BKUP7:	BUG(HLT,BKUPDF,<BKUPD - BAD CST1 ENTRY OR INCONSISTENT CST>)

BKUP3:	MOVX T3,SWPERR
	TDNE T3,CST3(T1)	;ERROR IN PAGE?
	JRST BKUPN		;YES, DON'T WRITE IT
	MOVX T3,CORMB
	TDNN T3,CST0(T1)	;PAGE MODIFIED?
	JRST [	TXNN Q1,SWPKPF	;NO, WHICH END OF RPLQ?
		JRST BKUPF	;TOP
		JRST BKUPN]	;END
	ANDCAM 3,CST0(1)
	HRLI 1,(DWRBIT)		;REQUEST WRITE
	AOS DSKWR		;COUNT IT FOR STATISTICS
	AOS IOIP		;NOTE WRITE IN PROGRESS
	MOVSI 3,(DSKNB)
	ANDCAM 3,CST1(1)	;MAKE SURE NO (DSKNB) STILL AROUND
	MOVEI 3,PSWIP		;INDICATE WRITE IN PROGRESS
	STOR 3,CSTAGE,(1)
	LOAD T3,SWPKPF,Q1	;SAVE KEEP FLAG FOR SWPDON
	STOR T3,DSKSWB,CST3(T1)
	CALL DSKIO
	RET

;HERE IF PAGE CAN BE PUT DIRECTLY ON RPLQ.

BKUPF:	CALLRET OFRQ		;TOP

BKUPN:	CALLRET ONRQ		;END
;PAGER TRAP

PGRTRP::DATAO PAG,SETMON	;SET MON AC BLOCK
	AOSGE INTDF		;MUST BE NOINT
	JRST [	BUG (CHK,NSKDT2,<PGRTRP-BAD INTDF>)
		SETZM INTDF	;FIX THE BAD VALUE
		JRST .+1]	;AND PROCEED
	SKIPE EXADF1		;EXTENDED ADDRESS?
	JRST PGRTE1		;YES
	EXCH T1,TRAPFL		;SAVE T1
	MOVEM T1,TRAPS0		;SAVE TRAP REASON
	HLLZ T1,TRAPPC		;GET FLAGS
	HRRZS TRAPPC		;ZERO HIGH PC
	EXCH T1,TRAPFL		;STORE FLAGS
PGRTE1:	CONSZ PI,177B27		;FROM PI ROUTINE?
	JRST PIPTRP		;YES. GO HANDLE IT THEN
	AOSE TRAPC		;FIRST TRAP?
	JRST PGRT2		;NO, RECURSIVE
	MOVEM P,TRAPAP		;SAVE AC-P
	MOVE P,TRAPSP		;SETUP TRAP STACK
	AOS UTRPCT		;COUNT TRAPS (BUT NOT RECURSIVE ONES)
PGRT2:	EXCH A,TRAPFL		;CHECK FLAGS
	TXNE A,UMODF		;USER?
	JRST [	EXCH A,TRAPFL	;YES, DON'T NEED TO SAVE ACS
		XJRSTF [PCU		;NOTE PERVIOUS CONTEXT USER
			0,,PGRT3]]
	EXCH A,TRAPFL
	ADD P,BHC+4		;SAVE ACS 1-4
	DMOVEM 1,-3(P)
	DMOVEM 3,-1(P)
	PUSH P,7
	PUSH P,CX
	PUSH P,TRAPSW
PGRT3:	LDB T2,[POINT 5,TRAPPC,17]
	LDB T1,[POINT 5,TRAPS0,17]
	SKIPG TRAPS0		;CHECK FOR USER OR MONITOR
	JRST SIMT2		;USER -- DON'T BUGHALT
	CAIE T2,MSEC1		;IS PC IN "CODE" SECTION?
	SKIPN T2		;NO. HOW ABOUT SECTION 0?
	CAILE T1,MAXSEC		;YES. IS REFERENCE TO A VALID SECTION?
	BUG(HLT,SECGT1,<PGRT3 - SECTION NUMBER GREATER THAN MAXSEC>)
SIMT2:	NOSKED			;NOSKED AND NOINT FOR DURATION OF TRAP
SIMT3:	MOVE 1,TRAPS0		;MOVE TRAP STATUS FROM TEMP
	MOVEM 1,TRAPSW		;TO SAFE PLACE
	SKIPE TRAPC
	JRST PGRT5		;NESTED TRAP, DON'T COUNT TIME TWICE
	SKIPE IPTIM		;INCLUDE PAGE TRAP TIME?
	JRST [	CALL GETHRT	;NO, GET CURRENT RUNTIME
		PUSH P,T1	;SAVE IT
		JRST PGRT5]
	CALL FRTOFF		;TURN OFF CLOCK
	PUSH P,T1		;HOLD STACK SLOT
PGRT5:	DMOVE 1,TRAPFL		;RETURN
	PUSH P,2		;SAVE TRAP
	PUSH P,1
	EXCH 1,2
	TLNE 2,(UMODF)		;FROM USER?
	DMOVEM 1,UPDL		;YES, LEAVE IT WHERE IT CAN BE FOUND
	MOVE FX,FORKX
	MOVE T1,TRAPSW
	TXNE T1,TWHPFF		;'HARD' FAILURE?
	JRST [	LOAD T1,TWCOD,T1 ;YES, GET CODE
		CAIL T1,PECOD0	;MPE GROUP?
		JRST PGMPE	;YES
		CAIGE T1,KLCOD0	;PROBLEM GROUP?
		JRST PFDSPT-TWCOD0(T1) ;YES, DISPATCH TO HANDLER
		JRST .+1]
	CALL PGTACC		;ACCOUNT FOR ONE PAGE TRAP
TRPRST:	CALL GETTPD		;DETERMINE CAUSE OF TRAP
	JRST 0(T1)		;DISPATCH TO HANDLE IT
;PAGE FAIL AT PI LEVEL. SEE IF AR/ARX AND IF SO, DO ANALYSIS.
;IN ALL CASES, BUGHLT
;NOTA BENE... THE SAVING OF T1 IN MEMPA DOES NOT INSURE THAT
;THE REGISTER'S INITITAL CONTENTS WILL ALWAYYS BE AVAILABLE IN
;A SUBSEQUENT DUMP. IF MULTIPLE PI LEVELS TRIP THROUGH THIS CODE,
;OR IF A MEMORY PARITY OCCURS FOLLOWS CLOE UPON A PI PAGE FAIL
;FROM A BUG, THEN THE CONTENTS OF MEMAP IS NOT WHAT IS NEEDED.
;IN THE UNLIKELY EVENT THAT THIS HAPPENS, WAIT FOR THE NEXT
;OCCURRENCE OF THE BUG.
;ADD DISCALIMER TO PIPTRP

PIPTRP:	MOVEM T1,MEMPA		;SAVE AN AC FOR DUMP ANALYSIS
	MOVE T1,TRAPSW		;GET PAGE FAIL WORD
	TXNN T1,TWHPFF		;ONE OF THE "HARD" FAILURES?
	JRST PIPTR1		;NO. BAD CODING THEN
	LOAD T2,TWCOD,T1	;YES. GET REASON
	CAIL T2,PECOD0		;AR OR ARX?
	JSP T2,PFAID		;YES. GO ANALYIZE IT
PIPTR1:	BUG(HLT,PITRAP,<PAGER TRAP WHILE PI IN PROGRESS>)
;DISPATCH FOR PAGE FAIL CODES

TWCOD0==20			;FIRST 'HARD' PAGE FAIL CODE
KLCOD0==30			;START OF KL PAGING CODES
PECOD0==36			;MPE GROUP
PFDSPT::JRST UBPGF		;UNIBUS PAGE FAIL
	JRST ILRD		;PROPRIETARY
	JRST PGRTH		;REFILL ERROR
	JRST ADRCMP		;ADDRESS COMPARE
	JRST ILIND		;ILLEGAL INDIRECT
	JRST PGRTH		;PAGE TABLE PARITY
	JRST ILWR		;UNUSED
	JRST ILSCN		;ILLEGAL SECTION

PGRTH:	MOVE T1,TRAPSW
	JSP T2,PFAID		;HANDLE HARD PAGE FAIL
PGRTH1:	DMOVE T1,TRAPFL		;GET FLAGS AND PC (IN CASE MODIFIED)
	EXCH T1,T2
	DMOVEM T1,-1(P)		;AND MAKE IT THE ONES WE WILL USE
	JRST PGUNTP		;RETRY

UBPGF::	SKIPN SMFLAG		;CHECK FOR KS10
	JRST PGUNTP		;NOT A KS10 IGNORE IT
	MOVE T1,TRAPFL		;FIND TRAP WORD
	TLNE T1,(UMODF)		;CHECK TO SEE IF USER MODE
	JRST ILWR		;YES -- ILLEGAL WRITE ERROR
	BUG(HLT,UBANXM,<I/O NMX FROM UNIBUS DEVICE>,<UPTPFW,UPTPFO>)

;MEMORY DATA PARITY - DETECTED IN AR/ARX

PGMPE:	CALL PGMPE0		;HANDLE IN APRSRV
	 SKIPA			;NOT RECOVERABLE
	JRST PGRTH1		;RETRY. GET NEW PC AND FLAGS FIRST
	MOVEI T1,ILLX03		;PARITY ERROR
	MOVEM T1,LSTERR
	MOVX T1,.ICDAE		;INITIATE PSI ON DATA ERROR CHANNEL
	JRST ILRF		;HANDLE AS ILLEG REFERENCE

ADRCMP:	SKIPE INSKED		;WEED OUT BUGS
	BUG(HLT,ABKSKD,<ADDRESS BREAK FROM SCHEDULER CONTEXT>)
	MOVX T1,PC%AFI		;SET ADDRESS BREAK INHIBIT
	IORM T1,0(P)		; SO FORK CAN CONTINUE AFTER SUSPENSION
	MOVE T2,TRAPPC		;GET ADDR OF FAULTING INSTR
	MOVEM T2,ADRBK1		;SAVE FOR THE EXEC
	MOVSI T1,400000+ADRBKF	;FLAG REQUEST FOR SCHEDULER
	IORM T1,FKINT(FX)	; ..
	MOVE T2,FORKX		;THIS FORK
	CALL PSIR4		;GET IT SEEN
	CHKINT			;MAKE IT HAPPEN
	JRST PGUNTP

   REPEAT 0,<
;BAD NSKED OR INTDF - FIX BEFORE PROCEEDING

PGRT4:	BUG(CHK,NSKDT2,<PGRTRP-BAD NSKED OR INTDF>)
	JRST -2(T1)		;REDO AOS UNTIL IT WORKS
   >				;END OF REPEAT 0

ILIND:	MOVE T1,TRAPSW		;FIND TRAP REASON
	JXN T1,TWUSR,ILRD		;DECLARE ILLEGAL READ
	BUG(HLT,ILLIND,<ILLEGAL INDIRECT>)

ILSCN:	MOVE T1,TRAPSW
	JXN T1,TWUSR,ILRD		;ILLEGAL READ IF USER MODE
	BUG(HLT,SECG37,<ILSCN-SECTION NUMBER GREATER THAN 37>)
	JRST PGUNTP		;AND RETRY
;RESUME PROCESS AFTER PAGER TRAP

PGUNTP:	SKIPE TRAPC		;OUTER LEVEL TRAP?
	JRST PGU4		;NO
	SKIPE IPTIM		;INCLUDE PAGE TRAP TIME?
	JRST [	CALL GETHRT	;YES, READ CURRENT TIME
		SUB T1,-2(P)	;COMPUTE DIFFERENCE
		JRST PGU5]
	CALL FRTON		;TURN CLOCK ON, GET TIME OFF
PGU5:	ADDM T1,PTTIM		;ACCUMULATE FORK TIME
	ADDB T1,HSPTTM		;ACCUMULATE SYSTEM TIME
	IDIVI T1,NTMS		;CONVERT UNITS
	MOVEM T1,SPTTIM		;MAINTAIN 1 MS UNITS
PGU4:	POP P,T3		;flags and pc
	POP P,T4
	SKIPN TRAPC		;top level trap?
	POP P,T1		;yes, flush runtime
	TLNN 3,(UMODF)		;TO USER?
	JRST PGU3		;NO, MONITOR
	DMOVEM 3,FFL		;USER, CAN PUT RETURN IN FFL
	SETOM TRAPC
	SOSG NSKED		;DO OKSKED
	XCT RSKED
	SETOM INTDF		;FOR USER, MUST BE -1
	JRST GOUSR		;RETURN TO USER

PGU3:	DMOVEM 3,TRAPFL
	POP P,TRAPSW
	POP P,CX		;RESTORE AC'S
	POP P,7
	DMOVE 3,-1(P)
	DMOVE 1,-3(P)
	SUB P,BHC+4		;CLEAN UP THE STACK
	SOSGE TRAPC		;UNDOING TOP LEVEL TRAP?
	MOVE P,TRAPAP		;YES, RESTORE P ALSO
	SOSG NSKED		;DO OKSKED
	XCT RSKED
	SOS INTDF
	OKINT
	XJRSTF TRAPFL
;DETERMINE CAUSE OF TRAP AND GET TRAP INFORMATION.  START FROM
;VIRTUAL ADDRESS IN TRAPSW.
;	CALL GETTPD
; RETURNS +1 ALWAYS, 
;	TRPID/ IDENT OF PAGE CAUSING TRAP
;	TRPPTR/ POINTER BITS AND/OR STORAGE ADDRESS

GETTPD:	MOVE T2,TRAPSW		;START WITH TRAP ADDRESS
	LOAD T1,TWVADR,T2
	TXNE T2,TWUSR		;USER?
	JRST [	TXO T1,1B0		;YES
		CALL FPTA	;GET I.D. OF PAGE
		JUMPE T1,GETT1G	;NON-EX SECTION. ILLEGAL
		JRST GETTP1]	;GOT IT.
	CALL FPTA		;GET IDENT OF FIRST POINTER
	JUMPE T1,GETTPX		;HAVE AN IDENTIFIER?
GETTP1:	HLRZ T2,T1		;GET PT IDENT
	CALL CHKDMO		;SEE IF THIS IS A DISMOUNTED OFN
	 JRST GETT1F		;IT IS
	MOVEM T2,TRPID		;SAVE IT UNTIL VERIFIED
	LOAD T2,STGADR,SPT(T2)	;GET ADR OF PT
	MOVEM T2,TRPPTR		;SAVE IT
	TXNE T2,NCORTM		;IN CORE?
	JRST GETT1A		;NO
	HLL T2,CST0(T2)		;CHECK AGE
	TXNN T2,PSASM		;ASSIGNED?
	JRST GETT1B		;NO
	MOVEM T1,TRPID		;PT OK, SAVE PAGE IDENT
	HRRZS T1
	CALL MOVRCA		;FETCH POINTER
	MOVEM T1,TRPPTR		;SAVE IT
	JUMPE T1,GETT1C		;JUMP IF NULL POINTER
	MOVE T2,TRAPSW		;CHECK ACCESS AGAINST REFERENCE
	TXNE T2,TWWRT		;WRITE REFERENCE?
	JRST [	TXNE T1,PTCPY	;YES, COPY?
		JRST GETT1D	;YES
		TXNN T1,PTWR	;WRITE LEGAL?
		JRST GETT1E	;NO
		JRST .+1]
	LOAD T2,PTRCOD,T1	;CHECK POINTER TYPE
	CAIN T2,INDCOD		;INDIRECT?
	JRST [	LOAD T2,SPTX,T1	;YES, CONSTRUCT IDENT OF PAGE POINTED TO
		LOAD T1,IPPGN,T1
		HRL T1,T2
		JRST GETTP1]	;CONTINUE TRACE
	CAIN T2,SHRCOD		;SHARED PTR?
	JRST [	LOAD T2,SPTX,T1	;YES, GET IDENT
		MOVEM T2,TRPID	;SAVE IT
		LOAD T1,STGADR,SPT(T2) ;GET ADDRESS
		MOVEM T1,TRPPTR	;SAVE IT
		CALL CHKDMO	;SEE IF DISMOUNTED OFN
		 JRST GETT1F	;IT IS
		JRST .+1]
	TXNE T1,NCORTM		;IN CORE?
	JRST GETT1A		;NO
	HRRZS T1		;GET ADDRESS ONLY
	LOAD T2,CSTAGE,(T1)	;CHECK AGE
	CAIGE T2,PSASN
	JRST GETT1B		;NOT ASSIGNED
	MOVEI T1,PGUNTP		;PAGE OK, MAY BE REFERENCED
	RET
;PAGE OR PAGE TABLE NOT IN CORE

GETT1A:	MOVEI T1,NIC
	RET

;PAGE OR PAGE TABLE AGE .L. 100

GETT1B:	MOVEI T1,TRP0
	RET

;NULL POINTER

GETT1C:	MOVEI T1,NPG
	RET

;WRITE-COPY

GETT1D:	MOVEI T1,WCPY
	RET

;ILLEGAL WRITE

GETT1E:	MOVEI T1,ILWR
	RET

;ATTMEPT TO CREATE PAGE TABLE IN NON-ZERO SECTION

GETTPX:	BUG (HLT,SECNX,<CREATING PAGE TABLE FOR NON-0 SECTION>)

;ILLEGAL REFERENCE BECAUSE OF DISMOUNTED OFN

GETT1F:	MOVEI T1,PMAPX7		;GET CHARACTERISITIC ERROR
	MOVEM T1,LSTERR		;LET PROCESS KNOW WHY MEM FAILED
	SKIPA T1,[ILRD1]	;SKIP SETTING ERROR CODE
GETT1G:	MOVEI T1,ILRD		;GO TO TRAP PLACE
	RET			;AND DONE

;ROUTINE TO CHECK IF PAGE FAULT HAS OCCURRED ON A DISMOUNTED OFN
;ACCEPTS:	T2/ SPTN OF PAGE TABLE
;RETURNS:	+1 IF PAGE BELONGS TO A FILE ON A DISMOUNTED STRUCTURE
;		+2 IF PAGE IS OK TO FAULT ON

CHKDMO::ACVAR <Q1,Q2>		;GET SOME REGS
	HRRZ Q2,T2		;GET SPTN FOR CHECKING
	CAIL Q2,NOFN		;AN OFN?
	JRST [	HLRZ Q2,SPTH(Q2) ;NO. SEE IF PAGE BELONGS TO A FILE
		SKIPN Q2	;DOES IT?
		RETSKP		;NO. OK TO USE IT
		JRST .+1]	;YES. MUST LOOK AT IT
	MOVX Q1,OFNDMO		;GET DISMOUNTED BIT
	TDNE Q1,SPTH(Q2)	;IS THIS A DISMOUNTED OFN?
	RET			;YES. SAY SO
	RETSKP			;NO
;AGE LESS THAN 100 TRAP

TRP0::	MOVE T2,TRPPTR		;GET CORE ADR
	LOAD T1,CSTAGE,(T2)	;GET STATE CODE
	CAILE T1,TRP0BM		;WITHIN RANGE?
	JRST TRPRST		;NO. START TRAP OVER, PAGE PROBABLY
				; HAS COMPLETED WRITING
	XCT TRP0B(T1)		;DISPATCH PER PAGE STATE CODE

TRP0B:	JRST TRP0C		;ON RPLQ
	JRST BADAGE
	JRST TRP2R		;READ COMPLETED
	JRST BADAGE
	JRST TRP0C		;WRITE IN PROGRESS
	JRST BADAGE
	JRST TRP0R		;READ IN PROGRESS
	JRST BADAGE
TRP0BM==.-TRP0B-1		;MAXIMUM LEGAL VALUE

TRP0C:	MOVE T1,TRPPTR		;GET PHYSICAL PAGE
	LOAD T2,CSTPST,(T1)	;GET SPECIAL PAGE STATE
	CAIE T2,PSTAVL		;STILL AVAILABLE?
	JRST TRPSPM		;NO - ATTEMPT TO PLACE ON SPMQ
	CALL CHKRPQ		;MAKE SURE ENOUGH PAGES
	 JRST TRPRST		;RESCHEDULED, RESTART TRAP
TRP2R:	MOVE T1,TRPPTR		;GET CORE PAGE NUMBER
	LOAD T2,CSTPST,(T1)	;GET SPECIAL PAGE STATE
	CAIE T2,PSTAVL		;STILL AVAILABLE?
	JRST TRPSPM		;NO - ATTEMPT TO PLACE ON SPMQ
	CALL AGESN		;ASSIGN PAGE
	JRST PGUNTP		;UNTRAP AND CONTINUE

TRP0R:	MOVSI T1,0(T2)
	HRRI T1,SWPRT
	RDISMS			;WAIT FOR PAGE
	NOSKED
	JRST TRPRST		;RECHECK TRAP

TRAPSP:	IOWD NTSK,TRAPSK	;POINTER TO LOCAL STACK

BADAGE:	BUG(HLT,ILAGE,<BAD AGE FIELD IN CST0>)

;HERE WHEN PAGE FAULTED ON WANTS TO BE REMOVED FROM AVAILABLE POOL

TRPSPM:	LOAD T2,CSTAGE,(T1)	;GET AGE
	CAIN T2,PSWIP		;WRITE IN PROGRESS?
	JRST TRPSP2		;YES - WAIT FOR COMPLETION
TRPSP1:	CALL RPCST		;NO - RPLQ OR READ DONE, REMOVE FROM CST
	PIOFF
	CALL ONSPMQ		;PLACE ON SPMQ
	JRST PGUNTP		;TRY REFERENCE AGAIN

TRPSP2:	CALL SKPNWR		;STILL BEING WRITTEN?
	  JRST TRPRST		;RESCHEDULED - RESTART TRAP
	JRST TRPSP1		;NO - FREE PAGE NOW
;ASSIGN PAGE AND SET AGE

AGESET:	PUSH P,FX
	MOVE FX,FORKX
	CALL AGESN
	POP P,FX
	RET

AGESN::	PUSH P,2
	MOVEI 2,0(1)
AGES1:	LOAD 1,CSTAGE,(2)	;GET AGE CODE
	CAIL 1,PSASN		;NOW ASSIGNED?
	JRST [	LOAD 1,CSTOFK,(2) ;YES, FIND OUT WHERE
		CAML 2,MONCOR	;NOT SWAPPABLE PAGE? OR
		CAIN 1,0(7)	;THIS PROCESS?
		JRST AGES2	;YES, OK
		CAIL 1,NFKS	;ANY PROCESS?
		JRST ATP1	;NO
		PUSH P,2
		MOVEI 2,0(1)
		CALL SOSWSP	;REDUCE WSP
		POP P,2
		JRST ATP1]	;GO ASSIGN TO THIS PROCESS
AGESX:	CAILE 1,TRP0TM		;WITHIN TABLE RANGE?
	JRST BADAGE		;NO - BOMB
	XCT TRP0T(1)
AGES2:	MOVEI 1,0(2)
	POP P,2
	RET

TRP0T:	JRST ATP0		;AVAILABLE AND ON REPLACABLE QUEUE
	JRST BADAGE
	JRST ATP1R		;READ COMPLETED
	JRST BADAGE
	JRST ATP4		;WRITE IN PROGRESS
	JRST BADAGE
	JRST ATP2		;READ IN PROGRESS
	JRST BADAGE
TRP0TM==.-TRP0T-1		;MAXIMUM LEGAL ENTRY

ATP1R:	MOVSI 1,(SWPERR)	;CHECK FOR ERROR ON READ
	TDNN 1,CST3(2)
	JRST ATP1		;NO ERROR
	PUSH P,2
	MOVEI T1,IOX5		;STORE ERROR CODE
	MOVEM T1,LSTERR
	MOVX 1,.ICDAE		;FILE DATA ERROR PSI CHANNEL
	MOVEI 2,0(7)		;GET FORK NUMBER
	CALL PSIRQ		;INTERRUPT THE FORK
	CHKINT			;GET IT SEEN
	POP P,2
	JRST ATP1

ATP2:	MOVSI 1,0(2)
	HRRI 1,SWPRT		;READ NOW IN PROGRESS OR COMPLETED
	PDISMS			;RESCHEDULE UNTIL AVAILABLE
	JRST AGES1		;CHECK AGE AGAIN
ATP4:	PIOFF
	LOAD 1,CSTAGE,(2)	;GET CURRENT STATE OF PAGE
	CAIE 1,PSWIP		;WRITE IN PROGRESS?
	JRST [	PION		;NO, GO LOOK AT STATE AGAIN
		JRST AGES1]
	SETZRO <CSTAGE,CFXRD>,(2) ;INHIBIT COMPLETION ACTION
	PION
	SOS IOIP
	JRST ATP1

ATP0:	SOS NRPLQ		;ONE LESS PAGE ON REPLACABLE
	PUSH P,3
	PIOFF
	MOVE 1,CST3(2)		;UNQUEUE PAGE FROM REPLACABLE
	HRRZ 3,1
	HLLM 1,0(3)
	HLRZ 3,1
	HRRM 1,0(3)
	PION
	POP P,3
	SETZM CST3(2)
ATP1:	AOS 1,FKWSP(7)		;INCREASE OWNERSHIP COUNT
	MOVEI 1,0(1)
	PUSH P,1
	LOAD 1,FKWSS		;GET CURRENT RESERVE
	CAML 1,0(P)		;LESS THAN CURRENT SIZE?
	JRST ATP1A		;NO, OK
	SUB 1,0(P)		;YES, CALCULATE DIFFERENCE
	MOVN 1,1
	ADDM 1,FKNR(7)		;INCREASE RESERVE
	ADDM 1,SUMNR
	LOAD 1,FKLOC
	CAIL 1,NBP		;FORK IN BALSET?
	BUG(CHK,FRKBAL,<AGESET-FORK NOT IN BALSET>)
ATP1A:	SUB P,BHC+1		;FLUSH GARBAGE
	HLRZ 1,FKNR(7)		;GET UPDATED AGE
	STOR 1,CSTAGE,(2)	;SET NEW AGE
	STOR 7,CSTOFK,(2)	;SET OWNERSHIP
	SETZRO PUFLD,CST0(2)	;CLEAR PUB FIELD
	MOVX T1,DSKSWB		;CLEAR MISC FLAGS
	ANDCAM T1,CST3(T2)
	JRST AGES2
;ILLEGAL REFERENCE TRAPS

ILRD::	MOVEI T1,ILLX01		;SET ERROR CODE
	MOVEM T1,LSTERR
ILRD1:	MOVX 1,.ICIRD		;MR TRAP CHANNEL
ILRF:	MOVE 2,TRAPSW		;SET UP FOR USER IN CASE
	MOVEM 2,UTRSW		; HE WANTS TRAP STATUS
	DMOVE 2,-1(P)		;GET FLAGS
	AOS 2			;INCREMENT TO NEXT INSTR
	TLNE 3,(UMODF)		;USER OR KERNEL
	JRST ILRFU		;USER MODE TRAP
	HLLZ 4,0(2)		;GET INSTRUCTION AFTER TRAP
	CAMN 4,[ERJMP]		;WANT JUMP SIMULATION?
	JRST ILRF1		;YES - EASY CASE
	CAME 4,[ERCAL]		;PUSHJ?
	JRST ILRFX		;NO - POST INTERUPT IN 1
	MOVE 4,BHC+1		;SIMULATE PUSHJ
	ADDB 4,TRAPAP		;UPDATE PDL PNTR
	TLNN 4,-1		;CHECK OVERFLOW
	BUG (HLT,ILRFPD,<PDL-OV IN ILLEGAL PAGE REFERENCE>)
	MOVEM 2,0(4)		;SAVE RETURN PC ON STACK
	AOS 0(4)		;ADJUST AFTER ERCAL
ILRF1:	MOVE 4,0(2)		;GET ADDRS TO XFER TO
	HRRM 4,-1(P)		;ALTER RETURN ADDRESS (CAN'T CROSS SEC BOUND HERE!)
	JRST PGUNTP		;EXIT TRAP

ILRFU:	PUSH P,1		;SAVE INTERUPT CHL CODE
	MOVE T1,-1(P)		;GET PC FLAGS.
	CALL ITRSIM		;CHECK FOR ERJMP/ERCAL (PC IN 2)
	 JRST [	POP P,1		;NONE - POST INTERUPT
		JRST ILRFX]
	SUB P,BHC+1		;PRUNE PDL
	HRRM 3,-1(P)		;ALTER RETURN ADDRESS (CAN'T CROSS SECTION BOUND HERE!)
	JRST PGUNTP		;EXIT TRAP

ILRFX:	CALL PSIRQ0		;REQUEST INTERRUPT, THIS FORK
	CHKINT			;GET IT SEEN
	MOVE 2,0(P)		;FLAGS
	TLNN 2,(UMODF)		;USER?
	SKIPGE INTDF		;OR INTERRUPTABLE?
	JRST PGUNTP		;YES
	AOS -1(P)		;NO, SKIP OVER INSTRUCTION CAUSING TRAP
	JRST PGUNTP

ILWR::	MOVE 1,TRAPSW
	JXN T1,TWUSR,ILWR1	;JUMP IF NOT MONITOR REFERENCE
	XMOVEI 1,0(1)
	TLNE 1,-1		;EXTENDED ADDRESS?
	JRST ILWR1		;YES -- DIRECTORY
	CAIGE 1,<PPRMPG>B26	;TO RESIDENT MON?
	JRST ILWR2		;YES
	CAIL 1,SWPMA		;TO SWAPPABLE MON?
	CAIL 1,NRPLBG
	JRST ILWR1		;NO
ILWR2:	BUG(HLT,ILWRT2,<ATTEMPTED WRITE REF TO PROTECTED MONITOR>)

ILWR1:	MOVEI T1,ILLX02		;SET ERROR CODE
	MOVEM T1,LSTERR
	MOVX 1,.ICIWR		;MW INTERRUPT CHANNEL
	JRST ILRF
;PAGE NOT IN EXISTANCE TRAPS

NPG::	MOVE 1,TRAPSW
	HLLZ 2,1		;CHECK FOR SECTION
	TXZ 2,EXFLBT		;ZERO FLAGS JUNK
	JXN T1,TWUSR,NPG1	;ALWAYS HONOR USER REQUEST
	JUMPE T2,[HRRZ 1,1	;IF MONITOR SECTION 0
		CAIL 1,PSSPSA
		CAIL 1,PSSPEA
		JRST NPG1	;YES
		JRST MILRF1]	;MONITOR MALFUNCTION
	CAMLE 2,[MAXSEC,,0]	;CHECK FOR ILLEGAL SECTION
	JRST MILRF1		;YES -- ERROR
NPG1:	MOVE T1,TRPID		;GET PAGE IDENT
	HLRZ 2,1		;GET PT NUMBER
	CAIL 2,NOFN		;OFN OR PT?
	JRST [	MOVE T3,DRMFRE	;PT, SEE IF ENOUGH DRUM SPACE
		CAML T3,DRMLV0	;ABOVE MINIMUM?
		JRST .+1	;YES. ALLOW CREATE THEN
		MOVE T3,TRAPFL	;NO. GET FLAGS OF TRAP
		TXNE T3,UMODF	;MONITOR PC?
		JRST NIC6E	;NO, BOMB OUT
		MOVE T3,INTDF	;YES. SEE IF NOW NOINT
		SOJLE T3,NIC6E	;NOT. ERROR THEN
		JRST .+1]	;IT IS. ALLOW CREATE
	CALL SETSPG		;MAP IT
	SKIPE CSWPGA(1)		;BE SURE PT SLOT NOW EMPTY
	JRST NPGBAD		;IT'S NOT, PROBABLY SPURIOUS TRAP
	MOVE 2,IMMPTR
	TXO 2,UAAB
	MOVEM 2,CSWPGA(1)	;SETUP NULL POINTER
	CALL RELSPG		;RELEASE MAP
	MOVE 1,PSICHM
	MOVE 2,TRAPSW
	JXE T2,TWUSR,NIC	;JUMP IF NOT USER REFERENCE
	TXNN 1,1B<.ICNXP>	;USER MAP AND NON-X PAGE CHANNEL ON?
	JRST NIC		;NO
	MOVEI T1,ILLX04		;SET ERROR CODE
	MOVEM T1,LSTERR
	MOVX 1,.ICNXP		;YES, REQUEST INTERRUPT
	CALL PSIRQ0
	CHKINT
	MOVE 1,TRAPSW
	MOVEM 1,UTRSW
	JRST NIC

MILRF1:	BUG(HLT,ILMADR,<ILLEGAL ADDRESS REFERENCE IN MONITOR>)

NPGBAD:	BUG(HLT,ILPPT3,<BAD POINTER IN PAGE TABLE>)
;COPY-ON-WRITE TRAP

WCPY::	PUSH P,TRPID		;SAVE ORIGIANL IDENT
	MOVX T4,TWWRT
	ANDCAM T4,TRAPSW	;CLEAR WRITE REF
	CALL GETTPD		;SEE IF PAGE READABLE
	CAIE T1,PGUNTP		;PAGE READY FOR COPYING?
	JRST [	POP P,0(P)	;CLEAN UP STACK
		JRST 0(T1)]	;AND GO HANDLE OTHER CAUSE
	MOVE T1,TRPPTR		;GET ADDRESS OF SOURCE PAGE
	MOVSI 3,(PLKV)		;NOW LOCK IT IN CORE
	ADDM 3,CST1(1)
	EXCH T1,0(P)		;SAVE CORE PAGE NUMBER, RESTORE IDENT
	HLRZ 2,1		;PTN
	CAIG 2,NOFN
	BUG(HLT,IBCPYW,<COPY-WRITE POINTER IN INDEX BLOCK>)
	CALL SETSPG		;MAP THE PT
	MOVX 2,PTPUB		;SELECT ACCESS BITS
	AND 2,CSWPGA(1)		;GET ACCESS OF SOURCE PAGE
	IOR 2,IMMPTR		;MAKE PRIVATE PTR
	TXO 2,UAACB		;WITH 'COPY' ADDRESS
	EXCH 2,CSWPGA(1)	;EXCH IT WITH THE WC POINTER
	LOAD 3,PTRCOD,2		;CHECK PTR TYPE
	CAIN 3,IMMCOD		;PRIVATE?
	JRST WCPY4		;NO, USER PROBABLY CONFUSED
	MOVEM 2,PSBM0+CPYPG	;PUT THE ORIG POINTER IN MON MAP
	CALL RELSPG
	SKIP CPYPGA		;REF SOURCE PAGE TO ENSURE ACCESS
	CALL SWPINP		;THIS WILL COPY FROM CPYPG TO A NEW PAGE
	POP P,1
	MOVSI 3,(-PLKV)
	ADDM 3,CST1(1)		;UNLOCK THE SOURCE PAGE
	MOVEI 1,PSBM0-PSBPGA+CPYPG
	HRL 1,FKPGS(7)
	CALL MRPT		;GET IDENT OF SHARE PAGE BEING RELEASED
	SETZ 1,			;INDIRECT TO FORK
	PUSH P,1
	MOVEI 1,PSBM0-PSBPGA+CPYPG
	HRL 1,FKPGS(7)
	CALL RELMPG		;RELEASE THE ORIG PAGE FROM MON MAP
	CALL RELCPT		;CLEANUP FROM RELMPG
	OKSKED
	POP P,1
	JUMPE 1,WCPY3		;IGNORE INDIRECT TO FORK PTR
	CALL JFNDCR		;DECREMENT MAP COUNT FOR JFN
WCPY3:	NOSKED
	JRST NIC		;UPDATE STATS AND CONTINUE

WCPY4:	TLZ 2,(PTCPY)		;MAKE IT LOOK LIKE WE COPIED IT
	TLO 2,(PTWR)
	MOVEM 2,CSWPGA(1)
	CALL RELSPG
	POP P,1
	MOVSI 3,(-PLKV)
	ADDM 3,CST1(1)		;UNLOCK THE SOURCE PAGE
	JRST NIC
;NOT IN CORE TRAP

NIC::
NIC2:	CALL GETTPD		;UPDATE TRAP INFO
	CAIE T1,NIC		;NOT IN CORE?
	JRST 0(T1)		;NO, HANDLE OTHER CAUSE
	MOVE T1,TRPID		;GET IDENT
	MOVE T2,TRPPTR		;GET ADDRESS
NIC6:	TLNN 2,(DSKAB+DRMAB)	;UNASSIGNED ADR?
	JRST NIC6A		;YES
NIC6B:	CALL CHKRPQ		;CHECK FOR ENOUGH PAGES FREE
	 JRST NIC2		;WASN'T, HAD TO RESKED
NIC8:	CALL SWPINW		;SWAP IN THE PAGE
	JRST NIC2
;HERE IF PAGE HAS UNASSIGNED ADDRESS

NIC6A:	HLRZ 2,1		;GET PT
	SKIPN 2			;FROM SPT?
	JRST [	CAMN 1,BTBBAS	;IS THIS THE BIT TABLE?
		BUG (HLT,BADBTB,<NIC- ILLEGAL REFERENCE TO BIT TABLE>)
		HLRZ 2,SPTH(1)	;NO. GET PT
		JRST .+1]	;AND PROCEED
	CAIE 2,0		;OFN OR PT?
	CAIL 2,NOFN
	JRST NIC6B		;PT, DON'T ASSIGN ADDRESS
	PUSH P,1		;SAVE ORIGINAL IDENT
	MOVX 1,TWWRT		;GET WRITE BIT
	TDNE 1,TRAPSW		;ORIGINAL REQUEST WAS WRITE?
	JRST NIC62		;YES, ACCESS ALREADY CHECKED
	IORM 1,TRAPSW		;MUST SEE IF WRITE ACCESS POSSIBLE
	CALL GETTPD		;RECOMPUTE AS IF WRITE ACCESS
	MOVX 2,TWWRT		;GET WRITE BIT AGAIN
	ANDCAM 2,TRAPSW		;RESTORE
	CAIE T1,ILWR		;WRITE PROBLEM?
	CAIN T1,WCPY
	JRST [	POP P,1		;CLEAN UP STACK
		JRST ILRD]	;AND GIVE ERROR
NIC62:	HLRZ 2,0(P)		;GET PTN
	JUMPE 2,NIC64		;JUMP IF NONE
	LOAD 1,STGADR,SPT(2)	;GET CORE ADR
	MOVX 2,PLKV		;LOCK IT IN CORE IN CASE RESKEDS BELOW
	ADDM 2,CST1(1)
NIC64:	HLRZ 1,0(P)		;GET OFN OF IDENT
	MOVE 2,0(P)		;GET IDENT
	SKIPN 1			;HAVE ONE?
	HLRZ 1,SPTH(2)		;NO, GET IT FROM SPTH
	PUSH P,1		;SAVE OFN
	CALL QCHK		;CHECK DISK, ETC...
	 JRST NIC6F		;CAN'T CREATE PAGE
	MOVE 1,0(P)		;GET OFN BACK
	MOVX 2,SPTLKB		;LOCK OFN
	TDNE 2,SPTH(1)
	JRST [	HRLZ 1,1	;ALREADY LOCKED. BLOCK UNTIL UNLOCKED
		CALL WTOFNL	;OKSKED AND DISMISS
		NOSKED
		POP P,1		;CLEAN OFF OFN
		POP P,1		;RECOVER IDENT
		CALL NIC6UC	;UNLOCK PT PAGE IF ANY
		JRST NIC2]	;START OVER
	TXO 2,OFNWRB		;NOTE OFN CHANGED
	IORM 2,SPTH(1)		;SET LOCK AND OFN MODIFIED
	MOVE T1,-1(P)		;GET IDENT
	TLNN T1,-1		;IN SPT?
	MOVE T1,SPTH(T1)	;YES, GET REAL IDENT
	CALL FNDLDA		;FIND LAST DISK ADDRESS ASSIGNED IN THIS XB
	MOVE T2,0(P)		;GET OFN
	LOAD T2,STRX,(T2)	;PASS STRUCTURE NUMBER TO DSKASN
	CALL DSKASN		;ASSIGN DISK ADDRESS FOR FILE PAGE
	 JRST NIC6D		;RAN OUT
	; ..
;ASSIGNING ADDRESS FOR NEW FILE PAGE...

	POP P,T2		;GET OFN
	LOAD T2,ALOCX,(T2)	;INDEX TO QUOTA TABLE
	DECR PGLFT,(T2)		;ONE LESS PAGE LEFT
	TLO 1,(DSKNB)		;INDICATE PAGE NEVER PREVIOUSLY WRITTEN
	MOVE 2,1
	POP P,1
	TLNN 1,-1		;IN SPT?
	JRST [	STOR 2,STGADR,SPT(1) ;YES, STORE NEW ADDRESS
		JRST NIC63]	;NOW GO SWAP IN PAGE
	PUSH P,6		;SAVE PERMANENT REGISTER
	HLRZ 6,1
	CALL SETSP6		;MAP XB
	STOR 2,STGADR,CSWPGA(1)	;STORE NEW ADDRESS IN XB
	MOVSI 2,(-PLKV)
	ADDM 2,CST1(6)		;UNDO LOCK ABOVE
	CALL RELSPG
	POP P,6			;RESTORE PERMANENT REGISTER
NIC63:	CALL NIC6UL		;UNLOCK OFN
	JRST NIC2		;START OVER, PAGE NOW ASSIGNED

;UNLOCK OFN AFTER ASSIGNMENT

NIC6UL:	HLRZ 2,1		;GET OFN
	SKIPN 2			;HAVE ONE?
	HLRZ 2,SPTH(1)		;NO, GET IT FROM SPTH
	MOVX 3,SPTLKB
	ANDCAM 3,SPTH(2)	;UNLOCK
	RET

;HERE WHEN NO ROOM CONDITION -- GENERATE INTERRUPT

NIC6D:	POP P,1			;RESTORE OFN
	MOVX 2,SPTLKB		;UNDO SPT LOCK
	ANDCAM 2,SPTH(1)	;...
	JRST NIC6G		;JOIN COMMON ERROR STUFF

NIC6F:	SUB P,BHC+1		;REMOVE OFN
NIC6G:	POP P,1			;GET ORIGINAL IDENT
	TLNN 1,-1		;OFN?
	JRST NIC6Y		;NO - JUST EXIT
	PUSH P,6		;SAVE PERM REG
	HLRZ 6,1		;OFN TO REG 6
	CALL SETSP6		;MAP THE PT
	SETZM CSWPGA(1)		;CLEAR POINTER (NO DSK ADDRS YET)
	MOVX 2,-PLKV		;UNDO PT LOCK
	ADDM 2,CST1(6)		;...
	CALL RELSPG		;RELEASE SPECIAL PAGE
	POP P,6			;RESTORE 6
NIC6Y:	MOVX 1,.ICQTA		;QUOTA EXCEDED CHL
NIC6X:	MOVEI 2,IOX11		;'NO ROOM'
	MOVEM 2,LSTERR
	JRST ILRF		;GENERATE ILLEG REF INT

NIC6E:	MOVX 1,.ICMSE		;MACH SIZE EXCEEDED INT CHANNEL
	MOVEI 2,IOX12		;DISC COMPLETELY FULL
	MOVEM 2,LSTERR
	JRST ILRF		;GENERATE INT

;UNLOCK PT PAGE IF ANY

NIC6UC:	HLRZ 2,1		;GET PTN
	JUMPE 2,R		;RETURN IMMED IF NONE
	LOAD 2,STGADR,SPT(2)	;GET ADR OF PT
	MOVX 3,-PLKV
	ADDM 3,CST1(2)		;UNLOCK IT
	RET
;FIND LAST DISK ADDRESS ASSIGNED IN THIS XB SO THAT DSKASN CAN ASSIGN
;THE NEXT PAGE AT AN OPTIMAL LOCATION
; T1/ IDENT

FNDLDA:	SAVEAC <Q2>
	HLRZ Q2,T1		;SETUP OFN
	JN NCORTM,SPT(Q2),FNDLDX ;IF NOT IN CORE, USE XBADDR
	CALL SETSP6		;MAP IT
FNDLD1:	HRRZ T2,T1		;GET PAGE NUMBER
	SKIPN T2,CSWPGA(T2)	;ANYTHING IN THIS SLOT?
	JRST FNDLD2		;NO
	LOAD T3,PTRCOD,T2	;YES, CHECK PTR TYPE
	CAIN T3,IMMCOD		;IMMEDIATE AND DISK ADDRESS?
	TXNN T2,DSKAB
	JRST FNDLD2		;NO, FORGET IT
	LOAD T1,STGADR,T2	;YES, USE THIS ADDRESS
	JRST FNDLD3

FNDLD2:	HRRI T1,-1(T1)		;SCAN BACKWARDS THROUGH XB
	TRNN T1,-PGSIZ		;RAN OFF TOP?
	JRST FNDLD1		;NO, CHECK THIS SLOT
FNDLDX:	HLRZ T1,T1		;YES, REVERT TO XB ADR ITSELF
	LOAD T1,STGADR,SPTH(T1) ;GET XB DISK ADR
FNDLD3:	CALL RELSPG		;RELEASE XB MAPPING
	RET

;ROUTINE TO CHECK ON DISK QUOTA AND DISK AVAILABILITY
;C(T1) := OFN
;
;RETURN +1	DISK FULL / QUOTA EXCEEDED
;RETURN +2	OK

QCHK:	SKIPN USRSPC		;USER SPACE CHECKING?
	JRST QCHK1		;NO - CHECK SYSTEM SPACE
	LOAD T2,ALOCX,(T1)	;GET INDEX INTO QUOTA TABLES
	SKIPN T2		;GOOD THING TO CHECK
	BUG (HLT,NULQTA,QCHK - NO QUOTA INFO SETUP)
	OPSTR <SKIPG>,PGLFT,(T2)
	JRST QCHK2		;OVER QUOTA - CHECK PRIVS
QCHK1:
   REPEAT 0,<
	LOAD T1,STRX,(T1)	;GET STRUCTURE NUMBER
	CAIE T1,PSNUM		;IS THIS ON PS?
	RETSKP			;NO. DON'T CHECK SPACE THEN
	CALL GSTRPG		;GET ALLOCATION OF THIS STRUCTURE IN T2
	CAMLE T2,SYSSPC		;ABOVE MINIMUM?
   >				;END OF REPEAT 0
	RETSKP			;OK - GOOD RETURN
QCHK2:	MOVE T2,CAPENB		;SEE IF USER IS WHEEL/OPR
	TXNN T2,SC%WHL!SC%OPR
	RET			;NO - ERROR
	RETSKP			;YES - OK TO CREATE PAGE
;ACCOUNT FOR ONE PAGE TRAP

PGTACC:
   REPEAT 0,<
	MOVE 1,IFAV		;UPDATE INTERFAULT AV
	FMPR 1,IFAVC0		;AV' = (C*AV + TIME)/(C+1)
	MOVE T2,FKRT		;GET CURRENT FORK RUNTIME
	SUBM T2,IFTIM		;COMPUTE INTERVAL SINCE LAST FAULT
	EXCH T2,IFTIM
	FLTR 2,2		;FLOAT IT
	FADR 1,2
	FDVR 1,IFAVC1
	MOVEM 1,IFAV
   >				;END REPEAT 0
	MOVE 2,JOBNO
	HRRZ 2,JOBNAM(2)	;GET SUBSYSTEM INDEX
	AOS SPFLTS(2)		;ACCOUNT PAGE FAULTS FOR SUBSYSTEM
	LOAD 1,FKXAGE		;GET AGE CLOCK AT LAST XGC
	LOAD 2,FKAGE		;GET CURRENT AGE
	SUBI 2,0(1)		;NOW-THEN
	CAIGE 2,0		;WRAPAROUND?
	ADDI 2,1000-100		;YES
	SKIPG TRAPC		;OUTER LEVEL?
	CAMGE 2,GCRATE		;TIME FOR ANOTHER XGC?
	JRST NICMG1		;NO
NICMG:
   REPEAT 0,<
	MOVE 1,IFAV		;CURRENT INTERFAULT AVERAGE
	FDVR 1,IFAMEA		;COMPUTE RATIO OF ACTUAL/DESIRED
	MOVE 2,CAPT		;CURRENT WINDOW SIZE
	MOVE 3,2
	ASH 3,-4		;ADJUST UP OR DOWN BY 1/16
	CAMGE 1,[0.5]		;IFAV NOW TOO LOW?
	ADD 2,3			;YES, MAKE CAPT LARGER
	CAML 1,[1.5]		;IFAV NOW TOO HIGH?
	SUB 2,3			;YES, MAKE CAPT SMALLER
	CAMLE 2,CAPTMX		;SEE IF CAPT WITHIN LIMITS
	MOVE 2,CAPTMX
	CAMGE 2,CAPTMN
	MOVE 2,CAPTMN
	MOVEM 2,CAPT
	MOVE 1,CAPT		;USE CURRENT CAPT
   >
   REPEAT 1,<
	MOVE T1,ICAPT		;USE FIXED WINDOW SIZE
	MOVEM T1,CAPT
   >
	CALL XGC
	LOAD T1,FKCSIZ		;SEE IF WS ESTIMATE SHOULD BE REDUCED
	ADDI T1,4		;CURRENT SIZE PLUS SMALL INCREMENT
	LOAD T2,FKWSS		;CURRENT ESTIMATE
	CAML T1,T2		;SIZE LESS THAN ESTIMATE?
	JRST NICMG1		;NO, NO CHANGE
	SUB T1,T2		;YES, COMPUTE (NEG) DIFFERENCE
	ADDM T1,SUMNR		;REDUCE NR AND SUMNR ACCORDINGLY
	ADDM T1,FKNR(FX)
NICMG1:	CALL NICCKS		;CHECK FOR ALLOWABLE SIZE
	MOVE 3,TRAPSW
	JXN 3,TWUSR,[LOAD 3,VPGNO,3 ;USER REF, GET PAGE NUMBER, UPDATE WS BITS
		CAIL 3,1000	;IF NOT SECTION 0 MUST RETURN
		RET
		IDIVI 3,^D36
		MOVE 4,BITS(4)
		IORM 4,WSPGS(3)
		JRST .+1]
	RET

;AVERAGE SWAP LATENCY * 2 - CONTROLS DESIRED INTERFAULT AVERAGE

IFAMEA:	40.0			;IDEAL IFAV

AGTICK==:^D40			;MILLISECONDS PER TICK OF AGE REGISTER
ICAPT::	^D3000/AGTICK		;WINDOW SIZE IN TICKS
;CAPTMX:	^D4000/AGTICK		;MAX CAPT
;CAPTMN:	^D2000/AGTICK		;MIN CAPT
GCRATE:	^D2000/AGTICK		;RECIPROCAL OF GC FREQUENCY

;DECAY CONSTANT FOR INTERFAULT AVERAGE

IFAVC0:	EXP 100.0		;LARGER C IMPLIES SLOWER IFAV CHANGE
IFAVC1:	EXP 101.0		;IFAVC0+1
;CHECK FOR SUFFICIENT PAGES ON RPLQ

CHKRPQ:	MOVE 2,NSKED
	CAILE 2,1		;NOSKED PROCESS?
	JRST RSKP		;YES, ALLOW PAGE
	MOVE 2,NRPMX		;OTHERWISE, ALLOW PAGE IF NRPLQ ABOVE
	CAMG 2,NRPLQ
	JRST RSKP		;ALLOW PAGE
	MOVEI 1,TRP0CT
	HRLI 1,0(2)		;MINIMUM NRPLQ
	RDISMS			;OKSKED AND DISMISS
	NOSKED
	RET			;RETURN NOSKIP BECAUSE RESKED DONE

TRP0CT:	MOVE 2,NRPLQ
	CAIGE 2,0(1)		;ABOVE STATED MIN?
	CAML 2,NRPMIN		;OR ABOVE NORMAL MIN?
	JRST 1(4)		;YES, UNBLOCK
	AOS CGFLG		;NO, SAY PAGES NEEDED
	JRST 0(4)
;CHECK OVERALL SIZE FOR PHYSICAL CORE LIMITS

NICCKS:	LOAD 1,FKWSS
	ADD T1,BALSHC
	CAMGE 1,MAXNR		;RESERVE NOW TOO BIG?
	CAML 1,FNPMAX
	JRST NIC3C		;YES
	LOAD T3,FKCSIZ		;GET CURRENT SIZE
	CAMLE 1,3		;RESERVE .G. CURRENT SIZE?
	RET			;YES, OK.
NIC3C:	MOVE 1,CAPT		;INIT WINDOW SIZE FOR POSSIBLE XGC
	ASH 1,-3		;IS 1/8 REG CAPT
	PUSH P,1
NIC3B:	LOAD T1,FKCSIZ		;ASSUME NR IS SIZE+1
	ADDI T1,1
	ADD T1,BALSHC
	CAMGE 1,MAXNR		;EXCEEDS SYSTEM LIMIT?
	CAML 1,FNPMAX		;EXCEEDS LEGAL LIMIT?
	JRST NIC3		;YES
	CAMGE 1,SNPMAX		;DEFINITELY NOT TOO BIG?
	JRST NIC3E		;YES
	MOVE 2,IRJAV
	CAIGE 2,2		;LDAV .GE. 2?
	JRST NIC3E		;NO, LET FORK BE LARGER
NIC3:
	SKIPLE TRAPC		;DOING AN OUTER LEVEL FAULT?
	JRST NIC3E		;NO. INHIBIT XGC THEN
;	CALL GCPG		;TRY COLLECTING JUST 1 PAGE
;	JRST .+2		;FAILED, MAYBE NO USER MAP PAGES
;	JRST NIC3B
	MOVE 1,0(P)		;GET WINDOW SIZE
	CALL XGC		;DO GC
	SKIPN 1,0(P)		;WINDOW SIZE NOW 0?
	JRST NIC3E		;YES, GIVE UP ON GC
	ASH 1,-1		;REDUCE WINDOW SIZE FOR NEXT GC
	MOVEM 1,0(P)
	JRST NIC3B

NIC3E:	LOAD T1,FKCSIZ		;GET CURRENT SIZE
	ADDI T1,1		;RESET NR TO SIZE + 1
	HRRZ 3,FKNR(FX)
	SUBM 1,3
	ADDM 3,FKNR(FX)
	ADDB 3,SUMNR		;UPDATE BALSET TOTAL
	CAMG 3,MAXNR		;BALSET NOW TOO FULL?
	JRST PA1		;NO, ALL OK.
	MOVEI 1,NICTST		;YES, SETUP TEST FOR BALSET SIZE
	RDISMS			;OKSKED AND DISMISS
	NOSKED
	JRST PA1		;SHOULD BE OK NOW

NICTST:	MOVE 1,SUMNR		;SCHED TEST FOR SUMNR .LE. MAXNR
	MOVE 2,NBPROC
	CAMLE 1,MAXNR
	CAIG 2,1		;SUCCESS IF ONLY 1 FORK IN BALSET
	JRST 1(4)
	JRST 0(4)
   REPEAT 0,<			;**NOT PRESENTLY USED**
;REMOVE 1 PAGE FROM PROCESS.  SELECT FIRST PAGE OLDER THAN CAPT,
;OR OLDEST PAGE

GCPG:	MOVSI 6,-NWSPGS		;SET TO SCAN WS BIT TABLE
	PUSH P,[0]		;WILL REMEMBER OLDEST PAGE FOUND
	LOAD 3,FKAGE		;CURRENT AGE
	PUSH P,3
	SUB 3,CAPT		;CUTOFF AGE
	PUSH P,3
	MOVE 3,-1(P)		;USE CURRENT AGE AS INIT MIN AGE
GCPG2:	SKIPE 4,WSPGS(6)
GCPG3:	JFFO 4,GCPG1		;FIND PAGE IN USE
	AOBJN 6,GCPG2
	SUB P,BHC+2		;DIDN'T FIND PAGE OLDER THAN CAPT
	POP P,1			;USE OLDEST PAGE SEEN
	JUMPE 1,R		;DIDN'T FIND COLLECTABLE PAGE
	JRST GCPG4		;COLLECT IT

GCPG1:	ANDCM 4,BITS(5)
	MOVEI 1,0(6)
	IMULI 1,^D36		;COMPUTE MAP PAGE NUMBER
	ADDI 1,0(5)
	SKIPN 1,UPTPGA(1)		;GET MAP WORD
	JRST GCPG3		;IGNORE EMPTY OR INDIRECT
	LOAD 2,PTRCOD,1		;GET PTR TYPE
	CAIN 2,INDCOD		;INDIRECT?
	JRST GCPG3		;YES, IGNORE
	CAIN 2,SHRCOD		;SHARED?
	JRST [	LOAD 1,SPTX,1	;YES, TRACE
		MOVE 1,SPT(1)
		JRST .+1]
	TLNE 1,(NCORTM)		;IN CORE?
	JRST GCPG3		;NO
	LOAD 2,CSTAGE,(1)
	CAIGE 2,100		;IN USE?
	JRST GCPG3		;NO
	LOAD 5,CSTOFK,(1)	;YES, TO THIS PROCESS?
	CAIE 5,0(7)
	JRST GCPG3		;NO
	CAMLE 2,-1(P)		;CHECK WRAPAROUND
	SUBI 2,1000-100
	CAMLE 2,0(P)		;OUTSIDE CAPT WINDOW?
	JRST [	MOVE 5,2	;NO, SAVE AGE
		CAMG 2,3	;OLDEST PAGE SEEN?
		CALL SWPCHK	;SWAPPABLE?
		JRST GCPG3	;NO
		MOVE 3,5	;YES, REMEMBER OLDEST AGE
		MOVEM 1,-2(P)	;AND PAGE
		JRST GCPG3]
	CALL SWPCHK		;CAN SWAPOUT PAGE?
	JRST GCPG3		;NO
	SUB P,BHC+3		;YES, FLUSH TEMPS
GCPG4:	SOS FKWSP(7)		;DEASSIGN PAGE
	CALL SWPOUT		;SWAP IT
	AOS 0(P)		;RETURN GOOD
	RET
   >				;END REPEAT 0
;RELEASE WORKING SET JSYS

.RWSET::MCENT
	NOSKED
	MOVE 7,FORKX
	SETZ 1,			;USE 0 WINDOW SIZE
	CALL XGC		;COLLECT ALL PAGES
	HRRZ 1,FKWSP(7)		;SET NEW NR TO MAX(6,SIZE)
	CAIGE 1,6		;SIZE .GE. 6?
	MOVEI 1,6		;NO, USE 6 AS NEW NR
	LOAD 2,FKWSS
	SUBI 1,0(2)
	ADDM 1,FKNR(7)
	ADDM 1,SUMNR
	OKSKED
	JRST MRETN

;CHECK IF PAGE IS SWAPPABLE NOW

SWPCHK:	MOVE 2,CST1(1)
	TLNE 2,(-PLKV)
	RET			;PAGE IS LOCKED OR HAS NO SWAP ADR
	MOVSI 2,(DWRBIT)
	TDNN 2,CST3(1)		;BEING WRITTEN?
	AOS 0(P)		;NO, OK
	RET
;COLLECT OLD PAGES FOR THIS PROCESS, CALLED WITH CUTOFF DIFFERENCE IN 1
;THE PAGES ASSIGNED TO THIS PROCESS ARE ASSUMED TO HAVE AGES RANGING
;FROM M1 TO M2.  M2 IS THE CURRENT AGE, LH OF FKNR. WE WISH TO
;FLUSH ALL PAGES OLDER THAN M, WHERE M1<M<M2.  IF EACH PAGE     >>
;HAS BEN REFERENCED ONLY ONCE, THE AGES WOULD BE EVENLY DISTRIBUTED
;BETWEEN M1 AND M2.  HOWEVER, PAGES ACTIVELY BEING USED SHOULD
;HAVE AGES CLOSER TO M2.  THEREFORE, WE PICK A CUTOFF AGE BY
;SUBTRACTING A SMALL NUMBER FROM M2.  TO PREVENT EXCESSIVE COLLECTION
;WHERE ALL PAGES HAVE BEEN REFERENCED RECENTLY, WE SET A LIMIT
;ON THE TOTAL NUMBER OF PAGES WHICH CAN BE FLUSHED, AND STOP
;IF WE HIT THIS LIMIT. ALSO, SINCE AGES CAN WRAP AROUND THE 9-BIT
;FIELD, AGES GREATER THAN M2 ARE ASSUMED TO BE LEFT FROM THE PREVIOUS
;WRAP AROUND AND ARE ADJUSTED ACCORDINGLY.

XGC:	SKIPG NSSUN		;FILESYS INITIALIZED?
	RET			;NO, DO NOTHING
	STKVAR <PBIT,MAXP,XAGE,CAGE,SAVQ2>
	MOVEM Q2,SAVQ2		;SAVE PERMANENT REGISTER
	HRRZ 4,FKCNO(FX)
	MOVE T4,BITS(T4)	;GET PROCESS USE BIT FOR THIS PROCESS
	MOVEM T4,PBIT
	MOVE Q2,MONCOR		;FIRST SWAPPING PAGE
	HRRZ 4,FKWSP(FX)	;NUMBER PAGES NOW IN CORE
;	ASH 4,-1		;COMPUTE 1/2 CURRENT SIZE
	MOVEM T4,MAXP		;MAX NUMBER OF PAGES TO COLLECT
	LOAD 3,FKAGE		;NOTE TIME OF LAST XGC
	STOR 3,FKXAGE
	MOVEM T3,XAGE		;SAVE IT
	SUBI 3,0(1)		;CUTOFF AGE, 'OLD'=NOW-DIFFERENCE
	MOVEM T3,CAGE		;SAVE CUTOFF AGE
XGC2:	LOAD 2,CSTOFK,(Q2)	;GET PROCESS ASSIGNMENT
	CAIE 2,0(FX)		;ASSIGNED TO THIS PROCESS?
	JRST XGC1		;NO
	LOAD 1,CSTAGE,(Q2)	;GET AGE FIELD
	CAIGE 1,PSASN		;PAGE IN USE?
	JRST XGC1		;NO
	MOVE 2,PBIT		;PROCESS USE BIT
	ANDCA 2,CST0(Q2)		;LOOK AT OTHER PROCESS USE BITS
	TXNE 2,PUFLD		;IF ANY ON, MEANS REFERENCES BY OTHER
	MOVE 1,XAGE		;PROCESSE, AGE INVALID SO USE CURRENT
	CAMLE 1,XAGE		;IF .G. NOW, MUST NOT HAVE WRAPPED
	SUBI 1,1000-100		;SO WRAP IT
	CAMLE 1,CAGE		;.G. OLD?
	JRST XGC1		;YES, SAVE IT
	MOVE 2,CST1(Q2)
	TLNE 2,(-PLKV)		;DON'T SWAP PAGE IF LOCKED
	JRST XGC1
	MOVSI 2,(DWRBIT)
	TDNE 2,CST3(Q2)		;DON'T SWAP PAGE IF NOW BEING WRITTEN
	JRST XGC1
	HRRZ T1,Q2
	CALL DASWSP		;DEASSIGN PAGE FROM THIS PROCESS
	CALL SWPOUT		;SWAP IT OUT
	SOSG MAXP		;COLLECTED ENOUGH PAGES?
	JRST XGC3		;YES
	OKSKED			;DON'T HOG MACHINE FOR TOO LONG
	NOSKED
	; ..
XGC1:	CAMGE Q2,NHIPG		;STOP AFTER HIGHEST KNOWN PAGE
	AOJA Q2,XGC2		;NO, LOOK AT NEXT PAGE
XGC3:	CALL PGRCLD

	MOVEM Q1,PBIT		;SAVE A WORK REGISTER
	SETZ 3,
	MOVSI Q2,-NWSPGS	;SETUP TO UPDATE WS BITS
XGC5:	SKIPE 4,WSPGS(Q2)
XGC6:	JFFO 4,XGC4		;FOUND BIT FOR PAGE
	AOBJN Q2,XGC5
	MOVE Q1,PBIT		;RESTORE PERMANENT REGISTER
	MOVE Q2,SAVQ2		;AND THIS ONE AS WELL
	RET

XGC4:	ANDCM 4,BITS(Q1)		;DON'T FIND THAT BIT NEXT TIME
	MOVEI 1,0(Q2)		;COMPUTE PAGE NUMBER
	IMULI 1,^D36
	ADDI 1,0(Q1)
	SKIPN 1,UPTPGA(1)		;PAGE DELETED?
	JRST XGC7		;YES, FORGET IT
	LOAD 2,PTRCOD,1		;GET PTR TYPE
	CAIN 2,INDCOD		;INDIRECT?
	JRST XGC7		;YES, IGNORE
	CAIN 2,SHRCOD		;SHARED?
	JRST [	LOAD 1,SPTX,1
		MOVE 1,SPT(1)
		JRST .+1]
	TLNE 1,(NCORTM)		;PAGE NOW IN CORE?
	JRST XGC7		;NO, FLUSH IT
	HRRZ 2,1
	LOAD 2,CSTAGE,(2)	;GET PAGE STATE CODE
	CAIL 2,PSASN		;STILL ASSIGNED?
	AOJA 3,XGC6		;YES, COUNT IT AND LEAVE IT
	CAIE 2,PSRDN		;READ COMPLETED?
	JRST XGC7		;NO
	CALL AGESN
	AOJA 3,XGC6		;COUNT PAGE AND KEEP IT

XGC7:	MOVE 1,BITS(Q1)
	ANDCAM 1,WSPGS(Q2)	;CLEAR BIT FOR PAGE NO LONGER IN WS
	JRST XGC6

;ROUTINE CALLED BY BIT TABLE LOGIC TO UNLOCK XB FOR BIT TABLE
;	1/ CORE PAGE NUMBER OF XB

UNLBTB::MOVSI T2,(-PLKV)	;GET ONE UNIT OF LOCK COUNT
	ADDM T2,CST1(T1)	;UNLOCK IT
	CALLRET MONCLA		;AND CLEAR PAGER

;LOCAL ROUTINE TO DO A SWAP IN AND LOCK. CALLED WITH SPTN
;IN 1. MUST BE CALLED FROM PROCESS CONTEXT.

SWPIN1::NOSKED			;GO NOSKED
	PUSH P,FX		;SAVE FX FOR CALLER
	MOVE FX,FORKX		;SAY THIS FORK IS THE TARGET
	CALL SWPIN0		;GO DO THE SWAP IN AND LOCK
	POP P,FX		;RESTORE FX FOR CALLER
	OKSKED			;AND ALLOW SCHEDULING AGAIN
	RET			;AND DONE

;SWAP IN PAGE TABLE OR PSB
;CALLED FROM SCHED OR FROM NOSKED PROCESS

SWPIN0::TLNE 1,-1		;SPTN?
	JRST SWP01		;NO
	MOVE 3,SPT(1)		;YES, GET CURRENT ADDRESS
	TLNE 3,(NCORTM)		;OUT OF CORE?
	JRST SWP01		;YES
	HRRZ 2,3
	LOAD 2,CSTAGE,(2)	;GET PAGE STATE CODE
	CAIE T2,PSRIP		;READ IN PROGRESS?
	AOS PSKED		;NO, SIGNAL THAT PAGE AVAILABLE
	CAIE 2,PSRDN		;BEING READ OR COMPLETED?
	CAIN 2,PSRIP
	JRST SWP03		;YES
	MOVEI 1,0(3)
	CALL AGESN		;GRAB PAGE OFF RPLQ
SWP03:	MOVSI 1,0(3)		;ALREADY IN CORE
	JRST SWP02

SWP01:	CALL SWPIN
	HLRZ 3,1
SWP02:	MOVSI 2,(PLKV)
	HRRZS 3
	ADDM 2,CST1(3)		;LOCK PAGE
	RET

;SWAPIN AND WAIT AND STAY NOSKED

SWPINP:	NOSKED
	CALL SWPINW
	OKSKED
	RET

;WAIT FOR PAGE AND ACCOUNT
; 1/ SCHED TEST
;	CALL PGIWT
; RETURN +1 ALWAYS AFTER SCHED TEST SATISFIED.

PGIWT::	HLRZ 2,1		;GET PAGE NUMBER
	LOAD 2,CSTAGE,(2)	;GET PAGE STATE CODE
	CAIE 2,PSRIP		;READ IN PROGRESS?
	RET			;NO, NO NEED TO WAIT
	RDISMS
	NOSKED
	RET
;SWAP IN AND WAIT FOR COMPLETION
;SWPINW - SWAP INTO PAGE FROM RPLQ
;SWPINQ - SWAP INTO PAGE FROM SPMQ, PAGE # IN 3

SWPINW:	SETO 3,
SWPINQ:	PUSH P,FX
	MOVE FX,FORKX
	AOS USWPCT		;COUNT SWAPS
	TLNE 1,-1		;PT?
	JRST SWPIW2		;YES
	CALL SWPIQ1		;SWAPIN AND WAIT FOR COMPLETION
SWPIW1:	CALL PGIWT
	HLRZ 1,1		;RESTORE PAGE NO TO R.H.
	POP P,FX
	RET

SWPIW2:	PUSH P,3		;SAVE PAGE #
	PUSH P,1		;SAVE ORIG REQUEST
	HLRZ 1,1		;GET PT
	MOVE 3,SPT(1)
	TLNE 3,(NCORTM)		;CORE?
	JRST SWPIW3		;NO
	MOVEI 1,0(3)
	CALL AGESN		;FIX PAGE
	MOVSI 3,(PLKV)
	ADDM 3,CST1(1)		;SO IT DOESN'T SNEAK AWAY
SWPIW4:	EXCH 1,0(P)		;SAVE CORE PAGE NUMBER, GET ORIG OFN.PN
	MOVE 3,-1(P)		;GET PAGE #
	CALL SWPIQ1		;SWAP THE ORIG PAGE
	EXCH 1,0(P)		;GET PT CORE PAGE NUMBER
	MOVSI 3,(-PLKV)
	ADDM 3,CST1(1)		;UNLOCK IT
	POP P,1
	POP P,3			;RESTORE PHY PAGE #
	JRST SWPIW1

SWPIW3:	NOSKED
	CALL SWPIN		;SWAP IN THE PT
	OKSKED
	HLRZ 2,1
	MOVSI 3,(PLKV)
	ADDM 3,CST1(2)		;LOCK IT
	PDISMS			;WAIT TO FINISH
	HLRZ 1,1
	CALL AGESN
	JRST SWPIW4		;NOW GO GET THE PAGE
;SWAP IN PAGE
;AC1/ OFN.PN OR 0.SPTN
;RETURNS AC1/ CORE PAGE NO IN LH

;SWPIN - SWAP INTO PAGE FROM RPLQ
;SWPIQ1 - SWAP INTO PAGE FROM SPMQ, PAGE # IN 3

SWPIQ1:	JUMPL 3,SWPIN		;IF .LT. 0, THEN CHOSE FROM RPLQ
	PUSH P,1
	PUSH P,2
	PUSH P,3
	MOVE 1,3
	CALL OFFSPQ		;REMOVE FROM SPMQ
	POP P,3
	POP P,2
	POP P,1
	CALLRET SWPIQ2		;START THE SWAP

SWPIQ2:	PUSH P,5
	PUSH P,6
	JRST SWPIQ3		;REMOVE PAGE AND SWAP

SWPIN:	MOVE 3,NRPLQ		;NUMBER OF REPLACABLE PAGES
	JUMPE 3,SWPQT		;GO WAIT IF NONE
	HRRZ 3,RPLQ		;YES, REMOVE FROM QUEUE
	SUBI 3,CST3
	SOS NRPLQ
	PUSH P,5
	PUSH P,6
	PIOFF
	MOVE 4,CST3(3)
	HRRZ 6,4
	HLLM 4,0(6)
	HLRZ 6,4
	HRRM 4,0(6)
	PION
SWPIQ3:	SETZRO CSTAGE,(3)		;CLEAR AGE CODE
	SETZRO <PUFLD,CORMB>,CST0(3)	;CLEAR PUR, MODIFIED BIT
	SETZM CST3(3)
	CALL DEPG		;RESET PREVIOUS OWNERSHIP
	TLNE 1,-1		;NEW PAGE FROM PT OR SPT?
	JRST SWPI3		;PT
	MOVE 4,SPT(1)		;SPT, GET ADDRESS
	TLNN 4,(NCORTM)
	BUG(HLT,SPTPIC,<SWPIN - SPT PAGE ALREADY IN CORE>)
	STOR 3,STGADR,SPT(1)	;STORE NEW (CORE) ADDRESS
SWPI4:	ANDX 4,STGADM		;EXTRACT ADDRESS
	MOVEM 4,CST1(3)		;STORE BACKUP ADDRESS
	MOVEM 1,CST2(3)		;STORE LOCATION OF OWNING PT
	TLNE 4,(DSKAB+DRMAB)	;BACKUP ADDRESS ASSIGNED?
	JRST SWPI5		;YES, GO READ IN PAGE
	MOVEI 1,0(3)
	CALL SETSP0		;MAP PAGE INTO CSWPG
	MOVX T1,PSASM		;SET LEGAL AGE FOR LOCAL REF
	IORM T1,CST0(T3)
	SETZM CSWPGA
	MOVE 1,[CSWPGA,,CSWPGA+1]
	TXNE 4,UAACB-UAAB	;'COPY-REQUEST' PTR?
	MOVE 1,[XWD CPYPGA,CSWPGA] ;YES, COPY FROM CPYPG
	BLT 1,CSWPGA+777
	CALL RELSPG
	MOVX 1,PSRDN		;SET TO READ COMPLETED
	STOR 1,CSTAGE,(3)	; ...
	MOVX 1,CORMB		;AND SET MODIFIED BIT
	IORM 1,CST0(3)		; ...
	STOR FX,CFXRD,(3)	;NOTE FORK INDEX
	MOVSI 1,0(3)		;RETURN PAGE NUMBER
	HRRI 1,SWPRT		;RETURN APPROPRIATE SCHED TEST
SWPIX:	POP P,6
	POP P,5
	RET
SWPI3:	HLRZ 6,1		;GET OWNING PT OFN
	CALL SETSP6		;MAP PT
	MOVSI 4,(PLKV)
	ADDM 4,CST1(6)		;INCREMENT LOCK COUNT
	HRRZ 6,1
	MOVE 4,CSWPGA(6)
	TLNN 4,(NCORTM)
	BUG(HLT,PTAIC,<SWPIN - PT PAGE ALREADY IN CORE>)
	STOR 3,STGADR,CSWPGA(6)	;STORE NEW (CORE) ADDRESS
	CALL RELSPG
	JRST SWPI4

SWPQT:	PUSH P,1		;SAVE REQUESTED PAGE IDENT
	MOVEI 1,SWPWTT		;RESCHEDULE UNTIL NRPLQ NON-0
	PDISMS
	POP P,1
	JRST SWPIN

SWPWTT:	SKIPLE NRPLQ
	JRST 1(4)
	AOS CGFLG		;REQUEST CORE
	JRST 0(4)

SWPI5:	MOVEI 1,0(3)
	MOVX 2,PSRIP
	STOR 2,CSTAGE,(1)	;SET STATE TO READ IN PROGRESS
	STOR FX,CFXRD,(1)	;REMEMBER INITIATING FORK
	TLNE 4,(DSKAB)		;DISK?
	JRST SWPIK		;YES
	TLNN 4,(DRMAB)		;DRUM?
	BUG(HLT,ILSWPA,<SWPIN - ILLEGAL SWAP ADDRESS>)
	CALL DRMIO		;YES, INITIATE READ
	AOS DRMRD		;COUNT DRUM READS FOR STATISTICS
	MOVSI 1,0(1)
	HRRI 1,SWPRT		;RETURN APPROPRIATE SCHED TEST
	JRST SWPIX

SWPIK:	TLNE 4,(DSKNB)		;NEWLY ASSIGNED PAGE?
	JRST [	CALL SWPZPG	;YES, ZERO IT
		MOVSI 2,(DSKNB)
		ANDCAM 2,CST1(1)
		MOVX 2,PSRDN	;SET CODE TO READ COMPLETED
		STOR 2,CSTAGE,(1)
		JRST SWPIK1]
	CALL DSKIO		;INITIATE DISK READ
	AOS DSKRD		;COUNT DISK READS FOR STATISTICS
SWPIK1:	MOVSI 1,0(1)		;RETURN APPROPRIATE SCHED TEST
	HRRI 1,DSKRT
	JRST SWPIX
DEPG:	MOVE 4,CST2(3)		;GET LOCATION OF PT OWNING OLD CONTENTS
	JUMPE 4,R		;0 => WAS NONE
	MOVE 5,CST1(3)		;GET BACKUP ADDRESS
	TLNE 4,-1		;PT OR SPT
	JRST SWPI1		;PT
	STOR 5,STGADR,SPT(4)	;SPT, RESTORE BACKUP ADDRESS
	RET

SWPI1:	HLRZ 6,4
	CALL SETSP6		;MAP PT
	MOVSI 2,(-PLKV)
	ADDB 2,CST1(6)		;DECREMENT LOCK COUNT
	HRRZ 6,4
	STOR 5,STGADR,CSWPGA(6)	;STORE BACKUP ADDRESS
	CALL RELSPG		;RELEASE TEMPORARY MAP WORD
	RET

;REMOVE PAGE FROM CST
; 1/ PAGE NUMBER
;	CALL RPCST
; RETURN +1 ALWAYS, POINTER TO PAGE UNDONE

RPCST:	SAVEQ
	MOVE 3,1
	CALL DEPG		;DO THE WORK
	SETZM CST2(1)		;FLUSH BACK PTR
	RET

;DEASSIGN PAGE FROM CURRENT CST USAGE, SIMILAR TO RPCST BUT CAN BE
;CALLED AT INTERRUPT LEVEL.

;MUST BE CALLED PIOFF

;T1/ PHYSICAL PAGE
;	CALL DASPAG
;RETURNS+1(ALWAYS):
;POINTERS BACKED UP TO NEXT LEVEL IN THE STORAGE HIERARCHY
;PRESERVES T1

DASPAG:	MOVE T2,CST2(T1)	;GET OWNING PT
	JUMPE T2,DASPGX		;NONE - NOTHING TO DO
	SETZM CST2(T1)		;DELETE BACK POINTER
	MOVE T3,CST1(T1)	;GET NEXT LEVEL ADDRESS
	TLNE T2,-1		;OWNED BY SPT?
	JRST DASPG1		;NO - MUST CLEAR PT SLOT
	STOR T3,STGADR,SPT(T2)	;YES - JUST BACKUP SPT ADDRESS
DASPGX:	RET
DASPG1:	PUSH P,T1		;BE TRANSPARENT FOR T1
	HLRZ T1,T2		;GET PT PHYSICAL PAGE
	LOAD T1,STGADR,SPT(T1)	; ...
	PUSH P,CST0(T1)		;SAVE CURRENT CST
	SETOM CST0(T1)		;PREVENT AGE FAULT
	PUSH P,T1		;SAVE PHYSICAL ADDRESS
	CALL MAPRCA		;MAP PAGE, RETURNS ADDRESS IN T1
	ADDI T1,(T2)		;GET MAP SLOT
	STOR T3,STGADR,(T1)	;STORE NEXT HIGHER LEVEL ADDRESS
	POP P,T1		;RESTORE PHYSICAL ADDRESS
	POP P,CST0(T1)		;RESTORE CST
	CALL UNMRCA		;RELEASE MAPPING
	MOVSI T2,(-PLKV)	;DECREMENT LOCK COUNT
	ADDM T2,CST1(T1)	; ...
	POP P,T1		;RESTORE ACS
	JRST DASPGX		;DONE
;ROUTINE CALLED FROM PHYSIO TO GET STRUCTURE NUMBER FOR GIVEN
;CORE PAGE NUMBER. IT WILL HANDLE EITHER FILE PAGE OR SWAPPING REQUESTS
;ACCEPTS:	A/ CORE PAGE NUMBER
;RETURNS: +1	B/ STRUCTURE NUMBER

FNDSTR::HLRZ B,CST2(A)		;GET PTN FROM CST
	JUMPN B,HAVPT		;IF HAVE ONE GO ANALYZE IT
	HRRZ B,CST2(A)		;GET SPTN
	CAIGE B,NOFN		;IS THIS AN OFN?
	JRST GOTOFN		;YES. GO CONSIDER IT
	HLRZ B,SPTH(B)		;NO. GET OFN FOR THIS SPT
	JUMPN B,GOTOFN		;IF A FILE PAGE JUMP TO LOOK AT IT
RTZRO:	SETZ B,			;IS NOT A FILE PAGE. ASSUME SWAPPING SPACE
	RET			;DONE

HAVPT:	CAIL B,NOFN		;IS THIS AN OFN?
	JRST RTZRO		;NO
GOTOFN:	LOAD B,STRX,(B)		;YES. GET STRUCTURE NUMBER
	RET			;AND RETURN
;SCHEDULER TEST FOR PSB AND PT READ COMPLETED

SWPINT::MOVE 3,4		;SAVE RETURN
	HRRZ 1,FKPGS(7)		;PSB
	MOVE 1,SPT(1)		;ASSIGNED PAGE
	JSP 4,SWPRT		;DONE?
	 JRST 0(3)		;NO, RETURN NOT RUNNABLE
	CALL AGESN		;SET AGE
	LOAD T1,FKJSB
	MOVE 1,SPT(1)		;CHECK JSB
	JSP 4,SWPRT
	 JRST 0(3)
	CALL AGESN
	HLRZ 1,FKPGS(7)		;PT
	MOVE 1,SPT(1)
	JSP 4,SWPRT		;PT READY?
	 JRST 0(3)		;NO
	CALL AGESN
	LOAD T1,FSSPTN		;GET STACK PAGE
	MOVE T1,SPT(T1)		;GET CORE PAGE
	JSP 4,SWPRT		;SEE IF IN YET
	 JRST 0(3)		;NOT
	CALL AGESN		;MAKE THE AGE GOOD
	JRST 1(3)

;SCHEDULER TEST FOR READ COMPLETED

DSKRT::	JFCL			;SAME AS SWPRT
SWPRT::	HRRZ 2,1
	LOAD 2,CSTAGE,(2)	;GET PAGE STATE CODE
	CAIN 2,PSRIP		;STILL READ-IN-PROGRESS?
	JRST 0(4)		;YES
	JRST 1(4)
;SWAP COMPLETION ROUTINE, CALLED FROM DRUM AND DISK INTERRUPT CODE
; 1/ PAGE NUMBER

SWPDON::MOVX 2,SWPERR
	TDNE 2,CST3(1)		;SWAP ERROR IN PAGE?
	JRST SWPER1		;YES, GO DIAGNOSE IT
SWPERX:	MOVSI 2,(DWRBIT)	;WRITE BIT
	TDNE 2,CST3(1)		;WAS WRITE?
	JRST SWPD1		;YES
	AOS PSKED		;INDICATE READ COMPLETED
	MOVX 2,PSRDN
	STOR 2,CSTAGE,(1)
	RET

SWPD1:	ANDCAM 2,CST3(1)	;CLEAR WRITE BIT
	LOAD 2,CSTAGE,(1)	;GET TRAP CODE
	CAIN 2,PSWIP		;STILL WRITE IN PROGRESS?
	SOS IOIP		;YES, NOTE COMPLETION
	SKIPE DWRCFL		;FORK WAITING FOR WRITE COMPLETION?
	JRST [	AOS PSKED	;YES, POKE SCHED
		SKIPN IOIP	;WRITES ALL COMPLETED?
		SETZM DWRCFL	;YES, CLEAR FLAG
		JRST .+1]
	SKIPN CST2(1)		;PAGE DELETED?
	JRST [	MOVEI 2,CST3(1)	;IT WAS DELETED, PUT ON DELETED QUEUE
		EXCH 2,DELPGQ
		HRRM 2,@DELPGQ
		MOVEI 2,PSDEL	;SET PAGE STATE TO DELETED
		STOR 2,CSTAGE,(1)
		RET]
	MOVX T3,SWPERR
	TDNE T3,CST3(T1)	;ERROR ON WRITE?
	JRST [	ANDCAM T3,CST3(T1) ;YES, CLEAR IT
		MOVX T3,CORMB
		IORM T3,CST0(T1) ;NOTE PAGE STILL NEEDS WRITING
		CAIE T2,PSWIP	;PAGE WAS REASSIGNED?
		JRST .+1	;YES, OK
		MOVX T2,OFNUL	;SET IT TO UNASSIGNED
		STOR T2,CSTOFK,(T1)
		STOR T2,CSTAGE,(T1)
		JRST .+1]
	CAIE 2,PSWIP		;PAGE REASSIGNED WHILE WRITING?
	RET			;YES, DO NOTHING ELSE
	MOVE 2,CST1(1)		;GET ADDRESS WHERE PAGE WAS WRITTEN
	TXNN 2,DSKAB		;WAS WRITE TO DISK?
	CALLRET ONRQ		;NO, PUT PAGE ON RPLQ
	MOVX T2,DSKSWB
	TDNN T2,CST3(T1)	;KEEP PAGE REQUESTED?
	CALLRET OFRQ		;NO, PUT ON RPLQ
	CALLRET ONRQ		;YES, TO END OF RPLQ
;DIAGNOSE SWAP ERROR
; A/ PAGE NUMBER

SWPER1:	HLRZ B,CST2(A)		;GET OWNING SPTN
	JUMPN B,SWPER3		;JUMP IF IN PT
	HRRZ B,CST2(A)		;GET SPTN OF PAGE
	CAIGE B,NOFN		;INDEX BLOCK?
	JRST [	CALL SWBOFN	;YES -  FLAG IN SPT
		JRST SWPEX2]	;AND NOTE MILD COMPLAINT
	HLRZ B,SPTH(B)		;GET OFN OF IDENT
	JUMPN B,SWPER3		;JUMP IF OFN PRESENT
	PUSH P,A		;SAVE PAGE NUMBER
	MOVE A,CST2(A)		;SETUP SPTN
	CALL FNDFPG		;GET TYPE OF FORK PAGE
	MOVE B,A		;B = TYPE
	POP P,A			;RECOVER PAGE NUMBER
	XCT [	JRST SWPEX7	; 0 - UNKNOWN OR HWPT
		JRST SWPEX8	;1 - PSB
		JRST SWPEX8	;2 - UPT
		JRST SWPEX8](B)	;3 - JSB

;HERE WHEN HAVE PAGE TABLE IDENT IN B

SWPER3:	CAIGE B,NOFN		;IN ORDINARY FILE?
	JRST [	CALL SWBOFN	;YES - MARK IN SPT
		JRST SWPERX]	;AND DEPART
	CAMN B,MMSPTN		;IN SWAPMON?
	JRST SWPEX3		;YES
	PUSH P,A		;SAVE PAGE NUMBER
	MOVE A,B		;SETUP SPTN
	CALL FNDFPG		;GET TYPE OF FORK PAGE
	MOVE B,A		;B = TYPE
	POP P,A			;RECOVER PAGE NUMBER
	XCT [	JRST SWPEX6	;0 - HWPT OR UNKNOWN
		JRST SWPEX4	;1 - PSB PAGE
		JRST SWPERX	;2 - UPT PAGE
		JRST SWPEX5](B)	;3 - JSB PAGE

;HERE TO INDICATE AN ERROR IN AN OFN

SWBOFN:	MOVX T3,OFNBAT		;GET BAT BIT
	TDNN T3,SPTH(T2)	;ALREADY SET?
	TXO T3,OFNWRB		;YES - INDICATE CHANGED
	IORM T3,SPTH(T2)	; IN SPTH
	RET
;DISPOSITION OF SWAP ERROR CASES

SWPEX1:	BUG(CHK,SWPFPE,<SWAP ERROR IN SENSITIVE FILE PAGE>)
	JRST SWPERX		;TRY TO CONTINUE

SWPEX2:	BUG(CHK,SWPIBE,<SWAP ERROR IN INDEX BLOCK>)
	JRST SWPERX		;SHOULD CONTINUE OK

SWPEX3:	BUG(HLT,SWPMNE,<SWAP ERROR IN SWAPPABLE MONITOR>)

SWPEX4:	BUG(HLT,SWPPSB,<SWAP ERROR IN PSB PAGE>)

SWPEX5:	BUG(CHK,SWPJSB,<SWAP ERROR IN JSB PAGE>)
	JRST SWPERX		;TRY TO CONTINUE

SWPEX6:	BUG(HLT,SWPPTP,<SWAP ERROR IN UNKNOWN PT PAGE>)

SWPEX7:	BUG(HLT,SWPPT,<SWAP ERROR IN UNKNOWN PT>)

SWPEX8:	BUG(HLT,SWPUPT,<SWAP ERROR IN UPT, OR PSB>)
;FIND TYPE OF FORK PAGE
; A/ SPTH OF PAGE
;	CALL FNDFPG
; RETURNS +1 ALWAYS,
; A/ 	0 - UNKNOWN PAGE OR HWPT
;	1 - PSB
;	2 - UPT
;	3 - JSB

FNDFPG:	SAVEQ
	SKIPE FX,SPTH(A)	;HAVE GOOD FORX INDEX?
	TLNE FX,-1
	JRST RETZ		;NO, RETURN UNKNOWN
	HRRZ Q1,A		;SAVE SPTH
	MOVSI A,-NFNFT		;SETUP TO SCAN TABLE
FNFP1:	XCT FNFTAB(A)		;GET SPTN FOR A FORK PAGE
	CAMN B,Q1		;SAME AS GIVEN ONE?
	RET			;YES, RETURN INDEX IN A
	AOBJN A,FNFP1		;SCAN TABLE
	JRST RETZ		;NOT FOUND

FNFTAB:	LOAD B,HWPTN
	LOAD B,FKPSB
	LOAD B,FKUPT
	LOAD B,FKJSB
NFNFT==.-FNFTAB
;PUT PAGE ON TOP OF REPLACABLE QUEUE.  THIS IS DONE WHEN CURRENT
;CONTENTS OF PAGE ARE NOT EXPECTED TO BE REUSED.  THE CORE PAGE THUS
;S PLACED WHERE SWPIN WILL GET TO IT IMMEDIATELY.

OFRQ:	MOVEI 2,CST3(1)		;MAKE PTR
	PIOFF			;NO DSK OR DRM INTERRUPTS WHILE DIDDLING PTRS
	LOAD 3,CSTPST,(1)	;CHECK PAGE STATE
	JUMPN 3,ONSPMQ		;OTHER THAN AVAILABLE?
	CAMGE 1,MONCOR		;A RESIDENT MONITOR PAGE?
	JRST [	CALL DASPAG	;DEASSIGN PAGE
		PION		;TURN ON PI'S AGAIN
		CALLRET FRCRRM]	;AND PUT PAGE IN SERVICE AGAIN
	HRRZ 3,RPLQ		;NO, MAKE PTR FOR NEW PAGE
	HLL 4,0(3)		; ..
	HRLM 2,0(3)		;FIX BACK PTR OF OLD TOP PAGE
	HLL 3,4
	MOVEM 3,0(2)		;SET PTRS FOR NEW TOP PAGE
	HRRM 2,RPLQ		;SET NEW PTR TO TOP PAGE IN RPLQ
	PION
	JRST ONRQ1		;GO FINISH UP

;PUT PAGE ON REPLACABLE QUEUE
; 1/ PAGE NUMBER
;	CALL ONRQ
; RETURN +1 ALWAYS

ONRQ:	MOVEI 2,CST3(1)		;CONSTRUCT ABSOLUTE PTR FOR PAGE
	PIOFF			;NO INTS WHILE DIDDLING LIST
	LOAD 3,CSTPST,(1)	;GET PAGE STATE
	JUMPN 3,ONSPMQ		;OTHER THAN AVAILABLE?
	CAMGE 1,MONCOR		;A RESIDENT MONITOR PAGE?
	JRST [	CALL DASPAG	;DEASSIGN PAGE
		PION		;TURN ON PI'S AGAIN
		CALLRET FRCRRM]	;AND PUT IT BACK IN SERVICE
	HLRZ 3,RPLQ		;NO, PUT PAGE ON 'IN' END OF QUEUE
	HRL 4,0(3)		; BECAUSE PAGES ARE TAKEN FROM 'OUT'
	HRRM 2,0(3)		; END OF QUEUE.
	HLL 3,4
	MOVSM 3,0(2)
	HRLM 2,RPLQ
	PION
ONRQ1:	AOS NRPLQ
	MOVEI 2,PSRPQ		;SET PAGE STATE
	STOR 2,CSTAGE,(1)
	RET
;HERE TO PLACE A PAGE ON THE SPECIAL MEMORY QUEUE
;MUST BE CALLED PIOFF
;T1/ CORE PAGE NUMBER
;	CALL ONSPMQ
;RETURNS+1(ALWAYS):
;PAGE REMOVED FROM CST, ON SPMQ
;**NOTE**: RETURNS PION

ONSPMQ:	CALL DASPAG		;REMOVE PAGE FROM CST
	LOAD T2,CSTAGE,(T1)	;GET STATE CODE
	CAIN T2,PSSPQ		;ALREADY ON SPMQ?
	JRST ONSPQX		;YES - DONE
	MOVEI T2,CST3(T1)	;BUILD POINTER
	HLRZ T3,SPMQ		;GET TAIL POINTER
	HRRM T2,(T3)		;APPEND TO LIST
	HRLZM T3,CST3(T1)	;BACK POINTER
	HRLM T2,SPMQ		;NEW TAIL OF LIST
	MOVEI T2,PSSPQ		;SET PAGE STATE TO ON SPMQ
	STOR T2,CSTAGE,(T1)	; ...
	AOS NSPMQ		;NOTE ANOTHER PAGE
	CAMG T1,NHIPG		;A KNOWN PAGE?
	CAMGE T1,MONCOR		;SWAPPABLE?
	JRST ONSPQX		;NO, ALL DONE
	AOS GNPBAS		;UPDATE PAGE ACCOUNTING
	AOS BALSHC
	AOS SUMNR
ONSPQX:	PION			;ENABLE INTERRUPTS
	RET			;ALL DONE

;ROUTINE TO REMOVE A PAGE FROM SPMQ
;T1/ PHYSICAL PAGE
;	CALL OFFSPQ
;RETURNS+1(ALWAYS):
;	PAGE REMOVED
;CAUTION - THE CALLER MUST BE SURE THE PAGE IS "STABLE" ON SPMQ

OFFSPQ:	PIOFF			;INTERLOCK
	LOAD T2,CSTAGE,(T1)	;CHECK STATE
	CAIE T2,PSSPQ		;NOW ON SPMQ?
	BUG (HLT,OFFSPE,<OFFSPQ- PAGE NOT ON SPMQ>)
	HRRZ T2,CST3(T1)	;GET POINTERS
	HLRZ T3,CST3(T1)
	JUMPE T2,[HRLM T3,SPMQ	;IF END-OF-LIST, MAKE NEW TAIL
		JRST OFFSP0]	;PROCEED
	HRLM T3,(T2)		;ADVANCE BACK POINTER
OFFSP0:	HRRM T2,(T3)		;BACKUP FORWARD LINK
	MOVX T2,UAAB		;UNASSIGNED ADDRESS
	STOR T2,STGADR,CST1(T1) ;SET IT
	MOVX T2,<FLD(OFNUL,CSTOFK)>
	MOVEM T2,CST3(T1)	;SET OWNER TO NULL
	SOS NSPMQ		;ONE FEWER PAGE
	CAMGE T1,MONCOR		;A SWAPPABLE PAGE?
	JRST ONSPQX		;NO. DON'T ACCOUNT IT
	CAMLE T1,NHIPG		;A NEW PAGE COMING IN?
	JRST [	MOVEM T1,NHIPG	;YES. MAKE XGC AND GCCRO SCAN IT
		AOS TOTRC	;ANOTHER REAL PAGE
		AOS PAGDIF	;NEW PAGE IN THE SYSTEM
		JRST ONSPQX]	;AND DONE
	CALL UPSWP		;ONE MORE SWAPPING PAGE
	CALLRET ONSPQX		;DONE

;ROUTINE TO RETURN CSTPST FOR A PHYSICAL PAGE
;T1/ PAGE
;	CALL GETPST
;RETURNS+1(ERROR):
;	INVALID PAGE NUMBER
;RETURNS+2(SUCCESS):
;T2/ SPECIAL PAGE STATE

GETPST::CAIL T1,MAXCOR		;CHECK RANGE
	RET			;INVALID PAGE
	LOAD T2,CSTPST,(T1)	;PAGE OK, RETURN CURRENT STATE
	RETSKP

;ROUTINE TO SET THE CSTPST STATE FOR A PHYSICAL PAGE
;ASSUMES PROCESS CONTEXT, AS IT MAY NEED TO BLOCK DEPENDING ON THE
;ACTION TO BE TAKEN

;T1/ PHYSICAL PAGE
;T2/ NEW SPECIAL PAGE STATE
;	CALL SETPST
;RETURNS+1(ERROR):
;	ERROR CODE IN T1
;RETURNS+2(SUCCESS):
;	PAGE ON SPMQ WITH REQUESTED STATE
;	T1/ PREVIOUS STATE OF PAGE

;LOCAL AC USAGE
;Q1/ PHYSICAL PAGE
;Q2/ NEW STATE
SETPST::SAVEQ
	STKVAR <SETOST>		;SAVE ORIGINAL STATE HERE
	MOVE Q1,T1		;COPY ARGUMENTS
	MOVE Q2,T2		; ...
	CAIN T2,PSTSPM		;ATTEMPTING TO USE TRANSITION STATE?
	RETBAD (PMCLX1)		;YES - CANNOT BE SET BY USER
	CAIL T1,MAXCOR		;LEGAL PAGE?
	RETBAD (ARGX06)		;NO - INVALID PAGE
	CALL LCKSPM		;INTERLOCK USER SIDE OF SPMQ LOGIC
				;PRESERVES T,Q,P ACS
	LOAD T3,CSTPST,(T1)	;YES - GET CURRENT PAGE STATE
	MOVEM T3,SETOST		;SAVE ORIGINAL STATE HERE
	LOAD T4,CSTAGE,(T1)	;NOW NOINT, IS PAGE ALREADY ON SPMQ
	CAIE T4,PSSPQ		; ?
	JRST STPST1		;NO
	CAMN T3,T2		;SAME AS REQUESTED STATE?
	JRST STPSTX		;YES - RETURN SUCCESS
STPST1:	LSH T3,2		;NO - FORM TRANSITION TABLE INDEX
	IOR T3,T2		; ...
	ADJBP T3,[POINT 2,STPSTA,1] ;INDEX INTO TRANSITION TABLE
	LDB T3,T3		;GET ACTION CODE
	XCT STPSTB(T3)		;PERFORM ACTION

;COMMON EXIT POINT

STPSTX:	CALL ULKSPM		;RELEASE USER SIDE OF SPMQ
	MOVE T1,SETOST		;RETURN ORIGINAL STATE TO CALLER
	RETSKP			;RETURN SUCCESS

;TRANSITION TABLE

STPSTA:	BYTE (2)0,0,1,1,0,0,0,0,2,0,0,3,2,0,3,0

;ACTION TABLE
;ENTERED WITH T1,Q1 = PAGE; T2,Q2 = REQUESTED STATE

STPSTB:	RETBAD (PMCLX1,<CALL ULKSPM>)	;ILLEGAL TRANSITION
	JRST STPSTF		;TRANSITION TO OFFLINE
	JRST STPSTN		;TRANSITION TO ONLINE
	JRST STPSTC		;CHANGE OFFLINE STATE

;HERE TO PLACE A PAGE OFFLINE

STPSTF:	CALL FRCSPM		;FORCE ONTO SPMQ
	  RETBAD (PMCLX2,<CALL ULKSPM>) ;COULDNT FREE PAGE
	MOVE T1,Q1		;GET PAGE AGAIN
	CALL CASHFP		;FLUSH PAGE FROM CACHE
	MOVX T1,PSTOFL		;SET PAGE OFFLINE
	STOR T1,CSTPST,(Q1)	; ...
	JRST STPSTX		;EXIT

;HERE TO PLACE A PAGE ONLINE

STPSTN:	CALL FRCSPM		;FORCE ONTO SPMQ
	  RETBAD (PMCLX2,<CALL ULKSPM>)
	MOVE T1,Q1		;COPY PAGE
	CALL CHKPAG		;CHECK PAGE FOR NXM
	  RETBAD (PMCLX3,<CALL ULKSPM>) ;ERRORS, DONT PLACE ONLINE
	MOVE T1,Q1		;COPY PAGE
	CALL OFFSPQ		;REMOVE FROM SPMQ
	MOVE T1,Q1		;COPY PAGE
	MOVX T3,PSTAVL		;SET SPECIAL PAGE STATE TO AVAILABLE
	STOR T3,CSTPST,(T1)	; ...
	CAMGE T1,MONCOR		;A RESIDENT MONITOR PAGE?
	JRST [	CALL FRCRRM	;YES. PUT IT BACK IN SERVICE
		JRST STPSTX]	;AND DONE
	NOSKED			;PROTECT THIS PAGE
	CALL OFRQ		;PLACE AT HEAD OF RPLQ
	OKSKED			;ALL QUEUED UP
	JRST STPSTX

;HERE TO CHANGE THE STATE OF A PAGE (FROM OFL TO ERR OR ERR TO OFL)

STPSTC:	CALL FRCSPM		;SHOULD BE A NOP
	  RETBAD (PMCLX2,<CALL ULKSPM>)
	STOR Q2,CSTPST,(Q1)	;SET TO NEW STATE
	JRST STPSTX

;COMMON ROUTINES FOR USER SPMQ MANIPULATION

;ROUTINE TO INTERLOCK USER MANIPULATION OF SPMQ
;PRESERVES T,Q,P ACS

LCKSPM:	PUSH P,T1		;SAVE T1
LCKSP1:	NOINT
	AOSE SPMLCK		;TEST/SET LOCK
	JRST LCKSP2		;MUST BLOCK
	MOVE T1,FORKX		;HAVE LOCK, INDICATE OWNER
	MOVEM T1,SPMONR		; ...
	POP P,T1		;RESTORE T1
	RET

LCKSP2:	OKINT			;BLOCK OKINT
	MOVEI T1,SPMLCK		;LOCK WORD
	CALL DISL		;WAIT FOR NEGATIVE
	JRST LCKSP1		;TRY AGAIN


;ROUTINE TO RELEASE SPMQ INTERLOCK
;PRESERVES ALL ACS

ULKSPM:	SETOM SPMONR		;NO OWNER
	SETOM SPMLCK		;FREE LOCK
	OKINT			;ALLOW INTERRUPTS
	RET

;ROUTINE TO FORCE A PAGE ONTO SPMQ
;T1/ PHYSICAL PAGE
;	CALL FRCSPM
;RETURNS+1(FAILURE):
;	UNABLE TO FREE PAGE
;RETURNS+2(SUCCESS):
;	PAGE IS ON SPMQ

FRCSPM:	ACVAR <Q1,Q2,Q3>
	MOVE Q1,T1		;COPY ARGUMENT
	MOVEI Q2,^D5		;NUMBER OF TIMES TO TRY
	LOAD Q3,CSTPST,(T1)	;GET PRESENT STATE
FRCSP1:	LOAD T2,CSTAGE,(Q1)	;GET CURRENT STATE
	CAIN T2,PSSPQ		;ON SPMQ NOW?
	RETSKP			;YES - NOTHING TO DO
	MOVX T2,PSTSPM		;SETUP TO CHANGE SPECIAL PAGE STATE
	PIOFF			;INTERLOCK
	LOAD T3,CSTPST,(Q1)	;CHECK CURRENT STATE
	CAIN T3,PSTAVL		;CURRENTLY AVAILABLE?
	STOR T2,CSTPST,(Q1)	;YES - MAKE UNAVAILABLE
	LOAD T2,CSTAGE,(Q1)	;GET SWAPPER STATE CODE
	CAIN T2,PSRPQ		;ON RPLQ?
	JRST FRCSP3		;YES - DIRECTLY TO SPMQ
	CAIGE T2,PSASN		;PAGE IN USE?
	JRST FRCSP4		;NO
	HLRZ T2,CST2(Q1)	;SEE IF PART OF MONITOR MAP
	CAMN T2,MMSPTN		;IS IT?
	JRST [	HRRZ T2,CST2(Q1) ;YES. GET INDEX
		CAML T2,SWPCOR	;IN OR ABOVE SWPMON?
		JRST .+1	;YES. CAN'T MOVE IT THEN
		CAML T2,MONCOR	;IS IT A RESIDENT PAGE?
		CALL [	MOVX T3,-PLKV ;NO. SEE IF LOCKED THEN
			TDNN T3,CST1(Q1) ;IS IT?
			RETSKP		;NO. LET STANDARD CODE DO IT
			CAIL Q1,<SPCRES+PGSIZ-1>/PGSIZ ;MOVABLE?
			RET		;MAYBE.
			RETSKP]		;NO.
		SKIPA T1,Q1	;YES. CAN TRY TO MOVE IT THEN
		JRST .+1	;NO. CAN'T MOVE IT
		PION		;TURN ON PI'S FOR A WHILE
		CALL FRCRMP	;SEE IF WE CAN DO IT
		 JRST FRCSP0	;CAN'T. RETURN BAD NEWS
		RETSKP]		;DONE. PAGE IS ON SPMQ
	CALL SWPCHK		;CAN PAGE BE SWAPPED OUT?
	  SKIPA			;NO - USE LARGE HAMMER
	JRST FRCSP5		;YES - SWAPOUT JUST THIS PAGE
	PION			;MUST UNLOAD MEMORY
	AOS SKEDFC		;INDICATE FORCED CLEAR
	ISB SCDCHN		;REQUEST SCHEDULER CYCLE
FRCSP2:	MOVEM Q1,SPMTPG		;SAVE REQUESTED PAGE
	MOVEI T1,^D2000		;AND WATCHDOG TIME
	ADD T1,TODCLK		; ...
	MOVEM T1,SPMTIM		;TWO SECONDS FROM NOW
	MOVEI T1,SPMTST		;TEST ROUTINE
	MDISMS			;REGRETABLY NOINT
	MOVE T1,Q1		;PUT PAGE NUMBER BACK IN T1
	SOJG Q2,FRCSP1		;TRY AGAIN
FRCSP0:	STOR Q3,CSTPST,(Q1)	;RESTORE ORIGINAL STATE
	RET			;FAILED
;FRCSPM CONTINUED

;ON RPLQ - REMOVE FROM RPLQ AND PLACE ON SPMQ

FRCSP3:	MOVE T2,Q1		;PAGE NUMBER
	NOSKED			;PROTECT ALL STRUCTURES
	CALL PRLDEQ		;GET OFF OF RPLQ
	MOVE T1,Q1		;PAGE NUMBER AGAIN
	PIOFF			;PRLDEQ DID A PION
	CALL ONSPMQ		;PLACE ON SPMQ (RETURNS PION)
	OKSKED			;ALLOW SCHEDULING AGAIN
	RETSKP			;SUCCESS

;HERE WHEN PAGE IS UNASSIGNED AND NOT ON RPLQ

FRCSP4:	PION
	JRST FRCSP2		;SHOULD BE TRANSIENT STATE

;HERE WHEN PAGE IS ASSIGNED AND CAN BE SWAPPED OUT

FRCSP5:	NOSKED			;FOR CALL TO SWPOUT
	PION
	CALL SWPOT0		;START SWAP
	OKSKED
	JRST FRCSP2		;JUST A MATTER OF TIME NOW...


;SCHEDULER TEST ROUTINE FOR FRCSPM

SPMTST:	MOVE T1,SPMTPG		;SOUGHT AFTER PAGE
	LOAD T2,CSTAGE,(T1)	;GET STATE CODE
	CAIN T2,PSSPQ		;ON SPMQ?
	JRST 1(T4)		;YES - UNBLOCK
	MOVE T1,SPMTIM		;NO - TIME UP?
	CAML T1,TODCLK		; ???
	JRST 0(T4)		;NO - REMAIN BLOCKED
	JRST 1(T4)		;TIME IS UP - UNBLOCK AND RETRY
;ROUTINE USED BY FRCSPM TO PLACE A RESIDENT MONITOR PAGE OFF-LINE.
;CALLED WITH:	T1/ PAGE NUMBER
;RETURNS:
;		+1 FAILED. CANNOT MOVE THIS PAGE
;		+2 SUCCESS. PAGE MOVED AND MMAP UPDATED
;PAGE MUST BE LESS THAN C(SWPCOR) AND MUST BE LOCKED.

FRCRMP:	STKVAR <SRCPAG,SRCADR>	 ;WHERE TO SAVE SOURCE PAGE
	HRRZ T2,CST2(T1)	;GET MONITOR VIRTUAL PAGE NUMBER
	MOVEM T2,SRCADR		;SAVE IT
	CALL RMPCHK		;SEE IF CAN MOVE THIS PAGE
	 RETBAD ()		;CAN'T.
	MOVEM T1,SRCPAG		;SAVE ADDRESS OF SOURCE PAGE
FRCRM1:	NOSKD1			;PROTECT RPLQ
	CALL CHKRPQ		;WAIT FOR RPLQ TO BE OKAY
	 JRST .-1		;REVERIFY IF BLOCKED
	HRRZ T2,RPLQ		;GET TOP PAGE
	SUBI T2,CST3		;COMPUTE PAGE NUMBER
	CALL PRLDEQ		;USE COMMON ROUTINE TO DEQUEUE THE PAGE
	PUSH P,T2		;SAVE CORE PAGE NUMBER
	MOVE T3,T2		;COPY PAGE NUMBER
	CALL DEPG		;DEASSIGN OWNERSHIP
	SETZM CST1(T3)		;NO BACKUP NOW
	MOVE T1,T3		;GET CORE PAGE NUMBER IN T1
	MOVX T3,PSRDN		;FAKE AGE
	STOR T3,CSTAGE,(T1)	; SO MLKCP WILL DO RIGHT THING
	CALL MLKCP		;LOCK IT IN CORE
	POP P,T2		;GET DEST CORE PAGE AGAIN
	MOVE T1,SRCPAG		;GET BACK SOURCE PAGE
	MOVE T3,CST2(T1)	;GET OWNERSHIP
	MOVEM T3,CST2(T2)	;NEW PAGE OWNERSHIP
	; ..
;PAGE NOW HAS PROPER I.D. MOVE DATA

	MOVE T3,SRCADR		;GET MONITOR VIRTUAL PAGE NUMBER OF SOURCE
	LSH T3,PGSFT		;AN ADDRESS
	MOVE T1,T2		;GET DEST CORE PAGE
	PIOFF			;OWN THE ENTIRE MACHINE
	CALL MAPRCA		;SET UP MAPPING
	MOVEI T4,PGSIZ-1(T1)	;COMPUTE END OF PAGE
	HRL T1,T3		;SET UP BLT ARG
	BLT T1,0(T4)		;MOVE DATA
	CALL UNMRCA		;UNDO MAPPING NOW THAT DATA IS MOVED
	MOVE T1,SRCADR		;GET BACK SOURCE PAGE
	STOR T2,STGADR,MMAP(T1)	;SET UP NEW MAPPING FOR THIS PAGE
	MOVE T1,T3		;GET SET TO MAKE PAGE USABLE
	CALL MONCLR		;DO IT
	MOVE T1,SRCPAG		;GET SOURCE PAGE # AGAIN
	MOVX T3,-PLKV		;TEST FOR LOCKED
	TDNE T3,CST1(T1)	;NOW LOCKED?
	CALL MULKCR		;YES. UNLOCK IT THEN
	MOVE T1,SRCPAG		;THE PAGE AGAIN
	SETZM CST2(T1)		;NOW NOT OWNED
   REPEAT 0,<			;DON'T NEED EPT CODE YET
	CALL TSTEPT		;SEE IF SOURCE PAGE IS NOW THE EPT
	JRST [	EXCH T1,T2	;IT IS. MUST CHANGE EPT THEN
		CALL SETEPT	;MAKE NEW PAGE THE EPT
		EXCH T1,T2
		JRST .+1]	;PROCEED
   >				;END OF REPEAT 0
	CALL ONSPMQ		;PUT PAGE ON SPECIAL QUEUE
	OKSKD1			;TURN ON SCHEDULER AGAIN
	RETSKP			;AND DONE
;ROUTINE TO PUT A RESIDENT MONITOR PAGE BACK ON-LINE.
;	T1/ PAGE NUMBER
;PAGE ALREADY OFF OF SPMQ

FRCRRM:	STKVAR <SRCPAG,OLDPAG>	;SAVE PAGE NUMBERS
	NOSKD1			;OWN THE MACHINE
	MOVEM T1,SRCPAG		;SAVE PAGE TO USE AGAIN
	LOAD T2,STGADR,MMAP(T1)	;GET CURRENT LOC OF DATA
	MOVEM T2,OLDPAG		;SAVE IT TOO
	MOVE T3,CST2(T2)	;I.D OF PAGE
	MOVEM T3,CST2(T1)	;SET UP I.D.
	SETONE CSTAGE,(T1)	;MAKE NEW PAGE ACCESSIBLE
	MOVE T2,T1		;GET ADDRESSABLE VALUE FOR CURRENT DATA
	LSH T2,PGSFT		;GET ADDRESS OF CURRENT DATA
	PIOFF			;PREVENT MISHAPS
	CALL MAPRCA		;GET ACCESS TO NEW PAGE
	MOVEI T4,PGSIZ-1(T1)	;GET END OF PAGE
	HRL T1,T2		;SET UP FOR DATA MOVE
	BLT T1,0(T4)		;MOVE THE DATA
	MOVE T1,SRCPAG		;GET NEW PAGE NUMBER AGAIN
	STOR T1,STGADR,MMAP(T1)	;MAKE MMAP POINT TO NEW PAGE
	MOVE T1,T2		;GET ADDRESS
	CALL MONCLR		;MAKE PAGE BE USED
	MOVE T1,OLDPAG		;GET OLD PAGE I.D.
   REPEAT 0,<			;DON'T NEED EPT CODE NOW
	CALL TSTEPT		;IS IT NOW THE EPT?
	JRST [	MOVE T1,SRCPAG	;YES. GET SOURCE PAGE
		CALL SETEPT	;MAKE IT THE NEW EPT
		MOVE T1,OLDPAG	;RESTORE OLD PAGE
		JRST .+1]	;AND PROCEED
   >				;END OF REPEAT 0
	CALL UNMRCA		;CLEAR TEMP MAPPING
	PION			;ALL IS O.K NOW. LET SYSTEM BREATH AGAIN

;DATA NOW RESTORED AND PAGE IN USE. RELEASE OLD PAGE

	SETZM CST2(T1)		;NO LONGER OWNED
	CALL MULKCR		;UNLOCK PAGE
				;UNLOCKER PUTS PAGE ON RPLQ
	OKSKD1			;ALLOW SCHEDULING AGAIN
	RET			;DONE
;SPECIAL ROUTINES USED BY DIAG MEMORY CONTROL.

;SET MAP TO POINT TO PHYSICAL MEMORY WITHOUT CHANGING STATE
;OF MEMORY PAGES. PROCESS SHOULD BE NOINT AND MUST INSURE
;THAT THE PAGES ARE REFERENCED ONLY WHILE NOSKED.
;ACCEPTS:
;		T1/ SOURCE I.D. (PTN,,PN)
;		T2/ FIRST CORE PAGE (-1 => CLEAR MAP)
;		T3/ COUNT
;RETURNS:	+1 ALWAYS

MAPPV::	ASUBR <SID,CPG,CNT>
	HLRZ T3,T1		;GET PTN OF MAP
	CALL SETXB1		;MAP PT
	MOVE T3,IMMPTR		;FORM AN IMMEDIATE POINTER TO MEMORY
	IOR T3,CPG		;INSERT MEMORY PAGE
	SKIPGE CPG		;WANT TO CLEAR?
	SETZM T3		;YES.
	MOVN T1,CNT		;GET NEG OF COUNT
	MOVSS T1
	HRR T1,SID		;STARTING PAGE IN MAP
MAPPV1:	MOVEM T3,CXBPGA(T1)	;UPDATE MAP
	SKIPE T3		;WANT CLEAR?
	ADDI T3,1		;NO. NEXT PAGE THEN
	AOBJN T1,MAPPV1		;DO ALL OF MAP
	CALL MONCLA		;CLEAR PAGER
	CALLRET RELCXB		;RELEASE PT AND RETURN

;ROUTINE TO SET UP CST0 FOR A PROCESS THAT HAS USED MAPPV.
;THE APPROPRIATE CST0'S ARE SET UP WITH PUFLD=-1 AND
;THE AGE SET TO THE CURRENT AGE OF THE PROCESS.
;MUST BE NOSKED
;ACCEPTS:
;		T1/ FIRST MEMORY PAGE
;		T2/ COUNT
;RETURNS:	+1 ALWAYS

SETCST::MOVX T4,<PUFLD!CORMB>	;PART OF NEW CST0 WORDS
	MOVE T3,FORKX		;CURRENT FORK
	HLRZ T3,FKNR(T3)	;PRESENT AGE
	STOR T3,AGEMSK,T4	;SET AGE
SETCS1:	MOVEM T4,CST0(T1)	;SET NEW CST0
	ADDI T1,1		;NEXT PAGE
	SOJG T2,SETCS1		;DO ALL OF THEM
	CALLRET MONCLA		;CLEAR PAGER
;ROUTINES USED BY LOADBS TO SEE IF THIS FORK'S PT,PSB,ETC
;ARE IN A TRANSITION PAGE.
;ACCEPST:	FX/ FORK HANDLE
;RETURNS:	+1 ONE OR MORE PAGES IN TRANSITION
;		+2 NONE IN TRANSITION

TSTFRP::CAMN FX,SPMONR		;THIS FORK OWN THE LOCK?
	RETSKP			;YES. ALLOW IT THEN
	LOAD T1,FKJSB		;GET JSB
	CALL TSTSPT		;GUILTY?
	 RET			;YES.
	HRRZ T1,FKPGS(FX)	;TRY PSB
	CALL TSTSPT
	 RET			;YES
	HLRZ T1,FKPGS(FX)	;NO. TRY PT
	CALL TSTSPT		;?
	 RET			;YES. GUILTY
	LOAD T1,FSSPTN		;STACK PAGE
	CALLRET TSTSPT		;?

;LOCAL ROUTINE TO TEST A GIVEN FORK PAGE.
;ACCEPTS:	T1/ SPT OFFSET
;RETURNS:	+1 IN TRANSITION
;		+2 NOT

TSTSPT:	LOAD T2,STGADR,SPT(T1) ;GET ADDRESS
	TXNE T2,NCORTM		;IN MEMORY?
	RETSKP			;NO. NOT IN TRANSITION THEN
	JE CSTPST,(T2),RSKP	;IN TRANSITION?
	RET			;YES.

	TNXEND
	END