sched: Skip wd_cancel() on wakeup when the waiter set no timeout.
Some checks are pending
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions

A task woken from a semaphore, a signal wait, a message queue or an event
wait gets its timeout watchdog cancelled, but most waiters set none, and
wd_cancel() then only takes the critical section to find that out.

Check WDOG_ISACTIVE() first at these call sites.  Each already holds the
critical section, so wd_expiration() cannot be running the watchdog on
another CPU and the check is exact on SMP too.  wd_cancel() itself keeps
its locked check.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
This commit is contained in:
Marco Casaroli 2026-09-29 14:53:14 +02:00 • committed by archer
parent 2f459314a0
commit 7e5cf3d5d0
5 changed files with 25 additions and 6 deletions

View file

@ -104,7 +104,11 @@ int nxevent_post(FAR nxevent_t *event, nxevent_mask_t events,
/* Stop timeout watchdog */
wd_cancel(&wtcb->waitdog);
if (WDOG_ISACTIVE(&wtcb->waitdog))
{
wd_cancel(&wtcb->waitdog);
}
wtcb->waitobj = NULL;
/* Make task ready-to-run */

View file

@ -253,7 +253,10 @@ void nxmq_notify_receive(FAR struct mqueue_inode_s *msgq)
DEBUGASSERT(btcb != NULL);
wd_cancel(&btcb->waitdog);
if (WDOG_ISACTIVE(&btcb->waitdog))
{
wd_cancel(&btcb->waitdog);
}
msgq->cmn.nwaitnotfull--;

View file

@ -286,7 +286,10 @@ void nxmq_notify_send(FAR struct mqueue_inode_s *msgq)
DEBUGASSERT(btcb);
wd_cancel(&btcb->waitdog);
if (WDOG_ISACTIVE(&btcb->waitdog))
{
wd_cancel(&btcb->waitdog);
}
msgq->cmn.nwaitnotempty--;

View file

@ -220,7 +220,10 @@ int nxsem_post_slow(FAR sem_t *sem)
/* Stop the watchdog timer */
wd_cancel(&stcb->waitdog);
if (WDOG_ISACTIVE(&stcb->waitdog))
{
wd_cancel(&stcb->waitdog);
}
/* Indicate that the wait is over. */

View file

@ -587,7 +587,10 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info,
}
sigemptyset(&stcb->sigwaitmask);
wd_cancel(&stcb->waitdog);
if (WDOG_ISACTIVE(&stcb->waitdog))
{
wd_cancel(&stcb->waitdog);
}
/* Remove the task from waiting list */
@ -650,7 +653,10 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info,
}
sigemptyset(&stcb->sigwaitmask);
wd_cancel(&stcb->waitdog);
if (WDOG_ISACTIVE(&stcb->waitdog))
{
wd_cancel(&stcb->waitdog);
}
/* Remove the task from waiting list */