Google
 

Trailing-Edge - PDP-10 Archives - bb-h138f-bm - 7-sources/rmsfsm.b36
There are 6 other files named rmsfsm.b36 in the archive. Click here to see a list.
%TITLE 'F S M   -- Free Storage Manager'
!<BLF/REQUIRE 'RMSBLF.REQ'>
MODULE fsm (IDENT = '2.0'
		) =
BEGIN

GLOBAL BIND
    fsmv = 2^24 + 0^18 + 451;			! Edit date: 18-Jan-84

!+
!
!    FUNCTION:	THIS MODULE CONTAINS ALL ROUTINES AND STRUCTURES
!    WHICH PROCESS AND DESCRIBE THE RMS-20 FREE STORAGE
!    MANAGER (FSM). CURRENTLY, ALL FREE STORAGE IS
!    MANAGED BY RMS-20 ITSELF. THE AMOUNT OF FREE STORAGE
!    IS A SYSTEM-BUILD PARAMETER AND CANNOT BE CHANGED ONCE
!    RMS-20 IS LOADED AND INITIALIZED.
!
!
!
!	COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1977, 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.
!
!
!
!    AUTHOR:	S. BLOUNT
!
!    **********	TABLE OF CONTENTS	***********
!
!    ROUTINE		FUNCTION
!    =======		========
!
!    GPAGE		ALLOCATE A FREE PAGE
!
!    PPAGE		RELEASE A FREE PAGE
!
!    GMEM		ALLOCATE A BLOCK OF FREE MEMORY
!
!    PMEM		RELEASE A BLOCK OF FREE MEMORY
!
!
!
!
!    REVISION HISTORY:
!
!    EDIT	DATE		WHO		PURPOSE
!    ====	====		===		=========
!
!    1	OCT-18-76	SB		FIX SYNTAX BUG IN GPAGE FOR MULTIPLE PAGES
!
!    *************************************************
!    *						*
!    *		NEW REVISION HISTORY		*
!    *						*
!    *************************************************
!
!    PRODUCT	MODULE	 SPR
!    EDIT	 EDIT	 QAR		DESCRIPTION
!    ======	======	=====		===========
!
!    14	2	11723		THE PAGE LINK CONSISTENCY CHECK IN GMEM
!    IS INCORRECT, SUCH THAT ONCE CORE
!    BECOMES FRAGMENTED, IT WILL ALWAYS FAIL.
!
!    ** V2 development **
!
!
!
!    400	400	DEVEL	    FIX UP CALLS, STRIP MACROS, FIX STRUCTURE
!				    REFERENCES (RL)
!
!    451	-	DEVEL	    (RL,18-Jan-84) Remove code which makes
!				    calls to FUNCT. if RMS is loaded below
!				    600000.
!
!    ***** END OF REVISION HISTORY *****
!
!
!
!
!
!-

REQUIRE 'RMSREQ';

!+
!
!    ***********************************************************************
!    *			FREE-CORE MANAGER STRUCTURES		      *
!    ***********************************************************************
!
!-
!+
!    THERE ARE TWO PRIMARY DATA STRUCTURES USED BY THE FSM
!    TO MANAGE FREE STORAGE---THE PAGE TABLE, AND THE FREE
!    CORE CHUNKS THEMSELVES.
!
!    THE PAGE TABLE IS BUILT AT RMS COMPILE-TIME AND IS CONTAINED
!    WITHIN THE MODULE "RMSGLB". IT HAS ONE WORD FOR EACH PAGE
!    WHICH IS ALLOCATED TO THE FSM. THE FORMAT OF EACH WORD IN THE
!    PAGE TABLE IS AS FOLLOWS:
!
!    FORMAT OF PAGE TABLE ENTRY
!
!    !=====================================!
!    !*!     BIGHOL     !    FIRSTFREE     !
!    !=====================================!
!
!    * = BUSY BIT:
!    0==>PAGE IS AVAILABLE FOR ALLOCATION
!    1==>PAGE WAS ALLOCATED BY GPAGE...IT IS BUSY
!
!
!
!
!    FREE CORE CHUNKS ARE FORMATTED SUCH THAT EACH CHUNK CONTAINS
!    A HEADER WHICH DESCRIBES THE SIZE OF THE CHUNK, AND THE ADDRESS
!    OF THE NEXT FREE CHUNK IN THE PAGE. THE HEADER IS ALWAYS AT THE
!    BOTTOM OF THE CHUNK (I.E., AT THE HIGHER MEMORY ADDRESS).
!    THE FORMAT OF A CHUNK HEADER IS AS FOLLOWS:
!
!    FORMAT OF CORE CHUNK HEADER
!
!    !=====================================!
!    !     HOLESIZE     !     FREEPTR      !
!    !=====================================!
!
!
!
!-

