Google
 

Trailing-Edge - PDP-10 Archives - bb-bt99m-bb - ctxser.x19
There are no other files named ctxser.x19 in the archive.
TITLE CTXSER - TOPS10 CONTEXT SERVICE - V60
SUBTTL	D. MASTROVITO/DPM/JMF/NT/RCB	27 MAY 86

	SEARCH	F,S

	SALL			;FOR CLEAN LISTINGS
	.DIRECTIVE FLBLST	;FOR CLEANER LISTINGS

	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1981,1986>
;COPYRIGHT (C) 1981,1982,1983,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.

;
;

	XP	VCTXSER,60	;PUT VERSION NUMBER IN STORAGE MAP AND GLOB

CTXSER::ENTRY	CTXSER		;ALWAYS LOAD CTXSER IF LIBRARY SEARCH
REPEAT 0,<

LOOSE ENDS:

CTXSER:
	INVENT INTERLOCK TO PREVENT RACES BETWEEN QUOTA CHECKS AND
	THE ACTUAL SAVE PROCESS.  THIS IS NEEDED TO KEEP THE SYSTEM
	CONTEXT AND SAVED PAGE COUNTERS ACCURATE ON A MULTI-CPU SYSTEM.

	FINISH CODING CX RESOURCE.

ERRCON/CTXSER:
	ADD CTXZAP ROUTINE TO BE CALLED BY ZAPHIM/ZAPHER/ZAPJOB AND FRIENDS

>
SUBTTL	CONTEXT PARAMETERS -- OFFSETS AND MACRO DEFINITIONS


; DEFINE ENTRIES IN CSRTAB
	.CXNUM==0		;;INIT COUNTER
DEFINE	CTX	(NAM,WDS,ARG),<
	IFNDEF .CX'NAM,<.CX'NAM==.CXNUM>
	.CXNUM==.CXNUM+WDS	;;COUNT WORDS SAVED IN CONTEXT BLOCK
	EXP	<ARG>		;;INSTRUCTION TO EXECUTE
> ;END CTX MACRO

;SPECIAL DUPLICATE DEFINITION FOR SPECIAL CHARACTER STATUS BYTES

XP LDBCSL,<CK.CHR/<^D36/CC.WID>>+1 ;NUMBER OF WORDS REQUIRED TO STORE THE BYTES


MAXLVL==:5

