.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 ;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, 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 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 ; 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 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