Trailing-Edge
-
PDP-10 Archives
-
BB-JF18A-BM
-
sources/rms/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