diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2008-10-03 18:44:30 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2008-10-03 18:44:30 +0000 |
commit | 3ed768f4dc2ac321ae74f18f47c627194c9cd78d (patch) | |
tree | 76bc47c612c49dc322ea62f807466e6cb72ce9ab /lib/libc | |
parent | 73b4d6fa72b5d71c2cb3271fc2ac8c8321fa0b02 (diff) |
when increasing the size of a larger than a page allocation try
mapping the region next to the existing one first; there's a pretty
high chance there's a hole there we can use; ok deraadt@ tedu@
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/stdlib/malloc.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index 1bd5c9f89c5..a205253fd48 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: malloc.c,v 1.99 2008/10/03 18:42:45 otto Exp $ */ +/* $OpenBSD: malloc.c,v 1.100 2008/10/03 18:44:29 otto Exp $ */ /* * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> * @@ -78,6 +78,9 @@ #define MMAP(sz) mmap(NULL, (size_t)(sz), PROT_READ | PROT_WRITE, \ MAP_ANON | MAP_PRIVATE, -1, (off_t) 0) +#define MMAPA(a,sz) mmap((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 */ @@ -440,6 +443,27 @@ unmap(struct dir_info *d, void *p, size_t sz) wrtwarning("malloc cache overflow"); } +static void +zapcacheregion(struct dir_info *d, void *p) +{ + u_int i; + struct region_info *r; + size_t rsz; + + for (i = 0; i < malloc_cache; i++) { + r = &d->free_regions[i]; + if (r->p == p) { + rsz = r->size << MALLOC_PAGESHIFT; + if (munmap(r->p, rsz)) + wrterror("munmap"); + r->p = NULL; + d->free_regions_size -= r->size; + r->size = 0; + malloc_used -= rsz; + } + } +} + static void * map(struct dir_info *d, size_t sz, int zero_fill) { @@ -1277,7 +1301,21 @@ orealloc(void *p, size_t newsz) size_t roldsz = PAGEROUND(goldsz); size_t rnewsz = PAGEROUND(gnewsz); - if (rnewsz < roldsz) { + if (rnewsz > roldsz) { + if (!malloc_guard) { + zapcacheregion(&g_pool, p + roldsz); + q = MMAPA(p + roldsz, rnewsz - roldsz); + if (q == p + roldsz) { + malloc_used += rnewsz - roldsz; + if (malloc_junk) + memset(q, SOME_JUNK, + rnewsz - roldsz); + r->size = newsz; + return p; + } else if (q != MAP_FAILED) + munmap(q, rnewsz - roldsz); + } + } else if (rnewsz < roldsz) { if (malloc_guard) { if (mprotect((char *)p + roldsz - malloc_guard, malloc_guard, PROT_READ | PROT_WRITE)) @@ -1289,7 +1327,7 @@ orealloc(void *p, size_t newsz) unmap(&g_pool, (char *)p + rnewsz, roldsz - rnewsz); r->size = gnewsz; return p; - } else if (rnewsz == roldsz) { + } else { if (newsz > oldsz && malloc_junk) memset((char *)p + newsz, SOME_JUNK, rnewsz - malloc_guard - newsz); |