Sunday, July 18, 2010

fifo_open - The next big thing

With the _rename_r mostly done and all the things falling in place, the next target was fifo_open routine under the libfs/. At first look, the routine looked too small to be so large in terms of code size and then realized that all the static routines invoked were inlined. Now, fifo_open was mostly fifo.c. This made it a big chunk.

Pipes / fifos are connectors used in a -ix system, which can be used by programs to convey data to other programs. A pipe has two (virtual) ends, write end - where a writer can fill in the data and a read end, from where a reader extracts data. From the implementation point of view, a pipe is a buffer, to which a reader / writer has exclusive access and modify the pipe by writing / reading.

About the routine:

Signature:

int fifo_open(
pipe_control_t **pipep,
rtems_libio_t *iop
);

This routine is called by open -> IMFS_fifo_open -> fifo_open

Open takes in a file name and the mode in which the pipe is to be opened. open creates an fd and provides the IMFS_fifo_open with the rtems_libio_t corresponding to the fd. IMFS_fifo_open extracts info from the rtems_libio_t and provides the (pipe_control_t **) and the (rtems_libio_t *) to fifo_open.

pipep - pipe control structure that is either already present or NULL.
iop - rtems_libio_t which is used to extract useful info like modes of the open

Purpose:

* open a fifo / pipe in the required mode

Misc:

* It is also called during a unnamed pipe creation - a posix pipe creation routine

Flow:

* Create a new pipe, if necessary
- If the pipe control structure does not exist, allocate a new pipe control stucture.
- A new pipe control structure requires
# pipe buffer
# Two barriers, one each for readers and writers
# A semaphore for the producer-consumer solution

* Check the mode in which the pipe is to be opened
* If read mode, wake up the possibly waiting writers
* If a non-blocking read mode is requested, return. Else wait at a barrier
* If write mode, wake up the possibly waiting readers
* If a non-blocking write mode is requested, its not possible and return with an error. Else, wait at a barrier until a reader wakes us up
* If the mode is a read-write mode, register the increase in number of readers/writers and return

Test cases:

With Pipes/fifos disabled in the configuration
* attempt opening a fifo

With Pipes/fifos enabled in the configuration, with a single task,

* Consume all barriers and semaphores, try opening fifo.
* Release a barrier, try opening fifo
* Release another barrier, try opening fifo
* Delete a semaphore, try opening fifo
* Consume all of the memory, try opening fifo
* open fifo in RD-WR mode
* open fifo in RDONLY, nonblock
* open fifo in WRONLY, nonblock
* open fifo several times, to get the wrap around a->z->a

With Pipes/fifos enabled in the configuration, with two tasks,

* open pipe in a read-only mode first, block the reader and then open the pipe in a write-only mode, which unblocks the reader
* open pipe in a write-only mode first, block the writer and then open the pipe in a read-only mode, which unblocks the writer
* write and read from the pipe to be sure about the fifo_open.

Changes to RTEMS, issues with routine:

* Without fifos enabled, fifo_opening was possible. New config item
CONFIGURE_FIFOS(PIPES)_ENABLED and
CONFIGURE_MAXIMUM_FIFOS (PIPES)
created as per which number of semaphore / barriers required are calculated. Fixed.

* when the fifo was opened in WRONLY | NONBLOCK mode, the pipe_release did not destroy the pipe. PR 1542 - Fixed.

* fifo_open returned EINTR where it was supposed to return ENOMEM. PR 1577 - Fixed.

* pipe_release did not delete the semaphore, since it was still in use. PR 1585 - Fixed.

Coverage result:

* fifo_open remains mostly covered, except for the following cases:
- Errors on barrier wait
- Errors on semaphore obtain

Challenges:


* Making my way through the code tree
* Understanding the working of a pipe / fifo
* Understanding task creation, deletion, blocking

Submitted patch:

PR on rtems-bugzilla - PR 1546

https://code.google.com/p/rtems-coverage-improvements-gsoc-2010/source/browse/#svn/trunk/fifo-open-patch

Learnings:

* How to better submit a test
* How to better submit a patch to the RTEMS
* Pipe / fifo related concepts
* Tasks, their creation, deletion, when do they block...
* Semaphore / barrier related concepts
* Get a ENOMEM by allocating most of heap
* How to hit the code, more hard :)

Next:

After this long stretch, thanks to the examinations at the university, next were the lot easier error reporting routines.

No comments:

Post a Comment