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_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);
}
}
}
else
{
events = POLLOUT;

View file

@ -92,11 +92,14 @@ void ipcc_rxfree_notify(FAR struct ipcc_driver_s *priv)
/* 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);
}
}
}
/****************************************************************************
* Name: ipcc_read

View file

@ -92,11 +92,14 @@ void ipcc_txfree_notify(FAR struct ipcc_driver_s *priv)
/* 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);
}
}
}
/****************************************************************************
* Name: ipcc_write

View file

@ -537,11 +537,14 @@ 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;
int sval;
while (nxsem_get_value(sem, &sval) >= 0 && sval <= 0)
if (nxsem_get_value(sem, &sval) >= 0)
{
while (sval++ <= 0)
{
nxsem_post(sem);
}
}
}
static int goldfish_pipe_interrupt(int irq, FAR void *context, FAR void *arg)
{

View file

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

View file

@ -742,11 +742,14 @@ static void spi_slave_notify(FAR struct spi_slave_dev_s *dev,
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);
}
}
}
/****************************************************************************
* Public Functions

View file

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

View file

@ -289,11 +289,14 @@ static void inotify_queue_event(FAR struct inotify_device_s *dev, int wd,
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);
}
}
}
/****************************************************************************
* Name: inotify_remove_watch_no_event