Google
 

Trailing-Edge - PDP-10 Archives - decuslib20-03 - decus/20-0081/vtmast.mac
There is 1 other file named vtmast.mac in the archive. Click here to see a list.
	TITLE	VTMAST	--	MASTER PART OF VTTAM SYSTEM
	SUBTTL	MASTER STOARGE AND CONSTANTS
	;TONY LAUCK	2 JUN 71

;VTMAST IS LOADED WITH A COBOL APPLICATION PROGRAM AND IS CALLED
;BY THE APPLICATION PROGRAM WITH ENTER MACRO STATEMENTS.

;VTMAST INTERPRETS THESE CALLS AND COMMUNICATES WITH THE SLAVE JOBS
;THAT DO THE ACTUAL TERMINAL PROCESSING. THIS COMMUNICATION IS VIA
;A SHARED HIGH-SEGMENT. THE COBOL PROGRAM MUST THEREFORE USE A NON-
;REENTRANT COPY OF LIBOL.

;VTMAST COMMUNICATES WITH THE SLAVE JOBS BASED ON VTTAM TERMINAL
;NUMBER, AS REFERENCED BY THE COBOL PROGRAM. IT IS NOT CONCERNED
;WITH MONITOR TTY NUMBERS. THE ACTUAL MAPPING BETWEEN VTTAM TERMINAL
;NUMBERS, SLAVE JOBS, AND MONITOR TTY NUMBERS IS CONTROLLED BY THE
;SLAVE JOBS.

;VTTAM IS HOWEVER CONCERNED WITH THE MONITOR JOB NUMBERS OF SLAVES
;HANDLING EACH VTTAM TERMINAL NUMBER. IT NEEDS THE JOB NUMBER TO
;AWAKEN THE CORRECT SLAVE. SHOULD THE APPLICATION PROGRAM REFER TO
;A VTTAM TERMINAL NUMBER FOR WHICH THERE IS NO RUNNING SLAVE JOB
;THE MASTER (AND HENCE COBOL PROGRAM) WILL HANG.

;ON START UP THE MASTER AND SLAVES MAY BE STARTED IN ANY ORDER. STARTING
;THE MASTER LAST WILL BE MOST EFFECIENT.

;ON SHUT DOWN, THE MASTER STORES THE CLOSING TIME IN THE SHARED
;SEGMENT. AFTER THIS IS DONE, THE SLAVES AND MASTER MAY BE STOPPED.

;SHOULD THE MASTER OR ANY SLAVE RETURN TO MONITOR LEVEL, ALL
;VTTAM JOBS MUST BE RESTARTED. THIS WILL INSURE CORRECT INITIALIZATION
;OF THE SHARED HIGH SEGMENT AS WELL AS PROPER SYNCHRONIZATION
;BETWEEN MASTER AND SLAVES. FAILURE TO DO THIS WILL RESULT IN
;ERRATIC OPERATION, INCLUDING POSSIBLE HUNG CONDITIONS, HALTS, OR
;LOST TRANSACTIONS.
;ACCUMULATORS

	A=1		;G.P. AC'S
	B=2
	C=3
	D=C+1

	T=5		;TEMPS
	T1=T+1

			;CALLING SEQUENCE AC'S
	TT=7		;VTTAM TERMINAL NUMBER
	L=10		;LINE NUMBER ON CRT SCREEN
	SS=11		;WORD ADDRESS OF USERS SCREEN BUFFER
	NW=12		;NUMBER OF FULL WORDS IN USERS SCREEN BUFFER
	NC=13		;NUMBER OF ODD CHARACTERS IN USERS BUFFER
	Q=16		;POINTER TO CALLING SEQUENCE ARGUMENTS

	W=14		;HOLDS WAKE ENABLE BITS FOR HIBER UUO
	P=17		;PUSH DOWN POINTER


;VT05 PARAMENTERS

	SCRCOL=^D72	;COLUMNS PER LINE OF VT05
	SCRLIN=^D20	;LINES PER SCREEN OF VT05
	INTERN SCRCOL,SCRLIN	;FORCE THESE TO MATCH HISEG AND SLAVE

	SCRCHR=SCRCOL*SCRLIN	;CHARACTERS PER SCREEN
	SCRWDS=<SCRCHR+5>/6	;WORDS PER SCREEN (DISPLAY-6)

	LINWDS=SCRCOL/6		;WORDS PER LINE
	IFN <SCRCOL-<6*LINWDS>>,
		<PRINTX NUMBER OF COLUMNS IS NOT A MULTIPLE OF 6>
;LOW SEGMENT STORAGE AREA

