Trailing-Edge
-
PDP-10 Archives
-
BB-FB49A-RM
-
sources/sntmem.b36
There are no other files named sntmem.b36 in the archive.
%title 'SNT Memory Management'
module SNTMEM (ident = 'Version 1.00') =
begin
! Copyright (c) 1984, 1985 by
! DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts
!
! 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 which is not supplied by Digital.
!++
! FACILITY: DECnet/SNA SNA Trace Utility memory manager.
!
! ABSTRACT: This module provide routines to do utility support, i.e.
! buffer allocation, enqueue/dequeue.
!
! ENVIRONMENT: TOPS-20 Operating Systems, user mode.
!
! AUTHOR: Son VoBa, CREATION DATE: May 14, 1982.
!
! MODIFIED BY:
!
! D. Brannon, 11-Oct-84 : VERSION 1.00
!
!--
!
! REQUIRED FILES
!
library 'MONSYM'; ! Monitor symbols
library 'SNTDEF'; ! SNT common definitions
require 'JSYS'; ! TOPS-20 JSYS declarations
!
! FORWARD REFERENCES
!
forward routine
MEM$GET,
MEM$GET_MULTIPLE_BUFFERS,
MEM$GET_SINGLE_BUFFER,
MEM$INITIALIZE: novalue,
MEM$RELINK: novalue,
MEM$RETURN: novalue;
!
! EXTERNAL REFERENCES
!
external
MEMORY: MEMORY_BUFFER_POOL,
CONTROL: GLOBAL_CONTROL_BLOCK;
external routine
USP$BUFFER_INITIALIZE: novalue,
USP$LOCK: novalue,
USP$UNLOCK: novalue;
%global_routine ('MEM$GET', COUNT) =
!++
! FUNCTIONAL DESCRIPTION:
!
! Routine to allocate memory buffer to requesting process.
! If fail to allocate requested memory buffers, notify the
! control terminal of the fact, wait 5 seconds, try it again.
!
! FORMAL PARAMETERS:
!
! COUNT Number of memory buffer units to be allocated
! contiguously. If negative or 0, assumed to be 1.
!
! ROUTINE VALUE:
!
! The address of the buffer if allocated.
!
! SIDE EFFECTS:
!
! none
!
!--
begin
literal
MAXIMUM_TRIES = 10;
local
TRIES,
BUFFER,
MCB: ref MEMORY_CONTROL_BLOCK volatile;
TRIES = MAXIMUM_TRIES; ! Number of unsuccessful tries
do begin
USP$LOCK ($BUFFER_POOL); ! Lock buffer pool
MCB = CONTROL[GCB_MEMORY_CONTROL_BLOCK];
! Try to relink free buffers if there are indications that
! we might have run out. After that, check again, if same
! condition exists, we did run out of buffers.
if .MCB[MCB_FREE_HEAD] geq $MEMORY_BUFFER_UNITS
then MEM$RELINK ();
if .MCB[MCB_FREE_HEAD] geq $MEMORY_BUFFER_UNITS
then BUFFER = 0 ! None left, return 0
else begin
if .COUNT leq 1
then BUFFER = MEM$GET_SINGLE_BUFFER () ! Get buffer
else begin ! Multiple units allocation
MEM$RELINK (); ! Relink buffer list
BUFFER = MEM$GET_MULTIPLE_BUFFERS (.COUNT); ! Get buffers
end;
end;
USP$UNLOCK ($BUFFER_POOL); ! Unlock buffer pool
if .BUFFER neq 0 ! Got the buffers
then return .BUFFER;
TRIES = .TRIES - 1;
jsys_disms (2000); ! Wait for 2 seconds
end
while (.TRIES gtr 0);
jsys_psout (CH$ASCIZ ('No buffer'));
jsys_haltf (); ! Dead lock, stop process
return 0;
end; ! End of MEM$GET
%routine ('MEM$GET_MULTIPLE_BUFFERS', COUNT) =
!++
! FUNCTIONAL DESCRIPTION:
!
! Routine to allocate sequence of memory buffers.
!
! FORMAL PARAMETERS:
!
! COUNT Number of memory buffer units to be allocated
! contiguously.
!
! ROUTINE VALUE:
!
! The address of the first buffer in the sequence if allocated.
! Otherwise 0.
!
! SIDE EFFECTS:
!
! none
!
!--
begin
local
FOUND,
BUFFER,
MCB: ref MEMORY_CONTROL_BLOCK volatile,
HEADERS: ref MEMORY_BUFFER_HEADERS,
HEAD: ref MEMORY_BUFFER_HEADER,
TAIL: ref MEMORY_BUFFER_HEADER,
USED: ref MEMORY_BUFFER_HEADER;
MCB = CONTROL[GCB_MEMORY_CONTROL_BLOCK];
HEADERS = MCB[MCB_HEADERS];
HEAD = HEADERS[(.MCB[MCB_FREE_HEAD] * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
FOUND = $FALSE; ! Assume that we cannot allocate
while not .FOUND
do begin ! Scan free list for buffer sequence
local HDR: ref MEMORY_BUFFER_HEADER;
HDR = .HEAD; ! Get new buffer header of next chain
FOUND = $TRUE; ! Pretend that we found the sequence
! Look ahead in the free link, starting with the buffer
! pointed to by HEAD. Upon exit, if successfull, HDR will
! point to the last buffer in the chain; otherwise, HEAD
! is update pointing to the next possible buffer chain.
incr I from 1 to (.COUNT-1)
do begin
local NEXT;
if (.HDR[MBH_FORWARD_LINK] lss $MEMORY_BUFFER_UNITS)
and (.HDR[MBH_IDENTIFIER] eql (.HDR[MBH_FORWARD_LINK] - 1))
then begin ! Next buffer is adjacent
NEXT = .HDR[MBH_FORWARD_LINK] * $MEMORY_BUFFER_HEADER_SIZE;
HDR = HEADERS[.NEXT,0,0,36,0];
end
else begin ! Next buffer is not adjacent
if .HDR[MBH_FORWARD_LINK] geq $MEMORY_BUFFER_UNITS
then return 0 ! This is the last in the list
else begin ! There are more buffers in the list
NEXT = .HDR[MBH_FORWARD_LINK] * $MEMORY_BUFFER_HEADER_SIZE;
HEAD = HEADERS[.NEXT,0,0,36,0];
end;
FOUND = $FALSE; ! Set flag to indicate failure
exitloop; ! Terminate current search
end;
end;
if .FOUND
then TAIL = .HDR;
end;
if not .FOUND ! If cannot allocate that many
then return 0; ! buffers, return none allocated
! At this point, we have identified the allocated buffer sequence.
! The sequence is pointed to by HEAD as the starting buffer and
! TAIL as the last buffer. Allocate the buffer area and initialize it.
BUFFER = MEMORY[(.HEAD[MBH_IDENTIFIER] * $MEMORY_BUFFER_SIZE)];
USP$BUFFER_INITIALIZE (.BUFFER, .COUNT * $MEMORY_BUFFER_SIZE);
! If there are already buffers on the allocated link,
! Calculate the identifier of the last buffer of the link.
! Append new allocated buffers to the allocated linked list.
if (USED = .MCB[MCB_ALLOCATED_TAIL]) neq -1
then begin
USED = HEADERS[(.USED * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
USED[MBH_FORWARD_LINK] = .HEAD[MBH_IDENTIFIER];
end;
! Update the head of the free link. If the allocate sequence is
! at the beginning of the free list, then just do straight update
! of the head of the free link; otherwise, snatch the sequence out
! of the free list and pluck the hole left behind without changing
! the head of the free link.
if .MCB[MCB_FREE_HEAD] eql .HEAD[MBH_IDENTIFIER]
then MCB[MCB_FREE_HEAD] = .TAIL[MBH_FORWARD_LINK]
else begin
local HD: ref MEMORY_BUFFER_HEADER, TL: ref MEMORY_BUFFER_HEADER;
if (HD = .HEAD[MBH_BACKWARD_LINK]) neq -1
then begin
HD = HEADERS[(.HD * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
HD[MBH_FORWARD_LINK] = .TAIL[MBH_FORWARD_LINK];
end;
if (TL = .TAIL[MBH_FORWARD_LINK]) lss $MEMORY_BUFFER_UNITS
then begin
TL = HEADERS[(.TL * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
TL[MBH_BACKWARD_LINK] = .HEAD[MBH_BACKWARD_LINK];
end;
end;
! Go through the buffer header chain
! set appropriate flags and links
HEAD[MBH_BACKWARD_LINK] = .MCB[MCB_ALLOCATED_TAIL];
TAIL[MBH_LOCK] = $TRUE;
TAIL[MBH_CLUSTER] = $FALSE;
TAIL[MBH_FORWARD_LINK] = -1;
USED = .HEAD;
incr I from 1 to (.COUNT-1)
do begin
USED[MBH_LOCK] = $TRUE;
USED[MBH_CLUSTER] = $TRUE;
USED = HEADERS[(.USED[MBH_FORWARD_LINK] * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
end;
! Update the tail of the allocated linked list
MCB[MCB_ALLOCATED_TAIL] = .TAIL[MBH_IDENTIFIER];
return .BUFFER; ! Return buffer address
end; ! End of MEM$GET_MULTIPLE_BUFFERS
%routine ('MEM$GET_SINGLE_BUFFER') =
!++
! FUNCTIONAL DESCRIPTION:
!
! Routine to allocate single memory buffer.
!
! FORMAL PARAMETERS:
!
! none
!
! ROUTINE VALUE:
!
! The address of the buffer if allocated, otherwise 0.
!
! SIDE EFFECTS:
!
! none
!
!--
begin
local
BUFFER,
HEADERS: ref MEMORY_BUFFER_HEADERS,
MCB: ref MEMORY_CONTROL_BLOCK volatile,
HEADER: ref MEMORY_BUFFER_HEADER,
USED: ref MEMORY_BUFFER_HEADER;
MCB = CONTROL[GCB_MEMORY_CONTROL_BLOCK];
HEADERS = MCB[MCB_HEADERS];
! Allocate buffer area, then initialize it
BUFFER = MEMORY[(.MCB[MCB_FREE_HEAD] * $MEMORY_BUFFER_SIZE)];
USP$BUFFER_INITIALIZE (.BUFFER, $MEMORY_BUFFER_SIZE);
! Get the header of the new allocated buffer
HEADER = HEADERS[(.MCB[MCB_FREE_HEAD] * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
! If there are already buffers on the allocated link,
! Calculate the indentifier of the last buffer of the link.
! Append new allocated buffer to the allocated linked list.
if (USED = .MCB[MCB_ALLOCATED_TAIL]) neq -1
then begin
USED = HEADERS[(.USED * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
USED[MBH_FORWARD_LINK] = .HEADER[MBH_IDENTIFIER];
end;
! Update the head of the free linked list.
MCB[MCB_FREE_HEAD] = .HEADER[MBH_FORWARD_LINK];
HEADERS[.MCB[MCB_FREE_HEAD],MBH_BACKWARD_LINK] = -1;
! Set appropriate flags and links of the new
! allocated buffer header
HEADER[MBH_LOCK] = $TRUE;
HEADER[MBH_CLUSTER] = $FALSE;
HEADER[MBH_BACKWARD_LINK] = .MCB[MCB_ALLOCATED_TAIL];
HEADER[MBH_FORWARD_LINK] = -1;
! If it is the first allocated buffer, update the head of
! the allocated linked list
if .MCB[MCB_ALLOCATED_HEAD] eql -1
then MCB[MCB_ALLOCATED_HEAD] = .HEADER[MBH_IDENTIFIER];
! Update the tail of the allocated linked list
MCB[MCB_ALLOCATED_TAIL] = .HEADER[MBH_IDENTIFIER];
return .BUFFER;
end; ! End of MEM$GET_SINGLE_BUFFER
%global_routine ('MEM$INITIALIZE') : novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Initialize memory buffers.
!
! FORMAL PARAMETERS:
!
! none
!
! ROUTINE VALUE:
!
! none
!
! SIDE EFFECTS:
!
! none
!
!--
begin
local
HEADERS: ref MEMORY_BUFFER_HEADERS,
MCB: ref MEMORY_CONTROL_BLOCK volatile;
! Initialize buffer pool area
USP$BUFFER_INITIALIZE (MEMORY, $MEMORY_POOL_SIZE);
! Initialize control area
MCB = CONTROL[GCB_MEMORY_CONTROL_BLOCK];
MCB[MCB_ALLOCATED_HEAD] = -1;
MCB[MCB_ALLOCATED_TAIL] = -1;
MCB[MCB_FREE_HEAD] = 0;
MCB[MCB_FREE_TAIL] = $MEMORY_BUFFER_UNITS - 1;
HEADERS = MCB[MCB_HEADERS];
! Initialize buffer headers
USP$BUFFER_INITIALIZE (MCB[MCB_HEADERS], $MEMORY_HEADERS);
incr I from 0 to ($MEMORY_BUFFER_UNITS-1)
do begin
local HEADER: ref MEMORY_BUFFER_HEADER;
HEADER = HEADERS[(.I * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
HEADER[MBH_FLAGS] = 0;
HEADER[MBH_FORWARD_LINK] = .I + 1;
HEADER[MBH_IDENTIFIER] = .I;
HEADER[MBH_BACKWARD_LINK] = .I - 1;
end;
return;
end; ! End of MEM$INITIALIZE
%global_routine ('MEM$RELINK') : novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Relink control linked list of the memory buffers.
!
! FORMAL PARAMETERS:
!
! none
!
! ROUTINE VALUE:
!
! none
!
! SIDE EFFECTS:
!
! none
!
!--
begin
local
UCOUNT,
FCOUNT,
USED: ref MEMORY_BUFFER_HEADER,
FREE: ref MEMORY_BUFFER_HEADER,
HEADERS: ref MEMORY_BUFFER_HEADERS,
MCB: ref MEMORY_CONTROL_BLOCK volatile;
FREE = USED = FCOUNT = UCOUNT = 0;
MCB = CONTROL[GCB_MEMORY_CONTROL_BLOCK];
HEADERS = MCB[MCB_HEADERS];
incr I from 0 to ($MEMORY_BUFFER_UNITS-1)
do begin
local HEADER: ref MEMORY_BUFFER_HEADER;
HEADER = HEADERS[(.I * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
if .HEADER[MBH_LOCK]
then begin ! Found allocated buffer
if .USED eql 0 ! Assign first allocated buffer to list
then begin
USED = .HEADER;
USED[MBH_FORWARD_LINK] = -1;
USED[MBH_BACKWARD_LINK] = -1;
MCB[MCB_ALLOCATED_HEAD] = .I;
MCB[MCB_ALLOCATED_TAIL] = .I;
UCOUNT = .UCOUNT + 1;
end
else begin ! Assign next allocated buffer to list
USED[MBH_FORWARD_LINK] = .I;
HEADER[MBH_BACKWARD_LINK] = .MCB[MCB_ALLOCATED_TAIL];
HEADER[MBH_FORWARD_LINK] = -1;
USED = .HEADER;
MCB[MCB_ALLOCATED_TAIL] = .I;
UCOUNT = .UCOUNT + 1;
end;
end
else begin ! Found free buffer
if .FREE eql 0
then begin ! Assign first free buffer to list
FREE = .HEADER;
FREE[MBH_FORWARD_LINK] = $MEMORY_BUFFER_UNITS;
FREE[MBH_BACKWARD_LINK] = -1;
MCB[MCB_FREE_HEAD] = .I;
MCB[MCB_FREE_TAIL] = .I;
FCOUNT = .FCOUNT + 1;
end
else begin ! Assign next free buffer to list
FREE[MBH_FORWARD_LINK] = .I;
HEADER[MBH_BACKWARD_LINK] = .MCB[MCB_FREE_TAIL];
HEADER[MBH_FORWARD_LINK] = $MEMORY_BUFFER_UNITS;
FREE = .HEADER;
MCB[MCB_FREE_TAIL] = .I;
FCOUNT = .FCOUNT + 1;
end;
end;
end;
if (.FCOUNT + .UCOUNT) neq $MEMORY_BUFFER_UNITS
then begin
jsys_psout (CH$ASCIZ ('Loose buffers'));
jsys_haltf ();
end;
return;
end; ! End of MEM$RELINK
%global_routine ('MEM$RETURN', ADDRESS) : novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Return the memory buffer to free pool.
!
! FORMAL PARAMETERS:
!
! ADDRESS Address of the buffer to be returned.
!
! ROUTINE VALUE:
!
! none
!
! SIDE EFFECTS:
!
! none
!
!--
begin
local
IDENTIFIER,
CHAINED,
MCB: ref MEMORY_CONTROL_BLOCK volatile,
PREV: ref MEMORY_BUFFER_HEADER,
NEXT: ref MEMORY_BUFFER_HEADER,
FREE: ref MEMORY_BUFFER_HEADER,
HEADER: ref MEMORY_BUFFER_HEADER,
HEADERS: ref MEMORY_BUFFER_HEADERS;
USP$LOCK ($BUFFER_POOL); ! Lock memory buffer pool
MCB = CONTROL[GCB_MEMORY_CONTROL_BLOCK];
HEADERS = MCB[MCB_HEADERS];
IDENTIFIER = (.ADDRESS - MEMORY) / $MEMORY_BUFFER_SIZE;
HEADER = HEADERS[(.IDENTIFIER * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
NEXT = .HEADER;
do begin
HEADER = .NEXT;
CHAINED = .HEADER[MBH_CLUSTER];
if (PREV = .HEADER[MBH_BACKWARD_LINK]) neq -1
then begin ! Update link of previous buffer
PREV = HEADERS[(.PREV * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
PREV[MBH_FORWARD_LINK] = .HEADER[MBH_FORWARD_LINK];
end;
if (NEXT = .HEADER[MBH_FORWARD_LINK]) neq -1
then begin ! Update link of next buffer
NEXT = HEADERS[(.NEXT * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
NEXT[MBH_BACKWARD_LINK] = .HEADER[MBH_BACKWARD_LINK];
end;
HEADER[MBH_FLAGS] = 0; ! Clear all flags
FREE = HEADERS[(.MCB[MCB_FREE_TAIL] * $MEMORY_BUFFER_HEADER_SIZE),0,0,36,0];
FREE[MBH_FORWARD_LINK] = .HEADER[MBH_IDENTIFIER];
HEADER[MBH_BACKWARD_LINK] = .MCB[MCB_FREE_TAIL];
HEADER[MBH_FORWARD_LINK] = $MEMORY_BUFFER_UNITS;
MCB[MCB_FREE_TAIL] = .HEADER[MBH_IDENTIFIER];
end
while .CHAINED and (.NEXT neq -1); ! Release all chained buffers
if .MCB[MCB_ALLOCATED_TAIL] eql .HEADER[MBH_IDENTIFIER]
then MCB[MCB_ALLOCATED_TAIL] = (if .PREV neq -1
then .PREV[MBH_IDENTIFIER]
else .PREV);
USP$UNLOCK ($BUFFER_POOL); ! Unlock memory buffer pool
return;
end; ! End of MEM$RETURN
end ! End of TSTMEM module
eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:2
! Comment Column:40
! Comment Rounding:+1
! End: