From 7e5cf3d5d0b57b2140195bfef49f0cedac541461 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 29 Sep 2026 14:53:14 +0200 Subject: [PATCH] sched: Skip wd_cancel() on wakeup when the waiter set no timeout. 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 --- sched/event/event_post.c | 6 +++++- sched/mqueue/mq_rcvinternal.c | 5 ++++- sched/mqueue/mq_sndinternal.c | 5 ++++- sched/semaphore/sem_post.c | 5 ++++- sched/signal/sig_dispatch.c | 10 ++++++++-- 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/sched/event/event_post.c b/sched/event/event_post.c index 3efc3f7d64d..6b6cf6ec0ad 100644 --- a/sched/event/event_post.c +++ b/sched/event/event_post.c @@ -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 */ diff --git a/sched/mqueue/mq_rcvinternal.c b/sched/mqueue/mq_rcvinternal.c index dd3c6c42003..9cab67c3a91 100644 --- a/sched/mqueue/mq_rcvinternal.c +++ b/sched/mqueue/mq_rcvinternal.c @@ -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--; diff --git a/sched/mqueue/mq_sndinternal.c b/sched/mqueue/mq_sndinternal.c index ac7bfe12e57..6c3908a9a7a 100644 --- a/sched/mqueue/mq_sndinternal.c +++ b/sched/mqueue/mq_sndinternal.c @@ -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--; diff --git a/sched/semaphore/sem_post.c b/sched/semaphore/sem_post.c index bb054d8341d..64db8f946db 100644 --- a/sched/semaphore/sem_post.c +++ b/sched/semaphore/sem_post.c @@ -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. */ diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index 174602477f8..000bd1e9913 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -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 */