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 <jukka.laiti...@tii.ae>
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 <jukka.laiti...@tii.ae>
---
 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);

Reply via email to