File F1095.PA (PAL assembler source file)

Directory of image this file is from
This file as a plain text file

/RTS-8	SMALL REAL TIME SYSTEM
/
/
/
/
/
/
/
/
/
/COPYRIGHT  (C)  1974 BY DIGITAL EQUIPMENT CORPORATION
/
/
/
/
/
/
/
/
/
/
/THE INFORMATION IN THIS DOCUMENT IS SUBJECT TO CHANGE WITHOUT NOTICE
/AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
/CORPORATION.  DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY
/FOR ANY ERRORS THAT MAY APPEAR IN THIS DOCUMENT.
/
/THE SOFTWARE DESCRIBED IN THIS DOCUMENT IS FURNISHED TO THE PURCHASER
/UNDER A LICENSE FOR USE ON A SINGLE COMPUTER SYSTEM AND CAN BE COPIED
/(WITH INCLUSION OF DIGITAL'S COPYRIGHT NOTICE) ONLY FOR USE IN SUCH
/SYSTEM, EXCEPT AS MAY OTHERWISE BE PROVIDED IN WRITING BY DIGITAL.
/
/DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY FOR THE USE
/OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY
/DIGITAL.
/
/
/
/
/
/
/
/
/
/

/RICHARD LARY		LAST EDITED FEB. 3, 1974

/BASED ON      T-O-Y	JUNE 5, 1973

/IOT'S FOR OPTIONAL HARDWARE:

	IFZERO	PDP8E	<CAFHLT=HLT>	/HALT TO LET USER CLEAR FLAGS
	IFNZRO	PDP8E	<CAFHLT=CAF>	/MACHINE WILL CLEAR FLAGS

SINT=	6254		/SKIP ON USER INTERRUPT
SUF=	6274		/SET USER MODE FLAG
SPL=	6102		/SKIP ON POWER LOW
/PAGE 0 OF FIELD 0

	*0		/INTERRUPT "VECTOR"
	0		/SET TO  JMP I 3  ON POWER FAILURE
	JMP I	.+1
	INTRPT
	IFNZRO	PWRFAL	<
PFLADR, PFLRTN		/CHANGED BY POWER FAIL TASK
	>

	*17
XR,	0		/INDEX REGISTER USED BY EXEC
LOC20,	0		/MONITOR CALL LOCATION ** MUST BE AT 20 **
DCDF,	CDF 0
CALIOF, IOF
	JMP I	CALEXC
	DSPOST		/** MUST BE AT LOC 24 **
	XWAITM		/** MUST BE AT LOC 25 **
CALEXC, EXEC
ACARG,	0		/HOLDS AC ARG ON EXEC CALLS
MPTR,	0		/POINTS TO FIRST WORD OF MESSAGE Q POINTER
MPT2,	0		/"	"  SECOND "   "
TASKX,	0		/CURRENT TASK NUMBER
INTT,	0		/INTERRUPT-LEVEL TEMPORARY

SVSFLG, -1		/SAVE STATE FLAG -
			/-1 MEANS CPU STATE COUNTS & SHOULD BE SAVED,
			/0 MEANS CPU STATE IS UNIMPORTANT.
TSWFLG, 1		/TASK SWITCHING INHIBITED FLAG -
			/ 1 = TASK SWITCHING ALLOWED
			/ 0 = TASK SWITCHING INHIBITED
			/-1 = TASK SWITCHING INHIBITED, RESCAN ASAP

TODL,	0		/TIME-OF-DAY LOW ORDER
TODH,	0		/TIME-OF-DAY HIGH ORDER
DATE,	TSTCLK		/DATE WORD - USED TO INIT CLOCK HANDLER
MCREF,	0		/MCR STARTUP EVENT FLAG
T,	0		/NON-INTERRUPT LEVEL TEMPORARY
	ZBLOCK	50-.	/RESERVED FOR FUTURE EXPANSION
/SET UP EXEC LINKAGE IN FIELDS 1-7

	IFZERO	HGHFLD-10&4000	<
	FIELD 1
	*21
	CDF 10
	CIF 0
	JMP	CALIOF
	DSPOST
	XWAITM
	>
	IFZERO	HGHFLD-20&4000	<
	FIELD 2
	*21
	CDF 20
	CIF 0
	JMP	CALIOF
	DSPOST
	XWAITM
	>
	IFZERO	HGHFLD-30&4000	<
	FIELD 3
	*21
	CDF 30
	CIF 0
	JMP	CALIOF
	DSPOST
	XWAITM
	>
	IFZERO	HGHFLD-40&4000	<
	FIELD 4
	*21
	CDF 40
	CIF 0
	JMP	CALIOF
	DSPOST
	XWAITM
	>
	IFZERO	HGHFLD-50&4000	<
	FIELD 5
	*21
	CDF 50
	CIF 0
	JMP	CALIOF
	DSPOST
	XWAITM
	>
	IFZERO	HGHFLD-60&4000	<
	FIELD 6
	*21
	CDF 60
	CIF 0
	JMP	CALIOF
	DSPOST
	XWAITM
	>
	IFZERO	HGHFLD-70&4000	<
	FIELD 7
	*21
	CDF 70
	CIF 0
	JMP	CALIOF
	DSPOST
	XWAITM
	>

	FIELD 0
/INTERRUPT ROUTINE

	*200

TS8LOC, CAFHLT		/SO WE CAN START AT 200
NEWTSK, ION
INTFGS, JMP I	.+1	/GO AND FIND THE FIRST
INTAC,	FINDJ		/TASK TO RUN

INTRPT,
	IFDEF	OS8	<
	SINT		/MUST BE FIRST SKIP IN INTERRUPT CHAIN!
	SKP
	JMP I	TS8LOC
	>
	DCA	INTAC	/SAVE AC
	IFNZRO	PDP8E	<GTF>
	IFZERO	PDP8E	<
	RAR		/COMBINE LINK, IF AND DF INTO ONE WORD
	RIB
	>
	DCA	INTFGS
USERSK, 		/VERY HIGH PRIORITY USER FLAG TESTS GO HERE
	IFNZRO	PWRFAL	<SPL>	/SKIP ON POWER LOW
	JMP	TSTCLK	/NO MORE H.P. SKIPS - GO TO SKIP CHAIN
	IFNZRO	PWRFAL	<
	TAD	0
	DCA	INTT	/SAVE LOCATION ZERO
	TAD	(JMP I PFLADR
	DCA	0	/SET UP 0 FOR RESTART
	HLT		/DON'T TRY ANYTHING FANCY

PWFLEF, 0		/POWER FAILURE EVENT FLAG
PFLRTN, TAD	INTT	/** MUST BE AT PWFLEF+1 **
	DCA	0	/RESTORE LOCATION OF POWER LOW INTERRUPT
	TAD	(PWFLEF /POST THE POWER-FAIL INTERRUPT
	POSTDS		/TO EXECUTE THE POWER-FAIL TASK (IF ANY)
	>
BSKCHN, DISMIS		/BEGINNING OF SKIP CHAIN LIST
TSTCLK, CDF CIF 0	/ADDRESS FOLLOWED BY CDF CIF FIELD
	NOP		/SET TO CLSK BY CLOCK ROUTINE
	JMP I	BSKCHN
DCDIF0, CDF CIF 0	/CLOCK HANDLER ALWAYS IN FLD 0
	JMP I	.+1
	DISMIS		/CHANGED BY CLOCK HANDLER (IF ANY)
/SUBROUTINE TO POST AN EVENT FLAG AND DISMISS FROM INTERRUPTS
/ENTER WITH IOF, DF=D.F. OF EVENT FLAG, AC=ADDRESS OF EVENT FLAG

DSPOST, SNA
	JMP	DISMIS	/NO EVENT FLAG - JUST DISMISS
	DCA	INTT
	AC4000
	TAD I	INTT	/LINK=1 IF EVENT FLAG.LT.0, 0 IF.GT.0
	DCA	NEWTSK	/SAVE OLD VALUE OF EVENT FLAG
	DCA I	INTT	/ZERO EVENT FLAG TO INDICATE EVENT COMPLETION
	TAD	NEWTSK
	SPA		/** LINK MUST BE 0 HERE IF AC IS NEGATIVE **
	JMP	.+3	/IF E.F. .LT. 0, TASK WAS WAITING FOR EVENT
	JMS I	(FREEJ	/SO CLEAR "EVENT WAIT" BIT IN FLAG WORD.
	EFWT!EORMWT	/IF THE TASK WHICH WAS WAITING ON THIS
	SNL CLA 	/EVENT FLAG IS HIGHER PRIORITY THAN THE TASK
	JMP	DISMIS	/CURRENTLY RUNNING, SUSPEND THE CURRENT TASK
	TAD	0	/UNLESS WE ARE IN A NON-INTERRUPTABLE ZONE
	IFDEF OS8 <RIB> /(NAMELY LOCS 0-77 OF A FIELD
	AND	(7700	/NOT USED BY OS/8 BACKGROUND)
	SZA CLA 	/OR TASK SWITCHING HAS BEEN SPECIFICALLY
	TAD	TSWFLG	/INHIBITED BY THE SOFTWARE
	SMA SZA CLA	/(BY MAKING TSWFLG LE 0)
	JMP	STOPJ
	STA		/IF TASK SWITCHING IS INHIBITED,
	DCA	TSWFLG	/SET FLAG TO INSURE A RESCAN OF THE TASK LIST
	JMP	DISMIS	/WHEN WE UNINHIBIT IT, THEN DISMISS NORMALLY.

STOPJ,	ISZ	SVSFLG	/IS THE STATE OF THE CURRENT TASK WORTH SAVING?
	JMP	NOSVST	/NO - FORGET IT.
	TAD	TASKX
	CLL RTL
	TAD	(TSTABL-1
	DCA	XR	/SAVE THE CURRENT TASK'S STATE
	TAD	INTFGS
	DCA I	XR
	TAD	0
	DCA I	XR
	TAD	INTAC
	DCA I	XR
	IFNZRO	EAE	<
	MQA
	DCA I	XR	/SAVE THE MQ
	>
NOSVST, TAD	NEWTSK	/WE NOW ATTEMPT TO START UP THE HIGHER
	ION		/PRIORITY TASK. - HOWEVER, SINCE INTERRUPTS
	DCA	TASKX	/HAVE BEEN OFF FOR A WHILE, WE RE-ENABLE THEM
			/WITH THE "DON'T SAVE STATE" FLAG ON.

/THIS MEANS THAT IF ANYBODY WITH HIGHER PRIORITY THAN "NEWTSK"
/GETS AN EVENT-FLAG-SETTING INTERRUPT NOW, WE'LL JUST DASH OFF
/AND START HIM INSTEAD.

/** NOW FALL INTO "STARTJ" ON THE NEXT PAGE **
/CODE TO START UP A TASK
/ENTER WITH TASK# IN "TASK", DF=0, ION, NO STATE (SVSFLG=0)

STARTJ, IFZERO	HGHFLD	<ION>	/INTERRUPTS ALREADY ON IF CIF WORKS
	TAD	TASKX
	CLL RTL
	TAD	(TSTABL-1	/FORM POINTER INTO TASK STATE TABLE
	DCA	XR
	STA
	IOF		/OK, THINGS ARE GETTING SENSITIVE - TURN INTS OFF
	DCA	SVSFLG	/AND RESET SAVE-STATE FLAG TO "YES"
	TAD I	XR
	DCA	INTFGS
	TAD I	XR
/	SNA		/PC=0 MEANS NONRESIDENT TASK, REAL PC IN MQ
/	JMP	NONRES	/** NOT IMPLEMENTED IN PHASE 1 **
	DCA	0	/SIMULATE AN INTERRUPT FROM THE TASK
	TAD I	XR
	DCA	INTAC	/AND DISMISS IT
	IFNZRO	EAE	<
	TAD I	XR
	MQL		/RESTORE MQ
	>

/** NOW FALL INTO "DISMIS" ON NEXT PAGE **
/INTERRUPT DISMISS ROUTINE - ALSO USED TO START TASKS

DISMIS, IFNZRO	PDP8E	<
	SRQ		/ANY OTHER INTERRUPTS PENDING?
	SKP		/NO
	JMP	USERSK	/YES - SKIP PREAMBLE STUFF FOR EXTRA SPEED
	>
	TAD	INTFGS
	IFNZRO	PDP8E	<
	IFNZRO	HGHFLD	<RTF>
	IFZERO	HGHFLD	<RAL>	/RTF DOESN'T WORK RIGHT ON 4K 8E'S
	CLA
	>
	IFZERO	PDP8E	<
	IFDEF	OS8	<
	TAD	(700	/PROPAGATE USER-MODE BIT FROM BIT 5 TO BIT 2
	>
	CLL RTL
	RAL		/USER-MODE BIT NOW IN LINK
	AND	(70	/FAKE AN RTF IF NOT ON A PDP8E
	TAD	DCDF
	DCA	DISCDF
	IFDEF	OS8	<
	SZL		/IF USER MODE WAS ON WHEN WE INTERRUPTED,
	SUF		/TURN IT ON WHEN WE DISMISS
	>
	AC4000
	TAD	INTFGS
	AND	(70	/NOTE THAT THE LINK IS NOW RESTORED
	TAD	DCDIF0
	DCA	DISCIF
DISCIF, 0
DISCDF, 0
	>
	TAD	INTAC
	IFZERO	-PDP8E&HGHFLD	<ION>	/FOR PRE 8E OR 4K 8E MACHINES
	JMP I	0
	PAGE
/RTS-8 EXECUTIVE - PROCESSES USER REQUESTS

/CALLED BY:	JMS 20	/IN ANY FIELD
/		ARGS
/
/CODE AT LOC 20 TURNS IOF, DOES CDF CUR AND CIF 0 AND JUMPS HERE

EXEC,	DCA	ACARG	/SAVE POSSIBLE AC ARGUMENT
	TAD	TSWFLG	/TSWFLG=1 HERE UNLESS WE WERE INTERRUPTED
	SMA CLA 	/WHEN WE WERE IN THE PAGE 0 CODE, IN WHICH CASE
	DCA	TSWFLG	/ITS -1  -  ZERO IT IF IT WAS 1
	ION		/IT IS NOW OK TO TURN INTERRUPTS BACK ON
	RDF
	TAD	ECDIF0
	DCA	EXRET	/SAVE RETURN FIELD
	TAD I	(LOC20	/GET LOC 20 OF THE CALLING FIELD
	DCA	LOC20	/SAVE IT IN FIELD 0
	TAD I	LOC20	/GET THE COMMAND
	ISZ	LOC20
	AND	(17
	TAD	CMDJMP
	DCA	.+1	/TURN COMMAND INTO DISPATCH JUMP
	HLT

CMDJMP, JMP I	.+1
	XSEND		/SEND MESSAGE TO A TASK
	XRECEIV 	/GET A MESSAGE FROM THE MESSAGE QUEUE
	XWAITE		/WAIT FOR AN EVENT FLAG TO BE POSTED
	XRUN		/RUN A TASK (IF NOT BEING RUN)
	XSUSPND 	/SUSPEND EXECUTION OF A TASK
	XPOST		/POST AN EVENT FLAG
	XSKPINS 	/INSERT SKIP INTO INTERRUPT CHAIN
	XDERAL		/DERAIL A TASK
	XBLKARG 	/BLOCK TASK FOR REASON SPECIFIED BY ARG
	XSENDW		/SEND MESSAGE AND WAIT FOR COMPLETION
	XUNBARG 	/UNBLOCK TASK FOR REASON SPECIFIED BY ARG

/ROUTINE TO DERAIL A TASK'S EXECUTION INTO A SUBROUTINE

XDERAL, TAD I	LOC20
	ISZ	LOC20
	DCA	T	/SAVE ADDR OF DERAIL SUBR
	TAD	ACARG
	CLL RTL
	TAD	(TSTABL /GET POINTER INTO TASK STATE TABLE
	DCA	MPTR
	CDF 0
	TAD I	MPTR
	AND	(70	/GET INSTRUCTION FIELD
	TAD	DCDF
	DCA	DRLCDF
	ISZ	MPTR
	TAD I	MPTR	/GET CURRENT TASK PC
DRLCDF, HLT		/CDF TO TASK FIELD
	DCA I	T	/STORE PC IN SUBR HEADER
	CDF 0
	TAD	T
	IAC
	DCA I	MPTR	/SET PC TO SUBR HEADER + 1
	JMP	EXRET	/RETURN TO CALLING TASK


/SUBROUTINE TO WAIT FOR MULTIPLE EVENTS
/CALLED VIA JMS I 25 WITH INTERRUPTS OFF.
/THIS ROUTINE SHOULD BE CALLED AFTER SCANNING THE MULTIPLE EVENT FLAGS
/(WITH INTERRUPTS OFF) TO AVOID TURNING INTERRUPTS ON BEFORE THE
/WAIT MASK IS PLACED IN TFTABL.  THE "BLKARG" CALL TO THE RTS EXEC
/WOULD TURN INTERRUPTS ON (IN THE EXEC), THUS INVITING
/MULTIPLE-UPDATE PROBLEMS.

XWAITM, 0
	TAD	XWAITM
	DCA	LOC20	/FAKE A CALL TO EXEC (IN CASE WE MUST WAIT)
	RDF
	TAD	ECDIF0
	DCA	EXRET
	DCA	TSWFLG	/THIS IS STILL PART OF THE FAKE CALL
	TAD I	LOC20	/GET THE WAIT MASK
	ISZ	LOC20
	CLL		/MAKE SURE TSWAIT ZEROS TASK AC
	JMP I	(TSWAIT /GO WAIT ON MASK
/INSERT A DEVICE SKIP INTO THE INTERRUPT CHAIN

XSKPINS,TAD I	LOC20	/GET THE ADDRESS OF THE SKIP - 2
	ISZ	LOC20
	DCA	T
	TAD I	T
	SZA CLA 	/IF ARGUMENT LOC IS NON-ZERO,
	JMP	EXRET	/IT IS ALREADY IN THE SKIP CHAIN - IGNORE
	TAD	(DISMIS /CHAIN IT TO THE END OF THE CHAIN
	DCA I	T
	ISZ	T
	TAD	ECDIF0
	DCA I	T
	IFNZRO	HGHFLD	<
	RDF		/GET CDF TO NEW "LAST SKIP"
	TAD	ECDIF0
INTCDF, CDF CIF 0	/CDF TO FLD OF OLD "LAST SKIP" AND INH INTS
	CIF 0		/CORRECT I.F. FROM LAST KLUDGEY INSTRUCTION
	DCA	INTCDF	/UPDATE "LAST SKIP" FIELD TO NEW ONE
	>
	TAD	T
	DCA I	INTEND	/CHAIN OLD SKIP TO NEW ONE
	ISZ	INTEND
	IFNZRO	HGHFLD	<
	TAD	INTCDF
	>
	DCA I	INTEND
	STA
	TAD	T
	DCA	INTEND	/UPDATE POINTER TO END OF SKIP CHAIN

EXRET,	HLT		/CDF CIF RETURN FIELD (ALSO INHIBIT INTERRUPTS)
	IFZERO	HGHFLD	<IOF>	/INTERRUPTS OFF FOR ISZ!
	ISZ	TSWFLG	/ALLOW TASK SWITCHING (SKIPS IF RESCAN NECESSARY)
	IFZERO	HGHFLD	<
	JMP	.+3	/NO RESCAN NECESSARY
	ION		/TASK SWITCHING STILL INHIBITED, TURN ION AND
	JMP	ECDIF0	/STOP CURRENT JOB AND GO TO RESCAN
	ION		/NOW ITS SAFE TO TURN INTERRUPTS BACK ON
	>
	JMP I	LOC20	/RETURN TO CALLING TASK
ECDIF0, CDF CIF 0	/OOPS - WE MUST TASK SWITCH IMMEDIATELY!
	JMP I	(TSTOP	/GO STOP THIS TASK AND RUN SOMEONE ELSE

INTEND, BSKCHN
	PAGE
/SEND A MESSAGE TO A TASK

XSENDW, STA		/SET OR
XSEND,	DCA	SWTFLG	/CLEAR WAIT FLAG
	TAD I	LOC20
	ISZ	LOC20	/GET THE
	DCA	ACARG	/TASK NUMBER FROM THE ARGUMENT LIST
	TAD I	LOC20	/GET THE ADDRESS OF THE MESSAGE
	DCA	MSGADR
	TAD I	MSGADR
	SNA CLA 	/IS THE MESSAGE ALREADY IN A QUEUE?
	JMP	MSGFRE	/NO
	AC7775
	TAD	LOC20
	DCA	LOC20	/BUMP PC BACK TO DO CALL AGAIN
MSEFWT, TAD	MSGADR
	JMP I	(WAITS	/WAIT FOR MESSAGE TO BE FREE
MSGFRE, ISZ	LOC20
	TAD	ACARG	/GET THE ADDRESS OF THE TARGET TASKS'
	JMS	SRCOMN	/MESSAGE QUEUE POINTER
	DCA	MSGCDF	/SAVE CDF TO NEW MESSAGE'S FIELD
	TAD	DCDF
ADDTOQ, DCA	MPTCDF	/SAVE CDF TO FIELD OF CURRENT QUEUE POINTER
	CLA IAC
	TAD	MPTR
	DCA	MPT2	/GET POINTER TO SECOND WORD OF POINTER
	TAD I	MPT2
	DCA	T	/SAVE ADDRESS OF NEXT QUEUE ENTRY
	TAD I	MPTR	/FIRST WORD IS A CDF
	SNA		/ZERO TERMINATES THE QUEUE
	JMP	ENDOFQ
	DCA	NXTCDF	/SAVE CDF
RCVPTR,
NXTCDF, HLT
	AC3777
	AND I	T	/FIRST WORD OF MESSAGE HEADER IS TASK#
	CIA CLL 	/COMPARE TO NUMBER OF SENDING TASK
	TAD	TASKX	/IF NUMBER IS LOWER WE INSERT
	SNL CLA 	/THE MESSAGE BEFORE THIS ONE
	JMP	ENDOFQ
	CLA IAC
	TAD	T
	DCA	MPTR	/OTHERWISE GO ON TO THE NEXT
	TAD	NXTCDF	/QUEUE ENTRY
	JMP	ADDTOQ
/COME HERE WHEN WE HAVE FOUND THE PLACE TO INSERT THE MESSAGE

ENDOFQ,
MPTCDF, HLT		/SET DF TO FIELD OF PREVIOUS POINTER
	TAD I	MPTR
	DCA	MPTCDF	/SAVE PREVIOUS CDF
	TAD	MSGCDF	/LINK THE NEW MESSAGE BETWEEN TWO
	DCA I	MPTR	/EXISTING MESSAGES ON THE QUEUE
	TAD	MSGADR
	DCA I	MPT2	/OK - HALF THE LINKAGE IS DONE
	IOF		/MUST TURN INTERRUPTS OFF TO CALL FREEJ!
	TAD	ACARG
	JMS I	(FREEJ	/CLEAR MESSAGE WAIT BIT FOR RECEIVER
	MSGWT!EORMWT	/(DO IT NOW SO DF WILL BE CORRECT LATER)
	TAD	TASKX	/*** CODE IN THIS RANGE MUST NOT TOUCH LINK ***
MSGCDF, HLT		/* NOW GO TO THE MESSAGE'S DATA FIELD
	ION		/* WE'RE SAFE - TURN INTERRUPTS ON
	DCA I	MSGADR	/* STORE THE SENDING TASK NUMBER
	ISZ	MSGADR	/*
	TAD	MPTCDF	/*
	DCA I	MSGADR	/* STORE CDF TO NEXT MESSAGE IN Q
	ISZ	MSGADR	/*
	TAD	T	/*
	DCA I	MSGADR	/* STORE ADDRESS OF NEXT MESSAGE IN Q
	ISZ	SWTFLG	/* SHOULD WE WAIT ON THIS MESSAGE?
	JMP I	(POSTEX /* NO - RUN RECEIVER IF ITS
			/* HIGHER PRIORITY, ELSE EXIT
	AC7776		/DON'T WORRY ABOUT RECEIVER -
			/WAITING WILL FORCE RESCAN OF TASK LIST -
	JMP	MSEFWT	/GO WAIT ON MESSAGE EVENT FLAG
			/** DF MUST BE SET TO CALLER'S FIELD HERE **

SRCOMN, 0		/SUBROUTINE USED BY SEND AND RECEIVE
	CLL RAL 	/GET POINTER TO A TASK'S
	TAD	(MSGTBL /MESSAGE QUEUE POINTER
	DCA	MPTR
	CDF 0
	AC7776
	TAD I	(EXRET
	JMP I	SRCOMN
/RECEIVE A MESSAGE FROM THE TASK'S MESSAGE QUEUE

XRECEIV,TAD	TASKX
	JMS	SRCOMN	/GET THE MESSAGE QUEUE PTR FOR THIS TASK
	DCA	STOCDF	/SAVE CDF TO CALLING FIELD
	TAD	DCDF
RCVLP,	DCA	PRVCDF	/SAVE PREVIOUS Q ENTRIES' FIELD
	TAD I	MPTR	/GET MESSAGE QUEUE POINTER
	SNA		/IF ZERO, THERE ARE NO MESSAGES IN THE Q
	JMP I	(WAITM3 /SO HANG THE TASK
	DCA	CHNCDF
	CLA IAC
	TAD	MPTR
	DCA	MPT2	/GET POINTER TO SECOND WORD OF Q POINTER
	TAD I	MPT2
	DCA	RCVPTR
SWTFLG,
CHNCDF, HLT		/CDF TO FIELD OF Q ENTRY
	TAD	ACARG	/ACARG CONTAINS TASK DEDICATION (IF ANY)
	CIA
	SZA		/IS RECEIVER DEDICATED TO ANYONE?
	TAD I	RCVPTR	/YES - CHECK ORIGIN OF THIS MESSAGE
	ISZ	RCVPTR
	CLL RAL 	/HIGH-ORDER BIT (WAIT BIT) IRRELEVANT
	SNA CLA 	/CAN THIS MESSAGE BE RECEIVED?
	JMP	RCVOK	/YES - PASS IT ON
	TAD	RCVPTR	/NO - CHAIN TO NEXT MESSAGE IN Q
	DCA	MPTR
	TAD	CHNCDF
	JMP	RCVLP

RCVOK,	TAD I	RCVPTR	/GET FIRST WORD OF ENTRY
	DCA	T
	ISZ	RCVPTR
	TAD I	RCVPTR
PRVCDF, HLT		/SET FIELD OF PREVIOUS Q ENTRY
	DCA I	MPT2	/SET PREV Q ENTRIES' POINTER (BOTH WORDS)
	TAD	T	/TO THE CONTENTS OF THIS Q ENTRIES'
	DCA I	MPTR	/POINTER, REMOVING THIS ENTRY FROM THE Q
	CLA IAC 	/FORM A POINTER TO THE FIRST WORD OF
	TAD	RCVPTR	/INFORMATION IN THE REMOVED MESSAGE
MSGADR,
STOCDF, HLT
	DCA I	LOC20	/AND STORE IT IN THE FIRST ARGUMENT
	ISZ	LOC20
	TAD	CHNCDF	/RETURN WITH CDF TO MESSAGE IN AC
	JMP I	(EXRET
	PAGE
/WAIT FOR MESSAGE

WAITM3, AC7776
	TAD	LOC20
	DCA	LOC20	/MOVE PC BACK TO "JMS 20"
	STL		/SET LINK TO PRESERVE AC ACROSS "TSTOP"
	TAD	(MSGWT	/BLOCK TASK ON MESSAGE WAIT

/COME HERE WITH BLOCKING BITS IN AC.
/TASK AC WILL BE CLEARED IF LINK IS 0, PRESERVED IF LINK IS 1

TSWAIT, DCA	BLKMSK	/ENTER HERE WITH BLOCKING BITS IN AC

TSWATX, TAD	TASKX	/ENTER HERE WITH BLOCKING BITS IN "BLKMSK"
	TAD	(TFTABL /GET INDEX INTO JOB FLAGS TABLE.
	DCA	T
	TAD	BLKMSK	/GET BLOCKING BITS
	CDF 0
	DCA I	T	/NO NEED TO OR THEM IN - WORD WAS ZERO BEFORE.
	ION		/(IN CASE WE CAME FROM "WAITE" OR "WAITM")
	SNL		/SHOULD WE CLEAR TASK AC?

TSTOP,	DCA	ACARG	/ENTER HERE WITH TASK AC IN AC
	TAD	TASKX	/TO STOP THE CURRENT TASK BUT NOT BLOCK IT.
	CLL RTL 	/GET A POINTER INTO THE TASK'S STATE TABLE ENTRY
	TAD	(TSTABL-1
	DCA	XR
	CDF 0
	IFNZRO	HGHFLD	<
	TAD I	(EXRET
	CLL RAR
	RTR
	TAD I	(EXRET
	TAD	(-5023	/5023 = 6203 + (6203 SHIFTED RIGHT 3)
	>
	DCA I	XR	/STORE RETURN IF AND DF=IF
	TAD	LOC20
	DCA I	XR	/STORE RETURN PC
	TAD	ACARG
	DCA I	XR	/STORE RETURN AC
	IFNZRO	EAE	<
	MQA		/EVEN PRESERVE THE MQ OVER MONITOR CALLS
	DCA I	XR	/(WHAT THE HECK, ITS ONLY 2 INSTRUCTIONS)
	>
			/** FALL INTO NEXT PAGE **
/RTS-8 SCHEDULER - SCANS TASK FLAGS TABLE TO DETERMINE HIGHEST
/PRIORITY RUNNABLE TASK - RUNS WITH INTERRUPTS ON (SOMETIMES)
/AND IS STATELESS.

FINDJ,	CLA IAC 	/CODE TO FIND FIRST RUNNABLE TASK
	DCA	TASKX	/INITIALIZE TASK NUMBER
	DCA	SVSFLG	/THE MACHINE STATE IS NOW UNIMPORTANT
	CLA IAC 	/AND WE SHOULD RE-ENABLE TASK SWITCHING
	DCA	TSWFLG	/SO THAT IF A TASK BECOMES RUNNABLE
	TAD	(TFTABL /AFTER WE SCAN IT, IT WILL INTERRUPT
	DCA	XR	/THE SCAN LOOP AND RUN.
FINDJL, CIF 0		/AS WE SEARCH A TASK'S ENTRY IN THE LIST,
	IFZERO	HGHFLD	<IOF>
	TAD I	XR	/WE ASSUME THAT TASK'S PRIORITY
	SNA CLA 	/LOOK FOR FIRST TABLE ENTRY OF 0
	JMP I	(STARTJ /(THERE HAS TO BE ONE - NAMELY THE NULL TASK)
	IFZERO	HGHFLD	<ION>
	ISZ	TASKX	/BUMP THE TASK NUMBER (AND PRIORITY)
			/ALLOW INTERRUPTS FOR ONE CYCLE SINCE
	JMP	FINDJL	/"TASK" IS BIGGER THAN CURRENT REJECTED TASK
/SCHEDULE A TASK TO BE RUN

XRUN,	TAD	(RUNWT
	JMP	UNBLOK

XUNBARG,TAD I	LOC20		/UNBLOCKING CODE IN ARGUMENT
	ISZ	LOC20

UNBLOK, DCA	UNBMSK	/AC CONTAINS REASON FOR UNBLOCKING TASK "ACARG"
	TAD	ACARG
	IOF		/FREEJ IS AN INTERRUPT-LEVEL ROUTINE!
	JMS	FREEJ	/REMOVE THE GIVEN BLOCKING BIT
UNBMSK, 0
	ION
POSTEX, SNL CLA 	/SHOULD THE NEW TASK BE RUN NOW?
	JMP I	(EXRET	/NO
	JMP	TSTOP	/YES-PUT TASK TO SLEEP WITHOUT BLOCKING IT


/SUSPEND EXECUTION OF A TASK

XSUSPND,TAD	(RUNWT
	JMP	BLOK

XBLKARG,TAD I	LOC20	/BLOCKING CODE IN ARGUMENT
	ISZ	LOC20
BLOK,	DCA	BLKMSK	/SAVE BLOCKING CODE
	TAD	ACARG	/GET TASK TO BE BLOCKED
	SNA
	JMP	TSWATX	/0 MEANS CURRENT TASK!

/			NOTE THE LINK IS RANDOM HERE BUT SINCE ACARG=0
/			IT DOESN'T MATTER IF WE CLEAR IT OR NOT

	CDF 0
	TAD	(TFTABL
	DCA	T
	TAD	BLKMSK	/GET THE BLOCKING FLAG(S)
	CMA
	AND I	T
	TAD	BLKMSK	/OR THEM INTO THE TASK FLAG WORD
	DCA I	T
	JMP I	(EXRET	/THIS DOESN'T AFFECT US - JUST RETURN
/ROUTINE TO UNBLOCK A TASK'S EXECUTION
/ENTER WITH TASK# IN AC, INTERRUPTS OFF, UNBLOCKING BIT IN CALL+1

FREEJ,	0
	CDF 0
	TAD	(TFTABL
	DCA	INTT
	TAD I	FREEJ	/GET UNBLOCKING BIT
	ISZ	FREEJ	/BUMP RETURN POINTER
	CMA
	AND I	INTT
	DCA I	INTT	/REMOVE THE FLAG FROM THE TASK FLAG WORD
	TAD I	INTT
	SNA CLA 	/IF THE TASK IS NOW RUNNABLE
	TAD	TASKX	/AND HAS A HIGHER PRIORITY THAN THE CURRENTLY
	TAD	(TFTABL /RUNNING TASK, RETURN WITH THE LINK ON.
	CIA STL
	TAD	INTT
	CLA		/OTHERWISE RETURN WITH THE LINK OFF.
	JMP I	FREEJ
/WAIT FOR EVENT FLAG

XWAITE, TAD I	LOC20	/GET ADDRESS OF EVENT FLAG
	ISZ	LOC20
WAITS,	DCA	T	/ENTER HERE FROM SEND
	IFZERO	HGHFLD	<IOF>	/INHIBIT INTERRUPTS
	IFNZRO	HGHFLD	<CIF 0> /WHILE TESTING FLAG!
	TAD I	T	/EVENT FLAG IS IN SAME FIELD AS CALL
	SNA CLA 	/ZERO MEANS EVENT COMPLETED
	JMP I	(EXRET	/SO EXIT IMMEDIATELY
	IOF		/INTERRUPTS MUST BE OFF BETWEEN SETTING EF
			/AND SETTING EF WAIT!
	AC4000		/SET EVENT FLAG TO TASK NUMBER
	TAD	TASKX	/WITH HIGH-ORDER BIT ON TO INDICATE
	DCA I	T	/THAT TASK IS WAITING FOR EVENT COMPLETION
	TAD	(EFWT
	JMP	TSWAIT	/AND BLOCK CURRENT TASK ON EVENT WAIT
			/** NOTE LINK=0 SO ACARG WILL BE CLEARED **

/POST AN EVENT FLAG

XPOST,	TAD I	LOC20	/GET DATA FIELD OF EVENT FLAG
	ISZ	LOC20
	DCA	.+1
BLKMSK, HLT		/CDF TO IT
	AC4000
	TAD I	ACARG	/ADDRESS WAS IN AC AT CALL
	DCA	T
	DCA I	ACARG	/ZERO EVENT FLAG
	SNL		/WAS A TASK WAITING ON EVENT FLAG?
	JMP I	(EXRET	/NO - WE'RE DONE
	TAD	T	/YES - LOW ORDER BITS ARE TASK NUMBER
	DCA	ACARG
	TAD	(EFWT!EORMWT
	JMP	UNBLOK	/UNBLOCK THIS TASK FROM EVENT FLAG WAIT
	PAGE
/DUMMY TABLE ENTRIES (EACH TASK OVERLAYS ITS ENTRY WHEN IT LOADS):

MSGTBX, ZBLOCK	NTASKS 2
	0;0		/MESSAGES FOR NULL TASK
TSTABX, ZBLOCK	NTASKS 4
	0
	.+1		/FIELDS, PC, AC FOR NULL TASK
	DCA	SVSFLG	/NULL TASK RUNS STATELESS
	JMP	.

TFTABX, IFNZRO	NTASKS&40 <
	1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1>
	IFNZRO	NTASKS&20 <
	1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1>
	IFNZRO	NTASKS&10 <
	1;1;1;1;1;1;1;1>
	IFNZRO	NTASKS&4 <1;1;1;1>
	IFNZRO	NTASKS&2 <1;1>
	IFNZRO	NTASKS&1 <1>

	0		/NULL TASK ALWAYS RUNNABLE

	IFNZRO	TFTABX-TFTABL-1 <TBLERR,  ERROR  >

	$-$-$



Feel free to contact me, David Gesswein djg@pdp8online.com with any questions, comments on the web site, or if you have related equipment, documentation, software etc. you are willing to part with.  I am interested in anything PDP-8 related, computers, peripherals used with them, DEC or third party, or documentation. 

PDP-8 Home Page   PDP-8 Site Map   PDP-8 Site Search