Google
 

Trailing-Edge - PDP-10 Archives - BB-JR93K-BB_1990 - 10,7/mon/lokcon.mac
There are 8 other files named lokcon.mac in the archive. Click here to see a list.
TITLE LOKCON -  MODULE FOR LOCKING JOBS IN CORE - V337
SUBTTL J. FLEMMING  TS	29-AUG-89

	SEARCH	F,S
	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 
;1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.

.CPYRT<1973,1988>


XP VLOKCN,337			;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
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
	TRZE	P3,PAGLOK##	;IS THIS PAGE FORMAT LOCK?
	JRST	LOCK31		;YES, MUST PROCESS DIFFERENTLY
LOCK3:	SKIPGE	T1,@[IW MS.MEM,PAGTAB(P3)] ;PAGE ON THE FREE CORE LIST?
	JRST	LOCK14		;YES, LOOP ON
	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	T1,P3		;NO, PAGE NUMBER TO T1
	JRST	LOCK14		;LOOK AT THE NEXT PAGE

	PUSHJ	P,CPIASP##	;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	LOCK14		;YES, NO ACTION NECESSARY
LOCK5:	CAIG	J,JOBMAX##	;IS THE SEGMENT CONTAINING THE PAGE WHICH
				; MUST BE MOVED A HIGH SEGMENT?
	JRST	LOCK11		;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	LOCK7		;NO, MUST SWAP OUT THE LOW SEGMENTS SHARING
				; IT TO MAKE IT GO AWAY
LOCK6:	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
LOCK7:	MOVE	T2,J		;SAVE HIGH SEGMENT NUMBER
	MOVE	J,HIGHJB##	;FIND A JOB SHARING IT
LOCK8:	MOVEI	T1,(T2)		;SEGMENT #
	PUSHJ	P,FNDHSB##	;DOES THIS JOB OWN THIS SEGMENT?
	  JRST	LOCK10		;NO
	SKIPE	JBTADR##(J)	;IS JOB IN CORE?
	JRST	LOCK9		;YES, GO SEE IF IT CAN BE SWAPPED OUT
	MOVE	T2,J		;SAVE JOB NUMBER BEFORE CALLING DECCNT
	EXCH	J,T1		;J=HIGH SEG BLOCK ADDR T1=JOB
	MOVE	J,.HBSGN(J)	;AND SEGMENT WORD
	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,LOCK6	;NO MORE JOBS SO SWAP OUT HIGH SEG
	EXCH	J,T2		;GET READY TO LOOK AT NEXT JOB
	JRST	LOCK10		;GO DO IT
LOCK9:	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	LOCK10		;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	LOCK12		;NO, SWAP OUT THE JOB
LOCK10:	SOJG	J,LOCK8		;LOOK AT NEXT JOB

	STOPCD	.,STOP,SSO,	;++SEGMENT SWAPPED OUT
LOCK11:
IFN FTMP,<
	PUSHJ	P,ANYRUN##	;RUNNING ON CPU1?
	  JRST	LOCK13		;YES
>
LOCK12:	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
LOCK13:	MOVEM	J,SW0JOB##	;TELL CPU1 TO STOP RUNNING THE JOB
	POPJ	P,		;AND RETURN
LOCK14:	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
LOCK15:	HRRZ	J,LOCK##	;SEGMENT NUMBER OF SEGMENT BEING LOCKED
	SKIPN	JBTADR##(J)	;IS THIS SEGMENT IN CORE?
	SKIPA	J,LASLOK##	;NO, GO CAUSE IT TO BE SWAPPED IN
	SKIPA	T1,LOKREL##	;SWAPPED IN, SEE IF LOCKING PAGES
	TLZA	J,-1		;CLEAR LEFT HALF
	SKIPA	R,JBTADR##(J)	;SET UP R
	S0JRST	FIT1##		;GO SWAP JOB IN

;ALLOCATE CORE, BLT SEGMENT INTO PLACE, AND LOCK IT
	TRNN	T1,PAGLOK##	;?
	CAILE	J,JOBMAX##	;NO, IS IT A HIGH SEGMENT?
	JRST	LOCK16		;PAGES OR HS, 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
LOCK16:	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
	TRNE	P2,PAGLOK##	;IF PAGES
	JRST	LOCK34		;THEN GO DO THAT
	CAILE	J,JOBMAX##	;IS THIS SEGMENT A LOW SEGMENT?
	JRST	LOCK18		;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
	PUSHJ	P,PAGMOV	;MOVE THE UPMP TO THE DESIRED POSITION
	  SETZ	P3,		;(CALLED EVEN IF IN PLACE TO CLEAR P2.LIP)
	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	LOCK17		;NO
	MOVE	T1,.CPMAP##
	MOVE	T1,.ECKSM/PAGSIZ(T1)
				;(PM.CSH OFF ALREADY)
	MOVEM	T1,.EUPMP+.UMJDT
	DPB	T1,JBYLSA##
LOCK17:	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
	HRRM	P2,@.CPSPT##	;SET UP THE SPT
IFN FTKL10,<TDO P2,[LG.LUB!LG.KPM!LG.IAM]> ;REQUEST LOADING OF UBR, INHIBIT
				; ACCOUNTING METER UPDATE
IFN FTKS10,<TLO P2,(SG.LUB)>	;REQUEST LOADING OF UBR
	DATAO	PAG,P2		;MAKE THE UPT ADDRESSABLE AND CLEAR THE A.M.
	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
LOCK18:	LDB	P3,IMGIN##	;NUMBER OF PAGES IN THE SEGMENT
	CAILE	J,JOBMAX##
	JRST	LOCK20
	LDB	T1,NFYPGS##
	ADDI	P3,-UPMPSZ##(T1)
	LDB	T1,NZSSCN##
	ADDI	P3,(T1)
	SETZM	.USSPT
	MOVSI	P4,400000
LOCK19:	PUSHJ	P,NXTWSB##
	JRST	LOCK24

LOCK20:	PUSHJ	P,ZERSWP##	;CLEAR DISK COPY OF HIGH SEG (BECAUSE MEMTAB
				;IS GOING TO GET SCRAMBLED)
	MOVE	T2,P1
	PUSHJ	P,SNPAGS##
	PUSHJ	P,PAGMOV
	  JFCL			;PAGE WAS IN PLACE
	SKIPN	T1,P1		;FIRST TIME?
	DPB	P2,JBYHSA##	;YES
	ADD	T1,JBTVAD##(J)	;POINT TO HIGH SEG MAP
	MOVSI	T2,(PM.NAD)	;GET BITS FOR PAGE
	ANDM	T2,(T1)		;CLEAR ALL BUT BITS
	IORM	P2,(T1)		;SET NEW PAGE
	JRST	LOCK22

LOCK21:	CAIN	T4,.UPMP+.UMUPT	;IS THIS THE UPT
	JRST	LOCK23		;YES, ALREADY DONE
	PUSHJ	P,PGMOVE
	JUMPN	P1,LOCK22
	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
LOCK22:	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,LOCK27
	CAILE	J,JOBMAX##
	JRST	LOCK20
	PUSHJ	P,FPNSHS
LOCK23:	PUSHJ	P,NXTWS3##
LOCK24:	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	LOCK21		;YES, STOP ON COUNT EXHAUSTED
	TRNN	M,<-1^!HLGPNO>	;IS IT A USER PAGE #?
	JRST	LOCK21		;NO, JUST CONTINUE THEN
	SKIPE	T4,.USSPT	;JUST DO S0?
	AOJA	T4,LOCK25	;INCREMENT SECTION
	PUSH	P,M		;SAVE THINGS TO DO FUNNY SPACE LATER
	PUSH	P,T1
	PUSH	P,T2
	PUSH	P,T3		;..
	AOJA	T4,LOCK26
LOCK25:	CAILE	T4,MXSECN	;ANY MORE TO DO?
	SETO	T4,		;NO, BACK TO S0 FOR FUNNY SPACE (2ND TIME)
LOCK26:	MOVEM	T4,.USSPT
	JUMPGE	T4,LOCK19	;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	LOCK21		;AND CONTINUE
LOCK27:	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	LOCK28		;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)]
LOCK28:	HLRZS	J,LOCK##	;GET THE SEGMENT NUMBER OF THE LOW SEGMENT
				; IF THERE IS ONE LEFT TO BE LOCKED
	JUMPE	J,LOCK29	;JUMP IF DONE
	HLRZS	LOKREL##	;STARTING PAGE NUMBER FOR THE LOW SEGMENT
	JRST	LOCK1		;AND GO TRY TO LOCK IT

LOCK29:	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
	SETZ	T1,		;START AT THE BEGINNING
