1 /* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 */ 9 10 #if defined(LIBC_SCCS) && !defined(lint) 11 static char rcsid[] = "$OpenBSD: malloc.c,v 1.19 1996/11/24 00:41:30 niklas Exp $"; 12 #endif /* LIBC_SCCS and not lint */ 13 14 /* 15 * Defining EXTRA_SANITY will enable extra checks which are related 16 * to internal conditions and consistency in malloc.c. This has a 17 * noticeable runtime performance hit, and generally will not do you 18 * any good unless you fiddle with the internals of malloc or want 19 * to catch random pointer corruption as early as possible. 20 */ 21 #undef EXTRA_SANITY 22 23 /* 24 * Defining MALLOC_STATS will enable you to call malloc_dump() and set 25 * the [dD] options in the MALLOC_OPTIONS environment variable. 26 * It has no run-time performance hit, but does pull in stdio... 27 */ 28 #undef MALLOC_STATS 29 30 #if defined(EXTRA_SANITY) && !defined(MALLOC_STATS) 31 # define MALLOC_STATS /* required for EXTRA_SANITY */ 32 #endif 33 34 /* 35 * What to use for Junk. This is the byte value we use to fill with 36 * when the 'J' option is enabled. 37 */ 38 #define SOME_JUNK 0xd0 /* as in "Duh" :-) */ 39 40 /* 41 * No user serviceable parts behind this point. 42 */ 43 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 #include <errno.h> 49 #include <sys/types.h> 50 #include <sys/param.h> 51 #include <sys/mman.h> 52 53 /* 54 * If these weren't defined here, they would be calculated on the fly, 55 * at a considerable cost in performance. 56 */ 57 #ifdef __OpenBSD__ 58 # if defined(__alpha__) || defined(__m68k__) || defined(__mips__) || \ 59 defined(__i386__) || defined(__m88k__) || defined(__ns32k__) || \ 60 defined(__vax__) 61 # define malloc_pagesize (NBPG) 62 # define malloc_pageshift (PGSHIFT) 63 # define malloc_maxsize (malloc_pagesize >> 1) 64 # define malloc_minsize 16U 65 # endif /* __i386__ */ 66 #endif /* __OpenBSD__ */ 67 68 /* 69 * This structure describes a page worth of chunks. 70 */ 71 72 struct pginfo { 73 struct pginfo *next; /* next on the free list */ 74 void *page; /* Pointer to the page */ 75 u_short size; /* size of this page's chunks */ 76 u_short shift; /* How far to shift for this size chunks */ 77 u_short free; /* How many free chunks */ 78 u_short total; /* How many chunk */ 79 u_long bits[1]; /* Which chunks are free */ 80 }; 81 82 /* 83 * This structure describes a number of free pages. 84 */ 85 86 struct pgfree { 87 struct pgfree *next; /* next run of free pages */ 88 struct pgfree *prev; /* prev run of free pages */ 89 void *page; /* pointer to free pages */ 90 void *end; /* pointer to end of free pages */ 91 u_long size; /* number of bytes free */ 92 }; 93 94 /* 95 * How many bits per u_long in the bitmap. 96 * Change only if not 8 bits/byte 97 */ 98 #define MALLOC_BITS (8*sizeof(u_long)) 99 100 /* 101 * Magic values to put in the page_directory 102 */ 103 #define MALLOC_NOT_MINE ((struct pginfo*) 0) 104 #define MALLOC_FREE ((struct pginfo*) 1) 105 #define MALLOC_FIRST ((struct pginfo*) 2) 106 #define MALLOC_FOLLOW ((struct pginfo*) 3) 107 #define MALLOC_MAGIC ((struct pginfo*) 4) 108 109 /* 110 * The i386 architecture has some very convenient instructions. 111 * We might as well use them. There are C-language backups, but 112 * they are considerably slower. 113 */ 114 #if defined(__i386__) && defined(__GNUC__) 115 #define ffs _ffs 116 static __inline int 117 _ffs(input) 118 unsigned input; 119 { 120 int result; 121 __asm("bsfl %1, %0" : "=r" (result) : "r" (input)); 122 return result+1; 123 } 124 125 #define fls _fls 126 static __inline int 127 _fls(input) 128 unsigned input; 129 { 130 int result; 131 __asm("bsrl %1, %0" : "=r" (result) : "r" (input)); 132 return result+1; 133 } 134 135 #define set_bit _set_bit 136 static __inline void 137 _set_bit(pi, bit) 138 struct pginfo *pi; 139 int bit; 140 { 141 __asm("btsl %0, (%1)" : 142 : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); 143 } 144 145 #define clr_bit _clr_bit 146 static __inline void 147 _clr_bit(pi, bit) 148 struct pginfo *pi; 149 int bit; 150 { 151 __asm("btcl %0, (%1)" : 152 : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); 153 } 154 155 #endif /* __i386__ && __GNUC__ */ 156 157 /* 158 * Set to one when malloc_init has been called 159 */ 160 static unsigned initialized; 161 162 /* 163 * The size of a page. 164 * Must be a integral multiplum of the granularity of mmap(2). 165 * Your toes will curl if it isn't a power of two 166 */ 167 #ifndef malloc_pagesize 168 static unsigned malloc_pagesize; 169 #endif /* malloc_pagesize */ 170 171 /* A mask for the offset inside a page. */ 172 #define malloc_pagemask ((malloc_pagesize)-1) 173 174 #define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask))) 175 #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo) 176 177 /* malloc_pagesize == 1 << malloc_pageshift */ 178 #ifndef malloc_pageshift 179 static unsigned malloc_pageshift; 180 #endif /* malloc_pageshift */ 181 182 /* 183 * The smallest allocation we bother about. 184 * Must be power of two 185 */ 186 #ifndef malloc_minsize 187 static unsigned malloc_minsize; 188 #endif /* malloc_minsize */ 189 190 /* 191 * The largest chunk we care about. 192 * Must be smaller than pagesize 193 * Must be power of two 194 */ 195 #ifndef malloc_maxsize 196 static unsigned malloc_maxsize; 197 #endif /* malloc_maxsize */ 198 199 /* The minimum size (in pages) of the free page cache. */ 200 static unsigned malloc_cache = 16; 201 202 /* The offset from pagenumber to index into the page directory */ 203 static u_long malloc_origo; 204 205 /* The last index in the page directory we care about */ 206 static u_long last_index; 207 208 /* Pointer to page directory. Allocated "as if with" malloc */ 209 static struct pginfo **page_dir; 210 211 /* How many slots in the page directory */ 212 static unsigned malloc_ninfo; 213 214 /* Free pages line up here */ 215 static struct pgfree free_list; 216 217 /* Abort(), user doesn't handle problems. */ 218 static int malloc_abort; 219 220 /* Are we trying to die ? */ 221 static int suicide; 222 223 #ifdef MALLOC_STATS 224 /* dump statistics */ 225 static int malloc_stats; 226 #endif /* MALLOC_STATS */ 227 228 /* always realloc ? */ 229 static int malloc_realloc; 230 231 #ifdef __FreeBSD__ 232 /* pass the kernel a hint on free pages ? */ 233 static int malloc_hint; 234 #endif 235 236 /* zero fill ? */ 237 static int malloc_zero; 238 239 /* junk fill ? */ 240 static int malloc_junk; 241 242 #ifdef __FreeBSD__ 243 /* utrace ? */ 244 static int malloc_utrace; 245 246 struct ut { void *p; size_t s; void *r; }; 247 248 #define UTRACE(a, b, c) \ 249 if (malloc_utrace) \ 250 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);} 251 #else /* !__FreeBSD__ */ 252 #define UTRACE(a,b,c) 253 #endif 254 255 /* my last break. */ 256 static void *malloc_brk; 257 258 /* one location cache for free-list holders */ 259 static struct pgfree *px; 260 261 /* compile-time options */ 262 char *malloc_options; 263 264 /* 265 * Necessary function declarations 266 */ 267 static int extend_pgdir(u_long index); 268 static void *imalloc(size_t size); 269 static void ifree(void *ptr); 270 static void *irealloc(void *ptr, size_t size); 271 272 #ifdef MALLOC_STATS 273 void 274 malloc_dump(fd) 275 FILE *fd; 276 { 277 struct pginfo **pd; 278 struct pgfree *pf; 279 int j; 280 281 pd = page_dir; 282 283 /* print out all the pages */ 284 for(j=0;j<=last_index;j++) { 285 fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j); 286 if (pd[j] == MALLOC_NOT_MINE) { 287 for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++) 288 ; 289 j--; 290 fprintf(fd, ".. %5d not mine\n", j); 291 } else if (pd[j] == MALLOC_FREE) { 292 for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++) 293 ; 294 j--; 295 fprintf(fd, ".. %5d free\n", j); 296 } else if (pd[j] == MALLOC_FIRST) { 297 for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++) 298 ; 299 j--; 300 fprintf(fd, ".. %5d in use\n", j); 301 } else if (pd[j] < MALLOC_MAGIC) { 302 fprintf(fd, "(%p)\n", pd[j]); 303 } else { 304 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n", 305 pd[j], pd[j]->free, pd[j]->total, 306 pd[j]->size, pd[j]->page, pd[j]->next); 307 } 308 } 309 310 for(pf=free_list.next; pf; pf=pf->next) { 311 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n", 312 pf, pf->page, pf->end, pf->size, pf->prev, pf->next); 313 if (pf == pf->next) { 314 fprintf(fd, "Free_list loops.\n"); 315 break; 316 } 317 } 318 319 /* print out various info */ 320 fprintf(fd, "Minsize\t%d\n", malloc_minsize); 321 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize); 322 fprintf(fd, "Pagesize\t%d\n", malloc_pagesize); 323 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift); 324 fprintf(fd, "FirstPage\t%ld\n", malloc_origo); 325 fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift, 326 (last_index + malloc_pageshift) << malloc_pageshift); 327 fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift); 328 } 329 #endif /* MALLOC_STATS */ 330 331 static char *malloc_func; 332 333 static void 334 wrterror(p) 335 char *p; 336 { 337 char *q = "Malloc error: "; 338 suicide = 1; 339 write(2, q, strlen(q)); 340 write(2, malloc_func, strlen(malloc_func)); 341 write(2, p, strlen(p)); 342 #ifdef MALLOC_STATS 343 if (malloc_stats) 344 malloc_dump(stderr); 345 #endif /* MALLOC_STATS */ 346 abort(); 347 } 348 349 static void 350 wrtwarning(p) 351 char *p; 352 { 353 char *q = "Malloc warning: "; 354 if (malloc_abort) 355 wrterror(p); 356 write(2, q, strlen(q)); 357 write(2, malloc_func, strlen(malloc_func)); 358 write(2, p, strlen(p)); 359 } 360 361 #ifdef EXTRA_SANITY 362 static void 363 malloc_exit() 364 { 365 FILE *fd = fopen("malloc.out", "a"); 366 char *q = "malloc() warning: Couldn't dump stats.\n"; 367 if (fd) { 368 malloc_dump(fd); 369 fclose(fd); 370 } else 371 write(2, q, strlen(q)); 372 } 373 #endif /* EXTRA_SANITY */ 374 375 376 /* 377 * Allocate a number of pages from the OS 378 */ 379 static caddr_t 380 map_pages(pages) 381 int pages; 382 { 383 caddr_t result, tail; 384 385 result = (caddr_t)pageround((u_long)sbrk(0)); 386 tail = result + (pages << malloc_pageshift); 387 388 if (brk(tail)) { 389 #ifdef EXTRA_SANITY 390 wrterror("(ES): map_pages fails\n"); 391 #endif /* EXTRA_SANITY */ 392 return 0; 393 } 394 395 last_index = ptr2index(tail) - 1; 396 malloc_brk = tail; 397 398 if ((last_index+1) >= malloc_ninfo && !extend_pgdir(last_index)) 399 return 0; 400 401 return result; 402 } 403 404 /* 405 * Set a bit in the bitmap 406 */ 407 #ifndef set_bit 408 static __inline void 409 set_bit(pi, bit) 410 struct pginfo *pi; 411 int bit; 412 { 413 pi->bits[bit/MALLOC_BITS] |= 1UL<<(bit%MALLOC_BITS); 414 } 415 #endif /* set_bit */ 416 417 /* 418 * Clear a bit in the bitmap 419 */ 420 #ifndef clr_bit 421 static __inline void 422 clr_bit(pi, bit) 423 struct pginfo *pi; 424 int bit; 425 { 426 pi->bits[bit/MALLOC_BITS] &= ~(1UL<<(bit%MALLOC_BITS)); 427 } 428 #endif /* clr_bit */ 429 430 #ifndef tst_bit 431 /* 432 * Test a bit in the bitmap 433 */ 434 static __inline int 435 tst_bit(pi, bit) 436 struct pginfo *pi; 437 int bit; 438 { 439 return pi->bits[bit/MALLOC_BITS] & (1UL<<(bit%MALLOC_BITS)); 440 } 441 #endif /* tst_bit */ 442 443 /* 444 * Find last bit 445 */ 446 #ifndef fls 447 static __inline int 448 fls(size) 449 size_t size; 450 { 451 int i = 1; 452 while (size >>= 1) 453 i++; 454 return i; 455 } 456 #endif /* fls */ 457 458 #if LONG_BIT == WORD_BIT 459 #define ffs_ul ffs 460 #else 461 static __inline int 462 ffs_ul(u_long ul) 463 { 464 u_int n; 465 int i; 466 int k; 467 468 for (i = 0; i < sizeof (u_long) / sizeof (u_int); i++) { 469 n = ul & UINT_MAX; 470 k = ffs (n); 471 if (k) 472 break; 473 ul >>= (sizeof (u_int) * 8); 474 } 475 if (k) 476 k += i * sizeof (u_int) * 8; 477 return k; 478 } 479 #endif 480 481 /* 482 * Extend page directory 483 */ 484 static int 485 extend_pgdir(index) 486 u_long index; 487 { 488 struct pginfo **new, **old; 489 int i; 490 size_t oldlen; 491 492 /* Make it this many pages */ 493 i = index * sizeof *page_dir; 494 i /= malloc_pagesize; 495 i += 2; 496 497 /* remember the old mapping size */ 498 oldlen = malloc_ninfo * sizeof *page_dir; 499 500 /* 501 * NOTE: we allocate new pages and copy the directory rather than tempt 502 * fate by trying to "grow" the region.. There is nothing to prevent 503 * us from accidently re-mapping space that's been allocated by our caller 504 * via dlopen() or other mmap(). 505 * 506 * The copy problem is not too bad, as there is 4K of page index per 507 * 4MB of malloc arena. 508 * 509 * We can totally avoid the copy if we open a file descriptor to associate 510 * the anon mappings with. Then, when we remap the pages at the new 511 * address, the old pages will be "magically" remapped.. But this means 512 * keeping open a "secret" file descriptor..... 513 */ 514 515 /* Get new pages */ 516 new = (struct pginfo**) mmap(0, i * malloc_pagesize, PROT_READ|PROT_WRITE, 517 MAP_ANON|MAP_PRIVATE, -1, (off_t)0); 518 if (new == (struct pginfo **)-1) 519 return 0; 520 521 /* Copy the old stuff */ 522 memcpy(new, page_dir, 523 malloc_ninfo * sizeof *page_dir); 524 525 /* register the new size */ 526 malloc_ninfo = i * malloc_pagesize / sizeof *page_dir; 527 528 /* swap the pointers */ 529 old = page_dir; 530 page_dir = new; 531 532 /* Now free the old stuff */ 533 munmap((caddr_t)old, oldlen); 534 return 1; 535 } 536 537 /* 538 * Initialize the world 539 */ 540 static void 541 malloc_init () 542 { 543 char *p, b[64]; 544 int i, j; 545 546 #ifdef EXTRA_SANITY 547 malloc_junk = 1; 548 #endif /* EXTRA_SANITY */ 549 550 for (i = 0; i < 3; i++) { 551 if (i == 0) { 552 j = readlink("/etc/malloc.conf", b, sizeof b - 1); 553 if (j <= 0) 554 continue; 555 b[j] = '\0'; 556 p = b; 557 } else if (i == 1 && issetugid() == 0) { 558 p = getenv("MALLOC_OPTIONS"); 559 } else if (i == 2) { 560 p = malloc_options; 561 } 562 else 563 p = NULL; 564 for (; p && *p; p++) { 565 switch (*p) { 566 case '>': malloc_cache <<= 1; break; 567 case '<': malloc_cache >>= 1; break; 568 case 'a': malloc_abort = 0; break; 569 case 'A': malloc_abort = 1; break; 570 #ifdef MALLOC_STATS 571 case 'd': malloc_stats = 0; break; 572 case 'D': malloc_stats = 1; break; 573 #endif /* MALLOC_STATS */ 574 #ifdef __FreeBSD__ 575 case 'h': malloc_hint = 0; break; 576 case 'H': malloc_hint = 1; break; 577 #endif /* __FreeBSD__ */ 578 case 'r': malloc_realloc = 0; break; 579 case 'R': malloc_realloc = 1; break; 580 case 'j': malloc_junk = 0; break; 581 case 'J': malloc_junk = 1; break; 582 #ifdef __FreeBSD__ 583 case 'u': malloc_utrace = 0; break; 584 case 'U': malloc_utrace = 1; break; 585 #endif /* __FreeBSD__ */ 586 case 'z': malloc_zero = 0; break; 587 case 'Z': malloc_zero = 1; break; 588 default: 589 j = malloc_abort; 590 malloc_abort = 0; 591 wrtwarning("unknown char in MALLOC_OPTIONS\n"); 592 malloc_abort = j; 593 break; 594 } 595 } 596 } 597 598 UTRACE(0, 0, 0); 599 600 /* 601 * We want junk in the entire allocation, and zero only in the part 602 * the user asked for. 603 */ 604 if (malloc_zero) 605 malloc_junk=1; 606 607 #ifdef EXTRA_SANITY 608 if (malloc_stats) 609 atexit(malloc_exit); 610 #endif /* EXTRA_SANITY */ 611 612 #ifndef malloc_pagesize 613 /* determine our pagesize */ 614 malloc_pagesize = getpagesize(); 615 #endif /* malloc_pagesize */ 616 617 #ifndef malloc_maxsize 618 malloc_maxsize = malloc_pagesize >> 1; 619 #endif /* malloc_maxsize */ 620 621 #ifndef malloc_pageshift 622 { 623 int i; 624 /* determine how much we shift by to get there */ 625 for (i = malloc_pagesize; i > 1; i >>= 1) 626 malloc_pageshift++; 627 } 628 #endif /* malloc_pageshift */ 629 630 #ifndef malloc_minsize 631 { 632 int i; 633 /* 634 * find the smallest size allocation we will bother about. 635 * this is determined as the smallest allocation that can hold 636 * it's own pginfo; 637 */ 638 i = 2; 639 for(;;) { 640 int j; 641 642 /* Figure out the size of the bits */ 643 j = malloc_pagesize/i; 644 j /= 8; 645 if (j < sizeof(u_long)) 646 j = sizeof (u_long); 647 if (sizeof(struct pginfo) + j - sizeof (u_long) <= i) 648 break; 649 i += i; 650 } 651 malloc_minsize = i; 652 } 653 #endif /* malloc_minsize */ 654 655 /* Allocate one page for the page directory */ 656 page_dir = (struct pginfo **) mmap(0, malloc_pagesize, PROT_READ|PROT_WRITE, 657 MAP_ANON|MAP_PRIVATE, -1, (off_t)0); 658 if (page_dir == (struct pginfo **) -1) 659 wrterror("mmap(2) failed, check limits.\n"); 660 661 /* 662 * We need a maximum of malloc_pageshift buckets, steal these from the 663 * front of the page_directory; 664 */ 665 malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift; 666 malloc_origo -= malloc_pageshift; 667 668 malloc_ninfo = malloc_pagesize / sizeof *page_dir; 669 670 /* Been here, done that */ 671 initialized++; 672 673 /* 674 * This is a nice hack from Kaleb Keithly (kaleb@x.org). 675 * We can sbrk(2) further back when we keep this on a low address. 676 */ 677 px = (struct pgfree *) imalloc (sizeof *px); 678 679 if (!malloc_cache) 680 malloc_cache++; 681 682 malloc_cache <<= malloc_pageshift; 683 } 684 685 /* 686 * Allocate a number of complete pages 687 */ 688 void * 689 malloc_pages(size) 690 size_t size; 691 { 692 void *p, *delay_free = 0; 693 int i; 694 struct pgfree *pf; 695 u_long index; 696 697 size = pageround(size); 698 699 p = 0; 700 /* Look for free pages before asking for more */ 701 for(pf = free_list.next; pf; pf = pf->next) { 702 703 #ifdef EXTRA_SANITY 704 if (pf->size & malloc_pagemask) 705 wrterror("(ES): junk length entry on free_list\n"); 706 if (!pf->size) 707 wrterror("(ES): zero length entry on free_list\n"); 708 if (pf->page == pf->end) 709 wrterror("(ES): zero entry on free_list\n"); 710 if (pf->page > pf->end) 711 wrterror("(ES): sick entry on free_list\n"); 712 if ((void*)pf->page >= (void*)sbrk(0)) 713 wrterror("(ES): entry on free_list past brk\n"); 714 if (page_dir[ptr2index(pf->page)] != MALLOC_FREE) 715 wrterror("(ES): non-free first page on free-list\n"); 716 if (page_dir[ptr2index(pf->end)-1] != MALLOC_FREE) 717 wrterror("(ES): non-free last page on free-list\n"); 718 #endif /* EXTRA_SANITY */ 719 720 if (pf->size < size) 721 continue; 722 723 if (pf->size == size) { 724 p = pf->page; 725 if (pf->next) 726 pf->next->prev = pf->prev; 727 pf->prev->next = pf->next; 728 delay_free = pf; 729 break; 730 } 731 732 p = pf->page; 733 pf->page = (char *)pf->page + size; 734 pf->size -= size; 735 break; 736 } 737 738 #ifdef EXTRA_SANITY 739 if (p && page_dir[ptr2index(p)] != MALLOC_FREE) 740 wrterror("(ES): allocated non-free page on free-list\n"); 741 #endif /* EXTRA_SANITY */ 742 743 size >>= malloc_pageshift; 744 745 /* Map new pages */ 746 if (!p) 747 p = map_pages(size); 748 749 if (p) { 750 751 index = ptr2index(p); 752 page_dir[index] = MALLOC_FIRST; 753 for (i=1;i<size;i++) 754 page_dir[index+i] = MALLOC_FOLLOW; 755 756 if (malloc_junk) 757 memset(p, SOME_JUNK, size << malloc_pageshift); 758 } 759 760 if (delay_free) { 761 if (!px) 762 px = delay_free; 763 else 764 ifree(delay_free); 765 } 766 767 return p; 768 } 769 770 /* 771 * Allocate a page of fragments 772 */ 773 774 static __inline int 775 malloc_make_chunks(bits) 776 int bits; 777 { 778 struct pginfo *bp; 779 void *pp; 780 int i, k, l; 781 782 /* Allocate a new bucket */ 783 pp = malloc_pages(malloc_pagesize); 784 if (!pp) 785 return 0; 786 787 /* Find length of admin structure */ 788 l = sizeof *bp - sizeof(u_long); 789 l += sizeof(u_long) * 790 (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS); 791 792 /* Don't waste more than two chunks on this */ 793 if ((1UL<<(bits)) <= l+l) { 794 bp = (struct pginfo *)pp; 795 } else { 796 bp = (struct pginfo *)imalloc(l); 797 if (!bp) 798 return 0; 799 } 800 801 bp->size = (1UL<<bits); 802 bp->shift = bits; 803 bp->total = bp->free = malloc_pagesize >> bits; 804 bp->page = pp; 805 806 page_dir[ptr2index(pp)] = bp; 807 808 bp->next = page_dir[bits]; 809 page_dir[bits] = bp; 810 811 /* set all valid bits in the bits */ 812 k = bp->total; 813 i = 0; 814 815 /* Do a bunch at a time */ 816 for(;k-i >= MALLOC_BITS; i += MALLOC_BITS) 817 bp->bits[i / MALLOC_BITS] = (u_long)~0; 818 819 for(; i < k; i++) 820 set_bit(bp, i); 821 822 if (bp == bp->page) { 823 /* Mark the ones we stole for ourselves */ 824 for(i=0;l > 0;i++) { 825 clr_bit(bp, i); 826 bp->free--; 827 bp->total--; 828 l -= (1 << bits); 829 } 830 } 831 832 return 1; 833 } 834 835 /* 836 * Allocate a fragment 837 */ 838 static void * 839 malloc_bytes(size) 840 size_t size; 841 { 842 int j; 843 struct pginfo *bp; 844 int k; 845 u_long *lp; 846 847 /* Don't bother with anything less than this */ 848 if (size < malloc_minsize) 849 size = malloc_minsize; 850 851 /* Find the right bucket */ 852 j = fls((size)-1); 853 854 /* If it's empty, make a page more of that size chunks */ 855 if (!page_dir[j] && !malloc_make_chunks(j)) 856 return 0; 857 858 bp = page_dir[j]; 859 860 /* Find first word of bitmap which isn't empty */ 861 for (lp = bp->bits; !*lp; lp++) 862 ; 863 864 /* Find that bit, and tweak it */ 865 k = ffs_ul(*lp) - 1; 866 *lp ^= 1UL<<k; 867 868 /* If there are no more free, remove from free-list */ 869 if (!--bp->free) { 870 page_dir[j] = bp->next; 871 bp->next = 0; 872 } 873 874 /* Adjust to the real offset of that chunk */ 875 k += (lp-bp->bits)*MALLOC_BITS; 876 k <<= bp->shift; 877 878 if (malloc_junk) 879 memset((char *)bp->page + k, SOME_JUNK, bp->size); 880 881 return (void *)((char *)bp->page + k); 882 } 883 884 /* 885 * Allocate a piece of memory 886 */ 887 static void * 888 imalloc(size) 889 size_t size; 890 { 891 void *result; 892 #ifdef _THREAD_SAFE 893 int status; 894 #endif 895 896 if (!initialized) 897 malloc_init(); 898 899 if (suicide) 900 abort(); 901 902 if (size <= malloc_maxsize) 903 result = malloc_bytes(size); 904 else 905 result = malloc_pages(size); 906 907 if (malloc_abort && !result) 908 wrterror("allocation failed.\n"); 909 910 if (malloc_zero) 911 memset(result, 0, size); 912 913 return result; 914 } 915 916 /* 917 * Change the size of an allocation. 918 */ 919 static void * 920 irealloc(ptr, size) 921 void *ptr; 922 size_t size; 923 { 924 void *p; 925 u_long osize, index; 926 struct pginfo **mp; 927 int i; 928 #ifdef _THREAD_SAFE 929 int status; 930 #endif 931 932 if (suicide) 933 return 0; 934 935 if (!initialized) { 936 wrtwarning("malloc() has never been called.\n"); 937 return 0; 938 } 939 940 index = ptr2index(ptr); 941 942 if (index < malloc_pageshift) { 943 wrtwarning("junk pointer, too low to make sense.\n"); 944 return 0; 945 } 946 947 if (index > last_index) { 948 wrtwarning("junk pointer, too high to make sense.\n"); 949 return 0; 950 } 951 952 mp = &page_dir[index]; 953 954 if (*mp == MALLOC_FIRST) { /* Page allocation */ 955 956 /* Check the pointer */ 957 if ((u_long)ptr & malloc_pagemask) { 958 wrtwarning("modified (page-) pointer.\n"); 959 return 0; 960 } 961 962 /* Find the size in bytes */ 963 for (osize = malloc_pagesize; *++mp == MALLOC_FOLLOW;) 964 osize += malloc_pagesize; 965 966 if (!malloc_realloc && /* unless we have to, */ 967 size <= osize && /* .. or are too small, */ 968 size > (osize - malloc_pagesize)) { /* .. or can free a page, */ 969 return ptr; /* don't do anything. */ 970 } 971 972 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */ 973 974 /* Check the pointer for sane values */ 975 if (((u_long)ptr & ((*mp)->size-1))) { 976 wrtwarning("modified (chunk-) pointer.\n"); 977 return 0; 978 } 979 980 /* Find the chunk index in the page */ 981 i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift; 982 983 /* Verify that it isn't a free chunk already */ 984 if (tst_bit(*mp, i)) { 985 wrtwarning("chunk is already free.\n"); 986 return 0; 987 } 988 989 osize = (*mp)->size; 990 991 if (!malloc_realloc && /* Unless we have to, */ 992 size < osize && /* ..or are too small, */ 993 (size > osize/2 || /* ..or could use a smaller size, */ 994 osize == malloc_minsize)) { /* ..(if there is one) */ 995 return ptr; /* ..Don't do anything */ 996 } 997 998 } else { 999 wrtwarning("pointer to wrong page.\n"); 1000 return 0; 1001 } 1002 1003 p = imalloc(size); 1004 1005 if (p) { 1006 /* copy the lesser of the two sizes, and free the old one */ 1007 if (osize < size) 1008 memcpy(p, ptr, osize); 1009 else 1010 memcpy(p, ptr, size); 1011 ifree(ptr); 1012 } 1013 return p; 1014 } 1015 1016 /* 1017 * Free a sequence of pages 1018 */ 1019 1020 static __inline void 1021 free_pages(ptr, index, info) 1022 void *ptr; 1023 int index; 1024 struct pginfo *info; 1025 { 1026 int i; 1027 struct pgfree *pf, *pt=0; 1028 u_long l; 1029 void *tail; 1030 1031 if (info == MALLOC_FREE) { 1032 wrtwarning("page is already free.\n"); 1033 return; 1034 } 1035 1036 if (info != MALLOC_FIRST) { 1037 wrtwarning("pointer to wrong page.\n"); 1038 return; 1039 } 1040 1041 if ((u_long)ptr & malloc_pagemask) { 1042 wrtwarning("modified (page-) pointer.\n"); 1043 return; 1044 } 1045 1046 /* Count how many pages and mark them free at the same time */ 1047 page_dir[index] = MALLOC_FREE; 1048 for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++) 1049 page_dir[index + i] = MALLOC_FREE; 1050 1051 l = i << malloc_pageshift; 1052 1053 #ifdef __FreeBSD__ 1054 if (malloc_hint) 1055 madvise(ptr, l, MADV_FREE); 1056 #endif 1057 1058 tail = (char *)ptr+l; 1059 1060 /* add to free-list */ 1061 if (!px) 1062 px = imalloc(sizeof *pt); /* This cannot fail... */ 1063 px->page = ptr; 1064 px->end = tail; 1065 px->size = l; 1066 if (!free_list.next) { 1067 1068 /* Nothing on free list, put this at head */ 1069 px->next = free_list.next; 1070 px->prev = &free_list; 1071 free_list.next = px; 1072 pf = px; 1073 px = 0; 1074 1075 } else { 1076 1077 /* Find the right spot, leave pf pointing to the modified entry. */ 1078 tail = (char *)ptr+l; 1079 1080 for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next) 1081 ; /* Race ahead here */ 1082 1083 if (pf->page > tail) { 1084 /* Insert before entry */ 1085 px->next = pf; 1086 px->prev = pf->prev; 1087 pf->prev = px; 1088 px->prev->next = px; 1089 pf = px; 1090 px = 0; 1091 } else if (pf->end == ptr ) { 1092 /* Append to the previous entry */ 1093 pf->end = (char *)pf->end + l; 1094 pf->size += l; 1095 if (pf->next && pf->end == pf->next->page ) { 1096 /* And collapse the next too. */ 1097 pt = pf->next; 1098 pf->end = pt->end; 1099 pf->size += pt->size; 1100 pf->next = pt->next; 1101 if (pf->next) 1102 pf->next->prev = pf; 1103 } 1104 } else if (pf->page == tail) { 1105 /* Prepend to entry */ 1106 pf->size += l; 1107 pf->page = ptr; 1108 } else if (!pf->next) { 1109 /* Append at tail of chain */ 1110 px->next = 0; 1111 px->prev = pf; 1112 pf->next = px; 1113 pf = px; 1114 px = 0; 1115 } else { 1116 wrterror("freelist is destroyed.\n"); 1117 } 1118 } 1119 1120 /* Return something to OS ? */ 1121 if (!pf->next && /* If we're the last one, */ 1122 pf->size > malloc_cache && /* ..and the cache is full, */ 1123 pf->end == malloc_brk && /* ..and none behind us, */ 1124 malloc_brk == sbrk(0)) { /* ..and it's OK to do... */ 1125 1126 /* 1127 * Keep the cache intact. Notice that the '>' above guarantees that 1128 * the pf will always have at least one page afterwards. 1129 */ 1130 pf->end = (char *)pf->page + malloc_cache; 1131 pf->size = malloc_cache; 1132 1133 brk(pf->end); 1134 malloc_brk = pf->end; 1135 1136 index = ptr2index(pf->end); 1137 last_index = index - 1; 1138 1139 for(i=index;i <= last_index;) 1140 page_dir[i++] = MALLOC_NOT_MINE; 1141 1142 /* XXX: We could realloc/shrink the pagedir here I guess. */ 1143 } 1144 if (pt) 1145 ifree(pt); 1146 } 1147 1148 /* 1149 * Free a chunk, and possibly the page it's on, if the page becomes empty. 1150 */ 1151 1152 /* ARGSUSED */ 1153 static __inline void 1154 free_bytes(ptr, index, info) 1155 void *ptr; 1156 int index; 1157 struct pginfo *info; 1158 { 1159 int i; 1160 struct pginfo **mp; 1161 void *vp; 1162 1163 /* Find the chunk number on the page */ 1164 i = ((u_long)ptr & malloc_pagemask) >> info->shift; 1165 1166 if (((u_long)ptr & (info->size-1))) { 1167 wrtwarning("modified (chunk-) pointer.\n"); 1168 return; 1169 } 1170 1171 if (tst_bit(info, i)) { 1172 wrtwarning("chunk is already free.\n"); 1173 return; 1174 } 1175 1176 set_bit(info, i); 1177 info->free++; 1178 1179 mp = page_dir + info->shift; 1180 1181 if (info->free == 1) { 1182 1183 /* Page became non-full */ 1184 1185 mp = page_dir + info->shift; 1186 /* Insert in address order */ 1187 while (*mp && (*mp)->next && (*mp)->next->page < info->page) 1188 mp = &(*mp)->next; 1189 info->next = *mp; 1190 *mp = info; 1191 return; 1192 } 1193 1194 if (info->free != info->total) 1195 return; 1196 1197 /* Find & remove this page in the queue */ 1198 while (*mp != info) { 1199 mp = &((*mp)->next); 1200 #ifdef EXTRA_SANITY 1201 if (!*mp) 1202 wrterror("(ES): Not on queue\n"); 1203 #endif /* EXTRA_SANITY */ 1204 } 1205 *mp = info->next; 1206 1207 /* Free the page & the info structure if need be */ 1208 page_dir[ptr2index(info->page)] = MALLOC_FIRST; 1209 vp = info->page; /* Order is important ! */ 1210 if(vp != (void*)info) 1211 ifree(info); 1212 ifree(vp); 1213 } 1214 1215 static void 1216 ifree(ptr) 1217 void *ptr; 1218 { 1219 struct pginfo *info; 1220 int index; 1221 #ifdef _THREAD_SAFE 1222 int status; 1223 #endif 1224 1225 /* This is legal */ 1226 if (!ptr) 1227 return; 1228 1229 if (!initialized) { 1230 wrtwarning("malloc() has never been called.\n"); 1231 return; 1232 } 1233 1234 /* If we're already sinking, don't make matters any worse. */ 1235 if (suicide) 1236 return; 1237 1238 index = ptr2index(ptr); 1239 1240 if (index < malloc_pageshift) { 1241 wrtwarning("junk pointer, too low to make sense.\n"); 1242 return; 1243 } 1244 1245 if (index > last_index) { 1246 wrtwarning("junk pointer, too high to make sense.\n"); 1247 return; 1248 } 1249 1250 info = page_dir[index]; 1251 1252 if (info < MALLOC_MAGIC) 1253 free_pages(ptr, index, info); 1254 else 1255 free_bytes(ptr, index, info); 1256 return; 1257 } 1258 1259 /* 1260 * These are the public exported interface routines. 1261 */ 1262 1263 #ifdef _THREAD_SAFE 1264 #include <pthread.h> 1265 #include "pthread_private.h" 1266 static int malloc_lock; 1267 #define THREAD_LOCK() _thread_kern_sig_block(&malloc_lock); 1268 #define THREAD_UNLOCK() _thread_kern_sig_unblock(&malloc_lock); 1269 #else 1270 #define THREAD_LOCK() 1271 #define THREAD_UNLOCK() 1272 #endif 1273 1274 static int malloc_active; 1275 1276 void * 1277 malloc(size_t size) 1278 { 1279 register void *r; 1280 1281 malloc_func = "malloc():"; 1282 THREAD_LOCK(); 1283 if (malloc_active++) { 1284 wrtwarning("recursive call.\n"); 1285 malloc_active--; 1286 return (0); 1287 } 1288 r = imalloc(size); 1289 UTRACE(0, size, r); 1290 malloc_active--; 1291 THREAD_UNLOCK(); 1292 return (r); 1293 } 1294 1295 void 1296 free(void *ptr) 1297 { 1298 malloc_func = "free():"; 1299 THREAD_LOCK(); 1300 if (malloc_active++) { 1301 wrtwarning("recursive call.\n"); 1302 malloc_active--; 1303 return; 1304 } 1305 ifree(ptr); 1306 UTRACE(ptr, 0, 0); 1307 malloc_active--; 1308 THREAD_UNLOCK(); 1309 return; 1310 } 1311 1312 void * 1313 realloc(void *ptr, size_t size) 1314 { 1315 register void *r; 1316 1317 malloc_func = "realloc():"; 1318 THREAD_LOCK(); 1319 if (malloc_active++) { 1320 wrtwarning("recursive call.\n"); 1321 malloc_active--; 1322 return (0); 1323 } 1324 if (!ptr) { 1325 r = imalloc(size); 1326 } else if (ptr && !size) { 1327 ifree(ptr); 1328 r = 0; 1329 } else { 1330 r = irealloc(ptr, size); 1331 } 1332 UTRACE(ptr, size, r); 1333 malloc_active--; 1334 THREAD_UNLOCK(); 1335 return (r); 1336 } 1337