Debugging FIFO logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@774 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2008-07-22 00:52:07 +00:00
parent d05f4750cb
commit 0b22d6a034
4 changed files with 104 additions and 210 deletions
+5 -1
View File
@@ -16,7 +16,7 @@
</b></big></h1> </b></big></h1>
<p><small>by</small></p> <p><small>by</small></p>
<p>Gregory Nutt</p> <p>Gregory Nutt</p>
<p><small>Last Update: March 15, 2008</small></p> <p><small>Last Update: July 21, 2008</small></p>
</center> </center>
<center><h1>Table of Contents</h1></center> <center><h1>Table of Contents</h1></center>
@@ -1509,6 +1509,10 @@ The system can be re-made subsequently by just typing <code>make</code>.
structures. The system manages a pool of preallocated structures. The system manages a pool of preallocated
watchdog structures to minimize dynamic allocations watchdog structures to minimize dynamic allocations
</li> </li>
<li>
<code>CONFIG_DEV_FIFO_SIZE</code>: Size, in bytes, of the buffer to allocated
for FIFO support (default is 1024).
</li>
</ul> </ul>
<h2>Network Support</h2> <h2>Network Support</h2>
+2
View File
@@ -239,6 +239,8 @@ defconfig -- This is a configuration file similar to the Linux
CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog CONFIG_PREALLOC_WDOGS - The number of pre-allocated watchdog
structures. The system manages a pool of preallocated structures. The system manages a pool of preallocated
watchdog structures to minimize dynamic allocations watchdog structures to minimize dynamic allocations
CONFIG_DEV_FIFO_SIZE - Size, in bytes, of the buffer to allocated
for FIFO support
TCP/IP and UDP support via uIP TCP/IP and UDP support via uIP
CONFIG_NET - Enable or disable all network features CONFIG_NET - Enable or disable all network features
+95 -208
View File
@@ -53,13 +53,14 @@
#include <assert.h> #include <assert.h>
#include <nuttx/fs.h> #include <nuttx/fs.h>
/****************************************************************************
* Definitions
****************************************************************************/
#ifndef CONFIG_DEV_FIFO_SIZE #ifndef CONFIG_DEV_FIFO_SIZE
# define CONFIG_DEV_FIFO_SIZE 1024 # define CONFIG_DEV_FIFO_SIZE 1024
#endif #endif
#if CONFIG_DEV_FIFO_SIZE > 0
/****************************************************************************
* Definitions
****************************************************************************/
/* Maximum number of open's supported on FIFO */ /* Maximum number of open's supported on FIFO */
@@ -269,12 +270,11 @@ static ssize_t fifo_read(FAR struct file *filep, FAR char *buffer, size_t len)
struct inode *inode = filep->f_inode; struct inode *inode = filep->f_inode;
struct fifo_dev_s *dev = inode->i_private; struct fifo_dev_s *dev = inode->i_private;
ssize_t nread = 0; ssize_t nread = 0;
ssize_t nrqstd = len; fifo_ndx_t ret;
int ret;
/* Some sanity checking */ /* Some sanity checking */
#if CONFIG_DEBUG #if CONFIG_DEBUG
if (dev) if (!dev)
{ {
return -ENODEV; return -ENODEV;
} }
@@ -287,115 +287,45 @@ static ssize_t fifo_read(FAR struct file *filep, FAR char *buffer, size_t len)
return ERROR; return ERROR;
} }
/* Loop until all of the bytes have been read */ /* If the fifo is empty, then wait for something to be written to it */
for (;;) while (dev->d_wrndx == dev->d_rdndx)
{ {
ssize_t nbytes; #warning "Support for O_NONBLOCK needed"
dev->d_nreaders++;
/* Is there data available at the end of the buffer? When the write sched_lock();
* index is smaller than the read index, then all of the data from the sem_post(&dev->d_bfsem);
* read index to the end of the buffer is available for reading. ret = sem_wait(&dev->d_rdsem);
*/ sched_unlock();
if (ret < 0 || sem_wait(&dev->d_bfsem) < 0)
if (dev->d_rdndx > dev->d_wrndx)
{ {
/* Yes.. How many bytes are available at the end of the circular buffer */ return ERROR;
nbytes = CONFIG_DEV_FIFO_SIZE - dev->d_rdndx;
if (nbytes > 0)
{
/* Read bytes from the end of the buffer. Are there more than we
* need?
*/
if (nbytes > nrqstd)
{
nbytes = nrqstd;
}
/* Copy the correct number of bytes */
memcpy(&buffer[nread], &dev->d_buffer[dev->d_rdndx], nbytes);
/* Then update all indices and counts */
nread += nbytes;
nrqstd -= nbytes;
dev->d_rdndx += nbytes;
if (dev->d_rdndx >= CONFIG_DEV_FIFO_SIZE)
{
dev->d_rdndx = 0;
}
}
}
/* We have read some or all of the data at the end of the buffer. Do we still need more? */
if (nrqstd > 0)
{
/* Yes... then we now that we have consumed all of the bytes at the end of the
* buffer. How many bytes are available at the end of the circular buffer>
*/
nbytes = dev->d_wrndx - dev->d_rdndx;
if (nbytes > 0)
{
/* Read bytes from the beginning of the buffer. Are there more than we
* need?
*/
if (nbytes > nrqstd)
{
nbytes = nrqstd;
}
/* Copy the correct number of bytes */
memcpy(&buffer[nread], &dev->d_buffer[dev->d_rdndx], nbytes);
/* Then update all indices and counts */
nread += nbytes;
nrqstd -= nbytes;
dev->d_rdndx += nbytes;
}
}
/* Was anything read? */
if (nread > 0)
{
/* Yes.. Notify the waiting writers that space is again available */
if (dev->d_nwriters > 0)
{
sem_post(&dev->d_wrsem);
}
/* Return the number of bytes read */
sem_post(&dev->d_bfsem);
return nread;
}
else
{
/* No.. wait for data to be added to the FIFO */
dev->d_nreaders++;
sched_lock();
sem_post(&dev->d_bfsem);
ret = sem_wait(&dev->d_rdsem);
sched_unlock();
fifo_semtake(&dev->d_bfsem);
dev->d_nreaders--;
if (ret != 0)
{
return ERROR;
}
} }
} }
/* Then return whatever is available in the FIFO (which is at least one byte) */
nread = 0;
while (nread < len && dev->d_wrndx != dev->d_rdndx)
{
*buffer++ = dev->d_buffer[dev->d_rdndx];
if (++dev->d_rdndx >= CONFIG_DEV_FIFO_SIZE)
{
dev->d_rdndx = 0;
}
nread++;
}
/* Notify any waiting writers that bytes have been removed from the buffer */
if (dev->d_nwriters > 0)
{
dev->d_nwriters--;
sem_post(&dev->d_wrsem);
}
sem_post(&dev->d_bfsem);
return nread;
} }
/**************************************************************************** /****************************************************************************
@@ -405,13 +335,13 @@ static ssize_t fifo_write(FAR struct file *filep, FAR const char *buffer, size_t
{ {
struct inode *inode = filep->f_inode; struct inode *inode = filep->f_inode;
struct fifo_dev_s *dev = inode->i_private; struct fifo_dev_s *dev = inode->i_private;
const char *src;
ssize_t nwritten = 0; ssize_t nwritten = 0;
ssize_t ntowrite = len; ssize_t last;
int nxtwrndx;
/* Some sanity checking */ /* Some sanity checking */
#if CONFIG_DEBUG #if CONFIG_DEBUG
if (dev) if (!dev)
{ {
return -ENODEV; return -ENODEV;
} }
@@ -426,112 +356,70 @@ static ssize_t fifo_write(FAR struct file *filep, FAR const char *buffer, size_t
/* Loop until all of the bytes have been written */ /* Loop until all of the bytes have been written */
src = buffer; last = 0;
for (;;) for (;;)
{ {
ssize_t nbytes; /* Calculate the write index AFTER the next byte is written */
/* Is there space available at the end of the buffer? When the write nxtwrndx = dev->d_wrndx + 1;
* index is greater than the read index, then all of the data from the if (nxtwrndx >= CONFIG_DEV_FIFO_SIZE)
* write index to the end of the buffer is available for writing.
*/
if (dev->d_wrndx >= dev->d_rdndx)
{ {
/* How many bytes are available at the end of the circular buffer */ nxtwrndx = 0;
nbytes = CONFIG_DEV_FIFO_SIZE - dev->d_wrndx;
if (nbytes > 0)
{
/* Write bytes to the end of the buffer. Is there more space than we
* need?
*/
if (nbytes > ntowrite)
{
nbytes = ntowrite;
}
/* Copy the correct number of bytes */
memcpy(&dev->d_buffer[dev->d_wrndx], &src[nwritten], nbytes);
/* Then update all indices and counts */
nwritten += nbytes;
ntowrite -= nbytes;
dev->d_wrndx += nbytes;
if (dev->d_wrndx >= CONFIG_DEV_FIFO_SIZE)
{
dev->d_wrndx = 0;
}
}
}
/* Do we still need to write more data? */
if (ntowrite > 0)
{
/* Yes... How many bytes are available at the end of the circular buffer */
nbytes = dev->d_rdndx - dev->d_wrndx - 1;
if (nbytes > 0)
{
/* Write bytes to the beginning of the buffer. Is there more space than we
* need?
*/
if (nbytes > ntowrite)
{
nbytes = ntowrite;
}
/* Copy the correct number of bytes */
memcpy(&dev->d_buffer[dev->d_wrndx], &src[nwritten], nbytes);
/* Then update all indices and counts */
nwritten += nbytes;
ntowrite -= nbytes;
dev->d_wrndx += nbytes;
}
} }
/* Was anything written? */ /* Would the next write overflow the circular buffer? */
if (nwritten > 0) if (nxtwrndx != dev->d_rdndx)
{ {
/* Yes.. Notify the waiting reades that more data is available */ /* No... copy the byte */
if (dev->d_nreaders > 0) dev->d_buffer[dev->d_wrndx] = *buffer++;
{ dev->d_wrndx = nxtwrndx;
sem_post(&dev->d_rdsem);
}
}
/* Was everything written? */ /* Is the write complete? */
if (ntowrite <= 0 ) if (++nwritten >= len)
{ {
/* Return the number of bytes written */ /* Yes.. Notify the waiting readers that more data is available */
sem_post(&dev->d_bfsem); if (dev->d_nreaders > 0)
return len; {
} dev->d_nreaders--;
sem_post(&dev->d_rdsem);
}
/* There is more to be writtend.. wait for data to be removed from the FIFO */ /* Return the number of bytes written */
dev->d_nwriters++; sem_post(&dev->d_bfsem);
sched_lock(); return len;
sem_post(&dev->d_bfsem); }
fifo_semtake(&dev->d_wrsem); }
sched_unlock(); else
fifo_semtake(&dev->d_bfsem); {
dev->d_nwriters--; /* There is not enough room for the next byte. Was anything written in this pass? */
src = &src[nwritten]; if (last < nwritten)
nwritten = 0; {
/* Yes.. Notify the waiting readers that more data is available */
if (dev->d_nreaders > 0)
{
dev->d_nreaders--;
sem_post(&dev->d_rdsem);
}
}
/* There is more to be written.. wait for data to be removed from the FIFO */
#warning "Support for O_NONBLOCK needed"
dev->d_nwriters++;
sched_lock();
sem_post(&dev->d_bfsem);
fifo_semtake(&dev->d_wrsem);
sched_unlock();
fifo_semtake(&dev->d_bfsem);
last = nwritten;
}
} }
} }
@@ -551,8 +439,6 @@ static ssize_t fifo_write(FAR struct file *filep, FAR const char *buffer, size_t
* reading or writing, in the same way as an ordinary file. NuttX FIFOs need * reading or writing, in the same way as an ordinary file. NuttX FIFOs need
* not be open at both ends before input or output operations on it. * not be open at both ends before input or output operations on it.
* *
* In NuttX pipes are built on top of FIFOs
*
* Inputs: * Inputs:
* pathname - The full path to the FIFO instance to attach to or to create * pathname - The full path to the FIFO instance to attach to or to create
* (if not already created). * (if not already created).
@@ -567,3 +453,4 @@ int mkfifo(FAR const char *pathname, mode_t mode)
{ {
return register_driver(pathname, &fifo_fops, mode, NULL); return register_driver(pathname, &fifo_fops, mode, NULL);
} }
#endif
+1
View File
@@ -143,6 +143,7 @@ EXTERN int rmdir(FAR const char *pathname);
/* Other */ /* Other */
EXTERN int getopt(int argc, FAR char *const argv[], FAR const char *optstring); EXTERN int getopt(int argc, FAR char *const argv[], FAR const char *optstring);
EXTERN int pipe(int filedes[2]);
#undef EXTERN #undef EXTERN
#if defined(__cplusplus) #if defined(__cplusplus)