DEFINE	CTXSFD	(ARG),<
	ZZ==0
	REPEAT ARG,<
	CTX (SFD,1,EXP <.PDSFD##+ZZ(W)>)
	ZZ==ZZ+1
	> ;;END REPEAT
> ;END CTXSFD MACRO
SUBTTL	CONTEXT PARAMETERS -- TABLE


; THE CTX MACRO DEFINES THE JOB PARAMETERS THAT GET SAVED AND
; RESTORED ON CONTEXT CALLS.  THE SAVE AND RESTORE ROUTINES
; LOOP THROUGH THE TABLE PROCESSING EACH ENTRY.  EACH EACH
; HAS ONE OF THREE FORMATS:
;
;	EXP	ADDR		WHERE ADDR IS AN ADDRESS INCLUDING
;				INDEXING AND INDIRECTION THAT WILL
;				BE SAVED OR RESTORED
;
;	1B0+ADDR		WHERE ADDR IS A SUBROUTINE TO EXECUTE
;
;	1B1+ADDR		WHERE ADDR IS AN ADDRESS INCLUDING
;				INDEXING AND INDIRECTION THAT WILL
;				BE SAVED-AND-ZEROED OR RESTORED

CSRTAB:	CTX (SYS,1,1B0+CSRSYS)		;FROM SYS BIT
	CTX (MON,1,1B0+CSRMON)		;MONITOR MODE BIT, ETC.
	CTX (SCX,1,1B1+.PDSCX##(W))	;SAVCTX WORD (ALSO .PDNET)
		EXTERN	.PDNET
	CTX (BKM,LDBCSL+3,1B0+CSRBKM)	;TTY BREAK MASK
IFN FTPI,<CTX (PIA,1,1B1+JBTPIA##(J))>	;PSI DATA BASE (PIT)
IFN FTIPCF,<CTX (IPC,11,1B0+CSRIPC)>	;IPCF DATA BASE
IFN FTEQDQ,<CTX (ENQ,1,1B0+CSRENQ)>	;ENQ/DEQ QUEUE CHAIN ADDRESS
	CTX (TTY,13,1B0+CSRTTY)		;TTY DDB
	CTX (STS,1,1B0+CSRSTS)		;JOB STATUS
IFE FTFDAE,<CTX (ST2,1,EXP <JBTST2##(J)>)>	;SECOND JOB STATUS WORD
IFN FTFDAE,<CTX (ST2,1,1B0+CSRST2)>	;SECOND JOB STATUS WORD
	CTX (SWP,1,EXP <JBTSWP##(J)>)	;SWAPPED OUT DISK ADDRESS
	CTX (IMI,1,EXP <JBTIMI##(J)>)	;SWAPPED IN IMAGE SIZE
	CTX (IMO,1,EXP <JBTIMO##(J)>)	;SWAPPED OUT IMAGE SIZE
	CTX (SGN,1,EXP <JBTSGN##(J)>)	;HIGH SEGMENT
	CTX (AD2,1,1B0+CSRAD2)		;JBTAD2
	CTX (PDB,1,EXP <JBTPDB##(J)>)	;NUMBER OF FUNNY PAGES
	CTX (CHK,1,EXP <JBTCHK##(J)>)	;SWAPPED OUT CHECKSUM
	CTX (PRG,1,EXP <JBTNAM##(J)>)	;PROGRAM NAME
	CTX (PC,1,EXP <JBTPC##(J)>)	;USER PC
	CTX (DDB,1,EXP <JBTDDB##(J)>)	;I/O WAIT DDB
	CTX (NAM,1,EXP <.PDNAM##(W)>)	;PROGRAM FILE NAME
	CTX (STR,1,EXP <.PDSTR##(W)>)	;PROGRAM STRUCTURE
	CTX (DIR,1,EXP <.PDDIR##(W)>)	;PROGRAM PPN
	CTXSFD	(MAXLVL)		;PROGRAM SFDS
	CTX (STM,1,EXP <.PDSTM##(W)>)	;TIME OF LAST RESET
	CTX (CMN,1,EXP <.PDCMN##(W)>)	;POINTER TO USER DEFINED COMMANDS
	CTX (UNQ,1,EXP <.PDUNQ##(W)>)	;POINTER TO UNQTAB FOR USER COMMANDS
IFN FTDECNET,<CTX (SJB,1,1B1+.PDSJB##(W))> ;DECNET DATA BASE
	CTX (ABS,1,EXP <.PDABS##(W)>)	;ADDRESS BREAK SETTINGS
	CTX (TMI,1,EXP <.PDTMI##(W)>)	;VIRTUAL TIMER TRAP INTERVAL
	CTX (TMC,1,EXP <.PDTMC##(W)>)	;COUNTER FOR ABOVE
	CTX (SPS,1,1B0+CSRSPS)		;SET RUN ONLY CPU7
	CTX (VRT,1,EXP <JBTVIR##(J)>)	;PROGRAM SIZE FOR CONTROL-T
	CTX (SG2,1,EXP <JBTSG2##(J)>)	;SECTION NUMBER FOR HISEG
	CTX (CVL,1,EXP <.PDCVL##(W)>)	;CVPL,,CPPL
	CTX (PVT,1,EXP <.PDVRT##(W)>)	;FAULT RATE
	CTX (LBS,1,1B0+CSRLBS)		;UUO-SET BIGBUF N
IFN FTHPQ,<CTX (RTD,1,1B0+CSRRTD)>	;HPQ AND HIBER SETTINGS
IFE FTHPQ,<CTX (RTD,1,EXP <JBTRTD##(J)>)> ;HIBER SETTINGS
IFN FTSCA,<CTX (SCS,1,EXP <.PDSCS##(W)>)> ;SCS. UUO
IFN FTENET,<CTX (EJB,1,1B1+<.PDEJB##(W)>)> ;ETHNT. UUO DATABASE
IFN FTPATT,<CTX (PAT,1,1B0+CSRPAT)>	;PATCH SPACE (CSRPAT SHOWS HOW TO USE)
CSRLEN==.-CSRTAB			;LENGTH OF TABLE
SUBTTL	CONTEXT BLOCK DEFINITIONS


; OFFSETS INTO THE DATA BLOCK POINTED TO BY .PDSAC(W)
.CTFLG==0			;CONTEXT BLOCK FLAGS
.CTJCH==.CTFLG+1		;OWNER JOB/CONTEXT HANDLE AT CREATION TIME
.CTNXT==.CTJCH+1		;NEXT CONTEXT BLOCK ADDRESS
.CTPRV==.CTNXT+1		;PREVIOUS CONTEXT BLOCK ADDRESS
.CTSUP==.CTPRV+1		;SUPERIOR CONTEXT BLOCK ADDRESS
.CTLAS==.CTSUP+1		;LAST CONTEXT BLOCK ADDRESS CONTAINING ARGS
.CTNEW==.CTLAS+1		;NEW CONTEXT ADDRESS
.CTRET==.CTNEW+1		;CTX. UUO RETURN AC
.CTCBN==.CTRET+1		;CONTXT BLOCK NAME IN SIXBIT
.CTNCN==.CTCBN+1		;NEW CONTEXT NAME
.CTIDL==.CTNCN+1		;UPTIME WHEN CONTEXT WENT IDLE
.CTPRG==.CTIDL+1		;AUTO-SAVE COMMAND PROGRAM NAME
.CTDSP==.CTPRG+1		;AUTO-SAVE COMMAND DISPATCH
.CTDTL==.CTDSP+1		;DATA BLOCK LENGTH(S)
.CTDTU==.CTDTL+1		;DATA BLOCK ADDRESS IN USER CORE
.CTDTE==.CTDTU+1		;DATA BLOCK ADDRESS IN EXEC CORE
.CTDTT==.CTDTE+1		;DATA BLOCK ADDRESS IN EXEC CORE (TEMPORARY)
.CTTCR==.CTDTT+1		;TMPCOR FILE LENGTH,,NAME
.CTTCA==.CTTCR+1		;TMPCOR FILE ADDRESS (USER)
.CTTCE==.CTTCA+1		;TMPCOR FILE ADDRESS (EXEC)
.CTRUA==.CTTCE+1		;RUN UUO AC (OFFSET,,SECTION #)
.CTRUB==.CTRUA+1		;RUN UUO BLOCK
.CTPUB==.CTRUB+6		;PATH UUO BLOCK (MUST BE ADJACENT TO .CTRUB)
.CTBPR==.CTPUB+2+MAXLVL+1	;BEGINING OF SAVED PARAMETER AREA
.CTEPR==.CTBPR+.CXNUM-1		;END OF SAVED PARAMETER AREA
.CTSIZ==.CTEPR+1		;LENGTH OF SAVED CONTEXT BLOCK
XP .CT4LN,<<.CTSIZ+3>&<-4>>	;LENGTH ROUNDED UP TO A 4-WORD BOUNDARY

; FLAGS AND FIELDS USED FOR CONTEXT CREATION AND BY THE SCHEDULER (.PDCTX).
; THE CONTEXT NUMBER FOR MIGRATION CONTROL OCCUPIES THE RIGHT-MOST BITS
; IN .PDCTX AND IS ONLY REFERENCED BY THE BYTE POINTER "PCTXMF".
CT.SCD==1B0			;CALL FROM SCHEDULER TO SAVE CONTEXT
CT.ATO==1B1			;AUTO-SAVE DONE
CT.TOP==1B2			;CREATE A NEW TOP LEVEL CONTEXT
CT.SWT==1B3			;SWITCH TO AN EXISTING CONTEXT
CT.HLT==1B5			;SAVE CONTEXT AND HALT JOB
CT.UUO==1B6			;SAVE CONTEXT VIA UUO
CT.PRN==1B7			;PHYSICAL DEVICE SEARCH ON RUN UUO

CT.LGO==1B18			;LOGGING OUT
CT.MTJ==1B19			;MIGRATING THIS JOB

; FLAGS AND FIELDS RETAINED FOR EACH CONTEXT (.CTFLG).  THE CONTEXT
; NUMBER OCCUPIES THE RIGHT-MOST BITS AND IS ONLY REFERENCED BY THE
; BYTE POINTER "PCTXNO".
CT.INF==1B9			;CONTEXT HAS AT LEAST ONE INFERIOR
CT.UUE==1B10			;UUO ERROR HAS OCCURRED
CT.DEL==1B11			;DELETE A CONTEXT
CT.CON==1B12			;CONTINUE PREVIOUS CONTEXT
CT.UAC==17B17			;UUO AC
SUBTTL	BYTE POINTERS


PCTXMF:	<Z .PDCTX##(W)>+CTXCBP## ;MIGRATE'S FIRST CONTEXT NUMBER

PCTXPQ:	<Z .PDCTQ##(W)>+CTXPBP## ;PAGE QUOTA
PCTXCQ:	<Z .PDCTQ##(W)>+CTXCBP## ;CONTEXT QUOTA
PCTXPU:	<Z .PDCTU##(W)>+CTXPBP## ;PAGES IN USE
PCTXCU:	<Z .PDCTU##(W)>+CTXCBP## ;CONTEXTS IN USE

PCTXUA:	POINT  4,.CTFLG(P1),17	;UUO AC
PCTXNO:	<Z .CTFLG(P1)>+CTXCBP## ;CONTEX NUMBER IN A CONTEXT BLOCK

PCTXDW:	POINT  9,T1,26		;RETURNED DATA BLOCK LENGTH
PCTXEC:	POINT  9,T1,35		;RETURNED ERROR CODE
SUBTTL	DATA BASE INTERLOCK MACROS


; MACRO TO INTERLOCK REFERENCES TO THE CTXSER DATA BASE

DEFINE	CTXLOK,<
IFN FTMP,<PUSHJ	P,LOKCTX>
>


DEFINE	CTXNLK,<
IFN FTMP,<PUSHJ	P,NLKCTX>
>
SUBTTL	ENTRY POINTS -- CTXINI - INITIALIZE


; CALLED FROM SYSINI TO SET SYSTEM QUOTAS BASED ON VIRTAL
; CALL:	PUSHJ	P,CTXINI

CTXINI::MOVEI	T1,JOBMAX##	;GET MAXIMUM NUMBER OF JOBS
	IMUL	T1,JOBCCQ	;TIMES THE NUMBER OF CONTEXTS PER JOB
	MOVEM	T1,SYSCCQ	;SAVE
	MOVEI	T1,JOBMAX##	;GET JOBMAX AGAIN
	IMUL	T1,JOBCPQ	;TIMES THE NUMBER OF PAGES PER JOB
	CAMLE	T1,VIRTAL##	;CAN THE SWAPPER HANDLE THIS MUCH?
	MOVE	T1,VIRTAL##	;NO
	MOVEM	T1,SYSCPQ	;SAVE
	POPJ	P,		;RETURN
SUBTTL	ENTRY POINTS -- CTXBLK - CREATE CONTEXT BLOCK FOR A NEW JOB


CTXBLK::JUMPE	J,CPOPJ1##	;NO-OP FOR THE NULL JOB
	SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,CREBLK	;CREATE A CONTEXT BLOCK
	  POPJ	P,		;NOT ENOUGH CORE
	MOVEI	T1,1		;START WITH CONTEXT NUMBER ONE
	DPB	T1,PCTXCU	;SET IT
	AOS	SYSCCU		;COUNT UP SYSTEM-WIDE CONTEXTS IN USE
	PUSHJ	P,FREECT	;FIND AND ASSIGN A FREE CONTEXT NUMBER
	SKIPN	T1,JOBCCQ	;GET DEFAULT CONTEXT QUOTA
	MOVEI	T1,CTXMAX##	;MAKE IT ABSOLUTE MAXIMUM
	DPB	T1,PCTXCQ	;SET IT
	MOVE	T1,JOBCPQ	;GET DEFAULT SAVED PAGE QUOTA
	DPB	T1,PCTXPQ	;SET IT
	JRST	CPOPJ1##	;DONE
SUBTTL	ENTRY POINTS -- CTXPRT - CONTROL-T TYPEOUT


CTXPRT::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE1##	;SAVE P1
	MOVEI	T1,[ASCIZ | Ctx:|]
	PUSHJ	P,CONMES##	;TYPE TEXT
	SKIPN	P1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT BLOCK
	TDZA	T1,T1		;JOB BEING KILLED
	LDB	T1,PCTXNO	;GET CONTEXT NUMBER
	PJRST	PRTDIG##	;TYPE IT AND RETURN
SUBTTL	ENTRY POINTS -- CTXKIL - ARBITRARILY DELETE CONTEXT BLOCKS


CTXKIL::SE1ENT			;ENTER SECTION 1
	LDB	T1,PCTXCU	;GET NUMBER OF CONTEXTS IN USE
	JUMPE	T1,CPOPJ##	;RETURN IF NONE
	PUSHJ	P,RELINK	;RELINK ALL BLOCKS
	  POPJ	P,		;NONE LEFT??

KILL1:	PUSHJ	P,DELBLK	;DELETE A BLOCK
	PUSHJ	P,DNCTXN	;DECREMENT CONTEXT USE COUNT
	SKIPE	.PDCTC##(W)	;HAVE A NEW "CURRENT" CONTEXT BLOCK?
	JRST	KILL1		;YES
	POPJ	P,		;ALL DONE
SUBTTL	ENTRY POINTS -- CTXLGO - DELETE CONTEXTS WHEN KILLING A JOB


CTXLGO::SE1ENT			;ENTER SECTION 1
	LDB	T1,PCTXCU	;GET NUMBER OF CONTEXTS IN USE
	JUMPE	T1,CPOPJ##	;ALREADY BEEN THROUGH HERE ONCE
	SOJE	T1,LOGOU1	;GO DELETE THE BLOCK AND RETURN IF ONLY ONE
	PUSHJ	P,RELINK	;RELINK ALL BLOCKS
	  POPJ	P,		;NO CONTEXT BLOCKS??
	PUSHJ	P,SWTCTX	;SWITCH TO THE MOST INFERIOR CONTEXT
	  JFCL			;CAN'T FAIL

LOGOU1:	PUSHJ	P,DELBLK	;FINALLY DELETE THE CURRENT CONTEXT BLOCK
	PJRST	DNCTXN		;COUNT DOWN CONTEXT USE COUNT AND RETURN
SUBTTL	ENTRY POINTS -- CTXNUM/CTXJCH - RETURN CURRENT CONTEXT NUMBER


; RETURN THE CURRENT CONTEXT NUMBER IN T1
; CALL:	MOVE	T1, JOB NUMBER
;	PUSHJ	P,CTXNUM
;	  <ERROR>	;ILLEGAL JOB NUMBER
;	<SKIP>		;OK, CTX/JCH IN T1

CTXJCJ::SKIPA	T1,J		;CTXJCH FOR CURRENT JOB
CTXNUM::TLOA	T2,-1		;FLAG CTX ENTRY
CTXJCH::TLZ	T2,-1		;FLAG JCH ENTRY POINT
	JUMPLE	T1,CPOPJ##	;CAN'T BE NEGATIVE OR ZERO
	CAILE	T1,JOBMAX##	;RANGE CHECK
	POPJ	P,		;LOSE
	HRR	T2,T1		;COPY ARGUMENT
	PUSHJ	P,FPDBT1##	;FIND THE PDB
	  JRST	[HRRZ	T1,T2	;NO SUCH JOB--LEAVE T1 UNCHANGED
		 POPJ	P,]	;RETURN
	SE1ENT			;ENTER SECTION 1
	SKIPN	.PDSAC##(T1)	;HAVE A CONTEXT BLOCK CHAIN?
	POPJ	P,		;NO, LOSE
	PUSH	P,P1		;SAVE P1
	MOVE	P1,.PDCTC##(T1)	;POINT TO CURRENT CONTEXT BLOCK
	LDB	T1,PCTXNO	;GET ITS CONTEXT NUMBER
	POP	P,P1		;RESTORE
	JUMPL	T2,CPOPJ1##	;RETURN IF ONLY CONTEXT NUMBER REQUESTED
	LSH	T1,CTXLSH##	;ELSE POSITION
	IOR	T1,T2		;INCLUDE JOB NUMBER
	JRST	CPOPJ1##	;AND RETURN


; VALIDATE A JOB/CONTEXT HANDLE
; CALL:	MOVE	T1, JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXVAL
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT
;	 <SKIP 1>		;JCH IS FOR CURRENT CONTEXT OF JOB
;	<SKIP 2>		;JCH OK BUT NOT CURRENT

CTXVAL::SE1ENT			;ENTER SECTION 1
	PUSH	P,P1		;SAVE P1 FOR CALLERS
	PUSHJ	P,JBCHCT	;CHECK OUT JCH
	  JRST	P1POPJ##	;NONESUCH
	  CAIA			;SKIP ONCE
	AOS	-1(P)		;SKIP TWICE
	AOS	-1(P)		;OR ONCE
	JRST	P1POPJ##	;NOW RESTORE AND RETURN
SUBTTL	ENTRY POINTS -- CTXPSI - RETURN PIT FOR ANY CONTEXT


; RETURN THE PIT FOR A GIVEN JOB/CONTEXT HANDLE
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXPSI
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT
;	<SKIP>			;T1 = JOB/CONTEXT HANDLE NUMBER
;				;T2 = ADDRESS OF PIT

IFN FTPI,<
CTXPSI::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,JBCHCT	;FIND THE CONTEXT BLOCK
	  POPJ	P,		;NO SUCH JOB OR CONTEXT
	  JRST	PSICUR		;FOUND CURRENT CONTEXT FOR A JOB
	MOVE	T2,.CTBPR+.CXPIA(P1) ;GET JBTPIA
	JRST	CPOPJ1##	;RETURN

PSICUR:	MOVE	T2,T1		;COPY JCH
	ANDI	T2,JOBMSK##	;ONLY WANT JOB NUMBER
	MOVE	T2,JBTPIA##(T2)	;GET PIT
	JRST	CPOPJ1##	;RETURN
> ;END FTPI
SUBTTL	ENTRY POINTS -- CTXIPC - RETURN IPCF DATA


; RETURN IPCF DATA FOR A GIVEN JOB/CONTEXT HANDLE
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXIPC
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT
;	<SKIP>			;J = JOB/CONTEXT HANDLE NUMBER
;				;W = ADDRESS OF IPCF DATA BLOCK

IFN FTIPCF,<
CTXIPC::TRNN	T1,JOBMSK##	;ANY JOB #?
	JRST	IPCCUR		;NO, JUST NUL JOB THEN
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,JBCHCT	;FIND THE CONTEXT BLOCK
	  POPJ	P,		;NO SUCH JOB OR CONTEXT
	  JRST	IPCCUR		;FOUND THE CURRENT ONE
	MOVE	J,T1		;COPY UPDATED JOB/CONTEXT HANDLE
	XMOVEI	W,.CTBPR+.CXIPC(P1) ;POINT TO DATA BLOCK
	JRST	CPOPJ1##	;RETURN

IPCCUR:	MOVE	J,T1		;COPY JCH
	ANDI	T1,JOBMSK##	;KEEP ONLY JOB NUMBER
	HRRZ	T1,JBTPDB##(T1)	;POINT TO PDB
	MOVEI	W,.PDIPC##(T1)	;POINT TO START OF IPCF DATA BLOCK
	JRST	CPOPJ1##	;AND RETURN
> ;END IFN FTIPCF
SUBTTL	ENTRY POINTS -- CTXENQ - RETURN .PDEQJ FOR ANY CONTEXT


; RETURN THE START OF THE QUEUE CHAIN FOR A GIVEN JOB/CONTEXT HANDLE
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXENQ
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT
;	<SKIP>			;T1 = JOB/CONTEXT HANDLE NUMBER
;				;T2 = C(.PDEQJ)

IFN FTEQDQ,<
CTXENQ::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,JBCHCT	;FIND THE CONTEXT BLOCK
	  POPJ	P,		;NO SUCH JOB OR CONTEXT
	  SKIPA	T2,.PDEQJ##(W)	;GET .PDEQJ FOR CURRENT CONTEXT
	MOVE	T2,.CTBPR+.CXENQ(P1) ;GET .PDEQJ
	JRST	CPOPJ1##	;RETURN
> ;END IFN FTEQDQ
SUBTTL	ENTRY POINTS -- CTXJPK - JOBPEK UUO SUPPORT


; RETURN JBTSWP FOR A GIVEN JOB/CONTEXT HANDLE
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXJPK
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT
;	<SKIP>			;T1 = JOB/CONTEXT HANDLE NUMBER
;				;T2 = C(JBTSWP)

CTXJPK::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,JBCHCT	;FIND THE CONTEXT BLOCK
	  POPJ	P,		;NO SUCH JOB OR CONTEXT
	  JRST	JPKCUR		;FOUND CURRENT CONTEXT FOR A JOB
	MOVE	T2,.CTBPR+.CXSWP(P1) ;GET JBTSWP
	JRST	CPOPJ1##	;RETURN

JPKCUR:	MOVE	T2,T1		;COPY JCH
	ANDI	T2,JOBMSK##	;ONLY WANT JOB NUMBER
	MOVE	T2,JBTSWP##(T2)	;GET DISK ADDRESS
	JRST	CPOPJ1##	;RETURN
SUBTTL	ENTRY POINTS -- CTXSGN - JOBPEK UUO SUPPORT


; RETURN JBTSGN & .JBYSG2 FOR A GIVEN JOB/CONTEXT HANDLE
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXSGN
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT
;	<SKIP>			;T1 = JBYSG2 VALUE
;				;T2 = JBTSGN ENTRY

CTXSGN::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,JBCHCT	;FIND THE CONTEXT BLOCK
	  POPJ	P,		;NO SUCH JOB OR CONTEXT
	  JRST	SGNCUR		;FOUND CURRENT CONTEXT FOR A JOB
	MOVE	T2,.CTBPR+.CXSGN(P1) ;GET JBTSGN
	LDB	T1,[PSG2LH##+.CTBPR+.CXSG2(P1)] ;GET JBYSG2
	JRST	CPOPJ1##	;RETURN

SGNCUR:	ANDI	T1,JOBMSK##	;WANT ONLY JOB NUMBER FROM JCH
	MOVE	T2,JBTSGN##(T1)	;GET JBTSGN
	LDB	T1,[PSG2LH##+JBTSG2##(T1)] ;GET JBYSG2
	JRST	CPOPJ1##	;RETURN
SUBTTL	ENTRY POINTS -- CTXSTS - GET STATUS OF ANY CONTEXT

; GET THE STATUS INFORMATION FOR A GIVEN JOB/CONTEXT HANDLE
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXSTS
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT
;	<SKIP>			;STATUS RETRIEVED IN T1 & T2
;
; RETURNS:
;	T1/ JBTSTS ENTRY FOR GIVEN JOB/CONTEXT HANDLE
;	T2/ JBTST2 ENTRY CORRESPONDING

CTXSTS::SE1ENT			;DO IN RIGHT SECTION
	PUSHJ	P,SAVE1##	;PRESERVE FOR OUR CALLER
	PUSHJ	P,JBCHCT	;GET CONTEXT BLOCK
	  POPJ	P,		;PROPAGATE FAILURE
	  JRST	STSCUR		;CURRENT JCH
	HRRZ	T1,.CTBPR+.CXSCX(P1) ;POINT TO SAVCTX BLOCK
	SKIPE	T1		;IF THERE,
	SKIPA	T1,2(T1)	;GET ITS SAVED JBTSTS
	MOVE	T1,.CTBPR+.CXSTS(P1) ;ELSE USE OURS
	MOVE	T2,.CTBPR+.CXST2(P1) ;GET OUR SAVED JBTST2
	JRST	CPOPJ1##	;RETURN GOODNESS

STSCUR:	ANDI	T1,JOBMSK##	;ONLY NEED THE JOB NUMBER
	MOVE	T2,JBTST2##(T1)	;GET JBTST2
	MOVE	T1,JBTSTS##(T1)	;AND JBTSTS
	JRST	CPOPJ1##	;RETURN AS ADVERTISED
SUBTTL	ENTRY POINTS -- CTXEWK - EWAKE ANY CONTEXT

; BREAK ANY CONTEXT OUT OF EVENT WAIT FOR A GIVEN JOB/CONTEXT HANDLE
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXEWK
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT
;	<SKIP>			;JOB/CONTEXT CLEARED FROM EVENT WAIT

CTXEWK::SE1ENT			;DO THIS IN CORRECT SECTION
	PUSHJ	P,SAVE1##	;FOR OUR CALLER
	PUSHJ	P,JBCHCT	;FIND CONTEXT BLOCK
	  POPJ	P,		;NOT THERE
	  JRST	EWKCUR		;CURRENT CONTEXT
	MOVEI	T1,EWAKEB	;WAKE UP PENDING
	IORM	T1,.CTBPR+.CXST2(P1) ;LIGHT THE MAGIC BIT
	JRST	CPOPJ1##	;AND RETURN GOODNESS

EWKCUR:	AOS	(P)		;GOING TO SKIP-RETURN
	ANDI	T1,JOBMSK##	;FOR EWAKE
	PJRST	EWAKE##		;WAKE JOB AND RETURN
SUBTTL	ENTRY POINTS -- CTXWAK - WAKE UP ANY CONTEXT


; WAKE UP ANY CONTEXT FOR A GIVEN JOB/CONTEXT HANDLE
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXWAK
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT
;	<SKIP>			;JOB/CONTEXT WOKEN UP

CTXWAK::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,JBCHCT	;FIND THE CONTEXT BLOCK
	  POPJ	P,		;NO SUCH JOB OR CONTEXT
	  JRST	WAKCUR		;CONTEXT IS CURRENT CONTEXT
	XMOVEI	T2,.CTBPR+.CXSTS(P1)	;POINT TO WHERE WE STORE JBTSTS
	HRRZ	T1,.CTBPR+.CXSCX(P1)	;GET SAVCTX BLOCK
	SKIPE	T1		;IF THERE IS ONE,
	XMOVEI	T2,2(T1)	;POINT TO WHERE SAVCTX SAVED JBTSTS
	SYSPIF			;GUARD AGAINST HIGHER PI ACTIVITY
	LDB	T1,[POINT JWSIZ,(T2),JWPOS]	;GET CURRENT QUEUE CODE
	CAIN	T1,SLPQ##	;IS THE JOB IN THE SLEEP QUEUE
	JRST	WAKSLP		;YES, THEN WAKE THE JOB UP
	CAIN	T1,NAPQ##	;NOT SLEEP, IS IT A NAP?
	JRST	WAKNAP		;YES, CLEAR WAIT STATE
	MOVSI	T1,WAKEB##	;NO, SET WAKEUP BIT INSTEAD
	IORM	T1,.CTBPR+.CXRTD(P1)	;SET WAKE UP BIT
	JRST	WAKDON		;RETURN
WAKSLP:
IFN FTPSCD,<
	AOS	REQWK##		;COUNT A WAKE
>
WAKNAP:	MOVEI	T1,RNQ##	;PREPARE TO PUT JOB IN THE RUN QUEUE
	DPB	T1,[POINT JWSIZ,(T2),JWPOS]	;PUT THE JOB IN THE RUN QUEUE
WAKDON:	SYSPIN			;TURN THE PI BACK ON
	JRST	CPOPJ1##	;GIVE SKIP RETURN

WAKCUR:	ANDI	T1,JOBMSK##	;GET JUST THE JOB NUMBER
	AOS	(P)		;GIVE GOOD RETURN
	S0JRST	WAKJOB##	;WAKE UP THE JOB THE OLD WAY
SUBTTL	ENTRY POINTS -- CTXWKJ - FINISH SLEEP/HIBER FOR ANY CONTEXT


; WAKE UP ANY CONTEXT FOR A GIVEN JOB/CONTEXT HANDLE AFTER SLEEP TIME EXPIRES
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,CTXWKJ
;	  <NON-SKIP>		;ALWAYS
; CLOBBERS P1
; CALLED ONLY BY SLEEP AND HIBER UUO TIMER EXPIRATIONS

CTXWKJ::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,JBCHCT	;FIND THE CONTEXT BLOCK
	  POPJ	P,		;NO SUCH JOB OR CONTEXT
	  JRST	WKJCUR		;CURRENT CONTEXT
	XMOVEI	T2,.CTBPR+.CXSTS(P1)	;POINT TO WHERE WE STORE JBTSTS
	HRRZ	T1,.CTBPR+.CXSCX(P1)	;GET SAVCTX BLOCK
	SKIPE	T1		;IF THERE IS ONE,
	XMOVEI	T2,2(T1)	;POINT TO WHERE SAVCTX SAVED JBTSTS
	MOVEI	T1,CLKR##	;GET CLOCK-REQUEST BIT
	ANDCAM	T1,(T2)		;CLEAR IT FOR NEXT SLEEP/HIBER DONE
	LDB	T1,[POINT JWSIZ,(T2),JWPOS]	;GET JBTSTS VALUE OF IDLE CONTEXT
	CAIE	T1,SLPQ##	;IS IT ASLEEP?
	CAIN	T1,NAPQ##	;OR NAPPING?
	TRNA			;YES, SKIP ON
	POPJ	P,		;NO, FORGET IT
IFN FTPSCD,<
	CAIN	T1,SLPQ##	;WAS IT SLEEP?
	AOS	REQSS##		;YES, COUNT UP A SLEEP SATISFIED
>
	MOVEI	T1,RNQ##	;YES, GET RUN QUEUE
	DPB	T1,[POINT JWSIZ,(T2),JWPOS] ;MAKE IT RUNNABLE WHEN NEXT CURRENT
	POPJ	P,		;RETURN TO CLOCK1

WKJCUR:	ANDI	T1,JOBMSK##	;KEEP ONLY JOB NUMBER PORTION
	S0JRST	WAKEJ##		;WAKE UP CURRENT CONTEXT THE OLD WAY
SUBTTL	ENTRY POINTS -- CTXMIG/CTXMGN - RETURN DATA FOR MIGRATION


; RETURN DATA FOR MIGRATION
; CALL: MOVE	J,JOB NUMBER
;	PUSHJ	P,CTXMIG
;	  <NON-SKIP>		;NO IDLE CONTEXTS TO MIGRATE
;	<SKIP>			;THERE ARE IDLE CONTEXTS FOR THIS JOB

CTXMIG::PUSHJ	P,FNDPDB##	;GET THE PDB
	  POPJ	P,		;NO CONTEXTS IF NO PDB
	MOVEI	T1,CT.MTJ	;MIGRATING THIS JOB BIT
	TDNE	T1,.PDCTX##(W)	;TRYING TO RE-START THIS MIGRATION?
	STOPCD	.,STOP,CTXMCT,	;++CTXMIG CALLED TWICE
	LDB	T2,PCTXCU	;GET NUMBER OF CONTEXTS IN USE
	SOJLE	T2,CPOPJ##	;NONE IDLE IF 1 OR 0
	PUSHJ	P,SAVE1##	;PRESERVE P1
	SKIPN	P1,.PDCTC##(W)	;GET CURRENT POINTER
	POPJ	P,		;NONE IDLE IF NO CURRENT
	IORM	T1,.PDCTX##(W)	;LIGHT MIGRATION BIT
	SE1ENT			;ENTER SECTION 1
	LDB	T1,PCTXNO	;GET CONTEXT NUMBER OF CURRENT CONTEXT
	DPB	T1,PCTXMF	;STORE AS START OF MIGRATE CHAIN
	JRST	CPOPJ1##	;GIVE IDLE CONTEXTS EXISTENCE RETURN

; ROUTINE TO ADVANCE TO NEXT CONTEXT FOR MIGRATE
; CALL:	MOVE	J,JOB NUMBER
;	PUSHJ	P,CTXMGN
;	  <NON-SKIP>		;NO MORE CONTEXTS TO MIGRATE (RESET TO INITIAL)
;	<SKIP>			;SWITCHED TO NEXT CONTEXT IN JOB
;
; IT IS THE CALLER'S RESPONSIBILITY TO ENSURE THAT THE JOB IS SWAPPED OUT
; BEFORE CALLING US.

CTXMGN::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,FNDPDS##	;GET THE PDB FOR THE JOB
	MOVEI	T1,CT.MTJ	;MIGRATE THIS JOB BIT
	TDNN	T1,.PDCTX##(W)	;CHECK
	STOPCD	.,STOP,CTXNIP,	;++CTX MIGRATION NOT IN PROGRESS
	PUSHJ	P,SAVE1##	;SAVE OUR FAVORITE REGISTER
	MOVE	P1,.PDCTC##(W)	;GET CURRENT POINTER
	MOVSI	T1,RUN		;THE 'RUNNABLE' BIT
	LDB	T2,PCTXMF	;NUMBER OF CONTEXT DONE BY MIGRATE
	LDB	T3,PCTXNO	;NUMBER OF CURRENT CONTEXT
	CAME	T2,T3		;FIRST CALL TO CTXMGN?
	IORM	T1,JBTSTS##(J)	;NO, RESTORE RUN BIT (VALUE UNKNOWN FOR FIRST)
	PUSHJ	P,SAVECT	;SAVE THE TABLES FOR THIS CONTEXT
	MOVE	P1,.PDCTC##(W)	;RESTORE CURRENT POINTER (CLOBBERED BY SAVECT)
	LDB	T4,PCTXMF	;RETRIEVE NUMBER OF MIGRATE'S FIRST CONTEXT
	LDB	T1,PCTXNO	;GET NUMBER OF CURRENT CONTEXT
	CAIE	T1,(T4)		;SAME AS START?
	SKIPA	P1,.CTNXT(P1)	;NO, ADVANCE POINTER
	MOVE	P1,.PDSAC##(W)	;YES, GO FROM START OF CHAIN
	JUMPE	P1,CTXMG1	;DONE IF END OF CHAIN
	LDB	T1,PCTXNO	;GET CONTEXT NUMBER
	CAIN	T1,(T4)		;THE ONE MIGRATE ALREADY DID?
	MOVE	P1,.CTNXT(P1)	;YES, ADVANCE PAST IT
	JUMPE	P1,CTXMG1	;CHECK END AGAIN
	MOVEM	P1,.PDCTC##(W)	;MAKE IT CURRENT
	PUSHJ	P,RESTCT	;RESTORE ALL THE TABLES FOR MIGRATE TO LOOK AT
	MOVSI	T1,RUN		;THE 'RUNNABLE' BIT
	ANDCAM	T1,JBTSTS##(J)	;CLEAR IT TO BE SURE THERE'S NO MISTAKE
	JRST	CPOPJ1##	;TELL IT WE DID GOOD

CTXMG1:	LDB	T1,PCTXMF	;GET NUMBER OF FIRST MIGRATION CONTEXT
	PUSHJ	P,FINDCT	;POINT TO ITS BLOCK
	  STOPCD .,STOP,CTXFWA,	;++CTXMIG'S FIRST CONTEXT WENT AWAY
	MOVEM	P1,.PDCTC##(W)	;MAKE IT CURRENT
	MOVEI	T1,CT.MTJ	;BIT TO CLEAR
	ANDCAM	T1,.PDCTX##(W)	;CLEAR IT
	DPB	T1,PCTXMF	;AND THE STARTING POINT
	PJRST	RESTCT		;RESTORE OUR TABLES AND GIVE DONE RETURN
SUBTTL	ENTRY POINTS -- CTXCMD - CONTEXT COMMAND


; CONTEXT COMMAND SYNTAX:
;
; .CONTEXT			;LISTS THE STATUS FOR ALL CONTEXTS
; .CONTEXT <NAME>=<NUMBER>	;NAMES A CONTEXT
; .CONTEXT <HANDLE>		;SWITCHED TO CONTEXT "HANDLE"
; .CONTEXT <HANDLE>=		;KEEP THE CURRRENT CONTEXT AND SPAWN ANOTHER
; .CONTEXT <HANDLE>/KILL	;DELETE THE SPECIFIED CONTEXT
; .CONTEXT <HANDLE>/LIST	;LIST THE STATUS FOR THE SPECIFIED CONTEXT
;
; WHERE <HANDLE> CAN BE EITHER A NAME, NUMBER, OR "."

CTXCMD::SE1ENT			;ENTER SECTION 1
	MOVSI	T1,(CT.UUO)	;FLAG TO CLEAR
	ANDCAM	T1,.PDCTX##(W)	;NOT DOING A UUO (FOR ERRXIT)
	PUSHJ	P,RDNAME	;GET CONTEXT NAME OR NUMBER
	  JRST	COMERA##	;COMPLAIN
	SKIPN	P1,T1		;SAVE CONTEXT BLOCK ADDRESS
	JRST	LISTER		;NONE GIVEN--LIST THEM ALL
	MOVE	P2,T2		;GET NAME OR NUMBER
	PUSHJ	P,SKIPS1##	;EAT LEADING TABS AND SPACES
	  JRST	CMD2		;EOL--SWITCH TO SPECIFIED CONTEXT
	CAIE	T3,"="		;NAME=NUMBER?
	JRST	CMD1		;NO--MAYBE A KEYWORD
	PUSHJ	P,SKIPS##	;EAT THE EQUALS SIGN
	  JRST	CMD3		;USER WANTS A NEW CONTEXT
	TLNN	P2,-1		;MUST BE A NAME, NOT A NUMBER
	SKIPN	P2		;A BLANK NAME IS OK TOO
	SKIPA			;NAME IS VALID
	JRST	CMDER2		;NUMERIC NAMES DON'T MAKE IT
	PUSHJ	P,RDNAME	;TRY TO GET ANOTHER
	  JRST	CMDER4		;BAD COMMAND--NEED NAME OR NUMBER
	JUMPL	T1,CMDER3	;NO SUCH CONTEXT
	JUMPE	T1,CMDER4	;NEED A NAME OR NUMBER TO SET NEW NAME
	MOVE	P1,T1		;SET CONTEXT BLOCK ADDRESS
	MOVE	T1,P2		;GET NEW NAME
	PUSHJ	P,NAMECT	;ASSIGN THE NAME
	TLZ	M,NOPER##+NOCRLF## ;TERMINATE LIKE ANY NORMAL COMMAND
	POPJ	P,		;RETURN

CMD1:	CAIE	T3,"/"		;WE EXPECT A SWITCH AT THIS POINT
	JRST	COMERA##	;CONFUSED USER
	PUSHJ	P,CTEXT##	;GET A KEYWORD
	JUMPE	T2,COMERA##	;CONFUSED USER
	MOVE	T1,[-KEYSIZ,,KEYTAB] ;POINT TO TABLE
	PUSHJ	P,FNDNAM##	;AND SEARCH IT
	  JRST	COMERA##	;AMBIGUOUS OR UNKNOWN KEYWORD
	JRST	@KEYDSP(T1)	;DISPATCH

CMD2:	JUMPL	P1,CMDER1	;CONTEXT MUST BE KNOWN
	MOVE	T1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT
	MOVEM	P1,.CTNEW(T1)	;SET NEW CONTEXT BLOCK ADDRESS
	JSP	T2,SAVCTX##	;RUN AT UUO LEVEL
	SETZ	P1,		;FLAG FOR ERRXIT
	PUSHJ	P,SWTCTX	;DO IT
	  JRST	CMDETX		;GO TRANSLATE ERROR CODE TO TEXT AND HALT JOB
	POPJ	P,		;USER TYPED CONTUNUE, CONTEXT RESTORED

CMD3:	SKIPE	P2		;IF BLANK NAME,
	TLNE	P2,-1		;OR IF SIXBIT,
	JRST	CMD4		;THEN USER WANTS A NEW CONTEXT
	JUMPLE	P1,CMDER1	;CONTEXT MUST EXIST
	SETZM	.CTCBN(P1)	;CLEAR THE CONTEXT'S NAME
	TLZ	M,NOPER##!NOCRLF## ;TERMINATE LIKE A NORMAL COMMAND
	POPJ	P,		;RETURN

CMD4:	MOVE	P1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT BLOCK
	MOVEM	P2,.CTNCN(P1)	;STORE NAME FOR NEW CONTEXT
	JSP	T2,SAVCTX##	;RUN AT UUO LEVEL
	SETZ	P1,		;FLAG FOR ERRXIT
	MOVSI	T1,(CT.TOP!CT.HLT) ;CREATE TOP LEVEL CONTEXT AND HALT JOB
	PUSHJ	P,CTXPSH	;DO IT
	  JRST	CMDETX		;GO TRANSLATE ERROR CODE TO TEXT AND HALT JOB
	POPJ	P,		;USER TYPED CONTINUE, CONTEXT RESTORED
LISTER:	JSP	T2,SAVCTX##	;RUN AT UUO LEVEL
	PUSHJ	P,LSTQTA	;LIST QUOTAS, ETC.
	MOVE	P1,.PDSAC##(W)	;POINT TO START OF CONTEXT BLOCK CHAIN
	SETZ	P2,		;CLEAR A COUNTER
	MOVEI	T1,LSTHDR	;POINT TO HEADER
	PUSHJ	P,CONMES##	;TYPE IT
LISTE1:	PUSHJ	P,LSTBLK	;LIST CONTEXT BLOCK STATUS
	SKIPE	P1,.CTNXT(P1)	;POINT TO NEXT BLOCK
	AOJA	P2,LISTE1	;COUNT THE CONTEXT AND LOOP
	POPJ	P,		;RETURN


LISTCT:	JUMPLE	P1,CMDER1	;CONTEXT MUST BE KNOWN
	TLZ	M,NOPER##!NOCRLF## ;TERMINATE LIKE NORMAL COMMAND
	MOVEI	T1,LSTHDR	;POINT TO HEADER
	PUSHJ	P,CONMES##	;TYPE IT
	PJRST	LSTBLK		;LIST CONTEXT BLOCK STATUS AND RETURN


LSTHDR:	ASCIZ	|
   Context      Superior     Prog    Idle time
|


LSTQTA:	PUSHJ	P,PCRLF##	;START WITH A CRLF
	MOVEI	T1,[ASCIZ |Contexts used/quota = |]
	LDB	T2,PCTXCU	;GET CONTEXTS USED
	SKIPN	T2		;HAVE A QUOTA?
	MOVEI	T2,777		;NO--THIS IS THE ABSOLUTE LIMIT
	LDB	T3,PCTXCQ	;GET QUOTA
	PUSHJ	P,LSTQT1	;DISPLAY
	MOVEI	T1,[ASCIZ |, pages used/quota = |]
	LDB	T2,PCTXPU	;GET PAGES USED
	LDB	T3,PCTXPQ	;GET QUOTA

LSTQT1:	PUSH	P,T3		;SAVE QUOTA
	PUSH	P,T2		;SAVE USED
	PUSHJ	P,CONMES##	;TYPE TEXT
	POP	P,T1		;GET USED
	PUSHJ	P,PRTDIG##	;TYPE IT
	MOVEI	T3,"/"		;TYPE
	PUSHJ	P,PRCHR##	; SEPARATOR
	POP	P,T1		;GET QUOTA BACK
	SKIPE	T1		;IF NO QUOTA, SAY SO
	PJRST	PRTDIG##	;ELSE TYPE QUOTA AND RETURN
	MOVEI	T1,[ASCIZ |none|] ;LOTS
	PJRST	CONMES##	;TYPE TEXT AND RETURN
; CONTEXT COMMAND KEYWORD AND DISPATCH TABLES

KEYTAB:	SIXBIT	/KILL/
	SIXBIT	/LIST/
KEYSIZ==.-KEYTAB

KEYDSP:	IFIW	KILLCT
	IFIW	LISTCT


; COMMAND ERROR PROCESSING

CMDER1:	JSP	T1,CMDERR
	ASCIZ	|No such context|

CMDER2:	JSP	T1,CMDERR
	ASCIZ	|Context name cannot be numeric|

CMDER3:	JSP	T1,CMDERR
	ASCIZ	|Cannot find context to be named|

CMDER4:	JSP	T1,CMDERR
	ASCIZ	|No context to be named|

CMDETX:	ANDI	T1,CT.ERR	;NO JUNK
	HRRZ	T1,ERRTAB(T1)	;TRANSLATE ERROR CODE TO TEXT
	TLO	T1,(IFIW)	;EXTENDED ADDRESSING HACK

CMDERR:	PUSH	P,T1		;SAVE STRING ADDRESS
	PUSHJ	P,PCRLF##	;TYPE A CRLF
	POP	P,T1		;GET MESSAGE ADDRESS BACK
	PJRST	ERRMES##	;ISSUE ERROR MESSAGE AND HALT JOB

KILLCT:	JUMPL	P1,CMDER1	;CONTEXT MUST BE KNOWN
	MOVE	T1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT
	MOVEM	P1,.CTNEW(T1)	;SET NEW CONTEXT BLOCK ADDRESS
	JSP	T2,SAVCTX##	;RUN AT UUO LEVEL
	SETZ	P1,		;FLAG FOR ERRXIT
	SETZ	T1,		;NO FLAGS
	PUSHJ	P,DELCTX	;DELETE THE SPECIFIED CONTEXT
	  JRST	CMDETX
	POPJ	P,
; READ A CONTEXT NAME OR NUMBER
; CALL:	PUSHJ	P,RDNAME
;	  <NON-SKIP>
;	<SKIP>
;
; NON-SKIP:	COMMAND ERROR, BAD ARGUMENTS GIVEN
; SKIP:		T1 CONTAINS:
;			 -1  IF NO SUCH CONTEXT
;			ZERO IF NO ARGUMENT GIVEN (LIST ALL)
;			ADDR IF AN EXISTING CONTEXT FOUND

RDNAME:	PUSHJ	P,SKIPS1##	;EAT LEADING SPACES AND TABS
	  JRST	RDNAM2		;INDICATE NO ARGUMENT SEEN
	MOVE	T1,.PDCTC##(W)	;POINT TO THE CURRENT CONTEXT
	CAIN	T3,"."		;WANT THAT ONE?
	JRST	RDNAM1		;GO RETURN THE CURRENT CONTEXT
	CAIL	T3,"0"		;RANGE CHECK
	CAILE	T3,"9"		; FOR A DIGIT
	JRST	RDNAM4		;MUST BE A SIXBIT NAME
	PUSHJ	P,DECIN1##	;PARSE A NUMBER
	  POPJ	P,		;NOT ENOUGH ARGUMENTS
	  JFCL			;END OF NUMBER
	MOVE	T1,.PDSAC##(W)	;POINT TO START OF CONTEXT BLOCK CHAIN
	JRST	RDNAM3		;GO SEARCH FOR A MATCHING NUMBER

; HERE IF "." SEEN
RDNAM1:	PUSHJ	P,COMTYS##	;EAT THE DOT
	SKIPA	T1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT

; HERE IF NO ARGUMENT
RDNAM2:	SETZ	T1,		;CLEAR CONTEXT BLOCK ADDRESS
	JRST	CPOPJ1##	;AND RETURN

; SEARCH FOR A MATCHING CONTEXT NUMBER
RDNAM3:	HRRZ	T3,.CTFLG(T1)
	CAIN	T2,(T3)		;MATCH?
	JRST	CPOPJ1##	;YES--RETURN
	SKIPE	T1,.CTNXT(T1)	;POINT TO NEXT BLOCK
	JRST	RDNAM3		;LOOP
	JRST	RDNAM6		;NO SUCH CONTEXT

; SEARCH FOR A MATCHING CONTEXT NAME
RDNAM4:	PUSHJ	P,CTEXT1##	;GET A NAME
	MOVE	T1,.PDSAC##(W)	;POINT TO START OF CONTEXT BLOCK CHAIN
RDNAM5:	CAMN	T2,.CTCBN(T1)	;MATCH?
	JRST	CPOPJ1##	;YES--RETURN
	SKIPE	T1,.CTNXT(T1)	;POINT TO NEXT BLOCK
	JRST	RDNAM5		;LOOP
RDNAM6:	MOVNI	T1,1		;NO SUCH CONTEXT
	JRST	CPOPJ1##	;RETURN
SUBTTL	ENTRY POINTS -- PSHCMD/POPCMD - PUSH AND POP COMMANDS


PSHCMD::SE1ENT			;ENTER SECTION 1
	JSP	T2,SAVCTX##	;RUN AT UUO LEVEL
	MOVSI	T1,(CT.UUO)	;BIT TO CLEAR
	ANDCAM	T1,.PDCTX##(W)	;FLAG NOT IN UUO (FOR ERRXIT)
	SETZ	P1,		;FLAG FOR ERRXIT
	MOVSI	T1,(CT.HLT)	;SAVE CONTEXT AND HALT JOB
	PUSHJ	P,CTXPSH	;DO IT
	  JRST	CMDETX		;GO TRANSLATE ERROR CODE TO TEXT AND HALT JOB
	POPJ	P,		;USER TYPED CONTINUE, CONTEXT RESTORED

POPCMD::SE1ENT			;ENTER SECTION 1
	JSP	T2,SAVCTX##	;RUN AT UUO LEVEL
	MOVSI	T1,(CT.UUO)	;BIT TO CLEAR
	ANDCAM	T1,.PDCTX##(W)	;FLAG NOT IN UUO (FOR ERRXIT)
	PUSHJ	P,CLRCOM	;CLEAR TTY INPUT BUFFER
	PUSHJ	P,CTXPOP	;RESTORE CONTEXT (SHOULD NEVER RETURN)
	PJRST	CMDETX		;GO TRANSLATE ERROR CODE TO TEXT AND HALT JOB
SUBTTL	ENTRY POINTS -- CTXATO - AUTO-SAVE CONTEXT


CTXATO::MOVSI	T1,(CT.UUO)	;BIT TO CLEAR
	ANDCAM	T1,.PDCTX##(W)	;FLAG NOT IN UUO (FOR ERRXIT)
	POP	P,(P)		;CPOPJ RETURNS ONLY IF NO CONTEXT SERVICE
	SE1ENT			;ENTER SECTION 1
	MOVE	T1,.PDCTC##(W)	;POINT TO CURRENT BLOCK
	HRLZM	P1,.CTRUA(T1)	;SAVE RUN OFFSET
	MOVEM	P2,.CTPRG(T1)	;SAVE PROGRAM NAME
	MOVEM	P3,.CTDSP(T1)	;SAVE DISPATCH
	JSP	T2,SAVCTD##	;RUN AT UUO LEVEL
	MOVE	P1,.PDCTC##(W)	;POINT TO CURRENT JUST TO HAVE A VALID POINTER
	MOVSI	T1,(CT.ATO)	;THIS IS AN AUTO-SAVE
	PUSHJ	P,CTXPSH	;SAVE THE WORLD
	  SKIPA	T1,.PDCTC##(W)	;FAILED--POINT TO CURRENT CONTEXT BLOCK
	POPJ	P,		;PROGRAM EXITED, CONTEXT RESTORED
	MOVE	T1,.CTRET(T1)	;GET WORD TO RETURN IN UUO AC
	LDB	T2,PCTXEC	;NOW GET THE ERROR CODE
	EXCH	T1,T2		;SWAP
	TLNN	T2,(CT.RUN)	;RUN UUO ERROR?
	PJRST	CMDETX		;NO--CONTEXT ERROR
	MOVEI	T2,[ASCIZ |Run error |] ;POINT TO DEFAULT TEXT
	PJRST	SGETXT		;TYPE ERROR MESSAGE AND RETURN
SUBTTL	ENTRY POINTS -- CTXSCD - SCHEDULER CALL TO SAVE CONTEXT


CTXSCD::SE1ENT			;ENTER SECTION 1
	CAILE	J,JOBMAX##	;HIGH SEGMENT?
	JRST	CTXSCH		;YES, CHECK IF IT'S OURS
	JUMPE	W,KCORE1##	;JUST GIVE BACK CORE IF NO PDB (CAN HAPPEN
				; ON A WEIRD KJOB CASE)
	SKIPL	.PDCTX##(W)	;NO,  EXPECTING THE SCHEDULAR TO CALL US?
	JRST	KCORE1##	;NO, JUST DELETE CORE IN CORE
	PUSH	P,P1		;SAVE P1
	PUSH	P,P2		;SAVE P2
	MOVE	P1,.PDCTC##(W)	;GET THE CURRENT CONTEXT BLOCK
	MOVSI	T1,(CT.SCD)	;GET BIT TO TEST
	ANDCAM	T1,.PDCTX##(W)	;CLEAR SO WE DON'T COME THROUGH HERE AGAIN
	MOVSI	T1,(CT.SWT)	;BIT TO TEST
	TDNN	T1,.PDCTX##(W)	;SWITCHING TO ANOTHER CONTEXT?
	SKIPE	P1,.CTLAS(P1)	;POINT TO PREVIOUS CONTEXT BLOCK
	PUSHJ	P,SAVECT	;SAVE CONTEXT
	POP	P,P2		;RESTORE P2
	POP	P,P1		;RESTORE P1
	SETZM	JBTIMO##(J)	;SWAPPED OUT SIZE IS 0P
	SETZM	JBTSWP##(J)	;CLEAR DISK ADDRESS AND COUNT OF SECTION MAPS
	PJRST	MAPBAK##	;CONVERT DISK ADDRESS BACK AND START JOB RUNNING

;HERE IF SWAPPING A HISEG TO DETERMINE IF IT'S OURS
CTXSCH:	HRRZ	T1,SWPOUT##	;GET ASSOCIATED LOWSEG (JOB)
	PUSHJ	P,FPDBT1##	;GET ITS PDB ADDRESS
	  JRST	KCORE1##	;HOW CAN THIS FAIL?  DELETE CORE IN CORE
	SKIPL	.PDCTX##(T1)	;IS JOB CHANGING CONTEXTS?
	JRST	KCORE1##	;NO, DELETE CORE IN CORE
	POPJ	P,		;ELSE RETURN WITHOUT DELETING CORE
SUBTTL	SAVE CURRENT CONTEXT


CTXPSH::PUSHJ	P,SAVE2##	;SAVE P1 AND P2
	MOVE	P2,T1		;SAVE NEW CONTEXT FLAGS
	PUSHJ	P,LGLCHK	;PERFORM LEGALITY CHECKS
	  POPJ	P,		;CAN'T SAVE CONTEXT--PROPAGATE ERROR BACK
	MOVE	P1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT BLOCK
	MOVE	T1,UPTIME##	;GET UPTIME NOW
	MOVEM	T1,.CTIDL(P1)	;MARK THIS CONTEXT IDLE AS OF NOW
	PUSHJ	P,CREBLK	;CREATE AND LINK A CONTEXT BLOCK
	  JRST	ERRNCS		;NOT ENOUGH CORE TO SAVE CONTEXT
	PUSHJ	P,UPPAGE	;ACCOUNT FOR THE PAGES ABOUT TO BE USED
	MOVE	P1,.CTLAS(P1)	;POINT TO LAST BLOCK (THE ONE WE'RE SAVING)
	HLLM	P2,.PDCTX##(W)	;SET NEW FLAGS
	MOVE	T1,JBTNAM##(J)	;GET PROGRAM NAME
	TLNN	P2,(CT.ATO)	;AUTO-SAVE?
	MOVEM	T1,.CTPRG(P1)	;NO--SAVE FOR DISPLAY
	PUSHJ	P,CLRCOM	;CLEAR TTY INPUT BUFFER
	PUSHJ	P,GETRUA	;GET RUN UUO ARGS FROM USER ADDRESS SPACE
	MOVSI	T1,(CT.TOP)	;BIT TO TEST
	TDNE	T1,.PDCTX##(W)	;CREATING A NEW TOP LEVEL CONTEXT?
	JRST	CTXPS0		;YES
	MOVE	T1,.PDCTC##(W)	;POINT TO CURRENT BLOCK
	MOVEM	P1,.CTSUP(T1)	;SET SUPERIOR CONTEXT BLOCK ADDRESS
	MOVSI	T1,(CT.INF)	;REMEMBER THE SUPERIOR
	IORM	T1,.CTFLG(P1)	; HAS INFERIOR CONTEXTS

CTXPS0:	PUSH	P,P1		;SAVE SUPERIOR BLOCK ADDRESS
	MOVE	P1,.PDCTC##(W)	;GET NEW INFERIOR ADDRESS
	PUSHJ	P,UPCTXN	;COUNT UP THE CONTEXT LEVEL
	PUSHJ	P,FREECT	;FIND AND ASSIGN A FREE CONTEXT NUMBER
	POP	P,P1		;RESTORE SUPERIOR
	PUSHJ	P,SWPCTX	;SWAP JOB AND SAVE CONTEXT
	  JRST	CTXPS4		;CONTEXT CONTINUED
	SETZM	JBTNAM##(J)	;ONLY FOR ^T
	SETZM	JBTPC##(J)	;DITTO
	SETZM	USRHCU##	;I/O CHANNELS NO LONGER OPENED
	SETZM	.USCTA		;NO EXTENDED CHANNEL TABLE
	PUSHJ	P,CORCTX	;GET MINIMAL JOB CORE FOR THIS CONTEXT

CTXPS2:	PUSHJ	P,WRTTCR	;WRITE TMPCOR IF REQUESTED
	PUSHJ	P,WCHCTX	;TYPE CONTEXT WATCH INFO
	MOVSI	T1,(JS.SAC)	;GET AUTO-RESTORE BIT
	ANDCAM	T1,JBTST2##(J)	;DON'T WANT TO DO THIS ON PUSH COMMANDS
	MOVSI	T1,(CT.HLT)	;GET HALT BIT
	TDNN	T1,.PDCTX##(W)	;SAVE CONTEXT AND HALT JOB?
	JRST	CTXPS3		;NO--IT'S SAVE CONTEXT AND RUN
	ANDCAM	T1,.PDCTX##(W)	;CLEAR SO DON'T LEAVE AROUND
	PUSHJ	P,PRRSP3##	;PRINT [XXX], CRLF, DOT
	PUSHJ	P,TTYSTC##	;GET THE TTY TYPING
	PJRST	ESTOP##		;START TTY IN MONITOR MODE AND STOP JOB

CTXPS3:	MOVE	P1,.CTLAS(P1)	;POINT TO THE LAST (SAVED) CONTEXT BLOCK
	PUSHJ	P,PUTRUA	;PUT RUN UUO ARGS IN USER ADDRESS SPACE
	MOVSI	T1,(JS.SAC)	;GET THE AUTO-RESTORE BIT
	IORM	T1,JBTST2##(J)	;LITE SO PROGRAM EXIT WILL GO BACK TO CALLER
	MOVSI	T1,(UP.CTX)	;LITE SPECIAL CONTEXT BIT
	IORM	T1,.USBTS	; FOR SAVE/GET ERROR RECOVERY
	MOVSI	T1,(CT.PRN)	;BIT TO TEST
	TDNN	T1,.PDCTX##(W)	;WANT PHYSICAL ONLY?
	TDZA	P1,P1		;NO
	MOVSI	P1,PHONLY	;LITE THE BIT
	ANDCAM	T1,.PDCTX##(W)	;CLEAR FOR FUTURE REFERENCE
IFN FTXMON,<JRST @[0,,.+1]>	;CAN'T USE SSEC0 HERE
	PUSHJ	P,URUN1A##	;DO A RUN UUO (NEVER RETURNS IF SUCESSFUL)

CTXRUE::
IFN FTXMON,<XJRST [MCSEC1+.+1]>	;BACK TO SECTION 1
	MOVE	P1,.PDCTC##(W)	;RELOAD CURRENT CONTEXT BLOCK ADDRESS
	MOVE	P1,.CTLAS(P1)	;POINT TO THE ONE WE CAME FROM
	TLO	T1,(CT.RUN)	;INDICATE RUN UUO ERROR
	MOVEM	T1,.CTRET(P1)	;STORE FOR RETURN
	MOVSI	T1,(CT.UUE)	;AN ERROR
	IORM	T1,.CTFLG(P1)	; HAS OCCURRED
	MOVSI	T1,(UP.CTX)	;CLEAR THE SPECIAL BIT USED
	ANDCAM	T1,.USBTS	; BY SAVE/GET ERROR RECOVERY
	MOVE	J,.CPJOB##	;IN CASE RUN UUO PUT KDB IN J
	JRST	MONRET##	;SET AUTO-RESTORE CLEAN UP

CTXPS4:	MOVSI	T1,(CT.DEL)	;GET DELETE FLAG
	TDNE	T1,.CTFLG(P1)	;KILLING OFF THIS CONTEXT?
	PJRST	CTXPOP		;YES
	MOVE	T1,.CTRET(P1)	;STUFF TO RETURN IN USER'S AC
	PUSHJ	P,PUTAC		;RETURN DATA
	MOVSI	T1,(CT.CON)	;CLEAR CONTINUE BIT TO
	ANDCAM	T1,.CTFLG(P1)	; PREVENT ETERNAL LOOPING
	MOVSI	T1,(CT.UUE)	;BIT TO TEST
	TDNN	T1,.CTFLG(P1)	;ERROR?
	AOSA	(P)		;SKIP
	ANDCAM	T1,.CTFLG(P1)	;CLEAR FOR NEXT TIME
	POPJ	P,		;RETURN
SUBTTL	SWITCH CURRENT CONTEXT

SWTCTX:	PUSHJ	P,SAVE2##	;SAVE P1 AND P2
	MOVSI	P2,(CT.SWT)	;SWITCHING CONTEXTS
	PUSHJ	P,LGLCHK	;PERFORM LEGALITY CHECKS
	  POPJ	P,		;CAN'T SAVE CONTEXT--PROPAGATE ERROR BACK
	MOVE	P1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT BLOCK
	MOVE	T1,.CTNEW(P1)	;POINT TO THE NEW CONTEXT
	CAME	T1,P1		;NEW SAME AS CURRENT?
	JRST	SWTCT1		;NO
	SETZM	.CTNEW(P1)	;CLEAR FOR NEXT TIME
	SETZM	.CTLAS(P1)	;NO LAST CONTEXT
	PUSHJ	P,WCHCTX	;DISPLAY WATCH INFO
	JRST	CPOPJ1##	;AND RETURN

SWTCT1:	MOVEI	T2,CT.LGO	;BIT TO TEST
	TDNE	T2,.PDCTX##(W)	;LOGGING OUT?
	JRST	SWTCT2		;YES
	MOVSI	T2,(CT.INF)	;BIT TO TEST
	TDNE	T2,.CTFLG(T1)	;NEW CONTEXT HAVE INFERIORS?
	  JRST	ERRCSI		;CANNOT SWITCH TO AN INTERMEDIATE CONTEXT

SWTCT2:	MOVE	T1,UPTIME##	;GET UPTIME NOW
	MOVEM	T1,.CTIDL(P1)	;MARK THIS CONTEXT IDLE AS OF NOW
	SETZM	.CTLAS(P1)	;NO LAST CONTEXT
	HLLM	P2,.PDCTX##(W)	;SET NEW FLAGS
	MOVE	T1,JBTNAM##(J)	;GET PROGRAM NAME
	MOVEM	T1,.CTPRG(P1)	;SAVE FOR DISPLAY
	PUSHJ	P,UPPAGE	;ACCOUNT FOR THE PAGES ABOUT TO BE USED
	PUSHJ	P,CLRCOM	;CLEAR TTY INPUT BUFFER
	PUSHJ	P,SWPCTX	;SWAP JOB AND SAVE CONTEXT
	  JRST	CTXPS4		;CONTEXT CONTINUED
	SETZM	JBTNAM##(J)	;ONLY FOR ^T
	SETZM	JBTPC##(J)	;DITTO
	SETZM	USRHCU##	;I/O CHANNELS NO LONGER OPENED
	SETZM	.USCTA		;NO EXTENDED CHANNEL TABLE
	PUSHJ	P,CORCTX	;GET MINIMAL JOB CORE FOR THIS CONTEXT
	MOVSI	T1,JLOG!JERR	;CLEAR JERR SO CAN'T ^C, JLOG SO
	ANDCAM	T1,JBTSTS##(J)	; ALL CORE GOES AWAY
	MOVSI	T1,JACCT	;SET JACCT SO
	IORM	T1,JBTSTS##(J)	; USER CAN'T CONTROL-C
	SETZM	.JDAT+.JBINT##	;ZAP TRAPPING
IFN FTXMON,<JRST @[0,,.+1]>	;CAN'T USE SSEC0 HERE
	PUSHJ	P,JOB1A##	;CLEAN UP
IFN FTXMON,<XJRST [MCSEC1+.+1]>	;BACK TO SECTION 1
	MOVE	P1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT BLOCK
	MOVE	P1,.CTNEW(P1)	;NOW GET ADDRESS OF TARGET CONTEXT BLOCK
	MOVEM	P1,.PDCTC##(W)	;SET FOR POSTERITY
	SETZM	.CTNEW(P1)	;CLEAR FOR NEXT TIME
	PUSHJ	P,RESTCT	;RESTORE CONTEXT
	PUSHJ	P,DNPAGE	;ACCOUNT FOR THE PAGES ABOUT TO BE GIVEN BACK
	PUSHJ	P,WCHCTX	;TYPE CONTEXT WATCH INFO
	JSP	T1,XITCTX	;SET UP CONTEXT EXIT
	PJRST	RSCHED##	;CALL SCHEDULER
SUBTTL	DELETE A CONTEXT

DELCTX:	PUSHJ	P,SAVE2##	;SAVE P1 AND P2
	MOVE	P2,T1		;COPY FLAGS
	TLO	P2,(CT.SWT)	;DELETE CONTEXT INVOLVES SWITCHING
	MOVE	P1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT BLOCK
	MOVE	T1,.CTNEW(P1)	;POINT TO THE NEW CONTEXT
	CAMN	T1,P1		;NEW SAME AS CURRENT?
	JRST	ERRCDC		;CANNOT DELETE CURRENT CONTEXT
	MOVSI	T2,(CT.INF)	;BIT TO TEST
	TDNE	T2,.CTFLG(T1)	;NEW CONTEXT HAVE INFERIORS?
	  JRST	ERRCDI		;CANNOT DELETE AN INTERMEDIATE CONTEXT
	MOVE	T3,.CTSUP(T1)	;GET TARGET'S SUPERIOR CONTEXT
	ANDCAM	T2,.CTFLG(T3)	;IT WON'T HAVE AN INFERIOR AFTER THE DELETE
	MOVEM	P1,.CTSUP(T1)	;MAKE CURRENT CONTEXT SUPERIOR TO TARGET
	MOVSI	T2,(CT.DEL)	;DELETING CONTEXTS
	IORM	T2,.CTFLG(T1)	;SET FOR TARGET CONTEXT
	MOVE	T1,UPTIME##	;GET UPTIME NOW
	MOVEM	T1,.CTIDL(P1)	;MARK THIS CONTEXT IDLE AS OF NOW
	SETZM	.CTLAS(P1)	;NO LAST CONTEXT
	HLLM	P2,.PDCTX##(W)	;SET NEW FLAGS
	MOVE	T1,JBTNAM##(J)	;GET PROGRAM NAME
	MOVEM	T1,.CTPRG(P1)	;SAVE FOR DISPLAY
	PUSHJ	P,UPPAGE	;ACCOUNT FOR THE PAGES ABOUT TO BE USED
	PUSHJ	P,SWPCTX	;SWAP JOB AND SAVE CONTEXT
	  JRST	CTXPS4		;CONTEXT CONTINUED
	SETZM	USRHCU##	;I/O CHANNELS NO LONGER OPENED
	SETZM	.USCTA		;NO EXTENDED CHANNEL TABLE
	PUSHJ	P,CORCTX	;GET MINIMAL JOB CORE FOR THIS CONTEXT
	MOVSI	T1,JLOG		;CLEAR JLOG SO
	ANDCAM	T1,JBTSTS##(J)	; ALL CORE GOES AWAY
	MOVSI	T1,JACCT	;SET JACCT SO
	IORM	T1,JBTSTS##(J)	; USER CAN'T CONTROL-C
	SETZM	.JDAT+.JBINT##	;ZAP TRAPPING
IFN FTXMON,<JRST @[0,,.+1]>	;CAN'T USE SSEC0 HERE
	PUSHJ	P,JOB1##	;CLEAN UP
IFN FTXMON,<XJRST [MCSEC1+.+1]>	;BACK TO SECTION 1
	MOVE	P1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT BLOCK
	MOVE	P1,.CTNEW(P1)	;NOW GET ADDRESS OF TARGET CONTEXT BLOCK
	MOVEM	P1,.PDCTC##(W)	;SET FOR POSTERITY
	SETZM	.CTNEW(P1)	;CLEAR FOR NEXT TIME
	PUSHJ	P,RESTCT	;RESTORE CONTEXT
	PUSHJ	P,DNPAGE	;ACCOUNT FOR THE PAGES ABOUT TO BE GIVEN BACK
	JSP	T1,XITCTX	;SET UP CONTEXT EXIT
	PJRST	RSCHED##	;CALL SCHEDULER
SUBTTL RESTORE PREVIOUS CONTEXT

CTXPOP::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,FNDPDS##	;FIND THE PDB
	MOVE	P1,.PDCTC##(W)	;GET THE ADDRESS OF THE CURRENT CONTEXT BLOCK
	SKIPN	.CTSUP(P1)	;HAVE A SUPERIOR CONTEXT TO RESTORE?
	JRST	ERRNSC		;NO
	MOVSI	T1,RUN		;LIGHT OUR RUN BIT
	IORM	T1,JBTSTS##(J)	;SO THIS CALL RETURNS
	S0PSHJ	RESET##		;STOP THE WORLD
IFN FTIPCF,<PUSHJ P,IPCPOP##>	;TELL IPCSER WE'RE LEAVING
IFN FTSCA,<PUSHJ P,SCSPOP##>	;TELL SCSUUO WE'RE LEAVING
IFN FTDECNET,<
IFE FTXMON,<DNCALL (SCUPOP##)> ;TELL SCMUUO WE'RE LEAVING
IFN FTXMON,<SNCALL (SCUPOP##,MS.HGH)> ;TELL SCMUUO WE'RE LEAVING
>; END IFN FTDECNET
	PUSHJ	P,MDIECT	;COPY DATA FROM INFERIOR TO EXEC
	MOVE	P1,.CTSUP(P1)	;POINT TO SUPERIOR CONTEXT
	MOVSI	T1,JLOG		;CLEAR JLOG SO
	ANDCAM	T1,JBTSTS##(J)	; ALL CORE GOES AWAY
	MOVSI	T1,RUN+JACCT	;RUNNABLE BIT + JACCT TO PREVENT ^C
	IORM	T1,JBTSTS##(J)	;MAKE SURE IT'S ON
	SETZM	.JDAT+.JBINT##	;ZAP TRAPPING
IFN FTXMON,<JRST @[0,,.+1]>	;CAN'T USE SSEC0 HERE
	PUSHJ	P,JOB1##	;CLEAN UP
IFN FTXMON,<XJRST [MCSEC1+.+1]>	;BACK TO SECTION 1
IFN FTEQDQ,<
	LDB	T1,PCTXNO	;GET SUPERIOR'S CTX NUMBER
	LSH	T1,CTXLSH##	;MOVE IT OVER
	IOR	T1,J		;MAKE FULL JCH
	XMOVEI	T2,.CTBPR+.CXENQ(P1) ;POINT TO QUESER DATA HEADER
	PUSHJ	P,ENQPOP##	;CALL QUESER FOR ETERNAL LOCKS
>;END OF IFN FTEQDQ
	SKIPE	U		;UNLESS DETACHED,
	PUSHJ	P,WCHEND##	;PRINT WATCH STATISTICS FOR NEATNESS'S SAKE
	PUSHJ	P,RESTCT	;RESTORE CONTEXT
	PUSHJ	P,DNCTXN	;COUNT DOWN THE CONTEXT LEVEL
	PUSHJ	P,DNPAGE	;ACCOUNT FOR THE PAGES ABOUT TO BE GIVEN BACK
	PUSHJ	P,DELBLK	;DELETE AND UNLINK CONTEXT BLOCK
	PUSHJ	P,WCHCTX	;TYPE WATCH INFO FOR THE NEW CONTEXT
	SETZM	.CTIDL(P1)	;NO LONGER IDLE
	MOVSI	T1,(CT.INF)	;THIS NEW CONTEXT NO
	ANDCAM	T1,.CTFLG(P1)	; LONGER HAS ANY INFERIORS
	JSP	T1,XITCTX	;SET UP CONTEXT EXIT
	PJRST	RSCHED##	;CALL SCHEDULER
SUBTTL	SWAP JOB AND SAVE CONTEXT


; THIS ROUTINE WILL MARK THE CURRENT JOB TO HAVE ITS CURRENT
; CONTEXT SAVED AND SWAP THE JOB OUT.
;
; CALL:	PUSHJ	P,SWPCTX
;	  <NON-SKIP>		;CONTINUE AFTER CONTEXT RESTORE
;	<SKIP>			;FINISH UP CONTEXT SAVE

SWPCTX:	AOS	TOTSAV		;COUNT THE CONTEXT ABOUT TO BE SAVED
	MOVSI	T1,(CT.UUO)	;BIT TO DIDDLE
	ANDCAM	T1,.CTFLG(P1)	;ASSUME FOR COMMAND
	TDNE	T1,.PDCTX##(W)	;THIS FOR A UUO?
	IORM	T1,.CTFLG(P1)	;YES, SET IN BLOCK
IFN FTFDAE,<
	MOVSI	T1,(JS.CFX)	;CALL FILDAE FOR EXIT MESSAGE
	TDNE	T1,JBTST2##(J)	;DO WE NEED TO DO SO?
	PUSHJ	P,SNDFPM##	;YES, SEND FILDAE A PUSH MESSAGE
>
	SKIPG	T1,JBTSGN##(J)	;DO WE HAVE A REAL HISEG?
	JRST	SWPCT1		;NO, DON'T FIDDLE WITH IT
	HRRZS	T1		; (NZS PROBLEMS)
	AOS	JBTSTS##(T1)	;YES, BUMP ITS INCORE COUNT FOR OUR CLONE
	AOS	JBTSHR##(T1)	;AND ALSO ITS TOTAL SHARER COUNT
SWPCT1:	LDB	T1,IMGIN##	;GET OUR IN-CORE SIZE
	PUSHJ	P,XPANDP##	;SET WHEELS IN MOTION TO SWAP US OUT
	MOVSI	T1,(CT.SCD)	;WAITING FOR SWAPOUT TO SAVE CONTEXT
	IORM	T1,.PDCTX##(W)	;REMEMBER WHEN THE SCHEDULER CALLS US
	PUSHJ	P,WSCHED##	;REQUEUE
CONTPC:
IFN FTXMON,<XJRST [MCSEC1+.+1]>	;SAVCTX (MAPBAK) PUTS US IN S0
	MOVE	P1,.PDCTC##(W)	;GET CURRENT CONTEXT BLOCK ADDRESS
	MOVSI	T1,(CT.CON)	;DID THE USER TYPE CONTINUE
	TDNN	T1,.CTFLG(P1)	; CAUSING A CONTEXT RESTORE?
	JRST	SWPCT2		;NO--FINISH UP CONTEXT SAVE
	ANDCAM	T1,.CTFLG(P1)	;CLEAR CONTINUE FLAG
	MOVSI	T1,(CT.UUO)	;BIT TO REMEMBER
	ANDCAM	T1,.PDCTX##(W)	;ASSUME BY COMMAND
	TDNE	T1,.CTFLG(P1)	;ON IN BLOCK?
	IORM	T1,.PDCTX##(W)	;YES, RESTORE
	PUSHJ	P,MDEUCT	;COPY DATA FROM EXEC TO USER
IFN FTFDAE,<
	MOVSI	T1,(JS.CFX)	;CALL FILDAE FOR EXIT MESSAGE
	TDNE	T1,JBTST2##(J)	;DO WE NEED TO DO SO?
	PUSHJ	P,SNDFRM##	;YES, SEND FILDAE A POP MESSAGE
>
	POPJ	P,		;AND RETURN
SWPCT2:	SKIPG	T1,JBTSGN##(J)	;DO WE HAVE A REAL HISEG?
	JRST	CPOPJ1##	;NO, GIVE FINISH-UP RETURN
	MOVSI	T2,CORCNT##	;YES, GET FLAG FOR DECCNT
	IORM	T2,JBTSGN##(J)	;SAY WE'RE STILL AN IN-CORE SHARER
	JRST	CPOPJ1##	;NOW GIVE FINISH-UP RETURN
SUBTTL	CORCTX - GET MINIMAL JOB DATA AREA


CORCTX:	SKIPN	JBTADR##(J)	;HAVE CORE?
	JRST	CORCT1		;LEAVE COUNTERS ALONE
	PUSHJ	P,CORESZ	;COMPUTE CORE SIZE
	MOVNS	T1		;NEED TO SUBTRACT
	ADDM	T1,VIRTAL##	;DO SO (SUBM GOES WRONG WAY)

CORCT1:	MOVSI	T1,(UP.CTX)	;LIGHT SPECIAL CONTEXT BIT
	IORM	T1,.USBTS	;SO DLTPAG WON'T DELETE OUR VIRTUAL PAGES
	S0PSHJ	GETMI1##	;GET MINIMAL JOB AREA IN CORE OR DISK
	MOVSI	T1,(UP.CTX)	;AND NOW CLEAR THE SPECIAL BIT
	ANDCAM	T1,.USBTS	;SO LATER PAGE DELETIONS WORK NORMALLY
	PUSHJ	P,CORESZ	;COMPUTE CORE SIZE NOW
	MOVNS	T1		;NEED TO SUBTRACT
	ADDM	T1,VIRTAL##	;DO SO (SUBM GOES WRONG WAY)
	MOVSI	T1,SWP!SHF	;AND NOT
	ANDCAM	T1,JBTSTS##(J)	; SWAPPING NOW
	SETZM	.JDAT		;CLEAR FIRST WORD OF JOBDAT
IFE FTXMON,<
	MOVE	T1,[.JDAT,,.JDAT+1] ;SET UP BLT POINTER
	BLT	T1,.JDAT+PAGSIZ##-1 ;CLEAR USER PAGE ZERO
> ;END IFE FTXMON
IFN FTXMON,<
	MOVEI	T1,PAGSIZ##-1	;CLEAR
	MOVEI	T2,.JDAT	; USER
	MOVEI	T3,.JDAT+1	;  PAGE
	EXTEND	T1,[XBLT]	;   ZERO
> ;END IFN FTXMON
	SETZM	USRDDT##	;CLEAR SAVED COPY OF DDT
	POPJ	P,		;RETURN
SUBTTL	EXIT FROM A CONTEXT


; CALL:	JSP	T1,XITCTX

XITCTX:	MOVSI	T2,(CT.CON)	;LITE CONTINUE CONTEXT SO IT
	IORM	T2,.CTFLG(P1)	; STARTS RUNNING AT LAST STOPPED PC
	XSFM	T2		;GET PC FLAGS (PC STILL IN T3)
	XMOVEI	T3,CONTPC	;CONTINUE PC
	DMOVEM	T2,.CPPC##	;SET RETURN PC DOUBLE WORD
	MOVE	P,.CPNPD##	;SET UP SCHEDULER PDL
	JRST	(T1)		;RETURN
SUBTTL	SAVE/RESTORE -- FREECT - FIND AND ASSIGN A FREE CONTEXT NUMBER


FREECT:	PUSH	P,P1		;SAVE P1
	MOVEI	T1,1		;START WITH CONTEXT NUMBER 1

FREEC1:	MOVE	P1,.PDSAC##(W)	;POINT TO THE START OF THE CHAIN

FREEC2:	LDB	T2,PCTXNO	;GET A CONTEXT NUMBER
	CAIN	T1,(T2)		;THIS NUMBER IN USE?
	AOJA	T1,FREEC1	;YES--TRY ANOTHER
	SKIPE	P1,.CTNXT(P1)	;POINT TO NEXT BLOCK
	JRST	FREEC2		;KEEP SEARCHING

FREEC3:	POP	P,P1		;RESTORE CONTEXT BLOCK POINTER
	DPB	T1,PCTXNO	;SET THIS NUMBER IN THE CURRENT BLOCK
	POPJ	P,		;AND RETURN
SUBTTL	SAVE/RESTORE -- FINDCT - FIND A CONTEXT GIVEN A NAME OR NUMBER


; CALL:	MOVE	T1, SIXBIT NAME OR NUMBER
;	PUSHJ	P,FINDCT
;	  <ERROR>		;NO SUCH CONTEXT
;	<SKIP>			;FOUND, P1 CONTAINS BLOCK ADDRESS

FINDCT:	TLNE	T1,-1		;SIXBIT NAME?
	JRST	FINDC1		;YES
	CAIE	T1,0		;CAN'T BE ZERO
	CAILE	T1,777		;A REASONABLE NUMBER?
	POPJ	P,		;NOPE

FINDC1:	MOVE	P1,.PDSAC##(W)	;POINT TO START OF CONTEXT BLOCK CHAIN

FINDC2:	TLNE	T1,-1		;NAME OR NUMBER?
	SKIPA	T2,.CTCBN(P1)	;NAME
	LDB	T2,PCTXNO	;NUMBER
	CAMN	T1,T2		;MATCH?
	JRST	CPOPJ1##	;YES
	SKIPE	P1,.CTNXT(P1)	;GET NEXT BLOCK ADDRESS
	JRST	FINDC2		;KEEP SEARCHING
	MOVE	P1,.PDCTC##(W)	;LEAVE P1 POINTING TO THE CURRENT
	POPJ	P,		;RETURN EMPTY HANDED
SUBTTL	SAVE/RESTORE -- NAMECT - ASSIGN A NAME TO A CONTEXT


; CALL:	MOVE	P1, CONTEXT BLOCK
;	MOVE	T1, SIXBIT NAME
;	PUSHJ	P,NAMECT

NAMECT:	JUMPE	T1,NAMEC3	;NULL NAME IS OK
	CAMN	T1,.CTCBN(P1)	;NAME ALREADY MATCH THE CURRENT ONE?
	POPJ	P,		;YES--NOTHING TO DO
	MOVE	T2,.PDSAC##(W)	;POINT TO START OF CONTEXT BLOCK CHAIN

NAMEC1:	CAMN	T1,.CTCBN(T2)	;MATCH?
	JRST	NAMEC2		;YES
	SKIPE	T2,.CTNXT(T2)	;GET NEXT BLOCK ADDRESS
	JRST	NAMEC1		;KEEP SEARCHING
	MOVE	T2,P1		;NAME NOT A DUPLICATE

NAMEC2:	SETZM	.CTCBN(T2)	;DEASSIGN NAME FROM OLD CONTEXT BLOCK
NAMEC3:	MOVEM	T1,.CTCBN(P1)	;AND ASSIGN THIS NAME TO THE NEW BLOCK
	POPJ	P,		;RETURN
SUBTTL	SAVE/RESTORE -- JBCHCT - FIND A CONTEXT GIVEN A JOB/CTX HANDLE


; FIND A CONTEXT GIVEN A JOB/CONTEXT HANDLE
; CALL:	MOVE	T1,JOB/CONTEXT HANDLE
;	PUSHJ	P,JBCHCT
;	  <NON-SKIP>		;NO SUCH JOB OR CONTEXT NUMBER
;	<SKIP 1>		;FOUND THE CURRENT CONTEXT BLOCK
;	<SKIP 2>		;FOUND A RANDOM CONTEXT BLOCK
;
; ON A SUCESSFUL RETURN, T1 WILL CONTAIN AN UPDATES JOB/CONTEXT
; HANDLE AND P1 WILL CONTAIN A CONTEXT BLOCK ADDRESS.
;
; NOTE:	IF THE SIGN OF OF T1 IS ON, THEN THIS ROUTINE WILL RETURN
;	THE NEXT CONTEXT FOR THE SPECIFIED JOB.  IN ADDITION, IF
;	REQUESTED CONTEXT NUMBER IS ZERO, THEN THE FIRST CONTEXT
;	BLOCK ADDRESS WILL BE RETURNED.  IN EITHER CASE, ON RETURN,
;	T1 WILL CONTAIN THE NEW JOB/CONTEXT HANDLE NUMBER.

JBCHCT:	PUSH	P,J		;SAVE J
	PUSH	P,W		;SAVE W
	PUSH	P,T2		;SAVE T2
	PUSH	P,T3		;SAVE T3
	MOVE	J,T1		;COPY ARGUMENT
	ANDI	J,JOBMSK##	;WANT ONLY JOB NUMBER
	PUSHJ	P,FNDPDB##	;FIND THE PDB
	  JRST	JBCHC6		;BAD JOB NUMBER
	LDB	T2,[POINT 9,T1,26] ;COPY TARGET CONTEXT NUMBER
	TRZ	T1,CTXMSK##	;CLEAR OLD CTXNUM
	SKIPE	P1,.PDSAC##(W)	;POINT TO START OF CONTEXT CHAIN
	JRST	JBCHC1		;ONWARD
	TRO	T1,1000		;CAN ONLY BE ONE
	TLZN	T1,400000	;STEP?
	SOJLE	T2,JBCHC5	;NO--MUST REQUEST FIRST OR ONLY CONTEXT
	JUMPE	T2,JBCHC5	;STEP ON, IF JUST JOB # WANTS ONLY CONTEXT
	JRST	JBCHC6		;REQUESTING CONTEXT OTHER THAN ONE

JBCHC1:	JUMPN	T2,JBCHC2	;JUMP IF A SPECIFIC ONE WANTED
	JUMPL	T1,JBCHC4	;IF ZERO REQUESTED AND NEXT, THEN GIVE FIRST
	MOVE	P1,.PDCTC##(W)	;ELSE POINT TO CURRENT
	JRST	JBCHC4		;AND FINISH UP

JBCHC2:	LDB	T3,PCTXNO	;GET THIS BLOCK'S NUMBER
	CAMN	T2,T3		;MATCH TARGET?
	JRST	JBCHC3		;YES
	SKIPE	P1,.CTNXT(P1)	;POINT TO NEXT
	JRST	JBCHC2		;KEEP SEARCHING
	JRST	JBCHC6		;GIVE UP

JBCHC3:	JUMPGE	T1,JBCHC4	;JUMP IF WANT THE CURRENT CONTEXT ONLY
	SKIPN	P1,.CTNXT(P1)	;YES--POINT TO IT
	JRST	JBCHC6		;THERE ISN'T ANOTHER ONE

JBCHC4:	LDB	T2,PCTXNO	;GET THIS BLOCK'S NUMBER
	MOVE	T3,P1		;SAVE BLOCK ADDRESS
	MOVE	P1,.PDCTC##(W)	;GET CURRENT
	LDB	P1,PCTXNO	;AND CURRENT CONTEXT NUMBER
	EXCH	T3,P1		;SWAP
	CAIE	T2,(T3)		;SEARCH FOUND THE CURRENT CONTEXT?
	AOS	-4(P)		;NO--DOUBLE SKIP
	LSH	T2,CTXLSH##	;POSITION
	IOR	T1,T2		;FORM JCH
	ANDI	T1,JCHMSK##	;STRIP OFF JUNK

JBCHC5:	AOS	-4(P)		;SKIP

JBCHC6:	POP	P,T3		;RESTORE T3
	POP	P,T2		;RESTORE T2
	POP	P,W		;RESTORE W
	POP	P,J		;RESTORE J
	POPJ	P,		;AND RETURN
SUBTTL	SAVE/RESTORE -- SAVECT - SAVE CONTEXT


SAVECT:	PUSHJ	P,TTYFND##	;GET TTY DDB (F,S,U)
	ADDI	P1,.CTBPR-1	;ACCOUNT FOR THE HEADER
	TLNN	P1,-1		;NZS CONTEXT BLOCK?
	HRLI	P1,-.CXNUM-1	;NO--AVOID PDL OVERFLOWS
	MOVSI	P2,-CSRLEN	;AOBJN POINTER

SAVEC1:	SKIPG	T1,CSRTAB(P2)	;GET AN ENTRY
	JRST	SAVEC2		;MUST BE A SUBROUTINE TO EXECUTE
	TLO	T1,(IFIW)	;MAKE IT A LOCAL REFERENCE
	TLZN	T1,(1B1)	;WANT TO PUSH-AND-ZERO, OR JUST PUSH?
	JRST	[PUSH	P1,@T1	;SAVE IT
		 JRST	SAVEC3]	;JOIN UP WITH COMMON CODE
	PUSH	P1,@T1		;SAVE SOMETHING
	SETZM	@T1		;YES, DO IT
	JRST	SAVEC3		;REJOIN COMMON CODE

SAVEC2:	PUSHJ	P,0(T1)		;DISPATCH
	  JFCL			;IGNORE ERRORS FOR NOW

SAVEC3:	AOBJN	P2,SAVEC1	;LOOP THROUGH TABLE
	POPJ	P,		;RETURN
SUBTTL	SAVE/RESTORE -- RESTCT - SAVE CONTEXT


RESTCT:	PUSHJ	P,TTYFND##	;GET TTY DDB (F,S,U)
	ADDI	P1,.CTEPR	;POINT TO END OF SAVED DATA
	TLNN	P1,-1		;NZS CONTEXT BLOCK?
	TLO	P1,-1		;NO--AVOID PDL UNDERFLOW
	MOVEI	P2,CSRLEN-1	;INIT TABLE INDEX

RESTC1:	SKIPG	T1,CSRTAB(P2)	;GET AN ENTRY
	JRST	RESTC2		;MUST BE AN INSTRUCTION TO EXECUTE
	TLO	T1,(IFIW)	;MAKE IT A LOCAL REFERENCE
	TLZ	T1,(1B1)	;ILLEGAL FOR IW TO HAVE BOTH 1B0 & 1B1
	POP	P1,@T1		;RESTORE SOMETHING
	JRST	RESTC3		;REJOIN COMMON CODE

RESTC2:	PUSHJ	P,1(T1)		;DISPATCH
	  JFCL			;IGNORE ERRORS FOR NOW

RESTC3:	SOJGE	P2,RESTC1	;LOOP THROUGH TABLE
	MOVE	P1,.PDCTC##(W)	;RESET CURRENT CONTEXT BLOCK ADDRESS
	POPJ	P,		;RETURN
SUBTTL	SAVE/RESTORE -- FROM SYS BIT


CSRSYS:	JRST	SAVSYS		;SAVE

RSTSYS:	MOVSI	T1,(JB.LSY)	;GET THE "FROM SYS" BIT
	ANDCAM	T1,JBTLIM##(J)	;CLEAR IT INITIALLLY
	POP	P1,T1		;GET THE SAVED BIT
	IORM	T1,JBTLIM##(J)	;SET AS APPROPRIATE
	POPJ	P,		;RETURN

SAVSYS:	MOVSI	T1,(JB.LSY)	;GET THE "FROM SYS" BIT
	AND	T1,JBTLIM##(J)	;KEEP ONLY THAT BIT
	PUSH	P1,T1		;SAVE IT
	POPJ	P,		;RETURN
SUBTTL	SAVE/RESTORE -- MONITOR MODE BIT


CSRMON:	JRST	SAVMON		;SAVE

RSTMON:	SE1ENT
	POP	P1,T1		;GET THE BIT
	JUMPE	U,CPOPJ##	;CAN'T RESTORE IF NOT ATTACHED
	JUMPN	T1,TTYSTC##	;FORCE MONITOR MODE IF WAS ON BEFORE
	PJRST	TTYUSW##	;AND USER MODE IF THAT WAS PREVIOUS

SAVMON:	SE1ENT
	MOVSI	T1,LDLCOM##	;GET THE MONITOR MODE BIT
	AND	T1,LDBDCH##(U)	;KEEP ONLY THAT BIT
	PUSH	P1,T1		;SAVE IT
	POPJ	P,		;RETURN
SUBTTL	SAVE/RESTORE -- BREAK MASK ADDRESS


CSRBKM:	JRST	SAVBKM		;SAVE

RSTBKM:	SE1ENT
	JUMPE	U,[ADJSP P1,-<LDBCSL+3>	;CLEAR STACK OF NOW USELESS VALUES
		   POPJ  P,]	;AND RETURN
	XMOVEI	T2,-<LDBCSL+2>(P1) ;TABLE ADDRESS
IFN FTXMON,<
	MOVEI	T1,LDBCSL+2	;LENGTH OF BLOCK
	XMOVEI	T3,LDBCSB##(U)	;WHERE TO RESTORE THE TABLE
	EXTEND	T1,[XBLT]	;MOVE THE WORDS
>
IFE FTXMON,<
	MOVSI	T1,(T2)		;SOURCE ADDRESS
	HRRI	T1,LDBCSB##(U)	;DESTINATION ADDRESS
	BLT	T1,LDBCSB##+LDBCSL+2-1(U) ;RESTORE THE TABLE
>
	ADJSP	P1,-<LDBCSL+2>	;TRIM THE BLOCK POINTER
	POP	P1,LDBBKB##(U)	;RESTORE BREAK MASK BLOCK
	POPJ	P,		;RETURN

SAVBKM:	SE1ENT
	PUSH	P1,LDBBKB##(U)	;SAVE BREAK MASK BLOCK
	XMOVEI	T1,(P1)		;POINT TO START OF TABLE
	ADJSP	P1,LDBCSL+2	;AND SKIP POINTER PAST IT
IFN FTXMON,<
	MOVE	T3,T1		;DESTINATION
	XMOVEI	T2,LDBCSB##(U)	;SOURCE
	MOVEI	T1,LDBCSL+2	;LENGTH
	EXTEND	T1,[XBLT]	;SAVE THE TABLE
>
IFE FTXMON,<
	MOVE	T2,T1		;DESTINATION
	HRLI	T2,LDBCSB##(U)	;SOURCE
	BLT	T2,LDBCSL+2-1(T1) ;SAVE IT AWAY
>
	SETZM	LDBBKB##(U)	;CLEAR SO NO CONFUSION WITH NEW CONTEXT
	POPJ	P,		;RETURN
SUBTTL	SAVE/RESTORE -- IPCF DATA


IFN FTIPCF,<
CSRIPC:	JRST	SAVIPC		;SAVE

RSTIPC:	POP	P1,.PDEPA##(W)	;(11) RESTORE EXEC PSEUDO-PROCESS PACKET ADDR
	POP	P1,.PDQSN##(W)	;(10) RESTORE SEQUENCE NUMBERS
	POP	P1,.PDIPN##(W)	;(07) RESTORE POINTER TO LAST PACKET IN QUEUE
	POP	P1,.PDIPI##(W)	;(06) RESTORE PID OF JOB'S [SYSTEM]INFO
	POP	P1,.PDPID##(W)	;(05) RESTORE PID FOR SPECIFIC RECEIVE WORD
	POP	P1,.PDIPL##(W)	;(04) RESTORE IPCF QUEUE INTERLOCK WORD
	POP	P1,.PDIPQ##(W)	;(03) RESTORE QUOTAS
	POP	P1,T1		;(02) RESTORE INCREMENTAL SND AND RCV COUNT
	ADDM	T1,.PDIPA##(W)	;     ACCUMULATE
	POP	P1,.PDIPC##(W)	;(01) RESTORE COUNTERS
	POPJ	P,		;RETURN

SAVIPC:	SYSPIF			;AVOID IPCF QUEUEING RACE
	MOVSI	T1,-1		;LINK HALFWORD
	TDNN	T1,.PDIPC##(W)	;IF EMPTY QUEUE,
	SETZM	.PDIPN##(W)	;MAKE SURE WE KNOW IT'S EMPTY
	SYSPIN			;END OF RACE
	PUSH	P1,.PDIPC##(W)	;(01) SAVE COUNTERS
	SETZM	.PDIPC##(W)	;     ZERO
	PUSH	P1,[EXP 0]	;(02) INIT INCREMENTAL STATISTICS (.PDIPA)
	PUSH	P1,.PDIPQ##(W)	;(03) SAVE QUOTAS
	HRLOI	T1,IP.CTX##	;     SPECIAL FLAGS PRESERVED OVER CTX CALLS
	ANDM	T1,.PDIPQ##(W)	;     CLEAR ALL OTHER BITS
	PUSH	P1,.PDIPL##(W)	;(04) SAVE IPCF QUEUE INTERLOCK WORD
	PUSH	P1,.PDPID##(W)	;(05) SAVE PID FOR SPECIFIC RECEIVE
	SETZM	.PDPID##(W)	;     ZERO
	PUSH	P1,.PDIPI##(W)	;(06) SAVE PID OF JOB'S [SYSTEM]INFO
	SETZM	.PDIPI##(W)	;     ZERO
	PUSH	P1,.PDIPN##(W)	;(07) SAVE POINTER TO LAST PACKET IN QUEUE
	SETZM	.PDIPN##(W)	;     ZERO
	PUSH	P1,.PDQSN##(W)	;(10) SAVE SEQUENCE NUMBERS
	SETZM	.PDQSN##(W)	;     ZERO
	PUSH	P1,.PDEPA##(W)	;(11) SAVE EXEC PSEUDO-PROCESS PACKET ADDRESS
	SETZM	.PDEPA##(W)	;     ZERO
	POPJ	P,		;RETURN
> ;END FTIPC
SUBTTL	SAVE/RESTORE -- .PDEQJ


IFN FTEQDQ,<
CSRENQ:	JRST	SAVENQ		;SAVE

RSTENQ:	POP	P1,.PDEQJ##(W)	;RESTORE QUEUE CHAIN ADDRESS
	POPJ	P,		;RETURN

SAVENQ:	PUSH	P1,.PDEQJ##(W)	;SAVE QUEUE CHAIN ADDRESS
	PUSHJ	P,ENQJBI##	;RE-INIT QUEUE LIST HEADER
	POPJ	P,		;RETURN
> ;END FTEQDQ
SUBTTL	SAVE/RESTORE -- JOB STATUS WORD

CSRSTS:	JRST	SAVSTS		;SAVE

RSTSTS:
IFN FTMP,<PUSHJ	P,SBSCD##>	;INTERLOCK THE SCHEDULER
	MOVSI	T1,JRQ		;REQUE'D BIT
	TDNE	T1,JBTSTS##(J)	;IS IT ON?
	IORM	T1,(P1)		;YES, PROPAGATE (ELSE RSJ'S RESULT)
	POP	P1,JBTSTS##(J)	;RESTORE STATUS WORD
	POPJ	P,		;BACK FOR MORE OF RESTCT

SAVSTS:	PUSH	P1,JBTSTS##(J)	;SAVE IS SIMPLE
	POPJ	P,		;VOILA!
SUBTTL	SAVE/RESTORE -- TTY DDB


CSRTTY:	JRST	SAVTTY		;SAVE

RSTTTY:	JUMPN	F,RSTTT1	;HAVE A DDB?
	ADJSP	P1,-13		;PHASE STACK
	POPJ	P,		;AND RETURN
RSTTT1:	POP	P1,T1		;(13) GET ASSIGNED BITS AND JCH
	HLRM	T1,DEVMOD(F)	;     RESTORE ASSPRG+ASSCON
	DPB	T1,PJCHN##	;     RESTORE OWNING JCH
	POP	P1,DEVISN(F)	;(12) RESTORE SECTION NUMBER FOR I/O
	POP	P1,DEVXTR(F)	;(11) RESTORE MSGSER CONTROL WORD
	POP	P1,DEVESE(F)	;(10) RESTORE PSI LINKS
	POP	P1,DEVPSI(F)	;(07) RESTORE PSI CONDITIONS
	POP	P1,DEVOAD(F)	;(06) RESTORE OUTPUT BUFFER ADDRESS
	POP	P1,DEVIAD(F)	;(05) RESTORE INPUT BUFFER ADDRESS
	POP	P1,DEVBUF(F)	;(04) RESTORE BUFFER HEADER ADDRESSES
	POP	P1,DEVLOG(F)	;(03) RESTORE LOGICAL NAME
	POP	P1,DEVIOS(F)	;(02) RESTORE I/O STATUS
	POP	P1,DEVCHR(F)	;(01) RESTORE DEVICE CHARACTERISTICS
	POPJ	P,		;RETURN

SAVTTY:	JUMPN	F,SAVTT1	;HAVE A DDB?
	ADJSP	P1,13		;PHASE STACK
	POPJ	P,		;AND RETURN
SAVTT1:	PUSH	P1,DEVCHR(F)	;(01) SAVE DEVICE CHARACTERISTICS
	PUSH	P1,DEVIOS(F)	;(02) SAVE I/O STATUS
	PUSH	P1,DEVLOG(F)	;(03) SAVE LOGICAL NAME
	PUSH	P1,DEVBUF(F)	;(04) SAVE BUFFER HEADER ADDRESSES
	PUSH	P1,DEVIAD(F)	;(05) SAVE INPUT BUFFER ADDRESS
	PUSH	P1,DEVOAD(F)	;(06) SAVE OUTPUT BUFFER ADDRESS
	PUSH	P1,DEVPSI(F)	;(07) SAVE PSI CONDITIONS
	SETZM	DEVPSI(F)	;     ZERO
	PUSH	P1,DEVESE(F)	;(10) SAVE PSI LINKS
	SETZM	DEVESE(F)	;     ZERO
	PUSH	P1,DEVXTR(F)	;(11) SAVE MSGSER CONTROL WORD
	PUSH	P1,DEVISN(F)	;(12) SAVE SECTION NUMBER FOR I/O
	LDB	T1,PJCHN##	;(13) GET OWNING JCH
	HRL	T1,DEVMOD(F)	;     GET ASSPRG+ASSCON
	PUSH	P1,T1		;     SAVE IT
	ANDI	T1,JOBMSK##	;     KEEP ONLY JOB NUMBER
	DPB	T1,PJCHN##	;     AS THE OWNER
	MOVEI	T1,ASSPRG	;     INIT'ED BIT
	ANDCAM	T1,DEVMOD(F)	;     NO MORE
	POPJ	P,		;RETURN
SUBTTL	SAVE/RESTORE -- JBTST2


IFN FTFDAE,<
CSRST2:	JRST	SAVST2		;SAVE ENTRY

RSTST2:	POP	P1,JBTST2##(J)	;RESTORE JBTST2
	POPJ	P,		;RETURN

SAVST2:	PUSH	P1,JBTST2##(J)	;SAVE JBTST2
	MOVSI	T1,(JS.CFX)	;FILDAE EXIT MESSAGE BIT
	ANDCAM	T1,JBTST2##(J)	;WE ALREADY DID THIS OUR WAY (.FDPSH)
	POPJ	P,		;RETURN
> ;END OF IFN FTFDAE
SUBTTL	SAVE/RESTORE -- JBTAD2



CSRAD2:	JRST	SAVAD2		;SAVE ENTRY

RSTAD2:	POP	P1,T1		;GET OLD JBTAD2
	TRZ	T1,37777	;CLEAR LOW SEG ADDRESS
	MOVEM	T1,JBTAD2##(J)	;UPDATE
	POPJ	P,		;RETURN

SAVAD2:	PUSH	P1,JBTAD2##(J)	;SAVE JBTAD2
	POPJ	P,		;RETURN
SUBTTL	SAVE/RESTORE -- SET CPU (.STCPU) SETTING

CSRSPS:	JRST	SAVSPS		;SAVE ENTRY

RSTSPS:	POP	P1,T1		;GET VALUE BACK
	SKIPE	[M.CPU##-1]	;ONLY IF REALLY SMP
	DPB	T1,[POINT 6,JBTSPS##(J),35] ;RESTORE IT TO CORRECT PLACE
	POPJ	P,		;DONE

SAVSPS:	SKIPE	T1,[M.CPU##-1]	;ONLY IF REALLY SMP
	LDB	T1,[POINT 6,JBTSPS##(J),35] ;GET VALUE WE CARE ABOUT
	PUSH	P1,T1		;SAVE IT
	POPJ	P,		;DONE
SUBTTL	SAVE/RESTORE -- UUO-LEVEL BIGBUF SIZE

CSRLBS:	JRST	SAVLBS		;SAVE ENTRY

RSTLBS:	POP	P1,T1		;GET VALUE BACK
	HRLM	T1,.PDLBS##(W)	;RESTORE IT IN CORRECT PLACE
	POPJ	P,		;DONE

SAVLBS:	HLRZ	T1,.PDLBS##(W)	;GET VALUE WE CARE ABOUT
	PUSH	P1,T1		;SAVE IT
	POPJ	P,		;DONE
SUBTTL	SAVE/RESTORE -- HPQ AND HIBWAKE

IFN FTHPQ,<

CSRRTD:	JRST	SAVRTD		;SAVE ENTRY

RSTRTD:	MOVSI	T1,HPQMSK##	;SET HPQ COMMAND SETTING
	ANDM	T1,JBTRTD##(J)	;SAVE IT
	ANDCAM	T1,(P1)		;ELIMINATE FROM SAVED VALUES
	POP	P1,T1		;RETRIEVE SAVED VALUES
	IORM	T1,JBTRTD##(J)	;RESTORE ALL OTHER VALUES
	LDB	T1,HPQPNT##	;GET UUO-LEVEL SETTING
	PJRST	HPQ##		;RE-PERFORM UUO, THEN BACK TO RESTCT

SAVRTD:	PUSH	P1,JBTRTD##(J)	;SAVE THE VALUE STRAIGHT AWAY
	POPJ	P,		;BACK TO SAVECT

> ;END OF IFN FTHPQ
SUBTTL	SAVE/RESTORE -- PATCH SPACE

IFN FTPATT,<

CSRPAT:	JRST	SAVPAT		;SAVE ENTRY

RSTPAT:	POP	P1,T1		;RETRIEVE DATA FROM CONTEXT STACK
	JFCL			;MODIFY T1
	JFCL			;PUT T1 SOMEWHERE
	POPJ	P,		;RETURN

SAVPAT:	MOVEI	T1,0		;GET DATA INTO T1
	JFCL			;MODIFY IT
	PUSH	P1,T1		;SAVE DATA ON CONTEXT STACK
	POPJ	P,		;RETURN

> ;END OF IFN FTPATT
SUBTTL	CTXUUO - CONTEXT UUO


; UUO TO MANIPULATE CONTEXTS
; CALL:	MOVEI	AC,ADR
;	CTX.	AC,
;	  <NON-SKIP>
;	<SKIP>

; ARGUMENT BLOCK
.CTFNC==0			;FUNCTION CODE WORD
   CT.PHY==1B0			   ;PHYSICAL ONLY RUN UUO
   CT.LEN==777B17		   ;LENGTH OF BLOCK INCLUDING THIS WORD
   CT.FNC==777777B35		   ;FUNCTION CODE
      .CTSVH==0			      ;SAVE CURRENT CONTEXT, HALT JOB
      .CTSVR==1			      ;SAVE CURRENT CONTEXT, RUN PROGRAM
      .CTSVT==2			      ;SAVE CURRENT CONTEXT, CREATE A TOP LEVEL
      .CTSVS==3			      ;SAVE CURRENT CONTEXT, SWITCH TO ANOTHER
      .CTSVD==4			      ;SAVE CURRENT CONTEXT, RUN PROGRAM
      .CTRDB==5			      ;READ DATA BUFFER
      .CTWDB==6			      ;WRITE DATA BUFFER
      .CTRQT==7			      ;READ QUOTAS INTO DATA BUFFER
      .CTSQT==10		      ;SET QUOTAS IN DATA BUFFER
      .CTDIR==11		      ;RETURN A DIRECTORY MAP OF ALL CONTEXTS
      .CTINF==12		      ;RETURN INFORMATION ABOUT A CONTEXT
.CTDBL==1			;DATA BUFFER LENGTH
.CTDBA==2			;DATA BUFFER ADDRESS
.CTNAM==3			;SIXBIT CONTEXT NAME
.CTRNO==4			;RUN UUO OFFSET (LH RESERVED)
.CTRNB==5			;RUN UUO BLOCK ADDRESS
.CTTMN==6			;TMPCOR LENGTH,,SIXBIT NAME
.CTTMB==7			;TMPCOR BUFFER ADDRESS
.CTMAX==10			;LENGTH OF ARGUMENT BLOCK

; DATA BUFFER OFFSETS FOR FUNCTIONS .CTRQT AND .CTSQT
.CTJOB==0			;JOB NUMBER
.CTCTQ==1			;CONTEXT QUOTA
.CTPGQ==2			;SAVED PAGES QUOTA

; DATA BUFFER OFFSETS FOR FUNCTION .CTDIR
;.CTJOB==0			;JOB NUMBER
.CTWCT==1			;RETURNED WORD COUNT OF BYTE-STREAM DATA
.CTFDW==2			;FIRST DATA WORD OF DIRECTORY BYTE-STREAM

; DATA BUFFER OFFSETS FOR FUNCTION .CTINF
;.CTJOB==0			;JOB NUMBER
.CTCNO==1			;THIS CONTEXT'S NUMBER
.CTCNM==2			;THIS CONTEXT'S NAME
.CTSNO==3			;SUPERIOR'S CONTEXT NUMBER
.CTSNM==4			;SUPERIOR'S CONTEXT NAME
.CTPGM==5			;PROGRAM NAME
.CTITM==6			;IDLE TIME IN TICKS

; ON ANY RETURN, THE AC WILL CONTAIN THE FOLLOWING
   CT.DAT==1B0			;DATA WORDS RETURNED
   CT.DBT==1B1			;DATA BUFFER TRUNCATED
   CT.ETX==1B2			;UUO ERROR TEXT IN DATA BUFFER
   CT.RUN==1B3			;RUN UUO ERROR
   CT.RDL==777B27		;WORDS IN DATA BUFFER
   CT.ERR==777B35		;ERROR CODE
; CTX. UUO ERROR CODES AND ERROR DISPATCH ADDRESS GENERATION

DEFINE	ERRS,<

	XLIST

	X (IFC,<Illegal function code>)
	X (ACR,<Address check reading arguments>)
	X (ACS,<Address check storing answers>)
	X (NEA,<Not enough arguments>)
	X (NLI,<Not logged in>)
	X (LOK,<Locked in core>)
	X (DET,<Detached>)
	X (SCE,<System context quota exceeded>)
	X (SPE,<System page quota exceeded>)
	X (JCE,<Job context quota exceeded>)
	X (JPE,<Job page quota exceeded>)
	X (NCS,<Not enough core to save context>)
	X (NCD,<Not enough core to return data block>)
	X (ICN,<Illegal context number>)
	X (NSC,<No superior context>)
	X (NPV,<No privileges to set quotas>)
	X (IJN,<Illegal job number>)
	X (CSI,<Cannot switch to an intermediate context>)
	X (CDI,<Cannot delete an intermediate context>)
	X (CDC,<Cannot delete the current context>)
	X (CNP,<Context not privileged>)
	X (NDA,<No data block available>)
	X (DTL,<Data block too long>)
	X (CCC,<Cannot create context from a captive program>)

	LIST

> ;END ERRS MACRO


DEFINE	X	(NAM,TEXT),<
	CX'NAM'%==ZZ
	ZZ==ZZ+1
	ERR'NAM:	JSP	T1,ERRXIT
> ;END X MACRO

	ZZ==0
ERRDSP:!
	ERRS			;GENERATE ERROR CODES AND DISPATCH ADDRESSES

ERRXIT:	HRRZS	T1		;KEEP ONLY RH
	SUBI	T1,ERRDSP+1	;GET OFFSET
	MOVSI	T2,(CT.UUO)	;USER-MODE BIT
	SKIPE	P1		;CONTEXT BLOCK SETUP YET?
	TDNN	T2,.PDCTX##(W)	;OR NOT USER LEVEL?
	POPJ	P,		;YES, JUST RETURN ERROR UP A LEVEL
	SKIPN	.CTDTU(P1)	;NO, USER SUPPLY A DATA BUFFER?
	PJRST	PUTAC		;STORE IN USER'S AC AND RETURN
	MOVEM	T1,.CTRET(P1)	;SAVE ERROR CODE
	HLRZ	T2,ERRTAB(T1)	;GET LENGTH OF MESSAGE
	HLRZ	T3,.CTDTL(P1)	;GET USER'S DATA BUFFER LENGTH
	MOVSI	T4,(CT.DBT)	;GET TRUNCATED BIT
	CAMLE	T2,T3		;TEXT TOO LONG FOR BUFFER?
	IORM	T4,.CTRET(P1)	;YES--INDICATE SO
	HRRM	T2,.CTDTL(P1)	;STORE TEXT LENGTH
	HRRZ	T2,ERRTAB(T1)	;GET MESSAGE ADDRESS
	MOVEM	T2,.CTDTT(P1)	;SAVE EXEC ADDRESS
	PUSHJ	P,MDEUCT	;MOVE DATA FROM EXEC TO USER
	MOVE	T1,.CTRET(P1)	;GET STUFF TO RETURN IN USER'S AC
	TLO	T1,(CT.ETX)	;INDICATE RETURNING ERROR TEXT
	PJRST	PUTAC		;STORE IN USER'S AC AND RETURN


DEFINE	X	(NAM,TEXT),<
	ZZ==0			;;INIT COUNTER
	IRPC	TEXT,<ZZ==ZZ+1>	;;COUNT CHARACTERS
NAM'TXT:	XWD	<<ZZ/5>+1>,[ASCIZ |TEXT|]
>
ERRTAB:	ERRS			;GENERATE ERROR TEXT TABLE
CTXUUO::MOVSI	T2,(CT.UUO)	;IN UUO FLAG
	IORM	T2,.PDCTX##(W)	;SET FOR ERRXIT
	MOVE	P2,T1		;SAVE ARG BLOCK ADDRESS
	MOVE	P3,P1		;COPY PHYSICAL BIT
	MOVE	P1,.PDCTC##(W)	;POINT TO THE CURRENT CONTEXT BLOCK
	LDB	T1,PUUOAC##	;GET UUO AC
	DPB	T1,PCTXUA	;PRESERVE
	MOVE	M,P2		;POINT M AT FIRST WORD OF USER ARG BLOCK
	MOVE	T1,M		;COPY ADDRESS
	PUSHJ	P,SXPCS##	;SET PCS
	  JRST	ERRACR		;ADDRESS CHECK
	PUSHJ	P,GETEWD##	;GET FIRST WORD
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	TLNE	P3,PHONLY	;PHYSICAL ONLY?
	TLO	T1,(CT.PHY)	;YES
	MOVE	P3,T1		;SAVE FUNCTION CODE, ETC.
	LDB	P4,[POINT 9,T1,17] ;GET ARG BLOCK LENGTH
	PUSHJ	P,UUODAT	;PROCESS DATA BLOCK ARGUMENTS
	  POPJ	P,		;PROPAGATE ERROR
	PUSHJ	P,UUONAM	;PROCESS NEW CONTEXT NAME
	  POPJ	P,		;PROPAGATE ERROR
	PUSHJ	P,UUOTMP	;PROCESS TMPCOR ARGUMENTS
	  POPJ	P,		;PROPAGATE ERROR
	PUSHJ	P,UUORUN	;PROCESS RUN UUO BLOCK
	  POPJ	P,		;PROPAGATE ERROR
	JRST	UUODSP
; PROCESS DATA BLOCK ARGUMENTS
UUODAT:	PUSHJ	P,ZERDAT	;CLEAR POINTERS TO STORAGE
	CAIG	P4,.CTDBL	;HAVE A DATA BLOCK WORD?
	JRST	CPOPJ1##	;NO
	HRRI	M,.CTDBL(P2)	;POINT M AT IT
	PUSHJ	P,GETEWD##	;GET LENGTH
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	SKIPN	T2,T1		;PUT IN APPROPRIATE PLACE
	JRST	CPOPJ1##	;ZERO LENGTH DATA BLOCK
	CAILE	T2,^D510	;MAXIMUM DATA BLOCK LENGTH
	JRST	ERRDTL		;DATA BLOCK TOO LONG
	PUSHJ	P,GETEW1##	;NOW GET ADDRESS WORD
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	PUSHJ	P,ARNGE##	;RANGE CHECK
	  JRST	ERRACR		;ADDRESS CHECK
	  JFCL			;ADDRESS OK BUT ILLEGAL FOR I/O (IGNORED HERE)
	MOVEM	T1,.CTDTU(P1)	;SAVE ADDRESS
	HRRM	T2,.CTDTL(P1)	;SAVE REQUESTED LENGTH
	JRST	CPOPJ1##	;RETURN
; PROCESS NEW CONTEXT NAME
UUONAM:	SETZM	.CTNCN(P1)	;INIT NAME STORAGE
	CAIG	P4,.CTNAM	;HAVE A NAME?
	JRST	CPOPJ1##	;NO
	HRRI	M,.CTNAM(P2)	;POINT AT IT
	PUSHJ	P,GETEWD##	;GET SIXBIT NAME
	  JRST	ERRACR		;ADDRESS CHECK
	MOVEM	T1,.CTNCN(P1)	;SAVE
	JRST	CPOPJ1##	;RETURN

; PROCESS TMPCOR ARGUMENTS
UUOTMP:	CAIG	P4,.CTTMN	;HAVE A TMPCOR BLOCK WORD?
	JRST	CPOPJ1##	;NO
	HRRI	M,.CTTMN(P2)	;POINT M AT IT
	PUSHJ	P,GETEWD##	;GET LENGTH,,NAME
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	TLNE	T1,-1		;MUST BE A NON-ZERO LENGTH
	SKIPN	T3,T1		;SAVE FOR A MINUTE
	JRST	CPOPJ1##	;SKIP TMPCOR STUFF
	PUSHJ	P,GETEW1##	;GET ADDRESS OF TMPCOR BLOCK
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	HLRZ	T2,T3		;COPY LENGTH
	PUSHJ	P,ARNGE##	;RANGE CHECK
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	  JFCL			;ADDRESS OK BUT ILLEGAL FOR I/O (IGNORED HERE)
	MOVEM	T1,.CTTCA(P1)	;SAVE USER ADDRESS OF TMPCOR BUFFER
	MOVEM	T3,.CTTCR(P1)	;SAVE TMPCOR FILE LENGTH,,NAME
	JRST	CPOPJ1##	;RETURN
; PROCESS RUN UUO ARGUMENTS
UUORUN:	PUSHJ	P,CLRRUA	;CLEAR OUT RUN UUO STORAGE
	CAIG	P4,.CTRNO	;HAVE A RUN UUO BLOCK WORD?
	JRST	CPOPJ1##	;NO
IFN FTXMON,<PUSHJ P,SSPCS##>	;SAVE PCS
	HRRI	M,.CTRNO(P2)	;POINT M AT IT
	PUSHJ	P,GETEWD##	;GET RUN OFFSET WORD
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	MOVE	T3,T1		;COPY FOR A MINUTE
	PUSHJ	P,GETEW1##	;GET RUN UUO BLOCK ADDRESS
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	JUMPE	T1,CPOPJ1##	;HAVE A RUN UUO BLOCK?
	MOVEI	T2,6		;STANDARD LENGTH
	PUSHJ	P,ARNGE##	;RANGE CHECK
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	  JFCL			;OK IF NOT I/O LEGAL
	HRLZM	T3,.CTRUA(P1)	;STORE RUN UUO OFFSET IN TEMPORARY AC INCORE
	SOS	M,T1		;COPY RUN UUO BLOCK ADDRESS -1
	PUSHJ	P,SXPCS##	;SET PCS ACCORDINGLY
	  JRST	ERRACR		;ADDRESS CHECK
	MOVSI	T3,-6		;LENGTH OF RUN UUO BLOCK
UUORU1:	PUSHJ	P,GETEW1##	;GET A WORD
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	XMOVEI	T2,.CTRUB(P1)	;POINT TO STARTING STORAGE ADDR
	ADDI	T2,(T3)		;INDEX
	MOVEM	T1,(T2)		;SAVE WORD
	AOBJN	T3,UUORU1	;LOOP THROUGH BLOCK
	SKIPE	T1,.CTRUB+4(P1)	;GET PPN/PATH POINTER
	TLNE	T1,-1		;A PATH?
	JRST	UUORU3		;NO
	HRRI	M,-1(T1)	;POINT TO USER'S PATH BLOCK
	MOVSI	T3,-<2+1+MAXLVL> ;OVERHEAD WORDS + ONE PPN + MAXLVL SFDS
UUORU2:	PUSHJ	P,GETEW1##	;GET A WORD
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	XMOVEI	T2,.CTPUB(P1)	;POINT TO STARTING STORAGE ADDR
	ADDI	T2,(T3)		;INDEX
	MOVEM	T1,(T2)		;SAVE WORD
	AOBJN	T3,UUORU2	;LOOP THROUGH PATH BLOCK

UUORU3:	HLRE	T1,.CTRUB+5(P1)	;GET LH
	AOJN	T1,CPOPJ1##	;RETURN IF NOTHING SPECIFIED
	HRRZ	T1,.CTRUB+5(P1)	;GET ADDRESS
	HRRI	M,-1(T1)	;POINT M AT IT
	PUSHJ	P,GETEW1##	;GET SECTION NUMBER
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	HRRM	T1,.CTRUA(P1)	;SAVE IN LH OF AC
	JRST	CPOPJ1##	;RETURN
UUODSP:	HRRE	T1,P3		;GET FUNCTION CODE
	CAML	T1,[DSPCST-DSPTAB] ;RANGE
	CAILE	T1,DSPLEN	; CHECK
	JRST	ERRIFC		;ILLEGAL FUNCTION CODE
	PJRST	@DSPTAB(T1)	;DISPATCH


DSPCST==.			;END OF CUSTOMER DISPATCH TABLE
	IFIW	CPOPJ##		;(-1) FIRST CUSTOMER FUNCTION GOES HERE
DSPTAB:	IFIW	SAVHLT		;(00) SAVE CURRENT CONTEXT, HALT
	IFIW	SAVRUN		;(01) SAVE CURRENT CONTEXT, RUN PROGRAM
	IFIW	SAVTOP		;(02) SAVE CURRENT CONTEXT, CREATE A TOP LEVEL
	IFIW	SAVSWT		;(03) SAVE CURRENT CONTEXT, SWITCH TO ANOTHER
	IFIW	SAVDEL		;(04) SAVE CURRENT CONTEXT, DELETE ANOTHER
	IFIW	REDDAT		;(05) READ DATA BUFFER
	IFIW	WRTDAT		;(06) WRITE DATA BUFFER
	IFIW	REDQTA		;(07) READ QUOTAS INTO DATA BUFFER
	IFIW	SETQTA		;(10) SET QUOTAS IN DATA BUFFER
	IFIW	DIRECT		;(11) READ CONTEXT DIRECTORY MAP
	IFIW	INFORM		;(12) RETURN INFORMATION ABOUT A CONTEXT
DSPLEN==.-DSPTAB		;LENGTH OF TABLE
SAVRUN:	MOVSI	T1,(CT.PRN)	;PHYSICAL DEVICE SEARCH ON RUN UUO
	ANDCAM	T1,.PDCTX##(W)	;CLEAR BIT INITIALLY
	TLNE	P3,(CT.PHY)	;USER WANT PHYSICAL ONLY?
	IORM	T1,.PDCTX##(W)	;YES
	TDZA	T1,T1		;DEFAULT IS TO RUN A PROGRAM

SAVHLT:	MOVSI	T1,(CT.HLT)	;LITE THE HALT BIT
	TLO	T1,(CT.UUO)	;REMEMBER SAVE CONTEXT VIA UUO
	PUSH	P,T1		;SAVE FROM DESTRUCTION
	PUSHJ	P,MDUECT	;MOVE DATA FROM USER TO EXEC
	  JRST	TPOPJ##		;FAILED
	POP	P,T1		;GET FLAGS BACK
	PUSHJ	P,CTXPSH	;DO IT
	  POPJ	P,		;FAILED--ERROR CODE IN T1
	JRST	CPOPJ1##	;RETURN AND CONTINUE PREVIOUS CONTEXT

SAVTOP:	MOVSI	T1,(CT.TOP!CT.HLT) ;CREATE TOP LEVEL CONTEXT AND HALT JOB
	PUSHJ	P,CTXPSH	;CREATE A NEW CONTEXT
	  POPJ	P,		;FAILED--ERROR CODE IN T1
	JRST	CPOPJ1##	;RETURN AND CONTINUE PREVIOUS CONTEXT

SAVSWT:	CAIG	P4,.CTNAM	;HAVE A NAME ARGUMENT?
	JRST	ERRNEA		;NO, NOT ENOUGH ARGUMENTS
	MOVE	T1,.CTNCN(P1)	;GET NEW CONTEXT NAME
	PUSHJ	P,FINDCT	;FIND THE MATCHING NAME OR NUMBER
	  JRST	ERRICN		;ILLEGAL CONTEXT NUMBER (OR NAME)
	MOVE	T1,.PDCTC##(W)	;POINT TO THE CURRENT CONTEXT
	MOVEM	P1,.CTNEW(T1)	;SET THE ONE WE'LL SWITCH TO
	PUSHJ	P,SWTCTX	;SWITCH TO ANOTHER CONTEXT
	  POPJ	P,		;FAILED--ERROR CODE IN T1
	JRST	CPOPJ1##	;RETURN AND CONTINUE PREVIOUS CONTEXT

SAVDEL:	CAIG	P4,.CTNAM	;HAVE A NAME ARGUMENT?
	JRST	ERRNEA		;NO, NOT ENOUGH ARGUMENTS
	MOVE	T1,.CTNCN(P1)	;GET NEW CONTEXT NAME
	PUSHJ	P,FINDCT	;FIND THE MATCHING NAME OR NUMBER
	  JRST	ERRICN		;ILLEGAL CONTEXT NUMBER (OR NAME)
	MOVE	T1,.PDCTC##(W)	;POINT TO THE CURRENT CONTEXT
	MOVEM	P1,.CTNEW(T1)	;SET THE ONE WE'LL SWITCH TO
	MOVSI	T1,(CT.UUO)	;UUO IN PROGRESS
	PUSHJ	P,DELCTX	;DELETE THE CONTEXT
	  POPJ	P,		;FAILED--ERROR CODE IN T1
	JRST	CPOPJ1##	;RETURN AND CONTINUE PREVIOUS CONTEXT
REDDAT:	PUSHJ	P,INIDAT	;SET UP TO READ DATA BUFFER
	  POPJ	P,		;PROPAGATE ERROR BACK
	JUMPE	T2,XITDAT	;ANY DATA TO MOVE?

REDDA1:	MOVE	T1,(T3)		;GET A WORD
	PUSHJ	P,PUTWD1##	;PUT A WORD
	ADDI	T3,1		;POINT TO NEXT STORAGE LOCATION
	AOBJN	T2,REDDA1	;LOOP
	MOVSI	T1,(CT.DBT)	;GET THE TRUNCATION BIT
	ANDCAM	T1,.CTRET(P1)	;CAN NEVER HAPPEN ON A READ
	JRST	XITDAT		;DONE


WRTDAT:	PUSHJ	P,INIDAT	;SET UP TO WRITE DATA BUFFER
	  POPJ	P,		;PROPAGATE ERROR BACK
	JUMPE	T2,XITDAT	;ANY DATA TO MOVE?

WRTDA1:	PUSHJ	P,GETWD1##	;GET A WORD
	MOVEM	T1,(T3)		;PUT A WORD
	ADDI	T3,1		;POINT TO NEXT STORAGE LOCATION
	AOBJN	T2,WRTDA1	;LOPO
	JRST	XITDAT		;DONE


; COMMON INITIALIZATION CODE FOR READ AND WRITE DATA FUNCTIONS
INIDAT:	SKIPN	T4,.CTSUP(P1)	;HAVE A SUPERIOR CONTEXT?
	JRST	ERRNSC		;NO
	CAIG	P4,.CTDBA	;UUO BLOCK CONTAIN LENGTH AND ADDRESS WORDS?
	JRST	ERRNEA		;NO--NOT ENOUGH ARGUMENTS
	MOVSI	T1,(CT.DAT)	;WE'LL BE RETURNING DATA WORDS
	HLRZ	T2,.CTDTL(T4)	;GET ACTUAL LENGTH
	HRRZ	T3,.CTDTL(P1)	;GET REQUESTED LENGTH
	CAMG	T2,T3		;REQUESTED GREATER THAN ACTUAL?
	SKIPA	T3,T2		;NO--ONLY MOVE AS MUCH DATA AS IS AVAILABLE
	TLO	T1,(CT.DBT)	;DATA BLOCK TRUNCATED
	MOVEM	T1,.CTRET(P1)	;SAVE FOR UUO EXIT
	MOVN	T2,T3		;USE THE SMALLER OF THE TWO LENGTHS
	HRLZS	T2		;MAKE -LEN,,0
	SKIPE	T3,.CTDTE(T4)	;DO WE HAVE A BLOCK?
	MOVE	M,.CTDTU(P1)	;GET ADDRESS OF BLOCK IN USER CORE
	SOJGE	M,CPOPJ1##	;ADJUST BY ONE AND RETURN
	JRST	ERRNDA		;NO DATA BLOCK AVAILABLE


; COMMON EXIT CODE FOR READ AND WRITE DATA FUNCTIONS
XITDAT:	MOVE	T1,.CTRET(P1)	;GET RETURNED AC FLAGS, ETC.
	DPB	T2,PCTXDW	;STORE COUNT FOR USER
	PJRST	PUTAC1		;PUT IN USER'S AC AND RETURN
; READ QUOTAS FOR SYSTEM OR ANY JOB
REDQTA:	PUSHJ	P,INIQTA	;SET UP FOR QUOTA READING
	  POPJ	P,		;PROPAGATE ERROR BACK
	SKIPN	J		;JOB?
	SKIPA	T1,SYSCCQ	;SYSTEM
	LDB	T1,PCTXCQ	;GET CONTEXT QUOTA
	PUSHJ	P,PUTEW1##	;STORE IT
	  JRST	ERRACS		;ADDRESS CHECK STORING ANSWERS
	AOBJP	T2,XITQTA	;BUFFER COUNT RUN OUT?
	SKIPN	J		;JOB?
	SKIPA	T1,SYSCPQ	;SYSTEM
	LDB	T1,PCTXPQ	;GET SAVED PAGE QUOTA
	PUSHJ	P,PUTEW1##	;STORE IT
	  JRST	ERRACS		;ADDRESS CHECK STORING ANSWERS
	AOJA	T2,XITQTA	;FIX UP USER'S AC AND RETURN



; SET QUOTAS FOR SYSTEM OR ANY JOB
SETQTA:	PUSHJ	P,PRVJC##	;GODLY?
	  SKIPA			;LETTERRIP
	JRST	ERRNPV		;MUST BE [1,2] OR JACCT
	PUSHJ	P,INIQTA	;SET UP FOR QUOTA SETTING
	  POPJ	P,		;PROPAGATE ERROR BACK
	PUSHJ	P,GETEW1##	;GET CONTEXT QUOTA
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	SKIPE	J		;JOB?
	DPB	T1,PCTXCQ	;SET JOB QUOTA
	SKIPN	J		;SYSTEM?
	MOVEM	T1,SYSCCQ	;SET SYSTEM-WIDE QUOTA
	AOBJP	T2,XITQTA	;BUFFER COUNT RUN OUT?
	PUSHJ	P,GETEW1##	;GET SAVED PAGES QUOTA
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	SKIPE	J		;JOB?
	DPB	T1,PCTXPQ	;SET JOB QUOTA
	SKIPN	J		;SYSTEM?
	MOVEM	T1,SYSCPQ	;SET SYSTEM-WIDE QUOTA
	AOJA	T2,XITQTA	;FIX UP USER'S AC AND RETURN
; COMMON SETUP CODE FOR SET AND READ QUOTA FUNCTIONS
INIQTA:	CAIG	P4,.CTDBA	;HAVE A DATA BUFFER LENGTH AND ADDRESS?
	JRST	ERRNEA		;NOT ENOUGH ARGUMENTS
IFN FTXMON,<PUSHJ P,SSPCS##>	;SAVE PCS
	HRRI	M,.CTDBL(P2)	;POINT TO DATA BUFFER LENGTH WORD
	HLL	M,P2		;INCLUDE SECTION NUMBER
	MOVE	T1,M		;SET UP CALL
	PUSHJ	P,SXPCS##	;SET PCS ACCORDINGLY
	  JRST	ERRACR		;ADDRESS CHECK
	PUSHJ	P,GETEWD##	;GET ADDRESS
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	SKIPG	T2,T1		;SAVE LENGTH
	JRST	ERRNEA		;NOT ENOUGH ARGUMENTS
	MOVNS	T2		;NEGATE
	HRLZS	T2		;MAKE IT -COUNT,,0
	PUSHJ	P,GETEW1##	;GET ADDRESS
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	MOVE	M,T1		;POINT M AT USER'S BUFFER
	PUSHJ	P,SXPCS##	;SET PCS ACCORDINGLY
	  JRST	ERRACR		;ADDRESS CHECK
	PUSHJ	P,GETEWD##	;GET JOB NUMBER IN T1
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS
	AOBJP	T2,ERRNEA	;NEED AT LEAST TWO WORDS
	JUMPE	J,CPOPJ1##	;RETURN IF READING OR SETTING SYSTEM QUOTAS
	CAMN	T1,[EXP -1]	;EXCEPTION
	MOVE	T1,.CPJOB##	;-1 MEANS SELF
	MOVE	J,T1		;LOAD JOB NUMBER
	PUSHJ	P,FNDPDB##	;SET UP W WITH THE TARGET PDB
	  JRST	ERRIJN		;BAD JOB NUMBER
	PUSHJ	P,PUTWDU##	;ALWAYS RETURN JOB NUMBER (INCASE -1 GIVEN)
	JUMPE	J,CPOPJ1##	;NO INTERLOCKING NEEDED IF NULL JOB
	CAME	J,.CPJOB##	;DOING TO SELF?
	PUSHJ	P,UPCX		;PREVENT RACES
	JRST	CPOPJ1##	;INDICATE JOB QUOTAS AND RETURN


; COMMON EXIT CODE FOR SET AND READ QUOTA FUNCTIONS
XITQTA:	SKIPE	J		;NULL JOB?
	CAME	J,.CPJOB##	;DOING TO SELF?
	SKIPA			;NO INTERLOCKING NEEDED
	PUSHJ	P,DWNCX		;GIVE UP CX RESOURCE
	MOVSI	T1,(CT.DAT)	;INDICATE STUFF IN THE DATA BUFFER
	DPB	T2,PCTXDW	;STORE WORDS RETURNED
	PJRST	PUTAC1		;STUFF INTO THE USER'S AC AND RETURN
; RETURN A DIRECTORY OF THE CONTEXT CHAINS FOR A JOB
; DATA IS STORED IN THE USER'S DATA BUFFER IN THE FOLLOWING
; FORMAT:
;	BUFFER/	EXP	JOB#		;SUPPLIED BY USER
;		EXP	WORDS RETURNED
;		BYTE(9) CTX1, INF1, INF2, ..., NUL
;		BYTE(9) CTX2, INF1, INF2, ..., NUL
;		 .	.
;		 .	.
;		 .	.

DIRECT:
IFN FTXMON,<PUSHJ P,SSPCS##>	;SAVE PCS
	PUSHJ	P,DIRINI	;INIT DATA BUFFER STUFF
	  POPJ	P,		;CAN'T
	TLNN	M,(IFIW)	;LOCAL REFERENCE?
	AOSA	M		;NO
	HRRI	M,1(M)		;ADVANCE BUT DON'T CROSS SECTION BOUNDRIES
	SETZ	P2,		;CLEAR MAP STORAGE ADDRESS
	PUSHJ	P,FNDPDB##	;FIND TARGET JOB'S PDB
	  JRST	DIRIJN		;ILLEGAL JOB NUMBER
	CAME	J,.CPJOB##	;IS IT US?
	PUSHJ	P,UPCX		;PDB ACCESS REQUIRES CX RESOURCE
	MOVEI	T2,2*CTXMAP##	;NUMBER OF WORDS FOR TWO MAPS
	PUSHJ	P,GTFWDC##	;GET FUNNY WORDS, CACHED
	  JRST	DIRNCS		;NOT ENOUGH CORE
IFE FTXMON,<
	HRLZ	T3,T1		;GET STARTING ADDRESS
	HRRI	T3,1(T1)	;MAKE A BLT POINTER
	SETZM	(T1)		;CLEAR FIRST WORD
	BLT	T3,<2*CTXMAP##>-1(T1) ;CLEAR BOTH MAPS
> ;END IFE FTXMON
IFN FTXMON,<
	MOVEI	T2,2*CTXMAP##-1	;LENGTH MAY HAVE BEEN CLOBBERED
	MOVE	T3,T1		;COPY STARTING ADDRESS
	AOS	T4,T1		;MAKE A BLT POINTER
	SETZM	(T3)		;ZERO FIRST WORD
	EXTEND	T2,[XBLT]	;ZREO BOTH MAPS
> ;END IFN FTXMON

	PUSH	P,M		;SAVE DATA BUFFER ADDRESS FOR LATER
	PUSH	P,P3		;SAVE DATA BUFFER LENGTH
	PUSH	P,P3		;SAVE WORKING COPY
	MOVE	P1,.PDSAC##(W)	;POINT TO START OF CHAIN
	SOS	P2,T1		;COPY CONTEXT INFERIOR MAP ADDRESS
	IOR	P2,DIRPTR	;MAKE A BYTE POINTER
	MOVE	P3,P2		;ANOTHER COPY
	ADDI	P3,CTXMAP##	;POINT TO CONTEXT HEADER MAP
	MOVNI	T1,1		;-1
	EXCH	T1,P3		;SWAP SO ADJBP PUTS RESULT IN P3
	ADJBP	P3,T1		;ACCOUNT FOR IDPB STORAGE
	MOVNI	U,1		;FLAG HAVING MAP STORAGE NOW
; HERE TO SCAN CONTEXT CHAIN(S) AND BUILD TWO MAPS.
;
; P3 CONTAINS A BYTE POINTER TO THE "HEAD OF CHAIN" MAP.  EACH SUCESSIVE
; BYTE WITHIN THE MAP HOLDS THE CONTEXT NUMBER OF ITS IMMEDIATE INFERIOR
; CONTEXT.  A ZERO BYTE INDICATES THERE ARE NO MORE CHAINS.
;
; P2 CONTAINS A BYTE POINTER TO THE "INFERIOR" MAP.  THIS MAP IS INDEXED
; BY THE CONTEXT NUMBERS.  A ZERO BYTE INDICATES THE END OF THE CHAIN.
;
; TO FOLLOW A CONTEXT CHAIN FROM THE HEAD OF THE CHAIN TO THE MOST INFERIOR
; CONTEXT, FIRST PICK UP A CONTEXT NUMBER FROM THE "HEAD OF CHAIN" MAP.
; THEN INDEX INTO THE "INFERIOR" MAP USING SAID CONTEXT NUMBER.  THIS BYTE
; WILL CONTAIN THE CONTEXT NUMBER OF THE NEXT INFERIOR, WHICH AGAIN MAY BE
; USED TO INDEX INTO THE "INFERIOR" MAP.  EVENTUALLY, A CONTEXT NUMBER OF
; ZERO WILL BE FOUND, INDICATING THE END OF THE CHAIN.

DIREC1:	MOVE	T1,P1		;SAVE STARTING BLOCK ADDRESS
	LDB	T3,PCTXNO	;GET CURRENT CONTEXT NUMBER
	SKIPN	T2,.CTSUP(P1)	;THIS BLOCK HAVE A SUPERIOR?
	JRST	DIREC2		;NO
	MOVE	P1,T2		;POINT TO SUPERIOR
	LDB	T4,PCTXNO	;GET SUPERIOR CONTEXT NUMBER
	ADJBP	T4,P2		;POSITION IN INFERIOR MAP
	DPB	T3,T4		;STORE INFERIOR CONTEXT NUMBER
	JRST	DIREC3		;SEE IF MORE CONTEXT BLOCKS

DIREC2:	IDPB	T3,P3		;STORE TOP LEVEL CONTEXT NUMBER

DIREC3:	SKIPE	P1,.CTNXT(T1)	;POINT TO NEXT BLOCK
	JRST	DIREC1		;FOLLOW CHAINS
	MOVNI	P3,1		;-1
	ADJBP	P3,P2		;POINT TO START OF INFERIOR MAP
	ADDI	P3,CTXMAP##	;ADVANCE TO CONTEXT HEADER MAP

DIREC4:	ILDB	T1,P3		;GET STARTING CONTEXT NUMBER OF A CHAIN
	JUMPE	T1,DIREC8	;DONE?
	PUSHJ	P,DIRSET	;SET UP BYTE POINTER AND COUNT FOR STORAGE
	IDPB	T1,T2		;STORE HEAD OF CHAIN
	SOJA	T3,DIREC6	;ENTER LOOP

DIREC5:	PUSHJ	P,DIRSET	;SET UP BYTE POINTER AND COUNT FOR STORAGE

DIREC6:	ADJBP	T1,P2		;INDEX INTO INFERIOR MAP
	MOVE	T4,T1		;COPY UPDATED BYTE POINTER
	LDB	T1,T4		;GET NEXT INFERIOR CONTEXT NUMBER
	IDPB	T1,T2		;SAVE TEMPORARILY
	JUMPE	T1,DIREC7	;END OF CHAIN?
	SOJG	T3,DIREC6	;LOOP BACK FOR ANOTHER

DIREC7:	EXCH	T1,P4		;SAVE T1, GET WORD OF BYTES
	PUSHJ	P,DIRPUT	;STORE IN DATA BUFFER
	  JRST	DIRACP		;ADDRESS CHECK??
	SKIPE	T1,P4		;RESTORE T1
	JRST	DIREC5		;LOOP IF MORE INFERIORS
	JRST	DIREC4		;ELSE SEE IF MORE CHAINS TO TRAVERSE
; HERE TO FINISH UP
DIREC8:	POP	P,T1		;GET COUNT OF WORDS STORED (SORT OF)
	POP	P,T2		;AND COUNT OF DATA WORDS AVAILABLE
	SUBI	T1,(T2)		;COMPUTE TOTAL WORDS NEEDED TO RETURN ALL DATA
	POP	P,M		;GET DATA BUFFER ADDRESS BACK
	PUSHJ	P,PUTEWD##	;STORE
	  JRST	DIRACS		;ADDRESS CHECK STORING ANSWERS
	PUSHJ	P,DIRRST	;RESET THINGS
	MOVSI	T3,(CT.DAT)	;DATA BEING RETURNED
	ADDI	T1,2		;ACCOUNT FOR OVERHEAD WORDS
	SKIPGE	T1		;TRUNCATED?
	TLO	T3,(CT.DBT)	;YES
	CAIL	T1,(T2)		;TRIED TO RETURN MORE THAN DATA BUFFER LENGTH?
	MOVE	T1,T2		;YES--GET LENGTH SUPPLIED BY USER
	EXCH	T1,T3		;SWAP SO WE CAN USE APPROPRIATE BYTE POINTER
	DPB	T3,PCTXDW	;STORE WORDS RETURNED
	PJRST	PUTAC1		;PUT C(T1) IN UUO AC AND RETURN
; INIT DATA BUFFER POINTERS
DIRINI:	CAIG	P4,.CTDBA	;HAVE A DATA BUFFER LENGTH AND ADDRESS?
	JRST	ERRNEA		;NOT ENOUGH ARGUMENTS
	HRRI	M,.CTDBL(P2)	;POINT TO DATA BUFFER LENGTH WORD
	HLL	M,P2		;INCLUDE SECTION NUMBER
	SOS	T1,M		;SET UP CALL
	PUSHJ	P,SXPCS##	;SET PCS ACCORDINALY
	  JRST	ERRACR		;ADDRESS CHECK
	PUSHJ	P,GETEW1##	;GET DATA BUFFER LENGTH
	  JRST	ERRACR		;ADDRESS CHECK
	SKIPLE	P3,T1		;COPY LENGTH
	CAIGE	P3,2		;NEED AT LEAST TWO WORDS
	JRST	ERRNEA		;NOT ENOUGH ARGUMENTS
	PUSHJ	P,GETEW1##	;GET ADDRESS OF DATA BUFFER
	  JRST	ERRACR		;ADDRESS CHECK
	MOVE	M,T1		;COPY IT
	PUSHJ	P,SXPCS##	;SET INITIAL PCS
	  JRST	ERRACR		;ILLEGAL ADDRESS
	PUSHJ	P,GETEWD##	;GET FIRST WORD (TARGET JOB NUMBER)
	  JRST	ERRACR		;ADDRESS CHECK READING ARGUMENT
	CAMN	T1,[EXP -1]	;IS IT US?
	MOVE	T1,.CPJOB##	;YES
	JUMPLE	T1,ERRIJN	;CHECK FOR ILLEGAL JOB NUMBERS
	PUSHJ	P,PUTEWD##	;UPDATE DATA BUFFER INCASE -1 GIVEN
	  JRST	ERRACS		;ADDRESS CHECK STORING ANSWER
	MOVE	J,T1		;GET JOB IN QUESTION
	JRST	CPOPJ1##	;RETURN
; RETURN ADDRESS CHECK ERROR AFTER PHASING STACK
DIRACP:	POP	P,(P)		;PRUNE GARBAGE
	POP	P,(P)		; OFF THE
	POP	P,(P)		;  STACK


; RETURN ADDRESS CHECK ERROR
DIRACS:	PUSHJ	P,DIRRST	;RESET THINGS
	JRST	ERRACS		;ADDRESS CHECK STORING ANSWERS


; RETURN ILLEGAL JOB NUMBER ERROR
DIRIJN:	PUSHJ	P,DIRRST	;RESET THINGS
	JRST	ERRIJN		;ILLEGAL JOB NUMBER


; RETURN NOT ENOUGH CORE ERROR
DIRNCS:	PUSHJ	P,DIRRST	;RESET THINGS
	JRST	ERRNCS		;NOT ENOUGH CORE


; HERE TO RESET THINGS ON ERRORS OR FINAL DIRECTORY FUNCTION EXIT
DIRRST:	CAME	J,.CPJOB##	;IS IT US?
	PUSHJ	P,DWNCX		;PDB ACCESS REQUIRED CX RESOURCE
	MOVE	J,.CPJOB##	;RESET OUR JOB NUMBER
	PUSHJ	P,FNDPDS##	;POINT TO OUR PDB
	MOVE	P1,.PDCTC##(W)	;RESET P1 FOR ERROR RETURN
	JUMPE	P2,CPOPJ##	;RETURN IF NOT OWNING ANY MAPS
	PUSH	P,T1		;SAVE T1
	PUSH	P,T2		;SAVE T2
	MOVEI	T1,2*CTXMAP##	;NUMBER OF WORDS FOR TWO MAPS
	HRRZ	T2,P2		;POINT TO MAPS
	PUSHJ	P,GVFWDS##	;GIVE UP FUNNY SPACE
	JRST	TTPOPJ##	;AND RETURN


; SET UP BYTE POINTER AND COUNT FOR STORAGE INTO USER'S DATA BUFFER
DIRSET:	MOVNI	T2,1		;-1
	MOVE	T3,DIRPTR	;GET BYTE POINTER FOR STORAGE
	HRRI	T3,P4		;TEMPORARY PLACE WHILE DOING IDPBS
	ADJBP	T2,T3		;ACCOUNT FOR IDPB STORAGE
	MOVEI	T3,CTXBPW##	;BYTES PER WORD
	SETZ	P4,		;ZERO TEMPORARY STORAGE
	POPJ	P,		;AND RETURN
; ROUTINE TO STORE A WORD IN THE DATA BUFFER
DIRPUT:	SOSGE	-2(P)		;ROOM TO STORE?
	JRST	DIRPU1		;NO--TRY TO PREVENT A KAF
	PUSH	P,J		;SAVE J
	MOVE	J,.CPJOB##	;INCASE LOOKING AT ANOTHER JOB
	PUSHJ	P,PUTEW1##	;PUT C(T1) INTO DATA BUFFER
	  JRST	JPOPJ##		;ADDRESS CHECK??
	POP	P,J		;RESTORE JOB WE'RE LOOKING AT

; HERE TO PREVENT KAF STOPCODES.  SCDCHK WILL BE CALLED EVERY
; CTXBPW*17 TIMES THROUGH THE CONTEXT NUMBER STORAGE LOOP.
DIRPU1:	EXCH	T1,-1(P)	;SAVE T1 AND GET COUNT
	TRNN	T1,17		;TIME TO TAKE A REST?
	PUSHJ	P,SCDCHK##	;GIVE SOMEONE ELSE A CHANCE TO RUN
	EXCH	T1,-1(P)	;RESTORE T1 AND COUNT
	JRST	CPOPJ1##	;RETURN
; RETURN INFORMATION ABOUT A SINGLE CONTEXT
; DATA IS STORED IN THE USER'S DATA BUFFER IN THE FOLLOWING
; FORMAT:
;	BUFFER/	EXP	JOB#		;SUPPLIED BY THE USER
;		EXP	CONTEXT#	;SUPPLIED BY THE USR
;		SIXBIT	/CONTEXT-NAME/	;TARGET CONTEXT'S NAME
;		EXP	SUP#		;SUPERIOR'S CONTEXT NUMBER
;		SIXBIT	/SUP-NAME/	;SUPERIOR'S CONTEXT NAME
;		SIXBIT	/PROGRAM/	;PROGRAM NAME
;		EXP	TIME		;IDLE TIME IN TICKS
;
; *** NOTE ***
; THE INTENT OF THIS FUNCTION IS TO PROVIDE THE SAME INFORMATION
; CURRENTLY AVAILABLE AT MONITOR LEVEL USING THE CONTEXT COMMAND.
; ALTHOUGH IT'S TEMPTING TO RETURN ADDITIONAL INFORMATION, A MORE
; GENERALIZED MECHANISM SHOULD BE EMPLOYED RATHER THAN EXPANDING
; THIS FUNCTION OF THE CONTEXT UUO.  PERHAPS AN EXTENSION TO THE
; GETTAB UUO IS NEEDED.  IN ANY CASE, WE'LL SAVE THIS FOR ANOTHER
; MONITOR RELEASE.

INFORM:
IFN FTXMON,<PUSHJ P,SSPCS##>	;SAVE PCS
	PUSHJ	P,DIRINI	;INIT DATA BUFFER POINTERS
	  POPJ	P,		;PROPAGATE ERROR
	SUBI	P3,1		;ACCOUNT FOR JOB NUMBER WORD ALREADY STORED
	CAME	J,.CPJOB##	;IS IT US?
	PUSHJ	P,UPCX		;PDB ACCESS REQUIRES CX RESOURCE
	PUSHJ	P,FNDPDB##	;FIND TARGET JOB'S PDB
	  JRST	INFIJN		;ILLEGAL JOB NUMBER
	MOVE	P1,.PDCTC##(W)	;POINT TO CURRENT BLOCK FOR TARGET JOB
	PUSHJ	P,GETEW1##	;GET NEXT WORD (CONTEXT NUMBER)
	  JRST	INFACR		;ADDRESS CHECK READING ARGUMENTS
	SUBI	M,1		;SET UP M FOR NEXT STORE
	SKIPN	T1		;CONTEXT ZERO REQUESTED?
	LDB	T1,PCTXNO	;USER WANTS THE CURRENT ONE
	CAIL	T1,1		;RANGE
	CAILE	T1,CTXMAX##	; CHECK
	JRST	INFICN		;PRELIMINARY CHECK SAYS NUMBER IS NO GOOD
	LSH	T1,CTXLSH##	;POSITION
	IOR	T1,J		;FORM JCH
	PUSHJ	P,JBCHCT	;FIND TARGET CONTEXT BLOCK
	  JRST	INFICN		;ILLEGAL CONTEXT NUMBER
	  JFCL			;DON'T CARE IF IT'S THE CURRENT ONE
	LSH	T1,-CTXLSH##	;KEEP ONLY THE CONTEXT NUMBER
	PUSHJ	P,INFPUT	;STORE INCASE CONTEXT ZERO WAS SPECIFIED
	  JRST	INFACS		;ADDRESS CHECK
	MOVSI	P2,-INFLEN	;AOBJN POINTER

INFOR1:	XCT	INFTAB(P2)	;GET A WORD OF DATA
	PUSHJ	P,INFPUT	;PUT A WORD OF DATA
	  JRST	INFACS		;ADDRESS CHECK STORING ANSWERS
	AOBJN	P2,INFOR1	;LOOP
	PUSHJ	P,INFRST	;RESET THINGS
	JRST	CPOPJ1##	;RETURN
INFTAB:	MOVE	T1,.CTCBN(P1)	;TARGET CONTEXT'S NAME
	PUSHJ	P,INFNUM	;SUPERIOR'S CONTEXT NUMBER
	PUSHJ	P,INFNAM	;SUPERIOR'S CONTEXT NAME
	MOVE	T1,.CTPRG(P1)	;PROGRAM NAME
	PUSHJ	P,INFIDL	;IDLE TIME IN TICKS
INFLEN==.-INFTAB		;LENGTH OF TABLE


; SUPERIOR'S CONTEXT NUMBER
INFNUM:	SKIPN	T1,.CTSUP(P1)	;GET SUPERIOR CONTEXT BLOCK ADDRESS
	POPJ	P,		;THERE IS NONE
	MOVE	T2,T1		;COPY
	EXCH	T2,P1		;SWAP WITH CURRENT
	LDB	T1,PCTXNO	;GET CONTEXT NUMBER
	MOVE	P1,T2		;REPLACE
	POPJ	P,		;RETURN


; SUPERIOR'S CONTEXT NAME
INFNAM:	SKIPE	T1,.CTSUP(P1)	;GET SUPERIOR CONTEXT BLOCK ADDRESS
	MOVE	T1,.CTCBN(T1)	;GET NAME
	POPJ	P,		;RETURN


; IDLE TIME IN TICKS
INFIDL:	MOVE	T1,UPTIME##	;GET SYSTEM UPTIME
	SUB	T1,.CTIDL(P1)	;COMPUTE IDLE TIME FOR THIS CONTEXT
	POPJ	P,		;RETURN
; RETURN ADDRESS CHECK ERROR
INFACR:	PUSHJ	P,INFRST	;RESET THINGS
	JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS


; RETURN ADDRESS CHECK ERROR
INFACS:	PUSHJ	P,INFRST	;RESET THINGS
	JRST	ERRACS		;ADDRESS CHECK STORING ANSWERS


; RETURN ILLEGAL JOB NUMBER ERROR
INFIJN:	PUSHJ	P,INFRST	;RESET THINGS
	JRST	ERRIJN		;ILLEGAL JOB NUMBER


; RETURN ILLEGAL CONTEXT NUMBER
INFICN:	PUSHJ	P,INFRST	;RESET THINGS
	JRST	ERRICN		;ILLEGAL CONTEXT NUMBER


; HERE TO RESET THINGS ON ERRORS OR FINAL INFORMATION FUNCTION EXIT
INFRST:	CAME	J,.CPJOB##	;IS IT US?
	PUSHJ	P,DWNCX		;PDB ACCESS REQUIRED CX RESOURCE
	MOVE	J,.CPJOB##	;RESET OUR JOB NUMBER
	PUSHJ	P,FNDPDS##	;POINT TO OUR PDB
	MOVE	P1,.PDCTC##(W)	;RESET P1 FOR ERROR RETURN
	POPJ	P,		;RETURN


; ROUTINE TO STORE A WORD IN THE DATA BUFFER
INFPUT:	SOJL	P3,CPOPJ1##	;RETURN IF NO MORE ROOM
	PUSH	P,J		;SAVE J
	MOVE	J,.CPJOB##	;INCASE LOOKING AT ANOTHER JOB
	PUSHJ	P,PUTEW1##	;PUT C(T1) INTO DATA BUFFER
	  JRST	JPOPJ##		;ADDRESS CHECK??
	POP	P,J		;RESTORE JOB WE'RE LOOKING AT
	JRST	CPOPJ1##	;RETURN

SUBTTL	UTILITY ROUTINES -- CREBLK - CREATE A CONTEXT BLOCK


CREBLK:
IFN FTXMON,<
	PUSHJ	P,UUOLVL##	;SKIP IF AT UUO LEVEL (CAN BLOCK)
	SKIPN	T1,RESBLK	;HAVE ANY RESERVED CONTEXT BLOCKS?
	JRST	CREBL1		;GO ALLOCATE CORE
	MOVE	T2,.CTNXT(T1)	;GET POINTER TO NEXT BLOCK (IF ANY)
	MOVEM	T2,RESBLK	;PUT AT HEAD OF CHAIN
	SOS	RESCNT		;COUNT DOWN
	JRST	CREBL2		;SKIP CORE ALLOCATION STUFF
CREBL1:
> ;END IFN FTXMON

	MOVEI	T2,.CTSIZ	;GET LENGTH OF CONTEXT SAVE BLOCK
	PUSHJ	P,GETCOR	;MAKE A BLOCK
	  POPJ	P,		;NO AVAILABLE CORE

CREBL2:	MOVE	P1,T1		;COPY NEW BLOCK ADDRESS
	SETZM	@P1		;CLEAR FIRST WORD OF CONTEXT BLOCK
IFE FTXMON,<
	MOVSI	T1,(P1)		;GET START ADDRESS
	HRRI	T1,1(P1)	;MAKE A BLT POINTER
	BLT	T1,.CTSIZ-1(P1)	;CLEAR THE CONTEXT BLOCK
> ;END IFE FTXMON
IFN FTXMON,<
	MOVEI	T1,.CTSIZ-1	;LENGTH OF TRANSFER
	MOVE	T2,P1		;START ADDR
	XMOVEI	T3,1(P1)	;MAKE A BLT POINTER
	EXTEND	T1,[XBLT]	;ZAP BLOCK
> ;END IFN FTXMON
	SKIPE	T1,.PDSAC##(W)	;POINT TO START OF CHAIN
	JRST	CREBL3		;ONWARD
	MOVEM	P1,.PDSAC##(W)	;FIRST BLOCK IN CHAIN
	JRST	CREBL5		;GO FINISH UP

CREBL3:	SKIPN	T2,.CTNXT(T1)	;GET ADDRESS OF NEXT BLOCK
	JRST	CREBL4		;END OF CHAIN
	MOVE	T1,T2		;COPY ADDRESS
	JRST	CREBL3		;SEARCH FOR END

CREBL4:	MOVEM	P1,.CTNXT(T1)	;LINK NEW BLOCK AT END OF CHAIN
	MOVEM	T1,.CTPRV(P1)	;LINK BACK TO PREVIOUS BLOCK
	MOVE	T2,.PDCTC##(W)	;GET CURRENT CONTEXT BLOCK ADDRESS
	MOVEM	T2,.CTLAS(P1)	;SAVE POINTER TO CONTEXT BLOCK WITH ARGS
	MOVE	T3,.CTTCR(T1)	;GET TMPCOR FILE LENGTH,,NAME
	MOVEM	T3,.CTTCR(P1)	;SAVE IN NEW CONTEXT BLOCK
	MOVE	T3,.CTTCE(T1)	;GET TMPCORE FILE ADDRESS (EXEC)
	MOVEM	T3,.CTTCE(P1)	;COPY TO NEW CONTEXT BLOCK
IFE FTXMON,<
	MOVE	T2,.CTLAS(P1)	;GET PREVIOUS BLOCK ADDRESS
	MOVSI	T1,.CTRUA(T2)	;POINT TO RUN UUO ARGUMENTS
	HRRI	T1,.CTRUA(P1)	;START OF RUN STORAGE
	BLT	T1,.CTRUA+1+6+2+MAXLVL-1(P1) ;COPY TO NEW BLOCK
> ;END IFE FTXMON
IFN FTXMON,<
	MOVEI	T1,1+6+2+MAXLVL-1 ;NUMBER OF WORDS TO COPY
	MOVE	T2,.CTLAS(P1)	;POINT TO PREVIOUS BLOCK
	XMOVEI	T2,.CTRUA(T2)	;FROM HERE
	XMOVEI	T3,.CTRUA(P1)	;INTO HERE
	EXTEND	T1,[XBLT]	;COPY TO NEW BLOCK
> ;END IFN FTXMON
	MOVE	T2,.CTLAS(P1)	;POINT TO PREVIOUS BLOCK
	SETZ	T1,		;CLEAR FOR NEXT TIME AND
	EXCH	T1,.CTNCN(T2)	; GET THE NEW CONTEXT NAME
	PUSHJ	P,NAMECT	;ASSIGN IT

CREBL5:	PUSHJ	P,INTLVL##	;RUNNING AT INTERRUPT LEVEL?
	  SKIPN	T1,.CPJCH##	;NO--GET JCH (CREATOR OF THIS BLOCK)
	MOVE	T1,J		;MUST BE A NEW JOB
	HRLI	T1,'CTX'	;INCLUDE IDENTIFIER
	MOVEM	T1,.CTJCH(P1)	;SAVE IN BLOCK FOR TRACKING PURPOSES
	MOVEM	P1,.PDCTC##(W)	;SET NEW BLOCK AS CURRENT ONE
	JRST	CPOPJ1##	;AND RETURN
SUBTTL	UTILITY ROUTINES -- DELBLK - DELETE A CONTEXT BLOCK


DELBLK:	MOVE	P1,.PDCTC##(W)	;GET CURRENT BLOCK ADDRESS
	MOVE	T1,.CTNXT(P1)	;GET LINK TO NEXT BLOCK
	SKIPE	T2,.CTPRV(P1)	;GET LINK TO PREVIOUS BLOCK
	MOVEM	T1,.CTNXT(T2)	;LINK PREVIOUS TO NEXT
	SKIPE	T1		;CHECK FOR END OF CHAIN
	MOVEM	T2,.CTPRV(T1)	;LINK NEXT TO PREVIOUS
	SKIPN	T2		;FIRST BLOCK GO AWAY?
	MOVEM	T1,.PDSAC##(W)	;YES--LINK THE NEXT ONE AT THE START
	SKIPN	T1,.CTSUP(P1)	;GET SUPERIOR CONTEXT FOR THE ONE TO BE DELETED
	MOVE	T1,.PDSAC##(W)	;ELSE POINT TO THE START OF THE CHAIN
	MOVEM	T1,.PDCTC##(W)	;MAKE IT THE NEW CURRENT CONTEXT
IFN FTXMON,<
	CAMGE	P1,SYSSIZ##	;BLOCK COME FROM LOW CORE?
	JRST	DELBL1		;YES--ALWAYS RELEASE IT
	CTXLOK			;INTERLOCK
	MOVE	T1,RESCNT	;GET COUNT RESERVED CONTEXT BLOCKS
IFN FTMP,<SKIPGE MMREQ##>	;CAN WE GET THE MM?
	CAMGE	T1,RESMAX	;HAVE ENOUGH?
	AOJA	T1,DELBL2	;PUT ON RESERVED CHAIN
	CTXNLK			;RELEASE INTERLOCK
DELBL1:
> ;END IFN FTXMON
	MOVEI	T1,.CTSIZ	;NUMBER OF WORDS
	MOVE	T2,P1		;ADDRESS OF CONTEXT BLOCK
	PUSHJ	P,GIVCOR	;RETURN CORE
	JRST	DELBL5		;AND FINISH UP

IFN FTXMON,<
DELBL2:	MOVEM	T1,RESCNT	;UPDATE COUNT
	MOVEI	T1,RESBLK-.CTNXT ;PRESET STORAGE

DELBL3:	SKIPN	T2,.CTNXT(T1)	;GET ADDRESS OF NEXT BLOCK
	JRST	DELBL4		;END OF CHAIN
	MOVE	T1,T2		;COPY ADDRESS
	JRST	DELBL3		;SEARCH FOR END

DELBL4:	MOVEM	P1,.CTNXT(T1)	;LINK NEW BLOCK TO END OF CHAIN
	SETZM	.CTNXT(P1)	;CLEAR OLD LINK SINCE AT END OF CHAIN
	CTXNLK			;RELEASE INTERLOCK
> ;END IFN FTXMON

DELBL5:	MOVE	P1,.PDCTC##(W)	;RESET CURRENT CONTEXT POINTER
	POPJ	P,		;AND RETURN
SUBTTL	UTILITY ROUTINES -- LSTBLK - LIST CONTEXT BLOCK STATUS


LSTBLK:	MOVEI	T1,[ASCIZ |  |]	;ASSUME NOT THE CURRENT ONE
	CAMN	P1,.PDCTC##(W)	;IS IT?
	MOVEI	T1,[ASCIZ |* |]	;YES
	PUSHJ	P,CONMES##	;TYPE JUNK
	MOVE	T4,.CTCBN(P1)	;GET CONTEXT NAME
	PUSHJ	P,LSTCNM	;TYPE IT
	PUSHJ	P,PRSPC##	;SPACE OVER
	LDB	T2,PCTXNO	;GET CONTEXT NUMBER
	PUSHJ	P,LSTCNO	;TYPE IT
	PUSHJ	P,LSTSPC	;SPACE OVER
	SKIPN	T1,.CTSUP(P1)	;GET SUPERIOR CONTEXT ADDRESS
	JRST	LSTBL1		;THERE ISN'T ONE
	MOVE	T4,.CTCBN(T1)	;GET SUPERIOR CONTEXT NAME
	PUSHJ	P,LSTCNM	;TYPE IT
	PUSHJ	P,PRSPC##	;SPACE OVER
	PUSH	P,P1		;SAVE SUPERIOR
	MOVE	P1,.CTSUP(P1)	;POINT TO SUPERIOR CONTEXT AGAIN
	LDB	T2,PCTXNO	;GET ITS CONTEXT NUMBER
	PUSHJ	P,LSTCNO	;TYPE IT
	POP	P,P1		;RESTORE SUPERIOR
	JRST	LSTBL2		;ONWARD

LSTBL1:	MOVEI	T1,[ASCIZ |          |]
	PUSHJ	P,CONMES##	;FILL FIELD WITH SPACES

LSTBL2:	PUSHJ	P,LSTSPC	;SPACE OVER
	CAMN	P1,.PDCTC##(W)	;CURRENT CONTEXT?
	SKIPA	T4,JBTNAM##(J)	;YES--GET PROGRAM NAME FROM JOB TABLE
	MOVE	T4,.CTPRG(P1)	;ELSE USE SAVED PROGRAM NAME
	PUSHJ	P,LSTCNM	;TYPE IT
	CAMN	P1,.PDCTC##(W)	;IS THIS THE CURRENT CONTEXT?
	JRST	LSTBL3		;YES--THEN IT'S NOT IDLE
	PUSHJ	P,LSTSPC	;SPACE OVER
	MOVE	T1,UPTIME##	;GET SYSTEM UPTIME
	SUB	T1,.CTIDL(P1)	;COMPUTE IDLE TIME FOR THIS CONTEXT
	PUSHJ	P,PRTIM##	;TYPE IT
LSTBL3:	PJRST	PCRLF##		;TYPE A CRLF AND RETURN


; CONTEXT NAME
LSTCNM:	MOVEI	T2,6		;SIX CHARACTERS
LSTCN1:	LSHC	T3,6		;SHIFT IN A CHARACTER
	ANDI	T3,77		;NO JUNK
	ADDI	T3,40		;CONVERT TO ASCII
	PUSHJ	P,PRCHR##	;TYPE CHARACTER
	SOJG	T2,LSTCN1	;LOOP
	POPJ	P,		;RETURN


; CONTEXT NUMBER
LSTCNO:	MOVEI	T3," "		;GET A LEADING SPACE
	CAIGE	T2,^D10		;000 - 009?
	PUSHJ	P,PRCHR##	;SPACE
	CAIGE	T2,^D100	;010 - 099?
	PUSHJ	P,PRCHR##	;SPACE
	MOVE	T1,T2		;GET NUMBER
	PJRST	PRTDIG##	;TYPE NUMBER AND RETURN


; SPACES
LSTSPC:	MOVEI	T1,[ASCIZ |   |]
	PJRST	CONMES##	;TYPE SPACES AND RETURN
SUBTTL	UTILITY ROUTINES -- MDUECT - MOVE DATA FROM USER TO EXEC


MDUECT:	HRLS	T2,.CTDTL(P1)	;GET REQUESTED LENGTH, MAKE ACTUAL LENGTH
	JUMPE	T2,MDUEC2	;CHECK TMPCOR STUFF IF NO DATA BUFFER
	HRRZS	T2		;KEEP REASONABLE
	PUSHJ	P,GTFWDC##	;GET FUNNY WORDS, CACHED
	  JRST	MDUEC4		;NOT ENOUGH CORE
	MOVEM	T1,.CTDTE(P1)	;SAVE ADDRESS
	HRRZ	T1,.CTDTL(P1)	;LENGTH
	SUBI	T1,1		;MAKE TRANSFER LENGTH
	MOVE	T2,.CTDTE(P1)	;START ADDRESS
	SETZM	@T2		;CLEAR FIRST WORD OF DATA BUFFER IN MONITOR
IFE FTXMON,<
	ADDI	T1,(T2)		;COMPUTE END ADDRESS
	HRLS	T2		;PUT IN LH
	HRRI	T2,1(T2)	;MAKE A BLT POINTER
	BLT	T2,-1(T1)	;CLEAR ENTIRE BLOCK
> ;END IFE FTXMON
IFN FTXMON,<
	XMOVEI	T3,1(T2)	;MAKE A BLT POINTER
	EXTEND	T1,[XBLT]	;CLEAR ENTIRE BLOCK
	PUSHJ	P,SSPCS##	;SAVE PCS
> ;END IFN FTXMON
	MOVE	M,.CTDTU(P1)	;POINT M AT THE DATA
	SOS	T1,M		;-1 FOR DATMAN
	PUSHJ	P,SXPCS##	;SET PCS ACCORDINGLY
	  JRST	MDUEC5		;ADDRESS CHECK
	HRRZ	T2,.CTDTL(P1)	;GET LENGTH AGAIN
	MOVE	T3,.CTDTE(P1)	;AND IT WILL GO HERE

MDUEC1:	PUSHJ	P,GETEW1##	;GET A WORD
	  JRST	MDUEC5		;ADDRESS CHECK READING ARGUMENTS
	MOVEM	T1,(T3)		;PUT A WORD
	ADDI	T3,1		;POINT TO NEXT STORAGE LOCATION
	SOJG	T2,MDUEC1	;LOOP

MDUEC2:	HLRZ	T2,.CTTCR(P1)	;GET TMPCOR FILE LENGTH
	JUMPE	T2,CPOPJ1##	;NO--RETURN
	ADDI	T2,2		;PLUS OVERHEAD WORDS
	PUSHJ	P,GTFWDC##	;GET FUNNY WORDS, CACHED
	  JRST	MDUEC6		;NOT ENOUGH CORE
	MOVEM	T1,.CTTCE(P1)	;SAVE ADDRESS
	HLRZ	T1,.CTTCR(P1)	;LENGTH
	ADDI	T1,2-1		;PLUS OVERHEAD WORDS -1
	MOVE	T2,.CTTCE(P1)	;START ADDRESS
	SETZM	@T2		;CLEAR FIRST WORD OF DATA BUFFER IN MONITOR
IFE FTXMON,<
	ADDI	T1,(T2)		;COMPUTE END ADDRESS
	HRLS	T2		;PUT IN LH
	HRRI	T2,1(T2)	;MAKE A BLT POINTER
	BLT	T2,-1(T1)	;CLEAR ENTIRE BLOCK
> ;END IFE FTXMON
IFN FTXMON,<
	XMOVEI	T3,1(T2)	;MAKE A BLT POINTER
	EXTEND	T1,[XBLT]	;CLEAR ENTIRE BLOCK
	PUSHJ	P,SSPCS##	;SAVE PCS
> ;END IFN FTXMON
	HRLZ	T1,.CTTCR(P1)	;GET TMPCOR FILE NAME,,0
	HLRZ	T2,.CTTCR(P1)	;GET LENGTH
	MOVNS	T2		;NEGATE
	HRLZS	T2		;PUT IN LH
	MOVE	T3,.CTTCE(P1)	;GET LENGTH OF DATA BUFFER IN MONITOR
	DMOVEM	T1,(T3)		;STORE
	ADDI	T3,2		;ACCOUNT FOR OVERHEAD WORDS
	HLRZ	T2,.CTTCR(P1)	;GET LENGTH OF TMPCOR FILE
	MOVE	T1,.CTTCA(P1)	;POINT M AT THE USER'S TMPCOR BUFFER
	SOS	M,T1		;COPY ADDRESS
	PUSHJ	P,SXPCS##	;SET PCS ACCORDINGLY
	  JRST	MDUEC5		;ADDRESS CHECK

MDUEC3:	PUSHJ	P,GETEW1##	;GET A WORD
	  JRST	MDUEC5		;ADDRESS CHECK READING ARGUMENTS
	MOVEM	T1,(T3)		;PUT A WORD
	ADDI	T3,1		;POINT TO NEXT STORAGE LOCATION
	SOJG	T2,MDUEC3	;LOOP
	JRST	CPOPJ1##	;AND RETURN

MDUEC4:	PUSHJ	P,ZERDAT	;ZERO OUT DATA BLOCK POINTERS
	JRST	ERRNCS		;NOT ENOUGH CORE TO SAVE CONTEXT

MDUEC5:	PUSHJ	P,MDEUC3	;RELEASE CORE, ZERO POINTERS
	JRST	ERRACR		;ADDRESS CHECK READING ARGUMENTS

MDUEC6:	PUSHJ	P,MDEUC2	;RELEASE CORE, ZERO POINTERS
	JRST	ERRNCS		;NOT ENOUGH CORE TO SAVE CONTEXT
SUBTTL	UTILITY ROUTINES -- MCEUCT - MOVE DATA FROM EXEC TO USER


MDEUCT:	SKIPN	T1,.CTTCR(P1)	;HAVE A TMPCOR FILE?
	JRST	MDEUC1		;NO
	HRLZS	T1		;POSITION LENGTH
	MOVE	T2,.CTTCE(P1)	;GET EXEC STORAGE ADDRESS
	PUSHJ	P,GIVCOR	;RELEASE CORE

MDEUC1:	HRRZ	T2,.CTDTL(P1)	;GET NUMBER OF WORDS RETURNED
	SKIPE	T3,.CTDTT(P1)	;HAVE A DATA BLOCK?
	SOSG	M,.CTDTU(P1)	;WHERE TO PUT IT IN USER CORE
	POPJ	P,		;NO
IFN FTXMON,<PUSHJ P,SSPCS##>	;SAVE PCS
	MOVE	T1,M		;SET UP CALL
	PUSHJ	P,SXPCS##	;SET PCS ACCORDINGLY
	  POPJ	P,		;GIVE UP
	MOVNS	T2		;NEGATE
	HRLZS	T2		;MAKE -LEN,,0

MDEUC2:	MOVE	T1,(T3)		;GET A WORD
	PUSHJ	P,PUTEW1##	;PUT A WORD
	  POPJ	P,		;SHOULDN'T FAIL AT THIS POINT
	ADDI	T3,1		;ADVANCE EXEC ADDRESS BY ONE
	AOBJN	T2,MDEUC2	;LOOP
	MOVE	T1,.CTRET(P1)	;GET AC CONTENTS TO RETURN
	TLO	T1,(CT.DAT)	;RETURNING DATA WORDS
	DPB	T2,PCTXDW	;STORE NUMBER OF DATA WORDS
	MOVEM	T1,.CTRET(P1)	;UPDATE

MDEUC3:	HLRZ	T1,.CTDTL(P1)	;GET ACTUAL BUFFER LENGTH
	SKIPE	T2,.CTDTE(P1)	;GET STORAGE ADDRESS
	PUSHJ	P,GIVCOR	;RELEASE CORE
	HLRZ	T1,.CTTCR(P1)	;GET TMPCOR FILE LENGTH
	ADDI	T1,2		;PLUS OVERHEAD WORDS
	SKIPE	T2,.CTTCE(P1)	;GET STORAGE ADDRESS
	PUSHJ	P,GIVCOR	;RELEASE CORE
	HRRZ	T1,.CTDTL(P1)	;GET LENGTH
	SKIPN	T2,.CTDTT(P1)	;GET TEMPORARY STORAGE ADDRESS
	PJRST	ZERDAT		;JUST ZAP DATA BLOCK POINTERS AND RETURN
	CAIL	T2,CTXSER	;IF THE ADDRESS IS
	CAILE	T2,CTXEND	; IN CTXSER, THEN IT
	PUSHJ	P,GIVCOR	;  DIDN'T COME FROM FRECOR
	PJRST	ZERDAT		;ZERO OUT DATA BLOCK POINTERS AND RETURN
SUBTTL	UTILITY ROUTINES -- MOVE DATA FROM INFERIOR TO EXEC


MDIECT:	SKIPE	P2,.CTSUP(P1)	;HAVE A SUPERIOR CONTEXT?
	SKIPN	.CTDTE(P2)	;HAVE A DATA BUFFER?
	POPJ	P,		;NO--JUST RETURN
	HRRZ	T2,.CTDTL(P2)	;GET NUMBER OF DATA WORDS WRITTEN
	PUSHJ	P,GETCOR	;GET CORE
	  JRST	MDIEC1		;NOT ENOUGH CORE TO RETURN DATA BUFFER
	MOVEM	T1,.CTDTT(P2)	;SAVE TEMPORARY BUFFER ADDRESS IN SUPERIOR
	HRRZ	T1,.CTDTL(P2)	;GET WORDS TO COPY
IFE FTXMON,<
	HRLZ	T2,.CTDTE(P2)	;WHERE THE BUFFER RESIDES NOW
	HRR	T2,.CTDTT(P2)	;AND WHERE IT'S BEING MOVED TO
	ADD	T1,.CTDTT(P2)	;COMPUTE END ADDRESS
	BLT	T2,-1(T1)	;COPY BUFFER
> ;END IFE FTXMON
IFN FTXMON,<
	MOVE	T2,.CTDTE(P2)	;WHERE THE BUFFER RESIDES NOW
	MOVE	T3,.CTDTT(P2)	;AND WHERE IT'S BEING MOVED TO
	EXTEND	T1,[XBLT]	;COPY BUFFER
> ;END IFN FTXMON
	PJRST	ZERDAT		;SKIP AROUND ERROR NONSENSE

MDIEC1:	PUSHJ	P,ERRNCD	;NOT ENOUGH CORE TO RETURN DATA BUFFER
	MOVSI	T1,(CT.UUE)	;FLAG A UUO ERROR
	IORM	T1,.CTFLG(P2)	;AND CAUSE AN ERROR RETURN TO SUPERIOR
;	PJRST	ZERDAT		;CLEAR POINTERS AND RETURN

ZERDAT:	SETZM	.CTDTL(P1)	;CLEAR BLOCK LENGTH(S)
	SETZM	.CTDTU(P1)	;CLEAR BLOCK ADDRESS IN USER CORE
	SETZM	.CTDTE(P1)	;CLEAR BLOCK ADDRESS IN EXEC CORE
	SETZM	.CTDTT(P1)	;CLEAR BLOCK ADDRESS IN EXEC CORE (TEMPORARY)
	SETZM	.CTTCR(P1)	;CLEAR TMPCOR FILE LENGTH,,NAME
	SETZM	.CTTCA(P1)	;CLEAR TMPFOR FILE ADDRESS (USER)
	SETZM	.CTTCE(P1)	;CLEAR TMPFOR FILE ADDRESS (EXEC)
	POPJ	P,		;RETURN
SUBTTL	UTILITY ROUTINES -- LGLCHK - CHECK LEGALITY


LGLCHK:	MOVEI	T1,CT.LGO	;BIT TO TEST
	MOVSI	T2,JLOG		;ANOTHER BIT TO TEST
	TDNN	T1,.PDCTX##(W)	;CURRENTLY TRYING TO LOGOUT?
	TDNE	T2,JBTSTS##(J)	;LOGGED IN?
	SKIPA	T1,[NSHF!NSWP,,0];YES TO EITHER
	JRST	ERRNLI		;NO
	SKIPG	T2,JBTSGN##(J)	;DO WE HAVE A REAL HISEG?
	SKIPA	T2,J		;NO--FAKE OUT CHECK
	HRRZS	T2		;KEEP ONLY THE SEGMENT NUMBER
	TDNN	T1,JBTSTS##(J)	;LOW LOCKED?
	TDNE	T1,JBTSTS##(T2)	;HIGH SEG LOCKED?
	JRST	ERRLOK		;YES--CAN'T DO IT
	PUSHJ	P,TTYSRC##	;NEED A TTY
	JRST	ERRDET		;JOB IS DETACHED
	PUSHJ	P,SYSNUM	;CHECK SYSTEM-WIDE CONTEXT QUOTAS
	  JRST	ERRSCE		;SYSTEM CONTEXT QUOTA EXCEEDED
	PUSHJ	P,SYSPAG	;CHECK SYSTEM-WIDE PAGES IN USE
	  JRST	ERRSPE		;SYSTEM PAGE QUOTA EXCEEDED
	PUSHJ	P,QTANUM	;CHECK CONTEXTS IN USE
	  JRST	ERRJCE		;JOB CONTEXT QUOTA EXCEEDED
	PUSHJ	P,QTAPAG	;CHECK PAGES IN USE
	  JRST	ERRJPE		;JOB PAGE QUOTA EXCEEDED
	PUSHJ	P,SWPCHK	;CHECK FOR ENOUGH SWAPPING SPACE
	  JRST	ERRNCS		;NOT ENOUGH VIRTUAL CORE TO SAVE CONTEXT
	MOVEI	T2,JS.RPC	;BIT TO TEST
	SKIPE	.PDPGM##(W)	;PROGRAM TO RUN?
	TDNN	T2,JBTST2##(J)	;AND NEVER RETURN TO MONITOR?
	JRST	CPOPJ1##	;NO--OK TO SAVE CONTEXT
	TLNE	P2,(CT.HLT)	;AUTO-SAVE?
	JRST	ERRCCC		;NO--CANNOT CREATE CONTEXT FROM CAPTIVE PROGRAM
	JRST	CPOPJ1##	;OK TO SAVE CONTEXT
; CHECK JOB CONTEXT QUOTA NUMBERS
QTANUM:	LDB	T1,PCTXCQ	;GET CONTEXT QUOTA
	LDB	T2,PCTXCU	;GET NUMBER OF CONTEXTS IN USE
	ADDI	T2,1		;THIS WILL BE THE NEW NUMBER
	SKIPN	T1		;HAVE A CONTEXT QUOTA?
	MOVEI	T1,CTXMAX##	;NO--CHECK AGAINST ABSOLUTE MAXIMUM
	CAML	T1,T2		;EXCEED NUMBER OF CONTEXTS?
	JRST	CPOPJ1##	;NO--DONE CHECKING
	PUSHJ	P,JACCTP	;GODLY PROGRAM?
	  JRST	QTANU1		;YES--LET HIM THROUGH
	TLNN	P2,(CT.ATO!CT.SWT) ;NO--OK TO EXCEED QUOTA?
	POPJ	P,		;NO
	AOSA	NPQEXC		;NORMAL PROGRAM SAVE QUOTA EXCEEDED
QTANU1:	AOS	JPPEXC		;JACCT PROGRAM SAVE QUOTA EXCEEDED
	JRST	CPOPJ1##	;AND LET THE JOB CONTINUE


; CHECK CONTEXT PAGES
QTAPAG:	PUSHJ	P,CORESZ	;COMPUTE SIZE OF CORE IMAGE
	LDB	T2,PCTXPU	;GET PAGES IN USE
	ADD	T1,T2		;THIS WILL BE THE NEW NUMBER
	LDB	T2,PCTXPQ	;GET PAGE QUOTA
	SKIPN	T2		;HAVE A PAGE QUOTA?
	SETZ	T1,		;NO--THE SKY'S THE LIMIT
	CAMG	T1,T2		;EXCEED THE NUMBER OF SAVED PAGES ALLOWED?
	JRST	CPOPJ1##	;OK TO PROCEED
	PUSHJ	P,JACCTP	;GODLY PROGRAM?
	  JRST	QTAPA1		;YES--LET HIM THROUGH
	TLNN	P2,(CT.ATO!CT.SWT) ;NO--OK TO EXCEED QUOTA?
	POPJ	P,		;NO
	AOSA	NPPEXC		;NORMAL PROGRAM PAGE QUOTA EXCEEDED
QTAPA1:	AOS	JPPEXC		;JACCT PROGRAM PAGE QUOTA EXCEEDED
	JRST	CPOPJ1##	;AND LET THE JOB CONTINUE


; CHECK SYSTEM-WIDE CONTEXT QUOTA NUMBERS
SYSNUM:	SKIPN	SYSCCQ		;HAVE A SYSTEM-WIDE QUOTA?
	JRST	CPOPJ1##	;NO QUOTA ENFORCEMENT
	CTXLOK			;INTERLOCK DATA BASE
	MOVE	T1,SYSCCU	;GET SYSTEM-WIDE CONTEXTS IN USE
	ADDI	T1,1		;THIS WILL BE THE NEW NUMBER
	CAMG	T1,SYSCCQ	;OVER THE LIMIT?
	AOS	(P)		;NO
	CTXNLK			;GIVE UP INTERLOCK
	POPJ	P,		;RETURN


; CHECK SYSTEM-WIDE PAGE QUOTAS
SYSPAG:	SKIPN	SYSCPQ		;HAVE A SYSTEM-WIDE QUOTA?
	JRST	CPOPJ1##	;NO QUOTA ENFORCEMENT
	PUSHJ	P,CORESZ	;COMPUTE SIZE OF CORE IMAGE
	CTXLOK			;INTERLOCK DATA BASE
	MOVE	T2,SYSCPU	;GET PAGES IN USE
	ADD	T1,T2		;THIS WILL BE THE NEW NUMBER
	CAMGE	T1,SYSCPQ	;OVER THE LIMIT?
	AOS	(P)		;NO
	CTXNLK			;GIVE UP INTERLOCK
	POPJ	P,		;RETURN


; CHECK VIRTAL
SWPCHK:	PUSHJ	P,CORESZ	;COMPUTE SIZE OF CORE IMAGE
	MOVE	T2,VIRTAL##	;GET TOTAL SWAPPING SPACE AVAILABLE
	SUB	T2,T1		;SUBTRACT AMOUNT NEEDED
	JUMPG	T2,CPOPJ1##	;HAVE ENOUGH
	POPJ	P,		;TOO BAD

; CHECK IF A JACCT'ED PROGRAM
JACCTP:	MOVSI	T3,JACCT	;THE BIT TO TEST
	TLNE	P2,(CT.UUO)	;COMING FROM COMCON?
	TDNN	T3,JBTSTS##(J)	;NO, TEST FOR GODLINESS OF PROGRAM
	AOS	(P)		;NOT GODLY ENOUGH
	POPJ	P,		;RETURN APPROPRIATELY
SUBTTL	UTILITY ROUTINES -- CORESZ - COMPUTE CORE IMAGE SIZE


; CALL:	PUSHJ	P,CORESZ
;
; ON RETURN T1 WILL CONTAIN THE SUM OF THE LOW AND HIGH SEG SIZES

CORESZ:	PUSH	P,J		;SAVE J
	S0PSHJ	SEGSIZ##	;GET LOW SEGMENT SIZE
	PUSH	P,T2		;SAVE IT
	SKIPG	J,JBTSGN##(J)	;GET HIGH SEGMENT NUMBER
	TDZA	T2,T2		;THERE ISN'T ONE
	S0PSHJ	SEGSIZ##	;GET HISEG SIZE
	POP	P,T1		;GET LOW SEG SIZE BACK
	TLNN	J,SHRSEG	;SHARABLE (HIGH SEGS ALREADY ACCOUNTED FOR)?
	ADD	T1,T2		;NO--ACCUMULATE TOTAL # OF NON-SHARABLE PAGES
	TLNE	J,UWPOFF
	ADDI	T1,1
	POP	P,J		;RESTORE JOB NUMBER
	POPJ	P,		;AND RETURN
SUBTTL	UTILITY ROUTINES -- CONTEXT ACCOUNTING


; INCREMENT THE CONTEXT NUMBER
UPCTXN:	LDB	T1,PCTXCU	;GET CURRENT CONTEXT LEVEL
	ADDI	T1,1		;COUNT UP
	TDNE	T1,[-1-CTXMAX##];FIELD OVERFLOW?
	PUSHJ	P,CTXSTP	;YES--DIE
	DPB	T1,PCTXCU	;UPDATE CONTEXT NUMBER
	AOS	SYSCCU		;COUNT UP SYSTEM-WIDE CONTEXTS IN USE
	POPJ	P,		;AND RETURN


; DECREMENT THE CONTEXT NUMBER
DNCTXN:	LDB	T1,PCTXCU	;GET CURRENT CONTEXT LEVEL
	SUBI	T1,1		;COUNT DOWN
	TDNE	T1,[-1-CTXMAX##];FIELD UNDERFLOW?
	PUSHJ	P,CTXSTP	;YES--DIE
	DPB	T1,PCTXCU	;UPDATE CONTEXT NUMBER
	CTXLOK			;INTERLOCK DATA BASE
	SOSGE	SYSCCU		;COUNT DOWN SYSTEM-WIDE CONTEXTS IN USE
	PUSHJ	P,CTXSTP	;WENT TOO FAR
	CTXNLK			;RELEASE INTERLOCK
	POPJ	P,		;AND RETURN

CTXSTP:	STOPCD	.,JOB,CTX,	;++CONTEXT SKEW


; INCREMENT THE NUMBER OF SAVED CONTEXT PAGES
UPPAGE:	PUSHJ	P,CORESZ	;COMPUTE SIZE OF CORE IMAGE
	CTXLOK			;INTERLOCK DATA BASE
	ADDM	T1,SYSCPU	;ADD TO SYSTEM SAVE PAGE TOTAL
	CTXNLK			;RELEASE INTERLOCK
	LDB	T2,PCTXPU	;GET PAGES USED SO FAR
	ADD	T1,T2		;ACCUMULATE
	DPB	T1,PCTXPU	;UPDATE TOTAL
	POPJ	P,		;AND RETURN


; DECREMENT THE NUMBER OF SAVED CONTEXT PAGES
DNPAGE:	PUSHJ	P,CORESZ	;COMPUTE SIZE OF CORE IMAGE
	CTXLOK			;INTERLOCK DATA BASE
	MOVE	T2,SYSCPU	;GET SYSTEM SAVE PAGE TOTAL
	SUB	T2,T1		;ADJUST
	SKIPGE	T2		;SHOULD NEVER BE NEGATIVE
	PUSHJ	P,CTXSTP	;DIE
	MOVEM	T2,SYSCPU	;UPDATE
	CTXNLK			;RELEASE INTERLOCK
	LDB	T2,PCTXPU	;GET TOTAL PAGES USED
	SUB	T2,T1		;DECREMENT
	SKIPGE	T2		;SHOULD NEVER BE NEGATIVE
	PUSHJ	P,CTXSTP	;DIE
	DPB	T2,PCTXPU	;UPDATE
	POPJ	P,		;AND RETURN
SUBTTL	UTILITY ROUTINES -- CLRCOM - CLEAR COMCON INPUT BUFFER


CLRCOM:	MOVSI	T1,(CT.UUO)	;GET THE UUO FLAG
	TDNN	T1,.PDCTX##(W)	;UUO IN PROGRESS?
	PUSHJ	P,TTYCMR##	;NO, LIGHT COMMAND SYNCH BIT (END OF COMMAND)
	MOVSI	T1,(CT.ATO)	;BIT FOR TESTING
	TDNN	T1,.PDCTX##(W)	;IF NOT AUTO-SAVE
	PUSHJ	P,TYIEAT##	;THEN MAKE COMCON NOT REREAD COMMANDS
	POPJ	P,		;GO BACK
SUBTTL	UTILITY ROUTINES -- CLRRUA - CLEAR RUN UUO ARGUMENT STORAGE


; CLEAR RUN UUO ARGUMENT STORAGE IN THE CONTEXT BLOCK
; CALL:	PUSHJ	P,CLRRUA

CLRRUA:	SETZM	.CTRUA(P1)	;CLEAR FIRST WORD OF RUN STORAGE
IFE FTXMON,<
	MOVSI	T1,.CTRUA(P1)	;START OF RUN STORAGE
	HRRI	T1,.CTRUA+1(P1)	;MAKE A BLT POINTER
	BLT	T1,.CTRUA+1+6+2+MAXLVL-1(P1) ;CLEAR OUT OUR BLOCKS
> ;END IFE FTXMON
IFN FTXMON,<
	MOVEI	T1,1+6+2+MAXLVL-1 ;NUMBER OF WORDS TO CLEAR
	XMOVEI	T2,.CTRUA(P1)	;FROM HERE
	XMOVEI	T3,.CTRUA+1(P1)	;INTO HERE
	EXTEND	T1,[XBLT]	;CLEAR OUT OUR BLOCKS
> ;END IFN FTXMON
	POPJ	P,		;RETURN
SUBTTL	UTILITY ROUTINES -- GETRUA - GET RUN UUO ARGUMENTS FROM USER CORE


GETRUA:	MOVSI	T1,(CT.UUO)	;BIT TO TEST
	TDNN	T1,.PDCTX##(W)	;CALLED VIA UUO?
	PUSHJ	P,CLRRUA	;NO--CLEAR STORAGE SINCE NOT DONE YET
	MOVSI	T1,(CT.ATO)	;BIT TO TEST
	TDNN	T1,.PDCTX##(W)	;AUTO-SAVE AND RUN?
	POPJ	P,		;JUST RETURN
	MOVE	T1,.CTPRG(P1)	;GET INVOKING COMMAND NAME
	CAMN	T1,PLNTXT##	;USER DEFINED COMMAND?
	JRST	GETRU1		;YES--MUST HANDLE DIFFERENTLY
	MOVEM	T1,.CTRUB+1(P1)	;SAVE PROGRAM NAME
	MOVSI	T1,'SYS'	;DEVICE
	MOVEM	T1,.CTRUB+0(P1)	;SAVE IT
	POPJ	P,		;DONE

GETRU1:	MOVE	T1,JBTNAM##(J)	;GET CORRECT NAME TO SAVE
	MOVEM	T1,.CTPRG(P1)	;AND DO SO
	HLRZ	P2,.CTDSP(P1)	;GET DISPATCH ADDRESS (USER COMMAND BLOCK)
	MOVE	T1,(P2)		;GET WORD COUNT
	SUBI	T1,1		;ACCOUNT FOR WORD COUNT WORD
	MOVE	T2,1(P2)	;DEVICE
	MOVEM	T2,.CTRUB+0(P1)
	SOJLE	T1,CPOPJ1##
	MOVE	T2,2(P2)	;FILE NAME
	MOVEM	T2,.CTRUB+1(P1)
	SOJLE	T1,CPOPJ1##
	MOVE	T2,3(P2)	;EXTENSION
	MOVEM	T2,.CTRUB+2(P1)
	SOJLE	T1,CPOPJ1##
	AOS	.CTRUB+4(P1)	;REMEMBER THAT WE HAVE A PATH
IFE FTXMON,<
	MOVSI	T2,4(P2)	;START ADDRESS
	HRRI	T2,.CTPUB+2(P1)	;WHERE TO PUT IT
	ADDI	T1,.CTPUB+2(P1)	;COMPUTE END ADDRESS
	BLT	T2,-1(T1)	;COPY
> ;END IFE FTXMON
IFN FTXMON,<
	XMOVEI	T2,4(P2)	;FIRST WORD OF PATH
	XMOVEI	T3,.CTPUB+2(P1)	;WHERE TO PUT IT
	EXTEND	T1,[XBLT]	;COPY
> ;END IFN FTXMON
	POPJ	P,		;ALL DONE
SUBTTL	UTILITY ROUTINES -- PUTRUA - PUT RUN UUO ARGUMENTS IN USER CORE


PUTRUA:
IFE FTXMON,<
	MOVSI	T1,.CTRUB(P1)	;POINT TO RUN UUO BLOCK
	HRRI	T1,.JDAT+.JBDA## ;WHERE TO PUT IT
	BLT	T1,.JDAT+.JBDA##+6-1 ;COPY IT
	MOVSI	T1,.CTPUB(P1)	;POINT TO PATH UUO BLOCK
	HRRI	T1,.JDAT+.JBDA##+7 ;WHERE TO PUT IT
	BLT	T1,.JDAT+.JBDA##+7+2+1+MAXLVL-1 ;COPY IT
> ;END IFE FTXMON
IFN FTXMON,<
	MOVEI	T1,6		;LENGTH
	XMOVEI	T2,.CTRUB(P1)	;POINT TO RUN UUO BLOCK
	MOVEI	T3,.JDAT+.JBDA## ;WHERE TO PUT IT
	EXTEND	T1,[XBLT]	;COPY IT
	HRRZ	T1,.CTRUA(P1)	;GET /USE SECTION NUMBER
	MOVEM	T1,.JDAT+.JBDA##+6 ;STORE
	HRROI	T1,.JBDA##+6	;WORD TO STUFF INTO BLOCK
	SKIPE	.CTRUB+5(P1)	;USER GIVE A POINTER?
	MOVEM	T1,.JDAT+.JBDA##+5 ;POINT TO SECTION NUMBER
	MOVEI	T1,2+1+MAXLVL	;LENGTH
	XMOVEI	T2,.CTPUB(P1)	;POINT TO PATH UUO BLOCK
	MOVEI	T3,.JDAT+.JBDA##+7 ;WHERE TO PUT IT
	EXTEND	T1,[XBLT]	;COPY IT
> ;END IFN FTXMON
	MOVEI	T1,.JBDA##+7	;RELATIVE ADDRESS OF PATH BLOCK IN PAGE
	SKIPE	T2,.CTRUB+4(P1)	;HAVE A PPN/PATH POINTER?
	TLNE	T2,-1		;PATH POINTER?
	SKIPA			;NO
	MOVEM	T1,.JDAT+.JBDA##+4;SET IT UP
	HLLZ	T1,.CTRUA(P1)	;GET RUN UUO OFFSET
	HRRI	T1,.JBDA##	;ARGUMENTS LIVE HERE
	EXCTXU	<MOVEM T1,0>	;STORE IN USER AC 0
	MOVEI	M,0		;SET UP AC 'M' FOR GETWRD CALLS
	POPJ	P,		;RETURN
SUBTTL	UTILITY ROUTINES -- GETCOR/GIVCOR - CORE ALLOCATION


GETCOR:
IFN FTXMON,<			;IF MONITOR SUPPORTS EXTENDED ADDRESSING,
	PUSHJ	P,INTLVL##	;CAN WE BLOCK?
	  PJRST	GFWNZS##	;YES, GET NON-ZERO SECTION FREE CORE
>
	PJRST	GETWDS##	;NO--GET SECTION ZERO FREE CORE

GIVCOR:	CAMGE	T2,SYSSIZ##	;SECTION ZERO FREE CORE?
	PJRST	GIVWDS##	;RETURN SECTION ZERO FREE CORE
IFE FTMP,<PJRST	GVFWDS##>	;RETURN FUNNY OR NZS CORE
IFN FTMP,<
	PUSHJ	P,INTLVL##	;CAN WE BLOCK?
	  PJRST	GVFWDS##	;YES--GIVE UP NZS CORE GRACEFULLY
	PUSHJ	P,GETMM##	;NEED THE MM RESOURCE
	  JRST	.-1		;I REALLY WANT IT NOW
	PUSHJ	P,GVFWDS##	;RETURN FUNNY OR NZS CORE
	PJRST	GIVMM##		;NOW GIVE UP THE MM RESOURCE AND RETURN
> ;END IFN FTMP
SUBTTL	UTILITY ROUTINES -- GETAC/PUTAC - USER AC GET/PUT ROUTINES


; GET THE CONTENTS OF THE USER'S UUO AC
; CALL:	PUSHJ	P,GETAC

GETAC:	LDB	M,PCTXUA	;GET AC
	PJRST	GETWDU##	;FETCH CONTENTS AND RETURN


; RETURN DATA IN THE USER'S AC
; CALL:	MOVE	T1, DATA
;	PUSHJ	P,PUTAC/PUTAC1

PUTAC1:	AOS	(P)		;SKIP
PUTAC:	PUSH	P,M		;SAVE M
	MOVSI	M,(CT.UUO)	;USER-MODE BIT
	TDNN	M,.PDCTX##(W)	;DOING THIS FOR A USER?
	JRST	MPOPJ##		;NO, LEAVE USER'S ACS ALONE
	LDB	M,PCTXUA	;POINT M AT USER'S AC
	PUSHJ	P,PUTWDU##	;STORE CONTENTS OF T1
	JRST	MPOPJ##		;RESTORE M AND RETURN
SUBTTL	UTILITY ROUTINES -- WCHCTX - TYPE CONTEXT WATCH INFORMATION


WCHCTX:	MOVSI	T1,JW.WCX	;SEE IF WATCHING
	TDNN	T1,JBTWCH##(J)	;YES--WANT TO SEE THIS CRUFT?
	POPJ	P,		;NO
	PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	P1,.PDCTC##(W)	;POINT TO CURRENT CONTEXT BLOCK
	PUSHJ	P,CRLF##	;START WITH A NEW LINE
	MOVEI	T1,[ASCIZ |[Context |]
	PUSHJ	P,CONMES##	;TYPE TEXT
	MOVE	T2,.CTCBN(P1)	;GET NAME IF ANY
	PUSH	P,T2		;SAVE NAME OR ZERO
	JUMPE	T2,WCHCT1	;AVOID EXTRA WORK IF NO NAME
	PUSHJ	P,PRNAME##	;TYPE CONTEXT NAME
	MOVEI	T3,"("		;PUT THE CONTEXT
	PUSHJ	P,PRCHR##	; NUMBER IN PARANTHESIS
WCHCT1:	LDB	T1,PCTXNO	;GET CURRENT CONTEXT NUMBER
	PUSHJ	P,PRTDIG##	;TYPE IT
	MOVEI	T3,")"		;CLOSE PARANTHESIS
	SKIPE	(P)		; UNLESS THERE WAS NO
	PUSHJ	P,PRCHR##	;   NAME FOR THIS CONTEXT
	POP	P,(P)		;TRIM STACK
	SKIPE	JBTNAM##(J)	;HAVE A PROGRAM NAME?
	PUSHJ	P,PRSPC##	;YES--SPACE OVER
	SKIPE	T2,JBTNAM##(J)	;GET PROGRAM NAME
	PUSHJ	P,PRNAME##	;TYPE IT
	MOVEI	T3,"]"		;FINISH
	PUSHJ	P,PRCHR##	; DISPLAY
	PJRST	CRLF##		;TYPE CRLF AND RETURN
SUBTTL	UTILITY ROUTINES -- WRTTCR - WRITE A TMPCOR FILE


WRTTCR:	SKIPN	.CTTCR(P1)	;TMPCOR FILE AVAILABLE?
	POPJ	P,		;NO
	MOVE	T1,.CTTCE(P1)	;POINT TO FILE ALREADY IN FUNNY SPACE
	PUSHJ	P,TMPCTX##	;CALL TMPUUO TO LINK INTO TMPCOR CHAIN
	POPJ	P,		;FOR NOW
SUBTTL	UTILITY ROUTINES -- SGETXT - REPORT SAVE/GET ERRORS


; ROUTINE TO TRANSLATE SAVE/GET ERROR CODES INTO MEANINGFUL TEXT
; CALL:	MOVE	T1, ERROR CODE
;	MOVE	T2, DEFAULT TEXT
;	PUSHJ	P,SGETXT

SGETXT:	HRL	T2,T1		;PUT ERROR CODE IN LH
	TLO	T2,400000	;AND LIGHT THE ERROR BIT
	PUSH	P,T2		;SAVE DEFAULT ERROR TEXT
	MOVSI	T2,-SGELEN	;MAKE AN AOBJN POINTER

SGETX1:	HLRZ	T3,SGETAB(T2)	;GET AN ERROR CODE
	CAIE	T3,(T1)		;A MATCH?
	AOBJN	T2,SGETX1	;NO
	MOVE	T1,SGETAB(T2)	;GET ASSOCIATED TEXT
	SKIPGE	T2		;FIND A MATCH?
	MOVEM	T1,(P)		;YES--OVERWRITE DEFAULT
	PUSHJ	P,PPQCRL##	;START WITH ?<CRLF>
	HRRZ	T1,(P)		;GET TEXT
	PUSHJ	P,CONMES##	;TYPE IT
	POP	P,T1		;GET ERROR CODE BACK
	JUMPGE	T1,SGETX2	;JUMP IF KNOWN ERROR CODE
	TLZ	T1,400000	;CLEAR ERROR BIT
	HLRZS	T1		;PUT IN RH
	PUSHJ	P,PRTDI8##	;TYPE OCTAL NUMBER

SGETX2:	MOVEI	J,0		;CLEAR JOB # TO INDICATE COMCON ERROR
	PJRST	PCRLF##		;TYPE A CRLF AND RETURN

SGETAB:	FNFERR,,[ASCIZ |File not found|]
	IPPERR,,[ASCIZ |Incorrect PPN|]
	PRTERR,,[ASCIZ |Protection failure|]
	TRNERR,,[ASCIZ |Transmission error|]
	NSFERR,,[ASCIZ |Not a save file|]
	NECERR,,[ASCIZ |Not enough core|]
	DNAERR,,[ASCIZ |Device not available|]
	NSDERR,,[ASCIZ |No such device|]
	SNFERR,,[ASCIZ |SFD not found|]
	SLEERR,,[ASCIZ |Search list empty|]
SGELEN==.-SGETAB
SUBTTL	UTILITY ROUTINES -- LOKCTX/NLKCTX - SYSTEM DATA BASE INTERLOCKS


IFN FTMP,<
; GET CTXSER DATA BASE INTERLOCK
; CALLED USING THE CTXLOK MACRO

LOKCTX:	SKIPGE	INTRCT		;INTERLOCK AVAILABLE?
	AOSE	INTRCT		;TRY TO GET IT
	JRST	LOKCTX		;SPIN
IFN FTKL10,<APRID INTOCT>	;STORE OWNING CPU SERIAL NUMBER
	POPJ	P,		;RETURN


; RELEASE CTXSER DATA BASE INTERLOCK
; CALLED USING THE CTXNLK MACRO

NLKCTX:	SETOM	INTOCT		;CLEAR OWING CPU
	SETOM	INTRCT		;CLEAR INTERLOCK
	POPJ	P,		;RETURN

> ;END IFN FTMP
SUBTTL	UTILITY ROUTINES -- RELINK - RELINK A USER'S CONTEXT BLOCKS


; THIS ROUTINE IS CALLED TO RELINK ALL CONTEXT BLOCKS OWNED BY A
; JOB INTO A SINGLE "PUSH" CHAIN.
; CALL:	PUSHJ	P,RELINK
;	  <NON-SKIP>		;NO CONTEXT BLOCKS
;	<SKIP>			;ONE OR MORE BLOCKS

RELINK:	SKIPN	P1,.PDSAC##(W)	;POINT TO THE START OF THE CHAIN
	POPJ	P,		;NO CONTEXT BLOCKS??

RELIN1:	SKIPN	T1,.CTNXT(P1)	;SEARCH FOR THE LAST ONE
	JRST	RELIN2		;FOUND IT
	CAMN	T1,.PDCTC##(W)	;FOUND THE CURRENT CONTEXT?
	MOVE	T1,.CTNXT(T1)	;YES--LOOK BEYOND
	JUMPE	T1,RELIN2	;END?
	MOVE	P1,T1		;SET POINTER
	JRST	RELIN1		;AND LOOP

RELIN2:	MOVE	P2,P1		;COPY TO A SAFE PLACE
RELIN3:	SKIPN	T1,.CTPRV(P1)	;GET PREVIOUS
	JRST	RELIN5		;CONTEXT BLOCKS ARE ALL LINKED
	CAME	T1,.PDCTC##(W)	;IS THE PREVIOUS THE CURRENT ONE?
	JRST	RELIN4		;NO
	SKIPN	T1,.CTSUP(T1)	;IGNORE CURRENT BLOCK
	JRST	RELIN5		;BEGINING OF CHAIN

RELIN4:	MOVEM	T1,.CTSUP(P1)	;MAKE IT OUR SUPERIOR
	MOVSI	T2,(CT.INF!CT.DEL) ;GET THE INFERIOR PLUS DELETE FLAGS
	IORM	T2,.CTFLG(T1)	;REMEMBER THE SUPERIOR OWNS THIS ONE
	MOVSI	T2,JLOG		;GET LOGGED IN BIT
	ANDCAM	T2,.CTBPR+.CXSTS(T1) ;CLEAR SO CONTEXT RESTORE WON'T LOG US IN
	MOVE	P1,T1		;NOW POINT TO THE PREVIOUS
	JRST	RELIN3		;AND LINK THAT BLOCK

RELIN5:	MOVE	T1,.PDCTC##(W)	;POINT TO THE CURRENT
	MOVEM	T1,.CTSUP(P1)	;PUT CURRENT AT THE TOP OF THE CHAIN
	SETZM	.CTSUP(T1)	;FIRST BLOCK IN CHAIN HAS NO SUPERIOR
	MOVSI	T2,(CT.INF)	;REMEMBER THE CURRENT
	IORM	T2,.CTFLG(T1)	; HAS AT LEAST ONE INFERIOR
	MOVEM	P2,.CTNEW(T1)	;WILL BE SWITCHING TO THE LAST BLOCK IN CHAIN
	MOVSI	T1,(CT.DEL)	;LAST CONTEXT IN CHAIN DIDN'T GET
	IORM	T1,.CTFLG(P2)	; THE DELETE BIT TURNED ON YET
	MOVEI	T1,CT.LGO	;LITE LOGGING OUT IN PROGRESS
	IORM	T1,.PDCTX##(W)	;SO THINGS PROCEED SMOOTHLY
	JRST	CPOPJ1##	;RETURN
SUBTTL	CX RESOURCE ROUTINES

;ROUTINES TO MANIPULATE THE CX RESOURCE FOR A JOB

;UPCX TO GET THE CX RESOURCE FOR THE JOB IN T1 (.CPJOB CONTAINS OUR JOB)
;UPCX WILL BLOCK IF THE REQUESTED CX RESOURCE ISN'T AVAILABLE

UPCX::	PUSH	P,T2		;SAVE EVERYTHING
	PUSH	P,J		;SAVE J
	MOVE	J,.CPJOB##
	SKIPN	T2,T1		;WHO WE WANT
	SOS	T2		;IF JOB 0, SAY -1
	HRLM	T2,JBTCX##(J)	;FLAG WHO WE WANT/OWN
	JUMPE	T1,UPCXR	;NO REAL INTERLOCKING FOR JOB 0
	SYSPIF			;GUARD RACES
	HRRZ	T2,JBTCX(T1)	;GET THE OWNER OF HIS CX RESOURCE
	JUMPN	T2,CXWAIT	;WAIT IF IT ISN'T AVAILABLE
	HRRM	J,JBTCX##(T1)	;WE OWN HIS CX
	SYSPIN
UPCXR:	POP	P,J
	JRST	T2POPJ##	;RETURN

CXWAIT:	SYSPIN
	MOVEI	T2,CXQ##	;THE QUEUE
	DPB	T2,PJBSTS##	;SAY IN CX WAIT
	POP	P,J		;RESTORE J
	POP	P,T2		;RESTORE T2
	PJRST	WSCHED##	;WAIT FOR RESOURCE

;HERE TO TRY AND GET CX RESOURCE AT INTERRUPT LEVEL.  RETURN CPOPJ1
;IF WE HAVE IT, CPOPJ OTHERWISE.  CALLER'S RESPONSIBILITY TO WAIT

GETCX::	PUSH	P,T1		;SAVE T1
	SYSPIF
	HRRZ	T1,JBTCX##(J)	;GET OWNER OF CX RESOURCE WE DESIRE
	JUMPN	T1,GETCXR	;OWNED BY SOMEONE ELSE
	MOVEM	J,.CPCXJ##	;SAVE WE OWN IT
	SKIPN	J		;JOB 0?
	SOSA	.CPCXJ		;YES, FLAG OWN NUL JOB
	HLLOS	JBTCX##(J)	;SAY A CPU OWNS IT
	AOS	-1(P)		;GIVE GOOD RETURN
GETCXR:	SYSPIN
	JRST	TPOPJ##

;COROUTINE TO GET AND GIVE THE CX RESOURCE (UUO LEVEL)

GGVCX::	PUSHJ	P,UPCX	;GET CX RESOURCE
	POP	P,(P)
	PUSHJ	P,@1(P)		;CALL BACK
	  CAIA
	AOS	(P)
;	PJRST	DWNCX		;(FALL INTO DWNCX)

;HERE TO RELEASE THE CX RESOURCE WE (THE JOB IN J) OWNS
;CALL GIVCX FOR INTERRUPT LEVEL (OWNED BY CPU), OR
;DWNCX *FOR UUO LEVEL ONLY* (OWNED BY JOB IN .CPJOB)

DWNCX::	PUSH	P,J		;SAVE J
	PUSH	P,F		;SAVE F
	MOVE	J,.CPJOB##	;GET JOB WHO IS RUNNING
	SYSPIF			;INTERLOCK
	HLRE	F,JBTCX##(J)	;GET WHO WE OWN
	HRRZS	JBTCX##(J)	;WE NO LONGER OWN HIM
DWNCX1:	SKIPL	F		;IF OWNED NUL JOB
	HLLZS	JBTCX##(F)	;HE IS NO LONGER OWNED
	SYSPIN
	JUMPL	F,DWNCXR	;RETURN IF NUL
	SETZ	F,		;**NO EVM**
	PUSHJ	P,[PUSH	P,T1	;SAVE T1
		   PUSH P,J	;AND J
		   PJRST SRFRCX##]
DWNCXR:	POP	P,F
	POP	P,J
	POPJ	P,

GIVCX::	PUSH	P,J		;SAVE J
	PUSH	P,F		;SAVE F
	SETZB	F,J		;GET & CLEAR
	SYSPIF
	EXCH	F,.CPCXJ##	;GET JOB
	JRST	DWNCX1

;HERE TO UNWIND CX RESOURCE AT SCHEDULAR LEVEL
;CALL WITH JOB WHOSE CX WE WANT IN J, RETURN WITH OWNER (IF ANY) IN T3

UNWCX::
	HLRE	T3,JBTCX##(J)	;WHO WE WANT
	SKIPLE	T3		;HUH?
	HRRE	T3,JBTCX##(T3)	;OWNER
	POPJ	P,

;HERE TO GRANT CX TO A JOB AT SCHEDULAR LEVEL

SCDCX::	HLRE	T3,JBTCX##(J)	;GET THE CX WE WANT
	JUMPLE	T3,CPOPJ1##	;HUH?
	SYSPIF			;GUARD RACES
	HRL	T3,JBTCX##(T3)	;MAKE SURE IT'S STILL FREE
	TLNE	T3,-1		;SOMEONE SNEAK IN?
	JRST	ONPOPJ##	;YES, LOSE
	HRRM	J,JBTCX##(T3)	;WE OWN HIS
	AOS	(P)
	JRST	ONPOPJ##	;WIN

;SUBROUTINE FOR CLOCK1 TO CALL TO SEE IF JOB IN J OWNS ANY CX RESOURCES
;SKIP RETURN IF OWN SOME CX, NON-SKIP OTHERWISE

OWNCX::	PUSH	P,T1		;SAVE T1
	HLRZ	T1,JBTCX##(J)	;OWN ANYTHING?
	JUMPN	T1,TPOPJ1##
	JRST	TPOPJ##

;ROUTINE TO SEE IF WE OWN THE CX.  NON-SKIP IF WE DON'T, SKIP
;IF WE DO.  CX DESIRED IN T1

CXOWN::	CAMN	T1,.CPCXJ##	;OWNED BY CPU?
	JRST	CPOPJ1##	;YES
	PUSH	P,T2
	HRRZ	T2,JBTCX##(T1)	;SEE WHO OWNS HIS CX
	CAMN	T2,.CPJOB##	;US?
	AOS	-1(P)		;YES
	JRST	T2POPJ##
SUBTTL	LITERAL POOL

	$LIT
SUBTTL	IMPURE DATA


	$LOW

INTRCT:	EXP	-1		;INTERLOCK REFERENCE COUNT
IFN FTKL10,<INTOCT: EXP	-1>	;INTERLOCK OWNER

IFN FTXMON,<
RESMAX:	EXP	M.CTXR##	;RESERVED CONTEXT BLOCK MAXIMUM
RESCNT:	BLOCK	1		;RESERVED CONTEXT BLOCK COUNT
RESBLK:	BLOCK	1		;RESERVED CONTEXT BLOCK CHAIN ADDRESS
> ;END IFN FTXMON

CTXTAB::!			;CONTEXT GETTAB TABLE

JOBCCQ:	EXP	M.CTXC##	;(00) DEFAULT JOB CONTEXT QUOTA
JOBCPQ:	EXP	M.CTXP##	;(01) DEFAULT JOB SAVED PAGE QUOTA
SYSCCQ:	BLOCK	1		;(02) SYSTEM-WIDE CONTEXT QUOTA
SYSCPQ:	BLOCK	1		;(03) SYSTEM-WIDE PAGE QUOTA
SYSCCU:	BLOCK	1		;(04) SYSTEM-WIDE CONTEXTS IN USE
SYSCPU:	BLOCK	1		;(05) SYSTEM-WIDE PAGES IN USE
TOTSAV:	BLOCK	1		;(06) TOTAL NUMBER OF CONTEXT SAVES
NPQEXC:	BLOCK	1		;(07) AUTO-SAVE SAVE QUOTA EXCEEDED COUNT
NPPEXC:	BLOCK	1		;(10) AUTO-SAVE PAGE QUOTA EXCEEDED COUNT
JPQEXC:	BLOCK	1		;(11) JACCT PROGRAM SAVE QUOTA EXCEEDED COUNT
JPPEXC:	BLOCK	1		;(12) JACCT PROGRAM PAGE QUOTA EXCEEDED COUNT
DIRPTR:	EXP	CTXDIR##	;(13) BYTE POINTER TO CONTEXT DIRECTORY MAP

CTXMXL==:<.-CTXTAB-1>B26	;MAXIMUM ENTRY IN GETTAB

	$HIGH

CTXEND::!END