TNeoKernel  v1.03
 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;
60  * - wait for messages from multiple queues.
61  *
62  * If the kernel doesn't offer a mechanism for that, programmer usually have to
63  * use polling services on these queues and sleep for a few system ticks.
64  * Obviously, this approach has serious drawbacks: we have a lot of useless
65  * context switches, and response for the message gets much slower. Actually,
66  * we lost the main goal of the preemtive kernel when we use polling services
67  * like that.
68  *
69  * TNeoKernel offers a solution: an event group can be connected to other
70  * kernel objects, and these objects will maintain certain flags inside that
71  * event group automatically.
72  *
73  * So, in case of multiple queues, we can act as follows (assume we have two
74  * queues: Q1 and Q2) :
75  *
76  * - create event group EG;
77  * - connect EG with flag 1 to Q1;
78  * - connect EG with flag 2 to Q2;
79  * - when task needs to receive a message from either Q1 or Q2, it just waits
80  * for the any of flags 1 or 2 in the EG, this is done in the single call
81  * to `tn_eventgrp_wait()`.
82  * - when that event happened, task checks which flag is set, and receive
83  * message from the appropriate queue.
84  *
85  * Please note that task waiting for the event should **not** clear the flag
86  * manually: this flag is maintained completely by the queue. If the queue is
87  * non-empty, the flag is set. If the queue becomes empty, the flag is cleared.
88  *
89  * For the information on system services related to queue, refer to the \ref
90  * tn_dqueue.h "queue reference".
91  *
92  * There is an example project available that demonstrates event group
93  * connection technique: `examples/queue_eventgrp_conn`. Be sure to examine the
94  * readme there.
95  *
96  */
97 
98 #ifndef _TN_EVENTGRP_H
99 #define _TN_EVENTGRP_H
100 
101 /*******************************************************************************
102  * INCLUDED FILES
103  ******************************************************************************/
104 
105 #include "tn_list.h"
106 #include "tn_common.h"
107 #include "tn_sys.h"
108 
109 
110 
111 #ifdef __cplusplus
112 extern "C" { /*}*/
113 #endif
114 
115 /*******************************************************************************
116  * PUBLIC TYPES
117  ******************************************************************************/
118 
119 /**
120  * Events waiting mode: wait for all flags to be set or just for any of the
121  * specified flags to be set.
122  */
124  ///
125  /// Task waits for **any** of the event bits from the `wait_pattern`
126  /// to be set in the event group
128  ///
129  /// Task waits for **all** of the event bits from the `wait_pattern`
130  /// to be set in the event group
132 };
133 
134 /**
135  * Modify operation: set, clear or toggle. To be used in `tn_eventgrp_modify()`
136  * / `tn_eventgrp_imodify()` functions.
137  */
138 enum TN_EGrpOp {
139  ///
140  /// Set flags that are set in given `pattern` argument. Note that this
141  /// operation can lead to the context switch, since other high-priority
142  /// task(s) might wait for the event.
144  ///
145  /// Clear flags that are set in the given `pattern` argument.
146  /// This operation can **not** lead to the context switch,
147  /// since tasks can't wait for events to be cleared.
149  /// Toggle flags that are set in the given `pattern` argument. Note that this
150  /// operation can lead to the context switch, since other high-priority
151  /// task(s) might wait for the event that was just set (if any).
153 };
154 
155 /**
156  * Event group
157  */
158 struct TN_EventGrp {
159  struct TN_ListItem wait_queue; //!< task wait queue
160  TN_UWord pattern; //!< current flags pattern
161  enum TN_ObjId id_event; //!< id for object validity verification
162 };
163 
164 /**
165  * EventGrp-specific fields related to waiting task,
166  * to be included in struct TN_Task.
167  */
169  ///
170  /// event wait pattern
172  ///
173  /// event wait mode: `AND` or `OR`
175  ///
176  /// pattern that caused task to finish waiting
178 };
179 
180 /**
181  * A link to event group: used when event group can be connected to
182  * some kernel object, such as queue.
183  */
184 struct TN_EGrpLink {
185  ///
186  /// event group whose event(s) should be managed by other kernel object
188  ///
189  /// event pattern to manage
191 };
192 
193 
194 /*******************************************************************************
195  * GLOBAL VARIABLES
196  ******************************************************************************/
197 
198 /*******************************************************************************
199  * DEFINITIONS
200  ******************************************************************************/
201 
202 
203 
204 /*******************************************************************************
205  * PUBLIC FUNCTION PROTOTYPES
206  ******************************************************************************/
207 
208 /**
209  * Construct event group. `id_event` field should not contain `#TN_ID_EVENTGRP`,
210  * otherwise, `#TN_RC_WPARAM` is returned.
211  *
212  * $(TN_CALL_FROM_TASK)
213  * $(TN_CALL_FROM_ISR)
214  * $(TN_LEGEND_LINK)
215  *
216  * @param eventgrp
217  * Pointer to already allocated struct TN_EventGrp
218  * @param initial_pattern
219  * Initial events pattern.
220  *
221  * @return
222  * * `#TN_RC_OK` if event group was successfully created;
223  * * If `#TN_CHECK_PARAM` is non-zero, additional return code
224  * is available: `#TN_RC_WPARAM`.
225  */
227  struct TN_EventGrp *eventgrp,
228  TN_UWord initial_pattern
229  );
230 
231 /**
232  * Destruct event group.
233  *
234  * All tasks that wait for the event(s) become runnable with `#TN_RC_DELETED`
235  * code returned.
236  *
237  * $(TN_CALL_FROM_TASK)
238  * $(TN_CAN_SWITCH_CONTEXT)
239  * $(TN_LEGEND_LINK)
240  *
241  * @param eventgrp Pointer to event groupt to be deleted.
242  *
243  * @return
244  * * `#TN_RC_OK` if event group was successfully deleted;
245  * * `#TN_RC_WCONTEXT` if called from wrong context;
246  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
247  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
248  */
249 enum TN_RCode tn_eventgrp_delete(struct TN_EventGrp *eventgrp);
250 
251 /**
252  * Wait for specified event(s) in the event group. If the specified event
253  * is already active, function returns `#TN_RC_OK` immediately. Otherwise,
254  * behavior depends on `timeout` value: refer to `#TN_Timeout`.
255  *
256  * $(TN_CALL_FROM_TASK)
257  * $(TN_CAN_SWITCH_CONTEXT)
258  * $(TN_CAN_SLEEP)
259  * $(TN_LEGEND_LINK)
260  *
261  * @param eventgrp
262  * Pointer to event group to wait events from
263  * @param wait_pattern
264  * Events bit pattern for which task should wait
265  * @param wait_mode
266  * Specifies whether task should wait for **all** the event bits from
267  * `wait_pattern` to be set, or for just **any** of them
268  * (see enum `#TN_EGrpWaitMode`)
269  * @param p_flags_pattern
270  * Pointer to the `TN_UWord` variable in which actual event pattern
271  * that caused task to stop waiting will be stored.
272  * May be `NULL`.
273  * @param timeout
274  * refer to `#TN_Timeout`
275  *
276  * @return
277  * * `#TN_RC_OK` if specified event is active (so the task can check
278  * variable pointed to by `p_flags_pattern` if it wasn't `NULL`).
279  * * `#TN_RC_WCONTEXT` if called from wrong context;
280  * * Other possible return codes depend on `timeout` value,
281  * refer to `#TN_Timeout`
282  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
283  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
284  */
286  struct TN_EventGrp *eventgrp,
287  TN_UWord wait_pattern,
288  enum TN_EGrpWaitMode wait_mode,
289  TN_UWord *p_flags_pattern,
290  TN_Timeout timeout
291  );
292 
293 /**
294  * The same as `tn_eventgrp_wait()` with zero timeout.
295  *
296  * $(TN_CALL_FROM_TASK)
297  * $(TN_CAN_SWITCH_CONTEXT)
298  * $(TN_LEGEND_LINK)
299  */
301  struct TN_EventGrp *eventgrp,
302  TN_UWord wait_pattern,
303  enum TN_EGrpWaitMode wait_mode,
304  TN_UWord *p_flags_pattern
305  );
306 
307 /**
308  * The same as `tn_eventgrp_wait()` with zero timeout, but for using in the ISR.
309  *
310  * $(TN_CALL_FROM_ISR)
311  * $(TN_CAN_SWITCH_CONTEXT)
312  * $(TN_LEGEND_LINK)
313  */
315  struct TN_EventGrp *eventgrp,
316  TN_UWord wait_pattern,
317  enum TN_EGrpWaitMode wait_mode,
318  TN_UWord *p_flags_pattern
319  );
320 
321 /**
322  * Modify current events bit pattern in the event group. Behavior depends
323  * on the given `operation`: refer to `enum #TN_EGrpOp`
324  *
325  * $(TN_CALL_FROM_TASK)
326  * $(TN_CAN_SWITCH_CONTEXT)
327  * $(TN_LEGEND_LINK)
328  *
329  * @param eventgrp
330  * Pointer to event group to modify events in
331  * @param operation
332  * Actual operation to perform: set, clear or toggle.
333  * Refer to `enum #TN_EGrpOp`
334  * @param pattern
335  * Events pattern to be applied (depending on `operation` value)
336  *
337  * @return
338  * * `#TN_RC_OK` on success;
339  * * `#TN_RC_WCONTEXT` if called from wrong context;
340  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
341  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
342  */
344  struct TN_EventGrp *eventgrp,
345  enum TN_EGrpOp operation,
347  );
348 
349 /**
350  * The same as `tn_eventgrp_modify()`, but for using in the ISR.
351  *
352  * $(TN_CALL_FROM_ISR)
353  * $(TN_CAN_SWITCH_CONTEXT)
354  * $(TN_LEGEND_LINK)
355  */
357  struct TN_EventGrp *eventgrp,
358  enum TN_EGrpOp operation,
360  );
361 
362 
363 #ifdef __cplusplus
364 } /* extern "C" */
365 #endif
366 
367 #endif // _TN_EVENTGRP_H
368 
369 /*******************************************************************************
370  * end of file
371  ******************************************************************************/
372 
373 
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:131
enum TN_EGrpWaitMode wait_mode
event wait mode: AND or OR
Definition: tn_eventgrp.h:174
TN_EGrpOp
Modify operation: set, clear or toggle.
Definition: tn_eventgrp.h:138
Clear flags that are set in the given pattern argument.
Definition: tn_eventgrp.h:148
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:100
TN_ObjId
Magic number for object validity verification.
Definition: tn_common.h:87
unsigned long TN_Timeout
The value representing maximum number of system ticks to wait.
Definition: tn_common.h:203
EventGrp-specific fields related to waiting task, to be included in struct TN_Task.
Definition: tn_eventgrp.h:168
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:123
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:152
Task waits for any of the event bits from the wait_pattern to be set in the event group...
Definition: tn_eventgrp.h:127
enum TN_ObjId id_event
id for object validity verification
Definition: tn_eventgrp.h:161
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:158
TN_UWord wait_pattern
event wait pattern
Definition: tn_eventgrp.h:171
Kernel system routines: system start, tick processing, time slice managing.
Set flags that are set in given pattern argument.
Definition: tn_eventgrp.h:143
TN_UWord actual_pattern
pattern that caused task to finish waiting
Definition: tn_eventgrp.h:177
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:160
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:159