diff --git a/drivers/pipes/pipe_common.c b/drivers/pipes/pipe_common.c index 1ab3ea427c..d68896dd1f 100644 --- a/drivers/pipes/pipe_common.c +++ b/drivers/pipes/pipe_common.c @@ -60,6 +60,26 @@ # define pipe_dumpbuffer(m,a,n) #endif +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pipecommon_bufferused + ****************************************************************************/ + +static pipe_ndx_t pipecommon_bufferused(FAR struct pipe_dev_s *dev) +{ + if (dev->d_wrndx >= dev->d_rdndx) + { + return dev->d_wrndx - dev->d_rdndx; + } + else + { + return dev->d_bufsize + dev->d_wrndx - dev->d_rdndx; + } +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -417,9 +437,14 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len) nread++; } - /* Notify all poll/select waiters that they can write to the FIFO */ + /* Notify all poll/select waiters that they can write to the + * FIFO when buffer can accept more than d_polloutthrd bytes. + */ - poll_notify(dev->d_fds, CONFIG_DEV_PIPE_NPOLLWAITERS, POLLOUT); + if (pipecommon_bufferused(dev) < (dev->d_bufsize - dev->d_polloutthrd)) + { + poll_notify(dev->d_fds, CONFIG_DEV_PIPE_NPOLLWAITERS, POLLOUT); + } /* Notify all waiting writers that bytes have been removed from the * buffer. @@ -527,10 +552,14 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, if ((size_t)nwritten >= len) { /* Notify all poll/select waiters that they can read from the - * FIFO. + * FIFO when buffer used exceeds poll threshold. */ - poll_notify(dev->d_fds, CONFIG_DEV_PIPE_NPOLLWAITERS, POLLIN); + if (pipecommon_bufferused(dev) > 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. @@ -661,28 +690,23 @@ int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds, * First, determine how many bytes are in the buffer */ - if (dev->d_wrndx >= dev->d_rdndx) - { - nbytes = dev->d_wrndx - dev->d_rdndx; - } - else - { - nbytes = dev->d_bufsize + dev->d_wrndx - dev->d_rdndx; - } + nbytes = pipecommon_bufferused(dev); - /* Notify the POLLOUT event if the pipe is not full, but only if + /* Notify the POLLOUT event if the pipe buffer can accept + * more than d_polloutthrd bytes, but only if * there is readers. */ eventset = 0; - if ((filep->f_oflags & O_WROK) && (nbytes < (dev->d_bufsize - 1))) + if ((filep->f_oflags & O_WROK) && + nbytes < (dev->d_bufsize - dev->d_polloutthrd)) { eventset |= POLLOUT; } - /* Notify the POLLIN event if the pipe is not empty */ + /* Notify the POLLIN event if buffer used exceeds poll threshold */ - if ((filep->f_oflags & O_RDOK) && (nbytes > 0)) + if ((filep->f_oflags & O_RDOK) && (nbytes > dev->d_pollinthrd)) { eventset |= POLLIN; } @@ -772,6 +796,34 @@ int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } break; + case PIPEIOC_POLLINTHRD: + { + pipe_ndx_t threshold = (pipe_ndx_t)arg; + if (threshold >= dev->d_bufsize) + { + ret = -EINVAL; + break; + } + + dev->d_pollinthrd = threshold; + ret = OK; + } + break; + + case PIPEIOC_POLLOUTTHRD: + { + pipe_ndx_t threshold = (pipe_ndx_t)arg; + if (threshold >= dev->d_bufsize) + { + ret = -EINVAL; + break; + } + + dev->d_polloutthrd = threshold; + ret = OK; + } + break; + case FIONWRITE: /* Number of bytes waiting in send queue */ case FIONREAD: /* Number of bytes available for reading */ { diff --git a/drivers/pipes/pipe_common.h b/drivers/pipes/pipe_common.h index ff579e81f6..eec1bac119 100644 --- a/drivers/pipes/pipe_common.h +++ b/drivers/pipes/pipe_common.h @@ -120,6 +120,8 @@ struct pipe_dev_s pipe_ndx_t d_wrndx; /* Index in d_buffer to save next byte written */ pipe_ndx_t d_rdndx; /* Index in d_buffer to return the next byte read */ pipe_ndx_t d_bufsize; /* allocated size of d_buffer in bytes */ + pipe_ndx_t d_pollinthrd; /* Buffer threshold for POLLIN to occur */ + pipe_ndx_t d_polloutthrd; /* Buffer threshold for POLLOUT to occur */ uint8_t d_nwriters; /* Number of reference counts for write access */ uint8_t d_nreaders; /* Number of reference counts for read access */ uint8_t d_flags; /* See PIPE_FLAG_* definitions */ diff --git a/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h index a231e85f82..12e52900ac 100644 --- a/include/nuttx/fs/ioctl.h +++ b/include/nuttx/fs/ioctl.h @@ -405,15 +405,33 @@ /* FIFOs and pipe driver ioctl definitions **********************************/ -#define _PIPEIOCVALID(c) (_IOC_TYPE(c)==_PIPEBASE) -#define _PIPEIOC(nr) _IOC(_PIPEBASE,nr) +#define _PIPEIOCVALID(c) (_IOC_TYPE(c)==_PIPEBASE) +#define _PIPEIOC(nr) _IOC(_PIPEBASE,nr) -#define PIPEIOC_POLICY _PIPEIOC(0x0001) /* Set buffer policy - * IN: unsigned long integer - * 0=free on last close - * (default) - * 1=fre when empty - * OUT: None */ +#define PIPEIOC_POLICY _PIPEIOC(0x0001) /* Set buffer policy + * IN: unsigned long integer + * 0=free on last close + * (default) + * 1=fre when empty + * OUT: None */ + +#define PIPEIOC_POLLINTHRD _PIPEIOC(0x0002) /* Set pipe POLLIN + * notifty buffer threshold. + * IN: unsigned long integer. + * POLLIN only occurs when + * buffer contains more + * bytes than the + * threshold. + * OUT: None */ + +#define PIPEIOC_POLLOUTTHRD _PIPEIOC(0x0003) /* Set pipe POLLOUT + * notifty buffer threshold. + * IN: unsigned long integer. + * POLLOUT only occurs + * when buffer can accept + * more bytes than + * threshold. + * OUT: None */ /* RTC driver ioctl definitions *********************************************/