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