diff options
Diffstat (limited to 'lib/chibios/os/oslib')
23 files changed, 7218 insertions, 0 deletions
diff --git a/lib/chibios/os/oslib/dox/lib.dox b/lib/chibios/os/oslib/dox/lib.dox new file mode 100644 index 000000000..7386c1365 --- /dev/null +++ b/lib/chibios/os/oslib/dox/lib.dox | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | /** | ||
20 | * @defgroup oslib OS Library | ||
21 | * @details The OS Library is a set of RTOS extensions compatible with both | ||
22 | * the RT and NIL RTOSes. | ||
23 | */ | ||
24 | |||
25 | /** | ||
26 | * @defgroup oslib_info Version Numbers and Identification | ||
27 | * @ingroup oslib | ||
28 | */ | ||
29 | |||
30 | /** | ||
31 | * @defgroup oslib_synchronization Synchronization | ||
32 | * @details Synchronization services. | ||
33 | * @ingroup oslib | ||
34 | */ | ||
35 | |||
36 | /** | ||
37 | * @defgroup oslib_binary_semaphores Binary Semaphores | ||
38 | * @ingroup oslib_synchronization | ||
39 | */ | ||
40 | |||
41 | /** | ||
42 | * @defgroup oslib_mailboxes Mailboxes | ||
43 | * @ingroup oslib_synchronization | ||
44 | */ | ||
45 | |||
46 | /** | ||
47 | * @defgroup oslib_pipes Pipes | ||
48 | * @ingroup oslib_synchronization | ||
49 | */ | ||
50 | |||
51 | /** | ||
52 | * @defgroup oslib_delegates Delegate Threads | ||
53 | * @ingroup oslib_synchronization | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * @defgroup oslib_jobs_queues Jobs Queues | ||
58 | * @ingroup oslib_synchronization | ||
59 | */ | ||
60 | |||
61 | /** | ||
62 | * @defgroup oslib_memory Memory Management | ||
63 | * @details Memory Management services. | ||
64 | * @ingroup oslib | ||
65 | */ | ||
66 | |||
67 | /** | ||
68 | * @defgroup oslib_memcore Core Memory Manager | ||
69 | * @ingroup oslib_memory | ||
70 | */ | ||
71 | |||
72 | /** | ||
73 | * @defgroup oslib_memheaps Memory Heaps | ||
74 | * @ingroup oslib_memory | ||
75 | */ | ||
76 | |||
77 | /** | ||
78 | * @defgroup oslib_mempools Memory Pools | ||
79 | * @ingroup oslib_memory | ||
80 | */ | ||
81 | |||
82 | /** | ||
83 | * @defgroup oslib_complex Complex Services | ||
84 | * @ingroup oslib | ||
85 | */ | ||
86 | |||
87 | /** | ||
88 | * @defgroup oslib_objects_fifos Objects FIFOs | ||
89 | * @ingroup oslib_complex | ||
90 | */ | ||
91 | |||
92 | /** | ||
93 | * @defgroup oslib_objchaches Objects Caches | ||
94 | * @ingroup oslib_complex | ||
95 | */ | ||
96 | |||
97 | /** | ||
98 | * @defgroup oslib_objects_factory Dynamic Objects Factory | ||
99 | * @ingroup oslib_complex | ||
100 | */ | ||
diff --git a/lib/chibios/os/oslib/include/chbsem.h b/lib/chibios/os/oslib/include/chbsem.h new file mode 100644 index 000000000..7969d4fd0 --- /dev/null +++ b/lib/chibios/os/oslib/include/chbsem.h | |||
@@ -0,0 +1,311 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chbsem.h | ||
22 | * @brief Binary semaphores structures and macros. | ||
23 | * @details Binary semaphores related APIs and services. | ||
24 | * <h2>Operation mode</h2> | ||
25 | * Binary semaphores are implemented as a set of inline functions | ||
26 | * that use the existing counting semaphores primitives. The | ||
27 | * difference between counting and binary semaphores is that the | ||
28 | * counter of binary semaphores is not allowed to grow above the | ||
29 | * value 1. Repeated signal operation are ignored. A binary | ||
30 | * semaphore can thus have only two defined states: | ||
31 | * - <b>Taken</b>, when its counter has a value of zero or lower | ||
32 | * than zero. A negative number represent the number of threads | ||
33 | * queued on the binary semaphore. | ||
34 | * - <b>Not taken</b>, when its counter has a value of one. | ||
35 | * . | ||
36 | * Binary semaphores are different from mutexes because there is no | ||
37 | * concept of ownership, a binary semaphore can be taken by a | ||
38 | * thread and signaled by another thread or an interrupt handler, | ||
39 | * mutexes can only be taken and released by the same thread. Another | ||
40 | * difference is that binary semaphores, unlike mutexes, do not | ||
41 | * implement the priority inheritance protocol.<br> | ||
42 | * In order to use the binary semaphores APIs the | ||
43 | * @p CH_CFG_USE_SEMAPHORES option must be enabled in @p chconf.h. | ||
44 | * | ||
45 | * @addtogroup oslib_binary_semaphores | ||
46 | * @{ | ||
47 | */ | ||
48 | |||
49 | #ifndef CHBSEM_H | ||
50 | #define CHBSEM_H | ||
51 | |||
52 | #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) | ||
53 | |||
54 | /*===========================================================================*/ | ||
55 | /* Module constants. */ | ||
56 | /*===========================================================================*/ | ||
57 | |||
58 | /*===========================================================================*/ | ||
59 | /* Module pre-compile time settings. */ | ||
60 | /*===========================================================================*/ | ||
61 | |||
62 | /*===========================================================================*/ | ||
63 | /* Derived constants and error checks. */ | ||
64 | /*===========================================================================*/ | ||
65 | |||
66 | /*===========================================================================*/ | ||
67 | /* Module data structures and types. */ | ||
68 | /*===========================================================================*/ | ||
69 | |||
70 | /** | ||
71 | * @extends semaphore_t | ||
72 | * | ||
73 | * @brief Binary semaphore type. | ||
74 | */ | ||
75 | typedef struct ch_binary_semaphore { | ||
76 | semaphore_t sem; | ||
77 | } binary_semaphore_t; | ||
78 | |||
79 | /*===========================================================================*/ | ||
80 | /* Module macros. */ | ||
81 | /*===========================================================================*/ | ||
82 | |||
83 | /** | ||
84 | * @brief Data part of a static semaphore initializer. | ||
85 | * @details This macro should be used when statically initializing a semaphore | ||
86 | * that is part of a bigger structure. | ||
87 | * | ||
88 | * @param[in] name the name of the semaphore variable | ||
89 | * @param[in] taken the semaphore initial state | ||
90 | */ | ||
91 | #define _BSEMAPHORE_DATA(name, taken) \ | ||
92 | {_SEMAPHORE_DATA(name.sem, ((taken) ? 0 : 1))} | ||
93 | |||
94 | /** | ||
95 | * @brief Static semaphore initializer. | ||
96 | * @details Statically initialized semaphores require no explicit | ||
97 | * initialization using @p chBSemInit(). | ||
98 | * | ||
99 | * @param[in] name the name of the semaphore variable | ||
100 | * @param[in] taken the semaphore initial state | ||
101 | */ | ||
102 | #define BSEMAPHORE_DECL(name, taken) \ | ||
103 | binary_semaphore_t name = _BSEMAPHORE_DATA(name, taken) | ||
104 | |||
105 | /*===========================================================================*/ | ||
106 | /* External declarations. */ | ||
107 | /*===========================================================================*/ | ||
108 | |||
109 | /*===========================================================================*/ | ||
110 | /* Module inline functions. */ | ||
111 | /*===========================================================================*/ | ||
112 | |||
113 | /** | ||
114 | * @brief Initializes a binary semaphore. | ||
115 | * | ||
116 | * @param[out] bsp pointer to a @p binary_semaphore_t structure | ||
117 | * @param[in] taken initial state of the binary semaphore: | ||
118 | * - @a false, the initial state is not taken. | ||
119 | * - @a true, the initial state is taken. | ||
120 | * . | ||
121 | * | ||
122 | * @init | ||
123 | */ | ||
124 | static inline void chBSemObjectInit(binary_semaphore_t *bsp, bool taken) { | ||
125 | |||
126 | chSemObjectInit(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * @brief Wait operation on the binary semaphore. | ||
131 | * | ||
132 | * @param[in] bsp pointer to a @p binary_semaphore_t structure | ||
133 | * @return A message specifying how the invoking thread has been | ||
134 | * released from the semaphore. | ||
135 | * @retval MSG_OK if the binary semaphore has been successfully taken. | ||
136 | * @retval MSG_RESET if the binary semaphore has been reset using | ||
137 | * @p bsemReset(). | ||
138 | * | ||
139 | * @api | ||
140 | */ | ||
141 | static inline msg_t chBSemWait(binary_semaphore_t *bsp) { | ||
142 | |||
143 | return chSemWait(&bsp->sem); | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * @brief Wait operation on the binary semaphore. | ||
148 | * | ||
149 | * @param[in] bsp pointer to a @p binary_semaphore_t structure | ||
150 | * @return A message specifying how the invoking thread has been | ||
151 | * released from the semaphore. | ||
152 | * @retval MSG_OK if the binary semaphore has been successfully taken. | ||
153 | * @retval MSG_RESET if the binary semaphore has been reset using | ||
154 | * @p bsemReset(). | ||
155 | * | ||
156 | * @sclass | ||
157 | */ | ||
158 | static inline msg_t chBSemWaitS(binary_semaphore_t *bsp) { | ||
159 | |||
160 | chDbgCheckClassS(); | ||
161 | |||
162 | return chSemWaitS(&bsp->sem); | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * @brief Wait operation on the binary semaphore. | ||
167 | * | ||
168 | * @param[in] bsp pointer to a @p binary_semaphore_t structure | ||
169 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
170 | * the following special values are allowed: | ||
171 | * - @a TIME_IMMEDIATE immediate timeout. | ||
172 | * - @a TIME_INFINITE no timeout. | ||
173 | * . | ||
174 | * @return A message specifying how the invoking thread has been | ||
175 | * released from the semaphore. | ||
176 | * @retval MSG_OK if the binary semaphore has been successfully taken. | ||
177 | * @retval MSG_RESET if the binary semaphore has been reset using | ||
178 | * @p bsemReset(). | ||
179 | * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset | ||
180 | * within the specified timeout. | ||
181 | * | ||
182 | * @sclass | ||
183 | */ | ||
184 | static inline msg_t chBSemWaitTimeoutS(binary_semaphore_t *bsp, | ||
185 | sysinterval_t timeout) { | ||
186 | |||
187 | chDbgCheckClassS(); | ||
188 | |||
189 | return chSemWaitTimeoutS(&bsp->sem, timeout); | ||
190 | } | ||
191 | |||
192 | /** | ||
193 | * @brief Wait operation on the binary semaphore. | ||
194 | * | ||
195 | * @param[in] bsp pointer to a @p binary_semaphore_t structure | ||
196 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
197 | * the following special values are allowed: | ||
198 | * - @a TIME_IMMEDIATE immediate timeout. | ||
199 | * - @a TIME_INFINITE no timeout. | ||
200 | * . | ||
201 | * @return A message specifying how the invoking thread has been | ||
202 | * released from the semaphore. | ||
203 | * @retval MSG_OK if the binary semaphore has been successfully taken. | ||
204 | * @retval MSG_RESET if the binary semaphore has been reset using | ||
205 | * @p bsemReset(). | ||
206 | * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset | ||
207 | * within the specified timeout. | ||
208 | * | ||
209 | * @api | ||
210 | */ | ||
211 | static inline msg_t chBSemWaitTimeout(binary_semaphore_t *bsp, | ||
212 | sysinterval_t timeout) { | ||
213 | |||
214 | return chSemWaitTimeout(&bsp->sem, timeout); | ||
215 | } | ||
216 | |||
217 | /** | ||
218 | * @brief Reset operation on the binary semaphore. | ||
219 | * @note The released threads can recognize they were waked up by a reset | ||
220 | * rather than a signal because the @p bsemWait() will return | ||
221 | * @p MSG_RESET instead of @p MSG_OK. | ||
222 | * @note This function does not reschedule. | ||
223 | * | ||
224 | * @param[in] bsp pointer to a @p binary_semaphore_t structure | ||
225 | * @param[in] taken new state of the binary semaphore | ||
226 | * - @a false, the new state is not taken. | ||
227 | * - @a true, the new state is taken. | ||
228 | * . | ||
229 | * | ||
230 | * @iclass | ||
231 | */ | ||
232 | static inline void chBSemResetI(binary_semaphore_t *bsp, bool taken) { | ||
233 | |||
234 | chDbgCheckClassI(); | ||
235 | |||
236 | chSemResetI(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); | ||
237 | } | ||
238 | |||
239 | /** | ||
240 | * @brief Reset operation on the binary semaphore. | ||
241 | * @note The released threads can recognize they were waked up by a reset | ||
242 | * rather than a signal because the @p bsemWait() will return | ||
243 | * @p MSG_RESET instead of @p MSG_OK. | ||
244 | * | ||
245 | * @param[in] bsp pointer to a @p binary_semaphore_t structure | ||
246 | * @param[in] taken new state of the binary semaphore | ||
247 | * - @a false, the new state is not taken. | ||
248 | * - @a true, the new state is taken. | ||
249 | * . | ||
250 | * | ||
251 | * @api | ||
252 | */ | ||
253 | static inline void chBSemReset(binary_semaphore_t *bsp, bool taken) { | ||
254 | |||
255 | chSemReset(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * @brief Performs a signal operation on a binary semaphore. | ||
260 | * @note This function does not reschedule. | ||
261 | * | ||
262 | * @param[in] bsp pointer to a @p binary_semaphore_t structure | ||
263 | * | ||
264 | * @iclass | ||
265 | */ | ||
266 | static inline void chBSemSignalI(binary_semaphore_t *bsp) { | ||
267 | |||
268 | chDbgCheckClassI(); | ||
269 | |||
270 | if (bsp->sem.cnt < (cnt_t)1) { | ||
271 | chSemSignalI(&bsp->sem); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * @brief Performs a signal operation on a binary semaphore. | ||
277 | * | ||
278 | * @param[in] bsp pointer to a @p binary_semaphore_t structure | ||
279 | * | ||
280 | * @api | ||
281 | */ | ||
282 | static inline void chBSemSignal(binary_semaphore_t *bsp) { | ||
283 | |||
284 | chSysLock(); | ||
285 | chBSemSignalI(bsp); | ||
286 | chSchRescheduleS(); | ||
287 | chSysUnlock(); | ||
288 | } | ||
289 | |||
290 | /** | ||
291 | * @brief Returns the binary semaphore current state. | ||
292 | * | ||
293 | * @param[in] bsp pointer to a @p binary_semaphore_t structure | ||
294 | * @return The binary semaphore current state. | ||
295 | * @retval false if the binary semaphore is not taken. | ||
296 | * @retval true if the binary semaphore is taken. | ||
297 | * | ||
298 | * @iclass | ||
299 | */ | ||
300 | static inline bool chBSemGetStateI(const binary_semaphore_t *bsp) { | ||
301 | |||
302 | chDbgCheckClassI(); | ||
303 | |||
304 | return (bsp->sem.cnt > (cnt_t)0) ? false : true; | ||
305 | } | ||
306 | |||
307 | #endif /* CH_CFG_USE_SEMAPHORES == TRUE */ | ||
308 | |||
309 | #endif /* CHBSEM_H */ | ||
310 | |||
311 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chdelegates.h b/lib/chibios/os/oslib/include/chdelegates.h new file mode 100644 index 000000000..b5b62f991 --- /dev/null +++ b/lib/chibios/os/oslib/include/chdelegates.h | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chdelegates.h | ||
22 | * @brief Delegate threads macros and structures. | ||
23 | * | ||
24 | * @addtogroup oslib_delegates | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHDELEGATES_H | ||
29 | #define CHDELEGATES_H | ||
30 | |||
31 | #if (CH_CFG_USE_DELEGATES == TRUE) || defined(__DOXYGEN__) | ||
32 | |||
33 | /*lint -save -e829 [17.1] Required by design.*/ | ||
34 | #include <stdarg.h> | ||
35 | /*lint -restore*/ | ||
36 | |||
37 | /*===========================================================================*/ | ||
38 | /* Module constants. */ | ||
39 | /*===========================================================================*/ | ||
40 | |||
41 | /*===========================================================================*/ | ||
42 | /* Module pre-compile time settings. */ | ||
43 | /*===========================================================================*/ | ||
44 | |||
45 | /*===========================================================================*/ | ||
46 | /* Derived constants and error checks. */ | ||
47 | /*===========================================================================*/ | ||
48 | |||
49 | #if CH_CFG_USE_MESSAGES == FALSE | ||
50 | #error "CH_CFG_USE_DELEGATES requires CH_CFG_USE_MESSAGES" | ||
51 | #endif | ||
52 | |||
53 | /*===========================================================================*/ | ||
54 | /* Module data structures and types. */ | ||
55 | /*===========================================================================*/ | ||
56 | |||
57 | /** | ||
58 | * @brief Type of a delegate veneer function. | ||
59 | */ | ||
60 | typedef msg_t (*delegate_veneer_t)(va_list *argsp); | ||
61 | |||
62 | /** | ||
63 | * @brief Type of a delegate function with no parameters. | ||
64 | */ | ||
65 | typedef msg_t (*delegate_fn0_t)(void); | ||
66 | |||
67 | /** | ||
68 | * @brief Type of a delegate function with one parameter. | ||
69 | */ | ||
70 | typedef msg_t (*delegate_fn1_t)(msg_t p1); | ||
71 | |||
72 | /** | ||
73 | * @brief Type of a delegate function with two parameters. | ||
74 | */ | ||
75 | typedef msg_t (*delegate_fn2_t)(msg_t p1, msg_t p2); | ||
76 | |||
77 | /** | ||
78 | * @brief Type of a delegate function with three parameters. | ||
79 | */ | ||
80 | typedef msg_t (*delegate_fn3_t)(msg_t p1, msg_t p2, msg_t p3); | ||
81 | |||
82 | /** | ||
83 | * @brief Type of a delegate function with four parameters. | ||
84 | */ | ||
85 | typedef msg_t (*delegate_fn4_t)(msg_t p1, msg_t p2, msg_t p3, msg_t p4); | ||
86 | |||
87 | /*===========================================================================*/ | ||
88 | /* Module macros. */ | ||
89 | /*===========================================================================*/ | ||
90 | |||
91 | /*===========================================================================*/ | ||
92 | /* External declarations. */ | ||
93 | /*===========================================================================*/ | ||
94 | |||
95 | #ifdef __cplusplus | ||
96 | extern "C" { | ||
97 | #endif | ||
98 | msg_t __ch_delegate_fn0(va_list *argsp); | ||
99 | msg_t __ch_delegate_fn1(va_list *argsp); | ||
100 | msg_t __ch_delegate_fn2(va_list *argsp); | ||
101 | msg_t __ch_delegate_fn3(va_list *argsp); | ||
102 | msg_t __ch_delegate_fn4(va_list *argsp); | ||
103 | void chDelegateDispatch(void); | ||
104 | msg_t chDelegateDispatchTimeout(sysinterval_t timeout); | ||
105 | msg_t chDelegateCallVeneer(thread_t *tp, delegate_veneer_t veneer, ...); | ||
106 | #ifdef __cplusplus | ||
107 | } | ||
108 | #endif | ||
109 | |||
110 | /*===========================================================================*/ | ||
111 | /* Module inline functions. */ | ||
112 | /*===========================================================================*/ | ||
113 | |||
114 | /** | ||
115 | * @brief Direct call to a function with no parameters. | ||
116 | * @note The return value is assumed to be not larger than a data | ||
117 | * pointer type. If you need a portable function then use | ||
118 | * @p chDelegateCallVeneer() instead. | ||
119 | * | ||
120 | * @param[in] tp pointer to the delegate thread | ||
121 | * @param[in] func pointer to the function to be called | ||
122 | * @return The function return value as a @p msg_t. | ||
123 | */ | ||
124 | static inline msg_t chDelegateCallDirect0(thread_t *tp, delegate_fn0_t func) { | ||
125 | |||
126 | return chDelegateCallVeneer(tp, __ch_delegate_fn0, func); | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * @brief Direct call to a function with one parameter. | ||
131 | * @note The return value and parameters are assumed to be not larger | ||
132 | * than a data pointer type. If you need a portable function then use | ||
133 | * @p chDelegateCallVeneer() instead. | ||
134 | * | ||
135 | * @param[in] tp pointer to the delegate thread | ||
136 | * @param[in] func pointer to the function to be called | ||
137 | * @param[in] p1 parameter 1 passed as a @p msg_t | ||
138 | * @return The function return value as a @p msg_t. | ||
139 | */ | ||
140 | static inline msg_t chDelegateCallDirect1(thread_t *tp, delegate_fn1_t func, | ||
141 | msg_t p1) { | ||
142 | |||
143 | return chDelegateCallVeneer(tp, __ch_delegate_fn1, func, p1); | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * @brief Direct call to a function with two parameters. | ||
148 | * @note The return value and parameters are assumed to be not larger | ||
149 | * than a data pointer type. If you need a portable function then use | ||
150 | * @p chDelegateCallVeneer() instead. | ||
151 | * | ||
152 | * @param[in] tp pointer to the delegate thread | ||
153 | * @param[in] func pointer to the function to be called | ||
154 | * @param[in] p1 parameter 1 passed as a @p msg_t | ||
155 | * @param[in] p2 parameter 2 passed as a @p msg_t | ||
156 | * @return The function return value as a @p msg_t. | ||
157 | */ | ||
158 | static inline msg_t chDelegateCallDirect2(thread_t *tp, delegate_fn2_t func, | ||
159 | msg_t p1, msg_t p2) { | ||
160 | |||
161 | return chDelegateCallVeneer(tp, __ch_delegate_fn2, func, p1, p2); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * @brief Direct call to a function with three parameters. | ||
166 | * @note The return value and parameters are assumed to be not larger | ||
167 | * than a data pointer type. If you need a portable function then use | ||
168 | * @p chDelegateCallVeneer() instead. | ||
169 | * | ||
170 | * @param[in] tp pointer to the delegate thread | ||
171 | * @param[in] func pointer to the function to be called | ||
172 | * @param[in] p1 parameter 1 passed as a @p msg_t | ||
173 | * @param[in] p2 parameter 2 passed as a @p msg_t | ||
174 | * @param[in] p3 parameter 3 passed as a @p msg_t | ||
175 | * @return The function return value as a @p msg_t. | ||
176 | */ | ||
177 | static inline msg_t chDelegateCallDirect3(thread_t *tp, delegate_fn3_t func, | ||
178 | msg_t p1, msg_t p2, msg_t p3) { | ||
179 | |||
180 | return chDelegateCallVeneer(tp, __ch_delegate_fn3, func, p1, p2, p3); | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * @brief Direct call to a function with four parameters. | ||
185 | * @note The return value and parameters are assumed to be not larger | ||
186 | * than a data pointer type. If you need a portable function then use | ||
187 | * @p chDelegateCallVeneer() instead. | ||
188 | * | ||
189 | * @param[in] tp pointer to the delegate thread | ||
190 | * @param[in] func pointer to the function to be called | ||
191 | * @param[in] p1 parameter 1 passed as a @p msg_t | ||
192 | * @param[in] p2 parameter 2 passed as a @p msg_t | ||
193 | * @param[in] p3 parameter 3 passed as a @p msg_t | ||
194 | * @param[in] p4 parameter 4 passed as a @p msg_t | ||
195 | * @return The function return value as a @p msg_t. | ||
196 | */ | ||
197 | static inline msg_t chDelegateCallDirect4(thread_t *tp, delegate_fn4_t func, | ||
198 | msg_t p1, msg_t p2, msg_t p3, | ||
199 | msg_t p4) { | ||
200 | |||
201 | return chDelegateCallVeneer(tp, __ch_delegate_fn4, func, p1, p2, p3, p4); | ||
202 | } | ||
203 | |||
204 | #endif /* CH_CFG_USE_DELEGATES == TRUE */ | ||
205 | |||
206 | #endif /* CHDELEGATES_H */ | ||
207 | |||
208 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chfactory.h b/lib/chibios/os/oslib/include/chfactory.h new file mode 100644 index 000000000..c751c6fd1 --- /dev/null +++ b/lib/chibios/os/oslib/include/chfactory.h | |||
@@ -0,0 +1,523 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chfactory.h | ||
22 | * @brief ChibiOS objects factory structures and macros. | ||
23 | * | ||
24 | * @addtogroup oslib_objects_factory | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHFACTORY_H | ||
29 | #define CHFACTORY_H | ||
30 | |||
31 | #if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__) | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Module constants. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /*===========================================================================*/ | ||
38 | /* Module pre-compile time settings. */ | ||
39 | /*===========================================================================*/ | ||
40 | |||
41 | /** | ||
42 | * @brief Maximum length for object names. | ||
43 | * @details If the specified length is zero then the name is stored by | ||
44 | * pointer but this could have unintended side effects. | ||
45 | */ | ||
46 | #if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) || defined(__DOXYGEN__) | ||
47 | #define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 | ||
48 | #endif | ||
49 | |||
50 | /** | ||
51 | * @brief Enables the registry of generic objects. | ||
52 | */ | ||
53 | #if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) || defined(__DOXYGEN__) | ||
54 | #define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE | ||
55 | #endif | ||
56 | |||
57 | /** | ||
58 | * @brief Enables factory for generic buffers. | ||
59 | */ | ||
60 | #if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) || defined(__DOXYGEN__) | ||
61 | #define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE | ||
62 | #endif | ||
63 | |||
64 | /** | ||
65 | * @brief Enables factory for semaphores. | ||
66 | */ | ||
67 | #if !defined(CH_CFG_FACTORY_SEMAPHORES) || defined(__DOXYGEN__) | ||
68 | #define CH_CFG_FACTORY_SEMAPHORES TRUE | ||
69 | #endif | ||
70 | |||
71 | /** | ||
72 | * @brief Enables factory for mailboxes. | ||
73 | */ | ||
74 | #if !defined(CH_CFG_FACTORY_MAILBOXES) || defined(__DOXYGEN__) | ||
75 | #define CH_CFG_FACTORY_MAILBOXES TRUE | ||
76 | #endif | ||
77 | |||
78 | /** | ||
79 | * @brief Enables factory for objects FIFOs. | ||
80 | */ | ||
81 | #if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__) | ||
82 | #define CH_CFG_FACTORY_OBJ_FIFOS TRUE | ||
83 | #endif | ||
84 | |||
85 | /** | ||
86 | * @brief Enables factory for objects FIFOs. | ||
87 | */ | ||
88 | #if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__) | ||
89 | #define CH_CFG_FACTORY_OBJ_FIFOS TRUE | ||
90 | #endif | ||
91 | |||
92 | /** | ||
93 | * @brief Enables factory for Pipes. | ||
94 | */ | ||
95 | #if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) | ||
96 | #define CH_CFG_FACTORY_PIPES TRUE | ||
97 | #endif | ||
98 | |||
99 | /*===========================================================================*/ | ||
100 | /* Derived constants and error checks. */ | ||
101 | /*===========================================================================*/ | ||
102 | |||
103 | #if (CH_CFG_FACTORY_SEMAPHORES == TRUE) && (CH_CFG_USE_SEMAPHORES == FALSE) | ||
104 | /*lint -save -e767 [20.5] Valid because the #undef.*/ | ||
105 | #undef CH_CFG_FACTORY_SEMAPHORES | ||
106 | #define CH_CFG_FACTORY_SEMAPHORES FALSE | ||
107 | /*lint restore*/ | ||
108 | #endif | ||
109 | |||
110 | #if (CH_CFG_FACTORY_MAILBOXES == TRUE) && (CH_CFG_USE_MAILBOXES == FALSE) | ||
111 | /*lint -save -e767 [20.5] Valid because the #undef.*/ | ||
112 | #undef CH_CFG_FACTORY_MAILBOXES | ||
113 | #define CH_CFG_FACTORY_MAILBOXES FALSE | ||
114 | /*lint restore*/ | ||
115 | #endif | ||
116 | |||
117 | #if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) && (CH_CFG_USE_OBJ_FIFOS == FALSE) | ||
118 | /*lint -save -e767 [20.5] Valid because the #undef.*/ | ||
119 | #undef CH_CFG_FACTORY_OBJ_FIFOS | ||
120 | #define CH_CFG_FACTORY_OBJ_FIFOS FALSE | ||
121 | /*lint restore*/ | ||
122 | #endif | ||
123 | |||
124 | #if (CH_CFG_FACTORY_PIPES == TRUE) && (CH_CFG_USE_PIPES == FALSE) | ||
125 | /*lint -save -e767 [20.5] Valid because the #undef.*/ | ||
126 | #undef CH_CFG_FACTORY_PIPES | ||
127 | #define CH_CFG_FACTORY_PIPES FALSE | ||
128 | /*lint restore*/ | ||
129 | #endif | ||
130 | |||
131 | #define CH_FACTORY_REQUIRES_POOLS \ | ||
132 | ((CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || \ | ||
133 | (CH_CFG_FACTORY_SEMAPHORES == TRUE)) | ||
134 | |||
135 | #define CH_FACTORY_REQUIRES_HEAP \ | ||
136 | ((CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || \ | ||
137 | (CH_CFG_FACTORY_MAILBOXES == TRUE) || \ | ||
138 | (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || \ | ||
139 | (CH_CFG_FACTORY_PIPES == TRUE)) | ||
140 | |||
141 | #if (CH_CFG_FACTORY_MAX_NAMES_LENGTH < 0) || \ | ||
142 | (CH_CFG_FACTORY_MAX_NAMES_LENGTH > 32) | ||
143 | #error "invalid CH_CFG_FACTORY_MAX_NAMES_LENGTH value" | ||
144 | #endif | ||
145 | |||
146 | #if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE) | ||
147 | #error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" | ||
148 | #endif | ||
149 | |||
150 | #if CH_CFG_USE_MEMCORE == FALSE | ||
151 | #error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MEMCORE" | ||
152 | #endif | ||
153 | |||
154 | #if CH_FACTORY_REQUIRES_POOLS && (CH_CFG_USE_MEMPOOLS == FALSE) | ||
155 | #error "CH_CFG_USE_MEMPOOLS is required" | ||
156 | #endif | ||
157 | |||
158 | #if CH_FACTORY_REQUIRES_HEAP && (CH_CFG_USE_HEAP == FALSE) | ||
159 | #error "CH_CFG_USE_HEAP is required" | ||
160 | #endif | ||
161 | |||
162 | /*===========================================================================*/ | ||
163 | /* Module data structures and types. */ | ||
164 | /*===========================================================================*/ | ||
165 | |||
166 | /** | ||
167 | * @brief Type of a dynamic object list element. | ||
168 | */ | ||
169 | typedef struct ch_dyn_element { | ||
170 | /** | ||
171 | * @brief Next dynamic object in the list. | ||
172 | */ | ||
173 | struct ch_dyn_element *next; | ||
174 | /** | ||
175 | * @brief Number of references to this object. | ||
176 | */ | ||
177 | ucnt_t refs; | ||
178 | #if (CH_CFG_FACTORY_MAX_NAMES_LENGTH > 0) || defined(__DOXYGEN__) | ||
179 | char name[CH_CFG_FACTORY_MAX_NAMES_LENGTH]; | ||
180 | #else | ||
181 | const char *name; | ||
182 | #endif | ||
183 | } dyn_element_t; | ||
184 | |||
185 | /** | ||
186 | * @brief Type of a dynamic object list. | ||
187 | */ | ||
188 | typedef struct ch_dyn_list { | ||
189 | dyn_element_t *next; | ||
190 | } dyn_list_t; | ||
191 | |||
192 | #if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) | ||
193 | /** | ||
194 | * @brief Type of a registered object. | ||
195 | */ | ||
196 | typedef struct ch_registered_static_object { | ||
197 | /** | ||
198 | * @brief List element of the registered object. | ||
199 | */ | ||
200 | dyn_element_t element; | ||
201 | /** | ||
202 | * @brief Pointer to the object. | ||
203 | * @note The type of the object is not stored in anyway. | ||
204 | */ | ||
205 | void *objp; | ||
206 | } registered_object_t; | ||
207 | #endif | ||
208 | |||
209 | #if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) | ||
210 | /** | ||
211 | * @brief Type of a dynamic buffer object. | ||
212 | */ | ||
213 | typedef struct ch_dyn_object { | ||
214 | /** | ||
215 | * @brief List element of the dynamic buffer object. | ||
216 | */ | ||
217 | dyn_element_t element; | ||
218 | } dyn_buffer_t; | ||
219 | #endif | ||
220 | |||
221 | #if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) | ||
222 | /** | ||
223 | * @brief Type of a dynamic semaphore. | ||
224 | */ | ||
225 | typedef struct ch_dyn_semaphore { | ||
226 | /** | ||
227 | * @brief List element of the dynamic semaphore. | ||
228 | */ | ||
229 | dyn_element_t element; | ||
230 | /** | ||
231 | * @brief The semaphore. | ||
232 | */ | ||
233 | semaphore_t sem; | ||
234 | } dyn_semaphore_t; | ||
235 | #endif | ||
236 | |||
237 | #if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) | ||
238 | /** | ||
239 | * @brief Type of a dynamic buffer object. | ||
240 | */ | ||
241 | typedef struct ch_dyn_mailbox { | ||
242 | /** | ||
243 | * @brief List element of the dynamic buffer object. | ||
244 | */ | ||
245 | dyn_element_t element; | ||
246 | /** | ||
247 | * @brief The mailbox. | ||
248 | */ | ||
249 | mailbox_t mbx; | ||
250 | } dyn_mailbox_t; | ||
251 | #endif | ||
252 | |||
253 | #if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) | ||
254 | /** | ||
255 | * @brief Type of a dynamic buffer object. | ||
256 | */ | ||
257 | typedef struct ch_dyn_objects_fifo { | ||
258 | /** | ||
259 | * @brief List element of the dynamic buffer object. | ||
260 | */ | ||
261 | dyn_element_t element; | ||
262 | /** | ||
263 | * @brief The objects FIFO. | ||
264 | */ | ||
265 | objects_fifo_t fifo; | ||
266 | } dyn_objects_fifo_t; | ||
267 | #endif | ||
268 | |||
269 | #if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) | ||
270 | /** | ||
271 | * @brief Type of a dynamic pipe object. | ||
272 | */ | ||
273 | typedef struct ch_dyn_pipe { | ||
274 | /** | ||
275 | * @brief List element of the dynamic pipe object. | ||
276 | */ | ||
277 | dyn_element_t element; | ||
278 | /** | ||
279 | * @brief The pipe. | ||
280 | */ | ||
281 | pipe_t pipe; | ||
282 | } dyn_pipe_t; | ||
283 | #endif | ||
284 | |||
285 | /** | ||
286 | * @brief Type of the factory main object. | ||
287 | */ | ||
288 | typedef struct ch_objects_factory { | ||
289 | /** | ||
290 | * @brief Factory access mutex or semaphore. | ||
291 | */ | ||
292 | #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) | ||
293 | mutex_t mtx; | ||
294 | #else | ||
295 | semaphore_t sem; | ||
296 | #endif | ||
297 | /** | ||
298 | * @brief List of the registered objects. | ||
299 | */ | ||
300 | dyn_list_t obj_list; | ||
301 | /** | ||
302 | * @brief Pool of the available registered objects. | ||
303 | */ | ||
304 | memory_pool_t obj_pool; | ||
305 | #if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) | ||
306 | /** | ||
307 | * @brief List of the allocated buffer objects. | ||
308 | */ | ||
309 | dyn_list_t buf_list; | ||
310 | #endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */ | ||
311 | #if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) | ||
312 | /** | ||
313 | * @brief List of the allocated semaphores. | ||
314 | */ | ||
315 | dyn_list_t sem_list; | ||
316 | /** | ||
317 | * @brief Pool of the available semaphores. | ||
318 | */ | ||
319 | memory_pool_t sem_pool; | ||
320 | #endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */ | ||
321 | #if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) | ||
322 | /** | ||
323 | * @brief List of the allocated buffer objects. | ||
324 | */ | ||
325 | dyn_list_t mbx_list; | ||
326 | #endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */ | ||
327 | #if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) | ||
328 | /** | ||
329 | * @brief List of the allocated "objects FIFO" objects. | ||
330 | */ | ||
331 | dyn_list_t fifo_list; | ||
332 | #endif /* CH_CFG_FACTORY_OBJ_FIFOS = TRUE */ | ||
333 | #if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) | ||
334 | /** | ||
335 | * @brief List of the allocated pipe objects. | ||
336 | */ | ||
337 | dyn_list_t pipe_list; | ||
338 | #endif /* CH_CFG_FACTORY_PIPES = TRUE */ | ||
339 | } objects_factory_t; | ||
340 | |||
341 | /*===========================================================================*/ | ||
342 | /* Module macros. */ | ||
343 | /*===========================================================================*/ | ||
344 | |||
345 | /*===========================================================================*/ | ||
346 | /* External declarations. */ | ||
347 | /*===========================================================================*/ | ||
348 | |||
349 | #if !defined(__DOXYGEN__) | ||
350 | extern objects_factory_t ch_factory; | ||
351 | #endif | ||
352 | |||
353 | #ifdef __cplusplus | ||
354 | extern "C" { | ||
355 | #endif | ||
356 | void _factory_init(void); | ||
357 | #if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) | ||
358 | registered_object_t *chFactoryRegisterObject(const char *name, | ||
359 | void *objp); | ||
360 | registered_object_t *chFactoryFindObject(const char *name); | ||
361 | registered_object_t *chFactoryFindObjectByPointer(void *objp); | ||
362 | void chFactoryReleaseObject(registered_object_t *rop); | ||
363 | #endif | ||
364 | #if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) | ||
365 | dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size); | ||
366 | dyn_buffer_t *chFactoryFindBuffer(const char *name); | ||
367 | void chFactoryReleaseBuffer(dyn_buffer_t *dbp); | ||
368 | #endif | ||
369 | #if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) | ||
370 | dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n); | ||
371 | dyn_semaphore_t *chFactoryFindSemaphore(const char *name); | ||
372 | void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp); | ||
373 | #endif | ||
374 | #if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) | ||
375 | dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n); | ||
376 | dyn_mailbox_t *chFactoryFindMailbox(const char *name); | ||
377 | void chFactoryReleaseMailbox(dyn_mailbox_t *dmp); | ||
378 | #endif | ||
379 | #if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) | ||
380 | dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name, | ||
381 | size_t objsize, | ||
382 | size_t objn, | ||
383 | unsigned objalign); | ||
384 | dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name); | ||
385 | void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp); | ||
386 | #endif | ||
387 | #if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) | ||
388 | dyn_pipe_t *chFactoryCreatePipe(const char *name, size_t size); | ||
389 | dyn_pipe_t *chFactoryFindPipe(const char *name); | ||
390 | void chFactoryReleasePipe(dyn_pipe_t *dpp); | ||
391 | #endif | ||
392 | #ifdef __cplusplus | ||
393 | } | ||
394 | #endif | ||
395 | |||
396 | /*===========================================================================*/ | ||
397 | /* Module inline functions. */ | ||
398 | /*===========================================================================*/ | ||
399 | |||
400 | /** | ||
401 | * @brief Duplicates an object reference. | ||
402 | * @note This function can be used on any kind of dynamic object. | ||
403 | * | ||
404 | * @param[in] dep pointer to the element field of the object | ||
405 | * @return The duplicated object reference. | ||
406 | * | ||
407 | * @api | ||
408 | */ | ||
409 | static inline dyn_element_t *chFactoryDuplicateReference(dyn_element_t *dep) { | ||
410 | |||
411 | dep->refs++; | ||
412 | |||
413 | return dep; | ||
414 | } | ||
415 | |||
416 | #if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) | ||
417 | /** | ||
418 | * @brief Returns the pointer to the inner registered object. | ||
419 | * | ||
420 | * @param[in] rop registered object reference | ||
421 | * @return The pointer to the registered object. | ||
422 | * | ||
423 | * @api | ||
424 | */ | ||
425 | static inline void *chFactoryGetObject(registered_object_t *rop) { | ||
426 | |||
427 | return rop->objp; | ||
428 | } | ||
429 | #endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */ | ||
430 | |||
431 | #if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) | ||
432 | /** | ||
433 | * @brief Returns the size of a generic dynamic buffer object. | ||
434 | * | ||
435 | * @param[in] dbp dynamic buffer object reference | ||
436 | * @return The size of the buffer object in bytes. | ||
437 | * | ||
438 | * @api | ||
439 | */ | ||
440 | static inline size_t chFactoryGetBufferSize(dyn_buffer_t *dbp) { | ||
441 | |||
442 | return chHeapGetSize(dbp) - sizeof (dyn_element_t); | ||
443 | } | ||
444 | |||
445 | /** | ||
446 | * @brief Returns the pointer to the inner buffer. | ||
447 | * | ||
448 | * @param[in] dbp dynamic buffer object reference | ||
449 | * @return The pointer to the dynamic buffer. | ||
450 | * | ||
451 | * @api | ||
452 | */ | ||
453 | static inline uint8_t *chFactoryGetBuffer(dyn_buffer_t *dbp) { | ||
454 | |||
455 | return (uint8_t *)(dbp + 1); | ||
456 | } | ||
457 | #endif /* CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE */ | ||
458 | |||
459 | #if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) | ||
460 | /** | ||
461 | * @brief Returns the pointer to the inner semaphore. | ||
462 | * | ||
463 | * @param[in] dsp dynamic semaphore object reference | ||
464 | * @return The pointer to the semaphore. | ||
465 | * | ||
466 | * @api | ||
467 | */ | ||
468 | static inline semaphore_t *chFactoryGetSemaphore(dyn_semaphore_t *dsp) { | ||
469 | |||
470 | return &dsp->sem; | ||
471 | } | ||
472 | #endif /* CH_CFG_FACTORY_SEMAPHORES == TRUE */ | ||
473 | |||
474 | #if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) | ||
475 | /** | ||
476 | * @brief Returns the pointer to the inner mailbox. | ||
477 | * | ||
478 | * @param[in] dmp dynamic mailbox object reference | ||
479 | * @return The pointer to the mailbox. | ||
480 | * | ||
481 | * @api | ||
482 | */ | ||
483 | static inline mailbox_t *chFactoryGetMailbox(dyn_mailbox_t *dmp) { | ||
484 | |||
485 | return &dmp->mbx; | ||
486 | } | ||
487 | #endif /* CH_CFG_FACTORY_MAILBOXES == TRUE */ | ||
488 | |||
489 | #if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) | ||
490 | /** | ||
491 | * @brief Returns the pointer to the inner objects FIFO. | ||
492 | * | ||
493 | * @param[in] dofp dynamic "objects FIFO" object reference | ||
494 | * @return The pointer to the objects FIFO. | ||
495 | * | ||
496 | * @api | ||
497 | */ | ||
498 | static inline objects_fifo_t *chFactoryGetObjectsFIFO(dyn_objects_fifo_t *dofp) { | ||
499 | |||
500 | return &dofp->fifo; | ||
501 | } | ||
502 | #endif /* CH_CFG_FACTORY_OBJ_FIFOS == TRUE */ | ||
503 | |||
504 | #if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) | ||
505 | /** | ||
506 | * @brief Returns the pointer to the inner pipe. | ||
507 | * | ||
508 | * @param[in] dpp dynamic pipe object reference | ||
509 | * @return The pointer to the pipe. | ||
510 | * | ||
511 | * @api | ||
512 | */ | ||
513 | static inline pipe_t *chFactoryGetPipe(dyn_pipe_t *dpp) { | ||
514 | |||
515 | return &dpp->pipe; | ||
516 | } | ||
517 | #endif /* CH_CFG_FACTORY_PIPES == TRUE */ | ||
518 | |||
519 | #endif /* CH_CFG_USE_FACTORY == TRUE */ | ||
520 | |||
521 | #endif /* CHFACTORY_H */ | ||
522 | |||
523 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chjobs.h b/lib/chibios/os/oslib/include/chjobs.h new file mode 100644 index 000000000..5eaa0e4ec --- /dev/null +++ b/lib/chibios/os/oslib/include/chjobs.h | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chjobs.h | ||
22 | * @brief Jobs Queues structures and macros. | ||
23 | * @details This module implements queues of generic jobs to be delegated | ||
24 | * asynchronously to a pool of dedicated threads. | ||
25 | * Operations defined for Jobs Queues | ||
26 | * - <b>Get</b>: An job object is taken from the pool of the | ||
27 | * available jobs. | ||
28 | * - <b>Post</b>: A job is posted to the queue, it will be | ||
29 | * returned to the pool after execution. | ||
30 | * . | ||
31 | * | ||
32 | * @addtogroup oslib_jobs_queues | ||
33 | * @{ | ||
34 | */ | ||
35 | |||
36 | #ifndef CHJOBS_H | ||
37 | #define CHJOBS_H | ||
38 | |||
39 | #if (CH_CFG_USE_JOBS == TRUE) || defined(__DOXYGEN__) | ||
40 | |||
41 | /*===========================================================================*/ | ||
42 | /* Module constants. */ | ||
43 | /*===========================================================================*/ | ||
44 | |||
45 | /** | ||
46 | * @brief Dispatcher return code in case of a @p JOB_NUL has been received. | ||
47 | */ | ||
48 | #define MSG_JOB_NULL ((msg_t)-2) | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Module pre-compile time settings. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | /*===========================================================================*/ | ||
55 | /* Derived constants and error checks. */ | ||
56 | /*===========================================================================*/ | ||
57 | |||
58 | #if CH_CFG_USE_MEMPOOLS == FALSE | ||
59 | #error "CH_CFG_USE_JOBS requires CH_CFG_USE_MEMPOOLS" | ||
60 | #endif | ||
61 | |||
62 | #if CH_CFG_USE_SEMAPHORES == FALSE | ||
63 | #error "CH_CFG_USE_JOBS requires CH_CFG_USE_SEMAPHORES" | ||
64 | #endif | ||
65 | |||
66 | #if CH_CFG_USE_MAILBOXES == FALSE | ||
67 | #error "CH_CFG_USE_JOBS requires CH_CFG_USE_MAILBOXES" | ||
68 | #endif | ||
69 | |||
70 | /*===========================================================================*/ | ||
71 | /* Module data structures and types. */ | ||
72 | /*===========================================================================*/ | ||
73 | |||
74 | /** | ||
75 | * @brief Type of a jobs queue. | ||
76 | */ | ||
77 | typedef struct ch_jobs_queue { | ||
78 | /** | ||
79 | * @brief Pool of the free jobs. | ||
80 | */ | ||
81 | guarded_memory_pool_t free; | ||
82 | /** | ||
83 | * @brief Mailbox of the sent jobs. | ||
84 | */ | ||
85 | mailbox_t mbx; | ||
86 | } jobs_queue_t; | ||
87 | |||
88 | /** | ||
89 | * @brief Type of a job function. | ||
90 | */ | ||
91 | typedef void (*job_function_t)(void *arg); | ||
92 | |||
93 | /** | ||
94 | * @brief Type of a job descriptor. | ||
95 | */ | ||
96 | typedef struct ch_job_descriptor { | ||
97 | /** | ||
98 | * @brief Job function. | ||
99 | */ | ||
100 | job_function_t jobfunc; | ||
101 | /** | ||
102 | * @brief Argument to be passed to the job function. | ||
103 | */ | ||
104 | void *jobarg; | ||
105 | } job_descriptor_t; | ||
106 | |||
107 | /*===========================================================================*/ | ||
108 | /* Module macros. */ | ||
109 | /*===========================================================================*/ | ||
110 | |||
111 | /*===========================================================================*/ | ||
112 | /* External declarations. */ | ||
113 | /*===========================================================================*/ | ||
114 | |||
115 | #ifdef __cplusplus | ||
116 | extern "C" { | ||
117 | #endif | ||
118 | |||
119 | #ifdef __cplusplus | ||
120 | } | ||
121 | #endif | ||
122 | |||
123 | /*===========================================================================*/ | ||
124 | /* Module inline functions. */ | ||
125 | /*===========================================================================*/ | ||
126 | |||
127 | /** | ||
128 | * @brief Initializes a jobs queue object. | ||
129 | * | ||
130 | * @param[out] jqp pointer to a @p jobs_queue_t structure | ||
131 | * @param[in] jobsn number of jobs available | ||
132 | * @param[in] jobsbuf pointer to the buffer of jobs, it must be able | ||
133 | * to hold @p jobsn @p job_descriptor_t structures | ||
134 | * @param[in] msgbuf pointer to the buffer of messages, it must be able | ||
135 | * to hold @p jobsn @p msg_t messages | ||
136 | * | ||
137 | * @init | ||
138 | */ | ||
139 | static inline void chJobObjectInit(jobs_queue_t *jqp, | ||
140 | size_t jobsn, | ||
141 | job_descriptor_t *jobsbuf, | ||
142 | msg_t *msgbuf) { | ||
143 | |||
144 | chDbgCheck((jobsn > 0U) && (jobsbuf != NULL) && (msgbuf != NULL)); | ||
145 | |||
146 | chGuardedPoolObjectInit(&jqp->free, sizeof (job_descriptor_t)); | ||
147 | chGuardedPoolLoadArray(&jqp->free, (void *)jobsbuf, jobsn); | ||
148 | chMBObjectInit(&jqp->mbx, msgbuf, jobsn); | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * @brief Allocates a free job object. | ||
153 | * | ||
154 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
155 | * @return The pointer to the allocated job object. | ||
156 | * | ||
157 | * @api | ||
158 | */ | ||
159 | static inline job_descriptor_t *chJobGet(jobs_queue_t *jqp) { | ||
160 | |||
161 | return (job_descriptor_t *)chGuardedPoolAllocTimeout(&jqp->free, TIME_INFINITE); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * @brief Allocates a free job object. | ||
166 | * | ||
167 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
168 | * @return The pointer to the allocated job object. | ||
169 | * @retval NULL if a job object is not immediately available. | ||
170 | * | ||
171 | * @iclass | ||
172 | */ | ||
173 | static inline job_descriptor_t *chJobGetI(jobs_queue_t *jqp) { | ||
174 | |||
175 | return (job_descriptor_t *)chGuardedPoolAllocI(&jqp->free); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * @brief Allocates a free job object. | ||
180 | * | ||
181 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
182 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
183 | * the following special values are allowed: | ||
184 | * - @a TIME_IMMEDIATE immediate timeout. | ||
185 | * - @a TIME_INFINITE no timeout. | ||
186 | * . | ||
187 | * @return The pointer to the allocated job object. | ||
188 | * @retval NULL if a job object is not available within the specified | ||
189 | * timeout. | ||
190 | * | ||
191 | * @sclass | ||
192 | */ | ||
193 | static inline job_descriptor_t *chJobGetTimeoutS(jobs_queue_t *jqp, | ||
194 | sysinterval_t timeout) { | ||
195 | |||
196 | return (job_descriptor_t *)chGuardedPoolAllocTimeoutS(&jqp->free, timeout); | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * @brief Allocates a free job object. | ||
201 | * | ||
202 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
203 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
204 | * the following special values are allowed: | ||
205 | * - @a TIME_IMMEDIATE immediate timeout. | ||
206 | * - @a TIME_INFINITE no timeout. | ||
207 | * . | ||
208 | * @return The pointer to the allocated job object. | ||
209 | * @retval NULL if a job object is not available within the specified | ||
210 | * timeout. | ||
211 | * | ||
212 | * @api | ||
213 | */ | ||
214 | static inline job_descriptor_t *chJobGetTimeout(jobs_queue_t *jqp, | ||
215 | sysinterval_t timeout) { | ||
216 | |||
217 | return (job_descriptor_t *)chGuardedPoolAllocTimeout(&jqp->free, timeout); | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * @brief Posts a job object. | ||
222 | * @note By design the object can be always immediately posted. | ||
223 | * | ||
224 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
225 | * @param[in] jp pointer to the job object to be posted | ||
226 | * | ||
227 | * @iclass | ||
228 | */ | ||
229 | static inline void chJobPostI(jobs_queue_t *jqp, job_descriptor_t *jp) { | ||
230 | msg_t msg; | ||
231 | |||
232 | msg = chMBPostI(&jqp->mbx, (msg_t)jp); | ||
233 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * @brief Posts a job object. | ||
238 | * @note By design the object can be always immediately posted. | ||
239 | * | ||
240 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
241 | * @param[in] jp pointer to the job object to be posted | ||
242 | * | ||
243 | * @sclass | ||
244 | */ | ||
245 | static inline void chJobPostS(jobs_queue_t *jqp, job_descriptor_t *jp) { | ||
246 | msg_t msg; | ||
247 | |||
248 | msg = chMBPostTimeoutS(&jqp->mbx, (msg_t)jp, TIME_IMMEDIATE); | ||
249 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
250 | } | ||
251 | |||
252 | /** | ||
253 | * @brief Posts a job object. | ||
254 | * @note By design the object can be always immediately posted. | ||
255 | * | ||
256 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
257 | * @param[in] jp pointer to the job object to be posted | ||
258 | * | ||
259 | * @api | ||
260 | */ | ||
261 | static inline void chJobPost(jobs_queue_t *jqp, job_descriptor_t *jp) { | ||
262 | msg_t msg; | ||
263 | |||
264 | msg = chMBPostTimeout(&jqp->mbx, (msg_t)jp, TIME_IMMEDIATE); | ||
265 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * @brief Posts an high priority job object. | ||
270 | * @note By design the object can be always immediately posted. | ||
271 | * | ||
272 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
273 | * @param[in] jp pointer to the job object to be posted | ||
274 | * | ||
275 | * @iclass | ||
276 | */ | ||
277 | static inline void chJobPostAheadI(jobs_queue_t *jqp, job_descriptor_t *jp) { | ||
278 | msg_t msg; | ||
279 | |||
280 | msg = chMBPostAheadI(&jqp->mbx, (msg_t)jp); | ||
281 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * @brief Posts an high priority job object. | ||
286 | * @note By design the object can be always immediately posted. | ||
287 | * | ||
288 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
289 | * @param[in] jp pointer to the job object to be posted | ||
290 | * | ||
291 | * @sclass | ||
292 | */ | ||
293 | static inline void chJobPostAheadS(jobs_queue_t *jqp, job_descriptor_t *jp) { | ||
294 | msg_t msg; | ||
295 | |||
296 | msg = chMBPostAheadTimeoutS(&jqp->mbx, (msg_t)jp, TIME_IMMEDIATE); | ||
297 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * @brief Posts an high priority job object. | ||
302 | * @note By design the object can be always immediately posted. | ||
303 | * | ||
304 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
305 | * @param[in] jp pointer to the job object to be posted | ||
306 | * | ||
307 | * @api | ||
308 | */ | ||
309 | static inline void chJobPostAhead(jobs_queue_t *jqp, job_descriptor_t *jp) { | ||
310 | msg_t msg; | ||
311 | |||
312 | msg = chMBPostAheadTimeout(&jqp->mbx, (msg_t)jp, TIME_IMMEDIATE); | ||
313 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * @brief Waits for a job then executes it. | ||
318 | * | ||
319 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
320 | * @return The function outcome. | ||
321 | * @retval MSG_OK if a job has been executed. | ||
322 | * @retval MSG_RESET if the internal mailbox has been reset. | ||
323 | * @retval MSG_JOB_NULL if a @p JOB_NULL has been received. | ||
324 | */ | ||
325 | static inline msg_t chJobDispatch(jobs_queue_t *jqp) { | ||
326 | msg_t msg, jmsg; | ||
327 | |||
328 | /* Waiting for a job.*/ | ||
329 | msg = chMBFetchTimeout(&jqp->mbx, &jmsg, TIME_INFINITE); | ||
330 | if (msg == MSG_OK) { | ||
331 | job_descriptor_t *jp = (job_descriptor_t *)jmsg; | ||
332 | |||
333 | chDbgAssert(jp != NULL, "is NULL"); | ||
334 | |||
335 | if (jp->jobfunc != NULL) { | ||
336 | |||
337 | /* Invoking the job function.*/ | ||
338 | jp->jobfunc(jp->jobarg); | ||
339 | |||
340 | /* Returning the job descriptor object.*/ | ||
341 | chGuardedPoolFree(&jqp->free, (void *)jp); | ||
342 | } | ||
343 | else { | ||
344 | msg = MSG_JOB_NULL; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | return msg; | ||
349 | } | ||
350 | |||
351 | /** | ||
352 | * @brief Waits for a job then executes it. | ||
353 | * | ||
354 | * @param[in] jqp pointer to a @p jobs_queue_t structure | ||
355 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
356 | * the following special values are allowed: | ||
357 | * - @a TIME_IMMEDIATE immediate timeout. | ||
358 | * - @a TIME_INFINITE no timeout. | ||
359 | * . | ||
360 | * @return The function outcome. | ||
361 | * @retval MSG_OK if a job has been executed. | ||
362 | * @retval MSG_TIMEOUT if a timeout occurred. | ||
363 | * @retval MSG_RESET if the internal mailbox has been reset. | ||
364 | * @retval MSG_JOB_NULL if a @p JOB_NULL has been received. | ||
365 | */ | ||
366 | static inline msg_t chJobDispatchTimeout(jobs_queue_t *jqp, | ||
367 | sysinterval_t timeout) { | ||
368 | msg_t msg, jmsg; | ||
369 | |||
370 | /* Waiting for a job or a timeout.*/ | ||
371 | msg = chMBFetchTimeout(&jqp->mbx, &jmsg, timeout); | ||
372 | if (msg == MSG_OK) { | ||
373 | job_descriptor_t *jp = (job_descriptor_t *)jmsg; | ||
374 | |||
375 | chDbgAssert(jp != NULL, "is NULL"); | ||
376 | |||
377 | if (jp->jobfunc != NULL) { | ||
378 | |||
379 | /* Invoking the job function.*/ | ||
380 | jp->jobfunc(jp->jobarg); | ||
381 | |||
382 | /* Returning the job descriptor object.*/ | ||
383 | chGuardedPoolFree(&jqp->free, (void *)jp); | ||
384 | } | ||
385 | else { | ||
386 | msg = MSG_JOB_NULL; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | return msg; | ||
391 | } | ||
392 | |||
393 | #endif /* CH_CFG_USE_JOBS == TRUE */ | ||
394 | |||
395 | #endif /* CHJOBS_H */ | ||
396 | |||
397 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chlib.h b/lib/chibios/os/oslib/include/chlib.h new file mode 100644 index 000000000..e8ad22f8e --- /dev/null +++ b/lib/chibios/os/oslib/include/chlib.h | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chlib.h | ||
22 | * @brief ChibiOS/LIB main include file. | ||
23 | * @details This header includes all the required library headers. This file | ||
24 | * is meant do be included by @p ch.h not directly by user. | ||
25 | * | ||
26 | * @addtogroup oslib_info | ||
27 | * @details OS Library related info. | ||
28 | * @{ | ||
29 | */ | ||
30 | |||
31 | #ifndef CHLIB_H | ||
32 | #define CHLIB_H | ||
33 | |||
34 | /*===========================================================================*/ | ||
35 | /* Module constants. */ | ||
36 | /*===========================================================================*/ | ||
37 | |||
38 | /** | ||
39 | * @brief ChibiOS/LIB identification macro. | ||
40 | */ | ||
41 | #define _CHIBIOS_OSLIB_ | ||
42 | |||
43 | /** | ||
44 | * @brief Stable release flag. | ||
45 | */ | ||
46 | #define CH_OSLIB_STABLE 1 | ||
47 | |||
48 | /** | ||
49 | * @name ChibiOS/LIB version identification | ||
50 | * @{ | ||
51 | */ | ||
52 | /** | ||
53 | * @brief OS Library version string. | ||
54 | */ | ||
55 | #define CH_OSLIB_VERSION "1.2.1" | ||
56 | |||
57 | /** | ||
58 | * @brief OS Library version major number. | ||
59 | */ | ||
60 | #define CH_OSLIB_MAJOR 1 | ||
61 | |||
62 | /** | ||
63 | * @brief OS Library version minor number. | ||
64 | */ | ||
65 | #define CH_OSLIB_MINOR 2 | ||
66 | |||
67 | /** | ||
68 | * @brief OS Library version patch number. | ||
69 | */ | ||
70 | #define CH_OSLIB_PATCH 1 | ||
71 | /** @} */ | ||
72 | |||
73 | /*===========================================================================*/ | ||
74 | /* Module pre-compile time settings. */ | ||
75 | /*===========================================================================*/ | ||
76 | |||
77 | /*===========================================================================*/ | ||
78 | /* Derived constants and error checks. */ | ||
79 | /*===========================================================================*/ | ||
80 | |||
81 | /* Host OS checks.*/ | ||
82 | #if !defined(_CHIBIOS_RT_) && !defined(_CHIBIOS_NIL_) | ||
83 | #error "OS check failed, must be included after ch.h" | ||
84 | #endif | ||
85 | |||
86 | /* Configuration file checks.*/ | ||
87 | #if !defined(CH_CFG_USE_MAILBOXES) | ||
88 | #error "CH_CFG_USE_MAILBOXES not defined in chconf.h" | ||
89 | #endif | ||
90 | |||
91 | #if !defined(CH_CFG_USE_MEMCORE) | ||
92 | #error "CH_CFG_USE_MEMCORE not defined in chconf.h" | ||
93 | #endif | ||
94 | |||
95 | #if !defined(CH_CFG_USE_HEAP) | ||
96 | #error "CH_CFG_USE_HEAP not defined in chconf.h" | ||
97 | #endif | ||
98 | |||
99 | #if !defined(CH_CFG_USE_MEMPOOLS) | ||
100 | #error "CH_CFG_USE_MEMPOOLS not defined in chconf.h" | ||
101 | #endif | ||
102 | |||
103 | #if !defined(CH_CFG_USE_OBJ_FIFOS) | ||
104 | #error "CH_CFG_USE_OBJ_FIFOS not defined in chconf.h" | ||
105 | #endif | ||
106 | |||
107 | #if !defined(CH_CFG_USE_PIPES) | ||
108 | #error "CH_CFG_USE_PIPES not defined in chconf.h" | ||
109 | #endif | ||
110 | |||
111 | #if !defined(CH_CFG_USE_OBJ_CACHES) | ||
112 | #error "CH_CFG_USE_OBJ_CACHES not defined in chconf.h" | ||
113 | #endif | ||
114 | |||
115 | #if !defined(CH_CFG_USE_DELEGATES) | ||
116 | #error "CH_CFG_USE_DELEGATES not defined in chconf.h" | ||
117 | #endif | ||
118 | |||
119 | #if !defined(CH_CFG_USE_JOBS) | ||
120 | #error "CH_CFG_USE_JOBS not defined in chconf.h" | ||
121 | #endif | ||
122 | |||
123 | /* Objects factory options checks.*/ | ||
124 | #if !defined(CH_CFG_USE_FACTORY) | ||
125 | #error "CH_CFG_USE_FACTORY not defined in chconf.h" | ||
126 | #endif | ||
127 | |||
128 | #if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) | ||
129 | #error "CH_CFG_FACTORY_MAX_NAMES_LENGTH not defined in chconf.h" | ||
130 | #endif | ||
131 | |||
132 | #if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) | ||
133 | #error "CH_CFG_FACTORY_OBJECTS_REGISTRY not defined in chconf.h" | ||
134 | #endif | ||
135 | |||
136 | #if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) | ||
137 | #error "CH_CFG_FACTORY_GENERIC_BUFFERS not defined in chconf.h" | ||
138 | #endif | ||
139 | |||
140 | #if !defined(CH_CFG_FACTORY_SEMAPHORES) | ||
141 | #error "CH_CFG_FACTORY_SEMAPHORES not defined in chconf.h" | ||
142 | #endif | ||
143 | |||
144 | #if !defined(CH_CFG_FACTORY_MAILBOXES) | ||
145 | #error "CH_CFG_FACTORY_MAILBOXES not defined in chconf.h" | ||
146 | #endif | ||
147 | |||
148 | #if !defined(CH_CFG_FACTORY_OBJ_FIFOS) | ||
149 | #error "CH_CFG_FACTORY_OBJ_FIFOS not defined in chconf.h" | ||
150 | #endif | ||
151 | |||
152 | /* License checks.*/ | ||
153 | #if !defined(CH_CUSTOMER_LIC_OSLIB) || !defined(CH_LICENSE_FEATURES) | ||
154 | #error "malformed chlicense.h" | ||
155 | #endif | ||
156 | |||
157 | #if (CH_LICENSE_FEATURES != CH_FEATURES_FULL) && \ | ||
158 | (CH_LICENSE_FEATURES != CH_FEATURES_INTERMEDIATE) && \ | ||
159 | (CH_LICENSE_FEATURES != CH_FEATURES_BASIC) | ||
160 | #error "invalid CH_LICENSE_FEATURES setting" | ||
161 | #endif | ||
162 | |||
163 | /* Restrictions in basic and intermediate modes.*/ | ||
164 | #if (CH_CUSTOMER_LIC_OSLIB == FALSE) || \ | ||
165 | (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || \ | ||
166 | (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) | ||
167 | |||
168 | /* Restricted subsystems.*/ | ||
169 | #undef CH_CFG_USE_FACTORY | ||
170 | |||
171 | #define CH_CFG_USE_FACTORY FALSE | ||
172 | |||
173 | #endif /* (CH_CUSTOMER_LIC_OSLIB == FALSE) || | ||
174 | (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || | ||
175 | (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */ | ||
176 | |||
177 | /* Restrictions in basic mode.*/ | ||
178 | #if (CH_CUSTOMER_LIC_OSLIB == FALSE) || \ | ||
179 | (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) | ||
180 | |||
181 | /* Restricted subsystems.*/ | ||
182 | #undef CH_CFG_USE_HEAP | ||
183 | #undef CH_CFG_USE_MEMPOOLS | ||
184 | #undef CH_CFG_USE_OBJ_FIFOS | ||
185 | #undef CH_CFG_USE_PIPES | ||
186 | #undef CH_CFG_USE_OBJ_CACHES | ||
187 | #undef CH_CFG_USE_DELEGATES | ||
188 | #undef CH_CFG_USE_JOBS | ||
189 | |||
190 | #define CH_CFG_USE_HEAP FALSE | ||
191 | #define CH_CFG_USE_MEMPOOLS FALSE | ||
192 | #define CH_CFG_USE_OBJ_FIFOS FALSE | ||
193 | #define CH_CFG_USE_PIPES FALSE | ||
194 | #define CH_CFG_USE_OBJ_CACHES FALSE | ||
195 | #define CH_CFG_USE_DELEGATES FALSE | ||
196 | #define CH_CFG_USE_JOBS FALSE | ||
197 | |||
198 | #endif /* (CH_CUSTOMER_LIC_OSLIB == FALSE) || | ||
199 | (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */ | ||
200 | |||
201 | /* Restrictions in unlicensed mode.*/ | ||
202 | #if (CH_CUSTOMER_LIC_OSLIB == FALSE) | ||
203 | |||
204 | /* Restricted subsystems.*/ | ||
205 | #undef CH_CFG_USE_MAILBOXES | ||
206 | |||
207 | #define CH_CFG_USE_MAILBOXES FALSE | ||
208 | |||
209 | #endif /* CH_CUSTOMER_LIC_OSLIB == FALSE */ | ||
210 | |||
211 | /*===========================================================================*/ | ||
212 | /* Module data structures and types. */ | ||
213 | /*===========================================================================*/ | ||
214 | |||
215 | /*===========================================================================*/ | ||
216 | /* Module macros. */ | ||
217 | /*===========================================================================*/ | ||
218 | |||
219 | /*===========================================================================*/ | ||
220 | /* External declarations. */ | ||
221 | /*===========================================================================*/ | ||
222 | |||
223 | /*===========================================================================*/ | ||
224 | /* Late inclusions. */ | ||
225 | /*===========================================================================*/ | ||
226 | |||
227 | /* OS Library headers.*/ | ||
228 | #include "chbsem.h" | ||
229 | #include "chmboxes.h" | ||
230 | #include "chmemcore.h" | ||
231 | #include "chmemheaps.h" | ||
232 | #include "chmempools.h" | ||
233 | #include "chobjfifos.h" | ||
234 | #include "chpipes.h" | ||
235 | #include "chobjcaches.h" | ||
236 | #include "chdelegates.h" | ||
237 | #include "chjobs.h" | ||
238 | #include "chfactory.h" | ||
239 | |||
240 | /*===========================================================================*/ | ||
241 | /* Module inline functions. */ | ||
242 | /*===========================================================================*/ | ||
243 | |||
244 | /** | ||
245 | * @brief Initialization of all library modules. | ||
246 | * | ||
247 | * @notapi | ||
248 | */ | ||
249 | static inline void _oslib_init(void) { | ||
250 | |||
251 | #if CH_CFG_USE_MEMCORE == TRUE | ||
252 | _core_init(); | ||
253 | #endif | ||
254 | #if CH_CFG_USE_HEAP == TRUE | ||
255 | _heap_init(); | ||
256 | #endif | ||
257 | #if CH_CFG_USE_FACTORY == TRUE | ||
258 | _factory_init(); | ||
259 | #endif | ||
260 | } | ||
261 | |||
262 | #endif /* CHLIB_H */ | ||
263 | |||
264 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chmboxes.h b/lib/chibios/os/oslib/include/chmboxes.h new file mode 100644 index 000000000..d925f219e --- /dev/null +++ b/lib/chibios/os/oslib/include/chmboxes.h | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chmboxes.h | ||
22 | * @brief Mailboxes macros and structures. | ||
23 | * | ||
24 | * @addtogroup oslib_mailboxes | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHMBOXES_H | ||
29 | #define CHMBOXES_H | ||
30 | |||
31 | #if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__) | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Module constants. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /*===========================================================================*/ | ||
38 | /* Module pre-compile time settings. */ | ||
39 | /*===========================================================================*/ | ||
40 | |||
41 | /*===========================================================================*/ | ||
42 | /* Derived constants and error checks. */ | ||
43 | /*===========================================================================*/ | ||
44 | |||
45 | /*===========================================================================*/ | ||
46 | /* Module data structures and types. */ | ||
47 | /*===========================================================================*/ | ||
48 | |||
49 | /** | ||
50 | * @brief Structure representing a mailbox object. | ||
51 | */ | ||
52 | typedef struct { | ||
53 | msg_t *buffer; /**< @brief Pointer to the mailbox | ||
54 | buffer. */ | ||
55 | msg_t *top; /**< @brief Pointer to the location | ||
56 | after the buffer. */ | ||
57 | msg_t *wrptr; /**< @brief Write pointer. */ | ||
58 | msg_t *rdptr; /**< @brief Read pointer. */ | ||
59 | size_t cnt; /**< @brief Messages in queue. */ | ||
60 | bool reset; /**< @brief True in reset state. */ | ||
61 | threads_queue_t qw; /**< @brief Queued writers. */ | ||
62 | threads_queue_t qr; /**< @brief Queued readers. */ | ||
63 | } mailbox_t; | ||
64 | |||
65 | /*===========================================================================*/ | ||
66 | /* Module macros. */ | ||
67 | /*===========================================================================*/ | ||
68 | |||
69 | /** | ||
70 | * @brief Data part of a static mailbox initializer. | ||
71 | * @details This macro should be used when statically initializing a | ||
72 | * mailbox that is part of a bigger structure. | ||
73 | * | ||
74 | * @param[in] name the name of the mailbox variable | ||
75 | * @param[in] buffer pointer to the mailbox buffer array of @p msg_t | ||
76 | * @param[in] size number of @p msg_t elements in the buffer array | ||
77 | */ | ||
78 | #define _MAILBOX_DATA(name, buffer, size) { \ | ||
79 | (msg_t *)(buffer), \ | ||
80 | (msg_t *)(buffer) + size, \ | ||
81 | (msg_t *)(buffer), \ | ||
82 | (msg_t *)(buffer), \ | ||
83 | (size_t)0, \ | ||
84 | false, \ | ||
85 | _THREADS_QUEUE_DATA(name.qw), \ | ||
86 | _THREADS_QUEUE_DATA(name.qr), \ | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * @brief Static mailbox initializer. | ||
91 | * @details Statically initialized mailboxes require no explicit | ||
92 | * initialization using @p chMBObjectInit(). | ||
93 | * | ||
94 | * @param[in] name the name of the mailbox variable | ||
95 | * @param[in] buffer pointer to the mailbox buffer array of @p msg_t | ||
96 | * @param[in] size number of @p msg_t elements in the buffer array | ||
97 | */ | ||
98 | #define MAILBOX_DECL(name, buffer, size) \ | ||
99 | mailbox_t name = _MAILBOX_DATA(name, buffer, size) | ||
100 | |||
101 | /*===========================================================================*/ | ||
102 | /* External declarations. */ | ||
103 | /*===========================================================================*/ | ||
104 | |||
105 | #ifdef __cplusplus | ||
106 | extern "C" { | ||
107 | #endif | ||
108 | void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n); | ||
109 | void chMBReset(mailbox_t *mbp); | ||
110 | void chMBResetI(mailbox_t *mbp); | ||
111 | msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); | ||
112 | msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); | ||
113 | msg_t chMBPostI(mailbox_t *mbp, msg_t msg); | ||
114 | msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); | ||
115 | msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); | ||
116 | msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg); | ||
117 | msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout); | ||
118 | msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout); | ||
119 | msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp); | ||
120 | #ifdef __cplusplus | ||
121 | } | ||
122 | #endif | ||
123 | |||
124 | /*===========================================================================*/ | ||
125 | /* Module inline functions. */ | ||
126 | /*===========================================================================*/ | ||
127 | |||
128 | /** | ||
129 | * @brief Returns the mailbox buffer size as number of messages. | ||
130 | * | ||
131 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
132 | * @return The size of the mailbox. | ||
133 | * | ||
134 | * @iclass | ||
135 | */ | ||
136 | static inline size_t chMBGetSizeI(const mailbox_t *mbp) { | ||
137 | |||
138 | /*lint -save -e9033 [10.8] Perfectly safe pointers | ||
139 | arithmetic.*/ | ||
140 | return (size_t)(mbp->top - mbp->buffer); | ||
141 | /*lint -restore*/ | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * @brief Returns the number of used message slots into a mailbox. | ||
146 | * | ||
147 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
148 | * @return The number of queued messages. | ||
149 | * | ||
150 | * @iclass | ||
151 | */ | ||
152 | static inline size_t chMBGetUsedCountI(const mailbox_t *mbp) { | ||
153 | |||
154 | chDbgCheckClassI(); | ||
155 | |||
156 | return mbp->cnt; | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * @brief Returns the number of free message slots into a mailbox. | ||
161 | * | ||
162 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
163 | * @return The number of empty message slots. | ||
164 | * | ||
165 | * @iclass | ||
166 | */ | ||
167 | static inline size_t chMBGetFreeCountI(const mailbox_t *mbp) { | ||
168 | |||
169 | chDbgCheckClassI(); | ||
170 | |||
171 | return chMBGetSizeI(mbp) - chMBGetUsedCountI(mbp); | ||
172 | } | ||
173 | |||
174 | /** | ||
175 | * @brief Returns the next message in the queue without removing it. | ||
176 | * @pre A message must be waiting in the queue for this function to work | ||
177 | * or it would return garbage. The correct way to use this macro is | ||
178 | * to use @p chMBGetUsedCountI() and then use this macro, all within | ||
179 | * a lock state. | ||
180 | * | ||
181 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
182 | * @return The next message in queue. | ||
183 | * | ||
184 | * @iclass | ||
185 | */ | ||
186 | static inline msg_t chMBPeekI(const mailbox_t *mbp) { | ||
187 | |||
188 | chDbgCheckClassI(); | ||
189 | |||
190 | return *mbp->rdptr; | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * @brief Terminates the reset state. | ||
195 | * | ||
196 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
197 | * | ||
198 | * @xclass | ||
199 | */ | ||
200 | static inline void chMBResumeX(mailbox_t *mbp) { | ||
201 | |||
202 | mbp->reset = false; | ||
203 | } | ||
204 | |||
205 | #endif /* CH_CFG_USE_MAILBOXES == TRUE */ | ||
206 | |||
207 | #endif /* CHMBOXES_H */ | ||
208 | |||
209 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chmemcore.h b/lib/chibios/os/oslib/include/chmemcore.h new file mode 100644 index 000000000..4004f70b7 --- /dev/null +++ b/lib/chibios/os/oslib/include/chmemcore.h | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chmemcore.h | ||
22 | * @brief Core memory manager macros and structures. | ||
23 | * | ||
24 | * @addtogroup oslib_memcore | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHMEMCORE_H | ||
29 | #define CHMEMCORE_H | ||
30 | |||
31 | #if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__) | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Module constants. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /*===========================================================================*/ | ||
38 | /* Module pre-compile time settings. */ | ||
39 | /*===========================================================================*/ | ||
40 | |||
41 | /** | ||
42 | * @brief Managed RAM size. | ||
43 | * @details Size of the RAM area to be managed by the OS. If set to zero | ||
44 | * then the whole available RAM is used. The core memory is made | ||
45 | * available to the heap allocator and/or can be used directly through | ||
46 | * the simplified core memory allocator. | ||
47 | * | ||
48 | * @note In order to let the OS manage the whole RAM the linker script must | ||
49 | * provide the @p __heap_base__ and @p __heap_end__ symbols. | ||
50 | * @note Requires @p CH_CFG_USE_MEMCORE. | ||
51 | */ | ||
52 | #if !defined(CH_CFG_MEMCORE_SIZE) || defined(__DOXYGEN__) | ||
53 | #define CH_CFG_MEMCORE_SIZE 0 | ||
54 | #endif | ||
55 | |||
56 | /*===========================================================================*/ | ||
57 | /* Derived constants and error checks. */ | ||
58 | /*===========================================================================*/ | ||
59 | |||
60 | #if CH_CFG_MEMCORE_SIZE < 0 | ||
61 | #error "invalid CH_CFG_MEMCORE_SIZE value specified" | ||
62 | #endif | ||
63 | |||
64 | /*===========================================================================*/ | ||
65 | /* Module data structures and types. */ | ||
66 | /*===========================================================================*/ | ||
67 | |||
68 | /** | ||
69 | * @brief Memory get function. | ||
70 | */ | ||
71 | typedef void *(*memgetfunc_t)(size_t size, unsigned align); | ||
72 | |||
73 | /** | ||
74 | * @brief Enhanced memory get function. | ||
75 | */ | ||
76 | typedef void *(*memgetfunc2_t)(size_t size, unsigned align, size_t offset); | ||
77 | |||
78 | /** | ||
79 | * @brief Type of memory core object. | ||
80 | */ | ||
81 | typedef struct { | ||
82 | /** | ||
83 | * @brief Next free address. | ||
84 | */ | ||
85 | uint8_t *basemem; | ||
86 | /** | ||
87 | * @brief Final address. | ||
88 | */ | ||
89 | uint8_t *topmem; | ||
90 | } memcore_t; | ||
91 | |||
92 | /*===========================================================================*/ | ||
93 | /* Module macros. */ | ||
94 | /*===========================================================================*/ | ||
95 | |||
96 | /** | ||
97 | * @brief Allocates a memory block. | ||
98 | * @note This is a generic form with unspecified allocation position. | ||
99 | * | ||
100 | * @iclass | ||
101 | */ | ||
102 | #define chCoreAllocAlignedWithOffsetI chCoreAllocFromTopI | ||
103 | |||
104 | /** | ||
105 | * @brief Allocates a memory block. | ||
106 | * @note This is a generic form with unspecified allocation position. | ||
107 | * | ||
108 | * @api | ||
109 | */ | ||
110 | #define chCoreAllocAlignedWithOffset chCoreAllocFromTop | ||
111 | |||
112 | /*===========================================================================*/ | ||
113 | /* External declarations. */ | ||
114 | /*===========================================================================*/ | ||
115 | |||
116 | #if !defined(__DOXYGEN__) | ||
117 | extern memcore_t ch_memcore; | ||
118 | #endif | ||
119 | |||
120 | #ifdef __cplusplus | ||
121 | extern "C" { | ||
122 | #endif | ||
123 | void _core_init(void); | ||
124 | void *chCoreAllocFromBaseI(size_t size, unsigned align, size_t offset); | ||
125 | void *chCoreAllocFromTopI(size_t size, unsigned align, size_t offset); | ||
126 | void *chCoreAllocFromBase(size_t size, unsigned align, size_t offset); | ||
127 | void *chCoreAllocFromTop(size_t size, unsigned align, size_t offset); | ||
128 | size_t chCoreGetStatusX(void); | ||
129 | #ifdef __cplusplus | ||
130 | } | ||
131 | #endif | ||
132 | |||
133 | /*===========================================================================*/ | ||
134 | /* Module inline functions. */ | ||
135 | /*===========================================================================*/ | ||
136 | |||
137 | /** | ||
138 | * @brief Allocates a memory block. | ||
139 | * @details The allocated block is guaranteed to be properly aligned to the | ||
140 | * specified alignment. | ||
141 | * @note This is a generic form with unspecified allocation position. | ||
142 | * | ||
143 | * @param[in] size the size of the block to be allocated. | ||
144 | * @param[in] align desired memory alignment | ||
145 | * @return A pointer to the allocated memory block. | ||
146 | * @retval NULL allocation failed, core memory exhausted. | ||
147 | * | ||
148 | * @iclass | ||
149 | */ | ||
150 | static inline void *chCoreAllocAlignedI(size_t size, unsigned align) { | ||
151 | |||
152 | return chCoreAllocAlignedWithOffsetI(size, align, 0U); | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * @brief Allocates a memory block. | ||
157 | * @details The allocated block is guaranteed to be properly aligned to the | ||
158 | * specified alignment. | ||
159 | * @note This is a generic form with unspecified allocation position. | ||
160 | * | ||
161 | * @param[in] size the size of the block to be allocated | ||
162 | * @param[in] align desired memory alignment | ||
163 | * @return A pointer to the allocated memory block. | ||
164 | * @retval NULL allocation failed, core memory exhausted. | ||
165 | * | ||
166 | * @api | ||
167 | */ | ||
168 | static inline void *chCoreAllocAligned(size_t size, unsigned align) { | ||
169 | |||
170 | return chCoreAllocAlignedWithOffset(size, align, 0U); | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * @brief Allocates a memory block. | ||
175 | * @details The allocated block is guaranteed to be properly aligned for a | ||
176 | * pointer data type. | ||
177 | * @note This is a generic form with unspecified allocation position. | ||
178 | * | ||
179 | * @param[in] size the size of the block to be allocated. | ||
180 | * @return A pointer to the allocated memory block. | ||
181 | * @retval NULL allocation failed, core memory exhausted. | ||
182 | * | ||
183 | * @iclass | ||
184 | */ | ||
185 | static inline void *chCoreAllocI(size_t size) { | ||
186 | |||
187 | return chCoreAllocAlignedWithOffsetI(size, PORT_NATURAL_ALIGN, 0U); | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * @brief Allocates a memory block. | ||
192 | * @details The allocated block is guaranteed to be properly aligned for a | ||
193 | * pointer data type. | ||
194 | * @note This is a generic form with unspecified allocation position. | ||
195 | * | ||
196 | * @param[in] size the size of the block to be allocated. | ||
197 | * @return A pointer to the allocated memory block. | ||
198 | * @retval NULL allocation failed, core memory exhausted. | ||
199 | * | ||
200 | * @api | ||
201 | */ | ||
202 | static inline void *chCoreAlloc(size_t size) { | ||
203 | |||
204 | return chCoreAllocAlignedWithOffset(size, PORT_NATURAL_ALIGN, 0U); | ||
205 | } | ||
206 | |||
207 | #endif /* CH_CFG_USE_MEMCORE == TRUE */ | ||
208 | |||
209 | #endif /* CHMEMCORE_H */ | ||
210 | |||
211 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chmemheaps.h b/lib/chibios/os/oslib/include/chmemheaps.h new file mode 100644 index 000000000..c0c4b97e0 --- /dev/null +++ b/lib/chibios/os/oslib/include/chmemheaps.h | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chmemheaps.h | ||
22 | * @brief Memory heaps macros and structures. | ||
23 | * | ||
24 | * @addtogroup oslib_memheaps | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHMEMHEAPS_H | ||
29 | #define CHMEMHEAPS_H | ||
30 | |||
31 | #if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__) | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Module constants. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /** | ||
38 | * @brief Minimum alignment used for heap. | ||
39 | * @note Cannot use the sizeof operator in this macro. | ||
40 | */ | ||
41 | #if (SIZEOF_PTR == 4) || defined(__DOXYGEN__) | ||
42 | #define CH_HEAP_ALIGNMENT 8U | ||
43 | #elif (SIZEOF_PTR == 2) | ||
44 | #define CH_HEAP_ALIGNMENT 4U | ||
45 | #else | ||
46 | #error "unsupported pointer size" | ||
47 | #endif | ||
48 | |||
49 | /*===========================================================================*/ | ||
50 | /* Module pre-compile time settings. */ | ||
51 | /*===========================================================================*/ | ||
52 | |||
53 | /*===========================================================================*/ | ||
54 | /* Derived constants and error checks. */ | ||
55 | /*===========================================================================*/ | ||
56 | |||
57 | #if CH_CFG_USE_MEMCORE == FALSE | ||
58 | #error "CH_CFG_USE_HEAP requires CH_CFG_USE_MEMCORE" | ||
59 | #endif | ||
60 | |||
61 | #if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE) | ||
62 | #error "CH_CFG_USE_HEAP requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" | ||
63 | #endif | ||
64 | |||
65 | /*===========================================================================*/ | ||
66 | /* Module data structures and types. */ | ||
67 | /*===========================================================================*/ | ||
68 | |||
69 | /** | ||
70 | * @brief Type of a memory heap. | ||
71 | */ | ||
72 | typedef struct memory_heap memory_heap_t; | ||
73 | |||
74 | /** | ||
75 | * @brief Type of a memory heap header. | ||
76 | */ | ||
77 | typedef union heap_header heap_header_t; | ||
78 | |||
79 | /** | ||
80 | * @brief Memory heap block header. | ||
81 | */ | ||
82 | union heap_header { | ||
83 | struct { | ||
84 | heap_header_t *next; /**< @brief Next block in free list. */ | ||
85 | size_t pages; /**< @brief Size of the area in pages. */ | ||
86 | } free; | ||
87 | struct { | ||
88 | memory_heap_t *heap; /**< @brief Block owner heap. */ | ||
89 | size_t size; /**< @brief Size of the area in bytes. */ | ||
90 | } used; | ||
91 | }; | ||
92 | |||
93 | /** | ||
94 | * @brief Structure describing a memory heap. | ||
95 | */ | ||
96 | struct memory_heap { | ||
97 | memgetfunc2_t provider; /**< @brief Memory blocks provider for | ||
98 | this heap. */ | ||
99 | heap_header_t header; /**< @brief Free blocks list header. */ | ||
100 | #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) | ||
101 | mutex_t mtx; /**< @brief Heap access mutex. */ | ||
102 | #else | ||
103 | semaphore_t sem; /**< @brief Heap access semaphore. */ | ||
104 | #endif | ||
105 | }; | ||
106 | |||
107 | /*===========================================================================*/ | ||
108 | /* Module macros. */ | ||
109 | /*===========================================================================*/ | ||
110 | |||
111 | /** | ||
112 | * @brief Allocation of an aligned static heap buffer. | ||
113 | */ | ||
114 | #define CH_HEAP_AREA(name, size) \ | ||
115 | ALIGNED_VAR(CH_HEAP_ALIGNMENT) \ | ||
116 | uint8_t name[MEM_ALIGN_NEXT((size), CH_HEAP_ALIGNMENT)] | ||
117 | |||
118 | /*===========================================================================*/ | ||
119 | /* External declarations. */ | ||
120 | /*===========================================================================*/ | ||
121 | |||
122 | #ifdef __cplusplus | ||
123 | extern "C" { | ||
124 | #endif | ||
125 | void _heap_init(void); | ||
126 | void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size); | ||
127 | void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align); | ||
128 | void chHeapFree(void *p); | ||
129 | size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp); | ||
130 | #ifdef __cplusplus | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | /*===========================================================================*/ | ||
135 | /* Module inline functions. */ | ||
136 | /*===========================================================================*/ | ||
137 | |||
138 | /** | ||
139 | * @brief Allocates a block of memory from the heap by using the first-fit | ||
140 | * algorithm. | ||
141 | * @details The allocated block is guaranteed to be properly aligned for a | ||
142 | * pointer data type. | ||
143 | * | ||
144 | * @param[in] heapp pointer to a heap descriptor or @p NULL in order to | ||
145 | * access the default heap. | ||
146 | * @param[in] size the size of the block to be allocated. Note that the | ||
147 | * allocated block may be a bit bigger than the requested | ||
148 | * size for alignment and fragmentation reasons. | ||
149 | * @return A pointer to the allocated block. | ||
150 | * @retval NULL if the block cannot be allocated. | ||
151 | * | ||
152 | * @api | ||
153 | */ | ||
154 | static inline void *chHeapAlloc(memory_heap_t *heapp, size_t size) { | ||
155 | |||
156 | return chHeapAllocAligned(heapp, size, CH_HEAP_ALIGNMENT); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * @brief Returns the size of an allocated block. | ||
161 | * @note The returned value is the requested size, the real size is the | ||
162 | * same value aligned to the next @p CH_HEAP_ALIGNMENT multiple. | ||
163 | * | ||
164 | * @param[in] p pointer to the memory block | ||
165 | * @return Size of the block. | ||
166 | * | ||
167 | * @api | ||
168 | */ | ||
169 | static inline size_t chHeapGetSize(const void *p) { | ||
170 | |||
171 | return ((heap_header_t *)p - 1U)->used.size; | ||
172 | } | ||
173 | |||
174 | #endif /* CH_CFG_USE_HEAP == TRUE */ | ||
175 | |||
176 | #endif /* CHMEMHEAPS_H */ | ||
177 | |||
178 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chmempools.h b/lib/chibios/os/oslib/include/chmempools.h new file mode 100644 index 000000000..52f78e004 --- /dev/null +++ b/lib/chibios/os/oslib/include/chmempools.h | |||
@@ -0,0 +1,385 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chmempools.h | ||
22 | * @brief Memory Pools macros and structures. | ||
23 | * | ||
24 | * @addtogroup oslib_mempools | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHMEMPOOLS_H | ||
29 | #define CHMEMPOOLS_H | ||
30 | |||
31 | #if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__) | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Module constants. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /*===========================================================================*/ | ||
38 | /* Module pre-compile time settings. */ | ||
39 | /*===========================================================================*/ | ||
40 | |||
41 | /*===========================================================================*/ | ||
42 | /* Derived constants and error checks. */ | ||
43 | /*===========================================================================*/ | ||
44 | |||
45 | #if CH_CFG_USE_MEMCORE == FALSE | ||
46 | #error "CH_CFG_USE_MEMPOOLS requires CH_CFG_USE_MEMCORE" | ||
47 | #endif | ||
48 | |||
49 | /*===========================================================================*/ | ||
50 | /* Module data structures and types. */ | ||
51 | /*===========================================================================*/ | ||
52 | |||
53 | /** | ||
54 | * @brief Memory pool free object header. | ||
55 | */ | ||
56 | struct pool_header { | ||
57 | struct pool_header *next; /**< @brief Pointer to the next pool | ||
58 | header in the list. */ | ||
59 | }; | ||
60 | |||
61 | /** | ||
62 | * @brief Memory pool descriptor. | ||
63 | */ | ||
64 | typedef struct { | ||
65 | struct pool_header *next; /**< @brief Pointer to the header. */ | ||
66 | size_t object_size; /**< @brief Memory pool objects | ||
67 | size. */ | ||
68 | unsigned align; /**< @brief Required alignment. */ | ||
69 | memgetfunc_t provider; /**< @brief Memory blocks provider | ||
70 | for this pool. */ | ||
71 | } memory_pool_t; | ||
72 | |||
73 | #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) | ||
74 | /** | ||
75 | * @brief Guarded memory pool descriptor. | ||
76 | */ | ||
77 | typedef struct { | ||
78 | semaphore_t sem; /**< @brief Counter semaphore guarding | ||
79 | the memory pool. */ | ||
80 | memory_pool_t pool; /**< @brief The memory pool itself. */ | ||
81 | } guarded_memory_pool_t; | ||
82 | #endif /* CH_CFG_USE_SEMAPHORES == TRUE */ | ||
83 | |||
84 | /*===========================================================================*/ | ||
85 | /* Module macros. */ | ||
86 | /*===========================================================================*/ | ||
87 | |||
88 | /** | ||
89 | * @brief Data part of a static memory pool initializer. | ||
90 | * @details This macro should be used when statically initializing a | ||
91 | * memory pool that is part of a bigger structure. | ||
92 | * | ||
93 | * @param[in] name the name of the memory pool variable | ||
94 | * @param[in] size size of the memory pool contained objects | ||
95 | * @param[in] align required memory alignment | ||
96 | * @param[in] provider memory provider function for the memory pool | ||
97 | */ | ||
98 | #define _MEMORYPOOL_DATA(name, size, align, provider) \ | ||
99 | {NULL, size, align, provider} | ||
100 | |||
101 | /** | ||
102 | * @brief Static memory pool initializer. | ||
103 | * @details Statically initialized memory pools require no explicit | ||
104 | * initialization using @p chPoolInit(). | ||
105 | * | ||
106 | * @param[in] name the name of the memory pool variable | ||
107 | * @param[in] size size of the memory pool contained objects | ||
108 | * @param[in] align required memory alignment | ||
109 | * @param[in] provider memory provider function for the memory pool or @p NULL | ||
110 | * if the pool is not allowed to grow automatically | ||
111 | */ | ||
112 | #define MEMORYPOOL_DECL(name, size, align, provider) \ | ||
113 | memory_pool_t name = _MEMORYPOOL_DATA(name, size, align, provider) | ||
114 | |||
115 | #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) | ||
116 | /** | ||
117 | * @brief Data part of a static guarded memory pool initializer. | ||
118 | * @details This macro should be used when statically initializing a | ||
119 | * memory pool that is part of a bigger structure. | ||
120 | * | ||
121 | * @param[in] name the name of the memory pool variable | ||
122 | * @param[in] size size of the memory pool contained objects | ||
123 | * @param[in] align required memory alignment | ||
124 | */ | ||
125 | #define _GUARDEDMEMORYPOOL_DATA(name, size, align) { \ | ||
126 | _SEMAPHORE_DATA(name.sem, (cnt_t)0), \ | ||
127 | _MEMORYPOOL_DATA(NULL, size, align, NULL) \ | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * @brief Static guarded memory pool initializer. | ||
132 | * @details Statically initialized guarded memory pools require no explicit | ||
133 | * initialization using @p chGuardedPoolInit(). | ||
134 | * | ||
135 | * @param[in] name the name of the guarded memory pool variable | ||
136 | * @param[in] size size of the memory pool contained objects | ||
137 | * @param[in] align required memory alignment | ||
138 | */ | ||
139 | #define GUARDEDMEMORYPOOL_DECL(name, size, align) \ | ||
140 | guarded_memory_pool_t name = _GUARDEDMEMORYPOOL_DATA(name, size, align) | ||
141 | #endif /* CH_CFG_USE_SEMAPHORES == TRUE */ | ||
142 | |||
143 | /*===========================================================================*/ | ||
144 | /* External declarations. */ | ||
145 | /*===========================================================================*/ | ||
146 | |||
147 | #ifdef __cplusplus | ||
148 | extern "C" { | ||
149 | #endif | ||
150 | void chPoolObjectInitAligned(memory_pool_t *mp, size_t size, | ||
151 | unsigned align, memgetfunc_t provider); | ||
152 | void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n); | ||
153 | void *chPoolAllocI(memory_pool_t *mp); | ||
154 | void *chPoolAlloc(memory_pool_t *mp); | ||
155 | void chPoolFreeI(memory_pool_t *mp, void *objp); | ||
156 | void chPoolFree(memory_pool_t *mp, void *objp); | ||
157 | #if CH_CFG_USE_SEMAPHORES == TRUE | ||
158 | void chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp, | ||
159 | size_t size, | ||
160 | unsigned align); | ||
161 | void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n); | ||
162 | void *chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp, | ||
163 | sysinterval_t timeout); | ||
164 | void *chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp, | ||
165 | sysinterval_t timeout); | ||
166 | void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp); | ||
167 | #endif | ||
168 | #ifdef __cplusplus | ||
169 | } | ||
170 | #endif | ||
171 | |||
172 | /*===========================================================================*/ | ||
173 | /* Module inline functions. */ | ||
174 | /*===========================================================================*/ | ||
175 | |||
176 | /** | ||
177 | * @brief Initializes an empty memory pool. | ||
178 | * | ||
179 | * @param[out] mp pointer to a @p memory_pool_t structure | ||
180 | * @param[in] size the size of the objects contained in this memory pool, | ||
181 | * the minimum accepted size is the size of a pointer to | ||
182 | * void. | ||
183 | * @param[in] provider memory provider function for the memory pool or | ||
184 | * @p NULL if the pool is not allowed to grow | ||
185 | * automatically | ||
186 | * | ||
187 | * @init | ||
188 | */ | ||
189 | static inline void chPoolObjectInit(memory_pool_t *mp, | ||
190 | size_t size, | ||
191 | memgetfunc_t provider) { | ||
192 | |||
193 | chPoolObjectInitAligned(mp, size, PORT_NATURAL_ALIGN, provider); | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * @brief Adds an object to a memory pool. | ||
198 | * @pre The memory pool must be already been initialized. | ||
199 | * @pre The added object must be of the right size for the specified | ||
200 | * memory pool. | ||
201 | * @pre The added object must be properly aligned. | ||
202 | * @note This function is just an alias for @p chPoolFree() and has been | ||
203 | * added for clarity. | ||
204 | * | ||
205 | * @param[in] mp pointer to a @p memory_pool_t structure | ||
206 | * @param[in] objp the pointer to the object to be added | ||
207 | * | ||
208 | * @api | ||
209 | */ | ||
210 | static inline void chPoolAdd(memory_pool_t *mp, void *objp) { | ||
211 | |||
212 | chPoolFree(mp, objp); | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * @brief Adds an object to a memory pool. | ||
217 | * @pre The memory pool must be already been initialized. | ||
218 | * @pre The added object must be of the right size for the specified | ||
219 | * memory pool. | ||
220 | * @pre The added object must be properly aligned. | ||
221 | * @note This function is just an alias for @p chPoolFreeI() and has been | ||
222 | * added for clarity. | ||
223 | * | ||
224 | * @param[in] mp pointer to a @p memory_pool_t structure | ||
225 | * @param[in] objp the pointer to the object to be added | ||
226 | * | ||
227 | * @iclass | ||
228 | */ | ||
229 | static inline void chPoolAddI(memory_pool_t *mp, void *objp) { | ||
230 | |||
231 | chPoolFreeI(mp, objp); | ||
232 | } | ||
233 | |||
234 | #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) | ||
235 | /** | ||
236 | * @brief Initializes an empty guarded memory pool. | ||
237 | * | ||
238 | * @param[out] gmp pointer to a @p guarded_memory_pool_t structure | ||
239 | * @param[in] size the size of the objects contained in this guarded | ||
240 | * memory pool, the minimum accepted size is the size | ||
241 | * of a pointer to void. | ||
242 | * | ||
243 | * @init | ||
244 | */ | ||
245 | static inline void chGuardedPoolObjectInit(guarded_memory_pool_t *gmp, | ||
246 | size_t size) { | ||
247 | |||
248 | chGuardedPoolObjectInitAligned(gmp, size, PORT_NATURAL_ALIGN); | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * @brief Gets the count of objects in a guarded memory pool. | ||
253 | * @pre The guarded memory pool must be already been initialized. | ||
254 | * | ||
255 | * @param[in] gmp pointer to a @p guarded_memory_pool_t structure | ||
256 | * @return The counter of the guard semaphore. | ||
257 | * | ||
258 | * @iclass | ||
259 | */ | ||
260 | static inline cnt_t chGuardedPoolGetCounterI(guarded_memory_pool_t *gmp) { | ||
261 | |||
262 | return chSemGetCounterI(&gmp->sem); | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * @brief Allocates an object from a guarded memory pool. | ||
267 | * @pre The guarded memory pool must be already been initialized. | ||
268 | * | ||
269 | * @param[in] gmp pointer to a @p guarded_memory_pool_t structure | ||
270 | * @return The pointer to the allocated object. | ||
271 | * @retval NULL if the pool is empty. | ||
272 | * | ||
273 | * @iclass | ||
274 | */ | ||
275 | static inline void *chGuardedPoolAllocI(guarded_memory_pool_t *gmp) { | ||
276 | void *p; | ||
277 | |||
278 | p = chPoolAllocI(&gmp->pool); | ||
279 | if (p != NULL) { | ||
280 | chSemFastWaitI(&gmp->sem); | ||
281 | chDbgAssert(chSemGetCounterI(&gmp->sem) >= (cnt_t)0, | ||
282 | "semaphore out of sync"); | ||
283 | } | ||
284 | return p; | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * @brief Releases an object into a guarded memory pool. | ||
289 | * @pre The guarded memory pool must already be initialized. | ||
290 | * @pre The freed object must be of the right size for the specified | ||
291 | * guarded memory pool. | ||
292 | * @pre The added object must be properly aligned. | ||
293 | * | ||
294 | * @param[in] gmp pointer to a @p guarded_memory_pool_t structure | ||
295 | * @param[in] objp the pointer to the object to be released | ||
296 | * | ||
297 | * @iclass | ||
298 | */ | ||
299 | static inline void chGuardedPoolFreeI(guarded_memory_pool_t *gmp, void *objp) { | ||
300 | |||
301 | chPoolFreeI(&gmp->pool, objp); | ||
302 | chSemSignalI(&gmp->sem); | ||
303 | } | ||
304 | |||
305 | /** | ||
306 | * @brief Releases an object into a guarded memory pool. | ||
307 | * @pre The guarded memory pool must already be initialized. | ||
308 | * @pre The freed object must be of the right size for the specified | ||
309 | * guarded memory pool. | ||
310 | * @pre The added object must be properly aligned. | ||
311 | * | ||
312 | * @param[in] gmp pointer to a @p guarded_memory_pool_t structure | ||
313 | * @param[in] objp the pointer to the object to be released | ||
314 | * | ||
315 | * @sclass | ||
316 | */ | ||
317 | static inline void chGuardedPoolFreeS(guarded_memory_pool_t *gmp, void *objp) { | ||
318 | |||
319 | chGuardedPoolFreeI(gmp, objp); | ||
320 | chSchRescheduleS(); | ||
321 | } | ||
322 | |||
323 | /** | ||
324 | * @brief Adds an object to a guarded memory pool. | ||
325 | * @pre The guarded memory pool must be already been initialized. | ||
326 | * @pre The added object must be of the right size for the specified | ||
327 | * guarded memory pool. | ||
328 | * @pre The added object must be properly aligned. | ||
329 | * @note This function is just an alias for @p chGuardedPoolFree() and | ||
330 | * has been added for clarity. | ||
331 | * | ||
332 | * @param[in] gmp pointer to a @p guarded_memory_pool_t structure | ||
333 | * @param[in] objp the pointer to the object to be added | ||
334 | * | ||
335 | * @api | ||
336 | */ | ||
337 | static inline void chGuardedPoolAdd(guarded_memory_pool_t *gmp, void *objp) { | ||
338 | |||
339 | chGuardedPoolFree(gmp, objp); | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * @brief Adds an object to a guarded memory pool. | ||
344 | * @pre The guarded memory pool must be already been initialized. | ||
345 | * @pre The added object must be of the right size for the specified | ||
346 | * guarded memory pool. | ||
347 | * @pre The added object must be properly aligned. | ||
348 | * @note This function is just an alias for @p chGuardedPoolFreeI() and | ||
349 | * has been added for clarity. | ||
350 | * | ||
351 | * @param[in] gmp pointer to a @p guarded_memory_pool_t structure | ||
352 | * @param[in] objp the pointer to the object to be added | ||
353 | * | ||
354 | * @iclass | ||
355 | */ | ||
356 | static inline void chGuardedPoolAddI(guarded_memory_pool_t *gmp, void *objp) { | ||
357 | |||
358 | chGuardedPoolFreeI(gmp, objp); | ||
359 | } | ||
360 | |||
361 | /** | ||
362 | * @brief Adds an object to a guarded memory pool. | ||
363 | * @pre The guarded memory pool must be already been initialized. | ||
364 | * @pre The added object must be of the right size for the specified | ||
365 | * guarded memory pool. | ||
366 | * @pre The added object must be properly aligned. | ||
367 | * @note This function is just an alias for @p chGuardedPoolFreeI() and | ||
368 | * has been added for clarity. | ||
369 | * | ||
370 | * @param[in] gmp pointer to a @p guarded_memory_pool_t structure | ||
371 | * @param[in] objp the pointer to the object to be added | ||
372 | * | ||
373 | * @sclass | ||
374 | */ | ||
375 | static inline void chGuardedPoolAddS(guarded_memory_pool_t *gmp, void *objp) { | ||
376 | |||
377 | chGuardedPoolFreeS(gmp, objp); | ||
378 | } | ||
379 | #endif /* CH_CFG_USE_SEMAPHORES == TRUE */ | ||
380 | |||
381 | #endif /* CH_CFG_USE_MEMPOOLS == TRUE */ | ||
382 | |||
383 | #endif /* CHMEMPOOLS_H */ | ||
384 | |||
385 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chobjcaches.h b/lib/chibios/os/oslib/include/chobjcaches.h new file mode 100644 index 000000000..9d8768e21 --- /dev/null +++ b/lib/chibios/os/oslib/include/chobjcaches.h | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chobjcaches.h | ||
22 | * @brief Objects Caches macros and structures. | ||
23 | * | ||
24 | * @addtogroup oslib_objchaches | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHOBJCACHES_H | ||
29 | #define CHOBJCACHES_H | ||
30 | |||
31 | #if (CH_CFG_USE_OBJ_CACHES == TRUE) || defined(__DOXYGEN__) | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Module constants. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /** | ||
38 | * @name Cached objects flags | ||
39 | * @{ | ||
40 | */ | ||
41 | #define OC_FLAG_INLRU 0x00000001U | ||
42 | #define OC_FLAG_INHASH 0x00000002U | ||
43 | #define OC_FLAG_SHARED 0x00000004U | ||
44 | #define OC_FLAG_NOTSYNC 0x00000008U | ||
45 | #define OC_FLAG_LAZYWRITE 0x00000010U | ||
46 | #define OC_FLAG_FORGET 0x00000020U | ||
47 | /** @} */ | ||
48 | |||
49 | /*===========================================================================*/ | ||
50 | /* Module pre-compile time settings. */ | ||
51 | /*===========================================================================*/ | ||
52 | |||
53 | /*===========================================================================*/ | ||
54 | /* Derived constants and error checks. */ | ||
55 | /*===========================================================================*/ | ||
56 | |||
57 | /*===========================================================================*/ | ||
58 | /* Module data structures and types. */ | ||
59 | /*===========================================================================*/ | ||
60 | |||
61 | /** | ||
62 | * @brief Flags of cached objects. | ||
63 | */ | ||
64 | typedef uint32_t oc_flags_t; | ||
65 | |||
66 | /** | ||
67 | * @brief Type of an hash element header. | ||
68 | */ | ||
69 | typedef struct ch_oc_hash_header oc_hash_header_t; | ||
70 | |||
71 | /** | ||
72 | * @brief Type of an LRU element header. | ||
73 | */ | ||
74 | typedef struct ch_oc_lru_header oc_lru_header_t; | ||
75 | |||
76 | /** | ||
77 | * @brief Type of a cached object. | ||
78 | */ | ||
79 | typedef struct ch_oc_object oc_object_t; | ||
80 | |||
81 | /** | ||
82 | * @brief Type of a cache object. | ||
83 | */ | ||
84 | typedef struct ch_objects_cache objects_cache_t; | ||
85 | |||
86 | /** | ||
87 | * @brief Object read function. | ||
88 | * | ||
89 | * @param[in] ocp pointer to the @p objects_cache_t structure | ||
90 | * @param[in] async requests an asynchronous operation if supported, the | ||
91 | * function is then responsible for releasing the | ||
92 | * object | ||
93 | */ | ||
94 | typedef bool (*oc_readf_t)(objects_cache_t *ocp, | ||
95 | oc_object_t *objp, | ||
96 | bool async); | ||
97 | |||
98 | /** | ||
99 | * @brief Object write function. | ||
100 | * | ||
101 | * @param[in] ocp pointer to the @p objects_cache_t structure | ||
102 | * @param[in] async requests an asynchronous operation if supported, the | ||
103 | * function is then responsible for releasing the | ||
104 | * object | ||
105 | */ | ||
106 | typedef bool (*oc_writef_t)(objects_cache_t *ocp, | ||
107 | oc_object_t *objp, | ||
108 | bool async); | ||
109 | |||
110 | /** | ||
111 | * @brief Structure representing an hash table element. | ||
112 | */ | ||
113 | struct ch_oc_hash_header { | ||
114 | /** | ||
115 | * @brief Next in the collisions list. | ||
116 | */ | ||
117 | oc_object_t *hash_next; | ||
118 | /** | ||
119 | * @brief Previous in the collisions list. | ||
120 | */ | ||
121 | oc_object_t *hash_prev; | ||
122 | }; | ||
123 | |||
124 | /** | ||
125 | * @brief Structure representing an hash table element. | ||
126 | */ | ||
127 | struct ch_oc_lru_header { | ||
128 | /** | ||
129 | * @brief Next in the collisions list. | ||
130 | */ | ||
131 | oc_object_t *hash_next; | ||
132 | /** | ||
133 | * @brief Previous in the collisions list. | ||
134 | */ | ||
135 | oc_object_t *hash_prev; | ||
136 | /** | ||
137 | * @brief Next in the LRU list. | ||
138 | */ | ||
139 | oc_object_t *lru_next; | ||
140 | /** | ||
141 | * @brief Previous in the LRU list. | ||
142 | */ | ||
143 | oc_object_t *lru_prev; | ||
144 | }; | ||
145 | |||
146 | /** | ||
147 | * @brief Structure representing a cached object. | ||
148 | */ | ||
149 | struct ch_oc_object { | ||
150 | /** | ||
151 | * @brief Next in the collisions list. | ||
152 | */ | ||
153 | oc_object_t *hash_next; | ||
154 | /** | ||
155 | * @brief Previous in the collisions list. | ||
156 | */ | ||
157 | oc_object_t *hash_prev; | ||
158 | /** | ||
159 | * @brief Next in the LRU list. | ||
160 | */ | ||
161 | oc_object_t *lru_next; | ||
162 | /** | ||
163 | * @brief Previous in the LRU list. | ||
164 | */ | ||
165 | oc_object_t *lru_prev; | ||
166 | /** | ||
167 | * @brief Object group. | ||
168 | */ | ||
169 | uint32_t obj_group; | ||
170 | /** | ||
171 | * @brief Object key. | ||
172 | */ | ||
173 | uint32_t obj_key; | ||
174 | /** | ||
175 | * @brief Semaphore for object access. | ||
176 | */ | ||
177 | semaphore_t obj_sem; | ||
178 | /** | ||
179 | * @brief Object flags. | ||
180 | */ | ||
181 | oc_flags_t obj_flags; | ||
182 | /** | ||
183 | * @brief User pointer. | ||
184 | * @note This pointer can be used to refer to external buffers, | ||
185 | * @p chCacheObjectInit() initializes it to @p NULL. | ||
186 | */ | ||
187 | void *dptr; | ||
188 | }; | ||
189 | |||
190 | /** | ||
191 | * @brief Structure representing a cache object. | ||
192 | */ | ||
193 | struct ch_objects_cache { | ||
194 | /** | ||
195 | * @brief Number of elements in the hash table. | ||
196 | */ | ||
197 | ucnt_t hashn; | ||
198 | /** | ||
199 | * @brief Pointer to the hash table. | ||
200 | */ | ||
201 | oc_hash_header_t *hashp; | ||
202 | /** | ||
203 | * @brief Number of elements in the objects table. | ||
204 | */ | ||
205 | ucnt_t objn; | ||
206 | /** | ||
207 | * @brief Size of elements in the objects table. | ||
208 | */ | ||
209 | size_t objsz; | ||
210 | /** | ||
211 | * @brief Pointer to the objects table. | ||
212 | */ | ||
213 | void *objvp; | ||
214 | /** | ||
215 | * @brief LRU list header. | ||
216 | */ | ||
217 | oc_lru_header_t lru; | ||
218 | /** | ||
219 | * @brief Semaphore for cache access. | ||
220 | */ | ||
221 | semaphore_t cache_sem; | ||
222 | /** | ||
223 | * @brief Semaphore for LRU access. | ||
224 | */ | ||
225 | semaphore_t lru_sem; | ||
226 | /** | ||
227 | * @brief Reader functions for cached objects. | ||
228 | */ | ||
229 | oc_readf_t readf; | ||
230 | /** | ||
231 | * @brief Writer functions for cached objects. | ||
232 | */ | ||
233 | oc_writef_t writef; | ||
234 | }; | ||
235 | |||
236 | /*===========================================================================*/ | ||
237 | /* Module macros. */ | ||
238 | /*===========================================================================*/ | ||
239 | |||
240 | /*===========================================================================*/ | ||
241 | /* External declarations. */ | ||
242 | /*===========================================================================*/ | ||
243 | |||
244 | #ifdef __cplusplus | ||
245 | extern "C" { | ||
246 | #endif | ||
247 | void chCacheObjectInit(objects_cache_t *ocp, | ||
248 | ucnt_t hashn, | ||
249 | oc_hash_header_t *hashp, | ||
250 | ucnt_t objn, | ||
251 | size_t objsz, | ||
252 | void *objvp, | ||
253 | oc_readf_t readf, | ||
254 | oc_writef_t writef); | ||
255 | oc_object_t *chCacheGetObject(objects_cache_t *ocp, | ||
256 | uint32_t group, | ||
257 | uint32_t key); | ||
258 | void chCacheReleaseObjectI(objects_cache_t *ocp, | ||
259 | oc_object_t *objp); | ||
260 | bool chCacheReadObject(objects_cache_t *ocp, | ||
261 | oc_object_t *objp, | ||
262 | bool async); | ||
263 | bool chCacheWriteObject(objects_cache_t *ocp, | ||
264 | oc_object_t *objp, | ||
265 | bool async); | ||
266 | #ifdef __cplusplus | ||
267 | } | ||
268 | #endif | ||
269 | |||
270 | /*===========================================================================*/ | ||
271 | /* Module inline functions. */ | ||
272 | /*===========================================================================*/ | ||
273 | |||
274 | /** | ||
275 | * @brief Releases an object into the cache. | ||
276 | * @note This function gives a meaning to the following flags: | ||
277 | * - @p OC_FLAG_INLRU must be cleared. | ||
278 | * - @p OC_FLAG_INHASH must be set. | ||
279 | * - @p OC_FLAG_SHARED must be cleared. | ||
280 | * - @p OC_FLAG_NOTSYNC invalidates the object and queues it on | ||
281 | * the LRU tail. | ||
282 | * - @p OC_FLAG_LAZYWRITE is ignored and kept, a write will occur | ||
283 | * when the object is removed from the LRU list (lazy write). | ||
284 | * . | ||
285 | * | ||
286 | * @param[in] ocp pointer to the @p objects_cache_t structure | ||
287 | * @param[in] objp pointer to the @p oc_object_t structure | ||
288 | * | ||
289 | * @api | ||
290 | */ | ||
291 | static inline void chCacheReleaseObject(objects_cache_t *ocp, | ||
292 | oc_object_t *objp) { | ||
293 | |||
294 | chSysLock(); | ||
295 | chCacheReleaseObjectI(ocp, objp); | ||
296 | chSchRescheduleS(); | ||
297 | chSysUnlock(); | ||
298 | } | ||
299 | |||
300 | #endif /* CH_CFG_USE_OBJ_CACHES == TRUE */ | ||
301 | |||
302 | #endif /* CHOBJCACHES_H */ | ||
303 | |||
304 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chobjfifos.h b/lib/chibios/os/oslib/include/chobjfifos.h new file mode 100644 index 000000000..56cec3634 --- /dev/null +++ b/lib/chibios/os/oslib/include/chobjfifos.h | |||
@@ -0,0 +1,430 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chobjfifos.h | ||
22 | * @brief Objects FIFO structures and macros. | ||
23 | * @details This module implements a generic FIFO queue of objects by | ||
24 | * coupling a Guarded Memory Pool (for objects storage) and | ||
25 | * a MailBox.<br> | ||
26 | * On the sender side free objects are taken from the pool, filled | ||
27 | * and then sent to the receiver, on the receiver side objects are | ||
28 | * fetched, used and then returned to the pool. | ||
29 | * Operations defined for object FIFOs: | ||
30 | * - <b>Take</b>: An object is taken from the pool of the free | ||
31 | * objects, can be blocking. | ||
32 | * - <b>Return</b>: An object is returned to the pool of the | ||
33 | * free objects, it is guaranteed to be non-blocking. | ||
34 | * - <b>Send</b>: An object is sent through the mailbox, it is | ||
35 | * guaranteed to be non-blocking | ||
36 | * - <b>Receive</b>: An object is received from the mailbox, | ||
37 | * can be blocking. | ||
38 | * . | ||
39 | * | ||
40 | * @addtogroup oslib_objects_fifos | ||
41 | * @{ | ||
42 | */ | ||
43 | |||
44 | #ifndef CHOBJFIFOS_H | ||
45 | #define CHOBJFIFOS_H | ||
46 | |||
47 | #if (CH_CFG_USE_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) | ||
48 | |||
49 | /*===========================================================================*/ | ||
50 | /* Module constants. */ | ||
51 | /*===========================================================================*/ | ||
52 | |||
53 | /*===========================================================================*/ | ||
54 | /* Module pre-compile time settings. */ | ||
55 | /*===========================================================================*/ | ||
56 | |||
57 | /*===========================================================================*/ | ||
58 | /* Derived constants and error checks. */ | ||
59 | /*===========================================================================*/ | ||
60 | |||
61 | #if CH_CFG_USE_MEMPOOLS == FALSE | ||
62 | #error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MEMPOOLS" | ||
63 | #endif | ||
64 | |||
65 | #if CH_CFG_USE_SEMAPHORES == FALSE | ||
66 | #error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_SEMAPHORES" | ||
67 | #endif | ||
68 | |||
69 | #if CH_CFG_USE_MAILBOXES == FALSE | ||
70 | #error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MAILBOXES" | ||
71 | #endif | ||
72 | |||
73 | /*===========================================================================*/ | ||
74 | /* Module data structures and types. */ | ||
75 | /*===========================================================================*/ | ||
76 | |||
77 | /** | ||
78 | * @brief Type of an objects FIFO. | ||
79 | */ | ||
80 | typedef struct ch_objects_fifo { | ||
81 | /** | ||
82 | * @brief Pool of the free objects. | ||
83 | */ | ||
84 | guarded_memory_pool_t free; | ||
85 | /** | ||
86 | * @brief Mailbox of the sent objects. | ||
87 | */ | ||
88 | mailbox_t mbx; | ||
89 | } objects_fifo_t; | ||
90 | |||
91 | /*===========================================================================*/ | ||
92 | /* Module macros. */ | ||
93 | /*===========================================================================*/ | ||
94 | |||
95 | /*===========================================================================*/ | ||
96 | /* External declarations. */ | ||
97 | /*===========================================================================*/ | ||
98 | |||
99 | #ifdef __cplusplus | ||
100 | extern "C" { | ||
101 | #endif | ||
102 | |||
103 | #ifdef __cplusplus | ||
104 | } | ||
105 | #endif | ||
106 | |||
107 | /*===========================================================================*/ | ||
108 | /* Module inline functions. */ | ||
109 | /*===========================================================================*/ | ||
110 | |||
111 | /** | ||
112 | * @brief Initializes a FIFO object. | ||
113 | * @pre The messages size must be a multiple of the alignment | ||
114 | * requirement. | ||
115 | * | ||
116 | * @param[out] ofp pointer to a @p objects_fifo_t structure | ||
117 | * @param[in] objsize size of objects | ||
118 | * @param[in] objn number of objects available | ||
119 | * @param[in] objalign required objects alignment | ||
120 | * @param[in] objbuf pointer to the buffer of objects, it must be able | ||
121 | * to hold @p objn objects of @p objsize size with | ||
122 | * @p objalign alignment | ||
123 | * @param[in] msgbuf pointer to the buffer of messages, it must be able | ||
124 | * to hold @p objn messages | ||
125 | * | ||
126 | * @init | ||
127 | */ | ||
128 | static inline void chFifoObjectInitAligned(objects_fifo_t *ofp, size_t objsize, | ||
129 | size_t objn, unsigned objalign, | ||
130 | void *objbuf, msg_t *msgbuf) { | ||
131 | |||
132 | chDbgCheck((objsize >= objalign) && ((objsize % objalign) == 0U)); | ||
133 | |||
134 | chGuardedPoolObjectInitAligned(&ofp->free, objsize, objalign); | ||
135 | chGuardedPoolLoadArray(&ofp->free, objbuf, objn); | ||
136 | chMBObjectInit(&ofp->mbx, msgbuf, objn); | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * @brief Initializes a FIFO object. | ||
141 | * @pre The messages size must be a multiple of the alignment | ||
142 | * requirement. | ||
143 | * | ||
144 | * @param[out] ofp pointer to a @p objects_fifo_t structure | ||
145 | * @param[in] objsize size of objects | ||
146 | * @param[in] objn number of objects available | ||
147 | * @param[in] objbuf pointer to the buffer of objects, it must be able | ||
148 | * to hold @p objn objects of @p objsize size | ||
149 | * @param[in] msgbuf pointer to the buffer of messages, it must be able | ||
150 | * to hold @p objn messages | ||
151 | * | ||
152 | * @init | ||
153 | */ | ||
154 | static inline void chFifoObjectInit(objects_fifo_t *ofp, size_t objsize, | ||
155 | size_t objn, void *objbuf, | ||
156 | msg_t *msgbuf) { | ||
157 | |||
158 | chFifoObjectInitAligned(ofp, objsize, objn, | ||
159 | PORT_NATURAL_ALIGN, | ||
160 | objbuf, msgbuf); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * @brief Allocates a free object. | ||
165 | * | ||
166 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
167 | * @return The pointer to the allocated object. | ||
168 | * @retval NULL if an object is not immediately available. | ||
169 | * | ||
170 | * @iclass | ||
171 | */ | ||
172 | static inline void *chFifoTakeObjectI(objects_fifo_t *ofp) { | ||
173 | |||
174 | return chGuardedPoolAllocI(&ofp->free); | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * @brief Allocates a free object. | ||
179 | * | ||
180 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
181 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
182 | * the following special values are allowed: | ||
183 | * - @a TIME_IMMEDIATE immediate timeout. | ||
184 | * - @a TIME_INFINITE no timeout. | ||
185 | * . | ||
186 | * @return The pointer to the allocated object. | ||
187 | * @retval NULL if an object is not available within the specified | ||
188 | * timeout. | ||
189 | * | ||
190 | * @sclass | ||
191 | */ | ||
192 | static inline void *chFifoTakeObjectTimeoutS(objects_fifo_t *ofp, | ||
193 | sysinterval_t timeout) { | ||
194 | |||
195 | return chGuardedPoolAllocTimeoutS(&ofp->free, timeout); | ||
196 | } | ||
197 | |||
198 | /** | ||
199 | * @brief Allocates a free object. | ||
200 | * | ||
201 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
202 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
203 | * the following special values are allowed: | ||
204 | * - @a TIME_IMMEDIATE immediate timeout. | ||
205 | * - @a TIME_INFINITE no timeout. | ||
206 | * . | ||
207 | * @return The pointer to the allocated object. | ||
208 | * @retval NULL if an object is not available within the specified | ||
209 | * timeout. | ||
210 | * | ||
211 | * @api | ||
212 | */ | ||
213 | static inline void *chFifoTakeObjectTimeout(objects_fifo_t *ofp, | ||
214 | sysinterval_t timeout) { | ||
215 | |||
216 | return chGuardedPoolAllocTimeout(&ofp->free, timeout); | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * @brief Releases a fetched object. | ||
221 | * | ||
222 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
223 | * @param[in] objp pointer to the object to be released | ||
224 | * | ||
225 | * @iclass | ||
226 | */ | ||
227 | static inline void chFifoReturnObjectI(objects_fifo_t *ofp, | ||
228 | void *objp) { | ||
229 | |||
230 | chGuardedPoolFreeI(&ofp->free, objp); | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * @brief Releases a fetched object. | ||
235 | * | ||
236 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
237 | * @param[in] objp pointer to the object to be released | ||
238 | * | ||
239 | * @sclass | ||
240 | */ | ||
241 | static inline void chFifoReturnObjectS(objects_fifo_t *ofp, | ||
242 | void *objp) { | ||
243 | |||
244 | chGuardedPoolFreeS(&ofp->free, objp); | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * @brief Releases a fetched object. | ||
249 | * | ||
250 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
251 | * @param[in] objp pointer to the object to be released | ||
252 | * | ||
253 | * @api | ||
254 | */ | ||
255 | static inline void chFifoReturnObject(objects_fifo_t *ofp, | ||
256 | void *objp) { | ||
257 | |||
258 | chGuardedPoolFree(&ofp->free, objp); | ||
259 | } | ||
260 | |||
261 | /** | ||
262 | * @brief Posts an object. | ||
263 | * @note By design the object can be always immediately posted. | ||
264 | * | ||
265 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
266 | * @param[in] objp pointer to the object to be posted | ||
267 | * | ||
268 | * @iclass | ||
269 | */ | ||
270 | static inline void chFifoSendObjectI(objects_fifo_t *ofp, | ||
271 | void *objp) { | ||
272 | msg_t msg; | ||
273 | |||
274 | msg = chMBPostI(&ofp->mbx, (msg_t)objp); | ||
275 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * @brief Posts an object. | ||
280 | * @note By design the object can be always immediately posted. | ||
281 | * | ||
282 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
283 | * @param[in] objp pointer to the object to be posted | ||
284 | * | ||
285 | * @sclass | ||
286 | */ | ||
287 | static inline void chFifoSendObjectS(objects_fifo_t *ofp, | ||
288 | void *objp) { | ||
289 | msg_t msg; | ||
290 | |||
291 | msg = chMBPostTimeoutS(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); | ||
292 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * @brief Posts an object. | ||
297 | * @note By design the object can be always immediately posted. | ||
298 | * | ||
299 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
300 | * @param[in] objp pointer to the object to be released | ||
301 | * | ||
302 | * @api | ||
303 | */ | ||
304 | static inline void chFifoSendObject(objects_fifo_t *ofp, void *objp) { | ||
305 | |||
306 | msg_t msg; | ||
307 | |||
308 | msg = chMBPostTimeout(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); | ||
309 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * @brief Posts an high priority object. | ||
314 | * @note By design the object can be always immediately posted. | ||
315 | * | ||
316 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
317 | * @param[in] objp pointer to the object to be posted | ||
318 | * | ||
319 | * @iclass | ||
320 | */ | ||
321 | static inline void chFifoSendObjectAheadI(objects_fifo_t *ofp, | ||
322 | void *objp) { | ||
323 | msg_t msg; | ||
324 | |||
325 | msg = chMBPostAheadI(&ofp->mbx, (msg_t)objp); | ||
326 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
327 | } | ||
328 | |||
329 | /** | ||
330 | * @brief Posts an high priority object. | ||
331 | * @note By design the object can be always immediately posted. | ||
332 | * | ||
333 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
334 | * @param[in] objp pointer to the object to be posted | ||
335 | * | ||
336 | * @sclass | ||
337 | */ | ||
338 | static inline void chFifoSendObjectAheadS(objects_fifo_t *ofp, | ||
339 | void *objp) { | ||
340 | msg_t msg; | ||
341 | |||
342 | msg = chMBPostAheadTimeoutS(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); | ||
343 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * @brief Posts an high priority object. | ||
348 | * @note By design the object can be always immediately posted. | ||
349 | * | ||
350 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
351 | * @param[in] objp pointer to the object to be released | ||
352 | * | ||
353 | * @api | ||
354 | */ | ||
355 | static inline void chFifoSendObjectAhead(objects_fifo_t *ofp, void *objp) { | ||
356 | |||
357 | msg_t msg; | ||
358 | |||
359 | msg = chMBPostAheadTimeout(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); | ||
360 | chDbgAssert(msg == MSG_OK, "post failed"); | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * @brief Fetches an object. | ||
365 | * | ||
366 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
367 | * @param[in] objpp pointer to the fetched object reference | ||
368 | * @return The operation status. | ||
369 | * @retval MSG_OK if an object has been correctly fetched. | ||
370 | * @retval MSG_TIMEOUT if the FIFO is empty and a message cannot be fetched. | ||
371 | * | ||
372 | * @iclass | ||
373 | */ | ||
374 | static inline msg_t chFifoReceiveObjectI(objects_fifo_t *ofp, | ||
375 | void **objpp) { | ||
376 | |||
377 | return chMBFetchI(&ofp->mbx, (msg_t *)objpp); | ||
378 | } | ||
379 | |||
380 | /** | ||
381 | * @brief Fetches an object. | ||
382 | * | ||
383 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
384 | * @param[in] objpp pointer to the fetched object reference | ||
385 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
386 | * the following special values are allowed: | ||
387 | * - @a TIME_IMMEDIATE immediate timeout. | ||
388 | * - @a TIME_INFINITE no timeout. | ||
389 | * . | ||
390 | * @return The operation status. | ||
391 | * @retval MSG_OK if an object has been correctly fetched. | ||
392 | * @retval MSG_TIMEOUT if the operation has timed out. | ||
393 | * | ||
394 | * @sclass | ||
395 | */ | ||
396 | static inline msg_t chFifoReceiveObjectTimeoutS(objects_fifo_t *ofp, | ||
397 | void **objpp, | ||
398 | sysinterval_t timeout) { | ||
399 | |||
400 | return chMBFetchTimeoutS(&ofp->mbx, (msg_t *)objpp, timeout); | ||
401 | } | ||
402 | |||
403 | /** | ||
404 | * @brief Fetches an object. | ||
405 | * | ||
406 | * @param[in] ofp pointer to a @p objects_fifo_t structure | ||
407 | * @param[in] objpp pointer to the fetched object reference | ||
408 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
409 | * the following special values are allowed: | ||
410 | * - @a TIME_IMMEDIATE immediate timeout. | ||
411 | * - @a TIME_INFINITE no timeout. | ||
412 | * . | ||
413 | * @return The operation status. | ||
414 | * @retval MSG_OK if an object has been correctly fetched. | ||
415 | * @retval MSG_TIMEOUT if the operation has timed out. | ||
416 | * | ||
417 | * @api | ||
418 | */ | ||
419 | static inline msg_t chFifoReceiveObjectTimeout(objects_fifo_t *ofp, | ||
420 | void **objpp, | ||
421 | sysinterval_t timeout) { | ||
422 | |||
423 | return chMBFetchTimeout(&ofp->mbx, (msg_t *)objpp, timeout); | ||
424 | } | ||
425 | |||
426 | #endif /* CH_CFG_USE_OBJ_FIFOS == TRUE */ | ||
427 | |||
428 | #endif /* CHOBJFIFOS_H */ | ||
429 | |||
430 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/include/chpipes.h b/lib/chibios/os/oslib/include/chpipes.h new file mode 100644 index 000000000..66fb70284 --- /dev/null +++ b/lib/chibios/os/oslib/include/chpipes.h | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/include/chpipes.h | ||
22 | * @brief Pipes macros and structures. | ||
23 | * | ||
24 | * @addtogroup oslib_pipes | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHPIPES_H | ||
29 | #define CHPIPES_H | ||
30 | |||
31 | #if (CH_CFG_USE_PIPES == TRUE) || defined(__DOXYGEN__) | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Module constants. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /*===========================================================================*/ | ||
38 | /* Module pre-compile time settings. */ | ||
39 | /*===========================================================================*/ | ||
40 | |||
41 | /*===========================================================================*/ | ||
42 | /* Derived constants and error checks. */ | ||
43 | /*===========================================================================*/ | ||
44 | |||
45 | /*===========================================================================*/ | ||
46 | /* Module data structures and types. */ | ||
47 | /*===========================================================================*/ | ||
48 | |||
49 | /** | ||
50 | * @brief Structure representing a pipe object. | ||
51 | */ | ||
52 | typedef struct { | ||
53 | uint8_t *buffer; /**< @brief Pointer to the pipe | ||
54 | buffer. */ | ||
55 | uint8_t *top; /**< @brief Pointer to the location | ||
56 | after the buffer. */ | ||
57 | uint8_t *wrptr; /**< @brief Write pointer. */ | ||
58 | uint8_t *rdptr; /**< @brief Read pointer. */ | ||
59 | size_t cnt; /**< @brief Bytes in the pipe. */ | ||
60 | bool reset; /**< @brief True if in reset state. */ | ||
61 | thread_reference_t wtr; /**< @brief Waiting writer. */ | ||
62 | thread_reference_t rtr; /**< @brief Waiting reader. */ | ||
63 | #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) | ||
64 | mutex_t cmtx; /**< @brief Common access mutex. */ | ||
65 | mutex_t wmtx; /**< @brief Write access mutex. */ | ||
66 | mutex_t rmtx; /**< @brief Read access mutex. */ | ||
67 | #else | ||
68 | semaphore_t csem; /**< @brief Common access semaphore.*/ | ||
69 | semaphore_t wsem; /**< @brief Write access semaphore. */ | ||
70 | semaphore_t rsem; /**< @brief Read access semaphore. */ | ||
71 | #endif | ||
72 | } pipe_t; | ||
73 | |||
74 | /*===========================================================================*/ | ||
75 | /* Module macros. */ | ||
76 | /*===========================================================================*/ | ||
77 | |||
78 | /** | ||
79 | * @brief Data part of a static pipe initializer. | ||
80 | * @details This macro should be used when statically initializing a | ||
81 | * pipe that is part of a bigger structure. | ||
82 | * | ||
83 | * @param[in] name the name of the pipe variable | ||
84 | * @param[in] buffer pointer to the pipe buffer array of @p uint8_t | ||
85 | * @param[in] size number of @p uint8_t elements in the buffer array | ||
86 | */ | ||
87 | #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) | ||
88 | #define _PIPE_DATA(name, buffer, size) { \ | ||
89 | (uint8_t *)(buffer), \ | ||
90 | (uint8_t *)(buffer) + size, \ | ||
91 | (uint8_t *)(buffer), \ | ||
92 | (uint8_t *)(buffer), \ | ||
93 | (size_t)0, \ | ||
94 | false, \ | ||
95 | NULL, \ | ||
96 | NULL, \ | ||
97 | _MUTEX_DATA(name.cmtx), \ | ||
98 | _MUTEX_DATA(name.wmtx), \ | ||
99 | _MUTEX_DATA(name.rmtx), \ | ||
100 | } | ||
101 | #else /* CH_CFG_USE_MUTEXES == FALSE */ | ||
102 | #define _PIPE_DATA(name, buffer, size) { \ | ||
103 | (uint8_t *)(buffer), \ | ||
104 | (uint8_t *)(buffer) + size, \ | ||
105 | (uint8_t *)(buffer), \ | ||
106 | (uint8_t *)(buffer), \ | ||
107 | (size_t)0, \ | ||
108 | false, \ | ||
109 | NULL, \ | ||
110 | NULL, \ | ||
111 | _SEMAPHORE_DATA(name.csem, (cnt_t)1), \ | ||
112 | _SEMAPHORE_DATA(name.wsem, (cnt_t)1), \ | ||
113 | _SEMAPHORE_DATA(name.rsem, (cnt_t)1), \ | ||
114 | } | ||
115 | #endif /* CH_CFG_USE_MUTEXES == FALSE */ | ||
116 | |||
117 | /** | ||
118 | * @brief Static pipe initializer. | ||
119 | * @details Statically initialized pipes require no explicit | ||
120 | * initialization using @p chPipeObjectInit(). | ||
121 | * | ||
122 | * @param[in] name the name of the pipe variable | ||
123 | * @param[in] buffer pointer to the pipe buffer array of @p uint8_t | ||
124 | * @param[in] size number of @p uint8_t elements in the buffer array | ||
125 | */ | ||
126 | #define PIPE_DECL(name, buffer, size) \ | ||
127 | pipe_t name = _PIPE_DATA(name, buffer, size) | ||
128 | |||
129 | /*===========================================================================*/ | ||
130 | /* External declarations. */ | ||
131 | /*===========================================================================*/ | ||
132 | |||
133 | #ifdef __cplusplus | ||
134 | extern "C" { | ||
135 | #endif | ||
136 | void chPipeObjectInit(pipe_t *pp, uint8_t *buf, size_t n); | ||
137 | void chPipeReset(pipe_t *pp); | ||
138 | size_t chPipeWriteTimeout(pipe_t *pp, const uint8_t *bp, | ||
139 | size_t n, sysinterval_t timeout); | ||
140 | size_t chPipeReadTimeout(pipe_t *pp, uint8_t *bp, | ||
141 | size_t n, sysinterval_t timeout); | ||
142 | #ifdef __cplusplus | ||
143 | } | ||
144 | #endif | ||
145 | |||
146 | /*===========================================================================*/ | ||
147 | /* Module inline functions. */ | ||
148 | /*===========================================================================*/ | ||
149 | |||
150 | /** | ||
151 | * @brief Returns the pipe buffer size as number of bytes. | ||
152 | * | ||
153 | * @param[in] pp the pointer to an initialized @p pipe_t object | ||
154 | * @return The size of the pipe. | ||
155 | * | ||
156 | * @api | ||
157 | */ | ||
158 | static inline size_t chPipeGetSize(const pipe_t *pp) { | ||
159 | |||
160 | /*lint -save -e9033 [10.8] Perfectly safe pointers | ||
161 | arithmetic.*/ | ||
162 | return (size_t)(pp->top - pp->buffer); | ||
163 | /*lint -restore*/ | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * @brief Returns the number of used byte slots into a pipe. | ||
168 | * | ||
169 | * @param[in] pp the pointer to an initialized @p pipe_t object | ||
170 | * @return The number of queued bytes. | ||
171 | * | ||
172 | * @api | ||
173 | */ | ||
174 | static inline size_t chPipeGetUsedCount(const pipe_t *pp) { | ||
175 | |||
176 | return pp->cnt; | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * @brief Returns the number of free byte slots into a pipe. | ||
181 | * | ||
182 | * @param[in] pp the pointer to an initialized @p pipe_t object | ||
183 | * @return The number of empty byte slots. | ||
184 | * | ||
185 | * @api | ||
186 | */ | ||
187 | static inline size_t chPipeGetFreeCount(const pipe_t *pp) { | ||
188 | |||
189 | return chPipeGetSize(pp) - chPipeGetUsedCount(pp); | ||
190 | } | ||
191 | |||
192 | /** | ||
193 | * @brief Terminates the reset state. | ||
194 | * | ||
195 | * @param[in] pp the pointer to an initialized @p pipe_t object | ||
196 | * | ||
197 | * @api | ||
198 | */ | ||
199 | static inline void chPipeResume(pipe_t *pp) { | ||
200 | |||
201 | pp->reset = false; | ||
202 | } | ||
203 | |||
204 | #endif /* CH_CFG_USE_PIPES == TRUE */ | ||
205 | |||
206 | #endif /* CHPIPES_H */ | ||
207 | |||
208 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/oslib.mk b/lib/chibios/os/oslib/oslib.mk new file mode 100644 index 000000000..e9fe2db9c --- /dev/null +++ b/lib/chibios/os/oslib/oslib.mk | |||
@@ -0,0 +1,57 @@ | |||
1 | # List of all the ChibiOS/LIB files, there is no need to remove the files | ||
2 | # from this list, you can disable parts of the kernel by editing chlibconf.h. | ||
3 | ifeq ($(USE_SMART_BUILD),yes) | ||
4 | |||
5 | # Configuration files directory | ||
6 | ifeq ($(CHCONFDIR),) | ||
7 | ifeq ($(CONFDIR),) | ||
8 | CHCONFDIR = . | ||
9 | else | ||
10 | CHCONFDIR := $(CONFDIR) | ||
11 | endif | ||
12 | endif | ||
13 | |||
14 | CHLIBCONF := $(strip $(shell cat $(CHCONFDIR)/chconf.h | egrep -e "\#define")) | ||
15 | |||
16 | LIBSRC := | ||
17 | ifneq ($(findstring CH_CFG_USE_MAILBOXES TRUE,$(CHLIBCONF)),) | ||
18 | LIBSRC += $(CHIBIOS)/os/oslib/src/chmboxes.c | ||
19 | endif | ||
20 | ifneq ($(findstring CH_CFG_USE_MEMCORE TRUE,$(CHLIBCONF)),) | ||
21 | LIBSRC += $(CHIBIOS)/os/oslib/src/chmemcore.c | ||
22 | endif | ||
23 | ifneq ($(findstring CH_CFG_USE_HEAP TRUE,$(CHLIBCONF)),) | ||
24 | LIBSRC += $(CHIBIOS)/os/oslib/src/chmemheaps.c | ||
25 | endif | ||
26 | ifneq ($(findstring CH_CFG_USE_MEMPOOLS TRUE,$(CHLIBCONF)),) | ||
27 | LIBSRC += $(CHIBIOS)/os/oslib/src/chmempools.c | ||
28 | endif | ||
29 | ifneq ($(findstring CH_CFG_USE_PIPES TRUE,$(CHLIBCONF)),) | ||
30 | LIBSRC += $(CHIBIOS)/os/oslib/src/chpipes.c | ||
31 | endif | ||
32 | ifneq ($(findstring CH_CFG_USE_OBJ_CACHES TRUE,$(CHLIBCONF)),) | ||
33 | LIBSRC += $(CHIBIOS)/os/oslib/src/chobjcaches.c | ||
34 | endif | ||
35 | ifneq ($(findstring CH_CFG_USE_DELEGATES TRUE,$(CHLIBCONF)),) | ||
36 | LIBSRC += $(CHIBIOS)/os/oslib/src/chdelegates.c | ||
37 | endif | ||
38 | ifneq ($(findstring CH_CFG_USE_FACTORY TRUE,$(CHLIBCONF)),) | ||
39 | LIBSRC += $(CHIBIOS)/os/oslib/src/chfactory.c | ||
40 | endif | ||
41 | else | ||
42 | LIBSRC := $(CHIBIOS)/os/oslib/src/chmboxes.c \ | ||
43 | $(CHIBIOS)/os/oslib/src/chmemcore.c \ | ||
44 | $(CHIBIOS)/os/oslib/src/chmemheaps.c \ | ||
45 | $(CHIBIOS)/os/oslib/src/chmempools.c \ | ||
46 | $(CHIBIOS)/os/oslib/src/chpipes.c \ | ||
47 | $(CHIBIOS)/os/oslib/src/chobjcaches.c \ | ||
48 | $(CHIBIOS)/os/oslib/src/chdelegates.c \ | ||
49 | $(CHIBIOS)/os/oslib/src/chfactory.c | ||
50 | endif | ||
51 | |||
52 | # Required include directories | ||
53 | LIBINC := $(CHIBIOS)/os/oslib/include | ||
54 | |||
55 | # Shared variables | ||
56 | ALLCSRC += $(LIBSRC) | ||
57 | ALLINC += $(LIBINC) | ||
diff --git a/lib/chibios/os/oslib/readme.txt b/lib/chibios/os/oslib/readme.txt new file mode 100644 index 000000000..ec43d5af2 --- /dev/null +++ b/lib/chibios/os/oslib/readme.txt | |||
@@ -0,0 +1,2 @@ | |||
1 | All the code contained under ./os/lib are high level RTOS extension modules | ||
2 | compatible with both RT and NIL. \ No newline at end of file | ||
diff --git a/lib/chibios/os/oslib/src/chdelegates.c b/lib/chibios/os/oslib/src/chdelegates.c new file mode 100644 index 000000000..648276eb6 --- /dev/null +++ b/lib/chibios/os/oslib/src/chdelegates.c | |||
@@ -0,0 +1,239 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/src/chdelegates.c | ||
22 | * @brief Delegate threads code. | ||
23 | * @details Delegate threads. | ||
24 | * <h2>Operation mode</h2> | ||
25 | * A delegate thread is a thread performing function calls triggered | ||
26 | * by other threads. This functionality is especially useful when | ||
27 | * encapsulating a library not designed for threading into a | ||
28 | * delegate thread. Other threads have access to the library without | ||
29 | * having to worry about mutual exclusion. | ||
30 | * @pre In order to use the pipes APIs the @p CH_CFG_USE_DELEGATES | ||
31 | * option must be enabled in @p chconf.h. | ||
32 | * @note Compatible with RT and NIL. | ||
33 | * | ||
34 | * @addtogroup oslib_delegates | ||
35 | * @{ | ||
36 | */ | ||
37 | |||
38 | #include "ch.h" | ||
39 | |||
40 | #if (CH_CFG_USE_DELEGATES == TRUE) || defined(__DOXYGEN__) | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Module local definitions. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Module exported variables. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Module local types. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | /** | ||
55 | * @brief Type of a structure representing a delegate call. | ||
56 | */ | ||
57 | typedef struct { | ||
58 | /** | ||
59 | * @brief The delegate veneer function. | ||
60 | */ | ||
61 | delegate_veneer_t veneer; | ||
62 | /** | ||
63 | * @brief Pointer to the caller @p va_list object. | ||
64 | */ | ||
65 | va_list *argsp; | ||
66 | } call_message_t; | ||
67 | |||
68 | /*===========================================================================*/ | ||
69 | /* Module local variables. */ | ||
70 | /*===========================================================================*/ | ||
71 | |||
72 | /*===========================================================================*/ | ||
73 | /* Module local functions. */ | ||
74 | /*===========================================================================*/ | ||
75 | |||
76 | /*===========================================================================*/ | ||
77 | /* Module exported functions. */ | ||
78 | /*===========================================================================*/ | ||
79 | |||
80 | /*lint -save -e586 [17.1] Required by design.*/ | ||
81 | |||
82 | /** | ||
83 | * @brief Veneer for functions with no parameters. | ||
84 | * | ||
85 | * @param[in] argsp the list of arguments | ||
86 | * @return The function return value. | ||
87 | */ | ||
88 | msg_t __ch_delegate_fn0(va_list *argsp) { | ||
89 | delegate_fn0_t fn0 = (delegate_fn0_t)va_arg(*argsp, delegate_fn0_t); | ||
90 | return fn0(); | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * @brief Veneer for functions with one parameter. | ||
95 | * | ||
96 | * @param[in] argsp the list of arguments | ||
97 | * @return The function return value. | ||
98 | */ | ||
99 | msg_t __ch_delegate_fn1(va_list *argsp) { | ||
100 | delegate_fn1_t fn1 = (delegate_fn1_t)va_arg(*argsp, delegate_fn1_t); | ||
101 | msg_t p1 = (msg_t)va_arg(*argsp, msg_t); | ||
102 | return fn1(p1); | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * @brief Veneer for functions with two parameters. | ||
107 | * | ||
108 | * @param[in] argsp the list of arguments | ||
109 | * @return The function return value. | ||
110 | */ | ||
111 | msg_t __ch_delegate_fn2(va_list *argsp) { | ||
112 | delegate_fn2_t fn2 = (delegate_fn2_t)va_arg(*argsp, delegate_fn2_t); | ||
113 | msg_t p1 = (msg_t)va_arg(*argsp, msg_t); | ||
114 | msg_t p2 = (msg_t)va_arg(*argsp, msg_t); | ||
115 | return fn2(p1, p2); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * @brief Veneer for functions with three parameters. | ||
120 | * | ||
121 | * @param[in] argsp the list of arguments | ||
122 | * @return The function return value. | ||
123 | */ | ||
124 | msg_t __ch_delegate_fn3(va_list *argsp) { | ||
125 | delegate_fn3_t fn3 = (delegate_fn3_t)va_arg(*argsp, delegate_fn3_t); | ||
126 | msg_t p1 = (msg_t)va_arg(*argsp, msg_t); | ||
127 | msg_t p2 = (msg_t)va_arg(*argsp, msg_t); | ||
128 | msg_t p3 = (msg_t)va_arg(*argsp, msg_t); | ||
129 | return fn3(p1, p2, p3); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * @brief Veneer for functions with four parameters. | ||
134 | * | ||
135 | * @param[in] argsp the list of arguments | ||
136 | * @return The function return value. | ||
137 | */ | ||
138 | msg_t __ch_delegate_fn4(va_list *argsp) { | ||
139 | delegate_fn4_t fn4 = (delegate_fn4_t)va_arg(*argsp, delegate_fn4_t); | ||
140 | msg_t p1 = (msg_t)va_arg(*argsp, msg_t); | ||
141 | msg_t p2 = (msg_t)va_arg(*argsp, msg_t); | ||
142 | msg_t p3 = (msg_t)va_arg(*argsp, msg_t); | ||
143 | msg_t p4 = (msg_t)va_arg(*argsp, msg_t); | ||
144 | return fn4(p1, p2, p3, p4); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * @brief Triggers a function call on a delegate thread. | ||
149 | * @note The thread must be executing @p chDelegateDispatchTimeout() in | ||
150 | * order to have the functions called. | ||
151 | * | ||
152 | * @param[in] tp pointer to the delegate thread | ||
153 | * @param[in] veneer pointer to the veneer function to be called | ||
154 | * @param[in] ... variable number of parameters | ||
155 | * @return The function return value casted to msg_t. It is | ||
156 | * garbage for functions returning @p void. | ||
157 | */ | ||
158 | msg_t chDelegateCallVeneer(thread_t *tp, delegate_veneer_t veneer, ...) { | ||
159 | va_list args; | ||
160 | call_message_t cm; | ||
161 | msg_t msg; | ||
162 | |||
163 | va_start(args, veneer); | ||
164 | |||
165 | /* Preparing the call message.*/ | ||
166 | cm.veneer = veneer; | ||
167 | cm.argsp = &args; | ||
168 | (void)cm; /* Suppresses a lint warning.*/ | ||
169 | |||
170 | /* Sending the message to the dispatcher thread, the return value is | ||
171 | contained in the returned message.*/ | ||
172 | msg = chMsgSend(tp, (msg_t)&cm); | ||
173 | |||
174 | va_end(args); | ||
175 | |||
176 | return msg; | ||
177 | } | ||
178 | |||
179 | /*lint -restore*/ | ||
180 | |||
181 | /** | ||
182 | * @brief Call messages dispatching. | ||
183 | * @details The function awaits for an incoming call messages and calls the | ||
184 | * specified functions, then it returns. In case multiple threads | ||
185 | * are sending messages then the requests are served in priority | ||
186 | * order. | ||
187 | * | ||
188 | * @api | ||
189 | */ | ||
190 | void chDelegateDispatch(void) { | ||
191 | thread_t *tp; | ||
192 | const call_message_t *cmp; | ||
193 | msg_t ret; | ||
194 | |||
195 | tp = chMsgWait(); | ||
196 | cmp = (const call_message_t *)chMsgGet(tp); | ||
197 | ret = cmp->veneer(cmp->argsp); | ||
198 | |||
199 | chMsgRelease(tp, ret); | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * @brief Call messages dispatching with timeout. | ||
204 | * @details The function awaits for an incoming call messages and calls the | ||
205 | * specified functions, then it returns. In case multiple threads | ||
206 | * are sending messages then the requests are served in priority | ||
207 | * order. | ||
208 | * | ||
209 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
210 | * the following special values are allowed: | ||
211 | * - @a TIME_INFINITE no timeout. | ||
212 | * . | ||
213 | * @return The function outcome. | ||
214 | * @retval MSG_OK if a function has been called. | ||
215 | * @retval MSG_TIMEOUT if a timeout occurred. | ||
216 | * | ||
217 | * @api | ||
218 | */ | ||
219 | msg_t chDelegateDispatchTimeout(sysinterval_t timeout) { | ||
220 | thread_t *tp; | ||
221 | const call_message_t *cmp; | ||
222 | msg_t ret; | ||
223 | |||
224 | tp = chMsgWaitTimeout(timeout); | ||
225 | if (tp == NULL) { | ||
226 | return MSG_TIMEOUT; | ||
227 | } | ||
228 | |||
229 | cmp = (const call_message_t *)chMsgGet(tp); | ||
230 | ret = cmp->veneer(cmp->argsp); | ||
231 | |||
232 | chMsgRelease(tp, ret); | ||
233 | |||
234 | return MSG_OK; | ||
235 | } | ||
236 | |||
237 | #endif /* CH_CFG_USE_DELEGATES == TRUE */ | ||
238 | |||
239 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/src/chfactory.c b/lib/chibios/os/oslib/src/chfactory.c new file mode 100644 index 000000000..9351ab151 --- /dev/null +++ b/lib/chibios/os/oslib/src/chfactory.c | |||
@@ -0,0 +1,829 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/src/chfactory.c | ||
22 | * @brief ChibiOS objects factory and registry code. | ||
23 | * | ||
24 | * @addtogroup oslib_objects_factory | ||
25 | * @details The object factory is a subsystem that allows to: | ||
26 | * - Register static objects by name. | ||
27 | * - Dynamically create objects and assign them a name. | ||
28 | * - Retrieve existing objects by name. | ||
29 | * - Free objects by reference. | ||
30 | * . | ||
31 | * Allocated OS objects are handled using a reference counter, only | ||
32 | * when all references have been released then the object memory is | ||
33 | * freed in a pool.<br> | ||
34 | * @pre This subsystem requires the @p CH_CFG_USE_MEMCORE and | ||
35 | * @p CH_CFG_USE_MEMPOOLS options to be set to @p TRUE. The | ||
36 | * option @p CH_CFG_USE_HEAP is also required if the support | ||
37 | * for variable length objects is enabled. | ||
38 | * @note Compatible with RT and NIL. | ||
39 | * @{ | ||
40 | */ | ||
41 | |||
42 | #include <string.h> | ||
43 | |||
44 | #include "ch.h" | ||
45 | |||
46 | #if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__) | ||
47 | |||
48 | /*===========================================================================*/ | ||
49 | /* Module local definitions. */ | ||
50 | /*===========================================================================*/ | ||
51 | |||
52 | /* | ||
53 | * Defaults on the best synchronization mechanism available. | ||
54 | */ | ||
55 | #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) | ||
56 | #define F_LOCK() chMtxLock(&ch_factory.mtx) | ||
57 | #define F_UNLOCK() chMtxUnlock(&ch_factory.mtx) | ||
58 | #else | ||
59 | #define F_LOCK() (void) chSemWait(&ch_factory.sem) | ||
60 | #define F_UNLOCK() chSemSignal(&ch_factory.sem) | ||
61 | #endif | ||
62 | |||
63 | /*===========================================================================*/ | ||
64 | /* Module exported variables. */ | ||
65 | /*===========================================================================*/ | ||
66 | |||
67 | /** | ||
68 | * @brief Factory object static instance. | ||
69 | * @note It is a global object because it could be accessed through | ||
70 | * a specific debugger plugin. | ||
71 | */ | ||
72 | objects_factory_t ch_factory; | ||
73 | |||
74 | /*===========================================================================*/ | ||
75 | /* Module local types. */ | ||
76 | /*===========================================================================*/ | ||
77 | |||
78 | /*===========================================================================*/ | ||
79 | /* Module local variables. */ | ||
80 | /*===========================================================================*/ | ||
81 | |||
82 | /*===========================================================================*/ | ||
83 | /* Module local functions. */ | ||
84 | /*===========================================================================*/ | ||
85 | |||
86 | static void copy_name(const char *sp, char *dp) { | ||
87 | unsigned i; | ||
88 | char c; | ||
89 | |||
90 | i = CH_CFG_FACTORY_MAX_NAMES_LENGTH; | ||
91 | do { | ||
92 | c = *sp++; | ||
93 | *dp++ = c; | ||
94 | i--; | ||
95 | } while ((c != (char)0) && (i > 0U)); | ||
96 | } | ||
97 | |||
98 | static inline void dyn_list_init(dyn_list_t *dlp) { | ||
99 | |||
100 | dlp->next = (dyn_element_t *)dlp; | ||
101 | } | ||
102 | |||
103 | static dyn_element_t *dyn_list_find(const char *name, dyn_list_t *dlp) { | ||
104 | dyn_element_t *p = dlp->next; | ||
105 | |||
106 | while (p != (dyn_element_t *)dlp) { | ||
107 | if (strncmp(p->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH) == 0) { | ||
108 | return p; | ||
109 | } | ||
110 | p = p->next; | ||
111 | } | ||
112 | |||
113 | return NULL; | ||
114 | } | ||
115 | |||
116 | static dyn_element_t *dyn_list_unlink(dyn_element_t *element, | ||
117 | dyn_list_t *dlp) { | ||
118 | dyn_element_t *prev = (dyn_element_t *)dlp; | ||
119 | |||
120 | /* Scanning the list.*/ | ||
121 | while (prev->next != (dyn_element_t *)dlp) { | ||
122 | if (prev->next == element) { | ||
123 | /* Found.*/ | ||
124 | prev->next = element->next; | ||
125 | return element; | ||
126 | } | ||
127 | |||
128 | /* Next element in the list.*/ | ||
129 | prev = prev->next; | ||
130 | } | ||
131 | |||
132 | return NULL; | ||
133 | } | ||
134 | |||
135 | #if CH_FACTORY_REQUIRES_HEAP || defined(__DOXYGEN__) | ||
136 | static dyn_element_t *dyn_create_object_heap(const char *name, | ||
137 | dyn_list_t *dlp, | ||
138 | size_t size, | ||
139 | unsigned align) { | ||
140 | dyn_element_t *dep; | ||
141 | |||
142 | chDbgCheck(name != NULL); | ||
143 | |||
144 | /* Checking if an object with this name has already been created.*/ | ||
145 | dep = dyn_list_find(name, dlp); | ||
146 | if (dep != NULL) { | ||
147 | return NULL; | ||
148 | } | ||
149 | |||
150 | /* Allocating space for the new buffer object.*/ | ||
151 | dep = (dyn_element_t *)chHeapAllocAligned(NULL, size, align); | ||
152 | if (dep == NULL) { | ||
153 | return NULL; | ||
154 | } | ||
155 | |||
156 | /* Initializing object list element.*/ | ||
157 | copy_name(name, dep->name); | ||
158 | dep->refs = (ucnt_t)1; | ||
159 | dep->next = dlp->next; | ||
160 | |||
161 | /* Updating factory list.*/ | ||
162 | dlp->next = dep; | ||
163 | |||
164 | return dep; | ||
165 | } | ||
166 | |||
167 | static void dyn_release_object_heap(dyn_element_t *dep, | ||
168 | dyn_list_t *dlp) { | ||
169 | |||
170 | chDbgCheck(dep != NULL); | ||
171 | chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number"); | ||
172 | |||
173 | dep->refs--; | ||
174 | if (dep->refs == (ucnt_t)0) { | ||
175 | dep = dyn_list_unlink(dep, dlp); | ||
176 | chHeapFree((void *)dep); | ||
177 | } | ||
178 | } | ||
179 | #endif /* CH_FACTORY_REQUIRES_HEAP */ | ||
180 | |||
181 | #if CH_FACTORY_REQUIRES_POOLS || defined(__DOXYGEN__) | ||
182 | static dyn_element_t *dyn_create_object_pool(const char *name, | ||
183 | dyn_list_t *dlp, | ||
184 | memory_pool_t *mp) { | ||
185 | dyn_element_t *dep; | ||
186 | |||
187 | chDbgCheck(name != NULL); | ||
188 | |||
189 | /* Checking if an object object with this name has already been created.*/ | ||
190 | dep = dyn_list_find(name, dlp); | ||
191 | if (dep != NULL) { | ||
192 | return NULL; | ||
193 | } | ||
194 | |||
195 | /* Allocating space for the new object.*/ | ||
196 | dep = (dyn_element_t *)chPoolAlloc(mp); | ||
197 | if (dep == NULL) { | ||
198 | return NULL; | ||
199 | } | ||
200 | |||
201 | /* Initializing object list element.*/ | ||
202 | copy_name(name, dep->name); | ||
203 | dep->refs = (ucnt_t)1; | ||
204 | dep->next = dlp->next; | ||
205 | |||
206 | /* Updating factory list.*/ | ||
207 | dlp->next = (dyn_element_t *)dep; | ||
208 | |||
209 | return dep; | ||
210 | } | ||
211 | |||
212 | static void dyn_release_object_pool(dyn_element_t *dep, | ||
213 | dyn_list_t *dlp, | ||
214 | memory_pool_t *mp) { | ||
215 | |||
216 | chDbgCheck(dep != NULL); | ||
217 | chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number"); | ||
218 | |||
219 | dep->refs--; | ||
220 | if (dep->refs == (ucnt_t)0) { | ||
221 | dep = dyn_list_unlink(dep, dlp); | ||
222 | chPoolFree(mp, (void *)dep); | ||
223 | } | ||
224 | } | ||
225 | #endif /* CH_FACTORY_REQUIRES_POOLS */ | ||
226 | |||
227 | static dyn_element_t *dyn_find_object(const char *name, dyn_list_t *dlp) { | ||
228 | dyn_element_t *dep; | ||
229 | |||
230 | chDbgCheck(name != NULL); | ||
231 | |||
232 | /* Checking if an object with this name has already been created.*/ | ||
233 | dep = dyn_list_find(name, dlp); | ||
234 | if (dep != NULL) { | ||
235 | /* Increasing references counter.*/ | ||
236 | dep->refs++; | ||
237 | } | ||
238 | |||
239 | return dep; | ||
240 | } | ||
241 | |||
242 | /*===========================================================================*/ | ||
243 | /* Module exported functions. */ | ||
244 | /*===========================================================================*/ | ||
245 | |||
246 | /** | ||
247 | * @brief Initializes the objects factory. | ||
248 | * | ||
249 | * @init | ||
250 | */ | ||
251 | void _factory_init(void) { | ||
252 | |||
253 | #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) | ||
254 | chMtxObjectInit(&ch_factory.mtx); | ||
255 | #else | ||
256 | chSemObjectInit(&ch_factory.sem, (cnt_t)1); | ||
257 | #endif | ||
258 | |||
259 | #if CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE | ||
260 | dyn_list_init(&ch_factory.obj_list); | ||
261 | chPoolObjectInit(&ch_factory.obj_pool, | ||
262 | sizeof (registered_object_t), | ||
263 | chCoreAllocAlignedI); | ||
264 | #endif | ||
265 | #if CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE | ||
266 | dyn_list_init(&ch_factory.buf_list); | ||
267 | #endif | ||
268 | #if CH_CFG_FACTORY_SEMAPHORES == TRUE | ||
269 | dyn_list_init(&ch_factory.sem_list); | ||
270 | chPoolObjectInit(&ch_factory.sem_pool, | ||
271 | sizeof (dyn_semaphore_t), | ||
272 | chCoreAllocAlignedI); | ||
273 | #endif | ||
274 | #if CH_CFG_FACTORY_MAILBOXES == TRUE | ||
275 | dyn_list_init(&ch_factory.mbx_list); | ||
276 | #endif | ||
277 | #if CH_CFG_FACTORY_OBJ_FIFOS == TRUE | ||
278 | dyn_list_init(&ch_factory.fifo_list); | ||
279 | #endif | ||
280 | #if CH_CFG_FACTORY_PIPES == TRUE | ||
281 | dyn_list_init(&ch_factory.pipe_list); | ||
282 | #endif | ||
283 | } | ||
284 | |||
285 | #if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXIGEN__) | ||
286 | /** | ||
287 | * @brief Registers a generic object. | ||
288 | * @post A reference to the registered object is returned and the | ||
289 | * reference counter is initialized to one. | ||
290 | * | ||
291 | * @param[in] name name to be assigned to the registered object | ||
292 | * @param[in] objp pointer to the object to be registered | ||
293 | * | ||
294 | * @return The reference to the registered object. | ||
295 | * @retval NULL if the object to be registered cannot be allocated or | ||
296 | * a registered object with the same name exists. | ||
297 | * | ||
298 | * @api | ||
299 | */ | ||
300 | registered_object_t *chFactoryRegisterObject(const char *name, | ||
301 | void *objp) { | ||
302 | registered_object_t *rop; | ||
303 | |||
304 | F_LOCK(); | ||
305 | |||
306 | rop = (registered_object_t *)dyn_create_object_pool(name, | ||
307 | &ch_factory.obj_list, | ||
308 | &ch_factory.obj_pool); | ||
309 | if (rop != NULL) { | ||
310 | /* Initializing registered object data.*/ | ||
311 | rop->objp = objp; | ||
312 | } | ||
313 | |||
314 | F_UNLOCK(); | ||
315 | |||
316 | return rop; | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * @brief Retrieves a registered object. | ||
321 | * @post A reference to the registered object is returned with the | ||
322 | * reference counter increased by one. | ||
323 | * | ||
324 | * @param[in] name name of the registered object | ||
325 | * | ||
326 | * @return The reference to the found registered object. | ||
327 | * @retval NULL if a registered object with the specified name | ||
328 | * does not exist. | ||
329 | * | ||
330 | * @api | ||
331 | */ | ||
332 | registered_object_t *chFactoryFindObject(const char *name) { | ||
333 | registered_object_t *rop; | ||
334 | |||
335 | F_LOCK(); | ||
336 | |||
337 | rop = (registered_object_t *)dyn_find_object(name, &ch_factory.obj_list); | ||
338 | |||
339 | F_UNLOCK(); | ||
340 | |||
341 | return rop; | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * @brief Retrieves a registered object by pointer. | ||
346 | * @post A reference to the registered object is returned with the | ||
347 | * reference counter increased by one. | ||
348 | * | ||
349 | * @param[in] objp pointer to the object to be retrieved | ||
350 | * | ||
351 | * @return The reference to the found registered object. | ||
352 | * @retval NULL if a registered object with the specified pointer | ||
353 | * does not exist. | ||
354 | * | ||
355 | * @api | ||
356 | */ | ||
357 | registered_object_t *chFactoryFindObjectByPointer(void *objp) { | ||
358 | registered_object_t *rop = (registered_object_t *)ch_factory.obj_list.next; | ||
359 | |||
360 | F_LOCK(); | ||
361 | |||
362 | while ((void *)rop != (void *)&ch_factory.obj_list) { | ||
363 | if (rop->objp == objp) { | ||
364 | rop->element.refs++; | ||
365 | |||
366 | F_UNLOCK(); | ||
367 | |||
368 | return rop; | ||
369 | } | ||
370 | rop = (registered_object_t *)rop->element.next; | ||
371 | } | ||
372 | |||
373 | F_UNLOCK(); | ||
374 | |||
375 | return NULL; | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * @brief Releases a registered object. | ||
380 | * @details The reference counter of the registered object is decreased | ||
381 | * by one, if reaches zero then the registered object memory | ||
382 | * is freed. | ||
383 | * @note The object itself is not freed, it could be static, only the | ||
384 | * allocated list element is freed. | ||
385 | * | ||
386 | * @param[in] rop registered object reference | ||
387 | * | ||
388 | * @api | ||
389 | */ | ||
390 | void chFactoryReleaseObject(registered_object_t *rop) { | ||
391 | |||
392 | F_LOCK(); | ||
393 | |||
394 | dyn_release_object_pool(&rop->element, | ||
395 | &ch_factory.obj_list, | ||
396 | &ch_factory.obj_pool); | ||
397 | |||
398 | F_UNLOCK(); | ||
399 | } | ||
400 | #endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */ | ||
401 | |||
402 | #if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXIGEN__) | ||
403 | /** | ||
404 | * @brief Creates a generic dynamic buffer object. | ||
405 | * @post A reference to the dynamic buffer object is returned and the | ||
406 | * reference counter is initialized to one. | ||
407 | * @post The dynamic buffer object is filled with zeros. | ||
408 | * | ||
409 | * @param[in] name name to be assigned to the new dynamic buffer object | ||
410 | * @param[in] size payload size of the dynamic buffer object to be created | ||
411 | * | ||
412 | * @return The reference to the created dynamic buffer object. | ||
413 | * @retval NULL if the dynamic buffer object cannot be allocated or | ||
414 | * a dynamic buffer object with the same name exists. | ||
415 | * | ||
416 | * @api | ||
417 | */ | ||
418 | dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size) { | ||
419 | dyn_buffer_t *dbp; | ||
420 | |||
421 | F_LOCK(); | ||
422 | |||
423 | dbp = (dyn_buffer_t *)dyn_create_object_heap(name, | ||
424 | &ch_factory.buf_list, | ||
425 | sizeof (dyn_buffer_t) + size, | ||
426 | CH_HEAP_ALIGNMENT); | ||
427 | if (dbp != NULL) { | ||
428 | /* Initializing buffer object data.*/ | ||
429 | memset((void *)(dbp + 1), 0, size); | ||
430 | } | ||
431 | |||
432 | F_UNLOCK(); | ||
433 | |||
434 | return dbp; | ||
435 | } | ||
436 | |||
437 | /** | ||
438 | * @brief Retrieves a dynamic buffer object. | ||
439 | * @post A reference to the dynamic buffer object is returned with the | ||
440 | * reference counter increased by one. | ||
441 | * | ||
442 | * @param[in] name name of the dynamic buffer object | ||
443 | * | ||
444 | * @return The reference to the found dynamic buffer object. | ||
445 | * @retval NULL if a dynamic buffer object with the specified name | ||
446 | * does not exist. | ||
447 | * | ||
448 | * @api | ||
449 | */ | ||
450 | dyn_buffer_t *chFactoryFindBuffer(const char *name) { | ||
451 | dyn_buffer_t *dbp; | ||
452 | |||
453 | F_LOCK(); | ||
454 | |||
455 | dbp = (dyn_buffer_t *)dyn_find_object(name, &ch_factory.buf_list); | ||
456 | |||
457 | F_UNLOCK(); | ||
458 | |||
459 | return dbp; | ||
460 | } | ||
461 | |||
462 | /** | ||
463 | * @brief Releases a dynamic buffer object. | ||
464 | * @details The reference counter of the dynamic buffer object is decreased | ||
465 | * by one, if reaches zero then the dynamic buffer object memory | ||
466 | * is freed. | ||
467 | * | ||
468 | * @param[in] dbp dynamic buffer object reference | ||
469 | * | ||
470 | * @api | ||
471 | */ | ||
472 | void chFactoryReleaseBuffer(dyn_buffer_t *dbp) { | ||
473 | |||
474 | F_LOCK(); | ||
475 | |||
476 | dyn_release_object_heap(&dbp->element, &ch_factory.buf_list); | ||
477 | |||
478 | F_UNLOCK(); | ||
479 | } | ||
480 | #endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */ | ||
481 | |||
482 | #if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__) | ||
483 | /** | ||
484 | * @brief Creates a dynamic semaphore object. | ||
485 | * @post A reference to the dynamic semaphore object is returned and the | ||
486 | * reference counter is initialized to one. | ||
487 | * @post The dynamic semaphore object is initialized and ready to use. | ||
488 | * | ||
489 | * @param[in] name name to be assigned to the new dynamic semaphore object | ||
490 | * @param[in] n dynamic semaphore object counter initialization value | ||
491 | * | ||
492 | * @return The reference to the created dynamic semaphore object. | ||
493 | * @retval NULL if the dynamic semaphore object cannot be allocated or | ||
494 | * a dynamic semaphore with the same name exists. | ||
495 | * | ||
496 | * @api | ||
497 | */ | ||
498 | dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n) { | ||
499 | dyn_semaphore_t *dsp; | ||
500 | |||
501 | F_LOCK(); | ||
502 | |||
503 | dsp = (dyn_semaphore_t *)dyn_create_object_pool(name, | ||
504 | &ch_factory.sem_list, | ||
505 | &ch_factory.sem_pool); | ||
506 | if (dsp != NULL) { | ||
507 | /* Initializing semaphore object dataa.*/ | ||
508 | chSemObjectInit(&dsp->sem, n); | ||
509 | } | ||
510 | |||
511 | F_UNLOCK(); | ||
512 | |||
513 | return dsp; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * @brief Retrieves a dynamic semaphore object. | ||
518 | * @post A reference to the dynamic semaphore object is returned with the | ||
519 | * reference counter increased by one. | ||
520 | * | ||
521 | * @param[in] name name of the dynamic semaphore object | ||
522 | * | ||
523 | * @return The reference to the found dynamic semaphore object. | ||
524 | * @retval NULL if a dynamic semaphore object with the specified name | ||
525 | * does not exist. | ||
526 | * | ||
527 | * @api | ||
528 | */ | ||
529 | dyn_semaphore_t *chFactoryFindSemaphore(const char *name) { | ||
530 | dyn_semaphore_t *dsp; | ||
531 | |||
532 | F_LOCK(); | ||
533 | |||
534 | dsp = (dyn_semaphore_t *)dyn_find_object(name, &ch_factory.sem_list); | ||
535 | |||
536 | F_UNLOCK(); | ||
537 | |||
538 | return dsp; | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * @brief Releases a dynamic semaphore object. | ||
543 | * @details The reference counter of the dynamic semaphore object is decreased | ||
544 | * by one, if reaches zero then the dynamic semaphore object memory | ||
545 | * is freed. | ||
546 | * | ||
547 | * @param[in] dsp dynamic semaphore object reference | ||
548 | * | ||
549 | * @api | ||
550 | */ | ||
551 | void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp) { | ||
552 | |||
553 | F_LOCK(); | ||
554 | |||
555 | dyn_release_object_pool(&dsp->element, | ||
556 | &ch_factory.sem_list, | ||
557 | &ch_factory.sem_pool); | ||
558 | |||
559 | F_UNLOCK(); | ||
560 | } | ||
561 | #endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */ | ||
562 | |||
563 | #if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXIGEN__) | ||
564 | /** | ||
565 | * @brief Creates a dynamic mailbox object. | ||
566 | * @post A reference to the dynamic mailbox object is returned and the | ||
567 | * reference counter is initialized to one. | ||
568 | * @post The dynamic mailbox object is initialized and ready to use. | ||
569 | * | ||
570 | * @param[in] name name to be assigned to the new dynamic mailbox object | ||
571 | * @param[in] n mailbox buffer size as number of messages | ||
572 | * | ||
573 | * @return The reference to the created dynamic mailbox object. | ||
574 | * @retval NULL if the dynamic mailbox object cannot be allocated or | ||
575 | * a dynamic mailbox object with the same name exists. | ||
576 | * | ||
577 | * @api | ||
578 | */ | ||
579 | dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n) { | ||
580 | dyn_mailbox_t *dmp; | ||
581 | |||
582 | F_LOCK(); | ||
583 | |||
584 | dmp = (dyn_mailbox_t *)dyn_create_object_heap(name, | ||
585 | &ch_factory.mbx_list, | ||
586 | sizeof (dyn_mailbox_t) + | ||
587 | (n * sizeof (msg_t)), | ||
588 | CH_HEAP_ALIGNMENT); | ||
589 | if (dmp != NULL) { | ||
590 | /* Initializing mailbox object data.*/ | ||
591 | chMBObjectInit(&dmp->mbx, (msg_t *)(dmp + 1), n); | ||
592 | } | ||
593 | |||
594 | F_UNLOCK(); | ||
595 | |||
596 | return dmp; | ||
597 | } | ||
598 | |||
599 | /** | ||
600 | * @brief Retrieves a dynamic mailbox object. | ||
601 | * @post A reference to the dynamic mailbox object is returned with the | ||
602 | * reference counter increased by one. | ||
603 | * | ||
604 | * @param[in] name name of the dynamic mailbox object | ||
605 | * | ||
606 | * @return The reference to the found dynamic mailbox object. | ||
607 | * @retval NULL if a dynamic mailbox object with the specified name | ||
608 | * does not exist. | ||
609 | * | ||
610 | * @api | ||
611 | */ | ||
612 | dyn_mailbox_t *chFactoryFindMailbox(const char *name) { | ||
613 | dyn_mailbox_t *dmp; | ||
614 | |||
615 | F_LOCK(); | ||
616 | |||
617 | dmp = (dyn_mailbox_t *)dyn_find_object(name, &ch_factory.mbx_list); | ||
618 | |||
619 | F_UNLOCK(); | ||
620 | |||
621 | return dmp; | ||
622 | } | ||
623 | |||
624 | /** | ||
625 | * @brief Releases a dynamic mailbox object. | ||
626 | * @details The reference counter of the dynamic mailbox object is decreased | ||
627 | * by one, if reaches zero then the dynamic mailbox object memory | ||
628 | * is freed. | ||
629 | * | ||
630 | * @param[in] dmp dynamic mailbox object reference | ||
631 | * | ||
632 | * @api | ||
633 | */ | ||
634 | void chFactoryReleaseMailbox(dyn_mailbox_t *dmp) { | ||
635 | |||
636 | F_LOCK(); | ||
637 | |||
638 | dyn_release_object_heap(&dmp->element, &ch_factory.mbx_list); | ||
639 | |||
640 | F_UNLOCK(); | ||
641 | } | ||
642 | #endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */ | ||
643 | |||
644 | #if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXIGEN__) | ||
645 | /** | ||
646 | * @brief Creates a dynamic "objects FIFO" object. | ||
647 | * @post A reference to the dynamic "objects FIFO" object is returned and | ||
648 | * the reference counter is initialized to one. | ||
649 | * @post The dynamic "objects FIFO" object is initialized and ready to use. | ||
650 | * | ||
651 | * @param[in] name name to be assigned to the new dynamic "objects FIFO" | ||
652 | * object | ||
653 | * @param[in] objsize size of objects | ||
654 | * @param[in] objn number of objects available | ||
655 | * @param[in] objalign required objects alignment | ||
656 | * @return The reference to the created dynamic "objects FIFO" | ||
657 | * object. | ||
658 | * @retval NULL if the dynamic "objects FIFO" object cannot be | ||
659 | * allocated or a dynamic "objects FIFO" object with | ||
660 | * the same name exists. | ||
661 | * | ||
662 | * @api | ||
663 | */ | ||
664 | dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name, | ||
665 | size_t objsize, | ||
666 | size_t objn, | ||
667 | unsigned objalign) { | ||
668 | size_t size1, size2; | ||
669 | dyn_objects_fifo_t *dofp; | ||
670 | |||
671 | F_LOCK(); | ||
672 | |||
673 | /* Enforcing alignment for the objects array.*/ | ||
674 | objsize = MEM_ALIGN_NEXT(objsize, objalign); | ||
675 | size1 = MEM_ALIGN_NEXT(sizeof (dyn_objects_fifo_t) + (objn * sizeof (msg_t)), | ||
676 | objalign); | ||
677 | size2 = objn * objsize; | ||
678 | |||
679 | /* Allocating the FIFO object with messages buffer and objects buffer.*/ | ||
680 | dofp = (dyn_objects_fifo_t *)dyn_create_object_heap(name, | ||
681 | &ch_factory.fifo_list, | ||
682 | size1 + size2, | ||
683 | objalign); | ||
684 | if (dofp != NULL) { | ||
685 | msg_t *msgbuf = (msg_t *)(dofp + 1); | ||
686 | uint8_t *objbuf = (uint8_t *)dofp + size1; | ||
687 | |||
688 | /* Initializing mailbox object data.*/ | ||
689 | chFifoObjectInitAligned(&dofp->fifo, objsize, objn, objalign, | ||
690 | (void *)objbuf, msgbuf); | ||
691 | } | ||
692 | |||
693 | F_UNLOCK(); | ||
694 | |||
695 | return dofp; | ||
696 | } | ||
697 | |||
698 | /** | ||
699 | * @brief Retrieves a dynamic "objects FIFO" object. | ||
700 | * @post A reference to the dynamic "objects FIFO" object is returned with | ||
701 | * the reference counter increased by one. | ||
702 | * | ||
703 | * @param[in] name name of the dynamic "objects FIFO" object | ||
704 | * | ||
705 | * @return The reference to the found dynamic "objects FIFO" | ||
706 | * object. | ||
707 | * @retval NULL if a dynamic "objects FIFO" object with the specified | ||
708 | * name does not exist. | ||
709 | * | ||
710 | * @api | ||
711 | */ | ||
712 | dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name) { | ||
713 | dyn_objects_fifo_t *dofp; | ||
714 | |||
715 | F_LOCK(); | ||
716 | |||
717 | dofp = (dyn_objects_fifo_t *)dyn_find_object(name, &ch_factory.fifo_list); | ||
718 | |||
719 | F_UNLOCK(); | ||
720 | |||
721 | return dofp; | ||
722 | } | ||
723 | |||
724 | /** | ||
725 | * @brief Releases a dynamic "objects FIFO" object. | ||
726 | * @details The reference counter of the dynamic "objects FIFO" object is | ||
727 | * decreased by one, if reaches zero then the dynamic "objects FIFO" | ||
728 | * object memory is freed. | ||
729 | * | ||
730 | * @param[in] dofp dynamic "objects FIFO" object reference | ||
731 | * | ||
732 | * @api | ||
733 | */ | ||
734 | void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp) { | ||
735 | |||
736 | F_LOCK(); | ||
737 | |||
738 | dyn_release_object_heap(&dofp->element, &ch_factory.fifo_list); | ||
739 | |||
740 | F_UNLOCK(); | ||
741 | } | ||
742 | #endif /* CH_CFG_FACTORY_OBJ_FIFOS = TRUE */ | ||
743 | |||
744 | #if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXIGEN__) | ||
745 | /** | ||
746 | * @brief Creates a dynamic pipe object. | ||
747 | * @post A reference to the dynamic pipe object is returned and | ||
748 | * the reference counter is initialized to one. | ||
749 | * @post The dynamic pipe object is initialized and ready to use. | ||
750 | * | ||
751 | * @param[in] name name to be assigned to the new dynamic pipe | ||
752 | * object | ||
753 | * @param[in] size pipe buffer size | ||
754 | * @return The reference to the created dynamic pipe | ||
755 | * object. | ||
756 | * @retval NULL if the dynamic pipe object cannot be | ||
757 | * allocated or a dynamic pipe object with | ||
758 | * the same name exists. | ||
759 | * | ||
760 | * @api | ||
761 | */ | ||
762 | dyn_pipe_t *chFactoryCreatePipe(const char *name, size_t size) { | ||
763 | dyn_pipe_t *dpp; | ||
764 | |||
765 | F_LOCK(); | ||
766 | |||
767 | dpp = (dyn_pipe_t *)dyn_create_object_heap(name, | ||
768 | &ch_factory.pipe_list, | ||
769 | sizeof (dyn_pipe_t) + size, | ||
770 | CH_HEAP_ALIGNMENT); | ||
771 | if (dpp != NULL) { | ||
772 | /* Initializing mailbox object data.*/ | ||
773 | chPipeObjectInit(&dpp->pipe, (uint8_t *)(dpp + 1), size); | ||
774 | } | ||
775 | |||
776 | F_UNLOCK(); | ||
777 | |||
778 | return dpp; | ||
779 | } | ||
780 | |||
781 | /** | ||
782 | * @brief Retrieves a dynamic pipe object. | ||
783 | * @post A reference to the dynamic pipe object is returned with | ||
784 | * the reference counter increased by one. | ||
785 | * | ||
786 | * @param[in] name name of the pipe object | ||
787 | * | ||
788 | * @return The reference to the found dynamic pipe | ||
789 | * object. | ||
790 | * @retval NULL if a dynamic pipe object with the specified | ||
791 | * name does not exist. | ||
792 | * | ||
793 | * @api | ||
794 | */ | ||
795 | dyn_pipe_t *chFactoryFindPipe(const char *name) { | ||
796 | dyn_pipe_t *dpp; | ||
797 | |||
798 | F_LOCK(); | ||
799 | |||
800 | dpp = (dyn_pipe_t *)dyn_find_object(name, &ch_factory.pipe_list); | ||
801 | |||
802 | F_UNLOCK(); | ||
803 | |||
804 | return dpp; | ||
805 | } | ||
806 | |||
807 | /** | ||
808 | * @brief Releases a dynamic pipe object. | ||
809 | * @details The reference counter of the dynamic pipe object is | ||
810 | * decreased by one, if reaches zero then the dynamic pipe | ||
811 | * object memory is freed. | ||
812 | * | ||
813 | * @param[in] dpp dynamic pipe object reference | ||
814 | * | ||
815 | * @api | ||
816 | */ | ||
817 | void chFactoryReleasePipe(dyn_pipe_t *dpp) { | ||
818 | |||
819 | F_LOCK(); | ||
820 | |||
821 | dyn_release_object_heap(&dpp->element, &ch_factory.pipe_list); | ||
822 | |||
823 | F_UNLOCK(); | ||
824 | } | ||
825 | #endif /* CH_CFG_FACTORY_PIPES = TRUE */ | ||
826 | |||
827 | #endif /* CH_CFG_USE_FACTORY == TRUE */ | ||
828 | |||
829 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/src/chmboxes.c b/lib/chibios/os/oslib/src/chmboxes.c new file mode 100644 index 000000000..a9f738109 --- /dev/null +++ b/lib/chibios/os/oslib/src/chmboxes.c | |||
@@ -0,0 +1,522 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/src/chmboxes.c | ||
22 | * @brief Mailboxes code. | ||
23 | * | ||
24 | * @addtogroup oslib_mailboxes | ||
25 | * @details Asynchronous messages. | ||
26 | * <h2>Operation mode</h2> | ||
27 | * A mailbox is an asynchronous communication mechanism.<br> | ||
28 | * Operations defined for mailboxes: | ||
29 | * - <b>Post</b>: Posts a message on the mailbox in FIFO order. | ||
30 | * - <b>Post Ahead</b>: Posts a message on the mailbox with urgent | ||
31 | * priority. | ||
32 | * - <b>Fetch</b>: A message is fetched from the mailbox and removed | ||
33 | * from the queue. | ||
34 | * - <b>Reset</b>: The mailbox is emptied and all the stored messages | ||
35 | * are lost. | ||
36 | * . | ||
37 | * A message is a variable of type msg_t that is guaranteed to have | ||
38 | * the same size of and be compatible with (data) pointers (anyway an | ||
39 | * explicit cast is needed). | ||
40 | * If larger messages need to be exchanged then a pointer to a | ||
41 | * structure can be posted in the mailbox but the posting side has | ||
42 | * no predefined way to know when the message has been processed. A | ||
43 | * possible approach is to allocate memory (from a memory pool for | ||
44 | * example) from the posting side and free it on the fetching side. | ||
45 | * Another approach is to set a "done" flag into the structure pointed | ||
46 | * by the message. | ||
47 | * @pre In order to use the mailboxes APIs the @p CH_CFG_USE_MAILBOXES | ||
48 | * option must be enabled in @p chconf.h. | ||
49 | * @note Compatible with RT and NIL. | ||
50 | * @{ | ||
51 | */ | ||
52 | |||
53 | #include "ch.h" | ||
54 | |||
55 | #if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__) | ||
56 | |||
57 | /*===========================================================================*/ | ||
58 | /* Module exported variables. */ | ||
59 | /*===========================================================================*/ | ||
60 | |||
61 | /*===========================================================================*/ | ||
62 | /* Module local types. */ | ||
63 | /*===========================================================================*/ | ||
64 | |||
65 | /*===========================================================================*/ | ||
66 | /* Module local variables. */ | ||
67 | /*===========================================================================*/ | ||
68 | |||
69 | /*===========================================================================*/ | ||
70 | /* Module local functions. */ | ||
71 | /*===========================================================================*/ | ||
72 | |||
73 | /*===========================================================================*/ | ||
74 | /* Module exported functions. */ | ||
75 | /*===========================================================================*/ | ||
76 | |||
77 | /** | ||
78 | * @brief Initializes a @p mailbox_t object. | ||
79 | * | ||
80 | * @param[out] mbp the pointer to the @p mailbox_t structure to be | ||
81 | * initialized | ||
82 | * @param[in] buf pointer to the messages buffer as an array of @p msg_t | ||
83 | * @param[in] n number of elements in the buffer array | ||
84 | * | ||
85 | * @init | ||
86 | */ | ||
87 | void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n) { | ||
88 | |||
89 | chDbgCheck((mbp != NULL) && (buf != NULL) && (n > (size_t)0)); | ||
90 | |||
91 | mbp->buffer = buf; | ||
92 | mbp->rdptr = buf; | ||
93 | mbp->wrptr = buf; | ||
94 | mbp->top = &buf[n]; | ||
95 | mbp->cnt = (size_t)0; | ||
96 | mbp->reset = false; | ||
97 | chThdQueueObjectInit(&mbp->qw); | ||
98 | chThdQueueObjectInit(&mbp->qr); | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * @brief Resets a @p mailbox_t object. | ||
103 | * @details All the waiting threads are resumed with status @p MSG_RESET and | ||
104 | * the queued messages are lost. | ||
105 | * @post The mailbox is in reset state, all operations will fail and | ||
106 | * return @p MSG_RESET until the mailbox is enabled again using | ||
107 | * @p chMBResumeX(). | ||
108 | * | ||
109 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
110 | * | ||
111 | * @api | ||
112 | */ | ||
113 | void chMBReset(mailbox_t *mbp) { | ||
114 | |||
115 | chSysLock(); | ||
116 | chMBResetI(mbp); | ||
117 | chSchRescheduleS(); | ||
118 | chSysUnlock(); | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * @brief Resets a @p mailbox_t object. | ||
123 | * @details All the waiting threads are resumed with status @p MSG_RESET and | ||
124 | * the queued messages are lost. | ||
125 | * @post The mailbox is in reset state, all operations will fail and | ||
126 | * return @p MSG_RESET until the mailbox is enabled again using | ||
127 | * @p chMBResumeX(). | ||
128 | * | ||
129 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
130 | * | ||
131 | * @api | ||
132 | */ | ||
133 | void chMBResetI(mailbox_t *mbp) { | ||
134 | |||
135 | chDbgCheckClassI(); | ||
136 | chDbgCheck(mbp != NULL); | ||
137 | |||
138 | mbp->wrptr = mbp->buffer; | ||
139 | mbp->rdptr = mbp->buffer; | ||
140 | mbp->cnt = (size_t)0; | ||
141 | mbp->reset = true; | ||
142 | chThdDequeueAllI(&mbp->qw, MSG_RESET); | ||
143 | chThdDequeueAllI(&mbp->qr, MSG_RESET); | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * @brief Posts a message into a mailbox. | ||
148 | * @details The invoking thread waits until a empty slot in the mailbox becomes | ||
149 | * available or the specified time runs out. | ||
150 | * | ||
151 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
152 | * @param[in] msg the message to be posted on the mailbox | ||
153 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
154 | * the following special values are allowed: | ||
155 | * - @a TIME_IMMEDIATE immediate timeout. | ||
156 | * - @a TIME_INFINITE no timeout. | ||
157 | * . | ||
158 | * @return The operation status. | ||
159 | * @retval MSG_OK if a message has been correctly posted. | ||
160 | * @retval MSG_RESET if the mailbox has been reset. | ||
161 | * @retval MSG_TIMEOUT if the operation has timed out. | ||
162 | * | ||
163 | * @api | ||
164 | */ | ||
165 | msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { | ||
166 | msg_t rdymsg; | ||
167 | |||
168 | chSysLock(); | ||
169 | rdymsg = chMBPostTimeoutS(mbp, msg, timeout); | ||
170 | chSysUnlock(); | ||
171 | |||
172 | return rdymsg; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * @brief Posts a message into a mailbox. | ||
177 | * @details The invoking thread waits until a empty slot in the mailbox becomes | ||
178 | * available or the specified time runs out. | ||
179 | * | ||
180 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
181 | * @param[in] msg the message to be posted on the mailbox | ||
182 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
183 | * the following special values are allowed: | ||
184 | * - @a TIME_IMMEDIATE immediate timeout. | ||
185 | * - @a TIME_INFINITE no timeout. | ||
186 | * . | ||
187 | * @return The operation status. | ||
188 | * @retval MSG_OK if a message has been correctly posted. | ||
189 | * @retval MSG_RESET if the mailbox has been reset. | ||
190 | * @retval MSG_TIMEOUT if the operation has timed out. | ||
191 | * | ||
192 | * @sclass | ||
193 | */ | ||
194 | msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { | ||
195 | msg_t rdymsg; | ||
196 | |||
197 | chDbgCheckClassS(); | ||
198 | chDbgCheck(mbp != NULL); | ||
199 | |||
200 | do { | ||
201 | /* If the mailbox is in reset state then returns immediately.*/ | ||
202 | if (mbp->reset) { | ||
203 | return MSG_RESET; | ||
204 | } | ||
205 | |||
206 | /* Is there a free message slot in queue? if so then post.*/ | ||
207 | if (chMBGetFreeCountI(mbp) > (size_t)0) { | ||
208 | *mbp->wrptr++ = msg; | ||
209 | if (mbp->wrptr >= mbp->top) { | ||
210 | mbp->wrptr = mbp->buffer; | ||
211 | } | ||
212 | mbp->cnt++; | ||
213 | |||
214 | /* If there is a reader waiting then makes it ready.*/ | ||
215 | chThdDequeueNextI(&mbp->qr, MSG_OK); | ||
216 | chSchRescheduleS(); | ||
217 | |||
218 | return MSG_OK; | ||
219 | } | ||
220 | |||
221 | /* No space in the queue, waiting for a slot to become available.*/ | ||
222 | rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout); | ||
223 | } while (rdymsg == MSG_OK); | ||
224 | |||
225 | return rdymsg; | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * @brief Posts a message into a mailbox. | ||
230 | * @details This variant is non-blocking, the function returns a timeout | ||
231 | * condition if the queue is full. | ||
232 | * | ||
233 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
234 | * @param[in] msg the message to be posted on the mailbox | ||
235 | * @return The operation status. | ||
236 | * @retval MSG_OK if a message has been correctly posted. | ||
237 | * @retval MSG_RESET if the mailbox has been reset. | ||
238 | * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be | ||
239 | * posted. | ||
240 | * | ||
241 | * @iclass | ||
242 | */ | ||
243 | msg_t chMBPostI(mailbox_t *mbp, msg_t msg) { | ||
244 | |||
245 | chDbgCheckClassI(); | ||
246 | chDbgCheck(mbp != NULL); | ||
247 | |||
248 | /* If the mailbox is in reset state then returns immediately.*/ | ||
249 | if (mbp->reset) { | ||
250 | return MSG_RESET; | ||
251 | } | ||
252 | |||
253 | /* Is there a free message slot in queue? if so then post.*/ | ||
254 | if (chMBGetFreeCountI(mbp) > (size_t)0) { | ||
255 | *mbp->wrptr++ = msg; | ||
256 | if (mbp->wrptr >= mbp->top) { | ||
257 | mbp->wrptr = mbp->buffer; | ||
258 | } | ||
259 | mbp->cnt++; | ||
260 | |||
261 | /* If there is a reader waiting then makes it ready.*/ | ||
262 | chThdDequeueNextI(&mbp->qr, MSG_OK); | ||
263 | |||
264 | return MSG_OK; | ||
265 | } | ||
266 | |||
267 | /* No space, immediate timeout.*/ | ||
268 | return MSG_TIMEOUT; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * @brief Posts an high priority message into a mailbox. | ||
273 | * @details The invoking thread waits until a empty slot in the mailbox becomes | ||
274 | * available or the specified time runs out. | ||
275 | * | ||
276 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
277 | * @param[in] msg the message to be posted on the mailbox | ||
278 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
279 | * the following special values are allowed: | ||
280 | * - @a TIME_IMMEDIATE immediate timeout. | ||
281 | * - @a TIME_INFINITE no timeout. | ||
282 | * . | ||
283 | * @return The operation status. | ||
284 | * @retval MSG_OK if a message has been correctly posted. | ||
285 | * @retval MSG_RESET if the mailbox has been reset. | ||
286 | * @retval MSG_TIMEOUT if the operation has timed out. | ||
287 | * | ||
288 | * @api | ||
289 | */ | ||
290 | msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { | ||
291 | msg_t rdymsg; | ||
292 | |||
293 | chSysLock(); | ||
294 | rdymsg = chMBPostAheadTimeoutS(mbp, msg, timeout); | ||
295 | chSysUnlock(); | ||
296 | |||
297 | return rdymsg; | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * @brief Posts an high priority message into a mailbox. | ||
302 | * @details The invoking thread waits until a empty slot in the mailbox becomes | ||
303 | * available or the specified time runs out. | ||
304 | * | ||
305 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
306 | * @param[in] msg the message to be posted on the mailbox | ||
307 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
308 | * the following special values are allowed: | ||
309 | * - @a TIME_IMMEDIATE immediate timeout. | ||
310 | * - @a TIME_INFINITE no timeout. | ||
311 | * . | ||
312 | * @return The operation status. | ||
313 | * @retval MSG_OK if a message has been correctly posted. | ||
314 | * @retval MSG_RESET if the mailbox has been reset. | ||
315 | * @retval MSG_TIMEOUT if the operation has timed out. | ||
316 | * | ||
317 | * @sclass | ||
318 | */ | ||
319 | msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { | ||
320 | msg_t rdymsg; | ||
321 | |||
322 | chDbgCheckClassS(); | ||
323 | chDbgCheck(mbp != NULL); | ||
324 | |||
325 | do { | ||
326 | /* If the mailbox is in reset state then returns immediately.*/ | ||
327 | if (mbp->reset) { | ||
328 | return MSG_RESET; | ||
329 | } | ||
330 | |||
331 | /* Is there a free message slot in queue? if so then post.*/ | ||
332 | if (chMBGetFreeCountI(mbp) > (size_t)0) { | ||
333 | if (--mbp->rdptr < mbp->buffer) { | ||
334 | mbp->rdptr = mbp->top - 1; | ||
335 | } | ||
336 | *mbp->rdptr = msg; | ||
337 | mbp->cnt++; | ||
338 | |||
339 | /* If there is a reader waiting then makes it ready.*/ | ||
340 | chThdDequeueNextI(&mbp->qr, MSG_OK); | ||
341 | chSchRescheduleS(); | ||
342 | |||
343 | return MSG_OK; | ||
344 | } | ||
345 | |||
346 | /* No space in the queue, waiting for a slot to become available.*/ | ||
347 | rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout); | ||
348 | } while (rdymsg == MSG_OK); | ||
349 | |||
350 | return rdymsg; | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * @brief Posts an high priority message into a mailbox. | ||
355 | * @details This variant is non-blocking, the function returns a timeout | ||
356 | * condition if the queue is full. | ||
357 | * | ||
358 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
359 | * @param[in] msg the message to be posted on the mailbox | ||
360 | * @return The operation status. | ||
361 | * @retval MSG_OK if a message has been correctly posted. | ||
362 | * @retval MSG_RESET if the mailbox has been reset. | ||
363 | * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be | ||
364 | * posted. | ||
365 | * | ||
366 | * @iclass | ||
367 | */ | ||
368 | msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg) { | ||
369 | |||
370 | chDbgCheckClassI(); | ||
371 | chDbgCheck(mbp != NULL); | ||
372 | |||
373 | /* If the mailbox is in reset state then returns immediately.*/ | ||
374 | if (mbp->reset) { | ||
375 | return MSG_RESET; | ||
376 | } | ||
377 | |||
378 | /* Is there a free message slot in queue? if so then post.*/ | ||
379 | if (chMBGetFreeCountI(mbp) > (size_t)0) { | ||
380 | if (--mbp->rdptr < mbp->buffer) { | ||
381 | mbp->rdptr = mbp->top - 1; | ||
382 | } | ||
383 | *mbp->rdptr = msg; | ||
384 | mbp->cnt++; | ||
385 | |||
386 | /* If there is a reader waiting then makes it ready.*/ | ||
387 | chThdDequeueNextI(&mbp->qr, MSG_OK); | ||
388 | |||
389 | return MSG_OK; | ||
390 | } | ||
391 | |||
392 | /* No space, immediate timeout.*/ | ||
393 | return MSG_TIMEOUT; | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * @brief Retrieves a message from a mailbox. | ||
398 | * @details The invoking thread waits until a message is posted in the mailbox | ||
399 | * or the specified time runs out. | ||
400 | * | ||
401 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
402 | * @param[out] msgp pointer to a message variable for the received message | ||
403 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
404 | * the following special values are allowed: | ||
405 | * - @a TIME_IMMEDIATE immediate timeout. | ||
406 | * - @a TIME_INFINITE no timeout. | ||
407 | * . | ||
408 | * @return The operation status. | ||
409 | * @retval MSG_OK if a message has been correctly fetched. | ||
410 | * @retval MSG_RESET if the mailbox has been reset. | ||
411 | * @retval MSG_TIMEOUT if the operation has timed out. | ||
412 | * | ||
413 | * @api | ||
414 | */ | ||
415 | msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) { | ||
416 | msg_t rdymsg; | ||
417 | |||
418 | chSysLock(); | ||
419 | rdymsg = chMBFetchTimeoutS(mbp, msgp, timeout); | ||
420 | chSysUnlock(); | ||
421 | |||
422 | return rdymsg; | ||
423 | } | ||
424 | |||
425 | /** | ||
426 | * @brief Retrieves a message from a mailbox. | ||
427 | * @details The invoking thread waits until a message is posted in the mailbox | ||
428 | * or the specified time runs out. | ||
429 | * | ||
430 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
431 | * @param[out] msgp pointer to a message variable for the received message | ||
432 | * @param[in] timeout the number of ticks before the operation timeouts, | ||
433 | * the following special values are allowed: | ||
434 | * - @a TIME_IMMEDIATE immediate timeout. | ||
435 | * - @a TIME_INFINITE no timeout. | ||
436 | * . | ||
437 | * @return The operation status. | ||
438 | * @retval MSG_OK if a message has been correctly fetched. | ||
439 | * @retval MSG_RESET if the mailbox has been reset. | ||
440 | * @retval MSG_TIMEOUT if the operation has timed out. | ||
441 | * | ||
442 | * @sclass | ||
443 | */ | ||
444 | msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) { | ||
445 | msg_t rdymsg; | ||
446 | |||
447 | chDbgCheckClassS(); | ||
448 | chDbgCheck((mbp != NULL) && (msgp != NULL)); | ||
449 | |||
450 | do { | ||
451 | /* If the mailbox is in reset state then returns immediately.*/ | ||
452 | if (mbp->reset) { | ||
453 | return MSG_RESET; | ||
454 | } | ||
455 | |||
456 | /* Is there a message in queue? if so then fetch.*/ | ||
457 | if (chMBGetUsedCountI(mbp) > (size_t)0) { | ||
458 | *msgp = *mbp->rdptr++; | ||
459 | if (mbp->rdptr >= mbp->top) { | ||
460 | mbp->rdptr = mbp->buffer; | ||
461 | } | ||
462 | mbp->cnt--; | ||
463 | |||
464 | /* If there is a writer waiting then makes it ready.*/ | ||
465 | chThdDequeueNextI(&mbp->qw, MSG_OK); | ||
466 | chSchRescheduleS(); | ||
467 | |||
468 | return MSG_OK; | ||
469 | } | ||
470 | |||
471 | /* No message in the queue, waiting for a message to become available.*/ | ||
472 | rdymsg = chThdEnqueueTimeoutS(&mbp->qr, timeout); | ||
473 | } while (rdymsg == MSG_OK); | ||
474 | |||
475 | return rdymsg; | ||
476 | } | ||
477 | |||
478 | /** | ||
479 | * @brief Retrieves a message from a mailbox. | ||
480 | * @details This variant is non-blocking, the function returns a timeout | ||
481 | * condition if the queue is empty. | ||
482 | * | ||
483 | * @param[in] mbp the pointer to an initialized @p mailbox_t object | ||
484 | * @param[out] msgp pointer to a message variable for the received message | ||
485 | * @return The operation status. | ||
486 | * @retval MSG_OK if a message has been correctly fetched. | ||
487 | * @retval MSG_RESET if the mailbox has been reset. | ||
488 | * @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be | ||
489 | * fetched. | ||
490 | * | ||
491 | * @iclass | ||
492 | */ | ||
493 | msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp) { | ||
494 | |||
495 | chDbgCheckClassI(); | ||
496 | chDbgCheck((mbp != NULL) && (msgp != NULL)); | ||
497 | |||
498 | /* If the mailbox is in reset state then returns immediately.*/ | ||
499 | if (mbp->reset) { | ||
500 | return MSG_RESET; | ||
501 | } | ||
502 | |||
503 | /* Is there a message in queue? if so then fetch.*/ | ||
504 | if (chMBGetUsedCountI(mbp) > (size_t)0) { | ||
505 | *msgp = *mbp->rdptr++; | ||
506 | if (mbp->rdptr >= mbp->top) { | ||
507 | mbp->rdptr = mbp->buffer; | ||
508 | } | ||
509 | mbp->cnt--; | ||
510 | |||
511 | /* If there is a writer waiting then makes it ready.*/ | ||
512 | chThdDequeueNextI(&mbp->qw, MSG_OK); | ||
513 | |||
514 | return MSG_OK; | ||
515 | } | ||
516 | |||
517 | /* No message, immediate timeout.*/ | ||
518 | return MSG_TIMEOUT; | ||
519 | } | ||
520 | #endif /* CH_CFG_USE_MAILBOXES == TRUE */ | ||
521 | |||
522 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/src/chmemcore.c b/lib/chibios/os/oslib/src/chmemcore.c new file mode 100644 index 000000000..0c081aa48 --- /dev/null +++ b/lib/chibios/os/oslib/src/chmemcore.c | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/src/chmemcore.c | ||
22 | * @brief Core memory manager code. | ||
23 | * | ||
24 | * @addtogroup oslib_memcore | ||
25 | * @details Core Memory Manager related APIs and services. | ||
26 | * <h2>Operation mode</h2> | ||
27 | * The core memory manager is a simplified allocator that only | ||
28 | * allows to allocate memory blocks without the possibility to | ||
29 | * free them.<br> | ||
30 | * This allocator is meant as a memory blocks provider for the | ||
31 | * other allocators such as: | ||
32 | * - C-Runtime allocator (through a compiler specific adapter module). | ||
33 | * - Heap allocator (see @ref oslib_memheaps). | ||
34 | * - Memory pools allocator (see @ref oslib_mempools). | ||
35 | * . | ||
36 | * By having a centralized memory provider the various allocators | ||
37 | * can coexist and share the main memory.<br> | ||
38 | * This allocator, alone, is also useful for very simple | ||
39 | * applications that just require a simple way to get memory | ||
40 | * blocks. | ||
41 | * @pre In order to use the core memory manager APIs the @p CH_CFG_USE_MEMCORE | ||
42 | * option must be enabled in @p chconf.h. | ||
43 | * @note Compatible with RT and NIL. | ||
44 | * @{ | ||
45 | */ | ||
46 | |||
47 | #include "ch.h" | ||
48 | |||
49 | #if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__) | ||
50 | |||
51 | /*===========================================================================*/ | ||
52 | /* Module exported variables. */ | ||
53 | /*===========================================================================*/ | ||
54 | |||
55 | /** | ||
56 | * @brief Memory core descriptor. | ||
57 | */ | ||
58 | memcore_t ch_memcore; | ||
59 | |||
60 | /*===========================================================================*/ | ||
61 | /* Module local types. */ | ||
62 | /*===========================================================================*/ | ||
63 | |||
64 | /*===========================================================================*/ | ||
65 | /* Module local variables. */ | ||
66 | /*===========================================================================*/ | ||
67 | |||
68 | /*===========================================================================*/ | ||
69 | /* Module local functions. */ | ||
70 | /*===========================================================================*/ | ||
71 | |||
72 | /*===========================================================================*/ | ||
73 | /* Module exported functions. */ | ||
74 | /*===========================================================================*/ | ||
75 | |||
76 | /** | ||
77 | * @brief Low level memory manager initialization. | ||
78 | * | ||
79 | * @notapi | ||
80 | */ | ||
81 | void _core_init(void) { | ||
82 | #if CH_CFG_MEMCORE_SIZE == 0 | ||
83 | extern uint8_t __heap_base__[]; | ||
84 | extern uint8_t __heap_end__[]; | ||
85 | |||
86 | /*lint -save -e9033 [10.8] Required cast operations.*/ | ||
87 | ch_memcore.basemem = __heap_base__; | ||
88 | ch_memcore.topmem = __heap_end__; | ||
89 | /*lint restore*/ | ||
90 | #else | ||
91 | static uint8_t static_heap[CH_CFG_MEMCORE_SIZE]; | ||
92 | |||
93 | ch_memcore.basemem = &static_heap[0]; | ||
94 | ch_memcore.topmem = &static_heap[CH_CFG_MEMCORE_SIZE]; | ||
95 | #endif | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * @brief Allocates a memory block starting from the lowest address upward. | ||
100 | * @details This function allocates a block of @p offset + @p size bytes. The | ||
101 | * returned pointer has @p offset bytes before its address and | ||
102 | * @p size bytes after. | ||
103 | * | ||
104 | * @param[in] size the size of the block to be allocated. | ||
105 | * @param[in] align desired memory alignment | ||
106 | * @param[in] offset aligned pointer offset | ||
107 | * @return A pointer to the allocated memory block. | ||
108 | * @retval NULL allocation failed, core memory exhausted. | ||
109 | * | ||
110 | * @iclass | ||
111 | */ | ||
112 | void *chCoreAllocFromBaseI(size_t size, unsigned align, size_t offset) { | ||
113 | uint8_t *p, *next; | ||
114 | |||
115 | chDbgCheckClassI(); | ||
116 | chDbgCheck(MEM_IS_VALID_ALIGNMENT(align)); | ||
117 | |||
118 | p = (uint8_t *)MEM_ALIGN_NEXT(ch_memcore.basemem + offset, align); | ||
119 | next = p + size; | ||
120 | |||
121 | /* Considering also the case where there is numeric overflow.*/ | ||
122 | if ((next > ch_memcore.topmem) || (next < ch_memcore.basemem)) { | ||
123 | return NULL; | ||
124 | } | ||
125 | |||
126 | ch_memcore.basemem = next; | ||
127 | |||
128 | return p; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * @brief Allocates a memory block starting from the top address downward. | ||
133 | * @details This function allocates a block of @p offset + @p size bytes. The | ||
134 | * returned pointer has @p offset bytes before its address and | ||
135 | * @p size bytes after. | ||
136 | * | ||
137 | * @param[in] size the size of the block to be allocated. | ||
138 | * @param[in] align desired memory alignment | ||
139 | * @param[in] offset aligned pointer offset | ||
140 | * @return A pointer to the allocated memory block. | ||
141 | * @retval NULL allocation failed, core memory exhausted. | ||
142 | * | ||
143 | * @iclass | ||
144 | */ | ||
145 | void *chCoreAllocFromTopI(size_t size, unsigned align, size_t offset) { | ||
146 | uint8_t *p, *prev; | ||
147 | |||
148 | chDbgCheckClassI(); | ||
149 | chDbgCheck(MEM_IS_VALID_ALIGNMENT(align)); | ||
150 | |||
151 | p = (uint8_t *)MEM_ALIGN_PREV(ch_memcore.topmem - size, align); | ||
152 | prev = p - offset; | ||
153 | |||
154 | /* Considering also the case where there is numeric overflow.*/ | ||
155 | if ((prev < ch_memcore.basemem) || (prev > ch_memcore.topmem)) { | ||
156 | return NULL; | ||
157 | } | ||
158 | |||
159 | ch_memcore.topmem = prev; | ||
160 | |||
161 | return p; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * @brief Allocates a memory block starting from the lowest address upward. | ||
166 | * @details This function allocates a block of @p offset + @p size bytes. The | ||
167 | * returned pointer has @p offset bytes before its address and | ||
168 | * @p size bytes after. | ||
169 | * | ||
170 | * @param[in] size the size of the block to be allocated. | ||
171 | * @param[in] align desired memory alignment | ||
172 | * @param[in] offset aligned pointer offset | ||
173 | * @return A pointer to the allocated memory block. | ||
174 | * @retval NULL allocation failed, core memory exhausted. | ||
175 | * | ||
176 | * @api | ||
177 | */ | ||
178 | void *chCoreAllocFromBase(size_t size, unsigned align, size_t offset) { | ||
179 | void *p; | ||
180 | |||
181 | chSysLock(); | ||
182 | p = chCoreAllocFromBaseI(size, align, offset); | ||
183 | chSysUnlock(); | ||
184 | |||
185 | return p; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * @brief Allocates a memory block starting from the top address downward. | ||
190 | * @details This function allocates a block of @p offset + @p size bytes. The | ||
191 | * returned pointer has @p offset bytes before its address and | ||
192 | * @p size bytes after. | ||
193 | * | ||
194 | * @param[in] size the size of the block to be allocated. | ||
195 | * @param[in] align desired memory alignment | ||
196 | * @param[in] offset aligned pointer offset | ||
197 | * @return A pointer to the allocated memory block. | ||
198 | * @retval NULL allocation failed, core memory exhausted. | ||
199 | * | ||
200 | * @api | ||
201 | */ | ||
202 | void *chCoreAllocFromTop(size_t size, unsigned align, size_t offset) { | ||
203 | void *p; | ||
204 | |||
205 | chSysLock(); | ||
206 | p = chCoreAllocFromTopI(size, align, offset); | ||
207 | chSysUnlock(); | ||
208 | |||
209 | return p; | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * @brief Core memory status. | ||
214 | * | ||
215 | * @return The size, in bytes, of the free core memory. | ||
216 | * | ||
217 | * @xclass | ||
218 | */ | ||
219 | size_t chCoreGetStatusX(void) { | ||
220 | |||
221 | /*lint -save -e9033 [10.8] The cast is safe.*/ | ||
222 | return (size_t)(ch_memcore.topmem - ch_memcore.basemem); | ||
223 | /*lint -restore*/ | ||
224 | } | ||
225 | #endif /* CH_CFG_USE_MEMCORE == TRUE */ | ||
226 | |||
227 | /** @} */ | ||
diff --git a/lib/chibios/os/oslib/src/chmemheaps.c b/lib/chibios/os/oslib/src/chmemheaps.c new file mode 100644 index 000000000..d5d272317 --- /dev/null +++ b/lib/chibios/os/oslib/src/chmemheaps.c | |||
@@ -0,0 +1,399 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file oslib/src/chmemheaps.c | ||
22 | * @brief Memory heaps code. | ||
23 | * | ||
24 | * @addtogroup oslib_memheaps | ||
25 | * @details Heap Allocator related APIs. | ||
26 | * <h2>Operation mode</h2> | ||
27 | * The heap allocator implements a first-fit strategy and its APIs | ||
28 | * are functionally equivalent to the usual @p malloc() and @p free() | ||
29 | * library functions. The main difference is that the OS heap APIs | ||
30 | * are guaranteed to be thread safe and there is the ability to | ||
31 | * return memory blocks aligned to arbitrary powers of two.<br> | ||
32 | * @pre In order to use the heap APIs the @p CH_CFG_USE_HEAP option must | ||
33 | * be enabled in @p chconf.h. | ||
34 | * @note Compatible with RT and NIL. | ||
35 | * @{ | ||
36 | */ | ||
37 | |||
38 | #include "ch.h" | ||
39 | |||
40 | #if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__) | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Module local definitions. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /* | ||
47 | * Defaults on the best synchronization mechanism available. | ||
48 | */ | ||
49 | #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) | ||
50 | #define H_LOCK(h) chMtxLock(&(h)->mtx) | ||
51 | #define H_UNLOCK(h) chMtxUnlock(&(h)->mtx) | ||
52 | #else | ||
53 | #define H_LOCK(h) (void) chSemWait(&(h)->sem) | ||
54 | #define H_UNLOCK(h) chSemSignal(&(h)->sem) | ||
55 | #endif | ||
56 | |||
57 | #define H_BLOCK(hp) ((hp) + 1U) | ||
58 | |||
59 | #define H_LIMIT(hp) (H_BLOCK(hp) + H_PAGES(hp)) | ||
60 | |||
61 | #define H_NEXT(hp) ((hp)->free.next) | ||
62 | |||
63 | #define H_PAGES(hp) ((hp)->free.pages) | ||
64 | |||
65 | #define H_HEAP(hp) ((hp)->used.heap) | ||
66 | |||
67 | #define H_SIZE(hp) ((hp)->used.size) | ||
68 | |||
69 | /* | ||
70 | * Number of pages between two pointers in a MISRA-compatible way. | ||
71 | */ | ||
72 | #define NPAGES(p1, p2) \ | ||
73 | /*lint -save -e9033 [10.8] The cast is safe.*/ \ | ||
74 | ((size_t)((p1) - (p2))) \ | ||
75 | /*lint -restore*/ | ||
76 | |||
77 | /*===========================================================================*/ | ||
78 | /* Module exported variables. */ | ||
79 | /*===========================================================================*/ | ||
80 | |||
81 | /*===========================================================================*/ | ||
82 | /* Module local types. */ | ||
83 | /*===========================================================================*/ | ||
84 | |||
85 | /*===========================================================================*/ | ||
86 | /* Module local variables. */ | ||
87 | /*===========================================================================*/ | ||
88 | |||
89 | /** | ||
90 | * @brief Default heap descriptor. | ||
91 | */ | ||
92 | static memory_heap_t default_heap; | ||
93 | |||
94 | /*===========================================================================*/ | ||
95 | /* Module local functions. */ | ||
96 | /*===========================================================================*/ | ||
97 | |||
98 | /*===========================================================================*/ | ||
99 | /* Module exported functions. */ | ||
100 | /*===========================================================================*/ | ||
101 | |||
102 | /** | ||
103 | * @brief Initializes the default heap. | ||
104 | * | ||
105 | * @notapi | ||
106 | */ | ||
107 | void _heap_init(void) { | ||
108 | |||
109 | default_heap.provider = chCoreAllocAlignedWithOffset; | ||
110 | H_NEXT(&default_heap.header) = NULL; | ||
111 | H_PAGES(&default_heap.header) = 0; | ||
112 | #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) | ||
113 | chMtxObjectInit(&default_heap.mtx); | ||
114 | #else | ||
115 | chSemObjectInit(&default_heap.sem, (cnt_t)1); | ||
116 | #endif | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * @brief Initializes a memory heap from a static memory area. | ||
121 | * @note The heap buffer base and size are adjusted if the passed buffer | ||
122 | * is not aligned to @p CH_HEAP_ALIGNMENT. This mean that the | ||
123 | * effective heap size can be less than @p size. | ||
124 | * | ||
125 | * @param[out] heapp pointer to the memory heap descriptor to be initialized | ||
126 | * @param[in] buf heap buffer base | ||
127 | * @param[in] size heap size | ||
128 | * | ||
129 | * @init | ||
130 | */ | ||
131 | void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size) { | ||
132 | heap_header_t *hp = (heap_header_t *)MEM_ALIGN_NEXT(buf, CH_HEAP_ALIGNMENT); | ||
133 | |||
134 | chDbgCheck((heapp != NULL) && (size > 0U)); | ||
135 | |||
136 | /* Adjusting the size in case the initial block was not correctly | ||
137 | aligned.*/ | ||
138 | /*lint -save -e9033 [10.8] Required cast operations.*/ | ||
139 | size -= (size_t)((uint8_t *)hp - (uint8_t *)buf); | ||
140 | /*lint restore*/ | ||
141 | |||
142 | /* Initializing the heap header.*/ | ||
143 | heapp->provider = NULL; | ||
144 | H_NEXT(&heapp->header) = hp; | ||
145 | H_PAGES(&heapp->header) = 0; | ||
146 | H_NEXT(hp) = NULL; | ||
147 | H_PAGES(hp) = (size - sizeof (heap_header_t)) / CH_HEAP_ALIGNMENT; | ||
148 | #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) | ||
149 | chMtxObjectInit(&heapp->mtx); | ||
150 | #else | ||
151 | chSemObjectInit(&heapp->sem, (cnt_t)1); | ||
152 | #endif | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * @brief Allocates a block of memory from the heap by using the first-fit | ||
157 | * algorithm. | ||
158 | * @details The allocated block is guaranteed to be properly aligned to the | ||
159 | * specified alignment. | ||
160 | * | ||
161 | * @param[in] heapp pointer to a heap descriptor or @p NULL in order to | ||
162 | * access the default heap. | ||
163 | * @param[in] size the size of the block to be allocated. Note that the | ||
164 | * allocated block may be a bit bigger than the requested | ||
165 | * size for alignment and fragmentation reasons. | ||
166 | * @param[in] align desired memory alignment | ||
167 | * @return A pointer to the aligned allocated block. | ||
168 | * @retval NULL if the block cannot be allocated. | ||
169 | * | ||
170 | * @api | ||
171 | */ | ||
172 | void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align) { | ||
173 | heap_header_t *qp, *hp, *ahp; | ||
174 | size_t pages; | ||
175 | |||
176 | chDbgCheck((size > 0U) && MEM_IS_VALID_ALIGNMENT(align)); | ||
177 | |||
178 | /* If an heap is not specified then the default system header is used.*/ | ||
179 | if (heapp == NULL) { | ||
180 | heapp = &default_heap; | ||
181 | } | ||
182 | |||
183 | /* Minimum alignment is constrained by the heap header structure size.*/ | ||
184 | if (align < CH_HEAP_ALIGNMENT) { | ||
185 | align = CH_HEAP_ALIGNMENT; | ||
186 | } | ||
187 | |||
188 | /* Size is converted in number of elementary allocation units.*/ | ||
189 | pages = MEM_ALIGN_NEXT(size, CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT; | ||
190 | |||
191 | /* Taking heap mutex/semaphore.*/ | ||
192 | H_LOCK(heapp); | ||
193 | |||
194 | /* Start of the free blocks list.*/ | ||
195 | qp = &heapp->header; | ||
196 | while (H_NEXT(qp) != NULL) { | ||
197 | |||
198 | /* Next free block.*/ | ||
199 | hp = H_NEXT(qp); | ||
200 | |||
201 | /* Pointer aligned to the requested alignment.*/ | ||
202 | ahp = (heap_header_t *)MEM_ALIGN_NEXT(H_BLOCK(hp), align) - 1U; | ||
203 | |||
204 | if ((ahp < H_LIMIT(hp)) && (pages <= NPAGES(H_LIMIT(hp), ahp + 1U))) { | ||
205 | /* The block is large enough to contain a correctly aligned area | ||
206 | of sufficient size.*/ | ||
207 | |||
208 | if (ahp > hp) { | ||
209 | /* The block is not properly aligned, must split it.*/ | ||
210 | size_t bpages; | ||
211 | |||
212 | bpages = NPAGES(H_LIMIT(hp), H_BLOCK(ahp)); | ||
213 | H_PAGES(hp) = NPAGES(ahp, H_BLOCK(hp)); | ||
214 | if (bpages > pages) { | ||
215 | /* The block is bigger than required, must split the excess.*/ | ||
216 | heap_header_t *fp; | ||
217 | |||
218 | /* Creating the excess block.*/ | ||
219 | fp = H_BLOCK(ahp) + pages; | ||
220 | H_PAGES(fp) = (bpages - pages) - 1U; | ||
221 | |||
222 | /* Linking the excess block.*/ | ||
223 | H_NEXT(fp) = H_NEXT(hp); | ||
224 | H_NEXT(hp) = fp; | ||
225 | } | ||
226 | |||
227 | hp = ahp; | ||
228 | } | ||
229 | else { | ||
230 | /* The block is already properly aligned.*/ | ||
231 | |||
232 | if (H_PAGES(hp) == pages) { | ||
233 | /* Exact size, getting the whole block.*/ | ||
234 | H_NEXT(qp) = H_NEXT(hp); | ||
235 | } | ||
236 | else { | ||
237 | /* The block is bigger than required, must split the excess.*/ | ||
238 | heap_header_t *fp; | ||
239 | |||
240 | fp = H_BLOCK(hp) + pages; | ||
241 | H_NEXT(fp) = H_NEXT(hp); | ||
242 | H_PAGES(fp) = NPAGES(H_LIMIT(hp), H_BLOCK(fp)); | ||
243 | H_NEXT(qp) = fp; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | /* Setting in the block owner heap and size.*/ | ||
248 | H_SIZE(hp) = size; | ||
249 | H_HEAP(hp) = heapp; | ||
250 | |||
251 | /* Releasing heap mutex/semaphore.*/ | ||
252 | H_UNLOCK(heapp); | ||
253 | |||
254 | /*lint -save -e9087 [11.3] Safe cast.*/ | ||
255 | return (void *)H_BLOCK(hp); | ||
256 | /*lint -restore*/ | ||
257 | } | ||
258 | |||
259 | /* Next in the free blocks list.*/ | ||
260 | qp = hp; | ||
261 | } | ||
262 | |||
263 | /* Releasing heap mutex/semaphore.*/ | ||
264 | H_UNLOCK(heapp); | ||
265 | |||
266 | /* More memory is required, tries to get it from the associated provider | ||
267 | else fails.*/ | ||
268 | if (heapp->provider != NULL) { | ||
269 | ahp = heapp->provider(pages * CH_HEAP_ALIGNMENT, | ||
270 | align, | ||
271 | sizeof (heap_header_t)); | ||
272 | if (ahp != NULL) { | ||
273 | hp = ahp - 1U; | ||
274 | H_HEAP(hp) = heapp; | ||
275 | H_SIZE(hp) = size; | ||
276 | |||
277 | /*lint -save -e9087 [11.3] Safe cast.*/ | ||
278 | return (void *)ahp; | ||
279 | /*lint -restore*/ | ||
280 | } | ||
281 | } | ||
282 | |||
283 | return NULL; | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * @brief Frees a previously allocated memory block. | ||
288 | * | ||
289 | * @param[in] p pointer to the memory block to be freed | ||
290 | * | ||
291 | * @api | ||
292 | */ | ||
293 | void chHeapFree(void *p) { | ||
294 | heap_header_t *qp, *hp; | ||
295 | memory_heap_t *heapp; | ||
296 | |||
297 | chDbgCheck((p != NULL) && MEM_IS_ALIGNED(p, CH_HEAP_ALIGNMENT)); | ||
298 | |||
299 | /*lint -save -e9087 [11.3] Safe cast.*/ | ||
300 | hp = (heap_header_t *)p - 1U; | ||
301 | /*lint -restore*/ | ||
302 | heapp = H_HEAP(hp); | ||
303 | qp = &heapp->header; | ||
304 | |||
305 | /* Size is converted in number of elementary allocation units.*/ | ||
306 | H_PAGES(hp) = MEM_ALIGN_NEXT(H_SIZE(hp), | ||
307 | CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT; | ||
308 | |||
309 | /* Taking heap mutex/semaphore.*/ | ||
310 | H_LOCK(heapp); | ||