!+
!    STRUCTURE OF EACH ENTRY IN THE PAGE TABLE
!-

MACRO
    fcmbusy =
 35,1, 0 %,					! BIT 0 MEANS PAGE NOT FREE
    bighol =
 18,10, 0 %,					! LARGEST HOLE ON PAGE
    firstfree =
 0,18, 0 %;					! FIRST FREE CHUNK ON PAGE

!+
!    STRUCTURE OF EACH CHUNK HEADER ON A FREE PAGE
!-

MACRO
    holesize =
 0,lh%,						! SIZE OF THIS HOLE
    freeptr =
 0,rh %;					! ADDRESS OF NEXT HOLE
%SBTTL 'GPAGE -- allocate pages'

GLOBAL ROUTINE gpage (pages) = 			! GPAGE
! =====
! THIS ROUTINE ALLOCATES CONSECUTIVE PAGES FROM THE POOL OF FREE CORE.
! NO CHOICE OF A SPECIFIC PAGE IS ALLOWED.
!
! INPUT:
!	# OF CONTIGUOUS PAGES TO ALLOCATE
! OUTPUT:
!	PAGE # OF 1ST PAGE IN GROUP
!	RETURN FALSE IF NONE AVAILABLE
    BEGIN

    REGISTER
	pagenum,
	pagecount;

    TRACE ('GPAGE');
    checkinput (pages, GTR, 0);			! PAGES MUST BE POSITIVE

%IF 0 						! Delete FUNCT. code	!A451
%THEN						! ...			!A451
    !+
    !    CODE TO UTILIZE OTS'S MEMORY MANAGER. TEMPORARY SOLUTION.
    !    THE ROUTINES THAT CALL ON LIBOL'S MEMORY MANAGER ARE IN A
    !    SEPERATE MODULE CALLED RMSOTS.MAC. THE ROUTINES IN THIS
    !    MODULE ARE APPROPRIATELY NAMED    FGPAGE, FGMEM AND FPMEM
    !-

    IF (rms$$g LSS %O'643000')
    THEN
	BEGIN
	%(WE ARE PROBABLY LOADED BELOW 600000 FOR COBOL V12B)%

	IF (pagenum = fgpage (.pages^p2w)) EQL false
	THEN
	    RETURN false
	ELSE
	    BEGIN
	    RETURN .pagenum
	    END

	END;

    !+
    !    END OF CODE TO UTILIZE OTS'S MEMORY MANAGER
    !-
%FI						! End code deletion	!A451

    pagenum = 0;				! START AT FIRST PAGE

    !+
    !    LOOP OVER ALL PAGES IN THE PAGE TABLE
    !-

    WHILE (.pagenum LEQ .numfreepages - .pages)	! UNTIL LAST PAGE
    DO
	BEGIN
	%( CHECK IF BLOCK BEGINS HERE )%pagecount = 0;	! CHECK FOR EACH PAGE OF BLOCK

	WHILE (.pagtab [.pagenum, fcmbusy] EQL 0) DO
	    BEGIN
	    %( THIS PAGE IS FREE. CHECK FOR REST OF BLOCK )%

	    IF (.pagecount + 1 GEQ .pages)
	    THEN
		BEGIN
		%( SET BUSY FOR ALL PAGES IN BLOCK )%

		DECR pagecount FROM .pagenum TO .pagenum - .pages + 1 BY 1 DO
		    BEGIN
		    %( SET BUSY )%pagtab [.pagecount, wrd] = 0;
		    pagtab [.pagecount, fcmbusy] = 1
		    END;%( OF SET BUSY )%

		crepage (.pagenum - .pages + 1 + .frecor, .pages);
		RETURN (.pagenum - .pages + 1 + .frecor)
		END;%( OF SET BUSY FOR ALL PAGES OF BLOCK )%

	    pagenum = .pagenum + 1;		! INCR PAGTAB INDEX
	    pagecount = .pagecount + 1		! COUNT NO. PAGES WE FOUND
	    END;%( OF THIS PAGE IS FREE )%

	pagenum = .pagenum + 1
	END;%( OF CHECK IF BLOCK BEGINS HERE )%

    RETURN false				! NO ROOM, GIVE FAILURE RETURN
    END;

