Skip to content

Commit

Permalink
sched/semaphore/sem_tickwait.c: Fix nxsem_tickwait_uninterruptible en…
Browse files Browse the repository at this point in the history
…d condition

nxsem_tickwait correctly sleeps more than 1 tick. But nxsem_tickwait_uninterruptible
may wake up to a signal (with -EINTR), in which case the tick + 1 must also
be taken into account. Otherwise the nxsem_tickwait_uninterruptible may
wake up 1 tick too early.

This patch has the side effect that if such a wakeup by signal occurs
at the last waiting tick, the nxsem_tickwait_uninterruptible may end up
sleeping one tick too long due to nxsem_tickwait won't ever timeout at
the next tick. This is however (more) correct behaviour than waking up
too early.

Also fix the nxsem_tickwait to return with -ETIMEDOUT if called with delay 0.
This is similar to e.g.  posix sem_timedwait.

Signed-off-by: Jukka Laitinen <[email protected]>
  • Loading branch information
jlaitine committed Sep 27, 2024
1 parent c8d993e commit 42bc72e
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 2 deletions.
5 changes: 5 additions & 0 deletions arch/arm64/src/common/arm64_arch_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ static int arm64_tick_start(struct oneshot_lowerhalf_s *lower,

if (count_now - priv->next_cycle >= tick_counts)
{
/* Align the next_cycle to be evenly divisible by cycle_per_tick.
* This will ensure that any call to arm64_tick_current always
* returns the currently ongoing tick.
*/

priv->next_cycle = (count_now / priv->cycle_per_tick) *
priv->cycle_per_tick;
}
Expand Down
5 changes: 3 additions & 2 deletions sched/semaphore/sem_tickwait.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ int nxsem_tickwait(FAR sem_t *sem, uint32_t delay)

if (delay == 0)
{
/* Return the errno from nxsem_trywait() */
/* Timed out already before waiting */

ret = -ETIMEDOUT;
goto out;
}

Expand Down Expand Up @@ -149,7 +150,7 @@ int nxsem_tickwait(FAR sem_t *sem, uint32_t delay)

int nxsem_tickwait_uninterruptible(FAR sem_t *sem, uint32_t delay)
{
clock_t end = clock_systime_ticks() + delay;
clock_t end = clock_systime_ticks() + delay + 1;
int ret;

for (; ; )
Expand Down

0 comments on commit 42bc72e

Please sign in to comment.