summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Wiklander <jens.wiklander@linaro.org>2020-12-28 22:29:50 +0100
committerJérôme Forissier <jerome@forissier.org>2021-01-05 15:21:06 +0100
commit17967299679c805b86fc045a4e0939ad2ad3a797 (patch)
tree02ca3548f3116acbedf0972c50b865d4fb91ba4a
parentcc5981b239d3f1d1ef4cffa3d8cdd407c4c7ef79 (diff)
libutil: add hdr_size parameter to bget
Adds a hdr_size parameter to bget(), bgetz() and bgetr(). hdr_size must be a multiple of BGET_HDR_QUANTUM. If hdr_size is larger than 0 the buffer will be allocated so that the alignment constraints are fulfilled after advancing hdr_size bytes into the returned buffer. Acked-by: Etienne Carriere <etienne.carriere@linaro.org> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
-rw-r--r--lib/libutils/isoc/bget.c59
-rw-r--r--lib/libutils/isoc/bget.h8
-rw-r--r--lib/libutils/isoc/bget_malloc.c24
3 files changed, 52 insertions, 39 deletions
diff --git a/lib/libutils/isoc/bget.c b/lib/libutils/isoc/bget.c
index 00b81993..48ee1100 100644
--- a/lib/libutils/isoc/bget.c
+++ b/lib/libutils/isoc/bget.c
@@ -576,7 +576,8 @@ struct bpoolset {
#define ESent ((bufsize) (-(((1L << (sizeof(bufsize) * 8 - 2)) - 1) * 2) - 2))
-static bufsize buf_get_pos(struct bfhead *bf, bufsize align, bufsize size)
+static bufsize buf_get_pos(struct bfhead *bf, bufsize align, bufsize hdr_size,
+ bufsize size)
{
unsigned long buf = 0;
bufsize pos = 0;
@@ -585,12 +586,13 @@ static bufsize buf_get_pos(struct bfhead *bf, bufsize align, bufsize size)
return -1;
/*
- * plus sizeof(struct bhead) since buf will follow just after a struct
- * bhead.
+ * plus sizeof(struct bhead) and hdr_size since buf will follow just
+ * after a struct bhead and an eventual extra header.
*/
- buf = (unsigned long)bf + bf->bh.bsize - size + sizeof(struct bhead);
+ buf = (unsigned long)bf + bf->bh.bsize - size + sizeof(struct bhead) +
+ hdr_size;
buf &= ~(align - 1);
- pos = buf - (unsigned long)bf - sizeof(struct bhead);
+ pos = buf - (unsigned long)bf - sizeof(struct bhead) - hdr_size;
if (pos == 0) /* exact match */
return pos;
@@ -602,8 +604,9 @@ static bufsize buf_get_pos(struct bfhead *bf, bufsize align, bufsize size)
/* BGET -- Allocate a buffer. */
-void *bget(requested_align, requested_size, poolset)
+void *bget(requested_align, hdr_size, requested_size, poolset)
bufsize requested_align;
+ bufsize hdr_size;
bufsize requested_size;
struct bpoolset *poolset;
{
@@ -620,8 +623,12 @@ void *bget(requested_align, requested_size, poolset)
#endif
assert(size > 0);
+ COMPILE_TIME_ASSERT(BGET_HDR_QUANTUM == SizeQ);
+
if (align < 0 || (align > 0 && !IS_POWER_OF_TWO((unsigned long)align)))
return NULL;
+ if (hdr_size % BGET_HDR_QUANTUM != 0)
+ return NULL;
if (size < SizeQ) { /* Need at least room for the */
size = SizeQ; /* queue links. */
@@ -640,6 +647,8 @@ void *bget(requested_align, requested_size, poolset)
/* Add overhead in allocated buffer to size required. */
if (ADD_OVERFLOW(size, sizeof(struct bhead), &size))
return NULL;
+ if (ADD_OVERFLOW(size, hdr_size, &size))
+ return NULL;
#ifdef BECtl
/* If a compact function was provided in the call to bectl(), wrap
@@ -660,7 +669,7 @@ void *bget(requested_align, requested_size, poolset)
#ifdef BestFit
while (b != &poolset->freelist) {
assert(b->bh.prevfree == 0);
- pos = buf_get_pos(b, align, size);
+ pos = buf_get_pos(b, align, hdr_size, size);
if (pos >= 0) {
if ((best == &poolset->freelist) ||
(b->bh.bsize < best->bh.bsize)) {
@@ -673,7 +682,7 @@ void *bget(requested_align, requested_size, poolset)
#endif /* BestFit */
while (b != &poolset->freelist) {
- pos = buf_get_pos(b, align, size);
+ pos = buf_get_pos(b, align, hdr_size, size);
if (pos >= 0) {
struct bhead *b_alloc = BH((char *)b + pos);
struct bhead *b_next = BH((char *)b + b->bh.bsize);
@@ -783,8 +792,12 @@ void *bget(requested_align, requested_size, poolset)
bdh = BDH(p);
buf = bdh + 1;
} else {
- buf = (void *)(((unsigned long)p + sizeof(*bdh) + align) &
- ~(align - 1));
+ unsigned long tp = (unsigned long)p;
+
+ tp += sizeof(*bdh) + hdr_size + align;
+ tp &= ~(align - 1);
+ tp -= hdr_size;
+ buf = (void *)tp;
bdh = BDH((char *)buf - sizeof(*bdh));
}
@@ -799,7 +812,6 @@ void *bget(requested_align, requested_size, poolset)
poolset->numget++; /* Increment number of bget() calls */
poolset->numdget++; /* Direct bget() call count */
#endif
- buf = (void *) (bdh + 1);
tag_asan_alloced(buf, size);
return buf;
}
@@ -812,7 +824,7 @@ void *bget(requested_align, requested_size, poolset)
if ((newpool = poolset->acqfcn((bufsize) exp_incr)) != NULL) {
bpool(newpool, exp_incr, poolset);
- buf = bget(align, requested_size, pool); /* This can't, I say, can't
+ buf = bget(align, hdr_size, requested_size, pool); /* This can't, I say, can't
get into a loop. */
return buf;
}
@@ -830,12 +842,13 @@ void *bget(requested_align, requested_size, poolset)
the entire contents of the buffer to zero, not just the
region requested by the caller. */
-void *bgetz(align, size, poolset)
+void *bgetz(align, hdr_size, size, poolset)
bufsize align;
+ bufsize hdr_size;
bufsize size;
struct bpoolset *poolset;
{
- char *buf = (char *) bget(align, size, poolset);
+ char *buf = (char *) bget(align, hdr_size, size, poolset);
if (buf != NULL) {
struct bhead *b;
@@ -862,9 +875,10 @@ void *bgetz(align, size, poolset)
enhanced to allow the buffer to grow into adjacent free
blocks and to avoid moving data unnecessarily. */
-void *bgetr(buf, align, size, poolset)
+void *bgetr(buf, align, hdr_size, size, poolset)
void *buf;
bufsize align;
+ bufsize hdr_size;
bufsize size;
struct bpoolset *poolset;
{
@@ -872,7 +886,7 @@ void *bgetr(buf, align, size, poolset)
bufsize osize; /* Old size of buffer */
struct bhead *b;
- if ((nbuf = bget(align, size, poolset)) == NULL) { /* Acquire new buffer */
+ if ((nbuf = bget(align, hdr_size, size, poolset)) == NULL) { /* Acquire new buffer */
return NULL;
}
if (buf == NULL) {
@@ -1605,6 +1619,7 @@ int bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *))
bufsize bs = (myrand() & (ExpIncr * 4 - 1)) / (1 << (myrand() & 0x7));
#endif
bufsize align = 0;
+ bufsize hdr_size = 0;
switch (rand() & 0x3) {
case 1:
@@ -1620,12 +1635,14 @@ int bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *))
break;
}
+ hdr_size = (rand() & 0x3) * BGET_HDR_QUANTUM;
+
assert(bs <= (((bufsize) 4) * ExpIncr));
bs = blimit(bs);
if (myrand() & 0x400) {
- cb = (char *) bgetz(align, bs, &mypoolset);
+ cb = (char *) bgetz(align, hdr_size, bs, &mypoolset);
} else {
- cb = (char *) bget(align, bs, &mypoolset);
+ cb = (char *) bget(align, hdr_size, bs, &mypoolset);
}
if (cb == NULL) {
#ifdef EasyOut
@@ -1645,7 +1662,7 @@ int bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *))
continue;
#endif
}
- assert(!align || !((unsigned long)cb & (align - 1)));
+ assert(!align || !(((unsigned long)cb + hdr_size) & (align - 1)));
*((char **) cb) = (char *) bchain;
bchain = cb;
@@ -1698,11 +1715,13 @@ int bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *))
#ifdef BECtl
protect = 1; /* Protect against compaction */
#endif
- newb = (char *) bgetr((void *) fb, align, bs, &mypoolset);
+ newb = (char *) bgetr((void *) fb, align, hdr_size, bs, &mypoolset);
#ifdef BECtl
protect = 0;
#endif
if (newb != NULL) {
+ assert(!align || !(((unsigned long)newb + hdr_size) &
+ (align - 1)));
*((char **) bc) = newb;
}
}
diff --git a/lib/libutils/isoc/bget.h b/lib/libutils/isoc/bget.h
index b7d5de84..abef8531 100644
--- a/lib/libutils/isoc/bget.h
+++ b/lib/libutils/isoc/bget.h
@@ -26,13 +26,15 @@
#endif /* PROTOTYPES */
#endif
+#define BGET_HDR_QUANTUM (2 * sizeof(long))
+
typedef long bufsize;
struct bpoolset;
void bpool _((void *buffer, bufsize len, struct bpoolset *poolset));
-void *bget _((bufsize align, bufsize size, struct bpoolset *poolset));
-void *bgetz _((bufsize align, bufsize size, struct bpoolset *poolset));
-void *bgetr _((void *buffer, bufsize align, bufsize newsize,
+void *bget _((bufsize align, bufsize hdr_size, bufsize size, struct bpoolset *poolset));
+void *bgetz _((bufsize align, bufsize hdr_size, bufsize size, struct bpoolset *poolset));
+void *bgetr _((void *buffer, bufsize align, bufsize hdr_size, bufsize newsize,
struct bpoolset *poolset));
void brel _((void *buf, struct bpoolset *poolset, int wipe));
void bectl _((int (*compact)(bufsize sizereq, int sequence),
diff --git a/lib/libutils/isoc/bget_malloc.c b/lib/libutils/isoc/bget_malloc.c
index ae804957..ced39ea2 100644
--- a/lib/libutils/isoc/bget_malloc.c
+++ b/lib/libutils/isoc/bget_malloc.c
@@ -361,17 +361,15 @@ static void *raw_malloc(size_t hdr_size, size_t ftr_size, size_t pl_size,
raw_malloc_validate_pools(ctx);
- /* Compute total size */
- if (ADD_OVERFLOW(pl_size, hdr_size, &s))
- goto out;
- if (ADD_OVERFLOW(s, ftr_size, &s))
+ /* Compute total size, excluding the header */
+ if (ADD_OVERFLOW(pl_size, ftr_size, &s))
goto out;
/* BGET doesn't like 0 sized allocations */
if (!s)
s++;
- ptr = bget(0, s, &ctx->poolset);
+ ptr = bget(0, hdr_size, s, &ctx->poolset);
out:
raw_malloc_return_hook(ptr, pl_size, ctx);
@@ -394,11 +392,9 @@ static void *raw_calloc(size_t hdr_size, size_t ftr_size, size_t pl_nmemb,
raw_malloc_validate_pools(ctx);
- /* Compute total size */
+ /* Compute total size, excluding hdr_size */
if (MUL_OVERFLOW(pl_nmemb, pl_size, &s))
goto out;
- if (ADD_OVERFLOW(s, hdr_size, &s))
- goto out;
if (ADD_OVERFLOW(s, ftr_size, &s))
goto out;
@@ -406,7 +402,7 @@ static void *raw_calloc(size_t hdr_size, size_t ftr_size, size_t pl_nmemb,
if (!s)
s++;
- ptr = bgetz(0, s, &ctx->poolset);
+ ptr = bgetz(0, hdr_size, s, &ctx->poolset);
out:
raw_malloc_return_hook(ptr, pl_nmemb * pl_size, ctx);
@@ -431,7 +427,7 @@ static void *raw_realloc(void *ptr, size_t hdr_size, size_t ftr_size,
if (!s)
s++;
- p = bgetr(ptr, 0, s, &ctx->poolset);
+ p = bgetr(ptr, 0, 0, s, &ctx->poolset);
out:
raw_malloc_return_hook(p, pl_size, ctx);
@@ -513,13 +509,9 @@ static void *gen_mdbg_malloc(struct malloc_ctx *ctx, const char *fname,
uint32_t exceptions = malloc_lock(ctx);
/*
- * Check struct mdbg_hdr doesn't get bad alignment.
- * This is required by C standard: the buffer returned from
- * malloc() should be aligned with a fundamental alignment.
- * For ARM32, the required alignment is 8. For ARM64, it is 16.
+ * Check struct mdbg_hdr works with BGET_HDR_QUANTUM.
*/
- COMPILE_TIME_ASSERT(
- (sizeof(struct mdbg_hdr) % (__alignof(uintptr_t) * 2)) == 0);
+ COMPILE_TIME_ASSERT((sizeof(struct mdbg_hdr) % BGET_HDR_QUANTUM) == 0);
hdr = raw_malloc(sizeof(struct mdbg_hdr),
mdbg_get_ftr_size(size), size, ctx);