[net.sources] 4.2 malloc test program and commentary

jpl@allegra.UUCP (John P. Linderman) (09/17/85)

If you have been following the discussion about the 4.2 malloc
refusing to break up large areas of free space to avoid failing
on small allocations, then you may find the test program and
commentary useful or at least enlightening.  My apologies to
those who don't care.

John P. Linderman  allegra!jpl

# To unbundle, delete any lines before this one and sh this file.
echo unbundling README
#################### README Tue Sep 17 15:47:46 EDT 1985 ####################
sed -e 's/.//' > README <<'John P. Linderman allegra!jpl MH3D-435 x6427'
XThe accompanying C program (talloc.c) can be used to interact with
Xthe storage allocation routines (malloc and friends).  A simple
Xinterface allows users to allocate, free and reallocate storage,
Xand to print a simple summary of current allocations.  Commands
Xare read from the standard input, and consist of single letters
Xfollowed by 0 to 2 numbers.  Pointers to allocated storage are
Xkept in an array, and the index of each allocation is reported
Xwhen the allocation occurs so the associated storage can be freed
Xor reallocated.  A ``default'' allocation size is initialized to
X4000000 bytes, and is reset by each allocation or reallocation
Xcommand.  Commands are as follows.
X
Xa [N]	Attempt to allocate storage.  If a positive number is
X	specified with the command, it becomes the new default
X	allocation size.  In any event, an attempt is made to
X	allocate the default allocation size.  If successful,
X	the index of the pointer to the storage and the base
X	address of the storage are reported.
X
Xf I	Free the storage indexed by the specified number.
X	The index is reported when allocations are made,
X	or when allocations are summarized using...
X
Xs	Summarize all outstanding allocations, reporting index,
X	size and base address.
X
Xr I [N]	Reallocate the storage indexed by I.  If a second
X	number is present, it becomes the new default allocation.
X	In any event, an attempt is made to reallocate the
X	default allocation.  If successful, the old and new
X	sizes and base addresses are reported.  The storage
X	continues to be indexed by I.
X
Xq	Quit.
X
X?	Print a short command summary.
X
XAn annotated session demonstrating the commands, the quirk in 4.2
Xmalloc as delivered, and the fixes posted earlier, follows.  The
Xkernel crash that I observed seems to be due to an rmalloc()
Xbug that was reported (and fixed) by Dave Mason at the University
Xof Calgary.  If you do get a panic: sleep or panic: trap while
Xrunning the tests, get hold of the fixes before trying again.
X
X
X% cc talloc.c -o talloc
X% talloc
Xa				# keep going after 4 million ...
X0: 4000000 bytes at 0x8004
Xa
X1: 4000000 bytes at 0x408004
Xa
X2: 4000000 bytes at 0x808004
Xa
X3: 4000000 bytes at 0xc08004
Xa				# ... until we run out
XOut of space looking for 4000000 bytes
Xa 2000000			# repeat for 2 million ...
X4: 2000000 bytes at 0x1008004
Xa 1000000			# ... and for 1 million
X5: 1000000 bytes at 0x1208004
Xa
XOut of space looking for 1000000 bytes
Xs				# summarize what we got
X      0:   4000000 bytes at 0x8004
X      1:   4000000 bytes at 0x408004
X      2:   4000000 bytes at 0x808004
X      3:   4000000 bytes at 0xc08004
X      4:   2000000 bytes at 0x1008004
X      5:   1000000 bytes at 0x1208004
Xf				# give back 4 million
X0: 4000000 bytes at 0x8004
Xa				# now try for a mere million
XOut of space looking for 1000000 bytes
Xq				# Rats, foiled.
X% cc talloc.c malloc.c -o talloc
Xtalloc.c:
Xmalloc.c:
X% talloc
X[Same as above]
Xs
X      0:   4000000 bytes at 0x8004
X      1:   4000000 bytes at 0x408004
X      2:   4000000 bytes at 0x808004
X      3:   4000000 bytes at 0xc08004
X      4:   2000000 bytes at 0x1008004
X      5:   1000000 bytes at 0x1208004
Xa
XOut of space looking for 1000000 bytes
Xf 0
X0: 4000000 bytes at 0x8004
Xa				# try to recover what was returned
X0: 1000000 bytes at 0x208004
Xq				# that's more like it
John P. Linderman allegra!jpl MH3D-435 x6427
echo unbundling talloc.c
#################### talloc.c Tue Sep 17 15:47:48 EDT 1985 ####################
sed -e 's/.//' > talloc.c <<'John P. Linderman allegra!jpl MH3D-435 x6427'
X#include <stdio.h>
X#include <ctype.h>
X
X#ifndef ASLOTS
X#define ASLOTS 1000
X#endif
X
Xchar *Me;
X
Xstruct {
X    char *p;
X    int z;
X} a[ASLOTS];
X
X#define SKIP(p) while (isspace(*p)) p++
X
Xchar *
Xcvnum(p, np)
X    register char *p;
X    int *np;
X{
X    register int n;
X
X    SKIP(p);
X    if (isdigit(*p))
X	for (n = 0; isdigit(*p);)
X	    n = 10 * n + *p++ - '0';
X    else    n = -1;
X    *np = n;
X    return (p);
X}
X
Xint
Xfindex()
X{
X    register int i;
X
X    for (i = 0; i < ASLOTS; i++) {
X	if (a[i].z == 0)
X	    return (i);
X    }
X    (void) fprintf(stderr, "%s: %s %s %d\n",
X		    Me,
X		    "Pointer table full -- do some frees",
X		    "or recompile with ASLOTS >",
X		    ASLOTS);
X    return (-1);
X}
X
Xmain(argc, argv)
X    int argc;
X    char **argv;
X{
X    register char *p;
X    register int i;
X    char buf[256], *malloc(), *realloc(), *gets();
X    int n, last = 4000000;
X
X    Me = argv[0];
X    while (gets(buf)) {
X	p = buf;
X	SKIP(p);
X	switch (*p) {
X	case 'a':   /* allocate: n, or last allocation; report index */
X	    if ((i = findex()) < 0) continue;
X	    (void) cvnum(p+1, &n);
X	    if (n > 0) last = n;
X	    if (p = malloc(last)) {
X		(void) printf("%d: %d bytes at %#x\n", i, last, p);
X		a[i].p = p;
X		a[i].z = last;
X	    } else {
X		(void) printf("Out of space looking for %d bytes\n", last);
X	    }
X	    break;
X	case 'f':
X	    (void) cvnum(p+1, &n);
X	    i = n;
X	    if ((i < 0) || (i >= ASLOTS) || (a[i].z == 0)) {
X		(void) printf("Slot invalid or already free\n");
X	    } else {
X		free(p = a[i].p);
X		(void) printf("%d: %d bytes at %#x\n", i, a[i].z, p);
X		a[i].z = 0;
X		a[i].p = NULL;
X	    }
X	    break;
X	case 'r':
X	    p = cvnum(p+1, &n);
X	    i = n;
X	    if ((i < 0) || (i >= ASLOTS) || (a[i].z == 0)) {
X		(void) printf("Slot invalid or free\n");
X	    } else {
X		(void) cvnum(p, &n);
X		if (n > 0) last = n;
X		if (p = realloc(p, last)) {
X		    (void) printf("%d: %d=>%d bytes from %#x to %#x\n",
X			i, a[i].z, last, a[i].p, p);
X		    a[i].p = p;
X		    a[i].z = last;
X		} else {
X		    (void) printf("Out of space looking for %d bytes\n", last);
X		}
X	    }
X	    break;
X	case 's':
X	    for (i = 0; i < ASLOTS; i++) {
X		if (a[i].z) {
X		    (void) printf("%7d: %9d bytes at %#x\n",
X			i, a[i].z, a[i].p);
X		}
X	    }
X	    break;
X	case 'q':
X	    exit(0);
X	case '?':
X	    (void) printf("a [N] => allocate N bytes, report index\n");
X	    (void) printf("f index => free space at index\n");
X	    (void) printf("r index [N] => reallocate N bytes at index\n");
X	    (void) printf("s => print summary of allocated storage\n");
X	    (void) printf("q => quit\n");
X	    (void) printf("? => print this helpful summary\n");
X	    break;
X	default:
X	    (void) fprintf(stderr, "%s: %s %s\n",
X		Me, "Unrecognized command --",
X		"enter ? for help");
X	}
X    }
X}
John P. Linderman allegra!jpl MH3D-435 x6427
exit 0