TNeo  v1.08
tn_eventgrp.h
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * TNeo: real-time kernel initially based on TNKernel
4  *
5  * TNKernel: copyright 2004, 2013 Yuri Tiomkin.
6  * PIC32-specific routines: copyright 2013, 2014 Anders Montonen.
7  * TNeo: copyright 2014 Dmitry Frank.
8  *
9  * TNeo was born as a thorough review and re-implementation of
10  * TNKernel. The new kernel has well-formed code, inherited bugs are fixed
11  * as well as new features being added, and it is tested carefully with
12  * unit-tests.
13  *
14  * API is changed somewhat, so it's not 100% compatible with TNKernel,
15  * hence the new name: TNeo.
16  *
17  * Permission to use, copy, modify, and distribute this software in source
18  * and binary forms and its documentation for any purpose and without fee
19  * is hereby granted, provided that the above copyright notice appear
20  * in all copies and that both that copyright notice and this permission
21  * notice appear in supporting documentation.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33  * THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  ******************************************************************************/
36 
37 /**
38  * \file
39  *
40  * Event group.
41  *
42  * An event group has an internal variable (of type `#TN_UWord`), which is
43  * interpreted as a bit pattern where each bit represents an event. An event
44  * group also has a wait queue for the tasks waiting on these events. A task
45  * may set specified bits when an event occurs and may clear specified bits
46  * when necessary.
47  *
48  * The tasks waiting for an event(s) are placed in the event group's wait
49  * queue. An event group is a very suitable synchronization object for cases
50  * where (for some reasons) one task has to wait for many tasks, or vice versa,
51  * many tasks have to wait for one task.
52  *
53  * \section eventgrp_connect Connecting an event group to other system objects
54  *
55  * Sometimes task needs to wait for different system events, the most common
56  * examples are:
57  *
58  * - wait for a message from the queue(s) plus wait for some
59  * application-dependent event (such as a flag to finish the task, or
60  * whatever);
61  * - wait for messages from multiple queues.
62  *
63  * If the kernel doesn't offer a mechanism for that, programmer usually have to
64  * use polling services on these queues and sleep for a few system ticks.
65  * Obviously, this approach has serious drawbacks: we have a lot of useless
66  * context switches, and response for the message gets much slower. Actually,
67  * we lost the main goal of the preemptive kernel when we use polling services
68  * like that.
69  *
70  * TNeo offers a solution: an event group can be connected to other
71  * kernel objects, and these objects will maintain certain flags inside that
72  * event group automatically.
73  *
74  * So, in case of multiple queues, we can act as follows (assume we have two
75  * queues: Q1 and Q2) :
76  *
77  * - create event group EG;
78  * - connect EG with flag 1 to Q1;
79  * - connect EG with flag 2 to Q2;
80  * - when task needs to receive a message from either Q1 or Q2, it just waits
81  * for the any of flags 1 or 2 in the EG, this is done in the single call
82  * to `tn_eventgrp_wait()`.
83  * - when that event happened, task checks which flag is set, and receive
84  * message from the appropriate queue.
85  *
86  * Please note that task waiting for the event should **not** clear the flag
87  * manually: this flag is maintained completely by the queue. If the queue is
88  * non-empty, the flag is set. If the queue becomes empty, the flag is cleared.
89  *
90  * For the information on system services related to queue, refer to the \ref
91  * tn_dqueue.h "queue reference".
92  *
93  * There is an example project available that demonstrates event group
94  * connection technique: `examples/queue_eventgrp_conn`. Be sure to examine the
95  * readme there.
96  *
97  */
98 
99 #ifndef _TN_EVENTGRP_H
100 #define _TN_EVENTGRP_H
101 
102 /*******************************************************************************
103  * INCLUDED FILES
104  ******************************************************************************/
105 
106 #include "tn_list.h"
107 #include "tn_common.h"
108 #include "tn_sys.h"
109 
110 
111 
112 #ifdef __cplusplus
113 extern "C" { /*}*/
114 #endif
115 
116 /*******************************************************************************
117  * PUBLIC TYPES
118  ******************************************************************************/
119 
120 /**
121  * Events waiting mode that should be given to `#tn_eventgrp_wait()` and
122  * friends.
123  */
125  ///
126  /// Task waits for **any** of the event bits from the `wait_pattern`
127  /// to be set in the event group.
128  /// This flag is mutually exclusive with `#TN_EVENTGRP_WMODE_AND`.
130  ///
131  /// Task waits for **all** of the event bits from the `wait_pattern`
132  /// to be set in the event group.
133  /// This flag is mutually exclusive with `#TN_EVENTGRP_WMODE_OR`.
135  ///
136  /// When a task <b>successfully</b> ends waiting for event bit(s), these
137  /// bits get cleared atomically and automatically. Other bits stay
138  /// unchanged.
140 };
141 
142 /**
143  * Modify operation: set, clear or toggle. To be used in `tn_eventgrp_modify()`
144  * / `tn_eventgrp_imodify()` functions.
145  */
146 enum TN_EGrpOp {
147  ///
148  /// Set flags that are set in given `pattern` argument. Note that this
149  /// operation can lead to the context switch, since other high-priority
150  /// task(s) might wait for the event.
152  ///
153  /// Clear flags that are set in the given `pattern` argument.
154  /// This operation can **not** lead to the context switch,
155  /// since tasks can't wait for events to be cleared.
157  ///
158  /// Toggle flags that are set in the given `pattern` argument. Note that this
159  /// operation can lead to the context switch, since other high-priority
160  /// task(s) might wait for the event that was just set (if any).
162 };
163 
164 
165 /**
166  * Attributes that could be given to the event group object.
167  *
168  * Makes sense if only `#TN_OLD_EVENT_API` option is non-zero; otherwise,
169  * there's just one dummy attribute available: `#TN_EVENTGRP_ATTR_NONE`.
170  */
172 #if TN_OLD_EVENT_API || defined(DOXYGEN_ACTIVE)
173  /// \attention deprecated. Available if only `#TN_OLD_EVENT_API` option is
174  /// non-zero.
175  ///
176  /// Indicates that only one task could wait for events in this event group.
177  /// This flag is mutually exclusive with `#TN_EVENTGRP_ATTR_MULTI` flag.
179  ///
180  /// \attention deprecated. Available if only `#TN_OLD_EVENT_API` option is
181  /// non-zero.
182  ///
183  /// Indicates that multiple tasks could wait for events in this event group.
184  /// This flag is mutually exclusive with `#TN_EVENTGRP_ATTR_SINGLE` flag.
186  ///
187  /// \attention strongly deprecated. Available if only `#TN_OLD_EVENT_API`
188  /// option is non-zero. Use `#TN_EVENTGRP_WMODE_AUTOCLR` instead.
189  ///
190  /// Can be specified only in conjunction with `#TN_EVENTGRP_ATTR_SINGLE`
191  /// flag. Indicates that <b>ALL</b> flags in this event group should be
192  /// cleared when task successfully waits for any event in it.
193  ///
194  /// This actually makes little sense to clear ALL events, but this is what
195  /// compatibility mode is for (see `#TN_OLD_EVENT_API`)
197 #endif
198 
199 #if !TN_OLD_EVENT_API || defined(DOXYGEN_ACTIVE)
200  ///
201  /// Dummy attribute that does not change anything. It is needed only for
202  /// the assistance of the events compatibility mode (see
203  /// `#TN_OLD_EVENT_API`)
205 #endif
206 };
207 
208 
209 /**
210  * Event group
211  */
212 struct TN_EventGrp {
213  ///
214  /// id for object validity verification.
215  /// This field is in the beginning of the structure to make it easier
216  /// to detect memory corruption.
218  ///
219  /// task wait queue
221  ///
222  /// current flags pattern
224 
225 #if TN_OLD_EVENT_API || defined(DOXYGEN_ACTIVE)
226  ///
227  /// Attributes that are given to that events group,
228  /// available if only `#TN_OLD_EVENT_API` option is non-zero.
230 #endif
231 
232 };
233 
234 /**
235  * EventGrp-specific fields related to waiting task,
236  * to be included in struct TN_Task.
237  */
239  ///
240  /// event wait pattern
242  ///
243  /// event wait mode: `AND` or `OR`
244  enum TN_EGrpWaitMode wait_mode;
245  ///
246  /// pattern that caused task to finish waiting
248 };
249 
250 /**
251  * A link to event group: used when event group can be connected to
252  * some kernel object, such as queue.
253  */
254 struct TN_EGrpLink {
255  ///
256  /// event group whose event(s) should be managed by other kernel object
258  ///
259  /// event pattern to manage
261 };
262 
263 
264 /*******************************************************************************
265  * PROTECTED GLOBAL DATA
266  ******************************************************************************/
267 
268 /*******************************************************************************
269  * DEFINITIONS
270  ******************************************************************************/
271 
272 
273 
274 /*******************************************************************************
275  * PUBLIC FUNCTION PROTOTYPES
276  ******************************************************************************/
277 
278 /**
279  * The same as `#tn_eventgrp_create()`, but takes additional argument: `attr`.
280  * It makes sense if only `#TN_OLD_EVENT_API` option is non-zero.
281  *
282  * @param eventgrp
283  * Pointer to already allocated struct TN_EventGrp
284  * @param attr
285  * Attributes for that particular event group object, see `struct
286  * #TN_EGrpAttr`
287  * @param initial_pattern
288  * Initial events pattern.
289  */
291  struct TN_EventGrp *eventgrp,
292  enum TN_EGrpAttr attr,
293  TN_UWord initial_pattern
294  );
295 
296 /**
297  * Construct event group. `id_event` field should not contain `#TN_ID_EVENTGRP`,
298  * otherwise, `#TN_RC_WPARAM` is returned.
299  *
300  * $(TN_CALL_FROM_TASK)
301  * $(TN_CALL_FROM_ISR)
302  * $(TN_LEGEND_LINK)
303  *
304  * @param eventgrp
305  * Pointer to already allocated struct TN_EventGrp
306  * @param initial_pattern
307  * Initial events pattern.
308  *
309  * @return
310  * * `#TN_RC_OK` if event group was successfully created;
311  * * If `#TN_CHECK_PARAM` is non-zero, additional return code
312  * is available: `#TN_RC_WPARAM`.
313  */
315  struct TN_EventGrp *eventgrp,
316  TN_UWord initial_pattern
317  )
318 {
320  eventgrp,
323 #else
325 #endif
326  initial_pattern
327  );
328 }
329 
330 /**
331  * Destruct event group.
332  *
333  * All tasks that wait for the event(s) become runnable with `#TN_RC_DELETED`
334  * code returned.
335  *
336  * $(TN_CALL_FROM_TASK)
337  * $(TN_CAN_SWITCH_CONTEXT)
338  * $(TN_LEGEND_LINK)
339  *
340  * @param eventgrp Pointer to event groupt to be deleted.
341  *
342  * @return
343  * * `#TN_RC_OK` if event group was successfully deleted;
344  * * `#TN_RC_WCONTEXT` if called from wrong context;
345  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
346  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
347  */
348 enum TN_RCode tn_eventgrp_delete(struct TN_EventGrp *eventgrp);
349 
350 /**
351  * Wait for specified event(s) in the event group. If the specified event
352  * is already active, function returns `#TN_RC_OK` immediately. Otherwise,
353  * behavior depends on `timeout` value: refer to `#TN_TickCnt`.
354  *
355  * $(TN_CALL_FROM_TASK)
356  * $(TN_CAN_SWITCH_CONTEXT)
357  * $(TN_CAN_SLEEP)
358  * $(TN_LEGEND_LINK)
359  *
360  * @param eventgrp
361  * Pointer to event group to wait events from
362  * @param wait_pattern
363  * Events bit pattern for which task should wait
364  * @param wait_mode
365  * Specifies whether task should wait for **all** the event bits from
366  * `wait_pattern` to be set, or for just **any** of them
367  * (see enum `#TN_EGrpWaitMode`)
368  * @param p_flags_pattern
369  * Pointer to the `TN_UWord` variable in which actual event pattern
370  * that caused task to stop waiting will be stored.
371  * May be `TN_NULL`.
372  * @param timeout
373  * refer to `#TN_TickCnt`
374  *
375  * @return
376  * * `#TN_RC_OK` if specified event is active (so the task can check
377  * variable pointed to by `p_flags_pattern` if it wasn't `TN_NULL`).
378  * * `#TN_RC_WCONTEXT` if called from wrong context;
379  * * Other possible return codes depend on `timeout` value,
380  * refer to `#TN_TickCnt`
381  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
382  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
383  */
385  struct TN_EventGrp *eventgrp,
386  TN_UWord wait_pattern,
387  enum TN_EGrpWaitMode wait_mode,
388  TN_UWord *p_flags_pattern,
389  TN_TickCnt timeout
390  );
391 
392 /**
393  * The same as `tn_eventgrp_wait()` with zero timeout.
394  *
395  * $(TN_CALL_FROM_TASK)
396  * $(TN_CAN_SWITCH_CONTEXT)
397  * $(TN_LEGEND_LINK)
398  */
400  struct TN_EventGrp *eventgrp,
401  TN_UWord wait_pattern,
402  enum TN_EGrpWaitMode wait_mode,
403  TN_UWord *p_flags_pattern
404  );
405 
406 /**
407  * The same as `tn_eventgrp_wait()` with zero timeout, but for using in the ISR.
408  *
409  * $(TN_CALL_FROM_ISR)
410  * $(TN_CAN_SWITCH_CONTEXT)
411  * $(TN_LEGEND_LINK)
412  */
414  struct TN_EventGrp *eventgrp,
415  TN_UWord wait_pattern,
416  enum TN_EGrpWaitMode wait_mode,
417  TN_UWord *p_flags_pattern
418  );
419 
420 /**
421  * Modify current events bit pattern in the event group. Behavior depends
422  * on the given `operation`: refer to `enum #TN_EGrpOp`
423  *
424  * $(TN_CALL_FROM_TASK)
425  * $(TN_CAN_SWITCH_CONTEXT)
426  * $(TN_LEGEND_LINK)
427  *
428  * @param eventgrp
429  * Pointer to event group to modify events in
430  * @param operation
431  * Actual operation to perform: set, clear or toggle.
432  * Refer to `enum #TN_EGrpOp`
433  * @param pattern
434  * Events pattern to be applied (depending on `operation` value)
435  *
436  * @return
437  * * `#TN_RC_OK` on success;
438  * * `#TN_RC_WCONTEXT` if called from wrong context;
439  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
440  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
441  */
443  struct TN_EventGrp *eventgrp,
444  enum TN_EGrpOp operation,
446  );
447 
448 /**
449  * The same as `tn_eventgrp_modify()`, but for using in the ISR.
450  *
451  * $(TN_CALL_FROM_ISR)
452  * $(TN_CAN_SWITCH_CONTEXT)
453  * $(TN_LEGEND_LINK)
454  */
456  struct TN_EventGrp *eventgrp,
457  enum TN_EGrpOp operation,
458  TN_UWord pattern
459  );
460 
461 
462 #ifdef __cplusplus
463 } /* extern "C" */
464 #endif
465 
466 #endif // _TN_EVENTGRP_H
467 
468 /*******************************************************************************
469  * end of file
470  ******************************************************************************/
471 
472 
enum TN_RCode tn_eventgrp_create_wattr(struct TN_EventGrp *eventgrp, enum TN_EGrpAttr attr, TN_UWord initial_pattern)
The same as tn_eventgrp_create(), but takes additional argument: attr.
When a task successfully ends waiting for event bit(s), these bits get cleared atomically and automat...
Definition: tn_eventgrp.h:139
enum TN_RCode tn_eventgrp_iwait_polling(struct TN_EventGrp *eventgrp, TN_UWord wait_pattern, enum TN_EGrpWaitMode wait_mode, TN_UWord *p_flags_pattern)
The same as tn_eventgrp_wait() with zero timeout, but for using in the ISR.
Task waits for all of the event bits from the wait_pattern to be set in the event group...
Definition: tn_eventgrp.h:134
Circular doubly linked list, for internal kernel usage.
TN_EGrpOp
Modify operation: set, clear or toggle.
Definition: tn_eventgrp.h:146
Clear flags that are set in the given pattern argument.
Definition: tn_eventgrp.h:156
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:81
TN_ObjId
Magic number for object validity verification.
Definition: tn_common.h:65
EventGrp-specific fields related to waiting task, to be included in struct TN_Task.
Definition: tn_eventgrp.h:238
unsigned long TN_TickCnt
Type for system tick count, it is used by the kernel to represent absolute tick count value as well a...
Definition: tn_common.h:188
TN_EGrpWaitMode
Events waiting mode that should be given to tn_eventgrp_wait() and friends.
Definition: tn_eventgrp.h:124
Definitions used through the whole kernel.
enum TN_RCode tn_eventgrp_imodify(struct TN_EventGrp *eventgrp, enum TN_EGrpOp operation, TN_UWord pattern)
The same as tn_eventgrp_modify(), but for using in the ISR.
Toggle flags that are set in the given pattern argument.
Definition: tn_eventgrp.h:161
Task waits for any of the event bits from the wait_pattern to be set in the event group...
Definition: tn_eventgrp.h:129
enum TN_RCode tn_eventgrp_wait(struct TN_EventGrp *eventgrp, TN_UWord wait_pattern, enum TN_EGrpWaitMode wait_mode, TN_UWord *p_flags_pattern, TN_TickCnt timeout)
Wait for specified event(s) in the event group.
enum TN_ObjId id_event
id for object validity verification.
Definition: tn_eventgrp.h:217
#define TN_OLD_EVENT_API
Whether the old TNKernel events API compatibility mode is active.
enum TN_EGrpAttr attr
Attributes that are given to that events group, available if only TN_OLD_EVENT_API option is non-zero...
Definition: tn_eventgrp.h:229
TN_EGrpAttr
Attributes that could be given to the event group object.
Definition: tn_eventgrp.h:171
enum TN_RCode tn_eventgrp_modify(struct TN_EventGrp *eventgrp, enum TN_EGrpOp operation, TN_UWord pattern)
Modify current events bit pattern in the event group.
enum TN_RCode tn_eventgrp_delete(struct TN_EventGrp *eventgrp)
Destruct event group.
Event group.
Definition: tn_eventgrp.h:212
#define _TN_STATIC_INLINE
For some compilers, order of these qualifiers matters (at least when _TN_INLINE expands to some compi...
TN_UWord wait_pattern
event wait pattern
Definition: tn_eventgrp.h:241
_TN_STATIC_INLINE enum TN_RCode tn_eventgrp_create(struct TN_EventGrp *eventgrp, TN_UWord initial_pattern)
Construct event group.
Definition: tn_eventgrp.h:314
Kernel system routines: system start, tick processing, time slice managing.
Set flags that are set in given pattern argument.
Definition: tn_eventgrp.h:151
TN_UWord actual_pattern
pattern that caused task to finish waiting
Definition: tn_eventgrp.h:247
Circular doubly linked list item, for internal kernel usage.
Definition: tn_list.h:63
unsigned int TN_UWord
Unsigned integer type whose size is equal to the size of CPU register.
Dummy attribute that does not change anything.
Definition: tn_eventgrp.h:204
TN_UWord pattern
current flags pattern
Definition: tn_eventgrp.h:223
enum TN_RCode tn_eventgrp_wait_polling(struct TN_EventGrp *eventgrp, TN_UWord wait_pattern, enum TN_EGrpWaitMode wait_mode, TN_UWord *p_flags_pattern)
The same as tn_eventgrp_wait() with zero timeout.
struct TN_ListItem wait_queue
task wait queue
Definition: tn_eventgrp.h:220