Google
 

Trailing-Edge - PDP-10 Archives - BB-D351C-SM_3-16-83 - sources/xdispa.p11
There are 5 other files named xdispa.p11 in the archive. Click here to see a list.
	.SBTTL	XDISPA - task scheduler and dispatcher

; this section contains the dispatcher.  it distributes cpu
;  time among the tasks on a "non-preemptive" basis.
;  that is, a task must deliberately relinquish control by
;  calling "wait" before another task can get control.
;
; in addition, the once-per-clock-tick subroutines are called
;  from here, as are the once-per-second subroutines.
;
; if a task takes too much time, the clock tick interrupt will
;  issue a stopcode, so each task calls "wait" after only
;  a little processing.  

.REPT 0


                          COPYRIGHT (c) 1982,1981,1980, 1979
            DIGITAL EQUIPMENT CORPORATION, maynard, mass.

THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH  LICENSE AND WITH THE
INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR  ANY  OTHER
COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
TRANSFERRED.

THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE  WITHOUT  NOTICE
AND  SHOULD  NOT  BE  CONSTRUED  AS  A COMMITMENT BY DIGITAL EQUIPMENT
CORPORATION.

DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR  RELIABILITY  OF  ITS
SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.

.ENDR
;		REVISION HISTORY


; 4(001) BS	ADD VERSION NUMBER
;
; 4(002) RLS	MOVE LOOP CHECK FROM DSPIDL TO WAIT OTHERWISE IT REQUIRES
;		ALL TASKS TO BE SIMULTANEOUSLY IDLE AT LEAST ONCE PER SECOND!!

; 4(003) RLS 25-Feb-81	remove task timer checking from DSPIDL and make
;			 function TSKTIK - called from CLKINT.
;			Move calls to once/tick routines(DSPDQT,DSPDLT) from
;			 DSPIDL	to CLKINT - made necessary by task timer change
;			 above. Of course, it should have been this way anyhow.
;			make DSPUDC check if task waiting for timer whenever
;			TCTIM is zero.
; 4(004) RLS 05-OCT-81	Move call to DSPDLS from dspidl to CLKINT.

VDISPT=004

VEDIT=VEDIT+VDISPT
	.SBTTL		SKED - the moby hyber function

ISKD:				;schedule a task interrupt
				;2(SP)/interrupting task
;trace caller,interrupting task,previous interrupting task,current task
	TRACE	TRCINT!TRCDSP,<(SP),4(SP),SKDWRD,DSPTCB>
	CMP	2(SP),DSPTCB	;check if interrupting self
	BEQ	20$
	SAVE	R0
	MOV	4(SP),R0	;get the interrupting task tcb
	CMPB	TCPS(R0),SKDP	;compare priorities
	BLOS	15$
				;this one higher - schedule it
	MOV	R0,SKDWRD	;set reeskd flag
	MOV	TCPS(R0),SKDP
	BISB	#37,SKDP	;set up priority for comparing

15$:	RESTOR	R0		;let the previous one ride
20$:	MOV	(SP)+,(SP)	;clean up stack and exit
	RETURN

;all interrupts return through this function

	.ENABL	LSB
SKDCHK:	TST	SKDWRD		;check if scheduler pass required
	BNE	10$		;yes - go check interrupt level
5$:	RTI			;no - just depart

10$:	TSTB	2(SP)		;identify interrupted task by priority level
	BMI	5$		;must be an interrupt process(BR4=200)
	TST	DSPTCB		;not an interrupt process - check if task
	BNE	15$
	MOV	#SKDINI,(SP)	;no - just the scheduler
	MOV	#BR7,2(SP)	;shut off the interrupts long enough to init
	RTI			;force scheduler to restart

15$:				;yes - fall thru as though task volunteered
	TRACE	TRCLIN!TRCDSP,<R5,2(SP),SKDWRD,JIFCLK>
REESKD:
	MOV	2(SP),-(SP)	;move wake loc and ps down on stack
	MOV	2(SP),-(SP)
	CLR	4(SP)		;stash args as if task were gentlemenly
	CLR	6(SP)		;task is immediately runnable
	.DSABL	LSB

