Google
 

Trailing-Edge - PDP-10 Archives - BB-JF18A-BM - sources/rms/rmsbuf.b36
There are 6 other files named rmsbuf.b36 in the archive. Click here to see a list.
%TITLE 'B U F F E R   -- file buffer routines'
!<BLF/REQUIRE 'RMSBLF.REQ'>
MODULE buffer (IDENT = '2.0'
		) =
BEGIN
!
!	COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1984, 1986.
!	ALL RIGHTS RESERVED.
!
!	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 THAT IS NOT SUPPLIED BY DIGITAL.
!

!++
! FACILITY:	RMS
!
! ABSTRACT:
!
!	BUFFER contains all routines which process
!	file buffers within RMS-20.
!
! ENVIRONMENT:	Deep within RMS, interrupts deferred until JSYS return.
!
! AUTHOR: Ron Lusk , CREATION DATE: 15-Mar-83
!
! MODIFIED BY:
!
!	, : VERSION
! 01	-
!--

!
! TABLE OF CONTENTS
!
!
!	GETBUF	-- allocate a file buffer
!	PUTBUF	-- Deallocate a file buffer
!
!
! INCLUDE FILES:
!

REQUIRE 'rmsreq';

!
! MACROS:
!
!<BLF/MACRO>

MACRO
    !
    !	SETLRU (buffer) sets the buffer's Least Recently
    !	Used count to the current buffer access count.
    !	This count is incremented each time a buffer is
    !	allocated and is never decremented, thus giving
    !	a "timestamp" of sorts for determining age of
    !	a given buffer.
    !
    setlru (a) =
	a [0, wrd] = .bufacc %;

!
! EQUATED SYMBOLS:
!

GLOBAL BIND
    bufrv = 2^24 + 0^18 + 400;			! Current edit level

!
! OWN STORAGE:
!
!   None.
!
! EXTERNAL REFERENCES:
!
!   None.
!
%SBTTL 'GETBUF -- allocate a file buffer'

GLOBAL ROUTINE getbuf (fpage, bsize, contigflag, p_bpage, p_incore, p_bfdadr) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	GETBUF allocates a buffer for a specified number of
!	file pages beginning with the specified file page.
!	There are four cases which may occur (listed here in
!	decreasing priority):
!
!	1)  Specified file page is still mapped into our
!	    process;
!	2)  A buffer is available (use one with smallest LRU
!	    count, which is the least recently used, except
!	    that empty buffers will be used before the file
!	    pages in unused buffers are flushed);
!	3)  A buffer must be allocated from free storage;
!	4)  No buffer is available (give failure return).
!
!
! FORMAL PARAMETERS
!
!	FPAGE	    -   File page number
!	BSIZE	    -   Bucket/buffer size in pages
!	CONTIGFLAG  -	Buffers should be allocated
!			contiguously (see note below)
!	BPAGE	    -	Buffer page number (returned to
!			caller)
!	INCORE	    -	if page is in core (if false, caller
!			must map it) (returned to caller)
!	BFDADR	    -	adress of buffer descriptor (if 0,
!			then called by Free Storage Manager
!			(returned to caller)
!
! IMPLICIT INPUTS
!
!	?
!
! COMPLETION CODES:
!
!	TRUE	    -	Got buffer, (BPAGE, INCORE, and
!			BFDADR will be set)
!	FALSE	    -	could not get buffer, no free
!			storage
!
! SIDE EFFECTS:
!
!	?
!
! NOTES:
!
!	1)  If the page was not found in any of the core
!	    buffers, then INCORE will be false and it is
!	    then the caller's responsibility to map the file
!	    page into the buffer returned by this routine.
!
!	2)  If CONTIGFLAG is non-zero (not TRUE, just merely
!	    non-zero), then it means that if we don't find
!	    the page in our buffers, we should completely
!	    fill up our buffer pool by mapping all pages
!	    that will fit.  Currently, this facility is used
!	    only for Sequential/Relative files which use
!	    Read-ahead.
!--

    BEGIN

    BIND
	bpage = .p_bpage,
	incore = .p_incore,
	bfdadr = .p_bfdadr : REF BLOCK;

    EXTERNAL
	bfound,					! # buffers found in chain
	bfault,					! # buffers not found in chain
	bfcore;					! # buffers allocated

    						!   from free core

    LOCAL
	usecount,				! # Of users of this buffer
	bfdptr : REF BLOCK,
	lruptr : REF BLOCK,			! Ptr to LRU word for BFDPTR
	lrumin;

    TRACE ('GETBUF');

