diff options
author | tedu <> | 2014-05-12 19:02:20 +0000 |
---|---|---|
committer | tedu <> | 2014-05-12 19:02:20 +0000 |
commit | 1b7bf9f1ebd8096b9d44b3bf148bd664715501ab (patch) | |
tree | 63bbc29300741fdb381b71619be0351944a63078 /src | |
parent | dede2c823d35f580f859348c66c7313aa7093350 (diff) | |
download | openbsd-1b7bf9f1ebd8096b9d44b3bf148bd664715501ab.tar.gz openbsd-1b7bf9f1ebd8096b9d44b3bf148bd664715501ab.tar.bz2 openbsd-1b7bf9f1ebd8096b9d44b3bf148bd664715501ab.zip |
change to having four freelists per size, to reduce another source of
deterministic behavior. four selected because it's more than three, less
than five. i.e., no particular reason.
Diffstat (limited to 'src')
-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 | ||