fs/drivers: Avoid causing a busy loop in the program due to context switching induced by sem_post.

examples:
There are two threads involved: thread A with a priority of 100 and
thread B with a priority of 101. Here's how they interact:

When thread A releases a semaphore, thread B is scheduled to execute
some code and may reacquire the semaphore. If no other tasks are ready,
thread A will be scheduled to run.
This continuous process can lead to a busy loop.

Thread A:                                                   Thread B:

while (nxsem_get_value(&priv->wait, &semcount) >= 0 &&  <---
       semcount <= 0)                                      |  2)context switch
  {                                  1)contex switch       |
    nxsem_post(&priv->wait);         ------------->     run some code and nxsem_wait again
  }

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2025-02-17 22:04:26 +08:00 committed by Alin Jerpelea
parent 7a96bee46f
commit cfd359141f
8 changed files with 40 additions and 17 deletions

View file

@ -506,11 +506,14 @@ static int i2c_slave_callback(FAR void *arg, i2c_slave_complete_t status,
priv->read_index = 0; priv->read_index = 0;
priv->read_length = length; priv->read_length = length;
while (nxsem_get_value(&priv->wait, &semcount) >= 0 && semcount <= 0) if (nxsem_get_value(&priv->wait, &semcount) >= 0)
{
while (semcount++ <= 0)
{ {
nxsem_post(&priv->wait); nxsem_post(&priv->wait);
} }
} }
}
else else
{ {
events = POLLOUT; events = POLLOUT;

View file

@ -92,10 +92,13 @@ void ipcc_rxfree_notify(FAR struct ipcc_driver_s *priv)
/* Notify all blocked readers that data is available to read */ /* Notify all blocked readers that data is available to read */
while (nxsem_get_value(&priv->rxsem, &semval) >= 0 && semval <= 0) if (nxsem_get_value(&priv->rxsem, &semval) >= 0)
{
while (semval++ <= 0)
{ {
nxsem_post(&priv->rxsem); nxsem_post(&priv->rxsem);
} }
}
} }
/**************************************************************************** /****************************************************************************

View file

@ -92,10 +92,13 @@ void ipcc_txfree_notify(FAR struct ipcc_driver_s *priv)
/* Notify all blocked writers that data is available to write */ /* Notify all blocked writers that data is available to write */
while (nxsem_get_value(&priv->txsem, &semval) >= 0 && semval <= 0) if (nxsem_get_value(&priv->txsem, &semval) >= 0)
{
while (semval++ <= 0)
{ {
nxsem_post(&priv->txsem); nxsem_post(&priv->txsem);
} }
}
} }
/**************************************************************************** /****************************************************************************

View file

@ -537,10 +537,13 @@ static void goldfish_pipe_wake(FAR struct goldfish_pipe_s *pipe,
FAR sem_t *sem = is_write ? &pipe->wait_for_write : &pipe->wait_for_read; FAR sem_t *sem = is_write ? &pipe->wait_for_write : &pipe->wait_for_read;
int sval; int sval;
while (nxsem_get_value(sem, &sval) >= 0 && sval <= 0) if (nxsem_get_value(sem, &sval) >= 0)
{
while (sval++ <= 0)
{ {
nxsem_post(sem); nxsem_post(sem);
} }
}
} }
static int goldfish_pipe_interrupt(int irq, FAR void *context, FAR void *arg) static int goldfish_pipe_interrupt(int irq, FAR void *context, FAR void *arg)

View file

@ -76,10 +76,13 @@ static void pipecommon_wakeup(FAR sem_t *sem)
{ {
int sval; int sval;
while (nxsem_get_value(sem, &sval) == OK && sval <= 0) if (nxsem_get_value(sem, &sval) >= 0)
{
while (sval++ <= 0)
{ {
nxsem_post(sem); nxsem_post(sem);
} }
}
} }
/**************************************************************************** /****************************************************************************

View file

@ -742,10 +742,13 @@ static void spi_slave_notify(FAR struct spi_slave_dev_s *dev,
poll_notify(&priv->fds, 1, POLLERR); poll_notify(&priv->fds, 1, POLLERR);
} }
while (nxsem_get_value(&priv->wait, &semcnt) == 0 && semcnt <= 0) if (nxsem_get_value(&priv->wait, &semcnt) >= 0)
{
while (semcnt++ <= 0)
{ {
nxsem_post(&priv->wait); nxsem_post(&priv->wait);
} }
}
} }
/**************************************************************************** /****************************************************************************

View file

@ -561,12 +561,14 @@ static void bt_slip_unack_handle(FAR struct sliphci_s *priv)
{ {
int semcount; int semcount;
while (nxsem_get_value(&priv->sem, &semcount) >= 0 && if (nxsem_get_value(&priv->sem, &semcount) >= 0)
semcount <= 0) {
while (semcount++ <= 0)
{ {
nxsem_post(&priv->sem); nxsem_post(&priv->sem);
} }
} }
}
to_remove--; to_remove--;
} }

View file

@ -289,10 +289,13 @@ static void inotify_queue_event(FAR struct inotify_device_s *dev, int wd,
poll_notify(dev->fds, CONFIG_FS_NOTIFY_FD_POLLWAITERS, POLLIN); poll_notify(dev->fds, CONFIG_FS_NOTIFY_FD_POLLWAITERS, POLLIN);
while (nxsem_get_value(&dev->sem, &semcnt) == 0 && semcnt <= 1) if (nxsem_get_value(&dev->sem, &semcnt) >= 0)
{
while (semcnt++ <= 1)
{ {
nxsem_post(&dev->sem); nxsem_post(&dev->sem);
} }
}
} }
/**************************************************************************** /****************************************************************************