TNeoKernel  v1.04
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tn_eventgrp.h
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * TNeoKernel: 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  * TNeoKernel: copyright © 2014 Dmitry Frank.
8  *
9  * TNeoKernel 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: TNeoKernel.
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  * TNeoKernel 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: wait for all flags to be set or just for any of the
122  * specified flags to be set.
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 
135 /**
136  * Modify operation: set, clear or toggle. To be used in `tn_eventgrp_modify()`
137  * / `tn_eventgrp_imodify()` functions.
138  */
139 enum TN_EGrpOp {
140  ///
141  /// Set flags that are set in given `pattern` argument. Note that this
142  /// operation can lead to the context switch, since other high-priority
143  /// task(s) might wait for the event.
145  ///
146  /// Clear flags that are set in the given `pattern` argument.
147  /// This operation can **not** lead to the context switch,
148  /// since tasks can't wait for events to be cleared.
150  /// Toggle flags that are set in the given `pattern` argument. Note that this
151  /// operation can lead to the context switch, since other high-priority
152  /// task(s) might wait for the event that was just set (if any).
154 };
155 
156 /**
157  * Event group
158  */
159 struct TN_EventGrp {
160  struct TN_ListItem wait_queue; //!< task wait queue
161  TN_UWord pattern; //!< current flags pattern
162  enum TN_ObjId id_event; //!< id for object validity verification
163 };
164 
165 /**
166  * EventGrp-specific fields related to waiting task,
167  * to be included in struct TN_Task.
168  */
170  ///
171  /// event wait pattern
173  ///
174  /// event wait mode: `AND` or `OR`
176  ///
177  /// pattern that caused task to finish waiting
179 };
180 
181 /**
182  * A link to event group: used when event group can be connected to
183  * some kernel object, such as queue.
184  */
185 struct TN_EGrpLink {
186  ///
187  /// event group whose event(s) should be managed by other kernel object
189  ///
190  /// event pattern to manage
192 };
193 
194 
195 /*******************************************************************************
196  * GLOBAL VARIABLES
197  ******************************************************************************/
198 
199 /*******************************************************************************
200  * DEFINITIONS
201  ******************************************************************************/
202 
203 
204 
205 /*******************************************************************************
206  * PUBLIC FUNCTION PROTOTYPES
207  ******************************************************************************/
208 
209 /**
210  * Construct event group. `id_event` field should not contain `#TN_ID_EVENTGRP`,
211  * otherwise, `#TN_RC_WPARAM` is returned.
212  *
213  * $(TN_CALL_FROM_TASK)
214  * $(TN_CALL_FROM_ISR)
215  * $(TN_LEGEND_LINK)
216  *
217  * @param eventgrp
218  * Pointer to already allocated struct TN_EventGrp
219  * @param initial_pattern
220  * Initial events pattern.
221  *
222  * @return
223  * * `#TN_RC_OK` if event group was successfully created;
224  * * If `#TN_CHECK_PARAM` is non-zero, additional return code
225  * is available: `#TN_RC_WPARAM`.
226  */
228  struct TN_EventGrp *eventgrp,
229  TN_UWord initial_pattern
230  );
231 
232 /**
233  * Destruct event group.
234  *
235  * All tasks that wait for the event(s) become runnable with `#TN_RC_DELETED`
236  * code returned.
237  *
238  * $(TN_CALL_FROM_TASK)
239  * $(TN_CAN_SWITCH_CONTEXT)
240  * $(TN_LEGEND_LINK)
241  *
242  * @param eventgrp Pointer to event groupt to be deleted.
243  *
244  * @return
245  * * `#TN_RC_OK` if event group was successfully deleted;
246  * * `#TN_RC_WCONTEXT` if called from wrong context;
247  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
248  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
249  */
250 enum TN_RCode tn_eventgrp_delete(struct TN_EventGrp *eventgrp);
251 
252 /**
253  * Wait for specified event(s) in the event group. If the specified event
254  * is already active, function returns `#TN_RC_OK` immediately. Otherwise,
255  * behavior depends on `timeout` value: refer to `#TN_Timeout`.
256  *
257  * $(TN_CALL_FROM_TASK)
258  * $(TN_CAN_SWITCH_CONTEXT)
259  * $(TN_CAN_SLEEP)
260  * $(TN_LEGEND_LINK)
261  *
262  * @param eventgrp
263  * Pointer to event group to wait events from
264  * @param wait_pattern
265  * Events bit pattern for which task should wait
266  * @param wait_mode
267  * Specifies whether task should wait for **all** the event bits from
268  * `wait_pattern` to be set, or for just **any** of them
269  * (see enum `#TN_EGrpWaitMode`)
270  * @param p_flags_pattern
271  * Pointer to the `TN_UWord` variable in which actual event pattern
272  * that caused task to stop waiting will be stored.
273  * May be `TN_NULL`.
274  * @param timeout
275  * refer to `#TN_Timeout`
276  *
277  * @return
278  * * `#TN_RC_OK` if specified event is active (so the task can check
279  * variable pointed to by `p_flags_pattern` if it wasn't `TN_NULL`).
280  * * `#TN_RC_WCONTEXT` if called from wrong context;
281  * * Other possible return codes depend on `timeout` value,
282  * refer to `#TN_Timeout`
283  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
284  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
285  */
287  struct TN_EventGrp *eventgrp,
288  TN_UWord wait_pattern,
289  enum TN_EGrpWaitMode wait_mode,
290  TN_UWord *p_flags_pattern,
291  TN_Timeout timeout
292  );
293 
294 /**
295  * The same as `tn_eventgrp_wait()` with zero timeout.
296  *
297  * $(TN_CALL_FROM_TASK)
298  * $(TN_CAN_SWITCH_CONTEXT)
299  * $(TN_LEGEND_LINK)
300  */
302  struct TN_EventGrp *eventgrp,
303  TN_UWord wait_pattern,
304  enum TN_EGrpWaitMode wait_mode,
305  TN_UWord *p_flags_pattern
306  );
307 
308 /**
309  * The same as `tn_eventgrp_wait()` with zero timeout, but for using in the ISR.
310  *
311  * $(TN_CALL_FROM_ISR)
312  * $(TN_CAN_SWITCH_CONTEXT)
313  * $(TN_LEGEND_LINK)
314  */
316  struct TN_EventGrp *eventgrp,
317  TN_UWord wait_pattern,
318  enum TN_EGrpWaitMode wait_mode,
319  TN_UWord *p_flags_pattern
320  );
321 
322 /**
323  * Modify current events bit pattern in the event group. Behavior depends
324  * on the given `operation`: refer to `enum #TN_EGrpOp`
325  *
326  * $(TN_CALL_FROM_TASK)
327  * $(TN_CAN_SWITCH_CONTEXT)
328  * $(TN_LEGEND_LINK)
329  *
330  * @param eventgrp
331  * Pointer to event group to modify events in
332  * @param operation
333  * Actual operation to perform: set, clear or toggle.
334  * Refer to `enum #TN_EGrpOp`
335  * @param pattern
336  * Events pattern to be applied (depending on `operation` value)
337  *
338  * @return
339  * * `#TN_RC_OK` on success;
340  * * `#TN_RC_WCONTEXT` if called from wrong context;
341  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
342  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
343  */
345  struct TN_EventGrp *eventgrp,
346  enum TN_EGrpOp operation,
348  );
349 
350 /**
351  * The same as `tn_eventgrp_modify()`, but for using in the ISR.
352  *
353  * $(TN_CALL_FROM_ISR)
354  * $(TN_CAN_SWITCH_CONTEXT)
355  * $(TN_LEGEND_LINK)
356  */
358  struct TN_EventGrp *eventgrp,
359  enum TN_EGrpOp operation,
361  );
362 
363 
364 #ifdef __cplusplus
365 } /* extern "C" */
366 #endif
367 
368 #endif // _TN_EVENTGRP_H
369 
370 /*******************************************************************************
371  * end of file
372  ******************************************************************************/
373 
374 
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_Timeout timeout)
Wait for specified event(s) in the event group.
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:175
Circular doubly linked list, for internal kernel usage.
TN_EGrpOp
Modify operation: set, clear or toggle.
Definition: tn_eventgrp.h:139
Clear flags that are set in the given pattern argument.
Definition: tn_eventgrp.h:149
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:80
TN_ObjId
Magic number for object validity verification TODO: use TN_UWord here instead of unsigned int...
Definition: tn_common.h:65
unsigned long TN_Timeout
The value representing maximum number of system ticks to wait.
Definition: tn_common.h:183
EventGrp-specific fields related to waiting task, to be included in struct TN_Task.
Definition: tn_eventgrp.h:169
TN_EGrpWaitMode
Events waiting mode: wait for all flags to be set or just for any of the specified flags to be set...
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:153
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_ObjId id_event
id for object validity verification
Definition: tn_eventgrp.h:162
enum TN_RCode tn_eventgrp_create(struct TN_EventGrp *eventgrp, TN_UWord initial_pattern)
Construct event group.
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:159
TN_UWord wait_pattern
event wait pattern
Definition: tn_eventgrp.h:172
Kernel system routines: system start, tick processing, time slice managing.
Set flags that are set in given pattern argument.
Definition: tn_eventgrp.h:144
TN_UWord actual_pattern
pattern that caused task to finish waiting
Definition: tn_eventgrp.h:178
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.
TN_UWord pattern
current flags pattern
Definition: tn_eventgrp.h:161
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:160