diff options
Diffstat (limited to 'src')
-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 | } |