perm filename NWORLD[10X,AIL] blob sn#102531 filedate 1974-05-22 generic text, type T, neo UTF8
00100	COMMENT ⊗   VALID 00033 PAGES VERSION 17-1(13)
00200	RECORD PAGE   DESCRIPTION
00300	 00001 00001
00400	 00004 00002	HISTORY
00500	 00009 00003	 MANY DECLARATIONS
00600	 00015 00004	PROCESS VARIABLE NUMBERS
00700	 00018 00005	event variables
00800	 00019 00006	procedure descriptors & null process skeleton
00900	 00021 00007	DSCR SPROUT -- THE PROCESS SPROUTER
01000	 00028 00008	
01100	 00035 00009	
01200	 00036 00010	routines for inserting & deleting set elements
01300	 00040 00011	USER REQUESTED SCHEDULING
01400	 00045 00012	HERE(RESUME)
01500	 00049 00013	SUSPEND and TERMINATE runtime routines
01600	 00052 00014	The JOIN runtime routine
01700	 00054 00015	THE MAIN PROCESS INITIALIZER
01800	 00056 00016	CALLER , MYPROC, AND PSTATUS 
01900	 00058 00017	 PRISET -- ROUTINE USER CALLS TO CHANGE PRIORITY 
02000	 00059 00018	SPECIAL GC ROUTINE FOR PROCESSES
02100	 00060 00019	INTERRUPT ROUTINES
02200	 00064 00020	THE INTERRUPT PROCESS
02300	 00068 00021	
02400	 00069 00022	 CAUSE 
02500	 00071 00023	CAUSE1 -- ROUTINE TO DO ACTUAL WORK 
02600	 00074 00024	ANSWER -- subroutine used by CAUSE
02700	 00076 00025	DELWRQ -- delete all wait requests
02800	 00078 00026	INTERROGATE
02900	 00080 00027	ASK -- used by INTERROGATE
03000	 00083 00028	MKEVTT,SETCP,& SETIP
03100	 00084 00029	SPARE HERE TABLE ENTRIES
03200	 00085 00030	COMPIL(IRP,,,,,,DUMMYFORGDSCISS)
03300	 00087 00031	HERE(INTTBL)
03400	 00090 00032	PROCEDURES TO ENABLE FOR INTERRUPTS
03500	 00101 00033	
03600	 00102 ENDMK
03700	⊗;
     

00100	COMMENT ⊗HISTORY
00200	AUTHOR,REASON
00300	021  102100000015  ⊗;
00400	
00500	
00600	COMMENT ⊗
00700	VERSION 17-1(13) 3-26-74 BY RLS INSTALL TENEX
00800	VERSION 17-1(12) 12-8-73 BY JRL  REMOVE SPECIAL STANFORD CHARACTERS(WHERE POSSIBLE)
00900	VERSION 17-1(11) 12-8-73 BY RHT FIX IEXT5 SCREW FOR EXPO WORLD
01000	VERSION 17-1(10) 12-8-73 BY RHT CHANGE PLACE WHERE REMEMBER THE APRENB BITS
01100	VERSION 17-1(9) 12-4-73 BY rht fix process string garb coll routine
01200	VERSION 17-1(8) 12-3-73 BY RHT MAKE SUSPEND(OTHERGUY) RETURN ANY
01300	VERSION 17-1(7) 12-2-73 BY RHT ADD A FEW IRP SPARES
01400	VERSION 17-1(6) 10-30-73 BY RHT BUG #OU# A TYPO IN %AA%
01500	VERSION 17-1(5) 10-30-73 BY RHT BUG #OT# SPROUT APPLY BUG
01600	VERSION 17-1(4) 10-28-73 BY RHT FEAT %AG% INITIALIZE RSMR←DADDY WHEN SPROUT
01700	VERSION 17-1(27) 10-14-73 BY RHT BUG #OO# SPROUT APPLY TROUBLES
01800	VERSION 17-1(26) 9-1-73 BY RHT FEATURE %AA% -- ADD CODE FOR SPROUT DEFAULTS
01900	VERSION 17-1(25) 8-19-73 BY RHT FIX COMPIL FOR SAIIRP TO KNOW ABOUT APRACS
02000	VERSION 17-1(24) 7-26-73 BY RHT **** VERSION 17 ****
02100	VERSION 16-2(23) 7-15-73 BY RHT BUG #NC# ASKNTC WAS WRONG
02200	VERSION 16-2(22) 7-15-73 BY RHT MORE OF BUG NB
02300	VERSION 16-2(21) 7-15-73 BY RHT BUG #NB# NOT GETTING CONTXT RIGHT FOR USER IP
02400	VERSION 16-2(20) 7-14-73 BY RHT MAKE SAIIRP A SEP COMPIL & PROVIDE FOR APPL$Y
02500	VERSION 16-2(19) 7-14-73 BY RHT BUG #NA# RACE CONDITION IN URSCHD IWAIT
02600	VERSION 16-2(18) 3-18-73 BY RHT MINOR MOD TO DFR1IN
02700	VERSION 16-2(17) 2-4-73 BY RHT PROVIDE MORE HOOKS INTO EVENT ROUTINES
02800	VERSION 16-2(16) 1-15-73 BY DCS BUG #LB# MINOR RESUME BUG
02900	VERSION 16-2(15) 12-9-72 BY RHT MAKE MINOR ADJUSTMENTS TO RESUME
03000	VERSION 16-2(14) 12-4-72 BY RHT INTERNAL PSTATUS
03100	VERSION 16-2(13) 12-4-72 BY RHT  CURE POTENTIAL LOSSAGE OF STATIC LINKAGE
03200	VERSION 16-2(12) 12-2-72 BY RHT REWRITE RESUME
03300	VERSION 16-2(11) 12-1-72 BY RHT PROVIDE FOR DEFAULTS AS CORE VARS
03400	VERSION 16-2(10) 11-30-72 BY RHT ADD THE DDFINT ROUTINE & ZAP POLL
03500	VERSION 16-2(9) 11-29-72 BY DCS ADD INTERRUPT THINGS TO ENTRIES IN COMPIL
03600	VERSION 16-2(8) 11-29-72 BY RHT RESUME DISPATCH NEEDS @
03700	VERSION 16-2(7) 11-26-72 BY DCS ALLOW <ESC>I AS IO INTERRUPT (AVOID "NO ONE TO RUN")
03800	VERSION 16-2(6) 11-26-72 BY DCS CHANGE OPDEF FOR INTENS TO 400030 FROM ..31
03900	VERSION 16-2(5) 11-25-72 BY RHT FIX DATAB & INFTAB REFERENCES
04000	VERSION 16-2(4) 11-15-72 BY RHT ADD OPTIONS FOR RESUME
04100	VERSION 16-2(3) 11-15-72 BY RHT ADD INTERRUPTS,SPARE HERE ENTRIES
04200	VERSION 16-2(2) 11-15-72 
04300	VERSION 16-2(1) 11-15-72 
04400	
04500	⊗;
     

00100	; MANY DECLARATIONS
00200	TENX<
00300	↓APRISW←←1	;Not always what's wanted but better than 0.
00400	>;TENX
00500	COMPIL(PRC,,,,,,DUMMYFORGDSCISS)
00600	DEFINE ENS1 < SPROUT,URSCHD,RESUME,SUSPEND,TERMINATE,JOIN,MAINPR,CALLER>
00700	DEFINE ENS2 <%PSSGC,DDFINT,INTSET,CAUSE,ANSWER,INTERROGATE,SETCP>
00800	DEFINE ENS3 <MKEVTT,SETIP,MYPROC,CLKMOD,DFR1IN,DFRINT,INTPRO>
00900	DEFINE ENS4 <DFCPKT,PSTATUS,ASKNTC,CAUSE1,PRISET>
01000	DEFINE EXT1 <LEAP,STKUWD,X44,GOGTAB,%ARSR1,SGINS,ALLPDP>
01100	DEFINE EXT2 <CORGET,CORREL,INTRPT,INFTB,%SPGC,X22,%SPGC1,FP1DON,STACSV>
01200	DEFINE EXT3 <X33,%ARRSR,DATM,SGLKBK,FP2DON,SGREM,STACRS,RUNNER,NOPOLL>
01300	DEFINE EXT4 <X11,DEFSSS,DEFPSS,DEFPRI,DEFQNT,INTTBL,APPL$Y>
01400	
01500	IFN APRISW <
01600	DEFINE XJBCNI <JOBCNI>
01700	DEFINE XJBTPC <JOBTPC>
01800	DEFINE XJBAPR <JOBAPR>
01900	DEFINE EXT5 <JOBCNI,JOBTPC,JOBAPR>
02000	IFN ALWAYS <
02100	EXTERN EXT5	;THESE ARE ALWAYS EXTERNAL
02200	>;IFN ALWAYS
02300	>;IFN APRISW
02400	IFE APRISW <
02500	DEFINE EXT5 <XJBCNI,XJBTPC,XJBAPR,JOBINT>
02600	IFN ALWAYS <
02700	EXTERNAL JOBINT ;THIS FELLOW IS ALWAYS EXTERNAL
02800	>;IFN ALWAYS
02900	>;IFE APRISW
03000	COMMENT ⊗THIS IS FOR THE STUPIDITY OF SCISS ⊗
03100	
03200	COMPXX(PRC,<ENS1,ENS2,ENS3,ENS4>,<EXT1,EXT2,EXT3,EXT4,EXT5>
03300		,<MULTIPLE PROCESS STUFF>,<SPRPDA>,HIIFPOSSIB)
03400	
03500	
03600	
03700	BEGIN PROCSS
03800	
03900	; (AC DEFNS)
04000	
04100	; A,B,C,P,SP,RF AS BEFORE
04200	KL	←D	;KILL LIST & SCRATCH
04300	PB	←5	;PROCESS BASE
04400	OPTS	←6	;HOLDS OPTIONS
04500	PDA	←7	;HOLDS PDA
04600	EVT	←10	;EVENT DATUM
04700	NSP	←←10	;NEW SP
04800	NP	←11	;NEW P
04900	TMP	←LPSA	;TEMP AC
05000	
05100	GLOB < 
05200	TABL ←← 7	;NEEDED BY LIST CELL GETTER
05300	>;GLOB
05400	NOGLOB <
05500	TABL ←← USER	;NEEDED BY LIST CELL GETTER
05600	>;NOGLOB
05700	FP ←← 6		;NEEDED BY LIST CELL GETTER
05800	
05900	; (LOCAL VARIABLES FOR SCHEDULER)
06000	MAXPRI ←← 0	;MAXIMUM PRIORITY
06100	MINPRI ←← NPRIS-1
06200	
06300	;REASONS FOR SUSPENSION
06400	PSPF←←0		;ONLY P, SP, F NEED BE RESTORED
06500	SPNDR←←1	;SUSPENDED (FROM READY) BY SUSPEND
06600	JOINR←←2	;SUSPENDED BECAUSE OF A JOIN
06700	WAITNG←←3	;WAITING ON AN EVENT OR SO
06800	
06900	; ( CONSTANT DATA USED BY SPROUTER)
07000	
07100	; FIELD DEFNS FOR OPTIONS WORD (SEE ALSO POINT S BELOW)
07200	
07300	STSMSK←	77 ⊗ =8	;MASK FOR P STACK SIZE FIELD
07400	SSSMSK←	17 ⊗ =14;MASK FOR SP STACK SIZE FIELD OF OPTIONS WORD
07500	PRIMSK←	17 ⊗ 4	;MASK FOR PRIORITY FIELD
07600	QNTMSK←← 17	;MASK FOR QUANTUM
07700	RUNME←←	1	;RUN THE SPROUTING PROCESS
07800	SPNDME←←2	;SUSPEND THE SPROUTING PROCESS
07900	SPNDNP←←10	;SUSPEND THE NEW PROCESS
08000	
08100	;MORE FIELD DEFS & BIT VALUES
08200	TERM  ←← 1	;BIT (LH) IN DATUM OF TERMINATED PROCESS ITEM
08300	
08400	;DEFAULT VALUES --INITIALLY SET BY MAINPR
08500	
08600	STPSZ←	40	;DEFAULT P- STACK SIZE (MINUS THE PROCESS TABLE AREA)
08700	STSPST ←20	;DEFAULT SP STACK SIZE
08800	STDQNT ←← 4	;DEFAULT STD QUANTUM IS 4
08900	STDPRI	←←7	;DEFAULT PRIORITY
09000	
09100	;OPTIONS FOR RESUME
09200	MSTMSK←←14	;MASK FOR MY NEW STATUS FIELD
09300	NOTNOW←←1	;SET IF RESUMED PROCESS IS MERELY TO GO READY
09400	
09500	;CONSTANTS USED BY RESUME
09600	MSTBYT:	POINT	2,OPTS,33 ;MY NEW STATUS
09700	
09800	; (CONSTANTS USED BY SPROUTER)
09900	SSSBYT:	POINT	4,OPTS,21	;STRING STACK FIELD (MOD 32)
10000	STSBYT:	POINT	6,OPTS,27	;P - STACK FIELD (MOD 32)
10100	PRIBYT:	POINT	4,OPTS,31	;PRIORITY FIELD
10200	QNTBYT:	POINT	4,OPTS,17	;LOG2 (QUANTUM)
10300	
10400	
10500	; MACROS USED TO GET LIST CELLS
10600	DEFINE NCELL(AC) <
10700		MOVE	FP,FP1(TABL)	;USE WHERE SURE THE LIST SPACE IS INITIALIZED
10800		HRRI	AC,(FP)
10900		SKIPN	FP,(FP)
11000		PUSHJ	P,FP1DON
11100		HRRM	FP,FP1(TABL)
11200	>
11300	
11400	DEFINE NNCELL(AC) <
11500		SKIPN	FP,FP1(TABL)	;USE WHERE LIST SPACE MAY NEED INITIALIZATION
11600		PUSHJ	P,FP1DON
11700		HRRI	AC,(FP)
11800		SKIPN	FP,(FP)
11900		PUSHJ	P,FP1DON
12000		HRRM	FP,FP1(TABL)
12100	>
12200	
12300	DEFINE NNCLL2(AC) <
12400		SKIPN	FP,FP2(TABL)	;USE WHERE LIST SPACE MAY NEED INITIALIZATION
12500		PUSHJ	P,FP2DON
12600		HRRI	AC,(FP)
12700		SKIPN	FP,(FP)
12800		PUSHJ	P,FP2DON
12900		HRRM	FP,FP2(TABL)
13000	>
13100	
13200	NOTENX <
13300	OPDEF INTENS [CALLI 400030]
13400	OPDEF IWAIT [CALLI 400040]
13500	>;NOTENX
13600	
     

