Skip to content

Commit 2c01641

Browse files
author
Jyri Sarha
committed
lib: vregion: lazy interim heap creation from remaining lifetime space
Refactor the vregion memory layout to use a single contiguous buffer instead of two separately page-aligned partitions. The vregion lifetime allocations start at the base and growing upward. The interim k_heap is created lazily when vregion_set_interim() is called for whatever space remains after lifetime allocations. This eliminates the rigid partition boundary that previously wasted memory when lifetime usage was smaller or larger than pre-configured. The interim heap creation is deferred until actually needed, at which point the lifetime region is sealed and any further allocation requests are redirected to the interim. The vregion tracks internal allocation mode (lifetime or interim). All allocations start in lifetime mode. The vregion_set_interim() function switches to interim mode. The enum vregion_mem_type parameter has been removed from the vregion_alloc*() API since the mode is now internal state. vregion_set_interim() is called in pipeline_comp_complete() in case the component's processing domain is Data Processing. The DP components are so far the only place where vregions are used at the moment. Add a guard to skip k_heap_init() in interim_heap_init() if the remaining interim size is too small (< 1024 bytes), which would otherwise trigger an assert failure in sys_heap_init(). Mark the vregion type to VREGION_MEM_TYPE_INVALID if that happens. Key changes: - vregion_create(): Takes single memsize argument instead of separate lifetime_size and interim_size - New vregion_set_interim(): Switches allocation mode from lifetime to interim, warns on repeated calls - vregion_alloc*(): No longer take enum vregion_mem_type parameter, use internal state instead - New interim_heap_init(): Called lazily, page-aligns interim start, logs lifetime used and interim available at INFO level - vregion_free(): Guards interim pointer range - pipeline_comp_completee(): Calls vregion_set_interim() to switch mode Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
1 parent 60283dc commit 2c01641

8 files changed

Lines changed: 176 additions & 102 deletions

File tree

src/audio/module_adapter/module_adapter.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,7 @@ static struct vregion *module_adapter_dp_heap_new(const struct comp_ipc_config *
6565
/* FIXME: the size will be derived from configuration */
6666
const size_t buf_size = 28 * 1024;
6767

68-
/*
69-
* A 1-to-1 replacement of the original heap implementation would be to
70-
* have "lifetime size" equal to 0. But (1) this is invalid for
71-
* vregion_create() and (2) we gradually move objects, that are simple
72-
* to move to the lifetime buffer. Make it 4k for the beginning.
73-
*/
74-
return vregion_create(4096, buf_size - 4096);
68+
return vregion_create(buf_size);
7569
}
7670

7771
static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv,
@@ -109,9 +103,9 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
109103
if (!mod_vreg)
110104
mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0);
111105
else if (flags & SOF_MEM_FLAG_COHERENT)
112-
mod = vregion_alloc_coherent(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*mod));
106+
mod = vregion_alloc_coherent(mod_vreg, sizeof(*mod));
113107
else
114-
mod = vregion_alloc(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*mod));
108+
mod = vregion_alloc(mod_vreg, sizeof(*mod));
115109

116110
if (!mod) {
117111
comp_cl_err(drv, "failed to allocate memory for module");
@@ -136,7 +130,7 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
136130
* single-core configurations.
137131
*/
138132
if (mod_vreg)
139-
dev = vregion_alloc_coherent(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*dev));
133+
dev = vregion_alloc_coherent(mod_vreg, sizeof(*dev));
140134
else
141135
dev = sof_heap_alloc(mod_heap, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0);
142136

src/audio/pipeline/pipeline-graph.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77