%( OF GPAGE)%
%SBTTL 'PPAGE - return pages to free core'

GLOBAL ROUTINE ppage (pagenum, pages, killflag) =
! PPAGE
! =====
! THIS ROUTINE RETURNS CONSECUTIVE FULL PAGES TO FREE CORE
! THE PAGES MUST HAVE BEEN ALLOCATED BY GPAGE
! INPUT:
!	PAGE # OF 1ST PAGE
!	# OF PAGES TO RETURN
!	DESTROY-FLAG ( TRUE MEANS DESTROY THIS PROCESS PAGE )
! OUTPUT:
!	<NONE>
    BEGIN

    LOCAL
	pageindex;

    TRACE ('PPAGE');
    checkinput (pages, GTR, 0);			! MUST BE POSITIVE NO. PAGES

%IF 0 						! Delete FUNCT. code	!A451
%THEN						! ...			!A451
    !+
    !    Code to utilize OTS's memory manager.
    !-

    IF (rms$$g LSS %O'643000')
    THEN
	BEGIN
	%( WE ARE LOADED BELOW 600000 )%

	IF fpmem (.pagenum^p2w, .pages^p2w) THEN RETURN true ELSE rmsbug (msginput);

	END;

    !+
    !    End of code to utilize OTS's memory manager
    !-
%FI						! End code deletion	!A451

    !+
    !    LOOP THRU ALL PAGES IN THE CHUNK WHICH IS BEING RETURNED
    !-

    INCR pageindex FROM .pagenum - .frecor TO .pagenum - .frecor + .pages - 1 BY 1 DO
	BEGIN
	%( REMOVE THIS PAGE )%

	IF (.pagtab [.pageindex, fcmbusy] EQL 0) THEN rmsbug (msgpna);	! ** PAGE NOT AVAILABLE **

	pagtab [.pageindex, wrd] = 0;

	!+
	!    SHOULD WE DESTROY THIS PAGE?
	!-

	IF (.killflag) THEN killpage (.pageindex + .frecor, 1);

	END;%( OF REMOVE THIS PAGE )%

    RETURN true
    END;

%( OF PPAGE)%
%SBTTL 'GMEM - allocate core'

GLOBAL ROUTINE gmem (size) =
! GMEM
! ====
! THIS ROUTINE ALLOCATES CORE FROM THE FREE POOL IN
! VARIABLE-SIZED CHUNKS. EACH REQUEST MUST
! BE FOR LESS THAN 1 PAGE. IF MORE THAN
! ONE PAGE IS REQUIRED, THE CALLER MUST
! COMPUTE HIS NEEDS ALL CALL GPAGE FOR THE
! REQUIRED PAGES.
! INPUT:
!	SIZE OF REQUEST.
! OUTPUT:
!	ADDRESS OF 1ST WORD
    BEGIN

    REGISTER
	bltac;					! TEMPORARY REGISTER

    LOCAL
	ahole,
	pagefull,
	bhole,
	answer,
	pagenum,
	pageadr,
	freepage;

    MAP
	ahole : REF BLOCK,
	bhole : REF BLOCK,
	answer : REF BLOCK;

    MAP
	pageadr : REF BLOCK;

    TRACE ('GMEM');

    IF (.size GTR pagesize) OR (.size LEQ 0) THEN rmsbug (msginput);	! BAD CORE REQUEST

    pagenum = 0;				! POINTER TO PAGTAB

