summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/stdlib/malloc.c83
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
162struct malloc_readonly { 162struct 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
691static struct chunk_info * 692static struct chunk_info *
692alloc_chunk_info(struct dir_info *d) 693alloc_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
1531dump_free_chunk_info(int fd, struct dir_info *d) 1550dump_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}