Skip to content

Conversation

@lyakh
Copy link
Collaborator

@lyakh lyakh commented Dec 23, 2025

add an allocator for equal size pool management where allocated elements are never freed but only added to a free pool

Copilot AI review requested due to automatic review settings December 23, 2025 11:18
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a simple batch allocator for managing equal-size memory pools where allocated elements are returned to a free pool rather than being deallocated. The allocator dynamically grows the pool using power-of-2 sized batches (starting with 2 elements, up to a maximum of 32 per batch) and uses bitmasks to track allocation state.

Key Changes

  • New batch allocator API with batch_alloc() and batch_free() functions
  • Dynamic pool growth strategy using power-of-2 batch sizes
  • Comprehensive unit test suite for the batch allocator

Reviewed changes

Copilot reviewed 7 out of 11 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
src/include/sof/batch.h New public API header declaring batch allocator functions
src/lib/batch.c Implementation of batch allocator with dynamic growth and bitmask-based tracking
src/lib/CMakeLists.txt Added batch.c to the common source files list
test/ztest/unit/batch/testcase.yaml Test configuration for batch allocator unit tests
test/ztest/unit/batch/test_batch_ztest.c Unit tests validating allocation/deallocation across multiple batch sizes
test/ztest/unit/batch/prj.conf Ztest project configuration for batch tests
test/ztest/unit/batch/CMakeLists.txt CMake build configuration for batch unit tests
test/ztest/unit/math/basic/trigonometry/prj.conf No functional change (formatting only)
test/ztest/unit/math/basic/arithmetic/prj.conf No functional change (formatting only)
test/ztest/unit/list/prj.conf No functional change (formatting only)
test/ztest/unit/fast-get/prj.conf No functional change (formatting only)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@lyakh lyakh force-pushed the batch branch 2 times, most recently from 46b8123 to 33f9c9e Compare December 23, 2025 12:56
Copy link
Member

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the use case here ?

@lyakh
Copy link
Collaborator Author

lyakh commented Dec 23, 2025

Whats the use case here ?

@lgirdwood memory domains

@lyakh
Copy link
Collaborator Author

lyakh commented Dec 23, 2025

The PTL Jenkins failure https://sof-ci.01.org/sofpr/PR10456/build18317/devicetest/index.html?model=PTLP_RVP_SDW&testcase=check-runtime-pm-status is strange. I cannot find earlier occurrences and it couldn't be caused by this PR, because it isn't changing runtime by itself. The test has been run on top of 70828dd - before #10386 was merged

Copy link
Collaborator

@kv2019i kv2019i left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice to have the testsuite included.

@lgirdwood
Copy link
Member

lgirdwood commented Jan 5, 2026

Whats the use case here ?

@lgirdwood memory domains

ok, memory domain kobjects ? Why does this need to be special for memory domain ? Can you give some more context around usage.

If its for general purpose use within certain domain, then this is what vregion is for.

@lyakh
Copy link
Collaborator Author

lyakh commented Jan 5, 2026

Whats the use case here ?

@lgirdwood memory domains

ok, memory domain kobjects ? Why does this need to be special for memory domain ? Can you give some more context around usage.

If its for general purpose use within certain domain, then this is what vregion is for.

@lgirdwood don't think vregions are related. This is to adapt to the fact, that memory domains cannot be freed, and therefore should be reused. So this allocator just grows the pool of objects as needed. If no free object is available, a new batch is allocated, when objects are released, they're returned to the pool, but never freed back to the heap. Memory domains should be the first user of this allocator, but it's generic. It is somewhat similar to module resource containers, so we can move those to this allocator too if desired.

@lgirdwood
Copy link
Member

Whats the use case here ?

@lgirdwood memory domains

ok, memory domain kobjects ? Why does this need to be special for memory domain ? Can you give some more context around usage.
If its for general purpose use within certain domain, then this is what vregion is for.

@lgirdwood don't think vregions are related. This is to adapt to the fact, that memory domains cannot be freed, and therefore should be reused. So this allocator just grows the pool of objects as needed. If no free object is available, a new batch is allocated, when objects are released, they're returned to the pool, but never freed back to the heap. Memory domains should be the first user of this allocator, but it's generic. It is somewhat similar to module resource containers, so we can move those to this allocator too if desired.

Ok, so is this for memory domain context data or general module data ?