; SUBROUTINE TO WAIT UNTIL THE CONDITION SPECIFIED IN THE
;  TCB HAS BEEN SATISFIED.

;EMT traps to here
;	stack:	wake location
;		ps of caller
;		wakeup time limit
;		wake conditions - low byte

;interrupts are disabled

SKED:	CMP	R5,DSPTCB	;basic integrity check
	BEQ	10$
	STOPCD	BUG		;can't allow this

10$:	MOV	(SP)+,TCPC(R5)	;SAVE PROGRAM COUNTER
	MOV	(SP)+,TCPS(R5)	;save the task ps
	MOV	(SP)+,TCTIM(R5)	;set wakeup time limit
	BEQ	15$
	BISB	#EBTIME,(SP)	;set timer wakeup if non-zero time
15$:	MOVB	(SP)+,(R5)	;set wakeup events
	BICB	#EBTIME,TCEV(R5) ;task timer's always reset
	TRACE	TRCDSP,<R5,TCPC(R5),TCEW(R5)>	;trace hyber call and wakeup condtions
	KGSAVE	-(SP)		;save KG11 state
	SAVE	<R0,R1,R2,R3,R4>;save the task registers
	MOV	SP,TCSP(R5)	;SAVE STACK POINTER
				;task state preserved now

SKDINI:				;enter here to init scheduler
	CLR	DSPTCB		;NO LONGER RUNNING A TASK
	CLR	SKDWRD		;note scheduler pass not needed
	CLR	SKDP		;allow any tasks to interrupt
	MOV	#PDL,SP		;SWITCH TO DISPATCHER STACK
	CLR	-(SP)		;SET UP STACK AS THOUGH FROM AN INTERRUPT
	MOV	#DISPATCH,-(SP)	;SO WE CAN CLEAR THE "T" BIT
20$:	RTI			;DISMISS THE "INTERRUPT", I.E.,
				; BRANCH TO DISPATCHER

; THIS IS THE MAIN ENTRY POINT AND THE RECYCLE POINT.

DISPATCH:
	MOV	TCBP1,R5	;GET HIGHEST PRIORITY TASKS
	CALL	DISP
	MOV	TCBP2,R5	;GET MEDIUM PRIORITY TCBS
	CALL	DISP
	MOV	TCBP3,R5	;GET LOWEST PRIORITY TCBS
	CALL	DISP

	JSR	PC,DSPIDL	;DO IDLE TIME CODE
	BR	DISPATCH	; AND CHECK ALL TCBS AGAIN.
; SUBROUTINE TO TEST A TCB TO SEE IF THE TASK IS DISPATCHABLE.
;  IF THE TASK IS DISPATCHABLE WE DISPATCH TO IT, OTHERWISE
;  WE RETURN.
;
;	R5/ptr to a tcb

DISP:	TST	R5		;check for empty list

5$:	BNE	6$		;more to check
	RETURN

6$:	CLR	R0		;get the wakeup conditions
	BISB	TCWK(R5),R0
	BEQ	15$		;none => runnable
	MOVB	TCEV(R5),R1	;get signalled events
	COM	R1
	BIC	#177400,R1
	BIC	R1,R0		;flush those which haven't happened
	BNE	10$		;anything left have happened and cause wakeup
	MOV	TCHAIN(R5),R5	;check rest of tasks on this chain
	BR	5$

10$:	MTPS	#BR7		;shut off world long enough to check current events
	MOV	R0,TCWKEV(R5)	;task is runnable
	BICB	R0,TCEV(R5)	;these events are now ancient history
	BR	20$

;special case - do not mung task's last wake events in case he hasn't had a
; chance to check them yet!

15$:	MTPS	#BR7

