In such a way you have opened a whole spectrum of development and implementation lanes, allowing maximum flexibility with uncompromized performances.
The new services provided can be useful when you have many tasks, both in kernel and user space, that must execute in soft/hard real time but do not need any RTAI scheduler service that could lead to a task block. Such tasks are here called tasklets and can be of two kinds: normal tasklets and timed tasklets (timers).
It must be noted that only timers should need to be made available both in user and kernel space. In fact normal tasklets in kernel space are nothing but standard functions that can be directly executed by calling them, so there would be no need for any special treatment. However to maintain full usage symmetry, and to ease any possible porting from one address space to the other, also normal tasklet functions can be used in whatever address space.
Note that if, at this point, you are reminded to similar Linux kernel services you are not totally wrong. They are not exactly the same, because of their symmetric availability in kernel and user space, but the basic idea behind them is clearly fairly similar.
Tasklets should be used whenever the standard hard real time tasks available with RTAI and LXRT schedulers can be a waist of resources and the execution of simple, possibly timed, functions could often be more than enough. Instances of such applications are timed polling and simple Programmable Logic Controllers (PLC) like sequences of services. Obviously there are many others instances that can make it sufficient the use of tasklets, either normal or timers. In general such an approach can be a very useful complement to fully featured tasks in controlling complex machines and systems, both for basic and support services.
It is remarked that the implementation found here for timed tasklets rely on a server support task that executes the related timer functions, either in oneshot or periodic mode, on the base of their time deadline and according to their, user assigned, priority. Instead, as told above, plain tasklets are just functions executed from kernel space; their execution needs no server and is simply triggered by calling a given service function at due time, either from a kernel task or interrupt handler requiring, or in charge of, their execution when they are needed. Once more it is important to recall that all non blocking RTAI scheduler services can be used in any tasklet function. Blocking services must absolutely be avoided. They will deadlock the timers server task, executing task or interrupt handler, whichever applies, so that no more tasklet functions will be executed.
User and kernel space MINI_RTAI_LXRT applications can cooperate and synchronize by using shared memory. It has been called MINI_RTAI_LXRT because it is a kind of light soft/hard real time server that can partially substitute RTAI and LXRT in simple applications, i.e. if the constraints hinted above are wholly satisfied. So MINI_RTAI_LXRT can be used in kernel and user space, with any RTAI scheduler. Its implementations has been very easy, as it is nothing but what its name implies. LXRT made all the needed tools already available. In fact it duplicates a lot of LXRT so that its final production version will be fully integrated with it, ASAP. However, at the moment, it cannot work with LXRT yet.
Note that in user space you run within the memory of the process owning the tasklet function so you MUST lock all of your processes memory in core, by using mlockall, to prevent it being swapped out. Also abundantly pre grow your stack to the largest size needed during the execution of your application, see mlockall usage in Linux manuals.
The RTAI distribution contains many useful examples that demonstrate the use of most services, both in kernel and user space.
Files | |
file | rtai_nam2num.h |
Conversion between characters strings and unsigned long identifiers. | |
file | rtai_tasklets.h |
Interface of the mini LXRT RTAI tasklets module. | |
file | tasklets.c |
Implementation of the mini LXRT RTAI tasklets module. | |
Functions | |
rt_tasklet_struct * | rt_init_tasklet (void) |
Init, in kernel space, a tasklet structure to be used in user space. | |
void | rt_delete_tasklet (struct rt_tasklet_struct *tasklet) |
Delete, in kernel space, a tasklet structure to be used in user space. | |
int | rt_insert_timer (struct rt_tasklet_struct *timer, int priority, RTIME firing_time, RTIME period, void(*handler)(unsigned long), unsigned long data, int pid) |
Insert a timer in the list of timers to be processed. | |
void | rt_remove_timer (struct rt_tasklet_struct *timer) |
Remove a timer in the list of timers to be processed. | |
void | rt_set_timer_priority (struct rt_tasklet_struct *timer, int priority) |
Change the priority of an existing timer. | |
void | rt_set_timer_firing_time (struct rt_tasklet_struct *timer, RTIME firing_time) |
Change the firing time of a timer. | |
void | rt_set_timer_period (struct rt_tasklet_struct *timer, RTIME period) |
Change the period of a timer. | |
int | rt_insert_tasklet (struct rt_tasklet_struct *tasklet, int priority, void(*handler)(unsigned long), unsigned long data, unsigned long id, int pid) |
Insert a tasklet in the list of tasklets to be processed. | |
void | rt_remove_tasklet (struct rt_tasklet_struct *tasklet) |
Remove a tasklet in the list of tasklets to be processed. | |
int | rt_exec_tasklet (struct rt_tasklet_struct *tasklet) |
Exec a tasklet. | |
rt_tasklet_struct * | rt_find_tasklet_by_id (unsigned long id) |
Find a tasklet identified by its id. |
|
Delete, in kernel space, a tasklet structure to be used in user space. rt_tasklet_delete free a tasklet structure (struct rt_tasklet_struct) in kernel space that was allocated by rt_tasklet_init.
|
|
Exec a tasklet. rt_exec_tasklet execute a tasklet from the list of tasklets to be processed.
User space tasklets instead must be first found within the tasklet list by calling rt_find_tasklet_by_id() to get the tasklet address to be used in rt_tasklet_exec().
|
|
Find a tasklet identified by its id.
|
|
Init, in kernel space, a tasklet structure to be used in user space. rt_tasklet_init allocate a tasklet structure (struct rt_tasklet_struct) in kernel space to be used for the management of a user space tasklet. This function is to be used only for user space tasklets. In kernel space it is just an empty macro, as the user can, and must allocate the related structure directly, either statically or dynamically.
|
|
Insert a tasklet in the list of tasklets to be processed. rt_insert_tasklet insert a tasklet in the list of tasklets to be processed.
|
|
Insert a timer in the list of timers to be processed. rt_insert_timer insert a timer in the list of timers to be processed. Timers can be either periodic or oneshot. A periodic timer is reloaded at each expiration so that it executes with the assigned periodicity. A oneshot timer is fired just once and then removed from the timers list. Timers can be reinserted or modified within their handlers functions.
|
|
Remove a tasklet in the list of tasklets to be processed. rt_remove_tasklet remove a tasklet from the list of tasklets to be processed.
|
|
Remove a timer in the list of timers to be processed. rt_remove_timer remove a timer from the list of the timers to be processed.
|
|
Change the firing time of a timer. rt_set_timer_firing_time changes the firing time of a periodic timer overloading any existing value, so that the timer next shoot will take place at the new firing time. Note that if a oneshot timer has its firing time changed after it has already expired this function has no effect. You should reinsert it in the timer list with the new firing time.
|
|
Change the period of a timer. rt_set_timer_period changes the period of a periodic timer. Note that the new period will be used to pace the timer only after the expiration of the firing time already in place. Using this function with a period different from zero for a oneshot timer, that has not expired yet, will transform it into a periodic timer.
This function an be used within the timer handler.
|
|
Change the priority of an existing timer. rt_set_timer_priority change the priority of an existing timer.
|