ChibiOS/RT
2.5.1
chmsg.c
Go to the documentation of this file.
00001 /*
00002     ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
00003                  2011,2012 Giovanni Di Sirio.
00004 
00005     This file is part of ChibiOS/RT.
00006 
00007     ChibiOS/RT is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 3 of the License, or
00010     (at your option) any later version.
00011 
00012     ChibiOS/RT is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 /**
00022  * @file    chmsg.c
00023  * @brief   Messages code.
00024  *
00025  * @addtogroup messages
00026  * @details Synchronous inter-thread messages APIs and services.
00027  *          <h2>Operation Mode</h2>
00028  *          Synchronous messages are an easy to use and fast IPC mechanism,
00029  *          threads can both act as message servers and/or message clients,
00030  *          the mechanism allows data to be carried in both directions. Note
00031  *          that messages are not copied between the client and server threads
00032  *          but just a pointer passed so the exchange is very time
00033  *          efficient.<br>
00034  *          Messages are scalar data types of type @p msg_t that are guaranteed
00035  *          to be size compatible with data pointers. Note that on some
00036  *          architectures function pointers can be larger that @p msg_t.<br>
00037  *          Messages are usually processed in FIFO order but it is possible to
00038  *          process them in priority order by enabling the
00039  *          @p CH_USE_MESSAGES_PRIORITY option in @p chconf.h.<br>
00040  * @pre     In order to use the message APIs the @p CH_USE_MESSAGES option
00041  *          must be enabled in @p chconf.h.
00042  * @post    Enabling messages requires 6-12 (depending on the architecture)
00043  *          extra bytes in the @p Thread structure.
00044  * @{
00045  */
00046 
00047 #include "ch.h"
00048 
00049 #if CH_USE_MESSAGES || defined(__DOXYGEN__)
00050 
00051 #if CH_USE_MESSAGES_PRIORITY
00052 #define msg_insert(tp, qp) prio_insert(tp, qp)
00053 #else
00054 #define msg_insert(tp, qp) queue_insert(tp, qp)
00055 #endif
00056 
00057 /**
00058  * @brief   Sends a message to the specified thread.
00059  * @details The sender is stopped until the receiver executes a
00060  *          @p chMsgRelease()after receiving the message.
00061  *
00062  * @param[in] tp        the pointer to the thread
00063  * @param[in] msg       the message
00064  * @return              The answer message from @p chMsgRelease().
00065  *
00066  * @api
00067  */
00068 msg_t chMsgSend(Thread *tp, msg_t msg) {
00069   Thread *ctp = currp;
00070 
00071   chDbgCheck(tp != NULL, "chMsgSend");
00072 
00073   chSysLock();
00074   ctp->p_msg = msg;
00075   ctp->p_u.wtobjp = &tp->p_msgqueue;
00076   msg_insert(ctp, &tp->p_msgqueue);
00077   if (tp->p_state == THD_STATE_WTMSG)
00078     chSchReadyI(tp);
00079   chSchGoSleepS(THD_STATE_SNDMSGQ);
00080   msg = ctp->p_u.rdymsg;
00081   chSysUnlock();
00082   return msg;
00083 }
00084 
00085 /**
00086  * @brief   Suspends the thread and waits for an incoming message.
00087  * @post    After receiving a message the function @p chMsgGet() must be
00088  *          called in order to retrieve the message and then @p chMsgRelease()
00089  *          must be invoked in order to acknowledge the reception and send
00090  *          the answer.
00091  * @note    If the message is a pointer then you can assume that the data
00092  *          pointed by the message is stable until you invoke @p chMsgRelease()
00093  *          because the sending thread is suspended until then.
00094  *
00095  * @return              A reference to the thread carrying the message.
00096  *
00097  * @api
00098  */
00099 Thread *chMsgWait(void) {
00100   Thread *tp;
00101 
00102   chSysLock();
00103   if (!chMsgIsPendingI(currp))
00104     chSchGoSleepS(THD_STATE_WTMSG);
00105   tp = fifo_remove(&currp->p_msgqueue);
00106   tp->p_state = THD_STATE_SNDMSG;
00107   chSysUnlock();
00108   return tp;
00109 }
00110 
00111 /**
00112  * @brief   Releases a sender thread specifying a response message.
00113  * @pre     Invoke this function only after a message has been received
00114  *          using @p chMsgWait().
00115  *
00116  * @param[in] tp        pointer to the thread
00117  * @param[in] msg       message to be returned to the sender
00118  *
00119  * @api
00120  */
00121 void chMsgRelease(Thread *tp, msg_t msg) {
00122 
00123   chSysLock();
00124   chDbgAssert(tp->p_state == THD_STATE_SNDMSG,
00125               "chMsgRelease(), #1", "invalid state");
00126   chMsgReleaseS(tp, msg);
00127   chSysUnlock();
00128 }
00129 
00130 #endif /* CH_USE_MESSAGES */
00131 
00132 /** @} */