Google
 

Trailing-Edge - PDP-10 Archives - bb-jr93e-bb - 7,6/ap016/lokcon.x16
There are 2 other files named lokcon.x16 in the archive. Click here to see a list.
TITLE LOKCON -  MODULE FOR LOCKING JOBS IN CORE - V302
SUBTTL J. FLEMMING  TS     22 JUL 86
	SEARCH	F,S
	$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 VKILOK,302			;PUT VERSION NUMBER IN STORAGE MAP

ENTRY	LOKCON			;ENTRY POINT SYMBOL SO LOADER WILL LOAD LOKCON
				; IN A LIBRARY SEARCH

LOKCON::;ENTRY POINT SYMBOL TO CAUSE LOADING OF LOKCON
SUBTTL SWAP - USER PROGRAM SWAPPING ROUTINES

;ROUTINE TO MOVE A JOB TO A PREDETERMINED PLACE IN CORE AND LOCK IT THERE
;CALLING SEQUENCE:
;	HRRZ	AC,JOB NUMBER
;	HRL	AC,HIGH SEGMENT NUMBER
;	MOVSM	AC,LOCK
;OR IF LOW SEGMENT ONLY JOB
;	HRRZ	AC,JOB NUMBER
;	MOVEM	AC,LOCK
;AND
;	MOVEI	P1,LOK
;	IORM	P1,JBTSTS(AC)	;SO SCHEDULAR WON'T RUN THE JOB
;AND
;	MOVE	AC,DESIRED PROTECTION/RELOCATION FOR HIGH SEGMENT OR JOB IF NONE
;	MOVEM	AC,LOKREL
;	PUSHJ	P,WSCHED
;RETURN HERE WHEN JOB (BOTH LOW AND HIGH SEGMENTS) ARE IN PLACE AND LOCKED
;NOTE:	LOW SEGMENT GOES
;	ABOVE THE HIGH SEGMENT
;
;CALLED FROM SCHED WHEN SWAPPER IS IDLE

LKERR1==1
LKERR2==2
LKERR3==3
LKERR4==4
LKERR5==5
LKERR6==6

LKB==1
LKEB==2
LKPB==4
LKCB==10
LOCK0::	SE1ENT			;LOCK MUST RUN IN SECTION 1, SINCE PAGTAB AND
				;MEMTAB SIT IN ANOTHER SECTION (MS.MEM)
	PUSHJ	P,BPSLST##	;MAKE EVERYTHING ON PAGE QUEUES GO OUT
	SKIPE	PAGIPQ##	;I/O IN PROGRESS NOW?
	POPJ	P,		;YES, WAIT UNTIL ITS DONE
	PUSHJ	P,FLSOPQ##	;FLUSH "OUT" QUEUE - PUT PAGES ON FREE CORE LIST
