This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit fb14b54b83f3a5517c249f86f34dfcd4ffe0202c
Author: Xiang Xiao <xiaoxi...@xiaomi.com>
AuthorDate: Sun Jun 22 03:03:59 2025 +0800

    libc/semaphore: Use the while loop to handle the inerrupt correctly
    
    If atomic_try_cmpxchg_xxxx runs on LL/SC architectures (e.g.ARMv7,
    ARMv8, RISC-V), the weak CAS expands to a single LDREX/STREX pair.
    
    If the CPU takes an IRQ/FIQ/SVC between the two instructions,
    hardware performs an implicit CLREX and the following STREX returns
    1, therefore atomic_try_cmpxchg_xxxx return failure even though
    *addr* still holds the expected value.
    
    So let's retry atomic_try_cmpxchg_xxxx in this case.
    
    Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
---
 libs/libc/semaphore/sem_post.c    | 19 +++++++++----------
 libs/libc/semaphore/sem_trywait.c | 40 ++++++++++++++++-----------------------
 libs/libc/semaphore/sem_wait.c    | 19 +++++++++----------
 3 files changed, 34 insertions(+), 44 deletions(-)

diff --git a/libs/libc/semaphore/sem_post.c b/libs/libc/semaphore/sem_post.c
index 874954a8a21..d34b6fea566 100644
--- a/libs/libc/semaphore/sem_post.c
+++ b/libs/libc/semaphore/sem_post.c
@@ -151,24 +151,26 @@ int nxsem_post(FAR sem_t *sem)
     }
 #  endif
 
-  if (fastpath)
+  while (fastpath)
     {
-      int32_t old;
-      int32_t new;
       FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
+      int32_t old = atomic_read(val);
+      int32_t new;
 
       if (mutex)
         {
-          old = _SCHED_GETTID();
+          if (NXSEM_MBLOCKING(old))
+            {
+              break;
+            }
+
           new = NXSEM_NO_MHOLDER;
         }
       else
         {
-          old = atomic_read(val);
-
           if (old < 0)
             {
-              goto out;
+              break;
             }
 
           new = old + 1;
@@ -179,9 +181,6 @@ int nxsem_post(FAR sem_t *sem)
           return OK;
         }
     }
-
-out:
-
 #else
   UNUSED(mutex);
   UNUSED(fastpath);
diff --git a/libs/libc/semaphore/sem_trywait.c 
b/libs/libc/semaphore/sem_trywait.c
index 39112aa219d..8f1686ea023 100644
--- a/libs/libc/semaphore/sem_trywait.c
+++ b/libs/libc/semaphore/sem_trywait.c
@@ -146,43 +146,35 @@ int nxsem_trywait(FAR sem_t *sem)
     }
 #  endif
 
-  if (fastpath)
+  while (fastpath)
     {
-      bool ret = false;
-      int32_t old;
-      int32_t new;
       FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
+      int32_t old = atomic_read(val);
+      int32_t new;
 
       if (mutex)
         {
-          old = NXSEM_NO_MHOLDER;
+          if (old != NXSEM_NO_MHOLDER)
+            {
+              return -EAGAIN;
+            }
+
+          new = _SCHED_GETTID();
         }
       else
         {
-          old = atomic_read(val);
-        }
-
-      do
-        {
-          if (!mutex)
-            {
-              if (old < 1)
-                {
-                  break;
-                }
-
-              new = old - 1;
-            }
-          else
+          if (old < 1)
             {
-              new = _SCHED_GETTID();
+              return -EAGAIN;
             }
 
-          ret = atomic_try_cmpxchg_acquire(NXSEM_MHOLDER(sem), &old, new);
+          new = old - 1;
         }
-      while (!mutex && !ret);
 
-      return ret ? OK : -EAGAIN;
+      if (atomic_try_cmpxchg_acquire(val, &old, new))
+        {
+          return OK;
+        }
     }
 
 #else
diff --git a/libs/libc/semaphore/sem_wait.c b/libs/libc/semaphore/sem_wait.c
index 6a187e23acd..dca20eb4bd6 100644
--- a/libs/libc/semaphore/sem_wait.c
+++ b/libs/libc/semaphore/sem_wait.c
@@ -174,24 +174,26 @@ int nxsem_wait(FAR sem_t *sem)
     }
 #  endif
 
-  if (fastpath)
+  while (fastpath)
     {
-      int32_t old;
-      int32_t new;
       FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
+      int32_t old = atomic_read(val);
+      int32_t new;
 
       if (mutex)
         {
-          old = NXSEM_NO_MHOLDER;
+          if (old != NXSEM_NO_MHOLDER)
+            {
+              break;
+            }
+
           new = _SCHED_GETTID();
         }
       else
         {
-          old = atomic_read(val);
-
           if (old < 1)
             {
-              goto out;
+              break;
             }
 
           new = old - 1;
@@ -202,9 +204,6 @@ int nxsem_wait(FAR sem_t *sem)
           return OK;
         }
     }
-
-out:
-
 #else
   UNUSED(mutex);
   UNUSED(fastpath);

Reply via email to