--- ray/src/common/malloc.c 1990/09/26 08:26:11 1.4 +++ ray/src/common/malloc.c 1990/11/13 14:39:05 1.10 @@ -13,20 +13,32 @@ static char SCCSid[] = "$SunId$ LBL"; * bmalloc() doesn't keep track of free lists -- it's usually * just a buffered call to sbrk(2). However, bmalloc will * call mscrounge() if sbrk fails. - * mscrounge() returns whatever memory it can find to satisfy the + * mscrounge() returns whatever free memory it can find to satisfy the * request along with the number of bytes (modified). * * Greg Ward Lawrence Berkeley Laboratory */ +#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 @@ -43,7 +55,9 @@ typedef union m_head { static M_HEAD *free_list[NBUCKETS]; +static char DUMMYLOC[BYTES_WORD]; + char * mscrounge(np) /* search free lists to satisfy request */ register unsigned *np; @@ -58,6 +72,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; @@ -77,6 +94,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 */ @@ -122,8 +142,12 @@ 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)); + bsiz = BYTES_WORD - ((unsigned)p&(BYTES_WORD-1)); if (bsiz < BYTES_WORD) { p += bsiz; n -= bsiz; @@ -144,16 +168,26 @@ char * malloc(n) /* allocate n bytes of memory */ unsigned n; { + extern int errno; register M_HEAD *mp; register int bucket; register unsigned bsiz; - + /* don't return NULL on 0 request */ if (n == 0) - return(NULL); + return(DUMMYLOC); /* find first bucket that fits */ - bucket = FIRSTBUCKET; - for (bsiz = 1<= n) + break; + if (bucket >= NBUCKETS) { + errno = EINVAL; + return(NULL); + } +#ifdef MSTATS + m_nalloced += bsiz + sizeof(M_HEAD); + m_nwasted += bsiz + sizeof(M_HEAD) - n; +#endif if (free_list[bucket] == NULL) { /* need more core */ mp = (M_HEAD *)bmalloc(bsiz+sizeof(M_HEAD)); if (mp == NULL) @@ -169,23 +203,26 @@ unsigned n; char * realloc(op, n) /* reallocate memory using malloc() */ -char *op; +register char *op; unsigned n; { - extern char *memcpy(); - register char *p; + char *p; register unsigned on; - - free(op); /* free it first */ - p = malloc(n); /* p==op if same bucket */ - if (p == NULL) - return(NULL); - if (p != op) /* different bucket, do copy */ + /* get old size */ + if (op != NULL && op != DUMMYLOC) + on = 1 << ((M_HEAD *)op-1)->bucket; + else + on = 0; + if (n <= on && (n > on>>1 || on == 1<on ? on : n); #else (void)memcpy(p, op, n>on ? on : n); #endif + free(op); return(p); } @@ -196,12 +233,15 @@ char *p; register M_HEAD *mp; register int bucket; - if (p == NULL) + if (p == NULL || p == DUMMYLOC) return; mp = (M_HEAD *)p - 1; bucket = mp->bucket; mp->next = free_list[bucket]; free_list[bucket] = mp; +#ifdef MSTATS + m_nfreed += (1 << bucket) + sizeof(M_HEAD); +#endif } @@ -211,14 +251,41 @@ char *p; int getpagesize() /* use SYSV var structure to get page size */ { - static int pagesz = 0; struct var v; - if (pagesz == 0) { - uvar(&v); - pagesz = 1 << v.v_pageshift; - } - return(pagesz); + uvar(&v); + 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<