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

unix.superglobalmegacorp.com

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