From fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 Mon Sep 17 00:00:00 2001
From: Joseph Hunkeler <jhunkeler@gmail.com>
Date: Wed, 8 Jul 2015 20:46:52 -0400
Subject: Initial commit

---
 sys/nmemio/doc/memio.hlp | 308 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 308 insertions(+)
 create mode 100644 sys/nmemio/doc/memio.hlp

(limited to 'sys/nmemio/doc/memio.hlp')

diff --git a/sys/nmemio/doc/memio.hlp b/sys/nmemio/doc/memio.hlp
new file mode 100644
index 00000000..1bc5c0a0
--- /dev/null
+++ b/sys/nmemio/doc/memio.hlp
@@ -0,0 +1,308 @@
+.help memio Feb83 "Dynamic Memory Management Routines"
+.sh
+Introduction
+
+    The memory management routines manage both a stack and a heap.
+Storage for the stack may be fragmented, and chunks of stack storage are
+allocated dynamically from the heap as needed.  Programs may allocate
+heap storage directly if desired, for large or semipermanent buffers.
+Stack storage is intended for use with small buffers, where the overhead
+of allocating and deallocating space must be kept to a minimum.
+
+
+.ks
+.nf
+heap routines:
+
+	malloc  (ptr, number_of_elements, data_type)
+	calloc  (ptr, number_of_elements, data_type)
+	realloc (ptr, number_of_elements, data_type)
+	mfree   (ptr, data_type)
+
+
+stack routines:
+
+	salloc  (ptr, number_of_elements, data_type)
+	smark   (ptr)
+	sfree   (ptr)
+.fi
+.ke
+
+
+MALLOC allocates space on the heap.  CALLOC does the same, and fills the buffer
+with zeroes.  REALLOC is used to change the size of a previously allocated
+buffer, copying the contents of the buffer if necessary.  MFREE frees space
+allocated by a prior call to MALLOC, CALLOC, or REALLOC.
+
+Space is allocated on the stack with SALLOC.  SMARK should be called before
+SALLOC, to mark the position of the stack pointer.  SFREE returns all space
+allocated on the stack since the matching call to SMARK.
+
+
+.KS
+Example:
+.nf
+	pointer	buf, sp
+
+	begin
+		call smark (sp)
+		call salloc (buf, SZ_BUF, TY_CHAR)
+		while (getline (fd, Memc[buf]) != EOF) {
+		    (code to use buffer ...)
+		}
+		call sfree (sp)
+.fi
+.KE
+
+
+These routines will generate an error abort if memory cannot be allocated
+for some reason.
+
+.sh
+Heap Management
+
+    Since many operating systems provide heap management facilities,
+MALLOC and MFREE consist of little more than calls to Z routines to
+allocate and free blocks of memory.  The main function of MALLOC is
+to convert the physical buffer address returned by the Z routine into
+a pointer of the requested type.
+
+The pointer returned to the calling routine does not point at the beginning
+of the physical buffer, but at a location a few bytes into the buffer.
+The physical address of the buffer is stored in the buffer, immediately
+before the cell pointed to by the pointer returned by MALLOC.  The
+stored address must be intact when MFREE is later called to deallocate
+the buffer, or a "Memory corrupted" error diagnostic will result.
+
+The Z routines required to manage the heap are the following:
+
+.KS
+.nf
+	 zmget (bufadr, nbytes)
+	zmrget (bufadr, nbytes)
+	zmfree (buf_addr)
+.fi
+.KE
+
+The "get" routines should return NULL as the buffer address if space
+cannot be allocated for some reason.
+
+.sh
+Stack Management
+
+    The heap management routines have quite a bit of overhead associated
+with them, which precludes their use in certain applications.  In addition,
+the heap can be most efficiently managed when it contains few buffers.
+The stack provides an efficient mechanism for parceling out small amounts
+of storage, which can later all be freed with a single call.
+
+The main use of the stack is to provide automatic storage for local 
+arrays in procedures.  The preprocessor compiles code which makes calls
+to the stack management routines whenever an array is declared with the
+storage calls AUTO, or whenever the ALLOC statement is used in a procedure.
+
+
+.KS
+.nf
+	auto	char lbuf[SZ_LINE]
+	real	x[n], y[n]
+	int	n
+
+	begin
+		alloc (x[npix], y[npix])
+
+		while (getline (fd, lbuf) != EOF) {
+		    ...
+.fi
+.KE
+
+
+The AUTO storage class and the ALLOC statement are provided in the full
+preprocessor, but not in the subset preprocessor.  The following subset
+preprocessor code is functionally equivalent to the code show above:
+
+
+.KS
+.nf
+	pointer	lbuf, x, y, sp
+	int	n, getline()
+
+	begin
+		call smark (sp)
+		call salloc (lbuf, SZ_LINE, TY_CHAR)
+		n = npix
+		call salloc (x, n, TY_REAL)
+		call salloc (y, n, TY_REAL)
+
+		while (getline (fd, Memc[lbuf]) != EOF) {
+		    ...
+
+		call sfree (sp)
+.fi
+.KE
+
+.sh
+Semicode for Stack Management
+
+    At any given time, the "stack" is a contiguous buffer of a certain size.
+Stack overflow is handled by calling MALLOC to allocate another stack segment.
+A pointer to the previous stack segment is kept in each new stack segment,
+to permit reclamation of stack space.
+
+
+
+
+.KS
+.nf
+		salloc             smark              sfree
+
+
+
+	    stack_overflow 
+
+
+	
+		malloc            realloc             mfree
+
+
+
+		zmget              zmrget             zmfree
+
+
+
+		Structure of the Memory Management Routines
+.fi
+.KE
+
+
+
+
+.tp 5
+.nf
+procedure salloc (bufptr, nelements, data_type)
+
+bufptr:		upon output, contains pointer to the allocated space
+nelements:	number of elements of space to be allocated
+data_type:	data type of the elements and of the buffer pointer
+
+begin
+	# align stack pointer for the specified data type,
+	# compute amount of storage to be allocated
+
+	if (data_type == TY_CHAR)
+	    nchars = nelements
+	else {
+	    sp = sp + mod (sp-1, sizeof(data_type))
+	    nchars = nelements * sizeof(data_type)
+	}
+
+	if (sp + nchars > stack_top)		# see if room
+	    call stack_overflow (nchars)
+
+	if (data_type == TY_CHAR)		# return pointer
+	    bufptr = sp
+	else
+	    bufptr = (sp-1) / sizeof(data_type) + 1
+
+	sp = sp + nchars			# bump stack ptr
+	return
+end
+
+
+
+
+.tp 5
+procedure sfree (old_sp)			# pop the stack
+
+begin
+	# return entire segments until segment containing the old
+	# stack pointer is reached
+
+	while (old_sp < stack_base || old_sp > stack_top) {
+	    if (this is the first stack segment)
+		fatal error, invalid value for old_sp
+	    stack_base = old_segment.stack_base
+	    stack_top = old_segment.stack_top
+	    mfree (segment_pointer, TY_CHAR)
+	    segment_pointer = old_segment
+	}
+
+	sp = old_sp
+end
+
+
+
+
+.tp 5
+procedure smark (old_sp)			# save stack pointer
+
+begin
+	old_sp = sp
+end
+
+
+
+
+.tp 5
+procedure stack_overflow (nchars_needed)	# increase stk size
+
+begin
+	# allocate storage for new segment
+	segment_size = max (SZ_STACK, nchars_needed + SZ_STKHDR)
+	malloc (new_segment, segment_size, TY_CHAR)
+
+	# initialize header for the new segment
+	new_segment.old_segment = segment_pointer
+	new_segment.stack_base = new_segment + SZ_STKHDR
+	new_segment.stack_top = new_segment + segment_size
+
+	# make new segment the current segment
+	segment_pointer = new_segment
+	stack_base = new_segment.stack_base
+	stack_top = new_segment.stack_top
+	sp = stack_base
+end
+
+
+.fi
+The segment header contains fields describing the location and size of
+the segment, plus a link pointer to the previous segment in the list.
+
+
+.KS
+.nf
+	struct stack_header {
+		char	*stack_base
+		char	*stack_top
+		struct	stack_header *old_segment
+	}
+.fi
+.KE
+
+.sh
+Pointers and Addresses
+
+    Pointers are indices into (one indexed) Fortran arrays.  A pointer to
+an object of one datatype will in general have a different value than a
+pointer to an object of a different datatype, even if the objects are stored
+at the same physical address.  Pointers have strict alignment requirements,
+and it is not always possible to coerce the type of a pointer.  For this
+reason, the pointers returned by MALLOC and SALLOC are always aligned for
+all data types, regardless of the data type requested.
+
+The IRAF system code must occasionally manipulate and store true physical
+addresses, obtained with the function LOC.  The problem with physical
+addresses is that they are unsigned integers, but Fortran does not provide
+any unsigned data types.  Thus, comparisons of addresses are difficult
+in Fortran.
+
+A second LOC primitive is provided for use in routines which must compare
+addresses.  LOCC returns the address of the object passed as argument,
+right shifted to the size of a CHAR.  Thus, the difference between LOCC(a[1])
+and LOCC(a[n]) is the size of the N element array A in chars.
+
+The relationship between chars, bytes, and machine addresses is machine
+dependent.  Bytes seem to be the smallest units.  Some machines are byte
+addressable, others are word addressable.  The size of a CHAR in machine
+bytes is given by the constant SZB_CHAR.  The size of a machine word in
+machine bytes is given by the constant SZB_WORD.
-- 
cgit 

