-
Notifications
You must be signed in to change notification settings - Fork 349
Add a simple object pool allocator #10456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this 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()andbatch_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.
46b8123 to
33f9c9e
Compare
lgirdwood
left a comment
There was a problem hiding this 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 ?
@lgirdwood memory domains |
|
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 |
kv2019i
left a comment
There was a problem hiding this 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.
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 ? |
@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
left a comment
There was a problem hiding this 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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
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. |
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]>
|
SOFCI TEST |
add an allocator for equal size pool management where allocated elements are never freed but only added to a free pool