QJOBN:	BLOCK	1	;OUR JOB NUMBER SAVED HERE
QWORD:	BLOCK	1	;WORD POINTER TO OUR QBIT ENTRY
QMASK:	BLOCK	1	;BIT MASK TO OUR QBIT ENTRY
PSAV:	BLOCK	1	;SAVE AREA FOR P DURING GETSEG UUO.
			; ALSO A FLAG. NON-ZERO MEANS THAT
			; THE HIGH SEGMENT IS SET UP.


;HIGH SEGMENT LOCATIONS

	EXTERN SHZERL,SHZERH	;LIMITS OF DATA IN HISEG FOR ZEROING


	EXTERN	JOBTAB		;TABLE INDEXED BY TERMINAL # 
				; GIVING SLAVE MONITOR JOB #
	EXTERN	MAXTRM		;MAX NUMBER OF VTTAM TERMINALS
	EXTERN	STDAY		;DATE SYSTEM STARTED OR STOPPED
	EXTERN	STTIME		;STARTING TIME MASTER BEGAN OR STOPPED
				;START IF POS, STOP IF NEG.
	EXTERN	MJOBN		;JOB NUMBER OF MASTER
	EXTERN	SINFLG		;0 IF INPUT BUFFER FREE
				;ELSE TERM NO WHICH FILLED IT
	EXTERN	SINBF		;SHARED INPUT BUFFER
	EXTERN	SOUTRM		;0 IF OUTPUT BUFFER EMPTY
				; ELSE TERMINAL NUMBER OF DATA IN
				; SOUTBF
	EXTERN	SOUMOD		;TYPE OF OUTPUT REQUEST
				;-1 ERASE SCREEN, 0 FULL SCREEN, ELSE
				; WRITE LINE
	EXTERN	SOUTBF		;SHARED OUTPUT BUFFER
	EXTERN	QREQ		;CRITICAL SECTION SYNC COUNT
	EXTERN	QBITS		;SLAVE SYNC REQUEST BIT-TABLE
	EXTERN	AVLINP		;ASSIGNMENT WORD FOR SHARED INPUT BUFFER
	EXTERN	QININP		;PUTTER FOR QUEUE FOR INPUT BUFFER
	EXTERN	QOUINP		;TAKER FOR QUEUE FOR INPUT BUFFER
	EXTERN	QBFINP		;QUEUE AREA FOR INPUT BUFFER
	EXTERN	QSTINP		;BYTE POINTER TO FIRST INPUT BUFFER
				; QUEUE ENTRY
	EXTERN	QFNINP		;BYTE POINTER TO LAST INPUT BUFFER
				; QUEUE ENTRY
;MONITOR STUFF
	PRJPRG=2		;GETTAB TABLE FOR PROJECT PROGRAMMER #'S
	NSWTBL=12		;GETTAB TABLE FOR HIGHEST JOB NUMBER
	HIGHJB=20		;GETTAB ENTRY FOR HIGHEST JOB NUMBER
				; CURRENTLY ON SYSTEM

	WAKPRJ=1B17		;WAKE UUO ENABLED FOR PROJECT MATCH

	OPDEF	PJRST	[JRST]	;PUSHJ POPJ CONVENTION
	SUBTTL	VTTAM CALL PROCESSING

	ENTRY VTOPEN,VTCLSE,ERSCR,ERLIN,WRSCR,WRLIN,VTWAIT

;HERE ON VTOPEN
VTOPEN:	PUSHJ	P,SETSEG	;SET UP THE SHARED DATA SEGMENT
	SKIPE	STTIME		;ARE WE NOW SAFELY STOPPED?
	PUSHJ	P,VTCLSE	;IF NOT, DO IMPLIED CLOSE
	SETZM	SHZERL		;ZERO SHARED SEGMENT
	MOVE	T,[XWD SHZERL,SHZERL+1]
	BLT	T,SHZERH
	PUSHJ	P,MQINIT	;SET UP SHARED QUEUE AREAS
	PUSHJ	P,UQINIT	;SET UP MASTER'S OWN QUEUE AREA
	DATE	T,		;STORE DATE FOR START-UP MESSAGE
	MOVEM	T,STDAY
	MSTIME	T,		;GET TIME
	ADDI	T,1		;ADD 1 IN CASE OF MIDNIGHT
	MOVEM	T,STTIME	;STORE IT TO START SLAVES
	PJRST	WAKALL		;WAKE ALL THE SLAVES AND RETURN TO COBOL