!+
!   Increment counter of calls to GETBUF
!   (this is used to fill in the LRU count
!   for a buffer).
!-

    bufacc = .bufacc + 1;			! Incr count of buffer accesses

%IF dbug
%THEN
    !
    !   Check our input
    !

    IF .contigflag AND idxfile THEN rmsbug (msgflags);

%FI

!+
!   Search for a buffer to return to caller
!-

    bfdadr = 0;					! Reset ptr to available buffer
    lrumin = plusinfinity;			! Preset smallest LRU

    INCR j FROM bfdoffset			!
	TO bfdoffset + .rst [rstbfdcount] - 1	!
	BY 1					!
	DO
	BEGIN
	bfdptr = .j;				! Setup ptr to this
						!   buffer descriptor
	lruptr = .j + .rst [rstbfdcount];	! Point at its LRU word

!+
!   1.	Check if the specified file
!	page is in this buffer.
!-

	IF .bfdptr [bfdfpage] EQL .fpage	!
	    AND .bfdptr [bfdbktsiz] NEQ 0	!
	THEN
	    BEGIN				! Return file page
	    					!   already in core
	    setlru (lruptr);			! Set LRU count
	    bfdptr [bfdusecount] = .bfdptr [bfdusecount] + 1;	! Incr users
	    bpage = .bfdptr [bfdbpage];		! Return buffer page no.
	    incore = true;			! Return "file page is in core"
	    bfdadr = .bfdptr;			! Pointer to buffer descriptor
	    bfound = .bfound + 1;		! Bump count of found buffs
	    RETURN true;			! Give good return to caller
	    END;

!+
!   2. Check if this buffer is empty or
!      available with has smaller LRU count.
!-

	IF .bfdptr [bfdbktsiz] EQL 0 OR 	!
	    (.bfdptr [bfdusecount] EQL 0 AND 	!
	    .lruptr [0, wrd] LSS .lrumin)	!
	THEN
	    BEGIN				! Save pointer to LRU buffer
	    bfdadr = .bfdptr;			! Tentatively set LRU buffer

	    IF .bfdptr [bfdbktsiz] EQL 0 THEN EXITLOOP;	! Use 1st empty buffer

	    lrumin = .lruptr [0, wrd]		! Reset lowest LRU seen
	    END

	END;					! Search iteration

!+
!   If contiguous allocation is needed,
!   assume we found the first buffer.
!-

    IF .contigflag NEQ false			!
    THEN
	bfdadr = bfdoffset;

!+
!   Check if we found a buffer to use (empty or LRU)
!-

    IF (.bfdadr NEQ 0)
    THEN
	BEGIN					! Return this buffer to caller
	usecount = 1;				! this buffer is busy
	bfdptr = .bfdadr;			! Set up moving pointer
	bpage = .bfdptr [bfdbpage];		! Return buffer page
						!   number to caller
	incore = false;				! Return "page must be
						!   mapped from file" to caller
	bfault = .bfault + 1;			! Bump # of faults

!+
!   Do this loop once for each buffer if
!   contiguous allocation, only once otherwise.
!-

	INCR j FROM 1 TO .rst [rstbfdcount] DO
	    BEGIN
	    lruptr = .bfdptr + .rst [rstbfdcount];	! Point at chosen LRU

	    IF bfdupd (bfdptr)			! Do old contents
						!   need putting out?
	    THEN
		pagout (.fst [fstjfn], 		! JFN
		    .bfdptr [bfdfpage], 	! File page number
		    .bfdptr [bfdbpage], 	! Page number of buffer
		    .bfdptr [bfdbktsiz]);	! Number of pages to write

	    clearbfdupd (bfdptr);		! Reset flag
	    setlru (lruptr);			! Set LRU count for buffer
	    bfdptr [bfdusecount] = .usecount;	! Set initial use count
	    					!   for buffer
	    bfdptr [bfdfpage] = .fpage;		! Set file page number
	    					!   that is in buffer
	    bfdptr [bfdbktsiz] = .bsize;	! For demand flush
	    					!   in later GETBUF

