Skip to content

Commit f429d54

Browse files
lyakhkv2019i
authored andcommitted
objpool: add allocation flags
We need to be able to specify allocation flags for object pools and to verify their consistency. Add a parameter for that. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent 286b3be commit f429d54

3 files changed

Lines changed: 44 additions & 23 deletions

File tree

src/include/sof/objpool.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,21 @@
66
#ifndef __ZEPHYR_OBJPOOL_H__
77
#define __ZEPHYR_OBJPOOL_H__
88

9-
struct list_item;
9+
#include <sof/list.h>
10+
11+
#include <stdint.h>
12+
13+
struct objpool_head {
14+
struct list_item list;
15+
uint32_t flags;
16+
};
17+
1018
/**
1119
* Allocate memory tracked as part of an object pool.
1220
*
13-
* @param head Pointer to the object pool list head.
21+
* @param head Pointer to the object pool head.
1422
* @param size Size in bytes of memory blocks to allocate.
23+
* @param flags Memory allocation flags.
1524
*
1625
* @return a pointer to the allocated memory on success, NULL on failure.
1726
*
@@ -22,20 +31,22 @@ struct list_item;
2231
* is requested, the next call allocates 4 blocks, then 8, 16 and 32. After that
2332
* 32 blocks are allocated every time. Note, that by design allocated blocks are
2433
* never freed. See more below.
34+
* TODO: @a flags are currently only used when allocating new object sets.
35+
* Should add a check that they're consistent with already allocated objects.
2536
*/
26-
void *objpool_alloc(struct list_item *head, size_t size);
37+
void *objpool_alloc(struct objpool_head *head, size_t size, uint32_t flags);
2738

2839
/**
2940
* Return a block to the object pool
3041
*
31-
* @param head Pointer to the object pool list head.
42+
* @param head Pointer to the object pool head.
3243
* @param data Pointer to the object to return (can be NULL)
3344
*
3445
* @return 0 on success or a negative error code.
3546
*
3647
* Return a block to the object pool. Memory is never freed by design, unused
3748
* blocks are kept in the object pool for future re-use.
3849
*/
39-
int objpool_free(struct list_item *head, void *data);
50+
int objpool_free(struct objpool_head *head, void *data);
4051

4152
#endif

