LXRT is a module that allows you to use all the services made available by RTAI and its schedulers in user space, both for soft and hard real time. At the moment it is a feature youll find nowhere but with RTAI. For an explanation of how it works see Pierre Cloutiers LXRT-INFORMED FAQs, and the explanation of the implementation of hard real time in user space (contributed by: Pierre Cloutier, Paolo Mantegazza, Steve Papacharalambous).
LXRT-INFORMED should be the production version of LXRT, the latter being the development version. So it can happen that LXRT-INFORMED could be lagging slightly behind LXRT. If you need to hurry to the services not yet ported to LXRT-INFORMED do it without pain. Even if you are likely to miss some useful services found only in LXRT-INFORMED, we release only when a feature is relatively stable.
From what said above there should be no need for anything specific as all the functions you can use in user space have been already documented in this manual. There are however a few exceptions that need to be explained.
Note also that, as already done for the shared memory services in user space, the function calls for Linux processes are inlined in the file rtai_lxrt.h. This approach has been preferred to a library since it is simpler, more effective, the calls are short and simple so that, even if it is likely that there can be more than just a few per process, they could never be charged of making codes too bigger. Also common to shared memory is the use of unsigned int to identify LXRT objects. If you want to use string identifiers the same support functions, i.e. nam2num() and num2nam(), can be used.
Files | |
file | common.c |
Common scheduling function. | |
file | rtai_lxrt.h |
LXRT main header. | |
file | rtai_mbx.h |
file | rtai_nam2num.h |
Conversion between characters strings and unsigned long identifiers. | |
file | rtai_registry.h |
file | rtai_sem.h |
Defines | |
#define | rt_mbx_init(name, size) rt_typed_mbx_init(name, size, FIFO_Q) |
#define | rt_sem_init(name, value) rt_typed_sem_init(name, value, CNT_SEM) |
#define | rt_cond_init(name) rt_typed_sem_init(name, 0, BIN_SEM) |
Functions | |
void * | rt_get_adr (unsigned long name) |
Get an object address by its name. | |
unsigned long | rt_get_name (void *adr) |
Get an object name by its address. | |
RT_TASK * | rt_task_init (int name, int priority, int stack_size, int max_msg_size) |
Create a new real time task in user space. | |
int | rt_change_prio (RT_TASK *task, int priority) |
Change a task priority. | |
void | rt_make_soft_real_time (void) |
Return a hard real time Linux process, or pthread to the standard Linux behavior. | |
int | rt_task_delete (RT_TASK *task) |
int | rt_task_yield (void) |
Yield the current task. | |
int | rt_task_suspend (RT_TASK *task) |
rt_task_suspend suspends execution of the task task. | |
int | rt_task_resume (RT_TASK *task) |
Resume a task. | |
int | rt_task_make_periodic (RT_TASK *task, RTIME start_time, RTIME period) |
Make a task run periodically. | |
int | rt_task_make_periodic_relative_ns (RT_TASK *task, RTIME start_delay, RTIME period) |
Make a task run periodically. | |
void | rt_task_wait_period (void) |
Wait till next period. | |
void | rt_sleep (RTIME delay) |
Delay/suspend execution for a while. | |
void | rt_sleep_until (RTIME time) |
Delay/suspend execution for a while. | |
RTIME | start_rt_timer (int period) |
Start timer. | |
void | stop_rt_timer (void) |
Stop timer. | |
RTIME | rt_get_time (void) |
Get the current time. | |
RTIME | count2nano (RTIME count) |
Convert internal count units to nanoseconds. | |
RTIME | nano2count (RTIME nanos) |
Convert nanoseconds to internal count units. | |
void | rt_busy_sleep (int ns) |
Delay/suspend execution for a while. | |
void | rt_set_periodic_mode (void) |
Set timer mode. | |
void | rt_set_oneshot_mode (void) |
Set timer mode. | |
int | rt_task_signal_handler (RT_TASK *task, void(*handler)(void)) |
Set the signal handler of a task. | |
int | rt_task_use_fpu (RT_TASK *task, int use_fpu_flag) |
int | rt_linux_use_fpu (int use_fpu_flag) |
Set indication of FPU usage. | |
void | rt_preempt_always (int yes_no) |
Enable hard preemption. | |
RTIME | rt_get_time_ns (void) |
Get the current time. | |
RTIME | rt_get_cpu_time_ns (void) |
Get the current time. | |
void | rt_set_runnable_on_cpus (RT_TASK *task, unsigned long cpu_mask) |
Assign CPUs to a task. | |
void | rt_set_runnable_on_cpuid (RT_TASK *task, unsigned int cpuid) |
Assign CPUs to a task. | |
void | start_rt_apic_timers (struct apic_timer_setup_data *setup_mode, unsigned int rcvr_jiffies_cpuid) |
Start local apic timer. | |
void | rt_preempt_always_cpuid (int yes_no, unsigned int cpuid) |
Enable hard preemption. | |
RTIME | count2nano_cpuid (RTIME count, unsigned int cpuid) |
Convert internal count units to nanoseconds. | |
RTIME | nano2count_cpuid (RTIME nanos, unsigned int cpuid) |
Convert nanoseconds to internal count units. | |
RTIME | rt_get_time_cpuid (unsigned int cpuid) |
Get the current time. | |
RTIME | rt_get_time_ns_cpuid (unsigned int cpuid) |
Get the current time. | |
void | rt_make_hard_real_time (void) |
Give a Linux process, or pthread, hard real time execution capabilities allowing full kernel preemption. | |
void | rt_allow_nonroot_hrt (void) |
Allows a non root user to use the Linux POSIX soft real time process management and memory lock functions, and allows it to do any input-output operation from user space. | |
int | rt_register (unsigned long nam, void *adr, int typ, struct task_struct *tsk) |
int | rt_drg_on_name (unsigned long name) |
int | rt_drg_on_adr (void *adr) |
|
Initialize a condition variable. Allocates and initializes a condition variable to be referred by name.
|
|
Initialize mailbox. Initializes a mailbox referred to by name of size size. It is important to remark that the returned task pointer cannot be used directly, they are for kernel space data, but just passed as arguments when needed.
|
|
Initialize a counting semaphore. Allocates and initializes a semaphore to be referred by name.
|
|
Convert internal count units to nanoseconds. This function converts the time of timercounts internal count units into nanoseconds. Remember that the count units are related to the time base being used (see functions rt_set_oneshot_mode() and rt_set_periodic_mode() for an explanation).
|
|
Convert internal count units to nanoseconds. This function converts the time of timercounts internal count units into nanoseconds. It is to be used with the MUP scheduler since with such a scheduler it is possible to have independent timers, i.e. periodic of different periods or a mixing of periodic and oneshot, so that it is impossible to establish which conversion units should be used in the case one asks for a conversion from any CPU for any other CPU. All these functions have the same behavior with UP and SMP schedulers.
|
|
Convert nanoseconds to internal count units. This function converts the time of nanosecs nanoseconds into internal counts units. Remember that the count units are related to the time base being used (see functions rt_set_oneshot_mode() and rt_set_periodic_mode() for an explanation). The versions ending with_cpuid are to be used with the MUP scheduler since with such a scheduler it is possible to have independent timers, i.e. periodic of different periods or a mixing of periodic and oneshot, so that it is impossible to establish which conversion units should be used in the case one asks for a conversion from any CPU for any other CPU. All these functions have the same behavior with UP and SMP schedulers.
|
|
Convert nanoseconds to internal count units. This function converts the time of nanosecs nanoseconds into internal counts units. Remember that the count units are related to the time base being used (see functions rt_set_oneshot_mode() and rt_set_periodic_mode() for an explanation). This function is to be used with the MUP scheduler since with such a scheduler it is possible to have independent timers, i.e. periodic of different periods or a mixing of periodic and oneshot, so that it is impossible to establish which conversion units should be used in the case one asks for a conversion from any CPU for any other CPU. All these functions have the same behavior with UP and SMP schedulers.
|
|
Allows a non root user to use the Linux POSIX soft real time process management and memory lock functions, and allows it to do any input-output operation from user space. Only the process itself can use this functions, it is not possible to impose the related transition from another process. |
|
Delay/suspend execution for a while. rt_busy_sleep delays the execution of the caller task without giving back the control to the scheduler. This function burns away CPU cycles in a busy wait loop so it should be used only for very short synchronization delays. On machine not having a TSC clock it can lead to many microseconds uncertain busy sleeps because of the need of reading the 8254 timer.
|
|
Change a task priority. rt_change_prio changes the base priority of task task to prio. Recall that a task has a base native priority, assigned at its birth or by rt_change_prio(), and an actual, inherited, priority. They can be different because of priority inheritance.
|
|
Deregister an object by its address. rt_drg_on_adr deregisters the object identified by its adr.
|
|
Deregister an object by its name. rt_drg_on_name deregisters the object identified by its name.
|
|
Get an object address by its name. rt_get_adr returns the address associated to name.
|
|
Get the current time. rt_get_cpu_time_ns always returns the CPU time in nanoseconds whatever timer is in use.
|
|
Get an object name by its address. rt_get_name returns the name pointed by the address adr.
|
|
Get the current time. rt_get_time returns the time, in internal count units, since start_rt_timer was called. In periodic mode this number is in multiples of the periodic tick. In oneshot mode it is directly the TSC count for CPUs having a time stamp clock (TSC), while it is a (FIXME) on 8254 units for those not having it (see functions rt_set_oneshot_mode() and rt_set_periodic_mode() for an explanation).
|
|
Get the current time. rt_get_time_cpuid returns the time, in internal count units, since start_rt_timer was called. In periodic mode this number is in multiples of the periodic tick. In oneshot mode it is directly the TSC count for CPUs having a time stamp clock (TSC), while it is a (FIXME) on 8254 units for those not having it (see functions rt_set_oneshot_mode() and rt_set_periodic_mode() for an explanation). This version ending with _cpuid must be used with the MUP scheduler when there is the need to declare from which cpuid the time must be gotten (FIXME). In fact one can need to get the time of another CPU and timers can differ from CPU to CPU. (FIXME) All these functions have the same behavior with UP and SMP schedulers.
|
|
Get the current time. rt_get_time_ns is the same as rt_get_time() but the returned time is converted to nanoseconds.
|
|
Get the current time. rt_get_time_ns is the same as rt_get_time but the returned time is converted to nanoseconds. The version ending with _cpuid must be used with the MUP scheduler when there is the need to declare from which cpuidthe time must be got. In fact one can need to get the time of another CPU and timers can differ from CPU to CPU. All these functions have the same behavior with UP and SMP schedulers.
|
|
Set indication of FPU usage. rt_linux_use_fpu informs the scheduler that floating point arithmetic operations will be used also by foreground Linux processes, i.e. the Linux kernel itself (unlikely) and any of its processes.
|
|
Give a Linux process, or pthread, hard real time execution capabilities allowing full kernel preemption. rt_make_hard_real_time makes the soft Linux POSIX real time process, from which it is called, a hard real time LXRT process. It is important to remark that this function must be used only with soft Linux POSIX processes having their memory locked in memory. See Linux man pages. Only the process itself can use this functions, it is not possible to impose the related transition from another process. Note that processes made hard real time should avoid making any Linux System call that can lead to a task switch as Linux cannot run anymore processes that are made hard real time. To interact with Linux you should couple the process that was made hard real time with a Linux buddy server, either standard or POSIX soft real time. To communicate and synchronize with the buddy you can use the wealth of available RTAI, and its schedulers, services. After all it is pure nonsense to use a non hard real time Operating System, i.e. Linux, from within hard real time processes. |
|
Return a hard real time Linux process, or pthread to the standard Linux behavior. rt_make_soft_real_time returns to soft Linux POSIX real time a process, from which it is called, that was made hard real time by a call to rt_make_hard_real_time. Only the process itself can use this functions, it is not possible to impose the related transition from another process. |
|
Enable hard preemption. In the oneshot mode the next timer expiration is programmed after a timer shot by choosing among the timed tasks the one with a priority higher than the task chosen to run as current, with the constraint of always assuring a correct Linux timing. In such a view there is no need to fire the timer immediately. In fact it can happen that the current task can be so fast to get suspended and rerun before the one that was devised to time the next shot when it was made running. In such a view RTAI schedulers try to shoot only when strictly needed. This minimizes the number of slow setups of the 8254 timer used with UP and 8254 based SMP schedulers. While such a policy minimizes the number of actual shots, greatly enhancing efficiency, it can be unsuitable when an application has to be guarded against undesired program loops or other unpredicted error causes. Calling these functions with a nonzero value assures that a timed high priority preempting task is always programmed to be fired while another task is currently running. The default is no immediate preemption in oneshot mode, i.e. firing of the next shot programmed only when strictly needed to satisfy tasks timings.
|
|
Enable hard preemption. In the oneshot mode the next timer expiration is programmed after a timer shot by choosing among the timed tasks the one with a priority higher than the task chosen to run as current, with the constraint of always assuring a correct Linux timing. In such a view there is no need to fire the timer immediately. In fact it can happen that the current task can be so fast to get suspended and rerun before the one that was devised to time the next shot when it was made running. In such a view RTAI schedulers try to shoot only when strictly needed. This minimizes the number of slow setups of the 8254 timer used with UP and 8254 based SMP schedulers. While such a policy minimizes the number of actual shots, greatly enhancing efficiency, it can be unsuitable when an application has to be guarded against undesired program loops or other unpredicted error causes. Calling these functions with a nonzero value assures that a timed high priority preempting task is always programmed to be fired while another task is currently running. The default is no immediate preemption in oneshot mode, i.e. firing of the next shot programmed only when strictly needed to satisfy tasks timings.
|
|
Register an object. rt_register registers the object to be identified with name, which is pointed by adr.
|
|
Set timer mode. rt_set_periodic_mode sets the periodic mode for the timer. It consists of a fixed frequency timing of the tasks in multiple of the period set with a call to start_rt_timer(). The resolution is that of the 8254 (1193180 Hz) on a UP machine, or if the 8254 based SMP scheduler is being used. For the SMP scheduler timed by the local APIC timer and for the MUP scheduler the timer resolution is that of the local APIC timer frequency, generally the bus frequency divided 16. Any timing request not being an integer multiple of the set timer period is satisfied at the closest period tick. It is the default mode when no call is made to set the oneshot mode.
|
|
Set timer mode. rt_set_periodic_mode sets the periodic mode for the timer. It consists of a fixed frequency timing of the tasks in multiple of the period set with a call to start_rt_timer(). The resolution is that of the 8254 (1193180 Hz) on a UP machine, or if the 8254 based SMP scheduler is being used. For the SMP scheduler timed by the local APIC timer and for the MUP scheduler the timer resolution is that of the local APIC timer frequency, generally the bus frequency divided 16. Any timing request not being an integer multiple of the set timer period is satisfied at the closest period tick. It is the default mode when no call is made to set the oneshot mode.
|
|
Assign CPUs to a task. rt_set_runnable_on_cpuid select one or more CPUs which are allowed to run task task. rt_set_runnable_on_cpuid assigns a task to a single specific CPU. If no CPU, as selected by cpu_mask or cpuid, is available, both functions choose a possible CPU automatically, following the same rule as above.
|
|
Assign CPUs to a task. rt_set_runnable_on_cpus selects one or more CPUs which are allowed to run task task. rt_set_runnable_on_cpus behaves differently for MUP and SMP schedulers. Under the SMP scheduler bit<n> of cpu_mask enables the task to run on CPU<n>. Under the MUP scheduler it selects the CPU with less running tasks among those allowed by cpu_mask. Recall that with MUP a task must be bounded to run on a single CPU. If no CPU, as selected by cpu_mask or cpuid, is available, both functions choose a possible CPU automatically, following the same rule as above.
|
|
Delay/suspend execution for a while. rt_sleep suspends execution of the caller task for a time of delay internal count units. During this time the CPU is used by other tasks.
|
|
Delay/suspend execution for a while. rt_sleep_until is similar to rt_sleep() but the parameter time is the absolute time till the task have to be suspended. If the given time is already passed this call has no effect.
|
|
rt_task_delete deletes a real time task previously created by rt_task_init() or rt_task_init_cpuid().
|
|
Create a new real time task in user space. rt_task_init provides a real time buddy, also called proxy, task to the Linux process that wants to access RTAI scheduler services. It needs no task function as none is used, but it does need to setup a task structure and initialize it appropriately as the provided services are carried out as if the Linux process has become an RTAI task. Because of that it requires less arguments and returns the pointer to the task that is to be used in related calls.
Keep an eye on the default stack (512) and message (256) sizes as they seem to be acceptable, but this API has not been used extensively with complex interrupt service routines. Since the latter are served on the stack of any task being interrupted, and more than one can pile up on the same stack, it can be possible that a larger stack is required. In such a case either recompile lxrt.c with macros STACK_SIZE and MSG_SIZE set appropriately, or explicitly assign larger values at your buddy tasks inits. Note that while the stack size can be critical the message size will not. In fact the module reassigns it, appropriately sized, whenever it is needed. The cost is a kmalloc with GFP_KERNEL that can block, but within the Linux environment. Note also that max_msg_size is for a buffer to be used to copy whatever message, either mailbox or inter task, from user to kernel space, as messages are not necessarily copied immediately, and has nothing to do directly with what you are doing. It is important to remark that the returned task pointers cannot be used directly, they are for kernel space data, but just passed as arguments when needed.
|
|
Make a task run periodically. rt_task_make_periodic mark the task task, previously created with rt_task_init(), as suitable for a periodic execution, with period period, when rt_task_wait_period() is called. The time of first execution is defined through start_time or start_delay. start_time is an absolute value measured in clock ticks. start_delay is relative to the current time and measured in nanoseconds.
|
|
Make a task run periodically. rt_task_make_periodic_relative_ns mark the task task, previously created with rt_task_init(), as suitable for a periodic execution, with period period, when rt_task_wait_period() is called. The time of first execution is defined through start_time or start_delay. start_time is an absolute value measured in clock ticks. start_delay is relative to the current time and measured in nanoseconds.
|
|
Resume a task. rt_task_resume resumes execution of the task task previously suspended by rt_task_suspend(), or makes a newly created task ready to run, if it makes the task ready. Since no account is made for multiple suspend rt_task_resume unconditionally resumes any task it makes ready.
|
|
Set the signal handler of a task. rt_task_signal_handler installs, or changes, the signal function of a real time task.
|
|
rt_task_suspend suspends execution of the task task. It will not be executed until a call to rt_task_resume() or rt_task_make_periodic() is made. No account is made for multiple suspends, i.e. a multiply suspended task is made ready as soon as it is rt_task_resumed, thus immediately resuming its execution if it is the highest in priority.
|
|
rt_task_use_fpu informs the scheduler that floating point arithmetic operations will be used by the real time task task.
|
|
Wait till next period. rt_task_wait_period suspends the execution of the currently running real time task until the next period is reached. The task must have been previously marked for a periodic execution by calling rt_task_make_periodic() or rt_task_make_periodic_relative_ns().
|
|
Yield the current task. rt_task_yield() stops the current task and takes it at the end of the list of ready tasks having its same priority. The scheduler makes the next ready task of the same priority active. Recall that RTAI schedulers allow only higher priority tasks to preempt the execution of lower priority ones. So equal priority tasks cannot preempt each other and rt_task_yield() should be used if a user needs a cooperative time slicing among equal priority tasks. The implementation of the related policy is wholly in the hand of the user. It is believed that time slicing is too much an overhead for the most demanding real time applications, so it is left up to you. |
|
Start local apic timer. start_rt_apic_timers starts local APIC timers according to what is found in setup_data.
|
|
Start timer. start_rt_timer starts the timer with a period period. The period is in internal count units and is required only for the periodic mode. In the oneshot mode the period value is ignored. This functions uses the 8254 with the UP and the 8254 based SMP scheduler. Otherwise it uses a single local APIC with the APIC based SMP schedulers and an APIC for each CPU with the MUP scheduler. In the latter case all local APIC timers are paced in the same way, according to the timer mode set.
|
|
Stop timer. stop_rt_timer stops the timer. The timer mode is set to periodic.
|