Trailing-Edge
-
PDP-10 Archives
-
tops20-v7-ft-dist1-clock
-
7-sources/lodmem.b36
There are 3 other files named lodmem.b36 in the archive. Click here to see a list.
%TITLE 'L O D M E M -- RMSLOD memory manager'
!<BLF/REQUIRE 'BLI:BLF.REQ'>
MODULE lodmem (IDENT = '1'
) =
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: LOD
!
! ABSTRACT:
!
! LODMEM contains the memory management routines for RMSLOD.
!
! ENVIRONMENT: User mode, from RMSLOD
!
! AUTHOR: Ron Lusk , CREATION DATE: 9-Jul-84
!
! MODIFIED BY:
!
! , : VERSION
! 01 -
!--
!
! TABLE OF CONTENTS
!
FORWARD ROUTINE
getmem,
fremem,
inimem,
scneql,
scngtr,
garbge,
split,
remove;
!
! INCLUDE FILES:
!
!
! MACROS:
!
FIELD
mem$r_fields =
SET
mem$a_next = [0, 0, 18, 0], ! Address of next block header
mem$h_size = [0, 18, 18, 0] ! Size of this block
TES;
LITERAL
mem$k_bln = 2;
MACRO
$memory_block =
BLOCK [mem$k_bln] FIELD (mem$r_fields) %;
!
! EQUATED SYMBOLS:
!
LITERAL
number_of_pages = %O'20',
high_address = %O'377777';
!
! OWN STORAGE:
!
OWN
memory_lane : REF $memory_block INITIAL (0),
last_block : REF $memory_block,
current_block : REF $memory_block;
!
! EXTERNAL REFERENCES:
!
! None
GLOBAL ROUTINE getmem (size) =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! NONE.
!
! IMPLICIT INPUTS
!
! NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
BEGIN
LOCAL
block_address; ! Address of memory block
IF .memory_lane EQL 0 ! First time through
THEN
inimem ();
IF scneql (.size) NEQ 0 ! Found exact match
THEN
BEGIN
RETURN remove (.size);
END
ELSE
BEGIN
IF scngtr (.size) NEQ 0 ! Found one big enough
THEN
BEGIN
RETURN split (.size);
END
ELSE
BEGIN
garbge ();
IF scneql (.size) NEQ 0 ! Found exact match
THEN
BEGIN
RETURN remove (.size);
END
ELSE
BEGIN
IF scngtr (.size) NEQ 0 ! Found one big enough
THEN
BEGIN
RETURN split (.size);
END
ELSE
RETURN SIGNAL (0 %( ss$_dynamic_memory_exhausted )%);
END;
END;
END;
END; !End of GETMEM
GLOBAL ROUTINE fremem (address, size) =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! NONE.
!
! IMPLICIT INPUTS
!
! NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
BEGIN
LOCAL
ret_block : REF $memory_block;
ret_block = .address + .size - 1;
ret_block [mem$h_size] = .size;
current_block = memory_lane;
UNTIL .current_block [mem$a_next] LSSA .ret_block DO !
BEGIN
current_block = .current_block [mem$a_next];
END;
ret_block [mem$a_next] = .current_block [mem$a_next];
current_block [mem$a_next] = .ret_block;
RETURN 1;
END; !End of FREMEM
ROUTINE inimem =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! NONE.
!
! IMPLICIT INPUTS
!
! NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
BEGIN
memory_lane = high_address;
memory_lane [mem$a_next] = 0; ! No next block
memory_lane [mem$h_size] = number_of_pages*%O'1000';
RETURN 1;
END; !End of INIMEM
ROUTINE scneql (size) =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! NONE.
!
! IMPLICIT INPUTS
!
! NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
BEGIN
!
! Initialize the pointers
!
last_block = memory_lane;
current_block = .memory_lane;
!
! Look for the right sized block
!
UNTIL .current_block EQL 0 DO
BEGIN
IF .current_block [mem$h_size] EQL .size ! Right size?
THEN
EXITLOOP
ELSE
BEGIN
last_block = .current_block;
current_block = .current_block [mem$a_next];
END;
END;
!
! Return the current block. If this is zero, then
! we didn't find any memory blocks of the size
! requested. If it contains an address, then it is the
! address of the header of a block which is the same
! size as that requested by the caller.
!
RETURN .current_block;
END; !End of SCNEQL
ROUTINE scngtr (size) =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! NONE.
!
! IMPLICIT INPUTS
!
! NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
BEGIN
!
! Initialize the pointers
!
last_block = memory_lane;
current_block = .memory_lane;
!
! Look for a block big enough to hold our size block
!
UNTIL .current_block EQL 0 DO
BEGIN
IF .current_block [mem$h_size] GTR .size ! Right size?
THEN
EXITLOOP
ELSE
BEGIN
last_block = .current_block;
current_block = .current_block [mem$a_next];
END;
END;
!
! Return the current block. If this is zero, then
! we didn't find any memory blocks of the size
! requested. If it contains an address, then it is the
! address of the header of a block which is the same
! size as that requested by the caller.
!
RETURN .current_block;
END; !End of SCNGTR
ROUTINE garbge =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! NONE.
!
! IMPLICIT INPUTS
!
! NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
BEGIN
last_block = .memory_lane;
current_block = .last_block [mem$a_next];
UNTIL .current_block EQL 0 DO
BEGIN
IF .last_block - .last_block [mem$h_size] EQL .current_block !
THEN
BEGIN ! Coalesce the blocks
last_block [mem$a_next] = .current_block [mem$a_next];
last_block [mem$h_size] = .last_block [mem$h_size] + !
.current_block [mem$h_size];
current_block = .last_block [mem$a_next];
END
ELSE
BEGIN ! Move on to the next pair
last_block = .current_block;
current_block = .current_block [mem$a_next];
END;
END;
RETURN 1;
END; !End of GARBGE
ROUTINE split (size) =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! NONE.
!
! IMPLICIT INPUTS
!
! NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
BEGIN
current_block [mem$h_size] = .current_block [mem$h_size] - .size;
RETURN .current_block - .current_block [mem$h_size] - .size + 1;
END; !End of SPLIT
ROUTINE remove (size) =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! NONE.
!
! IMPLICIT INPUTS
!
! CURRENT_BLOCK - address of memory block to remove
! LAST_BLOCK - address of memory block before current block
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
BEGIN
last_block [mem$a_next] = .current_block [mem$a_next];
RETURN .current_block - .size + 1;
END; !End of REMOVE
END !End of Module LODMEM
ELUDOM