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 usermode_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_ */
|