mirror of
https://github.com/apache/nuttx.git
synced 2026-09-08 09:56:33 +00:00
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.laitinen@tii.ae>
This commit is contained in:
parent
01040400cb
commit
55913d16ad
3 changed files with 161 additions and 22 deletions
|
|
@ -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
|
||||
# endif
|
||||
)
|
||||
if ((sem->flags & SEM_PRIO_MASK) == SEM_PRIO_PROTECT)
|
||||
{
|
||||
int32_t old = _SCHED_GETTID();
|
||||
if (atomic_try_cmpxchg_release(NXSEM_MHOLDER(sem), &old,
|
||||
NXSEM_NO_MHOLDER))
|
||||
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;
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
# endif
|
||||
)
|
||||
if ((sem->flags & SEM_PRIO_MASK) == SEM_PRIO_PROTECT)
|
||||
{
|
||||
int32_t tid = _SCHED_GETTID();
|
||||
int32_t old = NXSEM_NO_MHOLDER;
|
||||
return atomic_try_cmpxchg_acquire(NXSEM_MHOLDER(sem), &old, tid) ?
|
||||
OK : -EAGAIN;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
# endif
|
||||
)
|
||||
if ((sem->flags & SEM_PRIO_MASK) == SEM_PRIO_PROTECT)
|
||||
{
|
||||
int32_t tid = _SCHED_GETTID();
|
||||
int32_t old = NXSEM_NO_MHOLDER;
|
||||
if (atomic_try_cmpxchg_acquire(NXSEM_MHOLDER(sem), &old, tid))
|
||||
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;
|
||||
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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue