home *** CD-ROM | disk | FTP | other *** search
- /* $Header: /home/hyperion/mu/christos/src/mine/lib/alloc/RCS/debugalloc.c,v 1.4 1991/05/05 02:49:43 christos Exp $ */
- /*
- *
- * debugalloc.c : Special Debug Malloc Routines
- *
- * Routines:
- * char * DebugMalloc();
- * char * DebugCalloc();
- * char * DebugRealloc();
- * void DebugFree();
- * unsigned DebugMemStat();
- * unsigned DebugMemPtr();
- * void DebugMemChain();
- *
- * $Log: debugalloc.c,v $
- * Revision 1.4 1991/05/05 02:49:43 christos
- * Fixed small lint bug
- *
- * Revision 1.3 1991/04/21 00:14:18 christos
- * Fixed free error message
- *
- * Revision 1.2 1991/02/10 00:44:07 christos
- * Added tests for pointers out of the allocated
- * range
- *
- * Revision 1.1 1991/02/01 08:12:55 christos
- * Initial revision
- *
- */
- #ifndef lint
- static char rcsid[] = "$Id: debugalloc.c,v 1.4 1991/05/05 02:49:43 christos Exp $";
- #endif /* lint */
- #include <stdio.h>
-
- #ifdef __STDC__
- # include <stdlib.h>
- # include <memory.h>
- #else
- extern char *malloc();
- extern char *calloc();
- extern char *realloc();
- extern void free();
- extern void abort();
- extern char *memset();
- extern void exit();
- #endif
-
- #ifndef NIL
- # define NIL(a) ((a *) 0)
- #endif /* NIL */
-
- #ifndef MIN
- # define MIN(a, b) ((a) > (b) ? (b) : (a))
- #endif /* MIN */
-
- #ifndef MAX
- # define MAX(a, b) ((a) < (b) ? (b) : (a))
- #endif /* MAX */
-
- #ifndef private
- # define private static
- #endif /* private */
-
- #ifndef public
- # define public
- #endif /* public */
-
- #define SIG_GOOD 0x01020304
- #define SIG_FREE 0x04030201
- #define SIG_CHAIN 0x44332211
- #define OVERHEAD sizeof(debug_t)
-
-
- #ifdef __STDC__
- typedef void *Ptr;
- #else
- typedef char *Ptr;
- #endif
-
- typedef struct debug_t {
- long d_sign;
- unsigned long d_size;
- char * d_file;
- long d_line;
- union {
- struct {
- struct debug_t *c_prev;
- struct debug_t *c_next;
- } d_c;
- struct {
- char *f_file;
- long f_line;
- } d_f;
- } d_d;
- } debug_t;
-
- #define d_next d_d.d_c.c_next
- #define d_prev d_d.d_c.c_prev
- #define d_ffile d_d.d_f.f_file
- #define d_fline d_d.d_f.f_line
-
-
-
- private unsigned _memused = 0;
- private unsigned _memalloc = 0;
- private Ptr _memtop = (Ptr) 0;
- private Ptr _membot = (Ptr) 0xffffffff;
- private debug_t *chain;
-
-
- /* _chaini():
- * Insert block in chain
- */
- private debug_t *
- _chaini(tptr, n, fname, lineno)
- char **tptr;
- unsigned n;
- char *fname;
- int lineno;
- {
- static debug_t __chain;
- debug_t *dbg;
-
- dbg = (debug_t *) *tptr;
- *tptr += OVERHEAD;
-
- if (chain == NIL(debug_t)) {
- chain = &__chain;
- chain->d_next = chain->d_prev = chain;
- chain->d_sign = SIG_CHAIN;
- chain->d_size = 0;
- chain->d_file = NIL(char);
- chain->d_line = 0;
- }
- dbg->d_sign = SIG_GOOD;
- dbg->d_size = n;
- dbg->d_file = fname;
- dbg->d_line = lineno;
- dbg->d_next = chain->d_next;
- dbg->d_prev = chain;
- chain->d_next->d_prev = dbg;
- chain->d_next = dbg;
- chain = dbg;
- _memused += chain->d_size;
- _memalloc++;
- return(dbg);
- } /* end _chaini */
-
-
- /* _chaina():
- * Allocate a block of the required size
- */
- private Ptr
- _chaina(n, action, routine, fname, lineno, tptr)
- unsigned n;
- char *action;
- Ptr (*routine)();
- char *fname;
- int lineno;
- Ptr tptr;
- {
- char *ptr;
- debug_t *dbg;
-
- if (tptr != (Ptr) 0 && (tptr < _membot || tptr > _memtop ||
- ((int) tptr) & 0x3)) {
- (void) fprintf(stderr, "*** %s, %d: %s invalid pointer.\n",
- fname, lineno, action);
- abort();
- }
- if (n == 0) {
- (void) fprintf(stderr,
- "*** %s, %d: %s zero length block.\n",
- fname, lineno, action);
- if (tptr != (Ptr) 0) {
- dbg = (debug_t *) tptr;
- (void) _chaini((char **) &tptr, (unsigned) dbg->d_size,
- dbg->d_file, (int) dbg->d_line);
- }
- abort();
- }
-
- ptr = (tptr == (Ptr) 0) ? (char *) (*routine)(n+OVERHEAD) :
- (*routine)(tptr, n+OVERHEAD);
-
- _memtop = MAX((Ptr) ptr, _memtop);
- _membot = MIN((Ptr) ptr, _membot);
-
- if (ptr == NIL(char)) {
- (void) fprintf(stderr,
- "*** %s, %d: Out of memory in %s (current allocation %u).\n",
- fname, lineno, action, n);
- if (tptr != (Ptr) 0) {
- dbg = (debug_t *) tptr;
- (void) _chaini((char **) &tptr, (unsigned) dbg->d_size,
- dbg->d_file, (int) dbg->d_line);
- }
- abort();
- }
- return((Ptr) ptr);
- } /* end _chaina */
-
-
- /* _chainf():
- * Free block in chain
- */
- private void
- _chainf(dbg, action, fname, lineno)
- debug_t *dbg;
- char *action;
- char *fname;
- int lineno;
- {
- dbg->d_sign = SIG_FREE;
- if (chain == dbg)
- chain = dbg->d_prev;
- dbg->d_prev->d_next = dbg->d_next;
- dbg->d_next->d_prev = dbg->d_prev;
- dbg->d_ffile = fname;
- dbg->d_fline = lineno;
- _memused -= dbg->d_size;
- _memalloc--;
- } /* end _chainf */
-
-
- /* _chaing():
- * Return the debug header of a chain
- */
- private debug_t *
- _chaing(ptr, action, fname, lineno)
- char **ptr;
- char *action;
- char *fname;
- int lineno;
- {
- if (*ptr == NIL(char)) {
- (void) fprintf(stderr, "**** %s, %d: %s nil pointer.\n",
- fname, lineno, action);
- abort();
- }
- *ptr -= OVERHEAD;
- if ((Ptr) *ptr < _membot || (Ptr) *ptr > _memtop || (((long) *ptr) & 0x3)) {
- (void) fprintf(stderr, "*** %s, %d: %s invalid pointer.\n",
- fname, lineno, action);
- abort();
- }
- return((debug_t *) *ptr);
- } /* end _chaing */
-
-
-
-
- /* _chainc():
- * Check block in chain
- */
- private void
- _chainc(dbg, action, fname, lineno)
- debug_t *dbg;
- char *action;
- char *fname;
- int lineno;
- {
- static char *msg1 = "*** %s, %d: %s %s block";
- static char *msg2 = " [%s, %d: %s]";
-
- switch (dbg->d_sign) {
- case SIG_GOOD:
- break;
- case SIG_FREE:
- (void) fprintf(stderr, msg1, fname, lineno, action, "freed");
- (void) fprintf(stderr, msg2, dbg->d_file, dbg->d_line, "allocated");
- (void) fprintf(stderr, msg2, dbg->d_ffile, dbg->d_fline, "freed");
- abort();
- break;
- default:
- (void) fprintf(stderr, msg1, fname, lineno, action, "invalid");
- (void) fprintf(stderr, ".\n");
- abort();
- break;
- }
- } /* end _chainc */
-
-
- /* DebugMalloc():
- * real alloc
- */
- public Ptr
- DebugMalloc(n, fname, lineno)
- unsigned n;
- char *fname;
- int lineno;
- {
- static char *routine = "malloc";
- Ptr ptr;
-
- ptr = _chaina(n, routine, malloc, fname, lineno, (Ptr) 0);
- (void) _chaini((char **) &ptr, n, fname, lineno);
- return(ptr);
- } /* end DebugMalloc */
-
-
- /* DebugFree():
- * free memory counting the number of bytes freed
- */
- public void
- DebugFree(ptr, fname, lineno)
- Ptr ptr;
- char *fname;
- int lineno;
- {
- static char *routine = "free";
- debug_t *dbg;
-
- dbg = _chaing((char **) &ptr, routine, fname, lineno);
- _chainc(dbg, routine, fname, lineno);
- _chainf(dbg, routine, fname, lineno);
- free(ptr);
- } /* end DebugFree */
-
-
- /* DebugMemStat():
- * return the amount of memory in use
- */
- public unsigned
- DebugMemStat()
- {
- return(_memused);
- } /* end DebugMemStat */
-
-
- /* DebugMemPtr():
- * return the amount of memory in use
- */
- public unsigned
- DebugMemPtr(ptr, fname, lineno)
- Ptr ptr;
- char *fname;
- int lineno;
- {
- static char *routine = "get size";
- debug_t *dbg;
-
- dbg = _chaing((char **) &ptr, routine, fname, lineno);
- _chainc(dbg, routine, fname, lineno);
-
- return((unsigned) dbg->d_size);
- } /* end DebugMemPtr */
-
-
- /* DebugRealloc():
- * real alloc
- */
- public Ptr
- DebugRealloc(ptr, n, fname, lineno)
- Ptr ptr;
- unsigned n;
- char *fname;
- int lineno;
- {
- static char *routine = "realloc";
- debug_t *dbg;
-
- dbg = _chaing((char **) &ptr, routine, fname, lineno);
- _chainc(dbg, routine, fname, lineno);
- _chainf(dbg, routine, fname, lineno);
- ptr = _chaina(n, routine, realloc, fname, lineno, ptr);
- dbg = _chaini((char **) &ptr, n, fname, lineno);
-
- return(ptr);
- } /* end DebugRealloc */
-
-
- /* DebugCalloc():
- * real alloc
- */
- public Ptr
- DebugCalloc(n, sz, fname, lineno)
- unsigned n, sz;
- char *fname;
- int lineno;
- {
- static char *routine = "calloc";
- Ptr ptr;
-
- n *= sz;
- ptr = _chaina(n, routine, malloc, fname, lineno, (Ptr) 0);
- (void) _chaini((char **) &ptr, n, fname, lineno);
- memset((char *) ptr, 0, n);
- return(ptr);
- } /* end DebugCalloc */
-
- /* DebugMemChain():
- * Dump the memory chain
- */
- public void
- DebugMemChain()
- {
- debug_t *dbg;
- unsigned min, max;
-
- max = 0x00000000;
- min = 0xffffffff;
-
- if (chain == NIL(debug_t) || chain->d_sign == SIG_CHAIN) {
- (void) fprintf(stdout, "\tNo memory allocated.\n");
- return;
- }
- (void) fprintf(stdout, "\tMemory Allocation Statistics.\n");
- (void) fprintf(stdout, "\t%u bytes allocated in %u chunks.\n",
- _memused, _memalloc);
- for (dbg = chain; dbg->d_sign != SIG_CHAIN; dbg = dbg->d_next);
- (void) fprintf(stdout, "\t%8.8s %8.8s %20.20s %5.5s\n",
- "Address", "Size", "Filename", "Line");
- for (dbg = dbg->d_next; dbg->d_sign != SIG_CHAIN; dbg = dbg->d_next) {
- (void) fprintf(stdout, "\t%.8x %8d %20.20s %5d\n",
- dbg, dbg->d_size, dbg->d_file, dbg->d_line);
- min = MIN(min, dbg->d_size);
- max = MAX(max, dbg->d_size);
- }
- (void) fprintf(stdout, "\tMin %u Max %u Avg %u.\n",
- min, max, _memused / _memalloc);
- } /* end DebugMemChain */
-