%IF 0 						! Delete FUNCT. code	!A451
%THEN						! ...			!A451
    !+
    !    CODE TO UTILIZE OTS'S MEMORY MANAGER INSTEAD OF THIS.
    !-

    IF (rms$$g LSS %O'643000')
    THEN
	BEGIN
	%(WE ARE LOADED BELOW 600000 FOR LIBOL)%

	IF (answer = fgmem (.size)) EQL false THEN rmsbug (msgcore) ELSE RETURN .answer

	END;

    !+
    !    END OF CODE TO UTILIZE OTS'S MEMORY MANAGER
    !-
%FI						! End code deletion	!A451

    !+
    !    LOOK AT THE INPUT ARGUMENTS
    !-

    lookat ('	CHUNK REQUESTED: ', size);

    !+
    !    LOOP OVER ALL CHUNKS
    !-

    WHILE (.pagtab [.pagenum, bighol] LSS .size) AND 	!
	(.pagenum LEQ .numfreepages) DO
	pagenum = .pagenum + 1;			! Bump pointer

    !+
    !    DID WE FIND A CHUNK? IF NOT, WE MUST ALLOCATE A NEW PAGE
    !-

    IF .pagenum GTR .numfreepages
    THEN 					! NO HOLES FOUND
	BEGIN

	IF (pagenum = gpage (1)) EQL false THEN RETURN false;	! GET A FREE PAGE

	pageadr = (.pagenum^p2w) + ofsetmask;	! GET LAST WORD IN PAGE
	pagenum = .pagenum - .frecor;		! FIND OFFSET
	pagtab [.pagenum, bighol] = pagesize;	! SET FREE SIZE
	pagtab [.pagenum, firstfree] = .pageadr;
	pageadr [holesize] = pagesize;		! HOLE IS 512 LONG
	pageadr [freeptr] = 0			! NO NEXT HOLE
	END;%( "PAGENUM" NOW CONTAINS THE PAGTAB INDEX OF THE

1ST PAGE WE FOUND WITH BIGHOL > SIZE )%
    freepage = .pagenum + .frecor;		! FIND PAGE #
    ahole = .pagtab [.pagenum, firstfree];	! SET 1ST HOLE
    bhole = 0;

    WHILE .ahole [holesize] LSS .size DO
	BEGIN

	IF (.ahole [freeptr]^w2p NEQ .freepage) OR