;HERE WHEN ALL OF THE PAGE QUEUES ARE EMPTY - ALL PAGES ON FREE CORE LIST
	MOVE	J,LOCK##	;-1 IF SETTING MEMORY OFF LINE
	AOJE	J,[HLRZ P2,LOKREL##
		   SKIPN MOFLPG##
		   JRST LOCK2	;GO IF NOT SETTING MONITOR MEMORY OFF-LINE
		   LDB P2,[POINT 14,MEMSIZ##,26]
		   LDB P3,[POINT 9,SYSSIZ##,26]
		   SUB P2,P3	;FORCE EVERYTHING OUT IF SETTING MONITOR MEMORY OFF
		   JRST LOCK3]

	HRRZ	J,LOCK##	;SEGMENT NUMBER OF SEGMENT TO BE LOCKED
LOCK1:	LDB	P2,IMGIN##	;NUMBER OF PAGES IN THE SEGMENT
	CAILE	J,JOBMAX##	;IS THIS A LOW SEGMENT?
	JRST	LOCK2
	MOVSI	T1,(JS.SIP)	;SWAPPING COULD BE IN PROGRESS
	TDNE	T1,JBTST2##(J)	;IS IT?
	POPJ	P,		;YES,WAIT UNTIL SWAPPING I/O IS DONE
	LDB	T1,NFYPGS##
	ADD	P2,T1		;YES, ACCOUNT FOR THE UPMP SIZE
	LDB	T1,NZSSCN##	;AND NZS MAPS
	ADD	P2,T1
LOCK2:	HRRZ	P3,LOKREL##	;PAGE NUMBER OF STARTING PAGE THIS SEGMENT
				; IS TO BE LOCKED IN
LOCK3:	SKIPGE	T1,@[IW MS.MEM,PAGTAB(P3)] ;PAGE ON THE FREE CORE LIST?
	JRST	LOCK13		;YES, LOOP ON
IFN FTIPCF,<
	TLNE	T1,IPCBIT	;AN IPCF PAGE?
	JRST	DELIPP		;YES, SWAP IT OUT
>
	SKIPGE	LOCK##		;SETTING MEMORY OFF-LINE?
	TLNN	T1,LKBITS	;YES, IGNORE MONITOR AND NON-EXISTANT PAGES
	SKIPA	P1,P3		;NO, PAGE NUMBER TO P1
	JRST	LOCK13		;LOOK AT THE NEXT PAGE

	LSH	P1,P2WLSH##	;CONVERT PAGE NUMBER TO AN ABSOLUTE ADDRESS
	PUSHJ	P,CPIASN##	;FIND THE SEGMENT NUMBER OF THE SEGMENT
				; CONTAINING THIS PAGE
	  STOPCD	.,STOP,SNF,	;++SEGMENT NOT FOUND
	MOVMS	J
LOCK4:	HRRZ	T1,LOCK##	;T1 = SEGMENT NUMBER OF SEGMENT BEING LOCKED
	CAIN	T1,(J)		;PAGE FOUND CONTAINED IN SEGMENT BEING LOCKED?
	JRST	LOCK13		;YES, NO ACTION NECESSARY
	CAIG	J,JOBMAX##	;IS THE SEGMENT CONTAINING THE PAGE WHICH
				; MUST BE MOVED A HIGH SEGMENT?
	JRST	LOCK10		;NO, JUST SWAP THIS SEGMENT OUT
	MOVE	P1,JBTSTS##(J)	;P1 = INCORE COUNT FOR THIS HIGH SEGMENT
	TLNE	P1,SWP		;ALREADY SWAPPING THIS HI SEG OUT?
	POPJ	P,		;YES, GO AWAY UNTIL THE SWAP COMPLETES
	TRNE	P1,ICCMSK	;IS THIS A DORMANT OR IDLE HIGH SEGMENT?
	JRST	LOCK6		;NO, MUST SWAP OUT THE LOW SEGMENTS SHARING
				; IT TO MAKE IT GO AWAY
LOCK5:	S0PSHJ	FREC4##		;ITS DORMANT OR IDLE - GO DELETE IT FROM CORE
	 S0JRST	FORIDL##	;IDLE WITH NO COPY ON THE DISK - WRITE ENABLED
	  JRST	LOCK0		;THE SEGMENT HAS BEEN DELETED FROM CORE - TRY AGAIN
LOCK6:	MOVE	T2,J		;SAVE HIGH SEGMENT NUMBER
	MOVE	J,HIGHJB##	;FIND A JOB SHARING IT
LOCK7:	SKIPLE	T1,JBTSGN##(J)	;THIS JOB HAVE A HIGH SEGMENT?
	CAIE	T2,(T1)		;YES, IS IT THE ONE WE WANT TO SWAP?
	JRST	LOCK9		;NO, LOOK AT NEXT JOB
	SKIPE	JBTADR##(J)	;IS JOB IN CORE?
	JRST	LOCK8		;YES, GO SEE IF IT CAN BE SWAPPED OUT
	MOVE	T2,J		;SAVE JOB NUMBER BEFORE CALLING DECCNT
	EXCH	J,T1		;J=HIGH SEG T1=JOB
	S0PSHJ	DECCNT##	;MAKE SURE IN-CORE COUNT IS DECREMENTED
	  JFCL			;ALREADY DECREMENTED OR JUST WENT TO ZERO
	HRRZS	J		;GET RID OF HIGH SEGMENT FLAGS
	JUMPE	T1,LOCK5	;NO MORE JOBS SO SWAP OUT HIGH SEG
	EXCH	J,T2		;GET READY TO LOOK AT NEXT JOB
	JRST	LOCK9		;GO DO IT
LOCK8:	MOVE	T1,JBTSTS##(J)	;GET JOB STATUS
	TLCE	T1,SWP!NSWP	;IS IT LOCKED AND SWAPPED?
	TLNE	T1,SWP!NSWP	;IF BOTH, SWAPPING IT WON'T HELP
	CAIA
	JRST	LOCK9		;SO LOOK AT NEXT JOB
	TRNE	P1,ICCMSK-1	;IN CORE COUNT = 1?
	CAME	J,LOCK##	;IF NOT, IS THIS THE JOB WE'RE LOCKING?
	JRST	LOCK11		;NO, SWAP OUT THE JOB
LOCK9:	SOJG	J,LOCK7		;LOOK AT NEXT JOB

	STOPCD	.,STOP,SSO,	;++SEGMENT SWAPPED OUT
LOCK10:
IFN FTMP,<
	PUSHJ	P,ANYRUN##	;RUNNING ON CPU1?
	  JRST	LOCK12		;YES
>
LOCK11:	MOVSI	T1,(JS.SIP)	;SWAPPING I/O IN PROGRESS BIT
	TDNE	T1,JBTST2##(J)	;JOB CURRENTLY BEING SWAPPED?
	POPJ	P,		;YES, WAIT FOR I/O TO COMPLETE
	S0JRST	FORCE0##	;NO, SWAP HIM NOW
LOCK12:	MOVEM	J,SW0JOB##	;TELL CPU1 TO STOP RUNNING THE JOB
	POPJ	P,		;AND RETURN
LOCK13:	AOS	P3		;NEXT PHYSICAL PAGE WHICH MUST BE FREED
	SOJG	P2,LOCK3	;LOOP UNTIL ALL NECESSARY PAGES ARE AVAILABLE
	SKIPGE	T1,LOCK##	;LOCK IS -1 IF SETTING MEMORY OFF
	AOJE	T1,SETMFL	;GO MOVE THE MONITOR AND SET MEMORY OFF
	HRRZ	J,LOCK##	;SEGMENT NUMBER OF SEGMENT BEING LOCKED
	SKIPN	JBTADR##(J)	;IS THIS SEGMENT IN CORE?
	JRST	[HRRZ J,LASLOK## ;NO, GO CAUSE IT TO BE SWAPPED IN
		 S0JRST FIT1##]

;ALLOCATE CORE, BLT SEGMENT INTO PLACE, AND LOCK IT
	CAILE	J,JOBMAX##	;IS IT A HIGH SEGMENT?
	JRST	LOCK14		;NO, DON'T NEED TO ADDRESS THE UPMP
	CAME	J,.CPJOB##	;IS THIS THE CURRENT JOB? IF SO UPMP IS ADDRESSABLE
	PUSHJ	P,SVEUB##	;MAKE THE UPMP ADDRESSABLE
LOCK14:	MOVE	R,JBTADR##(J)	;ANYACT REQUIRES THAT R BE SETUP
	S0PSHJ	ANYACT##	;ANY ACTIVE I/O?
	  POPJ	P,		;YES, TRY AGAIN NEXT CLOCK TICK
	HRRZ	J,LOCK##	;SEGMENT NUMBER OF SEGMENT BEING LOCKED
	PUSHJ	P,CLRLOQ	;ALL PAGES AVAILABLE, MOVE LOKCON'S
				;QUEUE TO THE FREE QUEUE
	MOVEI	P1,0		;P1 = RELATIVE PAGE NUMBER WITHIN THE SEGMENT
				; START AT RELATIVE PAGE ZERO
	HRRZ	P2,LOKREL##	;P2 = DESIRED PHYSICAL PAGE NUMBER
	CAILE	J,JOBMAX##	;IS THIS SEGMENT A LOW SEGMENT?
	JRST	LOCK16		;NO, NEEDN'T WORRY ABOUT MOVING THE UPMP
	HRRZ	T1,JBTUPM##(J)	;PAGE NUMBER OF UPMP
	PUSHJ	P,SETMAP
	PUSHJ	P,SCPAGS##	;FIND LAST PAGE IN PAGTAB CHAIN
	HRRZ	T2,JBTUPM##(J)	;PAGE NUMBER OF PROCESS TABLE
	HRRZ	T3,@[IW MS.MEM,PAGTAB(T2)] ;PAGE MAP PAGE
	HRRM	T3,@[IW MS.MEM,PAGTAB(T1)] ;LINK PAGE MAP PAGE TO THE END
					      ;OF PAGTAB CHAIN
	HRRM	T1,@[IW MS.MEM,PT2TAB(T3)] ;FIX UP PT2TAB ALSO
	HLLZS	@[IW MS.MEM,PAGTAB(T2)] ;UNLINK IT FROM PROCESS TABLE CHAIN

	HRRZ	T1,JBTUPM##(J)
	LDB	P3,JBYLSA##	;PAGE NUMBER OF FIRST PAGE OF THE JOB
	MOVEI	M,.UPMVP/PAGSIZ## ;TELL FIXMAP TO CALL NXTWSB
	CONO	PI,PI.OFF	;TURN OFF THE PIS WHILE CONFUSION REIGNS
	CAIN	T1,(P2)		;IS THE UPMP ALREADY IN PLACE?
	TDZA	P3,P3		;YES, DOESN'T NEED TO BE MOVED
	PUSHJ	P,PAGMOV	;MOVE THE UPMP TO THE DESIRED POSITION
	MOVSI	T1,(P2.LIP)	;IN CASE PAGMOVE NOT CALLED
	ANDCAM	T1,@[IW MS.MEM,PT2TAB(P2)] ;CLEAR P2.LIP ON THIS PAGE
	MOVE	T1,P2
	HRLI	T1,(<PM.DCD>B2+PM.WRT+PM.PUB)
	MOVEM	T1,.EUPMP+.UMUPT
IFN FTMP,<
	TLO	T1,(PM.CSH)	;TURN CACHE ON IF FTMP
>
	MOVEM	T1,.EUPMP+.UMUUP

	CAIE	P2,(P3)		;WAS THE UPMP EXCHANGED WITH THE FIRST PAGE
				; OF THE LOW SEGMENT (PAGE CONTAINING JOB
				; DATA AREA)?
	JRST	LOCK15		;NO
	MOVE	T1,.CPMAP##
	MOVE	T1,.ECKSM/PAGSIZ##(T1)
				;(PM.CSH OFF ALREADY)
	MOVEM	T1,.EUPMP+.UMJDT

	DPB	T1,JBYLSA##
LOCK15:	MOVEI	T1,UPMPSZ##	;+ SIZE OF THE UPMP IN THE RIGHT HALF
	ADDM	T1,LOKREL##	;UPDATE LOKREL TO REFLECT THE FACT THAT
				; THE UPMP IS IN PLACE AND LOCKED
	HLLZS	@[IW MS.MEM,PAGTAB(P2)] ;SIGNAL ONLY THIS PAGE IS ALLOCATED
	MOVSI	T1,LOKPHB	;AND INDICATE THAT THE UPMP IS LOCKED
	IORM	T1,@[IW MS.MEM,PAGTAB(P2)] ; IN PHYSICAL MEMORY
	HRRM	P2,JBTUPM##(J)	;STORE THE NEW PAGE NUMBER OF THE UPMP
	PUSHJ	P,STEUB##	;AND MAKE THE UPMP ADDRESSABLE THROUGH
				; THE PER PROCESS MAP (CLEAR THE AM)
	CONO	PI,PI.ON	;OK TO TURN ON PIS NOW
	HRRZ	P2,LOKREL##	;P2 = PHYSICAL PAGE WHERE FIRST PAGE OF THE
				; LOW SEGMENT SHOULD GO
LOCK16:	LDB	P3,IMGIN##	;NUMBER OF PAGES IN THE SEGMENT
	CAILE	J,JOBMAX##
	JRST	LOCK17
	LDB	T1,NFYPGS##
	ADDI	P3,-UPMPSZ##(T1)
	LDB	T1,NZSSCN##
	ADDI	P3,(T1)
	SETZM	.USSPT
	MOVSI	P4,400000
LOC16A:	PUSHJ	P,NXTWSB##
	JRST	LOC19D
LOCK17:	MOVE	T2,P1
	PUSHJ	P,SNPAGS##
	CAIE	T1,(P2)
	PUSHJ	P,PAGMOV
	JUMPN	P1,LOCK19
	DPB	P2,JBYHSA##
	JRST	LOCK19
LOCK18:	CAIN	T4,.UPMP+.UMUPT	;IS THIS THE UPT
	JRST	LOC19C		;YES, ALREADY DONE
	PUSHJ	P,PGMOVE
	JUMPN	P1,LOCK19
	MOVE	T4,P2
	HRLI	T4,(<PM.DCD>B2+PM.WRT+PM.PUB)
	MOVEM	T4,.UPMP+.UMJDT

	DPB	T4,JBYLSA##
	PUSHJ	P,NEWMAP	;CLEAR THE AM SO NEW MAPPING IS IN EFFECT
LOCK19:	MOVSI	T4,LOKPHB	;INDICATE THIS PAGE IS LOCKED IN PHYSICAL MEMORY
	SUBI	P2,1		;BACK DOWN TEMPORARILY
	SKIPE	P1		;SKIP IF FIRST PAGE OF THE SEGMENT
	IORM	T4,@[IW MS.MEM,PAGTAB(P2)] ; CONTIGIOUSLY
	ADDI	P1,1		;NEXT RELATIVE PAGE WITHIN THE SEGMENT
	ADDI	P2,2		;STEP TO NEXT TARGET PAGE, AND BACK UP AGAIN
	SOJE	P3,LOCK20
	CAILE	J,JOBMAX##
	JRST	LOCK17
	PUSHJ	P,FPNSHS
LOC19C:	PUSHJ	P,NXTWS3##
LOC19D:	MOVEM	M,.USTMP	;SAVE ACS FOR FIXMAP
	DMOVEM	T1,.USTMP+1
	MOVEM	T3,.USTMP+3
	SKIPGE	.USBTS		;EXTENDED USER?
	SKIPGE	.USSPT		;YES, ALREADY DID NZS?
	JRST	LOCK18		;YES, STOP ON COUNT EXHAUSTED
	TRNN	M,<-1^!HLGPNO>	;IS IT A USER PAGE #?
	JRST	LOCK18		;NO, JUST CONTINUE THEN
	SKIPE	T4,.USSPT	;JUST DO S0?
	AOJA	T4,LOC19A	;INCREMENT SECTION
	PUSH	P,M		;SAVE THINGS TO DO FUNNY SPACE LATER
	PUSH	P,T1
	PUSH	P,T2
	PUSH	P,T3		;..
	AOJA	T4,LOC19B
LOC19A:	CAILE	T4,MXSECN	;ANY MORE TO DO?
	SETO	T4,		;NO, BACK TO S0 FOR FUNNY SPACE (2ND TIME)
LOC19B:	MOVEM	T4,.USSPT
	JUMPGE	T4,LOC16A	;START NEW SECTION UNLESS FUNNY SPACE
	POP	P,T3
	POP	P,T2
	POP	P,T1
	POP	P,M		;RESTORE FUNNY SPACE VALUES
	MOVEI	T4,(M)		;RESET THE BYTE POINTER
	PUSHJ	P,GMPTR##
	JRST	LOCK18		;AND CONTINUE
LOCK20:	SUBI	P2,1		;BACK DOWN TEMPORARILY
	IORM	T4,@[IW MS.MEM,PAGTAB(P2)] ;INDICATE LAST PAGE OF SEGMENT
	ADDI	P2,1		;UN BACK DOWN TEMPORARILY
	MOVSI	T1,NSHF!NSWP	;AFTER ALL THAT WORK
	IORM	T1,JBTSTS##(J)	; MAKE SURE THE SEGMENT DOESN'T SWAP
	CAILE	J,JOBMAX##	;LOCKING A LOW SEGMENT?
	JRST	LOCK21		;NO
	MOVE	T2,.UPMP+.UMUPM ;PAGE MAP
	TLO	T2,(PM.PUB+PM.CSH) ;ALWAYS CACHED AND PUBLIC IN SECTION TABLE
	MOVEM	T2,.UPMP+SECTAB+0 ;STORE AS POINTER TO SECTION 0 PAGE MAP
	PUSHJ	P,NEWMAP	;ZAP PAGING MEMORY
	HRRZS	T2		;JUST PAGE NUMBER
	PUSHJ	P,LKPSF##	;FIND AND LINK AROUND IT
	HLLZS	@[IW MS.MEM,PAGTAB(T2)] ;LAST PAGE IN LOW SEGMENT CHAIN
	HRRZ	T1,JBTUPM##(J)	;PROCESS TABLE
	HRRM	T2,@[IW MS.MEM,PAGTAB(T1)] ;LINK PAGE MAP ONTO
					      ;PROCESS TABLE CHAIN
	HRRM	T1,@[IW MS.MEM,PT2TAB(T2)]
LOCK21:
	HLRZS	J,LOCK##	;GET THE SEGMENT NUMBER OF THE LOW SEGMENT
				; IF THERE IS ONE LEFT TO BE LOCKED
	JUMPE	J,LOCK22	;JUMP IF DONE
	HLRZS	LOKREL##	;STARTING PAGE NUMBER FOR THE LOW SEGMENT
	JRST	LOCK1		;AND GO TRY TO LOCK IT
LOCK22:	MOVEI	T1,LOK		;SET TO MAKE JOB RUNABLE AGAIN
	HRRZ	J,LASLOK##	;GET THE JOB NUMBER OF JOB ISSUING LOCK UUO
	ANDCAM	T1,JBTSTS##(J)	;TURN OFF LOK SO SCHEDULAR WILL RUN THE JOB AGAIN
	MOVSI	T1,SWP		;ASSUME THE HIGH SEGMENT GOT SWAPPED WHILE
				; LOCKING THE LOW SEGMENT
	SKIPG	T2,JBTSGN##(J)	;DOES THE JOB HAVE A REAL HIGH SEGMENT?
	POPJ	P,		;NO, RETURN
	HRRZS	T2		;CLEAN OUT LH OF JBTSGN SO WE CAN INDEX
	SKIPN	JBTADR##(T2)	;IS THE HIGH SEGMENT IN CORE
	IORM	T1,JBTSTS##(J)	;TURN ON SWP SO THE SCHEDULAR WON'T RUN
				; THE JOB UNTIL THE HIGH SEGMENT GETS SWAPPED IN
	MOVE	T1,HIGHJB##	;HIGHEST NUMBERED JOB
	MOVSI	T3,SEGMB		;SIGNAL TO MAP HIGH SEGMENT
LOCK23:	SKIPLE	T4,JBTSGN##(T1)	;GET HIGH SEGMENT OF ALL JOBS
	SKIPN	JBTADR##(T1)	;IGNORE IF NOT IN CORE
	JRST	LOCK24
	CAIE	T2,(T4)		;SAME HIGH SEGMENT AS OURS?
	JRST	LOCK24		;NO. LOOK AT NEXT ONE
	IORM	T3,JBTSGN##(T1)
LOCK24:	SOJG	T1,LOCK23	;LOOP FOR ALL JOBS
	POPJ	P,		;AND RETURN

IFN FTIPCF,<
;HERE WHEN AN IPCF PAGE WAS IN THE ROAD
DELIPP:	TLNE	T1,LOKPHB	;TURNED ON WHILE SWAPPING I/O IS IN PROGRESS
				; SO WE DON'T TRY TO SWAP OUT THE PAGE TWICE
	POPJ	P,		;I/O IN PROGRESS, WAIT FOR IT TO COMPLETE
	HRRZ	T2,P3		;ARGUMENT FOR IPCSSP
	PUSHJ	P,IPCSSP##	;GET SWAPPING SPACE
	S0PSHJ	MAKSLE##	;MAKE THE SWPLST ENTRY
	HRRZ	T2,P3		;RESTORE PHYSICAL PAGE NUMBER
	S0PSHJ	LOKIPC##	;FIND ENTRY IN AN IPCF QUEUE AND REPLACE PHYSICAL
				; PAGE WITH DISK ADDRESS
	  STOPCD .,STOP,IPU	;++IPCF PAGE UNOWNED
	S0JRST	SQOUT##		;START THE PAGING IO
				; WAIT FOR THE PAGE TO GO AWAY
>
;HERE TO MOVE THE MONITOR IF NECESSARY
SETMFL:	SKIPN	P4,MOFLPG##	;ANY OF THE PAGES BEING SET OFF CONTAIN MONITOR CODE?
	JRST	SETM17		;NO, THEN THIS IS EASY

;FIRST, MOVE ANY PAGES WHICH ARE REALLY MONITOR PAGES BUT DON'T
; APPEAR IN ANY MAP (UNMAPPED PHYSICAL PAGES)

	PUSHJ	P,MOVUMP	;MOVE UNMAPPED PHYSICAL PAGES
	SKIPN	P4,MOFLPG##	;ANY PAGES LEFT OVER?
	JRST	SETM17		;NO

;NEXT, MOVE ANY PAGES WHICH MUST REMAIN PHYSICALLY CONTIGUOUS

SETMF1:	MOVEI	T1,0		;STARTING AT PAGE 0
	LDB	T2,[POINT 14,MEMSIZ##,26] ;LOOK TO THE TOP OF CORE
SETMF2:	MOVE	T3,@[IW MS.MEM,PAGTAB(T1)] ;CURRENT PAGTAB ENTRY
	TLNE	T3,CONTGB	;MUST THIS RANGE OF PAGES REMAIN PHYSICALLY CONTIGUOUS?
	JRST	SETMF4		;YES
SETMF3:	HRRZS	T1		;CLEAR LEFT HALF JUNK - USED AS A TEMP BELOW
	CAIGE	T1,-1(T2)	;REACHED TOP OF MEMORY?
	AOJA	T1,SETMF2	;NO, LOOK ON
	JRST	SETM14		;YES, ALL PAGES HAVE BEEN MOVED
;FOUND FIRST, NOW DETERMINE THE RANGE
SETMF4:	HRLS	T1		;FIRST PAGE SEEN IN THE LEFT HALF
SETMF5:	CAIN	T2,1(T1)	;AT THE TOP OF MEMORY?
	AOJA	T1,SETMF6	;YES, HIGHEST PAGE + 1 IN THE RANGE
	HRRZ	T3,T1		;INDEX INTO PAGTAB
	MOVE	T3,@[IW MS.MEM,PAGTAB(T3)] ;NEXT PAGTAB ENTRY
	TLNE	T3,CONTGB	;ALSO A PAGE WHICH MUST REMAIN PHYSICALLY CONTIGUOUS?
	AOJA	T1,SETMF5	;YES
;HERE WHEN THE RANGE OF PAGES HAS BEEN DETERMINED, SEE IF THEY OVERLAP THE
; RANGE OF PAGES BEING SET OFF-LINE
SETMF6:	HRRZ	T3,LOKREL##	;FIRST PAGE BEING SET OFF-LINE
	HLRZ	T4,LOKREL##	;NUMBER OF PAGES BEING SET OFF-LINE
	ADDI	T4,(T3)		;HIGHEST PAGE + 1 BEING SET OFF-LINE
	CAIL	T3,(T1)		;BOTTOM OF MOFFL .LE. TOP OF CONTIGUOUS PAGES?
	JRST	SETMF3		;YES, THEY DON'T OVERLAP SO LOOK ON
	MOVSS	T1		;BOTTOM PAGE IN CONTIGUOUS PAGE RANGE
	CAIG	T4,(T1)		;LOWEST PAGE ABOVE RANGE BEING SET OFF-LINE?
	JRST	SETM14		;YES, DONE SINCE ABOVE REGION BEING SET OFF
;HERE TO COMPUTE THE NUMBER OF CONTIGUOUS PAGES WHICH OVERLAP THE MEMORY
;OFF-LINE RANGE
	HRRZ	P1,T1		;LOWEST CONTIGUOUS PAGE
	HLRZ	P2,T1		;HIGHEST CONTIGUOUS PAGE
SETMF7:	CAIL	P1,(T3)		;BELOW RANGE BEING SET OFF-LINE?
	CAIL	P1,(T4)		;OR ABOVE RANGE BEING SET OFF-LINE?
	CAIA			;NOT IN OFF-LINE RANGE
	SOS	P4		;DECREMENT NUMBER OF MONITOR PAGES BEING SET OFF
	CAIE	P1,-1(P2)	;LOOKED AT THE ENTIRE RANGE OF CONTIGUOUS PAGES
	AOJA	P1,SETMF7	;NO, LOOK AT THE NEXT PAGE
	HLRZ	P1,T1		;HIGHEST CONTIGUOUS PAGE
	SUBI	P1,(T1)		;NUMBER OF PAGES TO MOVE (MUST MOVE THEM ALL
				; EVEN IF ONLY A FEW OVERLAP SINCE PHYSICAL
				; CONTIGUITY MUST BE MAINTAINED)
	LDB	P2,[POINT 14,SYSSIZ##,26] ;STARTING AT SYSSIZ
SETMF8:	MOVEI	P3,0		;NUMBER OF CONTIGUOUS FREE PAGES SEEN
SETMF9:	HRRZ	T2,P2		;MAKE AN INDEX INTO PAGTAB
	CAML	T2,T3		;ABOVE RANGE BEING SET OFF-LINE?
	CAML	T2,T4		;NO, WITHIN RANGE BEING SET OFF-LINE?
	SKIPL	@[IW MS.MEM,PAGTAB(T2)] ;NOT WITHIN RANGE, IS THE PAGE FREE?
	JRST	SETM13		;NO, LOOK HIGHER UP
	TLNN	P2,-1		;FIRST PAGE OF THE HOLE?
	HRLS	P2		;YES, REMEMBER START OF HOLE
	AOS	P3		;NUMBER OF PAGES SEEN SO FAR IN THIS HOLE
	CAIGE	P3,(P1)		;ENOUGH PAGES SEEN TO MOVE THE CONTIGUOUS PAGES?
	AOJA	P2,SETMF9	;NO, SEE IF THERE ARE MORE PAGES AVAILABLE
;HERE WHEN ENOUGH FREE PAGES HAVE BEEN FOUND TO MOVE THE CONTIGUOUS PAGES
; T1 = TOP,,BOTTOM OF CONTIGUOUS PAGES, P1 = NUMBER OF PAGES TO MOVE,
; P2 = BOTTOM,,TOP OF HOLE
	PUSH	P,P1		;SAVE COUNT (NEED P1 FOR PAGFRE)
	MOVEI	P1,0		;NEVER A PREDECESSOR IN PAGFRE
	HLRZS	P2		;STARTING DESTINATION PAGE
	HRRZ	P3,T1		;STARTING SOURCE PAGE
SETM10:	HRRZ	T1,P3		;NEXT SOURCE PAGE
	PUSH	P,@[IW MS.MEM,PAGTAB(T1)] ;SAVE PAGE DESCRIPTOR BITS
	PUSHJ	P,PAGFRE	;MOVE THE PAGE AND FIX PAGTAB
	  STOPCD .,STOP,CMP	;++CAN'T MOVE PAGE
	POP	P,T1		;GET BACK PAGE DESCRIPTOR BITS
	HLLM	T1,@[IW MS.MEM,PAGTAB(P2)] ;FIX UP DESTINATION PAGTAB ENTRY
	PUSHJ	P,ADJMAP	;ADJUST EXEC MAP TO ACCOUNT FOR MOVED PAGE
	AOS	P2		;NEXT DESTINATION PAGE
	SOSLE	(P)		;ALL THE CONTIGUOUS PAGES BEEN MOVED?
	AOJA	P3,SETM10	;NO, MOVE THE NEXT SOURCE PAGE
	POP	P,(P)		;POP OFF JUNK
	JRST	SETMF1		;THESE PAGES HAVE BEEN MOVED, LOOK FOR MORE
SETM13:	HRRZS	P2		;NEXT FREE PAGE IS THE BEGINNING OF A HOLE
	LDB	T2,[POINT 14,MEMSIZ##,26]
	CAIE	P2,-1(T2)	;REACHED THE TOP OF MEMORY
	AOJA	P2,SETMF8	;NO, LOOK FOR THE NEXT HOLE
	STOPCD	.,STOP,NCC	;++NOT ENOUGH CONTIGUOUS FREE CORE
SETM14:	JUMPE	P4,SETM17	;GO IF ALL PAGES SET OFF WERE CONTIGUOUS
	MOVEI	P1,0		;FOR PAGFRE
	LDB	P2,[POINT 14,MEMSIZ##,26]
	HLRZ	P3,LOKREL##	;NUMBER OF PAGES TO BE SET OFF
	MOVNS	P3		;MAKE IT NEGATIVE
	HRL	P3,LOKREL##	;STARTING PAGE NUMBER
	MOVSS	P3		;MAKE AN AOBJN POINTER
SETM15:	HRRZ	T1,P3		;COPY PAGE NUMBER
	MOVE	T1,@[IW MS.MEM,PAGTAB(T1)] ;GET PAGTAB ENTRY FOR THIS PAGE
	TLNE	T1,MONTRB	;DOES THIS PAGE CONTAIN MONITOR CODE?
	JRST	SETM16		;YES
	AOBJN	P3,SETM15	;NO, LOOK AT THE NEXT PAGE
	STOPCD	.,STOP,MMR,	;++MOVING MONITOR PAGE NOT REQUIRED
;HERE WHEN A MONITOR PAGE HAS BEEN FOUND WITHIN THE RANGE BEING SET
; OFF-LINE, MOVE THE PAGE TO THE HIGHEST POSSIBLE FREE PAGE WHICH DOES
; NOT OVERLAP THE PAGES BEING SET OFF-LINE. THIS TENDS TO KEEP THE MONITOR
; AS HIGH IN CORE AS POSSIBLE SO THAT MORE SPACE IS AVAILABLE FOR
; LOCKING BELOW 112K AND HELPS TO KEEP THE MONITOR FROM BEING WRITTEN
; INTO WITH AN ABSOLUTE ADDRESS WHICH CAN ONLY BE DONE IF ITS BELOW 112K
SETM16:	HRRZ	T1,LOKREL##	;LOWEST PAGE BEING SET OFF LINE
	HLRZ	T2,LOKREL##	;NUMBER OF PAGES BEING SET OFF LINE
	ADDI	T2,-1(T1)	;HIGHEST PAGE BEING SET OFF LINE
	SUBI	P2,1		;CANDIDATE FOR WHERE TO MOVE THIS PAGE
	CAIL	P2,(T1)		;IS CANDIDATE BELOW FIRST PAGE BEING SET OFF?
	CAILE	P2,(T2)		;OR ABOVE LAST BEING SET OFF?
	SKIPL	@[IW MS.MEM,PAGTAB(P2)] ;YES, IS THE CANDIDATE PAGE FREE?
				; IF NOT, IT MUST CONTAIN A PAGE OF THE MONITOR
	JRST	SETM16		;NO, LOOK AT THE NEXT CANDIDATE
	HRRZ	T1,P3		;PART OF P3 TO BE USED AS AN INDEX
	PUSH	P,@[IW MS.MEM,PAGTAB(T1)] ;SAVE BITS FOR THIS PAGE
	HRRZ	T1,P3		;SOURCE PAGE
	PUSHJ	P,PAGFRE	;MOVE THE PAGE
	  STOPCD .,STOP,FPN,	;++FREE PAGE NOT FOUND
	PUSHJ	P,ADJMAP	;ADJUST EXEC MAP TO ACCOUNT FOR MOVED PAGE
	POP	P,T1		;MONITOR PAGE+CACHE BITS
	HRRZ	T2,P2		;GET INDEX INTO PAGTAB (LH P2 MAY HAVE JUNK)
	HLLM	T1,@[IW MS.MEM,PAGTAB(T2)] ;REMEMBER THAT
	SOJLE	P4,SETM17	;JUMP IF WE'VE MOVED THE LAST PAGE
	SKIPLE	.CPHTM##	;ONCE/SECOND TIME CREEPING UP ON US?
	JRST	SETM15		;NOT YET, GO TWIDDLE SOME MORE PAGES
	MOVEM	P4,MOFLPG##	;SAVE NEW NUMBER OF PAGES TO MOVE
	POPJ	P,		;DO ONCE/SECOND CODE (POKE DTE'S)
;HERE WHEN ALL PAGES TO BE SET OFF LINE ARE FREE AND ANY MONITOR
; PAGES WHICH NEEDED TO BE HAVE BEEN MOVED
SETM17:	HRRZ	T1,LOKREL##	;FIRST PAGE TO BE SET OFF LINE
	IDIVI	T1,^D36		;BIT POSITION AND WORD NUMBER WITHIN NXMTAB
				; CORESPONDING TO THE FIRST PAGE SET OFF
	MOVE	T2,BITTBL##(T2)	;BIT MASK CORRESPONDING TO BIT POSITION
	HLRZ	T3,LOKREL##	;NUMBER OF PAGES TO SET OFF
SETM18:	IORM	T2,NXMTAB##(T1)	;MAKE THE PAGE APPEAR TO BE NON-EXISTANT
	ROT	T2,-1		;NEXT BIT POSITION IN NXMTAB
	SKIPGE	T2		;PASSED A WORD BOUNDARY?
	ADDI	T1,1		;YES, BUMP TO THE NEXT WORD IN NXMTAB
	SOJG	T3,SETM18	;MARK ALL PAGES IN THE REQUEST AS OFF LINE

	MOVE	T1,BOOTVA##	;GET VIRTUAL ADDRESS OF BOOTSTRAP
	MAP	T1,(T1)		;GET (POSSIBLY) NEW PHYSICAL ADDRESS
	TLZ	T1,(MP.NAD)	;CLEAR NON-ADDRESS BITS
	MOVEM	T1,BOOTPA##	;(MAYBE) RESET PHYSICAL ADDRESS OF BOOTSTRAP

	SETZM	LOCK##		;INDICATE SUCCESS
	MOVEI	T1,LOK		;ALLOW JOB TO RUN AND/OR COMMAND TO COMPLETE
	HRRZS	J,LASLOK##	;JOB NUMBER OF JOB SETTING MEMORY OFF
	ANDCAM	T1,JBTSTS##(J)	;CLEAR THE BIT
	PJRST	CPINXF##	;FIXUP PAGTAB, CORTAL, BIGHOL, CORMAX, MAXMAX, ETC.
;ROUTINE TO MOVE UNMAPPED PHYSICAL PAGES
;CALLS WHOEVER USES UNMAPPED PHYSICAL MEMORY WITH:
;	P1/ FIRST PAGE BEING SET OFFLINE
;	P2/ LAST PAGE BEING SET OFFLINE
;IF THEY HAVE A PAGE IN THAT RANGE THEY SHOULD CALL MOVPAG
;TO MOVE THE PAGE.

MOVUMP:	HRRZ	P1,LOKREL##	;GET FIRST PAGE TO BE SET OFFLINE
	HLRZ	P2,LOKREL##	;GET NUMBER OF PAGES BEING SET OFFLINE
	ADDI	P2,-1(P1)	;P1 HAS FIRST PAGE GOING OFFLINE, P2 HAS LAST
	MOVSI	P3,-MOVTBL	;-VE LENGTH OF TABLE
	JUMPE	P3,CPOPJ##	;OF COURSE, THERE MIGHT NOT BE ANYONE!
	PUSHJ	P,@MOVTAB(P3)	;CALL A ROUTINE
	  JFCL			;HANDLE SILLINESS ON CALLEE'S PART
	AOBJN	P3,.-2		;LOOP FOR ALL
	POPJ	P,		;RETURN

;TABLE OF WHO TO CALL TO MOVE UNMAPPED PHYSICAL PAGES

MOVTAB:
IFN FTDECNET,<
	IFIW	DCNMOV##	;DECnet NAME/ADDRESS MAP PAGES
>; END IFN FTDECNET

;IF YOU HAVE SOME UNMAPPED PAGES TO MOVE, YOU TOO CAN ADD AN ENTRY
;TO THIS TABLE

MOVTBL==.-MOVTAB		;LENGTH OF TABLE
;ROUTINE TO MOVE A PAGE BEING SET OFFLINE
;CALL WITH NUMBER OF PAGE BEING SET OFFLINE IN T1, WILL
;MOVE THE PAGE SOMEPLACE OUT OF THE RANGE AND RETURN THE
;NUMBER OF THE NEW PAGE IN T1.

MOVPAG::HRRZ	T2,LOKREL##	;GET LOWEST PAGE BEING SET OFFLINE
	HLRZ	T3,LOKREL##	;GET NUMBER OF PAGES BEING SET OFFLINE
	ADDI	T3,-1(T2)	;GET FIRST PAGE IN T2, LAST PAGE IN T3
	CAML	T1,T2		;SUSPECT PAGE IN RANGE OF PAGES GOING OFFLINE?
	CAMLE	T1,T3		;...
	STOPCD	.,STOP,SMP,	;++SHOULDN'T MOVE PAGE
	PUSHJ	P,SAVE2##	;FREE UP THE AC'S WE'LL NEED
	HRRZ	P2,CORLST##	;GET END OF PAGTAB
	SUBI	P2,PAGTAB	;COMPUTE HIGHEST OFFSET
MOVPG1:	CAML	P2,T2		;THIS PAGE IN RANGE BEING SET OFFLINE?
	CAMLE	P2,T3		;...
	SKIPL	@[IW MS.MEM,PAGTAB(P2)] ;NOT IN RANGE, IS PAGE FREE?
	SOJG	P2,MOVPG1	;NO, OR IN RANGE, KEEP LOOKING
	SKIPN	P2		;DID WE FIND A PAGE?
	XCT	NCC		;++NOT ENOUGH CONTIGUOUS FREE CORE
	PUSH	P,@[IW MS.MEM,PAGTAB(T1)] ;SAVE PAGE DESCRIPTOR BITS
	MOVEI	P1,0		;NO PREDECESSOR FOR PAGFRE
	PUSHJ	P,PAGFRE	;MOVE THE PAGE
	  XCT	CMP		;++CAN'T MOVE PAGE
	POP	P,T1		;RESTORE PAGE DESCRIPTOR BITS
	HLLM	T1,@[IW MS.MEM,PAGTAB(P2)] ;SET BITS FOR NEW PAGE
	SOSGE	MOFLPG##	;DECREASE COUNT OF PAGES BEING SET OFFLINE
	STOPCD	.,STOP,MCW,	;++MOFLPG COUNT WRONG
	HRRZ	T1,P2		;GET PAGE NUMBER
	POPJ	P,		;RETURN
;HERE WITH SOURCE PAGE IN RH(P3), DESTINATION PAGE IN P2, FIND THE
; SOURCE PAGE IN THE EXEC MAP AND MAP THE DESTINATION PAGE THROUGH THAT
; MAP SLOT

ADJMAP:	MOVE	T1,MONVFF##	;1ST VIRTUAL ADDRESS ABOVE MONITOR
	SUBI	T1,MONORG##	;NUMBER OF WORDS (BOTTOM OF HISEG)
	LSH	T1,W2PLSH##	;NUMBER OF PAGES TO WORRY ABOUT
	MOVE	T2,[POINT 36,MONORG##/PAGSIZ##]
	ADD	T2,.CPMAP##
ADJMP1:	ILDB	T3,T2		;GET THE NEXT MAP ENTRY
	TLZ	T3,(PM.NAD)	;CLEAR ACCESS BITS
	CAIN	T3,(P3)		;IS THIS THE PAGE WHICH WAS JUST MOVED?
	JRST	ADJMP8		;YES
	SOJG	T1,ADJMP1	;LOOP OVER ALL OF THE MONITORS PAGES
	HRROI	T1,ADJSMP	;SUBROUTINE TO CALL TO SEE IF ITS IN SOME OTHER
	PUSHJ	P,CPUAPP##	; CPU'S SECTION TABLE. CHECK.
	JUMPN	T1,ADJMP3	;JUMP IF IT IS
	MOVE	T1,.CPEPT##	;PAGE MAY BE IN A NON-ZERO SECTION
	ADDI	T1,(MS.FMD)	;START AT SECTION 2
ADJMP2:	SKIPN	T2,SECTAB(T1)	;SECTION EXIST?
	JRST	ADJMP7		;NO
	MOVE	T3,.CPMAP##	;ADDRESS OF OUR MAP
	MOVEM	T2,.EUPMP/PAGSIZ##(T3) ;MAKE THE SECTION MAP ADDRESSABLE
	TLZ	T2,(PM.NAD)	;CLEAR ACCESS BITS
	CAIE	T2,(P3)		;IS THIS THE PAGE BEING SET OFF-LINE?
	JRST	ADJMP4		;NO
ADJMP3:	MOVSI	T2,(POINT 36,0,35) ;YES, SECTION MAP IS BEING SET OFF-LINE
	HRRI	T2,SECTAB(T1)	;BYTE POINTER TO THE SLOT IN THE SECTION TABLE
	JRST	ADJMP8		;REMAP THE PAGE
ADJMP4:	PUSHJ	P,NEWMAP	;TO LOOK AT THE SECTION MAP
	MOVE	T2,[POINT 36,.EUPMP] ;BYTE POINTER TO THE SECTION MAP
	MOVEI	T3,^D512	;512 PAGES/SECTION
ADJMP5:	ILDB	T4,T2		;NEXT ENTRY IN THE SECTION MAP
	LDB	T4,[POINT 3,T4,2] ;POINTER TYPE
	CAIE	T4,PM.DCD	;IGNORE ANYTHING EXCEPT DIRECT POINTERS
	JRST	ADJMP6		; ..
	LDB	T4,T2		;GET POINTER BACK AGAIN
	TLZ	T4,(PM.NAD)	;CLEAR ACCESS BITS
	CAIN	T4,(P3)		;PAGE THATS BEING SET OFF-LINE?
	JRST	ADJMP8		;YES
ADJMP6:	SOJG	T3,ADJMP5	;NO, LOOP OVER THE ENTIRE SECTION
ADJMP7:	MOVE	T3,.CPEPT##	;ADDRESS OF OUR PROCESS TABLE
	CAIGE	T1,MXSECN-1(T3)	;LOOKED AT ALL SECTIONS? (SECTION 37 IS SPECIAL)
	AOJA	T1,ADJMP2	;NO, LOOK AT THE NEXT ONE
	STOPCD	.,STOP,MPN,	;++MONITOR PAGE NOT FOUND

;HERE WITH THE BYTE POINTER TO THE EXEC MAP SLOT IN T2
ADJMP8:	LDB	T1,T2		;GET THE CURRENT CONTENTS OF THE MAP SLOT
	AND	T1,[-1,,760000]	;GET THE ACCESS BITS
	ADDI	T1,(P2)		;NEW PAGE NUMBER PLUS ACCESS BITS
	DPB	T1,T2		;STORE NEW PHYSICAL PAGE NUMBER
	PJRST	NEWMAP		;CAUSE NEW MAPPING TO BE IN EFFECT SINCE
				; PAGTAB MAY HAVE BEEN MOVED
;SUBROUTINE TO SEE IF THE SOURCE PAGE IS IN SOME OTHER CPU'S SECTION MAP
; RH(P3) IS THE SOURCE PAGE
;CALL:
;	HRROI	T1,ADJSMP
;	PUSHJ	P,ADJSMP
;RETURNS WITH T1=0 IF NOT IN A SECTION MAP, T1=POINTER TO SLOT IF IT IS

ADJSMP:	JUMPG	T1,CPOPJ##	;EXIT IF PAGE ALREADY FOUND
	MOVE	T1,.CPEPT##-.CPCDB##(P1) ;THIS CPU'S EPT
	ADDI	T1,(MS.FMD)	;START AT SECTION 2
ADJSM1:	SKIPN	T2,SECTAB(T1)	;SECTION POINTER
	JRST	ADJSM2		;NON-EXISTANT
	TLZ	T2,(PM.NAD)	;ISOLATE PHYSICAL PAGE NUMBER
	CAIN	T2,(P3)		;SAME AS SOURCE PAGE?
	POPJ	P,		;YES, FOUND RETURN (T1 POSITIVE)
ADJSM2:	MOVE	T2,.CPEPT##-.CPCDB##(P1) ;ADDRESS OF THIS CPU'S EPT
	CAIGE	T1,MXSECN-1(T2)	;LOOKED AT ALL SECTIONS? (SECTION 37 IS SPECIAL)
	AOJA	T1,ADJSM1	;NO, KEEP LOOKING
	SETZ	T1,		;INDICATE NOT FOUND
	POPJ	P,		;AND RETURN
;SUBROUTINE TO SEE IF TARGET PAGE IS ON THE FREE CORE LIST AND
; EXCHANGE IT WITH THE CURRENT PAGE IF SO
;ENTER WITH T1= CURRENT PAGE WHERE JOB IS
; ENTER P2= PAGE WE WANT TO PUT JOB AT
;EXIT CPOPJ1 IF THE TARGET PAGE IS ON THE FREE CORE LIST AND THE
; EXCHANGE HAS TAKEN PLACE

PAGFRE:	SKIPL	@[IW MS.MEM,PAGTAB(P2)] ;DOES PAGE SAY IT'S FREE?
	POPJ	P,		;NO
	HRRZ	T3,@[IW MS.MEM,PT2TAB(P2)] ;GET PREDECESSOR
IFN FTXMON,<
	SKIPE	T3		;IS THERE ONE?
	TLOA	T3,(MS.MEM)	;YES
	MOVEI	T3,PAGPTR##	;NO, THEN THIS IS PREDECESSOR
	.CREF	PAGTAB		;(WHICH IS AT SECTION RELATIVE 0)
>
IFE FTXMON,<
	SKIPN	T3		;IS THERE A PREDECESSOR?
	SKIPA	T3,[PAGPTR##]	;NO, THIS IS IT THEN
	ADDI	T3,PAGTAB	;POINT TO PAGTAB
>
;HERE WHEN TARGET PAGE IS ON THE FREE-PAGE LIST
;EXCHANGE TARGET PAGE AND CURRENT PAGE ON THE FREE LIST
PAGFR2:	SKIPE	P1
	HRRZ	T4,@[IW MS.MEM,PT2TAB(T1)]
	MOVE	T2,@[IW MS.MEM,PAGTAB(T1)]
	PUSHJ	P,FIXPTB
	MOVSI	T2,FREPAG
	HLLM	T2,@[IW MS.MEM,PAGTAB(T1)]
	PUSHJ	P,BLTPAG	;MOVE CURRENT PAGE TO TARGET PAGE (DATA)
	PJRST	CPOPJ1##	;AND SKIP-RETURN
;CALL THIS ROUTINE WHEN THE TARGET PAGE ISN'T ON FREE-LIST
;NOTE THAT THE PAGE IS THEREFORE IN THIS SEGMENT'S MAP
PAGFND:	LDB	T2,JBYLSA##	;ASSUME ITS A LOW SEGMENT
	CAILE	J,JOBMAX##	;IS IT?
	LDB	T2,JBYHSA##	;NO
	SETZ	T4,		;NO PREDECESSORS YET
	CAIE	T2,(P2)		;IS THE TARGET PAGE THE 1ST PAGE OF THE SEG?
	JRST	PAGFD1		;NO
	MOVE	T2,@[IW MS.MEM,PAGTAB(T1)] ;YES, GET SUCC TO CURRENT PAGE
	EXCH	T2,@[IW MS.MEM,PAGTAB(P2)] ;STORE AS SUCC TO TARGET PAGE
	HRRM	T2,@[IW MS.MEM,PAGTAB(T1)] ;SUCC TO TARGET TO CURRENT SUCC
	MOVE	T2,@[IW MS.MEM,PT2TAB(T1)]
	EXCH	T2,@[IW MS.MEM,PT2TAB(P2)]
	HRRM	T2,@[IW MS.MEM,PT2TAB(T1)]
	JRST	PAGFD2		;AND SKIP SOME MAGIC

;HERE WHEN THE TARGET PAGE ISN'T THE 1ST PAGE OF THE SEGMENT
PAGFD1:	HRRZ	T3,T2		;SET PREDECESSOR
	JUMPE	T3,CPOPJ##	;ERROR IF LAST PAGE OF SEGMENT
	HRRZ	T2,@[IW MS.MEM,PAGTAB(T3)] ;NOT LAST, GET NEXT PAGE
	CAIN	T2,(T1)
	HRR	T4,T3
	CAIN	T2,(P2)		;IS THIS THE TARGET PAGE?
	HRL	T4,T3
	SKIPE	P1
	TRNE	T4,-1
	TLNN	T4,-1
	JRST	PAGFD1		;NO, TRY AGAIN
	SKIPGE	T2,@[IW MS.MEM,PAGTAB(T1)] ;GET SUCCESSOR TO CURRENT PAGE
	STOPCD	.,STOP,NPF,	;++NEXT PAGE FREE
	HLRZ	T3,T4
	ADD	T3,[EXP MS.MEM+PAGTAB]
	PUSHJ	P,FIXPTB
PAGFD2:	CAIG	J,JOBMAX##	;IF A LOW SEGMENT,
	PUSHJ	P,FIXMAP	;FIND THE DESTINATION PAGE AND FIX THE MAP
	PUSHJ	P,EXCHPG	;EXCHANGE DATA OF CURRENT AND TARGET PAGES
	JRST	CPOPJ1##	;AND GIVE GOOD RETURN
;SUBROUTINE TO MAKE TARGET AND SOURCE PAGES ADDRESSABLE IN EXEC
; VIRTUAL MEMORY
;CALLING SEQUENCE:
;	MOVE	T1,ABSOLUTE PAGE NUMBER OF SOURCE PAGE
;	MOVE	P2,ABSOLUTE PAGE NUMBER OF TARGET PAGE
;	PUSHJ	P,SETMAP
;RETURN HERE, SOURCE AND TARGET PAGES ADDRESSABLE THROUGH .ECKSM AND
; .EUPMP RESPECTIVILY

SETMAP:	PUSHJ	P,SAVE1##
	MOVE	P1,.CPMAP##
	HRLI	T1,(<PM.DCD>B2+PM.WRT+PM.PUB)
	MOVEM	T1,.ECKSM/PAGSIZ##(P1)
	HRR	T1,P2
	MOVEM	T1,.EUPMP/PAGSIZ##(P1)
;	PJRST	NEWMAP
NEWMAP:	CLRPGT	(0)		;CLEAR THE ASSOCIATIVE MEMORY
				; SO THE NEW MAPPING WILL BE IN EFFECT
	POPJ	P,		;RETURN

;SUBROUTINE TO BLT SOURCE PAGE TO TARGET PAGE WHICH WAS ON THE FREE CORE LIST
;CALLING SEQUENCE:
;	MOVE	T1,ABSOLUTE PAGE NUMBER OF THE SOURCE PAGE
;	MOVE	P2,ABSOLUTE PAGE NUMBER OF THE TARGET PAGE
;	PUSHJ	P,BLTPAG
;RETURN HERE, SOURCE PAGE BLTED TO TARGET PAGE FROM FREE CORE LIST

BLTPAG:	PUSHJ	P,SETMAP	;MAKE THE SOURCE AND DESTINATION PAGES ADDRESSABLE
	MOVSI	T1,.ECKSM	;ADDRESS OF THE SOURCE PAGE
	HRRI	T1,.EUPMP	;ADDRESS OF THE DESTINATION PAGE
;THIS LABEL IS TO DETECT MEMORY PARITY ERROR IN EXEC MODE DURING BLT OF USER CORE
LOKINS::BLT	T1,.EUPMP+PAGSIZ##-1
	POPJ	P,		;MOVE THE PAGE AND RETURN
;SUBROUTINE TO EXCHANGE SOURCE AND TARGET PAGES WHEN THEY ARE BOTH CONTAINED
; WITHIN THE CURRENT SEGMENT
;CALLING SEQUENCE:
;	MOVE	T1,ABSOLUTE PAGE NUMBER OF THE SOURCE PAGE
;	MOVE	P2,ABSOLUTE PAGE NUMBER OF THE TARGET PAGE
;	PUSHJ	P,EXCHPG
;RETURN HERE, SOURCE AND TARGET PAGES HAVE BEEN EXCHANGED

EXCHPG:	PUSHJ	P,SETMAP	;MAKE THE SOURCE AND DESTINATION PAGES ADDRESSABLE
	MOVNI	T1,PAGSIZ##	;- THE NUMBER OF WORDS TO EXCHANGE
	HRLZS	T1		;T1 = AN AOBJN POINTER
EXCHP1:	MOVE	T2,.EUPMP(T1)	;GET A DATA WORD FORM THE DESTINATION PAGE
	EXCH	T2,.ECKSM(T1)	;EXCHANGE IT WITH THE WORD FROM THE SOURCE PAGE
	MOVEM	T2,.EUPMP(T1)	;WORD FROM SOURCE PAGE TO DESTINATION PAGE
	AOBJN	T1,EXCHP1	;EXCHANGE THE ENTIRE PAGES
	POPJ	P,		;AND RETURN
;SUBROUTINE TO FIND THE TARGET PAGE ON THE FREE CORE LIST OR WITHIN
; THE CURRENT SEGMENT AND MOVE/EXCHANGE THE SOURCE TO/WITH THE TARGET AS
; APPROPRIATE
;CALLING SEQUENCE:
;	MOVE	T1,ABSOLUTE PAGE NUMBER OF THE SOURCE PAGE
;	MOVE	P2,ABSOLUTE PAGE NUMBER OF THE TARGET PAGE
;RETURN HERE - THE SOURCE PAGE HAS BEEN MOVED TO THE TARGET DESTINATION

PAGMOV:	PUSHJ	P,PAGFRE	;IS THE DESTINATION PAGE ON THE FREE CORE
				; LIST? IF SO, MOVE SOURCE PAGE TO DESTINATION
				; PAGE AND FIXUP PAGTAB
	  SKIPA	T2,[P2.LIP]	;TARGET PAGE NOT ON FREE CORE LIST
	POPJ	P,		;PAGE IS IN PLACE
	ANDCAM	T2,@[IW MS.MEM,PT2TAB(P2)] ;CLEAR P2.LIP SINCE IT WASN'T ON
				;FREE CORE LIST AND CLRLOQ THEREFORE DIDN'T
	PUSHJ	P,PAGFND	;THE DESTINATION PAGE IS NOT ON THE FREE
				; CORE LIST SO IT MUST BELONG TO THIS SEGMENT
				; FIND IT WITHIN THE SEGMENT, FIXUP PAGTAB
				; AND EXCHANGE THE SOURCE AND TARGET PAGES
	  STOPCD .,STOP,PNP,	;++PAGE NOT PRESENT
	POPJ	P,		;RETURN



;SUBROUTINE TO DETERMINE IF THE CURRENT PAGE MUST BE MOVED AND IF SO,
; MOVE IT
PGMOVE:	PUSHJ	P,SAVT##
	MOVE	T1,(T4)
	TLZ	T1,(PM.NAD)
	PUSH	P,T4
	CAIE	T1,(P2)
	PUSHJ	P,PAGMOV
	MOVE	T1,(P)
	MOVE	T1,(T1)
	AND	T1,[-1,,760000]
	IORI	T1,(P2)
	HRRZ	T2,M
	MOVSI	T3,(JS.NCS)
	CAIGE	T2,.MCFV/PAGSIZ##
	TDNN	T3,JBTST2##(J)
	CAIA
	TDZ	T1,[PM.CSH]
	EXCH	T1,(P)
	POP	P,(T1)
	PJRST	NEWMAP
;SUBROUTINE TO FIND THE PAGE A PAGE WAS EXCHED WITH AND FIX THE
; MAP SLOT FOR THAT PAGE
FIXMAP:	PUSHJ	P,SAVT##	;SAVE THE TS AGAIN
	PUSH	P,M
	PUSH	P,.USSPT
FIXMA8:	CAIE	M,.UPMVP/PAGSIZ##	;FLAG THAT WE'RE MOVING UPT
	JRST	FIXMA9		;NOT MOVING UPT, START WHERE PAGE CURRENTLY IS
	SETZM	.USSPT
FIXMA0:	PUSHJ	P,NXTWSB##	;START
	JRST	FIXMA7		;..
FIXMA9:	MOVE	M,.USTMP	;ACS SAVED FOR US
	DMOVE	T1,.USTMP+1
	MOVE	T3,.USTMP+3
FIXMA1:	PUSHJ	P,NXTWS3##	;NEXT PAGE
FIXMA7:	SKIPGE	.USBTS		;IS USER EXTENDED?
	SKIPGE	.USSPT		;YES, DOING FUNNY SPACE (2ND TIME THROUGH S0)
	JRST	FIXMA3		;YES
	TRNN	M,<-1^!HLGPNO>	;USER PAGE?
	JRST	FIXMA3		;YES
	SKIPE	T4,.USSPT	;START NON-ZERO SECTIONS?
	AOJA	T4,FIXMA4	;NO, ALREADY STARTED
	PUSH	P,M
	PUSH	P,T1
	PUSH	P,T2
	PUSH	P,T3
	AOJA	T4,FIXMA5
FIXMA4:	CAILE	T4,MXSECN
	SETO	T4,		;START FUNNY SPACE
FIXMA5:	MOVEM	T4,.USSPT
	JUMPGE	T4,FIXMA0
	POP	P,T3
	POP	P,T2
	POP	P,T1
	POP	P,M
	MOVEI	T4,(M)
	PUSHJ	P,GMPTR##
FIXMA3:	MOVEI	P4,(M)
	CAILE	P4,<<.UPMVP/PAGSIZ##>+MXSECN>
	STOPCD	.,STOP,XPW	;++EXCHANGED PAGE WENT AWAY
	MOVE	P4,(T4)		;GET MAP POINTER
	TLZ	P4,(PM.NAD)	;FIND OUT WHICH PHYSICAL PAGE THIS WAS
	CAIE	P4,(P2)		;IS THIS THE PHYSICAL PAGE WE ARE LOOKING FOR?
	JRST	FIXMA1		;NOPE, TRY NEXT ONE.
	MOVE	T1,(T4)
	AND	T1,[PM.NAD]	;WE ONLY WANT HIS FLAGS
	IOR	T1,-3(P)	;NEW PAGE (SAVED T1)
	MOVEM	T1,(T4)		;AND PUT IT BACK IN THE MAP
	HRRZS	M		;SEE IF PAGE WAS .UPMAP
	CAIN	M,<.UPMVP/PAGSIZ##>-1
	MOVEM	T1,.UPMP+SECTAB+0 ;YES, SET S0 POINTER TOO
	SKIPLE	.USSPT		;FIND PAGE IN NZS?
	ADJSP	P,-4		;YES, CLEAR STACK JUNK
	POP	P,.USSPT	;RESTORE THINGS
	POP	P,M
	PJRST	NEWMAP		;AND CLEAR THE PAGER
;SUBROUTINE TO FIX UP PAGTAB AFTER EXCHANGING PAGES
;ARGS:
;	T3=PREDECESSOR *ADDRESS*
;	T1=CURRENT PAGE #
;	P2=TARGET PAGE #
;	T4=PREDECESSOR-TO-CURRENT PAGE #
;	T2=SUCCESSOR-CURRENT-PAGE #
;NOTE THAT T3 IS LOADED WITH THE ACTUAL ADDRESS OF AN ENTRY IN PAGTAB,
;AND NOT AN OFFSET INTO PAGTAB.
;NOTE THAT LH(T1) CANNOT CONTAIN ANY JUNK
FIXPTB:	HRL	T2,@[IW MS.MEM,PAGTAB(P2)]
	PUSH	P,T4		;SAVE WHILE WE MANGLE IT
	SSX	T4,MS.MEM	;SECTION PAGTAB IS IN
	SKIPN	P1
	TDZA	T4,T4		;SET PREDECESSOR TO ZERO IF NONE
	HRRM	P2,PAGTAB(T4)
	HRRM	T4,@[IW MS.MEM,PT2TAB(P2)]
	HRRM	T1,(T3)
	MOVEI	T4,-PAGTAB(T3)
	CAIN	T4,PAGPTR-PAGTAB
	SETZ	T4,
	HRRM	T4,@[IW MS.MEM,PT2TAB(T1)]
	MOVE	T4,(P)		;GET BACK ORIGINAL T4
	HLRZM	T2,(P)		;SAVE T2
	CAIE	P2,(T2)
	TLZA	T2,-1		;CLEAR JUNK IN LH
	HRRZ	T2,T1
	HRRZM	T2,@[IW MS.MEM,PAGTAB(P2)]
	HRRZM	P2,@[IW MS.MEM,PT2TAB(T2)]
	POP	P,T2		;RESTORE T2
	CAIN	T2,(T1)
	MOVE	T2,P2
	HRRM	T2,@[IW MS.MEM,PAGTAB(T1)]
	HRRM	T1,@[IW MS.MEM,PT2TAB(T2)]
	POPJ	P,
SUBTTL ERRCON - ERROR HANDLING CODE

;ROUTINE TO CHECK IF JOB HAS BOTH SEG LOCKED
;CALL:	MOVE	J,JOB NUMBER
;	PUSHJ	P,LOKCHK
;	  BOTH LOCKED - J PRESERVED
;	NEITHER OR ONLY ONE LOCKED - J PRESERVED

LOKCHK::SE1ENT			;JUST TO MARK THAT ALL LOKCON RUNS EXTENDED
	PUSHJ	P,SAVE2##	;SAVE P1-P2
	MOVSI	P1,NSHF!NSWP	;NO SHUFFLING OR SWAPPING BITS
	TDNE	P1,JBTSTS##(J)	;LOW SEG LOCKED?
	POPJ	P,		;YES
	SKIPG	P2,JBTSGN##(J)	;NO, DOES JOB HAVE A HIGH SEG?
	 JRST	CPOPJ1		;NO, THAT MEANS IT CAN'T BE LOCKED
	HRRZS	P2		;CLEAN OUT LEFT HALF SO CAN USE AS INDEX
	TDNN	P1,JBTSTS##(P2)	;HAS HISEG, IS IT LOCKED?
	AOS	(P)		;NEITHER LOCKED, SKIP RETURN
	POPJ	P,

;SUBROUTINE TO DETERMINE IF A SEGMENT IS LOCKED IN CONTIGUOUS EXEC
; VIRTUAL MEMORY
;CALLING SEQUENCE:
;	MOVE	J,SEGMENT NUMBER
;	PUSHJ	P,LOKEVC
;	...	RETURN HERE IF SEGMENT IS NOT LOCKED IN EVM
;	...	RETURN HERE IF SEGMENT IS LOCKED IN EVM

LOKEVC::SE1ENT			;HAVE TO LOOK AT PAGTAB
	PUSHJ	P,SAVE2##	;SAVE P1-P2
	LDB	P1,JBYLSA##	;ASSUME A LOW SEGMENT (GET ABSOLUTE PAGE NUMBER OF
				; FIRST PAGE OF THE LOW SEGMENT)
	CAILE	J,JOBMAX##	;IS IT A HIGH SEGMENT
	LDB	P1,JBYHSA##	;YES, GET ABSOLUTE PAGE NUMBER OF FIRST PAGE
				; OF THE HIGH SEGMENT
	MOVSI	P2,LOKEVB	;BIT INDICATING PAGE IS LOCKED IN EVM
	TDNE	P2,@[IW MS.MEM,PAGTAB(P1)] ;IS IT?
				; (IF FIRST PAGE IS LOCKED ALL MUST BE)
	AOS	(P)		;YES
	POPJ	P,		;GIVE LOCKED OR NOT LOCKED RETURN
SUBTTL UUOCON - UUO HANDLING ROUTINES

;ROUTINE TO SET UP CALL TO SWAPPER FOR LOCKING A JOB IN CORE
;CHECKS VALIDITY OF REQUEST AND TRIES TO FIND A PLACE TO PUT THE
;JOB IN CORE.
;THE CALLING JOB IS PUT AS LOW CORE IN AS
;POSSIBLE.
;CALLING SEQUENCE
;	PUSHJ	P,LOKJOB
;	ERROR RETURN
;	NORMAL RETURN (NSHF+NSWP SET)


LOKJOB::SE1ENT			;MARK THE FACT THAT LOKCON RUNS EXTENDED
	MOVE	T2,.USVRT	;VIRTUALOSITY
	SKIPLE	T3,JBTSGN##(J)	; A HIGH SEGMENT?
	TLNE	T3,SHRSEG	;YES, IS IT SHARABLE?
	JRST	[TRNE T1,-1	;YES, LOCKING THE LOW SEGMENT?
		 JUMPN T2,RTZER## ;NOT IMPLEMENTED IF VIRTUAL
		 JRST LOKJO1]	;SEE IF SEGMENT(S) CAN BE LOCKED
	JUMPN	T2,RTZER##	;NOT IMLEMENTED IF VIRTUAL
	TLNE	T1,LKB		;A NON-SHARABLE HIGH SEGMENT
	TRNN	T1,LKB		;ARE BOTH SEGMENTS TO BE LOCKED?
	JRST	RTZER##		;NO, NOT IMPLEMENTED
LOKJO1:	PUSHJ	P,SAVE4##	;SAVE T1-T4
	MOVSI	T1,PVLOCK	;BIT DENOTING PRIVILEDGES TO LOCK
	PUSHJ	P,PRVBIT##	;IS THIS USER A SUFFICIENT WHEEL?
	  SKIPA			;YES, PROCEED
	JRST	ERROR1		;NO, NOT PRIVILEGED ERROR RETURN
LOKJ0Z:	PUSHJ	P,GETTAC##	;RESTORE THE USER'S ARGUMENT

	JUMPL	T1,[PUSHJ P,LOKARG	;JUMP IF NEW STYLE ARGUMENT LIST
		      JRST STOTAC## ;MALFORMED ARGUMENT LIST, GIVE ERROR RETURN
		    JRST .+1]	;CONTINUE PROCESSING
LOKRET:	MOVSI	P1,NSHF!NSWP	;LOCKED BITS
	MOVE	T2,J		;SAVE JOB NUMBER
	MOVEI	T3,0		;ASSUME NO HIGH SEGMENT ADDRESS
	SKIPG	J,JBTSGN##(J)	;GRAB HIGH SEGMENT NUMBER IF ANY
	JRST	LOKJO2		;NO HIGH SEGMENT
	TLO	J,(1B0)		;MAKE THIS AC A VALID INDEX. THIS WORKS SINCE
				;1B0 IS SPYSEG, WHICH NOONE TESTS FURTHER DOWN.
	LDB	T3,JBYHSA##	;PHYSICAL ADDRESS OF HIGH SEGMENT
	TLNE	T1,LKB		;USER LOCKING HIGH SEGMENT?
	TDNN	P1,JBTSTS##(J)	;ALREADY LOCKED?
	JRST	HGHADR		;NO. GET ADDRESS ANYWAY
	MOVE	T4,@[IW MS.MEM,PAGTAB(T3)] ;GET STATUS OF LOCKED SEGMENT
	PUSHJ	P,ARGCK1	;OK TO LOCK AGAIN?
	  JRST	ERROR7		;NOT OK. ARGUMENT IS INCORRECT
	TLNE	J,LOKSEG	;ALREADY LOCKED, BUT FOR THIS JOB?
	JRST	HGHADR		;YES, ALREADY LOCKED FOR THIS JOB
	MOVSI	T4,LOKSEG	;NO, WELL NOW IT IS
	IORM	T4,JBTSGN##(T2)
	PUSHJ	P,CHKCS2	;SET CACHE BIT IN JBTSGN
	PUSHJ	P,MAPHGH##	;COPY CACHE BIT TO UPMP
	JRST	LOKJ0Z		;RESTORE AC'S AND START OVER
HGHADR:	TLNN	T1,LKEB		;LOCKED IN EVM?
	LDB	T3,[POINT 9,JBTADR##(J),26] ;YES, PROVIDE EVA TO USER
LOKJO2:	EXCH	J,T2		;J=JOB, T2=HIGH SEGMENT NUMBER
	TRNN	T1,LKB		;LOCK THE LOW SEGMENT?
	JRST	LOKJO3		;NO
	TDNN	P1,JBTSTS##(J)	;IS THE LOW SEGMENT ALREADY LOCKED?
	JRST	LOKJO4		;YES
LOKJO3:	TLNN	T1,LKB		;LOCK THE HIGH SEGMENT?
	JRST	ERROR0		;NO, NOTHING TO DO
	JUMPE	T3,ERROR0	;JUMP IF NO HIGH SEGMENT
	TDNE	P1,JBTSTS##(T2)	;ALREADY LOCKED?
	JRST	ERROR0		;YES, GO CHECK OUT LOW SEGMENT
	HRRZ	J,T2		;SAVE HIGH SEGMENT NUMBER
LOKJO4:	TLZ	T1,-1-<LKB>
	MOVEI	F,0		;INDICATE NO DDB
	PUSHJ	P,CAWAIT##	;YES, WAIT UNTIL ITS DONE
	SETZB	P4,T4		;ZERO LARGEST JOB SEEN SO FAR
	PUSH	P,J		;SAVE J
	MOVEI	J,1		;FIND THE LARGEST JOB NOT LOCKED
LOKJO5:	CAMN	J,.CPJOB##	;DON'T CONSIDER JOB BEING LOCKED
	JRST	LOKJO7
	MOVE	T2,JBTSTS##(J)	;IS THIS JOB LOCKED?
	TLNE	T2,NSHF!NSWP
	TDZA	T2,T2
	PUSHJ	P,SEGSIZ##	;NOT LOCKED, FIND OUT HOW BIG IT IS
	PUSH	P,J		;SAVE LOW SEGMENT NUMBER
	SKIPG	J,JBTSGN##(J)	;DOES IT HAVE A REAL HIGH SEGMENT?
	JRST	LOKJO6		;NO
	HRRZS	J
	MOVSI	P2,NSWP!NSHF
	MOVE	P1,.CPJOB##	;GET OUR JOB #
	HRRZ	P1,JBTSGN##(P1)	;GET OUR HISEG #
	TLNE	T1,LKB		;IF LOCKING OUR HISEG
	CAIE	P1,(J)		;AND HE IS USING IT
	TDNE	P2,JBTSTS##(J)	;OR IT IS ALREADY LOCKED
	JRST	LOKJO6		;THEN IGNORE THIS HISEG
	MOVE	P2,T2		;COUNT THE SIZE OF THE HIGH SEGMENT
	PUSHJ	P,SEGSIZ##
	ADDI	T2,(P2)		;T2_SIZE OF THE JOB
LOKJO6:	LSH	T2,P2WLSH##
	CAMLE	T2,P4		;LARGEST SO FAR?
	MOVE	P4,T2		;YES, SAVE ITS SIZE
	POP	P,J		;RESTORE JOB NUMBER
LOKJO7:	CAMGE	J,HIGHJB##	;LOOKED AT ALL JOBS YET?
	AOJA	J,LOKJO5	;NO
	MOVE	J,(P)
	PUSHJ	P,SEGSIZ##	;SIZE OF THIS SEGMENT IN PAGES
	LSH	T2,P2WLSH##	;SIZE IN WORDS
	HRRI	T1,-1(T2)	;SIZE-1 OF HIGH OR LOW SEGMENT
	TLZE	T1,LKB		;HIGH SEGMENT TO BE LOCKED?
	CAILE	J,JOBMAX##	;LOW SEGMENT ALREADY LOCKED?
	JRST	LOKJO8		;YES, JUST LOCK THE HIGH SEGMENT
	MOVSI	P2,NSHF!NSWP	;HIGH SEGMENT MAY ALREADY BE LOCKED
	SKIPG	P1,JBTSGN##(J)	;DOES THE JOB HAVE A HIGH SEGMENT?
	 JRST	LOKJO8		;NO, DON'T WORRY ABOUT IT.
	HRRZ	T2,P1		;MAKE AN INDEX WITH SEGMENT NUMBER
	TDNE	P2,JBTSTS##(T2)	;IS THE HIGH SEGMENT ALREADY LOCKED?
	JRST	LOKJO8		;NEEDN'T BE CONCERNED ABOUT THE HIGH SEGMENT
	HRLI	P1,(J)		;P1_JOB#,,HIGH SEGMENT#
	MOVEM	P1,(P)		;SAVE IT
	HLRZ	P1,JBTADR##(T2)	;SIZE OF THE HIGH SEGMENT
	ADDI	T1,1(P1)	;ADD IT TO THE TOTAL
LOKJO8:	PUSHJ	P,LRGHOL	;COMPUTE THE NUMBER OF PHYSICAL PAGES AVAILABLE
				; FOR LOCKING
	POP	P,P1		;RESTORE JOB#,,HIGH SEGMENT#
	SUBI	T2,1(T1)	;T2 = AMOUNT OF CORE LEFT IF THIS JOB IS LOCKED
	CAMGE	T2,P4		;WILL ALL EXISTING JOBS BE ABLE TO RUN IN
				; THE AMOUNT OF CORE WHICH WILL REMAIN?
	JRST	ERROR2		;NO, CAN'T LOCK THE JOB
	CAMGE	T2,CORMIN##	;WOULD LOCKING THIS JOB MAKE CORMAX .LT.
				; CORMIN?
	JRST	ERROR3		;YES, TELL THE USER HE LOST
	MOVEM	T2,MAXMAX##	;LARGEST LEGAL CORMAX
	HRRZ	T1,CORLIM##	;UPPER BOUND ON CORMAX
	LSH	T1,P2WLSH##	;CONVERT TO NUMBER OF WORDS MAX
	CAMLE	T1,T2		;NUMBER OF PHYSICAL PAGES WHICH WILL REMAIN
				; AFTER LOCKING .GT. MAX CORMAX?
	MOVE	T1,T2		;YES, NEW CORMAX = NUMBER OF PHYSICAL PAGES
				; LEFT AFTER LOCKING
	MOVEM	T1,CORMAX##	;STORE THE UPDATED VALUE OF CORMAX
	SUBI	T2,NWMCP+PAGSIZ##	;ACCOUNT FOR FUNNY SPACE
	MOVEM	T2,RMCMAX##	;SET "REAL" MAXIMUM VALUE OF CORMAX
	MOVE	J,.CPJOB##	;CURRENT JOB NUMBER
	MOVSI	T1,LOKSEG	;ASSUME THE HIGH SEGMENT IS BEING LOCKED
	CAILE	P1,JOBMAX##	;IS IT?
	IORM	T1,JBTSGN##(J)	;YES, INDICATE HIGH SEGMENT IS LOCKED FOR
				; THIS JOB
	MOVEM	J,LASLOK##	;REMEMBER THE JOB NUMBER OF THE LAST JOB
				; ISSUING A LOCK UUO
	PUSHJ	P,GETTAC##	;RESTORE THE USER'S ARGUMENT
	JUMPL	T1,LOKEXT	;IF NEGATIVE, PROCESS NEW STYLE ARGUMENT LIST
;DISPATCH TO DO VARIOUS TYPES OF LOCK FOR EACH SEGMENT
	PUSHJ	P,CHKCSH	;CHECK WHETHER THE CACHE SHOULD BE ON OR OFF
	CAIG	P1,JOBMAX##	;IS THE HIGH SEGMENT TO BE LOCKED?
	JRST	LOKJO9		;NO
	TLCE	T1,LKB+LKEB+LKPB;DOES THE USER WANT IT LOCKED IN PLACE?
	TLNE	T1,LKB+LKEB+LKPB; ..
	JRST	LOKJO9		;NO, SOME OTHER VARIETY OF LOCKING
	HRRZ	J,P1		;YES, J = HIGH SEGMENT NUMBER
	PUSHJ	P,LOKINP	;LOCK THE HIGH SEGMENT IN PLACE
	HLRZS	P1		;P1 = LOW SEGMENT NUMBER OR ZERO IF THE
				; LOW SEGMENT ISN'T TO BE LOCKED
	JUMPE	P1,LOKJ17	;JUMP IF LOW SEGMENT ISN'T TO BE LOCKED
LOKJO9:	PUSHJ	P,GETTAC##	;RESTORE THE USER'S ARGUMENT
	TRCE	T1,LKB+LKEB+LKPB;DOES THE USER WANT THE LOW SEGMENT LOCKED
	TRNE	T1,LKB+LKEB+LKPB; IN PLACE?
	JRST	LOKJ10		;NO, TRY SOME OTHER VARITY OF LOCKING
	HRRZ	J,P1		;YES, J = LOW SEGMENT NUMBER
	PUSHJ	P,LOKINP	;LOCK THE LOW SEGMENT IN PLACE
	JRST	LOKJ17		;AND FINISH UP
LOKJ10:	PUSHJ	P,GETTAC##	;RESTORE USER'S ARGUMENT
	MOVEI	T2,0		;ASSUME ONLY THE HIGH SEGMENT IS TO BE LOCKED
	TLNE	P1,-1		;LOCKING BOTH SEGMENT?
	MOVE	T2,[XWD LKPB,LKPB]
	CAIG	P1,JOBMAX##	;LOCKING ONLY THE LOW SEGMENT?
	MOVEI	T2,LKPB		;YES
	SKIPN	T2		;SKIP IF LOCKING ONLY LOW SEGMENT OR BOTH
	MOVSI	T2,LKPB		;LOCKING ONLY THE HIGH SEGMENT
	TDNE	T1,T2		;EITHER SEGMENT TO BE LOCKED PHYSICALLY CONTIGUOUS?
	JRST	LOKJ14		;THE USER DOES NOT REQUIRE PHYSICAL CONTIGUITY,
				; CHECK FOR CONTIGUOUS IN EVM
	PUSHJ	P,LOKPHY	;ATTEMPT TO LOCK THE JOB IN PHYSICALLY CONTIGUOUS
				; MEMORY
	  JRST	ERROR5		;COULDN'T MAKE IT, GIVE THE USER AN ERROR RETURN
LOKJ14:	MOVEI	T1,0		;INDICATE THAT NEITHER SEGMENT IS ALREADY
				; LOCKED IN EVM
LOKJ15:	MOVE	P2,T1		;P2 = SEGMENTS ADDRESSES IF LOCKED ALREADY
	PUSHJ	P,GETTAC##	;RESTORE THE USER'S ARGUMENT
	TDCE	T1,[XWD LKEB,LKEB]
	TDNE	T1,[XWD LKEB,LKEB]
	SKIPA			;THE USER WANTS ONE OR BOTH SEGMENTS
				; LOCKED IN CONTIGUOUS EXEC VIRTUAL MEMORY
	JRST	LOKJ17		;ALL DONE
	PUSHJ	P,GETTAC##	;RESTORE USER'S ARGUMENT
	EXCH	T1,P2		;T1 REFLECTS THE PROGRESS SO FAR
	CAILE	P1,JOBMAX##	;LOCKING ONLY THE LOW SEGMENT?
	TLNE	T1,-1		;NO, IS THE HIGH SEGMENT ALREADY LOCKED?
	JRST	LOKJ16		;GO CHECK THE LOW SEGMENT
	TLNE	P2,LKEB		;LOCK THE HIGH SEGMENT VIRTUALLY CONTIGUOUS?
	JRST	LOKJ16		;NO
	PUSH	P,T1		;SAVE THE ADDRESS OF THE LOW SEGMENT
	HRRZ	J,P1		;J = THE HIGH SEGMENT NUMBER
	MOVSI	T1,(PM.CSH)	;ASSUME WANT CACHE OFF
	SETZ	T2,
	TLNE	P2,LKCB		;WANT CACHE OFF?
	EXCH	T1,T2		;NO, WANT IT ON
	DMOVEM	T1,.USTMP	;SET FLAGS FOR LOKEVM
	PUSHJ	P,LOKEVM	;ATTEMPT TO LOCK THE HIGH SEGMENT IN EVM
	  JRST	ERROR4		;NOT ENOUGH EVM
	HRLM	T1,(P)		;STORE THE EVA OF THE HIGH SEGMENT
	POP	P,T1		;RESTORE THE ADDRESSES OF THE SEGMENTS
	HLRZS	P1		;P1 = LOW SEGMENT NUMBER OF LOW SEGMENT IS
				; TO BE LOCKED
	JUMPE	P1,LOKJ17	;ALL DONE IF NOT LOCKING LOW SEGMENT
LOKJ16:	TRNN	P2,LKEB		;LOCK THE LOW SEGMENT VIRTUALLY CONTIGUOUS?
	TRNE	T1,-1		;YES, IS THE LOW SEGMENT ALREADY LOCKED IN EVM?
	JRST	LOKJ17		;YES, FINISH UP
	PUSH	P,T1		;SAVE THE ADDRESSES OF THE SEGMENTS
	MOVE	J,.CPJOB##	;J = LOW SEGMENT NUMBER
	MOVSI	T1,(PM.CSH)	;ASSUME WANT CACHE OFF
	SETZ	T2,
	TRNE	P2,LKCB		;WANT CACHE OFF?
	EXCH	T1,T2		;NO, WANT IT ON
	DMOVEM	T1,.USTMP	;SET FLAGS FOR LOKEVM
	PUSHJ	P,LOKEVM	;ATTEMPT TO LOCK THE LOW SEGMENT IN EVM
	  JRST	ERROR4		;NOT ENOUGH EVM
	HRRM	T1,(P)		;STORE THE EVA OF THE LOW SEGMENT
	POP	P,T1		;RESTORE THE ADDRESSES OF THE SEGMENTS
LOKJ17:	PUSHJ	P,CAFREE##	;RETURN THE LOCK RESOURCE
	S0PSHJ	SETRLH##
	PUSHJ	P,GETTAC##
	JUMPGE	T1,LOKRET	;GO IF NO LOCK EXTENSION
	PUSHJ	P,RASBAD	;GET PHYSICAL PAGE NUMBER
	  JFCL			;RASBAD SKIPS
	PJRST	STOTC1##	;STORE ANSWER, SKIP RETURN
;SUBROUTINE TO LOCK A SEGMENT IN PLACE
;CALLING SEQUENCE:
;	MOVE	J,SEGMENT NUMBER OF SEGMENT TO BE LOCKED IN PLACE
;	PUSHJ	P,LOKINP
;RETURN HERE, SEGMENT IS LOCKED IN PLACE

LOKINP:	MOVEI	T3,LOKIPB	;BIT INDICATING PAGE IS LOCKED IN PLACE
	PUSHJ	P,LOKBTS	;TURN IT ON FOR EVERY PAGE IN THE SEGMENT
	MOVEI	T1,0		;ADDRESS WHERE SEGMENT IS LOCKED IS ZERO
				; SINCE NOTHING ELSE IS MEANINGFUL
	POPJ	P,		;RETURN

LOKARG:	HRRI	M,(T1)		;POINT AT USER'S ARGUMENT LIST
	HLRE	T2,T1		;- LENGTH OF THE ARGUMENT LIST
	CAME	T2,[-2]		;MUST BE EXACTLY 2 WORDS LONG
	JRST	LOKAR1		;BAD ARGUMENT LIST
	PUSHJ	P,GETWDU##	;GET THE FIRST ARGUMENT (FUNCTION)
	JUMPL	T1,LOKAR1	;CAN'T BE NEGATIVE
	CAIL	T1,MXLFCN	;IS IT A LEGAL FUNCTION?
	JRST	LOKAR1		;NO, BAD ARGUMENT LIST
	ROT	T1,-1		;DIVIDE BY 2, SAVE THE REMAINDER IN HIGH BIT
	SKIPGE	T1		;SKIP IF AN EVEN FUNCTION
	SKIPA	T1,LOKFCN(T1)	;ODD FUNCTION, GET DISPATCH ADDRESS
	MOVS	T1,LOKFCN(T1)	;EVEN FUNCTION, GET DISPATCH ADDRESS
	TRNN	T1,-1		;IMPLIMENTED FUNCTION?
	JRST	LOKAR1		;NO, GIVE BAD ARGUMENT LIST RETURN
	AOS	(P)		;SET FOR GOOD RETURN
	HRRZS	T1		;CLEAR LEFT-HALF BITS, SO WE DON'T JRST BOONIES
	JRST	(T1)		;DISPATCH TO THE FUNCTION PROCESSOR
LOKAR1:	MOVEI	T1,LKERR5	;BAD ARGUMENT LIST ERROR CODE
	POPJ	P,		;NON-SKIP RETURN TO CALLER

LOKFCN:	LOKHPH,,0
MXLFCN==2*<.-LOKFCN>

LOKHPH:	PUSHJ	P,GETWD1##	;GET THE SECOND WORD OF THE ARGUMENT LIST
	TLZE	T1,-1		;LOCK THE HIGH SEGMENT AT A SPECIFIED ADDRESS?
	TLO	T1,LKB		;YES, INDICATE HIGH SEGMENT TO BE LOCKED
	TRZE	T1,-1		;LOCK THE LOW SEGMENT AT A SPECIFIED ADDRESS?
	TRO	T1,LKB		;YES, INDICATE LOW SEGMENT TO BE LOCKED
	POPJ	P,		;AND RETURN
;SUBROUTINE TO LOCK A SEGMENT CONTIGUOUSLY IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;	DMOVEM	,.USTMP		;.USTMP:  BITS TO ANDCAM WITH PAGE MAP ENTRY 
				;(E.G. PM.CSH)
				;.USTMP+1:  BITS TO IOR WITH PAGE MAP ENTRY
				;(E.G. PM.CSH)
;	MOVE	J,SEGMENT NUMBER OF SEGMENT TO BE LOCKED IN EVM
;	PUSHJ	P,LOKEVM
;RETURN HERE IF NOT ENOUGH EVM TO LOCK THE SEGMENT
;RETURN HERE, SEGMENT IS LOCKED IN EVM - T1 = EV PAGE NUMBER OF SEGMENT

LOKEVM:	LDB	T1,IMGIN##	;SIZE OF THE SEGMENT
	PUSH	P,T1		;SAVE THAT
	CAIG	J,JOBMAX##	;A LOW SEGMENT?
	ADDI	T1,UPMPSZ##	;YES, UPMP MUST BE MAPPED TOO
	MOVEI	T2,EVMPTR##	;POINT TO BIT MAP OF SLOTS IN THE EXEC MAP
				; USED FOR LOCKING IN EVM
	MOVE	T3,T1		;AMOUNT OF EVM NEEDED
	ADD	T3,.C0EVU##	;AMOUNT ALREADY IN USE
	CAMG	T3,.C0EVM##	;GREATER THAN TOTAL AVAILABLE?
	PUSHJ	P,GETBIT##	;GET, SET BITS IN THE EVL TABLE
	  PJRST	TPOPJ##		;NOT ENOUGH SLOTS AVAILABLE
	MOVE	T2,(P)		;NUMBER OF PAGES IN THIS SEGMENT
	CAIG	J,JOBMAX##
	ADDI	T2,UPMPSZ##
	ADDM	T2,.C0EVU##	;COUNT EVM IN USE FOR LOCKING
	CAILE	J,JOBMAX##	;LOW SEG?
	JRST	LOKEV1		;NO
	POP	P,T2
	PUSHJ	P,SAVE4##
	DMOVE	P1,T1
	ADDI	T1,UPMPSZ##
	PUSH	P,T1
	PUSH	P,M
	LSH	T1,P2WLSH##
	HRRM	T1,JBTADR##(J)
	MOVEI	P4,(T1)
	MOVE	P3,.CPMAP##
	HRLI	P1,(POINT 36,(P3),35)
	MOVE	T3,.UPMP+.UMUPT

	DPB	T3,P1
IFN FTMP,<
	PUSHJ	P,MAPUC##
>
	SETZM	.USSPT			;START
LOKEV5:	PUSHJ	P,NXTWSB##
	CAIA
LOKEV0:	PUSHJ	P,NXTWS3##
	TRNN	M,<-1^!HLGPNO>		;PAGE NOT IN USER SPACE?
	JRST	LOKEV4			;USER PAGE
	AOS	.USSPT			;PROCEED TO NEXT SECTION
	JRST	LOKEV5
LOKEV4:	PUSHJ	P,FPNSHS
	PUSH	P,T3
	MOVE	T3,(T4)
	TDZ	T3,.USTMP		;TURN OFF CACHE BIT IF ASKED TO
	TDO	T3,.USTMP+1		;OR ON IF ASKED TO
	MOVEM	T3,(T4)
	IDPB	T3,P1
IFN FTMP,<
	PUSHJ	P,MAPUC##
>
	POP	P,T3
	SOJG	P2,LOKEV0
	POP	P,M
	JRST	LOKEV2
LOKEV1:	MOVE	T3,T1		;SAVE STARTING PAGE IN THE EXEC MAP
	PUSH	P,J		;SAVE HIGH SEGMENT NUMBER
	MOVE	J,.CPJOB##	;JOB NUMBER
	PUSHJ	P,HSVAD##	;COMPUTE STARTING VIRTUAL ADDRESS OF THE HIGH SEGMENT
	POP	P,J
	MOVE	T1,T3		;RESTORE T1
	MOVE	T3,T2		;T3=VIRTUAL ADDRESS OF HIGH SEGMENT
	MOVE	T2,(P)		;NUMBER OF PAGES TO MAP IN THE EXEC MAP
IFN FTMP,<
	PUSH	P,T3		;SAVE UVA
>
	S0PSHJ	MAPUEV##	;COPY THE USER'S MAP INTO THE EXEC MAP
	HRRM	T3,JBTADR##(J)	;STORE THE EVA OF THIS SEGMENT
IFN FTMP,<
	POP	P,T3		;RESTORE UVA
>
	MOVE	T2,T1		;T2=EXEC VIRTUAL PAGE NUMBER OF THE SEGMENT
	EXCH	T2,(P)		;SAVE THAT, RESTORE NUMBER OF PAGES TO BE MAPPED
IFN FTMP,<
	S0PSHJ	MAPUEC##	;COPY USER'S MAP TO CPU1'S MAP
>
LOKEV2:	MOVEI	T3,LOKEVB	;BIT INDICATING PAGE IS LOCKED IN EVM
	PUSHJ	P,LOKBTS	;TURN IT ON FOR EACH PAGE IN THE SEGMENT
	PUSHJ	P,CONEVA	;COMPLETE LARGEST HOLE IN EVM
	PUSHJ	P,CSDMP##
	MOVE	T1,.CPJOB##
	MOVSI	T2,(JS.NCS)
	IORM	T2,JBTST2##(T1)
	PJRST	TPOPJ1##	;RESTORE EV PAGE NUMBER AND GIVE SUCCESS RETURN

LOKEXT:	HRRI	M,(T1)		;POINT M AT THE USER'S ARGUMENT LIST
	PUSHJ	P,LOKHPH	;GET THE USER'S FIRST ARGUMENT
	PUSHJ	P,CHKCSH	;SEE IF CACHE SHOULD BE OFF OR ON
	PUSHJ	P,GETWDU##
;HERE WITH T1= WHERE HIGH SEGMENT IS TO BE LOCKED,,WHERE LOW SEGMENT
; IS TO BE LOCKED, P1= LOW SEGMENT NUMBER,,HIGH SEGMENT NUMBER
	MOVE	P2,T1		;SAVE WHERE,,WHERE
	SETZM	LOKREL##	;INITIALIZE FOR IORM
	TLNN	P1,-1		;LOCKING BOTH SEGMENTS?
	JRST	LKSPH2		;NO
	HLRZ	T2,T1		;WHERE THE HIGH SEGMENT IS TO BE LOCKED
	HRRZ	T3,T1		;WHERE THE LOW SEGMENT IS TO BE LOCKED
	LDB	T4,PCORSZ##	;HIGHEST PAGE IN THE LOW SEGMENT
	ADDI	T4,1+UPMPSZ##(T3)
	CAIL	T2,(T3)		;IF LOCKED AS REQUESTED,
	CAIL	T2,(T4)		; WILL THE HIGH AND LOW SEGMENTS OVERLAP?
	CAIA			;NO
	JRST	ERROR6		;YES, ERROR RETURN
	LDB	T4,[POINT 9,JBTADR##(P1),8]
	ADDI	T4,1(T2)	;TOP PAGE IN HIGH SEGMENT AFTER LOCKING
	CAIL	T3,(T2)		;IF LOCKED AS REQUESTED,
	CAIL	T3,(T4)		; WILL THE HIGH AND LOW SEGMENTS OVERLAP?
	JRST	LKSPH2		;NO, ALL IS WELL SO FAR
	JRST	ERROR6
LKSPH2:	HLRZ	J,P1		;LOW SEGMENT NUMBER IF LOCKING BOTH SEGMENTS
	CAIG	P1,JOBMAX##	;LOCKING BOTH SEGMENTS OR JUST THE HIGH SEGMENT?
	JRST	[HRRZ J,P1	;NO, ONLY LOCKING THE LOW SEGMENT
		 JRST LKSPH3]
	HLRZS	T1		;WHERE THE HIGH SEGMENT IS TO BE LOCKED
	HRRZ	J,P1		;HIGH SEGMENT NUMBER
	PUSHJ	P,PHYPF		;ARE THE PAGES AVAILABLE FOR LOCKING?
	  JRST	ERROR6		;NO, ERROR RETURN
	HRRZM	T1,LOKREL##	;STORE WHERE THE HIGH SEGMENT IS TO BE LOCKED
	HLRZ	J,P1		;LOW SEGMENT NUMBER IF LOCKING THE LOW SEGMENT
	JUMPE	J,LKSPH4	;ALL DONE IF NOT LOCKING THE LOW SEGMENT
LKSPH3:	HRRZ	T1,P2		;WHERE THE LOW SEGMENT IS TO BE LOCKED
	PUSHJ	P,PHYPF		;SEE IF THOSE PAGES ARE AVAILABLE FOR LOCKING
	  JRST	ERROR6		;NOT, LOSE
	SKIPE	LOKREL##	;HIGH SEGMENT TO BE LOCKED?
	HRLZS	T1		;YES, PAGE NUMBER TO THE LEFT HALF WORD
	IORM	T1,LOKREL##	;WHERE LOW,,WHERE HIGH
LKSPH4:	MOVE	J,.CPJOB##	;CURRENT JOB NUMBER
	PUSHJ	P,LOCKIT	;LOCK THE SEGMENTS REQUESTED WHERE REQUESTED
	  JFCL			;CAN'T HAPPEN
	JRST	LOKJ17		;GIVE JOB LOCKED RETURN
;SUBROUTINE TO DETERMINE IF A SEGMENT CAN BE LOCKED IN A SPECIFIC
; PLACE IN PHYSICAL MEMORY. I.E., DETERMINE THAT THE PAGES REQUIRED ARE
; EXISTANT, NOT LOCKED, AND NOT PART OF THE MONITOR.
;CALLING SEQUENCE:
;	MOVE	T1,STARTING PHYSICAL PAGE #
;	MOVE	J,SEGMENT #
;	PUSHJ	P,PHYPF
;RETURN CPOPJ, T1=LKERR6 IF THE PAGES ARE NOT AVAILABLE
; CPOPJ1 IF THEY ARE, T1 PRESERVED

PHYPF:	LDB	T2,[POINT 9,SYSSIZ##,26]
	LDB	T3,[POINT 14,MEMSIZ##,26]
	CAIL	T1,(T2)		;ABOVE THE MONITOR?
	CAIL	T1,(T3)		;AND BELOW THE TOP OF MEMORY?
	POPJ	P,		;NO, LOSE
	LDB	T2,PCORSZ##	;HIGHEST PAGE IN THE SEGMENT
	ADDI	T2,1		;NUMBER OF PAGES IN THE SEGMENT
	CAIG	J,JOBMAX##	;IF A LOW SEGMENT,
	ADDI	T2,UPMPSZ##	;ACCOUNT FOR THE LOW SEGMENT SIZE
	MOVE	T3,T1		;STARTING PAGE FOR LOCKING THE SEGMENT
IFN FTMP,<
	PUSHJ	P,GGVMM##	;MUST HAVE THE MM RESOURCE WHILE LOOKING AT PAGTAB
>
PHYPF1:	MOVE	T4,@[IW MS.MEM,PAGTAB(T3)] ;PAGTAB ENTRY REPRESENTING
				; THIS PHYSICAL PAGE
	TLNE	T4,LKBITS	;LOCKED OR NON-EXISTANT PAGE?
	POPJ	P,		;YES, LOSE
	SOSE	T2		;LOOKED AT ALL THE PAGES REQUIRED TO LOCK THE SEGMENT?
	AOJA	T3,PHYPF1	;NO, CHECK THE NEXT PHYSICAL PAGE
	AOS	(P)		;SKIP RETURN (ALL PAGES FREEABLE)
	LDB	T2,PCORSZ##	;SIZE
	PJRST	SETLIP		;SET LOCK IN PROGRESS
;SUBROUTINE TO SET "LOCK IN PROGRESS" ON ALL PAGES WHERE A PHYSICALLY
;CONTIGUOUS LOCK IS BEING PERFORMED.  MUST BE CALLED WITH MM
;CALL:
;		MOVE	T1,STARTING PAGE #
;		MOVE	T2,# OF PAGES TO SET FOR
;		PUSHJ	P,SETLIP
;		  RETURN
;PRESERVES ALL

SETLIP:	SE1ENT		;MUST RUN IN S1 FOR PAGTAB/MEMTAB
	PUSHJ	P,SAVT##
	PUSH	P,T2		;SAVE COUNT
	MOVSI	T4,(P2.LIP)		;LOCK IN PROGRESS
SETLI1:	IORM	T4,@[IW MS.MEM,PT2TAB(T1)]	;SET IT
	SKIPL	T3,@[IW MS.MEM,PAGTAB(T1)]	;IS PAGE FREE?
	JRST	SETLI4			;NO, CONTINUE
	HRRZ	T2,@[IW MS.MEM,PT2TAB(T1)] ;GET BACK LINK
	TRNE	T3,-1			;IF THERE IS A SUCCESSOR,
	HRRM	T2,@[IW MS.MEM,PT2TAB(T3)] ;THEN SET PREDECESSOR
	JUMPE	T2,[HRRZM T3,PAGPTR##	;IF IT WAS THE FIRST ON THE FREE LIST
		    JRST  SETLI2     ]
	HRRM	T3,@[IW MS.MEM,PAGTAB(T2)] ;DELINK FROM THE FREE LIST
SETLI2:	HRRZ	T2,LOKPTR##		;PUT IT ON LOKCON'S LIST
	HRRM	T2,@[IW MS.MEM,PAGTAB(T1)]
	SKIPE	T2
	HRRM	T1,@[IW MS.MEM,PT2TAB(T2)]
	HLLZS	@[IW MS.MEM,PT2TAB(T1)]
	HRRZM	T1,LOKPTR##
	AOS	LOKHOL##		;COUNT THE PAGE IN LOKHOL
	AOS	LOKTAL##		;AND IN LOKTAL
	SOS	CORTAL##		;DON'T COUNT TWICE
	SOS	BIGHOL##
SETLI4:	SOSLE	(P)			;MORE TO GO?
	AOJA	T1,SETLI1		;YES
	POP	P,(P)			;CLEAR STACK
	POPJ	P,
;SUBROUTINE TO MOVE ALL PAGES FROM LOKCON'S QUEUE (LOKPTR) TO THE
;FREE QUEUE AND CLEAR P2.LIP.  THIS SHOULD BE CALLED JUST BEFORE
;THE ACTUAL LOCK IS DONE.  CALL WITH J=SEGMENT #

CLRLOQ:	PUSHJ	P,SAVE3##		;SAVE SOME ACS
	SKIPN	P2,LOKPTR##		;GET LOKCON QUEUE
	JRST	CLRLQ2			;BE SURE P2.LIP CLEAR
CLRLQ1:	SSX	P2,MS.MEM		;WHERE PT2TAB ETC. LIVE
	HRRZ	P3,P2			;SAVE
	HRRZ	P2,PAGTAB(P2)		;NEXT
	JUMPN	P2,CLRLQ1		;CLEAR IT
	MOVE	P1,PAGPTR##		;START OF THE FREE LIST
	SSX	P3,MS.MEM		;SECTION
	HRRM	P1,PAGTAB(P3)
	SSX	P1,MS.MEM
	HRRM	P3,PT2TAB(P1)
	MOVE	P2,LOKPTR##
	MOVEM	P2,PAGPTR##		;NEW HEAD OF FREE LIST
	MOVE	P1,LOKTAL##		;COUNT
	ADDM	P1,CORTAL##
	MOVE	P1,LOKHOL##
	ADDM	P1,BIGHOL##		;PAGES ARE BACK ON THE FREE LIST
	SETZM	LOKHOL##
	SETZM	LOKTAL##
	SETZM	LOKPTR##
CLRLQ2:	MOVE	P1,LOKREL##		;FIRST PAGE
	SSX	P1,MS.MEM	;PT2TAB SECTION
	LDB	P3,IMGIN##	;SIZE
	CAILE	J,JOBMAX##	;LOW SEG?
	JRST	CLRLQ3
	LDB	P2,NFYPGS##	;ADD FUNNY PAGES IF LOW SEG
	ADDI	P3,(P2)
	LDB	P2,NZSSCN##
	ADDI	P3,(P2)
CLRLQ3:	MOVSI	P2,(P2.LIP)	;LOCK-IN-PROGRESS BIT
CLRLQ4:	ANDCAM	P2,PT2TAB(P1)
	SOSL	P3
	AOJA	P1,CLRLQ4
	POPJ	P,
;SUBROUTINE TO LOCK A JOB (ONE OR BOTH SEGMENTS) IN CONTIGUOUS
; PHYSICAL MEMORY
;CALLING SEQUENCE:
;	MOVE	P1,0,,LOW SEGMENT NUMBER IF LOCKING ONLY LOW SEGMENT, OR
;	MOVE	P1,0,,HIGH SEGMENT NUMBER IF LOCKING ONLY HIGH SEGMENT, OR
;	MOVE	P1,LOW SEGMENT NUMBER,,HIGH SEGMENT NUMBER IF LOCKING BOTH
;	PUSHJ	P,LOKPHY
;RETURN HERE IF NO HOLE IN PHYSICAL MEMORY IS BIG ENOUGH
;RETURN HERE, REQUESTED SEGMENTS ARE LOCKED IN CONTIGUOUS PHYSICAL MEMORY

LOKPHY:	HRRZ	T2,P1		;MAKE A USABLE INDEX
	MOVE	T2,JBTSTS##(T2)	;HIGH SEGMENT STATUS IF LOCKING THE HIGH SEGMENT
	CAILE	P1,JOBMAX##	;LOCKING THE HIGH SEGMENT?
	TLNE	T2,SHRSEG	;YES, IS IT SHARABLE?
	CAIA			;YES
	HLRZS	P1		;NO, LOCK LOW AND HIGH SEGMENT ALL AT ONCE
	HLRZ	J,P1		;LOW SEGMENT NUMBER (OR ZERO)
	LDB	T1,IMGIN##	;SIZE OF THE LOW SEGMENT (OR ZERO)
	LDB	T2,NFYPGS##	;NUMBER OF FUNNY PAGES (OR ZERO)
	ADD	T1,T2		;TOTAL
	LDB	T2,NZSSCN##
	ADD	T1,T2		;# OF NZS MAPS
	HRRZ	J,P1		;HISEG NUMBER (OR MAYBE LOWSEG)
	LDB	T2,IMGIN##	;SIZE OF IT
	ADD	T1,T2		;TOTAL
	CAILE	J,JOBMAX##	;IS IT A LOWSEG?
	JRST	LOKPH0
	LDB	T2,NFYPGS##	;NUMBER OF FUNNY PAGES (IF IT'S A LOWSEG)
	ADD	T1,T2		;YES, COUNT THAT TOO
	LDB	T2,NZSSCN##
	ADD	T1,T2
LOKPH0:	MOVE	T2,SYSSIZ##	;LOOK FOR A PLACE TO LOCK IT STARTING AT
				; THE TOP OF THE MONITOR
	LSH	T2,W2PLSH##	;CONVERT SYSSIZ TO PAGES
	MOVE	T3,MEMSIZ##	;LOOK THROUGH ALL OF USER CORE
	LSH	T3,W2PLSH##	; A PAGE AT A TIME
IFN FTMP,<
	PUSHJ	P,UPMM##	;MUST HAVE THE MM RESOURCE WHEN SCANNING PAGTAB
>
LOKPH1:	TDZA	T4,T4		;LARGEST HOLE SEEN SO FAR
LOKPH2:	ADDI	T4,1		;INCREMENT SIZE OF LARGEST HOLE
	CAIN	T3,(T2)		;LOOKED AT ALL OR CORE?
	JRST	LOKPH4		;YES, SEE IF A BIG ENOUGH HOLE WAS FOUND
	MOVE	S,@[IW MS.MEM,PAGTAB(T2)] ;STATUS OF THIS PAGE
	TLNN	S,LKBITS	;IS IT LOCKED OR NON-EXISTANT?
	AOJA	T2,LOKPH2	;NO, COUNT IT IN THIS HOLE
	CAMG	T4,T1		;IS THIS HOLE BIG ENOUGH?
	AOJA	T2,LOKPH1	;NO, LOOK HIGHER UP
LOKPH4:
	CAMG	T4,T1		;IS THE HOLE FOUND BIG ENOUGH?
IFN FTMP,<
	PJRST	DWNMM##		;NO, ERROR RETURN
>
IFE FTMP,<
	POPJ	P,
>
	SUBI	T2,(T4)		;STARTING PAGE NUMBER OF THE HOLE
	HRRZM	T2,LOKREL##	;SAVE THAT FOR LOCK
	EXCH	T1,T2
	PUSHJ	P,SETLIP	;SET "LOCK IN PROGRESS" AND MOVE PAGES
IFN FTMP,<
	PUSHJ	P,DWNMM##	;RETURN MM
>
	HRRZ	J,P1		;SIZE OF THE FIRST SEGMENT TO BE LOCKED
	LDB	T1,IMGIN##
	CAIG	P1,JOBMAX##	;LOCKING HIGH SEGMENT?
	ADDI	T1,UPMPSZ##	;NO, ACCOUNT FOR THE UPMP
	ADD	T1,LOKREL##	;STORE THAT FOR LOCK
	TLNE	P1,-1		;LOCKING BOTH SEGMENTS?
	HRLM	T1,LOKREL##	;WHERE TO LOCK THE OTHER SEGMENT
LOCKIT:	MOVEM	P1,LOCK##	;STORE SEGMENT NUMBERS FOR LOCK
	MOVE	J,.CPJOB##
	MOVEI	T1,LOK		;MAKE THE JOB UNRUNNABLE UNTIL LOCKING
	IORM	T1,JBTSTS##(J)	; IS COMPLETE
	PUSHJ	P,WSCHED##	;RESCHEDULE, RETURN WHEN JOB IS LOCKED
RASBAD:	LDB	T1,JBYLSA##	;STARTING PAGE NUMBER OF THE LOW SEGMENT
	SKIPG	J,JBTSGN##(J)	;JOB HAVE A REAL HIGH SEGMENT?
	 PJRST	CPOPJ1##	;NO HISEG, GIVE LOCKED RETURN (T1 = LOSEG ADDR)
	TLO	J,(1B0)		;MAKE J A REASONABLE INDEX
	LDB	T2,JBYHSA##	;STARTING PAGE NUMBER OF THE HIGH SEGMENT
	HRL	T1,T2		;HIGH SEGMENT ADDRESS,,LOW SEGMENT ADDRESS
	PJRST	CPOPJ1##	;AND GIVE LOCKED RETURN
;
;ROUTINE TO FREE CORE GIVEN UP BY A LOCKED JOB
;CALLED FROM UUOCON ON RESET UUO FROM USER OR
;ON A CALL TO RESET FROM COMCON
;ALSO CALLED FROM KILHGH IN SEGCON
;

UNLOKH::SE1ENT			;LOKCON ALWAYS RUNS EXTENDED
	MOVE	J,-2(P)		;GET JOB NUMBER
	MOVSI	T1,LKB		;UNLOCK THE HIGH SEGMENT
	JRST	UNLO00		;UNLOCK IT IF NOT LOCKED FOR SOME OTHER JOB
UNLOK.::SE1ENT			;RUN THIS EXTENDED.
	TDCN	T1,[LKB,,LKB]	;NOT UNLOCKING ANYTHING?
	JRST	CPOPJ1##	;YES, ALWAYS LEGAL
	TDCE	T1,[LKB,,LKB]	;YES, UNLOCKING BOTH SEGMENTS?
	SKIPG	T2,JBTSGN##(J)	;REAL HIGH SEG?
	JRST	UNLOK1		;NO HIGH SEGMENT OR UNLOCKING BOTH
	TLNE	T2,SHRSEG	;HIGH SEGMENT SHARABLE?
	JRST	UNLOK1		;YES, PROCEED TO UNLOCK
	TLNN	T2,LOKSEG+NCSH	;NO, IS IT ACTUALLY LOCKED?
	JRST	CPOPJ1##	;NO, NOT REALLY LOCKED
				;(WE CAN RETURN SUCCESSFULLY BECAUSE TH
				;LOW SEGMENT CANNOT BE LOCKED IN THIS CASE.)
	POPJ	P,		;YES, CANNOT UNLOCK ONLY ONE SEGMENT
UNLOK1:	AOSA	(P)		;GIVE SKIP RETURN
UNLOCK::MOVE	T1,[XWD LKB,LKB];UNLOCK BOTH LOW AND HIGH SEGMENTS
UNLO00:	SE1ENT			;CALL COROUTINE PUSHING ACS ON STACK
	PUSHJ	P,SAVE4##	;PRESERVE ACCUMULATORS
	PUSH	P,T1		;SAVE ARGUMENT WHILE UNLOCKING
ZZ==.				;PLACE ON STACK FOR ARGUMENT (T1)
	PUSH	P,J		;SAVE JOB NUMBER
ZZ==.-ZZ			;DEPTH ON STACK FOR ARGUMENT (T1)
	MOVSI	P4,NSHF!NSWP
	MOVEI	J,(J)		;CLEAR POSSIBLE LEFT HALF BITS
	CAILE	J,JOBMAX##	;IS THIS A HIGH SEGMENT?
	JRST	UNLO04		;YES IF CALLED FROM SEGCON OR LOKINI
	TRNE	T1,LKB		;UNLOCK THE LOW SEGMENT?
	TDNN	P4,JBTSTS##(J)	;IS IT LOCKED?
	JRST	UNLO01		;NO
IFN FTRTTRP,<
	S0PSHJ	RTREL##		;RESET REAL TIME
>
	PUSHJ	P,FRELOK	;UNLOCK THE LOW SEGMENT
	MOVSI	P2,(JS.NCS)	;DON'T CACHE BIT
	TDNE	P2,JBTST2##(J)
	PUSHJ	P,CSHLSG
	ANDCAM	P2,JBTST2##(J)	;TURN THE CACHE ON AGAIN
	MOVE	T1,-ZZ(P)	;RESTORE ARGUMENT
	HRROS	-ZZ(P)		;FLAG THAT CORE HAS CHANGED (SO CALL LRGHOL)
UNLO01:	TLNN	T1,LKB		;UNLOCK THE HIGH SEGMENT?
	JRST	UNLO05		;NO
	MOVSI	P2,LOKSEG+NCSH
	SKIPLE	P3,JBTSGN##(J)	;DOES THE JOB HAVE A REAL HIGH SEGMENT
	TDNN	P2,JBTSGN##(J)	;AND IS IT LOCKED
	JRST	UNLO05		;NO
	ANDCAM	P2,JBTSGN##(J)	;TURN OFF HIGH SEGMENT LOCKED FOR THIS JOB
	S0PSHJ	MAPHGH##	;TURN ON CACHE BITS IN THE MAP
	MOVE	T1,HIGHJB##	;IS ANOTHER JOB SHARING THE HIGH SEGMENT?
UNLO02:	SKIPG	JBTSGN##(T1)	;A REAL HIGH SEGMENT?
	JRST	UNLO03		;NO
	HRRZ	P1,JBTSGN##(T1)
	CAME	T1,(P)		;CURRENT JOB?
	CAIE	P1,(P3)		;SAME HIGH SEGMENT?
	JRST	UNLO03		;THIS SEGENT DOESN'T STOP UNLOCKING
	TDNE	P2,JBTSGN##(T1)	;IS THE LOW SEGMENT SHARING LOCKED?
	JRST	UNLO05		;YES, CAN'T UNLOCK THE HIGH SEGMENT
UNLO03:	SOJG	T1,UNLO02
	HRRZ	J,P3
UNLO04:	TDNN	P4,JBTSTS##(J)	;IS HIGH SEGMENT LOCKED?
	JRST	UNLO05		;NO, DO NOT UNLOCK HIGH SEGMENT
	HRROS	-ZZ(P)		;YES, FLAG FACT THAT A SEGMENT HAS
				; BEEN UNLOCKED
	PUSHJ	P,FRELOK	;NO OTHER LOCKED JOB SHARING, UNLOCK IT
UNLO05:	HRRZ	J,(P)		;GET INDEX INTO JOB TABLES
	MOVE	R,JBTADR##(J)	;RESTORE R
	POP	P,J		;RESTORE JOB NUMBER
	POP	P,T1		;HAS CORE CHANGED?
	JUMPGE	T1,CPOPJ##	;NO, REMOVE ARGUMENT AND RETURN
;FALL INTO COMLIM
;SUBROUTINE TO RECOMPUTE CORMAX AND MAXMAX
COMLIM:	PUSHJ	P,LRGHOL	;SET EXTENT OF THE LARGEST HOLE
	MOVEM	T2,MAXMAX##	;LARGEST LEGAL CORMAX
	SUBI	T2,NWMCP+PAGSIZ##	;ACCOUNT FOR FUNNY SPACE
	MOVEM	T2,RMCMAX##	;SET "REAL" MAXIMUM VALUE OF CORMAX
	HRRZ	P1,CORLIM##	;AND ADJUST CORMAX
	ASH	P1,P2WLSH##
	CAMLE	P1,T2		;TO CORLIM OR SIZE OF HOLE
	MOVE	P1,T2		;WHICH EVER IS SMALLER
	MOVEM	P1,CORMAX##
	POPJ	P,		;RETURN
FRELOK:	ANDCAM	P4,JBTSTS##(J)	;TURN OFF NSHF AND NSWP
	LDB	T1,JBYLSA##	;PAGE NUMBER OF FIRST PAGE OF THE LOW SEGMENT
	CAILE	J,JOBMAX##	;IS IT A HIGH SEGMENT?
	LDB	T1,JBYHSA##	;PAGE NUMBER OF FIRST PAGE OF THE HIGH SEGMENT
	MOVSI	T2,LOKEVB	;BIT INDICATING LOCKED IN EVM
	TDNN	T2,@[IW MS.MEM,PAGTAB(T1)] ;IS IT?
	JRST	FRELK2		;NO, PROCEED
	PUSH	P,T1		;SAVE STARTING PAGE NUMBER
	LDB	T1,IMGIN##
	HRRZ	T3,JBTADR##(J)	;EVA OF SEGMENT
	LSH	T3,W2PLSH##	;STARTING PAGE NUMBER
	CAILE	J,JOBMAX##	;A LOW SEGMENT?
	JRST	[PUSHJ P,SEGSIZ##
		 MOVE T1,T2
		 JRST FRELK1]	;NO, SKIP ON
	ADDI	T1,UPMPSZ##	;YES ACCOUNT FOR THE MAP
	SUBI	T3,UPMPSZ##	; WHICH IS ALSO MAPPED
FRELK1:	MOVN	T4,T1		;GET THE NUMBER OF PAGES IN SEGMENT
	ADDM	T4,.C0EVU##	;AND INDICATE THAT EVM IS NO LONGER USED
	MOVE	T2,EVMPTR##	;AOBJN POINTER FOR RETURNING SLOTS
	S0PSHJ	ZERBTS##	;RETURN EVM
	PUSHJ	P,CONEVA
	POP	P,T1		;RESTORE STARTING PAGE NUMBER
FRELK2:	MOVE	R,JBTADR##(J)	;EVA OF SEGMENT
	HRRI	R,.VJDT		;ASSUME ITS A HIGH SEGMENT
	CAILE	J,JOBMAX##	;IS IT?
	JRST	FRELK3		;YES
	HRRI	R,.JDAT		;ITS A LOW SEGMENT - EVA OF THE JOB DATA AREA
	CAMN	J,.CPJOB##	;ONLY UPDATE .CPADR IF IT'S THIS JOB
	MOVEM	R,.CPADR##	;RESET SOFTWARE RELOCATION INFO
	HRRZ	T3,P		;DIDDLE THE PUSH DOWN LIST POINTER
	MOVEI	T2,PDLPNO##	;PAGE NUMBER (EVA) OF THE PUSH DOWN LIST
	CAMLE	T3,SYSSIZ##	;IS THE PUSH DOWN LIST IN THE MONITOR?
	DPB	T2,[POINT 9,P,26];NO, AJUST RELOCATION
FRELK3:	MOVEM	R,JBTADR##(J)	;UPDATE JBTADR
FRELK4:	MOVSI	T2,LKBITS	;BITS INDICATING A PAGE IS LOCKED
	ANDCAB	T2,@[IW MS.MEM,PAGTAB(T1)] ;CLEAR THEM
	HRRZ	T1,T2		;NEXT PAGE IN THE SEGMENT
	JUMPN	T1,FRELK4	;LOOP IF MORE PAGES IN THE SEGMENT
	CAILE	J,JOBMAX##	;IS THIS A LOW SEGMENT?
	POPJ	P,		;NO, RETURN
	HRRZ	T1,JBTUPM##(J)	;YES, UNLOCK THE UPMP
	MOVSI	T2,LKBITS	;BITS INDICATING PAGES IS LOCKED
	ANDCAM	T2,@[IW MS.MEM,PAGTAB(T1)] ;CLEAR THEM FOR THE UPMP
	HRRZ	T1,@[IW MS.MEM,PAGTAB(T1)] ;GET THE MAP PAGE TOO.
	ANDCAM	T2,@[IW MS.MEM,PAGTAB(T1)]

	POPJ	P,		;AND RETURN
;SUBROUTINE TO DETERMINE IF A RANGE OF MEMORY OVERLAPS LOCKED JOBS
; AND IF SO, RETURN ALL THE JOBS WHICH OVERLAP THE RANGE
CKLJB::	SE1ENT			;NEED TO BE EXTENDED TO LOOK AT PAGTAB
	ADDI	J,1		;NEXT JOB
	CAMLE	J,HIGHJB##	;UP TO THE HIGHEST JOB IN THE SYSTEM?
	POPJ	P,		;YES, ALL DONE
	MOVE	T3,JBTSTS##(J)	;JOB STATUS FOR THE CURRENT JOB
	TLNN	T3,NSHF!NSWP	;IS IT LOCKED?
	JRST	CKLJB1		;NO, CHECK ITS HIGH SEGMENT
	HRRZ	T3,JBTUPM##(J)	;ADDRESS OF THE JOBS PAGE MAP
	PUSHJ	P,CKRNG		;SEE IF THATS WITHIN THE RANGE
	  JRST	CPOPJ1##	;YES, INDICATE OVERLAP
	PUSHJ	P,FSTPG		;GET THE PAGE NUMBER OF THE FIRST PAGE OF THE JOB
	PUSHJ	P,CKPGS		;SEE IF ANY OF THE JOBS PAGES OVERLAP THE RANGE
	  JRST	CPOPJ1##	;YES, INDICATE THAT TO THE CALLER
CKLJB1:	SKIPLE	T3,JBTSGN##(J)	;DOES THE JOB HAVE A REAL HIGH SEGMENT?
	TLNN	T3,LOKSEG	;AND IS IT LOCKED?
	JRST	CKLJB		;NO, LOOK AT THE NEXT JOB
	HRRZS	T3		;CLEAR LH BITS, SO WE CAN USE AS INDEX
	LDB	T3,[POINT 13,JBTHSA##(T3),35]
	PUSHJ	P,CKPGS		;SEE IF THE HIGH SEGMENT PAGES OVERLAP THE RANGE
	  JRST	CPOPJ1##	;THEY DO, TELL THE CALLER
	JRST	CKLJB		;THEY DON'T SO LOOK AT THE NEXT JOB

;SUBROUTINE TO DETERMINE IF ATTEMPTING TO SET MONITOR PAGES OFF-LINE
CKMOL::	SE1ENT			;TO INDICATE THE ENTIRE MODULE RUNS EXTENDED
	LDB	T3,[POINT 9,SYSSIZ##,26]
	CAIL	T1,(T3)		;LOWER BOUND BELOW SYSSIZ?
	AOS	(P)		;NO, INDICATE GOODNESS
	POPJ	P,		;RETURN

;SUBROUTINE TO COMPUTE THE VALUE CORMAX WOULD HAVE IF A RANGE OF PAGES
; WERE TO BE SET OFF LINE
NEWCMX::SE1ENT			;MUST BE EXTENDED TO LOOK AT PAGTAB
	MOVEI	T3,0		;NUMBER OF ON LINE PAGES IN THE RANGE
	MOVSI	T4,NXMBIT	;BIT INDICATING PAGE IS NON-EXISTANT
NEWCM1:	TDNN	T4,@[IW MS.MEM,PAGTAB(T1)] ;IS THIS PAGE NOW ON LINE
	ADDI	T3,PAGSIZ##	;YES, COUNT IT
	CAIE	T1,-1(T2)	;LOOKED AT ALL THE PAGES IN THE RANGE?
	AOJA	T1,NEWCM1	;NO, LOOK AT THE NEXT PAGE
	MOVE	T1,MAXMAX##	;CURRENT MAXIMUM VALUE FOR CORMAX
	SUB	T1,T3		;NEW MAXIMUM VALUE FOR CORMAX IF PAGES
				; IN THE RANGE WERE SET OFF
	POPJ	P,		;RETURN THE NUMBER TO THE CALLER
;HERE TO SET MEMORY OFF LINE (T1 = FIRST PAGE TO SET OFF, T2 = HIGHEST
; PAGE TO SET OFF)
MEMOFL::HRRZ	S,T1		;LOWER BOUND
	HRL	S,T2		;UPPER BOUND
	JSP	T2,SAVCTD##	;GET TO UUO LEVEL
	HRRZ	T1,S		;RESTORE LOWER BOUND
	HLRZ	T2,S		;AND UPPER BOUND
MEMOFU::SKIPE	LOCK##		;LOCKING IN PROGRESS?
	PUSHJ	P,DELAY1	;YES, WAIT A WHILE AND TRY AGAIN
	LDB	T3,[POINT 14,MEMSIZ##,26]
	CAIL	T1,(T3)		;TRYING TO SET MEMORY OFF ABOVE THE TOP OF MEMORY?
	POPJ	P,		;YES, IT'S ALREADY OFF
	CAIL	T2,(T3)		;HIGH PAGE ABOVE THE TOP OF MEMORY?
	MOVE	T2,T3		;YES, SET HIGH PAGE TO LAST PAGE OF MEMORY
	MOVEM	T1,LOKREL##	;FIRST PAGE TO SET OFF
	SUB	T2,T1		;COMPUTE THE NUMBER OF PAGES IN THE RANGE
	HRLM	T2,LOKREL##	;STORE THAT FOR LOCK
	MOVEI	T3,0		;ASSUME NO MONITOR PAGES TO MOVE AND NO
				; ON LINE PAGES TO SET OFF
	SE1ENT			;GO INTO SECTION 1 NOW, TO LOOK AT PAGTAB..
MEMOF1:	MOVE	T4,@[IW MS.MEM,PAGTAB(T1)] ;PAGE DESCRIPTOR BITS
	TLNE	T4,MONTRB	;DOES THIS PAGE CONTAIN MONITOR CODE?
	AOSA	T3		;YES, COUNT UP THE NUMBER OF MONITOR PAGES
	TLNN	T4,NXMBIT	;DOES THIS PAGE EXIST (IS IT ON LINE)?
	TLO	T3,-1		;YES, INDICATE AT LEAST ONE ON LINE PAGE SEEN
	ADDI	T1,1		;NEXT PAGE IN THE RANGE
	SOJG	T2,MEMOF1	;LOOK AT EVERY PAGE IN THE RANGE
	JUMPGE	T3,CPOPJ##	;EXIT IF NO ONLINE PAGES SEEN
	PUSHJ	P,CAWAIT##	;GET THE CA RESOURCE
	HRROM	J,LASLOK##	;INDICATE SETTING MEMORY OFF-LINE AND SAVE JOB NUMBER
IFN FTMP,<
	PUSHJ	P,ONCPU0##	;MAKE SURE ON THE BOOT CPU
>; END IFN FTMP
	TRNN	T3,-1		;MOVING MONITOR PAGES?
	JRST	MEMOF2		;NO, GO SET THE PAGES OFF
	PUSH	P,T3		;SAVE THE NUMBER OF MONITOR PAGES BEING SET OFF
IFN FTENET&FTKL10,<
	PUSHJ	P,KNIMOF##	;INFORM KLNI ABOUT MEMORY GOING OFFLINE
>; END IFN FTENET&FTKL10
IFN FTSCA,<
	PUSHJ	P,PPDMFL##	;DO PHYSICAL PORT DRIVER MEMORY OFFLINE CHECKS
>; END IFN FTSCA
	MOVEI	T1,3		;SLEEP 3 SECONDS TO LET THINGS SETTLE DOWN
	S0PSHJ	SLEEPF##	;ZZZZZZ
	POP	P,T3		;RESTORE NUMBER OF MONITOR PAGES
	HRRZM	T3,MOFLPG##	;STORE THE NUMBER OF MONITOR PAGES WHICH MUST BE MOVED
IFN FTMP,<
	PUSHJ	P,CP1STP##	;ASK CPU1 TO JUMP INTO ITS ACS
	  PUSHJ	P,DELAY1	;AND WAIT UNTIL IT DOES
>; END IFN FTMP
MEMOF2:	SETOM	LOCK##		;INDICATE SETTING PAGES OFF LINE IS IN PROGRESS
	MOVEI	T1,LOK		;PREVENT THE JOB FROM RUNNING UNTIL DONE
	IORM	T1,JBTSTS##(J)	; ..
	PUSHJ	P,USCHED##	;COME BACK WHEN THE MEMORY HAS BEEN SET OFF
	PUSHJ	P,CAFREE##	;MAKE THE LOCK RESOURCE AVAILABLE
IFN FTENET&FTKL10,<
	PUSHJ	P,KNIMON##	;LET KLNI KNOW THE COAST IS CLEAR
>; END IFN FTENET&FTKL10
IFN FTSCA,<
	PUSHJ	P,PPDMON##	;LET PHYSICAL PORT DRIVER CLEAN UP AS REQUIRED
>; END IFN FTSCA
IFN FTMP,<
	HRROI	T1,[MOVEM T2,.CPOK##-.CPCDB##(P1)
		    POPJ  P,]
	MOVN	T2,TICSEC##	;ONE SECOND TO GET THEIR OWN OK WORDS GOING AGAIN
	PUSHJ	P,CPUAPP##	;GIVE THE OTHER CPUS THIS MUCH TIME
	SETZM	MOFLPG##	;NOT SETTING MONITOR PAGES OFF LINE
>
	MOVE	T1,[.CSCMF,,.ERCSC]	;MEMORY OFF-LINE INDICATOR
	PUSH	P,J		;SAVE J FOR COMRET
	PUSHJ	P,DAEEIM##	;TELL DAEMON ABOUT THE MEMORY CONFIGURATION CHANGE
	POP	P,J		;RESTORE J

	PJRST	SETEDV##	;RESET EDV POINTERS AND RETURN
;SUBROUTINE TO SLEEP A TICK AND THEN RETRY AN OPERATION. ALWAYS RETURNS TO
; CALL MINUS ONE

DELAY1:	PUSHJ	P,SAVT##	;DON'T CLOBBER CALLERS ACS
	MOVEI	T1,0		;SLEEP 1 TIC
	S0PSHJ	SLEEPF##	;SLEEP BUT DON'T CLOBBER F
	SOS	-5(P)		;BACK UP PC TO THE TEST
	SOS	-5(P)		; ..
	POPJ	P,		;RETURN TO CHECK AGAIN

;SUBROUTINE TO CHECK IF A PAGE LIES WITHIN THE RANGE SPECIFIED BY T1 AND T2

CKRNG:	CAIL	T3,(T1)		;LESS THAN THE LOWER BOUND?
	CAIL	T3,(T2)		;OR GREATER THAN THE UPPER BOUND?
	AOS	(P)		;YES, NOT IN THE RANGE
	POPJ	P,		;RETURN

;SUBROUTINE TO CHECK IF ANY OF THE PAGES BELONGING TO A SEGMENT LIE
; WITHIN THE RANGE SPECIFIED BY T1 AND T2

CKPGS:	PUSHJ	P,CKRNG		;CHECK THIS PAGE
	  POPJ	P,		;ITS WITHIN THE RANGE
	HRRZ	T3,@[IW MS.MEM,PAGTAB(T3)] ;GET THE NEXT PAGE OF THE SEGMENT
	JUMPE	T3,CPOPJ1##	;GOOD RETURN IF THIS IS THE LAST PAGE OF THE SEGMNET
	JRST	CKPGS		;CHECK THE NEXT PAGE

;SUBROUTINE TO RETURN THE FIRST PAGE OF A LOW SEGMENT

FSTPG:	LDB	T3,JBYLSA##	;PAGE ZERO OF THE JOB
	POPJ	P,		;RETURN THE FIRST PAGE OF THE JOB

;SUBROUTINE TO DETERMINE THE NUMBER OF UNLOCKED PAGES IN USER CORE

LRGHOL:	PUSHJ	P,SAVE3##
	MOVEI	T2,0
	MOVE	P1,MEMSIZ##
	SUB	P1,SYSSIZ##
	LSH	P1,W2PLSH##
	MOVE	P2,SYSSIZ##
	LSH	P2,W2PLSH##
LRGHL1:	MOVE	P3,@[IW MS.MEM,PAGTAB(P2)]
	TLNN	P3,LKBITS
	ADDI	T2,PAGSIZ##
	ADDI	P2,1
	SOJG	P1,LRGHL1
	POPJ	P,

;SUBROUTINE TO TURN ON BITS INDICATING A PAGE IS LOCKED IN A SPECIFIED WAY

LOKBTS:	MOVSI	T1,NSHF!NSWP
	IORM	T1,JBTSTS##(J)
	LDB	T1,JBYHSA##
	CAILE	J,JOBMAX##
	JRST	LOKBT1
	HRRZ	T1,JBTUPM##(J)
	MOVSI	T2,(T3)
	IORM	T2,@[IW MS.MEM,PAGTAB(T1)]
	LDB	T1,JBYLSA##
LOKBT1:	MOVSI	T2,(T3)
	IORB	T2,@[IW MS.MEM,PAGTAB(T1)]
	HRRZ	T1,T2
	JUMPN	T1,LOKBT1
	POPJ	P,
ERROR0:	LDB	P1,JBYLSA##	;LOW SEGMENT PHYSICAL ADDRESS
	TRNN	T1,LKB		;LOCKING LOW SEGMENT?
	JRST	LOWADR		;NO, GET ADDRESS ANYWAY
	MOVE	T4,@[IW MS.MEM,PAGTAB(P1)] ;LOCK STATUS
	MOVSS	T1		;SET UP FOR CHECKING USER ARGUMENT
	PUSHJ	P,ARGCK1	;IS LOCK POSSIBLE?
	  JRST	ERROR7		;NO. USER ARGUMENT IS INVALID
LOWADR:	TLNN	T1,LKEB		;LOCKED IN EVM?
	LDB	P1,[POINT 9,JBTADR##(J),26] ;YES. LOAD EVA FOR USER.
	MOVE	T1,P1		;LOW ADDRESS
	HRL	T1,T3		;HIGH ADDRESS
	PJRST	STOTC1##	;RETURN TO USER WITH ADDRESSES

ERROR1:	MOVEI	T1,LKERR1
	PJRST	STOTAC##

ERROR2:	MOVEI	T1,LKERR2
	PJRST	ERRRET

ERROR3:	MOVEI	T1,LKERR3
	PJRST	ERRRET

ERROR4:	POP	P,T1
ERROR5:	PUSHJ	P,UNLOCK
	PUSHJ	P,COMLIM	;RECOMPUTE CORMAX/MAXMAX
	MOVEI	T1,LKERR4
	PJRST	ERRRET
ERROR6:	MOVEI	T1,LKERR6
ERRRET:	PUSHJ	P,STOTAC##
	PJRST	CAFREE##


;SUBROUTINE TO FIND THE LARGEST CONTIGUOUS CHECK

ERROR7:	MOVEI	T1,7		;ATTEMPTED TO CHANGE LOCK STATUS
	PJRST	STOTAC##	;WITH A LOCK UUO
;SUBROUTINE TO CHECK USER'S ARGUMENT WHEN SEGMENT IS ALREADY LOCKED
ARGCK1:	TLNN	T4,LOKPHB	;PHYSICALLY CONTIGUOUS?
	TLNE	T1,LKPB		;ASKING FOR IT?
	SKIPA			;NO. SO FAR SO GOOD
	POPJ	P,		;CAN'T MAKE IT CONTIGUOUS
	TLNN	T4,LOKEVB	;LOCKED IN EVM?
	TLNE	T1,LKEB		;ASKING FOR IT?
	JRST	CPOPJ1##	;NO. ALL IS WELL
	POPJ	P,		;NOT IN EVM, SO USER CAN'T LOCK IT
;SUBROUTINE TO FIND THE LARGEST CONTIGUOUS CHUNK
; OF EVM AVAILABLE FOR MAPPING BUFFERS
CONEVA:	PUSHJ	P,SAVE4##
	MOVE	P1,EVMPTR##
	MOVEI	P2,0
	MOVEI	P3,-1
	PUSHJ	P,GETZ##
	  MOVEM	P2,EVBMAX##
	POPJ	P,
;SUBROUTINE TO CHECK WHETHER THE CACHE SHOULD BE ON OR OFF
CHKCSH:	MOVE	J,.CPJOB##
	TRNE	T1,LKB
	TRNE	T1,LKCB
	JRST	CHKCS3
	MOVSI	T2,(JS.NCS)
	IORM	T2,JBTST2##(J)
CHKCS2:	MOVE	J,.CPJOB##
CHKCS3:	SKIPG	JBTSGN##(J)
	POPJ	P,
	TLNE	T1,LKB
	TLNE	T1,LKCB
	POPJ	P,
	MOVSI	T2,NCSH
	IORM	T2,JBTSGN##(J)
	POPJ	P,

;SUBROUTINE TO SEE IF THIS IS THE FIRST PAGE OF
; A SHARABLE HIGH SEGMENT
FPNSHS:	SKIPN	P4
	POPJ	P,
	ADDI	P4,PAGSIZ##
	PUSHJ	P,SAVT##
	LDB	T1,JBYSG2##		;SECTION HI SEG IS IN
	CAME	T1,.USSPT
	POPJ	P,			;NOT IN THIS SECTION
	HRRZ	T1,M
	PUSHJ	P,TPAHS##
	  SKIPA	T4,T1
	POPJ	P,
	PUSH	P,J
	HRRZ	J,JBTSGN##(J)
	SKIPL	P4
	HRRM	P4,JBTADR##(J)
	PUSHJ	P,MAPHI##
	DPB	T4,JBYHSA##
	MOVSI	T1,NSHF!NSWP
	IORM	T1,JBTSTS##(J)
	MOVEI	P4,0
	JRST	JPOPJ##
;SUBROUTINE TO CACHE THE LOW SEGMENT
CSHLSG:	PUSHJ	P,SAVE2##
	PUSH	P,M
	LDB	P1,IMGIN##
	SETZM	.USSPT
CSHLS0:	PUSHJ	P,NXTWSB##
	CAIA
CSHLS1:	PUSHJ	P,NXTWS3##
	TRNE	M,<-1^!HLGPNO>		;USER PAGE?
	AOSA	.USSPT
	SKIPA	P2,(T4)
	JRST	CSHLS0
	TLO	P2,(PM.CSH)
	MOVEM	P2,(T4)
	SOJG	P1,CSHLS1
	JRST	MPOPJ##
SUBTTL	SEGCON - ROUTINES TO HANDLE HIGH SEGMENTS

;
;ROUTINE TO DETERMINE WHETHER THE IDLE HIGH SEGMENT FOR THE JOB CURRENTLY
;  BEING SWAPPED CAN BE SWAPPED
;
;  CALLING SEQUENCE
;
;	MOVE	J,HIGH SEGMENT NUMBER
;	PUSHJ	P,SWPHGH
;	...	;RETURN HERE TO SWAP ONLY THE LOW SEGMENT SINCE
;		;  THE HIGH SEGMENT IS LOCKED OR BEING LOCKED
;		;  T1 CONTAINS THE LOW SEGMENT NUMBER
;	...	;RETURN HERE IF HIGH SEGMENT CAN BE SWAPPED
;


LOKHGH::PUSH	P,SWPOUT##	;JOB NUMBER OF JOB BEING SWAPPED - MUST
				;  BE SETUP FOR INCREMENTING IN CORE COUNT
				;  IF HIGH SEGMENT CANNOT BE SWAPPED
	MOVE	T1,LOCK##	;GET HIGH SEGMENT NUMBER IF LOCKING ONLY
				;  A HIGH SEGMENT
	MOVSI	T2,NSHF!NSWP	;CANNOT SWAP THE HIGH SEGMENT IF ITS LOCKED
	CAIE	T1,(J)		;IS THIS A HIGH SEGMENT WHICH IS CURRENTLY
				;  BEING LOCKED?
	TDNE	T2,JBTSTS##(J)	;IS IT LOCKED
	JRST	TPOPJ##		;YES, GIVE DON'T SWAP RETURN (T1=JOB #)
	HLRZ	T1,LOCK##	;JOB NUMBER OF JOB BEING LOCKED
	CAME	T1,SWPOUT##	;SAME AS JOB BEING SWAPPED?
	AOS	-1(P)		;NO, OK TO SWAP THE HIGH SEGMENT
	JRST	T2POPJ##	;POP OFF JUNK AND GIVE SKIP OR NON-SKIP RETURN


LOKEND:	END