Skip to content

Commit e68c92b

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, or by DSP core and separate hardware blocks), 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 4051187 commit e68c92b

File tree

4 files changed

+106
-3
lines changed

4 files changed

+106
-3
lines changed

src/audio/buffers/comp_buffer.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,15 @@ struct comp_buffer *buffer_alloc(size_t size, uint32_t flags, uint32_t align,
234234

235235
tr_dbg(&buffer_tr, "buffer_alloc()");
236236

237+
#if CONFIG_USERSPACE
238+
/*
239+
* cache control is not possible in user-space, so cross-core
240+
* buffers must be allocated as coherent
241+
*/
242+
if (is_shared && _buffer_is_user_thread())
243+
flags |= SOF_MEM_FLAG_COHERENT;
244+
#endif
245+
237246
/* validate request */
238247
if (size == 0) {
239248
tr_err(&buffer_tr, "new size = %zu is invalid", size);
@@ -272,6 +281,15 @@ struct comp_buffer *buffer_alloc_range(size_t preferred_size, size_t minimum_siz
272281
return NULL;
273282
}
274283

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

src/audio/buffers/ring_buffer.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,30 @@ static inline uint8_t __sparse_cache *ring_buffer_buffer_end(struct ring_buffer
4646
return ring_buffer->_data_buffer + ring_buffer->data_buffer_size;
4747
}
4848

49+
#if CONFIG_USERSPACE
50+
#include <zephyr/kernel.h>
51+
52+
static inline bool _ring_is_user_thread(void)
53+
{
54+
return (k_current_get()->base.user_options & K_USER) != 0;
55+
}
56+
#endif
57+
4958
static inline void ring_buffer_invalidate_shared(struct ring_buffer *ring_buffer,
5059
void __sparse_cache *ptr, size_t size)
5160
{
5261
/* no cache required in case of not shared queue */
5362
if (!ring_buffer_is_shared(ring_buffer))
5463
return;
5564

65+
#if CONFIG_USERSPACE
66+
/* user-space shared buffers are allocated as uncached */
67+
if (_ring_is_user_thread()) {
68+
__ASSERT_NO_MSG(sys_cache_is_ptr_cached(ptr) == false);
69+
return;
70+
}
71+
#endif
72+
5673
/* wrap-around? */
5774
if ((uintptr_t)ptr + size > (uintptr_t)ring_buffer_buffer_end(ring_buffer)) {
5875
/* writeback till the end of circular buffer */
@@ -72,6 +89,14 @@ static inline void ring_buffer_writeback_shared(struct ring_buffer *ring_buffer,
7289
if (!ring_buffer_is_shared(ring_buffer))
7390
return;
7491

92+
#if CONFIG_USERSPACE
93+
/* user-space shared buffers are allocated as uncached */
94+
if (_ring_is_user_thread()) {
95+
__ASSERT_NO_MSG(sys_cache_is_ptr_cached(ptr) == false);
96+
return;
97+
}
98+
#endif
99+
75100
/* wrap-around? */
76101
if ((uintptr_t)ptr + size > (uintptr_t)ring_buffer_buffer_end(ring_buffer)) {
77102
/* writeback till the end of circular buffer */
@@ -355,6 +380,20 @@ struct ring_buffer *ring_buffer_create(struct comp_dev *dev, size_t min_availabl
355380
*/
356381
ring_buffer->data_buffer_size = 3 * max_ibs_obs;
357382

383+
#if CONFIG_USERSPACE
384+
/*
385+
* cache control is not possible in user-space, so cross-core
386+
* buffers must be allocated as coherent
387+
*/
388+
if (is_shared && _ring_is_user_thread())
389+
memory_flags |= SOF_MEM_FLAG_COHERENT;
390+
391+
/*
392+
* TODO: _data_buffer is not cached anymore so will confuse
393+
* sparse
394+
*/
395+
#endif
396+
358397
/* allocate data buffer - always in cached memory alias */
359398
ring_buffer->data_buffer_size =
360399
ALIGN_UP(ring_buffer->data_buffer_size, PLATFORM_DCACHE_ALIGN);

src/include/sof/audio/audio_stream.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,15 @@ static inline void audio_stream_reset(struct audio_stream *buffer)
716716
*/
717717
void audio_stream_init(struct audio_stream *audio_stream, void *buff_addr, uint32_t size);
718718

719+
#if CONFIG_USERSPACE
720+
#include <zephyr/kernel.h>
721+
722+
static inline bool _audio_stream_is_user_thread(void)
723+
{
724+
return (k_current_get()->base.user_options & K_USER) != 0;
725+
}
726+
#endif
727+
719728
/**
720729
* Invalidates (in DSP d-cache) the buffer in range [r_ptr, r_ptr+bytes],
721730
* with rollover if necessary.
@@ -733,6 +742,14 @@ static inline void audio_stream_invalidate(struct audio_stream *buffer, uint32_t
733742
tail_size = bytes - head_size;
734743
}
735744

745+
#if CONFIG_USERSPACE
746+
/* user-space shared buffers are allocated as uncached */
747+
if (_audio_stream_is_user_thread()) {
748+
__ASSERT_NO_MSG(sys_cache_is_ptr_cached(buffer->addr) == false);
749+
return;
750+
}
751+
#endif
752+
736753
dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->r_ptr, head_size);
737754
if (tail_size)
738755
dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->addr,
@@ -756,6 +773,14 @@ static inline void audio_stream_writeback(struct audio_stream *buffer, uint32_t
756773
tail_size = bytes - head_size;
757774
}
758775

776+
#if CONFIG_USERSPACE
777+
/* user-space shared buffers are allocated as uncached */
778+
if (_audio_stream_is_user_thread()) {
779+
__ASSERT_NO_MSG(sys_cache_is_ptr_cached(buffer->addr) == false);
780+
return;
781+
}
782+
#endif
783+
759784
dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->w_ptr, head_size);
760785
if (tail_size)
761786
dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->addr,

src/include/sof/audio/buffer.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,15 @@ struct comp_buffer {
150150
struct list_item buffers_list;
151151
};
152152

153+
#if CONFIG_USERSPACE
154+
#include <zephyr/kernel.h>
155+
156+
static inline bool _buffer_is_user_thread(void)
157+
{
158+
return (k_current_get()->base.user_options & K_USER) != 0;
159+
}
160+
#endif
161+
153162
/*
154163
* get a component providing data to the buffer
155164
*/
@@ -261,20 +270,32 @@ bool buffer_params_match(struct comp_buffer *buffer,
261270
static inline void buffer_stream_invalidate(struct comp_buffer *buffer, uint32_t bytes)
262271
{
263272
#if CONFIG_INCOHERENT
264-
if (audio_buffer_is_shared(&buffer->audio_buffer))
273+
if (audio_buffer_is_shared(&buffer->audio_buffer)) {
274+
#if CONFIG_USERSPACE
275+
/* user-space shared buffers are allocated as uncached */
276+
if (_buffer_is_user_thread())
277+
return;
278+
#endif
265279
audio_stream_invalidate(&buffer->stream, bytes);
280+
}
266281
#endif
267282
}
268283

269284
static inline void buffer_stream_writeback(struct comp_buffer *buffer, uint32_t bytes)
270285
{
271286
#if CONFIG_INCOHERENT
272-
if (audio_buffer_is_shared(&buffer->audio_buffer))
287+
if (audio_buffer_is_shared(&buffer->audio_buffer)) {
288+
#if CONFIG_USERSPACE
289+
/* user-space shared buffers are allocated as uncached */
290+
if (_buffer_is_user_thread())
291+
return;
292+
#endif
293+
273294
audio_stream_writeback(&buffer->stream, bytes);
295+
}
274296
#endif
275297
}
276298

277-
278299
/*
279300
* Attach a new buffer at the beginning of the list. Note, that "head" must
280301
* really be the head of the list, not a list head within another buffer. We

0 commit comments

Comments
 (0)