LOCK30:	PUSHJ	P,GNXHSB##	;GET NEXT SEGMENT
	  POPJ	P,		;NO MORE
	SKIPLE	T2,.HBSGN(T1)	;IS THIS A REAL HIGH SEG
	TLNN	T2,SHRSEG	;WHICH IS SHARABLE?
	JRST	LOC30A		;SEE ABOUT NON-SHARABLE HIGH SEGS
	HRRZS	T2		;CLEAR JUNK IN LEFT HALF
	SKIPE	JBTADR##(T2)	;IS THIS HIGH SEG IN CORE?
	JRST	LOCK30		;YES, JUST LOOP ON TO NEXT
	MOVSI	T3,SWP		;DON'T LET SCHEDULAR RUN JOB
	IORM	T3,JBTSTS##(J)	;UNTIL ALL HIGH SEGS IN CORE
	POPJ	P,		;RETURN

LOC30A:	JUMPLE	T2,LOCK30	;IF NOT A REAL HIGH SEG AT ALL
	MOVSI	T3,LOKSEG	;MUST TURN ON LOKSEG...
	IORM	T3,.HBSGN(T1)	;FOR NON-SHARABLE HIGH SEGS HERE
	JRST	LOCK30		;AS NO ONE ELSE WILL
;HERE FOR LOCK SPECIFIED PAGES FORMAT

LOCK31:	SKIPN	JBTADR##(J)	;IS JOB IN CORE?
	S0JRST	FIT1##		;NO, PUT IT THERE
	PUSHJ	P,SVEUB##	;JOB MUST BE MAPPABLE
	MOVEI	T1,JS.ASA	;NOW THAT JOB IS BLOCKED, SET ASA
	CAME	J,.CPJOB##	;USER'S ACS NOT DUMPED YET IF STILL CURRENT
	IORM	T1,JBTSTS##(J)
	MOVE	M,.JDAT##+JOBDAC##+M ;LOAD USER UUO M
	PUSHJ	P,FSTPAG##	;POINT TO START OF ARG LST
	PUSH	P,.JDAT+JOBDAC##+P2 ;UUO LVL P2 HAS # OF ARGS
	SETZ	P2,		;COUNT OF CONTIG PAGES NEEDED
LOCK32:	PUSHJ	P,NXTLPG##	;GET NEXT PAGE
	JUMPL	T1,LOCK33	;NO MORE
	TRNN	T1,-1		;SPECIFIC PAGE REQUESTED?
	AOJA	P2,LOCK33	;NO, CHECK IT LATER
	SSX	T1,MS.MEM	;POINT TO PAGTAB SECTION
	.CREF	FREPAG		;SEE IF IT'S FREE
	SKIPGE	PAGTAB(T1)	;IS IT?
	JRST	LOCK33		;YES, CHECK MORE
	PUSHJ	P,CPIASP##	;IS PAGE IN THIS JOB?
	  XCT	SNF		;..NOT FOUND
	MOVMS	J		;DON'T CARE IF IT'S THE UPT
	CAME	J,.USJOB	;IS IT US?
	JRST	LOCK5		;NO, SWAP HIM OUT
LOCK33:	SOSLE	(P)		;MORE ARGS?
	JRST	LOCK32		;YES
	POP	P,(P)		;FIX STACK
	JUMPE	P2,LOCK15	;NO MORE PAGES TO CHECK (ONLY SPECIFICS)
	JRST	LOCK3		;CHECK CONTIG PAGES

;HERE TO COMPLETE LOCK SPECIFIED PAGES WHEN ALL PAGES ARE ON THE FREE LIST
;OR ARE PART OF THE JOB BEING LOCKED.

LOCK34:	MOVEI	T1,PAGLOK##	;CLEAR BIT
	ANDCAM	T1,LOKREL##
	PUSHJ	P,FSTPAG##	;M LOADED FROM PREVIOUS PATH THROUGH LOCK31
	PUSH	P,.JDAT+JOBDAC##+P2 ;# OF ARGS
	HRRZ	P1,JBTUPM##(J)	;SET P1 NON-ZERO; REMEMBER UPT PAGE
LOCK35:	PUSHJ	P,NXTLPG##	;GET NEXT
	JUMPL	T1,LOCK38	;UNLOCK ARG
	MOVE	T2,T1		;SAVE ARG
	TRNN	T1,-1		;SPECIFIC PAGE?
	AOSA	T1,LOKREL##	;NO, GET NEXT PHYS PAGE AVAILABLE
	TLZA	T1,-1		;CLEAR LEFT HALF
	SOSA	P2,T1		;GET REAL TARGET PAGE
	MOVE	P2,T1		;AND REAL SOURCE PAGE
	HLRZ	T1,T2		;GET VIRT PAGE INVOLVED
	ANDI	T1,HLGPGS	;MASK OUT BITS
	PUSHJ	P,GTPME##	;GET ENTRY
	PUSH	P,T1		;SAVE VIRT PAGE #
	MOVE	T1,T2		;PAGE THIS PAGE IS AT NOW
	TLZ	T1,(PM.NAD)	;CLEAR BITS
	CAIN	P1,(P2)		;EXCHANGING WITH THE UPT?
	CONO	PI,PI.OFF	;YES, TURN OFF THE PIS
	PUSHJ	P,PAGMOV	;MOVE THE PAGE
	  JRST	LOCK37		;WAS ALREADY IN PLACE
	CAIE	P1,(P2)		;EXCHANGE WITH THE UPT?
	JRST	LOCK36		;NO
	HRRM	P2,JBTUPM##(J)	;UPDATE JBTUPM
	HRRM	P2,@.CPSPT##	;SET UP THE SPT
	HRRZ	T1,P2		;GET PAGE NUMBER OF NEW UPT
IFN FTKL10,<TDO T1,[LG.LUB!LG.KPM!LG.IAM]> ;REQUEST LOADING OF UBR, INHIBIT
				; ACCOUNTING METER UPDATE
IFN FTKS10,<TLO T1,(SG.LUB)>	;REQUEST LOADING OF UBR
	DATAO	PAG,T1		;MAKE THE UPT ADDRESSABLE AND CLEAR THE A.M.
	CONO	PI,PI.ON	;TURN ON PIS AGAIN
	JRST	LOCK37		;CONTINUE
LOCK36:	MOVE	T1,(P)		;GET VIRT PAGE #
	PUSHJ	P,GTPME##	;GET PAGE
	AND	T2,[PM.NAD]	;KEEP BITS
	IOR	T2,P2		;PAGE # OF NEW PAGE
	TLO	T2,(PM.LOK)	;TURN ON "LOCKED PAGE" BIT
	MOVEM	T2,(T4)		;UPDATE MAP POINTER
	LDB	T1,JBYLSA##	;GET START OF LOW SEGMENT
	CAIE	T1,(P2)		;TARGET PAGE WAS FIRST PAGE OF LOW SEG?
	JRST	LOCK37		;NO
	SETZ	T1,		;GET FIRST PAGE OF JOB
	PUSHJ	P,GTPME##	;GET ENTRY
	TLZ	T2,(PM.CSH)	;TURN OFF CACHE
	MOVEM	T2,.UPMP+.UMJDT	;SET NEW .JDAT POINTER
	DPB	T2,JBYLSA##	;AND NEW FIRST PAGE OF JOB
LOCK37:	MOVE	T2,P2		;PHYSICAL PAGE
	PUSHJ	P,LKPSF##	;REMOVE PAGE FROM JOB'S REGULAR CHAIN
	EXCH	T2,.USLPG	;PUT ON CHAIN OF LOCKED PAGES JOB HAS
	SSX	P2,MS.MEM
	HRRM	T2,PAGTAB(P2)	;LINK REST OF CHAIN TO US
	SKIPE	T2		;AND IF THERE WAS A REST OF CHAIN
	HRRM	P2,@[IW MS.MEM,PT2TAB(T2)] ;LINK US TO IT
	POP	P,T1		;RESTORE VIRT PAGE # AGAIN
	DPB	T1,NVPNP2##	;STORE WHAT VIRT PAGE THIS PHYS PAGE MAPS TO
	HLLZS	PT2TAB(P2)
	PUSHJ	P,TSWST##	;GET WORKING SET BIT
	  STOPCD .+1,DEBUG,PSC,	;++PAGE SHOULD BE IN CORE
	ANDCAM	T2,(T4)		;PAGE NOT IN WORKING SET
	.CREF	IMGIN		;AND DECREMENT # OF WORKING SET PAGES
	SOS	JBTIMI##(J)
LOCK38:	SOSLE	(P)		;MORE ARGS?
	JRST	LOCK35		;YES
	MOVEI	T1,LOK+JS.ASA	;SET TO MAKE JOB RUNABLE AGAIN
	ANDCAM	T1,JBTSTS##(J)	;TURN OFF LOK SO SCHEDULAR WILL RUN THE JOB AGAIN
	SETZM	LOCK##		;CLEAR LOCKING FLAG
	JRST	TPOPJ##		;FIX STACK AND RETURN

