9
0
Fork 0

O_RDONLY open on FIFO blocks until writer opens

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@781 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2008-07-26 14:24:17 +00:00
parent 08db4b1055
commit 953b1c0f7b
5 changed files with 36 additions and 3 deletions

View File

@ -376,4 +376,5 @@
* Correct bug in recursive mutex logic
* Add mkfifo()
* Add pipe() and test for both pipes and fifos
* Attempts to open a FIFO will now block until there is at least one writer

View File

@ -1025,6 +1025,7 @@ nuttx-0.3.12 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* Correct bug in recursive mutex logic
* Add mkfifo()
* Add pipe() and test for both pipes and fifos
* Attempts to open a FIFO will now block until there is at least one writer
pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>

View File

@ -96,8 +96,12 @@ static struct file_operations fifo_fops =
* Once the FIFO has been created by mkfifo(), any thread can open it for
* reading or writing, in the same way as an ordinary file. However, it must
* have been opened from both reading and writing before input or output
* can be performed. Unlike other mkfifo() implementations, this one will
* NOT block when the FIFO is opened on only one end.
* can be performed. This FIFO implementation will block all attempts to
* open a FIFO read-only until at least one thread has opened the FIFO for
* writing.
*
* If all threads that write to the FIFO have closed, subsequent calls to
* read() on the FIFO will return 0 (end-of-file).
*
* Inputs:
* pathname - The full path to the FIFO instance to attach to or to create

View File

@ -139,6 +139,7 @@ int pipecommon_open(FAR struct file *filep)
{
struct inode *inode = filep->f_inode;
struct pipe_dev_s *dev = inode->i_private;
int sval;
/* Some sanity checking */
#if CONFIG_DEBUG
@ -160,11 +161,37 @@ int pipecommon_open(FAR struct file *filep)
if ((filep->f_oflags & O_WROK) != 0)
{
dev->s.d_nwriters++;
/* If this this is the first writer, then the read semaphore indicates the
* number of readers waiting for the first writer. Wake them all up.
*/
if (dev->s.d_nwriters == 1)
{
while (sem_getvalue(&dev->s.d_rdsem, &sval) == 0 && sval < 0)
{
sem_post(&dev->s.d_rdsem);
}
}
}
/* If opened for read-only, then wait for at least one writer on the pipe */
sched_lock();
(void)sem_post(&dev->s.d_bfsem);
if ((filep->f_oflags & O_RDWR) != O_RDONLY && dev->s.d_nwriters < 1)
{
/* NOTE: d_rdsem is normally used when the read logic waits for more
* data to be written. But until the first writer has opened the
* pipe, the meaning is different: it is used prevent O_RDONLY open
* calls from returning until there is at least one writer on the pipe.
* This is required both by spec and also because it prevents
* subsequent read() calls from returning end-of-file because there is
* no writer on the pipe.
*/
pipecommon_semtake(&dev->s.d_rdsem);
}
sched_unlock();
return OK;
}
return ERROR;

View File

@ -127,7 +127,7 @@ static void *reader(pthread_addr_t pvarg)
if (nbytes > NREAD_BYTES)
{
fprintf(stderr, "reader: Too many bytes read -- aborting: %d\n", nbytes);
return (void*)3;
return (void*)4;
}
}
printf("reader: %d bytes read\n", nbytes);