ChibiOS/RT Architecture - Reference Manual - Guides |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. 00003 00004 This file is part of ChibiOS/RT. 00005 00006 ChibiOS/RT is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 ChibiOS/RT is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 --- 00020 00021 A special exception to the GPL can be applied should you wish to distribute 00022 a combined work that includes ChibiOS/RT, without being obliged to provide 00023 the source code for any proprietary components. See the file exception.txt 00024 for full details of how and when the exception can be applied. 00025 */ 00026 00027 /** 00028 * @file chmsg.c 00029 * @brief Messages code. 00030 * 00031 * @addtogroup messages 00032 * @details Synchronous inter-thread messages APIs and services. 00033 * <h2>Operation Mode</h2> 00034 * Synchronous messages are an easy to use and fast IPC mechanism, 00035 * threads can both act as message servers and/or message clients, 00036 * the mechanism allows data to be carried in both directions. Note 00037 * that messages are not copied between the client and server threads 00038 * but just a pointer passed so the exchange is very time 00039 * efficient.<br> 00040 * Messages are usually processed in FIFO order but it is possible to 00041 * process them in priority order by enabling the 00042 * @p CH_USE_MESSAGES_PRIORITY option in @p chconf.h.<br> 00043 * Applications do not need to allocate buffers for synchronous 00044 * message queues, the mechanism just requires two extra pointers in 00045 * the @p Thread structure (the message queue header).<br> 00046 * In order to use the Messages APIs the @p CH_USE_MESSAGES option 00047 * must be enabled in @p chconf.h. 00048 * @{ 00049 */ 00050 00051 #include "ch.h" 00052 00053 #if CH_USE_MESSAGES 00054 00055 #if CH_USE_MESSAGES_PRIORITY 00056 #define msg_insert(tp, qp) prio_insert(tp, qp) 00057 #else 00058 #define msg_insert(tp, qp) queue_insert(tp, qp) 00059 #endif 00060 00061 /** 00062 * @brief Sends a message to the specified thread. 00063 * @details The sender is stopped until the receiver executes a 00064 * @p chMsgRelease()after receiving the message. 00065 * 00066 * @param[in] tp the pointer to the thread 00067 * @param[in] msg the message 00068 * @return The answer message from @p chMsgRelease(). 00069 */ 00070 msg_t chMsgSend(Thread *tp, msg_t msg) { 00071 Thread *ctp = currp; 00072 00073 chDbgCheck(tp != NULL, "chMsgSend"); 00074 00075 chSysLock(); 00076 ctp->p_msg = msg; 00077 ctp->p_u.wtobjp = &tp->p_msgqueue; 00078 msg_insert(ctp, &tp->p_msgqueue); 00079 if (tp->p_state == THD_STATE_WTMSG) 00080 chSchReadyI(tp); 00081 chSchGoSleepS(THD_STATE_SNDMSG); 00082 msg = ctp->p_u.rdymsg; 00083 chSysUnlock(); 00084 return msg; 00085 } 00086 00087 /** 00088 * @brief Suspends the thread and waits for an incoming message. 00089 * @note You can assume that the data contained in the message is stable 00090 * until you invoke @p chMsgRelease() because the sending thread is 00091 * suspended until then. 00092 * 00093 * @return The pointer to the message structure. Note, it is 00094 * always the message associated to the thread on the 00095 * top of the messages queue. 00096 */ 00097 msg_t chMsgWait(void) { 00098 msg_t msg; 00099 00100 chSysLock(); 00101 if (!chMsgIsPendingI(currp)) 00102 chSchGoSleepS(THD_STATE_WTMSG); 00103 #if defined(CH_ARCHITECTURE_STM8) 00104 msg = chMsgGetI((volatile Thread *)currp); /* Temporary hack.*/ 00105 #else 00106 msg = chMsgGetI(currp); 00107 #endif 00108 chSysUnlock(); 00109 return msg; 00110 } 00111 00112 /** 00113 * @brief Returns the next message in the queue. 00114 * @note You can assume that the data pointed by the message is stable until 00115 * you invoke @p chMsgRelease() because the sending thread is 00116 * suspended until then. Always remember that the message data is not 00117 * copied between the sender and the receiver, just a pointer is 00118 * passed. 00119 * 00120 * @return The pointer to the message structure. Note, it is 00121 * always the message associated to the thread on the 00122 * top of the messages queue. 00123 * @retval NULL if the queue is empty. 00124 */ 00125 msg_t chMsgGet(void) { 00126 msg_t msg; 00127 00128 chSysLock(); 00129 msg = chMsgIsPendingI(currp) ? chMsgGetI(currp) : (msg_t)NULL; 00130 chSysUnlock(); 00131 return msg; 00132 } 00133 00134 /** 00135 * @brief Releases the thread waiting on top of the messages queue. 00136 * @note You can call this function only if there is a message already in 00137 * the queue else the result will be unpredictable (a crash most likely). 00138 * Exiting from the @p chMsgWait() ensures you have at least one 00139 * message in the queue so it is not a big deal.<br> 00140 * The condition is only tested in debug mode in order to make this 00141 * code as fast as possible. 00142 * 00143 * @param[in] msg the message returned to the message sender 00144 */ 00145 void chMsgRelease(msg_t msg) { 00146 00147 chSysLock(); 00148 chDbgAssert(chMsgIsPendingI(currp), 00149 "chMsgRelease(), #1", 00150 "no message pending"); 00151 chSchWakeupS(fifo_remove(&currp->p_msgqueue), msg); 00152 chSysUnlock(); 00153 } 00154 00155 #endif /* CH_USE_MESSAGES */ 00156 00157 /** @} */