| /* |
| * Copyright (c) 2019 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_SYS_MUTEX_H_ |
| #define ZEPHYR_INCLUDE_SYS_MUTEX_H_ |
| |
| /* |
| * sys_mutex behaves almost exactly like k_mutex, with the added advantage |
| * that a sys_mutex instance can reside in user memory. |
| * |
| * Further enhancements will support locking/unlocking uncontended sys_mutexes |
| * with simple atomic ops instead of syscalls, similar to Linux's |
| * FUTEX_LOCK_PI and FUTEX_UNLOCK_PI |
| */ |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #ifdef CONFIG_USERSPACE |
| #include <sys/atomic.h> |
| #include <zephyr/types.h> |
| #include <sys_clock.h> |
| |
| struct sys_mutex { |
| /* Currently unused, but will be used to store state for fast mutexes |
| * that can be locked/unlocked with atomic ops if there is no |
| * contention |
| */ |
| atomic_t val; |
| }; |
| |
| /** |
| * @defgroup user_mutex_apis User mode mutex APIs |
| * @ingroup kernel_apis |
| * @{ |
| */ |
| |
| /** |
| * @brief Statically define and initialize a sys_mutex |
| * |
| * The mutex can be accessed outside the module where it is defined using: |
| * |
| * @code extern struct sys_mutex <name>; @endcode |
| * |
| * Route this to memory domains using K_APP_DMEM(). |
| * |
| * @param name Name of the mutex. |
| */ |
| #define SYS_MUTEX_DEFINE(name) \ |
| struct sys_mutex name |
| |
| /** |
| * @brief Initialize a mutex. |
| * |
| * This routine initializes a mutex object, prior to its first use. |
| * |
| * Upon completion, the mutex is available and does not have an owner. |
| * |
| * This routine is only necessary to call when userspace is disabled |
| * and the mutex was not created with SYS_MUTEX_DEFINE(). |
| * |
| * @param mutex Address of the mutex. |
| * |
| * @return N/A |
| */ |
| static inline void sys_mutex_init(struct sys_mutex *mutex) |
| { |
| ARG_UNUSED(mutex); |
| |
| /* Nothing to do, kernel-side data structures are initialized at |
| * boot |
| */ |
| } |
| |
| __syscall int z_sys_mutex_kernel_lock(struct sys_mutex *mutex, |
| k_timeout_t timeout); |
| |
| __syscall int z_sys_mutex_kernel_unlock(struct sys_mutex *mutex); |
| |
| /** |
| * @brief Lock a mutex. |
| * |
| * This routine locks @a mutex. If the mutex is locked by another thread, |
| * the calling thread waits until the mutex becomes available or until |
| * a timeout occurs. |
| * |
| * A thread is permitted to lock a mutex it has already locked. The operation |
| * completes immediately and the lock count is increased by 1. |
| * |
| * @param mutex Address of the mutex, which may reside in user memory |
| * @param timeout Waiting period to lock the mutex, |
| * or one of the special values K_NO_WAIT and K_FOREVER. |
| * |
| * @retval 0 Mutex locked. |
| * @retval -EBUSY Returned without waiting. |
| * @retval -EAGAIN Waiting period timed out. |
| * @retval -EACCES Caller has no access to provided mutex address |
| * @retval -EINVAL Provided mutex not recognized by the kernel |
| */ |
| static inline int sys_mutex_lock(struct sys_mutex *mutex, k_timeout_t timeout) |
| { |
| /* For now, make the syscall unconditionally */ |
| return z_sys_mutex_kernel_lock(mutex, timeout); |
| } |
| |
| /** |
| * @brief Unlock a mutex. |
| * |
| * This routine unlocks @a mutex. The mutex must already be locked by the |
| * calling thread. |
| * |
| * The mutex cannot be claimed by another thread until it has been unlocked by |
| * the calling thread as many times as it was previously locked by that |
| * thread. |
| * |
| * @param mutex Address of the mutex, which may reside in user memory |
| * @retval 0 Mutex unlocked |
| * @retval -EACCES Caller has no access to provided mutex address |
| * @retval -EINVAL Provided mutex not recognized by the kernel or mutex wasn't |
| * locked |
| * @retval -EPERM Caller does not own the mutex |
| */ |
| static inline int sys_mutex_unlock(struct sys_mutex *mutex) |
| { |
| /* For now, make the syscall unconditionally */ |
| return z_sys_mutex_kernel_unlock(mutex); |
| } |
| |
| #include <syscalls/mutex.h> |
| |
| #else |
| #include <kernel.h> |
| #include <kernel_structs.h> |
| |
| struct sys_mutex { |
| struct k_mutex kernel_mutex; |
| }; |
| |
| #define SYS_MUTEX_DEFINE(name) \ |
| struct sys_mutex name = { \ |
| .kernel_mutex = Z_MUTEX_INITIALIZER(name.kernel_mutex) \ |
| } |
| |
| static inline void sys_mutex_init(struct sys_mutex *mutex) |
| { |
| k_mutex_init(&mutex->kernel_mutex); |
| } |
| |
| static inline int sys_mutex_lock(struct sys_mutex *mutex, k_timeout_t timeout) |
| { |
| return k_mutex_lock(&mutex->kernel_mutex, timeout); |
| } |
| |
| static inline int sys_mutex_unlock(struct sys_mutex *mutex) |
| { |
| return k_mutex_unlock(&mutex->kernel_mutex); |
| } |
| |
| #endif /* CONFIG_USERSPACE */ |
| |
| /** |
| * @} |
| */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* ZEPHYR_INCLUDE_SYS_MUTEX_H_ */ |