mirror of
https://github.com/apache/nuttx.git
synced 2026-06-02 17:48:54 +08:00
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 <xiaoxiang@xiaomi.com>
This commit is contained in:
committed by
Alan C. Assis
parent
d8f241b29d
commit
fb14b54b83
@@ -151,24 +151,26 @@ int nxsem_post(FAR sem_t *sem)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
if (fastpath)
|
while (fastpath)
|
||||||
{
|
{
|
||||||
int32_t old;
|
|
||||||
int32_t new;
|
|
||||||
FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
|
FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
|
||||||
|
int32_t old = atomic_read(val);
|
||||||
|
int32_t new;
|
||||||
|
|
||||||
if (mutex)
|
if (mutex)
|
||||||
{
|
{
|
||||||
old = _SCHED_GETTID();
|
if (NXSEM_MBLOCKING(old))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
new = NXSEM_NO_MHOLDER;
|
new = NXSEM_NO_MHOLDER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
old = atomic_read(val);
|
|
||||||
|
|
||||||
if (old < 0)
|
if (old < 0)
|
||||||
{
|
{
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = old + 1;
|
new = old + 1;
|
||||||
@@ -179,9 +181,6 @@ int nxsem_post(FAR sem_t *sem)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
UNUSED(mutex);
|
UNUSED(mutex);
|
||||||
UNUSED(fastpath);
|
UNUSED(fastpath);
|
||||||
|
|||||||
@@ -146,43 +146,35 @@ int nxsem_trywait(FAR sem_t *sem)
|
|||||||
}
|
}
|
||||||
# endif
|
# 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);
|
FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
|
||||||
|
int32_t old = atomic_read(val);
|
||||||
|
int32_t new;
|
||||||
|
|
||||||
if (mutex)
|
if (mutex)
|
||||||
{
|
{
|
||||||
old = NXSEM_NO_MHOLDER;
|
if (old != NXSEM_NO_MHOLDER)
|
||||||
|
{
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
new = _SCHED_GETTID();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
old = atomic_read(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (!mutex)
|
|
||||||
{
|
{
|
||||||
if (old < 1)
|
if (old < 1)
|
||||||
{
|
{
|
||||||
break;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = old - 1;
|
new = old - 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (atomic_try_cmpxchg_acquire(val, &old, new))
|
||||||
{
|
{
|
||||||
new = _SCHED_GETTID();
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = atomic_try_cmpxchg_acquire(NXSEM_MHOLDER(sem), &old, new);
|
|
||||||
}
|
|
||||||
while (!mutex && !ret);
|
|
||||||
|
|
||||||
return ret ? OK : -EAGAIN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -174,24 +174,26 @@ int nxsem_wait(FAR sem_t *sem)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
if (fastpath)
|
while (fastpath)
|
||||||
{
|
{
|
||||||
int32_t old;
|
|
||||||
int32_t new;
|
|
||||||
FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
|
FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
|
||||||
|
int32_t old = atomic_read(val);
|
||||||
|
int32_t new;
|
||||||
|
|
||||||
if (mutex)
|
if (mutex)
|
||||||
{
|
{
|
||||||
old = NXSEM_NO_MHOLDER;
|
if (old != NXSEM_NO_MHOLDER)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
new = _SCHED_GETTID();
|
new = _SCHED_GETTID();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
old = atomic_read(val);
|
|
||||||
|
|
||||||
if (old < 1)
|
if (old < 1)
|
||||||
{
|
{
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = old - 1;
|
new = old - 1;
|
||||||
@@ -202,9 +204,6 @@ int nxsem_wait(FAR sem_t *sem)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
UNUSED(mutex);
|
UNUSED(mutex);
|
||||||
UNUSED(fastpath);
|
UNUSED(fastpath);
|
||||||
|
|||||||
Reference in New Issue
Block a user