This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 55913d16ad libs/libc/semaphore: Enable semaphore fast wait/post paths
for counting semaphores
55913d16ad is described below
commit 55913d16ad941b3668d12fdf3bc5d8a7dce31963
Author: Jukka Laitinen <[email protected]>
AuthorDate: Fri May 2 14:58:53 2025 +0300
libs/libc/semaphore: Enable semaphore fast wait/post paths for counting
semaphores
The fast path can be used also for counting semaphores when the priority
inheritance is disabled.
Signed-off-by: Jukka Laitinen <[email protected]>
---
libs/libc/semaphore/sem_post.c | 55 ++++++++++++++++++++++++++++----
libs/libc/semaphore/sem_trywait.c | 67 +++++++++++++++++++++++++++++++++++----
libs/libc/semaphore/sem_wait.c | 55 ++++++++++++++++++++++++++++----
3 files changed, 158 insertions(+), 19 deletions(-)
diff --git a/libs/libc/semaphore/sem_post.c b/libs/libc/semaphore/sem_post.c
index 0aafd7a94d..874954a8a2 100644
--- a/libs/libc/semaphore/sem_post.c
+++ b/libs/libc/semaphore/sem_post.c
@@ -119,6 +119,9 @@ int sem_post(FAR sem_t *sem)
int nxsem_post(FAR sem_t *sem)
{
+ bool mutex;
+ bool fastpath = true;
+
DEBUGASSERT(sem != NULL);
/* We don't do atomic fast path in case of LIBC_ARCH_ATOMIC because that
@@ -128,20 +131,60 @@ int nxsem_post(FAR sem_t *sem)
#ifndef CONFIG_LIBC_ARCH_ATOMIC
- if (NXSEM_IS_MUTEX(sem)
+ mutex = NXSEM_IS_MUTEX(sem);
+
+ /* Disable fast path if priority protection is enabled on the semaphore */
+
# ifdef CONFIG_PRIORITY_PROTECT
- && (sem->flags & SEM_PRIO_MASK) != SEM_PRIO_PROTECT
+ if ((sem->flags & SEM_PRIO_MASK) == SEM_PRIO_PROTECT)
+ {
+ fastpath = false;
+ }
+# endif
+
+ /* Disable fast path on a counting semaphore with priority inheritance */
+
+# ifdef CONFIG_PRIORITY_INHERITANCE
+ if (!mutex && (sem->flags & SEM_PRIO_MASK) != SEM_PRIO_NONE)
+ {
+ fastpath = false;
+ }
# endif
- )
+
+ if (fastpath)
{
- int32_t old = _SCHED_GETTID();
- if (atomic_try_cmpxchg_release(NXSEM_MHOLDER(sem), &old,
- NXSEM_NO_MHOLDER))
+ int32_t old;
+ int32_t new;
+ FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
+
+ if (mutex)
+ {
+ old = _SCHED_GETTID();
+ new = NXSEM_NO_MHOLDER;
+ }
+ else
+ {
+ old = atomic_read(val);
+
+ if (old < 0)
+ {
+ goto out;
+ }
+
+ new = old + 1;
+ }
+
+ if (atomic_try_cmpxchg_release(val, &old, new))
{
return OK;
}
}
+out:
+
+#else
+ UNUSED(mutex);
+ UNUSED(fastpath);
#endif
return nxsem_post_slow(sem);
diff --git a/libs/libc/semaphore/sem_trywait.c
b/libs/libc/semaphore/sem_trywait.c
index e8363c8232..39112aa219 100644
--- a/libs/libc/semaphore/sem_trywait.c
+++ b/libs/libc/semaphore/sem_trywait.c
@@ -107,6 +107,9 @@ int sem_trywait(FAR sem_t *sem)
int nxsem_trywait(FAR sem_t *sem)
{
+ bool mutex;
+ bool fastpath = true;
+
DEBUGASSERT(sem != NULL);
/* This API should not be called from the idleloop or interrupt */
@@ -123,18 +126,68 @@ int nxsem_trywait(FAR sem_t *sem)
#ifndef CONFIG_LIBC_ARCH_ATOMIC
- if (NXSEM_IS_MUTEX(sem)
+ mutex = NXSEM_IS_MUTEX(sem);
+
+ /* Disable fast path if priority protection is enabled on the semaphore */
+
# ifdef CONFIG_PRIORITY_PROTECT
- && (sem->flags & SEM_PRIO_MASK) != SEM_PRIO_PROTECT
+ if ((sem->flags & SEM_PRIO_MASK) == SEM_PRIO_PROTECT)
+ {
+ fastpath = false;
+ }
# endif
- )
+
+ /* Disable fast path on a counting semaphore with priority inheritance */
+
+# ifdef CONFIG_PRIORITY_INHERITANCE
+ if (!mutex && (sem->flags & SEM_PRIO_MASK) != SEM_PRIO_NONE)
+ {
+ fastpath = false;
+ }
+# endif
+
+ if (fastpath)
{
- int32_t tid = _SCHED_GETTID();
- int32_t old = NXSEM_NO_MHOLDER;
- return atomic_try_cmpxchg_acquire(NXSEM_MHOLDER(sem), &old, tid) ?
- OK : -EAGAIN;
+ bool ret = false;
+ int32_t old;
+ int32_t new;
+ FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
+
+ if (mutex)
+ {
+ old = NXSEM_NO_MHOLDER;
+ }
+ else
+ {
+ old = atomic_read(val);
+ }
+
+ do
+ {
+ if (!mutex)
+ {
+ if (old < 1)
+ {
+ break;
+ }
+
+ new = old - 1;
+ }
+ else
+ {
+ new = _SCHED_GETTID();
+ }
+
+ ret = atomic_try_cmpxchg_acquire(NXSEM_MHOLDER(sem), &old, new);
+ }
+ while (!mutex && !ret);
+
+ return ret ? OK : -EAGAIN;
}
+#else
+ UNUSED(mutex);
+ UNUSED(fastpath);
#endif
return nxsem_trywait_slow(sem);
diff --git a/libs/libc/semaphore/sem_wait.c b/libs/libc/semaphore/sem_wait.c
index d936fbf025..6a187e23ac 100644
--- a/libs/libc/semaphore/sem_wait.c
+++ b/libs/libc/semaphore/sem_wait.c
@@ -135,6 +135,9 @@ errout_with_cancelpt:
int nxsem_wait(FAR sem_t *sem)
{
+ bool mutex;
+ bool fastpath = true;
+
DEBUGASSERT(sem != NULL);
/* This API should not be called from the idleloop or interrupt */
@@ -151,20 +154,60 @@ int nxsem_wait(FAR sem_t *sem)
#ifndef CONFIG_LIBC_ARCH_ATOMIC
- if (NXSEM_IS_MUTEX(sem)
+ mutex = NXSEM_IS_MUTEX(sem);
+
+ /* Disable fast path if priority protection is enabled on the semaphore */
+
# ifdef CONFIG_PRIORITY_PROTECT
- && (sem->flags & SEM_PRIO_MASK) != SEM_PRIO_PROTECT
+ if ((sem->flags & SEM_PRIO_MASK) == SEM_PRIO_PROTECT)
+ {
+ fastpath = false;
+ }
+# endif
+
+ /* Disable fast path on a counting semaphore with priority inheritance */
+
+# ifdef CONFIG_PRIORITY_INHERITANCE
+ if (!mutex && (sem->flags & SEM_PRIO_MASK) != SEM_PRIO_NONE)
+ {
+ fastpath = false;
+ }
# endif
- )
+
+ if (fastpath)
{
- int32_t tid = _SCHED_GETTID();
- int32_t old = NXSEM_NO_MHOLDER;
- if (atomic_try_cmpxchg_acquire(NXSEM_MHOLDER(sem), &old, tid))
+ int32_t old;
+ int32_t new;
+ FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
+
+ if (mutex)
+ {
+ old = NXSEM_NO_MHOLDER;
+ new = _SCHED_GETTID();
+ }
+ else
+ {
+ old = atomic_read(val);
+
+ if (old < 1)
+ {
+ goto out;
+ }
+
+ new = old - 1;
+ }
+
+ if (atomic_try_cmpxchg_acquire(val, &old, new))
{
return OK;
}
}
+out:
+
+#else
+ UNUSED(mutex);
+ UNUSED(fastpath);
#endif
return nxsem_wait_slow(sem);