;HERE ON VTCLSE (ALSO ON VTOPEN TO DO AN IMPLIED CLOSE).
VTCLSE:	PUSHJ	P,CHKSEG	;CHECK AND GET HISEG IF NEEDED
	DATE	T,		;STORE DATE FOR SHUT-DOWN MESSAGE
	MOVEM	T,STDAY
	MSTIME	T,		;STORE -(TIME+1) TO SHUT DOWN SLAVES
	SETCAM	T,STTIME
	PUSHJ	P,WAKALL	;WAKE ALL SLAVES
	PUSHJ	P,WSTOP		;WAIT FOR ALL SLAVES TO SHUT DOWN
	SETZM	STTIME		;LEAVE FACT THAT WE ARE SAFELY DOWN
				; IN SHARED SEGMENT FOR NEXT VTOPEN.
	POPJ	P,		;RETURN
;HERE ON ERSCR CALL
ERSCR:	PUSHJ	P,GETTNO	;GET TERM-NO AND SET UP Q
	PUSHJ	P,SETRET	;SET UP RETURN ADDRESS ON STACK
	PUSHJ	P,GETOBF	;GET CONTROL OF SHARED OUTPUT BUFFER
	SETOM	SOUMOD		;OUTPUT REQUEST TO SLAVE = ERASE
	JRST	MOUTPB		;GO FINISH UP

;HERE ON ERLIN CALL
ERLIN:	PUSHJ	P,GETTNO	;GET TERM-NO
	PUSHJ	P,GETLNO	;GET LINE-NO
	PUSHJ	P,SETRET	;SET UP RETURN ADDRESS ON STACK
	PUSHJ	P,GETOBF	;GET CONTROL OF SHARED OUTPUT BUFFER
	SETZM	SOUTBF		;BLANK 1ST LINE OF SHARED OUTPUT BUFFER
	MOVE	T,[XWD SOUTBF,SOUTBF+1]
	BLT	T,SOUTBF+LINWDS-1
	MOVEM	L,SOUMOD	;TELL SLAVE WHICH LINE NUMBER
	JRST	MOUTPB		;GO FINISH UP

;HERE ON WRSCR CALL
WRSCR:	PUSHJ	P,GETTNO	;GET TERM-NO
	PUSHJ	P,GETSCR	;GET USER BUFFER AND SET UP RETURN ADR
	PUSHJ	P,GETOBF	;GET CONTROL OF SHARED OUTPUT BUFFER
	SETZM	SOUMOD		;TELL SLAVE TO WRITE SCREEN
	MOVEI	T,SCRWDS	;NUMBER OF WORDS TO COPY = SCREEN SIZE
	JRST	MOUTPA		;GO COPY AND FINISH UP

;HERE ON WRLIN CALL
WRLIN:	PUSHJ	P,GETTNO	;GET TERM-NO
	PUSHJ	P,GETLNO	;GET LINE-NO
	PUSHJ	P,GETSCR	;GET USER BUFFER AND SET UP RETURN ADR
	PUSHJ	P,GETOBF	;GET CONTROL OF SHARED OUTPUT BUFFER
	MOVEM	L,SOUMOD	;TELL SLAVE TO WRITE LINE L
	MOVEI	T,LINWDS	;NUMBER OF WORDS TO COPY = LINE SIZE
				;FALL INTO MOUTPA
;HERE ON WRLIN AND WRSCR TO COPY DATA TO SOUTBF.
MOUTPA:	PUSHJ	P,CPYOUT	;COPY T WORDS FROM USER BUFFER TO SOUTBF


;HERE ON ALL OUTPUT CALLS TO FLAG SOUTBF FULL, WAKE SLAVE, AND RETURN.
MOUTPB:	MOVEM	TT,SOUTRM	;TELL SLAVE HE HAS OUTPUT NOW
	PJRST	WAKSLV		;WAKE SLAVE THEN RETURN TO COBOL
;HERE ON VTWAIT
VTWAIT:	PUSHJ	P,CHKSEG	;CHECK AND GET HISEG IF NEEDED
	SKIPG	STTIME		;CHECK FOR VTOPEN CALLED
	JRST	ILLEG		;IF NOT, ILLEGAL TO CALL VTWAIT
	MOVE	Q,(P)		;SET UP Q BEYOND 1ST ARG.
	ADDI	Q,1		; (CAN'T USE GETTNO, CAUSE USER MAY
				;  HAVE GARBAGE IN TERM-NO.)
	PUSHJ	P,GETSCR	;GET USER'S BUFFER AND SET UP RETURN ADR

;(LOOP) HERE WAITING FOR DATA FROM A SLAVE
VTWAI1:	SKIPLE	TT,SINFLG	;IS THERE DATA YET?
	JRST	VTWAI2		;YES, GO PROCESS IT
	PUSHJ	P,MHIBER	;NO, HIBERNATE
	JRST	VTWAI1		; AND CHECK AGAIN

