ChibiOS/RT  6.0.3
chevents.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 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; either version 3 of the License, or
9  (at your option) any later version.
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 Scott (skute).
21  */
22 
23 /**
24  * @file chevents.c
25  * @brief Events code.
26  *
27  * @addtogroup events
28  * @details Event Flags, Event Sources and Event Listeners.
29  * <h2>Operation mode</h2>
30  * Each thread has a mask of pending events inside its
31  * @p thread_t structure.
32  * Operations defined for events:
33  * - <b>Wait</b>, the invoking thread goes to sleep until a certain
34  * AND/OR combination of events become pending.
35  * - <b>Clear</b>, a mask of events is cleared from the pending
36  * events, the cleared events mask is returned (only the
37  * events that were actually pending and then cleared).
38  * - <b>Signal</b>, an events mask is directly ORed to the mask of the
39  * signaled thread.
40  * - <b>Broadcast</b>, each thread registered on an Event Source is
41  * signaled with the events specified in its Event Listener.
42  * - <b>Dispatch</b>, an events mask is scanned and for each bit set
43  * to one an associated handler function is invoked. Bit masks are
44  * scanned from bit zero upward.
45  * .
46  * An Event Source is a special object that can be "broadcasted" by
47  * a thread or an interrupt service routine. Broadcasting an Event
48  * Source has the effect that all the threads registered on the
49  * Event Source will be signaled with an events mask.<br>
50  * An unlimited number of Event Sources can exists in a system and
51  * each thread can be listening on an unlimited number of
52  * them.
53  * @pre In order to use the Events APIs the @p CH_CFG_USE_EVENTS option must be
54  * enabled in @p chconf.h.
55  * @post Enabling events requires 1-4 (depending on the architecture)
56  * extra bytes in the @p thread_t structure.
57  * @{
58  */
59 
60 #include "ch.h"
61 
62 #if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
63 
64 /*===========================================================================*/
65 /* Module local definitions. */
66 /*===========================================================================*/
67 
68 /*===========================================================================*/
69 /* Module exported variables. */
70 /*===========================================================================*/
71 
72 /*===========================================================================*/
73 /* Module local types. */
74 /*===========================================================================*/
75 
76 /*===========================================================================*/
77 /* Module local variables. */
78 /*===========================================================================*/
79 
80 /*===========================================================================*/
81 /* Module local functions. */
82 /*===========================================================================*/
83 
84 /*===========================================================================*/
85 /* Module exported functions. */
86 /*===========================================================================*/
87 
88 /**
89  * @brief Registers an Event Listener on an Event Source.
90  * @details Once a thread has registered as listener on an event source it
91  * will be notified of all events broadcasted there.
92  * @note Multiple Event Listeners can specify the same bits to be ORed to
93  * different threads.
94  *
95  * @param[in] esp pointer to the @p event_source_t structure
96  * @param[in] elp pointer to the @p event_listener_t structure
97  * @param[in] events events to be ORed to the thread when
98  * the event source is broadcasted
99  * @param[in] wflags mask of flags the listening thread is interested in
100  *
101  * @api
102  */
104  event_listener_t *elp,
105  eventmask_t events,
106  eventflags_t wflags) {
107 
108  chDbgCheck((esp != NULL) && (elp != NULL));
109 
110  chSysLock();
111  elp->next = esp->next;
112  esp->next = elp;
113  elp->listener = currp;
114  elp->events = events;
115  elp->flags = (eventflags_t)0;
116  elp->wflags = wflags;
117  chSysUnlock();
118 }
119 
120 /**
121  * @brief Unregisters an Event Listener from its Event Source.
122  * @note If the event listener is not registered on the specified event
123  * source then the function does nothing.
124  * @note For optimal performance it is better to perform the unregister
125  * operations in inverse order of the register operations (elements
126  * are found on top of the list).
127  *
128  * @param[in] esp pointer to the @p event_source_t structure
129  * @param[in] elp pointer to the @p event_listener_t structure
130  *
131  * @api
132  */
134  event_listener_t *p;
135 
136  chDbgCheck((esp != NULL) && (elp != NULL));
137 
138  /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
139  p = (event_listener_t *)esp;
140  /*lint -restore*/
141  chSysLock();
142  /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
143  while (p->next != (event_listener_t *)esp) {
144  /*lint -restore*/
145  if (p->next == elp) {
146  p->next = elp->next;
147  break;
148  }
149  p = p->next;
150  }
151  chSysUnlock();
152 }
153 
154 /**
155  * @brief Clears the pending events specified in the events mask.
156  *
157  * @param[in] events the events to be cleared
158  * @return The mask of pending events that were cleared.
159  *
160  * @iclass
161  */
162 eventmask_t chEvtGetAndClearEventsI(eventmask_t events) {
163  eventmask_t m;
164 
165  m = currp->epending & events;
166  currp->epending &= ~events;
167 
168  return m;
169 }
170 
171 /**
172  * @brief Clears the pending events specified in the events mask.
173  *
174  * @param[in] events the events to be cleared
175  * @return The mask of pending events that were cleared.
176  *
177  * @api
178  */
179 eventmask_t chEvtGetAndClearEvents(eventmask_t events) {
180  eventmask_t m;
181 
182  chSysLock();
183  m = chEvtGetAndClearEventsI(events);
184  chSysUnlock();
185 
186  return m;
187 }
188 
189 /**
190  * @brief Adds (OR) a set of events to the current thread, this is
191  * @b much faster than using @p chEvtBroadcast() or @p chEvtSignal().
192  *
193  * @param[in] events the events to be added
194  * @return The mask of currently pending events.
195  *
196  * @api
197  */
198 eventmask_t chEvtAddEvents(eventmask_t events) {
199  eventmask_t newevt;
200 
201  chSysLock();
202  newevt = chEvtAddEventsI(events);
203  chSysUnlock();
204 
205  return newevt;
206 }
207 
208 /**
209  * @brief Signals all the Event Listeners registered on the specified Event
210  * Source.
211  * @details This function variants ORs the specified event flags to all the
212  * threads registered on the @p event_source_t in addition to the
213  * event flags specified by the threads themselves in the
214  * @p event_listener_t objects.
215  * @post This function does not reschedule so a call to a rescheduling
216  * function must be performed before unlocking the kernel. Note that
217  * interrupt handlers always reschedule on exit so an explicit
218  * reschedule must not be performed in ISRs.
219  *
220  * @param[in] esp pointer to the @p event_source_t structure
221  * @param[in] flags the flags set to be added to the listener flags mask
222  *
223  * @iclass
224  */
225 void chEvtBroadcastFlagsI(event_source_t *esp, eventflags_t flags) {
226  event_listener_t *elp;
227 
229  chDbgCheck(esp != NULL);
230 
231  elp = esp->next;
232  /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
233  while (elp != (event_listener_t *)esp) {
234  /*lint -restore*/
235  elp->flags |= flags;
236  /* When flags == 0 the thread will always be signaled because the
237  source does not emit any flag.*/
238  if ((flags == (eventflags_t)0) ||
239  ((flags & elp->wflags) != (eventflags_t)0)) {
240  chEvtSignalI(elp->listener, elp->events);
241  }
242  elp = elp->next;
243  }
244 }
245 
246 /**
247  * @brief Returns the flags associated to an @p event_listener_t.
248  * @details The flags are returned and the @p event_listener_t flags mask is
249  * cleared.
250  *
251  * @param[in] elp pointer to the @p event_listener_t structure
252  * @return The flags added to the listener by the associated
253  * event source.
254  *
255  * @api
256  */
258  eventflags_t flags;
259 
260  chSysLock();
261  flags = elp->flags;
262  elp->flags = (eventflags_t)0;
263  chSysUnlock();
264 
265  return flags & elp->wflags;
266 }
267 
268 /**
269  * @brief Adds a set of event flags directly to the specified @p thread_t.
270  *
271  * @param[in] tp the thread to be signaled
272  * @param[in] events the events set to be ORed
273  *
274  * @api
275  */
276 void chEvtSignal(thread_t *tp, eventmask_t events) {
277 
278  chDbgCheck(tp != NULL);
279 
280  chSysLock();
281  chEvtSignalI(tp, events);
283  chSysUnlock();
284 }
285 
286 /**
287  * @brief Adds a set of event flags directly to the specified @p thread_t.
288  * @post This function does not reschedule so a call to a rescheduling
289  * function must be performed before unlocking the kernel. Note that
290  * interrupt handlers always reschedule on exit so an explicit
291  * reschedule must not be performed in ISRs.
292  *
293  * @param[in] tp the thread to be signaled
294  * @param[in] events the events set to be ORed
295  *
296  * @iclass
297  */
298 void chEvtSignalI(thread_t *tp, eventmask_t events) {
299 
301  chDbgCheck(tp != NULL);
302 
303  tp->epending |= events;
304  /* Test on the AND/OR conditions wait states.*/
305  if (((tp->state == CH_STATE_WTOREVT) &&
306  ((tp->epending & tp->u.ewmask) != (eventmask_t)0)) ||
307  ((tp->state == CH_STATE_WTANDEVT) &&
308  ((tp->epending & tp->u.ewmask) == tp->u.ewmask))) {
309  tp->u.rdymsg = MSG_OK;
310  (void) chSchReadyI(tp);
311  }
312 }
313 
314 /**
315  * @brief Signals all the Event Listeners registered on the specified Event
316  * Source.
317  * @details This function variants ORs the specified event flags to all the
318  * threads registered on the @p event_source_t in addition to the
319  * event flags specified by the threads themselves in the
320  * @p event_listener_t objects.
321  *
322  * @param[in] esp pointer to the @p event_source_t structure
323  * @param[in] flags the flags set to be added to the listener flags mask
324  *
325  * @api
326  */
327 void chEvtBroadcastFlags(event_source_t *esp, eventflags_t flags) {
328 
329  chSysLock();
330  chEvtBroadcastFlagsI(esp, flags);
332  chSysUnlock();
333 }
334 
335 /**
336  * @brief Returns the unmasked flags associated to an @p event_listener_t.
337  * @details The flags are returned and the @p event_listener_t flags mask is
338  * cleared.
339  *
340  * @param[in] elp pointer to the @p event_listener_t structure
341  * @return The flags added to the listener by the associated
342  * event source.
343  *
344  * @iclass
345  */
347  eventflags_t flags;
348 
349  flags = elp->flags;
350  elp->flags = (eventflags_t)0;
351 
352  return flags & elp->wflags;
353 }
354 
355 /**
356  * @brief Invokes the event handlers associated to an event flags mask.
357  *
358  * @param[in] events mask of events to be dispatched
359  * @param[in] handlers an array of @p evhandler_t. The array must have size
360  * equal to the number of bits in eventmask_t.
361  *
362  * @api
363  */
364 void chEvtDispatch(const evhandler_t *handlers, eventmask_t events) {
365  eventid_t eid;
366 
367  chDbgCheck(handlers != NULL);
368 
369  eid = (eventid_t)0;
370  while (events != (eventmask_t)0) {
371  if ((events & EVENT_MASK(eid)) != (eventmask_t)0) {
372  chDbgAssert(handlers[eid] != NULL, "null handler");
373  events &= ~EVENT_MASK(eid);
374  handlers[eid](eid);
375  }
376  eid++;
377  }
378 }
379 
380 #if (CH_CFG_OPTIMIZE_SPEED == TRUE) || \
381  (CH_CFG_USE_EVENTS_TIMEOUT == FALSE) || \
382  defined(__DOXYGEN__)
383 /**
384  * @brief Waits for exactly one of the specified events.
385  * @details The function waits for one event among those specified in
386  * @p events to become pending then the event is cleared and returned.
387  * @note One and only one event is served in the function, the one with the
388  * lowest event id. The function is meant to be invoked into a loop in
389  * order to serve all the pending events.<br>
390  * This means that Event Listeners with a lower event identifier have
391  * an higher priority.
392  *
393  * @param[in] events events that the function should wait
394  * for, @p ALL_EVENTS enables all the events
395  * @return The mask of the lowest event id served and cleared.
396  *
397  * @api
398  */
399 eventmask_t chEvtWaitOne(eventmask_t events) {
400  thread_t *ctp = currp;
401  eventmask_t m;
402 
403  chSysLock();
404  m = ctp->epending & events;
405  if (m == (eventmask_t)0) {
406  ctp->u.ewmask = events;
408  m = ctp->epending & events;
409  }
410  m ^= m & (m - (eventmask_t)1);
411  ctp->epending &= ~m;
412  chSysUnlock();
413 
414  return m;
415 }
416 
417 /**
418  * @brief Waits for any of the specified events.
419  * @details The function waits for any event among those specified in
420  * @p events to become pending then the events are cleared and
421  * returned.
422  *
423  * @param[in] events events that the function should wait
424  * for, @p ALL_EVENTS enables all the events
425  * @return The mask of the served and cleared events.
426  *
427  * @api
428  */
429 eventmask_t chEvtWaitAny(eventmask_t events) {
430  thread_t *ctp = currp;
431  eventmask_t m;
432 
433  chSysLock();
434  m = ctp->epending & events;
435  if (m == (eventmask_t)0) {
436  ctp->u.ewmask = events;
438  m = ctp->epending & events;
439  }
440  ctp->epending &= ~m;
441  chSysUnlock();
442 
443  return m;
444 }
445 
446 /**
447  * @brief Waits for all the specified events.
448  * @details The function waits for all the events specified in @p events to
449  * become pending then the events are cleared and returned.
450  *
451  * @param[in] events events that the function should wait
452  * for, @p ALL_EVENTS requires all the events
453  * @return The mask of the served and cleared events.
454  *
455  * @api
456  */
457 eventmask_t chEvtWaitAll(eventmask_t events) {
458  thread_t *ctp = currp;
459 
460  chSysLock();
461  if ((ctp->epending & events) != events) {
462  ctp->u.ewmask = events;
464  }
465  ctp->epending &= ~events;
466  chSysUnlock();
467 
468  return events;
469 }
470 #endif /* CH_CFG_OPTIMIZE_SPEED || !CH_CFG_USE_EVENTS_TIMEOUT */
471 
472 #if (CH_CFG_USE_EVENTS_TIMEOUT == TRUE) || defined(__DOXYGEN__)
473 /**
474  * @brief Waits for exactly one of the specified events.
475  * @details The function waits for one event among those specified in
476  * @p events to become pending then the event is cleared and returned.
477  * @note One and only one event is served in the function, the one with the
478  * lowest event id. The function is meant to be invoked into a loop
479  * in order to serve all the pending events.<br>
480  * This means that Event Listeners with a lower event identifier have
481  * an higher priority.
482  *
483  * @param[in] events events that the function should wait
484  * for, @p ALL_EVENTS enables all the events
485  * @param[in] timeout the number of ticks before the operation timeouts,
486  * the following special values are allowed:
487  * - @a TIME_IMMEDIATE immediate timeout.
488  * - @a TIME_INFINITE no timeout.
489  * .
490  * @return The mask of the lowest event id served and cleared.
491  * @retval 0 if the operation has timed out.
492  *
493  * @api
494  */
495 eventmask_t chEvtWaitOneTimeout(eventmask_t events, sysinterval_t timeout) {
496  thread_t *ctp = currp;
497  eventmask_t m;
498 
499  chSysLock();
500  m = ctp->epending & events;
501  if (m == (eventmask_t)0) {
502  if (TIME_IMMEDIATE == timeout) {
503  chSysUnlock();
504  return (eventmask_t)0;
505  }
506  ctp->u.ewmask = events;
507  if (chSchGoSleepTimeoutS(CH_STATE_WTOREVT, timeout) < MSG_OK) {
508  chSysUnlock();
509  return (eventmask_t)0;
510  }
511  m = ctp->epending & events;
512  }
513  m ^= m & (m - (eventmask_t)1);
514  ctp->epending &= ~m;
515  chSysUnlock();
516 
517  return m;
518 }
519 
520 /**
521  * @brief Waits for any of the specified events.
522  * @details The function waits for any event among those specified in
523  * @p events to become pending then the events are cleared and
524  * returned.
525  *
526  * @param[in] events events that the function should wait
527  * for, @p ALL_EVENTS enables all the events
528  * @param[in] timeout the number of ticks before the operation timeouts,
529  * the following special values are allowed:
530  * - @a TIME_IMMEDIATE immediate timeout.
531  * - @a TIME_INFINITE no timeout.
532  * .
533  * @return The mask of the served and cleared events.
534  * @retval 0 if the operation has timed out.
535  *
536  * @api
537  */
538 eventmask_t chEvtWaitAnyTimeout(eventmask_t events, sysinterval_t timeout) {
539  thread_t *ctp = currp;
540  eventmask_t m;
541 
542  chSysLock();
543  m = ctp->epending & events;
544  if (m == (eventmask_t)0) {
545  if (TIME_IMMEDIATE == timeout) {
546  chSysUnlock();
547  return (eventmask_t)0;
548  }
549  ctp->u.ewmask = events;
550  if (chSchGoSleepTimeoutS(CH_STATE_WTOREVT, timeout) < MSG_OK) {
551  chSysUnlock();
552  return (eventmask_t)0;
553  }
554  m = ctp->epending & events;
555  }
556  ctp->epending &= ~m;
557  chSysUnlock();
558 
559  return m;
560 }
561 
562 /**
563  * @brief Waits for all the specified events.
564  * @details The function waits for all the events specified in @p events to
565  * become pending then the events are cleared and returned.
566  *
567  * @param[in] events events that the function should wait
568  * for, @p ALL_EVENTS requires all the events
569  * @param[in] timeout the number of ticks before the operation timeouts,
570  * the following special values are allowed:
571  * - @a TIME_IMMEDIATE immediate timeout.
572  * - @a TIME_INFINITE no timeout.
573  * .
574  * @return The mask of the served and cleared events.
575  * @retval 0 if the operation has timed out.
576  *
577  * @api
578  */
579 eventmask_t chEvtWaitAllTimeout(eventmask_t events, sysinterval_t timeout) {
580  thread_t *ctp = currp;
581 
582  chSysLock();
583  if ((ctp->epending & events) != events) {
584  if (TIME_IMMEDIATE == timeout) {
585  chSysUnlock();
586  return (eventmask_t)0;
587  }
588  ctp->u.ewmask = events;
590  chSysUnlock();
591  return (eventmask_t)0;
592  }
593  }
594  ctp->epending &= ~events;
595  chSysUnlock();
596 
597  return events;
598 }
599 #endif /* CH_CFG_USE_EVENTS_TIMEOUT == TRUE */
600 
601 #endif /* CH_CFG_USE_EVENTS == TRUE */
602 
603 /** @} */
eventmask_t chEvtWaitOne(eventmask_t events)
Waits for exactly one of the specified events.
Definition: chevents.c:399
#define CH_STATE_WTANDEVT
Several events.
Definition: chschd.h:78
void chEvtRegisterMaskWithFlags(event_source_t *esp, event_listener_t *elp, eventmask_t events, eventflags_t wflags)
Registers an Event Listener on an Event Source.
Definition: chevents.c:103
eventmask_t chEvtAddEvents(eventmask_t events)
Adds (OR) a set of events to the current thread, this is much faster than using chEvtBroadcast() or c...
Definition: chevents.c:198
eventmask_t chEvtGetAndClearEventsI(eventmask_t events)
Clears the pending events specified in the events mask.
Definition: chevents.c:162
eventflags_t wflags
Flags that this listener interested in.
Definition: chevents.h:67
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
eventmask_t epending
Pending events mask.
Definition: chschd.h:287
static void chSysLock(void)
Enters the kernel lock state.
Definition: chsys.h:353
Event Source structure.
Definition: chevents.h:74
eventmask_t events
Events to be set in the listening thread.
Definition: chevents.h:63
thread_t * chSchReadyI(thread_t *tp)
Inserts a thread in the Ready List placing it behind its peers.
Definition: chschd.c:218
eventflags_t chEvtGetAndClearFlags(event_listener_t *elp)
Returns the flags associated to an event_listener_t.
Definition: chevents.c:257
#define EVENT_MASK(eid)
Returns an event mask from an event identifier.
Definition: chevents.h:97
#define currp
Current thread pointer access macro.
Definition: chschd.h:459
msg_t rdymsg
Thread wakeup code.
Definition: chschd.h:216
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition: chsys.h:365
void chEvtBroadcastFlags(event_source_t *esp, eventflags_t flags)
Signals all the Event Listeners registered on the specified Event Source.
Definition: chevents.c:327
void chEvtSignal(thread_t *tp, eventmask_t events)
Adds a set of event flags directly to the specified thread_t.
Definition: chevents.c:276
void chSchRescheduleS(void)
Performs a reschedule if a higher priority thread is runnable.
Definition: chschd.c:456
thread_t * listener
Thread interested in the event source.
Definition: chevents.h:61
#define chDbgCheck(c)
Function parameters check.
Definition: chdebug.h:101
void chEvtUnregister(event_source_t *esp, event_listener_t *elp)
Unregisters an Event Listener from its Event Source.
Definition: chevents.c:133
void chEvtBroadcastFlagsI(event_source_t *esp, eventflags_t flags)
Signals all the Event Listeners registered on the specified Event Source.
Definition: chevents.c:225
event_listener_t * next
First Event Listener registered on the Event Source.
Definition: chevents.h:75
eventmask_t ewmask
Enabled events mask.
Definition: chschd.h:268
void chSchGoSleepS(tstate_t newstate)
Puts the current thread to sleep into the specified state.
Definition: chschd.c:289
static eventmask_t chEvtAddEventsI(eventmask_t events)
Adds (OR) a set of events to the current thread, this is much faster than using chEvtBroadcast() or c...
Definition: chevents.h:269
void chEvtSignalI(thread_t *tp, eventmask_t events)
Adds a set of event flags directly to the specified thread_t.
Definition: chevents.c:298
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:375
Event Listener structure.
Definition: chevents.h:57
#define MSG_OK
Normal wakeup message.
Definition: chschd.h:39
event_listener_t * next
Next Event Listener registered on the event source.
Definition: chevents.h:58
eventmask_t chEvtWaitAny(eventmask_t events)
Waits for any of the specified events.
Definition: chevents.c:429
eventmask_t chEvtWaitAllTimeout(eventmask_t events, sysinterval_t timeout)
Waits for all the specified events.
Definition: chevents.c:579
void(* evhandler_t)(eventid_t id)
Event Handler callback function.
Definition: chevents.h:83
tstate_t state
Current thread state.
Definition: chschd.h:180
eventmask_t chEvtWaitAnyTimeout(eventmask_t events, sysinterval_t timeout)
Waits for any of the specified events.
Definition: chevents.c:538
union ch_thread::@0 u
State-specific fields.
eventmask_t chEvtGetAndClearEvents(eventmask_t events)
Clears the pending events specified in the events mask.
Definition: chevents.c:179
#define TIME_IMMEDIATE
Zero interval specification for some functions with a timeout specification.
Definition: chtime.h:47
void chDbgCheckClassI(void)
I-class functions context check.
Definition: chdebug.c:233
eventmask_t chEvtWaitAll(eventmask_t events)
Waits for all the specified events.
Definition: chevents.c:457
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:127
#define CH_STATE_WTOREVT
One event.
Definition: chschd.h:77
eventflags_t flags
Flags added to the listener by the event source.
Definition: chevents.h:65
eventflags_t chEvtGetAndClearFlagsI(event_listener_t *elp)
Returns the unmasked flags associated to an event_listener_t.
Definition: chevents.c:346
ChibiOS/RT main include file.
void chEvtDispatch(const evhandler_t *handlers, eventmask_t events)
Invokes the event handlers associated to an event flags mask.
Definition: chevents.c:364
eventmask_t chEvtWaitOneTimeout(eventmask_t events, sysinterval_t timeout)
Waits for exactly one of the specified events.
Definition: chevents.c:495
Structure representing a thread.
Definition: chschd.h:153