1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-01 01:19:17 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

10329 lines
362 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE VMSER - VIRTUAL MEMORY SERVICE ROUTINE V4764
SUBTTL J. FLEMMING, T. WACHS/KBY 04-OCTOBER-88
SEARCH F,S,DEVPRM
SALL
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
;1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1973,1986>
XP VVMSER,4764 ;ASSEMBLY INSTRUCTIONS: VMSER,VMSER/C=F,S,VMSER
ENTRY VMSER
VMSER::
OPDEF PAGE. [CALLI 145]
OPDEF MERGE. [CALLI 173]
SUBTTL BYTE POINTERS
;THESE WILL HAVE TO BE CHANGED IF 30-BIT ADDRESSING IS EVER A REALITY
NVPNP1: POINT P2.SPN,PT2TAB(P1),<^L<P2.VPN>+P2.SPN-1> ;POINTER TO NEXT
NVPNP2::POINT P2.SPN,PT2TAB(P2),<^L<P2.VPN>+P2.SPN-1> ;POINTER TO NEXT
NVPNP4: POINT P2.SPN,PT2TAB(P4),<^L<P2.VPN>+P2.SPN-1> ;POINTER TO NEXT
NVPNT1: POINT P2.SPN,PT2TAB(T1),<^L<P2.VPN>+P2.SPN-1> ;POINTER TO NEXT
NVPNT2: POINT P2.SPN,PT2TAB(T2),<^L<P2.VPN>+P2.SPN-1> ;POINTER TO NEXT
NVPNF: POINT P2.SPN,PT2TAB(F),<^L<P2.VPN>+P2.SPN-1> ;POINTER TO NEXT
NVPNR: POINT P2.SPN,PT2TAB(R),<^L<P2.VPN>+P2.SPN-1> ;POINTER TO NEXT
NVPNT3: POINT P2.SPN,PT2TAB(T3),<^L<P2.VPN>+P2.SPN-1> ;POINTER TO NEXT
SUBTTL FILIO INTERFACE WITH FILSER
;SUBROUTINE TO SCAN FOR THINGS TO DO FOR THE SWAPPER
;OPTIMIZES ALL SEEK REQUESTS, TRANSFER REQUESTS, STARTS SEEKS GOING
;STARTS DATA TRANSFER GOING IF ON UUO (CHAN 7) LEVEL
SWPSCN::
IFN FTMP,<
SYSPIF
SKIPL T1,SCNOWN## ;IF NO CPU "OWNS" SCNCNT
CAMN T1,.CPCPN## ; OR IF THIS CPU "OWNS" IT
>
AOSE SCNCNT## ;SOMEONE ALREADY DOING THIS?
IFE FTMP,<
PJRST DOPOPJ## ;YES, GO AWAY (AT INTERRUPT LEVEL,
; SWPSCN IS RUNNING AT UUO LEVEL)
>
IFN FTMP,<
JRST [SYSPIN
PJRST DOPOPJ##]
MOVE T1,.CPCPN##
MOVEM T1,SCNOWN##
SYSPIN
>
DSKON
PUSHJ P,SAVE3## ;NO, NOW WE ARE
JUMPE J,SWPSC1 ;GO IF UUO LEVEL
SOS P3,CHNCFS(P1) ;UPDATE CHANNEL FAIRNESS COUNT FOR SWAPPING
HRR P3,CHNQUE(P1) ;RH NON-0 IF FILE TRANSFER WAITING
SWPSC1: PUSH P,J ;SAVE J
PUSH P,U ;SAVE U
SWPSC2: SETZB P1,T2 ;INDICATE FIRST CALL TO NEXT
HRLOI T1,377777 ;SET ALL UNITS IN A.S.L. TO HUGE
; TIMES TO BLOCK OR TIMES TO CYLINDER
MOVEI T4,TWCOD
SWPSC3: SKIPG T3,SWPTAB##(T2) ;UNIT IN ASL?
JRST SWPSC4
CAME T1,UNISWD(T3) ;TIME ALREADY INFINITY?
CAME T4,UNISTS(T3) ;NO, IS UNIT IN TRANSFER WAIT?
SKIPA U,T1 ;NO, MAKE TIME = INFINITY
MOVEI U,-1 ;YES, INSURE SWPPIK WILL FIND IT EVEN IF SWPSCN DOESN'T
MOVEM U,UNISWD(T3) ;SAVE LARGE TIME-TO-BLOCK OR CYLINDER
IFN FTDUAL,<
SKIPE T3,UNI2ND(T3) ;IN 2ND PORT TOO
MOVEM U,UNISWD(T3)
>
SWPSC4: CAIGE T2,SWPMAX## ;END OF THE ACTIVE SWAPPING LIST?
AOJA T2,SWPSC3 ;NO, LOOK AT ALL UNITS IN THE ASL
DSKOFF
SWPSC5: PUSHJ P,NEXT ;GET NEXT REQUEST FROM SWPLST
JRST SWPS22 ;DONE
JUMPL U,SWPS10 ;DISK (CPU) GONE, ERROR
HRRZ T2,UNICDA(U) ;DDB UNIT IS ATTACHED TO
CAIE T2,SWPDDB## ;IF NOT THE SWAPPER
JUMPN T2,SWPSC5 ;LET FILE IO HAPPEN
HRR J,UDBKDB(U) ;SET UP J POINTING TO KONTROLLER
;(PRESERVE UUO/INT LEVEL FLAG)
IFN FTDUAL,<
PUSHJ P,RHBP## ;NEED TO REREAD HOME BLOCKS?
JRST SWPSC5 ;YES, DON'T SWAP ON THIS UNIT
CAME J,-1(P) ;IGNORE BUSY IF INT ON THIS KON
SKIPL KONBSY##(J) ;KON BUSY?
JRST SWPSC6 ;IDLE, USE PRIME PORT
SKIPN T3,UNI2ND(U) ;BUSY, DUAL-PORTED DRIVE?
JRST SWPSC6 ;NO, WAIT FOR PRIME PORT
HRR J,UDBKDB(T3) ;YES, GET 2ND KON
;(PRESERVE UUO/INT LEVEL FLAG)
CAME J,-1(P) ;IGNORE BUSY IF INT ON THIS KON
SKIPL KONBSY##(J) ;KON BUSY?
HRRZ U,UNI2ND(U) ;IDLE, USE 2ND PORT
HRR J,UDBKDB(U) ;GET (NEW) KON
;(PRESERVE UUO/INT LEVEL FLAG)
SWPSC6:
IFN FTMP,<
PUSHJ P,SWPCP ;SET U IF OTHER CPU
JFCL
>>;END FTDUAL&FTMP
CAMN J,-1(P) ;IF NOT ON INTERRUPT LEVEL FOR THIS CHAN,
JRST SWPSC7
MOVE T2,KDBCHN(J)
SKIPE DIADSK##
CAME T2,DIACHN## ;IGNORE REQUEST IF SHUTTING DOWN CHAN
SKIPGE KONBSY##(J) ;IS KONTROLLER IDLE?
JRST SWPSC5 ;NO, TRY NEXT SWPLST ENTRY
JRST SWPSC8 ;YES, THIS REQUEST IS OK
SWPSC7: JUMPGE P3,SWPSC8 ;GO UNLESS BEING FAIR
IFN FTDUAL,<
SKIPE T4,UNI2ND(U) ;POSITIONS WAITING ON SECOND PORT?
SKIPN UNIQUE(T4)
>
SKIPE UNIQUE(U) ;OR PRIME PORT?
JRST SWPSC5 ;YES, DON'T DO THIS REQUEST
SWPSC8: SKIPG KONPOS##(J) ;CAN DO THINGS FOR THIS REQUEST
JRST SWPS12 ;UNIT DOESNT POSITION
MOVE T4,T1 ;POSITIONING UNIT - SAVE BLOCK NUMBER
PUSHJ P,@KONCCM##(J) ;COMPUTE DISTANCE TO BLOCK
JUMPE T1,SWPS11 ;GO IF UNIT ON CYLINDER
MOVMS T1 ;NOT ON CYL, GET + DISTANCE
SKIPE T2,UNISTS(U) ;IS UNIT IDLE
CAIN T2,O2COD ; OR OFF-LINE (NEED THIS TO GET TO BADUNI)
JRST SWPSC9 ;YES, SAVE THIS REQUEST
CAIN T2,PWCOD ;NO, IN POSITION WAIT?
CAML T1,UNISWD(U) ;YES, IS THIS DISTANCE SHORTER?
JRST SWPSC5 ;NO, TRY NEXT REQUEST
SWPSC9: MOVEI T2,PWCOD ;MAKE SURE UNIT IS IN POSITION WAIT
PUSHJ P,SETUDB ;SET UNISWA, ETC.
JRST SWPSC5 ;AND TEST NEXT SWPLST ENTRY
;HERE AFTER NUS STOPCD
SWPS10: PUSHJ P,SWPCD1 ;GIVE SWAP READ ERROR
JRST SWPSC5 ;AND PUSH ON
;HERE IF UNIT ON-CYLINDER
SWPS11: MOVE T1,T4 ;RESTORE BLOCK NUMBER
;HERE IF UNIT DOESN'T POSITION OR ON CYLINDER
SWPS12: CAMN J,-1(P) ;INTERRUPT LEVEL FOR THIS KON?
JRST SWPS13 ;YES
SKIPL KONBSY##(J) ;NO, IS KON BUSY?
JRST SWPS14 ;NO, KON IDLE
JRST SWPSC5 ;YES, KON BUSY
SWPS13: TRNE P3,-1 ;TRANSFERS WAITING?
JUMPL P3,SWPSC5 ;YES, IGNORE IF BEING FAIR
SWPS14:
IFN FTDUAL,<
MOVE T2,UDBKDB(U) ;FILE TRANSFERS WAITING ON THIS CHAN?
MOVE T2,KDBCHN(T2)
SKIPE CHNQUE(T2)
SKIPN T2,UNI2ND(U) ;AND DUAL PORTED?
JRST SWPS16 ;NO, OK LET IT HAPPEN
HRR J,UDBKDB(T2) ;YES, IS OTHER KON BUSY?
;(PRESERVE UUO/INT LEVEL FLAG)
CAME J,-1(P)
SKIPL KONBSY##(J)
JRST SWPS15 ;IDLE, LET SWAP HAPPEN
HRRZ T2,KONCUA##(J) ;BUSY, IS IT DOING A SWAP?
MOVE T3,UNISTS(T2)
HRRZ T4,UNICDA(T2)
CAIN T3,TCOD
CAIE T4,SWPDDB##
JRST SWPS15 ;NOT A SWAP
JRST SWPSC5 ;DON'T TIE UP BOTH CHANNELS DOING SWAPS
;LEAVE ONE CHANNEL OPEN FOR FILE I/O
SWPS15: HRR J,UDBKDB(U) ;GET KON BACK
;(PRESERVE UUO/INT LEVEL FLAG)
SWPS16:>
IFN FTMP,<
MOVE T2,UDBCAM(U)
TDNE T2,.CPBIT##
>
PUSHJ P,@KONLTM##(J) ;COMPUTE TIME TO BLOCK
MOVEI T1,0 ;UNIT OFF-LINE
SKIPE T2,UNISTS(U) ;IS UNIT IDLE
CAIN T2,PWCOD ; OR POSITION WAIT?
JRST SWPS17 ;YES, THIS IS THE BEST TIME TO BLOCK
CAIN T2,TWCOD ;NO, TRANSFER WAIT?
CAMLE T1,UNISWD(U) ;YES, IS THIS BEST?
JRST SWPSC5 ;NO, TEST NEXT ENTRY
SWPS17: MOVEI T2,TWCOD ;SET UNIT TO TRANSFER WAIT
PUSHJ P,SETUDB ;SET UNISWA, ETC.
IFN FTCIDSK,<
SKIPL KONMX##(J) ;MULTIPLE XFERS?
JRST SWPSC5 ;NO
PUSHJ P,SWPCH ;PARANOIA
JRST SWPSC5
SKIPL KONCNA##(J) ;CREDITS?
PUSHJ P,THSBLK ;YES, GET BLOCK NUMBER
JRST SWPSC5 ;MEMTAB MESSED UP
IFN FTMP,<
PUSHJ P,SWPCD ;ON THIS CPU?
JRST SWPS18 ;NO, SET SO DSKTIC WILL FIND IT
>
MOVEM T1,DEVBLK##(F) ;SAVE IN SWPDDB
MOVEM U,DEVUNI##(F) ;SAVE U IN DDB
PUSH P,P1 ;SAVE OUR PLACE
MOVE P1,KDBCHN(J) ;CHAN LOC
PUSHJ P,STRTIO## ;GO CRANK UP THE IO
POP P,P1 ;WHERE WERE WE?
DSKOFF ;STRTIO ENABLED INTERRUPTS
IFN FTMP,<
JRST SWPSC5
SWPS18: HRRZM J,.C0SWP##(T4) ;WAKE UP THE OTHER CPU
>
>; END IFN FTCIDSK
JRST SWPSC5 ;JUST RESCAN IF NO CI DISKS
IFN FTMP,<
SWPS20: SETOM .C0SWP##(T4) ;COME BACK AT DSKTIC
>
SWPS21: PUSHJ P,IDLEPW## ;SET IDLE OR PW
JRST SWPS26
;HERE WHEN ALL OF SWPLST HAS BEEN SCANNED. START SEEKS GOING
SWPS22: MOVEI P2,0 ;START AT 1ST UNIT IN ASL
SWPS23: SKIPG U,SWPTAB##(P2) ;GET UNIT
JRST SWPS26 ;NOT THERE, TRY NEXT
DSKOFF ;NO DISK INTERRUPTS HERE
MOVE T1,UNISTS(U) ;STATE OF UNIT
MOVE T2,UNISWD(U) ;DISTANCE OR TIME OF BEST
CAME T2,[377777,,-1];IS ANYTHING THERE?
CAIE T1,PWCOD ;YES, POSITION WAIT?
JRST SWPS26 ;NO
HRR J,UDBKDB(U) ;KONTROLLER
;(PRESERVE UUO/INT LEVEL FLAG)
IFN FTCIDSK,<
SKIPGE KONMX##(J) ;IF IT'S PW, WE DIDN'T PUT IT THERE
JRST SWPS26
>
IFN FTDUAL,<
CAME J,-1(P) ;IGNORE BUSY IF INT ON THIS KON
SKIPL KONBSY##(J) ;KON BUSY?
JRST SWPS24 ;IDLE, USE PRIME PORT
SKIPN T3,UNI2ND(U) ;BUSY, DUAL-PORTED DRIVE?
JRST SWPS24 ;NO, WAIT FOR PRIME PORT
HRR J,UDBKDB(T3) ;YES, GET 2ND KON
;(PRESERVE UUO/INT LEVEL FLAG)
CAME J,-1(P) ;IGNORE BUSY IF INT ON THIS KON
SKIPL KONBSY##(J) ;KON BUSY?
HRRZ U,UNI2ND(U) ;IDLE, USE 2ND PORT
HRR J,UDBKDB(U) ;GET (NEW) KON
;(PRESERVE UUO/INT LEVEL FLAG)
SWPS24:>
MOVE P1,UNISWA(U) ;GET SWPLST ENTRY
IFN FTMP,<
PUSHJ P,SWPCD ;UNIT ON THIS CPU?
JRST SWPS20 ;NO,COME BACK AT DSKTIC
>
CAMN J,-1(P) ;ON INTERRUPT LEVEL?
JRST SWPS25 ;YES, KONTROLLER ISNT REALLY BUSY
MOVSI T2,KOPPWX##
AND T2,KONPOS##(J) ;T2 NON-0 IF KON CAN START SEEKS WHILE BUSY
SKIPE DIADSK## ;IF DIAG IS GOING
SETZ T2, ;REQUIRE KDB TO BE IDLE
SKIPGE KONBSY##(J) ;IS KONTROLLER NOW BUSY?
JUMPE T2,SWPS21 ;YES, TOUGH LUCK
SWPS25:
IFN FTDUAL,<
HRL P1,U ;SAVE U (2ND PORT OF DUAL-PORTED DRIVE)
>
PUSHJ P,THSBLK ;NO, GET BLOCK AND UNIT AGAIN
JRST SWPS26 ;MEMTAB IS MESSED UP
IFN FTDUAL,<
HLRZ U,P1 ;RESTORE U
>
MOVEM T1,DEVBLK##(F) ;SAVE BLOCK IN SWPDDB FOR UNIPOS
MOVEM U,DEVUNI##(F) ;SAVE UNIT IN SWPDDB
MOVE P1,KDBCHN(J) ;IN CASE STRPOS CALLS STRTIO
IFN FTDUAL,<
SKIPE T1,UNI2ND(U) ;TO DETECT SPURIOUS INTERRUPTS
SETZM UNICDA(T1)
SETOM UNICDA(U) ;SAVE F IN ACTIVE UDB
>
PUSHJ P,STRPOS## ;GO START THE SEEK
SWPS26: CAIGE P2,SWPMAX## ;AT END OF SWPTAB?
AOJA P2,SWPS23 ;NO, TEST NEXT UNIT IN ASL
;HERE WHEN ALL UNITS HAVE BEEN STARTED SEEKING
DSKON
SKIPN -1(P) ;INTERRUPT LEVEL?
JRST SWPPI1 ;NO, START IO IF A UNIT IN TW
PJRST SWPPI6 ;YES, EXIT HOLDING SCNLOK (SWPPIK
;WILL BE CALLED SOON)
;ROUTINE TO SAVE STUFF IN UDB
;ENTER T1=UNISWD, T2=UNISTS, P1=UNISWA
SETUDB: MOVEM T1,UNISWD(U) ;SAVE TIME
MOVEM P1,UNISWA(U) ;SAVE SWPLST POSITION
IFN FTCIDSK,<
SKIPL KONMX##(J)
>
MOVEM T2,UNISTS(U) ;SAVE PW/TW
IFN FTDUAL,<
SKIPN T3,UNI2ND(U) ;IS THERE A SECOND PORT?
POPJ P, ;NO
MOVEM T1,UNISWD(T3) ;YES, SET UP THAT UDB TOO
MOVEM P1,UNISWA(T3)
IFN FTCIDSK,<
SKIPL KONMX##(J)
>
MOVEM T2,UNISTS(T3)
>
POPJ P,
;SUBROUTINE TO SCAN ALL UNITS IN A.S.L., START TRANSFER ON BEST
SWPPIK::
IFN FTMP,<
SKIPL T1,SCNOWN##
CAMN T1,.CPCPN## ;IF THIS CPU "OWNS" SCNCNT
>
SKIPE SCNCNT## ;SOMEONE ALREADY HERE?
POPJ P, ;YES, WAIT A WHILE
PUSHJ P,SAVE2## ;SAVE P1,P2
PUSH P,J ;SAVE J
PUSH P,U
HRRZ P2,P1 ;SAVE LOC OF CHAN DB
MOVSI T1,KOPBSY## ;SET EVERYTHING IDLE SO FILIO WILL DO SOMETHING
ANDCAM T1,KONBSY##(J) ; (THEY REALLY ARE, HAVEN'T YET BEEN MARKED)
SWPPI1: SETZB T1,P1 ;INITIALIZE
HRLOI T2,377777 ;INITIALIZE BEST-SO-FAR
DSKOFF
SWPPI2: SKIPG U,SWPTAB##(T1) ;GET ASL ENTRY
JRST SWPPI4
MOVE J,UDBKDB(U) ;SET KONTROLLER
IFN FTDUAL,<
CAIE P2,@KDBCHN(J) ;IGNORE BUSY IF INT ON THIS CHAN
SKIPGE @KDBCHN(J) ;CHAN BUSY?
JRST SWPPI3 ;IDLE, USE PRIME PORT
SKIPN T3,UNI2ND(U) ;BUSY, DUAL-PORTED DRIVE?
JRST SWPPI3 ;NO, WAIT FOR PRIME PORT
MOVE J,UDBKDB(T3) ;YES, GET 2ND KON
CAIE P2,@KDBCHN(J) ;IGNORE BUSY IF INT ON THIS CHAN
SKIPGE @KDBCHN(J) ;CHAN BUSY?
HRRZ U,UNI2ND(U) ;IDLE, USE 2ND PORT
MOVE J,UDBKDB(U) ;GET (NEW) KON
SWPPI3:>
IFN FTMP,<
PUSHJ P,SWPCP ;ON THIS CPU?
JRST [SKIPLE .C0SWP##(T4) ;NO, ALREADY QUEUED AN IO ON OTHER CPU?
JRST SWPPI4 ;YES, IGNORE THIS UNIT
JRST .+1] ;NO, GET 1 TO START ON OTHER CPU
>
IFE FTMP&FTDUAL,<
MOVE T3,UNISTS(U) ;STATE OF UNIT
>
IFN FTMP&FTDUAL,<
SKIPG T3,SWPTAB##(T1) ;GET UNISTS FROM THE UNIT WHICH IS IN
JRST SWPPI4 ;?
MOVE T3,UNISTS(T3) ; SWPTAB (MIGHT HAVE CHANGED U TO 2ND PORT)
>
CAIE P2,@KDBCHN(J)
SKIPGE @KDBCHN(J) ;IS CHANNEL IDLE?
CAIE T3,TWCOD ;YES, UNIT IN TRANSFER WAIT?
JRST SWPPI4 ;NO, TEST NEXT UNIT
CAMLE T2,UNISWD(U) ;YES, IS THIS BEST SO FAR?
PUSHJ P,SWPCH ;YES, CAN WE DO THIS IO (FRAG'D LIST)?
JRST SWPPI4 ;NO, TRY NEXT
MOVE T2,UNISWD(U) ;YES, SAVE TIME
MOVE P1,UNISWA(U) ;SAVE SWPLST POSITION
IFN FTDUAL,<
HRL P1,U ;SAVE ACTUAL UNIT
>
SWPPI4: CAIGE T1,SWPMAX## ;END OF ASL?
AOJA T1,SWPPI2 ;NO, TRY NEXT UNIT
JUMPE P1,SWPPI5 ;RETURN IF NOTHING TO DO
;HERE WHEN BEST TRANSFER HAS BEEN FOUND FOR SOME CHANNEL
PUSHJ P,THSBLK ;GET BLOCK NUMBER
JRST [SETZM (P1) ;MEMTAB MESSED UP
JRST SWPPI5]
IFN FTDUAL,<
HLRZ U,P1 ;GET ACTUAL UNIT BACK
>
MOVE J,UDBKDB(U) ;SET UP KONTROLLER
IFN FTMP,<
PUSHJ P,SWPCD ;ON THIS CPU?
JRST SWPPI7 ;NO, SET SO DSKTIC WILL FIND IT
>
MOVEM T1,DEVBLK##(F) ;SAVE IN SWPDDB
MOVEM U,DEVUNI##(F) ;SAVE U IN DDB
MOVE P1,KDBCHN(J) ;AND CHAN LOC
SKIPGE KONBSY##(J) ;IS KONTROLLER BUSY?
JRST SWPPI8 ;YES, CANT USE IT NOW
SETZM (P1) ;CHAN IS BUSY
IFN FTDUAL,<
SKIPE T1,UNI2ND(U)
SETZM UNICDA(T1)
SETOM UNICDA(U)
>
PUSHJ P,STRTIO## ;GO CRANK UP THE IO
CAIN P2,@KDBCHN(J) ;YES, INT ON THIS CHAN?
TLO P2,-1 ;YES, FLAG THAT CHAN IS NOW BUSY
JRST SWPPI1 ;LOOK FOR OTHER CHAN
;HERE WHEN THROUGH
SWPPI5: DSKON
SOSL SCNCNT## ;DECREMENT SCNCNT. DID INTERRUPT LEVEL TRY?
JUMPGE P2,SWPSC2 ;YES, SCAN AGAIN (UNIT IN ASL MAY HAVE CHANGED STATE)
;DON'T RETRY IF STARTED XFER. COULDN'T TELL
;IF KON WAS REALLY BUSY.
SKIPGE P2 ;STARTED XFER ON THIS CHAN?
AOS -2(P) ;YES, TELL FILSER SOMETHING HAPPENED
IFN FTCIDSK,<
;NOTE THAT FOR A CI TYPE DISK WE END UP LYING TO FILIO.
;WE TELL HIM THAT WE DIDN'T START A TRANSFER WHEN ACTUALLY WE DID.
;THIS WILL CONVINCE HIM THAT IT'S OK TO START A FILE.
>
IFN FTMP,<
SETOM SCNOWN##
>
MOVE J,-1(P) ;RESTORE J
JUMPE J,SWPPI6 ;IF ON INTERRUPT LEVEL,
MOVE P1,KDBCHN(J) ;GET CHAN LOC
SKIPGE T1,CHNCFS(P1) ;RESTORE CHNCFT IF IT COUNTED
MOVE T1,CHNIFS(P1) ;BELOW 0
MOVEM T1,CHNCFS(P1)
SWPPI6: POP P,U ;RESTORE U
PJRST JPOPJ## ;AND EXIT
IFN FTMP,<
SWPPI7: HRRZM J,.C0SWP##(T4) ;.CPSWP GREATER THAN 0
>
SWPPI8: DSKON
JRST SWPPI1
;SUBROUTINE TO SEE IF A SWAP REQUEST MAY BE STARTED
;CALLED AT INTERRUPT LEVEL BY FILIO ON A POSITION-DONE INTERRUPT AND BY SWPPIK
;NON-SKIP RETURN IF CAN'T START IT NOW (FRAGMENTED, ANOTHER FRAGMENT IN PROGRESS)
;SKIP RETURN IF IO CAN BE STARTED
;PRESERVES T1,T2
SWPCH:
SWPCHK::HLRZ T3,UNISWA(U) ;FRAGMENTED?
JUMPE T3,CPOPJ1## ;NO, OK TO START
HRL T3,(T3)
MOVSS T3 ;YES, GET START OF CHAIN
SWPCH1: SKIPN T4,(T3) ;GET FRAGMENT POINTER
PJRST CPOPJ1## ;DONE - OK TO START
JUMPL T4,[HRR T3,T4
JRST SWPCH1]
TLNE T4,(SL.IOP) ;IN PROGRESS?
CAMN T3,UNISWA(U) ;YES, IS IT THE ONE WE WANT TO START?
AOJA T3,SWPCH1 ;THIS ONE IS OK, CHECK NEXT
POPJ P, ;IO ALREADY HAPPENING - QUEUE THIS TILL LATER
IFN FTMP,<
;RETURNS CPOPJ IF ON OTHER CPU, CAUSES SWAP READ ERROR IF OTHER CPU IS DEAD
; RETURN CPOPJ1 IF ON THIS CPU
;PRESERVES T1,T2
SWPCD: PUSHJ P,SWPCP ;ON THIS CPU?
CAIA ;NO
JRST CPOPJ1## ;YES, ON THIS CPU RETURN
MOVSI T3,(CR.DET) ;CPU IS DETACHED BIT
TDNN T3,.C0RUN##(T4) ;CPU DETACHED?
POPJ P,
>
SWPCD1: PUSHJ P,SAVT## ;PRESERVE T1,T2 - SAVE T4
PUSHJ P,SW2LC ;INDEX INTO SW2LST
MOVE T4,SW2LST##(T1) ;ORIGINAL SWPLST ENTRY
TLO T4,(SL.ERR+SL.IOP) ;ERROR + I/O IN PROGRESS
PJRST DONE1 ;SET IT DONE
IFN FTMP,<
;RETURNS CPOPJ IF ON OTHER CPU, CPOPJ1 IF ON THIS
;PRESERVES T1,T2
;RETURNS CDB OFFSET IN T4 *ONLY* ON NON-SKIP RETURN
SWPCP: MOVE T4,UDBCAM(U) ;CPU THAT THIS KONTROLLER IS ON
TDNE T4,.CPBIT## ;THIS CPU?
JRST CPOPJ1## ;YES, DO THE I/O NOW
IFN FTDUAL,<
SKIPN T3,UNI2ND(U) ;SECOND PORT
JRST SWPCP1
MOVE T3,UDBCAM(T3) ;2ND PORT ON THIS CPU?
TDNN T3,.CPBIT##
JRST SWPCP1 ;NO
HRRZ U,UNI2ND(U) ;SWITCH TO OTHER PORT
MOVE J,UDBKDB(U) ;KONTROLLER FOR SECOND PORT
JRST CPOPJ1## ;DO I/O NOW RETURN
SWPCP1:
>
PUSH P,T1 ;SAVE AC
PUSH P,T2
PUSHJ P,GETCAM## ;BUILD COMBINED CPU BIT MASK
PUSHJ P,CAMCPU## ;PICK BEST CPU
MOVEI T4,(T1) ;COPY CPU NUMBER
IMULI T4,.CPLEN## ;TRANSLATE TO CDB OFFSET
JRST TTPOPJ##
> ;END IFN FTMP
;SUBROUTINE TO GET THE NEXT ENTRY FROM SWPLST
;CALL WITH P1=0 ON FIRST ENTRY
;SUBSEQUENTLY CALL WITH P1,P2=NUMBERS RETURNED FROM THE LAST CALL
;RETURNS CPOPJ IF NO MORE ENTRIES
;RETURNS CPOPJ1 WITH P1 POINTING AT NEXT ENTRY,
; U=LOC OF UNIT DATA BLOCK, T1=PHYSICAL DSK BLOCK NUMBER
NEXT: JUMPN P1,NEXT2 ;FIRST CALL?
PUSHJ P,UUOLVL## ;IF AT UUO LEVEL
JRST NEXT1 ;AVOID CHANGING THE UBR
HRRZ P1,.USSLX ;BY FINDING ONLY THE ENTRY FOR THIS JOB
MOVE T1,SWPLST##(P1)
TLNE T1,(SL.IOP!SL.IOD) ;ALREADY STARTED?
POPJ P, ;YES, GO AWAY
MOVEI P2,1
MOVEI P1,SWPLST##-1(P1)
JUMPL T1,NEXT9 ;IF FRAGMENTED
JRST NEXT7
NEXT1: MOVEI P1,SWPLST##-1 ;YES, INITIALIZE P1
SKIPN P2,SPRCNT## ;ONLY LOOK AT SWAPS IF THERE ARE ANY
SKIPA P2,SLECNT## ;P2=NUMBER OF ENTRIES IN SWPLST
ADD P2,SWPCNT##
NEXT2: JUMPE P2,CPOPJ## ;NON-SKIP RETURN IF NO MORE ENTRIES
NEXT3: SKIPA T2,[TLNN T1,(SL.IOP)] ;ASSUME NOT A FRAGMENTED ENTRY
NEXT4: MOVE T2,[TLNE T1,(SL.IOP)] ;IF IT IS A FRAGMENTED ENTRY
NEXT5: SKIPN T1,1(P1) ;IS THERE ANOTHER ENTRY IN SWPLST?
JRST NEXT11 ;MAYBE (IF WE'RE IN A FRAGMENT CHAIN)
SKIPE SPRCNT## ;IF ANY SWAPS WAITING,
TLNE T1,(SL.SIO) ;IF THIS IS A SWAP REQUEST
SKIPA T4,SINCNT## ; TEST IT
JRST NEXT11 ;PAGE REQUEST - IGNORE FOR NOW
JUMPL T1,NEXT9 ;SWAP, IS IT A FRAGMENT POINTER?
JUMPE P2,NEXT6 ;IGNORE SINCNT IF FRAGMENT IN PROGRESS
TLNE T1,(SL.DIO) ;NO, IF AN OUTPUT REQUEST
JUMPG T4,NEXT11 ; IGNORE IT IF ANY INPUT REQUESTS WAITING
NEXT6: XCT T2 ;IS IT USABLE?(SL.IOP=0 IF NOT IN A FRAGMENT CHAIN
; , SL.IOP=1 IF IN A FRAGMENT CHAIN)
TLNE T1,(SL.IOD) ; AND SL.IOD=0
AOJA P1,NEXT13 ;NO, TRY NEXT
TLZN P1,400000 ;FIRST TIME FOR THIS ENTRY?
TLNN P1,-1 ;NO, IN A FRAGMENT?
JRST NEXT7 ;NO, USE THIS ENTRY
MOVSI T4,(SL.MAP) ;MAP INFO IN THIS ENTRY BIT
TLNN T1,(SL.DIO) ;YES, SWAPPING OUT?
JRST NEXT7 ;NO, ALL IS WELL
SKIPE 2(P1) ;YES, LAST ENTRY IN THE FRAGMENT?
TDNE T4,1(P1) ;MAP INFO THIS ENTRY AS BAD AS LAST
JRST NEXT11 ;YES, CANT USE IT (CANT WRITE UPMP TILL ALL
; DSK ADDRESSES ARE FILLED IN)
NEXT7:
IFN FTMP&FTKL10,<
TLNE T1,(SL.DIO) ;IF PAGING OUT
TLNE T1,(SL.SIO) ;(NOT SWAPPING)
JRST NEXT8
PUSHJ P,SW2LC
TLNE P1,-1
SUBI T1,1
HRR J,SW3LST##+1(T1) ;GET JOB NUMBER
PUSHJ P,SBCCSH## ;IS IT RIGHT WRT CACHE?
SKIPA T1,1(P1) ;YES, DO IT
JRST NEXT11 ;NO, TRY SOMEONE ELSE
>
NEXT8: PUSHJ P,SWPMEM ;YES, GET DSK ADR, UNIT
JRST NEXT11 ;SWPLST IS ZERO!
TLNN P1,-1 ;A MAIN ENTRY?
SUBI P2,1 ;YES, DECREMENT NO OF ENTRIES LEFT
AOJA P1,CPOPJ1## ;AND SKIP-RETURN
;HERE ON A POINTER TO A FRAGMENT
NEXT9: HLRZ T3,P1 ;T3 NON-0 IF NOT FIRST LINK (FATHER NOT SWPLST ENTRY)
JUMPN T3,NEXT10 ;GO IF NOT FIRST TIME IN THIS FRAGMENT
TLNE T1,(SL.IOD!SL.IOP) ;I/O ALREADY STARTED OR DONE?
JRST NEXT11 ;DONE, ERROR, OR ACTIVE, NEXT ENTRY
MOVE T4,T1 ;SAVE THIS PIECE
PUSHJ P,SW2LC ;WE THINK WE FOUND A USABLE ENTRY
MOVE T4,SW2LST##+1(T1) ;TO SEE WHAT WE MUST LOOK FOR
MOVE T1,1(P1) ;OK - RESTORE SWPLST ENTRY TO T1
MOVSI P1,400001(P1) ;SAVE POINT IN SWPLST WHERE WE TURNED DOWN
SOJL P2,CPOPJ## ;COUNT THE ENTRY
NEXT10: HRRI P1,-1(T1) ;SET RH(P1) FOR 1ST THING IN CHAIN
JUMPN T3,NEXT5 ;T2 SET UP RIGHT IF NOT 1ST LINK
JUMPE T4,NEXT3 ;IF ANOTHER FRAG THIS ENTRY NOT
;BEING DONE, ANY PART IS OK
SETZ P2, ;MAKE SURE THIS ENTRY IS PICKED
JRST NEXT4
;HERE WHEN AT END OF CHAIN
NEXT11: JUMPLE P2,CPOPJ## ;RETURN IF ALL ITEMS IN SWPLST SCANNED
TLNN P1,-1 ;NOT END, IN A FRAGMENT?
AOJA P1,NEXT12 ;NO, TRY NEXT SWPLST ENTRY
HLRZS P1 ;RESTORE MAIN LOC IN SWPLST IF FRAGMENT
TRZ P1,400000 ;BIT IS ON IF FOUND NOTHING
NEXT12: CAIL P1,SW2LST## ;REACHED END?
POPJ P, ;YES (DUAL CPU, OTHER CPU IN ZERSLE)
JRST NEXT3
NEXT13: TLNE P1,-1 ;FRAGMENT?
JRST NEXT5 ;YES, P2 ALREADY DECREMENTED
SOJG P2,NEXT5 ;NO, DECR P2 AND TRY NEXT
POPJ P, ;ALL DONE - RETURN
;SUBROUTINE TO GET THE BLOCK NUMBER FOR THIS SWPLST ENTRY
;CALL P1= LOC OF ENTRY
;RETURNS CPOPJ1 WITH U SET UP, T1= BLOCK NUMBER
;RETURNS CPOPJ IF THINGS ARE MESSED UP
THSBLK: SKIPN T1,(P1) ;GET SWPLST ENTRY
STOPCD CPOPJ##,DEBUG,NSE, ;++NO SWPLST ENTRY
; PJRST SWPMEM ;FALL INTO SWPMEM
;SUBROUTINE TO OBTAIN THE DISK ADDRESS FROM MEMTAB
;ENTER WITH T1=SWPLST ENTRY
;RETURN CPOPJ1 WITH U, T1 SET TO DISK ADDRESS
;RETURNS CPOPJ IF THINGS ARE MESSED UP
SWPMEM: SE1ENT ;MUST BE IN SECTION 1 TO REFERENCE MEMTAB
LDB T1,[POINT 13,T1,26] ;GET PHYSICAL PAGE NUMBER
SSX T1,MS.MEM ;MEMTAB SECTION
SKIPN T1,MEMTAB(T1) ;GET DSK ADDRESS
STOPCD CPOPJ##,DEBUG,MIZ, ;++MEMTAB IS ZERO
SWPADR::LDB U,SSUNT1## ;GET SWAP UNIT
MOVE U,SWPTAB##(U)
JUMPL U,CPOPJ1## ;UNIT GONE, BUT WE EXPECTED IT
SKIPE U
SKIPG UNISLB(U)
STOPCD .,STOP,SBZ, ;++SWAP BLOCK ZERO
LDB T1,SLKNT1## ;1ST LOGICAL K
ROT T1,BLKSPP ;CONVERT TO BLOCKS
ADD T1,UNISLB(U) ;PLUS STARTING BLOCK NUMBER
JRST CPOPJ1## ;RETURN
;SUBROUTINE TO BE CALLED WHEN IO IS FINISHED. ENTERED AT INTERRUPT LEVEL FROM FILIO
;CALLED WITH P1=LOC OF SWPLST ENTRY, T1= NUMBER OF BLOCKS TRANSFERRED, P2=ERROR BITS
DONE:: MOVE T2,(P1) ;SWPLST ENTRY
MOVEI T3,UNIICT(U) ;SET CORRECT UNIT WORD TO
TLNN T2,(SL.IPC) ;IPC AND PAGE QUEUES ARE PAGING I/O
TLNN T2,(SL.SIO) ; COUNT THE IO (SWAP OR PAGE, IN OR OUT)
MOVEI T3,UNIPCI(U)
TLNE T2,(SL.DIO)
ADDI T3,1
ADDM T1,(T3)
PUSHJ P,SW2LC ;GET INDEX INTO 2ND TABLE
MOVE T4,SW2LST##(T1) ;ORIGINAL SWPLST ENTRY
TRNE S,IODERR+IODTER+IOIMPM ;IO ERROR?
TLO T4,(SL.ERR) ;YES, SET BIT
TRNE P2,IOCHMP+IOCHNX ;CHAN-DETECTED ERROR?
TLO T4,(SL.CHN) ;YES
DONE1: HLRZ T3,P1 ;ORIGINAL SWPLST ENTRY IF A FRAGMENT
LDB T2,[POINT 9,(P1),35] ;NUMBER OF PAGES LEFT IN ENTRY
TLNN T4,(SL.ERR+SL.CHN) ;ABORT IF ERROR
JUMPN T2,DONE7
JUMPE T3,DONE2 ;NO, GO IF NOT IN A FRAGMENT
MOVSI T2,(SL.IOP) ;IN A FRAGMENT - CLEAR THE IOP BIT
ANDCAM T2,(T3) ; IN THE SWPLST ENTRY ITSELF
DONE2: TLZE T4,(SL.IOP) ;CLEAR IN-PROGRESS BIT
TLOE T4,(SL.IOD+SL.DFM) ;SET DONE BIT
STOPCD .+1,DEBUG,SBW, ;++SWPLST BITS WRONG
SETZM SW2LST##(T1)
MOVEM T4,(P1) ;SAVE UPDATED SWPLST ENTRY
TLNE T4,(SL.CHN+SL.ERR)
HRRZM U,SWPEUJ## ;SAVE ADR OF UNIT
JUMPE T3,DONE6 ;FINISHED IF NONE
TLNE T4,(SL.ERR+SL.CHN) ;IF AN ERROR,
JRST DONE5 ; DONT WASTE TIME BY CONTINUING
SKIPL T1,(T3) ;GET ADR OF START OF CHAIN
STOPCD DONE5,DEBUG,NRF, ;++SWPLST NOT REALLY FRAGMENTED
DONE3: SKIPN T2,(T1) ;LOOK AT NEXT ENTRY IN FRAGMENT CHAIN
JRST DONE5 ;WHOLE CHAIN DONE IF AT END
JUMPGE T2,DONE4 ;CHECK IT IF NOT ANOTHER POINTER
MOVE T1,T2 ;GO TO NEXT PART OF CHAIN
JRST DONE3
DONE4: TLNN T2,(SL.IOD) ;THIS FRAGMENT DONE?
POPJ P, ;NO, DONT WAKE UP SWAPPER
AOJA T1,DONE3 ;YES, TEST NEXT ENTRY OF FRAGMENT CHAIN
;HERE IF THE ENTIRE SWPLST FRAGMENT CHAIN IS FINISHED
DONE5: HLLZS T4 ;INDICATE DONE, ERROR BIT IF ON
IORB T4,(T3)
HLRZS P1 ;POINT TO SWPLST
DONE6: HRLOI T1,377777 ;SET UNISWD HUGE
IFN FTDUAL,<
SKIPE T2,UNI2ND(U)
MOVEM T1,UNISWD(T2)
>
MOVEM T1,UNISWD(U)
TLNE T4,(SL.IPC) ;IF IPC PAGING
TLNN T4,(SL.DIO) ; OUT
JRST SWPINT##
TLNN T4,(SL.SIO) ;DON'T IF REALLY SWAPPING REPLACABLE QUEUE
AOS IPCCNT## ;BUMP A COUNT
PJRST SWPINT## ;KICK THE SWAPPER
;HERE IF THE SWPLST ENTRY WASN'T ENTIRELY PROCESSED
DONE7: SKIPN T3 ;IN A FRAGMENT?
MOVEI T3,(P1) ;NO, PICK UP ADDR OF ENTRY
MOVSI T1,(SL.IOP) ;CLEAR THE IO IN PROGRESS BIT
ANDCAM T1,(T3) ; SO NEXT WILL CONSIDER THIS ENTRY AGAIN
POPJ P, ;AND RETURN
;SUBROUTINE TO SET UP AN IOLIST FOR A SWAP/PAGE OPERATION
;ENTER P1=LOC OF SWPLST ENTRY, T3= MAX NUMBER OF BLOCKS TO DO
;EXIT P3=LOC OF 1ST IOWD, T1= NUMBER OF BLOCKS IN LIST
THIS:: PUSHJ P,GETSWJ ;GET JOB NUMBER
PUSHJ P,SVEUB## ;SET UP MAPPING
PUSHJ P,SAVE4## ;SAVE P'S
LSH T3,-2 ;CONVERT BLOCKS TO PAGES
MOVE P4,(P1) ;GET SWPLST ENTRY
LDB P2,[POINT SL.SCT,P4,<^L<SL.CNT>+SL.SCT-1>] ;NUMBER OF PAGES REQUIRED
MOVE T2,P2
CAMLE P2,T3 ;NEED MORE THAN WE CAN DO?
MOVE P2,T3 ;YES, SETTLE FOR LESSER AMOUNT
SUB T2,P2 ;AMOUNT LEFT AFTER THIS OPERATION FINISHED
SKIPN P2 ;REALLY ANYTHING TO DO?
STOPCD .,STOP,ZPS, ;++ZERO PAGE SWAP
PUSH P,T2
TLO P4,(SL.IOP) ;INDICATE IO IN PROGRESS
PUSHJ P,SW2LC
SKIPN SW2LST##(T1) ;IF THE FIRST TIME,
MOVEM P4,SW2LST##(T1) ; SAVE THE SWPLST ENTRY IN DUPLICATE TABLE
DPB T2,[POINT SL.SCT,P4,<^L<SL.CNT>+SL.SCT-1>] ;UPDATE SWPLST ENTRY WITH NEW COUNT
MOVEM P4,(P1)
MOVE T2,P2 ;NUMBER OF PAGES WE'LL DO
LSH T2,2 ;CONVERT TO BLOCKS
EXCH T2,(P)
PUSH P,T2 ;SAVE (RETURN NUMBER TO FILIO)
DSKOFF ;PROTECT AGAINST S BEING CHANGED AT
; INTERRUPT LEVEL
TLNE P4,(SL.DIO) ;INPUT OR OUTPUT?
TLOA S,IO ;OUTPUT
TLZ S,IO ;INPUT
TRZ S,IODTER+IODERR+IOIMPM
MOVEM S,DEVIOS(F) ;SAVE UPDATED S
IFN FTKL10,<
SETZ P1, ;WE NEED AN IOWD
PUSHJ P,GCH4WD## ;GET A LOW-CORE BLOCK FOR THE IOLIST
JRST THIS21 ;CANT GET ONE!
MOVE P1,T1 ;ADR IN P1
HRLI P1,-3 ;CAN SAVE 3 IOWD'S WITH NO HASSLE
MOVEM T1,-5(P) ;RETURN INITIAL IOWD LOC IN P2
>
PUSH P,U ;SAVE U
IFN FTKS10,<
MOVE P1,CHNIMR(P3) ;GET ADDRESS OF INITIAL MAPPING REGISTER
MOVEI T4,UBAEXP ;GET INITIAL MAPPING REGISTER ADDRESS
SUBM P1,T4 ;DISPLACEMENT OF THIS DEVICES FIRST
IMULI T4,UBAMUL ;MAKE INTO AN ELEVEN STYLE ADDRESS
MOVEM T4,CHNIEA(P3) ;AND SAVE AS INITIAL ELEVEN ADDRESS
HLL P1,CHNUBA(P3) ;GET UBA NUMBER
PUSH P,CHNMRC(P3) ;SAVE FOR LATER
>
MOVEI U,0 ;U=0 FOR 22-BIT CHAN
IFN FTKL10,<
MOVE T2,CHNTYP(P3) ;GET CHANNEL TYPE BITS
TLNE T2,CP.RH2!CP.KLP ;RH20 OR KLIPA?
MOVEI U,2 ;YES
>
TLNN P4,(SL.SIO) ;SWAPPING?
TLO U,1 ;NO, PAGING, REMEMBER THAT (SEC # FROM MEMTAB)
TLNE P4,(SL.IPC) ;IPCF?
TLOA U,400000 ;INDICATE BY U NEGATIVE
PUSHJ P,[EXCH P1,<-10-IFN FTKS10,<1>>(P)
PUSHJ P,GETVPN
EXCH P1,<-10-IFN FTKS10,<1>>(P)
POPJ P,]
LDB P4,[POINT 13,P4,26] ;PHYSICAL PAGE TO START IO AT
JUMPL U,THIS3 ;IF IPCF OR PAGING QUEUE
HRRZ T2,JBTUPM##(J) ;SWAPPING THE UPMP?
CAIG J,JOBMAX## ;IF HIGH SEG OR
CAIE T2,(P4) ;NOT SWAPPING UPT
JRST THIS4 ;PROCEED
TLO U,500000 ;YES, NO NEXT PAGE+"THIS IS UPT" BIT
TLNN S,IO ;INPUT?
TLO U,200000 ;YES, FLAG INPUT OF UPT
SKIPGE U
THIS3: SETO P3, ;BE SURE NON-ZERO AT THIS15 IF WE WANT IT TO BE
;HERE WITH P4=PAGE NUMBER OF THE BEGINNING PHYSICAL PAGE OF THE IO
;AND P3=POINTER TO VIRTUAL SLOT IF SWAPOUT
THIS4:
IFN FTKL10,<
MOVE T2,[400000+T1,,1] ;SET TO COUNT CONTIGUOUS PAGES (IOWD FOR KL)
>
IFN FTKS10,<
POP P,T2 ;RESTORE SAVED UMR COUNT
>
THIS5:
IFN FTXMON,<
XJRST [MCSEC1+.+1] ;ENTER SECTION 1 FOR PAGTAB/MEMTAB REFERENCES
>
MOVE T1,P4 ;STARTING PAGE
THIS6: SSX P4,MS.MEM ;SET SECTION INDEX FOR PAGTAB/MEMTAB
SKIPGE MEMTAB(P4) ;IS THIS LAST PAGE IN FRAGMENT?
SOJN P2,@[0,,THIS27] ;YES, SOMEONE IS CONFUSED IF NOT LAST PAGE
JUMPL U,THIS10 ;GO IF IPCF/PAGING QUEUE
LDB T4,[POINT MT.SAD,MEMTAB(P4),<^L<MT.DAD>+MT.SAD-1>] ;DSK ADR OF THIS PAGE
TLNN S,IO ;IF SWAPPING OUT,
JRST THIS7 ;NO, DON'T CHANGE PAGE MAP
MOVE T3,(P3) ;GET CURRENT MAP CONTENTS
AND T3,[PM.BTS-PM.COR] ;SAVE THE BITS
IOR T4,T3
MOVEM T4,(P3) ;SAVE ADDR IN UPMP
THIS7: JUMPE P2,THIS11 ;GO IF LAST PAGE
LDB T4,NVPNP4 ;GET NEXT VIRTUAL PAGE #
CAIN T4,.UPMVP/PAGSIZ ;UPMP?
TLO U,500000 ;YES, DONT WIPE OUT SLOT IN MAP
THIS9: TLNN S,IO ;INPUT?
TLZ U,400000 ;YES, STOP ON COUNT EXHAUSTED
CAIG J,JOBMAX## ;LOW OR HIGH SEG?
SKIPA P4,[GMPTR] ;LOW SEG
MOVEI P4,GMHPTR ;HIGH SEG
PUSHJ P,(P4) ;GET POINTER FOR MAP
MOVE P4,(T4) ;GET MAP ENTRY
TLZ P4,(PM.NAD) ;CLEAR BITS
SKIPA P3,T4 ;POINTER FOR NEXT DEPOSIT
THIS10: HRRZ P4,PAGTAB(P4) ;HI-SEG GETS NEXT PAGE FROM PAGTAB
IFN FTKL10,<
HRRZ T4,U ;LEFT HALF = 0 FOR INDEXING
CAIN P4,@T2 ;PAGES CONTIGUOUS?
CAML T2,MAXCNT(T4) ;YES, BELOW MAX SIZE OF AN IOWD?
SOJA P2,THIS11 ;NO, MAKE THE IOWD
CAMN T2,[400000+T1,,27] ;DON'T BUILD AN IOWD
SOJA P2,THIS11 ; THAT LOOKS LIKE AN RH20 GOTO WORD
SOJLE P2,THIS11 ;MAKE THE IOWD IF DONE
AOJA T2,THIS6 ;PAGE IN IOWD - COUNT AND TRY NEXT PAGE
>
;HERE TO FINISH THE IOWD/MAPPING REGISTER
THIS11:
IFN FTXMON,<
JRST @[0,,.+1] ;RETURN TO SECTION 0
>
IFN FTKL10,<
IMULI T2,-PAGSIZ ;COMPUTE WORDCOUNT
LSH T1,P2WLSH ;CONVERT BEGINNING PAGE NUMBER TO ADDRESS
TRNN U,2 ;IF NOT AN RH20,
SOJA T1,THIS12 ; ADDR-1
MOVNS T2 ;RH20 - ADDR RATHER THAN ADR-1
TRO T2,<(INSVL.(.CCFDT,CC.OPC)_-4)> ;+WDCNT, TRA BIT
THIS12: DPB T2,PNTCNT(U)
MOVEM T1,(P1) ;SAVE IOWD IN LOCORE BLOCK
ADDI T1,1 ;ADDRESS OF 1ST WORD TO TRANSFER
AND T1,MSK22B## ;GET ADDRESS
JUMPLE P2,THIS13 ;DONE IF P2=0
AOBJN P1,THIS4 ;MORE TO DO, GET NEXT CHUNK
PUSHJ P,GETMOR## ;NEED ANOTHER 4-WORD BLOCK
JRST THIS20 ;NONE AVAILABLE
JRST THIS4 ;GOT IT, DO NEXT CHUNK
>; END FTKL10
IFN FTKS10,<
TRO T1,UNB36B!UNBVBT ;SET 36 BIT MODE AND VALID BIT
WRIO T1,(P1) ;LOAD THE MAPPING REGISTER
ADDI P1,1 ;POINT TO NEXT MAPPING REGISTER
SOJLE P2,THIS13 ;DONE IF P2=0
SOJG T2,THIS5 ;IF UMR AVAILABLE, CONTINUE
MOVE T2,-7(P) ;OOPS, RAN OUT OF MAPPING REGISTERS
ADDM P2,(T2) ;INCREASE # PAGES LEFT TO DO
LSH P2,2
ADDM P2,-1(P) ;UPDATE # BLOCKS LEFT AFTER THIS IO
MOVNS P2
ADDM P2,-2(P) ;UPDATE # BLOCKS DONE THIS OPERATION
SOJA P1,THIS13 ;FINISH UP, START THE IO
>; END FTKS10
;HERE WHEN ALL REQUIRED IOWDS HAVE BEEN BUILT
THIS13:
IFN FTKL10,<
SETZM 1(P1) ;TERMINATE THE LIST
AOS T3,P1 ;POINT AT TERMINATION WORD
TRNN U,2 ;RH20?
JRST THIS14 ;NO
MOVSI T1,(CC.HLT) ;YES, INDICATE LAST IOWD
IORB T1,-1(P1)
LDB T2,[POINT 11,T1,13] ;WORDCOUNT
TLZ T1,077760 ;CLEAR WDCNT FIELD
ADD T1,T2 ;ADDR + N
JRST THIS15 ;STORE IN CHNTCW AND CONTINUE
THIS14: HLRO T1,-1(P1) ;WORD COUNT OF LAST IOWD
LDB T2,ADRPT2##(U) ;WHERE DATA ASSOCIATED WITH LAST IOWD
ASH T1,@ASH22B##(U) ; WILL START
SUBM T2,T1 ;WHERE LAST DATA ITEM WILL GO
DPB P1,ADRPT4##(U) ;WHERE TERMINATION WORD WILL BE FETCHED FROM
THIS15: MOVE T2,-5(P) ;ADDRESS OF THE CHANNEL DATA BLOCK
MOVEM T1,CHNTCW(T2) ;STORE WHAT CHANNEL TERMINATION WORD SHOULD LOOK LIKE
>
IFN FTKS10,<
MOVE T2,-5(P) ;ADDRESS OF THE CHANNEL DATA BLOCK
HLL P1,CHNIMR(T2) ;RESTORE LEFT HALF
SUB P1,CHNIMR(T2) ;GET NUMBER OF MAPPING REGISTERS USED
LSH P1,P2WLSH+2 ;MAKE INTO WORDS, 11 STYLE
MOVEM P1,CHNTCW(T2) ;STORE ADDRESS OF LAST WORD TO BE TRANSFERRED
SUB P1,CHNIEA(T2) ;COMPUTE TOTAL NUMBER OF BYTES IN TRANSFER
MOVEM P1,CHNBTC(T2) ; AND PUT IT HERE
>
SKIPN -1(P) ;WILL THIS BE THE LAST IO?
SETZB P3,P4 ;YES
TLNE U,200000 ;UPMP SWAP IN?
JRST THIS16 ;YES
MOVE P1,-7(P) ;ORIGINAL SWPLST ENTRY ADDRESS
MOVSI T1,(SL.IPC) ;PAGING QUEUE BIT
TLNE S,IO ;INPUT?
TDNE T1,(P1) ;NO, PAGING QUEUE?
JRST THIS16 ;INPUT OR PAGING QUEUE
PUSHJ P,SETVPN ;YES, SET VPN IN .USLPS OR TABLE
THIS16: JUMPE P3,THIS18 ;GO IF NO MORE TO DO
DPB P4,[POINT SL.SPN,(P1),<^L<SL.PPN>+SL.SPN-1>]
HLRZS P1 ;SWPLST ENTRY FOR MAIN WORD
JUMPE P1,THIS18 ;GO IF NOT IN A FRAGMENT
MOVSI T1,(SL.IOP)
IORM T1,(P1) ;INDICATE IN A FRAGMENT FOR NEXT
; (SO WILL ONLY PICK THIS PIECE)
THIS18: TLNE S,IO ;IN OR OUT?
TLZN U,100000 ;;OUT, JUST SWAP THE UPT?
JRST THIS19 ;NO
SKIPE .USLPS ;DID WE STOP JUST BEFORE THE UPT?
JRST THIS19 ;YES, WE'LL GET IT NEXT TIME THEN
MOVE T1,NLUPMP##+.UMUPT ;YES,GET POINTER TO NULL UPMP
MOVEM T1,.UPMP+.UMUPT
THIS19: POP P,U ;RESTORE U
POP P,(P) ;FIX STACK
POP P,T1 ;NO OF BLOCKS TO TRANSFER
SKIPE DINITF##
POPJ P,
TLNN S,IO
ADDM T1,.CPSBI## ;COUNT TOTAL SWAPPING BLOCKS
TLNE S,IO
ADDM T1,.CPSBO##
POPJ P, ;AND RETURN
;HERE IF WE RAN OUT OF LOWER CORE BLOCKS
THIS20: HRRZ T1,-7(P)
ADDM P2,(T1) ;INCREASE # PAGES LEFT TO DO
LSH P2,2
ADDM P2,-1(P) ;UPDATE # BLOCKS LEFT AFTER THIS IO
MOVNS P2
ADDM P2,-2(P) ;UPDATE # BLOCKS DONE THIS OPERATION
SOJA P1,THIS13 ;FINISH UP, START THE IO
;HERE IF THERE WASNT A LOWER-CORE BLOCK TO START AT
THIS21: ADD P4,P2 ;MAKE P4 THE SWPLST ENTRY AGAIN
TLZ P4,(SL.IOP)
HRRZ P1,-6(P) ;RESET P1
MOVEM P4,(P1) ;SAVE BACK IN SWPLST
POP P,(P) ;CLEAR GARBAGE OFF LIST
SETZB T1,-4(P) ;INDICATE 0 BLOCKS TRANSFERRED
PJRST T2POPJ## ;RETURN TO FILIO
;HERE ON VARIOUS ERRORS
THIS27: STOPCD THIS13,DEBUG,IPM, ;++ILLEGAL POINTER IN MEMTAB
;SUBROUTINES TO MANIPULATE VIRTUAL PAGE NUMBERS FOR SWAPOUT
;GET/SETVPN:
; MOVE P1,SWPLST-POINTER ;SWPLST,,FRAG OR 0,,SWPLST
; PUSHJ P,{GET|SET}VPN ;CALL ROUTINE
; <ONLY RETURN, FOR GETVPN - P3 CONTAINS VIRTUAL POINTER>
GETVPN: SE1ENT ;NEED TO BE IN S1 FOR HIGH SEGS
CAILE J,JOBMAX## ;JOB?
SKIPA P3,JBTVAD##(J) ;ADDRESS OF MAP
SKIPA P3,.USLPS ;JOB, GET POINTER FROM UPT
HRRZ P3,.M2VPN-.M2MAP(P3) ;GET ENTRY
TLNN P1,-1 ;FRAGMENTED SWPLST ENTRY?
JRST GETVPR ;NOT FRAGMENTED
PUSHJ P,FRGIDX ;GET FRAGMENT INDEX
ADDI P3,(T1) ;POINTER INTO TABLE
MOVE P3,(P3) ;AND ENTRY
GETVPR: CAILE J,JOBMAX## ;IF A HIGH SEG
ADD P3,JBTVAD##(J) ;CONVERT TO MAP POINTER
POPJ P,
SETVPN: SE1ENT ;NEED TO BE IN S1 FOR HIGH SEGS
CAILE J,JOBMAX## ;JOB?
SKIPA T2,JBTVAD##(J) ;JBYVAD IF HIGH SEG
SKIPA T2,[.USLPS] ;NO, STORE FOR CURRENT JOB
XMOVEI T2,.M2VPN-.M2MAP(T2) ;POINT TO VPN TABLE AREA FOR HIGH SEG
TLNN P1,-1 ;FRAGMENTED?
JRST SETVP5 ;NO
PUSHJ P,FRGIDX ;COMPUTE A FRAGMENT INDEX
HRRZ T2,(T2) ;RELOCATE
ADD T2,T1 ;PLACE TO STORE
SETVP5: JUMPE P3,SETVP6 ;(ZERO IS A SPECIAL CASE)
CAILE J,JOBMAX## ;ELSE, IF HIGH SEG,
SUB P3,JBTVAD##(J) ;CONVERT BACK TO RELATIVE POINTER
SETVP6: MOVEM P3,(T2) ;STORE
POPJ P,
;ROUTINE TO COMPUTE FRAGMENT TABLE OFFSET
;CALL WITH P1=SWPLST POINTER (SW2LC FORMAT)
;EXIT WITH T1=OFFSET INTO FRAGMENT VIRTUAL TABLE
FRGIDX: PUSH P,T2 ;GET AN AC
SETZ T1, ;COUNTER
HLRZ T2,P1 ;GET START OF CHAIN
HRRZ T2,(T2) ;FIRST FRAGMENT
FRGID2: CAIN T2,(P1) ;IS THIS THE RIGHT ENTRY?
JRST T2POPJ## ;YES, RETURN
AOS T1 ;NO, SET FOR NEXT
SKIPL 1(T2) ;POINTER TO NEXT
AOJA T2,FRGID2 ;NO
HRRZ T2,1(T2) ;GET NEXT BLOCK
JRST FRGID2 ;START LOOKING THERE
;SUBROUTINE TO GET SUFFICIENT FREE CORE TO BUILD THE VPN TABLE
;CALL:
; MOVE T1,FRAGMENT TABLE
; PUSHJ P,BLDVPN
; <NOT ENOUGH FREE CORE>
; <NORMAL RETURN, POINTER TO TABLE IN T2>
BLDVPN::SETZ T2, ;T2 COUNTS WORDS
JUMPGE T1,CPOPJ1## ;NOT REALLY FRAG'D?
HRRZS T1
BLDVP1: SKIPN T3,(T1) ;DONE?
JRST BLDVP4 ;YES
JUMPL T3,[HRRZ T1,T3 ;POINTER TO ANOTHER ENTRY
JRST BLDVP1] ;LOOP BACK
AOS T2 ;ONE MORE WORD WE NEED
AOJA T1,BLDVP1 ;LOOP
BLDVP4: AOS T2 ;ONE MORE WORD FOR COUNT
PUSH P,T2 ;SAVE # OF WORDS
PUSHJ P,GETWDS## ;GET THE CORE
JRST T2POPJ## ;NOT THERE
POP P,(T1) ;REMEMBER THE COUNT
AOS T2,T1 ;AND RETURN +1 AS THE ADDRESS
MOVE T1,-1(T2) ;GET COUNT AGAIN
TRZE T1,3 ;ROUND TO NEAREST MULTIPLE OF 4
ADDI T1,4 ;TO ENSURE LINK WORD IS ZERO IN CASE
ADDI T1,-1(T2) ;THIS EVER GETS USED FOR SWPLST ENTRY
SETZM -1(T1) ;ZAP IT
JRST CPOPJ1## ;GOOD RETURN
;SUBROUTINE TO RETURN THE VPN TABLE POINTED TO BY JOB OR HIGH SEG J
;USES T1,T2
RTNVPN::CAILE J,JOBMAX## ;JOB OR HIGH SEG?
JRST RTNVPH ;HIGH SEG
PUSHJ P,SVEUB## ;JOB, MAP IT
SKIPN T2,.USLPS ;IS THERE A POINTER?
POPJ P, ;NO, JUST RETURN
;(NO GOOD TO ZERO .USLPS SINCE NON-ZERO ON DSK)
RTNVPC: MOVE T1,-1(T2) ;GET COUNT
SOS T2 ;ADDRESS
PJRST GIVWDS##
RTNVPH: SE1ENT ;NEED TO BE IN S1
LDB T1,JBYVAD## ;POINT TO MAP AREA
HRRZ T2,.M2VPN-.M2MAP(T1) ;GET POINTER TO VPN TABLE
JUMPE T2,CPOPJ## ;IF NOTHING TO DO
HLLZM .M2VPN-.M2MAP(T1) ;HIGH SEG MAP STAYS IN CORE
JRST RTNVPC ;JOIN COMMON CODE
;SUBROUTINE TO SET UP J FROM SWPLST ENTRY
;ENTER P1 POINTING TO SWPLST
;EXITS WITH J NEGATIVE IF PAGING QUEUE; CPOPJ IF LOW SEG,
;CPOPJ1 IF HIGH SEG OR QUEUE
GETSWJ: PUSHJ P,SW2LC ;GET INDEX OF SWPLST ENTRY
HRRZ J,SW3LST##(T1) ;GET JOB NUMBER
MOVE T1,SWPLST##(T1) ;GET MAIN SWPLST ENTRY
TLC T1,(SL.SIO+SL.IPC) ;SWAPPING OUT THE REPLACABLE QUEUE?
TLNN T1,(SL.SIO+SL.IPC) ;?
TLOA J,-1 ;INDICATE PAGING QUEUE
CAILE J,JOBMAX## ;IF HIGH SEG OR PAGING QUEUE
AOS (P) ;GIVE SKIP RETURN
POPJ P, ;RETURN
;SUBROUTINE TO COMPUTE INDEX INTO SW2LST TABLE
;ENTER P1=ADDRESS IN SWPLST (OR FRAGMENT, ADR IN LH)
;EXIT T1=INDEX
;PRESERVES T2-T4
SW2LC:: TLNN P1,-1 ;POINTER TO A FRAGMENT?
SKIPA T1,P1 ;NO, USE MAIN ADDRESS
HLRZ T1,P1 ;YES, GET SWPLST LOCATION
TRZ T1,400000 ;SIGN BIT OF P1 MIGHT BE ON
SUBI T1,SWPLST## ;MAKE INTO AN INDEX
POPJ P, ;AND RETURN
SUBTTL SWPSER INTERFACE WITH THE SWAPPER
;SUBROUTINE TO SETUP SWPLST FOR SWAP OUT
BOSLST::PUSHJ P,SAVE4## ;SAVE ACS
CAILE J,JOBMAX## ;HI SEG?
JRST BOSLS5 ;YES, DO IT DIFFERENTLY
MOVEM T2,.USLPS ;VPN POINTER
SKIPL .USBTS ;GET BITS
TDZA T2,T2 ;NOT EXTENDED
MOVEI T2,MXSECN ;MAX SECTION TO TRY
MOVEM T2,.USSPT ;SECTION TO DO
MOVE T1,JBTADR##(J) ;SAVE JBTADR
HLLM T1,.USREL ; FOR SWAP-IN
MOVE T2,JBTSTS##(J)
TLNE T2,JXPN
MOVEM T1,.JDAT+JOBDPG##
MOVE T1,.JDAT+.JBPFH## ;GET JOBPFH
MOVEM T1,.USPFH ;AND SAVE IN UPMP FOR BISLST (MIGRATING JOB)
SKIPGE U,JBTSWP##(J) ;FRAGMENTED?
JRST BOSLS1 ;YES
LDB T1,IMGOUT## ;NO, GET SIZE TO SWAP OUT
SKIPLE JBTST2##(J) ;DEMAND PAGING?
SUB T1,.USWLP ;YES, DON'T WRITE OUT WRITE LOCKED PAGES
LDB T2,NFYPGS## ;ADD 1 PAGE FOR UPMP
ADD T1,T2
LDB J,NZSSCN## ;GET NUMBER OF NZS MAPS
ADDI J,(T1)
PUSH P,J ;SAVE NUMBER OF PAGES TO WRITE
PUSHJ P,SETOMT ;SETOMT WILL SET UP MEMTAB
MOVE J,.USJOB ;RESTORE JOB #
MOVEI T1,(P3) ;FIRST PHYSICAL PAGE
LSH T1,SL.SCT ;POSITION IT
POP P,T2 ;NUMBER OF PAGES TO WRITE
DPB T2,[POINT SL.SCT,T1,<^L<SL.CNT>+SL.SCT-1>] ;IN T1
HLRZ T4,P3 ;VIRTUAL PAGE #
PUSHJ P,GMPTR ;GET POINTER
MOVEM T4,.USLPS ;NOT FRAGMENTED
JRST BOSLS4 ;SET LH BITS AND STORE T1 IN SWPLST
;HERE IF LOW SEG SWAP OUT AND DISK SPACE IS FRAGMENTED
BOSLS1: MOVE P1,JBTSWP##(J)
; TLZ P1,FRGSEG
PUSH P,.USLPS ;INITIALIZE POINTER TO VPN TABLE
MOVSI P2,(SL.DIO+SL.SIO) ;SWPLST DESCRIPTORS
PUSHJ P,NXTFRG ;SET UP U FOR THIS FRAGMENT
STOPCD .+1,DEBUG,O1F, ;++ONLY 1 FRAGMENT
PUSHJ P,SETOMT ;SET UP MEMTAB
BOSLS2: DPB P3,[POINT SL.SPN,P2,<^L<SL.PPN>+SL.SPN-1>] ;STORE 1ST PAGE NUMBER OF FRAG
HLRZ T4,P3 ;VPN OF FIRST VIRTUAL PAGE
PUSHJ P,GMPTR ;GENERATE A POINTER
MOVEM T4,@(P) ;STORE
AOS (P) ;INCREMENT
MOVEM P2,-1(P1) ;STORE THE SWPLST FRAGMENT IN TABLE
PUSHJ P,NXTFRG ;GET U FOR NEXT FRAG
JRST BOSLS3 ;LAST FRAGMENT
MOVEI P3,0 ;P3=0 0N CALL TO SETOMT
PUSHJ P,[SE1ENT ;DO THIS IN SECTION 1
JRST SETOM8] ;SET UP MEMTAB FOR THIS FRAG
JRST BOSLS2 ;AND TRY NEXT
BOSLS3: POP P,(P) ;FIX STACK
PUSHJ P,[SE1ENT ;DO THIS IN SECTION 1
SSX F,MS.MEM ;MAKE A REAL POINTER TO MEMTAB
LDB U,[POINT MT.SAD,MEMTAB(F),<^L<MT.DAD>+MT.SAD-1>]
POPJ P,]
MOVE J,.USJOB ;RESTORE J
MOVE T1,JBTSWP##(J) ;ADDRESS OF FRAGMENT/SWPLST TABLE
;HERE WHEN DONE, T1=SWPLST ENTRY, U=DSK ADR OF UPMP
BOSLS4: HRRZS M ;IS THE UPMP THE LAST PAGE?
CAIE M,.UPMVP/PAGSIZ
STOPCD .,STOP,UNL ;++UPMP NOT LAST
MOVEM U,JBTSWP##(J) ;SAVE UPMP ADDR IN JBTSWP
TLO T1,(SL.DIO+SL.SIO) ;INDICATE SWAP OUT
MOVSI T2,(UP.PGB) ;INDICATE PAGES WILL BE GIVEN BACK
ANDCAM T2,.USBTS
JUMPL W,MAKSLE ;GO IF WORKING SET SWAPPING
LDB T2,IMGIN## ;YES, ADJUST SIZES FOR NEXT INPUT
LDB T3,IMGOUT## ; ..
SUB T2,T3 ;AMOUNT OF EXPANSION IF ANY
ADDI T2,1 ;ACCOUNT FOR PAGE 0
DPB T2,IMGIN## ;NEW INPUT SIZE
MOVEI T2,1 ;NEW OUTPUT SIZE
DPB T2,IMGOUT## ;STORE THAT
PUSHJ P,NCBPOP ;COUNT NUMBER OF CAN'T BE PAGED OUT PAGES
JFCL ;ALWAYS SKIPS
.CREF IMGIN,IMGOUT
ADDM T4,JBTIMI##(J) ;UPDATE COUNTS FOR NUMBER OF PAGES THAT
ADDM T4,JBTIMO##(J) ; CAN'T BE PAGED OUT
PJRST MAKSLE ;MAKE A SWPLST ENTRY AND RETURN
;HERE IF HIGH SEG SWAP OUT
BOSLS5: LDB P1,IMGOUT## ;SIZE OF OUTPUT IMAGE (NO PAGES TO SWAP)
HRLI P1,(SL.SIO+SL.DIO) ;SWPLST DESCRIPTORS
PJRST BHSLST ;GO DO IT
;SUBROUTINE TO SETUP SWPLST FOR SWAP IN OF UPMP
BUSLST::SE1ENT ;ENTER SECTION 1
CAILE J,JOBMAX## ;HI SEG?
JRST BUSLSH ;YES, DO DIFFERENTLY
PUSHJ P,SVEUB## ;MAKE THE JOB ADDRESSABLE
MOVE U,JBTSWP##(J) ;NO, GET DSK ADDR OF UPMP
HRRZ T1,JBTUPM##(J) ;PAGE NUMBER OF UPMP
TLO U,(MT.LEF) ;INDICATE ONLY 1 FRAGMENT
SSX T1,MS.MEM ;MAKE MEMTAB ADDRESSABLE
MOVEM U,MEMTAB(T1) ;MEMTAB FOR UPMP
LDB T2,JBYMAP## ;ADDRESS OF THE MAP
EXCH U,T2 ;PUT IN U
TLZ T2,(PM.NAD) ;CLEAR BITS
SOS T2
CAME U,T2 ;CONTIGUOUS?
JRST BUSLS2 ;NO, ALAS
HRR T1,PAGTAB(T1)
MOVEI T2,.UPMVP/PAGSIZ
DPB T2,NVPNT1 ;STORE POINTER TO NEXT WHICH IS UPT
MOVEM U,MEMTAB(T1)
HRRZS T1 ;CLEAR SECTION NUMBER FROM LEFT HALF
LSH T1,11
ADDI T1,2 ;NUMBER OF PAGES
TLO T1,(SL.SIO) ;SWAPPING UPMP IO (PREVENT FNDSLE FROM FINDING IT)
BUSLS1: LDB T2,JBYLSA## ;NUMBER OF 1ST PAGE FOR JOB
MOVEM T2,JBTSWP##(J) ;SAVE IN JBTSWP
AOS (P) ;GOOD RETURN
JRST MAKSLE ;SET UP SWPLST AND RETURN
BUSLS2: PUSH P,T1 ;SAVE PAGTAB/MEMTAB POINTER
HRLI T1,(<SL.SIO_-SL.SCT>) ;CLEAR SECTION #, SET BIT
LSH T1,SL.SCT ;POSITION
AOS T1 ;ONE PAGE
PUSH P,T1 ;SAVE IT
MOVEI T2,4 ;WORDS NEEDED
PUSHJ P,GETWDS## ;FOR THE SWPLST ENTRY
JRST TPOPJ## ;OOPS
POP P,1(T1) ;STORE THE ENTRY
TLO U,(MT.LEF) ;TURN ON
POP P,T2 ;PAGTAB POINTER
HRR T2,PAGTAB(T2) ;NEXT PAGE IN CHAIN
MOVEM U,MEMTAB(T2) ;STORE DISK ADDR IN MEMTAB
HRLI T2,(<SL.SIO_-SL.SCT>) ;CLEAR SECTION #, SET BIT
LSH T2,SL.SCT ;AND MAKE THE FRAGMENT ENTRY
AOS T2
MOVEM T2,(T1) ;MAP ENTRY
SETZM 2(T1) ;NO MORE
SETZM 3(T1)
HRLI T1,(SL.SIO!SL.FRG) ;SET FRAGMENTED ENTRY
JRST BUSLS1
;HERE FOR HI SEG
BUSLSH: PUSHJ P,SAVE3## ;SAVE ACS
SE1ENT ;NEED TO BE IN SECTION 1
LDB U,IMGIN## ;NO OF PAGES TO SWAP IN
LDB P1,JBYHSA## ;FIRST PAGE ALLOCATED TO HIGH SEG
MOVE T1,P1 ;COPY TO T1
LSH T1,SL.SCT ;SHIFT INTO PLACE
TLO T1,(SL.SIO) ;SET IT'S SWAPPING
PUSH P,T1 ;SAVE T1
SSX P1,MS.MEM ;POINT TO MEMTAB
SETZ P2, ;CLEAR P2
.CREF FRGSEG
LDB T4,JBYVAD## ;RELATVE ADDRESS OF MAP
SKIPGE T1,JBTSWP##(J) ;FRAGMENTED ON OUTPUT?
JRST BUSLHF ;YES
TLO T4,(GIDX(P2)) ;SET A GLOBAL INDEX
LDB T1,IMGOUT## ;NUMBER OF PAGES I/O WILL BE DONE FOR
IORM T1,(P) ;SET COUNT INTO SWPLST ENTRY
.CREF SL.CNT
BUSLH1: TRNN P1,-1 ;IS THERE A PAGE TO INSERT?
STOPCD .,STOP,WNP ;++WRONG NUMBER OF PAGES
SKIPN T1,@T4 ;GET MAP ENTRY
JRST BUSLH3 ;NO ENTRY, EXPANDING
TLO T1,(<PM.DCD>B2!PM.COR) ;TURN ON ACCESSIBILITY
MOVSI T3,(PM.NAD) ;KEEP BITS IN T3
AND T3,T1 ;...
ANDCAM T3,T1 ;AND ADDRESS IN T1
IORI T3,(P1) ;PAGE MAP ENTRY
MOVEM T3,@T4 ;STORE THIS ENTRY
MOVEM T1,MEMTAB(P1) ;SET DISK ADDRESS (CLEARING REST)
SOJLE U,BUSLH2 ;DONE IF NO MORE PAGES
AOS P2 ;NEXT VIRTUAL PAGE
DPB P2,NVPNP1 ;STORE POINTER TO NEXT PAGE
MOVE P3,P1 ;SAVE THIS PAGE
HRR P1,PAGTAB(P1) ;NEXT PAGE
JRST BUSLH1 ;LOOP BACK
BUSLH3: PUSHJ P,BUSLHZ ;ZERO THE REST OF THE PAGES
MOVE P1,P3 ;WHERE TO SET MT.LEF
BUSLH2: MOVSI T1,(MT.LEF) ;SET MEMTAB FLAG
IORM T1,MEMTAB(P1) ;..
POP P,T1 ;RESTORE T1
AOS (P) ;SKIP RETURN
PJRST MAKSLE ;MAKE SWPLST ENTRY AND RETURN
BUSLHF: POP P,(T1) ;PUT INITIAL ENTRY INTO FRAGMENT TABLE
TLO T1,(SL.FRG!SL.SIO) ;INDICATE THIS IS A FRAGMENTED ENTRY
;(NOTICE THAT THIS IS ALSO THE SIGN BIT!)
PUSH P,T1 ;SAVE THAT SWPLST ENTRY
PUSH P,T1 ;SAVE A WORKING COPY
MOVE T4,JBTVAD##(J) ;RELATVE ADDRESS OF MAP
TLO T4,(GIDX(P2)) ;SET A GLOBAL INDEX
BUSLF3: TRNN P1,-1 ;IS THERE A PAGE?
XCT WNP ;NO, ERROR
SKIPN T2,@T4 ;GET MAP ENTRY
JRST BUSLF5 ;NO MAP ENTRY, ZERO REST OF PAGES
TLO T2,(<PM.DCD>B2!PM.COR) ;TURN ON GOOD BITS
MOVSI T1,(PM.NAD) ;BITS TO T1,
AND T1,T2 ;..
ANDCAM T1,T2 ;AND DISK ADDR TO T2
HRRI T1,(P1) ;PUT IN THE PAGE
MOVEM T1,@T4 ;UPDATE THE PAGE MAP ENTRY
MOVEM T2,MEMTAB(P1) ;STORE DISK ADDRESS IN MEMTAB
AOS P2 ;INCREMENT VIRTUAL PAGE NUMBER
DPB P2,NVPNP1 ;NEXT PAGE
.CREF SL.CNT
AOS T1,@(P) ;UPDATE COUNT IN SWPLST ENTRY
TLC T1,SL.CNT ;IT'S EASIER TO TEST ZEROES...
SOJLE U,BUSLF6 ;DONE IF NO MORE PAGES
MOVE T3,@T4 ;GET NEXT ENTRY
TLZ T3,(PM.NAD) ;ONLY ADDRESS
AOS T2 ;INCREMENT OLD DISK ADDR
TLNE T1,SL.CNT ;ABOUT TO OVERFLOW COUNT (1000P HIGH SEG)?
CAME T2,T3 ;NO, ARE DISK ADDRS SAME?
JRST BUSLF6 ;ABOUT TO OVERFLOW OR DISK ADDRS DIF
MOVE P3,P1 ;SAVE PREVIOUS PAGE
HRR P1,PAGTAB(P1) ;GET NEXT PHYSICAL PAGE
JRST BUSLF3 ;LOOP AROUND
BUSLF6: MOVSI T3,(MT.LEF) ;LAST PART OF THIS FRAGMENT
IORM T3,MEMTAB(P1) ;SET IT
JUMPLE U,BUSLF9 ;JUMP IF DONE
HRR P1,PAGTAB(P1) ;POINT TO NEXT PHYS PAGE
MOVEI T1,(P1) ;PUT IN T1
LSH T1,SL.SCT ;POSITION IT
TLO T1,(SL.SIO) ;SWPLST BIT
AOS (P) ;POINT TO NEXT SLOT IN FRAGMENT TABLE
MOVEM T1,@(P) ;STORE BASE FOR NEW ENTRY
JRST BUSLF3 ;AND PROCESS MORE PAGES
BUSLF5: PUSHJ P,BUSLHZ ;ZERO REST OF PAGES AND INSERT IN MAP
MOVE P1,P3 ;AND FINISH THE SWPLST ENTRY UP
JRST BUSLF6
BUSLF9: POP P,T1 ;WORKING COPY
SETZM 1(T1) ;END THE SWPLST FRAGMENT TABLE
POP P,T1 ;COPY TO MAKE SWPLST ENTRY WITH
AOS (P) ;GIVE GOOD RETURN
PJRST MAKSLE ;MAKE IT
;SUBROUTINE TO FINISH OFF PAGES WE EXPANDED INTO
BUSLHZ: PUSH P,.UPMP+.UMTMP ;SAVE CURRENT TEMP MAPPING
BSLHZ1: TRNN P1,-1 ;THERE SHOULD BE A PAGE
XCT WNP ;ELSE SOMEONE IS CONFUSED
MOVE T2,@JBTVAD##(J) ;GET FIRST ENTRY IN MAP (FOR BITS)
AND T2,[PM.NAD] ;KEEP ONLY THAT
IORI T2,(P1) ;PAGE TO INSERT
MOVEM T2,@T4 ;STORE THE PAGE
PUSHJ P,ZPAGE ;ZERO THE PAGE
HRR P1,PAGTAB(P1) ;POINT TO NEXT PAGE
SOSLE U ;DONE IF COUNT WENT TO ZERO
AOJA P2,BSLHZ1 ;CONTINUE IF MORE PAGES
POP P,.UPMP+.UMTMP ;RESTORE UUO LEVEL .TMP SLOT
CLRPT .TEMP ;..
POPJ P,
;SUBROUTINE TO SET UP SWPLST FOR SWAP IN OF JOB
BISLST::PUSHJ P,SAVE4## ;SAVE SOME ACS
SETZB P3,.USLPS ;CLEAR SLOT IF LEFT FROM FRAGMENTED SWAPOUT
SKIPL JBTSWP##(J) ;IF NOT FRAGMENTED,
JRST BISLS1 ;GO DIRECTLY TO SETIMT
MOVSI T1,FRGSEG ;FRAG'D
ANDCAM T1,JBTSWP##(J) ;CLEAR BIT IN JBTSWP
DMOVE T1,.USTMP
DMOVE T3,.USTMP+2 ; TO SETIMT
MOVE M,.USTMP+4
MOVE F,.USTMP+5
MOVEI U,SETIMX ;WE'LL CALL SETIMX THIS TIME
JRST BISLS2
BISLS1: SKIPGE P1,.USBTS ;EXTENDED USER (UP.BIG=1B0)
TLNN P1,(UP.NZS) ;BIG USER, TIME TO DO NON-ZERO SECTIONS?
TDZA P1,P1 ;SECTION 0, DO IT
MOVEI P1,MXSECN ;START WITH SECTION 37 OTHERWISE
MOVEM P1,.USSPT ;SAVE AS SECTION TO START I/O AT
MOVEI U,SETIMT ;WHERE TO GO
BISLS2: SETZ P1, ;FIRST CALL
PUSHJ P,(U) ;SET UP UPMP FOR THIS FRAG, OR WHOLE JOB
BISLS3: SKIPA T1,P1 ;DONE - GET 1ST VIRT,,1ST PHYS
JRST BISLS4 ;ANOTHER FRAG TO DO
TLZ T1,-1 ;1ST PHYSICAL PAGE
LSH T1,SL.SCT ;POSITION IT
TLO T1,(SL.SIO) ;SWAPPING IO
DPB P3,[POINT SL.SCT,T1,<^L<SL.CNT>+SL.SCT-1>] ;NUMBER OF PAGES TO DO
JRST BISLS7 ;SET UP JBTADR AND CALL MAKSLE
;HERE WHEN FRAGMENTED
BISLS4: MOVEI P4,0 ;INDICATE 1ST CALL
PUSHJ P,GT4MR ;GET A 4-WORD BLOCK
JRST BISL12 ;CANT GET ONE
HRRZ P2,P4 ;SAVE 1ST ADR OF 4-WD BLOCKS
BISLS5: HRLI P3,(SL.SIO) ;SWAPPING IO
DPB P1,[POINT SL.SPN,P3,<^L<SL.PPN>+SL.SPN-1>] ;1ST PHY PAGE
MOVEM P3,(P4) ;SAVE SWPLST ENTRY IN 4-WD BLOCK
JUMPL P2,BISLS6 ;GO IF LAST FRAG
SETZB P1,P3 ;NOT LAST, SETIMX WANTS P1,P3=0
PUSHJ P,SETIMX ;SET UP UPMP FOR THIS FRAG
TLO P2,400000 ;LAST FRAGMENT - P2 NEGATIVE
AOBJN P4,BISLS5 ;GO DO NEXT IF 4-WD BLOCK NOT EXHAUSTED
PUSHJ P,GT4MR ;GET ANOTHER BLOCK
JRST BISL12 ;NONE AVAILABLE
JRST BISLS5 ;GET ONE - CONTINUE
;HERE WHEN LAST FRAGMENT DONE
BISLS6: SETZM 1(P4) ;TERMINATE LIST
HRRZ T1,P2 ;ADR OF START OF 4-WD BLOCKS
TLO T1,FRGSEG(SL.SIO) ;FRAGMENTED SWAP
;HERE AT END OF FRAG (OR WHOLE JOB)
BISLS7: HLRZ M,.USREL ;LH (JBTADR) ON SWAP-OUT
JUMPE M,BISLS8 ;ALREADY STORED
HRRZS .USREL ;CLEAR LH (.UPREL)
HRLM M,JBTADR##(J) ;RESTORE (NON-SHARABLE HS CASE)
BISLS8: MOVE R,JBTADR##(J) ;MAKE SURE R IS RIGHT
SKIPGE JBTSWP##(J) ;FRAGMENT END?
JRST BISLS9 ;YES, RAN OUT OF STUFF ON FRAGMENTED SWAP
MOVSI T2,(UP.NZS) ;BIT TO CHECK
XORB T2,.USBTS ;CHANGE STATE
JUMPGE T2,BISLS9 ;NORMAL USER
TLNE T2,(UP.NZS) ;BIT JUST GO ON?
HRRZM F,.USTMP+5 ;SAVE POINTER TO NEXT
MOVEM T2,.USBTS ;SAVE STATE OF BIT
BISLS9: MOVEI T2,JBTSGN##-.HBLNK(J) ;POINTER TO SEGMENT DATA BLOCKS
BISL9A: SKIPG T2,.HBLNK(T2) ;POINT TO NEXT
JRST BISL10 ;DONE
HRRZS T2 ;CLEAR BITS
JUMPE T2,BISL10 ;?
SKIPLE T3,.HBSGN(T2) ;GET SEGMENT WORD
TLNE T3,SHRSEG ;SKIP IF SHARABLE
JRST BISL9A ;NO, GO MAKE THE SWPLST ENTRY
HRRZS T3 ;CLEAR JUNK
LDB T4,[POINT 9,JBTADR##(T3),8] ;YES
SKIPE JBTADR##(T3) ;HIGHEST ADR IN HIGH SEG
ADDI T4,1
DPB T4,[PHSSLH+.HBHSZ(T2)]
JRST BISL9A ;CHECK ALL SEGS
BISL10: JUMPG P3,MAKSLE ;MAKE SWPLST ENTRY (NORMAL)
;HERE IF REALLY DON'T NEED TO SWAP ANYTHING. NOTE THAT THIS CAN ONLY
;HAPPEN ON THE THIRD SWAP OPERATION OF AN NZS PROGRAM AS SECTION 0 ALWAYS
;HAS PAGE 0 TO SWAP IN.
MOVSI P2,(SL.IOD)
IORB P2,T1 ;MARK AS DONE
PUSHJ P,MAKSLE ;MAKE NEW SWPLST ENTRY
MOVEI P1,(T2) ;INDEX TO SWXLST
AOS (P) ;SKIP AOS OF SWAPPER COUNT
SOS SPRCNT## ;FIX COUNTS UP
SOS SINCNT##
MOVEI F,SWPDDB## ;RESTORE F
PJRST SWPINA## ;AND CONTINUE
;HERE WHEN NOT ENOUGH 4-WD BLOCKS ARE AVAILABLE
BISL12: DMOVEM T1,.USTMP ;SAVE WORKING ACS IN UPMP
DMOVEM T3,.USTMP+2
MOVEM M,.USTMP+4
HRRZM F,.USTMP+5
MOVSI T1,FRGSEG ;INDICATE HAVE DONE A PART OF WHAT WE NEED
IORM T1,JBTSWP##(J)
JUMPE P4,BISLS3 ;FINISH UP THIS PART AND CALL MAKSLE
SOJA P4,BISLS6 ;FINISH UP
;SUBROUTINE TO SETUP SWPLST FOR HIGH SEGMENT SWAP IN OR OUT
;CALLING SEQUENCE:
;
; MOVE P1,HIGH SEGMENT SIZE
; HRLI P1,SWPLST ATTRIBUTES (I.E. DIRECTION OF I/O)
; MOVEI T2,ADDR+1 OF CORE BLOCK FOR FRAGMENT TABLE COPY (IF FRAG'D)
; PUSHJ P,BHSLST
;ALWAYS RETURNS CPOPJ
BHSLST: SE1ENT ;NEED TO BE IN SECTION 1
PUSHJ P,SAVE4## ;SAVE PS
MOVE T3,T2 ;SAVE CORE FOR FRAG COPY (IF ANY)
LDB T2,JBYHSA## ;1ST PAGE
SKIPGE T1,JBTSWP##(J) ;DSK ADR OF 1ST PAGE
JRST BHSLS1 ;FRAGMENTED
LDB T4,JBYVAD## ;VIRTUAL ADDRESS
SETZB P3,.M2VPN-.M2MAP(T4) ;START AT RELATIVE VIRT PAGE 0
HRRZ T3,P1 ;SIZE
MOVEI T4,STOHDA ;ROUTINE TO STORE DISK ADDRESS IN MEMTAB
PUSHJ P,SETXMT ;SET UP FOR SWAP
LDB T1,JBYHSA## ;1ST PAGE
LSH T1,SL.SCT ;POSITION IT FOR SWPLST
IOR T1,P1 ;ADD ATTRIBUTES, SIZE
JRST MAKSLE ;SET UP SWPLST AND RETURN
BHSLS1: HRRZ P2,T1 ;FRAGMENT TABLE ADDRESS
HRRZ T1,T3 ;ADDRESS OF VPN TABLE
LDB T2,JBYVAD## ;POINTER
MOVEM T1,.M2VPN-.M2MAP(T2) ;STORE FOR LATER
MOVEI P3,STOHDA ;ROUTINE TO STORE DISK ADDRESS IN MEMTAB
SETZ T3, ;START AT VPN 0
LDB T2,JBYHSA## ;FIRST PHYS ADDRESS
PJRST BFSLST ;SETUP SWPLST FRAGMENT TABLE,
;MAKE SWPLST ENTRY, AND RETURN
;SUBROUTINE TO STORE DISK ADDRESS IN MEMTAB, CALL WITH T1=DISK ADDRESS,
; T2=MEMTAB INDEX, ALWAYS RETURNS CPOPJ
STOHDA: AOS P3 ;INCREMENT OFFSET POINTER
DPB P3,NVPNT2 ;STORE IN PT2TAB
MOVEM T1,MEMTAB(T2) ;STORE DISK ADDRESS
POPJ P, ;AND RETURN
;SUBROUTINE TO SETUP SWPLST TO SWAP OUT PAGES ON "IN" QUEUE
;CALLING SEQUENCE:
; PUSHJ P,BPSLST
;ALWAYS RETURNS CPOPJ, I/O STARTED IF POSSIBLE
BMSLST::SKIPA T4,[STODAU] ;SPECIAL ENTRY FOR UUO LEVEL CALLS
BPSLST::MOVEI T4,STODA ;NORMAL ROUTINE TO CHANGE DSK ADDRS
SKIPE PAGIPQ## ;CAN'T DO ANYTHING IF I/O IS IN PROGRESS
POPJ P, ;RETURN DOING NOTHING IF I/O IS IN PROGRESS
PUSHJ P,SAVE1## ;SAVE AN AC
SKIPN U,PAGSNC## ;ANYTHING ON THE SLOW SWAPPING SPACE "IN" QUEUE?
JRST BPSLS1 ;NO, TRY "IN" QUEUE
MOVEI P1,PAGSNQ## ;YES, OUTPUT IT FIRST
TLO U,(PG.SLO) ;ALLOCATE FROM SLOW SWAPPING SPACE
JRST BPSLS2 ;GO START THE I/O
BPSLS1: SKIPN U,PAGINC## ;ANYTHING ON THE "IN" QUEUE?
POPJ P, ;NOTHING TO DO
MOVEI P1,PAGINQ## ;OUTPUT "IN" QUEUE
BPSLS2: PUSHJ P,SAVJW## ;SAVE J,W
MOVE W,T4 ;SAVE T4 (DON'T NEED W ANYWAY)
SETZ J, ;USE JOB 0
PUSHJ P,SWPSPC## ;GET SWAPPING SPACE
POPJ P, ;NONE AVAILABLE, TRY AGAIN LATER
MOVE J,-2(P) ;RESTORE J
DMOVE T2,(P1) ;"IN" QUEUE HEADER
DMOVEM T2,PAGIPQ## ;BECOMES "IP" QUEUE HEADER
CAIE P1,PAGIPQ## ;ARE WE RE-DOING THE IP QUEUE?
SETZB T3,(P1) ;"IN" QUEUE IS EMPTY
EXCH T3,1(P1) ;GET NUMBER OF PAGES ON "IP" QUEUE
MOVE T4,W ;RESTORE T4
JUMPL T1,BPSLS3 ;JUMP IF SWAPPING SPACE IS FRAGMENTED
.CREF FRGSEG
PUSHJ P,SETXMT ;SETUP MEMTAB AND COPY DISK ADDRESSES TO MAPS
MOVE T1,PAGIPQ## ;FIRST PAGE
LSH T1,SL.SCT ;POSITION FOR SWPLST ENTRY
IOR T1,PAGIPC## ;COUNT
TLO T1,(SL.SIO+SL.DIO+SL.IPC)
PUSHJ P,MAKSLE ;MAKE A SWPLST ENTRY
JRST BPSLS4 ;START I/O AND RETURN
;HERE WHEN SWAPPING SPACE IS FRAGMENTED
BPSLS3: PUSHJ P,SAVE4## ;SAVE ACS
MOVE P1,T3 ;COUNT TO P1
HRLI P1,(SL.SIO+SL.DIO+SL.IPC)
MOVE P2,T1 ;ADDRESS OF FRAGMENT TABLE
MOVEI P3,(T4) ;ADDRESS OF ROUTINE TO STORE IN MEMTAB
SETZ T1, ;NO VPN TABLE
PUSHJ P,BFSLST ;SETUP SWPLST
BPSLS4: PUSHJ P,INTLVL## ;AT INTERRUPT LEVEL?
HRRM T2,.USSLX ;NO, BE SURE WE FIND THIS SWPLST ENTRY
AOS SPRCNT## ;ONE MORE SWAP IN PROGRESS
PJRST SQOUT## ;START THE OUTPUT
;SUBROUTINE TO STORE DISK ADDRESS IN MEMTAB AND IN MAP THAT THE PAGE BELONGS TO
; CALL WITH T1=DISK ADDRESS, T2=MEMTAB INDEX, RETURNS CPOPJ, T1 AND T2 INTACT
STODA: PUSHJ P,SAVE3## ;SAVE ACS
MOVE P1,J ;SAVE J
DMOVE P2,T1 ;SAVE DISK ADDRESS AND MEMTAB INDEX
DPB T1,[POINT MT.SAD,MEMTAB(P3),<^L<MT.DAD>+MT.SAD-1>] ;SET DISK ADDR
MOVSI T1,(MT.IPC) ;IS THIS AN IPCF PAGE?
TDNE T1,MEMTAB(P3) ;?
JRST STODIP ;YES, HANDLE IT
LDB J,[POINT MT.SJB,MEMTAB(P3),<^L<MT.JOB>+MT.SJB-1>] ;GET JOB NUMBER OF JOB PAGE BELONGS TO
PUSHJ P,SVEUB## ;MAKE MAPS ADDRESSABLE
LDB T1,NVPNT2 ;PAGE #
.CREF P2.MBZ ;(ZERO BIT SHOULD BE ZERO HERE)
PUSHJ P,GTPME ;GET MAP CONTENTS
AND T2,[PM.BTS] ;EXTRACT ACCESS BITS
IOR T2,P2 ;ADD IN DISK ADDR
MOVEM T2,(T4) ;STORE IT IN THE MAP
STODA1: MOVE J,P1 ;RESTORE J
STODA2: DMOVE T1,P2 ;AND T1, T2
POPJ P, ;AND RETURN
;HERE FOR IPCF PAGE
STODIP: LDB T1,NVPNT2 ;GET LOW ORDER BITS
LDB T2,[POINT MT.SJB,MEMTAB(T2),<^L<MT.JOB>+MT.SJB-1>]
;HIGH ORDER BITS
LSH T2,P2.SPN ;POSITION
IORI T1,(T2) ;GET FULL ADDR
MOVSI T2,<PAGSIZ_<^D36-^D18-IP.PLN##-1>> ;THIS IS A PAGE
IOR T2,P2 ;YES, GET DISK ADDRESS BACK
TLO T2,IP.DSK##_-^D18 ;MARK IT AS A DISK ADDRESS FOR IPCSER
MOVEM T2,(T1) ;STORE IT IN THE PACKET
JRST STODA1 ;AND EXIT
;SUBROUTINE TO DO THE SAME THING AS STODA, BUT CAN BE CALLED AT
;UUO LEVEL. IS SLOWER, BUT DOESN'T CALL SVEUB. CANNOT BE CALLED
;AT NON-UUO LEVEL
STODAU::PUSHJ P,SAVE3## ;SAVE WORLD
DMOVE P2,T1 ;MOVE TO A BETTER PLACE
DPB T1,[POINT MT.SAD,MEMTAB(P3),<^L<MT.DAD>+MT.SAD-1>] ;SET DISK ADDR
MOVSI T1,(MT.IPC) ;IPCF PAGE?
TDNE T1,MEMTAB(P3) ;YES, PROCESS AS SUCH
JRST STODIP ;YES, DO THAT
LDB T1,[POINT MT.SJB,MEMTAB(P3),<^L<MT.JOB>+MT.SJB-1>] ;JOB IT GOES IN
HRRZ T2,JBTUPM##(T1) ;UPMP FOR THAT JOB
HRLI T2,(<PM.DCD>B2+PM.WRT+PM.PUB) ;DON'T BOTHER CACHING IT
MOVEM T2,.UPMP+.UMTMP
PUSHJ P,CLPTZO ;SET UP THE MAPPING
EXP .TEMP
LDB T1,[POINT P2.SSN,PT2TAB(P3),<^L<P2.VSN>+P2.SSN-1>] ;SECTION # PAGE IS IN
HRR T2,.TEMP+SECTAB(T1) ;SECTION MAP POINTER FOR THAT SECTION
MOVEM T2,.UPMP+.UMTMP ;MAP THAT
PUSHJ P,CLPTZO
EXP .TEMP ;CLEAR PAGING
LDB T1,[POINT P2.SRN,PT2TAB(P3),<^L<P2.RPN>+P2.SRN-1>] ;PAGE TO CHANGE
MOVSI T2,(PM.BTS) ;GET BITS
ANDM T2,.TEMP(T1) ;SAVE ONLY THEM
IORM P2,.TEMP(T1) ;AND PUT DSK ADDR IN
DMOVE T1,P2
POPJ P,
;SUBROUTINE TO BUILD A FRAGMENTED SWPLST ENTRY
; CALL WITH P1=ATTRIBUTES,,SIZE, P2=ADDRESS OF DISK ADDRESS FRAGMENT TABLE,
; P3=ROUTINE TO CALL TO SETUP MEMTAB FOR A FRAGMENT, ALWAYS RETURNS CPOPJ
;T1 IS ADDRESS OV VPN TABLE TO STORE IN (ZERO IF NONE)
;T3 HAS STARTING VPN (OR JUNK)
BFSLST: PUSHJ P,SAVE3## ;SAVE ACS
PUSH P,T1 ;ADDR OF VPN TABLE (OR ZERO)
PUSH P,T3 ;VPN TO START AT (OR JUNK)
PUSH P,J ;NXTFRG CLOBBERS J
EXCH P2,P1 ;ATTRIBUTES,,SIZE
PUSH P,P1 ;SAVE LOC OF BLOCK
HLLM P2,(P) ;AND BITS
BFSLS1: DPB T2,[POINT SL.SPN,P2,<^L<SL.PPN>+SL.SPN-1>] ;SAVE PAGE NUMBER IN P2
PUSHJ P,NXTFRG ;SET U FOR THIS FRAGMENT
JRST BFSLS2 ;DONE
MOVEM P2,-1(P1) ;SAVE SWPLST ENTRY
LDB T3,[POINT SL.SCT,P2,<^L<SL.CNT>+SL.SCT-1>] ;SIZE
MOVE T1,U ;1ST DSK ADR
MOVE T4,P3 ;ROUTINE TO CALL TO STORE IN MEMTAB
EXCH P3,-2(P) ;GET VIRTUAL POINTER
SKIPN -3(P) ;ANY VPN TABLE ADDRESS?
JRST BFSLS7 ;NO
MOVEM P3,@-3(P) ;YES, STORE VPN
AOS -3(P) ;INCREMENT
BFSLS7: PUSHJ P,SETXMT ;SET UP FOR THIS FRAG
EXCH P3,-2(P) ;STORE UPDATED POINTER RESTORE P3
JRST BFSLS1 ;OK, DO NEXT FRAG
BFSLS2: POP P,T1 ;RESTORE 1ST ADR OF 4-WD BLOCKS
TLO T1,FRGSEG ;INDICATE FRAGMENTED
POP P,J ;RESTORE J
ADJSP P,-2 ;FIX STACK
JRST MAKSLE ;CALL MAKSLE AND RETURN
;SUBROUTINE TO SET UP MEMTAB FOR A SWAP
;CALL WITH T1=1ST DSK ADR, T2=1ST PAGE NUMBER, T3=NUMBER OF PAGES, T4=ROUTINE
; TO CALL TO STORE DISK ADDRESSES
;ALWAYS RETURNS CPOPJ
SETXMT: SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVE2##
SETZ P1, ;NEED ZERO FOR SECTION #
MOVE P2,T4 ;ADDRESS OF ROUTINE TO CALL TO STORE DISK ADDRESS
SETXM1: SSX T2,MS.MEM ;SECTION NUMBER FOR PAGTAB/MEMTAB
PUSHJ P,(P2) ;SAVE DISK ADDRESS (CLEARING REST)
MOVE T4,T2 ;GET NEXT PAGE OF SEGMENT
TRNE T4,-1 ;LEGAL PREDESESSOR?
SKIPGE T2,PAGTAB(T2)
STOPCD .,STOP,PFC, ;++PAGE ON FREE CORE LIST
ADDI T1,1 ;INCR. DSK ADR BY 1
SOJG T3,SETXM1 ;GO DO NEXT PAGE
MOVSI T1,(MT.LEF)
IORM T1,MEMTAB(T4) ;INDICATE LAST PAGE IN MEMTAB
POPJ P, ;AND RETURN
;SUBROUTINE TO MOVE PAGES FROM "IP" QUEUE TO "OUT" QUEUE.
;CALL WITH P1=LOC OF SWPLST ENTRY, P2=SWPLST ENTRY
IP2OUT::SE1ENT ;MUST BE IN SECTION 1 TO LOOK AT PAGTAB/MEMTAB
PUSHJ P,SAVE2## ;SAVE ACS
IP2OU1: SKIPN P1,PAGIPQ## ;GET FIRST PAGE ON "IP" QUEUE
STOPCD IP2OU6,DEBUG,IPE, ;++IN PROGRESS QUEUE EMPTY
TLNE P2,(SL.ERR!SL.CHN!SL.CHK) ;ANY ERRORS?
JRST IP2ERR ;YES, PUT THE QUEUE BACK
IP2OU2: SSX P1,MS.MEM ;PAGTAB SECTION
MOVE P2,P1 ;SAVE PREDECESSOR
LDB T1,[POINT PT.SJB,PAGTAB(P1),<^L<PT.JOB>+PT.SJB-1>] ;GET POSSIBLE WAITING JOB NUMBER
JUMPE T1,IP2OU3 ;JUMP IF THERE IS NONE
S0PSHJ STPIOD## ;GET THE JOB STARTED AGAIN
HRRZS PAGTAB(P1) ;AND CLEAR JOB NUMBER
IP2OU3: MOVE T3,MEMTAB(P1) ;MEMTAB ENTRY
TLNN T3,(MT.GPB) ;DOES THE PAGE NEED TO BE GIVEN BACK?
JRST IP2OU4 ;NO, NEXT PAGE
LDB T2,[POINT MT.SAD,T3,<^L<MT.DAD>+MT.SAD-1>]
PUSHJ P,DLTDSP ;DELETE PAGE FROM DISK
HRRZ T2,P2 ;PHYSICAL PAGE NUMBER
MOVEI T3,PAGIPQ## ;"IP" QUEUE HEADER
PUSHJ P,RMVPFQ ;REMOVE THE PAGE FROM THE "IP" QUEUE
PUSHJ P,DLTPGC ;DELETE THE PAGE FROM CORE
SKIPE PAGIPQ## ;EMPTIED THE ENTIRE QUEUE?
JRST IP2OU1 ;NO, START OVER
JRST IP2OU5 ;YES, DELETE SWPLST ENTRY AND RETURN
IP2OU4: SKIPE P1,PAGTAB(P1) ;NEXT PAGE, EQUAL LAST PAGE?
JRST IP2OU2 ;YES, FINISH UP
DMOVE T1,PAGIPQ## ;GET FIRST PAGE, COUNT
EXCH T1,PAGOUQ## ;MAKE IT FIRST PAGE ON "OUT" QUEUE
MOVEM T1,PAGTAB(P2) ;LINK FORMER "OUT" QUEUE AT END OF FORMER "IP" QUEUE
SKIPE T1
HRRM P2,@[IW MS.MEM,PT2TAB(T1)]
ADDM T2,PAGOUC## ;UPDATE NUMBER OF PAGES ON "OUT" QUEUE
SETZM PAGIPQ## ;"IP" QUEUE IS NOW EMPTY
SETZM PAGIPC## ; ...
IP2OU5: MOVE P1,-2(P) ;GET SWPLST INDEX BACK
PUSHJ P,DLTSLX ;DELETE SWPLST ENTRY
IP2OU6:
IFN FTMP,<
PUSHJ P,SBSCD## ;MUST HAVE THE SCHEDULER INTERLOCK HERE
>
MOVEI P1,1 ;FLAG
HRRE J,JBTCQ##-PQIOQ## ;TAKE EVERYONE OUT OF PQIOW
JUMPLE J,IP2OU9 ;DONE HERE
IP2OU7: PUSHJ P,SSEC0##
IP2OU8: MOVEI T1,RNQ## ;REQUEUE HIM
SYSPIF
PUSHJ P,WAKOKE## ;PUT HIM IN THE RUN QUEUE
JFCL
HRRE J,JBTCQ##(J) ;NEXT JOB
JUMPG J,IP2OU8
IP2OU9: SOJL P1,CPOPJ## ;DONE IF LOOKED AT BOTH QUEUES
HRRE J,JBTCQ##-PQIOQ##-MXQUE##
JUMPG J,IP2OU7
POPJ P,
;HERE IF ERRORS IN THE SWPLST ENTRY
IP2ERR: SSX P1,MS.MEM ;SET RIGHT SECTION
HRRZ P2,PAGTAB(P1) ;NEXT PAGE (IF ANY)
MOVSI T3,(MT.GPB) ;REALLY NEED THIS PAGE?
TDNN T3,MEMTAB(P1) ;?
JRST IP2ERX
MOVEI T3,PAGIPQ## ;NO, JUST FLUSH IT
HRRZ T2,P1 ;...
PUSHJ P,RMVPFQ ;REMOVE THE PAGE
PUSHJ P,DLTPGC ;RETURN PAGE
IP2ERX: SKIPE P1,P2 ;SUCCESSOR (IF ANY)
JRST IP2ERR ;ONE EXISTS, CONTINUE
MOVE P1,-2(P) ;DELETE THIS ENTRY
PUSHJ P,DLTSLX
MOVEI P1,PAGIPQ## ;HEADER TO "TRANSFER"
MOVE U,PAGIPC## ;AMOUNT OF SWPSPC TO GET
MOVEI T4,STODA ;ROUTINE
PJRST BPSLS2 ;TRY, TRY AGAIN
;SUBROUTINE TO MAKE AN ENTRY IN SWPLST
;CALLING SEQUENCE:
;
; MOVE T1,SWPLST ENTRY
; PUSHJ P,MAKSLE
;ALWAYS RETURNS CPOPJ, T2 HAS SWPLST INDEX
MAKSLE::MOVSI T2,MJBTMX## ;MAX NUMBER OF SWPLST ENTRIES
DSKOFF
IFN FTMP,<
SYSPIF
>
MAKSL1: SKIPE SWPLST##(T2) ;THIS SLOT AVAILABLE?
AOBJN T2,MAKSL1 ;NO
JUMPL T2,MAKSL2 ;FOUND A SLOT IF T2 NEG
STOPCD CPOPJ##,DEBUG,SLF, ;++SWPLST FULL
MAKSL2: MOVEM J,SW3LST##(T2) ;SAVE J
MOVEM T1,SWPLST##(T2) ;SAVE SWPLST ENTRY
TLC T1,(SL.SIO+SL.IPC) ;SWPLST ENTRY TO SWAP OUT THE "IN" QUEUE?
TLCN T1,(SL.SIO+SL.IPC) ;SKIP IF NOT
HLLOS SW3LST(T2) ;YES, ZAP SEGMENT NUMBER SO IT CAN'T BE FOUND
MOVE T1,SWPOUT## ;SWPOUT (SCHED1) HAS TO BE SAVED
HRLM T1,SW3LST##(T2) ; IN CASE OF MULTIPLE SWAP-OUTS
AOS SLECNT## ;INCREMENT SWAP-LIST-ENTRY COUNT
MAKSL3:
IFN FTMP,<
SYSPIN
>
POPJ P, ;AND RETURN
;SUBROUTINE TO FIND A SWPLST ENTRY
;RETURNS CPOPJ IF NO ENTRIES (EVERYTHING IN SWPLST IS FOR PAGING)
;RETURNS CPOPJ1 IF FOUND, P1=INDEX , J=JOB NUMBER, T1=1ST PAGE, P2=ENTRY
FNDSLE::
IFN FTMP,<
SYSPIF ;MAKE SURE SOME OTHER CPU DOESN'T MAKE A SWPLST ENTRY
; AT INTERRUPT LEVEL
>
SKIPN P3,SLECNT## ;GET COUNT OF SWPLST ENTRIES
STOPCD MAKSL3,DEBUG,SLZ, ;++SLECNT IS ZERO
MOVEI P1,0 ;START AT 1ST THING IN SWPLST
FNDSL1: SKIPN P2,SWPLST##(P1);GET THE ENTRY
FNDSL2: AOJA P1,FNDSL1 ;NOT HERE - TRY NEXT
TLNE P2,(SL.DFM) ;DON'T FIND A UPMP ENTRY
JRST FNDSL3 ;IT WILL BE HANDLED AT INTERRUPT LEVEL
TLNE P2,(SL.SIO) ;SWAPPER ENTRY?
TLNN P2,(SL.IOD) ;YES, DONE?
FNDSL3: SOJG P3,FNDSL2 ;NO, TRY NEXT
JUMPE P3,ONPOPJ## ;DIDNT FIND ONE IF T1=0
MOVE T1,SW3LST##(P1) ;SWPOUT,,JOB NUMBER
TLNE P2,(SL.DIO) ;DON'T CHANGE SWPOUT IF INPUT
HLRZM T1,SWPOUT## ;RESTORE SWPOUT FOR SCHED1
HRRZ J,T1 ;SET UP J
LDB T1,[POINT 13,P2,26] ;1ST PHYSICAL PAGE
IFN FTMP,<
SYSPIN ;SLECNT AND SWPLST ARE CONSISTANT
>
PJRST CPOPJ1## ;TAKE SKIP-RETURN
;SUBROUTINE TO DELETE THE SWPLST ENTRY
;ENTER WITH P1=INDEX
;ALWAYS RETURNS CPOPJ
IFN FTMP,<
DLTSXI::
TDZA T1,T1
DLTSLX::
SETZ T1,
PUSH P,F ;PROBABLY NOT NECESSARY
MOVEI F,SWPDDB## ;FOR PIOFF
PIOFF ;GUARD AGAINST INTERPROCESSOR RACE
PUSHJ P,DLTSLZ ;DELETE SWPLST ENTRY AND DECREMENT SLECNT
PION
JRST FPOPJ## ;RESTORE F AND RETURN
>
IFE FTMP,<
DLTSXI::
>
DLTSLO::TDZA T1,T1
IFE FTMP,<
DLTSLX::
>
DLTSLE::SETO T1, ;FLAG ENTRY AT DLTSLE
DLTSLZ: PUSH P,T1 ;SAVE FLAG
SKIPN T1,SWPLST##(P1) ;GET ENTRY
STOPCD DLTSL3,DEBUG,SIE, ;++SWPLST IS EMPTY
TLNE T1,(SL.IOD) ;IO DONE FOR THIS ENTRY?
TLNN T1,(SL.SIO) ;SWAPPER?
JRST DLTSL1 ;PAGER - LEAVE SWPCNT ALONE
SOSGE SWPCNT## ;DECREMENT SWPCNT
STOPCD DLTSL2,DEBUG,SIN, ;++SWPCNT IS NEGATIVE
DLTSL1: SOS SLECNT## ;DECREMENT NUMBER OF ITEMS IN SWPLST
SETZM SWPLST##(P1) ;CLEAR OUT THE OLD ENTRY
SKIPN (P) ;ENTRY AT DLTSLO/DLTSXI?
JRST DLTSL3 ;YES
POP P,(P) ;FIX STACK
JUMPGE T1,CPOPJ## ;DONE IF NOT FRAGMENTED
;FALL INTO RTNBLK
;SUBROUTINE TO RETURN 4-WORD CORE BLOCKS USED IN SWPLST
;ENTER WITH T1=SWPLST ENTRY
RTNBLK::PUSHJ P,SAVE1## ;SAVE AC
MOVE P1,T1 ;ORIGINAL ENTRY
RTNBL1: HRRZ T2,P1 ;ADR OF 4-WD BLOCK
SKIPG T1,3(P1) ;NEXT BLOCK CONTIGUOUS WITH THIS?
SKIPA P1,T1 ;NO, SAVE ITS ADR
ADDI P1,4 ;YES
MOVEI T1,4 ;WORDS USED
PUSHJ P,GIVWDS##
JUMPE P1,CPOPJ## ;DONE IF LINK=0
JRST RTNBL1 ;NOT DONE, RETURN NEXT BLOCK
DLTSL2: SETZM SWPCNT## ;ZERO SWPCNT SO WONT KEEP GETTING HERE
DLTSL3: POP P,(P) ;FIX STACK
POPJ P, ;AND RETURN
;SUBROUTINE TO GET 4 WORDS OF MONITOR FREE CORE
;ENTER P4=0 1ST TIME, P4=PREVIOUS P4 ON FOLLOWING CALLS
;RETURNS CPOPJ IF NO BLOCKS AVAILABLE
;RETURNS CPOPJ1 IF GOT ONE, P4=AOBJN WORD FOR BLOCK
GT4MR: PUSHJ P,SAVT## ;SAVE A BUNCH OF ACS
MOVEI T2,4 ;WORDS NEEDED
PUSHJ P,GETWDS##
POPJ P,SETOMT ;CANT GET IT - POPJ
SETZM 3(T1) ;GOT IT, ZERO THE LINK
JUMPE P4,GT4M2 ;IF NOT 1ST CALL,
CAIE T1,1(P4) ;BLOCK CONTIGUOUS WITH PREVIOUS?
JRST GT4M1 ;NO
HRLI P4,-4 ;YES, CAN USE 4 WDS
JRST CPOPJ1## ; (LINK OF LAST, FIRST 3 OF THIS)
GT4M1: HRROM T1,(P4) ;POINT LAST WD OF PREVIOUS BLOCK AT THIS
GT4M2: MOVE P4,T1 ;ADR OF THIS BLOCK
HRLI P4,-3 ;CAN USE 3 WORDS
JRST CPOPJ1## ;TAKE GOOD RETURN
;SUBROUTINE TO SET UP BITS IN S FROM SWPLST
GETIOS::MOVEI S,0
TLNE P2,(SL.ERR) ;ERROR?
TRO S,IODERR ;YES
TLNE P2,(SL.CHN) ;CHAN ERROR?
TRO S,IOCHMP ;YES
TLNE P2,(SL.CHK) ;CHECKSUM ERRORS
TRO S,IOIMPM ;YES
TLNE P2,(SL.DIO) ;OUTPUT?
TLO S,IO ;YES
POPJ P, ;RETURN
;ROUTINE TO RETURN NEXT PAGE
;RETURNS RH(M)=VIRT PAGE, T4=POINTER TO MAP SLOT
;PRESERVE T1-T3,M ACCROSS CALLS (AFTER FIRST, CALL NXTSW2)
;BITS 3-17 OF M ARE PRESERVED FOR USE BY THE CALLER
;AND BITS 0-2 OF M (AS WELL AS RH(M) ARE FOR USE BY THIS ROUTINE
NXTWSB::SKIPGE .USBTS ;NOT A BIG USER?
SKIPG T2,.USSPT ;SECTION ZERO?
JRST [MOVEI T2,WSBTAB ;YES
JRST NXTWS1] ;DO THE OLD WAY
HRRZS T2 ;CLEAR LEFT HALF
IMULI T2,WSBTBL ;COMPUTE WHICH WSBTAB TO USE
MOVEI T2,.WSBNZ-WSBTBL(T2)
NXTWS1: AND M,[77777,,0] ;CLEAR ALL BITS WE USE
NXTWS2::MOVEI T1,^D36 ;36 BITS PER WORD
SKIPE T3,(T2) ;GET THE WSBTAB ENTRY
NXTWS3::JFFO T3,NXTWS4 ;FIND FIRST BIT
ADDI M,(T1) ;REST OF WORD 0 - COUNT VIRT PAGE IN M
HRRZ T3,M ;GET VPN
TLNN M,200000 ;TRANSLATED FUNNY SPACE #S YET?
CAIG T3,HLGPNO+1+<FYSSIZ/PAGSIZ>+MXSECN
CAIL T3,.UPMVP/PAGSIZ+MXSECN
SKIPA T3,[<.UPMVP/PAGSIZ>+MXSECN+1] ;RETURN INVALID #
AOJA T2,NXTWS2 ;AND TRY NEXT WSBTAB WORD
HRRI M,(T3) ;M RETURNS PAGE #, NOT T3
POPJ P,
NXTWS4: LSH T3,1(T4) ;SHIFT OUT BITS THROUGH BIT JUST FOUND
SUBI T1,1(T4) ;ACCOUNT FOR NO OF BITS SCANNED
ADDI M,1(T4) ;INCR VIRTUAL PAGE
TLON M,400000 ;1ST TIME?
SUBI M,1 ;YES, WE'RE 1 TOO HIGH
HRRZ T4,M ;GET VIRTUAL PAGE IN T4
CAIG T4,HLGPNO ;STILL IN USER SPACE?
JRST [MOVE T4,.USSPT ;GET SECTION #
LSH T4,S2PLSH ;MAKE FULL PAGE #
TRO T4,(M)
JRST GMPTR]
TLOE M,200000 ;NO, TRANSLATE ALREADY?
JRST GMPTR ;ALREADY TRANSLATED, GO TO GMPTR
HRRI M,<.MCFV/PAGSIZ>-<HLGPNO+1>(M) ;TRANSLATE #
HRRZ T4,M ;RESET T4
;FALL INTO GTMPTR
;SUBROUTINE TO SETUP A BYTE POINTER TO A HALF WORD IN THE MAP
;ENTER WITH T4=VIRTUAL PAGE NUMBER FOR WHICH THE BYTE PNTR IS TO BE COMPUTED
;PRESERVES T1-T3
GMPTR:: CAIGE T4,<.MCFV/PAGSIZ> ;USER ADDRESS?
JRST [ADD T4,[MS.MAP+UMAPS] ;YES
POPJ P,]
ADDI T4,.UPMP-<.MCFV/PAGSIZ>+.UMORG ;OFFSET TO MAP SLOTS IN UPT
CAILE T4,.UPMP+.UMUPT ;SECTION MAP?
MOVEI T4,SECTAB-.UMORG-<<.UPMVP/PAGSIZ>-<.MCFV/PAGSIZ>>(T4)
POPJ P,
;SUBROUTINE TO GET THE BYTE POINTER FROM A HIGH SEG "VIRTUAL POINTER"
;NOTE THAT THIS IS SIMPLY THE OFFSET FROM THE BEGINNING OF THE MAP PAGE
GMHPTR: LDB P4,JBYVAD## ;VIRTUAL ADDRESS WHERE MAP IS
ADD T4,P4 ;POINT THERE
POPJ P, ;RETURN
;SUBROUTINE TO SETUP MEMTAB FOR A SWAP OUT FROM THE WORKING SET TABLE
; AND THE UPMP
;CALLING SEQUENCE:
;
; MOVSI J,NUMBER OF PAGES ALLOCATED CONTIGUOUSLY ON THE DISK
; HRRI U,STARTING PAGE NUMBER ON THE DISK
; PUSHJ P,SETOMT ;FIRST CALL
; PUSHJ P,SETOM8 ;ALL SUBSEQUENT CALLS
;ALWAYS RETURNS CPOPJ, T1-T3,M,F,P4,R MUST BE PRESERVED FOR SUBSEQUENT CALLS
SETOMT: SE1ENT ;ENTER SECTION 1
SETZB P3,F ;FIRST TIME FOR ANYTHING
MOVSI P4,(UP.MAP) ;CLEAR BIT IN
ANDCAB P4,.USBTS ;.USBTS INDICATING MAP INFO
SETZ W, ;ASSUME DEMAND PAGING
TRNN P4,UP.NVS ;WRITE LOCKED PAGES HAVE A DISK COPY?
JRST SETOM2 ;NO, MUST DO WORKING SET SWAPPING
MOVE P4,.USJOB ;GET JOB NUMBER
SKIPE .USVRT ;JOB VIRTUAL?
SKIPGE JBTST2##(P4) ;YES, IN A RUN QUEUE?
SETOM2: TLO W,400000 ;NOT VIRTUAL OR IN A RUN QUEUE, WS SWAPPING
SKIPE R,.USSPT ;EXTENDED SECTION
JRST SETO18 ;YES
MOVEI P4,.UPMVP/PAGSIZ ;MAX PAGE HERE IS THE UPMP
SETOM3: PUSHJ P,NXTWSB ;GET 1ST PAGE OF WORKING SET
SETOM4: CAIGE P4,(M) ;LEGAL PAGE #?
JRST SETO16 ;NO, GO TO NEXT SECTION
JUMPN F,SETO10 ;MUST BE JUST A SECTION CYCLE
MOVE F,(T4) ;GET MAP ENTRY
MOVE T4,F ;FOR THE FIRST TIME AT SETOM6
TLZE F,(<PM.DCD>B2) ;ACCESS ALLOWED ON?
TLZA F,(PM.NAD) ;YES, CLEAR BITS
TLZA F,(<PM.NAD^!<PM.COR!PM.AAB>>) ;ACCESS ALLOWED OFF, SEE IF EXPAND
JUMPN F,SETOM5 ;PROCEED WITH PARANOIA IF DCD IS ON
TLZN F,(PM.AAB) ;AAB ON?
TLZN F,(PM.COR) ;NO, COR MUST BE ON TOO IF NOT EXPANSION
CAIA ;AAB ON OR COR OF, EXPANSION
JUMPN F,SETOM5 ;FOUND A PAGE TO START AT
PUSHJ P,NXTWS3 ;MUST BE A NZS SECTION W/O P0
JRST SETOM4 ;AND COMPARE MORE
SETOM5: SKIPGE P3,.USSPT ;GET SECTION
TDZA P3,P3 ;MAPS
LSH P3,^D18+S2PLSH ;LEFT HALF PAGE #
TLO P3,(M) ;VPN
HRR P3,F ;P3=1ST VIRT,,1ST PHYS
SETOM6: SSX F,MS.MEM ;SET SECTION NUMBER
PUSHJ P,CKWSS ;SEE IF DOING WORKING SET SWAPPING
JRST SETOM8 ;NO, DEMAND PAGING, CKWSS FIXED THINGS UP
MOVEM U,MEMTAB(F) ;SAVE DISK ADDRESS IN MEMTAB
MOVEI T4,(M)
CAIE T4,<.UPMVP-1>/PAGSIZ
JRST SETOM7
MOVSI T4,(UP.MAP) ;MAP INFO
IORM T4,.USBTS
MOVE T4,.USJOB
DPB U,JBYMT4## ;SET MAP
SETOM7: SOJLE J,SETO15 ;DONE
AOS U
SETOM8: JUMPE P4,SETO22 ;JUST DID A MAP
SETOM9: PUSHJ P,NXTWS3 ;NOT LAST, GET NEXT WS BIT
CAIGE P4,(M) ;LEGAL PAGE?
JRST SETO16 ;NO, NEXT SECTION
SETO10: MOVE T4,(T4) ;PHYSICAL PAGE
TDNN T4,[PM.ADR] ;ANY DISK ADDRESS?
JRST SETOM8 ;NO, IGNORE PAGE
TLZN T4,(<PM.DCD>B2)
JRST SETO14 ;NO
SETO11: JUMPN P3,SETO12 ;IF 1ST TIME,
SKIPGE P3,.USSPT
TDZA P3,P3
LSH P3,^D18+S2PLSH
TLO P3,(M)
TRO P3,(T4) ; AND PHYS PAGE IN P3
JRST SETO13
SETO12: TLNN T4,(PM.WRT) ;PAGE WRITE LOCKED?
JUMPGE W,SETO13 ;YES, DON'T STORE IN MEMTAB UNLESS WS SWAPPING
HRR F,W ;LAST WRITE ENABLED PAGE
TRNE M,-1^!HLGPNO ;FUNNY PAGE?
SKIPA R,M ;YES
DPB M,[POINT 9,R,35] ;ELSE R HAS SECTION, MAKE VPN
DPB R,NVPNF ;AND SET NEXT VPN
SETO13: MOVE F,T4 ;F=PHYS PAGE
JRST SETOM6 ;AND CONTINUE
;HERE IF PM.ACC OFF - EITHER EXPANDING (INSDSK) OR IT REALLY SHOULD BE OFF
SETO14: TLNN T4,(PM.AAB) ;IS AAB OFF?
TLNN T4,(PM.COR) ;YES, IS COR ON?
JRST SETOM8 ;SOME FLAVOUR OF EXPANSION, IGNORE
JRST SETO11
;HERE AT FRAGMENT'S END
SETO15: PUSH P,T1 ;SAVE T1
HLRZ T1,P3 ;FIRST PAGE
DPB T1,NVPNF ;POINT LAST TO IT
MOVSI T1,(MT.LEF)
IORM T1,MEMTAB(F) ;SET LAST
MOVSI T1,(UP.MAP) ;MAP INFO THIS FRAGMENT?
CAIE T4,.UPMVP/PAGSIZ ;DID WE JUST DO THE UPT?
TDNE T1,.USBTS ;?
TLO P2,(SL.MAP) ;YES, SET SWPLST BIT TOO
ANDCAM T1,.USBTS ;CLEAR BIT
JRST TPOPJ## ;RETURN
;HERE AT THE END OF A SECTION
SETO16: SKIPG .USSPT ;SECTION 0 OR MAPS?
JRST SETO19 ;YES, DO MAPS THEN OR RETURN
SETO17: SOSGE R,.USSPT ;COUNT DOWN TO DO NEXT SECTION
JRST SETO21 ;TIME TO START DOING MAPS
SETO18: SKIPN P4,.UPMP+SECTAB(R)
JRST SETO17
TRNN R,-1 ;SECTION 0?
SKIPA P4,[.UPMVP/PAGSIZ-1-1] ;YES, STOP AT MAP THEN
MOVEI P4,HLGPNO ;MAX FOR NON-ZERO SECTIONS
LSH R,S2PLSH ;MAKE IT A SECTION # WITH NO PAGE #
JRST SETOM3 ;START THE SECTION
;HERE WHEN DOING MAPS
SETO19: JUMPE P4,SETO21 ;DOING MAPS
CAIN P4,.UPMVP/PAGSIZ ;JUST DO UPMP?
POPJ P, ;HUH? PROBABLY A UNL THEN
SETO21: MOVEM T4,.USTMP ;SAVE RELEVANT VARIABLES
MOVEM M,.USTMP+1 ;WHICH WILL BE DESTROYED
SETO22: MOVSI P4,(UP.MAP) ;SET WE'RE DOING MAPS
IORM P4,.USBTS ;SET IT FOR BOSLST
SKIPL P4,.USSPT ;FIRST TIME?
MOVSI P4,-<MXSECN+1> ;YES
AOBJP P4,SETO24 ;TIME TO DO SECTION 0
SETO23: SKIPE T4,.UPMP+SECTAB(P4);SAVE A LITTLE TIME IN THIS
TLNE T4,(<PM.ACD^!PM.DCD>B2) ;INDIRECT POINTER?
AOBJN P4,SETO23
JUMPGE P4,SETO24 ;DONE
MOVEM P4,.USSPT ;SAVE POINTER TO CURRENT MAP
MOVEI M,.UPMVP/PAGSIZ(P4) ;PAGE # OF MAP
MOVEI T4,(M) ;POINTER
PUSHJ P,GMPTR ;GET MAP
SETZ P4, ;FLAG TO COME BACK HERE
HRRZS R ;AND THE SECTION #
JRST SETO10
;HERE TO DO MAP AND UPMP (FINISH SECTION 0)
SETO24: MOVE T4,.USTMP ;RESTORE RELEVANT VARIABLES
MOVE M,.USTMP+1
MOVEI P4,.UPMVP/PAGSIZ ;NOW UPMP IS LAST
SETZM .USSPT ;REALLY SECTION 0 NOW
JRST SETO10
;SUBROUTINE TO DO FIXUPS FOR WRITE LOCKED PAGES AND TAKE CARE OF DEMAND
; PAGING IF APPROPRIATE. CALL WITH T4=CONTENTS OF THE MAP, RETURNS CPOPJ
; IF ALL THE WORK HAS BEEN DONE, CPOPJ1 IF THE NORMAL THING SHOULD BE DONE.
;PRESERVES T ACS.
CKWSS: SKIPE .USWLP ;IGNORE PM.WRT IF NO WE PAGES (NON-SHARABLE) HI SEG
TLNE T4,(PM.WRT) ;PAGE WRITE LOCKED?
HRR W,F ;NO, SAVE PHYSICAL PAGE NUMBER OF LAST WE PAGE
TRNE M,-1^!HLGPNO ;MONITOR PAGE?
JRST CPOPJ1## ;YES, THIS ISN'T APPLICABLE
PUSHJ P,SAVT## ;ALL OF THIS CODE IS VERY TOUCHY ABOUT ACS
JUMPL W,CKWSS2 ;IF WSS, JUST TAKE CARE OF WRITE LOCKED PAGES
;HERE WHEN WE ARE GOING TO DEMAND PAGE IN THE JOB THE NEXT TIME IT COMES IN
HRRZ T1,M ;VIRTUAL PAGE WITHIN SECTION
TRZ R,HLGPNO ;MASK OUT POSSIBLE PAGE WITHIN SECTION
TRO T1,(R) ;SECTION NUMBER, VIRTUAL PAGE WITHIN IMAGE
JUMPE T1,CPOPJ1## ;DON'T DO ANY OF THIS FOR PAGE 0
MOVE T3,T4 ;COPY BITS (TSWST CLOBBERS T4)
PUSHJ P,CCBPOP ;SEE IF THIS PAGE CAN BE PAGED OUT
JRST CKWSS1 ;NO, PSI VECTOR, .JBBPT, .JBINT, ETC.
PUSHJ P,TSWST ;GET BIT AND POINTER TO WSBTAB
STOPCD CPOPJ##,DEBUG,MBW, ;MUST BE IN WORKING SET
ANDCAM T2,(T4) ;ITS NOT ANYMORE
PUSH P,T3 ;NEED T3 FOR NEXT PART
PUSH P,J ;J MUST CONTAIN THE JOB NUMBER
MOVE J,.USJOB ; ..
PUSHJ P,DECHJ ;DECREMENT HIGH SEGMENT INCORE PAGE COUNT IF
; THIS IS A NON-SHARABLE HIGH SEGMENT PAGE
POP P,J ;RESTORE ACS
POP P,T3 ; ..
CKWSS1: TLNE T3,(PM.WRT) ;ALL DONE (EASY PART) IF PAGE NOT WRITE LOCKED
JRST CPOPJ1## ;RETURN AND CAUSE PAGE TO BE WRITTEN OUT
;HERE WHEN DOING DEMAND PAGING AND PAGE IS WRITE LOCKED (WE HAVE BOTH AN
; IN-CORE COPY OF IT AND A COPY ON THE DISK)
MOVE T4,T1 ;SAVE VIRTUAL PAGE NUMBER FOR GMPTR
HLRZ T2,P3 ;VIRTUAL PAGE BEING REMEMBERED AS FIRST
CAIN T2,(T4) ;IS IT THIS PAGE?
SETZ P3, ;YES, THEN NOT REALLY STARTING AT THIS PAGE
MOVEI T2,0 ;ZERO MEMTAB
HRRZ T1,T3 ;PHYSICAL PAGE NUMBER
SSX T1,MS.MEM ;MEMTAB SECTION
EXCH T2,MEMTAB(T1) ;GET DISK ADDRESS, ZERO MEMTAB
TDZ T2,[PM.NAD] ;ISOLATE DISK ADDRESS
AND T3,[PM.BTS-PM.COR] ;JUST ACCESS BITS OF INTEREST
IOR T2,T3 ;FORM FULL DISK ADDRESS
PUSHJ P,GMPTR ;GET POINTER TO THE MAP
EXCH T2,(T4) ;T2=PHYSICAL PAGE, MAP=DISK ADDRESS
TDZ T2,[PM.NAD] ;PHYSICAL PAGE NUMBER
PUSHJ P,LKPSF ;LINK PAST PAGE IN PAGTAB
MOVE T1,T2 ;PHYSICAL PAGE NUMBER - ARGUMENT FOR ADDPTQ
MOVEI T3,PAGOUQ ;WHERE TO PUT IT
PJRST ADDPTQ ;PUT PAGE ON "OU" QUEUE. THIS COULD BE POSPONED
; UNTIL THE SWAP COMPLETED BUT SINCE WE ARE
; SWAPPING NOW, MAKE THE CORE AVAILABLE AS SOON
; AS POSSIBLE
;HERE WHEN VIRTUAL BUT DOING WORKING SET SWAPPING
CKWSS2: HRR W,F ;PHYSICAL PAGE NUMBER OF LAST PAGE
AOS (P) ;HAVE TO SWAP OUT THE PAGE IN ANY EVENT
SKIPE .USWLP ;IGNORE PM.WRT IF NO WL PAGES
TLNE T4,(PM.WRT) ;PAGE WRITE LOCKED?
POPJ P, ;NO, RETURN AND JUST SWAP IT OUT
HRRZ T2,T4 ;YES, THEN IT STILL HAS DISK SPACE FROM
PJRST RTNDPG ; FROM PREVIOUS SWAP-IN, RETURN IT
;THE FOLLOWING ROUTINE ARE CROCKS BECAUSE WE DON'T ALLOW PAGES CONTAINING
; PSI INTERRUPT VECTORS, THE PAGE(S) POINTED TO BY .JBINT, AND THE PAGE
; POINTED TO BY .JBBPT TO BE REMOVED FROM THE WORKING SET. THEY WILL BE
; REMOVED IF THE VARIOUS ROUTINES INVOLVED GET TAUGHT HOW TO BE RUN AT UUO
; LEVEL AND HOW TO PAGE IN A PAGE. THIS WOULD ALSO SAVE CONSIDERABLE WORK
; ON THE PART OF PFH.
;SUBROUTINE TO CALL CHECKER OR COUNTER OF CBPO PAGES. FOR CHECKER, CALL WITH
; T1=VIRTUAL PAGE TO CHECK, EXITS CPOPJ IF CBPO, CPOPJ1 OTHERWISE. COUNTER
; RETURNS WITH T4=COUNT OF CBPO PAGES.
NCBPOP: PUSHJ P,SAVE3## ;SAVE SOME WORKING ACS
SETZ T4, ;INITIAL COUNT
MOVEI P2,CNCBPO ;ROUTINE TO CALL
JRST CCBPO1 ;JOIN COMMON CODE
CCBPOP: PUSHJ P,SAVE3## ;SAVE ACS
MOVEI P2,CKCBPO ;ROUTINE TO CALL
CCBPO1: MOVE P1,T1 ;PAGE TO CHECK, ALSO PRESERVE P1 ON A SKIP RETURN
PUSH P,J ;SAVE J
MOVE J,.USJOB ;JOB NUMBER, SOME OF THESE ROUTINES NEED IT
MOVEI P3,GETJLM## ;.JBINT LIMITS
PUSHJ P,(P2) ;CALL COUNTER OR CHECKER
JRST JPOPJ## ;NON-SKIP RETURN
MOVEI P3,GETBLM## ;.JBBPT PAGE
PUSHJ P,(P2) ;CALL COUNTER OR CHECKER
JRST JPOPJ## ;NON-SKIP RETURN
MOVEI P3,GETPLM## ;PSI VECTOR LIMITS
PUSHJ P,(P2) ;CALL COUNTER OR CHECKER
JRST JPOPJ## ;NON-SKIP RETURN
MOVE T1,P1 ;RESTORE T1
JRST JPOPJ1## ;SKIP RETURN
;CALL THE FOLLOWING WITH P3=ADDRESS OF ROUTINE TO CALL
;ROUTINE TO COUNT NUMBER OF CBPO PAGES, INITIAL CALL SET T4=0, RETURNS T4=COUNT
CNCBPO: PUSHJ P,(P3) ;GET LIMITS
SKIPN T1 ;START IN PAGE 0?
JUMPE T2,CPOPJ1## ;GO IF BOTH START AND END ARE IN PAGE 0
SUB T2,T1 ;NUMBER OF PAGES - 1 IN THE RANGE
ADD T4,T2 ;ADD TO TOTAL SO FAR
AOJA T4,CPOPJ1## ;SKIP BUT COUNT AT LEAST ONE PAGE
;ROUTINE TO SEE IF PAGE CONTAINED IN P1 CAN'T BE PAGED OUT
CKCBPO: PUSHJ P,(P3) ;GET LIMITS
CAML P1,T1 ;BELOW FIRST PAGE?
CAMLE P1,T2 ;OR ABOVE HIGHEST?
JRST CPOPJ1## ;YES, OK TO REMOVE IT FROM THE WS
POPJ P, ;CBPO
;SUBROUTINE TO SETUP THE UPMP WITH PHYSICAL CORE ADDRESSES FROM PAGTAB,
; THE UPMP, THE WORKING SET TABLE, AND THE ACCESS ALLOWED TABLE AND SETUP
; MEMTAB FOR A SWAP IN
;CALLING SEQUENCE:
;
; PUSHJ P,SETIMT ;FIRST CALL
; PUSHJ P,SETIMX ;ALL SUBSEQUENT CALLS
;RETURNS CPOPJ1 WHEN A NON-CONTIGUOUS DISK ADDRESS IS FOUND. RETURNS
; CPOPJ WHEN THE ENTIRE UPMP HAS BEEN PROCESSED.
;RETURNS P3=# OF PAGES, P1=1ST VIRT,,1ST PHYS
;PRESERVE T1-T4,M,F OVER CALLS TO SETIMX
;BITS IN THE LEFT HALF OF P3 IN BELOW (USED ONLY LOCALLY):
; 1B0 JUST CHANGED SECTION, STILL CONTIGUOUS)
; 1B14 SECTION CHANGE REQUIRED ON NEXT MEMTAB ENTRY
; 1B15 NO I/O TO DO YET
; 1B16 NEED TO ADVANCE PHYSICAL PAGE FOR STORE INTO P1
; 1B17 MAY BE NO PAGES IN REQUEST
SETIMT: SE1ENT ;ENTER SECTION 1
PUSH P,J ;SAVE J
SKIPE T1,.USSPT ;SECTION ZERO?
JRST SETI20 ;SET UP FOR FIRST CALL IN NZS
LDB F,JBYLSA## ;FIRST PHYSICAL ADDRESS
SETIM1: PUSHJ P,NXTWSB ;GET 1ST PAGE IN WORKING SET
HRRZ R,M
CAILE R,.UPMVP/PAGSIZ+MXSECN
JRST SETI13
TLZ P3,4 ;ACTUALLY DOING SOMETHING I/OWISE
TLZE P3,400000 ;CYCLING THROUGH SECTIONS?
JRST SETIM5 ;YES, THIS WAS A LOGICAL CALL TO NXTNW3
MOVE U,(T4) ;GET MAP WORD
TLZ U,(PM.NAD) ;CLEAR EXTRANEOUS BITS
JUMPE U,SETI11 ;CONTINUE
JUMPN P1,SETIM3 ;IF JUST CYCLING THROUGH SECTIONS
SKIPGE P1,.USSPT
TDZA P1,P1
LSH P1,S2PLSH+^D18
TLO P1,(M)
HRR P1,F ;1ST VIRTUAL,,1ST PHYSICAL
JRST SETIM3 ;PROCEED
SETIM2: MOVE U,(T4) ;GET DSK ADR
TLZ U,(PM.NAD) ;MAKE SURE EXTRANEOUS BITS ARE 0
JUMPE U,SETIM8 ;MAY NOT BE ANY PAGES IN THIS SECTION
SETIM3: MOVE J,(T4) ;GET OLD PAGE MAP ENTRY
MOVE R,J ;SAVE PM.ADR FOR JXPN CHECK
AND J,[PM.BTS] ;KEEP ONLY ACCESSIBILITY BITS
TLNN J,(PM.AAB) ;IN AABTAB?
TRNE M,<-1^!HLGPGS> ;OR IS IT A MONITOR PAGE?
TLOA J,(<PM.DCD>B2)
TLZ J,(<PM.ACD>B2) ;NO ACCESS ALLOWED
TLO J,(PM.COR) ;NOW A CORE ADDRESS
TDNE R,[PM.ADR] ;SWAPPING OUT (EXPANDING) TO ALLOCATE THIS PAGE?
; IF SO, DOESN'T HAVE A DISK COPY SO DON'T WL
SKIPN .USVRT ;USER VIRTUAL?
JRST SETI3A ;NO
TRNE M,-1 ;PAGE ZERO?
TRNE M,<-1^!HLGPGS> ;ON A MONITOR PAGE?
JRST SETI3A ;YES, DON'T WRITE LOCK THOSE PAGES
SKIPE R,MIGRAT## ;MIGRATING JOB?
JRST [ANDI R,JOBMSK## ;ONLY JOB #, DISCARD FLAGS IN LH
CAMN R,.USJOB ;THIS JOB?
JRST SETI3A ;YES, DON'T WRITE-LOCK
JRST .+1] ;GO AHEAD AND WRITE-LOCK PAGES
TLZ J,(PM.WRT) ;CLEAR WRITE ENABLE
AOS .USWLP ;AND BUMP THE NUMBER OF WRITE LOCKED PAGES
SETI3A: ADDI J,(F)
MOVE R,F
SSX R,MS.MEM ;SET SECTION NUMBER FOR MEMTAB
TLNN F,-1 ;THIS PAGE HAVE A DISK ADDRESS?
MOVEM U,MEMTAB(R) ;YES, SAVE IN MEMTAB
MOVEM J,(T4) ;SAVE IN MAP
SETIM4: PUSHJ P,NXTWS3 ;GET NEXT PAGE, M=VIRT, T4=MAP POINTER
HRRZ R,M
CAILE R,.UPMVP/PAGSIZ+MXSECN
JRST SETI12
CAIE R,.UPMVP/PAGSIZ ;UPT?
CAIN R,.UPMVP/PAGSIZ-1 ;MAP?
JRST SETIM4 ;YES
SETIM5: MOVE J,(T4) ;DISK ADDR OF NEXT PAGE
TLZ J,(PM.NAD) ;CLEAR ACCESS BITS ETC.
JUMPE J,SETIM8 ;GO IF NO DISK ADDR
JUMPN P1,SETIM6 ;IF 1ST CALL,
SKIPGE P1,.USSPT ;SECTION #
TDZA P1,P1
LSH P1,S2PLSH+^D18
TLNN P3,2 ;NEED TO ADVANCE PHYSICAL PAGE?
HRR P1,F ;NO, GET CURRENT 1ST PHYS
SETIM6: SKIPN U ;FIND FIRST PAGE YET?
SOSA U ;NO, BE SURE WE THINK IT'S CONTIGUOUS
SUB U,J
HLRZ J,F ;PAGE NUMBER OF LAST PAGE WITH A DSK ADR
TLZN F,-1 ;IF IT WAS LAST PAGE,
MOVE J,F ;GET IT FROM F
AOJN U,SETI15 ;GO IF NOT CONTIGUOUS
MOVEI R,(P3) ;CHECK ONLY RIGHT HALF
CAIL R,776 ;CAN ONLY STORE NINE BITS
SOJA U,SETI15 ;FRAGMENT; BE SURE THAT U'S NON-ZERO
SETIM7: SKIPGE U,.USSPT ;CURRENT SECTION
TDZA U,U
LSH U,S2PLSH ;MAKE SECTION #
TRO U,(M) ;SET PART OTHER THAN SECTION
HRRZ R,J
SSX R,MS.MEM ;MAKE PAGTAB/MEMTAB ADDRESSBLE
DPB U,NVPNR ;STORE
HRR R,F ;FOR INDEXING INTO PAGTAB
HRR F,PAGTAB(R) ;NEXT PHYSICAL PAGE
TLZE P3,2 ;NEED TO STORE "ADVANCED" PHYSICAL IN P1?
HRRI P1,(F) ;YES, DO IT NOW
AOJA P3,SETIM2 ;COUNT THE PAGE, TEST NEXT
;HERE IF NEXT PAGE HAS NO DISK ADDRESS
SETIM8: PUSH P,T2 ;SAVE T2 FOR NXTWSB
MOVE T2,F ;FOR INDEXING INTO PAGTAB
SSX T2,MS.MEM ;SET SECTION NUMBER
HRRZ T2,PAGTAB(T2) ;THIS PHYSICAL PAGE
PUSHJ P,ZPAGE ;ZERO THE PAGE
POP P,T2 ;RESTORE T2
TLNN F,-1 ;FIRST SUCH PAGE?
HRLS F ;YES, SAVE IN LH(F)
SETIM9: MOVE R,F ;TO GET PAGTAB ENTRY
SSX R,MS.MEM ;SET SECTION
HRR F,PAGTAB(R) ;STEP TO NEXT PHYSICAL PAGE
SETI10: JUMPN P1,SETIM3 ;CONTINUE, U=DSK ADR IF NOT 1ST CALL TO SETIMX
JUMPE U,SETIM3 ;ALSO IF FIRST PAGE OF SECTION IS ABZ,
;THEN AVOID KAF
JRST SETIM2 ;1ST CALL TO SETIMX - GET U FROM BYTE PNTR
;HERE SAME AS SETIM8, BUT FOR FIRST TIME THROUGH MAIN SETIM LOOP
SETI11: TRNN P3,-1 ;ANY PAGES ALREADY IN REQUEST?
TLO P3,3 ;NO, THERE MAY BE NONE, FLAG PHYSICAL ADVANCE
PUSH P,T2 ;SAVE T2 FOR NXTWSB
HRRZI T2,(F) ;PAGE TO ZAP
PUSHJ P,ZPAGE ;ZERO THE PAGE
POP P,T2 ;RESTORE T2
JRST SETI10
;HERE FOR UPMP
SETI12: TLO P3,400010 ;FLAG A POSSIBLE SECTION CYCLE
SETI13: SKIPE .USSPT ;DOING SECTION 0?
JRST SETI17 ;NO, INCREMENT SECTION #
SETI14: SOS -1(P) ;RETURN CPOPJ
PUSHJ P,SETHSA ;UPDATE JBTHSA IF NECESSARY
TLNE F,-1 ;ENDING ON EXPANDING PAGES?
HLRZ J,F ;YES, LOAD J WITH LAST PAGE WE DID I/O TO
;HERE AT END OF THIS FRAGMENT
SETI15: HLRZ U,P1 ;NEXT VPN
MOVE R,J ;USE LAST PAGE I/O WAS DONE TO
SSX R,MS.MEM ;SET SECTION
DPB U,NVPNR ;SET NEXT VIRTUAL PAGE
MOVSI U,(MT.LEF)
IORM U,MEMTAB(R)
TLZ P3,400012 ;BE SURE THEY'RE CLEAR
TLZN P3,5 ;WENT THROUGH SETI11 (COUNT OFF BY ONE)?
;OR NOT DONE ANY I/O?
AOJA P3,JPOPJ1## ;NO, COUNT THE PAGE AND RETURN
JRST JPOPJ1## ;NO PAGES IN REQUEST
;HERE IF CONTIGUITY CROSSES A SECTION BOUNDARY
SETI17: SOSG T1,.USSPT ;DECREMENT SECTION WORKING ON
JRST SETI19 ;DONE IF THIS WAS LAST
SETI18: SKIPN .UPMP+SECTAB(T1) ;SECTION EXIST?
JRST SETI17 ;NO, TRY NEXT
JRST SETIM1 ;CONTINUE FRAGMENT
SETI19: SETZ T1, ;RESTORE SECTION 0
MOVEM T1,.USSPT
JRST SETI14
;HERE ON CALL TO SETIMT FOR NON-ZERO SECTIONS
SETI20: MOVE F,.USTMP+5 ;WHERE TO START
SSX F,MS.MEM ;PAGTAB SECTION
HRRZ F,PAGTAB(F) ;GET POINTER TO NEXT PHYSICAL PAGE
;(AND FLAG TO STORE U IN MEMTAB)
TLO P3,4 ;IN CASE WE DON'T DO ANY I/O
JRST SETI18 ;FIND FIRST REAL SECTION
;HERE FOR SUBSEQUENT CALLS
SETIMX: SE1ENT ;ENTER SECTION 1
PUSH P,J ;SAVE J
SSX F,MS.MEM ;SET SECTION
HRRZ F,PAGTAB(F) ;STEP TO NEXT PHYSICAL PAGE
;(AND STORE INTO MEMTAB AT SETIM2)
; JUMPN P1,SETIM3 ;CONTINUE, U=DSK ADR IF NOT 1ST CALL TO SETIMX
;(THE ABOVE JUMPN CAN'T EVER HAPPEN ANY MORE)
SKIPGE P1,.USSPT ;SECTION #
TDZA P1,P1
LSH P1,S2PLSH+^D18
TLO P1,(M) ;..
HRR P1,F
JRST SETIM2
;SUBROUTINE TO SETUP AN AOBJN POINTER TO BE USED TO SETUP MEMTAB -
; I.E. XWD -NUMBER OF CONTIGUOUS PAGES ON THE DISK, STARTING
; PAGE ON THE DISK, FROM THE FRAGMENT TABLE POINTED TO BY JBTSWP.
; IT ALSO SETS UP THE JOB NUMBER AND NUMBER OF PAGES
; ENTRIES IN THE SWPLST ENTRY WHICH IS BEING BUILT.
;CALLING SEQUENCE:
;
; MOVE P1,POINTER TO THE FRAGMENT TABLE (1ST CALL)
; MOVEI P2,SWPLST DESCRIPTORS
; PUSHJ P,NXTFRG
;RETURNS CPOPJ IF THIS IS THE LAST ENTRY IN THE FRAGMENT TABLE, CPOPJ1
; IF NOT, P1 POINTS TO THE NEXT ENTRY
NXTFR1: HRRZ P1,(P1) ;GET NEXT FRAG TABLE ENTRY
NXTFRG: SKIPN J,(P1) ;GET NO OF DSK PAGES
POPJ P, ;DONE IF 0
JUMPL J,NXTFR1 ;POINTER TO ANOTHER ADR IF NEG
LDB J,FRGCP1## ;FRAGMENT COUNT
DPB J,[POINT SL.SCT,P2,<^L<SL.CNT>+SL.SCT-1>] ;SAVE NUMBER OF PAGES
LDB U,FRGAP1## ;FRAGMENT ADDRESS
AOJA P1,CPOPJ1## ;GOOD RETURN
;SUBROUTINE TO FIX THINGS UP AFTER A SWAP-WRITE ERROR
MAPBAK::TDZA T1,T1 ;NORMAL ENTRY (DON'T CALL XPANDH WHEN DONE)
MAPBAX::MOVEI T1,UP.JXP ;CALL XPANDH WHEN DONE
CAILE J,JOBMAX##
JRST MAPBAH ;DO HIGH SEG
PUSHJ P,FNDPDS## ;GET PDB
HRRZ S,.PDSCX##(W) ;GET OLD SAVCTX POINTER (IF THERE IS)
HLLZS .PDSCX##(W) ;..
MOVE T3,.CPMAP##
HRRZ T2,JBTUPM##(J) ;POINT UPT BACK AT ITSELF
TLO T2,(<PM.DCD>B2+PM.WRT+PM.PUB+PM.COR+IFE FTMP,<PM.CSH>)
CONO PI,PI.OFF ;DON'T LET INTERRUPT LEVEL CHANGE THIS
MOVEM T2,.ECKSM/PAGSIZ(T3) ;SINCE IT POINTED AT NLUPMP
CLRPT .ECKSM
MOVEM T2,.ECKSM+.UMUPT ;POINT IT BACK AT ITSELF
CONO PI,PI.ON ;OK TO TURN THE PIS ON
PUSHJ P,SVEUB## ;MAKE SURE RIGHT STUFF GETS SAVED
IORM T1,.USBTS ;SET FLAG FOR WHEN DONE
PUSHJ P,SAVCTS## ;SAVE CONTEXT
STOPCD .,STOP,OOC ;++OUT OF CORE BLOCKS
JRST MAPB12
;HERE AT UUO LEVEL
PUSHJ P,MAPBK0 ;DO THE REAL WORK
PJRST USCHE1## ;CONTINUE NOW
MAPBK0: PUSHJ P,SAVE4## ;SAVE ACS
MOVE P3,.UPMP+SECTAB+0 ;MAKE SURE REAL SECTION 0 PTR (NOT DISK)
IFN FTMP,<
PUSHJ P,MLSCSH## ;CACHED?
TLZ P3,(PM.CSH) ;NO
>
MOVEM P3,.UPMP+.UMUPM
PUSHJ P,CLPTZO ;FIX PAGING MEMORY
EXP .UPMAP
SE1ENT ;MUST BE IN SECTION 1
MOVE J,.USJOB ;DON'T TRUST J
LDB P3,JBYLSA## ;YES, SET TO SCAN MEMTAB CHAIN
ADJSP P,1 ;ALLOCATE STACK SPACE TO REM LAST PAGE
MOVEI J,200 ;BEFORE CALLING SCDCHK
SETZM .USSPT
MAPBK1: PUSHJ P,NXTWSB ;GET 1ST PAGE IN WORKING SET
MAPBK2: HRRZ P4,M ;UPMP?
SKIPE .USSPT ;SECTION 0?
CAIG P4,HLGPNO ;NO, THIS IS MAX
CAILE P4,.UPMVP/PAGSIZ+MXSECN
JRST MAPBK7 ;END THIS SECTION
MOVE P2,(T4) ;GET DSK ADR
TRNE P2,-1 ;EVEN IF PM.COR WILL BE OFF, COULD BE ABZ
TLNE P2,(PM.COR) ;IS IT A DISK ADDRESS?
JRST MAPBK4 ;NO, LOOK AT NEXT PAGE
HLRZ P1,P2 ;SAVE ACCESS AND SOFTWARE BITS
TLZ P2,(PM.NAD) ;KEEP ONLY ADDR IN P2
ANDI P1,(PM.BTS) ;AND ONLY BITS IN P1
HRRZM P3,(P) ;SAVE PAGE WE START AT
MAPBK3: SSX P3,MS.MEM ;MAKE GLOBAL INDEX
MOVE P4,MEMTAB(P3) ;MEMTAB FOR THIS PAGE
TLZ P4,(<-1^!MT.DAD>)
CAME P2,P4 ;DSK ADR THE SAME?
JRST MAPBK5 ;NO
HRLI P3,<(PM.COR)>(P1)
TLNN P3,(PM.AAB) ;IN AABTAB?
TRNE M,<-1^!HLGPGS> ;OR IS IT A MONITOR PAGE?
TLO P3,(<PM.DCD>B2)
MOVEM P3,(T4) ;SAVE MAP ENTRY IN UPMP
MAPBK4: PUSHJ P,NXTWS3 ;GET NEXT PAGE IN WORKING SET
JRST MAPBK2 ;DO SO NOW
MAPBK5: HRRZ P3,PAGTAB(P3) ;STEP TO NEXT PAGE OF JOB
CAMN P3,(P) ;BEEN HERE BEFORE?
JRST MAPBK4 ;YES, MUST BE EXPANDING INTO THIS PAGE
JUMPN P3,MAPB10 ;CONTINUE
MOVE P3,J ;SAVE COUNT
MOVE J,.USJOB ;RESTORE JOB #
LDB J,JBYLSA## ;FIRST PAGE
EXCH J,P3 ;CONTINUE
MAPB10: SOJG J,MAPBK3 ;CONTINUE
MOVE J,.USJOB ;WAIT
PUSHJ P,SCDCHK## ;CHECK
MOVEI J,200
JRST MAPBK3
;HERE FOR NEXT SECTION
MAPBK7: SKIPL .USBTS ;EXTENDED?
JRST MAPBK9 ;RESTORE INDEX AND FINISH UP
MAPBK8: AOS T1,.USSPT ;NEXT SECTION
CAILE T1,MXSECN ;MAX?
JRST MAPBK9 ;RESTORE INDEX AND FINISH UP
SKIPE P2,.UPMP+SECTAB(T1) ;SECTION EXIST?
TLNE P2,(<PM.ACD^!PM.DCD>B2) ;IMMEDIATE POINTER?
JRST MAPBK8 ;NO
JRST MAPBK1 ;DO THIS SECTION
MAPBK9: HRRZS .USREL
MOVE J,.USJOB ;RESTORE JOB #
PUSHJ P,FNDPDS## ;GET PDB
HRRZ P1,.PDSCX##(W) ;GET CONTEXT BLOCK POINTER
HRRZ P1,.SCCIT##(P1) ;AND OLD POINTER (IF ANY)
PUSHJ P,RESCTS## ;GET RID OF THIS SAVCTX BLOCK
DMOVEM T1,.CPPC## ;SAVE PC
MOVSI T1,NSWP!NSHF ;RESTORE STATE OF NSWP,NSHF
AND T3,T1
ANDCAM T1,JBTSTS##(J)
IORM T3,JBTSTS##(J)
HRRM P1,.PDSCX##(W)
MOVEI P1,UP.JXP ;CALL XPANDH FOR SWAPPER?
TDNE P1,.USBTS ;?
PUSHJ P,XPANDH## ;YES, FORCE JOB OUT NOW
ANDCAM P1,.USBTS
JRST TPOPJ## ;FIX STACK AND RETURN
;HERE AFTER SETTING UP AT CLOCK LEVEL TO RUN MAPBAK AT UUO LEVEL
MAPB12: MOVSI T1,NSHF ;MAKE SURE SWAPPER DOESN'T FIDDLE WITH US
IORM T1,JBTSTS##(J) ;(SET NSHF BUT NOT NSWP)
MOVSI T1,SWP!SHF!JXPN!NSWP ;SO JOB WILL RUN
ANDCAM T1,JBTSTS##(J) ;CLEAR SO THE SCHEDULER KNOWS IT
PUSHJ P,REQUE## ;PUT INTO A QUEUE
S0JRST DLTSLX ;RETURN SWPLST ENTRY
;HERE TO PUT HIGH SEG MAP BACK IN PLACE
;NOTE THAT A HIGH SEG IS ALWAYS ORDERED SUCH THAT PAGES ARE IN
;INCREASING ORDER
MAPBAH: SE1ENT ;GET INTO SECTION 1
LDB T1,JBYHSA ;FIRST PAGE OF HIGH SEG
SSX T1,MS.MEM ;ADDRESS PAGTAB
LDB T2,JBYVAD## ;AND THE ADDRESS OF THE MAP
SETZ T3, ;CLEAR THE COUNTER
TLO T2,(GIDX(T3)) ;SET AN INDEX
MAPBH1: MOVSI T4,(PM.NAD) ;GET THE ENTRY
AND T4,@T2 ;FOR THIS PAGE (BITS ONLY)
TLO T4,(<PM.DCD>B2!PM.COR)
HRRI T4,(T1) ;AND THE PAGE
MOVEM T4,@T2 ;UPDATE
HRR T1,PAGTAB(T1) ;NEXT PAGE IN HIGH SEG
TRNE T1,-1 ;IF THERE IS ANY
AOJA T3,MAPBH1 ;ON TO NEXT PAGE
S0JRST DLTSLX ;DONE
;SUBROUTINE TO SET/CLEAR IO IN S FOR SWAPPER
;CALLED IN ERROR RECOVERY SINCE DEVIOS CAN CHANGE IN SWPDDB
;CALL WITH U SET UP
SWPINS::MOVE T1,UNISWA(U) ;POINTER TO SWPLST
MOVE T1,(T1) ;GET SWPLST ENTRY
TLNN T1,(SL.DIO) ;INPUT?
TLZA S,IO ;YES
TLO S,IO ;NO
POPJ P,
;SUBROUTINE TO DETERMINE IF A JOB HAS A PAGE OR PAGES ON EITHER THE "IN" QUEUE
; OR THE "SN" QUEUE. CALL WITH J=JOB NUMBER, SKIPS IF JOB ISN'T ON EITHER QUEUE
;PRESERVES ALL ACS (SINCE CALLED FROM THE SWAPPER, THAT'S THE ONLY SAFE THING TO DO)
JOBNQ:: PUSHJ P,SVEUB## ;SEE IF JOB IS VIRTUAL
SKIPN .USVRT ;IS HE?
JRST CPOPJ1## ;NO, CAN'T HAVE PAGES ON ANY QUEUE
PUSHJ P,SAVT## ;SAVE ALL ACS
MOVEI T1,PAGINQ## ;LOOK AT "IN" QUEUE FIRST
PUSHJ P,JOBNPQ ;SEE IF JOB HAS PAGES ON THAT QUEUE
POPJ P, ;YES
MOVEI T1,PAGSNQ## ;NOW LOOK AT "SN" QUEUE
PUSHJ P,JOBNPQ
POPJ P, ;ON THE SN QUEUE
MOVEI T1,PAGIPQ## ;CHECK THE IP QUEUE AS WELL
;FALL INTO JOBNPQ
;SUBROUTINE TO SEE IF A JOB HAS ANY PAGES ON A PAGE QUEUE
;CALL WITH T1 = ADDRESS OF QUEUE, SKIPS IF JOB ISN'T ON THE QUEUE
JOBNPQ: SKIPN T1,(T1) ;NOT ON QUEUE IF QUEUE IS EMPTY
JRST CPOPJ1## ;NOT ON QUEUE RETURN
SE1ENT ;MUST BE IN SECTION 1 TO REFERENCE PAGTAB/MEMTAB
JOBNP1: SSX T1,MS.MEM
LDB T2,[POINT MT.SJB,MEMTAB(T1),<^L<MT.JOB>+MT.SJB-1>] ;GET JOB NUMBER FROM QUEUE
HLL T2,MEMTAB(T1) ;AND BITS
TLNN T2,(MT.IPC) ;IF THIS IS AN IPCF PAGE, DON'T WORRY
CAIE J,(T2)
SKIPA T1,PAGTAB(T1) ;GET NEXT PAGE
POPJ P, ;YES, INDICATE THAT TO CALLER
TRNN T1,-1
AOSA (P) ;SKIP RETURN IF NO MORE PAGES
JRST JOBNP1 ;LOOP IF MORE PAGES ON QUEUE
POPJ P,
;SUBROUTINE TO CLEAR A JOB'S PAGES IN ANY PAGING QUEUE (ANY IN QUEUE OR
;THE IP QUEUE). CALLED BY CORE 0 PROCESSING
JOBFNQ::PUSHJ P,SVEUB## ;NEED TO MAP JOB
SE1ENT ;MUST BE IN SECTION 1
JOBFN2: SKIPN .USVRT ;IS JOB VIRTUAL?
POPJ P, ;NO, NOTHING TO DO
SKIPN PAGINC## ;ANYTHING ON THE FAST "IN" QUEUE?
JRST JOBFN3 ;NO
MOVEI T1,PAGINQ## ;POINT THERE
PUSHJ P,JOBNPQ ;SEE IF ANY PAGES ON THAT QUEUE FOR THIS JOB
SKIPA T1,PT2TAB(T1) ;YES, MUST PROCESS IT
JRST JOBFN3 ;NO PAGES ON IN QUEUE, PROCEED
LSH T1,<<^L<P2.VPN>+P2.SPN-1>-^D35>
ANDI T1,HLGPGS ;JUST SAVE PAGE #
PUSHJ P,DLTPAG ;GET RID OF THE PAG
JRST JOBFN2 ;AND LOOK FOR MORE
JOBFN3: SKIPN PAGSNC## ;ANYTHING ON THE SLOW QUEUE?
JRST JOBFN6 ;NO
SKIPN .USVRT ;ONLY CONTINUE IF STILL VIRTUAL
POPJ P, ;DONE IF NOT
MOVEI T1,PAGSNQ## ;SLOW QUEUE
PUSHJ P,JOBNPQ ;FIND ANYTHING THERE
SKIPA T1,PT2TAB(T1) ;YES, MUST PROCESS IT
JRST JOBFN6 ;NO MORE HERE
LSH T1,<<^L<P2.VPN>+P2.SPN-1>-^D35>
ANDI T1,HLGPGS ;JUST SAVE PAGE #
PUSHJ P,DLTPAG ;GET RID OF IT
JRST JOBFN3 ;CONTINUE LOOKING
JOBFN6: SKIPE PAGIPC## ;ANY PAGES ON IN PROGRESS QUEUE?
SKIPN .USVRT ;AND IS JOB STILL VIRTUAL?
POPJ P, ;NO TO ONE; ALL DONE
MOVEI T1,PAGIPQ## ;POINT TO IP QUEUE
PUSHJ P,JOBNPQ ;FIND PAGE THERE
CAIA ;FOUND ONE
POPJ P, ;DONE
MOVSI T2,(MT.GPB) ;GIVE PAGE BACK
IORM T2,MEMTAB(T1)
JRST JOBFN6
;SUBROUTINE TO REMOVE ALL DISK PAGES FOR JOB. CALLS SCDCHK, SO
;MUST BE RUN AT UUO LEVEL
DSKFLS::SKIPN .USVRT ;VIRTUAL
POPJ P, ;NO, CAN'T HAVE ANY OF THESE THEN
SE1ENT
SETZM .USSPT ;START AT S0
DSKFL0: PUSHJ P,NXTNWS ;GET FIRST NON-WORKING SET PAGE
DSKFL1: TRNE M,-1^!HLGPNO ;DONE THIS SECTION?
JRST DSKFL6 ;YES
PUSHJ P,DSKFLX ;REMOVE PAGE
PUSHJ P,NXTNW3 ;CONTINUE LOOKING
JRST DSKFL1
DSKFL6: SKIPL .USBTS ;EXTENDED USER?
POPJ P, ;NO, DONE
PUSH P,.USSPT ;IN CASE SOMETHING HAPPENS
PUSHJ P,SCDCHK##
POP P,.USSPT
AOS T1,.USSPT ;NEXT SECTION
DSKFL7: CAILE T1,MXSECN ;AT TOP
POPJ P, ;YES, DONE
SKIPE T2,.UPMP+SECTAB(T1) ;YES, DOES SECTION EXIST?
TLNE T2,(<PM.ACD^!PM.DCD>B2) ;AND INDIRECT
AOJA T1,DSKFL7
MOVEM T1,.USSPT ;SAVE
JRST DSKFL0
;HERE TO DELETE PAGE WE FOUND
DSKFLX: PUSHJ P,SAVT## ;SAVE TS FOR NXTNWS
MOVE T1,.USSPT ;GET SECTION
LSH T1,S2PLSH
IORI T1,(M)
JRST DLTPAG
;SUBROUTINE TO RETURN THE NEXT PAGE NOT IN THE WORKING SET
;RETURNS CPOPJ, WITH RH(M)=VIRT PAGE, T4=CONTENTS OF MAP SLOT
;ZERO PAGES AND PM.ZER PAGES ARE IGNORED
;NOTE THAT THIS ROUTINE ASSUMES ALL PER-PROCESS PAGES ARE IN THE WORKING SET
;PRESERVE T1-T3, M ACROSS CALLS (CALL NXTNW3 AFTER FIRST CALL)
;LIKE NXTWSB, BITS 3-17 OF M ARE PRESERVED FOR USE BY THE CALLER
;AND BITS 0-2 OF M (AS WELL AS RH(M) ARE FOR USE BY THIS ROUTINE
NXTNWS::SKIPGE .USBTS ;NOT A BIG USER?
SKIPG T2,.USSPT ;SECTION POINTER
JRST [MOVEI T2,WSBTAB
JRST NXTNW1] ;SECTION ZERO; OLD WAY
HRRZS T2
IMULI T2,WSBTBL
MOVEI T2,.WSBNZ-WSBTBL(T2)
NXTNW1: AND M,[77777,,0] ;CLEAR ALL BITS WE USE
NXTNW2: MOVEI T1,^D36 ;36 BITS IN A WORD
SETCM T3,(T2) ;BITS FOR EVERY NON-WS PAGE
NXTNW3::JFFO T3,NXTNW4 ;FIND A 1-BIT
ADDI M,(T1) ;REST OF WORD 0, STEP TO NEXT
MOVEI T4,(M) ;GET PAGE #
CAILE T4,HLGPNO ;IN USER SPACE?
TDZA T4,T4 ;NO, OFF THE END (SEE NOTE TOP OF THIS ROUTINE)
AOJA T2,NXTNW2
POPJ P,
NXTNW4: LSH T3,1(T4) ;CLEAR THE BIT
SUBI T1,1(T4) ;COUNT THE BIT
ADDI M,1(T4) ;...
TLON M,400000 ;FIRST TIME?
SUBI M,1 ;YES, WE'RE 1 TOO HIGH
MOVEI T4,(M) ;VIRTUAL PAGE #
CAILE T4,HLGPNO ;IN USER SPACE?
TDZA T4,T4 ;NO, RETURN ZERO
SKIPA T4,.USSPT
POPJ P,
LSH T4,S2PLSH
TRO T4,(M)
NXTNW5: PUSHJ P,GTPM4 ;GET MAP CONTENTS
JUMPE T4,NXTNW3 ;UNALLOCATED PAGE
TDNE T4,[PM.ADR^!PM.ZER] ;ABZ PAGE?
PUSHJ P,NXTHS ;SEE IF 0 OR HIGH SEG PAGE
JRST NXTNW3 ;0 OR PM.ZER, TRY NEXT
TLNN T4,(PM.SSP!PM.OIQ) ;QUEUE PAGE?
IFN FTPEEKSPY,<
TLNE T4,(PM.SPY) ;SPY PAGE?
JRST NXTNW3 ;YES, DON'T FIND IT
>
POPJ P, ;"REAL" PAGE, RETURN IT
;SUBROUTINE TO SEE IF MAP CONTENTS IS 0 OR IN A HIGH SEG
;PRESERVES ALL ACS
NXTHS: JUMPE T4,CPOPJ## ;IF MAP IS NON-0
PUSHJ P,SAVT## ;SAVE ALL ACS
HRRZ T1,M ;PAGE TO TEST
PJRST TPNSHS ;GO SEE IF IT IS IN A HIGH SEG
;SUBROUTINE TO TEST IF A DISK ADDRESS IS ON A UNIT BEING REMOVED
;ENTER T4=C(MAP SLOT) - DSK ADR
;EXIT CPOPJ IF UNIT GOING DOWN, CPOPJ1 IF NOT
;PRESERVES T1-T3
TSTUN::
IFN FTPEEKSPY,<
TLNE T4,(PM.SPY) ;SPY PAGE?
JRST CPOPJ1## ;YES, IT'S NOT ON A BAD UNIT
>
LDB T4,SSUNT4## ;GET SWAP UNIT
SKIPLE T4,SWPTAB##(T4) ;UNIT DATA BLOCK LOC
SKIPGE UNIFKS(T4) ;IF NEGATIVE, GOING DOWN TOO
JRST CPOPJ## ;UNIT ALREADY DOWN
MOVE T4,UNIUST(T4) ;STATUS
TLNN T4,UNPNNA+UNPRSS ;UNIT GOING DOWN?
AOS (P) ;NO, SKIP RETURN
POPJ P, ;RETURN
;SUBROUTINE TO COMPLEMENT A BIT IN WSBTAB
;ENTER RH(M) = VIRTUAL PAGE NUMBER
;PRESERVES T1-T3
;NOTE THAT .USSPT MUST NOT BE AN INDIRECT SECTION
BTCOM:: PUSH P,T1 ;SAVE T1
PUSH P,T2 ;AND T2
SKIPG T1,.USSPT ;CURRENT SECTION
TDZA T1,T1 ;IS REALLY S0
LSH T1,S2PLSH ;CONVERT TO PAGE #
ADDI T1,(M)
PUSHJ P,TSWST ;COMPUTE WSBTAB BIT, POSITION
JFCL
XORM T2,(T4) ;FLIP THE BIT IN WSBTAB
JRST TTPOPJ## ;NO
;SUBROUTINE TO ALLOCATE MONITOR PAGES
;CALLING SEQUENCE:
; MOVE T1,FIRST PAGE TO ALLOCATE
; MOVE T2,NUMBER OF PAGES TO ALLOCATE
; MOVE T3,SIGN BIT=FLAG 0=CACHED,NON-ZERO=UNCACHED (KL ONLY)
; PUSHJ P,CREMPG
; RETURNS HERE IF NO VIRTUAL CORE
; RETURNS HERE WHEN THE PAGES HAVE BEEN ALLOCATED
;STOPS IF THE PAGES ALREADY EXIST, CALLERS RESPONSIBILITY TO
; CHECK TO SEE THAT THE PROGRAM ISN'T GETTING TO BIG
CREMPG:
IFN FTMP,<
PUSHJ P,GGVMM## ;GET THE MM
>
GETMPG::PUSHJ P,SAVE3## ;SAVE P1-P3
IFN FTKL10,<
MOVE P3,T3 ;SAVE CACHED/UNCACHED FLAG
>
CAMLE T2,VIRTAL## ;MAKE SURE THERE'S ENOUGH SPACE
POPJ P, ;FAIL
DMOVEM T1,P1 ;SAVE STARTING PAGE NUMBER, NUMBER OF PAGES
MOVN T3,T2 ;MINUS THE NUMBER OF PAGES OF INCREASE
ADDM T3,VIRTAL## ;DECREMENT TOTAL SYSTEM VIRTUAL MEMORY AVAILABLE
CREMP1: MOVE T3,P2 ;NUMBER OF PAGES TO ALLOCATE
PUSHJ P,FRDCRW## ;ENOUGH CORE IN CORE TO SATISFY REQUEST?
JRST CREMP5 ;NO, ALLOCATE CORE ON THE DISK
SE1ENT ;ENTER SECTION 1 TO ADDRESS PAGTAB
PUSH P,J ;SAVE J, COULD POINT AT A KDB
MOVE J,.CPJOB## ;CURRENT JOB
MOVE T3,[MCPCNT] ;ONE IN COUNT OF FUNNY PAGES BYTE
IMULI T3,(P2) ;TIMES THE NUMBER OF FUNNY PAGES TO ALLOCATE
ADDM T3,JBTPDB##(J) ;UPDATE NUMBER OF FUNNY PAGES OWNED BY THIS JOB
MOVE T2,P2 ;NUMBER OF PAGES REQUESTED
LDB T1,JBYSSA## ;FIRST PAGE OF JOB
PUSHJ P,ADPAGS## ;ALLOCATE THAT NUMBER
EXCH P1,T1 ;P1 = FIRST PHYSICAL PAGE ALLOCATED, T1 = VIRTUAL PAGE
IFN FTLOCK,<
LDB T2,JBYLSA## ;PAGE 0
SSX T2,MS.MEM ;PAGTAB SECTION NUMBER
HLR P3,PAGTAB(T2) ;LOCK BITS
>
SSX P1,MS.MEM ;PAGTAB SECTION
JRST CREMP3 ;GO ADD THE PAGES TO THE JOB'S MAP
CREMP2: SSX P1,MS.MEM ;SET PAGTAB SECTION NUMBER
HRRZ P1,PAGTAB(P1) ;NEXT PHYSICAL PAGE
CREMP3:
IFN FTLOCK,<
HRLM P3,PAGTAB(P1) ;LOCK BITS
>
IFN FTKL10,<
JUMPGE P3,CREMP4 ;JUMP IF CACHED PAGE
PUSHJ P,WSBIT ;SETUP FOR CALL TO INSMPU
MOVE T3,P1
HRLI T3,(<PM.DCD>B2+PM.WRT+PM.PUB+PM.COR)
PUSHJ P,INSMPU ;PUST THE PAGE IN THE JOB'S MAP
CAIA ;SKIP
CREMP4:>
PUSHJ P,INSMPC ;INSERT THE PAGE IN THE JOB'S MAP CACHED
ADDI T1,1 ;NEXT VIRTUAL PAGE
SOJG P2,CREMP2 ;LOOP OVER ALL PAGES ALLOCATED
CLRPGT ;CLEAR MEMORY OF PREVIOUS MAP
JRST JPOPJ1## ;RESTORE J AND RETURN
CREMP5: PUSH P,J ;SAVE J, COULD POINT AT A KDB
MOVE J,.CPJOB## ;CURRENT JOB
IFN FTLOCK,<
MOVSI T2,NSHF!NSWP ;JOB IS LOCKED BITS
TDNN T2,JBTSTS##(J) ;IS THE JOB LOCKED?
JRST CREMP6 ;NO
IFN FTMP,<
PUSHJ P,DWNMM## ;RETURN THE MEMORY MANAGEMENT RESOURCE
>
PUSH P,T1 ;YES, SAVE STARTING PAGE NUMBER
MOVEI T1,1 ;SLEEP 1 SECOND SINCE CANNOT SWAP OUT JOB TO ALLOCATE CORE
PUSHJ P,SLEEPF## ;ZZZZZZ
POP P,T1 ;RESTORE STARTING PAGE NUMBER
IFN FTMP,<
PUSHJ P,UPMM## ;RE-GET THE MM RESOURCE
>
POP P,J
JRST CREMP1 ;AND START OVER FROM SCRATCH
>
IFE FTLOCK,<
SETZ T2, ;FOR CALL TO IOWAT BELOW
>
CREMP6: PUSH P,S ;SAVE S (FILSER IS PARTICULAR ABOUT THAT)
PUSH P,F ;AND F
PUSHJ P,IOWAT ;WAIT FOR ALL I/O TO STOP SINCE JOB WILL BE SWAPPED
POP P,F ;RESTORE F
POP P,S ;AND S
LDB T2,NFYPGS## ;NUMBER OF FUNNY PAGES CURRENTLY ALLOCATED TO THE JOB
ADD T2,P2 ;PLUS NUMBER OF PAGES OF INCREASE
DPB T2,IFYPGS## ;NUMBER OF PAGES REQUIRED WHEN SWAPPED BACK IN
CREMP7:
IFN FTKL10,<
PUSHJ P,[JUMPG P3,INSDMC ;IF CACHED
JRST INSDMU] ;IF NOT
>
IFN FTKS10,<
PUSHJ P,INSDMU ;INSERT PAGE (NEEDN'T WORRY ABOUT CACHE)
>
ADDI T1,1 ;NEXT VIRTUAL PAGE
SOJG P2,CREMP7 ;NEXT PAGE
PUSHJ P,XPANDH## ;MARK JOB AS EXPANDING
POP P,J ;RESTORE J
IFN FTMP,<
PUSHJ P,REMMM## ;GIVE UP MM NOW THAT XJOB AND JXPN AGREE
>
AOS (P) ;EVERYTHING IS OK
PJRST WSCHED## ;AND WAIT UNTIL THE JOB IS BACK IN CORE
;ROUTINE TO REQUEST ALLOCATION OF MONITOR PAGES AT CLOCK LEVEL.
;WHEN ALLOCATION IS COMPLETE (MAY TAKE A WHILE) THE CALLER WILL
;BE CALLED AT THE ADDRESS THEY SPECIFIED. THIS ROUTINE CAN BE
;CALLED ON ANY CPU BUT WILL ONLY RECALL ON THE BOOT CPU.
;CALL:
; T1/ SECTION #,,# PAGES REQUIRED
; T2/ ADDRESS OF ROUTINE TO CALL WHEN ALLOCATION COMPLETE
; T3-T4/ ARGUMENTS FOR CALLED ROUTINE (RETURNED IN T3-T4)
; PUSHJ P,GETCLP
;RETURN:
; CPOPJ ALWAYS
CLPLNK==0 ;LINK TO NEXT REQUEST IN CHAIN
CLPPGS==1 ;SECTION NUMBER,,NUMBER OF PAGES TO ALLOCATE
CLPRTN==2 ;ROUTINE TO CALL WHEN ALLOCATION COMPLETE
CLPARG==3 ;ARGUMENTS TO ROUTINE
CLPADR==5 ;VIRTUAL ADDRESS OF PAGES ALLOCATED
CLPLEN==10 ;LENGTH (ROUNDED UP TO A 4-WORD BOUNDRY)
$CSENT (GETCLP::) ;GLOBAL ENTRY
PUSHJ P,SAVE4## ;SAVE P1-P4
DMOVE P1,T1 ;SAVE CALLER'S ARGUMENTS
DMOVE P3,T3 ;...
MOVEI T2,CLPLEN ;GET MEMORY FOR REQUEST BLOCK
S0PSHJ GETWDS## ;ASK
STOPCD .,STOP,CAC, ;++CAN'T ALLOCATE CLOCK LEVEL PAGES
SETZM CLPLNK(T1) ;CLEAR LINK WORD
DMOVEM P1,CLPPGS(T1) ;SAVE ARGUMENTS
DMOVEM P3,CLPARG(T1) ;...
SYSPIF ;PREVENT RACES
MOVEM T1,@CLPBOT## ;LINK NEW ENTRY ONTO END OF LIST
MOVEM T1,CLPBOT## ;MAKE THIS ENTRY THE NEW END
JRST ONPOPJ## ;RESTORE PI'S AND RETURN
;ROUTINE TO LOOP THROUGH THE CLP LIST AND ALLOCATE PAGES.
;CAN ONLY BE CALLED ON THE BOOT CPU.
CRECLP::SE1ENT ;MUST RUN IN NZS
PUSHJ P,SAVE1## ;SAVE P1
MOVE P1,CLPTOP## ;GET FIRST ENTRY IN LIST
MOVE T1,CLPPGS(P1) ;GET NUMBER OF PAGES REQUESTED
IFN FTMP,<
JUMPL T1,CRECL1 ;JUMP IF WAITING FOR THE CACHE OR DATAO PAG,
PUSHJ P,GETMM## ;MUST HAVE THE MM
POPJ P, ;CAN'T GET IT, TRY AGAIN LATER
>; END IFN FTMP
HRRZ T3,T1 ;NUMBER OF PAGES TO ALLOCATE
PUSHJ P,FRDCR## ;SEE IF THE CORE IS AVAILABLE IN CORE
IFE FTMP,<
POPJ P, ;NOT NOW, WAIT A WHILE
>; END IFE FTMP
IFN FTMP,<
PJRST GIVMM## ;NOT NOW, WAIT A WHILE (GIVE UP MM)
>; END IFN FTMP
PUSHJ P,SAVR## ;SAVE R (JUST SUPERSTITION I HOPE)
HLRZ R,CLPPGS(P1) ;SECTION TO ALLOCATE FROM
HRRZ T2,T1 ;NUMBER OF PAGES TO ALLOCATE
PUSHJ P,CREMNS ;ALLOCATE PAGES, SETUP MAPS
IFE FTMP,<
STOPCD CPOPJ##,DEBUG,FDL, ;++FRDCR LIED
>; END IFE FTMP
IFN FTMP,<
STOPCD GIVMM##,DEBUG,FDL, ;++FRDCR LIED
PUSHJ P,GIVMM## ;NOW OK TO RETURN THE MM
>; END IFN FTMP
MOVEM T1,CLPADR(P1) ;SAVE VIRTUAL ADDRESS OF PAGES JUST ALLOCATED
IFN FTMP,<
HRROS CLPPGS(P1) ;INDICATE WAITING ON CACHE AND PAGING MEMORY
; ON OTHER CPUS
HRROI T1,[MOVE T2,.CPCSN##-.CPCDB##(P1) ;BUMP CACHE SWEEP NUMBER
ADDI T2,2 ; ON ALL OTHER CPUS
MOVEM T2,.CPCSW##-.CPCDB##(P1) ;...
POPJ P,] ;RETURN FROM CPUAPP
PUSHJ P,CPUAPP## ;CAUSE ALL CPUS TO SWEEP CACHE AND DO A DATAO PAG,
CRECL1: PUSHJ P,MLSCSH## ;SEE IF MONITOR LOW SEGMENT CACHED (ONLY 1 CPU RUNNING)
CAIA ;NO
JRST CRECL2 ;YES, DON'T HAVE TO WORRY ABOUT OTHER CPUS
HRROI T1,[SKIPGE .CPOK##-.CPCDB##(P1) ; (ONLY CHECK IF CPU ALIVE AND WELL)
SKIPN .CPCSW##-.CPCDB##(P1) ;HAVE WE SWEPT YET?
CAIA ;HAVE SWEPT OR CAN'T BECAUSE CPU HAS DIED
SETO T3, ;FLAG SOMEONE STILL NEEDS TO SWEEP
POPJ P,] ;RETURN FROM CPUAPP
SETZ T3, ;ASSUME ALL CPUS ARE DONE
PUSHJ P,CPUAPP## ;HAVE ALL CPUS SWEPT AND CLEARED PAGING MEMORY?
JUMPN T3,CPOPJ## ;NO, STILL HAVE TO WAIT A WHILE
>; END IFN FTMP
CRECL2: MOVE T1,CLPADR(P1) ;GET VIRTUAL ADDRESS OF MEMORY ALLOCATED
HRRZ T2,CLPPGS(P1) ;GET NUMBER OF PAGES REQUESTED
DMOVE T3,CLPARG(P1) ;GET ARGUMENTS FOR ROUTINE
PUSHJ P,@CLPRTN(P1) ;CALL THE NOTIFICATION ROUTINE
SYSPIF ;PREVENT RACES
MOVE T1,CLPLNK(P1) ;GET LINK TO NEXT BLOCK
JUMPN T1,CRECL3 ;JUMP IF THERE IS ONE
MOVEI T2,CLPTOP## ;NOTHING, RESET EMPTY QUEUE
MOVEM T2,CLPBOT## ;...
CRECL3: MOVEM T1,CLPTOP## ;MAKE NEXT NEW FIRST
SYSPIN ;OK TO INTERRUPT AGAIN
MOVEI T1,CLPLEN ;NUMBER OF WORDS
MOVE T2,P1 ;ADDRESS OF THEM
S0JRST GIVWDS## ;RETURN THE CHUNK AND RETURN
;SUBROUTINE TO ALLOCATE AND MAKE ADDRESSABLE PAGES IN A NON-ZERO SECTION
;CALLING SEQUENCE:
; MOVEI R,SECTION NUMBER PAGES ARE TO BE ALLOCATED IN
; IF (R) = 0, ALLOCATE IN FUNNY SPACE
; MOVEI T2,NUMBER OF PAGES TO BE ALLOCATED
; PUSHJ P,CREMNS
; ... ;RETURNS HERE IF NOT POSSIBLE TO ALLOCATE PAGES
; ... ;RETURNS HERE WITH T1 = VIRTUAL ADDRESS OF PAGES ALLOCATED
;MUST BE CALLED IN SECTION 1 IF ALLOCATING NZS SPACE
CREMNS::JUMPE R,CREFSP ;IF (R) = 0, ALLOCATE A PAGE OF FUNNY SPACE
PUSHJ P,SAVE4## ;SAVE WORKING ACS
IFN FTXMON,<
SKIPE .UONCE## ;IF USER-MODE,
PJRST USRNZN## ;GO GET A PAGE IN SAT SPACE
>
MOVE P1,T2 ;SAVE NUMBER OF PAGES REQUESTED
;VERIFY THAT ALLOCATING A PHYSICAL PAGE WON'T PREVENT ANY JOB FROM BEING SWAPPED
; IN AND ADJUST CORMAX IF NEED BE TO KEEP ANY JOB FROM GETTING TO BIG AFTER A PAGE
; IS ALLOCATED. ACCOUNT FOR SECTION MAP IF IT MUST BE ALLOCATED.
; INSERT CODE HERE
IFN FTXMON,<
MOVE T1,R ;SECTION TO ALLOCATE FROM
ADD T1,.CPEPT## ;ADDRESS OF THE EPT
SKIPE T2,SECTAB(T1) ;SECTION ALREADY EXIST?
JRST CREMN1 ;YES, JUST FIND THE FREE PAGES
;HERE WHEN A PAGE MUST BE ALLOCATED FOR A SECTION MAP
MOVEI T3,1 ;ALLOCATE 1 PAGE
PUSHJ P,GETPHP ;GET A PAGE OF PHYSICAL MEMORY
HRRZ T2,T1 ;PAGE NUMBER
MOVE T1,R ;SECTION NUMBER
MOVEM T2,SPTCOM##-<(MS.FMD)>(T1) ;STORE IN SPT SLOT
PUSH P,T2 ;SAVE THE PAGE NUMBER OF THE NEW SECTION MAP
ADDI T1,SECTAB ;WHERE TO STORE
PUSHJ P,STMAPS ;STORE PAGE NUMBER IN THE SECTION MAP
HRRZ T2,R ;SECTION NUMBER
ADD T2,.CPEPT## ;ADD IN EPT ADDRESS
MOVE T2,SECTAB(T2) ;GET SECTION MAP ENTRY
MOVEI T1,[HRRZ T3,R ;GET SECTION NUMBER
ADD T3,P1 ;ADD IN CDB ADDRESS
MOVEM T2,.CPMMA##-.CPCDB##(T3) ;FIX UP .CPMMA
POPJ P,]
PUSHJ P,CPUAPP## ;DO IT FOR ALL CPUS
POP P,T2 ;RESTORE PAGE NUMBER OF THE NEW SECTION MAP
>;END IFN FTXMON
IFE FTXMON,<
MOVE T2,.CPEPT## ;EPT FOR THIS CPU
MOVE T2,SECTAB+0(T2) ;CURRENT S0 MAP
>;END IFE FTXMON
CREMN1: HRLI T2,(<PM.DCD>B2+PM.WRT+PM.PUB+PM.COR)
MOVEM T2,.UPMP+.UMTMP ;MAKE SECTION MAP ADDRESSABLE
; CLRPT .TEMP ;MAKE NEW MAPPING VISIBLE
CLRPGT ;WANT TO FLUSH ENTIRE PAGING MEMORY TO BE
; SURE WE HAVE AN UP-TO-DATE SECTION MAP
PUSH P,T2 ;SAVE FOR LATER
MOVSI T1,-<HLGPNO+2> ;MAX # OF SLOTS+1 (FOR PRE-INCREMENT)
CREMN2: HRRZ P2,T1 ;FIRST FREE SLOT SEEN
MOVEI T3,0 ;NUMBER OF CONTIGUOUS FREE SLOTS SEEN SO FAR
CREMN3: CAIL T3,(P1) ;FOUND ENOUGH FREE SLOTS YET?
JRST CREMN4 ;YES
AOBJP T1,TPOPJ## ;SECTION FULL, CAN'T ALLOCATE HERE
SKIPE .TEMP-1(T1) ;NEXT SLOT FREE?
JRST CREMN2 ;NO, LOOK HIGHER UP
AOJA T3,CREMN3 ;YES, SEE IF ENOUGH SLOTS HAVE BEEN FOUND
CREMN4: PUSH P,P1 ;SAVE NUMBER OF MAP SLOTS TO RESERVE
PUSH P,P2 ; AND STARTING MAP SLOT
MOVSI T2,1 ;GET INVALID MAP SLOT MARKER
CREMN5: MOVEM T2,.TEMP(P2) ;MANUALLY UPDATE OUR MAP
SOJLE P1,CREMN6 ;DECREMENT COUNT OF SLOTS TO RESERVE, JUMP WHEN
; WE'VE RESERVED THE LAST ONE
AOJA P2,CREMN5 ;LOOP FOR REMAINING SLOTS
CREMN6: MOVEI T1,.TEMP(P2) ;WHERE TO STORE IN THE SECTION MAP
PUSHJ P,STMAPE ;RESERVE THE LAST MAP SLOT WHILE WE HAVE THE MM
;(YES, WE'VE ALREADY STORED THE MAPPING, BUT WE
; WANT TO FORCE OTHER CPUS TO UPDATE THEIR
; PAGING MEMORIES, SO WE HAVE TO CALL STMAPE)
POP P,P2 ;RESTORE STARTING MAP SLOT
POP P,P1 ; AND NUMBER OF MAP SLOTS
MOVE T3,P1 ;NUMBER OF PAGES TO ALLOCATE
PUSHJ P,GETPHP ;GET THE PAGES
POP P,.UPMP+.UMTMP ;MAKE THE SECTION MAP ADDRESSABLE
CLRPT .TEMP ;MAKE NEW MAPPING VISIBLE
MOVE P3,P2 ;STARTING MAP SLOT (NEEDED FOR VIRTUAL ADDRESS)
HRRZ P4,T1 ;FIRST PHYSICAL PAGE ALLOCATED
CREMN7: MOVE T2,P4 ;PAGE NUMBER TO T2
MOVEI T1,.TEMP(P2) ;WHERE TO STORE IN THE SECTION MAP
PUSHJ P,STMAPE ;MAKE THE MAP ENTRY
SSX P4,MS.MEM ;PAGTAB SECTION
MOVSI T1,TNCSHB ;"TEMPORARILY UNCACHED" BIT
IORB T1,PAGTAB(P4) ;SET THE BIT AND GET THE LINK TO NEXT PAGE
HRRZ P4,T1 ;NEXT PAGTAB ENTRY
SOSLE P1 ;LAST PAGE?
AOJA P2,CREMN7 ;NO, MAKE ENTRIES FOR EVERY PAGE *WE* ALLOCATED
CLRPGT ;CLEAR PAGING MEMORY
MOVE T1,P3 ;FIRST SLOT ALLOCATED
LSH T1,P2WLSH ;ADDRESS WITHIN THE SECTION
SSXE T1,(R) ;FULL VIRTUAL ADDRESS OF CORE ALLOCATED
JRST CPOPJ1## ;GIVE WON RETURN
;ROUTINE TO CREATE A PAGE IN FUNNY SPACE
; CALL WITH T1=BITS,,HEADER
;RETURNS CPOPJ IF NONE AVAILABLE, CPOPJ1 IF AVAILABLE, T1 = VIRTUAL ADDRESS OF PAGE
CREFSP::PUSH P,T1 ;SAVE BITS,,HEADER
MOVEI T1,.MCFV/PAGSIZ ;VIRTUAL PAGE NUMBER OF FIRST FUNNY PAGE
CREFS1: PUSHJ P,TSWST ;DOES IT EXIST
JRST [MOVE T2,-1(P) ;NO, CHECK IF RESTRICTED PAGE
CAIN T1,<<.MCFV+NWMCP>/PAGSIZ>-1 ;THE NEXT TO THE LAST FUNNY PAGE
TLNE T2,200000 ;YES, ARE WE ALLOWED TO GIVE IT OUT
JRST CREFS2 ;OK TO CREATE THIS PAGE
AOJA T1,.+1] ;CANNOT GIVE IT OUT, STOP LOOP
CAIGE T1,<.MCFV+NWMCP>/PAGSIZ ;OFF THE END OF FUNNY SPACE
AOJA T1,CREFS1 ;LOOK FOR A NON-EXISTANT PAGE
JRST TPOPJ## ;NONE AVAILABLE
CREFS2: MOVEI T2,1 ;NUMBER OF PAGES TO CREATE
PUSH P,T1 ;SAVE VIRTUAL PAGE NUMBER
IFN FTKL10,<
MOVE T3,-1(P) ;GET SIGN BIT FOR UNCACHED
>
PUSHJ P,CREMPG ;CREATE THE PAGE
JRST TTPOPJ## ;FAIL IF NO VIRTUAL SPACE
POP P,T1 ;RESTORE VIRTUAL PAGE NUMBER
SUBI T1,<.MCFV-.FPMC>/PAGSIZ ;CONVERT TO PER-PROCESS ADDRESS
LSH T1,P2WLSH ;...
JRST T2POJ1## ;POP OFF JUNK AND GIVE GOTIT RETURN
;SUBROUTINE TO GET PHYSICAL PAGES OF MEMORY
; CALL WITH T3 = NUMBER OF PAGES TO ALLOCATE
; CALLERS RESPONSABILITY TO CHECK TO SEE IF ALLOCATING PAGES REQUESTED WILL
; LEAVE ENOUGH ROOM FOR THE BIGGEST JOB TO SWAP IN
; RETURNS WITH T1 = FIRST PAGE ALLOCATED
; MUST OWN THE MM BEFORE CALL
GETPHP::PUSHJ P,FRDCR## ;MAKE ROOM IF POSSIBLE
CAIA ;DIDN'T MAKE IT, WAIT A WHILE
JRST GETPH1 ;PAGES ARE AVAILABLE, ALLOCATE THEM
PUSHJ P,UUOLVL## ;IF NOT AT UUO LEVEL, STOP (CALLER IS CONFUSED)
STOPCD CPOPJ##,DEBUG,NUL ;++NOT AT UUO LEVEL
IFN FTMP,<
PUSHJ P,DWNMM## ;RETURN MM BEFORE SLEEPING
>
PUSH P,T3 ;SAVE NUMBER OF PAGES REQUESTED
MOVEI T1,1 ;SLEEP A TIC
IFN FTXMON,<
PUSHJ P,SLEEPF## ;ZZZZZZ
>
IFE FTXMON,<
RGCALL SLEEPF##
>
IFN FTMP,<
PUSHJ P,UPMM## ;GET THE MM BACK
>
POP P,T3 ;RESTORE SIZE OF REQUEST
JRST GETPHP ;AND TRY AGAIN
GETPH1: SE1ENT ;ENTER SECTION 1
MOVE T2,T3 ;NUMBER OF PAGES TO GET
LSH T3,P2WLSH ;NUMBER OF WORDS BEING ALLOCATED
MOVNS T3 ;MAKE NEGATIVE
ADDM T3,MAXMAX## ;DECREASE MAX CORMAX
ADDB T3,RMCMAX## ;ADJUST REAL CORMAX
CAMGE T3,CORMAX## ;LOWER THAN CORMAX?
MOVEM T3,CORMAX## ;YES, DECREASE CORMAX AS WELL
PUSHJ P,GTPAGS## ;GET THE NEEDED PAGES
MOVE T3,T1 ;RETURN FIRST PAGE ALLOCATED IN T1
SSX T3,MS.MEM ;PAGTAB SECTION
GETPH2: HRRZ T2,T3 ;PAGE NUMBER OF PAGE TO BE ZEROED
PUSHJ P,ZPAGE ;ZERO THE PAGE
MOVSI T2,MONTRB+TNCSHB;MARK THIS PAGE AS A MONITOR PAGE
IORB T2,PAGTAB(T3) ;LITE THE BIT AND GET NEXT PAGE NUMBER
TRNN T2,-1 ;LAST PAGE ALLOCATED?
JRST GETPH3 ;SET UP PT2TAB AND RETURN
HRR T3,T2 ;NO, NEXT PAGE NUMBER
JRST GETPH2 ;LOOP TO MARK AND ZERO ALL PAGES ALLOCATED
GETPH3: HRRZ T2,LMPAG## ;GET LAST ALLOCATED MONITOR PAGE
HRRZM T3,LMPAG## ;SET LAST PAGE ALLOCATED
SSX T2,MS.MEM ;PAGTAB SECTION
HRRM T1,PAGTAB(T2) ;SET FORWARD LINK
HRRZM T2,@[IW MS.MEM,PT2TAB(T1)] ;SET BACK LINK
POPJ P,
;SUBROUTINE TO STORE A PAGE NUMBER IN A MAP (CAUSES ALL CPUS TO SEE NEW MAPPING)
; ENTER AT STMAPS TO STORE IN SECTION TABLE, STMAPE TO STORE IN SECTION MAP
;CALL WITH T1= MAP OFFSET, T2 = NEW PHYSICAL PAGE # (OR ZERO IF
;CLEARING). IF LH (T2) NON-ZERO, MAP ENTRY IS STORED VERBATIM (SEE CREMN5).
IFN FTXMON,<
STMAPS: TLOA T1,400000 ;REMEMBER ENTRY POINT
>
STMAPE: TLZ T1,400000 ;REMEMBER ENTRY POINT
PUSHJ P,SAVE4## ;SAVE ACS
IFN FTXMON,<
SKIPGE T1 ;STORING SECTION POINTER?
SKIPA P2,[<POINT 36,(P4),35>] ;YES, BYTE POINTER TO EPT INDEXED BY .CPEPT
>
MOVSI P2,(POINT 36,0,35) ;BYTE POINTER TO STORE IN SECTION MAP
SKIPN P3,T2 ;IF ZERO, STORE A ZERO
JRST STMAP1
TLNE P3,-1 ;LH NON-ZERO?
JRST STMAP1 ;YES, MUST BE CREMN5 RESERVING SLOTS
HRLI P3,(<PM.DCD>B2+PM.WRT+PM.CSH) ;ACCESSIBLE, WRITABLE, CACHED
SKIPL T1 ;IF NOT STORING SECTION POINTER,
TLOA P3,(PM.KPM) ; ALWAYS LIGHT "KEEP ME"
IOR P3,.CPKPM## ;ALSO LITE "KEEP ME" IF THERE IS AN MCA25
IFN FTPEEKSPY,<
SKIPL T1 ;SECTION POINTER?
TLO P3,(PM.PUB) ;NO, PAGES MUST BE PUBLIC FOR SPYING
>
IFN FTMP,<
JUMPL T1,STMAP1 ;SECTION POINTERS ALWAYS HAVE CACHE BIT ON
PUSHJ P,MLSCSH## ;MONITOR LOW SEGMENT CACHED?
TLZ P3,(PM.CSH) ;NO, CACHE MUST BE OFF
>
STMAP1: HRRI P2,(T1) ;OFFSET INTO SECTION TABLE OR MAP
MOVEI T1,STMPEC## ;ROUTINE TO STORE ENTRY IN ALL CPU'S MAPS
PUSHJ P,UUOLVL## ;MM AND SLEEPING (WAITING) ARE THE CALLER'S
S0JRST CPUAPP## ; RESPONSIBILITY IF NOT AT UUO LEVEL
IFN FTMP,<
PUSHJ P,DIFMM## ;GIVE UP THE MM IF OWNED SINCE STMPEC MAY SLEEP
>
S0PSHJ CPUAPP## ; AND INSURE THAT ALL CPUS SEE THE NEW MAPPING
; DO IT
IFN FTMP,<
PJRST UIFMM## ;RESTORE THE MM IF OWNED UPON ENTRY
>
IFE FTMP,<
POPJ P, ;RETURN
>
;SUBROUTINE TO ALLOCATE FUNNY SPACE IN WORDS RATHER THAN CHUNKS
; T2/ NUMBER OF WORDS DESIRED
; PUSHJ P,GTFWDC ;GET FUNNY WORDS, CACHED
; -OR-
; PUSHJ P,GTFWDU ;GET FUNNY WORDS, UNCACHED
;RETURN CPOPJ IF SPACE IS NOT AVAILABLE
; CPOPJ1 IF IT IS, T1 = ADDRESS
GFWDCH::HRRZS .USFCU ;CLEAR LARGEST HOLE
PUSHJ P,GTFWDC ;GET THE SPACE
CAIA ;NOT AVAILABLE
JRST CPOPJ1## ;GOT IT
HLRZ T2,.USFCU ;GET SIZE OF BIGGEST HOLE
POPJ P, ; AND FAIL
IFN FTKL10,<
GFWDUD::SKIPA T1,[GTFWDU] ;TRY REGULAR ENTRY POINTS FIRST
GFWDCD::MOVEI T1,GTFWDC ;...
PUSHJ P,(T1) ;CALL CORRECT ROUTINE
>
IFE FTKL10,<
GFWDUD::
GFWDCD::PUSHJ P,GTFWDC ;ALL THE SAME ON KI/KS
>
CAIA ;NO FUNNY SPACE AVAILABLE
JRST CPOPJ1## ;GIVE GOOD RETURN
MOVE T1,[600000,,.USFCD] ;TRY RESTRICTED SPACE
JRST GTFWD1 ;AND HOPE THAT THERE IS SOME
GTFWDU::
IFN FTKL10,<
SKIPE [M.CPU##-1] ;ALL SPACE IS CACHED IF ONLY 1
SKIPA T1,[400000,,.USFCU] ;ELSE GET UNCACHED HEADER
>
GTFWDC::MOVEI T1,.USFCC ;POINT TO CACHED LIST HEAD
GTFWD1: PUSHJ P,SAVR## ;SAVE R
MOVEI R,(MDSEC0) ;SECTION 0 SPACE (REALLY FUNNY SPACE)
JRST GTFWD2 ;JOIN COMMON CODE
IFN FTXMON,<
$CSENT (GFWNZN::)
HRLI T1,400000 ;SET NZS FLAG
JRST GFWNZZ ;JOIN COMMON CODE
GFWNZ2::SKIPA T1,[400000,,(MS.SAT)] ;SECTION 2 CORE
GFWNZS::MOVE T1,[400000,,(MS.MEM)] ;GENERAL NZS SPACE
SE1ENT ;MUST BE IN SECTION 1 TO ALLOCATE NZS SPACE
GFWNZZ:
>
IFN FTMP,<
PUSHJ P,MMOWN## ;WE OWN MM ALREADY?
PUSHJ P,GGVMM## ;NO--MUST HAVE THE MM TO LINK THROUGH FREE CORE CHAINS
>
PUSHJ P,SAVR## ;SAVE R
MOVE R,T1 ;COPY SECTION # TO R
MOVE T1,NZSFCH##(R) ;HEADER FOR SPACE (ALWAYS UNCACHED)
GTFWD2: PUSH P,T1 ;SAVE HEAD (FLAG ACTUALLY)
GTFWD3:
IFE FTXMON,<
MOVEI T3,(T1) ;REMEMBER LINK
>
IFN FTXMON,<
MOVE T3,T1 ;REMEMBER LINK
SKIPE R ;SECTION ZERO ALWAYS STORES SECTION
CAME T3,NZSFCH##(R) ;IF NOT THE FIRST TIME IN NON-ZERO SECTION
SSXE T1,(R) ; SET SECTION INDEX TO FUNNY SPACE SECTION
>
HLL T3,T1 ;SET PREDECESSOR SECTION
JUMPE R,GTFWD4 ;NON-ZERO SECTION HAS END POINTER
CAMN T1,NZSFCE##(R) ;THIS LAST BLOCK?
JRST GTFWD7 ;YES
HRRZ T1,(T1) ;POINT TO NEXT BLOCK
JRST GTFWD5
GTFWD4: HRRZ T1,0(T1) ;T1 = CURRENT CHUNK ADDRESS
JUMPE T1,GTFWD7 ;IF 0, NO HOLE AVAILABLE, GET SOME MORE
GTFWD5: SSXE T1,(R) ;ADDRESS CORRECT SECTION
HLRZ T4,0(T1) ;SIZE OF THIS HOLE
CAIGE T4,(T2) ;LARGE ENOUGH FOR REQUEST
JRST [JUMPN R,GTFWD3 ;NO BIGGEST HOLE IN NZS SPACE
HRLZ T4,T4 ;NO, MOVE SIZE OF THIS HOLE
CAMLE T4,.USFCU ;BIGGEST YET
HLLM T4,.USFCU ;YES, REMEMBER FOR TMPCOR
JRST GTFWD3] ; AND LOOK AT THE NEXT
MOVEM T1,(P) ;SAVE CHUNK ADDRESS
CAIN T4,(T2) ;AN EXACT SIZE MATCH
JRST [HRR T4,0(T1) ;YES, GET POINTER TO NEXT
HRRM T4,0(T3) ;RE-LINK PREVIOUS
JUMPE R,TPOPJ1##
JRST GTFWD6] ;CHECK IF THIS WAS LAST
HRL T4,0(T1) ;GET LINK TO NEXT CHUNK
ADDI T1,(T2) ;ADDRESS OF REMAINDER THIS CHUNK
HRRM T1,0(T3) ;STORE LINK TO REMAINDER
SUBI T4,(T2) ;SIZE OF REMAINDER
MOVSM T4,0(T1) ;STORE NEW LENGTH,OLD LINK IN REMAINDER
JUMPE R,TPOPJ1## ;SECTION ZERO, WE ARE DONE
MOVE T3,T1 ;NEW LAST BLOCK
GTFWD6: POP P,T1 ;RESTORE ADDRESS
CAMN T1,NZSFCE##(R) ;JUST ALLOCATE LAST BLOCK?
MOVEM T3,NZSFCE##(R) ;STORE IT
JRST CPOPJ1## ;DONE
GTFWD7: PUSH P,T2 ;SAVE AMOUNT REQUESTED
MOVE T1,-1(P) ;BITS,,HEADER
MOVEI T2,1 ;ALWAYS CREATE ONLY 1 PAGE
PUSH P,R ;SAVE R
PUSHJ P,CREMNS ;CREATE A PAGE IN FUNNY SPACE OR NON-ZERO SECTION
JRST GTFWD8
POP P,R
JRST GTFWD9 ;A WINNER
GTFWD8: POP P,R
IFN FTKL10,<
POP P,T2 ;RESTORE AMOUNT REQUESTED
POP P,T1 ;RESTORE HEADER USED
SKIPE [M.CPU##-1] ;ONLY ONE TRY IF ALL IS CACHED
JUMPGE T1,GTFWDU ;TRY FOR UNCACHED SPACE IF NO CACHED
POPJ P, ;ELSE OUT OF FUNNY SPACE
>
IFE FTKL10,<JRST TTPOPJ##> ;ONLY 1 TRY ON KI/KS
GTFWD9: POP P,T4 ;RESTORE AMOUNT REQUESTED
POP P,T3 ;RESTORE FREE SPACE HEADER AND FLAG
MOVEI T2,PAGSIZ ;AMOUNT JUST ACQUIRED
CAIN T4,PAGSIZ ;REQUESTED EXACTLY ONE PAGE?
JRST CPOPJ1## ;YES, RETURN NOW
SKIPN DINITF## ;INITIALIZATION?
CAILE T4,PAGSIZ ;REQUESTING MORE THAN 1 PAGE
JRST GTFW10 ;YES, MERGE THIS PAGE AND TRY AGAIN
;(KEEP ALLOC CONTIGUOUS DURING INIT)
SUB T2,T4 ;AMOUNT LEFT OVER AFTER SATISFYING REQUEST
PUSH P,T1 ;SAVE ADDRESS OF NEWLY ACQUIRED CHUNK
ADD T1,T4 ;ADDRESS OF RESIDUE
EXCH T1,T2 ;WANT ARGS IN OTHER ORDER
.CREF NZS
SKIPGE R ;IS THIS FUNNY SPACE?
TLO R,(PIH) ;NO, LIGHT HEADER FLAG
PUSHJ P,GVFWD3 ;GIVE IT BACK (T3 ALREADY SET UP)
JRST TPOPJ1## ;AND GIVE GOOD RETURN TO CALLER
GTFW10: PUSH P,T3 ;SAVE HEADER AND FLAGS
PUSH P,T4 ;SAVE ORIGINAL AMOUNT REQUESTED
TLO T3,(DRP) ;LIGHT BIT SAYING NOT TO RETURN FULL PAGES
EXCH T1,T2 ;WANT LENGTH AND ADDRESS IN THE OTHER ORDER
.CREF NZS
SKIPGE R ;IS THIS FUNNY SPACE?
TLO R,(PIH) ;NO, LIGHT HEADER FLAG
PUSHJ P,GVFWD3 ;RETURN FULL PAGE TO THE FREE LIST
POP P,T2 ;RESTORE ORIGINAL WORDS REQUESTED
POP P,T1 ;RESTORE FREE SPACE HEADER AND FLAGS
JRST GTFWD2 ;AND TRY TO SATISFY THE REQUEST NOW
;SUBROUTINE TO RETURN WORDS ACQUIRED BY GTFWDC, GTFWDU, OR GFWNZS
;CALL: T1/ WORDS TO RETURN
; T2/ ADDRESS
; T3/FLAGS,,? ;BITS (SEE BELOW)
; PUSHJ P,GVFWDS
;FLAG BITS IN T3:
RSP==1B1 ;RESTRICTED SPACE
DRP==1B2 ;DON'T RECLAIM FULL PAGES
;INTERNAL FLAG BITS (IN R)
NZS==1B0 ;NZS-STYLE LIST (EVEN IF CORE IS IN S0)
PIH==1B1 ;PREDECESSOR IS HEADER (I.E. FIRST TIME THROUGH)
GVFNZD::!
GVFWDS::PUSHJ P,SAVR## ;SAVE TEMP USED FOR SECTION INDEX
GVFWD1:
IFN FTXMON,<
MOVEI R,(MDSEC0) ;ASSUME WE ARE TALKING ABOUT SECTION 0 SPACE
HLRZ T4,T2 ;SECTION NUMBER
>
IFE FTXMON,<
SETZB R,T4 ;ONCE ONLY OR FUNNY SPACE IS SECTION 0
>
CAML T2,LOCORE## ;ONCE-ONLY CORE?
IFN FTXMON,<
TLZE T2,-1 ;NZS SPACE?
TRNA ;ONCE ONLY OR NZS
>
JRST GVFWD2 ;NO, SECTION ZERO FUNNY SPACE
GVFWDC: CAIGE T4,NZSFCL## ;KNOW ABOUT THIS SECTION?
SKIPN T3,NZSFCH##(T4) ;?
STOPCD CPOPJ##,DEBUG,RWS, ;++RETURNING SPACE TO WRONG SECTION
IFN FTXMON,<
SKIPE R,T4 ;GET SECTION #
SE1ENT ;IF RETURNING NZS CORE
TLO R,(NZS!PIH) ;FLAG NOT FUNNY SPACE
>
IFE FTXMON,<
MOVSI R,(NZS!PIH) ;FLAG NOT FUNNY SPACE BUT STILL SECTION ZERO
>
IFN FTMP,<
PUSHJ P,MMOWN## ;WE OWN MM ALREADY?
PUSHJ P,GGVMM## ;NO--MUST INTERLOCK CHAIN CHASING
>
MOVE T3,NZSFCH##(R) ;GET PROPER HEADER
JRST GVFWD3 ;JOIN COMMON CODE
GVFWD2: MOVE T4,T2 ;COPY ADDRESS OF PIECE
LSH T4,W2PLSH ;CONVERT TO PAGE NUMBER
CAIGE T4,.LPMC/PAGSIZ ;RANGE CHECK IT
CAIGE T4,.FPMC/PAGSIZ ;...
STOPCD CPOPJ##,DEBUG,PFR, ;++PIECE OUT OF FREE RANGE
CAIN T4,<.LPMC/PAGSIZ>-1 ;IS THIS THE RESTRICTED PAGE
JRST [MOVE T3,[IFIW!RSP+.USFCD] ;YES, USE THIS HEADER
JRST GVFWD3] ;ENTER COMMON CODE
ADDI T4,<.MCFV-.FPMC>/PAGSIZ ;CONVERT TO VIRTUAL ADDRESS
PUSHJ P,GTPM4 ;GET PAGE MAP ENTRY
SKIPN T4
STOPCD CPOPJ##,DEBUG,FPE, ;++FUNNY PAGE MUST EXIST
IFN FTKL10,<
TLNN T4,(PM.CSH) ;A CACHED PAGE
SKIPA T3,[IFIW+.USFCU] ;GET UNCACHED LIST HEADER
>
MOVEI T3,.USFCC ;GET CACHED LIST HEADER
GVFWD3: SPUSH T3 ;PUSH LEFT HALF
TLZ T3,(DRP) ;CLEAR POSSIBLE FLAG.
TLNE R,(NZS) ;FUNNY SPACE?
TLNE R,(PIH) ;PIH ON ONLY FIRST TIME
CAIA
IFN FTXMON,<
SSXE T3,(R) ; RELOCATE TO DATA SECTION
>
IFE FTXMON,<
HRRZS T3 ;ALL IS REALLY S0
>
JUMPE R,GVFWD4 ;ZERO TERMINATION FOR SECTION ZERO
CAMN T3,NZSFCE##(R) ;ELSE IS THIS LAST?
JRST [SPOP T3
JRST GVFWD5] ;YES
GVFWD4: HRRZ T4,0(T3) ;GET FIRST CHUNK IN FREE LIST
SPOP T3 ;RESTORE LEFT HALF
TLNN R,(NZS) ;FUNNY SPACE?
JUMPE T4,GVFWD5 ;SECTION ZERO IS ZERO TERMINATED
CAIN T4,(T2) ;ALREADY IN FREE LIST
STOPCD CPOPJ##,STOP,PFL ;++PIECE ON FREE LIST
CAIL T4,(T2) ;KEEP CHUNKS IN ADDRESS ORDER
JRST GVFWD5 ;IT GOES HERE
HRR T3,T4 ;REMEMBER LINK
TLZ R,(PIH) ;PREDECESSOR NO LONGER HEADER
JRST GVFWD3 ;AND LOOK AT THE NEXT
GVFWD5: PUSH P,T3 ;SAVE PREVIOUS (AND FLAGS)
TLZ T3,(DRP) ;BE SURE FLAG IS CLEAR
MOVEI T4,(T3) ;ADDRESS OF PREVIOUS
JUMPL R,GVFWD6 ;ALWAYS COMBINE NZS
.CREF NZS
CAIE T4,.USFCD ;RESTRICTED SPACE HEADER
CAIN T4,.USFCC ;OR CACHED HEADER THE PREVIOUS?
JRST GVFWD8 ;YES, CANNOT COMBINE (LH OF HDR IS NOT A LENGTH)
JUMPE R,GVFWD7 ;SKIP SOME IF FUNNY SPACE
GVFWD6:
IFN FTKL10,<
TLNN R,(PIH) ;PREDECESSOR IS HEADER (FIRST TIME)?
GVFWD7: CAIN T4,.USFCU ;UNCACHED HEADER
>
IFE FTKL10,<
TLNE R,(PIH) ;PREDECESSOR IS HEADER (FIRST TIME)?
>
JRST GVFWD8 ;IF NZS HEADER, CANNOT COMBINE
IFE FTKL10,<
GVFWD7:
>
IFE FTXMON,<
TLZ T3,-1 ;CLEAR JUNK
>
IFN FTXMON,<
SSXE T3,(R) ;PROPER SECTION FOR REFERENCES BELOW
>
HLRZ T4,0(T3) ;LENGTH OF PREVIOUS PIECE
ADDI T4,(T3) ;FIRST WORD NOT IN PREVIOUS CHUNK
CAILE T4,(T2) ;BETTER BE
STOPCD TPOPJ##,STOP,FOP, ;++FUNNY ADDRESS OVERLAPS PREVIOUS
CAIE T4,(T2) ;PIECES CONTIGUOUS
JRST GVFWD8 ;NO, CANNOT COMBINE
MOVEI T2,(T3) ;YES, ADDRESS OF LARGER CHUNK
HLRZ T4,0(T3) ;SIZE OF PREVIOUS
ADD T1,T4 ;SIZE OF COMBINED PIECES
GVFWD8:
IFN FTXMON,<
SSXE T2,(R) ;SET FOR PROPER SECTION ADDRESSING
>
IFE FTXMON,<
HRRZS T2
>
HRLM T1,0(T2) ;SIZE OF THIS CHUNK
HRRZ T4,0(T3) ;PREVIOUS LINK TO NEXT
HRRM T4,0(T2) ;LINK THIS TO NEXT
CAME T2,T3 ;PREV=THIS (CONCATENATION)
HRRM T2,0(T3) ;NO, LINK PREV TO THIS
JUMPE R,GVFWD9
CAMN T3,NZSFCE##(R) ;LAST?
MOVEM T2,NZSFCE##(R) ;WE ARE NOW LAST
GVFWD9: HRRZ T3,T2 ;ADDRESS OF CURRENT
ADD T3,T1 ;+SIZE OF CURRENT
SKIPN T4 ;WAS LAST ADDRESS ZERO?
JUMPE R,GVFW10 ;YES, END OF LIST IF SECTION ZERO
CAMN T2,NZSFCE##(R) ;ARE WE NOW LAST?
JRST GVFW10 ;YES, THERE IS NO NEXT
CAILE T3,(T4) ;BETTER BE
STOPCD .,STOP,FON, ;++FUNNY ADDRESS OVERLAPS NEXT
CAIE T3,(T4) ;BUTT UP AGAINST NEXT ONE
JRST GVFW10 ;NO, CANNOT COMBINE THAT SIDE
HRLZS T1 ;SIZE OF CURRENT,,0
IFN FTXMON,<
SSXE T4,(R) ;PROPER SECTION (STILL CLEAR IF IFE FTXMON)
>
ADD T1,0(T4) ;COMBINED SIZE,,NEXT'S LINK
MOVEM T1,0(T2) ;STORE NEW INFO
HLRZS T1 ;ISOLATE SIZE OF NEW, LARGER PIECE
JUMPE R,GVFW10 ;NOTHING MORE IF SECTION 0
CAMN T4,NZSFCE##(R) ;WAS THIS LAST?
MOVEM T2,NZSFCE##(R) ;WE ARE LAST NOW
GVFW10: POP P,T3 ;RESTORE ORIGINAL PREVIOUS (AND FLAGS)
TLNE T3,(DRP) ;SUPRESS RECLAMATION OF FULL PAGES
POPJ P, ;YES, ALL DONE NOW
TLCE R,(NZS) ;FUNNY SPACE?
JUMPE R,CPOPJ ;NO, CAN'T RECLAIM ONCE-ONLY CORE
TLC R,(NZS) ;PUT BIT BACK RIGHT
PUSHJ P,INTLVL## ;ONLY RECLAIM AT UUO LEVEL
CAIGE T1,PAGSIZ ;CAN WE RECLAIM A FULL CHUNK
POPJ P, ;NO, RETURN NOW
PUSHJ P,SAVE4## ;YES, SAVE SOME REGS
DMOVE P1,T1 ;SAVE LENGTH, ADDRESS OF PIECE
TRZ T1,PG.BDY ;MAX WORDS THAT CAN BE RETURNED
ADDI T2,PG.BDY ;AND ROUND ADDRESS TO CHUNK BOUNDRY
TRZ T2,PG.BDY ;...
MOVE P4,P2 ;ORIGINAL ADDRESS
ADD P4,P1 ;P4 = FIRST WORD NOT IN PIECE
MOVE T4,T2 ;START OF CHUNK THAT CAN BE RETURNED
ADD T4,T1 ;T4 = FIRST WORD THAT WON'T BE RETURNED
GVFW11: CAMGE P4,T4 ;RETURNABLE SPACE COMPLETELY CONTAINED
JRST [SUBI T1,PAGSIZ ;NO, LESS WORDS TO RETURN
JUMPE T1,CPOPJ## ;"AND THEN THERE WERE NONE"
SUBI T4,PAGSIZ ;ADJUST ENDING ADDRESS ( +1 )
JRST GVFW11] ;AND LOOK AT THE SMALLER PIECE
MOVEI P3,(P2) ;GET RIGHT HALF
CAIE P3,(T3) ;CURRENT = PREVIOUS (CONCATENTATION)
JRST [JUMPE R,GVFW15 ;GO IF FUNNY SPACE
TLNN R,(PIH) ;AT BEGINNING?
IFN FTXMON,< SSXE T3,(R)> ;NO, RELOCATE
IFE FTXMON,< HRRZS T3>
JRST GVFW15] ;AND UNLINK PIECE
JUMPE R,GVFW12 ;SECTION ZERO
HRR T3,NZSFCH##(R) ;ASSUME NZS CORE BEING RETURNED
JRST GVFW14 ;NON-ZERO SECTION
GVFW12: HRRI T3,.USFCC ;YES, MUST FIND NEW PREVIOUS
IFN FTKL10,<
SKIPGE T3 ;CACHED OR UNCACHED HEADER NEEDED
HRRI T3,.USFCU ;UNCACHED
>
TLNE T3,(RSP) ;RESTRICTED SPACE
HRRI T3,.USFCD ;YES
GVFW13:
IFN FTXMON,<
SSXE T3,(R) ;SET TO ADDRESS PROPER SECTION
>
IFE FTXMON,<
HRRZS T3
>
GVFW14: HRRZ P3,0(T3) ;GET LINK TO NEXT
CAIN P3,(P2) ;POINT TO THIS ONE
JRST GVFW15 ;YES, T3 = NEW PREVIOUS
HRR T3,P3 ;COPY PREVIOUS
JRST GVFW13 ;AND GO LOOK AGAIN
GVFW15: SPUSH P2 ;SAVE LEFT HALF
IFN FTXMON,<
SSXE P2,(R) ;SET PROPER SECTION
>
IFE FTXMON,<
HRRZS P2
>
HRRZ P3,0(P2) ;GET ADDRESS OF NEXT CHUNK
JUMPE R,GVFW16 ;SECTION ZERO
CAMN P2,NZSFCE##(R) ;WERE WE THE LAST?
MOVEM T3,NZSFCE##(R) ;PREDECESSOR NOW IS
GVFW16: SPOP P2 ;RESTORE LEFT HALF
HRRM P3,0(T3) ;DE-LINK THE LARGER PIECE
MOVE P1,T2 ;START OF REMOVED PIECE
SUB P1,P2 ;COMPUTE LENGTH OF L.H. EXCESS
MOVE P3,P4 ;1ST WORD NOT IN THE PIECE
SUB P3,T4 ;COMPUTE LENGTH OF R.H. EXCESS
MOVE P4,T4 ;AND WHERE IT STARTS
PUSH P,P1 ;SAVE REMAINDER INFORMATION
PUSH P,P2 ;...
DMOVE P1,T1 ;COPY AMOUNT TO RETURN
LSHC P1,W2PLSH ;P1 = NUMBER TO RETURN, P2 = PAGE NUMBER OF FIRST
GVFW17: MOVE J,.USJOB ;GET JOB NUMBER WHO OWNS THESE PAGES
PUSHJ P,DLTMPG ;DELTETE THIS PAGE
AOS P2 ;STEP TO NEXT PAGE TO RETURN
SOJG P1,GVFW17 ;GET THEM ALL
CLRPGT ;WE HAVE CHANGED THE MAP
POP P,T2 ;RESTORE LEFT HAND REMAINDER INFORMATION
POP P,T1 ;...
SKIPE T1 ;WAS THERE ANY
PUSHJ P,GVFWD1 ;YES, GIVE IT BACK
JUMPE P3,CPOPJ## ;DONE IF NO RIGHT HAND REMAINDER
DMOVE T1,P3 ;GET LENGTH AND ADDRESS OF IT
JRST GVFWD1 ;GIVE IT BACK AND RETURN
;SUBROUTINE TO RETURN A FUNNY PAGE, MUST BE A SUBROUTINE SO THAT
; IT CAN CALL THE COROUTINE GGVMM
; CALL WITH P2 = VIRTUAL PAGE NUMBER
DLTMPG: MOVE T1,P2 ;IN CASE A NZS PAGE
PJUMPN R,DNZSPG ;JUMP IF A NZS PAGE
IFN FTMP,<
PUSHJ P,GGVMM## ;GET MM RESOURCE SINCE DIDDLING CORE ALLOCATION TABLES
; WILL BE RETURNED UPON EXIT
>
DLTFSP::MOVN T1,[MCPCNT] ;DECREMENT COUNT OF FUNNY PAGES OWNED
ADDM T1,JBTPDB##(J) ;...
MOVEI T1,<.MCFV-.FPMC>/PAGSIZ(P2) ;CONVERT TO VIRTUAL PAGE NUMBER
PUSHJ P,TSWST ;GET BIT FOR WSBTAB
STOPCD .+1,DEBUG,PNW, ;++PAGE NOT IN WORKING SET
ANDCAM T2,(T4) ;NO LONGER IN WORKING SET
PUSHJ P,GTPME ;GET PAGE MAP ENTRY FOR IT
SETZM (T4) ;ZAP THE PAGE MAP ENTRY
TLZ T2,(PM.NAD) ;DOWN TO PHYSICAL PAGE NUMBER
PUSHJ P,LKPSF ;FIX UP PAGTAB
PJRST DLTPGC ;AND DELETE THE PAGE,
; RETURN MM RESOURCE AND RETURN TO CALLER
;SUBROUTINE TO RETURN A PAGE IN A NON-ZERO SECTION TO FREE CORE OR ONCE-ONLY CORE
; CALL WITH T1 = VIRTUAL PAGE NUMBER (MUST OWN THE MM RESOURCE)
;MUST BE IN SECTION 1
DNZSPG: LSHC T1,-^D9 ;ISOLATE SECTION NUMBER
LSH T2,-^D27 ;RIGHT JUSTIFY PAGE NUMBER
IFE FTXMON,<
MOVEI T1,0 ;MAKE SURE SECTION IS RIGHT
> ADD T1,.CPEPT## ;ADDRESS OF EPT + SECTION NUMBER
SKIPN T3,SECTAB(T1) ;GET ENTRY FROM SECTION MAP
STOPCD CPOPJ##,DEBUG,NXS, ;++NON-EXISTANT SECTION
MOVEM T3,.UPMP+.UMTMP ;MAKE THE SECTION MAP ADDRESSABLE
CLRPT .TEMP ;MAKE NEW MAPPING VISABLE
MOVEI T1,.TEMP(T2) ;ADDRESS OF THE POINTER SLOT (FOR STMAPE)
SKIPN T2,.TEMP(T2) ;GET PAGE POINTER
STOPCD CPOPJ##,DEBUG,RNP, ;++RETURNING NON-EXISTANT PAGE
TLZ T2,(PM.NAD) ;ISOLATE PHYSICAL PAGE NUMBER
; SE1ENT ;(RIGHT NOW, DNZSPG IS ALWAYS CALLED HERE)
PUSH P,T1 ;SAVE MAP OFFSET
HRRZ T1,@[IW MS.MEM,PT2TAB(T2)]
CAMN T2,LMPAG## ;IS THIS THE LAST MONITOR PAGE?
HRRZM T1,LMPAG## ;YES, NEW LAST PAGE
PUSHJ P,LKPSF ;REMOVE PAGE FROM MONITOR'S CHAIN
PUSHJ P,DLTPGC ;RETURN THE PAGE TO FREE CORE
MOVEI T1,PAGSIZ ;NUMBER OF WORDS BEING FREED
ADDM T1,MAXMAX## ;UPDATE MAXMAX TO REFLECT THAT
ADDM T1,RMCMAX## ;UPDATE REAL MAXIMUM FOR CORMAX
POP P,T1 ;RESTORE PAGE OFFSET
MOVEI T2,0 ;SET TO ZERO THE MAP SLOT
PJRST STMAPE ;ZERO THE MAP SLOT AND RETURN
SUBTTL COMCON INTERFACE WITH COMMAND DECODER
;PRIVILEGED COMMAND/UUO TO SET THE SYSTEM-WIDE VM LIMIT
SETVMX::PUSHJ P,CORLGL## ;GET CORE ARGUMENT
ADDI T2,1
LSH T2,W2PLSH ;CONVERT TO PAGES
SETVM1::CAMLE T2,VIRTAL## ;BIGGER THAN VIRTAL?
MOVE T2,VIRTAL## ;YES, USE VIRTAL
CAMGE T2,VMTOTL## ;BIGGER THAN TOTAL VM NOW IN USE?
MOVE T2,VMTOTL## ;YES, USE CURRENT AMOUNT IN USE
MOVEM T2,VMCMAX## ;SAVE SYSTEM WIDE VM LIMIT
PJRST CPOPJ1## ;AND RETURN
;PRIVILEGED UUO TO SET THE ABSOLUTE PER-USER MAXIMA
SETUVL::HRR M,T2 ;LOC OF ARGUMENT
TLZ M,MXSECN ;(SETUUO IS LOCAL)
PUSHJ P,FLTSX ;MAKE SURE WONT FAULT
JRST ECOD0## ;PAGE-FAULT AT NON-UUO LEVEL????!!??
PUSHJ P,GETWDU## ;GET ARG
PUSHJ P,CHKLIM ;MAKE SURE VALUES ARE OK
JRST ECOD0## ;NOT - NON SKIP
SETVLM::MOVEM T1,.PDMVL##(W) ;MVPL,,MPPL
SKIPN .PDCVL##(W) ;IF NOT ALREADY SET,
JRST SETUV2 ;SAVE AS CURRENT LIMITS TOO
PJRST CPOPJ1## ;AND GOOD RETURN
;NON-PRIVILEGED UUO TO SET INTERVAL FOR VIRTUAL-TIME INTERRUPT
SETVTM::PUSHJ P,FNDPDB## ;GET PDB FOR TARGET JOB
JRST ECOD0## ;CAN'T SET IF NO PDB
IMUL T2,TICSEC## ;CONVERT TO TICS-PER-INTERRUPT
IDIVI T2,^D1000
HRRM T2,.PDTMI##(W)
MOVEI T2,1 ;FIRST TIME, COUNT DOWN FAST
MOVEM T2,.PDTMC##(W)
PJRST CPOPJ1## ;AND RETURN
;SUBROUTINE TO CHECK CORE LIMITS
;ENTER T1=LIMITS
;EXIT CPOPJ IF TOO BIG, CPOPJ1 IF OK
;RETURNS T3=RH(T1) WITHOUT GUIDELINE BIT
CHKLIM: HLRZ T2,T1
HRRZ T3,T1
TRZ T3,400000 ;CLEAR LIMIT BIT
CAIG T2,<MXSECN+1>*<HLGPNO+1> ;OK?
CAILE T3,<MXSECN+1>*<HLGPNO+1>
POPJ P, ;NO, NON-SKIP
JUMPE T3,CPOPJ1## ;0 IS ALWAYS OK
CAIL T3,4 ;AT LEAST 4 PAGES?
PJRST CPOPJ1## ;YES, SKIP
TRZ T3,377777 ;CLEAR
TRO T3,4 ;MAKE IT FOUR PAGES
JRST CPOPJ1## ;SKIP RETURN
;NON-PRIVILEGED COMMAND TO SET CURRENT PER-USER LIMITS
SETUVC::SKIPA T1,[POINT 18,.PDMVL##(W),17]
SETUPC::MOVE T1,[POINT 18,.PDMVL##(W),35]
PUSHJ P,SAVE2## ;SAVE AN AC
MOVE P1,T1 ;SAVE POINTER TO MAX VALUE FOR THIS ARG
PUSHJ P,FNDPDB## ;GET PDB LOC
POPJ P, ;NONE-RETURN
MOVE T1,[-2,,[SIXBIT /GUIDEL/
SIXBIT /LIMIT/]]
PUSHJ P,TXTARG##
TDZA P2,P2
MOVE P2,T1
PUSHJ P,CORARG## ;GET THE CORE ARGUMENT
PJRST NOTENF##
ADDI T1,1 ;CONVERT TO PAGES
LSH T1,W2PLSH
PUSHJ P,CHKLIM ;LEGAL?
PJRST COMERA##
LDB T2,P1 ;YES, GET MAX VALUE FOR THIS ARG
CAILE T1,(T2) ;TRYING TO SET IT TOO HIGH?
JRST COMERA## ;YES
HRRI P1,.PDCVL## ;NO, SET TO STORE NEW VALUE
DPB T1,P1 ;SAVE CURRENT LIMIT
TRNN T1,-1 ;SETTING LIMIT/GUIDELINE TO ZERO?
MOVEI P2,0 ;YES, CLEAR LIMIT BIT
TLNN P1,770000 ;PHYSICAL?
DPB P2,[POINT 1,.PDCVL##(W),18]
PJRST CPOPJ1## ;AND TAKE GOOD RETURN
;NON-PRIVILEGED UUO TO SET PER-USER CURRENT LIMITS
SETUV1::HRR M,T2 ;ADR OF ARGUMENT
TLZ M,MXSECN ;(SETUUO IS LOCAL)
PUSHJ P,FLTSX
POPJ P, ;PAGE-FAULT AT NON-UUO LEVEL???!!!
PUSHJ P,GETWDU## ;GET ARGUMENT
PUSHJ P,CHKLIM ;LEGAL?
POPJ P, ;NO, RETURN
MOVE T2,.PDMVL##(W) ;YES, GET MAX LIMIT
HRRZ T4,T2 ;MAKE SURE ARGUMENTS ARE BELOW MAX LIMITS
CAILE T2,<MXSECN+1>*<HLGPNO+1>
HRLI T2,<MXSECN+1>*<HLGPNO+1>
TRO T2,-1 ;PUT LARGE NUMBER IN IRRELEVANT RIGHT-HALF
CAMG T1,T2
CAMLE T3,T4
POPJ P, ;TRYING TO SET THEM TOO BIG
SETUV2: TLNE T1,-1 ;OK, SAVE WHAT HE ASKED FOR
HLLM T1,.PDCVL##(W) ;CVPL
TRNE T1,-1
HRRM T1,.PDCVL##(W) ;CPPL
SKIPN T1 ;IF WHOLE THING ZERO,
MOVEM T1,.PDCVL##(W) ; DO IT ANYWAY
PJRST CPOPJ1##
;ROUTINE TO DETERMINE IF A PAGE EXISTS AND IF SO IF REFERENCING IT
; WILL CAUSE A PAGE FAULT. ENTER T2 = VIRTUAL ADDRESS
; EXIT CPOPJ IF PAGE DOESN'T EXIST
; CPOPJ1 IF PAGE EXISTS BUT IS PAGED OUT OR HAS ACCESS ALLOWED OFF,
; CPOPJ2 IF PAGE EXISTS AND IS IN CORE, OR IS ALLOCATED BUT ZERO
;RETURNS MAP CONTENTS FOR THE ADR IN T4
;PRESERVES T2.
FLTTC:: TLZ T2,-1-MXSECN ;CLEAR ANY POSSIBLE CRUFT
MOVE T4,T2 ;GET ADR
LSH T4,W2PLSH+P2SLSH ;GET SECTION
JUMPE T4,FLTTC1 ;CONTINUE IF S0
PUSH P,T2 ;SAVE T2
PUSHJ P,RSECT4 ;GET REAL SECTION #
JRST T2POPJ## ;SECTION DOESN'T EXIST
POP P,T2 ;RESTORE T2
FLTTC1: MOVE T4,T2 ;GET WORD ADDRESS AGAIN
LSH T4,W2PLSH ;PAGE #
SE1ENT
SKIPN T4,@[IW MS.MAP,UMAPS(T4)] ;GET ENTRY (SECTION EXISTS SO CAN'T FAULT)
POPJ P, ;TOO BAD PAGE DOESN'T
TLNE T4,(<PM.ACD>B2) ;IN CORE?
JRST CPOPJ2## ;YES
TLZ T4,(PM.NAD) ;KEEP ONLY ADDRESS
CAMN T4,[PM.ZER] ;ABZ PAGE?
AOS (P) ;YES, ACCESS ALLOWED IS ON
JRST CPOPJ1## ;DONE
;HERE TO DEPOSIT IN AN ALLOCATED BUT ZERO PAGE
; S = WHAT TO DEPOSIT, JOBEXM = WHERE
CREPAG::PUSHJ P,CLRASA## ;CLEAR JS.ASA IN CASE OF ERROR AND SO USER'S
; ACS WILL GET RESTORED WHEN MONITOR JOB IS STARTED
JUMPL P4,CREPA2 ;IF RUNNING, REQUIRE A CONTROL C
JSP T2,SAVCTX##
;RETURN HERE AT UUO LEVEL
MOVEM S,.JDAT+JOBFDV## ;SAVE WHAT TO DEPOSIT
MOVE T2,.JDAT+JOBEXM## ;WHERE TO DEPOSIT
TLZ T2,400000 ;CLEAR EXAMINE LAST FLAG
MOVEI T3,1 ;NUMBER OF PAGES TO CREATE FOR THE DEPOSIT
PUSHJ P,MAKPGS ;CREATE THE PAGE FOR THE DEPOSIT
JRST CREPA1 ;LOST, PHYSICAL LIMIT IS SET TOO LOW
MOVE T1,.JDAT+JOBFDV## ;WHAT
MOVE T2,.JDAT+JOBEXM## ;WHERE
TLZ T2,400000 ;CLEAR EXAMINE LAST FLAG
EXCTXU <MOVEM T1,(T2)> ;STORE IT AWAY FOR HIM
POPJ P,
CREPA1: PUSHJ P,TTYFUW## ;FIND HIS TTY AND RESTORE J
PUSHJ P,PRQM## ;"?"
MOVEI T1,OUTBMS## ;"OUT OF BOUNDS"
PJRST CONMES## ;PRINT THAT
CREPA2: SKIPGE .JDAT+JOBEXM## ;EXAMINE LAST FLAG ON?
TLO T2,400000 ;YES, SET IT AGAIN
MOVEM T2,.JDAT+JOBEXM## ;STORE WHAT USER TYPED SINCE CAN'T DO IT NOW
MOVEI T1,RUNERR## ;"PLEASE TYPE CONTROL C FIRST"
PJRST ERRMES## ;PRINT THAT AND RETURN TO COMCON
;SUBROUTINE TO RETURN # OF VIRTUAL PAGES ALLOCATED TO A USER'S JOB
;CALL WITH:
; UBR SETUP TO USER PAGE MAP PAGE
; MOVEI J,JOB #
; PUSHJ P,VMSIZE
; RETURNS HERE WITH LOWSEG SIZE IN T1 AND HISEG SIZE IN T2
;
; JOB'S UPMP IS IN CORE WHEN VMSIZE IS CALLED. LOWSEG SIZE
; INCLUDES THE JOB'S PAGE MAP PAGE.
;
VMSIZE::SETZB T1,T2 ;ASSUME USER DID CORE 0
SKIPN JBTADR##(J) ;ANY CORE ASSIGNED?
POPJ P, ;NO, RETURN ZEROS
PUSHJ P,LOSIZ ;GET THE LOW SEG SIZE
MOVEI T1,UPMPSZ##(T3) ; +1 FOR UPMP
ADD T1,.USMEM ; + NO OF NON-CONTIGUOUS PAGES
HRRZ T3,JBTSGN##(J) ;ANY HIGH SEGS?
JUMPE T3,CPOPJ## ;DONE IF NONE
PUSH P,T2 ;SAVE SUM(HIGH SEG SIZE)
VMSIZ1: HRRZ T2,.HBSGN(T3) ;GET SEGMENT # OR SIZE IF SPY SEG
SKIPLE .HBSGN(T3) ;SPY SEG?
HLRZ T2,JBTADR##(T2) ;NO, GET SIZE FROM JBTADR
AOS T2 ;CONVERT TO
LSH T2,W2PLSH ;PAGES
ADDM T2,(P) ;ADD IN
HRRZ T3,.HBLNK(T3) ;NEXT SEGMENT
JUMPN T3,VMSIZ1 ;LOOP
JRST T2POPJ## ;RETURN
;SUBROUTINE TO COMPUTE THE LOW SEG SIZE
;ENTER J=JOB NUMBER
;EXIT T3= LOW SEG SIZE IN PAGES
;PRESERVES ALL ACS (EXCEPT T3)
;CALL HISIZ TO COMPUTE HI SEG SIZE, ALWAYS RETURNS CPOPJ1
HISIZ: HLRZ T3,JBTADR##(J) ;USE JBTADR
AOS T3 ;ROUND UP
LSH T3,W2PLSH ;MAKE PAGES
JRST CPOPJ1## ;AND RETURN
LOSIZ: SKIPN T3,.USREL ;VIRTUAL?
HLRZ T3,JBTADR##(J) ;NO, USE JBTADR
ADDI T3,1
LSH T3,W2PLSH ;CONVERT TO PAGES
ADD T3,.USNCR ;ADD # OF NZS PAGES
POPJ P, ;AND RETURN
SUBTTL ERRCON ERROR HANDLING MODULE
;SUBROUTINE TO COMPUTE A VIRTUAL PAGE NUMBER WITHIN A JOB'S
; ADDRESS SPACE BASED ON AN ABSOLUTE PAGE NUMBER KNOWN TO BE IN THE
; JOB'S MAP
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER
; MOVE T3,PHYSICAL PAGE NUMBER TO BE USED IN VIRTUAL PAGE CALCULATION
; MAKE THE JOB'S MAP ADDRESSABLE
; PUSHJ P,PHYPVP ;CONVERT PHYSICAL PAGE NUMBER TO VIRTUAL PAGE NUMBER
;ALWAYS RETURNS POPJ,T1=VIRTUAL PAGE NUMBER WITHIN THE
; LOW SEGMENT OR RELATIVE PAGE NUMBER WITHIN HIGH SEGMENT
PHYPVP::SE1ENT ;TO TOUCH MAPS
SETZB T1,T4 ;START AT VIRTUAL PAGE 0
PUSHJ P,GMPTR ;GET A BYTE POINTER TO THE MAP
PHYPV1: MOVE T2,(T4) ;GET MAP CONTENTS
AOS T4 ;INCREMENT
TLZ T2,(PM.NAD) ;KEEP ONLY PAGE #
CAME T3,T2 ;IS THIS THE ABSOLUTE PAGE IN QUESTION?
AOJA T1,PHYPV1 ;NO, LOOK AT THE NEXT PAGE IN THE MAP
PUSHJ P,TSWST ;IN THE WORKING SET?
CAIA ;NO, SEE IF IN THE HIGH SEG
POPJ P, ;IT'S IN THE WORKING SET
PUSH P,T1 ;SAVE T1
PUSHJ P,TPNHX ;YES, IS THIS PAGE IN THE HIGH SEGMENT?
SKIPA J,.HBSGN(T2) ;YES, GET HIGH SEGMENT NUMBER
AOJA P1,[POP P,T1 ;RESTORE T1
JRST PHYPV1]
POP P,T1
LDB T2,JBYHSO## ;GET ORIGIN PAGE OF THE HIGH SEGMENT
SUBI T1,(T2) ;COMPUTE RELATIVE PAGE WITHIN HIGH SEGMENT
POPJ P, ; AND RETURN
SUBTTL CORE1 INTERFACE WITH THE CORE ROUTINES
;SUBROUTINE TO TURN ON BITS IN WSBTAB WHEN A JOB IS EXPANDING
;ENTER T1=HIGHEST RELATIVE PAGE DESIRED
;PRESERVES T1
CLRWS:: PUSHJ P,SAVE2## ;SAVE P1 & P2
MOVSI P1,(ANDCAM T1,(T4)) ;SET ARGUMENT FOR ADJWS1
JRST ADJWS1 ;CLEAR BITS IN WSBTAB
..UPMN==<.UPMAP-FYSORG>/PAGSIZ+^D512 ;BIT NUMBER OF .UPMAP IN WSBTAB
..UPTN==<.UPMP-FYSORG>/PAGSIZ+^D512 ;BIT NUMBER OF .UPMP IN WSBTAB
..UPMI==..UPMN/^D36 ;INDEX IN WSBTAB OF BIT FOR .UPMAP
..UPTI==..UPTN/^D36 ;INDEX IN WSBTAB OF BIT FOR .UPMP
..UPMB==1B0_<<..UPMI*^D36>-..UPMN> ;THE BIT IN THE WORD
..UPTB==1B0_<<..UPTI*^D36>-..UPTN> ;THE BIT IN THE WORD
ADJWS:: PUSHJ P,SAVE2## ;SAVE P1 & P2
MOVSI P1,(IORM T1,(T4)) ;SET ARG FOR ADJWS1
IFE ..UPMI-..UPTI,< ;IF BOTH BITS IN SAME WSBTAB WORD
MOVE T3,[..UPMB!..UPTB] ;GET THE BITS
IORM T3,WSBTAB+..UPMI ;MAKE SURE BITS FOR UPM AND UPT ON IN WSBTAB
>; END IFE
IFN ..UPMI-..UPTI,< ;IF BITS IN DIFFERENT WSBTAB WORDS
MOVE T3,[..UPMB] ;GET UPM BIT
IORM T3,WSBTAB+..UPMI ;SET IT
MOVE T3,[..UPTB] ;GET UPT BIT
IORM T3,WSBTAB+..UPTI ;SET IT
>; END IFN
ADJWS1: PUSHJ P,SAVT##
MOVEI T3,(T1) ;GET ARG SET
ANDI T3,HLGPNO ;ONLY KEEP PAGE NUMBER
ADJWS2: MOVEI P2,MXSECN_S2PLSH ;ISOLATE SECTION #
AND P2,T1
LSH P2,P2SLSH
ADJWS3: SKIPGE .USBTS ;NOT A BIG USER
SKIPN T4,P2 ;SECTION BEING DONE
SKIPA T4,[WSBTAB-.WSBNZ+WSBTBL]
IMULI T4,WSBTBL
ADDI T4,.WSBNZ-WSBTBL
DOBIT: MOVEI T1,^D36 ;SET UP FIRST PART OF MASK
PUSHJ P,BITMSK##
DOBIT1: XCT P1 ;SET OR CLEAR BITS
JUMPLE T3,DOBIT2 ;GO IF THROUGH
PUSHJ P,BITMS2## ;SET MASK FOR NEXT PART
JRST DOBIT1 ;AND CONTINUE
DOBIT2: SOSGE T1,P2 ;ANOTHER SECTION TO DO?
POPJ P, ;NO, DONE
SKIPN .UPMP+SECTAB(T1);SECTION EXIST?
JRST DOBIT2 ;NO, KEEP LOOKING (SEC 0 MUST EXIST FOR NOW)
MOVEI T3,HLGPNO ;DO ALL PAGES IN PRECEDING SECTIONS
JRST ADJWS3
;SUBROUTINE TO COMPUTE THE TOTAL VIRTUAL SIZE OF A JOB
;ENTER WITH JOB ADDRESSABLE
;EXIT T2= JOB SIZE IN PAGES (EXCLUDES UPMP SIZE)
;PRESERVES ALL ACS BUT T2
VRTSZ: PUSH P,J ;SAVE J
MOVE J,.USJOB ;JOB NUMBER
SKIPN T2,.USREL ;NON-CONTIGUOUS?
HLRZ T2,JBTADR##(J) ;NO, GET JBTADR
PUSH P,T1 ;SAVE T1
PUSHJ P,FNSPCS## ;FIND SEGMENT
JRST VRTSZ1 ;ONLY SHARABLE OR SPY
HRRZS J ;CLEAR JUNK
HLRZ T1,JBTADR##(J) ;YES, GET ITS SIZE
ADD T2,T1 ;LOW+HIGH SIZES
VRTSZ1: POP P,T1 ;RESTORE T1
LSH T2,W2PLSH
ADD T2,.USNCR ;AND NZS PAGES
ADD T2,.USMEM ;+NO OF NON-CONTIG PAGES
AOJA T2,JPOPJ## ;AND RETURN
;SUBROUTINE CALLED BY CORE1 ON A CORE UUO/COMMAND
;ALLOCATES SPACE (ALLOCATED BUT ZERO) IF A JOB IS ALREADY VIRTUAL
; OR IS GOING VIRTUAL BY THIS CORE OPERATION
;ENTER T3=AMOUNT OF INCREASE -1 ; T1=NEW HIGHEST ADDRESS
;EXIT CPOPJ IF ASKING FOR TOO MUCH
;EXIT CPOPJ1 IF ALLOCATED ON DSK
;EXIT CPOPJ2 OTHERWISE, T1=HIGHEST ADR, T3=AMOUNT OF INCREASE-1
VIRCHK::CAIG J,JOBMAX## ;LOW SEGS MUST CALL KISER TO
JUMPE R,CPOPJ2## ; GET INITIAL CORE (GETMIN)
TLNE J,SHRSEG ;A SHARABLE HIGH SEGMENT?
JRST CPOPJ2## ;YES, LET KISER HANDLE CORE ALLOCATION
PUSHJ P,UUOLVL## ;UUO LEVEL?
TDZA T3,T3 ;NO, MUST BE SECTION 0 THEN
XSFM T3 ;GET THE SECTION #
ANDI T3,MXSECN ;KEEP ONLY SECTION #
PUSHJ P,GETREL ;GET LOGICAL .USREL
MOVE T4,T1 ;HIGHEST ADDRESS REQUESTED
SUB T4,T2 ;MINUS CURRENT HIGHEST ADDRESS
JUMPLE T4,VIRCH9 ;DEALLOCATING
LSH T4,W2PLSH ;CONVERT TO NUMBER OF PAGES OF INCREASE
DMOVEM T1,.USTMP ;SAVE REQUESTED SIZE, CURRENT SIZE
CAIG J,JOBMAX## ;A HIGH SEGMENT?
JRST VIRCH1 ;NO
MOVE T1,J ;PUT SEGMENT # IN T1
PUSH P,T1 ;SAVE IT
MOVE J,.USJOB ;GET CURRENT JOB #
PUSHJ P,FNDHSB## ;GET HIGH SEG DATA BLOCK
XCT NSS## ;NOT FOUND
PUSHJ P,HSVAD## ;COMPUTE THE EXTENT OF THE HIGH SEGMENT
POP P,J ;RESTORE HIGH SEGMENT #
DMOVEM T1,.USTMP+3 ;SAVE VALUES FROM HSVAD
MOVE T1,T2 ;UVA OF HIGH SEGMENT
ADD T1,.USTMP ;CURRENT HIGEST ADDRESS IN THE HIGH SEGMENT
ADD T2,.USTMP+1
VIRCH1: CAMG T4,VIRTAL## ;IS ENOUGH SWAPPING SPACE AVAILABLE?
PUSHJ P,CKNZ1 ; AND ARE ALL PAGES REQUESTED NOT IN-USE?
POPJ P, ;NO, ERROR RETURN
MOVE T1,.USTMP ;RESTORE THE HIGEST ADDRESS REQUESTED
MOVEM T4,.USTMP ;SAVE THE NUMBER OF PAGES OF INCREASE
CAIG J,JOBMAX## ;A HIGH SEGMENT?
PUSHJ P,FNDPDS## ;NO, FIND THE PDB FOR THIS JOB
PUSHJ P,GSIZT ;DOES IT FIT (PHSYCIALLY, VIRTUALY, NOT AT ALL)?
JRST VIRCH2 ;MAYBE VIRTUALLY
SKIPGE P1 ;VIRTUALLY IF NOT PHYSICAL ONLY
JRST VIRCH3 ;PHYSICALLY
;HERE IF JOB ALREADY VIRTUAL OR HAS TO GO VIRTUAL
VIRCH2: JUMPL P1,CPOPJ## ;PHYSICAL-ONLY IF P1 NEGATIVE
PUSH P,T3 ;SAVE SECTION #
JRST VIRCH5 ;NO, LOW SEG VIRTUAL CORE
;HERE IF CAN GET PHYSICAL CORE
VIRCH3: PUSH P,T3 ;SAVE SECTION #
CAIG J,JOBMAX## ;HIGH SEG?
JRST VIRCH4 ;NO
SKIPN T2,.USTMP+3 ;(T1 STORED FROM PREV CALL TO HSVAD)
MOVE T2,.USTMP+4 ;IF ZERO (T2 STORED FROM PREV CALL TO HSVAD)
ADD T1,.USTMP+4 ;HIGHEST PAGE DESIRED
TRO T1,PG.BDY ;WORD ADDRESS
VIRCH4: TDZA T3,T3 ;CLEAR
VIRCH5: MOVSI T3,(PG.SLO) ;ON DISK
SUBI T1,(T2) ;# OF PAGES TO EFFECT
SKIPN R ;IF CREATING FROM NOTHING,
AOSA T1 ;INCLUDE 0TH PAGE
AOS T2 ;ELSE START AT FIRST NON-EX PAGE
LSHC T1,W2PLSH ;CONVERT TO PAGES
HLL T2,T3
POP P,T3 ;SECTION #
LSH T3,S2PLSH ;CONVERT TO PAGE #
IORI T2,(T3) ;REAL PAGE TO CREAT AND REMAP
MOVNM T1,.JDAT+JOBUAL##
MOVEM T2,.JDAT+JOBUAL##+1
SETZM .JDAT+JOBUAL##+6 ;NO SECOND UUO
CAIG J,JOBMAX## ;LOW SEG?
JRST VIRC14 ;DO THE UUOS
;HERE TO SET UP THE REMAP FOR A NON-SHARABLE HIGH SEG
HRRZM T2,.JDAT+JOBUAL##+4 ;SOURCE PAGE
HRRZM T2,.JDAT+JOBUAL##+5 ;NEW HS ORIGIN (APPEND)=IN PLACE
MOVNM T1,.JDAT+JOBUAL##+3 ;(NEGATIVE INDICATES APPEND)
MOVEI T1,3 ;# OF ARGS
MOVEM T1,.JDAT+JOBUAL##+2 ;SET IN ARG BLOCK
MOVE T1,[.PAGRM,,JOBUAL##+2] ;SET ARG POINTER
MOVEM T1,.JDAT+JOBUAL##+6
JRST VIRC19
;HERE TO DEALLOCATE STORAGE
VIRCH9: CAIG J,JOBMAX## ;JOB?
JRST VIRC10 ;YES, DO AS LOW SEG STUFF
ASH T4,W2PLSH ;CONVERT TO PAGES
JUMPE T4,VIRC18 ;NOTHING TO DO
MOVNM T4,.JDAT+JOBUAL+3 ;SET # OF PAGES TO DELETE FROM HS
MOVE T1,J ;SEG # TO T1
PUSH P,J ;SAVE J
MOVE J,.USJOB ;POINT J AT JOB
PUSHJ P,FNDHSB## ;FIND SEGMENT
JRST JPOPJ## ;?
LDB T1,[PSG2LH+.HBSG2(T1)] ;SECTION HIGH SEG IS IN
TRO T1,(PG.GAF) ;SPECIFY WE KNOW SECTION
HRLM T1,.JDAT+JOBUAL+3 ;SET SECTION
POP P,J ;RESTORE J
MOVEI T4,1
MOVEM T4,.JDAT+JOBUAL+2 ;# OF ARGS
MOVE T1,[.PAGRM,,JOBUAL##+2]
MOVEM T1,.JDAT+JOBUAL##+6
SETZM .JDAT+JOBUAL##
JRST VIRC19
;HERE TO DEALLOCATE FROM LOW SEG WITH PAGE UUOS
VIRC10: MOVEM T2,.USTMP ;SAVE ".USREL"
ADJSP P,2 ;ALLOCATE SPACE FOR HSBS
SSXE T1,(T3) ;SET PCS SECTION
LSH T1,W2PLSH ;NEW HIGHEST DESIRED PAGE
AOS T1 ;FIRST PAGE DON'T WANT
HRLI T1,(PG.IDC!PG.GAF)
MOVEM T1,.JDAT+JOBUAL+1 ;SET WHERE TO START
PUSH P,T3 ;SAVE T3
MOVSS T3 ;SECTION #
PUSH P,J ;SAVE J
PUSHJ P,GTRSGN## ;IN THIS SECTION
JRST VIRC11 ;ONLY SPY SEGS
JUMPE J,VIRC11 ;NO SEG RELEVANT
TLZ J,-1^!SPYSEG ;CLEAR ALL BUT SPYSEG (IFIW)
SKIPL J ;SPY SEG?
SKIPA T2,JBYHSO## ;NO, GET ORIGIN FROM JBTUPM
MOVE T2,[PSPOLH+.HBSPO(T1)]
LDB T2,T2 ;GET ORIGIN
MOVEM T1,-2(P) ;SAVE FIRST HIGH SEG BLOCK ADDR
MOVEI T3,-1 ;GET HIGHEST SEGMENT IN ADDRESS SPACE
HRL T3,-1(P) ;SECTION #
MOVE J,.USJOB ;JOB #
PUSH P,T2 ;SAVE ORIGIN OF FIRST SEG
PUSHJ P,GTRSGN## ;GET HIGHEST SEGMENT IN SECTION
JFCL ;DON'T CARE
POP P,T2 ;RESTORE T2
JUMPL J,[LDB T4,[PSPOLH+.HBSPO(T1)] ;GET ORIGIN
JRST VIRCH6] ;PROCEED
HRRZS J ;GET PARAMETERS FROM HIGH SEG DATA BASE
LDB T4,JBYHSO## ;ORIGIN
HLRZ J,JBTADR##(J)
VIRCH6: LSH J,W2PLSH ;CONVERT TO HIGHEST PAGE
ADDI T4,1(J) ;FIRST PAGE NOT IN HS
MOVEM T1,-3(P) ;SAVE HIGHEST HSB ADDR
POP P,J ;RESTORE J
POP P,T1 ;AND SECTION
MOVE T3,T1 ;SECTION
PUSHJ P,GETADR ;GET JBTADR FOR SECTION
CAMN T3,.USTMP ;IS ".USREL" EQUAL TO "JBTADR" FOR SECTION?
JRST VIRCH7 ;YES, JUST DELETE TO HIGH SEG
AOS T3 ;CONVERT TO PAGE
LSH T3,W2PLSH
CAIGE T3,(T4) ;IS IT ABOVE HIGH SEG?
JRST VIRC12 ;NO
SUBI T3,-1(T4)
MOVNS T3 ;RIGHT SIGN (NEGATIVE)
HRLI T4,(PG.GAF!PG.IDC) ;RIGHT FUNCTION
LSH T1,S2PLSH ;CONVERT TO PAGE
IORI T4,(T1) ;SET SECTION IN PAGE #
DMOVEM T3,.JDAT+JOBUAL##+2 ;MUST DELETE THOSE TOO
MOVE T3,[.PAGCD,,JOBUAL##+2] ;SET SECOND UUO ARG POINTER
MOVEM T3,.JDAT+JOBUAL##+6
JRST VIRC13 ;CONTINUE
;HERE IF NO HI SEG TO WORRY ABOUT
VIRC11: POP P,J ;RESTORE J
POP P,T1
MOVE T3,T1 ;SECTION
PUSHJ P,GETADR ;GET JBTADR FOR SECTION
AOS T2,T3 ;GET THOSE OFF-BY-ONES
LSH T2,W2PLSH ;CONVERT TO PAGES
VIRCH7: SETZM (P) ;DON'T HAVE TO DO ANOTHER SET OF UUOS
LSH T1,S2PLSH ;CONVERT TO PAGE
VIRC12: SETZM .JDAT+JOBUAL##+6 ;NO SECOND PAGE UUO
VIRC13: IORI T2,(T1) ;SET SECTION #
HRRZ T3,.JDAT+JOBUAL##+1 ;BASE PAGE
SUBI T2,(T3) ;# OF PAGES TO DELETE
VIRC35: MOVNM T2,.JDAT+JOBUAL##
PUSH P,T1 ;SAVE SECTION PAGE ADDRESS
PUSHJ P,VIRC14 ;DO THE FIRST SET OF UUOS
JRST [ADJSP P,-3 ;FIX STACK
POPJ P,] ;RETURN
POP P,T3 ;RESTORE SECTION (PAGE)
VIRC31: POP P,T1 ;FIRST HSB
SKIPE T1 ;ANY TO DO AT ALL?
CAMN T1,(P) ;OR ONLY ONE HIGH SEG?
JRST TPOPJ1## ;ONE OR LESS HIGH SEGS
PUSHJ P,HSVAD## ;GET ADDRESS LIMITATIONS OF HIGH SEG
AOS T4,T1 ;FIRST ADDRESS NOT IN THIS HIGH SEG
LSH T4,W2PLSH ;CONVERT TO PAGE
TLO T4,(PG.GAF!PG.IDC) ;TURN ON DELETE AND IDC
IORI T4,(T3) ;PUT IN SECTION
LSH T3,P2SLSH ;CONVERT TO SECTION
MOVEM T4,.JDAT+JOBUAL##+1 ;SET FIRST PAGE TO DELETE
PUSHJ P,GTNSGN## ;GET NEXT HIGH SEG ABOVE THIS
PUSH P,T1 ;SAVE THE HSB ADDR
PUSHJ P,HSVAD## ;GET ADDRESS LIMITATIONS OF THIS SEG
LSH T2,W2PLSH ;FIRST PAGE OF THIS HIGH SEG
HRRZ T4,.JDAT+JOBUAL##+1 ;GET STARTING PAGE TO DELETE AT
LSH T3,S2PLSH ;CONVERT TO SECTION
IORI T2,(T3) ;PUT IN SECTION
SUBI T2,(T4) ;# OF PAGES TO DELETE
JUMPE T2,VIRC31 ;NOTHING TO DO
MOVNM T2,.JDAT+JOBUAL## ;SET # OF PAGES TO DO
VIRC32: POP P,T4 ;GET HSB
CAMN T4,(P) ;IS THIS THE HIGHEST SEGMENT?
JRST [SETZM .JDAT+JOBUAL##+6 ;NO SECOND UUO
ADJSP P,-1 ;FIX STACK
PJRST VIRC14] ;EXIT
AOS T4,T1 ;FIRST PAGE NOT IN THIS HIGH SEG
TLO T4,(PG.GAF!PG.IDC)
IORI T4,(T3) ;PUT IN SECTION
MOVEM T4,.JDAT+JOBUAL##+2
LSH T3,P2SLSH ;CONVERT TO SECTION AGAIN
PUSHJ P,GTNSGN## ;NEXT HIGH SEG ADDRESS-WISE IN THIS SECTION
PUSH P,T1 ;SAVE HSB ADDR
PUSHJ P,HSVAD## ;GET LIMITS OF HIGH SEG
LSH T2,W2PLSH ;FIRST PAGE OF THIS HIGH SEG
HRRZ T4,.JDAT+JOBUAL##+2 ;LAST PAGE OF PREVIOUS
LSH T3,S2PLSH ;BACK TO PAGE
IORI T2,(T3) ;PUT IN SECTION
SUBI T2,(T4) ;# OF PAGES TO DELETE
JUMPE T2,VIRC32 ;SKIP TO NEXT HIGH SEG
MOVE T1,T3 ;SECTION (PAGE)
JRST VIRC35
;HERE TO ALLOCATE OR DEALLOCATE CORE VIA PAGE UUO (LOW SEG)
VIRC14: MOVE R,JBTADR##(J)
SKIPN .JDAT+JOBUAL## ;ANYTHING AT ALL TO DO?
SKIPE .JDAT+JOBUAL##+6;?
CAIA ;YES
JRST VIRC18
SETZ T1,
PUSHJ P,SVPCS## ;JOBUAL IS IN S0
IFN FTMP,<
PUSHJ P,INTLVL## ;INTERRUPT LEVEL?
PUSHJ P,REMMM## ;NO, GIVE UP THE MM
>
MOVEI T2,JS.ASA
TDNE T2,JBTSTS##(J) ;SHADOW ACS?
SKIPA T2,[EXCH T1,.JDAT+0] ;YES, USE AC 0 THERE
MOVE T2,[EXCTUU <EXCH T1,0>] ;ELSE USE USER AC 0
SKIPN .JDAT+JOBUAL## ;ANYTHING TO DO IN FIRST UUO?
SKIPA T1,.JDAT+JOBUAL##+6 ;NO, MUST BE IN SECOND THEN
MOVE T1,[.PAGCD,,JOBUAL##] ;YES, WHERE ARG IS
XCT T2 ;STORE
PUSH P,M ;SAVE M
PUSH P,T1 ;USER'S AC 0
PUSH P,T2 ;AND INSTRUCTION TO PUT IT BACK
SKIPN .JDAT+JOBUAL## ;ANY FIRST UUO TO DO?
JRST VIRC15 ;NO, JUST DO SECOND THEN
MOVE T1,[.PAGCD,,JOBUAL##]
SETZ M, ;ARG LIST POINTER
PUSHJ P,UPAGE. ;DO THE UUO
JRST VIRC17 ;OH WELL
SKIPN T1,.JDAT+JOBUAL##+6 ;SECOND UUO TO DO?
JRST VIRC16 ;NO, JUST SUCCEED THEN
XCT (P) ;SET UP USER AC
VIRC15: SETZ M,
MOVE T1,.JDAT+JOBUAL##+6 ;ARG POINTER
PUSHJ P,UPAGE. ;DO IT
CAIA ;OOPS
VIRC16: AOS -3(P)
VIRC17: POP P,T2 ;INSTR
POP P,T1 ;USER AC 0
POP P,M
XCT T2
SKIPA R,JBTADR##(J)
VIRC18: SKIPA R,JBTADR##(J)
POPJ P,
AOS (P)
POPJ P,
;HERE FOR HIGH SEGMENT STUFF - PRESERVE J AS HIGH SEG #+BITS
VIRC19: PUSH P,J ;SAVE J
MOVE J,.USJOB
VIRC20: PUSHJ P,VIRC14
CAIA
AOS -1(P)
POP P,J ;RESTORE J
MOVE R,JBTADR##(J)
POPJ P,
;SUBROUTINE TO COMPUTE .USREL (JBTADR) FOR SEGMENT IN J BASED
;ON SECTION NUMBER IN T3 (IF LOW SEG). R IS ASSUMED SET UP FOR
;JOB OR SEGMENT (SECTION 0)
GETREL: EXCH T3,T4 ;SAVE T4, PUT SECTION # IN T4
PUSHJ P,RSECT4 ;GET SECTION #
JFCL ;CATCH NON-EX SECTION LATER
EXCH T3,T4 ;RESTORE T4 AND PUT SECTION IN T3
CAIG J,JOBMAX## ;IS THIS A HIGH SEG?
SKIPN T2,.USREL ;NO, IS S0 LOW SEG CONTIGUOUS?
HLRZ T2,R ;HIGH SEG OR CONTINGUOUS S0 SPACE
JUMPE T3,CPOPJ## ;IF SECTION 0, DONE
CAIG J,JOBMAX## ;AGAIN, WAS IT LOW SEG?
SKIPN T2,.UPMP+SECTAB(T3) ;DOES SECTION EXIST?
POPJ P, ;NO, AVOID IME AND RETURN HIGHEST ADDR AS 0
HRRZ T2,T3 ;GET SECTION #
LSH T2,S2PLSH ;CONVERT TO PAGE #
SE1ENT ;MUST ENTER SECTION 1 TO REFERENCE MAPS
GETRL1: SKIPE @[IW MS.MAP,UMAPS(T2)] ;DOES THIS ENTRY EXIST?
AOSA T2 ;YES, STEP TO NEXT
JRST GETRL3 ;ENTRY DOESN'T EXIST, STEP BACK
TRNE T2,HLGPNO ;WANDER OFF THE END OF THE SECTION?
JRST GETRL1 ;NO, CHECK NEXT ENTRY
GETRL3: LSH T2,P2WLSH ;CONVERT TO FIRST NON-EX WORD
HRRZS T2 ;CLEAR SECTION
SOJA T2,CPOPJ## ;CONVERT TO HIGHEST ADDR AND RETURN
;SUBROUTINE TO RETURN JBTADR (LH) IN T3. INPUT IS SECTION # IN T3
;ASSUMES R, J SET UP FOR SECTION 0
GETADR: PUSH P,T2 ;SAVE T2
EXCH T3,T4 ;SAVE T4 & PUT SECTION # THERE
PUSHJ P,RSECT4 ;RESOLVE SECTION
JFCL ;DON'T CARE NOW
EXCH T4,T3 ;RESTORE T4, PUT SECTION IN T3
POP P,T2 ;OK TO RETORE T2 NOW
SKIPN .UPMP+SECTAB(T3) ;SECTION EXIST?
POPJ P, ;NO, HIGHEST ADDR IS 0
JUMPN T3,GETAD1 ;SECTION 0?
HLRZ T3,R ;YES, GET IT FROM R
POPJ P,
GETAD1: SE1ENT ;NEED TO BE IN S1 TO ACCESS MAPS
PUSH P,T1 ;SAVE T1
MOVE T1,T3 ;SECTION #
LSH T1,S2PLSH ;CONVERT TO PAGE #
TRO T1,HLGPNO ;HIGHEST POSSIBLE PAGE IN SECTION
GETAD2: SKIPE @[IW MS.MAP,UMAPS(T1)] ;PAGE EXIST?
PUSHJ P,TPNHS ;HIGH SEG PAGE?
TRNN T1,HLGPNO ; HS OR NX - FALLING OFF BOTTOM OF SECTION
SKIPA T3,T1 ;PUT HIGHEST EXISTENT PAGE IN T1
SOJA T1,GETAD2 ;CHECK PREVIOUS PAGE
LSH T3,P2WLSH ;CONVERT TO WORD ADDR
HRRZS T3 ;GET ONLY SECTION RELATIVE PORTION
SKIPE @[IW MS.MAP,UMAPS(T1)] ;IF PAGE DIDN'T EXIST
PUSHJ P,TPNHS ;OR WAS PART OF HIGH SEG
JRST TPOPJ## ;THEN DON'T PUT IN PG.BDY
TRO T3,PG.BDY ;HIGHEST ADDRESS IN SECTION
JRST TPOPJ## ;RESTORE T1 AND RETURN
;SUBROUTINE TO SET UP .UPVRT ACCORDING TO THE PAGE INVOLVED
;ENTER J=LOW SEG NUMBER, T1=PAGE
JSTVRT::PUSHJ P,TPAHS ;HIGH-SEG PAGE?
SKIPG T2,.HBSGN(T2) ;YES, IS THERE A HIGH SEG? (SHOULD SKIP)
PJRST SETVRT ;LOW SEG- CALL SETVRT
PUSH P,J ;HIGH SEG - SAVE J
MOVE J,T2 ;SET J TO HI SEG NUMBER
PUSHJ P,SETVRT ;CALL SETVRT
PJRST JPOPJ## ;RESTORE J AND RETURN
;SUBROUTINE TO SET UP .UPVRT
;ENTER J=SEGMENT NUMBER
SETVRT: PUSHJ P,SEGSIZ## ;GET PHYSICAL SIZE OF THIS SEG
CAIG J,JOBMAX##
JRST STVRT1
LDB T1,PCORSZ##
MOVSI T3,(HRROS)
JRST STVRT3
STVRT1: SKIPN T1,.USREL ;NUMBER OF CONTIGUOUS PAGES
HLRZ T1,R ;IF .UPREL = 0, ALL PAGES ARE CONTIGUOUS
LSH T1,W2PLSH ;CONVERT TO NUMBER OF PAGES
ADD T1,.USMEM ;TOTAL NUMBER OF PAGES, BOTH PHYSICAL AND VIRTUAL
ADD T1,.USNCR ;IN-CORE NZS PAGES
ADDI T1,UPMPSZ## ;LOW SEG, ACCOUNT FOR UPMP
STVRT2: MOVSI T3,(HLLOS) ;WORK WITH RH(UPVRT)
STVRT3: SKIPE R
CAIN T2,1(T1) ;PHYS SIZE = VIRTUAL SIZE?
TLC T3,30000 ;YES, CONVERT HXXOS TO HXXZS
HRRI T3,.USVRT
MOVE T1,.USVRT ;SAVE CURRENT UPVRT
TRZ T1,777 ;CLEAR .UPANA BITS FROM .UPVRT
XCT T3 ;SET/CLEAR HALF OF .UPVRT
SKIPE T3,.USANA ;ANY ANA PAGES?
MOVEI T3,777 ;YES, SET THAT PART OF .USVRT
DPB T3,[POINT 9,.USVRT,35]
MOVEI T2,UP.NVS ;NOT VIRTUAL WHEN SWAPPED BIT
SKIPN .USWLP ;IF .UPWLP WENT TO ZERO,
ANDCAM T2,.USBTS ;CLEAR THE BIT
MOVE T3,.USVRT ;GET CURRENT VALUE OF .USVRT
TRZ T3,777
SKIPE T3 ;IF .UPVRT DIDN'T CHANGE
JUMPN T1,STVSIZ ; FROM 0 TO NON-0 OR VICE-VERSA
SKIPN T3
JUMPE T1,STVSIZ ;RETURN
PUSHJ P,VRTSZ ;YES, GET CURRENT TOTAL VIRT SIZE OF JOB
SKIPE T3 ;IF WENT FROM 0 TI NON-0
MOVNS T2 ; DECREASE VMCMAX
ADDM T2,VMCMAX## ;INCR/DECR VMCMAX
MOVNS T2
ADDM T2,VMTOTL##
STVSIZ::PUSH P,J
MOVE J,.USJOB
PUSHJ P,VMSIZE
CAIE T1,0 ;"CORE 0?"
SUBI T1,UPMPSZ## ;NO, DISCOUNT UPMPSZ
DPB T2,HIVSIZ## ;STORE NEW HIGH SEGMENT SIZE
DPB T1,LOVSIZ## ;AND LOW SEGMENT SIZE
JRST JPOPJ## ;AND RETURN
;SUBROUTINE TO ENSURE THAT THERE ARE NO MAP ENTRIES
;ENTER T1=NEW HIGHEST ADR, T2=CURRENT HIGHEST ADR
;EXITS CPOPJ IF SOME PAGE EXISTS IN THE RANGE, CPOPJ1 IF OK
;PRESERVES ALL ACS
;NOTE THAT THIS ROUTINE CANT BE CALLED FOR STARTING ADR AT PAGE 0
CKNZ1:: PUSHJ P,SAVT## ;SAVE T1-T4
ADDI T1,1 ;CONVERT TO HIGHEST PAGE
ADDI T2,1 ; ..
TRZ T1,PG.BDY ;DON'T SHIFT JUNK TO LH(T2)
LSHC T1,W2PLSH ; ..
JRST CKNZ2 ;CHECK THAT RANGE OF PAGES
;ENTER HERE IF THE ARGS ARE IN PAGES
CKNZP:: PUSHJ P,SAVT## ;SAVE T1-T4
CKNZ2: PUSHJ P,SAVE1## ;SAVE A P
SE1ENT
MOVEI T4,-1(T2) ;STARTING PAGE NUMBER - 1 FOR ILDB
SUB T1,T2 ;NUMBER OF PAGES TO CHECK
CKNZ3: EXCH T1,T4 ;REQUIRED FOR NZS MAPPING ROUTINES
MOVE T3,T2 ;SAVE ORIGINAL STARTING PAGE IN T3
LSHC T1,P2SLSH ;GET SECTION #
CKNZ4: CAILE T1,MXSECN
STOPCD .,STOP,EMS ;++EXCEEDING MAXIMUM SECTION
SKIPE .UPMP+SECTAB(T1) ;DOES SECTION EXIST?
JRST [MOVE P1,T1
JRST CKNZ5] ;YES, MAP IT AND START
ANDI T3,HLGPNO ;SAVE ONLY PAGE #
SUBI T3,HLGPNO ;# OF PAGES TO THE BOUNDARY
ADD T4,T3 ;THAT MANY PAGES LESS TO CHECK
JUMPLE T4,CPOPJ1## ;DONE
SETZB T3,T2 ;STARTING AT PAGE 0 OF NEW SECTION
AOJA T1,CKNZ4 ;LOOK AGAIN
CKNZ5: LSHC T1,S2PLSH ;RESTORE STARTING PAGE #
EXCH T1,T4 ;AND SET ACS UP AGAIN
PUSHJ P,GMPTR ;GET A BYTE POINTER TO THE MAP
CKNZ6: AOS T4
MOVE T2,(T4) ;GET CONTENTS OF MAP SLOT
JUMPN T2,CPOPJ## ;LOSE IF NON-ZERO
TRC T4,PG.BDY ;ABOUT TO GO OVER SECTION BOUNDARY?
TRCN T4,PG.BDY ;(EASIER TO TEST ZEROES)
JRST [SOJLE T1,CPOPJ1## ;NOTHING TO CHECK ANYWAY
SETZB T3,T2 ;YES, CYCLE FOR NEXT SECTION
MOVE T4,P1 ;CURRENT SECTION MAPPED
AOS T4 ;NEXT SECTION TO CHECK
LSH T4,S2PLSH ;STARTING ADDRESS
JRST CKNZ3] ;AND MAP IT
SOJG T1,CKNZ6 ;LOOP OVER ALL NEW PAGES
PJRST CPOPJ1## ;ALL ARE ZERO, WIN RETURN
;SUBROUTINE TO DETERMINE IF A RANGE OF ADDRESSES OVERLAP THE HIGH
;SEGMENT CALLING SEQUENCE:
; MOVE T3,HIGHEST ADDRESS,,STARTING ADDRESS
; MOVE T1,SECTION # ;IF CALLING CKHSZ, THEN SECTION # IS ZERO
; ;AND THIS IS NOT REQUIRED
; ;(ONLY RH OF T1 NEED BE SET UP)
; PUSHJ P,CKHSO/Z ;SEE IF ADDRESSES OVERLAP THE HIGH SEGMENT
;RETURNS CPOPJ IF THE ADDRESSES OVERLAP THE HIGH SEGMENT,CPOPJ1 IF THEY
;DON'T . PRESERVES ALL AC'S
CKHSZ: PUSH P,T1 ;SAVE T1
SETZ T1, ;SECTION TO CHECK IN
PUSHJ P,CKHSO
JRST TPOPJ## ;..
JRST TPOPJ1##
CKHSO: PUSHJ P,SAVE2## ;SAVE WORKING AC'S
PUSH P,J ;SAVE J
PUSH P,T1 ;ARG
MOVEI T1,(J) ;JOB #
MOVE J,.USJOB ;LOAD JOB #
PUSHJ P,FNDHSB## ;GET SEG DATA BLOCK
JRST [POP P,T1 ;RESTORE T1
JRST JPOPJ1##] ;NO OVERLAP
MOVE P1,T1 ;SEG DATA BLOCK ADDR TO P1
POP P,T1 ;RESTORE T1
LDB P2,[PSG2LH+.HBSG2(P1)] ;GET SECTION
CAIE P2,(T1) ;SECTION DESIRED?
JRST JPOPJ1## ;NO, NO OVERLAP THEN
LDB P1,JBYHSO## ;LOWEST PAGE IN SEGMENT
LSH P1,P2WLSH ;WORD ADDR
HLRZ P2,JBTADR##(J) ;HIGHEST ADDR IN SEGMENT
POP P,J ;RESTORE J
HLRZ P3,T3 ;HIGHEST ADDRESS IN THE RANGE
CAIL P3,(P1)
CAIGE P2,(T3)
AOS (P) ;YES, ALL IS GOODNESS
POPJ P, ;RETURN
;SUBROUTINE TO ZERO PAGES ALLOCATED TO A JOB (LOW SEGMENT)
; WHEN THE JOB HAS A NON-SHARABLE HIGH SEGMENT
; CALLED ONLY ON A SWAP-IN
;CALLING SEQUENCE:
; MOVE J,SEGMENT NUMBER
; PUSHJ P,ZERHGH
; ... RETURNS HERE (PAGES HAVE BEEN ZEROED)
; ... RETURNS HERE IF PAGES CAN BE ZEROED IN TRADITIONAL FASHION
; T1=NUMBER OF WORDS TO ZERO
ZERHGH::SE1ENT
CAILE J,JOBMAX## ;A HIGH SEGMENT?
JRST CPOPJ1## ;YES, KISER CAN ZERO THE PAGES
PUSH P,J ;SAVE THE JOB NUMBER
PUSH P,T2 ;SAVE HIGHEST ADDRESS ALLOCATED
MOVEI T2,JBTSGN##-.HBLNK(J) ;POINT TO FIRST SEG
ZERHG0: HRRZ T2,.HBLNK(T2) ;NEXT HIGH SEGMENT
JUMPE T2,[POP P,T2 ;RESTORE T2
JRST JPOPJ1##] ;NO NON-SHARABLE SEGMENTS, LET CORE1 ZERO
SKIPLE J,.HBSGN(T2) ;IS SEGMENT A SPY SEG?
TLNE J,SHRSEG ;NO, IS IT NON-SHARABLE?
JRST ZERHG0 ;IT'S SPY OR SHARABLE
HRRZS J ;ZERO JUNK FOR SEGSIZ (MAY BE IN SECTION 1)
PUSHJ P,SEGSIZ## ;GET THE SIZE OF THE HIGH SEGMENT
EXCH T2,(P) ;T2 = HIGHEST ADDRESS ALLOCATED
SUB T2,(P) ;T2 = HIGHEST ADDRESS IN THE LOW SEG
LSH T1,W2PLSH ;NUMBER OF PAGES TO ZERO
MOVEM T1,(P) ;SAVE THAT
MOVE J,-1(P) ;RESTORE THE JOB NUMBER
PUSHJ P,SNPAGS## ;FIND THE FIRST PAGE TO ZERO
POP P,T3 ;RESTORE NUMBER OF PAGES TO ZERO
ZERHG1: MOVE T2,T1 ;SETUP ARGUMENT TO ZPAGE
PUSHJ P,ZPAGE ;ZERO THE PAGE
SSX T1,MS.MEM ;PAGTAB SECTION
HRRZ T1,PAGTAB(T1) ;NEXT PAGE TO ZERO
SOJG T3,ZERHG1 ;LOOP OVER ALL PAGES
JRST JPOPJ## ;INDICATE PAGES HAVE BEEN ZEROED
SUBTTL IPCF INTERFACE
;SUBROUTINE TO REMOVE A PAGE FROM A JOBS ADDRESS SPACE
;ENTER WITH T1= VIRTUAL PAGE NUMBER, J= JOB NUMBER (JOB ADDRESSABLE)
;ENTER ALSO WITH P3=ADDRESS OF TARGET IPCF PACKET, IF IPCF
;OR P3=0 IF NOT (COMCON). THIS IS SO WE KNOW TO CALL MIGRATE WAITING
;ROUTINES IF P3 =/= 0
;RETURNS CPOPJ IF PAGE NOT IN JOBS ADDRESSING SPACE
;RETURNS CPOPJ1 NORMALLY, T2=PHYSICAL PAGE NUMBER IF PAGE IN CORE,
; OR T2 = BIT 18 + DSK ADDRESS IF PAGE IS ON DSK
;ON NORMAL RETURN, THE IPCF INTERLOCK AND MM WILL BE HELD FOR THE TARGET
;JOB IF P3 =/= 0 ON ENTRY.
IPCRMV::JUMPE T1,CPOPJ## ;CANT REMOVE PAGE 0
PUSHJ P,LGLPG ;LEGAL PAGE NUMBER?
POPJ P, ;NO
PUSHJ P,TPSHS
POPJ P, ; OR A PAGE IN SHARABLE HI SEG
SE1ENT ;FOR PAGE MAP ENTRY
PUSHJ P,GTPME ;GET MAP ENTRY
JUMPE T2,CPOPJ## ;ERROR IF PAGE NOT ALLOCATED
TLZ T2,(PM.NAD) ;KEEP ONLY ADDRESS
CAMN T2,[PM.ZER] ;OR IF ABZ
JUMPN P3,CPOPJ## ;ERROR IF NOT SAVE
IFN FTPEEKSPY,<
PUSHJ P,TSSPT ;ERROR IF A SPY PAGE
CAIA
POPJ P,
>
IFN FTMP,<
JUMPE P3,[PUSHJ P,GGVMM## ;IF DOING THIS FOR COMCON
JRST IPCRM1]
>
IFE FTMP,<
JUMPE P3,IPCRM1
>
PUSHJ P,IPMCHK## ;CHECK MIGRATE STUFF IF IPCF
IFN FTMP,<
PUSHJ P,UPMM## ;GET MM RESOURCE
>
IPCRM1: PUSHJ P,RMVPGI ;OK, REMOVE FROM MAP
JRST IPCRM5 ;DISK ADDR (OR ON OUT QUEUE)
PUSH P,T2 ;SAVE ENTRY
TLNE T2,(PM.OIQ!PM.SSP) ;ON A QUEUE?
JRST IPCRM2 ;YES
MOVSI T1,(UP.WHC)
IORM T1,.USBTS ;NO, WORKING SET CHANGED
JUMPE P3,IPCR1A ;IF FROM COMCON, MAKE PAGE NOWHERE
TLO T2,(PM.OIQ!PM.SSP)
MOVEM T2,(P) ;RETURN THE BITS FOR THE ENTRY
HRRZS T1,T2 ;CLEAR BOTH LEFT HALVES
PUSHJ P,LKPSF ;REMOVE PAGE FROM JOB
MOVEI T3,PAGSNQ## ;QUEUE TO ADD TO
PUSHJ P,ADDPTQ ;PUT ON THE QUEUE
IPCRM9: SSX T2,MS.MEM ;POINT TO MEMTAB SECTION
MOVEI T1,.IPCFI##(P3) ;ADDRESS IN PACKET WHERE PAGE NUMBER GOES
DPB T1,NVPNT2 ;LOW ORDER BITS
ANDCMI T1,<P2.VPN_-<^L<P2.VPN>+P2.SPN>> ;CLEAR LOW ORDER STUFF
LSH T1,<^D35-<^L<MT.JOB>+MT.SJB-1>-P2.SPN>
TLO T1,(MT.IPC) ;IPCF PAGE
MOVEM T1,MEMTAB(T2) ;SET HIGH ORDER OF ADDR+MT.IPC
.CREF MT.DAD ;(THIS CLEARS THE DISK ADDRESS)
IPCR2A:
IFN FTKL10&FTMP,<
SETOM SAVCTL## ;SWEEP CACHE
>
IPCRM3: PUSHJ P,DCVMT ;ADJUST VM COUNTERS
PUSHJ P,STVSIZ
POP P,T2
PJRST FIXAD1 ; AND SKIP-RETURN
;HERE IF PAGE ON DISK (MAY BE ON IP OR OUT QUEUE TOO)
IPCRM5: TLO T2,IP.DSK##_-^D18 ;LIGHT DISK
PUSH P,T2 ;SAVE FOR LATER RETURN
IPCRM6: CAIE T3,PAGIPQ## ;WAS IT ON THE IP QUEUE?
JRST IPCRM3 ;NO, OUT QUEUE, DISK ADDR IS SAFE
SSX T4,MS.MEM ;POINT TO MEMTAB
DPB J,[POINT PT.SJB,PAGTAB(T4),<^L<PT.JOB>+PT.SJB-1>]
MOVEI T3,PIOWQ## ;PUT JOB INTO PAGING I/O WAIT
DPB T3,PJBSTS## ; UNTIL I/O IS DONE ON "IP" QUEUE
PUSHJ P,[IFN FTMP,<
PUSHJ P,REMMM## ;REMEMBER STATE OF THE MM
>
PJRST WSCHED##] ;WAIT
TLZ T2,IP.DSK##_-^D18
PUSHJ P,ONPOQ ;IS IT NOW ON THE PAGING QUEUE?
CAIA ;NO
JRST IPCRM6 ;BE SURE IT'S NOW ON THE OUT QUEUE
PUSHJ P,GTPME ;GET PAGE ENTRY AGAIN
JUMPE T2,IPCRM3 ;PAGE ON DISK, ADDRESS IS RIGHT
SETZM (T4) ;OOPS, MUST HAVE HAD ERROR AND IP2ERR PUT BACK
TLZ T2,(PM.NAD) ;ONLY ADDRESS
TLO T2,IP.DSK##_-^D18 ;SET DISK
MOVEM T2,(P) ;SAVE
JRST IPCRM6 ;BE ABSOLUTELY SURE IT'S ON THE OUT QUEUE
;HERE IF IPCRMV CALLED FROM COMCON AND PAGE WAS IN CORE NOT ON ANY QUEUE
IPCR1A: MOVSI T1,IPCBIT
SSX T2,MS.MEM ;SET SECTION NUMBER
IORM T1,PAGTAB(T2) ;IPCF PAGE IN NO MAP
JRST IPCR2A ;CONTINUE
;HERE IF PAGE WAS ON ONE OF THE "IN" QUEUES
IPCRM2: SSX T2,MS.MEM ;SET INDEX
JUMPN P3,IPCRM9 ;IF IPCSER, JUST UPDATE MEMTAB ADDR
TLNE T2,(PM.SSP) ;SLOW?
SKIPA T3,[PAGSNQ] ;YES
MOVEI T3,PAGINQ
PUSHJ P,RMVPFQ ;REMOVE
TLZ T2,(PM.NAD) ;CLEAR BITS
MOVEM T2,(P) ;STORE AS JUST PAGE #
JRST IPCR1A ;NOW IPCF PAGE NOWHERE (FOR COMCON)
;SUBROUTINE TO PAGE OUT A PAGE FOR IPCF
;ENTER J=JOB NO JOB ADDRESSABLE) T2=PHYS PAGE OR BIT 18+DSK ADR
;EXIT CPOPJ IF NO SWAPPING SPACE AVAILABLE OR IO ERROR
;EXIT CPOPJ1 IF ALL OK, T2=DSK ADDRESS OF PAGE
IPCPAG::TLNE T2,(1B0+PM.OIQ+PM.SSP) ;DISK ADR?
PJRST CPOPJ1## ;YES, ITS ALREADY OUT
PUSHJ P,SAVE2## ;NO, SAVE SOME ACS
IFN FTMP,<
PUSHJ P,MMOWN##
PUSHJ P,GGVMM## ;GUARD AGAINST RACES
>
PUSH P,U
PUSHJ P,IPCSSP ;ALLOCATE SWAPPING SPACE AND MAKE A SWPLST ENTRY
PUSHJ P,PGWAIT ;START THE IO AND WAIT FOR IT
SOS -1(P) ;ERROR - NON SKIP RETURN
HRRZ P1,T2 ;SWPLST INDEX
PUSHJ P,GVIPCP ;RETURN THE PAGE IF NOT ALREADY RETURNED
; BY THE SWAPPER
MOVE T2,U ;GET DSK ADR IN T2 (+ BIT 18)
PJRST UPOPJ1## ;AND TAKE SKIP-RETURN
;SUBROUTINE TO ALLOCATE SWAPPING SPACE TO PAGE OUT AN IPCF PAGE
; RETURNS CPOPJ ALWAYS, T1 SETUP TO MAKE A SWPLST ENTRY
IPCSSP::PUSHJ P,SAVE1## ;SAVE A WORKING AC
SE1ENT ;MUST BE IN SECTION 1 TO ADDRESS MEMTAB
MOVSI P1,LOKPHB ;INDICATE SWAPPING OUT THIS PAGE
IORM P1,@[IW MS.MEM,PAGTAB(T2)] ;SO IT GETS LEFT ALONE BY LOKCON
MOVE P1,T2
SKIPA U,[PG.SLO+1] ;GET 1 PAGE ON SLOW SWAPPING MEDIUM
IPCSS1: MOVEI U,1
PUSHJ P,SWPSPC##
JRST IPCSS1 ;CANT GET ANY SPACE - ERROR RETURN
TLO T1,(MT.LEF) ;INDICATE LAST PAGE
SSX P1,MS.MEM ;SET SECTION NUMBER
MOVEM T1,MEMTAB(P1) ;SAVE DSK ADR IN MEMTAB
MOVE U,T1
.CREF MT.LEF
; TLO U,IP.DSK##_-^D18 ;DSK ADR (+BIT 0)
HRRZ T1,P1 ;CORE ADR
LSH T1,11 ;MAKE SWPLST ENTRY
TDO T1,[SL.DIO+SL.IPC+1] ;OUTPUT 1 PAGE
POPJ P, ;RETURN
;SUBROUTINE TO INSERT A PAGE INTO A JOBS ADDRESS SPACE
;ENTER J=JOB NUMBER (JOB ADDRESSABLE)
; T1=VIRTUAL PAGE NUMBER, T2=PHYSICAL PAGE NUMBER OR BIT 0 + DSK ADDRESS
;EXIT CPOPJ IF PAGE ALREADY EXISTS OR ERROR (NEW SIZE TOO BIG, IO ERROR)
;EXIT CPOPJ1 NORMALLY
;ON ERROR RETURN, T1 CONTAINS IPCFR. ERROR CODE FOR FAILURE
;(PAGING I/O, LIMIT EXCEEDED, ETC.)
IPCINS::PUSHJ P,SAVE1## ;SAVE SOME ACS
PUSHJ P,FNDPDS## ;SET UP PDB FOR SIZE CHECKS
IFN FTMP,<
PUSHJ P,MMOWN##
PUSHJ P,GGVMM## ;MUST HAVE IF DON'T ALREADY
>
MOVE P1,T2 ;REMEMBER ADR
LSHC T1,P2SLSH ;CONVERT TO SECTION #
SKIPE .UPMP+SECTAB(T1);SECTION EXIST?
JRST IPCIN1 ;PROCEED IF SO
MOVEI T4,1 ;# OF SECTION MAP PAGES
PUSH P,P1 ;SAVE ARG
MOVEI T3,1 ;ONE PAGE OF INCREASE
SKIPL .USBTS ;ALREADY BIG?
AOS T3 ;INCLUDE .WSBNZ
PUSH P,T1 ;SAVE T1
PUSHJ P,SZCHK ;MAKE SURE HE CAN GET MAP PHYSICALLY
JRST [ADJSP P,-2 ;FIX STACK
MOVEI T1,IPCRP%## ;;NO (PHYSICAL) ROOM (FOR MAP)
POPJ P,] ;RETURN
PUSHJ P,GSMPGS
PUSHJ P,CRSMAP ;CREATE MAP
POP P,P1
IPCIN1: SE1ENT ;ENTER SECTION 1
LSHC T1,S2PLSH ;BACK TO PAGE #
PUSHJ P,GTPME ;GET MAP ENTRY
JUMPN T2,IPCI1B ;DUPLICATE PAGE ERROR
MOVEI T3,1 ;ONE PAGE OF INCREASE
PUSH P,T1
PUSHJ P,SZCHK ;TRYING TO GET TO BIG?
TLO P1,200000 ;YES
HLRZ T3,.PDCVL##(W) ;GET CURRENT VIRTUAL LIMIT
SKIPN T3 ;IF HE DOESN'T HAVE A LIMIT
AOSA T3 ;THEN HE'S OK (FLAG FOR LATER)
SUBI T3,-UPMPSZ##(T1) ;EXCESS PAGES HE HAS
POP P,T1 ;RESTORE T1
JUMPG T3,IPCI1C ;HE'S OK
IPCI1A: SKIPA T1,[IPCRV%##] ;NO ROOM (VIRTUAL LIMIT)
IPCI1B: MOVEI T1,IPCUP%## ;DUPLICATE PAGE
POPJ P,
IPCI1C: MOVE T2,P1 ;ADDRESS TO T2
TLZ T2,(PM.NAD) ;CLEAR CRUD
TLZE P1,(PM.OIQ) ;ON AN "IN" QUEUE?
JRST [TLNE P1,200000 ;TOO BIG?
JRST IPCI2A ;YES, INSERT AS IS
TLZN P1,(PM.SSP) ;SLOW?
SKIPA T3,[PAGINQ##] ;NO
MOVEI T3,PAGSNQ## ;YES
PUSHJ P,RMVPFQ ;REMOVE IT FROM THE QUEUE
JRST IPCI7A] ;AND PUT IT IN THE JOB'S MAP
TLZN P1,IP.DSK##_-^D18 ;INSERTING A DSK ADR?
JRST IPCIN7 ;NO
;HERE IF PAGE ON DSK
TLNN P1,200000 ;IF TRYING TO GET TOO BIG OR
JRST IPCIN3 ;SWAP PAGE IN FOR HIM
JUMPLE T3,IPCI1A ;ERROR IF CAN'T GO (MORE) VIRTUAL
IPCIN2: TLZ P1,(PM.NAD) ;KEEP GNLY ADDRESS
TLO P1,(PM.CSH!PM.WRT!PM.PUB!PM.AAB) ;SET ACCESS ALLOWED
MOVEM P1,(T4) ;SAVE DSK ADR IN MAP
JRST IPCIN9 ;FINISH UP
;HERE IF PAGE ON QUEUE AND CAN'T PAGE IN FOR JOB
IPCI2A: SSX T2,MS.MEM ;PHYS PAGE INVOLVED (POINT TO MEMTAB)
DPB J,[POINT MT.SJB,MEMTAB(T2),<^L<MT.JOB>+MT.SJB-1>]
DPB T1,NVPNT2 ;SET VIRTUAL PAGE # INVOLVED
TLZ P1,(PM.NAD^!PM.SSP) ;PARANOIA TO CLEAR JUNK BITS
TLO P1,(PM.OIQ!PM.CSH!PM.PUB!PM.WRT!PM.AAB) ;ON IN QUEUE
MOVEM P1,(T4) ;SAVE ENTRY IN MAP
MOVSI T4,(MT.IPC) ;CLEAR BIT IN MEMTAB
ANDCAM T4,MEMTAB(T2)
JRST IPCIN9 ;CONTINUE
;HERE TO SWAP THE PAGE IN SO CAN PUT IT IN THE MAP
IPCIN3: PUSH P,T4 ;SAVE MAP POINTER
IPCI3A: PUSHJ P,ONPOQ ;ON "IP" OR "OUT" QUEUE?
JRST IPCIN5 ;NO, "REALLY" OUT
CAIE T3,PAGIPQ## ;ON THE "IP" QUEUE?
JRST IPCIN4 ;NO, ON THE "OUT" QUEUE
SSX T4,MS.MEM ;MEMTAB SECTION
DPB J,[POINT PT.SJB,PAGTAB(T4),<^L<PT.JOB>+PT.SJB-1>] ;SAVE JOB NUMBER SO CAN GET STARTED AGAIN
MOVEI T3,PIOWQ## ;PUT JOB INTO PAGING I/O WAIT
DPB T3,PJBSTS## ; UNTIL I/O IS DONE ON "IP" QUEUE
IFN FTMP,<
PUSHJ P,[PUSHJ P,REMMM## ;REMEMBER STATE OF THE MM
PJRST WSCHED##] ;WAIT
>
IFE FTMP,<
PUSHJ P,WSCHED##
>
JRST IPCI3A ;NOW TRY TO FIND IT ON A QUEUE
IPCIN4: MOVE P1,T2 ;SAVE DISK ADDR
HRRZ T2,T4 ;PHYSICAL PAGE NUMBER
PUSHJ P,RMVPFQ ;REMOVE PAGE FROM THE "OUT" QUEUE
EXCH P1,T2 ;PHYSICAL PAGE TO P1, DSK ADDR TO T2
PUSH P,T1 ;SAVE T1
PUSHJ P,DLTPGD ;RECLAIM DISK SPACE
POP P,T1 ;RESTORE T1
POP P,T4 ;(FIX STACK - RESTORE MAP POINTER)
JRST IPCI7A ;AND PUT IT INTO THE JOB'S MAP
IPCIN5: EXCH T1,(P) ;SAVE VPN, GET POINTER
SKIPG BIGHOL## ;IS THERE A FREE PAGE IN CORE?
JRST IPCIN6 ;NO
LDB T1,JBYSSA## ;FIRST PAGE OF JOB
MOVEI T2,1
PUSHJ P,ADPAGS## ;AND INSERT ANOTHER PAGE THERE
SSX T1,MS.MEM ;SECTION WHICH CONTAINS MEMTAB
TLZ P1,(PM.NAD)
TLO P1,(MT.LEF) ;LAST
MOVEM P1,MEMTAB(T1)
MOVE P1,(P)
DPB P1,NVPNT1
HRRZ P1,T1 ;PHYSICAL PAGE NUMBER IN P1
MOVE T1,(P) ;GET VIRTUAL PAGE NUMBER
PUSHJ P,INSPAG ;PUT THE NEW PAGE IN THE MAP
MOVE T1,P1 ;RESTORE PHYSICAL PAGE NUMBER
LSH T1,11 ;MAKE A SWPLST ENTRY
TDO T1,[SL.IPC+1] ; 1 PAGE, IPC-TYPE
S0PSHJ PAGEIT ;SWAP IN (S0PSHJ SO RETURN IN S1, WILL FALL
;INTO S0 IF STARTING I/O
JRST IPCI10 ;IO ERROR - RETURN
POP P,T1 ;OK, RESTORE VIRT PAGE NO
PUSHJ P,GTPME ;SET UP POINTER TO MAP SLOT
JRST IPCIN8 ;AND CONTINUE
;HERE WHEN NOT ENOUGH CORE IN CORE
IPCIN6: TLZ P1,(PM.NAD)
TLO P1,(PM.AAB) ;MAKE SURE ACCESS ALLOWED
MOVEM P1,(T1) ;SAVE DSK ADDR IN MAP
MOVE T1,(P) ;VIRTUAL PAGE NUMBER
PUSHJ P,INSDWE ;PUT DSK ADR IN MAP
LDB T1,IMGIN## ;SIZE OF JOB
ADDI T1,1 ;IT WILL GROW BY 1 PAGE
PUSHJ P,XPANDP## ;GET THE PAGE INTO CORE
IFN FTMP,<
PUSHJ P,DIFMM## ;GIVE UP MM
>
PUSHJ P,WSCHED## ;WAIT FOR THE SWAP TO HAPPEN
IFN FTMP,<
PUSHJ P,UIFMM## ;RESTORE MM
>
POP P,T1 ;RESTORE VIRT PAGE NO.
JRST IPCIN9 ;AND FINISH UP
;HERE WHEN PAGE IS IN CORE
IPCIN7: TLZE P1,200000 ;PHYSICAL LIMIT EXCEEDED?
JRST IPCI11 ;YES, SEE ABOUT PUTTING PAGE ON QUEUE
SOS %CNPIC## ;DECREMENT COUNT OF IPCF PAGES IN CORE
IPCI7A: TLZ P1,(PM.NAD) ;PARANOIA
PUSHJ P,INSPAG ;INSERT THE PAGE IN THE JOB'S MAP
LDB T3,JBYLSA## ;FIRST PAGE IN THE LOW SEGMENT
SSX T3,MS.MEM ;TO ADDRESS PAGTAB SECTION
MOVE T2,PAGTAB(T3) ;ADD THIS PAGE TO THE FRONT
HRRM P1,PAGTAB(T3) ; OF THIS JOB'S PAGTAB LIST
SSX P1,MS.MEM ;PAGTAB SECTION
HRRZM T2,PAGTAB(P1) ;(CLEAR IPCBIT IN LH)
HRRM T3,PT2TAB(P1)
SSX T2,MS.MEM
HRRM P1,PT2TAB(T2)
IPCIN8: MOVSI T2,(UP.WHC) ;WORKING SET HAS CHANGED
IORM T2,.USBTS ;TURN THAT ON FOR THE PAGE FAULT HANDLER
IPCIN9: PUSHJ P,ICUPR ;BUMP UPREL IF THIS PAGE CONTIGUOUS
HRL P1,T1 ;FIX UP JBTADR, JOBREL, ETC
HRROI T1,777000 ;IF JOB IS VIRTUAL NOW,
AND T1,.USVRT ;MUST COUNT PAGE IN VMCMAX NOW
JUMPE T1,IPCI9A
AOS VMTOTL## ;INCREMENT AMOUNT OF VM IN USE
SOS VMCMAX##
IPCI9A: PUSHJ P,SETVRT ;ADJUST COUNTS, ETC.
PJRST FIXADR ; AND TAKE SKIP RETURN TO USER
;HERE ON A PAGING IO ERROR
IPCI10: HRRZ P1,T2 ;INDEX INTO SWPLST
PUSHJ P,DLTSLX ;ZAP THE SWPLST ENTRY
POP P,T1 ;RESTORE THE VIRTUAL PAGE NUMBER
PUSHJ P,DLTPAG ;RETURN THE PAGE
MOVEI T1,IPCIE%## ;PAGING I/O ERROR
POPJ P,
;HERE IF PAGE IS IN CORE, BUT WE CAN'T FIT IT INTO THE JOBS PHYS LIMIT
;PUT THE PAGE ON THE "IN" QUEUE AND PUT THE DISK ADDR IN THE MAP
;T1=VIRT PAGE #, T4 HAS MAP POINTER, T2 & P1 HAVE PHYS PAGE # + SOME
;EXTRANEOUS BITS IN P1
IPCI11: HRLI P1,(PM.OIQ!PM.AAB!PM.CSH!PM.PUB!PM.WRT)
MOVEM P1,(T4) ;SAVE POINTER IN MAP
SSX P1,MS.MEM ;POINT TO MEMTAB
SETZM MEMTAB(P1) ;CLEAR JUNK IN MEMTAB
DPB J,[POINT MT.SJB,MEMTAB(P1),<^L<MT.JOB>+MT.SJB-1>]
DPB T1,[POINT P2.SPN,PT2TAB(P1),<^L<P2.VPN>+P2.SPN-1>]
EXCH T2,PAGINQ## ;MAKE FIRST PAGE ON IN QUEUE
HRRZM T2,PAGTAB(P1) ;POINT US AT HIM (CLEARING IPCBIT)
SKIPE T2 ;IF THERE IS A PAGE
HRRM P1,@[IW MS.MEM,PT2TAB(P1)] ;THEN SET BACK LINK TOO
HLLZS PT2TAB(P1)
AOS PAGINC## ;INCREMENT
JRST IPCIN9 ;FINISH UP
;SUBROUTINE TO DELETE A PAGE FROM CORE OR DISK
;ENTER T2=ADR OF PAGE (BIT 0 ON IF DSK)
;ALWAYS RETURNS CPOPJ
;ENTER AT IPCDEL IF %CNPIC IS TO BE ADJUSTED IF PAGE WAS IN CORE, AT
;IPCDLX IF NOT
IPCDLX::TDZA T1,T1 ;FLAG TO NOT CHANGE %CNPIC
IPCDEL::SETO T1,
SE1ENT
IFN FTMP,<
PUSHJ P,MMOWN## ;OWN MM?
PUSHJ P,GGVMM## ;NO, GET IT
>
TLZ T2,(<PM.NAD^!<PM.OIQ!PM.SSP!1B0>>) ;CLEAR ALL BUT THESE
TLZE T2,(PM.OIQ+PM.SSP) ;PAGE ON THE "IN" QUEUE?
JRST [MOVEI T3,PAGSNQ##
PUSHJ P,RMVPFQ ;REMOVE IT FROM THE "IN" QUEUE
JRST DLTPGC] ;DELETE PAGE FROM CORE AND RETURN
PUSH P,T2 ;SAVE ADDRESS
TLZE T2,(1B0) ;JUST DISK ADDRESS
PUSHJ P,ONPOQ ;PAGE ON "IP" OR "OUT" QUEUE?
JRST IPCDE1 ;NO, JUST A GARDEN VARIETY PAGE
SSX T4,MS.MEM ;MEMTAB SECTION
CAIE T3,PAGIPQ## ;ON THE IN PROGRESS QUEUE?
JRST [SETZM MEMTAB(T4) ;MAKE SURE ITS NOT FOUND ON A QUEUE SEARCH
PUSHJ P,DLTPGD ;NO, "OUT" QUEUE, GIVE BACK DISK SPACE
JRST T2POPJ##] ;RESTORE T2 AND RETURN
MOVSI T2,(MT.GPB) ;GIVE BACK DISK SPACE WHEN I/O COMPLETES
IORM T2,MEMTAB(T4)
JRST T2POPJ## ;AND GIVE PAGE ON DISK RETURN
IPCDE1: POP P,T2 ;RESTORE PAGE NUMBER OR DISK ADDRESS
TLZE T2,(1B0) ;DSK?
JRST DLTPGD ;YES
ADDM T1,%CNPIC ;ADJUST %CNPIC IF NECESSARY
JRST DLTPGC ;NO
;SUBROUTINE TO RETURN IPC PAGES TO THE FREE CORE LIST
;CALLING SEQUENCE:
; PUSHJ P,GVIPCP
;ALWAYS RETURNS CPOPJ
GVIPCP::SKIPN IPCCNT## ;ANY IPCF PAGES WHICH HAVE PAGING OUTPUT DONE?
POPJ P, ;NO, RETURN
PUSHJ P,SAVE2## ;SAVE SOME WORKING ACS
GVIPC1: MOVEI P1,SWPLST## ;START LOOKING AT THE BEGINNING OF SWPLST
MOVE P2,SLECNT## ;NUMBER OF ENTRIES IN SWPLST
GVIPC2: SKIPE T1,(P1) ;A NON-ZERO SWPLST ENTRY?
TLNN T1,(SL.IOD) ;YES, IS I/O DONE FOR THIS SWPLST ENTRY?
GVIPC3: AOJA P1,GVIPC2 ;NO, LOOK AT THE NEXT SWPLST ENTRY
TLC T1,(SL.IPC) ;BE SURE NOT PAGING QUEUE ENTRY
TLNN T1,(SL.SIO!SL.IPC) ;AN IPCF PAGE? (WANT SL.IPC CLEAR SO THIS
;PAGE WON'T BE SEEN AGAIN)
TLNN T1,(SL.DIO) ;AND WAS IT BEING PAGED OUT?
JRST GVIPC4 ;NO, LOOK AT THE NEXT SWPLST ENTRY
PUSH P,T1 ;SAVE SWPLST INDEX
SUBI P1,SWPLST ;DLTSLE WANTS RELATIVE INDEX
PUSHJ P,DLTSLX ;REMOVE THE SWPLST ENTRY
POP P,T1 ;RESTORE SWPLST INDEX
LDB T1,[POINT 13,T1,26]
MOVSI P1,IPCBIT+LOKPHB
PUSHJ P,IPCLKP ;LINK PAST IF REQUIRED
PUSHJ P,GVPAGS## ;RETURN THE PAGE TO THE FREE CORE LIST
SOSG IPCCNT## ;DECREMENT THE COUNT OF IPCF PAGES PAGED OUT
POPJ P, ;RETURN IF NO MORE
JRST GVIPC1 ;ELSE, LOOK FOR THE NEXT ONE
GVIPC4: SOJG P2,GVIPC3 ;LOOK AT THE NEXT SWPLST ENTRY
STOPCD GVIPC5,DEBUG,IPN, ;++IPC PAGE NOT FOUND
GVIPC5: SETZM IPCCNT## ;ZERO IPCCNT TO AVOID A LOOP
POPJ P, ;AND RETURN
;SUBROUTINE TO LINK PAST THE PAGTAB PAGE FOR ABOVE. ONLY A SUBROUTINE
;SO CAN USE SE1ENT
IPCLKP: SE1ENT ;ENTER SECTION 1
HRRZ P2,T1 ;PAGE #
SSX P2,MS.MEM ;SECTION NUMBER
ANDCAB P1,PAGTAB(P2) ;NO LONGER AN IPCF PAGE
PUSH P,P1 ;SAVE SUCCESSOR
HRRZ P1,PT2TAB(P2) ;GET PREDECESSOR
CAMN T1,LMPAG## ;LAST MONITOR PAGE?
MOVEM P1,LMPAG## ;UPDATE
HLLZS PT2TAB(P2) ;CLEAR LINKS THIS PAGE
SETZM PAGTAB(P2)
POP P,P2 ;RESTORE SUCCESSOR
TRNE P1,-1
HRRM P2,@[IW MS.MEM,PAGTAB(P1)]
TRNE P2,-1
HRRM P1,@[IW MS.MEM,PT2TAB(P2)]
POPJ P,
SUBTTL SEGCON
;SUBROUTINE TO RETURN CORE ALLOCATED TO A NON-SHARABLE HIGH SEGMENT
;ENTER WITH JOB NUMBER -2(P), PHYSICAL SEGMENT SIZE -1(P)
KCOREV::LDB T1,IMGIN## ;SIZE OF THE SEGMENT
JUMPN T1,KCOREH## ;IF NON-ZERO, ITS SHARABLE AND SEGCON CAN
; GIVE BACK THE PAGES
MOVE T2,J ;SAVE HIGH SEG #
MOVE J,-2(P) ;GET THE JOB NUMBER
PUSHJ P,SVEUB## ;SETUP THE UBR TO POINT AT THE CURRENT JOB
MOVEI T1,(T2) ;GET HIGH SEG #
PUSHJ P,FNDHSB## ;GET SEG DATA BLOCK
XCT NSS## ;NO SUCH HIGH SEGMENT
LDB T1,[PSG2LH+.HBSG2(T1)] ;GET SECTION HIGH SEG IS IN
IFN FTXMON,<
PUSHJ P,SVPCS##
>
MOVE J,T2
MOVEI T1,0 ;ASKING FOR 0K OF CORE
PUSHJ P,CORE1## ;RETURN THE CORE
STOPCD .+1,DEBUG,CMS, ;++CORE1 MUST SKIP
IFE FTXMON,<
SETZM -5(P) ;SO SEGCON WON'T CHANGE VIRTAL WHICH
; WAS ALREADY MADE RIGHT BY VIRCHK
>
IFN FTXMON,<
SETZM -11(P) ;SVPCS USES MORE STACK
>
POPJ P,
;GENERALIZED REMAP (GIVEN A COLLECTION OF CONTIGUOUS PAGES, MOVE
; THEM TO THE VIRTUAL ADDRESS SPECIFIED BY THE USER AND MAKE THEM A
; HIGH SEGMENT)
;CALLING SEQUENCE:
; MOVE J,CURRENT JOB NUMBER
; MOVE T1,CURRENT STARTING VIRTUAL PAGE NUMBER
; MOVE T2,NEW STARTING VIRTUAL PAGE NUMBER
; MOVE T3,NUMBER OF PAGES
; MOVSI T4,FLAGS ;AS FOLLOWS:
; 1B0 ;ON=NON-SHARABLE NEW HIGH SEG, OFF=SHARABLE
; 1B1 ;APPEND TO EXISTING HIGH SEG IF ON
;RETURNS CPOPJ IF ARGUMENTS ARE WRONG, PAGES IN THE RANGE SPECIFIED
; DON'T ALL EXIST, OR MOVING THE PAGES TO THE VIRTUAL ADDRESSES
; SPECIFIED WOULD CAUSE THE HIGH SEGMENT AND LOW SEGMENT TO OVERLAP
;RETURNS CPOPJ1 IF EVERYTHING IS OK, NEW HIGH SEGMENT NUMBER IN J
NREMAP::TLO M,FLMCOM ;CAUSE ERRORS TO JUST RETURN RATHER THAN GOING STOTAC
JUMPLE T3,IALERR ;REMAPPING NO PAGES IS ILLEGAL
PUSHJ P,SAVE4## ;SAVE WORKING ACS
MOVE J,.USJOB ;CURRENT JOB NUMBER
DMOVE P1,T1 ;SAVE ARGUMENTS
DMOVE P3,T3 ; ..
PUSHJ P,LGLPG ;IS CURRENT STARTING VIRTUAL PAGE A LEGAL PAGE NUMBER?
POPJ P, ;NO
MOVE T1,P2 ;IS NEW STARTING VIRTUAL PAGE A LEGAL PAGE NUMBER?
PUSHJ P,LGLPG ; ..
POPJ P, ;NO
ANDI T1,HLGPNO ;DOES NEW SEGMENT
ADDI T1,-1(P3) ;CROSS A SEGMENT BOUNDARY?
TRNE T1,-1^!HLGPNO ;?
JRST ILPERR ;YES, THIS IS NOT ALLOWED
MOVE T1,P1 ;RESTORE STARTING VIRTUAL PAGE NUMBER
SE1ENT ;FOR REFS
NREMA1: LSHC T1,P2SLSH ;SECTION #
SKIPN .UPMP+SECTAB(T1);EXIST?
JRST PMEERR ;NO, ERROR
LSHC T1,S2PLSH
PUSHJ P,GTPME ;GET THE CONTENTS OF THE USER'S MAP
JUMPE T2,PMEERR ;(REDO RELOCATION)
IFN FTPEEKSPY,<
PUSHJ P,TSSPT ;A SPY PAGE?
>
PUSHJ P,TPNHS ;IS THIS A HIGH SEGMENT PAGE?
JRST PSHERR ;YES, THAT'S ILLEGAL
ADDI T1,1 ;NEXT PAGE
SOJG T3,NREMA1 ;CHECK ALL PAGES BEING REMAPPED
TLNN P4,(1B1) ;DON'T KILL OLD HIGH SEG?
PUSHJ P,[MOVE T1,.JDAT+SGAEND## ;GET FLAGS
TLNE T1,GTSGO## ;IF SEGOP
POPJ P, ; DON'T DELETE ANY SEGMENTS
HRRZ T1,P2 ;NEW STARTING ADDRESS
LSH T1,P2SLSH ;CONVERT TO SECTION #
PUSHJ P,SVPCS## ;SET AS PCS SECTION
SETZ T1, ;KILL ALL SEGS THAT SECTION
S0JRST KILHSH##]
CAMN P1,P2 ;NSA=OSA?
JRST NREMA4 ;YES, NOTHING TO CHECK
MOVE T1,P2 ;NSA
ADD T1,P3 ;NSA+L
CAML P2,P1 ;NSA.LT.OSA?
JRST NREMA2 ;NO
MOVE T2,P2 ;NSA
CAMLE T1,P1 ;NSA+L.LE.OSA?
MOVE T1,P1 ;NO, CHECK NSA TO OSA
JRST NREMA3 ;YES, CHECK NSA TO NSA+L
NREMA2: MOVE T2,P1 ;OSA
ADD T2,P3 ;OSA+L
CAMG T2,P2 ;OSA+L.GT.NSA?
MOVE T2,P2 ;NO, CHECK NSA TO NSA+L
; JRST NREMA3 ;YES, CHECK OSA+L TO NSA+L
NREMA3: PUSHJ P,CKNZP ;MAKE SURE PAGES BEING REMAPPED DON'T OVERLAP
; OTHER PAGES IN THE PROGRAM'S ADDRESS SPACE
JRST PCEERR ;THEY DO, GIVE PAGE CANNOT EXIST BUT DOES ERROR
NREMA4: TLNN P4,(1B1) ;WANT NEW HIGH SEG?
JRST NREM4A ;YES
PUSHJ P,FNSPCS## ;GET SEGMENT
JRST PSHERR ;SHARABLE NOT ALLOWED
JUMPN T1,NREM4D ;HAVE ONE (GET NEW ONE IF NONE)
NREM4A: PUSHJ P,FNDSGN## ;FIND A SEGMENT NUMBER FOR THE JOB'S NEW HI SEG
JRST NFSERR ;NO FREE SEGMENT #S
;AT THIS POINT, J HAS THE SEGMENT NUMBER WE ARE DIDDLING WITH AND
;T1 POINTS TO THE JOB'S SEGMENT DATA BLOCK (MAY NOT BE INITIALIZED IF
;A NEW SEGMENT)
NREM4D: HRRZS J
SKIPN JBTADR##(J) ;DON'T CHANGE ORIGIN IF APPENDING
DPB P2,JBYHSO## ;STORE THE VIRTUAL PAGE NUMBER OF THE HI SEG ORIGIN
PUSH P,J ;SAVE THE NEW HIGH SEGMENT NUMBER
ROT P2,P2SLSH ;DESTINATION SECTION
SKIPN JBTADR##(J) ;APPENDING?
SKIPA J,.USJOB ;NO, LOAD JOB #
SKIPA J,.USJOB ;APPENDING, STILL LOAD JOB #
DPB P2,[PSG2LH+.HBSG2(T1)] ;STORE SEGMENT SECTION
ROT P2,S2PLSH ;MOVE BACK
TLNE P4,(1B1) ;ADDING TO EXISTING HS?
JRST [LDB T2,[PHSSLH+.HBHSZ(T1)] ;YES, PICK UP OLD SIZE
ADDI T2,(P3) ;NEW SIZE
DPB T2,[PHSSLH+.HBHSZ(T1)] ;SET IT
JRST NREMA5 ] ;DON'T AFFECT ORIGIN
MOVE T2,P2 ;GET NEW STARTING PAGE NUMBER
LSH T2,P2SLSH ;STARTING SECTION NUMBER
DPB T2,[PSG2LH+.HBSG2(T1)] ;STORE IT AS HIGH SEG ORIGIN FOR THIS USER
DPB P3,[PHSSLH+.HBHSZ(T1)] ;STORE THE NEW HIGH SEGMENT'S SIZE
;HERE, IF THE SEGMENT IS SHARABLE, REMOVE THE PAGES FROM THE JOB'S
;WORKING SET AND PAGTAB CHAIN AND PUT THEM IN THE SECONDARY MAP
;PAGE OBTAINED BELOW
NREMA5: PUSH P,T1 ;SAVE SEGMENT DATA BLOCK ADDRESS
JUMPL P4,NREMA7 ;JUMP IF NON-SHARABLE
MOVEI T1,(P3) ;NUMBER OF SLOTS REQUIRED IN MAP
EXCH J,-1(P) ;GET SEGMENT #
PUSHJ P,GTHMAP## ;GET HIGH SEG MAP
JRST [POP P,T1 ;FIX STACK
POP P,J ;RESTORE J
JRST NCRERR] ;ERROR
PUSH P,P2 ;SAVE P2
MOVE P2,T1 ;MAP ADDR
MOVN T1,P3 ;NUMBER OF PAGES IN THE NEW HIGH SEGMENT
HRL T1,P1 ;STARTING PAGE NUMBER OF THE OLD HIGH SEGMENT
MOVSS T1 ;MAKE AN ABOJN POINTER
PUSH P,[0] ;WHERE FIRST PHYSICAL PAGE OF HIGH SEG IS
;HERE TO REMOVE PAGES AND MOVE THEM INTO SECONDARY MAP
NREMA6: PUSHJ P,GTPME ;GET THE CONTENTS OF THE USER'S MAP
MOVEM T2,(P2) ;SAVE PTR IN 2NDARY MAP
MOVSI T3,(<PM.NAD^!<PM.AAB!PM.COR>>) ;ACCESS BITS
AND T3,T2 ;ONLY BITS IN T3
TLZ T2,(PM.NAD) ;AND ONLY ADDR IN T2
TLO T3,<(<PM.ICD>B2)>(P2) ;CONVERT TO INDIRECT POINTER
HRRI T3,JBTUPM##-SPTTAB##(J) ;SPT SLOT WHERE 2NDARY MAP IS
MOVEM T3,(T4) ;SAVE NEW POINTER IN USER'S MAP
AOS P2 ;INCREMENT OFFSET
PUSHJ P,LKPSF ;LINK PAST THE PAGE IN PAGTAB
EXCH T1,(P) ;GET OLD PREDECESSOR
JUMPE T1,NREM6A ;NONE
HRRM T2,@[IW MS.MEM,PAGTAB(T1)] ;LINK FORWARD
HRRM T1,@[IW MS.MEM,PT2TAB(T2)] ;THEN POINT BACK TOO
NREM6A: MOVE T1,(P) ;GET T1 BACK
HRRZM T2,(P) ;NEW LAST PAGE IN SEGMENT
AOBJN T1,NREMA6 ;AND LOOP UNTIL ALL HIGH SEGMENT PAGES
; ARE IN PAGTAB IN THE SAME ORDER THAT THEY APPEAR
POP P,(P) ;FIX STACK
EXCH J,-2(P) ;SAVE SEG # AND GET JOB # BACK
POP P,P2 ;AND P2
; IN THE JOB'S MAP
TLZ P4,(1B0) ;HIGH SEG IS SHARABLE
;HERE TO MOVE THE PAGES TO THEIR NEW VIRTUAL ADDRESSES IN USER SPACE
NREMA7: CAML P1,P2 ;MOVING THE PAGES UP?
TDZA T1,T1 ;NO, DOWN OR REMAP IN PLACE
MOVEI T1,-1(P3) ;NUMBER OF PAGES - 1
HRLS T1 ;OFFSET
HRLS P1 ;FIRST PAGE
HRR P1,P2 ;DESTINATION PAGE
ADD P1,T1 ;SOURCE,,DESTINATION
PUSH P,P4 ;SAVE SHARABILITY ATTRIBUTE
MOVEI P4,0 ;BECAUSE THERE ARE ONLY 16 ACS
PUSH P,P4 ; ..
NREMA8: HRRZ T1,P1 ;GET DESTINATION PAGE
LSH T1,P2SLSH ;SECTION #
SKIPE .UPMP+SECTAB(T1);SECTION EXIST?
JRST NREM10 ;YES
PUSH P,P1 ;NO, MUST CREATE IT
MOVEI T4,1 ;# OF MAPS TO CREATE
PUSHJ P,GSMPGS ;GET PAGES
PUSHJ P,CRSMAP ;CREATE SECTION MAP & .WSBNZ IF MUST
POP P,P1 ;RESTORE P1
NREM10: MOVE T1,P1 ;SOURCE PAGE,,DESTINATION PAGE
PUSHJ P,MV1PG ;REMAP THE PAGE
SKIPGE T3,-1(P) ;SHARABLE HIGH SEGMENT?
JRST NREM11 ;NO
DPB T3,T4 ;YES, CLEAR THE WORKING SET BIT
MOVSI T4,(PM.AAB)
ANDCAM T4,(T1) ;CLEAR ACCESS ALLOWED
PUSH P,T1 ;SAVE BYTE POINTER TO THE MAP
PUSHJ P,DCVMT ;ADJUST COUNTS
POP P,T1 ;RESTORE BYTE POINTER TO THE MAP
NREM11: MOVE T3,(T1) ;YES, GET THE CONTENTS OF THE MAP
SKIPE .USVRT ;VIRTUAL?
SKIPL P4 ;YES, DON'T CHANGE PM.WRT (SWAP OUT WILL FIX IT)
TLZ T3,(PM.WRT) ;WRITE PROTECT THE PAGE
TLO T3,(PM.NIA) ;SET NO I/O ALLOWED
MOVEM T3,(T1) ;STORE THE WRITE PROTECTED ENTRY IN THE MAP
JUMPE T2,NREM12 ;WAS THE LOW SEGMENT PAGE IN THE WORKING SET?
AOS (P) ;COUNT THE NUMBER OF PHYSICAL PAGES IN THE HIGH SEGMENT
NREM12: HLRZ T1,P1 ;SOURCE PAGE
HRRZ T2,P1 ;DESTINATION PAGE
CAIL T1,(P1) ;MOVING PAGES DOWN?
AOBJP P1,NREM14 ;BUMP SOURCE,,DESTINATION PAGES
;(MUST ALWAYS JUMP)
NREM13: SUB P1,[1,,1] ;DECREMENT SOURCE,,DESTINATION
NREM14: PUSHJ P,ISITNZ ;NZS PAGE?
TDZA T2,T2 ;GO TO DCUPN1
MOVEI T2,DECNCR-DCUPN1 ;GO TO DECNCR
PUSHJ P,DCUPN1(T2)
CAIGE P4,-1(P3) ;REMAPPED ALL THE PAGES REQUESTED?
AOJA P4,NREMA8 ;NO, REMAP THE NEXT PAGE
HLRZ T1,P1 ;LAST PAGE MOVED
CAIGE T1,(P1) ;MOVING PAGES UP?
ADDI P1,1(P3) ;YES, HIGHEST PAGE = NEW ORGIGIN + NUMBER OF PAGES
MOVEI T1,-1(P1) ;HIGHEST VIRTUAL PAGE IN THE HIGH SEGMENT
LSH P1,P2WLSH ;CONVERT TO WORDS
SUBI P1,1 ;PAGE BOUNDARY - 1
HRRM P1,.JDAT+JOBHRL## ;STORE HIGHEST VIRTUAL ADDRESS IN HI SEG FOR THE USER
POP P,P2 ;RESTORE NUMBER OF PHYSICAL PAGES IN HI SEG
POP P,P4 ;AND SHARABALITY
MOVE J,-1(P) ;RESTORE THE HIGH SEGMENT NUMBER
TLNN P4,(1B1) ;ADDING TO OLD SEGMENT?
TDZA T2,T2 ;NO
HLRZ T2,JBTSWP##(J) ;YES, ADD TO OLD NUMBER NEW NUMBER
ADDI P2,(T2)
JUMPGE P4,NREM15 ;JUMP IF THE HIGH SEGMENT IS SHARABLE
HRLM P2,JBTSWP##(J) ;STORE THE NUMBER OF IN CORE PAGES IN THE HI SEG
SETZB P2,JBTIMO##(J) ;CLEAR OUTPUT SIZE AND DON'T DECREAS LOW SEG
NREM15: DPB P2,IMGIN## ;SET IMGIN SIZE FOR HIGH SEG (0 FOR NON-SHR)
JUMPE P2,NREM16 ;IF ZERO (ONLY NON-SHARE CASE) SKIP SOME
MOVE J,.USJOB ;CURRENT JOB NUMBER
LDB T1,IMGIN## ;DECREASE LOW SEGMENT SIZE BY THE NUMBER OF
SUBI T1,(P2) ; PAGES MAPPED INTO THE HIGH SEGMENT
DPB T1,IMGIN##
NREM16: MOVE T1,(P) ;SEGMENT DATA BLOCK ADDRESS
LDB T1,[PHSSLH+.HBHSZ(T1)] ;HIGHEST PAGE IN HIGH SEG
LSH T1,P2WLSH ;CONVERT TO HIGHEST WORD
SUBI T1,1 ;HIGHEST WORD - 1
HRLI T1,.VJDT ;VIRTUAL ADDRESS OF THE VESTIGUAL JOB DATA AREA
MOVE J,-1(P) ;SEGMENT #
MOVSM T1,JBTADR##(J) ;SAVE HIGH PROTECTION,,RELOCATION
JUMPGE P4,NREM32 ;GET FIRST PAGE OF SEG FROM HS MAP IF SHARABLE
MOVE T1,(P) ;SEG DATA BLOCK ADDR AGAIN
LDB T2,[PSG2LH+.HBSG2(T1)] ;SECTION HIGH SEG IS IN
LDB T1,JBYHSO## ;GET THE HIGH SEGMENT ORIGIN VIRTUAL PAGE
LSH T2,S2PLSH ;SECTION TO PAGE
TROA T1,(T2) ;NO, MAKE FULL PAGE #
NREM32: SKIPA T2,@JBTVAD##(J) ;GET ENTRY FROM HIGH SEG MAP
PUSHJ P,GTPME ;GET THE HIGH SEGMENT ORIGIN PHYSICAL PAGE
DPB T2,JBYHSA## ;STORE FOR POSTERITY
HRLI T2,(<PM.DCD>B2+PM.WRT+PM.CSH+PM.PUB)
MOVEM T2,.UPMP+.UMVJD
CLRPT .VJDT ;MAKE THE NEW MAPPING VISIBLE
MOVE T1,.JDAT+SGANAM## ;FILE SEGMENT CAME FROM
SKIPN .VJDT+.JBHNM## ;ALREADY A NAME IN .JBHRL?
JRST NREM33 ;YES, LEAVE IT ALONE
JUMPE T1,NREM34 ;JUMP IF JUST REMAP (SEGMENT NOT FROM A FILE)
MOVE T2,.JDAT+SGAEND## ;FLAGS
TLNE T2,GTSGO## ;SEGOP? (USER CAN PROVIDE A NAME)
TLNE T2,GTHGH## ;SEGOP, REMAP FUNCTION?
JRST NREM34 ;NO, USER DID NOT SUPPLY A NAME
NREM33: MOVEM T1,.VJDT+.JBHNM## ;YES, STORE THE NAME IN .JBHNM
NREM34: MOVE J,.USJOB ;JOB # AGAIN
CAME J,.CPJOB## ;CURRENT JOB?
JRST NREM17 ;NO, (VIRCHK) DON'T AFFECT .CPXXX
MOVEM R,.CPADR## ;STORE NEW LOW SEGMENT PROTECTION,,RELOCATION
HLRZM R,.CPREL## ;AND THE HIGHEST RELATIVE ADDRESS IN THE LOW SEGMENT
NREM17: SKIPE .USVRT ;VIRTUAL?
SKIPL P4 ; AND A NON-SHARABLE HIGH SEGMENT?
JRST NREM18 ;NO
PUSHJ P,XPANDH## ;YES, MUST SWAP OUT THE JOB TO GET .USWLP RIGHT
IFN FTMP,<
PUSHJ P,DIFMM## ;GIVE UP AND REMEMBER MM
>
PUSHJ P,WSCHED## ;WAIT UNTIL THE JOB GOES OUT AND COMES BACK IN
IFN FTMP,<
PUSHJ P,UIFMM## ;RESTORE MM
>
NREM18: POP P,T1 ;RESTORE SEGMENT DATA BLOCK ADDR
POP P,J ;RESTORE SEGMENT #
HLRZM R,.USHVA ;FOR ADDRESS CHECKING AT INTERRUPT LEVEL
PJRST FIXMJ1 ;CLEAR THE A.M. AND SKIP RETURN
;SUBROUTINE TO CHANGE A HIGH SEG'S CORE ADDRESSES TO DISK ADDRESSES
;IN THE HIGH SEG MAP. CALLED WITH J=HIGH SEG NUMBER
HCTOD:: SE1ENT ;ENTER S1
PUSHJ P,SAVE4## ;SAVE SOME ACS
PUSH P,J ;AND J
HRRZS J ;CLEAR JUNK
LDB P1,JBYVAD## ;VIRTUAL ADDRESS OF MAP
LDB P2,IMGIN## ;# OF SLOTS IN USE IN MAP
HCTOD1: HLLZ P3,(P1) ;BITS IN P3
HRRZ P4,(P1) ;PAGE # IN P4
LDB P4,[POINT MT.SAD,@[IW MS.MEM,MEMTAB(P4)],^L<MT.DAD>+MT.SAD-1]
IOR P3,P4 ;PUT DISK ADDR IN
TLZ P3,(<PM.ACD>B2!PM.COR) ;CLEAR ACCESSIBILITY
MOVEM P3,(P1) ;STORE UPDATED MAP
SOJLE P2,JPOPJ## ;EXIT IF NO MORE ENTRIES
AOJA P1,HCTOD1 ;YES
SUBTTL UUOCON INTERFACE WITH UUO HANDLER AND IOCSS
$CSUB
;SUBROUTINE TO TEST IF A UUO PAGE-FAULT WILL OCCUR
;ENTER WITH T1=ADR TO BE TESTED
;NON-SKIP RETURN IF A PAGE FAULT WILL OCCUR, CPOPJ1 IF ADR IS OK
;PRESERVES ALL ACS
FLTST:: PUSH P,T1 ;SAVE T1
EXCTUU <MAP T1,(T1)> ;MAP THE PAGE
PUSHJ P,FLTCHK
JRST TPOPJ##
JRST TPOPJ1##
FLTCHK::TLNN T1,(MP.BAD) ;BAD FAIL OR
TLNN T1,(MP.BTS) ; NO INFO?
POPJ P, ;YES TO EITHER, WILL FAULT
JRST CPOPJ1## ;REF OK. WIN.
$HIGH
;CHKIND -- CHECK A USER WORD FOR US TO INDIRECT OFF OF.
;CALL:
; MOVE T1,[USER BYTE POINTER]
; PUSHJ P,CHKIND
; FAIL, ON ADDRESS CHECK OF SOME SORT
; SUCCESS, T1 CONTAINS RESOLVED BYTE POINTER
;TRASHES M
;NOTE - THIS AND CHKBPT WILL HAVE TO BE RE-WRITTEN WHEN AND IF USER-MODE
;EXTENDED ADDRESSING IS IMPLEMENTED, SINCE NEITHER TRY TO SOLVE FOR THAT
;CASE (THINK OF ONE-WORD GLOBAL BYTE POINTERS! YIKES!)
CHKIND::TLNN T1,(17B17) ;CHECK FOR INDEXING FIRST
JRST CHKAT ;NONE, CHECK FOR INDIRECTING
PUSH P,T1 ;SAVE CURRENT ADDRESS
LDB T1,[POINT 4,T1,17] ;EXTRACT AC FROM INDEX FIELD OF WORD
DPB T1,[POINT 4,M,12] ; AND PLACE IT INTO AC FIELD OF A UUO
PUSHJ P,GETTAC## ; SO GETTAC CAN RETURN US THE AC CONTENTS
HRRZS T1 ;USE RIGHTMOST 18 BITS OF AC ONLY
ADD T1,(P) ;SIMULATE INDEXING BY ADDING RH TO ADDRESS
POP P,(P)
CHKAT: TLNN T1,(1B13) ;INDIRECT BIT ON?
JRST CPOPJ1## ;NOPE - ADDRESS IS RESOLVED
HRRI M,(T1) ;ADDRESS (RH ONLY) FOR GETWRD TO USE
PUSHJ P,GETWRD## ;GET THE WORD, DOING ALL CHECKS
POPJ P, ;ADDRESS CHECK - LET CALLER HANDLE THIS
PUSHJ P,SCDCHK## ;GIVE OTHER JOBS A CHANCE, AND USER A CHANCE
; TO ^C OUT OF THIS (IF HE GAVE US A LOOP).
JRST CHKIND ;START OVER AGAIN, WITH NEW ADDRESS
;CHKINS -- CHECK A USER WORD FOR US TO INDIRECT OFF OF.
;CALL:
; MOVE T1,[USER INSTRUCTION WORD]
; PUSHJ P,CHKINS
; <ERROR RET> ADDRESS CHECK OF SOME SORT
; <SKIP RETURN> ON SUCCESS
;ON SUCCESS RETURN, T1 CONTAINS RESOLVED ADDRESS AND T2 CONTAINS SECTION OF
; REFERENCE (USEFUL WHEN T1 POINTS TO AN AC). LH(T2) INDICATES WHETHER
; REFERENCE WAS GLOBAL OR LOCAL.
;PRESERVES ALL OTHER ACS
;IMPLICITLY USES PCS -- CALL AT CHKINX WITH SECTION-NESS IN T2 TO OVERRIDE
;FOR REAL INDIRECT WORDS (RATHER THAN INSTRUCTION WORDS), THERE ARE ANALOGOUS
;ROUTINES NAMED CHKEFI AND CHKEFX.
CHKINS::
IFN FTXMON,XSFM T2 ;GET DEFAULT SECTION OF REFERENCE
CHKINX::SE1ENT ;SPEED UP GETEWD SLIGHTLY
IFN FTXMON,PUSHJ P,SAVE2## ;FOR SCRATCH ACS
PUSH P,M ;SAVE PRESERVED AC
IFN FTXMON,< ;HARD CASES ONLY FOR MULTI-SECTION MACHINES
ANDI T2,(SECMSK) ;KEEP ONLY SECTION NUMBER FROM XSFM
CIFIW: PUSH P,T1 ;SAVE FOR LATER INDIRECTION CHECK
SETZM P2 ;REMEMBER DOING IFIW
HRRZ P1,T1 ;GET Y FIELD
LDB M,[POINT 4,T1,12] ;AND X FIELD
HRLI T1,(T2) ;INCLUDE SECTION IN CASE NO INDEXING
JUMPE M,CIFIW6 ;GO TEST INDIRECTION IF NOT
PUSHJ P,GETWDU## ;YES, FETCH INDEX REGISTER CONTENTS
MOVE M,T1 ;SCRATCH COPY
JUMPE T2,CIFIW2 ;IF SECTION 0 INDEX
JUMPL M,CIFIW2 ;OR LH(X) .LT. 0
TLNN M,-1 ;OR LH(X) .EQ. 0
CIFIW2: TLZA T1,-1 ;THEN ONLY 18-BITS OF INDEXING
HRRE P1,P1 ;ELSE SIGN-EXTEND Y TO 36-BITS
ADD T1,P1 ;DO THE INDEXING
JUMPE T2,CIFIW4 ;IF SECTION 0
JUMPL M,CIFIW4 ;OR LH(X) .LT. 0
TLNN M,-1 ;OR LH(X) .EQ. 0
JRST CIFIW4 ;THEN LOCAL INDEXING
SETOM P2 ;FLAG GLOBAL INDEXING
CAIA ;DON'T DIDDLE SECTION
CIFIW4: HRLI T1,(T2) ;E STAYS IN LOCAL SECTION
TLZ T1,770000 ;30-BIT ADDRESSING
HLR T2,T1 ;SAVE SECTION FOR NEXT ITERATION
;CHECK IFIW INDIRECTION
SKIPE P2 ;LOCAL INDEXING?
TDNN T1,[^-1,,^-17] ;NO, GLOBAL REFERENCE TO AC?
CIFIW6: TRNE T1,^-17 ;IS LOCAL REFERENCE TO A REGISTER?
CAIA ;NO, MEM. REF.
ANDI T1,17 ;YES, REDUCE TO OBVIOUS AC (SECTION-NESS IN T2)
POP P,M ;GET BACK ORIGINAL WORD
TLNN M,20 ;IFIW I BIT ON?
JRST CEFIW9 ;NO, CHECK OUT AC'S AND RETURN
CIFIW8: PUSHJ P,SCDCHK## ;YES, ALLOW USER TO ^C AND/OR SYSTEM TO SCHEDULE
MOVE M,T1 ;GET ADDRESS OF NEW ADDRESS
PUSHJ P,GETEWD## ;FETCH IT
JRST MPOPJ## ;PROPAGATE FAILURE
CIFIW9: JUMPE T2,CIFIW ;ONCE IN SECTION 0, ALWAYS HAVE IFIW'S
JUMPGE T1,CEFIW ;EFIW IF NOT MARKED AS IFIW
TLNN T1,(1B1) ;MAKE SURE NOT RESERVED FORMAT
JRST CIFIW ;NO, JUST ANOTHER IFIW
JRST MPOPJ## ;YES, GIVE FAILURE RETURN
CHKEFI::XSFM T2 ;SETUP DEFAULT SECTION OF REFERENCE
CHKEFX::PUSHJ P,SAVE2## ;GET SOME SCRATCH ACS
PUSH P,M ;SAVE PRESERVED AC
ANDI T2,(SECMSK) ;KEEP ONLY SECTION NUMBER FROM XSFM
JRST CIFIW9 ;DISPATCH ON TYPE OF INDIRECTION
CEFIW: PUSH P,T1 ;SAVE FOR LATER INDIRECTION CHECK
SETOM P2 ;EFIW'S GIVE GLOBAL RESULTS
LDB M,[POINT 4,T1,5] ;LOAD EFIW X FIELD
TLZ T1,770000 ;Y FIELD ONLY IN T1
MOVE P1,T1 ;SCRATCH COPY
JUMPE M,CEFIW6 ;SKIP INDEXING IF NO INDEX REGISTER
PUSHJ P,GETWDU## ;FETCH CONTENTS OF INDEX REGISTER
ADD T1,P1 ;INDEX THE Y FIELD
TLZ T1,770000 ;30-BIT ADDRESSING
;CHECK EFIW INDIRECTION
CEFIW6: POP P,M ;GET BACK ORIGINAL WORD
HLR T2,T1 ;KEEP SECTION OF REFERENCE FOR RETURN
TLNE T1,(1B1) ;CHECK EFIW I BIT
JRST CIFIW8 ;ITERATE IF ON
;CHECK OUT RETURN VALUE IF NOT
;CHECK AC ADDRESSING AND VALIDATE RANGE
CEFIW9: TLNE T1,^-<(SECMSK)> ;CHECK THAT FINAL ADDRESS IS LEGAL
JRST MPOPJ## ;FAIL IF NOT
HRL T2,P2 ;GET EA-IS-GLOBAL FLAG IN LH(T2)
TDNN T1,[^-1,,^-17] ;AC REFERENCE?
SKIPN T2 ;FROM NON-ZERO SECTION?
JRST MPOPJ1## ;NO, JUST RETURN SUCCESSFULLY
HRLI T1,1 ;YES, MAKE PROPER GLOBAL AC REFERENCE
JRST MPOPJ1## ;GIVE SUCCESS RETURN
> ;END OF IFN FTXMON
IFE FTXMON,< ;EASY CASE FOR NON-EXTENDED MACHINES
CHKIN0: PUSHJ P,CHKIND ;DO AN EA-CALC
JRST MPOPJ## ;PROPAGATE FAILURE
SETZ T2, ;RETURN SECTION NUMBER
ANDI T1,-1 ;CLEAR NON-ADDRESS BITS
JRST MPOPJ1## ;RETURN SUCCESS
CHKEFI==:CHKINS ;NO DIFFERENCE ON S0-ONLY MACHINE
CHKEFX==:CHKINX ;DITTO
> ;END OF IFE FTXMON
;CHKBPT -- RANGE CHECK A BYTE POINTER AFTER RESOLVING INDIRECT AND INDEXING
;CALL IS:
;
; MOVE T1,[BYTE POINTER TO USER VIRTUAL SPACE]
; MOVEI T2,NUMBER OF BYTES
; PUSHJ P,CHKBPT
; ON ADDRESS CHECK
; ON SUCCESS, T1 CONTAINS RESOLVED BYTE POINTER
;TRASHES M
;WILL NOT WORK ON A KI OR A KA.
CHKBPT::PUSHJ P,SAVE2## ;GET SOME PRESERVED REGISTERS
LDB P2,[POINT 6,T1,5] ;GET P FIELD OUT OF BYTE POINTER
CAILE P2,44 ;IF IT IS GREATER THAN WORD SIZE, IT IS OWGBP
POPJ P, ;ERROR RETURN.
MOVE P2,T2 ;SAVE BYTE COUNT
HRLZI P1,777740 ;FIELD CONTAINING BYTE SIZE AND COUNT
AND P1,T1 ;GET BYTE SIZE AND COUNT INTO SAVED REGISTER
XOR T1,P1 ;WIPE SAID BITS IN T1 (FIGURE THIS ONE OUT!)
PUSHJ P,CHKIND ;RESOLVE INDIRECTION AND INDEXING IN ADDRESS
POPJ P, ;ADDRESSING ERROR OF SOME SORT
IOR P1,T1 ;ADD IN RESOLVED ADDRESS TO BYTE SIZE AND COUNT
ADJBP P2,P1 ;GET A BYTE POINTER TO THE END OF THE STRING
TLZ P2,-1 ;MAKE IT BE NOTHING BUT AN ADDRESS
MOVEI M,1 ;1 BYTE
ADJBP M,P1 ;GET POINTER TO FIRST BYTE (SINCE ILDB POINTER)
CHKBPN: TLZ M,-1 ;MAKE IT BE AN ADDRESS
PUSHJ P,GETWRD## ;TRY TO GET THE WORD (CALL PFH MAYBE)
POPJ P, ;CAN'T, ERROR RETURN
TRO M,PG.BDY ;POINT M AT THE LAST WORD IN THAT PAGE
AOJ M, ;MAKE THAT THE FIRST WORD IN THE NEXT PAGE
CAIG M,(P2) ;WAS THE END OF STRING IN THAT PAGE?
JRST CHKBPN ;NO, TRY THE NEXT PAGE
MOVE T1,P1 ;GET BYTE POINTER TO RETURN
JRST CPOPJ1## ;SUCCESS RETURN
;BRNGE -- RANGE CHECK A USER I/O BUFFER
;CALL IS:
;
; MOVX T1,<BUFFER>
; PUSHJ P,BRNGE
; RETURN
;
;WHERE <BUFFER> IS THE USER VIRTUAL ADDRESS OF THE .BFHDR WORD OF THE
;USER BUFFER (THE SECOND WORD OF THE BUFFER HEADER).
;
; *** MAY ONLY BE CALLED AT UUO LEVEL ***
;
;IF AN I/O-ILLEGAL ADDRESS IS GIVEN (IN PROTECTED JOBDAT OR IN USER'S
;HIGH SEGMENT) BRNGE DISPATCHES TO ADRERR TO GIVE AN ADDRESS CHECK; IF A
;PAGE FAULT OCCURS (ACCESS ALLOWED OFF OR PAGED OUT) BRNGE DISPATCHES TO
;THE PAGE FAULT HANDLER (WHICH WILL IN TURN RE-EXECUTE THE UUO . . .);
;IF A NONEXISTANT ADDRESS IS ENCOUNTERED BRNGE DISPATCHES TO ADRERR.
;
;ON RETURN THE ENTIRE BUFFER IS ADDRESSABLE.
;
;USES T1 AND T2.
BRNGE:: EXCTUX <HLRZ T2,(T1)> ;GET BUFFER SIZE (DATA SIZE + 1)
TRZ T2,IOUSE ;REDUCE TO COUNT ALONE
SUBI T1,1 ;T1:=START OF BUFFER AREA (.BFSTS WORD)
ADDI T2,1(T1) ;T2:=END OF BUFFER
;FALL INTO LRNGE
;LRNGE -- RANGE CHECK A BLOCK OF USER ADDRESS SPACE (I/O)
;TRNGE -- RANGE CHECK A BLOCK OF USER ADDRESS SPACE (NON-I/O)
;CALL IS:
;
; MOVX T1,<FIRST>
; MOVX T2,<LAST>
; PUSHJ P,LRNGE/TRNGE
; RETURN
;
;WHERE <FIRST> IS THE FIRST ADDRESS OF THE BLOCK TO BE ADDRESS CHECKED,
;AND <LAST> IS THE LAST ADDRESS OF THE BLOCK TO BE ADDRESS CHECKED.
;
; *** MAY ONLY BE CALLED AT UUO LEVEL ***
;
;IF ANY ADDRESS WITHIN THE RANGE <FIRST> TO <LAST> INCLUSIVE IS NOT
;I/O-LEGAL LRNGE WILL DISPATCH TO ADRERR (TRNGE WILL IGNORE); IF ANY
;ADDRESS WOULD CAUSE A PAGE FAULT (EITHER ACCESS ALLOWED OFF OR PAGED
;OUT) BOTH LRNGE AND TRNGE DISPATCH TO THE PAGE FAULT HANDLER (WHICH
;WILL RE-EXECUTE THE USER UUO); IF AN ADDRESS IS ENCOUNTERED WHICH
;IS NON-EXISTANT BOTH LRNGE AND TRNGE DISPATCH TO ADRERR.
;
;ON RETURN THE ENTIRE RANGE IS ADDRESSABLE.
;
;USES T1 AND T2.
LRNGE:: TLNE T2,-1 ;IF BUFFER WRAPS AROUND CORE
S0JRST ADRERR## ; IT'S AN ADDRESS ERROR
TLO T2,400000 ;INDICATE CALL TO LRNGE
TRNGE:: CAILE T1,(T2) ;IF BUFFER WRAPS AROUND CORE
JRST UADERR## ;IT'S AN ADDRESS ERROR
XRNGE: JUMPGE T2,TRNGE1 ;IF CALL TO LRNGE ENSURE I/O LEGAL ADDR
PUSHJ P,IADRCK## ;LEGAL ADDRESS?
S0JRST ADRERR## ;NO, PAGE DOESN'T EXIST, HI SEG PAGE, OR SPY PAGE
JRST UUOFLT ;PAGE FAULT
TRNGE1: EXCTUX <SKIP (T1)> ;ENSURE ADDRESS IS ACCESSIBLE AND WRITABLE
ERJMP UUOFLT ;IF NOT, CHECK FOR PAGE FAULT
TRO T1,PG.BDY ;HIGHEST ADR IN THE PAGE
CAIL T1,(T2) ;CHECKED ALL REQUIRED PAGES?
POPJ P, ;YES, RETURN
ADDI T1,PAGSIZ ;NO, STEP TO NEXT PAGE
JRST XRNGE ;AND TEST IT
;SUBROUTINE TO CHECK A RANGE OF ADDRESSES, CALLED FROM ANY LEVEL
;RETURNS CPOPJ IF SOME ADR NOT IN CORE (PAGE FAULT OR NON-EXISTANT)
;RETURNS CPOPJ1 IF EVERYTHING IS OK
ZRNGE:: TRO T1,PG.BDY ;TOP ADR IN PAGE
PUSH P,T2 ;SAVE T2 FROM IADRCK
ZRNGE1: PUSHJ P,IADRCK## ;MAKE SURE PAGE LEGAL AND IN CORE
PJRST T2POPJ## ;ILLEGAL ADR ERR
PJRST T2POPJ## ;PAGE FAULT
CAML T1,(P) ;LEGAL, DONE?
PJRST T2POJ1## ;YES, GOOD RETURN
ADDI T1,PAGSIZ ;NO, STEP TO NEXT PAGE
JRST ZRNGE1 ;AND TEST IT
;SUBROUTINE TO TEST IF AN ADDRESS WILL GIVE A PAGE FAULT
;ENTER J= JOB NUMBER, R=RELOACATION, RH(M)=ADR TO TEST
;SKIP-RETURNS IF ADR IS OK OR WILL GIVE AN ADRESS ERROR
;DISPATCHES TO PAGE-FAULT HANDLER IF LEGAL, PAGE NOT IN CORE
; AND AT UUO LEVEL (NOT PI OR SCHEDULER)
;NON-SKIP RETURN IF PAGE-FAULT TYPE ADDRESS, NOT AT UUO LEVEL
;PRESERVES ALL ACS
$CSUB
FLTSX: PUSH P,T1 ;SAVE ACS
LDB T1,[POINT 23,M,35] ;GET ADDRESS
FLTSX2: PUSHJ P,FLTST
JRST FLTSX3 ;NO, CHECK IF AT UUO LEVEL
PJRST TPOPJ1## ;AND GIVE OK RETURN
;HERE ON A PAGE-FAULT
FLTSX3: CONSO PI,PI.IPA ;PI LEVEL?
SKIPE .CPISF## ;NO, IN SCHEDULER?
JRST TPOPJ## ;YES, ERROR RETURN
CAMN J,.CPJOB## ;NO, IS THIS THE RUNNING JOB?
JRST @[MCSEC0+UUOFLT] ;YES, CALL PFH
PJRST TPOPJ## ;ERROR
;HERE IF PAGE FAULT FROM GETWRD AND FRIENDS
FLTSY:: PUSH P,T1 ;SAVE ACS
MOVE T1,.USPFW ;GET PAGE FAIL WORD
PJRST FLTSX2 ;AND FAULT
$HIGH
;SUBROUTINE TO INCREMENT JOBPD1
INCPD1::HRRZ T2,.JDAT+JOBPD1##+1 ;JOBPD1
ADDI T2,1 ;+1 (CAN'T AOS, SINCE MIGHT = -1)
HRRM T2,.JDAT+JOBPD1##+1 ;STORE BACK
POPJ P, ; AND RETURN
;SUBROUTINE TO CHECK ARGUMENTS TO A UUO
;ENTER T1=C(AC) T3=CHECK-BITS FOR THE UUO
;CALLS PAGE FAULT HANDLER IF ERROR WILL OCCUR, RETURNS IF OK
;PRESERVES T1,T4
UUOCHK::MOVE T2,JBTSTS##(J) ;GET JBTSTS FOR JOB
TRNE T2,JS.ASA ;JS.ASA ON?
POPJ P, ;YES, MONITOR KNOWS WHAT ITS DOING (???)
PUSH P,T1 ;NO, SAVE T1
TRNE T3,UU.EA+UU.LER;EFFECTIVE ADR CHECK?
SKIPA T2,T1 ;YES, GET ADR
MOVE T2,.JDAT+JOBPD1##+1 ;NO, GET LOC OF UUO
TRNE T3,UU.CEA+UU.LER ;CHECK C(ADR)?
JRST UUOCH1 ;YES
TRNN T3,UU.CAC ;NO, CHECK C(AC)?
LDB T1,[POINT 6,T3,35] ;NO, GET NO OF ARGS FROM T3
JRST UUOCH2 ;AND CONTINUE
;HERE TO CHECK ADR
UUOCH1: PUSH P,M ;SAVE M
HRR M,T1 ;LOC TO CHECK
PUSHJ P,GETWRD## ;GET C(EA)
JRST UUOCH3 ;BAD - CALL PFH
POP P,M ;RESTOR M
TRNE T3,UU.LER ;LOOKUP/ENTER/RENAME?
TLNN T1,-1 ;YES, LH=0?
TRZA T1,770000 ;YES, NUMBER OF ARGS ALREADY IN T1, CLEAR FUNNY BITS
MOVEI T1,3 ;NO, CHECK 4 WORDS (TO ADR+3)
UUOCH2: TRNE T3,UU.MNS ;MINUS N?
MOVNS T1 ;YES
TRNN T3,UU.LFT ;NO OF ARGS IN LH?
TLZA T1,-1 ;NO, CLEAR LH
HLRZS T1 ;YES, USE LH
EXCH T1,T2 ;GET 1ST ADR, SAVE NUMBER
TLZ T1,-1
SKIPN T1 ;GET TOP ADR (A+N-1) IN T2
AOSA T2,T1
ADDI T2,(T1)
TRNN T3,UU.LER
SUBI T2,1
PUSHJ P,XRNGE ;ALL PAGES IN CORE?
PJRST TPOPJ## ;YES, RETURN
;HERE WHEN ADR ITSELF ISN'T IN CORE
UUOCH3: HRRZ T1,M ;BAD ADR IN T1
POP P,M ;RESTORE M
PJRST UUOFLT ;AND CALL PFH
;HERE IF ARGUMENT NOT IN CORE - PAGE FAULT WILL OCCUR IF UUO PROCEEDS
;T1= BAD ADDRESS
UUOFL1: POP P,(P) ;MAKE THE LIST RIGHT
UUOFLT::NTGIVE ;RETURN THE NETSER INTERLOCK.
IFN FTMP,<
PUSHJ P,TGVMM## ;OWN THE MM?
>
LDB T3,[POINT UPGWID+9,T1,35] ;ADDR
TLO T3,(PF.BAD) ;INDICATE THIS IS FROM A UUO
DMOVE T1,.JDAT+JOBPD1## ;ADDR OF UUO
SOS T2 ;(NOT RETURN PC)
MOVE J,.CPJOB## ;SET UP J
TLNE T1,(XC.USR) ;LOSE IF NOT USER MODE (COMCON)
PUSHJ P,USRFL1 ;CALL PFH (GENERALLY DOESN'T RETURN)
PJRST UADERR##
;HERE ON A TIME INTERRUPT
TIMFLT::MOVE P,[XWD MJOBPD##+2,.JDAT+JOBPDL##+2] ;SET UP P
MOVE J,.CPJOB## ;SET UP J
SETZ F, ;MAKE SURE F DOESN'T CONTAIN CRUD AT USER EXIT
PUSHJ P,FNDPDB## ;GET THE PDB
JRST USRXIT ;IF NO FAULT DATA-IGNORE INTERRUPT
DMOVE T1,.USPFP ;GET PC
DMOVEM T1,.JDAT+JOBPD1## ;SAVE PC (IN JOBPD1)
HRRZ T3,.PDTMI##(W) ;RESET COUNTER--THIS MUST BE DONE AFTER
JUMPE T3,TIMFL1
MOVEM T3,.PDTMC##(W) ; RESET OF JOBPD1 TO PROTECT PSISER
MOVEI T3,0 ;INDICATE TIME INTERRUPT
PUSHJ P,USRFL1 ;CALL PFH
JRST USRXIT## ;CANT GET PFH - IGNORE INTERRUPT
;HERE IF USER HASN'T ENABLED FOR TIME INTERRUPTS
;RECOMPUTE THE FAULT-RATE AND DISMISS THE INTERRUPT
TIMFL1: MOVEI P1,1 ;USE 1 PAGE AS BASIS
PUSHJ P,USRATE ;COMPUTE NEW PAGE-INTERVAL
MOVE T1,TICSEC## ;RECOMPUTE IN 1 SECOND
MOVEM T1,.PDTMC##(W)
PJRST USRXIT## ;GO RESTART USER JOB
;T4=PC WORD, T3=PAGE FAIL WORD
USRFLT::TDZA T4,T4 ;NORMAL ENTRY
USRFL1: MOVEI T4,USRFLY-USRFLZ
PUSHJ P,USRFLZ(T4) ;SUBROUTINE, SO CAN SET UP MAP
POPJ P, ;JUST RETURN
USERAC ;GIVE HIM BACK HIS ACS
XJEN .USMUO ;RETURN TO USER
USRFLZ: TLNE T3,(PF.BAD) ;"BAD" TYPE FAULT?
POPJ P, ;YES, TOO BAD
MOVE J,.CPJOB## ;NO, SET J
TLNN T3,(PF.ACC) ;IF PAGE IS ACCESSIBLE, THIS MUST BE A HISEG.
SKIPA R,.CPADR## ;NO, SET UP R
JRST [PUSHJ P,WLPFLT ;YES, HANDLE SPECIALLY
POPJ P, ;REALLY A WRITE VIOLATION
USERAC ;GIVE HIM HIS ACS BACK
XJRSTF .USPFP] ;RETURN TO THE USER - PAGE IS WRITE ENABLED
;USRFLY - SOME COMMENTS: BIT PF.BAD, WHICH IN A NORMAL PAGE FAIL WORD IS USED
; TO INDICATE A "BAD" FORM OF PAGE FAIL (PAGE FAIL CODE .GT. 20), IS
; USED HERE TO INDICATE CALL FROM MONITOR UUO. USRFLT WILL NOT CALL US
; IF THE BIT IS LIT, AND UUOFLT WILL ALWAYS LIGHT IT.
;
; ALSO, BIT VM.ZER IS THE LOW ORDER BIT OF THE PAGE FAIL ADDRESS. THE
; LOW ORDER BITS OF THE PF ADDRESS ARE NEVER USED, SO USING THIS BIT
; IS LEGAL.
USRFLY: DMOVEM T1,.USMUO ;SAVE PC DBLWRD
SKIPN .JDAT+.JBPFH## ;DO WE HAVE A PFH?
JRST PFH## ;CALL PFH (GENERALLY DOESN'T RETURN)
JUMPE T3,USRFL2 ;GO IF A TIME INTERRUPT
LDB T4,[POINT UPGWID,T3,26] ;NOT TIME, GET VIRT PAGE NO.
IFN FTXMON,<
TRNN T4,<MXSECN_S2PLSH> ;IS THIS AN EXTENDED PAGE?
TLNE T2,MXSECN ;OR IS THE PC EXTENDED?
JRST USRFLE ;YES, ILL MEM REF
>
MOVEI T1,(T3) ;GET PAGE FAULT ADDR AGAIN
LSH T1,W2PLSH ;CONVERT TO PAGE #
S1PSHJ GTPME ;GET MAP CONTENTS
JUMPE T2,CPOPJ## ;GO IF NO PAGE
TLZ T2,(PM.NAD)
CAMN T2,[PM.ZER] ;PAGE EXISTS, IS IT ABZ?
VM.ZER==1 ;NAME A BIT. INSIGNIFICANT BIT OF PF ADDRESS
TROA T3,VM.ZER ;YES, REMEMBER THAT
TRZ T3,VM.ZER ;NO
USRFL2: PUSHJ P,FNDPDS## ;FIND PDB FOR JOB
HRRZ T1,.JDAT+.JBPFH## ;GET ADR OF PFH
JUMPE T1,GETPFH ;LOAD DEFAULT IF NONE THERE
CAIL T1,JOBPFI## ;PFH REALLY THERE?
PUSHJ P,FLTST
POPJ P, ;NO, CAN'T DO ANYTHING
ADDI T1,5 ;POINT TO TOP LOC TO STORE IN
PUSHJ P,FLTST ;IS TOP OF BLOCK THERE?
POPJ P, ;NO, CAN'T DO GOOD THINGS FOR HIM
USRFL3: JUMPE T3,USRFL4 ;IF NOT A TIME INTERRUPT,
LDB T1,[POINT UPGWID,T3,26] ;GET VIRTUAL PAGE
HRL T3,T1 ;SAVE IN LH(T3)
PUSHJ P,TSWST ;IS PAGE IN WORKING SET?
JRST USRFL5 ;NO
MOVSI T2,(PM.AAB)
TDNE T2,.UPMAP(T1)
STOPCD .+1,DEBUG,WAD, ;++WSBTBL AND AABTBL DISCREPENCY
MOVEI T1,PC.PNA ;YES, SET REASON = PAGE NOT ACCESSABLE
MOVSI T2,(UP.SAA) ;SET ACCESS ALLOWED AUTOMATICALLY BIT
TDNN T2,.USBTS ;SHOULD WE SET A.A.?
JRST USRFL6 ;NO, GIVE FAULT TO PFH
HLRZ T1,T3 ;PAGE NUMBER, SIGN BIT SAYS SET A.A.
PUSHJ P,SCAABT ;TURN ON ACCESS ALLOWED
PUSHJ P,ADJANA ;MAKE .UPANA AND .UPVRT RIGHT
JRST USRFLX ;CONTINUE PROGRAM EXECUTION
USRFL4: MOVEI T1,PC.TIM ;SET REASON = TIME FAULT
JRST USRFL6 ;AND CONTINUE
;HERE IF PAGE NOT IN WORKING SET
USRFL5: MOVEI T1,PC.PNC ;REASON = PAGE NOT IN CORE
TLNE T3,(PF.BAD) ;IF FAULT FROM A UUO,
MOVEI T1,PC.UUO ; REASON = UUO FAULT
TRNN T3,VM.ZER ;ALLOCATED BUT ZERO PAGE?
JRST USRFL6 ;NO
ADDI T1,PC.AZM-PC.UUO ;YES, INCEMENT REASON BY 3
HLRZ T2,T3
MOVSI T4,(PM.AAB)
IORM T4,.UPMAP(T2)
USRFL6: HLL T1,T3 ;VIRTUAL PAGE IN LH(T1)
HRRZ M,.JDAT+.JBPFH## ;GET ADR OF PFH
PUSH P,T1 ;SAVE PAGE,,REASON
GETPC T1,.USMUO ;GET SINGLE WORD PC (MUST BE S0)
PUSHJ P,PUTWD1## ;SAVE PC IN WORD 1
POP P,T1 ;RESTORE PAGE,,REASON
MOVE T2,.USBTS
TLZE T2,(UP.WHC) ;WORKING SET CHANGED?
TLO T1,(PC.WHC)
TLZE T2,(UP.WSS) ;WORKING SET SCRAMBLED?
TLO T1,(PC.WSS)
MOVEM T2,.USBTS
PUSHJ P,PUTWD1## ; IN WORD 2
HRRZ P1,T1 ;SAVE REASON
MOVE T1,.PDTTM##(W) ;GET TIME
SKIPE .USFFT ;FIRST FAULT?
JRST USRFL7 ;NO
HRRZS .PDVRT##(W) ;CLEAR FAULT INTERVAL
MOVEM T1,.USFFT ;YES, SAVE AS FIRST FAULT TIME
USRFL7: SUB T1,.USFFT ;COMPUTE VIRTUAL TIME
IMULI T1,^D1000 ;CONVERT TO MILLISECS
IDIV T1,TICSEC##
PUSHJ P,PUTWD1## ;SAVE VIRT TIME IN WD 3
CAIN P1,PC.TIM ;TIME INTERRUPT?
PUSHJ P,PGRUPD ;YES, CALL PAGE RATE UPDATE ROUTINE
CAIE P1,PC.TIM ;TIME INTERRUPT?
CAIN P1,PC.PNA ;OR PAGE NOT IN AABTAB?
SKIPA P1,[1] ;COUNT IN RH FOR "NON-REAL" FAULTS
;HERE ON A TIME OR ACCESS-ALLOWED FAULT
MOVSI P1,1 ;COUNT IN LH FOR "REAL" FAULTS
ADDM P1,.USVCT ;COUNT FAULT IN UPMP
ADDM P1,SYSVCT## ;COUNT SYSTEM FAULTS
MOVE T1,J ;GET JOB #
PUSHJ P,FPDBT1##
TDZA T1,T1 ;HUH?
MOVE T1,.PDVRT##(T1)
PUSHJ P,PUTWD1## ;STORE IN WD 4
PUSHJ P,PSIIVA## ;GET INTERRUPT VECTOR ADDR
PUSHJ P,PUTWD1## ; AND STORE FOR USER WD 5
SUBI M,5 ;POINT BACK TO START OF BLOCK
PUSHJ P,GETWDU## ;GET ADR OF PFH
HLL T1,.USMUO ;GET FLAGS
TLZ T1,(IC.BIS+IC.ATN+IC.LIP) ;CLEAR TRAP BITS, BIS
TLO T1,USRMOD ;BE SURE PFH RUNS IN USER MODE
PUTPC T1,.USMUO ;SAVE FULL WORD S0 PC OF PFH
PUSHJ P,CLRASA## ;CLEAR JS.ASA
SKIPN .CPTMF## ;DID THE CLOCK TICK?
JRST CPOPJ1## ;NO -- GO TO THE USER
MOVE T1,JBTSTS##(J) ;YES -- GET JOB STATUS
PUSHJ P,USCHD1## ;RESCHEDULE
JRST CPOPJ1## ;GO TO THE USER
IFN FTXMON,<
;FAIL BECAUSE A PROGRAM WITH A PFH IS RUNNING EXTENDED.
USRFLE: PUSHJ P,INLMES## ;TYPE A MESSAGE AT HIM
ASCIZ \?Extended page fail, cannot be passed to user PFH\
>
POPJ P,
;SUBROUTINE TO WRITE ENABLE A PAGE IF ITS WRITE LOCKED
;CALL WITH T1=VIRTUAL ADDRESS TO BE WRITE ENABLED, ALWAYS RETURNS CPOPJ
CHKWLP::SKIPN .USWLP ;NOT WRITE LOCKED IF NOT VIRTUAL
POPJ P, ;SAVE SOME TIME
PUSH P,T1 ;SAVE ADDRESS
EXCTUU <MAP T1,(T1)> ;MAP THE VIRTUAL ADDRESS
PUSHJ P,FLTCHK ;BAD PAGE?
STOPCD TPOPJ##,DEBUG,BDP, ;++BAD PAGE
TLNE T1,(PM.WRT) ;PAGE WRITABLE ALREADY?
JRST TPOPJ## ;YES, NOTHING TO DO
EXCH T3,(P) ;ARGUMENT FOR WLPFLT
PUSHJ P,WLPFLT ;WRITE ENABLE THE PAGE
STOPCD TPOPJ##,DEBUG,CWP, ;CAN'T WRITE-ENABLE PAGE
JRST T3POPJ## ;RESTORE T3 AND RETURN
;HERE WHEN THE PAGE FAULT IS A WRITE VIOLATION
WLPFLT::SE1ENT ;MUST BE IN SECTION 1 TO MAKE PAGE REFERENCES
PUSH P,J ;SAVE J
MOVE J,.USJOB ;NEED J TO BE SETUP FOR TPNHX
MOVE T1,T3 ;PAGE FAIL WORD
LSH T1,W2PLSH ;PAGE #
ANDI T1,HLGPGS ;CLEAR EXTRANEOUS JUNK
MOVSI T4,UWPOFF ;BIT TO TEST IF PAGE IN HIGH SEG
PUSHJ P,TPNHX ;IS PAGE IN A HIGH SEG?
TDNE T4,.HBSGN(T2) ;YES, IS SEGMENT WRITABLE?
CAIA ;NOT IN A HIGH SEGMENT OR WRITABLE
JRST JPOPJ## ;IN A WRITE LOCKED HIGH SEGMENT
IFN FTPEEKSPY,<
PUSHJ P,TSSPT ;A SPY PAGE?
CAIA ;NO, OK TO WRITE ENABLE IT
JRST JPOPJ## ;YES, CAN'T WRITE ENABLE PAGE
>
SKIPE .USWLC ;DID USER WRITE-LOCK SOME PAGES?
JRST JPOPJ## ;YES, MONITOR CAN'T HAVE THEM THEN
MOVE T1,T3 ;GET PAGE FAIL PAGE AGAIN
LSH T1,W2PLSH
ANDI T1,HLGPGS ;CLEARING JUNK
PUSHJ P,GTPME ;GET POINTER
TLNE T2,(<PM.ACD>B2) ;MAKE SURE ITS ACCESSIBLE
TLOE T2,(PM.WRT) ;MAKE PAGE WRITABLE
STOPCD JPOPJ##,DEBUG,PAW, ;PAGE ALREADY WRITE-ENABLED
MOVEM T2,(T4)
SKIPN .USWLP ;DON'T OWN ANY DSK SPACE IF NO WL PAGES
JRST WLPFL1 ;SKIP ON
AOS SYSWLF## ;COUNT NUMBER OF MODIFIED PAGE FAULTS
PUSHJ P,RTNDPG ;RETURN SWAPPING SPACE
WLPFL1: POP P,J ;RESTORE J
USRFLX: CLRPGT
JRST CPOPJ1## ;TRY, TRY AGAIN
GETPFH: PUSH P,T3 ;SAVE T3
MOVSI T1,(UP.MPF)
IORM T1,.USBTS
MOVSI T1,'PFH' ;GO GET SYS:PFH.VMX
MOVEI T2,0 ;TOP LOC = -1
PUSHJ P,GETXXX ;LOAD PFH
JRST [POP P,(P) ;CANT GET IT -ERROR
PJRST CNGPFH]
MOVSI T1,(UP.MPF)
ANDCAM T1,.USBTS
MOVEM T2,.JDAT+.JBPFH## ;SAVE TOP,,START
MOVSI T3,(UP.MGP) ;INDICATE MONITOR GOT PFH
IORM T3,.USBTS
PUSHJ P,EXOPFH ;SEE IF PFH SHOULD BE CONCEALED
HRRZS .USFFT ;FIRST FAULT TIME = 0
MOVE T3,MAXINT## ;PRETEND NO FAULTS FOR A LONG TIME
MOVE T1,J
PUSHJ P,FPDBT1##
CAIA
HRLM T3,.PDVRT##(T1) ;ALLOW SEVERAL TO GET
; THE PROGRAM STARTED UP.
POP P,T3 ;RESTORE T3
LDB T1,[POINT 9,T3,26] ;VIRTUAL PAGE
LSH T1,P2WLSH ;CONVERT TO AN ADR
MOVE T2,.JDAT+.JBPFH## ;RESTORE T2
HLRZ T4,T2 ;TOP OF PFH
CAIL T1,(T2) ;WAS FAULT FOR AN ADR WHICH WE HAVE CHANGED
CAILE T1,(T4) ; BY READING PFH OVER IT?
JRST USRFL3 ;NO, CONTINUE
TLNN T3,(PF.BAD) ;YES, WAS IT A UUO?
JRST USRFLX ;NO, GO READ CURRENT CONTENTS
POPJ P, ;YES, UUO ERROR
;HERE TO READ SYS:DDT.VMX
GETDDT::GETPC T1,USRPC##
TLNN T1,(XC.USR)
GETPC T1,.JDAT+JOBPD1##
MOVEM T1,.JDAT+JOBOPC##
PJSP T2,MSTART## ;SET UP ACS
;
JSP T1,MONSTR## ;START JOB
MOVE T1,[SIXBIT /VMDDT/] ;LOAD SYS:VMDDT.EXE
MOVEI T2,700000 ;WHERE TO PUT IT
;AS IF IT REALLY MATTERS
PUSHJ P,GETXXX ;GO GET IT
SKIPA ;ERROR
JRST GETDD2 ;GOT IT
PUSHJ P,CNGDDT ;PRINT ERROR MESSAGE
PUSHJ P,TTYFUW## ;MAKE SURE TTY ATTACHED FOR ERROR MSG
PUSHJ P,PPQCRL## ;PRINT CRLF ?
JRST URUNSB## ;
GETDD2: PUSHJ P,CHKMED## ;SET MEDDLE SO CAN'T CHANGE SHARABLE HIGH SEGMENT
MOVE T2,.JDAT+JOBDDT## ;DDT START ADDRESS
JRST STARTD## ;START AT DDT OR "NO START ADR"
;SUBROUTINE CALLED BY THE SWAPPER TO MAKE PFH CONCEALED
SXOPFH::PUSHJ P,SVEUB## ;MAKE ADDRESSABLE
HRRZ T1,.JDAT+.JBPFH## ;START OF PFH
JUMPE T1,CPOPJ## ;RETURN IF PFH ISN'T AROUND
HLRZ T2,.JDAT+.JBPFH## ;HIGHEST ADDRESS IN PFH
CAML T2,T1 ;TOP .GT. START?
PUSHJ P,ZRNGE ;IN CORE AND LEGAL?
POPJ P, ;NO, SKIP IT
MOVE T3,.JDAT+.JBPFH## ;TOP,,START
PUSHJ P,CKHSZ ;CAN'T BE HI SEG PAGES EITHER
POPJ P, ;FORGET IT
MOVE T2,T3 ;T2 GETS (.JBPFH)
;YES, FALL INTO EXOPFH
;SUBROUTINE TO SEE IF PFH SHOULD BE CONCEALED
EXOPFH::MOVEI T1,JS.XO ;EXECUTE ONLY BIT
MOVSI T3,(UP.MGP) ;MONITOR GOT PFH BIT
TDNE T3,.USBTS ;FROM SYS?
TDNN T1,JBTSTS##(J) ;IS THIS AN EXECUTE ONLY PROGRAM?
POPJ P, ;NO
MOVE T1,JBTSGN##(J) ;GET SEGMENT WORD
TLNN T1,CONSEG ;JOB HAVE CONCEALED HIGH SEG?
POPJ P, ;NO, FORGET IT
HLRZ T3,T2 ;HIGHEST ADDRESS IN PFH
SUBI T3,(T2) ;LENGTH OF PFH
TRZ T3,PG.BDY ;AND OUT LOW BITS
ADDI T3,PAGSIZ ;ROUND UP
LSH T3,W2PLSH ;LENGTH OF PFH IN PAGES
HRRZ T1,T2 ;STARTING ADDRESS OF PFH
LSH T1,W2PLSH ;STARTING PAGE NUMBER
EXOPF1: PUSHJ P,GTPME ;GET CONTENTS OF MAP SLOT
TDZ T2,[PM.PUB] ;MAKE THE PAGE CONCEALED
MOVEM T2,(T4) ;STORE IT BACK IN THE MAP
SOSLE T3 ;DONE ALL OF PFH'S PAGES?
AOJA T1,EXOPF1 ;NO, LOOP OVER ALL PAGES
POPJ P, ;RETURN
;SUBROUTINE TO TEST AND REMOVE PFH IF FROM SYS
RMVPFH::SETZM .PDTMC##(W) ;TURN OFF TIMER TRAPS
HLLZS .PDTMI##(W)
SETZM .USLFT ;LAST FAULT TIME TOO (FOR MONPFH)
MOVSI T1,(UP.MGP)
SKIPE T3,.JDAT+.JBPFH## ;IS THERE A PFH?
TDNN T1,.USBTS ;YES, FROM SYS?
POPJ P, ;NO, DONT DO ANYTHING
PUSHJ P,CKHSZ
POPJ P,
ANDCAM T1,.USBTS ;YES, CLEAR THE BIT
PUSHJ P,SAVE1##
LDB P1,[POINT 9,T3,8] ;LAST PAGE OF PFH
LDB T1,[POINT 9,T3,26] ;FIRST PAGE OF PFH
JUMPE T1,CPOPJ##
CAMGE P1,T1 ;TOP .GE. START?
POPJ P, ;NO, FORGET IT
IFN FTMP,<
PUSHJ P,GGVMM##
>
PUSH P,U ;SAVE U FOR COMCON
MOVE R,JBTADR##(J) ;MAY NOT BE SETUP
RMVPF1: PUSHJ P,GTPME ;GET MAP CONTENTS
JUMPE T2,RMVPF2 ;FORGET IT IF NO PAGE THERE
PUSH P,T1
PUSHJ P,DLTPAG ;GIVE BACK THE PAGE
PUSHJ P,DCVMT
POP P,T1
RMVPF2: CAIGE T1,(P1) ;DONE?
AOJA T1,RMVPF1 ;NO, RETURN NEXT PAGE
SETZM .JDAT+.JBPFH## ;NOW NO PFH
MOVEM R,.CPADR## ;YES, ADJUST .CPREL, .CPADR
HLRZM R,.CPREL##
HLRZM R,.USHVA ;FOR ADDRESS CHECKING AT INTERRUPT LEVEL
PJRST UPOPJ## ;AND RETURN
;SUBROUTINE TO SAY "CAN NOT GET DDT"
CNGDDT: SKIPA T1,[SIXBIT /DDT/]
;DITTO FOR PFH
CNGPFH: MOVSI T1,'PFH' ;WHAT WE COULDN'T GET
PUSH P,U ;SAVE POSSIBLE LDB POINTER
PUSH P,T1 ;SAVE 'XXX'
PUSHJ P,TTYSRC## ;FIND THE TTY
JRST CNGXX1 ;WHOOPS! FORGET IT
MOVEI T1,[ASCIZ "?
?Can not get "]
PUSHJ P,CONMES## ;TYPE "?CAN NOT GET"
MOVE T2,(P) ;RESTORE "XXX"
PUSHJ P,PRNAME## ;PRINT "PFH" OR "DDT" AND RETURN WITH T2=0
CNGXX1: POP P,T1 ;RESTORE T1
JRST UPOPJ## ;AND RETURN
;SUBROUTINE TO GET XXX.VMX
;CALLING SEQUENCE:
; MOVE T1,[SIXBIT/XXX/]
; MOVEI T2,WHERE TO PUT IT OR 0 IF AT THE TOP OF CORE
; PUSHJ P,GETXXX
;RETURNS CPOPJ ON ERROR
;RETURNS CPOPJ1 ON SUCCESS, T2 = HIGHEST ADDRESS READ INTO,,START ADDRESS
;ENTER AT MAKPGS TO CREATE PAGES, T2 = WHERE, T3 = HOW MANY
MAKPGS: MOVEI T1,0 ;FLAG CREATING PAGES
TRZ T2,PG.BDY ;MAKE SURE IT STARTS AT PAGE BOUNDARY
LSH T3,P2WLSH ;NUMBER OF WORDS TO MAKE
MOVNS T3 ;-N
HRLZM T3,.JDAT+SGALEN## ;FAKE OUT LOOKUP STUFF
GETXXX: MOVEI T3,.USUAC ;SAVE THE CURRENT EXEC ACS
EXCTUX <BLT T3,.USUAC+17>
PUSHJ P,SETASA## ;GET ARGUMENTS FROM SHADOW ACS
PUSH P,T2 ;SAVE WHERE TO PUT IT
PUSH P,T2 ;ALLOCATE STACK SPACE
MOVSI T2,'EXE'
DMOVEM T1,.JDAT+SGANAM## ;INTO LOOKUP BLOCK
JUMPE T1,GETXX3 ;SKIP THE LOOKUP IF MAKPGS
PUSHJ P,GETXXC ;GET EXTENDED CHANNEL NUMBER
JRST TTPOPJ## ;RESTORE AC'S IF THE WORLD FALLS APART
MOVE T1,USRJDA## ;GET POINTER TO DDB CURRENTLY HERE
MOVEM T1,(T2) ;SAVE AS AN EXTENDED CHANNEL
MOVEM T2,(P) ;SAVE POINTER TO EXTENDED CHANNEL
SETZM USRJDA## ;DONT RELEASE WHEN WE INIT
MOVEI T1,D ;INIT SYS: IN DUMP MODE
MOVE T2,[JACCT,,JS.XO]
TDNE T2,JBTSTS##(J)
TLO T1,PHONLY
MOVSI T2,'SYS'
DMOVEM T1,.JDAT+SGAMOD##
SETZM .JDAT+SGAHED##
OPEN SGAMOD##
JRST GETX11 ;CANT INIT SYS:
SETZM .JDAT+SGALEN##
LOOKUP SGANAM## ;LOOKUP XXX.VMX
SKIPA T1,[PHONLY,,DR]
JRST GETXX1
MOVEM T1,.JDAT+SGAMOD##
GETXX1: SKIPL .JDAT+SGAMOD## ;PHYSICAL ONLY?
TDZA T3,T3 ;NO
MOVEI T3,UPHNLY ;YES, PHONLY
MOVE T1,.JDAT+SGANAM## ;FILE NAME
MOVEM T1,.JDAT+SGADEV##+1 ;STORE THAT IN THE MERGE ARGUMENT BLOCK
DMOVE T1,[SGADEV## ;POINTER TO ARGUMENT LIST
SIXBIT /SYS/] ;DEVICE
DMOVEM T1,.JDAT+SGADEV##-1 ;STORE THOSE IN THE MERGE ARGUMENT BLOCK
SETZB T1,T2 ;ZERO WORDS 2,3,4,5
DMOVEM T1,.JDAT+SGADEV##+2 ;..
DMOVEM T1,.JDAT+SGADEV##+4 ;..
PUSHJ P,VJSIZ ;CURRENT SIZE OF THE PROGRAM
PUSH P,T4 ;SAVE THAT
PUSH P,.JDAT+JOBPD1##;SAVE JOBPD1
SETZM .JDAT+JOBPD1## ;SO IT WON'T LOOK LIKE A USER MODE UUO
MERGE. 10,(T3) ;MERGE XXX.EXE INTO THE ADDRESS SPACE
JRST [POP P,(P) ;FAILED
JRST GETX11] ;CAN'T GET XXX
POP P,.JDAT+JOBPD1##;RESTORE JOBPD1
PUSHJ P,VJSIZ ;SIZE OF THE PROGRAM AFTER THE MERGE
POP P,T1 ;SIZE BEFORE THE MERGE
SUB T4,T1 ;INCREASE IN SIZE
LSH T4,P2WLSH ;CONVERT TO NUMBER OF WORDS
SKIPE T2,-1(P) ;WHERE TO PUT IT SPECIFIED?
JRST GETXX2 ;YES
MOVSI T2,1 ;NO. AT TOP OF ADDRESS SPACE
SUB T2,T4 ;ORGIN
GETXX2: HRLS T2 ;ORGIN TO THE LEFT HALF
ADDI T2,-1(T4) ;HIGHEST ADDRESS
MOVSM T2,-1(P) ;STORE HIGHEST ADDRESS,,ORGIN FOR RETURN
AOS -2(P) ;GOOD RETURN
JRST GETX12 ;RESTORE THE WORLD AND EXIT
GETXX3: MOVE J,.CPJOB## ;RESTORE J
HLRE T3,.JDAT+SGALEN## ;LENGTH OF FILE
JUMPGE T3,GETX11 ;BETTER BE NEGATIVE
MOVNS T3 ;+LENGTH
ADDI T3,PG.BDY ;CONVERT TO REQUIRED NO OF PAGES
LSH T3,W2PLSH
PUSHJ P,CHKLIN## ;GET BELOW LIMIT
JRST GETX11 ;CAN'T DO IT
GETXX7: HLRE T1,.JDAT+SGALEN## ;NO OF PAGES TO CREATE
SKIPE T2,-1(P) ;WHERE TO CREATE THEM
JRST GETXX8
MOVSI T2,1 ;AT TOP OF CORE - FIND REAL START
ADD T2,T1 ;START ADR
TRZ T2,PG.BDY ;START PAGE
HRRZM T2,-1(P) ;SAVE ON LIST AS START LOC
GETXX8: SUBM T2,T1 ;TOP ADDRESS IN T1, START ON THE STACK
SUBI T1,1
XOR T1,-1(P) ;CROSSING A SECTION?
TLNE T1,-1 ;?
JRST GETX11 ;YES, NOT ALLOWED
XOR T1,-1(P)
HRLM T1,-1(P) ;TOP ADR,,START ADR
MOVE T3,-1(P)
MOVSS T1
PUSHJ P,CKHSO
JRST GETX11
MOVSS T1
SUBI T1,-1(T2) ;NUMBER OF WORDS NEEDED
ADDI T1,PG.BDY ;ROUND UP
LSHC T1,W2PLSH ;NUMBER OF PAGES AND START PAGE
MOVEM T1,.JDAT+SGAPPN## ;SAVE NUMBER OF PAGES
MOVEI T3,.JDAT+SGAPPN##+1 ;WHERE TO STORE NEEDED PAGE NUMBERS
GETXX9: HRRZM T2,(T3) ;SAVE NEEDED PAGE NUMBER
SOJLE T1,GETX10 ;GO IF HAVE ENOUGH
ADDI T3,1 ;WHERE TO STORE NEXT PAGE NUMBER
AOJA T2,GETXX9 ;BUMP THE PAGE NO AND CONTINUE
GETX10: MOVE T1,[1,,SGAPPN##]
MOVEM T1,.JDAT+17 ;CREATE PAGES
PAGE. 17,
JRST GETX11 ;CANT CREATE THE PAGES - TOUGH LUCK
AOS -2(P) ;GOOD RETURN
GETX11: SKIPN .JDAT+SGANAM## ;MAKPGS?
JRST GETX12 ;YES, NO CHANNEL TO DESTROY
CLOSE CLSNMB ;CLOSE THE FILE
RELEASE ;GET RID OF THE DDB
GETX12: MOVE J,.CPJOB## ;RESOTRE J
PUSHJ P,CLRASA## ;CLEAR JS.ASA IN JBTSTS
MOVSI T2,.USUAC ;RESTORE THE EXEC ACS ON ENTRY
EXCTXU <BLT T2,17>
POP P,T2 ;GET POINTER TO EXTENDED USER CHANNEL ZERO
PUSH P,(T2) ;GET POINTER TO USER'S CHANNEL 0 DDB
SETZM (T2) ;CLEAR EXTENDED CHANNEL POINTER TO IT
POP P,USRJDA## ;AND RESTORE USER'S CHANNEL ZERO
JRST T2POPJ## ;RESTORE T2 AND RETURN
;GET AN EXTENDED CHANNEL NUMBER
;RETURN
; CPOPJ, NO FREE CORE OR NO FREE CHANNELS
; CPOPJ1, T2/ POINTER TO FREE CHANNEL SLOT
GETXXC: HRRZ T1,.USCTA ;AN EXTENDED CHANNEL TABLE ALREADY SETUP?
JUMPN T1,GETXC1 ;YES, FIND A FREE CHANNEL
MOVEI T2,HIGHXC##-20 ;NO, ALLOCATE AN EXTENDED CHANNEL TABLE
PUSHJ P,GTFWDC ;GET FUNNY WORDS CACHED
POPJ P, ;ERROR - NO PER-PROCESS SPACE AVAILABLE
HRRM T1,.USCTA ;STORE THE ADDRESS OF THE XCT
MOVSI T2,(T1) ;FORM A BLT POINTER
HRRI T2,1(T1) ; ..
SETZM (T1) ;ZERO FIRST WORD OF THE TABLE
BLT T2,HIGHXC##-21(T1) ;ZAP, THE TABLE IS INITIALIZED
;HERE WITH T1 = ADDRESS OF THE EXTENDED CHANNEL TABLE
GETXC1: MOVE T2,T1 ;ADDRESS OF THE TABLE
GETXC2: SKIPN (T2) ;CHANNEL IN USE?
JRST CPOPJ1## ;NO, AVAILABLE
CAIGE T2,HIGHXC##-20(T1) ;YES, LOOKED AT THE ENTIRE TABLE?
AOJA T2,GETXC2 ;NO, LOOP OVER ENTIRE TABLE
POPJ P, ;ERROR - NO FREE CHANNELS AVAILABLE
SUBTTL PAGE. UUO
UPAGE.::PUSHJ P,SAVU## ;JOB1 DEPENDS ON THIS
HLRZ U,T1 ;FUNCTION IN U
CAIL U,NPGUUO ;IS IT A LEGAL FUNCTION?
JRST UIFERR ;NO, ILLEGAL ARGUMENT LIST ERROR
MOVE U,PAGJMP(U) ;GET DISPATCH ENTRY
HLRZ T3,U ;PUT CHECK BITS IN T3
HRR M,T1 ;ADDRESS OF THE ARGUMENT LIST
TLNE U,UU.NCL ;NEGATIVE ARGUMENT LEGAL?
PUSHJ P,[PUSH P,T1 ;YES
PUSHJ P,GETWSU##
JUMPGE T1,TPOPJ ;GO IF NOT NEGATIVE
PUSHJ P,GETWS1## ;NEXT ARGUMENT MUST BE IN CORE
POP P,T1
POP P,(P) ;POP OFF CALL
SOJA M,UPAGE1] ;CHECK IF IT CAN BE DONE IF LOCKED
HRRZS T1 ;CLEAR FUNCTION FROM LEFT HALF
PUSHJ P,UUOCHK ;INSURE THAT ALL ITEMS IN THE ARGUMENT LIST
; ARE IN CORE
UPAGE1: TLNN U,UU.NAL ;IS THIS FUNCTION ALLOWED IF THE JOB IS LOCKED?
JRST UPAGE2 ;YES, PROCEED
HLL T1,JBTSTS##(J) ;STATUS WORD
HLR T1,JBTSGN##(J) ;SEGMENT WORD
TDNE T1,[NSHF!NSWP,,LOKSEG]
JRST IILERR ;YES, ILLEGAL IF LOCKED ERROR
UPAGE2:
IFN FTMP,<
PUSHJ P,INTLVL## ;CAN'T WAIT FOR ANYTHING IF AT CLOCK LEVEL
TLNE U,UU.CP1 ;CAN THIS UUO BE EXECUTED ON CPU1?
JRST UPAGE3 ;ALREADY HAVE (CLOCK LVL) OR DON'T NEED MM
>
SKIPL MIGRAT ;IF WAITING TO MIGRATE IPCF PAGES,
JRST UPAG2B ;CONTINUE IF NO MIGRATION IN PROGRESS
MOVSI T1,-1
ADDM T1,JBTCCC##(J) ;YES, J SHOULD BE OK AT UUO LEVEL
UPAG2A: MOVEI T1,1 ;WAIT FOR FILFND TO FINISH
PUSHJ P,SLEEPF##
SKIPGE MIGRAT## ;DONE WITH IPCF YET?
JRST UPAG2A ;NO
PUSHJ P,DECCCC## ;ALLOW JOB TO ^C AGAIN
UPAG2B:
IFN FTMP,<
PUSHJ P,UPMM## ;NOW GET THE JOB THE MM RESOURCE
>
UPAGE3: ;CLOCK LEVEL ALSO ALREADY HAS MM
HRRZ T1,U ;GET SUBR ADDRESS
CAIN T1,PAGACC ;PAGE ACCESSIBILITY CHECK?
JRST UPAGE4 ;YES, DON'T DECODE PAGE NUMBER AS ADDDRESS
PUSHJ P,GETWSU## ;GET THE NUMBER OF ARGUMENTS
TLNE U,UU.NCL ;IF NEGATIVE COUNT IS LEGAL,
MOVMS T1 ;POSITIVE ARGUMENT COUNT
HRLI T1,1(M) ;LEFT HALF OF T1 POINTS AT THE FIRST ARGUMENT
MOVSS T1 ;T1 = NUMBER OF ARGUMENTS,,ADDRESS OF FIRST ARGUMENT
UPAGE4: PUSHJ P,FNDPDS## ;GET PDB (FOR LIMITS)
SETZM .USTMU ;BE SURE ZEROED
PUSH P,U ;SAVE DISPATCH BITS
PUSHJ P,(U) ;DISPATCH TO PERFORM REQUESTED FUNCTION
JRST UPAGEE ;ERROR EXIT
PUSHJ P,SETHSA ;SET JBTHSA
PUSHJ P,ZAPSCS ;CHECK EMPTY SECTION MAPS
IFN FTMP,<
PUSHJ P,INTLVL## ;DON'T FIDDLE WITH MM IF AT CLOCK LEVEL
PUSHJ P,TGVMM## ;OWN THE MM?
>
POP P,U ;RESTORE DISPATCH BITS
GETPC T2,.JDAT+JOBPD1## ;GET USER PC
TLNE U,UU.WCC ;CAN THIS UUO CAUSE THE W.S. TO CHANGE
PUSHJ P,INPFH ;YES, PFH DOING THIS UUO?
JRST UPAGER ;RETURN
MOVSI T1,(UP.WHC) ;WORKING SET HAS CHANGED BIT
IORM T1,.USBTS ;REMEMBER THAT
UPAGER: SKIPL .USTMU ;YES, BETTER BE ZERO ON EXIT?
AOSA (P) ;WE'RE GOING TO GIVE A SKIP RETURN
XCT PMW ;OOPS
POPJ P, ;RETURN
UPAGEE: PUSHJ P,ZAPSCS ;CLEAR EMPTY SECTIONS
POP P,(P) ;FIX STACK
SKIPL T3,.USTMU ;ANY PAGES MOVED BY PLTSN?
JRST UPAGE9 ;NO
SE1ENT ;MUST BE IN S1 TO TOUCH MAPS&PAGTAB/MEMTAB
UPAGE5: SSX T3,MS.MEM ;POINT TO PAGTAB/MEMTAB SECTION
LDB T1,NVPNT3 ;GET VIRTUAL PAGE THIS PHYS PAGE BELONGS TO
PUSHJ P,GTPME ;GET PAGE MAP ENTRY
TLNE T2,(PM.OIQ) ;WAS PAGE ON AN IN QUEUE?
JRST UPAGE6 ;YES, TREAT AS SUCH
XOR T2,MEMTAB(T3) ;BE SURE DISK ADDRESSES ARE THE SAME
TDNE T2,[MT.DAD] ;...
XCT PMW ;++PAGE MAP IS WRONG
MOVEI T1,PAGOUQ## ;PUT PAGE ON OUT QUEUE
JRST UPAGE7
UPAGE6: TLNN T2,(PM.SSP) ;SLOW?
SKIPA T1,[PAGINQ##] ;NO, FAST
MOVEI T1,PAGSNQ## ;SLOW
TLZ T2,(PM.NAD) ;QUICK CHECK
CAIE T2,(T3) ;PAGE NUMBERS SHOULD MATCH
STOPCD CPOPJ,DEBUG,PMW, ;++PAGE MAP WRONG
UPAGE7: EXCH T1,T3 ;QUEUE TO T3, PAGE TO T1
MOVSI T4,(P2.TRN) ;CLEAR TRANSIENT PAGE BIT
ANDCAM T4,PT2TAB(T1)
HRRZ T4,PAGTAB(T1) ;GET CURRENT SUCCESSOR
HRRZS T1 ;ADDPTQ RE-ADDS IN MS.MEM
PUSHJ P,ADDPTQ ;ADD TO A QUEUE
UPAGE8: SKIPE T3,T4 ;IF THERE IS A NEXT PAGE
JRST UPAGE5 ;LOOP BACK
UPAGE9:
IFN FTMP,<
PUSHJ P,INTLVL## ;CLOCK LEVEL ALREADY HAD IT
PJRST TGVMM## ;OWN THE MM RESOURCE?
>
POPJ P, ;RETURN
;PAGE. UUO DISPATCH TABLE
PAGJMP: UU.NCL+UU.NAL+UU.LER+UU.WCC,,PAGEB ;(0) PAGE IN/OUT
UU.NCL+UU.NAL+UU.LER+UU.WCC,,CHGPGS ;(1) CREATE/DESTROY PAGES
UU.NCL+UU.NAL+UU.LER,,MOVPGS ;(2) MOVE/EXCHANGE PAGES
UU.NCL+UU.LER,,SETAAB ;(3) SET/CLEAR ACCESS ALLOWED BITS
UU.CP1+UU.LER,,GETWSB ;(4) GET WORKING SET BIT TABLE
UU.CP1+UU.LER,,GETAAB ;(5) GET ACCESS ALLOWED BIT TABLE
UU.CP1,,PAGACC ;(6) CHECK PAGE ACCESSABILITY
UU.NAL+UU.LER+UU.WCC+UU.CP1,,GREMAP ;(7)GENERALIZED REMAP
; UU.CP1 SO NREMAP CAN GET MM BY HAND
UU.NCL+UU.LER,,SETCSB ;(10) SET/CLEAR CACHE BITS
IFN FTPEEKSPY,<
UU.NCL+UU.LER,,SPYPGS ;(11) SPY ON PAGES
>
IFE FTPEEKSPY,<
UU.LER,,UIFERR ;(11) NOT IMPLEMENTED
>
UU.NCL+UU.LER+UU.NAL,,CHGSEC ;(12) CREATE/DESTROY SECTION MAPS
UU.CP1+UU.LER,,PAGCHK ;(13) ACCESSIBILITY BIT MAP
UU.CP1+UU.LER,,PAGACL ;(14) PAGE ACCESSIBILITY, LIST FORM
UU.NCL+UU.LER,,LOKPGS ;(15) LOCK SPECIFIED PAGES
UU.NCL+UU.LER,,PAGWLK ;(16) WRITE-ENABLE/LOCK PAGES
NPGUUO==.-PAGJMP
HSPAG==200000 ;PLTSN SETS IF PAGE IS IN A HIGH SEGMENT
ARGMD==100000 ;ARGUMENT MODIFIER, SET BY PLTSN IF ANY AGRUMENT
; HAS 1B1=1
;HERE TO FIND PAGES WHICH HAVE GIVEN ACCESSIBILITY
PAGCHK: HLRZ P1,T1 ;GET ARG COUNT
SOJLE P1,IALERR ;NOT ENOUGH ARGS
PUSHJ P,GETWD1## ;BIT MASK OF STATE
MOVE P4,T1 ;SAVE IN P4
SOJLE P1,IALERR ;NOT ENOUGH ARGS
PUSHJ P,GETWD1## ;BITS HE CARES ABOUT
MOVE R,T1
SOJLE P1,IALERR ;ERROR IF NO MORE ARGS
PUSHJ P,GETWD1## ;GET STARTING PAGE #
SE1ENT ;ENTER SECTION 1
PAGCH1: CAILE T1,HLGPGS
JRST ILPERR ;NO
MOVSI P2,(1B0) ;FIRST BIT TO SET
TDZA P3,P3 ;CLEAR MASK WORD VALUE
PAGCH2: LSH P2,-1 ;ADVANCE BIT TO SET IN WORD
TRNN T1,HLGPNO ;CROSS SECTION BOUNDARY?
PUSHJ P,SCDCHK## ;KAF GUARD
PAGCH3: CAILE T1,HLGPGS ;RAN OUT OF LEGAL PAGES?
JRST PAGCH5 ;YES, OUT OF BIT MAP NOW
PUSH P,T1
PUSHJ P,GTPACC ;GET PAGE ACCESSIBILITY BITS
XOR T1,P4 ;DIFFERENCES BETWEEN REALITY AND FANTASY
TDNN T1,R ;BUT DO ANY OF THEM MATTER?
TDO P3,P2 ;NO, THIS PAGE MATCHES
POP P,T1 ;RESTORE PAGE NUMBER
PAGCH4: TRNN P2,1 ;ANY MORE ROOM IN WORD?
AOJA T1,PAGCH2 ;YES
PAGCH5: EXCH P3,T1 ;WORD TO DEPOSIT
PUSHJ P,PUTWD1## ;GIVE TO USER
MOVE T1,P3 ;GET PAGE # BACK
SOJLE P1,CPOPJ1## ;USER WANT MORE (RETURN IF NO)?
AOJA T1,PAGCH1 ;ON TO NEXT
;HERE TO DETERMINE PAGE ACCESSABILITY
PAGACC: PUSHJ P,GETTAC## ;GET THE CONTENTS OF THE USER'S AC
HRRZS T1 ;GET PAGE NUMBER IN QUESTION
CAILE T1,HLGPGS ;IS IT LEGAL?
JRST ILPERR ;NO
PUSHJ P,PAGAC1 ;GET THE PAGE BITS
PJRST STOTC1## ;STORE THE RESULTS AND RETURN TO THE USER
;HERE FOR LIST FORMAT PAGACL
PAGACL: HLRZ P1,T1 ;COUNT
SOS P1 ;REMOVE COUNT WORD
SOJLE P1,IALERR ;MUST BE AT LEAST ONE MORE ARG
PUSHJ P,GETWD1## ;GET STARTING PAGE #
PUSH P,T1 ;SAVE STARTING PAGE
PGACL0: MOVEI P2,HLGPNO+1 ;FOR CALLING SCDCHK
PGACL1: PUSHJ P,PAGAC1 ;GET ACCESSIBILITY
PUSHJ P,PUTWD1## ;STORE IT
AOS T1,(P) ;POINT TO NEXT PAGE
SOJL P2,PGACL2
SOJG P1,PGACL1 ;CONTINUE
JRST TPOPJ1##
PGACL2: PUSHJ P,SCDCHK##
JRST PGACL0
;SUBROUTINE TO GET THE PAGE ACCESSABILITY BITS
;CALL:
; MOVE T1,PAGE #
; PUSHJ P,GETPAC
; HERE WITH BITS IN T1
;
GETPAC::MOVE J,.CPJOB## ;JOB NUMBER
GTPACC::HRRZS T1 ;PAGE NUMBER THAT THE USER IS INTERESTED IN
CAILE T1,HLGPGS ;PAGE NUMBER SPECIFIED .LE. HIGHEST LEGAL PAGE?
JRST ILPERR ;NON-EXISTENT
PAGAC1: SE1ENT
MOVEI U,0 ;ASSUME THE PAGE DOESN'T EXIST
LSHC T1,P2SLSH ;MAP
PUSH P,T2 ;SAVE T2
MOVE T4,T1 ;GET COPY
CAILE T4,MXSECN ;LEGAL?
JRST PAGAC8 ;NO, IS NON-EXISTENT THEN
PUSHJ P,RSECT4 ;GET SECTION #
JRST PAGAC8
MOVE T2,.UPMP+SECTAB(T1) ;GET MAP
EXCH T2,(P) ;RESTORE T2, SAVING ENTRY
LSHC T1,S2PLSH ;RESTORE PAGE #
POP P,T2
TLNN T2,(<PM.DCD^!PM.ACD>B2) ;INDIRECT?
JRST PAGAC0 ;NO
DPB T4,[POINT 5,U,<^L<PA.ISN>+5-1>] ;POSITION IT
TLO U,(PA.IND) ;SET INDIRECT
SKIPN .UPMP+SECTAB(T4) ;DOES REAL SECTION EXIST?
JRST PAGAC9 ;NO
PAGAC0: PUSHJ P,GTPME ;GET CONTENTS OF THE MAP
JUMPE T2,PAGAC7 ;NON-EXISTENT
MOVE T3,T2 ;SAVE THE MAP ENTRY
TLZ T2,(PM.NAD) ;ABZ?
CAMN T2,[PM.ZER]
TLO U,(PA.ZER) ;ZERO PAGE
PUSHJ P,TSWST ;IS THE PAGE IN THE WORKING SET?
TLOA U,(PA.OUT) ;NO, INDICATE THAT THE PAGE IS PAGED-OUT
JRST PAGA0A ;IF WSBTAB ON, NO SWEAT
TLNE T3,(PM.LOK) ;IF PAGE IS LOCKED,
TLC U,(PA.OUT!PA.LCK) ;THEN IT ISN'T IN THE WORKING SET
PAGA0A: TLNE T3,(PM.AAB) ;IN AABTAB?
TLO U,(PA.AA) ;YES, INDICATE ACCESS IS ALLOWED
TLNE U,(PA.OUT) ;IN MEMORY?
JRST PAGAC2 ;NO - MUST BE CACHED
TLNN T3,(PM.CSH) ;YES - CACHE TURNED OFF?
TLO U,(PA.NCS) ;YES, TELL USER NOT CACHED
PAGAC2: MOVE T2,T3 ;RESTORE MAP ENTRY
IFN FTPEEKSPY,<
TLNN T2,(PM.SPY) ;IS THIS A SPY PAGE?
JRST PAGA2A ;NO, SEE ABOUT HIGH SEG
TLNN T2,(<PM.DCD^!PM.ICD>B2) ;VIRTUAL SPY PAGE?
TROA U,(T2) ;PROPAGATE PHYSICAL PAGE NUMBER
PUSHJ P,PAGA10 ;IF VIRTUAL, HANDLE IT
MOVE T4,T2 ;MOVE MAP ENTRY HERE
SETZB T2,T3 ;NO HIGH SEG TO WORRY ABOUT
JRST PAGA1A ;MERGE WITH COMMON CODE
PAGA2A:>
MOVE T4,T2 ;PRESERVE PAGE MAP ENTRY
PUSH P,T1 ;SAVE T1 (NEED TO KEEP SECTION #)
PUSHJ P,TPNHX ;SEE IF PAGE IS IN SOME HIGH SEG
TLOA U,(PA.GHI) ;IT IS, FLAG AS SUCH
TDZA T2,T2 ;NO HIGH SEG DATA BLOCK
SKIPA T3,.HBSGN(T2) ;GET HIGH SEG DATA WORD
IFN FTPEEKSPY,<
TDZA T3,T3 ;NO HIGH SEG EITHER
TLNN T3,SPYSEG ;HIGH SEG ACTUALLY SPY SEG?
JRST PAGA1B ;NO, DON'T CHANGE
DPB T4,[POINT <36-^L<PA.SPN>>,U,35] ;YES, GIVE PHYSICAL PAGE #
POP P,T1 ;YES, RESTORE T1 NOW
PAGA1A: TLOA U,(PA.GSP!PA.CPO) ;YES, TELL USER
>
IFE FTPEEKSPY,<
SETZ T3,
>
PAGA1B: POP P,T1 ;RESTORE T1
JUMPE T2,PAGA1C ;A LOW SEG PAGE
TLNE T3,SHRSEG ;CAN PAGE BE SHARED WITH ANYONE ELSE?
TLOA U,(PA.GSH!PA.CPO) ;YES, FLAG IT AS SHARABLE
PUSHJ P,[TLNN T3,UWPOFF ;IS NON-SHARABLE SEG WRITE-LOCKED?
TLZA T4,(PM.WRT) ;YES, MAKE SURE WE KNOW THAT
TLO T4,(PM.WRT) ;MAKE SURE WE KNOW IT'S ENABLED
JRST CPOPJ1##] ;(MONITOR CAN'T DIDDLE WRITE ON SHARABLE HIGH SEGS)
TLZ U,(PA.LCK) ;SHARABLE CAN'T BE LOCKED (FOOLED BY INDIRECT FIELD)
SKIPLE T3 ;IF A REAL HISEG (SHARABLE OR NOT)
DPB T3,[POINT <36-^L<PA.SGN>>,U,35] ;THEN STORE THE SEGMENT NUMBER
PAGA1C: SKIPE .USWLP ;IS MONITOR WRITE-LOCKING PAGES?
TLNE U,(PA.GHI) ;YES, IS THIS A HIGH SEG PAGE (OK TO CHECK WRITE)
TLNE T4,(PM.WRT) ;HS OR NOT MONWL: WRITABLE PAGE?
TLOA U,(PA.WRT) ;A WRITABLE LOW OR HIGH SEG PAGE
TLZ U,(PA.WRT) ;A WRITE-LOCKED PAGE
PUSH P,T2 ;SAVE HIGH SEG DATA BLOCK ADDR
GETPC T2,.JDAT+JOBPD1## ;PC OF THE PAGE ACCESSABILITY UUO
TLNN T2,(IC.LIP) ;UUO DONE FROM A CONCEALED PAGE?
JRST PAGAC5 ;YES, PAGE CAN BE READ
TLNE T4,(PM.PUB) ;A PUBLIC PAGE?
JRST PAGAC5 ;THEN THE PAGE CAN BE READ
TLZ T4,(PM.NAD) ;KEEP ONLY ADDRESS
TLNN U,(PA.OUT)
CAMN T4,[PM.ZER] ;IF NOT ABZ,
CAIA
JRST PAGAC4 ;PAGE CANNOT BE READ
TLNN T3,SPYSEG ;IF NOT SPY,
TLNN T3,GTSSEG ;WAS IT GETSEGED?
JRST PAGAC5 ;NO, PAGE CAN BE READ
TLNE U,(PA.GHI) ;IS THE TARGET PAGE IN THE HI SEG?
PAGAC4: TLZA U,(PA.RED!PA.WRT); YES, PAGE CANNOT BE READ
PAGAC5: TLO U,(PA.RED) ;HERE IF PAGE CAN BE READ
TRNN T1,HLGPNO ;PAGE ZERO OF SOME FLAVOR?
PUSHJ P,ISITS0 ;YES, IS IT THE REAL PAGE ZERO?
TLNE U,(PA.GSH!PA.GSP) ; OR SPY OR SHARABLE HISEG?
TLOA U,(PA.CPO!PA.AA);YES - NEVER PAGEABLE, ACCESS ALWAYS ALLOWED
CAIA ;NO
TLZ U,(PA.OUT) ;YES - ALSO NEVER PAGED OUT
POP P,T4 ;HIGH SEG BLOCK ADDR (OR ZERO)
TLNE U,(PA.GSP) ;SPYING?
JRST PAGAC6 ;YES - "LOCK" MEANINGLESS
MOVSI T2,NSHF!NSWP ;LOCKED BITS
TLNN U,(PA.GHI) ;IS IT A HIGH-SEGMENT PAGE
SKIPA T4,J ;NO, GET IT'S LOW SEG "NUMBER"
HRRZ T4,.HBSGN(T4) ;YES, GET ITS HIGH SEG "NUMBER"
TDNE T2,JBTSTS##(T4) ;IS PAGE IN LOCKED SEGMENT
TLO U,(PA.LCK!PA.CPO) ;YES, THEN ALSO CAN'T BE PAGED OUT
PAGAC6: SKIPA T1,U ;YES, THEN IT CANNOT BE PAGED OUT
PAGAC7: MOVSI T1,(PA.NXP) ;PAGE IS NON-EXISTANT
POPJ P, ;RETURN
PAGAC8: POP P,T2 ;FIX STACK
TDZA T1,T1 ;JUST SET THESE BITS
PAGAC9: MOVE T1,U
TLO T1,(PA.NXS!PA.NXP) ;NON-EXISTENT SECTION & PAGE
POPJ P,
IFN FTPEEKSPY,<
PAGA10: MOVEI T3,SPTTAB##(T2) ;ACTUAL POSITION IN SPT
CAIL T3,SPTLOW## ;IS IT MAPPED VIA JBTUPM?
JRST PAGA91 ;NO, LOOK ON
MOVS T3,T2 ;YES, GET ACTUAL PAGE OFFSET
ANDI T3,PG.BDY ;MASK IT DOWN
CAIL T3,.UPCDB ;IS IT FOR THE CDB?
CAILE T3,.UPCDB+<CDBPGS##-1> ;ANY PAGE?
JRST PAGA9C ;NO, CHECK OTHER CASES
MOVEI T3,<.CPCDB##+MCSEC1>/PAGSIZ-.UPCDB(T3) ;YES, UPDATE TO PAGE NUMBER
JRST PAGA9A ;EXIT VIA COMMON CODE
PAGA9C: CAIL T3,SECTAB ;IF A SECTION MAP,
CAILE T3,SECTAB+HLGSNO ;OF ANY USER SECTION,
HRRI T3,<<<MCSEC1+FYSORG-<MS.MAP+UMAPS>>/PAGSIZ>-.UMORG+SECTAB>(T3)
HRRI T3,<MS.MAP+UMAPS>/PAGSIZ-SECTAB(T3) ;YES, ASSUME IN MS.MAP
PAGA9A: HRR U,T3 ;COPY VIRTUAL PAGE SPIED UPON
TLO U,(PA.VSP) ;NOTE IS VIRTUAL
SETZ T3, ;FOR LATER
POPJ P, ;RETURN
PAGA91:
IFN FTXMON,<
CAIL T3,SPTHGH## ;IS IT IN SECTIONS 0/1?
JRST PAGA92 ;NO, LOOK ON
>
MOVS T3,T2 ;YES, GET ACTUAL PAGE OFFSET
ANDI T3,PG.BDY ;MASK IT DOWN
TRO T3,<MCSEC1/PAGSIZ> ;SET SECTION 1
JRST PAGA9A ;SET FOR MCSEC1, NOW RETURN IT
IFN FTXMON,<
PAGA92: CAIL T3,SPTCOM## ;IS IT IN MS.HGH?
JRST PAGA93 ;NO, LOOK ON
MOVS T3,T2 ;YES, GET ACTUAL PAGE OFFSET
ANDI T3,PG.BDY ;MASK IT DOWN
TRO T3,<MS.HGH/PAGSIZ> ;SET FOR FOR CORRECT SECTION
JRST PAGA9A ;RETURN IT
PAGA93: SUBI T3,SPTCOM##-<(MS.FMD)> ;CONVERT SPT LOC TO SECTION NUMBER
LSH T3,S2PLSH ;THEN TO PAGE BASE
MOVSS T2 ;GET PAGE OFFSET IN CORRECT PLACE
ANDI T2,PG.BDY ;MASK IT DOWN
TRO T3,(T2) ;FORM FULL PAGE NUMBER
JRST PAGA9A ;RETURN IT
> ;END IFN FTXMON
> ;END IFN FTPEEKSPY
;HERE TO SET/CLEAR CACHE BITS IN THE LOW SEGMENT OF
; A LOCKED JOB
IFN FTLOCK,<
SETCSB: SE1ENT
MOVSI T1,PVLOCK ;BIT DENOTING PRIVILEDGES TO LOCK
PUSHJ P,PRVBIT## ;IS THIS USER A SUFFICIENT WHEEL?
SKIPA ;YES, PROCEED
JRST NPVERR ;NO PRIVS
MOVEI T2,PA.IHB+PA.PME ;CHECK ARGUMENT LIST (PAGE MUST EXIST)
PUSHJ P,PLTSN ;VERIFY LIST
POPJ P, ;BAD ARGUMENT LIST
TLNE M,HSPAG ;A HIGH SEGMENT PAGE SEEN?
JRST UIFERR ;YES, NOT IMPLEMENTED FOR HIGH SEGMENTS
ADD T3,T2 ;TOTAL NUMBER OF PAGES IN THE ARGUMENT LIST
PUSHJ P,FSTPAG ;POINT M AT FIRST ARGUMENT - 1
SETCS1: PUSHJ P,NXTPAG ;NEXT ARGUMENT
HRRZ T2,T1 ;JUST PAGE #
LSH T2,P2SLSH ;CONVERT TO SECTION #
SKIPN .UPMP+SECTAB(T2) ;IF SECTION DOESN'T EXIST
JRST SETCS2 ;IT MUST BE PG.IDC SO IGNORE
PUSHJ P,GTPME ;GET MAP ENTRY
TDZN T2,T2 ;ARE ANY BITS SET IN T2 (CLEAR ALWAYS)?
JRST SETCS2 ;IGNORE NON-EX PAGE
TLNE T1,(PG.GAF) ;SET OR CLEAR THE CACHE BIT?
TLOA T2,(<IORM T1,(T4)>) ;SET CACHE BIT
MOVSI T2,(<ANDCAM T1,(T4)>)
MOVSI T4,(PM.CSH)
XCT T2 ;SET OR CLEAR THE BIT
SETCS2: SOJG T3,SETCS1 ;LOOP OVER THE ENTIRE ARGUMENT LIST
PUSHJ P,CSDMP## ;FLUSH THE CACHE
JRST FIXMJ1 ;CLEAR PAGING MEMORY AND RETURN
>
;UUO TO SET OR CLEAR WRITE-ENABLE FOR PAGES. THIS ONLY WORKS
;FOR LOW SEG PAGES
PAGWLK: MOVEI T2,PA.PME!PA.PWE!PA.PWL ;PAGES TO BE WRITE-LOCKED MUST EXIST
SE1ENT ;ENTER SECTION 1
PUSHJ P,PLTSN ;CHECK THE ARG LIST
POPJ P, ;BAD ARG LIST
DMOVE P2,T2 ;SAVE PAGE COUNTS
SKIPE .USWLP ;HAVE ANY MONITOR-LOCKED PAGES?
PUSHJ P,CLRWLP ;YES, MAKE ALL POSSIBLE PAGES WRITABLE
PAGWL4: PUSHJ P,FSTPAG ;POINT TO BEGINNING OF ARG LIST
PAGWL5: PUSHJ P,NXTPAG ;GET NEXT PAGE
MOVE T3,T1 ;SAVE ARG
PUSHJ P,GTPME ;GET ENTRY
JUMPL T3,PAGWL ;LOCK THE PAGE
PAGWE: TLON T2,(PM.WRT) ;IF WRITE
SOS .USWLC ;WAS WRITE-LOCKED, TAKE OUT OF COUNT
MOVEM T2,(T4) ;WRITE-ENABLE THE PAGE
SOJG P3,PAGWL5 ;CONTINUE IF MORE TO ENABLE
JUMPG P2,PAGWL5 ;OR WRITE-LOCK
JRST CPOPJ1## ;GIVE GOOD RETURN
PAGWL: TLZE T2,(PM.WRT) ;WAS PAGE ALREADY WRITE-LOCKED?
AOS .USWLC ;NO, INCREMENT THE WRITE-LOCK COUNT
MOVEM T2,(T4)
SOJG P2,PAGWL5 ;CONTINUE IF MORE TO WRITE-LOCK
JUMPG P3,PAGWL5 ;OR WRITE-ENABLE
JRST CPOPJ1##
;HERE TO PAGE IN/OUT PAGES
PAGEB: MOVEI T2,PA.PME+PA.PMI+PA.PCI
PUSHJ P,PLTSN ;VERIFY THE ARGUMENT LIST (PAGE MUST EXIST
; AND FOR PAGING OUT MUST BE IN CORE, FOR
; PAGING IN THE PAGE MUST NOT BE IN CORE)
POPJ P, ;ERROR IN THE ARGUMENT LIST
PUSHJ P,SAVE4## ;SAVE P1-P4
PUSHJ P,FSTPAG ;POINT M AT FIRST ARGUMENT - 1
PUSHJ P,SZCHK ;MAKE SURE THAT AFTER PAGING OUT THE REQUESTED PAGES
; THAT PAGING IN THE REQUESTED PAGES WON'T EXCEED
; THE USER'S PHYSICAL LIMIT
PJRST TBGERR ;USER IS ATTEMPTING TO GET TO BIG
JUMPN T2,[HLRZ T4,.PDMVL##(W)
JUMPE T4,TBGERR
JRST .+1]
PUSH P,T3 ;SAVE THE NUMBER OF PAGES TO PAGE-IN
PUSH P,T2 ;AND THE NUMBER OF PAGES TO PAGE-OUT
MOVE P1,T2 ;TOTAL NUMBER OF PAGES TO XFER
ADD P1,T3
PUSHJ P,USRATE ;COMPUTE PAGING INTERVAL
PUSHJ P,SYRATE ;COMPUTE SYSTEM-WIDE PAGING INTERVAL
MOVE T1,TICSEC## ;HAS HE GOT A VIRTUAL TIMER RUNNING?
SKIPN .PDTMC##(W)
MOVEM T1,.PDTMC##(W) ;NO, GET TIME INTERRUPTS ANYWAY
;HERE TO GET SWAPPING SPACE
MOVE U,(P) ;NUMBER OF PAGES OF DISK SPACE TO ALLOCATE
; FOR PAGING OUT PAGES
JUMPE U,PAGEB1 ;IF NO PAGES TO PAGE-OUT PROCEED WITH PAGING IN
MOVN P1,(P) ;NEGATIVE NUMBER OF PAGES TO GO OUT
; MOVE U,T1 ;STARTING DISK ADDRESS
PUSHJ P,PAGOMT ;SETUP MEMTAB FOR PAGING OUT THE PAGES INDICATED
; BY THE USER
IFN FTMP,<
SETOM SAVCTL## ;MAKE SURE CACHE GETS SWEPT
>
PUSHJ P,FSTPAG ;RESET ARG LIST
PAGEB1: POP P,T2 ;RESTORE THE NUMBER OD PAGES TO BE PAGED-OUT
POP P,T3 ;AND THE NUMBER OF PAGES TO BE PAGED-IN
SKIPN .USTMU ;ANY PAGES ON THE INCORE QUEUES?
JUMPE T3,FIXMJ1 ;CLEAR THE A.M. AND RETURN TO THE USER IF
; THERE ARE NO PAGES TO BE PAGED IN
MOVE P2,T3 ;SAVE THE NUMBER OF PAGES REQUIRED
SETZB T1,P4 ;INDICATE NO PAGES ALLOCATED
SKIPN P1,T3 ;SKIP IF SOME PAGES "REALLY" NEED TO BE PAGED IN
JRST PAGEB2 ;ALL PAGES TO BE PAGED IN ARE ALREADY IN CORE
SKIPE .USTMU ;ANY PAGES ON QUEUES?
PUSHJ P,PAGIMT ;FILL IN THE QUEUE PAGES
JFCL ;SHOULD ALWAYS BE HERE
MOVE T3,P1 ;# OF PAGES TO ALLOCATE
PUSHJ P,FSTPAG ;POINT M AT FIRST ARGUMENT - 1
PUSHJ P,FRDCRW## ;ENOUGH PAGES IN CORE TO SATISFY THIS REQUEST?
JRST [SE1ENT ;SECTION 1 FOR CALLS TO GETPME
SETZ P3, ;NO NON-EX SECTION MAPS
MOVE T3,P2 ;# OF PAGES TO REALLY PAGE IN
PJSP P4,CHGP11] ;CREATE ON DISK
LDB T1,JBYSSA## ;FIRST PAGE OF JOB
MOVE T2,P2 ;SETUP ARGUMENTS TO ADPAGS
PUSHJ P,ADPAGS## ;ALLOCATE THE REQUIRED NUMBER OF PAGES
MOVSI P4,NSHF ;BE SURE WE DON'T SWAP
IORM P4,JBTSTS##(J) ;(NSWP CAN'T BE ON HERE)
;HERE WITH T1 = FIRST PHYSICAL PAGE ALLOCATED
PAGEB2: MOVEI P4,0 ;INDICATE INITIAL CALL TO PAGIMT
PUSH P,P2 ;SAVE # OF PAGES ALLOCATED
MOVN P3,P2 ;GET -# OF PAGES INTO P3
PUSHJ P,PAGIMT ;SETUP MEMTAB FOR PAGING INPUT
JRST PAGEB6 ;PAGES BEING INPUT ARE CONTIGUOUS ON THE DISK
;HERE ON A PAGE IN WHEN THE PAGES ARE FRAGMENTED
SUBM P4,(P) ;-# OF PAGES REMAINING ON STACK
MOVMS (P) ;+# OF PAGES REMAINING ON STACK
TLO P3,(MT.LEF) ;INDICATE NOT LAST FRAGMENT
MOVE P1,P4 ;SAVE THE NUMBER OF PAGES IN THIS FRAGMENT
MOVEI P4,0 ;INDICATE THE START OF A FRAGMENT TABLE
PUSHJ P,PGBGCR ;GET CORE
PUSH P,P4 ;SAVE THE START ADDRESS OF THE CORE BLOCK
PAGEB3: MOVE P2,P4 ;P2 = AN AOBJN POINTER TO THE CURRENT BLOCK
; IN THE FRAGMENT TABLE
PAGEB4: DPB P3,[POINT SL.SPN,P1,<^L<SL.PPN>+SL.SPN-1>]
MOVEM P1,(P2) ;STORE THE SWPLST ENTRY FOR THIS FRAGMENT
JUMPGE P3,PAGEB5 ;JUMP IF THIS IS THE LAST FRAGMENT
MOVEI P4,0 ;INITIALIZE THE COUNTEROF THE NUMBER OF PAGES
; IN THIS FRAGMENT
MOVN P3,-1(P) ;-# OF PAGES USABLE
PUSHJ P,PAGIMT ;SETUP MEMTAB FOR THIS FRAGMENT
TLZA P3,(MT.LEF) ;INDICATE LAST FRAGMENT
TLO P3,(MT.LEF) ;INDICATE NOT LAST FRAG
SUBM P4,-1(P) ;# OF PAGES REMAINING
MOVMS -1(P)
MOVE P1,P4 ;SAVE THE NUMBER OF PAGES IN FRAGMENT
AOBJN P2,PAGEB4 ;STORE THE FRAGMENTED SWPLST ENTRY AND CONTINUE
MOVE P4,P2 ;T4 = POINTER TOFRAGMENT TABLE
PUSHJ P,PGBGCR ;GET CORE
JRST PAGEB3 ;CONTINUE
PAGEB5: SETZM 1(P2) ;ZERO LAST ENTRY + 1 IN FRAGMENT TABLE
POP P,T1 ;RESTORE THE POINTER TO THE START OF THE
; FRAGMENT TABLE
HRLI T1,FRGSEG ;INDICATE A FRAGMENTED SWPLST ENTRY
ADJSP P,-1 ;CLEAN JUNK OFF THE STACK
JRST PAGEB7 ;MAKE THE ENTRY IN SWPLST AND DO THE I/O
PAGEB6: POP P,(P) ;FIX STACK (# OF PAGES ALLOCATED)
MOVE T1,P4 ;BUILD A SWPLST ENTRY
DPB P3,[POINT SL.SPN,T1,<^L<SL.PPN>+SL.SPN-1>]
PAGEB7: MOVSI T2,NSHF ;MAKE US SWAPPABLE AGAIN
ANDCAM T2,JBTSTS##(J)
JUMPE P2,PAGEB8 ;GO IF NO I/O TO DO
PUSHJ P,PAGEIT ;PAGE THE PAGES IN
JRST PIOERR ;PAGING I/O ERROR
PAGEB8: MOVE T1,.USNXP ;LAST VALUE OF .USNXP
CAME T1,[-1] ;REGULAR FORMAT?
SOSA T1 ;NO, NEGATIVE FORMAT
PUSHJ P,GETWSU## ;GET LAST (HIGHEST) PAGE BEING CREATED
PUSHJ P,JSTVRT ;ZERO .UPVRT IF NOW NON-VIRTUAL
PJRST FIXMJ1 ;CLEAR THE A.M. AND RETURN TO THE USER
PGBGCR: PUSHJ P,GT4MR
CAIA ;NOT IMMEDIATELY AVAILABLE
POPJ P, ;RETURN WITH CORE
PUSHJ P,SAVT## ;SAVE EVERYTHING
MOVSI T1,-1 ;MAKE HIM NON-CONTRL-CABLE
ADDM T1,JBTCCC##(J) ;..
PGBGC1: SETZ T1,
PUSHJ P,SLEEPF## ;WAIT A BIT TO SEE IF CORE APPEARS
PUSHJ P,GT4MR ;IS CORE NOW AVAILABLE?
JRST PGBGC1 ;NO, WAIT SOME MORE
PJRST DECCCC## ;CLEAR ^C WAIT
;SUBROUTINE TO SETUP MEMTAB AND THE UPMP FOR A PAGE IN
;CALLING SEQUENCE:
; MOVE T1,FIRST PHYSICAL PAGE ALLOCATED
; MOVE M,ADDRESS - 1 OF FIRST PAGE IN THE ARGUMENT LIST
; MOVEI P3,-# OF PAGES ALLOCATED (ONLY NEEDED IF P1=/=0)
; MOVEI P4,0
; PUSHJ P,PAGIMT
;RETURNS CPOPJ1 WHEN A NON-CONTIGUOUS DISK ADDRESS IS FOUND, CPOPJ WHEN
; THE ENTIRE ARGUMENT LIST HAS BEEN SCANNED, RETURNS P4 = # OF PAGES,
; P3 = FIRST PHYSICAL PAGE
PAGIMT: PUSHJ P,SAVE2## ;SAVE P1-P2
SE1ENT ;MUST BE IN SECTION 1 TO ADDRESS PAGTAB/MEMTAB
HRLZS P3 ;MAKE AOBJN POINTER
MOVE P1,T1 ;SAVE THE FIRST PHYSICAL PAGE ALLOCATED
PUSH P,[0] ;INIT FIRST VIRTUAL,,FIRST PHYSICAL
PUSH P,[0] ;INIT PREV DSK ADDR+PREV PHYS PAG
PAGIM1: PUSHJ P,INTLVL## ;AT INTERRUPT LEVEL?
TRNE P3,777 ;NO, DONE ~1000 PGS
CAIA ;DON'T WAIT
PUSHJ P,SCDCKM
PUSHJ P,NXTPAG ;GET THE NEXT USER ARGUMENT
JUMPL T1,PAGIM1 ;JUMP IF ARGUMENT INDICATES PAGE TO BE PAGED-OUT
HRRZS T1 ;CLEAR JUNK
PUSHJ P,GTPME ;GET THE CONTENTS OF THE MAP
IFN FTPEEKSPY,<
TLNE T2,(PM.SPY) ;SPY PAGE?
JRST PAGIM1 ;YES, DON'T TRY TO PAGE IT
>
MOVE T3,T2 ;PRESERVE DISK ADDRESS ACROSS CALL TO TSWST
PUSHJ P,TSWST ;ALREADY IN THE WORKING SET?
TDNN T3,[PM.ADR^!PM.ZER] ;NO, ABZ?
JRST PAGIM1 ;ALREADY IN OR ABZ PAGE (PG.IDC)
PUSHJ P,GTPME ;GET CONTENTS AND POINTER AGAIN
SKIPN .USTMU ;PAGES ON INCORE QUEUES?
JRST PAGIM4 ;NO, SKIP THIS
TLZ T2,(PM.NAD) ;ISOLATE ADDRESS
TLNE T3,(PM.OIQ) ;IS THIS PAGE ON THE "IN" QUEUE?
JRST PAGIM2 ;YES, SHOULD BE ON OUR QUEUE THEN
HRRZ T4,.USTMU ;GET HEADER FOR PRIVATE QUEUE
SKIPE T4 ;ANYTHING THERE?
PUSHJ P,SRCPQ0 ;YES, SEARCH QUEUE FOR PAGE
JRST PAGIM4 ;NOT THERE
SKIPN .USWLP ;IF WRITE-LOCKED PAGES, TAKE CARE OF IT LATER
PUSHJ P,[PUSHJ P,SAVT## ;SAVE VOLATILE ACS
PUSHJ P,TPAHS ;IF PAGE IS IN A HIGH SEGMENT, IT WILL GET
POPJ P, ; WRITE LOCKED SO DON'T GIVE BACK DISK SPACE
MOVE T2,-2(P);DISK ADDRESS TO BE RETURNED
PJRST DLTPGD];RETURN DISK SPACE
MOVE T2,T4 ;PAGE NUMBER TO T2
PAGIM2: HRRZ T3,.USTMU ;FIRST PAGE ON PRIVATE LIST?
CAIE T3,(T2) ;?
JRST [PUSHJ P,LKPSF ;NO, JUST LINK PAST
JRST PAGIM3] ;CONTINUE
SSX T3,MS.MEM ;POINT TO RIGHT SECTION
HRR T3,PAGTAB(T3) ;GET SUCCESSOR (IF ANY)
HRRM T3,.USTMU ;RESET LIST HEADER
TRNE T3,-1 ;IF THERE IS A SUCCESSOR
HLLZS PT2TAB(T3) ;CLEAR HIS BACK LINK
HLLZS @[IW MS.MEM,PAGTAB(T2)] ;CLEAR LINKS IN REMOVED PAGE
HLLZS @[IW MS.MEM,PT2TAB(T2)]
;HERE WITH PHYSICAL PAGE NUMBER IN T2
PAGIM3: MOVE P2,T2 ;PUT THIS PAGE ON THIS JOB'S PAGTAB CHAIN
LDB T3,JBYLSA## ; BUT PUT IT AT THE FRONT
SSX P2,MS.MEM ; ...
HRRM T3,PT2TAB(P2) ;JBYLSA IS PREVIOUS TO US
SSX T3,MS.MEM ; SO THAT A ZERO INDICATES THE LAST PAGE
EXCH T2,PAGTAB(T3) ; ALLOCATED FOR THIS PAGE IN
MOVEM T2,PAGTAB(P2) ; ...
SSX T2,MS.MEM
TRNE T2,-1 ;IF NOT LAST PAGE
HRRM P2,PT2TAB(T2) ;STORE BACK LINK
MOVSI T2,(P2.TRN) ;CLEAR TRANSIENT BIT
ANDCAM T2,PT2TAB(P2)
PUSHJ P,GTPME ;GET CONTENTS AND POINTER AGAIN
TLO P1,400000 ;PAGE ISN'T IN PAGTAB
HRRZS P2 ;CLEAR SECTION NUMBER
AND T2,[PM.NAD] ;ISOLATE ACCESS BITS
IOR P2,T2 ;ACCESS BITS+PHYSICAL PAGE NUMBER FOR BELOW
JRST PAGIM7 ;PUT THE PAGE IN THE WORKING SET
;HERE WHEN THE PAGE ISN'T ON A QUEUE, T2=MAP CONTENTS, P1=PHYSICAL PAGE NUMBER,
; 0(P)=PREVIOUS PHYSICAL PAGE NUMBER+PREVIOUS DISK ADDRESS OR 0 IF FIRST TIME
; THROUGH FOR THIS FRAGMENT
PAGIM4: JUMPE P1,PAGIM1 ;IF NO CORE ALLOCATED
ADDI P4,1 ;BUMP COUNT OF NUMBER OF PAGES IN THIS FRAGMENT
SSX P1,MS.MEM ;PAGTAB SECTION
MOVE P2,T2 ;MAP CONTENTS TO P2
TLZ T2,(PM.NAD) ;ISOLATE DISK ADDRESS
MOVEM T2,MEMTAB(P1) ;STORE DISK ADDRESS
SKIPE -1(P) ;FIRST TIME THROUGH FOR THIS FRAGMENT?
JRST PAGIM5 ;NO
HRRZM P1,-1(P) ;YES, REMEMBER FIRST PHYSICAL PAGE IN FRAGMENT
HRLM T1,-1(P) ;AND FIRST VIRTUAL PAGE IN FRAGMENT
JRST PAGIM6 ;SKIP ON SINCE DON'T KNOW NEXT VIRTUAL PAGE NUMBER YET
PAGIM5: LDB T2,[POINT 14,(P),35] ;PHYSICAL PAGE NUMBER FROM LAST TIME
SSX T2,MS.MEM ;PAGTAB SECTION
DPB T1,NVPNT2 ;STORE NEXT VPN
PUSHJ P,GTPME ;GET MAP CONTENTS
MOVE P2,T2 ;COPY IT
LDB T3,[POINT 21,(P),20] ;PREVIOUS DISK ADDRESS
AOS T3 ;FOR AJACENCY CHECK
XOR T3,T2 ;END THIS FRAGMENT? (THIS DISK ADDRESS
TDNE T3,[PM.ADR] ; NOT ADJACENT TO LAST)
SOJA P4,PAGIM9 ;FINISH UP THIS FRAGMENT
PAGIM6: DPB P1,[POINT 14,(P),35] ;SAVE PHYSICAL PAGE
DPB T2,[POINT 21,(P),20] ; AND DISK ADDRESS FOR NEXT TIME THROUGH
;HERE TO PUT PHYSICAL PAGE INTO THE MAP, P1=PHYSICAL PAGE NUMBER IF POSITIVE,
; P2=PHYSICAL PAGE NUMBER IF P1 IS NEGATIVE, LH(P2)= ACCESS BITS FOR PAGE,
; T4=BYTE POINTER TO THE MAP
PAGIM7: MOVE T3,T4 ;SAVE BYTE POINTER
PUSHJ P,WSBIT ;CHECK TO SEE IF THE PAGE IS IN THE WORKING
; SET (STOP IF IT IS), AND RETURN AN INDEX
; AND THE BIT POSITION TO ADD IT TO THE WORKING SET
AOS JBTIMI##(J) ;INCREASE THE NUMBER OF PAGES IN CORE
.CREF IMGIN
IORM T2,(T4) ;ADD THIS PAGE TO THE WORKING SET
MOVSI T2,(PM.BTS)
AND T2,P2 ;GET BITS FROM PREVIOUS ENTRY CONTENTS
SKIPGE P1 ;PAGE ALREADY IN CORE?
TROA T2,(P2) ;YES, PHYSICAL PAGE NUMBER IS IN P2
HRRI T2,(P1) ;PHYSICAL PAGE #
TLNN P2,(PM.AAB) ;SHOULD ACCESS ALLOWED BE ON FOR THIS PAGE?
TLZA T2,(<PM.DCD>B2)
TLO T2,(<PM.DCD>B2)
TLO T2,(PM.COR!PM.WRT) ;CORE ADDRESS+PM.WRT
SKIPN .USWLP ;CORE IMAGE ALREADY CONTAIN WRITE LOCKED PAGES?
JRST PAGI7A ;NO, PAGE DOESN'T HAVE A DSK ADDRESS
HRRZ T4,T2 ;PHYSICAL PAGE NUMBER
SSX T4,MS.MEM ;INDEX INTO MEMTAB
MOVE T4,MEMTAB(T4) ;GET DISK ADDRESS
TDNN T4,[MT.DAD] ;IF PAGE IS ON "IN" QUEUE, THERE'S NO DSK ADDR
JRST PAGI7A ;DON'T WRITE LOCK PAGE IF NO DSK ADDRESS
TLZ T2,(PM.WRT) ;WRITE LOCK THE PAGE
AOS .USWLP ;AND COUNT UP THE NUMBER OF WRITE LOCKED PAGES
PAGI7A: MOVEM T2,(T3) ;MAP THIS PAGE INTO THE USERS ADDRESS SPACE
PUSH P,T2 ;INCHJ CLOBBERS T2
PUSHJ P,INCHJ ;INCREMENTED THE NUMBER OF PAGES IN THE
; HIGH SEGMENT THAT ARE IN CORE
POP P,T2 ;RESTORE PAGE NUMBER
TLZN P1,400000 ;PAGE WAS ON A QUEUE?
JRST PAGIM8 ;NO
MOVSI T3,1 ;"DECREMENT" COUNT OF PAGES ON QUEUE
ADDB T3,.USTMU ;...
SKIPE T3 ;IF NOW ZERO (SHOULD BE IF DONE)
AOJA P3,PAGIM1 ;NO, GO GET ANOTHER ARGUMENT
JUMPE P1,PAGI10 ;DONE IF NO REAL PAGES (SHOULD BE TRUE)
AOJA P3,PAGIM1 ;YES, SETUP TO PAGE THEM IN
PAGIM8: SSX P1,MS.MEM ;PAGTAB SECTION
SKIPGE P1,PAGTAB(P1) ;GET THE NEXT PHYSICAL PAGE ALLOCATED
STOPCD CPOPJ##,DEBUG,APF, ;++ALLOCATED PAGE FREE
AOBJN P3,PAGIM1 ;IF NO QUEUED PAGES, ARE THERE MORE PHYSICAL?
SKIPE .USTMU ;STILL SOME QUEUED PAGES?
JRST PAGIM1 ;YES, GO PUT THEM IN THE MAP
JRST PAGI10
;HERE WHEN FRAGMENTED
PAGIM9: PUSHJ P,PREPAG ;BACK UP
MOVE T1,P1 ;WHERE TO START ON NEXT CALL
AOSA -2(P) ;FRAGMENTED RETURN
PAGI10: LDB P1,[POINT 14,(P),35] ;GET LAST PHYSICAL PAGE
POP P,T2 ;POP OFF REMINDER
POP P,P3 ;FIRST VIRTUAL,,FIRST PHYSICAL
JUMPE T2,CPOPJ## ;RETURN IF ALL PAGES ARE ALREADY IN CORE
SSX P1,MS.MEM ;MEMTAB SECTION
HLRZ P2,P3 ;FIRST PAGE OF FRAGMENT
DPB P2,NVPNP1 ;SET NEXT PAGE OF FRAGMENT
MOVSI P2,(MT.LEF)
IORM P2,MEMTAB(P1) ;STORE AS LAST PAGE OF FRAGMENT
POPJ P,
;SUBROUTINE TO SETUP MEMTAB FOR PAGING OUT
;CALLING SEQUENCE:
; MOVE M,ADDRESS - 1 OF ENTRY IN THE ARGUMENT LIST
; MOVE U,XWD - NUMBER OF PAGES ALLOCATED CONTIGUOUSLY ON THE DISK,
; STARTING DISK ADDRESS
; MOVEI P1,-# OF PAGES TO GO OUT
; MOVEI P3,0
; PUSHJ P,PAGOMT
;ALWAYS RETURNS CPOPJ
PAGOMT: PUSHJ P,SAVE2## ;SAVE P1-P2
SE1ENT ;MUST BE IN SECTION 1
PAGOM1: PUSHJ P,INTLVL## ;AT INTERRUPT LEVEL?
TRNE P1,777 ;IF NOT, STOP APPROX EVERY 1000 PGS
CAIA
PUSHJ P,SCDCKM
PUSHJ P,NXTPAG ;GET THE NEXT ARGUMENT FROM THE USER'S ARGUMENT LIST
JUMPGE T1,PAGOM1 ;JUMP IF THE ARGUMENT REQUESTS PAGING-IN
PAGOM2: HRRZS T1 ;PAGING-OUT, CLEAR THE HIGH ORDER BITS
PUSHJ P,GTPME ;GET THE CONTENTS OF THE MAP
IFN FTPEEKSPY,<
TLNE T2,(PM.SPY) ;SPY PAGE?
JRST PAGOM1 ;YES, DON'T TRY IT
>
MOVE T3,T2 ;SAVE ENTRY
PUSHJ P,TSWST ;IN THE WORKING SET?
JRST PAGOM1 ;IDC MUST HAVE BEEN ON IF IT ISN'T IN THE WS
TDNE T3,[PM.ADR^!PM.ZER] ;ABZ PAGE?
;(ZERO ENTRY SHOULD BE CAUGHT BY PLTSN)
.CREF IMGIN
SOSA JBTIMI##(J) ;DECREMENT # OF PAGES IN CORE
JRST PAGOM1 ;ABZ OR IN CORE, MUST BE PG.IDC
SKIPE .USWLP ;PAGES HAVE DISK ADDRESSES?
TLNE T3,(PM.WRT) ;WRITE ENABLED?
TLZA M,40000 ;NO, REMEMBER THAT
TLO M,40000 ;YES
TLZ T3,(PM.NAD) ;CLEAR ACCESS BITS (GET PHYS PAGE NUM)
JUMPN P3,PAGOM3 ;JUMP IF NOT FIRST TIME THROUGH FOR THIS FRAGMENT
HRLI P3,(T1)
HRR P3,T3 ;REMEMBER FIRST VIRTUAL AND FIRST PHYSICAL PAGE
PAGOM3: MOVE P2,T3 ;SAVE PHYSICAL PAGE NUMBER
PUSH P,T1 ;SAVE VIRTUAL PAGE NUMBER
MOVE T2,P2 ;ARG FOR LKPSP
PUSHJ P,LKPSF ;LINK PAST THE PHYSICAL PAGE IN PAGTAB
MOVE T1,P2 ;CURRENT PHYSICAL PAGE
MOVEI T3,PAGINQ## ;ASSUME PAGE IS TO GO ON THE "IN" QUEUE
TLNE M,ARGMD ;DID THE USER SPECIFY SLOW SWAPPING SPACE?
MOVEI T3,PAGSNQ## ;YES, PUT THE PAGE ON THE SLOW SWAPPING "IN" QUEUE
TLNE M,40000 ;IF PAGE IS WRITE LOCKED,
MOVEI T3,PAGOUQ## ; GO DIRECTLY TO "OU" QUEUE, DON'T PASS GO,
; DON'T COLECT 200 DOLLARS
PUSHJ P,ADDPTQ ;PUT THE PAGE ON THE SPECIFIED QUEUE
POP P,T1 ;RESTORE VIRTUAL PAGE NUMBER
SSX P2,MS.MEM ;FOR ADDRESSING MEMTAB BELOW
PUSHJ P,DECHJ ;DECREMENT NUMBER OF PAGES IN CORE IF A HIGH SEGMENT
PUSHJ P,TSWST ;IS THIS PAGE IN THE WORKING SET? (MUST BE)
STOPCD PAGOM2,DEBUG,PIW, ;++PAGE ISN'T IN WORKING SET
ANDCAM T2,(T4) ;IT WON'T BE AFTER PAGING IT OUT
PUSHJ P,GTPME ;GET MAP CONTENTS AGAIN
TLZ T2,(<PM.DCD>B2!PM.COR) ;NO ACCESS, MAKE IT LOOK OUT
SKIPE .USWLP ;PAGES HAVE DISK COPIES?
TLNE T2,(PM.WRT) ;PAGE WRITE LOCKED (STILL HAS A DISK COPY)?
JRST PAGOM4 ;NO
MOVEI T3,0 ;ZERO MEMTAB ENTRY
EXCH T3,MEMTAB(P2) ; AND GET DISK ADDRESS
TDZ T3,[PM.NAD] ;ISOLATE DISK ADDRESS
AND T2,[PM.BTS] ;EXTRACT ACCESS BITS
IOR T2,T3 ;ADD IN DISK ADDRESS
MOVEM T2,(T4) ;STORE IN THE MAP
SOS .USWLP ;ONE LESS WRITE LOCKED PAGE
JRST PAGOM5 ;NEXT PAGE
PAGOM4: TLO T2,(PM.OIQ) ;INDICATE ON "IN" QUEUE
TLNE M,ARGMD ;DID THE USER SPECIFY SLOW SWAPPING?
TLO T2,(PM.SSP) ;YES, REMEMBER THAT TOO
MOVEM T2,(T4) ;STORE IT BACK IN THE MAP
DPB T1,NVPNP2 ;STORE VIRTUAL PAGE #
.CREF P2.MBZ ;IMPLIED BIT SET
MOVE T2,.USJOB ; AND JOB NUMBER (FOR SWAPPER FIXUP)
LSH T2,<^D35-<^L<MT.JOB>+MT.SJB-1>>
MOVEM T2,MEMTAB(P2) ;SET MEMTAB, CLEARING REST
.CREF MT.DAD ;(IN PARTICULAR, THE DISK ADDRESS)
PAGOM5: AOJL P1,PAGOM1 ;LOOP OVER ALL PAGES TO BE PAGED OUT
S0JRST JSTVRT ;SET .UPVRT NON-0, UPDATE VMCMAX AND RETURN
;SUBROUTINE TO COMPUTE THE PAGING-RATE FOR A USER
;ENTER WITH P1=NUMBER OF PAGES IN THE UUO
;EXIT LH(.PDVRT)=T1 CONTAINING THE NEW INTERVAL
USRATE::PUSH P,W ;SAVE W
PUSHJ P,FNDPDB## ;GET PDB
JRST WPOPJ##
PUSHJ P,GTDTIM ;GET DELTA TIME MT2
IDIVI T2,(P1) ;BIAS BY NUMBER OF PAGES XFERRED
CAMLE T2,MAXINT## ;GREATER THAN MAX INTERVAL?
MOVE T2,MAXINT## ;YES, USE MAX INTERVAL
IMUL T2,VMCNST## ;ALPHA(*(DELTA-T)/N)
HLRZ T1,.PDVRT##(W)
IMUL T1,VMCDIF## ;(EXP-ALPHA)*INT(I-1)
ADD T1,T2 ;ADD IN THE CURRENT CONTRIBUTION
IDIV T1,VMCEXP## ;SCALE IT
USRAT1: HRLZM T1,.PDVRT##(W) ;AND SAVE NEW VALUE
JRST WPOPJ##
;SUBROUTINE TO COMPUTE THE SYSTEM-WIDE PAGING RATE
SYRATE: MOVE T1,SYSUPT##
SUB T1,LSFTIM## ;COMPUTE SYSTEM-WIDE PAGING INTERVAL
IDIVI T1,(P1)
IMUL T1,VMCNST##
MOVE T2,JBTVIR##
IMUL T2,VMCDIF##
ADD T1,T2
IDIV T1,VMCEXP##
MOVEM T1,JBTVIR## ;SAVE SYSTEM-WIDE INTERVAL
MOVE T2,SYSUPT## ;SAVE LAST FAULT TIME
MOVEM T2,LSFTIM##
POPJ P,
;SUBROUTINE TO ADJUST PAGING RATE OF USER IF NO PAGES TRANSFERRED DURING INTERVAL
PGRUPD::PUSH P,W
PUSHJ P,GTDTIM ;GET DELTA-TIME IN T2
CAMLE T2,MAXINT## ;IF TOO BIT
MOVE T2,MAXINT## ;THEN CUT DOWN
IMUL T2,VMCNST## ;ADJUST BY PAGE RATE ALGORITHM
IDIV T2,VMCDIF## ;..
PUSHJ P,FNDPDB## ;GET PDB
TDZA T1,T1 ;?
HLRZ T1,.PDVRT##(W)
ADD T1,T2 ;ADJUST BY TIME GONE BY
CAMLE T1,MAXINT## ;CHECK FOR OVERFLOW
MOVE T1,MAXINT## ;IF SO, USE MAXIMUM
JRST USRAT1 ;SAVE NEW VALUE AND RETURN
;SUBROUTINE TO COMPUTE DELTA TIME.
; STARTS NEW INTERVAL, RETURNS TIME DURING LAST INTERVAL IN T2
GTDTIM: MOVE T1,.PDTTM##(W) ;GET CURRENT RUN TIME
MULI T1,RTUPS## ;CONVERT TO 10-MICRO SEC UNITS
ADD T2,.PDTT2##(W)
DIV T1,TICSEC## ;CONVERT
MOVE T2,T1
SUB T2,.USLFT ;COMPUTE DELTA-TIME
MOVEM T1,.USLFT ;SAVE NOW AS LAST FAULT TIME
POPJ P, ;RETURN
;SUBROUTINE TO SCAN PAGTAB
;RETURNS T1= LAST PAGE IN PAGTAB CHAIN
;SCNPT PRESERVES T3
REPEAT 0,<
SCNPTB: SE1ENT ;GET TO SECTION 1 TO ADDRESS PAGTAB
LDB T1,JBYLSA## ;GET FIRST PAGE ALLOCATED TO THIS JOB
TLZA P4,-1 ;INDICATE NO PREDESSOR
SCNPT1: HRRZ T1,T2 ;PREDESSOR TO NEXT PAGE
SSX T1,MS.MEM ;PAGTAB SECTION
SKIPGE T2,PAGTAB(T1) ;GET NEXT PAGE ALLOCATED TO THIS JOB
STOPCD .+1,DEBUG,IPF, ;++IN-USE PAGE FREE
HRRZS T2
JUMPN T2,SCNPT1 ;JUMP IF NOT LAST PAGE ALLOCATED TO JOB
HRRZS T1 ;CLEAR SECTION NUMBER
POPJ P, ;RETURN
>
;MAKE SWPLST ENTRY, START IO, RETURN SWPLST INDEX IN T2
PGWAIT: MOVEI T2,PIOWQ## ;PAGE I/O QUEUE CODE
DPB T2,PJBSTS## ;PUT THE JOB INTO PAGE I/O WAIT
IFN FTMP,<
PUSH P,T1 ;SETCSJ DESTROYS T1
PUSHJ P,SETCSJ## ;SET JBTST3 ETC. IN CASE NEXT IS CALLED
POP P,T1 ;RESTORE SWPLST ENTRY
>
PUSHJ P,MAKSLE ;MAKE THE SWPLST ENTRY
HRRM T2,.USSLX
PUSHJ P,SQOUT## ;START THE PAGING IO
HRRZ T2,.USSLX ;GET SWPLST INDEX
MOVE J,.CPJOB## ;CURRENT JOB'S JOB NUMBER
MOVE R,JBTADR##(J) ;ADDRESS OF THE JOB
IFN FTMP,<
PUSHJ P,REMMM## ;REMEMBER STATE OF THE MM
>
PUSHJ P,WSCHED## ;WAIT UNTIL IT IS RUNNABLE AGAIN
MOVE T1,SWPLST##(T2) ;GET THE SWPLST ENTRY FOR THIS PAGING OPERATION
TLNN T1,(SL.CHN+SL.ERR)
AOS (P) ;SKIP RETURN SINCE NO PAGING I/O ERRORS
POPJ P, ;RETURN TO WAITER
;SUBROUTINE TO GET A PAGE INTO CORE
;ENTER T1=SWPLST ENTRY
;RETURNS WHEN PAGE IS IN CORE - CPOPJ IF IO ERROR, CPOPJ1 IF OK
PAGEIT::PUSHJ P,SAVE1## ;SAVE P1
PUSHJ P,PGWAIT ;WAIT UNTIL ITS DONE
POPJ P, ;PAGING I/O ERROR
HRRZ P1,T2 ;INDEX INTO SWPLST
AOS (P) ;OK RETURN
PJRST DLTSLX ;DELETE THE SWPLST ENTRY AND RETURN
;HERE TO CREATE OR DELETE PAGES
CHGPGS: MOVEI T2,PA.PME+PA.PCE;PAGE MUST EXIST ON DESTROY, CANNOT ON CREATE
PUSHJ P,PLTSN ;VALIDATE THE ARGUMENT LIST
POPJ P, ;ILLEGAL ARGUMENT
TLNE M,HSPAG ;ANY HI SEG PAGES IN ARG LIST?
JUMPN T2,IALERR ;YES, CANT DELETE HI-SEG PAGES
PUSHJ P,FSTPAG ;POINT M AT THE USER'S ARGUMENT LIST
PUSHJ P,SZCHKX ;MAKE SURE THAT THE JOB WON'T BE TO BIG IF
; PAGES ARE CREATED AFTER DESTROYING THOSE
; SPECIFIED IN THE ARGUMENT LIST
JRST [TLNN M,ARGMD ;TRYING TO GET TO BIG
JRST TBGERR
JRST .+1]
PUSHJ P,SAVE4## ;SAVE P1-P4
MOVE P3,T4 ;#SECTION MAPS+.WSBNZ
SUBI T1,(T2) ;CURRENT VIRTUAL SIZE MINUS PAGE BEING DESTROYED
SUB T1,.USTMU ;MINUS ALLOCATED BUT ZERO PAGES
ADDI T1,(T3) ;REAL NEW SIZE
HLRZ T4,.PDCVL##(W) ;CURRENT VIRTUAL LIMIT
CAILE T1,UPMPSZ##(T4) ;TRY TO GET TO BIG?
JUMPN T3,[JUMPN T4,TBGERR ;YES, ERROR RETURN
TLNE M,ARGMD
JRST NVLERR
JRST .+1]
MOVE T1,T3 ;NUMBER OF PAGES BEING CREATED
SUBI T1,(T2) ;MINUS THE NUMBER OF PAGES BEING DESTROYED
SUB T1,.USTMU ;MINUS ALLOCATED BUT ZERO PAGES
; (THEY'RE ALREADY ALLOCATED FOR IN VMCMAX)
HRROI T4,777000
AND T4,.USVRT ;GET VIRTUAL STATUS, EXCEPT ANA
TLNE M,ARGMD ;CREATING ABZ PAGES (IF SO WILL BE VIRTUAL)
AOS T4 ;YES, BE SURE T4 IS NON-ZERO
CAMLE T1,VMCMAX## ;TRYING TO EXCEED MAX VM CORE?
JUMPN T4,NSAERR ;CHECK ONLY VALID IF NOT VIRTUAL
ADDI T1,(P3) ;PLUS NUMBER OF SECTION MAPS BEING CREATED
CAMLE T1,VIRTAL## ;IS THERE ENOUGH VIRTUAL CORE TO SATISFY THE REQUEST?
JRST NSAERR ;CAN NEVER EXCEED VIRTAL, HOWEVER
ANDCMI T4,PG.BDY ;(CLEAR ANY AOS WE MAY HAVE DONE)
JUMPE T4,CHGPG1 ;IF NOT ALREADY VIRTUAL, SETVRT WILL FIX VM(CMAX,TOTL)
SUBI T1,(P3) ;MAPS ETC NOT INCLUDED IN VMCMAX
ADDM T1,VMTOTL##
MOVNS T1
ADDM T1,VMCMAX## ;DECREASE TOTAL AMOUNT OF VIRTUAL CORE AVAILABLE
CHGPG1: SE1ENT ;FOR PAGTAB/MEMTAB/PAGE MAP ENTRIES
JUMPE T2,CHGPG4 ;JUMP IF NOT DESTROYING PAGES
PUSH P,T3 ;SAVE THE NUMBER OF PAGES BEING CREATED
PUSH P,T2 ;AND THE NUMBER BEING DELETED
PUSHJ P,INTLVL## ;DON'T WAIT AT CLOCK LEVEL
PUSHJ P,IOWATM ;WAIT FOR I/O TO STOP
CHGPG2: PUSHJ P,NXTPAG ;GET THE NEXT ARGUMENT
JUMPGE T1,CHGPG2 ;JUMP IF NOT A DELETE REQUEST
HRRZS P1,T1 ;CLEAR THE HIGH ORDER BIT, CLEAR LEFT HALF OF P1
MOVE T3,T1
LSHC T3,P2SLSH
PUSHJ P,GTPME ;GET PAGE MAP ENTRY NOW
JUMPE T2,CHGPG2 ;DOESN'T REALLY EXIST (PG.IDC)
EXCH T1,T3
PUSHJ P,DECNZC ;DECREMENT NZS COUNT IF APPLICABLE
EXCH T1,T3
PUSHJ P,DLTPAG ;DELETE THE PAGE
CHGPG3: SOSLE T1,(P) ;DELETED ALL THAT WERE REQUESTED?
JRST [PUSHJ P,INTLVL## ;AT INTERRUPT LEVEL?
TRNE T1,777 ;NO, STOP EVERY APPROX 1000 PAGES
JRST CHGPG2 ;AT CLOCK LEVEL OR LIMIT NOT EXPIRED
PUSHJ P,SCDCKM ;WAIT
JRST CHGPG2]
PUSHJ P,FSTPAG ;RESTORE THE ARGUMENT LIST POINTER
POP P,(P) ;POP OFF JUNK
POP P,T3 ;RESTORE THE NUMBER OF PAGES BEING CREATED
CHGPG4: JUMPE T3,FIXADR ;CLEAR THE A.M. AND RETURN TO THE USER IF NOT
; CREATING PAGES
ADDI T3,(P3) ;INCLUDE SECTION MAPS BEING CREATED
MOVE P2,T3 ;SAVE THE NUMBER OF PAGES BEING CREATED
MOVN T1,T3 ;MINUS THE NUMBER OF PAGES BEING CREATED
ADDM T1,VIRTAL## ;UPDATE VIRTAL TO REFLECT THE DECREASE
TLNE M,ARGMD ;CREATING ABZ PAGES?
SKIPE T3,P3 ;SHOULD ALLOCATE PAGES ANYWAY IF NEED MAPS
CAIA
JRST CHGPG5 ;CREATE ABZ PAGES (NO MAPS TO MAKE)
PUSHJ P,FRDCRW## ;ARE THERE ENOUGH PAGES IN CORE TO SATISFY REQUEST?
JRST CHGP10 ;NOT ENOUGH, EXPAND
PUSH P,P2 ;# OF PAGES BEING CREATED
TLNE M,ARGMD ;UNLESS IT'S ALL ABZS
MOVEM T3,(P) ;THEN ONLY WANT # OF MAPS
POP P,T2 ;RESTORE # OF PAGES TO GET
LDB T1,JBYSSA## ;FIRST PAGE OF JOB
PUSHJ P,ADPAGS## ;ALLOCATE THE PAGES
MOVSI P1,NSHF ;FORCE NON-SWAPPABILITY
IORM P1,JBTSTS##(J) ;(NSWP CAN'T BE ON HERE)
;HERE WITH T1 = FIRST PHYSICAL PAGE ALLOCATED
SKIPA P1,T1 ;FIRST PHYSICAL PAGE ALLOCATED TO P1
CHGPG5: SETZ P1, ;NO PAGES ALLOCATED (ABZS ONLY)
SUBI P2,(P3) ;DON'T INCLUDE SECTION PAGES IN MAP COUNTER
CHGPG6: PUSHJ P,NXTPAG ;GET THE NEXT ARGUMENT
JUMPL T1,CHGPG6 ;JUMP IF DELETE PAGE REQUEST
HRRZS T1 ;CLEAR BIT 1
LSHC T1,P2SLSH ;SECTION #
PUSHJ P,CRSMAP ;CREATE SECTION MAP AND/OR POINT TO IT
MOVE T3,T1 ;SAVE SECTION #
LSHC T1,S2PLSH ;BACK TO PAGE #
PUSHJ P,ISITNZ ;ONLY REMEMBER S0 PAGES
HRL P4,T1 ;SAVE THE HIGHEST VIRTUAL PAGE SEEN SO FAR
PUSHJ P,GTPME ;GET POINTER TO THE MAP SLOT (PAGE NO IN T1)
TLZ T2,(PM.NAD)
CAMN T2,[PM.ZER] ;ABZ PAGE?
JRST CHGPG7 ;YES
JUMPN T2,CHGPG6 ;NO, MUST BE REAL PAGE (PG.IDC)
EXCH T1,T3 ;SAVE PAGE #, GET SECION #
PUSHJ P,INCNZC ;INCREMENT AS REQUIRED
MOVE T1,T3 ;RESTORE PAGE #
CHGPG7: TLNN M,ARGMD
JRST CHGPG8
PUSH P,T1 ;SAVE T1
CAMN T2,[PM.ZER]
PUSHJ P,INSMEM ;YES, FIX VIRTAL
POP P,T1 ;RESTORE PAGE #
MOVE T2,[PM.WRT!PM.AAB!PM.CSH!PM.PUB+PM.ZER] ;ASSUME WRITABLE
PUSHJ P,TPNHS ;A HIGH SEG PAGE?
TLZ T2,(PM.WRT) ;NOT WRITABLE
MOVEM T2,(T4) ;STORE THAT IN THE MAP
JRST CHGPG9 ;GET THE NEXT ARGUMENT
;HERE TO ADD A PAGE, T1=VIRTUAL PAGE NUMBER, P1 = PHYSICAL PAGE NUMBER,
; MAKE THE MAP ENTRY AND TURN ON THE BIT IN THE WORKING SET BIT TABLE
CHGPG8: PUSHJ P,INSPAG ;INSERT THE PAGE IN THE USER'S MAP
;HERE TO ZERO THE PAGE OBTAINED
PUSHJ P,ZERPAG ;ZERO THE PAGE
PUSHJ P,INCHJ ;INCREMENT THE NUMBER OF PAGES ALLOCATED
; IN CORE TO THE HIGH SEGMENT IF THIS IS A HIGH
; SEGMENT PAGE
CHGPG9: PUSHJ P,ICUPR ;UPDATE THE HIGHEST CONTIGUOUS PAGE IN THE LOW SEG
SOJLE P2,[MOVSI T1,NSHF
ANDCAM T1,JBTSTS##(J)
HLL P4,P1 ;HIGHEST PAGE SEEN
JRST FIXADR] ;.DONE
PUSHJ P,INTLVL## ;AT CLOCK LEVEL?
TRNE P2,777 ;NO, STOP EVERY APPROX 1000 PAGES
CAIA
PUSHJ P,SCDCKM ;TO CHECKFOR OTHER THINGS
TLNN M,ARGMD
SKIPA T1,P1 ;LAST PAGE
JRST CHGPG6 ;ONLY ABZS
SSX T1,MS.MEM ;SET TO GET NEXT PAGE
HRR P1,PAGTAB(T1) ;P1 = PHYSICAL PAGE NUMBER OF NEXT PAGE ALLOCATED
JRST CHGPG6 ;LOOP OVER ALL
;HERE WHEN NOT ENOUGH PAGES AVAILABLE IN CORE TO SATISFY A CREATE PAGES
; REQUEST
CHGP10: TLNE M,ARGMD ;JUST CREATING ABZ PAGES?
JRST CHGPG5 ;YES, MUST BE HERE BECAUSE NEEDED MAPS (IGNORE)
SETZ P4, ;FLAG WE'RE REALLY CREATING
CHGP11: SKIPE T4,P3 ;# OF SECTION MAPS NEED TO CREATE
PUSHJ P,GSMPG3 ;GET SECTION MAP PAGES (ALREADY KNOW ABOUT .WSBNZ)
MOVSI T1,NSHF ;DON'T SWAP 'TIL READY
IORM T1,JBTSTS##(J)
MOVNS P3 ;# OF MAP PAGES
ADD P2,P3 ;DON'T INCLUDE AS INCREASE
ADD P3,T3 ;SAVE THE NUMBER OF PAGES TO BE CREATED
PUSHJ P,INTLVL## ;NO WAITING AT CLOCK LEVEL
PUSHJ P,IOWATM ;WAIT FOR I/O TO STOP BEFORE CALLING XPAND
CHGP12: PUSHJ P,INTLVL## ;INTERRUPT LEVEL?
TRNE P3,777 ;NO, STOP APPROX EVERY 1000 PAGES
CAIA
PUSHJ P,SCDCKM
PUSHJ P,NXTPAG ;GET THE NEXT ARGUMENT
JUMPL T1,CHGP12 ;JUMP IF NOT CREATE PAGE ARGUMENT
LSHC T1,P2SLSH ;GET SECTION #
PUSHJ P,CRSMAP ;CREATE SECTION MAP
MOVE T3,T1 ;SAVE SECTION #
LSHC T1,S2PLSH
HRL P2,T1 ;SAVE THE HIGHEST VIRTUAL PAGE SEEN
PUSHJ P,GTPME ;GET ENTRY
TLNE T2,(PM.COR) ;IS THIS PAGE IN CORE?
JUMPN P4,CHGP12 ;YES, MUST HAVE BEEN ON A QUEUE
TLZ T2,(PM.NAD) ;SEE IF...
TDNE T2,[PM.ADR^!PM.ZER] ;PAGE ALREADY EXIST (IDC)?
JUMPE P4,CHGP12 ;YES, UNLESS HERE FROM PAGE IN/OUT
CHGP13: EXCH T1,T3 ;IN CASE CALLING INCNZC
CAME T2,[PM.ZER] ;AN ABZ...
PUSHJ P,INCNZC ;INCREMENT NZS COUNT
MOVE T1,T3
PUSHJ P,INCHJ ;INCREMENT NUMBER OF HIGH SEGMENT PAGES
; IN CORE IF THIS IS A HIGH SEGMENT PAGE
; EVEN THOUGH ITS NOT IN CORE YET SINCE
; IT WILL BE WHEN THE JOB SWAPS IN
MOVE T3,T1 ;PUT PAGE # BACK IN T3
PUSHJ P,TPNHX ;SHARABLE HS PAGE?
SKIPG .HBSGN(T2) ;?
TDZA T2,T2
MOVEI T2,INSDWL-INSDWE
MOVE T1,T3 ;RESTORE T1 TO PAGE #
PUSHJ P,INSDWE(T2)
PUSHJ P,GTPME ;CONTENTS OF THE MAP SLOT
TDNN T2,[PM.ADR] ;PAGE # OR DISK ADDRESS?
PUSHJ P,ICUPR ;UPDATE UPREL IF A CONTIGUOUS PAGE
SOJG P3,CHGP12 ;LOOP OVER ALL ARGUMENTS
MOVSI T1,NSHF
ANDCAM T1,JBTSTS##(J)
JRST FIXDSK ;FIX REVELANT VARIABLES
;SUBROUTINE FOR ABOVE TO CREATE AND/OR MAP TO PROPER SECTION WHEN CREATING PAGESS
;ENTER WITH T1=USER SECTION TO CREATE, P1=PHYSICAL PAGE ALLOCATED FOR IT
;(CHAINED FROM PAGTAB)
;IF P1=0, THEN THE MAP WILL BE CREATED AND THE JOB WILL SWAP OUT
;(ASSUMING NOT LOCKED) AND RETURN WHEN THE MAP IS IN CORE. IF P1 IS
;NEGATIVE, THEN THE MAP WILL BE CREATED ON DISK, BUT THE THE JOB WILL
;NOT SWAP OUT. IN THE LATTER CASE IT IS THE CALLER'S RESPONSIBILITY TO SET
;UP.BIG WHEN .WSBNZ EXISTS IN CORE
CRSMAP: SE1ENT
PUSH P,T1 ;SAVE T1
ANDI T1,MXSECN ;ENFORCE LEGALITY
PUSH P,T2 ;SAVE T2
PUSH P,T4 ;SAVE T4
SKIPE .UPMP+SECTAB(T1);SECTION EXIST?
JRST CRSMP5 ;YES, JUST SET UP AND RETURN
JUMPLE P1,CRSMP7 ;NO CORE
CRSMP1: PUSH P,P1
SSX P1,MS.MEM
MOVSI T2,(UP.BIG) ;BIG USER BIT
TDNE T2,.USBTS ;ALREADY BIG?
JRST CRSMP2 ;YES, DON'T WORRY ABOUT IT
IORM T2,.USBTS ;SET BIT
MOVEI T2,(P1) ;GET PHYSICAL PAGE
HRLI T2,(<PM.DCD>B2+PM.WRT+PM.PUB) ;BITS
MOVEM T2,.UPMP+.UMWSB ;CREATE NZS WSBTAB
PUSHJ P,CLPTZO
EXP .WSBNZ
PUSHJ P,ZPAGE
PUSHJ P,[PUSH P,T1 ;SAVE T1 AGAIN
MOVEI T1,.UPMVP/PAGSIZ-2 ;.WSBNZ VPN
JRST TSWST1];GET BIT MASK FOR IT
IORM T2,(T4) ;PUT IT ON IN WSBTAB TOO
MOVSI T4,1 ;AND ADD TO # OF FSPACE PAGES
ADDM T4,JBTPDB##(J) ;..
HRR P1,PAGTAB(P1) ;NEXT FREE PAGE
HRRM P1,(P) ;SAVE UPDATED P1
CRSMP2: MOVEI T2,(P1) ;PAGE #
JUMPLE T2,[POP P,P1 ;RESTORE UPDATE P1
JRST CRSMP7]
HRLI T2,(<PM.DCD>B2+PM.CSH+PM.PUB+PM.WRT+PM.COR)
MOVEM T2,.UPMP+SECTAB(T1)
HRR P1,PAGTAB(P1) ;NEXT PAGE
PUSHJ P,ZPAGE
PUSHJ P,[PUSH P,T1 ;SAVE T1
MOVEI T1,.UPMVP/PAGSIZ(T1)
JRST TSWST1];GET BIT MASK
;IGNORE .USSPT)
IORM T2,(T4) ;TURN IT ON
CRSMP3: HRRM P1,(P) ;NOW SAVE CURRENT RH(P1)
LDB P1,NZSSCN## ;# OF MAPS
AOS P1 ;ONE MORE
DPB P1,NZSSCN##
POP P,P1
CRSMP5: SOJL T1,CRSMP6 ;IN CASE S0
IDIVI T1,^D36/UP.SCS ;GET COUNTER
LDB T4,PNTNZS(T2) ;GET IT
JUMPN T4,CRSMP6 ;DONE
MOVEI T4,UP.VRG
DPB T4,PNTNZS(T2)
CRSMP6: POP P,T4
JRST TTPOPJ## ;RETURN
;HERE IF DON'T HAVE ANY MORE CORE FOR MAPS
CRSMP7: MOVSI T2,NSWP!NSHF ;LOCKED?
TDNE T2,JBTSTS##(J) ;?
JRST CRSM11 ;YES, WAIT FOR CORE TO APPEAR, I GUESS
PUSH P,T1 ;SAVE T1
MOVEI T1,.UPMVP/PAGSIZ(T1)
PUSHJ P,INSDMC ;INSERT THE PAGE
LDB T2,NZSICN## ;NUMBER OF MAPS ALREADY WAITING FORE
SKIPN T2 ;THERE ARE SOME
LDB T2,NZSSCN## ;IF NOT, NUMBER WE ALREADY HAVE
AOS T2 ;INCREASE
DPB T2,NZSICN## ;# NEED FOR SWAPIN
CRSMP8: SKIPGE .USBTS ;ALREADY A BIG USER?
JRST CRSM10 ;YES, DON'T WORRY ABOUT .WSBNZ
CRSMP9: MOVEI T1,.UPMVP/PAGSIZ-1-1 ;VPN OF .WSBNZ
PUSHJ P,INSDMU ;PUT THE PAGE IN
LDB T2,IFYPGS## ;# OF FUNNY PAGES NEED
SKIPN T2
LDB T2,NFYPGS## ;FIRST TIME
AOS T2
DPB T2,IFYPGS## ;NUMBER FOR SWAPIN
CRSM10: JUMPL P1,[POP P,T1 ;RESTORE T1
JRST CRSMP5];RESTORE ACS AND RETURN
PUSH P,S ;SAVE S AND F
PUSH P,F
PUSHJ P,IOWAT ;..
POP P,F ;RESTORE
POP P,S
PUSHJ P,XPANDH## ;MARK JOB AS EXPANDING
IFN FTMP,<
PUSHJ P,DIFMM## ;SAVE STATE OF MM
>
PUSHJ P,WSCHED## ;WAIT 'TIL WE COME BACK
IFN FTMP,<
PUSHJ P,UIFMM## ;GET THE MM BACK
>
POP P,T1 ;RESTORE T1
MOVSI T4,(UP.BIG) ;SET BIT
IORM T4,.USBTS
JRST CRSMP5 ;RESTORE ACS, SET MAP, SET BITS
CRSM11: PUSH P,T3
MOVEI T1,.UPMVP/PAGSIZ-1-1
PUSHJ P,TSWST ;.WSBNZ EXIST?
SKIPA T3,[1] ;NEED A PAGE FOR IT
SETZ T3,
AOS T3
CRSM12: PUSHJ P,FRDCRW## ;AVAILABLE NOW?
JRST CRSM13 ;NO
MOVEI T2,(T3)
LDB T1,JBYSSA## ;FIRST PAGE OF JOB
PUSHJ P,ADPAGS##
MOVEI P1,(T1)
POP P,T3
MOVE T1,-1(P)
JRST CRSMP1
CRSM13:
IFN FTMP,<
PUSHJ P,DIFMM##
>
MOVEI T1,1
PUSHJ P,SLEEPF##
IFN FTMP,<
PUSHJ P,UIFMM##
>
JRST CRSM12
;HERE IF CREATED MAP BUT NOT .WSBNZ
CRSM14: HLL P1,(P) ;RESTORE LEFT HALF OF P1
POP P,(P) ;LEAVE T4 ON STACK
JRST CRSMP9
;HERE TO GET PAGES FOR A SECTION MAP. RETURN WITH FIRST
;PAGE ALLOCATED IN P1, CALL WITH # OF PAGES TO GET IN T4. OVERWRITES
;ONLY P1. IF PAGES NOT AVAILABLE, RETURNS WITH P1=0
GSMPGS: JUMPE T4,CPOPJ## ;JUST IN CASE
PUSHJ P,SAVT## ;SAVE EVERYTHING
SKIPL .USBTS ;ALREADY A BIG USER?
AOS T4 ;NO, ADD ONE FOR .WSBNZ
GSMPG1: MOVEI T3,(T4) ;# TO CREATE
PUSHJ P,FRDCRW## ;AVAILABLE?
JRST [SKIPE T4,BIGHOL## ;GET AS MUCH AS WE CAN
JRST GSMPG2
SETZ P1, ;NONE AVAILABLE
POPJ P,] ;SO GIVE UP NOW
GSMPG2: MOVEI T2,(T4)
LDB T1,JBYSSA##
PUSHJ P,ADPAGS## ;ADD IT IN
MOVEI P1,(T1) ;FIRST PHYSICAL PAGE ALLOCATED IN P1
POPJ P,
;HERE IF ALREADY INCREMENTED FOR .WSBNZ
GSMPG3: PUSHJ P,SAVT##
JRST GSMPG1
;HERE TO EXCHANGE OR REMAP PAGES, ENTER T1 = N,,ARGUMENT LIST POINTER
; WHERE EACH WORD IN THE ARGUMENT LIST IS OF THE FORM
; XWD FLAG+SOURCE PAGE,DESTINATION PAGE
; WHERE FLAG = 1B0 IF THE PAGES ARE TO BE EXCHANGED, AND FLAG = 0B0
; IF THE SOURCE PAGE IS TO BE REMAPPED TO THE DESTINATION PAGE.
; IF FLAG = 1, BOTH SOURCE AND DESTINATION PAGES MUST EXIST.
; IF FLAG = 0, DESTINATION PAGE MUST NOT EXIST
MOVPGS: SE1ENT
PUSHJ P,SAVE4## ;SAVE P1-P4
PUSH P,T1 ;SAVE LEN,,ADDR OF ARG LIST
HLRZ P1,T1 ;NUMBER OF ARGUMENTS
MOVEI P3,-1(T1) ;ADDRESS OF FIRST WORD OF ARGUMENT LIST
MOVEI P4,-1(T1) ;ADDRESS OF LAST WORD
ADD P4,P1 ; OF THE ARGUMENT LIST
LSH P3,W2PLSH ;CONVERT TO PAGE NUMBER
LSH P4,W2PLSH
PUSHJ P,FSTPAG ;POINT M AT THE USER'S ARGUMENT LIST
PUSHJ P,IOWATM ;WAIT UNTIL ALL I/O STOPS
MOVPG1: TRNN P1,777 ;(THIS FUNCTION NOT EXECUTED @INTERRUPT LEVEL)
PUSHJ P,SCDCKM ;STOP EVERY APPROX 1000 PGS
PUSHJ P,NXTSPG ;GET THE NEXT ARGUMENT
PUSH P,T1 ;SAVE IT AT 0(P)
HRRZ T3,T1 ;SAVE DESTINATION PAGE
TLZE T1,400000 ;MOVE OR EXCHANGE PAGE?
TLO T3,400000 ;EXCHANGE, REMEMBER THAT
HLRZS T1 ;GET THE SOURCE PAGE
PUSHJ P,LGLPG ;IS IT A LEGAL PAGE?
JRST MOVPG9 ;NO, ILLEGAL PAGE ERROR
PUSHJ P,TPMOV ;IN A SHARABLE HIGH SEGMENT, OR MOVPGS IN ANY HI SEG?
JRST MOVPG9 ;YES, GO PROCESS ERROR
LSHC T1,P2SLSH
SKIPN .UPMP+SECTAB(T1);SECTION EXIST?
JRST MOVPG2 ;NO, ERROR
LSHC T1,S2PLSH
PUSHJ P,GTPME ;GET POINTER
JUMPN T2,MOVPG3 ;PAGE MUST EXIST
MOVPG2: PUSHJ P,PMEERR ;IT DOESN'T, ERROR
JRST MOVPG9
;HERE WHEN IT HAS BEEN VERIFIED THAT THE SOURCE PAGE EXISTS
MOVPG3: HRRZ T1,T3 ;DESTINATION PAGE
PUSHJ P,LGLPG ;IS IT A LEGAL PAGE?
JRST MOVPG9 ;NO, ERROR
PUSHJ P,TPMOV ;IS IT IN A SHARABLE HIGH SEGMENT?
JRST MOVPG9 ;YES, ERROR
LSHC T1,P2SLSH ;GET SECTION
SKIPN T4,.UPMP+SECTAB(T1);DOES SECTION EXIST?
JUMPL T3,MOVPG5 ;EXCHANGE, PAGE MUST EXIST AND CAN'T
PUSH P,P1 ;IN CASE WE NEED IT
JUMPN T4,MOVPG4 ;ALREADY HAVE A MAP
SOSGE VIRTAL## ;CAN WE GET A MAP PAGE?
JRST [AOS VIRTAL##;RESTORE VIRTAL
PUSHJ P,TBGERR ;SET ERROR
POP P,P1 ;RESTORE P1
JRST MOVPG9] ;AND FIX THINGS UP
MOVEI T4,1 ;ONE MAP PAGE
PUSHJ P,GSMPGS ;GET PAGE FOR SECTION MAP
MOVPG4: PUSHJ P,CRSMAP ;CREATE SECTION MAP
LSHC T1,S2PLSH
POP P,P1 ;RESTORE P1
PUSHJ P,GTPME ;GET THE CONTENTS OF THE MAP SLOT FOR THE
; DESTINATION PAGE
JUMPL T3,MOVPG6 ;VERIFY DEST PAGE DIFFERENTLY IF EXCH
JUMPE T2,MOVPG7 ;MOVE, PAGE MUST NOT EXIST
MOVPG5: PUSHJ P,PCEERR ;IT DOES, ERROR
JRST MOVPG9
;HERE ON AN EXCHANGE
MOVPG6: JUMPN T2,MOVPG7 ;DEST PAGE MUST EXIST
PUSHJ P,PMEERR ;IT DOESN'T, ERROR
JRST MOVPG9
;HERE WHEN IT HAS BEEN VERIFIED THAT THE DESTINATION PAGE DOES NOT
; EXIST IF THIS IS A REMAP OR DOES EXIST IF THIS IS AN EXCHANGE
MOVPG7: MOVE T1,(P) ;RESTORE USER'S ARG FOR MV1PG
PUSHJ P,MV1PG ;MOVE OR EXCHANGE THE PAGES
XOR T3,T2 ;BOTH PAGES IN CORE OR ON DISK?
MOVSI T2,UU.WCC ;
SKIPE T3
IORM T2,-10(P) ;NO, SET WORKING SET HAS CHANGED BIT
SKIPGE (P) ;IF WE JUST DID AN EXCHANGE,
JRST MOVPG8 ; THEN NOTHING CHANGED
HLRZ T1,(P) ;LIKE DELETING FROM PAGE
PUSHJ P,DCUPR ;FIX NUMBERS (MEM,REL)
HRRZ T1,(P) ;LIKE CREATING TO PAGE
PUSHJ P,ICUPR ;ADJUST NUMBERS
MOVPG8: POP P,(P) ;DISCARD LAST ARGUMENT
SOJG P1,MOVPG1 ;LOOP OVER THE ENTIRE ARGUMENT LIST
POP P,(P) ;DISCARD LEN,,ADDR OF ARG LIST
PJRST FIXAD1 ;UPDATE SOFTWARE RELOCATION INFORMATION, CLEAR A.M.
;HERE IF WE FOUND AN ILLEGAL ARGUMENT HALFWAY THROUGH THE ARGUMENT
;LIST. SCAN THE LIST BACKWARDS, UNDOING EVERYTHING DONE SO FAR.
MOVPG9: POP P,(P) ;DISCARD ARG BEING PROCESSED
EXCH T1,(P) ;SAVE ERROR CODE, RETRIEVE LEN,,ADDR
HLRZS T1 ;WE WANT NUMBER OF ARGUMENTS
SUBM T1,P1 ;PUT NUMBER OF ARGUMENTS TO UN-DO IN P1
JUMPE P1,TPOPJ## ;GET OUT IF FIRST ARGUMENT WAS BAD
MOVP10: TRNN P1,777 ;WAIT APPROX EVERY 1000 PGS
PUSHJ P,SCDCHK##
PUSHJ P,PREPAG ;BACK UP TO PREVIOUS ARGUMENT
MOVSS T1 ;MAKE IT AN ARG FOR UNDOING ITSELF
TRZE T1,400000 ;WAS IT AN EXCHANGE?
TLO T1,400000 ;YES, REMEMBER THAT
PUSH P,T1 ;SAVE USER'S MODIFIED ARGUMENT
PUSHJ P,MV1PG ;UNDO THIS ARGUMENT
SKIPGE (P) ;IF THIS WAS AN EXCHANGE,
JRST MOVP11 ; THEN NOTHING CHANGED
HLRZ T1,(P) ;IT WAS A MOVE, RETRIEVE SOURCE PAGE
PUSHJ P,DCUPR ;FIX REL, MEM
HRRZ T1,(P) ;NOW DEST PAGE
PUSHJ P,ICUPR ;FIX UP NUMBERS
MOVP11: POP P,(P) ;DISCARD USER'S ARG
SOJG P1,MOVP10 ;LOOP OVER ALL ARGS
CLRPGT ;CLEAR AM IN CASE WE GOT INTERRUPTED
JRST TPOPJ## ;RESTORE ERROR CODE
GBPTR: IDIVI T1,^D36 ;WORD NUMBER
MOVNI T2,-^D35(T2) ;BIT POSITION
HRLI T1,000100 ;MAKE A 1 BIT BYTE POINTER
DPB T2,[POINT 6,T1,5]
POPJ P, ;RETURN
XCBITS: LDB T2,T1 ;SOURCE BYTE (BIT)
LDB T3,T4 ;DESTINATION BYTE (BIT)
DPB T2,T4 ;SOURCE = DESTINATION
DPB T3,T1 ;DESTINATION = SOURCE
POPJ P, ;RETURN
;SUBROUTINE TO MAKE MEMTAB RIGHT ON MOVE OR EXCHANGE OF PAGES ON THE "IN" QUEUE
; CALL WITH T2 = MAP CONTENTS, T3 = VIRTUAL PAGE NUMBER
MVPMT: TLNN T2,(PM.OIQ) ;PAGE ON "IN" QUEUE?
POPJ P, ;NO, NOTHING TO FIX
SE1ENT ;SO CAN ADDRESS MEMTAB
SSX T2,MS.MEM ;MEMTAB SECTION
DPB T3,NVPNT2 ;STORE NEW VIRTAL PAGE NUMBER (JOB NUMBER IS OK)
POPJ P, ;AND RETURN
;SUBROUTINE TO TEST FOR PAGE-LEGALITY IN EXCHANGE, MOVE PAGES
TPMOV: CAMLE P3,P4 ;ARG LIST CROSS 777777?
JRST TPMOV1 ;YES, CHECK PAGE # DIFFERENTLY
CAML T1,P3 ;NO, IS THE USER TRYING TO MOVE THE ARG LIST?
CAMLE T1,P4 ; OR EXCHANGE IT (JUST AS BAD)?
JRST TPMOV2 ;NO, GO TEST OTHER THINGS
JRST IALERR ;YES, CAN'T LET HIM
;HERE WHEN ARG LIST CROSSES 777777
TPMOV1: CAMGE T1,P3 ;HIS PAGE NUMBER BETWEEN ARG LIST AND 777777?
CAMG T1,P4 ; OR BETWEEN 0 AND END OF ARG LIST?
JRST IALERR ;YES, CAN'T ALLOW IT
TPMOV2: MOVE T2,T1 ;GET PAGE #
LSH T2,P2SLSH ;CONVERT TO SECTION #
SKIPN .UPMP+SECTAB(T2) ;SECTION EXIST?
JRST CPOPJ1## ;NO, THEN NOT SPY OR SHARABLE PAGE
IFN FTPEEKSPY,<
PUSHJ P,TSSPT ;A SPY PAGE?
CAIA
JRST PSHERR
>
PUSHJ P,TPAHS ;IN A HI SEG?
SKIPA T2,.HBSGN(T2) ;YES
PJRST CPOPJ1## ;NO, OK
TLNE T2,SHRSEG!SPYSEG ;SHARABLE HI SEG OR SPY?
PJRST PSHERR ;YES
JUMPG T3,IALERR ;NO, CANT MOVPAG FROM ANY HI SEG
PJRST CPOPJ1## ;ALL OK
;SUBROUTINE TO MOVE OR EXCHANGE 1 PAGE IN MAP, ENTER T1=FROM-PAGE,,TO-PAGE
; BIT 0=1 IF EXCHANGE THE PAGES, EXIT T1=POINTER TO TO-PAGE MAP SLOT,
; T3= FROM-PAGE WSBTAB BIT, T4=POINTER TO WSBTAB FOR TO-PAGE. ALL NECESSARY
;SECTION MAPS MUST EXIST ALREADY AND DESTINATION SECTION MAPPED THROUGH .USSPT
MV1PG:: MOVE T3,T1 ;SAVE ARGUMENT
HLRZS T1 ;GET SOURCE PAGE
LSHC T1,P2SLSH ;GET SECTION #
TRZN T1,400000_P2SLSH ;NO CHANGE IF EXCHANGE
PUSHJ P,DECNZC ;DECREMENT COUNT
LSHC T1,S2PLSH ;CONVERT BACK TO PAGE #
PUSHJ P,GTPME
HRRZ T1,T3 ;DESTINATION PAGE
PUSH P,T2 ;SAVE CONTENTS OF SOURCE MAP SLOT
PUSH P,T4 ;AND BYTE POINTER TO SOURCE MAP SLOT
LSHC T1,P2SLSH ;SECTION
SKIPL T3 ;NO CHANGE IF EXCHANGE
PUSHJ P,INCNZC ;ELSE INCREMENT COUNT
;(NOTE IT'S ALREADY MAPPED ON ENTRY)
LSHC T1,S2PLSH ;CONVERT BACK
PUSHJ P,GTPME ;GET MAP POINTER
TLZN T3,400000 ;MOVE OR EXCHANGE?
MOVEI T2,0 ;MOVE, SET TO STORE 0 IN SOURCE SLOT
EXCH T4,(P) ;GET POINTER TO SOURCE, SAVE PTR TO DESTINATION
MOVEM T2,(T4) ;STORE
; SOURCE SLOT
MOVSS T3 ;SOURCE VIRTUAL PAGE NUMBER TO RIGHT HALF
PUSHJ P,MVPMT ;FIX MEMTAB IF OIQ
MOVSS T3 ;RESTORE T3
MOVE T4,(P) ;GET DESTIATION POINTER BACK
MOVE T2,-1(P) ;RESTORE CONTENTS OF SOURCE SLOT
POP P,-1(P) ;MOVE DESTINATION PTR BACK BY ONE
MOVEM T2,(T4) ;STORE IN DESTINATION SLOT
PUSHJ P,MVPMT ;FIXUP MEMTAB IF NECESSARY
ANDI T1,HLGPNO ;KEEP ONLY PAGE #
PUSHJ P,GBPTR ;GET A BYTE POINTER TO BIT TABLES
HRRZ T4,T3 ;FROM PAGE NUMBER
LSH T4,P2SLSH ;JUST FOR SECTION
PUSHJ P,RSECT4
JFCL
IMULI T4,WSBTBL ;OFFSET
SKIPN T4 ;NZS?
SKIPA T4,[WSBTAB] ;NO
ADDI T4,.WSBNZ-WSBTBL
ADD T4,T1 ;MAKE BYTE POINTER
HLRZ T1,T3 ;SETUP TO GET BYTE POINTER FOR DESTINATION BIT
ANDI T1,HLGPNO ;KEEP ONLY PAGE #
PUSHJ P,GBPTR ;GET THAT
HLRZS T3 ;GET ARG AGAIN
LSH T3,P2SLSH ;JUST FOR SECTION
EXCH T4,T3
PUSHJ P,RSECT4 ;GET REAL SECTION # FOR SOURCE
JFCL
EXCH T4,T3
IMULI T3,WSBTBL ;OFFSET
SKIPN T3 ;NZS?
SKIPA T3,[WSBTAB] ;NO
ADDI T3,.WSBNZ-WSBTBL
ADD T1,T3 ;RELOCATE BYTE POINTER
PUSHJ P,XCBITS ; THE WORKING SET TABLE
PJRST TPOPJ## ;RESTORE BYTE POINTER TO DESTINATION SLOT AND RETURN
;HERE TO SET/CLEAR THE ACCESS ALLOWED BITS IN THE MAP AND AABTAB
SETAAB: MOVEI T2,PA.IHB+PA.PME+PA.PMI
PUSHJ P,PLTSN ;CHECK THE ARGUMENT LIST (PAGES MUST EXIST
; AND BE IN CORE)
POPJ P, ;ARGUMENT ERROR
PUSHJ P,SAVE1## ;SAVE P1,P2
SE1ENT
HLRZ P1,T1 ;NUMBER OF ARGUMENTS
PUSHJ P,FSTPAG ;POINT M AT USER'S ARGUMENT LIST
MOVSI T1,(UP.SAA) ;SET A.A. AUTOMATICALLY BIT
TLNN M,ARGMD ;DID THE USER SPECIFY IT?
JRST [ANDCAM T1,.USBTS
JRST SETAA1] ;NO, CLEAR THE BIT
IORM T1,.USBTS ;YES, REMEMBER IT
SETAA1: PUSHJ P,NXTPAG ;GET THE NEXT ARGUMENT
HRRZ T2,T1 ;ONLY PAGE #
LSH T2,P2SLSH ;CONVERT TO SECTION #
SKIPE .UPMP+SECTAB(T2) ;SECTION EXIST?
PUSHJ P,SCAABT ;SET OR CLEAR THE BIT
SETAA2: SOJG P1,SETAA1 ;LOOP OVER ALL THE ARGUMENTS
PUSHJ P,ADJANA
FIXMJ1::CLRPGT ;CLEAR PAGE MEMORY
JRST CPOPJ1## ;SKIP RETURN
;SUBROUTINE TO SET OR CLEAR ACCESS ALLOWED BITS IN AABTAB AND THE MAP
; CALL WITH T1 = THE VIRTUAL PAGE NUMBER, SIGN BIT ON IF A.A. TO BE CLEARED
; EXITS CPOPJ ALWAYS
SCAABT: SE1ENT ;MUST BE IN S1
PUSHJ P,GTPME ;GET THE CONTENTS OF THE MAP SLOT FOR THIS PAGE
JUMPE T2,CPOPJ## ;DON'T DO ANYTHING IF PAGE DOESN'T EXIST
TLNN T1,400000 ;SET OR CLEAR ACCESS ALLOWED?
JRST SCAAB1
TLZE T2,(<PM.DCD>B2)
AOS .USANA ;YES, BUMP NO. OF NOT-ACCESSABLE PAGES
TLZ T2,(PM.AAB)
JRST SCAAB2
SCAAB1: TLON T2,(<PM.DCD>B2)
SOS .USANA ;YES, DECR NO OF NOT-ACCESSABLE PAGES
TLO T2,(PM.AAB)
SCAAB2: MOVEM T2,(T4) ;STORE ENTRY BACK IN THE MAP WITH THE
; ACCESS ALLOWED BIT SET OR CLEARED
POPJ P, ;RETURN
;SUBROUTINE TO MAKE UPVRT AGREE WITH UPANA
ADJANA::MOVE T3,.USANA
IORM T3,.USVRT ;ENSURE UPVRT NON-0 IF NON-ACCESS PAGES EXIST
JUMPN T3,CPOPJ## ;IF NO NON-ACCESS PAGES,
MOVEI T3,777 ; CLEAR THAT PORTION OF UPVRT
ANDCAM T3,.USVRT
POPJ P, ;RETURN
;HERE TO RETURN THE WORKING SET BIT TABLE TO THE USER
GETWSB: MOVEI T2,WSBTAB ;SOURCE ADDRESS
IFN FTXMON,<
XSFM T3 ;DESTINATION
HRLI T3,(T1) ;LOW ORDER PART
MOVSS T3 ;SET HALVES CORRECTLY
> ;IFN FTXMON
IFE FTXMON,<MOVEI T3,(T1)> ;DESTINATION ADDRESS
HLRZS T1 ;NUMBER OF WORDS TO RETURN
PUSH P,T1 ;SAVE # OF WORDS REQUESTED
CAILE T1,WSBTBL ;ASKING FOR MORE THAN THERE ARE?
MOVEI T1,WSBTBL ;YES, RETURN NUMBER THERE ACTUALLY ARE
IFN FTXMON,<XBLTXU T1> ;MOVE TABLE TO THE USER
IFE FTXMON,<
MOVSS T2 ;SOURCE IN LH
HRRI T2,(T3) ;DEST. IN RH
ADD T3,T1 ;ONE BEYOND END
EXCTXU <BLT T2,-1(T3)> ;MOVE TABLE TO THE USER
> ;END IFE FTXMON
ERJMP UADERR## ;MUSTA BEEN TO A HISEG
HRLOI T4,1777 ;SET TO CLEAR BIT REPRESENTING THE UPMP
JUMPGE U,TPOPJ1## ;WAS THE ENTIRE TABLE REQUESTED?
EXCTXU <ANDCAM T4,-1(T3)> ;YES, CLEAR JUNK FROM THE LAST WORD
POP P,T1 ;RESTORE # OF WORDS REQUESTED
SUBI T1,WSBTBL ;# WORDS LEFT
JUMPLE T1,CPOPJ1## ;NO, DONE
SKIPL .USBTS ;IS USER EXTENDED?
JRST GETWSZ ;NO, JUST ZERO REST OF BLOCK
IFN FTXMON,<
PUSH P,T1 ;SAVE # OF WORDS LEFT
MOVEI T2,.WSBNZ ;GET ADDR OF EXTENDED TABLE
CAILE T1,PAGSIZ ;WANT MORE THAN A PAGE WORTH?
MOVEI T1,PAGSIZ ;CAN'T GET ANY MORE
EXCTXU <EXTEND T1,[XBLT]>
ERJMP UADERR## ;NOT THERE
POP P,T1
SUBI T1,PAGSIZ
JUMPLE T1,CPOPJ1## ;IF NO MORE, DONE
> ;END IFN FTXMON
GETWSZ: EXCTXU <SETZM (T3)> ;CLEAR NEXT WORD
SOJLE T1,CPOPJ1##
IFN FTXMON,<
MOVE T2,T3 ;STARTING WORD
AOS T3 ;DESTINATION WORD
EXCTUU <EXTEND T1,[XBLT]> ;CLEAR REST OF USER'S BLOCK
> ;END IFN FTXMON
IFE FTXMON,<
MOVSI T2,(T3) ;SOURCE ADDR
HRRI T2,1(T3) ;DEST. ADDR
ADD T3,T1 ;FINAL+1
EXCTUU <BLT T2,-1(T3)> ;CLEAR REST OF USER'S BLOCK
> ;END IFE FTXMON
ERJMP UADERR## ;WENT BEYOND USER'S CORE
JRST CPOPJ1## ;DONE
;HERE TO RETURN AABTAB. T1 CONTAINS THE # OF WORDS TO RETURN
GETAAB: PUSHJ P,SAVE1## ;SAVE P1
SE1ENT
HRRZI M,-1(T1) ;WHERE TO START RETURNING
HLRZ U,T1 ;# OF WORDS TO RETURN
JUMPE U,CPOPJ1## ;NOTHING TO RETURN
SETZ P1, ;LET'S START AT THE VERY BEGINNING
MOVSI T3,(PM.AAB)
GETAA1: SKIPN .UPMP+SECTAB(P1)
JRST GETAA6
MOVEI T1,(P1) ;ARG FOR STUTMP
MOVE T4,[MS.MAP+UMAPS]
GETAA2: SETZ T1, ;DEFAULT BIT MASK
MOVSI T2,-^D36 ;PER WORD
GETAA3: LSH T1,1 ;SHIFT OVER
TDNE T3,(T4) ;AABTAB BIT ON?
AOS T1 ;YES
AOS T4
TRNE T4,HLGPNO ;CROSS SECTION BOUNDARY?
AOBJN T2,GETAA3 ;LOOP OVER ALL
GETAA4: PUSHJ P,PUTWS1## ;PUT THE WORD IN CORE
TRNN T4,HLGPNO ;CROSS SECTION OR WORD BOUNDARY?
AOJA P1,GETA4A ;SECTION (CAN NEVER BE BOTH)
SOJG U,GETAA2
JRST CPOPJ1##
GETA4A: CAIG P1,MXSECN ;AS LONG AS NOT TOO BIG
GETAA5: SOJG U,GETAA1 ;CONTINUE
JRST CPOPJ1##
GETAA6: MOVEI T2,WSBTBL
SETZ T1,
GETAA7: PUSHJ P,PUTWS1##
SOJLE T2,GETAA1
SOJG U,GETAA7
JRST CPOPJ1##
;HERE TO MAKE A CONTIGUOUS COLLECTION OF PAGES A HIGH SEGMENT
GREMAP: SETZM .JDAT+SGANAM## ;NO NAME
SETZM .JDAT+SGAEND## ;ALSO NO FLAGS
SREMAP::PUSHJ P,SAVE4## ;SAVE A WORKING AC
HLRE P1,T1 ;GET THE NUMBER OF ARGUMENTS
JUMPLE P1,IALERR ;.LE. 0 IS ILLEGAL
SOJL P1,IALERR ;THERE MUST BE AT LEAST TWO ARGUMENTS
; (NUMBER OF PAGES AND STARTING PAGE)
HRRI M,(T1) ;ADDRESS OF THE ARGUMENTS
PUSH P,.JDAT+SGANAM##;SAVE NAME
PUSH P,.JDAT+SGAEND##;AND FLAGS IN CASE IOWAIT OR UPMM BLOCK
PUSHJ P,INTLVL## ;CAN'T WAIT IF INTERRUPT (CLOCK) LEVEL (VIRCHK)
PUSHJ P,IOWATM ;WAIT FOR I/O TO STOP
PUSHJ P,GETWSU## ;GET THE FIRST ARGUMENT (NUMBER OF PAGES TO BE REMAPPED)
IFN FTMP,<
PUSHJ P,MMOWN## ;OWN MM?
PUSHJ P,UPMM## ;MUST HAVE THE MM TO DO A REMAP
>
POP P,.JDAT+SGAEND##;RESTORE FLAGS
POP P,.JDAT+SGANAM##;AND NAME
JUMPE P1,GREMA4 ;DELETE HS PAGES FUNCTION
PUSH P,T1 ;SAVE IT
PUSHJ P,GETWS1## ;GET THE STARTING PAGE NUMBER
PUSHJ P,LGLPG ;IS IT A LEGAL PAGE?
JRST T2POPJ## ;NO, TELL THE USER ILLEGAL PAGE NUMBER
MOVE T2,T1 ;STARTING PAGE NUMBER TO T2
SOJLE P1,GREMA1 ;JUMP IF THIRD ARGUMENT WASN'T SPECIFIED
PUSH P,T1 ;SAVE SECOND ARGUMENT (GETWSU CLOBBERS T2)
PUSHJ P,GETWS1## ;GET THE DESTINATION PAGE NUMBER
PUSHJ P,LGLPG ;IS THAT A LEGAL PAGE NUMBER?
JRST [POP P,(P) ;NO
JRST T2POPJ##] ;ILLEGAL PAGE RETURN TO THE USER
SKIPA T2,T1 ;DESTINATION PAGE TO T2
GREMA1: PUSH P,T1 ;SAVE SOURCE PAGE
MOVSI T4,(1B0) ;DON'T ALLOW A USER TO CREATE A SHARABLE
SKIPL -1(P) ;APPEND STYLE REMAP (CHECKING SAVED T3)?
JRST GREMA2 ;NO
MOVMS -1(P) ;MAYBE, MAKE IT POSITIVE
PUSHJ P,FNSPCS## ;JOB HAVE A NON-SHARABLE HIGH SEG IN THIS SECTION?
JRST GREMA2 ;NO
JUMPE T1,GREMA2 ;NO SEGMENT AT ALL
MOVEI P1,GREMA3 ;IF APPENDING, WE WILL EXIT HERE
HRRZ J,.HBSGN(T1) ;GET SEGMENT #
LDB T1,JBYHSO## ;GET ORIGIN PAGE OF HIGH SEG
HLRZ J,JBTADR##(J) ;GET SIZE-1
JUMPE J,GREM40 ;HAVE A HIGH SEG, BUT IT DOESN'T EXIST YET
LSH J,W2PLSH ;CONVERT TO PAGES-1
ADDI T1,1(J) ;FIRST PAGE AFTER HIGH SEG
CAIN T1,(T2) ;IS IT THE DESTINATION PAGE
JRST GREM40 ;YES, ALL IS WELL
ADJSP P,-2 ;FIX STACK
PJRST IALERR ;ILLEGAL ARG LIST
GREM40: TLOA T4,(1B1) ;YES, INDICATE APPEND
GREMA2: MOVEI P1,SHARE1## ;IN WIN CASE, GO TO SHARE1 FOR NORMAL REMAP
POP P,T1 ;RESTORE SOURCE PAGE
POP P,T3 ;RESTORE # OF PAGES
PUSHJ P,NREMAP ;DO THE REMAP
PJRST STOTAC## ;ERROR, STORE THE ERROR CODE FOR THE USER
PJSP T3,(P1) ;WIN, MAKE REMAPPED PAGES INTO A HIGH SEGMENT
GREMA3: MOVE J,.USJOB ;POINT TO JOB FOR MAPHGH
PUSHJ P,SETVRT ;SET UP .USVRT
AOS (P) ;SKIP RETURN
PJRST MAPHGH## ;JUST APPENDING
GREMA4: HRRZ P4,T1 ;SAVE T1
HLRZS T1 ;SECTION #
TRZE T1,(PG.GAF) ;SPECIFIED SECTION #?
PUSHJ P,SVPCS## ;YES, SET THAT SECTION
PUSHJ P,FNSPCS## ;FIND NON-SHARABLE SECTION IN PCS
JRST PSHERR ;SHARABLE NOT ALLOWED
JUMPE T1,PSHERR ;OR NON-EXISTENT SEGMENT
EXCH T1,P4 ;PUT BLOCK ADDR IN P4 RESTORING ARG
MOVE T2,JBTADR##(J) ;GET HIGH SEG JBTADR
LDB P3,JBYHSO## ;GET HIGH SEG ORIGIN
LSH P3,P2WLSH ;CONVERT TO WORD
MOVE J,.USJOB
HLRZ P1,T2 ;END OF CURRENT HIGH SEG
LSH P1,W2PLSH ;CONVERT TO HIGHEST PAGE IN SEG
SUBI P1,-1(T1) ;FIRST PAGE TO DELETE
JUMPL P1,IALERR ;HE IS, LOSE
LSH P1,P2WLSH ;MAKE SURE
SKIPN P1 ;DELETING ENTIRE HS?
TDZA T2,T2 ;YES, SET IT'S CLEAR
HRLI T2,-PAGSIZ+PG.BDY(P1) ;YES, SET NEW RELOCATION
ADD P1,P3
LDB T4,[PSG2LH+.HBSG2(P4)] ;SECTION HIGH SEG IS IN
HRLI P1,(T4) ;SET IT
LSH P1,W2PLSH ;BACK TO FIRST PAGE TO DELETE
MOVNS T1 ;MAKE COUNT
HRLI P1,(T1) ;FOR AOBJN POINTER
LDB T1,[PSG2LH+.HBSG2(P4)] ;SET SECTION
SE1ENT ;ENTER SECTION 1 HERE
PUSH P,T2 ;SAVE NEW R FOR HIGH SEG
LSH T1,S2PLSH
IORI P1,(T1) ;SET IN AOBJN PTR TOO
GREMA5: MOVEI T1,(P1) ;PAGE TO DELETE
TRNE T1,-1^!HLGPNO ;IF IN A NON-ZERO SECTION
AOS .USNCR ;UNDO THE CALL TO DECNCR BY DLTPAG
PUSHJ P,DLTPAG ;DELETE IT
MOVEI T1,(P1) ;T1 ISN'T PRESERVED IN DLTPAG
LSH T1,P2SLSH ;CONVERT TO SECTION
SKIPE T1 ;DECREMENT IF NZS
PUSHJ P,DECNZC ;YES
PUSHJ P,DCVMT
GREMA6: AOBJN P1,GREMA5
MOVSI T1,(UP.WHC) ;WORKING SET HAS CHANGED
IORM T1,.USBTS
CLRPGT
AOS -1(P) ;GOOD RETURN
HRRZ J,.HBSGN(P4) ;GET SEG NUMBER
EXCH R,(P) ;GET R FOR HIGH SEG
MOVSI T1,(UP.CTX) ;PUSH?
TDNN T1,.USBTS ;?
MOVEM R,JBTADR##(J)
PUSHJ P,SETVRT ;ADJUST #S
LDB T1,PCORSR##
SKIPE R ;IF ZERO, STORE ZERO
AOS T1 ;# OF PAGES, NOT HIGHEST ADDRESSABLE
DPB T1,[PHSSLH+.HBHSZ(P4)]
HLRZS R ;SET JOBHRL
LDB T2,JBYHSO## ;GET HIGH SEG ORIGIN
LSH T2,P2WLSH ;CONVERT TO WORD
SKIPE T1,R
ADDI T1,(T2) ;ADD IN BEGINNING
HRRM T1,.JDAT+JOBHRL##
MOVE J,.USJOB
JRST RPOPJ## ;RESTORE R AND RETURN
;HERE TO CREATE/DESTROY SPY PAGES
IFN FTPEEKSPY,<
SPYPGS: SE1ENT
PUSHJ P,SAVE4## ;SAVE ALL
PUSH P,T1 ;SAVE ADDRESS OF THE ARGUMENT LIST
MOVSI T1,PVSPYA ;REQUIRES SPY PRIVILEGES
PUSHJ P,PRVBIT## ;DOES THE JOB HAVE THEM?
SKIPA T1,(P) ;YES, PROCEED
JRST [POP P,(P) ;NO, POP OFF JUNK AND
JRST NPVERR] ; GIVE NEED PRIVILEGES ERROR RETURN
PUSHJ P,FSTPAG ;POINT M AT USERS ARGUMENT LIST
HLRE P3,T1 ;NUMBER OF ARGUMENTS
JUMPLE P3,[POP P,(P) ;ZERO OR NEGATIVE ARGUMENT COUNT IS ILLEGAL
JRST IALERR];GIVE ILLEGAL ARGUMENT LIST RETURN
SKIPGE -5(P) ;PHYSICAL ONLY? P1 ON STACK
TDZA P2,P2 ;PHYS ONLY
MOVEI P2,1
SETZB P4,.USTMU ;SECTION MAPS
SPYPG1: PUSHJ P,NXTSPG ;GET THE NEXT ARGUMENT
PUSHJ P,LGLPR ;LEGAL USER VIRTUAL PAGE NUMBER?
JRST TPOPJ## ;NO
MOVE P1,T1 ;SAVE CURRENT T1
LSH T1,P2SLSH ;GET SECTION #
ANDI T1,MXSECN ;CLEAR JUNK
SKIPN T2,.UPMP+SECTAB(T1);SECTION EXIST?
JRST [JUMPGE P1,SPYP12 ;CREATE, OK FOR NX SECTION
TLNE P1,(PG.IDC) ;DON'T CARE LIT?
JRST SPYP2A ;IDC IS LIT, BUT DON'T CREATE MAP
POP P,(P)
JRST PMEERR] ;BUT NOT FOR DELETE
SPYPG2: MOVE T1,P1 ;RESTORE T1
PUSHJ P,GTPME ;GET CONTENTS OF THE MAP CORRESPONDING TO THAT PAGE
JUMPL T1,SPYP2A ;DELETE SPY PAGE?
JUMPE T2,SPYPG3 ;CREATE AND PAGE DOESN'T EXIST, NO SWEAT
TLNE P1,(PG.IDC) ;DON'T CARE?
PUSHJ P,TPNHS ;YES, BUT IF IT'S IN THE HIGH SEG, CAN'T DELETE
CAIA ;CARES OR IT'S IN THE HS
JRST SPYPG3
POP P,(P) ;NO, MAP SLOT MUST BE ZERO
JRST PCEERR ;PAGE CANNOT EXIST ERROR
SPYP2A: HLRZ T4,P4
CAIL T4,(T1)
JRST [POP P,(P) ;FIX STACK
JRST IALERR]
HRL P4,T1 ;REMEMBER HIGHEST DELETE PAGE SEEN
TLNE P1,(PG.IDC) ;DO WE CARE?
JUMPE T2,SPYPG4 ;NO
HRRZ T1,P1
PUSHJ P,TSSPT
CAIA
JRST SPYPG4
POP P,(P)
JRST PMEERR
SPYPG3: MOVE T1,P1
HRRZ T4,P4 ;LAST PAGE CREATED
CAIL T4,(T1) ;INCREASING ORDER?
JRST [POP P,(P) ;FIX STACK
JRST IALERR]
HRR P4,T1 ;REMEMBER HIGHEST PAGE
HLRZ T2,T1 ;MONITOR PAGE NUMBER
LSH T2,P2WLSH ;MAKE WORD AFTER CLEARING BITS
XCT [CAML T2,MEMSIZ##
PUSHJ P,MONVPC](P2) ;MAP THE VIRTUAL ADDRESS
TLNE P1,(PG.IDC) ;OR DOESN'T CARE?
JRST SPYPG4 ;ALL IS MORE OR LESS WELL
POP P,(P) ;NO
JRST ILPERR ;ILLEGAL PAGE NUMBER ERRROR
SPYPG4: SOJG P3,SPYPG1 ;LOOP OVER THE ENTIRE ARGUMENT LIST
POP P,T1 ;RESTORE ARGUMENT LIST POINTER
HLRZ P3,T1 ;COUNT OF ARGUMENTS
SKIPE T4,.USTMU ;# OF SECTION MAPS
PUSHJ P,GSMPGS ;TRY TO GET MAPS NOW
PUSHJ P,FSTPAG ;POINT M AT USER'S ARGUMENT LIST
SPYPG5: PUSHJ P,NXTSPG ;GET THE NEXT ARGUMENT
HRRZ T4,T1 ;USER VIRTUAL PAGE NUMBER
PUSHJ P,GMPTR ;GET MAP POINTER
HLRZ T2,T1 ;MONITOR PAGE NUMBER
HRRZS T1 ;CLEAR JUNK
ROT T1,P2SLSH ;CONVERT TO SECTION
TRNE T2,400000 ;IS THIS A DELETE?
JRST [HRL T2,T1 ;YES, DOES SECTION EXIST (IDC)?
ANDI T1,MXSECN
SKIPN .UPMP+SECTAB(T1)
JRST SPYPG9 ;NO, DON'T CREATE A MAP TO DESTROY
HLRZ T1,T2 ;RESTORE T1
HRRZS T2 ;AND T2
JRST .+1] ;CONTINUE
PUSHJ P,CRSMAP
ROT T1,S2PLSH
TRNE T2,400000 ;DELETING A SPY PAGE?
JRST SPYPG7 ;YES
MOVE T3,(T4) ;GET CONTENTS OF MAP
SKIPE T3 ;IF PAGE DOESN'T EXIST, PROCEED
PUSHJ P,[PUSHJ P,SAVT## ;ELSE DELETE WHAT'S
PJRST DLTPAG];THERE ALREADY
MOVE T3,T2 ;MONITOR PAGE NUMBER TO T3
SKIPGE -4(P) ;PHYSICAL ONLY? P1 ON THE STACK
JRST SPYPG6 ;YES
ANDI T2,HLGPGS
PUSH P,T1 ;SAVE T1
PUSHJ P,MONVPM ;MAP THE VIRTUAL PAGE
JFCL ;IGNORE
MOVE T3,T1 ;PAGE MAP ENTRY
POP P,T1
JRST SPYPG8 ;DEPOSIT INTO MAP
SPYPG6: TLOA T3,(<PM.DCD>B2+PM.PUB+PM.SPY+PM.NIA)
SPYPG7: SETZ T3, ;SET TO REMOVE THE SPY PAGE
SPYPG8: MOVEM T3,(T4) ;STORE MAPPING IN THE USER'S MAP
LSH T1,P2SLSH ;SECTION #
JUMPE T1,SPYPG9 ;A SECTION 0 PAGE
JUMPE T3,[PUSHJ P,DECNZC ;DELETE, DECREMENT COUNT
JRST SPYPG9]
PUSHJ P,INCNZC
SPYPG9: SOJG P3,SPYPG5 ;NEXT ARGUMENT
MOVSI T1,(UP.CSP) ;MAP MAY CONTAIN SPY PAGES BIT
IORM T1,.USBTS ;TURN IT ON TO SAVE TIME LATER
JRST FIXMJ1 ;NEW MAPPING IN AFFECT, GOOD RETURN
SPYP12: HRRZ T2,P1 ;PAGE BEING CREATED
XOR T2,P4 ;GET DIFFERENCES
TRNE T2,MXSECN_S2PLSH ;SEE IF WE SAW THIS NON-EXISTENT SECT BEFORE
AOS .USTMU ;NO, REMEMBER TO CREATE MAP
JRST SPYPG3
;SUBROUTINE TO DELETE A SPY PAGE, CALL WITH T1 = USER VIRTUAL PAGE
; NUMBER OF THE PAGE, RETURNS CPOPJ IF SPY PAGE DELETED, CPOPJ1 IF NOT
; A SPY PAGE
DLTSP: PUSHJ P,TSSPT ;A SPY PAGE?
JRST CPOPJ1## ;NO, SKIP RETURN
SETZM (T4) ;ZERO MAP SLOT
POPJ P, ;AND RETURN
;SUBROUTINE TO CLEAR SPY PAGES FROM A USER'S MAP, CALLED BY GETMIN
CLRSPG::SE1ENT ;FOR MAP REFERENCES
MOVSI T1,(UP.CSP) ;JOB MAY HAVE SPY PAGES IN ITS MAP BIT
SKIPE JBTADR##(J) ;DOES IT HAVE CORE IN CORE?
TDNN T1,.USBTS ;YES, AND DID IT DO A FUNCTION 11 OF THE PAGE. UUO?
JRST CLRSP6 ;NO, BE SURE BIT CLEAR AND RETURN NOW
SETZ T1, ;START AT SECTION 0
CLRSP1: MOVEI T4,HLGPNO+1 ;MAX # OF PAGES IN SECTION
MOVSI T2,(PM.SPY) ;BIT TO CHECK
SKIPE T3,T1 ;COPY SECTION #
LSH T3,S2PLSH ;CONVERT TO PAGE #
ADD T3,[MS.MAP+UMAPS]
CLRSP2: TDNN T2,(T3) ;SPY PAGE?
JRST CLRS2B ;NO
SETZM (T3) ;CLEAR MAPPING
JUMPE T1,CLRS2B ;GO IF S0
PUSHJ P,DECNZC ;KEEP THE COUNTS RIGHT
CLRS2B: AOS T3 ;ADVANCE
CLRS2A: SOJG T4,CLRSP2
CLRSP3: SKIPL .USBTS ;EXTENDED PROGRAM?
JRST CLRSP5 ;NO, DONE
AOS T1 ;NEXT SECTION
CLRSP4: CAILE T1,MXSECN ;DONE MAYBE?
JRST CLRSP5 ;YES
SKIPE T2,.UPMP+SECTAB(T1) ;SECTION EXIST?
TLNE T2,(<PM.DCD^!PM.ACD>B2) ;IS IT INDIRECT?
AOJA T1,CLRSP4 ;KEEP LOOKING IF NO SECTION MAP
JRST CLRSP1
CLRSP5: MOVSI T1,(UP.CSP) ;NO LONGER HAS SPY PAGES
CLRSP6: ANDCAM T1,.USBTS
SETZM .USCDB ;MAKE SURE CLOCK1 KNOWS WE'RE CLEAN
POPJ P,
;HERE TO MAP MONITOR PAGE IN T2 INTO A USER POINTER IN T1
;CPOPJ ON FAILURE, CPOPJ1 ON SUCCESS
MONVPC: LSH T2,W2PLSH ;CHANGE ADDRESS TO PAGE
MONVPM: MOVE T1,T2 ;COPY PAGE
ANDI T2,PG.BDY ;KEEP PAGE WITHIN SECTION
LSH T1,P2SLSH ;ISOLATE SECTION NUMBER HERE
CAILE T1,MXSECN ;IS IT REASONABLE?
JRST MONVPE ;NO, GIVE ERROR RETURN
IFN FTXMON,<
CAILE T1,(MCSEC1) ;IS IT WHERE MOST CODE LIVES?
JRST MONVP4 ;NO, LOOK HARDER
>
CAIL T2,.CPCDB##/PAGSIZ ;IS IT THE CDB?
CAILE T2,<.CPCDB##/PAGSIZ>+1 ;EITHER PAGE?
JRST MONVP9 ;NO, CHECK FOR FUNNY SPACE
MOVE T1,[<PM.ICD>B2!PM.PUB!PM.SPY!<XWD <.CPCDB##/PAGSIZ>,<SPTLOW##-SPTTAB##>>]
ADD T1,.CPCPN## ;MAKE POINTER TO CURRENT .CPCDB
PUSH P,T2 ;SAVE AN AC
MOVSI T2,-CDBPGS## ;SET UP AOBJN
MOVEM T1,.USCDB(T2) ;STORE MAPPING
ADD T1,[XWD 1,0] ;MAP NEXT PAGE
AOBJN T2,.-2 ;LOOP FOR ALL CDB PAGES
POP P,T2 ;RESTORE T2
MOVSI T1,.UPCDB-<.CPCDB##/PAGSIZ>(T2) ;GET CORRESPONDING UPT OFFSET
JRST MONVP0 ;EXIT VIA PER-JOB MAPPING
MONVP9: CAIL T2,.FPPP/PAGSIZ ;IS IT IN FUNNY SPACE?
CAILE T2,.LPPP/PAGSIZ ; ...?
JRST MONVP1 ;NO, HANDLE IN SPTLOW
MOVSI T1,.UMORG-<FYSORG/PAGSIZ>(T2) ;GET SLOT OFFSET IN RIGHT PLACE
MONVP0: HRRI T1,M.CPU##(J) ;POINT TO JBTUPM(J) IN SPT
JRST MONVP3 ;GO THROUGH COMMON EXIT
MONVP1: MOVS T1,T2 ;GET PAGE OFFSET IN CORRECT PLACE
HRRI T1,SPTLOW##-SPTTAB## ;POINT TO CORRECT STARTING PLACE IN SPT
MONVP2: ADD T1,.CPCPN## ;OFFSET FOR CPU NUMBER
MONVP3: TLO T1,(<PM.ICD>B2+PM.PUB+PM.SPY) ;MAKE COMPLETE MAPPING POINTER
JRST CPOPJ1## ;RETURN SUCCESS
IFN FTXMON,<
MONVP4: CAIE T1,(MS.HGH) ;IS IT THE OTHER PER-CPU SECTION?
JRST MONVP5 ;NO, LOOK ONWARD
MOVS T1,T2 ;YES, GET PAGE OFFSET IN CORRECT HALFWORD
HRRI T1,SPTHGH##-SPTTAB## ;POINT TO CORRECT STARTING PLACE IN SPT
JRST MONVP2 ;EXIT VIA PER-CPU MAPPING
MONVP5: CAIE T1,(MS.MAP) ;IS IT THE OTHER SPECIAL SECTION?
JRST MONVP6 ;NO, HANDLE COMMON DATA SECTION
CAIL T2,<UMAPS/PAGSIZ> ;IS IT IN RANGE?
CAILE T2,<UMAPS/PAGSIZ>+HLGSNO ;BOTH WAYS?
JRST MONVPE ;NO, GIVE ERROR RETURN
MOVSI T1,SECTAB-<UMAPS/PAGSIZ>(T2) ;YES, POSITION MAPPING OFFSET
JRST MONVP0 ;EXIT VIA UPT MAPPING
MONVP6: MOVEI T1,SPTCOM##-SPTTAB##-<(MS.FMD)>(T1) ;POINT TO SPT SLOT
HRLI T1,(T2) ;YES, INCLUDE MAPPING OFFSET FOR PAGE
JRST MONVP3 ;EXIT VIA COMMON CODE
> ;END IFN FTXMON
MONVPE: SETZ T1, ;CLEAR MAPPING
POPJ P,
> ;END IFN FTPEEKSPY
;HERE TO CREATE/DESTROY SECTION MAPS
CHGSEC: SE1ENT
PUSHJ P,FSTPAG ;GET FIRST ARGUMENT
HLRES T1
MOVM P4,T1 ;# OF ARGS TO P4
MOVE P3,P4 ;SAVE ALSO IN P3
MOVSI T2,-<MXSECN+1> ;MAX # OF SECTIONS
SETZ P2, ;MAKE MASK OF SECTIONS NOW INDIRECT
MOVSI T4,(<PM.ACD^!PM.DCD>B2) ;SEE IF SECTION IS INDIRECT
CHGSC0: LSH P2,1 ;NEXT SECTION
TDNE T4,.UPMP+SECTAB(T2) ;IS THIS SECTION INDIRECT?
AOS P2 ;THIS SECTION IS INDIRECT
AOBJN T2,CHGSC0
LSH P2,^D35-<MXSECN>
SETZB P1,T4 ;# OF PAGES CREATED,,DESTROYED, PAGES TO ADD
XSFM T2 ;SECTION # OF PC SECTION
ANDI T2,MXSECN ;KEEPING ONLY SECTION #
MOVEM T2,.USTMU ;SAVE IT
SETO T2, ;HIGHEST SECTION SEEN THUS FAR
CHGSC1: PUSHJ P,NXTSPG ;GET NEXT ARG
CAIL T2,(T1) ;MONOTONICALLY INCREASING?
JRST IALERR ;NO
MOVEI T2,(T1) ;UPDATE
CAMN T2,.USTMU ;TRYING TO CHANGE ARG LIST SECTION?
JRST IALERR ;YES, LOSE
JUMPE T2,ILSERR ;ALSO MUSTN'T TOUCH S0
TRNE T2,^-MXSECN ;MAKE SURE SECTION IS IN RANGE
JRST ILSERR ;ILLEGAL SECTION HERE, TOO
JUMPL T1,CHGSC3 ;DESTROY MAP
TLNN T1,(PG.SLO) ;CREATE MAP EX NIL?
AOJA T4,CHGSC2 ;YES, ONLY VERIFY RIGHT HALF
TLNE T1,<-1^!<<(PG.GAF!PG.SLO!PG.IDC)>!MXSECN>>;ANY ILLEGAL BITS?
JRST ILSERR ;NO
CHGSC2: TLO T1,400000 ;MAKE IFIW
AOS P1 ;ONE MORE CREATE TO PROCESS
MOVE T3,BITTBL##(T1) ;GET BIT FOR THIS SECTION
SKIPN .UPMP+SECTAB(T1) ;NO, DOES SECTION EXIST?
JRST [TLNE T1,(PG.SLO) ;INDIRECT SECTION?
JRST CHGS2A ;CHECK TARGET SECTION
JRST CHGSC4] ;SECTION WON'T BE INDIRECT LATER
TLNN T1,(PG.IDC) ;IDC LIT?
JRST SCEERR ;NO, SECTION CAN'T EXIST
TLNE T1,(PG.SLO) ;WERE WE TO CREATE THIS FROM NOTHING?
JRST CHGS2A ;NO, GO DEAL WITH INDIRECTION
TDZ P2,T3 ;YES, SECTION WON'T BE INDIRECT LATER
MOVE T3,.UPMP+SECTAB(T1) ;GET MAP ENTRY
TLNN T3,(<PM.DCD^!PM.ACD>B2) ;IS IT CURRENTLY INDIRECT?
SOJA T4,CHGSC4 ;NO, WE CAN JUST RE-USE THE MAP
JRST CHGSC4 ;YES, STILL NEED TO CREATE A MAP
CHGS2A: TDO P2,T3 ;TURN IT ON FOR THIS SECTION
HRRZM T1,.USTMU+1 ;SAVE THE TARGET SECTION
HLRZS T1 ;GET THE SECTION MAPPING TO
CHGS2B: ANDI T1,MXSECN ;SAVE ONLY SECTION #
MOVE T3,BITTBL##(T1) ;BIT FOR THIS SECTION
CAILE T1,(T2) ;HAVE WE ALREADY SCANNED THIS FAR?
TRNE P2,1 ;OR DONE A FUTURE SCAN ALREADY?
PUSHJ P,CHGS20 ;SCAN AHEAD IN THE LIST
TDNN P2,T3 ;WILL SECTION BE INDIRECT AFTER PROCESSING?
JRST CHGSC4 ;NO
PUSHJ P,CHGS30 ;GET TARGET SECTION
CAMN T1,.USTMU+1 ;LOOP?
JRST IALERR ;YES, HE LOSES
JRST CHGS2B
CHGSC3: SKIPN .UPMP+SECTAB(T1) ;SECTION EXIST (NOTE SIGN BIT ON
;SO OK EVEN IF IN S1)
JRST [TLNE T1,(PG.IDC) ;IDC LIT?
JRST CHGSC4 ;YES, JUST PROCEED
JRST SMEERR] ;CAN'T DESTROY NON-EX SECTION
ADD P1,[1,,0] ;# OF SECTIONS BEING DESTROYED
TDZ P2,BITTBL##(T1) ;DEFINITELY WILL NOT BE INDIRECT
CHGSC4: SOJG P4,CHGSC1 ;VALIDATE ALL ARGS
PUSH P,T4 ;SAVE NUMBER OF MAPS TO ALLOCATE
PUSHJ P,FSTPAG ;GET FIRST PAGE
MOVE P4,P3 ;RESTORE COUNT
PUSHJ P,FNDPDS## ;POINT TO THE PDB
TLZN P1,-1 ;ANY MAPS TO DESTROY?
JRST CHGSC8 ;NO
CHGSC5: PUSHJ P,NXTSPG ;GET NEXT ARGUMENT
JUMPGE T1,CHGSC7 ;A CREATE, IGNORE FOR NOW
SKIPN T2,.UPMP+SECTAB(T1) ;GET SECTION ENTRY
JRST CHGSC7 ;CONTINUE
HRRZM T1,.USSPT
TLNE T2,(<PM.ACD^!PM.DCD>B2) ;IMMEDIATE POINTER?
JRST CHGSC6 ;NO, JUST ZAP SECTION POINTER
PUSH P,P1 ;SAVE MAPPING
MOVEI P1,(T1) ;SECTION
S0PSHJ KILHSS## ;KILL ALL HIGH SEGS THAT SECTION
POP P,P1
MOVE T1,.USSPT ;SECTION ARG AGAIN
PUSHJ P,KILSEC ;KILL ALL PAGES IN SECTION
LDB T1,NZSSCN##
SOS T1 ;DECREMENT MAP COUNT
DPB T1,NZSSCN##
MOVE T1,.USSPT
MOVE T2,.UPMP+SECTAB(T1) ;GET POINTER
ANDI T2,37777 ;PAGE # ONLY
PUSHJ P,LKPSF ;LINK PAST THE PAGE IN PAGTAB
SSX T2,MS.MEM ;PAGTAB SECTION
HLLZS PAGTAB(T2) ;INDICATE LAST PAGE ALLOCATED
HRRZS T2
PUSHJ P,DLTPGC ;DELETE PAGE
MOVE T1,.USSPT ;GET SECTION # ONE MORE TIME
MOVEI T1,.UPMVP/PAGSIZ(T1) ;TURN OFF WSB FOR IT
PUSHJ P,TSWST ;GET IT
CAIA
ANDCAM T2,(T4) ;CLEAR BIT
JRST CHGS6A
CHGSC6: MOVEI T4,(T1) ;SECTION WE'RE WORKING WITH
PUSHJ P,RSECT4 ;YES, GET REAL SECTION
JFCL ;IGNORE SKIP
SETZ T1, ;NO SEGMENT DATA BLOCK
CHGS6B: PUSHJ P,GNXHSB## ;FIND NEXT SEGMENT
JRST CHGS6A ;NO MORE
LDB T2,[PSG2LH+.HBSG2(T1)] ;GET CURRENT SECTION FOR SEGMENT
CAMN T2,.USSPT ;IS IT THE ONE WE'RE DELETING?
DPB T4,[PSG2LH+.HBSG2(T1)] ;YES, SET NEW SECTION FOR SEGMENT
JRST CHGS6B ;LOOP OVER SEGMENTS
CHGS6A: MOVE T1,.USSPT
SETZM .UPMP+SECTAB(T1) ;CLEAR
CHGSC7: SOJG P4,CHGSC5 ;OVER ALL ARGS
CHGSC8: JUMPE P1,TPOPJ1## ;CLEAR JUNK, NOTHING MORE TO DO
MOVE T4,(P) ;# OF PAGES WE NEED
SKIPE P1,T4 ;REALLY WANT ANY?
PUSHJ P,GSMPGS ;GET THEM
PUSHJ P,FSTPAG ;POINT TO FIRST PAGE AGAIN
MOVE P4,P3 ;RESTORE COUNT
CHGSC9: PUSHJ P,NXTSPG ;GET NEXT PAGE
JUMPL T1,CHGS10 ;DESTROY
HRRZ T2,T1 ;JUST SECTION #
HRRZM T1,.USSPT ;SAVE
TLNE T1,(PG.SLO) ;CREATE SECTION EX NIL?
JRST CHGS11 ;NO, MAP TOGETHER
MOVE T4,.UPMP+SECTAB(T2) ;GET CURRENT MAP INFO
TLNE T4,(<PM.DCD^!PM.ACD>B2) ;FORMERLY INDIRECT?
SETZM .UPMP+SECTAB(T2) ;YES, DON'T CONFUSE CRSMAP
SKIPN P1 ;HAVE CORE?
SETO P1, ;NO, DON'T WAIT FOR IT
PUSHJ P,CRSMAP ;MAKE SECTION
MOVE T1,.USSPT ;IN CASE SECTION 0
SOJL T1,CHGS10
IDIVI T1,^D36/UP.SCS ;GET COUNTER
LDB T4,PNTNZS(T2) ;GET IT
CAIN T4,UP.VRG ;JUST CREATED?
JRST CHGS10 ;YES
PUSH P,P1
MOVE P1,.USSPT ;GET SECTION #
S0PSHJ KILHSS## ;KILL ALL HIGH SEGMENTS IN THIS SECTION
POP P,P1
MOVE T1,.USSPT ;GET SECTION #
PUSHJ P,KILSEC ;EMPTY SECTION IF IDC AND IT EXISTED
MOVE T1,.USSPT
SOS T1
IDIVI T1,^D36/UP.SCS ;GET COUNTER
MOVEI T4,UP.VRG
DPB T4,PNTNZS(T2) ;SO IT WON'T GET DELETED
CHGS10: SOJG P4,CHGSC9 ;DO NEXT
SETZ T1, ;RESTORE SECTION 0 MAPPING
POP P,T4 ;RESTORE AMT OF CORE WE WANTED
JUMPE T4,CPOPJ1## ;DONE IF NOTHING REALLY CREATED
AOS (P)
SKIPL P1 ;GET ALL MAPS IN CORE?
POPJ P, ;YES, RETURN
PUSHJ P,XPANDH## ;MARK JOB EXPANDING
IFN FTMP,<
PUSHJ TGVMM##
>
PUSHJ P,WSCHED## ;WAIT
MOVSI T1,(UP.BIG)
IORM T1,.USBTS ;BE SURE SET
POPJ P,
;HERE IF USER WANTS TO MAP TWO SECTIONS TOGETHER
CHGS11: HRRZ T2,T1 ;TARGET SECTION
SKIPE T2,.UPMP+SECTAB(T2) ;DOES IT EXIST ALREADY?
TLNE T2,(<PM.DCD^!PM.ACD>B2) ;IF SO, IS IT INDIRECT ANYWAY?
JRST CHGS12 ;NON-EX OR INDIRECT, ALL IS WELL
PUSH P,T1 ;SAVE T1
PUSHJ P,KILSEC ;KILL ALL PAGES IN SECTION
HRRZ T1,(P) ;SECTION BEING KILLED
MOVE T2,.UPMP+SECTAB(T1)
PUSHJ P,ZAPNZM
POP P,T1
CHGS12: HLRZ T2,T1 ;SOURCE SECTION
ANDI T2,MXSECN ;KEEP ONLY SECTION #
ANDI T1,MXSECN ;..
MOVEI T2,SECTAB(T2) ;SOURCE SECTION
IORI T2,(<PM.ICD>B2!PM.CSH!PM.WRT!PM.PUB)
HRLI T2,M.CPU##(J) ;INDEX INTO THE SPT
MOVSM T2,.UPMP+SECTAB(T1) ;SET IT
JRST CHGS10
;HERE TO SCAN AHEAD IN THE ARG LIST TO SET ALL BITS FOR SECTIONS
;WHICH WILL BE INDIRECT
CHGS20: PUSHJ P,SAVT## ;SAVE THE T'S
PUSH P,.USNXP ;SAVE CURRENT POSITION
MOVEI T4,-1(P4) ;# OF ARGS LEFT
SOJLE T4,CHGS24
CHGS21: PUSHJ P,NXTSPG ;GET NEXT PAGE
MOVNI T2,(T1) ;WHATEVER THE TARGET PAGE IS
MOVSI T3,(1B0) ;MASK FOR THAT PAGE
LSH T3,(T2) ;MAKE IT
TLNN T1,(PG.GAF) ;IS THIS A DELETE?
TLNN T1,(PG.SLO) ;NO, IS THIS A MAP TOGETHER?
TDZA P2,T3 ;DELETE OR CREATE EMPTY
TDO P2,T3 ;MAP TOGETHER
SOJG T4,CHGS21
CHGS24: POP P,.USNXP ;RESTORE .USNXP
POPJ P, ;ALL BITS SET
;HERE TO GET NEXT LEVEL DOWN IN SECTION FOR SECTION IN T1
CHGS30: PUSH P,.USNXP ;SAVE CURRENT .USNXP
PUSH P,T1 ;SAVE THE ARG
PUSH P,T2
PUSH P,T3
PUSH P,T4
CAMG T1,.USTMU+1 ;NEED TO GO BACK IN LIST?
SKIPA T4,P3 ;RESTORE # OF ARGS
SKIPA T4,P4 ;NO
PUSHJ P,FSTPAG ;BACK TO THE BEGINNING
CHGS31: PUSHJ P,NXTSPG ;GET NEXT ARG
HRRZ T2,T1 ;TARGET SECTION
CAMLE T2,-3(P) ;PASSED DESIRED SECTION?
JRST CHGS35 ;YES, USE CURRENT MAPPING
CAME T2,-3(P) ;IS THIS THE DESIRED SECTION?
SOJG T4,CHGS31 ;NO, LOOK AHEAD
TLNN T1,(PG.GAF) ;IS DELETE SET (SHOULD NOT BE)
TLNN T1,(PG.SLO) ;IS SLO SET (SHOULD BE)
STOPCD .,JOB,MIC ;++MONITOR IS CONFUSED
HLRZS T1 ;THE SECTION
ANDI T1,MXSECN
JRST CHGS37
CHGS35: MOVE T1,-3(P) ;USE CURRENT MAPPING
SKIPE T1,.UPMP+SECTAB(T1) ;GET THAT SECTION POINTER
TLNN T1,(<PM.ACD^!PM.DCD>B2) ;BETTER BE INDIRECT
XCT MIC
LDB T1,[POINT 5,T1,17] ;SECTION IT'S CURRENTLY MAPPED TO
CHGS37: MOVEM T1,-3(P)
POP P,T4
POP P,T3
POP P,T2
POP P,T1
POP P,.USNXP
POPJ P,
;HERE TO LOCK INDIVIDUAL PAGES IN CORE. ARG LIST FORMAT:
;
; LIST: # OF ARGS
; BITS+VPN,,[PHYS PAGE #]
; ...
;BITS: GAF ON IMPLIES UNLOCK, OFF IMPLIES LOCK SPECIFIED PAGE
; ARGMOD ON IMPLIES LOCK IN EVM, OFF IMPLIES NO EVM
;IF PHYS PAGE # SPECIFIED AS ZERO, PAGE IS LOCKED IN PLACE
;IF EVM IS REQUESTED FOR SOME PAGE, ON GOOD RETURN EVM STARTING ADDRESS
;IS STORED IN THE AC.
LOKPGS: SE1ENT ;MUST RUN IN SECTION 1
MOVE T3,JBTSTS##(J) ;IS JOB LOCKED?
TLNE T3,NSHF!NSWP
JRST PALERR ;YES, DON'T LET HIM DO THIS
PUSHJ P,SAVE4## ;SAVE P1-P4
HLRZS T1 ;JUST # OF ARGS
PUSH P,T1 ;SAVE # OF ARGS
MOVE T3,T1 ;SLIGHTLY MORE PERMANENT PLACE
SETO P1, ;CA FLAG/COUNT OF PAGES BEING LOCKED
SETZ P2, ;# OF PAGES TO DELETE
SETZB P3,P4 ;# OF PHYS PAGES (P3), AMT OF EVM (P4)
PUSHJ P,FSTPAG ;START AT THE BEGINNING
LOKPG2: PUSHJ P,NXTLPG ;GET FIRST PAGE
PUSH P,T1 ;SAVE
HLRZS T1 ;GET VIRTUAL PAGE #
ANDI T1,HLGPGS ;SAVE ONLY PAGE #
LSHC T1,P2SLSH ;GET SECTION #
CAIG T1,MXSECN ;LEGAL?
SKIPN .UPMP+SECTAB(T1) ;AND DOES SECTION EXIST?
JRST [ADJSP P,-2 ;FIX STACK
SKIPL P1 ;IF REQUIRED
PUSHJ P,CAFREE## ;RETURN THE CA RESOURCE
JRST ILPERR] ;BAD PAGE #
LSHC T1,S2PLSH ;REVERT TO PAGE
TRNN T1,HLGPNO ;IS THIS PAGE 0?
PUSHJ P,ISITS0 ;OF SOME FLAVOUR?
CAIA ;NO
JRST [ADJSP P,-2 ;FIX STACK
SKIPL P1 ;IF REQUIRED
PUSHJ P,CAFREE## ;RETURN THE CA RESOURCE
JRST ILPERR] ;BAD PAGE
PUSHJ P,GTPME ;GET ENTRY
POP P,T1 ;RESTORE FULL ARG
SKIPL T1 ;UNLOCK?
TDZA T4,T4
MOVEI T4,1
XCT [TLNE T2,(PM.LOK)
TLNN T2,(PM.LOK)](T4)
JRST [TLNE T1,(PG.IDC) ;CARE?
JRST LOKPG4 ;NO
POP P,(P) ;FIX STACK
SKIPL P1 ;WRONG MODE (NO CA YET)
PUSHJ P,CAFREE## ;FREE THE CA
JRST PALERR(T4)] ;NO
JUMPE T2,[POP P,(P) ;FIX STACK
SKIPL P1 ;IF REQUIRED
PUSHJ P,CAFREE## ;RETURN THE CA RESOURCE
JRST PMEERR] ;PAGE MUST EXIST
JUMPL T1,[AOJA P2,LOKPG4] ;COUNT IF DELETE
TLNE T2,(PM.COR) ;IN CORE?
JRST LOKPG3 ;YES, NO PROBLEM
;WE REALLY OUGHT TO PAGE IN THE PAGE FOR THE GUY, BUT FOR
;NOW THAT IS NOT IMPLEMENTED. TO IMPLEMENT, REPLACE CODE HERE
POP P,(P) ;FIX STACK
SKIPL P1 ;IF REQUIRED,
PUSHJ P,CAFREE## ;RETURN THE RESOURCE
JRST UIFERR
LOKPG3: PUSHJ P,LKPGCA ;GET CA IF REQUIRED, INCREMENT P1
TLNE T1,(PG.SLO) ;NEED EVM FOR THIS PAGE?
AOS P4 ;YES
SKIPGE -5(P) ;PHYS ONLY (SAVED P1 ON STACK)?
AOJA P3,LOKPG4 ;THEN COUNT THIS PAGE
TRNE T1,-1 ;OR IF A SPECIFIC PAGE REQ'D
TLOA P3,(1B0) ;SET THE SIGN BIT
JRST LOKPG4 ;NO
HLLM P3,.USLPG ;FLAG FOR LOKCON
HRRZS T1 ;PAGE #
LSH T1,P2WLSH ;CONVERT TO WORD
CAML T1,MEMSIZ## ;CAN PHYS PAGE EXIST?
JRST [POP P,(P) ;FIX STACK
SKIPL P1 ;IF REQUIRED,
PUSHJ P,CAFREE## ;RETURN THE RESOURCE
JRST ILPERR] ;NO
LSH T1,W2PLSH ;CONVERT BACK TO PAGE #
SSX T1,MS.MEM ;POINT TO PAGTAB SECTION
MOVE T1,PAGTAB(T1) ;GET ENTRY
TLNE T1,LKBITS ;PART OF LOCKED JOB, MONITOR, ETC.?
;***CHECK OTHER THINGS***
JRST [POP P,(P) ;FIX STACK
SKIPL P1 ;IF REQUIRED,
PUSHJ P,CAFREE## ;RETURN THE RESOURCE
JRST PNAERR] ;PAGE IN LOCKED JOB, ETC.
LOKPG4: SOJG T3,LOKPG2 ;SCAN LIST
JUMPLE P2,LOKPG8 ;NO PAGES TO UNLOCK
PUSHJ P,FSTPAG ;START AGAIN
MOVSI T3,(PM.LOK)
LOKPG5: PUSHJ P,NXTLPG ;GET NEXT PAGE
JUMPGE T1,LOKPG5 ;A LOCK
HLRZS T1 ;ONLY VPN
ANDI T1,HLGPGS
PUSHJ P,GTPME ;GET POINTER TO PAGE
TLNN T2,(PM.LOK) ;IS IT LOCKED?
JRST LOKPG5 ;MUST HAVE BEEN A DON'T CARE PAGE
ANDCAM T3,(T4) ;CLEAR LOCK IN HERE
TLZ T2,(PM.NAD) ;KEEP ONLY PAGE #
AOS JBTIMI##(J) ;INCREMENT IMGIN
.CREF IMGIN
PUSHJ P,RMVLPG
PUSHJ P,WSBIT
IORM T2,(T4) ;PUT BACK IN THE WORKING SET
LDB T1,JBYLSA## ;GET FIRST PAGE OF JOB
SSX T1,MS.MEM ;SET SECTION
SSX T2,MS.MEM
HRRZ T3,PAGTAB(T1)
HRRM T2,PAGTAB(T1) ;SET FORWARD LINKS
HRRM T3,PAGTAB(T2)
SKIPE T3 ;IF NOT ZERO
HRRM T2,@[IW MS.MEM,PT2TAB(T3)]
HRRM T1,PT2TAB(T2)
SOJG P2,LOKPG5
LOKPG8: SETZ T1, ;NOT LOCKING EITHER SEG
PUSHJ P,CHKLPG## ;SEE IF THINGS WILL FIT
JRST [POP P,(P) ;RESTORE STACK
SKIPL P1 ;IF REQUIRED,
PUSHJ P,CAFREE## ;RETURN THE RESOURCE
JRST IRLERR] ;INSUFFICIENT ROOM TO LOCK
MOVEI T1,(P3) ;# OF PAGES LOKPHY NEEDS TO KNOW
PUSH P,P1 ;SAVE FLAG
MOVN P1,-1(P) ;GET -COUNT
SKIPE P3 ;IF ONLY IN-PLACE PAGES, JUST DO HERE
PUSHJ P,LOKPHY## ;LOCK
POP P,P1 ;RESTORE CA FLAG
SKIPGE -5(P) ;COULD ANY IN-PLACE PGS BE THERE?
JRST LKPEVM ;NO (SAVED P1), SEE IF NEED EVM
PUSHJ P,FSTPAG ;START
LOKPG9: PUSHJ P,NXTLPG ;GET NEXT PAGE
JUMPL T1,LOKP10 ;DELETE, ALREADY DONE
TRNE T1,-1 ;SPECIFIC PAGE REQUESTED?
JRST LOKP10 ;YES, THIS IS NOT AN IN PLACE
HLRZS T1 ;GET PAGE #
ANDI T1,HLGPGS
PUSHJ P,GTPME ;GET PAGE MAP ENTRY
PUSH P,T2 ;SAVE PAGE #
MOVSI T2,(PM.LOK) ;LOCK PAGE
IORM T2,(T4) ;SET IT
POP P,T2 ;RESTORE PHYS PAGE #
TLZ T2,(PM.NAD) ;CLEAR BITS
PUSHJ P,LKPSF ;PULL OUT OF JOB'S PAGTAB CHAIN
HRRZ T4,.USLPG ;CURRENT 1ST PAGE IN LOCKED Q
HRRM T2,.USLPG ;WE ARE NOW FIRST
SSX T2,MS.MEM
DPB T1,[POINT P2.SPN,PT2TAB(T2),<^L<P2.VPN>+P2.SPN-1>]
HRRM T4,PAGTAB(T2) ;SAVE
TRNE T4,-1 ;IF THERE IS A SUCCESSOR
HRRM T2,@[IW MS.MEM,PT2TAB(T4)] ;POINT HIM AT US
PUSHJ P,TSWST ;GET BIT
CAIA ;ALREADY CLEAR
ANDCAM T2,(T4) ;CLEAR
SOS JBTIMI##(J) ;DECREMENT IMGIN
.CREF IMGIN
LOKP10: SOSLE (P) ;ANY MORE ARGS?
JRST LOKPG9 ;YES
LKPEVM: SKIPL P1 ;IF REQUIRED,
PUSHJ P,CAFREE## ;RETURN CA RESOURCE NOW
JUMPE P4,TPOPJ1## ;DONE IF NO EVM
MOVSI T1,(PM.CSH) ;TURN CACHE OFF
SETZ T2,
DMOVEM T1,.USTMP ;YES, MUST BE .USTMP (NOT .USTMU)
MOVN T1,P4 ;-AMOUNT OF EVM REQUIRED
PUSHJ P,LOKEVX## ;LOCK PAGES IN EVM
CAIA ;OOPS
JRST TPOPJ1## ;DONE
PUSHJ P,EVMERR ;NO EVM ERROR
POP P,(P) ;FIX STACK
CAIA ;FALL INTO CLEAR LOCKED PAGES CODE
CLRLPG::SE1ENT
SKIPN T2,.USLPG ;ANY PAGES TO UNLOCK?
POPJ P, ;NO
PUSH P,T1 ;SAVE T1
LDB T3,JBYLSA## ;FIRST PAGE OF LOW SEG
SSX T3,MS.MEM ;PAGTAB ADDRESS
PUSH P,PAGTAB(T3) ;SAVE CURRENT LINK TO NEXT
SSX T2,MS.MEM ;SET INDEX FOR THIS
HRRM T3,PT2TAB(T2) ;SET BACK LINK
CLRLP1: HRRM T2,PAGTAB(T3) ;STORE LINK TO NEXT
HRRI T3,(T2) ;POINT FORWARD
MOVSI T2,LKBITS ;CLEAR LOCKED BITS IN PAGTAB
AND T2,PAGTAB(T3) ;GET THE BITS THAT ARE SET
ANDCAM T2,PAGTAB(T3)
TLNN T2,LOKEVB ;THIS PAGE IN EVM?
JRST CLRLP2 ;NO
SOS .C0EVU## ;CLEAR THIS PAGE USED
PUSH P,T3
MOVE T3,MEMTAB(T3) ;EVM ADDRESS
.CREF MT.EVM
MOVE T2,EVMPTR##
S0PSHJ ZERBTS## ;CLEAR EVM BITS
PUSHJ P,CONEVA##
POP P,T3
CLRLP2: LDB T1,NVPNT3 ;GET VIRT PAGE THIS PAGE IS FOR
PUSHJ P,GTPME ;GET PAGE ENTRY
MOVSI T2,(PM.LOK) ;CLEAR BIT
ANDCAM T2,(T4) ;CLEAR THIS
AOS JBTIMI##(J) ;PUT BACK IN WORKING SET
PUSHJ P,WSBIT ;GET BIT
IORM T2,(T4) ;TURN IT ON
HRRZ T2,PAGTAB(T3) ;LINK TO NEXT
JUMPN T2,CLRLP1 ;LOOP BACK
POP P,T2 ;RESTORE REST OF JOB'S CHAIN
HRRM T2,PAGTAB(T3) ;LINK FROM LOCKED CHAIN TO IT
SSX T2,MS.MEM ;RIGHT SECTION
TRNE T2,-1 ;ASSUMING THERE ARE MORE PAGES,
HRRM T3,PT2TAB(T2) ;SET BACK LINK
CLRLP4: SETZM .USLPG ;NO MORE LOCKED PAGES
JRST TPOPJ## ;RESTORE T1 AND RETURN
LKPGCA: AOJN P1,CPOPJ## ;ONLY GET CA IF FIRST TIME
IFN FTMP,<
PUSHJ P,REMMM## ;REMEMBER STATE OF MM
>
PUSHJ P,CAWAIT## ;GET THE CA RESOURCE
AOJA P1,CPOPJ## ;RETURN
;HERE TO REMOVE A LOCKED PAGE FROM A JOB'S CHAIN (NOT RE-INSERTING IT
;ANYWHERE). T2 HAS PHYSICAL PAGE TO REMOVE
RMVLPG: PUSHJ P,SAVT## ;SAVE TS
MOVEI T3,.USLPG
PUSHJ P,REMPFQ
MOVSI T1,LKBITS ;GET THE LOCK BITS
SSX T2,MS.MEM ;POINT TO THE SECTION
AND T1,PAGTAB(T2) ;GET WHAT THE BITS ARE
ANDCAM T1,PAGTAB(T2) ;THEN CLEAR THEM
TLNN T1,LOKEVB ;WAS PAGE IN EVM?
POPJ P, ;NO, NOTHING MORE TO DO
MOVE T3,MEMTAB(T2) ;ELSE MUST RETURN THE EVM
.CREF MT.EVM
SOS .C0EVU## ;LESS IN USE
MOVE T2,EVMPTR##
S0PSHJ ZERBTS## ;CLEAR BITS
PJRST CONEVA## ;RETURN
;SUBROUTINE TO SCAN A LIST OF PAGES, VERIFY THAT EACH ENTRY IN THE
; LIST REPRESENTS A LEGAL VIRTUAL PAGE NUMBER, AND COUNT THE NUMBER
; OF ENTRIES WITH THE HIGH ORDER BIT ON AND THE NUMBER OF ENTRIES WITH
; THE HIGH ORDER BIT OFF.
;CALLING SEQUENCE:
;
; MOVE T1,[XWD N,ADDRESS OF LIST]
; MOVE T2,REQUIRED ATTRIBUTES
; PUSHJ P,PLTSN
;ERROR RETURNS, ILLEGAL PAGE NUMBER, PAGE EXISTS BUT MUST NOT, PAGE
; DOESN'T EXIST BUT MUST, PAGE MUST BE IN CORE BUT ISN'T, PAGE MUST
; NOT BE IN CORE BUT IS, AN ATTEMPT HAS BEEN MADE TO DO ANYTHING TO A
; PAGE IN A SHARABLE HIGH SEGMENT.
;RETURNS CPOPJ ON AN ERROR, T1 = ERROR CODE,
; RETURNS CPOPJ1 ON SUCCESS, T1 PRESERVED, T2 = NUMBER OF ENTRIES
; WITH THE SIGN BIT ON, T3 = THE NUMBER OF ENTRIES WITH THE SIGN BIT OFF
; .UPTMP=C(T3) - NUMBER OF ALLOCATED BUT ZERO PAGES
; T4=# OF NON-EXISTENT SECTIONS (AND PA.PME WASN'T ON) + 1 IF UP.BIG WASN'T ON
;AND T4 IS NON-ZERO OTHERWISE (SO WILL ALLOCATE PAGE FOR .WSBNZ)
;RETURNS WITH BIT 0 ON IN M IF BIT 1(PG.SLO, PG.DSK) IS ON IN ANY ARGUMENT WORD
PLTSN: PUSHJ P,INTLVL## ;NO WAITING AT INTERRUPT LEVEL
PUSHJ P,IOWAT ;WAIT FOR I/O TO STOP (SO I/O CAN'T CHANGE ARG LIST)
PUSHJ P,SAVE3## ;SAVE P1-P3
PUSHJ P,SAVR## ;AND R
SE1ENT
PUSH P,T1 ;SAVE POINTER TO THE ARGUMENT LIST
HRRZ P1,T1 ;SAVE COPY FOR COMPUTING LIST LIMITS
PUSHJ P,FSTPAG ;POINTER TO USER'S ARGUMENT LIST
HLRE P2,T1 ;NUMBER OF ARGUMENTS
JUMPLE P2,[PUSHJ P,IALERR
JRST T2POPJ##] ;MUST BE A POSITIVE NUMBER OF ARGUMENTS
ADJSP P,2 ;FOR STORING LIMITS
PUSH P,P2 ;SAVE THE NUMBER OF ARGUMENTS
MOVE P3,.USNXP ;NEGATIVE ARG LIST FORM?
AOSE P3 ;?
MOVEI P2,1 ;YES, THEN ARG LIST SIZE IS 1
SOS P1 ;INCLUDE COUNT
ADDI P2,(P1) ;LAST PAGE OF ARG LIST
TRZ P1,PG.BDY ;SO WON'T SHIFT INTO P2
LSHC P1,W2PLSH ;FIRST AND LAST PAGES CONTAINING ARG LIST
DMOVEM P1,-2(P) ;SAVE THEM
MOVE P2,T2 ;CHECK BITS
PLTSN0: SETZB P1,.USTMU ;INITIALIZE ARGUMENT TYPE COUNTER AND .UPTMP TO ZERO
SETZB R,P3 ;NOTE CAN **NEVER** THINK OF DESTROYING P0
PLTSN1: PUSHJ P,NXTPAG ;GET THE NEXT ARGUMENT
TLZE T1,(PG.SLO) ;CREATE VIRTUAL OR PAGE ON SLOW DEVICE?
TLO M,ARGMD ;YES, REMEMBER THAT
MOVE T3,T1 ;SAVE ARG
HRRZS T1
TRNN T1,HLGPNO ;IS IT PAGE 0 OF SOME FLAVOUR?
PUSHJ P,ISITS0 ;??
CAIA ;IS NOT PAGE 0
JRST PLTSN2 ;IS PAGE 0, CHECK IT SOME OTHER WAY
PUSHJ P,LGLPG ;A LEGAL PAGE?
JRST PLTSN3 ;NO
PLTSN4: JUMPE T1,PLTS30 ;CHECK PAGE 0 OTHERWISE
CAML T1,-2(P) ;DOES IT CONTAIN THE ARG LIST?
CAMLE T1,-1(P) ;?
PLTS30: SKIPA T1,T3
JRST PLTSN3 ;LOSE
TRNN P2,PA.IHB ;IGNORE THE HIGH ORDER BIT OF THE ARGUMENT?
JUMPGE T1,PLTSN5 ;NO, JUMP IF THE HIGH ORDER BIT IS OFF
TLZ T1,400000 ;CLEAR THE HIGH ORDER BIT
CAIL P3,(T1) ;THIS PAGE HIGHER THAN LAST ONE SEEN?
JRST [PUSHJ P,IALERR ;NO, ILLEGAL ARGUMENT LIST ERROR
JRST PLTS16] ;ARGUMENT LIST MUST BE IN INCREASING VIRTUAL ORDER
MOVEI P3,(T1) ;SAVE AS HIGHEST PAGE SEEN SO FAR
MOVEI T4,(T1) ;GET PAGE NUMBER
LSH T4,P2SLSH ;CONVERT TO SECTION
TRNE P2,PA.PWE ;MUST PAGE BE WRITE ENABLED?
PUSHJ P,RSECT4 ;MUST BE WRITE ENABLED, DOES IT EXIST?
JRST PLTS4A ;DOESN'T EXIST (AND IS THUS WE, SORT OF) OR WE
PUSHJ P,GTPME ;GET THE PAGE MAP ENTRY
TLNN T2,(PM.WRT) ;IS IT WRITE-ENABLED?
TLNE T1,(PG.IDC) ;DOES HE CARE?
JRST PLTS4A ;NO
PUSHJ P,PWLERR ;CAN'T BE WRITE-LOCKED
PJRST PLTS16
PLTS4A: MOVEI T3,1 ;ASSUME NORMAL CASE (SEE NOTE @PLTSN8)
TRNN P2,PA.PMI ;MUST THE PAGE BE IN CORE?
JRST PLTSN8 ;NO
PUSHJ P,TSWST ;SEE IF THE PAGE IS IN THE WORKING SET
TLOA T3,(1B0) ;FLAG TO NOT ADD ANY COUNT
JRST PLTSN8 ;IN THE WORKING SET
TLNE T1,(PG.IDC) ;DOES HE WANT US TO IGNORE THIS?
JRST PLTSN8 ;YES, DO SO
PUSHJ P,PMIERR ;HE CARES, HE ALSO LOSES
PJRST PLTS16
PLTSN5: JUMPE P3,PLTS5A ;FIRST TIME
CAIL P3,(T1) ;THIS PAGE HIGHER THAN THE LAST PAGE SEEN?
JRST [PUSHJ P,IALERR ;NO, ILLEGAL ARGUMENT LIST ERROR
JRST PLTS16] ;LOSE
PLTS5A: MOVEI P3,(T1) ;SAVE AS HIGHEST PAGE SEEN
MOVSI T3,1 ;ADD 1 TO THE COUNT OF ARGUMENTS WITH THE
; HIGH ORDER BIT OFF (SEE NOTE @PLTSN8)
PUSHJ P,PLTS20 ;SECTION EXIST?
JRST PLTS17 ;NO, SEE ABOUT NON-EX SECTION CREATION
PUSHJ P,GTPME ;GET CONTENTS OF MAP SLOT
TLZ T2,(PM.NAD)
CAMN T2,[PM.ZER] ;ABZ PAGE?
AOSA .USTMU ;YES, BUMP COUNTER
TRNN P2,PA.PCE ;CAN THE PAGE EXIST?
JRST PLTSN6 ;YES, PROCEED
JUMPE T2,PLTS13 ;DOES PAGE EXIST (GO IF NO)?
TLO T3,(1B0) ;IN CASE WE DON'T CARE
TLNE T1,(PG.IDC) ;REALLY NOT WANT IT TO EXIST?
JRST PLTS13
PUSHJ P,PCEERR ;YES, PAGE CANNOT EXIST BUT DOES ERROR
JRST PLTS16 ;LOSE
PLTSN6: MOVE T2,(T4) ;GET FULL ENTRY AGAIN
TRNE P2,PA.PWL ;MUST PAGE BE WRITE-LOCKED?
TLNN T2,(PM.WRT) ;YES, AND IS IT?
JRST PLTS6A ;WE DON'T CARE, OR IT IS
TLNE T1,(PG.IDC) ;DOES HE REALLY CARE?
JRST PLTS6A ;NO
PUSHJ P,PWEERR
JRST PLTS16
PLTS6A: TRNN P2,PA.PCI ;CAN THE PAGE BE IN CORE?
JRST PLTSN8 ;YES, PROCEED
PUSH P,P1 ;NEED TO SAVE T2 HERE
MOVSI P1,(PM.NAD) ;REALLY ONLY WANT ENTRY PART
ANDCA P1,T2 ;SO ONLY PICK UP THAT PART
PUSHJ P,TSWST ;IS THE PAGE IN THE WORKING SET?
CAMN P1,[PM.ZER] ;NO, ABZ?
TLOA T3,(1B0) ;NO COUNT TO ADD
JRST PLTSN7 ;NO, ALL IS WELL
CAME P1,[PM.ZER] ;ALWAYS CARE ON PAGE I/O IF ABZ
TLNN T1,(PG.IDC) ;DO WE?
JRST [POP P,P1 ;RESTORE P1
JRST PLTS15] ;CONTINUE
PLTSN7: POP P,P1
;AT THIS POINT T3 AS "1" IN THE RIGHT HALF IF THE ARG HAD THE SIGN ON,
;AND "1" IN THE LEFT HALF IF THE SIGN BIT WAS OFF. HOWEVER, IF THE
;SIGN BIT OF T3 IS ON, THIS NUMBER WILL *NOT* BE ADDED TO TO THE
;ACCUMULATED COUNTS. THE CODE *CANNOT* JUST ZERO T3 TO INDICATE
;NOTHING TO ADD AS THE EXISTANCE OF THE COUNT IN THE APPROPRIATE
;HALFWORD IS USED TO DECIDE WHETHER THE ORIGINAL ARG HAD THE SIGN
;BIT ON OR NOT. NOTE THAT RIGHT-HALF TESTERS CAN TEST FOR -1, BUT
;LEFT HALF TESTERS MUST TEST FOR NO MORE BITS THAN 377777.
PLTSN8: TRNN P2,PA.PME ;MUST THE PAGE EXIST?
JRST PLTS13 ;NO, PROCEED
PUSHJ P,PLTS20
TDZA T2,T2 ;NO, PAGE DOESN'T THEN
PUSHJ P,GTPME ;GET THE CONTENTS OF THE MAP SLOT
JUMPN T2,PLTSN9 ;IT DOES
TLO T3,(1B0) ;IN CASE WE DON'T CARE
TLNE T1,(PG.IDC) ;DO WE?
TRNE P2,PA.PMI!PA.PCI!PA.PWE!PA.PWL ;CAN'T FOLLOW IGNORE BIT FOR PAGE IN/OUT
CAIA
JRST PLTS13 ;NO
PUSHJ P,PMEERR ;JUMP IF PAGE DOESN'T EXIST SINCE IT MUST
JRST PLTS16 ;LOSE
PLTSN9: TRNN T3,-1 ;SIGN BIT OFF IN ARGUMENT?
TRNN P2,PA.PCI ;REALLY ASKING IF THIS IS A PAGE IN
JRST PLTS13 ;NO, DON'T CHECK INCORE QUEUES
TLNE T2,(PM.OIQ) ;ON IN LIST?
JRST [TLNN T2,(PM.SSP) ;SLOW?
SKIPA T3,[PAGINQ##] ;NO, FAST
MOVEI T3,PAGSNC## ;SLOW QUEUE
TLZ T2,(PM.NAD) ;CLEAR JUNK
JRST PLTS11] ;REMOVE PAGE
TLZ T2,(PM.NAD) ;ISOLATE ADDRESS
PLTS10: PUSHJ P,ONPOQ ;NO, IS THE PAGE ON THE IP OR OUT LIST?
JRST PLTS12 ;NO
CAIN T3,PAGIPQ## ;THIS PAGE IN THE IN PROGRESS QUEUE?
JRST PLTS18 ;YES
HRRZ T2,T4 ;YES, GET THE PAGE
PLTS11: PUSHJ P,RMVPFQ ;REMOVE PAGE FROM QUEUE
HRRZ T3,.USTMU ;CURRENT PAGE ON PRIVATE QUEUE
HRRM T3,@[IW MS.MEM,PAGTAB(T2)] ;POINT AHEAD
SKIPE T3 ;AND IF SOMETHING IS THERE
HRRM T2,@[IW MS.MEM,PT2TAB(T3)] ;POINT HIM BACK
HRRM T2,.USTMU ;PUT PAGE IN OUR PRIVATE QUEUE
MOVSI T3,(P2.TRN) ;MARK PAGE IN TRANSIT
IORM T3,@[IW MS.MEM,PT2TAB(T2)]
MOVSI T3,-1 ;AND "INCREMENT" COUNT
ADDM T3,.USTMU
TDZA T3,T3 ;DON'T NEED TO ALLOCATE ANY CORE
PLTS12: MOVSI T3,1 ;NO, COUNT THE PAGE
PLTS13: PUSHJ P,PLTS20 ;SECTION EXIST?
JRST PLTS14 ;NO, DON'T WORRY ABOUT HIGH SEGS THEN
PLTS19: PUSHJ P,TPNHX ;IS THE PAGE IN A HIGH SEGMENT?
TLOA M,HSPAG ;YES, REMEMBER HIGH SEGMENT PAGE SEEN
JRST PLTS14 ;NOT A HIGH SEG PAGE
MOVE T2,.HBSGN(T2) ;GET HIGH SEGMENT BITS
TLNN T2,SHRSEG!SPYSEG;YES, IS THE HIGH SEGMENT SHARABLE OR A SPY SEG?
JRST PLTS14 ;NO
PUSHJ P,PSHERR ;YES, PAGE IN A SHARABLE HIGH SEGMENT ERROR
JRST PLTS16 ;LOSE
PLTS14: SKIPL T3 ;IF SIGN BIT SET, DON'T ACCUMULATE
ADD P1,T3 ;ACCUMULATE NUMBER OF ARGUMENTS
SOSLE (P) ;LOOKED AT ALL ARGUMENTS IN THE LIST?
JRST PLTSN1 ;NO, LOOP OVER ALL ARGUMENTS
ADJSP P,-3 ;CLEAR STACK JUNK
HRRZ T2,P1 ;T2 = NUMBER OF ARGUMENTS WITH THE SIGN BIT ON
HLRZ T3,P1 ;T3 = NUMBER OF ARGUMENTS WITH THE SIGN BIT OFF
MOVEI T4,(R) ;# OF NON-EX SECTIONS
SKIPGE .USBTS ;ALREADY A BIG USER?
JRST TPOPJ1## ;YES, DON'T NEED TO MAKE .WSBNZ
JUMPE T4,TPOPJ1## ;NOT BIG ALREADY, BUT NOT BECOMING SO EITHER
AOJA T4,TPOPJ1## ;RESTORE T1 AND RETURN
PLTS15: PUSHJ P,PCIERR
PLTS16: ADJSP P,-4 ;FIX STACK
POPJ P,
; ERROR CODE IN T1
PLTS17: TRNN P2,PA.PCE ;CAN'T EXIST?
JRST PLTSN6 ;NO, CHECK OTHER THINGS
HLRZ T4,R ;PREVIOUS HIGHEST SECTION COUNTED
HRL R,T2 ;REMEMBER SECTION
CAME T4,T2 ;SAME AS CURRENT?
AOJA R,PLTS14
JRST PLTS14
;HERE IF PAGE ON THE IP QUEUE
PLTS18: SSX T4,MS.MEM ;YES, MUST WAIT UNTIL I/O IS DONE, PAGTAB SECTION
DPB J,[POINT PT.SJB,PAGTAB(T4),^L<PT.JOB>+PT.SJB-1] ;STORE JOB NUMBER IN IP QUEUE
MOVEI T3,PIOWQ## ; SO JOB CAN BE WOKEN UP WHEN I/O IS DONE
DPB T3,PJBSTS## ;PUT JOB IN PAGING I/O WAIT
PUSHJ P,[IFN FTMP,<
PUSHJ P,REMMM## ;REMEMBER STATE OF THE MM
>
PJRST WSCHED##] ;COME BACK WHEN "IP" QUEUE HAS BEEN WRITTEN
PUSHJ P,GTPME ;(IN CASE PAGE WRITE ERROR ENCOUNTERED)
JRST PLTS10 ;SEE IF IT'S ON THE OUT QUEUE NOW
PLTS20: HRRZ T2,T1 ;PAGE #
LSH T2,P2SLSH ;CONVERT TO SECTION #
SKIPE .UPMP+SECTAB(T2) ;DOES IT EXIST?
AOS (P) ;YES
POPJ P,
PLTSN2: TLNE T3,(PG.IDC) ;IS THIS AN I DON'T CARE?
JUMPGE T3,PLTSN4 ;W/O PG.GAF LIT?
PLTSN3: PUSHJ P,IALERR
JRST PLTS16
;SUBROUTINE TO SEE IF A PAGE IS ON THE "IN PROGRESS" OR "OUT: QUEUE
;CALL:
; MOVE T2,MAP CONTEXTS (DSK ADDRESS)
; PUSHJ P,ONPOQ ;SEE IF ON EITHER QUEUE
; NOT FOUND
; FOUND, T3=QUEUE, T4=PHYSICAL PAGE NUMBER
;PRESERVES T1
ONPOQ:: SE1ENT ;ENTER SECTION 1
MOVEI T3,PAGOUQ## ;"OUT" QUEUE HEADER
PUSHJ P,SRCPQ ;SCAN THE QUEUE
ONIPQ:: SKIPA T3,[PAGIPQ##] ;NOT THERE, TRY "IP" QUEUE
JRST CPOPJ1## ;FOUND RETURN
; PJRST SRCPQ ;SCAN THAT QUEUE
;SUBROUTINE TO SEARCH A PAGE QUEUE TO SEE IF IT CONTAINS A PAGE WITH A GIVEN
; DSK ADDRESS
;CALL: MOVE T2,DSK ADDRESS
; MOVEI T3,ADDRESS OF QUEUE HEADER
; PUSHJ P,SRCPQ ;SEARCH THE PAGE QUEUE
; NOT FOUND
; FOUND, T4=PHYSICAL PAGE NUMBER
;PRESERVES T1
SRCPQ: SKIPN T4,(T3) ;ANYTHING AT ALL ON THE QUEUE?
POPJ P, ;NO, SO PAGE IN QUESTION ISN'T
SRCPQ0: PUSHJ P,SAVE1## ;SAVE A WORK REG
SRCPQ1: SSX T4,MS.MEM ;PAGTAB SECTION
LDB P1,[POINT MT.SAD,MEMTAB(T4),<^L<MT.DAD>+MT.SAD-1>]
CAMN P1,T2 ;SAME AS DSK ADDRESS FROM A MAP?
JRST SRCPQ2 ;YES, FOUND IT
HRRZ T4,PAGTAB(T4) ;NEXT PAGE ON QUEUE, LAST PAGE?
JUMPN T4,SRCPQ1 ;NO, LOOP OVER ALL PAGES ON THE LIST
POPJ P, ;PAGE NOT IN THE LIST
SRCPQ2: HRRZS T4 ;ISOLATE PHYSICAL PAGE NUMBER
JRST CPOPJ1## ;AND GIVE FOUND RETURN
;SUBROUTINE TO POINT M AT THE FIRST ARGUMENT IN THE USER'S ARGUMENT
; LIST AND SETUP .UPNXP IF A NEGATIVE COUNT WAS SPECIFIED, I.E.,
; A RANGE OF PAGES RATHER THAN A LIST OF PAGES
FSTPAG::PUSHJ P,SAVT## ;MAKE THIS LOOK LIKE A HRRI M,-1(T1)
PUSHJ P,GETSAC## ;GET CONTENTS OF USER'S AC
SETOM .USNXP ;ASSUME A TRADITIONAL ARGUMENT LIST
HRRI M,(T1) ;SETUP M TO GET ARGUMENT COUNT
PUSHJ P,GETWSU## ;GET ARGUMENT COUNT
JUMPGE T1,CPOPJ## ;POSITIVE MEANS A LIST IS SPECIFIED
PUSHJ P,GETWS1## ;GET THE RANGE
JRST PREPA1 ;STORE IT FOR CALLS TO NXTPAG AND RETURN
;SUBROUTINE TO GET THE NEXT WORD FROM THE USER'S ARGUMENT LIST
; FSTPAG MUST HAVE BEEN CALLED BEFORE CALLING NXTPAG
NXTPAG: MOVE T1,.USNXP ;A RANGE OF PAGES SPECIFIED?
CAMN T1,[-1]
PJRST GETWS1## ;NO, GET NEXT ARGUMENT FROM LIST
TLNN T1,37777 ;LEFT HALF, RIGHT HALF ARGUMENT?
AOSA T1 ;NO, JUST INCREMENT LEFT HALF
AOBJN T1,.+1 ;YES, INCREMENT BOTH HALVES
EXNXP: EXCH T1,.USNXP ;GET CURRENT VALUE AND SET NEW ONE
POPJ P,
NXTSPG: MOVE T1,.USNXP ;A RANGE OF PAGES SPECIFIED?
CAMN T1,[-1]
PJRST GETWS1## ;NO, GET NEXT ARGUMENT FROM LIST
AOBJN T1,EXNXP ;YES, INCREMENT BOTH HALVES
JRST EXNXP ;STORE FOR NEXT CALL AND RETURN
NXTLPG::MOVS T1,.USNXP ;RANGE SPECIFIED?
CAMN T1,[-1] ;?
PJRST GETWS1## ;NO, GET NEXT ARG
AOS T1 ;ALWAYS INCREMENT LEFT HALF
MOVSS T1 ;PUT HALVES BACK
TRNE T1,-1 ;IF THIS SPECIFIED 0 FOR DEST,
AOS T1 ;LEAVE AS 0 ELSE INCREMENT
JRST EXNXP ;RETURN CURRENT VALUE AND STORE NEXT
;SUBROUTINE TO GET PREVIOUS WORD FROM THE USER'S ARGUMENT LIST
; FSTPAG MUST HAVE BEEN CALLED BEFORE CALLING PREPAG
PREPAG: MOVE T1,.USNXP ;A RANGE OF PAGES SPECIFIED?
CAMN T1,[-1]
SOJA M,GETWSU## ;NO, BACK UP TO PREVIOUS ARGUMENT IN LIST AN GET IT
TLNN T1,37777 ;PAGE PAIR?
SOSA T1 ;NO, BACK UP THE PAGE NUMBER
SUB T1,[1,,1] ;BACK UP 1 PAGE
PREPA1: MOVEM T1,.USNXP ;SAVE FOR NEXT CALL
POPJ P, ;AND RETURN
;ERROR RETURNS
PIOERR: PUSHJ P,SAVE1##
HRRZ P1,T2 ;SWPLST INDEX
MOVE S,SWPLST##(P1) ;GET THE SWPLST ENTRY CONTAINING THE ERROR
TLNN S,(SL.DIO) ;INPUT ERROR?
JRST PIOER1 ;YES, NOTHING CAN BE DONE ABOUT IT
PUSHJ P,MAPBAK ;RESTORE THE MAP
SOS .JDAT+JOBPD1##+1 ;FORCE THE UUO TO BE REDONE
POPJ P, ;RETURN
PIOER1: PUSHJ P,DLTSLX ;DELETE THE SWPLST ENTRY
JRST PIOER2 ;RETURN ERROR CODE TO THE USER
;ERROR RETURNS
ERCODE UIFERR,PAGUF% ;(0)UNIMPLEMENTED FUNCTION
ERCODE IALERR,PAGIA% ;(1)ILLEGAL ARGUMENT LIST
ERCODE ILPERR,PAGIP% ;(2)ILLEGAL PAGE
ERCODE PCEERR,PAGCE% ;(3)PAGE CANNOT EXIST BUT DOES
ERCODE PMEERR,PAGME% ;(4)PAGE MUST EXIST BUT DOESN'T
ERCODE PMIERR,PAGMI% ;(5)PAGE MUST BE IN CORE BUT ISN'T
ERCODE PCIERR,PAGCI% ;(6)PAGE CANNOT BE IN CORE BUT IS
ERCODE PSHERR,PAGSH% ;(7)PAGE IN A SHARABLE HIGH SEGMENT
ERCODE PIOER2,PAGIO% ;(10)PAGING I/O ERROR
ERCODE NSAERR,PAGNS% ;(11)NO SWAPPING SPACE AVAILABLE
ERCODE TBGERR,PAGLE% ;(12)CORE (VIRTAL OR USER LIMIT) EXCEEDED
ERCODE IILERR,PAGIL% ;(13)ILLEGAL IF LOCKED
ERCODE NVLERR,PAGNV% ;(14)ATTEMPT TO CREATE ABZ PAGE WITH CVPL=0
ERCODE NPVERR,PAGNP% ;(15)NOT PRIVILEGED
ERCODE SCEERR,PAGSC% ;(16)SECTION CAN'T EXIST BUT DOES
ERCODE SMEERR,PAGSM% ;(17)SECTION MUST EXIST BUT DOESN'T
ERCODE ILSERR,PAGIS% ;(20)ILLEGAL SECTION
ERCODE PALERR,PAGAL% ;(21)PAGE ALREADY LOCKED
ERCODE PAUERR,PAGAU% ;(22)PAGE ALREADY UNLOCKED (MUST BE CONTIGUOUS
;WITH PALERR)
ERCODE PNAERR,PAGNA% ;(23)PAGE NOT AVAILABLE (E.G. PHYS PAGE REQ'D
;TO BE LOCKED IS IN A LOCKED JOB, ETC.)
ERCODE IRLERR,PAGNR% ;(24) NO ROOM TO LOCK
ERCODE EVMERR,PAGNE% ;(25) INSUFFICIENT EVM AVAILABLE
ERCODE NFSERR,PAGNN% ;(26)NO FREE SEGMENT #S
ERCODE NCRERR,PAGNC% ;(27)NO FREE CORE AVAILABLE
ERCODE PWLERR,PAGWL% ;(30)PAGE ALREADY WRITE-LOCKED
ERCODE PWEERR,PAGWE% ;(31)PAGE ALREADY WRITE-ENABLED
SUBTTL SUBROUTINES
FIXDSK::PUSH P,J ;SAVE J
MOVE J,.USJOB ;J = THE CURRENT JOB'S JOB NUMBER
LDB T1,IMGIN## ;T1 = THE NUMBER OF PAGES THIS JOB HAS IN CORE
ADDI T1,(P2) ;THE NEW SIZE
PUSHJ P,XPANDP## ;CAUSE THE ADDITIONAL PAGES TO BE ALLOCATED ON
; THE NEXT SWAP-IN
HLRZS P2 ;HIGHEST VIRTUAL PAGE SEEN
;***FOR NOW****
TRZ P2,PG.BDY ;DON'T INCLUDE NZS FOR NOW
;***CROCK***
MOVE T1,(P) ;RESTORE SEGMENT OR JOB NUMBER
CAIG T1,JOBMAX## ;IS THIS A HIGH SEGMENT?
JRST FIXDS1
LDB T1,[POINT 9,R,8];CURRENT SIZE OF THE JOB
CAIG P2,(T1) ;HAS THE JOB INCREASED ITS VIRTUAL SIZE?
MOVEI P2,(T1) ;NO, ORIGIONAL SIZE
MOVE T1,(P) ;SEG NUMBER IN QUESTION
PUSHJ P,FNDHSB## ;GET HIGH SEG BLOCK FOR THIS SEG #
XCT NSS## ;NO SUCH SEGMENT
DPB P2,[PHSSLH+.HBHSZ(T1)]
DPB P2,[POINT 9,R,8];STORE NEW HIGHEST VIRTUAL ADDRESS IN SEGMENT
MOVE T1,(P) ;SEG # AGAIN
MOVEM R,JBTADR##(T1) ;STORE THAT
FIXDS1: POP P,J ;RESTORE SEG # TO J
PUSHJ P,SETVRT ;SET .UPVRT NON-0, UPDATE VMTOTL,VMCMAX
MOVE T1,.USJOB ;JOB NUMBER
MOVE R,JBTADR##(J) ;SETUP R FOR THE LOW SEGMENT FOR WSCHED
;OR FOR THE HIGH SEG FOR SEGCON/VIRCHK
AOS (P) ;GOOD RETURN
SKIPN .CPISF## ;ON CLOCK LEVEL (CORE COMMAND)?
CAILE J,JOBMAX## ;IF A HIGH SEG,
POPJ P, ;SEGCON WILL CALL WSCHED
IFN FTMP,<
PUSHJ P,REMMM## ;REMEMBER STATE OF THE MM RESOURCE
>
PJRST WSCHED## ;AND WAIT UNTIL JOB GOES OUT AND COMES BACK IN
FIXADR: TLNE P1,-1^!HLGPNO ;NZS PAGE SEEN?
JRST FIXMJ1 ;YES, NOTHING TO DO
HLRZ T1,P1 ;HIGHEST PAGE SEEN
CAIG J,JOBMAX## ;IS THIS A HIGH SEGMENT?
PUSHJ P,TPAHS ;PAGE IN THE HIGH SEGMENT?
JRST FIXMJ1 ;YES, NOTHING TO DO
PUSHJ P,JSTVRT ;SET .UPVRT NON-0, UPDATE VMCMAX
LDB T1,PCORSZ## ;LOW SEGMENT SIZE - 1
HLRZS P1 ;PUT HIGHEST VIRTUAL PAGE SEEN IN THE RIGHT HALF
CAIG P1,(T1) ;WAS A PAGE CREATED ABOVE THE HIGHEST WHICH EXISTED?
MOVE P1,T1 ;YES, NEW HIGHEST
DPB P1,PCORSZ## ;STORE NEW LOW SEGMENT SIZE
MOVE R,JBTADR##(J) ;GET SEGMENT SIZE,,SEGMENT ADDRESS
CAME J,.CPJOB##
PJRST FIXMJ1
FIXAD1: HLRZM R,.USHVA ;FOR ADDRESS CHECKING AT INTERRUPT LEVEL
CAME J,.CPJOB## ;ONLY FIX FOR CURRENT JOB (VIRCHK)
PJRST FIXMJ1 ;JUST CLEAR AM
MOVEM R,.CPADR## ;STORE FOR UUOCON
HLRZM R,.CPREL## ;AND FOR ADDRESS CHECKING
PJRST FIXMJ1 ;CLEAR THE A.M. AND RETURN TO THE USER
;ROUTINE TO INCREMENT .UPREL ON CREATE PAGES UUO
;ONLY ICUPR PRESERVES T1
ICUPRW: LSH T1,W2PLSH ;GET PAGE NUMBER INVOLVED
ICUPR: PUSHJ P,ISITS0 ;IS IT IN SECTION 0?
JRST INCNCR ;NO, JUST INCREMENT .USNCR
CAIG J,JOBMAX##
PUSHJ P,TPAHS
POPJ P, ;DON'T WORRY ABOUT IT
PUSH P,T1 ;PRESERVE ARG
ANDI T1,HLGPNO ;CLEAR SECTION # (PAGE RESOLVES TO S0 IF WE'RE HERE)
SKIPN T2,.USREL ;JOB VIRTUAL?
HLRZ T2,R ;NO, PHYSICAL SIZE EQUALS VIRTUAL SIZE
LSH T2,W2PLSH ;CONVERT TO HIGHEST PAGE NUMBER
CAIGE T1,1(T2) ;PAGE IN THE MIDDLE OF THE ADR SPACE?
JRST TPOPJ## ;YES, NOTHING TO DO
SKIPN .USREL ;NON-CONTIGUOUS CORE IMAGE?
HLRZM R,.USREL ;NO, STORE R SINCE IT MAY BE NOW
HLRZ T3,R ;HIGHEST VIRTUAL ADDRESS IN THIS JOB'S ADDRESS SPACE
LSH T3,W2PLSH ;CONVERT TO HIGHEST PAGE
CAIE T1,1(T2) ;NEXT PAGE NON-CONTIGUOUS?
JRST ICUPR4 ;YES, UPDATE UPMEM, SETUP R AND RETURN
PUSHJ P,GICUPH ;GET HIGH SEG
PUSH P,T2 ;SAVE START PAGE ON THE LIST
ADDI T1,1 ;NEXT PAGE
ICUPR1: CAILE T1,(T3) ;IS THIS PAGE ABOVE THE HIGHEST?
JRST ICUPR3 ;YES, ALL PAGES ARE CONTIGUOUS
PUSHJ P,GTPME ;GET THE CONTENTS OF THE MAP
JUMPE T2,ICUPR2 ;IF NEXT PAGE EXISTS,
CAML T1,(P) ; IF ABOVE HI SEG
JRST ICUPR2 ; WE'RE DONE. IF NOT ABOVE HI SEG,
SOS .USMEM ; IT WILL NOW BE INCLUDED IN .UPREL
; SO REMOVE IT FROM .UPMEM
AOJA T1,ICUPR1
ICUPR2: LSH T1,P2WLSH ;CONVERT FROM PAGE NUMBER TO ADDRESS
SOSA T1 ;ADDRESS - 1
ICUPR3: MOVEI T1,0 ;ALL PAGES ARE CONTIGUOUS
MOVEM T1,.USREL ;STORE NEW UPREL
POP P,(P) ;REMOVE START HI-SEG PAGE FROM LIST
SKIPA T1,(P) ;GET PAGE IN QUESTION
ICUPR4: AOS .USMEM ;A NON-CONTIGUOUS PAGE, COUNT UP THE NUMBER OF SAME
ANDI T1,HLGPNO ;JUST TO BE SURE
CAIL T1,(T3) ;CURRENT PAGE HIGHER THAN PREVIOUS HIGHEST?
DPB T1,[POINT 9,R,8];YES, MAKE R REFLECT THE HIGHER PAGE
MOVEM R,JBTADR##(J) ;NEW PROTECTION,,RELOCATION
SKIPN T1,.USREL
HLRZ T1,R
MOVEM T1,JOBREL##+.JDAT
PJRST TPOPJ## ;RESTORE VIRTUAL PAGE NUMBER AND RETURN
;SUBROUTINE FOR ABOVE
GICUPH: PUSH P,T1 ;SAVE T1
PUSH P,T3 ;T3
PUSH P,T4 ;AND T4
PUSH P,J ;J
MOVSI T3,-1 ;FIND LOWEST ADDRESSED SEG IN PCS
PUSHJ P,GTRSGN## ;GET LOWEST SEGMENT
JFCL ;NONE
JUMPL J,[LDB T2,[PSPOLH+.HBSPO(T1)] ;SPY SEG ORIGIN
JRST GICUP1]
HRRZS J
LDB T2,JBYHSO## ;ORIGIN OF THAT SEGMENT
GICUP1: POP P,J ;RESTORE J
POP P,T4 ;T4
POP P,T3 ;T3
JRST TPOPJ## ;AND RETURN
;ROUTINE TO DECREMENT .UPREL (PRESERVES T1)
DCUPR: PUSHJ P,ISITS0 ;IN SECTION 0?
JRST DECNCR ;JUST DECREMENT .USNCR
CAIG J,JOBMAX## ;A HIGH SEGMENT?
PUSHJ P,TPAHS ;MAKE SURE
POPJ P, ;YES, NOTHING TO DO
DCUPN1: SKIPN T2,.USREL ;ALREADY A VIRTUAL USER?
HLRZ T2,R ;LH(R) = HIGHEST VIRTUAL ADDRESS
ADDI T2,1
MOVE T3,T1 ;T3 = VIRTUAL PAGE NUMBER
LSH T3,P2WLSH ;CONVERT TO HIGHEST VIRTUAL ADDRESS
CAIG T2,(T3) ;LOWER THAN PREVIOUS HIGHEST (IGNORING SECTION,
;WE'RE REALLY IN S0)?
SOJA T2,DCUPR1 ;UPDATE UPREL AND R
MOVEI T4,PG.BDY(T3) ;TOP NEW ADR
ADDI T4,1
SUBM T2,T4 ;NUMBER OF PAGES ABOVE .UPREL
ASH T4,W2PLSH
ADDM T4,.USMEM ;INCREASE NO OF NON-CONTIG VIRTUAL PAGES
ADD T2,[-PAGSIZ]
PUSH P,T1 ;SAVE IN CASE WE NEED TO
CAMN T3,T2 ;ADJACENT TO HIGHEST PAGE?
SKIPE T2,.USREL ;YES, NO CHANGE
SOSA T2,T3 ;NEW UPREL = NEW ALLOCATION - 1
SOJA T3,DCUPR3 ;LEAVE UPREL = 0, DECREASE R
MOVEM T2,.USREL ;STORE NEW VALUE OF UPREL
SKIPN T2 ;IF NOW CONTIGUOUS
HLRZ T2,R ; USE JOB SIZE
MOVEM T2,.JDAT+JOBREL## ;UPDATE USERS JOBREL
JRST TPOPJ## ;AND RETURN
DCUPR1: SOS .USMEM ;DECREMENT COUNT OF NON-CONTIGUOUS PAGES
LDB T3,[POINT 9,R,8] ;CURRENT HIGHEST PAGE IN THE LOW SEGMENT
ANDI T1,HLGPNO ;CLEAR SECTION # (WE KNOW THIS REALLY RESOLVES
;TO S0)
CAIE T1,(T3) ;DECREASING SIZE?
POPJ P, ;NO GO AWAY
PUSH P,T1
LSH T2,W2PLSH ;CONVERT HIGEST CONTIGUOUS ADDRESS TO PAGE NUMBER
SUBI T3,1(T2) ;NUMBER OF PAGES ABOVE NEW HIGHEST PAGE
MOVE T4,T1
PUSHJ P,GMPTR
DCUPR2: MOVE T2,(T4) ;EACH MAP ENTRY IS A FULL WORD
TLNN T2,(PM.SPY!PM.NIA) ;SPY OR HIGH SEG PAGE?
JUMPN T2,DCUPR4 ; IF NON-ZERO, DON'T CHANGE UPREL
SUB R,[PAGSIZ,,0] ;THIS SLOT EMPTY - DECREMENT R
SOS T4 ;PREVIOUS MAP SLOT
SOJG T3,DCUPR2 ;LOOP OVER ALL PAGES POSSIBLY NOT IN THE MAP
SKIPE .USREL
HRL R,.USREL ;NEW HIGHEST ADDRESS
SETZM .USREL ;ALL PAGES IN THE LOW SEGMENT ARE CONTIGUOUS
JRST DCUPR4 ;STORE R AND RETURN
DCUPR3: HRL R,T3 ;NEW HIGHEST ADDRESS
HLRZM R,.JDAT+JOBREL##;STORE NEW HIGHEST ADDRESS IN LOW SEG FOR THE USER
DCUPR4: MOVEM R,JBTADR##(J) ;STORE NEW PROTECTION,,RELOCATION
POP P,T1 ;RESTORE T1
POPJ P, ;AND RETURN
INCNCR: AOSA .USNCR
DECNCR: SOS .USNCR
POPJ P,
;ROUTINE TO DECIDE WHETHER PAGE GIVEN IN T1 IS REALLY A SECTION 0 PAGE
;OR NOT. SKIP RETURN IF REALLY MAPPED TO SECTION 0, NON-SKIP OTHERWISE
ISITS0: TRNN T1,-1^!HLGPNO ;IF IT SAYS IT'S S0
JRST CPOPJ1## ;THEN IT PROBABLY IS
PUSH P,T1 ;SAVE THE ARG
HRRZS T1 ;CLEAR LH JUNK
LSH T1,P2SLSH ;GET SECTION #
ISITS1: MOVE T1,.UPMP+SECTAB(T1) ;GET SECTION MAP POINTER
TLNN T1,(<PM.ACD^!PM.DCD>B2) ;IS IT INDIRECT?
JRST TPOPJ## ;NO, CAN'T INDIRECT TO S0 THEN
LDB T1,[POINT 5,T1,17] ;GET SECTION NUMBER IT MAPS TO IF INDIRECT
JUMPN T1,ISITS1 ;CHECK IT
JRST TPOPJ1## ;IT IS S0 IF THIS IS
;ROUTINE TO DO THE OPPOSITE OF ISITS0
ISITNZ: TRNN T1,-1^!HLGPNO ;DOES IT CLAIM TO BE NZS?
POPJ P, ;NO, THEN IT ISN'T
PUSH P,T1 ;SAVE ARG
HRRZS T1 ;CLEAR LEFT HALF JUNK
LSH T1,P2SLSH ;GET SECTION # ONLY
ISITN1: MOVE T1,.UPMP+SECTAB(T1)
TLNN T1,(<PM.ACD^!PM.DCD>B2) ;INDIRECT?
JRST TPOPJ1## ;NO
LDB T1,[POINT 5,T1,17]
JUMPN T1,ISITN1 ;CHECK NEW MAPPING
JRST TPOPJ## ;IT IS IN S0
;ROUTINE TO ADD A DISK PAGE TO THE WORKING SET
;ENTER T1=VIRTUAL PAGE NUMBER OF THE PAGE
;INSDWE MAKES THE PAGE WRITE ENABLED, INSDWL MAKES THE PAGE WRITE LOCKED
;HIGH SEGMENT CALLS INSDWL
INSDWL: PUSHJ P,GTPME ;GET POINTER
TLO T2,(PM.CSH!PM.PUB) ;JUST SET AABTAB BIT
JRST INSDSX
INSDWE: PUSHJ P,GTPME ;GET MAP POINTER
TLO T2,(PM.WRT!PM.CSH!PM.PUB) ;SET AABTAB BIT
INSDSX: TDNN T2,[PM.ADR^!PM.ZER] ;IS IT AN ABZ PAGE?
TLNN T2,(PM.ZER) ;MAYBE
JRST INSDSY ;NOT ABZ
TDZ T2,[PM.ADR] ;MAKE ZERO SO SETIMT WON'T
TLO T2,(PM.AAB) ;CREATE PAGE WITH AAB ON
MOVEM T2,(T4) ;DO DEPOSIT NOW
PUSHJ P,INSMEM
JRST INSDSZ ;FINISH UP
INSDSY: TDNN T2,[PM.ADR] ;NOT ABZ, EXPANDING OR CREATING?
TLO T2,(PM.AAB) ;CREATING, SET AAB
MOVEM T2,(T4)
INSDSZ: PUSHJ P,WSBIT ;GET BIT AND INDEX INTO WORKING SET TABLE
IORM T2,(T4) ;ADD THE PAGE TO THE WORKING SET
POPJ P,
;ROUTINE TO INSERT A MONITOR PAGE INTO THE JOBS MAP
INSDMC: PUSHJ P,GTPME ;GET MAP POINTER
TLO T2,(PM.CSH!PM.WRT!PM.PUB) ;SET CACHE BIT
JRST INSDSX
INSDMU: PUSHJ P,GTPME
TLO T2,(PM.WRT!PM.PUB)
JRST INSDSX
;ROUTINE TO INSERT A PAGE IN THE MAP, WSBTAB AND AABTAB
;ENTER T1=VIRTUAL PAGE NUMBER, P1=PHYSICAL PAGE NUMBER
;EXIT T1=VIRTUAL PAGE NUMBER
;NOTE THAT INSPAG SHOULD ONLY BE CALLED FOR USER MODE PAGES
;AND INSMPC SHOULD NOT BE CALLED FOR NON-ZERO SECTION USER PAGES (SECTION
;NUMBER CONFUSION VS PAGE 1000-1030=FUNNY SPACE PAGES)
INSPAG: MOVE T3,.USJOB ;CURRENT JOB'S JOB NUMBER
.CREF IMGIN
AOS JBTIMI##(T3) ;INCREMENT NUMBER OF PAGES ALLOCATED IN PHYSICAL CORE
INSMPC: MOVE T3,P1
HRLI T3,(<PM.DCD>B2+PM.PUB+PM.WRT+PM.CSH+PM.AAB+PM.COR)
PUSHJ P,WSBIT ;GET BIT AND INDEX INTO WSBTAB
INSMPU: IORM T2,(T4) ;INDICATE THIS PAGE IS NOW IN THE WORKING SET
CAILE J,JOBMAX## ;HIGH SEGMENT?
TDZ T3,[PM.WRT] ;YES, WRITE LOCK THE PAGE
PUSHJ P,GTPME
MOVEM T3,(T4) ;STORE THE PHYSICAL PAGE NUMBER IN THE MAP
TLZ T2,(PM.NAD)
CAME T2,[PM.ZER]
POPJ P,
;HERE TO ADJUST VIRTAL, UPMEM FOR ALLOCATED BUT 0 PAGES
INSMEM: AOS VIRTAL## ;VIRTAL WAS ALREADY UPDATED
CAIG J,JOBMAX##
PUSHJ P,TPAHS
POPJ P,
PUSHJ P,ISITS0 ;IS IT A SECTION ZERO PAGE?
PJRST DECNCR ;NO, DECREMENT .USNCR
PUSH P,T1 ;SAVE THE ARG
ANDI T1,HLGPNO ;MAKE IT S0
SKIPN T2,.USREL
HLRZ T2,R ;IF THIS PAGE IS NON-CONTIGUOUS,
LSH T2,W2PLSH
CAILE T1,1(T2) ; ICUPR WILL AOS UPMEM
SOS .USMEM ; SO DECREMENT IT IN ANTICIPATION
JRST TPOPJ##
;ROUTINE TO ZERO A PAGE
;ENTER WITH T1=VIRTUAL PAGE NUMBER
;EXIT T1=VIRTUAL PAGE NUMBER
ZERPAG::PUSHJ P,GTPME ;GET MAP POINTER
ZPAGE: HRLI T2,(<PM.DCD>B2+PM.WRT+PM.PUB+PM.CSH)
IFN FTMP&FTKL10,<
PUSHJ P,MLSCSH## ;IS FREEOR CACHED
TLZ T2,(PM.CSH) ;MUST BE UNCACHED
>
MOVEM T2,.UPMP+.UMTMP
CLRPT .TEMP ;CLEAR THE A.M. SO NEW MAPPING WILL BE USED
MOVE T2,[.TEMP,,.TEMP+1]
SETZM .TEMP ;CLEAR THE FIRST WORD OF THE PAGE
BLT T2,.TEMP+PG.BDY ;ZERO THE PAGE
MOVEI T2,PAGSIZ ;NUMBER OF WORDS ZEROED
ADDM T2,CLRWRD## ;UPDATE AMOUNT OF TIME SPENT ZEROING CORE
POPJ P, ;AND RETURN
;SUBROUTINE TO ADJUST VMTOTL AND VMCMAX WHEN A PAGE
; IS BEING REMOVED
;PRESERVES ALL ACS BUT T1
DCVMT:: SKIPL T1,.USVRT ;IF HI SEG IS VIRTUAL,
TRNE T1,777000 ;OR LOW SEG IS VIRTUAL
SOSA VMTOTL## ;ADJUST NUMBERS
POPJ P, ;JUST ACCESS ALLOWED - RETURN
AOS VMCMAX## ;INCR. VMCMAX
POPJ P,
;SUBROUTINE TO RETURN THE CURRENT VIRTUAL SIZE
; OF A JOB IN T4
;PRESERVES T3
VJSIZ: PUSH P,T3 ;SAVE T3
PUSH P,J ;AND J
MOVE J,.USJOB ;CURRENT JOB'S JOB NUMBER
PUSHJ P,VMSIZE ;GET THE JOB'S VIRTUAL SIZE
MOVE T4,T1 ;LOW SEGMENT VIRTUAL SIZE
ADD T4,T2 ;ADD HIGH SEGMENT VIRTUAL SIZE
POP P,J ;RESTORE J
JRST T3POPJ## ;RESTORE T3 AND RETURN JOB'S VIRTUAL SIZE IN T4
;SUBROUTINE TO SEE IF PAGE UUO WILL CAUSE THE JOB TO BECOME TOO BIG
;ENTER WITH T3 AS AMOUNT OF INCREASE
;EXIT CPOPJ IF TOO BIG, CPOPJ1 IF OK
;EITHER EXIT T1 = CURRENT VIRTUAL SIZE OF THE JOB
;PRESERVES T2-T4
SZCHK: JUMPE T3,CPOPJ1## ;RETURN IF NOT INCREASING NUMBER OF PAGES IN CORE
PUSH P,T4
PUSHJ P,GSIZD ;SEE IF IT WILL FIT
SOS -1(P) ;NO, ERROR
JFCL ;YES, HE CAN GROW TO MPPL
MOVE T1,T4 ;CURRENT VIRTUAL SIZE
POP P,T4
PJRST CPOPJ1## ;SKIP RETURN
;SAME AS SZCHK, BUT ENTER WITH T3=INCREASE AND T4=# OF NON-EX SECT MAPS
;AND UP.BIG SET IN .USBTS IF USER ALREADY HAS SOME INDEPENDENT NZS
;SECTION (NORMAL CASE).
SZCHKX: JUMPE T4,SZCHK ;SAME AS SZCHK UNLESS EXTENDED
PUSH P,T3 ;SAVE T3
ADDI T3,(T4) ;AMOUNT OF INCREASE INCLUDING MAPS
.CREF UP.BIG
SKIPL .USBTS ;IS HE ALREADY EXTENDED?
AOS T3 ;INCLUDE .WSBNZ
PUSHJ P,SZCHK
JRST T3POPJ## ;RETURN
AOS -1(P)
JRST T3POPJ## ;GOOD RETURN
;SUBROUTINE TO WAIT FOR I/O TO STOP
;PRESERVES T1-T4
IOWAT: PUSHJ P,SAVT## ;SAVE T1-T4
IFN FTMP,<
PUSHJ P,REMMM## ;REMEMBER STATE OF THE MM
>
CAIE T2,PA.PME+PA.PCE ;CREATING A PAGE?
JRST IOWAIT## ;NO, WAIT FOR I/O TO STOP
JRST INWAT1 ;YES,,WAIT FOR INPUT TO STOP
;SUBROUTINE TO WAIT FOR INPUT TO STOP
;PRESERVES T1-T4
INWAT:: PUSHJ P,SAVT## ;BE NICE AND SAVE T1-T4
INWAT1: MOVEI T1,WAITI ;WAIT FOR INPUT TO STOP
JRST IOALL##
;SUBROUTINE TO WAIT FOR INPUT TO STOP ON A DEVICE
WAITI: TLNN S,IO ;INPUT
JRST WAIT1## ;YES, WAIT UNTIL IT COMPLETES
POPJ P, ;NO, DON'T WAIT
;SUBROUTINE TO REMEMBER THE STATE OF THE MM RESOURCE AND CALL IOWAIT
IOWATM:
IFN FTMP,<
PUSHJ P,REMMM## ;REMEMBER THE STATE OF THE MM
>
PJRST IOWAIT## ;WAIT FOR I/O, MM WILL RESTORED ON EXIT
;SUBROUTINE TO REMEMBER THE STAE OF THE MM RESOURCE AND CALL SCDCHK
IFN FTMP,<
SCDCKM: PUSHJ P,REMMM## ;REMEMBER
PJRST SCDCHK##
>
IFE FTMP,<
SCDCKM==SCDCHK##
>
;SUBROUTINE TO CHECK IF ADDING A HIGH SEGMENT TO A JOBS ADDRESSING
; SPACE WOULD CAUSE IT TO BE TO BIG
;EXITS CPOPJ IF IT WON'T FIT AT ALL,
;EXITS CPOPJ1 IF PAGING OUT THE LOW SEGMENT WILL MAKE IT FIT,
;EXITS CPOPJ2 IF IT WILL FIT PHYSICALLY
;RESPECTS T2
GSZSG:: LDB T1,IMGIN## ;SIZE OF THE HIGH SEGMENT
ADDI T1,UPMPSZ##+1 ;PLUS SIZE OF THE UPMP + PAGE 0
LSH T1,P2WLSH ;CONVERT TO WORDS
PUSH P,T2 ;SAVE T2
HRRZ T2,.PDCVL##(W) ;CURRENT PHYSICAL LIMIT/GUIDELINE
JUMPE T2,GSZSG1 ;JUMP IF THERE ISN'T ONE
TRZN T2,400000 ;LIMIT?
HRRZ T2,.PDMVL##(W) ;NO, GUIDELINE - USE MAX PHYSICAL LIMIT
JUMPE T2,GSZSG1 ;JUMP IF NONE
LSH T2,P2WLSH ;CONVERT TO WORDS
CAMG T1,T2 ;EXCEEDING LIMIT?
GSZSG1: CAMLE T1,CORMAX## ;OR BIGGER THAN CORMAX?
PJRST T2POPJ## ;YES, THEN IT WILL NEVER FIT
PUSHJ P,VJSIZ ;GET CURRENT VIRTUAL SIZE
PUSHJ P,SEGSIZ## ;AND SIZE OF NEW HISEG
ADD T4,T2 ;COMPUTE NEW VIRTUAL SIZE
HLRZ T2,.PDCVL##(W) ;GET CURRENT VM LIMIT
CAMGE T2,T4 ;WILL IT FIT?
JUMPN T2,T2POPJ## ;NO, ERROR TO EXCEED VM LIMIT
SETZB T2,T3 ;IT WILL FIT PHYSICALLY, SEE IF MUST GO VIRTUAL
PUSHJ P,GSIZD ;CHECK LIMITS
JRST [HRRZ T2,.PDMVL##(W) ;IGNORE WON'T FIT SINCE ALREADY CHECKED THAT
JUMPE T2,T2POPJ## ;WON'T FIT IF NOT MPPL
JRST .+1] ;OK
SKIPA T4,T1 ;T4 = VIRTUAL SIZE
JRST GSZSG4 ;IT WILL FIT PHYSICALLY
HLRZ T2,.PDCVL##(W) ;GET CURRENT VM LIMIT
JUMPE T2,T2POPJ## ;DOESN'T FIT IF NO VIRTUAL AND TOO BIG FOR PHYSICAL
MOVSI T1,(UP.GET) ;GETTING GET?
TDNE T1,.USBTS ;IF SO, THATS OK
JRST GSZSG4 ;SAY IT WILL FIT PHYSICALLY
PUSH P,J ;SAVE THE HIGH SEGMENT NUMBER
MOVE J,.CPJOB## ;JOB NUMBER
LDB T1,IMGIN## ;JOB'S CURRENT PHYSICAL SIZE
LSH T1,P2WLSH ;CONVERT TO WORDS
ADD T4,T1 ;COMPUTE NEW JOB SIZE
MOVE T2,JBTSTS##(J) ;JOB STATUS FOR THIS JOB
TLNE T2,JACCT ;IS IT A PRIVILEGED PROGRAM?
JRST GSZSG3 ;YES, DON'T GO VIRTUAL
TRNN T2,JS.RUU ;GETSEG?
PJRST GSZSG2 ;YES, DON'T CHECK FOR RUNNING A PRIV. PROG.
MOVE T1,.JDAT+SGANAM## ;NAME OF THE PROGRAM BEING RUN
TLNE F,SYSDEV ;BEING RUN FROM SYS?
PUSHJ P,PRVPG## ;YES, IS IT A PRIVILEDGED PROGRAM?
GSZSG2: SOS -2(P) ;NO, ONLY FITS IF VIRTUAL
GSZSG3: POP P,J ;RESTORE HIGH SEGMENT NUMBER
GSZSG4: POP P,T2 ;AND PRESERVED AC
JRST CPOPJ2## ;GIVE SINGLE OR DOUBLE SKIP RETURN
;SUBROUTINE TO TEST VARIOUS CORE LIMITS, ENTER GSIZI WITH T3=# PAGES OF INCREASE
;ENTER GSIZD WITH T3-T2=# PAGES OF INCREASE, EXIT CPOPJ IF WILL NEVER FIT PHYSICALLY
;EXIT CPOPJ1 IF .GT. CPPL, .LE. MPPL, EXIT CPOPJ2 IF .LE. CPPL
;RETURNS T1=NEW HIGHEST ADR, T4=NEW JOB SIZE, RESPECTS T2-T3
GSIZT:: PUSH P,T1 ;SAVE T1
PUSH P,T3 ;AND T3
MOVE T3,T4 ;SET ARGUMENT FOR GSIZI
PUSHJ P,GSIZI ;SEE IF IT WILL FIT
SOS -2(P) ;NOT AT ALL
CAIA ;ONLY VIRTUALLY
AOS -2(P) ;PHYSICALLY
POP P,T3 ;RESTORE PRESERVED AC
PJRST TPOPJ1## ;RESTORE T1 AND RETURN
GSIZI:: PUSH P,T2 ;SAVE T2
TDZA T2,T2 ;NO PAGES OF DECREASE
GSIZD:: PUSH P,T2 ;PRESERVE T2
PUSH P,T2 ;PUT ARGUMENT ON THE STACK
PUSHJ P,VJSIZ ;GET THE JOBS CURRENT VIRTUAL SIZE
PUSHJ P,SEGSIZ## ;PHYSICAL SIZE OF THE SEGMENT
CAIG J,JOBMAX## ;IS THIS A HIGH SEGMENT?
SUBI T2,UPMPSZ## ;NO, SUBTRACT OUT THE UPMP SIZE
SUB T2,(P) ;SUBTRACT OUT THE NUMBER OF PAGES OF DECREASE
POP P,(P) ;POP OFF JUNK
ADD T2,T3 ;NEW PHYSICAL SIZE OF THE SEGMENT
LSH T2,P2WLSH ;CONVERT TO WORDS
SOS T1,T2 ;HIGHEST ADDRESS REQUESTED IN T1
PUSH P,P1 ;SAVE P1
MOVSI P1,PHONLY ;ASK IF IT WILL FIT PHYSICALLY
PUSHJ P,SUMSEG## ;WILL BOTH SEGMENTS PLUS THE INCREASE FIT?
SKIPA P1,.PDCVL##(W) ;NO, GET THE CURRENT PHYSICAL LIMIT/GUIDELINE
AOJA T2,[HRRZ P1,.PDCVL##(W)
JUMPE P1,GSIZ2
LSH T2,W2PLSH
CAIGE T2,(P1)
JRST GSIZ2 ;NOT EXCEEDING GUIDELINE
LSH T2,P2WLSH
SOJA T2,.+1];EXCEEDING GUIDELINE, SEE IF IT WILL FIT ANYWAY
ADDI T2,UPMSZW## ;ACCOUNT FOR THE UPMP
TLO P1,PHONLY ;GET PHYSICAL LIMIT
EXCH J,.USJOB
LDB T1,NZSSCN## ;# OF MAPS
.CREF UP.BIG
SKIPL .USBTS
AOS T1
LSH T1,P2WLSH ;WORDS
ADDI T2,(T1)
PUSHJ P,CORBND## ; ..
EXCH J,.USJOB
CAMG T2,T1 ;GETTING TO BIG PHYSICALLY?
TRNE P1,400000 ;NO, GUIDELINE OR LIMIT?
JRST GSIZ1 ;LIMIT, CAN'T HELP HIM
MOVE P1,.PDMVL##(W) ;GET THE MAXIMUM PHYSICAL LIMIT
LSH T2,W2PLSH ;CONVERT TO WORDS
TRNE P1,-1 ;WAS MPPL SET?
CAILE T2,-1(P1) ;YES, TRYING TO EXCEED THAT?
GSIZ1: SOS -2(P) ;YES, WON'T FIT
JRST GSIZ3 ;RESTORE ACS AND NON-SKIP RETURN
GSIZ2: AOS -2(P) ;HERE IF CAN FIT PHYSICALLY
GSIZ3: POP P,P1 ;RESTORE P1
PJRST T2POJ1## ;RESTORE T2 AND RETURN
;SUBROUTINE TO GET THE MAP ENTRY FOR THE VIRTUAL PAGE SPECIFIED BY
; THE CONTENTS OF T1
;CALLING SEQUENCE:
;
; MOVE T1,VIRTUAL PAGE NUMBER
; PUSHJ P,GTMPE
;RETURN CPOPJ, T2 = CONTENTS OF THE MAP, T4= MAP SLOT POINTR
;T1,T3 PRESERVED
GTPME:: HRRZ T4,T1 ;ARGUMENT TO GMPTR
PUSHJ P,GMPTR ;GET A BYTE POINTER TO THE MAP SLOT
MOVE T2,(T4) ;CONTENTS OF THE SLOT
POPJ P, ;RETURN
;SUBROUTINE TO GET THE MAP ENTRY FOR A PAGE
;ENTER T4=VIRTUAL PAGE NUMBER
;EXIT T4=CONTENTS OF MAP SLOT
;T1-T3 PRESERVED
GTPM4:: PUSHJ P,GMPTR ;GET POINTER TO MAP SLOT
MOVE T4,(T4) ;GET MAP CONTENTS
POPJ P, ;AND RETURN
;SUBROUTINE TO SEE IF THE VIRTUAL PAGE NUMBER SPECIFIED BY THE CONTENTS OF
; T1 IS A LEGAL VIRTUAL PAGE NUMBER
;PRESERVES T1
LGLPG:: TLNE T1,377777 ;EXTRA BITS ON IN LH
JRST ILPERR ;YES, ILLEGAL PAGE NUMBER
LGLPR: HRRZ T2,T1 ;PAGE NUMBER (HIGH ORDER BIT MAY BE ON IN T1)
JUMPE T2,ILPERR ;REAL PAGE 0 IS ILLEGAL
CAILE T2,HLGPGS ;LESS THAN HIGHEST LEGAL PAGE NUMBER?
JRST ILPERR ;ILLEGAL PAGE
TRNN T2,HLGPNO ;COULD IT BE PAGE 0 IN ANOTHER FORM?
PUSHJ P,ISITS0 ;MAYBE, IS REALLY IN S0?
AOS (P) ;NOT IN S0 OR NOT P0
POPJ P, ;P0
;SUBROUTINE TO TEST TO SEE IF THE VIRTUAL PAGE SPECIFIED BY THE CONTENTS
; OF T1 IS IN THE WORKING SET, I.E., IN CORE, RETURNS CPOPJ IF NOT, CPOPJ1
; IF SO, T2 = MASK TO SET OR CLEAR THE BIT, T4 IS THE INDEX INTO THE
; WORKING SET BIT TABLE
;PRESERVES T1,T3
TSWST:: PUSH P,T1
TSWST1: HRRZS T1 ;CLEAR JUNK
MOVEI T4,MXSECN_S2PLSH ;GET SECTION # SPECIFIED
ANDI T4,(T1)
LSH T4,P2SLSH ;MAKE IT A SECTION INDEX
CAILE T1,HLGPGS ;FUNNY SPACE?
TDZA T4,T4 ;YES, S0
TRZA T1,-1^!HLGPNO ;CLEAR SECTION #
MOVEI T1,HLGPNO+1-<.MCFV/PAGSIZ>(T1)
PUSHJ P,RSECT4 ;GET REAL SECTION # IN T4
JFCL ;WORRY ABOUT THIS LATER
SKIPN T4 ;IF NOT S0, MULTIPLY
SKIPA T4,[WSBTAB-.WSBNZ+WSBTBL]
IMULI T4,WSBTBL
ADDI T4,.WSBNZ-WSBTBL
IDIVI T1,^D36 ;WORD NUMBER IN T1, BIT POSITION IN T2
MOVE T2,BITTBL##(T2) ;GET POSITIONED BIT FROM BIT NUMBER
.CREF UP.BIG
CAIG T4,.UPMP ;IS IT IN THE S0 WSBTAB (WHICH ALWAYS EXISTS)
SKIPGE .USBTS ;NO, DOES NZS WSBTAB EXIST (UP.BIG)
TLOA T4,400000+T1 ;IFIW (WSBTAB EXISTS)
TLOA T4,400000+T1 ;IFIW (.WSBNZ DOESN'T)
TDNN T2,@T4 ;IS THE BIT ON IN WSBTAB (PAGE IN CORE)?
SOS -1(P) ;NO, NON-SKIP RETURN
MOVEI T4,@T4 ;RETURN WORD NUMBER IN T4
PJRST TPOPJ1## ;RESTORE VIRTUAL PAGE NUMBER AND RETURN
;ROUTINE TO GET THE "REAL" (I.E. INDEPENDENT) SECTION # IN T4.
;RETURNS CPOPJ1 WITH "REAL" SECTION NUMBER IN T4,
;CPOPJ IF SECTION NON-EXISTENT
;STARTS WITH C(T4) AND IS ASSUMED TO BE
;ZERO IF IT IS 0 OR NEGATIVE. USES T2.
RSECT4::JUMPG T4,RSCT4A ;GO IF SECTION NON-ZERO
SETZ T4, ;HE REALLY WANTS S0
JRST CPOPJ1## ;GOOD RETURN
RSCT4A: CAIG T4,MXSECN ;DON'T FALL OFF THE END
RSCT4B: SKIPN T2,.UPMP+SECTAB(T4) ;GET SECTION POINTER
POPJ P, ;RETURN SAYING NON-EX SCN
TLNN T2,(<PM.ACD^!PM.DCD>B2) ;IS THIS AN INDEPENDENT SECTION?
JRST CPOPJ1## ;YES
LDB T4,[POINT 5,T2,17] ;NOTE THAT 540 AND 37 DON'T
;OVERLAP ANY NON-ZERO BITS
JUMPN T4,RSCT4B ;AND CHECK IT OUT
JRST CPOPJ1## ;RETURN IF S0
;SUBROUTINE TO GET BIT, INDEX FOR WSBTAB
;ENTER AND EXIT WITH ACS LIKE TSWST
;RETURNS NON-SKIP IF PAGE ISNT IN WORKING SET, HALTS IF IT IS
;PRESERVES T1,T3
WSBIT: PUSHJ P,TSWST ;IS THE PAGE IN THE WORKING SET?
POPJ P, ;NO, RETURN
STOPCD CPOPJ##,STOP,PIN, ;++PAGE IN WORKING SET
;SUBROUTINE TO TEST IF BIT ON IN AABTAB
;ENTER WITH T4=MAP POINTER (CORRECT .UPMAP ASSUMED!)
;ENTER AT TSAATC WITH MAP CONTENTS ALREADY IN T4
;EXIT CPOPJ1 IF BIT IS ON, CPOPJ OTHERWISE
;PRESERVES ALL ACS
TSAAT: PUSH P,T4 ;SAVE BIT
MOVE T4,(T4) ;GET MAP CONTENTS
TLNE T4,(PM.AAB) ;ACCESS ALLOWED?
AOS -1(P) ;YES, SKIP RETURN
PJRST T4POPJ## ;RESTORE T1 AND RETURN
;SUBROUTINE TO SEE IF PAGE SPECIFIED BY T1 IS A SPY PAGE. ENTER WITH PAGE #
;IN T1 (PRESERVED). EXIT WITH MAP CONTENTS IN T2 AND BYTE POINTER IN T4.
;ASSUMES CORRECT MAP IN .UPMAP. EXIT CPOPJ1 IF THIS IS A SPY PAGE, CPOPJ
;OTHERWISE
IFN FTPEEKSPY,<
TSSPT:: SE1ENT
PUSHJ P,GTPME ;GET CONTENTS
TLNE T2,(PM.SPY) ;SPY PAGE?
AOS (P)
POPJ P,
>
;SUBROUTINE TO TEST TO SEE IF USER IS IN HIS PAGE FAULT HANDLER
;CALL WITH:
; T2 = PC
; PUSHJ P,INPFH
; RETURN HERE IF IN PFH
; RETURN HERE IF NOT
;
; RESPECTS ALL AC'S EXCEPT T3
;
INPFH:: HRRZ T3,.JDAT+.JBPFH## ;GET START OF PFH
SKIPE .JDAT+.JBPFH## ;ANY PAGE FAULT HANDLER AT ALL
CAILE T3,(T2) ;ABOVE START?
JRST CPOPJ1## ;NO--NOT IN PFH
HLRZ T3,.JDAT+.JBPFH## ;GET END OF PFH
CAIGE T3,(T2) ;ABOVE END?
JRST CPOPJ1## ;YES--NOT IN PFH
POPJ P,0 ;IN PFH
;SUBROUTINE TO DESTROY PAGES. ENTER WITH VIRTUAL PAGE NUMBER OF PAGE
; TO BE DELETED IN T1, PAGE MUST EXIST
; GET PHYSICAL PAGE NUMBER, ZERO MAP ENTRY, FIND PHYSICAL PAGE NUMBER
; IN PAGTAB, LINK PAGTAB AROUND IT, UPDATE CORTAL, BIGHOL
DLTPAG: PUSHJ P,DLTSP ;DELETE SPY PAGE?
POPJ P, ;YES
IFN FTMP,<
PUSHJ P,MMOWN## ;OWN THE MM?
PUSHJ P,MMDIE## ;NO, STOP
>
PUSHJ P,RMVPAG ;REMOVE THE PAGE FROM THE MAP
JRST DLTPGE ;GIVE BACK THE SWAPPING SPACE
;HERE WITH T2=PAGE TO BE GIVEN BACK
DLTPGC::SE1ENT ;MUST BE IN SECTION 1 TO ADDRESS PAGTAB
HRRZ T1,T2
SSX T2,MS.MEM
SETZM PAGTAB(T2) ;ONLY ONE PAGE TO RETURN (CLEAR BITS AS WELL)
HLLZS PT2TAB(T2) ;SO GVPAGS DOESN'T GET CONFUSED
AOS VIRTAL## ;AND THE AMOUNT OF SWAPPING SPACE AVAILABLE
PJRST GVPAGS## ;RETURN THE PAGE
;HERE IF MAPPED PAGE IS ON DISK
DLTPGE: JUMPE T2,CPOPJ## ;GO IF PAGE WAS ON THE OUT QUEUE
MOVSI T1,(UP.CTX) ;IF THIS IS FOR A JOB DOING A PUSH,
TDNE T1,.USBTS ; (TEST)
POPJ P, ;YES, DON'T GIVE AWAY HIS VIRTUAL PAGES (OR BAC)
;NO, FALL INTO DLTPGD
;HERE IF PAGE IS ON DISK
DLTPGD::AOS VIRTAL## ;INCREMENT THE AMOUNT OF SWAPPING SPACE AVAILABLE
TLZ T2,(PM.NAD)
DLTPGF: CAMN T2,[PM.ZER]
POPJ P, ;YES, ALL DONE
DLTDSP: MOVE T1,T2 ;ARGUMENT TO FXSAT
MOVEI U,1 ;NUMBER OF PAGES TO RETURN
PJRST FXSAT1## ;GIVE BACK THE SWAPPING SPACE
;SUBROUTINE TO REMOVE PAGE FROM JOBS ADDRESSING SPACE
;ENTER T1= VIRTUAL PAGE TO BE REMOVED
;EXIT CPOPJ, T2=DSK ADDRESS IF PAGE ON DSK
; OR EXIT CPOPJ1, T2= PHYSICAL PAGE NUMBER IF PAGE IN CORE
;IF CALLED AT RMVPGI AND PAGE WAS ON A QUEUE, T2 WILL IN CLUDE OIQ!SSP
;(IF IN QUEUES) OR T3 WILL CONTAIN QUEUE HEADER AND T4 PHYS PAGE (OUT OR IP)
RMVPGI: PUSHJ P,SAVE1## ;SAVE P1
SJSP P1,RMVPG0 ;SET NON-ZERO AS A FLAG
RMVPAG::PUSHJ P,SAVE1## ;SAVE P1
SETZ P1, ;SET FLAG
RMVPG0: PUSHJ P,GTPME ;GET THE CONTENTS OF THE MAP SLOT
SETZM (T4) ;ZERO THE MAP SLOT SINCE PAGE NO LONGER EXISTS
PUSH P,T2 ;SAVE THE PREVIOUS MAP CONTENTS
PUSHJ P,DCUPR ;DECREMENT UPREL
MOVE T3,(P) ;GET PREVIOUS MAP-SLOT CONTENTS
TLNN T3,(PM.AAB) ;ACCESS ALLOWED ON?
TDNN T3,[PM.ADR^!PM.ZER]
JRST RMVPG1
TLNN T3,(PM.AAB)
SOS .USANA ;YES, DECR COUNT
RMVPG1: TLNE T3,(PM.LOK) ;IS THIS PAGE LOCKED?
JRST RMVPG7 ;YES, HANDLE DIFFERENTLY
LDB T2,[POINT PM.SAD,T3,<^L<PM.ADR>+PM.SAD-1>]
TLNE T3,(PM.OIQ) ;PAGE ON THE "IN" QUEUE?
JRST RMVPG5 ;YES
MOVEM T2,(P) ;NO, JUST RETURN DSK ADDR/PAGE #
PUSH P,T3 ;SAVE MAP ENTRY
TLNN T3,(PM.COR) ;IF PAGE IS IN CORE, IT ISN'T ON A QUEUE
PUSHJ P,ONPOQ ;PAGE ON "IP" OR "OUT" QUEUE?
JRST [POP P,T3 ;RESTORE PAGE MAP ENTRY
JRST RMVPG2] ;NO, JUST A GARDEN VARITY PAGE
POP P,(P) ;POP OFF JUNK
JUMPN P1,T2POPJ## ;DON'T CHANGE QUEUE IF CALLED FROM IPCRMV
SSX T4,MS.MEM ;MEMTAB SECTION
CAIE T3,PAGIPQ## ;ON THE IN PROGRESS QUEUE?
JRST [MOVSI T3,(UP.CTX) ;JOB DOING A PUSH?
TDNN T3,.USBTS ;IF NOT,
SETZM MEMTAB(T4) ;DON'T BOTHER TO PUT PHYSICAL PAGE ON
JRST T2POPJ##] ; FREE CORE LIST, BUT DON'T FIND IN "OUT" QUEUE
MOVSI T2,(MT.GPB) ;GIVE BACK DISK SPACE WHEN I/O COMPLETES
MOVSI T3,(UP.CTX) ;JOB DOING A PUSH?
TDNN T3,.USBTS ;IF SO,
IORM T2,MEMTAB(T4)
SETZM (P) ;INDICATE NO PAGE TO GIVE BACK
JRST T2POPJ## ;AND GIVE PAGE ON DISK RETURN
;HERE WITH T3=CONTENTS OF THE MAP (SIGN BIT GUARENTEED OFF)
RMVPG2: PUSHJ P,TSWST ;WAS THE PAGE IN THE WORKING SET?
TLOA T3,400000 ;NO, REMEMBER THAT
.CREF IMGIN
SOS JBTIMI##(J) ;YES, DECREMENT THE COUNT OF THE NUMBER OF
; PAGES IN CORE
ANDCAM T2,(T4) ;CLEAR THE BIT IN THE WORKING SET TABLE
POP P,T2
SKIPL T3 ;PAGE IN THE WORKING SET?
TLNE T3,(PM.WRT) ;YES, IS IT ALSO WRITE LOCKED?
CAIA ;NO
PUSHJ P,[SKIPN .USWLP ;NO DISK SPACE TO GIVE BACK IF NO WL PAGES
POPJ P, ;JUST GO AWAY
PUSHJ P,SAVT## ;YES, IT HAS BOTH A DISK AND IN-CORE COPY
MOVSI T1,(UP.CTX)
TDNE T1,.USBTS
POPJ P, ;IF PUSH, DON'T DO ANYTHING
PJRST RTNDPG];SO RETURN DISK SPACE
TLZE T3,400000 ;PAGE ON DISK?
POPJ P, ;YES, NON-SKIP RETURN
SE1ENT ;GET TO SECTION 1
SKIPE T1 ;DON'T LINK PAST PAGE ZERO
PUSHJ P,LKPSF ;LINK PAST THE PAGE IN PAGTAB
PUSH P,T2 ;SAVE THE PHYSICAL PAGE NUMBER
SSX T2,MS.MEM ;PAGTAB SECTION
HLLZS PAGTAB(T2) ;INDICATE LAST PAGE ALLOCATED
RMVPG3: PUSHJ P,DECHJ ;DECREMENT THE NUMBER OF HIGH SEGMENT PAGES
; IN CORE IF THIS IS A HIGH SEGMENT PAGE
RMVPG4: MOVEI T2,777 ;IF REMOVED ALL NON-ACCESSABLE PAGES,
SKIPE .USANA
PJRST T2POJ1## ;DONE
ANDCAM T2,.USVRT ; CLEAR THAT PORTION OF .UPVRT
PJRST T2POJ1## ;RESTORE T2 AND GIVE PAGE-IN-CORE RETURN
RMVPG5: JUMPN P1,RMVPG4 ;RETURN WITH BITS NOW IF FROM IPCRMV
MOVEM T2,(P) ;NOT AFTER THIS IT'S NOT
TLNE T3,(PM.SSP)
SKIPA T3,[PAGSNQ##]
MOVEI T3,PAGINQ##
PUSHJ P,RMVPFQ ;REMOVE IT FROM THE "IN" QUEUE
JRST RMVPG4 ;FIX COUNTS AND RETURN
RMVPG7: POP P,T2 ;RESTORE PAGE #
TLZ T2,(PM.NAD) ;KEEP ONLY PAGE
AOS (P) ;GIVE IN-CORE RETURN
PJRST RMVLPG ;REMOVE PAGE AND RETURN
;SUBROUTINE TO RETURN DISK SPACE WHEN A PAGE IS WRITE ENABLED
;ENTER WITH T2=PHYSICAL PAGE NUMBER, ALWAYS RETURNS CPOPJ
RTNDPG: SKIPN .USWLC ;ELSE DECREMENT PROPER COUNT
SOSA .USWLP ;MUST BE A MONITOR PAGE
SOS .USWLC
RTNFS0::TLZ T2,(PM.NAD) ;CLEAR ACCESS BITS
SSX T2,MS.MEM ;INDEX INTO MEMTAB
LDB T1,[POINT MT.SAD,MEMTAB(T2),<^L<MT.DAD>+MT.SAD-1>] ;DISK ADDRESS
SETZM MEMTAB(T2) ;DON'T FIND IT ON "OU" QUEUE
PUSH P,U ;DON'T CLOBBER U, LOTS! OF PEOPLE DEPEND ON IT
SKIPE T2,T1 ;ARGUMENT FOR DLTPGD
PUSHJ P,DLTPGF ;RETURN SWAPPING SPACE
JRST UPOPJ## ;RESTORE U AND RETURN
;SUBROUTINE TO RETURN SWAPPING SPACE ALLOCATED TO PAGE 0, FUNNY SPACE,
; AND SECTION MAPS FOR A JOB WHOSE CORE IMAGE CONTAINS WRITE LOCKED PAGES
RTNNWL::PUSHJ P,SVEUB## ;JOB'S NOT ADDRESSABLE HERE
SKIPN .USWLP ;JOB HAVE ANY WRITE LOCKED PAGES?
POPJ P, ;NO, NOTHING TO RETURN
SE1ENT ;MUST BE IN SECTION 1 TO REFERENCE PAGTAB/MEMTAB
MOVEI T1,0 ;PAGE 0 IS ALWAYS WRITE ENABLED
PUSHJ P,GTPME ; SO GET PHYSICAL PAGE NUMBER
PUSHJ P,RTNFS0 ; AND RETURN ITS SWAPPING SPACE
;THE FOLLOWING CODE ASSUMES FUNNY SPACE STARTS AT HLGPNO+1, GIVE BACK
; FUNNY SPACE PAGES AND SECTION MAPS
;SETUP TO START SCANNING WSBTAB WHERE FUNNY SPACE BEGINS
SKIPA M,.+1
SETZ HLGPNO
MOVEI T1,^D36-<<HLGPNO+1>-^D36*<<HLGPNO+1>/^D36>>
MOVEI T2,WSBTAB+<HLGPNO+1>/^D36
MOVE T3,(T2)
LSH T3,<<HLGPNO+1>-^D36*<<HLGPNO+1>/^D36>>
PUSHJ P,SAVE1## ;NEED AN EXTRA AC
RTNNW1: PUSHJ P,NXTWS3 ;GET NEXT PAGE OF FUNNY SPACE
HRRZ P1,M ;VIRTUAL PAGE NUMBER
CAIE P1,.UPMVP/PAGSIZ ;UPT?
CAIN P1,.UPMVP/PAGSIZ-1 ; OR MAP?
JRST RTNNW1 ; YES, ALREADY GIVEN BACK ON UPT AND MAP SWAP IN
CAILE P1,.UPMVP/PAGSIZ+MXSECN ;DONE?
POPJ P, ;YES, RETURN
PUSHJ P,[PUSHJ P,SAVT## ;PRESERVE T ACS FOR NEXT CALL TO NXTWS3
MOVE T2,(T4) ;PHYSICAL PAGE NUMBER
PJRST RTNFS0];RETURN SWAPPING SPACE
JRST RTNNW1 ;NEXT PAGE
;SUBROUTINE TO REMOVE A PAGE FROM A QUEUE
;CALL:
; MOVE T2,PHYSICAL PAGE NUMBER
; MOVEI T3,ADDRESS OF QUEUE HEADER
; PUSHJ P,RMVPFQ ;REMOVE THE PAGE FROM THE QUEUE
; ALWAYS RETURN HERE
;STOPCDS IF PAGE ISN'T ON THE QUEUE
;REMPFQ WILL REMOVE A PAGE FROM A GENERALIZED QUEUE WHOSE ADDRESS
;IS IN T3 (USED BY LOKPGS CODE)
RMVPFQ: SE1ENT ;ENTER SECTION 1
SOSL 1(T3) ;DECREMENT COUNT OF PAGES ON QUEUE
REMPFQ: SKIPN T4,(T3) ;ANY PAGES ON THE QUEUE
STOPCD CPOPJ##,DEBUG,PQW, ;++PAGE QUEUE WRONG
CAIE T2,(T4) ;FIRST ELEMENT IN THE QUEUE?
JRST LKPSF ;NO, JUST LINK AROUND THE PAGE
SSX T4,MS.MEM ;PAGTAB SECTION
MOVE T4,PAGTAB(T4) ;SUCCESSOR TO PAGE BEING REMOVED
HRRM T4,(T3) ;STORE AS NEW FIRST ELEMENT IN QUEUE
SSX T4,MS.MEM ;SECTION AGAIN
HLLZS PT2TAB(T4)
HLLZS @[IW MS.MEM,PAGTAB(T2)] ;CLEAR LINK IN THIS PAGE
HLLZS @[IW MS.MEM,PT2TAB(T2)] ;AND BACK LINK
POPJ P, ;AND RETURN
;SUBROUTINE TO ADD A PAGE TO A QUEUE
;CALL:
; MOVE T1,PHYSICAL PAGE NUMBER
; MOVEI T3,ADDRESS OF QUEUE HEADER
; PUSHJ P,ADDPTQ ;ADD THE PAGE TO THE QUEUE
; ALWAYS RETURN HERE
ADDPTQ: EXCH T1,(T3) ;NEW FIRST PAGE ON THE QUEUE, GET OLD FIRST
AOS 1(T3) ;ONE MORE PAGE ON THE QUEUE
MOVE T3,(T3) ;PREVIOUS FIRST PAGE
SSX T3,MS.MEM ;PAGTAB SECTION
MOVEM T1,PAGTAB(T3) ;LINK IT INTO CHAIN
HLLZS PT2TAB(T3) ;WE HAVE NO PREVIOUS
SSX T1,MS.MEM ;PAGTAB SECTION
TRNE T1,-1 ;IF NOT LAST,
HRRM T3,PT2TAB(T1) ;SET BACK LINK
POPJ P, ;RETURN
;SUBROUTINE TO LINK PAGTAB AROUND THE PAGE SPECIFIED BY THE CONTENTS OF T2
;CALLING SEQUENCE:
; MOVE T2,PAGE TO BE LINKED PAST
; PUSHJ P,LKPSP
;RETURNS CPOPJ, T3 = PREDECESSOR TO PAGE LINKED AROUND
;PRESERVES T1
REPEAT 0,<
LKPSP:: LDB T4,JBYLSA## ;FIRST PAGE OF THE LOW SEGMENT
SE1ENT ;SETION 1 TO ADDRESS PAGTAB
LNKPS1: MOVE T3,T4 ;SAVE PREVIOUS PAGE IN T3
SSX T3,MS.MEM ;PAGTAB SECTION
SKIPG T4,PAGTAB(T3) ;NEXT PAGE OF THE SEGMENT
STOPCD .+1,DEBUG,FIP, ;++FREE-PAGE IN USE
CAIE T2,(T4) ;IS THIS THE PAGE TO BE LINKED AROUND?
JRST LNKPS1 ;NO, TRY THE NEXT PAGE
SSX T4,MS.MEM ;PAGTAB SECTION
SKIPGE T4,PAGTAB(T4) ;GET THE NEXT PAGE
STOPCD CPOPJ##,DEBUG,PIF, ;++PAGE IS FREE
MOVEM T4,PAGTAB(T3) ;LINK AROUND THE PAGE
HRRZS T3 ;CLEAR SECTION NUMBER
HLLZS @[IW MS.MEM,PAGTAB(T2)] ;CLEAR LINK IN THIS PAGE
HLLZS @[IW MS.MEM,PT2TAB(T2)]
TRNN T4,-1 ;ANY NEXT PAGE?
POPJ P, ;NO
SSX T4,MS.MEM ;SECTION AGAIN
HRRZM T3,PT2TAB(T4) ;BACK LINK
POPJ P, ;AND RETURN
> ;END REPEAT 0
LKPSF:: SE1ENT ;SECTION 1
HRRZ T4,T2 ;PAGE TO BE LINKED PAST
SSX T4,MS.MEM ;SECTION # FOR MEMTAB
HRRZ T3,PT2TAB(T4)
SSX T3,MS.MEM ;FOR IT TOO
SKIPGE T4,PAGTAB(T4) ;NEXT
STOPCD CPOPJ##,DEBUG,PIF, ;++PAGE IS FREE
MOVEM T4,PAGTAB(T3) ;LINK FORWARD
HRRZS T3
HLLZS @[IW MS.MEM,PAGTAB(T2)] ;CLEAR LINK IN THIS PAGE
HLLZS @[IW MS.MEM,PT2TAB(T2)]
TRNN T4,-1 ;ANY NEXT PAGE?
POPJ P, ;NO, NOTHING MORE TO DO
SSX T4,MS.MEM
HRRM T3,PT2TAB(T4)
POPJ P,
;SUBROUTINE TO MOVE PAGES FROM THE "OUT" QUEUE CHAIN TO THE FREE CORE CHAIN
;CALLING SEQUENCE:
; MOVE T3,AMOUNT NEEDED
; PUSHJ P,FRPCR
; RETURNS HERE IF NOT ENOUGH CAN BE MADE AVAILABLE
; RETURNS HERE - HAVE BEEN MADE AVAILABLE, BIGHOL WILL SATISFY REQUEST
;PRESERVES ALL ACS
FLSOPQ::SE1ENT ;ENTER SECTION 1
SOS (P) ;UNDO SKIP RETURN
JRST FRPCR1 ;PUT ALL PAGES ON THE "OUT" QUEUE ON FREE CORE LIST
FRPCR:: PUSHJ P,SAVT## ;THE SWAPPER IS PARTICULAR ABOUT ACS
SUB T3,BIGHOL## ;NUMBER OF PAGES THAT WEREN'T AVAILABLE
CAMLE T3,PAGOUC## ;THAT MANY AVAILABLE ON THE "OUT" QUEUE?
JRST [MOVE T3,-3(P) ;MAY STILL BE ABLE TO MAKE CORE AVAILABLE
SUB T3,CORTAL##; BY DELETING DORMANT SEGMENTS
CAMLE T3,PAGOUQ## ;CAN BE DONE?
POPJ P, ;NO, HAVE TO SWAP TO MAKE CORE AVAILABLE
SOS (P) ;YES, CORE IS AVAILABLE IF DORMANT SEGMENTS
SE1ENT ; ARE DELETED AND THE QUEUE IS FLUSHED - NON-SKIP
JRST FRPCR1] ; RETURN TO SEGCON SO IT WILL DELETE DORMANT SEGMENTS
SE1ENT ;MUST BE IN SECTION 1 TO FOLLOW PAGTAB
MOVE T2,PAGOUC## ;NUMBER OF PAGES ON "OUT" QUEUE
MOVNS T3 ;MINUS NUMBER OF PAGES NEEDED FROM THE QUEUE
ADD T2,T3 ;NUMBER OF PAGES TO SKIP AT THE BEGINING OF THE QUEUE
ADDB T3,PAGOUC## ;DECREASE NUMBER OF PAGES ON QUEUE BY THAT AMOUNT
JUMPN T3,FRPCR2 ;GO IF QUEUE ISN'T EMPTY
FRPCR1: SETZB T1,PAGOUC## ;ZERO COUNT (CONVENIENT FOR FLSOPQ)
EXCH T1,PAGOUQ## ;FIRST PAGE ON QUEUE, QUEUE IS NOW EMPTY
JUMPE T1,CPOPJ1## ;EXIT IF EMPTY (FLSOPQ)
JRST FRPCR3 ;RETURN ALL OF THE PAGES TO THE FREE CORE LIST
FRPCR2: SOS T2 ;FIND THE PREDECESSOR
MOVE T3,PAGOUQ## ;FIRST PAGE ON THE "OUT" QUEUE
PUSHJ P,SNPAG1## ;SKIP THAT NUMBER OF PAGES
SSX T1,MS.MEM ;PAGTAB SECTION
HLLZS PAGTAB(T1) ;NEW END OF QUEUE
MOVE T1,T3 ;PAGE TO START GIVING BACK AT
FRPCR3: PUSHJ P,GVPAGS## ;RETURN THE PAGES TO THE FREE CORE LIST
JRST CPOPJ1## ;AND GIVE SUCCESS RETURN
;SUBROUTINE TO TEST IF THE PAGE SPECIFIED BY THE CONTENTS OF T1
; IS CONTAINED IN A SHARABLE HIGH SEGMENT OR A SPY SEGMENT
;CALLING SEQUENCE:
; MOVE T1,PAGE NUMBER TO BE TESTED
; MOVE J,JOB NUMBER
; PUSHJ P,TPSHS
;RETURNS CPOPJ IF THE PAGE IS CONTAINED IN A SHARABLE HIGH SEGMENT
; OR A SPY SEGMENT, CPOPJ1 IF NOT
;PRESERVES T1,T3
;ON CPOPJ RETURN, T2 POINTS TO HIGH SEG DATA BLOCK IN WHICH PAGE WAS FOUND
TPWHS:
IFN FTPEEKSPY,<
PUSHJ P,TSSPT ;A SPY PAGE?
CAIA ;NO
JRST CPOPJ1##
>
MOVSI T4,UWPOFF ;IF IT IS AN A HIGH SEG
PUSHJ P,TPAHS ;IS IT IN HIGH SEG?
TDNN T4,.HBSGN(T2) ;IN HIGH SEG, IS HIGH SEG WRITABLE?
AOS (P) ;NOT IN HIGH SEG OR NOT IN WRITABLE HIGH SEG
POPJ P,
TPAHS:: TDZA T2,T2 ;CLEAR T2
TPSHS:: MOVSI T2,SHRSEG!SPYSEG ;BITS TO TEST
PUSHJ P,SAVE3## ;SAVE P1
SETO P1, ;FLAG LOOK AT ALL SEGMENTS
TPXHS: SKIPN P3,T2 ;BITS IN LEFT HALF OF P3
SETCA P3, ;IF ZERO, PRETEND -1
MOVEI P2,(T1) ;AND PAGE # IN RIGHT HALF
PUSH P,T1 ;SAVE THE VIRTUAL PAGE NUMBER
TDZA T1,T1 ;GET FIRST HIGH SEG BLOCK
TPXHS1: POP P,T1 ;RESTORE LAST BLOCK FOUND
PUSHJ P,GNXHSB## ;GET NEXT HIGH SEG BLOCK
JRST TPOPJ1## ;NOT IN ANY HIGH SEG
PUSH P,T1 ;SAVE HIGH SEG BLOCK ADDR
TDNN P3,.HBSGN(T1) ;ARE THOSE BITS SET IN THE HIGH SEG WORD?
JRST TPXHS1 ;NO
PUSHJ P,HSVAD## ;GET STARTING AND ENDING VIRTUAL ADDRESSES
; OF THE HIGH SEGMENT
LSHC T1,W2PLSH ;CONVERT TO STARTING AND ENDING PAGE NUMBERS
CAIL P2,(T2) ;BELOW THE START OF THE HIGH SEGMENT?
CAILE P2,(T1) ;OR ABOVE THE TOP OF THE HIGH SEGMENT
JRST TPXHS1 ;OK FOR THIS HIGH SEG
JUMPL P1,TTPOPJ## ;POINT T2 AT HIGH SEG BLOCK, RESTORE T1, RETURN
MOVE T1,(P) ;GET HIGH SEG BLOCK ADDR AGAIN
LDB T1,[PSG2LH+.HBSG2(T1)] ;SECTION #
CAIE T1,(P1) ;RIGHT SECTION?
JRST TPXHS1 ;NO, LOOP ON
JRST TTPOPJ## ;POINT T2 AT HSB, RESTORE T1, RETURN
;SUBROUTINE TO CHECK SECTION # AGAINST JBYSG2 AS WELL AS THE
;CHECKS TPAHS/TPSHS DOES. SAME RETURNS AS TPAHS
;TPNHS SAVES ALL T ACS, ALL OTHER ENTRY POINTS DESTROY T1 AND T2
;BUT PRESERVE T3 AND T4
TPNHS:: PUSHJ P,SAVT##
TPNHX: TDZA T2,T2
TPNSHS: MOVSI T2,SHRSEG!SPYSEG ;BITS TO TEST
PUSHJ P,SAVE3## ;SECTION #
MOVE P1,T4 ;SAVE T4 FOR ALL CALLERS
MOVEI T4,(T1) ;GET PAGE #
LSH T4,P2SLSH ;ONLY SECTION #
PUSHJ P,RSECT4 ;RESOLVE SECTION # TO INDEPENDENT SECTION
JRST CPOPJ1## ;NON-EXISTENT SECTION ISN'T IN HIGH SEG
EXCH T4,P1 ;PUT SECTION INTO P1 AND RESTORE T4
ANDI T1,HLGPNO ;KEEP ONLY PAGE #
PJRST TPXHS ;CONTINUE
;SUBROUTINE TO INCREMENT OR DECREMENT JBTSWP FOR A HI SEG
;PRESERVES T1
INCHJ:: SKIPA T3,[1,,0] ;PREPARE TO INCREMENT NUMBER OF HIGH SEGMENT
; PAGES IN CORE
DECHJ: MOVSI T3,-1 ;DECREMENT NUMBER OF HIGH SEGMENT PAGES IN CORE
PUSH P,T1 ;SAVE T1
PUSHJ P,TPNHX ;IS THIS PAGE IN THE HIGH SEGMENT?
SKIPG .HBSGN(T2) ;IS THERE A REALY HIGH SEG?
JRST TPOPJ## ;SPY SEG OR NOT IN HIGH SEG
MOVSI T4,(UP.CTX) ;GET CONTEXT SERVICE BIT
TDNE T4,.USBTS ;DELETING A HISEG FOR CTXSER?
JRST TPOPJ## ;YES, DON'T TOUCH THE PAGE COUNT
HRRZ T4,.HBSGN(T2) ;NO, GET HIGH SEGMENT NUMBER
ADDM T3,JBTSWP##(T4) ;INCREMENT OR DECREMENT PAGE COUNT
JUMPL T3,TPOPJ## ;RETURN IF REMOVING A PAGE FROM CORE
EXCH J,T4 ;PUT SEGMENT NUMBER IN USEFUL PLACE
LDB J,JBYHSO## ;GET ORIGIN PAGE
PUSH P,J ;SAVE THAT
PUSH P,P2 ;SAVE P2
MOVE P2,T2 ;HIGH SEG DATA BLOCK ADDR TO P2
MOVE J,T4 ;RESTORE J
PUSHJ P,SCWEXO##
POP P,P2 ;RESTORE P2
POP P,T4
POP P,T1
POPJ P,
;SUBROUTINE TO SET UP JBTHSA FOR NON-SHARABLE HI SEG CASES
;IN CASE IT CHANGED (PARTICULARY FOR LOKCON, BUT SO THE INFORMATION
;WILL BE CORRECT ANYWAY). PRESERVES ALL ACS, IF A NON-SHARABLE HI SEG UPDATES
;JBTHSA ACCORDING TO CURRENTLY MAPPED UPMP
SETHSA: PUSHJ P,SAVT## ;SAVE TEMP AC'S
SE1ENT ;MUST BE IN SECTION 1 (GTPME)
PUSH P,J ;AND J
MOVE J,.USJOB ;GET JOB NUMBER
MOVEI T1,JS.RUU ;IN RUN UUO?
MOVSI T2,(JS.IGS) ;OR GETSEG UUO?
TDNN T1,JBTSTS##(J) ;IF SO, .UPHSS IS NOT
TDNE T2,JBTST2##(J) ;RELIABLE
JRST JPOPJ## ;SO DON'T TRUST IT
MOVEI T1,JBTSGN##-.HBLNK(J) ;HEADER FOR SEGMENT DATA BLOCK ADDR
SETHS1: HRRZ T1,.HBLNK(T1) ;GET NEXT BLOCK
JUMPE T1,JPOPJ## ;DONE IF NO MORE
SKIPLE J,.HBSGN(T1) ;SPY SEG?
TLNE J,SHRSEG ;OR SHARABLE?
JRST SETHS1 ;NOT CONCERNED WITH THOSE
HRRZS J ;MAKE USABLE INDEX
LDB T4,[PSG2LH+.HBSG2(T1)] ;GET SECTION #
LSH T4,S2PLSH ;CONVERT TO PAGE #
LDB T2,JBYHSO## ;GET VIRT PAGE # OF ORIGIN OF SEGMENT
ADD T4,T2 ;MAKE FULL PAGE #
PUSHJ P,GTPM4 ;GET PAGE MAP ENTRY
TLNN T4,(PM.COR) ;IN CORE?
SETZ T4, ;NO, STORE 0
DPB T4,JBYHSA## ;STORE FIRST PAGE
JRST SETHS1 ;CONTINUE
;SUBROUTINE TO WAIT FOR MIGRAT TO PASS US
;CALLED BY IPCFS
;USES T1
IPMWAT::PUSH P,J ;SAVE J
IPMWT1: SKIPL T1,MIGRAT## ;MIGRATE IN PROGRESS?
HRRZS T1 ;(CLEAR FLAGS)
JUMPE T1,JPOPJ## ;NO
CAMLE T1,.USJOB ;IF SO, HAS IT PASSED US?
JRST JPOPJ## ;NOT IN PROGRESS OR HAS PASSED US
MOVEI T1,1 ;SLEEP A BIT
MOVE J,.CPJOB
PUSHJ P,SLEEPF## ;..
JRST IPMWT1 ;AND CHECK AGAIN
SUBTTL KILL NON-ZERO SECTION PAGES
;HERE TO KILL ALL NON-ZERO SECTIONS AND PAGES, AND MARK THE USER SMALL AGAIN.
KILNZS::SKIPN JBTADR##(J) ;JOB REALLY HAVE ANY CORE?
JRST CPOPJ1## ;NO, DON'T DO ANYTHING THEN
PUSHJ P,SAVE4## ;SAVE ACS
PUSHJ P,SAVT## ;SAVE THESE TOO
SE1ENT ;FOR PAGTAB/MEMTAB
MOVSI P1,-<MXSECN+1> ;AOBJN POINTER TO SECTIONS
AOBJP P1,CPOPJ1## ;DONE
PUSH P,J ;SAVE J
MOVE J,.USJOB ;GET CURRENTLY MAPPED JOB
KILNZ1: PUSHJ P,KILNZ6 ;SEE IF NEED TO WAIT
JRST JPOPJ##
KILNZ2: SKIPN P2,.UPMP+SECTAB(P1) ;SECTION EXIST?
JRST KILNZ3
TLNN P2,(<PM.ACD^!PM.DCD>B2) ;INDIRECT OR IMMEDIATE?
JRST KILN2A ;IMMEDIATE
MOVEI T4,(P1) ;SECTION IN QUESTION
PUSHJ P,RSECT4 ;REAL SECTION #
JFCL
MOVEI T1,(T4) ;INTO T1
PUSHJ P,STPCS## ;PUT PCS IN INDEPENDENT SECTION
JRST KILNZ3
KILN2A: MOVEI T1,(P1) ;SECTION IN QUESTION
PUSHJ P,KILSEC ;KILL THE SECTION
MOVEI T2,(P2) ;GET SECTION MAP ENTRY
MOVEI T1,(P1) ;SECTION # AGAIN
PUSHJ P,ZAPNZM ;KILL THE MAP
TDZA T1,T1
KILNZ3: HRREI T1,KILNZ2-KILNZ1
SETZM .UPMP+SECTAB(P1)
AOBJN P1,KILNZ1(T1) ;CONTINUE
SKIPL .USBTS ;REALLY A BIG USER?
JRST KILNZ5 ;CLEAR PAGING MEM AND RETURN
KILNZ4: MOVE T2,.UPMP+.UMWSB ;WSBTAB FOR NZS
ANDI T2,37777 ;KILL IT TOO
PUSHJ P,LKPSF ;LINK PAST THE PAGE IN PAGTAB
SSX T2,MS.MEM ;PAGTAB SECTION
HLLZS PAGTAB(T2) ;INDICATE LAST PAGE ALLOCATED
HRRZS T2
PUSHJ P,DLTPGC
SETZM .UPMP+.UMWSB
MOVEI T1,.UPMVP/PAGSIZ-1-1 ;VPN OF .WSBNZ
PUSHJ P,TSWST ;GET BIT TO CLEAR IN...
CAIA
ANDCAM T2,(T4) ;WSBTAB
MOVSI P1,(UP.BIG)
ANDCAM P1,.USBTS ;NO LONGER A BIG USER
MOVSI T1,-1 ;DECREMENT # FUNNY PAGES
ADDM T1,JBTPDB##(J)
KILNZ5: SETZ T1,
DPB T1,NZSXCN## ;CLEAR # OF NZS SECTIONS
CLRPGT ;FLUSH PAGING MEMORY
JRST JPOPJ1## ;RESTORE J AND RETURN
KILNZ6: SKIPE SCDRTF## ;FORCED RESCHED PENDING?
JRST KILNZ7
PUSH P,T1 ;SAVE T1
SKIPE T1,.CPTMF## ;CLOCK TICK AT ALL?
CAIG T1,3 ;MORE THAN 3 TIMES?
PJRST TPOPJ1## ;OK TO PROCEED
POP P,T1
KILNZ7: PUSHJ P,UUOLVL## ;UUO LEVEL?
POPJ P, ;NO
AOS (P) ;SKIP RETURN WHEN WE DO
IFN FTMP,<
PUSHJ P,REMMM## ;REMEBER STATE OF MM
>
PJRST WSCHED## ;WAIT
;SUBROUTINE TO KILL ALL PAGES IN A (NON-ZERO) SECTION
;NOTE THAT J MUST BE SET UP
KILSEC: PUSHJ P,SAVE3## ;GET AN AC
MOVE P3,.USVRT ;GET VIRTUAL STATUS OF JOB
ANDCMI P3,777 ;FORGET ANA
MOVE P2,T1 ;SECTION #
PUSHJ P,GETNZC ;GET COUNT OF PAGES IN SECTION
SKIPN P1,T1 ;SAVE IT
POPJ P, ;NOTHING TO DO
PUSH P,P2 ;SAVE SECTION #
LSH P2,S2PLSH ;SECTION # (SO DCUPR DOES RIGHT THING)
HRLI P2,-<HLGPNO+1> ;STARTING AT PAGE 0
KILSE1: HRRZ T1,P2 ;FOR DLTPAG & GTPME
PUSHJ P,GTPME ;GET PAGE MAP ENTRU
JUMPE T2,KILSE2 ;NOTHING TO DO THIS ENTRY
JUMPE P3,KILS1A ;IF NOT VIRTUAL, SKIP THIS
SOS VMTOTL## ;LESS VM IN USE
AOS VMCMAX##
KILS1A: PUSHJ P,DLTPAG ;DELETE THE PAGE
SOJLE P1,KILSE3 ;DONE
KILSE2: AOBJN P2,KILSE1 ;CONTINUE
KILSE3: PUSHJ P,SETVRT ;FIX .USVRT
POP P,T1 ;RESTORE SECTION #
SETZ T2,
PJRST PUTNZC ;NO PAGES LEFT
;ROUTINE TO KILL ALL EMPTY NZS MAPS, MAKE USER SMALL IF HE NOW IS.
ZAPSCS: SKIPL .USBTS ;NEED TO DO THIS AT ALL?
POPJ P, ;NO
SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVE2## ;SAVE P1 & P2
MOVSI P1,-MXSECN ;NOTE THAT SECTION 0 NOT INCLUDED
IFN FTMP,<
PUSHJ P,MMOWN## ;OWN THE MM?
PUSHJ P,GGVMM## ;MM IF REQUIRED
>
MOVE P2,[POINT UP.SCS,.USSCT,] ;ARRAY OF COUNTS
ZAPSCL: ILDB T2,P2 ;COUNT OF PAGES
JUMPN T2,ZAPSCE ;KILL SECTION IF NEED TO
SKIPE T2,.UPMP+SECTAB+1(P1) ;GET THE MAP ENTRY
TLNE T2,(<PM.ACD^!PM.DCD>B2) ;DON'T INCLUDE INDIRECTS
JRST ZAPSCE
MOVEI T1,1(P1) ;SECTION # KILLING
PUSHJ P,ZAPNZM ;KILL THE MAP
SETZM .UPMP+SECTAB+1(P1) ;CLEAR THE ENTRY
ZAPSCE: AOBJN P1,ZAPSCL ;..
LDB P1,NZSXCN## ;ANY MAPS HAVE OR DESIRED?
JUMPN P1,CPOPJ## ;DONE
PUSH P,J ;KILNZ4 WANTS J ON THE STACK
SOS -1(P) ;KILNZ4 TRIES TO SKIP
JRST KILNZ4
;HERE TO KILL A SECTION MAP. POINTER TO MAP IN T2
;T1=SECTION # BEING KILLED
;***DOES NOT ZERO MAP SLOT***
ZAPNZM: PUSH P,T1 ;SAVE T1
ANDI T2,37777 ;KEEP ONLY PHYS. PAGE #
PUSHJ P,LKPSF ;LINK PAST THE PAGE IN PAGTAB
SSX T2,MS.MEM ;PAGTAB SECTION
HLLZS PAGTAB(T2) ;INDICATE LAST PAGE ALLOCATED
HRRZS T2
PUSHJ P,DLTPGC ;RETURN THE PAGE
POP P,T1 ;RESTORE SECTION #
MOVEI T1,.UPMVP/PAGSIZ(T1) ;TURN OFF WSB FOR IT
PUSHJ P,TSWST ;GET IT
POPJ P,
ANDCAM T2,(T4) ;CLEAR BIT
LDB T2,NZSSCN## ;DECREMENT # OF MAPS
SOS T2
DPB T2,NZSSCN##
LDB T2,NZSICN## ;JUST IN CASE
JUMPE T2,CPOPJ##
SOS T2
DPB T2,NZSICN##
POPJ P,
;ROUTINES TO INCREMENT/DECREMENT EXISTENT PAGES IN NON-ZERO SECTIONS.
;CALL WITH T1=SECTION # TO CHANGE. PRESERVES WORLD.
;NOTE - TO BE CALLED AT UUO LEVEL ONLY -
INCNZC: JUMPE T1,CPOPJ## ;DON'T DIDDLE SECTION 0
PUSHJ P,SAVT## ;SAVE ACS
MOVEI T3,1 ;FLAG INCREMENT
JRST CHGNZC ;FIX IT
DECNZC: JUMPE T1,CPOPJ## ;DON'T CHANGE SECTION 0
PUSHJ P,SAVT## ;SAVE ACS
MOVNI T3,1
CHGNZC: HRRZS T1 ;CLEAR JUNK
CHGNZ0: MOVE T2,.UPMP+SECTAB(T1) ;GET SECTION #
TLNN T2,(<PM.ACD^!PM.DCD>B2) ;INDEPENDENT SECTION?
JRST CHGNZ1 ;YES, PROCEED
LDB T1,[POINT 5,T2,17] ;NOTE 540(SECTAB) AND 37 DON'T
;OVERLAP ANY NON-ZERO BITS
JUMPN T1,CHGNZ0 ;SEE IF IT'S INDEPENDENT
CHGNZ1: SOSGE T1 ;NOTHING FOR SECTION 0
POPJ P, ;REALLY WAS SECTION 0
IDIVI T1,^D36/UP.SCS ;SIZE OF BYTE
LDB T4,PNTNZS(T2) ;GET COUNT
TRZ T4,UP.VRG ;NO LONGER A "VIRGIN" SECTION
ADD T4,T3 ;ADJUST COUNT
DPB T4,PNTNZS(T2) ;REPLACE
POPJ P,
GETNZC: PUSH P,T2
SOS T1
IDIVI T1,^D36/UP.SCS ;SIZE OF BYTE
LDB T1,PNTNZS(T2)
JRST T2POPJ## ;RETURN
PUTNZC: PUSH P,T2
SOS T1
IDIVI T1,^D36/UP.SCS
EXCH T3,(P)
DPB T3,PNTNZS(T2)
JRST T3POPJ##
;SUBROUTINE TO WRITE-ENABLE ALL MONITOR (AND USER) WRITE-LOCKED PAGES
;USES T1-T2
CLRWLP: PUSHJ P,SAVE2## ;SAVE P1-P2
MOVE P1,.USWLP ;# OF MONITOR-LOCKED PAGES
ADD P1,.USWLC ;+# OF USER LOCKED PAGES
JUMPE P1,CPOPJ## ;ALREADY ALL DONE?
SETZ T1, ;CLEAR PAGE WE'RE ON
CLRWL1: SKIPN P2,@[IW MS.MAP,UMAPS(T1)] ;GET PAGE ENTRY
AOJA T1,CLRWL3 ;CONTINUE IF NO PAGE
PUSH P,T1 ;SAVE PAGE #
PUSHJ P,TPNSHS ;IN A HIGH SEG?
JRST CLRWL7 ;YES, PONDER THE PROBLEM
POP P,T1 ;RESTORE T1
TLZE P2,@[IW MS.MAP,UMAPS(T1)] ;WRITE-ENABLE; WAS IT ALREADY?
SOJLE P1,CLRWL9 ;YES, COUNT AS CHANGED - DONE IF NO MORE
AOS T1 ;POINT TO NEXT PAGE
CLRWL3: TRNE T1,HLGPNO ;CROSS SECTION BOUNDARY?
JRST CLRWL1 ;NO, LOOP ON
LSH T1,P2SLSH ;YES, GET SECTION #
CLRWL4: CAILE T1,MXSECN ;ABOVE TOP IN # OF SECTIONS?
JRST CLRWL9 ;YES, DONE
SKIPE T2,.UPMP+SECTAB(T1) ;DOES NEW SECTION EXIST?
TLNE T1,(<PM.ACD^!PM.DCD>B2) ;YES, IS IT INDIRECT?
AOJA T1,CLRWL4 ;EXISTS AND ISN'T INDIRECT, CONTINUE
LSH T1,S2PLSH ;CONVERT BACK TO PAGE #
PUSHJ P,SCDCHK## ;BLOCK IF WE SHOULD
JRST CLRWL1 ;THEN LOOP AROUND
;HERE IF PAGE IN HIGH SEG
;***SHOULD SKIP TO END OF HIGH SEG***
CLRWL7: POP P,T1 ;RESTORE T1
AOJA T1,CLRWL3 ;FOR NOW, JUST CONTINUE
CLRWL9: SETZM .USWLP ;CLEAR
SETZM .USWLC ;ALL COUNTS
POPJ P, ;RETURN
SUBTTL ROUTINE TO DO CLRPGT FOR BOTH SECTION 0 AND 1
;CALL:
; PUSHJ P,CLPTZO
; EXP (ADDRESS TO CLEAR)
;USES NOTHING
CLPTZO::SE1ENT
PUSH P,T1
HRRZ T1,@-1(P)
CLRPT (T1) ;CLEAR SECTION LOCAL (SECTION 1)
CLRPT @T1 ;CLEAR GLOBAL (SECTION 0)
JRST TPOPJ1##
;NOTE THAT THE DX ENTRIES IN THIS TABLE SHOULD NEVER BE USED BY THIS
PNTCNT: POINT 14,T1,13 ;RH10
POINT 14,T1,13 ;DX10 (HAH!)
POINT 14,T1,13 ;RH20
MAXCNT: 400000+T1,,37 ;RH10
400000+T1,,37 ;DX10 (HAH!)
400000+T1,,3 ;RH20
PNTNZS: POINT UP.SCS,.USSCT(T1),<UP.SCS-1>
POINT UP.SCS,.USSCT(T1),<2*UP.SCS-1>
$LIT
$HIGH
VMEND: END