diff options
Diffstat (limited to 'src/lib/libc/stdlib/malloc.c')
| -rw-r--r-- | src/lib/libc/stdlib/malloc.c | 83 |
1 files changed, 55 insertions, 28 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 9682f91cda..5fc75c2c75 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/lib/libc/stdlib/malloc.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: malloc.c,v 1.139 2011/07/12 14:43:42 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.140 2011/10/06 14:37:04 otto Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> | 3 | * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> |
| 4 | * | 4 | * |
| @@ -109,8 +109,8 @@ struct dir_info { | |||
| 109 | struct region_info *r; /* region slots */ | 109 | struct region_info *r; /* region slots */ |
| 110 | size_t regions_total; /* number of region slots */ | 110 | size_t regions_total; /* number of region slots */ |
| 111 | size_t regions_free; /* number of free slots */ | 111 | size_t regions_free; /* number of free slots */ |
| 112 | /* list of free chunk info structs */ | 112 | /* lists of free chunk info structs */ |
| 113 | struct chunk_head chunk_info_list; | 113 | struct chunk_head chunk_info_list[MALLOC_MAXSHIFT + 1]; |
| 114 | /* lists of chunks with free slots */ | 114 | /* lists of chunks with free slots */ |
| 115 | struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1]; | 115 | struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1]; |
| 116 | size_t free_regions_size; /* free pages cached */ | 116 | size_t free_regions_size; /* free pages cached */ |
| @@ -156,7 +156,7 @@ struct chunk_info { | |||
| 156 | u_short free; /* how many free chunks */ | 156 | u_short free; /* how many free chunks */ |
| 157 | u_short total; /* how many chunk */ | 157 | u_short total; /* how many chunk */ |
| 158 | /* which chunks are free */ | 158 | /* which chunks are free */ |
| 159 | u_short bits[(MALLOC_PAGESIZE / MALLOC_MINSIZE) / MALLOC_BITS]; | 159 | u_short bits[1]; |
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | struct malloc_readonly { | 162 | struct malloc_readonly { |
| @@ -622,9 +622,10 @@ omalloc_init(struct dir_info **dp) | |||
| 622 | d->regions_total = 0; | 622 | d->regions_total = 0; |
| 623 | return 1; | 623 | return 1; |
| 624 | } | 624 | } |
| 625 | LIST_INIT(&d->chunk_info_list); | 625 | for (i = 0; i <= MALLOC_MAXSHIFT; i++) { |
| 626 | for (i = 0; i <= MALLOC_MAXSHIFT; i++) | 626 | LIST_INIT(&d->chunk_info_list[i]); |
| 627 | LIST_INIT(&d->chunk_dir[i]); | 627 | LIST_INIT(&d->chunk_dir[i]); |
| 628 | } | ||
| 628 | malloc_used += regioninfo_size; | 629 | malloc_used += regioninfo_size; |
| 629 | d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d; | 630 | d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d; |
| 630 | d->canary2 = ~d->canary1; | 631 | d->canary2 = ~d->canary1; |
| @@ -689,22 +690,36 @@ omalloc_grow(struct dir_info *d) | |||
| 689 | } | 690 | } |
| 690 | 691 | ||
| 691 | static struct chunk_info * | 692 | static struct chunk_info * |
| 692 | alloc_chunk_info(struct dir_info *d) | 693 | alloc_chunk_info(struct dir_info *d, int bits) |
| 693 | { | 694 | { |
| 694 | struct chunk_info *p; | 695 | struct chunk_info *p; |
| 695 | int i; | 696 | size_t size, count; |
| 696 | 697 | ||
| 697 | if (LIST_EMPTY(&d->chunk_info_list)) { | 698 | if (bits == 0) |
| 698 | p = MMAP(MALLOC_PAGESIZE); | 699 | count = MALLOC_PAGESIZE / MALLOC_MINSIZE; |
| 699 | if (p == MAP_FAILED) | 700 | else |
| 701 | count = MALLOC_PAGESIZE >> bits; | ||
| 702 | |||
| 703 | size = howmany(count, MALLOC_BITS); | ||
| 704 | size = sizeof(struct chunk_info) + (size - 1) * sizeof(u_short); | ||
| 705 | size = ALIGN(size); | ||
| 706 | |||
| 707 | if (LIST_EMPTY(&d->chunk_info_list[bits])) { | ||
| 708 | void *q; | ||
| 709 | int i; | ||
| 710 | |||
| 711 | q = MMAP(MALLOC_PAGESIZE); | ||
| 712 | if (q == MAP_FAILED) | ||
| 700 | return NULL; | 713 | return NULL; |
| 701 | malloc_used += MALLOC_PAGESIZE; | 714 | malloc_used += MALLOC_PAGESIZE; |
| 702 | for (i = 0; i < MALLOC_PAGESIZE / sizeof(*p); i++) | 715 | count = MALLOC_PAGESIZE / size; |
| 703 | LIST_INSERT_HEAD(&d->chunk_info_list, &p[i], entries); | 716 | for (i = 0; i < count; i++, q += size) |
| 717 | LIST_INSERT_HEAD(&d->chunk_info_list[bits], | ||
| 718 | (struct chunk_info *)q, entries); | ||
| 704 | } | 719 | } |
| 705 | p = LIST_FIRST(&d->chunk_info_list); | 720 | p = LIST_FIRST(&d->chunk_info_list[bits]); |
| 706 | LIST_REMOVE(p, entries); | 721 | LIST_REMOVE(p, entries); |
| 707 | memset(p, 0, sizeof *p); | 722 | memset(p, 0, size); |
| 708 | p->canary = d->canary1; | 723 | p->canary = d->canary1; |
| 709 | return p; | 724 | return p; |
| 710 | } | 725 | } |
| @@ -803,14 +818,14 @@ omalloc_make_chunks(struct dir_info *d, int bits) | |||
| 803 | { | 818 | { |
| 804 | struct chunk_info *bp; | 819 | struct chunk_info *bp; |
| 805 | void *pp; | 820 | void *pp; |
| 806 | long i, k; | 821 | int i, k; |
| 807 | 822 | ||
| 808 | /* Allocate a new bucket */ | 823 | /* Allocate a new bucket */ |
| 809 | pp = map(d, MALLOC_PAGESIZE, 0); | 824 | pp = map(d, MALLOC_PAGESIZE, 0); |
| 810 | if (pp == MAP_FAILED) | 825 | if (pp == MAP_FAILED) |
| 811 | return NULL; | 826 | return NULL; |
| 812 | 827 | ||
| 813 | bp = alloc_chunk_info(d); | 828 | bp = alloc_chunk_info(d, bits); |
| 814 | if (bp == NULL) { | 829 | if (bp == NULL) { |
| 815 | unmap(d, pp, MALLOC_PAGESIZE); | 830 | unmap(d, pp, MALLOC_PAGESIZE); |
| 816 | return NULL; | 831 | return NULL; |
| @@ -829,7 +844,7 @@ omalloc_make_chunks(struct dir_info *d, int bits) | |||
| 829 | k = mprotect(pp, MALLOC_PAGESIZE, PROT_NONE); | 844 | k = mprotect(pp, MALLOC_PAGESIZE, PROT_NONE); |
| 830 | if (k < 0) { | 845 | if (k < 0) { |
| 831 | unmap(d, pp, MALLOC_PAGESIZE); | 846 | unmap(d, pp, MALLOC_PAGESIZE); |
| 832 | LIST_INSERT_HEAD(&d->chunk_info_list, bp, entries); | 847 | LIST_INSERT_HEAD(&d->chunk_info_list[0], bp, entries); |
| 833 | return NULL; | 848 | return NULL; |
| 834 | } | 849 | } |
| 835 | } else { | 850 | } else { |
| @@ -956,7 +971,7 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr) | |||
| 956 | { | 971 | { |
| 957 | struct chunk_head *mp; | 972 | struct chunk_head *mp; |
| 958 | struct chunk_info *info; | 973 | struct chunk_info *info; |
| 959 | long i; | 974 | int i; |
| 960 | 975 | ||
| 961 | info = (struct chunk_info *)r->size; | 976 | info = (struct chunk_info *)r->size; |
| 962 | if (info->canary != d->canary1) | 977 | if (info->canary != d->canary1) |
| @@ -997,7 +1012,11 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr) | |||
| 997 | unmap(d, info->page, MALLOC_PAGESIZE); | 1012 | unmap(d, info->page, MALLOC_PAGESIZE); |
| 998 | 1013 | ||
| 999 | delete(d, r); | 1014 | delete(d, r); |
| 1000 | LIST_INSERT_HEAD(&d->chunk_info_list, info, entries); | 1015 | if (info->size != 0) |
| 1016 | mp = &d->chunk_info_list[info->shift]; | ||
| 1017 | else | ||
| 1018 | mp = &d->chunk_info_list[0]; | ||
| 1019 | LIST_INSERT_HEAD(mp, info, entries); | ||
| 1001 | } | 1020 | } |
| 1002 | 1021 | ||
| 1003 | 1022 | ||
| @@ -1521,7 +1540,7 @@ dump_chunk(int fd, struct chunk_info *p, void *f, int fromfreelist) | |||
| 1521 | } | 1540 | } |
| 1522 | p = LIST_NEXT(p, entries); | 1541 | p = LIST_NEXT(p, entries); |
| 1523 | if (p != NULL) { | 1542 | if (p != NULL) { |
| 1524 | snprintf(buf, sizeof(buf), " "); | 1543 | snprintf(buf, sizeof(buf), " "); |
| 1525 | write(fd, buf, strlen(buf)); | 1544 | write(fd, buf, strlen(buf)); |
| 1526 | } | 1545 | } |
| 1527 | } | 1546 | } |
| @@ -1531,17 +1550,25 @@ static void | |||
| 1531 | dump_free_chunk_info(int fd, struct dir_info *d) | 1550 | dump_free_chunk_info(int fd, struct dir_info *d) |
| 1532 | { | 1551 | { |
| 1533 | char buf[64]; | 1552 | char buf[64]; |
| 1534 | int i; | 1553 | int i, count; |
| 1535 | 1554 | ||
| 1536 | snprintf(buf, sizeof(buf), "Free chunk structs:\n"); | 1555 | snprintf(buf, sizeof(buf), "Free chunk structs:\n"); |
| 1537 | write(fd, buf, strlen(buf)); | 1556 | write(fd, buf, strlen(buf)); |
| 1538 | for (i = 0; i <= MALLOC_MAXSHIFT; i++) { | 1557 | for (i = 0; i <= MALLOC_MAXSHIFT; i++) { |
| 1539 | struct chunk_info *p = LIST_FIRST(&d->chunk_dir[i]); | 1558 | struct chunk_info *p; |
| 1540 | if (p != NULL) { | 1559 | |
| 1541 | snprintf(buf, sizeof(buf), "%2d) ", i); | 1560 | count = 0; |
| 1542 | write(fd, buf, strlen(buf)); | 1561 | LIST_FOREACH(p, &d->chunk_info_list[i], entries) |
| 1562 | count++; | ||
| 1563 | p = LIST_FIRST(&d->chunk_dir[i]); | ||
| 1564 | if (p == NULL && count == 0) | ||
| 1565 | continue; | ||
| 1566 | snprintf(buf, sizeof(buf), "%2d) %3d ", i, count); | ||
| 1567 | write(fd, buf, strlen(buf)); | ||
| 1568 | if (p != NULL) | ||
| 1543 | dump_chunk(fd, p, NULL, 1); | 1569 | dump_chunk(fd, p, NULL, 1); |
| 1544 | } | 1570 | else |
| 1571 | write(fd, "\n", 1); | ||
| 1545 | } | 1572 | } |
| 1546 | 1573 | ||
| 1547 | } | 1574 | } |
