ChibiOS 21.11.5
chmboxes.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio.
3
4 This file is part of ChibiOS.
5
6 ChibiOS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 3 of the License.
9
10 ChibiOS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file oslib/src/chmboxes.c
21 * @brief Mailboxes code.
22 *
23 * @addtogroup oslib_mailboxes
24 * @details Asynchronous messages.
25 * <h2>Operation mode</h2>
26 * A mailbox is an asynchronous communication mechanism.<br>
27 * Operations defined for mailboxes:
28 * - <b>Post</b>: Posts a message on the mailbox in FIFO order.
29 * - <b>Post Ahead</b>: Posts a message on the mailbox with urgent
30 * priority.
31 * - <b>Fetch</b>: A message is fetched from the mailbox and removed
32 * from the queue.
33 * - <b>Reset</b>: The mailbox is emptied and all the stored messages
34 * are lost.
35 * .
36 * A message is a variable of type msg_t that is guaranteed to have
37 * the same size of and be compatible with (data) pointers (anyway an
38 * explicit cast is needed).
39 * If larger messages need to be exchanged then a pointer to a
40 * structure can be posted in the mailbox but the posting side has
41 * no predefined way to know when the message has been processed. A
42 * possible approach is to allocate memory (from a memory pool for
43 * example) from the posting side and free it on the fetching side.
44 * Another approach is to set a "done" flag into the structure pointed
45 * by the message.
46 * @pre In order to use the mailboxes APIs the @p CH_CFG_USE_MAILBOXES
47 * option must be enabled in @p chconf.h.
48 * @note Compatible with RT and NIL.
49 * @{
50 */
51
52#include "ch.h"
53
54#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__)
55
56/*===========================================================================*/
57/* Module exported variables. */
58/*===========================================================================*/
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 Initializes a @p mailbox_t object.
78 *
79 * @param[out] mbp the pointer to the @p mailbox_t structure to be
80 * initialized
81 * @param[in] buf pointer to the messages buffer as an array of @p msg_t
82 * @param[in] n number of elements in the buffer array
83 *
84 * @init
85 */
86void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n) {
87
88 chDbgCheck((mbp != NULL) && (buf != NULL) && (n > (size_t)0));
89
90 mbp->buffer = buf;
91 mbp->rdptr = buf;
92 mbp->wrptr = buf;
93 mbp->top = &buf[n];
94 mbp->cnt = (size_t)0;
95 mbp->reset = false;
98}
99
100/**
101 * @brief Resets a @p mailbox_t object.
102 * @details All the waiting threads are resumed with status @p MSG_RESET and
103 * the queued messages are lost.
104 * @post The mailbox is in reset state, all operations will fail and
105 * return @p MSG_RESET until the mailbox is enabled again using
106 * @p chMBResumeX().
107 *
108 * @param[in] mbp the pointer to an initialized @p mailbox_t object
109 *
110 * @api
111 */
113
114 chSysLock();
115 chMBResetI(mbp);
117 chSysUnlock();
118}
119
120/**
121 * @brief Resets a @p mailbox_t object.
122 * @details All the waiting threads are resumed with status @p MSG_RESET and
123 * the queued messages are lost.
124 * @post The mailbox is in reset state, all operations will fail and
125 * return @p MSG_RESET until the mailbox is enabled again using
126 * @p chMBResumeX().
127 *
128 * @param[in] mbp the pointer to an initialized @p mailbox_t object
129 *
130 * @api
131 */
133
135 chDbgCheck(mbp != NULL);
136
137 mbp->wrptr = mbp->buffer;
138 mbp->rdptr = mbp->buffer;
139 mbp->cnt = (size_t)0;
140 mbp->reset = true;
143}
144
145/**
146 * @brief Posts a message into a mailbox.
147 * @details The invoking thread waits until a empty slot in the mailbox becomes
148 * available or the specified time runs out.
149 *
150 * @param[in] mbp the pointer to an initialized @p mailbox_t object
151 * @param[in] msg the message to be posted on the mailbox
152 * @param[in] timeout the number of ticks before the operation timeouts,
153 * the following special values are allowed:
154 * - @a TIME_IMMEDIATE immediate timeout.
155 * - @a TIME_INFINITE no timeout.
156 * .
157 * @return The operation status.
158 * @retval MSG_OK if a message has been correctly posted.
159 * @retval MSG_RESET if the mailbox has been reset.
160 * @retval MSG_TIMEOUT if the operation has timed out.
161 *
162 * @api
163 */
165 msg_t rdymsg;
166
167 chSysLock();
168 rdymsg = chMBPostTimeoutS(mbp, msg, timeout);
169 chSysUnlock();
170
171 return rdymsg;
172}
173
174/**
175 * @brief Posts a message into a mailbox.
176 * @details The invoking thread waits until a empty slot in the mailbox becomes
177 * available or the specified time runs out.
178 *
179 * @param[in] mbp the pointer to an initialized @p mailbox_t object
180 * @param[in] msg the message to be posted on the mailbox
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 operation status.
187 * @retval MSG_OK if a message has been correctly posted.
188 * @retval MSG_RESET if the mailbox has been reset.
189 * @retval MSG_TIMEOUT if the operation has timed out.
190 *
191 * @sclass
192 */
194 msg_t rdymsg;
195
197 chDbgCheck(mbp != NULL);
198
199 do {
200 /* If the mailbox is in reset state then returns immediately.*/
201 if (mbp->reset) {
202 return MSG_RESET;
203 }
204
205 /* Is there a free message slot in queue? if so then post.*/
206 if (chMBGetFreeCountI(mbp) > (size_t)0) {
207 *mbp->wrptr++ = msg;
208 if (mbp->wrptr >= mbp->top) {
209 mbp->wrptr = mbp->buffer;
210 }
211 mbp->cnt++;
212
213 /* If there is a reader waiting then makes it ready.*/
216
217 return MSG_OK;
218 }
219
220 /* No space in the queue, waiting for a slot to become available.*/
221 rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout);
222 } while (rdymsg == MSG_OK);
223
224 return rdymsg;
225}
226
227/**
228 * @brief Posts a message into a mailbox.
229 * @details This variant is non-blocking, the function returns a timeout
230 * condition if the queue is full.
231 *
232 * @param[in] mbp the pointer to an initialized @p mailbox_t object
233 * @param[in] msg the message to be posted on the mailbox
234 * @return The operation status.
235 * @retval MSG_OK if a message has been correctly posted.
236 * @retval MSG_RESET if the mailbox has been reset.
237 * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
238 * posted.
239 *
240 * @iclass
241 */
243
245 chDbgCheck(mbp != NULL);
246
247 /* If the mailbox is in reset state then returns immediately.*/
248 if (mbp->reset) {
249 return MSG_RESET;
250 }
251
252 /* Is there a free message slot in queue? if so then post.*/
253 if (chMBGetFreeCountI(mbp) > (size_t)0) {
254 *mbp->wrptr++ = msg;
255 if (mbp->wrptr >= mbp->top) {
256 mbp->wrptr = mbp->buffer;
257 }
258 mbp->cnt++;
259
260 /* If there is a reader waiting then makes it ready.*/
262
263 return MSG_OK;
264 }
265
266 /* No space, immediate timeout.*/
267 return MSG_TIMEOUT;
268}
269
270/**
271 * @brief Posts an high priority message into a mailbox.
272 * @details The invoking thread waits until a empty slot in the mailbox becomes
273 * available or the specified time runs out.
274 *
275 * @param[in] mbp the pointer to an initialized @p mailbox_t object
276 * @param[in] msg the message to be posted on the mailbox
277 * @param[in] timeout the number of ticks before the operation timeouts,
278 * the following special values are allowed:
279 * - @a TIME_IMMEDIATE immediate timeout.
280 * - @a TIME_INFINITE no timeout.
281 * .
282 * @return The operation status.
283 * @retval MSG_OK if a message has been correctly posted.
284 * @retval MSG_RESET if the mailbox has been reset.
285 * @retval MSG_TIMEOUT if the operation has timed out.
286 *
287 * @api
288 */
290 msg_t rdymsg;
291
292 chSysLock();
293 rdymsg = chMBPostAheadTimeoutS(mbp, msg, timeout);
294 chSysUnlock();
295
296 return rdymsg;
297}
298
299/**
300 * @brief Posts an high priority message into a mailbox.
301 * @details The invoking thread waits until a empty slot in the mailbox becomes
302 * available or the specified time runs out.
303 *
304 * @param[in] mbp the pointer to an initialized @p mailbox_t object
305 * @param[in] msg the message to be posted on the mailbox
306 * @param[in] timeout the number of ticks before the operation timeouts,
307 * the following special values are allowed:
308 * - @a TIME_IMMEDIATE immediate timeout.
309 * - @a TIME_INFINITE no timeout.
310 * .
311 * @return The operation status.
312 * @retval MSG_OK if a message has been correctly posted.
313 * @retval MSG_RESET if the mailbox has been reset.
314 * @retval MSG_TIMEOUT if the operation has timed out.
315 *
316 * @sclass
317 */
319 msg_t rdymsg;
320
322 chDbgCheck(mbp != NULL);
323
324 do {
325 /* If the mailbox is in reset state then returns immediately.*/
326 if (mbp->reset) {
327 return MSG_RESET;
328 }
329
330 /* Is there a free message slot in queue? if so then post.*/
331 if (chMBGetFreeCountI(mbp) > (size_t)0) {
332 if (--mbp->rdptr < mbp->buffer) {
333 mbp->rdptr = mbp->top - 1;
334 }
335 *mbp->rdptr = msg;
336 mbp->cnt++;
337
338 /* If there is a reader waiting then makes it ready.*/
341
342 return MSG_OK;
343 }
344
345 /* No space in the queue, waiting for a slot to become available.*/
346 rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout);
347 } while (rdymsg == MSG_OK);
348
349 return rdymsg;
350}
351
352/**
353 * @brief Posts an high priority message into a mailbox.
354 * @details This variant is non-blocking, the function returns a timeout
355 * condition if the queue is full.
356 *
357 * @param[in] mbp the pointer to an initialized @p mailbox_t object
358 * @param[in] msg the message to be posted on the mailbox
359 * @return The operation status.
360 * @retval MSG_OK if a message has been correctly posted.
361 * @retval MSG_RESET if the mailbox has been reset.
362 * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
363 * posted.
364 *
365 * @iclass
366 */
368
370 chDbgCheck(mbp != NULL);
371
372 /* If the mailbox is in reset state then returns immediately.*/
373 if (mbp->reset) {
374 return MSG_RESET;
375 }
376
377 /* Is there a free message slot in queue? if so then post.*/
378 if (chMBGetFreeCountI(mbp) > (size_t)0) {
379 if (--mbp->rdptr < mbp->buffer) {
380 mbp->rdptr = mbp->top - 1;
381 }
382 *mbp->rdptr = msg;
383 mbp->cnt++;
384
385 /* If there is a reader waiting then makes it ready.*/
387
388 return MSG_OK;
389 }
390
391 /* No space, immediate timeout.*/
392 return MSG_TIMEOUT;
393}
394
395/**
396 * @brief Retrieves a message from a mailbox.
397 * @details The invoking thread waits until a message is posted in the mailbox
398 * or the specified time runs out.
399 *
400 * @param[in] mbp the pointer to an initialized @p mailbox_t object
401 * @param[out] msgp pointer to a message variable for the received message
402 * @param[in] timeout the number of ticks before the operation timeouts,
403 * the following special values are allowed:
404 * - @a TIME_IMMEDIATE immediate timeout.
405 * - @a TIME_INFINITE no timeout.
406 * .
407 * @return The operation status.
408 * @retval MSG_OK if a message has been correctly fetched.
409 * @retval MSG_RESET if the mailbox has been reset.
410 * @retval MSG_TIMEOUT if the operation has timed out.
411 *
412 * @api
413 */
415 msg_t rdymsg;
416
417 chSysLock();
418 rdymsg = chMBFetchTimeoutS(mbp, msgp, timeout);
419 chSysUnlock();
420
421 return rdymsg;
422}
423
424/**
425 * @brief Retrieves a message from a mailbox.
426 * @details The invoking thread waits until a message is posted in the mailbox
427 * or the specified time runs out.
428 *
429 * @param[in] mbp the pointer to an initialized @p mailbox_t object
430 * @param[out] msgp pointer to a message variable for the received message
431 * @param[in] timeout the number of ticks before the operation timeouts,
432 * the following special values are allowed:
433 * - @a TIME_IMMEDIATE immediate timeout.
434 * - @a TIME_INFINITE no timeout.
435 * .
436 * @return The operation status.
437 * @retval MSG_OK if a message has been correctly fetched.
438 * @retval MSG_RESET if the mailbox has been reset.
439 * @retval MSG_TIMEOUT if the operation has timed out.
440 *
441 * @sclass
442 */
444 msg_t rdymsg;
445
447 chDbgCheck((mbp != NULL) && (msgp != NULL));
448
449 do {
450 /* If the mailbox is in reset state then returns immediately.*/
451 if (mbp->reset) {
452 return MSG_RESET;
453 }
454
455 /* Is there a message in queue? if so then fetch.*/
456 if (chMBGetUsedCountI(mbp) > (size_t)0) {
457 *msgp = *mbp->rdptr++;
458 if (mbp->rdptr >= mbp->top) {
459 mbp->rdptr = mbp->buffer;
460 }
461 mbp->cnt--;
462
463 /* If there is a writer waiting then makes it ready.*/
466
467 return MSG_OK;
468 }
469
470 /* No message in the queue, waiting for a message to become available.*/
471 rdymsg = chThdEnqueueTimeoutS(&mbp->qr, timeout);
472 } while (rdymsg == MSG_OK);
473
474 return rdymsg;
475}
476
477/**
478 * @brief Retrieves a message from a mailbox.
479 * @details This variant is non-blocking, the function returns a timeout
480 * condition if the queue is empty.
481 *
482 * @param[in] mbp the pointer to an initialized @p mailbox_t object
483 * @param[out] msgp pointer to a message variable for the received message
484 * @return The operation status.
485 * @retval MSG_OK if a message has been correctly fetched.
486 * @retval MSG_RESET if the mailbox has been reset.
487 * @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be
488 * fetched.
489 *
490 * @iclass
491 */
493
495 chDbgCheck((mbp != NULL) && (msgp != NULL));
496
497 /* If the mailbox is in reset state then returns immediately.*/
498 if (mbp->reset) {
499 return MSG_RESET;
500 }
501
502 /* Is there a message in queue? if so then fetch.*/
503 if (chMBGetUsedCountI(mbp) > (size_t)0) {
504 *msgp = *mbp->rdptr++;
505 if (mbp->rdptr >= mbp->top) {
506 mbp->rdptr = mbp->buffer;
507 }
508 mbp->cnt--;
509
510 /* If there is a writer waiting then makes it ready.*/
512
513 return MSG_OK;
514 }
515
516 /* No message, immediate timeout.*/
517 return MSG_TIMEOUT;
518}
519#endif /* CH_CFG_USE_MAILBOXES == TRUE */
520
521/** @} */
#define chThdQueueObjectInit(tqp)
Initializes a threads queue object.
#define chSysUnlock()
Leaves the kernel lock state.
#define chSysLock()
Enters the kernel lock state.
#define chDbgCheck(c)
Function parameters check.
Definition chdebug.h:117
#define chDbgCheckClassS()
Definition chdebug.h:99
#define chDbgCheckClassI()
Definition chdebug.h:98
int32_t msg_t
Definition chearly.h:87
void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n)
Initializes a mailbox_t object.
Definition chmboxes.c:86
msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout)
Retrieves a message from a mailbox.
Definition chmboxes.c:414
msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout)
Posts a message into a mailbox.
Definition chmboxes.c:164
msg_t chMBPostI(mailbox_t *mbp, msg_t msg)
Posts a message into a mailbox.
Definition chmboxes.c:242
static size_t chMBGetUsedCountI(const mailbox_t *mbp)
Returns the number of used message slots into a mailbox.
Definition chmboxes.h:151
msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout)
Posts an high priority message into a mailbox.
Definition chmboxes.c:289
static size_t chMBGetFreeCountI(const mailbox_t *mbp)
Returns the number of free message slots into a mailbox.
Definition chmboxes.h:166
void chMBResetI(mailbox_t *mbp)
Resets a mailbox_t object.
Definition chmboxes.c:132
msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout)
Posts a message into a mailbox.
Definition chmboxes.c:193
msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout)
Posts an high priority message into a mailbox.
Definition chmboxes.c:318
msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp)
Retrieves a message from a mailbox.
Definition chmboxes.c:492
msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg)
Posts an high priority message into a mailbox.
Definition chmboxes.c:367
msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout)
Retrieves a message from a mailbox.
Definition chmboxes.c:443
void chMBReset(mailbox_t *mbp)
Resets a mailbox_t object.
Definition chmboxes.c:112
void chSchRescheduleS(void)
Performs a reschedule if a higher priority thread is runnable.
Definition chschd.c:457
#define MSG_OK
Normal wakeup message.
Definition chschd.h:38
#define MSG_TIMEOUT
Wakeup caused by a timeout condition.
Definition chschd.h:39
#define MSG_RESET
Wakeup caused by a reset condition.
Definition chschd.h:41
msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout)
Enqueues the caller thread on a threads queue object.
Definition chthreads.c:867
void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg)
Dequeues and wakes up one thread from the threads queue object, if any.
Definition chthreads.c:888
void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg)
Dequeues and wakes up all threads from the threads queue object.
Definition chthreads.c:903
uint64_t sysinterval_t
Type of time interval.
Definition chtime.h:118
Structure representing a mailbox object.
Definition chmboxes.h:51
threads_queue_t qw
Queued writers.
Definition chmboxes.h:60
msg_t * wrptr
Write pointer.
Definition chmboxes.h:56
threads_queue_t qr
Queued readers.
Definition chmboxes.h:61
bool reset
True in reset state.
Definition chmboxes.h:59
msg_t * buffer
Pointer to the mailbox buffer.
Definition chmboxes.h:52
size_t cnt
Messages in queue.
Definition chmboxes.h:58
msg_t * rdptr
Read pointer.
Definition chmboxes.h:57
msg_t * top
Pointer to the location after the buffer.
Definition chmboxes.h:54