|
@ -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); |
|
|