Line data Source code
1 0 : /* 2 : * Copyright (c) 2019 Intel Corporation 3 : * 4 : * SPDX-License-Identifier: Apache-2.0 5 : */ 6 : 7 : #ifndef ZEPHYR_INCLUDE_SYS_MUTEX_H_ 8 : #define ZEPHYR_INCLUDE_SYS_MUTEX_H_ 9 : 10 : /* 11 : * sys_mutex behaves almost exactly like k_mutex, with the added advantage 12 : * that a sys_mutex instance can reside in user memory. 13 : * 14 : * Further enhancements will support locking/unlocking uncontended sys_mutexes 15 : * with simple atomic ops instead of syscalls, similar to Linux's 16 : * FUTEX_LOCK_PI and FUTEX_UNLOCK_PI 17 : */ 18 : 19 : #ifdef __cplusplus 20 : extern "C" { 21 : #endif 22 : 23 : #ifdef CONFIG_USERSPACE 24 : #include <zephyr/sys/atomic.h> 25 : #include <zephyr/types.h> 26 : #include <zephyr/sys_clock.h> 27 : 28 0 : struct sys_mutex { 29 : /* Currently unused, but will be used to store state for fast mutexes 30 : * that can be locked/unlocked with atomic ops if there is no 31 : * contention 32 : */ 33 0 : atomic_t val; 34 : }; 35 : 36 : /** 37 : * @defgroup user_mutex_apis User mode mutex APIs 38 : * @ingroup kernel_apis 39 : * @{ 40 : */ 41 : 42 : /** 43 : * @brief Statically define and initialize a sys_mutex 44 : * 45 : * The mutex can be accessed outside the module where it is defined using: 46 : * 47 : * @code extern struct sys_mutex <name>; @endcode 48 : * 49 : * Route this to memory domains using K_APP_DMEM(). 50 : * 51 : * @param name Name of the mutex. 52 : */ 53 1 : #define SYS_MUTEX_DEFINE(name) \ 54 : struct sys_mutex name 55 : 56 : /** 57 : * @brief Initialize a mutex. 58 : * 59 : * This routine initializes a mutex object, prior to its first use. 60 : * 61 : * Upon completion, the mutex is available and does not have an owner. 62 : * 63 : * This routine is only necessary to call when userspace is disabled 64 : * and the mutex was not created with SYS_MUTEX_DEFINE(). 65 : * 66 : * @param mutex Address of the mutex. 67 : */ 68 1 : static inline void sys_mutex_init(struct sys_mutex *mutex) 69 : { 70 : ARG_UNUSED(mutex); 71 : 72 : /* Nothing to do, kernel-side data structures are initialized at 73 : * boot 74 : */ 75 : } 76 : 77 : __syscall int z_sys_mutex_kernel_lock(struct sys_mutex *mutex, 78 : k_timeout_t timeout); 79 : 80 : __syscall int z_sys_mutex_kernel_unlock(struct sys_mutex *mutex); 81 : 82 : /** 83 : * @brief Lock a mutex. 84 : * 85 : * This routine locks @a mutex. If the mutex is locked by another thread, 86 : * the calling thread waits until the mutex becomes available or until 87 : * a timeout occurs. 88 : * 89 : * A thread is permitted to lock a mutex it has already locked. The operation 90 : * completes immediately and the lock count is increased by 1. 91 : * 92 : * @param mutex Address of the mutex, which may reside in user memory 93 : * @param timeout Waiting period to lock the mutex, 94 : * or one of the special values K_NO_WAIT and K_FOREVER. 95 : * 96 : * @retval 0 Mutex locked. 97 : * @retval -EBUSY Returned without waiting. 98 : * @retval -EAGAIN Waiting period timed out. 99 : * @retval -EACCES Caller has no access to provided mutex address 100 : * @retval -EINVAL Provided mutex not recognized by the kernel 101 : */ 102 1 : static inline int sys_mutex_lock(struct sys_mutex *mutex, k_timeout_t timeout) 103 : { 104 : /* For now, make the syscall unconditionally */ 105 : return z_sys_mutex_kernel_lock(mutex, timeout); 106 : } 107 : 108 : /** 109 : * @brief Unlock a mutex. 110 : * 111 : * This routine unlocks @a mutex. The mutex must already be locked by the 112 : * calling thread. 113 : * 114 : * The mutex cannot be claimed by another thread until it has been unlocked by 115 : * the calling thread as many times as it was previously locked by that 116 : * thread. 117 : * 118 : * @param mutex Address of the mutex, which may reside in user memory 119 : * @retval 0 Mutex unlocked 120 : * @retval -EACCES Caller has no access to provided mutex address 121 : * @retval -EINVAL Provided mutex not recognized by the kernel or mutex wasn't 122 : * locked 123 : * @retval -EPERM Caller does not own the mutex 124 : */ 125 1 : static inline int sys_mutex_unlock(struct sys_mutex *mutex) 126 : { 127 : /* For now, make the syscall unconditionally */ 128 : return z_sys_mutex_kernel_unlock(mutex); 129 : } 130 : 131 : #include <zephyr/syscalls/mutex.h> 132 : 133 : #else 134 : #include <zephyr/kernel.h> 135 : #include <zephyr/kernel_structs.h> 136 : 137 : struct sys_mutex { 138 : struct k_mutex kernel_mutex; 139 : }; 140 : 141 : #define SYS_MUTEX_DEFINE(name) \ 142 : struct sys_mutex name = { \ 143 : .kernel_mutex = Z_MUTEX_INITIALIZER(name.kernel_mutex) \ 144 : } 145 : 146 : static inline void sys_mutex_init(struct sys_mutex *mutex) 147 : { 148 : k_mutex_init(&mutex->kernel_mutex); 149 : } 150 : 151 : static inline int sys_mutex_lock(struct sys_mutex *mutex, k_timeout_t timeout) 152 : { 153 : return k_mutex_lock(&mutex->kernel_mutex, timeout); 154 : } 155 : 156 : static inline int sys_mutex_unlock(struct sys_mutex *mutex) 157 : { 158 : return k_mutex_unlock(&mutex->kernel_mutex); 159 : } 160 : 161 : #endif /* CONFIG_USERSPACE */ 162 : 163 : /** 164 : * @} 165 : */ 166 : 167 : #ifdef __cplusplus 168 : } 169 : #endif 170 : 171 : #endif /* ZEPHYR_INCLUDE_SYS_MUTEX_H_ */