Trailing-Edge
-
PDP-10 Archives
-
BB-M081Z-SM
-
monitor-sources/fork.mac
There are 53 other files named fork.mac in the archive. Click here to see a list.
; Edit= 9148 to FORK.MAC on 21-Feb-90 by GSCOTT
;Update copyright date.
; Edit= 9119 to FORK.MAC on 24-Aug-89 by GSCOTT
;Implement new GETOK functions .GODSK, .GOSJP, and .GOSPR.
; Edit= 9041 to FORK.MAC on 13-Dec-88 by RASPUZZI
;Finish off some of the security features that were started at one time (like
;password expiration). Also, add new features to help a system manager secure
;the system.
; Edit= 9017 to FORK.MAC on 8-Nov-88 by LOMARTIRE
;Merge Production changes to BUG text
; Edit= 8937 to FORK.MAC on 23-Aug-88 by LOMARTIRE
;Spell MONITR correctly in ACTION field of BUGs!
; Edit= 8910 to FORK.MAC on 17-Aug-88 by LOMARTIRE
;Improve BUG. documentation
; UPD ID= 8519, RIP:<7.MONITOR>FORK.MAC.5, 9-Feb-88 15:36:11 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 291, RIP:<7.MONITOR>FORK.MAC.4, 12-Nov-87 15:20:13 by WADDINGTON
;More of TCO 7.1120 - Move call to LATRST to after the CLZFF
; UPD ID= 275, RIP:<7.MONITOR>FORK.MAC.3, 6-Nov-87 23:16:09 by WADDINGTON
;TCO 7.1120 Call LATRST to clean up reverse-lat connections in KSELF:
; *** Edit 7456 to FORK.MAC by GSCOTT on 23-Apr-87, for SPR #19597
; Write session records properly when a job is attached, detached, or its
; session remark is changed. Also make sure session start time is correct.
; *** Edit 7433 to FORK.MAC by MCCOLLUM on 2-Apr-87, for SPR #21502
; In SETJSB, map FPG2 to the second page of the other job's JSB.
; *** Edit 7421 to FORK.MAC by PUCHRIK on 9-Mar-87, for SPR #21262
; Remove routines DGET and FFUSEC. Cleanup GETPA1, GETDMS, and GETSEG.
; Fix situation where DSK: defined to be a program and that program gets
; loaded instead of XRMS.EXE.
; *** Edit 7254 to FORK.MAC by MRASPUZZI on 9-Mar-86, for SPR #20965
; Prevent GLFNF bughlts by reinstalling edit 1868
; Edit 7173 to FORK.MAC by PALMIERI on 23-Oct-85 (TCO 6.1.1542)
; Move modules NIUSR and LLMOP to an extended section. This required the
; changing of some global routine names in LLMOP; Therefor the changes to
; MEXEC, JSYSA, and FORK.
; Edit 7146 to FORK.MAC by TBOYLE on 10-Sep-85, for SPR #19847 (TCO 6-1-1537)
; Fix 30-bit argument address problems.
; Edit 7109 to FORK.MAC by WAGNER on 26-Jul-85, for SPR #17842 (TCO 6-1-1498)
; Fix GFRKH% to not TAKE .FHSUP IN AC2, but will take in AC 1
;TCO 6.1.1498 Change GFRKH% to not take .FHSUP in AC2, but will in AC1
; UPD ID= 2299, SNARK:<6.1.MONITOR>FORK.MAC.151, 17-Jul-85 11:17:19 by LEACHE
;TCO 6.1.1478 Reinitialize datablock size in argblock of recursive PDVOP
; UPD ID= 2076, SNARK:<6.1.MONITOR>FORK.MAC.150, 3-Jun-85 14:36:21 by MCCOLLUM
;TCO 6.1.1406 - Update copyright notice.
; UPD ID= 2036, SNARK:<6.1.MONITOR>FORK.MAC.149, 31-May-85 10:06:30 by MOSER
;TCO 6.1.1411 - FIX UP FLKTIM FOREVER
; UPD ID= 1986, SNARK:<6.1.MONITOR>FORK.MAC.148, 17-May-85 15:13:08 by MCCOLLUM
;TCO 6.1.1397 - Kill newly created fork after MSETPT error in CFK4
; UPD ID= 1878, SNARK:<6.1.MONITOR>FORK.MAC.147, 4-May-85 12:29:06 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1751, SNARK:<6.1.MONITOR>FORK.MAC.146, 12-Apr-85 15:45:37 by TBOYLE
;TCO 6.1.1318 - fix handling of handle counts by SPLFK% with suicide option.
; UPD ID= 1729, SNARK:<6.1.MONITOR>FORK.MAC.145, 8-Apr-85 14:35:26 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1687, SNARK:<6.1.MONITOR>FORK.MAC.144, 26-Mar-85 15:28:58 by LOMARTIRE
;TCO 6.1.1288 - Make the RT%DIM bit work as documented
; UPD ID= 1684, SNARK:<6.1.MONITOR>FORK.MAC.143, 25-Mar-85 15:08:28 by MCCOLLUM
;TCO 6.1.1287 - Change an ITERR to a RETERR in .CFORK.
; UPD ID= 1587, SNARK:<6.1.MONITOR>FORK.MAC.142, 5-Mar-85 10:53:24 by WAGNER
;TCO 6.1.1229 - *PERFORMANCE* Modify SETJSB to check if ourselves
; UPD ID= 1481, SNARK:<6.1.MONITOR>FORK.MAC.141, 5-Feb-85 17:18:33 by GLINDELL
; TCO 6.1.1174 - EPCAP% jsys and ACJ
; UPD ID= 1426, SNARK:<6.1.MONITOR>FORK.MAC.140, 29-Jan-85 15:40:23 by MCCOLLUM
;TCO 6.1.1163 - Do not clear SYSFK entry until after CLNZSC succeeds in KSELF
; UPD ID= 1182, SNARK:<6.1.MONITOR>FORK.MAC.139, 11-Dec-84 14:12:08 by LEACHE
;Change EHLJSB conditional to EXTJSB
; UPD ID= 1051, SNARK:<6.1.MONITOR>FORK.MAC.138, 13-Nov-84 01:04:08 by GROSSMAN
;TCO 6.1.1045 - Add NI% JSYS reset code to KSELF.
; UPD ID= 5020, SNARK:<6.MONITOR>FORK.MAC.137, 26-Oct-84 13:58:23 by LEACHE
;Add code (under EHLJSB conditional) for extended JSB
; UPD ID= 4807, SNARK:<6.MONITOR>FORK.MAC.136, 17-Sep-84 10:00:42 by PURRETTA
;Update copyright notice
; UPD ID= 4741, SNARK:<6.MONITOR>FORK.MAC.135, 24-Aug-84 09:43:02 by PAETZOLD
;TCO 6.2193 - Prevent IDFOD2 BUGCHKs from long form RFSTS% at RFSLN2.
; UPD ID= 4639, SNARK:<6.MONITOR>FORK.MAC.134, 31-Jul-84 14:34:34 by GLINDELL
;More TCO 6.2153 - fix MOVEI/MOVX
; UPD ID= 4636, SNARK:<6.MONITOR>FORK.MAC.133, 31-Jul-84 12:28:36 by TBOYLE
;COMMENTS FOR WFORK% AND USE OF FKSPL.
; UPD ID= 4631, SNARK:<6.MONITOR>FORK.MAC.132, 30-Jul-84 13:55:31 by GLINDELL
;Tco 6.2153 - fix section 0/section local confusion in PDVOP% jsys
; UPD ID= 4554, SNARK:<6.MONITOR>FORK.MAC.131, 18-Jul-84 10:52:30 by MOSER
;TCO 6.2125 - SYNCRONOUS KFORK
; UPD ID= 4453, SNARK:<6.MONITOR>FORK.MAC.130, 12-Jul-84 10:35:49 by CDUNN
;More TCO 6.1127 Make KFORK% call SCSKIL in SCSJSY to delete any connects
;the fork may have had.
; UPD ID= 4440, SNARK:<6.MONITOR>FORK.MAC.129, 5-Jul-84 16:51:56 by GROSSMAN
;TCO 6.2118 - Fix UTFRK% function UT%TRP so that forks don't get started at
; PC of ITRAP in user mode if their PC was changed via SFORK%.
; UPD ID= 4389, SNARK:<6.MONITOR>FORK.MAC.128, 26-Jun-84 19:03:26 by PAETZOLD
;TCO 6.2110 - Use correct index register when testing FKEFR in TFRKSR.
; UPD ID= 4348, SNARK:<6.MONITOR>FORK.MAC.127, 15-Jun-84 16:03:18 by TBOYLE
;TCO 6.2090 - Replace TCO 6.2075 - Do not allow indirection or indexing
; UPD ID= 4325, SNARK:<6.MONITOR>FORK.MAC.126, 12-Jun-84 13:28:35 by MOSER
;TCO 6.2086 - FIX SHROFN UNMAP INDEX FILE
; UPD ID= 4301, SNARK:<6.MONITOR>FORK.MAC.125, 4-Jun-84 23:01:56 by MOSER
;REFERENCE SC%CTC SYMBOLICLY
; UPD ID= 4273, SNARK:<6.MONITOR>FORK.MAC.124, 30-May-84 21:21:58 by MOSER
;TCO 6.2059 ADD SETVGN TO RESTORE FORK VIRGINITY
; UPD ID= 4263, SNARK:<6.MONITOR>FORK.MAC.123, 30-May-84 17:59:40 by TBOYLE
;TCO 6.2075 - Make pointers to .POADR in PDVs work the way they should.
; UPD ID= 4225, SNARK:<6.MONITOR>FORK.MAC.122, 16-May-84 15:42:11 by TBOYLE
;More TCO 6.2056 - unblk1 code nosked, be sure fork was blocked, see
; if on TRMLST rather than checking if TRMTST, remove KSELFJ, keep
; whole code to the killing with fork lock locked.
; UPD ID= 4223, SNARK:<6.MONITOR>FORK.MAC.121, 15-May-84 16:26:38 by MOSER
;TCO 6.2061 - PREVENT NOSKED PAGE FAULT IN SFORK
; UPD ID= 4203, SNARK:<6.MONITOR>FORK.MAC.120, 9-May-84 17:02:32 by TBOYLE
;More TCO 6.2056 - Change the value of FLKOWN during the NOSKED splice.
; UPD ID= 4186, SNARK:<6.MONITOR>FORK.MAC.119, 8-May-84 15:40:15 by TBOYLE
;More TCO 6.2056 - Make KSELFJ also call DASFKH to free fork handles.
; UPD ID= 4150, SNARK:<6.MONITOR>FORK.MAC.118, 30-Apr-84 12:26:01 by TBOYLE
;TCO 6.2056 Use FKSPL bit in TRMTST in case of race condition.
; UPD ID= 4133, SNARK:<6.MONITOR>FORK.MAC.117, 25-Apr-84 11:12:15 by LOMARTIRE
;TCO 6.2046 - Add GSWFRK to return system wide fork number given handle
; UPD ID= 4046, SNARK:<6.MONITOR>FORK.MAC.116, 4-Apr-84 16:27:12 by TBOYLE
;More TCO 6.2017 For non WHL: don't use SETJFK on .FHSUP, code explicitly.
; UPD ID= 4015, SNARK:<6.MONITOR>FORK.MAC.115, 31-Mar-84 16:14:24 by PAETZOLD
;TCO 6.2019 - Use ADJSPs
; UPD ID= 3997, SNARK:<6.MONITOR>FORK.MAC.114, 28-Mar-84 15:19:03 by TBOYLE
;More TCO 6.2017 Add comments to SPLFK code in .WFORK, KSELF, .SPLFK
; UPD ID= 3971, SNARK:<6.MONITOR>FORK.MAC.112, 24-Mar-84 23:11:07 by TBOYLE
;More TCO 6.2017 Fix a bug in .wfork on restart, and fix unblk1 at splfk4
; UPD ID= 3965, SNARK:<6.MONITOR>FORK.MAC.111, 23-Mar-84 18:56:54 by TBOYLE
;More TCO 6.2017 Change KFORK to use subroutine to remove fork. New KSELFJ
; routine will perform suicidal death. End of new SPLFK will disable
; interrupts and enter KSELFJ.
; UPD ID= 3920, SNARK:<6.MONITOR>FORK.MAC.110, 13-Mar-84 17:48:23 by TBOYLE
;More TCO 6.2017 Fix error return, to goto EFRKR.
; UPD ID= 3918, SNARK:<6.MONITOR>FORK.MAC.109, 13-Mar-84 17:15:34 by TBOYLE
;More TCO 6.2017 Fix the calls to SFRKV, XSFRK%, and some bugs.
; UPD ID= 3862, SNARK:<6.MONITOR>FORK.MAC.108, 6-Mar-84 17:32:45 by TBOYLE
;More TCO 6.2017 Fix the code, and do the error recovery.
; UPD ID= 3859, SNARK:<6.MONITOR>FORK.MAC.107, 5-Mar-84 18:44:12 by TBOYLE
;More TCO 6.2017 Fix the code.
; UPD ID= 3858, SNARK:<6.MONITOR>FORK.MAC.106, 5-Mar-84 17:52:33 by TBOYLE
;More TCO 6.2017 Fix the new code.
; UPD ID= 3855, SNARK:<6.MONITOR>FORK.MAC.105, 5-Mar-84 16:51:50 by TBOYLE
;More SPLFK, TCO 6.2017, Fix the old code, subroutinize.
; UPD ID= 3854, SNARK:<6.MONITOR>FORK.MAC.104, 5-Mar-84 15:53:09 by TBOYLE
;New SPLFK% Replace self with inferior fork, start, destroy old self.
; UPD ID= 3797, SNARK:<6.MONITOR>FORK.MAC.103, 29-Feb-84 01:42:04 by TGRADY
;IMPLEMENT GLOBAL JOB NUMBERS
; IN .SJPRI, DON' COMPARE JOB NUMBER TO NJOBS...USE GL2LCL TO CONVERT IT
; UPD ID= 3631, SNARK:<6.MONITOR>FORK.MAC.102, 1-Feb-84 22:08:05 by MURPHY
;Flush refs to SYMPAG
; UPD ID= 3626, SNARK:<6.MONITOR>FORK.MAC.101, 1-Feb-84 18:56:49 by MOSER
;MORE 6.1748 - COMPARE TO LOWQ NOT MAXQ
; UPD ID= 3445, SNARK:<6.MONITOR>FORK.MAC.99, 12-Jan-84 14:19:52 by PAETZOLD
;TCO 6.1929 - Change FKJOBN to FKJBN
; UPD ID= 3341, SNARK:<6.MONITOR>FORK.MAC.98, 19-Dec-83 09:56:04 by TSANG
;TCO 6.1913 - Make .POADE ending address available
; UPD ID= 3296, SNARK:<6.MONITOR>FORK.MAC.97, 12-Dec-83 15:57:31 by LOMARTIRE
;TCO 6.1860 - Make routine CLNZSC global
; UPD ID= 3267, SNARK:<6.MONITOR>FORK.MAC.96, 6-Dec-83 17:25:20 by MOSER
;TCO 6.1828 - PREVENT HUNG JOBS - UNLOCK DEVLKK
; UPD ID= 3266, SNARK:<6.MONITOR>FORK.MAC.95, 6-Dec-83 17:06:38 by MOSER
;TCO 6.1748 - CHECK ARGS FOR SJPRI AND SPRIW
; UPD ID= 3259, SNARK:<6.MONITOR>FORK.MAC.94, 6-Dec-83 10:05:40 by MOSER
;TCO 6.1887 - PREVENT FLKINT DOING TFORK .TFRES
; UPD ID= 3115, SNARK:<6.MONITOR>FORK.MAC.93, 8-Nov-83 09:01:45 by MCINTEE
;~6.0 - Remove NSP% jsys
; UPD ID= 3054, SNARK:<6.MONITOR>FORK.MAC.92, 21-Oct-83 19:30:09 by MURPHY
;Remove init of JOBNO from .CFORK - it is done in FKSET now.
;Suppress BP$xxx breakpoint symbols.
; UPD ID= 3010, SNARK:<6.MONITOR>FORK.MAC.91, 7-Oct-83 23:25:33 by TGRADY
;TCO 6.1821 - don't use XRMS, since it breaks lots of old applications
; UPD ID= 3005, SNARK:<6.MONITOR>FORK.MAC.90, 7-Oct-83 17:56:00 by GUNN
;~6.0 Add call to LLMRSF from KSEF0 to clean up LLMOP resources on KFORK%.
; UPD ID= 2883, SNARK:<6.MONITOR>FORK.MAC.89, 9-Sep-83 10:59:38 by TBOYLE
;More TCO 6.1788 - fix GFRKS correctly.
; UPD ID= 2878, SNARK:<6.MONITOR>FORK.MAC.88, 7-Sep-83 10:48:59 by TBOYLE
;TCO 6.1788 - Correct off by one bug in GFRKS%.
; UPD ID= 2728, SNARK:<6.MONITOR>FORK.MAC.87, 22-Jul-83 14:58:34 by PAETZOLD
;TCO 6.1733 - Remove NETKFK call as NCP has gone away.
; UPD ID= 2698, SNARK:<6.MONITOR>FORK.MAC.86, 15-Jul-83 17:57:59 by TAMBURRI
;Two instruction edit to 2652 to pass correct args to GETSEG.
; UPD ID= 2661, SNARK:<6.MONITOR>FORK.MAC.85, 4-Jul-83 14:54:20 by HALL
;TCO 6.1689 - Move fork tables.
; Remove one more direct reference
; UPD ID= 2652, SNARK:<6.MONITOR>FORK.MAC.84, 1-Jul-83 15:23:28 by TAMBURRI
;TCO 6.1712 Remember and use the section number of the current PA1050
; UPD ID= 2648, SNARK:<6.MONITOR>FORK.MAC.83, 29-Jun-83 21:23:04 by MCLEAN
;REMOVE RFSTS: IN PREVIOUS EDIT IT CAUSES A MUUO SINCE RFSTS JSYS IS USED HERE
; UPD ID= 2640, SNARK:<6.MONITOR>FORK.MAC.82, 27-Jun-83 16:19:52 by CHALL
;TCO 6.1673 MRFSTS- Add special check for signal JFN
; UPD ID= 2625, SNARK:<6.MONITOR>FORK.MAC.81, 22-Jun-83 14:04:14 by HALL
;TCO 6.1689 - Move fork tables to extended section
; Reference fork tables via DEFSTRs
; UPD ID= 2455, SNARK:<6.MONITOR>FORK.MAC.80, 11-May-83 08:42:58 by MCINTEE
;Move calls to release DECnet resources (6.1) in KSELF to after the CLZFF
; UPD ID= 2375, SNARK:<6.MONITOR>FORK.MAC.79, 29-Apr-83 14:24:00 by MURPHY
;TCO 6.1635 - Use MONENV instead of MONFLG to init flag word.
; UPD ID= 2280, SNARK:<6.MONITOR>FORK.MAC.78, 16-Apr-83 19:12:41 by PAETZOLD
;TCO 6.1557 - TCP Merge - Delete old edit history - Update copyright.
; UPD ID= 2247, SNARK:<6.MONITOR>FORK.MAC.77, 12-Apr-83 13:16:55 by MCINTEE
;Remove IFNDEF FTNSPSRV
; UPD ID= 2220, SNARK:<6.MONITOR>FORK.MAC.76, 8-Apr-83 13:55:02 by TSANG
;TCO 6.1580 - Use JRST MRETN instead of JSP T2,ITRAP1
; UPD ID= 2097, SNARK:<6.MONITOR>FORK.MAC.75, 28-Mar-83 17:37:36 by MURPHY
;Minor cleanup.
; UPD ID= 2052, SNARK:<6.MONITOR>FORK.MAC.74, 21-Mar-83 18:03:26 by MURPHY
;GET RID OF OBSOLETE SEARCH PROKL
; UPD ID= 1874, SNARK:<6.MONITOR>FORK.MAC.73, 23-Feb-83 21:45:30 by MURPHY
;TCO 6.1514 - Use ITERX instead of JSP T2,ITRAP.
; UPD ID= 1869, SNARK:<6.MONITOR>FORK.MAC.72, 23-Feb-83 14:25:36 by HALL
;TCO 6.1511 - Make RESET JSYS undo SWTRP (Add CLRTRP)
; UPD ID= 1797, SNARK:<6.MONITOR>FORK.MAC.71, 14-Feb-83 14:35:03 by MCINTEE
;Still more TCO 6.1484 - remove conditional from CALL EVRKIL
; UPD ID= 1753, SNARK:<6.MONITOR>FORK.MAC.70, 3-Feb-83 13:15:03 by MCINTEE
;More TCO 6.1484 - Put CALL EVRKIL under IFN FTNSPSRV
; UPD ID= 1750, SNARK:<6.MONITOR>FORK.MAC.69, 3-Feb-83 10:32:49 by GRANT
; Previous edit should say KSELF, not .RESET
; UPD ID= 1748, SNARK:<6.MONITOR>FORK.MAC.68, 3-Feb-83 10:22:05 by GRANT
;TCO 6.1484 - In .RESET, check for DECnet event reader fork
; UPD ID= 1722, SNARK:<6.MONITOR>FORK.MAC.67, 28-Jan-83 16:01:57 by MURPHY
;More 6.1475 - Use macro for setting PCS so all CPU types work.
; UPD ID= 1696, SNARK:<6.MONITOR>FORK.MAC.66, 26-Jan-83 07:34:12 by MCINTEE
;Remove conditional from CALL NTCOFF (6.1 now has net top change int)
; UPD ID= 1689, SNARK:<6.MONITOR>FORK.MAC.65, 20-Jan-83 18:32:42 by MURPHY
;TCO 6.1475 - Fix starting PA1050 in non-0 section.
; UPD ID= 1624, SNARK:<6.MONITOR>FORK.MAC.64, 6-Jan-83 16:16:30 by CHALL
;Move call to .NSPRS to KSELF from .RESET
; UPD ID= 1568, SNARK:<6.MONITOR>FORK.MAC.63, 22-Dec-82 19:12:09 by NICHOLS
;Add DECnet-36 code under IFE FTNSPSRV
; UPD ID= 1548, SNARK:<6.MONITOR>FORK.MAC.62, 21-Dec-82 08:08:16 by MOSER
;TCO 6.1409 - REINSTALL FLKINT DON'T DISMS WHEN UNLOCKING FORK LOCK
; UPD ID= 1501, SNARK:<6.MONITOR>FORK.MAC.61, 1-Dec-82 12:15:50 by MOSER
;TCO 6.1208 - CHECK MINOR STATE IN TRMTST
; UPD ID= 1493, SNARK:<6.MONITOR>FORK.MAC.60, 30-Nov-82 15:57:41 by MOSER
;TCO 6.1133 - PREVENT HUNG JOBS WHEN JSYS TRAPPING
; UPD ID= 1468, SNARK:<6.MONITOR>FORK.MAC.59, 19-Nov-82 14:24:48 by MOSER
;MORE TCO 6.1376
; UPD ID= 1464, SNARK:<6.MONITOR>FORK.MAC.58, 18-Nov-82 13:52:17 by MOSER
;TCO 6.1376 - PREVENT FLKTIM-FLKNS
; UPD ID= 1036, SNARK:<6.MONITOR>FORK.MAC.57, 4-Aug-82 14:04:05 by WALLACE
;TCO 6.1104 - Place initialization of CTSSBK and call to CLRCTS
; under FTDYN instead of FTCTS since Known Library List is in CTS
; State Block
; UPD ID= 954, SNARK:<6.MONITOR>FORK.MAC.55, 22-Jun-82 15:34:18 by MURPHY
;TCO 5.1.1036 - Prevent confusion in GCVEC% when getting -1 PATADR.
; UPD ID= 929, SNARK:<6.MONITOR>FORK.MAC.54, 14-Jun-82 09:58:48 by HALL
;TCO 6.1156 - Don't clear ADRBRK when killing fork
; UPD ID= 891, SNARK:<6.MONITOR>FORK.MAC.53, 9-Jun-82 22:55:51 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here and put them in-line.
; UPD ID= 873, SNARK:<6.MONITOR>FORK.MAC.52, 8-Jun-82 09:44:14 by MILLER
;TCO 6.1157. Fix GJCAPS to inhibit "temporary capabilities".
; UPD ID= 872, SNARK:<6.MONITOR>FORK.MAC.51, 8-Jun-82 09:00:19 by MCINTEE
;Typo in previous edit
; UPD ID= 865, SNARK:<6.MONITOR>FORK.MAC.50, 7-Jun-82 10:52:25 by HALL
;TCO 6.1156 - Allow exec mode address break
; Decrement user mode break count at KSELF
; UPD ID= 789, SNARK:<6.MONITOR>FORK.MAC.49, 26-May-82 19:11:23 by WALLACE
;TCO 6.1105 - Add Canonical Terminal Support
; Call to CLRCTS (Clear CTS State Information) when fork is killed
; Initialize the CTS State Block (CTSSBK) to zero at fork creation
; UPD ID= 729, SNARK:<6.MONITOR>FORK.MAC.48, 11-May-82 10:47:51 by HALL
;TCO 6.1000 - Support the 2080
; SFRKV - Set monitor's AC blocks when starting fork at SFRKV1
; Set user AC blocks when forcing user mode flags (SFRKV,SFORK0)
; UPD ID= 711, SNARK:<6.MONITOR>FORK.MAC.47, 9-May-82 14:17:35 by HALL
;TCO 6.1000 - Support the 2080
; Make GETDAT and GETDMS set up data correctly for the KC
; UPD ID= 706, SNARK:<6.MONITOR>FORK.MAC.46, 9-May-82 13:01:09 by HALL
;TCO 6.1000 - Support the 2080
; Change contents of new flags word for user mode to include CAB
; (CFORK, KSELF)
; Change contents of new flags word for monitor mode to include CAB
; and PAB (KFORK, MSFRK)
; Make extended RFSTS return only the flags bits that users should see
; Make SFORK1 store full word of flags
; UPD ID= 636, SNARK:<6.MONITOR>FORK.MAC.45, 13-Apr-82 15:24:42 by MURPHY
;TCO 6.1091 - Fix SCVEC% -1.
; UPD ID= 525, SNARK:<6.MONITOR>FORK.MAC.44, 18-Mar-82 03:21:24 by PAETZOLD
;TCO 5.1761 - Fix LOKK macro in SCTSET
; UPD ID= 498, SNARK:<6.MONITOR>FORK.MAC.43, 15-Mar-82 14:41:31 by MILLER
;TCO 6.1066. ADD CALL TO INTCLR
; UPD ID= 468, SNARK:<6.MONITOR>FORK.MAC.42, 11-Mar-82 21:46:50 by PAETZOLD
;TCO 5.1751 - Zero PATLEV when zeroing PATADR in SEVC
; UPD ID= 452, SNARK:<6.MONITOR>FORK.MAC.41, 11-Mar-82 07:02:28 by HALL
;TCO 6.1000 - Support the 2080
; Add search of PROKL temporarily.. XGTPW JSYS expects to know bits
; in the page fail word.
; UPD ID= 429, SNARK:<6.MONITOR>FORK.MAC.40, 1-Mar-82 09:45:29 by MURPHY
;More 5.1697 - try for XRMS.EXE and XPAT.EXE
; UPD ID= 359, SNARK:<6.MONITOR>FORK.MAC.39, 29-Jan-82 11:39:29 by WALLACE
;TCO 5.1706 - Fix three problems with XGTPW%: 1) Properly return
; page trap address from page fail word. 2) Get OpCode from right
; half of MUUO OpCode word. 3) Fix counter so the number of words
; requested by user will be returned. Count was off by one.
;TCO 5.1703 - Initialize Previous Context Section (PCS) to section
; number of entry vector in the SFRKV% routine, SFRKV5
;TCO 5.1702 - Make .POLOC function of PDVOP% return the number of
; available PDVA's in the left half of argument block word .POCT2
; as well as the actual number of PDVA's returned in the right half
; UPD ID= 352, SNARK:<6.MONITOR>FORK.MAC.38, 26-Jan-82 18:42:29 by MURPHY
;DITTO
; UPD ID= 345, SNARK:<6.MONITOR>FORK.MAC.37, 24-Jan-82 23:49:24 by MURPHY
;TCO 5.1697 - XSSEV%, etc. Move GETPAT and GETDMS from MEXEC.MAC to here.
; UPD ID= 321, SNARK:<6.MONITOR>FORK.MAC.36, 19-Jan-82 08:05:37 by MILLER
;MORE OF THE SAME
; UPD ID= 319, SNARK:<6.MONITOR>FORK.MAC.34, 18-Jan-82 19:00:20 by MILLER
;TCO 5.1678 again. Release TTY if top fork and FRKTTY is set
; UPD ID= 318, SNARK:<6.MONITOR>FORK.MAC.33, 18-Jan-82 17:49:02 by MILLER
; UPD ID= 315, SNARK:<6.MONITOR>FORK.MAC.32, 18-Jan-82 14:49:22 by MILLER
;TCO 5.1678. Don't call TTYDAS for FRKTTY TTY when fork goes away
; Make sure TTY in SCTTY is assigned to this job
; UPD ID= 288, SNARK:<6.MONITOR>FORK.MAC.31, 9-Jan-82 19:39:07 by PAETZOLD
;TCO 5.1662 - Unlock FKLOCK during error processing for MSETPT in CFK4
; UPD ID= 205, SNARK:<6.MONITOR>FORK.MAC.30, 11-Nov-81 18:06:46 by HALL
;Fix typo in previous edit
; UPD ID= 203, SNARK:<6.MONITOR>FORK.MAC.29, 11-Nov-81 16:37:11 by HALL
;TCO 6.1037 - ADD PDL OVERFLOW TO SWTRP JSYS
;TCO 6.1000 - ADD SW%NMI TO SWTRP JSYS (NEEDED FOR 2080)
; UPD ID= 189, SNARK:<6.MONITOR>FORK.MAC.28, 6-Nov-81 12:32:11 by MURPHY
;TCO 5.1608 - extended address for MSFRK.
; UPD ID= 138, SNARK:<6.MONITOR>FORK.MAC.27, 19-Oct-81 15:54:40 by COBB
;TCO 6.1029 - CHANGE SE1CAL TO EA.ENT
; UPD ID= 113, SNARK:<6.MONITOR>FORK.MAC.26, 16-Oct-81 17:13:29 by WALLACE
;TCO 5.1558 - Make .PONAM function of PDVOP% include section number of
; the PDVA in the addresses of a name string if no section number is
; specified in the PDV.
; UPD ID= 112, SNARK:<6.MONITOR>FORK.MAC.25, 16-Oct-81 12:23:57 by MURPHY
;Ignore FH%EPN bit in fork handles.
; UPD ID= 237, SNARK:<5.MONITOR>FORK.MAC.24, 2-Oct-81 13:14:47 by SCHMITT
;TCO 5.1548 - OKINT Jsys trapped process if not resumed in UTFRK JSYS
; UPD ID= 84, SNARK:<5.MONITOR>FORK.MAC.23, 30-Jul-81 07:10:33 by FLEMMING
;add code for XGTPW
; UPD ID= 50, SNARK:<5.MONITOR>FORK.MAC.22, 19-Jul-81 06:38:39 by FLEMMING
;TCO 5.1422 - turn on PM%EPN when PMAPping away section 0
; UPD ID= 45, SNARK:<5.MONITOR>FORK.MAC.21, 17-Jul-81 16:18:16 by MURPHY
;TCO 5.1398 - SKIP RETURN FROM MSETPT
; UPD ID= 1993, SNARK:<5.MONITOR>FORK.MAC.20, 14-May-81 13:22:18 by HALL
;Temporary addition to previous edit -- wait a while after FLKTIM BUGCHK
; UPD ID= 1928, SNARK:<5.MONITOR>FORK.MAC.19, 4-May-81 09:47:40 by GRANT
;Add FORKN optional data to FLKNS; don't commandeer the lock after a FLKTIM
; UPD ID= 1875, SNARK:<5.MONITOR>FORK.MAC.18, 23-Apr-81 16:11:33 by SCHMITT
;More TCO 5.1296 - Change around previous edit
; UPD ID= 1869, SNARK:<5.MONITOR>FORK.MAC.17, 22-Apr-81 11:05:59 by SCHMITT
;TCO 5.1296 - Call CLRVGN before loading ACS in CFK1
; UPD ID= 1658, SNARK:<5.MONITOR>FORK.MAC.16, 10-Mar-81 09:06:42 by FLEMMING
; UPD ID= 1602, SNARK:<5.MONITOR>FORK.MAC.15, 27-Feb-81 09:52:42 by FLEMMING
;tco 5.1265 - fix RMAP returning wrong access information
; UPD ID= 1441, SNARK:<5.MONITOR>FORK.MAC.14, 15-Jan-81 15:52:20 by FLEMMING
;add code for SMAP/RSMAP
; UPD ID= 1328, SNARK:<5.MONITOR>FORK.MAC.13, 1-Dec-80 16:11:13 by OSMAN
;tco 5.1205 - Add XGVEC and XSVEC jsyses
;tco 5.1204 - Add XSFRK jsys
; UPD ID= 1284, SNARK:<5.MONITOR>FORK.MAC.12, 18-Nov-80 14:39:44 by OSMAN
;Fixups for runing programs in other sections
;Use only right half of .JBSA and .JBREN
; UPD ID= 1196, SNARK:<5.MONITOR>FORK.MAC.11, 25-Oct-80 12:14:59 by HALL
;TCO 5.1180 - MOVE THE DST TO NON-ZERO SECTION
; KFORK -- MAKE KILLED FORK START IN SECTION 1 AT KSELF
; UPD ID= 1084, SNARK:<5.MONITOR>FORK.MAC.10, 1-Oct-80 11:59:27 by MURPHY
;FIX ACVAR
; UPD ID= 1012, SNARK:<5.MONITOR>FORK.MAC.9, 12-Sep-80 14:21:45 by OSMAN
;tco 5.1145 - Fix SCTTY to not thaw frozen forks.
; UPD ID= 962, SNARK:<5.MONITOR>FORK.MAC.8, 25-Aug-80 16:26:39 by ENGEL
;TCO 5.1136 - ADD DEVLKK
; UPD ID= 840, SNARK:<5.MONITOR>FORK.MAC.7, 5-Aug-80 16:19:37 by OSMAN
;tco 5.1109 - Add PDVOP%
; UPD ID= 795, SNARK:<5.MONITOR>FORK.MAC.6, 24-Jul-80 09:21:26 by OSMAN
;Add temporary .PDVOP for until real one is in
; UPD ID= 709, SNARK:<5.MONITOR>FORK.MAC.5, 26-Jun-80 17:01:06 by SANICHARA
;TCO 5.1085 - ALLOW CH 23 TO USER ASSIGNABLE
; UPD ID= 670, SNARK:<5.MONITOR>FORK.MAC.4, 17-Jun-80 16:36:34 by KONEN
;TCO 5.1068 - DO DESTRUCTIVE PMAP IN KSELF IF OF%DUD IS ON
; UPD ID= 564, SNARK:<5.MONITOR>FORK.MAC.3, 28-May-80 15:18:52 by ZIMA
;TCO 5.1049 - FIX SECURITY CHECK IN MSFRK
; UPD ID= 435, SNARK:<5.MONITOR>FORK.MAC.2, 13-Apr-80 15:13:22 by OSMAN
; UPD ID= 427, SNARK:<4.1.MONITOR>FORK.MAC.250, 13-Apr-80 14:34:51 by OSMAN
;<OSMAN.MON>FORK.MAC.2, 10-Apr-80 17:51:10, EDIT BY OSMAN
;Shorten source by using FRKTTY instead of FKCTYP
; UPD ID= 392, SNARK:<4.1.MONITOR>FORK.MAC.249, 31-Mar-80 13:59:57 by OSMAN
;tco 4.1.1132 - Fix EPCAP to always trim AC3 according to what fork's allowed
;capabilities are, regardless of wheel.
; UPD ID= 283, SNARK:<4.1.MONITOR>FORK.MAC.248, 20-Feb-80 17:55:31 by MURPHY
;MAKE FKINT BITS FULL-WORD DEF
; UPD ID= 225, SNARK:<4.1.MONITOR>FORK.MAC.247, 25-Jan-80 11:28:38 by GRANT
;TCO 4.2598 - ADD CHECK FOR PRARG JSB FREE SPACE TO KSELF
; UPD ID= 62, SNARK:<4.1.MONITOR>FORK.MAC.246, 29-Nov-79 16:34:15 by MILLER
;ONE MORE TIME. FIX UP FKLOCK WHEN NEXTING
; UPD ID= 58, SNARK:<4.1.MONITOR>FORK.MAC.245, 29-Nov-79 13:39:57 by MILLER
;TCO 4.1.1036. FKLOCK ALWAYS NESTS WITHIN A PROCESS
; UPD ID= 56, SNARK:<4.1.MONITOR>FORK.MAC.244, 29-Nov-79 12:26:58 by MILLER
;MORE.... FIX FLOCK, FLOCKN AND FUNLKI
; UPD ID= 52, SNARK:<4.1.MONITOR>FORK.MAC.243, 29-Nov-79 10:28:37 by MILLER
;TCO 4.1.1026. ADD FUNLKI ENTRY
; UPD ID= 38, SNARK:<4.1.MONITOR>FORK.MAC.242, 28-Nov-79 11:06:55 by MILLER
;TCO 4.2582 AGAIN. SET FKTIMW LARGE WHEN UNLOCKED
; UPD ID= 35, SNARK:<4.1.MONITOR>FORK.MAC.241, 28-Nov-79 10:58:26 by MILLER
; UPD ID= 32, SNARK:<4.MONITOR>FORK.MAC.239, 28-Nov-79 10:50:56 by MILLER
;TCO 4.2582. ADD CHECK AND SET FOR FKTIMW
; UPD ID= 16, SNARK:<4.1.MONITOR>FORK.MAC.240, 27-Nov-79 10:29:05 by OSMAN
;Document FLKTIM
; UPD ID= 8, SNARK:<4.1.MONITOR>FORK.MAC.239, 21-Nov-79 14:52:34 by OSMAN
;<4.1.MONITOR>FORK.MAC.238, 16-Nov-79 14:50:41, EDIT BY ENGEL
;PUT INTERNAL LINE NUMBER INTO T2 AT CALL TO STTOPF IN SCTT3
; COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976, 1990.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
; ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
; INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
; COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
; OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
; TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
; AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
; CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
; SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
SEARCH PROLOG
TTITLE FORK
;FORK CONTROLLING JSYSES AND FUNCTIONS - D. MURPHY
;LOCAL ITEMS DECLARED IN STG.MAC
EXTN <DEVKFK>
;ITEMS DEFINED IN APRSRV FOR SWTRP
EXTN <SETART,SETLUU,GTLUUB>
;AC DEFINITIONS USED HEREIN
DEFAC (FX,Q3) ;FORK INDEX
;DATA STRUCTURES REFERENCED ONLY IN SWPMON
;Definitions for SYSFK in JSB (index by JRFN)
;Bit 0 set indicates JRFN not in use
DEFSTR(SFEXO,SYSFK,1,1) ;Fork is Execute-Only if set
DEFSTR(SFNVG,SYSFK,2,1) ;Fork is not "virgin" if set
DEFSTR(SFGXO,SYSFK,3,1) ;Fork can PMAP into execute-only forks
; because it is doing an execute-only GET
DEFSTR(SFSRT,SYSFK,4,1) ;FORK HAS BEEN STARTED
;Bits 5 to 8 are unused
DEFSTR(FKHCNT,SYSFK,17,9) ;COUNT OF HANDLES ON A GIVEN FORK
;Bits 18 to 35 is the system fork number
SWAPCD
;XSVEC% allows a global PC to be specified for the entry vector address
.XSVEC::MCENT
CALLRET SEVEC0 ;USE COMMON CODE
;GET/SET ENTRY VECTOR
.SEVEC::MCENT
HRRZ C,B ;GET ADDRESS PART OF ENTRY VECTOR
HLRZ B,B ;GET LENGTH
CALLRET SEVEC0 ;USE COMMON CODE
;SEVEC0 is common routine for setting entry vectors
;
;Accepts: A/ fork handle
; B/ length
; C/ address
SEVEC0: CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFX ;Map PSB and check for execute-only
CAIN B,0
CAIE C,0
CAIA
JRST SEV1 ;ALL-0 IS LEGAL
CAIN B,<JRST>B53 ;10/50 STYLE?
JRST SEV1 ;YES
CAIL B,1000
ESVX1: ERRJMP(SEVEX1,ITFRKR) ;NOT LEGAL
SEV1: MOVEM B,EVLNTH(A) ;SAVE LENGTH
MOVEM C,EVADDR(A) ;SAVE ADDRESS
JRST CLFRET
.XGVEC::MCENT
CALL FLOCK
CALL SETLFK
DMOVE B,EVLNTH(A) ;GET VECTOR
XCTU [DMOVEM B,B] ;TELL USER
CALLRET CLFRET
.GEVEC::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
HRL B,EVLNTH(A) ;GET LENGTH
HRR B,EVADDR(A) ;GET ADDRESS PART (WITHOUT SECTION FOR NOW)
GCV1: UMOVEM 2,2
JRST CLFRET
;GET/SET COMPATIBILITY ENTRY VECTOR AND PARAMETERS
.GCVEC::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
MOVE T2,PATADR(1)
JUMPL T2,GCV1 ;NEGATIVE - JUST RETURN IT
TLNE T2,-1 ;EXTENDED FIELDS?
ITERR XSEVX3,<CALL FKLERR> ;YES, CAN'T READ WITH THIS JSYS
HRL T2,PATLEV(T1) ;LENGTH
MOVE 3,PATUPC(1)
HRL 3,PATU40(1)
UMOVEM 3,3
JRST GCV1
.SCVEC::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFX ;Map PSB and check for execute-only
IFL. T2 ;NEG ARG?
SETOM PATADR(T1) ;YES, MEANS PREVENT LOADING OF PA1050
SETZM PATLEV(T1)
JRST CLFRET
ENDIF.
HLRZM T2,PATLEV(T1) ;SAVE LENGTH
XCTU [XHLLI T2,.] ;DEFAULT SECTION
MOVEM 2,PATADR(1)
HRRM 3,PATUPC(1)
HLRM 3,PATU40(1)
JRST CLFRET
;GET/SET RMS (FORMERLY DMS) ENTRY VECTOR
;GET DMS ENTRY VECTOR
;ACCEPTS IN 1/ FORK HANDLE
; GDVEC
;RETURNS +1: ALWAYS
; 2/ LENGTH ,, ENTRY VECTOR ADDRESS
.GDVEC::MCENT
CALL FLOCK ;LOCK FORK STRUCTURE
CALL SETLFK ;MAP IN PSB OF FORK
MOVE 2,DMSADR(1) ;GET ENTRY VECTOR
TLNE T2,-1 ;ENTENDED ADDRESS?
ITERR XSEVX3,<CALL FKLERR> ;YES, CAN'T READ WITH THIS JSYS
HRL T2,DMSLEV(T1) ;LENGTH
JRST GCV1 ;GIVE THESE TO USER
;SET DMS ENTRY VECTOR
;ACCEPTS IN 1/ FORK HANDLE
; 2/ LENGTH ,, ENTRY VECTOR ADDRESS
.SDVEC::MCENT
CALL FLOCK ;LOCK FORK STRUCTURE
CALL SETLFX ;Map PSB and check for execute-only
HLRZM T2,DMSLEV(T1) ;SAVE LENGTH
XCTU [XHLLI T2,.] ;DEFAULT SECTION
MOVEM T2,DMSADR(T1) ;SAVE DMS ENTRY VECTOR
UMOVE 3,4(2) ;GET POINTER TO PC WORD
HRRM 3,DMSUPC(1) ;SAVE ADR OF WHERE TO PUT PC
UMOVE 3,3(2) ;GET POINTER TO JSYS LOCATION
HRRM 3,DMSU40(1) ;SAVE ADR OF WHERE TO PUT JSYS
JRST CLFRET ;EXIT UNLOCKING PSB
;Extended SET/GET special entry vector - i.e. RMS or PA1050
; T1/ vector type code ,, fork handle
; T2/ length
; T3/ 30-bit address. bit 0 = 1 for extended vector format, = 0
; for non-extended format
.XSSEV::MCENT
CALL FLOCK
CALL SETLFX ;MAP PSB, ETC.
XCTU [HLRZ T2,T1] ;GET VECTOR TYPE
CAIL T2,SEVTL
ITERR XSEVX1,<CALL FKLERR> ;ILLEGAL VECTOR TYPE
HRRZ T2,SEVTB(T2) ;DISPATCH TO APPROPRIATE CODE
JRST 0(T2)
.XGSEV::MCENT
CALL FLOCK
CALL SETLFK ;MAP PSB
XCTU [HLRZ T2,T1] ;GET VECTOR TYPE
CAIL T2,SEVTL
ITERR XSEVX1,<CALL FKLERR> ;ILLEGAL VECTOR TYPE
HLRZ T2,SEVTB(T2) ;DISPATCH TO APPROPRIATE CODE
JRST 0(T2)
;DISPATCH FOR SPECIAL VECTOR TYPES
; GET ROUTINE ,, SET ROUTINE
SEVTB: PHASE 0
.XSEVC::! GEVC,,SEVC ;TOPS10 COMPATIBILITY PKG.
.XSEVD::! GEVD,,SEVD ;RMS
DEPHASE
SEVTL==.-SEVTB
;GET/SET PA1050 ENTRY VECTOR
GEVC: MOVE T2,PATLEV(T1) ;LENGTH
UMOVEM T2,T2
MOVE T3,PATADR(T1) ;ADDRESS
UMOVEM T3,T3
JRST CLFRET
SEVC: UMOVE T2,T2 ;GET LENGTH
IFLE. T2
MOVEM T2,PATADR(T1) ;CLEAR
SETZM PATLEV(T1)
JRST CLFRET ;DONE
ENDIF.
CAIGE T2,.SVRPC ;LONG ENOUGH FOR REQUIRED WORDS?
ITERR XSEVX2,<CALL FKLERR> ;NO, INVALID LENGTH
MOVEM T2,PATLEV(T1) ;SAVE LENGTH
UMOVE T2,T3 ;GET ADDRESS
MOVEM T2,PATADR(T1) ;SAVE IT
CALL SETPVV ;SET PC AND UUO WORDS
JRST CLFRET ;RELEASE LOCKS AND RETURN
;GET PA1050 PC AND UUO WORDS
; T1/ FORK PSB OFFSET
; T2/ ENTRY VECTOR ADDRESS
SETPVV: SETPCS T2 ;SET PCS TO SECTION OF ENTRY VECTOR
UMOVE T3,.SVRPC(T2) ;GET POINTERS FROM VECTOR
TXNN T3,VSECNO ;SECTION NUMBER SUPPLIED?
HLL T3,T2 ;NO, DEFAULT TO SAME AS ENTRY VECTOR
MOVEM T3,PATUPC(T1)
UMOVE T3,.SV40(T2)
TXNN T3,VSECNO ;SECTION?
HLL T3,T2 ;NO, DEFAULT IT
MOVEM T3,PATU40(T1)
RET
;GET/SET RMS VECTOR
GEVD: MOVE T2,DMSLEV(T1) ;LENGTH
UMOVEM T2,T2
MOVE T3,DMSADR(T1) ;ADDRESS
UMOVEM T3,T3
JRST CLFRET ;DONE
SEVD: UMOVE T2,T2 ;GET LENGTH OF VECTOR
IFE. T2
SETZM DMSADR(T1) ;CLEAR
JRST CLFRET ;DONE
ENDIF.
CAIGE T2,.SVRPC ;LONG ENOUGH FOR REQUIRED WORDS?
ITERR XSEVX2,<CALL FKLERR> ;NO
MOVEM T2,DMSLEV(T1) ;SAVE LENGTH
UMOVE T2,T3 ;GET ADDRESS
MOVEM T2,DMSADR(T1)
CALL SETDVV ;SET PC AND UUO POINTERS
JRST CLFRET ;UNLOCK AND RETURN
;SET PC AND UUO WORD POINTERS
; T1/ FORK PSB OFFSET
; T2/ ENTRY VECTOR ADDRESS
SETDVV: SETPCS T2 ;SET PCS TO SECTION OF ENTRY VECTOR
UMOVE T3,.SVRPC(T2) ;GET POINTERS FROM VECTOR
TXNN T3,VSECNO ;SECTION?
HLL T3,T2 ;NO, DEFAULT IT
MOVEM T3,DMSUPC(T1)
UMOVE T3,.SV40(T2)
TXNN T3,VSECNO ;SECTION?
HLL T3,T2 ;NO, DEFAULT IT
MOVEM T3,DMSU40(T1)
RET
;HERE ON FIRST OCCURRANCE OF MUUO IN FORK. MAP TOPS10 COMPATIBILITY
;MODULE INTO USER ADDRESS SPACE.
;THIS CODE ALSO IMPLEMENTS THE VIROS/TOPS10 TEST UUO. IF
;THE USER DOES A GETTAB (CALLI 41) WITH ARGUMENT 112,,11 (TABLE
;11, WORD 112) THEN BITS 18-23 TELL WHAT KIND OF MONITOR IT IS.
;IN PARTICULAR, 4 MEANS VIROS.
;THIS CODE CHECKS FOR THIS SPECIFIC CALLI AND ARGUMENT SO THAT
;THE USER PROGRAM CAN EXECUTE IT WITHOUT ACTUALLY INVOKING THE
;COMPATIBILITY MODULE.
GETPAT::
IFN KLFLG,<
MOVE P1,FFL ;GET FLAGS WORD WITH OP CODE AND AC AND PCS
>
IFN KCFLG,<
MOVE P1,FFL ;GET FLAGS WORD WITH CAB AND PAB AND PCS
HRR P1,KIMOAC ;GET OP CODE AND AC TO LOOK LIKE KL
> ;END OF IFN KCFLG
MOVE P2,FPC ;GET PC WORD
MOVE P3,KIMUEF ;GET EFFECTIVE ADDRESS WORD
MCENTR ;GETS HERE FROM UUO HANDLER
HRLZ T1,P1 ;LOOK AT UUO
HRR T1,P3
TLZ 1,(777B17) ;DON'T LOOK AT AC, I, X
CAME 1,[047000,,41] ;WAS IT A CALLI 41 ?
JRST GETPA1 ;NO, CONTINUE
LDB 2,[POINT 4,P1,30] ;YES, CHECK ARGUMENT
UMOVE 1,0(2) ;GET CONTENTS OF DESIGNATED AC
CAME 1,[112,,11] ;IS IT MAGIC NUMBER?
JRST GETPA1 ;NO, CONTINUE
MOVEI 1,4B23 ;YES, RETURN ANOTHER MAGIC NUMBER
UMOVEM 1,0(2) ;RETURN IT IN DESIGNATED AC
SMRETN
GETPA1: SKIPGE T1,PATADR ;FORCED INCOMPATABLILITY?
ITERR(ILINS4) ;YES - GIVE ERROR.
MOVE T1,PATADR ;Get the possible entry vector
HRROI T2,[ASCIZ /SYS:PA1050.EXE/]
; HRROI T3,[ASCIZ /SYS:EPAT.EXE/] ;[7421] EXTENDED VERSION
CALL GETSEG ;Get PA1050
ITERR(ILINS3) ;NO FILE
MOVEM T1,PATLEV ;SAVE LENGTH
MOVEM T2,PATADR ;ADDRESS
SETZ T1, ;NO PSB OFFSET
CALL SETPVV ;SET PC AND UUO POINTERS
SKIPG T1,PATADR ;SHOULD HAVE IT NOW
ITERR ILINS3 ;BAD FILE
REPEAT 0, < ;[7421]
TXNN T1,XS%EEV ;EXTENDED FORMAT VECTOR?
IFSKP.
MOVE T1,PATUPC ;YES, GET ITS ADDRESS
DMOVE T2,P1 ;GET FLAGS, PC
XCTU [DMOVEM T2,0(T1)] ;PASS THEM TO PA1050
MOVE T1,PATU40 ;PTR TO UUO WORD
MOVE T2,P3 ;MOVE UUO WORD TO PA1050
UMOVEM T2,0(T1)
ELSE.
> ;[7421] Repeat 0
MOVE T1,PATUPC ;NON-EXTENDED FORMAT, GET PTR TO PC
MOVE T2,P2 ;CONSTRUCT OLD STYLE FLAGS,,PC
HLL T2,P1
UMOVEM T2,0(T1) ;PASS IT TO PA1050
MOVE T1,PATU40 ;PTR TO UUO WORD
MOVE T2,P3 ;CONSTRUCT OLD STYLE UUO WORD
HRL T2,P1
UMOVEM T2,0(T1)
; ENDIF. ;[7421]
MOVE T1,PATADR
ADDI T1,.SVINE ;INITIAL ENTRY IS OFFSET
MOVEM T1,-1(P) ;CHANGE RETURN PC TO ENTER PA1050
JRST MRETN ;GO TO COMPATIBILITY
;HERE ON FIRST RAF JSYS TO LOAD RMS.EXE INTO FORK ADDRESS SPACE
GETDMS::
IFN KLFLG,<
MOVE P1,FFL ;GET FLAGS WORD WITH OP CODE AND AC AND PCS
>
IFN KCFLG,<
MOVE P1,FFL ;GET FLAGS WORD WITH CAB AND PAB AND PCS
HRR P1,KIMOAC ;GET OP CODE AND AC TO LOOK LIKE KL
> ;END OF IFN KCFLG
MOVE P2,FPC ;GET PC WORD
MOVE P3,KIMUEF ;GET EFFECTIVE ADDRESSS WORD
MCENTR ;ENTER MONITOR CONTEXT
MOVE T1,DMSADR ;Get address of entry vector
HRROI T2,[ASCIZ/SYS:RMS.EXE/]
SETZM T3 ;[7421] MAKE SURE WE DON'T TRY AN EXTENDED FLAVOR
; HRROI T3,[ASCIZ /SYS:XRMS.EXE/] ;[7421] EXTENDED ADR VERSION
CALL GETSEG ;Get RMS into this process
ITERR(ILINS5) ;NO FILE
MOVEM T1,DMSLEV ;SAVE LENGTH
MOVEM T2,DMSADR ;ADDRESS
SETZ T1, ;NO PSB OFFSET
CALL SETDVV ;SET PC AND UUO POINTERS
MOVE T1,DMSADR ;NOW SETUP PC AND UUO WORD
REPEAT 0, < ;[7421]
TXNN T1,XS%EEV ;EXTENDED FORMAT VECTOR?
IFSKP.
MOVE T1,DMSUPC ;PTR TO PC
XCTU [DMOVEM P1,0(T1)] ;PASS IT TO RMS
MOVE T1,DMSU40 ;PTR TO UUO WORD
UMOVEM P3,0(T1) ;PASS UUO WORD TO RMS
ELSE.
> ;[7421] Repeat 0
MOVE T1,DMSUPC ;OLD FORMAT VECTOR, GET PTR TO PC
MOVE T2,P2 ;CONSTRUCT OLD STYLE FLAGS, PC
HLL T2,P1
UMOVEM T2,0(T1) ;PASS IT TO RMS
MOVE T1,DMSU40 ;PTR TO UUO WORD
MOVE T2,P3 ;CONSTRUCT OLD STYLE UUO WORD
HRL T2,P1
UMOVEM T2,0(T1)
; ENDIF. ;[7421]
MOVE T1,DMSADR
ADDI T1,.SVINE
MOVEM T1,-1(P) ;CHANGE PC TO ENTER RMS
JRST MRETN
; GETSEG - Get a segment into this process
;
; Call:
; T2/ String pointer to file name of segment
;Note - as of edit 7421, GETSEG no longer uses T3
; T3/ String pointer to file name of possible extended version
; CALL GETSEG
;
; Returns:
; +1: No such file (GTJFN failed)
; +2: Success, entry vector from file in T1
;
; Clobbers T1, T2
;
GETSEG: ASUBR <GETSG1,GETSG2> ;[7421]
SAVEAC <Q1,Q2>
MOVE Q1,EVLNTH ;Save old entry vector
MOVE Q2,EVADDR
MOVE T1,FORKN ;Get current JRFN
CALL CKNXOR ;Skip if not execute-only
SKIPA T1,[EXP GJ%PHY!GJ%SHT!GJ%OLD] ;Execute-only-- make sure physical SYS:
MOVX T1,GJ%SHT!GJ%OLD ;Not execute-only, just get file
; MOVEM T1,GETSG4 ;[7421] SAVE FLAGS FOR RETRY
MOVE T2,GETSG2 ;[7421] TRY NON-EXTENDED VERSION
GTJFN
REPEAT 0, < ;[7421]
IFSKP.
MOVEM T1,GETSG4 ;HAVE EXTENDED VERSION, SAVE JFN
SKIPG T2,GETSG1 ;Get the address of the entry vector
IFSKP.
HLRZ T1,(T2) ;Get the section number from previous vector
TRZ T1,770000 ; ...so we reuse section,,Zap extraneous flags
ELSE.
MOVEI T1,.FHSLF ;This fork
CALL FFUSEC ;FIND FREE USER SECTION
RET ;ALL FULL
ENDIF.
BLCAL. DGET,<GETSG4,[GT%BAS],0,0,T1> ;GET INTO SPECIFIED SECTION
RET
ELSE.
MOVE T1,GETSG4 ;RECOVER FLAGS
MOVE T2,GETSG2 ;NON-EXT FILE NAME
GTJFN ;Get a JFN on file
> ;[7421] Repeat 0
ERJMP R ;[7421] Error-- return +1 from GETSEG
HRLI T1,.FHSLF ;Get into this process
GET ;Get it
ERJMP R ;FAIL
; ENDIF. ;[7421]
DMOVE T1,Q1 ;GET OLD ENTRY VECTOR
EXCH T1,EVLNTH ;Put old entry vector back, get one from file in T1
EXCH T2,EVADDR
RETSKP ;Return +2 from GETSEG
ENDAS.
;DO EXTENDED GET - CALLED FROM ABOVE AS CONVENIENT WAY TO BUILD
;ARG BLOCK FOR GET
REPEAT 0,< ;[7421]
DGET: BLSUB. <DGJFN,DGFLG,DGAB1,DGAB2,DGAB3>
MOVE T1,DGJFN
HRLI T1,.FHSLF
TXO T1,GT%ARG ;SAY ARG BLOCK PTR IN T2
XMOVEI T2,DGFLG ;AND PUT IT THERE
GET ;GET INTO SECTION SPECIFIED BY DGAB3
ERJMP R
RETSKP
ENDBS.
> ;[7421] Repeat 0
;FIND FREE USER SECTION
; T1/ FORK HANDLE
; CALL FFUSEC
; RETURN +1: FAILED, no free sections or unexpected failures of RSMAP%, SMAP%
; +2: SUCCESS, T1/ section number
REPEAT 0,<
FFUSEC: ASUBR <FFUA1,FFUA2>
MOVEI T1,2 ;START WITH SECTION 2
MOVEM T1,FFUA2
DO.
HRL T1,FFUA1 ;SPECIFIED FORK
RSMAP% ;FIND OUT ABOUT SECTION
CAME T1,[-1] ;EMPTY?
IFSKP.
SETZ T1, ;YES, CREATE PRIVATE SECTION
MOVE T2,FFUA2
HRL T2,FFUA1
MOVX T3,SM%RD!SM%WR!SM%EX+1
SMAP%
ERJMP R
MOVE T1,FFUA2 ;RETURN SECTION CREATED
RETSKP
ENDIF.
AOS T1,FFUA2 ;SECTION NOT FREE, STEP TO NEXT
CAIG T1,(VSECNO) ;BEYOND END?
LOOP. ;NO, CHECK THIS ONE
RET ;YES, RETURN FAILURE
ENDDO.
ENDAS.
> ;[7421] Repeat 0
;SET SCHEDULER PRIORITY WORD
; 1/ FORK HANDLE
; 2/ PRIORITY WORD
; SPRIW
.SPRIW::MCENT
MOVE 2,CAPENB
TRNN 2,SC%WHL+SC%OPR
ITERR(WHELX1) ;MUST BE PRIVILEGED
GTOKM(.GOSPR,<T1,T2>) ;[9119] Get permission from ACJ
CALL CKPRWV ;CHECK WORD FOR LEGALITY
ITERR (ARGX22) ;INVALID BITS
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
SPRI1: UMOVE 2,2
MOVEM 2,JOBBIT(1)
MOVE T2,FORKN(T1) ;GET JOB-WIDE INDEX
HRRZ T2,SYSFK(T2) ;GET SYSTEM INDEX
CALL SETPRF ;INTERRUPT PROCESS
JRST CLFRET
;SET PRIORITY WORD FOR ANOTHER JOB
; 1/ JOB NUMBER
; 2/ PRIORITY WORD
; SJPRI
.SJPRI::MCENT
CALL CKMMOD ;SEE IF MONITOR OR USER
IFNSK. ;[9119] SJPRI was done from user mode today
MOVE T3,CAPENB ;[9119] Load current capabilities
TXNN T3,SC%WHL!SC%OPR ;[9119] Enough capabilites?
ITERR(WHELX1) ;[9119] Wheel or operator required
GTOKM(.GOSJP,<T1,T2>) ;[9119] Get permission from ACJ
ENDIF. ;[9119] End of user mode checks
CALL CKPRWV ;CHECK WORD FOR LEGALITY
ITERR (ARGX22) ;INVALID BITS
CALL FLOCK ;GET FORK LOCK IN CASE THIS JOB
CALL GL2LCL ;CONVERT GLOBAL JOB NUMBER TO LOCAL
JRST SJPRI1 ;ILLEGAL JOB NUMBER
CALL MAPJSB ;GET THE JSB MAPPED
JRST SJPRI1 ;NON-EX JOB
UMOVE T2,2 ;GET PRIORITY WORD
MOVEM T2,JOBSKD(T1) ;STORE IT
MOVE P1,T1 ;GET JSB OFFSET
HRLI P1,-NUFKS ;FORM AOBJN POINTER
SJPRI2: SKIPGE T2,SYSFK(P1) ;THIS FORK ACTIVE?
JRST SJPRI3 ;NO. GO ON
HRRZS T2 ;YES. GET FORK HANDLE
CALL SETPRF ;UPDATE ITS PRIORITY
SJPRI3: AOBJN P1,SJPRI2 ;DO ALL PROCESSES
JRST CLFRET ;AND DONE
SJPRI1: CALL FUNLK
ITERR (SJPRX1) ;NON-EXISTANT JOB
;CKPRWV - CHECK PRIORITY WORD IN USERS AC2 FOR .SJPRI AND .SPRIW JSYSES
;
;RETURN +1: ILLEGAL VALUES
; +2: VALUES ARE LEGAL
CKPRWV: SAVEAC <T1> ;PRESERVE T1 FOR CALLERS
UMOVE T2,2 ;GET PRIORITY WORD
LOAD T1,JP%MXQ,T2 ;GET MIN Q
LOAD T2,JP%MNQ,T2 ;AND MAX Q
CAIG T2,LOWQ ;MIN > MAX?
CAILE T1,LOWQ+1 ;MAX > MAX+1?
RET ;ERROR
RETSKP ;ALL IS OK
;GET AND SET PRIMARY IO JFN'S
.GPJFN::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
MOVE 2,PRIMRY(1)
UMOVEM 2,2
JRST CLFRET
.SPJFN::MCENT
XCTU [SKIPN 2] ;PROVIDING A VALID VALUE?
ITERR (DESX3) ;NO. DISALLOW IT THEN
CALL FLOCK ;LOCK THE FORK STRUCTURE
MOVX T2,<CALL SPJFN1> ;ROUTINE TO EXECUTE
CALL MAPFKH
NOP ;WON'T BLOCK
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
JRST MRETN
SPJFN1: CALL SKIIF
JRST FRKE2
CALL SETLF1
UMOVE 2,2
MOVEM 2,PRIMRY(1)
JRST CLRLFK
;GET TRAP WORDS FROM FORK
.GTRPW::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK ;MAP PSB
MOVE 2,UTRSW(1) ;TRAP STATUS WORD
TXNN T2,TWUSR ;SETUP BITS IN OLD FORMAT
TXO T2,TSW%MN ;MONITOR MODE REFERENCE
TXNE T2,TWWRT
TXO T2,TSW%WT ;WRITE REF
TXO T2,TSW%RD ;READ ALWAYS
UMOVEM 2,1 ;RETURNED IN 1
HRL 2,UMUUOW(1) ;MUUO WORD
HRR 2,UMUUOW+1(1)
UMOVEM 2,2 ;RETURNED IN 2
JRST CLFRET
;XGTPW
; 1/fork handle,,0
; 2/address of data block
; XGTPW%
;where data block is
; number of words in data block (including this one)
;return .+1 always, data block filled in with last page fail word and MUUO
.XGTPW::MCENT
UMOVE P1,(T2) ;NUMBER OF WORDS TO RETURN
SUBI P1,1 ;ACCOUNT FOR THE COUNT WORD
JUMPL P1,[ITERR (ARGX17)]
AOS P2,T2 ;WHERE TO STORE THE ANSWERS
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK ;MAP THE PSB
MOVE T3,UTRSW(T1) ;GET LAST PAGE FAIL WORD
MOVEI T2,0 ;ASSUME LAST PAGE FAIL WAS A READ IN EXEC MODE
TXNE T3,TWUSR ;USER OR MONITOR?
TXO T2,PF%USR ;USER
TXNE T3,TWWRT ;READ OR WRITE REFERENCE?
TXO T2,PF%WTF ;WRITE
CALL PUTWRU ;STORE THE ANSWER IF THE USER PROVIDED ROOM
LOAD T2,TWVADR,UTRSW(T1);Get the virtual address
CALL PUTWRU ;STORE THAT
HRLZ T2,UMUUOW(T1) ;Get MUUO OpCode AC,
CALL PUTWRU ;STORE THAT
MOVE T2,UMUUOW+1(T1) ;MUUO E FIELD
CALL PUTWRU ;STORE THAT
JRST CLFRET ;UNMAP THE PSB AND RETURN
PUTWRU: SOSL P1 ;DECREMENT COUNT, DON'T STORE IF EXHAUSTED
UMOVEM T2,(P2) ;STORE ANSWER
AOJA P2,R ;INCREMENT TO NEXT PLACE TO STORE AND RETURN
;FORK CREATION AND CONTROL JSYS'S
.CFORK::MCENT
MOVE T1,FKCNT ;COUNT OF FORKS
ADDI T1,2 ;CORRECT COUNT FOR THIS CREATION AND INITIAL JOB'S FORK
HRRZ T2,GTOKPR+.GOCFK ;GET COUNT OF FORKS
CAMG T1,T2 ;AND DO GETOK IF REQUIRED
JRST CFGOK ;NO PROCEED WITHOUT GETOK
SOS T1 ;MAKE CURRENT NUMBER
GTOKM (.GOCFK,<T1>,[RETERR ()])
CFGOK: CALL FLOCK ;LOCK THE FORK STRUCTURE
MOVEI T1,-1
CALL GFKH ;GET LOCAL HANDLE
ERRJMP(FRKHX6,EFRKR) ;NONE
PUSH P,T1 ;SAVE IT
NOSKED
MOVE T2,DRMFRE ;GET FREE SWAPPING SPACE
CAMG T2,DRMLV0 ;SPACE LEFT?
JRST CFBAD ;NO. DON'T CREATE THE FORK
MOVE T2,SPTC ;CURRENT SPT COUNT
CAML T2,SPC2 ;ROOM LEFT?
JRST CFBAD ;NO
SKIPE FREFK ;ROOM IN SYSTEM?
SKIPN FREJFK ;ROOM IN JOB?
JRST CFBAD ;NO
CALL ASSFK ;YES, ASSIGN FORK IN SYSTEM
CALL ASSJFK ;AND ASSIGN FORK IN JOB
PUSH P,T1 ;SAVE JOB FORK HANDLE
AOS FKCNT ;UPDATE THIS JOBS FORK COUNT
MOVE T1,FORKX
LOAD T2,FKJO%,(T1) ;GET JOB NUMBER
STOR T2,FKJBN ; AND SET IT FOR NEW FORK
LOAD T2,FKJS%,(T1) ;GET SPT INDEX FOR JSB
STOR T2,FKJSB ; AND SET IT FOR NEW FORK
IFN EXTJSB,<
LOAD T2,FKJP%,(T1) ;Get SPT index for extended JSB
STOR T2,FKJPT ; And set it for new fork
>
CALL WTCONC ;PUT FORK ON WAIT LIST
OKSKED
; ..
;CFORK ...
BP$019:! ;BREAKPOINT FOR CREATE SUBFORK
HRLZ T1,FX
CALL WAITFK ;WAIT FOR IT TO INITIALIZE
POP P,T1 ;RESTORE JOB FORK HANDLE
HRRZM FX,SYSFK(T1)
;Note that this clears all the
; flag bits in LH of SYSFK
MOVEI T2,1 ;INDICATE 1 HANDLE ON THIS FORK
STOR T2,FKHCNT,(T1) ; ...
SETZM FKPTRS(T1)
SETZM FKPSIE(T1)
SETZM FKDPSI(T1)
HRRZ T2,FORKN ;PUT NEW FORK INTO STRUCTURE LISTS
MOVEI Q2,FKPTRS(T2)
HLL Q2,INFERP
LDB T3,Q2 ;GET INFERIORS OF THIS FORK
DPB T1,Q2 ;PUT NEW FORK AT HEAD OF IT
MOVEI Q2,FKPTRS(T1)
HLL Q2,SUPERP
DPB T2,Q2 ;THIS FORK IS SUPERIOR OF NEW FORK
HLL Q2,PARALP
DPB T3,Q2 ;OTHER INFERIORS ARE PARALLEL TO NEW FORK
LOAD T4,FRKTTY,(T2) ;GET CTTY
STOR T4,FRKTTY,(T1) ;PUT SUPERIOR'S CTTY IN INFERIOR
PUSH P,T1
CALL SETLF1 ;MAP PSB OF NEW FORK
; ..
;CFORK ...
MOVE 2,0(P) ;NEW FORK'S JOB HANDLE
MOVEM 2,FORKN(1)
ADDM T2,JTBLK(T1) ;MAKE INFERIOR POINT TO CORRECT FKJTB
MOVE T3,@JTBLK ;GET EXECUTING FORK'S MONITOR, IF ANY
MOVEM T3,FKJTB(T2) ;SAME ENVIRONMENT TO INFERIOR
MOVE 2,PRIMRY
MOVEM 2,PRIMRY(1)
MOVE 2,JOBBIT
MOVEM 2,JOBBIT(1) ;PASS PRIORITY
SETZM CAPMSK(1)
SETZM CAPENB(1)
FTDYN < SETZM CTSSBK(T1) ;Initially No CTS State Block
> ;End of Conditional Assembly
SETZM PDVS(1) ;SAY NO PDVS YET
MOVEI 2,LSTRX1 ;INITIALIZE LAST ERROR CODE TO NONE
MOVEM 2,LSTERR(1)
POP P,4 ;GET JOB WIDE INDEX
MOVE 2,0(P) ;LOCAL HANDLE
ANDI 2,377777 ;MASK OFF FORK BIT
IDIVI 2,2 ;GET FKTAB INDEX
ADD 2,FKPTAB(3) ;GET PROPER BYTE POINTER
DPB 4,2 ;STORE LOCAL POINTER
JE FKIIF,(FX),CFK5 ;IF NO INTERRUPT PENDING, ASSUME INIT SUCCEEDED
MOVE 2,BITS+.ICMSE ;GOT INT. SEE IF FATAL
OPSTR <TDNN T2,>,FKIBX,(FX) ;WAS IT?
JRST CFK5 ;NO. LET IT GO ON
;Here on fatal error
CFFAT: CALL CLRLFK ;YES. CLEAR MAPPING
POP P,1 ;GET LOCAL INDEX
CALL SETJFK ;GET JOB-WIDE FORK HANDLE
CALL KFORK1 ;ZAP THE FORK
CALL FUNLK ;RELEASE FORK LOCK
RETERR (CFRKX3) ;GIVE NO RESOURCES ERROR
; ..
;CFORK...
CFK5: UMOVE T2,1 ;GET ARG
TXNE T2,CR%MAP ;Same map?
CALL CFK4 ;YES
TXNE T2,CR%CAP ;Give special capabilities?
CALL CFK3
TXNE T2,CR%ACS ;Load ACs?
CALL CFK1 ;YES
TXNE T2,CR%ST ;Start process?
CALL CFK2
CALL CLRLFK ;UNMAP PSB
POP P,1 ;RETURN LOCAL HANDLE
UMOVEM 1,1
MOVEI T2,0(7) ;GET SYSTEM FORK INDEX
MOVE 7,FORKX ;GET INDEX OF THIS FORK
LOAD T1,FKMNQ ;GET LOCAL MAX Q
MOVE 7,T2 ;RESTORE INDEX OF CREATED FORK
STOR T1,FKMNQ ;SET UP ITS MAX Q
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
SMRETN
CFBAD: OKSKED
ERRJMP(CFRKX3,EFRKR) ;NO ROOM
;FORK CONTROL SUBRS
;Load ACs
CFK1: SAVET
XCTU [MOVE T2,2] ;GET LOC OF INITIAL AC'S
XMOVEI T3,UAC(T1) ;FIND ADDRESS OF SAVE AREA
MOVEI T1,20 ;ALL ACS
CALL BLTUM1 ;TRANSFER AC'S TO MONITOR AND RETURN
MOVE T1,T4 ;GET JRFN
CALLRET CLRVGN ;SET NON-VIRGIN FOR PROCESS
;Start process
CFK2: MOVEI T3,0(T2) ;START ADDRESS
MOVEM T3,PPC(T1)
MOVX T3,USRCTX ;FLAGS WORD FOR USER MODE
MOVEM T3,PFL(T1)
PUSH P,T1
NOSKED
CALL UNBLK1 ;UNBLOCK IT
OKSKED
MOVE T1,0(P) ;Get PSB address
MOVE T1,FORKN(T1) ;Get JRFN for process
SETONE SFSRT,(T1) ;FLAG THAT FORK HAS BEEN STARTED
CALL CLRVGN ;No longer a Virgin Process
POP P,T1
RET
;Give special capabilities
CFK3: MOVE T3,CAPMSK ;GIVE NEW FORK SAME SPEC CAP
MOVEM T3,CAPMSK(T1)
MOVE T3,CAPENB
MOVEM T3,CAPENB(T1)
RET
;'SAME MAP' BIT - CAUSES MAP OF INFERIOR TO BE FILLED WITH
;IND PTRS TO SUPERIOR
CFK4: PUSH P,1
PUSH P,2
MOVE 1,FORKX
LOAD T3,FKUP%,(T1)
HRLZ T1,T3 ;SOURCE IS THIS FORK
LOAD T3,FKUPT
HRLZ T2,T3 ;DESTINATION IS NEW FORK
MOVSI 3,(PTRW)
MOVEI 4,PGSIZ
CALL MSETPT ;DO FOR ALL PAGES
JRST [ ADJSP P,-3 ;FIX UP STACK POINTER
JRST CFFAT] ;HANDLE FATAL ERROR
CALL CKXADR ;EXTENDED ADDRESSING SUPPORTED?
JRST CFK41 ;NO
;SECTION 0 COULD BE HANDLED WITH AN INDIRECT SECTION POINTER AS WELL
; MAYBE FUTURE ...
MOVE 1,FORKX
LOAD T1,FKPS%,(T1) ;GET SPT INDEX FOR PSB OF THIS FORK
HRLS T1 ; INTO LEFT HALF
HRRI 1,1 ;THIS FORK, SOURCE SECTION 1
LOAD T2,FKPSB ;GET SPT INDEX FOR PSB OF NEW FORK
HRLS T2 ; INTO LEFT HALF
HRRI 2,1 ;NEW FORK, DESTINATION SECTION 1
TXO 3,SM%IND ;MAP VIA INDIRECT POINTERS
MOVEI 4,MXSECN-1 ;ALL SECTIONS
CALL MSETST ;MAP SECTIONS 1 THRU MXSECN
JFCL ;CAN'T HAPPEN
CFK41: MOVE T1,FORKN ;Get current JRFN
CALL CKNXOR ;Is current process Execute-only?
JRST [ MOVE T1,-1(P) ;Yes-- get PSB of new process
MOVE T1,FORKN(T1) ;Get JRFN of new process
CALL SETEXO ;Make new process execute-only also
JFCL ;Can't (should never happen)
JRST .+1]
POP P,2
POP P,1
RET
;Wait for fork to become blocked.
;Accepts:
; T1/ fork handle for fork we're waiting for
; CALL WAITFK
;Returns +1: always, after waiting for the event
WAITFK: HRRI 1,WTFKT
MDISMS
RET
;Scheduler test. Called with fork handle in T1. Returns 1(T4) if fork
;is blocked.
RESCD ;SCHEDULER TEST, MUST BE RESIDENT
WTFKT: JE FKBL%,(T1),0(T4) ;IF NOT BLOCKED, DON'T WAKE UP CALLER
JRST 1(4) ;FORK IS BLOCKED. WAKE UP CALLER
ASSJFK: MOVE 1,@FREJFK
EXCH 1,FREJFK
SUBI 1,FKPTRS
RET
SWAPCD
;SPLICE FORK STRUCTURE
; 1/ FORK HANDLE OF NEW SUPERIOR
; 2/ FORK HANDLE OF FORK TO BECOME INFERIOR
; RETURNS +2: SUCCESS, WITH 1/ FORK HANDLE OF 2 RELATIVE TO 1
DEFINE SPLERR (ERN,JMP)<
JRST [CALL RALLI ;RESUME ALL INFERIORS
ERRJMP (ERN,JMP)]>
.SPLFK:: MCENT
TRVAR <F1,F2,F3>
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL FALLI ;FREEZE ALL OF CALLER'S INFERIORS
UMOVE Q1,T1
TXNE Q1,SF%EXT ;IS THIS AN EXTENDED CALL?
JRST SPLFK4 ;YES, DO SPECIALLY..
XCTU [HRRZ T1,T1] ;GET RFH OF NEW SUPERIOR
CALL SETJFK ;GET JOB FORK HANDLE OF 1
MOVEM T1,F1
CALL SKIIF ;IS 1 INFERIOR OR EQ TO SELF?
SPLERR(SPLFX1,EFRKR) ;NO
XCTU [HRRZ T1,T2] ;GET 2
CALL SETJFK ;GET JOB HANDLE OF 2
MOVEM T1,F2
CAME T1,FORKN ;IS 2 STRICTLY INFERIOR TO SELF?
CALL SKIIF
SPLERR(SPLFX2,EFRKR) ;NO
MOVE T1,F1 ;GET 1
MOVE T2,F2 ;GET 2
CALL SKIIFA ;IS 1 ALREADY EQ OR INFERIOR TO 2?
JRST .+2 ;NO, OK
SPLERR(SPLFX3,EFRKR) ;YES, ERROR
MOVE T1,F1 ;GET F1
SKIPN T1,FKJTB(T1) ;DOES F1 HAVE A JTB?
TROA T1,7777 ;NO, THERE IS NO MONITOR
LOAD T1,JTIMP,(T1) ;YES, GET F1'S MONITOR
MOVE T2,F2 ;GET F2
SKIPN T2,FKJTB(T2) ;DOES F2 HAVE A JTB?
TROA T2,7777 ;NO, THERE IS NO MONITOR
LOAD T2,JTIMP,(T2) ;YES, GET F2'S MONITOR
CAIE T1,(T2) ;F1 AND F2 HAVE THE SAME MONITOR?
CAMN T2,F1 ;OR IS F1 THE IMMEDIATE MONITOR OF F2?
CAIA ;YES, OK.
CALL SPLFK3 ;NO. UPDATE TRAP ENVIRONMENTS
CALL SPLFK9 ;DO THE SPLICE
MOVE T1,F1 ;GET 1
CALL SETLF1 ;MAP PSB OF 1
MOVSI T1,0(T1) ;SETUP ARG FOR GRFKH
HRR T1,F2 ;PSB OFFSET ,, JOB HANDLE
CALL GRFKH ;GET RELATIVE HANDLE FOR 2 RELATIVE TO 1
SETZ T1,
UMOVEM T1,T1
CALL CLRLFK
HRRZ T1,F2 ;NEW INFERIOR
HRRZ FX,SYSFK(T1)
SETONE FKFR1,(FX) ;NEW INFERIORS ALWAYS BECOME FROZEN
CALL RALLI ;RESUME ALL INFERIORS
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
SMRETN
; UPDATE JSYS TRAP ENVIRONMENTS DUE TO SPLICING
; F2 HAS ITS OLD JSYS TRAP ENVIRONMENT REMOVED AND A NEW ONE ADDED.
; THE NEW ENVIRONMENT IS EITHER THE SAME AS F1'S OR IS THE ENVIRONMENT
; F1 INDIRECTLY SET FOR F2 (BY MONITORING ONE OF F2'S SUPERIORS)
SPLFK3: MOVE P1,F2 ;F2
MOVE P2,F1 ;F1
PUSH P,FKJTB(P2) ;SAVE F1'S JTB, IF ANY.
MOVE P4,T2 ;SAVE F2'S MONITOR
SKIPA P3,P1 ;START WITH IMD. MON. OF F2 AND
SPFK3A: MOVE P3,T1 ;FIND OUT IF F1 IS A MON. OF F2
SKIPN T1,FKJTB(P3) ;GET THE NEXT MONITOR UP THE CHAIN
JRST SPFK3B ;NO MORE IN CHAIN
LOAD T1,JTIMP,(T1) ;WHO IS THE MONITOR?
CAIE T1,(P2) ;IS IT F1?
JRST SPFK3A ;NO, KEEP LOOKING.
PUSH P,FKJTB(P1) ;SAVE F2'S CURRENT JTB
CALL NEWJTB ;GET A NEW BLOCK
POP P,FKJTB(P1) ;RESTORE OLD BLOCK, ADDR OF NEW IN T2
MOVEM T2,0(P) ;USE IT AS NEW ENVIRONMENT FOR F2
HRL T1,FKJTB(P3) ;COPY F1'S INFERIOR'S BLOCK
HRR T1,T2 ;TO NEW BLOCK FOR F2
BLT T1,JTBSIZ(T2) ;RETAINING ENV OF F2 SET BY F1
SPFK3B: HRRZ T1,P1 ;FIND SUPERIOR OF F2
ADD T1,SUPERP ;BUILD NEEDED POINTER
LDB T1,T1 ;GET FORK
CAIN P4,(T1) ;IS F2'S MONITOR SAME AS F2'S SUPERIOR?
CALL RELJTB ;YES. RELEASE JTB POINTER TO BY FK IN P1
POP P,FKJTB(P1) ;F2'S NEW JSYS TRAP ENVIRONMENT
CALLRET TFINF ;UPDATE F2'S INFERIORS (FORK IN P1)
;CONTINUE WITH SPLICE NOW THAT THE
;JSYS TRAP ENVIRONMENTS ARE THE SAME
; DO THE SPLICE.
; F1 IS THE NEW SUPERIOR AND F2 IS THE NEW INFERIOR
SPLFK9:
NOSKED ;NOSKED WHILE CHANGING POINTERS
MOVE T1,F2
ADD T1,SUPERP ;MAKE PTR TO SUPERIOR OF 2
LDB T1,T1 ;GET IT
ADD T1,INFERP ;MAKE PTR TO FIRST INFERIOR
SPLFK1: LDB T2,T1 ;SEARCH FOR 2
CAMN T2,F2
JRST SPLFK2 ;FOUND IT
MOVE T1,T2
ADD T1,PARALP
JRST SPLFK1 ;CONTINUE SEARCH
;REMOVE 2 FROM THE INFERIOR LIST OF ITS SUPERIOR
SPLFK2: ADD T2,PARALP
LDB T3,T2 ;GET SUCCESSOR
DPB T3,T1 ;PATCH AROUND 2
;NOW MAKE 2 BE THE FIRST INFERIOR OF 1
MOVE T1,F2
MOVE T2,F1
ADD T2,INFERP ;MAKE PTR TO INFERIOR LIST OF 1
LDB T3,T2 ;GET CURRENT FIRST INFERIOR OF 1
DPB T1,T2 ;MAKE 2 NEW FIRST INFERIOR OF 1
ADD T1,PARALP
DPB T3,T1 ;CONC REST OF INFERIOR LIST TO 2
;NOW UPDATE TO SHOW 1 IS SUPERIOR OF 2
MOVE T1,F2
ADD T1,SUPERP ;MAKE PTR TO SUPERIOR OF 2
MOVE T2,F1
DPB T2,T1 ;PUT 1 AS SUPERIOR OF 2
OKSKED
RET
SPLFK4: TXZ Q1,SF%EXT ;REMOVE FLAG FROM ARG BLOCK ADDRESS
XCTU [HRRZ P1,.SFLEN(Q1)] ;GET WORD COUNT FROM USER
CAIGE P1,2 ;LONG ENOUGH FOR FUNCTION CODE?
SPLERR(SPLBTS,EFRKR) ;NO, ERROR, BLOCK TOO SHORT
UMOVE T1,.SFCOD(Q1) ;GET FUNCTION CODE
CAIE T1,.SFUNS ;IS IT .SFUNS (ONLY ONE SO FAR)
SPLERR(SPLBFC,EFRKR) ;NO, ERROR, BAD FUNCTION CODE.
CAIGE P1,4 ;DOES WORD COUNT INCLUDE FLAGS?
SPLERR(SPLBTS,EFRKR) ;NO, ERROR, BLOCK TOO SHORT
UMOVE T1,.SFUFL(Q1) ;GET FLAGS
TXNN T1,SF%GO
IFSKP. ;IF SF%GO..
CAIGE P1,5 ;IS THERE ROOM FOR ENTRY VECTOR.
SPLERR(SPLBTS,EFRKR) ;NO, ERROR
ENDIF.
TXNN T1,SF%ADR ;IF SF%ADR
IFSKP. ;IS THERE ROOM FOR PC FLAGS AND ADDRESS
CAIGE P1,6 ;NO, ERROR
SPLERR(SPLBTS,EFRKR)
ENDIF.
; SET UP F1, F2, F3 AND CHECK FOR ERRORS
MOVE T1,FORKN
ADD T1,SUPERP
LDB T1,T1
MOVEM T1,F1 ;F1 IS OUR SUPERIOR
XCTU [HRRZ T1,.SFUIN(Q1)]
CALL SETJFK
MOVEM T1,F2 ;F2 IS THE NEW INFERIOR
CAME T1,FORKN
CALL SKIIF ;BE SURE F2 IS STRICTLY INFERIOR TO SELF
SPLERR(SPLFX2,EFRKR)
MOVEI T1,.FHSLF
CALL SETJFK
MOVEM T1,F3 ;F3 IS US
; DO THE XSFRK% OR SFRKV NOW WHILE WE HAVE A VALID HANDLE. NOTHING
; WILL HAPPEN YET ANYWAY BECAUSE F2 IS FROZEN. WE ALSO CATCH ANY
; ERRORS HERE.
CALL SPLFK5 ;SETUP AND CALL APPROPRIATE JSYS.
JRST [CALL RALLI ;RESUME INFERIORS
MOVE T1,LSTERR
JRST EFRKR] ;ERROR RETURN
MOVE T1,F1 ;KILL ANY JSYS TRAPS TO F1
MOVEI Q1,.TFRAL
CALL TFSR
NOSKED ;EXCHANGE FORKN NUMBERS BETWEEN F3 AND F2
MOVE T2,FORKN ;GET OUR FORKN NUMBER
MOVE T1,F2
CALL SETLF1 ;MAP NEW INFERIOR
EXCH T2,FORKN(T1) ;SWAP FORK NUMBERS
PUSH P,T2 ;DON'T LOSE T2
CALL CLRLFK ;UNMAP NEW INFERIOR
POP P,T2
MOVEM T2,FORKN ;COMPLETE SWAP OF FORKN NUMBERS
CALL SPSWAP ;SWAP INFO BETWEEN F3 AND F2
CALL SPLFK9 ;CHANGE FORK STRUCTURE BASED ON F1,F2
HRRZ T1,FORKN ;VIA OUR FORKN
ADD T1,SUPERP ;GET SUPERIOR FORKN
LDB T1,T1
HRRZ FX,SYSFK(T1) ;GET SYSTEM ID OF SUPERIOR.
SETONE FKSPL,(FX) ;SET INFERIOR HAS SPLICED EVENT.
MOVE T1,FORKN ;GET NEW VALUE OF FORKN FOR US.
MOVEM T1,FLKOWN ;FIX THE OWNER OF FLOCK WHILE WE STILL HAVE IT
DO. ;WAKE SUPERIOR IF IT IS IN TRMTST FOR US.
JE FKBL%,(FX),ENDLP. ;IF NOT BLOCKED, THERE IS NO SCHEDULER TEST
LOAD T1,FKWTL ;BLOCKED, SEE WHERE IT IS?
CAIE T1,TRMLST ;WAITING FOR TERMINATION?
IFSKP.
LOAD T1,FKSTD,(FX) ;YES, FOR WHICH FORK?
CAMN T1,FORKX ;WAITING FOR US?
CALL UNBLK1 ;YES, THEN UNBLOCK.
ENDIF.
ENDDO.
OKSKED
CALL RALLI ;RESUME INFERIORS
MOVE T1,F3 ;THIS IS OUR BROTHER WHO WAS INFERIOR
CALL RFORK3 ;ALSO RESUME OUR BROTHER WHO WAS INFERIOR
CALL RFORK1 ;THIS NEEDS TO BE DONE ALSO, FOR SOME REASON.
MOVE T1,FORKN ;GET JOB FORK NUMBER
CALL DASFKH ;DEASSIGN FORK HANDLES
CALL KFORK3 ;REMOVE FROM FORK STRUCTURE
CALL FUNLK ;UNLOCK, WE ARE NOW OUT OF FORK STRUCTURE.
; THE FOLLOWING IS WHAT IS NECESSARY TO DO THE EQUIVALENT OF KSELF FOR ONES
; OWN JOB. THE CODE JUST ABOVE DOES WHAT .KFORK WHAT HAVE DONE.
MOVE 7,FORKX
MOVX T1,FKPSI1 ;DEFERRED INTERRUPT STATE
STOR T1,FKINX,(FX) ;THIS MAKES US NON-INTERRUPTIBLE
JRST KSELF1 ;ENTER KSELF CODE IN THE RIGHT PLACE.
SMRETN
; setup and call appropriate JSYS based on flags.
SPLFK5: UMOVE T1,.SFUFL(Q1)
TXNN T1,SF%CON ;continue fork specified?
IFSKP. ;yes, do it.
MOVX T1,SF%CON ;LH T1/ continue flag for XSFRK%
XCTU [HRR T1,.SFUIN(Q1)] ;RH T1/ obtain inferior to continue
XSFRK%
ERJMP [RET] ;error return
RETSKP ;good return
ENDIF.
TXNN T1,SF%ADR ;start fork at address?
IFSKP. ;yes, do it.
UMOVE T1,.SFUIN(Q1) ;T1/ inferior handle
UMOVE T2,.SFUA1(Q1) ;T2/ PC flags,,0
UMOVE T3,.SFUA2(Q1) ;T3/ PC address
XSFRK%
ERJMP [RET] ;error return
RETSKP ;good return
ENDIF.
TXNN T1,SF%GO ;start fork at entry vector?
IFSKP. ;yes, do it.
UMOVE T1,.SFUIN(Q1) ;T1/ inferior handle
UMOVE T2,.SFUA1(Q1) ;T2/ entry vector address
SFRKV
ERJMP [RET] ;error return
RETSKP ;good return
ENDIF.
RETSKP ;if no flags, then leave as is, good return.
; swap information between forks.
SPSWAP:
MOVEI T4,SYSFK ;MAKE F3 BECOME F2 AND VICE VERSA
CALL SPEXCH
CALL FHEXCH ;swap back the fork handle counts.
MOVEI T4,CTTAB ;controlling terminal
CALL SPEXCH
MOVEI T4,FKJTB ;JSYS traps
CALL SPEXCH
MOVEI T4,FKPSIE ;PSI related
CALL SPEXCH
MOVEI T4,FKDPSI ;PSI related
CALL SPEXCH
RET
;
; EXCHANGES INFORMATION IN JOB TABLES.
; T4/ JOB TABLE NAME
; F3 AND F2 INDICATE TGHE ONES TO EXCHANGE
;
SPEXCH:
MOVE T1,T4
ADD T1,F3 ;PTR TO TABLE(F3)
MOVE T3,0(T1)
MOVE T2,T4
ADD T2,F2 ;PTR TO TABLE(F2)
EXCH T3,0(T2)
MOVEM T3,0(T1)
RET
;
; EXCHANGE FORK HANDLE COUNTS BETWEEN FORK F3 AND F2.
;
FHEXCH: MOVE T1,F2 ;JFH OF FORK F2
MOVE T2,F3 ;JFH OF FORK F3
LOAD T3,FKHCNT,(T1)
LOAD T4,FKHCNT,(T2)
STOR T3,FKHCNT,(T2)
STOR T4,FKHCNT,(T1) ;SWAP COMPLETE
RET
ENDTV.
;.KFORK - KILL FORKS
;
; DESTROYS Q2,FX,P1,P2
;
; REGISTER USAGE - P1 IS COUNT OF FORKS KILLED
; P2 IS POINTER TO LIST OF KILLED FORKS
.KFORK::MCENT
MOVEI T1,0(T1)
CAIN T1,-4 ;ALL INFERIORS?
JRST KFORK2 ;YES
CALL FLOCK ;1 FORK, LOCK THE FORK STRUCTURE
CALL SETJFK ;GET SYSTEM FORK INDEX
CAMN 1,FORKN ;SELF?
ERRJMP(KFRKX2,ITFRKR) ;YES, NOT PERMITTED
CALL SKIIF ;INFERIOR?
JRST FRKE2 ;NO, NOT PERMITTED
SETZ P1, ;ZERO COUNT OF FORKS KILLED
MOVE P2,P ;GET STORAGE POINTER
ADJSP P,1 ;STORAGE FOR 1 FORK
CALL KFORK1 ;KILL IT
CALL FUNLK ;UNLOCK FORK STRUCTURE
CALL KFKWAT ;WAIT FOR COMPLETION
ADJSP P,-1 ;REMOVE STORAGE
JRST MRETN ;AND DONE
KFORK2: CALL FLOCK ;LOCK FORK STRUCTURE
HRRZ T1,FORKN
CALL MAPINF ;FREEZE ALL TO INSURE INTERRUPTIBILITY
CALL FFORK1
CALL KALLI ;KILL ALL INFERIORS (RETURNS FLOCK UNLOCK)
JRST MRETN ;AND DONE
KFORK1: HRLM T1,0(P)
CALL FFORK1 ;FREEZE ALL TO INSURE INTERRUPTIBILITY
HLRZ T1,0(P)
XHLLI Q2,20 ;GET CURRENT SECTION
HLLM Q2,0(P)
KFORK0: CALL DASFKH ;DEASSIGN LOCAL FORK HANDLE
MOVE Q2,T1
HRRZ FX,SYSFK(Q2)
CAMN FX,FORKX ;THIS FORK?
ERRJMP(KFRKX2,ITFRKR) ;CAN'T KILL SELF
CALL KFORK3 ;remove fork from structure
CALL SETLF1 ;MAP PSB
CALL SUSFK ;SUSPEND FORK
MOVE T2,FORKX ;GET SYSTEM FORK INDEX FOR SELF
MOVEM T2,PAC+4(T1) ;LEAVE IT IN AC4 OF VICTIM
SETZM INTDF(T1) ;MAKE VICTIM NON-INTERRUPTABLE
MOVX T2,MONENV ;MONITOR CONTEXT FLAGS WORD
MOVEM T2,PFL(T1) ;SET IT FOR DESTINATION PROCESS
MOVE T2,[MSEC1,,KSELF]
MOVEM T2,PPC(T1) ;START IT SO AS TO KILL ITSELF
AOS P1 ;COUNT FORKS KILLED
AOS P2 ;ADVANCE STORAGE POINTER
MOVEM FX,(P2) ;SAVE FORK INDEX
SETONE FKKIL ;SAY FORK IS WAITING TO DIE
CALL UNBLK1 ;NOW ALLOW FORK TO RUN
OKSKED ;MATCH NOSKED IN SUSFK
CALL CLRLFK
SETZ T1,
MOVEI T2,FPG0A
MOVEI T3,FPG3+1-FPG0 ;CLEAR FORK TEMP PAGES
CALL MSETMP
RET
;KILL ALL INFERIORS OF THIS FORK - MUST BE CALLED FLOCK LOCKED
; UNLOCKS IT FOR RETURN
KALLI: SETZ P1, ;INIT COUNT OF FORKS KILLED
MOVE P2,P ;GET POINTER TO STORAGE
ADJSP P,NUFKS ;GET SOME ROOM
DO.
HRRZ T1,FORKN
ADD T1,INFERP
LDB T1,T1 ;GET NEXT INFERIOR
JUMPE T1,[CALL FUNLK ;NO MORE UNLOCK FORK STR
CALL KFKWAT ;AND WAIT
ADJSP P,-NUFKS ;CLEAR SPACE
RET] ;AND DONE
CALL KFORK0 ;KILL ALL INFERIORS TOO
JRST TOP.
ENDDO.
; remove fork from structure, called by KSELF and KSELFJ.
; T1/ job fork number, destroys T3,T4
KFORK3: MOVE T3,T1
ADD T3,SUPERP
LDB T3,T3 ;GET SUPERIOR
ADD T3,INFERP
KFK01: LDB T4,T3 ;GET NEXT PARALLEL
CAIN T4,0(T1) ;DESIRED FORK?
JRST KFK02 ;YES
MOVE T3,T4
ADD T3,PARALP
JRST KFK01
KFK02: ADD T4,PARALP ;FOUND FORK TO BE KILLED IN LIST
LDB T4,T4
DPB T4,T3 ;PUT NEXT IN LAST, REMOVING FORK FROM LIST
RET
;WAIT FOR FORKS TO DIE - CALLING FORK MUST NOT HAVE FLOCK
KFKWAT: SOJL P1,R ;ALL DONE RETURN
HRL T1,(P2) ;GET FORK INDEX
HRRI T1,KFKTST ;AND ROUTINE
MDISMS ;WAIT FOR FORK TO DIE
SOJA P2,KFKWAT ;DECREMENT STORAGE POINTER AND LOOP
RESCD
;SCHEDULER TEST FOR ABOVE
KFKTST: JE FKKL%,(T1),RSKP ;IF FLAG IS CLEAR DONE WAITING
RET ;KEEP WAITING
SWAPCD
;FORK KILL SELF
; 4/ FORK WHICH INITIATED KSELF
BP$021:! ;(KSELF): BREAKPOINT FOR KFORK
;ASSUMES FORKX HAS SUICIDAL FORK INDEX
KSELF::
MOVE FX,FORKX
MOVX T1,FKPSI1
STOR T1,FKINX,(FX) ;DISABLE ANY FURTHER INTERRUPTS
MOVX T1,USRCTX ;SET UMODF AND CAB FOR USER MODE
MOVEM T1,FFL
SETZM FPC
MCENTR ;GET INTO REASONABLE MONITOR STATE
KSELF1: CALL ABTBUF ;FLUSH TCP BUFFERS FOR THIS FORK
MOVEI T1,0(FX) ;GET FORK HANDLE
CALL SCSKIL ;DEALLOCATE ANY SCS% RESOURCES
PUSH P,T2 ;SAVE
SETZ T2, ;CLEAR ALL FORK'S ENTRIES ON STACK
CALL JSBSTF ;GO PROCESS DEALLOCATION LIST
NOINT ;NOINT IN CASE THERE'S FREE SPACE TO REMOVE
SKIPE T2,PRARGP ;ANY JSB SPACE USED BY PRARG?
JRST [SETZM PRARGP ;ZERO OLD POINTER
CALL PRARGF ;RELEASE THE SPACE
JRST .+1]
SKIPE T2,PDVS ;ANY PDVAS STORED?
CALL RELJFR ;YES, RELEASE THEM
SETZM PDVS ;SAY NO PDVAS STORED ANYMORE
OKINT ;DONE WITH FREE SPACE STUFF, SO ALLOW INTERRUPTS AGAIN
FTDYN < CALL CLRCTS ;Clear all CTS State Information
> ;End of Conditional Assembly
CALL INTCLR ;CLEAR PROCESSOR DEPENDENT STUFF
CALL EVRKIL ;CHECK FOR DECNET EVENT READER
CALL NTCOFF ;CLEAR THE NETWORK CHANGE INTERRUPT TABLE
JFCL ;IGNORE
CALL NIJKFK## ;Reset NI% JSYS stuff
MOVEI T1,0(FX) ;GET FORK HANDLE
SETZ T2,0 ;CLEAR ALL FORK'S ENTRIE
CALL GOKFRE
POP P,T2 ;RESTORE T2
CAMN FX,ACJFN ;CHECK FOR ACJ FORK
CALL ACJKIL ;KILL ACJ NOW
SETOM INTDF
MOVEM T4,P1 ;SAVE FORKX OF SUPERIOR
SETZM PSIBW
CALL DTIALL ;DEASSIGN TERM INTERRUPTS
OPSTR <SKIPE >,PSUTPS ;DID THIS FORK USE .MOTPS MTOPR FUNCTION?
CALL TTDTPS ;YES, SCAN TTYS FOR THIS FORK
MOVE 1,JOBNO ;GET JOB NUMBER OF THIS PROCESS
OPSTR <SKIPE >,DIAFL,(T1) ;DOES THIS JOB HAVE DIAG RESOURCES?
CALL DGFKIL ;YES. GO RELEASE THIS PROCESSES SET
CALL MTAKFK ;KILL MTA ONLINE/OFFLINE PSI INTERRUPTS
HLRZ T1,DSPSFK ;GET DSK PSI FORK
CAIN FX,0(T1) ;SAME AS THIS ONE?
SETZM DSPSFK ;YES CANCEL IT
;..
;..
KSEFW: HRRZ T1,FORKN ;GET SELF
LOAD T2,FRKTTY,(T1) ;GET MY CTTY
CAIN T2,-1 ;JUST THE JOB'S CTTY?
JRST KSEF0 ;YES, NOTHING TO DO.
TRZN T2,1B18 ;CONVERT FROM DESIGNATOR TO LINE NUMBER
JRST KSEF0 ;WASN'T A DESIGNATOR?
CAIGE T2,NLINES ;RANGE CHECK
CAIGE T2,0
JRST KSEF0 ;NOT A VALID LINE
CALL GTTOPF ;GET THE TOP FORK OF CTTY GRP FOR THIS TTY
JRST KSEF0 ;NOT AN ACTIVE LINE
CAME T3,FORKX ;IS IT ME?
JRST KSEF0 ;NO. NOTHING TO DO.
SKIPN FORKN ;IS THIS THE TOP FORK?
IFNSK. ;IF SO
LOKK DEVLKK
CALL TTYDAS ;RELEASE TTY NOW
IFNSK. ;IFF ERROR RETURN
IFL. T1
HRL T1,T2
UNLOKK DEVLKK
MDISMS ;WAIT HERE FOR CONDITION TO IMPROVE
JRST KSEFW ;AND TRY IT AGAIN
ENDIF.
UNLOKK DEVLKK ;RELEASE DEVICE LOCK
ENDIF.
ELSE.
MOVEI T1,-1 ;CLEAR IT
CALL STTOPF ;SET TO NOT IN USE
ENDIF.
;..
;..
KSEF0: SETO T1,
RFRKH ;GO RELEASE ALL RELEASABLE HANDLES
JFCL
MOVSI T2,.FHSLF
MOVE T3,[PM%CNT+PM%ABT+PM%EPN+1000] ;REQUEST PMAP OF 1000 PAGES
PMAP ;CLEAR ALL PAGES FROM SECTION-ZERO MAP
CALL CLNZSC ;UNMAP PAGES FROM NON-ZERO SECTIONS
JFCL ;DON'T CARE IF SECTIONS STILL EXIST
MOVE T1,FORKX ;GET FORK NUMBER
CALL PIDKFK ;KILL ALL PIDS BELONGING TO THIS FORK
MOVE T1,FORKX
CALL ENQFKR ;DEQ ALL REQUESTS FOR THIS FORK
MOVE T1,FORKX ;CHECK IF THIS FORK OWNS THE UTEST LOCK
CAMN T1,UTLOCK ;...
CALL UTREL ;YES, RELEASE IT
;Clean up the effect of setting address break. Decrement the count of users
;who have address break set. We cannot zero ADRBRK here, because address break
;is still turned on in the hardware. When the process goes to HLTFK1, it will
;go through KISSAV, which will turn off address break in the hardware. Note
;that this code must not be executed twice for this fork, because that would
;cause a second SOS of USERBK.
SKIPE ADRBRK ;HAVE ADDRESS BREAK SET NOW?
SOS USERBK ;YES. DECREMENT NUMBER OF USERS BREAKING
SETOM PRIMRY ;SET PRIMARY I/O TO CONTROLLING TERMINAL
MOVE T1,[CZ%UNR+CZ%ABT+400000] ;REASSIGN STILL-MAPPED+FLUSH NONX FILES
CLZFF ;CLOSE FILES HERE AND BELOW
IFE FTNSPSRV,<
CALL RELSAB ;FREE DECNET SABs (Session Control Arg Blk)
CALL LLMRFK## ;[7173] Release any LLMOP resources
>
IFN LAHFLG,<
MOVE T1,FX ;[7.1120]Fork number to T1
CALL LATRST ;[7.1120](T1)Release any reverse LAT TTY's
> ;[7.1120]End of IFN LAHFLG
SOS FKCNT ;COUNT OF FORKS
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL KALLI ;KILL ALL FORKS AND UNLOCK FLOCK
CALL UNMIDX ;UNMAP THE DIRECTORY AND INDEX FILE
CALL CLKREL ; Release any clocks for this fork
MOVE T1,JOBNO ;GET JOB NUMBER OF THIS FORK
SKIPE SNPPGS ;THIS FORK SNOOPING?
CALL SNPREL ;YES, GO REMOVE ITS BREAK POINTS
MOVE FX,FORKX
LOAD T1,FKUPT ;GET SPT INDEX FOR UPT
LOAD T2,SPTSHC,(T1) ;GET SHARE COUNT OF UPT
PUSH P,T2 ;SAVE IT FOR LATER CHECK
CALL FLOCK
SKIPN T2,@JTBLK ;DO WE HAVE A JSYS TRAB BLOCK?
JRST KSEF1 ;NO
HRRZ T3,FORKN ;YES, SEE WHETHER IT SHOULD BE RELEASED
ADD T3,SUPERP ;IDENTIFY MY SUPERIOR
LDB T3,T3 ; ..
HRRZ P1,FORKN ;NEED MY FORK NUMBER FOR RELJTB
LOAD T2,JTIMP,(T2) ;MY MONITOR
CAIN T3,(T2) ;IS MY SUPERIOR MY MONITOR?
CALL RELJTB ;YES. RELEASE THE JTB
KSEF1: CALL FUNLK
LOAD T1,NOSTR
SKIPE T1 ;IF NO STRUCTURES MOUNTED, SKIP STR CODE
CALL RELSTR ;RELEASE ALL STRUCTURE MOUNTS FOR FORK
SETZRO FKKIL ;FORK IS NOW EFECTIVLY DEAD - TURN OFF FLAG
;..
;FINAL RUNDOWN - HAVE TO WAIT FOR THE SHARE COUNTS ON ALL SECTION MAPS
;TO GO TO ZERO. NON-ZERO SECTIONS ARE CHECKED WITH THE CLNZSC ROUTINE.
;SECTION ZERO IS CHECKED WITH BY EXPLICITLY TESTING ITS SHARE COUNT.
;IF ANY SECTIONS ARE STILL SHARED, DISMISS AND TRY AGAIN LATER.
;..
KSEF2: CALL CLNZSC ;DELETE USER'S NON-ZERO SECTIONS
JRST [ POP P,T2 ;STILL SOME LEFT, FIX STACK
JRST KSEF3] ;GO WAIT FOR A WHILE
POP P,T2 ;SHARE COUNT OF UPT
CAIE T2,1 ;UNSHARED?
JRST KSEF3
CALL FLOCK
HRRZ T4,FORKN ;GET JOB FORK HANDLE FOR SELF
LOAD T1,FKHCNT,(T4) ;GET NUMBER HANDLES OF THIS FORK
JUMPN 1,[MOVSI T1,(1B0) ;NO. MARK IT DELETED THEN
IORM T1,SYSFK(4) ;""
JRST KSEF5] ;AND GO FINISH UP
MOVEI T1,FKPTRS(4) ;NO OTHERS, PUT JOB SLOT BACK ON FREE LIST
EXCH T1,FREJFK
MOVEM T1,@FREJFK
SETOM SYSFK(T4) ;NOTE SLOT AVAILABLE
KSEF5: CALL FUNLK
MOVE FX,FORKX
LOAD T2,FKPSB ;GET SPT INDEX FOR PSB
HRLS T2 ; INTO LEFT HALF
SETZ T1,
HRRI T2,PPLOW ;CLEAR PROCESS MAP FROM PPLOW
MOVEI T4,PPHI-PPLOW+1 ; TO PPHI
CALL MSETPT ;CLEAR PROCESS MAP
NOP ;IGNORE FAILURES
CALL WTFPGS ;WAIT FOR UPT AND PSB TO BE UNMAPPED
JRST HLTFK1 ;GO DELETE UPT AND PSB
;Here when share count of section 0 map (UPT) is non-zero. Clear map
;again.
KSEF3: MOVEI T1,^D5000
DISMS ;WAIT FOR 5 SECS
LOAD T1,FKUPT ;GET SPT INDEX FOR UPT
LOAD T2,SPTSHC,(T1) ;SHARE COUNT OF UPT
PUSH P,T2
SETZ T1, ;INDICATE CLEARING
LOAD T2,FKUPT ;GET SPT INDEX OF UPT
HRLZS T2 ;UPT,,PAGE 0
KSEF4: HRRZ T3,T2 ;MAKE A GOOD ADDRESS.
SKIPE UPTPGA(T3) ;QUICK CHECK FOR ALREADY EMPTY
CALL SETPT ;BUT NOT USING PMAP
MOVEI Q2,0(T3)
CAIGE Q2,777
AOJA T2,KSEF4
JRST KSEF2
;CLNZSC - DELETE NON-ZERO SECTIONS OF USER'S ADDRESS SPACE
;RETURNS +1: ONE OR MORE SECTIONS CAN'T BE DELETED BECAUSE
; THEY ARE STILL SHARED
; +2: ALL NON-ZERO SECTIONS CLEARED
CLNZSC::CALL CKXADR ;EXTENDED-ADDRESSING MACHINE?
RETSKP ;NO, CAN'T HAVE NON-ZERO SECTIONS, DONE
SAVEAC <Q1,Q2> ;GET WORK AC'S
MOVEI Q1,(VSECNO) ;GET HIGHEST SECTION #
SETZ Q2, ;CLEAR COUNT OF SECTIONS I COULDN'T KILL
;LOOP TO SCAN ALL SECTIONS, ATTEMPTING TO DELETE ANY THAT EXIST
CLNZS1: MOVE T1,Q1 ;GET SECTION #
CALL CHKMPS ;DOES THIS SECTION EXIST?
JUMPE T1,CLNZS2 ;NO, SKIP IT
SETO T1, ;YES, GET -1 TO SPECIFY DELETION
MOVSI T2,.FHSLF
HRR T2,Q1 ;GET FORK HANDLE,,SECTION#
MOVE T3,[PM%ABT+1] ;COUNT (DESTRUCTIVE PMAP IF OF%DUD ON)
SMAP% ;TRY TO DELETE THE SECTION
ERJMP [HRRZ T1,LSTERR ;FAILED, GET ERROR CODE
CAIN T1,SMAPX1 ;FAILED BECAUSE STILL SHARED?
AOS Q2 ;YES, COUNT IT
JRST .+1]
CLNZS2: SOJG Q1,CLNZS1 ;LOOP THRU ALL SECTIONS
JUMPE Q2,RSKP ;SKIP RETURN IF ALL DELETED
RET ;SOME SECTION(S) STILL SHARED
;FREEZE FORK
;ACCEPTS:
; T1/ RELATIVE FORK HANDLE
;RETURNS +1: ALWAYS
; ILLEGAL INSTRUCTION TRAP ON ERROR
.FFORK::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
MOVEI 1,0(1)
CAIN 1,-4 ;ALL INFERIORS?
JRST FFORK5 ;YES
;USER WANTS TO FREEZE JUST ONE FORK. GET THE JOB-WIDE FORK HANDLE
;RETURN ERROR IF REQUEST IS FOR SELF, SUPERIOR, OR PARALLEL
CALL SETJFK ;OTHERWISE, ANY SINGLE INFERIOR
CAME 1,FORKN ;REQUESTING FREEZE OF SELF?
CALL SKIIF ;REQUESTING SELF OR INFERIOR?
JRST FRKE1 ;NOT INFERIOR. RETURN ERROR
;DO THE FREEZE. UPDATE TTY PSI INFORMATION IF REQUESTED FORK AND
;REQUESTING FORK HAVE THE SAME CONTROLLING TERMINAL
PUSH P,T1 ;SAVE THE REQUESTED JOB-WIDE INDEX
CALL FFORK1 ;DO THE WORK
POP P,T1 ;RESTORE REQUESTED INDEX
LOAD T1,FRKTTY,(T1) ;HERE'S ONE FORK'S CTTY
HRRZ T2,FORKN ;NOW DO SAME FOR SELF
LOAD T2,FRKTTY,(T2) ;HERE'S MY CTTY
CAIN T1,0(T2) ;ARE THEY THE SAME SOURCE?
CALLRET UPDTIR ;YES. SO GO UPDATE TTY PSI INFO
CALL FUNLK ;NO. SO JUST RELEASE FORK STRUCTURE
MRETNG ;AND RETURN
;HERE WHEN REQUESTED ALL INFERIORS OF THE CALLER. STEP THROUGH
;ALL IMMEDIATE INFERIORS AND, FOR EACH ONE, CALL FFORK1 TO
;FREEZE IT.
FFORK5: HRRZ 1,FORKN ;SELF
CALL MAPINF ;MAP ALL IMMED INFERIORS
CALL FFORK1 ;THROUGH FFORK1
HRRZ T1,FORKN ;GET MY SOURCE OF TERMINAL PSI'S
LOAD T1,FRKTTY,(T1)
CALLRET UPDTIR
;FFORK1 AND FFORK3 - FREEZE A FORK AND ALL OF ITS INFERIORS
;ACCEPTS:
; T1/ JOB-WIDE FORK HANDLE
; CALL FFORK1 - DIRECT FREEZE
; CALL FFORK3 - INDIRECT FREEZE
;RETURNS +1: ALWAYS
FFORK3: SKIPA 2,[FRZB2%] ;INDIRECT FREEZE BIT
FFORK1: MOVX 2,FRZB1% ;DIRECT FREEZE BIT
HRRZ FX,SYSFK(1) ;GET SYSTEM WIDE FORK INDEX
CAIE FX,-1 ;[7254] Fork exist?
OPSTR <TDNE 2,>,FKINX,(FX) ;ALREADY DONE?
RET ;YES
TXNE 2,FRZB1% ;REMEMBER WHICH BIT - B1?
TRO 1,1B18 ;YES
HRLM 1,0(P) ;SAVE CURRENT FORK
TRZ 1,1B18
CALL MAPINF ;DO INDIRECT FREEZE OF INFERIORS
CALL FFORK3
HLRZ T1,0(P) ;GET CURRENT FORKN
TRZ T1,1B18
LOAD T2,FRKTTY,(T1) ;THIS FORK'S CURRENT SOURCE OF PSI'S
PUSH P,Q1 ;SAVE A COUPLE AC'S
PUSH P,Q2 ; ..
MOVEI Q1,0(T1) ;FIND SUPERIOR OF THIS FORK
ADD Q1,SUPERP ; ..
LDB Q1,Q1 ;GET FORK NUMBER
LOAD T1,FRKTTY,(Q1) ;GET CONTROLLING TERMINAL
CAMN T2,T1 ;SAME AS FOR FORK BEING FROZEN?
JRST FFORK4 ;YES, SKIP THE PSI UPDATE
MOVEI T1,0(T2) ;NO, DIFFERENT. SO UPDATE PSI INFO
CALL UPDTI ; FOR THAT TTY
FFORK4: POP P,Q2 ;RESTORE AC'S USED JUST ABOVE
POP P,Q1 ; ..
HLRZ 1,0(P) ;RESTORE FORK PLUS FLAG BIT
XHLLI T2,20 ;GET SECTION #
HLLM T2,0(P) ;SET IT IN RETURN
MOVX 2,FRZB1% ;RESTORE BIT
TRZN 1,1B18 ;B1?
MOVX 2,FRZB2% ;NO, B2
HRRZ 7,SYSFK(1)
CALL SUSFK ;SUSPEND FORK
OPSTR <IORM 2,>,FKINX,(FX)
MOVEI 2,FRZWT
STOR 2,FKSTR,(FX) ;SET FROZEN STATE
CALL RECONC ;UPDATE LIST
OKSKED ;MATCH NOSKED IN SUSFK
RET
;(INDIRECTLY) FREEZE ALL INFERIORS
FALLI: MOVE T1,FORKN
CALL MAPINF
CALL FFORK3 ;XCTED BY MAPINF
RET
RESCD
FRZWT:: JRST 0(4) ;FREEZE WAIT SCHED TEST
SWAPCD
;RESUME FORK
.RFORK::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
MOVEI 1,0(1)
CAIN 1,-4 ;ALL INFERIORS?
JRST RFORK5 ;YES
CALL SETJFK
MOVE P1,T1 ;SAVE A COPY OF THE FORK INDEX
CAME 1,FORKN ;CHECK RELATIVITY
CALL SKIIF
JRST FRKE1 ;NOT INFERIOR
CALL RFORK1
LOAD T1,FRKTTY,(P1) ;GET CTTY
CALLRET UPDTIR
RFORK5: HRRZ 1,FORKN
CALL MAPINF ;DO ALL IMMED INFERIORS
CALL RFORK1
HRRZ T1,FORKN
LOAD T1,FRKTTY,(T1) ;FIND THE FORK'S CTTY
CALLRET UPDTIR
RFORK3: SKIPA 2,[FRZB2%] ;INDIRECT FREEZE BIT
RFORK1: MOVX 2,FRZB1% ;DIRECT FREEZE BIT
HRRZ 7,SYSFK(1)
OPSTR <TDNN 2,>,FKINX,(FX) ;FROZEN THIS WAY?
RET ;NO
OPSTRM <ANDCAB 2,>,FKINX,(FX) ;CLEAR THIS TYPE OF FREEZE
TXNE 2,FRZBB% ;ALL TYPES OF FREEZE NOW CLEARED?
RET ;NO, LEAVE FORK FROZEN
HRLM 1,0(P) ;SAVE CURRENT FORK
CALL MAPINF ;CLEAR INDIRECT FREEZE ON INFERIORS
CALL RFORK3
HLRZ 1,0(P)
HRRZ FX,SYSFK(T1) ;SYSTEM FORK INDEX
XHLLI T2,. ;FIND CURRENT SECTION
HLLM T2,0(P) ;SET IT IN RETURN PC
JN FKFRJ,(FX),R ;RETURN IF FROZEN BY JSYS TRAP
SETZRO FKFRA,(FX) ;CLEAR ADDRESS BREAK FREEZE
CALL STPFK1 ;SET TO UNFREEZE THIS FORK
SKIPN 2,PIOLDS(1) ;WAS ON WTLST BEFORE FREEZE?
JRST [ CALL UNBLK1 ;UNBLOCK IT
JRST RFORK4]
STOR 2,FKSTX,(FX)
CALL RECONC ;UPDATE WAIT LISTS
RFORK4: CALL CLRSFK ;UNSUSPEND FORK
OKSKED ;MATCH NOSKED IN STPFK1 (SUSFK)
JRST CLRLFK
;(INDIRECTLY) RESUME ALL INFERIORS
RALLI: MOVE T1,FORKN
CALL MAPINF
CALL RFORK3 ;XCTED BY MAPINF
RET
;BREAKPOINT JSYS FOR IDDT
.BPT:: MCENT
JRST HALTF1 ;MAKE LIKE HALTF
;PERPETUAL WAIT - INTERRUPTABLE
.WAIT:: MCENT
WAIT1:: MOVEI 1,JRET
MOVSI T2,FHV2 ;LOWER BLOCK PRIORITY
HDISMS
JRST MRETN
;SPECIAL ROUTINES CALLED FROM HANG-UP CODE TO INDIRECTLY FRREZE OR
;UNFREEZE ALL INFERIORS. THIS TECHNIQUE IS USED (RATHER THAN FFORK
;AND RFORK) IN ORDER TO PRESERVE THE FROZENNESS OF FORKS ACROSS
;A HANGUP ATTATCH SEQUENCE.
;FORK FREEZE INDIRECT:
FFORKI::CALL FLOCK ;LOCK UP THE JOB FORK STRUCTURE
HRRZ T1,FORKN ;GET RELATIVE HANDLE FOR THIS PROCESS
CALL MAPINF ;MAP ALL INFERIORS
CALL FFORK3 ;INDIRECTLY FREEZE THEM ALL
FORKI: CALL UPDTI ;UPDATE TTY PI WORDS
CALL FUNLK ;UNLOCK FORK STRUCTURE
RET ;AND DONE
;RESUME FREEZE INDIRECT
RFORKI::CALL FLOCK ;LOCK UP FORK STRUCTURE
HRRZ T1,FORKN ;GET JOB WIDE INDEX
CALL MAPINF ;MAP ALL INFERIORS
CALL RFORK3 ;INDIRECT RESUME OF ALL INFERIORS
JRST FORKI ;AND DONE
;READ FORK STATUS
.RFSTS::MCENT
TXNE T1,^-<RF%LNG!RF%PRH> ;ANY RESERVED BITS NON-0?
ITERR (DECRSV)
CALL FLOCK ;LOCK THE FORK STRUCTURE
MOVE P1,[-1] ;ASSUME FORK HANDLE IS UNASSIGNED, STATUS=-1
HRRZ T1,T1 ;USE ONLY 18 BITS
TRNE T1,200000 ;LOCAL DESIGNATOR?
JRST RFSTS5 ;NO
CAIN T1,400000 ;SELF?
JRST RFSTS5 ;YES - DONT TRANSLATE HANDLE
CALL RFHJFK ;CONVERT SINGLE FORK RFH TO JRFN
JRST ITFRKR ;ERROR - ERR CODE IN T1
CAIGE T1,NUFKS ;ASSIGNED?
SKIPG SYSFK(T1)
JRST RFSTS7 ;NO-- RETURN -1
JRST RFSTS6 ;YES
RFSTS5: CALL SETJFK ;NOT MULTIPLE FORKS
RFSTS6: HRRZ FX,SYSFK(T1) ;GET SYSTEM FORK INDEX
MOVE P1,T1 ;SAVE JOB INDEX
CALL MRFSTS ;GET FORK STATUS WORD
EXCH P1,T1 ;SAVE STATUS. GET BACK JOB INDEX
CALL SETLF1 ;MAP PSB
RFSTS7: UMOVE T2,1 ;GET USER AC1
TXNE T2,RF%LNG ;LONG FORM RFSTS?
JRST RFSLNG ;YES-- DO LONG FORM
CAMN P1,[EXP -1] ;UNASSIGNED FORK HANDLE?
JRST RFSTSR ;YES-- JUST RETURN STATUS
HLLZ T3,PFL(T1) ;GET FLAGS
MOVE T2,PPC(T1) ;GET PC
TXNN T3,UMODF ;USER MODE?
JRST [ HLLZ T3,UPDL+1(T1) ;NO, USER FLAGS IS FIRST ON STACK
MOVE T2,UPDL+0(T1) ;AND GET THE PC
TXZ T3,UMODF ;BUT TURN OFF USER BIT FOR INFO
JRST .+1]
TXZ T2,PCX ;IGNORE UNUSED PC BITS
TLNN T2,-1 ;SECTION 0?
IOR T2,T3 ;YES. FORM SECTION 0 PC WORD THEN
UMOVEM T2,2
CALL CLRLFK
RFSTSR: UMOVEM P1,1
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
JRST MRETN
;HERE FOR LONG FORM OF RFSTS CALL
; T1/ PSB OFFSET FOR PROCESS TO READ STATUS
RFSLNG: UMOVE Q1,2 ;GET ADDRESS OF ARGUMENT BLOCK
XCTU [HRRZ T2,.RFCNT(Q1)] ;GET USER'S MAX COUNT
MOVEI T3,RFSMAX ;ASSUME MAX ENTRIES ARE LEGAL
CAMN P1,[EXP -1] ;UNASSIGNED FORK HANDLE?
MOVEI T3,.RFPSW+1 ;YES-- JUST RETURN STATUS WORD
CAMLE T2,T3 ;USER'S LENGTH TOO BIG?
MOVE T2,T3 ;YES-- ONLY GIVE WHAT WE HAVE
MOVN T2,T2 ;FORM
MOVE P2,Q1 ;[7146]ACTUAL ADDRESS TO USER TABLE.
HRL Q1,T2 ; AOBJN POINTER TO USER TABLE
MOVEI Q2,.RFPSW ;FIRST WORD IS PROCESS STATUS WORD
AOBJP Q1,RFSLN2 ;SKIP COUNT WORD, DO NOTHING IF ONLY COUNT!
ADDI P2,1 ;[7146]SKIP ALSO FOR ADDRESS TO USER TABLE.
RFSLN1:
CALL @RFSLTB-.RFPSW(Q2) ;GET A WORD FOR TABLE INTO T2
UMOVEM T2,0(P2) ;[7146]STORE THE WORD
ADDI Q2,1 ;BUMP TO NEXT ENTRY
ADDI P2,1 ;[7146]BUMP ADDRESS FOR USER TABLE
AOBJN Q1,RFSLN1 ;LOOP FOR ALL ITEMS TO BE RETURNED
RFSLN2:
CAME P1,[-1] ;WAS A PSB MAPPED?
CALL CLRLFK ;YES SO RESET PSB MAPPING
CALL FUNLK ;UNLOCK FORK STRUCTURE
UMOVE T2,2 ;GET TABLE ADDRESS BACK
XCTU [HRLM Q2,.RFCNT(T2)] ;STORE COUNT OF WORDS RETURNED
JRST MRETN ;RETURN NOW
;DISPATCH TABLE FOR LONG RFSTS BLOCK ENTRIES
; CALL ROUTINE WITH T1/ PSB OFFSET
; RETURN WITH T2/ DATA WORD FOR THIS ITEM
RFSLTB: DTBDSP (RFSLSW) ;.RFPSW -- PROCESS STATUS WORD
DTBDSP (RFSLFL) ;.RFPFL -- PROCESS' PC FLAGS
DTBDSP (RFSLPC) ;.RFPPC -- PROCESS' PC
DTBDSP (RFSLSF) ;.RFSFL -- PROCESS STATUS FLAGS
RFSMAX==.-RFSLTB+.RFPSW
;PROCESS STATUS WORD
RFSLSW: MOVE T2,P1 ;GET STATUS WORD
RET ;RETURN FROM RFSLSW
;PROCESS' PC FLAGS
;NOTE: This routine returns only those flags that should be visible
;to the user. Although the microcode has stored AC blocks and PCS, if
;the process did an SFM it would not see them. Thus the JSYS does not
;return them.
RFSLFL: MOVE T2,PFL(T1) ;GET FLAGS
TXNN T2,UMODF ;IN USER MODE?
JRST [ MOVE T2,UPDL+1(T1) ;NO-- GET FLAGS FROM STACK
TXZ T2,UMODF ;BUT CLEAR USER AS FLAG
JRST .+1]
ANDX T2,EXFLBT ;RETURN ONLY THE FLAGS
RET ;RETURN FROM RFSLFL
;PROCESS' PC
RFSLPC: MOVE T2,PPC(T1) ;GET PROCESS' PC
MOVE T3,PFL(T1) ;GET FLAGS
TXNN T3,UMODF ;USER MODE?
MOVE T2,UPDL+0(T1) ;NO-- GET PC FROM STACK
TXZ T2,PCX ;CLEAR UNUSED PC BITS
RET ;RETURN FROM RFSLPC
;PROCESS STATUS FLAGS
RFSLSF: MOVX T2,0 ;ASSUME NONE
MOVE T3,FORKN(T1) ;GET JRFN FOR THIS PROCESS
JE SFEXO,(T3),RFSLS1 ;NOT EXECUTE-ONLY-- GO ON
TXO T2,RF%EXO ;EXECUTE-ONLY-- SET FLAG
RFSLS1: RET ;RETURN FROM RSFLSF
;MONITOR READ FORK STATUS
;FX/ SYSTEM FORK INDEX
; CALL MRFSTS
;RETURNS+1(ALWAYS):
;T1/ FORK STATUS
;**WARNING** IF FX POINTS TO A FORK IN A JOB DIFFERENT FROM THAT OF THE
; CURRENT FORK, YOU MUST INSURE THE FORK CANNOT BE KILLED
; OUT FROM UNDER YOU.(NOSKED IS ONE SOLUTION)
MRFSTS: CAME FX,FORKX ;SAME AS CURRENT CONTEXT?
JRST MRFST1 ;NO - GO ON
CHKINT ;INSURE UP TO DATE STATUS
CONI PI,T1 ;INSURE INTERRUPT ACCEPTED
TLNE T1,1_<SCDCHN-7> ;REQUEST STILL PENDING?
JRST .-2 ;YES - WAIT
MRFST1: SETZ T1, ;INITIALIZE T1
JE FKBLK,,MRFSTX ;IF NOT WAITING, RETURN ZERO
LOAD T2,FKSTR,(FX) ;IS WAITING, GET STATE
CAIN T2,FRZWT ;FROZEN?
JRST RFST4 ;YES
RFST5: CAIN T2,FORCTM ;FORCED TERMINATION?
JRST RFST3 ;YES
CAIN T2,HALTT ;REGULAR TERMINATION?
JRST RFST2 ;YES
CAIE T2,TRMTST ;WAITING FOR FORK TERMINATION
CAIN T2,TRMTS1 ;EITHER FLAVOR?
JRST RFST6 ;YES
CAIE T2,BLOCKM ;IN A DISMS?
CAIN T2,BLOCKW
JRST RFST7 ;YES
CAIE T2,BLOCKT ;LONG BLOCK?
CAIN T2,HIBERT ;OR HIBER JSYS?
JRST RFST7 ;YES
CAIN T2,JRET ;WAITING INDEFINITELY?
JRST RFST7 ;YES
TLO T1,.RFIO ;N.O.T.A., MUST BE I/O
JRST MRFSTX
RFST2: TLO T1,.RFHLT ;REGULAR TERMINATION GIVES 2
JRST MRFSTX
RFST6: TLO T1,.RFWAT
JRST MRFSTX
RFST3: PUSH P,T1
MOVE T1,FX ;COPY FORK INDEX
CALL SETLF3 ;MAP PSB
MOVE T2,FORCTC(T1) ;GET CHANNEL CAUSING FORCED TERM
HRRM T2,0(P) ;PUT IN RH OF STATUS WORD
CALL CLRLFK
POP P,T1
TLO T1,.RFFPT ;WITH 3 INDICATING FORCED TERM
JRST MRFSTX
RFST4: TLO T1,400000 ;FROZEN, INDICATE IN BIT 0
LOAD T2,FKINX,(FX) ;ADDRESS BREAK?
TXNE T2,ABFRZ% ; ?
JRST [ TLO T1,.RFABK ;YES, RETURN PROPER CODE
JRST MRFSTX] ; ..
TXNE T2,JTFRZ% ;NO, MAYBE JSYS TRAPPED?
TLOA T1,.RFTRP ;IT IS, FLAG IT.
CAIA
JRST MRFSTX ;AND RETURN THAT
LOAD T2,FKSTD,(FX) ;AND GET OLD STATUS
CAIN T2,-1 ;FROZEN BY A SIGNAL JFN?
JRST RFSTS1 ;YES - SAY THE JOB WANTS THE TTY
JUMPE T2,MRFSTX
JRST RFST5
RFSTS1: TLOA T1,.RFSIG ;NOTE FROZEN BY A SIGNAL JFN
RFST7: TLO T1,5 ;DISMS'ING
MRFSTX: RET ;COMMON EXIT
;START FORK VIA ENTRY VECTOR
.SFRKV::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETJFK
PUSH P,T1
UMOVE T2,2 ;Get user's start offset
CAIGE T2,0 ;Must be positive number
ERRJMP (SFRVX1,ITFRKR)
HRRZ T3,T2 ;Get position in vector
CAILE T3,1 ;Is offset 0 or 1?
CALL CHKNXS ;No-- make sure not execute-only
CALL SETLF1
MOVE T3,EVLNTH(T1) ;GET SIZE OF VECTOR IN DESTINATION FORK
CAIE T3,<JRST>B53 ;TOPS-10 style vector?
JRST SFKV01 ;No-- go on
MOVEI T3,2 ;Yes-- length is 2
CAMN T2,[XWD 1,0] ;This CCL start position?
JRST SFKV02 ;Yes-- all checking done
SFKV01: CAIL T3,1 ;REASONABLE VECTOR LENGTH?
CAIL T3,1000
JRST SFRKV2 ;NO
CAIL T2,0(T3) ;LEGAL ARG?
JRST SFRKV2 ;NO
SFKV02: MOVEM T2,FORCTC(T1) ;LEAVE FOR FOR TO START SELF
CALL CLRLFK
POP P,T1 ;RECOVER JOB HANDLE
HRRZ T2,FORKN ;GET JOB HANDLE FOR THIS FORK
CAMN T1,T2 ;SAME?
JRST [ CALL FUNLK ;YES, UNLOCK AND CONTINUE IN SAME FORK
CALL SFRKV5 ;CONSTRUCT NEW PC
MOVEM T1,0(P) ;STORE FLAGS
MOVEM T2,-1(P) ;STORE ADDRESS
JRST MRETN] ;RETURN TO IT
CALL STPFK
DMOVE T2,[MONENV ;SET NEW FLAGS TO START IN MONITOR
MSEC1,,SFRKV1]
CALLRET SFORK1
SFRKV2: CALL CLRLFK
ERRJMP(SFRVX1,ITFRKR) ;ILLEGAL RELATIVE NUMBER
;FORK STARTS HERE TO LOOK AT ENTRY VECTOR AND GO TO USER
SFRKV1: MOVE P,UPP ;SETUP STACK
CALL SFRKV5 ;CONSTRUCT NEW PC
DMOVEM T1,FFL ;SETUP FLAGS AND PC
JRST GOUSR ;RETURN TO IT
;CONSTRUCT ADDRESS FROM ENTRY VECTOR PARAMETERS
SFRKV5: MOVE T1,EVADDR ;ENTRY VECTOR ADDRESS
SETPCS T1 ;SET PCS TO SECTION NUMBER OF ENTRY VECTOR
HRRZ T2,FORCTC ;RELATIVE ADDRESS
MOVE T3,EVLNTH ;GET SIZE OF ENTRY VECTOR
CAIE T3,<JRST>B53 ;OLD STYLE?
IFSKP.
HLLZ T1,T1 ;GET SECTION OF PGM
CAIN T2,0 ;YES, 0 MEANS .JBSA
XCTU [HRR T1,.JBSA(T1)]
CAIN T2,1 ;1 MEANS .JBREN
XCTU [HRR T1,.JBREN(T1)]
HLRZ T2,FORCTC ;Get start offset (non-0 only for .JBSA)
ENDIF.
ADD T2,T1 ;COMPLETE ADDRESS
MOVX T1,USRCTX ;MAKE IT A USER PC
RET
;Start fork at specific starting address
;
;Accepts from user space:
; T1/ control flags,,fork handle
; T2/ PC flags
; T3/ PC address
.XSFRK::MCENT
UMOVE T1,T1 ;GET CONTROL FLAGS AND FORK HANDLE
XCTU [DMOVE T2,T2] ;GET PC FLAGS AND ADDRESS
CALLRET SFORK0 ;EXIT THROUGH COMMON CODE
;Start fork in starting address section
;
;Accepts from user space:
; T1/ control flags,,fork handle
; T2/ PC flags,,PC address without section
.SFORK::MCENT
UMOVE T1,T1 ;GET CONTROL FLAGS AND FORK HANDLE
XCTU [HLLZ T2,T2] ;GET PC FLAGS FROM LH OF USER'S AC2
XCTU [HRRO T3,T2] ;USE STARTING ADDRESS SECTION AND 18-BIT ADDRESS FROM USER'S AC2
CALLRET SFORK0 ;FINISH WITH COMMON ROUTINE
;SFORK0 is the worker routine for both SFORK and XSFRK jsyses.
;
;Accepts: T1/ control flags and fork handle
; T2/ PC flags
; T3/ PC address, -1 in left half means use s.a. section
SFORK0: TRVAR <CFLAGS,PCFLGS,PCADDR>
MOVEM T1,CFLAGS ;SAVE ARGS
MOVEM T2,PCFLGS
MOVEM T3,PCADDR
TXNE T1,^-<SF%CON!SF%PRH> ;ANY UNKNOWN BITS SET?
ITERR (DECRSV) ;YES-- GIVE ERROR
CALL FLOCK ;LOCK THE FORK STRUCTURE
HRRZ T1,CFLAGS ;GET FORK HANDLE
CALL SETJFK
MOVE T2,CFLAGS ;GET FLAGS/PROCESS HANDLE FROM USER
TXNE T2,SF%CON ;CONTINUE PROCESS ONLY?
JRST [ PUSH P,T1 ;SAVE JOB-WIDE HANDLE
OPSTR <SKIPN>,SFSRT,(T1) ;HAS FORK BEEN STARTED?
ITERR (FRKHX5,<CALL FUNLK>) ;NO, UNLOCK AND GIVE ERROR
HRRZ FX,SYSFK(T1) ;GET SYSTEM HANDLE
CALL MRFSTS ;GET STATUS OF FORK
LOAD T2,RF%STS,T1 ;GET STATUS
POP P,T1 ;RESTORE HANDLE
CAIE T2,.RFHLT ;HALTED?
CAIN T2,.RFFPT ;OR FORCED TERMINATION?
SKIPA ;YES
JRST CLFLK0 ;NO. RETURN NOW
CALL STPFK ;YES. STOP IT BEFORE STARTING IT
JRST SFORK2] ;AND PROCEED
;PROCESS TO BE STARTED-- MUST SETUP CONTEXT
CALL CHKNXS ;Check for execute-only
CALL STPFK ;STOP FORK
MOVE T3,PCADDR ;IF XSFRK JSYS, CALLER SUPPLIED SECTION
SKIPGE PCADDR
HLL T3,EVADDR(T1) ;IF SFORK JSYS, USE STARTING ADDRESS SECTION
HLLZ T2,PCFLGS ;GET PC FLAGS
TLZ T2,(UIOF+2037B17) ;USER I/O, CALFRMMON, IDX AND IND OFF
TXO T2,USRCTX ;SET USER MODE FLAGS AND AC BLOCKS
CALLRET SFORK1 ;DO COMMON CODE
;COMMON CODE FRO SFRKV%, SFORK%, XSFRK%, MSFRK%
; T1/ OFFSET ADDRESS TO OBJECT FORK PSB
; T2/ NEW FLAGS
; T3/ NEW PC
SFORK1: SETOM SLOWF(T1) ;NORMALIZE FLAG
PUSH P,PFL(T1)
MOVEM T2,PFL(T1) ;PUT FLAGS
MOVEM T3,PPC(T1) ;AND PC
HRRZ T2,FORKN(T1) ;GET JOB FORK NUMBER
SETONE SFSRT,(T2) ;FLAG THAT FORK HAS BEEN STARTED
POP P,T2 ;OLD FLAGS
TXNE T2,UMODF ;FORK WAS IN USER MODE?
JRST SFORK2 ;YES, ACS ALREADY IN RIGHT PLACE
HRRZ T2,ACBAS(T1)
CAIGE T2,<UACB>B39 ;IN NESTED MONITOR CALL?
JRST SFORK2 ;NO, ACS ALREADY IN RIGHT PLACE
MOVSI T2,UACB(T1) ;MUST MOVE ACS FROM AC STACK
HRRI T2,UAC(T1) ; TO SAVED BLOCK 1
BLT T2,UAC+17(T1)
SFORK2: SETZRO FKSTD,(FX) ;CLEAR LH IN CASE FROZEN
SETZM PIOLDS(T1) ;SET PRE-FREEZE STATE TO RUNNING
PUSH P,T1 ;SAVE PSB POINTER
HLLZ T2,PSIBIP(T1) ;PASS FORK'S CURRENT INTERRUPT STATE
HRRZ T1,FORKN(T1) ;GET THIS FORKS JOB ID
HRRZ T1,SYSFK(T1) ;GET SYSTEM ID
PUSH P,T1 ;SAVE FORK
PUSH P,T2 ;SAVE PSB STATE
OKSKED ;MUST DO THIS IN CASE JSBSTF OR GOKFRE BLOCK
CALL JSBSTF ;GO DO ANY DEALLOCATIONS
POP P,T2 ;RESTORE T2
POP P,T1 ;GET FORK AGAIN
CALL GOKFRE ;FREE GETOK REQUESTS
CALL SUSFK ;MAKE SURE FORK STILL SUSPENDED
POP P,T1 ;RECOVER PSB POINTER
JN FKFRZ,(FX),SFORK3 ;IF FROZEN, DON'T START FORK
PUSH P,T1
CALL UNBLK1 ;UNBLOCK IT
POP P,T1
CALL CLRSFK ;NOW CLEAR SUSPENSION
SFORK3: MOVE T2,FORKN(T1) ;FIND THAT FORK'S CTTY
ADD T2,T1 ;GET OFFSET (T1 MIGHT CONTAIN MORE THAN 18 BITS)
OKSKED ;MATCH NOSKED IN STPFK (SUSFK)
LOAD T1,FRKTTY,(T2) ;GET CONTROLLING TERMINAL
CALL UPDTI
CALLRET CLFRET
;MONITOR SFORK, CAN START IN MONITOR SPACE
; T1/ FORK HANDLE
; T2/ EXTENDED START ADDRESS
.MSFRK::MCENT
MOVE 3,0(P) ;THIS IS LEGAL IF CALLED FROM
MOVE 4,CAPENB ;MONITOR MODE, OR IF SC%WHL OR
TLNE 3,(UMODF) ;OPERATOR CAPABILITIES ARE PRESENT
TXNE 4,SC%WHL+SC%OPR ;TEST CAPS
JRST .+2
ITERR(CAPX1) ;USER LACKS CAPABILITY
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETJFK
CALL STPFK ;SAME STUFF AS SFORK
MOVEI T2,MFRKWD ;GET PRIORITY WORD FOR MONITOR FORKS
SKIPN JOBSKD ;DOES JOB HAVE PRIORITY?
SKIPE JOBBIT(T1) ;NO. DOES THE PROCESS ALREADY HAVE SOME?
SKIPA ;YES. DON'T SET IT
MOVEM T2,JOBBIT(T1) ;DOESN'T
MOVX T2,MONENV ;NEW FLAGS
UMOVE T3,T2 ;NEW PC
CALLRET SFORK1
;STOP FORK, USED BY SEVERAL FORK JSYS'S
STPFK: CALL SKIIF ;JOB FORK NUMBER IN 1, IS INFERIOR?
JRST FRKE2 ;NO
STPFK1: MOVE 6,1
HRRZ 7,SYSFK(6)
CAMN 7,FORKX ;THIS SAME FORK?
JRST FRKE1 ;YES, ILLEGAL
CALL SETLF1 ;MAP PSB
CALLRET SUSFK ;SUSPEND FORK
;READ/SET FORK AC'S
.RFACS::MCENT
XCTU [MOVES 0(2)] ;Test existence/writeability before NOSKED
XCTU [MOVES 17(2)] ; of whole block
CALL FACS
MOVEI T1,20 ;ALL ACS
EXCH T2,T3 ;GET ARGS IN RIGHT ORDER
CALL BLTMU1 ;DO BLT TO USER
JRST FACSR ;RETURN
.SFACS::MCENT
XCTU [SKIP 0(2)] ;Test existnece before NOSKED
XCTU [SKIP 17(2)] ; of whole block
CALL FACS
MOVEI T1,20 ;MOVE ACS
CALL BLTUM1 ;MOVE ACS TO MONITOR
; JRST FACSR ;RETURN
FACSR: OKSKED
JRST CLFRET
;COMMON AC ROUTINE
FACS: CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETJFK ;ONE FORK ONLY
CALL SKIIF ;AND IT MUST BE INFERIOR
JRST FRKE2 ;NOT INFERIOR
CALL CHKNXS ;Check for execute-only process
MOVE 6,1
HRRZ 7,SYSFK(6)
CALL SETLF1 ;MAP PSB
NOSKED
TMNN FKBLK ;FORK BLOCKED?
ERRJMP(FRKHX4,FACSE) ;NO
MOVE T2,PFL(T1) ;GET CURRENT PC
HRRZ T3,ACBAS(T1) ;GET AC STACK PTR
TXNN 2,UMODF ;IN USER MODE?
CAIGE 3,<UACB>B39 ;OR TOP-LEVEL MON CALL?
SKIPA 3,[UAC] ;YES, ACS IN SAVED BLOCK 1
MOVEI 3,UACB ;NO, ACS IN TOP OF AC STACK
ADDI 3,0(1) ;ADJUST INTO OTHER PSB
XCTU [MOVE 2,2] ;GET ADDRESS FROM USER
RET
FACSE: OKSKED
PUSH P,1 ;SAVE THE ERROR CODE
CALL CLRLFK
POP P,1 ;RESTORE ERROR CODE
JRST ITFRKR
;HALT FORK
.HFORK::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
HRRZ 1,1
CAIN 1,-4 ;ALL INFERIORS?
JRST [ MOVX T2,<CALL HFORK1> ;ROUTINE TO EXECUTE
CALL MAPFKH ;MAP OVER ALL FORKS
NOP ;WON'T BLOCK
JRST HFORK4]
CALL SETJFK ;NO, SOME ONE FORK
CAMN 1,FORKN ;SELF?
ERRJMP(HFRKX1,EFRKR) ;YES, RETURN ERROR
CALL SKIIF ;IS DESIGNATED FORK AN INFERIOR?
JRST FRKE2 ;NO, ILLEGAL
CALL HFORK1 ;DO THE WORK
HFORK4: CALL FUNLK
JRST MRETN
HFORK1: PUSH P,1 ;SAVE FORK NUMBER
CALL STPFK ;STOP THE FORK
MOVEI 2,HALTT
IFQN. FKFRZ,(FX) ;FROZEN?
STOR T2,FKSTD,(FX) ;YES. UPDATE PRE-FREEZE STATE
MOVEM T2,PIOLDS(1)
ELSE.
STOR T2,FKSTX,(FX) ;TERMINATED STATE
CALL CLRSFK ; BUT INTERRUPTIBLE
ENDIF.
HFORK2: MOVE 1,0(P)
ADD 1,SUPERP ;GET SUPERIOR
LDB 1,1
HRRZ 1,SYSFK(1) ;GET SYSTEM INDEX
CALL SUPUB0 ;WAKEUP SUPERIOR IF NECESSARY
HFORK3: MOVE T1,0(P)
OKSKED ;MATCH NOSKED IN STPFK (SUSFK)
CALL CLRLFK
POP P,T3 ;FORKN OF OTHER FORK
LOAD T1,FRKTTY,(T3) ;GET CONTROLLING TERMINAL
CALLRET UPDTI ;UPDATE TERM INT WORD
;CALL FROM TTY SERVICE TO RESOLVE FORK CONFLICT
TTFRKT::SKIPGE FKPT(1) ;FORK STILL EXISTS?
RET ;NO
LOAD 2,FKSTR,(T1) ;GET ITS STATUS
CAIE 2,TCITST ;STILL WAITING FOR TTY?
RET ;NO
MOVSI 3,-NUFKS ;SETUP TO SEARCH FOR FORK
SKIPL 2,SYSFK(3) ;THIS SLOT IN USE?
CAIE 1,0(2) ;AND HAS CORRECT FORKX?
AOBJN 3,.-2 ;NO
JUMPGE 3,R ;RETURN IF NOT FOUND IN THIS JOB
PUSH P,A ;SAVE FORK HANDLE IN CASE
MOVEI 1,0(3) ;FORKN OF OTHER FORK
CALL SKIIF ;IS IT INFERIOR
JRST [ MOVEI T1,^D1000 ;NO, WAIT AWHILE
DISMS
POP P,A ;GET BACK HANDLE OF THE FORK
JRST TTFRKT] ;TRY AGAIN
POP P,0(P) ;CLEAN UP STACK
SAVEPQ ;SAVE ALL PERMANENT REGS
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL HFORK1 ;HALT THE OTHER GUY
CALLRET FUNLK ;UNLOCK AND RETURN
;WAIT FOR FORK TO TERMINATE
;TRMTST IS USED TO TEST THE STATE OF THE FORK BASED ON ITS SYSTEM-WIDE
;FORK-ID. **NOTE WELL** THAT ANY SCHEDULER TEST OF THIS KIND MUST USE
;THE SUPERIOR'S FKSPL AND BE PREPARED TO RE-EVALUATE THE JOB-WIDE HANDLE IN
;CASE A SPLICE OCCURS. A SPLICE CAUSES THE FORK TO BECOME ANOTHER. DO NOT
;FORGET TO TEST FKSPL IN THE SCHEDULER TEST AS WELL.
.WFORK::MCENT
CAIN 1,-4 ;ALL INFERIORS?
JRST WFORKA ;YES
CALL FLOCK ;LOCK THE FORK STRUCTURE
MOVE T2,FORKX
SETZRO FKSPL,(T2) ;RESET INFERIOR SPLICED EVENT.
CALL SETJFK ;ONE FORK, GET ITS JOB HANDLE
HRLZ 1,SYSFK(1) ;SETUP TEST ON FORK INDEX
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
HRRI 1,TRMTST
MOVSI T2,FHV1 ;LOW BLOCK PRIORITY
HDISMS
MOVE T1,FORKX
JE FKSPL,(T1),MRETN ;NOT DUE TO INFERIOR SPLICE, A GENUINE RETURN
UMOVE T1,T1
JRST .WFORK ;RE-EVALUATE FORK HANDLE AND DO AGAIN.
WFORKA::MOVSI D,-NLFKS+1 ;NUMBER TO DO
MOVE C,FKPTAB ;GET POINTER TO HANDLES
WFORK3: ILDB A,C ;GET NEXT HANDLE
CAIN A,-1 ;ASSIGNED?
JRST WFORK4 ;NO. LOOP TO NEXT THEN
MOVEI A,.FHSLF+1(D) ;GET NEXT HANDLE
RFSTS ;GET STATUS
CAMN A,[-1] ;IS IT DELETED?
JRST WFORK4 ;YES. GO DO NEXT THEN
LOAD A,RF%STS,A ;GET STATUS
CAIE A,.RFHLT ;HALTED?
CAIN A,.RFFPT ;NO. ERROR ABORT?
JRST MRETN ;YES. RETURN GOOD
WFORK4: AOBJN D,WFORK3 ;NO. LOOK AT ALL LOCALS
MOVEI A,TRMTS1 ;SETUP TEST TO WAIT UNTIL CHANGED
MOVSI T2,FHV1 ;LOW BLOCK PRIORITY
HDISMS
JRST MRETN
RESCD
TRMTST::
JN FKSPL,(FX),1(T4) ;GET OUT IF AN INFERIOR HAS SPLICED.
JE FKBL%,(T1),0(T4) ;DON'T WAKE UP IF FORK IS BLOCKED
LOAD 2,FKSTR,(1) ;GET SCHEDULER TEST
CAIE 2,HALTT ;WAITING BECAUSE TERMINATION?
CAIN 2,FORCTM ;OR FORCED TERM?
JRST 1(4) ;YES
CAIE T2,FRZWT ;FROZEN?
JRST 0(4) ;NO WAIT
LOAD 2,FKSTD,(1) ;GET PRE FREEZE STATE
CAIE 2,HALTT ;HALTED?
CAIN 2,FORCTM ;OR FORCED TERM?
JRST 1(4) ;YES
; JRST TRMTS1 ;WAIT LONGER
TRMTS1::JRST 0(4)
SWAPCD
;SUSPEND FORK SO IT CAN BE DIDDLED
; RETURNS NOSKED SO THAT CALLER CAN FINISH CHANGING STATE RACE-FREE
SUSFK: SAVEAC <T1,T2>
CAMN 7,FORKX
BUG.(HLT,FRKSLF,FORK,SOFT,<SUSFK - Given self as argument>,,<
Cause: Some routine in the monitor has erroneously tried to suspend
itself with SUSFK.
>)
SUSF6: NOSKED
JE FKBLK,,SUSF4 ;IS FORK BLOCKED NOW?
LOAD 2,FKSTR,(FX) ;YES. GET WAITING STATUS
CAIE 2,SUSWT ;ALREADY SUSPENDED OR FROZEN?
CAIN 2,FRZWT
RET
CAIN 2,TCITST ;WAS IN TTYIN WAIT?
JRST [ LOAD 2,FKSTD,(FX) ;YES, GET TERMINAL NUMBER
CALL TTCLFK ;INDICATE NO FORK WAITING
JRST .+1]
SUSF5: SETONE <FKPS0,FKSUS>,(FX) ;SUSPEND FORK REQUEST BIT FOR PSI
MOVEI 2,0(7)
CALL PSIR4 ;INTERRUPT THE FORK
OKSKED
MOVSI 1,0(7) ;SETUP SCHEDULER TEST TO WAIT
HRRI 1,SUSFKT ;UNTIL FORK HAS SUSPENDED ITSELF
MOVSI T2,FHV5 ;HIGHER BLOCK PRIORITY
HDISMS
JRST SUSF6 ;NOW CHECK IT AGAIN
;Here if fork is not blocked now. Request interrupt and loop back to check
;status
SUSF4: JE FKINX,(FX),SUSF5 ;TRANSITIONAL STATE?
SETONE <FKPS0,FKSUS>,(FX) ;YES. REQUEST INTERRUPT FOR SUSPENSION
MOVEI 2,0(7)
CALL PSIR4
OKSKED ;THEN WAIT TO BE SURE IT WAS RECEIVED
MOVEI 1,^D50
DISMS
JRST SUSF6 ;AND CHECK AGAIN
;SCHEDULER TEST FOR SUSPENSION
RESCD
SUSFKT::JE FKBL%,(T1),0(T4) ;DON'T WAKE UP IF FORK ISN'T BLOCKED
LOAD 2,FKSTR,(1) ;GET SCHEDULER TEST
CAIE 2,SUSWT ;SUSPENSION?
CAIN 2,FRZWT
JRST 1(4)
JRST 0(4)
SWAPCD
;CLEAR FORK WHICH HAD BEEN SUSPENDED
CLRSFK: SETZRO FKPS1,(FX) ;CLEAR "PSI STARTING" STATE
PUSH P,1
SETZ 1,
MOVE 2,FX
CALL PSIRQB ;REQUEST TO RECHECK PENDING PSI'S
POP P,1
RET
;MAP ALL IMMEDIATE INFERIORS OF FORK IN 1
; EXECUTES +1 FOR EACH FORK
; RETURNS +2
MAPINF: ADD 1,INFERP
MAPIF1: LDB 1,1
JUMPE 1,MAPIF2
HRLM 1,0(P)
HRRZ T2,0(P) ;GET CALLER PC
XCT 0(T2) ;EXECUTE INSTRUCTION AT CALL+1
HLRZ 1,0(P)
ADD 1,PARALP
JRST MAPIF1
MAPIF2: XHLLI 2,20 ;FIND CURRENT SECTION
HLLM 2,0(P) ;RESTORE IT FOR RETSKP
JRST RSKP ;RETURN
;GET FORK STRUCTURE
;RETURNS A COPY OF THE JOB FORK STRUCTURE FROM A SPECIFIED
;STARTING POINT DOWNWARD.
;CALL
;1/ HANDLE ON INITIAL FORK
;2/ FLAGS - GF%GFH TO GET RELATIVE FORK HANDLES, GF%GFS TO DO RFSTS
;3/ -LENGTH,,START ADDR OF USER AREA TO RETURN FORK STRUCTURE IN
;EACH FORK IS REPRESENTED IN THE STRUCTURE BY A 3 WORD BLOCK:
;WD0: PARALLEL PTR,,INFERIOR PTR
;WD1: SUPERIOR PTR,,RELATIVE FORK HANDLE(IF REQUESTED)
;WD3: STATUS WORD (IF REQUESTED - ELSE -1)
;NOTE: EVEN IF GF%GFH IS OFF,PREVIOUSLY ACQUIRED FORK HANDLES WILL BE
; GIVEN FOR FORKS APPEARING IN THE RETURNED STRUCTURE.
;AC USAGE
;GLOBALS
;Q1/ REMAINING FREE AREA,,NEXT FREE CELL (USER ADDR)
;Q2/ GF%GFH!GF%GFS - COPIES OF UAC2; B17 - LOCAL FLAG
; FOR RFH SPACE EXHAUSTED. RH CONTAINS JRFN OF STARTING FORK
;RECURSIVE VARIABLES
;P1/ CURRENT JRFN,,USER ADDR OF CORRESPONDING BLOCK
.GFRKS::MCENT
HRRZ T1,T1 ;IGNORE LH T1
MOVE Q1,T3 ;INITIALIZE FREE POINTER
SUB Q1,BITS+^D17 ;SUBTRACT [1,,0] FOR CORRECT COUNTING
MOVSI Q2,(GF%GFH!GF%GFS) ;COPY OPTIONAL COMMAND BITS
AND Q2,T2 ; ...
MOVE T2,T1 ;COPY SPECIFIED HANDLE
CALL FLOCK ;FREEZE FORK DATABASE
CALL STJFKR ;CONVERT RFH IN T1 TO JRFN
JRST [CAIE T2,.FHTOP ;TOP FORK?
JRST EFRKR ;NO - ERROR CODE STILL IN T1
HLRZ T1,FORKN ;YES - UNPRIVLEDGED REF TO TOP FORK
TLZ Q2,(GF%GFH) ;PROHIBIT ACQUISITION OF HANDLES
JRST .+1]
HRR Q2,T1 ;SET STARTING FORK JRFN
HRLZ P1,T1 ;SET INITIAL CURRENT FORK
PUSH P,[0] ;DUMMY UP SUPERIOR
CALL GFRKS1 ;WALK THE TREE
POP P,(P) ;SCRAP DUMMY SUPERIOR
CALL FUNLK ;RELEASE FORK LOCK
TLNN Q2,(1B17) ;WERE THERE ENOUGH RFH?
SMRETN ;YES - SKIP RETURN
RETERR(FRKHX6) ;NO - RETURN ERROR CODE
;PREORDER TRANSITION OF A N-ARY TREE
GFRKS1: HLRZ T1,P1 ;GET CURRENT JRFN
HRRZ T2,Q1 ;SAVE NEW BASE ADDR
ADD Q1,BHC+2 ;ALLOCATE NEW BLOCK
AOBJP Q1,[MOVEI T1,GFKSX1 ;SPACE EXHAUSTED
JRST EFRKR] ;ERROR RETURN
XCTU [SETZM (T2)] ;CLEAR OUT NEW BLOCK
XCTU [SETZM 1(T2)] ; ...
XCTU [SETOM 2(T2)] ; ...
XCTU [HRLM P1,(T2)] ;STORE PARALLEL POINTER
HRR P1,T2 ;UPDATE CURRENT POINTER
MOVE T2,-1(P) ;GET SUPERIOR POINTER
HRRZ P2,P1 ;GET ADDRESS ONLY
XCTU [HRLM T2,1(P2)] ;STORE SUPERIOR POINTER
CALL JFKRFH ;SEE IF A HANDLE ALREADY EXISTS
XCTU [HRRM T2,1(P2)] ;RETURN HANDLE OR ZERO
TLNN Q2,(GF%GFH) ;ASSIGN RFH?
JRST GFRKS2 ;NO - GO ON
CALL SKIIF ;IS JRFN IN T1 INFERIOR?
JRST GFRKS2 ;NO - DONT GIVE OUT HANDLE
CALL GFKH ;JRFN STILL IN T1, RETURNS RFH IN T1
TLOA Q2,(1B17) ;ERROR RETURN - RFH EXHAUSTED
XCTU [HRRM T1,1(P2)] ;RETURN RELATIVE FORK HANDLE
GFRKS2: TLNN Q2,(GF%GFS) ;FORK STATUS REQUESTED?
JRST GFRKS3 ;NO - GO ON TO INFERIORS
HLRZ T1,P1 ;YES - GET JRFN
HRRZ FX,SYSFK(T1) ;GET SYSTEM FORK INDEX
CALL MRFSTS ;DO RFSTS
UMOVEM T1,2(P2) ;STORE STATUS.
GFRKS3: HLRZ T1,P1 ;GET JRFN AGAIN
ADD T1,INFERP ;CHECK FOR INFERIORS
LDB T1,T1 ; ...
JUMPE T1,GFRKS4 ;NONE - GO ON TO PARALLEL
PUSH P,P1 ;SAVE RECURSIVE VARIABLES
HRLZ P1,T1 ;GET INF JRFN & CLEAR PAR. PTR
CALL GFRKS1 ;DO ALL INFERIORS
HRRZ P2,(P) ;GET CURRENT BLOCK BACK
XCTU [HRRM P1,(P2)] ;STORE INFERIOR LIST
POP P,P1 ;RESTORE RECURSIVE VARS
GFRKS4: HLRZ T1,P1 ;GET CURRENT JRFN BACK
CAIN T1,(Q2) ;TOP SPECIFIED FORK?
RET ;YES - DONT DO PARALLEL
ADD T1,PARALP ;SEE IF ANY PARALLEL
LDB T1,T1 ; ...
JUMPE T1,R ;NONE - DONE WITH THIS LEVEL
HRL P1,T1 ;LOOP FOR THIS LEVEL
JRST GFRKS1 ; ...
;ROUTINE TO MAP A JRFN TO RFH FROM CURRENT FORK
;T1/ JRFN
; CALL JFKRFH
;RETURNS+1(ALWAYS):
;T1/ JRFN (UNCHANGED)
;T2/ RFH OR 0 IF NONE
;T3/ BYTE POINTER TO FKTAB ENTRY CORRESPONDING TO RFH
JFKRFH: CAIGE T1,NUFKS ;REASONABLE JRFN?
JRST JFKRH1 ;YES - MAP IT
BUG.(CHK,ILJRFN,FORK,SOFT,<JFKRFH - Bad JRFN, ignored>,,<
Cause: Routine JFKRFH was erroneously called with a fork number which
is out of range. The correct range is a value less than NUFKS.
JFKRFH changes a fork number into a fork handle.
Action: If this BUG persists, make it dumpable and submit an SPR with the
dump and a copy of MONITR.EXE. If possible, include any known
method for reproducing the problem and/or the state of the system
at the time the BUG was observed.
>)
JRST JFKRH3 ;ACT AS IF NOT FOUND
JFKRH1: MOVEI T2,.FHSLF ;CHECK IF SELF FIRST
HRRZ T3,FORKN ; ...
CAMN T1,T3 ;SELF?
RET ;YES - RETURN
MOVE T4,[-NLFKS+1,,1] ;SETUP COUNT
MOVE T3,FKPTAB ;SETUP INIITAL POINTER
JFKRH2: ILDB T2,T3 ;GET JRFN CORRESPONDING TO RFH IN T4
CAIN T2,(T1) ;MATCH?
JRST JFKRH4 ;YES - RETURN RFH
AOBJN T4,JFKRH2 ;NO - LOOP
JFKRH3: SETZ T2, ;NO MATCH - RETURN 0
RET
JFKRH4: MOVEI T2,400000(T4) ;BUILD CORRESPONDING RFH
RET
;ROUTINE TO MAP A SINGLE LOCAL RFH TO A JRFN
;NOTE THE DIFFERENCE BETWEEN RFHJFK AND SETJFK/STJFKR.
;RFHJFK ALLOWS ONLY LOCAL FORK HANDLES AND IGNORES THE ISSUE
;OF HAVING A HANDLE ON A PREVIOUSLY KILLED FORK. RFHJFK SHOULD
;ONLY BE USED WHEN THE CALLER IS PREPARED TO HANDLE THIS
;CASE (RFSTS, RFRKH FOR EXAMPLE). SETJFK/STJFKR ARE INTENDED FOR
;MOST USES. THEY ALLOW ALL NON MULTIPLE HANDLES AND SUCCEED ONLY
;IF THERE IS A LIVE FORK UNDER THE GIVEN HANDLE.
;T1/ RFH
; CALL RFHJFK
;RETURNS+1(ERROR):
;T1/ ERROR CODE
;RETURNS+2(SUCCESS):
;T1/ JRFN
;ALL OTHER ACS UNCHANGED
RFHJFK: CAIL T1,400001 ;REASONABLE LOCAL HANDLE?
CAIL T1,400000+NLFKS ; ...
JRST FRKESR ;NO - FIGURE OUT ERROR CODE
TRZ T1,400000 ;YES - GET LOCAL INDEX
PUSH P,T2 ;BE TRANSPARENT WRT ACS
IDIVI T1,2 ;BUILD BYTE POINTER
ADD T1,FKPTAB(T2) ; ...
POP P,T2 ;RESTORE T2
LDB T1,T1 ;GET JRFN
CAIN T1,-1 ;IN USE?
JRST FRKE1R ;NO, GIVE ERROR RETURN
RETSKP ;SUCCESS RETURN
;GET FORK HANDLE.
;CALL WITH T1/ HANDLE ON KNOWING FORK, T2/ HANDLE IN
; KNOWING FORK ON DESIRED FORK
;
;RETURNS A (POSSIBLY NEW) HANDLE IN T1 USABLE BY CALLER.
.GFRKH:: MCENT ;ESTABLISH CONTEXT
CALL FLOCK ;LOCK FORK STRUCTURE
ANDI T2,377777
CAIL T2,0 ;NEGATIVE IS ILLEGAL
CAIL T2,NLFKS ;A LEGIT FORK HANDLE?
ERRJMP (GFRKX1,EFRKR) ;NO. FAIL RETURN NONSKIP
CALL SETLF0 ;OK, SET UP THE PSB OF KNOWER
CAIE T2,0 ;WANT "SELF" OF KNOWER?
IFSKP.
MOVE T2,FORKN(T1) ;OH YEAH, COVER THIS SPECIAL CASE
ELSE. ;NO, NORMAL CASE
IDIVI T2,2 ;BUILD A POINTER TO JOB F INDEX
ADD T2,FKPTAB(T3) ; IN THE MAPPED PSB
TLO T2,1 ;OFFSET TO MAPPED PSB BY INDEXING PNTR
LDB T2,T2 ;GET THE DESIRED FORK'S JOB FORK INDEX
ENDIF.
CAIGE T2,NUFKS ;MAKE SURE IT'S ASSIGNED
SKIPGE SYSFK(T2) ;FORK STILL EXIST?
ERRJMP (GFRKX1,EFRKRC) ;NO, RETURN ERROR
MOVEI T1,(T2) ;OK, HERE'S THE DESIRED JOB FORK INDEX
CALL GFKH ;GET A FORK HANDLE IN THIS FORK FOR IT.
ERRJMP (FRKHX6,EFRKRC) ;COULDN'T. NO SPACE LEFT.
UMOVEM T1,T1 ;OK. RETURN H-PRIME TO USER.
CALL CLRLFK
CALL FUNLK ;UNLOCK FORK STRUCTURE
SMRETN ;AND SKIP RETURN TO HIM.
;RELEASE FORK HANDLE JSYS
;CALL
;1/ FORK HANDLE TO BE RELEASED
; RFRKH
;RETURNS+1:
;1/ ERROR CODE
;RETURNS+2:
;SUCCESS - AC UNCHANGED
.RFRKH::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CAMN A,[-1] ;WANT TO DO ALL OF THEM?
JRST RFRKH2 ;YES. GO DO IT THEN
CALL RFRKH0 ;GO DO THE WORK
JRST EFRKR ;FOUND AN ERROR. GO REPORT IT
CALL FUNLK ;FREE THE STRUCTURE
SMRETN ;AND RETURN GOOD
;INTERNAL ROUTINE TO RELEASE A FORK HANDLE
;ACCEPTS: A/ PROCESS RELATIVE FORK HANDLE
;RETURNS: +1 / CAN'T RELEASE HANDLE. REASON IN A
; +2/ HANDLE RELEASED AND ALL RELEVANT JOB FORK
; TABLES CLEANED UP
;WARNING: MUST BE CALLED WITH JOB FORK LOCK LOCKED
RFRKH0: CALL RFHJFK ;MAP RFH IN T1 TO JRFN
RET ;ERROR. CODE IN A
SKIPGE SYSFK(A) ;NOW ASSIGNED?
JRST RFRKH1 ;NO,IS OKAY TO DO IT.
LOAD B,FKHCNT,(A) ;IS INFERIOR. SEE ABOUT COUNT
CAIG B,1 ;NOW BEING SHARED?
JRST [ MOVEI A,FRKHX1 ;CAN'T RELEASE IT
RET] ;SO RETURN AN ERROR
RFRKH1: CALL DASFKH ;DEASSIGN FORK HANDLE
RETSKP ;GOOD RETURN
;ROUTINE TO RELEASE ALL HANDLES
RFRKH2: MOVE D,[-NLFKS+1,,1]
MOVE C,FKPTAB ;BEGINNING POINTER
RFRKH3: ILDB A,C ;GET POINTER
CAIN A,-1 ;IN USE?
JRST RFRKH4 ;NO
MOVEI A,.FHSLF(D) ;YES. GET RELATIVE HANDLE
PUSH P,C ;SAVE POINTER
PUSH P,D ;SAVE COUNTER
CALL RFRKH0 ;GO RELEASE IT
JFCL ;DON'T CARE
POP P,D
POP P,C ;RESTORE REGISTERS
RFRKH4: AOBJN D,RFRKH3 ;DO ALL HANDLES
CALL FUNLK ;FREE THE STRUCTURE
SMRETN ;AND DONE
;PERFORM FORK CONTROL FUNCTION FOR EACH FORK OF MULTIPLE FORK
;HANDLE (I.E. MAP A FUNCTION ONTO ALL FORKS)
; 1/ USER FORK HANDLE (SINGLE OR MULTIPLE)
; 2/ INSTRUCTION TO DO FOR EACH FORK
; CALL MAPFKH
; ;EXECUTE INSTRUCTION WITH JOB-WIDE
; HANDE IN T1
;RETURNS: +1 COROUTINE NEEDS TO BLOCK
; +2 ALL DONE
MAPFKH::CAIL 1,-5 ;IS IT A MULTIPLE FORK DESIGNATOR?
CAILE 1,-3
JRST [ PUSH P,T2 ;SAVE INST
CALL SETJFK ;GET HANDLE
POP P,T2 ;GET INST
XCT T2 ;DO IT
RETSKP ;DONE
RET] ;BLOCK
PUSH P,P6 ;SAVE FRAME POINTER
MOVE P6,P ;ESTABLISH FRAME
PUSH P,T2 ;SAVE INSTRUCTION
CALL MAPFT+5(1) ;DISPATCH TO APPROPRIATE FUNCTION
NOP ;NEVER GETS HERE
MOVE P,P6 ;RESTORE STACK
POP P,P6 ;RESTORE REG
RETSKP ;AND DONE
MAPFT: JRST MAPF5 ;-5, ALL FORKS IN JOB
JRST MAPF4 ;-4, ALL INFERIORS
JRST MAPF3 ;-3, SELF AND ALL INFERIORS
MAPF3: HRRZ 1,FORKN ;SELF
MAPF51: PUSH P,1
XCT 1(P6) ;DO INSTRUCTION
SKIPA ;DONE
JRST MAPBLW ;NEEDS TO BLOCK
POP P,1
MAPF41: ADD 1,INFERP ;DO INFERIORS
MAPF42: LDB 1,1 ;GET NEXT IN LIST
JUMPE 1,MAPF43 ;END OF LIST, RETURN AND SKIP INSTR
HRLM 1,0(P) ;SAVE THIS FORK NUMBER
CALL MAPF41 ;DO INFERIORS OF IT
BUG.(HLT,MAP41F,FORK,SOFT,<MAPF41 failed to skip>,,<
Cause: The MAPFKH routine calls itself recursively in order to
find every fork in a specified tree. For each fork found, the
instruction following the call to MAPFKH is executed. MAPFKH
finally skip-returns in order not to fall into that coinstruction
at .+1. The recursive calls skip-return too, merely because they
fall through the same RETSKP instruction.
The MAP41F BUGHLT should never happen, and is merely a placeholder
for the impossible non-skip return from the recursive call to
MAPFKH.
>)
HLRZ 1,0(P) ;GET FORK NUMBER BACK
XCT 1(P6) ;DO THIS FORK
SKIPA ;DONE
JRST MAPBLW ;NEEDS TO BLOCK
HLRZ 1,0(P)
ADD 1,PARALP ;POINT TO NEXT IN LIST
JRST MAPF42
MAPF43: XHLLI T2,20 ;GET CURRENT SECTION
HLLM T2,0(P)
RETSKP
MAPF4: HRRZ 1,FORKN ;GET SELF
JRST MAPF41 ;DO INFERIORS
MAPF5: HLRZ 1,FORKN ;GET TOP
JRST MAPF51 ;DO THAT AND INFERIORS
;COROUTINE INDICATED TO BLOCK
MAPBLW: MOVE P,P6 ;GET PROPER FRAME
POP P,P6 ;RESTORE P6
RET ;AND INDICATE BLOCK UP
;FORK RELATIVITY TESTS
;SKIP IF FORK IN 1 IS SELF OR INFERIOR TO SELF
SKIIF:: PUSH P,2
HRRZ 2,FORKN ;GET SELF
CALL SKIIFA ;DO TEST
JRST PB2 ;RETURN NO SKIP
SKISF2: POP P,2
JRST RSKP
;SKIP IF FORK IN 1 IS SAME AS OR INFERIOR TO FORK IN 2
SKIIFA::HRLM 2,0(P) ;SAVE FORK NUMBER
SKIIF4: CAIN 1,0(2) ;SAME?
JRST SKIIF1 ;YES
ADD 2,INFERP ;NO, GET POINTER TO INFERIOR LIST
SKIIF2: LDB 2,2 ;NEXT INFERIOR
JUMPE 2,SKIIF6 ;END OF LIST
CALL SKIIFA ;IS THIS FORK OR INFERIOR?
JRST SKIIF5 ;NO
SKIIF1: HLRZ 2,0(P) ;SUCCEEDS, RETURN +2
XHLLI T4,20 ;FIND CURRENT SECTION
HLLM T4,0(P) ;SET IN RETURN
RETSKP ;AND RETURN +2
SKIIF6: HLRZ 2,0(P)
XHLLI T4,20 ;RESTORE SECTION NUMBER
HLLM T4,0(P)
RET ;FAILS RETURN +1
SKIIF5: ADD 2,PARALP ;LOOK PARALLEL
JRST SKIIF2
;SKIP IF FORK IN 1 IS SUPERIOR OF THIS FORK
SKISF:: PUSH P,2
HRRZ 2,FORKN
SKISF1: CAIN 1,0(2)
JRST SKISF2 ;SAME, RETURN GOOD
JUMPE 2,PB2 ;END OF LIST, RETURN BAD
ADD 2,SUPERP ;GET SUPERIOR POINTER
LDB 2,2
JRST SKISF1
;SKIMIF - SKIP IF FORK IN T1 IS IMMED INF OF EXECUTING FORK
SKIMIF: PUSH P,T1 ;MAKE TRANSPARENT TO T1
ADD T1,SUPERP ;GET SUPERIOR OF FORK IN T1
LDB T1,T1
CAMN T1,FORKN ;IS IT ME?
AOS -1(P) ;YES, SKIP RETURN.
POP P,T1 ;RESTORE CALLER'S ARG
RET
;Execute-Only process tests
; CHKNXS - Check for SELF or not execute-only
;
; Call:
; Fork structure is locked
; T1/ Job-relative fork number (JRFN) to be tested
; CALL CHKNXS
;
; Returns:
; +1: Always
; Process is now non-virgin
;
; ITRAPs if fork cannot be manipulated because it is execute-only
;
CHKNXS::
CALL CKNXSR ;Skip if OK
JRST ITFRKR ;Invalid-- ITRAP
RET ;Return from CHKNXS
;
;
; CKNXSR - Skip if not execute-only or SELF
; CKNXOR - Skip if not execute-only
;
; Call:
; Fork structure is locked
; T1/ Job-relative fork number (JRFN) to be tested
; CALL CKNXSR/CKNXOR
;
; Returns:
; +1: Check failed,
; T1/ Error code (FRKHX8)
; +2: Not execute-only (or SELF)
; Process is now non-virgin
;
CKNXSR:
CAMN T1,FORKN ;This SELF?
JRST CHKNX2 ;Yes, it's OK
CKNXOR::
JE SFEXO,(T1),CHKNX2 ;Jump if not execute-only
PUSH P,T1 ;Save the JRFN
MOVE T1,CAPENB ;Get enabled capability mask
TXNE T1,SC%WHL ;Is calling process a WHEEL?
JRST CHKNX1 ;Yes-- let him play
MOVE T1,FORKN ;GET OUR INDEX
JN SFGXO,(T1),[ POP P,T1 ;XONLY GET JSYS, SO ALLOW
RETSKP]
POP P,T1 ;Clean JRFN from stack
MOVEI T1,FRKHX8 ;Can't manipulate execute-only process
RET ;Return +1 with error code in T1
;
CHKNX1:
POP P,T1 ;Restore JRFN
CHKNX2:
CALL CLRVGN ;No longer virgin process
RETSKP ;Return +2 from CHKNXS/CHKNXO
;
;
; SETEXO - Set execute-only process
;
; Call:
; Fork structure is locked
; T1/ Job-relative fork number (JRFN) to be made execute-only
; CALL SETEXO
;
; Returns:
; +1: Cannot set execute-only becuase process is not virgin
; +2: Process is now execute-only
;
SETEXO::
JN SFNVG,(T1),R ;If not virgin, then can't be execute-only
SETONE SFEXO,(T1) ;Now process is execute-only
CALL CLRVGN ;No longer virgin
RETSKP ;Return +2 from SETEXO
;
;
; CLRVGN - Make process non-virgin
; SETVGN - Restore virginity
;
; Call:
; T1/ Job-relative fork number (JRFN) to be made non-virgin
; CALL CLRVGN or SETVGN
;
; Returns:
; +1: Always, process virginity set or cleared
;
CLRVGN:
SETONE SFNVG,(T1) ;No longer a virgin fork!!
RET ;Return from CLRVGN
SETVGN::SETZRO SFNVG,(T1) ;RESTORE VIRGINITY!!
RET
;
;
; SETGXO/CLRGXO - Enable/Disable for execute-only GET
;
; Call:
; CALL SETGXO/CLRGXO
;
; Returns:
; +1: Always
;
SETGXO::
PUSH P,T1 ;Save register
MOVE T1,FORKN ;Get current JRFN
SETONE SFGXO,(T1) ;Set execute-only GET flag
JRST CLRGX1 ;Restore T1 and return
;
CLRGXO::
PUSH P,T1 ;Save register
MOVE T1,FORKN ;Get current JRFN
SETZRO SFGXO,(T1) ;Reset execute-only GET bit
CLRGX1:
POP P,T1 ;Restore T1
RET ;Return from SETGXO/CLRGXO
;
;
; SETLFX - Map PSB and check for execute-only
;
; This routine is available for a common sequence of functions:
; - Convert RFH to JRFN
; - Check for execute-only
; - Map PSB of process
;
; Call:
; Fork structure is locked
; T1/ Process relative fork handle (RFH)
; CALL SETLFX
;
; Returns:
; +1: Always,
; T1/ Address of PSB
;
; ITRAPs under a variety of fork-handle conditions
;
SETLFX::
CALL SETJFK ;Convert RFH to JRFN
CALL CHKNXS ;Make sure not execute-only or SELF
CALLRET SETLF1 ;Map PSB of process, and return from SETLFX
SUBTTL MISCELLANEOUS ROUTINES
;MAP PSB OF FORK, GIVEN USER HANDLE IN 1
;RETURN WITH OFFSET TO MAPPED PSB IN 1
;DOES NOT CLOBBER T2 OR T3
SETLFK::
REPEAT 0,< ;This is antiquated by capability checking
TRNE 1,200000 ;SPECIAL DESIGNATOR?
JRST FRKES ;NOT ALLOWED
> ;End of REPEAT 0
SETLF0: CALL SETJFK ;GET JOB FORK INDEX
SETLF1::HRRZS T1
HRRZ 1,SYSFK(1) ;GET SYSTEM FORK INDEX
SETLF3: NOINT
EA.ENT
CAMN 1,FORKX ;CURRENT FORK?
JRST SETLF2 ;YES
LOAD T1,FKPS%,(T1) ;GET SPT INDEX OF PSB
HRLS T1 ; INTO LEFT HALF
HRRI T1,PSBM0-PSBPGA+PSBPG ;GET MAP OFFSET FOR THE PSB
PUSH P,2
PUSH P,T3 ;SAVE T3 AS WELL
MOVE 2,[PTRW+FPG1A]
MOVEI T3,2 ;MAP PSB AND STACK PAGE
CALL MSETMP ;DO IT
MOVEI 1,FPG1A-PSBPGA ;RETURN OFFSET USUAL PSB TO MAP PSB
JRST PB3
SETLF2: SETZ 1, ;USE CURRENT PSB, NO OFFSET
RET
;CLEAR MAPPING OF FPG1. USED BY LFK, PSB, JSB.
CLRJSB::
CLRPSB::
CLRLFK::SKIPN PSBM0+FPG1 ;NOW MAPPED?
JRST CLRLFX ;NO
SETZ 1,
MOVEI 2,FPG1A
MOVEI T3,2 ;CLEAR FPG1 AND FPG2
CALL MSETMP ;DO IT
CLRLFX: OKINT
RET
;MAPJSB - ROUTINE TO MAP ANOTHER JOB'S JSB
;
;ACCEPTS IN T1/ JOB NUMBER
; CALL MAPJSB
;RETURNS: +1 FAILED, NO SUCH JOB
; +2 SUCCESS, WITH T1/ OFFSET SUCH THAT JSB(T1) REFERS TO
; 'JSB' IN OTHER JOB'S JSB.
MAPJSB:: NOSKED ;PREVENT JOB FROM LOGGING OUT
SKIPGE JOBRT(T1) ;THIS JOB EXIST ?
RETBAD (,<OKSKED>) ;NO, FAIL
CALL SETJSB ;YES, MAP THE JSB
OKSKED ;PERMIT SCHEDULING AGAIN
RETSKP ;DONE, RETURN SUCCESS
;SETUP JSB FOR ANOTHER JOB
; 1/ JOB NUMBER
; RETURN +1 WITH JSB MAPPED INTO FPG1A,
; 1/ OFFSET SUCH THAT JSB(1) REFERS TO 'JSB' IN OTHER JOB'S JSB
;
;[7456] CAUTION: Routine DETREC in MEXEC depends on SETJSB mapping into FPG1A!
;[7456] Don't change where the JSB is mapped unless you change DETREC!
SETJSB::NOINT
CAME A,JOBNO ;SEE IF SETJSB'ING OURSELVES
IFSKP.
SETZ A, ;YES, ZERO THE INDEX
RET ;AND JUST RETURN
ENDIF.
PUSH P,FX ;NO, PREPARE TO DO THE MAP
HRRZ FX,JOBPT(A) ;GET TOP FORK OF OTHER JOB
LOAD A,FKJSB ;GET JSB OF OTHER JOB
MOVE B,[PTRW+FPG1A]
CALL SETMPG ;MAP JSB INTO FPG1
LOAD A,FKJSB ;[7433]GET BACK SPTX OF JSB
HRLS A ;[7433] IN LEFT HALF
HRRI A,1 ;[7433]JOBMAP OFFSET OF 2ND PAGE
MOVE B,[PTRW+FPG2A] ;[7433]ADDRESS TO MAP IT TO
CALL SETMPG ;[7433](A,B/)MAP JSB PAGE 2 INTO FPG2
MOVEI A,FPG1A-JSBPGA
POP P,FX
RET
;SETUP TOP FORK PSB FOR ANOTHER JOB
; 1/ JOB NUMBER
; RETURN +1 WITH PSB MAPPED INTO FPG1,
; 1/ OFFSET SUCH THAT PSB(1) REFERS TO 'PSB' IN OTHER JOB'S PSB
SETPSB::HRRZ A,JOBPT(A) ;GET TOP FORK OF OTHER JOB
JRST SETLF3 ;GO DO THE REST
;GET CAPABILITIES OF ANOTHER JOB
; 1/ JOB NUMBER
; RETURN +1,
; 1/ CAPMSK OF DESIGNATED JOB FROM TOP FORK
GJCAPS::CALL SETPSB ;GET OTHER JOB'S PSB
MOVE B,CAPENB(A) ;GET ENABLED CAPABILITES
AND B,CAPMSK(A) ;MASK OFF "TEMPORARY" BITS
PUSH P,B ;Save the value
CALL CLRPSB ;UNDO PSB MAPPING
CALLRET PA1 ;RETURN CAPS IN A
;GET SYSTEM WIDE FORK NUMBER (FORKX) GIVEN RELATIVE FORK HANDLE
;
; 1/ RELATIVE FORK HANDLE (NOT MULTIPLE)
;
; CALL GSWFRK
;
;RETURNS: +1 FAILURE WITH: T1/ ERROR CODE
; +2 SUCCESS WITH: T1/ SYSTEM WIDE FORK NUMBER
GSWFRK::CALL STJFKR ;(T1/T1) Get job relative fork number
RET ;Error, return failure with error code in T1
HRRZ T1,SYSFK(T1) ;Get system wide fork number
RETSKP ;Return success
;GET JOB FORK HANDLE GIVEN USER HANDLE IN 1
;FOR SINGLE (NOT MULTIPLE) FORK HANDLES ONLY
SETJFK::CALL STJFKR ;DO ACTUAL TRANSLATION
JRST ITFRKR ;ERROR - ITRAP
RET ;SUCCESS
STJFKR::HRRZ T1,T1 ;USE ONLY 18 BITS FOR FORK HANDLE
CAIL T1,-2 ;-1 OR -2?
XCT SETJFT+2(T1) ;YES - TRANSFER TO CORRECT ROUTINE
TXZ T1,FH%EPN ;FLUSH FLAG
CAIN T1,.FHSLF ;SELF?
JRST [ HRRZ T1,FORKN ;YES
RETSKP]
CALL RFHJFK ;LOCAL HANDLE - CONVERT TO JRFN
RET ;ILL FORMED - ERR CODE IN T1
CAIGE T1,NUFKS ;FORK HANDLE ASSIGNED?
SKIPGE SYSFK(T1) ;FORK KILLED?
JRST FRKE1R ;NO TO EITHER QUESTION
RETSKP ;RETURN
SETJFT: JRST GETTPF ;-2, TOP FORK
JRST GETSPF ;-1, SUPERIOR
GETSPF: MOVE T1,[1B9+SC%WHL+SC%OPR] ;DOES USER HAVE CAPABILITY TO
TDNN T1,CAPENB ; REFERENCE SUPERIOR FORK?
JRST FRKE2R ;NO
HRRZ T1,FORKN ;GET SUPERIOR FORK
MOVE T1,FKPTRS(T1)
LSH T1,-^D24
RETSKP
GETTPF: MOVEI T1,SC%WHL+SC%OPR ;DOES USER HAVE CAPABILITY TO
TDNN T1,CAPENB ; REFERENCE TOP FORK?
JRST FRKE2R ;NO
HLRZ T1,FORKN ;YES, GET TOP FORK
RETSKP
;COMMON ROUTINE TO LOCK FORK STRUCTURE
; CALL FLOCK
; RETURN +1: ALWAYS, CLOBBERS NO AC'S
;ALTERNATE ENTRY POINT, FLOCKN, ALLOWS NESTING OF THE LOCK.
;CALLING FLOCKN IMPLIES THAT A CALLER TO EITHER ENTRY THAT FINDS
;THE LOCK ALREADY LOCKED CAN FURTHER LOCK IT IF THE CALLING PROCESS
;IS THE ONE THAT LOCKED IT. A COUNT IS KEPT IN FLKCNT, AND THE
;LOCK IS UNLOCKED ONLY WHEN THE COUNT GOES TO 0. THE LEFT HALF OF
;FLKOWN IS -1 IF NESTING IS ALLOWED, 0 OTHERWISE.
FLOCK::
FLOCKN:: ;DEFINE THIS ENTRY AS WELL
ACVAR <W1,W2>
FLOCK1: CSKED ;BE CRITICAL IF LOCK WORKS
AOSN FKLOCK ;LOCK SUCCESSFUL?
;THE LOCK WAS PREVIOUSLY UNLOCKED. SAVE THIS FORK INDEX AND INCREMENT
;THE NEST COUNT
JRST [ HRRZ W2,FORKN ;GET OUR JOB-WIDE FORK HANDLE
MOVEM W2,FLKOWN ;SAVE IT AS THE OWNER
SKIPE FLKCNT ;IF NOT ZERO, SOMETHING IS WRONG
CALL [ BUG.(CHK,FKCTNZ,FORK,SOFT,<Fork lock nest count non-zero>,<<JOBNO,JOB>,<FORKN,JBFORK>>,<
Cause: The FLOCK routine has encountered the nest count for the fork lock
being non-zero, which should not be, since the lock has just been
locked for the first time. This is probably due to some other
software not having cleared the nest count from some previous lock.
Action: If this BUG persists, make it dumpable and submit an SPR with the
dump and a copy of MONITR.EXE. If possible, include any known
method for reproducing the problem and/or the state of the system
at the time the BUG was observed.
Data: JOB - Internal Job number whose fork discovered the non-zero
nest count.
JBFORK - Jobwide fork index of the discovering fork.
>)
SETZM FLKCNT
RET]
AOS FLKCNT ;INCREMENT NEST COUNT
MOVE W1,TODCLK ;GET NOW
ADDX W1,FLKTMV ;WHEN IT WILL TIMEOUT
MOVEM W1,FKTIMW ;SET IT
CALLRET FLKITT] ;SUCCESS. CHECK INTERRUPTABILITY AND RETURN
;SOMEONE HAS IT INCREMENTED. SUCCEED IF IT IS OUR FORK, AND INCREMENT
;THE NEST COUNT
ECSKED ;LOCK NOT SUCCESSFUL, ALLOW INTERRUPTS
HRRZ W1,FORKN ;GET US
CAME W1,FLKOWN ;ARE WE THE OWNER?
JRST FLOCK3 ;NO. GO WAIT THEN
AOS FLKCNT ;YES. INCREMENT NEST COUNT
SOS FKLOCK
RET ;SUCCESS
;SOMEONE ELSE HAS THE LOCK. WAIT A WHILE.
FLOCK3: CALL FLKITT ;CHECK INTERRUPTABILITY
MOVE W1,T1 ;PRESERVE T1
MOVEI T1,^D200 ;WAIT 200 MS BEFORE RECHECKING
DISMS
MOVE T1,W1 ;RESTORE T1
MOVE W1,TODCLK ;GET NOW
CAMG W1,FKTIMW ;HAS THE LOCK TIMED OUT YET?
JRST FLOCK1 ;NO, TRY AGAIN
;WE'VE BEEN WAITING A LONG TIME FOR THIS LOCK. BUGCHK AND THEN
;FORCE IT TO BE UNLOCKED
BUG.(CHK,FLKTIM,FORK,SOFT,<FLOCK - Fork lock timeout>,<<FORKN,JOBFRK>,<JOBNO,JOB>,<FLKOWN,OWNER>>,<
Cause: A fork has been waiting a "long time" for the fork lock.
This BUGCHK announces that the system is assuming that some fork has
neglected to unlock the fork lock and the waiting fork is being
given the lock even though someone else still has it.
The code could be in error here. The measure of a "long time" is
calculated arbitrarily and can be changed. It is parameter FLKTMV.
Action: This BUG appears if the fork owning the lock is hung due
to some other event (unit offline, CFS voting freeze, etc.). Usually,
this is not evidence of a real problem but just a temporary system
event which caused the fork timeout value to expire. This BUG is
usually followed by a FLKNS BUGCHK since this fork acquires and
unlocks the lock and then the fork which had it before attempts
to unlock the lock and finds it already unlocked.
There is no need to take any action due to this BUG unless a real
problem in the fork lock logic is suspected. If action is desired,
first, try increasing FLKTMV in STG.MAC and rebuilding the monitor.
If this BUG persists, make it dumpable and submit an SPR with the
dump and a copy of MONITR.EXE. If possible, include any known
method for reproducing the problem and/or the state of the system
at the time the BUG was observed.
Data: JOBFRK - Job fork number of fork desiring the lock
JOB - Internal Job number desiring the lock
OWNER - Job fork number of fork currently holding the lock
>)
IFE DEBUG,< ;IF NOT DEBUGGING
SKIPE DBUGSW ;DEBUG SWITCH NON-ZERO?
IFSKP.
SETZM FLKCNT ;ZERO THE NEST COUNT
SETOM FLKOWN ;CLEAR THE OWNER
SETOM FKLOCK ;TIMEOUT, CLEAR LOCK AND PROCEED
JRST FLOCK1 ;AND GO GET IT
ENDIF.
> ;END IFE DEBUG
MOVE W1,T1
MOVEI T1,^D50000
DISMS ;DON'T COMPLAIN FOR A WHILE
MOVE T1,W1
JRST FLOCK1
;TEST FOR INTERRUPTABILITY
FLKITT: SKIPN FORKN ;TOP FORK?
RET ;INTERRUPTABILITY NOT IMPORTANT IF TOP FORK
SKIPLE INTDF ;INTERRUPTABLE NOW OR WHEN LOCKING?
BUG.(INF,FLKINT,FORK,SOFT,<FLOCK - Called while NOINT>,,<
Cause: The routine FLOCK was called while the calling process was
unable to be interrupted. The calling fork was not nesting the lock
nor was it the top fork of the job. This indicated a logic error
because if this fork was unable to aquire the lock it will DISMS
while NOINT. This can cause a deadly embrace where the fork which
owns the lock is not relenquish it until the fork which has dismissed
is interrupted which never happens because the fork is NOINT.
Action: If this BUG persists, make it dumpable and submit an SPR with the
dump and a copy of MONITR.EXE. If possible, include any known
method for reproducing the problem and/or the state of the system
at the time the BUG was observed.
>)
RET ;RETURN
ENDAV. ;END ACVAR
;FUNLK - COMMON ROUTINE TO UNLOCK FORK STRUCTURE
; CALL FUNLK
; RETURN +1: ALWAYS, CLOBBERS NO AC'S
;NOTE: THIS CODE COULD CAUSE FLKCNT TO GO NEGATIVE IN THE FOLLOWING
;CASE: FORK 1 LOCKS FKLOCK AND INCREMENTS FLKCNT TO 1, FORK 2 TIMES
;OUT THE LOCK AND SETS FLKCNT TO 0, FORK 2 LOCKS THE LOCK AND LATER
;UNLOCKS IT. WHEN FORK 1 FINALLY UNLOCKS THE LOCK, THE COUNT IS ALREADY
;ZERO. THIS CODE FORCES THE COUNT TO BE NO LESS THAN ZERO.
FUNLK:: PUSH P,1 ;BE TRANSPARENT TO ALL AC'S
SOSLE FLKCNT ;DECREMENT THE NEST COUNT
JRST [ POP P,T1
RET] ;NOT THE LAST TIME. DONE
SETOM FLKOWN ;CLEAR OWNER OF LOCK
SETZM FLKCNT ;MAKE SURE THE COUNT IS ZERO
MOVX T1,1B1 ;GET VERY LARGE TIME
MOVEM T1,FKTIMW ;AND SAY IT NEVER TIMES OUT
SETO 1,
EXCH 1,FKLOCK ;CLEAR LOCK, GET PREVIOUS VALUE
ECSKED ;NO LONGER CRITICAL
JUMPL 1,FUNLK3 ;IF LOCK < 0 ERROR
FUNLK2: POP P,1 ; WAS MADE TO LOCK IT WHILE THIS FORK
RET
REPEAT 0,< ;FOLLOWING WASTES TIME AND IS USLESS
;IF LOCK WAS .G. 0, SOME OTHER FORK IS/WAS TRYING TO LOCK IT. THIS
;FORK WILL DO A BRIEF WAIT SO AS TO PREVENT HOGGING THE LOCK.
FUNLK1: JUMPL 1,FUNLK3 ;BUG IF LOCK NOT SET AT ALL
MOVEI 1,^D200 ;WAIT FOR 200 MS
DISMS
JRST FUNLK2
>
FUNLK3: BUG.(CHK,FLKNS,FORK,SOFT,<FUNLK - Lock not set>,<<FORKN,JOBFRK>>,<
Cause: The FUNLK routine, which unlocks the fork lock, detected that the
lock was already unlocked. This should not be, since anyone
calling FUNLK to unlock the lock presumably first called FLOCK to
lock it. This BUG is usually preceded by a FLKTIM BUGCHK. See
the description of FLKTIM for more details.
Action: No action is required for this BUG, especially if it was preceded
by a FLKTIM BUGCHK, unless a real problem in the fork lock logic is
suspected. If this is the case, make the BUG dumpable and submit an
SPR with the dump and a copy of MONITR.EXE. If possible, include
any known method for reproducing the problem and/or the state of the
system at the time the BUG was observed.
Data: JOBFRK - Job fork number of fork desiring the lock
>)
JRST FUNLK2
;ENTRY FROM PMAP ERROR TO UNLOCK FKLOCK IF THIS PROCESS HAS IT
FUNLKI::SKIPL INTDF ;MUST BE NOINT
SKIPGE FKLOCK ;AND LOCK MUST BE LOCKED
RET ;NOT. WE CAN'T HOLD IT THEN
HRRZ CX,FORKN ;GET US
CAME CX,FLKOWN ;ARE WE THE OWNER?
RET ;NO
CALLRET FUNLK ;YES. UNLOCK IT AND RETURN
;COMMON EXIT FROM FORK JSYS. CLEAR LOCAL PSB MAPPING, DO UNLOCK AND MRETN
CLFRET::CALL CLRLFK
CLFLK0: CALL FUNLK ;UNLOCK THE FORK STRUCTURE
JRST MRETN
;COMMON ERROR EXITS FROM FORK JSYS'S
FKLERR: CALL CLRLFK
CALLRET FUNLK
FRKE1: MOVEI 1,FRKHX1 ;'ILLEGAL FORK HANDLE'
JRST ITFRKR ;GO UNLOCK AND ITRAP
FRKE2: MOVEI 1,FRKHX2 ;'ILLEG REF TO SUPERIOR'
JRST ITFRKR ;GO UNLOCK AND TRAP
FRKE3: MOVEI 1,FRKHX3 ;'MULTIPLE FORK HANDLE NOT LEGAL'
JRST ITFRKR
FRKE4: MOVEI A,FRKHX7 ;RELATIVE PAGE NUMBER TOO LARGE
JRST ITFRKR ;GO UNLOCK AND TRAP
;ERROR RETURN FROM FORK JSYS
EFRKRC: PUSH P,T1 ;SAVE ERROR
CALL CLRLFK ;CLEAR MAPPED PAGE
POP P,T1 ;SNAG ERROR AGAIN
EFRKR: CALL FUNLK ;UNLOCK THE FORK STRUCTURE
RETERR() ;RETURN ERROR CODE ALREADY IN 1
FRKES: CALL FRKESR ;DETERMINE ERROR CODE
;; JRST ITFRKR ;ITRAP
;ITRAP RETURN FROM FORK JSYS
ITFRKR: CALL FUNLK ;UNLOCK THE FORK STRUCTURE
ITERR() ;RETURN ERROR CODE ALREADY IN 1
;COMMON NON-SKIP ERROR RETURNS FROM FORK JSYS'S
FRKE1R: MOVEI T1,FRKHX1 ;ILLEGAL FORK HANDLE
RET
FRKE2R: MOVEI T1,FRKHX2 ;ILLEGAL REFERENCE TO SUPERIOR
RET
FRKE3R: MOVEI T1,FRKHX3 ;MULTIPLE FORK HANDLE ILLEGAL
RET
;HERE TO FIGURE OUT WHICH OF THE ABOVE TO RETURN
FRKESR: HRRZ T1,T1 ;USE ONLY RH
CAIE T1,-1 ;CHECK SUPERIOR OR TOP FORK
CAIN T1,-2 ; ...
JRST FRKE2R ;ILLEGAL SUPERIOR
CAIL T1,-5 ;MULTIPLE FORK HANDLE?
CAILE T1,-3 ; ...
JRST FRKE1R ;NO, RANDOMNESS
JRST FRKE3R ;SUPERIOR ILLEGAL
;TRANSLATE FKH.PN TO PTN.PN
; FKHPTX - return error if execute-only and not SELF
; FKHPTN - normal entry
;ACCEPTS:
; T1/ FORK HANDLE,,PAGE NUMBER
; T2/ ACCESS BITS (PM%EPN) IF .FHSLF OR SECTION 0
; CALL FKHPTN
; OR
; CALL FKHPTX
;RETURNS +1: ERROR
; T1/ ERROR CODE
; +2: SUCCESS
; T1/ PTN,,PN
; T3/ SECTION ACCESS BITS IF NON-ZERO SECTION
;PRESERVES T2
FKHPTX::STKVAR <SAV3,SAV2,SAV1>
MOVEM T2,SAV2 ;SAVE T2
SETO T2, ;Flag to check execute-only
JRST FKHP1 ;Continue . . .
FKHPTN::STKVAR <SAV3,SAV2,SAV1>
MOVEM T2,SAV2 ;SAVE T2
SETZ T2, ;Flag no execute-only check
;FKHP1 - COMMON ENTRY
; T2/ -1 IF WANT TO RETURN ERROR FOR EXECUTE-ONLY
; 0 OTHERWISE
FKHP1: CALL FLOCK
TLNN T1,^-<.FHSLF> ;IS THIS MY FORK?
TRNE T1,777000 ;YES. IS THERE A SECTION NUMBER
JRST FKHP0 ;ANOTHER FORK OR SECTION NO. WAS SPECIFIED
MOVE T3,SAV2 ;GET ACCESS BITS (PM%EPN)
TXNE T3,PM%EPN ;EIGHTEEN BIT PAGE NUMBERS SUPPLIED BY USER?
JRST FKHP0 ;YES, DON'T USE PC SECTION
LOAD T3,VSECNO,UPDL ;GET USER'S PC SECTION
DPB T3,[POINT 9,T1,26] ;PUT IT INTO THE PAGE NUMBER
FKHP0: MOVEM T1,SAV1 ;SAVE PAGE NO. INCLUDING SECTION
LDB T3,[POINT 9,T1,26] ;GET SECTION NUMBER FROM ARG
CAILE T3,(VSECNO) ;A VALID SECTION?
JRST FKHPE1 ;NO
HLRZ T1,T1
CALL STJFKR ;GET JOB FORK INDEX
JRST FKHPER ;ILLEGAL - ERROR CODE IN 1
JUMPE T2,FKHP2 ;Skip check if call to FKHPTN
CALL CKNXSR ;Execute-only process?
JRST FKHPER ;Yes, return error
;..
;..
FKHP2: CALL SKIIF ;SELF OR INFERIOR TO SELF?
JRST [ MOVSI T2,(1B9) ;NOT INFERIOR
TDNN T2,CAPENB ;ALLOWED TO MAP SUPERIOR?
JRST FKHPE2 ;NO
MOVE T2,T1 ;YES, SAVE OBJECT FORK
CALL GETSPF ;GET HANDLE OF SUPERIOR
EXCH T1,T2
CAME T1,T2 ;IS OBJECT FORK IMMED SUPERIOR?
JRST FKHPE2 ;NO
JRST .+1]
HRRZ T2,SAV1 ;GET PAGE NUMBER FROM ARG
CAIGE T2,1000 ;NON-ZERO SECTION WANTED?
JRST [ HRRZ T1,SYSFK(T1) ;NO. GET SYSTEM FORK HANDLE
LOAD T1,FKUP%,(T1) ;GET PT OF SECTION 0
HRLS T1 ; INTO LEFT HALF
HRR T1,T2 ;AND COPY PAGE NUMBER AS WELL
MOVEM T1,SAV1 ;SAVE ANSWER
MOVX T1,PTWR ;ALL ACCESS ALLOWED TO SECTION 0
MOVEM T1,SAV3 ;SAVE THAT
JRST FKHP3] ;AND DONE
CALL SETLF1 ;MAP FORK'S PSB
MOVE T2,SAV1 ;GET BACK ORIGINAL ARG
LDB T3,[POINT 9,T2,26] ;GET SECTION # FROM ARG
ADD T1,T3 ;COMPUTE INDEX INTO OTHER PSB
CALL SECIND ;GET SECTION POINTER
JUMPE T1,[ ;IF NONE,
CALL CLRLFK ;UNMAP PSB
JRST FKHPE1] ;GIVE PROPER ERROR
MOVEM T1,SAV3 ;SAVE SECTION POINTER
LOAD T3,SPTX,T1 ;GET SPT INDEX OF PAGE TABLE
ANDI T2,777 ;GET PAGE OFFSET IN SECTION
HRL T2,T3 ;FORM PTN.PN
MOVEM T2,SAV1 ;SAVE RESULT
CALL CLRLFK ;UNMAP PSB
FKHP3: MOVE T1,SAV3 ;GET SECTION POINTER
TXO T1,PTCPY ;PAGE ACCESS DETERMINES COPY ON WRITE
CALL GPAC ;CONVERT HARDWARE ACCESS BITS TO USER BITS
MOVE T3,T1 ;RETURN ANSWER IN T3
MOVE T1,SAV1 ;GET BACK ARG
CALL FUNLK ;CAN CHANGE FORK STRUCTURE
MOVE T2,SAV2 ;RESTORE AC
RETSKP ;SUCCESS RETURN
FKHPE1: SKIPA T1,[ARGX06] ;ILLEGAL PAGE NUMBER
FKHPE2: MOVEI T1,FRKHX2 ;ILLEGAL SUPERIOR MANIPULATION
FKHPER: MOVE T2,SAV2 ;RESTORE AC
CALL FUNLK ;UNLOCK FORK STRUCTURE
RETBAD () ;ERROR RETURN
;PTNFKH - TRANSLATE PTN TO FKH
;ACCEPTS:
; T1/ PTN,,PN FOR A FORK'S PAGE
; CALL PTNFKH
;RETURNS +1: ERROR
; T1/ ERROR CODE
; +2: SUCCESS,
; T1/ LOCAL FORK HANDLE,,PAGE NUMBER IF PAGE CAN BE IDENTIFIED
; OR
; T1/ -1 IF PAGE CAN'T BE IDENTIFIED
;THIS ROUTINE IS CALLED BY THE RMAP JSYS WHEN IT HAS ALREADY
;DETERMINED THAT THE PAGE OF INTEREST IS OWNED BY A FORK.
;THE PAGE TABLE MAY BE A PAGE TABLE FOR ANY SECTION IN THE USER'S
;ADDRESS SPACE
PTNFKH::STKVAR <PTNFPT,PTNFPS,PTNFPN>
HRRZM T1,PTNFPN ;SAVE PAGE NUMBER
CALL FLOCK ;LOCK THE FORK STRUCTURE
HLRZ T2,T1 ;GET PTN
MOVEM T2,PTNFPT ;SAVE IT
HRRZ T1,SPTH(T2) ;GET THE OWNING FORK
LOAD T3,FKUP%,(T1) ;GET SECTION 0 PAGE TABLE
CAME T3,PTNFPT ;THE ONE WE WERE GIVEN?
JRST PTNF6 ;NO. GO TRY FOR NON-ZERO SECTION
;HERE WHEN IT IS THE FORK'S SECTION 0 PAGE TABLE. GET ITS
;JOB-WIDE INDEX
MOVSI 3,-NUFKS ;SETUP FOR SCAN OF JOB FORK TABLE
PTNF3: SKIPGE T2,SYSFK(3) ;HAVE A USABLE HANDLE?
JRST PTNF2 ;NO. SKIP IT THEN
CAIN T1,0(T2) ;IS IT THE FORK WE WANTED?
JRST [ HRRZ T1,T3 ;YES. GET HANDLE INTO AC
JRST PTNF1] ;GO CONVERT IT
PTNF2: AOBJN 3,PTNF3
SETOB T1,PTNFPN ;NOT FOUND, RETURN -1
JRST PTNF4
;..
;..
;HERE WHEN IT'S NOT THE FORK'S SECTION 0 PAGE TABLE
;SEE IF IT'S A NON-ZERO SECTION TABLE
PTNF6: CALL SETLF3 ;MAP THAT FORK'S PSB
MOVEM T1,PTNFPS ;SAVE INDEX TO PSB
MOVE T3,T1 ;FORM AN AOBJN POINTER TO SECTION TABLE
HRLI T3,-MXSECN-1
PTNF8: HRRZ T1,T3 ;SET SECIND ARGUMENT
CALL SECIND ;GET POINTER (FOLLOW INDIRECT POINTERS)
ANDX T1,STGADM ;GET SPT INDEX
CAMN T1,PTNFPT ;IS THIS THE ONE WE WANTED?
JRST [ HRRZ T2,T3 ;YES. CLEAR LEFT HALF
SUB T2,PTNFPS ;COMPUTE SECTION NUMBER
LSH T2,PGSFT ;MOVE IT TO PAGE NUMBER
ADDM T2,PTNFPN ;COMPUTE NEW PAGE NUMBER
MOVE T1,PTNFPS ;GET OFFSET INTO OTHER PSB
MOVE T1,FORKN(T1) ;GET JOB-WIDE FORK HANDLE
MOVEM T1,PTNFPS ;SAVE FORK HANDLE
CALL CLRLFK ;UNMAP THE PSB
MOVE T1,PTNFPS ;RESTORE FORK HANDLE
JRST PTNF1] ;GO CONVERT
AOBJN T3,PTNF8 ;TRY THE NEXT FORK
;DIDN'T FIND IT. PROBABLY THIS SPT SLOT WAS A SECTION TABLE
;FOR A FORK THAT HAS SINCE UNSMAP'D IT. THERE IS STILL A POINTER
;TO IT IN THE FORK OF INTEREST, AND THE OWNING FORK HAS BEEN
;CHANGED TO BE THE TOP FORK OF THE JOB.
CALL CLRLFK ;UNMAP THE PSB
SETOM T1 ;INDICATE UNKNOWN
JRST PTNF9 ;GO FINISH
;HERE WHEN FORK HAS BEEN FOUND. T1/ JOB-WIDE HANDLE. CONVERT
;TO LOCAL HANDLE AND FINISH
PTNF1: CALL GFKH ;CONVERT TO LOCAL HANDLE
RETBAD(FRKHX6,<CALL FUNLK>)
HRLS T1 ;GET PTN INTO LEFT HALF
PTNF4: HRR T1,PTNFPN ;PN INTO RIGHT HALF
PTNF9: CALL FUNLK ;UNLOCK THE FORK STRUCTURE
RETSKP
;FIND OR INSERT LOCAL FORK HANDLE
; 1/ PSB OFFSET (GRFKH ONLY) ,, JOB FORK INDEX
;GFKH GETS HANDLE RELATIVE TO SELF
;GRFKH GET HANDLE RELATIVE TO FORK WHOSE PSB IS IN LH 1
GFKH: MOVEI 1,0(1) ;LEAVE LH 0 FOR SELF
GRFKH: PUSH P,2
PUSH P,3
PUSH P,4
HLRE 3,1 ;GET PSB OFFSET
HRRZ 2,FORKN(3) ;GET JOB HANDLE FOR F1
PUSH P,3 ;SAVE PSB OFFSET
ADD 3,FKPTAB ;MAKE PTR TO FKTAB
MOVE 4,[XWD -NLFKS+1,1]
CAIN 2,0(1) ;IS IT SELF?
SOJA 4,GFKH4 ;YES, 0
HRLI 1,400000 ;USE LH TO REMEMBER ANY EMPTY ENTRIES
GFKH1: ILDB 2,3 ;LOOK AT NEXT HALF-WORD
CAIN 2,-1 ;ASSIGNED?
JRST GFKH2 ;NO
CAIN 2,0(1) ;IS GIVEN?
JRST GFKH4 ;YES
GFKH3: AOBJN 4,GFKH1
HRRZ 3,1
SKIPL SYSFK(3) ;FORK STILL EXTANT?
TLNE 1,400000 ;NOT FOUND, ROOM TO ADD ENTRY?
JRST POP41 ;NO, RETURN NOSKIP
HLRZ 3,1 ;GET INDEX OF FIRST FREE ENTRY
IDIVI 3,2 ;CONSTRUCT POINTER TO IT
ADD 3,FKPTAB(4)
ADD 3,0(P) ;OFFSET TO PROPER PSB
DPB 1,3 ;STORE JOB INDEX IN ENTRY
HRRZ 2,1 ;GET REQUESTED JRFN
CAIN 2,-1 ;FREE ENTRY REQUESTED?
JRST GFKH5 ;YES - DONT UP COUNT
HRRZ 4,1
LOAD 2,FKHCNT,(4) ;NO - INCR COUNT OF HANDLES ON THIS FORK
ADDI 2,1 ; ...
STOR 2,FKHCNT,(4) ;UPDATE COUNT
GFKH5: HLRZ 4,1
GFKH4: MOVEI 1,400000(4) ;RETURN LOCAL HANDLE WITH BIT
AOS -4(P)
POP41: ADJSP P,-1 ;FLUSH OFFSET
JRST PB4
GFKH2: TLNE 1,400000 ;FIRST EMPTY SLOT?
HRLI 1,0(4) ;YES, SAVE INDEX
JRST GFKH3
;DEASSIGN LOCAL FORK HANDLE GIVEN JOB HANDLE IN 1
DASFKH: PUSH P,2
PUSH P,3
PUSH P,4
CALL JFKRFH ;SEE IF A HANDLE EXISTS
JUMPN T2,DASFK1 ; ...
REPEAT 0,<
BUG.(CHK,NOXRFH,FORK,HARD,<DASFKH - Attempt to deassign nonexistant RFH, ignored>,,<
Cause: This BUG is not assembled into the monitor. When it is, complete
documentation should be provided.
>) > ;END REPEAT 0
JRST PB4 ;IGNORE ATTEMPT
DASFK1: MOVEI 2,-1 ;PUT A -1 WHERE ENTRY WAS
DPB 2,3
LOAD T2,FKHCNT,(T1) ;GET COUNT OF HANDLES ON THIS FORK
SUBI T2,1 ;DECREMENT
STOR T2,FKHCNT,(T1) ; ...
SKIPGE SYSFK(T1) ;WAS THIS FORK KILLED?
SKIPE T2 ;AND NO REMAINING HANDLES?
JRST PB4 ;NO - RETURN
MOVEI T2,FKPTRS(T1) ;YES - RELEASE JRFN NOW
EXCH T2,FREJFK ; ...
MOVEM T2,@FREJFK ; ...
SETOM SYSFK(T1)
JRST PB4
;TABLE OF BYTE POINTERS, HALF WORD
POINT 18,FKTAB,-1
FKPTAB: POINT 18,FKTAB,17
POINT 18,FKTAB,35
SUBTTL JSYS'S FOR SOFTWARE INTERRUPT SYSTEM
;SIR JSYS
;ACCEPTS:
; T1/ FORK HANDLE
; T2/ (ADDRESS OF LEVEL TABLE,,ADDRESS OF CHANNEL TABLE)
; SIR
;RETURNS +1: ALWAYS
; ILLEGAL INSTRUCTION INTERRUPT ON FAILURE
.SIR:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFX ;Map PSB and check execute-only
XSFM T4 ;GET FLAGS WORD, INCLUDING PCS
TXNE T4,EXPCS ;IS PCS NON-ZERO?
ERRJMP(SIRX2,ITFRKR) ;NO. DON'T ALLOW OLD STYLE SIR
JUMPE 2,SIR1 ;ALL 0 IS LEGAL
HLRZ 3,2 ;GET ADDRESSES GIVEN
MOVEI 4,0(2)
CAIL 3,20 ;BOTH .GE. 20?
CAIGE 4,20
ERRJMP(SIRX1,ITFRKR) ;NO
SIR1: HRRZM T2,PSCHNT(1) ;SAVE ADDRESS OF CHNTAB
HLRZM T2,PSLEVT(T1) ;SAVE ADDRESS OF LEVTAB
SETZRO PSXSIR,(T1) ;INDICATE NOT EXTENDED SIR
JRST CLFRET
;XSIR JSYS
;ACCEPTS:
; T1/ FORK HANDLE
; T2/ ADDRESS OF ARGUMENT BLOCK
;ARGUMENT BLOCK:
; LENGTH OF THIS BLOCK (3)
; ADDRESS OF LEVEL TABLE
; ADDRESS OF CHANNEL TABLE
; XSIR
;RETURNS +1: ALWAYS,
; ILLEGAL INSTRUCTION INTERRUPT ON FAILURE
;THIS IS AN EXTENDED SIR JSYS. IT IS USED BY PROGRAMS THAT WILL
;RUN IN NON-ZERO SECTIONS.
.XSIR:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFX ;MAP PSB AND CHECK EXECUTE-ONLY
UMOVE T4,2 ;GET ADDRESS OF ARGUMENT BLOCK
UMOVE T3,0(T4) ;GET SIZE OF THIS TABLE
TLNE T3,-1 ;CAN'T BE THIS BIG
ERRJMP (ARGX05,ITFRKR) ;ARGUMENT BLOCK TOO BIG
CAIGE T3,.SICHT+1 ;CAN'T BE TOO SMALL EITHER
ERRJMP(ARGX04,ITFRKR) ;ARGUMENT BLOCK TOO SMALL
UMOVE T2,.SILVT(T4) ;GET ADDRESS OF LEVEL TABLE
UMOVE T3,.SICHT(T4) ;GET ADDRESS OF CHANNEL TABLE
SKIPN T2 ;OK FOR BOTH TO BE ZERO
SKIPE T3
SKIPA ;NOT BOTH ZERO. CONTINUE
JRST [ SETZRO PSXSIR,(T1) ;BOTH ZERO. CLEAR EXTENDED SIR FLAG
JRST XSIR4] ;GO FINISH
;DON'T ALLOW CHNTAB OR LEVTAB TO BE IN THE AC'S
HRRZ P2,T2 ;GET OFFSET IN THE SECTION FOR LEVTAB
CAIGE P2,20 ;IS IT LESS THAN 20?
TLNE T2,777776 ;YES. SECTION 0 OR 1?
SKIPA ;OK
ERRJMP(SIRX1,ITFRKR) ;YES. INDICATE ERROR
HRRZ P3,T3 ;GET OFFSET IN SECTION FOR CHNTAB
CAIGE P3,20 ;IT IS LESS THAN 20?
TLNE T3,777776 ;YES. SECTION 0 OR 1?
SKIPA
ERRJMP(SIRX1,ITFRKR) ;YES. INDICATE ERROR
;..
;DON'T LET THE CHANNEL TABLE OR THE LEVEL TABLE GO BEYOND THE
;END OF ITS SECTION.
;..
MOVE P2,T3
ADDI P2,^D35 ;GET ADDRESS OF LAST WORD IN CHAN TABLE
XOR P2,T3 ;SEE IF START AND END ARE IN SAME SECTION
TLNE P2,-1 ;ARE THEY?
ERRJMP(XSIRX1,ITFRKR) ;NO. ERROR
MOVE P2,T2
ADDI P2,2 ;GET ADDRESS OF LAST WORD IN LEVEL TABLE
XOR P2,T2 ;SEE IF START AND END ARE IN SAME SECTION
TLNE P2,-1 ;ARE THEY?
ERRJMP(XSIRX2,ITFRKR) ;NO. ERROR
SETONE PSXSIR,(T1) ;INDICATE EXTENDED SIR WAS DONE
XSIR4: MOVEM T2,PSLEVT(T1) ;SAVE ADDRESS OF LEVEL TABLE
MOVEM T3,PSCHNT(T1) ;SAVE ADDRESS OF CHANNEL TABLE
JRST CLFRET ;RETURN SUCCESS
.EIR:: MCENT
REPEAT 0,< ;This is antiquated by capability checking
TRNE 1,200000 ;SPECIAL?
ITERR(FRKHX1) ;ILLEGAL
> ;End of REPEAT 0
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETJFK
CALL CHKNXS ;Check if specified process is execute-only or not SELF
PUSH P,SYSFK(1) ;REMEMBER FORK INDEX
CALL SETLF1 ;MAP PSB
SETZM PSISYS(1) ;0 IS ON
POP P,2
SKIPN PSIBW(1) ;ANY BREAKS WAITING?
JRST CLFRET ;NO
SETZ 1, ;YES, INITIATE SERVICE
NOSKED
CALL PSIRQB
OKSKED
CHKINT ;GET ANY PENDING BREAKS TO BE SEEN
JRST CLFRET
;SKIP IF PSI SYSTEM ENABLED
.SKPIR::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
MOVE P1,PSISYS(1) ;GET STATE OF PI SYSTEM
CALL CLRLFK ;UNLOCK THE FORK STRUCTURE
CALL FUNLK
JUMPN P1,EMRET1 ;TAKE NO SKIP RETURN
SMRETN ;SKIP
.DIR:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFX ;Map PSB and check execute-only
SETOM PSISYS(1)
JRST CLFRET
.AIC:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFX ;Map PSB and check execute-only
IORM 2,PSICHM(1)
ICR: CALL SETAOV ;SET ARITHMETIC OVERFLOW TRAP LOCATION IN UPT
CALL SETPOV ;SET PDL OVERFLOW TRAP LOCATION IN UPT
JRST CLFRET
.DIC:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFX ;Map PSB and check execute-only
ANDCM 2,MONCHN(1) ;DISALLOW MONITOR RESERVED CHANNELS
ANDCAM 2,PSICHM(1)
JRST ICR
;INITIATE INTERRUPT ON CHANNEL
; 1/ FORK HANDLE
; 2/ CHANNEL MASK
; IIC
; RETURN +1 ALWAYS
;FOR MONITOR USE, SEE IICSLF IN SCHED
.IIC:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETJFK
CALL CHKNXS ;Check if specified process is execute-only or not SELF
PUSH P,1
CALL SETLF1 ;MAP DEST PSB
UMOVE 2,2
ANDCM 2,MONCHN(1) ;DISALLOW MON RESERVED CHANS
PUSH P,2
CALL CLRLFK
POP P,2
POP P,1
MOVE 1,SYSFK(1)
EXCH 1,2
NOSKED
CALL PSIRQB
OKSKED
CHKINT ;GET IT SEEN
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
JRST MRETN
.RCM:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
MOVE 1,PSICHM(1)
JRST RETA1
;READ PSI IN PROGRESS AND WAITING MASKS
.RWM:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
MOVE 2,PSIBIP(1)
UMOVEM 2,2 ;REPORT BREAKS IN PROGRESS IN 2
MOVE 1,PSIBW(1)
RETA1: UMOVEM 1,1 ;RETURN VALUE IN 1
JRST CLFRET
.SIRCM::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFX ;Map PSB and check execute-only
CAIN 1,0 ;SELF?
JRST FRKE1 ;ILLEGAL
MOVEM 2,SUPCHN(1)
JRST CLFRET
.RIRCM::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
MOVE 2,SUPCHN(1)
RETA2: UMOVEM 2,2
JRST CLFRET
;RIR JSYS
;ACCEPTS:
; T1/FORK HANDLE
; RIR
;RETURNS +1: ALWAYS
; T2/ (ADDRESS OF LEVEL TABLE,,ADDRESS OF CHANNEL TABLE)
; ILLEGAL INSTRUCTION INTERRUPT ON FAILURE
;IT IS ILLEGAL TO DO THIS JSYS IF THE INTERRUPT SYSTEM WAS SET
;UP VIA XSIR.
.RIR:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
JN PSXSIR,(T1),[ ERRJMP(RIRX1,ITFRKR)] ;XSIR WAS DONE PREVIOUSLY
HRL T2,PSLEVT(T1) ;GET LEVEL TABLE
HRR T2,PSCHNT(T1) ;GET CHANNEL TABLE
JRST RETA2
;XRIR JSYS
;ACCEPTS:
; T1/ FORK HANDLE
; T2/ ADDRESS OF ARGUMENT BLOCK
; XRIR
;RETURNS +1: ALWAYS
;ARGUMENT BLOCK:
; UNCHANGED
; ADDRESS OF LEVEL TABLE
; ADDRESS OF CHANNEL TABLE
;ILLEGAL INSTRUCTION INTERRUPT ON FAILURE
.XRIR::
MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFX ;MAP PSB AND CHECK EXECUTE-ONLY
UMOVE T4,2 ;GET ADDRESS OF ARGUMENT BLOCK
UMOVE T3,0(T4) ;GET SIZE OF THIS TABLE
TLNE T3,-1 ;CAN'T BE THIS BIG
ERRJMP (ARGX05,ITFRKR) ;ARGUMENT BLOCK TOO BIG
CAIGE T3,.SICHT+1 ;CAN'T BE TOO SMALL EITHER
ERRJMP(ARGX04,ITFRKR) ;ARGUMENT BLOCK TOO SMALL
MOVE T2,PSLEVT(T1) ;GET LEVEL TABLE
UMOVEM T2,1(T4) ;RETURN TO USER
MOVE T2,PSCHNT(T1) ;GET CHANNEL TABLE
UMOVEM T2,2(T4) ;RETURN TO USER
JRST CLFRET ;RETURN
;ACTIVATE TERMINAL INTERRUPT
; 1/ TERMINAL CODE ,, CHANNEL NUMBER
; ATI
; RETURN +1: ALWAYS.
.ATI:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
HLRZ 1,1
CAIL 1,^D36 ;REASONABLE TERM CODE?
ATIE1: ERRJMP(TERMX1,ITFRKR) ;NO
CAIN 1,.TICCC ;CONTROL-C?
JRST [ MOVE 3,CAPENB ;YES, SEE IF LEGAL
TXNN 3,SC%CTC
JRST ATX2E
JRST .+1]
CALL GETCHA
XCTU [HRRZ 3,1] ;GET CHANNEL NUMBER
CAIG 3,^D5 ;LEGAL CHANNEL NUMBER?
JRST ATI3 ;YES
CAIL 3,^D23 ;ALLOW CH23 AND ABOVE ALSO
CAILE 3,^D35
ERRJMP(ATIX1,ITFRKR) ;NO
ATI3: DPB 3,2 ;ASSIGN IT TO THIS CODE
HRRZ 4,FORKN
MOVE 3,BITS(1)
IORM 3,FKPSIE(4)
LOAD T1,FRKTTY,(T4) ;GET CONTROLLING TERMINAL
CALL UPDTI ;UPDATE JOB WORD
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
MRETNG
ATX2E: ERRJMP(ATIX2,ITFRKR) ;USER LACKS ^C CAPABILITY
;DEACTIVATE TERMINAL INTERRUPT
; 1/ TERMINAL CODE
; DTI
; RETURN +1: ALWAYS, UNLESS ITRAP
.DTI:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CAIL 1,0
CAIL 1,^D36 ;REASONABLE CODE?
JRST ATIE1 ;NO
HRRZ 2,FORKN
MOVE 6,BITS(1)
ANDCAM 6,FKPSIE(2) ;CLEAR FROM THIS FORK
LOAD T1,FRKTTY,(T2) ;GET CONTROLLING TERMINAL
UPDTIR: CALL UPDTI ;UPDATE JOB WORDS
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
JRST MRETN
;UPDATE JOB TPSI WORDS BY SCANNING FORK WORDS
;TTY DESIGNATOR IN T1 AT CALL
UPDTI: TRNN T1,1B18 ;IS IT A TTY DESIGNATOR?
RET ;NOPE, DO NOTHING.
SAVEQ ;GET SOME MORE WORK AC'S
MOVSI T3,-NUFKS ;SETUP TO SCAN ALL FORKS OF JOB
SETZB T4,Q1 ;IOR PSI AND DPSI WORDS
UPDT0: HRRZ Q2,SYSFK(T3) ;GET FORKX OF THE FORK
CAIN Q2,-1 ;DOES THE FORK EXIST?
JRST UPDT2 ;NO, SKIP OVER IT
LOAD Q2,FRKTTY,(T3) ;GET CONTROLLING TERMINAL
CAIN Q2,0(T1) ;IS IT THE ONE WE WERE CALLED WITH?
JRST UPDT1 ;YES! GO UPDATE THE PSI WORDS
UPDT2: AOBJN T3,UPDT0
MOVEI T2,(T1) ;MOVE TO AC FOR TTYSRV
CAIN T2,-1 ;IS THE CALLING ARG THE JOB CTTY?
JRST UPDT4 ;YES.
TRZ T2,1B18 ;MAYBE NOT
CAMN T2,CTRLTT ;CHECK IN LINE NUMBER FORM
JRST UPDT4 ;IT IS.
CAIGE T2,NLINES ;NOPE. THIS THING IS A LEGAL TTY, I HOPE?
CAIGE T2,0
RET ;NO, IT WASN'T. ALL FOR NOW.
JRST UPDT5 ;YES, GO STORE PSI WORDS
UPDT4: AND T4,TTJTIW ;ALLOW ONLY ENABLED BITS
MOVEM T4,TTSPSI
AND Q1,TTJTIW
MOVEM Q1,TTSDPS ;DEFERRED CODES
SKIPGE T2,CTRLTT ;IF ATTACHED
RET
UPDT5: MOVEM T4,T1 ;SET LINE'S PSI WORDS
MOVEM Q1,T3 ; ..
CALLRET TTSINT
UPDT1: HRRZ FX,SYSFK(T3) ;GET THE SYSTEM FORKX
MOVEI T2,(FX) ;KEEP A COPY
CALL CHKWT ;IS THE FORK DISMISSED?
JRST UPDT3 ;NO
LOAD Q2,FKSTR,(FX) ;YES, SEE HOW.
CAIE Q2,FRZWT ;FROZEN?
JRST UPDT8 ;NO
JE FKFRJ,(FX),UPDT2 ;YES. IS IT JSYS TRAP?
JN FKEFR,(FX),UPDT2 ;YES. JSYS TRAP AND ALSO OTHER FREEZE?
UPDT8: CAIE Q2,HALTT ;WHAT OTHER KIND OF WAIT IS IT?
CAIN Q2,FORCTM ;HALT OR FORCED TERMINATION?
JRST UPDT2 ;YES. DON'T INCLUDE THIS FORK'S PSI BITS
UPDT3: IOR T4,FKPSIE(T3) ;INCLUDE THESE BITS. THIS FORK COUNTS FOR
IOR Q1,FKDPSI(T3) ; PSI COLLECTION PURPOSES
JRST UPDT2 ;ON TO MORE FORKS
;DEASSIGN ALL TERMINAL INTERRUPTS FOR THIS FORK
DTIALL::HRRZ T1,FORKN
SETZM FKPSIE(T1)
LOAD T1,FRKTTY,(T1) ;GET CONTROLLING TERMINAL
CALLRET UPDTI ;UPDATE AND RETURN
;CLEAR PSI SYSTEM
.CIS:: MCENT
NOINT ;PREVENT INTERRUPTION
SETZM PSIBIP
SETZM PSIBW
MOVE T1,[IOWD NPSIPG*PGSIZ,PSIPGA] ;SET UP STACK POINTER
MOVEM 1,PSIPT ;RESET PSI STORAGE
MOVE T1,FORKX ;GET ID OF THIS PROCESS
SETZ 2, ;CLEAR ALL FORK'S ENTRIES ON STACK
CALL JSBSTF ;GO MAKE SURE IT IS CLEAN
MOVE T1,FORKX ;GET ID OF THIS PROCESS
SETZ T2,0
CALL GOKFRE ;FREE GETOKK REQUESTS
OKINT ;ALLOW INTS NOW
JRST MRETN
;READ/SET TERMINAL INTERRUPT WORD
.RTIW:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
HRRZS T1
CAIN 1,-5 ;WHOLE JOB?
JRST [ MOVE 2,TTJTIW ;YES
JRST RTIW1]
CALL SETJFK ;GET JOB INDEX
MOVE 2,FKDPSI(1) ;DEFERRED CODES
UMOVE T3,T1 ;Get the user flags
TXNE T3,RT%DIM ;User want to get deferred mask?
UMOVEM T2,T3 ;Yes, return in T3
MOVE 2,FKPSIE(1)
RTIW1: UMOVEM 2,2
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
JRST MRETN
.STIW:: MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
HRRZS T1
CAIN 1,-5
JRST [ MOVE 3,CAPENB
TXNN 3,SC%CTC ;^C CAPABILITY?
JRST ATX2E ;NO, DON'T PERMIT CHANGE TO JOB TI
MOVEM 2,TTJTIW ;SET JOB MASK WORD
MOVEI T1,-1 ;JOB CONTROLLING TERMINAL
JRST STIW2] ;GO UPDATE AND RET
CALL SETJFK
CALL CHKNXS ;Check if specified process is execute-only or not SELF
UMOVE 3,3 ;GET DEFERRED CODES
UMOVE 4,1 ;GET THE FLAGS
TXNE 4,ST%DIM ;USER WANT TO SET DEFERRED MASK?
MOVEM 3,FKDPSI(1) ;YES, SET THE DEFERRED CODES
EXCH 2,FKPSIE(1) ;SET NEW, REMEMBER OLD
XOR 2,FKPSIE(1) ;DIFFERENCES
SKIPE MONCHN(1) ;RESERVED MON CHANS EXIST?
TLZN 2,(1B16) ;AND ^P BEING CHANGED?
JRST STIW1 ;NO
MOVE 3,BITS+20 ;YES, PUT ^P BACK LIKE IT WAS
XORM 3,FKPSIE(1)
STIW1: LOAD T1,FRKTTY,(T1) ;GET CONTROLLING TERMINAL
STIW2: CALL UPDTI ;UPDATE JOB TIW
CALL FUNLK ;UNLOCK THE FORK STRUCTURE
JRST MRETN
;SPECIAL CAPABILITIES CONTROL
.RPCAP::MCENT
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETJFK
CALL SETLF1
MOVE 2,CAPMSK(1)
UMOVEM 2,2 ;RETURN POSSIBLE IN 2
MOVE 3,CAPENB(1)
UMOVEM 3,3 ;ENABLED IN 3
JRST CLFRET
.EPCAP::MCENT
HRRZ Q1,CAPENB ;CHECK FOR CHANGE
HRRZ Q2,T3 ;REQUESTED
CAMN Q1,Q2
JRST EPCNGO ;NO
CAME T3,[-1] ;Are they asking for all caps?
IFSKP. ; -yes, make it easier for ACJ to determine
MOVE T3,CAPMSK ; Get possible caps
CAIN T1,.FHSLF ; Enabling ourselves?
ANSKP. ; -no,
TLO T3,(777B17) ; so set all bits determined by superior
AND T3,T2 ; and with the "possible mask" supplied
ENDIF. ;T3 now has caps the user is enabling
GTOKM (.GOCAP,<T3>,MRETN)
EPCNGO: CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETJFK
CALL SKIIF
ERRJMP(FRKHX2,ITFRKR) ;INFERIORS ONLY
CALL SETLF1
JUMPE 1,[XOR 3,CAPMSK(1) ;IF SELF, DON'T MODIFY 14-17
TLZ 3,(17B17)
XOR 3,CAPMSK(1)
JRST EPC1]
MOVE 4,CAPMSK
TLO 4,(777B17) ;9-17 DETERMINED BY SUPERIOR
AND 2,4
MOVEM 2,CAPMSK(1)
EPC1: AND 3,CAPMSK(1) ;ONLY ALLOW MODES IN MASK
MOVEM 3,CAPENB(1)
JRST CLFRET
;SWTRP JSYS. SET AND READ USER-MODE TRAPS. CALLING SEQUENCE IS:
; T1/ FORK HANDLE
; T2/ FLAGS,,FUNCTION
; T3/ FUNCTION DEPENDENT ARG
;ITRAP ON ANY ILLEGAL ACT
SWTBIT==SW%NMI ;LEGAL BITS
SWTMSK==<-1,,0>^!SWTBIT ;ILLEGAL BITS IN LEFT HALF
.SWTRP::MCENT ;ESTABLISH CONTEXT
UMOVE T1,1 ;GET FORK HANDLE
CALL FLOCK ;LOCK FORK STURCTURE
CALL SETLFK ;MAP FORK
UMOVE T2,2 ;GET ARG
HRRZ T3,T2 ;GET FUNCTION WITHOUT BITS
CAILE T3,.SWRPD ;VALID FUNCTION?
ITERR (ARGX02,<CALL CLRLFK
CALL FUNLK>)
CAIE T3,.SWART ;IS THIS SET ARITHMETIC OVERFLOW?
CAIN T3,.SWSPD ;OR SET PDL OVERFLOW?
JRST [ TXNE T2,SWTMSK ;YES. ANY ILLEGAL BITS IN LEFT HALF?
ITERR (ARGX22,<CALL CLRLFK
CALL FUNLK>)
JRST SWTR2]
TLNE T2,-1 ;NO. DON'T ALLOW ANYTHING IN LEFT HALF
ITERR (ARGX22,<CALL CLRLFK
CALL FUNLK>)
SWTR2: TRNN T2,1 ;IS THIS A "SET" FUNCTION?
JRST [ UMOVE T3,3 ;YES. GET ADDRESS OF BLOCK
HLRZ T4,T3 ;GET SECTION NUMBER
CAIL T4,7777 ;MUST BE LESS THAN 7777
ITERR (ARGX23,<CALL CLRLFK
CALL FUNLK>)
JRST .+1]
CALL @SWTRPT(T2) ;DO THE FUNCTION
JRST CLFRET ;AND DONE
;DISPATCH TABLE FOR SWTRP ARGS
SWTRPT: IFIW!ARTSET ;.SWART - SET ARITHMETIC TRAP
IFIW!ARTGET ;.SWRAT - READ ARITHMETIC TRAP
IFIW!LUUSET ;.SWLUT - SET LUUO BLOCK
IFIW!LUUGET ;.SWRLT - READ LUUO BLOCK
IFIW!PDLSET ;.SWSPD - SET PDL OVERFLOW BLOCK
IFIW!PDLGET ;.SWRPD - READ PDL OVEFLOW BLOCK
;SET ARITHMETIC TRAP
ARTSET: CALL SETART ;SAVE BLOCK ADDRESS AND SET UP UPT
RET ;AND DONE
;READ ARITHMETIC TRAP
ARTGET: MOVE T3,ARTHTR ;GET TRAP VALUE
UMOVEM T3,3 ;STASH IT
RET ;DONE
;SET LUUO DISPATCH ADDRESS
LUUSET: CALL SETLUU ;STORE ADDRESS IN UPT
RET
;READ LUUO DISPATCH ADDRESS
LUUGET: CALL GTLUUB ;GET LUUO BLOCK ADDRESS
UMOVEM T3,3 ;RETURN VALUE
RET ;AND DONE
;SET PDL OVERFLOW TRAP
PDLSET: CALL SETPDL ;SAVE ADDRESS OF BLOCK AND SET UP UPT
RET
;READ PDL OVERFLOW TRAP
PDLGET: MOVE T3,PDOVTR ;GET ADDRESS OF BLOCK
UMOVEM T3,3 ;RETURN TO USER
RET
;CLRTRP - Routine to clear all functions set by SWTRP. Called by RESET JSYS
; CALL CLRTRP
;Returns +1: always
;Works only on this fork
CLRTRP::SETZM T1 ;OFFSET FOR PSB ADDRESSING FOR THIS FORK
SETZM T3 ;INDICATE "CLEAR FUNCTION"
CALL SETART ;CLEAR ARITHMETIC OVERFLOW TRAP WORD
SETZM T3 ;INDICATE "CLEAR FUNCTION"
CALL SETLUU ;CLEAR LUUO BLOCK ADDRESS
SETZM T3 ;INDICATE "CLEAR FUNCTION"
CALL SETPDL ;CLEAR PDL OVERFLOW TRAP WORD
RET
; Jsys Traps jsyses (TFORK, RTFRK and UTFRK)
;TFORK JSYS - FOR SETTING AND REMOVING TRAPS
;1: XWD function code, fork handle
;2: XWD channel #, number of bits in bit table
;3: Address of bit table
;FUNCTION CODES:
; 0: (.TFSET) Set traps as specified by bit table
; 1: (.TFRAL) Remove all traps set by this fork
; 2: (.TFRTP) Remove traps set by this fork as specified by bit table
; 3: (.TFSPS) Set JSYS trap PSI chan from LH(2); 77=>Don't PSI on trap
; 4: (.TFRPS) Read JSYS trap PSI chan into LH(2)
; 5: (.TFTST) Test if self is monitored: Ret with 2=-1/0 for yes/no
; 6: (.TFRES) Trap reset-remove traps from all inferiors, clear PSI chan
; 7: (.TFUUO) Set UUO traps for fork
; 8: (.TFSJU) Set both UUO and JSYS traps (combine 1 & 7)
; 9: (.TFRUU) Remove UUO traps
; Returns +1 always
.TFORK::MCENT
MOVE Q2,T2 ; Get chan #, # bits set in bit tbl
MOVE P4,T3 ; Bit tbl addr
HRR Q2,T1 ; Make channel, fork handle
HLRZ Q1,T1 ; Function code
CAIL Q1,0 ; Range check the function code
CAILE Q1,.TFRUU
ITERR TFRKX1 ; Bad code, abort
CALL @TFFUN(Q1) ;DO USER'S FUNCTION
MRETNG ; Return a success
TFFUN: IFIW!TFRKSR ; 0 set traps
IFIW!TFRKSR ; 1 remove traps
IFIW!TFRKSR ; 2 remove all
IFIW!TFORK3 ; 3 set channel
IFIW!TFORK4 ; 4 read channel
IFIW!TFORK5 ; 5 test if trapped
IFIW!TFORK6 ; 6 Reset
IFIW!TFRKSR ; 7 UUO traps set
IFIW!TFRKSR ; 8 combine 1 & 7
IFIW!TFRKSR ; 9 Remove UUO traps
TFRKSR: CALL FLOCK ;LOCK FORK STRUCTURE
MOVEI T1,(Q2) ;FORK HANDLE
CAIN T1,-4 ;ALL INFERIORS?
JRST TFSRA ;YES
CALL STJFKR ;CONVERT REL. HANDLE TO JOB FORK INDEX
ITERR TFRKX2,<CALL FUNLK>
CALL SKIMIF ;IS IT AN IMMEDIATE INFERIOR?
ITERR TFRKX2,<CALL FUNLK> ;NO, ERROR
CALL CHKNXS ;Check if specified process is execute-only or not SELF
HRRZ T2,SYSFK(T1) ;SYSTEM FORK INDEX
TMNN FKEFR,(T2) ;IS THE FORK FROZEN?
ITERR TFRKX3,<CALL FUNLK> ;NO, TELL THE USER
CALL TFSR ;SET OR REMOVE THE TRAPS
CALLRET FUNLK ;UNLOCK FORK STRUCTURE AND RET
TFSRA: HRRZ T1,FORKN
CALL MAPINF
CALL TFFRZ ;CHECK ALL FORKS FOR FROZENNESS
HRRZ T1,FORKN
CALL MAPINF
CALL TFSR
CALLRET FUNLK
TFFRZ: HRRZ T1,SYSFK(T1) ;JOB FORK NO. TO SYSTEM FORK INDEX
JN FKEFR,(T1),R ;RETURN IF FORK FROZEN DIRECTLY OR INDIRECTLY
ITERR TFRKX3,<CALL FUNLK> ;NOT FROZEN, LET USER KNOW IT
RET ;YES, FORK IS FROZEN; DIRECT OR INDIRECT
;SET OR REMOVE TRAPS FOR A FORK
;T1/ FORKN OF FORK TO TRAP OR UNTRAP
TFSR: MOVE P1,T1 ;copy forkn
MOVE P3,SUPERP
ADD P3,P1
LDB P3,P3 ;forkn of superior
SKIPN T2,FKJTB(P1) ;do we have a monitor at all?
JRST [ CALL TFIFST ; Some form of setting?
RET ; No, and no monitor so done
CALL NEWJTB ;yes, ret addr. in T2
JRST .+1]
LOAD P2,JTIMP,(T2) ;forkn of our immed. monitor
;P1/ FORKN OF IMMEDIATE INF. TO SET/REMOVE TRAPS FOR
;P2/ FORKN OF P1'S MONITOR
;P3/ FORKN OF P1'S SUPERIOR
CAME P2,P3 ;is my monitor my superior?
JRST [ CALL TFIFST ; A form of set?
RET ; No, & sup. not my mon. so done
CALL NEWJTB ;yes, assign new JTB, ret addr. in T2
LOAD P2,JTIMP,(T2) ;forkn of ITS immed. monitor
JRST .+1]
CAIN Q1,.TFRAL ; Removing all?
JRST [ CALL RELJTB ;yes, release block
CALLRET TFINF3] ;take superior's block and update inf's
CALL TFUBIM ;update JTBIM (im. mon.'s bit table)
CALL TFUALL ;update JTALL
TFINF: MOVE T1,P1 ;pass starting point to mapinf
CALL MAPINF ;do all of his immediate inferiors
CALL TFINF1 ;trap forks inferiors
RET
TFINF1: MOVE P1,T1 ;copy forkn (of inf. fork)
MOVE P3,SUPERP ;get superior pointer
ADD P3,P1
LDB P3,P3 ;get forkn of superior fork
SKIPN T2,FKJTB(P1) ;does this fork have a monitor?
JRST TFINF3 ;no, point to superior's JTB
LOAD P2,JTIMP,(T2) ;P2=forkn of immediate mon for this fork
CAME P2,P3 ;is my monitor my immed. superior?
JRST TFINF3 ;no, point to superior's JTB
CALL TFUALL ;yes, update JTBAL
CALLRET TFINF ;do this forks inferiors, etc.
TFINF3: MOVE T1,FKJTB(P3) ;superior's JTB
MOVEM T1,FKJTB(P1) ;equals inferiors JTB
CALLRET TFINF ;do this forks inferiors, etc.
;UPDATE JTBAL, CALLED WHEN IMMED. MONITOR OF FORK IN P1 IS IT'S SUPERIOR
;P1/ FORKN OF INFERIOR TO SET/REMOVE TRAPS FOR
;P2/ FORKN OF P1'S IMMEDIATE MONITOR (ALSO IT'S SUPERIOR)
TFUALL: MOVSI T4,-JTBTL
HRR T4,FKJTB(P1) ;addr. of inf's JTB
HRRZ T3,FKJTB(P2) ;addr. of monitor's JTB (possibly null)
JUMPE T3,[MOVSI T1,JTBIM(T4) ;this forks JTBIM
HRRI T1,JTBAL(T4) ;equals this forks JTBAL
BLT T1,JTBAL+JTBTL-1(T4)
RET]
TFUAL1: MOVE T1,JTBAL(T3) ;monitor's JTBAL
IOR T1,JTBIM(T4) ;this fork's JTBIM
MOVEM T1,JTBAL(T4) ;this fork's JTBAL
AOS T3
AOBJN T4,TFUAL1
RET
;UPDATE JTBIM, CALLED FOR IMMED. INF. OF EXECUTING FORK ONLY
;P1/ FORKN OF THE IMMED. INF. FORK TO UPDATE
TFUBIM: MOVSI T4,-JTBTL
HRR T4,FKJTB(P1) ;addr. of inf's JTB
MOVE T3,P4 ;addr. of user table
MOVSI T2,(1B0) ; JSYS 0, or UUO trap bit
UMOVE T1,(T3) ; Get word that would be in
CALL TFIFST ; Form of set?
JRST TFUBI2 ; No
CAIE Q1,.TFSJU
CAIN Q1,.TFUUO ; Either form that allows B0 W0?
JRST [ IOR T1,T2 ; Yes, do that
CAIN Q1,.TFUUO ; UUO's only?
MOVE T1,T2 ; Then ignore that from bit tbl
JRST TFUB10]
ANDCAM T2,T1 ; No, remove it
CAIA
TFUBI1: UMOVE T1,(T3) ;user's table
TFUB10: IORM T1,JTBIM(T4) ;ored with existing table (maybe zero)
AOS T3
CAIE Q1,.TFUUO ; If UUO's only, get out
AOBJN T4,TFUBI1
RET
TFUBI2: CAIN Q1,.TFRUU ; Removing UUO traps?
JRST [ MOVE T1,T2 ; Then UUO's only
JRST TFUB20]
ANDCAM T2,T1 ; Can't remove UUO traps this way
CAIA
TFUB21: UMOVE T1,(T3) ;user's table
TFUB20: ANDCAM T1,JTBIM(T4) ;remove from JTB
AOS T3
CAIE Q1,.TFRUU ; If UUO's only, get out
AOBJN T4,TFUBI2
RET
TFIFST: CAIE Q1,.TFSET ; Check if function code is form of set
CAIN Q1,.TFSJU
JRST RSKP
CAIN Q1,.TFUUO
JRST RSKP
RET ; No form of set
;ASSIGN A NEW Jsys Trap Block (JTB)
;P1/ FORKN OF FORK TO ASSIGN TABLE
;RETURNS: +1 ALWAYS
;T2/ ADDRESS OF JTB
NEWJTB: MOVE T1,JTBFRE ;FREE STORAGE BIT TABLE
JFFO T1,.+2
BUG.(CHK,NWJTBE,FORK,SOFT,<No free JTB blocks>,,<
Cause: Word JTBFRE in the JSB has bit n on if JSYS trap block n is
available. The NEWJTB routine assigns trap blocks, looking in JTBFRE
for a bit on. If no bit is found to be on in JTBFRE, the NWJTBE BUGCHK
occurs.
Action: If this BUG persists, make it dumpable and submit an SPR with the
dump and a copy of MONITR.EXE. If possible, include any known
method for reproducing the problem and/or the state of the system
at the time the BUG was observed.
>)
MOVE T3,BITS(T2) ;MARK BLOCK AS ASSIGNED
ANDCAM T3,JTBFRE
IMULI T2,JTBSIZ ; Adr=(blk #*size)+ JTB pg adr+1
ADDI T2,JTBOFF ;FIRST WORD IS FREE BIT TABLE
HRLZI T1,JTBAL(T2)
HRRI T1,JTBAL+1(T2)
SETZM JTBAL(T2)
BLT T1,JTBSIZ-1(T2) ;CLEAR BOTH BIT TABLES
HRRZ T1,FORKN
MOVEM T1,JTBMN(T2) ;SET JTIMP TO FORK EXECUTING TFORK
MOVEM T2,FKJTB(P1) ;MAKE INF. FORK POINT TO JTB
RET
;RELEASE Jsys Trap Block
;P1/ FORKN OF FORK THAT HAS BLOCK ASSIGNED (TO BE RELEASED)
RELJTB: SKIPN T1,FKJTB(P1) ;GET ADDRESS OF JTB
RET ;IF THERE ISN'T A BLOCK ASSIGNED, RETRUN
SETZM FKJTB(P1) ;SAY FORK IS NO LONGER TRAPPED
SUBI T1,JTBOFF
IDIVI T1,JTBSIZ
MOVE T1,BITS(T1)
IORM T1,JTBFRE ;RELEASE BLOCK
RET
TFORK3: HLRZ T2,Q2 ;GET CHANNEL FROM COPY OF USER'S AC2
CAILE T2,^D35 ;LEGAL CHANNEL?
MOVEI T2,77 ;NO, ASSUME NO PSI'S WANTED
STOR T2,JTMCN ;SET THE CHANNEL
RET
TFORK4: LOAD T2,JTMCN ;GET CHANNEL NUMBER
XCTU [HRLM T2,2] ;RETURN IT IN LEFT HALF OF USER'S AC2
RET
TFORK5: SETZ T2, ;ASSUME NOT MONITORED
SKIPE @JTBLK ;ARE WE MONITORED?
SETO T2, ;YES, THEN SAY SO
UMOVEM T2,2 ;RETURN IN USER'S AC2
RET
TFORK6: CALL FLOCK ;TFORK RESET
MOVSI T1,77 ;CLEAR PSI CHANNEL FOR TRAPS
STOR T1,JTMCN ;CAUSE MONITORED FORKS TO BYPASS US
MOVE T1,[XWD .TFRAL,-4] ;REMOVE TRAPS FROM ALL INFERIORS
TFORK ; Forks must be frozen; this has side
; effect of forcing forks queued with
; traps to this fork to bypass it
ERJMP [CALL FUNLK ; Not all forks frozen
ITERX] ; LSTERR is already set from last ITERR
; At this point should scan the JSYS trap Q (FKJTQ) & deQ forks waiting
; on this fork and force them to resume at JTRLCK. If the forks are all
; frozen, then this should have happened already (in susend PSI code)
RTFRK
ERJMP [CALL FUNLK ; Can't buy a handle
ITERX] ; LSTERR is already set from last ITERR
JUMPE T1,TFOR61 ;WAS A TRAP PENDING?
UTFRK
TFOR61: MOVE T2,FORKX ;CLEAR PENDING TRAP PSI (IF ANY)
SETZRO FKIJT,(T2) ;WHICH MAY HAVE OCCURED AFTER
;NOINT AND BEFORE TFORK
SETOM JTLCK ;CLEAR THE LOCK
CALLRET FUNLK
;RTFRK JSYS - READ TRAPPED FORK
; Returns +1 always with:
; 1: Relative fork handle; 0=> no fork currently trapped
; 2: JSYS instruction or UUO that caused fork to be trapped
.RTFRK::MCENT
LOAD T1,JTFRK ; Get job fork index
MOVE T2,JTTRW ; Get trapped JSYS or UUO instruction
JUMPE T1,RTFRK1 ; T1=0 if no fork trapped
PUSH P,T1 ; Save it
PUSH P,T2
CALL GFKH ; Get relative fork handle
ITERR FRKHX6 ; No handles left
MOVEM T1,-1(P) ; Save relative handle
NOSKED ; Prevent sched while clearing lock
SETZRO JTFRK ; Clear trapped fork
SETZM JTTRW ; And JSYS or UUO that we trapped on
CALL JTULCK
OKSKED
POP P,T2 ; JSYS or UUO
POP P,T1 ; Relative fork handle
RTFRK1: UMOVEM T1,1 ; Return stuff to user
UMOVEM T2,2
MRETNG
; UTFRK JSYS - Untrap fork
; Used to resume a trapped fork after a JSYS trap
; 1: Flags,,User handle for fork to untrap
; Flags: B0 (UT%TRP) ITRAP JSYS (or do ERJMP/ERCAL if present)
; Returns: +1 always
; NOOP if fork is not trapped or if executing fork is not permitted
; to untrap the fork (i.e. not forked trapped to or its superior).
.UTFRK::MCENT
MOVE P2,1 ; Get flags & fork handle
MOVEI T1,(P2) ; Check fork handle
TRNE T1,200000 ; Multiple?
ITERR FRKHX3 ; Not allowed
CALL FLOCK ; Nail down structure
CALL SETJFK ; Get job fork index
CALL SKIIF ; Is it an inferior?
ITERR FRKHX2,<CALL FUNLK> ; No, tell user
CALL CHKNXS ;Check if specified process is execute-only or not SELF
HRRZ FX,SYSFK(T1) ; FORKX of fork
CALL SETLF1 ; Map PSB
MOVEI P1,0(T1) ; Save offset to the PSB
MOVES PSBPGA(P1) ; Touch to aviod NOSKED page fault
NOSKED ; Let no others run
CALL CHKWT ; Fork waiting?
JRST UTFRK0 ; No, NOOP
LOAD T2,FKSTR,(FX)
CAIE T2,FRZWT ; Is it frozen
JRST UTFRK0 ; No, NOOP
JE FKFRJ,(FX),UTFRK0 ; NOOP if not trapped?
LOAD T3,JTMNI,(P1) ; Job index of fork trapped to
CAMN T3,FORKN ; Same as executing fork?
JRST UTFRK2 ; Yes.
HRRZ T1,T3 ; Job index of fork trapped to
MOVE T2,FORKN
CALL SKIIFA ; Is that fork inf to ex. fork?
JRST UTFRK0 ; No, NOOP
UTFRK2: MOVEI T1,0(P1) ; Offset to fork's PSB
TLNN P2,(UT%TRP) ; Caller want us to bomb JSYS?
IFSKP.
MOVE T2,PFL(T1) ; Get the trapped process's flags
TXNN T2,UMODF ; Is it a user mode PC?
IFSKP.
SETZM SLOWF(T1) ; Yes, setup proper JSYS context
MOVEM T2,UPDL+1(T1) ; Setup flags for return from ITRAP
MOVEM T2,UPDL+3(T1) ; Gotta go here too
MOVE T2,PPC(T1) ; Fetch user mode PC
MOVEM T2,UPDL+0(T1) ; Setup PC for return from ITRAP
MOVEM T2,UPDL+2(T1) ; Gotta go here too
MOVX T2,MONENV ; Get flags for monitor mode startup
MOVEM T2,PFL(T1) ; Install them in the other process
ENDIF.
XMOVEI T2,ITRAP ; Get new PC to start process at
HRRM T2,PPC(T1) ; Install it in the trapped processes PCB
XMOVEI T2,. ;FAKE PC AS IF JSP
MOVEM T2,PAC+T2
ENDIF.
MOVX T2,JTFRZ%
OPSTRM <ANDCAB T2,>,FKINX,(FX) ; Clear JSYS trap freeze
TXNE T2,FRZBB% ; Is fork still frozen?
JRST [SETOM INTDF(T1) ;YES, MAKE IT OKINT
JRST UTFRK0] ;AND FINISH UP
SKIPN T2,PIOLDS(T1) ; No, resume it
JRST [ CALL UNBLK1 ; Unblock fork
JRST UTFRK3]
STOR T2,FKSTX,(FX)
SETOM INTDF(T1) ; Since process not resumed, OKINT it
CALL RECONC ; Update wait lists
UTFRK3: CALL CLRSFK ; Clear FKINT bit 1
UTFRK0: OKSKED ; NOOP exit
CALL CLRLFK
CALL FUNLK
MRETNG
; SCTTY - Set fork controlling TTY (Terminal PSI)
; 1: Function code,,fork handle
; 2: Source designator (only tty designator implemented)
; Function codes:
; 0: (.SCRET) Return designator for fork in 2
; 1: (.SCSET) Set fork controlling TTY
; 2: (.SCRST) Clear fork controlling TTY (restores job CTTY)
.SCTTY::MCENT
CALL FLOCK ; Prevent meddling
HRRZ P1,1 ; Get fork
MOVE P2,2 ; Get designator
HLRZ P3,1 ; Function number
HRRZ T1,P1 ; Fork
CALL STJFKR ; Job fork number
ITERR(FRKHX1,<CALL FUNLK>)
CALL SKIIF ; Is fork an inferior?
ITERR(FRKHX2,<CALL FUNLK>) ; No, that's not legal
HRRZ P1,T1 ; Update to Job fork number
CAIL P3,0 ; Check range on functions
CAILE P3,.SCRST ; In range?
ITERR(SCTX1,<CALL FUNLK>) ; Undefined function code
XCT SCTFUN(P3) ; Do it
CALL FUNLK ; Returns here successful
MRETNG
SCTFUN: CALL SCTT0 ; Return CTTY for fork
CALL SCTSET ; Set CTTY
CALL SCTCLR ; Clear it (reset to JOB's)
SCTT0: LOAD T2,FRKTTY,(P1) ;GET CONTROLLING TERMINAL
UMOVEM T2,2 ; And hand to user
RET
CHKSCT: MOVX T1,SC%SCT ; Allowed to fiddle CTTY's?
TDNN T1,CAPENB ; ..
ITERR (SCTX4,<CALL FUNLK>)
RET ; OK
; Function to set a new controlling TTY for a fork and its inferiors
SCTSET: STKVAR <TTLNUM>
CALL CHKSCT ; Quit if not allowed to do this
MOVE T2,P2 ; Get designator
TRZN T2,1B18 ; DES = 4XXXXX?
ITERR(DESX1,<CALL FUNLK>) ; No
CAIGE T2,NLINES ; Check as a legal line #
CAIGE T2,0
ITERR(DESX1,<CALL FUNLK>) ; Isn't
LOKK DEVLKK
MOVEM T2,TTLNUM
MOVEI T1,.TTDES(T2) ;GET DESIGNATOR
CALL CHKDEV ;VERIFY ACCESS
ITERR (,<UNLOKK DEVLKK
CALL FUNLK>) ;CAN'T
TMNN DV%ASN,DEVCHR(T2) ;ASSIGNED BY THIS JOB?
ITERR (DEVX2,<UNLOKK DEVLKK ;NO. NOT ASSIGNED AT ALL THEN
CALL FUNLK>)
MOVE T2,TTLNUM
CAMN T2,CTRLTT ; Job CTTY?
ITERR(SCTX3,<UNLOKK DEVLKK
CALL FUNLK>)
CALL GTTOPF ; 3 := TOP FK FOR WHICH THIS TTY IS CTTY
CAIA ; CAN'T FAIL. GIVE ERROR IF IT DOES
CAIE T3,-1 ; Null fork?
ITERR(SCTX2,<UNLOKK DEVLKK
CALL FUNLK>)
MOVEI T1,-2 ; This is just a "different" value
CALL STTOPF ; SET TOP FORK TO "ASSIGNING"
UNLOKK DEVLKK
MOVE T3,P2 ; Retrieve original designator
JRST SCTT21 ; Enter mainline
; Function to remove special controlling terminal from a fork and
; its inferiors. It reverts to the job's CTTY.
SCTCLR: CALL CHKSCT ; Is process privileged to do this?
MOVEI T3,-1 ; Restore fork CTTY to job CTTY
;Here to set the designator in T3 to be the controlling terminal
; for the fork in P1.
SCTT21: MOVE P3,T3 ; New designator
HRRZ T2,FORKN ; Fork number of self
HRRZ T1,P1 ; Job fork number we are setting
CAIN T2,0(P1) ; Setting own CTTY?
CALL MAPINF ; Yes, freeze inferiors only
CALL FFORK3 ; Freeze forks (updates TTPSI words)
HRRZ T1,P1 ; Job number we are setting
HLRZ T4,FORKN ; Top job fork
MOVEI Q1,(T1) ; Compute pointer to its superior
ADD Q1,SUPERP ; ..
LDB Q1,Q1 ; Job fork number of its superior
MOVEI T2,377777 ; NULL designator, just something that
; the previous CTTY won't be.
CAIE T4,0(T1) ; Fork being changed=top job fork?
LOAD T2,FRKTTY,(Q1) ; Get designator of superior's old CTTY
HRRZ T3,P3 ; New designator for desired fork's ctty
CALL SCTT3 ; Set new CTTY for fork and inferiors
CAIN T3,-1 ; Was that all set to job CTTY?
JRST SCTT22 ; Yes, skip following stuff
MOVEI T2,-400000(T3) ; It's a real line. Must set it to know
PUSH P,T1 ; what FORKX to poke on an interrupt char
HRRZ T1,SYSFK(T1) ; Get system FORKX for that fork.
CALL STTOPF ; Set top fork in TTYSRV data base
POP P,T1 ; Restore job fork number
SCTT22: HRRZ T2,FORKN
CAIN T2,0(P1) ; Resume the forks that we froze
CALL MAPINF
CALL RFORK3 ; Resume forks (updates TTPSI words)
RET
; Change the CTTY for some fork and its inferiors
;1/ Job fork index
;2/ Superior fork's prev CTTY designator
;3/ New CTTY designator for fork in 1
SCTT3: LOAD T4,FRKTTY,(T1) ;GET OLD CTTY
STOR T3,FRKTTY,(T1) ; And store NEW
CAIE T4,0(T3) ; New CTTY=old CTTY?
CAIN T4,0(T2) ; Prev CTTY same as sup's prev CTTY?
JRST SCTT5 ; Yes
;Here if this fork is getting a new CTTY, and it also used to have
; a CTTY which wasn't the same as its superior's CTTY.
CAIN T4,-1 ; Was prev CTTY job CTTY?
JRST SCTT4 ; Yes, no need to fix TTFRK1
MOVEI Q2,0(T4) ; No, prev des (assumed to be TTY des)
TRZN Q2,1B18 ; Convert to line #
JRST SCTT4 ; Not a TTY designator
CAIGE Q2,NLINES ; Is it valid?
CAIGE Q2,0
JRST SCTT4 ; No, don't touch TTFRK1
PUSH P,T1 ; Shuffle some AC's for TTYSRV calls
PUSH P,T2 ; ..
MOVEI T2,(Q2) ; Line number
SETO T1,0 ; CLEAR ALL BITS IN TERMINAL PSI WORD
CALL CLRINT ; ..
MOVEI T2,(Q2) ; Line number
CALL STTOPF ; AND SET -1 AS TOP FORK FOR THIS TTY
POP P,T2 ; Restore ac's
POP P,T1 ; ..
SCTT4:
;Here if a different "superior's CTTY" must be told to inferiors
PUSH P,T2 ; Save this fork's SUPERIOR's previous CTTY
MOVEI T2,0(T4) ; Set prev CTTY for inferiors to be old
; CTTY of this fork.
JRST SCTT6 ; Go tell the inferiors
; Here if the "Superior's CTTY" to be told to inferiors is same as
; the one this fork was told
SCTT5: PUSH P,T2 ; Save this fork's superior's previous CTTY
SCTT6: HRLM T1,0(P) ; Save current fork
CALL MAPINF
CALL SCTT3 ; Do above for inferiors
HLRZ T1,0(P) ; Restore current fork
POP P,T2 ; Restore previous CTTY os superior
HRRZS T2 ; Clear fork from LH (saving stack space)
RET ; Done
SUBTTL Program Data Vector (PDVOP% jsys)
;The PDVOP% jsys manipulates program data vectors.
;
;Accepts: AC1/ function
; AC2/ arg block address
;
;Returns+1: always (unless error) function performed
PD0LEN==1+.POADE ;SIZE BLOCK NEEDED TO HOLD ENTIRE ARG BLOCK
.PDVOP::MCENT ;DELCARE JSYS CONTEXT
TRVAR <<OURBLK,PD0LEN>,OURSIZ,LOCUPT,LOCBLK,DATBLK,PPOMAR,POMAR,POLMAP,POPAGE,SAVPER,NREM,NEWPVS,ADRREM,PDFRKN,PONEW,FNDLOW,FNDHGH,PDVN,PDVLST,PSBOFF,PARLEN,PARAD,PCODE,<PD0,PD0LEN>>
SETOM DATBLK ;NO BLOCK HERE YET
SETOM LOCBLK ;NO BLOCK NEEDED TO RELEASE YET
SETOM POLMAP ;NO MAPPED PAGE YET
SETOM POPAGE ;NO WINDOW ADDRESS YET
UMOVE D,A ;GET USER'S FUNCTION CODE
CAIL D,0 ;DISALLOW NEGATIVE ARG
CAIL D,PDVAMX ;DISALLOW BLOATED ARG
ITERR (ARGX02) ;"INVALID FUNCTION"
UMOVE B,B ;GET USER'S ARGUMENT BLOCK ADDRESS
MOVEM B,PARAD ;REMEMER IT
UMOVE A,.POCT1(B) ;GET SIZE OF USER'S ARGUMENT BLOCK
MOVEM A,PARLEN ;REMEMBER ARGUMENT BLOCK LENGTH
LSH D,1 ;ACCOUNT FOR TABLE BEING PAIRS
MOVEM D,PCODE ;REMEMBER CODE
CAILE A,PD0LEN ;MAKE SURE WE HAVE ROOM FOR ARGUMENT BLOCK
ITERR (ARGX05) ;"ARGUMENT BLOCK TOO LONG" (PICKY PICKY!)
HRRZ C,PDVTAB+1(D) ;GET REQUIRED OFFSET
CAMG A,C ;MAKE SURE ARGUMENT BLOCK IS LONG ENOUGH
ITERR (ARGX04) ;"ARGUMENT BLOCK TOO SMALL"
XMOVEI C,PD0 ;GET ADDRESS FOR OUR COPY OF ARG BLOCK
CALL BLTUM ;COPY ARG BLOCK FROM USER SPACE TO OUR COPY
MOVE A,.POADE+PD0 ;GET POSSIBLE ENDING ADDRESS ARG
MOVE B,PARLEN ;GET USER'S ARG BLOCK LENGTH
CAIG B,.POADE ;DID USER SUPPLY AN ENDING ADDRESS?
HRLOI A,377777 ;NO, SO ASSUME NO LARGE BOUND
SKIPN A ;YES, IS IT ZERO?
HRLOI A,377777 ;YES, SO ASSUME THE LARGEST BOUND
CAILE B,.POADR ;NO ERROR POSSIBLE IF .POADR NOT SUPPLIED
CAML A,.POADR+PD0 ;MAKE SURE ENDING ADDRESS AS LARGE AS STARTING ADDRESS
CAIA
ITERR (PDVX01) ;"ENDING ADDRESS MUST BE AS LARGE AS STARTING ADDRESS"
MOVEM A,.POADE+PD0 ;IN CASE NO ENDING ADDRESS GIVEN, USE LARGE VALUE
MOVE A,.POADR+PD0 ;GET POSSIBLE LOW BOUND
CAIG B,.POADR ;IS ONE SUPPLIED?
MOVEI A,0 ;NO, SO ASSUME 0.
MOVEM A,.POADR+PD0
CALL FLOCK ;DON'T LET FORK STRUCTURE CHANGE WHILE WE'RE DOING THINGS
MOVE A,.POPHD+PD0 ;GET FORK HANDLE
CALL SETJFK ;GET FORK NUMBER
MOVEM A,PDFRKN ;REMEMBER FORK NUMBER
MOVE D,PCODE ;GET OFFSET INTO TABLE
MOVX B,PDXOKF ;GET BIT SAYING EXECUTE-ONLY FORKS OK
TDNN B,PDVTAB+1(D) ;DON'T WORRY ABOUT XONLY IF FLAG ON
CALL CHKNXS ;MAKE SURE FORK ISN'T EXECUTE-ONLY
MOVE A,.POPHD+PD0 ;GET PROCESS HANDLE
CALL SETLFK ;MAP IN PSB OF APPROPRIATE FORK
MOVEM A,PSBOFF ;REMEMBER OFFSET FOR PSB
MOVE B,PDVS(A) ;GET ADDRESS OF PDVA BLOCK (OR 0 IF NONE)
CAIN B,0 ;IS THERE ANY BLOCK YET?
SKIPA A,[1] ;NO, PRETEND BLOCK ONLY HAS HEADER
HRRZ A,(B) ;YES, GET LENGTH OF BLOCK
SOJ A, ;SUBTRACT ONE FOR HEADER
MOVEM A,PDVN ;REMEMBER NUMBER OF PDVAS IN BLOCK
AOJ B, ;GET ADDRESS OF ACTUAL LIST OF PDVAS
MOVEM B,PDVLST ;REMEMBER WHERE LIST OF PDVAS BEGINS
MOVE A,PCODE ;GET VERIFIED FUNCTION CODE
CALL @PDVTAB(A) ;DO THE SPECIFIED FUNCTION
CALL POCLEN ;UNMAP WINDOW PAGE IF NECESSARY
JRST CLFRET ;GIVE SUCCESS RETURN, UNLOCKING ALL.
DEFINE FEN (SYMBUL,HEISST) ;MACRO TO ALLOW ORDER-INDEPENDENT DISPATCH ASSIGNMENT
< SYMNAM==.'SYMBUL ;;MAKE REAL SYMBOL
RELOC PDVTAB+2*SYMNAM ;;GET TO CORRECT TABLE LOCATION
DTBDSP SYMBUL ;;PUT DISPATCH ADDRESS IN TABLE
HEISST ;;REMEMBER HIGHEST REQUIRED ARG OFFSET
IFG SYMNAM-PDVAMX,< ;;KEEP TRACK OF LENGTH OF TABLE
PDVAMX==SYMNAM+1>
RELOC PDVTAB+2*PDVAMX ;;GET OUT OF TABLE IN CASE IT'S DONE
>
PDVAMX==0 ;;INITIALIZE TABLE SIZE TO 0
;As defined by the FEN macro, PDVTAB is organized like this:
;
; PDVTAB: address for function 0
; flags,,highest arg block offset needed for function 0
; address for function 1
; flags,,highest arg block offset needed for function 1
; . . .
;
; address n
; flags,,highest offset n
;
; PDVAMX == n + 1 (i.e. PDVAMX is number of functions)
;The following flags may appear in PDVTAB entries:
PDXOKF==1B0 ;execute-only forks are O.K.
PDVTAB: FEN POGET,PDXOKF!.PODAT ;GET LIST OF PDVA'S
FEN POADD,.PODAT ;ADD SOME PDVAS TO THE LIST
FEN POREM,.POPHD ;REMOVE SOME
FEN POLOC,PDXOKF!.PODAT ;LOCATE PDVAS HAVING GIVEN NAME
FEN POVER,PDXOKF!.POADR ;GET VERSION NUMBER
FEN PONAM,PDXOKF!.POADR ;GET PROGRAM NAME
;In all the function-specific routines, the following argument
;block words have the same meaning when relevant:
; .POCT1/ total number of words in argument block
; .POPHD/ process handle
;POVER reads the version word out of a particular PDV.
;This function is needed for execute-only forks.
;
;Accepts: .POADR/ PDVA of PDV being read
; .POCT2/ must contain at least 1
; .PODAT/ address in which to store version word
;
;Returns+1: (user's .PODAT)/version word
; user's .POCT2/ 1
POVER: CALL VERPDV ;VERIFY THAT WE'RE DEALING WITH A PDV
SKIPG .POCT2+PD0 ;IS THERE ROOM FOR THE ONE WORD
JRST [ MOVE A,PARAD ;NO, GET USER'S ARG BLOCK ADDRESS
XCTU [SETZM .POCT2(A)] ;TELL USER NOTHING WAS RETURNED
RET]
MOVE A,.POADR+PD0 ;GET PDVA
ADDI A,.PVVER ;GET ADDRESS OF VERSION WORD
CALL GETWRD ;READ VERSION WORD
MOVE B,.PODAT+PD0 ;GET ADDRESS INTO WHICH RESULT SHOULD BE STORED
UMOVEM A,0(B) ;GIVE USER THE RESULT
MOVEI A,1
MOVE B,PARAD
UMOVEM A,.POCT2(B) ;TELL USER ONE WORD WAS RETURNED
RET
;PONAM reads the ASCIZ program name from a particular PDV.
;This function is needed for execute-only forks.
;
;Accepts: .POADR/ PDVA of PDV to be read
; .POCT2/ maximum number of words we've room for
; .PODAT/ address to store ASCIZ name in
;
;Returns+1: user's .POCT2/ real length,,length of returned string
PONAM: CALL VERPDV ;MAKE SURE WE'RE DEALING WITH A PDV
MOVEI Q1,0 ;NUMBER OF WORDS RETURNED SO FAR
MOVE P1,.PODAT+PD0 ;GET ADDRESS INTO WHICH NAME SHOULD BE STORED
MOVE A,.POADR+PD0 ;GET PDVA
ADDI A,.PVNAM ;GET ADDRESS OF POINTER TO NAME
CALL GETWRD ;READ ADDRESS OF PROGRAM NAME
TXNE A,IFIW ;If section number of address of name string
HLL A,.POADR+PD0 ; is IFIW then use section number of PDVA
MOVE Q2,A ;REMEMBER ADDRESS OF STRING
PONAM1: MOVE A,Q2 ;GET ADDRESS OF NEXT PART OF STRING
CALL GETWRD ;GET IT FROM OTHER FORK
CAML Q1,.POCT2+PD0 ;HAVE WE RETURNED MAXIMUM NUMBER OF WORDS YET?
JRST PONAM3 ;YES, DON'T STORE OR COUNT
UMOVEM A,0(P1) ;NO, STORE PART OF STRING
AOJ Q1, ;KEEP TRACK OF HOW MANY WORDS HAVE BEEN STORED
PONAM3: AOJ P1, ;STEP TO NEXT DESTINATION ADDRESS
TXNE A,177B6 ;STRING NOT OVER UNTIL NULL SEEN SOMEWHERE IN IT
TXNN A,177B13
JRST PONAM2 ;NULL IN ONE OF FIRST TWO SPOTS, STOP STORING
TXNE A,177B20
TXNN A,177B27
JRST PONAM2 ;NULL IN THIRD OR FOURTH SPOT
TXNE A,177B34
AOJA Q2,PONAM1 ;NO NULL YET, KEEP READING NAME
PONAM2: MOVE A,PARAD ;GET USER'S ARG BLOCK ADDRESS
SUB P1,.PODAT+PD0 ;CALCULATE LENGTH OF NAME
HRL Q1,P1 ;GIVE ACTUAL LENGTH IN LEFT HALF
UMOVEM Q1,.POCT2(A) ;TELL USER HOW MANY WORDS WERE RETURNED
RET
;POADD adds some PDVAs to a process.
;
;Accepts: .POCT2/ number of PDVAs being added
; .PODAT/ address of block of PDVAs
POADD: MOVEI Q1,0 ;NUMBER OF OVERLAPS
MOVE Q2,.POCT2+PD0 ;NUMBER OF PDVAS TO CHECK
MOVX P2,1B0 ;PREVIOUS PDVA CHECKED IN NEW BLOCK
MOVE P1,.PODAT+PD0 ;GET ADDRESS OF LIST OF PDVAS BEING ADDED
POAD1: SOJL Q2,POAD2 ;LEAVE LOOP IF ALL NEW PDVAS CHECKED
UMOVE A,0(P1) ;GET A NEW PDVA
MOVE B,A ;UPPERBOUND IS SAME AS LOWERBOUND
CAMG B,P2 ;MAKE SURE EACH NEW PDVA LARGER THAN PREVIOUS
JRST [ MOVEI A,PDVX02 ;ERROR IF NOT ASCENDING ORDER
JRST POERR]
MOVE P2,B ;REMEMBER LARGEST WE'VE SEEN SO FAR
CALL POFND ;SEE IF THIS PDVA IS ALREADY IN THE LIST
AOJA P1,POAD1 ;NO, GO SCAN THE REST
AOJA Q1,.-1 ;YES, REMEMBER HOW MANY OVERLAPS
POAD2: MOVE A,.POCT2+PD0 ;GET NUMBER OF NEW PDVAS GIVEN BY USER
SUB A,Q1 ;SUBTRACT OVERLAPS
ADD A,PDVN ;ADD NUMBER ALREADY EXISTING TO GET NEW TOTAL
CALL GETPBF ;GET A NEW BLOCK FOR THE EXPANDED LIST
MOVEM A,PONEW ;REMEMBER POINTER TO NEW BLOCK
AOJ A, ;GET FIRST ADDRESS INTO WHICH TO STORE A PDVA
MOVE B,PDVLST ;GET FIRST ADDRESS OF A PDVA IN OLD LIST
MOVE C,.PODAT+PD0 ;GET USER ADDRESS OF FIRST NEW PDVA
MOVE Q1,PDVN ;GET NUMBER OF OLD ONES TO SCAN
MOVE Q2,.POCT2+PD0 ;GET NUMBER OF NEW ONES TO SCAN
POAD3: JUMPE Q1,POAD4 ;PERHAPS NO OLD ONES LEFT TO MERGE
MOVE D,(B) ;THERE IS AN OLD ONE LEFT, GET IT
JUMPE Q2,POAD5 ;JUMP IF NO NEW ONES LEFT TO SCAN
UMOVE P2,0(C) ;THERE IS A NEW ONE LEFT, GET IT
CAMLE D,P2 ;SEE WHICH IS SMALLER
JRST [ MOVEM P2,(A) ;NEW ONE SMALLER STORE IT IN NEW LIST
AOJ C, ;REMEMBER THAT THIS NEW ONE HAS BEEN USED
SOJ Q2, ;REMEMBER HOW MANY NEW ONES LEFT
AOJA A,POAD3] ;KEEP MERGING LISTS
CAMLE P2,D
JRST [ MOVEM D,(A) ;OLD ONE SMALLER, STORE IT.
AOJ B, ;STEP TO ADDRESS OF NEXT OLD ONE
SOJ Q1, ;REMEMBER THAT ONE LESS OLD ONE TO SCAN
AOJA A,POAD3]
MOVEM D,(A) ;THEY'RE EQUAL, STORE ONE OF THEM.
AOJ B, ;ADVANCE ADDRESS OF OLD
AOJ C, ;ADVANCE ADDRESS OF NEW
SOJ Q1, ;DECREASE NUMBER OF OLDS LEFT
SOJ Q2, ;DECREASE NUMBER OF NEWS LEFT
AOJA A,POAD3 ;ADVANCE POINTER TO RESULT AND KEEP MERGING
POAD4: MOVE B,C ;GET USER ADDRESS OF NEXT NEW ONE TO PICK UP
MOVE C,A ;GET NEXT MONITOR ADDRESS INTO WHICH TO STORE
MOVE A,Q2 ;GET NUMBER OF NEW ONES LEFT TO STORE
CALL BLTUM ;COPY REST OF NEW ONES INTO RESULT
CALLRET POSWCH ;GO FINISH UP
POAD5: MOVE C,A ;GET NEXT MONITOR ADDRESS INTO WHICH TO STORE
MOVE A,Q1 ;NEW LIST RAN OUT, GET NUMBER OF OLDS LEFT
CALL XBLTA ;COPY REST OF OLD LIST INTO RESULT
CALLRET POSWCH ;GO SWITCH BLOCKS AND RETURN
;POREM removes some PDVAs for a process.
;
;Accepts: .POADR/ smallest address
; .POADE/ largest address (optional)
;
;All PDVAs in the included address range are removed.
POREM: MOVE A,.POADR+PD0 ;GET LOWERBOUND
MOVE B,.POADE+PD0 ;GET UPPERBOUND
CALL POFND ;DECIDE WHAT'S BEING REMOVED
RET ;NOTHING, SO BYE
MOVEM A,NREM ;REMEMBER NUMBER BEING REMOVED
MOVEM B,ADRREM ;REMEMBER ADDRESS OF BLOCK TO BE REMOVED
SUB A,PDVN ;CALCULATE NEGATIVE PDVAS LEFT AFTER REMOVAL
JUMPE A,POR0 ;HANDLE CASE OF NONE LEFT
MOVN A,A ;GET POSITIVE PDVAS LEFT
CALL GETPBF ;GET NEW BLOCK
MOVEM A,PONEW ;REMEMBER ADDRESS OF NEW BLOCK
AOJ A, ;LOCATE BEGINNING OF PDVAS IN NEW BLOCK
MOVEM A,NEWPVS
MOVE A,ADRREM ;GET BEGINNING OF BLOCK TO REMOVE
SUB A,PDVLST ;CALCULATE NUMBER OF ONES TO PRESERVE IN FRONT OF REMOVAL
MOVE B,PDVLST ;COPY FROM OLD BLOCK
MOVE C,NEWPVS ;COPY INTO NEW BLOCK
CALL XBLTA ;COPY PRESERVED STUFF
MOVE B,ADRREM ;GET ADDRESS OF FIRST REMOVAL
ADD B,NREM ;GET ADDRESS OF FIRST ONE BEYOND REMOVAL
MOVE A,PDVLST ;GET ADDRESS OF FIRST OLD ONE
ADD A,PDVN ;GET SMALLEST ADDRESS BEYOND LIST
SUB A,B ;CALCULATE NUMBER OF PDVAS AFTER REMOVAL
CALL XBLTA ;COPY STUFF BEYOND REMOVAL INTO NEW BLOCK
CALLRET POSWCH ;SWITCH BLOCKS AND RETURN
POR0: SETZM PONEW ;SAY THERE'S NO BLOCK ANYMORE
CALLRET POSWCH ;CLEAR OLD BLOCK AND RETURN
;POSWCH replaces an old PDV block with a new, releasing the space taken up
;by the old.
;
;Accepts: PONEW/ pointer to new block
POSWCH: MOVE B,PONEW ;GET NEW BLOCK ADDRESS
MOVE Q1,PSBOFF ;GET OFFSET INTO PSB
EXCH B,PDVS(Q1) ;STORE NEW POINTER, GET OLD
MOVEI A,JSBFRE ;SAY JSB FREE SPACE
JUMPE B,R ;DON'T TRY TO RELEASE NONEXISTENT BLOCK
CALLRET RELFRE ;RELEASE OLD BLOCK AND RETURN
;POLOC gets the pdvas for pdvs having a specified program name.
;
;Accepts: .POCT2/ maximum pdvas to return
; .POADR/ smallest pdva of interest
; .POADE/ largest pdva of interest
; User's AC3/ pointer to ASCIZ string
;
;Returns: User's .POCT2/ number found,,number returned
; User's .PODAT/ the pdvas
POLOC: MOVE A,.POADR+PD0 ;LOCATE RANGE USER IS INTERESTED IN
MOVE B,.POADE+PD0
CALL POFND
NOP ;WE SHOULD BE ABLE TO HANDLE 0 IN NORMAL FASHION
MOVE P1,B ;REMEMBER WHERE FIRST ONE IS
MOVE Q2,A ;REMEMBER HOW MANY PDVS TO LOOK AT
UMOVE A,C ;GET USER'S POINTER TO NAME
CALL CPYFUS ;COPY NAME INTO OUR ADDRESS SPACE
JRST POX02 ;CAN'T, JSB FULL
HRRZM A,LOCBLK ;REMEMBER POINTER TO FREE SPACE BLOCK WE'RE TYING UP
HRROI A,1(A) ;MAKE BYTE POINTER TO NAME
MOVEM A,LOCUPT ;REMEMBER POINTER TO USER'S STRING
HRRZ B,@LOCBLK ;GET SIZE BLOCK WE'LL NEED FOR READING NAMES INTO
SOJ B, ;DISCOUNT HEADER TO GET SIZE DATA BLOCK
MOVEM B,OURSIZ ;Save size of block
AOJ B, ;INCLUDE HEADER TO GET OUR BLOCK
CALL ASGJFR ;GET BLOCK FOR READING NAMES INTO
JRST POX02 ;NO ROOM FOR THIS BLOCK
MOVEM A,DATBLK ;REMEMBER POINTER TO OUR BLOCK
AOJ A, ;GET OVER HEADER
MOVEM A,.PODAT+OURBLK ;ESTABLISH WHERE OUR DATA BLOCK IS
MOVE A,.POPHD+PD0 ;GET FORK WE'RE LOOKING AT
MOVEM A,.POPHD+OURBLK ;SET UP FOR OUR OWN PDVOP% JSYS
MOVEI A,1+.POADR ;SPECIFY HOW MUCH OR OUR ARG BLOCK IS USED
MOVEM A,.POCT1+OURBLK
MOVE Q1,.POCT2+PD0 ;GET MAXIMUM NUMBER OF PDVAS TO RETURN
MOVE P2,.PODAT+PD0 ;GET NEXT ADDRESS TO STORE A PDVA IN
MOVEI P3,0 ;NUMBER OF MATCHING PDVAS FOUND
POL1: SOJL Q2,POL2 ;LEAVE LOOP IF NO MORE PDVAS TO EXAMINE
MOVE A,(P1) ;GET NEXT PDVA OF PDV TO READ
MOVEM A,.POADR+OURBLK ;SAY WHICH PDVA WE WANT THE NAME OF
MOVEI A,.PONAM ;SPECIFY THAT WE ARE READING A NAME
MOVE B,OURSIZ ;Get block size
MOVEM B,.POCT2+OURBLK ;Set it up
MOVEI B,OURBLK ;TELL PDVOP% WHERE THE ARG BLOCK IS
PDVOP% ;READ THE NAME IN THIS PDV
ERJMP [MOVE A,LSTERR ;FAILED, TELL CALLER WHY
JRST POERR]
MOVE A,LOCUPT ;GET POINTER TO USER'S STRING
HRRO B,.PODAT+OURBLK ;POINT AT NAME OF CURRENT PDV
STCMP% ;COMPARE THE TWO NAMES
ERJMP [MOVE A,LSTERR ;FAILED, SO SAY WHY AND DIE.
JRST POERR]
JUMPE A,[AOJ P3, ;REMEMBER HOW MANY HAVE BEEN FOUND
SOJL Q1,.+1 ;THIS ONE MATCHES, JUMP IF NO ROOM FOR IT
MOVE A,.POADR+OURBLK ;ROOM, GET THE MATCHING ONE
UMOVEM A,(P2) ;STORE IN USER SPACE
AOJA P2,.+1] ;STEP TO NEXT SLOT IN WHICH TO STORE ONE
AOJA P1,POL1 ;LOOP TO EXAMINE REST OF PDVS
POL2: MOVE A,PARAD ;DONE STORING, GET USER'S ARG BLOCK ADDRESS
SUB P2,.PODAT+PD0 ;CALCULATE QUANTITY ACTUALLY RETURNED
HRL P2,P3 ;GIVE NUMBER FOUND,,NUMBER RETURNED
UMOVEM P2,.POCT2(A) ;GIVE TO USER
RET ;DONE
;POGET gets the addresses of PDVs for the specified process.
;
;Accepts: .POCT2/ maximum PDVAs to return
; .POADR/ address to scan up from
; .POADE/ largest address to return (optional)
;
;Returns: user's .POCT2/ number found,,number returned
POGET: MOVE A,.POADR+PD0 ;GET RANGE TO SEARCH
MOVE B,.POADE+PD0
CALL POFND ;FIND INTERESTING SET OF PDVAS
NOP ;IF NONE FOUND, WE'LL "DO" 0
MOVE D,PARAD ;GET USER'S ARG BLOCK ADDRESS
HRL C,A ;GET COUNT BEFORE TRIMMING
CAMLE A,.POCT2+PD0 ;ARE THERE MORE GOOD PDVAS THAN USER WANTS?
MOVE A,.POCT2+PD0 ;YES, TRIM QUANTITY
HRR C,A ;GET NUMBER REALLY BEING DELIVERED
UMOVEM C,.POCT2(D) ;TELL USER HOW MANY PDVAS WE'RE REALLY GIVING.
MOVE C,.PODAT+PD0 ;GET ADDRESS WHERE USER WANTS PDVAS PUT
CALLRET BLTMU ;GIVE USER THE PDVAS
;Come to POGET0 to explicitly return zero (0) PDVAs to the user
POGET0: MOVE D,PARAD ;GET USER'S ARG BLOCK ADDRESS
XCTU [SETZM .POCT2(D)] ;TELL HER NO PDVAS HAVE BEEN RETURNED
RET
;VERPDV verifies that the given pdva is really a pdva.
;
;Accepts: .POADR+PD0/ pdva being verified
;
;Returns+1: yes
VERPDV: MOVE A,.POADR+PD0 ;GET PDVA BEING VERIFIED
MOVE B,A ;WE ONLY WANT TO SEARCH FOR ONE
CALL POFND ;TRY TO FIND THE SPECIFIED PDVA
CAIA ;GIVE ERROR IF NOT FOUND
RET ;IT'S FOUND, SO IT'S O.K.
MOVEI A,PDVX03 ;SAY "NON-PDV GIVEN"
CALLRET POERR ;GO GIVE ERROR
;POFND finds a subset of PDVAs in the stored list.
;
;Accepts: A/ smallest PDVA of interest
; B/ largest PDVA of interest
; PDVLST/ address of first PDVA
; PDVN/ total number of PDVAs in list
;
;Returns+1: no interesting ones found, A/ 0
; +2: A/ number of interesting ones found
; B/ address of first interesting one
POFND: MOVEM A,FNDLOW ;SAVE LOWERBOUND
MOVEM B,FNDHGH ;SAVE UPPERBOUND
MOVE A,PDVLST ;GET SMALLEST POSSIBLE BOUND
MOVE C,PDVN ;GET TOTAL PDVAS TO SCAN
MOVE B,FNDLOW ;GET SMALLEST INTERESTING POSSIBLE PDVA
POF0: SOJL C,RFALSE ;IF COUNT RUNS OUT, WE FOUND NONE
CAMLE B,(A) ;IS THIS PDVA LARGE ENOUGH?
AOJA A,POF0 ;NO, KEEP SCANNING
MOVE B,FNDHGH ;GET LARGEST INTERESTING POSSIBLE PDVA
MOVE D,A ;REMEMBER SMALL INTERESTING ADDRESS
CAIA ;CONSIDER CURRENT WORD WITH UPPERBOUND
POF1: SOJL C,POFDON ;IF COUNT RUNS OUT, WE'VE FOUND ENTIRE SET
CAML B,(A) ;IS TEST PDVA SMALL ENOUGH?
AOJA A,POF1 ;YES, EXPAND RANGE
POFDON: SUB A,D ;CALCULATE NUMBER OF GOOD ADDRESSES OF PDVAS
JUMPLE A,RFALSE ;IF NONE, SAY SO
MOVE B,D ;GET FIRST GOOD ADDRESS
RETSKP ;SKIP TO SAY SOME FOUND
;POX02 is for handling failures from attempts to get free space, when
;the reason is that JSB free space is full.
POX02: MOVEI A,MONX02 ;SAY JSB FULL
CALLRET POERR
;POERR causes ITRAP from PDVOP% jsys, unlocking what's necessary first.
;
;Accepts: A/ error code
POERR: MOVEM A,SAVPER ;SAVE ERROR CODE
CALL POCLEN ;UNMAP POSSIBLE WINDOW
CALL CLRLFK ;UNMAP FORK'S PSB
CALL FUNLK ;UNLOCK FORK STRUCTURE
MOVE A,SAVPER ;GET ERROR CODE
ITERR ;CAUSE ERROR RETURN
;POCLEN does CLEAN up stuff.
POCLEN: SKIPL A,POPAGE ;IS THERE A WINDOW?
CALL RELPAG ;YES, RELEASE IT
MOVEI A,JSBFRE ;PREPARE TO RELEASE FREE SPACE
SKIPL B,LOCBLK ;BLOCK HERE TO RELEASE?
CALL RELFRE ;YES, RELEASE IT
MOVEI A,JSBFRE ;PREPARE TO RELEASE FREE SPACE
SKIPL B,DATBLK ;BLOCK HERE TO RELEASE?
CALL RELFRE ;YES, RELEASE IT
RET
;GETPBF gets a PDV block from JSB free space.
;
;Accepts: A/ number of PDVAs to be stored
;
;Returns+1: A/ address of block, or 0 if none were to be stored
GETPBF: JUMPE A,R ;IF NEED 0 WORDS, RETURN 0
AOS B,A ;LEAVE ROOM FOR HEADER
CALL ASGJFR ;ASSIGN JSB FREE SPACE
JRST POX02 ;CAN'T, JSB FULL
RET
;GETWRD reads a word from another fork in the job.
;
;Accepts: .POPHD+PD0/ fork handle
; A/ address whose contents is to be read
; Note: should be a 30-bit address.
; Callers should resolve IFIW words.
; POLMAP/ number of page currently mapped, or -1
; POPAGE/ page window, or -1 if not set up yet
;
;Returns+1: A/ data from word, or 0 if can't read
GETWRD: MOVEM A,POMAR ;REMEMBER ADDRESS BEING SOUGHT
LSH A,-9 ;MAKE PAGE NUMBER
MOVEM A,PPOMAR ;REMEMBER PAGE
CAMN A,POLMAP ;IS CORRECT PAGE MAPPED ALREADY?
JRST GET1 ;YES, PIECE OF CAKE.
MOVEM A,POLMAP ;NO, SO REMEMBER THAT WE'RE MAPPING IT NOW
SKIPL B,POPAGE ;IS THERE A WINDOW ESTABLISHED YET?
JRST GET2 ;YES
CALL ASGPAG ;NO, GET A PAGE
JRST POX02 ;CAN'T JSB FULL
MOVEM A,POPAGE ;REMEMBER ADDRESS OF WINDOW PAGE
GET2: HRL A,.POPHD+PD0 ;GET FORK HANDLE
HRR A,PPOMAR ;GET DESIRED PAGE
MOVX B,PM%EPN ;Extended page numbers
CALL FKHPTN ;GET PTN,,PAGE
JRST POERR ;FAILED, ERROR CODE IN A
MOVE B,POPAGE ;GET ADDRESS TO MAP PAGE INTO
TXO B,PM%RD ;SAY WE WANT TO READ IT
CALL SETMPG ;SET UP THE MAPPING
GET1: MOVE A,POPAGE ;GET ADDRESS INTO WHICH DATA IS NOW MAPPED
LDB B,[001100,,POMAR] ;GET OFFSET INTO PAGE
ADD B,A ;MAKE ADDRESS IN WINDOW
MOVEI A,0 ;GET 0 IN CASE DATA CAN'T BE READ
MOVE A,(B) ;REFERENCE THE DATA
ERJMP .+1 ;RETURN 0 IF PAGE UNREADABLE
RET
TNXEND
END