Annotation of 43BSDReno/contrib/emacs-18.55/src/malloc.c, revision 1.1

1.1     ! root        1: /* dynamic memory allocation for GNU.
        !             2:    Copyright (C) 1985, 1987 Free Software Foundation, Inc.
        !             3: 
        !             4:                       NO WARRANTY
        !             5: 
        !             6:   BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
        !             7: NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
        !             8: WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
        !             9: RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
        !            10: WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
        !            11: BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
        !            12: FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
        !            13: AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
        !            14: DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
        !            15: CORRECTION.
        !            16: 
        !            17:  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
        !            18: STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
        !            19: WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
        !            20: LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
        !            21: OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
        !            22: USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
        !            23: DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
        !            24: A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
        !            25: PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
        !            26: DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
        !            27: 
        !            28:                GENERAL PUBLIC LICENSE TO COPY
        !            29: 
        !            30:   1. You may copy and distribute verbatim copies of this source file
        !            31: as you receive it, in any medium, provided that you conspicuously and
        !            32: appropriately publish on each copy a valid copyright notice "Copyright
        !            33: (C) 1985 Free Software Foundation, Inc."; and include following the
        !            34: copyright notice a verbatim copy of the above disclaimer of warranty
        !            35: and of this License.  You may charge a distribution fee for the
        !            36: physical act of transferring a copy.
        !            37: 
        !            38:   2. You may modify your copy or copies of this source file or
        !            39: any portion of it, and copy and distribute such modifications under
        !            40: the terms of Paragraph 1 above, provided that you also do the following:
        !            41: 
        !            42:     a) cause the modified files to carry prominent notices stating
        !            43:     that you changed the files and the date of any change; and
        !            44: 
        !            45:     b) cause the whole of any work that you distribute or publish,
        !            46:     that in whole or in part contains or is a derivative of this
        !            47:     program or any part thereof, to be licensed at no charge to all
        !            48:     third parties on terms identical to those contained in this
        !            49:     License Agreement (except that you may choose to grant more extensive
        !            50:     warranty protection to some or all third parties, at your option).
        !            51: 
        !            52:     c) You may charge a distribution fee for the physical act of
        !            53:     transferring a copy, and you may at your option offer warranty
        !            54:     protection in exchange for a fee.
        !            55: 
        !            56: Mere aggregation of another unrelated program with this program (or its
        !            57: derivative) on a volume of a storage or distribution medium does not bring
        !            58: the other program under the scope of these terms.
        !            59: 
        !            60:   3. You may copy and distribute this program (or a portion or derivative
        !            61: of it, under Paragraph 2) in object code or executable form under the terms
        !            62: of Paragraphs 1 and 2 above provided that you also do one of the following:
        !            63: 
        !            64:     a) accompany it with the complete corresponding machine-readable
        !            65:     source code, which must be distributed under the terms of
        !            66:     Paragraphs 1 and 2 above; or,
        !            67: 
        !            68:     b) accompany it with a written offer, valid for at least three
        !            69:     years, to give any third party free (except for a nominal
        !            70:     shipping charge) a complete machine-readable copy of the
        !            71:     corresponding source code, to be distributed under the terms of
        !            72:     Paragraphs 1 and 2 above; or,
        !            73: 
        !            74:     c) accompany it with the information you received as to where the
        !            75:     corresponding source code may be obtained.  (This alternative is
        !            76:     allowed only for noncommercial distribution and only if you
        !            77:     received the program in object code or executable form alone.)
        !            78: 
        !            79: For an executable file, complete source code means all the source code for
        !            80: all modules it contains; but, as a special exception, it need not include
        !            81: source code for modules which are standard libraries that accompany the
        !            82: operating system on which the executable file runs.
        !            83: 
        !            84:   4. You may not copy, sublicense, distribute or transfer this program
        !            85: except as expressly provided under this License Agreement.  Any attempt
        !            86: otherwise to copy, sublicense, distribute or transfer this program is void and
        !            87: your rights to use the program under this License agreement shall be
        !            88: automatically terminated.  However, parties who have received computer
        !            89: software programs from you with this License Agreement will not have
        !            90: their licenses terminated so long as such parties remain in full compliance.
        !            91: 
        !            92:   5. If you wish to incorporate parts of this program into other free
        !            93: programs whose distribution conditions are different, write to the Free
        !            94: Software Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet
        !            95: worked out a simple rule that can be stated here, but we will often permit
        !            96: this.  We will be guided by the two goals of preserving the free status of
        !            97: all derivatives of our free software and of promoting the sharing and reuse of
        !            98: software.
        !            99: 
        !           100: 
        !           101: In other words, you are welcome to use, share and improve this program.
        !           102: You are forbidden to forbid anyone else to use, share and improve
        !           103: what you give them.   Help stamp out software-hoarding!  */
        !           104: 
        !           105: 
        !           106: /*
        !           107:  * @(#)nmalloc.c 1 (Caltech) 2/21/82
        !           108:  *
        !           109:  *     U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs
        !           110:  *
        !           111:  *     Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD.
        !           112:  *
        !           113:  * This is a very fast storage allocator.  It allocates blocks of a small 
        !           114:  * number of different sizes, and keeps free lists of each size.  Blocks
        !           115:  * that don't exactly fit are passed up to the next larger size.  In this 
        !           116:  * implementation, the available sizes are (2^n)-4 (or -16) bytes long.
        !           117:  * This is designed for use in a program that uses vast quantities of
        !           118:  * memory, but bombs when it runs out.  To make it a little better, it
        !           119:  * warns the user when he starts to get near the end.
        !           120:  *
        !           121:  * June 84, ACT: modified rcheck code to check the range given to malloc,
        !           122:  * rather than the range determined by the 2-power used.
        !           123:  *
        !           124:  * Jan 85, RMS: calls malloc_warning to issue warning on nearly full.
        !           125:  * No longer Emacs-specific; can serve as all-purpose malloc for GNU.
        !           126:  * You should call malloc_init to reinitialize after loading dumped Emacs.
        !           127:  * Call malloc_stats to get info on memory stats if MSTATS turned on.
        !           128:  * realloc knows how to return same block given, just changing its size,
        !           129:  * if the power of 2 is correct.
        !           130:  */
        !           131: 
        !           132: /*
        !           133:  * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
        !           134:  * smallest allocatable block is 8 bytes.  The overhead information will
        !           135:  * go in the first int of the block, and the returned pointer will point
        !           136:  * to the second.
        !           137:  *
        !           138: #ifdef MSTATS
        !           139:  * nmalloc[i] is the difference between the number of mallocs and frees
        !           140:  * for a given block size.
        !           141: #endif MSTATS
        !           142:  */
        !           143: 
        !           144: #ifdef emacs
        !           145: /* config.h specifies which kind of system this is.  */
        !           146: #include "config.h"
        !           147: #else
        !           148: 
        !           149: /* Determine which kind of system this is.  */
        !           150: #include <signal.h>
        !           151: #ifndef SIGTSTP
        !           152: #ifndef VMS
        !           153: #ifndef USG
        !           154: #define USG
        !           155: #endif
        !           156: #endif /* not VMS */
        !           157: #else /* SIGTSTP */
        !           158: #ifdef SIGIO
        !           159: #define BSD4_2
        !           160: #endif /* SIGIO */
        !           161: #endif /* SIGTSTP */
        !           162: 
        !           163: #endif /* not emacs */
        !           164: 
        !           165: /* Define getpagesize () if the system does not.  */
        !           166: #include "getpagesize.h"
        !           167: 
        !           168: #ifndef BSD4_2
        !           169: #ifndef USG
        !           170: #include <sys/vlimit.h>                /* warn the user when near the end */
        !           171: #endif /* not USG */
        !           172: #else /* if BSD4_2 */
        !           173: #include <sys/time.h>
        !           174: #include <sys/resource.h>
        !           175: #endif /* BSD4_2 */
        !           176: 
        !           177: extern char *start_of_data ();
        !           178: 
        !           179: #ifdef BSD
        !           180: #ifndef DATA_SEG_BITS
        !           181: #define start_of_data() &etext
        !           182: #endif
        !           183: #endif
        !           184: 
        !           185: #ifndef emacs
        !           186: #define start_of_data() &etext
        !           187: #endif
        !           188: 
        !           189: #define ISALLOC ((char) 0xf7)  /* magic byte that implies allocation */
        !           190: #define ISFREE ((char) 0x54)   /* magic byte that implies free block */
        !           191:                                /* this is for error checking only */
        !           192: #define ISMEMALIGN ((char) 0xd6)  /* Stored before the value returned by
        !           193:                                     memalign, with the rest of the word
        !           194:                                     being the distance to the true
        !           195:                                     beginning of the block.  */
        !           196: 
        !           197: extern char etext;
        !           198: 
        !           199: /* These two are for user programs to look at, when they are interested.  */
        !           200: 
        !           201: unsigned int malloc_sbrk_used;       /* amount of data space used now */
        !           202: unsigned int malloc_sbrk_unused;     /* amount more we can have */
        !           203: 
        !           204: /* start of data space; can be changed by calling init_malloc */
        !           205: static char *data_space_start;
        !           206: 
        !           207: #ifdef MSTATS
        !           208: static int nmalloc[30];
        !           209: static int nmal, nfre;
        !           210: #endif /* MSTATS */
        !           211: 
        !           212: /* If range checking is not turned on, all we have is a flag indicating
        !           213:    whether memory is allocated, an index in nextf[], and a size field; to
        !           214:    realloc() memory we copy either size bytes or 1<<(index+3) bytes depending
        !           215:    on whether the former can hold the exact size (given the value of
        !           216:    'index').  If range checking is on, we always need to know how much space
        !           217:    is allocated, so the 'size' field is never used. */
        !           218: 
        !           219: struct mhead {
        !           220:        char     mh_alloc;      /* ISALLOC or ISFREE */
        !           221:        char     mh_index;      /* index in nextf[] */
        !           222: /* Remainder are valid only when block is allocated */
        !           223:        unsigned short mh_size; /* size, if < 0x10000 */
        !           224: #ifdef rcheck
        !           225:        unsigned mh_nbytes;     /* number of bytes allocated */
        !           226:        int      mh_magic4;     /* should be == MAGIC4 */
        !           227: #endif /* rcheck */
        !           228: };
        !           229: 
        !           230: /* Access free-list pointer of a block.
        !           231:   It is stored at block + 4.
        !           232:   This is not a field in the mhead structure
        !           233:   because we want sizeof (struct mhead)
        !           234:   to describe the overhead for when the block is in use,
        !           235:   and we do not want the free-list pointer to count in that.  */
        !           236: 
        !           237: #define CHAIN(a) \
        !           238:   (*(struct mhead **) (sizeof (char *) + (char *) (a)))
        !           239: 
        !           240: #ifdef rcheck
        !           241: 
        !           242: /* To implement range checking, we write magic values in at the beginning and
        !           243:    end of each allocated block, and make sure they are undisturbed whenever a
        !           244:    free or a realloc occurs. */
        !           245: /* Written in each of the 4 bytes following the block's real space */
        !           246: #define MAGIC1 0x55
        !           247: /* Written in the 4 bytes before the block's real space */
        !           248: #define MAGIC4 0x55555555
        !           249: #define ASSERT(p) if (!(p)) botch("p"); else
        !           250: #define EXTRA  4               /* 4 bytes extra for MAGIC1s */
        !           251: #else
        !           252: #define ASSERT(p)
        !           253: #define EXTRA  0
        !           254: #endif /* rcheck */
        !           255: 
        !           256: 
        !           257: /* nextf[i] is free list of blocks of size 2**(i + 3)  */
        !           258: 
        !           259: static struct mhead *nextf[30];
        !           260: 
        !           261: /* busy[i] is nonzero while allocation of block size i is in progress.  */
        !           262: 
        !           263: static char busy[30];
        !           264: 
        !           265: /* Number of bytes of writable memory we can expect to be able to get */
        !           266: static unsigned int lim_data;
        !           267: 
        !           268: /* Level number of warnings already issued.
        !           269:   0 -- no warnings issued.
        !           270:   1 -- 75% warning already issued.
        !           271:   2 -- 85% warning already issued.
        !           272: */
        !           273: static int warnlevel;
        !           274: 
        !           275: /* Function to call to issue a warning;
        !           276:    0 means don't issue them.  */
        !           277: static void (*warnfunction) ();
        !           278: 
        !           279: /* nonzero once initial bunch of free blocks made */
        !           280: static int gotpool;
        !           281: 
        !           282: char *_malloc_base;
        !           283: 
        !           284: static void getpool ();
        !           285: 
        !           286: /* Cause reinitialization based on job parameters;
        !           287:   also declare where the end of pure storage is. */
        !           288: void
        !           289: malloc_init (start, warnfun)
        !           290:      char *start;
        !           291:      void (*warnfun) ();
        !           292: {
        !           293:   if (start)
        !           294:     data_space_start = start;
        !           295:   lim_data = 0;
        !           296:   warnlevel = 0;
        !           297:   warnfunction = warnfun;
        !           298: }
        !           299: 
        !           300: /* Return the maximum size to which MEM can be realloc'd
        !           301:    without actually requiring copying.  */
        !           302: 
        !           303: int
        !           304: malloc_usable_size (mem)
        !           305:      char *mem;
        !           306: {
        !           307:   int blocksize = 8 << (((struct mhead *) mem) - 1) -> mh_index;
        !           308: 
        !           309:   return blocksize - sizeof (struct mhead) - EXTRA;
        !           310: }
        !           311: 
        !           312: static void
        !           313: morecore (nu)                  /* ask system for more memory */
        !           314:      register int nu;          /* size index to get more of  */
        !           315: {
        !           316:   char *sbrk ();
        !           317:   register char *cp;
        !           318:   register int nblks;
        !           319:   register unsigned int siz;
        !           320:   int oldmask;
        !           321: 
        !           322: #ifdef BSD
        !           323: #ifndef BSD4_1
        !           324:   /* ?? There was a suggestion not to block SIGILL, somehow for GDB's sake.  */
        !           325:   oldmask = sigsetmask (-1);
        !           326: #endif
        !           327: #endif
        !           328: 
        !           329:   if (!data_space_start)
        !           330:     {
        !           331:       data_space_start = start_of_data ();
        !           332:     }
        !           333: 
        !           334:   if (lim_data == 0)
        !           335:     get_lim_data ();
        !           336: 
        !           337:  /* On initial startup, get two blocks of each size up to 1k bytes */
        !           338:   if (!gotpool)
        !           339:     { getpool (); getpool (); gotpool = 1; }
        !           340: 
        !           341:   /* Find current end of memory and issue warning if getting near max */
        !           342: 
        !           343: #ifndef VMS
        !           344:   /* Maximum virtual memory on VMS is difficult to calculate since it
        !           345:    * depends on several dynmacially changing things. Also, alignment
        !           346:    * isn't that important. That is why much of the code here is ifdef'ed
        !           347:    * out for VMS systems.
        !           348:    */
        !           349:   cp = sbrk (0);
        !           350:   siz = cp - data_space_start;
        !           351: 
        !           352:   if (warnfunction)
        !           353:     switch (warnlevel)
        !           354:       {
        !           355:       case 0: 
        !           356:        if (siz > (lim_data / 4) * 3)
        !           357:          {
        !           358:            warnlevel++;
        !           359:            (*warnfunction) ("Warning: past 75% of memory limit");
        !           360:          }
        !           361:        break;
        !           362:       case 1: 
        !           363:        if (siz > (lim_data / 20) * 17)
        !           364:          {
        !           365:            warnlevel++;
        !           366:            (*warnfunction) ("Warning: past 85% of memory limit");
        !           367:          }
        !           368:        break;
        !           369:       case 2: 
        !           370:        if (siz > (lim_data / 20) * 19)
        !           371:          {
        !           372:            warnlevel++;
        !           373:            (*warnfunction) ("Warning: past 95% of memory limit");
        !           374:          }
        !           375:        break;
        !           376:       }
        !           377: 
        !           378:   if ((int) cp & 0x3ff)        /* land on 1K boundaries */
        !           379:     sbrk (1024 - ((int) cp & 0x3ff));
        !           380: #endif /* not VMS */
        !           381: 
        !           382:  /* Take at least 2k, and figure out how many blocks of the desired size
        !           383:     we're about to get */
        !           384:   nblks = 1;
        !           385:   if ((siz = nu) < 8)
        !           386:     nblks = 1 << ((siz = 8) - nu);
        !           387: 
        !           388:   if ((cp = sbrk (1 << (siz + 3))) == (char *) -1)
        !           389:     {
        !           390: #ifdef BSD
        !           391: #ifndef BSD4_1
        !           392:       sigsetmask (oldmask);
        !           393: #endif
        !           394: #endif
        !           395:       return;                  /* no more room! */
        !           396:     }
        !           397:   malloc_sbrk_used = siz;
        !           398:   malloc_sbrk_unused = lim_data - siz;
        !           399: 
        !           400: #ifndef VMS
        !           401:   if ((int) cp & 7)
        !           402:     {          /* shouldn't happen, but just in case */
        !           403:       cp = (char *) (((int) cp + 8) & ~7);
        !           404:       nblks--;
        !           405:     }
        !           406: #endif /* not VMS */
        !           407: 
        !           408:  /* save new header and link the nblks blocks together */
        !           409:   nextf[nu] = (struct mhead *) cp;
        !           410:   siz = 1 << (nu + 3);
        !           411:   while (1)
        !           412:     {
        !           413:       ((struct mhead *) cp) -> mh_alloc = ISFREE;
        !           414:       ((struct mhead *) cp) -> mh_index = nu;
        !           415:       if (--nblks <= 0) break;
        !           416:       CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz);
        !           417:       cp += siz;
        !           418:     }
        !           419:   CHAIN ((struct mhead *) cp) = 0;
        !           420: 
        !           421: #ifdef BSD
        !           422: #ifndef BSD4_1
        !           423:   sigsetmask (oldmask);
        !           424: #endif
        !           425: #endif
        !           426: }
        !           427: 
        !           428: static void
        !           429: getpool ()
        !           430: {
        !           431:   register int nu;
        !           432:   char * sbrk ();
        !           433:   register char *cp = sbrk (0);
        !           434: 
        !           435:   if ((int) cp & 0x3ff)        /* land on 1K boundaries */
        !           436:     sbrk (1024 - ((int) cp & 0x3ff));
        !           437: 
        !           438:   /* Record address of start of space allocated by malloc.  */
        !           439:   if (_malloc_base == 0)
        !           440:     _malloc_base = cp;
        !           441: 
        !           442:   /* Get 2k of storage */
        !           443: 
        !           444:   cp = sbrk (04000);
        !           445:   if (cp == (char *) -1)
        !           446:     return;
        !           447: 
        !           448:   /* Divide it into an initial 8-word block
        !           449:      plus one block of size 2**nu for nu = 3 ... 10.  */
        !           450: 
        !           451:   CHAIN (cp) = nextf[0];
        !           452:   nextf[0] = (struct mhead *) cp;
        !           453:   ((struct mhead *) cp) -> mh_alloc = ISFREE;
        !           454:   ((struct mhead *) cp) -> mh_index = 0;
        !           455:   cp += 8;
        !           456: 
        !           457:   for (nu = 0; nu < 7; nu++)
        !           458:     {
        !           459:       CHAIN (cp) = nextf[nu];
        !           460:       nextf[nu] = (struct mhead *) cp;
        !           461:       ((struct mhead *) cp) -> mh_alloc = ISFREE;
        !           462:       ((struct mhead *) cp) -> mh_index = nu;
        !           463:       cp += 8 << nu;
        !           464:     }
        !           465: }
        !           466: 
        !           467: char *
        !           468: malloc (n)             /* get a block */
        !           469:      unsigned n;
        !           470: {
        !           471:   register struct mhead *p;
        !           472:   register unsigned int nbytes;
        !           473:   register int nunits = 0;
        !           474: 
        !           475:   /* Figure out how many bytes are required, rounding up to the nearest
        !           476:      multiple of 8, then figure out which nestf[] area to use.
        !           477:      Both the beginning of the header and the beginning of the
        !           478:      block should be on an eight byte boundary.  */
        !           479:   nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7;
        !           480:   {
        !           481:     register unsigned int   shiftr = (nbytes - 1) >> 2;
        !           482: 
        !           483:     while (shiftr >>= 1)
        !           484:       nunits++;
        !           485:   }
        !           486: 
        !           487:   /* In case this is reentrant use of malloc from signal handler,
        !           488:      pick a block size that no other malloc level is currently
        !           489:      trying to allocate.  That's the easiest harmless way not to
        !           490:      interfere with the other level of execution.  */
        !           491:   while (busy[nunits]) nunits++;
        !           492:   busy[nunits] = 1;
        !           493: 
        !           494:   /* If there are no blocks of the appropriate size, go get some */
        !           495:   /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */
        !           496:   if (nextf[nunits] == 0)
        !           497:     morecore (nunits);
        !           498: 
        !           499:   /* Get one block off the list, and set the new list head */
        !           500:   if ((p = nextf[nunits]) == 0)
        !           501:     {
        !           502:       busy[nunits] = 0;
        !           503:       return 0;
        !           504:     }
        !           505:   nextf[nunits] = CHAIN (p);
        !           506:   busy[nunits] = 0;
        !           507: 
        !           508:   /* Check for free block clobbered */
        !           509:   /* If not for this check, we would gobble a clobbered free chain ptr */
        !           510:   /* and bomb out on the NEXT allocate of this size block */
        !           511:   if (p -> mh_alloc != ISFREE || p -> mh_index != nunits)
        !           512: #ifdef rcheck
        !           513:     botch ("block on free list clobbered");
        !           514: #else /* not rcheck */
        !           515:     abort ();
        !           516: #endif /* not rcheck */
        !           517: 
        !           518:   /* Fill in the info, and if range checking, set up the magic numbers */
        !           519:   p -> mh_alloc = ISALLOC;
        !           520: #ifdef rcheck
        !           521:   p -> mh_nbytes = n;
        !           522:   p -> mh_magic4 = MAGIC4;
        !           523:   {
        !           524:     /* Get the location n after the beginning of the user's space.  */
        !           525:     register char *m = (char *) p + ((sizeof *p + 7) & ~7) + n;
        !           526: 
        !           527:     *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1;
        !           528:   }
        !           529: #else /* not rcheck */
        !           530:   p -> mh_size = n;
        !           531: #endif /* not rcheck */
        !           532: #ifdef MSTATS
        !           533:   nmalloc[nunits]++;
        !           534:   nmal++;
        !           535: #endif /* MSTATS */
        !           536:   return (char *) p + ((sizeof *p + 7) & ~7);
        !           537: }
        !           538: 
        !           539: free (mem)
        !           540:      char *mem;
        !           541: {
        !           542:   register struct mhead *p;
        !           543:   {
        !           544:     register char *ap = mem;
        !           545: 
        !           546:     if (ap == 0)
        !           547:       return;
        !           548: 
        !           549:     p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7));
        !           550:     if (p -> mh_alloc == ISMEMALIGN)
        !           551:       {
        !           552:        ap -= p->mh_size;
        !           553:        p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7));
        !           554:       }
        !           555: 
        !           556: #ifndef rcheck
        !           557:     if (p -> mh_alloc != ISALLOC)
        !           558:       abort ();
        !           559: 
        !           560: #else rcheck
        !           561:     if (p -> mh_alloc != ISALLOC)
        !           562:       {
        !           563:        if (p -> mh_alloc == ISFREE)
        !           564:          botch ("free: Called with already freed block argument\n");
        !           565:        else
        !           566:          botch ("free: Called with bad argument\n");
        !           567:       }
        !           568: 
        !           569:     ASSERT (p -> mh_magic4 == MAGIC4);
        !           570:     ap += p -> mh_nbytes;
        !           571:     ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1);
        !           572:     ASSERT (*ap++ == MAGIC1); ASSERT (*ap   == MAGIC1);
        !           573: #endif /* rcheck */
        !           574:   }
        !           575:   {
        !           576:     register int nunits = p -> mh_index;
        !           577: 
        !           578:     ASSERT (nunits <= 29);
        !           579:     p -> mh_alloc = ISFREE;
        !           580: 
        !           581:     /* Protect against signal handlers calling malloc.  */
        !           582:     busy[nunits] = 1;
        !           583:     /* Put this block on the free list.  */
        !           584:     CHAIN (p) = nextf[nunits];
        !           585:     nextf[nunits] = p;
        !           586:     busy[nunits] = 0;
        !           587: 
        !           588: #ifdef MSTATS
        !           589:     nmalloc[nunits]--;
        !           590:     nfre++;
        !           591: #endif /* MSTATS */
        !           592:   }
        !           593: }
        !           594: 
        !           595: char *
        !           596: realloc (mem, n)
        !           597:      char *mem;
        !           598:      register unsigned n;
        !           599: {
        !           600:   register struct mhead *p;
        !           601:   register unsigned int tocopy;
        !           602:   register unsigned int nbytes;
        !           603:   register int nunits;
        !           604: 
        !           605:   if (mem == 0)
        !           606:     return malloc (n);
        !           607:   p = (struct mhead *) (mem - ((sizeof *p + 7) & ~7));
        !           608:   nunits = p -> mh_index;
        !           609:   ASSERT (p -> mh_alloc == ISALLOC);
        !           610: #ifdef rcheck
        !           611:   ASSERT (p -> mh_magic4 == MAGIC4);
        !           612:   {
        !           613:     register char *m = mem + (tocopy = p -> mh_nbytes);
        !           614:     ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1);
        !           615:     ASSERT (*m++ == MAGIC1); ASSERT (*m   == MAGIC1);
        !           616:   }
        !           617: #else /* not rcheck */
        !           618:   if (p -> mh_index >= 13)
        !           619:     tocopy = (1 << (p -> mh_index + 3)) - ((sizeof *p + 7) & ~7);
        !           620:   else
        !           621:     tocopy = p -> mh_size;
        !           622: #endif /* not rcheck */
        !           623: 
        !           624:   /* See if desired size rounds to same power of 2 as actual size. */
        !           625:   nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7;
        !           626: 
        !           627:   /* If ok, use the same block, just marking its size as changed.  */
        !           628:   if (nbytes > (4 << nunits) && nbytes <= (8 << nunits))
        !           629:     {
        !           630: #ifdef rcheck
        !           631:       register char *m = mem + tocopy;
        !           632:       *m++ = 0;  *m++ = 0;  *m++ = 0;  *m++ = 0;
        !           633:       p-> mh_nbytes = n;
        !           634:       m = mem + n;
        !           635:       *m++ = MAGIC1;  *m++ = MAGIC1;  *m++ = MAGIC1;  *m++ = MAGIC1;
        !           636: #else /* not rcheck */
        !           637:       p -> mh_size = n;
        !           638: #endif /* not rcheck */
        !           639:       return mem;
        !           640:     }
        !           641: 
        !           642:   if (n < tocopy)
        !           643:     tocopy = n;
        !           644:   {
        !           645:     register char *new;
        !           646: 
        !           647:     if ((new = malloc (n)) == 0)
        !           648:       return 0;
        !           649:     bcopy (mem, new, tocopy);
        !           650:     free (mem);
        !           651:     return new;
        !           652:   }
        !           653: }
        !           654: 
        !           655: #ifndef VMS
        !           656: 
        !           657: char *
        !           658: memalign (alignment, size)
        !           659:      unsigned alignment, size;
        !           660: {
        !           661:   register char *ptr = malloc (size + alignment);
        !           662:   register char *aligned;
        !           663:   register struct mhead *p;
        !           664: 
        !           665:   if (ptr == 0)
        !           666:     return 0;
        !           667:   /* If entire block has the desired alignment, just accept it.  */
        !           668:   if (((int) ptr & (alignment - 1)) == 0)
        !           669:     return ptr;
        !           670:   /* Otherwise, get address of byte in the block that has that alignment.  */
        !           671:   aligned = (char *) (((int) ptr + alignment - 1) & -alignment);
        !           672: 
        !           673:   /* Store a suitable indication of how to free the block,
        !           674:      so that free can find the true beginning of it.  */
        !           675:   p = (struct mhead *) aligned - 1;
        !           676:   p -> mh_size = aligned - ptr;
        !           677:   p -> mh_alloc = ISMEMALIGN;
        !           678:   return aligned;
        !           679: }
        !           680: 
        !           681: #ifndef HPUX
        !           682: /* This runs into trouble with getpagesize on HPUX.
        !           683:    Patching out seems cleaner than the ugly fix needed.  */
        !           684: char *
        !           685: valloc (size)
        !           686: {
        !           687:   return memalign (getpagesize (), size);
        !           688: }
        !           689: #endif /* not HPUX */
        !           690: #endif /* not VMS */
        !           691: 
        !           692: #ifdef MSTATS
        !           693: /* Return statistics describing allocation of blocks of size 2**n. */
        !           694: 
        !           695: struct mstats_value
        !           696:   {
        !           697:     int blocksize;
        !           698:     int nfree;
        !           699:     int nused;
        !           700:   };
        !           701: 
        !           702: struct mstats_value
        !           703: malloc_stats (size)
        !           704:      int size;
        !           705: {
        !           706:   struct mstats_value v;
        !           707:   register int i;
        !           708:   register struct mhead *p;
        !           709: 
        !           710:   v.nfree = 0;
        !           711: 
        !           712:   if (size < 0 || size >= 30)
        !           713:     {
        !           714:       v.blocksize = 0;
        !           715:       v.nused = 0;
        !           716:       return v;
        !           717:     }
        !           718: 
        !           719:   v.blocksize = 1 << (size + 3);
        !           720:   v.nused = nmalloc[size];
        !           721: 
        !           722:   for (p = nextf[size]; p; p = CHAIN (p))
        !           723:     v.nfree++;
        !           724: 
        !           725:   return v;
        !           726: }
        !           727: int
        !           728: malloc_mem_used ()
        !           729: {
        !           730:   int i;
        !           731:   int size_used;
        !           732: 
        !           733:   size_used = 0;
        !           734:   
        !           735:   for (i = 0; i < 30; i++)
        !           736:     {
        !           737:       int allocation_size = 1 << (i + 3);
        !           738:       struct mhead *p;
        !           739:       
        !           740:       size_used += nmalloc[i] * allocation_size;
        !           741:     }
        !           742: 
        !           743:   return size_used;
        !           744: }
        !           745: 
        !           746: int 
        !           747: malloc_mem_free ()
        !           748: {
        !           749:   int i;
        !           750:   int size_unused;
        !           751: 
        !           752:   size_unused = 0;
        !           753:   
        !           754:   for (i = 0; i < 30; i++)
        !           755:     {
        !           756:       int allocation_size = 1 << (i + 3);
        !           757:       struct mhead *p;
        !           758:       
        !           759:       for (p = nextf[i]; p ; p = CHAIN (p))
        !           760:        size_unused += allocation_size;
        !           761:     }
        !           762: 
        !           763:   return size_unused;
        !           764: }
        !           765: #endif /* MSTATS */
        !           766: 
        !           767: /*
        !           768:  *     This function returns the total number of bytes that the process
        !           769:  *     will be allowed to allocate via the sbrk(2) system call.  On
        !           770:  *     BSD systems this is the total space allocatable to stack and
        !           771:  *     data.  On USG systems this is the data space only.
        !           772:  */
        !           773: 
        !           774: #ifdef USG
        !           775: 
        !           776: get_lim_data ()
        !           777: {
        !           778:   extern long ulimit ();
        !           779:     
        !           780: #ifdef ULIMIT_BREAK_VALUE
        !           781:   lim_data = ULIMIT_BREAK_VALUE;
        !           782: #else
        !           783:   lim_data = ulimit (3, 0);
        !           784: #endif
        !           785: 
        !           786:   lim_data -= (long) data_space_start;
        !           787: }
        !           788: 
        !           789: #else /* not USG */
        !           790: #ifndef BSD4_2
        !           791: 
        !           792: get_lim_data ()
        !           793: {
        !           794:   lim_data = vlimit (LIM_DATA, -1);
        !           795: }
        !           796: 
        !           797: #else /* BSD4_2 */
        !           798: 
        !           799: get_lim_data ()
        !           800: {
        !           801:   struct rlimit XXrlimit;
        !           802: 
        !           803:   getrlimit (RLIMIT_DATA, &XXrlimit);
        !           804: #ifdef RLIM_INFINITY
        !           805:   lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */
        !           806: #else
        !           807:   lim_data = XXrlimit.rlim_cur;        /* soft limit */
        !           808: #endif
        !           809: }
        !           810: 
        !           811: #endif /* BSD4_2 */
        !           812: #endif /* not USG */
        !           813: 
        !           814: #ifdef VMS
        !           815: /* There is a problem when dumping and restoring things on VMS. Calls
        !           816:  * to SBRK don't necessarily result in contiguous allocation. Dumping
        !           817:  * doesn't work when it isn't. Therefore, we make the initial
        !           818:  * allocation contiguous by allocating a big chunk, and do SBRKs from
        !           819:  * there. Once Emacs has dumped there is no reason to continue
        !           820:  * contiguous allocation, malloc doesn't depend on it.
        !           821:  *
        !           822:  * There is a further problem of using brk and sbrk while using VMS C
        !           823:  * run time library routines malloc, calloc, etc. The documentation
        !           824:  * says that this is a no-no, although I'm not sure why this would be
        !           825:  * a problem. In any case, we remove the necessity to call brk and
        !           826:  * sbrk, by calling calloc (to assure zero filled data) rather than
        !           827:  * sbrk.
        !           828:  *
        !           829:  * VMS_ALLOCATION_SIZE is the size of the allocation array. This
        !           830:  * should be larger than the malloc size before dumping. Making this
        !           831:  * too large will result in the startup procedure slowing down since
        !           832:  * it will require more space and time to map it in.
        !           833:  *
        !           834:  * The value for VMS_ALLOCATION_SIZE in the following define was determined
        !           835:  * by running emacs linked (and a large allocation) with the debugger and
        !           836:  * looking to see how much storage was used. The allocation was 201 pages,
        !           837:  * so I rounded it up to a power of two.
        !           838:  */
        !           839: #ifndef VMS_ALLOCATION_SIZE
        !           840: #define VMS_ALLOCATION_SIZE    (512*256)
        !           841: #endif
        !           842: 
        !           843: /* Use VMS RTL definitions */
        !           844: #undef sbrk
        !           845: #undef brk
        !           846: #undef malloc
        !           847: int vms_out_initial = 0;
        !           848: char vms_initial_buffer[VMS_ALLOCATION_SIZE];
        !           849: static char *vms_current_brk = &vms_initial_buffer;
        !           850: static char *vms_end_brk = &vms_initial_buffer[VMS_ALLOCATION_SIZE-1];
        !           851: 
        !           852: #include <stdio.h>
        !           853: 
        !           854: char *
        !           855: sys_sbrk (incr)
        !           856:      int incr;
        !           857: {
        !           858:   char *sbrk(), *temp, *ptr;
        !           859: 
        !           860:   if (vms_out_initial)
        !           861:     {
        !           862:       /* out of initial allocation... */
        !           863:       if (!(temp = malloc (incr)))
        !           864:        temp = (char *) -1;
        !           865:     }
        !           866:   else
        !           867:     {
        !           868:       /* otherwise, go out of our area */
        !           869:       ptr = vms_current_brk + incr; /* new current_brk */
        !           870:       if (ptr <= vms_end_brk)
        !           871:        {
        !           872:          temp = vms_current_brk;
        !           873:          vms_current_brk = ptr;
        !           874:        }
        !           875:       else
        !           876:        {
        !           877:          vms_out_initial = 1;  /* mark as out of initial allocation */
        !           878:          if (!(temp = malloc (incr)))
        !           879:            temp = (char *) -1;
        !           880:        }
        !           881:     }
        !           882:   return temp;
        !           883: }
        !           884: #endif /* VMS */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.