14#ifndef __SOF_COHERENT_H__
15#define __SOF_COHERENT_H__
31#define __coherent __aligned(PLATFORM_DCACHE_ALIGN)
91BUILD_ASSERT(
sizeof(
struct coherent) <= DCACHE_LINE_SIZE,
"DCACHE_LINE_SIZE too small");
98#ifdef COHERENT_CHECK_ALIAS
99#define ADDR_IS_INCOHERENT(_c) assert(!is_uncached(_c))
100#define ADDR_IS_COHERENT(_c) assert(is_uncached(_c))
102#define ADDR_IS_INCOHERENT(_c)
103#define ADDR_IS_COHERENT(_c)
107#ifdef COHERENT_CHECK_NONSHARED_CORES
109#define CORE_CHECK_STRUCT_FIELD uint32_t __core; bool __is_shared
110#define CORE_CHECK_STRUCT_INIT(_c, is_shared) { (_c)->__core = cpu_get_id(); \
111 (_c)->__is_shared = is_shared; }
112#define CORE_CHECK_STRUCT(_c) { assert(!!(_c)->__is_shared == !!is_uncached(_c)); \
113 assert(cpu_get_id() == (_c)->__core || (_c)->__is_shared); }
115#define CHECK_COHERENT_CORE(_c) assert((_c)->core == cpu_get_id())
119#define CORE_CHECK_STRUCT_FIELD
120#define CORE_CHECK_STRUCT_INIT(_c, is_shared)
121#define CORE_CHECK_STRUCT(_c)
123#define CHECK_COHERENT_CORE(_c)
128#define CHECK_ISR() __ASSERT(!k_is_in_isr(), "Attempt to sleep in ISR!")
129#define CHECK_SLEEP(_c) __ASSERT((_c)->sleep_allowed, \
130 "This context hasn't been initialized for sleeping!")
131#define CHECK_ATOMIC(_c) __ASSERT(!(_c)->sleep_allowed, \
132 "This context has been initialized for sleeping!")
134#define CHECK_ISR() assert(!k_is_in_isr())
135#define CHECK_SLEEP(_c) assert((_c)->sleep_allowed)
136#define CHECK_ATOMIC(_c) assert(!(_c)->sleep_allowed)
154 struct coherent __sparse_cache *cc = uncache_to_cache(c);
164 c->
key = k_spin_lock(&c->
lock);
203 struct coherent *uc = cache_to_uncache(c);
210 k_spin_unlock(&uc->
lock, uc->
key);
232 ALIGN_UP(size, PLATFORM_DCACHE_ALIGN));
238 c = (
struct coherent *)((uint8_t *)
object + offset);
260#define coherent_init(type, member) __coherent_init(offsetof(type, member), \
278 c->
key = k_spin_lock(&c->
lock);
281 k_spin_unlock(&c->
lock, c->
key);
292#define coherent_shared(object, member) __coherent_shared(&(object)->member, \
308 struct coherent *c,
const size_t size)
310 struct coherent __sparse_cache *cc = uncache_to_cache(c);
321 k_mutex_lock(&c->
mutex, K_FOREVER);
350 struct coherent *uc = cache_to_uncache(c);
357 k_mutex_unlock(&uc->
mutex);
375 ALIGN_UP(size, PLATFORM_DCACHE_ALIGN));
381 c = (
struct coherent *)((uint8_t *)
object + offset);
384 k_mutex_init(&c->
mutex);
403#define coherent_init_thread(type, member) __coherent_init_thread(offsetof(type, member), \
422 k_mutex_lock(&c->
mutex, K_FOREVER);
425 k_mutex_unlock(&c->
mutex);
436#define coherent_shared_thread(object, member) __coherent_shared_thread(&(object)->member, \
449#define coherent_free(object, member) \
452 ADDR_IS_COHERENT(object); \
454 dcache_writeback_invalidate_region(uncache_to_cache(object), \
468 c->
key = k_spin_lock(&c->
lock);
470 return (__sparse_force
struct coherent __sparse_cache *)c;
477 k_spin_unlock(&c->lock, c->key);
484 ALIGN_UP(size, PLATFORM_DCACHE_ALIGN));
490 c = (
struct coherent *)((uint8_t *)
object + offset);
501#define coherent_init(type, member) __coherent_init(offsetof(type, member), \
504#define coherent_free(object, member) rfree(object)
508 c->
key = k_spin_lock(&c->
lock);
510 k_spin_unlock(&c->
lock, c->
key);
513#define coherent_shared(object, member) __coherent_shared(&(object)->member, \
518 struct coherent *c,
const size_t size)
521 k_mutex_lock(&c->
mutex, K_FOREVER);
523 return (__sparse_force
struct coherent __sparse_cache *)c;
530 k_mutex_unlock(&c->mutex);
537 ALIGN_UP(size, PLATFORM_DCACHE_ALIGN));
543 c = (
struct coherent *)((uint8_t *)
object + offset);
546 k_mutex_init(&c->
mutex);
554#define coherent_init_thread(type, member) __coherent_init_thread(offsetof(type, member), \
559 k_mutex_lock(&c->
mutex, K_FOREVER);
561 k_mutex_unlock(&c->
mutex);
564#define coherent_shared_thread(object, member) __coherent_shared_thread(&(object)->member, \
571#define coherent_acquire_thread coherent_acquire
572#define coherent_release_thread coherent_release
573#define coherent_init_thread coherent_init
574#define coherent_shared_thread coherent_shared
585#define coherent_free_thread coherent_free
593#define is_coherent_shared(object, member) ((object)->member.shared)
static void dcache_writeback_invalidate_region(void *addr, size_t size)
Write back and invalidate data cache lines in the specified memory region.
Definition cache.h:95
static void dcache_invalidate_region(void *addr, size_t size)
Invalidate data cache lines in the specified memory region.
Definition cache.h:67
#define STATIC_ASSERT(COND, MESSAGE)
Definition common.h:156
#define ALIGN_UP(size, alignment)
Definition common.h:93
#define __must_check
Definition common.h:15
#define CHECK_ISR()
Definition coherent.h:128
static void __coherent_shared(struct coherent *c, const size_t size)
Internal helper to mark an allocated coherent object as actively shared.
Definition coherent.h:272
#define ADDR_IS_COHERENT(_c)
Definition coherent.h:103
#define CHECK_COHERENT_CORE(_c)
Definition coherent.h:123
static struct coherent * coherent_acquire(struct coherent *c, const size_t size)
Acquire exclusive access to a cache-coherent shared object in atomic/spinlock context.
Definition coherent.h:151
void * rzalloc(uint32_t flags, size_t bytes)
Allocate zero-initialized memory block with default natural alignment.
static void * __coherent_init(size_t offset, const size_t size)
Internal helper to allocate and initialize a coherent shared object.
Definition coherent.h:224
#define SOF_MEM_FLAG_USER
Base allocation flag denoting memory allocated for user-space threads and module execution.
Definition alloc.h:69
static void * __coherent_init_thread(size_t offset, const size_t size)
Internal helper to allocate and initialize a thread-capable coherent shared object.
Definition coherent.h:371
static struct coherent * coherent_acquire_thread(struct coherent *c, const size_t size)
Acquire exclusive access to a cache-coherent shared object in thread/mutex context.
Definition coherent.h:307
static void coherent_release(struct coherent *c, const size_t size)
Release exclusive access to a cache-coherent shared object in atomic/spinlock context.
Definition coherent.h:194
static void __coherent_shared_thread(struct coherent *c, const size_t size)
Internal helper to mark a thread-capable coherent object as actively shared.
Definition coherent.h:415
#define CHECK_SLEEP(_c)
Definition coherent.h:129
static void coherent_release_thread(struct coherent *c, const size_t size)
Release exclusive access to a cache-coherent shared object in thread/mutex context.
Definition coherent.h:340
#define SOF_MEM_FLAG_COHERENT
Allocate uncached / coherent memory address.
Definition alloc.h:53
#define ADDR_IS_INCOHERENT(_c)
Definition coherent.h:102
#define __coherent
Cache line alignment specifier for coherent shared memory objects.
Definition coherent.h:31
#define CHECK_ATOMIC(_c)
Definition coherent.h:131
static void list_init(struct list_item *list)
Definition list.h:25
Memory attributes, cold/hot execution paths, and platform memory inclusions.
RTOS spinlock primitives and initialization.
static void k_spinlock_init(struct k_spinlock *lock)
Initialize a spinlock structure to the unlocked state.
Definition spinlock.h:25
Header embedded at start of multi-core shared memory objects for cache coherence.
Definition coherent.h:73
k_spinlock_key_t key
Spinlock key storing interrupt flags.
Definition coherent.h:77
uint16_t core
Owner core ID when object is not shared.
Definition coherent.h:85
struct k_spinlock lock
Spinlock synchronizing multi-core access.
Definition coherent.h:76
struct k_mutex mutex
Mutex synchronizing thread-level access when sleeping is allowed.
Definition coherent.h:80
uint8_t shared
Non-zero if object is shared across non-coherent cores.
Definition coherent.h:84
uint8_t sleep_allowed
Non-zero if context allows sleeping/blocking mutex operations.
Definition coherent.h:83
struct list_item list
Node for coherent tracking list iteration.
Definition coherent.h:86