Google
 

Trailing-Edge - PDP-10 Archives - cuspbinsrc_2of2_bb-fp63b-sb - 10,7/rms10/rmssrc/rmsfsm.b36
There are 6 other files named rmsfsm.b36 in the archive. Click here to see a list.
MODULE  FSM =


BEGIN

GLOBAL BIND	FSMV = 1^24 + 0^18 + 4;		!EDIT DATE: 6-JUL-78

%([
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.

THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.

!COPYRIGHT (C) 1977, 1979 BY DIGITAL EQUIPMENT CORPORATION


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.

****************** Start RMS-10 V1.1 *********************
********************* TOPS-10 ONLY ***********************

PRODUCT	MODULE	 SPR
 EDIT	 EDIT	 QAR		DESCRIPTION
======	======	=====		===========

 100	  3	Dev		Make declarations for routine names
				be EXTERNAL ROUTINE so RMS will compile 
				under BLISS V4 (RMT, 10/22/85).

 102	  4	Dev		Change checks for RMS$$G to be for less
				than 643000, so that RMS$$G can be assigned
				higher to avoid symbol conflicts under
				BLISS V4 (RMT, 12/2/85).

	***** END OF REVISION HISTORY *****




])%

%([ EXTERNAL DECLARATIONS ])%

EXTERNAL ROUTINE
	FGPAGE,		! ENTRY POINT IN FUNCT. TO GET A PAGE
	FGMEM,		! ENTRY POINT IN FUNCT. TO GET BLOCK OF MEM.
	FPMEM,		! ENTRY POINT IN FUNCT. TO FREE MEM.
	CRASH,
	DUMP;

EXTERNAL
	RMS$$G,		!LOCATION OF RMS GLOBALS. THEY GO IN ONE OF 3 LOCS
			!LOWSEG (RMS.REL WITH COBOL/R)
			!573000 (RMSCOB.EXE)
			!643000 (RMS.EXE) -- THIS CASE ONLY USE RMS'S OWN FSM
	NUMFREEPAGES;

%([ ERROR MESSAGE REFERENCES IN THIS MODULE ])%

EXTERNAL
    MSGBSP,
    MSGPM2,			! BIGHOL IS NON-ZERO
    MSGBSTATUS,		! BAD RETURNED BY GMEM
    MSGPM3,			! BAD VALUE FOUND IN PMEM
    MSGINPUT,		! BAD INPUT VALUE
    MSGLINK,		! LINK INCONSISTENCY
    MSGCORE,		! CANT GET CORE
    MSGPNA;			! PAGE NOT ALLOCATED





REQUIRE 'RMSREQ';
EXTDECLARATIONS;



