TNeo  v1.06
 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  struct TN_ListItem wait_queue; //!< task wait queue
212  TN_UWord pattern; //!< current flags pattern
213  enum TN_ObjId id_event; //!< id for object validity verification
214 
215 #if TN_OLD_EVENT_API || defined(DOXYGEN_ACTIVE)
216  ///
217  /// Attributes that are given to that events group,
218  /// available if only `#TN_OLD_EVENT_API` option is non-zero.
220 #endif
221 
222 };
223 
224 /**
225  * EventGrp-specific fields related to waiting task,
226  * to be included in struct TN_Task.
227  */
229  ///
230  /// event wait pattern
232  ///
233  /// event wait mode: `AND` or `OR`
235  ///
236  /// pattern that caused task to finish waiting
238 };
239 
240 /**
241  * A link to event group: used when event group can be connected to
242  * some kernel object, such as queue.
243  */
244 struct TN_EGrpLink {
245  ///
246  /// event group whose event(s) should be managed by other kernel object
248  ///
249  /// event pattern to manage
251 };
252 
253 
254 /*******************************************************************************
255  * PROTECTED GLOBAL DATA
256  ******************************************************************************/
257 
258 /*******************************************************************************
259  * DEFINITIONS
260  ******************************************************************************/
261 
262 
263 
264 /*******************************************************************************
265  * PUBLIC FUNCTION PROTOTYPES
266  ******************************************************************************/
267 
268 /**
269  * The same as `#tn_eventgrp_create()`, but takes additional argument: `attr`.
270  * It makes sense if only `#TN_OLD_EVENT_API` option is non-zero.
271  *
272  * @param eventgrp
273  * Pointer to already allocated struct TN_EventGrp
274  * @param attr
275  * Attributes for that particular event group object, see `struct
276  * #TN_EGrpAttr`
277  * @param initial_pattern
278  * Initial events pattern.
279  */
281  struct TN_EventGrp *eventgrp,
282  enum TN_EGrpAttr attr,
283  TN_UWord initial_pattern
284  );
285 
286 /**
287  * Construct event group. `id_event` field should not contain `#TN_ID_EVENTGRP`,
288  * otherwise, `#TN_RC_WPARAM` is returned.
289  *
290  * $(TN_CALL_FROM_TASK)
291  * $(TN_CALL_FROM_ISR)
292  * $(TN_LEGEND_LINK)
293  *
294  * @param eventgrp
295  * Pointer to already allocated struct TN_EventGrp
296  * @param initial_pattern
297  * Initial events pattern.
298  *
299  * @return
300  * * `#TN_RC_OK` if event group was successfully created;
301  * * If `#TN_CHECK_PARAM` is non-zero, additional return code
302  * is available: `#TN_RC_WPARAM`.
303  */
305  struct TN_EventGrp *eventgrp,
306  TN_UWord initial_pattern
307  )
308 {
310  eventgrp,
313 #else
315 #endif
316  initial_pattern
317  );
318 }
319 
320 /**
321  * Destruct event group.
322  *
323  * All tasks that wait for the event(s) become runnable with `#TN_RC_DELETED`
324  * code returned.
325  *
326  * $(TN_CALL_FROM_TASK)
327  * $(TN_CAN_SWITCH_CONTEXT)
328  * $(TN_LEGEND_LINK)
329  *
330  * @param eventgrp Pointer to event groupt to be deleted.
331  *
332  * @return
333  * * `#TN_RC_OK` if event group was successfully deleted;
334  * * `#TN_RC_WCONTEXT` if called from wrong context;
335  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
336  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
337  */
338 enum TN_RCode tn_eventgrp_delete(struct TN_EventGrp *eventgrp);
339 
340 /**
341  * Wait for specified event(s) in the event group. If the specified event
342  * is already active, function returns `#TN_RC_OK` immediately. Otherwise,
343  * behavior depends on `timeout` value: refer to `#TN_TickCnt`.
344  *
345  * $(TN_CALL_FROM_TASK)
346  * $(TN_CAN_SWITCH_CONTEXT)
347  * $(TN_CAN_SLEEP)
348  * $(TN_LEGEND_LINK)
349  *
350  * @param eventgrp
351  * Pointer to event group to wait events from
352  * @param wait_pattern
353  * Events bit pattern for which task should wait
354  * @param wait_mode
355  * Specifies whether task should wait for **all** the event bits from
356  * `wait_pattern` to be set, or for just **any** of them
357  * (see enum `#TN_EGrpWaitMode`)
358  * @param p_flags_pattern
359  * Pointer to the `TN_UWord` variable in which actual event pattern
360  * that caused task to stop waiting will be stored.
361  * May be `TN_NULL`.
362  * @param timeout
363  * refer to `#TN_TickCnt`
364  *
365  * @return
366  * * `#TN_RC_OK` if specified event is active (so the task can check
367  * variable pointed to by `p_flags_pattern` if it wasn't `TN_NULL`).
368  * * `#TN_RC_WCONTEXT` if called from wrong context;
369  * * Other possible return codes depend on `timeout` value,
370  * refer to `#TN_TickCnt`
371  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
372  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
373  */
375  struct TN_EventGrp *eventgrp,
376  TN_UWord wait_pattern,
377  enum TN_EGrpWaitMode wait_mode,
378  TN_UWord *p_flags_pattern,
379  TN_TickCnt timeout
380  );
381 
382 /**
383  * The same as `tn_eventgrp_wait()` with zero timeout.
384  *
385  * $(TN_CALL_FROM_TASK)
386  * $(TN_CAN_SWITCH_CONTEXT)
387  * $(TN_LEGEND_LINK)
388  */
390  struct TN_EventGrp *eventgrp,
391  TN_UWord wait_pattern,
392  enum TN_EGrpWaitMode wait_mode,
393  TN_UWord *p_flags_pattern
394  );
395 
396 /**
397  * The same as `tn_eventgrp_wait()` with zero timeout, but for using in the ISR.
398  *
399  * $(TN_CALL_FROM_ISR)
400  * $(TN_CAN_SWITCH_CONTEXT)
401  * $(TN_LEGEND_LINK)
402  */
404  struct TN_EventGrp *eventgrp,
405  TN_UWord wait_pattern,
406  enum TN_EGrpWaitMode wait_mode,
407  TN_UWord *p_flags_pattern
408  );
409 
410 /**
411  * Modify current events bit pattern in the event group. Behavior depends
412  * on the given `operation`: refer to `enum #TN_EGrpOp`
413  *
414  * $(TN_CALL_FROM_TASK)
415  * $(TN_CAN_SWITCH_CONTEXT)
416  * $(TN_LEGEND_LINK)
417  *
418  * @param eventgrp
419  * Pointer to event group to modify events in
420  * @param operation
421  * Actual operation to perform: set, clear or toggle.
422  * Refer to `enum #TN_EGrpOp`
423  * @param pattern
424  * Events pattern to be applied (depending on `operation` value)
425  *
426  * @return
427  * * `#TN_RC_OK` on success;
428  * * `#TN_RC_WCONTEXT` if called from wrong context;
429  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
430  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
431  */
433  struct TN_EventGrp *eventgrp,
434  enum TN_EGrpOp operation,
436  );
437 
438 /**
439  * The same as `tn_eventgrp_modify()`, but for using in the ISR.
440  *
441  * $(TN_CALL_FROM_ISR)
442  * $(TN_CAN_SWITCH_CONTEXT)
443  * $(TN_LEGEND_LINK)
444  */
446  struct TN_EventGrp *eventgrp,
447  enum TN_EGrpOp operation,
449  );
450 
451 
452 #ifdef __cplusplus
453 } /* extern "C" */
454 #endif
455 
456 #endif // _TN_EVENTGRP_H
457 
458 /*******************************************************************************
459  * end of file
460  ******************************************************************************/
461 
462 
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:234
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:228
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:213
#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:219
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:231
static _TN_INLINE enum TN_RCode tn_eventgrp_create(struct TN_EventGrp *eventgrp, TN_UWord initial_pattern)
Construct event group.
Definition: tn_eventgrp.h:304
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:237
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:212
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:211