diff options
author | Jens Wiklander <jens.wiklander@linaro.org> | 2020-12-28 22:29:50 +0100 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2021-01-05 15:21:06 +0100 |
commit | 17967299679c805b86fc045a4e0939ad2ad3a797 (patch) | |
tree | 02ca3548f3116acbedf0972c50b865d4fb91ba4a | |
parent | cc5981b239d3f1d1ef4cffa3d8cdd407c4c7ef79 (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.c | 59 | ||||
-rw-r--r-- | lib/libutils/isoc/bget.h | 8 | ||||
-rw-r--r-- | lib/libutils/isoc/bget_malloc.c | 24 |
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); |