summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2011-05-05 12:11:21 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2011-05-05 12:11:21 +0000
commit3507176bda3b5c66ab178e2eab9e1daf6502a7c3 (patch)
tree7bd9b1013d49527a2e3ab7c595b589020acccdcf /lib
parenta3fd6084d44ed453397a1d4ee24f6c1150d1ffd0 (diff)
Up until now, malloc scanned the bits of the chunk bitmap from
position zero, skipping a random number of free slots and then picking the next free one. This slowed things down, especially if the number of full slots increases. This changes the scannning to start at a random position in the bitmap and then taking the first available free slot, wrapping if the end of the bitmap is reached. Of course we'll still scan more if the bitmap becomes more full, but the extra iterations skipping free slots and then some full slots are avoided. The random number is derived from a global, which is incremented by a few random bits every time a chunk is needed (with a small optimization if only one free slot is left). Thanks to the testers!
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdlib/malloc.c56
1 files changed, 24 insertions, 32 deletions
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 84ca2be7183..0d1b2290be5 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: malloc.c,v 1.129 2011/04/30 15:46:46 otto Exp $ */
+/* $OpenBSD: malloc.c,v 1.130 2011/05/05 12:11:20 otto Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
@@ -113,6 +113,7 @@ struct dir_info {
struct region_info free_regions[MALLOC_MAXCACHE];
/* delayed free chunk slots */
void *delayed_chunks[MALLOC_DELAYED_CHUNKS + 1];
+ u_short chunk_start;
#ifdef MALLOC_STATS
size_t inserts;
size_t insert_collisions;
@@ -1013,40 +1014,31 @@ malloc_bytes(struct dir_info *d, size_t size)
if (bp->canary != d->canary1)
wrterror("chunk info corrupted", NULL);
- /* Find first word of bitmap which isn't empty */
- for (lp = bp->bits; !*lp; lp++)
- /* EMPTY */;
-
- /* Find that bit, and tweak it */
- u = 1;
- k = 0;
- while (!(*lp & u)) {
- u += u;
- k++;
- }
- /* advance a random # of positions */
- if (bp->free > 1) {
- i = getrnibble() % bp->free;
- while (i > 0) {
- u += u;
- k++;
- if (k >= MALLOC_BITS) {
- while (!*++lp)
- /* EMPTY */;
- u = 1;
- k = 0;
- if (lp - bp->bits > (bp->total - 1) /
- MALLOC_BITS) {
- wrterror("chunk overflow", NULL);
- errno = EFAULT;
- return (NULL);
- }
- }
- if (*lp & u)
- i--;
+ i = d->chunk_start;
+ if (bp->free > 1)
+ i += getrnibble();
+ if (i >= bp->total)
+ i &= bp->total - 1;
+ for (;;) {
+ for (;;) {
+ lp = &bp->bits[i / MALLOC_BITS];
+ if (!*lp) {
+ i += MALLOC_BITS;
+ i &= ~(MALLOC_BITS - 1);
+ if (i >= bp->total)
+ i = 0;
+ } else
+ break;
}
+ k = i % MALLOC_BITS;
+ u = 1 << k;
+ if (*lp & u)
+ break;
+ if (++i >= bp->total)
+ i = 0;
}
+ d->chunk_start += i + 1;
*lp ^= u;