Browse Source

small step towards multiple pools: move two globls into the struct dir_info

ok @stefan armani@
OPENBSD_6_0
otto 8 years ago
parent
commit
32c6baecf9
1 changed files with 126 additions and 112 deletions
  1. +126
    -112
      src/lib/libc/stdlib/malloc.c

+ 126
- 112
src/lib/libc/stdlib/malloc.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: malloc.c,v 1.183 2016/03/13 18:34:21 guenther Exp $ */
/* $OpenBSD: malloc.c,v 1.184 2016/03/14 17:20:26 otto Exp $ */
/* /*
* Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net> * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net>
* Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@ -93,13 +93,13 @@
#define MQUERY(a, sz) mquery((a), (size_t)(sz), PROT_READ | PROT_WRITE, \ #define MQUERY(a, sz) mquery((a), (size_t)(sz), PROT_READ | PROT_WRITE, \
MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t)0) MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t)0)
#define _MALLOC_LEAVE() if (__isthreaded) do { \
malloc_active--; \
#define _MALLOC_LEAVE(d) if (__isthreaded) do { \
(d)->active--; \
_MALLOC_UNLOCK(); \ _MALLOC_UNLOCK(); \
} while (0) } while (0)
#define _MALLOC_ENTER() if (__isthreaded) do { \
#define _MALLOC_ENTER(d) if (__isthreaded) do { \
_MALLOC_LOCK(); \ _MALLOC_LOCK(); \
malloc_active++; \
(d)->active++; \
} while (0) } while (0)
struct region_info { struct region_info {
@ -114,6 +114,7 @@ LIST_HEAD(chunk_head, chunk_info);
struct dir_info { struct dir_info {
u_int32_t canary1; u_int32_t canary1;
int active; /* status of malloc */
struct region_info *r; /* region slots */ struct region_info *r; /* region slots */
size_t regions_total; /* number of region slots */ size_t regions_total; /* number of region slots */
size_t regions_free; /* number of free slots */ size_t regions_free; /* number of free slots */
@ -127,6 +128,7 @@ struct dir_info {
/* delayed free chunk slots */ /* delayed free chunk slots */
void *delayed_chunks[MALLOC_DELAYED_CHUNK_MASK + 1]; void *delayed_chunks[MALLOC_DELAYED_CHUNK_MASK + 1];
size_t rbytesused; /* random bytes used */ size_t rbytesused; /* random bytes used */
char *func; /* current function */
u_char rbytes[32]; /* random bytes */ u_char rbytes[32]; /* random bytes */
u_short chunk_start; u_short chunk_start;
#ifdef MALLOC_STATS #ifdef MALLOC_STATS
@ -203,8 +205,6 @@ static union {
#define getpool() mopts.malloc_pool #define getpool() mopts.malloc_pool
char *malloc_options; /* compile-time options */ char *malloc_options; /* compile-time options */
static char *malloc_func; /* current function */
static int malloc_active; /* status of malloc */
static u_char getrbyte(struct dir_info *d); static u_char getrbyte(struct dir_info *d);
@ -241,7 +241,7 @@ hash(void *p)
} }
static void static void
wrterror(char *msg, void *p)
wrterror(struct dir_info *d, char *msg, void *p)
{ {
char *q = " error: "; char *q = " error: ";
struct iovec iov[7]; struct iovec iov[7];
@ -254,8 +254,13 @@ wrterror(char *msg, void *p)
iov[1].iov_base = pidbuf; iov[1].iov_base = pidbuf;
snprintf(pidbuf, sizeof(pidbuf), "(%d) in ", getpid()); snprintf(pidbuf, sizeof(pidbuf), "(%d) in ", getpid());
iov[1].iov_len = strlen(pidbuf); iov[1].iov_len = strlen(pidbuf);
iov[2].iov_base = malloc_func;
iov[2].iov_len = strlen(malloc_func);
if (d != NULL) {
iov[2].iov_base = d->func;
iov[2].iov_len = strlen(d->func);
} else {
iov[2].iov_base = "unknown";
iov[2].iov_len = 7;
}
iov[3].iov_base = q; iov[3].iov_base = q;
iov[3].iov_len = strlen(q); iov[3].iov_len = strlen(q);
iov[4].iov_base = msg; iov[4].iov_base = msg;
@ -316,14 +321,14 @@ unmap(struct dir_info *d, void *p, size_t sz)
u_int i, offset; u_int i, offset;
if (sz != PAGEROUND(sz)) { if (sz != PAGEROUND(sz)) {
wrterror("munmap round", NULL);
wrterror(d, "munmap round", NULL);
return; return;
} }
if (psz > mopts.malloc_cache) { if (psz > mopts.malloc_cache) {
i = munmap(p, sz); i = munmap(p, sz);
if (i) if (i)
wrterror("munmap", p);
wrterror(d, "munmap", p);
STATS_SUB(d->malloc_used, sz); STATS_SUB(d->malloc_used, sz);
return; return;
} }
@ -337,7 +342,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
if (r->p != NULL) { if (r->p != NULL) {
rsz = r->size << MALLOC_PAGESHIFT; rsz = r->size << MALLOC_PAGESHIFT;
if (munmap(r->p, rsz)) if (munmap(r->p, rsz))
wrterror("munmap", r->p);
wrterror(d, "munmap", r->p);
r->p = NULL; r->p = NULL;
if (tounmap > r->size) if (tounmap > r->size)
tounmap -= r->size; tounmap -= r->size;
@ -349,7 +354,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
} }
} }
if (tounmap > 0) if (tounmap > 0)
wrterror("malloc cache underflow", NULL);
wrterror(d, "malloc cache underflow", NULL);
for (i = 0; i < mopts.malloc_cache; i++) { for (i = 0; i < mopts.malloc_cache; i++) {
r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)]; r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
if (r->p == NULL) { if (r->p == NULL) {
@ -364,9 +369,9 @@ unmap(struct dir_info *d, void *p, size_t sz)
} }
} }
if (i == mopts.malloc_cache) if (i == mopts.malloc_cache)
wrterror("malloc free slot lost", NULL);
wrterror(d, "malloc free slot lost", NULL);
if (d->free_regions_size > mopts.malloc_cache) if (d->free_regions_size > mopts.malloc_cache)
wrterror("malloc cache overflow", NULL);
wrterror(d, "malloc cache overflow", NULL);
} }
static void static void
@ -381,7 +386,7 @@ zapcacheregion(struct dir_info *d, void *p, size_t len)
if (r->p >= p && r->p <= (void *)((char *)p + len)) { if (r->p >= p && r->p <= (void *)((char *)p + len)) {
rsz = r->size << MALLOC_PAGESHIFT; rsz = r->size << MALLOC_PAGESHIFT;
if (munmap(r->p, rsz)) if (munmap(r->p, rsz))
wrterror("munmap", r->p);
wrterror(d, "munmap", r->p);
r->p = NULL; r->p = NULL;
d->free_regions_size -= r->size; d->free_regions_size -= r->size;
r->size = 0; r->size = 0;
@ -400,15 +405,15 @@ map(struct dir_info *d, void *hint, size_t sz, int zero_fill)
if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
d->canary1 != ~d->canary2) d->canary1 != ~d->canary2)
wrterror("internal struct corrupt", NULL);
wrterror(d, "internal struct corrupt", NULL);
if (sz != PAGEROUND(sz)) { if (sz != PAGEROUND(sz)) {
wrterror("map round", NULL);
wrterror(d, "map round", NULL);
return MAP_FAILED; return MAP_FAILED;
} }
if (!hint && psz > d->free_regions_size) { if (!hint && psz > d->free_regions_size) {
_MALLOC_LEAVE();
_MALLOC_LEAVE(d);
p = MMAP(sz); p = MMAP(sz);
_MALLOC_ENTER();
_MALLOC_ENTER(d);
if (p != MAP_FAILED) if (p != MAP_FAILED)
STATS_ADD(d->malloc_used, sz); STATS_ADD(d->malloc_used, sz);
/* zero fill not needed */ /* zero fill not needed */
@ -458,10 +463,10 @@ map(struct dir_info *d, void *hint, size_t sz, int zero_fill)
if (hint) if (hint)
return MAP_FAILED; return MAP_FAILED;
if (d->free_regions_size > mopts.malloc_cache) if (d->free_regions_size > mopts.malloc_cache)
wrterror("malloc cache", NULL);
_MALLOC_LEAVE();
wrterror(d, "malloc cache", NULL);
_MALLOC_LEAVE(d);
p = MMAP(sz); p = MMAP(sz);
_MALLOC_ENTER();
_MALLOC_ENTER(d);
if (p != MAP_FAILED) if (p != MAP_FAILED)
STATS_ADD(d->malloc_used, sz); STATS_ADD(d->malloc_used, sz);
/* zero fill not needed */ /* zero fill not needed */
@ -652,7 +657,7 @@ omalloc_init(struct dir_info **dp)
regioninfo_size = d->regions_total * sizeof(struct region_info); regioninfo_size = d->regions_total * sizeof(struct region_info);
d->r = MMAP(regioninfo_size); d->r = MMAP(regioninfo_size);
if (d->r == MAP_FAILED) { if (d->r == MAP_FAILED) {
wrterror("malloc init mmap failed", NULL);
wrterror(NULL, "malloc init mmap failed", NULL);
d->regions_total = 0; d->regions_total = 0;
return 1; return 1;
} }
@ -715,7 +720,7 @@ omalloc_grow(struct dir_info *d)
} }
/* avoid pages containing meta info to end up in cache */ /* avoid pages containing meta info to end up in cache */
if (munmap(d->r, d->regions_total * sizeof(struct region_info))) if (munmap(d->r, d->regions_total * sizeof(struct region_info)))
wrterror("munmap", d->r);
wrterror(d, "munmap", d->r);
else else
STATS_SUB(d->malloc_used, STATS_SUB(d->malloc_used,
d->regions_total * sizeof(struct region_info)); d->regions_total * sizeof(struct region_info));
@ -803,7 +808,7 @@ find(struct dir_info *d, void *p)
if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
d->canary1 != ~d->canary2) d->canary1 != ~d->canary2)
wrterror("internal struct corrupt", NULL);
wrterror(d, "internal struct corrupt", NULL);
p = MASK_POINTER(p); p = MASK_POINTER(p);
index = hash(p) & mask; index = hash(p) & mask;
r = d->r[index].p; r = d->r[index].p;
@ -826,9 +831,9 @@ delete(struct dir_info *d, struct region_info *ri)
size_t i, j, r; size_t i, j, r;
if (d->regions_total & (d->regions_total - 1)) if (d->regions_total & (d->regions_total - 1))
wrterror("regions_total not 2^x", NULL);
wrterror(d, "regions_total not 2^x", NULL);
d->regions_free++; d->regions_free++;
STATS_INC(getpool()->deletes);
STATS_INC(d->deletes);
i = ri - d->r; i = ri - d->r;
for (;;) { for (;;) {
@ -844,7 +849,7 @@ delete(struct dir_info *d, struct region_info *ri)
(j < i && i <= r)) (j < i && i <= r))
continue; continue;
d->r[j] = d->r[i]; d->r[j] = d->r[i];
STATS_INC(getpool()->delete_moves);
STATS_INC(d->delete_moves);
break; break;
} }
@ -910,7 +915,7 @@ omalloc_make_chunks(struct dir_info *d, int bits, int listnum)
bits++; bits++;
if ((uintptr_t)pp & bits) if ((uintptr_t)pp & bits)
wrterror("pp & bits", pp);
wrterror(d, "pp & bits", pp);
insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp, NULL); insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp, NULL);
return bp; return bp;
@ -930,7 +935,7 @@ malloc_bytes(struct dir_info *d, size_t size, void *f)
if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
d->canary1 != ~d->canary2) d->canary1 != ~d->canary2)
wrterror("internal struct corrupt", NULL);
wrterror(d, "internal struct corrupt", NULL);
/* Don't bother with anything less than this */ /* Don't bother with anything less than this */
/* unless we have a malloc(0) requests */ /* unless we have a malloc(0) requests */
if (size != 0 && size < MALLOC_MINSIZE) if (size != 0 && size < MALLOC_MINSIZE)
@ -955,7 +960,7 @@ malloc_bytes(struct dir_info *d, size_t size, void *f)
} }
if (bp->canary != d->canary1) if (bp->canary != d->canary1)
wrterror("chunk info corrupted", NULL);
wrterror(d, "chunk info corrupted", NULL);
i = d->chunk_start; i = d->chunk_start;
if (bp->free > 1) if (bp->free > 1)
@ -1018,25 +1023,25 @@ find_chunknum(struct dir_info *d, struct region_info *r, void *ptr)
info = (struct chunk_info *)r->size; info = (struct chunk_info *)r->size;
if (info->canary != d->canary1) if (info->canary != d->canary1)
wrterror("chunk info corrupted", NULL);
wrterror(d, "chunk info corrupted", NULL);
if (mopts.malloc_canaries && info->size > 0) { if (mopts.malloc_canaries && info->size > 0) {
char *end = (char *)ptr + info->size; char *end = (char *)ptr + info->size;
uintptr_t *canary = (uintptr_t *)(end - mopts.malloc_canaries); uintptr_t *canary = (uintptr_t *)(end - mopts.malloc_canaries);
if (*canary != (mopts.malloc_chunk_canary ^ hash(canary))) if (*canary != (mopts.malloc_chunk_canary ^ hash(canary)))
wrterror("chunk canary corrupted", ptr);
wrterror(d, "chunk canary corrupted", ptr);
} }
/* Find the chunk number on the page */ /* Find the chunk number on the page */
chunknum = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift; chunknum = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift;
if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) { if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) {
wrterror("modified chunk-pointer", ptr);
wrterror(d, "modified chunk-pointer", ptr);
return -1; return -1;
} }
if (info->bits[chunknum / MALLOC_BITS] & if (info->bits[chunknum / MALLOC_BITS] &
(1U << (chunknum % MALLOC_BITS))) { (1U << (chunknum % MALLOC_BITS))) {
wrterror("chunk is already free", ptr);
wrterror(d, "chunk is already free", ptr);
return -1; return -1;
} }
return chunknum; return chunknum;
@ -1092,9 +1097,8 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
static void * static void *
omalloc(size_t sz, int zero_fill, void *f)
omalloc(struct dir_info *pool, size_t sz, int zero_fill, void *f)
{ {
struct dir_info *pool = getpool();
void *p; void *p;
size_t psz; size_t psz;
@ -1118,7 +1122,7 @@ omalloc(size_t sz, int zero_fill, void *f)
if (mopts.malloc_guard) { if (mopts.malloc_guard) {
if (mprotect((char *)p + psz - mopts.malloc_guard, if (mprotect((char *)p + psz - mopts.malloc_guard,
mopts.malloc_guard, PROT_NONE)) mopts.malloc_guard, PROT_NONE))
wrterror("mprotect", NULL);
wrterror(pool, "mprotect", NULL);
STATS_ADD(pool->malloc_guarded, mopts.malloc_guard); STATS_ADD(pool->malloc_guarded, mopts.malloc_guard);
} }
@ -1161,15 +1165,15 @@ omalloc(size_t sz, int zero_fill, void *f)
* potentially worse. * potentially worse.
*/ */
static void static void
malloc_recurse(void)
malloc_recurse(struct dir_info *d)
{ {
static int noprint; static int noprint;
if (noprint == 0) { if (noprint == 0) {
noprint = 1; noprint = 1;
wrterror("recursive call", NULL);
wrterror(d, "recursive call", NULL);
} }
malloc_active--;
d->active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
errno = EDEADLK; errno = EDEADLK;
} }
@ -1180,7 +1184,7 @@ malloc_init(void)
if (omalloc_init(&mopts.malloc_pool)) { if (omalloc_init(&mopts.malloc_pool)) {
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (mopts.malloc_xmalloc) if (mopts.malloc_xmalloc)
wrterror("out of memory", NULL);
wrterror(NULL, "out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
@ -1191,26 +1195,29 @@ void *
malloc(size_t size) malloc(size_t size)
{ {
void *r; void *r;
struct dir_info *d;
int saved_errno = errno; int saved_errno = errno;
_MALLOC_LOCK(); _MALLOC_LOCK();
malloc_func = "malloc():";
if (getpool() == NULL) {
d = getpool();
if (d == NULL) {
if (malloc_init() != 0) if (malloc_init() != 0)
return NULL; return NULL;
d = getpool();
} }
d->func = "malloc():";
if (malloc_active++) {
malloc_recurse();
if (d->active++) {
malloc_recurse(d);
return NULL; return NULL;
} }
if (size > 0 && size <= MALLOC_MAXCHUNK) if (size > 0 && size <= MALLOC_MAXCHUNK)
size += mopts.malloc_canaries; size += mopts.malloc_canaries;
r = omalloc(size, 0, CALLER);
malloc_active--;
r = omalloc(d, size, 0, CALLER);
d->active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (r == NULL && mopts.malloc_xmalloc) { if (r == NULL && mopts.malloc_xmalloc) {
wrterror("out of memory", NULL);
wrterror(d, "out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
} }
if (r != NULL) if (r != NULL)
@ -1220,16 +1227,15 @@ malloc(size_t size)
/*DEF_STRONG(malloc);*/ /*DEF_STRONG(malloc);*/
static void static void
validate_junk(void *p) {
validate_junk(struct dir_info *pool, void *p) {
struct region_info *r; struct region_info *r;
struct dir_info *pool = getpool();
size_t byte, sz; size_t byte, sz;
if (p == NULL) if (p == NULL)
return; return;
r = find(pool, p); r = find(pool, p);
if (r == NULL) { if (r == NULL) {
wrterror("bogus pointer in validate_junk", p);
wrterror(pool, "bogus pointer in validate_junk", p);
return; return;
} }
REALSIZE(sz, r); REALSIZE(sz, r);
@ -1239,22 +1245,21 @@ validate_junk(void *p) {
sz = 32; sz = 32;
for (byte = 0; byte < sz; byte++) { for (byte = 0; byte < sz; byte++) {
if (((unsigned char *)p)[byte] != SOME_FREEJUNK) { if (((unsigned char *)p)[byte] != SOME_FREEJUNK) {
wrterror("use after free", p);
wrterror(pool, "use after free", p);
return; return;
} }
} }
} }
static void static void
ofree(void *p)
ofree(struct dir_info *pool, void *p)
{ {
struct dir_info *pool = getpool();
struct region_info *r; struct region_info *r;
size_t sz; size_t sz;
r = find(pool, p); r = find(pool, p);
if (r == NULL) { if (r == NULL) {
wrterror("bogus pointer (double free?)", p);
wrterror(pool, "bogus pointer (double free?)", p);
return; return;
} }
REALSIZE(sz, r); REALSIZE(sz, r);
@ -1262,7 +1267,7 @@ ofree(void *p)
if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE - if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE -
MALLOC_LEEWAY) { MALLOC_LEEWAY) {
if (r->p != p) { if (r->p != p) {
wrterror("bogus pointer", p);
wrterror(pool, "bogus pointer", p);
return; return;
} }
} else { } else {
@ -1277,12 +1282,12 @@ ofree(void *p)
} }
if (mopts.malloc_guard) { if (mopts.malloc_guard) {
if (sz < mopts.malloc_guard) if (sz < mopts.malloc_guard)
wrterror("guard size", NULL);
wrterror(pool, "guard size", NULL);
if (!mopts.malloc_freeunmap) { if (!mopts.malloc_freeunmap) {
if (mprotect((char *)p + PAGEROUND(sz) - if (mprotect((char *)p + PAGEROUND(sz) -
mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard,
PROT_READ | PROT_WRITE)) PROT_READ | PROT_WRITE))
wrterror("mprotect", NULL);
wrterror(pool, "mprotect", NULL);
} }
STATS_SUB(pool->malloc_guarded, mopts.malloc_guard); STATS_SUB(pool->malloc_guarded, mopts.malloc_guard);
} }
@ -1306,17 +1311,17 @@ ofree(void *p)
tmp = p; tmp = p;
p = pool->delayed_chunks[i]; p = pool->delayed_chunks[i];
if (tmp == p) { if (tmp == p) {
wrterror("double free", p);
wrterror(pool, "double free", p);
return; return;
} }
if (mopts.malloc_junk) if (mopts.malloc_junk)
validate_junk(p);
validate_junk(pool, p);
pool->delayed_chunks[i] = tmp; pool->delayed_chunks[i] = tmp;
} }
if (p != NULL) { if (p != NULL) {
r = find(pool, p); r = find(pool, p);
if (r == NULL) { if (r == NULL) {
wrterror("bogus pointer (double free?)", p);
wrterror(pool, "bogus pointer (double free?)", p);
return; return;
} }
free_bytes(pool, r, p); free_bytes(pool, r, p);
@ -1327,6 +1332,7 @@ ofree(void *p)
void void
free(void *ptr) free(void *ptr)
{ {
struct dir_info *d;
int saved_errno = errno; int saved_errno = errno;
/* This is legal. */ /* This is legal. */
@ -1334,18 +1340,19 @@ free(void *ptr)
return; return;
_MALLOC_LOCK(); _MALLOC_LOCK();
malloc_func = "free():";
if (getpool() == NULL) {
d = getpool();
if (d == NULL) {
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
wrterror("free() called before allocation", NULL);
wrterror(d, "free() called before allocation", NULL);
return; return;
} }
if (malloc_active++) {
malloc_recurse();
d->func = "free():";
if (d->active++) {
malloc_recurse(d);
return; return;
} }
ofree(ptr);
malloc_active--;
ofree(d, ptr);
d->active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
errno = saved_errno; errno = saved_errno;
} }
@ -1353,19 +1360,18 @@ free(void *ptr)
static void * static void *
orealloc(void *p, size_t newsz, void *f)
orealloc(struct dir_info *pool, void *p, size_t newsz, void *f)
{ {
struct dir_info *pool = getpool();
struct region_info *r; struct region_info *r;
size_t oldsz, goldsz, gnewsz; size_t oldsz, goldsz, gnewsz;
void *q; void *q;
if (p == NULL) if (p == NULL)
return omalloc(newsz, 0, f);
return omalloc(pool, newsz, 0, f);
r = find(pool, p); r = find(pool, p);
if (r == NULL) { if (r == NULL) {
wrterror("bogus pointer (double free?)", p);
wrterror(pool, "bogus pointer (double free?)", p);
return NULL; return NULL;
} }
if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
@ -1377,7 +1383,7 @@ orealloc(void *p, size_t newsz, void *f)
goldsz = oldsz; goldsz = oldsz;
if (oldsz > MALLOC_MAXCHUNK) { if (oldsz > MALLOC_MAXCHUNK) {
if (oldsz < mopts.malloc_guard) if (oldsz < mopts.malloc_guard)
wrterror("guard size", NULL);
wrterror(pool, "guard size", NULL);
oldsz -= mopts.malloc_guard; oldsz -= mopts.malloc_guard;
} }
@ -1416,7 +1422,7 @@ gotit:
return p; return p;
} else if (q != MAP_FAILED) { } else if (q != MAP_FAILED) {
if (munmap(q, needed)) if (munmap(q, needed))
wrterror("munmap", q);
wrterror(pool, "munmap", q);
} }
} }
} else if (rnewsz < roldsz) { } else if (rnewsz < roldsz) {
@ -1424,11 +1430,11 @@ gotit:
if (mprotect((char *)p + roldsz - if (mprotect((char *)p + roldsz -
mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard,
PROT_READ | PROT_WRITE)) PROT_READ | PROT_WRITE))
wrterror("mprotect", NULL);
wrterror(pool, "mprotect", NULL);
if (mprotect((char *)p + rnewsz - if (mprotect((char *)p + rnewsz -
mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard,
PROT_NONE)) PROT_NONE))
wrterror("mprotect", NULL);
wrterror(pool, "mprotect", NULL);
} }
unmap(pool, (char *)p + rnewsz, roldsz - rnewsz); unmap(pool, (char *)p + rnewsz, roldsz - rnewsz);
r->size = gnewsz; r->size = gnewsz;
@ -1454,7 +1460,7 @@ gotit:
STATS_SETF(r, f); STATS_SETF(r, f);
return p; return p;
} else if (newsz != oldsz || mopts.malloc_realloc) { } else if (newsz != oldsz || mopts.malloc_realloc) {
q = omalloc(newsz, 0, f);
q = omalloc(pool, newsz, 0, f);
if (q == NULL) if (q == NULL)
return NULL; return NULL;
if (newsz != 0 && oldsz != 0) { if (newsz != 0 && oldsz != 0) {
@ -1463,7 +1469,7 @@ gotit:
copysz -= mopts.malloc_canaries; copysz -= mopts.malloc_canaries;
memcpy(q, p, copysz); memcpy(q, p, copysz);
} }
ofree(p);
ofree(pool, p);
return q; return q;
} else { } else {
STATS_SETF(r, f); STATS_SETF(r, f);
@ -1474,27 +1480,30 @@ gotit:
void * void *
realloc(void *ptr, size_t size) realloc(void *ptr, size_t size)
{ {
struct dir_info *d;
void *r; void *r;
int saved_errno = errno; int saved_errno = errno;
_MALLOC_LOCK(); _MALLOC_LOCK();
malloc_func = "realloc():";
if (getpool() == NULL) {
d = getpool();
if (d == NULL) {
if (malloc_init() != 0) if (malloc_init() != 0)
return NULL; return NULL;
d = getpool();
} }
if (malloc_active++) {
malloc_recurse();
d->func = "realloc():";
if (d->active++) {
malloc_recurse(d);
return NULL; return NULL;
} }
if (size > 0 && size <= MALLOC_MAXCHUNK) if (size > 0 && size <= MALLOC_MAXCHUNK)
size += mopts.malloc_canaries; size += mopts.malloc_canaries;
r = orealloc(ptr, size, CALLER);
r = orealloc(d, ptr, size, CALLER);
malloc_active--;
d->active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (r == NULL && mopts.malloc_xmalloc) { if (r == NULL && mopts.malloc_xmalloc) {
wrterror("out of memory", NULL);
wrterror(d, "out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
} }
if (r != NULL) if (r != NULL)
@ -1513,38 +1522,41 @@ realloc(void *ptr, size_t size)
void * void *
calloc(size_t nmemb, size_t size) calloc(size_t nmemb, size_t size)
{ {
struct dir_info *d;
void *r; void *r;
int saved_errno = errno; int saved_errno = errno;
_MALLOC_LOCK(); _MALLOC_LOCK();
malloc_func = "calloc():";
if (getpool() == NULL) {
d = getpool();
if (d == NULL) {
if (malloc_init() != 0) if (malloc_init() != 0)
return NULL; return NULL;
d = getpool();
} }
d->func = "calloc():";
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) { nmemb > 0 && SIZE_MAX / nmemb < size) {
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (mopts.malloc_xmalloc) if (mopts.malloc_xmalloc)
wrterror("out of memory", NULL);
wrterror(d, "out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }
if (malloc_active++) {
malloc_recurse();
if (d->active++) {
malloc_recurse(d);
return NULL; return NULL;
} }
size *= nmemb; size *= nmemb;
if (size > 0 && size <= MALLOC_MAXCHUNK) if (size > 0 && size <= MALLOC_MAXCHUNK)
size += mopts.malloc_canaries; size += mopts.malloc_canaries;
r = omalloc(size, 1, CALLER);
r = omalloc(d, size, 1, CALLER);
malloc_active--;
d->active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (r == NULL && mopts.malloc_xmalloc) { if (r == NULL && mopts.malloc_xmalloc) {
wrterror("out of memory", NULL);
wrterror(d, "out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
} }
if (r != NULL) if (r != NULL)
@ -1559,11 +1571,11 @@ mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill)
char *p, *q; char *p, *q;
if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0) { if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0) {
wrterror("mapalign bad alignment", NULL);
wrterror(d, "mapalign bad alignment", NULL);
return MAP_FAILED; return MAP_FAILED;
} }
if (sz != PAGEROUND(sz)) { if (sz != PAGEROUND(sz)) {
wrterror("mapalign round", NULL);
wrterror(d, "mapalign round", NULL);
return MAP_FAILED; return MAP_FAILED;
} }
@ -1582,19 +1594,18 @@ mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill)
q = (char *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1)); q = (char *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1));
if (q != p) { if (q != p) {
if (munmap(p, q - p)) if (munmap(p, q - p))
wrterror("munmap", p);
wrterror(d, "munmap", p);
} }
if (munmap(q + sz, alignment - (q - p))) if (munmap(q + sz, alignment - (q - p)))
wrterror("munmap", q + sz);
wrterror(d, "munmap", q + sz);
STATS_SUB(d->malloc_used, alignment); STATS_SUB(d->malloc_used, alignment);
return q; return q;
} }
static void * static void *
omemalign(size_t alignment, size_t sz, int zero_fill, void *f)
omemalign(struct dir_info *pool, size_t alignment, size_t sz, int zero_fill, void *f)
{ {
struct dir_info *pool = getpool();
size_t psz; size_t psz;
void *p; void *p;
@ -1605,7 +1616,7 @@ omemalign(size_t alignment, size_t sz, int zero_fill, void *f)
*/ */
if (sz < alignment) if (sz < alignment)
sz = alignment; sz = alignment;
return omalloc(sz, zero_fill, f);
return omalloc(pool, sz, zero_fill, f);
} }
if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
@ -1631,7 +1642,7 @@ omemalign(size_t alignment, size_t sz, int zero_fill, void *f)
if (mopts.malloc_guard) { if (mopts.malloc_guard) {
if (mprotect((char *)p + psz - mopts.malloc_guard, if (mprotect((char *)p + psz - mopts.malloc_guard,
mopts.malloc_guard, PROT_NONE)) mopts.malloc_guard, PROT_NONE))
wrterror("mprotect", NULL);
wrterror(pool, "mprotect", NULL);
STATS_ADD(pool->malloc_guarded, mopts.malloc_guard); STATS_ADD(pool->malloc_guarded, mopts.malloc_guard);
} }
@ -1649,6 +1660,7 @@ omemalign(size_t alignment, size_t sz, int zero_fill, void *f)
int int
posix_memalign(void **memptr, size_t alignment, size_t size) posix_memalign(void **memptr, size_t alignment, size_t size)
{ {
struct dir_info *d;
int res, saved_errno = errno; int res, saved_errno = errno;
void *r; void *r;
@ -1657,23 +1669,25 @@ posix_memalign(void **memptr, size_t alignment, size_t size)
return EINVAL; return EINVAL;
_MALLOC_LOCK(); _MALLOC_LOCK();
malloc_func = "posix_memalign():";
if (getpool() == NULL) {
d = getpool();
if (d == NULL) {
if (malloc_init() != 0) if (malloc_init() != 0)
goto err; goto err;
d = getpool();
} }
if (malloc_active++) {
malloc_recurse();
d->func = "posix_memalign():";
if (d->active++) {
malloc_recurse(d);
goto err; goto err;
} }
if (size > 0 && size <= MALLOC_MAXCHUNK) if (size > 0 && size <= MALLOC_MAXCHUNK)
size += mopts.malloc_canaries; size += mopts.malloc_canaries;
r = omemalign(alignment, size, 0, CALLER);
malloc_active--;
r = omemalign(d, alignment, size, 0, CALLER);
d->active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (r == NULL) { if (r == NULL) {
if (mopts.malloc_xmalloc) { if (mopts.malloc_xmalloc) {
wrterror("out of memory", NULL);
wrterror(d, "out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
} }
goto err; goto err;
@ -1925,7 +1939,7 @@ malloc_dump(int fd)
continue; continue;
r = find(pool, p); r = find(pool, p);
if (r == NULL) { if (r == NULL) {
wrterror("bogus pointer in malloc_dump", p);
wrterror(pool, "bogus pointer in malloc_dump", p);
continue; continue;
} }
free_bytes(pool, r, p); free_bytes(pool, r, p);


Loading…
Cancel
Save