/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2017, Linaro Limited */ #ifndef __KERNEL_MUTEX_H #define __KERNEL_MUTEX_H #include #include #include #include struct mutex { unsigned spin_lock; /* used when operating on this struct */ struct wait_queue wq; short state; /* -1: write, 0: unlocked, > 0: readers */ }; #define MUTEX_INITIALIZER { .wq = WAIT_QUEUE_INITIALIZER } struct recursive_mutex { struct mutex m; /* used when lock_depth goes 0 -> 1 or 1 -> 0 */ short int owner; struct refcount lock_depth; }; #define RECURSIVE_MUTEX_INITIALIZER { .m = MUTEX_INITIALIZER, \ .owner = THREAD_ID_INVALID } TAILQ_HEAD(mutex_head, mutex); void mutex_init(struct mutex *m); void mutex_destroy(struct mutex *m); void mutex_init_recursive(struct recursive_mutex *m); void mutex_destroy_recursive(struct recursive_mutex *m); unsigned int mutex_get_recursive_lock_depth(struct recursive_mutex *m); #ifdef CFG_MUTEX_DEBUG void mutex_unlock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_unlock(m) mutex_unlock_debug((m), __FILE__, __LINE__) void mutex_lock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_lock(m) mutex_lock_debug((m), __FILE__, __LINE__) bool mutex_trylock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_trylock(m) mutex_trylock_debug((m), __FILE__, __LINE__) void mutex_read_unlock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_read_unlock(m) mutex_read_unlock_debug((m), __FILE__, __LINE__) void mutex_read_lock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_read_lock(m) mutex_read_lock_debug((m), __FILE__, __LINE__) bool mutex_read_trylock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_read_trylock(m) mutex_read_trylock_debug((m), __FILE__, __LINE__) void mutex_unlock_recursive_debug(struct recursive_mutex *m, const char *fname, int lineno); #define mutex_unlock_recursive(m) mutex_unlock_recursive_debug((m), __FILE__, \ __LINE__) void mutex_lock_recursive_debug(struct recursive_mutex *m, const char *fname, int lineno); #define mutex_lock_recursive(m) mutex_lock_recursive_debug((m), __FILE__, \ __LINE__) #else void mutex_unlock(struct mutex *m); void mutex_lock(struct mutex *m); bool mutex_trylock(struct mutex *m); void mutex_read_unlock(struct mutex *m); void mutex_read_lock(struct mutex *m); bool mutex_read_trylock(struct mutex *m); void mutex_unlock_recursive(struct recursive_mutex *m); void mutex_lock_recursive(struct recursive_mutex *m); #endif struct condvar { unsigned int spin_lock; struct mutex *m; }; #define CONDVAR_INITIALIZER { .m = NULL } void condvar_init(struct condvar *cv); void condvar_destroy(struct condvar *cv); #ifdef CFG_MUTEX_DEBUG void condvar_signal_debug(struct condvar *cv, const char *fname, int lineno); #define condvar_signal(cv) condvar_signal_debug((cv), __FILE__, __LINE__) void condvar_broadcast_debug(struct condvar *cv, const char *fname, int lineno); #define condvar_broadcast(cv) condvar_broadcast_debug((cv), __FILE__, __LINE__) void condvar_wait_debug(struct condvar *cv, struct mutex *m, const char *fname, int lineno); #define condvar_wait(cv, m) condvar_wait_debug((cv), (m), __FILE__, __LINE__) /* * Return TEE_ERROR_TIMEOUT if the normal world returns before * the condvar has been signaled. */ TEE_Result condvar_wait_timeout_debug(struct condvar *cv, struct mutex *m, uint32_t timeout_ms, const char *fname, int lineno); #define condvar_wait_timeout(cv, m, timeout_ms) \ condvar_wait_timeout_debug((cv), (m), (timeout_ms), __FILE__, __LINE__) #else void condvar_signal(struct condvar *cv); void condvar_broadcast(struct condvar *cv); void condvar_wait(struct condvar *cv, struct mutex *m); /* * Return TEE_ERROR_TIMEOUT if the normal world returns before * the condvar has been signaled. */ TEE_Result condvar_wait_timeout(struct condvar *cv, struct mutex *m, uint32_t timeout_ms); #endif /* * Helper for testing that a given mutex is locked. This helper is to be used * with caution since it does not enforce that the executing thread is holding * the mutex. */ static inline bool mutex_is_locked(struct mutex *m) { return m->state; } #endif /*__KERNEL_MUTEX_H*/