Google
 

Trailing-Edge - PDP-10 Archives - AP-D543V_SB - kilock.mac
There are 2 other files named kilock.mac in the archive. Click here to see a list.
TITLE KILOCK -  KI10 MODULE FOR LOCKING JOBS IN CORE - V7107
SUBTTL J. FLEMMING  TS     19 SEP 78
	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.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VKILOK,7107			;PUT VERSION NUMBER IN STORAGE MAP

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

KILOCK:	;ENTRY POINT SYMBOL TO CAUSE LOADING OF KILOCK

EXTERNAL LOKREL,LOCK,CORMIN,PAGSIZ,P2WLSH,W2PLSH,LASLOK
EXTERNAL BIGHOL,CORTAL,JBYHSA,JBYLSA,PAGPTR,PCORSZ,SYSSIZ
EXTERNAL JOBMAX,JBTMAX,.C0JOB
EXTERNAL JBTADR,JBTSTS,JBTUPM
IFN FTSWAP,<
EXTERNAL FORCE0,FIT1,FORIDL
>
IFN FT2REL,<
EXTERNAL TWOREG,JBTSGN
>
EXTERNAL CPOPJ,TPOPJ,T2POPJ
EXTERNAL PCORSZ
INTERNAL FTSWAP,FTPRV,FTRTTRP,FTMETR
INTERNAL LOCK0
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::
IFN FTMOFFL,<
	MOVE	J,LOCK##	;-1 IF SETTING MEMORY OFF LINE
	AOJE	J,[HLRZ P2,LOKREL##
		IFN FT2SEGMON,<SKIPN MOFLPG##>
		JRST LOCK1A	;GO IF NOT SETTING MONITOR MEMORY OFF-LINE
		IFN FT2SEGMON,<	LDB P2,[POINT 14,MEMSIZ##,26]
		LDB P3,[POINT 9,SYSSIZ##,26]
		SUB P2,P3	;FORCE EVERYTHING OUT IF SETTING MONITOR MEMORY OFF
		JRST LOCK2>]
>
	HRRZ	J,LOCK		;SEGMENT NUMBER OF SEGMENT TO BE LOCKED
LOCK1:	SKIPN	JBTADR(J)	;IS THIS SEGMENT IN CORE?
	JRST	[MOVE J,LASLOK##  ;NO, GO CAUSE IT TO BE SWAPPED IN
		 JRST FIT1##]
	LDB	P2,PCORSZ##	;HIGHEST PAGE IN THE SEGMENT
	ADDI	P2,1		;NUMBER OF PAGES IN THE SEGMENT
	CAIG	J,JOBMAX	;IS THIS A LOW SEGMENT?
	ADDI	P2,UPMPSZ	;YES, ACCOUNT FOR THE UPMP SIZE
LOCK1A:	HRRZ	P3,LOKREL	;PAGE NUMBER OF STARTING PAGE THIS SEGMENT
				; IS TO BE LOCKED IN
LOCK2:	SKIPGE	T1,PAGTAB(P3)	;IS THIS PAGE ON THE FREE CORE LIST?
	JRST	LOCK6		;YES, LOOP ON
IFN FTIPCF,<
	TLNE	T1,IPCBIT	;AN IPCF PAGE?
	POPJ	P,		;YES, DELAY UNTIL ITS RECEIVED
>
IFN FTMOFFL,<
	SKIPGE	LOCK		;SETTING MEMORY OFF-LINE?
	TLNN	T1,NXMBIT+MONTRB;YES, IGNORE MONITOR AND NON-EXISTANT PAGES
	SKIPA	P1,P3		;NO, PAGE NUMBER TO P1
	JRST	LOCK6		;LOOK AT THE NEXT PAGE
>
IFE FTMOFFL,<
	MOVE	P1,P3		;ITS NOT A FREE PAGE, SEE WHO IT BELONGS TO
>
	LSH	P1,P2WLSH##	;CONVERT PAGE NUMBER TO AN ABSOLUTE ADDRESS
	TLO	P1,400000	;PREVENT CPIASN FROM COMPUTING A VIRTUAL ADDRESS WITHIN SEGMENT
	PUSHJ	P,CPIASN##	;FIND THE SEGMENT NUMBER OF THE SEGMENT
				; CONTAINING THIS PAGE
	  TDZA	T2,T2		;NOT IN ANY SEGMENT - IT SHOULD BE ON THE
				; FREE CORE LIST
	JUMPN	J,LOCK3		;WAS A SEGMENT CONTAINING THIS PAGE FOUND?
	SKIPN	J,T2		;OR IS THE PAGE SOME JOBS UPMP?
	STOPCD	.,STOP,SNF,	;++SEGMENT NOT FOUND
LOCK3:	HRRZ	T1,LOCK		;T1 = SEGMENT NUMBER OF SEGMENT BEING LOCKED
	CAIN	T1,(J)		;PAGE FOUND CONTAINED IN SEGMENT BEING LOCKED?
	JRST	LOCK6		;YES, NO ACTION NECESSARY
	CAIG	J,JOBMAX	;IS THE SEGMENT CONTAINING THE PAGE WHICH
				; MUST BE MOVED A HIGH SEGMENT?
	JRST	LOCK5C		;NO, JUST SWAP THIS SEGMENT OUT
	MOVE	P1,JBTSTS(J)	;P1 = INCORE COUNT FOR THIS HIGH SEGMENT
	TRNE	P1,ICCMSK	;IS THIS A DORMANT OR IDLE HIGH SEGMENT?
	JRST	LOCK4		;NO, MUST SWAP OUT THE LOW SEGMENTS SHARING
				; IT TO MAKE IT GO AWAY
LOK3A:	PUSHJ	P,FREC4##	;ITS DORMANT OR IDLE - GO DELETE IT FROM CORE
	  JRST	FORIDL##	;IDLE WITH NO COPY ON THE DISK - WRITE ENABLED
	  JRST	LOCK0		;THE SEGMENT HAS BEEN DELETED FROM CORE - TRY AGAIN
LOCK4:	MOVE	T2,J		;SAVE HIGH SEGMENT NUMBER
	MOVE	J,HIGHJB	;FIND A JOB SHARING IT
LOCK5:	SKIPE	T1,JBTSGN(J)	;THIS JOB HAVE A HIGH SEGMENT?
	CAIE	T2,@T1		;YES, IS IT THE ONE WE WANT TO SWAP?
	JRST	LOCK5B		;NO, LOOK AT NEXT JOB
	SKIPE	JBTADR(J)	;IS JOB IN CORE?
	JRST	LOCK5A		;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
	PUSHJ	P,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,LOK3A	;NO MORE JOBS SO SWAP OUT HIGH SEG
	EXCH	J,T2		;GET READY TO LOOK AT NEXT JOB
	JRST	LOCK5B		;GO DO IT
LOCK5A:	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	LOCK5B		;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	FORCE0		;NO, SWAP OUT THE JOB
LOCK5B:	SOJG	J,LOCK5		;LOOK AT NEXT JOB
	STOPCD	.,STOP,SSO,	;++SEGMENT SWAPPED OUT
LOCK5C:	PUSHJ	P,ANYRUN##
	 JRST	LOCK5D
	JRST	FORCE0##
LOCK5D:	MOVEM	J,SW0JOB##
	POPJ	P,

LOCK6:	AOS	P3		;NEXT PHYSICAL PAGE WHICH MUST BE FREED
	SOJG	P2,LOCK2	;LOOP UNTIL ALL NECESSARY PAGES ARE AVAILABLE
IFN FTMOFFL,<
	SKIPGE	T1,LOCK##	;LOCK IS -1 IF SETTING MEMORY OFF
	AOJE	T1,SETMFL	;GO MOVE THE MONITOR AND SET MEMORY OFF
>
;ALLOCATE CORE, BLT SEGMENT INTO PLACE, AND LOCK IT
	HRRZ	J,LOCK		;SEGMENT NUMBER OF SEGMENT BEING LOCKED
	CAILE	J,JOBMAX##	;IS IT A HIGH SEGMENT?
	JRST	LOCK7		;NO, DON'T NEED TO ADDRESS THE UPMP
	CAME	J,.C0JOB##	;IS THIS THE CURRENT JOB? IF SO UPMP IS ADDRESSABLE
	PUSHJ	P,SVEUB##	;MAKE THE UPMP ADDRESSABLE
LOCK7:	MOVE	R,JBTADR(J)	;ANYACT REQUIRES THAT R BE SETUP
	PUSHJ	P,ANYACT##	;ANY ACTIVE I/O?
	  POPJ	P,		;YES, TRY AGAIN NEXT CLOCK TICK
	HRRZ	J,LOCK		;SEGMENT NUMBER OF SEGMENT BEING LOCKED
	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	LOCK9		;NO, NEEDN'T WORRY ABOUT MOVING THE UPMP
	HRRZ	T1,JBTUPM(J)	;PAGE NUMBER OF UPMP
	CAIN	T1,(P2)		;IS THE UPMP ALREADY IN PLACE?
	JRST	LOCK8		;YES, DOESN'T NEED TO BE MOVED
	LDB	P3,JBYLSA	;PAGE NUMBER OF FIRST PAGE OF THE JOB
	PUSHJ	P,PAGMOV	;MOVE THE UPMP TO THE DESIRED POSITION
	MOVEI	T1,PM.ACC+PM.WRT(P2)
	HRLM	T1,.EUPMP+.MUPMP;MAKE THE UPMP ADDRESSABLE IN ITS NEW
				; POSITION THROUGH THE PER PROCESS MAP
	CAIE	P2,(P3)		;WAS THE UPMP EXCHANGED WITH THE FIRST PAGE
				; OF THE LOW SEGMENT (PAGE CONTAINING JOB
				; DATA AREA)?
	JRST	LOCK8		;NO
	HRRZ	T1,.EPMP##+.MECKS
	HRRM	T1,.EUPMP+.MJDAT;YES, MAKE THE JOB DATA AREA ADDRESSABLE
				; THROUGH THE PER PROCESS MAP
LOCK8:
	HRRI	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	PAGTAB(P2)	;SIGNAL ONLY THIS PAGE IS ALLOCATED
	MOVSI	T1,LOKPHB	;AND INDICATE THAT THE UPMP IS LOCKED
	IORM	T1,PAGTAB(P2)	; IN PHYSICAL MEMORY
	HRRM	P2,JBTUPM(J)	;STORE THE NEW PAGE NUMBER OF THE UPMP
IFN FTKL10,<
	TDO	P2,[LG.LUB+LG.IAM]
	DATAO	PAG,P2
>
IFN FTKI10,<
	PUSHJ	P,STEUB##	;AND MAKE THE UPMP ADDRESSABLE THROUGH
				; THE PER PROCESS MAP (CLEAR THE AM)
>
	HRRZ	P2,LOKREL	;P2 = PHYSICAL PAGE WHERE FIRST PAGE OF THE
				; LOW SEGMENT SHOULD GO
LOCK9:	LDB	P3,PCORSZ##	;HIGHEST PAGE IN THE SEGMENT
	ADDI	P3,1		;NUMBER OF PAGES IN THE SEGMENT
LOCK10:	MOVE	T2,P1		;T2 = RELATIVE PAGE NUMBER INTO THIS SEGMENT
	PUSHJ	P,SNPAGS##	;FIND WHICH PHYSICAL PAGE CONTAINS THE RELATIVE PAGE
	CAIE	P2,(T1)		;IS THE PAGE ALREADY IN PLACE?
	PUSHJ	P,PAGMOV	;NO, MOVE IT
	JUMPN	P1,LOCK12	;JUMP IF NOT THE FIRST PAGE OF THE SEGMENT
	CAILE	J,JOBMAX	;IT IS THE FIRST PAGE - IS THIS A LOW SEGMENT?
	JRST	LOCK11		;NO, STORE NEW ADDRESS OF FIRST PAGE OF HIGH SEGMENT
	MOVEI	T1,PM.ACC+PM.WRT(P2)
	HRRM	T1,.UPMP+.MJDAT	;AND MAKE THE JOB DATA ADDRESSABLE
	PUSHJ	P,NEWMAP	;CLEAR THE AM SO NEW MAPPING IS IN EFFECT
	JRST	LOCK12		;AND CONTINUE ON
LOCK11:	DPB	P2,JBYHSA	;NEW ADDRESS OF FIRST PAGE OF HIGH SEGMENT
LOCK12:
	MOVSI	T1,LOKPHB	;INDICATE THIS PAGE IS LOCKED IN PHYSICAL MEMORY
	SKIPE	P1		;SKIP IF FIRST PAGE OF THE SEGMENT
	IORM	T1,PAGTAB-1(P2)	; CONTIGIOUSLY
	ADDI	P1,1		;NEXT RELATIVE PAGE WITHIN THE SEGMENT
	ADDI	P2,1		;STEP TO NEXT TARGET PAGE
	SOJG	P3,LOCK10	;LOCK THE NEXT PAGE
	MOVEM	T1,PAGTAB-1(P2)	;INDICATE LAST PAGE OF THE SEGMENT
	MOVSI	T1,NSHF!NSWP	;AFTER ALL THAT WORK
	IORM	T1,JBTSTS(J)	; MAKE SURE THE SEGMENT DOESN'T SWAP
	HLRZS	J,LOCK		;GET THE SEGMENT NUMBER OF THE LOW SEGMENT
				; IF THERE IS ONE LEFT TO BE LOCKED
	JUMPE	J,LOCK13	;JUMP IF DONE
	HLRZS	LOKREL		;STARTING PAGE NUMBER FOR THE LOW SEGMENT
	JRST	LOCK1		;AND GO TRY TO LOCK IT
LOCK13:	MOVEI	T1,LOK		;SET TO MAKE JOB RUNABLE AGAIN
	MOVE	J,LASLOK	;GET THE JOB NUMBER OF JOB ISSUING LOCK UUO
	MOVSI	T2,1001		;MAKE SURE MAP
IFN FTVM,<
	PUSHJ	P,[PUSHJ  P,SVEUB##
		   SKIPN  .UPMP+.UPVRT	;IF VIRTUAL,
		   SKIPE  .UPMP+.UPREL	;OR NON-CONTIGOUS,
		   TLZ	  T2,777	;THEN, MUST BE LOCKING ONLY HI SEG
		   POPJ	  P,]
>
	SKIPG	JBTSGN##(J)	;SPY OR NO HI SEG?
	TLZ	T2,777000	;YES, DON'T REDO HI SEG PART OF THE MAP
	ADDM	T2,JBTUPM(J)	; GETS REDONE
	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
	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
	HRLI	T2,0		;REMOVE LH OF JBTSGN FOR THIS JOB
	MOVE	T1,HIGHJB	;HIGHEST NUMBERED JOB
	MOVSI	T3,1000		;SIGNAL TO MAP HIGH SEGMENT
LOCK14:	SKIPLE	T4,JBTSGN(T1)	;GET HIGH SEGMENT OF ALL JOBS
	SKIPN	JBTADR(T1)	;IGNORE IF NOT IN CORE
	JRST	LOK14A
	CAME	J,T1		;DON'T DO IT TO OUR JOB
	CAIE	T2,@T4		;SAME HIGH SEGMENT AS OURS?
	JRST	LOK14A		;NO. LOOK AT NEXT ONE
	ADDM	T3,JBTUPM(T1)	;YES. ADD TO SIZE SO IT WILL REMAP
	TLO	T4,SEGMB	;SET SEGMENT MOVED BIT
	MOVEM	T4,JBTSGN(T1)	;SO IF NEXT JOB WAS LAST JOB, ALL
LOK14A:	SOJG	T1,LOCK14	;LOOP FOR ALL JOBS
	POPJ	P,		;AND RETURN
IFN FTMOFFL,<
SETMFL:
IFN FT2SEGMON,<
;HERE TO MOVE THE MONITOR IF NECESSARY
	SKIPN	P4,MOFLPG##	;ANY OF THE PAGES BEING SET OFF CONTAIN MONITOR CODE?
	JRST	SETMF5		;NO, THEN THIS IS EASY
	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
SETMF1:	MOVE	T1,PAGTAB(P3)	;GET PAGE DESCRIPTOR BITS
	TLNE	T1,MONTRB	;DOES THIS PAGE CONTAIN MONITOR CODE?
	JRST	SETMF2		;YES
	AOBJN	P3,SETMF1	;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
SETMF2:	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	T1,PAGTAB(P2)	;YES, AND IS THE CANDIDATE PAGE FREE?
				; IF NOT, IT MUST CONTAIN A PAGE OF THE MONITOR
	JRST	SETMF2		;NO, LOOK AT THE NEXT CANDIDATE
	HRRZ	T1,P3		;SOURCE PAGE
	PUSHJ	P,PAGFRE	;MOVE THE PAGE
	  STOPCD	.,STOP,FPN,	;++FREE PAGE NOT FOUND
;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
	LDB	T1,[POINT 9,SYSLEN##,26]
	MOVE	T2,[POINT 18,.EPPM##+<MONORG-400000>/<2*1000>]
SETMF3:	ILDB	T3,T2		;GET THE NEXT MAP ENTRY
	ANDI	T3,17777	;CLEAR ACCESS BITS
	CAIN	T3,(P3)		;IS THIS THE PAGE WHICH WAS JUST MOVED?
	JRST	SETMF4		;YES
	SOJG	T1,SETMF3	;LOOP OVER ALL OF THE MONITORS PAGES
	STOPCD	.,STOP,MPN,	;++MONITOR PAGE NOT FOUND
;HERE WITH THE BYTE POINTER TO THE EXEC MAP SLOT IN T2
SETMF4:	LDB	T1,T2		;GET THE CURRENT CONTENTS OF THE MAP SLOT
	ANDI	T1,760000	;GET THE ACCESS BITS
	ADDI	T1,(P2)		;NEW PAGE NUMBER PLUS ACCESS BITS
	DPB	T1,T2		;STORE NEW PHYSICAL PAGE NUMBER
	SOJG	P4,SETMF1	;MOVE THE NEXT MONITOR PAGE
> ;END FT2SEGMON

; STILL IN FTMOFFL
;HERE WHEN ALL PAGES TO BE SET OFF LINE ARE FREE AND ANY MONITOR
; PAGES WHICH NEEDED TO BE HAVE BEEN MOVED
SETMF5:	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
SETMF6:	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,SETMF6	;MARK ALL PAGES IN THE REQUEST AS OFF LINE
	SETZM	LOCK		;INDICATE SUCCESS
	SETOM	LASLOK		;ALLOW COMMAND TO SIGNAL COMPLETION
	PJRST	CPINXF##	;FIXUP PAGTAB, CORTAL, BIGHOL, CORMAX, MAXMAX, ETC.
> ;END FTMOFFL


;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:	MOVEI	T3,PAGPTR	;PRESET PREDECESSOR
	SKIPN	T2,PAGPTR	;START LOOKING AT 1ST FREE PAGE
	POPJ	P,		;NONE FREE
PAGFR1:	CAIN	P2,(T2)		;TARGET PAGE ON FREE LIST?
	JRST	PAGFR2		;YES
	MOVEI	T3,PAGTAB(T2)	;NO, SET PRED.
	SKIPL	T2,PAGTAB(T2)	;STEP TO NEXT PAGE IN FREE LIST
	STOPCD	.,STOP,FPF,	;++PAGE ON THE FREE LIST ISN'T FREE!
	TRNE	T2,-1		;END OF FREE LIST?
	JRST	PAGFR1		;NO, TEST THIS FREE PAGE
	POPJ	P,		;YES, TARGET PAGE ISNT FREE

;HERE WHEN TARGET PAGE IS ON THE FREE-PAGE LIST
;EXCHANGE TARGET PAGE AND CURRENT PAGE ON THE FREE LIST
PAGFR2:	MOVE	T2,PAGTAB(T2)	;SUCCESSOR OF TARGET PAGE
	EXCH	T2,PAGTAB(T1)	; = SUCCES. OF CURRENT PAGE, GET CURRENT-SUCC.
	MOVEM	T2,PAGTAB(P2)	;SET NEW SUCC. OF TARGET PAGE
	HRRM	T1,(T3)		;SET PRED. OF FREE PAGE WE FOUND
	SKIPE	P1		;DOES THE CURRENT PAGE HAVE A PRED?
	MOVEM	P2,PAGTAB-1(P2);YES, SET PRED TO TARGET PAGE
	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
	CAIE	T2,(P2)		;IS THE TARGET PAGE THE 1ST PAGE OF THE SEG?
	JRST	PAGFD1		;NO
	MOVE	T2,PAGTAB(T1)	;YES, GET SUCC TO CURRENT PAGE
	EXCH	T2,PAGTAB(P2)	;STORE AS SUCC TO TARGET PAGE
	HRRM	T2,PAGTAB(T1)	;SUCC TO TARGET INTO CURRENT SUCCESSOR
	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
	SKIPGE	T2,PAGTAB(T3)	;NOT LAST, GET NEXT PAGE
	STOPCD	.,STOP,PFA,	;++PAGE FREE ALREADY
	CAIE	T2,(P2)		;IS THIS THE TARGET PAGE?
	JRST	PAGFD1		;NO, TRY AGAIN
	SKIPGE	T2,PAGTAB(T1)	;GET SUCCESSOR TO CURRENT PAGE
	STOPCD	.,STOP,NPF,	;++NEXT PAGE FREE
	HRRM	T1,PAGTAB(T3)	;POINT TARGET PRED TO CURRENT PAGE
	CAIN	P2,(T2)		;IS TARGET = SUCCESSOR OF CURRENT PAGE?
	MOVE	T2,T3		;YES, GET PRED TO CURRENT PAGE
	EXCH	T2,PAGTAB(P2)	;SAVE SUCC TO TARGET, GET SUCC TO CURRENT
	HRRM	T2,PAGTAB(T1)	;SAVE SUCCESSOR TO CURRENT PAGE
	SKIPE	P1		;DOES CURRENT PAGE HAVE A PRED?
	HRRM	P2,PAGTAB-1(P2);YES, SET PRED TO TARGET PAGE
PAGFD2:	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:	TRO	T1,PM.ACC+PM.WRT;ACCESS ALLOWED AND WRITABLE
	HRRM	T1,.EPMP##+.MECKS
	MOVEI	T1,PM.ACC+PM.WRT(P2)
	HRLM	T1,.EPMP##+.MEUPM
;	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 TARGETY 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			;TARGET PAGE NOT ON FREE CORE LIST
	POPJ	P,		;PAGE IS IN PLACE
	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

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
	INTERNAL LOKCHK

LOKCHK:	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
IFN FT2REL,<			;2 RELOC REG FEATURE?
	SKIPLE	P2,JBTSGN##(J)	;NO, DOES JOB HAVE A HIGH SEG?
	TDNN	P1,JBTSTS(P2)	;YES, IS IT LOCKED?
	JRST	CPOPJ1		;NEITHER SEGMENT LOCKED
	POPJ	P,		;HIGH SEGMENT LOCKED
>
IFE FT2REL,<
	JRST	CPOPJ1
>
 
;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::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	P1,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,PAGTAB(P1)	;IS IT? (IF FIRST PAGE IS 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.  IT FIRST TRIES THE TOP OF USER CORE, AND IF IT ALREADY
;CONTAINS A LOCKED JOB, THE CALLING JOB IS PUT IN AS LOW CORE AS
;POSSIBLE. 
;CALLING SEQUENCE
;	PUSHJ	P,LOKJOB
;	ERROR RETURN
;	NORMAL RETURN (NSHF+NSWP SET)

INTERNAL LOKJOB,UNLOCK,UNLOK.
EXTERNAL CORLIM,CORMAX,HIGHJB,JOB
EXTERNAL CAWAIT,MEMSIZ,WSCHED,CPOPJ1,TPOPJ,STOTAC,CAFREE

LOKJOB:
IFN FTVM,<
	TRNN	T1,-1		;LOCK THE LOW SEGMENT?
	JRST	LOKJO0		;NO
	SKIPN	.UPMP+.UPVRT	;YES, A VIRTUAL USER?
	SKIPE	.UPMP+.UPMEM	;NO, LOW SEGMENT NON-CONTIGUOUS?
	JRST	RTZER##		;YES, NOT IMPLEMENTED
LOKJO0:	SKIPLE	T2,JBTSGN##(J)	;JOB HAVE A HIGH SEGMENT?
	TLNE	T2,SHRSEG	;YES, IS IT SHARABLE?
	CAIA			;YES
	JRST	RTZER##		;NO, NOT IMPLEMENTED
>
	PUSHJ	P,SAVE4##	;SAVE P1-P4
IFN FTPRV,<
	MOVSI	T1,PVLOCK	;BIT DENOTING PRIVILEDGES TO LOCK
	PUSHJ	P,PRVBIT##	;IS THIS USER A SUFFICIENT WHEEL?
	  SKIPA			;YES, PROCEED
	JRST	ERROR1		;NO, NOT PRIVILEDGED ERROR RETURN
	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
	MOVSI	P1,NSHF!NSWP	;LOCKED BITS
	MOVE	T2,J		;SAVE JOB NUMBER
	MOVEI	T3,0		;ASSUME NO HIGH SEGMENT ADDRESS
IFN FT2REL,<
	SKIPE	TWOREG		;TWO REGISTER SOFTWARE?
	SKIPG	J,JBTSGN(J)	;GRAB HIGH SEGMENT NUMBER IF ANY
	JRST	LOKJ0A		;NO HIGH SEGMENT
	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,PAGTAB(T3)	;GET STATUS OF LOCKED SEGMENT
	PUSHJ	P,ARGCK1	;OK TO LOCK AGAIN?
	JRST	ERROR7		;NOT OK. ARGUMENT IS INCORRECT
	MOVSI	T4,LOKSEG	;DON'T FORGET TO LOCK THIS JOB'S
	IORM	T4,JBTSGN(T2)	;HIGH SEGMENT
HGHADR:	TLNN	T1,LKEB		;LOCKED IN EVM?
	MOVE	T3,JBTADR(J)	;YES, PROVIDE EVA TO USER
	>
LOKJ0A:	EXCH	J,T2		;J=JOB, T2=HIGH SEGMENT NUMBER
	TRNN	T1,LKB		;LOCK THE LOW SEGMENT?
	JRST	LOKJ00		;NO
	TDNN	P1,JBTSTS(J)	;IS THE LOW SEGMENT ALREADY LOCKED?
	JRST	LOKJ01		;YES
LOKJ00:
IFN FT2REL,<
	SKIPE	TWOREG		;TWO REGISTER SOFTWARE?
	TLNN	T1,LKB		;LOCK THE HIGH SEGMENT?
>
	JRST	ERROR0		;NO, NOTHING TO DO
IFN FT2REL,<
	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
>
LOKJ01:	TLZ	T1,-1-IFN FT2REL,<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
IFN FTSWAP,<
	MOVEI	J,1		;FIND THE LARGEST JOB NOT LOCKED
LOKJ02:	CAMN	J,JOB		;DON'T CONSIDER JOB BEING LOCKED
	JRST	LOKJ04
	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
IFN FT2REL,<
	SKIPE	TWOREG		;TWO REGISTER SOFTWARE?
	SKIPG	J,JBTSGN(J)	;DOES IT HAVE A REAL HIGH SEGMENT?
	JRST	LOKJ03		;NO
	MOVSI	P2,NSWP!NSHF
	MOVE	P1,JOB		;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 ALRERADY LOCKED
	JRST	LOKJ03		;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
>
LOKJ03:	LSH	T2,P2WLSH
	CAMLE	T2,P4		;LARGEST SO FAR?
	MOVE	P4,T2		;YES, SAVE ITS SIZE
	POP	P,J		;RESTORE JOB NUMBER
LOKJ04:	CAMGE	J,HIGHJB	;LOOKED AT ALL JOBS YET?
	AOJA	J,LOKJ02	;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
IFN FT2REL,<
	TLZE	T1,LKB		;HIGH SEGMENT TO BE LOCKED?
	CAILE	J,JOBMAX	;LOW SEGMENT ALREADY LOCKED?
	JRST	LOKJ05		;YES, JUST LOCK THE HIGH SEGMENT
	MOVSI	P2,NSHF!NSWP	;HIGH SEGMENT MAY ALREADY BE LOCKED
	SKIPLE	P1,JBTSGN(J)	;DOES THE JOB HAVE A HIGH SEGMENT?
	TDNE	P2,JBTSTS(P1)	;IS THE HIGH SEGMENT ALREADY LOCKED?
	JRST	LOKJ05		;NEEDN'T BE CONCERNED ABOUT THE HIGH SEGMENT
	HRLI	P1,(J)		;P1_JOB#,,HIGH SEGMENT#
	MOVEM	P1,(P)		;SAVE IT
	HLRZ	P1,JBTADR(P1)	;SIZE OF THE HIGH SEGMENT
	ADDI	T1,1(P1)	;ADD IT TO THE TOTAL
>
LOKJ05:	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
	MOVE	J,.C0JOB	;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
IFN FTKL10,<
	PUSHJ	P,CHKCSH	;CHECK WHETHER THE CACHE SHOULD BE ON OR OFF
>
	CAIG	P1,JOBMAX	;IS THE HIGH SEGMENT TO BE LOCKED?
	JRST	LOKJ06		;NO
	TLCE	T1,LKB+LKEB+LKPB;DOES THE USER WANT IT LOCKED IN PLACE?
	TLNE	T1,LKB+LKEB+LKPB; ..
	JRST	LOKJ06		;NO, SOME OTHER VARITY 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,LOKJ14	;JUMP IF LOW SEGMENT ISN'T TO BE LOCKED
LOKJ06:	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	LOKJ07		;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	LOKJ14		;AND FINISH UP
LOKJ07:	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	LOKJ11		;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	ERRO4A		;COULDN'T MAKE IT, GIVE THE USER AN ERROR RETURN
	CAIG	P1,JOBMAX	;LOCKING A HIGH SEGMENT?
	JRST	LOKJ09		;NO, PROCEED
	HLRZ	T3,T1		;YES, T3 = PHYSICAL PAGE NUMBER OF FIRST PAGE OF
				; THE HIGH SEGMENT
	PUSH	P,T1		;SAVE FIRST PAGE OF HIGH SEGMENT,,FIRST
				; PAGE OF LOW SEGMENT
	PUSHJ	P,GETTAC##	;RESTORE THE USER'S ARGUMMENT
	HRRZ	J,P1		;J = HIGH SEGMENT NUMBER
	TLNE	T1,LKEB		;DOES THE USER ALSO REQUIRE THAT THE HIGH
				; SEGMENT BE CONTIGUOUS IN EVM?
	JRST	LOKJ08		;NO, PROCEED
	PUSHJ	P,LKEVC		;IS THE SEGMENT ALSO CONTIGUOUS IN EVM
				; BY VIRTUE OF BEING BELOW 112K?
	  JRST	[POP 	P,T1	;NO, RESTORE ADDRESSES OF SEGMENTS
		TLZ	T1,-1	;INDICATE HIGH SEGMENT NOT ALREADY LOCKED IN EVM
		JRST	LOKJ09]	;SEE ABOUT THE LOW SEGMENT
LOKJ08:	POP	P,T1		;RESTORE THE ADDRESSES OF THE SEGMENTS
	HLRZS	P1		;P1 = LOW SEGMENT NUMBER OR ZERO IF LOW
				; SEGMENT IS NOT TO BE LOCKED
	JUMPE	P1,LOKJ14	;ALL DONE IF LOW SEGMENT IS NOT TO BE LOCKED
LOKJ09:	HRRZ	T3,T1		;T3 = PHYSICAL PAGE NUMBER OF FIRST PAGE OF
				; THE LOW SEGMENT
	PUSH	P,T1		;SAVE ADDRESSES OF THE SEGMENTS
	PUSHJ	P,GETTAC##	;RESTORE THE USER'S ARGUMENT
	HRRZ	J,P1		;J = LOW SEGMENT NUMBER
	CAILE	P1,JOBMAX	;LOCKING THE HIGH SEGMENT ALSO?
	HLRZ	J,P1		;YES, THEN THE LOW SEGMENT NUMBER IS IN
				; THE LEFT HALF
	TRNE	T1,LKEB		;DOES THE USER REQUIRE THAT THE LOW SEGMENT
				; BE LOCKED IN CONTIGUOUS EVM?
	JRST	LOKJ10		;NO, CONTINUE
	PUSHJ	P,LKEVC		;IS THE LOW SEGMENT ALREADY LOCKED IN
				; CONTIGUOUS EVM BY VIRTUE OF BEING LOCKED
				; IN PHYSICALLY CONTIGUOUS MEMORY BELOW 112K?
	  JRST	[POP	P,T1	;NO, RESTORE SEGMENTS ADDRESSES
		TRZ	T1,-1	;INDICATE THAT THE LOW SEGMENT IS NOT
				; ALREADY CONTIGUOUS IN EVM
		JRST	LOKJ12]	;GO MAKE IT CONTIGUOUS IN EVM
LOKJ10:	POP	P,T1		;YES, RESTORE SEGMENTS ADDRESSES
	TLZN	P1,-1		;IS THERE STILL A HIGH SEGMENT TO WORRY ABOUT?
	JRST	LOKJ14		;NO, FINISH UP
	JRST	LOKJ12		;YES
LOKJ11:	MOVEI	T1,0		;INDICATE THAT NEITHER SEGMENT IS ALREADY
				; LOCKED IN EVM
LOKJ12:	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	LOKJ14		;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	LOKJ13		;GO CHECK THE LOW SEGMENT
	TLNE	P2,LKEB		;LOCK THE HIGH SEGMENT VIRTUALLY CONTIGUOUS?
	JRST	LOKJ13		;NO
	PUSH	P,T1		;SAVE THE ADDRESS OF THE LOW SEGMENT
	HRRZ	J,P1		;J = THE HIGH SEGMENT NUMBER
	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,LOKJ14	;ALL DONE IF NOT LOCKING LOW SEGMENT
LOKJ13:	TRNN	P2,LKEB		;LOCK THE LOW SEGMENT VIRTUALLY CONTIGUOUS?
	TRNE	T1,-1		;YES, IS THE LOW SEGMENT ALREADY LOCKED IN EVM?
	JRST	LOKJ14		;YES, FINISH UP
	PUSH	P,T1		;SAVE THE ADDRESSES OF THE SEGMENTS
	MOVE	J,.C0JOB##	;J = LOW SEGMENT NUMBER
	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
LOKJ14:	AOS	(P)		;SET FOR OK RETURN
LOKJ15:	PUSHJ	P,CAFREE	;RETURN THE LOCK RESOURCE
	PUSHJ	P,STOTAC	;STORE ERROR OR HIGH SEGMENT ADDRESS,,
				; LOW SEGMENT ADDRESS
	PJRST	SETRLH##	;AND REDO THE PAGE MAP
;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
	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:
;	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,PCORSZ	;SIZE OF THE SEGMENT - 1
	ADDI	T1,1		;SIZE OF THE SEGMENT
	PUSH	P,T1		;SAVE THAT
IFN FTVM,<
	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
	MOVEI	T1,400(T1)	;MAKE RELATIVE LOCATION IN THE MAP INTO PAGE NUMBER
	MOVE	T2,(P)		;NUMBER OF PAGES IN THIS SEGMENT
IFN FTVM,<
	CAIG	J,JOBMAX##
	ADDI	T2,UPMPSZ##
>
	ADDM	T2,.C0EVU##	;COUNT EVM IN USE FOR LOCKING
IFE FTVM,<
	MOVEI	T3,0		;T3 = USER VIRTUAL ADDRESS TO START AT
				; WHEN COPYING THE USER'S MAP INTO THE EXEC MAP
	CAIG	J,JOBMAX	;IS THIS A HIGH SEGMENT
	JRST	LOKEV2		;NO
>
IFN FTVM,<
	CAILE	J,JOBMAX##	;LOW SEG?
	JRST	LOKEV1		;NO
	MOVE	T2,T1		;PAGE WHERE UPMP IS TO BE MAPPED
	ROT	T2,-1		;DIVIDE BY 2
	TLZN	T2,400000	;ODD OR EVEN?
	TDOA	T2,[POINT 18,.EPMP##,17]
	TDO	T2,[POINT 18,.EPMP##,35]
	HLRZ	T3,.UPMP+.MUPMP  ;PHYSICAL PAGE 3 OF THE UPMP
	DPB	T3,T2		;MAP THE UPMP IN THE EXEC MAP
IFN FTMS,<
	PUSHJ	P,MAPUC##	;MAP IT IN CPU1'S MAP
>
	MOVEI	T3,0		;STARTING VIRTUAL ADDRESS
	AOJA	T1,LOKEV2	;MAP LOW SEG STARTING AT NEXT PAGE
LOKEV1:>
	MOVE	T3,T1		;SAVE STARTING PAGE IN THE EXEC MAP
	PUSH	P,J		;SAVE HIGH SEGMENT NUMBER
	MOVE	J,.C0JOB##	;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
LOKEV2:	MOVE	T2,(P)		;NUMBER OF PAGES TO MAP IN THE EXEC MAP
IFN FTMS,<
	PUSH	P,T3		;SAVE UVA
>
	PUSHJ	P,MAPUEV##	;COPY THE USER'S MAP INTO THE EXEC MAP
	HRRM	T3,JBTADR(J)	;STORE THE EVA OF THIS SEGMENT
IFN FTMS,<
	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 FTMS,<
	PUSHJ	P,MAPUEC##	;COPY USER'S MAP TO CPU1'S MAP
>
	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
	PJRST	TPOPJ1##	;RESTORE EV PAGE NUMBER AND GIVE SUCCESS RETURN

LOKEXT:	HRRI	M,(T1)		;POINT M AT THE USER'S ARGUMENT LIST
	PUSHJ	P,GETWD1##	;GET THE SECOND WORD OF THE ARGUMENT LIST
IFN FTKL10,<
	PUSHJ	P,GETWDU##	;GET THE USER'S FIRST ARGUMENT
	PUSHJ	P,CHKCSH	;SEE IF CACHE SHOULD BE OFF OR ON
>
;HERE WITH T1= WHERE HIGH SEGMENT IS TO BE LOCKED,,WHERE LOW SEGMENT
; IS TO BE LOCKED, P1= LOW SEGMENT NUMBER,,HIGH SEGMENT NUMBER
LKSPHY:	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	LKSPH1		;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
LKSPH1:	MOVEI	T1,LKERR6	;YES, HIGH AND LOW SEGMENTS WILL OVERLAP
	JRST	LOKJ15		;GIVE ERROR RETURN
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	LOKJ15		;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	LOKJ15		;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,.C0JOB##	;CURRENT JOB NUMBER
	PUSHJ	P,LOCKIT	;LOCK THE SEGMENTS REQUESTED WHERE REQUESTED
	  JFCL			;CAN'T HAPPEN
	JRST	LOKJ14		;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?
	JRST	PHYPF2		;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
PHYPF1:	MOVE	T4,PAGTAB(T3)	;PAGTAB ENTRY REPRESENTING THIS PHYSICAL PAGE
	TLNE	T4,LKBITS+IPCBIT  ;LOCKED OR NON-EXISTANT PAGE?
	JRST	PHYPF2		;YES, LOSE
	SOSE	T2		;LOOKED AT ALL THE PAGES REQUIRED TO LOCK THE SEGMENT?
	AOJA	T3,PHYPF1	;NO, CHECK THE NEXT PHYSICAL PAGE
	AOSA	(P)		;YES, ALL PAGES ARE FREEABLE SO SKIP RETURN
PHYPF2:	MOVEI	T1,LKERR6	;CAN'T LOCK THERE ERROR CODE
	POPJ	P,		;RETURN
;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:	HLRZ	T1,P1		;LOW SEGMENT NUMBER OR ZERO
	HLRZ	T1,JBTADR(T1)	;SIZE OF THE LOW SEGMENT OR ZERO
	SKIPE	T1		;SKIP IF LOW SEGMENT NOT BEING LOCKED
	ADDI	T1,1+UPMSZW##	;ACCOUNT FOR THE UPMP
	HLRZ	T2,JBTADR(P1)	;SIZE OF THE HIGH SEGMENT OR LOW SEGMENT
				; IF HIGH SEGMENT IS NOT BEING LOCKED
	ADDI	T1,1(T2)	;AMOUNT BEING LOCKED
	LSH	T1,W2PLSH	;CONVERT TO NUMBER OF PAGES
	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
LOKPH1:	TDZA	T4,T4		;LARGEST HOLE SEEN SO FAR
LOKPH2:	ADDI	T4,1		;INCREMENT SIZE OF LARGEST HOLE
LOKPH3:	CAIN	T3,(T2)		;LOOKED AT ALL OR CORE?
	JRST	LOKPH4		;YES, SEE IF A BIG ENOUGH HOLE WAS FOUND
	MOVE	S,PAGTAB(T2)	;STATUS OF THIS PAGE
	TLNN	S,LKBITS+IPCBIT  ;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?
	POPJ	P,		;NO, ERROR RETURN
	SUBI	T2,(T4)		;STARTING PAGE NUMBER OF THE HOLE
	HRRZM	T2,LOKREL	;SAVE THAT FOR LOCK
	HLRZ	T1,JBTADR(P1)	;SIZE OF THE FIRST SEGMENT TO BE LOCKED
	ADDI	T1,1		; ..
	LSH	T1,W2PLSH	;CONVERT TO NUMBER OF PAGES
	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 SEGMENT?
	HRLM	T1,LOKREL	;WHERE TO LOCK THE OTHER SEGMENT
LOCKIT:	MOVEM	P1,LOCK		;STORE SEGMENT NUMBERS FOR LOCK
	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
	MOVEI	T2,0		;ASSUME NO HIGH SEGMENT
	SKIPLE	J,JBTSGN(J)	;JOB HAVE A REAL HIGH SEGMENT?
	LDB	T2,JBYHSA	;YES, 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
;

IFN FT2REL,<
INTERNAL UNLOKH
UNLOKH:	MOVE	J,-1-IFN FTSWAP,<1>(P)	;GET JOB NUMBER
	MOVSI	T1,LKB		;UNLOCK THE HIGH SEGMENT
	JRST	UNLO00		;UNLOCK IT IF NOT LOCKED FOR SOME OTHER JOB
>
UNLOCK:	SKIPA	T1,[XWD LKB,LKB];UNLOCK BOTH LOW AND HIGH SEGMENTS
UNLOK.:	AOS	(P)		;HERE FROM UNLOCK UUO. ALWAYS GIVE OK RETURN.
UNLO00:	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
IFN FT2REL,<
	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,<
	EXTERN RTREL
	PUSHJ	P,RTREL		;RESET REAL TIME
>
	PUSHJ	P,FRELOK	;UNLOCK THE LOW SEGMENT
IFN FTKL10,<
	MOVSI	T1,(JS.NCS)	;DON'T CACHE BIT
	ANDCAM	T1,JBTST2##(J)	;TURN THE CACHE ON AGAIN
	MOVE	R,JBTADR##(J)
	PUSHJ	P,MAPLOW##	;TURN ON CACHE BITS IN THE MAP
>
	MOVE	T1,-ZZ(P)	;RESTORE ARGUMENT
	HRROS	-ZZ(P)		;FLAG THAT CORE HAS CHANGED (SO CALL LRGHOL)
IFN FT2REL,<
UNLO01:	TLNE	T1,LKB		;UNLOCK THE HIGH SEGMENT?
	SKIPN	TWOREG		;TWO SEGMENT HARDWARE?
	JRST	UNLO05		;NO
	MOVSI	P2,LOKSEG+IFN FTKL10,<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
IFN FTKL10,<
	PUSHJ	P,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
	MOVE	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:	POP	P,J		;RESTORE JOB NUMBER
	MOVE	R,JBTADR(J)	;AND R
	POP	P,T1		;HAS CORE CHANGED?
	JUMPGE	T1,CPOPJ##	;NO, REMOVE ARGUMENT AND RETURN
COMLIM:
IFN FTSWAP,<
	PUSHJ	P,LRGHOL	;SET EXTENT OF THE LARGEST HOLE
	MOVEM	T2,MAXMAX##	;LARGEST LEGAL 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:
IFN FTMETR,<			;RELEASE ANY METER POINTS EFFECTED
	PUSHJ	P,METREL##
>
	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,PAGTAB(T1)	;IS IT?
	JRST	FRELK4		;NO, PROCEED
	HRRZ	T3,JBTADR(J)	;EVA OF THIS SEGMENT
	LSH	T3,W2PLSH	;CONVERT TO PAGE NUMBER
	PUSHJ	P,LKEVA		;IS THIS SEGMENT LOCKED IN EVM BY VIRTUE
				; OF BEING BELOW 112K?
	  CAIA			;NO
	JRST	FRELK2		;YES, DON'T NEED TO RETURN EVM
	PUSH	P,T1		;SAVE STARTING PAGE NUMBER
	HLRZ	T1,JBTADR(J)	;SIZE OF THIS SEGMENT
	LSH	T1,W2PLSH	; IN PAGES - 1
	ADDI	T1,1		;IN PAGES
	SUBI	T3,400		;CONVERT TO RELATIVE PAGE WITHIN EXEC MAP
IFN FTVM,<
	CAILE	J,JOBMAX##	;A LOW SEGMENT?
	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
	PUSHJ	P,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
	MOVEM	R,.C0ADR##	;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:	SKIPE	R		;GETTING CORE?
	PUSHJ	P,IICLNK##	;YES
	SKIPN	R		;GIVING UP CORE?
	PUSHJ	P,DICLNK##	;YES
	MOVEM	R,JBTADR(J)	;STORE DIDDLED RELOCATION
FRELK4:	MOVSI	T2,LKBITS	;BITS INDICATING A PAGE IS LOCKED
	ANDCAB	T2,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,PAGTAB(T1)	;CLEAR THEM FOR THE UPMP
	POPJ	P,		;AND RETURN
IFN FTMOFFL,<
;SUBROUTINE TO DETERMINE IF A RANGE OF MEMORY OVERLAPS LOCKED JOBS
; AND IF SO, RETURN ALL THE JOBS WHICH OVERLAP THE RANGE
CKLJB::	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
	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::	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::MOVEI	T3,0		;NUMBER OF ON LINE PAGES IN THE RANGE
	MOVSI	T4,NXMBIT	;BIT INDICATING PAGE IS NON-EXISTANT
NEWCM1:	TDNN	T4,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::SKIPE	LOCK##		;LOCKING IN PROGRESS?
	PJRST	DLYCM##		;YES, TRY AGAIN WHEN ITS DONE
	MOVE	T3,LASLOK##	;SETTING MEMORY OFF LINE IN PROGRESS?
	SETZM	LASLOK##	;NOT ANYMORE IN CASE WE WERE
	AOJE	T3,MEMOF3	;JUMP IF A SET MEMORY OFF COMMAND JUST COMPLETED
				; (LASLOK GETS SET TO -1 AT COMPLETION BY CLOCK LEVEL CODE)
	LDB	T3,[POINT 14,MEMSIZ##,26]
	CAIL	T1,(T3)		;TRYING TO SET MEMORY OFF ABOVE THE TOP OFF MEMORY?
	POPJ	P,		;YES, ITS 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
MEMOF1:	MOVE	T4,PAGTAB(T1)	;PAGE DESCRIPTOR BITS
IFN FT2SEGMON,<
	TLNE	T4,MONTRB	;DOES THIS PAGE CONTAIN MONITOR CODE?
	ADDI	T3,1		;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
IFN FT2SEGMON,<
	HRRZM	T3,MOFLPG##	;STORE THE NUMBER OF MONITOR PAGES WHICH MUST BE MOVED
> ;END FT2SEGMON
IFN FTMS&FT2SEGMON,<
	TRNN	T3,-1		;IF NOT MOVING MONITOR PAGES, DON'T NEED CPU1 TO STOP
	JRST	MEMOF2		;GO SET THE PAGES OFF
	PUSHJ	P,CP1STP##	;ASK CPU1 TO JUMP INTO ITS ACS
	  PJRST	DLYCM##		;AND WAIT UNTIL IT DOES
MEMOF2:>
	AOSE	CAREQ##		;CAN'T CALL CAWAIT BECAUSE THAT REQUIRES
				; A CORE IMAGE
	STOPCD	.,STOP,CRW,	;++CA RESOURCE WRONG
	SETOM	LOCK##		;INDICATE SETTING PAGES OFF LINE IS IN PROGRESS
	PJRST	DLYCM##		;AND WAIT UNTIL ITS DONE
MEMOF3:	SOSL	CAREQ##		;MAKE THE LOCK RESOURCE AVAILABLE
	SETOM	CAAVAL##	;AND WAKE UP THE WAITERS FOR IT
IFN FTMS&FT2SEGMON,<
	SETZM	MOFLPG##	;NOT SETTING MONITOR PAGES OFF LINE
>
	TLO	M,CMWRQ##	;GET JOB OUT OF COMMAND WAIT
IFN FTDAEM,<
	MOVE	T1,[11,,.ERCSC]	;MEMORY OFF-LINE INDICATOR
	PUSH	P,J		;SAVE J FOR COMRET
	PUSHJ	P,DAEEIM##	;TELL DAEMON ABOUT THE MEMORY CONFIGURATION CHANGE
	PJRST	JPOPJ##		;RESTORE J AND RETURN TO COMCON
>
IFE FTDAEM,<
	POPJ	P,		;IF NO DAEMON, JUST 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,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:	HRRZ	T3,JBTUPM##(J)	;ADDRESS OF THE JOBS UPMP
	TRO	T3,PM.ACC	;ACCESS ALLOWED
	HRLM	T3,.EPMP##+.MEUPM ;MAKE IT ADDRESSABLE VIA THE EXEC MAP
	CLRPGT	(0,.TEMP)	;CLEAR THE AM SO NEW MAPPING IS IN EFFECT
	LDB	T3,[POINT 13,.EUPMP+.MJDAT,35]
	POPJ	P,		;RETURN THE FIRST PAGE OF THE JOB

> ;END FTMEMOFL
;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,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,PAGTAB(T1)
	LDB	T1,JBYLSA
LOKBT1:	MOVSI	T2,(T3)
	IORB	T2,PAGTAB(T1)
	HRRZ	T1,T2
	JUMPN	T1,LOKBT1
	POPJ	P,

;SUBROUTINE TO DETERMINE IF A SEGMENT IS LOCKED IN EVM BY VIRTURE OF BEING
; BELOW 112K. (PRESERVES T3)

LKEVA:	LDB	T2,PCORSZ
	ADDI	T2,1(T3)
	CAIG	T2,^D224
	AOS	(P)
	POPJ	P,

;SUBROUTINE TO LOCK A SEGMENT IN EVM IF IT IS BELOW 112K. (PRESERVES T1)
LKEVC:	PUSHJ	P,LKEVA
	  POPJ	P,
LKEVS:	LSH	T3,P2WLSH
	HRRM	T3,JBTADR(J)
	PUSH	P,T1
	MOVEI	T3,LOKEVB
	PUSHJ	P,LOKBTS
	PJRST	TPOPJ1##
ERROR0:	LDB	P1,JBYLSA	;LOW SEGMENT PHYSICAL ADDRESS

	TRNN	T1,LKB		;LOCKING LOW SEGMENT?
	JRST	LOWADR		;NO, GET ADDRESS ANYWAY
	MOVE	T4,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?
	MOVE	P1,JBTADR(J)	;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	LOKJ15

ERROR3:	MOVEI	T1,LKERR3
	PJRST	LOKJ15

ERROR4:	POP	P,T1
ERRO4A:	PUSHJ	P,UNLOCK
	PUSHJ	P,COMLIM	;RECOMP CORMAX/MAXMAX
	MOVEI	T1,LKERR4
	PJRST	LOKJ15

;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
IFN FTKL10,<
CHKCSH:	MOVE	J,.C0JOB##
	SKIPG	JBTSGN##(J)
	JRST	CHKCS1
	MOVSI	T2,NCSH
	TLNE	T1,LKB
	TLNE	T1,LKCB
	CAIA
	IORM	T2,JBTSGN##(J)
CHKCS1:	TRNE	T1,LKB
	TRNE	T1,LKCB
	POPJ	P,
	MOVSI	T2,(JS.NCS)
	IORM	T2,JBTST2##(J)
	POPJ	P,
>
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
;
IFN FT2REL,<

	INTERN	LOKHGH

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