TNeoKernel  v1.04
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tn_tasks.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  * \section tn_tasks__tasks Task
41  *
42  * In TNeoKernel, 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 TNeoKernel 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 delete 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  * TNeoKernel 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  * TNeoKernel 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  /// This state should never be publicly available.
143  /// It may be stored in task_state only temporarily,
144  /// while some system service is in progress.
146  ///
147  /// Task is ready to run (it doesn't mean that it is running at the moment)
149  ///
150  /// Task is waiting. The reason of waiting can be obtained from
151  /// `task_wait_reason` field of the `struct TN_Task`.
152  ///
153  /// @see `enum #TN_WaitReason`
154  TN_TASK_STATE_WAIT = (1 << 1),
155  ///
156  /// Task is suspended (by some other task)
158  ///
159  /// Task was previously waiting, and after this it was suspended
161  ///
162  /// Task isn't yet activated or it was terminated by `tn_task_terminate()`.
164 };
165 
166 
167 /**
168  * Task wait reason
169  */
171  ///
172  /// task isn't waiting for anything
174  ///
175  /// task has called `tn_task_sleep()`
177  ///
178  /// task waits to acquire a semaphore
179  /// @see tn_sem.h
181  ///
182  /// task waits for some event in the event group to be set
183  /// @see tn_eventgrp.h
185  ///
186  /// task wants to put some data to the data queue, and there's no space
187  /// in the queue.
188  /// @see tn_dqueue.h
190  ///
191  /// task wants to receive some data to the data queue, and there's no data
192  /// in the queue
193  /// @see tn_dqueue.h
195  ///
196  /// task wants to lock a mutex with priority ceiling
197  /// @see tn_mutex.h
199  ///
200  /// task wants to lock a mutex with priority inheritance
201  /// @see tn_mutex.h
203  ///
204  /// task wants to get memory block from memory pool, and there's no free
205  /// memory blocks
206  /// @see tn_fmem.h
208 };
209 
210 /**
211  * Options for `tn_task_create()`
212  */
214  ///
215  /// whether task should be activated right after it is created.
216  /// If this flag is not set, user must activate task manually by calling
217  /// `tn_task_activate()`.
219  ///
220  /// for internal kernel usage only: this option must be provided
221  /// when creating idle task
223 };
224 
225 /**
226  * Options for `tn_task_exit()`
227  */
229  ///
230  /// whether task should be deleted right after it is exited.
231  /// If this flag is not set, user must either delete it manually by
232  /// calling `tn_task_delete()` or re-activate it by calling
233  /// `tn_task_activate()`.
235 };
236 
237 
238 /**
239  * Task
240  */
241 struct TN_Task {
242  /// pointer to task's current top of the stack;
243  /// Note that this field **must** be a first field in the struct,
244  /// this fact is exploited by platform-specific routines.
246  ///
247  /// queue is used to include task in ready/wait lists
249  ///
250  /// timer object to implement task waiting for timeout
251  struct TN_Timer timer;
252  ///
253  /// pointer to object's (semaphore, mutex, event, etc) wait list in which
254  /// task is included for waiting
256  ///
257  /// queue is used to include task in creation list
258  /// (currently, this list is used for statistics only)
260 
261 #if TN_USE_MUTEXES
262  ///
263  /// list of all mutexes that are locked by task
265 #if TN_MUTEX_DEADLOCK_DETECT
266  ///
267  /// list of other tasks involved in deadlock. This list is non-empty
268  /// only in emergency cases, and it is here to help you fix your bug
269  /// that led to deadlock.
270  ///
271  /// @see `#TN_MUTEX_DEADLOCK_DETECT`
273 #endif
274 #endif
275 
276  /// base top of the stack for this task
278  ///
279  /// size of task's stack (in `sizeof(TN_UWord)`, not bytes)
281  ///
282  /// pointer to task's body function given to `tn_task_create()`
284  ///
285  /// pointer to task's parameter given to `tn_task_create()`
287  ///
288  /// base priority of the task (actual current priority may be higher than
289  /// base priority because of mutex)
291  ///
292  /// current task priority
293  int priority;
294  ///
295  /// id for object validity verification
297  ///
298  /// task state
300  ///
301  /// reason for waiting (relevant if only `task_state` is
302  /// $(TN_TASK_STATE_WAIT) or $(TN_TASK_STATE_WAITSUSP))
304  ///
305  /// waiting result code (reason why waiting finished)
307  //
308  // remaining time until timeout; may be `#TN_WAIT_INFINITE`.
309  //TN_Timeout tick_count;
310  ///
311  /// time slice counter
313 #if 0
314  ///
315  /// last operation result code, might be used if some service
316  /// does not return that code directly
317  int last_rc;
318 #endif
319  ///
320  /// subsystem-specific fields that are used while task waits for something.
321  /// Do note that these fields are grouped by union, so, they must not
322  /// interfere with each other. It's quite ok here because task can't wait
323  /// for different things.
324  union {
325  /// fields specific to tn_eventgrp.h
327  ///
328  /// fields specific to tn_dqueue.h
330  ///
331  /// fields specific to tn_fmem.h
333  } subsys_wait;
334 
335 #if TN_DEBUG
336  /// task name for debug purposes, user may want to set it by hand
337  const char *name;
338 #endif
339 
340  /// Internal flag used to optimize mutex priority algorithms.
341  /// For the comments on it, see file tn_mutex.c,
342  /// function `_mutex_do_unlock()`.
344 
345  /// Flag indicates that task waited for something
346  /// This flag is set automatially in `_tn_task_set_waiting()`
347  /// Must be cleared manually before calling any service that could sleep,
348  /// if the caller is interested in the relevant value of this flag.
349  unsigned waited : 1;
350 
351 
352 // Other implementation specific fields may be added below
353 
354 };
355 
356 
357 
358 /*******************************************************************************
359  * GLOBAL VARIABLES
360  ******************************************************************************/
361 
362 /*******************************************************************************
363  * DEFINITIONS
364  ******************************************************************************/
365 
366 
367 
368 
369 /*******************************************************************************
370  * PUBLIC FUNCTION PROTOTYPES
371  ******************************************************************************/
372 
373 /**
374  * Construct task and probably start it (depends on options, see below).
375  * `id_task` member should not contain `#TN_ID_TASK`, otherwise,
376  * `#TN_RC_WPARAM` is returned.
377  *
378  * Usage example:
379  *
380  * \code{.c}
381  * #define MY_TASK_STACK_SIZE (TN_MIN_STACK_SIZE + 200)
382  * #define MY_TASK_PRIORITY 5
383  *
384  * struct TN_Task my_task;
385  *
386  * //-- define stack array, we use convenience macro TN_STACK_ARR_DEF()
387  * // for that
388  * TN_STACK_ARR_DEF(my_task_stack, MY_TASK_STACK_SIZE);
389  *
390  * void my_task_body(void *param)
391  * {
392  * //-- an endless loop
393  * for (;;){
394  * tn_task_sleep(1);
395  *
396  * //-- probably do something useful
397  * }
398  * }
399  * \endcode
400  *
401  *
402  *
403  * And then, somewhere from other task or from the callback
404  * `#TN_CBUserTaskCreate` given to `tn_sys_start()` :
405  * \code{.c}
406  * enum TN_RCode rc = tn_task_create(
407  * &my_task,
408  * my_task_body,
409  * MY_TASK_PRIORITY,
410  * my_task_stack,
411  * MY_TASK_STACK_SIZE,
412  * TN_NULL, //-- parameter isn't used
413  * TN_TASK_CREATE_OPT_START //-- start task on creation
414  * );
415  *
416  * if (rc != TN_RC_OK){
417  * //-- handle error
418  * }
419  * \endcode
420  *
421  * $(TN_CALL_FROM_TASK)
422  * $(TN_LEGEND_LINK)
423  *
424  * @param task
425  * Ready-allocated `struct TN_Task` structure. `id_task` member should not
426  * contain `#TN_ID_TASK`, otherwise `#TN_RC_WPARAM` is returned.
427  * @param task_func
428  * Pointer to task body function.
429  * @param priority
430  * Priority for new task. **NOTE**: the lower value, the higher priority.
431  * Must be > `0` and < `(#TN_PRIORITIES_CNT - 1)`.
432  * @param task_stack_low_addr
433  * Pointer to the stack for task.
434  * User must either use the macro `TN_STACK_ARR_DEF()` for the definition
435  * of stack array, or allocate it manually as an array of `#TN_UWord` with
436  * `#TN_ARCH_STK_ATTR_BEFORE` and `#TN_ARCH_STK_ATTR_AFTER` macros.
437  * @param task_stack_size
438  * Size of task stack array, in words (`#TN_UWord`), not in bytes.
439  * @param param
440  * Parameter that is passed to `task_func`.
441  * @param opts
442  * Options for task creation, refer to `enum #TN_TaskCreateOpt`
443  *
444  * @return
445  * * `#TN_RC_OK` on success;
446  * * `#TN_RC_WCONTEXT` if called from wrong context;
447  * * `#TN_RC_WPARAM` if wrong params were given;
448  *
449  * @see `#TN_ARCH_STK_ATTR_BEFORE`
450  * @see `#TN_ARCH_STK_ATTR_AFTER`
451  */
453  struct TN_Task *task,
454  TN_TaskBody *task_func,
455  int priority,
456  TN_UWord *task_stack_low_addr,
457  int task_stack_size,
458  void *param,
459  enum TN_TaskCreateOpt opts
460  );
461 
462 
463 /**
464  * If the task is $(TN_TASK_STATE_RUNNABLE), it is moved to the
465  * $(TN_TASK_STATE_SUSPEND) state. If the task is in the $(TN_TASK_STATE_WAIT)
466  * state, it is moved to the $(TN_TASK_STATE_WAITSUSP) state. (waiting +
467  * suspended)
468  *
469  * $(TN_CALL_FROM_TASK)
470  * $(TN_CAN_SWITCH_CONTEXT)
471  * $(TN_LEGEND_LINK)
472  *
473  * @param task Task to suspend
474  *
475  * @return
476  * * `#TN_RC_OK` on success;
477  * * `#TN_RC_WCONTEXT` if called from wrong context;
478  * * `#TN_RC_WSTATE` if task is already suspended or dormant;
479  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
480  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
481  *
482  * @see `enum #TN_TaskState`
483  */
484 enum TN_RCode tn_task_suspend(struct TN_Task *task);
485 
486 /**
487  * Release task from $(TN_TASK_STATE_SUSPEND) state. If the given task is in
488  * the $(TN_TASK_STATE_SUSPEND) state, it is moved to $(TN_TASK_STATE_RUNNABLE)
489  * state; afterwards it has the lowest precedence among runnable tasks with the
490  * same priority. If the task is in $(TN_TASK_STATE_WAITSUSP) state, it is
491  * moved to $(TN_TASK_STATE_WAIT) state.
492  *
493  * $(TN_CALL_FROM_TASK)
494  * $(TN_CAN_SWITCH_CONTEXT)
495  * $(TN_LEGEND_LINK)
496  *
497  * @param task Task to release from suspended state
498  *
499  * @return
500  * * `#TN_RC_OK` on success;
501  * * `#TN_RC_WCONTEXT` if called from wrong context;
502  * * `#TN_RC_WSTATE` if task is not suspended;
503  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
504  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
505  *
506  * @see enum TN_TaskState
507  */
508 enum TN_RCode tn_task_resume(struct TN_Task *task);
509 
510 /**
511  * Put current task to sleep for at most timeout ticks. When the timeout
512  * expires and the task was not suspended during the sleep, it is switched to
513  * runnable state. If the timeout value is `#TN_WAIT_INFINITE` and the task was
514  * not suspended during the sleep, the task will sleep until another function
515  * call (like `tn_task_wakeup()` or similar) will make it runnable.
516  *
517  * $(TN_CALL_FROM_TASK)
518  * $(TN_CAN_SWITCH_CONTEXT)
519  * $(TN_CAN_SLEEP)
520  * $(TN_LEGEND_LINK)
521  *
522  * @param timeout
523  * Refer to `#TN_Timeout`
524  *
525  * @returns
526  * * `#TN_RC_TIMEOUT` if task has slept specified timeout;
527  * * `#TN_RC_OK` if task was woken up from other task by `tn_task_wakeup()`
528  * * `#TN_RC_FORCED` if task was released from wait forcibly by
529  * `tn_task_release_wait()`
530  * * `#TN_RC_WCONTEXT` if called from wrong context
531  *
532  * @see TN_Timeout
533  */
534 enum TN_RCode tn_task_sleep(TN_Timeout timeout);
535 
536 /**
537  * Wake up task from sleep.
538  *
539  * Task is woken up if only it sleeps because of call to `tn_task_sleep()`.
540  * If task sleeps for some another reason, task won't be woken up,
541  * and `tn_task_wakeup()` returns `#TN_RC_WSTATE`.
542  *
543  * After this call, `tn_task_sleep()` returns `#TN_RC_OK`.
544  *
545  * $(TN_CALL_FROM_TASK)
546  * $(TN_CAN_SWITCH_CONTEXT)
547  * $(TN_LEGEND_LINK)
548  *
549  * @param task sleeping task to wake up
550  *
551  * @return
552  * * `#TN_RC_OK` if successful
553  * * `#TN_RC_WSTATE` if task is not sleeping, or it is sleeping for
554  * some reason other than `tn_task_sleep()` call.
555  * * `#TN_RC_WCONTEXT` if called from wrong context;
556  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
557  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
558  *
559  */
560 enum TN_RCode tn_task_wakeup(struct TN_Task *task);
561 
562 /**
563  * The same as `tn_task_wakeup()` but for using in the ISR.
564  *
565  * $(TN_CALL_FROM_ISR)
566  * $(TN_CAN_SWITCH_CONTEXT)
567  * $(TN_LEGEND_LINK)
568  */
569 enum TN_RCode tn_task_iwakeup(struct TN_Task *task);
570 
571 /**
572  * Activate task that is in $(TN_TASK_STATE_DORMANT) state, that is, it was
573  * either just created by `tn_task_create()` without
574  * `#TN_TASK_CREATE_OPT_START` option, or terminated.
575  *
576  * Task is moved from $(TN_TASK_STATE_DORMANT) state to the
577  * $(TN_TASK_STATE_RUNNABLE) state.
578  *
579  * $(TN_CALL_FROM_TASK)
580  * $(TN_CAN_SWITCH_CONTEXT)
581  * $(TN_LEGEND_LINK)
582  *
583  * @param task dormant task to activate
584  *
585  * @return
586  * * `#TN_RC_OK` if successful
587  * * `#TN_RC_WSTATE` if task is not dormant
588  * * `#TN_RC_WCONTEXT` if called from wrong context;
589  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
590  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
591  *
592  * @see TN_TaskState
593  */
594 enum TN_RCode tn_task_activate(struct TN_Task *task);
595 
596 /**
597  * The same as `tn_task_activate()` but for using in the ISR.
598  *
599  * $(TN_CALL_FROM_ISR)
600  * $(TN_CAN_SWITCH_CONTEXT)
601  * $(TN_LEGEND_LINK)
602  */
603 enum TN_RCode tn_task_iactivate(struct TN_Task *task);
604 
605 /**
606  * Release task from $(TN_TASK_STATE_WAIT) state, independently of the reason
607  * of waiting.
608  *
609  * If task is in $(TN_TASK_STATE_WAIT) state, it is moved to
610  * $(TN_TASK_STATE_RUNNABLE) state. If task is in $(TN_TASK_STATE_WAITSUSP)
611  * state, it is moved to $(TN_TASK_STATE_SUSPEND) state.
612  *
613  * `#TN_RC_FORCED` is returned to the waiting task.
614  *
615  * $(TN_CALL_FROM_TASK)
616  * $(TN_CAN_SWITCH_CONTEXT)
617  * $(TN_LEGEND_LINK)
618  *
619  * \attention Usage of this function is discouraged, since the need for
620  * it indicates bad software design
621  *
622  * @param task task waiting for anything
623  *
624  * @return
625  * * `#TN_RC_OK` if successful
626  * * `#TN_RC_WSTATE` if task is not waiting for anything
627  * * `#TN_RC_WCONTEXT` if called from wrong context;
628  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
629  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
630  *
631  *
632  * @see TN_TaskState
633  */
634 enum TN_RCode tn_task_release_wait(struct TN_Task *task);
635 
636 /**
637  * The same as `tn_task_release_wait()` but for using in the ISR.
638  *
639  * $(TN_CALL_FROM_ISR)
640  * $(TN_CAN_SWITCH_CONTEXT)
641  * $(TN_LEGEND_LINK)
642  */
643 enum TN_RCode tn_task_irelease_wait(struct TN_Task *task);
644 
645 /**
646  * This function terminates the currently running task. The task is moved to
647  * the $(TN_TASK_STATE_DORMANT) state.
648  *
649  * After exiting, the task may be either deleted by the `tn_task_delete()`
650  * function call or reactivated by the `tn_task_activate()` /
651  * `tn_task_iactivate()` function call. In this case task starts execution from
652  * beginning (as after creation/activation). The task will have the lowest
653  * precedence among all tasks with the same priority in the
654  * $(TN_TASK_STATE_RUNNABLE) state.
655  *
656  * If this function is invoked with `#TN_TASK_EXIT_OPT_DELETE` option set, the
657  * task will be deleted after termination and cannot be reactivated (needs
658  * recreation).
659  *
660  * Please note that returning from task body function has the same effect as
661  * calling `tn_task_exit(0)`.
662  *
663  * $(TN_CALL_FROM_TASK)
664  * $(TN_CAN_SWITCH_CONTEXT)
665  * $(TN_LEGEND_LINK)
666  *
667  * @return
668  * Returns if only called from wrong context. Normally, it never returns
669  * (since calling task becomes terminated)
670  *
671  * @see `#TN_TASK_EXIT_OPT_DELETE`
672  * @see `tn_task_delete()`
673  * @see `tn_task_activate()`
674  * @see `tn_task_iactivate()`
675  */
676 void tn_task_exit(enum TN_TaskExitOpt opts);
677 
678 
679 /**
680  * This function is similar to `tn_task_exit()` but it terminates any task
681  * other than currently running one.
682  *
683  * After task is terminated, the task may be either deleted by the
684  * `tn_task_delete()` function call or reactivated by the `tn_task_activate()`
685  * / `tn_task_iactivate()` function call. In this case task starts execution
686  * from beginning (as after creation/activation). The task will have the
687  * lowest precedence among all tasks with the same priority in the
688  * $(TN_TASK_STATE_RUNNABLE) state.
689  *
690  * $(TN_CALL_FROM_TASK)
691  * $(TN_CAN_SWITCH_CONTEXT)
692  * $(TN_LEGEND_LINK)
693  *
694  * @param task task to terminate
695  *
696  * @return
697  * * `#TN_RC_OK` if successful
698  * * `#TN_RC_WSTATE` if task is already dormant
699  * * `#TN_RC_WCONTEXT` if called from wrong context;
700  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
701  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
702  */
703 enum TN_RCode tn_task_terminate(struct TN_Task *task);
704 
705 /**
706  * This function deletes the task specified by the task. The task must be in
707  * the $(TN_TASK_STATE_DORMANT) state, otherwise `#TN_RC_WCONTEXT` will be
708  * returned.
709  *
710  * This function resets the `id_task` field in the task structure to 0 and
711  * removes the task from the system tasks list. The task can not be reactivated
712  * after this function call (the task must be recreated).
713  *
714  * $(TN_CALL_FROM_TASK)
715  * $(TN_LEGEND_LINK)
716  *
717  * @param task dormant task to delete
718  *
719  * @return
720  * * `#TN_RC_OK` if successful
721  * * `#TN_RC_WSTATE` if task is not dormant
722  * * `#TN_RC_WCONTEXT` if called from wrong context;
723  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
724  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
725  *
726  */
727 enum TN_RCode tn_task_delete(struct TN_Task *task);
728 
729 /**
730  * Get current state of the task; note that returned state is a bitmask,
731  * that is, states could be combined with each other.
732  *
733  * Currently, only $(TN_TASK_STATE_WAIT) and $(TN_TASK_STATE_SUSPEND) states
734  * are allowed to be set together. Nevertheless, it would be probably good
735  * idea to test individual bits in the returned value instead of plain
736  * comparing values.
737  *
738  * Note that if something goes wrong, variable pointed to by `p_state`
739  * isn't touched.
740  *
741  * $(TN_CALL_FROM_TASK)
742  * $(TN_LEGEND_LINK)
743  *
744  * @param task
745  * task to get state of
746  * @param p_state
747  * pointer to the location where to store state of the task
748  *
749  * @return state of the task
750  */
752  struct TN_Task *task,
753  enum TN_TaskState *p_state
754  );
755 
756 /**
757  * Set new priority for task.
758  * If priority is 0, then task's base_priority is set.
759  *
760  * $(TN_CALL_FROM_TASK)
761  * $(TN_LEGEND_LINK)
762  *
763  * \attention this function is obsolete and will probably be removed
764  */
765 enum TN_RCode tn_task_change_priority(struct TN_Task *task, int new_priority);
766 
767 
768 
769 #ifdef __cplusplus
770 } /* extern "C" */
771 #endif
772 
773 #endif // _TN_TASKS_H
774 
775 
776 /*******************************************************************************
777  * end of file
778  ******************************************************************************/
779 
780 
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:170
task wants to lock a mutex with priority inheritance
Definition: tn_tasks.h:202
const char * name
task name for debug purposes, user may want to set it by hand
Definition: tn_tasks.h:337
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...
Circular doubly linked list, for internal kernel usage.
Task is suspended (by some other task)
Definition: tn_tasks.h:157
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).
Task.
Definition: tn_tasks.h:241
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:80
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 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
enum TN_WaitReason task_wait_reason
reason for waiting (relevant if only task_state is WAIT or WAIT+SUSPEND)
Definition: tn_tasks.h:303
Task was previously waiting, and after this it was suspended.
Definition: tn_tasks.h:160
task wants to receive some data to the data queue, and there's no data in the queue ...
Definition: tn_tasks.h:194
Definitions used through the whole kernel.
enum TN_TaskState task_state
task state
Definition: tn_tasks.h:299
enum TN_RCode tn_task_delete(struct TN_Task *task)
This function deletes the task specified by the task.
Task is waiting.
Definition: tn_tasks.h:154
TN_TaskCreateOpt
Options for tn_task_create()
Definition: tn_tasks.h:213
struct TN_EGrpTaskWait eventgrp
fields specific to tn_eventgrp.h
Definition: tn_tasks.h:326
TN_UWord * base_stack_top
base top of the stack for this task
Definition: tn_tasks.h:277
int stack_size
size of task's stack (in sizeof(TN_UWord), not bytes)
Definition: tn_tasks.h:280
TN_TaskBody * task_func_addr
pointer to task's body function given to tn_task_create()
Definition: tn_tasks.h:283
int tslice_count
time slice counter
Definition: tn_tasks.h:312
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:272
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.
TN_TaskState
Task state.
Definition: tn_tasks.h:141
This state should never be publicly available.
Definition: tn_tasks.h:145
Timer.
Definition: tn_timer.h:202
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.
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:234
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:290
Event group.
Task isn't yet activated or it was terminated by tn_task_terminate().
Definition: tn_tasks.h:163
task has called tn_task_sleep()
Definition: tn_tasks.h:176
enum TN_ObjId id_task
id for object validity verification
Definition: tn_tasks.h:296
Task is ready to run (it doesn't mean that it is running at the moment)
Definition: tn_tasks.h:148
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:245
task wants to get memory block from memory pool, and there's no free memory blocks ...
Definition: tn_tasks.h:207
struct TN_DQueueTaskWait dqueue
fields specific to tn_dqueue.h
Definition: tn_tasks.h:329
unsigned waited
Flag indicates that task waited for something This flag is set automatially in _tn_task_set_waiting()...
Definition: tn_tasks.h:349
int priority
current task priority
Definition: tn_tasks.h:293
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:255
struct TN_ListItem task_queue
queue is used to include task in ready/wait lists
Definition: tn_tasks.h:248
for internal kernel usage only: this option must be provided when creating idle task ...
Definition: tn_tasks.h:222
task wants to lock a mutex with priority ceiling
Definition: tn_tasks.h:198
struct TN_FMemTaskWait fmem
fields specific to tn_fmem.h
Definition: tn_tasks.h:332
struct TN_Timer timer
timer object to implement task waiting for timeout
Definition: tn_tasks.h:251
Kernel system routines: system start, tick processing, time slice managing.
union TN_Task::@0 subsys_wait
subsystem-specific fields that are used while task waits for something.
task wants to put some data to the data queue, and there's no space in the queue. ...
Definition: tn_tasks.h:189
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:144
task waits to acquire a semaphore
Definition: tn_tasks.h:180
enum TN_RCode tn_task_sleep(TN_Timeout timeout)
Put current task to sleep for at most timeout ticks.
task isn't waiting for anything
Definition: tn_tasks.h:173
unsigned priority_already_updated
Internal flag used to optimize mutex priority algorithms.
Definition: tn_tasks.h:343
whether task should be activated right after it is created.
Definition: tn_tasks.h:218
void * task_func_param
pointer to task's parameter given to tn_task_create()
Definition: tn_tasks.h:286
FMem-specific fields related to waiting task, to be included in struct TN_Task.
Definition: tn_fmem.h:112
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.
task waits for some event in the event group to be set
Definition: tn_tasks.h:184
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:259
TN_TaskExitOpt
Options for tn_task_exit()
Definition: tn_tasks.h:228
enum TN_RCode task_wait_rc
waiting result code (reason why waiting finished)
Definition: tn_tasks.h:306
struct TN_ListItem mutex_queue
list of all mutexes that are locked by task
Definition: tn_tasks.h:264