TNeo  v1.06
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tn_tasks.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  * \section tn_tasks__tasks Task
41  *
42  * In TNeo, a task is a branch of code that runs concurrently with other
43  * tasks from the programmer's point of view. Indeed, tasks are actually
44  * executed using processor time sharing. Each task can be considered to be an
45  * independed program, which executes in its own context (processor registers,
46  * stack pointer, etc.).
47  *
48  * Actually, the term <i>thread</i> is more accurate than <i>task</i>, but the
49  * term <i>task</i> historically was used in TNKernel, so TNeo keeps this
50  * convention.
51  *
52  * When kernel decides that it's time to run another task, it performs
53  * <i>context switch</i>: current context (at least, values of all registers)
54  * gets saved to the preempted task's stack, pointer to currently running
55  * task is altered as well as stack pointer, and context gets restored from
56  * the stack of newly running task.
57  *
58  * \section tn_tasks__states Task states
59  *
60  * For list of task states and their description, refer to `enum
61  * #TN_TaskState`.
62  *
63  *
64  * \section tn_tasks__creating Creating/starting tasks
65  *
66  * Create task and start task are two separate actions; although you can
67  * perform both of them in one step by passing `#TN_TASK_CREATE_OPT_START` flag
68  * to the `tn_task_create()` function.
69  *
70  * \section tn_tasks__stopping Stopping/deleting tasks
71  *
72  * Stop task and delete task are two separate actions. If task was just stopped
73  * but not deleted, it can be just restarted again by calling
74  * `tn_task_activate()`. If task was deleted, it can't be just activated: it
75  * should be re-created by `tn_task_create()` first.
76  *
77  * Task stops execution when:
78  *
79  * - it calls `tn_task_exit()`;
80  * - it returns from its task body function (it is the equivalent to
81  * `tn_task_exit(0)`)
82  * - some other task calls `tn_task_terminate()` passing appropriate pointer to
83  * `struct #TN_Task`.
84  *
85  * \section tn_tasks__scheduling Scheduling rules
86  *
87  * TNeo always runs the most privileged task in state
88  * $(TN_TASK_STATE_RUNNABLE). In no circumstances can task run while there is
89  * at least one task is in the $(TN_TASK_STATE_RUNNABLE) state with higher
90  * priority. Task will run until:
91  *
92  * - It becomes non-runnable (say, it may wait for something, etc)
93  * - Some other task with higher priority becomes runnable.
94  *
95  * Tasks with the same priority may be scheduled in round robin fashion by
96  * getting a predetermined time slice for each task with this priority.
97  * Time slice is set separately for each priority. By default, round robin
98  * is turned off for all priorities.
99  *
100  * \section tn_tasks__idle Idle task
101  *
102  * TNeo has one system task: an idle task, which has lowest priority.
103  * It is always in the state $(TN_TASK_STATE_RUNNABLE), and it runs only when
104  * there are no other runnable tasks.
105  *
106  * User can provide a callback function to be called from idle task, see
107  * #TN_CBIdle. It is useful to bring the processor to some kind of real idle
108  * state, so that device draws less current.
109  *
110  */
111 
112 #ifndef _TN_TASKS_H
113 #define _TN_TASKS_H
114 
115 /*******************************************************************************
116  * INCLUDED FILES
117  ******************************************************************************/
118 
119 #include "tn_sys.h"
120 #include "tn_list.h"
121 #include "tn_common.h"
122 
123 #include "tn_eventgrp.h"
124 #include "tn_dqueue.h"
125 #include "tn_fmem.h"
126 #include "tn_timer.h"
127 
128 
129 
130 #ifdef __cplusplus
131 extern "C" { /*}*/
132 #endif
133 
134 /*******************************************************************************
135  * PUBLIC TYPES
136  ******************************************************************************/
137 
138 /**
139  * Task state
140  */
142  ///
143  /// This state should never be publicly available.
144  /// It may be stored in task_state only temporarily,
145  /// while some system service is in progress.
147  ///
148  /// Task is ready to run (it doesn't mean that it is running at the moment)
150  ///
151  /// Task is waiting. The reason of waiting can be obtained from
152  /// `task_wait_reason` field of the `struct TN_Task`.
153  ///
154  /// @see `enum #TN_WaitReason`
155  TN_TASK_STATE_WAIT = (1 << 1),
156  ///
157  /// Task is suspended (by some other task)
159  ///
160  /// Task was previously waiting, and after this it was suspended
162  ///
163  /// Task isn't yet activated or it was terminated by `tn_task_terminate()`.
165 
166 
167 };
168 
169 
170 /**
171  * Task wait reason
172  */
174  ///
175  /// Task isn't waiting for anything
177  ///
178  /// Task has called `tn_task_sleep()`
180  ///
181  /// Task waits to acquire a semaphore
182  /// @see tn_sem.h
184  ///
185  /// Task waits for some event in the event group to be set
186  /// @see tn_eventgrp.h
188  ///
189  /// Task wants to put some data to the data queue, and there's no space
190  /// in the queue.
191  /// @see tn_dqueue.h
193  ///
194  /// Task wants to receive some data to the data queue, and there's no data
195  /// in the queue
196  /// @see tn_dqueue.h
198  ///
199  /// Task wants to lock a mutex with priority ceiling
200  /// @see tn_mutex.h
202  ///
203  /// Task wants to lock a mutex with priority inheritance
204  /// @see tn_mutex.h
206  ///
207  /// Task wants to get memory block from memory pool, and there's no free
208  /// memory blocks
209  /// @see tn_fmem.h
211 
212 
213  ///
214  /// Wait reasons count
216 };
217 
218 /**
219  * Options for `tn_task_create()`
220  */
222  ///
223  /// whether task should be activated right after it is created.
224  /// If this flag is not set, user must activate task manually by calling
225  /// `tn_task_activate()`.
227  ///
228  /// for internal kernel usage only: this option must be provided
229  /// when creating idle task
231 };
232 
233 /**
234  * Options for `tn_task_exit()`
235  */
237  ///
238  /// whether task should be deleted right after it is exited.
239  /// If this flag is not set, user must either delete it manually by
240  /// calling `tn_task_delete()` or re-activate it by calling
241  /// `tn_task_activate()`.
243 };
244 
245 #if TN_PROFILER || DOXYGEN_ACTIVE
246 /**
247  * Timing structure that is managed by profiler and can be read by
248  * `#tn_task_profiler_timing_get()` function. This structure is contained in
249  * each `struct #TN_Task` structure.
250  *
251  * Available if only `#TN_PROFILER` option is non-zero, also depends on
252  * `#TN_PROFILER_WAIT_TIME`.
253  */
255  ///
256  /// Total time when task was running.
257  ///
258  /// \attention
259  /// This is NOT the time that task was in $(TN_TASK_STATE_RUNNABLE) state:
260  /// if task A is preempted by high-priority task B, task A is not running,
261  /// but is still in the $(TN_TASK_STATE_RUNNABLE) state. This counter
262  /// represents the time task was actually <b>running</b>.
263  unsigned long long total_run_time;
264  ///
265  /// How many times task got running. It is useful to find an average
266  /// value of consecutive running time: `(total_run_time / got_running_cnt)`
267  unsigned long long got_running_cnt;
268  ///
269  /// Maximum consecutive time task was running.
271 
272 #if TN_PROFILER_WAIT_TIME || DOXYGEN_ACTIVE
273  ///
274  /// Available if only `#TN_PROFILER_WAIT_TIME` option is non-zero.
275  ///
276  /// Total time when task was not running; time is broken down by reasons of
277  /// waiting.
278  ///
279  /// For example, to get the time task was waiting for mutexes with priority
280  /// inheritance protocol, use: `total_wait_time[ #TN_WAIT_REASON_MUTEX_I ]`
281  ///
282  /// To get the time task was runnable but preempted by another task, use:
283  /// `total_wait_time[ #TN_WAIT_REASON_NONE ]`
284  ///
285  unsigned long long total_wait_time[ TN_WAIT_REASONS_CNT ];
286  ///
287  /// Available if only `#TN_PROFILER_WAIT_TIME` option is non-zero.
288  ///
289  /// Maximum consecutive time task was not running; time is broken down by
290  /// reasons of waiting.
291  ///
292  /// @see `total_wait_time`
294 #endif
295 };
296 
297 /**
298  * Internal kernel structure for profiling data of task.
299  *
300  * Available if only `#TN_PROFILER` option is non-zero.
301  */
303  ///
304  /// Tick count of when the task got running or non-running last time.
306 #if TN_PROFILER_WAIT_TIME || DOXYGEN_ACTIVE
307  ///
308  /// Available if only `#TN_PROFILER_WAIT_TIME` option is non-zero.
309  ///
310  /// Value of `task->task_wait_reason` when task got non-running last time.
312 #endif
313 
314 #if TN_DEBUG
315  ///
316  /// For internal profiler self-check only: indicates whether task is
317  /// running or not. Available if only `#TN_DEBUG` is non-zero.
318  int is_running;
319 #endif
320  ///
321  /// Main timing structure managed by profiler. Contents of this structure
322  /// can be read by `#tn_task_profiler_timing_get()` function.
324 };
325 #endif
326 
327 /**
328  * Task
329  */
330 struct TN_Task {
331  /// pointer to task's current top of the stack;
332  /// Note that this field **must** be a first field in the struct,
333  /// this fact is exploited by platform-specific routines.
335  ///
336  /// queue is used to include task in ready/wait lists
338  ///
339  /// timer object to implement task waiting for timeout
340  struct TN_Timer timer;
341  ///
342  /// pointer to object's (semaphore, mutex, event, etc) wait list in which
343  /// task is included for waiting
345  ///
346  /// queue is used to include task in creation list
347  /// (currently, this list is used for statistics only)
349 
350 #if TN_USE_MUTEXES
351  ///
352  /// list of all mutexes that are locked by task
354 #if TN_MUTEX_DEADLOCK_DETECT
355  ///
356  /// list of other tasks involved in deadlock. This list is non-empty
357  /// only in emergency cases, and it is here to help you fix your bug
358  /// that led to deadlock.
359  ///
360  /// @see `#TN_MUTEX_DEADLOCK_DETECT`
362 #endif
363 #endif
364 
365  /// base top of the stack for this task
367  ///
368  /// size of task's stack (in `sizeof(TN_UWord)`, not bytes)
370  ///
371  /// pointer to task's body function given to `tn_task_create()`
373  ///
374  /// pointer to task's parameter given to `tn_task_create()`
376  ///
377  /// base priority of the task (actual current priority may be higher than
378  /// base priority because of mutex)
380  ///
381  /// current task priority
382  int priority;
383  ///
384  /// id for object validity verification
386  ///
387  /// task state
389  ///
390  /// reason for waiting (relevant if only `task_state` is
391  /// $(TN_TASK_STATE_WAIT) or $(TN_TASK_STATE_WAITSUSP))
393  ///
394  /// waiting result code (reason why waiting finished)
396  //
397  // remaining time until timeout; may be `#TN_WAIT_INFINITE`.
398  //TN_TickCnt tick_count;
399  ///
400  /// time slice counter
402 #if 0
403  ///
404  /// last operation result code, might be used if some service
405  /// does not return that code directly
406  int last_rc;
407 #endif
408  ///
409  /// subsystem-specific fields that are used while task waits for something.
410  /// Do note that these fields are grouped by union, so, they must not
411  /// interfere with each other. It's quite ok here because task can't wait
412  /// for different things.
413  union {
414  /// fields specific to tn_eventgrp.h
416  ///
417  /// fields specific to tn_dqueue.h
419  ///
420  /// fields specific to tn_fmem.h
422  } subsys_wait;
423  ///
424  /// Task name for debug purposes, user may want to set it by hand
425  const char *name;
426 #if TN_PROFILER || DOXYGEN_ACTIVE
427  /// Profiler data, available if only `#TN_PROFILER` is non-zero.
429 #endif
430 
431  /// Internal flag used to optimize mutex priority algorithms.
432  /// For the comments on it, see file tn_mutex.c,
433  /// function `_mutex_do_unlock()`.
435 
436  /// Flag indicates that task waited for something
437  /// This flag is set automatially in `_tn_task_set_waiting()`
438  /// Must be cleared manually before calling any service that could sleep,
439  /// if the caller is interested in the relevant value of this flag.
440  unsigned waited : 1;
441 
442 
443 // Other implementation specific fields may be added below
444 
445 };
446 
447 
448 
449 /*******************************************************************************
450  * PROTECTED GLOBAL DATA
451  ******************************************************************************/
452 
453 /*******************************************************************************
454  * DEFINITIONS
455  ******************************************************************************/
456 
457 
458 
459 
460 /*******************************************************************************
461  * PUBLIC FUNCTION PROTOTYPES
462  ******************************************************************************/
463 
464 /**
465  * Construct task and probably start it (depends on options, see below).
466  * `id_task` member should not contain `#TN_ID_TASK`, otherwise,
467  * `#TN_RC_WPARAM` is returned.
468  *
469  * Usage example:
470  *
471  * \code{.c}
472  * #define MY_TASK_STACK_SIZE (TN_MIN_STACK_SIZE + 200)
473  * #define MY_TASK_PRIORITY 5
474  *
475  * struct TN_Task my_task;
476  *
477  * //-- define stack array, we use convenience macro TN_STACK_ARR_DEF()
478  * // for that
479  * TN_STACK_ARR_DEF(my_task_stack, MY_TASK_STACK_SIZE);
480  *
481  * void my_task_body(void *param)
482  * {
483  * //-- an endless loop
484  * for (;;){
485  * tn_task_sleep(1);
486  *
487  * //-- probably do something useful
488  * }
489  * }
490  * \endcode
491  *
492  *
493  *
494  * And then, somewhere from other task or from the callback
495  * `#TN_CBUserTaskCreate` given to `tn_sys_start()` :
496  * \code{.c}
497  * enum TN_RCode rc = tn_task_create(
498  * &my_task,
499  * my_task_body,
500  * MY_TASK_PRIORITY,
501  * my_task_stack,
502  * MY_TASK_STACK_SIZE,
503  * TN_NULL, //-- parameter isn't used
504  * TN_TASK_CREATE_OPT_START //-- start task on creation
505  * );
506  *
507  * if (rc != TN_RC_OK){
508  * //-- handle error
509  * }
510  * \endcode
511  *
512  * $(TN_CALL_FROM_TASK)
513  * $(TN_LEGEND_LINK)
514  *
515  * @param task
516  * Ready-allocated `struct TN_Task` structure. `id_task` member should not
517  * contain `#TN_ID_TASK`, otherwise `#TN_RC_WPARAM` is returned.
518  * @param task_func
519  * Pointer to task body function.
520  * @param priority
521  * Priority for new task. **NOTE**: the lower value, the higher priority.
522  * Must be > `0` and < `(#TN_PRIORITIES_CNT - 1)`.
523  * @param task_stack_low_addr
524  * Pointer to the stack for task.
525  * User must either use the macro `TN_STACK_ARR_DEF()` for the definition
526  * of stack array, or allocate it manually as an array of `#TN_UWord` with
527  * `#TN_ARCH_STK_ATTR_BEFORE` and `#TN_ARCH_STK_ATTR_AFTER` macros.
528  * @param task_stack_size
529  * Size of task stack array, in words (`#TN_UWord`), not in bytes.
530  * @param param
531  * Parameter that is passed to `task_func`.
532  * @param opts
533  * Options for task creation, refer to `enum #TN_TaskCreateOpt`
534  *
535  * @return
536  * * `#TN_RC_OK` on success;
537  * * `#TN_RC_WCONTEXT` if called from wrong context;
538  * * `#TN_RC_WPARAM` if wrong params were given;
539  *
540  * @see `#tn_task_create_wname()`
541  * @see `#TN_ARCH_STK_ATTR_BEFORE`
542  * @see `#TN_ARCH_STK_ATTR_AFTER`
543  */
545  struct TN_Task *task,
546  TN_TaskBody *task_func,
547  int priority,
548  TN_UWord *task_stack_low_addr,
549  int task_stack_size,
550  void *param,
551  enum TN_TaskCreateOpt opts
552  );
553 
554 
555 /**
556  * The same as `tn_task_create()` but with additional argument `name`,
557  * which could be very useful for debug.
558  */
560  struct TN_Task *task,
561  TN_TaskBody *task_func,
562  int priority,
563  TN_UWord *task_stack_low_addr,
564  int task_stack_size,
565  void *param,
566  enum TN_TaskCreateOpt opts,
567  const char *name
568  );
569 
570 /**
571  * If the task is $(TN_TASK_STATE_RUNNABLE), it is moved to the
572  * $(TN_TASK_STATE_SUSPEND) state. If the task is in the $(TN_TASK_STATE_WAIT)
573  * state, it is moved to the $(TN_TASK_STATE_WAITSUSP) state. (waiting +
574  * suspended)
575  *
576  * $(TN_CALL_FROM_TASK)
577  * $(TN_CAN_SWITCH_CONTEXT)
578  * $(TN_LEGEND_LINK)
579  *
580  * @param task Task to suspend
581  *
582  * @return
583  * * `#TN_RC_OK` on success;
584  * * `#TN_RC_WCONTEXT` if called from wrong context;
585  * * `#TN_RC_WSTATE` if task is already suspended or dormant;
586  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
587  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
588  *
589  * @see `enum #TN_TaskState`
590  */
591 enum TN_RCode tn_task_suspend(struct TN_Task *task);
592 
593 /**
594  * Release task from $(TN_TASK_STATE_SUSPEND) state. If the given task is in
595  * the $(TN_TASK_STATE_SUSPEND) state, it is moved to $(TN_TASK_STATE_RUNNABLE)
596  * state; afterwards it has the lowest precedence among runnable tasks with the
597  * same priority. If the task is in $(TN_TASK_STATE_WAITSUSP) state, it is
598  * moved to $(TN_TASK_STATE_WAIT) state.
599  *
600  * $(TN_CALL_FROM_TASK)
601  * $(TN_CAN_SWITCH_CONTEXT)
602  * $(TN_LEGEND_LINK)
603  *
604  * @param task Task to release from suspended state
605  *
606  * @return
607  * * `#TN_RC_OK` on success;
608  * * `#TN_RC_WCONTEXT` if called from wrong context;
609  * * `#TN_RC_WSTATE` if task is not suspended;
610  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
611  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
612  *
613  * @see enum TN_TaskState
614  */
615 enum TN_RCode tn_task_resume(struct TN_Task *task);
616 
617 /**
618  * Put current task to sleep for at most timeout ticks. When the timeout
619  * expires and the task was not suspended during the sleep, it is switched to
620  * runnable state. If the timeout value is `#TN_WAIT_INFINITE` and the task was
621  * not suspended during the sleep, the task will sleep until another function
622  * call (like `tn_task_wakeup()` or similar) will make it runnable.
623  *
624  * $(TN_CALL_FROM_TASK)
625  * $(TN_CAN_SWITCH_CONTEXT)
626  * $(TN_CAN_SLEEP)
627  * $(TN_LEGEND_LINK)
628  *
629  * @param timeout
630  * Refer to `#TN_TickCnt`
631  *
632  * @returns
633  * * `#TN_RC_TIMEOUT` if task has slept specified timeout;
634  * * `#TN_RC_OK` if task was woken up from other task by `tn_task_wakeup()`
635  * * `#TN_RC_FORCED` if task was released from wait forcibly by
636  * `tn_task_release_wait()`
637  * * `#TN_RC_WCONTEXT` if called from wrong context
638  *
639  * @see TN_TickCnt
640  */
641 enum TN_RCode tn_task_sleep(TN_TickCnt timeout);
642 
643 /**
644  * Wake up task from sleep.
645  *
646  * Task is woken up if only it sleeps because of call to `tn_task_sleep()`.
647  * If task sleeps for some another reason, task won't be woken up,
648  * and `tn_task_wakeup()` returns `#TN_RC_WSTATE`.
649  *
650  * After this call, `tn_task_sleep()` returns `#TN_RC_OK`.
651  *
652  * $(TN_CALL_FROM_TASK)
653  * $(TN_CAN_SWITCH_CONTEXT)
654  * $(TN_LEGEND_LINK)
655  *
656  * @param task sleeping task to wake up
657  *
658  * @return
659  * * `#TN_RC_OK` if successful
660  * * `#TN_RC_WSTATE` if task is not sleeping, or it is sleeping for
661  * some reason other than `tn_task_sleep()` call.
662  * * `#TN_RC_WCONTEXT` if called from wrong context;
663  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
664  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
665  *
666  */
667 enum TN_RCode tn_task_wakeup(struct TN_Task *task);
668 
669 /**
670  * The same as `tn_task_wakeup()` but for using in the ISR.
671  *
672  * $(TN_CALL_FROM_ISR)
673  * $(TN_CAN_SWITCH_CONTEXT)
674  * $(TN_LEGEND_LINK)
675  */
676 enum TN_RCode tn_task_iwakeup(struct TN_Task *task);
677 
678 /**
679  * Activate task that is in $(TN_TASK_STATE_DORMANT) state, that is, it was
680  * either just created by `tn_task_create()` without
681  * `#TN_TASK_CREATE_OPT_START` option, or terminated.
682  *
683  * Task is moved from $(TN_TASK_STATE_DORMANT) state to the
684  * $(TN_TASK_STATE_RUNNABLE) state.
685  *
686  * $(TN_CALL_FROM_TASK)
687  * $(TN_CAN_SWITCH_CONTEXT)
688  * $(TN_LEGEND_LINK)
689  *
690  * @param task dormant task to activate
691  *
692  * @return
693  * * `#TN_RC_OK` if successful
694  * * `#TN_RC_WSTATE` if task is not dormant
695  * * `#TN_RC_WCONTEXT` if called from wrong context;
696  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
697  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
698  *
699  * @see TN_TaskState
700  */
701 enum TN_RCode tn_task_activate(struct TN_Task *task);
702 
703 /**
704  * The same as `tn_task_activate()` but for using in the ISR.
705  *
706  * $(TN_CALL_FROM_ISR)
707  * $(TN_CAN_SWITCH_CONTEXT)
708  * $(TN_LEGEND_LINK)
709  */
710 enum TN_RCode tn_task_iactivate(struct TN_Task *task);
711 
712 /**
713  * Release task from $(TN_TASK_STATE_WAIT) state, independently of the reason
714  * of waiting.
715  *
716  * If task is in $(TN_TASK_STATE_WAIT) state, it is moved to
717  * $(TN_TASK_STATE_RUNNABLE) state. If task is in $(TN_TASK_STATE_WAITSUSP)
718  * state, it is moved to $(TN_TASK_STATE_SUSPEND) state.
719  *
720  * `#TN_RC_FORCED` is returned to the waiting task.
721  *
722  * $(TN_CALL_FROM_TASK)
723  * $(TN_CAN_SWITCH_CONTEXT)
724  * $(TN_LEGEND_LINK)
725  *
726  * \attention Usage of this function is discouraged, since the need for
727  * it indicates bad software design
728  *
729  * @param task task waiting for anything
730  *
731  * @return
732  * * `#TN_RC_OK` if successful
733  * * `#TN_RC_WSTATE` if task is not waiting for anything
734  * * `#TN_RC_WCONTEXT` if called from wrong context;
735  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
736  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
737  *
738  *
739  * @see TN_TaskState
740  */
741 enum TN_RCode tn_task_release_wait(struct TN_Task *task);
742 
743 /**
744  * The same as `tn_task_release_wait()` but for using in the ISR.
745  *
746  * $(TN_CALL_FROM_ISR)
747  * $(TN_CAN_SWITCH_CONTEXT)
748  * $(TN_LEGEND_LINK)
749  */
750 enum TN_RCode tn_task_irelease_wait(struct TN_Task *task);
751 
752 /**
753  * This function terminates the currently running task. The task is moved to
754  * the $(TN_TASK_STATE_DORMANT) state.
755  *
756  * After exiting, the task may be either deleted by the `tn_task_delete()`
757  * function call or reactivated by the `tn_task_activate()` /
758  * `tn_task_iactivate()` function call. In this case task starts execution from
759  * beginning (as after creation/activation). The task will have the lowest
760  * precedence among all tasks with the same priority in the
761  * $(TN_TASK_STATE_RUNNABLE) state.
762  *
763  * If this function is invoked with `#TN_TASK_EXIT_OPT_DELETE` option set, the
764  * task will be deleted after termination and cannot be reactivated (needs
765  * recreation).
766  *
767  * Please note that returning from task body function has the same effect as
768  * calling `tn_task_exit(0)`.
769  *
770  * $(TN_CALL_FROM_TASK)
771  * $(TN_CAN_SWITCH_CONTEXT)
772  * $(TN_LEGEND_LINK)
773  *
774  * @return
775  * Returns if only called from wrong context. Normally, it never returns
776  * (since calling task becomes terminated)
777  *
778  * @see `#TN_TASK_EXIT_OPT_DELETE`
779  * @see `tn_task_delete()`
780  * @see `tn_task_activate()`
781  * @see `tn_task_iactivate()`
782  */
783 void tn_task_exit(enum TN_TaskExitOpt opts);
784 
785 
786 /**
787  * This function is similar to `tn_task_exit()` but it terminates any task
788  * other than currently running one.
789  *
790  * After task is terminated, the task may be either deleted by the
791  * `tn_task_delete()` function call or reactivated by the `tn_task_activate()`
792  * / `tn_task_iactivate()` function call. In this case task starts execution
793  * from beginning (as after creation/activation). The task will have the
794  * lowest precedence among all tasks with the same priority in the
795  * $(TN_TASK_STATE_RUNNABLE) state.
796  *
797  * $(TN_CALL_FROM_TASK)
798  * $(TN_CAN_SWITCH_CONTEXT)
799  * $(TN_LEGEND_LINK)
800  *
801  * @param task task to terminate
802  *
803  * @return
804  * * `#TN_RC_OK` if successful
805  * * `#TN_RC_WSTATE` if task is already dormant
806  * * `#TN_RC_WCONTEXT` if called from wrong context;
807  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
808  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
809  */
810 enum TN_RCode tn_task_terminate(struct TN_Task *task);
811 
812 /**
813  * This function deletes the task specified by the task. The task must be in
814  * the $(TN_TASK_STATE_DORMANT) state, otherwise `#TN_RC_WCONTEXT` will be
815  * returned.
816  *
817  * This function resets the `id_task` field in the task structure to 0 and
818  * removes the task from the system tasks list. The task can not be reactivated
819  * after this function call (the task must be recreated).
820  *
821  * $(TN_CALL_FROM_TASK)
822  * $(TN_LEGEND_LINK)
823  *
824  * @param task dormant task to delete
825  *
826  * @return
827  * * `#TN_RC_OK` if successful
828  * * `#TN_RC_WSTATE` if task is not dormant
829  * * `#TN_RC_WCONTEXT` if called from wrong context;
830  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
831  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
832  *
833  */
834 enum TN_RCode tn_task_delete(struct TN_Task *task);
835 
836 /**
837  * Get current state of the task; note that returned state is a bitmask,
838  * that is, states could be combined with each other.
839  *
840  * Currently, only $(TN_TASK_STATE_WAIT) and $(TN_TASK_STATE_SUSPEND) states
841  * are allowed to be set together. Nevertheless, it would be probably good
842  * idea to test individual bits in the returned value instead of plain
843  * comparing values.
844  *
845  * Note that if something goes wrong, variable pointed to by `p_state`
846  * isn't touched.
847  *
848  * $(TN_CALL_FROM_TASK)
849  * $(TN_LEGEND_LINK)
850  *
851  * @param task
852  * task to get state of
853  * @param p_state
854  * pointer to the location where to store state of the task
855  *
856  * @return state of the task
857  */
859  struct TN_Task *task,
860  enum TN_TaskState *p_state
861  );
862 
863 #if TN_PROFILER || DOXYGEN_ACTIVE
864 /**
865  * Read profiler timing data of the task. See `struct #TN_TaskTiming` for
866  * details on timing data.
867  *
868  * $(TN_CALL_FROM_TASK)
869  * $(TN_CALL_FROM_ISR)
870  * $(TN_LEGEND_LINK)
871  *
872  * @param task
873  * Task to get timing data of
874  * @param tgt
875  * Target structure to fill with data, should be allocated by caller
876  */
878  const struct TN_Task *task,
879  struct TN_TaskTiming *tgt
880  );
881 #endif
882 
883 
884 /**
885  * Set new priority for task.
886  * If priority is 0, then task's base_priority is set.
887  *
888  * $(TN_CALL_FROM_TASK)
889  * $(TN_LEGEND_LINK)
890  *
891  * \attention this function is obsolete and will probably be removed
892  */
893 enum TN_RCode tn_task_change_priority(struct TN_Task *task, int new_priority);
894 
895 #ifdef __cplusplus
896 } /* extern "C" */
897 #endif
898 
899 #endif // _TN_TASKS_H
900 
901 
902 /*******************************************************************************
903  * end of file
904  ******************************************************************************/
905 
906 
enum TN_RCode tn_task_activate(struct TN_Task *task)
Activate task that is in DORMANT state, that is, it was either just created by tn_task_create() witho...
TN_WaitReason
Task wait reason.
Definition: tn_tasks.h:173
Task wants to lock a mutex with priority inheritance.
Definition: tn_tasks.h:205
const char * name
Task name for debug purposes, user may want to set it by hand.
Definition: tn_tasks.h:425
enum TN_RCode tn_task_release_wait(struct TN_Task *task)
Release task from WAIT state, independently of the reason of waiting.
enum TN_RCode tn_task_iwakeup(struct TN_Task *task)
The same as tn_task_wakeup() but for using in the ISR.
enum TN_RCode tn_task_terminate(struct TN_Task *task)
This function is similar to tn_task_exit() but it terminates any task other than currently running on...
Internal kernel structure for profiling data of task.
Definition: tn_tasks.h:302
Circular doubly linked list, for internal kernel usage.
Task is suspended (by some other task)
Definition: tn_tasks.h:158
enum TN_RCode tn_task_create(struct TN_Task *task, TN_TaskBody *task_func, int priority, TN_UWord *task_stack_low_addr, int task_stack_size, void *param, enum TN_TaskCreateOpt opts)
Construct task and probably start it (depends on options, see below).
enum TN_WaitReason last_wait_reason
Available if only TN_PROFILER_WAIT_TIME option is non-zero.
Definition: tn_tasks.h:311
enum TN_RCode tn_task_profiler_timing_get(const struct TN_Task *task, struct TN_TaskTiming *tgt)
Read profiler timing data of the task.
unsigned long max_consecutive_run_time
Maximum consecutive time task was running.
Definition: tn_tasks.h:270
Task.
Definition: tn_tasks.h:330
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:81
DQueue-specific fields related to waiting task, to be included in struct TN_Task. ...
Definition: tn_dqueue.h:140
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
enum TN_WaitReason task_wait_reason
reason for waiting (relevant if only task_state is WAIT or WAIT+SUSPEND)
Definition: tn_tasks.h:392
unsigned long long total_wait_time[TN_WAIT_REASONS_CNT]
Available if only TN_PROFILER_WAIT_TIME option is non-zero.
Definition: tn_tasks.h:285
Task was previously waiting, and after this it was suspended.
Definition: tn_tasks.h:161
Task wants to receive some data to the data queue, and there's no data in the queue.
Definition: tn_tasks.h:197
Definitions used through the whole kernel.
enum TN_TaskState task_state
task state
Definition: tn_tasks.h:388
unsigned long max_consecutive_wait_time[TN_WAIT_REASONS_CNT]
Available if only TN_PROFILER_WAIT_TIME option is non-zero.
Definition: tn_tasks.h:293
enum TN_RCode tn_task_delete(struct TN_Task *task)
This function deletes the task specified by the task.
for internal kernel usage only: this option must be provided when creating idle task ...
Definition: tn_tasks.h:230
Task is waiting.
Definition: tn_tasks.h:155
TN_TaskCreateOpt
Options for tn_task_create()
Definition: tn_tasks.h:221
struct TN_EGrpTaskWait eventgrp
fields specific to tn_eventgrp.h
Definition: tn_tasks.h:415
TN_TickCnt last_tick_cnt
Tick count of when the task got running or non-running last time.
Definition: tn_tasks.h:305
TN_UWord * base_stack_top
base top of the stack for this task
Definition: tn_tasks.h:366
int stack_size
size of task's stack (in sizeof(TN_UWord), not bytes)
Definition: tn_tasks.h:369
TN_TaskBody * task_func_addr
pointer to task's body function given to tn_task_create()
Definition: tn_tasks.h:372
int tslice_count
time slice counter
Definition: tn_tasks.h:401
enum TN_RCode tn_task_change_priority(struct TN_Task *task, int new_priority)
Set new priority for task.
struct TN_ListItem deadlock_list
list of other tasks involved in deadlock.
Definition: tn_tasks.h:361
Timer is a kernel object that is used to ask the kernel to call some user-provided function at a part...
enum TN_RCode tn_task_wakeup(struct TN_Task *task)
Wake up task from sleep.
enum TN_RCode tn_task_sleep(TN_TickCnt timeout)
Put current task to sleep for at most timeout ticks.
union TN_Task::@2 subsys_wait
subsystem-specific fields that are used while task waits for something.
TN_TaskState
Task state.
Definition: tn_tasks.h:141
This state should never be publicly available.
Definition: tn_tasks.h:146
Timer.
Definition: tn_timer.h:205
Fixed memory blocks pool.
enum TN_RCode tn_task_suspend(struct TN_Task *task)
If the task is RUNNABLE, it is moved to the SUSPEND state.
Timing structure that is managed by profiler and can be read by tn_task_profiler_timing_get() functio...
Definition: tn_tasks.h:254
void tn_task_exit(enum TN_TaskExitOpt opts)
This function terminates the currently running task.
whether task should be deleted right after it is exited.
Definition: tn_tasks.h:242
enum TN_RCode tn_task_irelease_wait(struct TN_Task *task)
The same as tn_task_release_wait() but for using in the ISR.
enum TN_RCode tn_task_resume(struct TN_Task *task)
Release task from SUSPEND state.
int base_priority
base priority of the task (actual current priority may be higher than base priority because of mutex)...
Definition: tn_tasks.h:379
Event group.
Task isn't yet activated or it was terminated by tn_task_terminate().
Definition: tn_tasks.h:164
Task has called tn_task_sleep()
Definition: tn_tasks.h:179
enum TN_ObjId id_task
id for object validity verification
Definition: tn_tasks.h:385
Task is ready to run (it doesn't mean that it is running at the moment)
Definition: tn_tasks.h:149
TN_UWord * stack_top
pointer to task's current top of the stack; Note that this field must be a first field in the struct...
Definition: tn_tasks.h:334
Task wants to get memory block from memory pool, and there's no free memory blocks.
Definition: tn_tasks.h:210
struct TN_DQueueTaskWait dqueue
fields specific to tn_dqueue.h
Definition: tn_tasks.h:418
unsigned waited
Flag indicates that task waited for something This flag is set automatially in _tn_task_set_waiting()...
Definition: tn_tasks.h:440
int priority
current task priority
Definition: tn_tasks.h:382
struct _TN_TaskProfiler profiler
Profiler data, available if only TN_PROFILER is non-zero.
Definition: tn_tasks.h:428
enum TN_RCode tn_task_iactivate(struct TN_Task *task)
The same as tn_task_activate() but for using in the ISR.
struct TN_ListItem * pwait_queue
pointer to object's (semaphore, mutex, event, etc) wait list in which task is included for waiting ...
Definition: tn_tasks.h:344
struct TN_ListItem task_queue
queue is used to include task in ready/wait lists
Definition: tn_tasks.h:337
Task wants to lock a mutex with priority ceiling.
Definition: tn_tasks.h:201
struct TN_FMemTaskWait fmem
fields specific to tn_fmem.h
Definition: tn_tasks.h:421
struct TN_Timer timer
timer object to implement task waiting for timeout
Definition: tn_tasks.h:340
struct TN_TaskTiming timing
Main timing structure managed by profiler.
Definition: tn_tasks.h:323
Kernel system routines: system start, tick processing, time slice managing.
unsigned long long got_running_cnt
How many times task got running.
Definition: tn_tasks.h:267
Task wants to put some data to the data queue, and there's no space in the queue. ...
Definition: tn_tasks.h:192
enum TN_RCode tn_task_state_get(struct TN_Task *task, enum TN_TaskState *p_state)
Get current state of the task; note that returned state is a bitmask, that is, states could be combin...
void( TN_TaskBody)(void *param)
Prototype for task body function.
Definition: tn_common.h:145
Task waits to acquire a semaphore.
Definition: tn_tasks.h:183
Task isn't waiting for anything.
Definition: tn_tasks.h:176
unsigned priority_already_updated
Internal flag used to optimize mutex priority algorithms.
Definition: tn_tasks.h:434
whether task should be activated right after it is created.
Definition: tn_tasks.h:226
void * task_func_param
pointer to task's parameter given to tn_task_create()
Definition: tn_tasks.h:375
FMem-specific fields related to waiting task, to be included in struct TN_Task.
Definition: tn_fmem.h:112
unsigned long long total_run_time
Total time when task was running.
Definition: tn_tasks.h:263
Wait reasons count.
Definition: tn_tasks.h:215
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.
enum TN_RCode tn_task_create_wname(struct TN_Task *task, TN_TaskBody *task_func, int priority, TN_UWord *task_stack_low_addr, int task_stack_size, void *param, enum TN_TaskCreateOpt opts, const char *name)
The same as tn_task_create() but with additional argument name, which could be very useful for debug...
Task waits for some event in the event group to be set.
Definition: tn_tasks.h:187
A data queue is a FIFO that stores pointer (of type void *) in each cell, called (in uITRON style) a ...
struct TN_ListItem create_queue
queue is used to include task in creation list (currently, this list is used for statistics only) ...
Definition: tn_tasks.h:348
TN_TaskExitOpt
Options for tn_task_exit()
Definition: tn_tasks.h:236
enum TN_RCode task_wait_rc
waiting result code (reason why waiting finished)
Definition: tn_tasks.h:395
struct TN_ListItem mutex_queue
list of all mutexes that are locked by task
Definition: tn_tasks.h:353