From cfd359141fce953c33d613b26bcfae5c4a79c2e3 Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Mon, 17 Feb 2025 22:04:26 +0800 Subject: [PATCH] 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 --- drivers/i2c/i2c_slave_driver.c | 7 +++++-- drivers/ipcc/ipcc_read.c | 7 +++++-- drivers/ipcc/ipcc_write.c | 7 +++++-- drivers/misc/goldfish_pipe.c | 7 +++++-- drivers/pipes/pipe_common.c | 7 +++++-- drivers/spi/spi_slave_driver.c | 7 +++++-- drivers/wireless/bluetooth/bt_slip.c | 8 +++++--- fs/notify/inotify.c | 7 +++++-- 8 files changed, 40 insertions(+), 17 deletions(-) diff --git a/drivers/i2c/i2c_slave_driver.c b/drivers/i2c/i2c_slave_driver.c index dfc0ef479c..0e46ebaa5c 100644 --- a/drivers/i2c/i2c_slave_driver.c +++ b/drivers/i2c/i2c_slave_driver.c @@ -506,9 +506,12 @@ 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) { - nxsem_post(&priv->wait); + while (semcount++ <= 0) + { + nxsem_post(&priv->wait); + } } } else diff --git a/drivers/ipcc/ipcc_read.c b/drivers/ipcc/ipcc_read.c index d1d93322b0..83af2142f2 100644 --- a/drivers/ipcc/ipcc_read.c +++ b/drivers/ipcc/ipcc_read.c @@ -92,9 +92,12 @@ 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) { - nxsem_post(&priv->rxsem); + while (semval++ <= 0) + { + nxsem_post(&priv->rxsem); + } } } diff --git a/drivers/ipcc/ipcc_write.c b/drivers/ipcc/ipcc_write.c index 369edb0e96..aee5eedc51 100644 --- a/drivers/ipcc/ipcc_write.c +++ b/drivers/ipcc/ipcc_write.c @@ -92,9 +92,12 @@ 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) { - nxsem_post(&priv->txsem); + while (semval++ <= 0) + { + nxsem_post(&priv->txsem); + } } } diff --git a/drivers/misc/goldfish_pipe.c b/drivers/misc/goldfish_pipe.c index bde70a4df4..d9003e2793 100644 --- a/drivers/misc/goldfish_pipe.c +++ b/drivers/misc/goldfish_pipe.c @@ -537,9 +537,12 @@ 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) { - nxsem_post(sem); + while (sval++ <= 0) + { + nxsem_post(sem); + } } } diff --git a/drivers/pipes/pipe_common.c b/drivers/pipes/pipe_common.c index 594c1c198b..3bdcef5ef1 100644 --- a/drivers/pipes/pipe_common.c +++ b/drivers/pipes/pipe_common.c @@ -76,9 +76,12 @@ 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) { - nxsem_post(sem); + while (sval++ <= 0) + { + nxsem_post(sem); + } } } diff --git a/drivers/spi/spi_slave_driver.c b/drivers/spi/spi_slave_driver.c index 73293d697d..427a59a694 100644 --- a/drivers/spi/spi_slave_driver.c +++ b/drivers/spi/spi_slave_driver.c @@ -742,9 +742,12 @@ 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) { - nxsem_post(&priv->wait); + while (semcnt++ <= 0) + { + nxsem_post(&priv->wait); + } } } diff --git a/drivers/wireless/bluetooth/bt_slip.c b/drivers/wireless/bluetooth/bt_slip.c index cfbce689f1..9dfef441a7 100644 --- a/drivers/wireless/bluetooth/bt_slip.c +++ b/drivers/wireless/bluetooth/bt_slip.c @@ -561,10 +561,12 @@ 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) { - nxsem_post(&priv->sem); + while (semcount++ <= 0) + { + nxsem_post(&priv->sem); + } } } diff --git a/fs/notify/inotify.c b/fs/notify/inotify.c index 6370c4b41c..97924e3821 100644 --- a/fs/notify/inotify.c +++ b/fs/notify/inotify.c @@ -289,9 +289,12 @@ 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) { - nxsem_post(&dev->sem); + while (semcnt++ <= 1) + { + nxsem_post(&dev->sem); + } } }