Google
 

Trailing-Edge - PDP-10 Archives - BB-J992D-SB_1984 - stgman.p11
There are 30 other files named stgman.p11 in the archive. Click here to see a list.
	.SBTTL	STGMAN - storage management

; this set of subroutines gets and frees chunks and messages.
;  also included in this section are subroutines to get
;  and free task control blocks.

.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	ADDED EDIT NUMBERS
; 4(002) RLS	MUNG GETSTG TO GET A SINGLE CHUNK ONLY
; 4(003) RLS	99&44/100% REWRITE OF STORAGE MGT. TO EFFECT SIMPLY LINKED
;		FREE CHUNK LIST. GETSTG AND FRESTG BECOME MERE SHADOWS OF
;		THEIR FORMER SELVES.  RCVSEC & RCVPRI CHANGED TO CALL GETCHK
;		INSTEAD OF RIPPING OFF THEIR OWN CHUNKS. NOBODY QUEUES CHUNKS
;		TO IDLE(THE NULL JOB) ANYMORE, THEY CALL FRECHK DIRECTLY INSTEAD.
; 4(004) RLS	MAKE GETTCB USE GETCHK INSTEAD OF GETSTG(SO THERE IS NO WAIT
;		ON ALLOCATION FAILURE. MAKE GETCHK ENTRY CHECK FOR LOW FREE
;		STORAGE AND RETURN IF TOO LOW; ADD RIPCHK ENTRY TO GET ANYTHING
;		AVAILABLE(FOR USE BY RCVPRI & RCVSEC).
; 4(005) 01-Apr-81 RLS	Make GETTCB use tail end of tcb for task stack.
; 4(006) 17-Apr-81 RLS	Transform static flow control to statci/line control
; 4(007) 26-APR-82 RLS	Flush TRCFLG CONDITIONAL
; 4(010) 28-JUN-82 RLS	GCO 4.2.1405 - don't hang xlate  tasks in GETSTG if 
;			aborting.

VSTGMN=010

VEDIT=VEDIT+VSTGMN
	.SBTTL		GETTCB,FRETCB - tcb storage fcns

; on return:
;
;	R0 = pointer to tcb.  caller must fill in initial
;	   address and put in a task list.
;
; on success, C is clear.  on failure, C is set.

GETTCB:	CALL	GETPRM			;get core for it
	BCS	12$			;not available
	CALL	CLRCHK			;cleen the chunk
	MOV	R0,TCSP(R0)		;initialize stack pointer
	ADD	#CHSIZE,TCSP(R0)	;point to end of tcb+2
	MOV	TCSP(R0),TCSPT(R0)	;record initial value for debugging
	CLC				;flag success
	RETURN

; here to give error return.

12$:	SEC				;flag error
	RETURN


; subroutine to free a tcb.  R0 points to the tcb.

FRETCB:	CALL	FREPRM			;free it
	RETURN
	.SBTTL		GETSTG - get some dynamic storage

; function	- grabs a chunk if available, will sleep awhile if not.
;
;	R5 points to the task control block
;
; on return:
;
;	R0 points to the storage, if it was available.
;
;	  C is set on failure, clear on success
;	NOTE: GETSTG will not fail for translate tasks - only for TENTSK and
;		BSC tasks.

GETSTG:	MOV	TCLCB(R5),R0		;get line block
	CMP	LB.TC1(R0),R5		;are we BSC task?
	BEQ	GETCHK			;yes - go directly to allocator
	CMP	TCDLDR,R5		;check for tentsk
	BEQ	GETCHK			;yes - same fate

10$:	CMP	LB.FRE(R0),#DRPOOL	;apply higher cutoff for xlate
	BLE	11$
	CMP	CHFREC,#DRPOOL		;apply absolute limit - new line enables
	BLE	11$			; cause transients where this applies
	CALL	GETCHK			;xlate task - try for a chunk
	BCC	20$			;all is ok

11$:	BIT	#TCIAB!TCOAB,TCFG2(R0)	;if aborting
	BEQ	12$
	SAVE	R4			;make sure the xlate task doesn't hang
	MOV	R0,R4
	CALL	GTLCHK			;things can get desperate otherwise
	RESTOR	R4
	RETURN

12$:	BIT	#TCSTG,TCFG1(R5)
	BNE	15$
	TRACE	TRCFLO,<(SP),R5,LB.FRE(R0),LB.RES(R0)>
	BIS	#TCSTG,TCFG1(R5)	;mark xlate suspended for storage
	CLR	TCGMC(R5)

15$:	DSCHED	,#10			;mark waiting for time to pass
	ADD	#10,TCGMC(R5)		;keep track of this for kicks
	BR	10$
20$:	BIT	#TCSTG,TCFG1(R5)
	BEQ	25$
	BIC	#TCSTG,TCFG1(R5)	;unmark it
	TRACE	TRCFLO,<(SP),R5,LB.FRE(R0),LB.RES(R0),TCGMC(R5)>

25$:	CLC
	RETURN
	.SBTTL		GETCHK,GETPRM,GTLCHK - primitives for ripping off a free chunk

;	R5/task tcb

; on return:

;	R0 points to the chunk obtained, or 0 if that chunk
;	  was not available.  C is set for failure and 
;	  cleared for success.

GETCHK:	MFPS	-(SP)			;save interrupt status
	MTPS	#BR7			;disable interrupts
	SAVE	R4
	MOV	TCLCB(R5),R4		;get the line block
	CMP	LB.FRE(R4),#DRPOOL	;keep some chunks/line in reserve
					; for high priority fcns

	BGT	GTLCH0			;gogetem
	TRACE	TRCFLO,<4(SP),R5,LB.FRE(R4),LB.RES(R4)>
	CMP	LB.TC1(R4),R5		;is this a high priority task?
	BEQ	GTLCH0			;yes - strip the free pool
	BR	RIPFAL			;send condolences

GETPRM:	MFPS	-(SP)			;save interrupt status
	MTPS	#BR7			;disable interrupts
	SAVE	R4
	CMP	CHFREC,#DRPOOL		;don't rape free pool while it's down
	BLE	RIPFAL
	CALL	GTLCH1			;snatch a chunk
	BCS	RIPFAL
	DEC	FRECNT			;remove from pool
	INC	PRMCNT
	BR	RIPSUC

GTLCHK:					;take anything not nailed down
					;R4/lcb
	MFPS	-(SP)			;save interrupt status
	MTPS	#BR7			;disable interrupts
	SAVE	R4

GTLCH0:	CALL	GTLCH1			;snatch a chunk
	BCS	RIPFAL			;nothing left anyhow - mysterious!
	DEC	LB.FRE(R4)		;count chunk out of line's pool
	INC	LB.USE(R4)		;count it in use

RIPSUC:					;come here to suc
	RESTOR	R4
	.IF	NE,CHOWNR
	SAVE R1
	MOV	R5,R1			;use the task as the owner
	CALL	CHOWNG
	RESTOR	R1
	.ENDC

	MTPS	(SP)+			;enable interrupts
	TRACE	TRCCNK,<(SP),R5,TCLCB(R5),R0> ;trace exit from "get a chunk"
	CLR	(R0)			;flush the chunk link
	CLR	CHLEN(R0)		;the chunk is hungry
	RETURN


RIPFAL:					;come here to fail
	RESTOR	R4
	MTPS	(SP)+			;enable interrupts
	TRACE	TRCCNK,<(SP),R5,TCLCB(R5),CHFREC> ;trace unsuccessful exit
	CLR	R0			; return null ptr
	SEC				; and set C to indicate failure
	RETURN				;give error return to caller

GTLCH1:					;come here to snatch a chunk
	MOV	CHFST,R0		;pointer to first chunk
	BEQ	15$			;empty
	MOV	(R0),CHFST		;link free list to cdr
	BEQ	20$			;check for last chunk
	DEC	CHFREC			;decrement count of free chunks
	CLC
	RETURN

15$:	SEC
	RETURN

20$:	MOV	#CHFST,CHTAIL		;free list empty - fix tail ptr
	CLR	CHFREC			; and guarantee count
	RETURN
	.SBTTL		FRECHK,FREPRM,FREMSG - generic functions to release chunks

;	R0 points to the chunk

FRECHK:	TST	R0			;check for null chunk
	BEQ	69$			;don't count these!
	CALL	RETCH			;return the chunk
	MOV	TCLCB(R5),R0		;do the accounting
	INC	LB.FRE(R0)		;1 more available
	DEC	LB.USE(R0)		;1 less in use
.IF NE,0				;this check cannot normally be done because all
					;the numbers change when lines are enabled/disabled
	MOV	LINSHR,-(SP)		;try to catch extra returns when they happen
	SUB	LB.FRE,(SP)
	SUB	LB.USE,(SP)+		;should be 0
	BNE	10$
	STOPCD	BUG
10$:
.ENDC ;.IF NE,0
	CLR	R0
69$:	RETURN

RETCH:					;trace caller,his caller or msg cdr,prev caller
	TRACE	TRCCNK,<(SP),4(SP),10(SP),14(SP),R5,TCLCB(R5),R0>
.IF NE,FT.CHK
	CMP	R0,CHLOW		;in chunk space?
	BLO	10$			;no
	CMP	R0,PHYLIM		;above end of core?
	BLO	11$			;no, all ok.
10$:	STOPCD	BAF			;yes, bad address in frechk

11$:
.ENDC ;.IF NE,FT.CHK

20$:	PIOFF				;disable interrupts
	CLR	(R0)			;make this chunk last
	MOV	R0,@CHTAIL
	MOV	R0,CHTAIL
	INC	CHFREC			;increment count of free chunks

	.IF	NE,CHOWNR
	CALL	CHOWNF			; mark chunk returned
	.ENDC

	CLR	R0			;chunk no longer available to caller
	PION				;restore interrupt level
69$:	RETURN

FREPRM:	TST	R0			;check for null chunk
	BEQ	69$			;don't count these!
	CALL	RETCH			;return a non-dynamic chunk
	INC	FRECNT			;make it available
	DEC	PRMCNT
69$:	RETURN


;FREMSG	- free a msg: linked list of chunks
;	R0/ptr to list

FREMSG:	TST	R0
	BEQ	20$
					;free a whole msg
10$:	MOV	(R0),-(SP)		;save cdr
	CALL	FRECHK			;free car
	MOV	(SP)+,R0		;get cdr
	BNE	10$			;free cdr of list
20$:	RETURN
	.SBTTL		FLOSHR - calculate line resources

FLOSHR:	SAVE	<R0,R1,R2,R3>		;recalculate chunk allocations  for lines
	MOV	#NLINES,R1		;1st count the enabled lines
	MOV	#LINTBL,R2
	CLR	R3

10$:	MOV	(R2)+,R0		;get an lcb
	BEQ	20$			;none there
	BIT	#LS.ENB,(R0)		;check if enabled
	BEQ	20$			;nope
	INC	R3			;yep - count it
20$:	SOB	R1,10$

	CLR	R0			;now divide the spoils
	TST	R3
	BEQ	30$			;nobody cares anyhow
	MOV	FRECNT,R1		;get the available free pool
.IF EQ,PDP11-34
	DIV	R3,R0			;generate quotient + reaminder
.IFF
	CALL	FLODIV			;generate quotient + reaminder
.ENDC	;.IF EQ,PDP11-34
					;ignore the remainder

30$:	MOV	R0,LINSHR		;this much per line

	TRACE	TRCTEN,<R0,FRECNT,R3>

	MOV	#NLINES,R1		;now adjust all line allocations
	MOV	#LINTBL,R2

40$:	MOV	(R2)+,R0		;get an lcb
	BEQ	50$			;none there
	BIT	#LS.ENB,(R0)		;check if enabled
	BEQ	50$			;nope
	MOV	LINSHR,R3		;get its allocation
	SUB	LB.USE(R0),R3		; reduced by amount its now using
	MOV	R3,LB.FRE(R0)		;stuff the new free count - may be negative
50$:	SOB	R1,40$

	RESTOR	<R3,R2,R1,R0>
	RETURN

.IF NE,PDP11-34

FLODIV:					;special divide for FLOSHR
	SAVE	R2
	SWAB	R3			;don't expect very large dividends
	MOV	#400,R2			;initial divisor
	BR	15$
10$:	ASR	R3
15$:	SUB	R3,R1
	BLT	20$
	ADD	R2,R0
	BR	15$
20$:	ADD	R3,R1
	ASR	R2
	BGT	10$
	RESTOR	R2
	RETURN
.ENDC	;.IF NE,PDP11-34
	.SBTTL		RCVCHK,RCVCLR,GETRBF - line driver receiver buffer mgt

RCVCHK:	MOV	LB.RBF(R4),R0		;snarf enough chunks up front to receive msg
	CALL	CNTMSG			;check how many are hanging around
	MOV	#XBSZ0,R1		;this is how many we need
	SUB	R0,R1			; and how many to get
	BLE	15$			;already have them

10$:	CALL	GTLCHK			;snatch another
	BCS	20$			;too bad
	MOV	LB.RBF(R4),(R0)		;make a list
	MOV	R0,LB.RBF(R4)
	SOB	R1,10$
15$:	CLC
	RETURN
20$:	CALL	RCVCLR			;unsnarf remaining chunks
	SEC
	RETURN

RCVCLR:	SAVE	<R0,R5>			; might be called from interrupt level with only R4 setup
	MOV	LB.TC1(R4),R5		;get bsc tcb
	MOV	LB.RBF(R4),R0		;return any unused chunks to free list
	CALL	FREMSG
	CLR	LB.RBF(R4)		;no more list
	RESTOR	<R5,R0>
	RETURN

GETRBF:	MOV	LB.RBF(R4),R0		;advance to next chunk to receive more message
	BEQ	10$			;no more - msg a trifle long
	MOV	(R0)+,LB.RBF(R4)	;delink it
	CLR	(R0)			;clear link and count
	CLR	-(R0)
	RETURN
10$:	SEC
	RETURN