diff options
Diffstat (limited to 'usr.bin/patch/malloc.c')
-rw-r--r-- | usr.bin/patch/malloc.c | 468 |
1 files changed, 0 insertions, 468 deletions
diff --git a/usr.bin/patch/malloc.c b/usr.bin/patch/malloc.c deleted file mode 100644 index 352eaa04f5b..00000000000 --- a/usr.bin/patch/malloc.c +++ /dev/null @@ -1,468 +0,0 @@ -/* * $OpenBSD: malloc.c,v 1.3 2001/11/19 19:02:15 mpech Exp $*/ -/* - * from: @(#)nmalloc.c 1 (Caltech) 2/21/82 - * - * U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs - * - * Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD. - * - * This is a very fast storage allocator. It allocates blocks of a small - * number of different sizes, and keeps free lists of each size. Blocks - * that don't exactly fit are passed up to the next larger size. In this - * implementation, the available sizes are (2^n)-4 (or -16) bytes long. - * This is designed for use in a program that uses vast quantities of - * memory, but bombs when it runs out. To make it a little better, it - * warns the user when he starts to get near the end. - * - * June 84, ACT: modified rcheck code to check the range given to malloc, - * rather than the range determined by the 2-power used. - * - * Jan 85, RMS: calls malloc_warning to issue warning on nearly full. - * No longer Emacs-specific; can serve as all-purpose malloc for GNU. - * You should call malloc_init to reinitialize after loading dumped Emacs. - * Call malloc_stats to get info on memory stats if MSTATS turned on. - * realloc knows how to return same block given, just changing its size, - * if the power of 2 is correct. - */ - -/* - * nextf[i] is the pointer to the next free block of size 2^(i+3). The - * smallest allocatable block is 8 bytes. The overhead information will - * go in the first int of the block, and the returned pointer will point - * to the second. - * -#ifdef MSTATS - * nmalloc[i] is the difference between the number of mallocs and frees - * for a given block size. -#endif /* MSTATS */ - */ - -#define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */ -#define ISFREE ((char) 0x54) /* magic byte that implies free block */ - /* this is for error checking only */ - -extern char etext; - -/* end of the program; can be changed by calling init_malloc */ -static char *endofpure = &etext; - -#ifdef MSTATS -static int nmalloc[30]; -static int nmal, nfre; -#endif /* MSTATS */ - -/* If range checking is not turned on, all we have is a flag indicating - whether memory is allocated, an index in nextf[], and a size field; to - realloc() memory we copy either size bytes or 1<<(index+3) bytes depending - on whether the former can hold the exact size (given the value of - 'index'). If range checking is on, we always need to know how much space - is allocated, so the 'size' field is never used. */ - -struct mhead { - char mh_alloc; /* ISALLOC or ISFREE */ - char mh_index; /* index in nextf[] */ -/* Remainder are valid only when block is allocated */ - unsigned short mh_size; /* size, if < 0x10000 */ -#ifdef rcheck - unsigned mh_nbytes; /* number of bytes allocated */ - int mh_magic4; /* should be == MAGIC4 */ -#endif /* rcheck */ - }; - -/* Access free-list pointer of a block. - It is stored at block + 4. - This is not a field in the mhead structure - because we want sizeof (struct mhead) - to describe the overhead for when the block is in use, - and we do not want the free-list pointer to count in that. */ - -#define CHAIN(a) \ - (*(struct mhead **) (sizeof (char *) + (char *) (a))) - -#ifdef rcheck - -/* To implement range checking, we write magic values in at the beginning and - end of each allocated block, and make sure they are undisturbed whenever a - free or a realloc occurs. */ -/* Written in each of the 4 bytes following the block's real space */ -#define MAGIC1 0x55 -/* Written in the 4 bytes before the block's real space */ -#define MAGIC4 0x55555555 -#define ASSERT(p) if (!(p)) botch("p"); else -static -botch(s) - char *s; -{ - - printf("assertion botched: %s\n", s); - abort(); -} -#define EXTRA 4 /* 4 bytes extra for MAGIC1s */ -#else -#define ASSERT(p) -#define EXTRA 0 -#endif /* rcheck */ - -/* nextf[i] is free list of blocks of size 2**(i + 3) */ - -static struct mhead *nextf[30]; - -#ifdef M_WARN -/* Number of bytes of writable memory we can expect to be able to get */ -static int lim_data; -/* Level number of warnings already issued. - 0 -- no warnings issued. - 1 -- 75% warning already issued. - 2 -- 85% warning already issued. -*/ -static int warnlevel; -#endif /* M_WARN */ - -/* nonzero once initial bunch of free blocks made */ -static int gotpool; - -/* Cause reinitialization based on job parameters; - also declare where the end of pure storage is. */ -malloc_init (end) - char *end; { - endofpure = end; -#ifdef M_WARN - lim_data = 0; - warnlevel = 0; -#endif /* M_WARN */ - } - -static -morecore (nu) /* ask system for more memory */ - int nu; { /* size index to get more of */ - char *sbrk (); - char *cp; - int nblks; - int siz; - -#ifdef M_WARN -#ifndef BSD42 -#ifdef USG - extern long ulimit (); - if (lim_data == 0) /* find out how much we can get */ - lim_data = ulimit (3, 0) - TEXT_START; -#else /*HMS: was endif */ - if (lim_data == 0) /* find out how much we can get */ - lim_data = vlimit (LIM_DATA, -1); -#endif /* USG */ /HMS:* was not here */ -#else - if (lim_data == 0) { - struct rlimit XXrlimit; - - getrlimit (RLIMIT_DATA, &XXrlimit); - lim_data = XXrlimit.rlim_cur;} /* soft limit */ -#endif /* BSD42 */ -#endif /* M_WARN */ - - /* On initial startup, get two blocks of each size up to 1k bytes */ - if (!gotpool) - getpool (), getpool (), gotpool = 1; - - /* Find current end of memory and issue warning if getting near max */ - - cp = sbrk (0); - siz = cp - endofpure; -#ifdef M_WARN - switch (warnlevel) { - case 0: - if (siz > (lim_data / 4) * 3) { - warnlevel++; - malloc_warning ("Warning: past 75% of memory limit");} - break; - case 1: - if (siz > (lim_data / 20) * 17) { - warnlevel++; - malloc_warning ("Warning: past 85% of memory limit");} - break; - case 2: - if (siz > (lim_data / 20) * 19) { - warnlevel++; - malloc_warning ("Warning: past 95% of memory limit");} - break;} -#endif /* M_WARN */ - - if ((int) cp & 0x3ff) /* land on 1K boundaries */ - sbrk (1024 - ((int) cp & 0x3ff)); - - /* Take at least 2k, and figure out how many blocks of the desired size we're about to get */ - nblks = 1; - if ((siz = nu) < 8) - nblks = 1 << ((siz = 8) - nu); - - if ((cp = sbrk (1 << (siz + 3))) == (char *) -1) - return; /* no more room! */ - if ((int) cp & 7) { /* shouldn't happen, but just in case */ - cp = (char *) (((int) cp + 8) & ~7); - nblks--;} - - /* save new header and link the nblks blocks together */ - nextf[nu] = (struct mhead *) cp; - siz = 1 << (nu + 3); - while (1) { - ((struct mhead *) cp) -> mh_alloc = ISFREE; - ((struct mhead *) cp) -> mh_index = nu; - if (--nblks <= 0) break; - CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz); - cp += siz;} -/* CHAIN ((struct mhead *) cp) = 0; /* since sbrk() returns cleared core, this is already set */ - } - -static -getpool () { - int nu; - char *cp = sbrk (0); - - if ((int) cp & 0x3ff) /* land on 1K boundaries */ - sbrk (1024 - ((int) cp & 0x3ff)); - - /* Get 2k of storage */ - - cp = sbrk (04000); - if (cp == (char *) -1) - return; - - /* Divide it into an initial 8-word block - plus one block of size 2**nu for nu = 3 ... 10. */ - - CHAIN (cp) = nextf[0]; - nextf[0] = (struct mhead *) cp; - ((struct mhead *) cp) -> mh_alloc = ISFREE; - ((struct mhead *) cp) -> mh_index = 0; - cp += 8; - - for (nu = 0; nu < 7; nu++) { - CHAIN (cp) = nextf[nu]; - nextf[nu] = (struct mhead *) cp; - ((struct mhead *) cp) -> mh_alloc = ISFREE; - ((struct mhead *) cp) -> mh_index = nu; - cp += 8 << nu;}} - -char * -malloc (n) /* get a block */ - unsigned n; { - struct mhead *p; - unsigned int nbytes; - int nunits = 0; - - /* Figure out how many bytes are required, rounding up to the nearest - multiple of 4, then figure out which nextf[] area to use */ - nbytes = (n + sizeof *p + EXTRA + 3) & ~3; - { - unsigned int shiftr = (nbytes - 1) >> 2; - - while (shiftr >>= 1) - nunits++; - } - - /* If there are no blocks of the appropriate size, go get some */ - /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ - if (nextf[nunits] == 0) - morecore (nunits); - - /* Get one block off the list, and set the new list head */ - if ((p = nextf[nunits]) == 0) - return 0; - nextf[nunits] = CHAIN (p); - - /* Check for free block clobbered */ - /* If not for this check, we would gobble a clobbered free chain ptr */ - /* and bomb out on the NEXT allocate of this size block */ - if (p -> mh_alloc != ISFREE || p -> mh_index != nunits) -#ifdef rcheck - botch ("block on free list clobbered"); -#else - abort (); -#endif /* rcheck */ - - /* Fill in the info, and if range checking, set up the magic numbers */ - p -> mh_alloc = ISALLOC; -#ifdef rcheck - p -> mh_nbytes = n; - p -> mh_magic4 = MAGIC4; - { - char *m = (char *) (p + 1) + n; - - *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; - } -#else - p -> mh_size = n; -#endif /* rcheck */ -#ifdef MSTATS - nmalloc[nunits]++; - nmal++; -#endif /* MSTATS */ - return (char *) (p + 1);} - -free (mem) - char *mem; { - struct mhead *p; - { - char *ap = mem; - - ASSERT (ap != 0); - p = (struct mhead *) ap - 1; - ASSERT (p -> mh_alloc == ISALLOC); -#ifdef rcheck - ASSERT (p -> mh_magic4 == MAGIC4); - ap += p -> mh_nbytes; - ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); - ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); -#endif /* rcheck */ - } - { - int nunits = p -> mh_index; - - ASSERT (nunits <= 29); - p -> mh_alloc = ISFREE; - CHAIN (p) = nextf[nunits]; - nextf[nunits] = p; -#ifdef MSTATS - nmalloc[nunits]--; - nfre++; -#endif /* MSTATS */ - } - } - -char * -realloc (mem, n) - char *mem; - unsigned n; { - struct mhead *p; - unsigned int tocopy; - int nbytes; - int nunits; - - if ((p = (struct mhead *) mem) == 0) - return malloc (n); - p--; - nunits = p -> mh_index; - ASSERT (p -> mh_alloc == ISALLOC); -#ifdef rcheck - ASSERT (p -> mh_magic4 == MAGIC4); - { - char *m = mem + (tocopy = p -> mh_nbytes); - ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); - ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); - } -#else - if (p -> mh_index >= 13) - tocopy = (1 << (p -> mh_index + 3)) - sizeof *p; - else - tocopy = p -> mh_size; -#endif /* rcheck */ - - /* See if desired size rounds to same power of 2 as actual size. */ - nbytes = (n + sizeof *p + EXTRA + 7) & ~7; - - /* If ok, use the same block, just marking its size as changed. */ - if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) { -#ifdef rcheck - char *m = mem + tocopy; - *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; - p-> mh_nbytes = n; - m = mem + n; - *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; -#else - p -> mh_size = n; -#endif /* rcheck */ - return mem;} - - if (n < tocopy) - tocopy = n; - { - char *new; - void bcopy(); /*HMS: here? */ - - if ((new = malloc (n)) == 0) - return 0; - bcopy (mem, new, tocopy); - free (mem); - return new; - } - } - -#ifdef MSTATS -/* Return statistics describing allocation of blocks of size 2**n. */ - -struct mstats_value { - int blocksize; - int nfree; - int nused; - }; - -struct mstats_value -malloc_stats (size) - int size; { - struct mstats_value v; - int i; - struct mhead *p; - - v.nfree = 0; - - if (size < 0 || size >= 30) { - v.blocksize = 0; - v.nused = 0; - return v;} - - v.blocksize = 1 << (size + 3); - v.nused = nmalloc[size]; - - for (p = nextf[size]; p; p = CHAIN (p)) - v.nfree++; - - return v;} -#endif - -/* how much space is available? */ - -unsigned freespace() { - int i, j; - struct mhead *p; - unsigned space = 0; - int local; /* address only is used */ - - space = (char *)&local - sbrk(0); /* stack space */ - - for (i = 0; i < 30; i++) { - for (j = 0, p = nextf[i]; p; p = CHAIN (p), j++) ; - space += j * (1 << (i + 3));} - - return(space);} - -/* How big is this cell? */ - -unsigned mc_size(cp) - char *cp;{ - struct mhead *p; - - if ((p = (struct mhead *) cp) == 0) { - /*HMS? */ - } - p--; -#ifdef rcheck - return p -> mh_nbytes; -#else - return (1 << (p -> mh_index + 3)) - sizeof *p; -/**/ -/* if (p -> mh_index >= 13) -/* return (1 << (p -> mh_index + 3)) - sizeof *p; -/* else -/* return p -> mh_size; -/**/ -#endif /* rcheck */ - } - -/*HMS: Really should use memcpy, if available... */ - -void bcopy(source, dest, len) - char *source, *dest; - len; { - i; - - for (i = 0; i < len; i++) - *dest++ = *source++;} |