Revert "drivers/pipes: return after short write if buffer is full"
This reverts commit d0680fd1bc
.
This commit is contained in:
parent
610efc8f1a
commit
573115734d
1 changed files with 85 additions and 44 deletions
|
@ -506,6 +506,7 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
|
||||||
FAR struct inode *inode = filep->f_inode;
|
FAR struct inode *inode = filep->f_inode;
|
||||||
FAR struct pipe_dev_s *dev = inode->i_private;
|
FAR struct pipe_dev_s *dev = inode->i_private;
|
||||||
ssize_t nwritten = 0;
|
ssize_t nwritten = 0;
|
||||||
|
ssize_t last;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(dev);
|
DEBUGASSERT(dev);
|
||||||
|
@ -545,32 +546,97 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* REVISIT: "If all file descriptors referring to the read end of a
|
/* Loop until all of the bytes have been written */
|
||||||
* pipe have been closed, then a write will cause a SIGPIPE signal to
|
|
||||||
* be generated for the calling process. If the calling process is
|
|
||||||
* ignoring this signal, then write(2) fails with the error EPIPE."
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (dev->d_nreaders <= 0 && PIPE_IS_POLICY_0(dev->d_flags))
|
last = 0;
|
||||||
|
for (; ; )
|
||||||
{
|
{
|
||||||
nxrmutex_unlock(&dev->d_bflock);
|
/* REVISIT: "If all file descriptors referring to the read end of a
|
||||||
return -EPIPE;
|
* pipe have been closed, then a write will cause a SIGPIPE signal to
|
||||||
}
|
* be generated for the calling process. If the calling process is
|
||||||
|
* ignoring this signal, then write(2) fails with the error EPIPE."
|
||||||
|
*/
|
||||||
|
|
||||||
/* Would the next write overflow the circular buffer? */
|
if (dev->d_nreaders <= 0 && PIPE_IS_POLICY_0(dev->d_flags))
|
||||||
|
|
||||||
while (circbuf_is_full(&dev->d_buffer))
|
|
||||||
{
|
|
||||||
if (filep->f_oflags & O_NONBLOCK)
|
|
||||||
{
|
{
|
||||||
/* If O_NONBLOCK was set, then return EGAIN. */
|
|
||||||
|
|
||||||
nxrmutex_unlock(&dev->d_bflock);
|
nxrmutex_unlock(&dev->d_bflock);
|
||||||
return -EAGAIN;
|
return nwritten == 0 ? -EPIPE : nwritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Would the next write overflow the circular buffer? */
|
||||||
|
|
||||||
|
if (!circbuf_is_full(&dev->d_buffer))
|
||||||
|
{
|
||||||
|
/* Loop until all of the bytes have been written */
|
||||||
|
|
||||||
|
nwritten += circbuf_write(&dev->d_buffer,
|
||||||
|
buffer + nwritten, len - nwritten);
|
||||||
|
|
||||||
|
if ((size_t)nwritten == len)
|
||||||
|
{
|
||||||
|
/* Notify all poll/select waiters that they can read from the
|
||||||
|
* FIFO when buffer used exceeds poll threshold.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (circbuf_used(&dev->d_buffer) > dev->d_pollinthrd)
|
||||||
|
{
|
||||||
|
poll_notify(dev->d_fds, CONFIG_DEV_PIPE_NPOLLWAITERS,
|
||||||
|
POLLIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Yes.. Notify all of the waiting readers that more data is
|
||||||
|
* available.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pipecommon_wakeup(&dev->d_rdsem);
|
||||||
|
|
||||||
|
/* Return the number of bytes written */
|
||||||
|
|
||||||
|
nxrmutex_unlock(&dev->d_bflock);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Wait for data to be removed from the pipe. */
|
/* There is not enough room for the next byte. Was anything
|
||||||
|
* written in this pass?
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (last < nwritten)
|
||||||
|
{
|
||||||
|
/* Notify all poll/select waiters that they can read from the
|
||||||
|
* FIFO.
|
||||||
|
*/
|
||||||
|
|
||||||
|
poll_notify(dev->d_fds, CONFIG_DEV_PIPE_NPOLLWAITERS, POLLIN);
|
||||||
|
|
||||||
|
/* Yes.. Notify all of the waiting readers that more data is
|
||||||
|
* available.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pipecommon_wakeup(&dev->d_rdsem);
|
||||||
|
}
|
||||||
|
|
||||||
|
last = nwritten;
|
||||||
|
|
||||||
|
/* If O_NONBLOCK was set, then return partial bytes written or
|
||||||
|
* EGAIN.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (filep->f_oflags & O_NONBLOCK)
|
||||||
|
{
|
||||||
|
if (nwritten == 0)
|
||||||
|
{
|
||||||
|
nwritten = -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxrmutex_unlock(&dev->d_bflock);
|
||||||
|
return nwritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There is more to be written.. wait for data to be removed from
|
||||||
|
* the pipe
|
||||||
|
*/
|
||||||
|
|
||||||
nxrmutex_unlock(&dev->d_bflock);
|
nxrmutex_unlock(&dev->d_bflock);
|
||||||
ret = nxsem_wait(&dev->d_wrsem);
|
ret = nxsem_wait(&dev->d_wrsem);
|
||||||
|
@ -580,35 +646,10 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
|
||||||
* received or if the task was canceled.
|
* received or if the task was canceled.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return (ssize_t)ret;
|
return nwritten == 0 ? (ssize_t)ret : nwritten;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write data to buffer. */
|
|
||||||
|
|
||||||
nwritten = circbuf_write(&dev->d_buffer, buffer, len);
|
|
||||||
|
|
||||||
/* Notify all poll/select waiters that they can read from the
|
|
||||||
* FIFO when buffer used exceeds poll threshold.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (circbuf_used(&dev->d_buffer) > dev->d_pollinthrd)
|
|
||||||
{
|
|
||||||
poll_notify(dev->d_fds, CONFIG_DEV_PIPE_NPOLLWAITERS,
|
|
||||||
POLLIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Yes.. Notify all of the waiting readers that more data is
|
|
||||||
* available.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pipecommon_wakeup(&dev->d_rdsem);
|
|
||||||
|
|
||||||
/* Return the number of bytes written */
|
|
||||||
|
|
||||||
nxrmutex_unlock(&dev->d_bflock);
|
|
||||||
return nwritten;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
Loading…
Reference in a new issue