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