Trailing-Edge
-
PDP-10 Archives
-
CFS_TSU04_19910205_1of1
-
update/ietsrc/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) 1977,1978,1979,1980,1981,1982,1983,1984,1985,1986
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.
; 4(011) 10-AUG-84 TPW In GETSTG bit test for abort should be in task
; control block not line control block
;
VSTGMN=011
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(R5) ;[011]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