@lyakh
Copy link
Collaborator Author

lyakh commented Jan 6, 2026

Ok, so is this for memory domain context data or general module data ?

@lgirdwood for the context, this isn't for users, this is for actual memory domain objects, used by Zephyr

@lgirdwood
Copy link
Member

Ok, so is this for memory domain context data or general module data ?

@lgirdwood for the context, this isn't for users, this is for actual memory domain objects, used by Zephyr

Got you, can we spell this out in the comments and API naming as this looks like a general purpose API from its description. A usage flow in the comments around domains would be helpful. Thanks !

@lyakh
Copy link
Collaborator Author

lyakh commented Jan 7, 2026

Ok, so is this for memory domain context data or general module data ?

@lgirdwood for the context, this isn't for users, this is for actual memory domain objects, used by Zephyr

Got you, can we spell this out in the comments and API naming as this looks like a general purpose API from its description. A usage flow in the comments around domains would be helpful. Thanks !

@lgirdwood the API IS general purpose. This is just one use case that I've described, for which this API has been developed

@softwarecki softwarecki self-requested a review January 7, 2026 14:43
Copy link
Collaborator

@softwarecki softwarecki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion the file and function naming needs improvement. The batch_ is too generic and does not convey any meaning. When looking only at the function name batch_alloc it is not clear what it actually does. It would be helpful to introduce a structure that represents this allocator so we do not pass a raw list pointer. The PR description does not explain the purpose or the planned usage of this allocator. The discussion in the comments clarified the idea only partially. I agree it could be useful in several parts of the sof. I am not convinced that using it for the memory domain is the right direction. Would it not be better to extend Zephyr so that unnecessary domains can be removed? Below are a few minor comments from me:

src/lib/batch.c Outdated
abatch->n = n;
/* clear bit means free */
abatch->mask = 0;
abatch->size = size;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider storing aligned_size here. It would add size flexibility and may simplify allocation and freeing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that was my initial implementation, but it's needed to check user's size

src/lib/batch.c Outdated

struct batch {
struct list_item list;
unsigned int n;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest avoiding single-character names. Maybe block_count, capacity or something similar?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a structure member, inside a .c file, not visible outside of it

src/lib/batch.c Outdated
struct batch {
struct list_item list;
unsigned int n;
uint32_t mask;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used_mask ?

Storing free_mask here would simplify allocation to a single ffs call.

src/lib/batch.c Outdated
uint8_t data[];
};

static int batch_add(struct list_item *head, unsigned int n, size_t size)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest avoiding single-character names. Maybe instead of n use block_count, count, depth, capacity or something similar?

I know it is a static function, but its name says absolutely nothing. On first read I wasn't able to infer its purpose.

src/lib/batch.c Outdated

static int batch_add(struct list_item *head, unsigned int n, size_t size)
{
if (n > 32)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be more readable and flexible to define it in one place instead of hardcoding the raw value 32 in multiple locations.

@lgirdwood
Copy link
Member

Ok, so is this for memory domain context data or general module data ?

@lgirdwood for the context, this isn't for users, this is for actual memory domain objects, used by Zephyr

Got you, can we spell this out in the comments and API naming as this looks like a general purpose API from its description. A usage flow in the comments around domains would be helpful. Thanks !

@lgirdwood the API IS general purpose. This is just one use case that I've described, for which this API has been developed

I dont see this being used outside of memory domains, everyone else should just use existing APIs.

It actually sounds like it may be far more useful as a Zephyr allocator since its optimized for domains. I would say we merge into SOF and optimize around domains, once mature it would then probably make sense to transfer into Zephyr.

lyakh added 2 commits January 9, 2026 15:03
Add missing "new line" symbols in multiple prj.conf files.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
Add a simple "batch allocator." It allocates memory for equally
sized objects, that never has to be freed, but can be reused instead.
The first call to this allocator allocates two instances of the
object, the next one allocates 4, then 8, 16, and after that every
new allocation request adds 32 instances. When those objects are
freed, they are only marked as free and kept for reuse. Also add a
unit test for it.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
@lyakh lyakh changed the title Add a simple batch allocator Add a simple object pool allocator Jan 9, 2026
@lyakh
Copy link
Collaborator Author

lyakh commented Jan 12, 2026

SOFCI TEST

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants