Skip to content

Commit 44bcba0

Browse files
committed
fast-get: fix a recent regression
Recent commits 7d0621e ("fast-get: fix partition leak for multi-thread usage") and 3c757dd ("fast-get: fix crash by freeing buffer before removing partition") introduced a regression when using SRC in DP mode in userspace on PTL and running two aplay -r 44100 back to back. The reason is that SRC isn't calling mod_fast_put() explicitly and is instead relying on automatic clean up, which then happens in a different thread. In fact those two commits weren't needed AFAICS, since fast_put() shouldn't be called directly from userspace, instead only mod_fast_put() should be called, which is a syscall, and therefore fast_put() then will have access to all the memory. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent 04b2d16 commit 44bcba0

File tree

6 files changed

+39
-32
lines changed

6 files changed

+39
-32
lines changed

src/audio/module_adapter/module/generic.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ EXPORT_SYMBOL(z_impl_mod_fast_get);
341341
static int free_contents(struct processing_module *mod, struct module_resource *container)
342342
{
343343
struct module_resources *res = &mod->priv.resources;
344+
struct k_mem_domain *mdom;
344345

345346
switch (container->type) {
346347
case MOD_RES_HEAP:
@@ -354,7 +355,12 @@ static int free_contents(struct processing_module *mod, struct module_resource *
354355
#endif
355356
#if CONFIG_FAST_GET
356357
case MOD_RES_FAST_GET:
357-
fast_put(res->heap, container->sram_ptr);
358+
#if CONFIG_USERSPACE
359+
mdom = mod->mdom;
360+
#else
361+
mdom = NULL;
362+
#endif
363+
fast_put(res->heap, mdom, container->sram_ptr);
358364
return 0;
359365
#endif
360366
default:

src/include/module/module/base.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,8 @@ struct processing_module {
201201
enum module_processing_type proc_type;
202202
#if CONFIG_USERSPACE
203203
struct userspace_context *user_ctx;
204-
#endif /* CONFIG_USERSPACE */
205-
#if CONFIG_SOF_USERSPACE_APPLICATION
206204
struct k_mem_domain *mdom;
207-
#endif
205+
#endif /* CONFIG_USERSPACE */
208206
#endif /* SOF_MODULE_PRIVATE */
209207
};
210208

src/include/sof/lib/fast-get.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <stddef.h>
1212

1313
struct k_heap;
14+
struct k_mem_domain;
1415

1516
/*
1617
* When built for SOF, fast_get() and fast_put() are only needed when DRAM
@@ -25,13 +26,13 @@ struct k_heap;
2526
(CONFIG_LLEXT_TYPE_ELF_RELOCATABLE || !defined(LL_EXTENSION_BUILD))) || \
2627
!CONFIG_SOF_FULL_ZEPHYR_APPLICATION
2728
const void *fast_get(struct k_heap *heap, const void * const dram_ptr, size_t size);
28-
void fast_put(struct k_heap *heap, const void *sram_ptr);
29+
void fast_put(struct k_heap *heap, struct k_mem_domain *mdom, const void *sram_ptr);
2930
#else
3031
static inline const void *fast_get(struct k_heap *heap, const void * const dram_ptr, size_t size)
3132
{
3233
return dram_ptr;
3334
}
34-
static inline void fast_put(struct k_heap *heap, const void *sram_ptr) {}
35+
static inline void fast_put(struct k_heap *heap, struct k_mem_domain *mdom, const void *sram_ptr) {}
3536
#endif
3637

3738
#endif /* __SOF_LIB_FAST_GET_H__ */

test/cmocka/src/lib/fast-get/fast-get-tests.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ static void test_simple_fast_get_put(void **state)
7777
assert(ret);
7878
assert(!memcmp(ret, testdata[0], sizeof(testdata[0])));
7979

80-
fast_put(NULL, ret);
80+
fast_put(NULL, NULL, ret);
8181
}
8282

8383
static void test_fast_get_size_missmatch_test(void **state)
@@ -94,7 +94,7 @@ static void test_fast_get_size_missmatch_test(void **state)
9494
ret[1] = fast_get(NULL, testdata[0], sizeof(testdata[0]) + 1);
9595
assert(!ret[1]);
9696

97-
fast_put(NULL, ret);
97+
fast_put(NULL, NULL, ret);
9898
}
9999

100100
static void test_over_32_fast_gets_and_puts(void **state)
@@ -111,7 +111,7 @@ static void test_over_32_fast_gets_and_puts(void **state)
111111
assert(!memcmp(copy[i], testdata[i], sizeof(testdata[0])));
112112

113113
for (i = 0; i < ARRAY_SIZE(copy); i++)
114-
fast_put(NULL, copy[i]);
114+
fast_put(NULL, NULL, copy[i]);
115115
}
116116