;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	SETM12		;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	SETM12		;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	SETM11		;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
	PUSHJ	P,PAGFRE	;MOVE THE PAGE AND FIX PAGTAB
	  STOPCD .,STOP,CMP	;++CAN'T MOVE PAGE
	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
SETM11:	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
SETM12:	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
SETM13:	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	SETM14		;YES
	AOBJN	P3,SETM13	;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
SETM14:	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	SETM14		;NO, LOOK AT THE NEXT CANDIDATE
	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
	HRRZ	T1,P3		;SOURCE PAGE AGAIN
	SETZ	J,		;CLEAR J (FIRST TIME)
SETM15:	PUSHJ	P,CKHMAP##	;IS IT SOME HIGH SEGS MAP?
	  JRST	SETM16		;YES
	HRRM	P2,JBTUPM##(J)	;STORE NEW MAP (SOMEONE ELSE WILL DO DATAO PAG)
	JRST	SETM15		;CHECK FOR OTHER MAPS THIS PAGE
SETM16:	SOJLE	P4,SETM17	;JUMP IF WE'VE MOVED THE LAST PAGE
	SKIPLE	.CPHTM##	;ONCE/SECOND TIME CREEPING UP ON US?
	JRST	SETM13		;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,CSBORG##	;NUMBER OF WORDS (BOTTOM OF HISEG)
	LSH	T1,W2PLSH	;NUMBER OF PAGES TO WORRY ABOUT
	MOVE	T2,[POINT 36,CSBORG##/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.
	SKIPE	T1		;WAS IT FOUND IN SOME OTHER CPU'S SECTION MAP?
	PUSHJ	P,ADJMP3	;YES, STORE THE CORRECT NUMBER THERE AND LOOK HERE AS WELL
	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
	SKIPE	P1
	HRRZ	T4,@[IW MS.MEM,PT2TAB(T1)]
	MOVSI	T2,(P2.LIP)	;BE SURE P2.LIP GETS CLEARED
	ANDCAM	T2,@[IW MS.MEM,PT2TAB(P2)]
	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
;P1 IS ZERO/NON-ZERO FLAG FOR THERE "IS NOT"/"IS" A PREDECESSOR TO DEAL WITH
;P2 IS TARGET PAGE, T1 IS CURRENT PAGE

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
	MOVEM	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)]
	MOVEM	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,@[IW MS.MEM,PT2TAB(P2)] ;PREDEDESSOR TO TARGET
	ADD	T3,[EXP MS.MEM+PAGTAB] ;CONVERT TO ADDR
	HRRZ	T4,@[IW MS.MEM,PT2TAB(T1)] ;PREDECESSOR TO CURRENT
	HRRZ	T2,@[IW MS.MEM,PAGTAB(T1)] ;SUCCESSOR TO CURRENT
	PUSHJ	P,FIXPTB
PAGFD2:	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			;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+PG.BDY
	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
	MOVSI	T1,-PAGSIZ	;AOBJN COUNTER FOR NUMBER OF WORDS TO EXCHANGE
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
;P1 IS ZERO/NON-ZERO FLAG FOR THERE "IS NOT"/"IS" A PREDECESSOR TO DEAL WITH
;NON-SKIP RETURN - PAGE WAS IN PLACE ALREADY (P2.LIP CLEARED, THOUGH)
;SKIP RETURN - THE SOURCE PAGE HAS BEEN MOVED TO THE TARGET DESTINATION

PAGMOV:	CAIE	T1,(P2)		;IS IT ALREADY IN PLACE?
	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
	JRST	CPOPJ1##	;PAGE IS NOW 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
	CAIN	T1,(P2)		;IF PAGE WAS IN PLACE
	POPJ	P,		;RETURN
	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
	AOS	(P)		;PAGE WASN'T IN PLACE
	POPJ	P,		;RETURN


;SUBROUTINE TO DETERMINE IF THE CURRENT PAGE MUST BE MOVED AND IF SO,
; MOVE IT
;T4 CONTAINS MAP POINTER FOR VIRTUAL PAGE TO MOVE, P2 HAS TARGET PAGE
;P1 ZERO/NON-ZERO FLAG FOR THERE "IS NOT"/"IS" A PREDECESSOR
;TO BE DEALT WITH
;P2=TARGET, T1=CURRENT PAGES

PGMOVE:	PUSHJ	P,SAVT##
	MOVE	T1,(T4)
	TLZ	T1,(PM.NAD)
	PUSH	P,T4
	PUSHJ	P,PAGMOV
	  JFCL			;DON'T CARE IF IT WAS IN PLACE
	MOVE	T1,(P)
	MOVE	T1,(T1)
	AND	T1,[PM.NAD]	;SAVE ALL BUT ADDRESS
	IORI	T1,(P2)
	HRRZ	T2,M
	MOVSI	T3,(JS.NCS)
	CAIGE	T2,.MCFV/PAGSIZ
	TDNN	T3,JBTST2##(J)
	CAIA
	TLZ	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:	CAILE	J,JOBMAX##	;JOB?
	JRST	FIXHMP		;NO, FIX A HIGH SEG MAP THEN
	PUSHJ	P,SAVT##	;SAVE THE TS AGAIN
	PUSH	P,M
	PUSH	P,.USSPT
FIXMA1:	CAIE	M,.UPMVP/PAGSIZ	;FLAG THAT WE'RE MOVING UPT
	JRST	FIXMA3		;NOT MOVING UPT, START WHERE PAGE CURRENTLY IS
	SETZM	.USSPT
FIXMA2:	PUSHJ	P,NXTWSB##	;START
	JRST	FIXMA5		;..
FIXMA3:	MOVE	M,.USTMP	;ACS SAVED FOR US
	DMOVE	T1,.USTMP+1
	MOVE	T3,.USTMP+3
FIXMA4:	PUSHJ	P,NXTWS3##	;NEXT PAGE
FIXMA5:	SKIPGE	.USBTS		;IS USER EXTENDED?
	SKIPGE	.USSPT		;YES, DOING FUNNY SPACE (2ND TIME THROUGH S0)
	JRST	FIXMA8		;YES
	TRNN	M,<-1^!HLGPNO>	;USER PAGE?
	JRST	FIXMA8		;YES
	SKIPE	T4,.USSPT	;START NON-ZERO SECTIONS?
	AOJA	T4,FIXMA6	;NO, ALREADY STARTED
	PUSH	P,M
	PUSH	P,T1
	PUSH	P,T2
	PUSH	P,T3
	AOJA	T4,FIXMA7
FIXMA6:	CAILE	T4,MXSECN
	SETO	T4,		;START FUNNY SPACE
FIXMA7:	MOVEM	T4,.USSPT
	JUMPGE	T4,FIXMA2
	POP	P,T3
	POP	P,T2
	POP	P,T1
	POP	P,M
	MOVEI	T4,(M)
	PUSHJ	P,GMPTR##
FIXMA8:	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	FIXMA4		;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

;HERE FOR HIGH SEG

FIXHMP:	PUSHJ	P,SAVE4##	;SAVE ACS
	MOVE	P1,JBTVAD##(J)	;START OF MAP
	LDB	P3,IMGIN##	;SIZE OF SEGMENT
	TLO	P1,(<GIDX(P3)>)	;INDEX
	SOS	P3		;HIGHEST RELATIVE PAGE IN SEGMENT
FIXHM1:	MOVE	P4,@P1		;GET MAP ENTRY
	TLZ	P4,(PM.NAD)	;CLEAR BITS
	CAIE	P4,(P2)		;PAGE WE WANT?
	SOJGE	P3,FIXHM1	;NO
	SKIPGE	P3		;FALL OFF END OF MAP?
	XCT	XPW		;YES, SOMEONE IS CONFUSED
	MOVSI	P4,(PM.NAD)	;SAVE BITS IN ENTRY
	AND	P4,@P1
	IORI	P4,(T1)		;NEW PAGE #
	IORM	T1,@P1		;UPDATE MAP
	POPJ	P,		;AND RETURN
