RTAI API 5.1
Loading...
Searching...
No Matches
A general overview of RTAI fifos.

The new fifo implementation for RTAI maintains full compatibility with the basic services provided by its original NMT-RTL counterpart while adding many more.

It is important to remark that even if RTAI fifo APIs appears as before the implementation behind them is based on the mailbox concepts, already available in RTAI and symmetrically usable from kernel modules and Linux processes. The only notable difference, apart from the file style API functions to be used in Linux processes, is that on the module side you always have only non blocking put/get, so that any different policy should be enforced by using appropriate user handler functions.

With regard to fifo handlers it is now possible to install also one with a read/write argument (read 'r' , write 'w' ). In this way you have a handler that can know what it has been called for. It is useful when you open read-write fifos or to check against miscalls.

For that you can have a handler prototyped as:

int x_handler(unsigned int fifo, int rw);

that can be installed by using:

rtf_create_handler(fifo_numver, X_FIFO_HANDLER(x_handler));
int rtf_create_handler(unsigned int minor, void *handler)
Install a FIFO handler function.
Definition: fifos.c:1086

see rtai_fifos.h for the #X_FIFO_HANDLER macro definition. The handler code is likely to be a kind of:

int x_handler(unsigned int fifo, int rw);
{
if (rw == 'r') {
// do stuff for a call from read and return appropriate value.
} else {
// do stuff for a call from write and return appropriate value.
}
}

Even if fifos are strictly no more required in RTAI, because of the symmetric inter/intra kernel/user space support, they are kept both for compatibility reasons and because they are very useful tools to be used to communicate with interrupt handlers, since they do not require any scheduler to be installed. Notice that for such applications RTAI has now shared memory circular buffers (SCB) that might be even more effective to exchange data to/from interrupt handlers. In this sense you can see this new implementation of fifos as a kind of universal form of device drivers, since once you have your interrupt handler installed you can use fifo services to do all the rest.

However the new implementation made it easy to add some new services. One of these is the possibility of using asyncronous signals to notify data availability by catching a user set signal. It is implemented in a standard way, see the function:

rtf_set_async_sig(int fd, int signum) (default signum is SIGIO);
int rtf_set_async_sig(int fd, int signum)
Activate asynchronous notification of data availability.
Definition: rtai_fifos.h:723

and standard Linux man for fcntl and signal/sigaction, while the others are specific to this implementation.

A complete picture of what is available can be obtained from a look at rtai_fifos.h prototypes.

It is important to remark that now fifos allows multiple readers/writers so the select/poll mechanism to synchronize with in/out data can lead to unexpected blocks for such cases. For example: you poll and get that there are data available, then read/write them sure not to be blocked, meanwhile another user gets into and stoles all of your data, when you ask for them you get blocked.

To avoid such problems you have available the functions:

rtf_read_all_at_once(fd, buf, count);
int rtf_read_all_at_once(int fd, void *buf, int count)
Read data from FIFO in user space, waiting for all of them.
Definition: rtai_fifos.h:544

that blocks till all count bytes are available;

rtf_read_timed(fd, buf, count, ms_delay);
rtf_write_timed(fd, buf, count, ms_delay);
int rtf_write_timed(int fd, void *buf, int count, int ms_delay)
Write data to FIFO in user space, with timeout.
Definition: rtai_fifos.h:607
int rtf_read_timed(int fd, void *buf, int count, int ms_delay)
Read data from FIFO in user space, with timeout.
Definition: rtai_fifos.h:572

that block just for the specified delay in milliseconds but are queued in real time Linux process priority order. If ms_delay is zero they return immediately with all the data they could get, even if you did not set O_NONBLOCK at fifo opening.

So by mixing normal read/writes with their friends above you can easily implement blocking, non blocking and timed IOs. They are not standard and so not portable, but far easy to use then the select/poll mechanism. The standard llseek is also available but it is equivalent to calling rtf_reset, whatever fifo place you point at in the call.

For an easier timing you have available also:

rtf_suspend_timed(fd, ms_delay).
int rtf_suspend_timed(int fd, int ms_delay)
Suspend a process for some time.
Definition: rtai_fifos.h:467

To make them easier to use, fifos can now be created by the user at open time. If a fifo that does not exist already is opened, it is created with a 1K buffer. Any following creation on modules side resizes it without any loss of data. Again if you want to create a fifo from the user side with a desired buffer size you can use:

rtf_open_sized(const char *dev, perm, size).
int rtf_open_sized(const char *dev, int perm, int size)
Create a real-time FIFO.
Definition: rtai_fifos.h:507

Since they had to be there already to implement our mailboxes we have made available also binary semaphores. They can be used for many things, e.g. to synchronize shared memory access without any scheduler installed and in place of using blocking fifos read/writes with dummy data, just to synchronize. The semaphore services available are:

rtf_sem_init(fd, init_val);
rtf_sem_trywait(fd);
rtf_sem_timed_wait(fd, ms_delay);
rtf_sem_post(fd);
rtf_sem_destroy(fd);
int rtf_sem_timed_wait(int fd, int ms_delay)
Wait a semaphore with timeout.
Definition: rtai_fifos.h:694
int rtf_sem_wait(int fd)
Take a semaphore.
Definition: rtai_fifos.h:656

Note that fd is the file descriptor, a semaphore is always associated to a fifo and you must get a file descriptor by opening the corresponding fifo.

Naturally the above functions are symmetrically available in kernel space but, except for init and create, only for the nonblocking services, i.e: trywait and post.