util: Add a way to set the min_buffer_size in linear_alloc

The default value remains 2048, which is also used for rounding up
any user provided size.

The option is useful in cases where there's a better idea of the
amount of data that's going to be used.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25279>
This commit is contained in:
Caio Oliveira 2023-10-02 22:35:04 -07:00 committed by Marge Bot
parent 39c8cca34f
commit 89afcc94ea
3 changed files with 47 additions and 7 deletions

View file

@ -964,7 +964,6 @@ gc_sweep_end(gc_ctx *ctx)
* other buffers.
*/
#define MIN_LINEAR_BUFSIZE 2048
#define SUBALLOC_ALIGNMENT 8
#define LMAGIC_CONTEXT 0x87b9c7d3
#define LMAGIC_NODE 0x87b910d3
@ -976,6 +975,8 @@ struct linear_ctx {
#ifndef NDEBUG
unsigned magic; /* for debugging */
#endif
unsigned min_buffer_size;
unsigned offset; /* points to the first unused byte in the latest buffer */
unsigned size; /* size of the latest buffer */
void *latest; /* the only buffer that has free space */
@ -1021,9 +1022,9 @@ linear_alloc_child(linear_ctx *ctx, unsigned size)
if (unlikely(ctx->offset + size > ctx->size)) {
/* allocate a new node */
unsigned node_size = size;
if (likely(node_size < MIN_LINEAR_BUFSIZE))
node_size = MIN_LINEAR_BUFSIZE;
if (likely(node_size < ctx->min_buffer_size))
node_size = ctx->min_buffer_size;
const unsigned canary_size = get_node_canary_size();
const unsigned full_size = canary_size + node_size;
@ -1070,21 +1071,35 @@ linear_alloc_child(linear_ctx *ctx, unsigned size)
linear_ctx *
linear_context(void *ralloc_ctx)
{
const linear_opts opts = {0};
return linear_context_with_opts(ralloc_ctx, &opts);
}
linear_ctx *
linear_context_with_opts(void *ralloc_ctx, const linear_opts *opts)
{
linear_ctx *ctx;
if (unlikely(!ralloc_ctx))
return NULL;
const unsigned size = MIN_LINEAR_BUFSIZE;
const unsigned default_min_buffer_size = 2048;
const unsigned min_buffer_size =
MAX2(ALIGN_POT(opts->min_buffer_size, default_min_buffer_size),
default_min_buffer_size);
const unsigned size = min_buffer_size;
const unsigned canary_size = get_node_canary_size();
const unsigned full_size =
sizeof(linear_ctx) + canary_size + size;
sizeof(linear_ctx) + canary_size + size;
ctx = ralloc_size(ralloc_ctx, full_size);
if (unlikely(!ctx))
return NULL;
ctx->min_buffer_size = min_buffer_size;
ctx->offset = 0;
ctx->size = size;
ctx->latest = (char *)&ctx[1] + canary_size;
@ -1125,7 +1140,7 @@ ralloc_steal_linear_context(void *new_ralloc_ctx, linear_ctx *ctx)
{
if (unlikely(!ctx))
return;
assert(ctx->magic == LMAGIC_CONTEXT);
/* Linear context is also the ralloc parent of extra nodes. */

View file

@ -579,6 +579,10 @@ typedef struct linear_ctx linear_ctx;
*/
void *linear_alloc_child(linear_ctx *ctx, unsigned size);
typedef struct {
unsigned min_buffer_size;
} linear_opts;
/**
* Allocate a linear context that will internally hold linear buffers.
* Use it for all child node allocations.
@ -587,6 +591,8 @@ void *linear_alloc_child(linear_ctx *ctx, unsigned size);
*/
linear_ctx *linear_context(void *ralloc_ctx);
linear_ctx *linear_context_with_opts(void *ralloc_ctx, const linear_opts *opts);
/**
* Same as linear_alloc_child, but also clears memory.
*/

View file

@ -70,3 +70,22 @@ TEST(LinearAlloc, AvoidWasteAfterLargeAlloc)
ralloc_free(ctx);
}
TEST(LinearAlloc, Options)
{
void *ctx = ralloc_context(NULL);
linear_opts opts = {};
opts.min_buffer_size = 8192;
linear_ctx *lin_ctx = linear_context_with_opts(ctx, &opts);
/* Assert allocations spanning the first 8192 bytes are contiguous. */
char *first = (char *)linear_alloc_child(lin_ctx, 1024);
for (int i = 1; i < 8; i++) {
char *ptr = (char *)linear_alloc_child(lin_ctx, 1024);
EXPECT_EQ(ptr - first, 1024 * i);
}
ralloc_free(ctx);
}