88
#include <sof/audio/buffer.h>
99
#include <sof/audio/component_ext.h>
10+
#include <sof/audio/module_adapter/module/generic.h>
1011
#include <sof/audio/pipeline.h>
1112
#include <sof/ipc/msg.h>
13+
#include <sof/lib/vregion.h>
1214
#include <rtos/interrupt.h>
1315
#include <rtos/symbol.h>
1416
#include <rtos/alloc.h>
@@ -294,8 +296,14 @@ static int pipeline_comp_complete(struct comp_dev *current,
294296
* It will be calculated during module prepare operation
295297
* either by the module or to default value based on module's OBS
296298
*/
297-
if (current->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL)
299+
if (current->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) {
298300
current->period = ppl_data->p->period;
301+
} else {
302+
struct processing_module *mod = comp_mod(current);
303+
304+
if (mod && mod->priv.resources.alloc)
305+
vregion_set_interim(mod->priv.resources.alloc->vreg);
306+
}
299307

300308
current->priority = ppl_data->p->priority;
301309

src/include/sof/lib/vregion.h

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,32 @@ struct vregion;
2424
enum vregion_mem_type {
2525
VREGION_MEM_TYPE_INTERIM, /* interim allocation that can be freed */
2626
VREGION_MEM_TYPE_LIFETIME, /* lifetime allocation */
27+
VREGION_MEM_TYPE_INVALID, /* Interim heap initialization failed */
2728
};
2829

2930
#if CONFIG_SOF_VREGIONS
3031

3132
/**
3233
* @brief Create a new virtual region instance.
3334
*
34-
* Create a new virtual region instance with specified static and dynamic partitions.
35-
* Total size is the sum of static and dynamic sizes.
35+
* Create a new virtual region instance with specified memory size.
36+
* Allocations start in LIFETIME mode.
3637
*
37-
* @param[in] lifetime_size Size of the virtual region lifetime partition.
38-
* @param[in] interim_size Size of the virtual region interim partition.
38+
* @param[in] memsize Total size of the virtual region memory.
3939
* @return struct vregion* Pointer to the new virtual region instance, or NULL on failure.
4040
*/
41-
struct vregion *vregion_create(size_t lifetime_size, size_t interim_size);
41+
struct vregion *vregion_create(size_t memsize);
42+
43+
/**
44+
* @brief Switch virtual region allocations to interim mode.
45+
*
46+
* After this call, all allocations from this vregion will use the interim
47+
* heap. The interim heap is created lazily from remaining lifetime space.
48+
* Multiple calls are allowed but log a warning.
49+
*
50+
* @param[in] vr Pointer to the virtual region instance.
51+
*/
52+
void vregion_set_interim(struct vregion *vr);
4253

4354
/**
4455
* @brief Increment virtual region's user count.
@@ -66,36 +77,33 @@ struct vregion *vregion_put(struct vregion *vr);
6677
* @brief Allocate memory from the specified virtual region.
6778
*
6879
* @param[in] vr Pointer to the virtual region instance.
69-
* @param[in] type Type of memory to allocate (lifetime or interim).
7080
* @param[in] size Size of memory to allocate in bytes.
7181
* @return void* Pointer to the allocated memory, or NULL on failure.
7282
*/
73-
void *vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size);
83+
void *vregion_alloc(struct vregion *vr, size_t size);
7484

7585
/**
7686
* @brief like vregion_alloc() but allocates coherent memory
7787
*/
78-
void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, size_t size);
88+
void *vregion_alloc_coherent(struct vregion *vr, size_t size);
7989

8090
/**
8191
* @brief Allocate aligned memory from the specified virtual region.
8292
*
83-
* Allocate aligned memory from the specified virtual region based on the memory type.
93+
* Allocate aligned memory from the specified virtual region using the
94+
* current allocation mode (lifetime or interim).
8495
*
8596
* @param[in] vr Pointer to the virtual region instance.
86-
* @param[in] type Type of memory to allocate (lifetime or interim).
8797
* @param[in] size Size of memory to allocate in bytes.
8898
* @param[in] alignment Alignment of memory to allocate in bytes.
8999
* @return void* Pointer to the allocated memory, or NULL on failure.
90100
*/
91-
void *vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type,
92-
size_t size, size_t alignment);
101+
void *vregion_alloc_align(struct vregion *vr, size_t size, size_t alignment);
93102