;HERE WHEN THERE IS DATA TO PROCESS. TT HOLDS VTTAM TERMINAL NUMBER.
VTWAI2:	MOVEM	TT,@-3(Q)	;STORE NUMBER FOR COBOL IN TERM-NO
	PUSHJ	P,CPYIN		;COPY DATA FROM SINBF TO USER'S BUFFER
	SETZM	SINFLG		;FLAG INPUT BUFFER EMPTY
	PJRST	RELINP		;RELEASE INPUT BUFFER
				; AND RETURN TO COBOL
	SUBTTL	COBOL LINKAGE ROUTINES

;SUBROUTINE TO SET UP Q (CALLING SEQUENCE POINTER AC),
;PICK UP VTTAM TERMINAL NUMBER IN TT AND CHECK IT,
;AND FINALLY MAKE SURE VTOPEN HAS BEEN CALLED.
;UPON RETURN, Q IS LEFT POINTING BEYOND FIRST ARG PSEUDO-OP.

;NOTE: THIS SUBROUTINE MUST BE CALLED DIRECTLY FROM MAIN LINE.

GETTNO:	PUSHJ	P,CHKSEG	;CHECK AND GET HISEG IF NEEDED
	SKIPG	STTIME		;HAS VTOPEN BEEN CALLED?
	JRST	ILLEG		;IF NOT, ILLEGAL CALL
	MOVE	Q,-1(P)		;SET UP Q
	SKIPLE	TT,@(Q)		;GET AND CHECK TT
	CAILE	TT,MAXTRM
	JRST	ILLEG		;IF ILLEGAL T
	AOJA	Q,CPOPJ		;INCREMENT Q AND RETURN

;HERE ON ILLEGAL CALL BY THE COBOL PROGRAM
ILLEG:	OUTSTR	[ASCIZ /?ILLEGAL VTTAM CALL/]	;TELL LOSER
	EXIT		; AND RETURN TO MONITOR


;SUBROUTINE TO SET UP AND CHECK L (LINE-NO).
;ASSUMES Q IS SET UP ON ENTRY AND RETURNS WITH Q POINTING TO NEXT ENTRY

GETLNO:	SKIPLE	L,@(Q)		;GET AND CHECK L
	CAILE	L,SCRLIN
	JRST	ILLEG		;IF BAD
	AOJA	Q,CPOPJ		;INCREMENT Q AND RETURN
;SUBROUTINE TO SET UP POINTERS TO USER'S SCREEN BUFFER.
;SS IS SET TO WORD ADDRESS OF SCREEN.
;NW IS SET TO NUMBER OF WHOLE WORDS IN SCREEN.
;NC IS SET TO NUMBER OF ODD CHARACTERS IN SCREEN.
;WHEN DONE, SETRET IS CALLED TO SET UP RETURN ADDRESS ON STACK.

GETSCR:	MOVE	SS,@(Q)		;GET BYTE POINTER TO SCREEN
	IBP	SS		;MAKE IT A LDB/DPB POINTER
	TLC	SS,360000	;IS IT SYNCHRONIZED?
	TLCE	SS,360000
	JRST	ILLEG		;IF NOT AN ERROR
	HRRZ	SS,SS		;GET ADDRESS OF BUFFER
	MOVE	T1,@1(Q)	;GET BYTE POINTER TO SCREEN-END
	IBP	T1		;MAKE IT A LDB/DPB POINTER
	ADDI	Q,2		;SET Q BEYOND THESE TWO ARGUMENTS
	MOVEI	NC,0		;ZERO PARTIAL CHARACTER COUNT

;LOOP HERE UNTIL T1 IS A SYNCHRONIZED BYTE POINTER.
GETSC1:	TLC	T1,360000	;IS T1 SYNCHRONIZED?
	TLCE	T1,360000
	JRST	GETSC2		;NOT YET
	HRRZ	NW,T1		;YES, GET NUMBER OF WHOLE WORDS
	SUB	NW,SS
	JUMPE	NC,SETRET	;IF T1 WAS ORIGINALLY SYNCHRONIZED, DONE
	ADDI	NC,6		; ELSE MAKE NC THE NUMBER OF ODD CHARS
	SUBI	NW,1		; AND REDUCE NUMBER OF FULL WORDS BY 1.
				;FALL INTO SETRET

;SUBROUTINE TO SET UP POPJ RETURN TO COBOL PROGRAM.
;THIS ROUTINE IS CALLED WHEN CALLING SEQUENCE ARGUMENTS MUST BE SKIPPED.
;AC Q MUST POINT PAST LAST ARGUMENT, AND PDL MUST BE 1 DEEP.

