aboutsummaryrefslogtreecommitdiff
path: root/sys/memio/doc
diff options
context:
space:
mode:
Diffstat (limited to 'sys/memio/doc')
-rw-r--r--sys/memio/doc/memio.hlp308
1 files changed, 308 insertions, 0 deletions
diff --git a/sys/memio/doc/memio.hlp b/sys/memio/doc/memio.hlp
new file mode 100644
index 00000000..1bc5c0a0
--- /dev/null
+++ b/sys/memio/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.