TNeo  v1.07
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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
129  ///
130  /// Task waits for **all** of the event bits from the `wait_pattern`
131  /// to be set in the event group
133  ///
134  /// When a task <b>successfully</b> ends waiting for event bit(s), these
135  /// bits get cleared atomically and automatically. Other bits stay
136  /// unchanged.
138 };
139 
140 /**
141  * Modify operation: set, clear or toggle. To be used in `tn_eventgrp_modify()`
142  * / `tn_eventgrp_imodify()` functions.
143  */
144 enum TN_EGrpOp {
145  ///
146  /// Set flags that are set in given `pattern` argument. Note that this
147  /// operation can lead to the context switch, since other high-priority
148  /// task(s) might wait for the event.
150  ///
151  /// Clear flags that are set in the given `pattern` argument.
152  /// This operation can **not** lead to the context switch,
153  /// since tasks can't wait for events to be cleared.
155  ///
156  /// Toggle flags that are set in the given `pattern` argument. Note that this
157  /// operation can lead to the context switch, since other high-priority
158  /// task(s) might wait for the event that was just set (if any).
160 };
161 
162 
163 /**
164  * Attributes that could be given to the event group object.
165  *
166  * Makes sense if only `#TN_OLD_EVENT_API` option is non-zero; otherwise,
167  * there's just one dummy attribute available: `#TN_EVENTGRP_ATTR_NONE`.
168  */
170 #if TN_OLD_EVENT_API || defined(DOXYGEN_ACTIVE)
171  /// \attention deprecated. Available if only `#TN_OLD_EVENT_API` option is
172  /// non-zero.
173  ///
174  /// Indicates that only one task could wait for events in this event group.
175  /// This flag is mutually exclusive with `#TN_EVENTGRP_ATTR_MULTI` flag.
177  ///
178  /// \attention deprecated. Available if only `#TN_OLD_EVENT_API` option is
179  /// non-zero.
180  ///
181  /// Indicates that multiple tasks could wait for events in this event group.
182  /// This flag is mutually exclusive with `#TN_EVENTGRP_ATTR_SINGLE` flag.
184  ///
185  /// \attention strongly deprecated. Available if only `#TN_OLD_EVENT_API`
186  /// option is non-zero. Use `#TN_EVENTGRP_WMODE_AUTOCLR` instead.
187  ///
188  /// Can be specified only in conjunction with `#TN_EVENTGRP_ATTR_SINGLE`
189  /// flag. Indicates that <b>ALL</b> flags in this event group should be
190  /// cleared when task successfully waits for any event in it.
191  ///
192  /// This actually makes little sense to clear ALL events, but this is what
193  /// compatibility mode is for (see `#TN_OLD_EVENT_API`)
195 #endif
196 
197 #if !TN_OLD_EVENT_API || defined(DOXYGEN_ACTIVE)
198  ///
199  /// Dummy attribute that does not change anything. It is needed only for
200  /// the assistance of the events compatibility mode (see
201  /// `#TN_OLD_EVENT_API`)
203 #endif
204 };
205 
206 
207 /**
208  * Event group
209  */
210 struct TN_EventGrp {
211  ///
212  /// id for object validity verification.
213  /// This field is in the beginning of the structure to make it easier
214  /// to detect memory corruption.
216  ///
217  /// task wait queue
219  ///
220  /// current flags pattern
222 
223 #if TN_OLD_EVENT_API || defined(DOXYGEN_ACTIVE)
224  ///
225  /// Attributes that are given to that events group,
226  /// available if only `#TN_OLD_EVENT_API` option is non-zero.
228 #endif
229 
230 };
231 
232 /**
233  * EventGrp-specific fields related to waiting task,
234  * to be included in struct TN_Task.
235  */
237  ///
238  /// event wait pattern
240  ///
241  /// event wait mode: `AND` or `OR`
243  ///
244  /// pattern that caused task to finish waiting
246 };
247 
248 /**
249  * A link to event group: used when event group can be connected to
250  * some kernel object, such as queue.
251  */
252 struct TN_EGrpLink {
253  ///
254  /// event group whose event(s) should be managed by other kernel object
256  ///
257  /// event pattern to manage
259 };
260 
261 
262 /*******************************************************************************
263  * PROTECTED GLOBAL DATA
264  ******************************************************************************/
265 
266 /*******************************************************************************
267  * DEFINITIONS
268  ******************************************************************************/
269 
270 
271 
272 /*******************************************************************************
273  * PUBLIC FUNCTION PROTOTYPES
274  ******************************************************************************/
275 
276 /**
277  * The same as `#tn_eventgrp_create()`, but takes additional argument: `attr`.
278  * It makes sense if only `#TN_OLD_EVENT_API` option is non-zero.
279  *
280  * @param eventgrp
281  * Pointer to already allocated struct TN_EventGrp
282  * @param attr
283  * Attributes for that particular event group object, see `struct
284  * #TN_EGrpAttr`
285  * @param initial_pattern
286  * Initial events pattern.
287  */
289  struct TN_EventGrp *eventgrp,
290  enum TN_EGrpAttr attr,
291  TN_UWord initial_pattern
292  );
293 
294 /**
295  * Construct event group. `id_event` field should not contain `#TN_ID_EVENTGRP`,
296  * otherwise, `#TN_RC_WPARAM` is returned.
297  *
298  * $(TN_CALL_FROM_TASK)
299  * $(TN_CALL_FROM_ISR)
300  * $(TN_LEGEND_LINK)
301  *
302  * @param eventgrp
303  * Pointer to already allocated struct TN_EventGrp
304  * @param initial_pattern
305  * Initial events pattern.
306  *
307  * @return
308  * * `#TN_RC_OK` if event group was successfully created;
309  * * If `#TN_CHECK_PARAM` is non-zero, additional return code
310  * is available: `#TN_RC_WPARAM`.
311  */
313  struct TN_EventGrp *eventgrp,
314  TN_UWord initial_pattern
315  )
316 {
318  eventgrp,
321 #else
323 #endif
324  initial_pattern
325  );
326 }
327 
328 /**
329  * Destruct event group.
330  *
331  * All tasks that wait for the event(s) become runnable with `#TN_RC_DELETED`
332  * code returned.
333  *
334  * $(TN_CALL_FROM_TASK)
335  * $(TN_CAN_SWITCH_CONTEXT)
336  * $(TN_LEGEND_LINK)
337  *
338  * @param eventgrp Pointer to event groupt to be deleted.
339  *
340  * @return
341  * * `#TN_RC_OK` if event group was successfully deleted;
342  * * `#TN_RC_WCONTEXT` if called from wrong context;
343  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
344  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
345  */
346 enum TN_RCode tn_eventgrp_delete(struct TN_EventGrp *eventgrp);
347 
348 /**
349  * Wait for specified event(s) in the event group. If the specified event
350  * is already active, function returns `#TN_RC_OK` immediately. Otherwise,
351  * behavior depends on `timeout` value: refer to `#TN_TickCnt`.
352  *
353  * $(TN_CALL_FROM_TASK)
354  * $(TN_CAN_SWITCH_CONTEXT)
355  * $(TN_CAN_SLEEP)
356  * $(TN_LEGEND_LINK)
357  *
358  * @param eventgrp
359  * Pointer to event group to wait events from
360  * @param wait_pattern
361  * Events bit pattern for which task should wait
362  * @param wait_mode
363  * Specifies whether task should wait for **all** the event bits from
364  * `wait_pattern` to be set, or for just **any** of them
365  * (see enum `#TN_EGrpWaitMode`)
366  * @param p_flags_pattern
367  * Pointer to the `TN_UWord` variable in which actual event pattern
368  * that caused task to stop waiting will be stored.
369  * May be `TN_NULL`.
370  * @param timeout
371  * refer to `#TN_TickCnt`
372  *
373  * @return
374  * * `#TN_RC_OK` if specified event is active (so the task can check
375  * variable pointed to by `p_flags_pattern` if it wasn't `TN_NULL`).
376  * * `#TN_RC_WCONTEXT` if called from wrong context;
377  * * Other possible return codes depend on `timeout` value,
378  * refer to `#TN_TickCnt`
379  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
380  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
381  */
383  struct TN_EventGrp *eventgrp,
384  TN_UWord wait_pattern,
385  enum TN_EGrpWaitMode wait_mode,
386  TN_UWord *p_flags_pattern,
387  TN_TickCnt timeout
388  );
389 
390 /**
391  * The same as `tn_eventgrp_wait()` with zero timeout.
392  *
393  * $(TN_CALL_FROM_TASK)
394  * $(TN_CAN_SWITCH_CONTEXT)
395  * $(TN_LEGEND_LINK)
396  */
398  struct TN_EventGrp *eventgrp,
399  TN_UWord wait_pattern,
400  enum TN_EGrpWaitMode wait_mode,
401  TN_UWord *p_flags_pattern
402  );
403 
404 /**
405  * The same as `tn_eventgrp_wait()` with zero timeout, but for using in the ISR.
406  *
407  * $(TN_CALL_FROM_ISR)
408  * $(TN_CAN_SWITCH_CONTEXT)
409  * $(TN_LEGEND_LINK)
410  */
412  struct TN_EventGrp *eventgrp,
413  TN_UWord wait_pattern,
414  enum TN_EGrpWaitMode wait_mode,
415  TN_UWord *p_flags_pattern
416  );
417 
418 /**
419  * Modify current events bit pattern in the event group. Behavior depends
420  * on the given `operation`: refer to `enum #TN_EGrpOp`
421  *
422  * $(TN_CALL_FROM_TASK)
423  * $(TN_CAN_SWITCH_CONTEXT)
424  * $(TN_LEGEND_LINK)
425  *
426  * @param eventgrp
427  * Pointer to event group to modify events in
428  * @param operation
429  * Actual operation to perform: set, clear or toggle.
430  * Refer to `enum #TN_EGrpOp`
431  * @param pattern
432  * Events pattern to be applied (depending on `operation` value)
433  *
434  * @return
435  * * `#TN_RC_OK` on success;
436  * * `#TN_RC_WCONTEXT` if called from wrong context;
437  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
438  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
439  */
441  struct TN_EventGrp *eventgrp,
442  enum TN_EGrpOp operation,
444  );
445 
446 /**
447  * The same as `tn_eventgrp_modify()`, but for using in the ISR.
448  *
449  * $(TN_CALL_FROM_ISR)
450  * $(TN_CAN_SWITCH_CONTEXT)
451  * $(TN_LEGEND_LINK)
452  */
454  struct TN_EventGrp *eventgrp,
455  enum TN_EGrpOp operation,
457  );
458 
459 
460 #ifdef __cplusplus
461 } /* extern "C" */
462 #endif
463 
464 #endif // _TN_EVENTGRP_H
465 
466 /*******************************************************************************
467  * end of file
468  ******************************************************************************/
469 
470 
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:137
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:132
enum TN_EGrpWaitMode wait_mode
event wait mode: AND or OR
Definition: tn_eventgrp.h:242
Circular doubly linked list, for internal kernel usage.
TN_EGrpOp
Modify operation: set, clear or toggle.
Definition: tn_eventgrp.h:144
Clear flags that are set in the given pattern argument.
Definition: tn_eventgrp.h:154
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:81
#define _TN_INLINE
If compiler does not conform to c99 standard, there's no inline keyword.
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:236
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:159
Task waits for any of the event bits from the wait_pattern to be set in the event group...
Definition: tn_eventgrp.h:128
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:215
#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:227
TN_EGrpAttr
Attributes that could be given to the event group object.
Definition: tn_eventgrp.h:169
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:210
TN_UWord wait_pattern
event wait pattern
Definition: tn_eventgrp.h:239
static _TN_INLINE enum TN_RCode tn_eventgrp_create(struct TN_EventGrp *eventgrp, TN_UWord initial_pattern)
Construct event group.
Definition: tn_eventgrp.h:312
Kernel system routines: system start, tick processing, time slice managing.
Set flags that are set in given pattern argument.
Definition: tn_eventgrp.h:149
TN_UWord actual_pattern
pattern that caused task to finish waiting
Definition: tn_eventgrp.h:245
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:202
TN_UWord pattern
current flags pattern
Definition: tn_eventgrp.h:221
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:218