!** [14] ROUTINE:GMEM, AT LINE 4478, EGM, 6-JUL-78
	    ((.ahole - .ahole [holesize] + 1)/512 NEQ .freepage)
	THEN
	    rmsbug (msglink);			! PAGE LINKS SCREWED UP

	IF .ahole [freeptr] EQL 0 THEN rmsbug (msgcore);	! CANT GET CORE

	bhole = .ahole;
	ahole = .ahole [freeptr]		! ADVANCE TO NEXT HOLE
	END;

    pagefull = false;
    answer = .ahole - .ahole [holesize] + 1;	!ADDR OF HOLE
    lookat ('	CHUNK ALLOCATED: ', answer);

    !+
    !    IS IT AN EXACT MATCH?
    !-

    IF .ahole [holesize] EQL .size
    THEN 					! EXACT MATCH
	BEGIN

	IF .bhole EQL 0
	THEN 					! 1ST HOLE IN PAGE...
	    BEGIN
	    pagtab [.pagenum, firstfree] = .ahole [freeptr];

	    IF .ahole [freeptr] EQL 0
	    THEN 				! THE PAGE IS COMPLETELY FULL
		pagefull = true

	    END
	ELSE
	    bhole [freeptr] = .ahole [freeptr];	! RESET POINTER TO NEXT HOLE

	END
    ELSE
    %( IF AHOLE [ HOLESIZE ] GTR SIZE )%
	BEGIN
	ahole [holesize] = .ahole [holesize] - .size	! NEW SIZE
	END;%( OF IF AHOLE [ HOLESIZE ] GTR .SIZE )%%(

     WE HAVE NOW SET UP THE ANSWER AND WE'RE READY TO RESET BIGHOL )%

    IF .pagefull %( IS TRUE )%
    THEN
	pagtab [.pagenum, bighol] = 0		! CLEAR BIGHOL
    ELSE
	BEGIN
	ahole = .pagtab [.pagenum, firstfree];	! START AT BEGINNING OF LIST
	bhole = .ahole [holesize];		! BHOLE = LARGEST SIZE FOUND SO FAR

	UNTIL .ahole EQL 0 DO
	    BEGIN

	    IF .ahole [holesize] GTR .bhole THEN bhole = .ahole [holesize];

						! RESET BHOLE IS WE FOUND A BIGGER HOLE
	    ahole = .ahole [freeptr]
	    END;

	pagtab [.pagenum, bighol] = .bhole	! RESET IT
	END;

    !+
    !    WE MUST NOW CLEAR THE CONTENTS OF THIS CORE BLOCK
    !-

    clear (.answer, .size);%( ONE LAST CHECK )%

    IF .answer^w2p NEQ (.pagenum + .frecor) THEN rmsbug (msgbstatus);	! ANSWER ISNT RIGHT

    RETURN .answer
    END;
%SBTTL 'PMEM - deallocate storage'

GLOBAL ROUTINE pmem (size, p_chunk2) =
! PMEM
! ====
! THIS ROUTINE DEALLOCATES STORAGE ON A PAGE. THE
! PAGE DIDN'T HAVE TO BE ALLOCATED BY GMEM,
! BUT IT MUST NOT CURRENTLY BE AVAILABLE.
! INPUT:
!	ADDRESS OF CHUNK
!	# OF CONTIGUOUS WORDS ( MUST NOT SPAN PAGE )
    BEGIN

    BIND
	chunk2 = .p_chunk2;

    LOCAL
	pagenum,
	apage,
	ahole,
	chunk,
	bhole;

    MAP
	chunk : REF BLOCK,
	ahole : REF BLOCK;

    TRACE ('PMEM');
    chunk = .chunk2;				! GET ADDRESS OF CORE

%IF 0 						! Delete FUNCT. code	!A451
%THEN						! ...			!A451
    !+
    !    code to utilize OTS's memory manager.
    !    Calls on the module RMSOTS.MAC
    !-

    IF (rms$$g LSS %O'643000')
    THEN
	BEGIN
	%(RMS IS LOADED BELOW 600000 FOR COBOL V12B)%

	IF fpmem (.chunk, .size) THEN RETURN true ELSE rmsbug (msginput)

	END;

    !+
    !    End of code to utilize OTS's memory manager
    !-
%FI						! End code deletion	!A451

    !+
    !    CHECK OUT OUR ARGS
    !-

    lookat ('	CHUNK RETURNED: ', chunk);
    lookat ('	CHUNK SIZE: ', size);
    apage = .chunk^w2p;				! GET PAGE #
    pagenum = .apage - .frecor;			! AND OFFSET

    IF (.pagenum LSS 0) OR (.pagenum GTR .numfreepages) OR (.size GTR pagesize) OR (.size LEQ 0)
    THEN
	rmsbug (msginput);

    IF (.chunk + .size - 1) GTR (.chunk OR %O'777') THEN rmsbug (msgbsp);	! CORE BLOCK SPANS PAGES

    IF .pagtab [.pagenum, fcmbusy] EQL 0 THEN rmsbug (msgpna);	! PAGE NOT ALLOCATED

!+
!    CLEAR THE HEADER WORD OF EACH CHUNK SO IT WONT BE ACCIDENTLY
!    TAKEN TO BE A VALID CONTROL BLOCK
!-
    chunk [wholeword] = 0;
    chunk = .chunk + .size - 1;			! COMPUTE LAST WORD OF HOLE

    !+
    !    CHECK TO SEE IF THE PAGE IS FULL OF ALLOCATED HOLES
    !-

    IF (ahole = .pagtab [.pagenum, firstfree]) EQL 0	! IF PAGE IS FULL
    THEN
	BEGIN

	IF .pagtab [.pagenum, bighol] NEQ 0 THEN rmsbug (msgpm2);	! BIGHOL NON-ZERO

	chunk [holesize] = .size;		! SET CHUNK SIZE
	chunk [freeptr] = 0;			! END OF CHAIN
	pagtab [.pagenum, firstfree] = .chunk;
	END
    ELSE
	BEGIN
	%( IF PAGE ISNT FULL )%

	!+
	!    IS THIS CHUNK LOWER ON THE PAGE THAN THE FIRST HOLE?
	!-

	IF .ahole LSS .chunk
	THEN
	    BEGIN
	    %( IF NEW CHUNK IS LOWER ON PAGE THEN 1ST HOLE)%chunk [holesize] = .size;	! SET SIZE
	    chunk [freeptr] = .ahole;		! RESET PTR
	    pagtab [.pagenum, firstfree] = .chunk
	    END
	ELSE
	    BEGIN
	    %( IF WE MUST SEARCH FREE-LIST )%

	    !+
	    !    LOOP OVER ALL CHUNKS UNTIL WE FIND IT
	    !-

	    WHILE .ahole [freeptr] GTR .chunk	! UNTIL WE COME TO OUR CHUNK...
	    DO
		BEGIN

		IF .ahole [freeptr] EQL 0
		THEN 				! CHECK FOR INCONSISTENCIES
		    rmsbug (msgpm3);		! BAD VALUE

		IF .ahole [freeptr] LSS ((.apage^9)) THEN rmsbug (msglink);	! LINK INCONSISTENCY

		ahole = .ahole [freeptr]	! AND GO TO NEXT HOLE
		END;%( AT THIS POINT, AHOLE POINTS TO THE HOLE WHICH

			IS IMMEDIATELY LOWER ON THE PAGE THAN
			CHUNK. )%
	    chunk [freeptr] = .ahole [freeptr];	! TAKE HIS LINK
	    ahole [freeptr] = .chunk;		! MAKE HIM POINT TO US
	    chunk [holesize] = .size;		! SET OUT SIZE FIELD
	    %( NOW, COLLAPSE CHUNK IF IT TOUCHES NEXT HIGHER HOLE )%

	    IF .ahole - .ahole [holesize] EQL .chunk
	    THEN
		BEGIN
		%( TO MERGE OUR CHUNK WITH THE NEXT ONE DOWN IN THE PAGE )%ahole [holesize] = .ahole [holesize
		] + .chunk [holesize];
		ahole [freeptr] = .chunk [freeptr];	! RELINK
		chunk = .ahole
		END %( OF MERGING WITH PREVIOUS HOLE )%

	    END;%( BEGIN SEARCHING FREE LIST )%%( NOW, WE MUST CHECK IF WE SHOULD

		MERGE THIS HOLE WITH THE PRECEDING HOLE ( THAT IS, THE
		HOLE IMMEDIATELY ABOVE IT ON THE PAGE ) )%

	IF (.chunk - .chunk [holesize]) EQL .chunk [freeptr]	! IF THE HOLES TOUCH...
	THEN
	    BEGIN
	    %( TO MERGE THEM )%ahole = .chunk [freeptr];
	    chunk [holesize] = .chunk [holesize] + .ahole [holesize];	! MERGE SIZES
	    chunk [freeptr] = .ahole [freeptr]
	    END %( OF MERGE WITH PRECEDING CHUNK )%

	END;%( OF ELSE IF PAGE WASNT FULL )%

    IF .chunk [holesize] GTR .pagtab [.pagenum, bighol] THEN pagtab [.pagenum, bighol] = .chunk [holesize];

						! UPDATE BIGHOL

    !+
    !    IS THIS THE LAST CHUNK TO BE RETURNED ON THIS PAGE?
    !-

    IF .pagtab [.pagenum, bighol] EQL pagesize
    THEN
	BEGIN
	%( TO GIVE BACK A COMPLETE PAGE )%ppage (.apage, 1, true)
	END;%( OF IF BIGHOL IS PAGESIZE )%

    RETURN true
    END;

%( OF PMEM ROUTINE )%
END

ELUDOM