static char Sccsid
[] = "aq.c @(#)aq.c 1.1 10/1/82 Berkeley ";
* malloc/free/afreset -- dynamic memory allocation
* This source file is a slight modificattion of the alloc/free system
* described by Kernighan and Ritchie in "The C Programming Language",
* The modifications include allocation by a bestfit (rather than
* firstfit) strategy, and ability to reset memory completely.
/* NOTE: the "afnfree" and "afnused" values are not precise. They
* do not currently refect the allocation and release of headers.
* This will be changed soon (I hope).
#define NULL 0 /* null value */
#define NALLOC 128 /* # of units requested on each "sbrk" */
#define NALLOC 1024 /* lots of memory each time for vaxes */
typedef int ALIGN
; /* force alignment on PDP-11 and VAX */
union header
{ /* free block header structure */
union header
*ptr
; /* next free block */
unsigned size
; /* size of this free block */
ALIGN x
; /* force alignment of blocks */
typedef union header HEADER
;
static HEADER base
; /* empty list to get started */
static HEADER
*allocp
= NULL
; /* last allocated block */
register unsigned nunits
;
/* malloc is a general-purpose memory allocator. It is called
* with the desired number of bytes, expressed as an unsigned
* integer, and it returns the address of the allocated memory.
* If "aftrace" is non-zero, a trace of the allocation will
* be printed. If it is not possible to alloate what is
* requested, the error "workspace exceeded" will result.
* This routine was originally called "alloc" but was changed
* to "malloc" because an increasing number of library routines
* perform dynamic memory allocation. A macro in "apl.h"
* converts calls on "alloc" to calls on "malloc".
nunits
= 1+(nbytes
+sizeof(HEADER
)-1)/sizeof(HEADER
);
base
.s
.ptr
= allocp
= q
= &base
; /* start list */
/* Search list for smallest free block */
for(p
=q
->s
.ptr
;;q
=p
, p
=p
->s
.ptr
){
if (p
->s
.size
>= nunits
){
if ((!rp
) || p
->s
.size
< rp
->s
.size
){
if (p
->s
.size
== nunits
) break;
if ((p
=morecore(nunits
)) == NULL
)
error("workspace exceeded");
/* Allocate memory as needed */
if (rp
->s
.size
== nunits
)
printf("[alloc: %d at %o]\n",
(int)nunits
*sizeof(HEADER
), rp
);
/* Ask system for more memory. Requests are made in blocks
* of NALLOC header units. Returns NULL if request fails,
rnu
= NALLOC
* ((nu
+NALLOC
-1) / NALLOC
);
cp
= sbrk(rnu
* sizeof(HEADER
));
return(NULL
); /* no more space */
printf("[morecore: %d at %o]\n", rnu
*sizeof(HEADER
),
/* Put block into free list. Used by "morecore" to put a newly-
* allocated block of memory into the freelist -- also used to
* return a previously allocated block to the freelist.
p
= (HEADER
*)ap
- 1; /* point to header */
for (q
=allocp
; !(p
> q
&& p
< q
->s
.ptr
); q
=q
->s
.ptr
)
if (q
>= q
->s
.ptr
&& (p
> q
|| p
< q
->s
.ptr
))
if (p
+p
->s
.size
== q
->s
.ptr
){ /* join to upper nbr */
p
->s
.size
+= q
->s
.ptr
->s
.size
;
p
->s
.ptr
= q
->s
.ptr
->s
.ptr
;
if (q
+q
->s
.size
== p
){ /* join to lower nbr */
printf("[free: %d at %o]\n", fsize
*sizeof(HEADER
), ap
);
/* Zap all dynamic allocation by resettting the lists and
* releasing all additional memory.
printf("[afreset: dynamic allocation released]\n");