20$:	MOV	R5,DSPTCB	; REMEMBER THE TCB
	MOV	TCPS(R5),SKDP
	BIS	#37,SKDP	;set task priority up for schedluer interrupts
	TRACE	TRCDSP,<R5,(R5),TCWKEV(R5)>;trace dispatch of task and reasons
	MOV	TCSP(R5),SP	;LOAD THE TASK'S STACK
	RESTOR	<R4,R3,R2,R1,R0>;restore task regs
	KGLOAD	(SP)+		;restore KG11 status
	MOV	TCPS(R5),-(SP)	; AT TASK'S PRIORITY LEVEL
	MOV	TCPC(R5),-(SP)	;CREATE A PSEUDO-INTERRUPT
	RTI			;GO RUN THE TASK.
; SUBROUTINE CALLED BY THE DISPATCHER WHEN ALL TASKS ARE WAITING.

DSPIDL:	CMP	DSPCLK,JIFCLK	;IS THE DISPATCHER CLOCK UP TO DATE?
	BEQ	17$		;NO - NUTHIN TODO

; HERE WHEN THE CLOCK HAS TICKED.

12$:	MOV	JIFCLK,R0	;catch up to real time
	SUB	DSPCLK,R0
	MOV	JIFCLK,DSPCLK
	ADD	R0,DSPSEC
	CMP	R0,BSYMAX	;track max busy time between idle loop
	BLE	13$
	MOV	R0,BSYMAX
13$:	CMP	DSPSEC,#JIFSEC	;REACHED ONE SECOND?
	BLT	17$		;NO.
	SUB	#JIFSEC,DSPSEC	;YES, CLEAR SECONDS COUNTER
	INC	DSPUPT		;INCREMENT UP TIME
	BNE	14$
	INC	DSPUPT+2	;ADD CARRY TO HIGH-ORDER WORD
14$:	CMP	DLGONE,#-6	;CHECK FOR TEN DOWN TOO LONG
	BGT	16$		;NOT 5 SECONDS, JUST UPDATE STATUS

; HERE ONCE A SECOND AFTER THE 10 HAS BEEN GONE FOR A WHILE.

	CALL	INITDL		;TRY TO INITIALIZE THE DL10

; HERE ONCE A SECOND ANYHOW

16$:
17$:	RETURN
; SUBROUTINE TO UPDATE THE CLOCKS IN A LIST OF TASKS

TSKTIK:				;update all task timers - called from CLKINT
	MOV	TCBP1,R5	;GET HIGH PRIORITY TASKS
	JSR	PC,DSPUDC	;UPDATE THEIR CLOCKS
	MOV	TCBP2,R5	;GET MEDIUM PRIORITY TASKS
	JSR	PC,DSPUDC	;UPDATE THEIR CLOCKS
	MOV	TCBP3,R5	;GET LOW PRIORITY TASKS
	CALL	DSPUDC

	MOV	#NLINES,R0	;check line timers
	MOV	#LINTBL,R1

10$:	MOV	(R1)+,R4	;get an lcb
	BEQ	15$		;not created
	TST	LB.ALR(R4)
	BEQ	15$		;alarm not enabled
	BIT	#LS.ENB,(R4)
	BEQ	14$		;line not enabled
	DEC	LB.ALR(R4)	;count down alarm
	BGT	15$		;not expired yet
14$:	CLR	LB.ALR(R4)	;set alarm expired
	MOV	LB.TC1(R4),R5	;get BSC task
	BEQ	15$		;none???
	SIGNAL	R5,EBALR	;signal alarm event

15$:	SOB	R0,10$
	RETURN

DSPUDC:				;update all timers on R5/list of tasks
	TST	R5		;ANY TASKS?
11$:	BNE	12$		;YES.
	RTS	PC		;NO, DONE WITH THIS LIST

12$:	TST	TCTIM(R5)	;HAS THIS TASK A TIMER?
	BEQ	14$		;NO.
	DEC	TCTIM(R5)	;YES, DECREMENT IT.
	BNE	13$		;BRANCH IF TIME NOT YET UP
14$:	BIT	#EBTIME,(R5)	;IS TASK WAITING FOR TIMER?
	BEQ	13$		;NO, IGNORE IT.
	SIGNAL	R5,EBTIME	;signal task timer expired
13$:	MOV	TCHAIN(R5),R5	;GET NEXT TCB
	BR	11$		; AND TEST IT.