/* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. ChibiOS/RT 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/RT 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 as * 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_USE_MAILBOXES option * must be enabled in @p chconf.h. * @{ */ #include "ch.h" #if CH_USE_MAILBOXES || defined(__DOXYGEN__) /** * @brief Initializes a Mailbox object. * * @param[out] mbp the pointer to the Mailbox structure to be initialized * @param[in] buf the circular messages buffer * @param[in] n the buffer size as number of @p msg_t * * @init */ void chMBInit(Mailbox *mbp, msg_t *buf, cnt_t n) { chDbgCheck((mbp != NULL) && (buf != NULL) && (n > 0), "chMBInit"); mbp->mb_buffer = mbp->mb_wrptr = mbp->mb_rdptr = buf; mbp->mb_top = &buf[n]; chSemInit(&mbp->mb_emptysem, n); chSemInit(&mbp->mb_fullsem, 0); } /** * @brief Resets a Mailbox object. * @details All the waiting threads are resumed with status @p RDY_RESET and * the queued messages are lost. * * @param[in] mbp the pointer to an initialized Mailbox object * * @api */ void chMBReset(Mailbox *mbp) { chDbgCheck(mbp != NULL, "chMBReset"); chSysLock(); mbp->mb_wrptr = mbp->mb_rdptr = mbp->mb_buffer; chSemResetI(&mbp->mb_emptysem, mbp->mb_top - mbp->mb_buffer); chSemResetI(&mbp->mb_fullsem, 0); chSchRescheduleS(); chSysUnlock(); } /** * @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 Mailbox object * @param[in] msg the message to be posted on the mailbox * @param[in] time 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 RDY_OK if a message has been correctly posted. * @retval RDY_RESET if the mailbox has been reset while waiting. * @retval RDY_TIMEOUT if the operation has timed out. * * @api */ msg_t chMBPost(Mailbox *mbp, msg_t msg, systime_t time) { msg_t rdymsg; chSysLock(); rdymsg = chMBPostS(mbp, msg, time); 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 Mailbox object * @param[in] msg the message to be posted on the mailbox * @param[in] time 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 RDY_OK if a message has been correctly posted. * @retval RDY_RESET if the mailbox has been reset while waiting. * @retval RDY_TIMEOUT if the operation has timed out. * * @sclass */ msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t time) { msg_t rdymsg; chDbgCheck(mbp != NULL, "chMBPostS"); rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time); if (rdymsg == RDY_OK) { *mbp->mb_wrptr++ = msg; if (mbp->mb_wrptr >= mbp->mb_top) mbp->mb_wrptr = mbp->mb_buffer; chSemSignalI(&mbp->mb_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 Mailbox object * @param[in] msg the message to be posted on the mailbox * @return The operation status. * @retval RDY_OK if a message has been correctly posted. * @retval RDY_TIMEOUT if the mailbox is full and the message cannot be * posted. * * @iclass */ msg_t chMBPostI(Mailbox *mbp, msg_t msg) { chDbgCheck(mbp != NULL, "chMBPostI"); if (chSemGetCounterI(&mbp->mb_emptysem) <= 0) return RDY_TIMEOUT; chSemFastWaitI(&mbp->mb_emptysem); *mbp->mb_wrptr++ = msg; if (mbp->mb_wrptr >= mbp->mb_top) mbp->mb_wrptr = mbp->mb_buffer; chSemSignalI(&mbp->mb_fullsem); return RDY_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 Mailbox object * @param[in] msg the message to be posted on the mailbox * @param[in] time 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 RDY_OK if a message has been correctly posted. * @retval RDY_RESET if the mailbox has been reset while waiting. * @retval RDY_TIMEOUT if the operation has timed out. * * @api */ msg_t chMBPostAhead(Mailbox *mbp, msg_t msg, systime_t time) { msg_t rdymsg; chSysLock(); rdymsg = chMBPostAheadS(mbp, msg, time); chSysUnlock(); return rdymsg; } /** * @brief Posts an high prior
/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.

    ChibiOS/RT 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/RT 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 <http://www.gnu.org/licenses/>.
*/

/**
 * @file    chfiles.h
 * @brief   Data files.
 * @details This header defines abstract interfaces useful to access generic
 *          data files in a standardized way.
 *
 * @addtogroup data_files
 * @details This module define an abstract interface for generic data files by
 *          extending the @p BaseSequentialStream interface. Note that no code
 *          is present, data files are just abstract interface-like structures,
 *          you should look at the systems as to a set of abstract C++ classes
 *          (even if written in C). This system has the advantage to make the
 *          access to streams independent from the implementation logic.<br>
 *          The data files interface can be used as base class for high level
 *          object types such as an API for a File System implementation.
 * @{
 */

#ifndef _CHFILES_H_
#define _CHFILES_H_

/**
 * @brief   Error code from the file stream methods.
 */
#define FILE_ERROR 0xFFFFFFFFUL

/**
 * @brief   File offset type.
 */
typedef uint32_t fileoffset_t;

/**
 * @brief   BaseFileStream specific methods.
 */
#define _base_file_stream_methods                                           \
  _base_sequential_stream_methods                                           \
  /* File close method.*/                                                   \
  uint32_t (*close)(void *instance);                                        \
  /* Get last error code method.*/                                          \
  int (*geterror)(void *instance);                                          \
  /* File get size method.*/                                                \
  fileoffset_t (*getsize)(void *instance);                                  \
  /* File get current position method.*/                                    \
  fileoffset_t (*getposition)(void *instance);                              \
  /* File seek method.*/                                                    \
  fileoffset_t (*lseek)(void *instance, fileoffset_t offset);

/**
 * @brief   @p BaseFileStream specific data.
 * @note    It is empty because @p BaseFileStream is only an interface
 *          without implementation.
 */
#define _base_file_stream_data                                              \
  _base_sequential_stream_data

/**
 * @brief   @p BaseFileStream virtual methods table.
 */
struct BaseFilelStreamVMT {
  _base_file_stream_methods
};

/**
 * @extends BaseSequentialStream
 *
 * @brief   Base file stream class.
 * @details This class represents a generic file data stream.
 */
typedef struct {
  /** @brief Virtual Methods Table.*/
  const struct FileStreamVMT *vmt;
  _base_file_stream_data
} BaseFileStream;

/**
 * @brief   Base file Stream close.
 * @details The function closes a file stream.
 *
 * @param[in] ip        pointer to a @p BaseFileStream or derived class
 *
 * @api
 */
#define chFileStreamClose(ip) ((ip)->vmt->close(ip))

/**
 * @brief   Returns an implementation dependent error code.
 *
 * @param[in] ip        pointer to a @p BaseFileStream or derived class
 *
 * @api
 */
#define chFileStreamGetError ((ip)->vmt->geterror(ip))

/**
 * @brief   Returns the current file size.
 *
 * @param[in] ip        pointer to a @p BaseFileStream or derived class
 *
 * @api
 */
#define chFileStreamGetSize ((ip)->vmt->getposition(ip))

/**
 * @brief   Returns the current file pointer position.
 *
 * @param[in] ip        pointer to a @p BaseFileStream or derived class
 *
 * @api
 */
#define chFileStreamGetPosition ((ip)->vmt->getposition(ip))

/**
 * @brief   Moves the file current pointer to an absolute position.
 *
 * @param[in] ip        pointer to a @p BaseFileStream or derived class
 * @param[in] offset    new absolute position
 *
 * @api
 */
#define chFileStreamSeek ((ip)->vmt->lseek(ip, offset))

#endif /* _CHFILES_H_ */

/** @} */