%IF dbug
%THEN
	    begindebug (dbio);
	    printvalue ('	PAGE FAULT FOR PAGE:  ', fpage);
	    enddebug;
%FI

!+
!   We can exit in the normal case.
!-

	    IF .contigflag EQL false THEN RETURN true;

	    bfdptr = .bfdptr + 1;		! Bump pointer
	    lruptr = .lruptr + 1;		! Bump pointer
	    fpage = .fpage + .bsize;		! And page number
	    usecount = 0			! Other buffers are free
	    END;

!+
!   We have set up all buffer descriptors
!   for contiguous allocation.
!-

	RETURN true
	END;

!+
!   Didn't find buffer. ask free storage manager for buffer.
!-

    IF (bpage = gpage (.bsize			! Page count
	)) NEQ false
    THEN
	BEGIN					! Got buffer from FSM
	incore = false;				! Return "Page Must
						!   Be Mapped" to caller
	bfcore = .bfcore + 1;			! Bump count of free core buffs
	RETURN true				! Successful return
	END
    ELSE
	returnstatus (er$dme)			! Return "Can't get buffer"
    END;					! End of GETBUF
%SBTTL 'PUTBUF -- Deallocate a file buffer'

GLOBAL ROUTINE putbuf (bsize, bpage, incore, bfdadr : REF BLOCK) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	PUTBUF deallocates a buffer.  If the buffer was
!	allocated from free storage, then the Free Storage
!	Manager is called to release the pages composing the
!	buffer.  Otherwise, the buffer is "returned" to the
!	buffer pool (note that if there is more than one
!	user of the buffer then the buffer becomes free only
!	after the last user calls this routine.
!
! FORMAL PARAMETERS
!
!	BSIZE	    -	bucket/buffer size in pages
!	BPAGE	    -	buffer page number
!	INCORE	    -	if page is in core (if FALSE, it was
!			pmapped to file; FALSE also means
!			that the buffer is now empty)
!	BFDADR	    -	address of buffer descriptor
!
! IMPLICIT INPUTS
!
!	NONE.
!
! COMPLETION CODES:
!
!	TRUE	    -	always.
!
! SIDE EFFECTS:
!
!	?
!
! NOTES:
!	1)  If the address of the buffer descriptor (BFDADR)
!	    in the bucket descriptor is null, this indicates
!	    that the buffer was not allocated from the
!	    buffer pool in the Record Status Table.
!	    Instead, it was allocated from the Free Storage
!	    Manager because all other buffers were already
!	    in use (this situation should not happen
!	    currently since a minimum of 3 buffers is
!	    allocated when a record stream is initiated).
!--

    BEGIN
    TRACE ('PUTBUF');

!+
!   If buffer came from free storage, return it to the FSM.
!-

    IF (.bfdadr EQL 0)
    THEN 					! Return buffer to FSM
	BEGIN
	ppage (.bpage, 				! Page number
	    .bsize, 				! Count
	    true);				! Kill Flag
	RETURN true
	END;

!+
!   Decrement use count for buffer.
!-

    BEGIN

    REGISTER
	tempac;

    tempac = .bfdadr [bfdusecount];

    IF .tempac EQL 0 THEN rmsbug (msgbna);

    bfdadr [bfdusecount] = .tempac - 1;		! Decrement use count
    END;

!+
!   If buffer is now empty, and if there are
!   no more users of the buffer, then make the
!   Buffer Descriptor indicate that condition.
!-

    IF (.incore EQL false)			!
	AND (.bfdadr [bfdusecount] EQL 0)	!
    THEN
	bfdadr [bfdbktsiz] = 0;			! Indicate no data in buffer

    RETURN true;				! Give "good" return to caller
    END;					! End of PUTBUF

END						! End of Module BUFFER

ELUDOM