From d8de214e9d1040c84226d42edd5b8afeac83e295 Mon Sep 17 00:00:00 2001 From: tedu <> Date: Fri, 22 Jun 2012 01:30:17 +0000 Subject: [PATCH] two changes which should improve realloc. first, fix zapcacheregion to clear out the entire requested area, not just a perfect fit. second, use mquery to check for room to avoid getting an address we don't like and having to send it back. --- src/lib/libc/stdlib/malloc.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 92efd7d6..7a48a0f2 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/lib/libc/stdlib/malloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: malloc.c,v 1.143 2012/06/20 13:13:15 tedu Exp $ */ +/* $OpenBSD: malloc.c,v 1.144 2012/06/22 01:30:17 tedu Exp $ */ /* * Copyright (c) 2008 Otto Moerbeek * @@ -94,6 +94,9 @@ #define MMAPA(a,sz) mmap((a), (size_t)(sz), PROT_READ | PROT_WRITE, \ MAP_ANON | MAP_PRIVATE, -1, (off_t) 0) +#define MQUERY(a, sz) mquery((a), (size_t)(sz), PROT_READ | PROT_WRITE, \ + MAP_ANON | MAP_PRIVATE, -1, (off_t)0) + struct region_info { void *p; /* page; low bits used to mark chunks */ uintptr_t size; /* size for pages, or chunk_info pointer */ @@ -356,7 +359,7 @@ unmap(struct dir_info *d, void *p, size_t sz) } static void -zapcacheregion(struct dir_info *d, void *p) +zapcacheregion(struct dir_info *d, void *p, size_t len) { u_int i; struct region_info *r; @@ -364,7 +367,7 @@ zapcacheregion(struct dir_info *d, void *p) for (i = 0; i < mopts.malloc_cache; i++) { r = &d->free_regions[i]; - if (r->p == p) { + if (r->p >= p && r->p <= (void *)((char *)p + len)) { rsz = r->size << MALLOC_PAGESHIFT; if (munmap(r->p, rsz)) wrterror("munmap", r->p); @@ -1283,20 +1286,26 @@ orealloc(void *p, size_t newsz, void *f) if (rnewsz > roldsz) { if (!mopts.malloc_guard) { + void *hint = (char *)p + roldsz; + size_t needed = rnewsz - roldsz; + STATS_INC(g_pool->cheap_realloc_tries); - zapcacheregion(g_pool, (char *)p + roldsz); - q = MMAPA((char *)p + roldsz, rnewsz - roldsz); - if (q == (char *)p + roldsz) { - malloc_used += rnewsz - roldsz; + zapcacheregion(g_pool, hint, needed); + q = MQUERY(hint, needed); + if (q == hint) + q = MMAPA(hint, needed); + else + q = MAP_FAILED; + if (q == hint) { + malloc_used += needed; if (mopts.malloc_junk) - memset(q, SOME_JUNK, - rnewsz - roldsz); + memset(q, SOME_JUNK, needed); r->size = newsz; STATS_SETF(r, f); STATS_INC(g_pool->cheap_reallocs); return p; } else if (q != MAP_FAILED) { - if (munmap(q, rnewsz - roldsz)) + if (munmap(q, needed)) wrterror("munmap", q); } }