SETRET:	HRRM	Q,-1(P)		;FIX UP RETUN ADDRESS
	POPJ	P,		;RETURN

;HERE IN GETSCR WHEN T1 POINTER IS NOT YET SYNCHRONIZED.
GETSC2:	IBP	T1		;INCREMENT IT
	SOJA	NC,GETSC1	;COUNT DOWN NC AND TRY AGAIN.
	SUBTTL	DATA MOVING ROUTINES

;SUBROUTINE TO COPY A LINE OR SCREEN FROM USER BUFFER TO SOUTBF.
;CALLED WITH SS,NW, AND NC SET TO USER'S BUFFER PARAMETERS,
; AND WITH T= NUMBER OF WORDS TO COPY.

;UPON RETURN THE DATA IS COPIED WITH TRUNCATION OR BLANK
; FILL IF APPROPRIATE.

;NC IS CLOBBERED.

CPYOUT:	CAMLE	T,NW		;T1 = MIN(T,NW)
	SKIPA	T1,NW
	MOVE	T1,T
	JUMPE	T1,CPYOU1	;IF T1=0, NO FULL WORDS TO COPY
	HRLZ	B,SS		; ELSE BLT T1 WORDS
	HRRI	B,SOUTBF
	BLT	B,SOUTBF-1(T1)

;HERE WHEN ANY FULL WORDS HAVE BEEN COPIED
CPYOU1:	JUMPE	NC,CPYOU3	;JUMP IF NO PARTIAL WORD
	CAML	T1,T		;DO WE BLANK FILL?
	POPJ	P,		;IF NOT, RETURN
	SETZM	SOUTBF(T1)	;YES, ZERO PARTIAL WORD
	MOVSI	A,(POINT 6,0(T1))	;GET BYTE POINTER TO PARTIAL
	ADD	A,SS			; WORD IN USER'S BUFFER
	MOVE	B,[POINT 6,SOUTBF(T1)]	;GET BYTE POINTER TO STOW
					; PARTIAL WORD IN SOUTBF
;LOOP HERE COPYING CHARACTER OF PARTIAL WORD
CPYOU2:	ILDB	C,A		;COPY CHARACTER
	IDPB	C,B
	SOJG	NC,CPYOU2	;COUNT AND LOOP
	ADDI	T1,1		;WHEN DONE, COUNT THIS WORD AS FINISHED

;HERE WHEN BLANK FILL IS NEEDED AND ANY PARTIAL WORD HAS BEEN COPIED.
;AT THIS POINT, T1 WORDS ARE DONE.
CPYOU3:	CAMGE	T1,T		;ANY MORE WORDS?
	SETZM	SOUTBF(T1)	;IF SO, ZERO THE FIRST ONE
	CAIL	T1,-1(T)	;1 OR FEWER WORDS TO ZERO?
	POPJ	P,		;IF SO, WE ARE DONE
	MOVEI	T1,SOUTBF+1(T1)	; ELSE BLT ZEROS TO REST
	HRLI	T1,-1(T1)
	BLT	T1,SOUTBF-1(T)
CPOPJ:	POPJ	P,		;RETURN    (DEFINE COMMON POPJ)
;SUBROUTINE TO COPY SHARED INPUT BUFFER TO USER'S BUFFER
; WITH TRUNCATION OR FILL AS NEEDED.
;CALLED WITH SS, NW AND NC SET TO USER'S BUFFER PARAMETERS.
;UPON RETURN, NC IS CLOBBERED.

CPYIN:	MOVE	T,SS		;T=ADDRESS OF LAST FULL WORD OF USER'S
	ADDI	T,-1(NW)	; BUFFER
	MOVE	B,SS		;BLT WORD FOR SINBF TO USER'S BUFFER
	HRLI	B,SINBF

	CAIL	NW,SCRWDS	;IS USER BUFFER SHORTER THEN SINBF?
	JRST	CPYIN3		;IF NOT, GO TO COPY AND FILL ROUTINE.

;HERE WHEN USER'S BUFFER IS SHORTER THAN SINBF. WE USE ALL OUR DATA.
	JUMPE	NW,CPYIN1	;ANY FULL WORDS AT ALL?
	BLT	B,(T)		;IF SO, COPY THEM
;HERE WHEN ANY FULL WORDS HAVE BEEN COPIED
CPYIN1:	JUMPE	NC,CPOPJ	;IF NO ODD CHARACTERS, RETURN
	MOVE	A,[POINT 6,SINBF(NW)]	;ELSE GET BYTE POINTER TO READ
					; ODD CHARACTERS
	HRLI	T,(POINT 6,0,35)	;MAKE T A BYTE POINTER TO STORE
					; ODD CHARACTERS