117117
static void test_fast_get_refcounting(void **state)
@@ -133,13 +133,13 @@ static void test_fast_get_refcounting(void **state)
133133
assert(!memcmp(copy[0][i], testdata[i], sizeof(testdata[0])));
134134

135135
for (i = 0; i < ARRAY_SIZE(copy[0]); i++)
136-
fast_put(NULL, copy[0][i]);
136+
fast_put(NULL, NULL, copy[0][i]);
137137

138138
for (i = 0; i < ARRAY_SIZE(copy[0]); i++)
139139
assert(!memcmp(copy[1][i], testdata[i], sizeof(testdata[0])));
140140

141141
for (i = 0; i < ARRAY_SIZE(copy[0]); i++)
142-
fast_put(NULL, copy[1][i]);
142+
fast_put(NULL, NULL, copy[1][i]);
143143
}
144144

145145
int main(void)

test/ztest/unit/fast-get/test_fast_get_ztest.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ ZTEST(fast_get_suite, test_simple_fast_get_put)
7272
zassert_mem_equal(ret, testdata[0], sizeof(testdata[0]),
7373
"Returned data should match original data");
7474

75-
fast_put(NULL, ret);
75+
fast_put(NULL, NULL, ret);
7676
}
7777

7878
/**
@@ -94,7 +94,7 @@ ZTEST(fast_get_suite, test_fast_get_size_missmatch_test)
9494
ret[1] = fast_get(NULL, testdata[0], sizeof(testdata[0]) + 1);
9595
zassert_is_null(ret[1], "fast_get with different size should return NULL");
9696

97-
fast_put(NULL, ret[0]);
97+
fast_put(NULL, NULL, ret[0]);
9898
}
9999

100100
/**
@@ -116,7 +116,7 @@ ZTEST(fast_get_suite, test_over_32_fast_gets_and_puts)
116116
"Data at index %d should match original", i);
117117

118118
for (i = 0; i < ARRAY_SIZE(copy); i++)
119-
fast_put(NULL, copy[i]);
119+
fast_put(NULL, NULL, copy[i]);
120120
}
121121

122122
/**
@@ -147,7 +147,7 @@ ZTEST(fast_get_suite, test_fast_get_refcounting)
147147

148148
/* Release first set of references */
149149
for (i = 0; i < ARRAY_SIZE(copy[0]); i++)
150-
fast_put(NULL, copy[0][i]);
150+
fast_put(NULL, NULL, copy[0][i]);
151151

152152
/* Data should still be valid through second set of references */
153153
for (i = 0; i < ARRAY_SIZE(copy[0]); i++)
@@ -156,7 +156,7 @@ ZTEST(fast_get_suite, test_fast_get_refcounting)
156156

157157
/* Release second set of references */
158158
for (i = 0; i < ARRAY_SIZE(copy[0]); i++)
159-
fast_put(NULL, copy[1][i]);
159+
fast_put(NULL, NULL, copy[1][i]);
160160
}
161161

162162
/**

zephyr/lib/fast-get.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct sof_fast_get_entry {
2929
const void *dram_ptr;
3030
void *sram_ptr;
3131
#if CONFIG_USERSPACE
32-
struct k_thread *thread;
32+
struct k_mem_domain *mdom;
3333
#endif
3434
size_t size;
3535
unsigned int refcount;
@@ -117,7 +117,7 @@ static bool fast_get_domain_exists(struct k_thread *thread, void *start, size_t
117117
return false;
118118
}
119119

120-
static int fast_get_access_grant(k_tid_t thread, void *addr, size_t size)
120+
static int fast_get_access_grant(struct k_mem_domain *mdom, void *addr, size_t size)
121121
{
122122
struct k_mem_partition part = {
123123
.start = (uintptr_t)addr,
@@ -126,7 +126,7 @@ static int fast_get_access_grant(k_tid_t thread, void *addr, size_t size)
126126
};
127127

128128
LOG_DBG("add %#zx @ %p", part.size, addr);
129-
return k_mem_domain_add_partition(thread->mem_domain_info.mem_domain, &part);
129+
return k_mem_domain_add_partition(mdom, &part);
130130
}
131131
#endif /* CONFIG_USERSPACE */
132132

