Skip to content

Commit 3e19e01

Browse files
committed
audio: make shared buffers uncached for user-space threads
To ease moving audio code to user-space, modify the logic for allocating shared buffers so that if a buffer is shared (accessed by multiple cores), and code is run in user-space, the buffer is allocated uncached. Similarly, in invalidate and writeback functions, check for matching conditions and skip the cache operations accordingly. This approach allows to reuse most of the audio module code in user-space and even have shared buffers between different user-space threads running on different cores. There is no impact to builds without user-space, or when running modules in user-space without shared buffers. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent ba3e73f commit 3e19e01

4 files changed

Lines changed: 79 additions & 3 deletions

File tree

src/audio/buffers/comp_buffer.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <errno.h>
2525
#include <stddef.h>
2626
#include <stdint.h>
27+
#include <zephyr/syscall.h>
2728

2829
LOG_MODULE_REGISTER(buffer, CONFIG_SOF_LOG_LEVEL);
2930

@@ -235,6 +236,15 @@ struct comp_buffer *buffer_alloc(size_t size, uint32_t flags, uint32_t align,
235236

236237
tr_dbg(&buffer_tr, "buffer_alloc()");
237238

239+
#if CONFIG_USERSPACE
240+
/*
241+
* cache control is not possible in user-space, so cross-core
242+
* buffers must be allocated as coherent
243+
*/
244+
if (is_shared && k_is_user_context())
245+
flags |= SOF_MEM_FLAG_COHERENT;
246+
#endif
247+
238248
/* validate request */
239249
if (size == 0) {
240250
tr_err(&buffer_tr, "new size = %zu is invalid", size);
@@ -273,6 +283,15 @@ struct comp_buffer *buffer_alloc_range(size_t preferred_size, size_t minimum_siz
273283
return NULL;
274284
}
275285

286+
#if CONFIG_USERSPACE
287+
/*
288+
* cache control is not possible in user-space, so cross-core
289+
* buffers must be allocated as coherent
290+
*/
291+
if (is_shared && k_is_user_context())
292+
flags |= SOF_MEM_FLAG_COHERENT;
293+
#endif
294+
276295
/* Align preferred size to a multiple of the minimum size */
277296
if (preferred_size % minimum_size)
278297
preferred_size += minimum_size - preferred_size % minimum_size;

src/audio/buffers/ring_buffer.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <rtos/alloc.h>
1414
#include <ipc/topology.h>
1515

16+
#include <zephyr/syscall.h>
17+
1618
LOG_MODULE_REGISTER(ring_buffer, CONFIG_SOF_LOG_LEVEL);
1719

1820
SOF_DEFINE_REG_UUID(ring_buffer);
@@ -53,6 +55,14 @@ static inline void ring_buffer_invalidate_shared(struct ring_buffer *ring_buffer
5355
if (!ring_buffer_is_shared(ring_buffer))
5456
return;
5557

58+
#if CONFIG_USERSPACE
59+
/* user-space shared buffers are allocated as uncached */
60+
if (k_is_user_context()) {
61+
__ASSERT_NO_MSG(sys_cache_is_ptr_cached(ptr) == false);
62+
return;
63+
}
64+
#endif
65+
5666
/* wrap-around? */
5767
if ((uintptr_t)ptr + size > (uintptr_t)ring_buffer_buffer_end(ring_buffer)) {
5868
/* writeback till the end of circular buffer */
@@ -72,6 +82,14 @@ static inline void ring_buffer_writeback_shared(struct ring_buffer *ring_buffer,
7282
if (!ring_buffer_is_shared(ring_buffer))
7383
return;
7484

85+
#if CONFIG_USERSPACE
86+
/* user-space shared buffers are allocated as uncached */
87+
if (k_is_user_context()) {
88+
__ASSERT_NO_MSG(sys_cache_is_ptr_cached(ptr) == false);
89+
return;
90+
}
91+
#endif
92+
7593
/* wrap-around? */
7694
if ((uintptr_t)ptr + size > (uintptr_t)ring_buffer_buffer_end(ring_buffer)) {
7795
/* writeback till the end of circular buffer */
@@ -355,6 +373,15 @@ struct ring_buffer *ring_buffer_create(struct comp_dev *dev, size_t min_availabl
355373
*/
356374
ring_buffer->data_buffer_size = 3 * max_ibs_obs;
357375

376+
#if CONFIG_USERSPACE
377+
/*
378+
* cache control is not possible in user-space, so cross-core
379+
* buffers must be allocated as coherent
380+
*/
381+
if (is_shared && k_is_user_context())
382+
memory_flags |= SOF_MEM_FLAG_COHERENT;
383+
#endif
384+
358385
/* allocate data buffer - always in cached memory alias */
359386
ring_buffer->data_buffer_size =
360387
ALIGN_UP(ring_buffer->data_buffer_size, PLATFORM_DCACHE_ALIGN);

src/include/sof/audio/audio_stream.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <ipc/stream.h>
2727
#include <ipc4/base-config.h>
2828
#include <module/audio/audio_stream.h>
29+
#include <zephyr/syscall.h>
2930

3031
#include <stdbool.h>
3132
#include <stdint.h>
@@ -733,6 +734,14 @@ static inline void audio_stream_invalidate(struct audio_stream *buffer, uint32_t
733734
tail_size = bytes - head_size;
734735
}
735736

737+
#if CONFIG_USERSPACE
738+
/* user-space shared buffers are allocated as uncached */
739+
if (k_is_user_context()) {
740+
__ASSERT_NO_MSG(sys_cache_is_ptr_cached(buffer->addr) == false);
741+
return;
742+
}
743+
#endif
744+
736745
dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->r_ptr, head_size);
737746
if (tail_size)
738747
dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->addr,
@@ -756,6 +765,14 @@ static inline void audio_stream_writeback(struct audio_stream *buffer, uint32_t
756765
tail_size = bytes - head_size;
757766
}
758767

768+
#if CONFIG_USERSPACE
769+
/* user-space shared buffers are allocated as uncached */
770+
if (k_is_user_context()) {
771+
__ASSERT_NO_MSG(sys_cache_is_ptr_cached(buffer->addr) == false);
772+
return;
773+
}
774+
#endif
775+
759776
dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->w_ptr, head_size);
760777
if (tail_size)
761778
dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->addr,

src/include/sof/audio/buffer.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <ipc/topology.h>
2828
#include <user/trace.h>
2929
#include <sof/audio/format.h>
30+
#include <zephyr/syscall.h>
3031

3132
#include <stdbool.h>
3233
#include <stddef.h>
@@ -257,20 +258,32 @@ bool buffer_params_match(struct comp_buffer *buffer,
257258
static inline void buffer_stream_invalidate(struct comp_buffer *buffer, uint32_t bytes)
258259
{
259260
#if CONFIG_INCOHERENT
260-
if (audio_buffer_is_shared(&buffer->audio_buffer))
261+
if (audio_buffer_is_shared(&buffer->audio_buffer)) {
262+
#if CONFIG_USERSPACE
263+
/* user-space shared buffers are allocated as uncached */
264+
if (k_is_user_context())
265+
return;
266+
#endif
261267
audio_stream_invalidate(&buffer->stream, bytes);
268+
}
262269
#endif
263270
}
264271

265272
static inline void buffer_stream_writeback(struct comp_buffer *buffer, uint32_t bytes)
266273
{
267274
#if CONFIG_INCOHERENT
268-
if (audio_buffer_is_shared(&buffer->audio_buffer))
275+
if (audio_buffer_is_shared(&buffer->audio_buffer)) {
276+
#if CONFIG_USERSPACE
277+
/* user-space shared buffers are allocated as uncached */
278+
if (k_is_user_context())
279+
return;
280+
#endif
281+
269282
audio_stream_writeback(&buffer->stream, bytes);
283+
}
270284
#endif
271285
}
272286

273-
274287
/*
275288
* Attach a new buffer at the beginning of the list. Note, that "head" must
276289
* really be the head of the list, not a list head within another buffer. We

0 commit comments

Comments
 (0)