From 641f2c372605cf405f0dda8536b45a78e0e5e2e2 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Tue, 16 Feb 2016 09:59:21 +0000 Subject: Tree reorganization. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8899 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/common/oslib/src/chmboxes.c | 435 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 435 insertions(+) create mode 100644 os/common/oslib/src/chmboxes.c (limited to 'os/common/oslib/src/chmboxes.c') diff --git a/os/common/oslib/src/chmboxes.c b/os/common/oslib/src/chmboxes.c new file mode 100644 index 000000000..bb75fee6c --- /dev/null +++ b/os/common/oslib/src/chmboxes.c @@ -0,0 +1,435 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmboxes.c + * @brief Mailboxes code. + * + * @addtogroup mailboxes + * @details Asynchronous messages. + *

Operation mode

+ * A mailbox is an asynchronous communication mechanism.
+ * Operations defined for mailboxes: + * - Post: Posts a message on the mailbox in FIFO order. + * - Post Ahead: Posts a message on the mailbox with urgent + * priority. + * - Fetch: A message is fetched from the mailbox and removed + * from the queue. + * - Reset: The mailbox is emptied and all the stored messages + * are lost. + * . + * A message is a variable of type msg_t that is guaranteed to have + * the same size of and be compatible with (data) pointers (anyway an + * explicit cast is needed). + * If larger messages need to be exchanged then a pointer to a + * structure can be posted in the mailbox but the posting side has + * no predefined way to know when the message has been processed. A + * possible approach is to allocate memory (from a memory pool for + * example) from the posting side and free it on the fetching side. + * Another approach is to set a "done" flag into the structure pointed + * by the message. + * @pre In order to use the mailboxes APIs the @p CH_CFG_USE_MAILBOXES + * option must be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes a @p mailbox_t object. + * + * @param[out] mbp the pointer to the @p mailbox_t structure to be + * initialized + * @param[in] buf pointer to the messages buffer as an array of @p msg_t + * @param[in] n number of elements in the buffer array + * + * @init + */ +void chMBObjectInit(mailbox_t *mbp, msg_t *buf, cnt_t n) { + + chDbgCheck((mbp != NULL) && (buf != NULL) && (n > (cnt_t)0)); + + mbp->buffer = buf; + mbp->rdptr = buf; + mbp->wrptr = buf; + mbp->top = &buf[n]; + chSemObjectInit(&mbp->emptysem, n); + chSemObjectInit(&mbp->fullsem, (cnt_t)0); +} + +/** + * @brief Resets a @p mailbox_t object. + * @details All the waiting threads are resumed with status @p MSG_RESET and + * the queued messages are lost. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * + * @api + */ +void chMBReset(mailbox_t *mbp) { + + chSysLock(); + chMBResetI(mbp); + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Resets a @p mailbox_t object. + * @details All the waiting threads are resumed with status @p MSG_RESET and + * the queued messages are lost. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * + * @api + */ +void chMBResetI(mailbox_t *mbp) { + + chDbgCheckClassI(); + chDbgCheck(mbp != NULL); + + mbp->wrptr = mbp->buffer; + mbp->rdptr = mbp->buffer; + chSemResetI(&mbp->emptysem, (cnt_t)(mbp->top - mbp->buffer)); + chSemResetI(&mbp->fullsem, (cnt_t)0); +} + +/** + * @brief Posts a message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +msg_t chMBPost(mailbox_t *mbp, msg_t msg, systime_t timeout) { + msg_t rdymsg; + + chSysLock(); + rdymsg = chMBPostS(mbp, msg, timeout); + chSysUnlock(); + + return rdymsg; +} + +/** + * @brief Posts a message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +msg_t chMBPostS(mailbox_t *mbp, msg_t msg, systime_t timeout) { + msg_t rdymsg; + + chDbgCheckClassS(); + chDbgCheck(mbp != NULL); + + rdymsg = chSemWaitTimeoutS(&mbp->emptysem, timeout); + if (rdymsg == MSG_OK) { + *mbp->wrptr++ = msg; + if (mbp->wrptr >= mbp->top) { + mbp->wrptr = mbp->buffer; + } + chSemSignalI(&mbp->fullsem); + chSchRescheduleS(); + } + + return rdymsg; +} + +/** + * @brief Posts a message into a mailbox. + * @details This variant is non-blocking, the function returns a timeout + * condition if the queue is full. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be + * posted. + * + * @iclass + */ +msg_t chMBPostI(mailbox_t *mbp, msg_t msg) { + + chDbgCheckClassI(); + chDbgCheck(mbp != NULL); + + if (chSemGetCounterI(&mbp->emptysem) <= (cnt_t)0) { + return MSG_TIMEOUT; + } + + chSemFastWaitI(&mbp->emptysem); + *mbp->wrptr++ = msg; + if (mbp->wrptr >= mbp->top) { + mbp->wrptr = mbp->buffer; + } + chSemSignalI(&mbp->fullsem); + + return MSG_OK; +} + +/** + * @brief Posts an high priority message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +msg_t chMBPostAhead(mailbox_t *mbp, msg_t msg, systime_t timeout) { + msg_t rdymsg; + + chSysLock(); + rdymsg = chMBPostAheadS(mbp, msg, timeout); + chSysUnlock(); + + return rdymsg; +} + +/** + * @brief Posts an high priority message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +msg_t chMBPostAheadS(mailbox_t *mbp, msg_t msg, systime_t timeout) { + msg_t rdymsg; + + chDbgCheckClassS(); + chDbgCheck(mbp != NULL); + + rdymsg = chSemWaitTimeoutS(&mbp->emptysem, timeout); + if (rdymsg == MSG_OK) { + if (--mbp->rdptr < mbp->buffer) { + mbp->rdptr = mbp->top - 1; + } + *mbp->rdptr = msg; + chSemSignalI(&mbp->fullsem); + chSchRescheduleS(); + } + + return rdymsg; +} + +/** + * @brief Posts an high priority message into a mailbox. + * @details This variant is non-blocking, the function returns a timeout + * condition if the queue is full. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be + * posted. + * + * @iclass + */ +msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg) { + + chDbgCheckClassI(); + chDbgCheck(mbp != NULL); + + if (chSemGetCounterI(&mbp->emptysem) <= (cnt_t)0) { + return MSG_TIMEOUT; + } + chSemFastWaitI(&mbp->emptysem); + if (--mbp->rdptr < mbp->buffer) { + mbp->rdptr = mbp->top - 1; + } + *mbp->rdptr = msg; + chSemSignalI(&mbp->fullsem); + + return MSG_OK; +} + +/** + * @brief Retrieves a message from a mailbox. + * @details The invoking thread waits until a message is posted in the mailbox + * or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[out] msgp pointer to a message variable for the received message + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly fetched. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +msg_t chMBFetch(mailbox_t *mbp, msg_t *msgp, systime_t timeout) { + msg_t rdymsg; + + chSysLock(); + rdymsg = chMBFetchS(mbp, msgp, timeout); + chSysUnlock(); + + return rdymsg; +} + +/** + * @brief Retrieves a message from a mailbox. + * @details The invoking thread waits until a message is posted in the mailbox + * or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[out] msgp pointer to a message variable for the received message + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly fetched. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +msg_t chMBFetchS(mailbox_t *mbp, msg_t *msgp, systime_t timeout) { + msg_t rdymsg; + + chDbgCheckClassS(); + chDbgCheck((mbp != NULL) && (msgp != NULL)); + + rdymsg = chSemWaitTimeoutS(&mbp->fullsem, timeout); + if (rdymsg == MSG_OK) { + *msgp = *mbp->rdptr++; + if (mbp->rdptr >= mbp->top) { + mbp->rdptr = mbp->buffer; + } + chSemSignalI(&mbp->emptysem); + chSchRescheduleS(); + } + + return rdymsg; +} + +/** + * @brief Retrieves a message from a mailbox. + * @details This variant is non-blocking, the function returns a timeout + * condition if the queue is empty. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[out] msgp pointer to a message variable for the received message + * @return The operation status. + * @retval MSG_OK if a message has been correctly fetched. + * @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be + * fetched. + * + * @iclass + */ +msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp) { + + chDbgCheckClassI(); + chDbgCheck((mbp != NULL) && (msgp != NULL)); + + if (chSemGetCounterI(&mbp->fullsem) <= (cnt_t)0) { + return MSG_TIMEOUT; + } + chSemFastWaitI(&mbp->fullsem); + *msgp = *mbp->rdptr++; + if (mbp->rdptr >= mbp->top) { + mbp->rdptr = mbp->buffer; + } + chSemSignalI(&mbp->emptysem); + + return MSG_OK; +} +#endif /* CH_CFG_USE_MAILBOXES == TRUE */ + +/** @} */ -- cgit v1.2.3