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 pipe_dev_s *dev = inode->i_private;
|
||||
ssize_t nwritten = 0;
|
||||
ssize_t last;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(dev);
|
||||
|
@ -545,32 +546,97 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* REVISIT: "If all file descriptors referring to the read end of a
|
||||
* 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."
|
||||
*/
|
||||
/* Loop until all of the bytes have been written */
|
||||
|
||||
if (dev->d_nreaders <= 0 && PIPE_IS_POLICY_0(dev->d_flags))
|
||||
last = 0;
|
||||
for (; ; )
|
||||
{
|
||||
nxrmutex_unlock(&dev->d_bflock);
|
||||
return -EPIPE;
|
||||
}
|
||||
/* REVISIT: "If all file descriptors referring to the read end of a
|
||||
* 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? */
|
||||
|
||||
while (circbuf_is_full(&dev->d_buffer))
|
||||
{
|
||||
if (filep->f_oflags & O_NONBLOCK)
|
||||
if (dev->d_nreaders <= 0 && PIPE_IS_POLICY_0(dev->d_flags))
|
||||
{
|
||||
/* If O_NONBLOCK was set, then return EGAIN. */
|
||||
|
||||
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
|
||||
{
|
||||
/* 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);
|
||||
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.
|
||||
*/
|
||||
|
||||
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