;SUBROUTINE TO FIX UP PAGTAB AFTER EXCHANGING PAGES
;ARGS:
;	T3=PREDECESSOR-TO-TARGET 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 THERE IS TO BE NONE
	HRRM	P2,PAGTAB(T4)	;PRED-TO-CURR-->TARGET
	HRRM	T4,@[IW MS.MEM,PT2TAB(P2)] ;PRED-TO-CUR<--TARGET
	HRRM	T1,(T3)		;PRED-TO-TARGET-->CURRENT
	CAIN	T3,PAGPTR##	;IS THERE NO PRED-TO-TARGET PAGE?
	TDZA	T4,T4		;YES, SET PRED-TO-TARGET PAGE TO 0
	MOVEI	T4,-PAGTAB(T3)	;ELSE GET PAGE # FOR PRED-TO-TARGET
	HRRM	T4,@[IW MS.MEM,PT2TAB(T1)] ;PRED-TO-TARGET<--CURRENT
	MOVE	T4,(P)		;RESTORE T4
	HLRZM	T2,(P)		;SAVE SUCCESSOR TO TARGET
	CAIE	P2,(T2)		;EXCHANGING TARGET WITH SUCCESSOR TO CURRENT?
	TLZA	T2,-1		;NO, JUST CLEAR JUNK IN LH
	HRRZ	T2,T1		;IF YES, SET CURRENT AS SUCCESSOR TO CURRENT
	HRRM	T2,@[IW MS.MEM,PAGTAB(P2)] ;TARGET-->SUCCESSOR TO CURRENT
	TRNE	T2,-1		;IS THERE A REAL SUCCESSOR TO CURRENT?
	HRRM	P2,@[IW MS.MEM,PT2TAB(T2)] ;TARGET<--SUCCESSOR TO CURRENT
	HLL	T2,@[IW MS.MEM,PAGTAB(P2)] ;EXCHANGE BITS FOR
	HLR	T2,@[IW MS.MEM,PAGTAB(T1)] ;CURRENT AND TARGET PAGES
	HLLM	T2,@[IW MS.MEM,PAGTAB(T1)] ;..
	HRLM	T2,@[IW MS.MEM,PAGTAB(P2)] ;..
	MOVE	T2,@[IW MS.MEM,MEMTAB(T1)] ;EXCH MEMTABS IN CASE HIGH SEG
	EXCH	T2,@[IW MS.MEM,MEMTAB(P2)]
	MOVEM	T2,@[IW MS.MEM,MEMTAB(T1)]
	POP	P,T2		;RESTORE SUCCESSOR TO TARGET
	CAIN	T2,(T1)		;IF SUCCESSOR TO TARGET IS CURRENT
	MOVE	T2,P2		;THEN SUCCESSOR TO TARGET IS TARGET
	HRRM	T2,@[IW MS.MEM,PAGTAB(T1)] ;TARGET-->SUCCESSOR TO CURRENT
	TRNE	T2,-1		;DO NOTHING ELSE IF NO SUCCESSOR
	HRRM	T1,@[IW MS.MEM,PT2TAB(T2)] ;TARGET<--SUCCESSOR TO CURRENT
	POPJ	P,
SUBTTL ERRCON - ERROR HANDLING CODE

;ROUTINE TO CHECK IF JOB HAS SOME SEG LOCKED
;CALL:	MOVE	J,JOB NUMBER
;	PUSHJ	P,LOKCHK
;	  SOME LOCKED - J PRESERVED
;	NONE LOCKED - J PRESERVED

LOKCHK::PUSHJ	P,SAVE2##	;SAVE P1-P2
	MOVSI	P1,NSHF!NSWP	;NO SHUFFLING OR SWAPPING BITS
	MOVSI	P2,LOKSEG	;LOCKED HIGH SEG SOMEWHERE?
	TDNN	P1,JBTSTS##(J)	;LOW SEG LOCKED?
	TDNE	P2,JBTSGN##(J)	;OR A LOCKED HIGH SEG SOMEWHERE?
	POPJ	P,		;YES
	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
	JUMPL	T1,LOKJO2	;SKIP CHECKS HERE FOR FORMAT 2
	TRNE	T1,-1		;LOCKING THE LOW SEG?
	SKIPN	.USVRT		;YES, IS JOB VIRTUAL?
	SKIPE	.USLPG		;NOT VIRTUAL, ANY LOCKED PAGES?
	JRST	RTZER##		;CAN'T LOCK VIRTUAL LOW SEG
	PUSHJ	P,NSHCHK	;CHECK FOR NON-SHARABLE SEG PROBLEM
	  JRST	RTZER##		;NOT IMPLEMENTED
LOKJO2:	PUSHJ	P,SAVE4##	;SAVE P1-P4
	PUSHJ	P,SAVU##	;SAVE U
	MOVSI	T1,PVLOCK	;BIT DENOTING PRIVILEDGES TO LOCK
	PUSHJ	P,PRVBIT##	;IS THIS USER A SUFFICIENT WHEEL?
	  SKIPA	P4,JBTSGN##(J)	;YES, PROCEED (POINT TO FIRST HIGH SEG)
	JRST	ERROR1		;NO, NOT PRIVILEGED ERROR RETURN
	SETZ	P1,		;INDICATE FIRST TIME
	PUSHJ	P,GETTAC##	;GET THE ARGUMENT
	PUSH	P,T1		;SAVE ON STACK
LOKJ2A:	PUSHJ	P,LOKJO3	;LOCK THIS HIGH SEG AND JOB
	  JRST	LOKERR		;FAILURE; FIX UP THINGS AND FINISH UP
	MOVE	T2,(P)		;USER'S AC
	EXCH	T1,T2		;VALUE TO RETURN
	PUSHJ	P,LOKVAL	;RETURN VALUE TO USER AS APPROPRIATE
	JUMPL	P4,LOKJ2A	;LOOP IF EXTENDED FORMAT
	JUMPE	P4,LOKJ2B	;OR EXIT IF DONE
	HRRZ	P4,.HBLNK(P4)	;POINT TO NEXT
	JUMPN	P4,LOKJ2A	;LOOP AROUND FOR THIS HIGH SEG
LOKJ2B:	POP	P,(P)		;THROW USER'S ARG AWAY
	JRST	CPOPJ1##	;DONE IF NO MORE HIGH SEG
;HERE TO PROCESS ONE LOCK FOR EITHER A LOW SEG (PERHAPS PLUS HIGH SEG)
;OR A HIGH SEG ONLY (J ALWAYS SHOULD HAVE THE LOW SEG FOR WHOM THE
;HIGH SEG IS BEING LOCKED)
;AC USAGE THROUGH THIS:
;P3=USER'S ARG
;P4=ADDRESS OF HIGH SEG DATA BLOCK FOR HIGH SEG TO BE LOCKED (0 IF NONE)

LOKJO3:	PUSHJ	P,SAVE1##	;SAVE P1
LOKJ3A:	MOVE	P3,T1		;ARG SAVED IN P3
	JUMPL	P3,LOKFM2	;PROCESS NEW STYLE ARG LIST
LOKRET:	MOVSI	P1,NSHF!NSWP	;LOCKED BITS
	MOVE	T2,J		;SAVE JOB NUMBER
	MOVEI	T3,0		;ASSUME NO HIGH SEGMENT ADDRESS
	SKIPE	P4		;A HIGH SEG?
	SKIPG	J,.HBSGN(P4)	;REALLY A REAL HIGH SEG?
	JRST	LOKJO4		;NO
	TLO	J,(IFIW)	;MAKE THIS AC A VALID INDEX. THIS WORKS SINCE
	.CREF	SPYSEG		;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,.HBSGN(P4)
	PUSHJ	P,CHKCS1	;SET CACHE BIT IN JBTSGN
	PUSHJ	P,MAPHGH##	;COPY CACHE BIT TO UPMP
	JRST	LOKJ3A		;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
LOKJO4:	EXCH	J,T2		;J=JOB, T2=HIGH SEGMENT NUMBER
	TRNN	T1,LKB		;LOCK THE LOW SEGMENT?
	JRST	LOKJO5		;NO
	TDNN	P1,JBTSTS##(J)	;IS THE LOW SEGMENT ALREADY LOCKED?
	JRST	LOKJO6		;YES
LOKJO5:	TLNN	T1,LKB		;LOCK THE HIGH SEGMENT?
	JRST	GETLOW		;NO, CHECK OUT LOW EG
	JUMPE	T3,GETLOW	;JUMP IF NO HIGH SEGMENT
	TDNE	P1,JBTSTS##(T2)	;ALREADY LOCKED?
	JRST	GETLOW		;YES, GO CHECK OUT LOW SEGMENT
	HRRZ	J,T2		;SAVE HIGH SEGMENT NUMBER
LOKJO6:	TLZ	T1,-1-<LKB>
	MOVEI	F,0		;INDICATE NO DDB
	PUSHJ	P,CAWAIT##	;YES, WAIT UNTIL ITS DONE
CHKLPG::			;ENTER HERE FOR CHECK ON LOCK PAGES FUNCTION
	SETZB	U,T4		;ZERO LARGEST JOB SEEN SO FAR
	PUSH	P,P1		;SAVE CURRENT P1 (IN CASE CHKLPG)
	PUSH	P,J		;SAVE J
	MOVEI	J,1		;FIND THE LARGEST JOB NOT LOCKED
	MOVE	P1,T1		;SAVE ARG
LOKJO7:	CAMN	J,.CPJOB##	;DON'T CONSIDER JOB BEING LOCKED
	JRST	LOKJ12
	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
	PUSH	P,T1		;SAVE HIGH SEGMENT LKB
	SETZ	T1,		;FIND HIGH SEGS THIS JOB HAS
