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);