--- ray/src/common/malloc.c 1990/10/03 16:20:38 1.8 +++ ray/src/common/malloc.c 1991/04/02 09:36:21 1.12 @@ -1,4 +1,4 @@ -/* Copyright (c) 1990 Regents of the University of California */ +/* Copyright (c) 1991 Regents of the University of California */ #ifndef lint static char SCCSid[] = "$SunId$ LBL"; @@ -21,31 +21,50 @@ static char SCCSid[] = "$SunId$ LBL"; #include +#ifdef MSTATS +#include +static unsigned b_nalloced = 0; +static unsigned b_nfreed = 0; +static unsigned b_nscrounged = 0; +static unsigned m_nalloced = 0; +static unsigned m_nfreed = 0; +static unsigned m_nwasted = 0; +#else #define NULL 0 +#endif #ifndef ALIGN #define ALIGN int /* align type */ #endif #define BYTES_WORD sizeof(ALIGN) -#define MAXINCR (1<<18) /* largest sbrk(2) increment */ +#define MAXINCR (1<<16) /* largest sbrk(2) increment */ #ifdef NOVMEM -#define getpagesize() BYTES_WORD +#define getpagesize() 1024 #endif /* malloc free lists */ typedef union m_head { union m_head *next; - int bucket; + struct { + short magic; + short bucket; + } a; ALIGN dummy; } M_HEAD; +#define MAGIC 0x1a2 /* magic number for allocated memory */ + #define FIRSTBUCKET 3 #define NBUCKETS 30 static M_HEAD *free_list[NBUCKETS]; +static ALIGN dummy_mem; +#define DUMMYLOC ((char *)&dummy_mem) + + char * mscrounge(np) /* search free lists to satisfy request */ register unsigned *np; @@ -60,6 +79,9 @@ register unsigned *np; *np = bsiz+sizeof(M_HEAD); p = (char *)free_list[bucket]; free_list[bucket] = free_list[bucket]->next; +#ifdef MSTATS + b_nscrounged += *np; +#endif return(p); } *np = 0; @@ -79,6 +101,9 @@ register unsigned n; unsigned thisamnt; register char *p; +#ifdef MSTATS + b_nalloced += n; +#endif if (pagesz == 0) { /* initialize */ pagesz = amnt = getpagesize(); nrem = (int)sbrk(0); /* page align break */ @@ -124,6 +149,10 @@ register unsigned n; { register int bucket; register unsigned bsiz; + +#ifdef MSTATS + b_nfreed += n; +#endif /* align pointer */ bsiz = BYTES_WORD - ((unsigned)p&(BYTES_WORD-1)); if (bsiz < BYTES_WORD) { @@ -150,6 +179,9 @@ unsigned n; register M_HEAD *mp; register int bucket; register unsigned bsiz; + /* don't return NULL on 0 request */ + if (n == 0) + return(DUMMYLOC); /* find first bucket that fits */ for (bucket = FIRSTBUCKET, bsiz = 1<next; } - mp->bucket = bucket; /* tag block */ + mp->a.magic = MAGIC; /* tag block */ + mp->a.bucket = bucket; return((char *)(mp+1)); } @@ -180,8 +217,8 @@ unsigned n; char *p; register unsigned on; /* get old size */ - if (op != NULL) - on = 1 << ((M_HEAD *)op-1)->bucket; + if (op != NULL && op != DUMMYLOC && ((M_HEAD *)op-1)->a.magic == MAGIC) + on = 1 << ((M_HEAD *)op-1)->a.bucket; else on = 0; if (n <= on && (n > on>>1 || on == 1<bucket; + if (mp->a.magic != MAGIC) /* sanity check */ + return; + bucket = mp->a.bucket; mp->next = free_list[bucket]; free_list[bucket] = mp; +#ifdef MSTATS + m_nfreed += (1 << bucket) + sizeof(M_HEAD); +#endif } @@ -225,4 +267,35 @@ getpagesize() /* use SYSV var structure to get page return(1 << v.v_pageshift); } #endif +#endif + + +#ifdef MSTATS +printmemstats(fp) /* print memory statistics to stream */ +FILE *fp; +{ + register int i; + int n; + register M_HEAD *mp; + unsigned int total = 0; + + fprintf(fp, "Memory statistics:\n"); + fprintf(fp, "\tbmalloc: %d bytes allocated\n", b_nalloced); + fprintf(fp, "\tbmalloc: %d bytes freed\n", b_nfreed); + fprintf(fp, "\tbmalloc: %d bytes scrounged\n", b_nscrounged); + fprintf(fp, "\tmalloc: %d bytes allocated\n", m_nalloced); + fprintf(fp, "\tmalloc: %d bytes wasted (%.1f%%)\n", m_nwasted, + 100.0*m_nwasted/m_nalloced); + fprintf(fp, "\tmalloc: %d bytes freed\n", m_nfreed); + for (i = NBUCKETS-1; i >= FIRSTBUCKET; i--) { + n = 0; + for (mp = free_list[i]; mp != NULL; mp = mp->next) + n++; + if (n) { + fprintf(fp, "\t%d * %u\n", n, 1<