00100	;PROCESS VARIABLE NUMBERS
00200	
00300	DEFINE PVAR (V,ATTRIB),
00400		<↑V ←← NPVARS
00500		NPVARS←← NPVARS+1
00600	IFE ALWAYS,<
00700		IFDIF <ATTRIB>,<> < ATTRIB V >
00800	>;IFE ALWAYS
00900		>
01000	
01100	
01200	NPVARS←← 0
01300	
01400		PVAR	DYNL	;DYNAMIC LINK
01500		PVAR	STATL	;STATIC LINK
01600		PVAR	ISP	;REST OF MSCP
01700		PVAR	AC0	;AC SAVE AREA
01800		PVAR	AC1
01900		PVAR	AC2
02000		PVAR	AC3
02100		PVAR	AC4
02200		PVAR	AC5
02300		PVAR	AC6
02400		PVAR	AC7
02500		PVAR	AC10
02600		PVAR	AC11
02700		PVAR	AC12
02800		PVAR	AC13
02900		PVAR	AC14
03000		PVAR	AC15
03100		PVAR	AC16
03200		PVAR	AC17
03300	↑ACF ←← AC12
03400	↑ACP ←← AC17
03500	↑ACSP ←← AC16
03600		PVAR	PCW	;PC WORD
03700		PVAR	QUANTM	;TIME QUANTUM
03800		PVAR	PRIOR	;PRIORITY
03900		PVAR	PRCITM	;PROCESS ITEM OF THIS PROCESS
04000		PVAR	KLOWNR	;THE OWNER OF MY KILL LIST
04100		PVAR 	STATUS	;-1 = RUNNING, 0 = SUSPEND, 1 = READY, 2 = TERMINATED
04200		PVAR	DADDY,INTERNAL	;PROCESS ITEM OF SPROUTING PROCESS
04300		PVAR	CAUSRA	;RETN ADDRESS FROM CAUSE
04400	;THE FOLLOWING ARE ZEROED OUT ON CREATION
04500	ZFIRST←←NPVARS
04600		PVAR	CURSCB,INTERNAL	;CURRENT SEARCH CONTROL BLOCK
04700		PVAR	REASON	;HOW GOT UNSCHEDULED (0 MEANS ONLY NEED ACS F,SP,P)
04800		PVAR	PLISTE	;PRIORITY LIST ENTRY
04900		PVAR	RSMR	;THE GUY WHO RESUMED ME (%AG% ** INIT TO DADDY ** )
05000		PVAR	JOINCT	;HOW MANY PROCESSES NEED TO JOIN THIS ONE
05100		PVAR	JOINS	;WHO IS WAITING TO FOR ME TO JOIN (A SET OF ITEMS)
05200		PVAR	WAITES	;LIST OF ALL EVENT TYPES ON WHICH I AM WAITING
05300		PVAR	INTRGC	;THE CONTROL WORD FOR MY CURENT INTERROGATION
05400		PVAR	CAUSES	;COUNT OF CAUSES PENDING
05500		PVAR	CAUSEQ	;QUEUE OF CAUSES TO BE MADE
05600	ZLAST←←NPVARS-1
05700	
05800	↑NPVARS ← NPVARS
05900	↑STKBAS ← NPVARS	;STACK BASE SIZE (= #PROCESS VARS FOR NOW)
     

00100	COMMENT ⊗event variables⊗
00200	
00300	NEVARS←←0
00400	
00500	DEFINE EVAR(V) ,
00600		<↑↑V←←NEVARS
00700		NEVARS←←NEVARS+1
00800		>
00900	
01000		EVAR	NOTCLS		;LIST OF CURRENT NOTICES
01100		EVAR	WAITLS		;LIST OF CURRENTLY WAITING PROCESSES
01200		EVAR	CAUSEP		;USER SPEC CAUSE PROC
01300		EVAR	INTRGP		;USER SPEC INTERROGATE PROC
01400		EVAR	USER1		;AVAIL TO USER
01500		EVAR	USER2		;AVAIL TO USERR
01600	
01700	;OPTIONS BITS FOR CAUSE
01800	DNTSAV ←← 1
01900	TELLAL ←← 2
02000	SCHDIT ←← 4
02100	
02200	;OPTIONS BITS FOR INTERROGATE
02300	RETAIN ←← 1
02400	WAIT   ←← 2
02500	SAYWCH ←← 10
02600	MULTIN ←← 200000
02700	NOJOY  ←← 400000
02800	
     

00100	COMMENT ⊗procedure descriptors & null process skeleton⊗
00200	
00300	FLXXX←←0
00400	UP <
00500	FLXXX←←%FIRLOC-400000
00600	>;UP
00700	
00800	
00900	DEFINE PUTINLOC(LCN,V),< 
01000	UP <
01100		SVPCXX ←← .
01200		DEPHASE
01300	>;UP
01400		RELOC LCN+FLXXX
01500		V
01600		RELOC
01700	UP <
01800		PHASE SVPCXX
01900	>;UP
02000	>
02100	
02200	;MAKE A PD FOR THE SPROUTER
02300	↑SPRPDA:BLOCK PD.XXX+1
02400	
02500	DEFINE FPDE(IX,V),<PUTINLOC (SPRPDA+IX,V)>
02600	
02700		FPDE	(PD.,SPROUT)
02800		FPDE	(PD.DSW,STKBAS)
02900		FPDE	(PD.PDA,<<XWD SPRPDA,0>>)
03000		FPDE	(PD.LLW,<SPRPDA+PD.XXX>)
03100		FPDE	(PD.DLW,<SPRPDA+PD.XXX>)
03200	
03300	
03400	IFN 0,<
03500	
03600	;NULL PROCESS
03700	NULPDA:	NULPRO			;PD OF NUL PROC
03800	↑NULPRC: %NULPR			;NULL PROCESS
03900	
04000	%NULPR:	BLOCK STKBAS+=32	;NULL PROCESS AREA
04100	
04200	DEFINE NPE (IX,V), <PUTINLOC (%NULPR+IX,V)>
04300	
04400		NPE	(STATL,<<XWD SPRPDA,0>>)
04500		NPE	(ACF,STKBAS+%NULPR+1)
04600		NPE	(ACP,<<TPDL: XWD - =29,%NULPR+STKBAS+3>>)
04700		NPE	(STKBAS+1,%NULPR+DYNL)
04800		NPE	(STKBAS+2,<<XWD NULPDA,0>>)
04900	
05000	
05100	
05200	↑NULPRO:
05300		ERR	<I SHOULD NEVER RUN>
05400	>;IFN 0
05500	
05600	
05700	
05800	
05900	
06000	
06100	
     

00100	DSCR SPROUT -- THE PROCESS SPROUTER
00200	CAL 	PUSHJ
00300	PARM	-1(P)	;KILL LIST
00400		-2(P)	;OPTIONS WORD
00500		-3(P)	;PDA OF SPROUTED PROCESS
00600		-4(P)	; PROCEDURE PARAMS
00700		:
00800		-?(P)	;LAST OF PROCEDURRE PARAMS
00900		-?-1(P)	;PROCESS ITEM
01000	DES 
01100		This procedure acts as the "process" procedure.
01200	Roughly, it does the following:
01300	
01400	1. Saves the return address in PCW(RUNNER)
01500	2. gets stack space
01600	3. puts self on appropriate kill list & priority list
01700	4. copies over the procedure parameters.
01800	5. sets status of new & SPROUTing process
01900		&(eventually) calls the appropriate procedure.
02000	6. when the procedure returns, SPROUT then kills the process.
02100	
02200	⊗
02300	HERE (SPROUT)
02400		MOVE	USER,RUNNER	;
02500		POP	P,PCW(USER)	;RETN ADDRESS
02600		POP	P,KL		;PICK UP KILLL LIST
02700		POP	P,OPTS		;OPTIONS
02800		POP	P,PDA		;FIND OUT WHO
02900	;;%AA% -- 1 OF 1  DEFAULTS, ALSO THE POP P,PDA USED TO BE LATER
03000		CAIN 	PDA,APPL$Y	;SPROUT APPLY IS A ROYAL PAIN
03100	;;#OU# A TYPO RHT
03200		SKIPA	TMP,-1(P)	;REAL PDA FOR SPROUT APPLY
03300		MOVE	TMP,PDA		;
03400		HRRZ	A,PD.PDB(TMP)	;THE DEFAULTS
03500		JUMPE	A,SALCS		;NO DEFAULTS -- SPROUT ALLOCATIONS NOW
03600		LSH	A,4		;INTO POSITION
03700		TRNE	OPTS,STSMSK	;P STACK
03800		TRZ	A,STSMSK
03900		TRNE	OPTS,SSSMSK	;SP STACK
04000		TRZ	A,SSSMSK
04100		TRNE	OPTS,PRIMSK	;PRIORITY
04200		TRZ	A,PRIMSK
04300		TLNE	OPTS,QNTMSK	;QUANTUM
04400		TLZ	A,QNTMSK	;
04500		IOR	OPTS,A		;OR IN THE BITS FOR DEFAULTS
04600	SALCS:
04700	;;%AA%
04800	
04900		TRNE	OPTS,SSSMSK	;SPECIFIED SP STACK SIZE ?
05000		JRST	[ LDB C,SSSBYT	;YES, GET IT
05100			LSH   C,5	;TIMES 32
05200			JRST  .+2 ]
05300		MOVE	C,DEFSSS	;STANDARD SIZE
05400		PUSHJ	P,CORGET	;GET SPACE
05500		ERR	<NOT ENOUGH CORE -- SPROUT >
05600		MOVN	C,C		;MAKE PDP
05700		HRLZI	NSP,-1(C)	
05800		HRRI	NSP,-1(B)
05900		TRNE	OPTS,STSMSK	;P - STACK
06000		JRST	[ LDB C,STSBYT	;YES, GET IT
06100			LSH	C,5	;TIMES 32
06200			JRST	.+2]
06300		MOVE	C,DEFPSS	;STANDARD AMOUNT TO GET
06400		ADDI	C,STKBAS	;SPACE FOR BASE
06500		PUSHJ	P,CORGET	;GET ROOM
06600		ERR	<NOT ENOUGH CORE -- SPROUT >
06700		MOVE	PB,B		;PROCESS BASE
06800		MOVN	C,C
06900		HRLZI	NP,STKBAS(C)	;MAKE PDP
07000		HRRI	NP,STKBAS(PB)
07100	
07200	;ZERO OUT SOME OF THE PROCESS VARS
07300		HRLZI	A,ZFIRST(PB)	;
07400		HRRI	A,ZFIRST+1(PB)
07500		SETZM	ZFIRST(PB)
07600		BLT	A,ZLAST(PB)
07700	
07800	;REMEMBER DADDY
07900		MOVE	USER,RUNNER
08000		MOVE	A,PRCITM(USER)
08100		MOVEM	A,DADDY(PB)
08200	;;%AG% ! REMEMBER SPROUTER AS THE FIRST CALLER. RHT
08300		MOVEM	A,RSMR(PB)	;SO CALLER(MYPROC) STARTS OUT AS DADDY
08400	
08500	;BUILD MSCP, ETC.
08600	
08700		SETZM	DYNL(PB)	;NULL DYN LINK
08800		CAIN	PDA,APPL$Y	;IS IT A SPROUT APPLY?
08900		JRST	[		;YES
09000	UP <
09100			MOVE	PDA,(PDA) ;SINCE APPL$Y IS HERED
09200	>;UP
09300			POP	P,TMP	;ARG LIST
09400			POP	P,A	;PDA OF TARGET
09500			PUSH	NP,A	;PUT ON CALL STACK
09600			PUSH	NP,TMP	;PUT ON CALL STACK
09700	;;#OO# !(1 OF 2) A TYPO
09800			HRLZI	TMP,SPRPDA
09900			HLRZ	C,PD.DLW(A) ;LOOK FOR RIGHT LINK
10000	;;#OT# ! RHT DONT LOOK IF THE FELLOW SUPPLIES AN ENVIRONMENT
10100			TLNN	A,-1	;ENVIRON SUPPLIED??
10200			CAIG	C,1	;GLOBAL??
10300			JRST	SSLON	;YES
10400			HRRZ	A,PD.PPD(A);
10500			SKIPA	TMP,RF
10600		SSLFLP:	HLRZ	TMP,C
10700			MOVS	C,1(TMP)
10800			CAIE	A,(C)
10900			JRST	SSLFLP
11000	;;#OO# ! (2 OF 2) NEED TO SAY A SPROUT
11100			HRLI	TMP,SPRPDA
11200		SSLON:	MOVEM	TMP,STATL(PB)
11300			MOVEM	NSP,ISP(PB)
11400			JRST	APSON	]
11500		HLRZ	A,PD.DLW(PDA)	;DISPLAY LEVEL
11600		HRLZI	TMP,SPRPDA	;IN CASE OUTER LEVEL
11700		CAIG	A,1		;OUTER BLOCK PROC?
11800		JRST	SLON		;YES -- NO LOOP
11900		HRRZ	A,PD.PPD(PDA)	;THE LEXICAL PARENT
12000		SKIPA	TMP,RF		;DYNL
12100	SLFLP:	HLRZ	TMP,C		;BACK A STATL
12200		MOVS	C,1(TMP)	;SL,,PDA
12300		CAIE	A,(C)		;SAME AS DADDY?
12400		JRST	SLFLP		;NO
12500		HRLI	TMP,SPRPDA	;SPRPDA,,STATL
12600	SLON:	MOVEM	TMP,STATL(PB)	;STATIC LINK WORD
12700		MOVEM	NSP,ISP(PB)	;SP WORD
12800	
12900	;COPY PROC PARAMS
13000	
13100		HLRZ	TMP,PD.NPW(PDA)	;#STRING PARAMS*2
13200		JUMPE	TMP,STPSON	;HAVE ANY ?
13300		HRL	TMP,TMP		;YES, DO A BLT
13400		HRRZI	A,1(NSP)	;DEST
13500		ADD	NSP,TMP		;BUMP OLD STACK
13600		SUB	SP,TMP		;DECREMENT OLD STACK
13700		HRLI	A,1(SP)		;SOURCE
13800		BLT	A,(NSP)		;COPY THEM
13900	STPSON:	HRRZ	TMP,PD.NPW(PDA)	;# ARITH PARMS +1
14000		SOJLE	TMP,APSON	;ANY TO BLT ?
14100		HRL	TMP,TMP		;MAKE XWD
14200		HRRZI	A,1(NP)		;DEST
14300		ADD	NP,TMP
14400		SUB	P,TMP
14500		HRLI	A,1(P)
14600		BLT	A,(NP)		;DO IT
14700	APSON:
14800	
     

00100	
00200	;NOW  SET UP NEW PROCESS'S STATUS, QUANTUM, & PRIORITY
00300	
00400		SETOM	STATUS(PB)		;ASSUME RUNNING
00500		TRNE	OPTS,SPNDNP		;UNLESS SUSPEND
00600		SETZM	STATUS(PB)		;0 MEANS SUSPENDED
00700		MOVE	TMP,DEFQNT		;STANDARD QUANTUM
00800		TLNN	OPTS,QNTMSK		;GET LOG2 QUANTUM
00900		JRST	SVQNT			;NO NEED
01000		LDB	A,QNTBYT
01100		MOVEI	TMP,1
01200		LSH	TMP,(A)
01300	SVQNT:	MOVEM	TMP,QUANTM(PB)
01400		MOVE 	A,DEFPRI		;ASSUME STD PRIORITY
01500		TRNE	OPTS,PRIMSK		;SAID OTHERWISE?
01600		LDB	A,PRIBYT
01700		PUSHJ	P,SETPRI		;GO SET PRIORITY
01800	
01900	;SET UP PROCESS ITEM
02000	
02100		POP	P,C			;PICK UP ITEM #
02200		MOVEM	C,PRCITM(PB)		;REMEMBER IT
02300		MOVEI	A,PRCTYP		;SAY IS OF TYPE PROCESS
02400	
02500	COMMENT **** MAY WANT TO WORRY HERE ABOUT GLOBAL ITEMS **** ;
02600	
02700		MOVE	TABL,GOGTAB
02800		DPB	A,INFOTAB(TABL)		;SAY IS A PROCESS
02900		HRRZM	PB,@DATAB(TABL)		;SET DATUM VALUE
03000	
03100	;KILL SET STUFF
03200		MOVE	B,C			;ITEM NUMBER
03300		MOVEM	KL,KLOWNR(PB)		;REMEMBER KILL LIST OWNER
03400		JUMPE	KL,NEWSTT		;ONLY PUT ON KILL SET IF HAVE ONE
03500		PUSH	P,TABL			;NEED TO SAVE THESE
03600		PUSH	P,FP			;
03700		PUSHJ	P,INSRTS		;GO PUT ITEM IN KILL SET
03800		POP	P,FP
03900		POP	P,TABL
04000	
04100	;NOW DECIDE WHAT TO DO WITH SPROUTING PROCESS & DO THE RIGHT THING
04200	
04300	NEWSTT:	MOVE 	USER,RUNNER		;HOPE IT IS STILL HIM
04400		TRNE	OPTS,RUNME		; DOES SPROUTING PROCESS WANT TO RUN?
04500		JRST	RNSPRR			;YES
04600		MOVEM	P,ACP(USER)		;IF HERE, THEN WANT TO RUN NEW GUY
04700		MOVEM	SP,ACSP(USER)		;SAVE THE NECESSARY ACS
04800		MOVEM	RF,ACF(USER)		;
04900		MOVNS	STATUS(USER)		;RUNNING BECOMES READY
05000		TRNE	OPTS,SPNDME		;IF I WANTED SUSPENSION
05100		SETZM	STATUS(USER)		;DO IT
05200		SKIPL	STATUS(PB)		;DOES SPROUTED PROCESS WANT TO RUN
05300		JRST	NORFR			;NO
05400		MOVE	USER,GOGTAB
05500		MOVE	A,QUANTM(PB)
05600		MOVEM	A,TIMER(USER)
05700		MOVE	P,NP			;
05800		MOVE	SP,NSP			;GET READY
05900		MOVEI	RF,DYNL(PB)		;
06000		MOVEM	PB,RUNNER
06100	CALLIT:	PUSHJ	P,@PD.(PDA)		;CALL THE SO AND SO
06200	
06300	;HERE IS WHERE WE COME ON PROCEDURE EXIT
06400	CALRET:	MOVE	PB,RUNNER		;I HOPE ITS ME
06500		PUSHJ	P,KACTS			;DO EVERYTHING BUT SPACE FREEING
06600		MOVE	P,ALLPDP		;USE THIS PDL FOR KILLING CORE
06700	
06800	;NOW KILL CORE FOR SP STACK
06900	
07000		HRRZ	B,ISP(PB)
07100		ADDI	B,1
07200		PUSHJ	P,CORREL
07300	
07400	;NOW KILL CORE FOR P-STACK
07500	
07600		HRRZI	B,(PB)
07700		PUSHJ	P,CORREL
07800	
07900	;NOW ALL TRACES ARE GONE (I HOPE)
08000	
08100		JRST	FOTR			;GO FIND SOMETHING TO DO
08200	
08300	;PROCEDURE THAT PERFORMS ALL KILL ACTIONS EXCEPT STACK RELEASING
08400	;EXPECTS PB TO POINT AT THE CONDEMNED PROCESS
08500	;USES A,B,C,KL
08600	
08700	KACTS:	HRRZ	C,PRCITM(PB)
08800		MOVE	B,C			;
08900		MOVE	TABL,GOGTAB		;
09000		TLO	PB,TERM			;SET TERM BIT
09100		MOVEM	PB,@DATAB(TABL)		;TERMINATED
09200		SKIPE	KL,KLOWNR(PB)		;IF HAVE A KILL SET
09300		PUSHJ	P,DELTSE		;DELETE FROM SET
09400	
09500	;NOW  CHECK TO SEE IF WE WERE ON ANY JOIN LISTS
09600	
09700		SKIPN	A,JOINS(PB)
09800		JRST	REMPRI
09900		MOVE	KL,GOGTAB	;
10000	KACT.1:	HLRZ	C,(A)		;THE ITEM
10100		MOVE	B,@DATAB(TABL)	;GET ADDRESS OF THE DATUM
10200		TLNE	B,TERM		;DEAD ALREADY??
10300		JRST	KACT.2		;YES
10400		SOSLE	JOINCT(B)	;READY TO ROLL ??
10500		JRST	KACT.2		;NO
10600		SKIPN	STATUS(B)	;CURRENT STATUS
10700		AOS	STATUS(B)	;READY
10800	KACT.2:	HRRZ	B,(A)
10900		HRR	C,FP1(KL)	;RELEASE LIST CELL
11000		HRRM	C,(A)	
11100		HRRM	A,FP1(KL)	;NEW FREE LIST
11200		JUMPE	B,REMPRI	;END OF LIST
11300		MOVE	A,B		;
11400		JRST 	KACT.1
11500	
11600	
11700	
11800	;NOW TAKE OFF PRIORITY LIST AND RETURN
11900	;NOTE -- THE CODE FROM HERE TO THE POPJ IS ITSELF A PROCEDURE USED
12000	;ELSEWHERE TO REMOVE PROCESS (PB) FROM ITS PRIORITY LIST
12100	;SIDE EFFECTS -- USES A,B,C 
12200	
12300	REMPRI:	MOVE	A,PRIOR(PB)
12400		ADD	A,GOGTAB
12500		HRRZ	B,PLISTE(PB)
12600		HLRZ	C,PLISTE(PB)
12700		JUMPN	C,.+3
12800		HRRM	B,PRILIS(A)		;HEAD OF LIST
12900		JRST	.+2
13000		HRRM	B,PLISTE(C)		;NEXT(C)←B
13100		JUMPN	B,.+3
13200		HRLM	C,PRILIS(A)		;NEW TAIL
13300		POPJ	P,
13400		HRLM	C,PLISTE(B)		;PREV(B)←C
13500		POPJ	P,
13600	
13700	;PROCEDURE TO PUT PROCESS (PB) ON PRIORITY LIST A
13800	;SIDE EFFECT -- MODIFIES B
13900	SETPRI:	MOVEM	A,PRIOR(PB)		;REMEMBER MY PRIORITY
14000		ADD	A,GOGTAB
14100		SKIPE	B,PRILIS(A)		;PRIORITY LIST OWNER
14200		HRLM	PB,PLISTE(B)		;LINK BACK
14300		HRRZM	B,PLISTE(PB)		;LIINK DOWM
14400		HRRM	PB,PRILIS(A)		;NEW RHS FOR OWNER IS PTR TO  ME
14500		TLNN	B,-1			;WAS THE LIST EMPTY ??
14600		HRLM	PB,PRILIS(A)		;YES -- THIS IS THE TAIL TOO
14700	CPOPJ:	POPJ	P,
14800	
     

00100	
00200	;HERE IF DONT WANT TO RUN NEW GUY RIGHT AWAY
00300	NORFR:	TROA	B,1			;FLAG
00400	RNSPRR:	MOVEI	B,0
00500		MOVNS	STATUS(PB)		;IF NEW IS "RUNNING", THEN "READY"
00600		PUSH	NP,[CALRET]		;
00700		MOVEM	NP,ACP(PB)		;SET UP NEC. SAVES
00800		MOVEM	NSP,ACSP(PB)
00900		MOVEI	A,DYNL(PB)		
01000		MOVEM	A,ACF(PB)
01100		MOVE	A,PD.(PDA)		;WHERE HE STARTS
01200		MOVEM	A,PCW(PB)
01300		CAIN	B,			;SPROUTER RUNS??
01400		JRST	@PCW(USER)		;YES -- 
01500		JRST	FOTR			;NO -- FIND SOMEONE TO RUN
01600	
     

00100	COMMENT ⊗routines for inserting & deleting set elements⊗
00200	
00300	;expects item no in B , (KL) = the owner
00400	;mangles A,B,C,FP,TABL
00500	
00600	INSRTS:	MOVE	TABL,GOGTAB
00700		SKIPN	A,(KL)		;GET OWNER
00800		JRST	NEWINS		;IT WAS NULL BEFORE
00900		MOVE	C,(A)		;POINT AT FIRST
01000	ISCH:	MOVS	C,(C)		;CONTENTS (SWAPPED) OF THIS
01100		CAILE	B,(C)		;ELIGIBLE
01200		JRST	NX1		;MUST GO FURTHER
01300		CAIL	B,(C)		;THERE ALREADY?
01400		POPJ	P,		;YES
01500	NI:	HRL	B,(A)		;POINTER AT THIS
01600		NCELL	(C)		;GET A CELL FOR IT
01700		MOVSM	B,(C)		;SAVE CONTENTS OF CELL
01800		HRRM	C,(A)		;LINK TO NEW
01900		HRLZI	A,1
02000		ADDB	A,(KL)		;UPDATE COUNT -- POINT AT LAST,,FIRST
02100		TLNN	B,-1		;AT THE END???
02200		HRLM	C,(A)		;YES
02300		POPJ	P,
02400	NX1:	HRRZ	A,(A)
02500		TLNN	C,-1		;END OF LIST
02600		JRST	NI		;YES -- PUT AT END
02700		MOVSS	C
02800		JRST	ISCH		;GO LOOK SOME MORE
02900	NEWINS:	NNCELL	(A)
03000		SETZM	(A)
03100		HRRZM	A,(KL)		;IT USED TO BE NULL
03200		JRST	NI
03300	
03400	;ROUTINES FOR ADDING TO LISTS
03500	;EXPECT ITEM NO IN B, KL= ADRS OF OWNER
03600	;MANGLE A,B,C,FP,TABL
03700	;;#QK# RHT ! SET UP OF TABL NEEDED
03800	IHEDLS:	MOVE	TABL,GOGTAB
03900		SKIPN	A,(KL)		;INSERT AT HEAD
04000		JRST	NEWINS
04100		JRST	NI		
04200	ITAILS:	
04300	;;#QK# ! SET UP TABL (2 OF 2)
04400		MOVE	TABL,GOGTAB	;
04500		SKIPN	A,(KL)		;INSERT AT TAIL
04600		JRST	NEWINS
04700		MOVS	A,(A)
04800		JRST	NI
04900	
05000	
05100	;ROUTINE TO DELETE SET OR LIST ELEMENTS
05200	;B = ITEM NO, (KL) IS THE OWNER
05300	;MANGLES A,B,C,TABL
05400	
05500	DELTLE:
05600	DELTSE:	SKIPN	A,(KL)		;GET SET DESCRIPTOR
05700		POPJ	P,		;NULL ALREADY
05800		MOVE	C,(A)
05900	DSCH:	MOVE	C,(C)
06000		TLC	C,(B)
06100		TLNN	C,-1		;WAS IT THIS ONE???
06200		JRST	DIT		;YES
06300		TRNN	C,-1		;END OF SEARCH
06400		POPJ	P,		;YES
06500		MOVE	A,(A)		;LINK
06600		JRST	DSCH		;GO LOOK
06700	DIT:	MOVE	TABL,GOGTAB
06800		MOVE	B,(A)		;B PTR TO THIS CELL
06900		HRRM	C,(A)		;LINK PREV TO NEXT
07000		HRL	C,FP1(TABL)	;OLD FREE LIST
07100		HLRM	C,(B)		;LINK CELL
07200		HRRM	B,FP1(TABL)	;
07300		HRLZI	B,-1		;ADJUST DESCRIPTOR
07400		ADDB	B,(KL)
07500		TLNE	B,-1		;LIST NULL NOW???
07600		JRST	CKEND		;NO
07700		SETZM	(KL)		;YES
07800		MOVSS	(B)		;LAST,,FIRST CELL 
07900					;NOW IS 0,,PTR TO CELL JUST FREED UP
08000		HRRM	B,FP1(TABL)	;NEW FREE LIST
08100		POPJ	P,
08200	CKEND:	TRNN	C,-1		;WAS THIS THE END
08300		HRLM	A,(B)		;YES
08400		POPJ	P,
08500	
08600	
08700	;ROUTINE TO DELETE FIRST ELT OF A LIST
08800	;PUTS ITEM # INTO A
08900	;EXPECTS (KL) = THE OWNER
09000	;MODIFIES A,B,C,TABL
09100	
09200	REMCAR:	SKIPN	A,(KL)
09300		POPJ	P,		;IF WAS NULL RETURN A 0
09400		MOVE	C,(A)
09500		MOVE	C,(C)		;FIRST REAL LIST CELL
09600		HLRZ	B,C		;FIRST ONE
09700		PUSH	P,B		;SAVE IT
09800		PUSHJ	P,DIT
09900		POP	P,A		;VALUE
10000		POPJ	P,
10100	
10200	
10300	
10400	
10500	
     

00100	;USER REQUESTED SCHEDULING
00200	
00300	
00400	HERE(URSCHD)
00500		MOVE	PB,RUNNER
00600		SKIPL	STATUS(PB)		;
00700		JRST 	FOTR			;GO FIND ONE TO RUN
00800		MOVNS	STATUS(PB)		;SET TO READY
00900	SPSRN1:	SETZM	REASON(PB)		;OTHER ACS NOT SAVED
01000	SPSRN2:	POP	P,PCW(PB)		;DITTO -- BUT LEAVE REASON INTACT
01100						;THESE TWO LABELS ARE USED
01200						;BY SUSPEND, JOIN & THE LIKE
01300		MOVEM	P,ACP(PB)
01400		MOVEM	SP,ACSP(PB)
01500		MOVEM	RF,ACF(PB)		
01600	FOTR:	HRRZ	B,GOGTAB
01700		TLO	B,-NPRIS
01800		MOVEI	A,1			;READY
01900	SCHLIS:	SKIPN	PB,PRILIS(B)		;SEARCH DOWN THIS LIST
02000		JRST	NXLIS			;LIST IS EMPTY
02100	TRYTHS:	CAMN	A,STATUS(PB)		;IS THIS READY
02200		JRST	SCDTHS			;YES -- DO HIM
02300		HRRZ	PB,PLISTE(PB)		;LINK DOWN LIST
02400		JUMPN	PB,TRYTHS		;IF ANY LEFT AT THIS LEVEL,TRY
02500	NXLIS:	AOBJN	B,SCHLIS		;SEARCH LIST
02600		
02700	IFE APRISW <
02800	;;#NA#  RACE CONDITION ON WHEN INTERRUPT HAPPENS
02900		IMSKCL	1,[-1]			;MASK OFF ALL INTERRUPTS
03000		SKIPE	INTRPT			; A RECENT INTERRUPT
03100		JRST	[INGOSC: SETZM INTRPT	;GO TRY AGAIN TO SCCHEDULE
03200				IMSKST 1,[-1]
03300				JRST	FOTR ]
03400		INTENS	B,			;GET INTERRUPT ENABLING
03500		TLNN	B,775204		;IS HE ENABLED FOR SOMETHING
03600						;THAT CAN STILL HAPPEN
03700		ERR <NO ONE TO RUN>,1,INGOSC	;NO
03800		IMSTW	[-1			;WAIT FOR AN INTERRUPT
03900			1]
04000		SETZM	INTRPT			;ZERO THE FLAG
04100	;;#NA# -- EVENTUALLY FIX THIS CROCK
04200	>;IFE APRISW
04300	IFN APRISW <
04400		SKIPN	INTRPT
04500		ERR <NO ONE TO RUN>,1
04600		SETZM	INTRPT
04700	>;IFN APRISW
04800		JRST	FOTR			;FIND SOMEONE TO RUN
04900	
05000	SCDTHS:	
05100	;CIRCLE THE QUEUE
05200		SKIPN	A,PLISTE(PB)		;ONLY ONE ON THE LIST?
05300		JRST	RDYTHS			;YES
05400		TRNN	A,-1			;ALREADY AT END?
05500		JRST	RDYTHS			;YES
05600		HLLM	A,PLISTE(A)		;PREV(NEXT(ME))←PREV(ME)
05700		MOVS	C,A			;NEXT(ME),,PREV(ME)
05800		TRNE	C,-1			;ANY PREV?
05900		HLRM	C,PLISTE(C)		;YES -- NEXT(PREV(ME))←NEXT(ME)
06000		TLNE	A,-1			;WAS I FIRST?
06100		HRR	A,PRILIS(B)		;NO -- FIRST WILL STAY FIRST
06200		HRL	A,PB			;NEW OWNER -- ME,,NEW FIRST
06300		EXCH	A,PRILIS(B)		;GET OLD LAST,,FIRST
06400		HLLZM	A,PLISTE(PB)		;MY NEW ENTRY IS OLD LAST,,0
06500		MOVS	A,A			;    XXX,,OLD LAST
06600		HRRM	PB,PLISTE(A)		;POINT AT ME
06700	
06800	
06900	RDYTHS:	SETOM 	STATUS(PB)		;RUNNING
07000		HRRM 	PB,RUNNER		;SAY SO
07100		MOVE	USER,GOGTAB
07200		MOVE	A,QUANTM(PB)
07300		MOVEM	A,TIMER(USER)
07400		SKIPE	A,REASON(PB)
07500		JRST	@SPCASE(A)		;SOME SPECIAL CASE
07600	RPSPF:	MOVE	P,ACP(PB)		;GET THE NEEDED REGISTERS
07700		MOVE	SP,ACSP(PB)
07800		MOVE	RF,ACF(PB)
07900		JRST	@PCW(PB)		;GO START RUNNING THE SO AND SO
08000	
08100	
08200	SPCASE:	RPSPF				;0 THEN RESTORE P, SP, F
08300		RSTACS				;1 THEN RESTORE ALL ACS
08400		RPSPF				;2 THEN FROM JOINER
08500		RST1				;3 THEN FROM INTERROGATE
08600	
08700	RSTACS:	MOVE	P,ACP(PB)		;PUT THE RETURN ADDRESS ON THE STACK
08800		PUSH	P,PCW(PB)
08900		MOVEM	P,ACP(PB)
09000		HRLZI	P,AC0(PB)
09100		BLT	P,P			;RESTORE THE OLD ACS
09200		POPJ	P,			;GO RUN
09300	
09400	
09500	RST1:	MOVE	A,AC1(PB)		;RESTORE REG 1 , SP,P,F
09600		JRST	RPSPF
09700	
     

00100	HERE(RESUME)
00200		MOVE	USER,RUNNER	;TAKE CARE OF RET ADDRS
00300		POP	P,PCW(USER)
00400		POP	P,OPTS		;OPTIONS
00500		POP	P,A		;RETURN VALUE
00600		POP	P,C		;WHO
00700		MOVE	TEMP,GOGTAB	;
00800		LDB	B,INFOTAB(TEMP)	;TEST THE TYPE
00900		CAIE	B,PRCTYP	;IS THE TYPE A PROCESS
01000		ERR	<ATTEMPT TO RESUME SOMETHING NOT A PROCESS>
01100		MOVE	PB,@DATAB(TEMP)	;GET THE DATUM
01200		TLNE	PB,TERM		;WAS IT TERMINATED?
01300		ERR	<ATTEMPT TO RESUME A TERMINATED PROCESS>
01400		MOVE	B,PRCITM(USER)	;MY NAME
01500		MOVEM	B,RSMR(PB)	;REMEMBER CALLER
01600		SKIPE	STATUS(PB)	;HIS STATUS BETTER BE 0
01700		ERR	<ATTEMPT TO RESUME NON-SUSPENDED PROCESS>,1,<@PCW(USER)>
01800		JUMPN	OPTS,NS.RSM	;NONSTANDARD IF JUMP
01900		SETZM	STATUS(USER)
02000	RSM.H:	SETOM	STATUS(PB)
02100		MOVEM	P,ACP(USER)	;SAVE NEEDFUL REGISTERS
02200		MOVEM	RF,ACF(USER)
02300		MOVEM	SP,ACSP(USER)
02400		SETZM	REASON(USER)	;ONTL P, SP, F IMPORTANT
02500		MOVEM	PB,RUNNER	;
02600		MOVE	C,REASON(PB)	;
02700		JRST	@SPCASE(C)	;GO FIRE HIM UP
02800	
02900	
03000	NS.RSM:	TRNN	OPTS,MSTMSK	;FUNNYNESS IN MY NEW STATUS?
03100		JRST	RSM.4		;NO -- IT MUST BE NOTNOW
03200		LDB	D,MSTBYT	;GET INDEX
03300		JRST	@[ RSM.1	;I GO READY
03400			  RSM.3		;I DIE
03500			  RSM.4		;I WANT TO KEEP RUNNING
03600			]-1(D)		;SELECT
03700	
03800	RSM.1:	TRNN	OPTS,NOTNOW	;HE RUNS?
03900		JRST	RSM.2		;YES
04000		AOS	STATUS(PB)	;MAKE HIM READY
04100		MOVE	B,REASON(PB)	;WERE ALL REGISTERS SAVED
04200		CAIN	B,1		;
04300		JRST	RSM.01		;YES
04400		MOVEM	A,AC1(PB)	;
04500		MOVEI	A,3
04600		MOVEM	A,REASON(PB)	;A IS IMPORTANT
04700	RSM.01:	PUSH	P,PCW(USER)	;RET AD
04800		JRST	URSCHD		;RESCHEDULE
04900	
05000	
05100	
05200	RSM.2:	MOVNS	STATUS(USER)	;
05300		JRST	RSM.H		;GO GET HIM GOING
05400	
05500	
05600	
05700	RSM.3:	MOVE	B,REASON(PB)	;
05800		CAIN	B,1		;ALL ACS SAVED?
05900		JRST	RSM.3X		;YES
06000		MOVEM	A,AC1(PB)	;SAVE A
06100		MOVEI	A,3		;
06200		MOVEM	A,REASON(PB)	;
06300	RSM.3X:	TRNE	OPTS,NOTNOW	;HE RUNS?
06400		JRST	RSM.03		;YES
06500		AOS	STATUS(PB)	;NO - I CAN COMMIT SUICIDE
06600		MOVE	PB,USER		;
06700		JRST	TERMPB		; I DIE
06800	RSM.03:	MOVE	B,ACP(PB)	;
06900		MOVEI	C,RSM.T		;
07000		EXCH	C,PCW(PB)	;FIRST HE WILL KILL ME
07100		PUSH 	B,C		;
07200		PUSH	B,PB		;
07300		MOVEM	B,ACP(PB)	;THE TERMPB POPJ WILL CONTINUE HIM
07400		JRST	RSM.H		;GO FIRE THE DEAR BOY UP
07500	
07600	RSM.4:	AOS	STATUS(PB)	;GET HIM READY
07700		MOVE	B,REASON(PB)	;SHOULD WE SAVE 1
07800		CAIE	B,1		;
07900		JRST	@PCW(USER)	;I GO ON MY WAY
08000		MOVEM	A,AC1(PB)	;SAVE IT
08100		MOVEI	A,3		;
08200		MOVEM	A,REASON(PB)	;
08300	;;#LB#! 1-15-73 DCS WAS @PCW(PB), THAT'S WRONG ("TYPO")
08400		JRST	@PCW(USER)	;
08500	
08600	RSM.T:	MOVE	PB,(P)		;
08700		PUSHJ	P,TERMPB	;
08800		MOVE	PB,1(P)		;TERMPB BACKED UP THE STACK
08900		POP	P,PCW(PB)	;RET AD
09000		MOVE	C,REASON(PB)	;
09100		JRST	@SPCASE(C)	;GO DO RIGHT THING ABOUT ACS
09200	
     

00100	COMMENT ⊗SUSPEND and TERMINATE runtime routines⊗
00200	HERE(SUSPEND)
00300		MOVE	C,-1(P)		;THE ITEM
00400		POP	P,-1(P)		;BACK UP RETN ADDR
00500		MOVE	TABL,GOGTAB	;
00600		LDB	B,INFOTAB(TABL)
00700		CAIE	B,PRCTYP	;BE SURE A PROCESS ITEM
00800		ERR	<ATTEMPT TO SUSPEND A NON PROCESS ITEM>
00900		MOVE	PB,@DATAB(TABL)
01000	        TLNE	PB,TERM		;IF TERMINATED , 
01100		ERR	<SUSPENDING A TERMINATED ITEM>
01200		CAME	PB,RUNNER	;IS IT THE RUNNER
01300		JRST	OTHGUY		;NO
01400		SETZM	STATUS(PB)
01500		JRST	SPSRN1		;GO RESCHEDULE
01600	OTHGUY:	MOVEI	A,SPNDR		;HE MUST HAVE BEEN READY
01700		SKIPE	STATUS(PB)	;IF HE WASNT SUSPENDED
01800		MOVEM	A,REASON(PB)	;THE REGISTERS MUST BE RESTORED
01900		SETZM	STATUS(PB)	;BE SURE
02000	TENX <
02400	IFNAVL ITMANY, <
02500	ITMANY←←-1
02600	>
02700	>;TENX
02800		MOVEI	A,ITMANY	;GET THE ITEM ANY
02900		POPJ	P,
03000	
03100	HERE(TERMINATE)
03200		MOVE	C,-1(P)
03300		MOVE	TABL,GOGTAB	;
03400		LDB	B,INFOTAB(TABL)	;IS HE A PROCESS
03500		CAIE	B,PRCTYP
03600		ERR	<TERMINATING A NON-PROCESS>
03700		MOVE	PB,@DATAB(TABL)	;POINT AT PROCESS
03800		TLNE	PB,TERM		;ALREADY DEAD
03900		JRST	RET1		;YES
04000	↑TERMPB:
04100		MOVE	USER,RUNNER	;COME HERE IF PB LOADED
04200		CAMN	PB,USER		;IS IT ME THAT IS TO DIE?
04300		JRST	KILLIT		;YES
04400		PUSH	P,PRIOR(USER)	;I AM ABOUT TO GET HIGH PRIORITY
04500		PUSHJ	P,REMPRI
04600		MOVEI	A,MAXPRI	;
04700		PUSHJ	P,SETPRI
04800		MOVEI	A,FIXPRI
04900		MOVEM	A,PCW(USER)
05000		MOVEM	P,ACP(USER)
05100		MOVEM	RF,ACF(USER)
05200		MOVEM	SP,ACSP(USER)
05300		MOVE	RF,ACF(PB)
05400		MOVE	P,ACP(PB)
05500		MOVE	SP,ACSP(PB)
05600		MOVEI	A,1		;NOW FIX STATUS
05700		MOVEM	A,STATUS(USER)	;
05800		MOVNM	A,STATUS(PB)
05900		MOVEM	PB,RUNNER	;THE NEW RUNNER
06000	KILLIT:	MOVEI	LPSA,SPRPDA	;THE SPROUTER IS WHERE WE GO BACK TO
06100		PUSHJ	P,STKUWD	;UNWIND THE STACK
06200		JRST	CALRET		;GO DIE 
06300	
06400	;IF LIVED THROUGH THE DESTRUCTION, WILL COME HERE
06500	FIXPRI:	PUSHJ	P,REMPRI
06600		POP	P,A		;REAL PRIORITY
06700		PUSHJ	P,SETPRI
06800	RET1:	SUB	P,[XWD 2,2]	;GET OFF THE PARAMETER
06900		JRST	@2(P)		;RETURN
07000	
     

00100	COMMENT ⊗The JOIN runtime routine⊗
00200	
00300	DSCR JOIN
00400	CAL  PUSH P,SET
00500	     PUSHJ P,JOIN
00600	DES  CAUSES YOUR PROCESS TO WAIT FOR THE TERMINATION OF ANY
00700	PROCESSES NAMED IN ITS ARGUMENT SET
00800	⊗
00900	
01000	HERE(JOIN)
01100		MOVE	PB,RUNNER
01200		MOVE	B,-1(P)		;THE SET 
01300		POP	P,-1(P)		;FOR LATER
01400		JUMPE	B,CPOPJ		;
01500		MOVE	TABL,GOGTAB	;GET READY FOR CELL GETTING
01600		HRRZ	A,(B)		;A NOW POINTS AT FIRST
01700		HRLZ	D,PRCITM(PB)	;THE PROCESS ITEM OF THE JOIN
01800	
01900	;NOW LOOP ALONG SET, GIVING WARNINGS
02000	
02100	JNST:	HLRZ	C,(A)		;THE ITEM NUMBER
02200		LDB	B,INFOTAB(TABL)	;GET TYPE
02300		CAIE	B,PRCTYP	;PROCESS?
02400		ERR	<ATTEMPT TO DO JOIN ON NON-PROCESS>
02500		MOVE	B,@DATAB(TABL)	;GET DATUM
02600		TLNE	B,TERM		;DEAD ???
02700		JRST	NXTJNR		;YES
02800		AOS	JOINCT(PB)	;ONE MORE TO DIE
02900		NNCELL	(C)		;GET (POSSIBLY FIRST) NEW CELL
03000		HRR	D,JOINS(B)	;LINK TO OLD JOIN LIST
03100		MOVEM	D,(C)		;NEW CONTENTS OF THIS CELL
03200		HRRZM	C,JOINS(B)	;NEW JOIN LIST
03300	NXTJNR:	HRRZ	A,(A)		;GET NEXT ENTRY
03400		JUMPN	A,JNST
03500		SKIPG	JOINCT(PB)	;DO WE NEED TO WAIT?
03600		POPJ	P,		;NO
03700		MOVEI	A,JOINR		;REASON IS A JOIN
03800		MOVEM	A,REASON(PB)	;
03900		SETZM	STATUS(PB)	;I AM SUSPENDED
04000		JRST	SPSRN2		;GO SAVE P,RF,SP & RUN SOMEONE
04100					;(BUT DONT CHANGE REASON)
04200	
04300	
04400	
04500	
04600	
04700	
04800	
     

00100	COMMENT ⊗THE MAIN PROCESS INITIALIZER⊗
00200	
00300	HERE(MAINPR)
00400		MOVE	USER,GOGTAB
00500		SKIPE	GGDAD(USER)	;INITIALIZED ALREADY
00600		POPJ	P,		;YES
00700		MOVEI	C,NPVARS+40	;HOW MUCH SPACE WE NEED
00800		PUSHJ	P,CORGET
00900		ERR	<NO ROOM FOR THE MAIN PROCESS>
01000		HRRZ	PB,B		;PROCESS BASE
01100		MOVE	A,SPDL(USER)	;STRING PDL
01200		MOVEM	A,ISP(PB)
01300		SETOM	DYNL(PB)
01400		HLROI	A,SPRPDA
01500		MOVEM	A,STATL(PB)
01600		MOVEM	PB,GGDAD(USER)
01700		MOVEM	PB,RUNNER	;SAY THIS IS THE RUNNER
01800		HRLZI	A,ZFIRST(PB)
01900		HRRI	A,ZFIRST+1(PB)
02000		SETZM	ZFIRST(PB)
02100		BLT	A,ZLAST(PB)
02200	
02300		MOVEI	C,MAINPI	;THE MAIN PROCESS ITEM NUMBER
02400		MOVEI	A,PRCTYP	;MAKE A PROCESS
02500		DPB	A,INFOTAB(USER)
02600		HRRZM	PB,@DATAB(USER)
02700		MOVEM	C,PRCITM(PB)
02800	
02900		SETZM	KLOWNR(PB)	;NASTY
03000		SETOM	STATUS(PB)	;I AM THE RUNNER
03100		MOVEI	A,STPSZ		;SET DEFAULTS
03200		MOVEM	A,DEFPSS	;P STACK
03300		MOVEI	A,STSPST	;
03400		MOVEM	A,DEFSSS	;SP STACK
03500		MOVEI	A,STDQNT	;
03600		MOVEM	A,DEFQNT	;QUANTUM
03700		MOVEM	A,QUANTM(PB)	;
03800		MOVEI	A,STDPRI	;STANDARD PRIORITY
03900		MOVEM	A,DEFPRI	;PRIORITY
04000		PUSHJ	P,SETPRI	;SET THE PRIORITY
04100		PUSH	P,[%SPGC]
04200		PUSHJ	P,SGREM
04300		PUSH	P,[%ARRSRT]
04400		PUSHJ	P,SGREM
04500		PUSH	P,[%PSSGC]
04600		PUSH	P,[SGLKBK+1]
04700		PUSHJ	P,SGINS
04800	
04900		POPJ	P,
05000	
05100	
     

00100	COMMENT ⊗CALLER , MYPROC, AND PSTATUS ⊗
00200	
00300	HERE(CALLER)
00400		JSP	TEMP,PDG
00500		ERR	<NOT A PROCESS ITEM>
00600		TLNE	A,TERM
00700		ERR	<PROCESS IS TERMINATED>
00800		MOVE	A,RSMR(A)
00900	C.XIT1:	EXCH	C,-1(P)
01000	C.XIT:	SUB	P,X22
01100		JRST	@2(P)
01200	
01300	HERE(MYPROC)
01400		MOVE	USER,RUNNER
01500		MOVE	A,PRCITM(USER)
01600		POPJ	P,
01700	
01800	HERE(PSTATUS)
01900		JSP	TEMP,PDG
02000		ERR	<NOT A PROCESS ITEM>
02100		TLNN	A,TERM
02200		SKIPA	A,STATUS(A)
02300		MOVEI	A,2
02400		JRST	C.XIT1
02500	
02600	
02700	;PDG -- GETS PROC ITEM IN -1(P) INTO C , CHECKS TYPE, & PUTS DATUM INTO A
02800	;CALLED BY JSP TEMP,PDG
02900	;SIDE EFFECTS: USES USER, PUTS OLD VALUE OF C INTO -1(P), SKIP RETURNS IF
03000	;THE ITEM WAS OK. OTHERWISE RETURNS WITH A= WHATEVER TYPE ITEM IN C IS
03100	
03200	PDG:	EXCH	C,-1(P)		;ITEM NUMBER
03300		MOVE	USER,GOGTAB
03400		LDB	A,INFOTAB(USER)
03500		CAIE	A,PRCTYP
03600		JRST	(TEMP)		;WAS NOT A PROC ITEM
03700		MOVE	A,@DATAB(USER)
03800		JRST	1(TEMP)		;RETURN
03900	
     

00100	COMMENT ⊗ PRISET -- ROUTINE USER CALLS TO CHANGE PRIORITY ⊗
00200	
00300	HERE(PRISET)
00400		MOVE	C,-2(P)		;ITEM
00500		MOVE	TABL,GOGTAB	;
00600		LDB	A,INFOTAB(TABL)
00700		CAIE	A,PRCTYP
00800		ERR	<ATTEMPT TO SET PRIORITY OF NON PROCESS ITEM>
00900		MOVE	PB,@DATAB(TABL)	;GET DATUM
01000		TLNE	PB,TERM
01100		ERR	<ATTEMPT TO SET PRIORITY OF TERMINATED PROCESS>
01200		PUSHJ	P,REMPRI	;TAKE OFF MY LIST
01300		MOVE	A,-1(P)
01400		CAIG	A,17		;CHECK BOUNDS
01500		CAIGE	A,0
01600		ERR	<ERR ATTEMPT TO GIVE A PROCESS AN ILLEGAL PRIORITY>
01700		PUSHJ	P,SETPRI
01800		SUB	P,X33
01900		JRST	@3(P)
02000	
     

00100	COMMENT ⊗SPECIAL GC ROUTINE FOR PROCESSES⊗
00200	
00300	
00400	HERE(%PSSGC)
00500		MOVE	TEMP,RUNNER
00600		MOVEM	SP,ACSP(TEMP)
00700	;; dont get it from here (assume was ok)
00800	;	MOVE	RF,RACS+RF(USER)
00900		MOVEM	RF,ACF(TEMP)
01000		HRLZI	B,-NPRIS
01100		HRR	B,GOGTAB
01200	SCHL1:	SKIPN	TEMP,PRILIS(B)
01300		JRST	NXLS
01400		PUSH	P,B
01500	SCHL2:	MOVE	RF,ACF(TEMP)
01600		PUSH	P,TEMP
01700		PUSHJ	P,%ARSR1
01800		MOVE	TEMP,(P)
01900		HRRZ	A,ISP(TEMP)
02000		MOVE	SP,ACSP(TEMP)
02100		PUSHJ	P,%SPGC1
02200		POP	P,TEMP
02300		HRRZ	TEMP,PLISTE(TEMP)
02400		JUMPN	TEMP,SCHL2
02500		POP	P,B
02600	NXLS:	AOBJN	B,SCHL1
02700		MOVE	TEMP,RUNNER
02800	;; now get rf for this process back (also sp)
02900		MOVE	RF,ACF(TEMP)
03000		MOVE	SP,ACSP(TEMP)
03100		POPJ	P,
03200	
03300	
03400	
03500	
03600	
03700	
     

00100	COMMENT ⊗INTERRUPT ROUTINES⊗
00200	
00300	
00400	HERE(DDFINT)			;DO DEFERRED INTERRUPT
00500		SKIPE	NOPOLL		;IGNORING IT?
00600		POPJ	P,		;YES
00700		SETZM	INTRPT		;
00800		MOVE	USER,RUNNER	;NEED TO SAVE ACS
00900		POP	P,PCW(USER)	;SAVE PC WORD
01000		MOVNS	STATUS(USER)	;READY
01100		MOVEI	TEMP,AC0(USER)	;
01200		BLT	TEMP,ACP(USER)	;
01300		MOVEI	A,1		;NEED ALL ACS
01400		MOVEM	A,REASON(USER)	;
01500		JRST	FOTR		;SEE WHOM TO RUN
01600	
01700	HERE(INTSET)
01800	
01900	;CALL IS  INTSET(ITEM,SPROUT OPTS)
02000	;ORS IN THE STATUS OPTIONS FOR SPNDNP+RUNME
02100	;TURNS OFF THE OPTION FOR SPNDME
02200		MOVE	USER,GOGTAB	;
02300		SKIPE	DISPAT(USER)	;HAVE TABLES???
02400		JRST	.+3		;YES
02500		PUSH	P,[=128]	;DEFAULT BUFFER SIZE
02600		PUSHJ	P,INTTBL	;GO GET EM
02700		PUSH	P,-2(P)		;ITEM
02800		PUSH	P,[INTPDA]	;INTERRUPT PROCEDURE
02900		MOVE	A,-2(P)		;GET OPTIONS
03000		TRZ	A,SPNDME	;SET UP STATUS FIELD
03100		TRO	A,SPNDNP+RUNME	;
03200		PUSH	P,A		;
03300		PUSH	P,[0]		;NO KILL SET
03400		PUSHJ	P,SPROUT	;SPROUT IT
03500	
03600		MOVE	C,-2(P)		;THE ITEM
03700		MOVE	A,@DATM
03800		MOVE	USER,GOGTAB
03900		MOVEM	A,INTPRC(USER)	;REMEMBER INTERRUPT PROCESS BASE
04000		MOVE	A,-1(P)		;
04100		TRNE	A,PRIMSK	;DID HE SPEC A PRIORITY
04200		JRST	POK
04300	
04400		PUSH	P,C		;ITEM
04500		PUSH	P,[0]
04600		PUSHJ	P,PRISET	;SET THE PRIORITY
04700	POK:
04800		SUB	P,X33
04900		JRST	@3(P)
05000	
05100	
05200	
05300	
05400	HERE(CLKMOD)
05500	NOTENX<
05600		MOVE	USER,GOGTAB	;
05700		SOSG	TIMER(USER)	;IF COUNTDOWN COMPLETE THEN
05800		SETOM	INTRPT		;SIGNAL THE INTERRUPT
05900		POPJ	P,		;LET CALLER DISMIS
06000	>;NOTENX
06100	TENX<
06200		ERR <CLKMOD not implemented.>
06300	>;TENX
06400	
06500	DEFINE QW(VALAC,WPAC,RPTR,WTOP,WBOT,OVINST) <
06600		MOVEM	VALAC,(WPAC)
06700		ADDI	WPAC,1
06800		CAMLE	WPAC,WTOP
06900		MOVE	WPAC,WBOT
07000		CAMN	WPAC,RPTR
07100		OVINST
07200		>
07300	
07400	DEFINE QR(VALAC,WPTR,RPAC,WTOP,WBOT,OVINST) <
07500		CAMN	RPAC,WPTR
07600		OVINST
07700		MOVE	VALAC,(RPAC)
07800		ADDI	RPAC,1
07900		CAMLE	RPAC,WTOP
08000		MOVE	RPAC,WBOT
08100		>
08200	
08300	DEFINE IQW(VAC) <
08400		QW(VAC,11,<INTQRP(USER)>,<INTQWT(USER)>,<INTQWB(USER)>,< JRST IQWOV >)
08500		>
08600	
08700	HERE(DFR1IN)
08800		MOVE	USER,GOGTAB	;SO CAN CALL ANY TIME
08900		MOVE	11,INTQWP(USER)
09000	NOTENX <
09100		IQW	1
09200		IQW	6
09300		MOVE	TEMP,XJBCNI
09400		IQW	TEMP
09500		MOVE	TEMP,XJBTPC
09600		IQW	TEMP
09700	>;NOTENX
09800	TENX <
09900		IQW	14		;LPC WORD FOR THIS INTERRUPT.
10000	>;TENX
10100		MOVE	TEMP,RUNNER
10200		IQW	TEMP
10300		MOVE	1,-1(P)
10400	VILOOP:	MOVE	TEMP,(1)
10500		IQW	TEMP
10600		AOBJN	1,VILOOP
10700		MOVEM	11,INTQWP(USER)
10800		SETOM	INTRPT
10900		SKIPN	7,INTPRC(USER)	;INTERRUPT PROCESS
11000		JRST	DF.X
11100		MOVEI	TEMP,1		;READY
11200		SKIPL	STATUS(7)
11300		MOVEM	TEMP,STATUS(7)
11400	DF.X:	SUB	P,X22
11500		JRST	@2(P)
11600	
11700	IQWOV:	ERR	<DRYROT IN INTMOD -- WRITER>
11800		JRST	DF.X
11900	
12000	HERE(DFRINT)
12100	NOTENX <
12200		PUSH	P,@DFRINF(USER)
12300	>;NOTENX
12400	TENX <
12500		PUSH	P,13		;PUSH AOBJN PTR, 3RD ARG TO INTMAP
12600	>;TENX
12700		PUSHJ	P,DFR1IN
12800		POPJ	P,
12900	
13000	
13100	
     

00100	COMMENT ⊗THE INTERRUPT PROCESS⊗
00200	
00300	
00400	DEFINE IQR(AC) <
00500		QR	(AC,<INTQWP(USER)>,D,<INTQWT(USER)>,<INTQWB(USER)>,<JRST QRERR>)
00600		>
00700	
00800	HERE(INTPRO)
00900		PUSH	P,RF
01000		PUSH	P,INPDA0
01100		PUSH	P,SP
01200		MOVE	USER,GOGTAB
01300	DO1INT:	MOVE	D,INTQRP(USER)	;READER OF THE QUEUE
01400		QR	(1,<INTQWP(USER)>,D,<INTQWT(USER)>,<INTQWB(USER)>,< JRST ALDCIS >);
01500	;ABOVE GETS LPC WORD ON TENEX, FOR IJBTPC
01600	NOTENX <
01700		IQR	6
01800		IQR	TEMP
01900		MOVEM	TEMP,IJBCNI(USER)
02000		IQR	TEMP
02100		MOVEM	TEMP,IJBTPC(USER)
02200	>;NOTENX
02300	TENX <
02400		MOVEM	1,IJBTPC(USER)
02500	>;TENX
02600		IQR	TEMP
02700		MOVEM	TEMP,IRUNNR(USER)
02800		IQR	B
02900	TENX <
03000		SUBI	B,1		;GROSS CROCK - FIND OUT WHY WORKS SOMEDAY
03100					;ACTUALLY FIND OUT WHY STANFORD WORKS WITHOUT
03200					;THE CROCK. SEEMS TO BE DISAGREEMENT BETWEEN
03300					;QUEUE WRITER AND READER AS TO WHETHER THE COUNT
03400					;WORD INCLUDES SELF OR NOT.
03500	>;TENX
03600		JUMPE	B,DISDFI
03700	DO1I.1:	
03800		IQR	C
03900		MOVEM	D,INTQRP(USER)
04000		SOJLE	B,DO1I.2
04100		PUSH	P,C
04200		JRST	DO1I.1
04300	DO1I.2:	HLRZ	D,C		
04400		CAIN	D,-1		;IS THIS A PDA
04500		JRST	DO1I.4		;NO -- JUST ISSUE THE CALL
04600		TLNN	C,-1		;WAS THERE A CONTEXT??
04700		JRST	DO1I.3		;NO
04800		MOVS	D,C		;PDA,,STATIC LINK
04900		HRRZ	TEMP,PD.PPD(C)	;PARENTS PDA
05000		PUSH	P,[ DO1INT]
05100		PUSH	P,RF
05200		HLRZ	LPSA,1(D)	;THE PDA IIN THE STACK
05300		CAIE	LPSA,TEMP	;BETTER BE THE SAME
05400		ERR	<ATTEMPT TO REFERENCE A NON-EX ENVIRONMENT IN INTPRO >
05500		PUSH	P,D		;STATIC LINK
05600		PUSH	P,SP		;SAVE SP
05700		HLRZ	C,PD.PPD	;END OF MKSEMT
05800		JRST	(C)
05900	DO1I.3:	HRRZ	C,PD.(C)	;ENTRY ADDRESS
06000	DO1I.4:	PUSHJ	P,(C)		;CALL THE PROCEDURE
06100		JRST	DO1INT
06200	
06300	ALDCIS:	MOVE	PB,RUNNER	;ALL DONE CURRENT INTERRUPTS
06400		SETZM	STATUS(PB)	;SUSPEND SELF
06500		PUSHJ	P,SPSRN1
06600		JRST	DO1INT
06700	
06800	QRERR: ERR	<DRYROT IN INTPRO -- READER>
06900		JRST 	ALDCIS
07000	
07100	
07200	DISDFI:	ERR	<STRANGENESS IN DEFERRED INTERRUPT>,1
07300		JRST	DO1INT
07400	
07500	DEFINE IPDE(X,V), < PUTINLOC(INTPDA+X,V) >
07600	
07700	INTPDA: BLOCK PD.XXX+1
07800	
07900		IPDE	(PD.,INTPRO)
08000		IPDE	(PD.DSW,3)
08100		IPDE	(PD.PDA,<<INPDA0: XWD INTPDA,0>>)
08200		IPDE	(PD.LLW,<INTPDA+PD.XXX>)
08300		IPDE	(PD.DLW,<INTPDA+PD.XXX>)
08400	
08500	
     

00100	
00200	
00300	;DFCPKT(5 WD BLOCK ADDR,EVTYP,EVNOT,OPTS)
00400	; CREATES A FIVE WORD BLOCK FOR A DEFERED CAUSE & RETURNS AN AOBJN 
00500	; POINTER TO THE BLOCK
00600	; IF THE SUPPLIED BASE ADDRESS IS ≠0 THEN USES THAT ADDRESS
00700	; OTHERWISE DOES A CORGET TO GET THE FIVE WORDS
00800	
00900	HERE(DFCPKT)
01000		SKIPE	B,-4(P)		;DID USER GIVE ME A BLOCK
01100		JRST	DFC.1		;YES
01200		MOVEI	C,5
01300		PUSHJ	P,CORGET
01400		ERR	<NO CORE LEFT>
01500	DFC.1:	HRLI	B,-5
01600		MOVE	A,B		;AOBJN PTR
01700		SUB	B,X11		;READY FOR PUSHES
01800		PUSH	B,[4]
01900		PUSH	B,-3(P)
02000		PUSH	B,-2(P)
02100		PUSH	B,-1(P)
02200		PUSH	B,[XWD -1,CAUSE]
02300		SUB	P,[XWD 5,5]
02400		JRST	@5(P)		;RETURN
02500	
     

00100	COMMENT ⊗ CAUSE ⊗
00200	
00300	HERE(CAUSE)
00400		MOVE	PB,RUNNER
00500		AOS	A,CAUSES(PB)
00600		CAIE	A,1		;FIRST CAUSE?
00700		JRST	DFRCS		;NO -DEFER IT
00800		POP	P,CAUSRA(PB)	;SAVE RETN ADDRESS
00900	CSIT:	PUSHJ	P,CAUSE1	;DO THE WORK
01000		MOVE	PB,RUNNER
01100		SOSG	A,CAUSES(PB)	;DONE ONE
01200		JRST	CSE.X		;ALL ARE DONE -- CHECK FOR SCHED REQ
01300		MOVEI	KL,CAUSEQ(PB)	;GET NEXT FROM QUEUE
01400		PUSHJ	P,REMCAR
01500		HLRZ	B,(A)		;PICK UP TYPE
01600		PUSH	P,B
01700		HRRZ	B,(A)		;NOTICE
01800		PUSH	P,B
01900		PUSH	P,1(A)		;OPTIONS
02000		MOVE	TABL,GOGTAB
02100		HRR	B,FP2(TABL)	;RELEASE 2 WD BLOCK
02200		HRRM	B,(A)
02300		HRRM	A,FP2(TABL)
02400		JRST	CSIT		;GO WORK ON THIS
02500	DFRCS:	MOVE	TABL,GOGTAB	;
02600		NNCLL2	(B)		;GET 2 WD CELL
02700		POP	P,TMP		;RETURN ADDRESS
02800		POP	P,1(B)		;OPTS
02900		POP	P,(B)		;NOTICE
03000		POP	P,A		;TYPE
03100		HRLM	A,(B)
03200		MOVEI	KL,CAUSEQ(KL)	;PUT ON CAUSE QUEUE
03300		PUSHJ	P,ITAILS	;PUT ON TAIL OF QUEUE
03400		JRST	(TMP)		;RETURN
03500	CSE.X:	MOVE	USER,GOGTAB
03600		SKIPN	SCHDRQ(USER)	;SCHEDULING REQUEST
03700		JRST	@CAUSRA(PB) 	;NO
03800		SETZM	SCHDRQ(USER)	;YES
03900		PUSH	P,CAUSRA(PB)	;YES
04000		JRST	URSCHD		;RESCHEDULE
04100	
     

00100	COMMENT ⊗CAUSE1 -- ROUTINE TO DO ACTUAL WORK ⊗
00200	
00300	HERE(CAUSE1)
00400	CSE1:	JSP	TMP,EVTCK3	;VERIFY THAT THIS IS AN EVENT ITEM
00500					;ALSO EVT ← DATUM ,B&C←ITEM #
00600		SKIPE	PDA,CAUSEP(EVT)	;DID THE USER SAY SOMETHING???
00700		JRST	USPPRC		;USER SPEC PROCEDURE
00800		MOVE	FF,-1(P)	;OPTIONS
00900		SKIPN	TMP,WAITLS(EVT)	;WAS ANYONE WAITING?
01000		JRST	SCA.2		;NO
01100		MOVE	TEMP,B		;EV TYP NO
01200		MOVE	TMP,(TMP)	;LAST,,FIRST
01300		MOVE	D,-2(P)		;NOTICE NO
01400	SCA.1:	MOVE	TMP,(TMP)	;WAIT ENTRY
01500		HLRZ	C,TMP		;PROCESS NO
01600		MOVE	TABL,GOGTAB	;SET TABL TO RIGHT THING
01700		PUSHJ	P,ANSWR1	;SPECIAL ENTRY POINT IN ANSWER
01800		TRNE	A,NOJOY		;DID WE SUCCEED??
01900		JRST	SCA.1A		;NO
02000		TRNN	A,RETAIN	;KEEP THE NOTICE??
02100		TRO	FF,DNTSAV	;YES
02200		TRNN	FF,TELLAL	;TELL THE WHOLE WORLD?
02300		JRST	SCA.2		;NO
02400	SCA.1A:	TRNE	TMP,-1		;ANY LEFT
02500		JRST	SCA.1		;YES
02600	
02700	SCA.2:	TRNE	FF,DNTSAV	;SAVE IT?
02800		JRST	SCA.3		;NO
02900		MOVE	B,-2(P)		;ITEM NO OF NOTICE
03000		MOVEI	KL,NOTCLS(EVT)	;
03100		PUSHJ	P,ITAILS	;PUT ON END OF NOTIICE LIST
03200	SCA.3:
03300		MOVE	USER,GOGTAB
03400		TRNE	FF,SCHDIT	;WANT TO RESCHEDULE
03500		SETOM	SCHDRQ(USER)	;RESCHEDULE REQUEST
03600	SCA.X:	SUB	P,X44		;RETURN
03700		JRST	@4(P)
03800	
03900	USPPRC:	MOVE	B,PD.(PDA)	;HERE IF USER SPECIFIED A PROCEDURE
04000	;;#NB# !TYPO -- WAS A TLNE
04100		TLNN	PDA,-1		;CONTEXT GIVEN
04200		JRST	(B)		;NO
04300		PUSH	P,RF		;SET UP CONTEXT
04400		HRRZ	C,PD.PPD	;PARENTS PDA
04500		MOVS	A,PDA		;
04600		HLRZ	D,1(A)
04700		CAME	D,C		;SAME?
04800		ERR 	<CONTEXT WRONG OR CLOBBERED IN INTERP CALL
04900	USER SPEC EVENT PROC >
05000		PUSH	P,A		;STATL
05100		PUSH	P,SP
05200		HLRZ	B,PD.PPD(PDA)
05300		JRST	(B)		;GO TO INSTR AFTER THE MKSEMT
05400	
     

00100	COMMENT ⊗ANSWER -- subroutine used by CAUSE⊗
00200	
00300	HERE(ANSWER)
00400	
00500	;A←ANSWER(EV!TYP,NOT,PROCESS!ITEM);
00600	;IF ATTEMPT TO ANSWER INTERROGATE IS SUCCESSFUL, A ← REQUEST CODE
00700	;OTHERWISE, NOJOY BIT IS ON IN A & REST OF WORD IS INVALID
00800	
00900		MOVE	TEMP,-3(P)	;EV TYPE
01000		POP	P,-3(P)		;RET ADRS
01100		POP	P,C		;PROCESS ITEM
01200		POP	P,D		;NOTICE
01300		MOVE	TABL,GOGTAB
01400		LDB	B,INFOTAB(TABL)
01500		CAIE	B,PRCTYP
01600		ERR	<NOT A PROCESS ITEM>
01700	
01800	;THE REST OF THIS IS CALLED INTERNALLY 
01900	;EXPECTS D= NOIICE, C=PROCESS ITEM, TEMP=EV TYPE
02000	;        ALSO TABL SET UP FOR PROCESS ITEM
02100	;MODIFIES A,B,C,TABL,PB,TEMP,USER
02200	
02300	ANSWR1:	MOVE	PB,@DATAB(TABL)	;THE PROCESS BASE
02400		TLNN	PB,TERM		;TERMINATED?
02500		SKIPE	STATUS(PB)	;OR NOT SUSPENDED??
02600		JRST	NOANS		;YES
02700		AOS	STATUS(PB)	;MAKE READY
02800		MOVEM	D,AC1(PB)
02900	ANSWR2:	PUSHJ	P,DELWRQ	;DELETE ALL WAIT REQUESTS
03000		MOVE	A,INTRGC(PB)	;THE INTERROG CONTROL WORD
03100		TRNN	A,SAYWCH	;ASKED FOR THE ASSOCIATION
03200		POPJ	P,		;NO
03300		PUSH	P,[EVTYPI]	;
03400		PUSH	P,D
03500		PUSH	P,TEMP
03600		PUSHJ	P,STACSV	;SAVE ALL ACS
03700		MOVEI	5,16		;MAKE
03800		PUSHJ	P,LEAP
03900		PUSHJ	P,STACRS	;GET ACS BACK
04000		POPJ	P,
04100	NOANS:	TRO	A,NOJOY
04200		POPJ	P,		;RETURN
     

00100	COMMENT ⊗DELWRQ -- delete all wait requests⊗
00200	
00300	;EXPECTS PB = THIS PROCESS
00400	;MANGLES A,B,C,TABL
00500	
00600	DELWRQ:	SKIPN	A,WAITES(PB)
00700		POPJ	P,
00800		PUSH	P,KL
00900		MOVE	A,(A)		;A IS LAST,,FIRST
01000	DTHSRQ:	MOVE	A,(A)		;NEXT ENTRY
01100		HLRZ	C,A		;ITEM NUMBER OF TYPE
01200		PUSH	P,A		;FOR SAFE KEEPING
01300		MOVE	TABL,GOGTAB	;
01400	GLOB <
01500	;;%BE%
01600		CAIL	C,GBRK		;GLOBAL ??
01700		MOVEI	TABL,GLUSER	;
01800	>;GLOB
01900		MOVE	A,@DATAB(TABL)
02000		MOVEI	KL,WAITLS(A)
02100		MOVE	B,PRCITM(PB)
02200		PUSHJ	P,DELTLE	;DELETE ELEMENT
02300					;SETS TABL BACK TO GOGTAB
02400					;(MAYBE)
02500		POP	P,A		
02600		TRNE	A,-1		;ANY LEFT
02700		JRST	DTHSRQ		;YES
02800		MOVE	A,WAITES(PB)
02900		MOVE	TABL,GOGTAB
03000		HLRZ	B,(A)		;ADDRESS OF LAST
03100		HRRZ	C,FP1(TABL)
03200		HRRM	C,(B)		;RELEASE THE LOT
03300		HRRM	A,FP1(TABL)
03400		SETZM	WAITES(PB)	;NONE LEFT
03500		POP	P,KL
03600		POPJ	P,
     

00100	COMMENT ⊗INTERROGATE⊗
00200	HERE(INTERROGATE)
00300		SKIPN	B,-2(P)		;SET OR ITEM
00400		ERR	<NULL INTERROGATION???>
00500		TLNN	B,-1		;SET?
00600		JRST	ASK1.0		;NO
00700		MOVEI	FF,MULTIN
00800		IORM	FF,-1(P)	;SAY MULT REQUEST
00900		MOVE	TMP,(B)		;LAST,,FIRST
01000	MPCI:	MOVE	TMP,(TMP)	;NEXT ENTRY
01100		HLRZ	B,TMP
01200		PUSH	P,TMP
01300		PUSH	P,B		;TYPE ITEM
01400		PUSH	P,-3(P)		;OPTIONS WORD
01500		PUSHJ	P,ASK1.0
01600		POP	P,TMP		;GET LIST BACK
01700		CAIE	A,NIC		;FIND ONE??
01800		JRST	ASK1.X		;YES
01900		TRNE	TMP,-1		;DONE LIST???
02000		JRST	MPCI		;NO
02100		MOVE	FF,-1(P)
02200		TRNN	FF,WAIT		;WAITING REQUESTED
02300		JRST	ASK1.X		;NO
02400		MOVE	PB,RUNNER	;SUSPEND SELF
02500		MOVE	B,-2(P)		;THE LIST
02600		MOVE	TMP,(B)		;LAST,,FIRST
02700	BWL:	MOVEI	KL,WAITES(PB)
02800		MOVE	TMP,(TMP)	;NEXT
02900		HLRZ	B,TMP		;ITEM NO
03000		MOVE	C,B
03100		MOVE	EVT,@DATM
03200		PUSHJ	P,ITAILS	;ON TAIL
03300		MOVE	B,PRCITM(PB)	;
03400		MOVEI	KL,WAITLS(EVT)
03500		PUSHJ	P,ITAILS	;ON EVENT WAIL LIST
03600		TRNE	TMP,-1
03700		JRST	BWL		;CDR DOWN LIST
03800		JRST	DOWAIT		;GO WAIT
     

00100	COMMENT ⊗ASK -- used by INTERROGATE⊗
00200	
00300	ASK1I:	MOVE	B,-2(P)
00400	ASK1.0:	JSP	TMP,EVTCKB	;GET DATUM OF EVENT TYPE
00500	;;#NB# ! WAS SKIPE A,...
00600		SKIPE	PDA,INTRGP(EVT)	;USER WAIT PROCESS??
00700		JRST	USPPRC		;YES
00800	;;# #! ASKNTC POINTS HERE
00900	ASKN:	MOVE	FF,-1(P)	;CONTROL WORD
01000		SKIPN	A,NOTCLS(EVT)	;ANY READY TO GO
01100		JRST	ASK1.4		;NO
01200		TRNE	FF,RETAIN	;RETAIN THIS ONE??
01300		JRST 	ASK1.1		;YES
01400		MOVEI	KL,NOTCLS(EVT)
01500		PUSHJ	P,REMCAR	;GET THE FIRST
01600		JRST	ASK1.2		;TEST SAYWCH
01700	ASK1.1:	MOVE	A,(A)
01800		HLRZ	A,(A)		;THI FIRST ITEM
01900	ASK1.2:	TRNN	FF,SAYWCH	;WANT ASSOCIATION
02000		JRST	ASK1.3		;NO
02100		PUSH	P,[EVTYPI]	;EVENT TYPE
02200		PUSH	P,A		;NOTICE
02300		PUSH	P,-4(P)		;WHATEVER TYPE IT IS
02400		PUSHJ	P,STACSV	;SAVE REGS
02500		MOVEI	5,16		;MAKE
02600		PUSHJ	P,LEAP
02700		PUSHJ	P,STACRS	;GET ACS BACK
02800	ASK1.3:
02900	ASK1.X:	SUB	P,X33
03000		JRST	@3(P)		;RETURN
03100	
03200	ASK1.4:	MOVEI	A,NIC
03300		TRNE	FF,WAIT		;IF NOT WAITING OR 
03400		TRNE	FF,MULTIN	;MUL REQ
03500		JRST	ASK1.X		;ALL DONE
03600		MOVE	PB,RUNNER
03700		MOVEI	KL,WAITES(PB)	;WAIT ON THIS ONE
03800		PUSHJ	P,ITAILS	;PUT ON TAIL
03900		MOVE	B,PRCITM(PB)
04000		MOVEI	KL,WAITLS(EVT)
04100		PUSHJ	P,ITAILS
04200	DOWAIT:	SETZM	STATUS(PB)
04300		MOVEM	FF,INTRGC(PB)
04400		MOVEI	A,WAITNG
04500		MOVEM	A,REASON(PB)
04600		PUSHJ	P,SPSRN2	;WAIT
04700		JRST	ASK1.X		;RETURN
04800	
04900	HERE(ASKNTC)
05000	;;#NC# ! WAS A PUSHJ
05100		JSP  	TMP,EVTCK3	;CHECK EVENT TYPE
05200		JRST	ASKN		;GO DO IT
05300	
05400	;ROUTINE TO SET UP EVENT TYPE ITEM
05500	;SETS B & C TO ITEM #
05600	;SETS EVT TO DATUM
05700	;SETS TABL TO RIGHT THING FOR ITEM
05800	;CALLED VIA JSP TMP,EVTCKX
05900	
06000	
06100	EVTCK3:	SKIPA	B,-3(P)
06200	EVTCK2:	MOVE	B,-2(P)
06300	EVTCKB:	MOVE	TABL,GOGTAB
06400		MOVE	C,B
06500	GLOB <
06600	;;%BE% allow for global items RHT 1-8-74
06700		CAIL	C,GBRK		;IS THE ITEM GLOBAL
06800		MOVEI	TABL,GLUSER	;YES, USE GLOBAL INFO STUFF
06900	>;GLOB
07000		LDB	A,INFOTAB(TABL)
07100		CAIE	A,EVTTYP
07200		ERR	<THIS ITEM IS NOT AN EVENT TYPE>,6
07300		MOVE	EVT,@DATAB(TABL)
07400	GLOB <
07500	;;%BE% real hack for now, only the item gets to be global.
07600		MOVE	TABL,GOGTAB
07700	>;GLOB
07800		JRST	(TMP)
     

00100	COMMENT ⊗MKEVTT,SETCP,& SETIP⊗
00200	HERE(SETCP)
00300		JSP	TMP,EVTCK2
00400		MOVE	A,-1(P)
00500		MOVEM	A,CAUSEP(EVT)
00600	XIT3:	SUB	P,X33
00700		JRST	@3(P)
00800	
00900	
01000	HERE(SETIP)
01100		JSP	TMP,EVTCK2
01200		MOVE	A,-1(P)
01300		MOVEM	A,INTRGP(EVT)
01400		JRST	XIT3
01500	
01600	HERE(MKEVTT)	;MAKE EVENT TYPE
01700		MOVE	C,-1(P)
01800		MOVEI	A,EVTTYP
01900		MOVE	TABL,GOGTAB
02000		DPB	A,INFOTAB(TABL)
02100		MOVEI	C,NEVARS
02200		PUSHJ	P,CORGET
02300		ERR	<NO CORE LEFT -- MKEVT>
02400		MOVE	C,-1(P)
02500		MOVE	TABL,GOGTAB
02600		MOVEM	B,@DATAB(TABL)
02700		HRLI	D,(B)
02800		HRRI	D,1(B)
02900		SETZM	(B)
03000		BLT	D,NEVARS-1(B)
03100		SUB	P,X22
03200		JRST	@2(P)
03300	
     

00100	COMMENT ⊗SPARE HERE TABLE ENTRIES⊗
00200	
00300	;THE IDEA IS THAT THIS WAY WE HAVE FLEXIBILITY 
00400	;WITHOUT GOING TO A NEW SEGMENT ALL THE TIME
00500	
00600	HERE(NWLD1)
00700	HERE(NWLD2)
00800	HERE(NWLD3)
00900	HERE(NWLD4)
01000	HERE(NWLD5)
01100		ERR <DRYROT IN NWORLD>
01200	
01300	BEND PROCSS
01400	
01500	ENDCOM(PRC)
01600	
     

00100	COMPIL(IRP,,,,,,DUMMYFORGDSCISS)
00200	NOTENX <
00300	DEFINE IENS1 < INTTBL,INTMOD,ENABLE,DISABLE,INTMAP>
00400	>;NOTENX
00500	TENX <
00600	DEFINE IENS1 < INTTBL,ENABLE,DISABLE,ATI,DTI,INTMAP,EINTA>
00700	>;TENX
00800	DEFINE IEXT1 < GOGTAB,INTRPT,X22,CORGET >
00900	
01000	IFN APRISW <
01100	DEFINE XJBCNI <JOBCNI>
01200	DEFINE XJBTPC <JOBTPC>
01300	DEFINE XJBAPR <JOBAPR>
01400	DEFINE IEXT5 <JOBCNI,JOBTPC,JOBAPR,XJBENB,APRACS>
01500	IFN ALWAYS <
01600	EXTERN JOBCNI,JOBTPC,JOBAPR	;THESE ARE ALWAYS EXTERNAL
01700	>;IFN ALWAYS
01800	>;IFN APRISW
01900	IFE APRISW <
02000	DEFINE IEXT5 <XJBCNI,XJBTPC,XJBAPR,JOBINT>
02100	IFN ALWAYS <
02200	EXTERNAL JOBINT ;THIS FELLOW IS ALWAYS EXTERNAL
02300	>;IFN ALWAYS
02400	>;IFE APRISW
02500	
02600	COMPXX(IRP,< IENS1 >,< IEXT1,IEXT5 >
02700			,<INTERRUPT STUFF>,,HIIFPOSSIB)
02800	
02900	BEGIN IRPPKG
03000	
03100	INTDBG←←0
03200	
03300	NOTENX<
03400	IFE APRISW <
03500	
03600	IFE INTDBG <
03700	OPDEF DISMIS [ CALLI 400024]
03800	>;IFE INTDBG
03900	IFN INTDBG <
04000	DEFINE DISMIS < JRST DSMMSR >
04100	DSMMSR:
04200		HRLZI	P,INACS
04300		BLT	P,P
04400		JRST	@JOBTPC
04500	INACS:	BLOCK 	20
04600	>;IFN ITDBG
04700	OPDEF INTORM [ CALLI 400026]
04800	OPDEF INTACM [ CALLI 400027]
04900	OPDEF INTENB [ CALLI 400025]
05000	>;IFE APRISW
05100	
05200	IFN APRISW <
05300	OPDEF APRENB [ CALLI 16]
05400	DEFINE DISMIS < JRST DSMSSR >
05500	DSMSSR:	HRLZI	17,APRACS
05600		BLT	17,17	;BLT BACK ALL ACS
05700		JRST	@XJBTPC
05800	>;IFN APRISW
05900	>;NOTENX
06000	
     

00100	HERE(INTTBL)
00200	;CALL IS INTTBL(BUFFER!SIZE)
00300	;SETS UP TABLES NEEDED BY THE INTERRUPT SYSTEM
00400	;ON TENEX, SEE DFEINT FOR OTHER TABLES OMITTED HERE
00500	
00600		MOVE	USER,GOGTAB	;
00700	INTTB1:
00800	NOTENX <
00900		MOVEI	C,=110
01000		ADD	C,-1(P)
01100	>;NOTENX
01200	TENX <
01300		MOVE	C,-1(P)
01400	>;TENX
01500		PUSHJ	P,CORGET
01600		ERR <NOT ENOUGH SPACE FOR INTSET>
01700	NOTENX <
01800		SKIPN	D,DISPAT(USER)	;ALREADY HABE ONE?
01900		JRST	INTTB2		;NO
02000		MOVSS	D		
02100		HRR	D,B		;D ← OLD,,NEW
02200		BLT	D,=71(B)	;COPY OLD DISPAT TABLE
02300		JRST	INTTB3
02400	INTTB2:	SETZM	(B)
02500		HRL	A,B
02600		HRRI	A,1(B)
02700		ADDI	C,-1(B)
02800		BLT	A,(C)
02900	INTTB3:	HRLI	B,10
03000		MOVEM	B,DISPAT(USER)
03100		ADDI	B,=36
03200		MOVEM	B,DFRINF(USER)
03300		ADDI	B,=36
03400	>;NOTENX
03500		HRRZM	B,INTQWB(USER)
03600		HRRZM	B,INTQWP(USER)
03700		HRRZM	B,INTQRP(USER)
03800		ADD	B,-1(P)
03900		HRRZM	B,INTQWT(USER)
04000	NOTENX <
04100		HRLI	B,-20
04200		MOVEM	B,IPDP(USER)
04300		ADD	B,[XWD -10,20]
04400		MOVEM	B,ISPDP(USER)
04500	>;NOTENX
04600		SUB	P,X22
04700		JRST 	@2(P)
04800	
04900	
05000	
05100	
05200	NOTENX <
05300	;AGAIN SEE DFEINT FOR TENEX EQUIVALENT OF FOLLOWING STUFF.
05400	IFN INTDBG,<
05500	INTAPR:	MOVEM	P,INACS+17
05600		MOVEI	P,INACS
05700		BLT	P,INACS+16
05800	>;IFN INTDBG
05900	
06000	HERE(INTMOD)
06100	IFN APRISW <
06200		MOVEM	17,APRACS+17
06300		MOVEI	17,APRACS
06400		BLT	17,APRACS+16	;SAVE THE ACS
06500	>;IFN APRISW
06600		MOVE	USER,GOGTAB
06700		MOVE	7,XJBCNI	;PICK UP THE BITS
06800	IFN APRISW <			
06900		ANDI	7,235110	;BE SURE LEGIT BITS ONLY
07000	>;IFN APRISW
07100		MOVE	P,IPDP(USER)	;A PDL FOR THIS
07200		MOVE	SP,ISPDP(USER)	;A STRING PDL
07300	DSPIT:	JFFO	7,DODISP	;DISPATCH INDEX
07400		ERR	<DRYROT: INTMOD>
07500	DODISP:
07600		SKIPN	7,@DISPAT(USER)	;GO DISPATCH
07700		DISMIS			;DISMISS
07800		PUSHJ	P,(7)		;
07900		DISMIS
08000	>;NOTENX
08100	
     

00100	COMMENT ⊗PROCEDURES TO ENABLE FOR INTERRUPTS⊗
00200	
00300	;ENABLE(INDEX) -- DOES AN INTORM, OR AIC ON TENEX
00400	;DISABLE(INDEX) -- DOES AN INTACM, OR DIC ON TENEX
00500	
00600	NOTENX <
00700	IFE APRISW <
00800	HERE(ENABLE)
00900		SKIPA	B,[ INTORM A, ]
01000	HERE(DISABLE)
01100		MOVE	B,[ INTACM A, ]
01200		MOVN	C,-1(P)
01300		HRLZI	A,400000
01400		LSH	A,(C)
01500		XCT	B
01600		SUB	P,X22
01700		JRST	@2(P)
01800	>;IFE APRISW
01900	IFN APRISW <
02000	HERE(ENABLE)
02100		SKIPA	B,[OR A,XJBENB]
02200	HERE(DISABLE)
02300		MOVE	B,[ANDCA A,XJBENB]
02400		MOVN	C,-1(P)		;
02500		HRLZI	A,400000
02600		LSH	A,(C)		;THE BIT
02700	EXPO <
02800		TRO	A,400000	;REPETITIVE ENABLE (THIS MIGHT GET YOU
02900					;IN TROUBLE WITH THE CLOCK INTERRUPT)
03000	>;EXPO
03100		XCT	B
03200		MOVEM	A,XJBENB	;REMEMBER
03300		APRENB	A,
03400		SUB	P,X22
03500		JRST	@2(P)
03600	>;IFN APRISW
03700	>;NOTENX
03800	TENX <
03900	HERE(ENABLE)
04000		SKIPA C,AIC1
04100	HERE(DISABLE)
04200		MOVE C,DIC1
04300		MOVN A,-1(P)
04400		HRLZI B,400000
04500		LSH B,(A)
04600		HRRZI A,400000	;Fork handle for 'this fork'
04700		XCT C
04800		SUB P,X22
04900		JRST @2(P)
05000	
05100	AIC1:	JSYS	AIC
05200	DIC1:	JSYS	DIC
05300	
05400	HERE(DTI)
05500		HRRZ	A,-1(P)		;CHARACTER TO DE-ACTIVATE
05600		JUMPL	A,DTIERR
05700		CAILE	A,=35
05800	DTIERR:	  ERR 	<DTI:  Terminal interrupt code not in range>
05900		JSYS	DTI
06000		SUB	P,X22
06100		JRST	@2(P)
06200	
06300	
06400	HERE(ATI)
06500		HRRZ	B,-2(P)		;1ST ARG IS "TERMINAL INTERRUPT CODE"
06600		JUMPL	B,.+2		;31-35 UNUSED, 0 IS BREAK OR ↑@
06700		 CAILE	B,=35		;OTHERS OUT OF RANGE
06800		 ERR	<ATI: Terminal Interrupt Code not in range>,1
06900		MOVE	A,-1(P)		;2nd arg is interrupt channel, 0-35
07000		JUMPL	A,BADCHN
07100		CAILE	A,=35
07200		 JRST	BADCHN
07300		CAIGE	A,=24
07400		 CAIG	A,=5
07500		SKIPA
07600	BADCHN:	 ERR	<ATI: Term. Intrpt. Chnl. not 0-5 or 24-35 dec.>,1
07700		HRL	A,B		;MAKE XWD TERMINAL CODE, CHANNEL NUMBER
07800		JSYS	ATI
07900		SUB	P,X33
08000		JRST	@3(P)
08100	
08200	ATI1:	JSYS	ATI
08300	DTI1:	JSYS	DTI
08400	
08500	;To arm a keybd interrupt on TENEX you must do the ATI in addition
08600	;to the regular stuff (INTMAP's & ENABLE's) because any channel which
08700	;can take a keybd interrupt (namely 0-5 and 24-35) can take any
08800	;interrupt character so you must declare.
08900	>;TENX
09000	
09100	;INTMAP(INDEX,ENTRY!ADDR,PARAM);
09200	NOTENX <
09300	;DISPAT[INDEX]←ENTRY!ADDR
09400	;DFRINF[INDEX]←PARAM
09500	
09600	HERE(INTMAP)
09700	
09800	IFE APRISW <
09900		MOVEI	A,XJBCNI
10000		MOVEM	A,JOBINT
10100	>;IFE APRISW
10200	
10300	IFE INTDBG,<
10400		MOVEI	A,INTMOD
10500	>;IFE INTDBG
10600	IFN INTDBG,<
10700		MOVEI	A,INTAPR
10800	>;IFN INTDBG
10900		MOVEM	A,XJBAPR
11000		MOVE	USER,GOGTAB
11100		SKIPE	DISPAT(USER)
11200		JRST	.+3
11300		PUSH	P,[=128]
11400		PUSHJ	P,INTTB1	;GET MINIMAL TABLES
11500		MOVE	10,-3(P)	;GET INDEX
11600		POP	P,-3(P)		;RET ADR
11700		POP	P,@DFRINF(USER)
11800		POP	P,@DISPAT(USER)
11900		POPJ	P,
12000	>;NOTENX
12100	TENX <
12200	HERE(INTMAP)
12300		HRRZI	A,400000
12400		JSYS	RIR
12500		JUMPE	2,[MOVE	2,[XWD	LEVTAB,CHNTAB]
12600			   JSYS SIR
12700			   JRST .+1]
12800		JSYS	EIR		;ENABLE INTERRUPT SYSTEM IN GENERAL
12900		SKIPL	A,-3(P)		;CHNL
13000		CAILE	A,=35
13100		 ERR	<INTMAP: Channel # not between 0 and 35 dec.>
13200	
13300	
13400	
13500	;The CHNL'th word of the actual TENEX channel table gets the value
13600	;	LVL,,jmpchn-slot		The LVL is the interrupt level. The
13700	;dispatch is to the parallel entry of JMPCHN, a table of 3-word slots,
13800	;one per channel, addressed by the XX var JMPCHN, each of which
13900	;looks like this if the channel is in use:
14000	;	JSA USER,EINT<N>
14100	;	Ptr to simple-procedure		;POPJ'D TO IN EINTA
14200	;	AOBJN ptr for calling block
14300	;
14400	;The EINTn is EINT1, EINT2,  or EINT3, depending on the level of
14500	;the interrupt. INTMAP always initializes an interrupt to level 3,
14600	;i.e. EINT3, but in the future a subr may be provided to change the level
14700	;after the INTMAP is done (or perhaps an argument to INTMAP).
14800	;The three EINT's all immediately jrst to EINTA, but each must have
14900	;its own return vector for reentrancy's sake.
15000	
15100		ADDI	2,(A)		;2 pts to CHNTAB slot.
15200		IMULI	A,3
15300		ADDI	A,JMPCHN	;A pts to JMPCHN slot.
15400		HRLI	A,3		;Level 3 assumed.
15500		MOVEM	A,(2)		;CHNTAB[chnl]←level3,,JMPCHN[3*chnl]
15600		POP	P,-3(P)		;Return goes over 1st arg (chnl)
15700		POP	P,2(A)		;3rd INTMAP arg, AOBJN ptr, to 3rd
15800					;word of JMPCHN slot. DFRINT uses it.
15900		POP	P,1(A)		;2nd JMPCHN wrd gets XWD unused,user's simple
16000					;procedure. Goes onto stack and is POPJ'd to.
16100		MOVE	B,[JSA	USER,EINT3]	;Level 3 assumed.
16200		MOVEM	B,(A)	;1st JMPCHN slot word.
16300		POPJ	P,
16400	
16500	
16600	
16700	
16800	
16900	
17000	;EINT1, EINT2, and EINT3 are in the XX table since they get JSA'd to.
17100	;Each immediately JRST's to EINTA so that all share the code thru the
17200	;DEBRK in EINTR. Note that the TENEX DEBRK call is the normal way to
17300	;leave interrupt level whether continuing normally or forcing continuation
17400	;at a specified place (this is different than Stanford's DEBRK call).
17500	;The following code saves all accumulators because that's what the DEC 
17600	;monitor does and any other solution would have destroyed all semblance of
17700	;compatibility between DECUS or Stanford SAIL and TENEX SAIL.
17800	;Note however that the work of saving AC's has to be done somewhere
17900	;if you are going to run SAIL code at interrupt level; and if you want to
18000	;hack a very fast interrupt in machine language you can easily do it yourself
18100	;by using RIR to find the channel table and so on.
18200	;
18300	;A few more stack words than are really necessary are covered by the
18400	;ADD P,[XWD 21,21] deliberately, in order to leave some room in case the
18500	;interrupted code was not observing stack discipline religiously, because
18600	;it is fairly common in the SAIL system to see routines end with sequences like:
18700	;	SUB	P,X44
18800	;	JRST	4(P)
18900	;
19000	;One non-obvious trick here is that the BLT's which save and restore ac's 
19100	;save and restore a clobbered value of USER, because the value of USER which
19200	;prevailed in the nterrupted code is saved by the JSA/JRA pair around the
19300	;whole mess. Finally it may be helpful to note that at the point just before
19400	;EINTR, i.e. the POPJ, the top of the stack contains:
19500	;0(P)		USERCODE	;addr. of his simple procedure, so that we
19600					;"call" it with POPJ
19700	;-1(P)		AOBJN ptr	;to the "calling block" parameters to his code
19800	;-2(P)		EINTR		;Fake return so his stuff returns to us.
19900	
20000	;We also save 40 for reentrancy since his simple procedure may
20100	;use compiler-emitted UUO's like any other code and thus clobber UUO's in
20200	;progres in the interrupted code (obviously).
20300	
20400	HERE(EINTA)
20500		ADD	P,[XWD 23,23]
20600		TLNN	P,400000	;TEST FOR PDL OVERFLOW
20700		  ERR	<EINTA:  PDL overflow>
20800		MOVEM	16,0(P)
20900		HRRZI	16,-15(P)
21000		BLT	16,-1(P)
21100		MOVE	16,0(P)
21200		PUSH	P,40
21300		PUSH	P,1(USER)	;AOBJN PTR
21400		PUSH	P,[EINTR]	;FAKE RETURN TO REGAIN CONTROL FROM USERCODE
21500		PUSH	P,(USER)	;USERCODE
21600		MOVE	USER,GOGTAB
21700		POPJ	P,		;GO OFF TO RUN HIS STUFF AT INTERRUPT LEVEL
21800	
21900	;IT RETURNS HERE BY VIRTUE OF FAKE RETURN WORD
22000	EINTR:	POP	P,40
22100		HRLZI	16,-15(P)
22200		BLT	16,15
22300		MOVE	16,0(P)
22400		SUB	P,[XWD 23,23]
22500		JRA	USER,.+1
22600		JSYS	DEBRK		;BACK TO INTERRUPTED CODE
22700	>;TENX
22800	
22900	HERE(IRPSP1)
23000	HERE(IRPSP2)
23100	HERE(IRPSP3)
23200	
23300	BEND IRPPKG
23400	
23500	ENDCOM(IRP)
23600	
     

00100	
00200	
00300	
00400