Trailing-Edge
-
PDP-10 Archives
-
bb-jr93d-bb
-
7,6/ap017/vmser.x17
There is 1 other file named vmser.x17 in the archive. Click here to see a list.
TITLE VMSER - VIRTUAL MEMORY SERVICE ROUTINE V4653
SUBTTL J. FLEMMING, T. WACHS 30 JULY 86
SEARCH F,S
SALL
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1973,1986>
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
XP VVMSER,4653 ;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
NVPNT3: POINT P2.SPN,PT2TAB(T3),<^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
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,UNIKON##(U) ;SET UP J POINTING TO KONTROLLER
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,UNIKON##(T3) ;YES, GET 2ND KON
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,UNIKON##(U) ;GET (NEW) KON
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
HRRZ T2,KONCHN##(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,<
HRRZ T2,UNICHN##(U) ;FILE TRANSFERS WAITING ON THIS CHAN?
SKIPE CHNQUE##(T2)
SKIPN T2,UNI2ND##(U) ;AND DUAL PORTED?
JRST SWPS16 ;NO, OK LET IT HAPPEN
HRR J,UNIKON##(T2) ;YES, IS OTHER KON BUSY?
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,UNIKON##(U) ;GET KON BACK
SWPS16:>
IFN FTMP,<
MOVE T2,UNICAM##(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,KONCHN##(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,UNIKON##(U) ;KONTROLLER
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,UNIKON##(T3) ;YES, GET 2ND KON
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,UNIKON##(U) ;GET (NEW) KON
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,KONCHN##(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
HRR J,UNIKON##(U) ;SET KONTROLLER
IFN FTDUAL,<
CAIE P2,@KONCHN##(J) ;IGNORE BUSY IF INT ON THIS CHAN
SKIPGE @KONCHN##(J) ;CHAN BUSY?
JRST SWPPI3 ;IDLE, USE PRIME PORT
SKIPN T3,UNI2ND##(U) ;BUSY, DUAL-PORTED DRIVE?
JRST SWPPI3 ;NO, WAIT FOR PRIME PORT
HRR J,UNIKON##(T3) ;YES, GET 2ND KON
CAIE P2,@KONCHN##(J) ;IGNORE BUSY IF INT ON THIS CHAN
SKIPGE @KONCHN##(J) ;CHAN BUSY?
HRRZ U,UNI2ND##(U) ;IDLE, USE 2ND PORT
HRR J,UNIKON##(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,@KONCHN##(J)
SKIPGE @KONCHN##(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
>
HRR J,UNIKON##(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,KONCHN##(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,@KONCHN##(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,KONCHN##(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
SWPCP: MOVE T4,UNICAM##(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,UNICAM##(T3) ;2ND PORT ON THIS CPU?
TDNN T3,.CPBIT##
JRST SWPCP1 ;NO
HRRZ U,UNI2ND##(U) ;SWITCH TO OTHER PORT
HRR J,UNIKON##(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
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## ;SAVE MAPPING IN EFFECT
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 18-BIT CHAN
IFN FTKL10,<
SKIPGE T2,CHB22B##(P3)
MOVEI U,1 ;22-BIT CHAN
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)
IFN FTIPCF,<
TLNN P4,(SL.IPC) ;IPCF?
>
CAILE J,JOBMAX## ;HIGH SEG?
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 ;PROCEED IF HIGH SEG, IPCF, OR PAGING QUEUE
HRRZ T2,JBTUPM##(J) ;SWAPPING THE UPMP?
CAIE T2,(P4)
JRST THIS4 ;NO
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 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 HI-SEG
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
PUSHJ P,GMPTR ;GET POINTER
MOVE P4,(T4) ;GET POINTER
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,-1000 ;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,RH2TRX## ; +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##(U) ;GET ADDRESS
JUMPLE P2,THIS13 ;DONE IF P2=0
AOBJN P1,THIS4 ;MORE TO DO, GET NEXT CHUNK
TRNE U,2 ;IF AN RH20
TRO U,4 ; TELL KLSER
PUSHJ P,GETMOR## ;NEED ANOTHER 4-WORD BLOCK
JRST THIS20 ;NONE AVAILABLE
TRZ U,4 ;CLEAR KLSER'S RH20-BIT
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,RH2LST## ;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 ;NO
CAIG J,JOBMAX## ;JOB?
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>]
JUMPL J,THIS17 ;IF SWAPPING "IP" QUEUE
TLNN U,200000 ;OR THIS IS UPMP SWAP IN
CAILE J,JOBMAX## ; OR A HIGH SEGMENT,
JRST THIS17 ;DON'T STORE SINCE A RANDOM JOB IS ADDRESSABLE
THIS17: 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: MOVE P3,.USLPS ;NO, GET POINTER FROM CURRENT UPT
TLNN P1,-1 ;FRAGMENTED SWPLST ENTRY?
POPJ P, ;NO, ALL IS WELL
PUSHJ P,FRGIDX ;GET FRAGMENT INDEX
ADDI P3,(T1) ;POINTER INTO TABLE
MOVE P3,(P3) ;AND ENTRY
POPJ P,
SETVPN: MOVEI T2,.USLPS ;NO, STORE FOR CURRENT JOB
TLNN P1,-1 ;FRAGMENTED?
JRST SETVP5 ;NO
PUSHJ P,FRGIDX ;COMPUTE A FRAGMENT INDEX
MOVE T2,(T2) ;RELOCATE
ADD T2,T1 ;PLACE TO STORE
SETVP5: 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 C(T1)
RTNVPN::
MOVE T1,-1(T2) ;GET COUNT
SOS T2 ;ADDRESS
PJRST GIVWDS##
;SUBROUTINE TO SET UP J FROM SWPLST ENTRY
;ENTER P1 POINTING TO SWPLST
;EXIT CPOPJ1 IF A HIGH SEG, CPOPJ IF LOW
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 ;YES, INDICATE THAT BY SETTING J NEGATIVE
CAILE J,JOBMAX## ;HIGH SEG?
AOS (P) ;HIGH SEG OR PAGING QUEUE RETURN
POPJ P, ;BACK
;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
PUSHJ P,SVEUB## ;LOW SEG, MAKE JOB ADDRESSABLE
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
LDB T2,NFYPGS## ;ADD 1 PAGE FOR UPMP
ADD T1,T2
LDB J,NZSSCN## ;GET NUMBER OF NZS MAPS
ADDI J,(T1)
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
LDB T2,IMGOUT## ;NUMBER OF PAGES
LDB T3,NFYPGS## ;PLUS 1 FOR UPMP
ADD T2,T3
LDB T3,NZSSCN## ;# OF MAPS AGAIN
ADDI T2,(T3) ;ADD IN
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
PJRST MAKSLE ;STORE IN SWPLST 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 BISL11 ;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,1 ;GET A CORE BLOCK
PUSHJ P,GET4WD## ;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
;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,.USHSE
LSH T1,W2PLSH##
LSH T2,W2PLSH##
EXCH T1,.USTMP
EXCH T2,.USTMP+1
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: SKIPLE T2,JBTSGN##(J) ;IS THERE A NON-SHARABLE HI-SEG?
TLNE T2,SHRSEG
JRST BISL10 ;NO, GO MAKE THE SWPLST ENTRY
IFN FTXMON,<
HRRZS T2 ;CLEAR JUNK
>
LDB T3,[POINT 9,JBTADR##(T2),8] ;YES
SKIPE JBTADR##(T2) ;HIGHEST ADR IN HIGH SEG
ADDI T3,1
DPB T3,JBYHSS## ;SAVE AS HI SEG SIZE
LDB T4,[POINT 9,JBTUPM##(T2),8] ;HI-SEG OFFSET
PUSHJ P,MAPHI
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 FOR HI SEG
BISL11: PUSHJ P,SAVE2## ;SAVE ACS
LDB P1,IMGOUT## ;NO OF PAGES TO SWAP IN
HRLI P1,(SL.SIO) ;SWAPPING IO
MOVE T1,JBTSWP##(J) ;GET DISK ADDR
PUSHJ P,BLDVPN ;GET CORE FOR TABLE, IF NECESSARY
POPJ P, ;OOPS
AOS (P) ;GOOD RETURN
PJRST BHSLST ;SET UP SWPLST FOR HI SEG
;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: 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
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: PUSHJ P,SAVE4## ;SAVE ACS
SOS P4,T3 ;GET CORE ADDRESS (WE DON'T NEED COUNT,
;BUT DO NEED EXTRA WORD FOR TERMINATING ZERO)
MOVE P2,T1 ;ADDRESS OF DISK ADDRESS FRAGMENT TABLE
MOVEI P3,STOHDA ;ROUTINE TO STORE DISK ADDRESS IN MEMTAB
PUSHJ P,BFSLST ;SETUP SWPLST FRAGMENT TABLE, MAKE SWPLST ENTRY, AND RETURN
HRRM P4,JBTSWP##(J) ;STORE NEW SWPLST TABLE
POPJ P,
;SUBROUTINE TO STORE DISK ADDRESS IN MEMTAB, CALL WITH T1=DISK ADDRESS,
; T2=MEMTAB INDEX, ALWAYS RETURNS CPOPJ
STOHDA: 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 P4, ;NO FRAG TABLE COPY
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,<1000_<^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
; P4=ADDRESS TO COPY ORIGINAL FRAGMENT TABLE TO (CONTIGUOUS BLOCK)
; OR ZERO IF NONE (COPY IS USED FOR HIGH SEG)
BFSLST: PUSHJ P,SAVE4## ;SAVE ACS
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
JUMPE P4,BFSLS4 ;NO COPYING TO DO
MOVE T1,-1(P1) ;GET ORIGINAL ENTRY
MOVEM T1,(P4) ;COPY IT
AOS P4
BFSLS4: 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
PUSHJ P,SETXMT ;SET UP FOR THIS FRAG
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
SKIPE P4 ;IF COPY OF FRAGMENT LIST
SETZM (P4) ;THEN TERMINATE COPY
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) ;SWAPPING 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
DLTSLX::
IFN FTMP,<
PUSH P,F ;PROBABLY NOT NECESSARY
MOVEI F,SWPDDB## ;FOR PIOFF
PIOFF ;GUARD AGAINST INTERPROCESSOR RACE
PUSHJ P,DLTSLE ;DELETE SWPLST ENTRY AND DECREMENT SLECNT
PION
JRST FPOPJ## ;RESTORE F AND RETURN
>
DLTSLE::SKIPN T1,SWPLST##(P1) ;GET ENTRY
STOPCD CPOPJ##,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
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,1 ;DELETE 1 BLOCK
PUSHJ P,GIV4WD##
JUMPE P1,CPOPJ## ;DONE IF LINK=0
JRST RTNBL1 ;NOT DONE, RETURN NEXT BLOCK
DLTSL2: SETZM SWPCNT## ;ZERO SWPCNT SO WONT KEEP GETTING HERE
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,1 ;GET 1 BLOCK
PUSHJ P,GET4WD##
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##>
JRST [ADD T4,[UMAPSN+UMAPS]
POPJ P,]
ADDI T4,.UPMP-<.MCFV/PAGSIZ##>+.UMORG
CAILE T4,.UPMP+.UMUPT ;SECTION MAP?
MOVEI T4,SECTAB-.UMORG-<<.UPMVP/PAGSIZ##>-<.MCFV/PAGSIZ##>>(T4)
POPJ P,
;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
ANDCAM P4,.USBTS ;.USBTS INDICATING MAP INFO
SKIPE R,.USSPT ;EXTENDED SECTION
JRST SETO18 ;YES
SETOM1: SETZB R,.USSPT ;BE SURE THAT'S WHAT WE'RE DOING
SETOM2: 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
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
MOVEM U,MEMTAB(F) ;SAVE DISK ADDRESS IN MEMTAB
MOVEI T4,(M)
CAIE T4,<.UPMVP-1>/PAGSIZ##
JRST SETOM7
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: 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?
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 SETO20 ;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
SETO20:
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 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
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
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 SETI16 ;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
SETI16:
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 DLTSLX
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
;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,<^D35-<^L<P2.VPN>+P2.SPN-1>>
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,<^D35-<^L<P2.VPN>+P2.SPN-1>>
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,JBYLSA## ;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 (0) ;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
CLP4WD==2 ;NUMBER OF 4 WORD BLOCKS FOR REQUEST
GETCLP::PUSHJ P,SAVE4## ;SAVE P1-P4
DMOVE P1,T1 ;SAVE CALLER'S ARGUMENTS
DMOVE P3,T3 ;...
MOVEI T2,CLP4WD ;GET MEMORY FOR REQUEST BLOCK
S0PSHJ GET4WD## ;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,CLP4WD ;NUMBER OF 4-WORD CHUNKS
MOVE T2,P1 ;ADDRESS OF THEM
S0JRST GIV4WD## ;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
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
MOVE T2,T1 ;PAGE NUMBER
MOVE T1,R ;SECTION NUMBER
MOVEM T2,SPTCOM##-<(MS.FMD)>(T1) ;STORE IN SPT SLOT
ADDI T1,SECTAB ;WHERE TO STORE
PUSHJ P,STMAPS ;STORE PAGE NUMBER IN THE 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
CLRPGT (0)
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: MOVE T3,P1 ;NUMBER OF PAGES TO ALLOCATE
PUSHJ P,GETPHP ;GET THE PAGES
POP P,.UPMP+.UMTMP ;MAKE THE SECTION MAP ADDRESSABLE
CLRPGT (0) ;FLUSH PAGING MEMORY
MOVE P3,P2 ;STARTING MAP SLOT (NEEDED FOR VIRTUAL ADDRESS)
HRRZ P4,T1 ;FIRST PHYSICAL PAGE ALLOCATED
CREMN5: 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
HRRZ P4,PAGTAB(P4) ;NEXT PAGTAB ENTRY
TRNE P4,-1 ;LAST PAGE?
AOJA P2,CREMN5 ;NO, LOOP MAKING ENTRIES FOR EVERY PAGE ALLOCATED
CLRPGT (0) ;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)
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
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 THAT 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 [CPUN##-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
IFE FTXMON,<
GFWNZD:: ;DECNET USES "ONCE-ONLY" CORE
GFWNZO::MOVE T1,[400000,,0] ;"ONCE-ONLY" CORE FOR THE KS
>
IFN FTXMON,<
GFWNZ2::SKIPA T1,[400000,,(MS.SAT)] ;SECTION 2 CORE
GFWNZD:: ;(NAME FOR DECNET TO CALL)
GFWNZS::MOVE T1,[400000,,(MS.MEM)] ;GENERAL NZS SPACE
SE1ENT ;MUST BE IN SECTION 1 TO ALLOCATE NZS SPACE
>
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 [CPUN##-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
CAILE T4,PAGSIZ## ;REQUESTING MORE THAN 1 PAGE
JRST GTFW10 ;YES, MERGE THIS PAGE AND TRY AGAIN
SUB T2,T4 ;AMOUNT LEFT OVER AFTER SATISFYING REQUEST
JUMPE T2,CPOPJ1## ;EXACT AMOUNT, RETURN NOW
PUSH P,T1 ;SAVE ADDRESS OF NEWLY ACQUIRED CHUNK
ADD T1,T4 ;ADDRESS OF RESIDUE
EXCH T1,T2 ;WANT ARGS IN OTHER ORDER
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,100000 ;LIGHT BIT SAYING NOT TO RETURN FULL PAGES
EXCH T1,T2 ;WANT LENGTH AND ADDRESS IN THE OTHER ORDER
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
; PUSHJ P,GVFWDS
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,400000 ;FLAG NOT FUNNY SPACE
>
IFE FTXMON,<
MOVSI R,400000 ;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,[600000,,.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,[400000,,.USFCU] ;GET UNCACHED LIST HEADER
>
MOVEI T3,.USFCC ;GET CACHED LIST HEADER
GVFWD3: SPUSH T3 ;PUSH LEFT HALF
TLZ T3,100000 ;CLEAR POSSIBLE FLAG.
TLNE R,400000 ;FUNNY SPACE?
CAME T3,NZSFCH##(R) ;IF NOT THE FIRST TIME
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,400000 ;FUNNY SPACE?
JUMPE T4,GVFWD5 ;SECTION ZERO IS ZERO TERMINATED
CAIN T4,(T2) ;ALREADY IN FREE LIST
STOPCD CPOPJ##,DEBUG,PFL ;++PIECE ON FREE LIST
CAIL T4,(T2) ;KEEP CHUNKS IN ADDRESS ORDER
JRST GVFWD5 ;IT GOES HERE
HRR T3,T4 ;REMEMBER LINK
JRST GVFWD3 ;AND LOOK AT THE NEXT
GVFWD5: PUSH P,T3 ;SAVE PREVIOUS (AND FLAGS)
TLZ T3,100000 ;BE SURE FLAG IS CLEAR
MOVEI T4,(T3) ;ADDRESS OF PREVIOUS
JUMPL R,GVFWD6 ;ALWAYS COMBINE 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: HLL T4,NZSFCH##(R) ;COMPARE WITH NZS HEADER FOR RIGHT SECTION
IFN FTKL10,<
CAME T4,NZSFCH##(R)
TLZA T4,-1 ;CLEAR LEFT HALF, PRESERVE NON-SKIP
TLZA T4,-1 ;CLEAR LEFT HALF PRESERVE SKIP
GVFWD7: CAIN T4,.USFCU ;UNCACHED HEADER
>
IFE FTKL10,<
CAMN T4,NZSFCH##(R)
TLZA T4,-1 ;CLEAR LEFT HALF, PRESERVE NON-SKIP
TLZA T4,-1 ;CLEAR LEFT HALF PRESERVE SKIP
>
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##,DEBUG,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 .,JOB,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,100000 ;SUPRESS RECLAMATION OF FULL PAGES
POPJ P, ;YES, ALL DONE NOW
TLCE R,400000 ;FUNNY SPACE?
JUMPE R,CPOPJ ;NO, CAN'T RECLAIM ONCE-ONLY CORE
TLC R,400000 ;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,PAGSIZ##-1 ;MAX WORDS THAT CAN BE RETURNED
ADDI T2,PAGSIZ##-1 ;AND ROUND ADDRESS TO CHUNK BOUNDRY
TRZ T2,PAGSIZ##-1 ;...
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
CAME T3,NZSFCH##(R) ;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,200000 ;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 (0) ;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
CLRPGT (0) ;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
HRRZM T2,.PDTMC##(W) ;SAVE IN UPMP
HRRM T2,.PDTMI##(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 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 #
JUMPN T4,T2POPJ## ;DOESN'T EXIST
POP P,T2 ;RESTORE T2
FLTTC1: MOVE T4,T2 ;GET WORD ADDRESS AGAIN
LSH T4,W2PLSH## ;PAGE #
SE1ENT
SKIPN T4,@[IW UMAPSN,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
SKIPLE T3,JBTSGN##(J) ;HAVE A HI SEG?
TLOA T3,(1B0) ;MAKE A USABLE INDEX OUT OF COPY OF JBTSGN
TRNA ;NO HISEG
HLRZ T2,JBTADR##(T3) ;YES, GET ITS SIZE
ADDI T2,1
LSH T2,W2PLSH## ;CONVERT TO PAGES
POPJ P, ;AND 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
PUSHJ P,TPNHS ;YES, IS THIS PAGE IN THE HIGH SEGMENT?
SKIPA J,JBTSGN##(J) ;YES, GET HIGH SEGMENT NUMBER
AOJA P1,PHYPV1 ;NO, NOT A REAL PAGE THEN (DISK ADDR?)
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
ADJWS:: PUSHJ P,SAVE2## ;SAVE P1 & P2
MOVSI P1,(IORM T1,(T4)) ;SET ARG FOR ADJWS1
MOVEI T3,30 ;MAKE SURE UPMP BIT ON IN WSBTAB
IORM T3,WSBTAB+16
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,T1 ;SAVE T1
MOVE T1,.USJOB ;JOB NUMBER
SKIPN T2,.USREL ;NON-CONTIGUOUS?
HLRZ T2,JBTADR##(T1) ;NO, GET JBTADR
SKIPLE T1,JBTSGN##(T1) ;IS THERE A NON-SHARABLE HI-SEG?
TLNE T1,SHRSEG
JRST VRTSZ1 ;NO
HRRZS T1
HLRZ T1,JBTADR##(T1) ;YES, GET ITS SIZE
ADD T2,T1 ;LOW+HIGH SIZES
VRTSZ1: LSH T2,W2PLSH##
ADD T2,.USNCR ;AND NZS PAGES
ADD T2,.USMEM ;+NO OF NON-CONTIG PAGES
AOJA T2,TPOPJ## ;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 #
TRNE T3,MXSECN ;NON-ZERO SECTION?
JRST VIRCH6 ;YES, HANDLE DIFFERENTLY
CAIG J,JOBMAX## ;A HIGH SEGMENT?
SKIPN T2,.USREL ;NO, HIGHEST CONTIGUOUS ADDRESS IN THE LOW SEGMENT
HLRZ T2,R ;HIGHEST ADDRESS IN THE SEGMENT
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
EXCH J,.USJOB ;JOB NUMBER
PUSHJ P,HSVAD## ;COMPUTE THE EXTENT OF THE HIGH SEGMENT
EXCH J,.USJOB ;RESTORE HIGH SEGMENT NUMBER
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
JRST VIRCH5 ;NO, LOW SEG VIRTUAL CORE
;HERE IF CAN GET PHYSICAL CORE
VIRCH3: CAIG J,JOBMAX## ;HIGH SEG?
JRST VIRCH4 ;NO
SKIPN T2,.USHSE ;CREATING?
MOVE T2,.USHSS ;YES, THEN START AT THE VERY BEGINNING
ADD T1,.USHSS ;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
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
MOVE J,.USJOB ;POINT TO LOW SEG
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 VIRC20
;HERE TO DO CORE UUO FOR A NON-ZERO SECTION
VIRCH6: CAILE J,JOBMAX## ;JOB OR HIGH SEG?
JRST VIRCH7 ;HIGH SEG
LSH T1,W2PLSH## ;CONVERT TO HIGHEST PAGE DESIRED
AOS T1 ;INCLUDE P0
MOVNM T1,.JDAT+JOBUAL## ;# OF PAGES TO "CREATE"
LSH T3,S2PLSH## ;CHANGE SECTION # TO PAGE 0 IN THAT SECTION
HRLI T3,(PG.IDC) ;DON'T CARE ABOUT PAGES THAT ALREADY EXIST
MOVEM T3,.JDAT+JOBUAL##+1 ;ARG
SETZM .JDAT+JOBUAL##+6 ;NO SECOND UUO
PJRST VIRC14 ;FINISH UP
;HERE FOR HIGH SEG
VIRCH7: MOVE T3,[.PAGRM,,JOBUAL##+2] ;A REMAP WILL BE DONE
MOVEM T3,.JDAT+JOBUAL##+6 ;POINTER TO BLOCK
MOVE J,.USJOB
LDB T3,JBYSG2##
XSFM T4
CAIN T3,(T4) ;IS HIGH SEG IN THIS SECTION?
SKIPN R ;YES, DOES IT ALREADY EXIST?
SKIPA T2,[377000] ;DOESN'T EXIST OR WRONG SECTION, CREATE
SKIPA T2,.USHSE ;APPENDING, CURRENT END OF HIGH SEG
SKIPA T3,[400000]
MOVE T3,.USHSS
ADDI T1,(T3)
LDB T3,JBYSG2## ;RESTORE SECTION #
HRLI T1,(T4) ;SECTION #
HRLI T2,(T4) ;HERE ALSO
LSHC T1,W2PLSH## ;PAGES
TLZN T2,-1 ;"CORE 0"
SOS T1 ;YES, ONE MORE PAGE TO DELETE
SUBM T2,T1 ;-# OF PAGES TO CREATE/REMAP
JUMPL T1,VIRCH8 ;NEGATIVE, ALL IS WELL
SETZM .JDAT+JOBUAL## ;NO FIRST UUO FOR DELETE
MOVEI T2,1 ;ONLY ONE ARG FOR DELETE REMAP
MOVEM T2,.JDAT+JOBUAL##+2 ;# OF ARGS
MOVEM T1,.JDAT+JOBUAL##+3 ;SET # OF PAGES (APPEND)
PJRST VIRC20
VIRCH8: MOVEM T1,.JDAT+JOBUAL##
CAIN T3,(T4) ;IS HIGH SEG IN THIS SECTION?
SKIPN R ;YES, DOES IT ALREADY EXIST?
MOVNS T1 ;CREATE
AOS T2
MOVEM T2,.JDAT+JOBUAL##+1 ;CREATE ARG TOO
HRRZS T2 ;INCASE DELETE
MOVEM T2,.JDAT+JOBUAL##+4 ;"FROM" REMAP PAGE
MOVEM T2,.JDAT+JOBUAL##+5 ;"TO" REMAP PAGE
MOVEI T2,3
MOVEM T2,.JDAT+JOBUAL##+2 ;# OF ARGS
MOVEM T1,.JDAT+JOBUAL##+3 ;SET # OF PAGES (APPEND)
JRST VIRC20
;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
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: 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
SKIPG T2,JBTSGN##(J) ;JOB HAVE HIGH SEG?
JRST VIRC11 ;NO
EXCH T2,J ;PUT WHERE IT'S USEFUL
LDB T4,PCORSZ## ;HIGHEST ADDR IN SEGMENT
LDB J,JBYHSO## ;LOWEST PAGE IN SEGMENT
EXCH T2,J ;BACK TO NORMAL
ADDI T4,1(T2) ;FIRST NOT IN HS
SKIPN .USMEM ;YES, CAN HE HAVE PAGES ABOVE HS?
JRST VIRC12 ;NO, JUST HAVE TO DELETE BELOW HS
LDB T3,PCORSZ## ;HIGHEST PAGE IN LOW SEG
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
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 NON-SHARABLE HI SEG TO WORRY ABOUT
VIRC11: LDB T2,PCORSZ## ;DELETE TO HIGHEST PAGE
AOS T2 ;GET THOSE OFF-BY-ONES
VIRC12: SETZM .JDAT+JOBUAL##+6 ;NO SECOND PAGE UUO
VIRC13: SUBI T2,(T1) ;# OF PAGES TO DELETE
MOVNM T2,.JDAT+JOBUAL##
;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: MOVE J,.USJOB
VIRC20: PUSHJ P,VIRC14
CAIA
AOS (P)
MOVE J,JBTSGN##(J) ;INCLUDE BITS IN RETURN
MOVE R,JBTADR##(J)
POPJ P,
;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,JBTSGN##(J) ;YES, IS THERE A HI 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]
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,777 ;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,777 ;ABOUT TO GO OVER SECTION BOUNDARY?
TRCN T4,777 ;(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
MOVE J,.USJOB ;LOAD JOB #
LDB P1,JBYSG2## ;SECTION HIGH SEG IS IN
CAIE P1,(T1) ;SECTION DESIRED?
JRST JPOPJ1## ;NO, NO OVERLAP THEN
POP P,J ;RESTORE J
HLRZ P1,T3 ;HIGHEST ADDRESS IN THE RANGE
HRRZ P2,T3 ;STARTING ADDRESS
CAML P1,.USHSS ;HIGHEST ADDRESS BELOW THE START OF THE HISEG?
CAMLE P2,.USHSE ;STARTING ADDRESS ABOVE THE END OF THE HISEG?
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
;MUST BE CALLED IN SECTION 1
ZERHGH::CAILE J,JOBMAX## ;A HIGH SEGMENT?
JRST CPOPJ1## ;YES, KISER CAN ZERO THE PAGES
PUSH P,J ;SAVE THE JOB NUMBER
SKIPLE J,JBTSGN##(J) ;DOES THIS JOB HAVE A HIGH SEGMENT?
TLNE J,SHRSEG ;AND IS IT NON-SHARABLE?
JRST JPOPJ1## ;NO, KISER CAN ZERO THE PAGES
PUSH P,T2 ;SAVE HIGHEST ADDRESS ALLOCATED
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
IFN FTIPCF,<
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
MOVEI T3,PAGSNQ## ;PUT ON THE SLOW QUEUE
HRRZS T1,T2 ;CLEAR BOTH LEFT HALVES
EXCH T1,(T3) ;APPROPRIATE QUEUE
SSX T2,MS.MEM
HRRM T1,PAGTAB(T2)
HLLZS PT2TAB(T2) ;NO BACK
SSX T1,MS.MEM
TRNE T1,-1
HRRM T2,PT2TAB(T1)
AOS PAGSNC##
IPCRM9: 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
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
IFN FTIPCF,<
PUSHJ P,GVIPCP ;RETURN THE PAGE IF NOT ALREADY RETURNED
>;END FTIPCF
; 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
> ;END FTIPCF
IFN FTIPCF,<
;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
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,JBYLSA## ;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)
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,
> ;END FTIPCF!FTEXE
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
LDB T1,JBYSG2## ;GET SECTION #
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,400000 ;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,TPAHS ;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?
S0PSHJ KILHSH## ;REMOVE JOB'S CURRENT HIGH SEG
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: TLNE P4,(1B1) ;WANT NEW HIGH SEG?
SKIPN J,JBTSGN##(J) ;NO, UNLESS THERE ISN'T ONE
PUSHJ P,FNDSGN## ;FIND A SEGMENT NUMBER FOR THE JOB'S NEW HI SEG
TLNE J,SHRSEG ;CAN'T ADD TO/FIDDLE WITH SHARABLE THIS WAY
JRST PSHERR ;..
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,JBYSG2## ;SET SEGMENT
ROT P2,S2PLSH## ;MOVE BACK
TLNE P4,(1B1) ;ADDING TO EXISTING HS?
JRST [LDB T1,JBYHSS## ;YES, PICK UP OLD SIZE
ADDI T1,(P3) ;NEW SIZE
DPB T1,JBYHSS## ;SET IT
JRST NREMA5 ] ;DON'T AFFECT ORIGIN
MOVE T1,P2 ;GET NEW STARTING PAGE NUMBER
LSH T1,P2SLSH## ;STARTING SECTION NUMBER
DPB T1,JBYSG2## ;STORE IT AS HIGH SEG ORIGIN FOR THIS USER
DPB P3,JBYHSS## ;STORE THE NEW HIGH SEGMENT'S SIZE
NREMA5: JUMPL P4,NREMA7 ;JUMP IF NON-SHARABLE
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
NREMA6: PUSHJ P,GTPME ;GET THE CONTENTS OF THE USER'S MAP
TLZ T2,(PM.NAD) ;CLEAR ACCESS BITS
PUSH P,T1 ;SAVE THE AOBJN POINTER
PUSH P,T2 ;AND THE PHYSICAL PAGE NUMBER
PUSHJ P,LKPSF ;LINK PAST THE PAGE IN PAGTAB
PUSHJ P,SCNPTB ;FIND THE PAGE AND ITS PREDESSOR IN PAGTAB
POP P,T2 ;RESTORE THE PHYSICAL PAGE NUMBER
SSX T1,MS.MEM ;SET PAGTAB SECTION
MOVEM T2,PAGTAB(T1) ;LINK AROUND THIS PAGE, AND
SSX T2,MS.MEM ;DITTO
HLLZS PAGTAB(T2) ; INDICATE THAT THIS IS NOW THE LAST PAGE IN THE LIST
HRRM T1,PT2TAB(T2)
POP P,T1 ;RESTORE THE AOBJN POINTER
AOBJN T1,NREMA6 ;AND LOOP UNTIL ALL HIGH SEGMENT PAGES
; ARE IN PAGTAB IN THE SAME ORDER THAT THEY APPEAR
; IN THE JOB'S MAP
TLZ P4,(1B0) ;HIGH SEG IS SHARABLE
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 NREMA9 ;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
NREMA9:
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
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
MOVE T4,-1(P) ;SHARABILITY/APPEND ATTRIBUTE
TLNE T4,200000 ;APPEND?
SKIPA T3,.USHSS ;YES, DON'T AFFECT .USHSS
SKIPA T3,T2
LSH T3,W2PLSH## ;SO THE REST WORKS RIGHT
CAIGE T1,(P1) ;MOVING PAGES DOWN?
JRST NREM13 ;NO
TLNN T4,200000 ;DON'T CHANGE IF APPEND
SUB T3,P4 ;YES
AOBJP P1,NREM14 ;BUMP SOURCE,,DESTINATION PAGES
NREM13: ADD T2,P4 ;MOVING PAGES UP
SUB P1,[1,,1] ;DECREMENT SOURCE,,DESTINATION
NREM14: LSHC T2,P2WLSH## ;CONVERT TO WORDS
TRO T2,PG.BDY## ;NEXT PAGE BOUNDARY - 1
DMOVEM T2,.USHSE ;STORE END, BEGINNING OF HS
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
HRRZS .USHSE ;MAKE SURE THESE ARE SECTION RELATIVE
HRRZS .USHSS
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,(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
SETZM JBTIMI##(J) ;AND CLEAR SIZES
SETZM JBTIMO##(J)
JRST NREM16 ;AND SKIP ON
NREM15: PUSHJ P,GTPME ;PHYSICAL PAGE WHICH CORRESPONDS TO THE
MOVE T3,T2 ; THE HIGHEST VIRTUAL PAGE IN THE HIGH SEGMENT
DPB P2,IMGIN## ;STORE THE SIZE OF THE HIGH SEGMENT
LDB T1,JBYHSO## ;HIGH SEGMENT STARTING VIRTUAL PAGE
MOVE J,.USJOB ;CURRENT JOB NUMBER
LDB T2,JBYSG2## ;GET SECTION TOO
LSH T2,S2PLSH##
IORI T1,(T2)
PUSHJ P,GTPME ;GET MAP CONTENTS (PHYSICAL PAGE)
MOVE P4,T2 ;SET ARGUMENT TO SCNPT
LDB T1,IMGIN## ;DECREASE LOW SEGMENT SIZE BY THE NUMBER OF
SUBI T1,(P2) ; PAGES MAPPED INTO THE HIGH SEGMENT
DPB T1,IMGIN##
TLZ P4,(PM.NAD) ;SAVE ONLY PAGE #
HRRZ P4,@[IW MS.MEM,PT2TAB(P4)]
TLZ T3,(PM.NAD) ;PHYSICAL PAGE OF THE TOP OF THE HIGH SEGMENT
SSX T3,MS.MEM ;PAGTAB SECTION
SSX P4,MS.MEM ;DITTO
MOVE T1,PAGTAB(T3) ;GET ITS LINK
HLLZS PAGTAB(T3) ;TERMINATE PAGTAB LINKED LIST FOR THE HIGH SEGMENT
HRRM T1,PAGTAB(P4) ;LINK PAGES PAST THE HI SEG TO THE LOW SEG
SSX T1,MS.MEM
TRNE T1,-1 ;IF NO PAGE
HRRM P4,PT2TAB(T1)
NREM16: MOVE J,.USJOB ;BE SURE POINTING @JOB
LDB T1,JBYHSS## ;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
LDB T2,JBYSG2## ;GET HIGH SEG SECTION # BEFORE SWITCHING J
MOVE J,(P) ;SEGMENT #
MOVSM T1,JBTADR##(J) ;SAVE HIGH PROTECTION,,RELOCATION
LDB T1,JBYHSO## ;GET THE HIGH SEGMENT ORIGIN VIRTUAL PAGE
LSH T2,S2PLSH## ;SECTION TO PAGE
IORI T1,(T2) ;FULL PAGE #
PUSHJ P,GTPME ;GET THE HIGH SEGMENT ORIGIN PHYSICAL PAGE
DPB T2,JBYHSA## ;STORE THAT FOR REDOING THE HIGH SEGMENT MAP
HRLI T2,(<PM.DCD>B2+PM.WRT+PM.CSH+PM.PUB)
MOVEM T2,.UPMP+.UMVJD
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: POP P,J ;RESTORE SEGMENT #
MOVS T1,JBTADR##(J) ;FOR UREMAP
MOVS T1,JBTADR(J) ;FOR UREMAP
HLRZM R,.USHVA ;FOR ADDRESS CHECKING AT INTERRUPT LEVEL
PJRST FIXMJ1 ;CLEAR THE A.M. AND SKIP RETURN
SUBTTL UUOCON INTERFACE WITH UUO HANDLER AND IOCSS
;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.
;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,777 ;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
PJRST 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?
JRST ADRERR## ;NO, PAGE DOESN'T EXIST, HI SEG PAGE, OR SPY PAGE
JRST UUOFLT ;PAGE FAULT
TRNGE1: EXCTUX <SKIP (T1)> ;ENSURE ADDRESS IS ACCESSIBLE
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
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?
PJRST 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
;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 USRFL9 ;YES, HANDLE SPECIALLY
;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
IFN FTPI,<
PUSHJ P,PSIIVA## ;GET INTERRUPT VECTOR ADDR
>
IFE FTPI,<
MOVEI T1,0
>
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,
;HERE WHEN THE PAGE FAULT IS A WRITE VIOLATION
USRFL9: PUSH P,T1 ;SAVE T1
SKIPLE T1,JBTSGN##(J) ;A REAL HIGH SEGMENT?
TLNN T1,UWPOFF ;YES, WRITE ENABLED?
JRST TPOPJ## ;NO, ILL MEM REF
MOVE T1,T3 ;PAGE FAIL WORD
LSH T1,W2PLSH## ;PAGE #
ANDI T1,HLGPGS ;CLEAR EXTRANEOUS JUNK
IFN FTXMON,<
XJRST [MCSEC1+.+1] ;ENTER SECTION 1 FOR PAGE MAP REF
>
PUSHJ P,GTPME ;GET POINTER
TDO T2,[PM.WRT] ;MAKE THE PAGE WRITABLE
MOVEM T2,(T4)
CLRPGT (P4) ;MAKE NEW MAPPING VISABLE
USERAC ;USER ACS
XJRSTF .USPFP ;AND RETURN TO THE USER
;LEAVING POINTER MESSED UP
USRFLX: CLRPGT (P4)
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
PUSHJ P,GETXXX ;GO GET IT
PUSHJ P,CNGDDT
JUMPN T2,GETDD2 ;JUMP IF GOT DDT
PUSHJ P,TTYFUW## ;MAKE SURE TTY ATTACHED FOR ERROR MSG
PUSHJ P,PPQCRL## ;PRINT CRLF ?
JRST URUNSB## ;
GETDD2: MOVEM T2,.JDAT+JOBDDT## ;SAVE L(DDT) IF WE WON
MOVEM T2,USRDDT## ;AND IN PROTECTED AREA
PUSHJ P,CHKMED## ;SET MEDDLE SO CAN'T CHANGE SHARABLE HIGH SEGMENT
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
SKIPLE T1,JBTSGN##(J) ;JOB HAVE A HI-SEG?
TLNN T1,GTSSEG ;AND WILL IT BE CONCEALED?
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
POPJ P, ;URP.
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
MOVSI T1,NSHF!NSWP ;LOCKED BITS
SKIPLE T2,JBTSGN##(J) ;DOES THIS JOB HAVE A HIGH SEGMENT?
TLNE T2,SHRSEG ;YES, IS IT SHARABLE?
MOVEI T2,0 ;NO, SET HIGH SEGMENT NUMBER TO ZERO
TDNN T1,JBTSTS##(J) ;IS THE LOW SEGMENT LOCKED?
TDNE T1,JBTSTS##(T2) ;IS THE HIGH SEGMENT LOCKED?
JRST IILERR ;YES, ILLEGAL IF LOCKED ERROR
UPAGE2:
IFN FTMP,<
PUSHJ P,UUOLVL## ;CAN'T WAIT FOR ANYTHING IF AT CLOCK LEVEL
JRST UPAGE3 ;(WHICH ALREADY HAS MM)
TLNN U,UU.CP1 ;CAN THIS UUO BE EXECUTED ON CPU1?
PUSHJ P,UPMM## ;NO, INSURE JOB OWNS 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?
PJRST CPOPJ1## ;DON'T INDICATE W.S. HAS CHANGED
MOVSI T1,(UP.WHC) ;WORKING SET HAS CHANGED BIT
IORM T1,.USBTS ;REMEMBER THAT
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
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 U,T1
SOJLE P1,IALERR ;ERROR IF NO MORE ARGS
PUSHJ P,GETWD1## ;GET STARTING PAGE #
CAILE T1,HLGPGS
JRST ILPERR ;NO
SE1ENT ;ENTER SECTION 1
PAGCH1: MOVSI P2,-^D35 ;# WORDS PER PAGE
SETZ P3, ;MASK WORD
PAGCH2: TRNN T1,HLGPNO ;CROSS SECTION BOUNDARY?
JRST PAGC17 ;YES
PAGCH3: HRRZ T2,T1
LSH T2,P2SLSH##
MOVE T4,T2 ;IN CASE CALL RSECT4
SKIPN T2,.UPMP+SECTAB(T2) ;DOES SECTION EXIST?
JRST PAGC19 ;NO
TLNN U,(PA.NXS) ;CARE ABOUT SECTION EXISTENCE?
JRST PAGCH4 ;NO
TLNE P4,(PA.NXS) ;SECTION EXISTS, WANT NON-EX SECTIONS?
JRST PAGC20 ;WANTS NON-EX SECT
PAGCH4: TLNN U,(PA.IND) ;CARE ABOUT INDEPENDENCE?
JRST PAGC40 ;NO
TLNN T2,(<PM.ACD^!PM.DCD>B2) ;IS IT INDEPENDENT?
TLON P4,(PA.IND) ;IT IS INDIRECT, IS THAT WHAT HE WANTS?
TLNN P4,(PA.IND) ;OR THE OTHER
JRST PAGC16 ;WRONG
TDNN U,[PA.ISN] ;CARE ABOUT SECTION #?
JRST PAGC40 ;NO
PUSHJ P,RSECT4 ;GET REAL SECTION #
JFCL ;IGNORE SKIP
LSH T4,<<^D35-5>-^L<PA.ISN>> ;PUT IT IN THE RIGHT PLACE
XOR T4,P4 ;CHECK FOR EQUIVALENCE
AND T4,U ;WHERE IT IS CARED ABOUT
TDNE T4,[PA.ISN] ;..
JRST PAGC16 ;DOESN'T MATCH
PAGC40: PUSHJ P,GTPME ;GET PAGE MAP ENTRY
TLNN P4,(PA.NXP) ;WANT NON-EXISTENT PAGES?
JUMPE T2,PAGC16 ;WANTS EXISTENT PAGES AND THIS ONE DOESN'T
TLNN U,(PA.OUT) ;CARE ABOUT OUT PAGES?
JRST PAGCH5 ;NO
TLNN T2,(PM.COR) ;IN-CORE PAGE?
TLZE P4,(PA.OUT) ;OUT, DOES HE WANT OUT?
TLNE P4,(PA.OUT) ;OR IN?
JRST PAGC16 ;WANTS WHAT IT ISN'T
PAGCH5: TLNN U,(PA.NCS) ;CARE ABOUT CACHE?
JRST PAGCH6 ;NO
TLNN T2,(PM.CSH) ;CACHED?
TLZE P4,(PA.NCS) ;WANT CACHED...
TLNE P4,(PA.NCS) ;OR UNCACHED?
JRST PAGC16
PAGCH6: TLNN U,(PA.WRT) ;CARE ABOUT WRITE?
JRST PAGCH7 ;NO
TLNN T2,(PM.WRT) ;WRITABLE?
TLON P4,(PA.WRT) ;CARE?
TLNN P4,(PA.WRT) ;...
JRST PAGC16
PAGCH7: TLNN U,(PA.RED) ;CARE ABOUT READ STATUS?
JRST PAGCH8 ;NO
TLNN T2,(<PM.DCD>B2) ;IS PAGE ACCESIBLE?
TLON P4,(PA.RED)
TLNN P4,(PA.RED)
JRST PAGC16
PAGCH8: TLNN U,(PA.GSP) ;CARE ABOUT SPY?
JRST PAGCH9 ;NO
TLNN T2,(PM.SPY) ;IS IT?
TLON P4,(PA.GSP)
TLNN P4,(PA.GSP)
JRST PAGC16
PAGCH9: TLNN U,(PA.VSP) ;CARE ABOUT SPY PAGES?
JRST PAGC30 ;NO
TLNN T2,(PM.SPY) ;IS THIS ANY KIND OF SPY PAGE?
JRST PAGC16 ;NO, CAN'T BE VIRTUAL OR NOT THEN
TLNN T2,(<PM.ACD^!PM.DCD>B2) ;VIRTUAL IF IT'S INDIRECT
TLON P4,(PA.VSP) ;IT'S PHYSICAL, HE WANTED PHYSICAL?
TLNN P4,(PA.VSP) ;OR VIRTUAL
JRST PAGC16 ;HE WANTED WHAT IT ISN'T
TRNN U,PA.SPN ;CARE ABOUT THE PAGE # BEING SPIED ON?
JRST PAGC30 ;NO
PUSH P,U ;SAVE U (CARE MASK)
TLNN T2,(<PM.ACD^!PM.DCD>B2) ;NOW, WAS IT VIRT OR PHYS?
JRST PAGC27 ;PHYS
PUSH P,T2 ;SAVE T2
PUSHJ P,PAGA10 ;GET PAGE # (RETURNED IN U)
POP P,T2 ;RESTORE T2
SKIPA T3,U ;LOAD VIRT PAGE # INTO T3
PAGC27: MOVE T3,T2 ;PHYSICAL PAGE # FROM T2
POP P,U ;RESTORE CARE MASK
XOR T3,P4 ;FIND THE DIFFERENCES BETWIXED REALITY AND FANTASY
AND T3,U ;SUPPRESSING THOSE THINGS WE DON'T CARE ABOUT
TRNE T3,PA.SPN ;ARE THEY THE SAME?
JRST PAGC16 ;NO
PAGC30:PAGC30: PUSHJ P,TPNHS ;IS IT IN A HIGH SEG?
SKIPA T3,[PA.GHI] ;REMEMBER IT IS
TDZA T3,T3
TLZE P4,(PA.GHI) ;YES
TLZE P4,(PA.GHI)
TLNN U,(PA.GHI) ;HIGH SEG?
TDOA P4,T3 ;REMEMBER THAT IT'S IN THE HIGH SEG
JRST PAGC16
PAGC10: TLNN U,(PA.AA) ;CARE ABOUT ACCESS ALLOWED?
JRST PAGC11
TLNN T2,(PM.AAB)
TLON P4,(PA.AA)
TLNN P4,(PA.AA)
JRST PAGC16
PAGC11: MOVSI T3,SHRSEG ;IS THIS PAGE
TLNE T3,JBTSGN##(J) ;IN A
TLNN P4,(PA.GHI) ;SHARABLE HIGH SEG?
SKIPA T3,[PA.GSH] ;REMEMBER IT'S NOT SHARABLE
TDZA T3,T3
TLON P4,(PA.GSH) ;NO
TLON P4,(PA.GSH)
TLNN U,(PA.GSH) ;WRONG SENSE, DO WE CARE?
TDCA P4,T3 ;WE DON'T CARE OR IT'S RIGHT, SKIP ON
JRST PAGC16
PAGC12: TLNN U,(PA.LCK) ;CARE IF IT'S LOCKED?
JRST PAGC13 ;NO
TLNE P4,(PA.GHI) ;IS IT A HIGH SEG PAGE?
TDNN T3,JBTSGN##(J) ;YES, IS HIGH SEG SHARABLE?
SKIPA T3,J ;NO, OR IT'S LOW SEG PAGE
HRRZ T3,JBTSGN##(J) ;ELSE POINT AT HIGH SEG
MOVE T3,JBTSTS##(T3) ;STATUS WORD
TLNE T3,NSHF!NSWP ;LOCKED?
TLZE P4,(PA.LCK)
TLNE P4,(PA.LCK)
JRST PAGC16
PAGC13: TLNN U,(PA.CPO) ;CARE IF WE CAN PAGE IT OUT?
JRST PAGC14 ;NO
TLNN P4,(PA.GSH) ;IS IT SHARABLE?
SKIPN T1 ;OR IS IT PAGE 0?
TLZE P4,(PA.CPO) ;CAN'T BE PAGED, WHICH SENSE DOES HE WANT?
TLNE P4,(PA.CPO)
JRST PAGC16
PAGC14: TLNN U,(PA.ZER) ;CARE IF IT'S ABZ?
JRST PAGC15 ;NO
TLZ T2,(PM.NAD)
CAMN T2,[PM.ZER] ;IS IT ABZ?
TLZE P4,(PA.ZER)
TLNE P4,(PA.ZER)
JRST PAGC16
PAGC15: AOS P3 ;TURN BIT ON
PAGC16: LSH P3,1 ;NEXT
AOS T1 ;NEXT PAGE #
AOBJN P2,PAGCH2 ;CONTINUE
EXCH P3,T1 ;SAVE T1
PUSHJ P,PUTWD1## ;PUT BIT MASK
MOVE T1,P3 ;RESTORE T1
SOJG P1,PAGCH1
JRST CPOPJ1##
PAGC17: CAILE T1,HLGPGS ;NO MORE SECTIONS?
JRST PAGC18 ;NO, FINISH UP
SETZ T1,
PUSHJ P,SCDCHK## ;DELAY ON PER-SECTION BASIS
JRST PAGCH3
PAGC18: TRNN P2,-1 ;ANY BITS TO PUT?
JRST CPOPJ1## ;NO, DONE
MOVE T1,P3
AOS (P)
JRST PUTWD1## ;PUT LAST WORD IN
;HERE IF A WHOLE SECTION DOESN'T EXIST
PAGC19: PUSH P,P4 ;SAVE P4
TLNN U,(PA.BTS^!PA.NXS) ;CARE ABOUT ANYTHING OTHER THAN SECTION ACCESS?
TLNN U,(PA.NXS) ;DO WE EVEN CARE ABOUT SECTION EXISTENCE?
JRST PAGC20
TLNE P4,(PA.NXS) ;DO WE WANT NON-EX SECTIONS?
PAGC20: TDZA P4,P4 ;SET NO BITS
SETO P4, ;SET ALL BITS
ASH P2,-^D18 ;-# OF BITS LEFT IN WORD
MOVMS P2 ;+# OF BITS LEFT IN WORD
LSHC P3,(P2) ;SET/CLEAR THAT MANY BITS
MOVNS P2 ;-# OF PAGES JUST SET/CLEARED
ADDI P2,1000 ;# OF PAGES LEFT IN SECTION
ASH P4,-^D36 ;SET P4 TO -1 OR ZERO
MOVE T1,P4 ;COPY TO T1
PAGC21: PUSHJ P,PUTWD1## ;STORE WORD
SOJLE P1,TPOPJ1## ;FIX STACK AND RETURN
SUBI P2,^D35 ;# OF PAGES LEFT IN SECT AFTER NEXT WORD
JUMPGE P2,PAGC21 ;CAN PUT IN A FULL WORD
SETZ P3, ;START WITH A CLEAN SLATE
LSHC P3,^D35(P2) ;SET/CLEAR LEFTOVER BITS
POP P,P4
JRST PAGC17
;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 #
JFCL ;DON'T CARE ABOUT SKIP
SKIPN T2,.UPMP+SECTAB(T1);SECTION EXIST?
JRST PAGAC8
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?
TLO U,(PA.OUT) ;NO, INDICATE THAT THE PAGE IS PAGED-OUT
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:
IFN FTPEEKSPY,<
MOVEI T3,0 ;ASSUME A SPY PAGE
PUSHJ P,TSSPT ;IS IT?
SKIPA T3,JBTSGN##(J) ;NO, GET HIGH SEG STATUS
JRST [TLNN T2,(<PM.DCD^!PM.ICD>B2) ;VIRTUAL SPY PAGE?
TROA U,(T2) ;PROPAGATE PHYSICAL PAGE NUMBER
PUSHJ P,PAGA10 ;IF VIRTUAL, HANDLE IT
JRST PAGA1A] ;MERGE WITH COMMON CODE
>
IFE FTPEEKSPY,<
MOVE T3,JBTSGN##(J)
>
JUMPE T3,PAGAC3 ;IF NO HI SEG AND NOT SPY PAGE, MUST BE WRITEABLE
PUSHJ P,TPNHS ;SEE IF PAGE IS IN HIGH SEG
TLOA U,(PA.GHI) ;IT IS, FLAG AS SUCH
JRST PAGAC3 ;LOW SEGMENT ERGO WRITEABLE
IFN FTPEEKSPY,<
TLNN T3,SPYSEG ;HIGH SEG ACTUALLY SPY SEG?
JRST PAGA1B ;NO, DON'T CHANGE
HRR U,T2 ;YES, PROPAGATE PHYSICAL PAGE NUMBER
PAGA1A: TLOA U,(PA.GSP!PA.CPO) ;YES, TELL USER
>
PAGA1B: TLNE T3,SHRSEG ;CAN PAGE BE SHARED WITH ANYONE ELSE?
TLO U,(PA.GSH!PA.CPO) ;YES, FLAG IT AS SHARABLE
TLNE T3,UWPOFF ;UWP OFF (I.E.,WRITE-ENABLED)?
PAGAC3: TLO U,(PA.WRT) ;YES, PAGE IS CONTAINED IN THE HIGH SEGMENT AND THE
; HIGH SEGMENT IS WRITABLE SO THE PAGE IS WRITABLE
GETPC T4,.JDAT+JOBPD1## ;PC OF THE PAGE ACCESSABILITY UUO
TLNN T4,(IC.LIP) ;UUO DONE FROM A CONCEALED PAGE?
JRST PAGAC5 ;YES, PAGE CAN BE READ
PUSHJ P,GTPME ;CONTENTS OF THE MAP
TDNE T2,[PM.PUB] ;A PUBLIC PAGE?
JRST PAGAC5 ;THEN THE PAGE CAN BE READ
TLZ T2,(PM.NAD) ;KEEP ONLY ADDRESS
TLNN U,(PA.OUT)
CAMN T2,[PM.ZER] ;IF NOT ABZ,
CAIA
JRST PAGAC4 ;PAGE CANNOT BE READ
SKIPLE T2,JBTSGN##(J) ;JOB HAVE A HI-SEG?
TLNN T2,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
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,JBTSGN##(J) ;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+1 ;EITHER 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-<UMAPSN+UMAPS>>/PAGSIZ##>-.UMORG+SECTAB>(T3)
HRRI T3,<UMAPSN+UMAPS>/PAGSIZ##-SECTAB(T3) ;YES, ASSUME IN UMAPSN
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 T2,NSHF!NSWP ;JOB MUST BE LOCKED
TDNN T2,JBTSTS##(J) ;IS IT?
JRST UIFERR ;NOT IMPLEMENTED FOR JOBS NOT LOCKED
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
>
;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,JBYLSA## ;FIRST PAGE OF JOB
MOVE T2,P2 ;SETUP ARGUMENTS TO ADPAGS
PUSHJ P,ADPAGS## ;ALLOCATE THE REQUIRED NUMBER OF PAGES
;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,GT4MR ;GET A 4 WORD CORE BLOCK FOR THIS FRAGMENT
JRST PAGE10 ;NO AVAILABLE
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,GT4MR ;ADD ANOTHER BLOCK TO THE FRAGMENT TABLA
JRST PAGEB9 ;NONE AVAILABLE
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: JUMPE P2,PAGEB8 ;GO IF NO I/O TO DO
PUSHJ P,PAGEIT ;PAGE THE PAGES IN
JRST PIOERR ;PAGING I/O ERROR
PAGEB8: SKIPN T1,.USNXP ;IF RANGE SPECIFIED GET HIGHEST PAGE
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
PAGEB9: POP P,(P) ;POP OFF JUNK
PAGE10: HALT . ;AND RECOVER (NOT IMPLIMENTED)
;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,SCDCHK##
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
PUSH P,T1 ;SAVE T1
PUSH P,T4 ;AND T4
PUSHJ P,DLTPGD ;RETURN THE DISK PAGE
POP P,T2 ;RESTORE PAGE NUMBER TO T2
POP P,T1 ;RESTORE T1
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) ;CORE ADDRESS
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,SCDCHK##
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
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
EXCH T1,(T3) ;MAKE IT FIRST PAGE ON "IN" QUEUE
SSX P2,MS.MEM ;PAGTAB SECTION
MOVEM T1,PAGTAB(P2) ;LINK PREVIOUS FIRST PAGE INTO QUEUE
HLLZS PT2TAB(P2) ;WE HAVE NO PREVIOUS
SSX T1,MS.MEM
TRNE T1,-1
HRRM P2,PT2TAB(T1) ;SET BACK LINK IF NOT LAST
AOS 1(T3) ;INCREMENT NUMBER OF PAGE ON "IN" QUEUE
POP P,T1 ;RESTORE VIRTUAL PAGE NUMBER
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
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
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,UPTIME##
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,UPTIME## ;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
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,777 ;(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,SCDCHK## ;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,JBYLSA## ;FIRST PAGE OF JOB
PUSHJ P,ADPAGS## ;ALLOCATE THE PAGES
;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 P3,T4 ;TPAHS DESTROYS T2
PUSHJ P,TPNHS ;A HIGH SEG PAGE?
SKIPG JBTSGN##(J) ;YES, NON-SHARABLE?
SKIPA T2,[PM.WRT!PM.AAB!PM.CSH!PM.PUB+PM.ZER] ;WRITABLE IF NOT HIGH SEG
MOVE T2,[PM.AAB!PM.CSH!PM.PUB+PM.ZER]
MOVEM T2,(P3) ;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,[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,SCDCHK## ;TO CHECK FOR 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)
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,SCDCHK##
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 SWAP IN
PUSHJ P,TPNHS ;SHARABLE HS PAGE?
SKIPG JBTSGN##(J) ;?
TDZA T2,T2
MOVEI T2,INSDWL-INSDWE
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
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 CRSMP4 ;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
CRSMP4:
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 CRSMP4 ;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,JBYLSA## ;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,JBYLSA##
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,SCDCHK## ;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 (0) ;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,JBTSGN##(J) ;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 (0) ;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,[UMAPSN+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: PUSHJ P,SAVE1## ;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
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
>
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
MOVE T2,T1 ;DESTINATION PAGE TO T2
POP P,T1 ;RESTORE SOURCE PAGE
GREMA1: POP P,T3 ;RESTORE THE NUMBER OF PAGES TO BE REMAPPED
MOVSI T4,(1B0) ;DON'T ALLOW A USER TO CREATE A SHARABLE
JUMPGE T3,GREMA2 ;APPEND STYLE REMAP?
MOVMS T3 ;MAYBE, MAKE T3 + IN ANY CASE
MOVEI P1,GREMA3 ;IF APPENDING, WE WILL EXIT HERE
SKIPE .USHSE ;DOES JOB ALREADY HAVE A HIGH SEG?
TLOA T4,(1B1) ;YES, INDICATE APPEND
GREMA2: MOVEI P1,SHARE1## ;IN WIN CASE, GO TO SHARE1 FOR NORMAL REMAP
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
AOS (P) ;SKIP RETURN
PJRST MAPHGH## ;JUST APPENDING
GREMA4: SKIPLE J,JBTSGN##(J) ;GET SEGMENT
TLNE J,SHRSEG ;CAN'T DO SHARABLE
JRST PSHERR ;..
MOVE T2,JBTADR##(J) ;GET HIGH SEG JBTADR
MOVE J,.USJOB
MOVE P1,.USHSE ;END OF CURRENT HIGH SEG
LSH P1,W2PLSH## ;CONVERT TO HIGHEST PAGE IN SEG
SUBI P1,-1(T1) ;FIRST PAGE TO DELETE
LSH P1,P2WLSH## ;MAKE SURE
SUB P1,.USHSS ;HE'S NOT TRYING TO DELETE THE LOW SEG TOO?
JUMPL P1,IALERR ;HE IS, LOSE
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,.USHSS
LDB T4,JBYSG2## ;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,JBYSG2## ;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 (0)
AOS -1(P) ;GOOD RETURN
HRRZ J,JBTSGN##(J)
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##
MOVE J,.USJOB
SKIPE R ;IF ZERO, STORE ZERO
AOS T1 ;# OF PAGES, NOT HIGHEST ADDRESSABLE
DPB T1,JBYHSS## ;..
HLRZ T1,R ;SET JOBHRL TOO
SKIPE T1
ADD T1,.USHSS ;..
HRRM T1,.JDAT+JOBHRL##
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,T1 ;FIX STACK
JRST IALERR] ;ILLEGAL ORDER IF NOT INCREASING
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,T1 ;FIX STACK
JRST IALERR] ;ILLEGAL ORDER IF NOT INCREASING
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,<MXSECN*<HLGPNO+1>+HLGPNO>
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,[UMAPSN+UMAPS]
CLRSP2: TDNE T2,(T3) ;SPY PAGE?
SETZM (T3) ;CLEAR MAPPING
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?
POPJ P, ;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
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?
IFE FTXMON,<
JRST MONVP4 ;NO, CHECK FOR DECNET SECTION
>
IFN FTXMON,<
JRST MONVPE ;NO, GIVE ERROR RETURN
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
MOVEM T1,.USCDB ;STASH IT AWAY
ADD T1,[XWD 1,0] ;MAP SECOND PAGE
MOVEM T1,.USCDB+1 ;STORE THAT, TOO
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
IFE FTXMON,<
MONVP4: CAIE T1,1 ;IS IT THE DECNET DATA SECTION?
JRST MONVPE ;NO, IT'S ILLEGAL
>
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
IFN FTXMON,<
MONVP5: CAIE T1,(UMAPSN) ;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
JUMPL T1,CHGSC3 ;DESTROY MAP
TLNN T1,(PG.SLO) ;CREATE MAP EX NIL?
AOJA T4,CHGSC2 ;YES, ONLY VERIFY RIGHT HALF
TLNN T1,<-1^!<<(PG.GAF!PG.SLO!PG.IDC)>!MXSECN>>;ANY ILLEGAL BITS?
CHGSC2: TRNE T1,<-1^!MXSECN> ;LEGAL SECTION #?
JRST ILSERR ;NO
TLO T1,400000 ;MAKE IFIW
AOS P1 ;ONE MORE CREATE TO PROCESS
PUSH P,T1 ;SAVE ARG
MOVSI T3,(1B0) ;TURN ON THAT THIS SECTION IS INDIRECT
MOVNI T1,(T1)
LSH T3,(T1) ;FIND RIGHT BIT
POP P,T1 ;RESTORE ARG
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
TLNN T1,(PG.SLO) ;WERE WE TO CREATE THIS FROM NOTHING?
TDZA P2,T3 ;SECTION WON'T BE INDIRECT LATER
CHGS2A: TDOA P2,T3 ;TURN IT ON FOR THIS SECTION
SOJA T4,CHGSC4 ;ONE LESS PAGE TO GET MAP FOR
HRRZM T1,.USTMU+1 ;SAVE THE TARGET SECTION
HLRZS T1 ;GET THE SECTION MAPPING TO
CHGS2B: ANDI T1,MXSECN ;SAVE ONLY SECTION #
MOVNS T1 ;-SECTION #
MOVSI T3,(1B0) ;MAKE BIT MASK AGAIN
LSH T3,(T1) ;...
MOVNS T1 ;SECTION # AGAIN
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: TRNE T1,-1 ;CAN'T DELETE SECTION 0
TRNE T1,<-1^!MXSECN> ;AND MUST BE A LEGAL SECTION
JRST ILSERR ;LOSE
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
CAMN T1,.USTMP ;TRYING TO DESTROY SECTION WITH ARGS?
JRST IALERR ;CAN'T
ADD P1,[1,,0] ;# OF SECTIONS BEING DESTROYED
MOVSI T3,(1B0) ;THIS SECTION IF INDIRECT, NO
MOVNI T1,(T1) ;LONGER EXISTS
LSH T3,(T1) ;...
ANDCAM T3,P2 ;...
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,FNDPDB## ;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,T1 ;SAVE MAPPING
LDB T2,JBYSG2## ;GET HIGH SEG SECTION #
CAIN T2,(T1) ;THIS SECTION?
S0PSHJ KILHGS## ;YES, KILL HIGH SEG THEN
HRRZS T1,(P) ;SECTION ARG AGAIN
PUSHJ P,KILSEC ;KILL ALL PAGES IN SECTION
LDB T1,NZSSCN##
SOS T1 ;DECREMENT MAP COUNT
DPB T1,NZSSCN##
POP P,T1 ;RETURN
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
MOVE T1,.USSPT ;ONE MO' TIME
CHGSC6: LDB T4,JBYSG2## ;GET HIGH SEG SECTION
CAMN T4,.USSPT ;THIS SECTION (ONLY IF INDIRECT)?
PUSHJ P,RSECT4 ;YES, GET REAL SECTION
JFCL ;IGNORE SKIP
DPB T4,JBYSG2## ;PUT IT IN INDEPENDENT SECTION
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
SKIPN P1 ;HAVE CORE?
SETO P1, ;NO, DON'T WAIT FOR IT
PUSHJ P,CRSMAP ;MAKE SECTION
SKIPN T1,.USSPT ;IN CASE SECTION 0
JRST CHGS10
SOS T1
IDIVI T1,^D36/UP.SCS ;GET COUNTER
LDB T4,PNTNZS(T2) ;GET IT
CAIN T1,UP.VRG ;JUST CREATED?
JRST CHGS10 ;YES
MOVE P2,T2
MOVE T1,.USSPT ;GET SECTION NUMBER
LDB T2,JBYSG2## ;GET HIGH SEG SECTION #
CAIN T2,(T1) ;THIS SECTION?
S0PSHJ KILHGS## ;YES, KILL HIGH SEG THEN
MOVE T1,.USSPT ;GET SECTION #
PUSHJ P,KILSEC ;EMPTY SECTION IF IDC AND IT EXISTED
MOVEI T4,UP.VRG
DPB T4,PNTNZS(P2) ;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,CPUN##(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,
;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,<PAGSIZ##-1> ;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 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: TRNN P2,PA.PCI ;CAN THE PAGE BE IN CORE?
JRST PLTSN8 ;YES, PROCEED
PUSH P,P1 ;NEED TO SAVE T2 HERE
MOVE P1,T2
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 ;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,TPNHS ;IS THE PAGE IN A HIGH SEGMENT?
TLO M,HSPAG ;YES, REMEMBER HIGH SEGMENT PAGE SEEN
MOVE T2,JBTSGN##(J) ;GET HIGH SEGMENT BITS
TLNE M,HSPAG ;WAS THIS A HIGH SEGMENT PAGE?
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
JRST PREPA2 ;STORE FOR NEXT CALL AND RETURN
NXTSPG: MOVE T1,.USNXP ;A RANGE OF PAGES SPECIFIED?
CAMN T1,[-1]
PJRST GETWS1## ;NO, GET NEXT ARGUMENT FROM LIST
AOBJN T1,.+1 ;YES, INCREMENT BOTH HALVES
JRST PREPA2 ;STORE FOR NEXT CALL AND RETURN
;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
PREPA1: TLNN T1,37777 ;PAGE PAIR?
SOSA T1 ;NO, BACK UP THE PAGE NUMBER
SUB T1,[1,,1] ;BACK UP 1 PAGE
PREPA2: 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
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,777 ;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
DPB P2,JBYHSS## ;YES, STORE NEW HIGH SEGMENT SIZE
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
MOVE T2,.USHSS ;IS THERE A HI SEG?
SKIPN .USHSE
MOVSI T2,1 ;NO, MAKE SURE TEST WILL FAIL
LSH T2,W2PLSH## ;COMPUTE START PAGE OF HI 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
;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,[-1,,MPGSIZ##]
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
;INSDSK DECIDES ON INSDWL OR INSDWE DEPENDING ON THE CONTENTS OF J (HIGH
;SEG CALLS INSDWL)
INSDSK: CAIG J,JOBMAX
JRST INSDWE
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
CLRPGT (0,.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 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
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, OR CPOPJ WITH T4 CLEARED
;IF REAL SECTION IN SECTION 0. STARTS WITH C(T4) AND IS ASSUMED TO BE
;ZERO IF IT IS 0 OR NEGATIVE. USES T2.
RSECT4::SKIPG T4 ;NO, SEE IF IT IS
TDZA T4,T4 ;WANTS SECTION 0
SKIPN T2,.UPMP+SECTAB(T4) ;GET SECTION POINTER
POPJ P, ;RETURN SAYING S0 OR 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,RSECT4 ;AND CHECK IT OUT
POPJ P, ;UNLESS IT'S 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##,DEBUG,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)
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
JSP 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: 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 #
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 RMVPG2 ;NO, JUST A GARDEN VARIETY PAGE
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,.UPBTS ;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,.UPBTS ;IF SO,
IORM T2,MEMTAB(T4)
SETZM (P) ;INDICATE NO PAGE TO GIVE BACK
JRST T2POPJ## ;AND GIVE PAGE ON DISK RETURN
RMVPG2: SETZ T3, ;SO IPCSER KNOWS IT'S NOT ON A QUEUE
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
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
;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
RMVPFQ: SE1ENT ;ENTER SECTION 1
SOSL 1(T3) ;DECREMENT COUNT OF PAGES ON QUEUE
SKIPN T4,(T3) ;ANY PAGES ON THE QUEUE
STOPCD CPOPJ##,DEBUG,PQW, ;++PAGE QUEUE WRONG
CAME 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
MOVEM 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
TPWHS: SKIPLE T2,JBTSGN##(J) ;DOES THIS JOB HAVE A REAL HIGH SEGMENT?
TLNN T2,UWPOFF ;IS WRITE PROTECT OFF FOR THE HIGH SEGMENT?
JRST CPOPJ1## ;NO, PAGE ISN'T IN A WRITABLE HIGH SEGMENT
IFN FTPEEKSPY,<
PUSHJ P,TSSPT ;A SPY PAGE?
JRST TPAHS ;NO
JRST CPOPJ1##
>
IFE FTPEEKSPY,<
JRST TPAHS ;TEST TO SEE IF THE PAGE IS IN THE HIGH SEGMENT
>
TPSHS:: MOVE T2,JBTSGN##(J) ;HIGH SEGMENT NUMBER PLUS HIGH SEGMENT BITS
TLNN T2,SHRSEG!SPYSEG;SHARABLE SEGMENT OR SPY SEGMENT?
JRST CPOPJ1## ;NO, PAGE IS NOT IN A SPY OR SHR SEG
TPAHS:: PUSH P,T1 ;SAVE THE VIRTUAL PAGE NUMBER
PUSHJ P,HSVAD## ;GET STARTING AND ENDING VIRTUAL ADDRESSES
; OF THE HIGH SEGMENT
HRRZS J ;CLEAR JUNK
LSHC T1,W2PLSH## ;CONVERT TO STARTING AND ENDING PAGE NUMBERS
HRRZ T4,(P) ;VIRTUAL PAGE IN QUESTION
CAIL T4,(T2) ;BELOW THE START OF THE HIGH SEGMENT?
CAILE T4,(T1) ;OR ABOVE THE TOP OF THE HIGH SEGMENT
AOS -1(P) ;PAGE ISN'T IN THE HIGH SEGMENT
PJRST TPOPJ## ;RESTORE THE VIRTUAL PAGE NUMBER AND RETURN
;SUBROUTINE TO CHECK SECTION # AGAINST JBYSG2 AS WELL AS THE
;CHECKS TPAHS/TPSHS DOES. SAME RETURNS AS TPAHS
TPNSHS::
PUSHJ P,SAVT##
MOVEI T3,TPSHS
JRST TPNHS1
TPNHS:: PUSHJ P,SAVT##
MOVEI T3,TPAHS
TPNHS1: LDB T4,[POINT 5,T1,26]
PUSHJ P,RSECT4 ;RESOLVE SECTION # TO INDEPENDENT SECTION
JFCL ;IGNORE POSSIBLE SKIP RETURN
LDB T2,JBYSG2## ;GET HI SEG SECTION #
CAIE T2,(T4) ;THIS SECTION #
JRST CPOPJ1## ;NO, NOT IN HIGH SEG
ANDI T1,HLGPNO ;CLEAR SECTION #
PJRST (T3) ;AND CHECK
;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
PUSHJ P,TPNHS ;IS THIS PAGE IN THE HIGH SEGMENT?
INCHJA: SKIPG JBTSGN##(J) ;YES, IS THERE A HIGH SEGMENT?
POPJ P, ;NO, NOTHING TO DO
MOVSI T4,(UP.CTX) ;GET CONTEXT SERVICE BIT
TDNE T4,.USBTS ;DELETING A HISEG FOR CTXSER?
POPJ P, ;YES, DON'T TOUCH THE PAGE COUNT
HRRZ T4,JBTSGN##(J) ;NO, GET HIGH SEGMENT NUMBER
ADDM T3,JBTSWP##(T4) ;INCREMENT OR DECREMENT PAGE COUNT
JUMPL T3,CPOPJ## ;RETURN IF REMOVING A PAGE FROM CORE
PUSH P,T1
PUSH P,T4
PUSHJ P,SCWEXO##
POP P,T4
POP P,T1
LDB T4,[POINT 9,JBTUPM##(T4),8] ;FIRST VIRTUAL PAGE IN THE HI-SEG
MAPHI:: LDB T3,JBYSG2## ;SECTION OF HIGH SEG
LSH T3,S2PLSH## ;CONVERT TO SECTION
IORI T4,(T3)
PUSHJ P,GTPM4 ;YES, GET FIRST PHYSICAL PAGE IN HI SEG
HRLI T4,(<PM.DCD>B2+PM.WRT+PM.PUB)
MOVEM T4,.UPMP+.UMVJD
POPJ P, ;AND RETURN
;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
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
SKIPLE J,JBTSGN##(J) ;DOES JOB HAVE A REAL
TLNE J,SHRSEG ;NON-SHARABLE HI SEG
JRST JPOPJ## ;NO
HRRZS J ;IN CASE S1
MOVE T1,.USHSS ;GET START OF HI SEG
LSH T1,W2PLSH## ;CVT TO PAGE #
PUSHJ P,TSWST ;IS IT IN THE WORKING SET?
TDZA T2,T2 ;NO, STORE ZERO IN JBTHSA
PUSHJ P,GTPME ;GET CONTENTS OF THAT SLOT IF IN WS
DPB T2,JBYHSA## ;STORE IN JBTHSA
JRST JPOPJ## ;AND RETURN
;SUBROUTINE TO WAIT FOR MIGRAT TO PASS US
;CALLED BY IPCFS
;USES T1
MIGWAT:
IPMWAT::PUSH P,J ;SAVE J
IPMWT1: HRRZ T1,MIGRAT## ;MIGRATE IN PROGRESS?
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: SKIPE P2,.UPMP+SECTAB(P1) ;SECTION EXIST?
TLNE P2,(<PM.ACD^!PM.DCD>B2) ;INDIRECT OR IMMEDIATE?
JRST KILNZ3 ;NOTHING TO DO
MOVEI T1,(P1)
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 (0) ;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##
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##
PNTCNT: POINT 18,T1,17
POINT 14,T1,13
POINT 14,T1,13
MAXCNT: 400000+T1,,-1
400000+T1,,37
400000+T1,,3
PNTNZS: POINT UP.SCS,.USSCT(T1),<UP.SCS-1>
POINT UP.SCS,.USSCT(T1),<2*UP.SCS-1>
$LIT
$HIGH
VMEND: END