ChibiOS/RT  6.1.4
chmsg.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
3  2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
4 
5  This file is part of ChibiOS.
6 
7  ChibiOS is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation version 3 of the License.
10 
11  ChibiOS is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 /**
21  * @file rt/src/chmsg.c
22  * @brief Messages code.
23  *
24  * @addtogroup messages
25  * @details Synchronous inter-thread messages APIs and services.
26  * <h2>Operation Mode</h2>
27  * Synchronous messages are an easy to use and fast IPC mechanism,
28  * threads can both act as message servers and/or message clients,
29  * the mechanism allows data to be carried in both directions. Note
30  * that messages are not copied between the client and server threads
31  * but just a pointer passed so the exchange is very time
32  * efficient.<br>
33  * Messages are scalar data types of type @p msg_t that are guaranteed
34  * to be size compatible with data pointers. Note that on some
35  * architectures function pointers can be larger that @p msg_t.<br>
36  * Messages are usually processed in FIFO order but it is possible to
37  * process them in priority order by enabling the
38  * @p CH_CFG_USE_MESSAGES_PRIORITY option in @p chconf.h.<br>
39  * @pre In order to use the message APIs the @p CH_CFG_USE_MESSAGES option
40  * must be enabled in @p chconf.h.
41  * @post Enabling messages requires 6-12 (depending on the architecture)
42  * extra bytes in the @p thread_t structure.
43  * @{
44  */
45 
46 #include "ch.h"
47 
48 #if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
49 
50 /*===========================================================================*/
51 /* Module exported variables. */
52 /*===========================================================================*/
53 
54 /*===========================================================================*/
55 /* Module local types. */
56 /*===========================================================================*/
57 
58 /*===========================================================================*/
59 /* Module local variables. */
60 /*===========================================================================*/
61 
62 /*===========================================================================*/
63 /* Module local functions. */
64 /*===========================================================================*/
65 
66 #if CH_CFG_USE_MESSAGES_PRIORITY == TRUE
67 #define msg_insert(tp, qp) ch_sch_prio_insert(&tp->hdr.queue, qp)
68 #else
69 #define msg_insert(tp, qp) ch_queue_insert(&tp->hdr.queue, qp)
70 #endif
71 
72 /*===========================================================================*/
73 /* Module exported functions. */
74 /*===========================================================================*/
75 
76 /**
77  * @brief Sends a message to the specified thread.
78  * @details The sender is stopped until the receiver executes a
79  * @p chMsgRelease()after receiving the message.
80  *
81  * @param[in] tp the pointer to the thread
82  * @param[in] msg the message
83  * @return The answer message from @p chMsgRelease().
84  *
85  * @api
86  */
87 msg_t chMsgSend(thread_t *tp, msg_t msg) {
88  thread_t *ctp = currp;
89 
90  chDbgCheck(tp != NULL);
91 
92  chSysLock();
93  ctp->u.sentmsg = msg;
94  msg_insert(ctp, &tp->msgqueue);
95  if (tp->state == CH_STATE_WTMSG) {
96  (void) chSchReadyI(tp);
97  }
99  msg = ctp->u.rdymsg;
100  chSysUnlock();
101 
102  return msg;
103 }
104 
105 /**
106  * @brief Suspends the thread and waits for an incoming message.
107  * @post After receiving a message the function @p chMsgGet() must be
108  * called in order to retrieve the message and then @p chMsgRelease()
109  * must be invoked in order to acknowledge the reception and send
110  * the answer.
111  * @note If the message is a pointer then you can assume that the data
112  * pointed by the message is stable until you invoke @p chMsgRelease()
113  * because the sending thread is suspended until then.
114  * @note The reference counter of the sender thread is not increased, the
115  * returned pointer is a temporary reference.
116  *
117  * @return A pointer to the thread carrying the message.
118  *
119  * @sclass
120  */
122  thread_t *tp;
123 
125 
126  if (!chMsgIsPendingI(currp)) {
128  }
129  tp = (thread_t *)ch_queue_fifo_remove(&currp->msgqueue);
130  tp->state = CH_STATE_SNDMSG;
131 
132  return tp;
133 }
134 
135 /**
136  * @brief Suspends the thread and waits for an incoming message or a
137  * timeout to occur.
138  * @post After receiving a message the function @p chMsgGet() must be
139  * called in order to retrieve the message and then @p chMsgRelease()
140  * must be invoked in order to acknowledge the reception and send
141  * the answer.
142  * @note If the message is a pointer then you can assume that the data
143  * pointed by the message is stable until you invoke @p chMsgRelease()
144  * because the sending thread is suspended until then.
145  * @note The reference counter of the sender thread is not increased, the
146  * returned pointer is a temporary reference.
147  *
148  * @param[in] timeout the number of ticks before the operation timeouts,
149  * the following special values are allowed:
150  * - @a TIME_INFINITE no timeout.
151  * .
152  * @return A pointer to the thread carrying the message.
153  * @retval NULL if a timeout occurred.
154  *
155  * @sclass
156  */
158  thread_t *tp;
159 
161 
162  if (!chMsgIsPendingI(currp)) {
163  if (chSchGoSleepTimeoutS(CH_STATE_WTMSG, timeout) != MSG_OK) {
164  return NULL;
165  }
166  }
167  tp = (thread_t *)ch_queue_fifo_remove(&currp->msgqueue);
168  tp->state = CH_STATE_SNDMSG;
169 
170  return tp;
171 }
172 
173 /**
174  * @brief Poll to check for an incoming message.
175  * @post If a message is available the function @p chMsgGet() must be
176  * called in order to retrieve the message and then @p chMsgRelease()
177  * must be invoked in order to acknowledge the reception and send
178  * the answer.
179  * @note If the message is a pointer then you can assume that the data
180  * pointed by the message is stable until you invoke @p chMsgRelease()
181  * because the sending thread is suspended until then.
182  * @note The reference counter of the sender thread is not increased, the
183  * returned pointer is a temporary reference.
184  *
185  * @return Result of the poll.
186  * @retval NULL if no incoming message waiting.
187  *
188  * @sclass
189  */
191  thread_t *tp = NULL;
192 
193  if (chMsgIsPendingI(currp)) {
194  tp = (thread_t *)ch_queue_fifo_remove(&currp->msgqueue);
195  tp->state = CH_STATE_SNDMSG;
196  }
197 
198  return tp;
199 }
200 
201 /**
202  * @brief Releases a sender thread specifying a response message.
203  * @pre Invoke this function only after a message has been received
204  * using @p chMsgWait().
205  *
206  * @param[in] tp pointer to the thread
207  * @param[in] msg message to be returned to the sender
208  *
209  * @api
210  */
211 void chMsgRelease(thread_t *tp, msg_t msg) {
212 
213  chSysLock();
214  chDbgAssert(tp->state == CH_STATE_SNDMSG, "invalid state");
215  chMsgReleaseS(tp, msg);
216  chSysUnlock();
217 }
218 
219 #endif /* CH_CFG_USE_MESSAGES == TRUE */
220 
221 /** @} */
CH_STATE_WTMSG
#define CH_STATE_WTMSG
Waiting for a message.
Definition: chschd.h:79
chSysLock
static void chSysLock(void)
Enters the kernel lock state.
Definition: chsys.h:355
chSchReadyI
thread_t * chSchReadyI(thread_t *tp)
Inserts a thread in the Ready List placing it behind its peers.
Definition: chschd.c:153
chMsgPollS
thread_t * chMsgPollS(void)
Poll to check for an incoming message.
Definition: chmsg.c:190
currp
#define currp
Current thread pointer access macro.
Definition: chschd.h:462
ch_thread::rdymsg
msg_t rdymsg
Thread wakeup code.
Definition: chschd.h:201
chDbgAssert
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:127
chMsgReleaseS
static void chMsgReleaseS(thread_t *tp, msg_t msg)
Releases the thread waiting on top of the messages queue.
Definition: chmsg.h:201
chSchGoSleepTimeoutS
msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout)
Puts the current thread to sleep into the specified state with timeout specification.
Definition: chschd.c:258
chDbgCheck
#define chDbgCheck(c)
Function parameters check.
Definition: chdebug.h:101
chMsgWaitS
thread_t * chMsgWaitS(void)
Suspends the thread and waits for an incoming message.
Definition: chmsg.c:121
CH_STATE_SNDMSGQ
#define CH_STATE_SNDMSGQ
Sending a message, in queue.
Definition: chschd.h:75
ch_thread::sentmsg
msg_t sentmsg
Thread sent message.
Definition: chschd.h:227
ch_thread
Structure representing a thread.
Definition: chschd.h:134
chSchGoSleepS
void chSchGoSleepS(tstate_t newstate)
Puts the current thread to sleep into the specified state.
Definition: chschd.c:210
chMsgSend
msg_t chMsgSend(thread_t *tp, msg_t msg)
Sends a message to the specified thread.
Definition: chmsg.c:87
ch_queue_fifo_remove
static ch_queue_t * ch_queue_fifo_remove(ch_queue_t *qp)
Removes the first-out element from a queue and returns it.
Definition: chlists.h:265
ch_thread::msgqueue
ch_queue_t msgqueue
Messages queue.
Definition: chschd.h:266
ch_thread::u
union ch_thread::@1 u
State-specific fields.
CH_STATE_SNDMSG
#define CH_STATE_SNDMSG
Sent a message, waiting answer.
Definition: chschd.h:77
chMsgIsPendingI
static bool chMsgIsPendingI(thread_t *tp)
Evaluates to true if the thread has pending messages.
Definition: chmsg.h:167
MSG_OK
#define MSG_OK
Normal wakeup message.
Definition: chschd.h:39
chMsgRelease
void chMsgRelease(thread_t *tp, msg_t msg)
Releases a sender thread specifying a response message.
Definition: chmsg.c:211
sysinterval_t
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
ch_thread::state
tstate_t state
Current thread state.
Definition: chschd.h:165
ch.h
ChibiOS/RT main include file.
chSysUnlock
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition: chsys.h:367
chDbgCheckClassS
void chDbgCheckClassS(void)
S-class functions context check.
Definition: chdebug.c:248
chMsgWaitTimeoutS
thread_t * chMsgWaitTimeoutS(sysinterval_t timeout)
Suspends the thread and waits for an incoming message or a timeout to occur.
Definition: chmsg.c:157