1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2014-2017, Linaro Limited 4 */ 5 #ifndef __KERNEL_MUTEX_H 6 #define __KERNEL_MUTEX_H 7 8 #include <kernel/refcount.h> 9 #include <kernel/wait_queue.h> 10 #include <sys/queue.h> 11 #include <types_ext.h> 12 13 struct mutex { 14 unsigned spin_lock; /* used when operating on this struct */ 15 struct wait_queue wq; 16 short state; /* -1: write, 0: unlocked, > 0: readers */ 17 }; 18 19 #define MUTEX_INITIALIZER { .wq = WAIT_QUEUE_INITIALIZER } 20 21 struct recursive_mutex { 22 struct mutex m; /* used when lock_depth goes 0 -> 1 or 1 -> 0 */ 23 short int owner; 24 struct refcount lock_depth; 25 }; 26 27 #define RECURSIVE_MUTEX_INITIALIZER { .m = MUTEX_INITIALIZER, \ 28 .owner = THREAD_ID_INVALID } 29 30 TAILQ_HEAD(mutex_head, mutex); 31 32 void mutex_init(struct mutex *m); 33 void mutex_destroy(struct mutex *m); 34 35 void mutex_init_recursive(struct recursive_mutex *m); 36 void mutex_destroy_recursive(struct recursive_mutex *m); 37 unsigned int mutex_get_recursive_lock_depth(struct recursive_mutex *m); 38 39 #ifdef CFG_MUTEX_DEBUG 40 void mutex_unlock_debug(struct mutex *m, const char *fname, int lineno); 41 #define mutex_unlock(m) mutex_unlock_debug((m), __FILE__, __LINE__) 42 43 void mutex_lock_debug(struct mutex *m, const char *fname, int lineno); 44 #define mutex_lock(m) mutex_lock_debug((m), __FILE__, __LINE__) 45 46 bool mutex_trylock_debug(struct mutex *m, const char *fname, int lineno); 47 #define mutex_trylock(m) mutex_trylock_debug((m), __FILE__, __LINE__) 48 49 void mutex_read_unlock_debug(struct mutex *m, const char *fname, int lineno); 50 #define mutex_read_unlock(m) mutex_read_unlock_debug((m), __FILE__, __LINE__) 51 52 void mutex_read_lock_debug(struct mutex *m, const char *fname, int lineno); 53 #define mutex_read_lock(m) mutex_read_lock_debug((m), __FILE__, __LINE__) 54 55 bool mutex_read_trylock_debug(struct mutex *m, const char *fname, int lineno); 56 #define mutex_read_trylock(m) mutex_read_trylock_debug((m), __FILE__, __LINE__) 57 58 void mutex_unlock_recursive_debug(struct recursive_mutex *m, const char *fname, 59 int lineno); 60 #define mutex_unlock_recursive(m) mutex_unlock_recursive_debug((m), __FILE__, \ 61 __LINE__) 62 63 void mutex_lock_recursive_debug(struct recursive_mutex *m, const char *fname, 64 int lineno); 65 #define mutex_lock_recursive(m) mutex_lock_recursive_debug((m), __FILE__, \ 66 __LINE__) 67 #else 68 void mutex_unlock(struct mutex *m); 69 void mutex_lock(struct mutex *m); 70 bool mutex_trylock(struct mutex *m); 71 void mutex_read_unlock(struct mutex *m); 72 void mutex_read_lock(struct mutex *m); 73 bool mutex_read_trylock(struct mutex *m); 74 75 void mutex_unlock_recursive(struct recursive_mutex *m); 76 void mutex_lock_recursive(struct recursive_mutex *m); 77 #endif 78 79 struct condvar { 80 unsigned int spin_lock; 81 struct mutex *m; 82 }; 83 #define CONDVAR_INITIALIZER { .m = NULL } 84 85 void condvar_init(struct condvar *cv); 86 void condvar_destroy(struct condvar *cv); 87 88 #ifdef CFG_MUTEX_DEBUG 89 void condvar_signal_debug(struct condvar *cv, const char *fname, int lineno); 90 #define condvar_signal(cv) condvar_signal_debug((cv), __FILE__, __LINE__) 91 92 void condvar_broadcast_debug(struct condvar *cv, const char *fname, int lineno); 93 #define condvar_broadcast(cv) condvar_broadcast_debug((cv), __FILE__, __LINE__) 94 95 void condvar_wait_debug(struct condvar *cv, struct mutex *m, 96 const char *fname, int lineno); 97 #define condvar_wait(cv, m) condvar_wait_debug((cv), (m), __FILE__, __LINE__) 98 99 /* 100 * Return TEE_ERROR_TIMEOUT if the normal world returns before 101 * the condvar has been signaled. 102 */ 103 TEE_Result condvar_wait_timeout_debug(struct condvar *cv, struct mutex *m, 104 uint32_t timeout_ms, const char *fname, 105 int lineno); 106 #define condvar_wait_timeout(cv, m, timeout_ms) \ 107 condvar_wait_timeout_debug((cv), (m), (timeout_ms), __FILE__, __LINE__) 108 #else 109 void condvar_signal(struct condvar *cv); 110 void condvar_broadcast(struct condvar *cv); 111 void condvar_wait(struct condvar *cv, struct mutex *m); 112 /* 113 * Return TEE_ERROR_TIMEOUT if the normal world returns before 114 * the condvar has been signaled. 115 */ 116 TEE_Result condvar_wait_timeout(struct condvar *cv, struct mutex *m, 117 uint32_t timeout_ms); 118 #endif 119 120 /* 121 * Helper for testing that a given mutex is locked for writing. This helper 122 * is to be used with caution since it does not guarantee that the executing 123 * thread is holding the mutex. 124 */ 125 static inline bool mutex_is_locked(struct mutex *m) 126 { 127 return m->state == -1; /* write locked */ 128 } 129 #endif /*__KERNEL_MUTEX_H*/ 130 131