TITLE VMSER - VIRTUAL MEMORY SERVICE ROUTINE V4636 SUBTTL J. FLEMMING, T. WACHS 5 MAR 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,4636 ;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.SPN-1> ;POINTER TO NEXT NVPNP4::POINT P2.SPN,PT2TAB(P4),<^L+P2.SPN-1> ;POINTER TO NEXT NVPNT1::POINT P2.SPN,PT2TAB(T1),<^L+P2.SPN-1> ;POINTER TO NEXT NVPNT2::POINT P2.SPN,PT2TAB(T2),<^L+P2.SPN-1> ;POINTER TO NEXT NVPNF:: POINT P2.SPN,PT2TAB(F),<^L+P2.SPN-1> ;POINTER TO NEXT NVPNR:: POINT P2.SPN,PT2TAB(R),<^L+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,KONCAM##(J) 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 IFE 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,KONCAM##(J) ;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 HRRZ T3,UNIKON##(T3) MOVE T3,KONCAM##(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,CHKCSH## ;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 S,IO 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.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.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(P) PUSHJ P,GETVPN EXCH P1,-10(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.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.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 ; 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 ; ; 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.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.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.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,() ;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,() ;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.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.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,SAVE4## ;SAVE ACS MOVE P1,J ;SAVE J DMOVE P2,T1 ;SAVE DISK ADDRESS AND MEMTAB INDEX EXCH T1,MEMTAB(T2) ;STORE DISK ADDRESS, GET JOB NUMBER+VIRTUAL PAGE NUMBER TLZE T1,(MT.IPC) ;AN IPCF PAGE? JRST STODIP ;YES, HANDLE IT MOVE P4,T1 ;SAVE THAT LDB J,[POINT MT.SJB,P4,<^L+MT.SJB-1>] ;GET JOB NUMBER OF JOB PAGE BELONGS TO PUSHJ P,SVEUB## ;MAKE MAPS ADDRESSABLE LDB T1,[POINT ,P4,<^L+MT.SPN+MT.SSN-1>] ;GET PAGE NUMBER PUSHJ P,GTPME ;GET MAP CONTENTS AND T2,[PM.BTS] ;EXTRACT ACCESS BITS IOR T2,MEMTAB(P3) ;ADD IN DISK ADDRESS MOVEM T2,(T4) ;STORE IT IN THE MAP DPB P4,[POINT P2.SPN,PT2TAB(P3),<^L+P2.SPN-1>] ;REMEMBER ;WHERE IT CAME FROM DPB J,[POINT MT.SJB,MEMTAB(P3),<^L+MT.SJB-1>] ;AND SET JOB # STODA1: MOVE J,P1 ;RESTORE J STODA2: DMOVE T1,P2 ;AND T1, T2 POPJ P, ;AND RETURN ;HERE FOR IPCF PAGE STODIP: DPB T1,[POINT P2.SPN,PT2TAB(T2),<^L+P2.SPN-1>] ;SET LOW ;ORDER BITS ROT T1,-P2.SPN ;DEPOSIT DPB T1,[POINT <^D18-P2.SPN>,MEMTAB(T2),<^L+MT.SJB-1>] ;HIGH ORDER BITS ROT T1,P2.SPN ;PUT BACK MOVSI P4,(MT.IPC) ;LEAVE MT.IPC ON TOO IORM P4,MEMTAB(T2) 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 .CREF MT.IPA ;IPCF PACKET ADDRESS 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,SAVE4## ;SAVE WORLD DMOVE P2,T1 ;MOVE TO A BETTER PLACE EXCH T1,MEMTAB(T2) ;SAVE DISK ADDR, GET WHERE TO PUT IT TLZE T1,(MT.IPC) ;IPCF PAGE? JRST STODIP ;YES, DO THAT MOVE P4,T1 ;LOCATION WORD LDB T1,[POINT MT.SJB,P4,<^L+MT.SJB-1>] ;JOB IT GOES IN DPB T1,[POINT MT.SJB,MEMTAB(P3),<^L+MT.SJB-1>] ;PRESERVE HRRZ T2,JBTUPM##(T1) ;UPMP FOR THAT JOB HRLI T2,(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 MT.SSN,P4,<^L+MT.SSN-1>] ;SECTION # PAGE IS IN HRR T2,.TEMP+SECTAB(T1) ;SECTION MAP POINTER FOR THAT SECTION TLZ T2,(PM.CSH) ;BE SURE IT'S OFF MOVEM T2,.UPMP+.UMTMP ;MAP THAT PUSHJ P,CLPTZO EXP .TEMP ;CLEAR PAGING LDB T1,[POINT MT.SPN,P4,<^L+MT.SPN-1>] ;PAGE TO CHANGE MOVSI T2,(PM.BTS) ;GET BITS ANDM T2,.TEMP(T1) ;SAVE ONLY THEM MOVE T2,MEMTAB(P3) ;GET DISK ADDRESS TLZ T2,(-1^!MT.DAD) ;KEEP ONLY ADDRESS IORM T2,.TEMP(T1) ;AND PUT IT IN DPB P4,[POINT P2.SPN,PT2TAB(P3),<^L+P2.SPN-1>] 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.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.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.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.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 LDB T1,[POINT P2.SPN,PT2TAB(P1),<^L+P2.SPN-1>] ;GET "VPN" MOVSI T3,(MT.GPB) ;REALLY NEED THIS PAGE? TDNE T3,MEMTAB(P1) ;? JRST [MOVEI T3,PAGIPQ## ;NO, JUST FLUSH IT HRRZ T2,P1 ;... HRRZ P1,PAGTAB(P1) ;GET SUCCESSOR (IF ANY) PUSHJ P,RMVPFQ ;REMOVE THE PAGE JRST IP2ERX ] ;CONTINUE MOVSI T3,(MT.IPC) ;IPCF PAGE? TDNE T3,MEMTAB(P1) ;IS IT? JRST IP2EIP ;YES, TREAT DIFFERENTLY DPB T1,[POINT MT.SPN+MT.SSN,MEMTAB(P1),<^L+MT.SPN+MT.SSN-1>] IP2ERE: HRRZ P1,PAGTAB(P1) ;NEXT PAGE ON IP QUEUE IP2ERX: JUMPN P1,IP2ERR ;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 IP2EIP: LDB J,[POINT MT.SJB,MEMTAB(P1),<^L+MT.SJB-1>] LSH J,P2.SPN ;SHIFT IOR T1,J ;FULL 18-BIT ADDR HRRM T1,MEMTAB(P1) ;SAVE IPCF ADDR SETZ J, DPB J,[POINT MT.SJB,MEMTAB(P1),<^L+MT.SJB-1>] JRST IP2ERE ;CONTINUE WITH QUEUE ;SUBROUTINE TO MAKE AN ENTRY IN SWPLST ;CALLING SEQUENCE: ; ; MOVE T1,SWPLST ENTRY ; PUSHJ P,MAKSLE ;ALWAYS RETURNS CPOPJ 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 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++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##>-(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,(B2) ;ACCESS ALLOWED ON? TLZA F,(PM.NAD) ;YES, CLEAR BITS TLZA F,(>) ;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,(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,- ;YES AOBJP P4,SETO24 ;TIME TO DO SECTION 0 SETO23: SKIPE T4,.UPMP+SECTAB(P4);SAVE A LITTLE TIME IN THIS TLNE T4,(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,(B2) TLZ J,(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.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,(B2+PM.WRT+PM.PUB+PM.COR+IFE FTMP,) 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,(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,(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,(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.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 JUMPE T1,JOBNP1 ;CHECK IF IT EXISTS JRST CPOPJ1## ;NOT ON THE QUEUE ;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,MEMTAB(T1) ;YES, MUST PROCESS IT JRST JOBFN3 ;NO PAGES ON IN QUEUE, PROCEED ANDI T1,MT.VSN+MT.VPN ;SAVE JUST 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,MEMTAB(T1) ;YES, MUST PROCESS IT JRST JOBFN6 ;NO MORE HERE ANDI T1,MT.VSN+MT.VPN 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,(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 PUSHJ P,SCPAGS## ;FIND THE LAST PAGE ALLOCATED TO THIS JOB MOVE T2,P2 ;NUMBER OF PAGES REQUESTED 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,(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 IFE FTXMON,< SKIPE R ;ANY SECTION NUMBER? PUSHJ P,SVDCN## ;YES, ENTER DECNET CONTEXT >; END IFE FTXMON 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,(B2+PM.WRT+PM.PUB+PM.COR) MOVEM T2,.UPMP+.UMTMP CLRPGT (0) PUSH P,T2 ;SAVE FOR LATER MOVSI T1,- ;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,[] ;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,(B2+PM.WRT+PM.CSH) ;ACCESSIBLE, WRITABLE, CACHED IOR P3,.CPKPM## ;ALSO LITE "KEEP ME" IF THERE IS AN MCA25 HRRI P2,(T1) ;OFFSET INTO SECTION TABLE OR MAP 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: 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::SKIPA T1,[400000,,(MS.DCN)] ;"DECNET" CORE FOR THE KS GFWNZO::SKIPA T1,[400000,,0] ;"ONCE-ONLY" CORE FOR THE KS PUSHJ P,SVDCN## ;IF DECNET, POINT TO DECNET CORE > 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, ;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 IFE FTXMON,< GVFNZD::PUSHJ P,SAVR## ;SAVE R MOVEI R,(MS.DCN) ;FLAG DECNET CONTEXT SETZ T4, ;BUT STILL S0 PUSHJ P,SVDCN## ;MAP DECNET JRST GVFWDC GVFNZO:: > ;END IFE FTXMON IFN FTXMON,< 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) 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 FTMP,< SSXE T3,(R) ;NO, RELOCATE > IFE FTMP,< 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,* ;OK? CAILE T3,* 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,* HRLI T2,* 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:: 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,(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 ;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) ;SHAD