diff options
Diffstat (limited to 'src/lib/libc/stdlib/malloc.c')
| -rw-r--r-- | src/lib/libc/stdlib/malloc.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 361294eb51..c0542fc9c8 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.162 2014/05/10 18:14:55 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.163 2014/05/12 19:02:20 tedu Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net> | 3 | * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net> |
| 4 | * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> | 4 | * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> |
| @@ -64,6 +64,7 @@ | |||
| 64 | #define MALLOC_DELAYED_CHUNK_MASK 15 | 64 | #define MALLOC_DELAYED_CHUNK_MASK 15 |
| 65 | #define MALLOC_INITIAL_REGIONS 512 | 65 | #define MALLOC_INITIAL_REGIONS 512 |
| 66 | #define MALLOC_DEFAULT_CACHE 64 | 66 | #define MALLOC_DEFAULT_CACHE 64 |
| 67 | #define MALLOC_CHUNK_LISTS 4 | ||
| 67 | 68 | ||
| 68 | /* | 69 | /* |
| 69 | * When the P option is active, we move allocations between half a page | 70 | * When the P option is active, we move allocations between half a page |
| @@ -110,7 +111,7 @@ struct dir_info { | |||
| 110 | /* lists of free chunk info structs */ | 111 | /* lists of free chunk info structs */ |
| 111 | struct chunk_head chunk_info_list[MALLOC_MAXSHIFT + 1]; | 112 | struct chunk_head chunk_info_list[MALLOC_MAXSHIFT + 1]; |
| 112 | /* lists of chunks with free slots */ | 113 | /* lists of chunks with free slots */ |
| 113 | struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1]; | 114 | struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1][MALLOC_CHUNK_LISTS]; |
| 114 | size_t free_regions_size; /* free pages cached */ | 115 | size_t free_regions_size; /* free pages cached */ |
| 115 | /* free pages cache */ | 116 | /* free pages cache */ |
| 116 | struct region_info free_regions[MALLOC_MAXCACHE]; | 117 | struct region_info free_regions[MALLOC_MAXCACHE]; |
| @@ -621,7 +622,8 @@ omalloc_init(struct dir_info **dp) | |||
| 621 | } | 622 | } |
| 622 | for (i = 0; i <= MALLOC_MAXSHIFT; i++) { | 623 | for (i = 0; i <= MALLOC_MAXSHIFT; i++) { |
| 623 | LIST_INIT(&d->chunk_info_list[i]); | 624 | LIST_INIT(&d->chunk_info_list[i]); |
| 624 | LIST_INIT(&d->chunk_dir[i]); | 625 | for (j = 0; j < MALLOC_CHUNK_LISTS; j++) |
| 626 | LIST_INIT(&d->chunk_dir[i][j]); | ||
| 625 | } | 627 | } |
| 626 | malloc_used += regioninfo_size; | 628 | malloc_used += regioninfo_size; |
| 627 | d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d; | 629 | d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d; |
| @@ -816,7 +818,7 @@ delete(struct dir_info *d, struct region_info *ri) | |||
| 816 | * Allocate a page of chunks | 818 | * Allocate a page of chunks |
| 817 | */ | 819 | */ |
| 818 | static struct chunk_info * | 820 | static struct chunk_info * |
| 819 | omalloc_make_chunks(struct dir_info *d, int bits) | 821 | omalloc_make_chunks(struct dir_info *d, int bits, int listnum) |
| 820 | { | 822 | { |
| 821 | struct chunk_info *bp; | 823 | struct chunk_info *bp; |
| 822 | void *pp; | 824 | void *pp; |
| @@ -867,7 +869,7 @@ omalloc_make_chunks(struct dir_info *d, int bits) | |||
| 867 | for (; i < k; i++) | 869 | for (; i < k; i++) |
| 868 | bp->bits[i / MALLOC_BITS] |= (u_short)1U << (i % MALLOC_BITS); | 870 | bp->bits[i / MALLOC_BITS] |= (u_short)1U << (i % MALLOC_BITS); |
| 869 | 871 | ||
| 870 | LIST_INSERT_HEAD(&d->chunk_dir[bits], bp, entries); | 872 | LIST_INSERT_HEAD(&d->chunk_dir[bits][listnum], bp, entries); |
| 871 | 873 | ||
| 872 | bits++; | 874 | bits++; |
| 873 | if ((uintptr_t)pp & bits) | 875 | if ((uintptr_t)pp & bits) |
| @@ -884,7 +886,7 @@ omalloc_make_chunks(struct dir_info *d, int bits) | |||
| 884 | static void * | 886 | static void * |
| 885 | malloc_bytes(struct dir_info *d, size_t size, void *f) | 887 | malloc_bytes(struct dir_info *d, size_t size, void *f) |
| 886 | { | 888 | { |
| 887 | int i, j; | 889 | int i, j, listnum; |
| 888 | size_t k; | 890 | size_t k; |
| 889 | u_short u, *lp; | 891 | u_short u, *lp; |
| 890 | struct chunk_info *bp; | 892 | struct chunk_info *bp; |
| @@ -907,13 +909,13 @@ malloc_bytes(struct dir_info *d, size_t size, void *f) | |||
| 907 | j++; | 909 | j++; |
| 908 | } | 910 | } |
| 909 | 911 | ||
| 912 | listnum = getrbyte() % MALLOC_CHUNK_LISTS; | ||
| 910 | /* If it's empty, make a page more of that size chunks */ | 913 | /* If it's empty, make a page more of that size chunks */ |
| 911 | if (LIST_EMPTY(&d->chunk_dir[j])) { | 914 | if ((bp = LIST_FIRST(&d->chunk_dir[j][listnum])) == NULL) { |
| 912 | bp = omalloc_make_chunks(d, j); | 915 | bp = omalloc_make_chunks(d, j, listnum); |
| 913 | if (bp == NULL) | 916 | if (bp == NULL) |
| 914 | return NULL; | 917 | return NULL; |
| 915 | } else | 918 | } |
| 916 | bp = LIST_FIRST(&d->chunk_dir[j]); | ||
| 917 | 919 | ||
| 918 | if (bp->canary != d->canary1) | 920 | if (bp->canary != d->canary1) |
| 919 | wrterror("chunk info corrupted", NULL); | 921 | wrterror("chunk info corrupted", NULL); |
| @@ -973,7 +975,7 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr) | |||
| 973 | { | 975 | { |
| 974 | struct chunk_head *mp; | 976 | struct chunk_head *mp; |
| 975 | struct chunk_info *info; | 977 | struct chunk_info *info; |
| 976 | int i; | 978 | int i, listnum; |
| 977 | 979 | ||
| 978 | info = (struct chunk_info *)r->size; | 980 | info = (struct chunk_info *)r->size; |
| 979 | if (info->canary != d->canary1) | 981 | if (info->canary != d->canary1) |
| @@ -994,16 +996,18 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr) | |||
| 994 | info->bits[i / MALLOC_BITS] |= 1U << (i % MALLOC_BITS); | 996 | info->bits[i / MALLOC_BITS] |= 1U << (i % MALLOC_BITS); |
| 995 | info->free++; | 997 | info->free++; |
| 996 | 998 | ||
| 997 | if (info->size != 0) | ||
| 998 | mp = d->chunk_dir + info->shift; | ||
| 999 | else | ||
| 1000 | mp = d->chunk_dir; | ||
| 1001 | |||
| 1002 | if (info->free == 1) { | 999 | if (info->free == 1) { |
| 1003 | /* Page became non-full */ | 1000 | /* Page became non-full */ |
| 1001 | listnum = getrbyte() % MALLOC_CHUNK_LISTS; | ||
| 1002 | if (info->size != 0) | ||
| 1003 | mp = &d->chunk_dir[info->shift][listnum]; | ||
| 1004 | else | ||
| 1005 | mp = &d->chunk_dir[0][listnum]; | ||
| 1006 | |||
| 1004 | LIST_INSERT_HEAD(mp, info, entries); | 1007 | LIST_INSERT_HEAD(mp, info, entries); |
| 1005 | return; | 1008 | return; |
| 1006 | } | 1009 | } |
| 1010 | |||
| 1007 | if (info->free != info->total) | 1011 | if (info->free != info->total) |
| 1008 | return; | 1012 | return; |
| 1009 | 1013 | ||
