Browse Source

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@
OPENBSD_4_5
otto 16 years ago
parent
commit
cdd5a2c930
1 changed files with 41 additions and 3 deletions
  1. +41
    -3
      src/lib/libc/stdlib/malloc.c

+ 41
- 3
src/lib/libc/stdlib/malloc.c View File

@ -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> * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
* *
@ -78,6 +78,9 @@
#define MMAP(sz) mmap(NULL, (size_t)(sz), PROT_READ | PROT_WRITE, \ #define MMAP(sz) mmap(NULL, (size_t)(sz), PROT_READ | PROT_WRITE, \
MAP_ANON | MAP_PRIVATE, -1, (off_t) 0) 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 { struct region_info {
void *p; /* page; low bits used to mark chunks */ void *p; /* page; low bits used to mark chunks */
uintptr_t size; /* size for pages, or chunk_info pointer */ 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"); 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 * static void *
map(struct dir_info *d, size_t sz, int zero_fill) 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 roldsz = PAGEROUND(goldsz);
size_t rnewsz = PAGEROUND(gnewsz); 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 (malloc_guard) {
if (mprotect((char *)p + roldsz - malloc_guard, if (mprotect((char *)p + roldsz - malloc_guard,
malloc_guard, PROT_READ | PROT_WRITE)) malloc_guard, PROT_READ | PROT_WRITE))
@ -1289,7 +1327,7 @@ orealloc(void *p, size_t newsz)
unmap(&g_pool, (char *)p + rnewsz, roldsz - rnewsz); unmap(&g_pool, (char *)p + rnewsz, roldsz - rnewsz);
r->size = gnewsz; r->size = gnewsz;
return p; return p;
} else if (rnewsz == roldsz) {
} else {
if (newsz > oldsz && malloc_junk) if (newsz > oldsz && malloc_junk)
memset((char *)p + newsz, SOME_JUNK, memset((char *)p + newsz, SOME_JUNK,
rnewsz - malloc_guard - newsz); rnewsz - malloc_guard - newsz);


Loading…
Cancel
Save