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 | |
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.
-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 | ||