diff options
author | otto <> | 2018-01-08 12:20:23 +0000 |
---|---|---|
committer | otto <> | 2018-01-08 12:20:23 +0000 |
commit | 7bf3aa14de4848bd18b9e7cce77ac9a6d79600e9 (patch) | |
tree | b0f164e8972236d8d1109369da0e774eaf603282 | |
parent | b5565d9f20514e6aee34a8beb128ad836d739bf9 (diff) | |
download | openbsd-7bf3aa14de4848bd18b9e7cce77ac9a6d79600e9.tar.gz openbsd-7bf3aa14de4848bd18b9e7cce77ac9a6d79600e9.tar.bz2 openbsd-7bf3aa14de4848bd18b9e7cce77ac9a6d79600e9.zip |
optimization and some cleanup; mostly from kshe (except the unmap() part)
-rw-r--r-- | src/lib/libc/stdlib/malloc.c | 118 |
1 files changed, 51 insertions, 67 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 02349d9ef9..b0083cb91e 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.238 2018/01/01 12:41:48 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.239 2018/01/08 12:20:23 otto Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net> | 3 | * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net> |
4 | * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> | 4 | * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> |
@@ -376,12 +376,11 @@ omalloc_parseopt(char opt) | |||
376 | case 'X': | 376 | case 'X': |
377 | mopts.malloc_xmalloc = 1; | 377 | mopts.malloc_xmalloc = 1; |
378 | break; | 378 | break; |
379 | default: { | 379 | default: |
380 | dprintf(STDERR_FILENO, "malloc() warning: " | 380 | dprintf(STDERR_FILENO, "malloc() warning: " |
381 | "unknown char in MALLOC_OPTIONS\n"); | 381 | "unknown char in MALLOC_OPTIONS\n"); |
382 | break; | 382 | break; |
383 | } | 383 | } |
384 | } | ||
385 | } | 384 | } |
386 | 385 | ||
387 | static void | 386 | static void |
@@ -448,9 +447,6 @@ omalloc_init(void) | |||
448 | ; | 447 | ; |
449 | } | 448 | } |
450 | 449 | ||
451 | /* | ||
452 | * Initialize a dir_info, which should have been cleared by caller | ||
453 | */ | ||
454 | static void | 450 | static void |
455 | omalloc_poolinit(struct dir_info **dp) | 451 | omalloc_poolinit(struct dir_info **dp) |
456 | { | 452 | { |
@@ -502,7 +498,7 @@ omalloc_grow(struct dir_info *d) | |||
502 | size_t i; | 498 | size_t i; |
503 | struct region_info *p; | 499 | struct region_info *p; |
504 | 500 | ||
505 | if (d->regions_total > SIZE_MAX / sizeof(struct region_info) / 2 ) | 501 | if (d->regions_total > SIZE_MAX / sizeof(struct region_info) / 2) |
506 | return 1; | 502 | return 1; |
507 | 503 | ||
508 | newtotal = d->regions_total * 2; | 504 | newtotal = d->regions_total * 2; |
@@ -641,9 +637,9 @@ static void | |||
641 | unmap(struct dir_info *d, void *p, size_t sz, int clear) | 637 | unmap(struct dir_info *d, void *p, size_t sz, int clear) |
642 | { | 638 | { |
643 | size_t psz = sz >> MALLOC_PAGESHIFT; | 639 | size_t psz = sz >> MALLOC_PAGESHIFT; |
644 | size_t rsz, tounmap; | 640 | size_t rsz; |
645 | struct region_info *r; | 641 | struct region_info *r; |
646 | u_int i, offset; | 642 | u_int i, offset, mask; |
647 | 643 | ||
648 | if (sz != PAGEROUND(sz)) | 644 | if (sz != PAGEROUND(sz)) |
649 | wrterror(d, "munmap round"); | 645 | wrterror(d, "munmap round"); |
@@ -662,30 +658,34 @@ unmap(struct dir_info *d, void *p, size_t sz, int clear) | |||
662 | STATS_SUB(d->malloc_used, sz); | 658 | STATS_SUB(d->malloc_used, sz); |
663 | return; | 659 | return; |
664 | } | 660 | } |
665 | tounmap = 0; | ||
666 | if (psz > rsz) | ||
667 | tounmap = psz - rsz; | ||
668 | offset = getrbyte(d); | 661 | offset = getrbyte(d); |
669 | for (i = 0; tounmap > 0 && i < mopts.malloc_cache; i++) { | 662 | mask = mopts.malloc_cache - 1; |
670 | r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)]; | 663 | if (psz > rsz) { |
671 | if (r->p != NULL) { | 664 | size_t tounmap = psz - rsz; |
672 | rsz = r->size << MALLOC_PAGESHIFT; | 665 | i = 0; |
673 | if (munmap(r->p, rsz)) | 666 | for (;;) { |
674 | wrterror(d, "munmap %p", r->p); | 667 | r = &d->free_regions[(i + offset) & mask]; |
675 | r->p = NULL; | 668 | if (r->p != NULL) { |
676 | if (tounmap > r->size) | 669 | rsz = r->size << MALLOC_PAGESHIFT; |
677 | tounmap -= r->size; | 670 | if (munmap(r->p, rsz)) |
678 | else | 671 | wrterror(d, "munmap %p", r->p); |
679 | tounmap = 0; | 672 | r->p = NULL; |
680 | d->free_regions_size -= r->size; | 673 | if (tounmap > r->size) |
681 | r->size = 0; | 674 | tounmap -= r->size; |
682 | STATS_SUB(d->malloc_used, rsz); | 675 | else |
676 | tounmap = 0; | ||
677 | d->free_regions_size -= r->size; | ||
678 | STATS_SUB(d->malloc_used, rsz); | ||
679 | if (tounmap == 0) { | ||
680 | offset = i; | ||
681 | break; | ||
682 | } | ||
683 | } | ||
684 | i++; | ||
683 | } | 685 | } |
684 | } | 686 | } |
685 | if (tounmap > 0) | 687 | for (i = 0; ; i++) { |
686 | wrterror(d, "malloc cache underflow"); | 688 | r = &d->free_regions[(i + offset) & mask]; |
687 | for (i = 0; i < mopts.malloc_cache; i++) { | ||
688 | r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)]; | ||
689 | if (r->p == NULL) { | 689 | if (r->p == NULL) { |
690 | if (clear) | 690 | if (clear) |
691 | memset(p, 0, sz - mopts.malloc_guard); | 691 | memset(p, 0, sz - mopts.malloc_guard); |
@@ -702,8 +702,6 @@ unmap(struct dir_info *d, void *p, size_t sz, int clear) | |||
702 | break; | 702 | break; |
703 | } | 703 | } |
704 | } | 704 | } |
705 | if (i == mopts.malloc_cache) | ||
706 | wrterror(d, "malloc free slot lost"); | ||
707 | if (d->free_regions_size > mopts.malloc_cache) | 705 | if (d->free_regions_size > mopts.malloc_cache) |
708 | wrterror(d, "malloc cache overflow"); | 706 | wrterror(d, "malloc cache overflow"); |
709 | } | 707 | } |
@@ -723,7 +721,6 @@ zapcacheregion(struct dir_info *d, void *p, size_t len) | |||
723 | wrterror(d, "munmap %p", r->p); | 721 | wrterror(d, "munmap %p", r->p); |
724 | r->p = NULL; | 722 | r->p = NULL; |
725 | d->free_regions_size -= r->size; | 723 | d->free_regions_size -= r->size; |
726 | r->size = 0; | ||
727 | STATS_SUB(d->malloc_used, rsz); | 724 | STATS_SUB(d->malloc_used, rsz); |
728 | } | 725 | } |
729 | } | 726 | } |
@@ -760,7 +757,6 @@ map(struct dir_info *d, void *hint, size_t sz, int zero_fill) | |||
760 | if (r->size == psz) { | 757 | if (r->size == psz) { |
761 | p = r->p; | 758 | p = r->p; |
762 | r->p = NULL; | 759 | r->p = NULL; |
763 | r->size = 0; | ||
764 | d->free_regions_size -= psz; | 760 | d->free_regions_size -= psz; |
765 | if (mopts.malloc_freeunmap) | 761 | if (mopts.malloc_freeunmap) |
766 | mprotect(p, sz, PROT_READ | PROT_WRITE); | 762 | mprotect(p, sz, PROT_READ | PROT_WRITE); |
@@ -808,10 +804,7 @@ init_chunk_info(struct dir_info *d, struct chunk_info *p, int bits) | |||
808 | int i; | 804 | int i; |
809 | 805 | ||
810 | if (bits == 0) { | 806 | if (bits == 0) { |
811 | p->shift = 1; | 807 | p->shift = MALLOC_MINSHIFT; |
812 | i = MALLOC_MINSIZE - 1; | ||
813 | while (i >>= 1) | ||
814 | p->shift++; | ||
815 | p->total = p->free = MALLOC_PAGESIZE >> p->shift; | 808 | p->total = p->free = MALLOC_PAGESIZE >> p->shift; |
816 | p->size = 0; | 809 | p->size = 0; |
817 | p->offset = 0xdead; | 810 | p->offset = 0xdead; |
@@ -824,13 +817,9 @@ init_chunk_info(struct dir_info *d, struct chunk_info *p, int bits) | |||
824 | p->canary = (u_short)d->canary1; | 817 | p->canary = (u_short)d->canary1; |
825 | 818 | ||
826 | /* set all valid bits in the bitmap */ | 819 | /* set all valid bits in the bitmap */ |
827 | for (i = 0; p->total - i >= MALLOC_BITS; i += MALLOC_BITS) | 820 | i = p->total - 1; |
828 | p->bits[i / MALLOC_BITS] = (u_short)~0U; | 821 | memset(p->bits, 0xff, sizeof(p->bits[0]) * (i / MALLOC_BITS)); |
829 | 822 | p->bits[i / MALLOC_BITS] = (2U << (i % MALLOC_BITS)) - 1; | |
830 | if (i < p->total) | ||
831 | p->bits[i / MALLOC_BITS] = 0; | ||
832 | for (; i < p->total; i++) | ||
833 | p->bits[i / MALLOC_BITS] |= (u_short)1U << (i % MALLOC_BITS); | ||
834 | } | 823 | } |
835 | 824 | ||
836 | static struct chunk_info * | 825 | static struct chunk_info * |
@@ -907,23 +896,20 @@ err: | |||
907 | static int | 896 | static int |
908 | find_chunksize(size_t size) | 897 | find_chunksize(size_t size) |
909 | { | 898 | { |
910 | int i, j; | 899 | int r; |
911 | 900 | ||
912 | /* Don't bother with anything less than this */ | 901 | /* malloc(0) is special */ |
913 | /* unless we have a malloc(0) requests */ | 902 | if (size == 0) |
914 | if (size != 0 && size < MALLOC_MINSIZE) | 903 | return 0; |
904 | |||
905 | if (size < MALLOC_MINSIZE) | ||
915 | size = MALLOC_MINSIZE; | 906 | size = MALLOC_MINSIZE; |
907 | size--; | ||
916 | 908 | ||
917 | /* Find the right bucket */ | 909 | r = MALLOC_MINSHIFT; |
918 | if (size == 0) | 910 | while (size >> r) |
919 | j = 0; | 911 | r++; |
920 | else { | 912 | return r; |
921 | j = MALLOC_MINSHIFT; | ||
922 | i = (size - 1) >> (MALLOC_MINSHIFT - 1); | ||
923 | while (i >>= 1) | ||
924 | j++; | ||
925 | } | ||
926 | return j; | ||
927 | } | 913 | } |
928 | 914 | ||
929 | static void | 915 | static void |
@@ -1013,7 +999,7 @@ found: | |||
1013 | *lp ^= u; | 999 | *lp ^= u; |
1014 | 1000 | ||
1015 | /* If there are no more free, remove from free-list */ | 1001 | /* If there are no more free, remove from free-list */ |
1016 | if (!--bp->free) | 1002 | if (--bp->free == 0) |
1017 | LIST_REMOVE(bp, entries); | 1003 | LIST_REMOVE(bp, entries); |
1018 | 1004 | ||
1019 | /* Adjust to the real offset of that chunk */ | 1005 | /* Adjust to the real offset of that chunk */ |
@@ -1048,8 +1034,8 @@ validate_canary(struct dir_info *d, u_char *ptr, size_t sz, size_t allocated) | |||
1048 | while (p < q) { | 1034 | while (p < q) { |
1049 | if (*p != SOME_JUNK) { | 1035 | if (*p != SOME_JUNK) { |
1050 | wrterror(d, "chunk canary corrupted %p %#tx@%#zx%s", | 1036 | wrterror(d, "chunk canary corrupted %p %#tx@%#zx%s", |
1051 | ptr, p - ptr, sz, *p == SOME_FREEJUNK ? | 1037 | ptr, p - ptr, sz, |
1052 | " (double free?)" : ""); | 1038 | *p == SOME_FREEJUNK ? " (double free?)" : ""); |
1053 | } | 1039 | } |
1054 | p++; | 1040 | p++; |
1055 | } | 1041 | } |
@@ -1173,8 +1159,7 @@ omalloc(struct dir_info *pool, size_t sz, int zero_fill, void *f) | |||
1173 | else | 1159 | else |
1174 | memset(p, SOME_JUNK, | 1160 | memset(p, SOME_JUNK, |
1175 | psz - mopts.malloc_guard); | 1161 | psz - mopts.malloc_guard); |
1176 | } | 1162 | } else if (mopts.chunk_canaries) |
1177 | else if (mopts.chunk_canaries) | ||
1178 | fill_canary(p, sz - mopts.malloc_guard, | 1163 | fill_canary(p, sz - mopts.malloc_guard, |
1179 | psz - mopts.malloc_guard); | 1164 | psz - mopts.malloc_guard); |
1180 | } | 1165 | } |
@@ -1225,7 +1210,7 @@ _malloc_init(int from_rthreads) | |||
1225 | max = from_rthreads ? _MALLOC_MUTEXES : 1; | 1210 | max = from_rthreads ? _MALLOC_MUTEXES : 1; |
1226 | if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0) | 1211 | if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0) |
1227 | mprotect(&malloc_readonly, sizeof(malloc_readonly), | 1212 | mprotect(&malloc_readonly, sizeof(malloc_readonly), |
1228 | PROT_READ | PROT_WRITE); | 1213 | PROT_READ | PROT_WRITE); |
1229 | for (i = 0; i < max; i++) { | 1214 | for (i = 0; i < max; i++) { |
1230 | if (mopts.malloc_pool[i]) | 1215 | if (mopts.malloc_pool[i]) |
1231 | continue; | 1216 | continue; |
@@ -2030,8 +2015,7 @@ omemalign(struct dir_info *pool, size_t alignment, size_t sz, int zero_fill, | |||
2030 | SOME_JUNK, psz - sz); | 2015 | SOME_JUNK, psz - sz); |
2031 | else | 2016 | else |
2032 | memset(p, SOME_JUNK, psz - mopts.malloc_guard); | 2017 | memset(p, SOME_JUNK, psz - mopts.malloc_guard); |
2033 | } | 2018 | } else if (mopts.chunk_canaries) |
2034 | else if (mopts.chunk_canaries) | ||
2035 | fill_canary(p, sz - mopts.malloc_guard, | 2019 | fill_canary(p, sz - mopts.malloc_guard, |
2036 | psz - mopts.malloc_guard); | 2020 | psz - mopts.malloc_guard); |
2037 | 2021 | ||