Skip to content

Commit fb14b54

Browse files
xiaoxiang781216Alan C. Assis
authored andcommitted
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 <[email protected]>
1 parent d8f241b commit fb14b54

File tree

3 files changed

+34
-44
lines changed

3 files changed

+34
-44
lines changed

libs/libc/semaphore/sem_post.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,24 +151,26 @@ int nxsem_post(FAR sem_t *sem)
151151
}
152152
# endif
153153

154-
if (fastpath)
154+
while (fastpath)
155155
{
156-
int32_t old;
157-
int32_t new;
158156
FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
157+
int32_t old = atomic_read(val);
158+
int32_t new;
159159

160160
if (mutex)
161161
{
162-
old = _SCHED_GETTID();
162+
if (NXSEM_MBLOCKING(old))
163+
{
164+
break;
165+
}
166+
163167
new = NXSEM_NO_MHOLDER;
164168
}
165169
else
166170
{
167-
old = atomic_read(val);
168-
169171
if (old < 0)
170172
{
171-
goto out;
173+
break;
172174
}
173175

174176
new = old + 1;
@@ -179,9 +181,6 @@ int nxsem_post(FAR sem_t *sem)
179181
return OK;
180182
}
181183
}
182-
183-
out:
184-
185184
#else
186185
UNUSED(mutex);
187186
UNUSED(fastpath);

libs/libc/semaphore/sem_trywait.c

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -146,43 +146,35 @@ int nxsem_trywait(FAR sem_t *sem)
146146
}
147147
# endif
148148

149-
if (fastpath)
149+
while (fastpath)
150150
{
151-
bool ret = false;
152-
int32_t old;
153-
int32_t new;
154151
FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
152+
int32_t old = atomic_read(val);
153+
int32_t new;
155154

156155
if (mutex)
157156
{
158-
old = NXSEM_NO_MHOLDER;
157+
if (old != NXSEM_NO_MHOLDER)
158+
{
159+
return -EAGAIN;
160+
}
161+
162+
new = _SCHED_GETTID();
159163
}
160164
else
161165
{
162-
old = atomic_read(val);
163-
}
164-
165-
do
166-
{
167-
if (!mutex)
168-
{
169-
if (old < 1)
170-
{
171-
break;
172-
}
173-
174-
new = old - 1;
175-
}
176-
else
166+
if (old < 1)
177167
{
178-
new = _SCHED_GETTID();
168+
return -EAGAIN;
179169
}
180170

181-
ret = atomic_try_cmpxchg_acquire(NXSEM_MHOLDER(sem), &old, new);
171+
new = old - 1;
182172
}
183-
while (!mutex && !ret);
184173

185-
return ret ? OK : -EAGAIN;
174+
if (atomic_try_cmpxchg_acquire(val, &old, new))
175+
{
176+
return OK;
177+
}
186178
}
187179

188180
#else

libs/libc/semaphore/sem_wait.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -174,24 +174,26 @@ int nxsem_wait(FAR sem_t *sem)
174174
}
175175
# endif
176176

177-
if (fastpath)
177+
while (fastpath)
178178
{
179-
int32_t old;
180-
int32_t new;
181179
FAR atomic_t *val = mutex ? NXSEM_MHOLDER(sem) : NXSEM_COUNT(sem);
180+
int32_t old = atomic_read(val);
181+
int32_t new;
182182

183183
if (mutex)
184184
{
185-
old = NXSEM_NO_MHOLDER;
185+
if (old != NXSEM_NO_MHOLDER)
186+
{
187+
break;
188+
}
189+
186190
new = _SCHED_GETTID();
187191
}
188192
else
189193
{
190-
old = atomic_read(val);
191-
192194
if (old < 1)
193195
{
194-
goto out;
196+
break;
195197
}
196198

197199
new = old - 1;
@@ -202,9 +204,6 @@ int nxsem_wait(FAR sem_t *sem)
202204
return OK;
203205
}
204206
}
205-
206-
out:
207-
208207
#else
209208
UNUSED(mutex);
210209
UNUSED(fastpath);

0 commit comments

Comments
 (0)