;LOOP HERE COPYING ODD CHARACTERS.
CPYIN2:	ILDB	C,A		;COPY A CHARACTER
	IDPB	C,T
	SOJG	NC,CPYIN2	;COUNT ODD CHARS LEFT. LOOP IF NOT DONE
	POPJ	P,		; ELSE RETURN


;HERE WHEN USER'S BUFFER IS NOT SHORTER THAN SINBF. WE MAY HAVE TO FILL.
CPYIN3:	BLT	B,SCRWDS-1(SS)	;COPY ALL OF SINBF
	CAILE	NW,SCRWDS	;MORE FULL WORDS IN USER BUFFER?
	SETZM	SCRWDS(SS)	;IF SO, ZERO 1ST EXTRA WORD
	CAIG	NW,SCRWDS+1	;AT LEAST 2 EXTRA WORDS?
	JRST	CPYIN4		;IF NOT, SKIP BLT
	MOVEI	B,SCRWDS+1(SS)	; ELSE BLT ZEROS TO EXTRA WORDS
	HRLI	B,-1(B)
	BLT	B,(T)
;HERE WHEN ANY EXTRA WHOLE WORDS HAVE BEEN ZEROED.
;NOW ZERO ANY ODD CHARACTERS.
CPYIN4:	JUMPE	NC,CPOPJ	;IF NO ODD CHARACTERS, RETURN
	MOVEI	C,0		;GET A ZERO
	HRLI	T,(POINT 6,0,35)	;MAKE T INTO A BYTE POINTER
					; TO LAST WORD OF USER'S BUF
;LOOP HERE ZEROING ODD CHARACTERS AT END OF USER'S BUFFER
CPYIN5:	IDPB	C,T		;STOW A ZERO CHARACTER
	SOJG	NC,CPYIN5	;COUNT DOWN ODD CHARACTERS. LOOP IF MORE
	POPJ	P,		; ELSE RETURN
	SUBTTL	SEGMENT CONTROL

;SUBROUTINE TO CHECK IF HI-SEGMENT HAS BEEN CALLED
; AND CALL SETSEG ROUTINE IF NOT.

;PSAV IS USED AS A FLAG. IT HOLDS ACCUMULATOR P DURING THE GETSEG UUO,
; AND SO IS NON-ZERO IF NO GETSEG UUO HAS BEEN DONE.

CHKSEG:	SKIPN	PSAV		;HAS A GETSEG BEEN DONE YET?
	PUSHJ	P,SETSEG	;IF NOT, SET UP HIGH SEGMENT
	POPJ	P,		;RETURN



;SUBROUTINE TO SET UP HIGH SEGMENT.
;A GETSEG IS PERFORMED TO DSK:VTTAM.SHR, AND THEN SETUWP IS CALLED
; TO UNLOCK THE HIGH SEGMENT.
;ALL AC'S EXCEPT P ARE CLOBBERED BY THIS ROUTINE.
;UPON EXIT, PSAV IS SET NON-ZERO, TO INDICATE THAT THIS ROUTINE
; WAS CALLED

SETSEG:	MOVEM	P,PSAV		;SAVE P DURING GETSEG UUO
	MOVEI	T,SEGBLK	;GET SHARED SEGMENT
	GETSEG	T,
	HALT	.		;COULDN'T GET SEGMENT
	MOVE	P,PSAV		;RESTORE P
	MOVEI	T,0		;UNLOCK SHARED SEGMENT
	SETUWP	T,
	HALT	.		;COULDN'T UNLOCK SHARED SEGMENT
	POPJ	P,		;RETURN


;CONTROL BLOCK FOR USE BY GETSEG UUO

SEGBLK:	SIXBIT	/DSK/		;GETSEG DEVICE
	SIXBIT	/VTTAM/		;FILE
	SIXBIT	/SHR/		;EXT
	0
	0			;PPN
	0
	SUBTTL	SYNCHRONIZATION AND QUEUEING

;SUBROUTINE TO AWAKEN SLAVE JOB RUNNING VTTAM TERMINAL TT.
;IF THE SLAVE HAS STARTED UP, THIS ROUTINE RETURNS IMMEDIATELY.
;IF THE SLAVE HAS NOT YET STARTED UP, THIS ROUTINE WAITS FOR HIM.

;CALL	PUSHJ P,WAKSLV

;BACK HERE TO WAIT FOR SLAVE
WAKSL1:	PUSHJ	P,MHIBER	;MASTER HIBERNATES
				;FALL INTO WAKSLV TO TRY AGAIN