LOKJO8:	PUSHJ	P,GNXHSB##	;DOES HE HAVE ANY (MORE)?
	  JRST	LOKJ11		;NO
	PUSH	P,T1		;SAVE HIGH SEG DATA BLOCK ADDR
	SKIPG	T1,.HBSGN(T1)	;IS THIS A REAL HIGH SEG?
	JRST	LOKJ10		;NO
	HRRZS	T1		;CLEAR JUNK
	TLNN	P1,LKB		;ARE WE LOCKING A HIGH SEG?
	JRST	LOKJO9		;NO
	MOVE	P2,JBTSTS##(T1)	;GET THAT SEGMENT'S STATUS WORD
	JUMPE	P4,LOKJO9
	SKIPLE	J,.HBSGN(P4)	;GET OUR SEGMENT #
	CAIE	T1,(J)		;IS THIS THE SEGMENT IN QUESTION?
LOKJO9:	TLNE	P2,NSHF!NSWP	;OR IS THIS SEGMENT ALREADY LOCKED?
	JRST	LOKJ10		;ALREADY LOCKED OR SEGMENT BEING LOCKED; IGNORE
	MOVE	P2,T2		;SUMMATION SO FAR
	HRRZS	J		;CLEAR JUNK
	PUSHJ	P,SEGSIZ##	;SIZE OF THAT SEGMENT
	ADDI	T2,(P2)		;INCLUDE IN SUM
LOKJ10:	POP	P,T1		;RESTORE HIGH SEG DATA BLOCK ADDR
	JRST	LOKJO8		;AND CONTINUE LOOKING AT THIS JOB'S HIGH SEGS
LOKJ11:	POP	P,T1		;RESTORE HIGH SEGMENT LKB
	LSH	T2,P2WLSH
	CAMLE	T2,U		;LARGEST SO FAR?
	MOVE	U,T2		;YES, SAVE ITS SIZE
	POP	P,J		;RESTORE JOB NUMBER
LOKJ12:	CAMGE	J,HIGHJB##	;LOOKED AT ALL JOBS YET?
	AOJA	J,LOKJO7	;NO
	MOVE	J,(P)
	SKIPN	T3,P1		;SAVE ARGS
	JRST	[MOVE	T1,-1(P) ;# OF PAGES TO LOCK ON LOCK PAGES FCN
		 SOJA	T1,LOKJ13] ;CHECK
	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	LOKJ13		;YES, JUST LOCK THE HIGH SEGMENT
	MOVSI	P2,NSHF!NSWP	;HIGH SEGMENT MAY ALREADY BE LOCKED
	JUMPE	P4,LOKJ13
	SKIPG	P1,.HBSGN(P4)	;REALLY ANY HIGH SEG?
	JRST	LOKJ13		;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	LOKJ13		;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
LOKJ13:	PUSHJ	P,LRGHOL	;COMPUTE THE NUMBER OF PHYSICAL PAGES AVAILABLE
				; FOR LOCKING
	POP	P,P2		;RESTORE JOB#,,HIGH SEGMENT#
	POP	P,P1		;IN CASE WE RETURN
	SUBI	T2,1(T1)	;T2 = AMOUNT OF CORE LEFT IF THIS JOB IS LOCKED
	CAMGE	T2,U		;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	P2,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
	JUMPE	T3,CPOPJ1##	;IF CALLED FROM LOKPGS, RETURN THERE NOW
	MOVE	P1,P2		;REFILL P1 NOW THAT WE KNOW IT'S NOT CHKLPG
	MOVE	T1,P3		;DESTROYABLE COPY
	JUMPGE	P3,LKJ13A	;PROCEED IF OLD FORMAT LOCK
	HRRZ	M,(P3)		;POINT TO USER'S ARG LIST
	PUSHJ	P,GETWDU##	;GET FUNCTION
	CAIN	T1,.LKPPN	;IF SPECIFIED PAGE FUNCTION,
	JRST	LOKEXT		;PROCESS IT
;DISPATCH TO DO VARIOUS TYPES OF LOCK FOR EACH SEGMENT
LKJ13A:	PUSHJ	P,CHKCSH	;CHECK WHETHER THE CACHE SHOULD BE ON OR OFF
	CAIG	P1,JOBMAX##	;IS THE HIGH SEGMENT TO BE LOCKED?
	JRST	LOKJ14		;NO
	TLCE	T1,LKB+LKEB+LKPB;DOES THE USER WANT IT LOCKED IN PLACE?
	TLNE	T1,LKB+LKEB+LKPB; ..
	JRST	LOKJ14		;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,LOKJ19	;JUMP IF LOW SEGMENT ISN'T TO BE LOCKED
LOKJ14:	MOVE	T1,P3		;GET A DESTROYABLE COPY OF USER'S AC
	TRCE	T1,LKB+LKEB+LKPB;DOES THE USER WANT THE LOW SEGMENT LOCKED
	TRNE	T1,LKB+LKEB+LKPB; IN PLACE?
	JRST	LOKJ15		;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	LOKJ19		;AND FINISH UP
LOKJ15:	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	P3,T2		;EITHER SEGMENT TO BE LOCKED PHYSICALLY CONTIGUOUS?
	JRST	LOKJ16		;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
LOKJ16:	MOVEI	T1,0		;INDICATE THAT NEITHER SEGMENT IS ALREADY
				; LOCKED IN EVM
LOKJ17:	MOVE	P2,T1		;P2 = SEGMENTS ADDRESSES IF LOCKED ALREADY
	MOVE	T1,P3		;DESTRUCTABLE COPY
	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	LOKJ19		;ALL DONE
	MOVE	T1,P3		;COPY TO PLAY AROUND WITH
	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	LOKJ18		;GO CHECK THE LOW SEGMENT
	TLNE	P2,LKEB		;LOCK THE HIGH SEGMENT VIRTUALLY CONTIGUOUS?
	JRST	LOKJ18		;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,LOKJ19	;ALL DONE IF NOT LOCKING LOW SEGMENT
LOKJ18:	TRNN	P2,LKEB		;LOCK THE LOW SEGMENT VIRTUALLY CONTIGUOUS?
	TRNE	T1,-1		;YES, IS THE LOW SEGMENT ALREADY LOCKED IN EVM?
	JRST	LOKJ19		;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
LOKJ19:	PUSHJ	P,CAFREE##	;RETURN THE LOCK RESOURCE
	S0PSHJ	SETRLH##
	JUMPGE	P3,LOKRET	;PICK UP ARGS ELSEWHERE IF OLD FMT
	PUSHJ	P,RASBAD	;GET PHYSICAL PAGE NUMBER
	  JFCL			;RASBAD SKIPS
	PJRST	CPOPJ1##	;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
;HERE FOR FORMAT 2 TYPE LOCKS

LOKFM2:	PUSHJ	P,LOKARG	;JUMP IF NEW STYLE ARGUMENT LIST
	  JRST	STOTAC##	;MALFORMED ARGUMENT LIST, GIVE ERROR RETURN
	JRST LOKRET		;CONTINUE PROCESSING

LOKARG:	HRRI	M,(T1)		;POINT AT USER'S ARGUMENT LIST
	HLRE	T2,T1		;- LENGTH OF THE ARGUMENT LIST
	CAMLE	T2,[-2]		;MUST BE AT LEAST 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
	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,,LOKSGN
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!LKAB	;YES, INDICATE HIGH SEGMENT TO BE LOCKED
	TRZE	T1,-1		;LOCK THE LOW SEGMENT AT A SPECIFIED ADDRESS?
	TRO	T1,LKB!LKAB	;YES, INDICATE LOW SEGMENT TO BE LOCKED
	AOS	(P)		;SET FOR GOOD RETURN
	POPJ	P,		;AND RETURN

LOKSGN:	JUMPL	P4,LOKSG3	;IS THIS THE FIRST TIME?
	HRL	P4,T2		;SET COUNT OF ARGS (+1) IN LEFT HALF OF P4)
LOKSG3:	AOBJP	P4,LOKSGR	;RETURN SUCCESS
	PUSHJ	P,GETWDU##	;GET NEXT LOCK ARG
	TRNN	T1,L2SGN	;IS THIS JOB OR A SEGMENT?
	JRST	LOKSGL		;LOW SEG
	PUSH	P,T1		;SAVE ARG
	PUSHJ	P,FNDHSB##	;GET HIGH SEG BLOCK ADDRESS
	  JRST	TPOPJ##		;NO SUCH HIGH SEG
	HRRI	P4,(T1)		;SET WHICH HIGH SEG TO FIDDLE WITH
	MOVSI	T1,LKB		;SAY TO LOCK THE HIGH SEG
	POP	P,T2		;NOW FIGURE OUT HOW TO DO IT
	JRST	CPOPJ1##	;GOOD RETURN

LOKSGL:	MOVE	T2,T1		;PUT ARG BITS IN T2
	MOVEI	T1,LKB		;SET TO LOCK LOW SEG
	JRST	CPOPJ1##	;AND GOOD RETURN