94103
/**
95104
* @brief like vregion_alloc_align() but allocates coherent memory
96105
*/
97-
void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type,
98-
size_t size, size_t alignment);
106+
void *vregion_alloc_coherent_align(struct vregion *vr, size_t size, size_t alignment);
99107

100108
/**
101109
* @brief Free memory allocated from the specified virtual region.
@@ -129,10 +137,11 @@ struct vregion {
129137
unsigned int use_count;
130138
};
131139

132-
static inline struct vregion *vregion_create(size_t lifetime_size, size_t interim_size)
140+
static inline struct vregion *vregion_create(size_t memsize)
133141
{
134142
return NULL;
135143
}
144+
static inline void vregion_set_interim(struct vregion *vr) {}
136145
static inline struct vregion *vregion_get(struct vregion *vr)
137146
{
138147
return vr;
@@ -141,22 +150,20 @@ static inline struct vregion *vregion_put(struct vregion *vr)
141150
{
142151
return vr;
143152
}
144-
static inline void *vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size)
153+
static inline void *vregion_alloc(struct vregion *vr, size_t size)
145154
{
146155
return NULL;
147156
}
148-
static inline void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type,
149-
size_t size)
157+
static inline void *vregion_alloc_coherent(struct vregion *vr, size_t size)
150158
{
151159
return NULL;
152160
}
153-
static inline void *vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type,
154-
size_t size, size_t alignment)
161+
static inline void *vregion_alloc_align(struct vregion *vr, size_t size, size_t alignment)
155162
{
156163
return NULL;
157164
}
158-
static inline void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type,
159-
size_t size, size_t alignment)
165+
static inline void *vregion_alloc_coherent_align(struct vregion *vr, size_t size,
166+
size_t alignment)
160167
{
161168
return NULL;
162169
}

src/lib/objpool.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ static int objpool_add(struct objpool_head *head, unsigned int n, size_t size, u
4444
pobjpool = sof_heap_alloc(head->heap, flags,
4545
aligned_size + sizeof(*pobjpool), 0);
4646
else if (flags & SOF_MEM_FLAG_COHERENT)
47-
pobjpool = vregion_alloc_coherent(head->vreg, VREGION_MEM_TYPE_INTERIM,
47+
pobjpool = vregion_alloc_coherent(head->vreg,
4848
aligned_size + sizeof(*pobjpool));
4949
else
50-
pobjpool = vregion_alloc(head->vreg, VREGION_MEM_TYPE_INTERIM,
50+
pobjpool = vregion_alloc(head->vreg,
5151
aligned_size + sizeof(*pobjpool));
5252

5353
if (!pobjpool)

zephyr/include/rtos/alloc.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,9 @@ static inline void *sof_ctx_alloc(struct mod_alloc_ctx *ctx, uint32_t flags,
189189
return sof_heap_alloc(ctx ? ctx->heap : NULL, flags, size, alignment);
190190

191191
if (flags & SOF_MEM_FLAG_COHERENT)
192-
return vregion_alloc_coherent_align(ctx->vreg, VREGION_MEM_TYPE_INTERIM,
193-
size, alignment);
192+
return vregion_alloc_coherent_align(ctx->vreg, size, alignment);
194193

195-
return vregion_alloc_align(ctx->vreg, VREGION_MEM_TYPE_INTERIM, size, alignment);
194+
return vregion_alloc_align(ctx->vreg, size, alignment);
196195
}
197196

198197
/**

zephyr/lib/fast-get.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ const void *fast_get(struct mod_alloc_ctx *alloc, const void *dram_ptr, size_t s
203203

204204
if (alloc && alloc->vreg && size <= FAST_GET_MAX_COPY_SIZE)
205205
/* A userspace allocation, that won't be shared */
206-
ret = vregion_alloc_align(alloc->vreg, VREGION_MEM_TYPE_INTERIM, alloc_size,
206+
ret = vregion_alloc_align(alloc->vreg, alloc_size,
207207
alloc_align);
208208
else
209209
ret = sof_heap_alloc(heap, alloc_flags, alloc_size, alloc_align);

0 commit comments

Comments
 (0)