;ENTER HERE
WAKSLV:	SKIPG	T,JOBTAB(TT)	;GET SLAVE JOB NUMBER
	JRST	WAKSL1		;WAIT IF NONE SET UP YET
	WAKE	T,		; ELSE WAKE SLAVE.
	HALT	.		;WAKE FAILED
	POPJ	P,		;RETURN


;SUBROUTINE TO WAKE ALL VTTAM JOBS.
;CALLED BY MASTER ON VTOPEN AND VTCLSE TO AVOID HUNG CONDITIONS.
;IN ORDER TO REDUCE SWAPPING, ONLY JOBS WITH SAME PPN AS MASTER
;ARE AWAKENED.

WAKALL:	GETPPN	A,		;GET MASTER PPN
	JFCL			;IN CASE OF SKIP RETURN
	MOVE	T,[XWD HIGHJB,NSWTBL]	;GET HIGHEST JOB # IN USE
	GETTAB	T,
	HALT	.		;GETTAB FAILED

;LOOP HERE TO AWAKEN JOB T IF IN SAME PROJECT AS MASTER.
WAKAL1:	MOVEI	B,PRJPRG	;GET PPN OF JOB T
	HRL	B,T
	GETTAB	B,
	MOVEI	B,0		;IF GETTAB FAILED, NOT A MATCH!
	CAMN	B,A		;IS ITS PPN = MASTER'S?
	WAKE	T,		;IF SO WAKE IT
	JFCL			;NO-OP IF NO MATCH OR WAKE FAILED
	SOJG	T,WAKAL1	;TRY NEXT LOWEST JOB NUMBER IF NOT DONE
	POPJ	P,		; ELSE RETURN



;SUBROUTINE FOR MASTER TO HIBERNATE.
MHIBER:	MOVSI	W,(WAKPRJ)	;SET WAKE ENABLE BITS
	HIBER	W,		;HIBER UUO
	HALT	.		;HIBER UUO FAILED
	POPJ	P,		;OK - RETURN
;SUBROUTINE TO WAIT UNTIL ALL SLAVES ARE SAFELY STOPPED.
;CALLED ON VTCLSE AFTER STTIME IS SET NEGATIVE AND ALL SLAVES
; HAVE BEEN AWAKENED.
WSTOP:	MOVEI	T,MAXTRM		;SET TO SCAN ALL SLAVES
	JRST	WSTOP2			;GO DO SO

;BACK HERE TO WAIT AND THEN CHECK A SLAVE AGAIN
WSTOP1:	MOVE	W,[WAKPRJ!^D5000]	;HIBERNATE 5 SECONDS OR UNTIL
	HIBER	W,			; WAKE CALLED.
	HALT	.			;HIBER UUO FAILED
				;(WE CAN'T USE INFINITE HIBERNATE
				; BECAUSE SLAVE MAY ALREADY BE GONE)
;(LOOP) HERE TO CHECK SLAVE T.
WSTOP2:	SKIPE	JOBTAB(T)	;IS SLAVE RUNNING?
	JRST	WSTOP1		;IF SO, WAIT A WHILE
	SOJG	T,WSTOP2	;IF NOT GO CHECK NEXT SLAVE UNLESS DONE
	POPJ	P,		;DONE, SO RETURN

;SUBROUTINE TO GET CONTROL OF SHARED OUTPUT BUFFER.
;CALLED BY MASTER PRIOR TO ENTERING A REQUEST TO ENSURE THAT BUFFER IS
;FREE.
;WAITS IF NECESSARY UNTIL IT IS FREE.

GETOBF:	SKIPN	SOUTRM		;IS OUTPUT BUFFER FREE?
	POPJ	P,		;IF SO RETURN
	PUSHJ	P,MHIBER	; ELSE HIBERNATE
	JRST	GETOBF		; AND TRY AGAIN.


;SUBROUTINE TO RELEASE INPUT BUFFER RESOURCE AND WAKE UP THE
;FIRST WAITER (FCFS) IF ANY.

RELINP:	PUSHJ	P,GETQ		;SYNCHRONIZE
	SETZM	AVLINP		;MAKE RESOURCE FREE
	MOVE	T,QININP	;IS THERE A QUEUED REQUEST?
	CAMN	T,QOUINP
	PJRST	RELQ		;NO, LEAVE CRITICAL SECTION AND RETURN
	ILDB	T,QOUINP	;YES, ASSIGN TO FIRST USER
	MOVEM	T,AVLINP
	WAKE	T,		;AWAKEN HIM
	HALT	.		;WAKE SHOULD NEVER FAIL
	MOVE	T,QSTINP	;SET QOUINP TO START IF AT END
	MOVE	T1,QFNINP
	CAMN	T1,QOUINP
	MOVEM	T,QOUINP
	PJRST	RELQ		;LEAVE CRITICAL SECTION AND RETURN