LOKSGR:	SETZB	T1,P4		;STOP ALL ARG PROCESSING
	JRST	CPOPJ1##	;AND RETURN
;SUBROUTINE TO RETURN LOCK ARGUMENT (IN T2) INTO THE APPROPRIATE PLACE
;T1 CONTAINS THE USER'S AC

LOKVAL:	JUMPL	P4,LOKVLE	;EXTENDED FORMAT
	MOVE	T1,T2		;FOR OLD FORMAT, PUT IN AC
	PJRST	STOTAC##	;AND DO IT

LOKVLE:	MOVEI	M,(P4)		;WHERE TO PUT IT
	PUSHJ	P,GETWDU##	;GET ARG FROM USER
	TRNE	T2,L2SGN	;LOW OR HIGH SEG?
	MOVSS	T2		;HIGH SEG, PUT ADDRESS IN RIGHT HALF
	LSH	T2,W2PLSH	;CONVERT TO PAGE #
	ANDI	T2,(L2PPN)	;KEEP ONLY PAGE #
	TLO	T1,(T2)		;PUT IN THE VALUE
	PJRST	PUTWDU##
;HERE TO UNLOCK EVERYTHING WE TRIED TO LOCK (ERROR IN MIDDLE OF LIST)
LOKERR:	MOVEM	T1,(P)		;DON'T NEED USER'S AC ANYMORE
	MOVE	T1,P3		;GET USER'S AC
	AOBJP	T1,TPOPJ##	;(ASSUME OLD FORMAT TAKES CARE OF ITSELF)
	PUSHJ	P,UUNLOK	;UNLOCK THIS LIST (IGNORE ERRORS...
	  JFCL			;...SINCE SOME THINGS MAY NOT BE LOCKED ANYWAY)
	POP	P,T1		;RESTORE ERROR CODE
	PJRST	STOTAC##	;AND RETURN IT TO USER
;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
LOKEVX::PUSH	P,T1		;SAVE THAT
	JUMPLE	T1,LOKEV1	;IF PAGES, FORGET UPT
	CAIG	J,JOBMAX##	;A LOW SEGMENT?
	ADDI	T1,UPMPSZ##	;YES, UPMP MUST BE MAPPED TOO
LOKEV1:	MOVEI	T2,EVMPTR##	;POINT TO BIT MAP OF SLOTS IN THE EXEC MAP
				; USED FOR LOCKING IN EVM
	MOVMS	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
	MOVM	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	LOKEV8		;NO
	POP	P,T2
	PUSHJ	P,SAVE4##
	MOVE	P1,T1		;SAVE T1 IN P1 (FOR LOKEV3)
	SKIPL	P2,T2		;AND AMOUNT OF EVM IN P2
	ADDI	T1,UPMPSZ##
	PUSH	P,T1
	JUMPL	P2,LOKEV3	;IF FROM LOKPGS
	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
LOKEV2:	PUSHJ	P,NXTWSB##
	JRST	LOKEV6
LOKEV3:	PUSHJ	P,FSTPAG##	;POINT TO FIRST PAGE
	HRRI	T1,(P1)		;START OF EVM
	LSH	T1,W2PLSH	;CONVERT TO PAGE #
	HRLM	T1,.USLPG	;STORE FOR LATER RETURN
	MOVMS	P2		;MAKE POSITIVE
LOKEV4:	SKIPGE	(P)		;PAGES FORMAT?
	JRST	LOKEV5		;NO
	PUSHJ	P,NXTWS3##
	JRST	LOKEV6
LOKEV5:	PUSHJ	P,NXTLPG##	;GET NEXT PAGE
	TLNE	T1,(PG.SLO!PG.GAF)	;THIS ARG REQUIRE EVM?
	JRST	LOKEV5			;NO
	PUSHJ	P,GTPME##
	MOVE	T3,T2			;GET MAP ENTRY
	TLZ	T3,(PM.NAD)		;KEEP ONLY PAGE #
	MOVSI	T1,LOKEVB		;TURN ON LOCKED IN EVM BIT
	IORM	T1,@[IW MS.MEM,PAGTAB(T3)]
	MOVEI	T1,1(P1)
	MOVEM	T1,@[IW MS.MEM,MEMTAB(T3)] ;STORE EVM FOR RETURN
	.CREF	MT.EVM			;...
	JRST	LOKEV7			;CONTINUE
LOKEV6:	TRNN	M,<-1^!HLGPNO>		;PAGE NOT IN USER SPACE?
	JRST	LOKEV7			;USER PAGE
	AOS	.USSPT			;PROCEED TO NEXT SECTION
	JRST	LOKEV2
LOKEV7:	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,LOKEV4
	POP	P,M
	JRST	LOKEV9
LOKEV8:	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
>
LOKEV9:	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:	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	LKSPH1		;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	LKSPH1		;NO, ALL IS WELL SO FAR
	JRST	ERROR6
LKSPH1:	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 LKSPH2]
	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,LKSPH3	;ALL DONE IF NOT LOCKING THE LOW SEGMENT
LKSPH2:	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
LKSPH3:	MOVE	J,.CPJOB##	;CURRENT JOB NUMBER
	PUSHJ	P,LOCKIT	;LOCK THE SEGMENTS REQUESTED WHERE REQUESTED
	  JFCL			;CAN'T HAPPEN
	JRST	LOKJ19		;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:	SKIPL	T3,@[IW MS.MEM,PAGTAB(T1)]	;IS PAGE FREE?
	JRST	SETLI3			;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
	SOSA	BIGHOL##
SETLI3:	IORM	T4,@[IW MS.MEM,PT2TAB(T1)]	;SET P2.LIP
	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.  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
	POPJ	P,			;ALREADY MOVED
;*	MOVSI	P1,(P2.LIP)		;CLEAR THIS BIT
CLRLQ1:	SSX	P2,MS.MEM		;WHERE PT2TAB ETC. LIVE
	HRRZ	P3,P2			;SAVE
;*	ANDCAM	P1,PT2TAB(P2)		;CLEAR P2.LIP IN ALL FREE PAGES
	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##
	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::JUMPL	P1,LOKPH1	;IF LOCKING PAGES
	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	LOKPH1
	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
LOKPH1:	JUMPE	T1,LOKPH5	;LOCK PAGES, ONLY SPECIFIC PAGES LISTED
	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,MMOWN##	;IN CASE OWN MM ALREADY (LOCKING PAGES)
	  PUSHJ	P,UPMM##	;MUST HAVE THE MM RESOURCE WHEN SCANNING PAGTAB
>
LOKPH2:	TDZA	T4,T4		;LARGEST HOLE SEEN SO FAR
LOKPH3:	ADDI	T4,1		;INCREMENT SIZE OF LARGEST HOLE
	CAIN	T3,(T2)		;LOOKED AT ALL OF 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,LOKPH3	;NO, COUNT IT IN THIS HOLE
	CAMG	T4,T1		;IS THIS HOLE BIG ENOUGH?
	AOJA	T2,LOKPH2	;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,
>
	CAIG	T2,PAGSIZ	;WILL THE JOB BE IN THE FIRST 256K OF CORE?
	JRST	LOKPH9		;YES, WE'RE GOLDEN
	JUMPL	P1,LOKPH9	;PAGE. USERS CAN TAKE CARE OF THEMSELVES
	CAILE	P1,JOBMAX##	;DOING JUST A LOWSEG?
	SKIPA	T3,P3		;NO, KEEP BITS WHERE THEY WERE
	MOVS	T3,P3		;YES, MOVE THEM FOR MY CONVENIENCE
	TLNN	P1,-1		;DOING BOTH?
	HLRS	T3		;NO, MAKE BOTH HALVES LOOK THE SAME
	TRNE	T3,LKAB!LKPB	;IF EITHER HALF
	TLNN	T3,LKAB!LKPB	;CARES,
IFN FTMP,<JRST	DWNMM##>	;THEN IT LOSES
IFE FTMP,<POPJ	P,>		;SO FAIL IT
LOKPH9:	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
	JUMPG	P1,LOKPH8	;IF ACTUALLY LOCKING ENTIRE JOB
LOKPH5:	PUSHJ	P,FSTPAG##	;;DO SPECIFIC  LOCK PAGES ARGS
	MOVN	T3,P1		;COUNT OF ARGS