src/lib/objpool.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ struct objpool {
2424

2525
#define OBJPOOL_BITS (sizeof(((struct objpool *)0)->mask) * 8)
2626

27-
static int objpool_add(struct list_item *head, unsigned int n, size_t size)
27+
static int objpool_add(struct list_item *head, unsigned int n, size_t size, uint32_t flags)
2828
{
2929
if (n > OBJPOOL_BITS)
3030
return -ENOMEM;
@@ -35,7 +35,7 @@ static int objpool_add(struct list_item *head, unsigned int n, size_t size)
3535
size_t aligned_size = ALIGN_UP(size, sizeof(int));
3636

3737
/* Initialize with 0 to give caller a chance to identify new allocations */
38-
struct objpool *pobjpool = rzalloc(0, n * aligned_size + sizeof(*pobjpool));
38+
struct objpool *pobjpool = rzalloc(flags, n * aligned_size + sizeof(*pobjpool));
3939

4040
if (!pobjpool)
4141
return -ENOMEM;
@@ -50,7 +50,7 @@ static int objpool_add(struct list_item *head, unsigned int n, size_t size)
5050
return 0;
5151
}
5252

53-
void *objpool_alloc(struct list_item *head, size_t size)
53+
void *objpool_alloc(struct objpool_head *head, size_t size, uint32_t flags)
5454
{
5555
size_t aligned_size = ALIGN_UP(size, sizeof(int));
5656
struct list_item *list;
@@ -60,7 +60,11 @@ void *objpool_alloc(struct list_item *head, size_t size)
6060
if (!size || aligned_size > (UINT_MAX >> 5) - sizeof(*pobjpool))
6161
return NULL;
6262

63-
list_for_item(list, head) {
63+
if (!list_is_empty(&head->list) && head->flags != flags)
64+
/* List isn't empty, and flags don't match */
65+
return NULL;
66+
67+
list_for_item(list, &head->list) {
6468
pobjpool = container_of(list, struct objpool, list);
6569

6670
uint32_t free_mask = MASK(pobjpool->n - 1, 0) & ~pobjpool->mask;
@@ -83,37 +87,37 @@ void *objpool_alloc(struct list_item *head, size_t size)
8387
/* no free elements found */
8488
unsigned int new_n;
8589

86-
if (list_is_empty(head)) {
90+
if (list_is_empty(&head->list)) {
8791
new_n = 2;
8892
} else {
8993
/* Check the last one */
90-
pobjpool = container_of(head->prev, struct objpool, list);
94+
pobjpool = container_of(head->list.prev, struct objpool, list);
9195

9296
if (pobjpool->n == OBJPOOL_BITS)
9397
new_n = OBJPOOL_BITS;
9498
else
9599
new_n = pobjpool->n << 1;
96100
}
97101

98-
if (objpool_add(head, new_n, size) < 0)
102+
if (objpool_add(&head->list, new_n, size, flags) < 0)
99103
return NULL;
100104

101105
/* Return the first element of the new objpool, which is now the last one in the list */
102-
pobjpool = container_of(head->prev, struct objpool, list);
106+
pobjpool = container_of(head->list.prev, struct objpool, list);
103107
pobjpool->mask = 1;
104108

105109
return pobjpool->data;
106110
}
107111

108-
int objpool_free(struct list_item *head, void *data)
112+
int objpool_free(struct objpool_head *head, void *data)
109113
{
110114
struct list_item *list;
111115
struct objpool *pobjpool;
112116

113117
if (!data)
114118
return 0;
115119

116-
list_for_item(list, head) {
120+
list_for_item(list, &head->list) {
117121
pobjpool = container_of(list, struct objpool, list);
118122

119123
size_t aligned_size = ALIGN_UP(pobjpool->size, sizeof(int));

test/ztest/unit/objpool/test_objpool_ztest.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#include <sof/objpool.h>
1010
#include <sof/common.h>
1111
#include <sof/list.h>
12+
13+
#include <rtos/alloc.h>
14+
1215
#include <stdlib.h>
1316
#include <string.h>
1417

@@ -26,23 +29,26 @@ void *__wrap_rzalloc(uint32_t flags, size_t bytes)
2629

2730
ZTEST(objpool_suite, test_objpool_wrong_size)
2831
{
29-
struct list_item head = LIST_INIT(head);
32+
struct objpool_head head = {.list = LIST_INIT(head.list)};
3033
/* new object pool of 2 blocks */
31-
uint8_t *block1 = objpool_alloc(&head, DATA_SIZE);
34+
uint8_t *block1 = objpool_alloc(&head, DATA_SIZE, 0);
3235
/* should fail because of a different size */
33-
uint8_t *block2 = objpool_alloc(&head, DATA_SIZE + 1);
36+
uint8_t *block2 = objpool_alloc(&head, DATA_SIZE + 1, 0);
3437
/* second block in the first object pool */
35-
uint8_t *block3 = objpool_alloc(&head, DATA_SIZE);
38+
uint8_t *block3 = objpool_alloc(&head, DATA_SIZE, 0);
3639
/* new object pool of 4 blocks */
37-
uint8_t *block4 = objpool_alloc(&head, DATA_SIZE);
40+
uint8_t *block4 = objpool_alloc(&head, DATA_SIZE, 0);
3841
/* should fail because of a different size */
39-
uint8_t *block5 = objpool_alloc(&head, DATA_SIZE * 2);
42+
uint8_t *block5 = objpool_alloc(&head, DATA_SIZE * 2, 0);
43+
/* should fail because of different flags */
44+
uint8_t *block6 = objpool_alloc(&head, DATA_SIZE * 2, SOF_MEM_FLAG_COHERENT);
4045

4146
zassert_not_null(block1);
4247
zassert_is_null(block2);
4348
zassert_not_null(block3);
4449
zassert_not_null(block4);
4550
zassert_is_null(block5);
51+
zassert_is_null(block6);
4652

4753
zassert_not_ok(objpool_free(&head, block1 + 1));
4854
zassert_ok(objpool_free(&head, block1));
@@ -54,7 +60,7 @@ ZTEST(objpool_suite, test_objpool_wrong_size)
5460

5561
ZTEST(objpool_suite, test_objpool)
5662
{
57-
struct list_item head = LIST_INIT(head);
63+
struct objpool_head head = {.list = LIST_INIT(head.list)};
5864
void *blocks[62]; /* 2 + 4 + 8 + 16 + 32 */
5965
unsigned int k = 0;
6066

@@ -64,7 +70,7 @@ ZTEST(objpool_suite, test_objpool)
6470
uint8_t *start;
6571

6672
for (unsigned int j = 0; j < n; j++) {
67-
uint8_t *block = objpool_alloc(&head, DATA_SIZE);
73+
uint8_t *block = objpool_alloc(&head, DATA_SIZE, 0);
6874

6975
zassert_not_null(block, "allocation failed loop %u iter %u", i, j);
7076

0 commit comments

Comments
 (0)