|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.