pollnotify: we should send poll events before semaphore incrementes.

There is a good case on sim platform:
When we input some cmd and click enter key to start application in terminal,
this context will change to application from IDLE loop. Althrough entey key '\r'
has been received to recv buffer and complete post semaphore of reader, but
pollnotify may not be called because context change. So when application run
poll function, because no events happend and poll enter wait, context will
again change to IDLE loop, this pollnotify of IDLE loop will run to send poll
events, poll function of applicaton will wake up. It's wrong!

Change-Id: I812a889f2e90781a9c3cb4b0251cccc4d32bebd1
Signed-off-by: dongjiuzhu <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu
2020-09-26 20:25:03 +08:00
committed by Alan Carvalho de Assis
parent 13e10504c9
commit d452a05910
17 changed files with 229 additions and 221 deletions
+13 -13
View File
@@ -254,19 +254,6 @@ static void sam_tsd_notify(struct sam_tsd_s *priv)
{
int i;
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the
* touchscreen is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for touchscreen data to become
* available, then wake them up now. NOTE: we wake up all waiting threads
* because we do not know that they are going to do. If they all try to
@@ -283,6 +270,19 @@ static void sam_tsd_notify(struct sam_tsd_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the
* touchscreen is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
+17 -15
View File
@@ -181,20 +181,6 @@ static void up_notify(FAR struct up_dev_s *priv)
{
int i;
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
iinfo("contact=%d nwaiters=%d\n", priv->sample.contact, priv->nwaiters);
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because
* the touchscreen is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for touchscreen data to become
* available, then wake them up now. NOTE: we wake up all waiting threads
* because we do not know what they are going to do. If they all try to
@@ -211,6 +197,20 @@ static void up_notify(FAR struct up_dev_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
iinfo("contact=%d nwaiters=%d\n", priv->sample.contact, priv->nwaiters);
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because
* the touchscreen is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
@@ -239,7 +239,9 @@ static int up_sample(FAR struct up_dev_s *priv,
if (sample->contact == CONTACT_UP)
{
/* Next.. no contract. Increment the ID so that next contact ID will be unique */
/* Next.. no contract. Increment the ID so that next contact ID
* will be unique
*/
priv->sample.contact = CONTACT_NONE;
priv->id++;
@@ -605,19 +605,6 @@ static void tc_notify(FAR struct tc_dev_s *priv)
}
#endif
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the
* touchscreen is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for touchscreen data to become
* available, then wake them up now. NOTE: we wake up all waiting threads
* because we do not know that they are going to do. If they all try to
@@ -634,6 +621,19 @@ static void tc_notify(FAR struct tc_dev_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the
* touchscreen is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
@@ -491,19 +491,6 @@ static void tc_notify(FAR struct tc_dev_s *priv)
{
int i;
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the
* touchscreen is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for touchscreen data to become
* available, then wake them up now. NOTE: we wake up all waiting threads
* because we do not know that they are going to do.
@@ -521,6 +508,19 @@ static void tc_notify(FAR struct tc_dev_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the
* touchscreen is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
+6 -6
View File
@@ -487,6 +487,12 @@ static void adc_notify(FAR struct adc_dev_s *dev)
{
FAR struct adc_fifo_s *fifo = &dev->ad_recv;
/* If there are threads waiting on poll() for data to become available,
* then wake them up now.
*/
adc_pollnotify(dev, POLLIN);
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
@@ -495,12 +501,6 @@ static void adc_notify(FAR struct adc_dev_s *dev)
{
nxsem_post(&fifo->af_sem);
}
/* If there are threads waiting on poll() for data to become available,
* then wake them up now.
*/
adc_pollnotify(dev, POLLIN);
}
/****************************************************************************
+12 -12
View File
@@ -1326,6 +1326,12 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
fifo->rx_tail = nexttail;
/* Notify all poll/select waiters that they can read from the
* cd_recv buffer
*/
can_pollnotify(dev, POLLIN);
sval = 0;
if (nxsem_get_value(&fifo->rx_sem, &sval) < 0)
{
@@ -1349,12 +1355,6 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
}
errcode = OK;
/* Notify all poll/select waiters that they can read from the
* cd_recv buffer
*/
can_pollnotify(dev, POLLIN);
}
#ifdef CONFIG_CAN_ERRORS
else
@@ -1471,6 +1471,12 @@ int can_txdone(FAR struct can_dev_s *dev)
can_xmit(dev);
/* Notify all poll/select waiters that they can write to the cd_xmit
* buffer
*/
can_pollnotify(dev, POLLOUT);
/* Are there any threads waiting for space in the TX FIFO? */
if (dev->cd_ntxwaiters > 0)
@@ -1485,12 +1491,6 @@ int can_txdone(FAR struct can_dev_s *dev)
}
}
/* Notify all poll/select waiters that they can write to the cd_xmit
* buffer
*/
can_pollnotify(dev, POLLOUT);
return ret;
}
+13 -13
View File
@@ -294,19 +294,6 @@ static void ads7843e_notify(FAR struct ads7843e_dev_s *priv)
{
int i;
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the ADS7843E
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for ADS7843E data to become
* available, then wake them up now. NOTE: we wake up all waiting threads
* because we do not know that they are going to do. If they all try to
@@ -323,6 +310,19 @@ static void ads7843e_notify(FAR struct ads7843e_dev_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the ADS7843E
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
+13 -13
View File
@@ -224,19 +224,6 @@ static void ft5x06_notify(FAR struct ft5x06_dev_s *priv)
{
int i;
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the FT5x06
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for FT5x06 data to become
* available, then wake them up now. NOTE: we wake up all waiting threads
* because we do not know that they are going to do. If they all try to
@@ -253,6 +240,19 @@ static void ft5x06_notify(FAR struct ft5x06_dev_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the FT5x06
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
+13 -13
View File
@@ -253,19 +253,6 @@ static void max11802_notify(FAR struct max11802_dev_s *priv)
{
int i;
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the sample
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for MAX11802 data to become
* available, then wake them up now. NOTE: we wake up all waiting
* threads because we do not know that they are going to do. If they
@@ -282,6 +269,19 @@ static void max11802_notify(FAR struct max11802_dev_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the sample
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
+13 -13
View File
@@ -583,19 +583,6 @@ static void mxt_notify(FAR struct mxt_dev_s *priv)
{
int i;
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the maXTouch
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for maXTouch data to become
* available, then wake them up now. NOTE: we wake up all waiting threads
* because we do not know that they are going to do. If they all try to
@@ -612,6 +599,19 @@ static void mxt_notify(FAR struct mxt_dev_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the maXTouch
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
+13 -13
View File
@@ -158,19 +158,6 @@ static void stmpe811_notify(FAR struct stmpe811_dev_s *priv)
{
int i;
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the STMPE811
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for STMPE811 data to become
* available, then wake them up now. NOTE: we wake up all waiting threads
* because we do not know that they are going to do. If they all try to
@@ -187,6 +174,19 @@ static void stmpe811_notify(FAR struct stmpe811_dev_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the STMPE811
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
+13 -13
View File
@@ -236,19 +236,6 @@ static void tsc2007_notify(FAR struct tsc2007_dev_s *priv)
{
int i;
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the TSC2007
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
/* If there are threads waiting on poll() for TSC2007 data to become
* available, then wake them up now. NOTE: we wake up all waiting
* threads because we do not know that they are going to do. If they
@@ -265,6 +252,19 @@ static void tsc2007_notify(FAR struct tsc2007_dev_s *priv)
nxsem_post(fds->sem);
}
}
/* If there are threads waiting for read data, then signal one of them
* that the read data is available.
*/
if (priv->nwaiters > 0)
{
/* After posting this semaphore, we need to exit because the TSC2007
* is no longer available.
*/
nxsem_post(&priv->waitsem);
}
}
/****************************************************************************
+20 -20
View File
@@ -321,14 +321,14 @@ int pipecommon_close(FAR struct file *filep)
if (--dev->d_nwriters <= 0)
{
/* Inform poll readers that other end closed. */
pipecommon_pollnotify(dev, POLLHUP);
while (nxsem_get_value(&dev->d_rdsem, &sval) == 0 && sval < 0)
{
nxsem_post(&dev->d_rdsem);
}
/* Inform poll readers that other end closed. */
pipecommon_pollnotify(dev, POLLHUP);
}
}
@@ -474,6 +474,10 @@ 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 */
pipecommon_pollnotify(dev, POLLOUT);
/* Notify all waiting writers that bytes have been removed from the
* buffer.
*/
@@ -483,10 +487,6 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
nxsem_post(&dev->d_wrsem);
}
/* Notify all poll/select waiters that they can write to the FIFO */
pipecommon_pollnotify(dev, POLLOUT);
nxsem_post(&dev->d_bfsem);
pipe_dumpbuffer("From PIPE:", start, nread);
return nread;
@@ -582,6 +582,12 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
nwritten++;
if ((size_t)nwritten >= len)
{
/* Notify all poll/select waiters that they can read from the
* FIFO.
*/
pipecommon_pollnotify(dev, POLLIN);
/* Yes.. Notify all of the waiting readers that more data is
* available.
*/
@@ -591,12 +597,6 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
nxsem_post(&dev->d_rdsem);
}
/* Notify all poll/select waiters that they can read from the
* FIFO.
*/
pipecommon_pollnotify(dev, POLLIN);
/* Return the number of bytes written */
nxsem_post(&dev->d_bfsem);
@@ -611,6 +611,12 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
if (last < nwritten)
{
/* Notify all poll/select waiters that they can read from the
* FIFO.
*/
pipecommon_pollnotify(dev, POLLIN);
/* Yes.. Notify all of the waiting readers that more data is
* available.
*/
@@ -619,12 +625,6 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
{
nxsem_post(&dev->d_rdsem);
}
/* Notify all poll/select waiters that they can read from the
* FIFO.
*/
pipecommon_pollnotify(dev, POLLIN);
}
last = nwritten;
+12 -12
View File
@@ -1644,6 +1644,10 @@ int uart_register(FAR const char *path, FAR uart_dev_t *dev)
void uart_datareceived(FAR uart_dev_t *dev)
{
/* Notify all poll/select waiters that they can read from the recv buffer */
uart_pollnotify(dev, POLLIN);
/* Is there a thread waiting for read data? */
if (dev->recvwaiting)
@@ -1654,10 +1658,6 @@ void uart_datareceived(FAR uart_dev_t *dev)
nxsem_post(&dev->recvsem);
}
/* Notify all poll/select waiters that they can read from the recv buffer */
uart_pollnotify(dev, POLLIN);
#if defined(CONFIG_PM) && defined(CONFIG_SERIAL_CONSOLE)
/* Call pm_activity when characters are received on the console device */
@@ -1682,6 +1682,10 @@ void uart_datareceived(FAR uart_dev_t *dev)
void uart_datasent(FAR uart_dev_t *dev)
{
/* Notify all poll/select waiters that they can write to xmit buffer */
uart_pollnotify(dev, POLLOUT);
/* Is there a thread waiting for space in xmit.buffer? */
if (dev->xmitwaiting)
@@ -1691,10 +1695,6 @@ void uart_datasent(FAR uart_dev_t *dev)
dev->xmitwaiting = false;
nxsem_post(&dev->xmitsem);
}
/* Notify all poll/select waiters that they can write to xmit buffer */
uart_pollnotify(dev, POLLOUT);
}
/************************************************************************************
@@ -1730,6 +1730,10 @@ void uart_connected(FAR uart_dev_t *dev, bool connected)
dev->disconnected = !connected;
if (!connected)
{
/* Notify all poll/select waiters that a hangup occurred */
uart_pollnotify(dev, (POLLERR | POLLHUP));
/* Yes.. wake up all waiting threads. Each thread should detect the
* disconnection and return the ENOTCONN error.
*/
@@ -1753,10 +1757,6 @@ void uart_connected(FAR uart_dev_t *dev, bool connected)
dev->recvwaiting = false;
nxsem_post(&dev->recvsem);
}
/* Notify all poll/select waiters that a hangup occurred */
uart_pollnotify(dev, (POLLERR | POLLHUP));
}
leave_critical_section(flags);
+10 -10
View File
@@ -1284,16 +1284,6 @@ static int usbhost_kbdpoll(int argc, char *argv[])
newstate = (priv->headndx == priv->tailndx);
if (!newstate)
{
/* Yes.. Is there a thread waiting for keyboard data now? */
if (priv->waiting)
{
/* Yes.. wake it up */
usbhost_givesem(&priv->waitsem);
priv->waiting = false;
}
/* Did we just transition from no data available to data
* available? If so, wake up any threads waiting for the
* POLLIN event.
@@ -1303,6 +1293,16 @@ static int usbhost_kbdpoll(int argc, char *argv[])
{
usbhost_pollnotify(priv);
}
/* Yes.. Is there a thread waiting for keyboard data now? */
if (priv->waiting)
{
/* Yes.. wake it up */
usbhost_givesem(&priv->waitsem);
priv->waiting = false;
}
}
empty = newstate;
+12 -12
View File
@@ -381,6 +381,12 @@ static ssize_t eventfd_do_read(FAR struct file *filep, FAR char *buffer,
dev->counter = 0;
}
#ifdef CONFIG_EVENT_FD_POLL
/* Notify all poll/select waiters */
eventfd_pollnotify(dev, POLLOUT);
#endif
/* Notify all waiting writers that counter have been decremented */
eventfd_waiter_sem_t *cur_sem = dev->wrsems;
@@ -392,12 +398,6 @@ static ssize_t eventfd_do_read(FAR struct file *filep, FAR char *buffer,
dev->wrsems = NULL;
#ifdef CONFIG_EVENT_FD_POLL
/* Notify all poll/select waiters */
eventfd_pollnotify(dev, POLLOUT);
#endif
nxsem_post(&dev->exclsem);
return sizeof(eventfd_t);
}
@@ -458,6 +458,12 @@ static ssize_t eventfd_do_write(FAR struct file *filep,
dev->counter = new_counter;
#ifdef CONFIG_EVENT_FD_POLL
/* Notify all poll/select waiters */
eventfd_pollnotify(dev, POLLIN);
#endif
/* Notify all of the waiting readers */
eventfd_waiter_sem_t *cur_sem = dev->rdsems;
@@ -469,12 +475,6 @@ static ssize_t eventfd_do_write(FAR struct file *filep,
dev->rdsems = NULL;
#ifdef CONFIG_EVENT_FD_POLL
/* Notify all poll/select waiters */
eventfd_pollnotify(dev, POLLIN);
#endif
nxsem_post(&dev->exclsem);
return sizeof(eventfd_t);
}
+20 -14
View File
@@ -136,8 +136,8 @@ ssize_t nxterm_read(FAR struct file *filep, FAR char *buffer, size_t len)
break;
}
/* If the driver was opened with O_NONBLOCK option, then don't wait.
* Just return EGAIN.
/* If the driver was opened with O_NONBLOCK option, then
* don't wait. Just return EGAIN.
*/
if (filep->f_oflags & O_NONBLOCK)
@@ -147,8 +147,9 @@ ssize_t nxterm_read(FAR struct file *filep, FAR char *buffer, size_t len)
}
/* Otherwise, wait for something to be written to the circular
* buffer. Increment the number of waiters so that the nxterm_write()
* will not that it needs to post the semaphore to wake us up.
* buffer. Increment the number of waiters so that the
* nxterm_write() will not that it needs to post the semaphore
* to wake us up.
*/
sched_lock();
@@ -162,8 +163,8 @@ ssize_t nxterm_read(FAR struct file *filep, FAR char *buffer, size_t len)
ret = nxsem_wait(&priv->waitsem);
/* Pre-emption will be disabled when we return. So the decrementing
* nwaiters here is safe.
/* Pre-emption will be disabled when we return. So the
* decrementing nwaiters here is safe.
*/
priv->nwaiters--;
@@ -321,7 +322,6 @@ int nxterm_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup)
{
nxterm_pollnotify(priv, eventset);
}
}
else if (fds->priv)
{
@@ -429,7 +429,9 @@ void nxterm_kbdin(NXTERM handle, FAR const uint8_t *buffer, uint8_t buflen)
if (nexthead == priv->tail)
{
/* Yes... Return an indication that nothing was saved in the buffer. */
/* Yes... Return an indication that nothing was saved in
* the buffer.
*/
gerr("ERROR: Keyboard data overrun\n");
break;
@@ -450,16 +452,20 @@ void nxterm_kbdin(NXTERM handle, FAR const uint8_t *buffer, uint8_t buflen)
/* Are there threads waiting for read data? */
sched_lock();
for (i = 0; i < priv->nwaiters; i++)
{
/* Yes.. Notify all of the waiting readers that more data is available */
nxsem_post(&priv->waitsem);
}
/* Notify all poll/select waiters that they can read from the FIFO */
nxterm_pollnotify(priv, POLLIN);
for (i = 0; i < priv->nwaiters; i++)
{
/* Yes.. Notify all of the waiting readers that more data is
* available
*/
nxsem_post(&priv->waitsem);
}
sched_unlock();
}