ChibiOS 21.11.4
chcond.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 Concepts and parts of this file have been contributed by Leon Woestenberg.
21 */
22
23/**
24 * @file rt/src/chcond.c
25 * @brief Condition Variables code.
26 *
27 * @addtogroup condvars
28 * @details This module implements the Condition Variables mechanism. Condition
29 * variables are an extensions to the mutex subsystem and cannot
30 * work alone.
31 * <h2>Operation mode</h2>
32 * The condition variable is a synchronization object meant to be
33 * used inside a zone protected by a mutex. Mutexes and condition
34 * variables together can implement a Monitor construct.
35 * @pre In order to use the condition variable APIs the @p CH_CFG_USE_CONDVARS
36 * option must be enabled in @p chconf.h.
37 * @{
38 */
39
40#include "ch.h"
41
42#if (CH_CFG_USE_CONDVARS == TRUE) || defined(__DOXYGEN__)
43
44/*===========================================================================*/
45/* Module local definitions. */
46/*===========================================================================*/
47
48/*===========================================================================*/
49/* Module exported variables. */
50/*===========================================================================*/
51
52/*===========================================================================*/
53/* Module local types. */
54/*===========================================================================*/
55
56/*===========================================================================*/
57/* Module local variables. */
58/*===========================================================================*/
59
60/*===========================================================================*/
61/* Module local functions. */
62/*===========================================================================*/
63
64/*===========================================================================*/
65/* Module exported functions. */
66/*===========================================================================*/
67
68/**
69 * @brief Initializes s @p condition_variable_t structure.
70 *
71 * @param[out] cp pointer to a @p condition_variable_t structure
72 *
73 * @init
74 */
76
77 chDbgCheck(cp != NULL);
78
79 ch_queue_init(&cp->queue);
80}
81
82/**
83 * @brief Signals one thread that is waiting on the condition variable.
84 *
85 * @param[in] cp pointer to the @p condition_variable_t structure
86 *
87 * @api
88 */
90
91 chDbgCheck(cp != NULL);
92
93 chSysLock();
94 if (ch_queue_notempty(&cp->queue)) {
96 }
98}
99
100/**
101 * @brief Signals one thread that is waiting on the condition variable.
102 * @post This function does not reschedule so a call to a rescheduling
103 * function must be performed before unlocking the kernel. Note that
104 * interrupt handlers always reschedule on exit so an explicit
105 * reschedule must not be performed in ISRs.
106 *
107 * @param[in] cp pointer to the @p condition_variable_t structure
108 *
109 * @iclass
110 */
112
114 chDbgCheck(cp != NULL);
115
116 if (ch_queue_notempty(&cp->queue)) {
118 tp->u.rdymsg = MSG_OK;
119 (void) chSchReadyI(tp);
120 }
121}
122
123/**
124 * @brief Signals all threads that are waiting on the condition variable.
125 *
126 * @param[in] cp pointer to the @p condition_variable_t structure
127 *
128 * @api
129 */
137
138/**
139 * @brief Signals all threads that are waiting on the condition variable.
140 * @post This function does not reschedule so a call to a rescheduling
141 * function must be performed before unlocking the kernel. Note that
142 * interrupt handlers always reschedule on exit so an explicit
143 * reschedule must not be performed in ISRs.
144 *
145 * @param[in] cp pointer to the @p condition_variable_t structure
146 *
147 * @iclass
148 */
150
152 chDbgCheck(cp != NULL);
153
154 /* Empties the condition variable queue and inserts all the threads into the
155 ready list in FIFO order. The wakeup message is set to @p MSG_RESET in
156 order to make a chCondBroadcast() detectable from a chCondSignal().*/
157 while (ch_queue_notempty(&cp->queue)) {
159 }
160}
161
162/**
163 * @brief Waits on the condition variable releasing the mutex lock.
164 * @details Releases the currently owned mutex, waits on the condition
165 * variable, and finally acquires the mutex again. All the sequence
166 * is performed atomically.
167 * @pre The invoking thread <b>must</b> have at least one owned mutex.
168 *
169 * @param[in] cp pointer to the @p condition_variable_t structure
170 * @return A message specifying how the invoking thread has been
171 * released from the condition variable.
172 * @retval MSG_OK if the condition variable has been signaled using
173 * @p chCondSignal().
174 * @retval MSG_RESET if the condition variable has been signaled using
175 * @p chCondBroadcast().
176 *
177 * @api
178 */
180 msg_t msg;
181
182 chSysLock();
183 msg = chCondWaitS(cp);
184 chSysUnlock();
185 return msg;
186}
187
188/**
189 * @brief Waits on the condition variable releasing the mutex lock.
190 * @details Releases the currently owned mutex, waits on the condition
191 * variable, and finally acquires the mutex again. All the sequence
192 * is performed atomically.
193 * @pre The invoking thread <b>must</b> have at least one owned mutex.
194 *
195 * @param[in] cp pointer to the @p condition_variable_t structure
196 * @return A message specifying how the invoking thread has been
197 * released from the condition variable.
198 * @retval MSG_OK if the condition variable has been signaled using
199 * @p chCondSignal().
200 * @retval MSG_RESET if the condition variable has been signaled using
201 * @p chCondBroadcast().
202 *
203 * @sclass
204 */
206 thread_t *currtp = chThdGetSelfX();
208 msg_t msg;
209
211 chDbgCheck(cp != NULL);
212 chDbgAssert(mp != NULL, "not owning a mutex");
213
214 /* Releasing "current" mutex.*/
215 chMtxUnlockS(mp);
216
217 /* Start waiting on the condition variable, on exit the mutex is taken
218 again.*/
219 currtp->u.wtobjp = cp;
220 ch_sch_prio_insert(&cp->queue, &currtp->hdr.queue);
222 msg = currtp->u.rdymsg;
223 chMtxLockS(mp);
224
225 return msg;
226}
227
228#if (CH_CFG_USE_CONDVARS_TIMEOUT == TRUE) || defined(__DOXYGEN__)
229/**
230 * @brief Waits on the condition variable releasing the mutex lock.
231 * @details Releases the currently owned mutex, waits on the condition
232 * variable, and finally acquires the mutex again. All the sequence
233 * is performed atomically.
234 * @pre The invoking thread <b>must</b> have at least one owned mutex.
235 * @pre The configuration option @p CH_CFG_USE_CONDVARS_TIMEOUT must be enabled
236 * in order to use this function.
237 * @post Exiting the function because a timeout does not re-acquire the
238 * mutex, the mutex ownership is lost.
239 *
240 * @param[in] cp pointer to the @p condition_variable_t structure
241 * @param[in] timeout the number of ticks before the operation timeouts, the
242 * special values are handled as follow:
243 * - @a TIME_INFINITE no timeout.
244 * - @a TIME_IMMEDIATE this value is not allowed.
245 * .
246 * @return A message specifying how the invoking thread has been
247 * released from the condition variable.
248 * @retval MSG_OK if the condition variable has been signaled using
249 * @p chCondSignal().
250 * @retval MSG_RESET if the condition variable has been signaled using
251 * @p chCondBroadcast().
252 * @retval MSG_TIMEOUT if the condition variable has not been signaled within
253 * the specified timeout.
254 *
255 * @api
256 */
258 msg_t msg;
259
260 chSysLock();
261 msg = chCondWaitTimeoutS(cp, timeout);
262 chSysUnlock();
263
264 return msg;
265}
266
267/**
268 * @brief Waits on the condition variable releasing the mutex lock.
269 * @details Releases the currently owned mutex, waits on the condition
270 * variable, and finally acquires the mutex again. All the sequence
271 * is performed atomically.
272 * @pre The invoking thread <b>must</b> have at least one owned mutex.
273 * @pre The configuration option @p CH_CFG_USE_CONDVARS_TIMEOUT must be enabled
274 * in order to use this function.
275 * @post Exiting the function because a timeout does not re-acquire the
276 * mutex, the mutex ownership is lost.
277 *
278 * @param[in] cp pointer to the @p condition_variable_t structure
279 * @param[in] timeout the number of ticks before the operation timeouts, the
280 * special values are handled as follow:
281 * - @a TIME_INFINITE no timeout.
282 * - @a TIME_IMMEDIATE this value is not allowed.
283 * .
284 * @return A message specifying how the invoking thread has been
285 * released from the condition variable.
286 * @retval MSG_OK if the condition variable has been signaled using
287 * @p chCondSignal().
288 * @retval MSG_RESET if the condition variable has been signaled using
289 * @p chCondBroadcast().
290 * @retval MSG_TIMEOUT if the condition variable has not been signaled within
291 * the specified timeout.
292 *
293 * @sclass
294 */
296 thread_t *currtp = chThdGetSelfX();
298 msg_t msg;
299
301 chDbgCheck((cp != NULL) && (timeout != TIME_IMMEDIATE));
302 chDbgAssert(mp != NULL, "not owning a mutex");
303
304 /* Releasing "current" mutex.*/
305 chMtxUnlockS(mp);
306
307 /* Start waiting on the condition variable, on exit the mutex is taken
308 again.*/
309 currtp->u.wtobjp = cp;
310 ch_sch_prio_insert(&cp->queue, &currtp->hdr.queue);
312 if (msg != MSG_TIMEOUT) {
313 chMtxLockS(mp);
314 }
315
316 return msg;
317}
318#endif /* CH_CFG_USE_CONDVARS_TIMEOUT == TRUE */
319
320#endif /* CH_CFG_USE_CONDVARS == TRUE */
321
322/** @} */
#define chThdGetSelfX()
Returns a pointer to the current thread_t.
#define chSysUnlock()
Leaves the kernel lock state.
#define chSchWakeupS(ntp, msg)
Wakes up a thread.
#define chSysLock()
Enters the kernel lock state.
#define chSchGoSleepS(newstate)
Puts the current thread to sleep into the specified state.
#define chDbgAssert(c, r)
Condition assertion.
Definition chdebug.h:144
#define chDbgCheck(c)
Function parameters check.
Definition chdebug.h:118
#define chDbgCheckClassS()
Definition chdebug.h:100
#define chDbgCheckClassI()
Definition chdebug.h:99
void chCondBroadcast(condition_variable_t *cp)
Signals all threads that are waiting on the condition variable.
Definition chcond.c:130
msg_t chCondWaitTimeoutS(condition_variable_t *cp, sysinterval_t timeout)
Waits on the condition variable releasing the mutex lock.
Definition chcond.c:295
void chCondObjectInit(condition_variable_t *cp)
Initializes s condition_variable_t structure.
Definition chcond.c:75
void chCondSignalI(condition_variable_t *cp)
Signals one thread that is waiting on the condition variable.
Definition chcond.c:111
void chCondBroadcastI(condition_variable_t *cp)
Signals all threads that are waiting on the condition variable.
Definition chcond.c:149
msg_t chCondWaitTimeout(condition_variable_t *cp, sysinterval_t timeout)
Waits on the condition variable releasing the mutex lock.
Definition chcond.c:257
struct condition_variable condition_variable_t
condition_variable_t structure.
msg_t chCondWaitS(condition_variable_t *cp)
Waits on the condition variable releasing the mutex lock.
Definition chcond.c:205
void chCondSignal(condition_variable_t *cp)
Signals one thread that is waiting on the condition variable.
Definition chcond.c:89
msg_t chCondWait(condition_variable_t *cp)
Waits on the condition variable releasing the mutex lock.
Definition chcond.c:179
static mutex_t * chMtxGetNextMutexX(void)
Returns the next mutex in the mutexes stack of the current thread.
Definition chmtx.h:159
struct ch_mutex mutex_t
Type of a mutex structure.
Definition chmtx.h:52
void chMtxLockS(mutex_t *mp)
Locks the specified mutex.
Definition chmtx.c:139
void chMtxUnlockS(mutex_t *mp)
Unlocks the specified mutex.
Definition chmtx.c:413
static void ch_queue_init(ch_queue_t *qp)
Queue initialization.
Definition chlists.h:222
static bool ch_queue_notempty(const ch_queue_t *qp)
Evaluates to true if the specified queue is not empty.
Definition chlists.h:249
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
#define threadref(p)
Safe cast of a queue pointer to a thread pointer.
Definition chearly.h:206
int32_t msg_t
Definition chearly.h:88
struct ch_thread thread_t
Type of a thread structure.
Definition chearly.h:133
void chSchRescheduleS(void)
Performs a reschedule if a higher priority thread is runnable.
Definition chschd.c:458
#define MSG_OK
Normal wakeup message.
Definition chschd.h:39
#define CH_STATE_WTCOND
On a cond.variable.
Definition chschd.h:70
thread_t * chSchReadyI(thread_t *tp)
Inserts a thread in the Ready List placing it behind its peers.
Definition chschd.c:280
#define MSG_TIMEOUT
Wakeup caused by a timeout condition.
Definition chschd.h:40
void ch_sch_prio_insert(ch_queue_t *qp, ch_queue_t *tp)
Inserts a thread into a priority ordered queue.
Definition chschd.c:250
#define MSG_RESET
Wakeup caused by a reset condition.
Definition chschd.h:42
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:359
#define TIME_IMMEDIATE
Zero interval specification for some functions with a timeout specification.
Definition chtime.h:47
uint64_t sysinterval_t
Type of time interval.
Definition chtime.h:119
ch_queue_t queue
Threads queues element.
Definition chobjects.h:168
union ch_thread::@065317322233202114332352372014266163076165303275 hdr
Shared list headers.
msg_t rdymsg
Thread wakeup code.
Definition chobjects.h:242
void * wtobjp
Pointer to a generic "wait" object.
Definition chobjects.h:256
union ch_thread::@250330312022121344252011223135034045240103044261 u
State-specific fields.
ch_queue_t queue
Condition variable threads queue.
Definition chcond.h:60