;SUBROUTINES TO SYNCHRONIZE CRITICAL (SHORT) NON-REENTRANT SECTIONS.
;THESE ROUTINES MAY BE CALLED BY ANY JOB SHARING THE HIGH-SEGMENT.
;THE INTENTION IS TO USE THESE ROUTINES TO INTERLOCK ONLY A FEW
;INSTRUCTIONS OF A HIGHER LEVEL QUEUEING SYSTEM, IN MUCH THE MANNER
;THE MONITOR OCCASIONALLY USES CONO PI,PIOFF.
;THE QUEUING DISCIPLINE DEPENDS ONLY ON JOB NUMBER.
;IF THERE IS A CONFLICT THE LOSER(S) ARE BLOCKED, AND AWOKEN
;ACCORDING TO THE ABOVE DISCIPLINE.

;CAUTION: THIS CODE FAILS ON MULTI-PROCESSOR SYSTEMS USING DRUM-SPLIT!

;SUBROUTINE TO GET Q RESOURCE, WAITING IF NECESSARY.

GETQ:	MOVE	T,QMASK		;SET OUR REQUEST BIT
	IORM	T,@QWORD
	AOSN	QREQ		;TRY AND GRAB THE INTERLOCK
	ANDCAM	T,@QWORD	;WON, SO CLEAR REQUEST BIT

;LOOP THRU HERE WHILE WAITING FOR Q RESOURCE
GETQ1:	TDNN	T,@QWORD	;HAS OUR REQUEST BIT BEEN CLEARED?
	POPJ	P,		;YES, RETURN
	PUSHJ	P,MHIBER	;NO, WAIT UNTIL AWOKEN
	JRST	GETQ1		;AND CHECK FOR SPURIOUS WAKES


;SUBROUTINE TO RELEASE Q RESOURCE, WAKING UP A WAITER, IF THERE IS ONE.

RELQ:	SOSGE	QREQ		;COUNT DOWN USE INTERLOCK
	POPJ	P,		;-1 MEANS NO WAITERS, RETURN
	MOVEI	C,3		;SET TO SCAN ALL QBITS WORDS

;LOOP THRU HERE TO SCAN QBITS LOOKING FOR A 1 BIT
RELQ1:	SKIPE	T,QBITS(C)	;SEE IF WORD IS ZERO
	JFFO	T,RELQ2		;NO, SO FIND FIRST ONE BIT
	SOJGE	C,RELQ1		;YES, TRY NEXT WORD UNLESS LAST
	HALT	.		;SHOULD NEVER HAPPEN

;HERE WHEN A WAITER HAS BEEN FOUND.
RELQ2:	MOVN	T1,T1		;CLEAR HIS REQUEST BIT
	MOVSI	T,400000
	LSH	T,(T1)
	ANDCAM	T,QBITS(C)
	IMULI	C,^D36		;GET HIS JOB NUMBER
	SUB	C,T1
	WAKE	C,		;AWAKEN HIM
	HALT	.		;WAKE SHOULD NEVER FAIL
	POPJ	P,		;RETURN
;SUBROUTINE TO INITIALIZE MASTER'S QUEUE DATA

UQINIT:	PJOB	T,		;GET JOB NUMBER
	MOVEM	T,QJOBN		;SAVE IT
	WAKE	T,		;WAKE OURSELF UP
	HALT	.		;WAKE SHOULD NEVER FAIL
	IDIVI	T,^D36		;GET WORD AND BIT FOR THIS NUMBER
	ADDI	T,QBITS
	MOVEM	T,QWORD		;SAVE WORD ADDRESS
	MOVN	T1,T1
	MOVSI	T,400000
	LSH	T,(T1)
	MOVEM	T,QMASK		;BIT MASK
	PJRST	MHIBER		;DUMMY HIBERNATE TO SET MASTER WAKE
				; ENABLES, THEN RETURN

;SUBROUTINE FOR MASTER TO INITIAIZE INTERLOCKS AND QUEUES
;(ASSUMES ALL OF SHARED CORE HAS ALREADY BEEN ZEROED.)

MQINIT:	MOVE	T,QSTINP	;INITIALIZE QUEUE POINTERS
	MOVEM	T,QININP
	MOVEM	T,QOUINP
	PJOB	T,		;STORE MASTER JOB NUMBER
	MOVEM	T,MJOBN		; SO SLAVES CAN WAKE HIM.
	SETOM	QREQ		;MAKE Q RESOURCE FREE
	POPJ	P,		;RETURN
	LIT
	END