buffer: Add buffer range allocation functions

Add two new buffer allocation functions buffer_set_size_range and
buffer_alloc_range dedicated to deep buffering. They try to allocate
the largest possible buffer according to the suggested size. If this size
cannot be obtained, it will be reduced step by step until it reaches
the minimum size.

Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
This commit is contained in:
Adrian Warecki 2023-01-24 17:01:10 +01:00 committed by Kai Vehmanen
parent 8032abae17
commit 7d235d23ad
2 changed files with 104 additions and 0 deletions

View File

@ -164,6 +164,49 @@ int buffer_sync_shadow_dp_queue(struct comp_buffer *buffer, size_t limit)
}
#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */
struct comp_buffer *buffer_alloc_range(size_t preferred_size, size_t minimum_size, uint32_t caps,
uint32_t flags, uint32_t align, bool is_shared)
{
struct comp_buffer *buffer;
size_t size;
void *stream_addr = NULL;
tr_dbg(&buffer_tr, "buffer_alloc_range(): %zu -- %zu bytes", minimum_size, preferred_size);
/* validate request */
if (minimum_size == 0 || preferred_size < minimum_size) {
tr_err(&buffer_tr, "buffer_alloc_range(): new size range %zu -- %zu is invalid",
minimum_size, preferred_size);
return NULL;
}
/* Align preferred size to a multiple of the minimum size */
if (preferred_size % minimum_size)
preferred_size += minimum_size - preferred_size % minimum_size;
for (size = preferred_size; size >= minimum_size; size -= minimum_size) {
stream_addr = rballoc_align(0, caps, size, align);
if (stream_addr)
break;
}
tr_dbg(&buffer_tr, "buffer_alloc_range(): allocated %zu bytes", size);
if (!stream_addr) {
tr_err(&buffer_tr, "buffer_alloc_range(): could not alloc size = %zu bytes of type = %u",
minimum_size, caps);
return NULL;
}
buffer = buffer_alloc_struct(stream_addr, size, caps, flags, is_shared);
if (!buffer) {
tr_err(&buffer_tr, "buffer_alloc_range(): could not alloc buffer structure");
rfree(stream_addr);
}
return buffer;
}
void buffer_zero(struct comp_buffer *buffer)
{
buf_dbg(buffer, "stream_zero()");
@ -214,6 +257,63 @@ int buffer_set_size(struct comp_buffer *buffer, uint32_t size, uint32_t alignmen
return 0;
}
int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, size_t minimum_size,
uint32_t alignment)
{
void *ptr = audio_stream_get_addr(&buffer->stream);
const size_t actual_size = audio_stream_get_size(&buffer->stream);
void *new_ptr = NULL;
size_t new_size;
CORE_CHECK_STRUCT(buffer);
/* validate request */
if (minimum_size == 0 || preferred_size < minimum_size) {
buf_err(buffer, "resize size range %zu -- %zu is invalid", minimum_size,
preferred_size);
return -EINVAL;
}
/* Align preferred size to a multiple of the minimum size */
if (preferred_size % minimum_size)
preferred_size += minimum_size - preferred_size % minimum_size;
if (preferred_size == actual_size)
return 0;
if (!alignment) {
for (new_size = preferred_size; new_size >= minimum_size;
new_size -= minimum_size) {
new_ptr = rbrealloc(ptr, SOF_MEM_FLAG_NO_COPY, buffer->caps, new_size,
actual_size);
if (new_ptr)
break;
}
} else {
for (new_size = preferred_size; new_size >= minimum_size;
new_size -= minimum_size) {
new_ptr = rbrealloc_align(ptr, SOF_MEM_FLAG_NO_COPY, buffer->caps, new_size,
actual_size, alignment);
if (new_ptr)
break;
}
}
/* we couldn't allocate bigger chunk */
if (!new_ptr && new_size > actual_size) {
buf_err(buffer, "resize can't alloc %zu bytes type %u", new_size, buffer->caps);
return -ENOMEM;
}
/* use bigger chunk, else just use the old chunk but set smaller */
if (new_ptr)
buffer->stream.addr = new_ptr;
buffer_init_stream(buffer, new_size);
return 0;
}
int buffer_set_params(struct comp_buffer *buffer,
struct sof_ipc_stream_params *params, bool force_update)
{

View File

@ -186,6 +186,8 @@ struct buffer_cb_free {
/* pipeline buffer creation and destruction */
struct comp_buffer *buffer_alloc(size_t size, uint32_t caps, uint32_t flags, uint32_t align,
bool is_shared);
struct comp_buffer *buffer_alloc_range(size_t preferred_size, size_t minimum_size, uint32_t caps,
uint32_t flags, uint32_t align, bool is_shared);
struct comp_buffer *buffer_new(const struct sof_ipc_buffer *desc, bool is_shared);
#if CONFIG_ZEPHYR_DP_SCHEDULER
/*
@ -222,6 +224,8 @@ int buffer_create_shadow_dp_queue(struct comp_buffer *buffer, bool at_input);
int buffer_sync_shadow_dp_queue(struct comp_buffer *buffer, size_t limit);
#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */
int buffer_set_size(struct comp_buffer *buffer, uint32_t size, uint32_t alignment);
int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, size_t minimum_size,
uint32_t alignment);
void buffer_free(struct comp_buffer *buffer);
void buffer_zero(struct comp_buffer *buffer);