Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_1_19910112 - 6-1-monitor/pagem.mac
There are 55 other files named pagem.mac in the archive. Click here to see a list.
; *** Edit 7314 to PAGEM.MAC by LOMARTIRE on 9-Jun-86, for SPR #21208
; Prevent NSKDIS BUGHLTs from NOSKED before call to RELMPG in WCPY 
; *** Edit 7303 to PAGEM.MAC by WAGNER on 27-May-86
; Restore code removed in edit 7164 to prevent ILPSEC bughalts. 
; *** Edit 7283 to PAGEM.MAC by LOMARTIRE on 4-Apr-86, for SPR #21144
; Prevent OPNX9 errors from OF%RDU opens and bug in CHKLAC 
;------------------------- Autopatch Tape # 13 -------------------------
; *** Edit 7247 to PAGEM.MAC by LOMARTIRE on 19-Feb-86
; Implement OFN caching 
;------------------------- Autopatch Tape # 12 -------------------------
; *** Edit 7201 to PAGEM.MAC by GRANT on 19-Nov-85
; In MOVDSK, cause page fault while CSKED instead of NOSKED 
; Edit 7164 to PAGEM.MAC by WAGNER on 21-Oct-85
; ***PERFORMANCE*** modify scheduler and called routines to be more efficient 
; Edit 7136 to PAGEM.MAC by LOMARTIRE on 15-Aug-85, for SPR #20860 (TCO 6-1-1525)
; Prevent NSKDIS BUGHLT from LCKOFN call in RELP4 
;[LOTSA]DEV:<MONITOR>PAGEM.MAC.2,  7-Nov-85 16:00:38, Edit by A.ALDERSON
; Insert patch at MOVDSK to prevent cluster hangs--marked by [CFS]
;<6-1-MONITOR.FT6>PAGEM.MAC.2, 12-Aug-85 16:59:27, Edit by WHP4
; FT6 merge
;Stanford changes:
;  ADRTRP bugchk in ADRCMP for tracking down random clobberage
;  PGRTRP will bughlt on page faults in scheduler
;
; UPD ID= 2232, SNARK:<6.1.MONITOR>PAGEM.MAC.266,  18-Jun-85 15:17:23 by MOSER
;MORE 6.1.1447 - FIX A BUG
; UPD ID= 2227, SNARK:<6.1.MONITOR>PAGEM.MAC.265,  17-Jun-85 14:45:03 by MOSER
;TCO 6.1.1447 - ALWAYS CHECK FOR SKDPF1
; UPD ID= 2143, SNARK:<6.1.MONITOR>PAGEM.MAC.264,   5-Jun-85 10:24:45 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 2111, SNARK:<6.1.MONITOR>PAGEM.MAC.263,   3-Jun-85 16:15:12 by LOMARTIRE
;TCO 6.1.1393 - Fix potential DDMP hang
; UPD ID= 2039, SNARK:<6.1.MONITOR>PAGEM.MAC.261,   3-Jun-85 13:34:12 by TBOYLE
;TCO 6.1.1421 - Make SETPT0 error return PAGPTN and have callers either
; retry or BUGHLT depending on the routine.
; UPD ID= 1983, SNARK:<6.1.MONITOR>PAGEM.MAC.259,  16-May-85 17:38:57 by TBOYLE
;Remove 6.1.1297 until a better solution is invented.
; UPD ID= 1952, SNARK:<6.1.MONITOR>PAGEM.MAC.258,   9-May-85 18:17:10 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1905, SNARK:<6.1.MONITOR>PAGEM.MAC.257,   4-May-85 20:37:22 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1855, SNARK:<6.1.MONITOR>PAGEM.MAC.256,  30-Apr-85 15:20:04 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1840, SNARK:<6.1.MONITOR>PAGEM.MAC.255,  29-Apr-85 14:42:19 by GROSSMAN
;TCO 6.1.1347 - Fix FPTAXC to return correct page ownership for XCDSEC pages.
;Also fix indentation at FPTAX2.
;TCO 6.1.1346 - Fix MRPAC% to prevent MDDT from touching PSB special pages in
;XCDSEC, and eventually causing PAGLCK BUGHLT's.
; UPD ID= 1791, SNARK:<6.1.MONITOR>PAGEM.MAC.254,  23-Apr-85 13:06:45 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1736, SNARK:<6.1.MONITOR>PAGEM.MAC.253,   9-Apr-85 11:03:36 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1708, SNARK:<6.1.MONITOR>PAGEM.MAC.252,   1-Apr-85 16:17:56 by TBOYLE
; TCO 6.1.1297 - In MSETPT remove window between RELMP5 and SETPT0.
; UPD ID= 1180, SNARK:<6.1.MONITOR>PAGEM.MAC.251,  11-Dec-84 14:09:40 by LEACHE
;Change EHLJSB conditional to EXTJSB
; UPD ID= 945, SNARK:<6.1.MONITOR>PAGEM.MAC.250,   4-Nov-84 15:26:48 by GLINDELL
;More TCO 6.1.1021 - MDDT is now in XCDSEC - change FPTAXC
; UPD ID= 5017, SNARK:<6.MONITOR>PAGEM.MAC.248,  26-Oct-84 13:26:01 by LEACHE
;Add code (under EHLJSB conditional) for extended JSB
; UPD ID= 5000, SNARK:<6.MONITOR>PAGEM.MAC.247,  24-Oct-84 20:09:57 by GLINDELL
;More TCO 6.1.1021 - small improvements
; UPD ID= 4937, SNARK:<6.MONITOR>PAGEM.MAC.246,  15-Oct-84 13:09:13 by GRANT
;The assembly switch CFSCOD has been eliminated
; UPD ID= 4927, SNARK:<6.MONITOR>PAGEM.MAC.245,  15-Oct-84 12:46:46 by MOSER
;TCO 6.2245 - PERFORMANCE - CALL APSKED IN ALL CASES OF SWPDON
; UPD ID= 4916, SNARK:<6.MONITOR>PAGEM.MAC.244,  10-Oct-84 17:16:18 by GLINDELL
;TCO 6.1.1021 - 6.1 address space
;	IFE FTNSPSRV	;Add FPTA routine for XCDSEC
; UPD ID= 4819, SNARK:<6.MONITOR>PAGEM.MAC.243,  17-Sep-84 10:15:02 by PURRETTA
;Update copyright notice
; UPD ID= 4729, SNARK:<6.MONITOR>PAGEM.MAC.242,  22-Aug-84 14:44:42 by LOMARTIRE
;Add trapping code for use of OFN 0
; UPD ID= 4688, SNARK:<6.MONITOR>PAGEM.MAC.241,  14-Aug-84 15:35:30 by MOSER
;TCO 6.2149 - FIX SECTION MAP LOOPS
; UPD ID= 4608, SNARK:<6.MONITOR>PAGEM.MAC.240,  27-Jul-84 13:33:34 by MCCOLLUM
;TCO 6.2142 - Make MRPAC check for existent section before calling FPTA
; UPD ID= 4264, SNARK:<6.MONITOR>PAGEM.MAC.239,  30-May-84 21:17:35 by MOSER
;TCO 6.2069 - FIX FORK GARBAGE COLLECTOR - FKGC
; UPD ID= 4145, SNARK:<6.MONITOR>PAGEM.MAC.238,  25-Apr-84 21:39:45 by MOSER
;TCO 6.2044 - FIX PAGLCK, PTNIC1, PSBNIC AND PLKMOD. USE FKPSB NOT PSBBAS
; UPD ID= 4072, SNARK:<6.MONITOR>PAGEM.MAC.237,  11-Apr-84 19:20:09 by MOSER
;ADD MOUSETRAP FOR PAGLCK BUGS
; UPD ID= 4068, SNARK:<6.MONITOR>PAGEM.MAC.236,  11-Apr-84 19:04:09 by MOSER
;TCO 6.6023 - REMOVE VESTIGES OF ERCAL IN MONITOR ADD SUPPORT FOR ALL
; ERJMPR AND ERJMPS
; UPD ID= 4065, SNARK:<6.MONITOR>PAGEM.MAC.235,  11-Apr-84 19:00:20 by MOSER
;TCO 6.2008 - REMOVE ILLIND BUGHLT
; UPD ID= 4031, SNARK:<6.MONITOR>PAGEM.MAC.234,  31-Mar-84 20:48:18 by GRANT
;Remove references to FTKLIPA and FTCI
; UPD ID= 4023, SNARK:<6.MONITOR>PAGEM.MAC.233,  31-Mar-84 16:21:16 by PAETZOLD
;TCO 6.2019 - Use ADJSPs
; UPD ID= 3994, SNARK:<6.MONITOR>PAGEM.MAC.232,  28-Mar-84 14:19:12 by MOSER
;TCO 6.2000 - PREVENT SKDPF1 WHEN GARBAGE COLLECTING
; UPD ID= 3845, SNARK:<6.MONITOR>PAGEM.MAC.231,   5-Mar-84 09:46:41 by LOMARTIRE
;TCO 6.1955 - Prevent ASGSW2 BUGHLTs when swap space full - add SMGFUL BUGCHK
; UPD ID= 3544, SNARK:<6.MONITOR>PAGEM.MAC.230,  25-Jan-84 21:00:45 by MURPHY
;Remove TABSEC extern.
; UPD ID= 3262, SNARK:<6.MONITOR>PAGEM.MAC.229,   6-Dec-83 14:39:22 by MOSER
;TCO 6.1875 FIX PAGLCK/ILMNRF BUGHLT
; UPD ID= 3104, SNARK:<6.MONITOR>PAGEM.MAC.228,   7-Nov-83 09:34:19 by MILLER
;TCO 6.1094. Use PGPTR def for CFS resource block address
; UPD ID= 3085, SNARK:<6.MONITOR>PAGEM.MAC.227,  28-Oct-83 18:28:48 by MILLER
;TCO 6.1839 again. Don't look at DRMFRE
; UPD ID= 3069, SNARK:<6.MONITOR>PAGEM.MAC.226,  25-Oct-83 10:15:09 by MILLER
;TCO 6.1839. Don't swap unmodified file page if swapping space is low
; UPD ID= 2904, SNARK:<6.MONITOR>PAGEM.MAC.225,  19-Sep-83 19:44:58 by MILLER
;QCHKH should always succeed
; UPD ID= 2902, SNARK:<6.MONITOR>PAGEM.MAC.224,  17-Sep-83 12:24:42 by MILLER
;One more try
; UPD ID= 2901, SNARK:<6.MONITOR>PAGEM.MAC.223,  17-Sep-83 11:38:09 by MILLER
;TCO 6.1094. NIC6A must determine if CFS action needed
; UPD ID= 2899, SNARK:<6.MONITOR>PAGEM.MAC.222,  16-Sep-83 23:03:02 by MILLER
;TCO 6.1094. Improve code at NTWRTK
; UPD ID= 2876, SNARK:<6.MONITOR>PAGEM.MAC.221,   6-Sep-83 08:54:56 by MILLER
;TCO 6.1094. Add IOX11 errors to QCHK failures
; UPD ID= 2850, SNARK:<6.MONITOR>PAGEM.MAC.220,  19-Aug-83 14:30:06 by MURPHY
;More - Fix FPTA so PCIN0 check works.
; UPD ID= 2841, SNARK:<6.MONITOR>PAGEM.MAC.219,  17-Aug-83 21:38:33 by MURPHY
;More 6.1525 - Separate 0/1 maps.  FPTA mods.
; UPD ID= 2818, SNARK:<6.MONITOR>PAGEM.MAC.218,   9-Aug-83 14:04:48 by PURRETTA
;Change BUG. macro at FPTMSS, ILESCD Bughlt is from PAGEM not PAGFIL.
; UPD ID= 2688, SNARK:<6.MONITOR>PAGEM.MAC.217,  11-Jul-83 13:22:47 by MILLER
;Have CFS QCHK return the allocation if not over quota
; UPD ID= 2631, SNARK:<6.MONITOR>PAGEM.MAC.216,  23-Jun-83 14:06:06 by MURPHY
;Fix FPTMXX check in FPTA.
; UPD ID= 2626, SNARK:<6.MONITOR>PAGEM.MAC.214,  22-Jun-83 16:22:00 by MURPHY
;TCO 6.1700 - Allow SETMPG, SETPT to be called in sched context. SPHYPG.
; UPD ID= 2604, SNARK:<6.MONITOR>PAGEM.MAC.213,  20-Jun-83 16:00:34 by HALL
;TCO 6.1689 - Move fork tables to extended section
;	Reference FKSWP,FKNR,FKINT,FKPGS,FKWSP via DEFSTR
; UPD ID= 2585, SNARK:<6.MONITOR>PAGEM.MAC.212,  15-Jun-83 13:24:54 by MILLER
;TCO 6.1094. Clean up CFS-specific checks in PRLCHK
; UPD ID= 2499, SNARK:<6.MONITOR>PAGEM.MAC.211,  23-May-83 10:41:11 by MURPHY
;TCO 6.1525 - Move SPFLTS table to ext section.
; UPD ID= 2488, SNARK:<6.MONITOR>PAGEM.MAC.210,  18-May-83 15:00:10 by MURPHY
;More of .-1 -- fix up EPGSEC stuff.
; UPD ID= 2469, SNARK:<6.MONITOR>PAGEM.MAC.209,  16-May-83 17:15:39 by MURPHY
;TCO 6.1635 - Use MONENV instead of MONFLG to init flag word for mon.
;TCO 6.1525 - Revise FPTA for general handling of monitor sections.
; UPD ID= 2377, SNARK:<6.MONITOR>PAGEM.MAC.208,  29-Apr-83 14:24:17 by MURPHY
;TCO 6.1635 - Use MONENV instead of MONFLG to init flag word for mon.
; UPD ID= 2287, SNARK:<6.MONITOR>PAGEM.MAC.207,  16-Apr-83 19:14:53 by PAETZOLD
;TCO 6.1557 - TCP Merge
; UPD ID= 2194, SNARK:<6.MONITOR>PAGEM.MAC.206,   7-Apr-83 23:47:26 by MURPHY
;Make some interns.
; UPD ID= 2190, SNARK:<6.MONITOR>PAGEM.MAC.205,   7-Apr-83 22:18:32 by MURPHY
;More of previous - fix up externs.
; UPD ID= 2187, SNARK:<6.MONITOR>PAGEM.MAC.204,   7-Apr-83 21:41:25 by MURPHY
;TCO 6.1601 - Merge PAGFIL into PAGEM and PAGUTL.
; UPD ID= 2108, SNARK:<6.MONITOR>PAGEM.MAC.202,  28-Mar-83 17:50:22 by MILLER
; UPD ID= 2081, SNARK:<6.MONITOR>PAGEM.MAC.201,  24-Mar-83 21:24:27 by MILLER
;Once more, can't nest TRVAR and ASUBR!
; UPD ID= 2079, SNARK:<6.MONITOR>PAGEM.MAC.200,  24-Mar-83 14:07:50 by MILLER
;More on the previous edit
; UPD ID= 2076, SNARK:<6.MONITOR>PAGEM.MAC.199,  24-Mar-83 13:48:09 by MILLER
;TCO 6.1094. Don't hold onto dir. quota resource in NIC62.
; UPD ID= 1965, SNARK:<6.MONITOR>PAGEM.MAC.198,  10-Mar-83 15:31:58 by MURPHY
;Handle second PSB consistently with first.  Change name to FKPS2.
; UPD ID= 1959, SNARK:<6.MONITOR>PAGEM.MAC.197,  10-Mar-83 14:58:15 by MILLER
;TCO 6.1094. More fixed for CFS testing in PREPG
; UPD ID= 1926, SNARK:<6.MONITOR>PAGEM.MAC.196,   7-Mar-83 20:55:19 by CDUNN
;Change defualt so KLIPA code is loaded
; UPD ID= 1910, SNARK:<6.MONITOR>PAGEM.MAC.194,   2-Mar-83 19:12:31 by MILLER
;Onc more
; UPD ID= 1909, SNARK:<6.MONITOR>PAGEM.MAC.193,   2-Mar-83 19:09:44 by MILLER
;TCO 6.1205. Check for valid section correctly
; UPD ID= 1863, SNARK:<6.MONITOR>PAGEM.MAC.192,  23-Feb-83 13:19:11 by MILLER
;TCO 6.1520. Preallocate disk pages.
; UPD ID= 1731, SNARK:<6.MONITOR>PAGEM.MAC.191,   1-Feb-83 14:01:22 by MILLER
;Once more...
; UPD ID= 1729, SNARK:<6.MONITOR>PAGEM.MAC.190,   1-Feb-83 13:42:56 by MILLER
;TCO 6.1094 again. Fix returns from QCHKHW
; UPD ID= 1721, SNARK:<6.MONITOR>PAGEM.MAC.189,  28-Jan-83 15:05:29 by MCINTEE
;REMOVE FTNSPSRV SINCE IT IS NOT USED
; UPD ID= 1702, SNARK:<6.MONITOR>PAGEM.MAC.188,  27-Jan-83 15:54:05 by MILLER
;TCO 6.1094. Add first part of CFS directory allocation support
; UPD ID= 1654, SNARK:<6.MONITOR>PAGEM.MAC.187,  14-Jan-83 08:02:54 by HALL
;TCO 6.1463 - Split PAGEM into three parts
;	Make the following be global: ONRQ,OFRQ,RPCST,AGECHK,DECOR,SWPINW,SWPIN,
;		SWPOT0,CHKRPQ,DASPAG,SWPCHK,DEPG,AGESET,REMFP1,SWPOTK,DELWSC,
;		QCHK,FNDLDA
;	Move data to STG and PROLOG
; UPD ID= 1600, SNARK:<6.MONITOR>PAGEM.MAC.185,  29-Dec-82 13:33:34 by DONAHUE
;TCO 6.1414 - Don't zero TRPDSP at ILRF2
; UPD ID= 1597, SNARK:<6.MONITOR>PAGEM.MAC.184,  29-Dec-82 10:43:12 by DONAHUE
;TCO 6.1192 - Prevent SWPSTL Bugchk's
; UPD ID= 1538, SNARK:<6.MONITOR>PAGEM.MAC.182,  20-Dec-82 17:12:47 by NICHOLS
;Add FTNSPSRV to distinguish between release 6.0 and 6.1
; UPD ID= 1537, SNARK:<6.MONITOR>PAGEM.MAC.181,  20-Dec-82 11:55:28 by MCINTEE
;TCO 6.1423 - Add a new bughlt to hopefully catch ILSPTH problems earlier.
; UPD ID= 1536, SNARK:<6.MONITOR>PAGEM.MAC.180,  19-Dec-82 22:05:44 by CDUNN
;More TCO 6.1127 - Remove SUBTTL from routine PGRSKD such that entire PAGEM
;listing does not claim to be part of PGRSKD...
; UPD ID= 1524, SNARK:<6.MONITOR>PAGEM.MAC.179,   9-Dec-82 10:17:25 by MILLER
;Fix edit 1516. Need to add a NOINT as well
; UPD ID= 1517, SNARK:<6.MONITOR>PAGEM.MAC.178,   7-Dec-82 20:46:56 by COBB
;TCO 5.1.1113 - MSETST - Don't compress out indirect ptrs. -- on behalf of MURPHY
; UPD ID= 1516, SNARK:<6.MONITOR>PAGEM.MAC.177,   7-Dec-82 17:52:15 by MILLER
;TCO 6.1094. Fix code around ASOF6 to lock OFN properly
; UPD ID= 1510, SNARK:<6.MONITOR>PAGEM.MAC.176,   2-Dec-82 15:08:40 by MILLER
;TCO 6.1094. Reverse OFN lock and file state setting in LCKOFN
; UPD ID= 1509, SNARK:<6.MONITOR>PAGEM.MAC.175,   2-Dec-82 14:47:24 by MOSER
;TCO 6.1191 - PREVENT ILPAG1 BUGHLTS
; UPD ID= 1495, SNARK:<6.MONITOR>PAGEM.MAC.174,  30-Nov-82 20:45:05 by GRANT
;TCO 6.1010 - make a better test in MOVCST
; UPD ID= 1481, SNARK:<6.MONITOR>PAGEM.MAC.173,  29-Nov-82 09:44:52 by GRANT
;TCO 6.1010 - Add MOVCST and a few EA.ENTs
; UPD ID= 1471, SNARK:<6.MONITOR>PAGEM.MAC.172,  22-Nov-82 17:50:05 by MILLER
;TCO 6.1094. Handle write =) read access transition
; UPD ID= 1456, SNARK:<6.MONITOR>PAGEM.MAC.171,  17-Nov-82 15:55:50 by MILLER
;Same as before
; UPD ID= 1451, SNARK:<6.MONITOR>PAGEM.MAC.170,  17-Nov-82 08:13:56 by MILLER
;TCO 6.1094. Clear CSWRB during DDMP force out!
; UPD ID= 1448, SNARK:<6.MONITOR>PAGEM.MAC.169,  16-Nov-82 14:21:35 by CDUNN
; More TCO 6.1127 - Make PGRSKD return the size of the origional request
;when it succeeds.
; UPD ID= 1437, SNARK:<6.MONITOR>PAGEM.MAC.168,  11-Nov-82 17:01:33 by MILLER
;TCO 6.1094. Call FRECFS on any ASGOFN failure
; UPD ID= 1436, SNARK:<6.MONITOR>PAGEM.MAC.167,  11-Nov-82 15:13:28 by MILLER
;TCO 6.1094. Add some debug checks to DASOFN
; UPD ID= 1434, SNARK:<6.MONITOR>PAGEM.MAC.166,  11-Nov-82 12:44:06 by MILLER
;TCO 6.1000. Set CST write bit in SETCST
; UPD ID= 1433, SNARK:<6.MONITOR>PAGEM.MAC.165,  10-Nov-82 16:49:52 by MILLER
;TCO 4.1000. Set CST write bit in FRCRMP
; UPD ID= 1431, SNARK:<6.MONITOR>PAGEM.MAC.164,   9-Nov-82 17:19:05 by MILLER
;TCO 6.1094. Add call to FRECFS to CLROFN
; UPD ID= 1423, SNARK:<6.MONITOR>PAGEM.MAC.163,   8-Nov-82 08:48:03 by GRANT
;TCO 6.1010 - Make MULK1 run in section 1.  Change comments in BSMGP.
; UPD ID= 1421, SNARK:<6.MONITOR>PAGEM.MAC.162,   5-Nov-82 15:50:13 by MURPHY
;TCO 5.1.1103 - Optional data on SWPSTL.
; UPD ID= 1419, SNARK:<6.MONITOR>PAGEM.MAC.161,   5-Nov-82 14:52:56 by MILLER
;TCO 6.1094 again.
; UPD ID= 1417, SNARK:<6.MONITOR>PAGEM.MAC.160,   5-Nov-82 09:54:14 by MILLER
;tco 6.1094. Various CFS fixes
; UPD ID= 1407, SNARK:<6.MONITOR>PAGEM.MAC.159,   3-Nov-82 16:33:09 by MILLER
;TCO 6.1094. More CFS changes to DDMP
; UPD ID= 1404, SNARK:<6.MONITOR>PAGEM.MAC.158,   3-Nov-82 06:52:55 by GRANT
;More TCO 6.1010 - make SWPDON run in section 1
; UPD ID= 1399, SNARK:<6.MONITOR>PAGEM.MAC.157,   1-Nov-82 17:22:36 by MILLER
;TCO 6.1094. Fix PREPG to check for CFS status of files
; UPD ID= 1398, SNARK:<6.MONITOR>PAGEM.MAC.156,   1-Nov-82 15:49:57 by MILLER
;TCO 6.1094. Fix GETT1B to get OFN properly
; UPD ID= 1389, SNARK:<6.MONITOR>PAGEM.MAC.155,  28-Oct-82 12:12:20 by MILLER
;TCO 6.1094. More CFS merges
; UPD ID= 1388, SNARK:<6.MONITOR>PAGEM.MAC.154,  27-Oct-82 23:29:45 by CDUNN
;More TCO 6.1127 - Fix typo in last edit
; UPD ID= 1384, SNARK:<6.MONITOR>PAGEM.MAC.153,  26-Oct-82 19:43:31 by CDUNN
;More TCO 6.1127 - Make PGRSKD abuse the RPLQ the right way
; UPD ID= 1382, SNARK:<6.MONITOR>PAGEM.MAC.152,  26-Oct-82 17:43:20 by MILLER
;Fix call to CFSGWL for CFS
; UPD ID= 1381, SNARK:<6.MONITOR>PAGEM.MAC.151,  26-Oct-82 13:38:24 by MILLER
;tco 6.1094. Eliminate need for DDXBI in most cases
; UPD ID= 1378, SNARK:<6.MONITOR>PAGEM.MAC.150,  25-Oct-82 14:32:12 by MILLER
;TCO 6.1094. Add CFS section support
; UPD ID= 1371, SNARK:<6.MONITOR>PAGEM.MAC.149,  22-Oct-82 14:50:14 by MILLER
;Fix to restore state of FILUB broken by TCO 6.1094
; UPD ID= 1368, SNARK:<6.MONITOR>PAGEM.MAC.148,  22-Oct-82 09:14:59 by MILLER
;Put in more CFS conditionals
; UPD ID= 1365, SNARK:<6.MONITOR>PAGEM.MAC.147,  21-Oct-82 17:20:27 by MILLER
;TCO 6.1094. Merge latest CFS changes
; UPD ID= 1360, SNARK:<6.MONITOR>PAGEM.MAC.146,  20-Oct-82 15:39:09 by MILLER
;Check in DDMP for XB locked (for CFS)
; UPD ID= 1359, SNARK:<6.MONITOR>PAGEM.MAC.145,  20-Oct-82 14:17:22 by MILLER
;TCO 6.1094. Merge in CFS changes
; UPD ID= 1352, SNARK:<6.MONITOR>PAGEM.MAC.144,  18-Oct-82 16:40:51 by MILLER
;TCO 6.1094. Add CFS checking to CHKOFN
; UPD ID= 1350, SNARK:<6.MONITOR>PAGEM.MAC.143,  18-Oct-82 13:57:19 by MILLER
;TCO 6.1094. Merge in latest CFS changes
; UPD ID= 1342, SNARK:<6.MONITOR>PAGEM.MAC.142,  14-Oct-82 17:36:44 by MILLER
;TCO 6.1094. Rewrite code at RELMP2 so as not to cause NOSKED page fault
; UPD ID= 1341, SNARK:<6.MONITOR>PAGEM.MAC.141,  14-Oct-82 13:42:19 by MILLER
;TCO 6.1094. CFS fixes
; UPD ID= 1340, SNARK:<6.MONITOR>PAGEM.MAC.140,  14-Oct-82 09:31:55 by MILLER
;Add CFSCOD conditional to prevent assembly errors
; UPD ID= 1339, SNARK:<6.MONITOR>PAGEM.MAC.139,  14-Oct-82 08:33:57 by MCINTEE
;Add . to ANSKP
; UPD ID= 1336, SNARK:<6.MONITOR>PAGEM.MAC.138,  13-Oct-82 17:37:37 by MILLER
;Numerous changes for CFS
; UPD ID= 1329, SNARK:<6.MONITOR>PAGEM.MAC.137,  12-Oct-82 17:24:51 by MILLER
;Fixes to DDMP
; UPD ID= 1328, SNARK:<6.MONITOR>PAGEM.MAC.136,  12-Oct-82 16:49:28 by MILLER
;Don't use DDXLOK in DDMP
; UPD ID= 1327, SNARK:<6.MONITOR>PAGEM.MAC.135,  12-Oct-82 15:59:28 by MILLER
;TCO 6.1094. Set CSWRB in MAPPHP and CGPLK (for BOOT)
; UPD ID= 1324, SNARK:<6.MONITOR>PAGEM.MAC.134,  11-Oct-82 16:56:24 by MILLER
;Fix to DDMP: SKPNWR must be called while NOSKED
; UPD ID= 1323, SNARK:<6.MONITOR>PAGEM.MAC.133,  11-Oct-82 16:13:05 by MCINTEE
;Fix typo two edits ago - OKSKED at BADD-3 should have been NOSKED
; UPD ID= 1315, SNARK:<6.MONITOR>PAGEM.MAC.132,   9-Oct-82 15:26:07 by MILLER
;Fix race in hadnling of XB reverification
; UPD ID= 1310, SNARK:<6.MONITOR>PAGEM.MAC.131,   8-Oct-82 16:54:42 by MILLER
; UPD ID= 1306, SNARK:<6.MONITOR>PAGEM.MAC.130,   8-Oct-82 16:02:26 by MOSER
;TCO 6.1282 - ADD SWPDIR BUGCHK
; UPD ID= 1304, SNARK:<6.MONITOR>PAGEM.MAC.129,   8-Oct-82 15:30:31 by MOSER
;TCO 6.1285 - NOINT BEFORE LOCKING STRLOK IN DDMP
; UPD ID= 1300, SNARK:<6.MONITOR>PAGEM.MAC.128,   8-Oct-82 14:28:29 by MILLER
; UPD ID= 1297, SNARK:<6.MONITOR>PAGEM.MAC.127,   7-Oct-82 17:22:26 by MILLER
;Fix typeo in DDXBI
; UPD ID= 1296, SNARK:<6.MONITOR>PAGEM.MAC.126,   7-Oct-82 14:18:41 by MILLER
;Many, many CFS fixes
; UPD ID= 1290, SNARK:<6.MONITOR>PAGEM.MAC.125,   6-Oct-82 19:37:22 by MILLER
; UPD ID= 1289, SNARK:<6.MONITOR>PAGEM.MAC.124,   6-Oct-82 17:41:33 by CDUNN
;Fix defaults for shared memory placement and size for CI emulator
; UPD ID= 1288, SNARK:<6.MONITOR>PAGEM.MAC.123,   6-Oct-82 13:54:51 by MILLER
;More CFS fixes
; UPD ID= 1285, SNARK:<6.MONITOR>PAGEM.MAC.122,   6-Oct-82 13:32:55 by MILLER
; UPD ID= 1283, SNARK:<6.MONITOR>PAGEM.MAC.121,   5-Oct-82 19:44:35 by MILLER
; UPD ID= 1282, SNARK:<6.MONITOR>PAGEM.MAC.120,   5-Oct-82 18:41:44 by MILLER
; UPD ID= 1281, SNARK:<6.MONITOR>PAGEM.MAC.119,   5-Oct-82 16:08:41 by MILLER
; UPD ID= 1277, SNARK:<6.MONITOR>PAGEM.MAC.118,   4-Oct-82 19:55:00 by MILLER
; UPD ID= 1276, SNARK:<6.MONITOR>PAGEM.MAC.117,   4-Oct-82 16:30:36 by MILLER
; UPD ID= 1275, SNARK:<6.MONITOR>PAGEM.MAC.116,   4-Oct-82 16:20:39 by CDUNN
;Fix CISRV parameters dealing with memory size and location...
; UPD ID= 1268, SNARK:<6.MONITOR>PAGEM.MAC.115,   1-Oct-82 14:24:34 by MILLER
;FIx typeo in previous
; UPD ID= 1267, SNARK:<6.MONITOR>PAGEM.MAC.114,   1-Oct-82 13:45:25 by MILLER
;Allow OF%RDU access to bygpass all CFS restrictons!!
; UPD ID= 1266, SNARK:<6.MONITOR>PAGEM.MAC.113,   1-Oct-82 13:01:18 by MILLER
;Don't allow OF%RDU if file already opened for exclusive access
; UPD ID= 1250, SNARK:<6.MONITOR>PAGEM.MAC.112,  27-Sep-82 23:29:33 by MILLER
;CFS -- Improve DDMP logic somewhat
; UPD ID= 1248, SNARK:<6.MONITOR>PAGEM.MAC.111,  27-Sep-82 22:36:46 by MILLER
;CFS -- Fix ATP1A to preserve T1
; UPD ID= 1246, SNARK:<6.MONITOR>PAGEM.MAC.110,  27-Sep-82 22:23:26 by MILLER
;CFS -- FIx DDMP
; UPD ID= 1228, SNARK:<6.MONITOR>PAGEM.MAC.109,  23-Sep-82 23:48:17 by MILLER
;More CFS fixes
; UPD ID= 1225, SNARK:<6.MONITOR>PAGEM.MAC.108,  23-Sep-82 21:10:14 by MILLER
;Fix DDXBI to map OFN correctly. FIxes to UPDPGS as well
; UPD ID= 1224, SNARK:<6.MONITOR>PAGEM.MAC.107,  23-Sep-82 19:03:04 by MILLER
;Put call to DDXBI under CFSCOD conditional
; UPD ID= 1219, SNARK:<6.MONITOR>PAGEM.MAC.106,  23-Sep-82 10:34:13 by MILLER
;CFS... Handle error cases in ASGOFN
; UPD ID= 1215, SNARK:<6.MONITOR>PAGEM.MAC.104,  22-Sep-82 20:30:15 by MILLER
;More CFS stuff. Make CHKLAC check with other systems
; UPD ID= 1213, SNARK:<6.MONITOR>PAGEM.MAC.103,  21-Sep-82 22:13:36 by MILLER
; UPD ID= 1212, SNARK:<6.MONITOR>PAGEM.MAC.102,  21-Sep-82 20:35:23 by MILLER
;More edits to DDXBI
; UPD ID= 1211, SNARK:<6.MONITOR>PAGEM.MAC.101,  21-Sep-82 20:18:37 by MILLER
;Fix types in DDXBI
; UPD ID= 1209, SNARK:<6.MONITOR>PAGEM.MAC.100,  21-Sep-82 17:09:02 by MILLER
; UPD ID= 1203, SNARK:<6.MONITOR>PAGEM.MAC.99,  20-Sep-82 22:40:52 by MILLER
;Oce more
; UPD ID= 1202, SNARK:<6.MONITOR>PAGEM.MAC.98,  20-Sep-82 22:36:15 by MILLER
;TCO 6.1094. Make code at GETT1B check for SPTFO
; UPD ID= 1201, SNARK:<6.MONITOR>PAGEM.MAC.97,  20-Sep-82 22:02:51 by MILLER
;TCO 6.1094. More fixes to DDMP
; UPD ID= 1196, SNARK:<6.MONITOR>PAGEM.MAC.96,  17-Sep-82 13:51:59 by MILLER
;TCO 6.1271. Check for page fault in scheuler
; UPD ID= 1194, SNARK:<6.MONITOR>PAGEM.MAC.95,  17-Sep-82 12:53:01 by MILLER
;Once more time!
; UPD ID= 1193, SNARK:<6.MONITOR>PAGEM.MAC.94,  17-Sep-82 11:50:10 by MILLER
;Fixes to "force out" and XB swap in for CFS
; UPD ID= 1192, SNARK:<6.MONITOR>PAGEM.MAC.93,  16-Sep-82 23:22:20 by MILLER
;TCO 1.094 Check for swap from disk of OFN in SWPIN
; UPD ID= 1187, SNARK:<6.MONITOR>PAGEM.MAC.92,  15-Sep-82 19:10:22 by MILLER
;Fix to handling of CST write bit
; UPD ID= 1186, SNARK:<6.MONITOR>PAGEM.MAC.91,  15-Sep-82 16:16:07 by MILLER
;Always set CSWRB for an XB page
; UPD ID= 1185, SNARK:<6.MONITOR>PAGEM.MAC.90,  14-Sep-82 22:55:26 by MILLER
;A few more
; UPD ID= 1184, SNARK:<6.MONITOR>PAGEM.MAC.89,  14-Sep-82 22:42:42 by MILLER
;TCO 6.1094. Add some debug stuff for CFS
; UPD ID= 1169, SNARK:<6.MONITOR>PAGEM.MAC.88,  13-Sep-82 13:11:17 by MILLER
;put call to FRECFS under CFSCOD conditional
; UPD ID= 1165, SNARK:<6.MONITOR>PAGEM.MAC.87,  13-Sep-82 07:54:16 by MILLER
; UPD ID= 1162, SNARK:<6.MONITOR>PAGEM.MAC.86,  10-Sep-82 14:34:42 by MILLER
; UPD ID= 1158, SNARK:<6.MONITOR>PAGEM.MAC.85,   9-Sep-82 22:38:15 by MILLER
;TCO 6.1094 again. More fixes for CFS
; UPD ID= 1150, SNARK:<6.MONITOR>PAGEM.MAC.84,   7-Sep-82 10:43:58 by MILLER
;TCO 6.1255. handle DBUGSW GT 2
; UPD ID= 1137, SNARK:<6.MONITOR>PAGEM.MAC.83,   2-Sep-82 20:30:52 by MILLER
;Remove call to CFSORM
; UPD ID= 1135, SNARK:<6.MONITOR>PAGEM.MAC.82,   2-Sep-82 19:50:57 by MILLER
;Once more
; UPD ID= 1131, SNARK:<6.MONITOR>PAGEM.MAC.80,   1-Sep-82 22:52:13 by MILLER
;More CFS fixes to DDMP
; UPD ID= 1127, SNARK:<6.MONITOR>PAGEM.MAC.79,  31-Aug-82 22:42:53 by MILLER
;More CFS fixes
; UPD ID= 1040, SNARK:<6.MONITOR>PAGEM.MAC.78,   4-Aug-82 21:55:57 by MILLER
; UPD ID= 1035, SNARK:<6.MONITOR>PAGEM.MAC.77,   3-Aug-82 21:20:46 by MILLER
; UPD ID= 1034, SNARK:<6.MONITOR>PAGEM.MAC.76,   3-Aug-82 13:16:26 by MILLER
; UPD ID= 1033, SNARK:<6.MONITOR>PAGEM.MAC.75,   3-Aug-82 11:38:45 by MILLER
; UPD ID= 1030, SNARK:<6.MONITOR>PAGEM.MAC.74,   3-Aug-82 08:00:33 by MILLER
; UPD ID= 1028, SNARK:<6.MONITOR>PAGEM.MAC.73,   2-Aug-82 21:39:02 by MILLER
;More CFS fixes
; UPD ID= 1027, SNARK:<6.MONITOR>PAGEM.MAC.72,   2-Aug-82 18:44:28 by MILLER
;TCO 6.1205. Add WSMGR and support routines.
; UPD ID= 1018, SNARK:<6.MONITOR>PAGEM.MAC.70,  30-Jul-82 09:29:39 by PAETZOLD
;More TCO 6.1010 - Fix up the rest the left halves of some CST?X references
;Delete old edit history from before release 5
; UPD ID= 1013, SNARK:<6.MONITOR>PAGEM.MAC.69,  29-Jul-82 22:16:30 by CDUNN
;TCO 6.1199 Fix GETTPD bug in CFS code
; UPD ID= 1007, SNARK:<6.MONITOR>PAGEM.MAC.68,  27-Jul-82 15:12:37 by COBB
;TCO 6.1193 - Put call to NBNSB under SKEDSW conditional
; UPD ID= 998, SNARK:<6.MONITOR>PAGEM.MAC.67,  21-Jul-82 09:07:21 by WALLACE
;TCO 6.1104 - Make sure PC from dynamic invocation of a Dynamic
;    Library is from User Mode and trap to illegal memory read if not
;  Initialize SPTH for CTS Section(s) to say slot has no home
; UPD ID= 966, SNARK:<6.MONITOR>PAGEM.MAC.66,  29-Jun-82 11:32:48 by HALL
;TCO 6.1000 - Support the 2080
;	In address break code, save address
; UPD ID= 958, SNARK:<6.MONITOR>PAGEM.MAC.65,  23-Jun-82 21:33:35 by LEACHE
;Fix comment
; UPD ID= 949, SNARK:<6.MONITOR>PAGEM.MAC.64,  18-Jun-82 13:19:33 by MILLER
; UPD ID= 948, SNARK:<6.MONITOR>PAGEM.MAC.63,  18-Jun-82 13:00:39 by MILLER
;TCO 6.1094. Fix up KC page fault handling to include CFS checks
; UPD ID= 939, SNARK:<6.MONITOR>PAGEM.MAC.62,  16-Jun-82 16:38:07 by WALLACE
;TCO 6.1104 - More Dynamically Linked Libraries - Rather than linking
;  libraries during page faults, untrap and simulate UUO to establish
;  a JSYS context in which library link operations should be performed
; UPD ID= 870, SNARK:<6.MONITOR>PAGEM.MAC.61,   8-Jun-82 03:14:53 by CDUNN
;TCO 6.1127 - Fix cache bug in CISRV support code
; UPD ID= 867, SNARK:<6.MONITOR>PAGEM.MAC.60,   7-Jun-82 13:00:14 by MILLER
; UPD ID= 843, SNARK:<6.MONITOR>PAGEM.MAC.59,   6-Jun-82 12:42:05 by CDUNN
;Fix ILLIND BUGHLT after BUGS.MAC move...
; UPD ID= 835, SNARK:<6.MONITOR>PAGEM.MAC.58,   4-Jun-82 20:51:44 by MURPHY
;Move bugs in-line.
; UPD ID= 824, SNARK:<6.MONITOR>PAGEM.MAC.57,   3-Jun-82 14:04:49 by HALL
;TCO 6.1000 - In XGCCHK, fake a page fail code.
; UPD ID= 820, SNARK:<6.MONITOR>PAGEM.MAC.56,   3-Jun-82 12:54:45 by MILLER
;General bug fixes to CFS code.
; UPD ID= 810, SNARK:<6.MONITOR>PAGEM.MAC.55,   2-Jun-82 10:38:07 by WALLACE
;TCO 6.1105 - Add Canonical Terminal Support
;  Add code for support of CTS Section: Add dispatch routine FPTACT
;  and place it in FPTABL.  Initialize CTS Section entry in MSECTB with
;  a share pointer and initialize the entry for the pointer, in the SPT,
;  with the page, CTSIDX.
;TCO 6.1104 - Add Dynamically Linked Libraries
;  Dynamic Library Invocation from Hard Page Failure Type Illegal Indirect
; UPD ID= 807, SNARK:<6.MONITOR>PAGEM.MAC.54,   1-Jun-82 13:08:34 by PAETZOLD
;More TCO 6.1010 - Fix up yet some more left halves of some CST?X references
; UPD ID= 803, SNARK:<6.MONITOR>PAGEM.MAC.53,   1-Jun-82 11:09:01 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here.
; UPD ID= 769, SNARK:<6.MONITOR>PAGEM.MAC.52,  19-May-82 14:46:27 by HALL
;TCO 6.1000 - Support the 2080
;	In PGUNTD, set AC blocks in new flags word if page fault was from user
; UPD ID= 766, SNARK:<6.MONITOR>PAGEM.MAC.51,  19-May-82 14:17:20 by CDUNN
;TCO 6.1127 - Fix the all references to MAXSEC to be references to EPGSEC.
;Also teach ILFPTE and tranfer table all about dynamic section allocation, all
;code is under  IFN <FTCI!FTKLIPA> conditional.
; UPD ID= 755, SNARK:<6.MONITOR>PAGEM.MAC.50,  15-May-82 12:45:06 by MILLER
;Once more.
; UPD ID= 754, SNARK:<6.MONITOR>PAGEM.MAC.49,  15-May-82 12:41:22 by MILLER
;TCO 6.1094. Random bug fixes
; UPD ID= 737, SNARK:<6.MONITOR>PAGEM.MAC.48,  12-May-82 05:45:19 by CDUNN
;More TCO 6.1127 - After rejection of origional free space scheme, add code
;to support final SCA free space solution.
; UPD ID= 713, SNARK:<6.MONITOR>PAGEM.MAC.47,   9-May-82 18:34:23 by CDUNN
;TCO 6.1127 - Add code for init of extended memory allocator for SCA/CISRV
;Note: this code in included if either FTCI or FTKLIPA is non-zero
; UPD ID= 669, SNARK:<6.MONITOR>PAGEM.MAC.46,  28-Apr-82 12:57:14 by HALL
;TCO 6.1000 - Support the 2080
;	Add KC page fault handler
; UPD ID= 657, SNARK:<6.MONITOR>PAGEM.MAC.45,  22-Apr-82 15:36:48 by HALL
;TCO 6.1000 - Fix rewrite of page fault handler to restore page number at WCPY4.
; UPD ID= 655, SNARK:<6.MONITOR>PAGEM.MAC.44,  20-Apr-82 14:23:37 by PAETZOLD
;More TCO 6.1010 - Fix up left halves of some CST?X references
; UPD ID= 652, SNARK:<6.MONITOR>PAGEM.MAC.43,  18-Apr-82 11:13:10 by HALL
;TCO 6.1096 - Clean up exit from the page fault handler
;Fix up new LCKOFN and ULKOFN to do critical section code correctly (MILLER)
; UPD ID= 644, SNARK:<6.MONITOR>PAGEM.MAC.42,  14-Apr-82 15:22:12 by MILLER
;TCO 6.1094. Add CFS support code.
; UPD ID= 639, SNARK:<6.MONITOR>PAGEM.MAC.41,  14-Apr-82 08:57:58 by HALL
;TCO 6.1000 - Write KC version of CHKPAG
; UPD ID= 628, SNARK:<6.MONITOR>PAGEM.MAC.40,  12-Apr-82 09:35:30 by HALL
;TCO 6.1000 - Support the 2080
;	More work on XGCCHK
;	Remove UBPGF code
;	Put more hard errors under KL conditional
; UPD ID= 623, SNARK:<6.MONITOR>PAGEM.MAC.39,  10-Apr-82 16:04:44 by HALL
;TCO 6.1000 - Support the 2080
;	Make PGRTRP use SZPI for both processors (PROLOG has definition for KL)
;	Make page fault handler use TRVAR
;	Make XGCCHK look for a new label to mark end of page fault handler
;	Add KC-specific code to page fault handler
;	Initialize EPT and UPT to request KL compatible mode in super section
;	Add ENDTV to end of page fault handler
;	More work on XGCCHK for the KC
;	Remove redundant XJRSTF at ILRFU
;	Don't use PTPUB for the KC
;	Don't clear or set PTCACH in LODPPG and ULDPAG
;	Don't have PTCACH in the default pointer
; UPD ID= 612, SNARK:<6.MONITOR>PAGEM.MAC.38,   8-Apr-82 14:43:25 by CDUNN
;Fix more of the great PAGEM disaster. Redefine C%MFPG
; UPD ID= 609, SNARK:<6.MONITOR>PAGEM.MAC.37,   7-Apr-82 17:00:22 by CDUNN
;Fix IFNDEF for CI code and remove LCSSEC references (again)
; UPD ID= 605, SNARK:<6.MONITOR>PAGEM.MAC.36,   7-Apr-82 16:14:06 by COBB
;TCO 5.1743 - Fix simultaneous access bug at CHKACC (missing line prob)
;		pointer
; UPD ID= 612, SNARK:<6.MONITOR>PAGEM.MAC.38,   8-Apr-82 14:43:25 by CDUNN
;Fix more of the great PAGEM disaster. Redefine C%MFPG
;TCO 6.1072 - Make PGRINI's memory scan use its own page fault handler, and
;	add code for the KC
; UPD ID= 609, SNARK:<6.MONITOR>PAGEM.MAC.37,   7-Apr-82 17:00:22 by CDUNN
;Fix IFNDEF for CI code and remove LCSSEC references (again)
; UPD ID= 605, SNARK:<6.MONITOR>PAGEM.MAC.36,   7-Apr-82 16:14:06 by COBB
;TCO 5.1743 - Fix simultaneous access bug at CHKACC (missing line prob)
; UPD ID= 570, SNARK:<6.MONITOR>PAGEM.MAC.35,   1-Apr-82 16:16:20 by CDUNN
;Get back edit for TCO 6.1074, lost in programmer mix up...
; UPD ID= 569, SNARK:<6.MONITOR>PAGEM.MAC.34,   1-Apr-82 15:13:24 by CDUNN
;Add code to support CI emulation. Add code under feature test FTCI which
;is off by default.
; UPD ID= 566, SNARK:<6.MONITOR>PAGEM.MAC.31,  31-Mar-82 16:07:10 by MURPHY
;TCO 6.1074 - Revise build procedures, eliminate PROKL, etc.
;
;TCO 6.1074 - Revise build procedures, eliminate PROKL, etc.
; UPD ID= 384, SNARK:<6.MONITOR>PAGEM.MAC.25,   5-Feb-82 14:04:08 by HALL
;TCO 6.1000 - Support the 2080
;	PGRINI - Remove check for EXADDR and initialization of MMAP for
;	  bit table in section 0
;	SETDST - don't handle model A. DST is always in non-zero section
;	PGRTRP and XGCCHK - remove conversion of model A format flags/PC
; UPD ID= 324, SNARK:<6.MONITOR>PAGEM.MAC.24,  19-Jan-82 12:21:26 by MURPHY
;DITTO
; UPD ID= 317, SNARK:<6.MONITOR>PAGEM.MAC.22,  18-Jan-82 17:34:27 by MURPHY
;TCO 5.1686 - reduce SPC0 threshold to prevent SPT full situations.
; UPD ID= 310, SNARK:<6.MONITOR>PAGEM.MAC.21,  18-Jan-82 10:14:02 by PAETZOLD
;TCO 5.1682 - change ILSN to generate ILLX05 as TWWRT is not valid
;TCO 5.1683 - fix GETTPD to generate correct error dispatch for
;	      non-existant section references
; UPD ID= 282, SNARK:<6.MONITOR>PAGEM.MAC.20,   8-Jan-82 13:37:49 by MURPHY
;More 5.1616 - don't wait in RELP3.
; UPD ID= 270, SNARK:<6.MONITOR>PAGEM.MAC.19,   2-Jan-82 13:09:47 by HALL
;A few comments
; UPD ID= 227, SNARK:<6.MONITOR>PAGEM.MAC.18,   2-Dec-81 13:35:57 by MURPHY
;TCO 5.1623
;Change GNPBAS to BALSHC around NICCKS (old fix).  Get rid of GNPBAS completely.
; UPD ID= 226, SNARK:<6.MONITOR>PAGEM.MAC.17,   1-Dec-81 11:20:20 by GRANT
;TCO 5.1621 - fix cause of MONPDL BUGHLT in SETP6 routine
; UPD ID= 223, SNARK:<6.MONITOR>PAGEM.MAC.16,  30-Nov-81 14:45:22 by MURPHY
;fix previous
; UPD ID= 220, SNARK:<6.MONITOR>PAGEM.MAC.15,  30-Nov-81 08:41:07 by PAETZOLD
;More TCO 6.1010 - CST3 linked list references
; UPD ID= 217, SNARK:<6.MONITOR>PAGEM.MAC.14,  23-Nov-81 13:11:37 by MURPHY
;TCO 5.1616 - Check page locked in core in MOVDSK and elsewhere.
; UPD ID= 209, SNARK:<6.MONITOR>PAGEM.MAC.11,  16-Nov-81 17:38:30 by MURPHY
;TCO 5.1615 - call SETPCV at ILRF
; UPD ID= 183, SNARK:<6.MONITOR>PAGEM.MAC.10,   4-Nov-81 10:44:11 by GRANT
;TCO 5.1605 - Fix bug in SWPEX6
; UPD ID= 176, SNARK:<6.MONITOR>PAGEM.MAC.9,  31-Oct-81 14:41:58 by PAETZOLD
;More TCO 6.1010 - CST3 References
; UPD ID= 153, SNARK:<6.MONITOR>PAGEM.MAC.8,  21-Oct-81 14:25:10 by PAETZOLD
;TCO 5.1591 - Have MSETPT unlock the correct OFN when cleaning up during
; failure code
; UPD ID= 145, SNARK:<6.MONITOR>PAGEM.MAC.7,  19-Oct-81 16:14:41 by COBB
;TCO 6.1029 - CHANGE SE1CAL TO EA.ENT
; UPD ID= 110, SNARK:<6.MONITOR>PAGEM.MAC.6,  15-Oct-81 22:43:26 by PAETZOLD
;TCO 5.1574 - Check for overflowing the SPT SHARE COUNT before
; incrementing it
; UPD ID= 89, SNARK:<6.MONITOR>PAGEM.MAC.5,   4-Oct-81 23:51:41 by PAETZOLD
;TCO 5.1554 - ADD CODE TO TRACE SPTLKB STUFF UNDER CONTROL OF SPTDSW
; UPD ID= 77, SNARK:<6.MONITOR>PAGEM.MAC.4,  17-Sep-81 01:49:49 by PAETZOLD
;More TCO 6.1010 - Change mask CST0, CST1 references
; UPD ID= 70, SNARK:<6.MONITOR>PAGEM.MAC.3,  15-Sep-81 16:00:40 by PAETZOLD
;More TCO 6.1010 - Change non mask CST0, CST1, CST2 references
; UPD ID= 68, SNARK:<6.MONITOR>PAGEM.MAC.2,  14-Sep-81 22:50:07 by PAETZOLD
;TCO 6.1010 - MOVE CSTS TO CSTSEC - FILL CSTX TABLES WITH DUMMY ENTRIES
; UPD ID= 141, SNARK:<5.MONITOR>PAGEM.MAC.44,   3-Sep-81 08:40:08 by PAETZOLD
;Add semicolins to comments in previous edit
; UPD ID= 139, SNARK:<5.MONITOR>PAGEM.MAC.43,   2-Sep-81 16:48:37 by HALL
;Comments
; UPD ID= 135, SNARK:<5.MONITOR>PAGEM.MAC.42,   1-Sep-81 17:31:07 by HALL
;Comments
; UPD ID= 111, SNARK:<5.MONITOR>PAGEM.MAC.41,  20-Aug-81 17:28:03 by MURPHY
;TCO 5.1006X - Set OFNWRB in RELADR to prevent DEAUNA bugchks.
;TCO 5.1007X - Fix reference to flags word at PGUNT0.
; UPD ID= 74, SNARK:<5.MONITOR>PAGEM.MAC.40,  24-Jul-81 16:01:55 by SCHMITT
;TCO 5.1433 - Insert page map and section map loop checking in MSETST & SETPT0
; UPD ID= 47, SNARK:<5.MONITOR>PAGEM.MAC.39,  17-Jul-81 16:19:45 by MURPHY
;DITTO - SKIP/NOSKIP RETURN FROM MSETPT
; UPD ID= 29, SNARK:<5.MONITOR>PAGEM.MAC.38,  13-Jul-81 15:23:16 by MURPHY
;YET MORE TCO 5.1398
; UPD ID= 26, SNARK:<5.MONITOR>PAGEM.MAC.37,  13-Jul-81 13:18:20 by MURPHY
;MORE TCO 5.1398
; UPD ID= 15, SNARK:<5.MONITOR>PAGEM.MAC.36,  10-Jul-81 09:19:28 by MOSER
;TCO 5.1406 - IF WCPY IS CALLED FOR A LOCKED PAGE GENERATE AN ILLEGAL MEMORY
; WRITE.
; UPD ID= 9, SNARK:<5.MONITOR>PAGEM.MAC.35,   9-Jul-81 17:13:22 by MURPHY
;TCO 5.1398 - SEPARATE DISK FULL FROM OVER QUOTA, ETC.
; UPD ID= 2187, SNARK:<5.MONITOR>PAGEM.MAC.34,  11-Jun-81 15:55:55 by MURPHY
;CHANGE TQNx TO TMNx REFLECTING CHANGE IN MACSYM
; UPD ID= 1892, SNARK:<5.MONITOR>PAGEM.MAC.33,  27-Apr-81 13:17:01 by GRANT
;Undo REPEAT 0 around GETCPA
; UPD ID= 1887, SNARK:<5.MONITOR>PAGEM.MAC.32,  24-Apr-81 17:33:53 by MURPHY
;TCO 5.1298 - COUNT INDIRECT POINTERS SEEN IN GETTPD AND ELSEWHERE
; UPD ID= 1611, SNARK:<5.MONITOR>PAGEM.MAC.31,  27-Feb-81 18:23:20 by MURPHY
;ASOFN, BUG FROM OF%RDU
; UPD ID= 1601, SNARK:<5.MONITOR>PAGEM.MAC.30,  27-Feb-81 09:51:59 by FLEMMING
;TCO 5.1265 - fix RMAP returning wrong access information
; UPD ID= 1561, SNARK:<5.MONITOR>PAGEM.MAC.29,  13-Feb-81 16:44:11 by MURPHY
;NEW OPENF MODE - OF%RDU - READ-UNRESTRICTED
; UPD ID= 1475, SNARK:<5.MONITOR>PAGEM.MAC.28,  22-Jan-81 12:16:37 by MURPHY
;Fix PM%ABT in new page case
; UPD ID= 1447, SNARK:<5.MONITOR>PAGEM.MAC.27,  15-Jan-81 15:59:22 by FLEMMING
;add code for SMAP/RSMAP
; UPD ID= 1371, SNARK:<5.MONITOR>PAGEM.MAC.26,  22-Dec-80 08:52:24 by GRANT
;TCO 5.1217 - Fix bug in YESBAT
; UPD ID= 1311, SNARK:<5.MONITOR>PAGEM.MAC.25,  24-Nov-80 17:36:57 by MURPHY
;BUG - PREPG1 not returning page number in T1
; UPD ID= 1295, SNARK:<5.MONITOR>PAGEM.MAC.24,  19-Nov-80 12:22:18 by MURPHY
;IN SECMAP - REMEMBER FORKX OF FORK OWNING PRIVATE PAGE
; UPD ID= 1220, SNARK:<5.MONITOR>PAGEM.MAC.23,   2-Nov-80 11:48:23 by HALL
;MORE ON TCO 5.1180 - REMOVE SE1CAL'S FROM SWPOML,GCCOR,REMFPA,DDMP --
;MADE POSSIBLE BY RUNNING SCHED0, GSMDX, AND CHKR IN SECTION 1
; UPD ID= 1219, SNARK:<5.MONITOR>PAGEM.MAC.22,  31-Oct-80 16:58:19 by HALL
;MORE ON TCO 5.1180 - MAKE REMFPA ENTER SECTION 1 BECAUSE EXEC0 CALLS IT
;	VIA SETMPG
; UPD ID= 1209, SNARK:<5.MONITOR>PAGEM.MAC.21,  29-Oct-80 14:24:37 by MURPHY
;DITTO
; UPD ID= 1206, SNARK:<5.MONITOR>PAGEM.MAC.20,  28-Oct-80 17:35:14 by MURPHY
;FIX VERY OLD BUG WITH PM%ABT (IN REMFP1)
; UPD ID= 1200, SNARK:<5.MONITOR>PAGEM.MAC.19,  26-Oct-80 16:59:30 by HALL
;MORE ON TCO 5.1180 -- ADD RETURN TO SETDST
; UPD ID= 1194, SNARK:<5.MONITOR>PAGEM.MAC.18,  25-Oct-80 12:14:45 by HALL
;TCO 5.1180 - MOVE DST TO NON-ZERO SECTION
;	MAKE ALL CALLERS OF GDSTX EXPECT IT TO RETURN AN ADDRESS RATHER THAN AN
;		OFFSET
;	GCCOR - ENTER SECTION 1
;	DDMP - ENTER SECTION 1
;	ADDED SETDST TO SET UP PAGE MAP AND DSTLOC
;	TEMPORARILY MAKE SWPOML DO SE1CAL
; UPD ID= 1137, SNARK:<5.MONITOR>PAGEM.MAC.17,   7-Oct-80 11:50:55 by HALL
;ASFSB - CHANGE ACVAR TO SAVEAC
; UPD ID= 1104, SNARK:<5.MONITOR>PAGEM.MAC.16,   2-Oct-80 09:28:17 by MURPHY
;DITTO
; UPD ID= 1089, SNARK:<5.MONITOR>PAGEM.MAC.15,   1-Oct-80 12:13:57 by MURPHY
;FIX ACVAR
; UPD ID= 1013, SNARK:<5.MONITOR>PAGEM.MAC.14,  13-Sep-80 16:11:29 by HALL
;MAKE PGRTRP RUN IN SECTION 1
;	CLEAR LEFT HALF OF INDEX REGISTERS
;	DO SECTION-RELATIVE JRST AT TRPRST
;	IN XGCCHK, START PROCESS AT PGRTRP IN SECTION 1
; UPD ID= 990, SNARK:<5.MONITOR>PAGEM.MAC.13,   4-Sep-80 18:42:53 by ENGEL
;ADD TABSEC AS SECTION FOR MONITOR TABLES
; UPD ID= 922, SNARK:<5.MONITOR>PAGEM.MAC.12,  20-Aug-80 09:40:34 by MURPHY
;Use open NOSKED/OKSKED in MULK1 because runs at interrupt level
; UPD ID= 912, SNARK:<5.MONITOR>PAGEM.MAC.11,  18-Aug-80 21:41:52 by MURPHY
;NOSKD1 required in MULK1 to prevent possuble SUMNR1, SUMNR2 bugchks
; UPD ID= 898, SNARK:<5.MONITOR>PAGEM.MAC.10,  14-Aug-80 10:36:21 by LYONS
;tco 5.1062 - change swppsb, swppt, swpptp, swpupt into delayed bugchk
; UPD ID= 880, SNARK:<5.MONITOR>PAGEM.MAC.9,  12-Aug-80 16:16:33 by MURPHY
;Private page count; fix INTDF checks at ILRF
; UPD ID= 810, SNARK:<5.MONITOR>PAGEM.MAC.8,  30-Jul-80 10:53:25 by MURPHY
;ADD CHECK OF WEFLAG - 1=DON'T WRITE-PROTECT RES MON
; UPD ID= 809, SNARK:<5.MONITOR>PAGEM.MAC.7,  30-Jul-80 10:34:49 by HALL
;IN PGRINI, IF DBUGSW=1, WRITE-PROTECT THE RESIDENT CODE
; UPD ID= 614, SNARK:<5.MONITOR>PAGEM.MAC.6,   6-Jun-80 16:56:18 by KONEN
;TCO 5.1061 - Add call to STROFL from DDMP to see if structure off-line
; UPD ID= 510, SNARK:<5.MONITOR>PAGEM.MAC.5,   7-May-80 20:47:07 by ENGEL
;ADD THE LCS SECTIN DEFINITIONS
; UPD ID= 420, SNARK:<5.MONITOR>PAGEM.MAC.4,  11-Apr-80 13:50:55 by HALL
;CHANGES TO WRITE-PROTECT THE RESIDENT MONITOR:
;	ADD RSDAT PSECT TO PGRINI (CREATE ENTRY IN MMAP, LOCK PAGE IN
;	MEMORY, AND ADD RSDAT TO DDT'S ALTERNATE MAP)
; UPD ID= 407, SNARK:<5.MONITOR>PAGEM.MAC.3,   3-Apr-80 16:15:37 by HALL
;CHANGES TO WRITE-PROTECT THE RESIDENT MONITOR:
;	NEW ENTRY TO PGRIGR TO SET UP MAP WRITE-PROTECTED
;	PGRINI - SET UP RSCOD WRITE-PROTECTED IF DBUGSW IS 2
;	MAKE SWPMWP WRITE-PROTECT RSCOD, TOO

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT  (C)  DIGITAL  EQUIPMENT  CORPORATION  1976, 1985.
;ALL RIGHTS RESERVED.


	SEARCH PROLOG

	TTITLE PAGEM

EXTN <MEMSTR,CLRMPE,NXTAJB,CLNXMF,KIPFS,PFSA1,SETPFH,LCKOFN>  ;[7247]

DEFAC (FX,Q3)			;FORK INDEX


SCWOPR==SC%WHL!SC%OPR

;PARAMETERS FOR WORKING SET ADDRESS CACHE

WSCIDX==177000			;INDEX INTO CACHE - LOW ORDER 7 PAGE NUMBER BITS
WSCASS==37600000		;ASSOCIATIVE BITS - SECTION AND HIGH ORDER PAGE
WSCUSR==200			;USER/EXEC MODE BIT
WSCVAL==400			;VALID BIT
WSCFLD==777			;ONE FIELD IN CACHE

WSCNBF==<WID WSCFLD>		;SIZE OF FIELD
WSCNCW==:1B<35-<WID WSCIDX>>		;NUMBER OF CACHE WORDS

WSCVAM==0			;VALID MASK
WSCMS1==0			;LOW ORDER 1'S MASK
..X2==1B<WSCNBF-1>		;LEFT JUSTIFIED LOW ORDER 1
..X1==<WSCVAL>B<WSCNBF-1>	;LEFT JUSTIFIED WSCVAL
REPEAT ^D36/WSCNBF,<		;REPEAT FOR NUMBER FIELDS IN WORD
  WSCVAM=WSCVAM!..X1		;PUT VALID BIT IN ALL FIELDS
  WSCMS1=WSCMS1!..X2		;PUT 1 IN ALL FIELDS
  ..X1=..X1_-WSCNBF		;RIGHT SHIFT ONE FIELD
  ..X2=..X2_-WSCNBF
   >

SECADR==CPTPGA+USECTO		;WHERE TO FIND SECTION POINTER
;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,PAGEM,SOFT,<MSCANP - ILLEG IDENT>,,<

Cause:	A routine has been called to scan the pages of a file to find
	the first non-zero page. Its arguments include an OFN
	associated with the file. The BUGHLT occurs because the caller
	has passed a 0.
>)
	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 MRPACF		;GET ACCESS DATA
	POP P,2
	RET
;READ PAGE ACCESSIBILITY
; 1/ IDENT
; RETURNS +1 WITH ACCESS INFORMATION IN RPACS FORMAT IN 1

;MRPACS - GENERAL VERSION
;MRPACF - "FAST" VERSION, DOESN'T TRACE INDIRECT PTRS AND DOESN'T GO NOSKED

MRPACF:	SAVEAC <Q1,Q2,P1>
	SETZ Q2,		;INIT ACCESS
	SETO P1,		;FLAG NO INDIRECT TRACING
	JRST MRP1

MRPACS::SAVEAC <Q1,Q2,P1>
	SETZB Q2,P1		;NO PTR AND NO INDIRECT COUNT
	NOSKED
	NOINT
MRP1:	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,PAGEM,SOFT,<MRPACS - Illegal PTN>,,<

Cause:	A routine has been called to determine the possible access to a
	page. Its arguments include the SPT index for the page table
	associated with the page. The BUGHLT occurs because the caller has
	passed a 0.
>)
	CALL SETXB1		;MAP PT
	HLRZ T3,T1
	HRRZS T1
	SKIPL P1		;Are we NOSKED?
	IFNSK.			;If so
	 CAIL T3,NOFN		;And is this an OFN?
	 ANSKP.			;If so
	  OKSKED		;Allow scheduling for a bit
	  MOVE T3,CXBPGA(T1)	;Get pointer
	  NOSKED
	ELSE.
	 MOVE T3,CXBPGA(T1)	;GET PTR
	ENDIF.
	SKIPN Q2		;FIRST PTR?
	MOVEM T3,Q2		;YES, SAVE IT
	JUMPE T3,MRP2		;JUMP IF EMPTY
	TXNN T4,PTWR		;ACCUMULATING COMPOSITE STILL HAVE WRITE SET?
	TXOA T3,PTCPY		;NO, IGNORE ALL FUTURE COPY-ON-WRITE PTRS
	TXC T3,PTCPY		;'AND' 0S FOR THIS BIT
	ANDM T3,T4		;COMPUTE COMPOSIT ACCESS
	JUMPL P1,MRP2		;DONE IF NOT TRACING IND PTRS
	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:	IFGE. P1		;If NOSKED above
	 OKINT
	 OKSKED
	ENDIF.
	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 PAGER NOTICE
	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
	TXZ T1,1B0		;CANNOT ASK ABOUT A USER ADDRESS
	HLRZ T2,T1		;GET SECTION NUMBER AND ILLEGAL BITS
	CAIG T2,HGHSEC		;POSSIBLE SECTION?
	 SKIPN MSECTB(T2)	;YES. DOES IT EXIST?
	  JRST MRPC1		;NO. CAN'T ACCESS IT THEN

	CAIE T2,XCDSEC		; Extended code section?
	IFSKP.			;   Yes.
	  CAML T1,[XCDSEC,,PPVAR] ;IN PPVAR AREA?
	  CAMLE T1,[XCDSEC,,PPVARZ!777]	;IS IT?
	  TRNA			;NO, CHECK OTHER PLACES
	  JRST MRPC1		;YES, SAY NO ACCESS
	  CAML T1,[XCDSEC,,PSSPSA] ;IN PSB SPECIAL PAGES?
	  CAML T1,[XCDSEC,,PSSPEA] ;SETPT ETC.
	  JRST MRPC4		;NO, KEEP CHECKING
	  JRST MRPC1		;YES, SAY NO ACCESS
	ENDIF.

	SKIPE T2		;YES. MONITOR PC SECTION?
	CAIN T2,MSEC1		;OR THIS ONE?
	TLZA T1,-1		;YES. PROCESS MONITOR PC SECTION
	JRST MRPC4		;NO. CHECK OUT ADDRESS THEN
	CAIL T1,PPVAR		;IN PPVAR AREA?
	CAILE T1,PPVARZ!777	;IS IT?
	CAIA			;NO, CHECK OTHER PLACES
	JRST MRPC1		;YES, SAY NO ACCESS
	CAIL T1,PSSPSA		;IN PSB SPECIAL PAGES?
	CAIL T1,PSSPEA		;SETPT ETC.
	CAIA			;NO, KEEP CHECKING
	JRST	MRPC1		;YES, SAY NO ACCESS
MRPC4:	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 PHYSICAL PAGE INTO MAP
; T1/ Physical page number
; T2/ Virtual address of destination page and access
;	CALL SPHYPG
;Return +1: Failure, can't unmap previous contents.
;	+2: OK
;May be called at scheduler or JSYS level.
;Destination map must be accessible.  Source page must be accessible
;if referenced at scheduler level; must be locked if not at scheduler
;level.

SPHYPG::EXCH T1,T2
	MOVE T3,T1		;GET ACCESS BITS
	TXZ T3,VMADR
	TXZ T1,<^-VMADR>	;FLUSH THEM FROM DEST ADDRESS
	CALL FPTA		;CONVERT TO IDENT
	; ..

;Same as above, except takes ident and access bits as follows:
; T1/ Destination ID
; T2/ Source ID
; T3/ Access bits
;	CALL SPHYPT
;Return +1: Failure, couldn't unmap previous page.
;	+2: Success.

SPHYPT::ASUBR <DEST,SRC,ACCB,AT4>
	HLRZ T4,DEST
	CAIGE T4,NOFN		;SOURCE MUST NOT BE OFN
	BUG.(HLT,PPGOFN,PAGEM,SOFT,<SPHYPT - Destination is OFN>,<<T4,OFN>>,<

Cause:	SPHYPG or SPHYPG has been given an destination argument which
	is an OFN.  This type of mapping may only be done into
	non-file page tables.

Data:	OFN - The OFN.
>)
	SKIPE INSKED
	IFSKP.
	  CALL SETCPT		;(T1) MAP THE PAGE TABLE
	  CALL RELMP5		;(T1,T2,T3) RELEASE OLD MAPPING
	ELSE.
	  CALL SETSPG		;(T1) MAP THE PAGE TABLE
	  CALL SCHRPG		;(T1)
	  IFNSK.
	   SETOM SRC		;NOTE FAILURE
	   JRST SPHYPX		;QUIT
	  ENDIF.
	ENDIF.
	CALL CCLRPT		;(T1) DO APPROPRIATE HW CLEAR
	MOVE T2,SRC
	JUMPE T2,SPHYPX		;DONE IF NO NEW PAGE TO MAP
	CAMLE T2,NHIPG		;LEGAL PAGE?
	IFSKP.
	  LOAD T3,PLKCNT,+T2	;BE SURE PAGE ALREADY LOCKED
	  CAIGE T3,1
	ANSKP.
	ELSE.
	BUG.(HLT,SPGNLK,PAGEM,SOFT,<SPHYPG - Page not locked>,<<T2,PAGE>>,<

Cause:	SPHYPG or SPHYPT requires a locked physical page to map.
	The argument given is either not a physical core page or
	is not locked.

Data:	PAGE - Offending argument.
>)
	ENDIF.
	INCR PLKCNT,+T2		;BUMP LOCK COUNT
	IOR T2,IMMPTR		;MAKE A PTR
	MOVE T3,ACCB		;SET ACCESS
	TXNN T3,PA%WT		;WRITE ACCESS WANTED?
	TXZA T2,PTWR		;NO
	TXO T2,PTWR		;YES
SPHYPX:	HRRZ T1,DEST
	SKIPE INSKED
	IFSKP.
	  MOVEM T2,CPTPGA(T1)	;SET IT
	  CALL RELCPT		;() RELEASE PT MAPPING
	ELSE.
	  MOVEM T2,CSWPGA(T1)
	  CALL RELSPG		;() RELEASE PT MAPPING
	ENDIF.
	SKIPGE SRC
	RET			;FAIL RETURN
	RETSKP

	ENDAS.

;CLEAR APPROPRIATE HARDWARE PAGE MAPS
; T1/ Destination ID
;	CALL CCLRPT
;Return +1 always.

CCLRPT:	SAVEAC <T2>
	HLRZ T2,T1		;LOOK AT PTN
	CAME T2,MMSPTN		;MONITOR VA?
	IFSKP.
	  CALL MONCLA		;YES
	ELSE.
	  CALL PGRCLD		;NO, CLEAR ALL
	ENDIF.
	RET
;SET PAGE IN MONITOR OR USER MAP (INTERNAL MONITOR CALL)
; AC1/ OFN,,PN   (OFN IS SPT POINTER, PN IS 0-777)
; AC2/ VIRTUAL ADDRESS OF PAGE (NOT PAGE NUMBER)
;       0    1 => USER MAP, 0 => MONITOR MAP
;	1-17 - ACCESS

SETMPG::SKIPN INSKED		;SCHED CONTEXT?
	IFSKP.
	  CALL VERPT		;MAKE SURE SOURCE NOT DISMOUNTED
	   RET
	  EXCH T1,T2		
	  MOVE T3,T1		;GET ACCESS BITS
	  TXZ T3,VMADR
	  TXZ T1,<^-VMADR>	;FLUSH THEM FROM DEST ADDRESS
	  CALL FPTA		;(T1) CONVERT ADR TO IDENT
	  CALLRET SPSCH		;(T1,T2,T3) SCHED-LEVEL SET PAGE
	ENDIF.
	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
	HLLZ T3,ADR		;GET ACCESS BITS
	CALL RELMP5		;RELEASE OLD CONTENTS
	SKIPGE ADR		;CHANGING EXEC OR USER MAP?
	IFSKP.
	  CALL MONCLA		;EXEC, CLEAR EXEC SCRATCHPAD
	ELSE.
	  CALL PGRCLD		;USER, CLEAR ALL PAGE TABLE
	ENDIF.
	SKIPE T2,SID		;DELETING ONLY?
	IFSKP.
	  MOVE T1,ADR		;YES, CLEAR VA FROM WS CACHE
	  ANDX T1,TWUSR+777777 	;CLEAR ACCESS BITS
	  CALL DELWSC
	  MOVE T1,DEST		;RESTORE DEST ID
	  CALLRET MSETM2
	ENDIF.
	MOVE T1,DEST
	HLLZ T3,ADR		;GET ACCESS BITS
	CALL SETPT0		;SET NEW CONTENTS
	 CALL MSEINT		;FAILED, INTERRUPT
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

;FAILURE TO SET PAGE, GENERATE INTERRUPT

MSEINT:	CAIN T1,PAGPTN		;BUGHLT IF PAGE TABLE ENTRY WAS NONZERO.
	BUG.(HLT,PTNON0,PAGEM,SOFT,<SETPT0 - Previous contents NON-0>,,<

Cause:	A routine has been called to change the map for a page of a
	process. The caller is expected to have unmapped any previous
	contents of the page. The BUGHLT indicates that the page table
	contains a non-zero pointer for the page.
>)
	MOVEI 2,.ICILI		;ERROR CHANNEL
	CAIN 1,IOX11		;QUOTA EXCEEDED?
	MOVEI 2,.ICQTA		;YES - USE THIS CHL
	MOVE 1,2		;COPY CHL TO T1
	CALL PSIRQ0		;REQUEST PSI
	CHKINT			;GET IT SEEN
	RET
;SET MAP IN SCHEDULER CONTEXT.
;The following must be true:
; 1. The destination map must be in core (locked or known to be
;	present like MMAP.)
; 2. The source page must be in core (locked or know to be
;	present.)
; 3. The destination should have no current mapping, or should
;	have only an indirect pointer such as would be setup herein.
;An indirect pointer will be setup if the ident is a PTN.PN; a
; shared pointer if the ident is SPTN.

;At this point:
; T1/ Destination ident
; T2/ Source ident
; T3/ Access
;Verification, check for dismounted OFN, etc. already done.

SPSCH:	ASUBR <DEST,SRC,ACCB>
	SAVEAC <Q1,Q2,P1>
	HLRZ T1,T1
	CAIGE T1,NOFN		;DEST CAN'T BE FILE
	BUG.(HLT,SPSCHF,PAGEM,SOFT,<SPSCH - Destination is file>,<<T1,ID>>,<

Cause:	A file page identifier has been passed to SPSCH as the destination
	page.

Data:	ID - OFN.PN of offending identifier
>)
	CALL SETSPG		;(T1) - MAP DEST PT
	MOVE T1,DEST
	CALL SCHRPG		;RELEASE OLD MAPPING
	 JRST SPSCHX		;FAILED
	CALL CCLRPT		;(T1) CLEAR HW PT
	SKIPN SRC		;NEW SOURCE?
	JRST SPSCHX		;NO
	HRRZ T2,SRC
	HLRZ Q1,SRC		;CHECK SOURCE
	IFE. Q1
	  MOVE Q2,SHRPTR	;BUILD SHARE PTR
	  STOR T2,SPTX,Q2
	ELSE.
	  MOVE Q2,INDPTR
	  STOR Q1,SPTX,Q2
	  STOR T2,IPPGN,Q2	;BUILD INDIRECT PTR
	ENDIF.
	TXNN T3,PA%WT		;WRITE ACCESS?
	TXZA Q2,PTWR		;NO
	TXO Q2,PTWR
	HRRZ T1,DEST		;DEST PAGE NUMBER
	MOVEM Q2,CSWPGA(T1)
	LOAD T1,SPTX,Q2		;GET SPT USED
	CALL UPSHR		;(T1) BUMP SHARE COUNT
SPSCHX:	CALLRET RELSPG		;() RELEASE PT MAPPING

	ENDAS.
;LOCAL ROUTINE TO RELEASE PREVIOUS MAPPING
; T1/ DESTINATION IDENT, ALREADY MAPPED INTO CSWPGA
;RETURN +1: FAILED, CAN'T HANDLE AT SCHED LEVEL
;	+2: OK

SCHRPG:	SAVEAC <Q1>
	HRRZ Q1,T1
	MOVE T2,CSWPGA(Q1)	;GET PREVIOUS MAPPING
	IFN. T2
	  LOAD T3,PTRCOD,T2	;CHECK TYPE
	  CAIE T3,IMMCOD	;IMMEDIATE
	  IFSKP.
	    LOAD T3,STGADR,T2	;YES, CHECK ADDRESS
	    TXNE T3,NCORTM	;IN CORE?
	    JRST RTN		;NO, CAN'T HANDLE IT HERE
	    MOVE T4,@CST2X+T3	;CHECK OWNER ID
	    CAMN T4,T1		;THIS MAP?
	    JRST RTN		;YES, CAN'T HANDLE IT HERE
	    LOAD T4,PLKCNT,+T3	;CHECK CURRENT LOCK COUNT
	    SOJLE T4,RTN	;GIVE UP IF NOT STILL LOCKED
	    STOR T4,PLKCNT,+T3
	  ELSE.			;OTHERWISE, SHARE OR INDIRECT PTR
	    LOAD T3,SPTX,T2	;SPT INDEX
	    LOAD T4,SPTSHC,(T3)	;GET SHARE COUNT
	    SOJLE T4,RTN	;GIVE UP IF NOT STILL SHARED
	    STOR T4,SPTSHC,(T3)
	  ENDIF.
	  SETZM CSWPGA(Q1)	;FLUSH OLD PTR
	ENDIF.
	RETSKP
;MULTIPLE SET PAGE IN MAP - SAME AS ABOVE EXCEPT
; 3/ NUMBER OF SUCCESSIVE PAGES TO BE SET

MSETMP::TRVAR <SID,ADR,PCT,ARG4,DEST,PCT2>
	DMOVEM T1,SID		;SAVE ARGS
	DMOVEM T3,PCT
	MOVEM T3,PCT2		;SAVE SECOND COPY OF COUNT
	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:	HLLZ T3,ADR		;GET ACCESS BITS
	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
	 CALL MSEINT		;FAILED, INTERRUPT
	AOS T1,DEST		;NEXT DEST ADDRESS
	SKIPE 2			;SOURCE 0?
	AOS T2,SID		;NEXT SOURCE IF APPROPRIATE
	SOSLE PCT		;COUNT PAGES DONE
	JRST MSETM1
	SKIPL ADR		;CHANGING EXEC OR USER MAP?
	IFSKP.
	  CALL PGRCLD		;USER, CLEAR ALL
	ELSE.
	  CALL MONCLA		;EXEC, CLEAR EXEC ONLY
	ENDIF.
	SKIPE ADR		;DELETING ONLY?
	CALLRET MSETM2		;NO
MSETM3:	MOVE T1,ADR		;YES, FLUSH PAGES FROM WS CACHE
	ANDX T1,TWUSR+777777	;CLEAR ACCESS BITS FROM ADR
	CALL DELWSC
	MOVEI T1,PGSIZ
	ADDM T1,ADR		;STEP ADDRESS BY ONE PAGE
	SOSLE PCT2		;COUNT PAGES
	JRST MSETM3
	MOVE T1,DEST		;RESTORE DEST ID
	CALLRET MSETM2
;LOCAL ROUTINE USED BY SETMPG AND MSETMP TO VERIFY THAT REQUESTOR
;IS NOT SELECTING A DISMOUNTED OFN.
; T1/ IDENT (PTN.PN) TO CHECK

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::SKIPE INSKED		;SCHED LEVEL?
	RET			;YES, DO NOTHING
	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,PAGEM,SOFT,<SETMPG - Attempt to map non-ex section>,,<

Cause:	A routine has been called to modify a process's map for one
	or more pages. A virtual address was provided. The caller is
	expected to provide a valid address. The BUGHLT indicates that
	a section that does not exist in the process's map was
	specified.
>)
;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 MSEINT		;FAILED, INTERRUPT
	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
; RETURN +1: FAILURE, T1/ ERROR CODE
;	+2: SUCCESS

MSETPT::SASUBR <SID,DID,ARG3,ARG4>
	CALL PTVER		;VERIFY ARGS
	 RET			;CAN'T USE A DISMOUNTED OFN
	MOVE 1,2
	CALL SETCPT		;SETUP DESTINATION MAP
	SKIP CPTPGA		;SWAP IN CPTPGA BEFORE NOSKED
	CALL LCKOFI		;LOCK DEST IF OFN
	MOVE 2,SID		;GET SOURCE PTR
MSETP1:	MOVE T3,ARG3		;GET ACCESS BITS
	CALL RELMP5		;RELEASE OLD CONTENTS
	MOVE T2,SID
	MOVE T1,DID		;RESTORE ARGS
	MOVE T3,ARG3		;ACCESS BITS
	CALL SETPT0		;SET NEW CONTENTS
	IFNSK.
	  CAIN T1,PAGPTN	;WAS PAGE TABLE ENTRY NON-ZERO?
	  JRST MSETP1		;YES, WE MUST RETRY THE RELEASE AND SET
	  MOVEM T1,SID		;FAILED, SAVE ERROR CODE
	  MOVE T1,DID		;GET THE DESTINATION ID
	  CALL MSETXX		;CLEAN UP
	  RET
	ENDIF.
	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
	CALL MSETXX		;CLEAN UP
	RETSKP

;LOCAL FINISH UP - RELEASE MAPS, ETC.
; T1/ DEST ID

MSETXX:	CALL RELCXB		;RELEASE SOURCE PT
	CALL RELCPT		;RELEASE DESTINATION PT
	CALL ULKOFI		;UNLOCK DEST IF OFN
	RET
;SET NEW CONTENTS OF PT
; T1/ DEST ID
; T2/ SOURCE ID
; T3/ ACCESS BITS
;RETURN +1: FAILURE, T1/ ERROR CODE
;	+2: SUCCESS
;ASSUMES SOURCE AND DEST PT'S ALREADY MAPPED

SETPT0:	JUMPE 2,RSKP		;CHECK FOR NO NEW PAGE TO SET
	SASUBR <ARG1,ARG2,ARG3,ARG4>
	NOSKED
SETP5A:	CAME 1,2		;DON'T ALLOW MAP TO SELF
	IFSKP.
	  MOVEI T1,PMAPX8	;ILLEGAL TO MAP TO SELF
	  JRST SETPTE
	ENDIF.
	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,PAGEM,SOFT,<Illegal source identifier given to SETPT>,,<

Cause:	A routine has been called to change the map for a page. The
	caller is expected to provide an identifier for the source
	that is of the form (SPT index,,page number). The BUGHLT
	indicates that the right half of the identifier contains an illegal
	value (that exceeds 777).
>)
	MOVE 3,ARG3		;GET FLAGS
	TXNE 3,PM%MVP		;MOVE OF PAGE REQUESTED?
	JRST [	CALL MVPT	;YES, DO IT
		 JRST [	JUMPN T1,SETPTE ;IF REAL FAILURE, DONE
			MOVE T1,ARG1
			MOVE T2,ARG2
			MOVE T3,ARG3
			JRST SETP5A]
		JRST SETPT2]
	HLRZ 4,1		;GET DESTINATION PTN
	CAIGE 4,NOFN		;FILE?
	JRST [	CALL MVPT	;YES, **SHOULD BE CHANGED TO SETPF1**
		 JRST [	JUMPN T1,SETPTE ;IF REAL FAILURE, DONE
			MOVE T1,ARG1
			MOVE T2,ARG2
			MOVE T3,ARG3
			JRST SETP5A]
		JRST SETPT2]
	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
	HLRZ 4,2		;GET SOURCE PTN
	CAIL 4,NOFN		;PROCESS?
	JRST SETP5		;YES, GO SETUP INDIRECT POINTER
	MOVE T4,ARG3		;GET FLAGS
	TXNE T4,PM%IND		;INDIRECT PTR REQUESTED?
	JRST SETP5		;YES
	LOAD 4,PTRCOD,3		;GET PTR TYPE
	CAIN 4,INDCOD		;INDIRECT?
	BUG.(HLT,ILXBP,PAGEM,SOFT,<SETPT - Bad pointer in XB>,,<

Cause:	A routine has been called to change the map for a page of a
	process. The page is being mapped to a file page. The BUGHLT
	indicates that the index block for the file contains an indirect
	pointer in memory. Only share pointers and immediate pointers
	are legal for index blocks.
>)
	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
SETPE2:	MOVEM 1,ARG1		;AND SAVE THE ERROR
	OKSKED
	RET
;HERE TO CONSTRUCT INDIRECT PTR TO SOURCE

SETP5:  LOAD T4,PTRCOD,T3	;GET TYPE CODE
	CAIE T4,INDCOD		;INDIRECT?
	IFSKP.
	CALL SETP6		;YES, CHECK FOR INDIRECT LOOP
	 JRST SETPTE		;THERE IS A LOOP GIVE ERROR
	ENDIF.
	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
	CAIGE T4,MAXSC0		;TOO MUCH?
	IFSKP.
	  CAIGE T3,NOFN		;IS THIS AN OFN?
	ANSKP.
	  MOVEI T1,CFRKX3	;NO. SHARE COUNT TOO LARGE
	  JRST SETPTE
	ENDIF.
	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
	SKIPN CPTPGA(T1)	;BE SURE PREVIOUS CONTENTS NULL
	IFSKP.
	  MOVEI T1,PAGPTN	;INFORM CALLER FOR RETRY OR BUGHLT
	  JRST SETPE2		;DO NOT SAVE ERROR CODE IN LSTERR.
	ENDIF.			;
	MOVEM T3,CPTPGA(1)	;PUT MAP WORD IN MAP
SETPT2:	OKSKED
	RETSKP

;SETP6 -
;Routine to check for potential page pointer loop.
;
;   T1/   Destination Page ID ( SPTN,,Page # )
;   T2/   Source Page ID
;
;Returns
;   +1    Failure, mapping of source page to destination
;         would build a page pointer loop
;   +2    Success, OK to map pages
;
;Preserves all ACs

SETP6:	SAVEAC <T2,T3,T4>
      DO.
	HLRZ T3,T2		;GET SOURCE PTN
	CALL SETXB1		;MAP SOURCE XB
	OKSKED			;REFERENCE PAGE WHILE OKSKED
	HRRZ T3,T2		;...
	SKIP CXBPGA(T3)		;...
	NOSKED			;GO NOSKED AGAIN
	MOVE T3,CXBPGA(T3)	;GET WORD FROM XB
	LOAD T4,PTRCOD,T3	;GET PTR TYPE
	CAIE T4,INDCOD		;INDIRECT?
	 RETSKP			;NO, DONE WITH TRACE
	LOAD T4,SPTX,T3		;YES, GET SPTN
	CAIGE T4,NOFN		;VIA INDEX BLOCK?
	 RETSKP			;YES, OK
	CALL RELCXB		;NO, TRACE DOWN
	LOAD T2,IPPGN,T3	;CONSTRUCT ID OF PAGE POINTED
	HRLI T2,0(T4)		; TO BY INDIRECT PTR
	CAMN T1,T2		;HAVE WE DETECTED A LOOP?
	 RETBAD (PMAPX8)	;YES, TIME FOR AN ERROR
     LOOP.
     ENDDO.

SETMXB:	CAIL 2,SSPT		;LEGAL NUMBER?
	BUG.(HLT,ILSPTI,PAGEM,SOFT,<Illegal SPT index given to SETMXB>,,<

Cause:	A routine has been called to change the map for a page. The
	caller provided a source identifier for a page table (an SPT
	index) rather than a single page. The BUGHLT indicates that
	the source identifier is an invalid SPT index, larger than the
	maximum value allowed.
>)
	HLRZ 3,1		;GET DESTINATION PTN
	CAIGE 3,NOFN		;FILE?
	BUG.(HLT,ILDEST,PAGEM,HARD,<Illegal destination identifier to SETMPG or SETPT>,,<

Cause:	A routine has been called to change the map for a page. The
	caller provided a source identifier for a page table (an SPT
	index) rather than a single page. The BUGHLT indicates that
	the caller provided a file page as a destination. This is
	illegal when the source is a page table.
>)
	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,PAGEM,SOFT,<SPT completely full>,,<

Cause:	A routine has been called to change the map for a page of a
	process. The page is being mapped to a file page that is not
	already shared. The code is going to create an entry for the
	file page in the SPT so that the destination can have a
	share pointer. The choice of a share pointer over an indirect
	pointer was made because the count of available SPT slots
	exceeded a threshold. The BUGHLT occurred because the head
	of the queue of free SPT slots contains a zero, indicating
	that there are no free slots. This means that there is an
	inconsistency in the monitor's data.
>)
	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,@CST2X+6		;CHECK OLD OWNERSHIP
	BUG.(HLT,CST2I1,PAGEM,SOFT,<Page table core pointer and CST2 fail to correspond>,,<

Cause:	A routine has been called to change the map for a page of a
	process. The page is being mapped to a file page that is not
	already shared. The code is going to create an entry for the
	file page in the SPT so that the destination can have a
	share pointer. The page pointer in the index block contains
	a core address. The BUGHLT indicates that the owner of the
	core page is not the file page that points to it. This means
	that there is an inconsistency in the monitor's data.
>)
	MOVEM 4,@CST2X+6	;RECORD NEW LOCATION OF CORE ADDRESS
	HLRZ 6,2		;YES, UPDATE LOCK COUNT FOR
	HRRZ 6,SPT(6)		;OWNING PT
	CALL ULKP6		;UNLOCK PAGE
	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
	EXCH T1,T3		;GET SPT INDEX IN CORRECT PLACE
	CALL CHKSHC		;CHECK THE SHARE COUNT FOR OVERFLOW
	 JRST [	EXCH T1,T3	;GET ACS BACK IN PROPER STATE
		MOVEI T1,CFRKX3	;WILL OVERFLOW SO GET ERROR CODE
		JRST SETPTE]	;AND PASS THE FAILURE DOWN
	EXCH T1,T3		;GET ACS BACK IN STATE
	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,PAGEM,SOFt,<SETPT - SPTH inconsistent with XB>,,<

Cause:	A routine has been called to change the map for a page of a
	process. The page is being mapped to a file page for which
	the index block has a share pointer. The share pointer points
	to an SPT slot. The BUGHLT indicates that the SPT slot is not
	owned by the file page whose map word points to it. This
	indicates an inconsistency in the monitor's data.
>)
	EXCH T1,T3		;GET ACS MOVED AROUND
	CALL CHKSHC		;CHECK THE CURRENT SHARE COUNT
	 JRST [	EXCH T1,T3	;GET ACS BACK
		MOVEI T1,CFRKX3	;WILL OVERFLOW SO GET THE ERROR CODE
		JRST SETPTE]	;AND PASS THE FAILURE DOWN
	EXCH T1,T3		;GET ACS BACK IN STATE
	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:	ASUBR <MVPTA1,MVPTA2>
	SAVEAC <Q1>
MVPT0:	DMOVE T1,MVPTA1		;RESTORE ACS IF RESTART
	HLRZ T3,T2		;GET SOURCE PTN
	CALL SETXB1		;MAP INDEX BLOCK
	OKSKED
	SKIP CXBPGA		;REFERENCE PAGE WHILE OKSKED
	SKIP CPTPGA		;FORCE IN DESTINATION PT AS WELL
	NOSKED
	HLRZ 4,2		;GET SOURCE AND DEST PTN'S
	HLRZ 3,1
	CAIL 3,NOFN		;DEST IS FILE?
	IFSKP.
	  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
	ELSE.
	  CAIGE 4,NOFN 		;DEST IS FORK, SOURCE ALSO?
	  RETBAD(PMAPX4)		;NO, FILE-TO-FORK ILLEGAL
	ENDIF.
	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,@CST2X+4		;YES, CHECK CST CONSISTENCY
	BUG.(HLT,CST2I2,PAGEM,SOFT,<MVPT - CST2 inconsistent>,,<

Cause:	A routine has been called to move a page from one page table
	to another. The source page table has an immediate pointer to
	a page in memory. The BUGHLT indicates that the CST entry for
	that page contains a different owner from the source identifier that
	points to it. This indicates an inconsistency in the monitor's
	data.
>)
	MOVEM 1,@CST2X+4		;NOTE NEW LOCATION OF POINTER
	CALL MVLK		;MOVE THE PT LOCK COUNT
	HRRZ 1,2
	MOVE 1,CXBPGA(1)	;GET CORE PAGE NUMBER
	CALL DECOR		;DEASSIGN PAGE FROM WS
	MOVE T1,MVPTA1		;RESTORE DEST
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
;CODE FORCES DEST PAGE IN. SOURCE PAGE MUST BE IN MEMORY
;SINCE A POINTER IS FETCHED FROM IT WHILE THE PROCESS IS NOSKED.

MVLK:	SAVEAC <T3,T4>
	SKIP CPTPGA		;MAKE SURE DEST PT IN MEMORY
	HLRZ 4,2		;SOURCE PTN
	HRRZ 4,SPT(4)
	CALL ULKP4
	HLRZ 4,1
	HRRZ 4,SPT(4)
	MOVSI 3,(PLKV)
	ADDM 3,@CST1X+4		;INCREASE LOCK COUNT OF XB
	RET
;DESTINATION IS FILE, SOURCE FORK

SETP7:	HRRZ T3,T2
	MOVE T3,CXBPGA(T3)	;GET PTR
	JUMPE T3,SETP73		;JUMP IF PAGE NON-EXISTENT
	LOAD T4,PTRCOD,T3      	;GET PTR TYPE
	CAIE T4,IMMCOD		;NOT PRIVATE?
	RETBAD(PMAPX3)		;YES, ERROR
	HRRZ Q1,T3		;ELIMINATE LEFT HALF OF 3
	TLNE T3,(DSKAB)		;NOW ON DISK?
	JRST SETP71		;YES
	TLNE T3,(DRMAB)		;NOW ON DRUM?
	JRST SETP7D		;YES, GO ADJUST DRUM BACKUP ADR
	LOAD T4,STGADR,T3     	;IN CORE, GET PAGE NUMBER
	CAML T4,MONCOR		;NORMAL SWAPPING PAGE?
	CAMLE T4,NHIPG
	RETBAD(PMAPX5)		;NO, CAN'T MAP FILE
	MOVEI T1,0(Q1)
	CALL AGECHK		;FIX PAGE
	CALL SKPNLK		;PAGE LOCKED?
	IFNSK.
	   CALL WTNLK		;YES, WAIT FOR UNLOCK
	   JRST MVPT0		;RESTART
	ENDIF.
	MOVE T1,MVPTA1		;RESTORE DEST
	MOVSI T4,(PLKV)		;IN CORE,
	ADDB T4,@CST1X+Q1      	;GET BACKUP ADR AND LOCK PAGE
	TLNE T4,(DSKAB)		;DISK?
	JRST SETP7C		;YES
	TLNE T4,(DRMAB)		;DRUM?
	JRST SETP7E		;YES
	XMOVEI T4,@CST1X+Q1	;NOT ASSIGNED, PUT BACKUP ADR IN CST1
	CALL SETP7A		;ASSIGN BACKUP ADR AND STORE IT
	 JRST [	MOVEM T1,LSTERR
		HRRZ Q1,T3	;FAILED. GET CORE ADDRESS
		CALL ULKP5
		MOVE T1,LSTERR
		RET]
SETP7C:	HRRZ Q1,T3
	MOVEM T1,@CST2X+Q1	;IN CORE, ADJUST CST
	CALL ULKP5
	CALL MVLK		;MOVE PT LOCK COUNT
SETP71:	HRRZ Q1,T2
	SETZM CXBPGA(Q1)	;PUT SOURCE PTR IN DEST MAP
	ANDX T3,STGADM		;EXTRACT STORAGE ADDRESS
	IOR T3,IMMPTR		;MAKE PRIVATE PTR
	HRRZS T1
	MOVEM T3,CPTPGA(T1)
SETP72:	MOVE T1,MVPTA1		;BE SURE WE HAVE IDENT
	HRRZ T3,T1
	MOVE T3,CPTPGA(T3)	;GET CURRENT ADR OF PAGE
	TLNE T3,(DSKAB)		;PAGE NOW ON DSK?
	JRST SETP73		;YES, DONE
	TLNE T3,(DRMAB)		;ON DRUM?
	JRST [	CALL SWPINW	;YES, GET IT IN CORE
		JRST SETP72]	;RECHECK ADDRESS
	HRRZS T1
	MOVE T1,CPTPGA(T1)	;GET CURRENT ADDRESS OF PAGE
	CALL SKPNWR		;WRITE IN PROGRESS?
	 JRST SETP72		;YES, RECHECK ADDRESS
	MOVX T2,DSKSWB		;GET DISK BIT
	IORM T2,@CST3X+T1       ;AND SET DISK BIT IN CST
	CALL SWPOT0		;SWAP PAGE TO DISK
SETP73:	MOVE T1,MVPTA1		;IDENT
	HLRZ T3,T1		;GET DEST OFN
	MOVX T4,OFNWRB		;NOTE CHANGE TO IT
	IORM T4,SPTH(T3)
	RETSKP
SETP7D:	MOVE 4,3
SETP7E:	PUSH P,3
	MOVE 2,4		;DRUM ADDRESS
	CALL GDSTX		;GET DST INDEX
	MOVE 4,2		;WHERE TO STORE ADDRESS
	POP P,3
	MOVE T2,MVPTA2
	MOVE Q1,0(4)		;PRESENT BACKUP
	TLNE Q1,(DSKAB)		;DISK?
	JRST SETPE1
	CALL SETP7A		;NO, ASSIGN DISK ADDRESS AND STORE IT
	 JRST [	MOVEM T1,LSTERR
		HRRZ Q1,T3	;FAILED. GET CORE ADDRESS (IF ONE)
		TLNN T3,(NCORTM) ;CORE PAGE?
		CALL ULKP5
		MOVE 1,LSTERR
		RET]
SETPE1:	TLNN 3,(NCORTM)
	JRST SETP7C
	JRST SETP71

	ENDAS.
;ASSIGN DISK ADR AND STORE IT
; T1/ IDENT OF XB
; T4/ ADR OF PTR TO BE SET
; RETURN +1: FAILED, T1/ ERROR CODE. A code of 0 indictaes resched
;	+2: SUCCESS

SETP7A:	SASUBR <P71,P72,P73,P74>
  	STKVAR <SVALL>
	HLRZ T1,P71
	CALL QCHKHW		;SEE IF OK TO ASSIGN DISK PAGE
	IFNSK.			;If failed
	 MOVEM T1,P71		;So error is returned
	 RETBAD()		;Fail
	ENDIF.
;   IFN CFSCOD,<			;If CFS
	IFE. T2			;If did a resched...
	 SETZM P71		;Tell caller
	 RET			;And return
	ENDIF.
	SOS T2,T1		;Update it now
	HLRZ T1,P71		;The OFN
	CALL QSET		;It's changed
;   >	;IFN CFSCOD
	MOVE T1,P71		;GET DEST IDENT
	CALL FNDLDA		;GET LAST DISK ADR ASSIGNED FOR DSKASN
	IFNSK.			;If didn't find one
	 HLRZ T2,P71		;GET OFN
	 CALL DSKGET		;Assign a disk address for the page
	  SKIPA
	 SKIPN T1		;Get an address?
	 ANNSK.			;If some failure
	 EXCH T1,P71		;Save error, recover OFN
;   IFN CFSCOD,<			;If CFS
	 HLRZS T1
	 CALLRET QRUP		;Release the lock and fix quota
;   >	;IFN CFSCOD
	 RET
	ENDIF.			;If made it here, have an address
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<			;If not CFS
	HLRZ T3,P71		;GET OFN AGAIN
	LOAD T3,ALOCX,(T3)	;INDEX INTO QUOTA TABLE
	DECR PGLFT,(T3)	;ONE LESS PAGE LEFT
   >	;IFE CFSCOD
   >				;END REPEAT 0
	MOVE T4,P74
	STOR T1,STGADR,0(T4)	;STORE ADDRESS PER ARG
   REPEAT 0,<			;Don't do this until DSKFIL fixed
	HLRZ T1,P71		;The OFN again
	MOVE T2,T4		;Address
	CALL DSKFIL		;Try to fill preallocated pages
   >	;REPEAT 0
	RETSKP

	ENDSV.
	ENDSA.
;RELEASE PAGE FROM MAP
; AC1/ OFN.PN OF PAGE
;AC3/ ACCESS BITS

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::SAVEAC <Q1>		;HOLD FLAGS HERE
	HLLZ Q1,T3		;GET FLAGS.

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
	TXNN T2,PTWR		;THIS POINTER HAVE WRITE ACCESS?
	TXZ Q1,PM%ABT		;NO. DON'T HONOR "ABORT" REQUEST THEN
	CAIN T3,INDCOD		;INDIRECT?
	JRST RELMI1		;YES
	; ..
;PROCESS A SHARE POINTER

	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
	TXNE Q1,PM%ABT		;WANT "ABORT" UNMAP?
	JRST [	MOVX T4,OFNDUD	;GET DUD BIT
		TDNE T4,SPTH(T3) ;OPENED "DUD"?
		CALL CHKDMO	;SEE IF MOUNTED
		 JRST .+1	;NOT. DON'T "ABORT"
		PUSH P,T2
		PUSH P,T3	;SAVE CRITICAL ACS
		LOAD T1,STGADR,SPT(T2) ;GET STORAGE ADDRESS
		HRRZ T2,T3	;PASS OFN
		CALL RELADR	;GO RELEASE PAGES
		POP P,T3
		POP P,T2	;RESTORE CRITICAL ACS
		STOR T1,STGADR,SPT(T2) ;STORE DISK ADDRESS
		JRST .+1]	;DONE
	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
   REPEAT 0,<
	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,@CST1X+1		;AND LOCK WHILE ADJUSTING
   >	;Repeat 0
	; ..
RELMP2:	JN OFNDMO,SPTH(T3),RELMPZ ;If dismounted, all done
	CALL SETXB1		;MAP OWNING XB
	DO.
	 MAP T4,CXBPGA		;See if the page is accessible now
   IFN KLFLG,<
	 TLNE T4,360000
	 TLNE T4,200000		;HARD PAGE FAIL CODE?
   >				;END OF IFN KLFLG
   IFN KCFLG,<
	 TXNN T4,MPHPFF		;HARD FAILURE?
	 TXNN T4,MPVALD		;NO. DOES MAPPING EXIST?
   >				;END OF IFN KCFLG
	 IFNSK.			;If not
	  INCR SPTSHC,(T2)	;Increment share count again
	  NOINT			;Protect our map
	  OKSKED
	  SKIP CXBPGA
	  NOSKED
	  OKINT
	  DECR SPTSHC,(T2)	;One less unit
	  TMNN SPTSHC,(T2)	;Still unshared?
	  LOOP.			;yep. do it again
	  JRST RELMPS		;And done
	 ENDIF.
	ENDDO.
RELMPZ:	HRRZS T1,T3		;GET XB INDEX
	CALL DWNSHR		;DECREMENT SHARE COUNT
	LOAD T1,STGADR,SPT(T2)	;Get present location of page
	TXNN T1,NCORTM		;In mem?
	IFNSK.			;If so
	 CALL AGESET		;Make it accessible
	 MOVX T4,PLKV		;Get a unit of lock count
	 ADDM T4,@CST1X+T1	;And lock it
	ENDIF.
	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,@CST2X+1		;CONFIRM OLD OWNERSHIP
	BUG.(HLT,CST2I3,PAGEM,SOFT,<Page table core pointer and CST2 fail to correspond>,,<

Cause:	A routine has been called to remove a page from a process's
	map. The map contains a share pointer to a file page. The
	SPT entry to which the map points contains a core page number.
	The BUGHLT indicates that the CST entry for that core page
	does not point back to the SPT entry.
>)
	MOVEM 4,@CST2X+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,@CST1X+3		;INCREMENT LOCK COUNT
	CALL ULKP1		;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 RELMI5		;YES. GO HANDLE PT
	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 [	TXNE Q1,PM%ABT	;WANT "ABORT"?
		CALL RELMI2	;YES. GO DO IT THEN
		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

;HERE IF POINTER IS TO OFN ON DISMOUNTED STRUCTURE

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

;HERE IF INDIRECT POINTER TO A PAGE TABLE. IF THIS IS NOT THE
;LAST SHARER, DECREMENT THE SHARE COUNT AND CONTINUE. IF IT IS
;THE LAST SHARER, THE SPT SLOT MUST HAVE BEEN A SECTION POINTER FOR
;ANOTHER PROCESS THAT HAS SINCE UN-SMAP'D IT. THE CALLING PROCESS
;MAY HAVE TOUCHED SOME PAGES SINCE THEN, BUT ONLY IMMEDIATE POINTERS
;CAN EXIST IN THE MAP. GO RELEASE THE PAGES AND THE SPT SLOT.

RELMI5:	MOVEI T1,0(T2)		;GET SPTN
	CALL GETSHR		;GET THE SHARE COUNT
	JUMPN T1,RELMPS		;IF NOT THE LAST ONE, FINISHED
	MOVE T3,T2		;GET SPTN
	CALL SETXB1		;MAP THE PAGE TABLE
	CALL SCNPT		;RELEASE ALL POINTERS IN P.T.
	MOVE T1,T2		;GET SPT INDEX
	CALL UPSHR		;INCREMENT SHARE COUNT FOR DESPT
	CALL DESPT		;DEASSIGN THE SPT SLOT
	CALL RELCXB		;UNMAP THE PAGE TABLE
	JRST RELMPS		;DONE
;RELMI2 - LOCAL ROUTINE TO DO "ABORT" UNMAP.

RELMI2:	SAVEAC <T2,T3,Q1>	;SAVE CRITICAL REGS
	EXCH T2,T3		;OFN TO T3. POINTER TO T2
	CALL SETXB1 		;MAP XB
	LOAD Q1,IPPGN,T2	;GET PAGE NUMBER IN XB
	MOVEI Q1,CXBPGA(Q1) 	;GET ADDRESS OF POINTER
	LOAD T1,PTRCOD,0(Q1) 	;GET POINTER
	JUMPE T1,RELMI3		;IF NULL, GO ON
	CAIE T1,IMMCOD		;IMMEDIATE POINTER?
	JRST [	LOAD Q1,SPTX,0(Q1) ;NO. SHARED. GET SPT INDEX
		MOVEI Q1,SPT(Q1) ;GET ADDRESS OF NEW POINTER
		JRST .+1]	;PROCEED
	LOAD T1,STGADR,0(Q1) 	;GET STORAGE ADDRESS
	HRRZ T2,T3		;PASS OFN
	CALL RELADR		;RELEASE PAGES
	STOR T1,STGADR,0(Q1) 	;PUT ADDRESS BACK
RELMI3:	CALLRET RELCXB 		;RELEASE XB
;RELMP5 CONTINUED ...
;PAGE BECOMING UNSHARED, MUST MAKE IT BE ON DISK

;**;[7136]  Add 8 lines after RELP4:+0			DML	15-Aug-85
RELP4:	HLRZ T1,T4		;GET THE OFN
RELP41:	MOVX T3,SPTLKB		;[7136]
	TDNN T3,SPTH(T1)	;[7136] Is the OFN now locked?
	IFSKP.			;[7136] Yes
 	 CALL WTOFNS		;[7136]	Undo NOSKED from above and wait
	 NOSKED			;[7136]	Go NOSKED again
	 HLRZS T1		;[7136]	Adjust T1
	 JRST RELP41		;[7136] Try again
	ENDIF.			;[7136]
	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?
;**;[7247]  Replace 1 line with 9 at RELP4:+7		DML	19-Feb-86
	SKIPE T3,PSBM0+CPTPG	;[7247] Yes.  Get current mapping in CPTPGA
	CALL RELCPT		;[7247] Release current mapping if any
	PUSH P,T3		;[7247] Save it for later
	MOVE T1,-1(P)		;[7247] Get OFN again
	CALL LCKOFN		;[7247] Lock the OFN against modification
	CALL OC.CSH		;[7247] Cache the OFN

REPEAT 0,<			;[7247] Old code from before OFN caching

	CALL DASALC		;CLEAR ALLOC ENTRY IN THE OFN
	SKIPE T3,PSBM0+CPTPG	;GET CURRENT MAPPING IN CPTPGA
	CALL RELCPT		;RELEASE CURRENT MAPPING IF ANY
	PUSH P,T3		;SAVE IT FOR LATER
   REPEAT 0,<
	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
   >	;REPEAT 0
	CALL LCKOFO		;LOCK THE OFN AGAINST MODIFICATION
	OKSKED
	CALL DSKUGT		;Free any cached disk pages
	NOSKED
;   IFN CFSCOD,<
	CSKED			;Stay critical
	OKSKED			;While we get access token
	SETZM T2
	CALL CFSAWP		;GET ACCESS TO FILE
	MOVE T1,-1(P)
	NOSKED			;Own system for a bit more
;   >	;IFN CFSCOD
	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,T1		;RESTORE PAGE TABLE MAPPING
	HRLZS T1		;MAKE IT SPTN.PN
	SKIPE T1		;MAKE SURE SOMETHING IS HERE
	CALL SETCPT		;REMAP IT

;**;[7247]  Add 5 lines after RLMPR2:-1			DML	19-Feb-86
> ;[7247] End REPEAT 0 - Old code from pre cache days

	MOVE T1,-1(P)		;[7247] Get back OFN
	CALL ULKOFN		;[7247] Unlock the OFN
	POP P,T1		;RESTORE PAGE TABLE MAPPING
	HRLZS T1		;MAKE IT SPTN.PN
	SKIPE T1		;MAKE SURE SOMETHING IS HERE
	CALL SETCPT		;REMAP IT

RLMPR2:	POP P,T1		;GET OFN
	CALL DWNSHR		;RESTORE ORIGINAL SHARE COUNT
RELMPR:	CALL RELCXB		;RELEASE XB MAPPING
RELMPS:	OKSKED
	RET

;ROUTINE USED TO RELEASE PRIVATE STORAGE IF "ABORT" UNMAP REQUESTED
;	T1/ STORAGE ADDRESS TO RELEASE
;	T2/ OFN
;Returns:	+1. T1/ final address

RELADR:	ASUBR <XT1,XT2>
	CALL REMFP1		;RELEASE STORAGE
	MOVE T2,XT2		;RESTORE T2
	TXNN T1,DSKNB		;NEW DISK PAGE?
	IFSKP.
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<			;If not CFS
	  LOAD T3,ALOCX,(T2) 	;YES, MUST DELETE IT
	  INCR PGLFT,(T3)	;ADJUST QUOTAS
   >	;IFE CFSCOD
   >				;END REPEAT 0
;   IFN CFSCOD,<			;If CFS
	  MOVEM T1,XT1		;Save disk address
	  MOVE T1,T2		;Copy OFN
	  NOSKED		;Lock up system until we get this
	  CALL QCHKH		;Get allocation and lock
	   MOVE T1,T2		;The allocation
	  OKSKED
	  ADDI T1,1		;One more
	  MOVE T2,T1
	  MOVE T1,XT2		;Get the OFN
	  CALL QSET		;Set new allocation
	  MOVE T2,XT2
	  MOVE T1,XT1
;   >	;IFN CFSCOD
	  SETONE OFNWRB,SPTH(T2) ;NOTE OFN MODIFIED
	  LOAD T3,STRX,(T2) 	;GET STRUCTURE NUMBER
	  MOVE T2,SPTH(T2) 	;PASS OFN BITS
	  CALL DEDSKC		;DEALLOCATE THE DISK PAGE
	  SETZ T1,    		;SAY NOTHING LEFT.
	ENDIF.
	SKIPN T1		;ANYTHING LEFT?
	MOVX T1,UAAB		;NO. SAY UNASSIGNED THEN
	RET			;DONE
	ENDAS.
;HERE IF PRIVATE PAGE -- PAGE WILL BE DELETED

RELP3:	TLNE 2,(NCORTM)		;IN CORE?
	JRST RELP32		;NO, CAN RELEASE ALL.
	PUSH P,1
	HRRZ T1,T2
	CALL SKPNWR		;WAIT FOR WRITE COMPLETION
	IFNSK.
	  POP P,1
	  OKSKED		;RELMP6 GOES NOSKED AGAIN
	  JRST RELMP6		;GO TRY AGAIN
	ENDIF.
	POP P,1
RELP32:	SOS NPRIVP		;ADJUST PRIVATE PAGE COUNT
	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 AGECHK		;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
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<			;If not CFS
	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
   >	;IFE CFSCOD
   >				;END REPEAT 0
;   IFN CFSCOD,<			;If CFS
	HLRZ T1,-1(P)		;Get OFN
	CALL QCHKH		;Get allocation
	 MOVE T1,T2		;Get it in proper place
	MOVE T2,T1		;Copy it
	ADDI T2,1		;One more
	HLRZ T1,-1(P)		;The OFN
	CALL QSET
	POP P,T1		;Disk address
	HLRZ T2,0(P)
;   >	;IFN CFSCOD
	LOAD C,STRX,(2)		;GET STRUCTURE NUMBER
	MOVE 2,SPTH(2)		;SEND DEDSK THE OFN BITS
	CALL DEDSKC		;DELETE IT
	POP P,1			;RECOVER IDENT
	CALL SETCPT		;MAP PT AGAIN
	OKINT			;UNDO NOINT ABOVE
	RET
;SCNPT - SCAN A PAGE TABLE AND CLEAR ALL POINTERS

;ACCEPTS:
;	NO AC'S, BUT PAGE TABLE MAPPED IN CXBPG

;	CALL SCNPT

;RETURNS +1: ALWAYS
;	PRESERVES ALL AC'S

;ENTRIES MUST ALL BE IMMEDIATE POINTERS TO CORE

SCNPT:	SAVET
	ACVAR<W1>
	MOVSI W1,-PGSIZ		;SET UP TO STEP THROUGH PAGE
SCNPT1:	SKIPN T1,CXBPGA(W1)	;GET MAP ENTRY
	JRST SCNPT4		;ZERO. SKIP IT
	LOAD T2,PTRCOD,T1	;GET THE POINTER TYPE
	CAIE T2,IMMCOD		;IS IT IMMEDIATE?
	JRST SCNPT8		;NO. BUG
	ANDX T1,STGADR		;GET JUST THE ADDRESS
	CALL REMFP1		;GO DEASSIGN THE PAGE
	JUMPN T1,SCNPT9		;FAILED TO DEASSIGN. MUST BE ON DISK
SCNPT4:	AOBJN W1,SCNPT1		;LOOP THROUGH THE PAGE
	RET
SCNPT8:	BUG.(HLT,SCPT01,PAGEM,SOFT,<SCNPT - Entry is not an immediate pointer>,,<

Cause:	A routine has been called to release all pages to which a specified
	page table points. The caller must ensure that all pointers
	are immediate pointers to core with no disk backup. The BUGHLT
	indicates that a pointer was not an immediate pointer.
>)
SCNPT9:	BUG.(HLT,SCPT02,PAGEM,HARD,<SCNPT - Page was not deleted>,,<

Cause:	A routine has been called to release all pages to which a specified
	page table points. The caller must ensure that all pointers
	are immediate pointers to core with no disk backup. The BUGHLT
	indicates that a page had backup on disk.
>)

	ENDAV.			;END ACVAR
;SUPPORT ROUTINES FOR SECTION MAPPING. ALLOWS A PROCESS
;TO MAP OR UNMAP NON-ZERO SECTIONS OF ITS ADDRESS SPACE

;SET/CLEAR MAP
;	T1/ SOURCE SPTN (SPT INDEX FOR SOURCE -- OFN OR FORK'S PSB)
;		OR
;	T1/ -1 TO CREATE PRIVATE SECTION
;		OR
;	T1/ 0 TO CLEAR SECTION POINTER
;	T2/ PTN,,SECTION
;	T3/ACCESS BITS,,FORKX OF DESTINATION FORK

;RETURNS +1: ERROR, CODE IN T1
;	 +2: SUCCESS

;USECTO IS OFFSET IN PSB FOR SECTION POINTER. PSB GETS MAPPED INTO
;CPTPGA. SECADR IS THE ADDRESS WHERE THE SECTION 0 POINTER IS MAPPED.

;SECTION POINTER CAN BE ONE OF THE FOLLOWING:
;	SHARE POINTER TO ANOTHER FORK'S SECTION MAP (PTSECM IS SET)
;	SHARE POINTER TO A FILE'S OFN (PTSECM IS SET)
;	PRIVATE SECTION (SHARE POINTER TO SPT, PTSECM IS OFF)
;	SECTION DOESN'T EXIST (0)

SECMAP::ASUBR<SID,SECN,SECACS,SECSPT>	;SAVE ARGS
	NOSKED			;PREVENT INTERRUPTION
	MOVE T1,T2		;GET DESTINATION PT
	CALL SETCPT		;MAP IT
	HRRZ T1,SECN		;GET DESIRED SECTION
	SKIPN T2,SECADR(T1)	;NOW EXIST?
	JRST SECMA2		;NO. GO ON THEN
	LOAD T3,PTRCOD,T2	;CHECK PTR TYPE
	CAIE T3,SHRCOD		;SHARE?
	JRST [	CAIE T3,INDCOD	;NO, MUST BE INDIRECT
		BUG.(HLT,BADPTR,PAGEM,SOFT,<Bad section pointer - SECMAP>,,<

Cause:	The section pointer being deleted was not one of the
	types (share or indirect) expected.
>)
		LOAD T1,SPTX,T2	;CAN ALWAYS DELETE
		CALL DWNSHR
		JRST SECMA1]
	TXNE T2,PTSECM		;YES, IS THE SECTION MAPPED?
	JRST [	LOAD T1,SPTX,T2	;YES, GET SPT INDEX
		CALL DWNSHR	;DECREMENT SHARE COUNT
		JRST SECMA1]	;DELETE THE SECTION POINTER AND GO AWAY
;SECTION IS PRIVATE AND CAN ONLY BE DELETED IF NOT SHARED
	LOAD T1,SPTX,T2		;CHECK SHARE COUNT
	CALL GETSHR
	CAIE T1,1		;ANY OTHER USERS?
	RETBAD (SMAPX1,<OKSKED
		CALL RELCPT>)	;YES, CAN'T DELETE
	LOAD T1,SPTX,T2
	CALL DESPT		;DELETE THE PT
SECMA1:	HRRZ T1,SECN		;VANISH THE PTR
	SETZM SECADR(T1)
	; ..
	; ..

;DELETE DONE. SET MAP

SECMA2:	SKIPN T1,SID		;WANT TO SET A NEW MAP?
	JRST SECMA5		;NO. DONE THEN
	JUMPL T1,SECMA3		;CREATE PRIVATE SECTION IF DESIRED
	MOVE T3,SHRPTR		;ASSUME A SHARE POINTER
	TXO T3,PTSECM		;SAY IS MAPPED
	TLNE T1,-1		;PTN.PN?
	JRST [	MOVE T3,INDPTR	;YES. GET IND POINTER THEN
		ADDI T1,USECTO	;ORIGIN OF SECTION TABLE
		STOR T1,IPPGN,T3 ;STORE PAGE NUMBER
		HLRZS T1	;GET PTN
		JRST .+1]	;AND PROCEED
	CALL UPSHR		;SHARE IT
	JRST SECMA4		;GO CLEAN UP AND EXIT

;HERE TO CREATE A PRIVATE SECTION.

SECMA3:	CALL ASSPTL		;GET AN SPT SLOT
	MOVEM T1,SECSPT		;SAVE SPT INDEX
	HRRZ T3,SECACS		;GET FORKX OF OWNING FORK
	MOVEM T3,SPTH(T1)	;REMEMBER IT
	CALL SWPIN1		;GET A PHYSICAL PAGE
	CALL ULKP3		;UNLOCK PAGE
	MOVE T3,SHRPTR		;CONSTRUCT SHARE PTR TO NEW SPT SLOT
	MOVE T1,SECSPT		;GET SPT SLOT
SECMA4:	STOR T1,SPTX,T3		;MAKE THE SHARE POINTER
	HLLZ T2,SECACS		;GET DESIRED ACCESS
	CALL SPAC		;CONVERT TO INTERNAL BITS
	HRRZ T1,SECN		;GET SECTION NUMBER
	MOVEM T3,SECADR(T1)	;STORE SHARE POINTER IN PSB
SECMA5:	CALL MONCLA		;CLEAR PAGER
	OKSKED			;ALLOW SCHEDULING AGAIN
	CALL RELCPT		;AND DONE
	RETSKP
;SAME AS SECMAP SETS/CLEARS MULTIPLE SECTIONS IN THE MAP
;ACCEPTS:
;	T1/ SOURCE I.D. (PSB,,SECN)
;	T2/ DESTINATION I.D. (PSB,,SECN)
;	T3/ ACCESS
;	T4/ COUNT (NUMBER OF SECTIONS TO MAP)

;	CALL MSETST

;RETURNS:	+1 FAILURE. T1/ ERROR CODE
;		+2 SUCCESS

MSETST::SAVEQ			;SAVE ACS
	DMOVE Q1,T1		;PUT ARGUMENTS IN A SAFE PLACE
	HLLZ FX,T3		;ACCESS
	HRR FX,T4		;COUNT
MSETS1:	MOVE T1,Q1		;SOURCE (PSB,,SECN)
	TXNE FX,SM%IND		;CALLER REQUEST INDIRECT MAPPING?
	JRST MSETS3		;YES GET ARGS AND CHECK
	CALL SECJFN		;A FILE?
	 JRST MSETS2		;NO, JUST STORE A SHARE POINTER TO THE FORK
	CALL [	<SAVEQ>		;SAVE VOLATILE ACS
		HRRZ T1,T2	;PAGE NUMBER WITHIN THE FILE
		LSH T1,-PGSFT	;CONVERT TO SECTION NUMBER
		HLL T1,T2	;JFN,,SECN
		HRRZ Q1,T1	;SOURCE SECTION NUMBER
		HRRI FX,1	;MAP ONE SECTION
		CALLRET SMFILE]	;MAP IT AND UPDATE OFN SHARE COUNTS
	 RETBAD ()		;A LOSER
	JRST MSETS4		;LOOP OVER ENTIRE ARGUMENT LIST

MSETS2:	MOVE T1,Q1		;GET BACK SOURCE ID, MAP INDIRECT ANYHOW
MSETS3:	DMOVE T2,Q2		;DESTINATION (PSB,,SECN)
	TXZ T3,<<-1>^!<PM%RD!PM%WR>> ;ACCESS
	CALL SETS6		;CHECK FOR INDIRECT LOOP
	 RETBAD()		;LOOP! RETURN ERROR
	MOVE T1,Q1		;GET T1 AGAIN
	CALL SECMAP		;MAP DESTINATION TO SOURCE
	 RETBAD ()		;FAILURE
MSETS4:	ADDI Q1,1		;NEXT SOURCE SECTION
	ADDI Q2,1		;NEXT DESTINATION SECTION
	TRNE FX,777776		;MAPPED ALL SECTIONS?
	SOJA FX,MSETS1		;NO, DECREMENT COUNT AND MAP NEXT SECTION
	RETSKP			;GOOD RETURN

;SETS6 -
;Routine to check for potential section pointer loop.
;
;   T1/   Source Section ID ( PSB,,Section # )
;   T2/   Destination Page ID
;
;Returns
;   +1    Failure, mapping of source page to destination
;         would build a page pointer loop
;	     T1/   Error code (SMAPX2)
;   +2    Success, OK to map pages
;
;Preserves all ACs but T1

SETS6:	SAVEAC <T2,T3>		;PRESERVE THESE ACS
SETS6A:	CAMN T1,T2		;ARE SOURCE AND DESTINATION THE SAME?
	 RETBAD (SMAPX2)	;YES, ILLEGAL TO MAP SECTIONS IN A LOOP
	PUSH P,T2		;SAVE DESTINATION ID
	CALL SECPTR		;GET THE POINTER FOR SOURCE ID
	POP P,T2		;GET DISTINATION ID BACK
	LOAD T3,PTRCOD,T1	;GET POINTER TYPE
	CAIE T3,INDCOD		;INDIRECT?
	 RETSKP			;NO, THIS IS THE END OF THE LINE.
	LOAD T3,SPTX,T1		;GET SPT INDEX
	LOAD T1,IPPGN,T1	;GET INDEX INTO SECTION TABLE
	SUBI T1,USECTO		;GET SECTION NUMBER
	HRL T1,T3		;PSB,,SECN
	JRST SETS6A		;TRY TO TRACE ANOTHER LEVEL
;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 T2,T4
;**;[7201] Insert 5 lines at MOVDSK+1		CEG	19-Nov-85
	CSKED			;[7201] GET THE BIG SCHEDULER BOOST
	OKSKED			;[7201] ALLOW SCHEDULING
	SKIP CXBPGA(T2)		;[7201] FAULT IN THE PAGE IF IT'S NOT ALREADY IN
	NOSKED			;[7201] PREVENT SCHEDULING
	ECSKED			;[7201] DON'T NEED SPECIAL SCHEDULING ANYMORE
	MOVE T1,CXBPGA(T2)	;GET CURRENT ADR OF PAGE
	JUMPE T1,R		;MAY BE EMPTY
	LOAD T2,PTRCOD,T1
	CAIN T2,SHRCOD		;BECAME SHARED AGAIN?
	RET			;YES, NOTHING TO DO OR CAN BE DONE
	TXNN T1,NCORTM		;IN CORE?
	JRST MOVDS1		;YES. GO CHECK IT
	TXNE T1,DSKAB		;ON DISK?
	RET			;YES. ALL DONE
	TXNN T1,DRMAB		;ON DRUM?
	JRST [	HRRZ T2,T4
		SETZM CXBPGA(T2) ;NO, UNNASSIGNED. FLUSH IT
		RET]		;AND DONE
	MOVE T2,T1		;PAGE ON DRUM, GET DRUM ADR
	CALL GDSTX		;GET DST INDEX
	MOVE T3,(T2)		;CHECK DRUM STATUS WORD
	TLNE T3,(BWRBIT)       	;HAS PAGE BEEN MODIFIED SINCE DISK?
	JRST [	MOVE T1,T4	;YES, MUST WRITE IT BACK ON DISK
		PUSH P,T4
		CALL SWPINW	;SO FIRST GET IT INTO CORE
		POP P,T4
		JRST MOVDSK]	;NEXT SWPOUT WILL GO TO DISK
	SETOM (T2)		;PAGE NOT MODIFIED, NO WRITING NEEDED
	HRRZ T2,T4
	STOR T3,STGADR,CXBPGA(T2) ;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 SKPNLK		;LOCKED?
	IFNSK.
	  CALL WTNLK		;YES, WAIT FOR UNLOCK
	  JRST MOVDSK		;RECHECK
	ENDIF.
	HRRZ T2,T1		;GET ONLY DESIRED INDEX BITS
	LOAD T2,STGADR,@CST1X+T2 ;CHECK BACKUP ADR
	TXNN T2,DSKAB		;ON DISK ALREADY?
	JRST MOVDS2		;NO
	HRRZ T2,T1		;GET ONLY DESIRED INDEX BITS
	LOAD T2,CSTAGE,+T2	;YES, CHECK STATE
	CAIN T2,PSRPQ		;ON RPLQ ALREADY?
	RET			;YES, DONE
MOVDS2:	CALL AGECHK		;MAKE PAGE IN USE
	CALL SKPNWR		;CHECK FOR WRITE AGAIN
	 JRST MOVDSK		;WAS WRITE IN PROGRESS. TRY AGAIN
	MOVX T3,DSKSWB		;MAKE SURE IT GOES TO DISK
	HRRZ T2,T1		;GET ONLY DESIRED INDEX BITS
	IORM T3,@CST3X+T2      	;BY REQUESTING THIS EXPLICITLY
	CALL SWPOT0		;SWAP IT OUT
	RET			;DONE
;FPTA,FPTAP and FPTAXP -- construct ID corresponding to address

;Accepts:
;	T1/ virtual address plus bit TWUSR (bit 0) if user mode
;	FX/ Fork handle (if calling FPTAX)

;	CALL FPTA or CALL FPTAX or CALL FPTAXP

;Returns +1: always
;		T1/ PTN,,PN if section exists
;		    0 if user mode and section does not exist

; SAME AS FPTAX BUT DOES NOT ALLOW PAGES FAULTS TO HAPPEN CALLERS SHOULD BE
; PREPARED FOR -1,,SPTX WHERE SPTX IS SPT INDEX OF NIC PAGE TABLE

FPTAXP:	SAVEAC <T2,Q1,Q2>
	MOVEI T2,1		;FLAG SENSITIVE TO NIC PAGE TABLES
	JRST FPTAX2

FPTA::	SAVEAC <T2,Q1,Q2,FX>
	MOVE FX,FORKX
	JRST FPTAX1

;FPTAX - SAME AS ABOVE BUT ASSUMES FX ALREADY SETUP

FPTAX::	SAVEAC <T2,Q1,Q2>
FPTAX1:	TDZ T2,T2		;NOT SENSITIVE TO PAGE FAULTS NORMALLY
FPTAX2:	LOAD Q2,VSECNO,T1	;GET SECTION NUMBER
	LOAD Q1,LPGNO,T1	;GET PAGE NUMBER WITHIN SECTION
	JXN T1,TWUSR,[MOVE T1,Q2 ;YES. GET SECTION POINTER
		CALL @[ IFIW!SECIND
			IFIW!SECINP](T2) ;CALL PROPER ROUTINE
		JUMPLE T1,R	;JUMP IF NON-EX SECTION OR NIC SPT
		ANDX T1,STGADM	;GET SPT INDEX ONLY
		JRST FPTAR]

;Address is in monitor. Crash if illegal section. Transfer according to section
;number. PGRINI sets up FPTABL

	CAILE Q2,HGHSEC
ILLFPT::BUG.(HLT,ILFPTE,PAGEM,SOFT,<ILLFPT - Illegal section number referenced>,,<

Cause:	A routine was called to translate a virtual address into an
	internal identifier. The BUGHLT indicates that the caller provided a
	monitor address that contained an invalid section number. This
	can mean any of the following:

	1. The section number is larger than the maximum possible.

	2. On a machine that does not support extended addressing, a
	non-zero section number was provided.
>)
	HRRZ T2,FPTABL(Q2)	;DISPATCH TO APPROPRIATE ROUTINE
	JRST 0(T2)
;Section 0 or 1. Determine page number. If PSB, return
;(SPT index for PSB,,offset for page).

FPTA0::	CAIL Q1,PSVARP		;WHICH PART OF MONITOR?
	CAILE Q1,PSVARL		;PRIVATE PER PROCESS (PSB) ?
	JRST FPTA1		;NO, GO CHECK NEXT AREA
	ADDI Q1,-PSVARP+PSBMAP-PSBPGA ;OFFSET INTO PSBMAP
	CAIGE FX,0		;GOOD FORK HERE?
FPTMX1:	BUG.(HLT,FPTMXX,PAGEM,SOFT,<FPTA - Process address in sched context>,<<T1,ADR>>,<

Cause:	FPTA has been called in scheduler context and given an address
	that is part of the process/job context area.

Data:	ADR - Given address.
>)
	LOAD T1,FKPSB		;GET PSB IDENT
	JRST FPTAR
   IFN EXTJSB,<
;Extended JSB, return (SPT index for page-table,,offset for page)
FPTAJ:: CAIGE FX,0		;Do we have a valid fork?
	JRST FPTMX1		;No, BUGHLT because we are in scheduler
	LOAD T1,FKJPT		;Get SPT index of page-table
	JRST FPTAR		;Continue and add page offset
   >

;Non-extended JSB, return (SPT index for JSB,,offset for page)
FPTA1::	CAIL Q1,JSVARP
	CAILE Q1,JSVARL		;PRIVATE PER JOB (JSB) ?
	JRST FPTA2		;NO, TRY NEXT AREA
	ADDI Q1,-JSVARP+JOBMAP-JSBPGA ;FIRST JOB PAGE MAPPED BY JOBMAP+0
	CAIGE FX,0		;GOOD FORK HERE?
	JRST FPTMX1		;CAN'T BE IN SCHED FOR THIS
	LOAD T1,FKJSB		;GET JSB IDENT
	JRST FPTAR

FPTA2::
	CAIE Q2,MSEC1		;SECTION 1?
	IFSKP.
	  CAIL Q1,RSCODP	;IN RSCOD OR NRCOD?
	  CAILE Q1,RSCODL
	  IFNSK.
	    CAIL Q1,NRCODP
	    CAILE Q1,NRCODL
	    ANNSK.
	  ELSE.
	    MOVE T1,M1SPTN	;YES, SECTION 1 MAP ID
	    JRST FPTAR
	  ENDIF.
	ENDIF.
	MOVE T1,MMSPTN		;NO, SECTION 0 MAP ID
	JRST FPTAR

;Section reserved for directories. Return (OFN for currently mapped directory,,PN)

FPTA6::	CAIGE FX,0		;GOOD FORK HERE?
	JRST FPTMX1		;CAN'T BE IN SCHED HERE
	HRRZ T1,DRMAP		;MAP DIRECTORY
FPTAS:	JUMPE T1,R		;IF NO SECTION POINTER, RETURN 0

;Here to exit. Construct (PTN,,PN) in T1. T1 already has PN. Get PTN from Q1.

FPTAR:	HRLM T1,Q1		;CONSTRUCT PAGE IDENT
	MOVE T1,Q1		;RETURN RESULT
	RET

;Section reserved for index table. Return (OFN for currently mapped index
;table,,PN)

FPTA7::	CAIGE FX,0		;GOOD FORK HERE?
	JRST FPTMX1		;CAN'T BE IN SCHED HERE
	HRRZ T1,IDXMAP		;FIND IDXMAP
	JRST FPTAS		;GO FINISH UP

;SECTION FOR BIT TABLE - MAY BE EMPTY

FPTA8:	LOAD T1,SPTX,MSECTB+BTSEC
	JRST FPTAS

  IFE FTNSPSRV,< ;[6.1]
;Section for extended code, mapped 1-1 with MMAP except for NRCOD
FPTAXC::CAIL Q1,NRCODP		;Is virtual address between NRCOD
	CAILE Q1,NRCODL		; and NRCODZ?
	JRST FPTA0		; -no, mapped 1-1 with MMAP, handle as sec 0/1
	MOVE T1,XCDBAS		;-yes, load SPT index for XCDSEC
	JRST FPTAR		; and go finish up
  >

;INITIAL FPTABL FOR SPECIAL SECTIONS

IFPTBL::FPTA0			;Section zero
	FPTA0			;Section one
	FPTA6			;Directory section
	FPTA7			;Index-table section
	FPTA8			;Bit-table section
	FPTMSS			;DDT and symbol-table section
   IFE FTNSPSRV,<
	FPTAXC			;Extended code section
     IFN EXTJSB,<
	FPTAJ			;Job-storage section
     >
   >

NIFPTL==:.-IFPTBL
;Most monitor sections are identified by the OFN or SPTX in MSECTB

FPTMSS::SKIPN T1,MSECTB(Q2)	;HAVE A SECTION POINTER?
	JRST ILLFPT		;NO - BAD NEWS
	LOAD T2,PTRCOD,T1	;CHECK PTR TYPE
	CAIN T2,SHRCOD		;SHARE?
	IFSKP.
	  BUG.(HLT,ILESCD,PAGEM,SOFT,<Monitor section pointer not shared>,<<T1,POINTER>,<Q2,SECTION>>,<

Cause:	A pointer for a monitor section has been found that is not a
	share pointer.  Only share pointers are expected.  If other
	pointer types are used, this code must be enhanced.  It is possible 
	that the monitor section table has been clobbered.

Data:	POINTER - The pointer.
	SECTION - The monitor section for which it was found.
>)
	ENDIF.
	HRRZ T1,T1		;SHARE POINTER, USE SPT INDEX
	JRST FPTAR		;GO FINISH UP
;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
;
;**;[7303] INSERT 2 LINES AT REMFPB::+0.L	DSW	5/27/86
REMFPB::SKIPN DELPGQ		;[7303] ANY PAGES ON DELETED PAGE QUEUE?
	RET			;[7303] NO, DONE
	PIOFF			; PREVENT INTERRUPTS WHILE REMOVING
	HRRZ T1,DELPGQ		;GET FIRST PAGE ON QUEUE
	HRRZ T1,@CST3X+T1	;GET PAGE IT LINKS TO
	EXCH T1,DELPGQ		;REMOVE FIRST PAGE FROM QUEUE
	PION
	CALL REMFB1		;FINISH UP DELETE
	SKIPE T1		;COMPLETELY DELETED?
	BUG.(HLT,PGNDEL,PAGEM,SOFT,<REMFPB - Page not completely deleted>,,<

Cause:	A page has been marked as partially deleted and placed on a
	queue. The routine that processes the queue has found that the
	page still has a backup on disk. The routine that marked the
	page should have deleted all backup pages.
>)
	JRST REMFPB		;DO ALL PAGES
;REMOVE PAGE FROM SYSTEM (DELETE PERMANENT AND TEMPORARY ADDRESSES)
; 1/ STORAGE ADDRESS
;If address is disk or drum, deassignment proceeds immediately.
;If address is core, deassignment must wait in the one case that
;a write is in progress to the disk.  If a write is in progress to
;the drum, CST2 is left 0 and SWPDON cleans up.

REMFP1::SAVEAC <Q1>
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 [	SETZ T1,	;UNASSIGNED, DONE
		RET]
	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
		SETZ T1,	;IGNORE
		RET]
	LOAD 2,CSTAGE,+Q1	;GET PAGE STATE CODE
	CAIL 2,PSASN		;ASSIGNED TO PROCESS?
	CALL DECOR		;YES, DEASSIGN
	HLRZ 2,@CST2X+Q1		;GET PTN OF OWNING PT
	IFN. T2
	  HRRZ 3,SPT(2)		;GET ADR OF OWNING PT
	  CALL ULKP3
	ENDIF.
	MOVE T2,@CST1X+Q1	;GET BACKUP
	TXNE T2,DSKAB		;DISK?
	JRST [	NOSKED		;YES, STAY NOSKED FOR WRITE CHECK
		CALL SKPNWR	;BEING WRITTEN?
		 NOP		;DONE NOW
		OKSKED
		JRST REMFB2]	;FINISH UP
	TXNN T2,DRMAB		;DRUM?
	JRST REMFB2		;NO, UNASSIGNED. GO FINISH UP
	CALL GDSTX		;GET DST INDEX
	MOVX T1,UAAB
	EXCH T1,(T2)		;RESET BACKUP
	TXNN T1,DSKAB		;WAS DISK?
	SETZ T1,		;NO, UNASSIGNED
	PIOFF
	SETZM @CST2X+Q1		;FLUSH BACKUP PTR
	MOVE T3,@CST3X+Q1	;GET CURRENT DWRBIT
	PION
	TXNE T3,DWRBIT		;WRITE STILL IN PROGRESS?
	RET			;YES, COMPLETION HANDLED BY SWPDON
	SAVEAC <T1>		;NO, FINISH UP NOW, RETURN ADR NOW IN T1
	MOVE T1,Q1
REMFB2:	HRRZ Q1,T1
	SETZM @CST2X+Q1		;FLUSH BACK PTR
	MOVSI 4,(-PLKV)
	LOAD 3,CSTAGE,+Q1	;GET STATE CODE
	CAIE 3,PSRPQ		;ON RPLQ?
	TDNE 4,@CST1X+Q1	;OR LOCKED IN CORE?
	SKIPA			;YES, LEAVE IT
	CALL OFRQ		;PUT ON TOP OF RPLQ SINCE NOT TO BE REUSED
	MOVSI T1,(-PLKV)
	AND T1,@CST1X+Q1	;FLUSH BACKUP ADDRESS, LEAVE LK CNT
	EXCH T1,@CST1X+Q1	;GET BACKUP ADDRESS
	JRST REMFPA

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

;ALTERNATE ENTRY - FROM REMFPB ONLY, ASSUMES CORE PAGE AND CST2 ALREADY 0
; T1/ CORE PAGE NUMBER

REMFB1:	SAVEAC <Q1>
	JRST REMFB2		;JOIN REGULAR SEQUENCE
;**;[7247]  Add routine ISOCSH				DML	19-Feb-86
;[7247] IOSCSH - Routine which determines if a page belongs to a cached OFN
;[7247] 
;[7247] Accepts:	T1/ Core page number of page
;[7247] 
;[7247] Returns:	+1 - Page belongs to cached OFN
;[7247] 		+2 - Page does NOT belong to cached OFN
;[7247] 
;[7247] Preserves all ACs

ISOCSH::SAVEAC <T2>		;[7247] Save the used AC
	NOSKED			;[7247] Own system for awhile
	MOVE T2,@CST2X+T1	;[7247] Get PTN,,PN
	TLNE T2,-1		;[7247] Is this a page in a PT?
	HLRZS T2		;[7247] Yes, so position PT
	CAIL T2,NOFN		;[7247] Does page really belong to an OFN?
	JRST ISOSKP 		;[7247] No
	TMNN OFNCSH,(T2)	;[7247] Is this OFN cached?
	IFSKP.			;[7247] Yes
       	  OKSKED		;[7247] 
	  RET			;[7247] 
	ELSE.			;[7247] No
ISOSKP:	  OKSKED		;[7247] 
	  RETSKP		;[7247] 
	ENDIF.		 	;[7247] 
;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::	SAVEAC <FX>
	MOVE FX,FORKX
	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
	 NOP			;IGNORE INCOMPLETE
	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

PRENRF==1B0			;PAGE NOT READY FLAG
PRERST==1B1			;WS HAS BEEN RESET

PRELD::	TRVAR <PREOKF>
	SETOM PRELRQ		;NOTE PRELOADING REQUESTS FOR SWAPPER
	SETZM PREOKF		;CLEAR FLAGS
	CALL SETPP1		;SETUP MAP FOR FORK
	LOAD T1,FKWSS		;SEE IF FKNR HAS BEEN RESET, I.E.
	CAMGE T1,NWSCE		;.L. NWSEC AND .LE. MINWSS
	CAMLE T1,MINWSS
	JRST PRELD1		;NO, PRELOAD
	MOVX T1,PRERST		;YES, FLAG RESET
	IORM T1,PREOKF
PRELD1:	MOVE T1,[CALL PRELW1]	;MAP ALL PAGES IN WS
	CALL MAPWSC
	CALL SETPSK		;RESET TO SCHED CONTEXT
	SETZM PRELRQ
	MOVE T1,PREOKF
	TXNN T1,PRENRF		;ALL PAGES READY?
	RETSKP			;YES
	HRLZ T1,T1		;NO, RETURN TEST FOR NOT READY PAGE
	HRRI T1,PRELWT
	RET

PRELWT::JUMPN T1,SWPRT		;CHECK PAGE IF HAVE PAGE NUMBER
	MOVE T2,NRPLQ		;OTHERWISE, CHECK RPLQ
	CAMG T2,NRPMX
	JRST 0(T4)
	JRST 1(T4)

;ROUTINE CALLED FOR EACH PAGE OF WS
; T1/ VIRTUAL ADDRESS IN PAGE FAIL FORMAT

PRELW1:	MOVE T2,PREOKF
	TXNE T2,PRERST		;WS RESET?
	JRST [	CALLRET DELWSC]	;YES, REMOVE ENTRY FROM WS CACHE
	MOVE T2,NRPLQ
	CAMG T2,NRPMX		;ROOM FOR ANOTHER PAGE?
	JRST PRELW2		;NO
	TXNE T1,TWUSR		;USER SECTION 0?
	TXNE T1,VSECNO
	JRST [	CALL FPTAX	;NO, GET ID
		JUMPE T1,R	;QUIT IF NO SECTION PTR
		CALL PREPGP	;LOAD THE PAGE
		 JRST PRELW3	;NOT COMPLETE
		RET]
	LOAD T1,LPGNO,T1	;GET PAGE NUMBER
	MOVE T2,UPTPGA(T1)	;GET PTR
	LOAD T3,FKUPT		;CONSTRUCT ID FOR USER SECTION 0 PAGE
	HRL T1,T3
	CALL PREPG1		;LOAD THE PAGE
	 JRST PRELW3		;NOT COMPLETE
	RET

PRELW3:	HRRM T1,PREOKF		;SAVE PAGE NUMBER
PRELW2:	MOVX T1,PRENRF
	IORM T1,PREOKF		;NOTE SAW A PAGE NOT READY
	RET
;PRELOAD A PAGE - INITIATE SWAPIN IF PAGE NOT ALREADY IN CORE
; T1/ IDENT
;	CALL PREPGP
; RETURN +1: PAGE BEING LOADED, T1/ PAGE NUMBER
; RETURN +2: PAGE READY NOW

PREPGP::STKVAR <PREPID,ICNT>
	MOVEI T3,MAXIND		;SETUP INDIRECT COUNT
	MOVEM T3,ICNT
	MOVEM T1,PREPID
	HLRZ T1,T1
	JUMPN T1,PREPP1		;JUMP IF HAVE PTN
	HRRZ T1,PREPID		;SPTN GIVEN
	MOVE T2,T1		;Copy it
	CALL PRLCHK		;Do all checks
	 JRST PREPG2		;Can't touch it
	LOAD T2,STGADR,SPT(T1)	;GET ADR
	JRST PREPG5

;SAME AS ABOVE BUT FASTER IF PTR ALREADY FETCHED
; 1/ IDENT OF PAGE
; 2/ PTR
;	CALL PREPG1
; RETURN +1: ALWAYS

PREPG1:	STKVAR <PREPID,ICNT>
	MOVEI T3,MAXIND		;SETUP INDIRECT COUNT
	MOVEM T3,ICNT
	MOVEM T1,PREPID
PREPG0:	JUMPE T2,PREPG2		;JUMP IF NO PAGE
	LOAD 3,PTRCOD,2		;GET PTR TYPE
	CAIN 3,INDCOD		;AN INDIRECT POINTER?
	JRST PREPG3		;YES
	CAIN 3,SHRCOD		;SHARED?
	JRST [	LOAD 1,SPTX,2	;YES, GET SPT INDEX
		MOVE 2,1	;SPTN TO 2
		CALL PRLCHK	;Do all checks
		 JRST PREPG2	;IT IS, IGNORE IT
		LOAD 2,STGADR,SPT(1) ;AND ADDRESS FROM SPT
		JRST .+1]
PREPG5:	TLNE 2,(NCORTM)		;PAGE NOW IN CORE?
	JRST [	TLNN 2,(DSKAB+DRMAB) ;PAGE IS ASSIGNED?
		JRST PREPG2	;NO
		SKIPLE NRPLQ	;FREE PAGE AVAILABLE?
		CALL SWPIN	;YES, SWAP IT IN
		HLRZ T1,T1	;LEAVE PAGE ONLY IN T1
		JRST PREPGX]	;PAGE NOT READY YET
	CALL PRELSC		;SET CST APPROPRIATELY
	 JRST PREPGX		;PAGE NOT READY YET
PREPG2:	RETSKP			;RETURN PAGE READY FOR USE

PREPGX:	RET			;RETURN PAGE NOT READY
;INDIRECT PTR

PREPG3:	LOAD T1,SPTX,T2		;PTN
	LOAD T2,IPPGN,T2	;PAGE NUMBER
	HRL T2,T1		;CONSTRUCT NEW IDENT
	MOVEM T2,PREPID		;SAVE IT
PREPP1:	MOVE T2,T1
	CALL PRLCHK		;Do all checks
	 JRST PREPG2		;YES, IGNORE IT
	LOAD T2,STGADR,SPT(T1)	;PT ADDRESS
	TXNE T2,NCORTM		;IN CORE?
	JRST PREPG5		;NO, GO LOAD IT
	CALL PRELSC		;YES, CHECK CST, ETC.
	 JRST PREPGX		;NOT READY, CAN'T GET PTR FROM IT
	HRRZ T1,PREPID		;CAN FETCH PTR FROM IT
	CALL MOVRCA
	MOVE T2,T1
	MOVE T1,PREPID
	SOSLE ICNT		;COUNT INDIRECT PTRS SEEN
	JRST PREPG0		;TRY AGAIN
	JRST PREPG2		;INDIRECT LOOP, INGORE IT

;CHECK AND FIXUP CST AS APPROPRIATE FOR PAGE BEING PRELOADED

PRELSC:	HRRZ T1,T2		;FLUSH LH, LEAVE PN IN T1
	LOAD T3,CSTAGE,+T1	;PAGE IS IN CORE, SEE WHAT STATE
	CAIL T3,PSASN		;ASSIGNED?
	RETSKP			;YES, CAN BE USED NOW
	CAIN T3,PSRIP		;READ IN PROGRESS?
	RET			;YES, CANNOT BE USED
	CALL AGESN		;OTHERWISE CAN BE ASSIGNED
	RETSKP			;CAN BE USED NOW

;Here to check on SPT slot for PREPG
;	T2/ SPT offset to check

PRLCHK:	SAVEAC <T1>
	CALL CHKDMO		;Is it mounted?
	 RETBAD			;No. Error then
	CAIGE T2,NOFN		;Is this an OFN?
	SKIPA T1,T2		;Yes
	HLRZ T1,SPTH(T2)	;No. Maybe it is part of an OFN
	JUMPE T1,RSKP		;If a zero, not an OFN
	MOVE T1,SPTO2(T1)	;Get the flags word
;   IFN CFSCOD,<
	TXNE T1,SPTST		;If we've no access
;   >		;IFN CFSCOD
	TXNE T1,SPTSFD!SPTFO	;or if it is being forced out
	RET			;Give up
	RETSKP			;OK!
;CHECK AGE FIELD OF PAGE TO ENSURE TEMPORARY ACCESS.  IF PAGE MUST
;BE ASSIGNED, DEASSIGN IT IMMEDIATELY SO GCCOR WILL CATCH IT.
; T1/ CORE PAGE NUMBER
;	CALL AGECHK
; RETURN +1 ALWAYS

AGECHK::PUSH P,FX
	MOVE FX,FORKX		;GET SELF
	CALL AGECKN		;DO THE WORK
	POP P,FX
	RET

;SAME AS ABOVE BUT EXPECTS FX ALREADY SETUP
; T1/ CORE PAGE NUMBER
; FX/ FORK INDEX
;	CALL AGECKN
; RETURN +1 ALWAYS

AGECKN::PUSH P,T2		;MUST PRESERVE THIS
	HRRZ T1,T1
	LOAD T2,CSTAGE,+T1
	CAIL T2,PSASN		;NOW ASSIGNED?
	JRST [	LOAD T2,CSTOFK,+T1 ;YES, CHECK OWNER
		CAIL T2,NFKS	;OWNED?
		JRST PB2	;NO
		JRST AGECK0]	;YES, DEASSIGN
	CALL AGESN		;MAKE ACCESSABLE
AGECK0:	CALL XDECR0		;DEASSING
	CALLRET PB2		;AND DONE
;DEASSIGN CORE
; T1/ CORE PAGE NUMBER
;RETURN +1 ALWAYS, LH OF T1 CLEARED

DECOR::	TLNE T1,(NCORTM)	;GIVEN MAP WORD, NOW IN CORE?
	RET			;NO, NOTHING TO DO
	SAVEAC <T2>
	HRRZ T1,T1
	LOAD T2,CSTAGE,+T1	;GET STATE CODE
	CAIGE T2,PSASN		;NOW ASSIGNED?
	RET			;NO
	LOAD T2,CSTOFK,+T1	;GET PROCESS ASSIGNMENT
	CAIL T2,NFKS		;ASSIGNED?
	RET			;NO
	CALL SOSWSP		;REDUCE N FOR THIS PROCESS
	MOVX T2,OFNUL		;MARK PAGE UNASSIGNED
	STOR T2,CSTOFK,+T1
   REPEAT 0,<			;LEAVE PAGE UNCHARGED UNTIL NEXT GCCOR
	MOVX T2,-PLKV
	TDNE T2,@CST1X+T1	;LOCKED?
	JRST [	AOS BALSHC	;YES, CHARGE TO SYSTEM
		AOS SUMNR
		AOS SUMBNR
		JRST .+1]
   >				;END REPEAT 0
	RET

;DECOR AND RESET LAST REFERENCE
;AS ABOVE BUT ASSUMING ASSIGNED CORE PAGE AND T2 AVAILABLE

XDECOR:	LOAD T2,CSTOFK,+T1	;OWNER?
	CAIL T2,NFKS
	RET			;NO
XDECR0:	CALL SOSWSP		;REDUCE FKWSP
	MOVX T2,CFXNUL
	STOR T2,CFXRD,+T1	;RESET LAST REF
	MOVX T2,OFNUL
	STOR T2,CSTOFK,+T1	;RESET OWNER
	RET
;DECREMENT WSP AND RELEASE CORE NUMBER IF WSP 0
; T1/ CORE PAGE NUMBER
;RETURN +1 ALWAYS, ALL ACS PRESERVED

SOSWSP:	SAVEAC <T2,FX>
	LOAD FX,CSTOFK,+T1	;GET FORK ASSIGNMENT
	LOAD T2,FKCSIZ		;GET CURRENT COUNT
	SOJL T2,[BUG.(CHK,WSPNEG,PAGEM,HARD,<SOSWSP - WSP negative>,<<FX,FORK>,<T2,FKCSIZ>>,<

Cause:	SOSWSP has been been called to decrement the working set size of
	the current fork by one. In so doing, the working set size would
	become negative. This indicates a problem with the monitor's
	calculation of the fork's working set size since it should never be
	negative.

Action:	The working set size has not been decremented.

Data:	FORK - Fork number
	FKCSIZ - Current size of working set (RH of FKWSP)
>)
		JRST SOSWS1]	;DON'T ALLOW NEGATIVE
	STOR T2,FKCSIZ		;UPDATE COUNT
SOSWS1:	RET
;GARBAGE COLLECT CORE, REMOVE PAGES OF PROCESSES NOT IN BAL SET

;TEST FOR GCCOR NEEDED - CALLED FROM SCHED.  IF GCCOR NEEDED, OVERHEAD
;CHARGING IS SWITCHED BEFORE CALL TO GCCOR

TSTGCC::SKIPE SKEDFC		;FORCED CLEAR?
	RETSKP			;YES, DO GCCOR
	SKIPG DRMTPG		;SWAPPING INITIALIZED?
	RET			;NO, DO NOTHING
	MOVE T2,TODCLK
	SUB T2,LSTAGE		;COMPUTE TIME SINCE LAST GCCOR
	CAIL T2,<AGEWRP-200>*GLATCK	;NEAR END OF RANGE?
	RETSKP			;YES, COLLECT
	RET			;NO, DO NOTHING

GLATCK==:^D100			;MS PER TICK OF GLOBAL PAGE AGE CLOCK
SHRWND:	^D1000/GLATCK		;SHARED PAGE AGE WINDOW
;MAIN ROUTINE - FUNCTIONS SOMEWHAT DIFFERENTLY DEPENDING ON POSPGF.
;UPDATES BALSHC BASED ON NUMBER OF PAGES BEING KEPT IN CORE BECAUSE
;THEY ARE LOCKED OR BECAUSE THEY ARE IN USE BY BALSET FORKS.
;AC USE:
; P1/ RUNNING COUNT OF AVAILABLE PAGES
; P2/ MASK OF CORE NUMBERS OF BALSET FORKS
; P3/ MASK OF RECENTLY RELEASED CORE NUMBERS TO BE CLEARED FROM CST0
; P4/ AOBJN PTR TO CST

GCCOR::	SKIPG DRMTPG		;DRUM INITED?
	RET			;NO, DO NOTHING
	SAVEP
	AOS NGCCOR		;COUNT OCCURRANCES
	SETZ P2,
	MOVE 1,NRPMX
	SKIPN SKEDFC		;DEPG ALL IF FORCED CLEAR
	CAMLE 1,NRPLQ
	MOVE 1,NRPLQ		;INSPECT N PAGES
	JUMPE 1,GCWS4		;N MAY BE 0 ...
	HRRZ P3,@SRPLQ		;GET FIRST PAGE
GCPC1:	CAIN P3,SRPLQO
	HRRZ P3,@DRPLQ
	MOVEI T3,(P3)
	CALL DEPGS		;UNDO POINTER AND FLUSH BACK PTR,
	SETZM @CST2X+3		;THUS UNLOCKING OWNING PT
	HRRZ P3,@CST3X+P3
	SOJG 1,GCPC1
GCWS4:	MOVE P1,NRPLQ
	ADD P1,IOIP		;WRITES NOW IN PROGRESS
	MOVE T1,TODCLK		;UPDATE CURAGE
	IDIVI T1,GLATCK
	IDIVI T1,AGEWRP		;REM = VALUE IN RANGE FOR AGE REG
	MOVEI T1,LGABOT(T2)	;ADD BIAS
	MOVEM T1,CURAGE
	MOVE T2,NWSMEM
	CAIG T2,1		;ONLY 1 FORK IN MEM?
	JRST GCWS5		;YES, FLUSH ALL SHARED PAGES
	MOVE T2,NGOJOB
	CAME T2,NBPROC		;ALL RUNNABLE FORKS IN MEM?
	JRST [	SUB T1,SHRWND	;NO, FIXED 1 SEC WINDOW
		JRST GCWS5]
	MOVE T2,TOTRC		;ESTIMATE CORE DEMAND
	SUB T2,SUMBNR
	IMULI T2,^D10
	CAMGE T2,TOTRC		;MIN LIMIT
	MOVE T2,TOTRC
	IDIV T2,TOTRC
	IMUL T2,SHRWND
	SUB T1,T2		;COMPUTE START OF WINDOW
GCWS5:	MOVEM T1,CUTAGE		;SAVE IT
	; ..
	; ..
GCCOR2:	CALL SWPOMI		;INIT SWAPOUT LIST
	SETZM BSHC2
	MOVE P4,MONCOR
	SUB P4,NHIPG		;COMPUTE MAX NUMBER PAGES TO CHECK
	MOVSI P4,-1(P4)
	HRR P4,MONCOR		;SETUP AOBJN PTR
GCC2:	HRRZ T1,P4		;GET ONLY DESIRED INDEX BITS
	LOAD T1,CSTAGE,+T1	;CODE FIELD
	CAIGE 1,PSASN		;PAGE IN USE?
	JRST [	CAIE T1,PSRDN	;NO, READ COMPLETED?
		JRST GCC1	;NO, LEAVE IT
		HRRZ T2,P4	;Page number
		MOVE T2,@CST2X+T2 ;Get owner
		CAIGE T2,NOFN	;An OFN?
		CALL	[	;if so
			 JN SPTDSF,(T1),RSKP ;If XB check needed, leave it
			 RET]	;Otherwise, look some more
		SKIPA
		JRST GCC1	;Don't collect
		SKIPE SKEDFC	;COLLECT ALL?
		JRST GCCS	;YES, COLLECT READ COMPLETED PAGE
		HRRZ FX,P4	;GET ONLY DESIRED INDEX BITS
		LOAD FX,CFXRD,+FX ;GET FX OF FORK WHICH INITIATED READ
		CAIGE FX,NFKS	;IF NOT A FORK,
		SKIPGE FKPT(FX)	;OR FORK DELETED?
		JRST GCCS	;FLUSH PAGE
		HRRZ T1,P4
		CALL AGESN	;ASSIGN PAGE AND SET AGE
		JE FKWSL,,GCCS	;COLLECT PAGE IF WS NOT IN MEM
		JRST GCC1]	;LEAVE PAGE
	SKIPE SKEDFC		;COLLECT ALL?
	JRST GCCS		;YES
	CAMLE T1,CURAGE		;PAGE AGE .G. CURRENT AGE?
	SUBI T1,AGEWRP		;YES, WRAPAROUND
	HRRZ FX,P4		;GET DESIRED INDEX BITS
	LOAD FX,CSTOFK,+FX	;GET OWNING FORK
	CAIL FX,NFKS
	JRST [	MOVX T3,-PLKV	;NONE, PAGE LOCKED?
		HRRZ T2,P4	;GET DESIRED INDEX BITS
		TDNN T3,@CST1X+T2
		JRST GCCA3	;NO, CHECK AGE
		AOS BSHC1	;YES, CHARGE TO SYSTEM
		JRST GCC1]	;DONE WITH PAGE
	SKIPGE FKPT(FX)		;OWNER DELETED? (NOT SUPPOSED TO HAPPEN)
	JRST GCCS		;YES, COLLECT
	JE FKWSL,,GCCS		;COLLECT IF FORK WS NOT LOADED
	LOAD T1,FKXAGE		;GET AGE AT LAST XGC OR WSSWPO
	ANDX T1,<.RTJST XGAGE,XGAGE>
	HRRZ T3,P4		;GET DESIRED INDEX BITS
	LOAD T3,XGAGE,+T3	;GET AGE AT WHICH PAGE LAST INSPECTED
	CAME T3,T1		;SAME?
	JRST GCCS		;NO, PAGE LOST FROM WS CACHE, COLLECT IT
	JRST GCC1		;KEEP

GCCA3:	CAMG T1,CUTAGE		;OLD?
	JRST GCCS		;YES, COLLECT
	HRRZ FX,P4		;GET DESIRED INDEX BITS
	LOAD FX,CFXRD,+FX	;GET IDENT OF LAST REF
	CAIL FX,NFKS
	JRST GCCS		;NONE, COLLECT
	JE FKWSL,,GCCS		;COLLECT IF WS NOT LOADED
	AOS BSHC2		;COUNT DESCRETIONARY SHARED PAGES
	AOS BSHC1		;YES, CHARGE TO SCHED
	JRST GCC1		;DONE WITH PAGE
GCCS:	HRRZ T1,P4
	CALL DECOR		;DEASSIGN PAGE FROM FORK
	HRRZ T2,P4		;GET DESIRED INDEX BITS
	MOVE T2,@CST1X+T2	;BACKUP ADDRESS
	TLNE T2,(-PLKV)		;PAGE LOCKED?
	JRST [	AOS BSHC1	;YES, LEAVE IT AND CHARGE TO SCHED
		JRST GCC1]
;**;[7247]  Add 9 lines after GCCS:+6			DML	19-Feb-86
	CALL ISOCSH		;[7247] (T1/) Does page belong to cached OFN?
	IFNSK.			;[7247] Yes
	  MOVE T2,@CST2X+T1	;[7247] Get PTN,,PT
	  TLNE T2,-1		;[7247] Is this a PT or PTT?
	  IFSKP.     		;[7247] Yes, share count should be 0 since cached
	    AOS BSHC1		;[7247] Keep this page and count it
	    JRST GCC1		;[7247] Don't collect, let FREOFG do it
	  ENDIF.		;[7247] 
	ENDIF.			;[7247] 
	MOVSI T2,(DWRBIT)
	HRRZ T1,P4		;GET DESIRED INDEX BITS
	TDNE T2,@CST3X+T1	;PAGE BEING WRITTEN?
	JRST GCC1		;YES, LEAVE IT
	HRRZ T1,P4		;SWAPOUT
	MOVX T2,CORMB
	TDNE T2,@CST0X+T1      	;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
	AOS SGCCWR		;SYSTEM TOTAL
GCC1:	AOBJN P4,GCC2
	HRRZ T1,P4
	CAMLE T1,NHIPG		;REACHED END OF CORE?
	CALL GCECOR		;YES, WRAPAROUND, UPDATE VARIABLES, ETC.
	MOVEM P4,GCCLPG		;REMEMBER LAST PAGE DONE
	CALL SWPOMG		;DO ALL SWAPS QUEUED ABOVE
	SETZM CGFLG
	MOVE T2,TODCLK		;NOTE TIME OF LAST GCCOR
	MOVEM T2,LSTAGE
GCCZ:	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		;UPDATE SUMNR AND SUMBNR BY DIFFERENCE
	ADDM T1,SUMBNR
	PION
	SETZM BSHC1		;RESET NEW SHARE COUNT
	RET

;UPDATE SUMNR AND SUMBNR
; T1/ DIFFERENCE
; FX/ FORKX

UPDSNR:	OPSTRM <ADDM T1,>,FKWSS
	ADDM T1,SUMNR
	JE FKIBS,,R		;DONE IF FORK NOT IN BALSET
	ADDM T1,SUMBNR
	RET
;FORK GC - COLLECT PAGES FOR SPECIFIED PROCESS
; FX/ FORK INDEX
;	CALL FKGC

FKGC::	SAVEAC <P1>
	MOVE T1,MONCOR		;SETUP AOBJN PTR
	SUB T1,NHIPG
	MOVSI P1,-1(T1)
	HRR P1,MONCOR
	CALL SWPOMI		;INIT SWAPOUT LIST
FGC1:	HRRZ T1,P1		;GET ONLY PAGE NUMBER
	LOAD T2,CSTOFK,+T1	;GET OWNING FORK INDEX
	CAMN T2,FX		;SAME FORK?
	CALL FGC2		;YES, COLLECT IT
FGC3:	AOBJN P1,FGC1		;DO ALL PAGES
	CALL SWPOMG		;SWAPOUT LIST
	RET			;DONE OK

;SUBROUTINE OF THE ABOVE - CALLED FOR EACH PAGE THAT IS TO BE GARBAGE COLLECTED
;
; T1/ PAGE NUMBER
;
; RETURNS +1: ALWAYS, PAGE COLLECTED IF NOT BEING WRITTEN OR LOCKED
;
FGC2:	LOAD T2,CSTAGE,+T1	;GET PAGE AGE
	CAIGE T2,PSASN		;PAGE ASSIGNED?
	RET			;NO, DONE
	CALL XDECR0		;YES, DEASSIGN
	MOVX T3,-PLKV
	MOVX T2,DWRBIT
	TDNN T3,@CST1X+T1	;PAGE LOCKED?
	TDNE T2,@CST3X+T1	;PAGE BEING WRITTEN?
	RET			;LOCKED OR BEING WRITTEN, SKIP IT
	MOVX T2,CORMB
	TDNE T2,@CST0X+T1	;PAGE MODIFIED?
	SKIPG SWRSAF		;REASSIGN SWAP ADDRESSES?
	 CALLRET SWPOUT		;NO, SINGLE PAGE SWPOUT
	CALLRET SWPOML		;YES, YES - BUILD SWAP LIST
;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 T1,SWPLSO		;INIT END PTR
	MOVEM T1,SWPLSI
	MOVE T2,CST3X		;GET CST3X BASE ADDRESS
	ADD T2,T1		;GET SWPLSO ADDRESS
	MOVEM T2,SWPLST		;SAVE THE SWP LIST POINTER
	MOVEM T1,@SWPLST
	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:
	HRRZ T3,T1		;GET DESIRED INDEX BITS
	TMNN CSTPST,+T3		;PAGE AVAILABLE?
	SKIPN T2,@CST2X+T3	;PTR BACKUP EXISTS?
	JRST SWPOM1		;NO, EXCEPTION CASE.
	HLRZ T3,T2		;CHECK IF IN SPT
	JUMPN T3,[CAIGE T3,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:	HRRZ T2,T1		;GET DESIRED INDEX BITS ONLY
	MOVE T2,@CST1X+T2      	;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,(2)		;GET NEXT LEVEL BACKUP ADDRESS
	MOVX 4,CORMB
	PUSH P,1
	HRRZS T1		;GET ONLY DESIRED INDEX BITS
	TLZE 3,(BWRBIT)		;MODIFIED ON DRUM?
	IORM 4,@CST0X+T1	;YES, NOTE
	SETOM (T2)		;FLUSH DST SLOT
	EXCH T3,@CST1X+T1	;REPLACE BACKUP ADDRESS FOR PAGE
	MOVE 1,3		;GET DRUM ADDRESS
	CALL DASDRM		;DEASSIGN IT
	POP P,1
	MOVEI 2,(1)		;PUT PAGE ON SWAPOUT LIST
	HLLZS @CST3X+2		;MARK END OF LIST WITH 0
	HRRZ 3,SWPLSI		;GET PAGE POINTER BY SWPLSI
	HRRM 2,@CST3X+3		;SAVE NEW POINTER
	MOVEM 2,SWPLSI		;UPDATE END PTR
	AOS SWPRC0		;COUNT PAGES ON LIST
	MOVX T2,DWRBIT
	HRRZ T3,T1		;GET ONLY DESIRED INDEX BITS
	IORM T2,@CST3X+T3	;NOTE WRITE IN PROGRESS
	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
	IFNSK.			;ERROR?
	  BUG.(CHK,SMGFUL,PAGEM,SOFT,<Can't swap multiple pages (drum is full)>,,<

Cause:	The monitor is attempting to swap a group of core pages to the
	drum. There is no space available.  The general handling
	of drum assignments should insure that there are always a
	few pages available for "critical" assignments such as
	this case. It is possible that some user program could overtax 
	the normal reserves and cause this failure.
>)				;YES, THE DRUM IS FULL
	  POP P,P2		;RESTORE ACS
	  POP P,P1
	  RET			;RETURN AND LEAVE PAGES
	ENDIF.
	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:
	CAIN P1,SWPLSO		;END OF LIST?
	 JRST SWPOG3		;YES
	MOVE 1,SWPDAD		;HAVE ANOTHER PAGE TO DO, GET NEXT DRUM
	CALL DRMASA		; ADDRESS IN SEQUENCE AND ASSIGN IT
	 BUG.(HLT,ASGSW2,PAGEM,SOFT,<SWPOMG - Cannot assign reserved drum address>,,<

Cause:	The monitor is swapping a group of pages to a set of contiguous
	pages in the swapping space. The swapping space manager has
	provided a starting address for a block of free pages. An attempt
	to assign one of the pages has failed. This indicates an
	inconsistency in the monitor's data or a race condition.
	For example, a context switch may have occurred when it was
	not expected.
>)
	MOVEI 1,0(P1)		;GET PAGE NUMBER
	MOVE 2,SWPDAD		;GET NEW DRUM ADDRESS
	MOVE 4,@CST1X+1		;GET PRESENT BACKUP ADR FOR PAGE
	MOVEM 2,@CST1X+1	;SET DRUM ADR AS NEW BACKUP
	CALL GDSTX		;GET DST INDEX FOR DRUM ADDRESS
	MOVX 3,CORMB
	TDNE 3,@CST0X+1		;PAGE WAS MODIFIED IN CORE?
	TLO 4,(BWRBIT)		;YES, MEANS MODIFIED RELATIVE TO DISK TOO
	MOVEM 4,(2)		;SAVE DISK ADR OF PAGE
	ANDCAM 3,@CST0X+1	;CLEAR MODIFIED BIT IN CORE
	SETO T3,
	STOR T3,CFXRD,+T1	;SAY NO FORK WAITING FOR PAGE
	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,@CST3X+P1 ;DO CDR IF HAVE MORE PAGES IN THIS GROUP
		JRST SWPOG1]	;GO DO NEXT ONE
SWPOG3:	HRRZ 1,@CST3X+P1		;END OF GROUP, GET PTR TO NEXT GROUP
	HLLZS @CST3X+P1		;TIE OFF LIST
	EXCH 1,@SWPLST		;SET NEXT LIST, GET CURRENT LIST
	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
SWPDRX==1B1

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

SWPOUX::SAVEAC<Q1>
	MOVX Q1,SWPDRX		;Must go to drum
	JRST SWPOT1		;Join common code

SWPOT0::SAVEAC <Q1>
	MOVX Q1,0
SWPOT1:	TLNE T1,(NCORTM)       	;IN CORE?
	JRST SWPTBD		;NO
	HRRZ T2,T1
	CAML T2,MONCOR		;NO, LEGAL PAGE NUMBER?
	CAMLE T2,NHIPG
	JRST [	CALL RESPCK	;PART OF RESMON?
		 JRST .+1	;NO. SWAP IT OUT THEN
		JRST SWPTBD]	;YES. ERROR OF SOME SORT
	CALL AGECHK		;CHECK AND DEASSIGN PAGE
	HRRZ T3,T1		;GET ONLY DESIRED INDEX BITS
	MOVE T2,@CST1X+T3
	TLNE T2,(-PLKV)		;CAN SWAP IT OUT?
	JRST SWPTBD		;NO, LOCKED
	MOVSI T2,(DWRBIT)
	TDNE T2,@CST3X+T3      	;BEING WRITTEN?
	JRST SWPTBD		;YES
	CALLRET SWPOU0		;ALL OK, SWAPOUT THE PAGE

;HERE IF ANYTHING WRONG WITH PAGE

SWPTBD:	BUG.(HLT,ILPAG1,PAGEM,SOFT,<SWPOT0 - Invalid page>,,<

Cause:	A routine was called to swap out a page in core. The BUGHLT
	indicates that the caller provided a bad argument, resulting
	in one of the following:

	1. The page is not in core.

	2. The page is part of the resident monitor.

	3. The page is locked in memory.

	4. The page is already being swapped.
>)
;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:	HRRZ T2,T1
	SKIPN 2,@CST2X+2	;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:	HRRZ T2,T1
	MOVE 2,@CST3X+T2
	TLNE 2,(DSKSWB)		;SWAP TO DISK REQUESTED BY DDMP?
	JRST BKUPD		;YES
BKUPS:	HRRZ T2,T1
	MOVE 2,@CST1X+T2	;CORE PAGE NUMBER IN 1, GET BACKUP ADR
	TLNN 2,(DSKAB)		;DISK?
	IFSKP.			;If so
   REPEAT 0,<			;looking at DRMFRE is not always right
	 MOVE T3,DRMFRE		;See if we've enough swapping space
	 CAML T3,DRMIN0		;Do we?
	 JRST SWPO4		;Yes. Go swap it out then
   >	;RERPEAT 0
	 HRRZ T3,T1		;Get page number again
	 MOVE T3,@CST0X+T3	;Get CST0 word
	 TXNE T3,CORMB		;Is it modified?
	 JRST SWPO4		;Yes. Must swap it then
	 JRST BKUPN		;No. Recyle the page
	ENDIF.
	TLNN 2,(DRMAB)		;No. Is it unassigned?
	JRST SWPO4		;YES
BKUP0:	HRRZ T3,T1
	MOVE 3,@CST0X+T3	;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,(2)
SWPO2:	CALL CHPERR		;SEE IF PAGE HAS PARITY ERROR
	 RET			;IT DOES. GIVE UP NOW
	HRRZS T1		;TURN OFF UNWANTED BITS
	MOVX 3,CORMB
	ANDCAM 3,@CST0X+1	;CLEAR WRITTEN BIT
	SETO T3,
	STOR T3,CFXRD,+T1	;SAY NO FORK WAITING FOR PAGE
	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

;**;[7247]  Replace 3 lines with 13 at SWPOF1:+0	DML	19-Feb-86
SWPOF1:	SKIPE T3		;[7247] OFN still shared and in use?
	IFSKP.			;[7247] No, share count is zero
	  TMNE OFNCSH,(T2)	;[7247] Cached?
	  RET			;[7247] Yes, don't remove it
	  BUG.(CHK,SWOFCT,PAGEM,SOFT,<OFN share count zero but OFN not cached>,,<

Cause:	The monitor is attemping to swap an OFN and it has found that the
 	OFN share count is zero. When this happened, the OFN should have
	been cached.  However, it is not cached.
>)				;[7247] Report unexpected condition
	  MOVE 1,2		;[7247] No. OFN is unused
	  CALLRET CLROFN 	;[7247] So get rid of it
	ENDIF.			;[7247] 
	HRRZ T2,T1
	MOVE 2,@CST1X+T2	;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:	HRRZ T4,T1
	MOVSI T3,(SWPERR)
	TDNE T3,@CST3X+T4	;ERROR READING FROM DISK?
	JRST BKUPN		;YES, DON'T WRITE IT
	MOVE T3,DRMFRE
	SKIPN NSWAPF		;SWAPPING ALLOWED?
	CAMGE T3,DRMIN0		;YES. HAVE ROOM ON THE SWAPPING?
	JRST [	TXNE T2,DSKAB	;NO. HAVE A BACK UP DISK ADDRESS?
		TXNE Q1,SWPDRX	;Or force to drum?
		JRST SWOFN	;NO. PUT IT ON THE SWAP SPACE ANYWAY
		HLRZ T3,@CST2X+T4 ;YES. GET HOME FOR THIS PAGE
		SKIPN T3	;DOES IT LIVE IN AN OFN?
		HRRZ T3,@CST2X+T4 ;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:	SKIPE NSWAPF		;SWAPPING ALLOWED?
	RET			;NO, LEAVE PAGE
	PUSH P,1
	CALL DRMASN		;ASSIGN DRUM ADDRESS
	 JRST [	BUG.(CHK,DRMFUL,PAGEM,SOFT,<Drum completely full>,,<

Cause:	The monitor is attempting to swap a core page to the
	drum. There is no space available.  The general handling
	of drum assignments should insure that here are always a
	few pages available for "critical" assignments such as
	this case. It is possible that some user program could overtax 
	the normal reserves and cause this failure.
>)
		POP P,T1	;NO ROOM, LEAVE PAGE
		RET]
	MOVE 2,1
	POP P,1
	HRRZ T3,T1		;GET ONLY DESIRED INDEX BITS
	MOVE T4,@CST1X+T3      	;GET PREVIOUS BACKUP ADDRESS
	MOVEM T2,@CST1X+T3	;SET DRUM AS NEW BACKUP ADDRESS
	CALL GDSTX
	MOVEM T4,(T2)		;PREVIOUS BACKUP ADDRESS TO DST
SWPP1:	HRRZ T3,T1		;GET ONLY DESIRED INDEX BITS
	MOVE T3,@CST0X+T3	;GET THE CORE STATUS WORD
	TXNE T3,CORMB		;PAGE WRITTEN WHILE IN CORE?
	JRST SWPO5		;YES, SET BACKUP WRITTEN BIT ALSO
	JRST SWPO2		;NO
;SWAP PAGE TO DISK

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

BKUP7:	BUG.(HLT,BKUPDF,PAGEM,SOFT,<BKUPD - Bad CST1 entry or inconsistent CST>,,<

Cause:	A routine has been called to swap a core page to disk or drum.
	It has decided to swap to the disk. The BUGHLT indicates that
	no back address was found in the CST. This usually indicates
	bad data in the CST or a bad pointer in a page table.
>)

BKUP3:	HRRZ T2,T1		;GET ONLY DESIRED INDEX BITS
	MOVX T3,SWPERR
	TDNE T3,@CST3X+T2	;ERROR IN PAGE?
	JRST BKUPN		;YES, DON'T WRITE IT
	CALL CHPERR		;CHECK FOR PARITY ERROR IN PAGE
	 RET			;IS. LEAVE IT ALONE THEN
	MOVX T3,CORMB
	TDNN T3,@CST0X+T2	;PAGE MODIFIED?
	JRST [	TXNN Q1,SWPKPF	;NO, WHICH END OF RPLQ?
		JRST BKUPF	;TOP
		JRST BKUPN]	;END
	ANDCAM T3,@CST0X+T2
	HRLI 1,(DWRBIT)		;REQUEST WRITE
	AOS DSKWR		;COUNT IT FOR STATISTICS
	AOS IOIP		;NOTE WRITE IN PROGRESS
	MOVSI T3,(DSKNB)
	TDNE T3,@CST1X+T2      	;IS THIS A NEW ADDRESS?
	JRST [	ANDCAM T3,@CST1X+T2 ;YES. TURN IT OFF
		HLRZ T3,@CST2X+T2 ;GET OFN
		SKIPN T3	;THIS IT?
		HRRZ T3,@CST2X+T2 ;NO. THIS IS IT THEN
		CAIL 3,NOFN	;IS THIS AN OFN?
		HLRZ T3,SPTH(3)	;NO. GET THE OFN
		SETONE OFNWRB,SPTH(3) ;SET MODIFIED BIT IN THE OFN
		JRST .+1]	;AND PROCEED
	SETO T3,
	STOR T3,CFXRD,+T2	;SAY NO FORK WAITING FOR PAGE
	MOVEI 3,PSWIP		;INDICATE WRITE IN PROGRESS
	STOR 3,CSTAGE,+T2
	LOAD T3,SWPKPF,Q1	;SAVE KEEP FLAG FOR SWPDON
	STOR T3,DSKSWB,@CST3X+T2
	CALLRET DSKIO

;HERE IF PAGE CAN BE PUT DIRECTLY ON RPLQ.

BKUPF:	CALLRET OFRQ		;TOP

BKUPN:	CALLRET ONRQ		;END

;LOCAL ROUTINE OF SWPOUT TO SEE IF MEM PAGE HAS A PARITY ERROR
;IN IT.
;	T1/ PAGE NUMBER
;RETURNS: +1 YES. DON'T SWAP IT
;	  +2 NO. OK TO SWAP IT

CHPERR:	HRRZ T3,T1		;TURN OFF UNWANTED INDEX BITS
	LOAD T3,CSTPST,+T3	;GET STATE OF PAGE
	CAIN T3,PSTERR		;PAGE HAS ERROR?
	RET			;YES. CAN'T SWAP IT THEN
	RETSKP			;NO. ALLOW SWAP
;WHAT YOU'LL FIND ON THE TRAPSK STACK FOR VARIOUS FLAVORS OF PAGE FAULT:

;The page fault handler now allocates space on the stack using TRVAR.
;However, not all locations are saved on all page faults. In addition, more
;words are saved for a KC than for a KL.

;For the KL, the following locations are allocated:

;	TRVAR <<PFHACS,5>,PFHTIM,PFHTMP,PFHPFW,PFHFL,PFHPC>

;THe following shows which words are stored. In addition, PFHTMP is used
;for temporary storage, and CX is pushed onto the stack before the call to
;PFAULT.

;Reference from USER mode, first trap

;PFHTIM   /	? (APPEARS TO BE SOME SORT OF RUN TIME)
;PFHPFW / 	Page fail word
;PFHFL /	FLAGS AT TIME OF TRAP
;PFHPC /	PC AT TIME OF TRAP


;Reference from USER mode, nested trap

;PFHPFW / 	Page fail word
;PFHFL /	FLAGS AT TIME OF TRAP
;PFHPC /	PC AT TIME OF TRAP




;Reference from MONITOR mode, first trap

;PFHACS   /	AC 1
;PFHACS+1 /	AC 2
;PFHACS+2 /	AC 3
;PFHACS+3 /	AC 4
;PFHACS+4 /	AC 7
;PFHTIM /	? (SAME TIME AS ABOVE)
;PFHPFW /	Page fail word
;PFHFL /	FLAGS AT TIME OF TRAP
;PFHPC /	PC AT TIME OF TRAP




;Reference from MONITOR mode, nested trap

;PFHACS   /	AC 1
;PFHACS+1 /	AC 2
;PFHACS+2 /	AC 3
;PFHACS+3 /	AC 4
;PFHACS+4 /	AC 7
;PFHPFW /	Page fail word
;PFHFL /	FLAGS AT TIME OF TRAP
;PFHPC /	PC AT TIME OF TRAP
	SUBTTL Page fault Handler

;PAGER TRAP. Here on page fault. Microcode has stored the following locations
;in the UPT:
;	UPTPFW/ page fail word
;	TRAPFL/ flags at time of trap
;	TRAPPC/ PC at time of trap

TRAPSP:	IOWD NTSK,TRAPSK	;POINTER TO LOCAL STACK

;The KC microcode has set up previous context to be user, current to
;be monitor. This has the same effect as the DATAO below. Note that, for
;both processors, the previous context AC block points to user on nested
;page faults. Thus previous context references will go to the wrong place.

PGRTRP::
   IFN KLFLG,<
	DATAO PAG,SETMON	;SET MON AC BLOCK
   >
	SKIPE INSKED		;IN THE SCHEDULER?
	JRST KIPFS		;GO HANDLE IN PROPER HANDLER
	AOSGE INTDF		;MUST BE NOINT
	JRST [	BUG.(CHK,NSKDT2,PAGEM,SOFT,<PGRTRP - Bad NSKED or INTDF>,,<

Cause:	When a page fault occurred, the running process's interrupt 
	indicator had an abnormally low value. This could
	cause interruptions when it should not. The monitor
	has set the value to prevent interruptions, but this indicates
	a bug in which too many OKINT's have been executed.
>)
		SETZM INTDF	;FIX THE BAD VALUE
		JRST .+1]	;AND PROCEED

;Check for interrupt in progress

	SZPI 177B27		;FROM PI ROUTINE?
	JRST PIPTRP		;YES. GO HANDLE IT THEN

;Count nested traps. If this is the top level, save the stack pointer and
;set up P to point to TRAPSK stack.

	AOSE TRAPC		;FIRST TRAP?
	JRST PGRTR2		;NO, RECURSIVE
	MOVEM P,TRAPAP		;SAVE AC-P
	MOVE P,TRAPSP		;SETUP TRAP STACK
	AOS UTRPCT		;COUNT TRAPS (BUT NOT RECURSIVE ONES)
	AOS STRPCT		;SYSTEM TOTAL
PGRTR2:	PUSH P,CX		;SAVE AC USED BY TRVAR
	CALL PFAULT		;PROCESS THE PAGE FAULT
	IFNSK.			;If return to user
	 OKSKED
	 SETOM INTDF		;FOR USER, MUST BE -1
	 SETOM TRAPC		;RETURNING TO USER. RESET NEST COUNT
	 JRST GOUSR		;RETURN TO USER
	ENDIF.
	OKSKED	
	POP P,CX		;RESTORE THE WORK AC
	SOSGE TRAPC		;RETURNING TO MONITOR. UNDOING TOP LEVEL TRAP?
	MOVE P,TRAPAP		;YES, RESTORE P
	OKINT
	XJRSTF TRAPFL
;PFAULT - Routine to process page faults

;	CALL PFAULT

;RETURNS +1: RETURNING TO USER,
;		FFL AND FPC SET UP
;	 +2: RETURNING TO MONITOR,
;		TRAPFL AND TRAPPC SET UP

;Caller must preserve CX

PFAULT:
   IFN KLFLG,<
	TRVAR <<PFHACS,5>,PFHTIM,PFHTMP,PFHPFW,PFHFL,PFHPC>
	MOVE CX,UPTPFO		;GET TRAP PC
	MOVEM CX,PFHPC		;SAVE IT ON THE STACK
	MOVE CX,UPTPFW		;GET PAGE FAIL WORD
	MOVEM CX,PFHPFW		;SAVE THAT, TOO
	MOVE CX,UPTPFL		;GET TRAP FLAGS
	MOVEM CX,PFHFL		;SAVE ON THE STACK
   >				;END OF IFN KLFLG

   IFN KCFLG,<
	TRVAR <<PFHACS,5>,PFHTIM,PFHTMP,PFHPFW,PFHFL,PFHPC,PFHCD,PFHD1,PFHD2>
	MOVE CX,KCPFOP		;GET TRAP PC
	MOVEM CX,PFHPC		;SAVE IT ON THE STACK

;This is conjuring up a KL-style page fail word. Note that these bits may
;overlap a 30-bit address but can coexist with a 23-bit address.

	MOVE CX,KCPFVA		;GET REFERENCE ADDRESS
	MOVEM CX,PFHPFW		;SAVE ON THE STACK
	MOVE CX,KCPFCD		;GET PAGE FAIL CODE WORD
	ANDX CX,TWUSR!TWWRT!TWHPFF ;PRESERVE CRITICAL BITS
	IORM CX,PFHPFW		;SAVE IT AS ONE WORD FOR GETTPD
	MOVE CX,KCPFCD		;GET PAGE FAIL CODE WORD
	MOVEM CX,PFHCD		;SAVE IT
	MOVE CX,KCPFD1		;GET PAGE FAIL DATA 1 WORD
	MOVEM CX,PFHD1		;SAVE IT
	MOVE CX,KCPFD2		;GET PAGE FAIL DATA 2 WORD
	MOVEM CX,PFHD2		;SAVE IT
	MOVE CX,KCPFOF		;GET TRAP FLAGS
	MOVEM CX,PFHFL		;SAVE ON THE STACK
   >				;END OF IFN KCFLG
	;..
;If reference is from the monitor, save work AC's and previous page fail
;word

	;..
	JXN CX,UMODF,PFAUL3	;TRAPPED FROM USER MODE?
	DMOVEM T1,PFHACS	;NO. SAVE AC'S THAT WE WILL USE
	DMOVEM T3,2+PFHACS
	MOVEM FX,4+PFHACS

;Save the PC if NOSKED

PFAUL3:
IFN SKEDSW,<
	HRRZ T1,PFHPC
	SKIPE NSKED		;A NOSKED PAGE FAULT?
	CALL NBNSB		;YES, REMEMBER PC OF IT
			>	;END IFN SKEDSW

	NOSKED			;NOSKED AND NOINT FOR DURATION OF TRAP

;If not charging user for page fault time, save
;current time base so trap time can be subtracted out.

	SKIPE TRAPC		;IS THIS A NESTED TRAP?
	JRST PFAUL5		;NESTED TRAP, DON'T COUNT TIME TWICE
	SKIPE IPTIM		;INCLUDE PAGE TRAP TIME?
	JRST [	CALL GETHRT	;NO, GET CURRENT RUNTIME
		MOVEM T1,PFHTIM	;SAVE IT
		JRST PFAUL5]
	CALL FRTOFF		;TURN OFF CLOCK

;If user mode, save flags and PC at the top of UPDL. RFSTS looks at the top of
;UPDL for flags and PC if process is in monitor mode.

PFAUL5:	MOVE T2,PFHFL		;GET FLAGS
	TXNN T2,UMODF		;USER MODE?
	JRST PFAUL7		;NO. DON'T COPY.
	MOVE T1,PFHPC		;GET PC
	DMOVEM T1,UPDL		;SAVE PC AND FLAGS ON TOP OF UPDL

;If page fail code indicates "hard" failure, go handle separately.

PFAUL7:	MOVE FX,FORKX
	MOVE T1,PFHPFW
	TXNE T1,TWHPFF		;'HARD' FAILURE?
   IFN KLFLG,<
	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]
   >				;END OF IFN KLFLG
   IFN KCFLG,<
	JRST [	BUG.(HLT,KCHARD,PAGEM,SOFT,<Hard page fault occurred - no code exists>,,<

Cause:	A page fault occurred indicating hard error for a KC. No code exists
	to handle this.
>)]
   >				;END OF IFN KCFLG
;Here on "soft" page fault. For the KC, transfer according to reason code.
;For the KL, go determine the reason and then transfer.

	CALL PGTACC		;ACCOUNT FOR ONE PAGE TRAP AND CALL XGC

   IFN KCFLG,<
	LOAD T1,TWCOD,PFHCD	;GET PAGE FAIL CODE
	CAIL T1,PFVCLN		;IS IT IN THE TABLE?
PFHBUG:	BUG.(HLT,KCPFH8,PAGEM,HARD,<INVALID PAGE FAULT CODE>,,<

Cause:	A page fault occurred in which the "hard error" bit was not set, but
	the code provided by the microcode was not within the range of
	expected codes.

Action:	Debug the microcode
>)
	JRST @PFHVEC(T1)	;GO HANDLE THE FAULT
   >				;END OF IFN KCFLG

;GETTPD will determine cause of trap and return next address to go to in T1.
;If it returns PGUNTP, the reference should succeed.

PFAUL9:	CALL GETTPD		;DETERMINE CAUSE OF TRAP
	CAIN T1,PGUNTP		;ACTION NECESSARY?
	JRST 0(T1)		;NO

;Action is required. Go do it.

	MOVEM T1,PFHTMP		;SAVE DISPATCH ADDRESS
	MOVE T1,PFHPFW		;GET PAGE FAIL WORD
	CALL ADDWSC		;INCLUDE ADDRESS IN WORKING SET
	MOVE T1,PFHTMP		;RESTORE ADDRESS TO GO TO (SECTION-RELATIVE)
	JRST 0(T1)		;AND GO THERE
;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 MEMPA IS NOT WHAT IS NEEDED.
;IN THE UNLIKELY EVENT THAT THIS HAPPENS, WAIT FOR THE NEXT
;OCCURRENCE OF THE BUG.

PIPTRP:
   IFN KLFLG,<
	MOVEM T1,MEMPA		;SAVE AN AC FOR DUMP ANALYSIS
	MOVE T1,UPTPFW		;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
   >				;END OF IFN KLFLG
PIPTR1:	BUG.(HLT,PITRAP,PAGEM,SOFT,<Pager trap while PI in progress>,,<

Cause:	A page fault occurred while a hardware interrupt was in progress.
	This can be the result of hardware failure or a software bug. If
	the page fail word indicates an AR or ARX parity error, the monitor
	has printed an analysis of the problem on the CTY, and a SYSERR
	entry will be created when the monitor is rebooted.
>)
;MEMORY DATA PARITY - DETECTED IN AR/ARX
;Code is 36 or 37 (AR or ARX parity error). Handle it in APRSRV, and
;give interrupt to user.

   IFN KLFLG,<
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

;DISPATCH FOR PAGE FAIL CODES
;These codes are associated with "hard" failures as indicated by bit 1
;in the page fail word. Code in bits 2-5 indicates the particular failure

TWCOD0==20			;FIRST 'HARD' PAGE FAIL CODE
KLCOD0==30			;START OF KL PAGING CODES
PECOD0==36			;MPE GROUP
PFDSPT::JRST PGRTH		;UNUSED (20)
	JRST ILRD		;PROPRIETARY (21)
	JRST PGRTH		;REFILL ERROR (22)
	JRST ADRCMP		;ADDRESS COMPARE (23)
	JRST ILIND		;ILLEGAL INDIRECT (24)
	JRST PGRTH		;PAGE TABLE PARITY (25)
	JRST ILWR		;UNUSED (26)
	JRST ILSN		;ILLEGAL SECTION (27)

;Handle certain errors in APRSRV. Resume at the failing instruction.

PGRTH:	MOVE T1,PFHPFW		;GET PAGE FAIL WORD
	JSP T2,PFAID		;HANDLE HARD PAGE FAIL
PGRTH1:	MOVE T1,UPTPFL		;GET FLAGS WORD (IN CASE MODIFIED)
	MOVEM T1,PFHFL		;SAVE
	MOVE T1,UPTPFO		;GET PC WORD
	MOVEM T1,PFHPC		;SAVE IT
	JRST PGUNTP		;RETRY
   >				;END OF IFN KLFLG

;Here on address compare. Previously-defined address break was hit.
;Give interrupt to the user.

ADRCMP:	SKIPE INSKED		;WEED OUT BUGS
	BUG.(HLT,ABKSKD,PAGEM,SOFT,<Address break from scheduler context>,,<

Cause:	A page failure occurred while the monitor was running in scheduler
	context, and the page fail word indicated an address break. Address
	breaks can only be set in code that runs in process context.
>)
	MOVX T1,PC%AFI		;SET ADDRESS BREAK INHIBIT
	IORM T1,PFHFL		; SO FORK CAN CONTINUE AFTER SUSPENSION
IFN STANSW,<
	SKIPN EXECBK		;ARE WE DEBUGGING THE MONITOR?
	IFSKP.
	  BUG.(CHK,ADRTRP,PAGEM,SOFT,<Address Break at ADRCMP>,<<TRAPPC,PC>,<EXECBK,DATAIO>>)			;YES, PRINT A BUGCHK
	  JRST PGUNTP		;AND EXIT EARLY
	ENDIF.
>;IFN STANSW
	MOVE T2,PFHPC		;GET ADDR OF FAULTING INSTR
	MOVEM T2,ADRBK1		;SAVE FOR THE EXEC
	LOAD T2,TWVADR,PFHPFW	;GET ADDRESS ON WHICH BREAK OCCURRED
	MOVEM T2,ADRBAD		;SAVE FOR THE EXEC
	SETONE <FKPS0,FKABK>,(FX) ;REQUEST ADDRESS BREAK INTERRUPT
	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(NSKDT2)
	JRST -2(T1)		;REDO AOS UNTIL IT WORKS
   >				;END OF REPEAT 0

;Bits 0 and 1 are set in an indirect word.  If indirect word is in the
;  Monitor, then BUGHLT.  If PC is User Mode and in a non-zero section
;  then set up to untrap and subsequently link a Dynamic Library.
;  Otherwise just give illegal memory read.

ILIND:	FTDYN <			;IF DYNAMIC LYBRARY SUPPORT
	MOVE T1,PFHPFW		;Get page fail word
	TXNN T1,TWUSR		;Test in which mode trap occurred
	 IFSKP.			;If the trap was from user mode
	  MOVE T2,PFHFL		;  then first get flags at time of fault
	  JXE T2,UMODF,ILRD	;If PC was in the Monitor, give illegal read
	  MOVE T2,PFHPC		;Now get User PC at time of trap
	  JXE T2,EXSCBT,ILRD	;If section number was zero, give illegal read
	  MOVEM T1,UTRSW	;Save page fail word for DYNLNK
	  XMOVEI T1,DYNLNK	;But if section number of PC was non-zero
	  JRST PGUNTD		;  untrap and dispatch to link Dynamic Library
	 ENDIF.			;IF TRAP OCCURRED IN MONITOR
>				;End of Conditional Assembly
	JRST ILRD		;HANDLE LIKE ILLEGAL READ
REPEAT 0,<
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,PAGEM,SOFT,<I/O NMX from Unibus device>,<<UPTPFW,PFW>,<UPTPFO,PC>>,<

Cause:	The monitor tried to reference a non-existent device on the
	UNIBUS. This BUGHLT occurs only on the 2020.
>)
>


;DYNLNK - Dynamic Library Invocation

	FTDYN <
DYNLNK:	MOVE T1,UTRSW		;Get back page fail word
	LOAD T1,TWVADR,T1	;Get address of indirect word that failed
	XCTU [HRR T1,(T1)]	;Get address of Local Transfer Vector
	CALL LNKLIB		;Link the Dynamic Library
	 ITERR			;Instruction trap if failure return
	MRETNG			;Give successful return
>				;End of Conditional Assembly
   IFN KCFLG,<

;Transfer vector for page fault codes for the KC. Highest-numbered code is
;not generated by microcode, but faked by XGCCHK to force a call to XGC.

PFHVEC:	IFIW!PFHBUG			;CODE 0 - SHOULDN'T HAPPEN
	IFIW!PFWRTF			;CODE 1 - WRITE FAILURE
	IFIW!PFBAGE			;CODE 2 - ILLEGAL AGE WHEN TRANSLATION EXISTS
	IFIW!PFADDB			;CODE 3 - ADDRESS BREAK
	IFIW!PFBSSP			;CODE 4 - ILLEGAL SUPER SECTION POINTER
	IFIW!PFBSEC			;CODE 5 - SECTION GREATER THAN 37
	IFIW!PFBPTR			;CODE 6 - ILLEGAL POINTER
	IFIW!PFNOAC			;CODE 7 - NO ACCESS POINTER
	IFIW!PFNIC			;CODE 10 - NOT IN CORE
	IFIW!PFILAG			;CODE 11 - ILLEGAL AGE
	IFIW!PFMBZ			;CODE 12 - "MUST BE ZERO" BITS ARE NON-ZERO
	IFIW!PFBIND			;CODE 13 - ILLEGAL INDIRECT
	IFIW!PFBPXC			;CODE 14 - ILLEGAL PXCT
	IFIW!PFBPMA			;CODE 15 - ILLEGAL PHYSICAL EA WORD
	IFIW!PFBOWG			;CODE 16 - ILLEGAL ONE-WORD GLOBAL
	IFIW!PFBINT			;CODE 17 - ILLEGAL INTERRUPT VECTOR
	IFIW!PGUNTP			;MAX CODE +1 - SOFTWARE REQUESTED PAGE FAULT
PFVCLN==.-PFHVEC

;Here on write failure. Since the microcode can't tell us anything useful,
;we'll call GETTPD to find out what to do.

PFWRTF:	JRST PFAUL9			;GO FIND OUT THE REASON AND HANDLE IT

;Here on illegal age when a translation existed for this address. We don't
;expect this to happen. (When we set the age invalid, we also clear the pager.)
;So complain, but then go fix things.

PFBAGE:	BUG.(CHK,KCPFH1,PAGEM,HARD,<Unexpected page fault code (illegal age)>,,<

Cause:	A page fault occurred in which the code indicated that a CST entry had
	an illegal age when the corresponding virtual address existed in the  
	hardware's translation buffer. We expect to clear the pager when we  
	set an illegal age, so this condition should never occur.

Action:	No action is required. The monitor proceeds as if the translation did
	not exist.
>)
	JRST PFILAG			;GO HANDLE LIKE ANY ILLEGAL AGE TRAP

;Here on address break.

; * * * * *
;Work on this
; * * * *

PFADDB:	JRST ADRCMP

;Here on illegal super section pointer 0

PFBSSP:	BUG.(HLT,KCPFH2,PAGEM,SOFT,<Illegal super section pointer>,,<

Cause:	A page fault occurred indicating that the microcode found an illegal
	super section pointer. Its type field contained 5, 6, or 7.

Action:	Debug the code that created the pointer.
>)

;Here on section greater than 37

PFBSEC:	JRST ILSN

;Here on illegal pointer.

PFBPTR:	BUG.(HLT,KCPFH3,PAGEM,SOFT,<Illegal pointer>,,<

Cause:	A page fault occurred indicating that the microcode found an illegal
	pointer. Its type field contained 4, 5, 6, or 7.

Action:	Debug the code that created the pointer.
>)
;Here on "no access" pointer. This probably means the pointer is a zero. If it's
;a super section pointer or section pointer, handle as illegal section. If it's
;a map pointer, handle as non-existent page

PFNOAC:	JRST PFAUL9
; * * * *
;Note that the preceding JRST jumps around the following code. The JRST
;will be removed after initial debug of the breadboard
	LOAD T1,TWLEV,PFHCD
	CAIN T1,LVPPTR		;IS IT A PAGE POINTER
	JRST PFNOA2		;YES.
	TMNN TWUSR,PFHCD	;NO. IS THIS A USER REFERENCE?
	JRST ILSN		;EXEC. HANDLE AS ILLEGAL SECTION
	TMNE TWWRT,PFHCD	;USER MODE. IS IT A WRITE REFERENCE?
	JRST ILWR		;USER MODE WRITE. HANDLE AS ILLEGAL WRITE
	JRST ILRD		;USER MODE READ. HANDLE AS ILLEGAL READ

;This is a page pointer. Data word 1 contains
;(core page number of map,,offset within map). Construct (PTN,,PN) and store
;it in TRPID.

PFNOA2:	MOVE T1,PFHPFW		;GET PAGE FAULT WORD
	CALL ADDWSC		;ADD ADDRESS TO WORKING SET CACHE
	HLRZ T1,PFHD1		;GET CORE PAGE NUMBER FOR SOURCE OF POINTER
	HRL T2,@CST2X+T1	;GET SPT INDEX FOR PAGE TABLE
	HRR T2,PFHD1		; AND OFFSET WITHIN PAGE TABLE
	MOVEM T2,TRPID		;SAVE PTN,,PN
	JRST NPG		;GO HANDLE NON-EXISTENT PAGE
; * * * *

;Here if map or data page is not in core.

PFNIC:	JRST PFAUL9
; * * * *
;Note that the preceding JRST jumps around the following code. The JRST
;will be removed after initial debug of the breadboard
	CALL CNVPFD		;SET UP TRPID AND TRPPTR
	MOVE T1,PFHPFW		;GET PAGE FAULT WORD
	CALL ADDWSC		;ADD ADDRESS TO WORKING SET CACHE
	CALL GETT1A		;Figure out where to go for CFS stuff
	JRST 0(T1)		;Go there.
; * * * *

;Here if core page has illegal age

PFILAG:	JRST PFAUL9
; * * * *
;Note that the preceding JRST jumps around the following code. The JRST
;will be removed after initial debug of the breadboard
	CALL CNVPFD		;SET UP TRPID AND TRPPTR
	MOVE T1,PFHPFW		;GET PAGE FAULT WORD
	CALL ADDWSC		;ADD ADDRESS TO WORKING SET CACHE
	CALL GETT1B		;Verify the action
	JRST 0(T1)
; * * * *
;Here if must-be-zero bits are non-zero.

PFMBZ:	BUG.(HLT,KCPFH4,PAGEM,SOFT,<MUST-BE-ZERO BITS ARE NON-ZERO>,,<

Cause:	A page fault occurred indicating that must-be-zero bits are non-zero.
	Most likely the monitor did an XJRSTF with some non-zero bits in
	the reserved part of the flags word.

Action:	Debug the code that set up the flags word. Most likely, it has stored
	a section number from a PC word in the rightmost bits of the left
	half of the flags word.

>)

;Here for illegal indirect

PFBIND:	JRST ILIND

;Here for illegal PXCT (We don't expect this to happen)

PFBPXC:	BUG.(CHK,KCPFH5,PAGEM,SOFT,<Illegal PXCT>,,<

Cause:	A page fault occurred indicating that a PXCT was executed with the
	current AC block and the previous AC block set to the same value.

Action:	The monitor is not coded to run under these conditions. Most likely,
	some new flags word contains 0 in the PAB and CAB fields. Find the
	code that did this, and correct it.

>)

;Here for illegal physical effective address word

PFBPMA:	BUG.(HLT,KCPFH6,PAGEM,SOFT,<ILLEGAL PHYSICAL EFFECTIVE ADDRESS WORD>,,<

Cause:	A page fault occurred indicating that the microcode found a physical
	effective address word with a 1 in bit 0 or bit 1.

Action:	The monitor has made a physical reference with invalid data. Find the
	reference and correct it.

>)

;Here for illegal one-word global byte pointer

; * * * *
;WORK ON THIS
; * * * *
PFBOWG:	MOVEI T1,ARGX09		;ILLEGAL BYTE SIZE
	MOVEM T1,LSTERR
	JRST ILRD1		;HANDLE AS ILLEG REFERENCE

;Here for illegal interrupt vector. This should cause an I/O page fail and not
;come here

PFBINT:	BUG.(HLT,KCPFH7,PAGEM,SOFT,<Illegal interrput vector>,,<

Cause:	A page fault occurred indicating that the microcode found a all-zero
	interrupt vector word when attempting to give an interrupt. This
	should cause an I/O page fail and not a normal page fault.

Action:	Find the reason for the zero interrupt vector word (probably a software
	bug). Also find out why the microcode gave a normal page fault for
	this condition.

>)
;CNVPFD - Routine to convert page fault data from KC format to format generated
;by GETTPD. Stores TRPID and TRPPTR.

;	CALL CNVPFD

;RETURNS +1: ALWAYS

;Expects TRVAR set up by PFAULT

CNVPFD:	MOVE T1,PFHD1		;GET FIRST DATA WORD
	TLNN T1,-1		;IS LEFT HALF ZERO

;A map is inaccessible. Data word 1 has (0,,SPTN). Store this in TRPID,
;and the contents of the SPT in TRPPTR.

	JRST [	MOVEM T1,TRPID	;YES. FIRST DATA WORD IS SPT INDEX FOR MAP
		MOVE T2,SPT(T1)	;GET ADDRESS OF MAP
		MOVEM T2,TRPPTR	;SAVE IT
		RET]

;A data page is inaccessible. Data word 1 has (core page number of map,,PN).
;Data word 2 has the map entry. Store (PTN,,PN) in TRPID, and the contents
;of the map entry in TRPPTR.

	HLRZ T2,T1		;GET CORE PAGE NUMBER
	HRL T1,@CST2X+T2	;GET PTN
	MOVEM T1,TRPID		;SAVE PTN,,PN
	MOVE T1,KCPFD2		;GET POINTER
	MOVEM T1,TRPPTR		;SAVE IT
	RET
   >				;END OF IFN KCFLG
;DETERMINE CAUSE OF TRAP AND GET TRAP INFORMATION.  START FROM
;VIRTUAL ADDRESS IN PFHPFW.
;	CALL GETTPD
; RETURNS +1 ALWAYS,
;	T1/ ADDRESS TO GO TO (EFFECTIVELY A REASON CODE)
;	TRPID/ IDENT OF PAGE CAUSING TRAP
;	TRPPTR/ POINTER BITS AND/OR STORAGE ADDRESS

;This routine effectively simulates the action of the microcode and
;determines the reason for the page fault. It traces page pointers and
;exits when it finds a reason for failure.

;Expects TRVAR set up by PFAULT

GETTPD:	MOVE T2,PFHPFW		;START WITH TRAP ADDRESS
	LOAD T1,TWVADR,T2
	TRNN T1,777760		;POSSIBLY A REG?
	TLNE T1,36		;YES. IS IT SEC 0 OR 1?
	SKIPA			;NO. NOT A REG THEN
	JRST GETTGD		;YES. IS A REG. ALLOW IT

;Not an AC. Convert address in page fail word to PTN,,PN.

	TXNE T2,TWUSR		;USER?
	JRST [	TXO T1,TWUSR	;YES
		CALL FPTAXP	;GET I.D. OF PAGE DON'T PF ON SECTION POINTERS
		JUMPE T1,GETT1G	;NON-EX SECTION. ILLEGAL
		JUMPL T1,GETT1H	;SECTION POINTER TRACE WOULD PAGE FAULT
		JRST GETTP1]	;GOT IT.
	CALL FPTAX		;GET IDENT OF FIRST POINTER
	JUMPE T1,GETTPX		;IF NO IDENTIFIER, GO TO ILSN

;T1/ PTN,,PN. If page is on a dismounted structure, give illegal read.

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
;	..
;See if this map is accessible. If not in core, or age is invalid, quit.
;	TRPID/ SPT index for page map (PTN)
;	TRPPTR/ Contents of SPT for page map

	;..
	TXNE T2,NCORTM		;IN CORE?
	JRST GETT1A		;NO
	HLL T3,@CST0X+T2	;CHECK AGE
	TXNN T3,PSASM		;ASSIGNED?
	JRST GETT1B		;NO
	MOVEM T1,TRPID		;PT OK, SAVE PAGE IDENT
	HRRZS T1
	CALL MOVRCA		;FETCH POINTER
	MOVEM T1,TRPPTR		;SAVE IT

;Map is accessible. If entry for this page is 0, quit.
;If write reference, handle possible illegal reference.
;	TRPID/ PTN,,PN
;	TRPPTR/ Map entry for offset PN

	JUMPE T1,GETT1C		;JUMP IF NULL POINTER
	MOVE T2,PFHPFW		;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
		TXNN T2,TWUSR	;USER FAULT?
		JRST .+1	;NO, FAULT IS NOT AN ILL WRITE
		LOAD T1,VSECNO,T2 ;GET SECTION NUMBER
		CALL SECIND	;SECTION POINTER + AND OF ACCESS BITS IF IND
		TXNN T1,PTWR	;SECTION POINTER ALLOW WRITE?
		JRST GETT1E	;NO, THATS ILLEGAL AS WELL
		MOVE T1,TRPPTR	;RESTORE T1
		JRST .+1]
	;..
;Look at page pointer. If indirect pointer, follow the chain and get the
;next page table. NOTE: SOME PAGES ARE MAPPED INDIRECT THROUGH PSBBAS IF THIS
; IS THE CASE WE SUBSTITUTE THE FORK'S PSB FOR THE PAGE TABLE

	;..
	LOAD T2,PTRCOD,T1	;CHECK POINTER TYPE
	CAIN T2,INDCOD		;INDIRECT?
	JRST [	LOAD T2,SPTX,T1	;YES, CONSTRUCT IDENT OF PAGE POINTED TO
		CAMN T2,PSBBAS	;IS IT PSBBAS?
		LOAD T2,FKPSB	;YES. USE THIS FORKS PSB INSTEAD
		LOAD T1,IPPGN,T1 ;GET PN
		HRL T1,T2	;CONSTRUCT PTN,,PN
		JRST GETTP1]	;LOOP

;If shared pointer, update TRPID and TRPPTR to reflect shared SPT slot

	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]

;Have immediate pointer or contents of SPT slot. Quit if it is not in core or
;age is bad.

	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
	JN CSWRB,+T1,GETTGD	;IF WRITE ACCESS ALREADY, DONE
	TMNN TWWRT,PFHPFW	;DON'T WANT TO WRITE IT?
	JRST GETTGD		;NO. ALL DONE THEN
	MOVEI T1,NWRBS		;NO WRITE ACCESS
	RET			;AND DONE

;No reason for page fault. Probably the condition has been cleared. Try the
;reference again.

GETTGD:	MOVEI T1,PGUNTP		;PAGE OK, MAY BE REFERENCED
	RET
;Error returns from GETTPD. Caller will go to the routine returned in T1.

;HERE IF WE ENCOUNTERED A NIC SECTION TABLE (PSB) WHILE TRACING A POINTER
;T1/ -1,,PTN

GETT1H:	HRLZS T1		;GET PTN ONLY IN LEFT HALF
	JRST GETTP1		;AND HANDLE IT

;PAGE OR PAGE TABLE NOT IN CORE
;We get here either by a direct transfer from within GETTPD, or
;by a CALL from some routine outside of GETTPD. Either way,
;the result is that GETT1A RETurns to a caller with:
;	T1/ Next place to go

GETT1A:
;   IFN CFSCOD,<
	CALL XOFN		;EXTRACT OFN FROM PAGE FAULT
	CFSLOK			;Lock the CFS data base
	JUMPE T1,GETT2A		;NO OFN. ALLOW THE THING TO PROCEED
	TMNE SPTFO,(T1)		;BEING FORCED OUT?
	SKIPGE DDPFRK		;Is this DDMP?
	SKIPA			;IS OK
	JRST GETT2Z		;NEED TO WAIT
	LOAD T2,SPTST,(T1)	;GET FILE STATE
	IFE. T2			;If not here
	 MOVE T2,SPTH(T1)	;Get open mode
;**;[7247]  Change 1 line at GETT1A:+12			DML	19-Feb-86
	 CALL SKPOPR		;[7247] Skip if any "regular" openers?
	 TXNN T2,FILUB		;No. Unrestricted?
	 JRST GETT2Z		;REGULAR OR NOT FILUB GO GET PROPER ACCESS TYPE
	 JRST GETT2A		;UNRESTRICTED. GO ON WITHOUT CFS
	ELSE.			;If already have the token...
	 TMNN SPTSFD,(T1)	;Need to verify XB?
	 ANSKP.			;If so
	  CFSULK
	  MOVEI T1,GETXSM	;Where to go to do it
	  RET			;And do it
	ENDIF.
	CAIN T2,.SPSWR		;WRITE?
	JRST GETT2A		;IF HAVE EXCLUSIVE ACCESS NOW, ALL SET
	TMNE TWWRT,PFHPFW	;HAVE READ ONLY. NEED WRITE?

;Here if we need to modify the "write token"
GETT2Z:	SKIPA T1,[NTWRTK]	;WHERE TO GO
;   >	;IFN CFSCOD

GETT2A: MOVEI T1,NIC
;   IFN CFSCOD,<
	CFSULK			;Unlock CFS data base
;   >
	RET

;PAGE OR PAGE TABLE AGE .L. 100

GETT1B:
;   IFN CFSCOD,<
	SKIPGE DDPFRK		;Is this DDMP?
	IFSKP.			;If not
	 CALL XOFN		;Get the OFN
	 SKIPN T1
	 ANSKP.
	  CFSLOK		;Lock up the CFS data base
	  JE SPTST,(T1),GETT2Z	;If no access yet, go get it first
	  TMNE SPTSFD,(T1)	;Need XB check done?
	  IFNSK.		;If so
	   CFSULK
	   MOVEI T1,GETXSM	;Where to go to do it
	   RET
	  ENDIF.
	  TMNN <SPTFO,SPTDSF>,(T1) ; Is it being forced out?
	  IFSKP.		;If so
	   CFSULK
	   MOVEI T1,FRCWT	;yes.
	   RET
	  ENDIF.
	  CFSULK
	ENDIF.
;   >	;IFN CFSCOD
	MOVEI T1,TRP0
	RET

;NULL POINTER. PAGE DOESN'T EXIST

GETT1C:
;   IFN CFSCOD,<			;For CFS stuff
	CALL XOFN		;Get the OFN if present
	IFG. (T1)		;If we have one
	 CFSLOK			;Lock up the data base
	 LOAD T2,SPTST,(T1)	;Get state of the OFN
	 CAIE T2,.SPSWR		;Exclusive?
	 IFNSK.			;If not
	  MOVE T2,SPTH(T1)	;But, see if unrestrcted first
;**;[7247]  Change 1 line at GETT1C:+8			DML	19-Feb-86
	  CALL SKPOPR		;[7247] Skip if open regular not FILUB only
	  TXNN T2,FILUB		;Is it really unrestricted?
;**;[7283] Change 1 line at GETT1C:+11			DML	4-Apr-86
	  ANNSK.		;[7283] No, regular openers or not FILUB
	  CFSULK
	  MOVEI T1,NTWRTX	;Say we need exclusive access
	  RET			;And return
	 ENDIF.
	 CFSULK			;Free the lock
	ENDIF.			;and go to NPG with CFS data base locked
;   >	;IFN CFSCOD
	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:	MOVEI T1,ILSN		;RETURN TO HANDLE ILLEG SECTION
	RET

;ILLEGAL REFERENCE BECAUSE OF DISMOUNTED OFN

GETT1F:	MOVEI T1,PMAPX7		;GET CHARACTERISITIC ERROR
	MOVEM T1,LSTERR		;LET PROCESS KNOW WHY MEM FAILED
	MOVEI T1,ILRD1		;GET DISPATCH FOR CALLER
	RET			;AND DONE

GETT1G:	MOVEI T1,ILWR		;ASSUME ILLEGAL WRITE
	TXNN T2,TWWRT		;WAS IT A WRITE REFERENCE?
	 MOVEI T1,ILRD		;OF COURSE NOT
	RET			;AND DONE

;Here when AGE<100 and OFN being forced out

;   IFN CFSCOD,<
FRCWT:	CALL XOFN		;Get the OFN
	JUMPE T1,TRPRST		;If no OFN, why are we here?
	MOVSS T1
	HRRI T1,WTFOD		;Wait for force-out to complete
	RDISMS			;Do it
	NOSKED
	JRST TRPRST		;Try again
;   >		;IFN CFSCOD
;Here to modify the write token

;   IFN CFSCOD,<
NTWRTK:	TDZA T2,T2		;Remember this entry
NTWRTX:	MOVEI T2,1		;And this one as well
	CALL XOFN		;GET THE OFN
NTWRT0:	TMNN SPTFO,(T1)		;BEING FROCED OUT?
	IFSKP.
	 MOVSS T1		;YES
	 HRRI T1,WTFOD		;SCHEDULER TEST
	 RDISMS			;WAIT FOR IT
	 NOSKED
	ELSE.
	 TMNE TWWRT,PFHPFW	;NEED WRITE ACCESS?
	 MOVEI T2,1		;need exclusive access if here
	 CALL CFSAWT		;ACQUIRE THE LOCK
	ENDIF.
	JRST TRPRST		;GO SEE WHAT WE NEED TO DO NEXT

;Here to verify XB when faulting in a page of the file (or the XB itself)

GETXSM:	CALL XOFN		;Fetch OFN
	CALL XBCHK		;Do the verification
	JRST TRPRST		;And done

;Routine to do XB verification.
;	T1/ OFN
;Called NOSKED or not, your choice

XBCHK::	CALLRET DDXBI		;Do verification
;   >	;IFN CFSCOD
;More routines to fix reason for PF

;Here to handle no write access in CST

NWRBS:
;   IFN CFSCOD,<
	CALL XOFN		;GET THE OFN
	JUMPE T1,NWRBS0		;SET BIT
	SKIPGE DDPFRK		;Is this DDMP?
	IFSKP.			;No
	  TMNN SPTFO,(T1)	;DDMP working on this?
	  IFSKP. <JRST NTWRT0>	;Go wait if so
	ENDIF.
	CFSLOK			;Lock the CFS data base
	LOAD T2,SPTST,(T1)
	CAIE T2,.SPSWR
	IFNSK.			;If need to change resource
	 CFSULK			;Free the data base lock
	 MOVEI T2,1		;Say need exclusive access
	 JRST NTWRT0		;GO GET THE WRITE TOKEN
	ENDIF.
	CFSULK			;Free the data base
;   >	;IFN CFSCOD

;Set write bit in the CST

NWRBS0:	HRRZS T1,TRPPTR		;GET THE PHYSICAL PAGE NUMBER
	SETONE CSWRB,+T1	;SET THE BIT
	LOAD T1,STGADR,TRPPTR	;GET ADDRESS
	JRST PGUNTP		;AND RETRY

;Routine to get OFN of page fault

XOFN:	HLRZ T1,TRPID		;GET IT
	SKIPN T1		;ANYTING HERE?
	HRRZ T1,TRPID		;NO
	CAIL T1,NOFN		;IS THIS THE OFN?
	HLRZ T1,SPTH(T1)	;NO. MAYBE IT'S HERE
	RET			;AND DONE
;AGE LESS THAN 100 TRAP

;Expects TRVAR set up by PFAULT

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

;Transfer according to age.

TRP0B:	JRST TRP0C		;ON RPLQ (PSRPQ)
	JRST BADAGE		;DELETED (PSDEL)
	JRST TRP2R		;READ COMPLETED (PSRDN)
	JRST BADAGE		;NOT USED
	JRST TRP0C		;WRITE IN PROGRESS (PSWIP)
	JRST BADAGE		;NOT USED
	JRST TRP0R		;READ IN PROGRESS (PSRIP)
	JRST TRPRST		;NOW ON SPMQ. RESTART TRAP (PSSPQ)
TRP0BM==.-TRP0B-1		;MAXIMUM LEGAL VALUE

;AGE IS EITHER "ON REPLACEABLE QUEUE" OR "WRITE IN PROGRESS"
;IF PAGE HAS HAD AN ERROR, PLACE IT ON THE SPECIAL MEMORY QUEUE.
;OTHERWISE, UPDATE ITS AGE AND FINISH THE PAGE FAULT

TRP0C:	HRRZ 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

;Here if read completed, on replaceable queue, or write in progress.

TRP2R:	HRRZ 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

;AGE IS "READ IN PROGRESS". WAIT FOR THE READ TO COMPLETE.

TRP0R:	MOVSI T1,0(T2)		;SET PAGE NUMBER OF SCHEDULER TEST
	HRRI T1,SWPRT		;SCHEDULER TEST. RETURNS WHEN PSRIP NOT SET
	HRRZ T3,T2		;GET THE DESIRED INDEX BIT ONLY
	MOVE T3,@CST1X+T3
	TXNE T3,DSKAB		;USE APPROPRIATE TEST
	HRRI T1,DSKRT		;DISK READ (ACTUALLY SAME AS SWPRT)
	RDISMS			;WAIT FOR PAGE
	NOSKED
	JRST TRPRST		;RECHECK TRAP
BADAGE:	BUG.(HLT,ILAGE,PAGEM,SOFT,<Bad age field in CST0>,,<

Cause:	The age of a memory page contains an unexpected value. One of the
	following happened:

	1. A page fault occurred and the age was either PSDEL or an
	undefined age LESS THAN PSASN.

	2. A process attempted to assign the page and its age was PSDEL,
	PSSPQ, or an undefined age LESS THAN PSASN.
>)

;HERE WHEN PAGE FAULTED ON WANTS TO BE REMOVED FROM AVAILABLE POOL
;Deassign it in the CST and add to replaceable queue. Copy the backup
;address to the primary address. When the faulting
;instruction is reexecuted, a new page will be assigned.

TRPSPM:	HRRZ T2,T1		;GET THE DESIRED INDEX BITS
	LOAD T2,CSTAGE,+T2	;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 TRPRST		;TRY REFERENCE AGAIN

TRPSP2:	CALL SKPNWR		;STILL BEING WRITTEN?
	  JRST TRPRST		;RESCHEDULED - RESTART TRAP
	JRST TRPSP1		;NO - FREE PAGE NOW
;ILLEGAL REFERENCE TRAPS

;Illegal write. Set up error code and interrupt channel

ILWR:	MOVEI T1,ILLX02		;SET ERROR CODE
	MOVEM T1,LSTERR
	MOVX T1,.ICIWR		;MW INTERRUPT CHANNEL
	JRST ILRF

;Illegal section. Can be non-existent section or section > 37.

ILSN:	MOVEI T1,ILLX05		;ERROR CODE
	MOVEM T1,LSTERR		;SET THE ERROR CODE
	JRST ILRD1		;GO CAUSE ILLEGAL READ INTERRUPT

;Illegal read. (Also proprietary violation and illegal indirect.)
;Save error code in LSTERR and set up interrupt channel.

ILRD:	MOVEI T1,ILLX01		;SET ERROR CODE
	MOVEM T1,LSTERR
ILRD1:	MOVX 1,.ICIRD		;MR TRAP CHANNEL

;Common code for illegal reference. LSTERR contains last error, and
;	T1/ channel on which to interrupt

ILRF:	MOVEM T1,PFHTMP		;SAVE CHANNEL TEMPORARILY
   IFN KLFLG,<
	MOVE T1,PFHFL		;GET FLAGS AT TIME OF TRAP
	MOVE T2,PFHPC		;GET PC AT TIME OF TRAP
	CALL SETPCV		;MAKE SURE PCU AND PCS CORRECT
   >				;END OF IFN KLFLG
	MOVE T1,PFHPFW		;GET PAGE FAIL WORD FOR USER
	MOVEM T1,UTRSW		;SAVE IN PSB
	MOVE T2,PFHFL		;GET FLAGS WORD
	MOVE T3,PFHPC		;GET PC
	AOS T3			;INCREMENT TO NEXT INSTR
	TXNE T2,UMODF		;USER OR KERNEL
	JRST ILRFU		;USER MODE TRAP

;Error occurred in monitor. See if instruction is followed by an ERJMP style
;instruction, or an address to dispatch to was provided. If not, BUGHLT.

; * * * *
;This isn't right for a nested trap
; * * * *

	HLLZ 4,0(T3)		;GET INSTRUCTION AFTER TRAP
	CAMN 4,[ERJMPR]		;IS IT ERJMPR?
	JRST [MOVE T1,LSTERR	;YES, GET LAST ERROR
	      MOVEM T1,PFHACS	;SAVE IT
	      JRST ILRF1]	;AND CONTINUE
	CAME 4,[ERJMPS]		;IS IT ERJMPS?
	CAMN 4,[ERJMP]		;OR ERJMP?
	JRST ILRF1		;YES - EASY CASE
	SKIPE T4,TRPDSP		;TRAP DISPATCH SET?
	JRST ILRF2		;YES
	JXN T1,TWUSR,ILRFX	;OK IF REF TO USER MODE
	BUG.(HLT,ILMNRF,PAGEM,SOFT,<Illegal reference to MON ADR SPACE>,<<T1,PFW>,<T2,FLAGS>,<T3,PC>>,<

Cause:	The monitor made an illegal reference to an address in its map
	and was not prepared to handle the error. The possible errors
	include illegal read, write, and section number. See the page
	fail word for the reason code.

	This BUGHLT can also occur if an unrecoverable AR/ARX parity
	error is detected on certain monitor references. In this
	case, the analysis of the error will already have been
	printed on the CTY.

Data:	PFW - Page Fail Word
	FLAGS - PC flags
	PC - PC
>)
;Fix the return PC to go to target of ERJMP or ERCAL.

ILRF1:	MOVE 4,0(T3)		;GET ADDRS TO XFER TO
	HRRM 4,PFHPC		;ALTER RETURN ADDRESS (CAN'T CROSS SEC BOUND HERE!)
	JRST PGUNT0		;EXIT TRAP
;User made the illegal reference. Follow the ERJMP or ERCAL if any.

ILRFU:
;	XSFM T1			;GET PRESENT FLAGS
;	XMOVEI T2,ILRFU1	;WHERE TO PROCEED
;	TXO T1,PCU		;NEED TO MAKE USER PREVIOUS CONTEXT
;	XJRSTF T1		;SET IT
ILRFU1:	MOVE T1,PFHFL		;GET FLAGS AT TIME OF PAGE FAULT
	MOVE T2,T3		;GET PC
	SOSG NSKED		;DON'T BE NOSKED FOR THIS, BUT BE NOINT
	XCT RSKED		;CHECK IF SCHEDULER NEEDS ATTENTION
	CALL ITRSIM		;CHECK FOR ERJMP/ERCAL (PC IN 2)
	 JRST [	AOS NSKED	;BE NOSKED AGAIN
		JRST ILRFX]
	AOS NSKED		;BE NOSKED AGAIN
	MOVEM 3,PFHPC		;ALTER RETURN ADDRESS
	JRST PGUNT0		;EXIT TRAP

;HERE IF ILLEG REF FROM MONITOR AND DISPATCH WORD SET

;T4/ dispatch word

ILRF2:	STOR T4,EXPCBT,PFHPC	;PUT ADR ON STACK FOR RETURN
	TXNN T4,TRPIRF		;WANTS INTERRUPT TOO?
	JRST PGUNTP		;NO
	MOVE T1,PFHTMP		;GET INTERRUPT CHANNEL
	CALL PSIRQ0		;YES, DO IT
	CHKINT
	JRST PGUNTP		;DONE

;HERE IF REF TO USER ADR SPACE AND NO ERJMP/ERCAL
;If monitor mode and NOINT, skip over instruction that failed.
;Give an interrupt.

ILRFX:	MOVE T1,PFHTMP		;GET CHANNEL
	CALL PSIRQ0		;REQUEST INTERRUPT, THIS FORK
	CHKINT			;GET IT SEEN
	MOVE 2,PFHFL		;FLAGS
	TLNN 2,(UMODF)		;USER?
	SKIPG INTDF		;OR INTERRUPTABLE?
	JRST PGUNTP		;YES
	AOS PFHPC		;NO, SKIP OVER INSTRUCTION CAUSING TRAP
	JRST PGUNT0
;Here when map entry is zero. This code creates the page and assigns an
;address of "unassigned".

;PAGE NOT IN EXISTANCE TRAPS

;Expects TRVAR set up by PFAULT


NPG:	MOVE T1,PFHPFW
	JXN T1,TWUSR,NPG1	;ALWAYS HONOR USER REQUEST

;See if the monitor is trying to touch an illegal section
;or code which is not supposed to be in section 0.

	TXZ T1,EXFLBT		;ZERO FLAGS JUNK
	HLRZ T2,T1		;CHECK SECTION
	CAILE T2,MSEC1		;MONITOR SECTIONS 0 OR 1?
	IFSKP.
	  CAIL T1,RSCOD		;TRYING TO TOUCH CODE IN SEC 0?
	  CAILE T1,RSCODZ
	  IFNSK.
	    CAIL T1,NRCOD
	    CAILE T1,NRCODZ
	  ANNSK.
				;NO, FALL THRU
	  ELSE.
	    MOVE T2,PFHPC	;SETUP PC FOR BUG.
	    BUG.(CHK,PCIN0,PAGEM,SOFT,<PAGEM - PC has gone into section 0>,<<T2,PC>,<T1,PFW>>,<

Cause:	A reference has been made to RSCOD or NRCOD in section 0.  This should
	not happen because section 0 code cannot reference data in
	extended sections.  As an expedient, the page being referenced
	will be mapped to section 1 with an indirect pointer.

Data:	PC - PC
	PFW - Page fail word
>)
	    MOVE T2,INDPTR
	    MOVE T3,M1SPTN	;MAKE INDIRECT POINTER TO SECTION 1
	    STOR T3,SPTX,T2
	    LOAD T3,LPGNO,T1	;PAGE SAME AS THIS REFERENCE
	    STOR T3,IPPGN,T2
	    MOVEM T2,MMAP(T3)
	    JRST PGUNTP		;NOW TRY IT...
	  ENDIF.
	  HRRZ 1,1		;IF MONITOR SECTION 0 OR 1
	  CAIL 1,PSSPSA
	  CAIL 1,PSSPEA
	  JRST NPG1		;YES
	  JRST MILRF1		;MONITOR MALFUNCTION
	ENDIF.
	CAILE T2,HGHSEC		;CHECK FOR ILLEGAL SECTION
	JRST MILRF1		;YES -- ERROR

;Decide whether to create page based on room in the swapping space.

NPG1:	MOVE T1,TRPID		;GET PAGE IDENT
	HLRZ 2,1		;GET PT NUMBER
	CAIGE 2,NOFN		;OFN OR PT?
	IFSKP.			;If OFN
	  MOVE T3,DRMFRE	;PT, SEE IF ENOUGH DRUM SPACE
	  CAML T3,DRMLV0	;ABOVE MINIMUM?
	ANSKP.
	  MOVE T3,PFHFL		;NO. GET FLAGS OF TRAP
	  TXNE T3,UMODF		;MONITOR PC?
	  JRST NIC6E		;NO, BOMB OUT
	  MOVE T3,INTDF		;YES. SEE IF NOW NOINT
	  JUMPE T3,NIC6E	;NOT. ERROR THEN
	ENDIF.

;Map the page table and create the entry, indicating "unassigned"

	CALL SETSPG		;MAP IT
	HRRZS T1		;CLEAR LEFT HALF FOR INDEXED REFERENCE
	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
	MOVEM T2,TRPPTR		;THIS IS WHAT GETTPD WOULD GIVE US
	CALL RELSPG		;RELEASE MAP
	;..
;If reference was from user mode, and the user wants an interrupt for
;creating a page, give it. Then prcoess the page as not in core.

	;..
	AOS NPRIVP		;ADJUST PRIVATE PAGE COUNT
	MOVE 1,PSICHM
	MOVE 2,PFHPFW
	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,PFHPFW
	MOVEM 1,UTRSW
	JRST NIC

;Monitor tried to create page illegally. Go handle that

MILRF1:	JRST ILSN
;SWAPPING SPACE INSUFFICIENT FOR NEW PRIVATE PAGE TO BE CREATED
;PRINT MESSAGE AND WAIT.
;(CODE TO GENERATE INTERRUPT IF CHANNEL ON NOT USED NOW)

NIC6E:	MOVEI T2,IOX12		;SWAPPING SPACE FULL
	MOVEM T2,LSTERR
	;MOVE T1,PSICHM		;SEE IF INTERRUPT ENABLED
	;IFXE. T1,<1B<.ICMSE>>
	  XMOVEI T1,NIC6H	;NO, UNTRAP TO CODE TO DO BLOCK
	  JRST PGUNTD
	;ENDIF.
	MOVX 1,.ICMSE		;MACH SIZE EXCEEDED INT CHANNEL
	JRST ILRF		;GENERATE INT

;HERE IN JSYS CONTEXT TO HANDLE SWAPPING SPACE FULL

;CALL NIC6H

;Returns +1: always

NIC6H:	SAVEAC <T1>
	HRROI T1,[ASCIZ /
[MONITOR: Swapping space exhausted, waiting.../]
	PSOUT
	MOVEI T1,DRMSPC		;SCHED TEST TO WAIT FOR SPACE
	HRL T1,DRMLV0		;REQUIRED LEVEL
	MDISMS
	HRROI T1,[ASCIZ /OK]
/]
	PSOUT
	RET			;TRY AGAIN

;SCHED TEST FOR SWAPPING SPACE AVAILABLE
; T1/ MINIMUM SWAP SPACE LEVEL FOR WAKEUP

DRMSPC:	CAML T1,DRMFRE		;ENOUGH NOW?
	JRST 0(T4)		;NO
	JRST 1(T4)

NPGBAD:	BUG.(HLT,ILPPT3,PAGEM,SOFT,<Bad pointer in page table>,,<

Cause:	A page fault occurred because a process touched a page whose
	map entry contained access bits of 0, indicating non-existent
	page. But when the monitor mapped the page table, the page's
	entry was not 0. A non-existent page should always be
	represented by an all-zero entry.
>)
;Here when write reference failed, and process has copy-on-write access.

;Expects TRVAR set up by PFAULT

WCPY:	MOVE T4,TRPID		;SAVE THE ORIGINAL IDENT
	MOVEM T4,PFHTMP		; WHILE GETTPD GENERATES A NEW ONE

;Analyze the reference without "write reference" to see if a read would succeed.
;If not, go handle the reason it failed.

	MOVX T4,TWWRT
	ANDCAM T4,PFHPFW	;CLEAR WRITE REF
	CALL GETTPD		;SEE IF PAGE READABLE
	CAIE T1,PGUNTP		;PAGE READY FOR COPYING?
	JRST 0(T1)		;GO HANDLE OTHER CAUSE

;Read would have succeeded.
;	TRPID/ PTN,,PN for page to be copied
;	TRPPTR/ Map word for the page
;Lock the page in core

	HRRZ T1,TRPPTR		;GET ADDRESS OF SOURCE PAGE
	MOVE T2,@CST1X+T1	;GET CST1 ENTRY FOR PAGE
	TLNE 2,(-PLKV)		;LOCKED ALREADY?
	JRST ILWR		;ILLEGAL WRITE.
	MOVSI 3,(PLKV)		;NOW LOCK IT IN CORE
	ADDM 3,@CST1X+1

;Get original map. Store immediate pointer in user's map, indicating
;"unassigned and copy".

	EXCH T1,PFHTMP		;SAVE CORE PAGE NUMBER, RESTORE IDENT
	HLRZ 2,1		;PTN
	CAIG 2,NOFN
	BUG.(HLT,IBCPYW,PAGEM,SOFT,<COPY - Write pointer in index block>,,<

Cause:	A page fault occurred because a process attempted to write into
	a page whose access was copy-on-write. The BUGHLT indicates that
	the page table is an index block that should never have copy-
	on-write access.
>)
	CALL SETSPG		;MAP THE PT
	HRRZ T3,T1		;ALLOW INDEXED REFERENCE IN SECTION 1
   IFN KLFLG,<
	MOVX T2,PTPUB		;SELECT ACCESS BITS
	AND T2,CSWPGA(T3)	;GET ACCESS OF SOURCE PAGE
   >				;END OF IFN KLFLG
   IFN KCFLG,<
	SETZM T2
   >				;END OF IFN KCFLG
	IOR T2,IMMPTR		;MAKE PRIVATE PTR
	TXO T2,UAACB		;WITH 'COPY' ADDRESS
	EXCH T2,CSWPGA(T3)	;EXCH IT WITH THE WC POINTER
	LOAD T4,PTRCOD,T2	;CHECK PTR TYPE
	CAIN T4,IMMCOD		;PRIVATE?
	JRST WCPY4		;YES, USER PROBABLY CONFUSED

;Store user's original pointer (copy-on-write to source page) in monitor map
;slot for CPYPGA. The call to SWPINP causes the data at CPYPGA to be copied
;to the page pointed to by the contents of T1 when UAACB is set in the
;pointer. T1 contains (PTN,,PN) for the user's original page.

	MOVEM 2,PSBM0+CPYPG	;PUT THE ORIG POINTER IN MON MAP
	CALL RELSPG
	AOS NPRIVP		;INCREASE PRIVATE PAGE COUNT
	SKIP CPYPGA		;REF SOURCE PAGE TO ENSURE ACCESS
	CALL SWPINP		;THIS WILL COPY FROM CPYPG TO A NEW PAGE
	;..
;Determine whether source was fork or file. Remove map entry from monitor
;map.

	;..
	MOVE T1,PFHTMP		;GET ORIGINAL CORE PAGE
	CALL ULKP1
	LOAD T1,FKPSB		;GET SPT INDEX FOR PSB
	HRL T1,T1		; INTO LEFT HALF
	HRRI 1,PSBM0-PSBPGA+CPYPG ;COMBINE WITH PAGE NUMBER
	CALL MRPT		;GET IDENT OF SHARE PAGE BEING RELEASED
	 SETZ 1,		;INDIRECT TO FORK (SKIP RETURN MEANS FILE)
	MOVEM T1,PFHTMP		;SAVE INDICATOR OF TYPE OF PAGE
	LOAD T1,FKPSB		;GET SPT INDEX FOR PSB
	HRL T1,T1		; INTO LEFT HALF
	HRRI 1,PSBM0-PSBPGA+CPYPG ;COMBINE WITH PAGE NUMBER
	SETZM T3		;NO FLAGS
;**;[7314]  Add 2 lines after WCPY3:-10			DML	3-Jun-86
 	CSKED			;[7314] Boost our priority ...
	OKSKED			;[7314] ... then go OKSKED for call into RELMPG
	CALL RELMPG		;RELEASE THE ORIG PAGE FROM MON MAP
	CALL RELCPT		;CLEANUP FROM RELMPG
;**;[7314]  Remove 1 line at WCPY3:-7			DML	3-Jun-86

;If original source was a file, decrement JFN map count.

	MOVE T1,PFHTMP		;RESTORE INDICATION OF TYPE
	JUMPE 1,WCPY3		;IGNORE INDIRECT TO FORK PTR
	CALL JFNDCR		;DECREMENT MAP COUNT FOR JFN
;**;[7314]  Replace 1 line with 2 at WCPY3:		DML	3-Jun-86
WCPY3:	ECSKED			;[7314] Reduce our priority now
	NOSKED			;[7314] Go NOSKED again and continue with trap
	JRST TRPRST		;UPDATE STATS AND CONTINUE

;User had private pointer. No need to make another one. Allow write
;access.

WCPY4:	TLZ T2,(PTCPY)		;MAKE IT LOOK LIKE WE COPIED IT
	TLO T2,(PTWR)
	MOVEM T2,CSWPGA(T3)
	CALL RELSPG
	MOVE T1,PFHTMP		;GET BACK CORE PAGE NUMBER
	CALL ULKP1		;UNLOCK THE SOURCE PAGE
	JRST PGUNTP		;REFERENCE SHOULD SUCCEED NOW
;NOT IN CORE TRAP

;Expects TRVAR set up by PFAULT

;Page or page table is not in core. If unassigned disk address, go assign it
;and come back here. Otherwise, swap it in.

NIC:
	MOVE T1,TRPID		;GET IDENT
	MOVE T2,TRPPTR		;GET ADDRESS
	TLNE 2,(DSKAB+DRMAB)	;UNASSIGNED ADR?
	IFSKP.
	  HLRZ 2,1		;YES. GET PT
	  IFE. T2		;IF FROM SPT...
	    CAMN 1,BTBBAS	;IS THIS THE BIT TABLE?
	    JRST ILSN		;YES, ILLEGAL
	    HLRZ 2,SPTH(1)	;NO. GET PT
	  ENDIF.
	  CAIE 2,0		;OFN OR PT?
	  CAIL 2,NOFN
	ANSKP.

;Unassigned file page. Create it if possible, setting DSKNB in the map entry

	  CALL NIC6A		;OFN, ASSIGN DISK ADR
	   JRST 0(T4)		;COULDN'T
	  JRST TRPRST		;OK, REANALYZE
	ENDIF.

;Make sure there are enough core pages left, and swap the data in.

	CALL CHKRPQ		;CHECK FOR ENOUGH PAGES FREE
	 JRST TRPRST		;WASN'T, HAD TO RESKED
	CALL SWPINW		;SWAP IN THE PAGE
	JRST TRPRST
;HERE IF PAGE HAS UNASSIGNED ADDRESS

;Accepts:
;	T1/ IDENT OF PAGE (either (0,,SPTN) or (PTN,,PN)

;	CALL NIC6A

;Returns +1: page cannot be created
;		T4/ Return address that caller JRST's to
;		T1/ Interrupt channel if T4 contains ILRF
;	 +2: Page on disk has been assigned

;This is the normal mechanism for creating a file page. Page fault
;occurs for "not in core" condition

;Expects TRVAR set up by PFAULT

NIC6A:	SAVEAC <Q2>
	STKVAR <N6ID,N6OF,N6QT>
	MOVEM T1,N6ID		;SAVE ORIGINAL IDENT

;Original request may have been read or write. If read, see if write would
;be allowed. Simulate write request. If GETTPD returns ILWR or WCPY, write
;would have failed.

	MOVX 1,TWWRT		;GET WRITE BIT
	TDNE 1,PFHPFW		;ORIGINAL REQUEST WAS WRITE?
	JRST NIC62		;YES, ACCESS ALREADY CHECKED
	IORM 1,PFHPFW		;MUST SEE IF WRITE ACCESS POSSIBLE
	CALL GETTPD		;RECOMPUTE AS IF WRITE ACCESS
	MOVX 2,TWWRT		;GET WRITE BIT AGAIN
	ANDCAM 2,PFHPFW		;RESTORE
	CAIE T1,ILWR		;WRITE PROBLEM?
	CAIN T1,WCPY
	IFNSK.

;Here if illegal to write (not copy-on-write). If we have PTN,,PN, then a
;temporary pointer has been stored in the page table. Clear it, because
;this user cannot create the page.

	  MOVE T1,N6ID		;GET ID
	  TLNN T1,-1		;AN OFN TO CLEAR?
	  JRST N6ILRD		;NO
	  HLRZ Q2,T1		;GET THE OFN
	  CALL SETSP6		;MAP THE OFN
	  HRRZS T1		;ALLOW INDEXED REFERENCE IN SECTION 1
	  SETZM CSWPGA(T1) 	;CLEAR MAP SLOT IN THE OFN
	  CALL RELSPG		;CLEAR MAPPING
	  JRST N6ILRD		;AND GIVE ERROR
	ENDIF.
;   IFN CFSCOD,<			;If CFS stuff
	CAIN T1,NIC		;Still doing NIC code?
	IFSKP.			;If not
	 CAIN T1,NTWRTK		;token modify?
	 MOVEI T1,NTWRTX	;Make sure it is "write"
	 MOVE T4,T1		;Copy the action routine
	 RET			;And go to it
	ENDIF.
;   >	;IFN CFSCOD

;Here if legal to create page. Lock the page table into core.

NIC62:	HLRZ 2,N6ID		;GET PTN
	IFN. T2			;IF THERE IS ONE...
	  HRRZ T1,SPT(T2)	;GET CORE ADR
	  MOVX 2,PLKV		;LOCK IT IN CORE IN CASE RESKEDS BELOW
	  ADDM 2,@CST1X+1
	ENDIF.
	;..
;See if there is room on the disk.

	;..
	HLRZ 1,N6ID		;GET OFN OF IDENT
	MOVE 2,N6ID		;GET IDENT
	SKIPN 1			;HAVE ONE?
	HLRZ 1,SPTH(2)		;NO, GET IT FROM SPTH
	MOVEM T1,N6OF
	CALL QCHKHW		;CHECK DISK, ETC...
	 JRST NIC6F		;CAN'T CREATE PAGE
;   IFN CFSCOD,<			;If CFS
	IFE. T2			;If did a resched
	 MOVE T1,N6ID
	 CALL NIC6UC		;UNLOCK PT PAGE IF ANY
	 RETSKP			;RETURN AND TRY AGAIN
	ENDIF.
	MOVEM T1,N6QT		;Save it
;   >	;IFN CFSCOD

;If OFN is locked, wait and dismiss the page fault. Someone else may have
;fixed the problem. Otherwise, lock the OFN

	MOVE 1,N6OF		;GET OFN BACK
	MOVX 2,SPTLKB
	TDNN 2,SPTH(1)		;IS IT NOW LOCKED?
	IFSKP.
;   IFN CFSCOD,<
	  CALL QREL		;Release hold on quota
;   >
	  CALL WTOFNS		;OKSKED AND DISMISS
	  NOSKED
	  MOVE T1,N6ID
	  CALL NIC6UC		;UNLOCK PT PAGE IF ANY
	  RETSKP		;RETURN AND TRY AGAIN
	ENDIF.
;   IFN CFSCOD,<
	LOAD T2,SPTST,(T1)	;GET FILE STATE
	CAIE T2,.SPSWR		;WRITE ACCESS?
	IFNSK.
	  OKSKED		;ALLOW SCHEDULING
  	  MOVE T1,N6OF		;GET OFN
	  CALL QREL		;Release the alloc lock
	  MOVEI T2,1		;EXCL ACCESS
	  CALL CFSAWT		;GET IT
	  NOSKED
	  MOVE T1,N6ID
	  CALL NIC6UC
	  RETSKP
	ENDIF.
;   >	;IFN CFSCOD
	MOVE 1,N6OF
	CALL LCKOFA		;GET IT. IT WILL SUCCEED, I.E. NO BLOCKING
	MOVX 2,OFNWRB		;NOTE OFN CHANGED
	IORM 2,SPTH(1)		;SET LOCK AND OFN MODIFIED
IFN SPTDSW,<			;ONLY IF DEBUGING SPTLKB PROBLEMS
	CALL SPTRAC		;RECORD WHO LOCKED SPTLKB
 >				;END OF IFN SPTDSW

;Assign a page on the disk and update allocation information for the directory.

;   IFN CFSCOD,<
	MOVE T1,N6OF		;The OFN
	SOS T2,N6QT		;One less on the quota
	CALL QSET		;Set new value assuming all is well
;   >	;IFN CFSCOD
	MOVE T1,N6ID		;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
	SKIPA T2,N6OF		;Recover OFN
	JRST NIC99		;Have an address!
	CALL DSKGET		;assign an address
	IFNSK.			;If no more space
;   IFN CFSCOD,<
	 MOVEM T1,LSTERR	;Save error
	 MOVE T1,N6OF		;Get OFN
	 CALL QRUP		;Undo decrement
	 MOVE T1,LSTERR
;   >	;IFN CFSCOD
	 JRST NIC6D		;RAN OUT
	ENDIF.
NIC99:	SKIPE T1		;SUCCEED OR RESCHED?
	IFSKP.
	   MOVE T1,N6ID		;DID A RESCHED.
	   CALL NIC6UC		;FREE PAGE
	   MOVE T1,N6OF		;GET OFN
;   IFN CFSCOD,<
	CALL QRUP
;   >
	   CALL ULKOFN		;UNLOCK IT
	   RETSKP		;AND TRY AGAIN
	ENDIF.
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<
	MOVE T2,N6OF		;GET OFN
	LOAD T2,ALOCX,(T2)	;INDEX TO QUOTA TABLE
	DECR PGLFT,(T2)		;ONE LESS PAGE LEFT
   >	;IFE CFSCOD
   >				;END REPEAT 0

;Save the disk address. If ID was (0,,SPTN), then it points to the entry in
;the SPT for this page. Fill in the address there. IF ID was (PTN,,PN), map
;the OFN and store the page pointer at offset PN.

	TLO 1,(DSKNB)		;INDICATE PAGE NEVER PREVIOUSLY WRITTEN
	MOVE 2,1
	MOVE T1,N6ID		;ORIG PAGE
	TLNE 1,-1		;IN SPT?
      IFSKP.
	STOR 2,STGADR,SPT(1) 	;YES, STORE NEW ADDRESS
      ELSE.
	HLRZ Q2,1
	CALL SETSP6		;MAP XB
	HRRZ T3,T1		;ALLOW INDEXED REFERENCE IN SECTION 1
	STOR 2,STGADR,CSWPGA(T3) ;STORE NEW ADDRESS IN XB
	CALL ULKP6		;UNDO LOCK ABOVE
   REPEAT 0,<			;Don't use this until DSKFIL is fixed
	HLRZS T1		;OFN
	XMOVEI T2,CSWPGA(T3)	;address we just stored
	CALL DSKFIL		;Try to fill in preallocated pages
	MOVE T1,N6ID		;Restore IDENT
   >	;REPEAT 0
	CALL RELSPG
      ENDIF.
	CALL NIC6UL		;UNLOCK OFN
	RETSKP			;PAGE NOW ASSIGNED, RETURN
;HERE WHEN NO ROOM CONDITION

;Unlock the OFN

NIC6D:	MOVEM T1,LSTERR
	MOVE T1,N6OF		;GET OFN
	CALL ULKOFN
	SKIPA

;If ID was (OFN,,PN), clear page table entry and unlock the core page for the
;OFN

NIC6F:	MOVEM T1,LSTERR		;SAVE ERROR CODE
	MOVE T1,N6ID		;GET ORIGINAL IDENT
	TLNN 1,-1		;OFN?
      IFSKP.
	HLRZ Q2,1		;YES, OFN TO REG 6
	CALL SETSP6		;MAP THE PT
	HRRZS T1		;ALLOW INDEXED REFERENCE IN SECTION 1
	SETZM CSWPGA(1)		;CLEAR POINTER (NO DSK ADDRS YET)
	CALL ULKP6		;UNDO PT LOCK
	CALL RELSPG		;RELEASE SPECIAL PAGE
      ENDIF.

;Set up address for caller to go to. Set up channel for quota exceeded
;interrupt.

	MOVE T2,LSTERR		;SEE WHICH ERROR
	MOVX 1,.ICQTA		;QUOTA EXCEDED CHL
	CAIN T2,IOX11		;QUOTA EXCEEDED?
	JRST N6ILRF		;YES, DO INTERRUPT
	MOVX T1,.ICMSE		;MACH SIZE CHNL
	CAIN T2,IOX35		;ALLOCATION SCREWED UP?
	JRST N6ILRF		;YES, GENERATE ILLEG REF INT
	MOVE T3,BITS(T1)	;BIT FOR MSE CHANNEL
	TDNE T3,PSICHM		;CHANNEL ON?
	JRST N6ILRF		;YES, DO IT
	;..
	;..
   REPEAT 1,<
	JRST N6ILRF>		;TO ILLEG REF
   REPEAT 0,<
;The following is not now used.  It will cause a fork to wait on
;a 'disk full' condition rather than bombing out.
	XMOVEI T1,N6DSKC	;NO, SET TO WAIT FOR DISK
	XMOVEI T4,PGUNTD
	RET

;UNTRAP TO HERE IF DISK FULL AND MSE INTERRUPT NOT ENABLED

N6DSKC:	SAVET
	HRRZ T2,UTRSW		;SHOULD BE STR NUMBER
	HLRZ T3,UTRSW		;CHECK QUANTITY
	CAIE T3,N6DSKC		;CHANGED?
	RET			;YES, RETURN AND TRY AGAIN
	HRROI T1,[ASCIZ /
[Disk full, waiting.../]
	PSOUT
      DO.
	NOSKED
	SETZ T1,		;SAY FREE CHOICE ASSMT
	CALL [	SAVEAC <T2>	;TRY ASSMT (PRESERVE STR NO IN T2)
;   IFN CFSCOD,<
		CALLRET DSKASW
;   >
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<CALLRET DSKASN>
   >				;END REPEAT 0
		              ]
	IFSKP.
	  SKIPE T1		;SEE IF IT WORKED OR DID A RESCHED
	  CALL DEDSK		;IT WORKED, GIVE BACK PAGE AGAIN
	  OKSKED
	  HRROI T1,[ASCIZ /OK]
/]
	  PSOUT
	  RET			;RETURN TO TRY REF AGAIN
	ENDIF.
	OKSKED			;STILL FULL
	MOVEI T1,^D5000		;WAIT 5 SECS
	DISMS
	LOOP.			;TRY AGAIN
      ENDDO.
   >				;END OF REPEAT 0

;EXITS FROM NIC6A

N6ILRD:	XMOVEI T4,ILRD		;DISPATCH AFTER RETURN
	RET

N6ILRF:	XMOVEI T4,ILRF
	RET
;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
	CALL ULKP2		;UNLOCK IT
	RET

;UNLOCK OFN AFTER ASSIGNMENT

NIC6UL:	SAVEAC<T1>		;SAVE THE OFN
	HLRZ 2,1		;GET OFN
	SKIPN 2			;HAVE ONE?
	HLRZ 2,SPTH(1)		;NO, GET IT FROM SPTH
	MOVE T1,T2		;COPY OFN
	CALLRET ULKOFN
	ENDSV.

;Scheduler test to wait for force out of OFN to finish
;	T1/ the OFN

WTFOD::	TMNE <SPTDSF,SPTFO>,(T1) ;STILL BEING FORCED OUT?
	JRST 0(4)		;YES
	JRST 1(4)		;NO
;Here when we think that TRPID and TRPPTR are no longer valid, and
;a retry of the reference will probably cause another page fault.

TRPRST:	CALL GETTPD		;ANALYZE THINGS AGAIN
	JRST 0(T1)

;RESUME PROCESS AFTER PAGER TRAP

;Expects TRVAR set up by PFAULT

PGUNT0:	MOVX CX,FPD		;ON ERROR
	ANDCAM CX,PFHFL		; CLEAR FPD BEFORE PROCEEDING
PGUNTP:	SKIPE TRAPC		;OUTER LEVEL TRAP?
	JRST PGUNT4		;NO

;Here if returning from top level trap. Handle user runtime.

	SKIPE IPTIM		;INCLUDE PAGE TRAP TIME?
	JRST [	CALL GETHRT	;YES, READ CURRENT TIME
		SUB T1,PFHTIM	;COMPUTE DIFFERENCE
		JRST PGUNT5]
	CALL FRTON		;TURN CLOCK ON, GET TIME OFF
PGUNT5:	ADDM T1,PTTIM		;ACCUMULATE FORK TIME
	ADDB T1,HSPTTM		;ACCUMULATE SYSTEM TIME
	IDIVI T1,NTMS		;CONVERT UNITS
	MOVEM T1,SPTTIM		;MAINTAIN 1 MS UNITS

;Stack contains flags and PC to which we want to go. If returning to user,
;store them in FFL and FPC and return.

PGUNT4:	MOVE T3,PFHFL		;GET FLAGS AT TIME OF TRAP
	MOVE T4,PFHPC		;GET PC AT TIME OF TRAP
	TXNN T3,UMODF		;TO USER?
	JRST PGUNT6		;NO, MONITOR
	DMOVEM T3,FFL		;USER, CAN PUT RETURN IN FFL
	RET

;Trapped from monitor. Restore work AC's. Store flags and PC in TRAPFL and
;TRAPPC

PGUNT6:	DMOVEM T3,TRAPFL	;SAVE FLAGS AND PC
	DMOVE T1,PFHACS		;RESTORE WORK AC'S
	DMOVE T3,2+PFHACS
	MOVE FX,4+PFHACS
	RETSKP			;INDICATE RETURNING TO MONITOR

;This label is for the benefit of XGCCHK. It marks the highest address in
;the page fault handler that could conflict with XGCCHK's modification of
;the UPT.
PFHEND:
;UNTRAP AND DISPATCH TO SPECIFIED ADDRESS
; T1/ MONITOR ADDRESS

PGUNTD:	SKIPE TRAPC		;NESTED TRAP?
	BUG.(HLT,PGUNDX,PAGEM,SOFT,<PGUNTD - In nested trap>,,<

Cause:	There was an attempt to use a special untrap address while in 
	a nested trap.
>)
	MOVE T3,PFHFL		;GET FLAGS
	MOVE T4,PFHPC		;GET PC
	TXNN T3,UMODF		;FROM USER?
	IFSKP.
	  DMOVEM T3,KIMUFL	;YES, SIMULATE MUUO
	  MOVEM T1,KIMUEF	;WITH DISPATCH ADR AS UUO WORD
	  XMOVEI T1,MENTP	;UNTRAP TO ENTER JSYS CONTEXT
	  MOVEM T1,PFHPC	;SET ROUTINE BELOW AS NEW PC
	  MOVX T2,MONENV	;INIT FLAGS AT UNTRAP
	  MOVEM T2,PFHFL	;SET PCU IN FLAGS WORD
	ELSE.
	  MOVE T2,TRAPAP	;FROM MONITOR, SIMULATE CALL
	  PUSH T2,T4		;PUSH PC
	  MOVEM T1,PFHPC	;SET UNTRAP ADDRESS
	ENDIF.
	JRST PGUNTP

;ENTER JSYS CONTEXT AND DISPATCH

MENTP:	MCENTR			;ENTER JSYS CONTEXT
	CALL @KIMUEF		;CALL ROUTINE
	 JRST MRETN		;RETURN TO USER
	SMRETN
	ENDTV.			;END OF PFAULT'S TRVAR
;ASSIGN PAGE AND SET AGE

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

;AGESN -- assign a valid age to a page, and add it to a process's working set

;Accepts:
;	T1/ pointer to page
;	FX/ fork handle

;	CALL AGESN

;Returns +1: always

AGESN::	SAVET			;TRANSPARENT TO ALL ACS
	HRRZ T2,T1		;CORE PAGE NUMBER
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
		SKIPE PRELRQ	;PRELOAD REQUEST?
		JRST AGES2	;YES, DON'T REASSIGN
		HRRZ T1,T2	;PASS PAGE NUMBER
		CALL SOSWSP	;REDUCE WSP
		JRST ATP1]	;GO ASSIGN TO THIS PROCESS
	CAILE 1,TRP0TM		;WITHIN TABLE RANGE?
	JRST BADAGE		;NO - BOMB
	XCT TRP0T(1)
AGES2:	RET

;Transfer according to age of page

TRP0T:	JRST ATP0		;AVAILABLE AND ON REPLACABLE QUEUE (PSRPQ)
	JRST BADAGE		;READ COMPLETED (PSRDN)
	JRST ATP1R		;READ COMPLETED (PSRDN)
	JRST BADAGE		;NOT USED
	JRST ATP4		;WRITE IN PROGRESS (PSWIP)
	JRST BADAGE		;NOT USED
	JRST ATP2		;READ IN PROGRESS (PSRIP)
	JRST BADAGE		;ON SPECIAL MEMORY QUEUE (PSSPQ)
TRP0TM==.-TRP0T-1		;MAXIMUM LEGAL ENTRY
;Read done. If there was an error, interrupt this fork

ATP1R:	MOVSI 1,(SWPERR)	;CHECK FOR ERROR ON READ
	TDNN 1,@CST3X+2
	JRST ATP1		;NO ERROR
	PUSH P,2
	HLRZ T1,@CST2X+T2	;GET OWNING SPTN
	JUMPN T1,[CAIL T1,NOFN	;OFN?
		  JRST ATP1R2	;NO, FORGET IT
		  JRST ATP1R1]	;YES
	HRRZ T1,@CST2X+T2	;SPTN OF PAGE
	CAIL T1,NOFN		;OFN?
	HLRZ T1,SPTH(T1)	;NO, GET OFN
	JUMPE T1,ATP1R2		;NONE FORGET IT
ATP1R1:	LOAD T2,DIROFN		;GET OFN OF CURRENT DIRECTORY
	CAMN T1,T2		;SAME?
	JRST [LOAD T1,STRX,(T1)	;GET STRUCTURE NUMBER
	      BUG.(CHK,SWPDIR,PAGEM,HARD,<Swap error in directory page>,<<T1,STRX>>,<

Cause:	The monitor detected an error while swapping in a page with the same
	OFN as the currently mapped directory. The directory will be marked.

Data:	STRX - Structure number
>)
	      JRST .+1]		;AND CONTINUE
ATP1R2:	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

;Read in progress. Wait for completion and recheck age

ATP2:	MOVSI 1,0(2)
	HRRI 1,SWPRT		;READ NOW IN PROGRESS OR COMPLETED
	MOVE T3,@CST1X+T2
	TXNE T3,DSKAB		;USE APPROPRIATE TEST
	HRRI T1,DSKRT
	PDISMS			;RESCHEDULE UNTIL AVAILABLE
	JRST AGES1		;CHECK AGE AGAIN

;Write in progress. Clear age so SWPDON won't put page on replaceable
;queue.

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

;Page is on the replaceable queue. remove it.

ATP0:	SOS NRPLQ		;ONE LESS PAGE ON REPLACABLE
	PUSH P,3
	PIOFF
	MOVE 1,@CST3X+2		;UNQUEUE PAGE FROM REPLACABLE Q
	HRRZ 3,1
	HLLM 1,@CST3X+3
	HLRZ 3,1
	HRRM 1,@CST3X+3
	PION
	POP P,3
	SETZM @CST3X+2
	AOS SRPQSC		;SYSTEM COUNT OF "SAVES"
	;..
;Here to add the page to the process's working set.

	;..
ATP1:	OPSTRM <AOS T1,>,FKCSIZ	;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
	CALL UPDSNR		;UPDATE SUMNR
	JN FKWSL,,ATP1A		;MAKE SURE WS IN MEM
	BUG.(CHK,FRKBAL,PAGEM,HARD,<AGESET - Fork not in BALSET>,,<

Cause:	While adding a page to a process's working set, AGESET detected
	that the working set is not in memory.

>)
ATP1A:	ADJSP P,-1 		;FLUSH GARBAGE
	STOR FX,CSTOFK,+2	;SET OWNERSHIP
	STOR FX,CFXRD,+T2
	LOAD T1,FKXAGE		;INIT LAST XGC TIME
	STOR T1,XGAGE,+T2
	MOVX T1,DSKSWB		;CLEAR MISC FLAGS
	ANDCAM T1,@CST3X+T2
;   IFN CFSCOD,<
	MOVE T1,@CST2X+T2	;GET OWNER
	CAIL T1,NOFN		;IS THIS AN OFN?
	IFSKP.
	 TMNN SPTSFD,(T1)	;YES. DOES IT NEED XSUM STUFF?
	 ANSKP.
	  BUG.(HLT,AGSETX,PAGEM,SOFT,<AGESET - XB needs checking>,,<

Cause:	A index block that has been "forced out" needs to be swapped in and
	checked.
>)
;	  CALL ATPSER		;No. rats
	ENDIF.
;   >	;IFN CFSCOD
	MOVE T1,CUTAGE
	CAIGE T1,LGABOT		;Within range
	ADDI T1,AGEWRP		;No
	STOR T1,CSTAGE,+T2	;Set old age
	JRST AGES2

;Local routine to give an PSI on swap error

;   IFN CFSCOD,<
ATPSER: MOVEI T1,OPNX16		;STORE ERROR CODE
	MOVEM T1,LSTERR
	MOVX T1,.ICDAE		;FILE DATA ERROR PSI CHANNEL
	MOVEI T2,0(FX)		;GET FORK NUMBER
	CALL PSIRQ		;INTERRUPT THE FORK
	CHKINT			;GET IT SEEN
	RET			;DONE

;Scheduler wait routine for above

WTXBI:	TMNE SPTDSF,(T1)	;DDMP done it yet?
	JRST 0(4)		;No
	JRST 1(4)		;Yes
;   >	;IFN CFSCOD
;CHECK FOR XGC DUE - CALLED BY SCHED
;This routine causes XGC to be run by forcing the process to simulate a page
;fault.

XGCCHK::MOVE T2,FKRT
	SUB T2,LSTXGR		;TIME SINCE LAST XGC
	TMNN FKINX,(FX)		;OK TO INTERRUPT NOW?
	CAMGE T2,GCRATE		;GC DUE?
	RET			;NO, NO

;Don't do this if the process can't take an interrupt or is in the initial
;stages of a page fault.

	MOVE T1,PFL		;GET PC FLAGS
	CALL PITEST		;OK TO INTERRUPT NOW?
	 RET			;NO
	DMOVE T1,PFL
	TXNN T1,UMODF		;USER MODE?
	JRST [	HRRZ T3,T2	;NO, SEE IF PGRTRP ENTRY OR EXIT
		CAIL T3,PGRTRP
		CAIL T3,PFHEND
		JRST .+1	;NOT CRITICAL SECTION
		RET]		;CRITICAL - DEFER

;Copy flags and PC at last unscheduling to trap locations. Store the PC
;in the page fail word, setting TWUSR if process was in user mode. Set
;the new PC to PGRTRP. The process will resume at PGRTRP as if a page fault
;had occurred. This will cause PGTACC to be called, which will call XGC.

   IFN KLFLG,<
	DMOVEM T1,UPTPFL	;SIMULATE PGR TRAP
	TXNE T1,UMODF
	TXO T2,TWUSR		;USE PC AS PAGE FAIL WORD
	MOVEM T2,UPTPFW
   >				;END OF IFN KLFLG
   IFN KCFLG,<
	DMOVEM T1,KCPFOF	;SAVE AS OLD FLAGS AND PC
	MOVEM T2,KCPFVA		;SAVE PC AS THE VIRTUAL ADDRESS
	MOVEI T2,PFVCLN-1	;FAKE A CODE ONE GREATER THAN HIGHEST EVER GENERATED
	STOR T2,TWCOD,T2	;SAVE IT IN THE PAGE FAIL CODE WORD
	TXNE T1,UMODF		;WAS PROCESS IN USER MODE?
	TXO T2,TWUSR		;YES. SET THIS IN THE CODE WORD
	MOVEM T2,KCPFCD		;SET THE PAGE FAIL CODE WORD
   >				;END OF IFN KCFLG

	LOAD T1,VSECNO,T2	;GET PCS
	TXO T1,PCU!MONFLG	;GET AC BLOCKS RIGHT
	MOVE T2,[MSEC1,,PGRTRP] ;MAKE THE PROCESS GO TO PGRTRP
	DMOVEM T1,PFL
	RET
;FIND LAST DISK ADDRESS ASSIGNED IN THIS XB SO THAT DSKASN CAN ASSIGN
;THE NEXT PAGE AT AN OPTIMAL LOCATION
; T1/ IDENT
;Returns:
;	+1 T1/ address of disk page last assinged.
;	+2 T1/ address of preallocated page to reuse.
;If a preallocated page is found, its slot in the XB will be
;zeroed. Therefore, the caller is responsible for disposing
;of this page.

FNDLDA::SAVEQ
	HLRZ Q2,T1		;SETUP OFN
	JN NCORTM,SPT(Q2),FNDLDX ;IF NOT IN CORE, USE XBADDR
	MOVE FX,FORKX		;GET CURRENT FORK
	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
   REPEAT 0,<			;Not needed until DSKFIL is reinstated
	TXZE T2,DSKNB		;Is this a preallocated page?
	IFNSK.			;If so
	 HRRZ T3,T1		;Get offset
	 SETZM CSWPGA(T3)	;Zap the slot
	 LOAD T1,STGADR,T2	;Copy it
	 CALL RELSPG		;Clear mapping
	 RETSKP			;And say we have one
	ENDIF.
   >	;REPEAT 0
	LOAD T1,STGADR,T2	;Otherwise, use this address for assignment
	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

   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<			;If not CFS
QCHKH::
QCHKHW::
QCHK::	SKIPN USRSPC		;USER SPACE CHECKING?
	RETSKP			;NO
	LOAD T2,ALOCX,(T1)	;GET INDEX INTO QUOTA TABLES
	SKIPN T2		;GOOD THING TO CHECK
	BUG.(HLT,NULQTA,PAGEM,SOFT,<QCHK - NO QUOTA INFO SETUP>,,<

Cause:	The monitor is checking the disk quota to see if a page can be
	added to a file. However, this OFN's pointer into the allocation
	tables is 0, an illegal value. Either the caller provided a bad
	OFN, or the SPT entry for the OFN is incorrect.
>)
	OPSTR <SKIPG>,PGLFT,(T2)
	JRST QCHK2		;OVER QUOTA - CHECK PRIVS
	RETSKP			;OK

QCHK2:	MOVE T2,CAPENB		;SEE IF USER IS WHEEL/OPR
	TXNE T2,SC%WHL!SC%OPR
	RETSKP			;YES - OK TO CREATE PAGE
	MOVEI T1,IOX11		;NO, FAIL. SETUP ERROR CODE
	RET
   >	;IFE CFSCOD
   >				;END REPEAT 0
;ROUTINE TO CHECK ON DISK QUOTA AND DISK AVAILABILITY
;C(T1) := OFN
;
;Non-CFS entries:
;RETURN +1	DISK FULL / QUOTA EXCEEDED. T2/ The allocation
;RETURN +2	OK
; All entry points are the same for non-CFS monitor.
;For CFS: +2 return T1/ the current allocation
;	  QCHK Simply checks the quota. It may cause a resched.
;	  QCHKH checks quota and "locks" quota resource on this node
;	  if the quota is acceptable. May cause a resched.
;	  QCHKHW same as QCHKH execpt if a resched is required, it
;	  will not lock the resource and will return +2 T1/-1

;   IFN CFSCOD,<			;CFS only routines

;Get and lock allocation information
;	T1/ OFN
;	T2/ Write or read

QLOK:	MOVEI T3,.CFAGT		;Function
	SKIPE T2
	TXO T3,CF%HLD
	LOAD T1,ALOCX,(T1)	;Get alloc entry
	LOAD T1,PGPTR,(T1)	;Get allocation resource address
	SETZM T2
	SETOM T4
	CALL CFSDAU		;Get it
	 RET			;Did a resched
	RETSKP			;Got it cleanly

;Release and return +2 with value in AC2 preserved.
;	T1/ OFN

QREL1:	CALL QREL		;Release it (it savees the regs)
	RETSKP			;Do it

;Check allocation.
;	T1/ OFN
;Returns: +1 over alloc
;	+2 OK. T1/ The allocation

QCHK::	ASUBR <OFN1>
	MOVEI T2,0		;Read only
	CALL QLOK		;Get it
	 NOP			;Don't care if did a resched
	EXCH T1,OFN1		;Save alloc, get OFN
	CALL QREL		;Release it
	MOVE T1,OFN1		;Recover allocation
	TMNN SCWOPR,CAPENB
	SKIPLE OFN1		;OK?
	RETSKP			;Yes.
	RETBAD(IOX11)
	ENDAS.

;Check and hold lock. Implies write access
;	T1/ OFN
;Returns:	+1 over quota. Resource not locked. Never happens!
;		+2 OK. T1/ current allocation

QCHKH::	ASUBR <OFN1>		;Save OFN
	MOVEI T2,1		;Need write access
	CALL QLOK		;Get it
	 NOP			;Don't care abour resched
	SETOM T2
	RETSKP			;And return

;Worker for QCHKW and QCHKWH

QCHKW0:	IFLE. T1		;If under quota
	 TMNE SCWOPR,CAPENB	;A privileged job?
	 ANSKP.			;If not
	 MOVE T2,T1		;Return value in T2
	 MOVE T1,OFN1		;Get OFN
	 CALL QREL		;Release it
	 RETBAD (IOX11)		;And give error return
	ENDIF.
	SETOM T2		;Say we did not resched
	RETSKP			;And done
	ENDAS.

;Get, lock, but not if a resched
;Returns:	+1 over quota
;		+2 T2/ 0 =) Did a resched. Otherwise, OK

QCHKHW::ASUBR <OFN1>		;Save the OFN
	MOVEI T2,1		;Write access
	CALL QLOK		;Get it
	IFNSK.			;If did a resched
	 MOVE T1,OFN1
	 SETZM T2
	 CALLRET QREL1		;Tell above
	ENDIF.
	CALLRET QCHKW0		;Do common case
	ENDAS.
;More directory allocation routines for CFS

;Release allocation resource
;	T1/ OFN
;Returns:	+1. All regs preserved

QREL::	SAVET
	LOAD T2,ALOCX,(T1)	;Get dir #
	LOAD T1,PGPTR,(T2)	;Get resource block address
	SETZM T2
	MOVEI T3,.CFARL		;The function
	CALL CFSDAU
	 NOP
	RET

;Set (and release) allocation
;	T1/ OFN
;	T2/ Quota to set
;Returns +1. No ACs preserved

QSET::	MOVE T4,T2		;Copy quota
	LOAD T2,ALOCX,(T1)
	LOAD T1,PGPTR,(T2)	;Get pointer to block
	MOVEI T3,.CFAST		;Set function
	SETZM T2
	CALL CFSDAU		;Do it
	 NOP
	RET

;Here to undo decrement of quota and release resource
;	T1/ The OFN
;Preserves T1

QRUP::	SASUBR <AC1>
	MOVEI T2,1		;need write access
	CALL QLOK		;Get it
	 NOP			;Ignore resched
	AOS T2,T1		;Increase it
	MOVE T1,AC1
	CALLRET QSET		;Set new value
	ENDAS.

;   >	;IFN CFSCOD
;ACCOUNT FOR ONE PAGE TRAP

;	CALL PGTACC

;RETURNS +1: ALWAYS

PGTACC:	MOVE 2,JOBNO
	HRRZ 2,JOBNAM(2)	;GET SUBSYSTEM INDEX
	AOS @[EP. SPFLTS(2)]	;ACCOUNT PAGE FAULTS FOR SUBSYSTEM
	MOVE T2,FKRT
	SUB T2,LSTXGR		;TIME SINCE LAST XGC
	SKIPG TRAPC		;OUTER LEVEL?
	CAMGE 2,GCRATE		;TIME FOR ANOTHER XGC?
	JRST NICMG1		;NO
	CALL SETXAG		;SET CUTOFF FOR XGC
	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
	CALL UPDSNR		;REDUCE NR AND SUMNR ACCORDINGLY
NICMG1:	CALL NICCKS		;CHECK FOR ALLOWABLE SIZE
	RET
	SUBTTL Working Set Manager

;ADD VIRTUAL ADDRESS TO WORKING SET ADDRESS CACHE
; T1/ VIRTUAL ADDRESS IN PAGE FAIL WORD FORMAT
;	CALL ADDWSC
; RETURN +1 ALWAYS

ADDWSC:	TXNN T1,TWUSR+VSECNO	;MON SECTION 0?
	TXO T1,<MSEC1>B17	;YES, MAKE EQUIV TO SEC 1
	LDB T2,[POINTR T1,WSCASS] ;GET ASSOC BITS
	TXNE T1,TWUSR		;USER MODE ADR?
	TXO T2,WSCUSR		;YES
	LDB T1,[POINTR T1,WSCIDX] ;GET INDEX BITS
	IMUL T2,[WSCMS1]	;REPLICATE IN ALL FIELDS OF WORD
	IOR T2,[WSCVAM]		;INCLUDE VALID BIT
	MOVE T3,WSCSH(T1)	;GET CACHE WORD
	XOR T3,T2		;COMPARE ALL FIELDS

..X1==<WSCFLD>B<WSCNBF-1>
REPEAT ^D36/WSCNBF,<		;FOR ALL FIELDS OF WORD...
	TXNN T3,..X1		;FIELD ALL 0 (I.E. EQUAL)?
	RET			;YES, ENTRY ALREADY PRESENT. DO NOTHING
  ..X1=..X1_-WSCNBF		;SHIFT TO NEXT FIELD
   >
	AND T3,[WSCVAM]		;ENTRY NOT PRESENT, EXTRACT VALID BITS
	JFFO T3,[ASH T4,-3	;FIND AN UNUSED ENTRY
		DPB T2,WSCBPT(T4) ;STORE NEW ENTRY IN IT
		AOS NWSCE	;COUNT ENTRIES
		RET]		;DONE
	MOVE T3,WSCSH(T1)	;ALL ENTRIES FULL
	LSH T3,WSCNBF		;FLUSH LEFTMOST ENTRY
	DPB T2,[POINTR T3,WSCFLD] ;STORE NEW ENTRY IN RIGHTMOST FIELD
	MOVEM T3,WSCSH(T1)
	RET

;TABLE OF BYTE POINTERS TO ALL FIELDS OF WORD

WSCBPT:
  ..X==<WSCFLD>B<WSCNBF-1>
  REPEAT ^D36/WSCNBF,<
	POINTR WSCSH(T1),..X
	..X==..X_-WSCNBF
   >
;DELETE VIRTUAL ADDRESS FROM WORKING SET ADDRESS CACHE
; T1/ VIRTUAL ADDRESS IN PAGE FAIL WORD FORMAT
;	CALL DELWSC
; RETURN +1 ALWAYS. DOES NOTHING IF ENTRY NOT PRESENT

DELWSC::TXNN T1,TWUSR+VSECNO	;MON SECTION 0?
	TXO T1,<MSEC1>B17	;YES, MAKE EQUIV TO SEC 1
	LDB T2,[POINTR T1,WSCASS] ;GET ASSOCIATIVE BITS
	TXNE T1,TWUSR		;USER MODE ADR?
	TXO T2,WSCUSR		;YES
	LDB T1,[POINTR T1,WSCIDX] ;GET INDEX BITS
	TXO T2,WSCVAL		;INCLUDE VALID BIT
	MOVE T3,[POINT WSCNBF,WSCSH(T1)]
DELWS1:	ILDB T4,T3
	CAMN T4,T2		;GIVEN ENTRY?
	JRST [	SETZ T4,	;YES, CLEAR IT
		DPB T4,T3
		SOS NWSCE	;COUNT ENTRIES
		RET]
	TXNE T3,74B5		;CHECKED ALL ENTRIES?
	JRST DELWS1		;NO
	RET			;YES, DO NOTHING
;MAP ALL VALID CACHE ENTRIES USING GIVEN FUNCTION
; T1/ INSTRUCTION TO BE EXECUTED FOR EACH VALID ENTRY
;	CALL MAPWSC
; RETURN +1 ALWAYS

;INSTRUCTION GIVEN IN T1 IS EXECUTED FOR EACH VALID CACHE ENTRY WITH
;THE CORRESPONDING VIRTUAL ADDRESS IN T1 IN PAGE FAIL WORD FORMAT

MAPWSC:	SKIPA T2,[WSCSH]	;This fork if entered here
MAPWSO:	ADDI T2,WSCSH		;Compute location of cache
	STKVAR <MAPWFN,MAPWC1,MAPWBP>
	MOVEM T1,MAPWFN		;SAVE ARG
	HRLI T2,-WSCNCW		;INIT NO WORDS TO CHECK
	MAP T1,0(T2)		;Check access of page
   IFN KLFLG,<
	TLNE T1,360000
	TLNE T1,200000		;HARD PAGE FAIL CODE?
	RET			;Not. Skip it
   >				;END OF IFN KLFLG
   IFN KCFLG,<
	TXNN T1,MPHPFF		;HARD FAILURE?
	TXNN T1,MPVALD		;NO. DOES MAPPING EXIST?
	RET			;Can't do it
   >				;END OF IFN KCFLG
MAPWS5:	SKIPE 0(T2)		;WORD EMPTY?
	JRST MAPWS3		;NO, GO CHECK IT
MAPWS6:	AOBJN T2,MAPWS5		;LOOP OVER WORDS
	RET			;DONE

;FOUND NON-EMPTY WORD

MAPWS3:	MOVEM T2,MAPWC1		;SAVE WORD COUNT
	HRLI T2,(POINT WSCNBF,0) ;CONSTRUCT BYTE PTR TO FIRST ENTRY IN WORD
	MOVEM T2,MAPWBP
MAPWS4:	ILDB T2,MAPWBP		;SCAN BYTES
	JUMPN T2,MAPWS2		;JUMP IF VALID BYTE
MAPWS7:	MOVE T1,MAPWBP
	TXNE T1,74B5		;PTR AT END OF WORD?
	JRST MAPWS4		;NO, CONTINUE WORD
	MOVE T2,MAPWC1		;RESTORE AOBJN PTR
	JRST MAPWS6		;YES, STEP WORD

;FOUND VALID ENTRY, CONSTRUCT VIRTUAL ADDRESS

MAPWS2:	SETZ T1,
	HRRZ T3,MAPWBP		;COMPUTE INDEX
	SUBI T3,WSCSH
	DPB T3,[POINTR T1,WSCIDX] ;PUT INDEX IN PLACE
	TXZE T2,WSCUSR		;USER MODE ADR?
	TXO T1,TWUSR		;YES
	DPB T2,[POINTR T1,WSCASS] ;PUT ASSOC BITS IN PLACE
	XCT MAPWFN		;DO THE FUNCTION
	JRST MAPWS7		;CONTINUE WORD
;CHECK FOR SUFFICIENT PAGES ON RPLQ

CHKRPQ::MOVE 2,NSKED
	CAILE 2,1		;NOSKED PROCESS?
	JRST RSKP		;YES, ALLOW PAGE
	JSP T4,TRP0CT		;DO TEST
	 JRST [	MOVEI T1,TRP0CT	;MUST WAIT FOR ADDITIONAL PAGES
		RDISMS
		NOSKED
		RET]		;RETURN NOTING RESKED DONE
	CAMLE T2,NRPMIN		;GETTING LOW?
	RETSKP			;NO
	CHKINT			;YES, POKE SCHED AFTER TRAP COMPLETED
	RETSKP

TRP0CT:	MOVE T2,NRPLQ		;TEST FOR MEM AVAILABLE
	ADD T2,IOIP
	CAILE T2,NFKSPP		;BELOW MIN?
	SKIPN NRPLQ		;OR 0 IMMED AVAIL?
	JRST 0(T4)		;YES, WAIT
	JRST 1(T4)		;WAKE
;CHECK OVERALL SIZE FOR PHYSICAL CORE LIMITS

NICCKS:	SKIPE PAGDIF		;ANY PAGES ADDED OR DELETED RECENTLY?
	CALL ADJSWP		;YES. GO ADJUST NUMBERS THEN
	MOVE T4,FNPMAX		;DETERMINE CURRENT MAX SIZE
	MOVE T3,IRJAV
	CAIL T3,2		;LOAD ON SYSTEM?
	MOVE T4,SNPMAX		;YES, USE SMALLER LIMIT
	SUB T4,BALSHC		;REDUCE BY LOCKED PAGES, ETC.
	LOAD T1,FKWSS		;GET FORK VARIABLES
	LOAD T2,FKCSIZ
	CAML T2,T4		;CURRENT SIZE WITHIN BOUNDS?
	JRST NIC3		;NO, MUST REDUCE
	CAMG T1,T4		;RESERVE TOO LARGE?
	CAMG T1,T2		;RESERVE SUFFICIENT FOR ADD'L PAGE?
	JRST NIC3E		;YES, NO - RESET IT
	RET			;NO, ALL IS WELL

NIC3E:	LOAD T1,FKCSIZ		;RESET NR TO SIZE + 1
	ADDI T1,1
	LOAD T3,FKWSS
	SUB T1,T3
	CALLRET UPDSNR		;REDUCE SUMNR BY DIFFERENCE

;MUST DO XGC TO REDUCE SIZE OF FORK

NIC3:	SKIPLE TRAPC		;RECURSIVE TRAP?
	JRST NIC3E		;YES, DON'T XGC
	STKVAR <NICCAG>
	MOVE T1,CURAGE		;INIT CUTOFF AGE, 5 SEC WINDOW
	SUBI T1,^D5000/GLATCK
NIC3L:	MOVEM T1,NICCAG		;SAVE CUTOFF AGE
	CALL XGC
	LOAD T1,FKCSIZ
	ADD T1,BALSHC
	CAMGE T1,SNPMAX		;SIZE NOW WITHIN LIMITS?
	CAML T1,FNPMAX
	SKIPA
	JRST NIC3E		;YES, RESET NR AND CONTINUE
	MOVE T1,NICCAG
	CAMN T1,CURAGE		;CUTOFF WAS NOW?
	JRST NIC3E		;YES, CAN DO NO MORE
	ADDI T1,^D1000/GLATCK	;STEP IT BY 1 SEC
	CAMLE T1,CURAGE		;LIMIT TO CURRENT
	MOVE T1,CURAGE
	JRST NIC3L		;TRY AGAIN WITH SMALLER WINDOW
;RELEASE WORKING SET JSYS

.RWSET::MCENT
RWSET0:	NOSKED
	MOVE 7,FORKX
	MOVE T1,CURAGE		;SPECIFY 0 WINDOW
	CALL XGC
	LOAD T1,FKCSIZ		;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)
	CALL UPDSNR
	OKSKED
	JRST MRETN

;JSYS to manipulate process working set
;	WSMGR
;T1/	Function code
;T2/	Address of first pair
;T3/	Fork handle
;Pairs:
;	count of pages
;	first page
;
;Error if page number is too large, count is too large, or count
;is invalid.

RWMAX==200			;Max pages for each pass

.WSMGR::MCENT			;Standard entry
	SOSL T1
	CAILE T1,RWFNCN		;Valid function?
	RETERR (ARGX24)		;No
	JRST @RWFNCT(T1)	;Go to it

RWFNCT:	IFIW!RWSETZ		;Remove all
	IFIW!RWREMP		;Remove selected pages
	IFIW!RWLODP		;Load selected pages
	IFIW!RWRTRN		;Return working set
RWFNCN==.-RWFNCT-1

;Do RWSET function

RWSETZ:	CAIE T3,.FHSLF		;For this fork?
	ITERR (FRKHX1)		;No. Error then
	JRST RWSET0		;Do it

;Load or remove selected pages

RWLODP:	TDZA P3,P3
RWREMP:	MOVEI P3,1
	CAIE T3,.FHSLF		;Doing this fork?
	ITERR (FRKHX1)		;No. Can't do it then
	UMOVE Q1,0(T2)		;Get count of pairs
	MOVE Q2,T2		;Copy address pointer
	ADDI Q2,1		;Next word
	MOVE FX,FORKX		;Fork handle
	NOINT
	DO.			;Do all pairs
	 XCTU [DMOVE P1,0(Q2)]	;Get next pair
	 ERJMP [ MOVEI Q1,ARGX06 ;Illegal reference
	 	 EXIT.]		;Get out
	 SKIPL P2
	 CAMLE P2,[<VMADR>_-PGSFT] ;Is it valid?
	 IFNSK.			;If not valid
 	  MOVEI Q1,ARGX06	;Error code
	  EXIT.
	 ENDIF.
	 MOVE T3,P2		;See if end of range is valid
	 ADDI T3,-1(P1)		;Get last page in range
	 CAMLE T3,[<VMADR>_-PGSFT] ;is it?
	 IFNSK.
	  MOVEI Q1,ARGX24	;Error code
	  EXIT.
	 ENDIF.
	 IFG. P3		;If deleting
	  DO.			;Do this pair
	   DMOVE T1,P1		;Args for call
	   CAILE T1,RWMAX	;Can do it all in this one?
	   MOVEI T1,RWMAX	;No. Just do this much then so we aren't NOSKED
				; too long
	   CALL REMPGS		;Remove them
	   SUBI P1,RWMAX	;Did this much
	   JUMPLE P1,ENDLP.	;Keep going if need be
	   ADDI P2,RWMAX	;Increase page number
	   LOOP.
	  ENDDO.
	 ELSE.			;Or if adding
	  DO.
	   MOVE T1,P2		;Page number
	   LSH T1,PGSFT		;Make it an address
	   TXO T1,1B0		;User address
	   CALL FPTAX		;Get ID
	   JUMPE T1,ENDLP.	;If no translation, give up
	   MOVEI T2,1000	;Max pages in section
	   SUBI T2,0(T1)	;Compute max we can move
	   CAILE T2,0(P1)	;Compare to number we want to move
	   MOVEI T2,0(P1)	;Use smaller of the two
	   SUBI P1,0(T2)	;Compute number left
	   ADDI P2,0(T2)	;And page to continue from
	   CALL PREPG		;Do it
	    NOP			;Ignore failure
	   JUMPG P1,TOP.	;If more, do more
	  ENDDO.
	 ENDIF.
	 ADDI Q2,2		;Next pair
	 CALL PGRCLD		;Clear pager in case next reference is wrong
	 SOJG Q1,TOP.		;Do all pairs
	ENDDO.
	SKIPE T1,Q1		;Made it OK?
	RETERR()		;No
	MRETNG			;Yes, and done
;WSMGR continued

;Here to return the working set
;Register usage:
;	P1		Pair count
;	P2		pointer to current pair
;	P3		count of pages in current group
;	P4		Pointer to user's counter
;	P5		Offset for reading working set
;	Q1		Page expected in group
;	Q2		Beginning of group

RWRTRN:	CALL FLOCK		;Lock up job fork structure
	UMOVE T1,T3		;Get fork handle
	CALL SETLFK		;Map other fork to us
	MOVE P5,T1		;Copy offset
	UMOVE P1,0(T2)		;Get count of pairs in data base
	HRRZS P1
	MOVE P2,T2		;Block address
	MOVE P4,P2		;Save pointer to counter
	ADDI P2,1		;Point to first pair
	UMOVEM P1,0(P4)		;Clear left-half
	SETZB P3,Q1		;Nothing in current pair
	SETZM Q2		;Init start of range as well
	MOVE T1,[CALL RWRTR0]	;Coroutine of MAPWSC
	MOVE T2,P5		;Offset
	CALL MAPWSO		;Do it
	SKIPE P3		;Any residual pages?
	CALL RWRTR1		;Yes. Finish up
	CALL CLRLFK		;Clear fork mapping
	CALL FUNLK		;And clear fork lock
	MRETNG			;And done

;Coroutine of MAPWSC to handle page information.

RWRTR0:	TXZN T1,TWUSR		;A user address?
	RET			;No. Forget it
	LOAD T1,VPGNO,T1	;Get page number only
	CAME T1,Q1		;Is this the expected page?
	CALL RWRTR1		;No. Clean up last then
	ADDI P3,1		;Yes. Count up
	ADDI Q1,1		;Expect next one next time
	RET			;And done

;Handle end of range

RWRTR1:	IFG. P3			;If something to do
	 MOVSI T2,1		;A count
	 XCTU [ADDM T2,0(P4)]	;Increase pair count
	 SOSGE P1		;If more pairs
	 ANSKP.
	  UMOVEM P3,0(P2)	;Store it
	  UMOVEM Q2,1(P2)	;Store start of range
	  ADDI P2,2		;Next pointer
	ENDIF.
	SETZM P3		;No count
	MOVE Q1,T1		;New range pointer
	MOVE Q2,T1		;Save start of range
	RET			;Done

;CHECK IF PAGE IS SWAPPABLE NOW

SWPCHK::MOVE 2,@CST1X+1
	TLNE 2,(-PLKV)
	RET			;PAGE IS LOCKED OR HAS NO SWAP ADR
	MOVSI 2,(DWRBIT)
	TDNN 2,@CST3X+1		;BEING WRITTEN?
	AOS 0(P)		;NO, OK
	RET
;XGC, WSSWPO - ROUTINES WHICH SCAN FORK WORKING SET.
;XGC - NORMAL WORKING SET MANAGEMENT.  DEASSIGNS PAGES WHICH HAVE NOT BEEN
;	REFERENCED RECENTLY.  TIME OF LAST REFERENCE IS KNOWN FROM AGE
;	FIELD OF CST0, KEPT IN ELAPSED TIME UNITS.  FIXED BASE WINDOW SIZE
;	IS USED, BUT IS INCREASED IN INVERSE PROPORTION TO FRACTION OF
;	RUNTIME RECEIVED BY THIS PROCESS IN ORDER TO APPROXIMATE A
;	PROCESS TIME CLOCK.
;	XGC MAY BE CALLED MORE FREQUENTLY IF NECESSARY TO KEEP FORK SIZE WITHIN
;	LIMITS, SEE NICCKS.  IF CALLED WITH 0 SIZE WINDOW (CUTAGE=CURAGE),
;	XGC WILL DEASSIGN ALL PAGES FROM THE FORK.
;WSSWPO - SWAP OUT THE CURRENT WORKING SET WHEN DOING POSTPURGING.

GCWND:	^D2000/GLATCK		;BASE WINDOW SIZE
GCRATE:	^D2000			;RECIPROCAL OF GC FREQUENCY
GCMINW:	^D1000			;MINIMUM WINDOW FOR XGC

WSWPF==1B0			;LOCAL FLAG - SWAPOUT FUNCTION
XGSCF==1B1			;LOCAL FLAG - SHORT TIME SINCE LAST XGC
WSFLF==1B2			;Local flag. Cleaning up working set

XGC:	SKIPG DRMTPG		;SWAPPING INITIALIZED?
	RET			;NO, DO NOTHING
	TRVAR <XCUTAG,XGCVA,<XGCSQ,2>,XGCIPC>
	MOVEM T1,XCUTAG		;SAVE CUTOFF AGE
	DMOVEM Q1,XGCSQ
	SETZ Q1,		;NO FLAGS
	CALL XGC0		;DO THE WORK
	DMOVE Q1,XGCSQ
	CALLRET PGRCLD		;CLEAR HW PT

;COMPUTE NEW CUTOFF AGE

SETXAG:	MOVE T2,FKRT		;COMPUTE RUNTIME SINCE LAST UPDATE
	SUB T2,LSTXGR
	CAMG T2,GCMINW		;ABOVE MINIMUM?
	JRST [	MOVE T1,CURAGE	;NO, USE MAX WINDOW SIZE
		SUBI T1,AGEWRP-200
		JRST SETXG1]
	MOVE T1,FKRT		;UPDATE RUN AND ELAPSED TIMES
	MOVEM T1,LSTXGR
	MOVE T1,TODCLK		;COMPUTE ELPASED TIME SINCE LAST UPDATE
	SUBM T1,LSTXGT
	EXCH T1,LSTXGT
	IDIV T1,T2		;COMPUTE 1 / FRACTION OF TIME USED
	IMUL T1,GCWND		;SCALE WINDOW SIZE BY RATIO
SETXG1:	CAILE T1,AGEWRP-200	;LIMIT
	MOVEI T1,AGEWRP-200
	MOVN T1,T1		;SUBTRACT FROM CURRENT AGE
	ADD T1,CURAGE
	RET
;Routine to remove selected pages from the working set.
;	T1/ Count of pages
;	T2/ First page number
Returns:
;	+1 always. Note, this routine does not clear the pager.
;	The caller must do this before returning to the user!!!

REMPGS::SAVEAC <P1,P2>		;Work regs
	TRVAR <XCUTAG,XGCVA,<XGCSQ,2>,XGCIPC>
	DMOVEM Q1,XGCSQ		;We will use these
	MOVX Q1,WSFLF		;Indicate what we are doing
	DMOVE P1,T1		;Copy args
	MOVE T1,CURAGE		;Current pager age
	MOVEM T1,XCUTAG		;Collect anything we ask for!
	SUBI P2,1		;Init first page
	NOSKED
	DO.			;Let's do it
	 AOS T1,P2		;Next page
	 LSH T1,PGSFT		;Make it into an address
	 TXO T1,TWUSR		;It's a user page
	 CALL XGCR		;Do this one
	 SOJG P1,TOP.		;Do them all
	ENDDO.			;End of loop
	CALL NIC3E		;Update pager data now
	OKSKED
	DMOVE Q1,XGCSQ		;Recover regs
	RET			;Done
;SWAPOUT ALL PAGES OF PROCESS.  SIMILAR TO XGC, BUT SWAPS OUT
;PAGES STILL IN WORKING SET.
; FX/ FORK INDEX
;	CALL WSSWPO
; RETURN +1 ALWAYS

WSSWPO::TRVAR <XCUTAG,XGCVA,<XGCSQ,2>,XGCIPC>
	DMOVEM Q1,XGCSQ		;SAVE ACS
	MOVX Q1,WSWPF		;SET FLAG FOR FUNCTION
	CALL SETPP1		;SET PROCESS CONTEXT
	CALL SWPOMI		;INIT SWAPOUT LIST
	CALL SETXAG		;COMPUTE CUTOFF AGE
	MOVEM T1,XCUTAG
	CALL XGC0		;DO THE WORK
	CALL SETPSK		;RESTORE SCHED CONTEXT
	MOVSI Q1,-NFKSPP	;SET TO DO SPECIAL FORK PAGES
WSSWP1:	XCT FKSPPT(Q1)		;GET SPTN OF THE PAGE
	CALL WSSFKP		;COLLECT THE PAGE
	AOBJN Q1,WSSWP1
	CALL SWPOMG		;DO ALL QUEUED SWAPS
	DMOVE Q1,XGCSQ		;RESTORE AC
	RET

;COMMON CODE

XGC0:	MOVE T1,CURAGE
	STOR T1,FKXAGE		;SAVE TIME OF XGC
	MOVE T1,[CALL XGCR]
	CALLRET MAPWSC		;MAP WS PAGES
;ROUTINE CALLED FOR EACH PAGE IN WS
; T1/ VA IN PAGE FAIL FORMAT

XGCR:	MOVX T2,MAXIND		;INIT INDIRECT PTR COUNT
	MOVEM T2,XGCIPC
	MOVEM T1,XGCVA		;SAVE ADR
	TXNE T1,TWUSR		;IS IT A USER ADDRESS IN SECTION 0?
	TXNE T1,VSECNO
	JRST XGCR3		;NO
	LOAD Q2,LPGNO,T1	;USER SECTION 0 PAGE - FETCH PTR
	MOVE T1,UPTPGA(Q2)
	JRST XGCR2

XGCR3:	CALL FPTAXP		;GET IDENT
	JUMPLE T1,XGCRN		;NONX SECTION OR SECTION TABLE NIC
XGCR4:	CALL FETPTR		;FETCH PTR
	 JRST XGCRN		;COULDN'T - DELETE ADR FROM WS
XGCR2:	JUMPE T1,XGCRN		;FLUSH IF NO PTR THERE NOW
	MOVEM T1,Q2
	LOAD T1,PTRCOD,Q2	;GET PTR TYPE
	CAIN T1,INDCOD		;INDIRECT?
	JRST [	LOAD T1,IPPGN,Q2 ;YES, GET NEXT LEVEL PAGE NUMBER
		LOAD T2,SPTX,Q2	;AND PTN
		HRL T1,T2	;CONSTRUCT IDENT
		SOSLE XGCIPC	;INDIRECT LOOP?
		JRST XGCR4	;NO, KEEP TRACING
		JRST XGCRN]	;PROBABLY - IGNORE PAGE
	CAIN T1,SHRCOD		;SHARE?
	JRST [	LOAD T1,SPTX,Q2	;YES, GET SPTN
		LOAD Q2,STGADR,SPT(T1) ;GET ADR
		JRST XGCR1]
XGCR1:	TXNE Q2,NCORTM		;IN CORE?
	JRST XGCRN		;NO, DELETE FROM WS
	HRRZ Q2,Q2
	LOAD T1,CSTAGE,+Q2
	CAIGE T1,PSASN		;ASSIGNED?
	JRST [	CAIE T1,PSRDN	;NO, READ COMPLETED?
		JRST XGCRN	;NO, FLUSH FROM CACHE
		HRRZ T1,Q2
		CALL AGESN	;YES, ASSIGN IT
		JRST XGCRS]	;AND COLLECT IT
	CAMLE T1,CURAGE		;LEGAL AGE, CHECK FOR WRAPAROUND
	SUBI T1,AGEWRP
	LOAD T2,CSTOFK,+Q2	;GET OWNING FORK IDENT
	CAME T2,FX		;OUR PAGE?
	JRST XGCRF		;NO
	CAMG T1,XCUTAG		;OLDER THAN CUTOFF?
	JRST XGCRS		;YES, COLLECT
	MOVE T1,CURAGE		;NOTE THAT PAGE HAS BEEN SEEN
	STOR T1,XGAGE,+Q2
	JRST XGCRK		;NO, KEEP
;CHECK PAGE NOT OWNED BY THIS FORK

XGCRF:	TXNE Q1,WSFLF		;Flushing cache entries?
	IFSKP.			;If not
	 LOAD T3,CFXRD,+Q2	;GET ID OF LAST REFERENCE
	 CAMN T3,FX		;SELF?
	 JRST XGCRN1		;YES, KEEP PAGE BUT DON'T SWAP
	ENDIF.
	JXN Q1,WSWPF,XGCRS	;FLUSH IT IF SWAPOUT
	CAMG T1,XCUTAG		;RECENT REFERENCE?
	JRST XGCRN		;NO, REMOVE FROM OUR WS CACHE
	JRST XGCRN1		;YES, KEEP PAGE

;SWAPOUT AND DEASSIGN PAGE

XGCRS:	MOVE T1,XGCVA
	CALL DELWSC		;DELETE FROM WS CACHE
	JXN Q1,WSWPF,XGCRK1	;USE SWAPOUT LIST
	HRRZ T1,Q2
	CALL DECOR		;DEASSIGN
	CALL RSTLRF		;RESET LAST REF
	CALL CHKSHR		;PROBABLE SHARED PAGE?
	 JRST XGCRN1		;YES, LEAVE IT
	MOVE T2,NBPROC
	CAMN T2,NGOJOB		;ALL RUNNABLE FORKS IN MEM?
	JRST [	MOVE T2,MAXNR	;YES, AND PLENTY OF MEM?
		SUB T2,SUMBNR
		CAIL T2,^D100
		JRST XGCRN1	;YES, LEAVE PAGE AROUND
		JRST .+1]	;COLLECT IT
	HRRZ T3,Q2		;GET ONLY DESIRED INDEX BITS
	MOVE T2,@CST1X+T3	;SWAPOUT PAGE UNLESS LOCKED OR BEING WRITTEN
	TXNE T2,-PLKV
	JRST XGCRN1
	MOVX T2,DWRBIT
	TDNE T2,@CST3X+T3
	JRST XGCRN1
	HRRZ T1,Q2
	CALL SWPOUT		;SWAP IT OUT
	AOS SXGCWR
	OKSKD1			;GIVE OTHER PROCESSES A CHANCE
	NOSKD1
	JRST XGCRN1

XGCRN:	MOVE T1,XGCVA		;REMOVE PAGE FROM WS CACHE
	CALL DELWSC
XGCRN1:	RET
;KEEP PAGE.  DO NOTHING IF XGC, QUEUE FOR WRITE IF WSSWPO

XGCRK:	JXE Q1,WSWPF,XGCRN1	;DONE IF XGC
XGCRK1:	HRRZ T1,Q2
	CALL DECOR		;DEASSIGN
	CALL CHKSHR		;PROBABLY SHARED PAGE?
	 JRST XGCRN1		;YES, LEAVE IT FOR GCCOR
	CALL RSTLRF		;RESET LAST REF
	HRRZ T1,Q2
	MOVE T2,@CST1X+T1
	TXNE T2,-PLKV		;LOCKED?
	JRST XGCRN1		;YES, DO NOTHING
	MOVX T2,DWRBIT
	TDNE T2,@CST3X+T1	;BEING WRITTEN?
	JRST XGCRN1		;YES, DO NOTHING
	MOVX T2,CORMB
	TDNE T2,@CST0X+T1	;MODIFIED?
	SKIPG SWRSAF		;REASSIGN SWAP ADDRESSES?
	JRST [	CALL SWPOUT	;NO OR NO - DO REGULAR SWAPOUT
		JRST XGCRK2]
	CALL SWPOML		;YES AND YES - BUILD SWAP LIST
XGCRK2:	AOS SGCCWR
	JRST XGCRN1

;CHECK FOR PROBABLY SHARED PAGE

CHKSHR:	HRRZ T3,Q2		;GET ONLY DESIRED INDEX BITS
	HLRZ T1,@CST2X+T3
  IFE FTNSPSRV,<
	CAME T1,XCDBAS		;Section 6 swappable code?
  >
	CAMN T1,MMSPTN		;SWAPPABLE MON?
	RET			;YES, ASSUME SHARED
	JUMPN T1,RSKP		;IF NOT IN SPT, ASSUME PRIVATE
	LOAD T3,CFXRD,+T3	;IN SPT, CHECK LAST REFERENCE
	CAME T3,FX		;THIS FORK?
	RET			;NO, SHARED
	RETSKP			;YES, PRIVATE

;RESET LAST REFERENCE FIELD IF IT CONTAINS THIS FORK

RSTLRF:	HRRZ T1,Q2		;GET ONLY DESIRED INDEX BITS
	LOAD T2,CFXRD,+T1
	CAME T2,FX		;LAST REF BY THIS FORK?
	RET			;NO
	MOVX T2,CFXNUL
	STOR T2,CFXRD,+T1	;YES, RESET IT
	RET
;FETCH POINTER FROM PT GIVEN IDENT
; T1/ IDENT
;	CALL FETPTR
; RETURN +1: FAILURE, PT NOT IN CORE, ETC.
; RETURN +2: SUCCESS, T1/ WORD FROM PT OR SPT

FETPTR:	HLRZ T2,T1
	JUMPE T2,[LOAD T1,STGADR,SPT(T1) ;SPT - GET ADDRESS
		RET]
	LOAD T2,STGADR,SPT(T2)	;GET PT ADDRESS
	TXNE T2,NCORTM		;IN CORE?
	RET			;NO
	LOAD T3,CSTAGE,+T2	;YES, CHECK AGE
	CAIGE T3,PSASN		;ASSIGNED?
	RET			;NO
	HRRZ T1,T1		;GET OFFSET INTO PAGE
	CALL MOVRCA		;GET WORD
	RETSKP

;COLLECT SPECIAL FORK PAGE (PSB, ETC.)
; T1/ ID OF PAGE
;	CALL WSSFKP
; RETURN +1 ALWAYS, PAGE DEASSIGNED AND SWAPOUT STARTED IF POSSIBLE

WSSFKP:	LOAD Q2,STGADR,SPT(T1)	;GET ADR
	TXNE Q2,NCORTM		;IN CORE?
	BUG.(HLT,WSSPNC,PAGEM,SOFT,<WSSFKP - Fork special page not in core>,,<

Cause:	The monitor is swapping out all pages of a process. It is
	trying to swap out one of the special pages (JSB, PSB, etc.).
	The page should be in core and locked, but it is not in core.

>)
	LOAD T3,CSTAGE,+Q2
	CAIGE T3,PSASN		;STILL ASSIGNED?
	BUG.(HLT,WSSPNA,PAGEM,SOFT,<WSSFKP - Fork special page bad age>,,<

Cause:	The monitor is swapping out all pages of a process. It is
	trying to swap out one of the special pages (JSB, PSB, etc.).
	The page should be in core and locked, but it is not
	assigned (its age is LESS THAN PSASN).
>)
	CALL ULKP6		;UNLOCK PAGE
	CALLRET XGCRK1		;COLLECT IT

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

UNLBTB::CALL ULKP1		;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

;Accepts:
;	T1/ PTN,,PN or 0,,SPTN
;	FX/ fork handle

;	CALL SWPIN0

;Returns +1: always

;	T3/ physical page number

;SWAP IN PAGE TABLE,  PSB OR XB
;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. Swap it in

;Page is still in core. Retrieve it from the replaceable queue if necessary.

	HRRZ 2,3
	LOAD 2,CSTAGE,+2	;GET PAGE STATE CODE
	CAIE T2,PSRIP		;READ IN PROGRESS?
	CALL APSKED		;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

;Page is not in core. Swap it in.

SWP01:	CALL SWPIN
	HLRZ 3,1

;Page is in core now. Lock it and return

SWP02:	MOVSI 2,(PLKV)
	HRRZS 3
	ADDM 2,@CST1X+3		;LOCK PAGE
	RET

;Here if swapping in an XB from the disk. Need to do XB computation
	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

;SPECIAL ROUTINE TO SWAP IN AN SPTN AND LEAVE IT UNLOCKED.

SWPIN4::NOSKED			;MUST BE NOSKED
	CALL SWPIN0		;SWAP IN PAGE AND WAIT
	CALL ULKP3		;UNLOCK THE PAGE
	OKSKED
	RET			;DONE
;SWAP IN AND WAIT FOR COMPLETION
;SWPINW - SWAP INTO PAGE FROM RPLQ
;SWPINQ - SWAP INTO PAGE FROM SPMQ, PAGE # IN 3

;ACCEPTS:
;	T1/ PTN,,PN OR 0,,SPTN
;	T3/ CORE PAGE NUMBER INTO WHICH TO SWAP (SWPINQ ONLY)

;	CALL SWPINW
;		OR
;	CALL SWPINQ

;RETURNS +1: ALWAYS,
;	T1/ CORE PAGE NUMBER

;If T3 contains page number, page must be on special memory queue
;If T3 contains -1, page is selected from replaceable queue

SWPINW::SETO 3,			;REQUEST PAGE FROM REPLACEABLE QUEUE
SWPINQ:	PUSH P,FX
	MOVE FX,FORKX
	AOS USWPCT		;COUNT SWAPS
	TLNE 1,-1		;PT?
	JRST SWPIW2		;YES

;Here if caller provided (0,,SPTN). Swap the page in

	CALL SWPIQ1		;SWAPIN AND WAIT FOR COMPLETION

;Common exit. Swapin has begun; wait for it to finish, and return.

SWPIW1:	CALL PGIWT
	HLRZ 1,1		;RESTORE PAGE NO TO R.H.
	POP P,FX
	RET

;Here if caller provided (PTN,,PN). Make sure page table is in core and
;lock it

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 AGECKN		;FIX PAGE
	MOVSI 3,(PLKV)
	ADDM 3,@CST1X+1		;SO IT DOESN'T SNEAK AWAY

;Here when page table is accessible. Swap in the requested page and unlock
;the page table
;	t1/ core page of page table
;	0(P)/ original T1
;	-1(P)/ original T3

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
	CALL ULKP1		;UNLOCK IT
	POP P,1
	POP P,3			;RESTORE PHY PAGE #
	JRST SWPIW1
;SWPINW continued

;Page table is not in core. Swap it in and lock it
;	T1/ PTN

SWPIW3:	NOSKED
	CALL SWPIN		;SWAP IN THE PT
	OKSKED
	HLRZ 2,1
	MOVSI 3,(PLKV)
	ADDM 3,@CST1X+2		;LOCK IT
	PDISMS			;WAIT TO FINISH
	HLRZ 1,1		;GET CORE PAGE NO. OF PAGE TABLE
	CALL AGECKN
	JRST SWPIW4		;NOW GO GET THE PAGE
;SWPIQ1 - SWAP IN PAGE

;ACCEPTS:
;	T1/ PTN,,PN OR 0,,SPTN
;	T3/ PAGE NUMBER INTO WHICH TO SWAP, OR -1 FOR FREE CHOICE

;	CALL SWPIQ1

;RETURNS +1: ALWAYS
;	T1/ (CORE PAGE NUMBER,,SCHEDULER TEST)

;If T3 contains page number, page must be on special memory queue (SPMQ)
;If T3 contains -1, same as call to SWPIN. Page is taken from replaceable queue

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

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

;SWPIN - Swap in a page using replaceable queue

;ACCEPTS:
;	T1/ PTN,,PN OR 0,,SPTN

;	CALL SWPIN

;RETURNS +1: ALWAYS
;	T1/ (CORE PAGE NUMBER,,SCHEDULER TEST)

SWPIN::	MOVE T3,NRPLQ		;NUMBER OF REPLACABLE PAGES
	JUMPE T3,SWPQT		;GO WAIT IF NONE
	PUSH P,5
	PUSH P,6

;Decide which queue to use.

	TLNE T1,-1		;FROM SPT?
	JRST SWPIC1		;NO, USE SRPLQ
	MOVE T3,SPT(T1)		;YES, CHECK ADDRESS
	TXNE T3,DSKAB		;FROM DISK?
	SKIPA T3,[DRPLQO]	;YES, USE DRPLQ
SWPIC1:	MOVEI T3,SRPLQO		;USE SRPLQ
	HRRZ T4,@CST3X+T3	;GET PAGE FROM HEAD OF SELECTED RPLQ
	CAMN T3,T4		;EMPTY?
	XORI T3,SRPLQO^!DRPLQO	;YES, USE ALTERNATE RPLQ

;Unchain a page from the chosen queue

	HRRZ T3,@CST3X+T3	;NOW REALLY GET THE PAGE
	SOS NRPLQ
	PIOFF
	MOVE T4,@CST3X+T3
	HRRZ 6,T4
	HLLM T4,@CST3X+6
	HLRZ 6,T4
	HRRM T4,@CST3X+6
	PION
	;..
	;..

;Page has been unchained from appropriate queue. Set CST values
;	T3/ core page number
;	T1/ Ident

SWPIQ3:
   REPEAT 0,<			;This now handled by DDMP code
	CAIL T1,NOFN		;SWAPPNG IN AN OFN?
	IFSKP.
	 LOAD T4,STGADR,SPT(T1) ;GET ADDRESS
	 TMNE SPTCDO,(T1)	;ALREADY ACTIVE?
	 TXNN T4,DSKAB		;YES. FROM DISK?
	 ANSKP.
	  SETONE SPTSFD,(T1)	;YES. NEED XSUM STUFF THEN (in AGESN)
	ENDIF.
   >	;REPEAT 0
	SETZRO CSTAGE,+3	;CLEAR AGE CODE
	SETZRO CORMB,@CST0X+3	;CLEAR PUR, MODIFIED BIT
;   IFN CFSCOD,<
	TLNN T1,-1		;PTN.PN OR SPTN?
	SKIPA T4,T1		;GET SPT INDEX
	HLRZ T4,T1		; ""
	CAIL T4,NOFN		;IS THIS AN OFN?
	HLRZ T4,SPTH(T4)	;NO. POSSIBLY THIS IS
	DO.			; REALLY, THIS IS A "BEGIN"
	 CAIL T1,NOFN		;Is this the OFN itself?
	 SKIPN T4		;No. Is it private then?
	 IFSKP.			;If a file page, but not the OFN
	  LOAD T4,SPTST,(T4)	;YES. GET ITS STATE
	  CAIE T4,.SPSWR	;MAY WE WRITE IT?
	  IFNSK.		;IF NOT
	   SETZRO CSWRB,+T3	;NO WRITE ACCESS HERE
	   EXIT.		;AND DONE
	  ENDIF.
	 ENDIF.
	 SETONE CSWRB,+T3	;IF HERE, WE HAVE WRITE ACCESS. OFNs come here
	ENDDO.
;   >	;IFN CFSCOD
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<SETONE CSWRB,+T3> ;SET WRITE BIT ALWAYS
   >				;END REPEAT 0
	SETZM @CST3X+T3
	CALL DEPG		;RESET PREVIOUS OWNERSHIP
	TLNE T1,-1		;NEW PAGE FROM PT OR SPT?
	JRST SWPI3		;PT

;Caller provided (0,,SPTN). Make SPT slot point to this new page and
;save the old SPT entry

	MOVE T4,SPT(T1)		;SPT, GET ADDRESS
	TLNN T4,(NCORTM)
	BUG.(HLT,SPTPIC,PAGEM,SOFT,<SWPIN - SPT page already in core>,,<

Cause:	A routine has been called to swap a page into core. The id for
	the page indicates that it is a page table. The BUGHLT occurred 
	because the SPT entry for that page table already contains a core 
	address.
>)
	STOR T3,STGADR,SPT(T1)	;STORE NEW (CORE) ADDRESS

;Here when SPT or page table points to the new page. Store previous pointer
;from SPT or page table into CST as backup for this page.
;Now to get some data into this page. If previous entry was drum or disk,
;go copy the data into core.

SWPI4:	ANDX T4,STGADM		;EXTRACT ADDRESS
	MOVEM T4,@CST1X+T3	;STORE BACKUP ADDRESS
	MOVEM T1,@CST2X+T3	;STORE LOCATION OF OWNING PT
	TLNE T4,(DSKAB+DRMAB)	;BACKUP ADDRESS ASSIGNED?
	JRST SWPI5		;YES, GO READ IN PAGE

;Page was preiviously unassigned. Either zero the page or copy data from
;CPYPGA into it. The latter occurs after WCPY has mapped CPYPGA into the
;source page.

	MOVEI T1,0(T3)
	CALL SETSP0		;MAP PAGE INTO CSWPG
	MOVX T1,PSASM		;SET LEGAL AGE FOR LOCAL REF
	IORM T1,@CST0X+T3
	SETZM CSWPGA
	MOVE T1,[CSWPGA,,CSWPGA+1]
	TXNE T4,UAACB-UAAB	;'COPY-REQUEST' PTR?
	MOVE T1,[XWD CPYPGA,CSWPGA] ;YES, COPY FROM CPYPG
	BLT T1,CSWPGA+777
	CALL RELSPG

;Set values in the CST. Indicate page has been modified.

	MOVX T1,PSRDN		;SET TO READ COMPLETED
	STOR T1,CSTAGE,+3	; ...
	MOVX T1,CORMB		;AND SET MODIFIED BIT
	IORM T1,@CST0X+3		; ...
	STOR FX,CFXRD,+T3	;NOTE FORK INDEX
	MOVSI T1,0(T3)		;RETURN PAGE NUMBER
	HRRI T1,SWPRT		;RETURN APPROPRIATE SCHED TEST

;Common exit. T1 has been set up for scheduler test to wait for completion.
;In some cases, completion will occur immediately.

SWPIX:	POP P,6
	POP P,5
	RET
;Core page has been selected. Caller provided PTN,,PN. Fix map to point
;to the new core page, and save the old map entry.

SWPI3:	HLRZ 6,1		;GET OWNING PT OFN
	CALL SETSP6		;MAP PT
	MOVSI 4,(PLKV)
	ADDM 4,@CST1X+6		;INCREMENT LOCK COUNT
	HRRZ 6,1
	MOVE 4,CSWPGA(6)
	TLNN 4,(NCORTM)
	BUG.(HLT,PTAIC,PAGEM,SOFT,<SWPIN - PT page already in core>,,<

Cause:	A routine has been called to swap a page into core. The id for
	the page indicates that it is a data page. The BUGHLT
	occurred because the entry in its page table contains a core
	address.
>)
	STOR 3,STGADR,CSWPGA(6)	;STORE NEW (CORE) ADDRESS
	CALL RELSPG
	JRST SWPI4

;Here if no pages on the replaceable queue. Wait.

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)

;Here if original map entry had an address on drum or disk. Read that data
;into the core page
;	T3/ new core page
;	T4/ old mapy entry

SWPI5:	MOVEI 1,0(3)
	MOVX 2,PSRIP
	STOR 2,CSTAGE,+T1	;SET STATE TO READ IN PROGRESS
	STOR FX,CFXRD,+T1	;REMEMBER INITIATING FORK
	TLNE 4,(DSKAB)		;DISK?
	JRST SWPIK		;YES
	TLNN 4,(DRMAB)		;DRUM?
	BUG.(HLT,ILSWPA,PAGEM,SOFT,<SWPIN - Illegal swap address>,,<

Cause:	A routine has been called to swap a page into core. The backup
	address for the page is of an illegal format.
>)

;Read in from drum. Set up (core page,,scheduler test) to wait for read to
;complete

	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
;Here when original entry contained disk address. read data from disk unless
;it's a new page. In that case, zero it and cause immediate completion.

SWPIK:	TLNE 4,(DSKNB)		;NEWLY ASSIGNED PAGE?
	JRST [	CALL SWPZPG	;YES, ZERO IT
;		MOVSI 2,(DSKNB)
;		ANDCAM 2,@CST1X+1
		MOVX 2,PSRDN	;SET CODE TO READ COMPLETED
		STOR 2,CSTAGE,+T1
		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
;ACCEPTS:
;	T3/ CORE PAGE

;	CALL DEPGS

;RETURNS +1: ALWAYS

;Makes owning page table or SPT point to the backup address for this core
;page.

DEPGS:	SAVEAC <5,6>		;THIS ENTRY PRESERVES ACS PROPERLY
DEPG::	MOVE 4,@CST2X+3		;GET LOCATION OF PT OWNING OLD CONTENTS
	JUMPE 4,R		;0 => WAS NONE
	MOVE 5,@CST1X+3		;GET BACKUP ADDRESS
	TLNE 4,-1		;PT OR SPT
	JRST SWPI1		;PT
	STOR 5,STGADR,SPT(4)	;SPT, RESTORE BACKUP ADDRESS
	RET

;Fix owning page talbe, and decrement its lock count.

SWPI1:	HLRZ 6,4
	CALL SETSP6		;MAP PT
	CALL ULKP6		;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 @CST2X+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,@CST2X+T1	;GET OWNING PT
	JUMPE T2,DASPGX		;NONE - NOTHING TO DO
	SETZM @CST2X+T1		;DELETE BACK POINTER
	MOVE T3,@CST1X+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,@CST0X+T1	;SAVE CURRENT CST
	SETOM @CST0X+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,@CST0X+T1		;RESTORE CST
	CALL UNMRCA		;RELEASE MAPPING
	CALL ULKP1		;DECREMENT LOCK COUNT
	POP P,T1		;RESTORE ACS
	JRST DASPGX		;DONE
;SCHEDULER TEST FOR PSB AND PT READ COMPLETED


SWPINT::MOVE 3,4		;SAVE RETURN
	LOAD 1,FKPSB		;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
   IFN EXTJSB,<
	LOAD T1,FKJPT		;Check extended JSB
	MOVE 1,SPT(1)
	JSP 4,SWPRT
	 JRST 0(3)
	CALL AGESN
   >
	LOAD 1,FKUPT		;PT
	MOVE 1,SPT(1)
	JSP 4,SWPRT		;PT READY?
	 JRST 0(3)		;NO
	CALL AGESN
	LOAD T1,FKPS2		;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 T2,CSTAGE,+T2	;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::EA.ENT			;RUN IN SECTION 1
	MOVX 2,SWPERR
	TDNE 2,@CST3X+1		;SWAP ERROR IN PAGE?
	JRST SWPER1		;YES, GO DIAGNOSE IT
SWPERX:	MOVSI 2,(DWRBIT)	;WRITE BIT
	TDNE 2,@CST3X+1		;WAS WRITE?
	JRST SWPD1		;YES
	SKIPE @CST2X+1		;Has the page been deleted already?
	IFSKP.			;Yes
   IFN DEBUG,<
	  BUG.(CHK,SWDDEL,PAGEM,SOFT,<Swap read complete on a page already deleted>,<<T1,PAGE>>,<

Cause: 	There was a swap read complete but the page home map location in CST2  
	has been deleted.  This happens when the page is deleted.  The interrupt
	is simply ignored since the page does not exist anymore.

Data:	PAGE - page number

>)
>	  			;End of IFN DEBUG
	  RET			;Return and ignore interrupt
	ENDIF.
	BLOCK.
	  SAVEAC <FX>		;SIGNAL SKED
	  LOAD FX,CFXRD,+T1	;FORK WHICH IS PRESUMABLY WAITING
	  CALLRET APSKED
	ENDBK.
	MOVX 2,PSRDN
	STOR T2,CSTAGE,+T1
	RET

SWPD1:	ANDCAM 2,@CST3X+1	;CLEAR WRITE BIT
	LOAD T2,CSTAGE,+T1	;GET TRAP CODE
	CAIE 2,PSWIP		;STILL WRITE IN PROGRESS?
	JRST SWPD2		;NO
	SOS IOIP		;YES, NOTE COMPLETION
	BLOCK.
	  SAVEAC <FX>		;SIGNAL SKED
	  LOAD FX,CFXRD,+T1	;FORK WHICH IS PRESUMABLY WAITING
	  CALLRET APSKED
	ENDBK.
SWPD2:	SKIPN @CST2X+1		;PAGE DELETED?
	JRST [	MOVEI 2,(1)	;IT WAS DELETED, PUT ON DELETED QUEUE
		EXCH 2,DELPGQ
		HRRZ 3,DELPGQ
		HRRM 2,@CST3X+3
		MOVEI 2,PSDEL	;SET PAGE STATE TO DELETED
		STOR 2,CSTAGE,+T1
		RET]
	MOVX T3,SWPERR
	TDNE T3,@CST3X+T1	;ERROR ON WRITE?
	JRST [	ANDCAM T3,@CST3X+T1 ;YES, CLEAR IT
		MOVX T3,CORMB
		IORM T3,@CST0X+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,@CST1X+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,@CST3X+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,@CST2X+A		;GET OWNING SPTN
	JUMPN B,SWPER3		;JUMP IF IN PT
	SKIPE @CST2X+1		;Has the page been deleted already?
	IFSKP.			;Yes
   IFN DEBUG,<
	  BUG.(CHK,SWEDEL,PAGEM,SOFT,<Swap error on a page already deleted>,<<T1,PAGE>>,<

Cause: 	There was a swap read error but the page home map location in CST2 has 
	been deleted.  This happens when the page is deleted.  The interrupt
	is simply ignored since the page does not exist anymore.

Data:	PAGE - page number

>)
>	  			;End of IFN DEBUG
	  RET			;Return and ignore interrupt
	ENDIF.
	HRRZ B,@CST2X+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,@CST2X+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

SWPEX2:	BUG.(CHK,SWPIBE,PAGEM,HARD,<Swap error in index block>,,<

Cause:	A hardware error occurred while the monitor was reading or
	writing an index block either from the file space or
	the swapping area. Future attempts to read this block
	will generate an error. Future attempts to write it may
	produce the same BUGCHK. The page will be marked in the BAT
	blocks.

>)
	JRST SWPERX		;SHOULD CONTINUE OK

SWPEX3:	BUG.(HLT,SWPMNE,PAGEM,HARD,<Swap error in swappable monitor>,,<

Cause:	A hardware error occurred when the monitor was reading a
	page of the swappable monitor from the swapping space.
	A SYSERR entry will be created when the monitor is rebooted,
	but the BAT blocks will not be marked.
>)

SWPEX4:	AOS ERRSWP
	BUG.(CHK,SWPPSB,PAGEM,HARD,<Swap error in PSB page>,,<

Cause:	A hardware error occurred when the monitor was reading or writing
	a page in a process's per-process area to or from the swapping space.
	The monitor will continue to run in an attempt to update the BAT
	blocks, but will crash with a SWPXXX bughlt as soon as the disk has
	been updated.  If the monitor is unable to update the disk (in the case
	of the page having the error is needed to update the bat blocks), the
	system will stop with a J0NRUN bughlt, and the flag indicating that
	a serious swap error exists will be set.
>)
	RET

SWPEX5:	BUG.(CHK,SWPJSB,PAGEM,HARD,<Swap error in JSB page>,,<

Cause:	A hardware error occurred while the monitor was reading or
	writing a page in a process's per-job area in the swapping
	space. Future attempts to read this page
	will generate an error. Future attempts to write it may
	produce the same BUGCHK. The page will be marked in the BAT
	blocks.
>)
	JRST SWPERX		;TRY TO CONTINUE

SWPEX6:	AOS ERRSWP
	BUG.(CHK,SWPPTP,PAGEM,HARD,<Swap error in unknown PT page>,,<

Cause:	A hardware error occurred when the monitor was reading or writing
	a page from the file system or swapping space. The monitor is
	unable to identify the owning page table.
	The monitor will continue to run in an attempt to update the BAT
	blocks, but will crash with a SWPXXX bughlt as soon as the disk has
	been updated.  If the monitor is unable to update the disk (in case
	the page having the error is needed to update the bat blocks), the
	system will stop with a J0NRUN bughlt, and the flag indicating that
	a serious swap error exists will be set.
>)
	RET

SWPEX7:	AOS ERRSWP
	BUG.(CHK,SWPPT,PAGEM,HARD,<Swap error in unknown PT>,,<

Cause:	A hardware error occurred when the monitor was reading or writing
	a page table in the swapping space. The monitor is unable to
	identify the page table.
	The monitor will continue to run in an attempt to update the BAT
	blocks, but will crash with a SWPXXX bughlt as soon as the disk has
	been updated.  If the monitor is unable to update the disk (in the case
	of the page having the error is needed to update the bat blocks), the
	system will stop with a J0NRUN bughlt, and the flag indicating that
	a serious swap error exists will be set.
>)
	RET

SWPEX8:	AOS ERRSWP
	BUG.(CHK,SWPUPT,PAGEM,HARD,<Swap error in UPT, or PSB>,,<

Cause:	A hardware error occurred when the monitor was reading or
	writing a special page (PSB, JSB or user page table) in
	the swapping space.
	The monitor will continue to run in an attempt to update the BAT
	blocks, but will crash with a SWPXXX bughlt as soon as the disk has
	been updated.  If the monitor is unable to update the disk (in case
	the page having the error is needed to update the bat blocks), the
	system will stop with a J0NRUN bughlt, and the flag indicating that
	a serious swap error exists will be set.
>)
	RET
;PAGE UNLOCKING ROUTINES CALL ULKPn WHERE n IS THE AC NUMBER CONTAINING THE 
; CORE PAGE TO UNLOCK

ULKP6:	SAVEAC <T1,T2,Q2>
	MOVE T1,Q2
	JRST ULKP0
ULKP5:	SAVEAC <T1,T2,Q1>
	MOVE T1,Q1
	JRST ULKP0
ULKP4:	SAVEAC <T1,T2,T4>
	MOVE T1,T4
	JRST ULKP0
ULKP3::	SAVEAC <T1,T2,T3>
	MOVE T1,T3
	JRST ULKP0
ULKP2::	SAVEAC <T1,T2>
	SKIPA T1,T2
ULKP1::	SAVEAC <T1,T2>		;[7247] Make ULKP1 global - called from OC.UNC
ULKP0:	MOVX T2,-PLKV
	ADDB T2,@CST1X+1
	SKIPGE T2
	BUG.(HLT,PLKMOD,PAGEM,SOFT,<Page lock overly decremented>,,<

Cause:	The monitor decremented the lock count of a page past zero.
	This indicates a software problem.
>)
	RET
;PUT PAGE ON HEAD 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::	MOVE T2,@CST1X+T1	;CHECK BACKUP ADR
	TXNE T2,DSKAB		;DISK?
	JRST ONRQD		;YES, PUT PAGE ON TAIL OF DRPLQ
	SKIPE T2,@CST2X+T1	;NO. GET OWNER I.D.
	CAIL T2,NOFN		;YES. AN XB?
	SKIPA			;NO.
	JRST ONRQD		;YES. PUT ON TAIL OF DRPLQ
	MOVEI 2,(1)		;MAKE PTR
	PIOFF			;NO DSK OR DRM INTERRUPTS WHILE DIDDLING PTRS
	LOAD 3,CSTPST,+T1	;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,@SRPLQ		;NO, MAKE PTR FOR NEW PAGE
	HLL 4,@CST3X+3		; ..
	HRLM 2,@CST3X+3		;FIX BACK PTR OF OLD TOP PAGE
	HLL 3,4
	MOVEM 3,@CST3X+2	;SET PTRS FOR NEW TOP PAGE
	HRRM 2,@SRPLQ		;SET NEW PTR TO TOP PAGE IN RPLQ
	PION
	JRST ONRQ1		;GO FINISH UP

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

ONRQ::	MOVE T2,@CST1X+T1	;CHECK BACKUP ADR
	TXNN T2,DSKAB		;DISK?
	JRST [	SKIPE T2,@CST2X+T1 ;NO. GET OWNER I.D.
		CAIL T2,NOFN	;YES. AN XB?
		JRST ONRQS	;NO. PUT ON SRPLQ
		JRST .+1]	;YES. PUT ON DRPLQ
ONRQD:	JRST ONRQS		;ALWAYS USE SRPLQ

;************* DRPLQ NOT PRESENTLY USED ***********

	MOVEI 2,(1)		;CONSTRUCT ABSOLUTE PTR FOR PAGE
	PIOFF			;NO INTS WHILE DIDDLING LIST
	LOAD 3,CSTPST,+T1	;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,@DRPLQ		;NO, PUT PAGE ON 'IN' END OF QUEUE
	HRL 4,@CST3X+3		; BECAUSE PAGES ARE TAKEN FROM 'OUT'
	HRRM 2,@CST3X+3		; END OF QUEUE.
	HLL 3,4
	MOVSM 3,@CST3X+2
	HRLM 2,@DRPLQ
	PION
ONRQ1:	AOS NRPLQ
	MOVEI 2,PSRPQ		;SET PAGE STATE
	STOR 2,CSTAGE,+T1
	RET

ONRQS:	MOVEI 2,(1)		;CONSTRUCT ABSOLUTE PTR FOR PAGE
	PIOFF			;NO INTS WHILE DIDDLING LIST
	LOAD 3,CSTPST,+T1	;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,@SRPLQ		;NO, PUT PAGE ON 'IN' END OF QUEUE
	HRL 4,@CST3X+3		; BECAUSE PAGES ARE TAKEN FROM 'OUT'
	HRRM 2,@CST3X+3		; END OF QUEUE.
	HLL 3,4
	MOVSM 3,@CST3X+2
	HRLM 2,@SRPLQ
	PION
	JRST ONRQ1		;FINISH UP
	TNXEND
	END