ChibiOS  21.6.0
rt/src/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 /*===========================================================================*/
67 /* Module exported functions. */
68 /*===========================================================================*/
69 
70 /**
71  * @brief Sends a message to the specified thread.
72  * @details The sender is stopped until the receiver executes a
73  * @p chMsgRelease()after receiving the message.
74  *
75  * @param[in] tp the pointer to the thread
76  * @param[in] msg the message
77  * @return The answer message from @p chMsgRelease().
78  *
79  * @api
80  */
82  thread_t *currtp = chThdGetSelfX();
83 
84  chDbgCheck(tp != NULL);
85 
86  chSysLock();
87  currtp->u.sentmsg = msg;
88  __ch_msg_insert(&tp->msgqueue, currtp);
89  if (tp->state == CH_STATE_WTMSG) {
90  (void) chSchReadyI(tp);
91  }
93  msg = currtp->u.rdymsg;
94  chSysUnlock();
95 
96  return msg;
97 }
98 
99 /**
100  * @brief Suspends the thread and waits for an incoming message.
101  * @post After receiving a message the function @p chMsgGet() must be
102  * called in order to retrieve the message and then @p chMsgRelease()
103  * must be invoked in order to acknowledge the reception and send
104  * the answer.
105  * @note If the message is a pointer then you can assume that the data
106  * pointed by the message is stable until you invoke @p chMsgRelease()
107  * because the sending thread is suspended until then.
108  * @note The reference counter of the sender thread is not increased, the
109  * returned pointer is a temporary reference.
110  *
111  * @return A pointer to the thread carrying the message.
112  *
113  * @sclass
114  */
116  thread_t *currtp = chThdGetSelfX();
117  thread_t *tp;
118 
119  chDbgCheckClassS();
120 
121  if (!chMsgIsPendingI(currtp)) {
123  }
124  tp = (thread_t *)ch_queue_fifo_remove(&currtp->msgqueue);
125  tp->state = CH_STATE_SNDMSG;
126 
127  return tp;
128 }
129 
130 /**
131  * @brief Suspends the thread and waits for an incoming message or a
132  * timeout to occur.
133  * @post After receiving a message the function @p chMsgGet() must be
134  * called in order to retrieve the message and then @p chMsgRelease()
135  * must be invoked in order to acknowledge the reception and send
136  * the answer.
137  * @note If the message is a pointer then you can assume that the data
138  * pointed by the message is stable until you invoke @p chMsgRelease()
139  * because the sending thread is suspended until then.
140  * @note The reference counter of the sender thread is not increased, the
141  * returned pointer is a temporary reference.
142  *
143  * @param[in] timeout the number of ticks before the operation timeouts,
144  * the following special values are allowed:
145  * - @a TIME_INFINITE no timeout.
146  * .
147  * @return A pointer to the thread carrying the message.
148  * @retval NULL if a timeout occurred.
149  *
150  * @sclass
151  */
153  thread_t *currtp = chThdGetSelfX();
154  thread_t *tp;
155 
156  chDbgCheckClassS();
157 
158  if (!chMsgIsPendingI(currtp)) {
159  if (chSchGoSleepTimeoutS(CH_STATE_WTMSG, timeout) != MSG_OK) {
160  return NULL;
161  }
162  }
163  tp = (thread_t *)ch_queue_fifo_remove(&currtp->msgqueue);
164  tp->state = CH_STATE_SNDMSG;
165 
166  return tp;
167 }
168 
169 /**
170  * @brief Poll to check for an incoming message.
171  * @post If a message is available the function @p chMsgGet() must be
172  * called in order to retrieve the message and then @p chMsgRelease()
173  * must be invoked in order to acknowledge the reception and send
174  * the answer.
175  * @note If the message is a pointer then you can assume that the data
176  * pointed by the message is stable until you invoke @p chMsgRelease()
177  * because the sending thread is suspended until then.
178  * @note The reference counter of the sender thread is not increased, the
179  * returned pointer is a temporary reference.
180  *
181  * @return Result of the poll.
182  * @retval NULL if no incoming message waiting.
183  *
184  * @sclass
185  */
187  thread_t *currtp = chThdGetSelfX();
188  thread_t *tp = NULL;
189 
190  if (chMsgIsPendingI(currtp)) {
191  tp = (thread_t *)ch_queue_fifo_remove(&currtp->msgqueue);
192  tp->state = CH_STATE_SNDMSG;
193  }
194 
195  return tp;
196 }
197 
198 /**
199  * @brief Releases a sender thread specifying a response message.
200  * @pre Invoke this function only after a message has been received
201  * using @p chMsgWait().
202  *
203  * @param[in] tp pointer to the thread
204  * @param[in] msg message to be returned to the sender
205  *
206  * @api
207  */
208 void chMsgRelease(thread_t *tp, msg_t msg) {
209 
210  chSysLock();
211  chDbgAssert(tp->state == CH_STATE_SNDMSG, "invalid state");
212  chMsgReleaseS(tp, msg);
213  chSysUnlock();
214 }
215 
216 #endif /* CH_CFG_USE_MESSAGES == TRUE */
217 
218 /** @} */
CH_STATE_WTMSG
#define CH_STATE_WTMSG
Waiting for a message.
Definition: chschd.h:79
chSchReadyI
thread_t * chSchReadyI(thread_t *tp)
Inserts a thread in the Ready List placing it behind its peers.
Definition: chschd.c:276
chMsgWaitS
thread_t * chMsgWaitS(void)
Suspends the thread and waits for an incoming message.
Definition: rt/src/chmsg.c:115
chMsgPollS
thread_t * chMsgPollS(void)
Poll to check for an incoming message.
Definition: rt/src/chmsg.c:186
ch_thread::rdymsg
msg_t rdymsg
Thread wakeup code.
Definition: chobjects.h:242
chDbgAssert
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:144
msg_t
int32_t msg_t
Definition: chearly.h:88
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:355
chDbgCheck
#define chDbgCheck(c)
Function parameters check.
Definition: chdebug.h:118
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: chobjects.h:268
ch_thread
Structure representing a thread.
Definition: chobjects.h:156
chSchGoSleepS
void chSchGoSleepS(tstate_t newstate)
Puts the current thread to sleep into the specified state.
Definition: chschd.c:301
chMsgSend
msg_t chMsgSend(thread_t *tp, msg_t msg)
Sends a message to the specified thread.
Definition: rt/src/chmsg.c:81
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:280
ch_thread::msgqueue
ch_queue_t msgqueue
Messages queue.
Definition: chobjects.h:307
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: rt/include/chmsg.h:173
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: rt/src/chmsg.c:208
chMsgReleaseS
#define chMsgReleaseS(tp, msg)
Releases the thread waiting on top of the messages queue.
Definition: nil/include/chmsg.h:97
sysinterval_t
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
ch_thread::state
tstate_t state
Current thread state.
Definition: chobjects.h:206
chMsgWaitTimeoutS
thread_t * chMsgWaitTimeoutS(sysinterval_t timeout)
Suspends the thread and waits for an incoming message or a timeout to occur.
Definition: rt/src/chmsg.c:152
chSysUnlock
#define chSysUnlock()
Leaves the kernel lock state.
Definition: nil/include/ch.h:1053
chThdGetSelfX
#define chThdGetSelfX()
Returns a pointer to the current thread_t.
Definition: nil/include/ch.h:1132
chSysLock
#define chSysLock()
Enters the kernel lock state.
Definition: nil/include/ch.h:1043