Annotation of GNUtools/emacs/src/malloc.c, revision 1.1.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.