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