LOKPH6:	PUSHJ	P,NXTLPG##	;GET NEXT PAGE
	JUMPL	T1,LOKPH7	;AN UNLOCK PAGE
	TRNN	T1,-1		;SPECIFIC PAGE REQUESTED?
	JRST	LOKPH7		;NO, TOOK CARE OF THIS EARLIER
	SSX	T1,MS.MEM	;MAKE PAGTAB INDEX
	SKIPL	T2,PAGTAB(T1)	;IS PAGE FREE?
	JRST	[MOVSI	T4,(P2.LIP) ;NO, JUST SET LOCK IN PROGRESS
		 IORM	T4,PT2TAB(T1)
		 JRST	LOKPH7]	;AND CONTINUE
	HRRZ	T4,PT2TAB(T1)	;PREVIOUS PAGE TO OURS (IF ANY)
	SSX	T2,MS.MEM	;PAGTAB IDX
	TRNE	T2,-1		;IF THERE IS A SUCCESSOR TO US
	HRRM	T4,PT2TAB(T2)	;YES POINT US AT HIS PREDECESSOR (OR NONE)
	SKIPE	T4		;IS THERE A PREDECESSOR
	TLOA	T4,(MS.MEM)	;YES, SET INDEX UP
	MOVEI	T4,PAGPTR-PAGTAB ;ELSE PREDECESSOR IS PAGTAB
	HRRM	T2,PAGTAB(T4)	;POINT PREDECESSOR AT SUCCESSOR
	HRR	T2,LOKPTR	;CURRENT 1ST PAGE IN LOKQUE
	HRRZM	T1,LOKPTR	;NEW 1ST PAGE IN LOKQUE
	HLLZS	PT2TAB(T1)	;WHICH HAS NO PREDECESSOR
	HRRM	T2,PAGTAB(T1)	;OUR SUCCESSOR
	TRNE	T2,-1
	HRRM	T1,PT2TAB(T2)	;POINT HIM AT US
	AOS	LOKHOL##	;DO THE BOOKEEPING
	SOS	BIGHOL##
	AOS	LOKTAL##
	SOS	CORTAL##
LOKPH7:	SOJG	T3,LOKPH6
LOKPH8:
IFN FTMP,<
	PUSHJ	P,DWNMM##	;RETURN MM
>
	JUMPL	P1,LOCKP
	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
	CAILE	P1,JOBMAX##	;LOCKING A HIGH SEG?
	SKIPG	J,.HBSGN(P4)	;YES, BE SURE IT'S A REAL SEG
	JRST	LOCKIT		;NO
	TLNN	J,SHRSEG	;AND THAT IT'S SHARABLE
	JRST	LOCKIT		;NOT SHARABLE
	HRRZS	J		;CLEAR JUNK
	MOVEI	T1,HSTOP##	;YES, FORCE OTHER USERS OF HIGH SEG TO STOP
	TLO	T1,(1B0)	;DON'T APPLY TO US
	PUSHJ	P,HGHAPP##
	JRST	LOCKIT		;NOW LOCK JOB
LOCKP:	MOVN	P2,P1		;SAVE # OF ARGS IN P2 FOR CLOCK LEVEL
	MOVE	P1,.CPJOB##
	MOVEI	T1,PAGLOK##	;SET RH SIGN BIT TO INDICATE PAGE FORMAT
	IORM	T1,LOKREL##
LOCKIT:	MOVEI	T1,LOK		;MAKE THE JOB UNRUNNABLE UNTIL LOCKING
	MOVE	J,.CPJOB##	;(JOB # IN QUESTION)
	IORM	T1,JBTSTS##(J)	; IS COMPLETE
	MOVEM	P1,LOCK##	;STORE #S FOR LOCK
	PUSHJ	P,WSCHED##	;RESCHEDULE, RETURN WHEN JOB IS LOCKED
RASBAD:	LDB	T1,JBYLSA##	;STARTING PAGE NUMBER OF THE LOW SEGMENT
	JUMPE	P4,CPOPJ1##	;DONE IF NO HIGH SEG
	SKIPG	J,.HBSGN(P4)	;JOB HAVE A REAL HIGH SEGMENT?
	PJRST	CPOPJ1##	;NO HISEG, GIVE LOCKED RETURN (T1 = LOSEG ADDR)
	TLNN	J,SHRSEG	;SHARABLE?
	JRST	RASBD1		;NO
	HRRZS	J		;CLEAR JUNK
	MOVEI	T1,HGO##	;..
	TLO	T1,(1B0)	;DON'T APPLY TO US
	PUSHJ	P,HGHAPP##
	MOVE	J,.HBSGN(P4)	;RELOAD J
RASBD1:	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
;

UNLOCK::MOVE	T1,[XWD LKB,LKB];UNLOCK BOTH LOW AND HIGH SEGMENTS
UUNLOK::SE1ENT			;MUST BE RUN IN S1
	PUSHJ	P,SAVE4##	;SAVE P1-P4
	SKIPGE	P1,T1		;INIT ARG POINTER; EXTENDED FORMAT LIST?
	JRST	UNLOKX		;YES, PROCESS IT
UNLRET:	PUSHJ	P,NSHCHK	;CHECK NON-SHARABLE PROBLEMS
	  JRST	RTZER##		;NOT IMPLEMENTED
	CAILE	J,JOBMAX##	;JOB?
	  TDZA	P4,P4		;NO, NO HIGHER SEG THEN
	HRRZ	P4,JBTSGN##(J)	;IF JOB, POINT TO FIRST HIGH SEG
UNLOK1:	PUSHJ	P,UNLOK2	;UNLOCK
	JUMPL	P1,UNLOX1	;EXTENDED
	JUMPE	P4,CPOPJ1##	;NO, WE ARE DONE
	HRRZ	P4,.HBLNK(P4)	;IS THERE ANOTHER?
	JUMPE	P4,CPOPJ1##	;DONE
UNLOC1:	SKIPLE	T2,.HBSGN(P4)	;IS THIS A REAL HIGH SEG?
	TLNN	T2,SHRSEG!LOKSEG!NCSH ;SHARABLE OR REALLY LOCKED?
	JRST	UNLOC2		;NO
	HRRZS	T2		;CLEAR JUNK
	MOVE	T2,JBTSTS##(T2)	;GET STATUS WORD
	TLNN	T2,NSHF!NSWP	;LOCKED?
	JRST	UNLOC2		;NO
	PUSH	P,J		;SAVE J
	PUSHJ	P,UNLOKH	;UNLOCK THAT SEGMENT
	POP	P,J		;RESTORE J
UNLOC2:	HRRZ	P4,.HBLNK(P4)	;NEXT
	JUMPN	P4,UNLOC1
	AOS	(P)
	POPJ	P,
UNLOKH::SE1ENT			;ENTER S1 HERE
	MOVSI	T1,LKB		;UNLOCK HIGH SEG
UNLOK2:	PUSHJ	P,SAVE4##	;PRESERVE ACCUMULATORS
	PUSH	P,T1		;SAVE ARUMENT WHILE UNLOCKING
ZZ==.				;PLACE ON STACK FOR ARGUMENT (T1)
	PUSH	P,J		;SAVE JOB NUMBER
ZZ==.-ZZ			;DEPTH ON STACK FOR ARGUMENT (T1)
	MOVSI	P3,NSHF!NSWP
	MOVEI	J,(J)		;CLEAR POSSIBLE LEFT HALF BITS
	CAILE	J,JOBMAX##	;IS THIS A HIGH SEGMENT?
	JRST	UNLOK6		;YES IF CALLED FROM SEGCON OR LOKINI
	TRNE	T1,LKB		;UNLOCK THE LOW SEGMENT?
	TDNN	P3,JBTSTS##(J)	;IS IT LOCKED?
	JRST	UNLOK3		;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)
UNLOK3:	TRNE	P4,-1		;IS THERE A HIGH SEG TO UNLOCK?
	TLNN	T1,LKB		;UNLOCK THE HIGH SEGMENT?
	JRST	UNLOK7		;NO
	MOVSI	P2,LOKSEG	;BIT TO TEST
	ANDCAM	P2,.HBSGN(P4)	;CLEAR LOCKED BIT FOR THIS SEG
	SETZ	T1,		;START AT THE BEGINNING
UNLO3A:	PUSHJ	P,GNXHSB##	;GT NEXT HIGH SEG BLOCK
	  JRST	[ANDCAM	P2,JBTSGN##(J)
		 JRST	UNLO3C]	;ALL HIGH SEGS UNLOCKED
	CAIE	T1,(P4)		;IS IT THIS BLOCK?
	TDNN	P2,.HBSGN(T1)	;IS THIS SEGMENT LOCKED?
	JRST	UNLO3A		;THIS SEGMENT OR IT ISN'T LOCKED, CHECK NEXT
UNLO3C:	MOVEI	T1,(P4)		;HIGH SEG DATA BLOCK
	S0PSHJ	MAPHGH##	;TURN ON CACHE BITS IN THE MAP
	SKIPGE	.HBSGN(P4)	;SPY SEGMENT?
	JRST	UNLOK7		;IGNORE THIS ONE
	HRRZ	J,.HBSGN(P4)	;SEGMENT #
	LDB	T1,JBYVAD##	;GET MAP ADDRESS
	JUMPE	T1,UNLOK7	;NON-SHARABLE HIGH SEG
	SOSLE	.M2LCN-.M2MAX(T1) ;DECREMENT LOCKERS
	JRST	UNLOK7		;DON'T UNLOCK IF OTHERE LOCKERS
