diff options
-rw-r--r-- | src/lib/libc/stdlib/malloc.c | 35 |
1 files changed, 15 insertions, 20 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index c3b2332251..81ad79dfd3 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.291 2023/10/22 12:19:26 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.292 2023/10/26 17:59:16 otto Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net> | 3 | * Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net> |
4 | * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> | 4 | * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> |
@@ -169,16 +169,12 @@ struct dir_info { | |||
169 | void *caller; | 169 | void *caller; |
170 | size_t inserts; | 170 | size_t inserts; |
171 | size_t insert_collisions; | 171 | size_t insert_collisions; |
172 | size_t finds; | ||
173 | size_t find_collisions; | ||
174 | size_t deletes; | 172 | size_t deletes; |
175 | size_t delete_moves; | 173 | size_t delete_moves; |
176 | size_t cheap_realloc_tries; | 174 | size_t cheap_realloc_tries; |
177 | size_t cheap_reallocs; | 175 | size_t cheap_reallocs; |
178 | size_t malloc_used; /* bytes allocated */ | 176 | size_t malloc_used; /* bytes allocated */ |
179 | size_t malloc_guarded; /* bytes used for guards */ | 177 | size_t malloc_guarded; /* bytes used for guards */ |
180 | size_t pool_searches; /* searches for pool */ | ||
181 | size_t other_pool; /* searches in other pool */ | ||
182 | #define STATS_ADD(x,y) ((x) += (y)) | 178 | #define STATS_ADD(x,y) ((x) += (y)) |
183 | #define STATS_SUB(x,y) ((x) -= (y)) | 179 | #define STATS_SUB(x,y) ((x) -= (y)) |
184 | #define STATS_INC(x) ((x)++) | 180 | #define STATS_INC(x) ((x)++) |
@@ -209,12 +205,14 @@ static void unmap(struct dir_info *d, void *p, size_t sz, size_t clear); | |||
209 | struct chunk_info { | 205 | struct chunk_info { |
210 | LIST_ENTRY(chunk_info) entries; | 206 | LIST_ENTRY(chunk_info) entries; |
211 | void *page; /* pointer to the page */ | 207 | void *page; /* pointer to the page */ |
208 | /* number of shorts should add up to 8, check alloc_chunk_info() */ | ||
212 | u_short canary; | 209 | u_short canary; |
213 | u_short bucket; | 210 | u_short bucket; |
214 | u_short free; /* how many free chunks */ | 211 | u_short free; /* how many free chunks */ |
215 | u_short total; /* how many chunks */ | 212 | u_short total; /* how many chunks */ |
216 | u_short offset; /* requested size table offset */ | 213 | u_short offset; /* requested size table offset */ |
217 | u_short bits[1]; /* which chunks are free */ | 214 | #define CHUNK_INFO_TAIL 3 |
215 | u_short bits[CHUNK_INFO_TAIL]; /* which chunks are free */ | ||
218 | }; | 216 | }; |
219 | 217 | ||
220 | #define CHUNK_FREE(i, n) ((i)->bits[(n) / MALLOC_BITS] & (1U << ((n) % MALLOC_BITS))) | 218 | #define CHUNK_FREE(i, n) ((i)->bits[(n) / MALLOC_BITS] & (1U << ((n) % MALLOC_BITS))) |
@@ -656,12 +654,10 @@ find(struct dir_info *d, void *p) | |||
656 | index = hash(p) & mask; | 654 | index = hash(p) & mask; |
657 | r = d->r[index].p; | 655 | r = d->r[index].p; |
658 | q = MASK_POINTER(r); | 656 | q = MASK_POINTER(r); |
659 | STATS_INC(d->finds); | ||
660 | while (q != p && r != NULL) { | 657 | while (q != p && r != NULL) { |
661 | index = (index - 1) & mask; | 658 | index = (index - 1) & mask; |
662 | r = d->r[index].p; | 659 | r = d->r[index].p; |
663 | q = MASK_POINTER(r); | 660 | q = MASK_POINTER(r); |
664 | STATS_INC(d->find_collisions); | ||
665 | } | 661 | } |
666 | return (q == p && r != NULL) ? &d->r[index] : NULL; | 662 | return (q == p && r != NULL) ? &d->r[index] : NULL; |
667 | } | 663 | } |
@@ -949,7 +945,7 @@ init_chunk_info(struct dir_info *d, struct chunk_info *p, u_int bucket) | |||
949 | 945 | ||
950 | p->bucket = bucket; | 946 | p->bucket = bucket; |
951 | p->total = p->free = MALLOC_PAGESIZE / B2ALLOC(bucket); | 947 | p->total = p->free = MALLOC_PAGESIZE / B2ALLOC(bucket); |
952 | p->offset = bucket == 0 ? 0xdead : howmany(p->total, MALLOC_BITS); | 948 | p->offset = howmany(p->total, MALLOC_BITS); |
953 | p->canary = (u_short)d->canary1; | 949 | p->canary = (u_short)d->canary1; |
954 | 950 | ||
955 | /* set all valid bits in the bitmap */ | 951 | /* set all valid bits in the bitmap */ |
@@ -971,8 +967,13 @@ alloc_chunk_info(struct dir_info *d, u_int bucket) | |||
971 | count = MALLOC_PAGESIZE / B2ALLOC(bucket); | 967 | count = MALLOC_PAGESIZE / B2ALLOC(bucket); |
972 | 968 | ||
973 | size = howmany(count, MALLOC_BITS); | 969 | size = howmany(count, MALLOC_BITS); |
974 | size = sizeof(struct chunk_info) + (size - 1) * sizeof(u_short); | 970 | /* see declaration of struct chunk_info */ |
975 | if (mopts.chunk_canaries) | 971 | if (size <= CHUNK_INFO_TAIL) |
972 | size = 0; | ||
973 | else | ||
974 | size -= CHUNK_INFO_TAIL; | ||
975 | size = sizeof(struct chunk_info) + size * sizeof(u_short); | ||
976 | if (mopts.chunk_canaries && bucket > 0) | ||
976 | size += count * sizeof(u_short); | 977 | size += count * sizeof(u_short); |
977 | size = _ALIGN(size); | 978 | size = _ALIGN(size); |
978 | count = MALLOC_PAGESIZE / size; | 979 | count = MALLOC_PAGESIZE / size; |
@@ -1129,8 +1130,7 @@ fill_canary(char *ptr, size_t sz, size_t allocated) | |||
1129 | static void * | 1130 | static void * |
1130 | malloc_bytes(struct dir_info *d, size_t size) | 1131 | malloc_bytes(struct dir_info *d, size_t size) |
1131 | { | 1132 | { |
1132 | u_int i, r, bucket, listnum; | 1133 | u_int i, k, r, bucket, listnum; |
1133 | size_t k; | ||
1134 | u_short *lp; | 1134 | u_short *lp; |
1135 | struct chunk_info *bp; | 1135 | struct chunk_info *bp; |
1136 | void *p; | 1136 | void *p; |
@@ -1170,7 +1170,7 @@ malloc_bytes(struct dir_info *d, size_t size) | |||
1170 | /* no bit halfway, go to next full short */ | 1170 | /* no bit halfway, go to next full short */ |
1171 | i /= MALLOC_BITS; | 1171 | i /= MALLOC_BITS; |
1172 | for (;;) { | 1172 | for (;;) { |
1173 | if (++i >= howmany(bp->total, MALLOC_BITS)) | 1173 | if (++i >= bp->offset) |
1174 | i = 0; | 1174 | i = 0; |
1175 | lp = &bp->bits[i]; | 1175 | lp = &bp->bits[i]; |
1176 | if (*lp) { | 1176 | if (*lp) { |
@@ -1228,7 +1228,7 @@ validate_canary(struct dir_info *d, u_char *ptr, size_t sz, size_t allocated) | |||
1228 | } | 1228 | } |
1229 | } | 1229 | } |
1230 | 1230 | ||
1231 | static uint32_t | 1231 | static inline uint32_t |
1232 | find_chunknum(struct dir_info *d, struct chunk_info *info, void *ptr, int check) | 1232 | find_chunknum(struct dir_info *d, struct chunk_info *info, void *ptr, int check) |
1233 | { | 1233 | { |
1234 | uint32_t chunknum; | 1234 | uint32_t chunknum; |
@@ -1532,12 +1532,10 @@ findpool(void *p, struct dir_info *argpool, struct dir_info **foundpool, | |||
1532 | struct dir_info *pool = argpool; | 1532 | struct dir_info *pool = argpool; |
1533 | struct region_info *r = find(pool, p); | 1533 | struct region_info *r = find(pool, p); |
1534 | 1534 | ||
1535 | STATS_INC(pool->pool_searches); | ||
1536 | if (r == NULL) { | 1535 | if (r == NULL) { |
1537 | u_int i, nmutexes; | 1536 | u_int i, nmutexes; |
1538 | 1537 | ||
1539 | nmutexes = mopts.malloc_pool[1]->malloc_mt ? mopts.malloc_mutexes : 2; | 1538 | nmutexes = mopts.malloc_pool[1]->malloc_mt ? mopts.malloc_mutexes : 2; |
1540 | STATS_INC(pool->other_pool); | ||
1541 | for (i = 1; i < nmutexes; i++) { | 1539 | for (i = 1; i < nmutexes; i++) { |
1542 | u_int j = (argpool->mutex + i) & (nmutexes - 1); | 1540 | u_int j = (argpool->mutex + i) & (nmutexes - 1); |
1543 | 1541 | ||
@@ -2581,13 +2579,10 @@ malloc_dump1(int poolno, struct dir_info *d, struct leaktree *leaks) | |||
2581 | d->mmap_flag); | 2579 | d->mmap_flag); |
2582 | ulog("Region slots free %zu/%zu\n", | 2580 | ulog("Region slots free %zu/%zu\n", |
2583 | d->regions_free, d->regions_total); | 2581 | d->regions_free, d->regions_total); |
2584 | ulog("Finds %zu/%zu\n", d->finds, d->find_collisions); | ||
2585 | ulog("Inserts %zu/%zu\n", d->inserts, d->insert_collisions); | 2582 | ulog("Inserts %zu/%zu\n", d->inserts, d->insert_collisions); |
2586 | ulog("Deletes %zu/%zu\n", d->deletes, d->delete_moves); | 2583 | ulog("Deletes %zu/%zu\n", d->deletes, d->delete_moves); |
2587 | ulog("Cheap reallocs %zu/%zu\n", | 2584 | ulog("Cheap reallocs %zu/%zu\n", |
2588 | d->cheap_reallocs, d->cheap_realloc_tries); | 2585 | d->cheap_reallocs, d->cheap_realloc_tries); |
2589 | ulog("Other pool searches %zu/%zu\n", | ||
2590 | d->other_pool, d->pool_searches); | ||
2591 | ulog("In use %zu\n", d->malloc_used); | 2586 | ulog("In use %zu\n", d->malloc_used); |
2592 | ulog("Guarded %zu\n", d->malloc_guarded); | 2587 | ulog("Guarded %zu\n", d->malloc_guarded); |
2593 | dump_free_chunk_info(d, leaks); | 2588 | dump_free_chunk_info(d, leaks); |