@@ -183,15 +183,18 @@ const void *fast_get(struct k_heap *heap, const void *dram_ptr, size_t size)
183183
ret = entry->sram_ptr;
184184

185185
#if CONFIG_USERSPACE
186+
struct k_mem_domain *mdom = k_current_get()->mem_domain_info.mem_domain;
187+
186188
/* We only get there for large buffers */
187-
if (k_current_get()->mem_domain_info.mem_domain->num_partitions > 1) {
189+
if (mdom->num_partitions > 1) {
188190
/* A userspace thread makes the request */
189-
if (k_current_get() != entry->thread &&
191+
if (mdom != entry->mdom &&
190192
!fast_get_domain_exists(k_current_get(), ret,
191193
ALIGN_UP(size, CONFIG_MM_DRV_PAGE_SIZE))) {
192-
LOG_DBG("grant access to thread %p first was %p", k_current_get(),
193-
entry->thread);
194-
int err = fast_get_access_grant(k_current_get(), ret, size);
194+
LOG_DBG("grant access to domain %p first was %p", mdom,
195+
entry->mdom);
196+
197+
int err = fast_get_access_grant(mdom, ret, size);
195198

196199
if (err < 0) {
197200
LOG_ERR("failed to grant additional access err=%d", err);
@@ -228,10 +231,10 @@ const void *fast_get(struct k_heap *heap, const void *dram_ptr, size_t size)
228231
dcache_writeback_region((__sparse_force void __sparse_cache *)entry->sram_ptr, size);
229232

230233
#if CONFIG_USERSPACE
231-
entry->thread = k_current_get();
234+
entry->mdom = k_current_get()->mem_domain_info.mem_domain;
232235
if (size > FAST_GET_MAX_COPY_SIZE) {
233236
/* Otherwise we've allocated on thread's heap, so it already has access */
234-
int err = fast_get_access_grant(entry->thread, ret, size);
237+
int err = fast_get_access_grant(entry->mdom, ret, size);
235238

236239
if (err < 0) {
237240
LOG_ERR("failed to grant access err=%d", err);
@@ -265,7 +268,7 @@ static struct sof_fast_get_entry *fast_put_find_entry(struct sof_fast_get_data *
265268
return NULL;
266269
}
267270

268-
void fast_put(struct k_heap *heap, const void *sram_ptr)
271+
void fast_put(struct k_heap *heap, struct k_mem_domain *mdom, const void *sram_ptr)
269272
{
270273
struct sof_fast_get_data *data = &fast_get_data;
271274
struct sof_fast_get_entry *entry;
@@ -294,17 +297,16 @@ void fast_put(struct k_heap *heap, const void *sram_ptr)
294297
* Order matters: free buffer first (needs partition for cache access),
295298
* then remove partition.
296299
*/
297-
if (entry->size > FAST_GET_MAX_COPY_SIZE && entry->thread) {
300+
if (entry->size > FAST_GET_MAX_COPY_SIZE && entry->mdom) {
298301
struct k_mem_partition part = {
299302
.start = (uintptr_t)entry->sram_ptr,
300303
.size = ALIGN_UP(entry->size, CONFIG_MM_DRV_PAGE_SIZE),
301304
.attr = K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB,
302305
};
303-
struct k_mem_domain *domain = k_current_get()->mem_domain_info.mem_domain;
304306

305-
LOG_DBG("removing partition %p size %#zx from thread %p",
306-
(void *)part.start, part.size, k_current_get());
307-
int err = k_mem_domain_remove_partition(domain, &part);
307+
LOG_DBG("removing partition %p size %#zx memory domain %p",
308+
(void *)part.start, part.size, mdom);
309+
int err = k_mem_domain_remove_partition(mdom, &part);
308310

309311
if (err)
310312
LOG_WRN("partition removal failed: %d", err);

0 commit comments

Comments
 (0)