UNLOK6:	MOVSI	T1,NSHF!NSWP	;IS HIGH SEGMENT LOCKED?
	TDNN	T1,JBTSTS##(J)	;?
	JRST	UNLOK7		;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
UNLOK7:	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
;ROUTINE TO PROCESS EXTENDED FORMAT UNLOCK

UNLOKX:
UNLOX1:	AOBJP	P1,CPOPJ1##	;EXIT SUCCESS IF DONE
	HRRZ	T1,P1		;GET NEXT ARG
	PUSHJ	P,GETWDU##	;FRUM USER
	TRNN	T1,L2SGN	;JOB OR SEGMENT?
	JRST	UNLOXL		;LOW SEG
	PUSHJ	P,FNDHSB##	;POINT TO THE HIGH SEG BLOCK
	  JRST	RTZER##		;NOT FOUND ***SHOULD USE REAL ERROR***
	MOVE	P4,T1		;PUT BLOCK ADDR IN P4
	MOVSI	T1,LKB		;FLAG TO UNLOCK HIGH SEG
	JRST	 UNLRET		;AND RETURN
UNLOXL:	SETZ	P4,		;NO HIGH SEG
	MOVEI	T1,LKB		;UNLOCK LOW SEG
	JRST	UNLRET		;AND DO THE UNLOCK
FRELOK:	MOVSI	T1,NSHF!NSWP
	ANDCAM	T1,JBTSTS##(J)	;TURN OFF NSHF AND NSWP
	CAILE	J,JOBMAX##	;IS IT A HIGH SEGMENT?
	JRST	FRELK0		;NO, IF THIS IS A LOW SEG...
	SETZ	T1,		;THEN ALL NON-SHARABLE
FRELKA:	PUSHJ	P,GNXHSB##	;HIGH SEGS ARE ALSO BEING UNLOCKED NOW
	  JRST	FRELK0		;DONE IF NO MORE
	SKIPLE	T2,.HBSGN(T1)	;IS THIS A REAL HIGH SEG?
	TLOE	T2,<(IFIW)>!SHRSEG ;AND IS IT NON-SHARABLE
	.CREF	SPYSEG		;(TURN ON IFIW WHICH IS ALSO SPYSEG
				;AND MUST BE OFF TO BE HERE)?
	JRST	FRELKA		;SPY OR SHARABLE, LOOP ON
	MOVSI	T3,NSHF!NSWP
	ANDCAM	T3,JBTSTS##(T2)	;CLEAR LOCKED BITS FOR HIGH SEG
	MOVSI	T3,LOKSEG
	ANDCAM	T3,.HBSGN(T1)	;AND IN THIS HIGH SEG BLOCK
	JRST	FRELKA		;AND GO ON

FRELK0:	LDB	T1,JBYSSA##	;PAGE NUMBER OF FIRST PAGE OF THE 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
	LDB	T3,JBYLSA##	;PAGE ZERO 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:	MOVSI	T3,LOKSEG	;THIS JOB HAVE A LOCKED HIGH SEG?
	TDNN	T3,JBTSGN##(J)	;?
	JRST	CKLJB		;NO, LOOK AT THE NEXT JOB
	PUSH	P,T1		;SAVE T1 (LOWER BOUND)
	SETZ	T1,		;FIRST CALL
CKLJB2:	PUSHJ	P,GNXHSB##	;GET NEXT HIGH SEG BLOCK
	  JRST	CKLJB3		;NO MORE
	TDNN	T3,.HBSGN(T1)	;IS THIS SEGMENT LOCKED?
	JRST	CKLJB2		;NO, LOOK AT NEXT
	HRRZ	T3,.HBSGN(T1)	;GET SEGMENT #
	LDB	T3,[POINT 13,JBTHSA##(T3),35]
	EXCH	T1,(P)		;SAVE CURRENT HS BLOCK, GET LIMIT
	PUSHJ	P,CKPGS		;SEE IF THE HIGH SEGMENT PAGES OVERLAP THE RANGE
	  JRST	T3POJ1##	;THEY DO, TELL THE CALLER
	EXCH	T1,(P)		;STORE LIMIT, GET HIGH SEG BLOCK BACK
	JRST	CKLJB2		;CHECK ANOTHER HIGH SEG
CKLJB3:	POP	P,T1		;RESTORE T1
	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
	MOVE	T3,[NXMTAB##,,OLDNXM##] ;SET UP BLT TO COPY NXMTAB
	BLT	T3,NXMTAB##+NXMTBL##-1 ;MAKE "OLD" COPY OF ERROR LOGGING
	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
>
	MOVEI	T1,.CSCMF	;CONFIG STATUS CHANGE CODE
	PUSHJ	P,MEMELG##	;MAKE AN ERROR LOG ENTRY
	PJRST	SETEDV##	;RESET EDV POINTERS AND RETURN
;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 CHECK IF LOCKING/UNLOCKING JUST HIGH OR LOW SEG OF
;JOB WITH A NON-SHARABLE HIGH SEG.  RETURN CPOPJ IF ARE, CPOPJ1 IF NOT (OK CASE)
;USES T2
NSHCHK:	PUSH	P,T1		;SAVE T1
	HLRZ	T2,T1		;GET HIGH SEG LOCK BITS
	XORI	T2,(T1)		;ARE BOTH SEGS TO BE LOCKED/UNLOCKED?
	TRNN	T2,LKB		;?
	JRST	TPOPJ1##	;YES, NO SWEAT
	SETZ	T1,		;START LOOP
	MOVSI	T2,SHRSEG!SPYSEG ;MUST BE SHARABLE
NSHCK0:	PUSHJ	P,GNXHSB##	;NEXT HIGH SEG
	  JRST	TPOPJ1##	;ALL IS CLEAR
	TDNE	T2,.HBSGN(T1)	;IS THIS HIGH SEG SHARABLE?
	JRST	NSHCK0		;YES, ALL STILL OK
	POP	P,T1		;RESTORE T1
	POPJ	P,		;HAS A NON-SHARABLE HIGH SEG

;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,
GETLOW:	LDB	P1,JBYLSA##	;LOW SEGMENT PHYSICAL ADDRESS
	MOVE	T1,P3		;COPY OF ARG
	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	CPOPJ1##	;RETURN WITH VALUES IN T1

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	CHKCS2
	MOVSI	T2,(JS.NCS)
	IORM	T2,JBTST2##(J)
CHKCS1:	MOVE	J,.CPJOB##
CHKCS2:	SKIPG	.HBSGN(P4)
	POPJ	P,
	TLNE	T1,LKB
	TLNE	T1,LKCB
	POPJ	P,
	MOVSI	T2,NCSH
	IORM	T2,.HBSGN(P4)
	POPJ	P,

;SUBROUTINE TO SEE IF THIS IS THE FIRST PAGE OF
; A NON-SHARABLE HIGH SEGMENT
FPNSHS:	SKIPN	P4
	POPJ	P,
	ADDI	P4,PAGSIZ
	PUSHJ	P,SAVT##
	PUSHJ	P,SAVE1##		;SAVE P1
	MOVE	P1,.USSPT
	SETZ	T1,
FPNSH1:	PUSHJ	P,NXSSP1##		;GET NEXT SEGMENT THIS SECTION
	  POPJ	P,			;NONE
	PUSH	P,T1			;SAVE T1
	HRRZ	T1,M
	PUSHJ	P,TPAHS##
	  SKIPA	T4,T1
	JRST	TPOPJ##			;NOT SHARABLE
	POP	P,T1			;RESTORE T1
	PUSH	P,J
	HRRZ	J,.HBSGN(T1)		;GET SEGMENT NUMBER
	SKIPL	P4
	HRRM	P4,JBTADR##(J)
	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
CSHLS1:	PUSHJ	P,NXTWSB##
	CAIA
CSHLS2:	PUSHJ	P,NXTWS3##
	TRNE	M,<-1^!HLGPNO>		;USER PAGE?
	AOSA	.USSPT
	SKIPA	P2,(T4)
	JRST	CSHLS1
	TLO	P2,(PM.CSH)
	MOVEM	P2,(T4)
	SOJG	P1,CSHLS2
	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
	SUBTTL	INITIALIZATION

	$INIT

LOKINI::HRREI	T1,LOKMAX##	;SET GUARANTEED CORE FOR T-S JOBS
	SKIPGE	DEBUGF##	;DEBUGGING?
	MOVEI	T1,0		;THE SKY'S THE LIMIT
	JUMPL	T1,LOKIN1
	ASH	T1,P2WLSH	;MAKE PAGES INTO WORDS
	CAML	T1,MEMSIZ##
LOKIN1:	MOVE	T1,CORMAX##	;CORMIN_CORMAX
	MOVEM	T1,CORMIN##	;SAVE IT FOR TESTING
	POPJ	P,		;RETURN

	$HIGH

LOKEND:	END