FIFOs
=====

In the 2.4.xx related RTAi releases you'll find only our new fifo implementation
for RTAI. It maintains full compatibility with the basic services provided by
its original NMT-RTL counterpart while adding some more. 

The porting of David Schleef (ds@stm.lbl.gov) rt_printk( const char *fmt, ...), 
that allows you to safely use printk in RTAI modules, has been taken away and
put in rtai.c. 

It is important to remark that even if the RTAI fifo API appears as before
the implementation behind it is based on the mailboxes 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 what it has been called for. It is usefull 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).

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
availability of LXRT, fifos are kept for both 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.  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);

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);

that blocks till all count bytes are available;

	- rtf_read_timed(fd, buf, count, ms_delay);

	- rtf_write_timed(fd, buf, count, ms_delay);

that block just for the specified delay in millisecs but are queued in real time
Linux process priority order. If ms_delay is zero they return immediatly 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).

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 it 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).

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
sinchronize 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_wait(fd);
	- rtf_sem_trywait(fd);
	- rtf_sem_timed_wait(fd, ms_delay);
	- rtf_sem_post(fd);
	- rtf_sem_destroy(fd);

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.

A final, important, warning. All the new services have been tested in
relation to their basic working, while the standard RTL calls worked well
on all the examples they worked before. Thus you will not miss anything
with respect to either RTL fifos or the previous adaptation of RTAI to
them. We hope in some help in thorougly verifying all the remaining new
stuff.

Note that this directory contains an examples that shows the use of select,
timed reads and semaphores.

To use it:

insmod task  // for a real time task, a copy of the latency calibration task;
./check      // to see the interaction;

'check' ends by itself. See the macros on top of check.c to change the
execution parameters.