%([
***********************************************************************
*			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%,			! BIT 0 MEANS PAGE NOT FREE
	BIGHOL  = 18,10%,			! LARGEST HOLE ON PAGE
	FIRSTFREE = 0,18%;			! 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
		


! 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

GLOBAL ROUTINE GPAGE ( PAGES ) =
BEGIN
	ARGUMENT (PAGES,VALUE);

REGISTER
    PAGENUM,
    PAGECOUNT;


	TRACE ( 'GPAGE' );

	CHECKINPUT(PAGES,GTR,ZERO);		! PAGES MUST BE POSITIVE


	%([ 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 = $CALL ( FGPAGE, .PAGES ^ P2W ))  IS FALSE
		THEN
			BADRETURN
		ELSE
			BEGIN
			RETURN .PAGENUM
		END
	END;

	%([ END OF CODE TO UTILIZE OTS'S MEMORY MANAGER ])%


	PAGENUM = ZERO;				! 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 = ZERO;				! CHECK FOR EACH PAGE OF BLOCK
		WHILE (.PAGTAB [ .PAGENUM , FCMBUSY ] IS OFF )
		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 ] = ZERO;
 					PAGTAB [ .PAGECOUNT , FCMBUSY ] =  ON
 					END;  %( OF SET BUSY )%
				$CALL (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 )%
	BADRETURN					! NO ROOM, GIVE FAILURE RETURN
END; %( OF GPAGE)%



! 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>

GLOBAL ROUTINE PPAGE ( PAGENUM, PAGES, KILLFLAG ) =
BEGIN
	ARGUMENT (PAGENUM,VALUE);
	ARGUMENT (PAGES,VALUE);
	ARGUMENT (KILLFLAG,VALUE);

LOCAL
    PAGEINDEX;


	TRACE ( 'PPAGE' );

	CHECKINPUT(PAGES,GTR,ZERO);		! MUST BE POSITIVE NO. PAGES



	%([ Code to utilize OTS's memory manager.	])%
	
	IF (RMS$$G LSS  %O'643000') 
	THEN	BEGIN	%( WE ARE LOADED BELOW 600000 )%
		IF $CALL ( FPMEM, .PAGENUM ^ P2W, .PAGES ^ P2W )  
		THEN	GOODRETURN
		ELSE	RMSBUG ( MSGINPUT);
	END;

	%([ End of code to utilize OTS's memory manager  ])%

	%([ 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 ] IS OFF )
		THEN RMSBUG ( MSGPNA );		! ** PAGE NOT AVAILABLE **
		PAGTAB [ .PAGEINDEX , wrd ] = ZERO;

		%([ SHOULD WE DESTROY THIS PAGE? ])%

		IF ( .KILLFLAG )
		THEN $CALL (KILLPAGE, .PAGEINDEX+.FRECOR, 1);

		END;   %( OF REMOVE THIS PAGE )%

	GOODRETURN
END; %( OF PPAGE)%



! 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

GLOBAL ROUTINE GMEM ( SIZE ) =
BEGIN
	ARGUMENT (SIZE,VALUE);

REGISTER
    BLTAC;			! TEMPORARY REGISTER

LOCAL
    AHOLE,
    PAGEFULL,
    BHOLE,
    ANSWER,
    PAGENUM,
    PAGEADR,
    FREEPAGE;
MAP
    AHOLE:	POINTER,
    BHOLE:	POINTER,
    ANSWER:	POINTER;
MAP
    PAGEADR:	POINTER;

	TRACE ( 'GMEM' );

	IF ( .SIZE GTR PAGESIZE ) OR ( .SIZE LEQ 0 )
		THEN RMSBUG ( MSGINPUT );			! BAD CORE REQUEST

	PAGENUM = ZERO;					! POINTER TO PAGTAB


	%([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 = $CALL (FGMEM, .SIZE)) IS FALSE
		THEN
			RMSBUG ( MSGCORE )
		ELSE
			RETURN .ANSWER
		END;

	%([END OF CODE TO UTILIZE OTS'S MEMORY MANAGER          ])%


	%([ LOOK AT THE INPUT ARGUMENTS ])%

	LOOKAT ('	CHUNK REQUESTED: ', SIZE );

	%([ LOOP OVER ALL CHUNKS ])%

	WHILE ( .PAGTAB [ .PAGENUM, BIGHOL ] LSS .SIZE )
			AND
		( .PAGENUM LEQ .NUMFREEPAGES )
		DO INC ( 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 = CALLGPAGE ( PCI( 1 ) ) ) IS FALSE
		     THEN BADRETURN;			! 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 ] = ZERO		! 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 = ZERO;
	WHILE .AHOLE [ HOLESIZE ] LSS .SIZE
	DO
		BEGIN
		IF ( .AHOLE [ FREEPTR ] ^ W2P ISNT .FREEPAGE )
				OR
!** [14] ROUTINE:GMEM, AT LINE 4478, EGM, 6-JUL-78
%([14])%		( ( .AHOLE - .AHOLE [ HOLESIZE ] + 1 ) /512 ISNT .FREEPAGE )
			THEN RMSBUG ( MSGLINK );		! PAGE LINKS SCREWED UP
		IF .AHOLE [ FREEPTR ] IS ZERO 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 ] IS .SIZE THEN		! EXACT MATCH
		BEGIN
		IF .BHOLE IS ZERO THEN			! 1ST HOLE IN PAGE...
			BEGIN
			PAGTAB [ .PAGENUM, FIRSTFREE ] = .AHOLE [ FREEPTR ];
			IF .AHOLE [ FREEPTR ] IS ZERO 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 ] = ZERO		! CLEAR BIGHOL
	ELSE
		 BEGIN
		AHOLE = .PAGTAB [ .PAGENUM, FIRSTFREE ];	! START AT BEGINNING OF LIST
		BHOLE = .AHOLE [ HOLESIZE ];			! BHOLE = LARGEST SIZE FOUND SO FAR
		UNTIL .AHOLE IS ZERO
		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 ISNT ( .PAGENUM + .FRECOR ) THEN
		RMSBUG ( MSGBSTATUS );					! ANSWER ISNT RIGHT
	RETURN .ANSWER
END;


! 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 )

GLOBAL ROUTINE PMEM ( SIZE, CHUNK2 ) =
BEGIN
	ARGUMENT (SIZE,VALUE);
	ARGUMENT (CHUNK2,REFERENCE);

LOCAL
    PAGENUM,
    APAGE,
    AHOLE,
    CHUNK,
    BHOLE;

MAP
    CHUNK:	POINTER,
    AHOLE:	POINTER;


	TRACE ( 'PMEM');
	CHUNK = .CHUNK2;		! GET ADDRESS OF CORE


	%([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 $CALL (FPMEM, .CHUNK, .SIZE )
		THEN
			GOODRETURN
		ELSE
			RMSBUG ( MSGINPUT )
		END;

	%([ End of code to utilize OTS's memory manager ])%




	%([ 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 ZERO )
		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 ] IS OFF
		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 ] = ZERO;

	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 ] ) IS ZERO	! IF PAGE IS FULL
	THEN
		BEGIN
		IF .PAGTAB [ .PAGENUM, BIGHOL ] ISNT ZERO
			THEN RMSBUG ( MSGPM2 );			! BIGHOL NON-ZERO
		CHUNK [ HOLESIZE ] = .SIZE;			! SET CHUNK SIZE
		CHUNK [ FREEPTR ] = ZERO;			! 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 ] IS ZERO 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 ] IS .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 ] ) IS .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 ] IS PAGESIZE THEN
		BEGIN %( TO GIVE BACK A COMPLETE PAGE )%
		CALLPPAGE ( LCI ( APAGE ) , PCI ( 1 ), PCI ( TRUE ) )
		END; %( OF IF BIGHOL IS PAGESIZE )%


	GOODRETURN

END;   %( OF PMEM ROUTINE )%
end
eludom